]> git.lyx.org Git - lyx.git/commitdiff
Rename files in src/mathed and src/graphics from .C to .cpp, step 2
authorBo Peng <bpeng@lyx.org>
Wed, 25 Apr 2007 03:03:25 +0000 (03:03 +0000)
committerBo Peng <bpeng@lyx.org>
Wed, 25 Apr 2007 03:03:25 +0000 (03:03 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@17969 a592a061-630c-0410-9148-cb99ea01b6c8

170 files changed:
src/graphics/GraphicsCache.C [deleted file]
src/graphics/GraphicsCache.cpp [new file with mode: 0644]
src/graphics/GraphicsCacheItem.C [deleted file]
src/graphics/GraphicsCacheItem.cpp [new file with mode: 0644]
src/graphics/GraphicsConverter.C [deleted file]
src/graphics/GraphicsConverter.cpp [new file with mode: 0644]
src/graphics/GraphicsImage.C [deleted file]
src/graphics/GraphicsImage.cpp [new file with mode: 0644]
src/graphics/GraphicsLoader.C [deleted file]
src/graphics/GraphicsLoader.cpp [new file with mode: 0644]
src/graphics/GraphicsParams.C [deleted file]
src/graphics/GraphicsParams.cpp [new file with mode: 0644]
src/graphics/GraphicsTypes.C [deleted file]
src/graphics/GraphicsTypes.cpp [new file with mode: 0644]
src/graphics/LoaderQueue.C [deleted file]
src/graphics/LoaderQueue.cpp [new file with mode: 0644]
src/graphics/PreviewImage.C [deleted file]
src/graphics/PreviewImage.cpp [new file with mode: 0644]
src/graphics/PreviewLoader.C [deleted file]
src/graphics/PreviewLoader.cpp [new file with mode: 0644]
src/graphics/Previews.C [deleted file]
src/graphics/Previews.cpp [new file with mode: 0644]
src/mathed/InsetFormulaMacro.C [deleted file]
src/mathed/InsetFormulaMacro.cpp [new file with mode: 0644]
src/mathed/InsetMath.C [deleted file]
src/mathed/InsetMath.cpp [new file with mode: 0644]
src/mathed/InsetMathAMSArray.C [deleted file]
src/mathed/InsetMathAMSArray.cpp [new file with mode: 0644]
src/mathed/InsetMathArray.C [deleted file]
src/mathed/InsetMathArray.cpp [new file with mode: 0644]
src/mathed/InsetMathBig.C [deleted file]
src/mathed/InsetMathBig.cpp [new file with mode: 0644]
src/mathed/InsetMathBinom.C [deleted file]
src/mathed/InsetMathBinom.cpp [new file with mode: 0644]
src/mathed/InsetMathBoldSymbol.C [deleted file]
src/mathed/InsetMathBoldSymbol.cpp [new file with mode: 0644]
src/mathed/InsetMathBox.C [deleted file]
src/mathed/InsetMathBox.cpp [new file with mode: 0644]
src/mathed/InsetMathBoxed.C [deleted file]
src/mathed/InsetMathBoxed.cpp [new file with mode: 0644]
src/mathed/InsetMathBrace.C [deleted file]
src/mathed/InsetMathBrace.cpp [new file with mode: 0644]
src/mathed/InsetMathCases.C [deleted file]
src/mathed/InsetMathCases.cpp [new file with mode: 0644]
src/mathed/InsetMathChar.C [deleted file]
src/mathed/InsetMathChar.cpp [new file with mode: 0644]
src/mathed/InsetMathColor.C [deleted file]
src/mathed/InsetMathColor.cpp [new file with mode: 0644]
src/mathed/InsetMathCommand.C [deleted file]
src/mathed/InsetMathCommand.cpp [new file with mode: 0644]
src/mathed/InsetMathComment.C [deleted file]
src/mathed/InsetMathComment.cpp [new file with mode: 0644]
src/mathed/InsetMathDFrac.C [deleted file]
src/mathed/InsetMathDFrac.cpp [new file with mode: 0644]
src/mathed/InsetMathDecoration.C [deleted file]
src/mathed/InsetMathDecoration.cpp [new file with mode: 0644]
src/mathed/InsetMathDelim.C [deleted file]
src/mathed/InsetMathDelim.cpp [new file with mode: 0644]
src/mathed/InsetMathDiff.C [deleted file]
src/mathed/InsetMathDiff.cpp [new file with mode: 0644]
src/mathed/InsetMathDim.C [deleted file]
src/mathed/InsetMathDim.cpp [new file with mode: 0644]
src/mathed/InsetMathDots.C [deleted file]
src/mathed/InsetMathDots.cpp [new file with mode: 0644]
src/mathed/InsetMathEnv.C [deleted file]
src/mathed/InsetMathEnv.cpp [new file with mode: 0644]
src/mathed/InsetMathExFunc.C [deleted file]
src/mathed/InsetMathExFunc.cpp [new file with mode: 0644]
src/mathed/InsetMathExInt.C [deleted file]
src/mathed/InsetMathExInt.cpp [new file with mode: 0644]
src/mathed/InsetMathFBox.C [deleted file]
src/mathed/InsetMathFBox.cpp [new file with mode: 0644]
src/mathed/InsetMathFont.C [deleted file]
src/mathed/InsetMathFont.cpp [new file with mode: 0644]
src/mathed/InsetMathFontOld.C [deleted file]
src/mathed/InsetMathFontOld.cpp [new file with mode: 0644]
src/mathed/InsetMathFrac.C [deleted file]
src/mathed/InsetMathFrac.cpp [new file with mode: 0644]
src/mathed/InsetMathFracBase.C [deleted file]
src/mathed/InsetMathFracBase.cpp [new file with mode: 0644]
src/mathed/InsetMathFrameBox.C [deleted file]
src/mathed/InsetMathFrameBox.cpp [new file with mode: 0644]
src/mathed/InsetMathGrid.C [deleted file]
src/mathed/InsetMathGrid.cpp [new file with mode: 0644]
src/mathed/InsetMathHull.C [deleted file]
src/mathed/InsetMathHull.cpp [new file with mode: 0644]
src/mathed/InsetMathKern.C [deleted file]
src/mathed/InsetMathKern.cpp [new file with mode: 0644]
src/mathed/InsetMathLefteqn.C [deleted file]
src/mathed/InsetMathLefteqn.cpp [new file with mode: 0644]
src/mathed/InsetMathLim.C [deleted file]
src/mathed/InsetMathLim.cpp [new file with mode: 0644]
src/mathed/InsetMathMBox.C [deleted file]
src/mathed/InsetMathMBox.cpp [new file with mode: 0644]
src/mathed/InsetMathMacro.C [deleted file]
src/mathed/InsetMathMacro.cpp [new file with mode: 0644]
src/mathed/InsetMathMakebox.C [deleted file]
src/mathed/InsetMathMakebox.cpp [new file with mode: 0644]
src/mathed/InsetMathMatrix.C [deleted file]
src/mathed/InsetMathMatrix.cpp [new file with mode: 0644]
src/mathed/InsetMathNest.C [deleted file]
src/mathed/InsetMathNest.cpp [new file with mode: 0644]
src/mathed/InsetMathNumber.C [deleted file]
src/mathed/InsetMathNumber.cpp [new file with mode: 0644]
src/mathed/InsetMathOverset.C [deleted file]
src/mathed/InsetMathOverset.cpp [new file with mode: 0644]
src/mathed/InsetMathPar.C [deleted file]
src/mathed/InsetMathPar.cpp [new file with mode: 0644]
src/mathed/InsetMathPhantom.C [deleted file]
src/mathed/InsetMathPhantom.cpp [new file with mode: 0644]
src/mathed/InsetMathRef.C [deleted file]
src/mathed/InsetMathRef.cpp [new file with mode: 0644]
src/mathed/InsetMathRoot.C [deleted file]
src/mathed/InsetMathRoot.cpp [new file with mode: 0644]
src/mathed/InsetMathScript.C [deleted file]
src/mathed/InsetMathScript.cpp [new file with mode: 0644]
src/mathed/InsetMathSize.C [deleted file]
src/mathed/InsetMathSize.cpp [new file with mode: 0644]
src/mathed/InsetMathSpace.C [deleted file]
src/mathed/InsetMathSpace.cpp [new file with mode: 0644]
src/mathed/InsetMathSplit.C [deleted file]
src/mathed/InsetMathSplit.cpp [new file with mode: 0644]
src/mathed/InsetMathSqrt.C [deleted file]
src/mathed/InsetMathSqrt.cpp [new file with mode: 0644]
src/mathed/InsetMathStackrel.C [deleted file]
src/mathed/InsetMathStackrel.cpp [new file with mode: 0644]
src/mathed/InsetMathString.C [deleted file]
src/mathed/InsetMathString.cpp [new file with mode: 0644]
src/mathed/InsetMathSubstack.C [deleted file]
src/mathed/InsetMathSubstack.cpp [new file with mode: 0644]
src/mathed/InsetMathSymbol.C [deleted file]
src/mathed/InsetMathSymbol.cpp [new file with mode: 0644]
src/mathed/InsetMathTFrac.C [deleted file]
src/mathed/InsetMathTFrac.cpp [new file with mode: 0644]
src/mathed/InsetMathTabular.C [deleted file]
src/mathed/InsetMathTabular.cpp [new file with mode: 0644]
src/mathed/InsetMathUnderset.C [deleted file]
src/mathed/InsetMathUnderset.cpp [new file with mode: 0644]
src/mathed/InsetMathUnknown.C [deleted file]
src/mathed/InsetMathUnknown.cpp [new file with mode: 0644]
src/mathed/InsetMathXArrow.C [deleted file]
src/mathed/InsetMathXArrow.cpp [new file with mode: 0644]
src/mathed/InsetMathXYArrow.C [deleted file]
src/mathed/InsetMathXYArrow.cpp [new file with mode: 0644]
src/mathed/InsetMathXYMatrix.C [deleted file]
src/mathed/InsetMathXYMatrix.cpp [new file with mode: 0644]
src/mathed/MathAtom.C [deleted file]
src/mathed/MathAtom.cpp [new file with mode: 0644]
src/mathed/MathAutoCorrect.C [deleted file]
src/mathed/MathAutoCorrect.cpp [new file with mode: 0644]
src/mathed/MathData.C [deleted file]
src/mathed/MathData.cpp [new file with mode: 0644]
src/mathed/MathExtern.C [deleted file]
src/mathed/MathExtern.cpp [new file with mode: 0644]
src/mathed/MathFactory.C [deleted file]
src/mathed/MathFactory.cpp [new file with mode: 0644]
src/mathed/MathMacroArgument.C [deleted file]
src/mathed/MathMacroArgument.cpp [new file with mode: 0644]
src/mathed/MathMacroTable.C [deleted file]
src/mathed/MathMacroTable.cpp [new file with mode: 0644]
src/mathed/MathMacroTemplate.C [deleted file]
src/mathed/MathMacroTemplate.cpp [new file with mode: 0644]
src/mathed/MathParser.C [deleted file]
src/mathed/MathParser.cpp [new file with mode: 0644]
src/mathed/MathStream.C [deleted file]
src/mathed/MathStream.cpp [new file with mode: 0644]
src/mathed/MathSupport.C [deleted file]
src/mathed/MathSupport.cpp [new file with mode: 0644]
src/mathed/TextPainter.C [deleted file]
src/mathed/TextPainter.cpp [new file with mode: 0644]

diff --git a/src/graphics/GraphicsCache.C b/src/graphics/GraphicsCache.C
deleted file mode 100644 (file)
index 10f9fc7..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * \file GraphicsCache.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Baruch Even
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "GraphicsCache.h"
-#include "GraphicsCacheItem.h"
-#include "GraphicsImage.h"
-
-#include "debug.h"
-
-#include "support/filetools.h"
-
-#include <map>
-
-using std::string;
-
-
-namespace lyx {
-
-using support::FileName;
-
-namespace graphics {
-
-/** The cache contains one item per file, so use a map to find the
- *  cache item quickly by filename.
- */
-typedef std::map<FileName, Cache::ItemPtr> CacheType;
-
-class Cache::Impl {
-public:
-       ///
-       CacheType cache;
-};
-
-
-Cache & Cache::get()
-{
-       // Now return the cache
-       static Cache singleton;
-       return singleton;
-}
-
-
-Cache::Cache()
-       : pimpl_(new Impl)
-{}
-
-
-Cache::~Cache()
-{}
-
-
-std::vector<string> Cache::loadableFormats() const
-{
-       return Image::loadableFormats();
-}
-
-
-void Cache::add(FileName const & file) const
-{
-       // Is the file in the cache already?
-       if (inCache(file)) {
-               LYXERR(Debug::GRAPHICS) << "Cache::add(" << file << "):\n"
-                                       << "The file is already in the cache."
-                                       << std::endl;
-               return;
-       }
-
-       pimpl_->cache[file] = ItemPtr(new CacheItem(file));
-}
-
-
-void Cache::remove(FileName const & file) const
-{
-       CacheType::iterator it = pimpl_->cache.find(file);
-       if (it == pimpl_->cache.end())
-               return;
-
-       ItemPtr & item = it->second;
-
-       if (item.use_count() == 1) {
-               // The graphics file is in the cache, but nothing else
-               // references it.
-               pimpl_->cache.erase(it);
-       }
-}
-
-
-bool Cache::inCache(FileName const & file) const
-{
-       return pimpl_->cache.find(file) != pimpl_->cache.end();
-}
-
-
-Cache::ItemPtr const Cache::item(FileName const & file) const
-{
-       CacheType::const_iterator it = pimpl_->cache.find(file);
-       if (it == pimpl_->cache.end())
-               return ItemPtr();
-
-       return it->second;
-}
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/GraphicsCache.cpp b/src/graphics/GraphicsCache.cpp
new file mode 100644 (file)
index 0000000..10f9fc7
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ * \file GraphicsCache.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Baruch Even
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "GraphicsCache.h"
+#include "GraphicsCacheItem.h"
+#include "GraphicsImage.h"
+
+#include "debug.h"
+
+#include "support/filetools.h"
+
+#include <map>
+
+using std::string;
+
+
+namespace lyx {
+
+using support::FileName;
+
+namespace graphics {
+
+/** The cache contains one item per file, so use a map to find the
+ *  cache item quickly by filename.
+ */
+typedef std::map<FileName, Cache::ItemPtr> CacheType;
+
+class Cache::Impl {
+public:
+       ///
+       CacheType cache;
+};
+
+
+Cache & Cache::get()
+{
+       // Now return the cache
+       static Cache singleton;
+       return singleton;
+}
+
+
+Cache::Cache()
+       : pimpl_(new Impl)
+{}
+
+
+Cache::~Cache()
+{}
+
+
+std::vector<string> Cache::loadableFormats() const
+{
+       return Image::loadableFormats();
+}
+
+
+void Cache::add(FileName const & file) const
+{
+       // Is the file in the cache already?
+       if (inCache(file)) {
+               LYXERR(Debug::GRAPHICS) << "Cache::add(" << file << "):\n"
+                                       << "The file is already in the cache."
+                                       << std::endl;
+               return;
+       }
+
+       pimpl_->cache[file] = ItemPtr(new CacheItem(file));
+}
+
+
+void Cache::remove(FileName const & file) const
+{
+       CacheType::iterator it = pimpl_->cache.find(file);
+       if (it == pimpl_->cache.end())
+               return;
+
+       ItemPtr & item = it->second;
+
+       if (item.use_count() == 1) {
+               // The graphics file is in the cache, but nothing else
+               // references it.
+               pimpl_->cache.erase(it);
+       }
+}
+
+
+bool Cache::inCache(FileName const & file) const
+{
+       return pimpl_->cache.find(file) != pimpl_->cache.end();
+}
+
+
+Cache::ItemPtr const Cache::item(FileName const & file) const
+{
+       CacheType::const_iterator it = pimpl_->cache.find(file);
+       if (it == pimpl_->cache.end())
+               return ItemPtr();
+
+       return it->second;
+}
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/graphics/GraphicsCacheItem.C b/src/graphics/GraphicsCacheItem.C
deleted file mode 100644 (file)
index 74e9eb4..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-/**
- * \file GraphicsCacheItem.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Baruch Even
- * \author Herbert Voß
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "GraphicsCacheItem.h"
-#include "GraphicsConverter.h"
-#include "GraphicsImage.h"
-
-#include "ConverterCache.h"
-#include "debug.h"
-#include "format.h"
-
-#include "support/filetools.h"
-#include "support/FileMonitor.h"
-#include "support/lyxlib.h"
-
-#include <boost/bind.hpp>
-
-
-namespace lyx {
-
-using support::FileMonitor;
-using support::FileName;
-using support::isFileReadable;
-using support::makeDisplayPath;
-using support::onlyFilename;
-using support::tempName;
-using support::unlink;
-using support::unzipFile;
-using support::zippedFile;
-
-using std::endl;
-using std::string;
-
-
-namespace graphics {
-
-class CacheItem::Impl : public boost::signals::trackable {
-public:
-
-       ///
-       Impl(FileName const & file);
-
-       /** Start the image conversion process, checking first that it is
-        *  necessary. If it is necessary, then a conversion task is started.
-        *  CacheItem asumes that the conversion is asynchronous and so
-        *  passes a Signal to the converting routine. When the conversion
-        *  is finished, this Signal is emitted, returning the converted
-        *  file to this->imageConverted.
-        *
-        *  If no file conversion is needed, then convertToDisplayFormat() calls
-        *  loadImage() directly.
-        *
-        *  convertToDisplayFormat() will set the loading status flag as
-        *  approriate through calls to setStatus().
-        */
-       void convertToDisplayFormat();
-
-       /** Load the image into memory. This is called either from
-        *  convertToDisplayFormat() direct or from imageConverted().
-        */
-       void loadImage();
-
-       /** Get a notification when the image conversion is done.
-        *  Connected to a signal on_finish_ which is passed to
-        *  Converter::convert.
-        */
-       void imageConverted(bool);
-
-       /** Get a notification when the image loading is done.
-        *  Connected to a signal on_finish_ which is passed to
-        *  lyx::graphics::Image::loadImage.
-        */
-       void imageLoaded(bool);
-
-       /** Sets the status of the loading process. Also notifies
-        *  listeners that the status has changed.
-        */
-       void setStatus(ImageStatus new_status);
-
-       /** Can be invoked directly by the user, but is also connected to the
-        *  FileMonitor and so is invoked when the file is changed
-        *  (if monitoring is taking place).
-        */
-       void startLoading();
-
-       /** If we are asked to load the file for a second or further time,
-        *  (because the file has changed), then we'll have to first reset
-        *  many of the variables below.
-        */
-       void reset();
-
-       /// The filename we refer too.
-       FileName const filename_;
-       ///
-       FileMonitor const monitor_;
-
-       /// Is the file compressed?
-       bool zipped_;
-       /// If so, store the uncompressed file in this temporary file.
-       FileName unzipped_filename_;
-       /// The target format
-       string to_;
-       /// What file are we trying to load?
-       FileName file_to_load_;
-       /** Should we delete the file after loading? True if the file is
-        *  the result of a conversion process.
-        */
-       bool remove_loaded_file_;
-
-       /// The image and its loading status.
-       boost::shared_ptr<Image> image_;
-       ///
-       ImageStatus status_;
-
-       /// This signal is emitted when the image loading status changes.
-       boost::signal<void()> statusChanged;
-
-       /// The connection to the signal Image::finishedLoading
-       boost::signals::connection cl_;
-
-       /// The connection of the signal ConvProcess::finishedConversion,
-       boost::signals::connection cc_;
-
-       ///
-       boost::scoped_ptr<Converter> converter_;
-};
-
-
-CacheItem::CacheItem(FileName const & file)
-       : pimpl_(new Impl(file))
-{}
-
-
-CacheItem::~CacheItem()
-{}
-
-
-FileName const & CacheItem::filename() const
-{
-       return pimpl_->filename_;
-}
-
-
-void CacheItem::startLoading() const
-{
-       pimpl_->startLoading();
-}
-
-
-void CacheItem::startMonitoring() const
-{
-       if (!pimpl_->monitor_.monitoring())
-               pimpl_->monitor_.start();
-}
-
-
-bool CacheItem::monitoring() const
-{
-       return pimpl_->monitor_.monitoring();
-}
-
-
-unsigned long CacheItem::checksum() const
-{
-       return pimpl_->monitor_.checksum();
-}
-
-
-Image const * CacheItem::image() const
-{
-       return pimpl_->image_.get();
-}
-
-
-ImageStatus CacheItem::status() const
-{
-       return pimpl_->status_;
-}
-
-
-boost::signals::connection CacheItem::connect(slot_type const & slot) const
-{
-       return pimpl_->statusChanged.connect(slot);
-}
-
-
-//------------------------------
-// Implementation details follow
-//------------------------------
-
-
-CacheItem::Impl::Impl(FileName const & file)
-       : filename_(file),
-         monitor_(file, 2000),
-         zipped_(false),
-         remove_loaded_file_(false),
-         status_(WaitingToLoad)
-{
-       monitor_.connect(boost::bind(&Impl::startLoading, this));
-}
-
-
-void CacheItem::Impl::startLoading()
-{
-       if (status_ != WaitingToLoad)
-               reset();
-
-       convertToDisplayFormat();
-}
-
-
-void CacheItem::Impl::reset()
-{
-       zipped_ = false;
-       if (!unzipped_filename_.empty())
-               unlink(unzipped_filename_);
-       unzipped_filename_.erase();
-
-       if (remove_loaded_file_ && !file_to_load_.empty())
-               unlink(file_to_load_);
-       remove_loaded_file_ = false;
-       file_to_load_.erase();
-       to_.erase();
-
-       if (image_.get())
-               image_.reset();
-
-       status_ = WaitingToLoad;
-
-       if (cl_.connected())
-               cl_.disconnect();
-
-       if (cc_.connected())
-               cc_.disconnect();
-
-       if (converter_.get())
-               converter_.reset();
-}
-
-
-void CacheItem::Impl::setStatus(ImageStatus new_status)
-{
-       if (status_ == new_status)
-               return;
-
-       status_ = new_status;
-       statusChanged();
-}
-
-
-void CacheItem::Impl::imageConverted(bool success)
-{
-       string const text = success ? "succeeded" : "failed";
-       LYXERR(Debug::GRAPHICS) << "Image conversion " << text << '.' << endl;
-
-       file_to_load_ = converter_.get() ?
-               FileName(converter_->convertedFile()) : FileName();
-       converter_.reset();
-       cc_.disconnect();
-
-       success = !file_to_load_.empty() && isFileReadable(file_to_load_);
-
-       if (!success) {
-               LYXERR(Debug::GRAPHICS) << "Unable to find converted file!"
-                                       << endl;
-               setStatus(ErrorConverting);
-
-               if (zipped_)
-                       unlink(unzipped_filename_);
-
-               return;
-       }
-
-       // Add the converted file to the file cache
-       ConverterCache::get().add(filename_, to_, file_to_load_);
-
-       loadImage();
-}
-
-
-// This function gets called from the callback after the image has been
-// converted successfully.
-void CacheItem::Impl::loadImage()
-{
-       setStatus(Loading);
-       LYXERR(Debug::GRAPHICS) << "Loading image." << endl;
-
-       image_ = Image::newImage();
-
-       cl_.disconnect();
-       cl_ = image_->finishedLoading.connect(
-               boost::bind(&Impl::imageLoaded, this, _1));
-       image_->load(file_to_load_);
-}
-
-
-void CacheItem::Impl::imageLoaded(bool success)
-{
-       string const text = success ? "succeeded" : "failed";
-       LYXERR(Debug::GRAPHICS) << "Image loading " << text << '.' << endl;
-
-       // Clean up after loading.
-       if (zipped_)
-               unlink(unzipped_filename_);
-
-       if (remove_loaded_file_ && unzipped_filename_ != file_to_load_)
-               unlink(file_to_load_);
-
-       cl_.disconnect();
-
-       if (!success) {
-               setStatus(ErrorLoading);
-               return;
-       }
-
-       // Inform the outside world.
-       setStatus(Loaded);
-}
-
-
-static string const findTargetFormat(string const & from)
-{
-       typedef lyx::graphics::Image::FormatList FormatList;
-       FormatList const formats = lyx::graphics::Image::loadableFormats();
-
-        // There must be a format to load from.
-       BOOST_ASSERT(!formats.empty());
-
-       // Use the standard converter if we don't know the format to load
-       // from.
-       if (from.empty())
-               return string("ppm");
-
-       // First ascertain if we can load directly with no conversion
-       FormatList::const_iterator it  = formats.begin();
-       FormatList::const_iterator end = formats.end();
-       for (; it != end; ++it) {
-               if (from == *it)
-                       return *it;
-       }
-
-       // So, we have to convert to a loadable format. Can we?
-       it = formats.begin();
-       for (; it != end; ++it) {
-               if (lyx::graphics::Converter::isReachable(from, *it))
-                       return *it;
-               else
-                       LYXERR(Debug::GRAPHICS)
-                               << "Unable to convert from " << from
-                               << " to " << *it << std::endl;
-       }
-
-       // Failed! so we have to try to convert it to PPM format
-       // with the standard converter
-       return string("ppm");
-}
-
-
-void CacheItem::Impl::convertToDisplayFormat()
-{
-       setStatus(Converting);
-
-       // First, check that the file exists!
-       if (!isFileReadable(filename_)) {
-               if (status_ != ErrorNoFile) {
-                       setStatus(ErrorNoFile);
-                       LYXERR(Debug::GRAPHICS)
-                               << "\tThe file is not readable" << endl;
-               }
-               return;
-       }
-
-       // Make a local copy in case we unzip it
-       FileName filename;
-       zipped_ = zippedFile(filename_);
-       if (zipped_) {
-               unzipped_filename_ = tempName(FileName(), filename_.toFilesystemEncoding());
-               if (unzipped_filename_.empty()) {
-                       setStatus(ErrorConverting);
-                       LYXERR(Debug::GRAPHICS)
-                               << "\tCould not create temporary file." << endl;
-                       return;
-               }
-               filename = unzipFile(filename_, unzipped_filename_.toFilesystemEncoding());
-       } else
-               filename = filename_;
-
-       docstring const displayed_filename = makeDisplayPath(filename_.absFilename());
-       LYXERR(Debug::GRAPHICS) << "[graphics::CacheItem::Impl::convertToDisplayFormat]\n"
-               << "\tAttempting to convert image file: " << filename
-               << "\n\twith displayed filename: " << lyx::to_utf8(displayed_filename)
-               << endl;
-
-       string const from = formats.getFormatFromFile(filename);
-       if (from.empty()) {
-               setStatus(ErrorConverting);
-               LYXERR(Debug::GRAPHICS)
-                       << "\tCould not determine file format." << endl;
-       }
-       LYXERR(Debug::GRAPHICS)
-               << "\n\tThe file contains " << from << " format data." << endl;
-       to_ = findTargetFormat(from);
-
-       if (from == to_) {
-               // No conversion needed!
-               LYXERR(Debug::GRAPHICS) << "\tNo conversion needed (from == to)!" << endl;
-               file_to_load_ = filename;
-               loadImage();
-               return;
-       }
-
-       if (ConverterCache::get().inCache(filename, to_)) {
-               LYXERR(Debug::GRAPHICS) << "\tNo conversion needed (file in file cache)!"
-                                       << endl;
-               file_to_load_ = ConverterCache::get().cacheName(filename, to_);
-               loadImage();
-               return;
-       }
-
-       LYXERR(Debug::GRAPHICS) << "\tConverting it to " << to_ << " format." << endl;
-
-       // Add some stuff to create a uniquely named temporary file.
-       // This file is deleted in loadImage after it is loaded into memory.
-       FileName const to_file_base(tempName(FileName(), "CacheItem"));
-       remove_loaded_file_ = true;
-
-       // Remove the temp file, we only want the name...
-       // FIXME: This is unsafe!
-       unlink(to_file_base);
-
-       // Connect a signal to this->imageConverted and pass this signal to
-       // the graphics converter so that we can load the modified file
-       // on completion of the conversion process.
-       converter_.reset(new Converter(filename, to_file_base.absFilename(), from, to_));
-       converter_->connect(boost::bind(&Impl::imageConverted, this, _1));
-       converter_->startConversion();
-}
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/GraphicsCacheItem.cpp b/src/graphics/GraphicsCacheItem.cpp
new file mode 100644 (file)
index 0000000..74e9eb4
--- /dev/null
@@ -0,0 +1,451 @@
+/**
+ * \file GraphicsCacheItem.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Baruch Even
+ * \author Herbert Voß
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "GraphicsCacheItem.h"
+#include "GraphicsConverter.h"
+#include "GraphicsImage.h"
+
+#include "ConverterCache.h"
+#include "debug.h"
+#include "format.h"
+
+#include "support/filetools.h"
+#include "support/FileMonitor.h"
+#include "support/lyxlib.h"
+
+#include <boost/bind.hpp>
+
+
+namespace lyx {
+
+using support::FileMonitor;
+using support::FileName;
+using support::isFileReadable;
+using support::makeDisplayPath;
+using support::onlyFilename;
+using support::tempName;
+using support::unlink;
+using support::unzipFile;
+using support::zippedFile;
+
+using std::endl;
+using std::string;
+
+
+namespace graphics {
+
+class CacheItem::Impl : public boost::signals::trackable {
+public:
+
+       ///
+       Impl(FileName const & file);
+
+       /** Start the image conversion process, checking first that it is
+        *  necessary. If it is necessary, then a conversion task is started.
+        *  CacheItem asumes that the conversion is asynchronous and so
+        *  passes a Signal to the converting routine. When the conversion
+        *  is finished, this Signal is emitted, returning the converted
+        *  file to this->imageConverted.
+        *
+        *  If no file conversion is needed, then convertToDisplayFormat() calls
+        *  loadImage() directly.
+        *
+        *  convertToDisplayFormat() will set the loading status flag as
+        *  approriate through calls to setStatus().
+        */
+       void convertToDisplayFormat();
+
+       /** Load the image into memory. This is called either from
+        *  convertToDisplayFormat() direct or from imageConverted().
+        */
+       void loadImage();
+
+       /** Get a notification when the image conversion is done.
+        *  Connected to a signal on_finish_ which is passed to
+        *  Converter::convert.
+        */
+       void imageConverted(bool);
+
+       /** Get a notification when the image loading is done.
+        *  Connected to a signal on_finish_ which is passed to
+        *  lyx::graphics::Image::loadImage.
+        */
+       void imageLoaded(bool);
+
+       /** Sets the status of the loading process. Also notifies
+        *  listeners that the status has changed.
+        */
+       void setStatus(ImageStatus new_status);
+
+       /** Can be invoked directly by the user, but is also connected to the
+        *  FileMonitor and so is invoked when the file is changed
+        *  (if monitoring is taking place).
+        */
+       void startLoading();
+
+       /** If we are asked to load the file for a second or further time,
+        *  (because the file has changed), then we'll have to first reset
+        *  many of the variables below.
+        */
+       void reset();
+
+       /// The filename we refer too.
+       FileName const filename_;
+       ///
+       FileMonitor const monitor_;
+
+       /// Is the file compressed?
+       bool zipped_;
+       /// If so, store the uncompressed file in this temporary file.
+       FileName unzipped_filename_;
+       /// The target format
+       string to_;
+       /// What file are we trying to load?
+       FileName file_to_load_;
+       /** Should we delete the file after loading? True if the file is
+        *  the result of a conversion process.
+        */
+       bool remove_loaded_file_;
+
+       /// The image and its loading status.
+       boost::shared_ptr<Image> image_;
+       ///
+       ImageStatus status_;
+
+       /// This signal is emitted when the image loading status changes.
+       boost::signal<void()> statusChanged;
+
+       /// The connection to the signal Image::finishedLoading
+       boost::signals::connection cl_;
+
+       /// The connection of the signal ConvProcess::finishedConversion,
+       boost::signals::connection cc_;
+
+       ///
+       boost::scoped_ptr<Converter> converter_;
+};
+
+
+CacheItem::CacheItem(FileName const & file)
+       : pimpl_(new Impl(file))
+{}
+
+
+CacheItem::~CacheItem()
+{}
+
+
+FileName const & CacheItem::filename() const
+{
+       return pimpl_->filename_;
+}
+
+
+void CacheItem::startLoading() const
+{
+       pimpl_->startLoading();
+}
+
+
+void CacheItem::startMonitoring() const
+{
+       if (!pimpl_->monitor_.monitoring())
+               pimpl_->monitor_.start();
+}
+
+
+bool CacheItem::monitoring() const
+{
+       return pimpl_->monitor_.monitoring();
+}
+
+
+unsigned long CacheItem::checksum() const
+{
+       return pimpl_->monitor_.checksum();
+}
+
+
+Image const * CacheItem::image() const
+{
+       return pimpl_->image_.get();
+}
+
+
+ImageStatus CacheItem::status() const
+{
+       return pimpl_->status_;
+}
+
+
+boost::signals::connection CacheItem::connect(slot_type const & slot) const
+{
+       return pimpl_->statusChanged.connect(slot);
+}
+
+
+//------------------------------
+// Implementation details follow
+//------------------------------
+
+
+CacheItem::Impl::Impl(FileName const & file)
+       : filename_(file),
+         monitor_(file, 2000),
+         zipped_(false),
+         remove_loaded_file_(false),
+         status_(WaitingToLoad)
+{
+       monitor_.connect(boost::bind(&Impl::startLoading, this));
+}
+
+
+void CacheItem::Impl::startLoading()
+{
+       if (status_ != WaitingToLoad)
+               reset();
+
+       convertToDisplayFormat();
+}
+
+
+void CacheItem::Impl::reset()
+{
+       zipped_ = false;
+       if (!unzipped_filename_.empty())
+               unlink(unzipped_filename_);
+       unzipped_filename_.erase();
+
+       if (remove_loaded_file_ && !file_to_load_.empty())
+               unlink(file_to_load_);
+       remove_loaded_file_ = false;
+       file_to_load_.erase();
+       to_.erase();
+
+       if (image_.get())
+               image_.reset();
+
+       status_ = WaitingToLoad;
+
+       if (cl_.connected())
+               cl_.disconnect();
+
+       if (cc_.connected())
+               cc_.disconnect();
+
+       if (converter_.get())
+               converter_.reset();
+}
+
+
+void CacheItem::Impl::setStatus(ImageStatus new_status)
+{
+       if (status_ == new_status)
+               return;
+
+       status_ = new_status;
+       statusChanged();
+}
+
+
+void CacheItem::Impl::imageConverted(bool success)
+{
+       string const text = success ? "succeeded" : "failed";
+       LYXERR(Debug::GRAPHICS) << "Image conversion " << text << '.' << endl;
+
+       file_to_load_ = converter_.get() ?
+               FileName(converter_->convertedFile()) : FileName();
+       converter_.reset();
+       cc_.disconnect();
+
+       success = !file_to_load_.empty() && isFileReadable(file_to_load_);
+
+       if (!success) {
+               LYXERR(Debug::GRAPHICS) << "Unable to find converted file!"
+                                       << endl;
+               setStatus(ErrorConverting);
+
+               if (zipped_)
+                       unlink(unzipped_filename_);
+
+               return;
+       }
+
+       // Add the converted file to the file cache
+       ConverterCache::get().add(filename_, to_, file_to_load_);
+
+       loadImage();
+}
+
+
+// This function gets called from the callback after the image has been
+// converted successfully.
+void CacheItem::Impl::loadImage()
+{
+       setStatus(Loading);
+       LYXERR(Debug::GRAPHICS) << "Loading image." << endl;
+
+       image_ = Image::newImage();
+
+       cl_.disconnect();
+       cl_ = image_->finishedLoading.connect(
+               boost::bind(&Impl::imageLoaded, this, _1));
+       image_->load(file_to_load_);
+}
+
+
+void CacheItem::Impl::imageLoaded(bool success)
+{
+       string const text = success ? "succeeded" : "failed";
+       LYXERR(Debug::GRAPHICS) << "Image loading " << text << '.' << endl;
+
+       // Clean up after loading.
+       if (zipped_)
+               unlink(unzipped_filename_);
+
+       if (remove_loaded_file_ && unzipped_filename_ != file_to_load_)
+               unlink(file_to_load_);
+
+       cl_.disconnect();
+
+       if (!success) {
+               setStatus(ErrorLoading);
+               return;
+       }
+
+       // Inform the outside world.
+       setStatus(Loaded);
+}
+
+
+static string const findTargetFormat(string const & from)
+{
+       typedef lyx::graphics::Image::FormatList FormatList;
+       FormatList const formats = lyx::graphics::Image::loadableFormats();
+
+        // There must be a format to load from.
+       BOOST_ASSERT(!formats.empty());
+
+       // Use the standard converter if we don't know the format to load
+       // from.
+       if (from.empty())
+               return string("ppm");
+
+       // First ascertain if we can load directly with no conversion
+       FormatList::const_iterator it  = formats.begin();
+       FormatList::const_iterator end = formats.end();
+       for (; it != end; ++it) {
+               if (from == *it)
+                       return *it;
+       }
+
+       // So, we have to convert to a loadable format. Can we?
+       it = formats.begin();
+       for (; it != end; ++it) {
+               if (lyx::graphics::Converter::isReachable(from, *it))
+                       return *it;
+               else
+                       LYXERR(Debug::GRAPHICS)
+                               << "Unable to convert from " << from
+                               << " to " << *it << std::endl;
+       }
+
+       // Failed! so we have to try to convert it to PPM format
+       // with the standard converter
+       return string("ppm");
+}
+
+
+void CacheItem::Impl::convertToDisplayFormat()
+{
+       setStatus(Converting);
+
+       // First, check that the file exists!
+       if (!isFileReadable(filename_)) {
+               if (status_ != ErrorNoFile) {
+                       setStatus(ErrorNoFile);
+                       LYXERR(Debug::GRAPHICS)
+                               << "\tThe file is not readable" << endl;
+               }
+               return;
+       }
+
+       // Make a local copy in case we unzip it
+       FileName filename;
+       zipped_ = zippedFile(filename_);
+       if (zipped_) {
+               unzipped_filename_ = tempName(FileName(), filename_.toFilesystemEncoding());
+               if (unzipped_filename_.empty()) {
+                       setStatus(ErrorConverting);
+                       LYXERR(Debug::GRAPHICS)
+                               << "\tCould not create temporary file." << endl;
+                       return;
+               }
+               filename = unzipFile(filename_, unzipped_filename_.toFilesystemEncoding());
+       } else
+               filename = filename_;
+
+       docstring const displayed_filename = makeDisplayPath(filename_.absFilename());
+       LYXERR(Debug::GRAPHICS) << "[graphics::CacheItem::Impl::convertToDisplayFormat]\n"
+               << "\tAttempting to convert image file: " << filename
+               << "\n\twith displayed filename: " << lyx::to_utf8(displayed_filename)
+               << endl;
+
+       string const from = formats.getFormatFromFile(filename);
+       if (from.empty()) {
+               setStatus(ErrorConverting);
+               LYXERR(Debug::GRAPHICS)
+                       << "\tCould not determine file format." << endl;
+       }
+       LYXERR(Debug::GRAPHICS)
+               << "\n\tThe file contains " << from << " format data." << endl;
+       to_ = findTargetFormat(from);
+
+       if (from == to_) {
+               // No conversion needed!
+               LYXERR(Debug::GRAPHICS) << "\tNo conversion needed (from == to)!" << endl;
+               file_to_load_ = filename;
+               loadImage();
+               return;
+       }
+
+       if (ConverterCache::get().inCache(filename, to_)) {
+               LYXERR(Debug::GRAPHICS) << "\tNo conversion needed (file in file cache)!"
+                                       << endl;
+               file_to_load_ = ConverterCache::get().cacheName(filename, to_);
+               loadImage();
+               return;
+       }
+
+       LYXERR(Debug::GRAPHICS) << "\tConverting it to " << to_ << " format." << endl;
+
+       // Add some stuff to create a uniquely named temporary file.
+       // This file is deleted in loadImage after it is loaded into memory.
+       FileName const to_file_base(tempName(FileName(), "CacheItem"));
+       remove_loaded_file_ = true;
+
+       // Remove the temp file, we only want the name...
+       // FIXME: This is unsafe!
+       unlink(to_file_base);
+
+       // Connect a signal to this->imageConverted and pass this signal to
+       // the graphics converter so that we can load the modified file
+       // on completion of the conversion process.
+       converter_.reset(new Converter(filename, to_file_base.absFilename(), from, to_));
+       converter_->connect(boost::bind(&Impl::imageConverted, this, _1));
+       converter_->startConversion();
+}
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/graphics/GraphicsConverter.C b/src/graphics/GraphicsConverter.C
deleted file mode 100644 (file)
index 3a69da9..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/**
- * \file GraphicsConverter.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "GraphicsConverter.h"
-
-#include "converter.h"
-#include "debug.h"
-#include "format.h"
-
-#include "support/filetools.h"
-#include "support/forkedcallqueue.h"
-#include "support/convert.h"
-#include "support/lstrings.h"
-#include "support/lyxlib.h"
-#include "support/os.h"
-
-#include <boost/bind.hpp>
-
-#include <sstream>
-#include <fstream>
-
-namespace support = lyx::support;
-
-using support::addExtension;
-using support::changeExtension;
-using support::FileName;
-using support::Forkedcall;
-using support::ForkedCallQueue;
-using support::getExtension;
-using support::libScriptSearch;
-using support::onlyPath;
-using support::onlyFilename;
-using support::quoteName;
-using support::quote_python;
-using support::subst;
-using support::tempName;
-using support::unlink;
-
-using std::endl;
-using std::ostream;
-using std::ostringstream;
-using std::string;
-
-
-namespace lyx {
-namespace graphics {
-
-class Converter::Impl : public boost::signals::trackable {
-public:
-       ///
-       Impl(FileName const &, string const &, string const &, string const &);
-
-       ///
-       void startConversion();
-
-       /** This method is connected to a signal passed to the forked call
-        *  class, passing control back here when the conversion is completed.
-        *  Cleans-up the temporary files, emits the finishedConversion
-        *  signal and removes the Converter from the list of all processes.
-        */
-       void converted(pid_t pid, int retval);
-
-       /** At the end of the conversion process inform the outside world
-        *  by emitting a signal.
-        */
-       typedef boost::signal<void(bool)> SignalType;
-       ///
-       SignalType finishedConversion;
-
-       ///
-       string script_command_;
-       ///
-       FileName script_file_;
-       ///
-       FileName to_file_;
-       ///
-       bool valid_process_;
-       ///
-       bool finished_;
-};
-
-
-bool Converter::isReachable(string const & from_format_name,
-                           string const & to_format_name)
-{
-       return theConverters().isReachable(from_format_name, to_format_name);
-}
-
-
-Converter::Converter(FileName const & from_file, string const & to_file_base,
-                    string const & from_format, string const & to_format)
-       : pimpl_(new Impl(from_file, to_file_base, from_format, to_format))
-{}
-
-
-// Empty d-tor out-of-line to keep boost::scoped_ptr happy.
-Converter::~Converter()
-{}
-
-
-void Converter::startConversion() const
-{
-       pimpl_->startConversion();
-}
-
-
-boost::signals::connection Converter::connect(slot_type const & slot) const
-{
-       return pimpl_->finishedConversion.connect(slot);
-}
-
-
-FileName const & Converter::convertedFile() const
-{
-       static FileName const empty;
-       return pimpl_->finished_ ? pimpl_->to_file_ : empty;
-}
-
-/** Build the conversion script.
- *  The script is output to the stream \p script.
- */
-static void build_script(FileName const & from_file, string const & to_file_base,
-                 string const & from_format, string const & to_format,
-                 ostream & script);
-
-
-Converter::Impl::Impl(FileName const & from_file, string const & to_file_base,
-                     string const & from_format, string const & to_format)
-       : valid_process_(false), finished_(false)
-{
-       LYXERR(Debug::GRAPHICS) << "Converter c-tor:\n"
-               << "\tfrom_file:      " << from_file
-               << "\n\tto_file_base: " << to_file_base
-               << "\n\tfrom_format:  " << from_format
-               << "\n\tto_format:    " << to_format << endl;
-
-       // The converted image is to be stored in this file (we do not
-       // use ChangeExtension because this is a basename which may
-       // nevertheless contain a '.')
-       to_file_ = FileName(to_file_base + '.' +  formats.extension(to_format));
-
-       // The conversion commands are stored in a stringstream
-       ostringstream script;
-       build_script(from_file, to_file_base, from_format, to_format, script);
-       LYXERR(Debug::GRAPHICS) << "\tConversion script:"
-               << "\n--------------------------------------\n"
-               << script.str()
-               << "\n--------------------------------------\n";
-
-       // Output the script to file.
-       static int counter = 0;
-       script_file_ = FileName(onlyPath(to_file_base) + "lyxconvert" +
-               convert<string>(counter++) + ".py");
-
-       std::ofstream fs(script_file_.toFilesystemEncoding().c_str());
-       if (!fs.good()) {
-               lyxerr << "Unable to write the conversion script to \""
-                      << script_file_ << '\n'
-                      << "Please check your directory permissions."
-                      << std::endl;
-               return;
-       }
-
-       fs << script.str();
-       fs.close();
-
-       // The command needed to run the conversion process
-       // We create a dummy command for ease of understanding of the
-       // list of forked processes.
-       // Note: 'python ' is absolutely essential, or execvp will fail.
-       script_command_ = support::os::python() + ' ' +
-               quoteName(script_file_.toFilesystemEncoding()) + ' ' +
-               quoteName(onlyFilename(from_file.toFilesystemEncoding())) + ' ' +
-               quoteName(to_format);
-       // All is ready to go
-       valid_process_ = true;
-}
-
-
-void Converter::Impl::startConversion()
-{
-       if (!valid_process_) {
-               converted(0, 1);
-               return;
-       }
-
-       Forkedcall::SignalTypePtr
-               ptr = ForkedCallQueue::get().add(script_command_);
-
-       ptr->connect(boost::bind(&Impl::converted, this, _1, _2));
-
-}
-
-void Converter::Impl::converted(pid_t /* pid */, int retval)
-{
-       if (finished_)
-               // We're done already!
-               return;
-
-       finished_ = true;
-       // Clean-up behind ourselves
-       unlink(script_file_);
-
-       if (retval > 0) {
-               unlink(to_file_);
-               to_file_.erase();
-               finishedConversion(false);
-       } else {
-               finishedConversion(true);
-       }
-}
-
-
-static string const move_file(string const & from_file, string const & to_file)
-{
-       if (from_file == to_file)
-               return string();
-
-       ostringstream command;
-       command << "fromfile = " << from_file << "\n"
-               << "tofile = "   << to_file << "\n\n"
-               << "try:\n"
-               << "  os.rename(fromfile, tofile)\n"
-               << "except:\n"
-               << "  try:\n"
-               << "    shutil.copy(fromfile, tofile)\n"
-               << "  except:\n"
-               << "    sys.exit(1)\n"
-               << "  unlinkNoThrow(fromfile)\n";
-
-       return command.str();
-}
-
-
-static void build_conversion_command(string const & command, ostream & script)
-{
-       // Store in the python script
-       script << "\nif os.system(r'" << command << "') != 0:\n";
-
-       // Test that this was successful. If not, remove
-       // ${outfile} and exit the python script
-       script << "  unlinkNoThrow(outfile)\n"
-              << "  sys.exit(1)\n\n";
-
-       // Test that the outfile exists.
-       // ImageMagick's convert will often create ${outfile}.0,
-       // ${outfile}.1.
-       // If this occurs, move ${outfile}.0 to ${outfile}
-       // and delete ${outfile}.? (ignore errors)
-       script << "if not os.path.isfile(outfile):\n"
-                 "  if os.path.isfile(outfile + '.0'):\n"
-                 "    os.rename(outfile + '.0', outfile)\n"
-                 "    import glob\n"
-                 "    for file in glob.glob(outfile + '.?'):\n"
-                 "      unlinkNoThrow(file)\n"
-                 "  else:\n"
-                 "    sys.exit(1)\n\n";
-
-       // Delete the infile
-       script << "unlinkNoThrow(infile)\n\n";
-}
-
-
-static void build_script(FileName const & from_file,
-                 string const & to_file_base,
-                 string const & from_format,
-                 string const & to_format,
-                 ostream & script)
-{
-       BOOST_ASSERT(from_format != to_format);
-       LYXERR(Debug::GRAPHICS) << "build_script ... ";
-       typedef Converters::EdgePath EdgePath;
-
-       script << "#!/usr/bin/env python\n"
-                 "# -*- coding: utf-8 -*-\n"
-                 "import os, shutil, sys, locale\n\n"
-                 "def unlinkNoThrow(file):\n"
-                 "  ''' remove a file, do not throw if an error occurs '''\n"
-                 "  try:\n"
-                 "    os.unlink(file)\n"
-                 "  except:\n"
-                 "    pass\n\n"
-                 "def utf8ToDefaultEncoding(file):\n"
-                 "  ''' if possible, convert to the default encoding '''\n"
-                 "  try:\n"
-                 "    language, output_encoding = locale.getdefaultlocale()\n"
-                 "    if output_encoding == None:\n"
-                 "      output_encoding = 'latin1'\n"
-                 "    return unicode(file, 'utf8').encode(output_encoding)\n"
-                 "  except:\n"
-                 "    return file\n\n";
-
-       // we do not use ChangeExtension because this is a basename
-       // which may nevertheless contain a '.'
-       string const to_file = to_file_base + '.'
-               + formats.extension(to_format);
-
-       EdgePath const edgepath = from_format.empty() ?
-               EdgePath() :
-               theConverters().getPath(from_format, to_format);
-
-       // Create a temporary base file-name for all intermediate steps.
-       // Remember to remove the temp file because we only want the name...
-       static int counter = 0;
-       string const tmp = "gconvert" + convert<string>(counter++);
-       FileName const to_base(tempName(FileName(), tmp));
-       unlink(to_base);
-
-       // Create a copy of the file in case the original name contains
-       // problematic characters like ' or ". We can work around that problem
-       // in python, but the converters might be shell scripts and have more
-       // troubles with it.
-       string outfile = addExtension(to_base.absFilename(), getExtension(from_file.absFilename()));
-       script << "infile = utf8ToDefaultEncoding("
-                       << quoteName(from_file.absFilename(), quote_python)
-                       << ")\n"
-                 "outfile = " << quoteName(outfile, quote_python) << "\n"
-                 "shutil.copy(infile, outfile)\n";
-
-       // Some converters (e.g. lilypond) can only output files to the
-       // current directory, so we need to change the current directory.
-       // This has the added benefit that all other files that may be
-       // generated by the converter are deleted when LyX closes and do not
-       // clutter the real working directory.
-       script << "os.chdir(" << quoteName(onlyPath(outfile)) << ")\n";
-
-       if (edgepath.empty()) {
-               // Either from_format is unknown or we don't have a
-               // converter path from from_format to to_format, so we use
-               // the default converter.
-               script << "infile = outfile\n"
-                      << "outfile = " << quoteName(to_file, quote_python)
-                      << '\n';
-
-               ostringstream os;
-               os << support::os::python() << ' '
-                  << libScriptSearch("$$s/scripts/convertDefault.py",
-                                     quote_python) << ' ';
-               if (!from_format.empty())
-                       os << from_format << ':';
-               // The extra " quotes around infile and outfile are needed
-               // because the filename may contain spaces and it is used
-               // as argument of os.system().
-               os << "' + '\"' + infile + '\"' + ' "
-                  << to_format << ":' + '\"' + outfile + '\"' + '";
-               string const command = os.str();
-
-               LYXERR(Debug::GRAPHICS)
-                       << "\tNo converter defined! I use convertDefault.py\n\t"
-                       << command << endl;
-
-               build_conversion_command(command, script);
-       }
-
-       // The conversion commands may contain these tokens that need to be
-       // changed to infile, infile_base, outfile respectively.
-       string const token_from("$$i");
-       string const token_base("$$b");
-       string const token_to("$$o");
-
-       EdgePath::const_iterator it  = edgepath.begin();
-       EdgePath::const_iterator end = edgepath.end();
-
-       for (; it != end; ++it) {
-               lyx::Converter const & conv = theConverters().get(*it);
-
-               // Build the conversion command
-               string const infile      = outfile;
-               string const infile_base = changeExtension(infile, string());
-               outfile = addExtension(to_base.absFilename(), conv.To->extension());
-
-               // Store these names in the python script
-               script << "infile = "      << quoteName(infile, quote_python) << "\n"
-                         "infile_base = " << quoteName(infile_base, quote_python) << "\n"
-                         "outfile = "     << quoteName(outfile, quote_python) << '\n';
-
-               // See comment about extra " quotes above (although that
-               // applies only for the first loop run here).
-               string command = conv.command;
-               command = subst(command, token_from, "' + '\"' + infile + '\"' + '");
-               command = subst(command, token_base, "' + '\"' + infile_base + '\"' + '");
-               command = subst(command, token_to,   "' + '\"' + outfile + '\"' + '");
-               command = libScriptSearch(command, quote_python);
-
-               build_conversion_command(command, script);
-       }
-
-       // Move the final outfile to to_file
-       script << move_file("outfile", quoteName(to_file, quote_python));
-       LYXERR(Debug::GRAPHICS) << "ready!" << endl;
-}
-
-} // namespace graphics
-
-} // namespace lyx
diff --git a/src/graphics/GraphicsConverter.cpp b/src/graphics/GraphicsConverter.cpp
new file mode 100644 (file)
index 0000000..3a69da9
--- /dev/null
@@ -0,0 +1,404 @@
+/**
+ * \file GraphicsConverter.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "GraphicsConverter.h"
+
+#include "converter.h"
+#include "debug.h"
+#include "format.h"
+
+#include "support/filetools.h"
+#include "support/forkedcallqueue.h"
+#include "support/convert.h"
+#include "support/lstrings.h"
+#include "support/lyxlib.h"
+#include "support/os.h"
+
+#include <boost/bind.hpp>
+
+#include <sstream>
+#include <fstream>
+
+namespace support = lyx::support;
+
+using support::addExtension;
+using support::changeExtension;
+using support::FileName;
+using support::Forkedcall;
+using support::ForkedCallQueue;
+using support::getExtension;
+using support::libScriptSearch;
+using support::onlyPath;
+using support::onlyFilename;
+using support::quoteName;
+using support::quote_python;
+using support::subst;
+using support::tempName;
+using support::unlink;
+
+using std::endl;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+
+
+namespace lyx {
+namespace graphics {
+
+class Converter::Impl : public boost::signals::trackable {
+public:
+       ///
+       Impl(FileName const &, string const &, string const &, string const &);
+
+       ///
+       void startConversion();
+
+       /** This method is connected to a signal passed to the forked call
+        *  class, passing control back here when the conversion is completed.
+        *  Cleans-up the temporary files, emits the finishedConversion
+        *  signal and removes the Converter from the list of all processes.
+        */
+       void converted(pid_t pid, int retval);
+
+       /** At the end of the conversion process inform the outside world
+        *  by emitting a signal.
+        */
+       typedef boost::signal<void(bool)> SignalType;
+       ///
+       SignalType finishedConversion;
+
+       ///
+       string script_command_;
+       ///
+       FileName script_file_;
+       ///
+       FileName to_file_;
+       ///
+       bool valid_process_;
+       ///
+       bool finished_;
+};
+
+
+bool Converter::isReachable(string const & from_format_name,
+                           string const & to_format_name)
+{
+       return theConverters().isReachable(from_format_name, to_format_name);
+}
+
+
+Converter::Converter(FileName const & from_file, string const & to_file_base,
+                    string const & from_format, string const & to_format)
+       : pimpl_(new Impl(from_file, to_file_base, from_format, to_format))
+{}
+
+
+// Empty d-tor out-of-line to keep boost::scoped_ptr happy.
+Converter::~Converter()
+{}
+
+
+void Converter::startConversion() const
+{
+       pimpl_->startConversion();
+}
+
+
+boost::signals::connection Converter::connect(slot_type const & slot) const
+{
+       return pimpl_->finishedConversion.connect(slot);
+}
+
+
+FileName const & Converter::convertedFile() const
+{
+       static FileName const empty;
+       return pimpl_->finished_ ? pimpl_->to_file_ : empty;
+}
+
+/** Build the conversion script.
+ *  The script is output to the stream \p script.
+ */
+static void build_script(FileName const & from_file, string const & to_file_base,
+                 string const & from_format, string const & to_format,
+                 ostream & script);
+
+
+Converter::Impl::Impl(FileName const & from_file, string const & to_file_base,
+                     string const & from_format, string const & to_format)
+       : valid_process_(false), finished_(false)
+{
+       LYXERR(Debug::GRAPHICS) << "Converter c-tor:\n"
+               << "\tfrom_file:      " << from_file
+               << "\n\tto_file_base: " << to_file_base
+               << "\n\tfrom_format:  " << from_format
+               << "\n\tto_format:    " << to_format << endl;
+
+       // The converted image is to be stored in this file (we do not
+       // use ChangeExtension because this is a basename which may
+       // nevertheless contain a '.')
+       to_file_ = FileName(to_file_base + '.' +  formats.extension(to_format));
+
+       // The conversion commands are stored in a stringstream
+       ostringstream script;
+       build_script(from_file, to_file_base, from_format, to_format, script);
+       LYXERR(Debug::GRAPHICS) << "\tConversion script:"
+               << "\n--------------------------------------\n"
+               << script.str()
+               << "\n--------------------------------------\n";
+
+       // Output the script to file.
+       static int counter = 0;
+       script_file_ = FileName(onlyPath(to_file_base) + "lyxconvert" +
+               convert<string>(counter++) + ".py");
+
+       std::ofstream fs(script_file_.toFilesystemEncoding().c_str());
+       if (!fs.good()) {
+               lyxerr << "Unable to write the conversion script to \""
+                      << script_file_ << '\n'
+                      << "Please check your directory permissions."
+                      << std::endl;
+               return;
+       }
+
+       fs << script.str();
+       fs.close();
+
+       // The command needed to run the conversion process
+       // We create a dummy command for ease of understanding of the
+       // list of forked processes.
+       // Note: 'python ' is absolutely essential, or execvp will fail.
+       script_command_ = support::os::python() + ' ' +
+               quoteName(script_file_.toFilesystemEncoding()) + ' ' +
+               quoteName(onlyFilename(from_file.toFilesystemEncoding())) + ' ' +
+               quoteName(to_format);
+       // All is ready to go
+       valid_process_ = true;
+}
+
+
+void Converter::Impl::startConversion()
+{
+       if (!valid_process_) {
+               converted(0, 1);
+               return;
+       }
+
+       Forkedcall::SignalTypePtr
+               ptr = ForkedCallQueue::get().add(script_command_);
+
+       ptr->connect(boost::bind(&Impl::converted, this, _1, _2));
+
+}
+
+void Converter::Impl::converted(pid_t /* pid */, int retval)
+{
+       if (finished_)
+               // We're done already!
+               return;
+
+       finished_ = true;
+       // Clean-up behind ourselves
+       unlink(script_file_);
+
+       if (retval > 0) {
+               unlink(to_file_);
+               to_file_.erase();
+               finishedConversion(false);
+       } else {
+               finishedConversion(true);
+       }
+}
+
+
+static string const move_file(string const & from_file, string const & to_file)
+{
+       if (from_file == to_file)
+               return string();
+
+       ostringstream command;
+       command << "fromfile = " << from_file << "\n"
+               << "tofile = "   << to_file << "\n\n"
+               << "try:\n"
+               << "  os.rename(fromfile, tofile)\n"
+               << "except:\n"
+               << "  try:\n"
+               << "    shutil.copy(fromfile, tofile)\n"
+               << "  except:\n"
+               << "    sys.exit(1)\n"
+               << "  unlinkNoThrow(fromfile)\n";
+
+       return command.str();
+}
+
+
+static void build_conversion_command(string const & command, ostream & script)
+{
+       // Store in the python script
+       script << "\nif os.system(r'" << command << "') != 0:\n";
+
+       // Test that this was successful. If not, remove
+       // ${outfile} and exit the python script
+       script << "  unlinkNoThrow(outfile)\n"
+              << "  sys.exit(1)\n\n";
+
+       // Test that the outfile exists.
+       // ImageMagick's convert will often create ${outfile}.0,
+       // ${outfile}.1.
+       // If this occurs, move ${outfile}.0 to ${outfile}
+       // and delete ${outfile}.? (ignore errors)
+       script << "if not os.path.isfile(outfile):\n"
+                 "  if os.path.isfile(outfile + '.0'):\n"
+                 "    os.rename(outfile + '.0', outfile)\n"
+                 "    import glob\n"
+                 "    for file in glob.glob(outfile + '.?'):\n"
+                 "      unlinkNoThrow(file)\n"
+                 "  else:\n"
+                 "    sys.exit(1)\n\n";
+
+       // Delete the infile
+       script << "unlinkNoThrow(infile)\n\n";
+}
+
+
+static void build_script(FileName const & from_file,
+                 string const & to_file_base,
+                 string const & from_format,
+                 string const & to_format,
+                 ostream & script)
+{
+       BOOST_ASSERT(from_format != to_format);
+       LYXERR(Debug::GRAPHICS) << "build_script ... ";
+       typedef Converters::EdgePath EdgePath;
+
+       script << "#!/usr/bin/env python\n"
+                 "# -*- coding: utf-8 -*-\n"
+                 "import os, shutil, sys, locale\n\n"
+                 "def unlinkNoThrow(file):\n"
+                 "  ''' remove a file, do not throw if an error occurs '''\n"
+                 "  try:\n"
+                 "    os.unlink(file)\n"
+                 "  except:\n"
+                 "    pass\n\n"
+                 "def utf8ToDefaultEncoding(file):\n"
+                 "  ''' if possible, convert to the default encoding '''\n"
+                 "  try:\n"
+                 "    language, output_encoding = locale.getdefaultlocale()\n"
+                 "    if output_encoding == None:\n"
+                 "      output_encoding = 'latin1'\n"
+                 "    return unicode(file, 'utf8').encode(output_encoding)\n"
+                 "  except:\n"
+                 "    return file\n\n";
+
+       // we do not use ChangeExtension because this is a basename
+       // which may nevertheless contain a '.'
+       string const to_file = to_file_base + '.'
+               + formats.extension(to_format);
+
+       EdgePath const edgepath = from_format.empty() ?
+               EdgePath() :
+               theConverters().getPath(from_format, to_format);
+
+       // Create a temporary base file-name for all intermediate steps.
+       // Remember to remove the temp file because we only want the name...
+       static int counter = 0;
+       string const tmp = "gconvert" + convert<string>(counter++);
+       FileName const to_base(tempName(FileName(), tmp));
+       unlink(to_base);
+
+       // Create a copy of the file in case the original name contains
+       // problematic characters like ' or ". We can work around that problem
+       // in python, but the converters might be shell scripts and have more
+       // troubles with it.
+       string outfile = addExtension(to_base.absFilename(), getExtension(from_file.absFilename()));
+       script << "infile = utf8ToDefaultEncoding("
+                       << quoteName(from_file.absFilename(), quote_python)
+                       << ")\n"
+                 "outfile = " << quoteName(outfile, quote_python) << "\n"
+                 "shutil.copy(infile, outfile)\n";
+
+       // Some converters (e.g. lilypond) can only output files to the
+       // current directory, so we need to change the current directory.
+       // This has the added benefit that all other files that may be
+       // generated by the converter are deleted when LyX closes and do not
+       // clutter the real working directory.
+       script << "os.chdir(" << quoteName(onlyPath(outfile)) << ")\n";
+
+       if (edgepath.empty()) {
+               // Either from_format is unknown or we don't have a
+               // converter path from from_format to to_format, so we use
+               // the default converter.
+               script << "infile = outfile\n"
+                      << "outfile = " << quoteName(to_file, quote_python)
+                      << '\n';
+
+               ostringstream os;
+               os << support::os::python() << ' '
+                  << libScriptSearch("$$s/scripts/convertDefault.py",
+                                     quote_python) << ' ';
+               if (!from_format.empty())
+                       os << from_format << ':';
+               // The extra " quotes around infile and outfile are needed
+               // because the filename may contain spaces and it is used
+               // as argument of os.system().
+               os << "' + '\"' + infile + '\"' + ' "
+                  << to_format << ":' + '\"' + outfile + '\"' + '";
+               string const command = os.str();
+
+               LYXERR(Debug::GRAPHICS)
+                       << "\tNo converter defined! I use convertDefault.py\n\t"
+                       << command << endl;
+
+               build_conversion_command(command, script);
+       }
+
+       // The conversion commands may contain these tokens that need to be
+       // changed to infile, infile_base, outfile respectively.
+       string const token_from("$$i");
+       string const token_base("$$b");
+       string const token_to("$$o");
+
+       EdgePath::const_iterator it  = edgepath.begin();
+       EdgePath::const_iterator end = edgepath.end();
+
+       for (; it != end; ++it) {
+               lyx::Converter const & conv = theConverters().get(*it);
+
+               // Build the conversion command
+               string const infile      = outfile;
+               string const infile_base = changeExtension(infile, string());
+               outfile = addExtension(to_base.absFilename(), conv.To->extension());
+
+               // Store these names in the python script
+               script << "infile = "      << quoteName(infile, quote_python) << "\n"
+                         "infile_base = " << quoteName(infile_base, quote_python) << "\n"
+                         "outfile = "     << quoteName(outfile, quote_python) << '\n';
+
+               // See comment about extra " quotes above (although that
+               // applies only for the first loop run here).
+               string command = conv.command;
+               command = subst(command, token_from, "' + '\"' + infile + '\"' + '");
+               command = subst(command, token_base, "' + '\"' + infile_base + '\"' + '");
+               command = subst(command, token_to,   "' + '\"' + outfile + '\"' + '");
+               command = libScriptSearch(command, quote_python);
+
+               build_conversion_command(command, script);
+       }
+
+       // Move the final outfile to to_file
+       script << move_file("outfile", quoteName(to_file, quote_python));
+       LYXERR(Debug::GRAPHICS) << "ready!" << endl;
+}
+
+} // namespace graphics
+
+} // namespace lyx
diff --git a/src/graphics/GraphicsImage.C b/src/graphics/GraphicsImage.C
deleted file mode 100644 (file)
index c713040..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * \file GraphicsImage.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Baruch Even
- * \author Angus Leeming
- * \author Herbert Voß
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "GraphicsImage.h"
-#include "GraphicsParams.h"
-#include "debug.h"
-
-
-namespace lyx {
-namespace graphics {
-
-// This is to be connected to a function that will return a new
-// instance of a viable derived class.
-boost::function<Image::ImagePtr()> Image::newImage;
-
-/// Return the list of loadable formats.
-boost::function<Image::FormatList()> Image::loadableFormats;
-
-
-std::pair<unsigned int, unsigned int>
-Image::getScaledDimensions(Params const & params) const
-{
-       // scale only when value > 0
-       unsigned int width;
-       unsigned int height;
-       if (params.scale) {
-               width  = (getWidth() * params.scale) / 100;
-               height = (getHeight() * params.scale) / 100;
-       } else {
-               width = getWidth();
-               height = getHeight();
-       }
-
-       LYXERR(Debug::GRAPHICS)
-               << "graphics::Image::getScaledDimensions()"
-               << "\n\tparams.scale       : " << params.scale
-               << "\n\twidth              : " << width
-               << "\n\theight             : " << height
-               << std::endl;
-
-       return std::make_pair(width, height);
-}
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/GraphicsImage.cpp b/src/graphics/GraphicsImage.cpp
new file mode 100644 (file)
index 0000000..c713040
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * \file GraphicsImage.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Baruch Even
+ * \author Angus Leeming
+ * \author Herbert Voß
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "GraphicsImage.h"
+#include "GraphicsParams.h"
+#include "debug.h"
+
+
+namespace lyx {
+namespace graphics {
+
+// This is to be connected to a function that will return a new
+// instance of a viable derived class.
+boost::function<Image::ImagePtr()> Image::newImage;
+
+/// Return the list of loadable formats.
+boost::function<Image::FormatList()> Image::loadableFormats;
+
+
+std::pair<unsigned int, unsigned int>
+Image::getScaledDimensions(Params const & params) const
+{
+       // scale only when value > 0
+       unsigned int width;
+       unsigned int height;
+       if (params.scale) {
+               width  = (getWidth() * params.scale) / 100;
+               height = (getHeight() * params.scale) / 100;
+       } else {
+               width = getWidth();
+               height = getHeight();
+       }
+
+       LYXERR(Debug::GRAPHICS)
+               << "graphics::Image::getScaledDimensions()"
+               << "\n\tparams.scale       : " << params.scale
+               << "\n\twidth              : " << width
+               << "\n\theight             : " << height
+               << std::endl;
+
+       return std::make_pair(width, height);
+}
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/graphics/GraphicsLoader.C b/src/graphics/GraphicsLoader.C
deleted file mode 100644 (file)
index d762748..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/**
- * \file GraphicsLoader.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "GraphicsLoader.h"
-
-#include "GraphicsCacheItem.h"
-#include "GraphicsImage.h"
-#include "GraphicsParams.h"
-#include "LoaderQueue.h"
-
-#include <boost/bind.hpp>
-
-
-using std::string;
-
-
-namespace lyx {
-
-using support::FileName;
-       
-namespace graphics {
-
-class Loader::Impl : public boost::signals::trackable {
-public:
-       ///
-       Impl();
-       ///
-       ~Impl();
-       ///
-       void resetFile(FileName const &);
-       ///
-       void resetParams(Params const &);
-       ///
-       void createPixmap();
-       ///
-       void startLoading();
-       ///
-       Params const & params() const { return params_; }
-
-       /// The loading status of the image.
-       ImageStatus status_;
-       /** Must store a copy of the cached item to ensure that it is not
-        *  erased unexpectedly by the cache itself.
-        */
-       Cache::ItemPtr cached_item_;
-       /// We modify a local copy of the image once it is loaded.
-       Image::ImagePtr image_;
-       /// This signal is emitted when the image loading status changes.
-       boost::signal<void()> signal_;
-
-private:
-       ///
-       void statusChanged();
-       ///
-       void checkedLoading();
-
-       ///
-       Params params_;
-};
-
-
-Loader::Loader()
-       : pimpl_(new Impl)
-{}
-
-
-Loader::Loader(FileName const & file, DisplayType type)
-       : pimpl_(new Impl)
-{
-       reset(file, type);
-}
-
-
-Loader::Loader(FileName const & file, Params const & params)
-       : pimpl_(new Impl)
-{
-       reset(file, params);
-}
-
-
-Loader::Loader(Loader const & other)
-       : pimpl_(new Impl)
-{
-       Params const & params = other.pimpl_->params();
-       reset(params.filename, params);
-}
-
-
-Loader::~Loader()
-{}
-
-
-Loader & Loader::operator=(Loader const & other)
-{
-       if (this != &other) {
-               Params const & params = other.pimpl_->params();
-               reset(params.filename, params);
-       }
-       return *this;
-}
-
-
-void Loader::reset(FileName const & file, DisplayType type) const
-{
-       Params params;
-       params.display = type;
-       pimpl_->resetParams(params);
-
-       pimpl_->resetFile(file);
-       pimpl_->createPixmap();
-}
-
-
-void Loader::reset(FileName const & file, Params const & params) const
-{
-       pimpl_->resetParams(params);
-       pimpl_->resetFile(file);
-       pimpl_->createPixmap();
-}
-
-
-void Loader::reset(Params const & params) const
-{
-       pimpl_->resetParams(params);
-       pimpl_->createPixmap();
-}
-
-
-void Loader::startLoading() const
-{
-       if (pimpl_->status_ != WaitingToLoad || !pimpl_->cached_item_.get())
-               return;
-       pimpl_->startLoading();
-}
-
-
-void Loader::startMonitoring() const
-{
-       if (!pimpl_->cached_item_.get())
-               return;
-
-       pimpl_->cached_item_->startMonitoring();
-}
-
-
-bool Loader::monitoring() const
-{
-       if (!pimpl_->cached_item_.get())
-               return false;
-
-       return pimpl_->cached_item_->monitoring();
-}
-
-
-unsigned long Loader::checksum() const
-{
-       if (!pimpl_->cached_item_.get())
-               return 0;
-
-       return pimpl_->cached_item_->checksum();
-}
-
-
-FileName const & Loader::filename() const
-{
-       static FileName const empty;
-       return pimpl_->cached_item_.get() ?
-               pimpl_->cached_item_->filename() : empty;
-}
-
-
-ImageStatus Loader::status() const
-{
-       return pimpl_->status_;
-}
-
-
-boost::signals::connection Loader::connect(slot_type const & slot) const
-{
-       return pimpl_->signal_.connect(slot);
-}
-
-
-Image const * Loader::image() const
-{
-       return pimpl_->image_.get();
-}
-
-
-Loader::Impl::Impl()
-       : status_(WaitingToLoad)
-{
-}
-
-
-Loader::Impl::~Impl()
-{
-       resetFile(FileName());
-}
-
-
-void Loader::Impl::resetFile(FileName const & file)
-{
-       FileName const old_file = cached_item_.get() ?
-               cached_item_->filename() : FileName();
-
-       if (file == old_file)
-               return;
-
-       // If monitoring() the current file, should continue to monitor the
-       // new file.
-       bool continue_monitoring = false;
-
-       if (!old_file.empty()) {
-               continue_monitoring = cached_item_->monitoring();
-               cached_item_.reset();
-               Cache::get().remove(old_file);
-       }
-
-       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
-       image_.reset();
-
-       if (cached_item_.get() || file.empty())
-               return;
-
-       Cache & gc = Cache::get();
-       if (!gc.inCache(file))
-               gc.add(file);
-
-       // We /must/ make a local copy of this.
-       cached_item_ = gc.item(file);
-       status_ = cached_item_->status();
-
-       if (continue_monitoring && !cached_item_->monitoring())
-               cached_item_->startMonitoring();
-
-       cached_item_->connect(boost::bind(&Impl::statusChanged, this));
-}
-
-
-void Loader::Impl::resetParams(Params const & params)
-{
-       if (params == params_)
-               return;
-
-       params_ = params;
-       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
-       image_.reset();
-}
-
-
-void Loader::Impl::statusChanged()
-{
-       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
-       createPixmap();
-       signal_();
-}
-
-
-void Loader::Impl::createPixmap()
-{
-       if (!cached_item_.get() ||
-           params_.display == NoDisplay || status_ != Loaded)
-               return;
-
-       image_.reset(cached_item_->image()->clone());
-
-       // These do nothing if there's nothing to do
-       image_->clip(params_);
-       image_->rotate(params_);
-       image_->scale(params_);
-
-       bool const success = image_->setPixmap(params_);
-
-       if (success) {
-               status_ = Ready;
-       } else {
-               image_.reset();
-               status_ = ErrorGeneratingPixmap;
-       }
-}
-
-void Loader::Impl::startLoading()
-{
-       if (status_ != WaitingToLoad)
-               return;
-
-       LoaderQueue::get().touch(cached_item_);
-}
-
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/GraphicsLoader.cpp b/src/graphics/GraphicsLoader.cpp
new file mode 100644 (file)
index 0000000..d762748
--- /dev/null
@@ -0,0 +1,302 @@
+/**
+ * \file GraphicsLoader.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "GraphicsLoader.h"
+
+#include "GraphicsCacheItem.h"
+#include "GraphicsImage.h"
+#include "GraphicsParams.h"
+#include "LoaderQueue.h"
+
+#include <boost/bind.hpp>
+
+
+using std::string;
+
+
+namespace lyx {
+
+using support::FileName;
+       
+namespace graphics {
+
+class Loader::Impl : public boost::signals::trackable {
+public:
+       ///
+       Impl();
+       ///
+       ~Impl();
+       ///
+       void resetFile(FileName const &);
+       ///
+       void resetParams(Params const &);
+       ///
+       void createPixmap();
+       ///
+       void startLoading();
+       ///
+       Params const & params() const { return params_; }
+
+       /// The loading status of the image.
+       ImageStatus status_;
+       /** Must store a copy of the cached item to ensure that it is not
+        *  erased unexpectedly by the cache itself.
+        */
+       Cache::ItemPtr cached_item_;
+       /// We modify a local copy of the image once it is loaded.
+       Image::ImagePtr image_;
+       /// This signal is emitted when the image loading status changes.
+       boost::signal<void()> signal_;
+
+private:
+       ///
+       void statusChanged();
+       ///
+       void checkedLoading();
+
+       ///
+       Params params_;
+};
+
+
+Loader::Loader()
+       : pimpl_(new Impl)
+{}
+
+
+Loader::Loader(FileName const & file, DisplayType type)
+       : pimpl_(new Impl)
+{
+       reset(file, type);
+}
+
+
+Loader::Loader(FileName const & file, Params const & params)
+       : pimpl_(new Impl)
+{
+       reset(file, params);
+}
+
+
+Loader::Loader(Loader const & other)
+       : pimpl_(new Impl)
+{
+       Params const & params = other.pimpl_->params();
+       reset(params.filename, params);
+}
+
+
+Loader::~Loader()
+{}
+
+
+Loader & Loader::operator=(Loader const & other)
+{
+       if (this != &other) {
+               Params const & params = other.pimpl_->params();
+               reset(params.filename, params);
+       }
+       return *this;
+}
+
+
+void Loader::reset(FileName const & file, DisplayType type) const
+{
+       Params params;
+       params.display = type;
+       pimpl_->resetParams(params);
+
+       pimpl_->resetFile(file);
+       pimpl_->createPixmap();
+}
+
+
+void Loader::reset(FileName const & file, Params const & params) const
+{
+       pimpl_->resetParams(params);
+       pimpl_->resetFile(file);
+       pimpl_->createPixmap();
+}
+
+
+void Loader::reset(Params const & params) const
+{
+       pimpl_->resetParams(params);
+       pimpl_->createPixmap();
+}
+
+
+void Loader::startLoading() const
+{
+       if (pimpl_->status_ != WaitingToLoad || !pimpl_->cached_item_.get())
+               return;
+       pimpl_->startLoading();
+}
+
+
+void Loader::startMonitoring() const
+{
+       if (!pimpl_->cached_item_.get())
+               return;
+
+       pimpl_->cached_item_->startMonitoring();
+}
+
+
+bool Loader::monitoring() const
+{
+       if (!pimpl_->cached_item_.get())
+               return false;
+
+       return pimpl_->cached_item_->monitoring();
+}
+
+
+unsigned long Loader::checksum() const
+{
+       if (!pimpl_->cached_item_.get())
+               return 0;
+
+       return pimpl_->cached_item_->checksum();
+}
+
+
+FileName const & Loader::filename() const
+{
+       static FileName const empty;
+       return pimpl_->cached_item_.get() ?
+               pimpl_->cached_item_->filename() : empty;
+}
+
+
+ImageStatus Loader::status() const
+{
+       return pimpl_->status_;
+}
+
+
+boost::signals::connection Loader::connect(slot_type const & slot) const
+{
+       return pimpl_->signal_.connect(slot);
+}
+
+
+Image const * Loader::image() const
+{
+       return pimpl_->image_.get();
+}
+
+
+Loader::Impl::Impl()
+       : status_(WaitingToLoad)
+{
+}
+
+
+Loader::Impl::~Impl()
+{
+       resetFile(FileName());
+}
+
+
+void Loader::Impl::resetFile(FileName const & file)
+{
+       FileName const old_file = cached_item_.get() ?
+               cached_item_->filename() : FileName();
+
+       if (file == old_file)
+               return;
+
+       // If monitoring() the current file, should continue to monitor the
+       // new file.
+       bool continue_monitoring = false;
+
+       if (!old_file.empty()) {
+               continue_monitoring = cached_item_->monitoring();
+               cached_item_.reset();
+               Cache::get().remove(old_file);
+       }
+
+       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
+       image_.reset();
+
+       if (cached_item_.get() || file.empty())
+               return;
+
+       Cache & gc = Cache::get();
+       if (!gc.inCache(file))
+               gc.add(file);
+
+       // We /must/ make a local copy of this.
+       cached_item_ = gc.item(file);
+       status_ = cached_item_->status();
+
+       if (continue_monitoring && !cached_item_->monitoring())
+               cached_item_->startMonitoring();
+
+       cached_item_->connect(boost::bind(&Impl::statusChanged, this));
+}
+
+
+void Loader::Impl::resetParams(Params const & params)
+{
+       if (params == params_)
+               return;
+
+       params_ = params;
+       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
+       image_.reset();
+}
+
+
+void Loader::Impl::statusChanged()
+{
+       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
+       createPixmap();
+       signal_();
+}
+
+
+void Loader::Impl::createPixmap()
+{
+       if (!cached_item_.get() ||
+           params_.display == NoDisplay || status_ != Loaded)
+               return;
+
+       image_.reset(cached_item_->image()->clone());
+
+       // These do nothing if there's nothing to do
+       image_->clip(params_);
+       image_->rotate(params_);
+       image_->scale(params_);
+
+       bool const success = image_->setPixmap(params_);
+
+       if (success) {
+               status_ = Ready;
+       } else {
+               image_.reset();
+               status_ = ErrorGeneratingPixmap;
+       }
+}
+
+void Loader::Impl::startLoading()
+{
+       if (status_ != WaitingToLoad)
+               return;
+
+       LoaderQueue::get().touch(cached_item_);
+}
+
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/graphics/GraphicsParams.C b/src/graphics/GraphicsParams.C
deleted file mode 100644 (file)
index d13dc18..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * \file GraphicsParams.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "GraphicsParams.h"
-
-#include "lyxlength.h"
-
-#include <sstream>
-
-
-using std::string;
-using std::abs;
-
-
-namespace lyx {
-namespace graphics {
-
-Params::Params()
-       : display(ColorDisplay),
-         scale(100),
-         angle(0)
-{}
-
-
-bool operator==(Params const & a, Params const & b)
-{
-       return (a.filename == b.filename &&
-               a.display == b.display &&
-               a.bb == b.bb &&
-               a.scale == b.scale &&
-               a.angle == b.angle);
-}
-
-
-bool operator!=(Params const & a, Params const & b)
-{
-       return !(a == b);
-}
-
-
-std::ostream & operator<<(std::ostream & os, BoundingBox const & bb)
-{
-       os << bb.xl << ' ' << bb.yb << ' ' << bb.xr << ' ' << bb.yt;
-       return os;
-}
-
-
-BoundingBox::BoundingBox()
-       : xl(0), yb(0), xr(0), yt(0)
-{}
-
-
-BoundingBox::BoundingBox(string const & bb)
-       : xl(0), yb(0), xr(0), yt(0)
-{
-       if (bb.empty())
-               return;
-
-       std::istringstream is(bb.c_str());
-       string a, b, c, d;
-       is >> a >> b >> c >> d;
-
-       // inBP returns the length in Postscript points.
-       // Note further that there are 72 Postscript pixels per inch.
-       unsigned int const xl_tmp = abs(LyXLength(a).inBP());
-       unsigned int const yb_tmp = abs(LyXLength(b).inBP());
-       unsigned int const xr_tmp = abs(LyXLength(c).inBP());
-       unsigned int const yt_tmp = abs(LyXLength(d).inBP());
-
-       if (xr_tmp <= xl_tmp || yt_tmp <= yb_tmp)
-               return;
-
-       xl = xl_tmp;
-       yb = yb_tmp;
-       xr = xr_tmp;
-       yt = yt_tmp;
-}
-
-
-bool BoundingBox::empty() const
-{
-       return (!xl && !yb && !xr && !yt);
-}
-
-
-bool operator==(BoundingBox const & a, BoundingBox const & b)
-{
-       return (a.xl == b.xl &&
-               a.yb == b.yb &&
-               a.xr == b.xr &&
-               a.yt == b.yt);
-}
-
-
-bool operator!=(BoundingBox const & a, BoundingBox const & b)
-{
-       return !(a == b);
-}
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/GraphicsParams.cpp b/src/graphics/GraphicsParams.cpp
new file mode 100644 (file)
index 0000000..d13dc18
--- /dev/null
@@ -0,0 +1,110 @@
+/**
+ * \file GraphicsParams.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "GraphicsParams.h"
+
+#include "lyxlength.h"
+
+#include <sstream>
+
+
+using std::string;
+using std::abs;
+
+
+namespace lyx {
+namespace graphics {
+
+Params::Params()
+       : display(ColorDisplay),
+         scale(100),
+         angle(0)
+{}
+
+
+bool operator==(Params const & a, Params const & b)
+{
+       return (a.filename == b.filename &&
+               a.display == b.display &&
+               a.bb == b.bb &&
+               a.scale == b.scale &&
+               a.angle == b.angle);
+}
+
+
+bool operator!=(Params const & a, Params const & b)
+{
+       return !(a == b);
+}
+
+
+std::ostream & operator<<(std::ostream & os, BoundingBox const & bb)
+{
+       os << bb.xl << ' ' << bb.yb << ' ' << bb.xr << ' ' << bb.yt;
+       return os;
+}
+
+
+BoundingBox::BoundingBox()
+       : xl(0), yb(0), xr(0), yt(0)
+{}
+
+
+BoundingBox::BoundingBox(string const & bb)
+       : xl(0), yb(0), xr(0), yt(0)
+{
+       if (bb.empty())
+               return;
+
+       std::istringstream is(bb.c_str());
+       string a, b, c, d;
+       is >> a >> b >> c >> d;
+
+       // inBP returns the length in Postscript points.
+       // Note further that there are 72 Postscript pixels per inch.
+       unsigned int const xl_tmp = abs(LyXLength(a).inBP());
+       unsigned int const yb_tmp = abs(LyXLength(b).inBP());
+       unsigned int const xr_tmp = abs(LyXLength(c).inBP());
+       unsigned int const yt_tmp = abs(LyXLength(d).inBP());
+
+       if (xr_tmp <= xl_tmp || yt_tmp <= yb_tmp)
+               return;
+
+       xl = xl_tmp;
+       yb = yb_tmp;
+       xr = xr_tmp;
+       yt = yt_tmp;
+}
+
+
+bool BoundingBox::empty() const
+{
+       return (!xl && !yb && !xr && !yt);
+}
+
+
+bool operator==(BoundingBox const & a, BoundingBox const & b)
+{
+       return (a.xl == b.xl &&
+               a.yb == b.yb &&
+               a.xr == b.xr &&
+               a.yt == b.yt);
+}
+
+
+bool operator!=(BoundingBox const & a, BoundingBox const & b)
+{
+       return !(a == b);
+}
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/graphics/GraphicsTypes.C b/src/graphics/GraphicsTypes.C
deleted file mode 100644 (file)
index f8f6f45..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * \file GraphicsTypes.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Rob Lahaye
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "graphics/GraphicsTypes.h"
-
-#include <string>
-
-using std::string;
-
-
-namespace lyx {
-namespace graphics {
-
-namespace {
-
-/// The translator between the Display enum and corresponding lyx string.
-Translator<DisplayType, string> const initTranslator()
-{
-       Translator<DisplayType, string> translator(DefaultDisplay, "default");
-
-       // Fill the display translator
-       translator.addPair(MonochromeDisplay, "monochrome");
-       translator.addPair(GrayscaleDisplay, "grayscale");
-       translator.addPair(ColorDisplay, "color");
-       translator.addPair(NoDisplay, "none");
-
-       return translator;
-}
-
-} // namespace anon
-
-Translator<DisplayType, string> const & displayTranslator()
-{
-       static Translator<DisplayType, string> const translator =
-               initTranslator();
-       return translator;
-}
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/GraphicsTypes.cpp b/src/graphics/GraphicsTypes.cpp
new file mode 100644 (file)
index 0000000..f8f6f45
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * \file GraphicsTypes.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Rob Lahaye
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "graphics/GraphicsTypes.h"
+
+#include <string>
+
+using std::string;
+
+
+namespace lyx {
+namespace graphics {
+
+namespace {
+
+/// The translator between the Display enum and corresponding lyx string.
+Translator<DisplayType, string> const initTranslator()
+{
+       Translator<DisplayType, string> translator(DefaultDisplay, "default");
+
+       // Fill the display translator
+       translator.addPair(MonochromeDisplay, "monochrome");
+       translator.addPair(GrayscaleDisplay, "grayscale");
+       translator.addPair(ColorDisplay, "color");
+       translator.addPair(NoDisplay, "none");
+
+       return translator;
+}
+
+} // namespace anon
+
+Translator<DisplayType, string> const & displayTranslator()
+{
+       static Translator<DisplayType, string> const translator =
+               initTranslator();
+       return translator;
+}
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/graphics/LoaderQueue.C b/src/graphics/LoaderQueue.C
deleted file mode 100644 (file)
index 6038dbe..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * \file LoaderQueue.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alfredo Braunstein
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "LoaderQueue.h"
-#include "GraphicsCacheItem.h"
-
-#include "debug.h"
-
-#include <boost/bind.hpp>
-
-using std::endl;
-using std::list;
-
-namespace lyx {
-namespace graphics {
-
-int LoaderQueue::s_numimages_ = 5;
-int LoaderQueue::s_millisecs_ = 500;
-
-
-LoaderQueue & LoaderQueue::get()
-{
-       static LoaderQueue singleton;
-       return singleton;
-}
-
-
-void LoaderQueue::loadNext()
-{
-       LYXERR(Debug::GRAPHICS) << "LoaderQueue: "
-                               << cache_queue_.size()
-                               << " items in the queue" << endl;
-       int counter = s_numimages_;
-       while (cache_queue_.size() && counter--) {
-               Cache::ItemPtr ptr = cache_queue_.front();
-               cache_set_.erase(ptr);
-               cache_queue_.pop_front();
-               if (ptr->status() == WaitingToLoad)
-                       ptr->startLoading();
-       }
-       if (cache_queue_.size()) {
-               startLoader();
-       } else {
-               stopLoader();
-       }
-}
-
-
-void LoaderQueue::setPriority(int numimages , int millisecs)
-{
-       s_numimages_ = numimages;
-       s_millisecs_ = millisecs;
-       LYXERR(Debug::GRAPHICS) << "LoaderQueue:  priority set to "
-                               << s_numimages_ << " images at a time, "
-                               << s_millisecs_ << " milliseconds between calls"
-                               << endl;
-}
-
-
-LoaderQueue::LoaderQueue() : timer(s_millisecs_, Timeout::ONETIME),
-                            running_(false)
-{
-       timer.timeout.connect(boost::bind(&LoaderQueue::loadNext, this));
-}
-
-
-void LoaderQueue::startLoader()
-{
-       LYXERR(Debug::GRAPHICS) << "LoaderQueue: waking up" << endl;
-       running_ = true ;
-       timer.setTimeout(s_millisecs_);
-       timer.start();
-}
-
-
-void LoaderQueue::stopLoader()
-{
-       timer.stop();
-       running_ = false ;
-       LYXERR(Debug::GRAPHICS) << "LoaderQueue: I'm going to sleep" << endl;
-}
-
-
-bool LoaderQueue::running() const
-{
-       return running_ ;
-}
-
-
-void LoaderQueue::touch(Cache::ItemPtr const & item)
-{
-       if (! cache_set_.insert(item).second) {
-               list<Cache::ItemPtr>::iterator
-                       it = cache_queue_.begin();
-               list<Cache::ItemPtr>::iterator
-                       end = cache_queue_.end();
-
-               it = std::find(it, end, item);
-               if (it != end)
-                       cache_queue_.erase(it);
-       }
-       cache_queue_.push_front(item);
-       if (!running_)
-               startLoader();
-}
-
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/LoaderQueue.cpp b/src/graphics/LoaderQueue.cpp
new file mode 100644 (file)
index 0000000..6038dbe
--- /dev/null
@@ -0,0 +1,118 @@
+/**
+ * \file LoaderQueue.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alfredo Braunstein
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "LoaderQueue.h"
+#include "GraphicsCacheItem.h"
+
+#include "debug.h"
+
+#include <boost/bind.hpp>
+
+using std::endl;
+using std::list;
+
+namespace lyx {
+namespace graphics {
+
+int LoaderQueue::s_numimages_ = 5;
+int LoaderQueue::s_millisecs_ = 500;
+
+
+LoaderQueue & LoaderQueue::get()
+{
+       static LoaderQueue singleton;
+       return singleton;
+}
+
+
+void LoaderQueue::loadNext()
+{
+       LYXERR(Debug::GRAPHICS) << "LoaderQueue: "
+                               << cache_queue_.size()
+                               << " items in the queue" << endl;
+       int counter = s_numimages_;
+       while (cache_queue_.size() && counter--) {
+               Cache::ItemPtr ptr = cache_queue_.front();
+               cache_set_.erase(ptr);
+               cache_queue_.pop_front();
+               if (ptr->status() == WaitingToLoad)
+                       ptr->startLoading();
+       }
+       if (cache_queue_.size()) {
+               startLoader();
+       } else {
+               stopLoader();
+       }
+}
+
+
+void LoaderQueue::setPriority(int numimages , int millisecs)
+{
+       s_numimages_ = numimages;
+       s_millisecs_ = millisecs;
+       LYXERR(Debug::GRAPHICS) << "LoaderQueue:  priority set to "
+                               << s_numimages_ << " images at a time, "
+                               << s_millisecs_ << " milliseconds between calls"
+                               << endl;
+}
+
+
+LoaderQueue::LoaderQueue() : timer(s_millisecs_, Timeout::ONETIME),
+                            running_(false)
+{
+       timer.timeout.connect(boost::bind(&LoaderQueue::loadNext, this));
+}
+
+
+void LoaderQueue::startLoader()
+{
+       LYXERR(Debug::GRAPHICS) << "LoaderQueue: waking up" << endl;
+       running_ = true ;
+       timer.setTimeout(s_millisecs_);
+       timer.start();
+}
+
+
+void LoaderQueue::stopLoader()
+{
+       timer.stop();
+       running_ = false ;
+       LYXERR(Debug::GRAPHICS) << "LoaderQueue: I'm going to sleep" << endl;
+}
+
+
+bool LoaderQueue::running() const
+{
+       return running_ ;
+}
+
+
+void LoaderQueue::touch(Cache::ItemPtr const & item)
+{
+       if (! cache_set_.insert(item).second) {
+               list<Cache::ItemPtr>::iterator
+                       it = cache_queue_.begin();
+               list<Cache::ItemPtr>::iterator
+                       end = cache_queue_.end();
+
+               it = std::find(it, end, item);
+               if (it != end)
+                       cache_queue_.erase(it);
+       }
+       cache_queue_.push_front(item);
+       if (!running_)
+               startLoader();
+}
+
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/graphics/PreviewImage.C b/src/graphics/PreviewImage.C
deleted file mode 100644 (file)
index 89289e2..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/**
- * \file PreviewImage.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "PreviewImage.h"
-#include "GraphicsImage.h"
-#include "GraphicsLoader.h"
-#include "PreviewLoader.h"
-
-#include "support/filename.h"
-#include "support/lyxlib.h"
-
-#include <boost/bind.hpp>
-
-using std::string;
-
-
-namespace lyx {
-
-using support::FileName;
-
-namespace graphics {
-
-class PreviewImage::Impl : public boost::signals::trackable {
-public:
-       ///
-       Impl(PreviewImage & p, PreviewLoader & l,
-            string const & s, FileName const & f, double af);
-       ///
-       ~Impl();
-       ///
-       Image const * image();
-       ///
-       void statusChanged();
-
-       ///
-       PreviewImage const & parent_;
-       ///
-       PreviewLoader & ploader_;
-       ///
-       Loader iloader_;
-       ///
-       string const snippet_;
-       ///
-       double const ascent_frac_;
-};
-
-
-PreviewImage::PreviewImage(PreviewLoader & l,
-                          string const & s,
-                          FileName const & f,
-                          double af)
-       : pimpl_(new Impl(*this, l, s, f, af))
-{}
-
-
-PreviewImage::~PreviewImage()
-{}
-
-
-string const & PreviewImage::snippet() const
-{
-       return pimpl_->snippet_;
-}
-
-
-int PreviewImage::ascent() const
-{
-       Image const * const image = pimpl_->iloader_.image();
-       if (!image)
-               return 0;
-
-       return int(pimpl_->ascent_frac_ * double(image->getHeight()));
-}
-
-
-int PreviewImage::descent() const
-{
-       Image const * const image = pimpl_->iloader_.image();
-       if (!image)
-               return 0;
-
-       // Avoids rounding errors.
-       return image->getHeight() - ascent();
-}
-
-
-int PreviewImage::width() const
-{
-       Image const * const image = pimpl_->iloader_.image();
-       return image ? image->getWidth() : 0;
-}
-
-
-Image const * PreviewImage::image() const
-{
-       return pimpl_->image();
-}
-
-
-PreviewImage::Impl::Impl(PreviewImage & p, PreviewLoader & l,
-                        string const & s,
-                        FileName const & bf,
-                        double af)
-       : parent_(p), ploader_(l), iloader_(bf),
-         snippet_(s), ascent_frac_(af)
-{
-       iloader_.connect(boost::bind(&Impl::statusChanged, this));
-}
-
-
-PreviewImage::Impl::~Impl()
-{
-       support::unlink(iloader_.filename());
-}
-
-
-Image const * PreviewImage::Impl::image()
-{
-       if (iloader_.status() == WaitingToLoad)
-               iloader_.startLoading();
-
-       return iloader_.image();
-}
-
-
-void PreviewImage::Impl::statusChanged()
-{
-       switch (iloader_.status()) {
-       case WaitingToLoad:
-       case Loading:
-       case Converting:
-       case Loaded:
-       case ScalingEtc:
-               break;
-
-       case ErrorNoFile:
-       case ErrorConverting:
-       case ErrorLoading:
-       case ErrorGeneratingPixmap:
-       case ErrorUnknown:
-               //lyx::unlink(iloader_.filename());
-               ploader_.remove(snippet_);
-               break;
-
-       case Ready:
-               support::unlink(iloader_.filename());
-               break;
-       }
-       ploader_.emitSignal(parent_);
-}
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/PreviewImage.cpp b/src/graphics/PreviewImage.cpp
new file mode 100644 (file)
index 0000000..89289e2
--- /dev/null
@@ -0,0 +1,162 @@
+/**
+ * \file PreviewImage.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "PreviewImage.h"
+#include "GraphicsImage.h"
+#include "GraphicsLoader.h"
+#include "PreviewLoader.h"
+
+#include "support/filename.h"
+#include "support/lyxlib.h"
+
+#include <boost/bind.hpp>
+
+using std::string;
+
+
+namespace lyx {
+
+using support::FileName;
+
+namespace graphics {
+
+class PreviewImage::Impl : public boost::signals::trackable {
+public:
+       ///
+       Impl(PreviewImage & p, PreviewLoader & l,
+            string const & s, FileName const & f, double af);
+       ///
+       ~Impl();
+       ///
+       Image const * image();
+       ///
+       void statusChanged();
+
+       ///
+       PreviewImage const & parent_;
+       ///
+       PreviewLoader & ploader_;
+       ///
+       Loader iloader_;
+       ///
+       string const snippet_;
+       ///
+       double const ascent_frac_;
+};
+
+
+PreviewImage::PreviewImage(PreviewLoader & l,
+                          string const & s,
+                          FileName const & f,
+                          double af)
+       : pimpl_(new Impl(*this, l, s, f, af))
+{}
+
+
+PreviewImage::~PreviewImage()
+{}
+
+
+string const & PreviewImage::snippet() const
+{
+       return pimpl_->snippet_;
+}
+
+
+int PreviewImage::ascent() const
+{
+       Image const * const image = pimpl_->iloader_.image();
+       if (!image)
+               return 0;
+
+       return int(pimpl_->ascent_frac_ * double(image->getHeight()));
+}
+
+
+int PreviewImage::descent() const
+{
+       Image const * const image = pimpl_->iloader_.image();
+       if (!image)
+               return 0;
+
+       // Avoids rounding errors.
+       return image->getHeight() - ascent();
+}
+
+
+int PreviewImage::width() const
+{
+       Image const * const image = pimpl_->iloader_.image();
+       return image ? image->getWidth() : 0;
+}
+
+
+Image const * PreviewImage::image() const
+{
+       return pimpl_->image();
+}
+
+
+PreviewImage::Impl::Impl(PreviewImage & p, PreviewLoader & l,
+                        string const & s,
+                        FileName const & bf,
+                        double af)
+       : parent_(p), ploader_(l), iloader_(bf),
+         snippet_(s), ascent_frac_(af)
+{
+       iloader_.connect(boost::bind(&Impl::statusChanged, this));
+}
+
+
+PreviewImage::Impl::~Impl()
+{
+       support::unlink(iloader_.filename());
+}
+
+
+Image const * PreviewImage::Impl::image()
+{
+       if (iloader_.status() == WaitingToLoad)
+               iloader_.startLoading();
+
+       return iloader_.image();
+}
+
+
+void PreviewImage::Impl::statusChanged()
+{
+       switch (iloader_.status()) {
+       case WaitingToLoad:
+       case Loading:
+       case Converting:
+       case Loaded:
+       case ScalingEtc:
+               break;
+
+       case ErrorNoFile:
+       case ErrorConverting:
+       case ErrorLoading:
+       case ErrorGeneratingPixmap:
+       case ErrorUnknown:
+               //lyx::unlink(iloader_.filename());
+               ploader_.remove(snippet_);
+               break;
+
+       case Ready:
+               support::unlink(iloader_.filename());
+               break;
+       }
+       ploader_.emitSignal(parent_);
+}
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/graphics/PreviewLoader.C b/src/graphics/PreviewLoader.C
deleted file mode 100644 (file)
index 4c32c76..0000000
+++ /dev/null
@@ -1,745 +0,0 @@
-/**
- * \file PreviewLoader.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "PreviewLoader.h"
-#include "PreviewImage.h"
-#include "GraphicsCache.h"
-
-#include "buffer.h"
-#include "converter.h"
-#include "debug.h"
-#include "format.h"
-#include "insetiterator.h"
-#include "LColor.h"
-#include "lyxrc.h"
-#include "outputparams.h"
-#include "paragraph.h"
-
-#include "frontends/Application.h" // hexName
-
-#include "insets/Inset.h"
-
-#include "support/filetools.h"
-#include "support/forkedcall.h"
-#include "support/forkedcontr.h"
-#include "support/lstrings.h"
-#include "support/lyxlib.h"
-#include "support/convert.h"
-
-#include <boost/bind.hpp>
-
-#include <sstream>
-#include <fstream>
-#include <iomanip>
-
-using lyx::support::FileName;
-
-using std::endl;
-using std::find;
-using std::fill;
-using std::find_if;
-using std::make_pair;
-
-using boost::bind;
-
-using std::ifstream;
-using std::list;
-using std::map;
-using std::ostringstream;
-using std::pair;
-using std::vector;
-using std::string;
-
-
-namespace {
-
-typedef pair<string, FileName> SnippetPair;
-
-// A list of all snippets to be converted to previews
-typedef list<string> PendingSnippets;
-
-// Each item in the vector is a pair<snippet, image file name>.
-typedef vector<SnippetPair> BitmapFile;
-
-
-string const unique_filename(string const & bufferpath)
-{
-       static int theCounter = 0;
-       string const filename = lyx::convert<string>(theCounter++) + "lyxpreview";
-       return lyx::support::addName(bufferpath, filename);
-}
-
-
-lyx::Converter const * setConverter()
-{
-       string const from = "lyxpreview";
-
-       typedef vector<string> FmtList;
-       typedef lyx::graphics::Cache GCache;
-       FmtList const loadableFormats = GCache::get().loadableFormats();
-       FmtList::const_iterator it = loadableFormats.begin();
-       FmtList::const_iterator const end = loadableFormats.end();
-
-       for (; it != end; ++it) {
-               string const to = *it;
-               if (from == to)
-                       continue;
-
-               lyx::Converter const * ptr = lyx::theConverters().getConverter(from, to);
-               if (ptr)
-                       return ptr;
-       }
-
-       static bool first = true;
-       if (first) {
-               first = false;
-               lyx::lyxerr << "PreviewLoader::startLoading()\n"
-                      << "No converter from \"lyxpreview\" format has been "
-                       "defined."
-                      << endl;
-       }
-       return 0;
-}
-
-
-void setAscentFractions(vector<double> & ascent_fractions,
-                       FileName const & metrics_file)
-{
-       // If all else fails, then the images will have equal ascents and
-       // descents.
-       vector<double>::iterator it  = ascent_fractions.begin();
-       vector<double>::iterator end = ascent_fractions.end();
-       fill(it, end, 0.5);
-
-       ifstream in(metrics_file.toFilesystemEncoding().c_str());
-       if (!in.good()) {
-               lyx::lyxerr[lyx::Debug::GRAPHICS]
-                       << "setAscentFractions(" << metrics_file << ")\n"
-                       << "Unable to open file!" << endl;
-               return;
-       }
-
-       bool error = false;
-
-       int snippet_counter = 1;
-       while (!in.eof() && it != end) {
-               string snippet;
-               int id;
-               double ascent_fraction;
-
-               in >> snippet >> id >> ascent_fraction;
-
-               if (!in.good())
-                       // eof after all
-                       break;
-
-               error = snippet != "Snippet";
-               if (error)
-                       break;
-
-               error = id != snippet_counter;
-               if (error)
-                       break;
-
-               *it = ascent_fraction;
-
-               ++snippet_counter;
-               ++it;
-       }
-
-       if (error) {
-               lyx::lyxerr[lyx::Debug::GRAPHICS]
-                       << "setAscentFractions(" << metrics_file << ")\n"
-                       << "Error reading file!\n" << endl;
-       }
-}
-
-
-class FindFirst : public std::unary_function<SnippetPair, bool> {
-public:
-       FindFirst(string const & comp) : comp_(comp) {}
-       bool operator()(SnippetPair const & sp) const
-       {
-               return sp.first == comp_;
-       }
-private:
-       string const comp_;
-};
-
-
-/// Store info on a currently executing, forked process.
-class InProgress {
-public:
-       ///
-       InProgress() : pid(0) {}
-       ///
-       InProgress(string const & filename_base,
-                  PendingSnippets const & pending,
-                  string const & to_format);
-       /// Remove any files left lying around and kill the forked process.
-       void stop() const;
-
-       ///
-       pid_t pid;
-       ///
-       string command;
-       ///
-       FileName metrics_file;
-       ///
-       BitmapFile snippets;
-};
-
-typedef map<pid_t, InProgress>  InProgressProcesses;
-
-typedef InProgressProcesses::value_type InProgressProcess;
-
-} // namespace anon
-
-
-
-namespace lyx {
-
-namespace graphics {
-
-class PreviewLoader::Impl : public boost::signals::trackable {
-public:
-       ///
-       Impl(PreviewLoader & p, Buffer const & b);
-       /// Stop any InProgress items still executing.
-       ~Impl();
-       ///
-       PreviewImage const * preview(string const & latex_snippet) const;
-       ///
-       PreviewLoader::Status status(string const & latex_snippet) const;
-       ///
-       void add(string const & latex_snippet);
-       ///
-       void remove(string const & latex_snippet);
-       ///
-       void startLoading();
-
-       /// Emit this signal when an image is ready for display.
-       boost::signal<void(PreviewImage const &)> imageReady;
-
-       Buffer const & buffer() const { return buffer_; }
-
-private:
-       /// Called by the Forkedcall process that generated the bitmap files.
-       void finishedGenerating(pid_t, int);
-       ///
-       void dumpPreamble(odocstream &) const;
-       ///
-       void dumpData(odocstream &, BitmapFile const &) const;
-
-       /** cache_ allows easy retrieval of already-generated images
-        *  using the LaTeX snippet as the identifier.
-        */
-       typedef boost::shared_ptr<PreviewImage> PreviewImagePtr;
-       ///
-       typedef map<string, PreviewImagePtr> Cache;
-       ///
-       Cache cache_;
-
-       /** pending_ stores the LaTeX snippets in anticipation of them being
-        *  sent to the converter.
-        */
-       PendingSnippets pending_;
-
-       /** in_progress_ stores all forked processes so that we can proceed
-        *  thereafter.
-           The map uses the conversion commands as its identifiers.
-        */
-       InProgressProcesses in_progress_;
-
-       ///
-       PreviewLoader & parent_;
-       ///
-       Buffer const & buffer_;
-       ///
-       double font_scaling_factor_;
-
-       /// We don't own this
-       static lyx::Converter const * pconverter_;
-};
-
-
-lyx::Converter const * PreviewLoader::Impl::pconverter_;
-
-
-//
-// The public interface, defined in PreviewLoader.h
-//
-
-PreviewLoader::PreviewLoader(Buffer const & b)
-       : pimpl_(new Impl(*this, b))
-{}
-
-
-PreviewLoader::~PreviewLoader()
-{}
-
-
-PreviewImage const * PreviewLoader::preview(string const & latex_snippet) const
-{
-       return pimpl_->preview(latex_snippet);
-}
-
-
-PreviewLoader::Status PreviewLoader::status(string const & latex_snippet) const
-{
-       return pimpl_->status(latex_snippet);
-}
-
-
-void PreviewLoader::add(string const & latex_snippet) const
-{
-       pimpl_->add(latex_snippet);
-}
-
-
-void PreviewLoader::remove(string const & latex_snippet) const
-{
-       pimpl_->remove(latex_snippet);
-}
-
-
-void PreviewLoader::startLoading() const
-{
-       pimpl_->startLoading();
-}
-
-
-boost::signals::connection PreviewLoader::connect(slot_type const & slot) const
-{
-       return pimpl_->imageReady.connect(slot);
-}
-
-
-void PreviewLoader::emitSignal(PreviewImage const & pimage) const
-{
-       pimpl_->imageReady(pimage);
-}
-
-
-Buffer const & PreviewLoader::buffer() const
-{
-       return pimpl_->buffer();
-}
-
-} // namespace graphics
-} // namespace lyx
-
-
-// The details of the Impl
-// =======================
-
-namespace {
-
-class IncrementedFileName {
-public:
-       IncrementedFileName(string const & to_format,
-                           string const & filename_base)
-               : to_format_(to_format), base_(filename_base), counter_(1)
-       {}
-
-       SnippetPair const operator()(string const & snippet)
-       {
-               ostringstream os;
-               os << base_ << counter_++ << '.' << to_format_;
-               string const file = os.str();
-
-               return make_pair(snippet, FileName(file));
-       }
-
-private:
-       string const & to_format_;
-       string const & base_;
-       int counter_;
-};
-
-
-InProgress::InProgress(string const & filename_base,
-                      PendingSnippets const & pending,
-                      string const & to_format)
-       : pid(0),
-         metrics_file(FileName(filename_base + ".metrics")),
-         snippets(pending.size())
-{
-       PendingSnippets::const_iterator pit  = pending.begin();
-       PendingSnippets::const_iterator pend = pending.end();
-       BitmapFile::iterator sit = snippets.begin();
-
-       std::transform(pit, pend, sit,
-                      IncrementedFileName(to_format, filename_base));
-}
-
-
-void InProgress::stop() const
-{
-       if (pid)
-               lyx::support::ForkedcallsController::get().kill(pid, 0);
-
-       if (!metrics_file.empty())
-               lyx::support::unlink(metrics_file);
-
-       BitmapFile::const_iterator vit  = snippets.begin();
-       BitmapFile::const_iterator vend = snippets.end();
-       for (; vit != vend; ++vit) {
-               if (!vit->second.empty())
-                       lyx::support::unlink(vit->second);
-       }
-}
-
-} // namespace anon
-
-
-namespace lyx {
-namespace graphics {
-
-PreviewLoader::Impl::Impl(PreviewLoader & p, Buffer const & b)
-       : parent_(p), buffer_(b), font_scaling_factor_(0.0)
-{
-       font_scaling_factor_ = 0.01 * lyxrc.dpi * lyxrc.zoom *
-               convert<double>(lyxrc.preview_scale_factor);
-
-       LYXERR(Debug::GRAPHICS) << "The font scaling factor is "
-                               << font_scaling_factor_ << endl;
-
-       if (!pconverter_)
-               pconverter_ = setConverter();
-}
-
-
-PreviewLoader::Impl::~Impl()
-{
-       InProgressProcesses::iterator ipit  = in_progress_.begin();
-       InProgressProcesses::iterator ipend = in_progress_.end();
-
-       for (; ipit != ipend; ++ipit) {
-               ipit->second.stop();
-       }
-}
-
-
-PreviewImage const *
-PreviewLoader::Impl::preview(string const & latex_snippet) const
-{
-       Cache::const_iterator it = cache_.find(latex_snippet);
-       return (it == cache_.end()) ? 0 : it->second.get();
-}
-
-
-namespace {
-
-class FindSnippet : public std::unary_function<InProgressProcess, bool> {
-public:
-       FindSnippet(string const & s) : snippet_(s) {}
-       bool operator()(InProgressProcess const & process) const
-       {
-               BitmapFile const & snippets = process.second.snippets;
-               BitmapFile::const_iterator beg  = snippets.begin();
-               BitmapFile::const_iterator end = snippets.end();
-               return find_if(beg, end, FindFirst(snippet_)) != end;
-       }
-
-private:
-       string const snippet_;
-};
-
-} // namespace anon
-
-PreviewLoader::Status
-PreviewLoader::Impl::status(string const & latex_snippet) const
-{
-       Cache::const_iterator cit = cache_.find(latex_snippet);
-       if (cit != cache_.end())
-               return Ready;
-
-       PendingSnippets::const_iterator pit  = pending_.begin();
-       PendingSnippets::const_iterator pend = pending_.end();
-
-       pit = find(pit, pend, latex_snippet);
-       if (pit != pend)
-               return InQueue;
-
-       InProgressProcesses::const_iterator ipit  = in_progress_.begin();
-       InProgressProcesses::const_iterator ipend = in_progress_.end();
-
-       ipit = find_if(ipit, ipend, FindSnippet(latex_snippet));
-       if (ipit != ipend)
-               return Processing;
-
-       return NotFound;
-}
-
-
-void PreviewLoader::Impl::add(string const & latex_snippet)
-{
-       if (!pconverter_ || status(latex_snippet) != NotFound)
-               return;
-
-       string const snippet = support::trim(latex_snippet);
-       if (snippet.empty())
-               return;
-
-       LYXERR(Debug::GRAPHICS) << "adding snippet:\n" << snippet << endl;
-
-       pending_.push_back(snippet);
-}
-
-
-namespace {
-
-class EraseSnippet {
-public:
-       EraseSnippet(string const & s) : snippet_(s) {}
-       void operator()(InProgressProcess & process)
-       {
-               BitmapFile & snippets = process.second.snippets;
-               BitmapFile::iterator it  = snippets.begin();
-               BitmapFile::iterator end = snippets.end();
-
-               it = find_if(it, end, FindFirst(snippet_));
-               if (it != end)
-                       snippets.erase(it, it+1);
-       }
-
-private:
-       string const & snippet_;
-};
-
-} // namespace anon
-
-
-void PreviewLoader::Impl::remove(string const & latex_snippet)
-{
-       Cache::iterator cit = cache_.find(latex_snippet);
-       if (cit != cache_.end())
-               cache_.erase(cit);
-
-       PendingSnippets::iterator pit  = pending_.begin();
-       PendingSnippets::iterator pend = pending_.end();
-
-       pending_.erase(std::remove(pit, pend, latex_snippet), pend);
-
-       InProgressProcesses::iterator ipit  = in_progress_.begin();
-       InProgressProcesses::iterator ipend = in_progress_.end();
-
-       std::for_each(ipit, ipend, EraseSnippet(latex_snippet));
-
-       while (ipit != ipend) {
-               InProgressProcesses::iterator curr = ipit++;
-               if (curr->second.snippets.empty())
-                       in_progress_.erase(curr);
-       }
-}
-
-
-void PreviewLoader::Impl::startLoading()
-{
-       if (pending_.empty() || !pconverter_)
-               return;
-
-       // Only start the process off after the buffer is loaded from file.
-       if (!buffer_.fully_loaded())
-               return;
-
-       LYXERR(Debug::GRAPHICS) << "PreviewLoader::startLoading()" << endl;
-
-       // As used by the LaTeX file and by the resulting image files
-       string const directory = buffer_.temppath();
-
-       string const filename_base = unique_filename(directory);
-
-       // Create an InProgress instance to place in the map of all
-       // such processes if it starts correctly.
-       InProgress inprogress(filename_base, pending_, pconverter_->to);
-
-       // clear pending_, so we're ready to start afresh.
-       pending_.clear();
-
-       // Output the LaTeX file.
-       FileName const latexfile(filename_base + ".tex");
-
-       // FIXME UNICODE
-       // This creates an utf8 encoded file, but the proper inputenc
-       // command is missing.
-       odocfstream of(latexfile.toFilesystemEncoding().c_str());
-       if (!of) {
-               LYXERR(Debug::GRAPHICS) << "PreviewLoader::startLoading()\n"
-                                       << "Unable to create LaTeX file\n"
-                                       << latexfile << endl;
-               return;
-       }
-       of << "\\batchmode\n";
-       dumpPreamble(of);
-       of << "\n\\begin{document}\n";
-       dumpData(of, inprogress.snippets);
-       of << "\n\\end{document}\n";
-       of.close();
-
-       // The conversion command.
-       ostringstream cs;
-       cs << pconverter_->command << ' ' << pconverter_->to << ' '
-          << support::quoteName(latexfile.toFilesystemEncoding()) << ' '
-          << int(font_scaling_factor_) << ' '
-          << theApp()->hexName(LColor::preview) << ' '
-          << theApp()->hexName(LColor::background);
-
-       string const command = support::libScriptSearch(cs.str());
-
-       // Initiate the conversion from LaTeX to bitmap images files.
-       support::Forkedcall::SignalTypePtr
-               convert_ptr(new support::Forkedcall::SignalType);
-       convert_ptr->connect(bind(&Impl::finishedGenerating, this, _1, _2));
-
-       support::Forkedcall call;
-       int ret = call.startscript(command, convert_ptr);
-
-       if (ret != 0) {
-               LYXERR(Debug::GRAPHICS) << "PreviewLoader::startLoading()\n"
-                                       << "Unable to start process\n"
-                                       << command << endl;
-               return;
-       }
-
-       // Store the generation process in a list of all such processes
-       inprogress.pid = call.pid();
-       inprogress.command = command;
-       in_progress_[inprogress.pid] = inprogress;
-}
-
-
-void PreviewLoader::Impl::finishedGenerating(pid_t pid, int retval)
-{
-       // Paranoia check!
-       InProgressProcesses::iterator git = in_progress_.find(pid);
-       if (git == in_progress_.end()) {
-               lyxerr << "PreviewLoader::finishedGenerating(): unable to find "
-                       "data for PID " << pid << endl;
-               return;
-       }
-
-       string const command = git->second.command;
-       string const status = retval > 0 ? "failed" : "succeeded";
-       LYXERR(Debug::GRAPHICS) << "PreviewLoader::finishedInProgress("
-                               << retval << "): processing " << status
-                               << " for " << command << endl;
-       if (retval > 0)
-               return;
-
-       // Read the metrics file, if it exists
-       vector<double> ascent_fractions(git->second.snippets.size());
-       setAscentFractions(ascent_fractions, git->second.metrics_file);
-
-       // Add these newly generated bitmap files to the cache and
-       // start loading them into LyX.
-       BitmapFile::const_iterator it  = git->second.snippets.begin();
-       BitmapFile::const_iterator end = git->second.snippets.end();
-
-       std::list<PreviewImagePtr> newimages;
-
-       int metrics_counter = 0;
-       for (; it != end; ++it, ++metrics_counter) {
-               string const & snip = it->first;
-               FileName const & file = it->second;
-               double af = ascent_fractions[metrics_counter];
-
-               PreviewImagePtr ptr(new PreviewImage(parent_, snip, file, af));
-               cache_[snip] = ptr;
-
-               newimages.push_back(ptr);
-       }
-
-       // Remove the item from the list of still-executing processes.
-       in_progress_.erase(git);
-
-       // Tell the outside world
-       std::list<PreviewImagePtr>::const_reverse_iterator
-               nit  = newimages.rbegin();
-       std::list<PreviewImagePtr>::const_reverse_iterator
-               nend = newimages.rend();
-       for (; nit != nend; ++nit) {
-               imageReady(*nit->get());
-       }
-}
-
-
-void PreviewLoader::Impl::dumpPreamble(odocstream & os) const
-{
-       // Why on earth is Buffer::makeLaTeXFile a non-const method?
-       Buffer & tmp = const_cast<Buffer &>(buffer_);
-       // Dump the preamble only.
-       // We don't need an encoding for runparams since it is not used by
-       // the preamble.
-       OutputParams runparams(0);
-       runparams.flavor = OutputParams::LATEX;
-       runparams.nice = true;
-       runparams.moving_arg = true;
-       runparams.free_spacing = true;
-       tmp.writeLaTeXSource(os, buffer_.filePath(), runparams, true, false);
-
-       // FIXME! This is a HACK! The proper fix is to control the 'true'
-       // passed to WriteStream below:
-       // int InsetMathNest::latex(Buffer const &, odocstream & os,
-       //                          OutputParams const & runparams) const
-       // {
-       //      WriteStream wi(os, runparams.moving_arg, true);
-       //      par_->write(wi);
-       //      return wi.line();
-       // }
-       os << "\n"
-          << "\\def\\lyxlock{}\n"
-          << "\n";
-
-       // Loop over the insets in the buffer and dump all the math-macros.
-       InsetBase & inset = buffer_.inset();
-       InsetIterator it = inset_iterator_begin(inset);
-       InsetIterator const end = inset_iterator_end(inset);
-
-       for (; it != end; ++it)
-               if (it->lyxCode() == InsetBase::MATHMACRO_CODE)
-                       it->latex(buffer_, os, runparams);
-
-       // All equation labels appear as "(#)" + preview.sty's rendering of
-       // the label name
-       if (lyxrc.preview_hashed_labels)
-               os << "\\renewcommand{\\theequation}{\\#}\n";
-
-       // Use the preview style file to ensure that each snippet appears on a
-       // fresh page.
-       os << "\n"
-          << "\\usepackage[active,delayed,dvips,showlabels,lyx]{preview}\n"
-          << "\n";
-}
-
-
-void PreviewLoader::Impl::dumpData(odocstream & os,
-                                  BitmapFile const & vec) const
-{
-       if (vec.empty())
-               return;
-
-       BitmapFile::const_iterator it  = vec.begin();
-       BitmapFile::const_iterator end = vec.end();
-
-       for (; it != end; ++it) {
-               // FIXME UNICODE
-               os << "\\begin{preview}\n"
-                  << from_utf8(it->first)
-                  << "\n\\end{preview}\n\n";
-       }
-}
-
-} // namespace graphics
-} // namespace lyx
-
diff --git a/src/graphics/PreviewLoader.cpp b/src/graphics/PreviewLoader.cpp
new file mode 100644 (file)
index 0000000..4c32c76
--- /dev/null
@@ -0,0 +1,745 @@
+/**
+ * \file PreviewLoader.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "PreviewLoader.h"
+#include "PreviewImage.h"
+#include "GraphicsCache.h"
+
+#include "buffer.h"
+#include "converter.h"
+#include "debug.h"
+#include "format.h"
+#include "insetiterator.h"
+#include "LColor.h"
+#include "lyxrc.h"
+#include "outputparams.h"
+#include "paragraph.h"
+
+#include "frontends/Application.h" // hexName
+
+#include "insets/Inset.h"
+
+#include "support/filetools.h"
+#include "support/forkedcall.h"
+#include "support/forkedcontr.h"
+#include "support/lstrings.h"
+#include "support/lyxlib.h"
+#include "support/convert.h"
+
+#include <boost/bind.hpp>
+
+#include <sstream>
+#include <fstream>
+#include <iomanip>
+
+using lyx::support::FileName;
+
+using std::endl;
+using std::find;
+using std::fill;
+using std::find_if;
+using std::make_pair;
+
+using boost::bind;
+
+using std::ifstream;
+using std::list;
+using std::map;
+using std::ostringstream;
+using std::pair;
+using std::vector;
+using std::string;
+
+
+namespace {
+
+typedef pair<string, FileName> SnippetPair;
+
+// A list of all snippets to be converted to previews
+typedef list<string> PendingSnippets;
+
+// Each item in the vector is a pair<snippet, image file name>.
+typedef vector<SnippetPair> BitmapFile;
+
+
+string const unique_filename(string const & bufferpath)
+{
+       static int theCounter = 0;
+       string const filename = lyx::convert<string>(theCounter++) + "lyxpreview";
+       return lyx::support::addName(bufferpath, filename);
+}
+
+
+lyx::Converter const * setConverter()
+{
+       string const from = "lyxpreview";
+
+       typedef vector<string> FmtList;
+       typedef lyx::graphics::Cache GCache;
+       FmtList const loadableFormats = GCache::get().loadableFormats();
+       FmtList::const_iterator it = loadableFormats.begin();
+       FmtList::const_iterator const end = loadableFormats.end();
+
+       for (; it != end; ++it) {
+               string const to = *it;
+               if (from == to)
+                       continue;
+
+               lyx::Converter const * ptr = lyx::theConverters().getConverter(from, to);
+               if (ptr)
+                       return ptr;
+       }
+
+       static bool first = true;
+       if (first) {
+               first = false;
+               lyx::lyxerr << "PreviewLoader::startLoading()\n"
+                      << "No converter from \"lyxpreview\" format has been "
+                       "defined."
+                      << endl;
+       }
+       return 0;
+}
+
+
+void setAscentFractions(vector<double> & ascent_fractions,
+                       FileName const & metrics_file)
+{
+       // If all else fails, then the images will have equal ascents and
+       // descents.
+       vector<double>::iterator it  = ascent_fractions.begin();
+       vector<double>::iterator end = ascent_fractions.end();
+       fill(it, end, 0.5);
+
+       ifstream in(metrics_file.toFilesystemEncoding().c_str());
+       if (!in.good()) {
+               lyx::lyxerr[lyx::Debug::GRAPHICS]
+                       << "setAscentFractions(" << metrics_file << ")\n"
+                       << "Unable to open file!" << endl;
+               return;
+       }
+
+       bool error = false;
+
+       int snippet_counter = 1;
+       while (!in.eof() && it != end) {
+               string snippet;
+               int id;
+               double ascent_fraction;
+
+               in >> snippet >> id >> ascent_fraction;
+
+               if (!in.good())
+                       // eof after all
+                       break;
+
+               error = snippet != "Snippet";
+               if (error)
+                       break;
+
+               error = id != snippet_counter;
+               if (error)
+                       break;
+
+               *it = ascent_fraction;
+
+               ++snippet_counter;
+               ++it;
+       }
+
+       if (error) {
+               lyx::lyxerr[lyx::Debug::GRAPHICS]
+                       << "setAscentFractions(" << metrics_file << ")\n"
+                       << "Error reading file!\n" << endl;
+       }
+}
+
+
+class FindFirst : public std::unary_function<SnippetPair, bool> {
+public:
+       FindFirst(string const & comp) : comp_(comp) {}
+       bool operator()(SnippetPair const & sp) const
+       {
+               return sp.first == comp_;
+       }
+private:
+       string const comp_;
+};
+
+
+/// Store info on a currently executing, forked process.
+class InProgress {
+public:
+       ///
+       InProgress() : pid(0) {}
+       ///
+       InProgress(string const & filename_base,
+                  PendingSnippets const & pending,
+                  string const & to_format);
+       /// Remove any files left lying around and kill the forked process.
+       void stop() const;
+
+       ///
+       pid_t pid;
+       ///
+       string command;
+       ///
+       FileName metrics_file;
+       ///
+       BitmapFile snippets;
+};
+
+typedef map<pid_t, InProgress>  InProgressProcesses;
+
+typedef InProgressProcesses::value_type InProgressProcess;
+
+} // namespace anon
+
+
+
+namespace lyx {
+
+namespace graphics {
+
+class PreviewLoader::Impl : public boost::signals::trackable {
+public:
+       ///
+       Impl(PreviewLoader & p, Buffer const & b);
+       /// Stop any InProgress items still executing.
+       ~Impl();
+       ///
+       PreviewImage const * preview(string const & latex_snippet) const;
+       ///
+       PreviewLoader::Status status(string const & latex_snippet) const;
+       ///
+       void add(string const & latex_snippet);
+       ///
+       void remove(string const & latex_snippet);
+       ///
+       void startLoading();
+
+       /// Emit this signal when an image is ready for display.
+       boost::signal<void(PreviewImage const &)> imageReady;
+
+       Buffer const & buffer() const { return buffer_; }
+
+private:
+       /// Called by the Forkedcall process that generated the bitmap files.
+       void finishedGenerating(pid_t, int);
+       ///
+       void dumpPreamble(odocstream &) const;
+       ///
+       void dumpData(odocstream &, BitmapFile const &) const;
+
+       /** cache_ allows easy retrieval of already-generated images
+        *  using the LaTeX snippet as the identifier.
+        */
+       typedef boost::shared_ptr<PreviewImage> PreviewImagePtr;
+       ///
+       typedef map<string, PreviewImagePtr> Cache;
+       ///
+       Cache cache_;
+
+       /** pending_ stores the LaTeX snippets in anticipation of them being
+        *  sent to the converter.
+        */
+       PendingSnippets pending_;
+
+       /** in_progress_ stores all forked processes so that we can proceed
+        *  thereafter.
+           The map uses the conversion commands as its identifiers.
+        */
+       InProgressProcesses in_progress_;
+
+       ///
+       PreviewLoader & parent_;
+       ///
+       Buffer const & buffer_;
+       ///
+       double font_scaling_factor_;
+
+       /// We don't own this
+       static lyx::Converter const * pconverter_;
+};
+
+
+lyx::Converter const * PreviewLoader::Impl::pconverter_;
+
+
+//
+// The public interface, defined in PreviewLoader.h
+//
+
+PreviewLoader::PreviewLoader(Buffer const & b)
+       : pimpl_(new Impl(*this, b))
+{}
+
+
+PreviewLoader::~PreviewLoader()
+{}
+
+
+PreviewImage const * PreviewLoader::preview(string const & latex_snippet) const
+{
+       return pimpl_->preview(latex_snippet);
+}
+
+
+PreviewLoader::Status PreviewLoader::status(string const & latex_snippet) const
+{
+       return pimpl_->status(latex_snippet);
+}
+
+
+void PreviewLoader::add(string const & latex_snippet) const
+{
+       pimpl_->add(latex_snippet);
+}
+
+
+void PreviewLoader::remove(string const & latex_snippet) const
+{
+       pimpl_->remove(latex_snippet);
+}
+
+
+void PreviewLoader::startLoading() const
+{
+       pimpl_->startLoading();
+}
+
+
+boost::signals::connection PreviewLoader::connect(slot_type const & slot) const
+{
+       return pimpl_->imageReady.connect(slot);
+}
+
+
+void PreviewLoader::emitSignal(PreviewImage const & pimage) const
+{
+       pimpl_->imageReady(pimage);
+}
+
+
+Buffer const & PreviewLoader::buffer() const
+{
+       return pimpl_->buffer();
+}
+
+} // namespace graphics
+} // namespace lyx
+
+
+// The details of the Impl
+// =======================
+
+namespace {
+
+class IncrementedFileName {
+public:
+       IncrementedFileName(string const & to_format,
+                           string const & filename_base)
+               : to_format_(to_format), base_(filename_base), counter_(1)
+       {}
+
+       SnippetPair const operator()(string const & snippet)
+       {
+               ostringstream os;
+               os << base_ << counter_++ << '.' << to_format_;
+               string const file = os.str();
+
+               return make_pair(snippet, FileName(file));
+       }
+
+private:
+       string const & to_format_;
+       string const & base_;
+       int counter_;
+};
+
+
+InProgress::InProgress(string const & filename_base,
+                      PendingSnippets const & pending,
+                      string const & to_format)
+       : pid(0),
+         metrics_file(FileName(filename_base + ".metrics")),
+         snippets(pending.size())
+{
+       PendingSnippets::const_iterator pit  = pending.begin();
+       PendingSnippets::const_iterator pend = pending.end();
+       BitmapFile::iterator sit = snippets.begin();
+
+       std::transform(pit, pend, sit,
+                      IncrementedFileName(to_format, filename_base));
+}
+
+
+void InProgress::stop() const
+{
+       if (pid)
+               lyx::support::ForkedcallsController::get().kill(pid, 0);
+
+       if (!metrics_file.empty())
+               lyx::support::unlink(metrics_file);
+
+       BitmapFile::const_iterator vit  = snippets.begin();
+       BitmapFile::const_iterator vend = snippets.end();
+       for (; vit != vend; ++vit) {
+               if (!vit->second.empty())
+                       lyx::support::unlink(vit->second);
+       }
+}
+
+} // namespace anon
+
+
+namespace lyx {
+namespace graphics {
+
+PreviewLoader::Impl::Impl(PreviewLoader & p, Buffer const & b)
+       : parent_(p), buffer_(b), font_scaling_factor_(0.0)
+{
+       font_scaling_factor_ = 0.01 * lyxrc.dpi * lyxrc.zoom *
+               convert<double>(lyxrc.preview_scale_factor);
+
+       LYXERR(Debug::GRAPHICS) << "The font scaling factor is "
+                               << font_scaling_factor_ << endl;
+
+       if (!pconverter_)
+               pconverter_ = setConverter();
+}
+
+
+PreviewLoader::Impl::~Impl()
+{
+       InProgressProcesses::iterator ipit  = in_progress_.begin();
+       InProgressProcesses::iterator ipend = in_progress_.end();
+
+       for (; ipit != ipend; ++ipit) {
+               ipit->second.stop();
+       }
+}
+
+
+PreviewImage const *
+PreviewLoader::Impl::preview(string const & latex_snippet) const
+{
+       Cache::const_iterator it = cache_.find(latex_snippet);
+       return (it == cache_.end()) ? 0 : it->second.get();
+}
+
+
+namespace {
+
+class FindSnippet : public std::unary_function<InProgressProcess, bool> {
+public:
+       FindSnippet(string const & s) : snippet_(s) {}
+       bool operator()(InProgressProcess const & process) const
+       {
+               BitmapFile const & snippets = process.second.snippets;
+               BitmapFile::const_iterator beg  = snippets.begin();
+               BitmapFile::const_iterator end = snippets.end();
+               return find_if(beg, end, FindFirst(snippet_)) != end;
+       }
+
+private:
+       string const snippet_;
+};
+
+} // namespace anon
+
+PreviewLoader::Status
+PreviewLoader::Impl::status(string const & latex_snippet) const
+{
+       Cache::const_iterator cit = cache_.find(latex_snippet);
+       if (cit != cache_.end())
+               return Ready;
+
+       PendingSnippets::const_iterator pit  = pending_.begin();
+       PendingSnippets::const_iterator pend = pending_.end();
+
+       pit = find(pit, pend, latex_snippet);
+       if (pit != pend)
+               return InQueue;
+
+       InProgressProcesses::const_iterator ipit  = in_progress_.begin();
+       InProgressProcesses::const_iterator ipend = in_progress_.end();
+
+       ipit = find_if(ipit, ipend, FindSnippet(latex_snippet));
+       if (ipit != ipend)
+               return Processing;
+
+       return NotFound;
+}
+
+
+void PreviewLoader::Impl::add(string const & latex_snippet)
+{
+       if (!pconverter_ || status(latex_snippet) != NotFound)
+               return;
+
+       string const snippet = support::trim(latex_snippet);
+       if (snippet.empty())
+               return;
+
+       LYXERR(Debug::GRAPHICS) << "adding snippet:\n" << snippet << endl;
+
+       pending_.push_back(snippet);
+}
+
+
+namespace {
+
+class EraseSnippet {
+public:
+       EraseSnippet(string const & s) : snippet_(s) {}
+       void operator()(InProgressProcess & process)
+       {
+               BitmapFile & snippets = process.second.snippets;
+               BitmapFile::iterator it  = snippets.begin();
+               BitmapFile::iterator end = snippets.end();
+
+               it = find_if(it, end, FindFirst(snippet_));
+               if (it != end)
+                       snippets.erase(it, it+1);
+       }
+
+private:
+       string const & snippet_;
+};
+
+} // namespace anon
+
+
+void PreviewLoader::Impl::remove(string const & latex_snippet)
+{
+       Cache::iterator cit = cache_.find(latex_snippet);
+       if (cit != cache_.end())
+               cache_.erase(cit);
+
+       PendingSnippets::iterator pit  = pending_.begin();
+       PendingSnippets::iterator pend = pending_.end();
+
+       pending_.erase(std::remove(pit, pend, latex_snippet), pend);
+
+       InProgressProcesses::iterator ipit  = in_progress_.begin();
+       InProgressProcesses::iterator ipend = in_progress_.end();
+
+       std::for_each(ipit, ipend, EraseSnippet(latex_snippet));
+
+       while (ipit != ipend) {
+               InProgressProcesses::iterator curr = ipit++;
+               if (curr->second.snippets.empty())
+                       in_progress_.erase(curr);
+       }
+}
+
+
+void PreviewLoader::Impl::startLoading()
+{
+       if (pending_.empty() || !pconverter_)
+               return;
+
+       // Only start the process off after the buffer is loaded from file.
+       if (!buffer_.fully_loaded())
+               return;
+
+       LYXERR(Debug::GRAPHICS) << "PreviewLoader::startLoading()" << endl;
+
+       // As used by the LaTeX file and by the resulting image files
+       string const directory = buffer_.temppath();
+
+       string const filename_base = unique_filename(directory);
+
+       // Create an InProgress instance to place in the map of all
+       // such processes if it starts correctly.
+       InProgress inprogress(filename_base, pending_, pconverter_->to);
+
+       // clear pending_, so we're ready to start afresh.
+       pending_.clear();
+
+       // Output the LaTeX file.
+       FileName const latexfile(filename_base + ".tex");
+
+       // FIXME UNICODE
+       // This creates an utf8 encoded file, but the proper inputenc
+       // command is missing.
+       odocfstream of(latexfile.toFilesystemEncoding().c_str());
+       if (!of) {
+               LYXERR(Debug::GRAPHICS) << "PreviewLoader::startLoading()\n"
+                                       << "Unable to create LaTeX file\n"
+                                       << latexfile << endl;
+               return;
+       }
+       of << "\\batchmode\n";
+       dumpPreamble(of);
+       of << "\n\\begin{document}\n";
+       dumpData(of, inprogress.snippets);
+       of << "\n\\end{document}\n";
+       of.close();
+
+       // The conversion command.
+       ostringstream cs;
+       cs << pconverter_->command << ' ' << pconverter_->to << ' '
+          << support::quoteName(latexfile.toFilesystemEncoding()) << ' '
+          << int(font_scaling_factor_) << ' '
+          << theApp()->hexName(LColor::preview) << ' '
+          << theApp()->hexName(LColor::background);
+
+       string const command = support::libScriptSearch(cs.str());
+
+       // Initiate the conversion from LaTeX to bitmap images files.
+       support::Forkedcall::SignalTypePtr
+               convert_ptr(new support::Forkedcall::SignalType);
+       convert_ptr->connect(bind(&Impl::finishedGenerating, this, _1, _2));
+
+       support::Forkedcall call;
+       int ret = call.startscript(command, convert_ptr);
+
+       if (ret != 0) {
+               LYXERR(Debug::GRAPHICS) << "PreviewLoader::startLoading()\n"
+                                       << "Unable to start process\n"
+                                       << command << endl;
+               return;
+       }
+
+       // Store the generation process in a list of all such processes
+       inprogress.pid = call.pid();
+       inprogress.command = command;
+       in_progress_[inprogress.pid] = inprogress;
+}
+
+
+void PreviewLoader::Impl::finishedGenerating(pid_t pid, int retval)
+{
+       // Paranoia check!
+       InProgressProcesses::iterator git = in_progress_.find(pid);
+       if (git == in_progress_.end()) {
+               lyxerr << "PreviewLoader::finishedGenerating(): unable to find "
+                       "data for PID " << pid << endl;
+               return;
+       }
+
+       string const command = git->second.command;
+       string const status = retval > 0 ? "failed" : "succeeded";
+       LYXERR(Debug::GRAPHICS) << "PreviewLoader::finishedInProgress("
+                               << retval << "): processing " << status
+                               << " for " << command << endl;
+       if (retval > 0)
+               return;
+
+       // Read the metrics file, if it exists
+       vector<double> ascent_fractions(git->second.snippets.size());
+       setAscentFractions(ascent_fractions, git->second.metrics_file);
+
+       // Add these newly generated bitmap files to the cache and
+       // start loading them into LyX.
+       BitmapFile::const_iterator it  = git->second.snippets.begin();
+       BitmapFile::const_iterator end = git->second.snippets.end();
+
+       std::list<PreviewImagePtr> newimages;
+
+       int metrics_counter = 0;
+       for (; it != end; ++it, ++metrics_counter) {
+               string const & snip = it->first;
+               FileName const & file = it->second;
+               double af = ascent_fractions[metrics_counter];
+
+               PreviewImagePtr ptr(new PreviewImage(parent_, snip, file, af));
+               cache_[snip] = ptr;
+
+               newimages.push_back(ptr);
+       }
+
+       // Remove the item from the list of still-executing processes.
+       in_progress_.erase(git);
+
+       // Tell the outside world
+       std::list<PreviewImagePtr>::const_reverse_iterator
+               nit  = newimages.rbegin();
+       std::list<PreviewImagePtr>::const_reverse_iterator
+               nend = newimages.rend();
+       for (; nit != nend; ++nit) {
+               imageReady(*nit->get());
+       }
+}
+
+
+void PreviewLoader::Impl::dumpPreamble(odocstream & os) const
+{
+       // Why on earth is Buffer::makeLaTeXFile a non-const method?
+       Buffer & tmp = const_cast<Buffer &>(buffer_);
+       // Dump the preamble only.
+       // We don't need an encoding for runparams since it is not used by
+       // the preamble.
+       OutputParams runparams(0);
+       runparams.flavor = OutputParams::LATEX;
+       runparams.nice = true;
+       runparams.moving_arg = true;
+       runparams.free_spacing = true;
+       tmp.writeLaTeXSource(os, buffer_.filePath(), runparams, true, false);
+
+       // FIXME! This is a HACK! The proper fix is to control the 'true'
+       // passed to WriteStream below:
+       // int InsetMathNest::latex(Buffer const &, odocstream & os,
+       //                          OutputParams const & runparams) const
+       // {
+       //      WriteStream wi(os, runparams.moving_arg, true);
+       //      par_->write(wi);
+       //      return wi.line();
+       // }
+       os << "\n"
+          << "\\def\\lyxlock{}\n"
+          << "\n";
+
+       // Loop over the insets in the buffer and dump all the math-macros.
+       InsetBase & inset = buffer_.inset();
+       InsetIterator it = inset_iterator_begin(inset);
+       InsetIterator const end = inset_iterator_end(inset);
+
+       for (; it != end; ++it)
+               if (it->lyxCode() == InsetBase::MATHMACRO_CODE)
+                       it->latex(buffer_, os, runparams);
+
+       // All equation labels appear as "(#)" + preview.sty's rendering of
+       // the label name
+       if (lyxrc.preview_hashed_labels)
+               os << "\\renewcommand{\\theequation}{\\#}\n";
+
+       // Use the preview style file to ensure that each snippet appears on a
+       // fresh page.
+       os << "\n"
+          << "\\usepackage[active,delayed,dvips,showlabels,lyx]{preview}\n"
+          << "\n";
+}
+
+
+void PreviewLoader::Impl::dumpData(odocstream & os,
+                                  BitmapFile const & vec) const
+{
+       if (vec.empty())
+               return;
+
+       BitmapFile::const_iterator it  = vec.begin();
+       BitmapFile::const_iterator end = vec.end();
+
+       for (; it != end; ++it) {
+               // FIXME UNICODE
+               os << "\\begin{preview}\n"
+                  << from_utf8(it->first)
+                  << "\n\\end{preview}\n\n";
+       }
+}
+
+} // namespace graphics
+} // namespace lyx
+
diff --git a/src/graphics/Previews.C b/src/graphics/Previews.C
deleted file mode 100644 (file)
index 0da83d9..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * \file Previews.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "Previews.h"
-#include "PreviewLoader.h"
-
-#include "buffer.h"
-#include "insetiterator.h"
-#include "lyxrc.h"
-#include "paragraph.h"
-
-#include "insets/Inset.h"
-
-
-namespace lyx {
-
-namespace graphics {
-
-LyXRC_PreviewStatus Previews::status()
-{
-       return lyxrc.preview;
-}
-
-
-Previews & Previews::get()
-{
-       static Previews singleton;
-       return singleton;
-}
-
-
-class Previews::Impl {
-public:
-       ///
-       typedef boost::shared_ptr<PreviewLoader> PreviewLoaderPtr;
-       ///
-       typedef std::map<Buffer const *, PreviewLoaderPtr> CacheType;
-       ///
-       CacheType cache;
-};
-
-
-Previews::Previews()
-       : pimpl_(new Impl)
-{}
-
-
-Previews::~Previews()
-{}
-
-
-PreviewLoader & Previews::loader(Buffer const & buffer) const
-{
-       Impl::CacheType::iterator it = pimpl_->cache.find(&buffer);
-
-       if (it == pimpl_->cache.end()) {
-               Impl::PreviewLoaderPtr ptr(new PreviewLoader(buffer));
-               pimpl_->cache[&buffer] = ptr;
-               return *ptr.get();
-       }
-
-       return *it->second.get();
-}
-
-
-void Previews::removeLoader(Buffer const & buffer) const
-{
-       Impl::CacheType::iterator it = pimpl_->cache.find(&buffer);
-
-       if (it != pimpl_->cache.end())
-               pimpl_->cache.erase(it);
-}
-
-
-void Previews::generateBufferPreviews(Buffer const & buffer) const
-{
-       PreviewLoader & ploader = loader(buffer);
-
-       InsetBase & inset = buffer.inset();
-       InsetIterator it = inset_iterator_begin(inset);
-       InsetIterator const end = inset_iterator_end(inset);
-
-       for (; it != end; ++it)
-               it->addPreview(ploader);
-
-       ploader.startLoading();
-}
-
-} // namespace graphics
-} // namespace lyx
diff --git a/src/graphics/Previews.cpp b/src/graphics/Previews.cpp
new file mode 100644 (file)
index 0000000..0da83d9
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * \file Previews.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "Previews.h"
+#include "PreviewLoader.h"
+
+#include "buffer.h"
+#include "insetiterator.h"
+#include "lyxrc.h"
+#include "paragraph.h"
+
+#include "insets/Inset.h"
+
+
+namespace lyx {
+
+namespace graphics {
+
+LyXRC_PreviewStatus Previews::status()
+{
+       return lyxrc.preview;
+}
+
+
+Previews & Previews::get()
+{
+       static Previews singleton;
+       return singleton;
+}
+
+
+class Previews::Impl {
+public:
+       ///
+       typedef boost::shared_ptr<PreviewLoader> PreviewLoaderPtr;
+       ///
+       typedef std::map<Buffer const *, PreviewLoaderPtr> CacheType;
+       ///
+       CacheType cache;
+};
+
+
+Previews::Previews()
+       : pimpl_(new Impl)
+{}
+
+
+Previews::~Previews()
+{}
+
+
+PreviewLoader & Previews::loader(Buffer const & buffer) const
+{
+       Impl::CacheType::iterator it = pimpl_->cache.find(&buffer);
+
+       if (it == pimpl_->cache.end()) {
+               Impl::PreviewLoaderPtr ptr(new PreviewLoader(buffer));
+               pimpl_->cache[&buffer] = ptr;
+               return *ptr.get();
+       }
+
+       return *it->second.get();
+}
+
+
+void Previews::removeLoader(Buffer const & buffer) const
+{
+       Impl::CacheType::iterator it = pimpl_->cache.find(&buffer);
+
+       if (it != pimpl_->cache.end())
+               pimpl_->cache.erase(it);
+}
+
+
+void Previews::generateBufferPreviews(Buffer const & buffer) const
+{
+       PreviewLoader & ploader = loader(buffer);
+
+       InsetBase & inset = buffer.inset();
+       InsetIterator it = inset_iterator_begin(inset);
+       InsetIterator const end = inset_iterator_end(inset);
+
+       for (; it != end; ++it)
+               it->addPreview(ploader);
+
+       ploader.startLoading();
+}
+
+} // namespace graphics
+} // namespace lyx
diff --git a/src/mathed/InsetFormulaMacro.C b/src/mathed/InsetFormulaMacro.C
deleted file mode 100644 (file)
index 1a17f87..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/**
- * \file InsetFormulaMacro.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetFormulaMacro.h"
-#include "MathMacroTable.h"
-#include "MathMacroTemplate.h"
-
-#include "BufferView.h"
-#include "cursor.h"
-#include "debug.h"
-#include "gettext.h"
-#include "LColor.h"
-#include "lyxlex.h"
-#include "outputparams.h"
-
-#include "frontends/FontMetrics.h"
-#include "frontends/Painter.h"
-
-#include "support/lstrings.h"
-
-#include <sstream>
-
-
-namespace lyx {
-
-using odocstream;
-using support::bformat;
-
-using std::string;
-using std::auto_ptr;
-using std::ostream;
-using std::endl;
-
-
-
-InsetFormulaMacro::InsetFormulaMacro()
-       : InsetMathNest(2), name_("unknownA")
-{}
-
-
-InsetFormulaMacro::InsetFormulaMacro
-               (string const & name, int nargs, string const & type)
-       : InsetMathNest(2), name_(name)
-{
-       MathMacroTable::create(MathAtom(new MathMacroTemplate(name, nargs, type)));
-}
-
-
-InsetFormulaMacro::InsetFormulaMacro(string const & s)
-       : InsetMathNest(2), name_("unknownB")
-{
-       std::istringstream is(s);
-       read(is);
-}
-
-
-auto_ptr<InsetBase> InsetFormulaMacro::clone() const
-{
-       return auto_ptr<InsetBase>(new InsetFormulaMacro(*this));
-}
-
-
-void InsetFormulaMacro::write(Buffer const &, ostream & os) const
-{
-       os << "FormulaMacro\n";
-       WriteStream wi(os, false, false);
-       tmpl()->write(wi);
-}
-
-
-int InsetFormulaMacro::latex(Buffer const &, odocstream & os,
-                             OutputParams const & runparams) const
-{
-       //lyxerr << "InsetFormulaMacro::latex" << endl;
-       WriteStream wi(os, runparams.moving_arg, true);
-       tmpl()->write(wi);
-       return 2;
-}
-
-
-int InsetFormulaMacro::plaintext(Buffer const &, odocstream & os,
-                                 OutputParams const &) const
-{
-       odocstringstream oss;
-       WriteStream wi(oss, false, true);
-       tmpl()->write(wi);
-
-       docstring const str = oss.str();
-       os << str;
-       return str.size();
-}
-
-
-int InsetFormulaMacro::docbook(Buffer const & buf, ostream & os,
-                               OutputParams const & runparams) const
-{
-       return plaintext(buf, os, runparams);
-}
-
-
-void InsetFormulaMacro::read(Buffer const &, LyXLex & lex)
-{
-       read(lex.getStream());
-}
-
-
-void InsetFormulaMacro::read(std::istream & is)
-{
-       auto_ptr<MathMacroTemplate> p(new MathMacroTemplate(is));
-       name_ = p->name();
-       MathMacroTable::create(MathAtom(p.release()));
-}
-
-
-string InsetFormulaMacro::prefix() const
-{
-       return to_utf8(bformat(_(" Macro: %1$s: "), lyx::from_utf8(name_)));
-}
-
-
-bool InsetFormulaMacro::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       //lyxerr << "InsetFormulaMacro: " << this << " -- " << &tmpl() << endl;
-       tmpl()->metrics(mi, dim);
-       dim.asc += 5;
-       dim.des += 5;
-       dim.wid += 10 + theFontMetrics(mi.base.font).width(prefix());
-       bool const changed = dim_ != dim;
-       dim_ = dim;
-       return changed;
-}
-
-
-void InsetFormulaMacro::draw(PainterInfo & p, int x, int y) const
-{
-       // label
-       LyXFont font = p.base.font;
-       font.setColor(LColor::math);
-
-       PainterInfo pi(p.base.bv, p.pain);
-       pi.base.style = LM_ST_TEXT;
-       pi.base.font  = font;
-
-       int const a = y - dim_.asc + 1;
-       int const w = dim_.wid - 2;
-       int const h = dim_.height() - 2;
-
-       // LColor::mathbg used to be "AntiqueWhite" but is "linen" now, too
-       pi.pain.fillRectangle(x, a, w, h, LColor::mathmacrobg);
-       pi.pain.rectangle(x, a, w, h, LColor::mathframe);
-
-#ifdef WITH_WARNINGS
-#warning FIXME
-#endif
-#if 0
-       LCursor & cur = p.base.bv->cursor();
-       if (cur.isInside(this))
-               cur.drawSelection(pi);
-#endif
-
-       pi.pain.text(x + 2, y, prefix(), font);
-
-       // body
-       tmpl()->draw(pi,
-               x + theFontMetrics(p.base.font).width(prefix()) + 5,
-               y);
-
-       setPosCache(pi, x, y);
-}
-
-
-MathAtom & InsetFormulaMacro::tmpl() const
-{
-       return MathMacroTable::provide(name_);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetFormulaMacro.cpp b/src/mathed/InsetFormulaMacro.cpp
new file mode 100644 (file)
index 0000000..1a17f87
--- /dev/null
@@ -0,0 +1,188 @@
+/**
+ * \file InsetFormulaMacro.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetFormulaMacro.h"
+#include "MathMacroTable.h"
+#include "MathMacroTemplate.h"
+
+#include "BufferView.h"
+#include "cursor.h"
+#include "debug.h"
+#include "gettext.h"
+#include "LColor.h"
+#include "lyxlex.h"
+#include "outputparams.h"
+
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
+#include "support/lstrings.h"
+
+#include <sstream>
+
+
+namespace lyx {
+
+using odocstream;
+using support::bformat;
+
+using std::string;
+using std::auto_ptr;
+using std::ostream;
+using std::endl;
+
+
+
+InsetFormulaMacro::InsetFormulaMacro()
+       : InsetMathNest(2), name_("unknownA")
+{}
+
+
+InsetFormulaMacro::InsetFormulaMacro
+               (string const & name, int nargs, string const & type)
+       : InsetMathNest(2), name_(name)
+{
+       MathMacroTable::create(MathAtom(new MathMacroTemplate(name, nargs, type)));
+}
+
+
+InsetFormulaMacro::InsetFormulaMacro(string const & s)
+       : InsetMathNest(2), name_("unknownB")
+{
+       std::istringstream is(s);
+       read(is);
+}
+
+
+auto_ptr<InsetBase> InsetFormulaMacro::clone() const
+{
+       return auto_ptr<InsetBase>(new InsetFormulaMacro(*this));
+}
+
+
+void InsetFormulaMacro::write(Buffer const &, ostream & os) const
+{
+       os << "FormulaMacro\n";
+       WriteStream wi(os, false, false);
+       tmpl()->write(wi);
+}
+
+
+int InsetFormulaMacro::latex(Buffer const &, odocstream & os,
+                             OutputParams const & runparams) const
+{
+       //lyxerr << "InsetFormulaMacro::latex" << endl;
+       WriteStream wi(os, runparams.moving_arg, true);
+       tmpl()->write(wi);
+       return 2;
+}
+
+
+int InsetFormulaMacro::plaintext(Buffer const &, odocstream & os,
+                                 OutputParams const &) const
+{
+       odocstringstream oss;
+       WriteStream wi(oss, false, true);
+       tmpl()->write(wi);
+
+       docstring const str = oss.str();
+       os << str;
+       return str.size();
+}
+
+
+int InsetFormulaMacro::docbook(Buffer const & buf, ostream & os,
+                               OutputParams const & runparams) const
+{
+       return plaintext(buf, os, runparams);
+}
+
+
+void InsetFormulaMacro::read(Buffer const &, LyXLex & lex)
+{
+       read(lex.getStream());
+}
+
+
+void InsetFormulaMacro::read(std::istream & is)
+{
+       auto_ptr<MathMacroTemplate> p(new MathMacroTemplate(is));
+       name_ = p->name();
+       MathMacroTable::create(MathAtom(p.release()));
+}
+
+
+string InsetFormulaMacro::prefix() const
+{
+       return to_utf8(bformat(_(" Macro: %1$s: "), lyx::from_utf8(name_)));
+}
+
+
+bool InsetFormulaMacro::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       //lyxerr << "InsetFormulaMacro: " << this << " -- " << &tmpl() << endl;
+       tmpl()->metrics(mi, dim);
+       dim.asc += 5;
+       dim.des += 5;
+       dim.wid += 10 + theFontMetrics(mi.base.font).width(prefix());
+       bool const changed = dim_ != dim;
+       dim_ = dim;
+       return changed;
+}
+
+
+void InsetFormulaMacro::draw(PainterInfo & p, int x, int y) const
+{
+       // label
+       LyXFont font = p.base.font;
+       font.setColor(LColor::math);
+
+       PainterInfo pi(p.base.bv, p.pain);
+       pi.base.style = LM_ST_TEXT;
+       pi.base.font  = font;
+
+       int const a = y - dim_.asc + 1;
+       int const w = dim_.wid - 2;
+       int const h = dim_.height() - 2;
+
+       // LColor::mathbg used to be "AntiqueWhite" but is "linen" now, too
+       pi.pain.fillRectangle(x, a, w, h, LColor::mathmacrobg);
+       pi.pain.rectangle(x, a, w, h, LColor::mathframe);
+
+#ifdef WITH_WARNINGS
+#warning FIXME
+#endif
+#if 0
+       LCursor & cur = p.base.bv->cursor();
+       if (cur.isInside(this))
+               cur.drawSelection(pi);
+#endif
+
+       pi.pain.text(x + 2, y, prefix(), font);
+
+       // body
+       tmpl()->draw(pi,
+               x + theFontMetrics(p.base.font).width(prefix()) + 5,
+               y);
+
+       setPosCache(pi, x, y);
+}
+
+
+MathAtom & InsetFormulaMacro::tmpl() const
+{
+       return MathMacroTable::provide(name_);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMath.C b/src/mathed/InsetMath.C
deleted file mode 100644 (file)
index 64db5a2..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * \file InsetMath.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMath.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "gettext.h"
-#include "debug.h"
-
-#include "support/lstrings.h"
-#include "support/textutils.h"
-
-#include <boost/current_function.hpp>
-
-using std::endl;
-
-namespace lyx {
-
-
-
-MathArray & InsetMath::cell(idx_type)
-{
-       static MathArray dummyCell;
-       lyxerr << BOOST_CURRENT_FUNCTION << ": I don't have any cell" << endl;
-       return dummyCell;
-}
-
-
-MathArray const & InsetMath::cell(idx_type) const
-{
-       static MathArray dummyCell;
-       lyxerr << BOOST_CURRENT_FUNCTION << ": I don't have any cell" << endl;
-       return dummyCell;
-}
-
-
-void InsetMath::dump() const
-{
-       lyxerr << "---------------------------------------------" << endl;
-       odocstringstream os;
-       WriteStream wi(os, false, true);
-       write(wi);
-       lyxerr << to_utf8(os.str());
-       lyxerr << "\n---------------------------------------------" << endl;
-}
-
-
-void InsetMath::metricsT(TextMetricsInfo const &, Dimension &) const
-{
-#ifdef WITH_WARNINGS
-       lyxerr << "InsetMath::metricsT(Text) called directly!" << endl;
-#endif
-}
-
-
-void InsetMath::drawT(TextPainter &, int, int) const
-{
-#ifdef WITH_WARNINGS
-       lyxerr << "InsetMath::drawT(Text) called directly!" << endl;
-#endif
-}
-
-
-
-void InsetMath::write(WriteStream & os) const
-{
-       docstring const s = name();
-       os << "\\" << s;
-       // We need an extra ' ' unless this is a single-char-non-ASCII name
-       // or anything non-ASCII follows
-       if (s.size() != 1 || isAlphaASCII(s[0]))
-               os.pendingSpace(true);
-}
-
-
-int InsetMath::plaintext(Buffer const &, odocstream &,
-                         OutputParams const &) const
-{
-       // all math plain text output shall take place in InsetMathHull
-       BOOST_ASSERT(false);
-       return 0;
-}
-
-
-void InsetMath::normalize(NormalStream & os) const
-{
-       os << '[' << name() << "] ";
-}
-
-
-void InsetMath::octave(OctaveStream & os) const
-{
-       NormalStream ns(os.os());
-       normalize(ns);
-}
-
-
-void InsetMath::maple(MapleStream & os) const
-{
-       NormalStream ns(os.os());
-       normalize(ns);
-}
-
-
-void InsetMath::maxima(MaximaStream & os) const
-{
-       MapleStream ns(os.os());
-       maple(ns);
-}
-
-
-void InsetMath::mathematica(MathematicaStream & os) const
-{
-       NormalStream ns(os.os());
-       normalize(ns);
-}
-
-
-void InsetMath::mathmlize(MathStream & os) const
-{
-        NormalStream ns(os.os());
-        normalize(ns);
-}
-
-
-HullType InsetMath::getType() const
-{
-       return hullNone;
-}
-
-
-docstring InsetMath::name() const
-{
-       return from_ascii("unknown");
-}
-
-
-std::ostream & operator<<(std::ostream & os, MathAtom const & at)
-{
-       odocstringstream oss;
-       WriteStream wi(oss, false, false);
-       at->write(wi);
-       return os << to_utf8(oss.str());
-}
-
-
-odocstream & operator<<(odocstream & os, MathAtom const & at)
-{
-       WriteStream wi(os, false, false);
-       at->write(wi);
-       return os;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMath.cpp b/src/mathed/InsetMath.cpp
new file mode 100644 (file)
index 0000000..64db5a2
--- /dev/null
@@ -0,0 +1,165 @@
+/**
+ * \file InsetMath.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMath.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "gettext.h"
+#include "debug.h"
+
+#include "support/lstrings.h"
+#include "support/textutils.h"
+
+#include <boost/current_function.hpp>
+
+using std::endl;
+
+namespace lyx {
+
+
+
+MathArray & InsetMath::cell(idx_type)
+{
+       static MathArray dummyCell;
+       lyxerr << BOOST_CURRENT_FUNCTION << ": I don't have any cell" << endl;
+       return dummyCell;
+}
+
+
+MathArray const & InsetMath::cell(idx_type) const
+{
+       static MathArray dummyCell;
+       lyxerr << BOOST_CURRENT_FUNCTION << ": I don't have any cell" << endl;
+       return dummyCell;
+}
+
+
+void InsetMath::dump() const
+{
+       lyxerr << "---------------------------------------------" << endl;
+       odocstringstream os;
+       WriteStream wi(os, false, true);
+       write(wi);
+       lyxerr << to_utf8(os.str());
+       lyxerr << "\n---------------------------------------------" << endl;
+}
+
+
+void InsetMath::metricsT(TextMetricsInfo const &, Dimension &) const
+{
+#ifdef WITH_WARNINGS
+       lyxerr << "InsetMath::metricsT(Text) called directly!" << endl;
+#endif
+}
+
+
+void InsetMath::drawT(TextPainter &, int, int) const
+{
+#ifdef WITH_WARNINGS
+       lyxerr << "InsetMath::drawT(Text) called directly!" << endl;
+#endif
+}
+
+
+
+void InsetMath::write(WriteStream & os) const
+{
+       docstring const s = name();
+       os << "\\" << s;
+       // We need an extra ' ' unless this is a single-char-non-ASCII name
+       // or anything non-ASCII follows
+       if (s.size() != 1 || isAlphaASCII(s[0]))
+               os.pendingSpace(true);
+}
+
+
+int InsetMath::plaintext(Buffer const &, odocstream &,
+                         OutputParams const &) const
+{
+       // all math plain text output shall take place in InsetMathHull
+       BOOST_ASSERT(false);
+       return 0;
+}
+
+
+void InsetMath::normalize(NormalStream & os) const
+{
+       os << '[' << name() << "] ";
+}
+
+
+void InsetMath::octave(OctaveStream & os) const
+{
+       NormalStream ns(os.os());
+       normalize(ns);
+}
+
+
+void InsetMath::maple(MapleStream & os) const
+{
+       NormalStream ns(os.os());
+       normalize(ns);
+}
+
+
+void InsetMath::maxima(MaximaStream & os) const
+{
+       MapleStream ns(os.os());
+       maple(ns);
+}
+
+
+void InsetMath::mathematica(MathematicaStream & os) const
+{
+       NormalStream ns(os.os());
+       normalize(ns);
+}
+
+
+void InsetMath::mathmlize(MathStream & os) const
+{
+        NormalStream ns(os.os());
+        normalize(ns);
+}
+
+
+HullType InsetMath::getType() const
+{
+       return hullNone;
+}
+
+
+docstring InsetMath::name() const
+{
+       return from_ascii("unknown");
+}
+
+
+std::ostream & operator<<(std::ostream & os, MathAtom const & at)
+{
+       odocstringstream oss;
+       WriteStream wi(oss, false, false);
+       at->write(wi);
+       return os << to_utf8(oss.str());
+}
+
+
+odocstream & operator<<(odocstream & os, MathAtom const & at)
+{
+       WriteStream wi(os, false, false);
+       at->write(wi);
+       return os;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathAMSArray.C b/src/mathed/InsetMathAMSArray.C
deleted file mode 100644 (file)
index 3febc45..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * \file InsetMathAMSArray.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "LaTeXFeatures.h"
-#include "InsetMathAMSArray.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-
-#include "funcrequest.h"
-#include "FuncStatus.h"
-#include "gettext.h"
-
-#include "support/lstrings.h"
-#include "support/std_ostream.h"
-
-using std::auto_ptr;
-
-namespace lyx {
-
-using support::bformat;
-
-
-InsetMathAMSArray::InsetMathAMSArray(docstring const & name, int m, int n)
-       : InsetMathGrid(m, n), name_(name)
-{}
-
-
-InsetMathAMSArray::InsetMathAMSArray(docstring const & name)
-       : InsetMathGrid(1, 1), name_(name)
-{}
-
-
-auto_ptr<InsetBase> InsetMathAMSArray::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathAMSArray(*this));
-}
-
-
-char const * InsetMathAMSArray::name_left() const
-{
-       if (name_ == "bmatrix")
-               return "[";
-       if (name_ == "Bmatrix")
-               return "{";
-       if (name_ == "vmatrix")
-               return "|";
-       if (name_ == "Vmatrix")
-               return "Vert";
-       if (name_ == "pmatrix")
-               return "(";
-       return ".";
-}
-
-
-char const * InsetMathAMSArray::name_right() const
-{
-       if (name_ == "bmatrix")
-               return "]";
-       if (name_ == "Bmatrix")
-               return "}";
-       if (name_ == "vmatrix")
-               return "|";
-       if (name_ == "Vmatrix")
-               return "Vert";
-       if (name_ == "pmatrix")
-               return ")";
-       return ".";
-}
-
-
-bool InsetMathAMSArray::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       ArrayChanger dummy(mi.base);
-       InsetMathGrid::metrics(mi, dim);
-       dim.wid += 14;
-       bool const changed = dim_ != dim;
-       dim_ = dim;
-       return changed;
-}
-
-
-void InsetMathAMSArray::draw(PainterInfo & pi, int x, int y) const
-{
-       int const yy = y - dim_.ascent();
-       // Drawing the deco after an ArrayChanger does not work
-       mathed_draw_deco(pi, x + 1, yy, 5, dim_.height(), from_ascii(name_left()));
-       mathed_draw_deco(pi, x + dim_.width() - 8, yy, 5, dim_.height(), from_ascii(name_right()));
-       ArrayChanger dummy(pi.base);
-       InsetMathGrid::drawWithMargin(pi, x, y, 6, 8);
-}
-
-
-bool InsetMathAMSArray::getStatus(LCursor & cur, FuncRequest const & cmd,
-               FuncStatus & flag) const
-{
-       switch (cmd.action) {
-       case LFUN_TABULAR_FEATURE: {
-               docstring const & s = cmd.argument();
-               if (s == "add-vline-left" || s == "add-vline-right") {
-                       flag.message(bformat(
-                               from_utf8(N_("Can't add vertical grid lines in '%1$s'")),       name_));
-                       flag.enabled(false);
-                       return true;
-               }
-               return InsetMathGrid::getStatus(cur, cmd, flag);
-       }
-       default:
-               return InsetMathGrid::getStatus(cur, cmd, flag);
-       }
-}
-
-
-void InsetMathAMSArray::write(WriteStream & os) const
-{
-       os << "\\begin{" << name_ << '}';
-       InsetMathGrid::write(os);
-       os << "\\end{" << name_ << '}';
-}
-
-
-void InsetMathAMSArray::infoize(odocstream & os) const
-{
-       docstring name = name_;
-       name[0] = support::uppercase(name[0]);
-       os << name << ' ';
-}
-
-
-void InsetMathAMSArray::normalize(NormalStream & os) const
-{
-       os << '[' << name_ << ' ';
-       InsetMathGrid::normalize(os);
-       os << ']';
-}
-
-
-void InsetMathAMSArray::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-       InsetMathGrid::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathAMSArray.cpp b/src/mathed/InsetMathAMSArray.cpp
new file mode 100644 (file)
index 0000000..3febc45
--- /dev/null
@@ -0,0 +1,155 @@
+/**
+ * \file InsetMathAMSArray.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "LaTeXFeatures.h"
+#include "InsetMathAMSArray.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+
+#include "funcrequest.h"
+#include "FuncStatus.h"
+#include "gettext.h"
+
+#include "support/lstrings.h"
+#include "support/std_ostream.h"
+
+using std::auto_ptr;
+
+namespace lyx {
+
+using support::bformat;
+
+
+InsetMathAMSArray::InsetMathAMSArray(docstring const & name, int m, int n)
+       : InsetMathGrid(m, n), name_(name)
+{}
+
+
+InsetMathAMSArray::InsetMathAMSArray(docstring const & name)
+       : InsetMathGrid(1, 1), name_(name)
+{}
+
+
+auto_ptr<InsetBase> InsetMathAMSArray::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathAMSArray(*this));
+}
+
+
+char const * InsetMathAMSArray::name_left() const
+{
+       if (name_ == "bmatrix")
+               return "[";
+       if (name_ == "Bmatrix")
+               return "{";
+       if (name_ == "vmatrix")
+               return "|";
+       if (name_ == "Vmatrix")
+               return "Vert";
+       if (name_ == "pmatrix")
+               return "(";
+       return ".";
+}
+
+
+char const * InsetMathAMSArray::name_right() const
+{
+       if (name_ == "bmatrix")
+               return "]";
+       if (name_ == "Bmatrix")
+               return "}";
+       if (name_ == "vmatrix")
+               return "|";
+       if (name_ == "Vmatrix")
+               return "Vert";
+       if (name_ == "pmatrix")
+               return ")";
+       return ".";
+}
+
+
+bool InsetMathAMSArray::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       ArrayChanger dummy(mi.base);
+       InsetMathGrid::metrics(mi, dim);
+       dim.wid += 14;
+       bool const changed = dim_ != dim;
+       dim_ = dim;
+       return changed;
+}
+
+
+void InsetMathAMSArray::draw(PainterInfo & pi, int x, int y) const
+{
+       int const yy = y - dim_.ascent();
+       // Drawing the deco after an ArrayChanger does not work
+       mathed_draw_deco(pi, x + 1, yy, 5, dim_.height(), from_ascii(name_left()));
+       mathed_draw_deco(pi, x + dim_.width() - 8, yy, 5, dim_.height(), from_ascii(name_right()));
+       ArrayChanger dummy(pi.base);
+       InsetMathGrid::drawWithMargin(pi, x, y, 6, 8);
+}
+
+
+bool InsetMathAMSArray::getStatus(LCursor & cur, FuncRequest const & cmd,
+               FuncStatus & flag) const
+{
+       switch (cmd.action) {
+       case LFUN_TABULAR_FEATURE: {
+               docstring const & s = cmd.argument();
+               if (s == "add-vline-left" || s == "add-vline-right") {
+                       flag.message(bformat(
+                               from_utf8(N_("Can't add vertical grid lines in '%1$s'")),       name_));
+                       flag.enabled(false);
+                       return true;
+               }
+               return InsetMathGrid::getStatus(cur, cmd, flag);
+       }
+       default:
+               return InsetMathGrid::getStatus(cur, cmd, flag);
+       }
+}
+
+
+void InsetMathAMSArray::write(WriteStream & os) const
+{
+       os << "\\begin{" << name_ << '}';
+       InsetMathGrid::write(os);
+       os << "\\end{" << name_ << '}';
+}
+
+
+void InsetMathAMSArray::infoize(odocstream & os) const
+{
+       docstring name = name_;
+       name[0] = support::uppercase(name[0]);
+       os << name << ' ';
+}
+
+
+void InsetMathAMSArray::normalize(NormalStream & os) const
+{
+       os << '[' << name_ << ' ';
+       InsetMathGrid::normalize(os);
+       os << ']';
+}
+
+
+void InsetMathAMSArray::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+       InsetMathGrid::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathArray.C b/src/mathed/InsetMathArray.C
deleted file mode 100644 (file)
index 8732f50..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/**
- * \file InsetMathArray.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "LaTeXFeatures.h"
-#include "InsetMathArray.h"
-#include "MathData.h"
-#include "MathParser.h"
-#include "MathStream.h"
-
-#include "support/lstrings.h"
-
-#include <iterator>
-#include <sstream>
-
-
-namespace lyx {
-
-using std::getline;
-using std::auto_ptr;
-using std::istringstream;
-using std::istream_iterator;
-using std::vector;
-using std::string;
-
-
-InsetMathArray::InsetMathArray(docstring const & name, int m, int n)
-       : InsetMathGrid(m, n), name_(name)
-{}
-
-
-InsetMathArray::InsetMathArray(docstring const & name, int m, int n,
-               char valign, docstring const & halign)
-       : InsetMathGrid(m, n, valign, halign), name_(name)
-{}
-
-
-InsetMathArray::InsetMathArray(docstring const & name, char valign,
-               docstring const & halign)
-       : InsetMathGrid(valign, halign), name_(name)
-{}
-
-
-InsetMathArray::InsetMathArray(docstring const & name, docstring const & str)
-       : InsetMathGrid(1, 1), name_(name)
-{
-       vector< vector<string> > dat;
-       istringstream is(to_utf8(str));
-       string line;
-       while (getline(is, line)) {
-               istringstream ls(line);
-               typedef istream_iterator<string> iter;
-               vector<string> v = vector<string>(iter(ls), iter());
-               if (v.size())
-                       dat.push_back(v);
-       }
-
-       for (row_type row = 1; row < dat.size(); ++row)
-               addRow(0);
-       for (col_type col = 1; col < dat[0].size(); ++col)
-               addCol(0);
-       for (row_type row = 0; row < dat.size(); ++row)
-               for (col_type col = 0; col < dat[0].size(); ++col)
-                       mathed_parse_cell(cell(index(row, col)), from_utf8(dat[row][col]));
-}
-
-
-auto_ptr<InsetBase> InsetMathArray::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathArray(*this));
-}
-
-
-bool InsetMathArray::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       ArrayChanger dummy(mi.base);
-       InsetMathGrid::metrics(mi, dim);
-       dim.wid += 6;
-       bool const changed = dim_ != dim;
-       dim_ = dim;
-       return changed;
-}
-
-
-void InsetMathArray::draw(PainterInfo & pi, int x, int y) const
-{
-       setPosCache(pi, x, y);
-       ArrayChanger dummy(pi.base);
-       InsetMathGrid::drawWithMargin(pi, x, y, 4, 2);
-}
-
-
-void InsetMathArray::write(WriteStream & os) const
-{
-       if (os.fragile())
-               os << "\\protect";
-       os << "\\begin{" << name_ << '}';
-
-       if (v_align_ == 't' || v_align_ == 'b')
-               os << '[' << char(v_align_) << ']';
-       os << '{' << halign() << "}\n";
-
-       InsetMathGrid::write(os);
-
-       if (os.fragile())
-               os << "\\protect";
-       os << "\\end{" << name_ << '}';
-       // adding a \n here is bad if the array is the last item
-       // in an \eqnarray...
-}
-
-
-void InsetMathArray::infoize(odocstream & os) const
-{
-       docstring name = name_;
-       name[0] = support::uppercase(name[0]);
-       os << name << ' ';
-}
-
-
-void InsetMathArray::normalize(NormalStream & os) const
-{
-       os << '[' << name_ << ' ';
-       InsetMathGrid::normalize(os);
-       os << ']';
-}
-
-
-void InsetMathArray::maple(MapleStream & os) const
-{
-       os << "array(";
-       InsetMathGrid::maple(os);
-       os << ')';
-}
-
-
-void InsetMathArray::validate(LaTeXFeatures & features) const
-{
-       if (name_ == "subarray")
-               features.require("amsmath");
-       InsetMathGrid::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathArray.cpp b/src/mathed/InsetMathArray.cpp
new file mode 100644 (file)
index 0000000..8732f50
--- /dev/null
@@ -0,0 +1,153 @@
+/**
+ * \file InsetMathArray.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "LaTeXFeatures.h"
+#include "InsetMathArray.h"
+#include "MathData.h"
+#include "MathParser.h"
+#include "MathStream.h"
+
+#include "support/lstrings.h"
+
+#include <iterator>
+#include <sstream>
+
+
+namespace lyx {
+
+using std::getline;
+using std::auto_ptr;
+using std::istringstream;
+using std::istream_iterator;
+using std::vector;
+using std::string;
+
+
+InsetMathArray::InsetMathArray(docstring const & name, int m, int n)
+       : InsetMathGrid(m, n), name_(name)
+{}
+
+
+InsetMathArray::InsetMathArray(docstring const & name, int m, int n,
+               char valign, docstring const & halign)
+       : InsetMathGrid(m, n, valign, halign), name_(name)
+{}
+
+
+InsetMathArray::InsetMathArray(docstring const & name, char valign,
+               docstring const & halign)
+       : InsetMathGrid(valign, halign), name_(name)
+{}
+
+
+InsetMathArray::InsetMathArray(docstring const & name, docstring const & str)
+       : InsetMathGrid(1, 1), name_(name)
+{
+       vector< vector<string> > dat;
+       istringstream is(to_utf8(str));
+       string line;
+       while (getline(is, line)) {
+               istringstream ls(line);
+               typedef istream_iterator<string> iter;
+               vector<string> v = vector<string>(iter(ls), iter());
+               if (v.size())
+                       dat.push_back(v);
+       }
+
+       for (row_type row = 1; row < dat.size(); ++row)
+               addRow(0);
+       for (col_type col = 1; col < dat[0].size(); ++col)
+               addCol(0);
+       for (row_type row = 0; row < dat.size(); ++row)
+               for (col_type col = 0; col < dat[0].size(); ++col)
+                       mathed_parse_cell(cell(index(row, col)), from_utf8(dat[row][col]));
+}
+
+
+auto_ptr<InsetBase> InsetMathArray::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathArray(*this));
+}
+
+
+bool InsetMathArray::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       ArrayChanger dummy(mi.base);
+       InsetMathGrid::metrics(mi, dim);
+       dim.wid += 6;
+       bool const changed = dim_ != dim;
+       dim_ = dim;
+       return changed;
+}
+
+
+void InsetMathArray::draw(PainterInfo & pi, int x, int y) const
+{
+       setPosCache(pi, x, y);
+       ArrayChanger dummy(pi.base);
+       InsetMathGrid::drawWithMargin(pi, x, y, 4, 2);
+}
+
+
+void InsetMathArray::write(WriteStream & os) const
+{
+       if (os.fragile())
+               os << "\\protect";
+       os << "\\begin{" << name_ << '}';
+
+       if (v_align_ == 't' || v_align_ == 'b')
+               os << '[' << char(v_align_) << ']';
+       os << '{' << halign() << "}\n";
+
+       InsetMathGrid::write(os);
+
+       if (os.fragile())
+               os << "\\protect";
+       os << "\\end{" << name_ << '}';
+       // adding a \n here is bad if the array is the last item
+       // in an \eqnarray...
+}
+
+
+void InsetMathArray::infoize(odocstream & os) const
+{
+       docstring name = name_;
+       name[0] = support::uppercase(name[0]);
+       os << name << ' ';
+}
+
+
+void InsetMathArray::normalize(NormalStream & os) const
+{
+       os << '[' << name_ << ' ';
+       InsetMathGrid::normalize(os);
+       os << ']';
+}
+
+
+void InsetMathArray::maple(MapleStream & os) const
+{
+       os << "array(";
+       InsetMathGrid::maple(os);
+       os << ')';
+}
+
+
+void InsetMathArray::validate(LaTeXFeatures & features) const
+{
+       if (name_ == "subarray")
+               features.require("amsmath");
+       InsetMathGrid::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathBig.C b/src/mathed/InsetMathBig.C
deleted file mode 100644 (file)
index e56acca..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * \file InsetMathBig.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathBig.h"
-#include "MathSupport.h"
-#include "MathStream.h"
-#include "MathStream.h"
-
-#include "frontends/FontMetrics.h"
-
-#include "support/lstrings.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathBig::InsetMathBig(docstring const & name, docstring const & delim)
-       : name_(name), delim_(delim)
-{}
-
-
-docstring InsetMathBig::name() const
-{
-       return name_;
-}
-
-
-auto_ptr<InsetBase> InsetMathBig::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathBig(*this));
-}
-
-
-InsetMathBig::size_type InsetMathBig::size() const
-{
-       // order: big Big bigg Bigg biggg Biggg
-       //        0   1   2    3    4     5
-       return name_[0] == 'B' ?
-               2 * (name_.size() - 4) + 1:
-               2 * (name_.size() - 4);
-}
-
-
-double InsetMathBig::increase() const
-{
-       // The formula used in amsmath.sty is
-       // 1.2 * (1.0 + size() * 0.5) - 1.0.
-       // We use a smaller step and a bigger offset because our base size
-       // is different.
-       return (size() + 1) * 0.3;
-}
-
-
-bool InsetMathBig::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       double const h = theFontMetrics(mi.base.font).ascent('I');
-       double const f = increase();
-       dim.wid = 6;
-       dim.asc = int(h + f * h);
-       dim.des = int(f * h);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathBig::draw(PainterInfo & pi, int x, int y) const
-{
-       // mathed_draw_deco does not use the leading backslash, so remove it
-       // (but don't use ltrim if this is the backslash delimiter).
-       // Replace \| by \Vert (equivalent in LaTeX), since mathed_draw_deco
-       // would treat it as |.
-       docstring const delim = (delim_ == "\\|") ?  from_ascii("Vert") :
-               (delim_ == "\\\\") ? from_ascii("\\") : support::ltrim(delim_, "\\");
-       mathed_draw_deco(pi, x + 1, y - dim_.ascent(), 4, dim_.height(),
-                        delim);
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathBig::write(WriteStream & os) const
-{
-       os << '\\' << name_ << delim_;
-       if (delim_[0] == '\\')
-               os.pendingSpace(true);
-}
-
-
-void InsetMathBig::normalize(NormalStream & os) const
-{
-       os << '[' << name_ << ' ' << delim_ << ']';
-}
-
-
-void InsetMathBig::infoize2(odocstream & os) const
-{
-       os << name_;
-}
-
-
-bool InsetMathBig::isBigInsetDelim(docstring const & delim)
-{
-       // mathed_draw_deco must handle these
-       static char const * const delimiters[] = {
-               "(", ")", "\\{", "\\}", "\\lbrace", "\\rbrace", "[", "]",
-               "|", "/", "\\slash", "\\|", "\\vert", "\\Vert", "'",
-               "\\\\", "\\backslash",
-               "\\langle", "\\lceil", "\\lfloor",
-               "\\rangle", "\\rceil", "\\rfloor",
-               "\\downarrow", "\\Downarrow",
-               "\\uparrow", "\\Uparrow",
-               "\\updownarrow", "\\Updownarrow", ""
-       };
-       return support::findToken(delimiters, to_utf8(delim)) >= 0;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathBig.cpp b/src/mathed/InsetMathBig.cpp
new file mode 100644 (file)
index 0000000..e56acca
--- /dev/null
@@ -0,0 +1,130 @@
+/**
+ * \file InsetMathBig.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathBig.h"
+#include "MathSupport.h"
+#include "MathStream.h"
+#include "MathStream.h"
+
+#include "frontends/FontMetrics.h"
+
+#include "support/lstrings.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathBig::InsetMathBig(docstring const & name, docstring const & delim)
+       : name_(name), delim_(delim)
+{}
+
+
+docstring InsetMathBig::name() const
+{
+       return name_;
+}
+
+
+auto_ptr<InsetBase> InsetMathBig::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathBig(*this));
+}
+
+
+InsetMathBig::size_type InsetMathBig::size() const
+{
+       // order: big Big bigg Bigg biggg Biggg
+       //        0   1   2    3    4     5
+       return name_[0] == 'B' ?
+               2 * (name_.size() - 4) + 1:
+               2 * (name_.size() - 4);
+}
+
+
+double InsetMathBig::increase() const
+{
+       // The formula used in amsmath.sty is
+       // 1.2 * (1.0 + size() * 0.5) - 1.0.
+       // We use a smaller step and a bigger offset because our base size
+       // is different.
+       return (size() + 1) * 0.3;
+}
+
+
+bool InsetMathBig::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       double const h = theFontMetrics(mi.base.font).ascent('I');
+       double const f = increase();
+       dim.wid = 6;
+       dim.asc = int(h + f * h);
+       dim.des = int(f * h);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathBig::draw(PainterInfo & pi, int x, int y) const
+{
+       // mathed_draw_deco does not use the leading backslash, so remove it
+       // (but don't use ltrim if this is the backslash delimiter).
+       // Replace \| by \Vert (equivalent in LaTeX), since mathed_draw_deco
+       // would treat it as |.
+       docstring const delim = (delim_ == "\\|") ?  from_ascii("Vert") :
+               (delim_ == "\\\\") ? from_ascii("\\") : support::ltrim(delim_, "\\");
+       mathed_draw_deco(pi, x + 1, y - dim_.ascent(), 4, dim_.height(),
+                        delim);
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathBig::write(WriteStream & os) const
+{
+       os << '\\' << name_ << delim_;
+       if (delim_[0] == '\\')
+               os.pendingSpace(true);
+}
+
+
+void InsetMathBig::normalize(NormalStream & os) const
+{
+       os << '[' << name_ << ' ' << delim_ << ']';
+}
+
+
+void InsetMathBig::infoize2(odocstream & os) const
+{
+       os << name_;
+}
+
+
+bool InsetMathBig::isBigInsetDelim(docstring const & delim)
+{
+       // mathed_draw_deco must handle these
+       static char const * const delimiters[] = {
+               "(", ")", "\\{", "\\}", "\\lbrace", "\\rbrace", "[", "]",
+               "|", "/", "\\slash", "\\|", "\\vert", "\\Vert", "'",
+               "\\\\", "\\backslash",
+               "\\langle", "\\lceil", "\\lfloor",
+               "\\rangle", "\\rceil", "\\rfloor",
+               "\\downarrow", "\\Downarrow",
+               "\\uparrow", "\\Uparrow",
+               "\\updownarrow", "\\Updownarrow", ""
+       };
+       return support::findToken(delimiters, to_utf8(delim)) >= 0;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathBinom.C b/src/mathed/InsetMathBinom.C
deleted file mode 100644 (file)
index 0a08e7b..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * \file InsetMathBinom.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathBinom.h"
-#include "MathData.h"
-#include "MathSupport.h"
-#include "MathStream.h"
-
-
-namespace lyx {
-
-
-using std::max;
-using std::auto_ptr;
-
-
-InsetMathBinom::InsetMathBinom(bool choose)
-       : choose_(choose)
-{}
-
-
-auto_ptr<InsetBase> InsetMathBinom::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathBinom(*this));
-}
-
-
-int InsetMathBinom::dw() const
-{
-       int w = dim_.height() / 5;
-       if (w > 15)
-               w = 15;
-       if (w < 6)
-               w = 6;
-       return w;
-}
-
-
-bool InsetMathBinom::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       ScriptChanger dummy(mi.base);
-       cell(0).metrics(mi);
-       cell(1).metrics(mi);
-       dim.asc = cell(0).height() + 4 + 5;
-       dim.des = cell(1).height() + 4 - 5;
-       dim.wid = max(cell(0).width(), cell(1).width()) + 2 * dw() + 4;
-       metricsMarkers2(dim);
-       bool const changed = dim_ != dim;
-       dim_ = dim;
-       return changed;
-}
-
-
-void InsetMathBinom::draw(PainterInfo & pi, int x, int y) const
-{
-       int m = x + dim_.width() / 2;
-       ScriptChanger dummy(pi.base);
-       cell(0).draw(pi, m - cell(0).width() / 2, y - cell(0).descent() - 3 - 5);
-       cell(1).draw(pi, m - cell(1).width() / 2, y + cell(1).ascent()  + 3 - 5);
-       mathed_draw_deco(pi, x, y - dim_.ascent(), dw(), dim_.height(), from_ascii("("));
-       mathed_draw_deco(pi, x + dim_.width() - dw(), y - dim_.ascent(),
-               dw(), dim_.height(), from_ascii(")"));
-       drawMarkers2(pi, x, y);
-}
-
-
-bool InsetMathBinom::extraBraces() const
-{
-       return choose_;
-}
-
-
-void InsetMathBinom::write(WriteStream & os) const
-{
-       if (choose_)
-               os << '{' << cell(0) << " \\choose " << cell(1) << '}';
-       else
-               os << "\\binom{" << cell(0) << "}{" << cell(1) << '}';
-}
-
-
-void InsetMathBinom::normalize(NormalStream & os) const
-{
-       os << "[binom " << cell(0) << ' ' << cell(1) << ']';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathBinom.cpp b/src/mathed/InsetMathBinom.cpp
new file mode 100644 (file)
index 0000000..0a08e7b
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ * \file InsetMathBinom.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathBinom.h"
+#include "MathData.h"
+#include "MathSupport.h"
+#include "MathStream.h"
+
+
+namespace lyx {
+
+
+using std::max;
+using std::auto_ptr;
+
+
+InsetMathBinom::InsetMathBinom(bool choose)
+       : choose_(choose)
+{}
+
+
+auto_ptr<InsetBase> InsetMathBinom::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathBinom(*this));
+}
+
+
+int InsetMathBinom::dw() const
+{
+       int w = dim_.height() / 5;
+       if (w > 15)
+               w = 15;
+       if (w < 6)
+               w = 6;
+       return w;
+}
+
+
+bool InsetMathBinom::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       ScriptChanger dummy(mi.base);
+       cell(0).metrics(mi);
+       cell(1).metrics(mi);
+       dim.asc = cell(0).height() + 4 + 5;
+       dim.des = cell(1).height() + 4 - 5;
+       dim.wid = max(cell(0).width(), cell(1).width()) + 2 * dw() + 4;
+       metricsMarkers2(dim);
+       bool const changed = dim_ != dim;
+       dim_ = dim;
+       return changed;
+}
+
+
+void InsetMathBinom::draw(PainterInfo & pi, int x, int y) const
+{
+       int m = x + dim_.width() / 2;
+       ScriptChanger dummy(pi.base);
+       cell(0).draw(pi, m - cell(0).width() / 2, y - cell(0).descent() - 3 - 5);
+       cell(1).draw(pi, m - cell(1).width() / 2, y + cell(1).ascent()  + 3 - 5);
+       mathed_draw_deco(pi, x, y - dim_.ascent(), dw(), dim_.height(), from_ascii("("));
+       mathed_draw_deco(pi, x + dim_.width() - dw(), y - dim_.ascent(),
+               dw(), dim_.height(), from_ascii(")"));
+       drawMarkers2(pi, x, y);
+}
+
+
+bool InsetMathBinom::extraBraces() const
+{
+       return choose_;
+}
+
+
+void InsetMathBinom::write(WriteStream & os) const
+{
+       if (choose_)
+               os << '{' << cell(0) << " \\choose " << cell(1) << '}';
+       else
+               os << "\\binom{" << cell(0) << "}{" << cell(1) << '}';
+}
+
+
+void InsetMathBinom::normalize(NormalStream & os) const
+{
+       os << "[binom " << cell(0) << ' ' << cell(1) << ']';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathBoldSymbol.C b/src/mathed/InsetMathBoldSymbol.C
deleted file mode 100644 (file)
index 1d7c6f6..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * \file InsetMathBoldSymbol.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathBoldSymbol.h"
-#include "MathStream.h"
-#include "MathData.h"
-#include "LaTeXFeatures.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathBoldSymbol::InsetMathBoldSymbol()
-       : InsetMathNest(1)
-{}
-
-
-auto_ptr<InsetBase> InsetMathBoldSymbol::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathBoldSymbol(*this));
-}
-
-
-bool InsetMathBoldSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       //FontSetChanger dummy(mi.base, "mathbf");
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       ++dim.wid;  // for 'double stroke'
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathBoldSymbol::draw(PainterInfo & pi, int x, int y) const
-{
-       //FontSetChanger dummy(pi.base, "mathbf");
-       cell(0).draw(pi, x + 1, y);
-       cell(0).draw(pi, x + 2, y);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathBoldSymbol::metricsT(TextMetricsInfo const & mi, Dimension & /*dim*/) const
-{
-       cell(0).metricsT(mi, dim_);
-}
-
-
-void InsetMathBoldSymbol::drawT(TextPainter & pain, int x, int y) const
-{
-       cell(0).drawT(pain, x, y);
-}
-
-
-void InsetMathBoldSymbol::validate(LaTeXFeatures & features) const
-{
-       InsetMathNest::validate(features);
-       features.require("amssymb");
-}
-
-
-void InsetMathBoldSymbol::write(WriteStream & os) const
-{
-       os << "\\boldsymbol{" << cell(0) << "}";
-}
-
-
-void InsetMathBoldSymbol::infoize(odocstream & os) const
-{
-       os << "Boldsymbol ";
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathBoldSymbol.cpp b/src/mathed/InsetMathBoldSymbol.cpp
new file mode 100644 (file)
index 0000000..1d7c6f6
--- /dev/null
@@ -0,0 +1,89 @@
+/**
+ * \file InsetMathBoldSymbol.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathBoldSymbol.h"
+#include "MathStream.h"
+#include "MathData.h"
+#include "LaTeXFeatures.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathBoldSymbol::InsetMathBoldSymbol()
+       : InsetMathNest(1)
+{}
+
+
+auto_ptr<InsetBase> InsetMathBoldSymbol::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathBoldSymbol(*this));
+}
+
+
+bool InsetMathBoldSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       //FontSetChanger dummy(mi.base, "mathbf");
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       ++dim.wid;  // for 'double stroke'
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathBoldSymbol::draw(PainterInfo & pi, int x, int y) const
+{
+       //FontSetChanger dummy(pi.base, "mathbf");
+       cell(0).draw(pi, x + 1, y);
+       cell(0).draw(pi, x + 2, y);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathBoldSymbol::metricsT(TextMetricsInfo const & mi, Dimension & /*dim*/) const
+{
+       cell(0).metricsT(mi, dim_);
+}
+
+
+void InsetMathBoldSymbol::drawT(TextPainter & pain, int x, int y) const
+{
+       cell(0).drawT(pain, x, y);
+}
+
+
+void InsetMathBoldSymbol::validate(LaTeXFeatures & features) const
+{
+       InsetMathNest::validate(features);
+       features.require("amssymb");
+}
+
+
+void InsetMathBoldSymbol::write(WriteStream & os) const
+{
+       os << "\\boldsymbol{" << cell(0) << "}";
+}
+
+
+void InsetMathBoldSymbol::infoize(odocstream & os) const
+{
+       os << "Boldsymbol ";
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathBox.C b/src/mathed/InsetMathBox.C
deleted file mode 100644 (file)
index 0447e84..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * \file InsetMathBox.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathBox.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathBox::InsetMathBox(docstring const & name)
-       : InsetMathNest(1), name_(name)
-{}
-
-
-auto_ptr<InsetBase> InsetMathBox::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathBox(*this));
-}
-
-
-void InsetMathBox::write(WriteStream & os) const
-{
-       os << '\\' << name_ << '{' << cell(0) << '}';
-}
-
-
-void InsetMathBox::normalize(NormalStream & os) const
-{
-       os << '[' << name_ << ' ';
-       //text_->write(buffer(), os);
-       os << "] ";
-}
-
-
-bool InsetMathBox::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       FontSetChanger dummy(mi.base, "textnormal");
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathBox::draw(PainterInfo & pi, int x, int y) const
-{
-       FontSetChanger dummy(pi.base, "textnormal");
-       cell(0).draw(pi, x, y);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathBox::infoize(odocstream & os) const
-{
-       os << "Box: " << name_;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathBox.cpp b/src/mathed/InsetMathBox.cpp
new file mode 100644 (file)
index 0000000..0447e84
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * \file InsetMathBox.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathBox.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathBox::InsetMathBox(docstring const & name)
+       : InsetMathNest(1), name_(name)
+{}
+
+
+auto_ptr<InsetBase> InsetMathBox::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathBox(*this));
+}
+
+
+void InsetMathBox::write(WriteStream & os) const
+{
+       os << '\\' << name_ << '{' << cell(0) << '}';
+}
+
+
+void InsetMathBox::normalize(NormalStream & os) const
+{
+       os << '[' << name_ << ' ';
+       //text_->write(buffer(), os);
+       os << "] ";
+}
+
+
+bool InsetMathBox::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       FontSetChanger dummy(mi.base, "textnormal");
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathBox::draw(PainterInfo & pi, int x, int y) const
+{
+       FontSetChanger dummy(pi.base, "textnormal");
+       cell(0).draw(pi, x, y);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathBox::infoize(odocstream & os) const
+{
+       os << "Box: " << name_;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathBoxed.C b/src/mathed/InsetMathBoxed.C
deleted file mode 100644 (file)
index 2ff4888..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * \file InsetMathBoxed.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathBoxed.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "LaTeXFeatures.h"
-#include "LColor.h"
-
-#include "support/std_ostream.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathBoxed::InsetMathBoxed()
-       : InsetMathNest(1)
-{}
-
-
-auto_ptr<InsetBase> InsetMathBoxed::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathBoxed(*this));
-}
-
-
-bool InsetMathBoxed::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi, dim);
-       metricsMarkers2(dim, 3); // 1 pixel space, 1 frame, 1 space
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathBoxed::draw(PainterInfo & pi, int x, int y) const
-{
-       pi.pain.rectangle(x + 1, y - dim_.ascent() + 1,
-               dim_.width() - 2, dim_.height() - 2, LColor::foreground);
-       cell(0).draw(pi, x + 3, y);
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathBoxed::write(WriteStream & os) const
-{
-       os << "\\boxed{" << cell(0) << '}';
-}
-
-
-void InsetMathBoxed::normalize(NormalStream & os) const
-{
-       os << "[boxed " << cell(0) << ']';
-}
-
-
-void InsetMathBoxed::infoize(odocstream & os) const
-{
-       os << "Boxed: ";
-}
-
-
-void InsetMathBoxed::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathBoxed.cpp b/src/mathed/InsetMathBoxed.cpp
new file mode 100644 (file)
index 0000000..2ff4888
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+ * \file InsetMathBoxed.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathBoxed.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "LaTeXFeatures.h"
+#include "LColor.h"
+
+#include "support/std_ostream.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathBoxed::InsetMathBoxed()
+       : InsetMathNest(1)
+{}
+
+
+auto_ptr<InsetBase> InsetMathBoxed::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathBoxed(*this));
+}
+
+
+bool InsetMathBoxed::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi, dim);
+       metricsMarkers2(dim, 3); // 1 pixel space, 1 frame, 1 space
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathBoxed::draw(PainterInfo & pi, int x, int y) const
+{
+       pi.pain.rectangle(x + 1, y - dim_.ascent() + 1,
+               dim_.width() - 2, dim_.height() - 2, LColor::foreground);
+       cell(0).draw(pi, x + 3, y);
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathBoxed::write(WriteStream & os) const
+{
+       os << "\\boxed{" << cell(0) << '}';
+}
+
+
+void InsetMathBoxed::normalize(NormalStream & os) const
+{
+       os << "[boxed " << cell(0) << ']';
+}
+
+
+void InsetMathBoxed::infoize(odocstream & os) const
+{
+       os << "Boxed: ";
+}
+
+
+void InsetMathBoxed::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathBrace.C b/src/mathed/InsetMathBrace.C
deleted file mode 100644 (file)
index 54b00d8..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * \file InsetMathBrace.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathBrace.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "LColor.h"
-
-#include "frontends/FontMetrics.h"
-#include "frontends/Painter.h"
-
-#include "support/std_ostream.h"
-
-namespace lyx {
-
-using std::max;
-using std::auto_ptr;
-
-
-InsetMathBrace::InsetMathBrace()
-       : InsetMathNest(1)
-{}
-
-
-InsetMathBrace::InsetMathBrace(MathArray const & ar)
-       : InsetMathNest(1)
-{
-       cell(0) = ar;
-}
-
-
-auto_ptr<InsetBase> InsetMathBrace::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathBrace(*this));
-}
-
-
-bool InsetMathBrace::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi);
-       Dimension t = theFontMetrics(mi.base.font).dimension('{');
-       dim.asc = max(cell(0).ascent(), t.asc);
-       dim.des = max(cell(0).descent(), t.des);
-       dim.wid = cell(0).width() + 2 * t.wid;
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathBrace::draw(PainterInfo & pi, int x, int y) const
-{
-       LyXFont font = pi.base.font;
-       font.setColor(LColor::latex);
-       Dimension t = theFontMetrics(font).dimension('{');
-       pi.pain.text(x, y, '{', font);
-       cell(0).draw(pi, x + t.wid, y);
-       pi.pain.text(x + t.wid + cell(0).width(), y, '}', font);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathBrace::write(WriteStream & os) const
-{
-       os << '{' << cell(0) << '}';
-}
-
-
-void InsetMathBrace::normalize(NormalStream & os) const
-{
-       os << "[block " << cell(0) << ']';
-}
-
-
-void InsetMathBrace::maple(MapleStream & os) const
-{
-       os << cell(0);
-}
-
-
-void InsetMathBrace::octave(OctaveStream & os) const
-{
-       os << cell(0);
-}
-
-
-void InsetMathBrace::mathmlize(MathStream & os) const
-{
-       os << MTag("mrow") << cell(0) << ETag("mrow");
-}
-
-
-void InsetMathBrace::mathematica(MathematicaStream & os) const
-{
-       os << cell(0);
-}
-
-
-void InsetMathBrace::infoize(odocstream & os) const
-{
-       os << "Nested Block: ";
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathBrace.cpp b/src/mathed/InsetMathBrace.cpp
new file mode 100644 (file)
index 0000000..54b00d8
--- /dev/null
@@ -0,0 +1,117 @@
+/**
+ * \file InsetMathBrace.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathBrace.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "LColor.h"
+
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
+#include "support/std_ostream.h"
+
+namespace lyx {
+
+using std::max;
+using std::auto_ptr;
+
+
+InsetMathBrace::InsetMathBrace()
+       : InsetMathNest(1)
+{}
+
+
+InsetMathBrace::InsetMathBrace(MathArray const & ar)
+       : InsetMathNest(1)
+{
+       cell(0) = ar;
+}
+
+
+auto_ptr<InsetBase> InsetMathBrace::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathBrace(*this));
+}
+
+
+bool InsetMathBrace::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi);
+       Dimension t = theFontMetrics(mi.base.font).dimension('{');
+       dim.asc = max(cell(0).ascent(), t.asc);
+       dim.des = max(cell(0).descent(), t.des);
+       dim.wid = cell(0).width() + 2 * t.wid;
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathBrace::draw(PainterInfo & pi, int x, int y) const
+{
+       LyXFont font = pi.base.font;
+       font.setColor(LColor::latex);
+       Dimension t = theFontMetrics(font).dimension('{');
+       pi.pain.text(x, y, '{', font);
+       cell(0).draw(pi, x + t.wid, y);
+       pi.pain.text(x + t.wid + cell(0).width(), y, '}', font);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathBrace::write(WriteStream & os) const
+{
+       os << '{' << cell(0) << '}';
+}
+
+
+void InsetMathBrace::normalize(NormalStream & os) const
+{
+       os << "[block " << cell(0) << ']';
+}
+
+
+void InsetMathBrace::maple(MapleStream & os) const
+{
+       os << cell(0);
+}
+
+
+void InsetMathBrace::octave(OctaveStream & os) const
+{
+       os << cell(0);
+}
+
+
+void InsetMathBrace::mathmlize(MathStream & os) const
+{
+       os << MTag("mrow") << cell(0) << ETag("mrow");
+}
+
+
+void InsetMathBrace::mathematica(MathematicaStream & os) const
+{
+       os << cell(0);
+}
+
+
+void InsetMathBrace::infoize(odocstream & os) const
+{
+       os << "Nested Block: ";
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathCases.C b/src/mathed/InsetMathCases.C
deleted file mode 100644 (file)
index 8688629..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * \file InsetMathCases.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathCases.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "FuncStatus.h"
-#include "LaTeXFeatures.h"
-#include "support/std_ostream.h"
-#include "cursor.h"
-#include "funcrequest.h"
-#include "gettext.h"
-#include "undo.h"
-
-#include "support/lstrings.h"
-
-
-namespace lyx {
-
-using support::bformat;
-
-using std::endl;
-using std::max;
-using std::min;
-using std::swap;
-using std::auto_ptr;
-
-
-InsetMathCases::InsetMathCases(row_type n)
-       : InsetMathGrid(2, n, 'c', from_ascii("ll"))
-{}
-
-
-auto_ptr<InsetBase> InsetMathCases::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathCases(*this));
-}
-
-
-bool InsetMathCases::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       dim = dim_;
-       InsetMathGrid::metrics(mi);
-       dim_.wid += 8;
-
-       if (dim_ == dim)
-               return false;
-       dim = dim_;
-       return true;
-}
-
-
-void InsetMathCases::draw(PainterInfo & pi, int x, int y) const
-{
-       mathed_draw_deco(pi, x + 1, y - dim_.ascent(), 6, dim_.height(), from_ascii("{"));
-       InsetMathGrid::drawWithMargin(pi, x, y, 8, 0);
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathCases::doDispatch(LCursor & cur, FuncRequest & cmd)
-{
-       //lyxerr << "*** InsetMathCases: request: " << cmd << endl;
-       switch (cmd.action) {
-       case LFUN_TABULAR_FEATURE: {
-               recordUndo(cur);
-               docstring const & s = cmd.argument();
-               if (s == "add-vline-left" || s == "add-vline-right") {
-                       cur.undispatched();
-                       break;
-               }
-       }
-       default:
-               InsetMathGrid::doDispatch(cur, cmd);
-       }
-}
-
-
-bool InsetMathCases::getStatus(LCursor & cur, FuncRequest const & cmd,
-               FuncStatus & flag) const
-{
-       switch (cmd.action) {
-       case LFUN_TABULAR_FEATURE: {
-               docstring const & s = cmd.argument();
-               if (s == "add-vline-left" || s == "add-vline-right") {
-                       flag.enabled(false);
-                       flag.message(bformat(
-                               from_utf8(N_("No vertical grid lines in '%1$s'")),
-                               s));
-                       return true;
-               }
-       }
-       default:
-               return InsetMathGrid::getStatus(cur, cmd, flag);
-       }
-}
-
-
-void InsetMathCases::write(WriteStream & os) const
-{
-       if (os.fragile())
-               os << "\\protect";
-       os << "\\begin{cases}\n";
-       InsetMathGrid::write(os);
-       if (os.fragile())
-               os << "\\protect";
-       os << "\\end{cases}";
-}
-
-
-void InsetMathCases::normalize(NormalStream & os) const
-{
-       os << "[cases ";
-       InsetMathGrid::normalize(os);
-       os << ']';
-}
-
-
-void InsetMathCases::maple(MapleStream & os) const
-{
-       os << "cases(";
-       InsetMathGrid::maple(os);
-       os << ')';
-}
-
-
-void InsetMathCases::infoize(odocstream & os) const
-{
-       os << "Cases ";
-}
-
-
-void InsetMathCases::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-       InsetMathGrid::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathCases.cpp b/src/mathed/InsetMathCases.cpp
new file mode 100644 (file)
index 0000000..8688629
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ * \file InsetMathCases.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathCases.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "FuncStatus.h"
+#include "LaTeXFeatures.h"
+#include "support/std_ostream.h"
+#include "cursor.h"
+#include "funcrequest.h"
+#include "gettext.h"
+#include "undo.h"
+
+#include "support/lstrings.h"
+
+
+namespace lyx {
+
+using support::bformat;
+
+using std::endl;
+using std::max;
+using std::min;
+using std::swap;
+using std::auto_ptr;
+
+
+InsetMathCases::InsetMathCases(row_type n)
+       : InsetMathGrid(2, n, 'c', from_ascii("ll"))
+{}
+
+
+auto_ptr<InsetBase> InsetMathCases::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathCases(*this));
+}
+
+
+bool InsetMathCases::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       dim = dim_;
+       InsetMathGrid::metrics(mi);
+       dim_.wid += 8;
+
+       if (dim_ == dim)
+               return false;
+       dim = dim_;
+       return true;
+}
+
+
+void InsetMathCases::draw(PainterInfo & pi, int x, int y) const
+{
+       mathed_draw_deco(pi, x + 1, y - dim_.ascent(), 6, dim_.height(), from_ascii("{"));
+       InsetMathGrid::drawWithMargin(pi, x, y, 8, 0);
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathCases::doDispatch(LCursor & cur, FuncRequest & cmd)
+{
+       //lyxerr << "*** InsetMathCases: request: " << cmd << endl;
+       switch (cmd.action) {
+       case LFUN_TABULAR_FEATURE: {
+               recordUndo(cur);
+               docstring const & s = cmd.argument();
+               if (s == "add-vline-left" || s == "add-vline-right") {
+                       cur.undispatched();
+                       break;
+               }
+       }
+       default:
+               InsetMathGrid::doDispatch(cur, cmd);
+       }
+}
+
+
+bool InsetMathCases::getStatus(LCursor & cur, FuncRequest const & cmd,
+               FuncStatus & flag) const
+{
+       switch (cmd.action) {
+       case LFUN_TABULAR_FEATURE: {
+               docstring const & s = cmd.argument();
+               if (s == "add-vline-left" || s == "add-vline-right") {
+                       flag.enabled(false);
+                       flag.message(bformat(
+                               from_utf8(N_("No vertical grid lines in '%1$s'")),
+                               s));
+                       return true;
+               }
+       }
+       default:
+               return InsetMathGrid::getStatus(cur, cmd, flag);
+       }
+}
+
+
+void InsetMathCases::write(WriteStream & os) const
+{
+       if (os.fragile())
+               os << "\\protect";
+       os << "\\begin{cases}\n";
+       InsetMathGrid::write(os);
+       if (os.fragile())
+               os << "\\protect";
+       os << "\\end{cases}";
+}
+
+
+void InsetMathCases::normalize(NormalStream & os) const
+{
+       os << "[cases ";
+       InsetMathGrid::normalize(os);
+       os << ']';
+}
+
+
+void InsetMathCases::maple(MapleStream & os) const
+{
+       os << "cases(";
+       InsetMathGrid::maple(os);
+       os << ')';
+}
+
+
+void InsetMathCases::infoize(odocstream & os) const
+{
+       os << "Cases ";
+}
+
+
+void InsetMathCases::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+       InsetMathGrid::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathChar.C b/src/mathed/InsetMathChar.C
deleted file mode 100644 (file)
index 0baad6a..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * \file InsetMathChar.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathChar.h"
-#include "MathSupport.h"
-#include "MathStream.h"
-
-#include "debug.h"
-#include "dimension.h"
-#include "support/lstrings.h"
-#include "TextPainter.h"
-
-#include "frontends/FontMetrics.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-extern bool has_math_fonts;
-
-namespace {
-
-       bool isBinaryOp(char_type c)
-       {
-               return support::contains("+-<>=/*", static_cast<char>(c));
-       }
-
-
-       bool slanted(char_type c)
-       {
-               return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
-       }
-
-}
-
-
-InsetMathChar::InsetMathChar(char_type c)
-       : char_(c), kerning_(0)
-{}
-
-
-
-auto_ptr<InsetBase> InsetMathChar::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathChar(*this));
-}
-
-
-bool InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       if (mi.base.font == font_cache_) {
-               dim = dim_;
-               return false;
-       }
-       font_cache_ = mi.base.font;
-
-#if 1
-       if (char_ == '=' && has_math_fonts) {
-               FontSetChanger dummy(mi.base, "cmr");
-               dim = theFontMetrics(mi.base.font).dimension(char_);
-       } else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
-               FontSetChanger dummy(mi.base, "cmm");
-               dim = theFontMetrics(mi.base.font).dimension(char_);
-       } else if (!slanted(char_) && mi.base.fontname == "mathnormal") {
-               ShapeChanger dummy(mi.base.font, LyXFont::UP_SHAPE);
-               dim = theFontMetrics(mi.base.font).dimension(char_);
-       } else {
-               frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
-               dim = fm.dimension(char_);
-               kerning_ = fm.rbearing(char_) - dim.wid;
-       }
-       int const em = mathed_char_width(mi.base.font, 'M');
-       if (isBinaryOp(char_))
-               dim.wid += static_cast<int>(0.5*em+0.5);
-       else if (char_ == '\'')
-               dim.wid += static_cast<int>(0.1667*em+0.5);
-#else
-       whichFont(font_, code_, mi);
-       dim = theFontMetrics(font_).dimension(char_);
-       if (isBinaryOp(char_, code_))
-               dim.wid += 2 * theFontMetrics(font_).width(' ');
-       lyxerr << "InsetMathChar::metrics: " << dim << endl;
-#endif
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathChar::draw(PainterInfo & pi, int x, int y) const
-{
-       //lyxerr << "drawing '" << char_ << "' font: " << pi.base.fontname << endl;
-       int const em = mathed_char_width(pi.base.font, 'M');
-       if (isBinaryOp(char_))
-               x += static_cast<int>(0.25*em+0.5);
-       else if (char_ == '\'')
-               x += static_cast<int>(0.0833*em+0.5);
-#if 1
-       if (char_ == '=' && has_math_fonts) {
-               FontSetChanger dummy(pi.base, "cmr");
-               pi.draw(x, y, char_);
-       } else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
-               FontSetChanger dummy(pi.base, "cmm");
-               pi.draw(x, y, char_);
-       } else if (!slanted(char_) && pi.base.fontname == "mathnormal") {
-               ShapeChanger dummy(pi.base.font, LyXFont::UP_SHAPE);
-               pi.draw(x, y, char_);
-       } else {
-               pi.draw(x, y, char_);
-       }
-#else
-       drawChar(pain, font_, x, y, char_);
-#endif
-}
-
-
-void InsetMathChar::metricsT(TextMetricsInfo const &, Dimension & dim) const
-{
-       dim.wid = 1;
-       dim.asc = 1;
-       dim.des = 0;
-}
-
-
-void InsetMathChar::drawT(TextPainter & pain, int x, int y) const
-{
-       //lyxerr << "drawing text '" << char_ << "' code: " << code_ << endl;
-       pain.draw(x, y, char_);
-}
-
-
-void InsetMathChar::write(WriteStream & os) const
-{
-       os.os().put(char_);
-}
-
-
-void InsetMathChar::normalize(NormalStream & os) const
-{
-       os << "[char ";
-       os.os().put(char_);
-       os << " mathalpha]";
-}
-
-
-void InsetMathChar::octave(OctaveStream & os) const
-{
-       os.os().put(char_);
-}
-
-
-void InsetMathChar::mathmlize(MathStream & ms) const
-{
-       switch (char_) {
-               case '<': ms << "&lt;"; break;
-               case '>': ms << "&gt;"; break;
-               case '&': ms << "&amp;"; break;
-               default: ms.os().put(char_); break;
-       }
-}
-
-
-bool InsetMathChar::isRelOp() const
-{
-       return char_ == '=' || char_ == '<' || char_ == '>';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathChar.cpp b/src/mathed/InsetMathChar.cpp
new file mode 100644 (file)
index 0000000..0baad6a
--- /dev/null
@@ -0,0 +1,179 @@
+/**
+ * \file InsetMathChar.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathChar.h"
+#include "MathSupport.h"
+#include "MathStream.h"
+
+#include "debug.h"
+#include "dimension.h"
+#include "support/lstrings.h"
+#include "TextPainter.h"
+
+#include "frontends/FontMetrics.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+extern bool has_math_fonts;
+
+namespace {
+
+       bool isBinaryOp(char_type c)
+       {
+               return support::contains("+-<>=/*", static_cast<char>(c));
+       }
+
+
+       bool slanted(char_type c)
+       {
+               return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
+       }
+
+}
+
+
+InsetMathChar::InsetMathChar(char_type c)
+       : char_(c), kerning_(0)
+{}
+
+
+
+auto_ptr<InsetBase> InsetMathChar::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathChar(*this));
+}
+
+
+bool InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (mi.base.font == font_cache_) {
+               dim = dim_;
+               return false;
+       }
+       font_cache_ = mi.base.font;
+
+#if 1
+       if (char_ == '=' && has_math_fonts) {
+               FontSetChanger dummy(mi.base, "cmr");
+               dim = theFontMetrics(mi.base.font).dimension(char_);
+       } else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
+               FontSetChanger dummy(mi.base, "cmm");
+               dim = theFontMetrics(mi.base.font).dimension(char_);
+       } else if (!slanted(char_) && mi.base.fontname == "mathnormal") {
+               ShapeChanger dummy(mi.base.font, LyXFont::UP_SHAPE);
+               dim = theFontMetrics(mi.base.font).dimension(char_);
+       } else {
+               frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
+               dim = fm.dimension(char_);
+               kerning_ = fm.rbearing(char_) - dim.wid;
+       }
+       int const em = mathed_char_width(mi.base.font, 'M');
+       if (isBinaryOp(char_))
+               dim.wid += static_cast<int>(0.5*em+0.5);
+       else if (char_ == '\'')
+               dim.wid += static_cast<int>(0.1667*em+0.5);
+#else
+       whichFont(font_, code_, mi);
+       dim = theFontMetrics(font_).dimension(char_);
+       if (isBinaryOp(char_, code_))
+               dim.wid += 2 * theFontMetrics(font_).width(' ');
+       lyxerr << "InsetMathChar::metrics: " << dim << endl;
+#endif
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathChar::draw(PainterInfo & pi, int x, int y) const
+{
+       //lyxerr << "drawing '" << char_ << "' font: " << pi.base.fontname << endl;
+       int const em = mathed_char_width(pi.base.font, 'M');
+       if (isBinaryOp(char_))
+               x += static_cast<int>(0.25*em+0.5);
+       else if (char_ == '\'')
+               x += static_cast<int>(0.0833*em+0.5);
+#if 1
+       if (char_ == '=' && has_math_fonts) {
+               FontSetChanger dummy(pi.base, "cmr");
+               pi.draw(x, y, char_);
+       } else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
+               FontSetChanger dummy(pi.base, "cmm");
+               pi.draw(x, y, char_);
+       } else if (!slanted(char_) && pi.base.fontname == "mathnormal") {
+               ShapeChanger dummy(pi.base.font, LyXFont::UP_SHAPE);
+               pi.draw(x, y, char_);
+       } else {
+               pi.draw(x, y, char_);
+       }
+#else
+       drawChar(pain, font_, x, y, char_);
+#endif
+}
+
+
+void InsetMathChar::metricsT(TextMetricsInfo const &, Dimension & dim) const
+{
+       dim.wid = 1;
+       dim.asc = 1;
+       dim.des = 0;
+}
+
+
+void InsetMathChar::drawT(TextPainter & pain, int x, int y) const
+{
+       //lyxerr << "drawing text '" << char_ << "' code: " << code_ << endl;
+       pain.draw(x, y, char_);
+}
+
+
+void InsetMathChar::write(WriteStream & os) const
+{
+       os.os().put(char_);
+}
+
+
+void InsetMathChar::normalize(NormalStream & os) const
+{
+       os << "[char ";
+       os.os().put(char_);
+       os << " mathalpha]";
+}
+
+
+void InsetMathChar::octave(OctaveStream & os) const
+{
+       os.os().put(char_);
+}
+
+
+void InsetMathChar::mathmlize(MathStream & ms) const
+{
+       switch (char_) {
+               case '<': ms << "&lt;"; break;
+               case '>': ms << "&gt;"; break;
+               case '&': ms << "&amp;"; break;
+               default: ms.os().put(char_); break;
+       }
+}
+
+
+bool InsetMathChar::isRelOp() const
+{
+       return char_ == '=' || char_ == '<' || char_ == '>';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathColor.C b/src/mathed/InsetMathColor.C
deleted file mode 100644 (file)
index c3358bf..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * \file InsetMathColor.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathColor.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "LaTeXFeatures.h"
-
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-using std::string;
-
-InsetMathColor::InsetMathColor(bool oldstyle, LColor_color const & color)
-       : InsetMathNest(1), oldstyle_(oldstyle),
-         color_(from_utf8(lcolor.getLaTeXName(color)))
-{}
-
-
-InsetMathColor::InsetMathColor(bool oldstyle, docstring const & color)
-       : InsetMathNest(1), oldstyle_(oldstyle), color_(color)
-{}
-
-
-auto_ptr<InsetBase> InsetMathColor::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathColor(*this));
-}
-
-
-bool InsetMathColor::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathColor::draw(PainterInfo & pi, int x, int y) const
-{
-       LColor_color origcol = pi.base.font.color();
-       pi.base.font.setColor(lcolor.getFromLaTeXName(to_utf8(color_)));
-       cell(0).draw(pi, x + 1, y);
-       pi.base.font.setColor(origcol);
-       drawMarkers(pi, x, y);
-       setPosCache(pi, x, y);
-}
-
-
-/// color "none" (reset to default) needs special treatment
-static bool normalcolor(docstring const & color)
-{
-       return color == "none";
-}
-
-
-void InsetMathColor::validate(LaTeXFeatures & features) const
-{
-       InsetMathNest::validate(features);
-       if (!normalcolor(color_))
-               features.require("color");
-}
-
-
-void InsetMathColor::write(WriteStream & os) const
-{
-       if (normalcolor(color_))
-               // reset to default color inside another color inset
-               os << "{\\normalcolor " << cell(0) << '}';
-       else if (oldstyle_)
-               os << "{\\color{" << color_ << '}' << cell(0) << '}';
-       else
-               os << "\\textcolor{" << color_ << "}{" << cell(0) << '}';
-}
-
-
-void InsetMathColor::normalize(NormalStream & os) const
-{
-       os << "[color " << color_ << ' ' << cell(0) << ']';
-}
-
-
-void InsetMathColor::infoize(odocstream & os) const
-{
-       os << "Color: " << color_;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathColor.cpp b/src/mathed/InsetMathColor.cpp
new file mode 100644 (file)
index 0000000..c3358bf
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * \file InsetMathColor.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathColor.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "LaTeXFeatures.h"
+
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+using std::string;
+
+InsetMathColor::InsetMathColor(bool oldstyle, LColor_color const & color)
+       : InsetMathNest(1), oldstyle_(oldstyle),
+         color_(from_utf8(lcolor.getLaTeXName(color)))
+{}
+
+
+InsetMathColor::InsetMathColor(bool oldstyle, docstring const & color)
+       : InsetMathNest(1), oldstyle_(oldstyle), color_(color)
+{}
+
+
+auto_ptr<InsetBase> InsetMathColor::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathColor(*this));
+}
+
+
+bool InsetMathColor::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathColor::draw(PainterInfo & pi, int x, int y) const
+{
+       LColor_color origcol = pi.base.font.color();
+       pi.base.font.setColor(lcolor.getFromLaTeXName(to_utf8(color_)));
+       cell(0).draw(pi, x + 1, y);
+       pi.base.font.setColor(origcol);
+       drawMarkers(pi, x, y);
+       setPosCache(pi, x, y);
+}
+
+
+/// color "none" (reset to default) needs special treatment
+static bool normalcolor(docstring const & color)
+{
+       return color == "none";
+}
+
+
+void InsetMathColor::validate(LaTeXFeatures & features) const
+{
+       InsetMathNest::validate(features);
+       if (!normalcolor(color_))
+               features.require("color");
+}
+
+
+void InsetMathColor::write(WriteStream & os) const
+{
+       if (normalcolor(color_))
+               // reset to default color inside another color inset
+               os << "{\\normalcolor " << cell(0) << '}';
+       else if (oldstyle_)
+               os << "{\\color{" << color_ << '}' << cell(0) << '}';
+       else
+               os << "\\textcolor{" << color_ << "}{" << cell(0) << '}';
+}
+
+
+void InsetMathColor::normalize(NormalStream & os) const
+{
+       os << "[color " << color_ << ' ' << cell(0) << ']';
+}
+
+
+void InsetMathColor::infoize(odocstream & os) const
+{
+       os << "Color: " << color_;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathCommand.C b/src/mathed/InsetMathCommand.C
deleted file mode 100644 (file)
index 076096e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * \file InsetMathCommand.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathCommand.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "dispatchresult.h"
-#include "funcrequest.h"
-
-#include <sstream>
-
-
-namespace lyx {
-
-using std::auto_ptr;
-using std::string;
-
-CommandInset::CommandInset(docstring const & name)
-       : InsetMathNest(2), name_(name), set_label_(false)
-{
-       lock_ = true;
-}
-
-
-auto_ptr<InsetBase> CommandInset::doClone() const
-{
-       return auto_ptr<InsetBase>(new CommandInset(*this));
-}
-
-
-bool CommandInset::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       if (!set_label_) {
-               set_label_ = true;
-               button_.update(screenLabel(), true);
-       }
-       button_.metrics(mi, dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-InsetBase * CommandInset::editXY(LCursor & cur, int /*x*/, int /*y*/)
-{
-       edit(cur, true);
-       return this;
-}
-
-
-void CommandInset::draw(PainterInfo & pi, int x, int y) const
-{
-       button_.draw(pi, x, y);
-       setPosCache(pi, x, y);
-}
-
-
-void CommandInset::write(WriteStream & os) const
-{
-       os << '\\' << name_.c_str();
-       if (cell(1).size())
-               os << '[' << cell(1) << ']';
-       os << '{' << cell(0) << '}';
-}
-
-
-docstring const CommandInset::screenLabel() const
-{
-       return name_;
-}
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathCommand.cpp b/src/mathed/InsetMathCommand.cpp
new file mode 100644 (file)
index 0000000..076096e
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * \file InsetMathCommand.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathCommand.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "dispatchresult.h"
+#include "funcrequest.h"
+
+#include <sstream>
+
+
+namespace lyx {
+
+using std::auto_ptr;
+using std::string;
+
+CommandInset::CommandInset(docstring const & name)
+       : InsetMathNest(2), name_(name), set_label_(false)
+{
+       lock_ = true;
+}
+
+
+auto_ptr<InsetBase> CommandInset::doClone() const
+{
+       return auto_ptr<InsetBase>(new CommandInset(*this));
+}
+
+
+bool CommandInset::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (!set_label_) {
+               set_label_ = true;
+               button_.update(screenLabel(), true);
+       }
+       button_.metrics(mi, dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+InsetBase * CommandInset::editXY(LCursor & cur, int /*x*/, int /*y*/)
+{
+       edit(cur, true);
+       return this;
+}
+
+
+void CommandInset::draw(PainterInfo & pi, int x, int y) const
+{
+       button_.draw(pi, x, y);
+       setPosCache(pi, x, y);
+}
+
+
+void CommandInset::write(WriteStream & os) const
+{
+       os << '\\' << name_.c_str();
+       if (cell(1).size())
+               os << '[' << cell(1) << ']';
+       os << '{' << cell(0) << '}';
+}
+
+
+docstring const CommandInset::screenLabel() const
+{
+       return name_;
+}
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathComment.C b/src/mathed/InsetMathComment.C
deleted file mode 100644 (file)
index ca0de54..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * \file InsetMathComment.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathComment.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathComment::InsetMathComment()
-       : InsetMathNest(1)
-{}
-
-
-InsetMathComment::InsetMathComment(docstring const & str)
-       : InsetMathNest(1)
-{
-       // FIXME UNICODE
-       asArray(str, cell(0));
-}
-
-
-auto_ptr<InsetBase> InsetMathComment::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathComment(*this));
-}
-
-
-bool InsetMathComment::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathComment::draw(PainterInfo & pi, int x, int y) const
-{
-       cell(0).draw(pi, x + 1, y);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathComment::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       cell(0).metricsT(mi, dim);
-}
-
-
-void InsetMathComment::drawT(TextPainter & pain, int x, int y) const
-{
-       cell(0).drawT(pain, x, y);
-}
-
-
-void InsetMathComment::write(WriteStream & os) const
-{
-       os << '%' << cell(0) << "\n";
-}
-
-
-void InsetMathComment::maple(MapleStream & os) const
-{
-       os << '#' << cell(0) << "\n";
-}
-
-
-void InsetMathComment::mathematica(MathematicaStream &) const
-{}
-
-
-void InsetMathComment::octave(OctaveStream &) const
-{}
-
-
-void InsetMathComment::mathmlize(MathStream & os) const
-{
-       os << MTag("comment") << cell(0) << cell(1) << ETag("comment");
-}
-
-
-void InsetMathComment::infoize(odocstream & os) const
-{
-       os << "Comment";
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathComment.cpp b/src/mathed/InsetMathComment.cpp
new file mode 100644 (file)
index 0000000..ca0de54
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * \file InsetMathComment.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathComment.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathComment::InsetMathComment()
+       : InsetMathNest(1)
+{}
+
+
+InsetMathComment::InsetMathComment(docstring const & str)
+       : InsetMathNest(1)
+{
+       // FIXME UNICODE
+       asArray(str, cell(0));
+}
+
+
+auto_ptr<InsetBase> InsetMathComment::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathComment(*this));
+}
+
+
+bool InsetMathComment::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathComment::draw(PainterInfo & pi, int x, int y) const
+{
+       cell(0).draw(pi, x + 1, y);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathComment::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       cell(0).metricsT(mi, dim);
+}
+
+
+void InsetMathComment::drawT(TextPainter & pain, int x, int y) const
+{
+       cell(0).drawT(pain, x, y);
+}
+
+
+void InsetMathComment::write(WriteStream & os) const
+{
+       os << '%' << cell(0) << "\n";
+}
+
+
+void InsetMathComment::maple(MapleStream & os) const
+{
+       os << '#' << cell(0) << "\n";
+}
+
+
+void InsetMathComment::mathematica(MathematicaStream &) const
+{}
+
+
+void InsetMathComment::octave(OctaveStream &) const
+{}
+
+
+void InsetMathComment::mathmlize(MathStream & os) const
+{
+       os << MTag("comment") << cell(0) << cell(1) << ETag("comment");
+}
+
+
+void InsetMathComment::infoize(odocstream & os) const
+{
+       os << "Comment";
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathDFrac.C b/src/mathed/InsetMathDFrac.C
deleted file mode 100644 (file)
index 5dded13..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * \file InsetMathDFrac.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathDFrac.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "LaTeXFeatures.h"
-#include "LColor.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-
-using std::string;
-using std::max;
-using std::auto_ptr;
-
-
-InsetMathDFrac::InsetMathDFrac()
-       : InsetMathFrac()
-{}
-
-
-auto_ptr<InsetBase> InsetMathDFrac::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathDFrac(*this));
-}
-
-
-bool InsetMathDFrac::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi);
-       cell(1).metrics(mi);
-       dim.wid = max(cell(0).width(), cell(1).width()) + 2;
-       dim.asc = cell(0).height() + 2 + 5;
-       dim.des = cell(1).height() + 2 - 5;
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathDFrac::draw(PainterInfo & pi, int x, int y) const
-{
-       int m = x + dim_.wid / 2;
-       cell(0).draw(pi, m - cell(0).width() / 2, y - cell(0).descent() - 2 - 5);
-       cell(1).draw(pi, m - cell(1).width() / 2, y + cell(1).ascent()  + 2 - 5);
-       pi.pain.line(x + 1, y - 5, x + dim_.wid - 2, y - 5, LColor::math);
-       setPosCache(pi, x, y);
-}
-
-
-docstring InsetMathDFrac::name() const
-{
-       return from_ascii("dfrac");
-}
-
-
-void InsetMathDFrac::mathmlize(MathStream & os) const
-{
-       os << MTag("mdfrac") << cell(0) << cell(1) << ETag("mdfrac");
-}
-
-
-void InsetMathDFrac::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-       InsetMathNest::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathDFrac.cpp b/src/mathed/InsetMathDFrac.cpp
new file mode 100644 (file)
index 0000000..5dded13
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+ * \file InsetMathDFrac.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathDFrac.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "LaTeXFeatures.h"
+#include "LColor.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+
+using std::string;
+using std::max;
+using std::auto_ptr;
+
+
+InsetMathDFrac::InsetMathDFrac()
+       : InsetMathFrac()
+{}
+
+
+auto_ptr<InsetBase> InsetMathDFrac::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathDFrac(*this));
+}
+
+
+bool InsetMathDFrac::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi);
+       cell(1).metrics(mi);
+       dim.wid = max(cell(0).width(), cell(1).width()) + 2;
+       dim.asc = cell(0).height() + 2 + 5;
+       dim.des = cell(1).height() + 2 - 5;
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathDFrac::draw(PainterInfo & pi, int x, int y) const
+{
+       int m = x + dim_.wid / 2;
+       cell(0).draw(pi, m - cell(0).width() / 2, y - cell(0).descent() - 2 - 5);
+       cell(1).draw(pi, m - cell(1).width() / 2, y + cell(1).ascent()  + 2 - 5);
+       pi.pain.line(x + 1, y - 5, x + dim_.wid - 2, y - 5, LColor::math);
+       setPosCache(pi, x, y);
+}
+
+
+docstring InsetMathDFrac::name() const
+{
+       return from_ascii("dfrac");
+}
+
+
+void InsetMathDFrac::mathmlize(MathStream & os) const
+{
+       os << MTag("mdfrac") << cell(0) << cell(1) << ETag("mdfrac");
+}
+
+
+void InsetMathDFrac::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+       InsetMathNest::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathDecoration.C b/src/mathed/InsetMathDecoration.C
deleted file mode 100644 (file)
index f7a038b..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * \file InsetMathDecoration.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathDecoration.h"
-#include "MathData.h"
-#include "MathParser.h"
-#include "MathSupport.h"
-#include "MathStream.h"
-
-#include "LaTeXFeatures.h"
-#include "debug.h"
-
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-
-InsetMathDecoration::InsetMathDecoration(latexkeys const * key)
-       : InsetMathNest(1), key_(key)
-{
-//     lyxerr << " creating deco " << key->name << std::endl;
-}
-
-
-std::auto_ptr<InsetBase> InsetMathDecoration::doClone() const
-{
-       return std::auto_ptr<InsetBase>(new InsetMathDecoration(*this));
-}
-
-
-bool InsetMathDecoration::upper() const
-{
-       return key_->name.substr(0, 5) != "under";
-}
-
-
-bool InsetMathDecoration::isScriptable() const
-{
-       return
-                       key_->name == "overbrace" ||
-                       key_->name == "underbrace" ||
-                       key_->name == "overleftarrow" ||
-                       key_->name == "overrightarrow" ||
-                       key_->name == "overleftrightarrow" ||
-                       key_->name == "underleftarrow" ||
-                       key_->name == "underrightarrow" ||
-                       key_->name == "underleftrightarrow";
-}
-
-
-bool InsetMathDecoration::protect() const
-{
-       return
-                       key_->name == "overbrace" ||
-                       key_->name == "underbrace" ||
-                       key_->name == "overleftarrow" ||
-                       key_->name == "overrightarrow" ||
-                       key_->name == "overleftrightarrow" ||
-                       key_->name == "underleftarrow" ||
-                       key_->name == "underrightarrow" ||
-                       key_->name == "underleftrightarrow";
-}
-
-
-bool InsetMathDecoration::wide() const
-{
-       return
-                       key_->name == "overline" ||
-                       key_->name == "underline" ||
-                       key_->name == "overbrace" ||
-                       key_->name == "underbrace" ||
-                       key_->name == "overleftarrow" ||
-                       key_->name == "overrightarrow" ||
-                       key_->name == "overleftrightarrow" ||
-                       key_->name == "widehat" ||
-                       key_->name == "widetilde" ||
-                       key_->name == "underleftarrow" ||
-                       key_->name == "underrightarrow" ||
-                       key_->name == "underleftrightarrow";
-}
-
-
-bool InsetMathDecoration::ams() const
-{
-       return
-                       key_->name == "overleftrightarrow" ||
-                       key_->name == "underleftarrow" ||
-                       key_->name == "underrightarrow" ||
-                       key_->name == "underleftrightarrow";
-}
-
-
-bool InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi, dim);
-
-       dh_  = 6; //mathed_char_height(LM_TC_VAR, mi, 'I', ascent_, descent_);
-       dw_  = 6; //mathed_char_width(LM_TC_VAR, mi, 'x');
-
-       if (upper()) {
-               dy_ = -dim.asc - dh_;
-               dim.asc += dh_ + 1;
-       } else {
-               dy_ = dim.des + 1;
-               dim.des += dh_ + 2;
-       }
-
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathDecoration::draw(PainterInfo & pi, int x, int y) const
-{
-       cell(0).draw(pi, x + 1, y);
-       if (wide())
-               mathed_draw_deco(pi, x + 1, y + dy_, cell(0).width(), dh_, key_->name);
-       else
-               mathed_draw_deco(pi, x + 1 + (cell(0).width() - dw_) / 2,
-                       y + dy_, dw_, dh_, key_->name);
-       drawMarkers(pi, x, y);
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathDecoration::write(WriteStream & os) const
-{
-       if (os.fragile() && protect())
-               os << "\\protect";
-       os << '\\' << key_->name << '{' << cell(0) << '}';
-}
-
-
-void InsetMathDecoration::normalize(NormalStream & os) const
-{
-       os << "[deco " << key_->name << ' ' <<  cell(0) << ']';
-}
-
-
-void InsetMathDecoration::infoize(odocstream & os) const
-{
-       os << "Deco: " << key_->name;
-}
-
-
-void InsetMathDecoration::validate(LaTeXFeatures & features) const
-{
-       if (ams())
-               features.require("amsmath");
-       InsetMathNest::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathDecoration.cpp b/src/mathed/InsetMathDecoration.cpp
new file mode 100644 (file)
index 0000000..f7a038b
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * \file InsetMathDecoration.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathDecoration.h"
+#include "MathData.h"
+#include "MathParser.h"
+#include "MathSupport.h"
+#include "MathStream.h"
+
+#include "LaTeXFeatures.h"
+#include "debug.h"
+
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+
+InsetMathDecoration::InsetMathDecoration(latexkeys const * key)
+       : InsetMathNest(1), key_(key)
+{
+//     lyxerr << " creating deco " << key->name << std::endl;
+}
+
+
+std::auto_ptr<InsetBase> InsetMathDecoration::doClone() const
+{
+       return std::auto_ptr<InsetBase>(new InsetMathDecoration(*this));
+}
+
+
+bool InsetMathDecoration::upper() const
+{
+       return key_->name.substr(0, 5) != "under";
+}
+
+
+bool InsetMathDecoration::isScriptable() const
+{
+       return
+                       key_->name == "overbrace" ||
+                       key_->name == "underbrace" ||
+                       key_->name == "overleftarrow" ||
+                       key_->name == "overrightarrow" ||
+                       key_->name == "overleftrightarrow" ||
+                       key_->name == "underleftarrow" ||
+                       key_->name == "underrightarrow" ||
+                       key_->name == "underleftrightarrow";
+}
+
+
+bool InsetMathDecoration::protect() const
+{
+       return
+                       key_->name == "overbrace" ||
+                       key_->name == "underbrace" ||
+                       key_->name == "overleftarrow" ||
+                       key_->name == "overrightarrow" ||
+                       key_->name == "overleftrightarrow" ||
+                       key_->name == "underleftarrow" ||
+                       key_->name == "underrightarrow" ||
+                       key_->name == "underleftrightarrow";
+}
+
+
+bool InsetMathDecoration::wide() const
+{
+       return
+                       key_->name == "overline" ||
+                       key_->name == "underline" ||
+                       key_->name == "overbrace" ||
+                       key_->name == "underbrace" ||
+                       key_->name == "overleftarrow" ||
+                       key_->name == "overrightarrow" ||
+                       key_->name == "overleftrightarrow" ||
+                       key_->name == "widehat" ||
+                       key_->name == "widetilde" ||
+                       key_->name == "underleftarrow" ||
+                       key_->name == "underrightarrow" ||
+                       key_->name == "underleftrightarrow";
+}
+
+
+bool InsetMathDecoration::ams() const
+{
+       return
+                       key_->name == "overleftrightarrow" ||
+                       key_->name == "underleftarrow" ||
+                       key_->name == "underrightarrow" ||
+                       key_->name == "underleftrightarrow";
+}
+
+
+bool InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi, dim);
+
+       dh_  = 6; //mathed_char_height(LM_TC_VAR, mi, 'I', ascent_, descent_);
+       dw_  = 6; //mathed_char_width(LM_TC_VAR, mi, 'x');
+
+       if (upper()) {
+               dy_ = -dim.asc - dh_;
+               dim.asc += dh_ + 1;
+       } else {
+               dy_ = dim.des + 1;
+               dim.des += dh_ + 2;
+       }
+
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathDecoration::draw(PainterInfo & pi, int x, int y) const
+{
+       cell(0).draw(pi, x + 1, y);
+       if (wide())
+               mathed_draw_deco(pi, x + 1, y + dy_, cell(0).width(), dh_, key_->name);
+       else
+               mathed_draw_deco(pi, x + 1 + (cell(0).width() - dw_) / 2,
+                       y + dy_, dw_, dh_, key_->name);
+       drawMarkers(pi, x, y);
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathDecoration::write(WriteStream & os) const
+{
+       if (os.fragile() && protect())
+               os << "\\protect";
+       os << '\\' << key_->name << '{' << cell(0) << '}';
+}
+
+
+void InsetMathDecoration::normalize(NormalStream & os) const
+{
+       os << "[deco " << key_->name << ' ' <<  cell(0) << ']';
+}
+
+
+void InsetMathDecoration::infoize(odocstream & os) const
+{
+       os << "Deco: " << key_->name;
+}
+
+
+void InsetMathDecoration::validate(LaTeXFeatures & features) const
+{
+       if (ams())
+               features.require("amsmath");
+       InsetMathNest::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathDelim.C b/src/mathed/InsetMathDelim.C
deleted file mode 100644 (file)
index a0f6aaa..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- * \file InsetMathDelim.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathDelim.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-
-#include "frontends/FontMetrics.h"
-
-namespace lyx {
-
-
-using std::string;
-using std::max;
-using std::auto_ptr;
-
-
-static docstring convertDelimToLatexName(docstring const & name)
-{
-       if (name.size() == 1) {
-               char_type const c = name[0];
-               if (c == '<' || c == '(' || c == '[' || c == '.' 
-                   || c == '>' || c == ')' || c == ']' || c == '/' || c == '|')
-                       return name;
-       }
-       return '\\' + name + ' ';
-}
-
-
-InsetMathDelim::InsetMathDelim(docstring const & l, docstring const & r)
-       : InsetMathNest(1), left_(l), right_(r)
-{}
-
-
-InsetMathDelim::InsetMathDelim
-               (docstring const & l, docstring const & r, MathArray const & ar)
-       : InsetMathNest(1), left_(l), right_(r)
-{
-       cell(0) = ar;
-}
-
-
-auto_ptr<InsetBase> InsetMathDelim::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathDelim(*this));
-}
-
-
-void InsetMathDelim::write(WriteStream & os) const
-{
-       os << "\\left" << convertDelimToLatexName(left_) << cell(0)
-          << "\\right" << convertDelimToLatexName(right_);
-}
-
-
-void InsetMathDelim::normalize(NormalStream & os) const
-{
-       os << "[delim " << convertDelimToLatexName(left_) << ' '
-          << convertDelimToLatexName(right_) << ' ' << cell(0) << ']';
-}
-
-
-bool InsetMathDelim::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi);
-       Dimension t = theFontMetrics(mi.base.font).dimension('I');
-       int h0 = (t.asc + t.des) / 2;
-       int a0 = max(cell(0).ascent(), t.asc)   - h0;
-       int d0 = max(cell(0).descent(), t.des)  + h0;
-       dw_ = cell(0).height() / 5;
-       if (dw_ > 8)
-               dw_ = 8;
-       if (dw_ < 4)
-               dw_ = 4;
-       dim.wid = cell(0).width() + 2 * dw_ + 8;
-       dim.asc = max(a0, d0) + h0;
-       dim.des = max(a0, d0) - h0;
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathDelim::draw(PainterInfo & pi, int x, int y) const
-{
-       int const b = y - dim_.asc;
-       cell(0).draw(pi, x + dw_ + 4, y);
-       mathed_draw_deco(pi, x + 4, b, dw_, dim_.height(), left_);
-       mathed_draw_deco(pi, x + dim_.width() - dw_ - 4,
-               b, dw_, dim_.height(), right_);
-       setPosCache(pi, x, y);
-}
-
-
-bool InsetMathDelim::isParenthesis() const
-{
-       return left_ == "(" && right_ == ")";
-}
-
-
-bool InsetMathDelim::isBrackets() const
-{
-       return left_ == "[" && right_ == "]";
-}
-
-
-bool InsetMathDelim::isAbs() const
-{
-       return left_ == "|" && right_ == "|";
-}
-
-
-void InsetMathDelim::maple(MapleStream & os) const
-{
-       if (isAbs()) {
-               if (cell(0).size() == 1 && cell(0).front()->asMatrixInset())
-                       os << "linalg[det](" << cell(0) << ')';
-               else
-                       os << "abs(" << cell(0) << ')';
-       }
-       else
-               os << left_ << cell(0) << right_;
-}
-
-
-void InsetMathDelim::maxima(MaximaStream & os) const
-{
-       if (isAbs()) {
-               if (cell(0).size() == 1 && cell(0).front()->asMatrixInset())
-                       os << "determinant(" << cell(0) << ')';
-               else
-                       os << "abs(" << cell(0) << ')';
-       }
-       else
-               os << left_ << cell(0) << right_;
-}
-
-
-void InsetMathDelim::mathematica(MathematicaStream & os) const
-{
-       if (isAbs()) {
-               if (cell(0).size() == 1 && cell(0).front()->asMatrixInset())
-                       os << "Det" << cell(0) << ']';
-               else
-                       os << "Abs[" << cell(0) << ']';
-       }
-       else
-               os << left_ << cell(0) << right_;
-}
-
-
-void InsetMathDelim::mathmlize(MathStream & os) const
-{
-       os << "<fenced open=\"" << left_ << "\" close=\""
-               << right_ << "\">" << cell(0) << "</fenced>";
-}
-
-
-void InsetMathDelim::octave(OctaveStream & os) const
-{
-       if (isAbs())
-               os << "det(" << cell(0) << ')';
-       else
-               os << left_ << cell(0) << right_;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathDelim.cpp b/src/mathed/InsetMathDelim.cpp
new file mode 100644 (file)
index 0000000..a0f6aaa
--- /dev/null
@@ -0,0 +1,181 @@
+/**
+ * \file InsetMathDelim.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathDelim.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+
+#include "frontends/FontMetrics.h"
+
+namespace lyx {
+
+
+using std::string;
+using std::max;
+using std::auto_ptr;
+
+
+static docstring convertDelimToLatexName(docstring const & name)
+{
+       if (name.size() == 1) {
+               char_type const c = name[0];
+               if (c == '<' || c == '(' || c == '[' || c == '.' 
+                   || c == '>' || c == ')' || c == ']' || c == '/' || c == '|')
+                       return name;
+       }
+       return '\\' + name + ' ';
+}
+
+
+InsetMathDelim::InsetMathDelim(docstring const & l, docstring const & r)
+       : InsetMathNest(1), left_(l), right_(r)
+{}
+
+
+InsetMathDelim::InsetMathDelim
+               (docstring const & l, docstring const & r, MathArray const & ar)
+       : InsetMathNest(1), left_(l), right_(r)
+{
+       cell(0) = ar;
+}
+
+
+auto_ptr<InsetBase> InsetMathDelim::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathDelim(*this));
+}
+
+
+void InsetMathDelim::write(WriteStream & os) const
+{
+       os << "\\left" << convertDelimToLatexName(left_) << cell(0)
+          << "\\right" << convertDelimToLatexName(right_);
+}
+
+
+void InsetMathDelim::normalize(NormalStream & os) const
+{
+       os << "[delim " << convertDelimToLatexName(left_) << ' '
+          << convertDelimToLatexName(right_) << ' ' << cell(0) << ']';
+}
+
+
+bool InsetMathDelim::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi);
+       Dimension t = theFontMetrics(mi.base.font).dimension('I');
+       int h0 = (t.asc + t.des) / 2;
+       int a0 = max(cell(0).ascent(), t.asc)   - h0;
+       int d0 = max(cell(0).descent(), t.des)  + h0;
+       dw_ = cell(0).height() / 5;
+       if (dw_ > 8)
+               dw_ = 8;
+       if (dw_ < 4)
+               dw_ = 4;
+       dim.wid = cell(0).width() + 2 * dw_ + 8;
+       dim.asc = max(a0, d0) + h0;
+       dim.des = max(a0, d0) - h0;
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathDelim::draw(PainterInfo & pi, int x, int y) const
+{
+       int const b = y - dim_.asc;
+       cell(0).draw(pi, x + dw_ + 4, y);
+       mathed_draw_deco(pi, x + 4, b, dw_, dim_.height(), left_);
+       mathed_draw_deco(pi, x + dim_.width() - dw_ - 4,
+               b, dw_, dim_.height(), right_);
+       setPosCache(pi, x, y);
+}
+
+
+bool InsetMathDelim::isParenthesis() const
+{
+       return left_ == "(" && right_ == ")";
+}
+
+
+bool InsetMathDelim::isBrackets() const
+{
+       return left_ == "[" && right_ == "]";
+}
+
+
+bool InsetMathDelim::isAbs() const
+{
+       return left_ == "|" && right_ == "|";
+}
+
+
+void InsetMathDelim::maple(MapleStream & os) const
+{
+       if (isAbs()) {
+               if (cell(0).size() == 1 && cell(0).front()->asMatrixInset())
+                       os << "linalg[det](" << cell(0) << ')';
+               else
+                       os << "abs(" << cell(0) << ')';
+       }
+       else
+               os << left_ << cell(0) << right_;
+}
+
+
+void InsetMathDelim::maxima(MaximaStream & os) const
+{
+       if (isAbs()) {
+               if (cell(0).size() == 1 && cell(0).front()->asMatrixInset())
+                       os << "determinant(" << cell(0) << ')';
+               else
+                       os << "abs(" << cell(0) << ')';
+       }
+       else
+               os << left_ << cell(0) << right_;
+}
+
+
+void InsetMathDelim::mathematica(MathematicaStream & os) const
+{
+       if (isAbs()) {
+               if (cell(0).size() == 1 && cell(0).front()->asMatrixInset())
+                       os << "Det" << cell(0) << ']';
+               else
+                       os << "Abs[" << cell(0) << ']';
+       }
+       else
+               os << left_ << cell(0) << right_;
+}
+
+
+void InsetMathDelim::mathmlize(MathStream & os) const
+{
+       os << "<fenced open=\"" << left_ << "\" close=\""
+               << right_ << "\">" << cell(0) << "</fenced>";
+}
+
+
+void InsetMathDelim::octave(OctaveStream & os) const
+{
+       if (isAbs())
+               os << "det(" << cell(0) << ')';
+       else
+               os << left_ << cell(0) << right_;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathDiff.C b/src/mathed/InsetMathDiff.C
deleted file mode 100644 (file)
index 2f866d2..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * \file InsetMathDiff.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathDiff.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "debug.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-using std::endl;
-
-
-InsetMathDiff::InsetMathDiff()
-       : InsetMathNest(1)
-{}
-
-
-auto_ptr<InsetBase> InsetMathDiff::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathDiff(*this));
-}
-
-
-void InsetMathDiff::addDer(MathArray const & der)
-{
-       cells_.push_back(der);
-}
-
-
-void InsetMathDiff::normalize(NormalStream & os) const
-{
-       os << "[diff";
-       for (idx_type idx = 0; idx < nargs(); ++idx)
-               os << ' ' << cell(idx);
-       os << ']';
-}
-
-
-bool InsetMathDiff::metrics(MetricsInfo &, Dimension &) const
-{
-       lyxerr << "should not happen" << endl;
-       return true;
-}
-
-
-void InsetMathDiff::draw(PainterInfo &, int, int) const
-{
-       lyxerr << "should not happen" << endl;
-}
-
-
-void InsetMathDiff::maple(MapleStream & os) const
-{
-       os << "diff(";
-       for (idx_type idx = 0; idx < nargs(); ++idx) {
-               if (idx != 0)
-                       os << ',';
-               os << cell(idx);
-       }
-       os << ')';
-}
-
-
-void InsetMathDiff::maxima(MaximaStream & os) const
-{
-       os << "diff(";
-       for (idx_type idx = 0; idx < nargs(); ++idx) {
-               if (idx != 0)
-                       os << ',';
-               os << cell(idx);
-               if (idx != 0)
-                       os << ",1";
-       }
-       os << ')';
-}
-
-
-void InsetMathDiff::mathematica(MathematicaStream & os) const
-{
-       os << "D[";
-       for (idx_type idx = 0; idx < nargs(); ++idx) {
-               if (idx != 0)
-                       os << ',';
-               os << cell(idx);
-       }
-       os << ']';
-}
-
-
-void InsetMathDiff::mathmlize(MathStream & os) const
-{
-       os << "diff(";
-       for (idx_type idx = 0; idx < nargs(); ++idx) {
-               if (idx != 0)
-                       os << ',';
-               os << cell(idx);
-       }
-       os << ')';
-}
-
-
-void InsetMathDiff::write(WriteStream &) const
-{
-       lyxerr << "should not happen" << endl;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathDiff.cpp b/src/mathed/InsetMathDiff.cpp
new file mode 100644 (file)
index 0000000..2f866d2
--- /dev/null
@@ -0,0 +1,120 @@
+/**
+ * \file InsetMathDiff.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathDiff.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "debug.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+using std::endl;
+
+
+InsetMathDiff::InsetMathDiff()
+       : InsetMathNest(1)
+{}
+
+
+auto_ptr<InsetBase> InsetMathDiff::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathDiff(*this));
+}
+
+
+void InsetMathDiff::addDer(MathArray const & der)
+{
+       cells_.push_back(der);
+}
+
+
+void InsetMathDiff::normalize(NormalStream & os) const
+{
+       os << "[diff";
+       for (idx_type idx = 0; idx < nargs(); ++idx)
+               os << ' ' << cell(idx);
+       os << ']';
+}
+
+
+bool InsetMathDiff::metrics(MetricsInfo &, Dimension &) const
+{
+       lyxerr << "should not happen" << endl;
+       return true;
+}
+
+
+void InsetMathDiff::draw(PainterInfo &, int, int) const
+{
+       lyxerr << "should not happen" << endl;
+}
+
+
+void InsetMathDiff::maple(MapleStream & os) const
+{
+       os << "diff(";
+       for (idx_type idx = 0; idx < nargs(); ++idx) {
+               if (idx != 0)
+                       os << ',';
+               os << cell(idx);
+       }
+       os << ')';
+}
+
+
+void InsetMathDiff::maxima(MaximaStream & os) const
+{
+       os << "diff(";
+       for (idx_type idx = 0; idx < nargs(); ++idx) {
+               if (idx != 0)
+                       os << ',';
+               os << cell(idx);
+               if (idx != 0)
+                       os << ",1";
+       }
+       os << ')';
+}
+
+
+void InsetMathDiff::mathematica(MathematicaStream & os) const
+{
+       os << "D[";
+       for (idx_type idx = 0; idx < nargs(); ++idx) {
+               if (idx != 0)
+                       os << ',';
+               os << cell(idx);
+       }
+       os << ']';
+}
+
+
+void InsetMathDiff::mathmlize(MathStream & os) const
+{
+       os << "diff(";
+       for (idx_type idx = 0; idx < nargs(); ++idx) {
+               if (idx != 0)
+                       os << ',';
+               os << cell(idx);
+       }
+       os << ')';
+}
+
+
+void InsetMathDiff::write(WriteStream &) const
+{
+       lyxerr << "should not happen" << endl;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathDim.C b/src/mathed/InsetMathDim.C
deleted file mode 100644 (file)
index e74bbbc..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * \file InsetMathDim.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathDim.h"
-
-#include "BufferView.h"
-#include "coordcache.h"
-#include "debug.h"
-#include "metricsinfo.h"
-
-
-namespace lyx {
-
-
-InsetMathDim::InsetMathDim()
-{}
-
-
-void InsetMathDim::setPosCache(PainterInfo const & pi, int x, int y) const
-{
-       //lyxerr << "InsetMathDim: cache to " << x << " " << y << std::endl;
-       pi.base.bv->coordCache().insets().add(this, x, y);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathDim.cpp b/src/mathed/InsetMathDim.cpp
new file mode 100644 (file)
index 0000000..e74bbbc
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * \file InsetMathDim.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathDim.h"
+
+#include "BufferView.h"
+#include "coordcache.h"
+#include "debug.h"
+#include "metricsinfo.h"
+
+
+namespace lyx {
+
+
+InsetMathDim::InsetMathDim()
+{}
+
+
+void InsetMathDim::setPosCache(PainterInfo const & pi, int x, int y) const
+{
+       //lyxerr << "InsetMathDim: cache to " << x << " " << y << std::endl;
+       pi.base.bv->coordCache().insets().add(this, x, y);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathDots.C b/src/mathed/InsetMathDots.C
deleted file mode 100644 (file)
index 6673d04..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * \file InsetMathDots.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathDots.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "MathParser.h"
-
-#include "frontends/FontMetrics.h"
-
-namespace lyx {
-
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathDots::InsetMathDots(latexkeys const * key)
-       : key_(key)
-{}
-
-
-auto_ptr<InsetBase> InsetMathDots::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathDots(*this));
-}
-
-
-bool InsetMathDots::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       dim = theFontMetrics(mi.base.font).dimension('M');
-       dh_ = 0;
-       if (key_->name == "cdots" || key_->name == "dotsb"
-                       || key_->name == "dotsm" || key_->name == "dotsi")
-               dh_ = dim.asc / 2;
-       else if (key_->name == "dotsc")
-               dh_ = dim.asc / 4;
-       else if (key_->name == "vdots") {
-               dim.wid = (dim.wid / 2) + 1;
-               dh_ = dim.asc;
-       }
-       else if (key_->name == "ddots")
-               dh_ = dim.asc;
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathDots::draw(PainterInfo & pain, int x, int y) const
-{
-       mathed_draw_deco(pain, x + 2, y - dh_, dim_.width() - 2, dim_.ascent(),
-               key_->name);
-       if (key_->name == "vdots" || key_->name == "ddots")
-               ++x;
-       if (key_->name != "vdots")
-               --y;
-       mathed_draw_deco(pain, x + 2, y - dh_, dim_.width() - 2, dim_.ascent(),
-               key_->name);
-       setPosCache(pain, x, y);
-}
-
-
-docstring InsetMathDots::name() const
-{
-       return key_->name;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathDots.cpp b/src/mathed/InsetMathDots.cpp
new file mode 100644 (file)
index 0000000..6673d04
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * \file InsetMathDots.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathDots.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "MathParser.h"
+
+#include "frontends/FontMetrics.h"
+
+namespace lyx {
+
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathDots::InsetMathDots(latexkeys const * key)
+       : key_(key)
+{}
+
+
+auto_ptr<InsetBase> InsetMathDots::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathDots(*this));
+}
+
+
+bool InsetMathDots::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       dim = theFontMetrics(mi.base.font).dimension('M');
+       dh_ = 0;
+       if (key_->name == "cdots" || key_->name == "dotsb"
+                       || key_->name == "dotsm" || key_->name == "dotsi")
+               dh_ = dim.asc / 2;
+       else if (key_->name == "dotsc")
+               dh_ = dim.asc / 4;
+       else if (key_->name == "vdots") {
+               dim.wid = (dim.wid / 2) + 1;
+               dh_ = dim.asc;
+       }
+       else if (key_->name == "ddots")
+               dh_ = dim.asc;
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathDots::draw(PainterInfo & pain, int x, int y) const
+{
+       mathed_draw_deco(pain, x + 2, y - dh_, dim_.width() - 2, dim_.ascent(),
+               key_->name);
+       if (key_->name == "vdots" || key_->name == "ddots")
+               ++x;
+       if (key_->name != "vdots")
+               --y;
+       mathed_draw_deco(pain, x + 2, y - dh_, dim_.width() - 2, dim_.ascent(),
+               key_->name);
+       setPosCache(pain, x, y);
+}
+
+
+docstring InsetMathDots::name() const
+{
+       return key_->name;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathEnv.C b/src/mathed/InsetMathEnv.C
deleted file mode 100644 (file)
index 110d09b..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * \file InsetMathEnv.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathEnv.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathEnv::InsetMathEnv(docstring const & name)
-       : InsetMathNest(1), name_(name)
-{}
-
-
-auto_ptr<InsetBase> InsetMathEnv::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathEnv(*this));
-}
-
-
-bool InsetMathEnv::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathEnv::draw(PainterInfo & pi, int x, int y) const
-{
-       cell(0).draw(pi, x + 1, y);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathEnv::write(WriteStream & os) const
-{
-       os << "\\begin{" << name_ << '}' << cell(0) << "\\end{" << name_ << '}';
-}
-
-
-void InsetMathEnv::normalize(NormalStream & os) const
-{
-       os << "[env " << name_ << ' ' << cell(0) << ']';
-}
-
-
-void InsetMathEnv::infoize(odocstream & os) const
-{
-       os << "Env: " << name_;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathEnv.cpp b/src/mathed/InsetMathEnv.cpp
new file mode 100644 (file)
index 0000000..110d09b
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * \file InsetMathEnv.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathEnv.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathEnv::InsetMathEnv(docstring const & name)
+       : InsetMathNest(1), name_(name)
+{}
+
+
+auto_ptr<InsetBase> InsetMathEnv::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathEnv(*this));
+}
+
+
+bool InsetMathEnv::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathEnv::draw(PainterInfo & pi, int x, int y) const
+{
+       cell(0).draw(pi, x + 1, y);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathEnv::write(WriteStream & os) const
+{
+       os << "\\begin{" << name_ << '}' << cell(0) << "\\end{" << name_ << '}';
+}
+
+
+void InsetMathEnv::normalize(NormalStream & os) const
+{
+       os << "[env " << name_ << ' ' << cell(0) << ']';
+}
+
+
+void InsetMathEnv::infoize(odocstream & os) const
+{
+       os << "Env: " << name_;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathExFunc.C b/src/mathed/InsetMathExFunc.C
deleted file mode 100644 (file)
index 9ede0e4..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * \file InsetMathExFunc.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathExFunc.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-using std::vector;
-using std::string;
-
-
-InsetMathExFunc::InsetMathExFunc(docstring const & name)
-       : InsetMathNest(1), name_(name)
-{}
-
-
-InsetMathExFunc::InsetMathExFunc(docstring const & name, MathArray const & ar)
-       : InsetMathNest(1), name_(name)
-{
-       cell(0) = ar;
-}
-
-
-auto_ptr<InsetBase> InsetMathExFunc::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathExFunc(*this));
-}
-
-
-bool InsetMathExFunc::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       mathed_string_dim(mi.base.font, name_, dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathExFunc::draw(PainterInfo & pi, int x, int y) const
-{
-       drawStrBlack(pi, x, y, name_);
-}
-
-
-docstring InsetMathExFunc::name() const
-{
-       return name_;
-}
-
-
-void InsetMathExFunc::maple(MapleStream & os) const
-{
-       if (name_ == "det")
-               os << "linalg[det](" << cell(0) << ')';
-       else
-               os << name_ << '(' << cell(0) << ')';
-}
-
-
-void InsetMathExFunc::maxima(MaximaStream & os) const
-{
-       if (name_ == "det")
-               os << "determinant(" << cell(0) << ')';
-       else
-               os << name_ << '(' << cell(0) << ')';
-}
-
-
-static string asMathematicaName(string const & name)
-{
-       if (name == "sin")    return "Sin";
-       if (name == "sinh")   return "Sinh";
-       if (name == "arcsin") return "ArcSin";
-       if (name == "asin")   return "ArcSin";
-       if (name == "cos")    return "Cos";
-       if (name == "cosh")   return "Cosh";
-       if (name == "arccos") return "ArcCos";
-       if (name == "acos")   return "ArcCos";
-       if (name == "tan")    return "Tan";
-       if (name == "tanh")   return "Tanh";
-       if (name == "arctan") return "ArcTan";
-       if (name == "atan")   return "ArcTan";
-       if (name == "cot")    return "Cot";
-       if (name == "coth")   return "Coth";
-       if (name == "csc")    return "Csc";
-       if (name == "sec")    return "Sec";
-       if (name == "exp")    return "Exp";
-       if (name == "log")    return "Log";
-       if (name == "ln" )    return "Log";
-       if (name == "arg" )   return "Arg";
-       if (name == "det" )   return "Det";
-       if (name == "gcd" )   return "GCD";
-       if (name == "max" )   return "Max";
-       if (name == "min" )   return "Min";
-       if (name == "erf" )   return "Erf";
-       if (name == "erfc" )  return "Erfc";
-       return name;
-}
-
-
-static docstring asMathematicaName(docstring const & name)
-{
-       return from_utf8(asMathematicaName(to_utf8(name)));
-}
-
-
-void InsetMathExFunc::mathematica(MathematicaStream & os) const
-{
-       os << asMathematicaName(name_) << '[' << cell(0) << ']';
-}
-
-
-void InsetMathExFunc::mathmlize(MathStream & os) const
-{
-       os << MTag(name_.c_str()) << cell(0) << ETag(name_.c_str());
-}
-
-
-void InsetMathExFunc::octave(OctaveStream & os) const
-{
-       os << name_ << '(' << cell(0) << ')';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathExFunc.cpp b/src/mathed/InsetMathExFunc.cpp
new file mode 100644 (file)
index 0000000..9ede0e4
--- /dev/null
@@ -0,0 +1,141 @@
+/**
+ * \file InsetMathExFunc.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathExFunc.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+using std::vector;
+using std::string;
+
+
+InsetMathExFunc::InsetMathExFunc(docstring const & name)
+       : InsetMathNest(1), name_(name)
+{}
+
+
+InsetMathExFunc::InsetMathExFunc(docstring const & name, MathArray const & ar)
+       : InsetMathNest(1), name_(name)
+{
+       cell(0) = ar;
+}
+
+
+auto_ptr<InsetBase> InsetMathExFunc::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathExFunc(*this));
+}
+
+
+bool InsetMathExFunc::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       mathed_string_dim(mi.base.font, name_, dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathExFunc::draw(PainterInfo & pi, int x, int y) const
+{
+       drawStrBlack(pi, x, y, name_);
+}
+
+
+docstring InsetMathExFunc::name() const
+{
+       return name_;
+}
+
+
+void InsetMathExFunc::maple(MapleStream & os) const
+{
+       if (name_ == "det")
+               os << "linalg[det](" << cell(0) << ')';
+       else
+               os << name_ << '(' << cell(0) << ')';
+}
+
+
+void InsetMathExFunc::maxima(MaximaStream & os) const
+{
+       if (name_ == "det")
+               os << "determinant(" << cell(0) << ')';
+       else
+               os << name_ << '(' << cell(0) << ')';
+}
+
+
+static string asMathematicaName(string const & name)
+{
+       if (name == "sin")    return "Sin";
+       if (name == "sinh")   return "Sinh";
+       if (name == "arcsin") return "ArcSin";
+       if (name == "asin")   return "ArcSin";
+       if (name == "cos")    return "Cos";
+       if (name == "cosh")   return "Cosh";
+       if (name == "arccos") return "ArcCos";
+       if (name == "acos")   return "ArcCos";
+       if (name == "tan")    return "Tan";
+       if (name == "tanh")   return "Tanh";
+       if (name == "arctan") return "ArcTan";
+       if (name == "atan")   return "ArcTan";
+       if (name == "cot")    return "Cot";
+       if (name == "coth")   return "Coth";
+       if (name == "csc")    return "Csc";
+       if (name == "sec")    return "Sec";
+       if (name == "exp")    return "Exp";
+       if (name == "log")    return "Log";
+       if (name == "ln" )    return "Log";
+       if (name == "arg" )   return "Arg";
+       if (name == "det" )   return "Det";
+       if (name == "gcd" )   return "GCD";
+       if (name == "max" )   return "Max";
+       if (name == "min" )   return "Min";
+       if (name == "erf" )   return "Erf";
+       if (name == "erfc" )  return "Erfc";
+       return name;
+}
+
+
+static docstring asMathematicaName(docstring const & name)
+{
+       return from_utf8(asMathematicaName(to_utf8(name)));
+}
+
+
+void InsetMathExFunc::mathematica(MathematicaStream & os) const
+{
+       os << asMathematicaName(name_) << '[' << cell(0) << ']';
+}
+
+
+void InsetMathExFunc::mathmlize(MathStream & os) const
+{
+       os << MTag(name_.c_str()) << cell(0) << ETag(name_.c_str());
+}
+
+
+void InsetMathExFunc::octave(OctaveStream & os) const
+{
+       os << name_ << '(' << cell(0) << ')';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathExInt.C b/src/mathed/InsetMathExInt.C
deleted file mode 100644 (file)
index 23fca48..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * \file InsetMathExInt.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathExInt.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "InsetMathSymbol.h"
-#include "debug.h"
-
-#include <boost/scoped_ptr.hpp>
-
-
-namespace lyx {
-
-
-using std::string;
-using std::auto_ptr;
-using std::endl;
-
-
-InsetMathExInt::InsetMathExInt(docstring const & name)
-       : InsetMathNest(4), symbol_(name)
-{}
-
-// 0 - core
-// 1 - diff
-// 2 - lower
-// 3 - upper
-
-
-auto_ptr<InsetBase> InsetMathExInt::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathExInt(*this));
-}
-
-
-void InsetMathExInt::symbol(docstring const & symbol)
-{
-       symbol_ = symbol;
-}
-
-
-bool InsetMathExInt::hasScripts() const
-{
-       // take empty upper bound as "no scripts"
-       return !cell(3).empty();
-}
-
-
-
-void InsetMathExInt::normalize(NormalStream & os) const
-{
-       os << '[' << symbol_ << ' ' << cell(0) << ' ' << cell(1) << ' '
-          << cell(2) << ' ' << cell(3) << ']';
-}
-
-
-bool InsetMathExInt::metrics(MetricsInfo &, Dimension &) const
-{
-       lyxerr << "should not happen" << endl;
-       return true;
-}
-
-
-void InsetMathExInt::draw(PainterInfo &, int, int) const
-{
-       lyxerr << "should not happen" << endl;
-}
-
-
-void InsetMathExInt::maple(MapleStream & os) const
-{
-       os << symbol_ << '(';
-       if (cell(0).size())
-               os << cell(0);
-       else
-               os << '1';
-       os << ',' << cell(1);
-       if (hasScripts())
-               os << '=' << cell(2) << ".." << cell(3);
-       os << ')';
-}
-
-
-void InsetMathExInt::maxima(MaximaStream & os) const
-{
-       if ( symbol_ == "int" )
-               os << "integrate(";
-       else
-               os << symbol_ << '(';
-
-       if (cell(0).size())
-               os << cell(0) << ',';
-       else
-               os << '1' << ',';
-       if (hasScripts())
-               os << cell(1) << ',' << cell(2) << ',' << cell(3) << ')';
-       else
-               os << cell(1) << ')';
-}
-
-void InsetMathExInt::mathematica(MathematicaStream & os) const
-{
-       if ( symbol_ == "int" )
-               os << "Integrate[";
-       else if (symbol_ == "sum")
-               os << "Sum[";
-       else
-               os << symbol_ << '[';
-
-       if (cell(0).size())
-               os << cell(0) << ',';
-       else
-               os << '1' << ',';
-       if (hasScripts())
-               os << '{' << cell(1) << ',' << cell(2) << ',' << cell(3) << "}]";
-       else
-               os << cell(1) << ']';
-}
-
-
-void InsetMathExInt::mathmlize(MathStream & os) const
-{
-       boost::scoped_ptr<InsetMathSymbol> sym(new InsetMathSymbol(symbol_));
-       //if (hasScripts())
-       //      mathmlize(sym, os);
-       //else
-               sym->mathmlize(os);
-       os << cell(0) << "<mo> &InvisibleTimes; </mo>"
-          << MTag("mrow") << "<mo> &DifferentialD; </mo>"
-          << cell(1) << ETag("mrow");
-}
-
-
-void InsetMathExInt::write(WriteStream &) const
-{
-       lyxerr << "should not happen" << endl;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathExInt.cpp b/src/mathed/InsetMathExInt.cpp
new file mode 100644 (file)
index 0000000..23fca48
--- /dev/null
@@ -0,0 +1,151 @@
+/**
+ * \file InsetMathExInt.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathExInt.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "InsetMathSymbol.h"
+#include "debug.h"
+
+#include <boost/scoped_ptr.hpp>
+
+
+namespace lyx {
+
+
+using std::string;
+using std::auto_ptr;
+using std::endl;
+
+
+InsetMathExInt::InsetMathExInt(docstring const & name)
+       : InsetMathNest(4), symbol_(name)
+{}
+
+// 0 - core
+// 1 - diff
+// 2 - lower
+// 3 - upper
+
+
+auto_ptr<InsetBase> InsetMathExInt::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathExInt(*this));
+}
+
+
+void InsetMathExInt::symbol(docstring const & symbol)
+{
+       symbol_ = symbol;
+}
+
+
+bool InsetMathExInt::hasScripts() const
+{
+       // take empty upper bound as "no scripts"
+       return !cell(3).empty();
+}
+
+
+
+void InsetMathExInt::normalize(NormalStream & os) const
+{
+       os << '[' << symbol_ << ' ' << cell(0) << ' ' << cell(1) << ' '
+          << cell(2) << ' ' << cell(3) << ']';
+}
+
+
+bool InsetMathExInt::metrics(MetricsInfo &, Dimension &) const
+{
+       lyxerr << "should not happen" << endl;
+       return true;
+}
+
+
+void InsetMathExInt::draw(PainterInfo &, int, int) const
+{
+       lyxerr << "should not happen" << endl;
+}
+
+
+void InsetMathExInt::maple(MapleStream & os) const
+{
+       os << symbol_ << '(';
+       if (cell(0).size())
+               os << cell(0);
+       else
+               os << '1';
+       os << ',' << cell(1);
+       if (hasScripts())
+               os << '=' << cell(2) << ".." << cell(3);
+       os << ')';
+}
+
+
+void InsetMathExInt::maxima(MaximaStream & os) const
+{
+       if ( symbol_ == "int" )
+               os << "integrate(";
+       else
+               os << symbol_ << '(';
+
+       if (cell(0).size())
+               os << cell(0) << ',';
+       else
+               os << '1' << ',';
+       if (hasScripts())
+               os << cell(1) << ',' << cell(2) << ',' << cell(3) << ')';
+       else
+               os << cell(1) << ')';
+}
+
+void InsetMathExInt::mathematica(MathematicaStream & os) const
+{
+       if ( symbol_ == "int" )
+               os << "Integrate[";
+       else if (symbol_ == "sum")
+               os << "Sum[";
+       else
+               os << symbol_ << '[';
+
+       if (cell(0).size())
+               os << cell(0) << ',';
+       else
+               os << '1' << ',';
+       if (hasScripts())
+               os << '{' << cell(1) << ',' << cell(2) << ',' << cell(3) << "}]";
+       else
+               os << cell(1) << ']';
+}
+
+
+void InsetMathExInt::mathmlize(MathStream & os) const
+{
+       boost::scoped_ptr<InsetMathSymbol> sym(new InsetMathSymbol(symbol_));
+       //if (hasScripts())
+       //      mathmlize(sym, os);
+       //else
+               sym->mathmlize(os);
+       os << cell(0) << "<mo> &InvisibleTimes; </mo>"
+          << MTag("mrow") << "<mo> &DifferentialD; </mo>"
+          << cell(1) << ETag("mrow");
+}
+
+
+void InsetMathExInt::write(WriteStream &) const
+{
+       lyxerr << "should not happen" << endl;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathFBox.C b/src/mathed/InsetMathFBox.C
deleted file mode 100644 (file)
index 4eb91a8..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * \file InsetMathFBox.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathFBox.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "LColor.h"
-
-#include "support/std_ostream.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathFBox::InsetMathFBox()
-       : InsetMathNest(1)
-{}
-
-
-auto_ptr<InsetBase> InsetMathFBox::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathFBox(*this));
-}
-
-
-InsetMath::mode_type InsetMathFBox::currentMode() const
-{
-       return TEXT_MODE;
-}
-
-
-bool InsetMathFBox::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       FontSetChanger dummy(mi.base, "textnormal");
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim, 3); // 1 pixel space, 1 frame, 1 space
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathFBox::draw(PainterInfo & pi, int x, int y) const
-{
-       pi.pain.rectangle(x + 1, y - dim_.ascent() + 1,
-               dim_.width() - 2, dim_.height() - 2, LColor::foreground);
-       FontSetChanger dummy(pi.base, "textnormal");
-       cell(0).draw(pi, x + 3, y);
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathFBox::write(WriteStream & os) const
-{
-       os << "\\fbox{" << cell(0) << '}';
-}
-
-
-void InsetMathFBox::normalize(NormalStream & os) const
-{
-       os << "[fbox " << cell(0) << ']';
-}
-
-
-void InsetMathFBox::infoize(odocstream & os) const
-{
-       os << "FBox: ";
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathFBox.cpp b/src/mathed/InsetMathFBox.cpp
new file mode 100644 (file)
index 0000000..4eb91a8
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * \file InsetMathFBox.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathFBox.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "LColor.h"
+
+#include "support/std_ostream.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathFBox::InsetMathFBox()
+       : InsetMathNest(1)
+{}
+
+
+auto_ptr<InsetBase> InsetMathFBox::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathFBox(*this));
+}
+
+
+InsetMath::mode_type InsetMathFBox::currentMode() const
+{
+       return TEXT_MODE;
+}
+
+
+bool InsetMathFBox::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       FontSetChanger dummy(mi.base, "textnormal");
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim, 3); // 1 pixel space, 1 frame, 1 space
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathFBox::draw(PainterInfo & pi, int x, int y) const
+{
+       pi.pain.rectangle(x + 1, y - dim_.ascent() + 1,
+               dim_.width() - 2, dim_.height() - 2, LColor::foreground);
+       FontSetChanger dummy(pi.base, "textnormal");
+       cell(0).draw(pi, x + 3, y);
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathFBox::write(WriteStream & os) const
+{
+       os << "\\fbox{" << cell(0) << '}';
+}
+
+
+void InsetMathFBox::normalize(NormalStream & os) const
+{
+       os << "[fbox " << cell(0) << ']';
+}
+
+
+void InsetMathFBox::infoize(odocstream & os) const
+{
+       os << "FBox: ";
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathFont.C b/src/mathed/InsetMathFont.C
deleted file mode 100644 (file)
index e079868..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * \file InsetMathFont.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathFont.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathParser.h"
-#include "LaTeXFeatures.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathFont::InsetMathFont(latexkeys const * key)
-       : InsetMathNest(1), key_(key)
-{}
-
-
-auto_ptr<InsetBase> InsetMathFont::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathFont(*this));
-}
-
-
-InsetMath::mode_type InsetMathFont::currentMode() const
-{
-       if (key_->extra == "mathmode")
-               return MATH_MODE;
-       if (key_->extra == "textmode")
-               return TEXT_MODE;
-       return UNDECIDED_MODE;
-}
-
-
-bool InsetMathFont::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       FontSetChanger dummy(mi.base, key_->name);
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathFont::draw(PainterInfo & pi, int x, int y) const
-{
-       FontSetChanger dummy(pi.base, key_->name.c_str());
-       cell(0).draw(pi, x + 1, y);
-       drawMarkers(pi, x, y);
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathFont::metricsT(TextMetricsInfo const & mi, Dimension &) const
-{
-       cell(0).metricsT(mi, dim_);
-}
-
-
-void InsetMathFont::drawT(TextPainter & pain, int x, int y) const
-{
-       cell(0).drawT(pain, x, y);
-}
-
-
-docstring InsetMathFont::name() const
-{
-       return key_->name;
-}
-
-
-void InsetMathFont::validate(LaTeXFeatures & features) const
-{
-       InsetMathNest::validate(features);
-       // Make sure amssymb is put in preamble if Blackboard Bold or
-       // Fraktur used:
-       if (key_->name == "mathfrak" || key_->name == "mathbb")
-               features.require("amssymb");
-       if (key_->name == "text")
-               features.require("amsmath");
-       if (key_->name == "textipa")
-               features.require("tipa");
-}
-
-
-void InsetMathFont::infoize(odocstream & os) const
-{
-       os << "Font: " << key_->name;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathFont.cpp b/src/mathed/InsetMathFont.cpp
new file mode 100644 (file)
index 0000000..e079868
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * \file InsetMathFont.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathFont.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathParser.h"
+#include "LaTeXFeatures.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathFont::InsetMathFont(latexkeys const * key)
+       : InsetMathNest(1), key_(key)
+{}
+
+
+auto_ptr<InsetBase> InsetMathFont::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathFont(*this));
+}
+
+
+InsetMath::mode_type InsetMathFont::currentMode() const
+{
+       if (key_->extra == "mathmode")
+               return MATH_MODE;
+       if (key_->extra == "textmode")
+               return TEXT_MODE;
+       return UNDECIDED_MODE;
+}
+
+
+bool InsetMathFont::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       FontSetChanger dummy(mi.base, key_->name);
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathFont::draw(PainterInfo & pi, int x, int y) const
+{
+       FontSetChanger dummy(pi.base, key_->name.c_str());
+       cell(0).draw(pi, x + 1, y);
+       drawMarkers(pi, x, y);
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathFont::metricsT(TextMetricsInfo const & mi, Dimension &) const
+{
+       cell(0).metricsT(mi, dim_);
+}
+
+
+void InsetMathFont::drawT(TextPainter & pain, int x, int y) const
+{
+       cell(0).drawT(pain, x, y);
+}
+
+
+docstring InsetMathFont::name() const
+{
+       return key_->name;
+}
+
+
+void InsetMathFont::validate(LaTeXFeatures & features) const
+{
+       InsetMathNest::validate(features);
+       // Make sure amssymb is put in preamble if Blackboard Bold or
+       // Fraktur used:
+       if (key_->name == "mathfrak" || key_->name == "mathbb")
+               features.require("amssymb");
+       if (key_->name == "text")
+               features.require("amsmath");
+       if (key_->name == "textipa")
+               features.require("tipa");
+}
+
+
+void InsetMathFont::infoize(odocstream & os) const
+{
+       os << "Font: " << key_->name;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathFontOld.C b/src/mathed/InsetMathFontOld.C
deleted file mode 100644 (file)
index d061280..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * \file InsetMathFontOld.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathFontOld.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathParser.h"
-#include "MathStream.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathFontOld::InsetMathFontOld(latexkeys const * key)
-       : InsetMathNest(1), key_(key)
-{
-       //lock(true);
-}
-
-
-auto_ptr<InsetBase> InsetMathFontOld::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathFontOld(*this));
-}
-
-
-bool InsetMathFontOld::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       FontSetChanger dummy(mi.base, key_->name.c_str());
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathFontOld::draw(PainterInfo & pi, int x, int y) const
-{
-       FontSetChanger dummy(pi.base, key_->name.c_str());
-       cell(0).draw(pi, x + 1, y);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathFontOld::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       cell(0).metricsT(mi, dim);
-}
-
-
-void InsetMathFontOld::drawT(TextPainter & pain, int x, int y) const
-{
-       cell(0).drawT(pain, x, y);
-}
-
-
-void InsetMathFontOld::write(WriteStream & os) const
-{
-       os << "{\\" << key_->name << ' ' << cell(0) << '}';
-}
-
-
-void InsetMathFontOld::normalize(NormalStream & os) const
-{
-       os << "[font " << key_->name << ' ' << cell(0) << ']';
-}
-
-
-void InsetMathFontOld::infoize(odocstream & os) const
-{
-       os << "Font: " << key_->name;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathFontOld.cpp b/src/mathed/InsetMathFontOld.cpp
new file mode 100644 (file)
index 0000000..d061280
--- /dev/null
@@ -0,0 +1,89 @@
+/**
+ * \file InsetMathFontOld.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathFontOld.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathParser.h"
+#include "MathStream.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathFontOld::InsetMathFontOld(latexkeys const * key)
+       : InsetMathNest(1), key_(key)
+{
+       //lock(true);
+}
+
+
+auto_ptr<InsetBase> InsetMathFontOld::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathFontOld(*this));
+}
+
+
+bool InsetMathFontOld::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       FontSetChanger dummy(mi.base, key_->name.c_str());
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathFontOld::draw(PainterInfo & pi, int x, int y) const
+{
+       FontSetChanger dummy(pi.base, key_->name.c_str());
+       cell(0).draw(pi, x + 1, y);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathFontOld::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       cell(0).metricsT(mi, dim);
+}
+
+
+void InsetMathFontOld::drawT(TextPainter & pain, int x, int y) const
+{
+       cell(0).drawT(pain, x, y);
+}
+
+
+void InsetMathFontOld::write(WriteStream & os) const
+{
+       os << "{\\" << key_->name << ' ' << cell(0) << '}';
+}
+
+
+void InsetMathFontOld::normalize(NormalStream & os) const
+{
+       os << "[font " << key_->name << ' ' << cell(0) << ']';
+}
+
+
+void InsetMathFontOld::infoize(odocstream & os) const
+{
+       os << "Font: " << key_->name;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathFrac.C b/src/mathed/InsetMathFrac.C
deleted file mode 100644 (file)
index 924cebe..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * \file InsetMathFrac.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathFrac.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "TextPainter.h"
-#include "LaTeXFeatures.h"
-#include "LColor.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-
-using std::string;
-using std::max;
-using std::auto_ptr;
-
-
-InsetMathFrac::InsetMathFrac(Kind kind)
-       : kind_(kind)
-{}
-
-
-auto_ptr<InsetBase> InsetMathFrac::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathFrac(*this));
-}
-
-
-InsetMathFrac * InsetMathFrac::asFracInset()
-{
-       return kind_ == ATOP ? 0 : this;
-}
-
-
-InsetMathFrac const * InsetMathFrac::asFracInset() const
-{
-       return kind_ == ATOP ? 0 : this;
-}
-
-
-bool InsetMathFrac::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       FracChanger dummy(mi.base);
-       cell(0).metrics(mi);
-       cell(1).metrics(mi);
-       if (kind_ == NICEFRAC) {
-               dim.wid = cell(0).width() + cell(1).width() + 5;
-               dim.asc = cell(0).height() + 5;
-               dim.des = cell(1).height() - 5;
-       } else {
-               dim.wid = max(cell(0).width(), cell(1).width()) + 2;
-               dim.asc = cell(0).height() + 2 + 5;
-               dim.des = cell(1).height() + 2 - 5;
-       }
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathFrac::draw(PainterInfo & pi, int x, int y) const
-{
-       setPosCache(pi, x, y);
-       int m = x + dim_.wid / 2;
-       FracChanger dummy(pi.base);
-       if (kind_ == NICEFRAC) {
-               cell(0).draw(pi, x + 2, 
-                               y - cell(0).descent() - 5);
-               cell(1).draw(pi, x + cell(0).width() + 5,
-                               y + cell(1).ascent() / 2);
-               pi.pain.line(x + cell(0).width(), 
-                               y + dim_.des - 2, 
-                               x + cell(0).width() + 5, 
-                               y - dim_.asc + 2, LColor::math);
-       } else {
-               cell(0).draw(pi, m - cell(0).width() / 2, 
-                               y - cell(0).descent() - 2 - 5);
-               cell(1).draw(pi, m - cell(1).width() / 2,
-                               y + cell(1).ascent()  + 2 - 5);
-       }
-       if (kind_ == FRAC || kind_ == OVER)
-               pi.pain.line(x + 1, y - 5, 
-                               x + dim_.wid - 2, y - 5, LColor::math);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathFrac::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       cell(0).metricsT(mi, dim);
-       cell(1).metricsT(mi, dim);
-       dim.wid = max(cell(0).width(), cell(1).width());
-       dim.asc = cell(0).height() + 1;
-       dim.des = cell(1).height();
-       //dim = dim_;
-}
-
-
-void InsetMathFrac::drawT(TextPainter & pain, int x, int y) const
-{
-       int m = x + dim_.width() / 2;
-       cell(0).drawT(pain, m - cell(0).width() / 2, y - cell(0).descent() - 1);
-       cell(1).drawT(pain, m - cell(1).width() / 2, y + cell(1).ascent());
-       // ASCII art: ignore niceties
-       if (kind_ == FRAC || kind_ == OVER || kind_ == NICEFRAC)
-               pain.horizontalLine(x, y, dim_.width());
-}
-
-
-void InsetMathFrac::write(WriteStream & os) const
-{
-       switch (kind_) {
-       case ATOP:
-               os << '{' << cell(0) << "\\atop " << cell(1) << '}';
-               break;
-       case OVER:
-               // \\over is only for compatibility, normalize this to \\frac
-               os << "\\frac{" << cell(0) << "}{" << cell(1) << '}';
-               break;
-       case FRAC:
-       case NICEFRAC:
-               InsetMathNest::write(os);
-               break;
-       }
-}
-
-
-docstring InsetMathFrac::name() const
-{
-       switch (kind_) {
-       case FRAC:
-               return from_ascii("frac");
-       case OVER:
-               return from_ascii("over");
-       case NICEFRAC:
-               return from_ascii("nicefrac");
-       case ATOP:
-               return from_ascii("atop");
-       }
-       // shut up stupid compiler
-       return docstring();
-}
-
-
-bool InsetMathFrac::extraBraces() const
-{
-       return kind_ == ATOP || kind_ == OVER;
-}
-
-
-void InsetMathFrac::maple(MapleStream & os) const
-{
-       os << '(' << cell(0) << ")/(" << cell(1) << ')';
-}
-
-
-void InsetMathFrac::mathematica(MathematicaStream & os) const
-{
-       os << '(' << cell(0) << ")/(" << cell(1) << ')';
-}
-
-
-void InsetMathFrac::octave(OctaveStream & os) const
-{
-       os << '(' << cell(0) << ")/(" << cell(1) << ')';
-}
-
-
-void InsetMathFrac::mathmlize(MathStream & os) const
-{
-       os << MTag("mfrac") << cell(0) << cell(1) << ETag("mfrac");
-}
-
-
-void InsetMathFrac::validate(LaTeXFeatures & features) const
-{
-       if (kind_ == NICEFRAC)
-               features.require("nicefrac");
-       InsetMathNest::validate(features);
-}
-
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathFrac.cpp b/src/mathed/InsetMathFrac.cpp
new file mode 100644 (file)
index 0000000..924cebe
--- /dev/null
@@ -0,0 +1,199 @@
+/**
+ * \file InsetMathFrac.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathFrac.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "TextPainter.h"
+#include "LaTeXFeatures.h"
+#include "LColor.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+
+using std::string;
+using std::max;
+using std::auto_ptr;
+
+
+InsetMathFrac::InsetMathFrac(Kind kind)
+       : kind_(kind)
+{}
+
+
+auto_ptr<InsetBase> InsetMathFrac::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathFrac(*this));
+}
+
+
+InsetMathFrac * InsetMathFrac::asFracInset()
+{
+       return kind_ == ATOP ? 0 : this;
+}
+
+
+InsetMathFrac const * InsetMathFrac::asFracInset() const
+{
+       return kind_ == ATOP ? 0 : this;
+}
+
+
+bool InsetMathFrac::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       FracChanger dummy(mi.base);
+       cell(0).metrics(mi);
+       cell(1).metrics(mi);
+       if (kind_ == NICEFRAC) {
+               dim.wid = cell(0).width() + cell(1).width() + 5;
+               dim.asc = cell(0).height() + 5;
+               dim.des = cell(1).height() - 5;
+       } else {
+               dim.wid = max(cell(0).width(), cell(1).width()) + 2;
+               dim.asc = cell(0).height() + 2 + 5;
+               dim.des = cell(1).height() + 2 - 5;
+       }
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathFrac::draw(PainterInfo & pi, int x, int y) const
+{
+       setPosCache(pi, x, y);
+       int m = x + dim_.wid / 2;
+       FracChanger dummy(pi.base);
+       if (kind_ == NICEFRAC) {
+               cell(0).draw(pi, x + 2, 
+                               y - cell(0).descent() - 5);
+               cell(1).draw(pi, x + cell(0).width() + 5,
+                               y + cell(1).ascent() / 2);
+               pi.pain.line(x + cell(0).width(), 
+                               y + dim_.des - 2, 
+                               x + cell(0).width() + 5, 
+                               y - dim_.asc + 2, LColor::math);
+       } else {
+               cell(0).draw(pi, m - cell(0).width() / 2, 
+                               y - cell(0).descent() - 2 - 5);
+               cell(1).draw(pi, m - cell(1).width() / 2,
+                               y + cell(1).ascent()  + 2 - 5);
+       }
+       if (kind_ == FRAC || kind_ == OVER)
+               pi.pain.line(x + 1, y - 5, 
+                               x + dim_.wid - 2, y - 5, LColor::math);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathFrac::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       cell(0).metricsT(mi, dim);
+       cell(1).metricsT(mi, dim);
+       dim.wid = max(cell(0).width(), cell(1).width());
+       dim.asc = cell(0).height() + 1;
+       dim.des = cell(1).height();
+       //dim = dim_;
+}
+
+
+void InsetMathFrac::drawT(TextPainter & pain, int x, int y) const
+{
+       int m = x + dim_.width() / 2;
+       cell(0).drawT(pain, m - cell(0).width() / 2, y - cell(0).descent() - 1);
+       cell(1).drawT(pain, m - cell(1).width() / 2, y + cell(1).ascent());
+       // ASCII art: ignore niceties
+       if (kind_ == FRAC || kind_ == OVER || kind_ == NICEFRAC)
+               pain.horizontalLine(x, y, dim_.width());
+}
+
+
+void InsetMathFrac::write(WriteStream & os) const
+{
+       switch (kind_) {
+       case ATOP:
+               os << '{' << cell(0) << "\\atop " << cell(1) << '}';
+               break;
+       case OVER:
+               // \\over is only for compatibility, normalize this to \\frac
+               os << "\\frac{" << cell(0) << "}{" << cell(1) << '}';
+               break;
+       case FRAC:
+       case NICEFRAC:
+               InsetMathNest::write(os);
+               break;
+       }
+}
+
+
+docstring InsetMathFrac::name() const
+{
+       switch (kind_) {
+       case FRAC:
+               return from_ascii("frac");
+       case OVER:
+               return from_ascii("over");
+       case NICEFRAC:
+               return from_ascii("nicefrac");
+       case ATOP:
+               return from_ascii("atop");
+       }
+       // shut up stupid compiler
+       return docstring();
+}
+
+
+bool InsetMathFrac::extraBraces() const
+{
+       return kind_ == ATOP || kind_ == OVER;
+}
+
+
+void InsetMathFrac::maple(MapleStream & os) const
+{
+       os << '(' << cell(0) << ")/(" << cell(1) << ')';
+}
+
+
+void InsetMathFrac::mathematica(MathematicaStream & os) const
+{
+       os << '(' << cell(0) << ")/(" << cell(1) << ')';
+}
+
+
+void InsetMathFrac::octave(OctaveStream & os) const
+{
+       os << '(' << cell(0) << ")/(" << cell(1) << ')';
+}
+
+
+void InsetMathFrac::mathmlize(MathStream & os) const
+{
+       os << MTag("mfrac") << cell(0) << cell(1) << ETag("mfrac");
+}
+
+
+void InsetMathFrac::validate(LaTeXFeatures & features) const
+{
+       if (kind_ == NICEFRAC)
+               features.require("nicefrac");
+       InsetMathNest::validate(features);
+}
+
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathFracBase.C b/src/mathed/InsetMathFracBase.C
deleted file mode 100644 (file)
index 22b0bef..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * \file InsetMathFracBase.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathFracBase.h"
-#include "MathData.h"
-#include "cursor.h"
-
-
-namespace lyx {
-
-
-InsetMathFracBase::InsetMathFracBase()
-       : InsetMathNest(2)
-{}
-
-
-bool InsetMathFracBase::idxRight(LCursor &) const
-{
-       return false;
-}
-
-
-bool InsetMathFracBase::idxLeft(LCursor &) const
-{
-       return false;
-}
-
-
-bool InsetMathFracBase::idxUpDown(LCursor & cur, bool up) const
-{
-       InsetMath::idx_type target = !up; // up ? 0 : 1, since upper cell has idx 0
-       if (cur.idx() == target)
-               return false;
-       cur.idx() = target;
-       cur.pos() = cell(target).x2pos(cur.x_target());
-       return true;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathFracBase.cpp b/src/mathed/InsetMathFracBase.cpp
new file mode 100644 (file)
index 0000000..22b0bef
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * \file InsetMathFracBase.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathFracBase.h"
+#include "MathData.h"
+#include "cursor.h"
+
+
+namespace lyx {
+
+
+InsetMathFracBase::InsetMathFracBase()
+       : InsetMathNest(2)
+{}
+
+
+bool InsetMathFracBase::idxRight(LCursor &) const
+{
+       return false;
+}
+
+
+bool InsetMathFracBase::idxLeft(LCursor &) const
+{
+       return false;
+}
+
+
+bool InsetMathFracBase::idxUpDown(LCursor & cur, bool up) const
+{
+       InsetMath::idx_type target = !up; // up ? 0 : 1, since upper cell has idx 0
+       if (cur.idx() == target)
+               return false;
+       cur.idx() = target;
+       cur.pos() = cell(target).x2pos(cur.x_target());
+       return true;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathFrameBox.C b/src/mathed/InsetMathFrameBox.C
deleted file mode 100644 (file)
index e77fe38..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * \file InsetMathFrameBox.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathFrameBox.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "LColor.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathFrameBox::InsetMathFrameBox()
-       : InsetMathNest(3)
-{}
-
-
-auto_ptr<InsetBase> InsetMathFrameBox::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathFrameBox(*this));
-}
-
-
-bool InsetMathFrameBox::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       FontSetChanger dummy(mi.base, "textnormal");
-       w_ = mathed_char_width(mi.base.font, '[');
-       InsetMathNest::metrics(mi);
-       dim  = cell(0).dim();
-       dim += cell(1).dim();
-       dim += cell(2).dim();
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathFrameBox::draw(PainterInfo & pi, int x, int y) const
-{
-       FontSetChanger dummy(pi.base, "textnormal");
-       pi.pain.rectangle(x + 1, y - dim_.ascent() + 1,
-               dim_.width() - 2, dim_.height() - 2, LColor::foreground);
-       x += 5;
-
-       drawStrBlack(pi, x, y, from_ascii("["));
-       x += w_;
-       cell(0).draw(pi, x, y);
-       x += cell(0).width();
-       drawStrBlack(pi, x, y, from_ascii("]"));
-       x += w_ + 4;
-
-       drawStrBlack(pi, x, y, from_ascii("["));
-       x += w_;
-       cell(1).draw(pi, x, y);
-       x += cell(1).width();
-       drawStrBlack(pi, x, y, from_ascii("]"));
-       x += w_ + 4;
-
-       cell(2).draw(pi, x, y);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathFrameBox::write(WriteStream & os) const
-{
-       os << "\\framebox";
-       os << '[' << cell(0) << ']';
-       if (cell(1).size())
-               os << '[' << cell(1) << ']';
-       os << '{' << cell(2) << '}';
-}
-
-
-void InsetMathFrameBox::normalize(NormalStream & os) const
-{
-       os << "[framebox " << cell(0) << ' ' << cell(1) << ' ' << cell(2) << ']';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathFrameBox.cpp b/src/mathed/InsetMathFrameBox.cpp
new file mode 100644 (file)
index 0000000..e77fe38
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+ * \file InsetMathFrameBox.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathFrameBox.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "LColor.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathFrameBox::InsetMathFrameBox()
+       : InsetMathNest(3)
+{}
+
+
+auto_ptr<InsetBase> InsetMathFrameBox::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathFrameBox(*this));
+}
+
+
+bool InsetMathFrameBox::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       FontSetChanger dummy(mi.base, "textnormal");
+       w_ = mathed_char_width(mi.base.font, '[');
+       InsetMathNest::metrics(mi);
+       dim  = cell(0).dim();
+       dim += cell(1).dim();
+       dim += cell(2).dim();
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathFrameBox::draw(PainterInfo & pi, int x, int y) const
+{
+       FontSetChanger dummy(pi.base, "textnormal");
+       pi.pain.rectangle(x + 1, y - dim_.ascent() + 1,
+               dim_.width() - 2, dim_.height() - 2, LColor::foreground);
+       x += 5;
+
+       drawStrBlack(pi, x, y, from_ascii("["));
+       x += w_;
+       cell(0).draw(pi, x, y);
+       x += cell(0).width();
+       drawStrBlack(pi, x, y, from_ascii("]"));
+       x += w_ + 4;
+
+       drawStrBlack(pi, x, y, from_ascii("["));
+       x += w_;
+       cell(1).draw(pi, x, y);
+       x += cell(1).width();
+       drawStrBlack(pi, x, y, from_ascii("]"));
+       x += w_ + 4;
+
+       cell(2).draw(pi, x, y);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathFrameBox::write(WriteStream & os) const
+{
+       os << "\\framebox";
+       os << '[' << cell(0) << ']';
+       if (cell(1).size())
+               os << '[' << cell(1) << ']';
+       os << '{' << cell(2) << '}';
+}
+
+
+void InsetMathFrameBox::normalize(NormalStream & os) const
+{
+       os << "[framebox " << cell(0) << ' ' << cell(1) << ' ' << cell(2) << ']';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathGrid.C b/src/mathed/InsetMathGrid.C
deleted file mode 100644 (file)
index 53354fa..0000000
+++ /dev/null
@@ -1,1400 +0,0 @@
-/**
- * \file InsetMathGrid.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathGrid.h"
-#include "MathData.h"
-#include "MathParser.h"
-#include "MathStream.h"
-
-#include "BufferView.h"
-#include "CutAndPaste.h"
-#include "FuncStatus.h"
-#include "LColor.h"
-#include "cursor.h"
-#include "debug.h"
-#include "funcrequest.h"
-#include "gettext.h"
-#include "undo.h"
-
-#include "frontends/Clipboard.h"
-#include "frontends/Painter.h"
-
-#include "insets/MailInset.h"
-
-#include "support/lstrings.h"
-
-#include <sstream>
-
-
-namespace lyx {
-
-using support::bformat;
-
-using std::endl;
-using std::max;
-using std::min;
-using std::swap;
-
-using std::string;
-using std::auto_ptr;
-using std::istream;
-using std::istringstream;
-using std::vector;
-
-class GridInsetMailer : public MailInset {
-public:
-       GridInsetMailer(InsetMathGrid & inset) : inset_(inset) {}
-       ///
-       virtual string const & name() const
-       {
-               static string const theName = "tabular";
-               return theName;
-       }
-       ///
-       virtual string const inset2string(Buffer const &) const
-       {
-               odocstringstream data;
-               //data << name() << " active_cell " << inset.getActCell() << '\n';
-               data << from_utf8(name()) << " active_cell " << 0 << '\n';
-               WriteStream ws(data);
-               inset_.write(ws);
-               return to_utf8(data.str());
-       }
-
-protected:
-       InsetBase & inset() const { return inset_; }
-       InsetMathGrid & inset_;
-};
-
-
-namespace {
-
-docstring verboseHLine(int n)
-{
-       docstring res;
-       for (int i = 0; i < n; ++i)
-               res += "\\hline";
-       if (n)
-               res += ' ';
-       return res;
-}
-
-
-int extractInt(istream & is)
-{
-       int num = 1;
-       is >> num;
-       return (num == 0) ? 1 : num;
-}
-
-}
-
-
-//////////////////////////////////////////////////////////////
-
-
-InsetMathGrid::CellInfo::CellInfo()
-       : dummy_(false)
-{}
-
-
-
-
-//////////////////////////////////////////////////////////////
-
-
-InsetMathGrid::RowInfo::RowInfo()
-       : lines_(0), skip_(0), allow_pagebreak_(true)
-{}
-
-
-
-int InsetMathGrid::RowInfo::skipPixels() const
-{
-       return crskip_.inBP();
-}
-
-
-
-//////////////////////////////////////////////////////////////
-
-
-InsetMathGrid::ColInfo::ColInfo()
-       : align_('c'), lines_(0)
-{}
-
-
-//////////////////////////////////////////////////////////////
-
-
-InsetMathGrid::InsetMathGrid(char v, docstring const & h)
-       : InsetMathNest(guessColumns(h)),
-         rowinfo_(2),
-         colinfo_(guessColumns(h) + 1),
-         cellinfo_(1 * guessColumns(h))
-{
-       setDefaults();
-       valign(v);
-       halign(h);
-       //lyxerr << "created grid with " << ncols() << " columns" << endl;
-}
-
-
-InsetMathGrid::InsetMathGrid()
-       : InsetMathNest(1),
-         rowinfo_(1 + 1),
-               colinfo_(1 + 1),
-               cellinfo_(1),
-               v_align_('c')
-{
-       setDefaults();
-}
-
-
-InsetMathGrid::InsetMathGrid(col_type m, row_type n)
-       : InsetMathNest(m * n),
-         rowinfo_(n + 1),
-               colinfo_(m + 1),
-               cellinfo_(m * n),
-               v_align_('c')
-{
-       setDefaults();
-}
-
-
-InsetMathGrid::InsetMathGrid(col_type m, row_type n, char v, docstring const & h)
-       : InsetMathNest(m * n),
-         rowinfo_(n + 1),
-         colinfo_(m + 1),
-               cellinfo_(m * n),
-               v_align_(v)
-{
-       setDefaults();
-       valign(v);
-       halign(h);
-}
-
-
-auto_ptr<InsetBase> InsetMathGrid::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathGrid(*this));
-}
-
-
-InsetMath::idx_type InsetMathGrid::index(row_type row, col_type col) const
-{
-       return col + ncols() * row;
-}
-
-
-void InsetMathGrid::setDefaults()
-{
-       if (ncols() <= 0)
-               lyxerr << "positive number of columns expected" << endl;
-       //if (nrows() <= 0)
-       //      lyxerr << "positive number of rows expected" << endl;
-       for (col_type col = 0; col < ncols(); ++col) {
-               colinfo_[col].align_ = defaultColAlign(col);
-               colinfo_[col].skip_  = defaultColSpace(col);
-       }
-}
-
-
-void InsetMathGrid::halign(docstring const & hh)
-{
-       col_type col = 0;
-       for (docstring::const_iterator it = hh.begin(); it != hh.end(); ++it) {
-               char_type c = *it;
-               if (c == '|') {
-                       colinfo_[col].lines_++;
-               } else if (col >= ncols()) {
-                       // Only '|' is allowed in the last dummy column
-                       break;
-               } else if (c == 'c' || c == 'l' || c == 'r') {
-                       colinfo_[col].align_ = (char)c;
-                       ++col;
-                       colinfo_[col].lines_ = 0;
-               } else {
-                       lyxerr << "unknown column separator: '" << c << "'" << endl;
-               }
-       }
-
-/*
-       col_type n = hh.size();
-       if (n > ncols())
-               n = ncols();
-       for (col_type col = 0; col < n; ++col)
-               colinfo_[col].align_ = hh[col];
-*/
-}
-
-
-InsetMathGrid::col_type InsetMathGrid::guessColumns(docstring const & hh) const
-{
-       col_type col = 0;
-       for (docstring::const_iterator it = hh.begin(); it != hh.end(); ++it)
-               if (*it == 'c' || *it == 'l' || *it == 'r')
-                       ++col;
-       // let's have at least one column, even if we did not recognize its
-       // alignment
-       if (col == 0)
-               col = 1;
-       return col;
-}
-
-
-void InsetMathGrid::halign(char h, col_type col)
-{
-       colinfo_[col].align_ = h;
-}
-
-
-char InsetMathGrid::halign(col_type col) const
-{
-       return colinfo_[col].align_;
-}
-
-
-docstring InsetMathGrid::halign() const
-{
-       docstring res;
-       for (col_type col = 0; col < ncols(); ++col) {
-               res += docstring(colinfo_[col].lines_, '|');
-               res += colinfo_[col].align_;
-       }
-       return res + docstring(colinfo_[ncols()].lines_, '|');
-}
-
-
-void InsetMathGrid::valign(char c)
-{
-       v_align_ = c;
-}
-
-
-char InsetMathGrid::valign() const
-{
-       return v_align_;
-}
-
-
-InsetMathGrid::col_type InsetMathGrid::ncols() const
-{
-       return colinfo_.size() - 1;
-}
-
-
-InsetMathGrid::row_type InsetMathGrid::nrows() const
-{
-       return rowinfo_.size() - 1;
-}
-
-
-InsetMathGrid::col_type InsetMathGrid::col(idx_type idx) const
-{
-       return idx % ncols();
-}
-
-
-InsetMathGrid::row_type InsetMathGrid::row(idx_type idx) const
-{
-       return idx / ncols();
-}
-
-
-void InsetMathGrid::vcrskip(LyXLength const & crskip, row_type row)
-{
-       rowinfo_[row].crskip_ = crskip;
-}
-
-
-LyXLength InsetMathGrid::vcrskip(row_type row) const
-{
-       return rowinfo_[row].crskip_;
-}
-
-
-void InsetMathGrid::metrics(MetricsInfo & mi) const
-{
-       // let the cells adjust themselves
-       InsetMathNest::metrics(mi);
-
-       // compute absolute sizes of vertical structure
-       for (row_type row = 0; row < nrows(); ++row) {
-               int asc  = 0;
-               int desc = 0;
-               for (col_type col = 0; col < ncols(); ++col) {
-                       MathArray const & c = cell(index(row, col));
-                       asc  = max(asc,  c.ascent());
-                       desc = max(desc, c.descent());
-               }
-               rowinfo_[row].ascent_  = asc;
-               rowinfo_[row].descent_ = desc;
-       }
-       rowinfo_[0].ascent_       += hlinesep() * rowinfo_[0].lines_;
-       rowinfo_[nrows()].ascent_  = 0;
-       rowinfo_[nrows()].descent_ = 0;
-
-       // compute vertical offsets
-       rowinfo_[0].offset_ = 0;
-       for (row_type row = 1; row <= nrows(); ++row) {
-               rowinfo_[row].offset_  =
-                       rowinfo_[row - 1].offset_  +
-                       rowinfo_[row - 1].descent_ +
-                       rowinfo_[row - 1].skipPixels() +
-                       rowsep() +
-                       rowinfo_[row].lines_ * hlinesep() +
-                       rowinfo_[row].ascent_;
-       }
-
-       // adjust vertical offset
-       int h = 0;
-       switch (v_align_) {
-               case 't':
-                       h = 0;
-                       break;
-               case 'b':
-                       h = rowinfo_[nrows() - 1].offset_;
-                       break;
-               default:
-                       h = rowinfo_[nrows() - 1].offset_ / 2;
-       }
-       for (row_type row = 0; row <= nrows(); ++row)
-               rowinfo_[row].offset_ -= h;
-
-
-       // compute absolute sizes of horizontal structure
-       for (col_type col = 0; col < ncols(); ++col) {
-               int wid = 0;
-               for (row_type row = 0; row < nrows(); ++row)
-                       wid = max(wid, cell(index(row, col)).width());
-               colinfo_[col].width_ = wid;
-       }
-       colinfo_[ncols()].width_  = 0;
-
-       // compute horizontal offsets
-       colinfo_[0].offset_ = border();
-       for (col_type col = 1; col <= ncols(); ++col) {
-               colinfo_[col].offset_ =
-                       colinfo_[col - 1].offset_ +
-                       colinfo_[col - 1].width_ +
-                       colinfo_[col - 1].skip_ +
-                       colsep() +
-                       colinfo_[col].lines_ * vlinesep();
-       }
-
-
-       dim_.wid   =   colinfo_[ncols() - 1].offset_
-                      + colinfo_[ncols() - 1].width_
-                + vlinesep() * colinfo_[ncols()].lines_
-                      + border();
-
-       dim_.asc  = - rowinfo_[0].offset_
-                      + rowinfo_[0].ascent_
-                + hlinesep() * rowinfo_[0].lines_
-                      + border();
-
-       dim_.des =   rowinfo_[nrows() - 1].offset_
-                      + rowinfo_[nrows() - 1].descent_
-                + hlinesep() * rowinfo_[nrows()].lines_
-                      + border();
-
-
-/*
-       // Increase ws_[i] for 'R' columns (except the first one)
-       for (int i = 1; i < nc_; ++i)
-               if (align_[i] == 'R')
-                       ws_[i] += 10 * df_width;
-       // Increase ws_[i] for 'C' column
-       if (align_[0] == 'C')
-               if (ws_[0] < 7 * workwidth / 8)
-                       ws_[0] = 7 * workwidth / 8;
-
-       // Adjust local tabs
-       width = colsep();
-       for (cxrow = row_.begin(); cxrow; ++cxrow) {
-               int rg = COLSEP;
-               int lf = 0;
-               for (int i = 0; i < nc_; ++i) {
-                       bool isvoid = false;
-                       if (cxrow->getTab(i) <= 0) {
-                               cxrow->setTab(i, df_width);
-                               isvoid = true;
-                       }
-                       switch (align_[i]) {
-                       case 'l':
-                               lf = 0;
-                               break;
-                       case 'c':
-                               lf = (ws_[i] - cxrow->getTab(i))/2;
-                               break;
-                       case 'r':
-                       case 'R':
-                               lf = ws_[i] - cxrow->getTab(i);
-                               break;
-                       case 'C':
-                               if (cxrow == row_.begin())
-                                       lf = 0;
-                               else if (cxrow.is_last())
-                                       lf = ws_[i] - cxrow->getTab(i);
-                               else
-                                       lf = (ws_[i] - cxrow->getTab(i))/2;
-                               break;
-                       }
-                       int const ww = (isvoid) ? lf : lf + cxrow->getTab(i);
-                       cxrow->setTab(i, lf + rg);
-                       rg = ws_[i] - ww + colsep();
-                       if (cxrow == row_.begin())
-                               width += ws_[i] + colsep();
-               }
-               cxrow->setBaseline(cxrow->getBaseline() - ascent);
-       }
-*/
-       metricsMarkers2(dim_);
-}
-
-
-bool InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       dim = dim_;
-       metrics(mi);
-       if (dim_ == dim)
-               return false;
-       dim = dim_;
-       return true;
-}
-
-
-void InsetMathGrid::draw(PainterInfo & pi, int x, int y) const
-{
-       drawWithMargin(pi, x, y, 0, 0);
-}
-
-void InsetMathGrid::drawWithMargin(PainterInfo & pi, int x, int y,
-       int lmargin, int rmargin) const
-{
-       for (idx_type idx = 0; idx < nargs(); ++idx)
-               cell(idx).draw(pi, x + lmargin + cellXOffset(idx),
-                       y + cellYOffset(idx));
-
-       for (row_type row = 0; row <= nrows(); ++row)
-               for (unsigned int i = 0; i < rowinfo_[row].lines_; ++i) {
-                       int yy = y + rowinfo_[row].offset_ - rowinfo_[row].ascent_
-                               - i * hlinesep() - hlinesep()/2 - rowsep()/2;
-                       pi.pain.line(x + lmargin + 1, yy,
-                                    x + dim_.width() - rmargin - 1, yy,
-                                    LColor::foreground);
-               }
-
-       for (col_type col = 0; col <= ncols(); ++col)
-               for (unsigned int i = 0; i < colinfo_[col].lines_; ++i) {
-                       int xx = x + lmargin + colinfo_[col].offset_
-                               - i * vlinesep() - vlinesep()/2 - colsep()/2;
-                       pi.pain.line(xx, y - dim_.ascent() + 1,
-                                    xx, y + dim_.descent() - 1,
-                                    LColor::foreground);
-               }
-       drawMarkers2(pi, x, y);
-}
-
-
-void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       // let the cells adjust themselves
-       //InsetMathNest::metrics(mi);
-       for (idx_type i = 0; i < nargs(); ++i)
-               cell(i).metricsT(mi, dim);
-
-       // compute absolute sizes of vertical structure
-       for (row_type row = 0; row < nrows(); ++row) {
-               int asc  = 0;
-               int desc = 0;
-               for (col_type col = 0; col < ncols(); ++col) {
-                       MathArray const & c = cell(index(row, col));
-                       asc  = max(asc,  c.ascent());
-                       desc = max(desc, c.descent());
-               }
-               rowinfo_[row].ascent_  = asc;
-               rowinfo_[row].descent_ = desc;
-       }
-       //rowinfo_[0].ascent_       += hlinesep() * rowinfo_[0].lines_;
-       rowinfo_[nrows()].ascent_  = 0;
-       rowinfo_[nrows()].descent_ = 0;
-
-       // compute vertical offsets
-       rowinfo_[0].offset_ = 0;
-       for (row_type row = 1; row <= nrows(); ++row) {
-               rowinfo_[row].offset_  =
-                       rowinfo_[row - 1].offset_  +
-                       rowinfo_[row - 1].descent_ +
-                       //rowinfo_[row - 1].skipPixels() +
-                       1 + //rowsep() +
-                       //rowinfo_[row].lines_ * hlinesep() +
-                       rowinfo_[row].ascent_;
-       }
-
-       // adjust vertical offset
-       int h = 0;
-       switch (v_align_) {
-               case 't':
-                       h = 0;
-                       break;
-               case 'b':
-                       h = rowinfo_[nrows() - 1].offset_;
-                       break;
-               default:
-                       h = rowinfo_[nrows() - 1].offset_ / 2;
-       }
-       for (row_type row = 0; row <= nrows(); ++row)
-               rowinfo_[row].offset_ -= h;
-
-
-       // compute absolute sizes of horizontal structure
-       for (col_type col = 0; col < ncols(); ++col) {
-               int wid = 0;
-               for (row_type row = 0; row < nrows(); ++row)
-                       wid = max(wid, cell(index(row, col)).width());
-               colinfo_[col].width_ = wid;
-       }
-       colinfo_[ncols()].width_  = 0;
-
-       // compute horizontal offsets
-       colinfo_[0].offset_ = border();
-       for (col_type col = 1; col <= ncols(); ++col) {
-               colinfo_[col].offset_ =
-                       colinfo_[col - 1].offset_ +
-                       colinfo_[col - 1].width_ +
-                       colinfo_[col - 1].skip_ +
-                       1 ; //colsep() +
-                       //colinfo_[col].lines_ * vlinesep();
-       }
-
-
-       dim.wid  =  colinfo_[ncols() - 1].offset_
-                      + colinfo_[ncols() - 1].width_
-                //+ vlinesep() * colinfo_[ncols()].lines_
-                      + 2;
-
-       dim.asc  = -rowinfo_[0].offset_
-                      + rowinfo_[0].ascent_
-                //+ hlinesep() * rowinfo_[0].lines_
-                      + 1;
-
-       dim.des  =  rowinfo_[nrows() - 1].offset_
-                      + rowinfo_[nrows() - 1].descent_
-                //+ hlinesep() * rowinfo_[nrows()].lines_
-                      + 1;
-}
-
-
-void InsetMathGrid::drawT(TextPainter & pain, int x, int y) const
-{
-       for (idx_type idx = 0; idx < nargs(); ++idx)
-               cell(idx).drawT(pain, x + cellXOffset(idx), y + cellYOffset(idx));
-}
-
-
-docstring InsetMathGrid::eolString(row_type row, bool emptyline, bool fragile) const
-{
-       docstring eol;
-
-       if (!rowinfo_[row].crskip_.zero())
-               eol += '[' + from_utf8(rowinfo_[row].crskip_.asLatexString()) + ']';
-       else if(!rowinfo_[row].allow_pagebreak_)
-               eol += '*';
-
-       // make sure an upcoming '[' does not break anything
-       if (row + 1 < nrows()) {
-               MathArray const & c = cell(index(row + 1, 0));
-               if (c.size() && c.front()->getChar() == '[')
-                       //eol += "[0pt]";
-                       eol += "{}";
-       }
-
-       // only add \\ if necessary
-       if (eol.empty() && row + 1 == nrows() && (nrows() == 1 || !emptyline))
-               return docstring();
-
-       return (fragile ? "\\protect\\\\" : "\\\\") + eol;
-}
-
-
-docstring InsetMathGrid::eocString(col_type col, col_type lastcol) const
-{
-       if (col + 1 == lastcol)
-               return docstring();
-       return from_ascii(" & ");
-}
-
-
-void InsetMathGrid::addRow(row_type row)
-{
-       rowinfo_.insert(rowinfo_.begin() + row + 1, RowInfo());
-       cells_.insert
-               (cells_.begin() + (row + 1) * ncols(), ncols(), MathArray());
-       cellinfo_.insert
-               (cellinfo_.begin() + (row + 1) * ncols(), ncols(), CellInfo());
-}
-
-
-void InsetMathGrid::appendRow()
-{
-       rowinfo_.push_back(RowInfo());
-       //cells_.insert(cells_.end(), ncols(), MathArray());
-       for (col_type col = 0; col < ncols(); ++col) {
-               cells_.push_back(cells_type::value_type());
-               cellinfo_.push_back(CellInfo());
-       }
-}
-
-
-void InsetMathGrid::delRow(row_type row)
-{
-       if (nrows() == 1)
-               return;
-
-       cells_type::iterator it = cells_.begin() + row * ncols();
-       cells_.erase(it, it + ncols());
-
-       vector<CellInfo>::iterator jt = cellinfo_.begin() + row * ncols();
-       cellinfo_.erase(jt, jt + ncols());
-
-       rowinfo_.erase(rowinfo_.begin() + row);
-}
-
-
-void InsetMathGrid::copyRow(row_type row)
-{
-       addRow(row);
-       for (col_type col = 0; col < ncols(); ++col)
-               cells_[(row + 1) * ncols() + col] = cells_[row * ncols() + col];
-}
-
-
-void InsetMathGrid::swapRow(row_type row)
-{
-       if (nrows() == 1)
-               return;
-       if (row + 1 == nrows())
-               --row;
-       for (col_type col = 0; col < ncols(); ++col)
-               swap(cells_[row * ncols() + col], cells_[(row + 1) * ncols() + col]);
-}
-
-
-void InsetMathGrid::addCol(col_type newcol)
-{
-       const col_type nc = ncols();
-       const row_type nr = nrows();
-       cells_type new_cells((nc + 1) * nr);
-       vector<CellInfo> new_cellinfo((nc + 1) * nr);
-
-       for (row_type row = 0; row < nr; ++row)
-               for (col_type col = 0; col < nc; ++col) {
-                       new_cells[row * (nc + 1) + col + (col > newcol)]
-                               = cells_[row * nc + col];
-                       new_cellinfo[row * (nc + 1) + col + (col > newcol)]
-                               = cellinfo_[row * nc + col];
-               }
-       swap(cells_, new_cells);
-       swap(cellinfo_, new_cellinfo);
-
-       ColInfo inf;
-       inf.skip_  = defaultColSpace(newcol);
-       inf.align_ = defaultColAlign(newcol);
-       colinfo_.insert(colinfo_.begin() + newcol, inf);
-}
-
-
-void InsetMathGrid::delCol(col_type col)
-{
-       if (ncols() == 1)
-               return;
-
-       cells_type tmpcells;
-       vector<CellInfo> tmpcellinfo;
-       for (col_type i = 0; i < nargs(); ++i)
-               if (i % ncols() != col) {
-                       tmpcells.push_back(cells_[i]);
-                       tmpcellinfo.push_back(cellinfo_[i]);
-               }
-       swap(cells_, tmpcells);
-       swap(cellinfo_, tmpcellinfo);
-
-       colinfo_.erase(colinfo_.begin() + col);
-}
-
-
-void InsetMathGrid::copyCol(col_type col)
-{
-       addCol(col);
-       for (row_type row = 0; row < nrows(); ++row)
-               cells_[row * ncols() + col + 1] = cells_[row * ncols() + col];
-}
-
-
-void InsetMathGrid::swapCol(col_type col)
-{
-       if (ncols() == 1)
-               return;
-       if (col + 1 == ncols())
-               --col;
-       for (row_type row = 0; row < nrows(); ++row)
-               swap(cells_[row * ncols() + col], cells_[row * ncols() + col + 1]);
-}
-
-
-int InsetMathGrid::cellXOffset(idx_type idx) const
-{
-       col_type c = col(idx);
-       int x = colinfo_[c].offset_;
-       char align = colinfo_[c].align_;
-       if (align == 'r' || align == 'R')
-               x += colinfo_[c].width_ - cell(idx).width();
-       if (align == 'c' || align == 'C')
-               x += (colinfo_[c].width_ - cell(idx).width()) / 2;
-       return x;
-}
-
-
-int InsetMathGrid::cellYOffset(idx_type idx) const
-{
-       return rowinfo_[row(idx)].offset_;
-}
-
-
-bool InsetMathGrid::idxUpDown(LCursor & cur, bool up) const
-{
-       if (up) {
-               if (cur.row() == 0)
-                       return false;
-               cur.idx() -= ncols();
-       } else {
-               if (cur.row() + 1 >= nrows())
-                       return false;
-               cur.idx() += ncols();
-       }
-       cur.pos() = cur.cell().x2pos(cur.x_target() - cur.cell().xo(cur.bv()));
-       return true;
-}
-
-
-bool InsetMathGrid::idxLeft(LCursor & cur) const
-{
-       // leave matrix if on the left hand edge
-       if (cur.col() == 0)
-               return false;
-       --cur.idx();
-       cur.pos() = cur.lastpos();
-       return true;
-}
-
-
-bool InsetMathGrid::idxRight(LCursor & cur) const
-{
-       // leave matrix if on the right hand edge
-       if (cur.col() + 1 == ncols())
-               return false;
-       ++cur.idx();
-       cur.pos() = 0;
-       return true;
-}
-
-
-bool InsetMathGrid::idxFirst(LCursor & cur) const
-{
-       switch (v_align_) {
-               case 't':
-                       cur.idx() = 0;
-                       break;
-               case 'b':
-                       cur.idx() = (nrows() - 1) * ncols();
-                       break;
-               default:
-                       cur.idx() = ((nrows() - 1) / 2) * ncols();
-       }
-       cur.pos() = 0;
-       return true;
-}
-
-
-bool InsetMathGrid::idxLast(LCursor & cur) const
-{
-       switch (v_align_) {
-               case 't':
-                       cur.idx() = ncols() - 1;
-                       break;
-               case 'b':
-                       cur.idx() = nargs() - 1;
-                       break;
-               default:
-                       cur.idx() = ((nrows() - 1) / 2 + 1) * ncols() - 1;
-       }
-       cur.pos() = cur.lastpos();
-       return true;
-}
-
-
-bool InsetMathGrid::idxDelete(idx_type & idx)
-{
-       // nothing to do if we have just one row
-       if (nrows() == 1)
-               return false;
-
-       // nothing to do if we are in the middle of the last row of the inset
-       if (idx + ncols() > nargs())
-               return false;
-
-       // try to delete entire sequence of ncols() empty cells if possible
-       for (idx_type i = idx; i < idx + ncols(); ++i)
-               if (cell(i).size())
-                       return false;
-
-       // move cells if necessary
-       for (idx_type i = index(row(idx), 0); i < idx; ++i)
-               swap(cell(i), cell(i + ncols()));
-
-       delRow(row(idx));
-
-       if (idx >= nargs())
-               idx = nargs() - 1;
-
-       // undo effect of Ctrl-Tab (i.e. pull next cell)
-       //if (idx + 1 != nargs())
-       //      cell(idx).swap(cell(idx + 1));
-
-       // we handled the event..
-       return true;
-}
-
-
-// reimplement old behaviour when pressing Delete in the last position
-// of a cell
-void InsetMathGrid::idxGlue(idx_type idx)
-{
-       col_type c = col(idx);
-       if (c + 1 == ncols()) {
-               if (row(idx) + 1 != nrows()) {
-                       for (col_type cc = 0; cc < ncols(); ++cc)
-                               cell(idx).append(cell(idx + cc + 1));
-                       delRow(row(idx) + 1);
-               }
-       } else {
-               cell(idx).append(cell(idx + 1));
-               for (col_type cc = c + 2; cc < ncols(); ++cc)
-                       cell(idx - c + cc - 1) = cell(idx - c + cc);
-               cell(idx - c + ncols() - 1).clear();
-       }
-}
-
-
-InsetMathGrid::RowInfo const & InsetMathGrid::rowinfo(row_type row) const
-{
-       return rowinfo_[row];
-}
-
-
-InsetMathGrid::RowInfo & InsetMathGrid::rowinfo(row_type row)
-{
-       return rowinfo_[row];
-}
-
-
-bool InsetMathGrid::idxBetween(idx_type idx, idx_type from, idx_type to) const
-{
-       row_type const ri = row(idx);
-       row_type const r1 = min(row(from), row(to));
-       row_type const r2 = max(row(from), row(to));
-       col_type const ci = col(idx);
-       col_type const c1 = min(col(from), col(to));
-       col_type const c2 = max(col(from), col(to));
-       return r1 <= ri && ri <= r2 && c1 <= ci && ci <= c2;
-}
-
-
-
-void InsetMathGrid::normalize(NormalStream & os) const
-{
-       os << "[grid ";
-       for (row_type row = 0; row < nrows(); ++row) {
-               os << "[row ";
-               for (col_type col = 0; col < ncols(); ++col)
-                       os << "[cell " << cell(index(row, col)) << ']';
-               os << ']';
-       }
-       os << ']';
-}
-
-
-void InsetMathGrid::mathmlize(MathStream & os) const
-{
-       os << MTag("mtable");
-       for (row_type row = 0; row < nrows(); ++row) {
-               os << MTag("mtr");
-               for (col_type col = 0; col < ncols(); ++col)
-                       os << cell(index(row, col));
-               os << ETag("mtr");
-       }
-       os << ETag("mtable");
-}
-
-
-void InsetMathGrid::write(WriteStream & os) const
-{
-       docstring eol;
-       for (row_type row = 0; row < nrows(); ++row) {
-               os << verboseHLine(rowinfo_[row].lines_);
-               // don't write & and empty cells at end of line
-               col_type lastcol = 0;
-               bool emptyline = true;
-               for (col_type col = 0; col < ncols(); ++col)
-                       if (!cell(index(row, col)).empty()) {
-                               lastcol = col + 1;
-                               emptyline = false;
-                       }
-               for (col_type col = 0; col < lastcol; ++col)
-                       os << cell(index(row, col)) << eocString(col, lastcol);
-               eol = eolString(row, emptyline, os.fragile());
-               os << eol;
-               // append newline only if line wasn't completely empty
-               // and this was not the last line in the grid
-               if (!emptyline && row + 1 < nrows())
-                       os << "\n";
-       }
-       docstring const s = verboseHLine(rowinfo_[nrows()].lines_);
-       if (!s.empty()) {
-               if (eol.empty()) {
-                       if (os.fragile())
-                               os << "\\protect";
-                       os << "\\\\";
-               }
-               os << s;
-       }
-}
-
-
-int InsetMathGrid::colsep() const
-{
-       return 6;
-}
-
-
-int InsetMathGrid::rowsep() const
-{
-       return 6;
-}
-
-
-int InsetMathGrid::hlinesep() const
-{
-       return 3;
-}
-
-
-int InsetMathGrid::vlinesep() const
-{
-       return 3;
-}
-
-
-int InsetMathGrid::border() const
-{
-       return 1;
-}
-
-
-void InsetMathGrid::splitCell(LCursor & cur)
-{
-       if (cur.idx() == cur.lastidx())
-               return;
-       MathArray ar = cur.cell();
-       ar.erase(0, cur.pos());
-       cur.cell().erase(cur.pos(), cur.lastpos());
-       ++cur.idx();
-       cur.pos() = 0;
-       cur.cell().insert(0, ar);
-}
-
-
-void InsetMathGrid::doDispatch(LCursor & cur, FuncRequest & cmd)
-{
-       //lyxerr << "*** InsetMathGrid: request: " << cmd << endl;
-       switch (cmd.action) {
-
-       case LFUN_MOUSE_RELEASE:
-               //if (cmd.button() == mouse_button::button3) {
-               //      GridInsetMailer(*this).showDialog();
-               //      return DispatchResult(true, true);
-               //}
-               InsetMathNest::doDispatch(cur, cmd);
-               break;
-
-       case LFUN_INSET_DIALOG_UPDATE:
-               GridInsetMailer(*this).updateDialog(&cur.bv());
-               break;
-
-       // insert file functions
-       case LFUN_LINE_DELETE:
-               // FIXME: We use recordUndoInset when a change reflects more
-               // than one cell, because recordUndo does not work for
-               // multiple cells. Unfortunately this puts the cursor in front
-               // of the inset after undo. This is (especilally for large
-               // grids) annoying.
-               recordUndoInset(cur);
-               //autocorrect_ = false;
-               //macroModeClose();
-               //if (selection_) {
-               //      selDel();
-               //      break;
-               //}
-               if (nrows() > 1)
-                       delRow(cur.row());
-               if (cur.idx() > cur.lastidx())
-                       cur.idx() = cur.lastidx();
-               if (cur.pos() > cur.lastpos())
-                       cur.pos() = cur.lastpos();
-               break;
-
-       case LFUN_CELL_SPLIT:
-               recordUndo(cur);
-               splitCell(cur);
-               break;
-
-       case LFUN_CELL_BACKWARD:
-               // See below.
-               cur.selection() = false;
-               if (!idxPrev(cur)) {
-                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
-                       cur.undispatched();
-               }
-               break;
-
-       case LFUN_CELL_FORWARD:
-               // Can't handle selection by additional 'shift' as this is
-               // hard bound to LFUN_CELL_BACKWARD
-               cur.selection() = false;
-               if (!idxNext(cur)) {
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
-                       cur.undispatched();
-               }
-               break;
-
-       case LFUN_BREAK_LINE: {
-               recordUndoInset(cur);
-               row_type const r = cur.row();
-               addRow(r);
-
-               // split line
-               for (col_type c = col(cur.idx()) + 1; c < ncols(); ++c)
-                       swap(cell(index(r, c)), cell(index(r + 1, c)));
-
-               // split cell
-               splitCell(cur);
-               swap(cell(cur.idx()), cell(cur.idx() + ncols() - 1));
-               if (cur.idx() > 0)
-                       --cur.idx();
-               cur.pos() = cur.lastpos();
-
-               //mathcursor->normalize();
-               //cmd = FuncRequest(LFUN_FINISHED_LEFT);
-               break;
-       }
-
-       case LFUN_TABULAR_FEATURE: {
-               recordUndoInset(cur);
-               //lyxerr << "handling tabular-feature " << to_utf8(cmd.argument()) << endl;
-               istringstream is(to_utf8(cmd.argument()));
-               string s;
-               is >> s;
-               if (s == "valign-top")
-                       valign('t');
-               else if (s == "valign-middle")
-                       valign('c');
-               else if (s == "valign-bottom")
-                       valign('b');
-               else if (s == "align-left")
-                       halign('l', cur.col());
-               else if (s == "align-right")
-                       halign('r', cur.col());
-               else if (s == "align-center")
-                       halign('c', cur.col());
-               else if (s == "append-row")
-                       for (int i = 0, n = extractInt(is); i < n; ++i)
-                               addRow(cur.row());
-               else if (s == "delete-row") {
-                       for (int i = 0, n = extractInt(is); i < n; ++i) {
-                               delRow(cur.row());
-                               if (cur.idx() >= nargs())
-                                       cur.idx() -= ncols();
-                       }
-                       cur.pos() = 0; // trick, see below
-               }
-               else if (s == "copy-row") {
-                       // Here (as later) we save the cursor col/row
-                       // in order to restore it after operation.
-                       row_type const r = cur.row();
-                       col_type const c = cur.col();
-                       for (int i = 0, n = extractInt(is); i < n; ++i)
-                               copyRow(cur.row());
-                       cur.idx() = index(r, c);
-               }
-               else if (s == "swap-row") {
-                       swapRow(cur.row());
-                       // Trick to suppress same-idx-means-different-cell
-                       // assertion crash:
-                       cur.pos() = 0;
-               }
-               else if (s == "add-hline-above")
-                       rowinfo_[cur.row()].lines_++;
-               else if (s == "add-hline-below")
-                       rowinfo_[cur.row()+1].lines_++;
-               else if (s == "delete-hline-above")
-                       rowinfo_[cur.row()].lines_--;
-               else if (s == "delete-hline-below")
-                       rowinfo_[cur.row()+1].lines_--;
-               else if (s == "append-column") {
-                       row_type const r = cur.row();
-                       col_type const c = cur.col();
-                       for (int i = 0, n = extractInt(is); i < n; ++i)
-                               addCol(cur.col());
-                       cur.idx() = index(r, c);
-               }
-               else if (s == "delete-column") {
-                       row_type const r = cur.row();
-                       col_type const c = cur.col();
-                       for (int i = 0, n = extractInt(is); i < n; ++i)
-                               delCol(col(cur.idx()));
-                       cur.idx() = index(r, min(c, cur.ncols() - 1));
-                       cur.pos() = 0; // trick, see above
-               }
-               else if (s == "copy-column") {
-                       row_type const r = cur.row();
-                       col_type const c = cur.col();
-                       copyCol(cur.col());
-                       cur.idx() = index(r, c);
-               }
-               else if (s == "swap-column") {
-                       swapCol(cur.col());
-                       cur.pos() = 0; // trick, see above
-               }
-               else if (s == "add-vline-left")
-                       colinfo_[cur.col()].lines_++;
-               else if (s == "add-vline-right")
-                       colinfo_[cur.col()+1].lines_++;
-               else if (s == "delete-vline-left")
-                       colinfo_[cur.col()].lines_--;
-               else if (s == "delete-vline-right")
-                       colinfo_[cur.col()+1].lines_--;
-               else {
-                       cur.undispatched();
-                       break;
-               }
-               lyxerr << "returning FINISHED_LEFT" << endl;
-               break;
-       }
-
-       case LFUN_PASTE: {
-               cur.message(_("Paste"));
-               cap::replaceSelection(cur);
-               docstring topaste;
-               if (cmd.argument().empty() && !theClipboard().isInternal())
-                       topaste = theClipboard().getAsText();
-               else {
-                       idocstringstream is(cmd.argument());
-                       int n = 0;
-                       is >> n;
-                       topaste = cap::getSelection(cur.buffer(), n);
-               }
-               InsetMathGrid grid(1, 1);
-               if (!topaste.empty())
-                       mathed_parse_normal(grid, topaste);
-
-               if (grid.nargs() == 1) {
-                       // single cell/part of cell
-                       recordUndo(cur);
-                       cur.cell().insert(cur.pos(), grid.cell(0));
-                       cur.pos() += grid.cell(0).size();
-               } else {
-                       // multiple cells
-                       recordUndoInset(cur);
-                       col_type const numcols =
-                               min(grid.ncols(), ncols() - col(cur.idx()));
-                       row_type const numrows =
-                               min(grid.nrows(), nrows() - cur.row());
-                       for (row_type r = 0; r < numrows; ++r) {
-                               for (col_type c = 0; c < numcols; ++c) {
-                                       idx_type i = index(r + cur.row(), c + col(cur.idx()));
-                                       cell(i).insert(0, grid.cell(grid.index(r, c)));
-                               }
-                               // append the left over horizontal cells to the last column
-                               idx_type i = index(r + cur.row(), ncols() - 1);
-                               for (InsetMath::col_type c = numcols; c < grid.ncols(); ++c)
-                                       cell(i).append(grid.cell(grid.index(r, c)));
-                       }
-                       // append the left over vertical cells to the last _cell_
-                       idx_type i = nargs() - 1;
-                       for (row_type r = numrows; r < grid.nrows(); ++r)
-                               for (col_type c = 0; c < grid.ncols(); ++c)
-                                       cell(i).append(grid.cell(grid.index(r, c)));
-               }
-               cur.clearSelection(); // bug 393
-               cur.bv().switchKeyMap();
-               finishUndo();
-               break;
-       }
-
-       case LFUN_LINE_BEGIN_SELECT:
-       case LFUN_LINE_BEGIN:
-       case LFUN_WORD_BACKWARD_SELECT:
-       case LFUN_WORD_BACKWARD:
-               cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT ||
-                               cmd.action == LFUN_LINE_BEGIN_SELECT);
-               cur.macroModeClose();
-               if (cur.pos() != 0) {
-                       cur.pos() = 0;
-               } else if (cur.idx() % cur.ncols() != 0) {
-                       cur.idx() -= cur.idx() % cur.ncols();
-                       cur.pos() = 0;
-               } else if (cur.idx() != 0) {
-                       cur.idx() = 0;
-                       cur.pos() = 0;
-               } else {
-                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
-                       cur.undispatched();
-               }
-               break;
-
-       case LFUN_WORD_FORWARD_SELECT:
-       case LFUN_WORD_FORWARD:
-       case LFUN_LINE_END_SELECT:
-       case LFUN_LINE_END:
-               cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT ||
-                               cmd.action == LFUN_LINE_END_SELECT);
-               cur.macroModeClose();
-               cur.clearTargetX();
-               if (cur.pos() != cur.lastpos()) {
-                       cur.pos() = cur.lastpos();
-               } else if ((cur.idx() + 1) % cur.ncols() != 0) {
-                       cur.idx() += cur.ncols() - 1 - cur.idx() % cur.ncols();
-                       cur.pos() = cur.lastpos();
-               } else if (cur.idx() != cur.lastidx()) {
-                       cur.idx() = cur.lastidx();
-                       cur.pos() = cur.lastpos();
-               } else {
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
-                       cur.undispatched();
-               }
-               break;
-
-       default:
-               InsetMathNest::doDispatch(cur, cmd);
-       }
-}
-
-
-bool InsetMathGrid::getStatus(LCursor & cur, FuncRequest const & cmd,
-               FuncStatus & status) const
-{
-       switch (cmd.action) {
-       case LFUN_TABULAR_FEATURE: {
-               string const s = to_utf8(cmd.argument());
-               if (nrows() <= 1 && (s == "delete-row" || s == "swap-row")) {
-                       status.enabled(false);
-                       status.message(from_utf8(N_("Only one row")));
-                       return true;
-               }
-               if (ncols() <= 1 &&
-                   (s == "delete-column" || s == "swap-column")) {
-                       status.enabled(false);
-                       status.message(from_utf8(N_("Only one column")));
-                       return true;
-               }
-               if ((rowinfo_[cur.row()].lines_ == 0 &&
-                    s == "delete-hline-above") ||
-                   (rowinfo_[cur.row() + 1].lines_ == 0 &&
-                    s == "delete-hline-below")) {
-                       status.enabled(false);
-                       status.message(from_utf8(N_("No hline to delete")));
-                       return true;
-               }
-
-               if ((colinfo_[cur.col()].lines_ == 0 &&
-                    s == "delete-vline-left") ||
-                   (colinfo_[cur.col() + 1].lines_ == 0 &&
-                    s == "delete-vline-right")) {
-                       status.enabled(false);
-                       status.message(from_utf8(N_("No vline to delete")));
-                       return true;
-               }
-               if (s == "valign-top" || s == "valign-middle" ||
-                   s == "valign-bottom" || s == "align-left" ||
-                   s == "align-right" || s == "align-center" ||
-                   s == "append-row" || s == "delete-row" ||
-                   s == "copy-row" || s == "swap-row" ||
-                   s == "add-hline-above" || s == "add-hline-below" ||
-                   s == "delete-hline-above" || s == "delete-hline-below" ||
-                   s == "append-column" || s == "delete-column" ||
-                   s == "copy-column" || s == "swap-column" ||
-                   s == "add-vline-left" || s == "add-vline-right" ||
-                   s == "delete-vline-left" || s == "delete-vline-right")
-                       status.enabled(true);
-               else {
-                       status.enabled(false);
-                       status.message(bformat(
-                               from_utf8(N_("Unknown tabular feature '%1$s'")), lyx::from_ascii(s)));
-               }
-
-               status.setOnOff(s == "align-left"    && halign(cur.col()) == 'l'
-                          || s == "align-right"   && halign(cur.col()) == 'r'
-                          || s == "align-center"  && halign(cur.col()) == 'c'
-                          || s == "valign-top"    && valign() == 't'
-                          || s == "valign-bottom" && valign() == 'b'
-                          || s == "valign-middle" && valign() == 'm');
-
-#if 0
-               // FIXME: What did this code do?
-               // Please check whether it is still needed!
-               // should be more precise
-               if (v_align_ == '\0') {
-                       status.enable(true);
-                       break;
-               }
-               if (cmd.argument().empty()) {
-                       status.enable(false);
-                       break;
-               }
-               if (!support::contains("tcb", cmd.argument()[0])) {
-                       status.enable(false);
-                       break;
-               }
-               status.setOnOff(cmd.argument()[0] == v_align_);
-               status.enabled(true);
-#endif
-               return true;
-       }
-
-       case LFUN_CELL_SPLIT:
-               status.enabled(true);
-               return true;
-
-       case LFUN_CELL_BACKWARD:
-       case LFUN_CELL_FORWARD:
-               status.enabled(true);
-               return true;
-
-       default:
-               return InsetMathNest::getStatus(cur, cmd, status);
-       }
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathGrid.cpp b/src/mathed/InsetMathGrid.cpp
new file mode 100644 (file)
index 0000000..53354fa
--- /dev/null
@@ -0,0 +1,1400 @@
+/**
+ * \file InsetMathGrid.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathGrid.h"
+#include "MathData.h"
+#include "MathParser.h"
+#include "MathStream.h"
+
+#include "BufferView.h"
+#include "CutAndPaste.h"
+#include "FuncStatus.h"
+#include "LColor.h"
+#include "cursor.h"
+#include "debug.h"
+#include "funcrequest.h"
+#include "gettext.h"
+#include "undo.h"
+
+#include "frontends/Clipboard.h"
+#include "frontends/Painter.h"
+
+#include "insets/MailInset.h"
+
+#include "support/lstrings.h"
+
+#include <sstream>
+
+
+namespace lyx {
+
+using support::bformat;
+
+using std::endl;
+using std::max;
+using std::min;
+using std::swap;
+
+using std::string;
+using std::auto_ptr;
+using std::istream;
+using std::istringstream;
+using std::vector;
+
+class GridInsetMailer : public MailInset {
+public:
+       GridInsetMailer(InsetMathGrid & inset) : inset_(inset) {}
+       ///
+       virtual string const & name() const
+       {
+               static string const theName = "tabular";
+               return theName;
+       }
+       ///
+       virtual string const inset2string(Buffer const &) const
+       {
+               odocstringstream data;
+               //data << name() << " active_cell " << inset.getActCell() << '\n';
+               data << from_utf8(name()) << " active_cell " << 0 << '\n';
+               WriteStream ws(data);
+               inset_.write(ws);
+               return to_utf8(data.str());
+       }
+
+protected:
+       InsetBase & inset() const { return inset_; }
+       InsetMathGrid & inset_;
+};
+
+
+namespace {
+
+docstring verboseHLine(int n)
+{
+       docstring res;
+       for (int i = 0; i < n; ++i)
+               res += "\\hline";
+       if (n)
+               res += ' ';
+       return res;
+}
+
+
+int extractInt(istream & is)
+{
+       int num = 1;
+       is >> num;
+       return (num == 0) ? 1 : num;
+}
+
+}
+
+
+//////////////////////////////////////////////////////////////
+
+
+InsetMathGrid::CellInfo::CellInfo()
+       : dummy_(false)
+{}
+
+
+
+
+//////////////////////////////////////////////////////////////
+
+
+InsetMathGrid::RowInfo::RowInfo()
+       : lines_(0), skip_(0), allow_pagebreak_(true)
+{}
+
+
+
+int InsetMathGrid::RowInfo::skipPixels() const
+{
+       return crskip_.inBP();
+}
+
+
+
+//////////////////////////////////////////////////////////////
+
+
+InsetMathGrid::ColInfo::ColInfo()
+       : align_('c'), lines_(0)
+{}
+
+
+//////////////////////////////////////////////////////////////
+
+
+InsetMathGrid::InsetMathGrid(char v, docstring const & h)
+       : InsetMathNest(guessColumns(h)),
+         rowinfo_(2),
+         colinfo_(guessColumns(h) + 1),
+         cellinfo_(1 * guessColumns(h))
+{
+       setDefaults();
+       valign(v);
+       halign(h);
+       //lyxerr << "created grid with " << ncols() << " columns" << endl;
+}
+
+
+InsetMathGrid::InsetMathGrid()
+       : InsetMathNest(1),
+         rowinfo_(1 + 1),
+               colinfo_(1 + 1),
+               cellinfo_(1),
+               v_align_('c')
+{
+       setDefaults();
+}
+
+
+InsetMathGrid::InsetMathGrid(col_type m, row_type n)
+       : InsetMathNest(m * n),
+         rowinfo_(n + 1),
+               colinfo_(m + 1),
+               cellinfo_(m * n),
+               v_align_('c')
+{
+       setDefaults();
+}
+
+
+InsetMathGrid::InsetMathGrid(col_type m, row_type n, char v, docstring const & h)
+       : InsetMathNest(m * n),
+         rowinfo_(n + 1),
+         colinfo_(m + 1),
+               cellinfo_(m * n),
+               v_align_(v)
+{
+       setDefaults();
+       valign(v);
+       halign(h);
+}
+
+
+auto_ptr<InsetBase> InsetMathGrid::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathGrid(*this));
+}
+
+
+InsetMath::idx_type InsetMathGrid::index(row_type row, col_type col) const
+{
+       return col + ncols() * row;
+}
+
+
+void InsetMathGrid::setDefaults()
+{
+       if (ncols() <= 0)
+               lyxerr << "positive number of columns expected" << endl;
+       //if (nrows() <= 0)
+       //      lyxerr << "positive number of rows expected" << endl;
+       for (col_type col = 0; col < ncols(); ++col) {
+               colinfo_[col].align_ = defaultColAlign(col);
+               colinfo_[col].skip_  = defaultColSpace(col);
+       }
+}
+
+
+void InsetMathGrid::halign(docstring const & hh)
+{
+       col_type col = 0;
+       for (docstring::const_iterator it = hh.begin(); it != hh.end(); ++it) {
+               char_type c = *it;
+               if (c == '|') {
+                       colinfo_[col].lines_++;
+               } else if (col >= ncols()) {
+                       // Only '|' is allowed in the last dummy column
+                       break;
+               } else if (c == 'c' || c == 'l' || c == 'r') {
+                       colinfo_[col].align_ = (char)c;
+                       ++col;
+                       colinfo_[col].lines_ = 0;
+               } else {
+                       lyxerr << "unknown column separator: '" << c << "'" << endl;
+               }
+       }
+
+/*
+       col_type n = hh.size();
+       if (n > ncols())
+               n = ncols();
+       for (col_type col = 0; col < n; ++col)
+               colinfo_[col].align_ = hh[col];
+*/
+}
+
+
+InsetMathGrid::col_type InsetMathGrid::guessColumns(docstring const & hh) const
+{
+       col_type col = 0;
+       for (docstring::const_iterator it = hh.begin(); it != hh.end(); ++it)
+               if (*it == 'c' || *it == 'l' || *it == 'r')
+                       ++col;
+       // let's have at least one column, even if we did not recognize its
+       // alignment
+       if (col == 0)
+               col = 1;
+       return col;
+}
+
+
+void InsetMathGrid::halign(char h, col_type col)
+{
+       colinfo_[col].align_ = h;
+}
+
+
+char InsetMathGrid::halign(col_type col) const
+{
+       return colinfo_[col].align_;
+}
+
+
+docstring InsetMathGrid::halign() const
+{
+       docstring res;
+       for (col_type col = 0; col < ncols(); ++col) {
+               res += docstring(colinfo_[col].lines_, '|');
+               res += colinfo_[col].align_;
+       }
+       return res + docstring(colinfo_[ncols()].lines_, '|');
+}
+
+
+void InsetMathGrid::valign(char c)
+{
+       v_align_ = c;
+}
+
+
+char InsetMathGrid::valign() const
+{
+       return v_align_;
+}
+
+
+InsetMathGrid::col_type InsetMathGrid::ncols() const
+{
+       return colinfo_.size() - 1;
+}
+
+
+InsetMathGrid::row_type InsetMathGrid::nrows() const
+{
+       return rowinfo_.size() - 1;
+}
+
+
+InsetMathGrid::col_type InsetMathGrid::col(idx_type idx) const
+{
+       return idx % ncols();
+}
+
+
+InsetMathGrid::row_type InsetMathGrid::row(idx_type idx) const
+{
+       return idx / ncols();
+}
+
+
+void InsetMathGrid::vcrskip(LyXLength const & crskip, row_type row)
+{
+       rowinfo_[row].crskip_ = crskip;
+}
+
+
+LyXLength InsetMathGrid::vcrskip(row_type row) const
+{
+       return rowinfo_[row].crskip_;
+}
+
+
+void InsetMathGrid::metrics(MetricsInfo & mi) const
+{
+       // let the cells adjust themselves
+       InsetMathNest::metrics(mi);
+
+       // compute absolute sizes of vertical structure
+       for (row_type row = 0; row < nrows(); ++row) {
+               int asc  = 0;
+               int desc = 0;
+               for (col_type col = 0; col < ncols(); ++col) {
+                       MathArray const & c = cell(index(row, col));
+                       asc  = max(asc,  c.ascent());
+                       desc = max(desc, c.descent());
+               }
+               rowinfo_[row].ascent_  = asc;
+               rowinfo_[row].descent_ = desc;
+       }
+       rowinfo_[0].ascent_       += hlinesep() * rowinfo_[0].lines_;
+       rowinfo_[nrows()].ascent_  = 0;
+       rowinfo_[nrows()].descent_ = 0;
+
+       // compute vertical offsets
+       rowinfo_[0].offset_ = 0;
+       for (row_type row = 1; row <= nrows(); ++row) {
+               rowinfo_[row].offset_  =
+                       rowinfo_[row - 1].offset_  +
+                       rowinfo_[row - 1].descent_ +
+                       rowinfo_[row - 1].skipPixels() +
+                       rowsep() +
+                       rowinfo_[row].lines_ * hlinesep() +
+                       rowinfo_[row].ascent_;
+       }
+
+       // adjust vertical offset
+       int h = 0;
+       switch (v_align_) {
+               case 't':
+                       h = 0;
+                       break;
+               case 'b':
+                       h = rowinfo_[nrows() - 1].offset_;
+                       break;
+               default:
+                       h = rowinfo_[nrows() - 1].offset_ / 2;
+       }
+       for (row_type row = 0; row <= nrows(); ++row)
+               rowinfo_[row].offset_ -= h;
+
+
+       // compute absolute sizes of horizontal structure
+       for (col_type col = 0; col < ncols(); ++col) {
+               int wid = 0;
+               for (row_type row = 0; row < nrows(); ++row)
+                       wid = max(wid, cell(index(row, col)).width());
+               colinfo_[col].width_ = wid;
+       }
+       colinfo_[ncols()].width_  = 0;
+
+       // compute horizontal offsets
+       colinfo_[0].offset_ = border();
+       for (col_type col = 1; col <= ncols(); ++col) {
+               colinfo_[col].offset_ =
+                       colinfo_[col - 1].offset_ +
+                       colinfo_[col - 1].width_ +
+                       colinfo_[col - 1].skip_ +
+                       colsep() +
+                       colinfo_[col].lines_ * vlinesep();
+       }
+
+
+       dim_.wid   =   colinfo_[ncols() - 1].offset_
+                      + colinfo_[ncols() - 1].width_
+                + vlinesep() * colinfo_[ncols()].lines_
+                      + border();
+
+       dim_.asc  = - rowinfo_[0].offset_
+                      + rowinfo_[0].ascent_
+                + hlinesep() * rowinfo_[0].lines_
+                      + border();
+
+       dim_.des =   rowinfo_[nrows() - 1].offset_
+                      + rowinfo_[nrows() - 1].descent_
+                + hlinesep() * rowinfo_[nrows()].lines_
+                      + border();
+
+
+/*
+       // Increase ws_[i] for 'R' columns (except the first one)
+       for (int i = 1; i < nc_; ++i)
+               if (align_[i] == 'R')
+                       ws_[i] += 10 * df_width;
+       // Increase ws_[i] for 'C' column
+       if (align_[0] == 'C')
+               if (ws_[0] < 7 * workwidth / 8)
+                       ws_[0] = 7 * workwidth / 8;
+
+       // Adjust local tabs
+       width = colsep();
+       for (cxrow = row_.begin(); cxrow; ++cxrow) {
+               int rg = COLSEP;
+               int lf = 0;
+               for (int i = 0; i < nc_; ++i) {
+                       bool isvoid = false;
+                       if (cxrow->getTab(i) <= 0) {
+                               cxrow->setTab(i, df_width);
+                               isvoid = true;
+                       }
+                       switch (align_[i]) {
+                       case 'l':
+                               lf = 0;
+                               break;
+                       case 'c':
+                               lf = (ws_[i] - cxrow->getTab(i))/2;
+                               break;
+                       case 'r':
+                       case 'R':
+                               lf = ws_[i] - cxrow->getTab(i);
+                               break;
+                       case 'C':
+                               if (cxrow == row_.begin())
+                                       lf = 0;
+                               else if (cxrow.is_last())
+                                       lf = ws_[i] - cxrow->getTab(i);
+                               else
+                                       lf = (ws_[i] - cxrow->getTab(i))/2;
+                               break;
+                       }
+                       int const ww = (isvoid) ? lf : lf + cxrow->getTab(i);
+                       cxrow->setTab(i, lf + rg);
+                       rg = ws_[i] - ww + colsep();
+                       if (cxrow == row_.begin())
+                               width += ws_[i] + colsep();
+               }
+               cxrow->setBaseline(cxrow->getBaseline() - ascent);
+       }
+*/
+       metricsMarkers2(dim_);
+}
+
+
+bool InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       dim = dim_;
+       metrics(mi);
+       if (dim_ == dim)
+               return false;
+       dim = dim_;
+       return true;
+}
+
+
+void InsetMathGrid::draw(PainterInfo & pi, int x, int y) const
+{
+       drawWithMargin(pi, x, y, 0, 0);
+}
+
+void InsetMathGrid::drawWithMargin(PainterInfo & pi, int x, int y,
+       int lmargin, int rmargin) const
+{
+       for (idx_type idx = 0; idx < nargs(); ++idx)
+               cell(idx).draw(pi, x + lmargin + cellXOffset(idx),
+                       y + cellYOffset(idx));
+
+       for (row_type row = 0; row <= nrows(); ++row)
+               for (unsigned int i = 0; i < rowinfo_[row].lines_; ++i) {
+                       int yy = y + rowinfo_[row].offset_ - rowinfo_[row].ascent_
+                               - i * hlinesep() - hlinesep()/2 - rowsep()/2;
+                       pi.pain.line(x + lmargin + 1, yy,
+                                    x + dim_.width() - rmargin - 1, yy,
+                                    LColor::foreground);
+               }
+
+       for (col_type col = 0; col <= ncols(); ++col)
+               for (unsigned int i = 0; i < colinfo_[col].lines_; ++i) {
+                       int xx = x + lmargin + colinfo_[col].offset_
+                               - i * vlinesep() - vlinesep()/2 - colsep()/2;
+                       pi.pain.line(xx, y - dim_.ascent() + 1,
+                                    xx, y + dim_.descent() - 1,
+                                    LColor::foreground);
+               }
+       drawMarkers2(pi, x, y);
+}
+
+
+void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       // let the cells adjust themselves
+       //InsetMathNest::metrics(mi);
+       for (idx_type i = 0; i < nargs(); ++i)
+               cell(i).metricsT(mi, dim);
+
+       // compute absolute sizes of vertical structure
+       for (row_type row = 0; row < nrows(); ++row) {
+               int asc  = 0;
+               int desc = 0;
+               for (col_type col = 0; col < ncols(); ++col) {
+                       MathArray const & c = cell(index(row, col));
+                       asc  = max(asc,  c.ascent());
+                       desc = max(desc, c.descent());
+               }
+               rowinfo_[row].ascent_  = asc;
+               rowinfo_[row].descent_ = desc;
+       }
+       //rowinfo_[0].ascent_       += hlinesep() * rowinfo_[0].lines_;
+       rowinfo_[nrows()].ascent_  = 0;
+       rowinfo_[nrows()].descent_ = 0;
+
+       // compute vertical offsets
+       rowinfo_[0].offset_ = 0;
+       for (row_type row = 1; row <= nrows(); ++row) {
+               rowinfo_[row].offset_  =
+                       rowinfo_[row - 1].offset_  +
+                       rowinfo_[row - 1].descent_ +
+                       //rowinfo_[row - 1].skipPixels() +
+                       1 + //rowsep() +
+                       //rowinfo_[row].lines_ * hlinesep() +
+                       rowinfo_[row].ascent_;
+       }
+
+       // adjust vertical offset
+       int h = 0;
+       switch (v_align_) {
+               case 't':
+                       h = 0;
+                       break;
+               case 'b':
+                       h = rowinfo_[nrows() - 1].offset_;
+                       break;
+               default:
+                       h = rowinfo_[nrows() - 1].offset_ / 2;
+       }
+       for (row_type row = 0; row <= nrows(); ++row)
+               rowinfo_[row].offset_ -= h;
+
+
+       // compute absolute sizes of horizontal structure
+       for (col_type col = 0; col < ncols(); ++col) {
+               int wid = 0;
+               for (row_type row = 0; row < nrows(); ++row)
+                       wid = max(wid, cell(index(row, col)).width());
+               colinfo_[col].width_ = wid;
+       }
+       colinfo_[ncols()].width_  = 0;
+
+       // compute horizontal offsets
+       colinfo_[0].offset_ = border();
+       for (col_type col = 1; col <= ncols(); ++col) {
+               colinfo_[col].offset_ =
+                       colinfo_[col - 1].offset_ +
+                       colinfo_[col - 1].width_ +
+                       colinfo_[col - 1].skip_ +
+                       1 ; //colsep() +
+                       //colinfo_[col].lines_ * vlinesep();
+       }
+
+
+       dim.wid  =  colinfo_[ncols() - 1].offset_
+                      + colinfo_[ncols() - 1].width_
+                //+ vlinesep() * colinfo_[ncols()].lines_
+                      + 2;
+
+       dim.asc  = -rowinfo_[0].offset_
+                      + rowinfo_[0].ascent_
+                //+ hlinesep() * rowinfo_[0].lines_
+                      + 1;
+
+       dim.des  =  rowinfo_[nrows() - 1].offset_
+                      + rowinfo_[nrows() - 1].descent_
+                //+ hlinesep() * rowinfo_[nrows()].lines_
+                      + 1;
+}
+
+
+void InsetMathGrid::drawT(TextPainter & pain, int x, int y) const
+{
+       for (idx_type idx = 0; idx < nargs(); ++idx)
+               cell(idx).drawT(pain, x + cellXOffset(idx), y + cellYOffset(idx));
+}
+
+
+docstring InsetMathGrid::eolString(row_type row, bool emptyline, bool fragile) const
+{
+       docstring eol;
+
+       if (!rowinfo_[row].crskip_.zero())
+               eol += '[' + from_utf8(rowinfo_[row].crskip_.asLatexString()) + ']';
+       else if(!rowinfo_[row].allow_pagebreak_)
+               eol += '*';
+
+       // make sure an upcoming '[' does not break anything
+       if (row + 1 < nrows()) {
+               MathArray const & c = cell(index(row + 1, 0));
+               if (c.size() && c.front()->getChar() == '[')
+                       //eol += "[0pt]";
+                       eol += "{}";
+       }
+
+       // only add \\ if necessary
+       if (eol.empty() && row + 1 == nrows() && (nrows() == 1 || !emptyline))
+               return docstring();
+
+       return (fragile ? "\\protect\\\\" : "\\\\") + eol;
+}
+
+
+docstring InsetMathGrid::eocString(col_type col, col_type lastcol) const
+{
+       if (col + 1 == lastcol)
+               return docstring();
+       return from_ascii(" & ");
+}
+
+
+void InsetMathGrid::addRow(row_type row)
+{
+       rowinfo_.insert(rowinfo_.begin() + row + 1, RowInfo());
+       cells_.insert
+               (cells_.begin() + (row + 1) * ncols(), ncols(), MathArray());
+       cellinfo_.insert
+               (cellinfo_.begin() + (row + 1) * ncols(), ncols(), CellInfo());
+}
+
+
+void InsetMathGrid::appendRow()
+{
+       rowinfo_.push_back(RowInfo());
+       //cells_.insert(cells_.end(), ncols(), MathArray());
+       for (col_type col = 0; col < ncols(); ++col) {
+               cells_.push_back(cells_type::value_type());
+               cellinfo_.push_back(CellInfo());
+       }
+}
+
+
+void InsetMathGrid::delRow(row_type row)
+{
+       if (nrows() == 1)
+               return;
+
+       cells_type::iterator it = cells_.begin() + row * ncols();
+       cells_.erase(it, it + ncols());
+
+       vector<CellInfo>::iterator jt = cellinfo_.begin() + row * ncols();
+       cellinfo_.erase(jt, jt + ncols());
+
+       rowinfo_.erase(rowinfo_.begin() + row);
+}
+
+
+void InsetMathGrid::copyRow(row_type row)
+{
+       addRow(row);
+       for (col_type col = 0; col < ncols(); ++col)
+               cells_[(row + 1) * ncols() + col] = cells_[row * ncols() + col];
+}
+
+
+void InsetMathGrid::swapRow(row_type row)
+{
+       if (nrows() == 1)
+               return;
+       if (row + 1 == nrows())
+               --row;
+       for (col_type col = 0; col < ncols(); ++col)
+               swap(cells_[row * ncols() + col], cells_[(row + 1) * ncols() + col]);
+}
+
+
+void InsetMathGrid::addCol(col_type newcol)
+{
+       const col_type nc = ncols();
+       const row_type nr = nrows();
+       cells_type new_cells((nc + 1) * nr);
+       vector<CellInfo> new_cellinfo((nc + 1) * nr);
+
+       for (row_type row = 0; row < nr; ++row)
+               for (col_type col = 0; col < nc; ++col) {
+                       new_cells[row * (nc + 1) + col + (col > newcol)]
+                               = cells_[row * nc + col];
+                       new_cellinfo[row * (nc + 1) + col + (col > newcol)]
+                               = cellinfo_[row * nc + col];
+               }
+       swap(cells_, new_cells);
+       swap(cellinfo_, new_cellinfo);
+
+       ColInfo inf;
+       inf.skip_  = defaultColSpace(newcol);
+       inf.align_ = defaultColAlign(newcol);
+       colinfo_.insert(colinfo_.begin() + newcol, inf);
+}
+
+
+void InsetMathGrid::delCol(col_type col)
+{
+       if (ncols() == 1)
+               return;
+
+       cells_type tmpcells;
+       vector<CellInfo> tmpcellinfo;
+       for (col_type i = 0; i < nargs(); ++i)
+               if (i % ncols() != col) {
+                       tmpcells.push_back(cells_[i]);
+                       tmpcellinfo.push_back(cellinfo_[i]);
+               }
+       swap(cells_, tmpcells);
+       swap(cellinfo_, tmpcellinfo);
+
+       colinfo_.erase(colinfo_.begin() + col);
+}
+
+
+void InsetMathGrid::copyCol(col_type col)
+{
+       addCol(col);
+       for (row_type row = 0; row < nrows(); ++row)
+               cells_[row * ncols() + col + 1] = cells_[row * ncols() + col];
+}
+
+
+void InsetMathGrid::swapCol(col_type col)
+{
+       if (ncols() == 1)
+               return;
+       if (col + 1 == ncols())
+               --col;
+       for (row_type row = 0; row < nrows(); ++row)
+               swap(cells_[row * ncols() + col], cells_[row * ncols() + col + 1]);
+}
+
+
+int InsetMathGrid::cellXOffset(idx_type idx) const
+{
+       col_type c = col(idx);
+       int x = colinfo_[c].offset_;
+       char align = colinfo_[c].align_;
+       if (align == 'r' || align == 'R')
+               x += colinfo_[c].width_ - cell(idx).width();
+       if (align == 'c' || align == 'C')
+               x += (colinfo_[c].width_ - cell(idx).width()) / 2;
+       return x;
+}
+
+
+int InsetMathGrid::cellYOffset(idx_type idx) const
+{
+       return rowinfo_[row(idx)].offset_;
+}
+
+
+bool InsetMathGrid::idxUpDown(LCursor & cur, bool up) const
+{
+       if (up) {
+               if (cur.row() == 0)
+                       return false;
+               cur.idx() -= ncols();
+       } else {
+               if (cur.row() + 1 >= nrows())
+                       return false;
+               cur.idx() += ncols();
+       }
+       cur.pos() = cur.cell().x2pos(cur.x_target() - cur.cell().xo(cur.bv()));
+       return true;
+}
+
+
+bool InsetMathGrid::idxLeft(LCursor & cur) const
+{
+       // leave matrix if on the left hand edge
+       if (cur.col() == 0)
+               return false;
+       --cur.idx();
+       cur.pos() = cur.lastpos();
+       return true;
+}
+
+
+bool InsetMathGrid::idxRight(LCursor & cur) const
+{
+       // leave matrix if on the right hand edge
+       if (cur.col() + 1 == ncols())
+               return false;
+       ++cur.idx();
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathGrid::idxFirst(LCursor & cur) const
+{
+       switch (v_align_) {
+               case 't':
+                       cur.idx() = 0;
+                       break;
+               case 'b':
+                       cur.idx() = (nrows() - 1) * ncols();
+                       break;
+               default:
+                       cur.idx() = ((nrows() - 1) / 2) * ncols();
+       }
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathGrid::idxLast(LCursor & cur) const
+{
+       switch (v_align_) {
+               case 't':
+                       cur.idx() = ncols() - 1;
+                       break;
+               case 'b':
+                       cur.idx() = nargs() - 1;
+                       break;
+               default:
+                       cur.idx() = ((nrows() - 1) / 2 + 1) * ncols() - 1;
+       }
+       cur.pos() = cur.lastpos();
+       return true;
+}
+
+
+bool InsetMathGrid::idxDelete(idx_type & idx)
+{
+       // nothing to do if we have just one row
+       if (nrows() == 1)
+               return false;
+
+       // nothing to do if we are in the middle of the last row of the inset
+       if (idx + ncols() > nargs())
+               return false;
+
+       // try to delete entire sequence of ncols() empty cells if possible
+       for (idx_type i = idx; i < idx + ncols(); ++i)
+               if (cell(i).size())
+                       return false;
+
+       // move cells if necessary
+       for (idx_type i = index(row(idx), 0); i < idx; ++i)
+               swap(cell(i), cell(i + ncols()));
+
+       delRow(row(idx));
+
+       if (idx >= nargs())
+               idx = nargs() - 1;
+
+       // undo effect of Ctrl-Tab (i.e. pull next cell)
+       //if (idx + 1 != nargs())
+       //      cell(idx).swap(cell(idx + 1));
+
+       // we handled the event..
+       return true;
+}
+
+
+// reimplement old behaviour when pressing Delete in the last position
+// of a cell
+void InsetMathGrid::idxGlue(idx_type idx)
+{
+       col_type c = col(idx);
+       if (c + 1 == ncols()) {
+               if (row(idx) + 1 != nrows()) {
+                       for (col_type cc = 0; cc < ncols(); ++cc)
+                               cell(idx).append(cell(idx + cc + 1));
+                       delRow(row(idx) + 1);
+               }
+       } else {
+               cell(idx).append(cell(idx + 1));
+               for (col_type cc = c + 2; cc < ncols(); ++cc)
+                       cell(idx - c + cc - 1) = cell(idx - c + cc);
+               cell(idx - c + ncols() - 1).clear();
+       }
+}
+
+
+InsetMathGrid::RowInfo const & InsetMathGrid::rowinfo(row_type row) const
+{
+       return rowinfo_[row];
+}
+
+
+InsetMathGrid::RowInfo & InsetMathGrid::rowinfo(row_type row)
+{
+       return rowinfo_[row];
+}
+
+
+bool InsetMathGrid::idxBetween(idx_type idx, idx_type from, idx_type to) const
+{
+       row_type const ri = row(idx);
+       row_type const r1 = min(row(from), row(to));
+       row_type const r2 = max(row(from), row(to));
+       col_type const ci = col(idx);
+       col_type const c1 = min(col(from), col(to));
+       col_type const c2 = max(col(from), col(to));
+       return r1 <= ri && ri <= r2 && c1 <= ci && ci <= c2;
+}
+
+
+
+void InsetMathGrid::normalize(NormalStream & os) const
+{
+       os << "[grid ";
+       for (row_type row = 0; row < nrows(); ++row) {
+               os << "[row ";
+               for (col_type col = 0; col < ncols(); ++col)
+                       os << "[cell " << cell(index(row, col)) << ']';
+               os << ']';
+       }
+       os << ']';
+}
+
+
+void InsetMathGrid::mathmlize(MathStream & os) const
+{
+       os << MTag("mtable");
+       for (row_type row = 0; row < nrows(); ++row) {
+               os << MTag("mtr");
+               for (col_type col = 0; col < ncols(); ++col)
+                       os << cell(index(row, col));
+               os << ETag("mtr");
+       }
+       os << ETag("mtable");
+}
+
+
+void InsetMathGrid::write(WriteStream & os) const
+{
+       docstring eol;
+       for (row_type row = 0; row < nrows(); ++row) {
+               os << verboseHLine(rowinfo_[row].lines_);
+               // don't write & and empty cells at end of line
+               col_type lastcol = 0;
+               bool emptyline = true;
+               for (col_type col = 0; col < ncols(); ++col)
+                       if (!cell(index(row, col)).empty()) {
+                               lastcol = col + 1;
+                               emptyline = false;
+                       }
+               for (col_type col = 0; col < lastcol; ++col)
+                       os << cell(index(row, col)) << eocString(col, lastcol);
+               eol = eolString(row, emptyline, os.fragile());
+               os << eol;
+               // append newline only if line wasn't completely empty
+               // and this was not the last line in the grid
+               if (!emptyline && row + 1 < nrows())
+                       os << "\n";
+       }
+       docstring const s = verboseHLine(rowinfo_[nrows()].lines_);
+       if (!s.empty()) {
+               if (eol.empty()) {
+                       if (os.fragile())
+                               os << "\\protect";
+                       os << "\\\\";
+               }
+               os << s;
+       }
+}
+
+
+int InsetMathGrid::colsep() const
+{
+       return 6;
+}
+
+
+int InsetMathGrid::rowsep() const
+{
+       return 6;
+}
+
+
+int InsetMathGrid::hlinesep() const
+{
+       return 3;
+}
+
+
+int InsetMathGrid::vlinesep() const
+{
+       return 3;
+}
+
+
+int InsetMathGrid::border() const
+{
+       return 1;
+}
+
+
+void InsetMathGrid::splitCell(LCursor & cur)
+{
+       if (cur.idx() == cur.lastidx())
+               return;
+       MathArray ar = cur.cell();
+       ar.erase(0, cur.pos());
+       cur.cell().erase(cur.pos(), cur.lastpos());
+       ++cur.idx();
+       cur.pos() = 0;
+       cur.cell().insert(0, ar);
+}
+
+
+void InsetMathGrid::doDispatch(LCursor & cur, FuncRequest & cmd)
+{
+       //lyxerr << "*** InsetMathGrid: request: " << cmd << endl;
+       switch (cmd.action) {
+
+       case LFUN_MOUSE_RELEASE:
+               //if (cmd.button() == mouse_button::button3) {
+               //      GridInsetMailer(*this).showDialog();
+               //      return DispatchResult(true, true);
+               //}
+               InsetMathNest::doDispatch(cur, cmd);
+               break;
+
+       case LFUN_INSET_DIALOG_UPDATE:
+               GridInsetMailer(*this).updateDialog(&cur.bv());
+               break;
+
+       // insert file functions
+       case LFUN_LINE_DELETE:
+               // FIXME: We use recordUndoInset when a change reflects more
+               // than one cell, because recordUndo does not work for
+               // multiple cells. Unfortunately this puts the cursor in front
+               // of the inset after undo. This is (especilally for large
+               // grids) annoying.
+               recordUndoInset(cur);
+               //autocorrect_ = false;
+               //macroModeClose();
+               //if (selection_) {
+               //      selDel();
+               //      break;
+               //}
+               if (nrows() > 1)
+                       delRow(cur.row());
+               if (cur.idx() > cur.lastidx())
+                       cur.idx() = cur.lastidx();
+               if (cur.pos() > cur.lastpos())
+                       cur.pos() = cur.lastpos();
+               break;
+
+       case LFUN_CELL_SPLIT:
+               recordUndo(cur);
+               splitCell(cur);
+               break;
+
+       case LFUN_CELL_BACKWARD:
+               // See below.
+               cur.selection() = false;
+               if (!idxPrev(cur)) {
+                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                       cur.undispatched();
+               }
+               break;
+
+       case LFUN_CELL_FORWARD:
+               // Can't handle selection by additional 'shift' as this is
+               // hard bound to LFUN_CELL_BACKWARD
+               cur.selection() = false;
+               if (!idxNext(cur)) {
+                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cur.undispatched();
+               }
+               break;
+
+       case LFUN_BREAK_LINE: {
+               recordUndoInset(cur);
+               row_type const r = cur.row();
+               addRow(r);
+
+               // split line
+               for (col_type c = col(cur.idx()) + 1; c < ncols(); ++c)
+                       swap(cell(index(r, c)), cell(index(r + 1, c)));
+
+               // split cell
+               splitCell(cur);
+               swap(cell(cur.idx()), cell(cur.idx() + ncols() - 1));
+               if (cur.idx() > 0)
+                       --cur.idx();
+               cur.pos() = cur.lastpos();
+
+               //mathcursor->normalize();
+               //cmd = FuncRequest(LFUN_FINISHED_LEFT);
+               break;
+       }
+
+       case LFUN_TABULAR_FEATURE: {
+               recordUndoInset(cur);
+               //lyxerr << "handling tabular-feature " << to_utf8(cmd.argument()) << endl;
+               istringstream is(to_utf8(cmd.argument()));
+               string s;
+               is >> s;
+               if (s == "valign-top")
+                       valign('t');
+               else if (s == "valign-middle")
+                       valign('c');
+               else if (s == "valign-bottom")
+                       valign('b');
+               else if (s == "align-left")
+                       halign('l', cur.col());
+               else if (s == "align-right")
+                       halign('r', cur.col());
+               else if (s == "align-center")
+                       halign('c', cur.col());
+               else if (s == "append-row")
+                       for (int i = 0, n = extractInt(is); i < n; ++i)
+                               addRow(cur.row());
+               else if (s == "delete-row") {
+                       for (int i = 0, n = extractInt(is); i < n; ++i) {
+                               delRow(cur.row());
+                               if (cur.idx() >= nargs())
+                                       cur.idx() -= ncols();
+                       }
+                       cur.pos() = 0; // trick, see below
+               }
+               else if (s == "copy-row") {
+                       // Here (as later) we save the cursor col/row
+                       // in order to restore it after operation.
+                       row_type const r = cur.row();
+                       col_type const c = cur.col();
+                       for (int i = 0, n = extractInt(is); i < n; ++i)
+                               copyRow(cur.row());
+                       cur.idx() = index(r, c);
+               }
+               else if (s == "swap-row") {
+                       swapRow(cur.row());
+                       // Trick to suppress same-idx-means-different-cell
+                       // assertion crash:
+                       cur.pos() = 0;
+               }
+               else if (s == "add-hline-above")
+                       rowinfo_[cur.row()].lines_++;
+               else if (s == "add-hline-below")
+                       rowinfo_[cur.row()+1].lines_++;
+               else if (s == "delete-hline-above")
+                       rowinfo_[cur.row()].lines_--;
+               else if (s == "delete-hline-below")
+                       rowinfo_[cur.row()+1].lines_--;
+               else if (s == "append-column") {
+                       row_type const r = cur.row();
+                       col_type const c = cur.col();
+                       for (int i = 0, n = extractInt(is); i < n; ++i)
+                               addCol(cur.col());
+                       cur.idx() = index(r, c);
+               }
+               else if (s == "delete-column") {
+                       row_type const r = cur.row();
+                       col_type const c = cur.col();
+                       for (int i = 0, n = extractInt(is); i < n; ++i)
+                               delCol(col(cur.idx()));
+                       cur.idx() = index(r, min(c, cur.ncols() - 1));
+                       cur.pos() = 0; // trick, see above
+               }
+               else if (s == "copy-column") {
+                       row_type const r = cur.row();
+                       col_type const c = cur.col();
+                       copyCol(cur.col());
+                       cur.idx() = index(r, c);
+               }
+               else if (s == "swap-column") {
+                       swapCol(cur.col());
+                       cur.pos() = 0; // trick, see above
+               }
+               else if (s == "add-vline-left")
+                       colinfo_[cur.col()].lines_++;
+               else if (s == "add-vline-right")
+                       colinfo_[cur.col()+1].lines_++;
+               else if (s == "delete-vline-left")
+                       colinfo_[cur.col()].lines_--;
+               else if (s == "delete-vline-right")
+                       colinfo_[cur.col()+1].lines_--;
+               else {
+                       cur.undispatched();
+                       break;
+               }
+               lyxerr << "returning FINISHED_LEFT" << endl;
+               break;
+       }
+
+       case LFUN_PASTE: {
+               cur.message(_("Paste"));
+               cap::replaceSelection(cur);
+               docstring topaste;
+               if (cmd.argument().empty() && !theClipboard().isInternal())
+                       topaste = theClipboard().getAsText();
+               else {
+                       idocstringstream is(cmd.argument());
+                       int n = 0;
+                       is >> n;
+                       topaste = cap::getSelection(cur.buffer(), n);
+               }
+               InsetMathGrid grid(1, 1);
+               if (!topaste.empty())
+                       mathed_parse_normal(grid, topaste);
+
+               if (grid.nargs() == 1) {
+                       // single cell/part of cell
+                       recordUndo(cur);
+                       cur.cell().insert(cur.pos(), grid.cell(0));
+                       cur.pos() += grid.cell(0).size();
+               } else {
+                       // multiple cells
+                       recordUndoInset(cur);
+                       col_type const numcols =
+                               min(grid.ncols(), ncols() - col(cur.idx()));
+                       row_type const numrows =
+                               min(grid.nrows(), nrows() - cur.row());
+                       for (row_type r = 0; r < numrows; ++r) {
+                               for (col_type c = 0; c < numcols; ++c) {
+                                       idx_type i = index(r + cur.row(), c + col(cur.idx()));
+                                       cell(i).insert(0, grid.cell(grid.index(r, c)));
+                               }
+                               // append the left over horizontal cells to the last column
+                               idx_type i = index(r + cur.row(), ncols() - 1);
+                               for (InsetMath::col_type c = numcols; c < grid.ncols(); ++c)
+                                       cell(i).append(grid.cell(grid.index(r, c)));
+                       }
+                       // append the left over vertical cells to the last _cell_
+                       idx_type i = nargs() - 1;
+                       for (row_type r = numrows; r < grid.nrows(); ++r)
+                               for (col_type c = 0; c < grid.ncols(); ++c)
+                                       cell(i).append(grid.cell(grid.index(r, c)));
+               }
+               cur.clearSelection(); // bug 393
+               cur.bv().switchKeyMap();
+               finishUndo();
+               break;
+       }
+
+       case LFUN_LINE_BEGIN_SELECT:
+       case LFUN_LINE_BEGIN:
+       case LFUN_WORD_BACKWARD_SELECT:
+       case LFUN_WORD_BACKWARD:
+               cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT ||
+                               cmd.action == LFUN_LINE_BEGIN_SELECT);
+               cur.macroModeClose();
+               if (cur.pos() != 0) {
+                       cur.pos() = 0;
+               } else if (cur.idx() % cur.ncols() != 0) {
+                       cur.idx() -= cur.idx() % cur.ncols();
+                       cur.pos() = 0;
+               } else if (cur.idx() != 0) {
+                       cur.idx() = 0;
+                       cur.pos() = 0;
+               } else {
+                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                       cur.undispatched();
+               }
+               break;
+
+       case LFUN_WORD_FORWARD_SELECT:
+       case LFUN_WORD_FORWARD:
+       case LFUN_LINE_END_SELECT:
+       case LFUN_LINE_END:
+               cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT ||
+                               cmd.action == LFUN_LINE_END_SELECT);
+               cur.macroModeClose();
+               cur.clearTargetX();
+               if (cur.pos() != cur.lastpos()) {
+                       cur.pos() = cur.lastpos();
+               } else if ((cur.idx() + 1) % cur.ncols() != 0) {
+                       cur.idx() += cur.ncols() - 1 - cur.idx() % cur.ncols();
+                       cur.pos() = cur.lastpos();
+               } else if (cur.idx() != cur.lastidx()) {
+                       cur.idx() = cur.lastidx();
+                       cur.pos() = cur.lastpos();
+               } else {
+                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cur.undispatched();
+               }
+               break;
+
+       default:
+               InsetMathNest::doDispatch(cur, cmd);
+       }
+}
+
+
+bool InsetMathGrid::getStatus(LCursor & cur, FuncRequest const & cmd,
+               FuncStatus & status) const
+{
+       switch (cmd.action) {
+       case LFUN_TABULAR_FEATURE: {
+               string const s = to_utf8(cmd.argument());
+               if (nrows() <= 1 && (s == "delete-row" || s == "swap-row")) {
+                       status.enabled(false);
+                       status.message(from_utf8(N_("Only one row")));
+                       return true;
+               }
+               if (ncols() <= 1 &&
+                   (s == "delete-column" || s == "swap-column")) {
+                       status.enabled(false);
+                       status.message(from_utf8(N_("Only one column")));
+                       return true;
+               }
+               if ((rowinfo_[cur.row()].lines_ == 0 &&
+                    s == "delete-hline-above") ||
+                   (rowinfo_[cur.row() + 1].lines_ == 0 &&
+                    s == "delete-hline-below")) {
+                       status.enabled(false);
+                       status.message(from_utf8(N_("No hline to delete")));
+                       return true;
+               }
+
+               if ((colinfo_[cur.col()].lines_ == 0 &&
+                    s == "delete-vline-left") ||
+                   (colinfo_[cur.col() + 1].lines_ == 0 &&
+                    s == "delete-vline-right")) {
+                       status.enabled(false);
+                       status.message(from_utf8(N_("No vline to delete")));
+                       return true;
+               }
+               if (s == "valign-top" || s == "valign-middle" ||
+                   s == "valign-bottom" || s == "align-left" ||
+                   s == "align-right" || s == "align-center" ||
+                   s == "append-row" || s == "delete-row" ||
+                   s == "copy-row" || s == "swap-row" ||
+                   s == "add-hline-above" || s == "add-hline-below" ||
+                   s == "delete-hline-above" || s == "delete-hline-below" ||
+                   s == "append-column" || s == "delete-column" ||
+                   s == "copy-column" || s == "swap-column" ||
+                   s == "add-vline-left" || s == "add-vline-right" ||
+                   s == "delete-vline-left" || s == "delete-vline-right")
+                       status.enabled(true);
+               else {
+                       status.enabled(false);
+                       status.message(bformat(
+                               from_utf8(N_("Unknown tabular feature '%1$s'")), lyx::from_ascii(s)));
+               }
+
+               status.setOnOff(s == "align-left"    && halign(cur.col()) == 'l'
+                          || s == "align-right"   && halign(cur.col()) == 'r'
+                          || s == "align-center"  && halign(cur.col()) == 'c'
+                          || s == "valign-top"    && valign() == 't'
+                          || s == "valign-bottom" && valign() == 'b'
+                          || s == "valign-middle" && valign() == 'm');
+
+#if 0
+               // FIXME: What did this code do?
+               // Please check whether it is still needed!
+               // should be more precise
+               if (v_align_ == '\0') {
+                       status.enable(true);
+                       break;
+               }
+               if (cmd.argument().empty()) {
+                       status.enable(false);
+                       break;
+               }
+               if (!support::contains("tcb", cmd.argument()[0])) {
+                       status.enable(false);
+                       break;
+               }
+               status.setOnOff(cmd.argument()[0] == v_align_);
+               status.enabled(true);
+#endif
+               return true;
+       }
+
+       case LFUN_CELL_SPLIT:
+               status.enabled(true);
+               return true;
+
+       case LFUN_CELL_BACKWARD:
+       case LFUN_CELL_FORWARD:
+               status.enabled(true);
+               return true;
+
+       default:
+               return InsetMathNest::getStatus(cur, cmd, status);
+       }
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathHull.C b/src/mathed/InsetMathHull.C
deleted file mode 100644 (file)
index cd3a590..0000000
+++ /dev/null
@@ -1,1525 +0,0 @@
-/**
- * \file InsetMathHull.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathArray.h"
-#include "InsetMathChar.h"
-#include "InsetMathColor.h"
-#include "MathData.h"
-#include "InsetMathDelim.h"
-#include "MathExtern.h"
-#include "MathFactory.h"
-#include "InsetMathHull.h"
-#include "MathStream.h"
-#include "MathParser.h"
-#include "InsetMathSpace.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "InsetMathRef.h"
-
-#include "bufferview_funcs.h"
-#include "lyxtext.h"
-
-#include "buffer.h"
-#include "bufferparams.h"
-#include "BufferView.h"
-#include "CutAndPaste.h"
-#include "FuncStatus.h"
-#include "LColor.h"
-#include "LaTeXFeatures.h"
-#include "cursor.h"
-#include "debug.h"
-#include "dispatchresult.h"
-#include "funcrequest.h"
-#include "gettext.h"
-#include "lyxrc.h"
-#include "outputparams.h"
-#include "sgml.h"
-#include "TextPainter.h"
-#include "undo.h"
-
-#include "insets/RenderPreview.h"
-#include "insets/InsetLabel.h"
-
-#include "graphics/PreviewImage.h"
-#include "graphics/PreviewLoader.h"
-
-#include "support/lyxlib.h"
-#include "support/lstrings.h"
-
-#include <boost/bind.hpp>
-
-#include <sstream>
-
-
-namespace lyx {
-
-using cap::grabAndEraseSelection;
-using support::bformat;
-using support::subst;
-
-using std::endl;
-using std::max;
-using std::ostream;
-using std::auto_ptr;
-using std::istringstream;
-using std::ostringstream;
-using std::pair;
-using std::swap;
-using std::vector;
-
-
-namespace {
-
-       int getCols(HullType type)
-       {
-               switch (type) {
-                       case hullEqnArray:
-                               return 3;
-                       case hullAlign:
-                       case hullFlAlign:
-                       case hullAlignAt:
-                       case hullXAlignAt:
-                       case hullXXAlignAt:
-                               return 2;
-                       default:
-                               return 1;
-               }
-       }
-
-
-       // returns position of first relation operator in the array
-       // used for "intelligent splitting"
-       size_t firstRelOp(MathArray const & ar)
-       {
-               for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
-                       if ((*it)->isRelOp())
-                               return it - ar.begin();
-               return ar.size();
-       }
-
-
-       char const * star(bool numbered)
-       {
-               return numbered ? "" : "*";
-       }
-
-
-} // end anon namespace
-
-
-HullType hullType(docstring const & s)
-{
-       if (s == "none")      return hullNone;
-       if (s == "simple")    return hullSimple;
-       if (s == "equation")  return hullEquation;
-       if (s == "eqnarray")  return hullEqnArray;
-       if (s == "align")     return hullAlign;
-       if (s == "alignat")   return hullAlignAt;
-       if (s == "xalignat")  return hullXAlignAt;
-       if (s == "xxalignat") return hullXXAlignAt;
-       if (s == "multline")  return hullMultline;
-       if (s == "gather")    return hullGather;
-       if (s == "flalign")   return hullFlAlign;
-       lyxerr << "unknown hull type '" << to_utf8(s) << "'" << endl;
-       return HullType(-1);
-}
-
-
-docstring hullName(HullType type)
-{
-       switch (type) {
-               case hullNone:       return from_ascii("none");
-               case hullSimple:     return from_ascii("simple");
-               case hullEquation:   return from_ascii("equation");
-               case hullEqnArray:   return from_ascii("eqnarray");
-               case hullAlign:      return from_ascii("align");
-               case hullAlignAt:    return from_ascii("alignat");
-               case hullXAlignAt:   return from_ascii("xalignat");
-               case hullXXAlignAt:  return from_ascii("xxalignat");
-               case hullMultline:   return from_ascii("multline");
-               case hullGather:     return from_ascii("gather");
-               case hullFlAlign:    return from_ascii("flalign");
-               default:
-                       lyxerr << "unknown hull type '" << type << "'" << endl;
-                       return from_ascii("none");
-       }
-}
-
-
-InsetMathHull::InsetMathHull()
-       : InsetMathGrid(1, 1), type_(hullNone), nonum_(1), label_(1),
-         preview_(new RenderPreview(this))
-{
-       //lyxerr << "sizeof InsetMath: " << sizeof(InsetMath) << endl;
-       //lyxerr << "sizeof MetricsInfo: " << sizeof(MetricsInfo) << endl;
-       //lyxerr << "sizeof InsetMathChar: " << sizeof(InsetMathChar) << endl;
-       //lyxerr << "sizeof LyXFont: " << sizeof(LyXFont) << endl;
-       initMath();
-       setDefaults();
-}
-
-
-InsetMathHull::InsetMathHull(HullType type)
-       : InsetMathGrid(getCols(type), 1), type_(type), nonum_(1), label_(1),
-         preview_(new RenderPreview(this))
-{
-       initMath();
-       setDefaults();
-}
-
-
-InsetMathHull::InsetMathHull(InsetMathHull const & other)
-       : InsetMathGrid(other),
-         type_(other.type_), nonum_(other.nonum_), label_(other.label_),
-         preview_(new RenderPreview(this))
-{}
-
-
-InsetMathHull::~InsetMathHull()
-{}
-
-
-auto_ptr<InsetBase> InsetMathHull::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathHull(*this));
-}
-
-
-InsetMathHull & InsetMathHull::operator=(InsetMathHull const & other)
-{
-       if (this == &other)
-               return *this;
-       *static_cast<InsetMathGrid*>(this) = InsetMathGrid(other);
-       type_  = other.type_;
-       nonum_ = other.nonum_;
-       label_ = other.label_;
-       preview_.reset(new RenderPreview(*other.preview_, this));
-
-       return *this;
-}
-
-
-InsetBase * InsetMathHull::editXY(LCursor & cur, int x, int y)
-{
-       if (use_preview_) {
-               edit(cur, true);
-               return this;
-       }
-       return InsetMathNest::editXY(cur, x, y);
-}
-
-
-InsetMath::mode_type InsetMathHull::currentMode() const
-{
-       if (type_ == hullNone)
-               return UNDECIDED_MODE;
-       // definitely math mode ...
-       return MATH_MODE;
-}
-
-
-bool InsetMathHull::idxFirst(LCursor & cur) const
-{
-       cur.idx() = 0;
-       cur.pos() = 0;
-       return true;
-}
-
-
-bool InsetMathHull::idxLast(LCursor & cur) const
-{
-       cur.idx() = nargs() - 1;
-       cur.pos() = cur.lastpos();
-       return true;
-}
-
-
-char InsetMathHull::defaultColAlign(col_type col)
-{
-       if (type_ == hullEqnArray)
-               return "rcl"[col];
-       if (type_ >= hullAlign)
-               return "rl"[col & 1];
-       return 'c';
-}
-
-
-int InsetMathHull::defaultColSpace(col_type col)
-{
-       if (type_ == hullAlign || type_ == hullAlignAt)
-               return 0;
-       if (type_ == hullXAlignAt)
-               return (col & 1) ? 20 : 0;
-       if (type_ == hullXXAlignAt || type_ == hullFlAlign)
-               return (col & 1) ? 40 : 0;
-       return 0;
-}
-
-
-docstring InsetMathHull::standardFont() const
-{
-       return from_ascii(type_ == hullNone ? "lyxnochange" : "mathnormal");
-}
-
-
-bool InsetMathHull::previewState(BufferView * bv) const
-{
-       if (!editing(bv) && RenderPreview::status() == LyXRC::PREVIEW_ON) {
-               graphics::PreviewImage const * pimage =
-                       preview_->getPreviewImage(*bv->buffer());
-               return pimage && pimage->image();
-       }
-       return false;
-}
-
-
-bool InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       if (previewState(mi.base.bv)) {
-               preview_->metrics(mi, dim);
-               // insert a one pixel gap in front of the formula
-               dim.wid += 1;
-               if (display())
-                       dim.des += displayMargin();
-               if (dim_ == dim)
-                       return false;
-               dim_ = dim;
-               return true;
-       }
-
-       FontSetChanger dummy1(mi.base, standardFont());
-       StyleChanger dummy2(mi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT);
-
-       // let the cells adjust themselves
-       InsetMathGrid::metrics(mi, dim);
-
-       if (display()) {
-               dim.asc += displayMargin();
-               dim.des += displayMargin();
-       }
-
-       if (numberedType()) {
-               FontSetChanger dummy(mi.base, from_ascii("mathbf"));
-               int l = 0;
-               for (row_type row = 0; row < nrows(); ++row)
-                       l = max(l, mathed_string_width(mi.base.font, nicelabel(row)));
-
-               if (l)
-                       dim.wid += 30 + l;
-       }
-
-       // make it at least as high as the current font
-       int asc = 0;
-       int des = 0;
-       math_font_max_dim(mi.base.font, asc, des);
-       dim.asc = max(dim.asc, asc);
-       dim.des = max(dim.des, des);
-
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathHull::draw(PainterInfo & pi, int x, int y) const
-{
-       use_preview_ = previewState(pi.base.bv);
-
-       if (use_preview_) {
-               // one pixel gap in front
-               preview_->draw(pi, x + 1, y);
-               setPosCache(pi, x, y);
-               return;
-       }
-
-       FontSetChanger dummy1(pi.base, standardFont());
-       StyleChanger dummy2(pi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT);
-       InsetMathGrid::draw(pi, x + 1, y);
-
-       if (numberedType()) {
-               int const xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20;
-               for (row_type row = 0; row < nrows(); ++row) {
-                       int const yy = y + rowinfo_[row].offset_;
-                       FontSetChanger dummy(pi.base, from_ascii("mathrm"));
-                       docstring const nl = nicelabel(row);
-                       pi.draw(xx, yy, nl);
-               }
-       }
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathHull::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       if (display()) {
-               InsetMathGrid::metricsT(mi, dim);
-       } else {
-               odocstringstream os;
-               WriteStream wi(os, false, true);
-               write(wi);
-               dim.wid = os.str().size();
-               dim.asc = 1;
-               dim.des = 0;
-       }
-}
-
-
-void InsetMathHull::drawT(TextPainter & pain, int x, int y) const
-{
-       if (display()) {
-               InsetMathGrid::drawT(pain, x, y);
-       } else {
-               odocstringstream os;
-               WriteStream wi(os, false, true);
-               write(wi);
-               pain.draw(x, y, os.str().c_str());
-       }
-}
-
-
-namespace {
-
-docstring const latex_string(InsetMathHull const & inset)
-{
-       odocstringstream ls;
-       WriteStream wi(ls, false, false);
-       inset.write(wi);
-       return ls.str();
-}
-
-} // namespace anon
-
-
-void InsetMathHull::addPreview(graphics::PreviewLoader & ploader) const
-{
-       if (RenderPreview::status() == LyXRC::PREVIEW_ON) {
-               docstring const snippet = latex_string(*this);
-               preview_->addPreview(snippet, ploader);
-       }
-}
-
-
-bool InsetMathHull::notifyCursorLeaves(LCursor & cur)
-{
-       if (RenderPreview::status() == LyXRC::PREVIEW_ON) {
-               Buffer const & buffer = cur.buffer();
-               docstring const snippet = latex_string(*this);
-               preview_->addPreview(snippet, buffer);
-               preview_->startLoading(buffer);
-               cur.updateFlags(Update::Force);
-       }
-       return false;
-}
-
-
-docstring InsetMathHull::label(row_type row) const
-{
-       BOOST_ASSERT(row < nrows());
-       return label_[row];
-}
-
-
-void InsetMathHull::label(row_type row, docstring const & label)
-{
-       //lyxerr << "setting label '" << label << "' for row " << row << endl;
-       label_[row] = label;
-}
-
-
-void InsetMathHull::numbered(row_type row, bool num)
-{
-       nonum_[row] = !num;
-       if (nonum_[row])
-               label_[row].clear();
-}
-
-
-bool InsetMathHull::numbered(row_type row) const
-{
-       return !nonum_[row];
-}
-
-
-bool InsetMathHull::ams() const
-{
-       return
-               type_ == hullAlign ||
-               type_ == hullFlAlign ||
-               type_ == hullMultline ||
-               type_ == hullGather ||
-               type_ == hullAlignAt ||
-               type_ == hullXAlignAt ||
-               type_ == hullXXAlignAt;
-}
-
-
-bool InsetMathHull::display() const
-{
-       return type_ != hullSimple && type_ != hullNone;
-}
-
-
-void InsetMathHull::getLabelList(Buffer const &, vector<docstring> & labels) const
-{
-       for (row_type row = 0; row < nrows(); ++row)
-               if (!label_[row].empty() && nonum_[row] != 1)
-                       labels.push_back(label_[row]);
-}
-
-
-bool InsetMathHull::numberedType() const
-{
-       if (type_ == hullNone)
-               return false;
-       if (type_ == hullSimple)
-               return false;
-       if (type_ == hullXXAlignAt)
-               return false;
-       for (row_type row = 0; row < nrows(); ++row)
-               if (!nonum_[row])
-                       return true;
-       return false;
-}
-
-
-void InsetMathHull::validate(LaTeXFeatures & features) const
-{
-       if (ams())
-               features.require("amsmath");
-
-
-       // Validation is necessary only if not using AMS math.
-       // To be safe, we will always run mathedvalidate.
-       //if (features.amsstyle)
-       //  return;
-
-       features.require("boldsymbol");
-       //features.binom      = true;
-
-       InsetMathGrid::validate(features);
-}
-
-
-void InsetMathHull::header_write(WriteStream & os) const
-{
-       bool n = numberedType();
-
-       switch(type_) {
-       case hullNone:
-               break;
-
-       case hullSimple:
-               os << '$';
-               if (cell(0).empty())
-                       os << ' ';
-               break;
-
-       case hullEquation:
-               if (n)
-                       os << "\\begin{equation" << star(n) << "}\n";
-               else
-                       os << "\\[\n";
-               break;
-
-       case hullEqnArray:
-       case hullAlign:
-       case hullFlAlign:
-       case hullGather:
-       case hullMultline:
-               os << "\\begin{" << hullName(type_) << star(n) << "}\n";
-               break;
-
-       case hullAlignAt:
-       case hullXAlignAt:
-               os << "\\begin{" << hullName(type_) << star(n) << '}'
-                 << '{' << static_cast<unsigned int>((ncols() + 1)/2) << "}\n";
-               break;
-
-       case hullXXAlignAt:
-               os << "\\begin{" << hullName(type_) << '}'
-                 << '{' << static_cast<unsigned int>((ncols() + 1)/2) << "}\n";
-               break;
-
-       default:
-               os << "\\begin{unknown" << star(n) << '}';
-               break;
-       }
-}
-
-
-void InsetMathHull::footer_write(WriteStream & os) const
-{
-       bool n = numberedType();
-
-       switch(type_) {
-       case hullNone:
-               os << "\n";
-               break;
-
-       case hullSimple:
-               os << '$';
-               break;
-
-       case hullEquation:
-               if (n)
-                       os << "\\end{equation" << star(n) << "}\n";
-               else
-                       os << "\\]\n";
-               break;
-
-       case hullEqnArray:
-       case hullAlign:
-       case hullFlAlign:
-       case hullAlignAt:
-       case hullXAlignAt:
-       case hullGather:
-       case hullMultline:
-               os << "\\end{" << hullName(type_) << star(n) << "}\n";
-               break;
-
-       case hullXXAlignAt:
-               os << "\\end{" << hullName(type_) << "}\n";
-               break;
-
-       default:
-               os << "\\end{unknown" << star(n) << '}';
-               break;
-       }
-}
-
-
-bool InsetMathHull::rowChangeOK() const
-{
-       return
-               type_ == hullEqnArray || type_ == hullAlign ||
-               type_ == hullFlAlign || type_ == hullAlignAt ||
-               type_ == hullXAlignAt || type_ == hullXXAlignAt ||
-               type_ == hullGather || type_ == hullMultline;
-}
-
-
-bool InsetMathHull::colChangeOK() const
-{
-       return
-               type_ == hullAlign || type_ == hullFlAlign ||type_ == hullAlignAt ||
-               type_ == hullXAlignAt || type_ == hullXXAlignAt;
-}
-
-
-void InsetMathHull::addRow(row_type row)
-{
-       if (!rowChangeOK())
-               return;
-       nonum_.insert(nonum_.begin() + row + 1, !numberedType());
-       label_.insert(label_.begin() + row + 1, docstring());
-       InsetMathGrid::addRow(row);
-}
-
-
-void InsetMathHull::swapRow(row_type row)
-{
-       if (nrows() <= 1)
-               return;
-       if (row + 1 == nrows())
-               --row;
-       swap(nonum_[row], nonum_[row + 1]);
-       swap(label_[row], label_[row + 1]);
-       InsetMathGrid::swapRow(row);
-}
-
-
-void InsetMathHull::delRow(row_type row)
-{
-       if (nrows() <= 1 || !rowChangeOK())
-               return;
-       InsetMathGrid::delRow(row);
-       // The last dummy row has no number info nor a label.
-       // Test nrows() + 1 because we have already erased the row.
-       if (row == nrows() + 1)
-               row--;
-       nonum_.erase(nonum_.begin() + row);
-       label_.erase(label_.begin() + row);
-}
-
-
-void InsetMathHull::addCol(col_type col)
-{
-       if (!colChangeOK())
-               return;
-       InsetMathGrid::addCol(col);
-}
-
-
-void InsetMathHull::delCol(col_type col)
-{
-       if (ncols() <= 1 || !colChangeOK())
-               return;
-       InsetMathGrid::delCol(col);
-}
-
-
-docstring InsetMathHull::nicelabel(row_type row) const
-{
-       if (nonum_[row])
-               return docstring();
-       if (label_[row].empty())
-               return from_ascii("(#)");
-       return '(' + label_[row] + ')';
-}
-
-
-void InsetMathHull::glueall()
-{
-       MathArray ar;
-       for (idx_type i = 0; i < nargs(); ++i)
-               ar.append(cell(i));
-       *this = InsetMathHull(hullSimple);
-       cell(0) = ar;
-       setDefaults();
-}
-
-
-void InsetMathHull::splitTo2Cols()
-{
-       BOOST_ASSERT(ncols() == 1);
-       InsetMathGrid::addCol(1);
-       for (row_type row = 0; row < nrows(); ++row) {
-               idx_type const i = 2 * row;
-               pos_type pos = firstRelOp(cell(i));
-               cell(i + 1) = MathArray(cell(i).begin() + pos, cell(i).end());
-               cell(i).erase(pos, cell(i).size());
-       }
-}
-
-
-void InsetMathHull::splitTo3Cols()
-{
-       BOOST_ASSERT(ncols() < 3);
-       if (ncols() < 2)
-               splitTo2Cols();
-       InsetMathGrid::addCol(1);
-       for (row_type row = 0; row < nrows(); ++row) {
-               idx_type const i = 3 * row + 1;
-               if (cell(i).size()) {
-                       cell(i + 1) = MathArray(cell(i).begin() + 1, cell(i).end());
-                       cell(i).erase(1, cell(i).size());
-               }
-       }
-}
-
-
-void InsetMathHull::changeCols(col_type cols)
-{
-       if (ncols() == cols)
-               return;
-       else if (ncols() < cols) {
-               // split columns
-               if (cols < 3)
-                       splitTo2Cols();
-               else {
-                       splitTo3Cols();
-                       while (ncols() < cols)
-                               InsetMathGrid::addCol(ncols() - 1);
-               }
-               return;
-       }
-
-       // combine columns
-       for (row_type row = 0; row < nrows(); ++row) {
-               idx_type const i = row * ncols();
-               for (col_type col = cols; col < ncols(); ++col) {
-                       cell(i + cols - 1).append(cell(i + col));
-               }
-       }
-       // delete columns
-       while (ncols() > cols) {
-               InsetMathGrid::delCol(ncols() - 1);
-       }
-}
-
-
-HullType InsetMathHull::getType() const
-{
-       return type_;
-}
-
-
-void InsetMathHull::setType(HullType type)
-{
-       type_ = type;
-       setDefaults();
-}
-
-
-void InsetMathHull::mutate(HullType newtype)
-{
-       //lyxerr << "mutating from '" << type_ << "' to '" << newtype << "'" << endl;
-
-       // we try to move along the chain
-       // none <-> simple <-> equation <-> eqnarray -> *align* -> multline, gather -+
-       //                                     ^                                     |
-       //                                     +-------------------------------------+
-       // we use eqnarray as intermediate type for mutations that are not
-       // directly supported because it handles labels and numbering for
-       // "down mutation".
-
-       if (newtype == type_) {
-               // done
-       }
-
-       else if (newtype < hullNone) {
-               // unknown type
-               dump();
-       }
-
-       else if (type_ == hullNone) {
-               setType(hullSimple);
-               numbered(0, false);
-               mutate(newtype);
-       }
-
-       else if (type_ == hullSimple) {
-               if (newtype == hullNone) {
-                       setType(hullNone);
-                       numbered(0, false);
-               } else {
-                       setType(hullEquation);
-                       numbered(0, false);
-                       mutate(newtype);
-               }
-       }
-
-       else if (type_ == hullEquation) {
-               if (newtype < type_) {
-                       setType(hullSimple);
-                       numbered(0, false);
-                       mutate(newtype);
-               } else if (newtype == hullEqnArray) {
-                       // split it "nicely" on the first relop
-                       splitTo3Cols();
-                       setType(hullEqnArray);
-               } else if (newtype == hullMultline || newtype == hullGather) {
-                       setType(newtype);
-               } else {
-                       // split it "nicely"
-                       splitTo2Cols();
-                       setType(hullAlign);
-                       mutate(newtype);
-               }
-       }
-
-       else if (type_ == hullEqnArray) {
-               if (newtype < type_) {
-                       // set correct (no)numbering
-                       bool allnonum = true;
-                       for (row_type row = 0; row < nrows(); ++row)
-                               if (!nonum_[row])
-                                       allnonum = false;
-
-                       // set first non-empty label
-                       docstring label;
-                       for (row_type row = 0; row < nrows(); ++row) {
-                               if (!label_[row].empty()) {
-                                       label = label_[row];
-                                       break;
-                               }
-                       }
-
-                       glueall();
-                       nonum_[0] = allnonum;
-                       label_[0] = label;
-                       mutate(newtype);
-               } else { // align & Co.
-                       changeCols(2);
-                       setType(hullAlign);
-                       mutate(newtype);
-               }
-       }
-
-       else if (type_ ==  hullAlign || type_ == hullAlignAt ||
-                type_ == hullXAlignAt || type_ == hullFlAlign) {
-               if (newtype < hullAlign) {
-                       changeCols(3);
-                       setType(hullEqnArray);
-                       mutate(newtype);
-               } else if (newtype == hullGather || newtype == hullMultline) {
-                       changeCols(1);
-                       setType(newtype);
-               } else if (newtype ==   hullXXAlignAt) {
-                       for (row_type row = 0; row < nrows(); ++row)
-                               numbered(row, false);
-                       setType(newtype);
-               } else {
-                       setType(newtype);
-               }
-       }
-
-       else if (type_ == hullXXAlignAt) {
-               for (row_type row = 0; row < nrows(); ++row)
-                       numbered(row, false);
-               if (newtype < hullAlign) {
-                       changeCols(3);
-                       setType(hullEqnArray);
-                       mutate(newtype);
-               } else if (newtype == hullGather || newtype == hullMultline) {
-                       changeCols(1);
-                       setType(newtype);
-               } else {
-                       setType(newtype);
-               }
-       }
-
-       else if (type_ == hullMultline || type_ == hullGather) {
-               if (newtype == hullGather || newtype == hullMultline)
-                       setType(newtype);
-               else if (newtype == hullAlign || newtype == hullFlAlign  ||
-                        newtype == hullAlignAt || newtype == hullXAlignAt) {
-                       splitTo2Cols();
-                       setType(newtype);
-               } else if (newtype ==   hullXXAlignAt) {
-                       splitTo2Cols();
-                       for (row_type row = 0; row < nrows(); ++row)
-                               numbered(row, false);
-                       setType(newtype);
-               } else {
-                       splitTo3Cols();
-                       setType(hullEqnArray);
-                       mutate(newtype);
-               }
-       }
-
-       else {
-               lyxerr << "mutation from '" << to_utf8(hullName(type_))
-                      << "' to '" << to_utf8(hullName(newtype))
-                      << "' not implemented" << endl;
-       }
-}
-
-
-docstring InsetMathHull::eolString(row_type row, bool emptyline, bool fragile) const
-{
-       docstring res;
-       if (numberedType()) {
-               if (!label_[row].empty() && !nonum_[row])
-                       res += "\\label{" + label_[row] + '}';
-               if (nonum_[row] && (type_ != hullMultline))
-                       res += "\\nonumber ";
-       }
-       return res + InsetMathGrid::eolString(row, emptyline, fragile);
-}
-
-
-void InsetMathHull::write(WriteStream & os) const
-{
-       header_write(os);
-       InsetMathGrid::write(os);
-       footer_write(os);
-}
-
-
-void InsetMathHull::normalize(NormalStream & os) const
-{
-       os << "[formula " << hullName(type_) << ' ';
-       InsetMathGrid::normalize(os);
-       os << "] ";
-}
-
-
-void InsetMathHull::mathmlize(MathStream & os) const
-{
-       InsetMathGrid::mathmlize(os);
-}
-
-
-void InsetMathHull::infoize(odocstream & os) const
-{
-       os << "Type: " << hullName(type_);
-}
-
-
-void InsetMathHull::check() const
-{
-       BOOST_ASSERT(nonum_.size() == nrows());
-       BOOST_ASSERT(label_.size() == nrows());
-}
-
-
-void InsetMathHull::doExtern(LCursor & cur, FuncRequest & func)
-{
-       docstring dlang;
-       docstring extra;
-       idocstringstream iss(func.argument());
-       iss >> dlang >> extra;
-       if (extra.empty())
-               extra = from_ascii("noextra");
-       std::string const lang = to_ascii(dlang);
-
-#ifdef WITH_WARNINGS
-#warning temporarily disabled
-       //if (cur.selection()) {
-       //      MathArray ar;
-       //      selGet(cur.ar);
-       //      lyxerr << "use selection: " << ar << endl;
-       //      insert(pipeThroughExtern(lang, extra, ar));
-       //      return;
-       //}
-#endif
-
-       MathArray eq;
-       eq.push_back(MathAtom(new InsetMathChar('=')));
-
-       // go to first item in line
-       cur.idx() -= cur.idx() % ncols();
-       cur.pos() = 0;
-
-       if (getType() == hullSimple) {
-               size_type pos = cur.cell().find_last(eq);
-               MathArray ar;
-               if (cur.inMathed() && cur.selection()) {
-                       asArray(grabAndEraseSelection(cur), ar);
-               } else if (pos == cur.cell().size()) {
-                       ar = cur.cell();
-                       lyxerr << "use whole cell: " << ar << endl;
-               } else {
-                       ar = MathArray(cur.cell().begin() + pos + 1, cur.cell().end());
-                       lyxerr << "use partial cell form pos: " << pos << endl;
-               }
-               cur.cell().append(eq);
-               cur.cell().append(pipeThroughExtern(lang, extra, ar));
-               cur.pos() = cur.lastpos();
-               return;
-       }
-
-       if (getType() == hullEquation) {
-               lyxerr << "use equation inset" << endl;
-               mutate(hullEqnArray);
-               MathArray & ar = cur.cell();
-               lyxerr << "use cell: " << ar << endl;
-               ++cur.idx();
-               cur.cell() = eq;
-               ++cur.idx();
-               cur.cell() = pipeThroughExtern(lang, extra, ar);
-               // move to end of line
-               cur.pos() = cur.lastpos();
-               return;
-       }
-
-       {
-               lyxerr << "use eqnarray" << endl;
-               cur.idx() += 2 - cur.idx() % ncols();
-               cur.pos() = 0;
-               MathArray ar = cur.cell();
-               lyxerr << "use cell: " << ar << endl;
-#ifdef WITH_WARNINGS
-#warning temporarily disabled
-#endif
-               addRow(cur.row());
-               ++cur.idx();
-               ++cur.idx();
-               cur.cell() = eq;
-               ++cur.idx();
-               cur.cell() = pipeThroughExtern(lang, extra, ar);
-               cur.pos() = cur.lastpos();
-       }
-}
-
-
-void InsetMathHull::doDispatch(LCursor & cur, FuncRequest & cmd)
-{
-       //lyxerr << "action: " << cmd.action << endl;
-       switch (cmd.action) {
-
-       case LFUN_FINISHED_LEFT:
-       case LFUN_FINISHED_RIGHT:
-       case LFUN_FINISHED_UP:
-       case LFUN_FINISHED_DOWN:
-               //lyxerr << "action: " << cmd.action << endl;
-               InsetMathGrid::doDispatch(cur, cmd);
-               notifyCursorLeaves(cur);
-               cur.undispatched();
-               break;
-
-       case LFUN_BREAK_PARAGRAPH:
-               // just swallow this
-               break;
-
-       case LFUN_BREAK_LINE:
-               // some magic for the common case
-               if (type_ == hullSimple || type_ == hullEquation) {
-                       recordUndoInset(cur);
-                       bool const align =
-                               cur.bv().buffer()->params().use_amsmath == BufferParams::package_on;
-                       mutate(align ? hullAlign : hullEqnArray);
-                       cur.idx() = 0;
-                       cur.pos() = cur.lastpos();
-               }
-               InsetMathGrid::doDispatch(cur, cmd);
-               break;
-
-       case LFUN_MATH_NUMBER:
-               //lyxerr << "toggling all numbers" << endl;
-               if (display()) {
-                       recordUndoInset(cur);
-                       bool old = numberedType();
-                       if (type_ == hullMultline)
-                               numbered(nrows() - 1, !old);
-                       else
-                               for (row_type row = 0; row < nrows(); ++row)
-                                       numbered(row, !old);
-
-                       cur.message(old ? _("No number") : _("Number"));
-               }
-               break;
-
-       case LFUN_MATH_NONUMBER:
-               if (display()) {
-                       recordUndoInset(cur);
-                       row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
-                       bool old = numbered(r);
-                       cur.message(old ? _("No number") : _("Number"));
-                       numbered(r, !old);
-               }
-               break;
-
-       case LFUN_LABEL_INSERT: {
-               recordUndoInset(cur);
-               row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
-               docstring old_label = label(r);
-               docstring const default_label = from_ascii(
-                       (lyxrc.label_init_length >= 0) ? "eq:" : "");
-               if (old_label.empty())
-                       old_label = default_label;
-
-               InsetCommandParams p("label");
-               p["name"] = cmd.argument().empty() ? old_label : cmd.argument();
-               std::string const data = InsetCommandMailer::params2string("label", p);
-
-               if (cmd.argument().empty())
-                       cur.bv().showInsetDialog("label", data, 0);
-               else {
-                       FuncRequest fr(LFUN_INSET_INSERT, data);
-                       dispatch(cur, fr);
-               }
-               break;
-       }
-
-       case LFUN_INSET_INSERT: {
-               //lyxerr << "arg: " << to_utf8(cmd.argument()) << endl;
-               std::string const name = cmd.getArg(0);
-               if (name == "label") {
-                       InsetCommandParams p("label");
-                       InsetCommandMailer::string2params(name, to_utf8(cmd.argument()), p);
-                       docstring str = p["name"];
-                       recordUndoInset(cur);
-                       row_type const r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
-                       str = support::trim(str);
-                       if (!str.empty())
-                               numbered(r, true);
-                       docstring old = label(r);
-                       if (str != old) {
-                               cur.bv().buffer()->changeRefsIfUnique(old, str,
-                                                       InsetBase::REF_CODE);
-                               label(r, str);
-                       }
-                       break;
-               }
-               InsetMathGrid::doDispatch(cur, cmd);
-               return;
-       }
-
-       case LFUN_MATH_EXTERN:
-               recordUndoInset(cur);
-               doExtern(cur, cmd);
-               break;
-
-       case LFUN_MATH_MUTATE: {
-               recordUndoInset(cur);
-               row_type row = cur.row();
-               col_type col = cur.col();
-               mutate(hullType(cmd.argument()));
-               cur.idx() = row * ncols() + col;
-               if (cur.idx() > cur.lastidx()) {
-                       cur.idx() = cur.lastidx();
-                       cur.pos() = cur.lastpos();
-               }
-               if (cur.pos() > cur.lastpos())
-                       cur.pos() = cur.lastpos();
-               //cur.dispatched(FINISHED);
-               break;
-       }
-
-       case LFUN_MATH_DISPLAY: {
-               recordUndoInset(cur);
-               mutate(type_ == hullSimple ? hullEquation : hullSimple);
-               cur.idx() = 0;
-               cur.pos() = cur.lastpos();
-               //cur.dispatched(FINISHED);
-               break;
-       }
-
-       default:
-               InsetMathGrid::doDispatch(cur, cmd);
-               break;
-       }
-}
-
-
-bool InsetMathHull::getStatus(LCursor & cur, FuncRequest const & cmd,
-               FuncStatus & status) const
-{
-       switch (cmd.action) {
-       case LFUN_FINISHED_LEFT:
-       case LFUN_FINISHED_RIGHT:
-       case LFUN_FINISHED_UP:
-       case LFUN_FINISHED_DOWN:
-               status.enabled(true);
-               return true;
-       case LFUN_BREAK_LINE:
-       case LFUN_MATH_NUMBER:
-       case LFUN_MATH_NONUMBER:
-       case LFUN_MATH_EXTERN:
-       case LFUN_MATH_MUTATE:
-       case LFUN_MATH_DISPLAY:
-               // we handle these
-               status.enabled(true);
-               return true;
-       case LFUN_LABEL_INSERT:
-               status.enabled(type_ != hullSimple);
-               return true;
-       case LFUN_INSET_INSERT:
-               if (cmd.getArg(0) == "label") {
-                       status.enabled(type_ != hullSimple);
-                       return true;
-               }
-               return InsetMathGrid::getStatus(cur, cmd, status);
-       case LFUN_TABULAR_FEATURE: {
-               istringstream is(to_utf8(cmd.argument()));
-               std::string s;
-               is >> s;
-               if (!rowChangeOK()
-                   && (s == "append-row"
-                       || s == "delete-row"
-                       || s == "copy-row")) {
-                       status.message(bformat(
-                               from_utf8(N_("Can't change number of rows in '%1$s'")),
-                               hullName(type_)));
-                       status.enabled(false);
-                       return true;
-               }
-               if (!colChangeOK()
-                   && (s == "append-column"
-                       || s == "delete-column"
-                       || s == "copy-column")) {
-                       status.message(bformat(
-                               from_utf8(N_("Can't change number of columns in '%1$s'")),
-                               hullName(type_)));
-                       status.enabled(false);
-                       return true;
-               }
-               if ((type_ == hullSimple
-                 || type_ == hullEquation
-                 || type_ == hullNone) &&
-                   (s == "add-hline-above" || s == "add-hline-below")) {
-                       status.message(bformat(
-                               from_utf8(N_("Can't add horizontal grid lines in '%1$s'")),
-                               hullName(type_)));
-                       status.enabled(false);
-                       return true;
-               }
-               if (s == "add-vline-left" || s == "add-vline-right") {
-                       status.message(bformat(
-                               from_utf8(N_("Can't add vertical grid lines in '%1$s'")),
-                               hullName(type_)));
-                       status.enabled(false);
-                       return true;
-               }
-               if (s == "valign-top" || s == "valign-middle"
-                || s == "valign-bottom" || s == "align-left"
-                || s == "align-center" || s == "align-right") {
-                       status.enabled(false);
-                       return true;
-               }
-               return InsetMathGrid::getStatus(cur, cmd, status);
-       }
-       default:
-               return InsetMathGrid::getStatus(cur, cmd, status);
-       }
-
-       // This cannot really happen, but inserted to shut-up gcc
-       return InsetMathGrid::getStatus(cur, cmd, status);
-}
-
-
-/////////////////////////////////////////////////////////////////////
-
-
-
-// simply scrap this function if you want
-void InsetMathHull::mutateToText()
-{
-#if 0
-       // translate to latex
-       ostringstream os;
-       latex(NULL, os, false, false);
-       string str = os.str();
-
-       // insert this text
-       LyXText * lt = view_->cursor().innerText();
-       string::const_iterator cit = str.begin();
-       string::const_iterator end = str.end();
-       for (; cit != end; ++cit)
-               view_->getIntl()->getTransManager().TranslateAndInsert(*cit, lt);
-
-       // remove ourselves
-       //dispatch(LFUN_ESCAPE);
-#endif
-}
-
-
-void InsetMathHull::handleFont(LCursor & cur, docstring const & arg,
-       docstring const & font)
-{
-       // this whole function is a hack and won't work for incremental font
-       // changes...
-       recordUndo(cur);
-       if (cur.inset().asInsetMath()->name() == font)
-               cur.handleFont(to_utf8(font));
-       else {
-               cur.handleNest(createInsetMath(font));
-               cur.insert(arg);
-       }
-}
-
-
-void InsetMathHull::handleFont2(LCursor & cur, docstring const & arg)
-{
-       recordUndo(cur);
-       LyXFont font;
-       bool b;
-       bv_funcs::string2font(to_utf8(arg), font, b);
-       if (font.color() != LColor::inherit) {
-               MathAtom at = MathAtom(new InsetMathColor(true, font.color()));
-               cur.handleNest(at, 0);
-       }
-}
-
-
-void InsetMathHull::edit(LCursor & cur, bool left)
-{
-       cur.push(*this);
-       left ? idxFirst(cur) : idxLast(cur);
-       // The inset formula dimension is not necessarily the same as the
-       // one of the instant preview image, so we have to indicate to the
-       // BufferView that a metrics update is needed. 
-       cur.updateFlags(Update::Force);
-}
-
-
-docstring const InsetMathHull::editMessage() const
-{
-       return _("Math editor mode");
-}
-
-
-void InsetMathHull::revealCodes(LCursor & cur) const
-{
-       if (!cur.inMathed())
-               return;
-       odocstringstream os;
-       cur.info(os);
-       cur.message(os.str());
-/*
-       // write something to the minibuffer
-       // translate to latex
-       cur.markInsert(bv);
-       ostringstream os;
-       write(NULL, os);
-       string str = os.str();
-       cur.markErase(bv);
-       string::size_type pos = 0;
-       string res;
-       for (string::iterator it = str.begin(); it != str.end(); ++it) {
-               if (*it == '\n')
-                       res += ' ';
-               else if (*it == '\0') {
-                       res += "  -X-  ";
-                       pos = it - str.begin();
-               }
-               else
-                       res += *it;
-       }
-       if (pos > 30)
-               res = res.substr(pos - 30);
-       if (res.size() > 60)
-               res = res.substr(0, 60);
-       cur.message(res);
-*/
-}
-
-
-InsetBase::Code InsetMathHull::lyxCode() const
-{
-       return MATH_CODE;
-}
-
-
-/////////////////////////////////////////////////////////////////////
-
-
-#if 0
-bool InsetMathHull::searchForward(BufferView * bv, string const & str,
-                                    bool, bool)
-{
-#ifdef WITH_WARNINGS
-#warning completely broken
-#endif
-       static InsetMathHull * lastformula = 0;
-       static CursorBase current = DocIterator(ibegin(nucleus()));
-       static MathArray ar;
-       static string laststr;
-
-       if (lastformula != this || laststr != str) {
-               //lyxerr << "reset lastformula to " << this << endl;
-               lastformula = this;
-               laststr = str;
-               current = ibegin(nucleus());
-               ar.clear();
-               mathed_parse_cell(ar, str);
-       } else {
-               increment(current);
-       }
-       //lyxerr << "searching '" << str << "' in " << this << ar << endl;
-
-       for (DocIterator it = current; it != iend(nucleus()); increment(it)) {
-               CursorSlice & top = it.back();
-               MathArray const & a = top.asInsetMath()->cell(top.idx_);
-               if (a.matchpart(ar, top.pos_)) {
-                       bv->cursor().setSelection(it, ar.size());
-                       current = it;
-                       top.pos_ += ar.size();
-                       bv->update();
-                       return true;
-               }
-       }
-
-       //lyxerr << "not found!" << endl;
-       lastformula = 0;
-       return false;
-}
-#endif
-
-
-void InsetMathHull::write(Buffer const &, std::ostream & os) const
-{
-       odocstringstream oss;
-       WriteStream wi(oss, false, false);
-       oss << "Formula ";
-       write(wi);
-       os << to_utf8(oss.str());
-}
-
-
-void InsetMathHull::read(Buffer const &, LyXLex & lex)
-{
-       MathAtom at;
-       mathed_parse_normal(at, lex);
-       operator=(*at->asHullInset());
-}
-
-
-int InsetMathHull::plaintext(Buffer const &, odocstream & os,
-                             OutputParams const &) const
-{
-       if (0 && display()) {
-               Dimension dim;
-               TextMetricsInfo mi;
-               metricsT(mi, dim);
-               TextPainter tpain(dim.width(), dim.height());
-               drawT(tpain, 0, dim.ascent());
-               tpain.show(os, 3);
-               // reset metrics cache to "real" values
-               //metrics();
-               return tpain.textheight();
-       } else {
-               odocstringstream oss;
-               WriteStream wi(oss, false, true);
-               wi << cell(0);
-
-               docstring const str = oss.str();
-               os << str;
-               return str.size();
-       }
-}
-
-
-int InsetMathHull::docbook(Buffer const & buf, odocstream & os,
-                           OutputParams const & runparams) const
-{
-       MathStream ms(os);
-       int res = 0;
-       docstring name;
-       if (getType() == hullSimple)
-               name = from_ascii("inlineequation");
-       else
-               name = from_ascii("informalequation");
-
-       docstring bname = name;
-       if (!label(0).empty())
-               bname += " id='" + sgml::cleanID(buf, runparams, label(0)) + "'";
-       ms << MTag(bname);
-
-       odocstringstream ls;
-       if (runparams.flavor == OutputParams::XML) {
-               ms << MTag(from_ascii("alt role='tex' "));
-               // Workaround for db2latex: db2latex always includes equations with
-               // \ensuremath{} or \begin{display}\end{display}
-               // so we strip LyX' math environment
-               WriteStream wi(ls, false, false);
-               InsetMathGrid::write(wi);
-               ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&amp;"), "<", "&lt;"));
-               ms << ETag(from_ascii("alt"));
-               ms << MTag(from_ascii("math"));
-               ms << ETag(from_ascii("alt"));
-               ms << MTag(from_ascii("math"));
-               InsetMathGrid::mathmlize(ms);
-               ms << ETag(from_ascii("math"));
-       } else {
-               ms << MTag(from_ascii("alt role='tex'"));
-               res = latex(buf, ls, runparams);
-               ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&amp;"), "<", "&lt;"));
-               ms << ETag(from_ascii("alt"));
-       }
-
-       ms << from_ascii("<graphic fileref=\"eqn/");
-       if (!label(0).empty())
-               ms << sgml::cleanID(buf, runparams, label(0));
-       else
-               ms << sgml::uniqueID(from_ascii("anon"));
-
-       if (runparams.flavor == OutputParams::XML)
-               ms << from_ascii("\"/>");
-       else
-               ms << from_ascii("\">");
-
-       ms << ETag(name);
-       return ms.line() + res;
-}
-
-
-void InsetMathHull::textString(Buffer const & buf, odocstream & os) const
-{
-       plaintext(buf, os, OutputParams(0));
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp
new file mode 100644 (file)
index 0000000..cd3a590
--- /dev/null
@@ -0,0 +1,1525 @@
+/**
+ * \file InsetMathHull.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathArray.h"
+#include "InsetMathChar.h"
+#include "InsetMathColor.h"
+#include "MathData.h"
+#include "InsetMathDelim.h"
+#include "MathExtern.h"
+#include "MathFactory.h"
+#include "InsetMathHull.h"
+#include "MathStream.h"
+#include "MathParser.h"
+#include "InsetMathSpace.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "InsetMathRef.h"
+
+#include "bufferview_funcs.h"
+#include "lyxtext.h"
+
+#include "buffer.h"
+#include "bufferparams.h"
+#include "BufferView.h"
+#include "CutAndPaste.h"
+#include "FuncStatus.h"
+#include "LColor.h"
+#include "LaTeXFeatures.h"
+#include "cursor.h"
+#include "debug.h"
+#include "dispatchresult.h"
+#include "funcrequest.h"
+#include "gettext.h"
+#include "lyxrc.h"
+#include "outputparams.h"
+#include "sgml.h"
+#include "TextPainter.h"
+#include "undo.h"
+
+#include "insets/RenderPreview.h"
+#include "insets/InsetLabel.h"
+
+#include "graphics/PreviewImage.h"
+#include "graphics/PreviewLoader.h"
+
+#include "support/lyxlib.h"
+#include "support/lstrings.h"
+
+#include <boost/bind.hpp>
+
+#include <sstream>
+
+
+namespace lyx {
+
+using cap::grabAndEraseSelection;
+using support::bformat;
+using support::subst;
+
+using std::endl;
+using std::max;
+using std::ostream;
+using std::auto_ptr;
+using std::istringstream;
+using std::ostringstream;
+using std::pair;
+using std::swap;
+using std::vector;
+
+
+namespace {
+
+       int getCols(HullType type)
+       {
+               switch (type) {
+                       case hullEqnArray:
+                               return 3;
+                       case hullAlign:
+                       case hullFlAlign:
+                       case hullAlignAt:
+                       case hullXAlignAt:
+                       case hullXXAlignAt:
+                               return 2;
+                       default:
+                               return 1;
+               }
+       }
+
+
+       // returns position of first relation operator in the array
+       // used for "intelligent splitting"
+       size_t firstRelOp(MathArray const & ar)
+       {
+               for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+                       if ((*it)->isRelOp())
+                               return it - ar.begin();
+               return ar.size();
+       }
+
+
+       char const * star(bool numbered)
+       {
+               return numbered ? "" : "*";
+       }
+
+
+} // end anon namespace
+
+
+HullType hullType(docstring const & s)
+{
+       if (s == "none")      return hullNone;
+       if (s == "simple")    return hullSimple;
+       if (s == "equation")  return hullEquation;
+       if (s == "eqnarray")  return hullEqnArray;
+       if (s == "align")     return hullAlign;
+       if (s == "alignat")   return hullAlignAt;
+       if (s == "xalignat")  return hullXAlignAt;
+       if (s == "xxalignat") return hullXXAlignAt;
+       if (s == "multline")  return hullMultline;
+       if (s == "gather")    return hullGather;
+       if (s == "flalign")   return hullFlAlign;
+       lyxerr << "unknown hull type '" << to_utf8(s) << "'" << endl;
+       return HullType(-1);
+}
+
+
+docstring hullName(HullType type)
+{
+       switch (type) {
+               case hullNone:       return from_ascii("none");
+               case hullSimple:     return from_ascii("simple");
+               case hullEquation:   return from_ascii("equation");
+               case hullEqnArray:   return from_ascii("eqnarray");
+               case hullAlign:      return from_ascii("align");
+               case hullAlignAt:    return from_ascii("alignat");
+               case hullXAlignAt:   return from_ascii("xalignat");
+               case hullXXAlignAt:  return from_ascii("xxalignat");
+               case hullMultline:   return from_ascii("multline");
+               case hullGather:     return from_ascii("gather");
+               case hullFlAlign:    return from_ascii("flalign");
+               default:
+                       lyxerr << "unknown hull type '" << type << "'" << endl;
+                       return from_ascii("none");
+       }
+}
+
+
+InsetMathHull::InsetMathHull()
+       : InsetMathGrid(1, 1), type_(hullNone), nonum_(1), label_(1),
+         preview_(new RenderPreview(this))
+{
+       //lyxerr << "sizeof InsetMath: " << sizeof(InsetMath) << endl;
+       //lyxerr << "sizeof MetricsInfo: " << sizeof(MetricsInfo) << endl;
+       //lyxerr << "sizeof InsetMathChar: " << sizeof(InsetMathChar) << endl;
+       //lyxerr << "sizeof LyXFont: " << sizeof(LyXFont) << endl;
+       initMath();
+       setDefaults();
+}
+
+
+InsetMathHull::InsetMathHull(HullType type)
+       : InsetMathGrid(getCols(type), 1), type_(type), nonum_(1), label_(1),
+         preview_(new RenderPreview(this))
+{
+       initMath();
+       setDefaults();
+}
+
+
+InsetMathHull::InsetMathHull(InsetMathHull const & other)
+       : InsetMathGrid(other),
+         type_(other.type_), nonum_(other.nonum_), label_(other.label_),
+         preview_(new RenderPreview(this))
+{}
+
+
+InsetMathHull::~InsetMathHull()
+{}
+
+
+auto_ptr<InsetBase> InsetMathHull::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathHull(*this));
+}
+
+
+InsetMathHull & InsetMathHull::operator=(InsetMathHull const & other)
+{
+       if (this == &other)
+               return *this;
+       *static_cast<InsetMathGrid*>(this) = InsetMathGrid(other);
+       type_  = other.type_;
+       nonum_ = other.nonum_;
+       label_ = other.label_;
+       preview_.reset(new RenderPreview(*other.preview_, this));
+
+       return *this;
+}
+
+
+InsetBase * InsetMathHull::editXY(LCursor & cur, int x, int y)
+{
+       if (use_preview_) {
+               edit(cur, true);
+               return this;
+       }
+       return InsetMathNest::editXY(cur, x, y);
+}
+
+
+InsetMath::mode_type InsetMathHull::currentMode() const
+{
+       if (type_ == hullNone)
+               return UNDECIDED_MODE;
+       // definitely math mode ...
+       return MATH_MODE;
+}
+
+
+bool InsetMathHull::idxFirst(LCursor & cur) const
+{
+       cur.idx() = 0;
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathHull::idxLast(LCursor & cur) const
+{
+       cur.idx() = nargs() - 1;
+       cur.pos() = cur.lastpos();
+       return true;
+}
+
+
+char InsetMathHull::defaultColAlign(col_type col)
+{
+       if (type_ == hullEqnArray)
+               return "rcl"[col];
+       if (type_ >= hullAlign)
+               return "rl"[col & 1];
+       return 'c';
+}
+
+
+int InsetMathHull::defaultColSpace(col_type col)
+{
+       if (type_ == hullAlign || type_ == hullAlignAt)
+               return 0;
+       if (type_ == hullXAlignAt)
+               return (col & 1) ? 20 : 0;
+       if (type_ == hullXXAlignAt || type_ == hullFlAlign)
+               return (col & 1) ? 40 : 0;
+       return 0;
+}
+
+
+docstring InsetMathHull::standardFont() const
+{
+       return from_ascii(type_ == hullNone ? "lyxnochange" : "mathnormal");
+}
+
+
+bool InsetMathHull::previewState(BufferView * bv) const
+{
+       if (!editing(bv) && RenderPreview::status() == LyXRC::PREVIEW_ON) {
+               graphics::PreviewImage const * pimage =
+                       preview_->getPreviewImage(*bv->buffer());
+               return pimage && pimage->image();
+       }
+       return false;
+}
+
+
+bool InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (previewState(mi.base.bv)) {
+               preview_->metrics(mi, dim);
+               // insert a one pixel gap in front of the formula
+               dim.wid += 1;
+               if (display())
+                       dim.des += displayMargin();
+               if (dim_ == dim)
+                       return false;
+               dim_ = dim;
+               return true;
+       }
+
+       FontSetChanger dummy1(mi.base, standardFont());
+       StyleChanger dummy2(mi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT);
+
+       // let the cells adjust themselves
+       InsetMathGrid::metrics(mi, dim);
+
+       if (display()) {
+               dim.asc += displayMargin();
+               dim.des += displayMargin();
+       }
+
+       if (numberedType()) {
+               FontSetChanger dummy(mi.base, from_ascii("mathbf"));
+               int l = 0;
+               for (row_type row = 0; row < nrows(); ++row)
+                       l = max(l, mathed_string_width(mi.base.font, nicelabel(row)));
+
+               if (l)
+                       dim.wid += 30 + l;
+       }
+
+       // make it at least as high as the current font
+       int asc = 0;
+       int des = 0;
+       math_font_max_dim(mi.base.font, asc, des);
+       dim.asc = max(dim.asc, asc);
+       dim.des = max(dim.des, des);
+
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathHull::draw(PainterInfo & pi, int x, int y) const
+{
+       use_preview_ = previewState(pi.base.bv);
+
+       if (use_preview_) {
+               // one pixel gap in front
+               preview_->draw(pi, x + 1, y);
+               setPosCache(pi, x, y);
+               return;
+       }
+
+       FontSetChanger dummy1(pi.base, standardFont());
+       StyleChanger dummy2(pi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT);
+       InsetMathGrid::draw(pi, x + 1, y);
+
+       if (numberedType()) {
+               int const xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20;
+               for (row_type row = 0; row < nrows(); ++row) {
+                       int const yy = y + rowinfo_[row].offset_;
+                       FontSetChanger dummy(pi.base, from_ascii("mathrm"));
+                       docstring const nl = nicelabel(row);
+                       pi.draw(xx, yy, nl);
+               }
+       }
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathHull::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       if (display()) {
+               InsetMathGrid::metricsT(mi, dim);
+       } else {
+               odocstringstream os;
+               WriteStream wi(os, false, true);
+               write(wi);
+               dim.wid = os.str().size();
+               dim.asc = 1;
+               dim.des = 0;
+       }
+}
+
+
+void InsetMathHull::drawT(TextPainter & pain, int x, int y) const
+{
+       if (display()) {
+               InsetMathGrid::drawT(pain, x, y);
+       } else {
+               odocstringstream os;
+               WriteStream wi(os, false, true);
+               write(wi);
+               pain.draw(x, y, os.str().c_str());
+       }
+}
+
+
+namespace {
+
+docstring const latex_string(InsetMathHull const & inset)
+{
+       odocstringstream ls;
+       WriteStream wi(ls, false, false);
+       inset.write(wi);
+       return ls.str();
+}
+
+} // namespace anon
+
+
+void InsetMathHull::addPreview(graphics::PreviewLoader & ploader) const
+{
+       if (RenderPreview::status() == LyXRC::PREVIEW_ON) {
+               docstring const snippet = latex_string(*this);
+               preview_->addPreview(snippet, ploader);
+       }
+}
+
+
+bool InsetMathHull::notifyCursorLeaves(LCursor & cur)
+{
+       if (RenderPreview::status() == LyXRC::PREVIEW_ON) {
+               Buffer const & buffer = cur.buffer();
+               docstring const snippet = latex_string(*this);
+               preview_->addPreview(snippet, buffer);
+               preview_->startLoading(buffer);
+               cur.updateFlags(Update::Force);
+       }
+       return false;
+}
+
+
+docstring InsetMathHull::label(row_type row) const
+{
+       BOOST_ASSERT(row < nrows());
+       return label_[row];
+}
+
+
+void InsetMathHull::label(row_type row, docstring const & label)
+{
+       //lyxerr << "setting label '" << label << "' for row " << row << endl;
+       label_[row] = label;
+}
+
+
+void InsetMathHull::numbered(row_type row, bool num)
+{
+       nonum_[row] = !num;
+       if (nonum_[row])
+               label_[row].clear();
+}
+
+
+bool InsetMathHull::numbered(row_type row) const
+{
+       return !nonum_[row];
+}
+
+
+bool InsetMathHull::ams() const
+{
+       return
+               type_ == hullAlign ||
+               type_ == hullFlAlign ||
+               type_ == hullMultline ||
+               type_ == hullGather ||
+               type_ == hullAlignAt ||
+               type_ == hullXAlignAt ||
+               type_ == hullXXAlignAt;
+}
+
+
+bool InsetMathHull::display() const
+{
+       return type_ != hullSimple && type_ != hullNone;
+}
+
+
+void InsetMathHull::getLabelList(Buffer const &, vector<docstring> & labels) const
+{
+       for (row_type row = 0; row < nrows(); ++row)
+               if (!label_[row].empty() && nonum_[row] != 1)
+                       labels.push_back(label_[row]);
+}
+
+
+bool InsetMathHull::numberedType() const
+{
+       if (type_ == hullNone)
+               return false;
+       if (type_ == hullSimple)
+               return false;
+       if (type_ == hullXXAlignAt)
+               return false;
+       for (row_type row = 0; row < nrows(); ++row)
+               if (!nonum_[row])
+                       return true;
+       return false;
+}
+
+
+void InsetMathHull::validate(LaTeXFeatures & features) const
+{
+       if (ams())
+               features.require("amsmath");
+
+
+       // Validation is necessary only if not using AMS math.
+       // To be safe, we will always run mathedvalidate.
+       //if (features.amsstyle)
+       //  return;
+
+       features.require("boldsymbol");
+       //features.binom      = true;
+
+       InsetMathGrid::validate(features);
+}
+
+
+void InsetMathHull::header_write(WriteStream & os) const
+{
+       bool n = numberedType();
+
+       switch(type_) {
+       case hullNone:
+               break;
+
+       case hullSimple:
+               os << '$';
+               if (cell(0).empty())
+                       os << ' ';
+               break;
+
+       case hullEquation:
+               if (n)
+                       os << "\\begin{equation" << star(n) << "}\n";
+               else
+                       os << "\\[\n";
+               break;
+
+       case hullEqnArray:
+       case hullAlign:
+       case hullFlAlign:
+       case hullGather:
+       case hullMultline:
+               os << "\\begin{" << hullName(type_) << star(n) << "}\n";
+               break;
+
+       case hullAlignAt:
+       case hullXAlignAt:
+               os << "\\begin{" << hullName(type_) << star(n) << '}'
+                 << '{' << static_cast<unsigned int>((ncols() + 1)/2) << "}\n";
+               break;
+
+       case hullXXAlignAt:
+               os << "\\begin{" << hullName(type_) << '}'
+                 << '{' << static_cast<unsigned int>((ncols() + 1)/2) << "}\n";
+               break;
+
+       default:
+               os << "\\begin{unknown" << star(n) << '}';
+               break;
+       }
+}
+
+
+void InsetMathHull::footer_write(WriteStream & os) const
+{
+       bool n = numberedType();
+
+       switch(type_) {
+       case hullNone:
+               os << "\n";
+               break;
+
+       case hullSimple:
+               os << '$';
+               break;
+
+       case hullEquation:
+               if (n)
+                       os << "\\end{equation" << star(n) << "}\n";
+               else
+                       os << "\\]\n";
+               break;
+
+       case hullEqnArray:
+       case hullAlign:
+       case hullFlAlign:
+       case hullAlignAt:
+       case hullXAlignAt:
+       case hullGather:
+       case hullMultline:
+               os << "\\end{" << hullName(type_) << star(n) << "}\n";
+               break;
+
+       case hullXXAlignAt:
+               os << "\\end{" << hullName(type_) << "}\n";
+               break;
+
+       default:
+               os << "\\end{unknown" << star(n) << '}';
+               break;
+       }
+}
+
+
+bool InsetMathHull::rowChangeOK() const
+{
+       return
+               type_ == hullEqnArray || type_ == hullAlign ||
+               type_ == hullFlAlign || type_ == hullAlignAt ||
+               type_ == hullXAlignAt || type_ == hullXXAlignAt ||
+               type_ == hullGather || type_ == hullMultline;
+}
+
+
+bool InsetMathHull::colChangeOK() const
+{
+       return
+               type_ == hullAlign || type_ == hullFlAlign ||type_ == hullAlignAt ||
+               type_ == hullXAlignAt || type_ == hullXXAlignAt;
+}
+
+
+void InsetMathHull::addRow(row_type row)
+{
+       if (!rowChangeOK())
+               return;
+       nonum_.insert(nonum_.begin() + row + 1, !numberedType());
+       label_.insert(label_.begin() + row + 1, docstring());
+       InsetMathGrid::addRow(row);
+}
+
+
+void InsetMathHull::swapRow(row_type row)
+{
+       if (nrows() <= 1)
+               return;
+       if (row + 1 == nrows())
+               --row;
+       swap(nonum_[row], nonum_[row + 1]);
+       swap(label_[row], label_[row + 1]);
+       InsetMathGrid::swapRow(row);
+}
+
+
+void InsetMathHull::delRow(row_type row)
+{
+       if (nrows() <= 1 || !rowChangeOK())
+               return;
+       InsetMathGrid::delRow(row);
+       // The last dummy row has no number info nor a label.
+       // Test nrows() + 1 because we have already erased the row.
+       if (row == nrows() + 1)
+               row--;
+       nonum_.erase(nonum_.begin() + row);
+       label_.erase(label_.begin() + row);
+}
+
+
+void InsetMathHull::addCol(col_type col)
+{
+       if (!colChangeOK())
+               return;
+       InsetMathGrid::addCol(col);
+}
+
+
+void InsetMathHull::delCol(col_type col)
+{
+       if (ncols() <= 1 || !colChangeOK())
+               return;
+       InsetMathGrid::delCol(col);
+}
+
+
+docstring InsetMathHull::nicelabel(row_type row) const
+{
+       if (nonum_[row])
+               return docstring();
+       if (label_[row].empty())
+               return from_ascii("(#)");
+       return '(' + label_[row] + ')';
+}
+
+
+void InsetMathHull::glueall()
+{
+       MathArray ar;
+       for (idx_type i = 0; i < nargs(); ++i)
+               ar.append(cell(i));
+       *this = InsetMathHull(hullSimple);
+       cell(0) = ar;
+       setDefaults();
+}
+
+
+void InsetMathHull::splitTo2Cols()
+{
+       BOOST_ASSERT(ncols() == 1);
+       InsetMathGrid::addCol(1);
+       for (row_type row = 0; row < nrows(); ++row) {
+               idx_type const i = 2 * row;
+               pos_type pos = firstRelOp(cell(i));
+               cell(i + 1) = MathArray(cell(i).begin() + pos, cell(i).end());
+               cell(i).erase(pos, cell(i).size());
+       }
+}
+
+
+void InsetMathHull::splitTo3Cols()
+{
+       BOOST_ASSERT(ncols() < 3);
+       if (ncols() < 2)
+               splitTo2Cols();
+       InsetMathGrid::addCol(1);
+       for (row_type row = 0; row < nrows(); ++row) {
+               idx_type const i = 3 * row + 1;
+               if (cell(i).size()) {
+                       cell(i + 1) = MathArray(cell(i).begin() + 1, cell(i).end());
+                       cell(i).erase(1, cell(i).size());
+               }
+       }
+}
+
+
+void InsetMathHull::changeCols(col_type cols)
+{
+       if (ncols() == cols)
+               return;
+       else if (ncols() < cols) {
+               // split columns
+               if (cols < 3)
+                       splitTo2Cols();
+               else {
+                       splitTo3Cols();
+                       while (ncols() < cols)
+                               InsetMathGrid::addCol(ncols() - 1);
+               }
+               return;
+       }
+
+       // combine columns
+       for (row_type row = 0; row < nrows(); ++row) {
+               idx_type const i = row * ncols();
+               for (col_type col = cols; col < ncols(); ++col) {
+                       cell(i + cols - 1).append(cell(i + col));
+               }
+       }
+       // delete columns
+       while (ncols() > cols) {
+               InsetMathGrid::delCol(ncols() - 1);
+       }
+}
+
+
+HullType InsetMathHull::getType() const
+{
+       return type_;
+}
+
+
+void InsetMathHull::setType(HullType type)
+{
+       type_ = type;
+       setDefaults();
+}
+
+
+void InsetMathHull::mutate(HullType newtype)
+{
+       //lyxerr << "mutating from '" << type_ << "' to '" << newtype << "'" << endl;
+
+       // we try to move along the chain
+       // none <-> simple <-> equation <-> eqnarray -> *align* -> multline, gather -+
+       //                                     ^                                     |
+       //                                     +-------------------------------------+
+       // we use eqnarray as intermediate type for mutations that are not
+       // directly supported because it handles labels and numbering for
+       // "down mutation".
+
+       if (newtype == type_) {
+               // done
+       }
+
+       else if (newtype < hullNone) {
+               // unknown type
+               dump();
+       }
+
+       else if (type_ == hullNone) {
+               setType(hullSimple);
+               numbered(0, false);
+               mutate(newtype);
+       }
+
+       else if (type_ == hullSimple) {
+               if (newtype == hullNone) {
+                       setType(hullNone);
+                       numbered(0, false);
+               } else {
+                       setType(hullEquation);
+                       numbered(0, false);
+                       mutate(newtype);
+               }
+       }
+
+       else if (type_ == hullEquation) {
+               if (newtype < type_) {
+                       setType(hullSimple);
+                       numbered(0, false);
+                       mutate(newtype);
+               } else if (newtype == hullEqnArray) {
+                       // split it "nicely" on the first relop
+                       splitTo3Cols();
+                       setType(hullEqnArray);
+               } else if (newtype == hullMultline || newtype == hullGather) {
+                       setType(newtype);
+               } else {
+                       // split it "nicely"
+                       splitTo2Cols();
+                       setType(hullAlign);
+                       mutate(newtype);
+               }
+       }
+
+       else if (type_ == hullEqnArray) {
+               if (newtype < type_) {
+                       // set correct (no)numbering
+                       bool allnonum = true;
+                       for (row_type row = 0; row < nrows(); ++row)
+                               if (!nonum_[row])
+                                       allnonum = false;
+
+                       // set first non-empty label
+                       docstring label;
+                       for (row_type row = 0; row < nrows(); ++row) {
+                               if (!label_[row].empty()) {
+                                       label = label_[row];
+                                       break;
+                               }
+                       }
+
+                       glueall();
+                       nonum_[0] = allnonum;
+                       label_[0] = label;
+                       mutate(newtype);
+               } else { // align & Co.
+                       changeCols(2);
+                       setType(hullAlign);
+                       mutate(newtype);
+               }
+       }
+
+       else if (type_ ==  hullAlign || type_ == hullAlignAt ||
+                type_ == hullXAlignAt || type_ == hullFlAlign) {
+               if (newtype < hullAlign) {
+                       changeCols(3);
+                       setType(hullEqnArray);
+                       mutate(newtype);
+               } else if (newtype == hullGather || newtype == hullMultline) {
+                       changeCols(1);
+                       setType(newtype);
+               } else if (newtype ==   hullXXAlignAt) {
+                       for (row_type row = 0; row < nrows(); ++row)
+                               numbered(row, false);
+                       setType(newtype);
+               } else {
+                       setType(newtype);
+               }
+       }
+
+       else if (type_ == hullXXAlignAt) {
+               for (row_type row = 0; row < nrows(); ++row)
+                       numbered(row, false);
+               if (newtype < hullAlign) {
+                       changeCols(3);
+                       setType(hullEqnArray);
+                       mutate(newtype);
+               } else if (newtype == hullGather || newtype == hullMultline) {
+                       changeCols(1);
+                       setType(newtype);
+               } else {
+                       setType(newtype);
+               }
+       }
+
+       else if (type_ == hullMultline || type_ == hullGather) {
+               if (newtype == hullGather || newtype == hullMultline)
+                       setType(newtype);
+               else if (newtype == hullAlign || newtype == hullFlAlign  ||
+                        newtype == hullAlignAt || newtype == hullXAlignAt) {
+                       splitTo2Cols();
+                       setType(newtype);
+               } else if (newtype ==   hullXXAlignAt) {
+                       splitTo2Cols();
+                       for (row_type row = 0; row < nrows(); ++row)
+                               numbered(row, false);
+                       setType(newtype);
+               } else {
+                       splitTo3Cols();
+                       setType(hullEqnArray);
+                       mutate(newtype);
+               }
+       }
+
+       else {
+               lyxerr << "mutation from '" << to_utf8(hullName(type_))
+                      << "' to '" << to_utf8(hullName(newtype))
+                      << "' not implemented" << endl;
+       }
+}
+
+
+docstring InsetMathHull::eolString(row_type row, bool emptyline, bool fragile) const
+{
+       docstring res;
+       if (numberedType()) {
+               if (!label_[row].empty() && !nonum_[row])
+                       res += "\\label{" + label_[row] + '}';
+               if (nonum_[row] && (type_ != hullMultline))
+                       res += "\\nonumber ";
+       }
+       return res + InsetMathGrid::eolString(row, emptyline, fragile);
+}
+
+
+void InsetMathHull::write(WriteStream & os) const
+{
+       header_write(os);
+       InsetMathGrid::write(os);
+       footer_write(os);
+}
+
+
+void InsetMathHull::normalize(NormalStream & os) const
+{
+       os << "[formula " << hullName(type_) << ' ';
+       InsetMathGrid::normalize(os);
+       os << "] ";
+}
+
+
+void InsetMathHull::mathmlize(MathStream & os) const
+{
+       InsetMathGrid::mathmlize(os);
+}
+
+
+void InsetMathHull::infoize(odocstream & os) const
+{
+       os << "Type: " << hullName(type_);
+}
+
+
+void InsetMathHull::check() const
+{
+       BOOST_ASSERT(nonum_.size() == nrows());
+       BOOST_ASSERT(label_.size() == nrows());
+}
+
+
+void InsetMathHull::doExtern(LCursor & cur, FuncRequest & func)
+{
+       docstring dlang;
+       docstring extra;
+       idocstringstream iss(func.argument());
+       iss >> dlang >> extra;
+       if (extra.empty())
+               extra = from_ascii("noextra");
+       std::string const lang = to_ascii(dlang);
+
+#ifdef WITH_WARNINGS
+#warning temporarily disabled
+       //if (cur.selection()) {
+       //      MathArray ar;
+       //      selGet(cur.ar);
+       //      lyxerr << "use selection: " << ar << endl;
+       //      insert(pipeThroughExtern(lang, extra, ar));
+       //      return;
+       //}
+#endif
+
+       MathArray eq;
+       eq.push_back(MathAtom(new InsetMathChar('=')));
+
+       // go to first item in line
+       cur.idx() -= cur.idx() % ncols();
+       cur.pos() = 0;
+
+       if (getType() == hullSimple) {
+               size_type pos = cur.cell().find_last(eq);
+               MathArray ar;
+               if (cur.inMathed() && cur.selection()) {
+                       asArray(grabAndEraseSelection(cur), ar);
+               } else if (pos == cur.cell().size()) {
+                       ar = cur.cell();
+                       lyxerr << "use whole cell: " << ar << endl;
+               } else {
+                       ar = MathArray(cur.cell().begin() + pos + 1, cur.cell().end());
+                       lyxerr << "use partial cell form pos: " << pos << endl;
+               }
+               cur.cell().append(eq);
+               cur.cell().append(pipeThroughExtern(lang, extra, ar));
+               cur.pos() = cur.lastpos();
+               return;
+       }
+
+       if (getType() == hullEquation) {
+               lyxerr << "use equation inset" << endl;
+               mutate(hullEqnArray);
+               MathArray & ar = cur.cell();
+               lyxerr << "use cell: " << ar << endl;
+               ++cur.idx();
+               cur.cell() = eq;
+               ++cur.idx();
+               cur.cell() = pipeThroughExtern(lang, extra, ar);
+               // move to end of line
+               cur.pos() = cur.lastpos();
+               return;
+       }
+
+       {
+               lyxerr << "use eqnarray" << endl;
+               cur.idx() += 2 - cur.idx() % ncols();
+               cur.pos() = 0;
+               MathArray ar = cur.cell();
+               lyxerr << "use cell: " << ar << endl;
+#ifdef WITH_WARNINGS
+#warning temporarily disabled
+#endif
+               addRow(cur.row());
+               ++cur.idx();
+               ++cur.idx();
+               cur.cell() = eq;
+               ++cur.idx();
+               cur.cell() = pipeThroughExtern(lang, extra, ar);
+               cur.pos() = cur.lastpos();
+       }
+}
+
+
+void InsetMathHull::doDispatch(LCursor & cur, FuncRequest & cmd)
+{
+       //lyxerr << "action: " << cmd.action << endl;
+       switch (cmd.action) {
+
+       case LFUN_FINISHED_LEFT:
+       case LFUN_FINISHED_RIGHT:
+       case LFUN_FINISHED_UP:
+       case LFUN_FINISHED_DOWN:
+               //lyxerr << "action: " << cmd.action << endl;
+               InsetMathGrid::doDispatch(cur, cmd);
+               notifyCursorLeaves(cur);
+               cur.undispatched();
+               break;
+
+       case LFUN_BREAK_PARAGRAPH:
+               // just swallow this
+               break;
+
+       case LFUN_BREAK_LINE:
+               // some magic for the common case
+               if (type_ == hullSimple || type_ == hullEquation) {
+                       recordUndoInset(cur);
+                       bool const align =
+                               cur.bv().buffer()->params().use_amsmath == BufferParams::package_on;
+                       mutate(align ? hullAlign : hullEqnArray);
+                       cur.idx() = 0;
+                       cur.pos() = cur.lastpos();
+               }
+               InsetMathGrid::doDispatch(cur, cmd);
+               break;
+
+       case LFUN_MATH_NUMBER:
+               //lyxerr << "toggling all numbers" << endl;
+               if (display()) {
+                       recordUndoInset(cur);
+                       bool old = numberedType();
+                       if (type_ == hullMultline)
+                               numbered(nrows() - 1, !old);
+                       else
+                               for (row_type row = 0; row < nrows(); ++row)
+                                       numbered(row, !old);
+
+                       cur.message(old ? _("No number") : _("Number"));
+               }
+               break;
+
+       case LFUN_MATH_NONUMBER:
+               if (display()) {
+                       recordUndoInset(cur);
+                       row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
+                       bool old = numbered(r);
+                       cur.message(old ? _("No number") : _("Number"));
+                       numbered(r, !old);
+               }
+               break;
+
+       case LFUN_LABEL_INSERT: {
+               recordUndoInset(cur);
+               row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
+               docstring old_label = label(r);
+               docstring const default_label = from_ascii(
+                       (lyxrc.label_init_length >= 0) ? "eq:" : "");
+               if (old_label.empty())
+                       old_label = default_label;
+
+               InsetCommandParams p("label");
+               p["name"] = cmd.argument().empty() ? old_label : cmd.argument();
+               std::string const data = InsetCommandMailer::params2string("label", p);
+
+               if (cmd.argument().empty())
+                       cur.bv().showInsetDialog("label", data, 0);
+               else {
+                       FuncRequest fr(LFUN_INSET_INSERT, data);
+                       dispatch(cur, fr);
+               }
+               break;
+       }
+
+       case LFUN_INSET_INSERT: {
+               //lyxerr << "arg: " << to_utf8(cmd.argument()) << endl;
+               std::string const name = cmd.getArg(0);
+               if (name == "label") {
+                       InsetCommandParams p("label");
+                       InsetCommandMailer::string2params(name, to_utf8(cmd.argument()), p);
+                       docstring str = p["name"];
+                       recordUndoInset(cur);
+                       row_type const r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
+                       str = support::trim(str);
+                       if (!str.empty())
+                               numbered(r, true);
+                       docstring old = label(r);
+                       if (str != old) {
+                               cur.bv().buffer()->changeRefsIfUnique(old, str,
+                                                       InsetBase::REF_CODE);
+                               label(r, str);
+                       }
+                       break;
+               }
+               InsetMathGrid::doDispatch(cur, cmd);
+               return;
+       }
+
+       case LFUN_MATH_EXTERN:
+               recordUndoInset(cur);
+               doExtern(cur, cmd);
+               break;
+
+       case LFUN_MATH_MUTATE: {
+               recordUndoInset(cur);
+               row_type row = cur.row();
+               col_type col = cur.col();
+               mutate(hullType(cmd.argument()));
+               cur.idx() = row * ncols() + col;
+               if (cur.idx() > cur.lastidx()) {
+                       cur.idx() = cur.lastidx();
+                       cur.pos() = cur.lastpos();
+               }
+               if (cur.pos() > cur.lastpos())
+                       cur.pos() = cur.lastpos();
+               //cur.dispatched(FINISHED);
+               break;
+       }
+
+       case LFUN_MATH_DISPLAY: {
+               recordUndoInset(cur);
+               mutate(type_ == hullSimple ? hullEquation : hullSimple);
+               cur.idx() = 0;
+               cur.pos() = cur.lastpos();
+               //cur.dispatched(FINISHED);
+               break;
+       }
+
+       default:
+               InsetMathGrid::doDispatch(cur, cmd);
+               break;
+       }
+}
+
+
+bool InsetMathHull::getStatus(LCursor & cur, FuncRequest const & cmd,
+               FuncStatus & status) const
+{
+       switch (cmd.action) {
+       case LFUN_FINISHED_LEFT:
+       case LFUN_FINISHED_RIGHT:
+       case LFUN_FINISHED_UP:
+       case LFUN_FINISHED_DOWN:
+               status.enabled(true);
+               return true;
+       case LFUN_BREAK_LINE:
+       case LFUN_MATH_NUMBER:
+       case LFUN_MATH_NONUMBER:
+       case LFUN_MATH_EXTERN:
+       case LFUN_MATH_MUTATE:
+       case LFUN_MATH_DISPLAY:
+               // we handle these
+               status.enabled(true);
+               return true;
+       case LFUN_LABEL_INSERT:
+               status.enabled(type_ != hullSimple);
+               return true;
+       case LFUN_INSET_INSERT:
+               if (cmd.getArg(0) == "label") {
+                       status.enabled(type_ != hullSimple);
+                       return true;
+               }
+               return InsetMathGrid::getStatus(cur, cmd, status);
+       case LFUN_TABULAR_FEATURE: {
+               istringstream is(to_utf8(cmd.argument()));
+               std::string s;
+               is >> s;
+               if (!rowChangeOK()
+                   && (s == "append-row"
+                       || s == "delete-row"
+                       || s == "copy-row")) {
+                       status.message(bformat(
+                               from_utf8(N_("Can't change number of rows in '%1$s'")),
+                               hullName(type_)));
+                       status.enabled(false);
+                       return true;
+               }
+               if (!colChangeOK()
+                   && (s == "append-column"
+                       || s == "delete-column"
+                       || s == "copy-column")) {
+                       status.message(bformat(
+                               from_utf8(N_("Can't change number of columns in '%1$s'")),
+                               hullName(type_)));
+                       status.enabled(false);
+                       return true;
+               }
+               if ((type_ == hullSimple
+                 || type_ == hullEquation
+                 || type_ == hullNone) &&
+                   (s == "add-hline-above" || s == "add-hline-below")) {
+                       status.message(bformat(
+                               from_utf8(N_("Can't add horizontal grid lines in '%1$s'")),
+                               hullName(type_)));
+                       status.enabled(false);
+                       return true;
+               }
+               if (s == "add-vline-left" || s == "add-vline-right") {
+                       status.message(bformat(
+                               from_utf8(N_("Can't add vertical grid lines in '%1$s'")),
+                               hullName(type_)));
+                       status.enabled(false);
+                       return true;
+               }
+               if (s == "valign-top" || s == "valign-middle"
+                || s == "valign-bottom" || s == "align-left"
+                || s == "align-center" || s == "align-right") {
+                       status.enabled(false);
+                       return true;
+               }
+               return InsetMathGrid::getStatus(cur, cmd, status);
+       }
+       default:
+               return InsetMathGrid::getStatus(cur, cmd, status);
+       }
+
+       // This cannot really happen, but inserted to shut-up gcc
+       return InsetMathGrid::getStatus(cur, cmd, status);
+}
+
+
+/////////////////////////////////////////////////////////////////////
+
+
+
+// simply scrap this function if you want
+void InsetMathHull::mutateToText()
+{
+#if 0
+       // translate to latex
+       ostringstream os;
+       latex(NULL, os, false, false);
+       string str = os.str();
+
+       // insert this text
+       LyXText * lt = view_->cursor().innerText();
+       string::const_iterator cit = str.begin();
+       string::const_iterator end = str.end();
+       for (; cit != end; ++cit)
+               view_->getIntl()->getTransManager().TranslateAndInsert(*cit, lt);
+
+       // remove ourselves
+       //dispatch(LFUN_ESCAPE);
+#endif
+}
+
+
+void InsetMathHull::handleFont(LCursor & cur, docstring const & arg,
+       docstring const & font)
+{
+       // this whole function is a hack and won't work for incremental font
+       // changes...
+       recordUndo(cur);
+       if (cur.inset().asInsetMath()->name() == font)
+               cur.handleFont(to_utf8(font));
+       else {
+               cur.handleNest(createInsetMath(font));
+               cur.insert(arg);
+       }
+}
+
+
+void InsetMathHull::handleFont2(LCursor & cur, docstring const & arg)
+{
+       recordUndo(cur);
+       LyXFont font;
+       bool b;
+       bv_funcs::string2font(to_utf8(arg), font, b);
+       if (font.color() != LColor::inherit) {
+               MathAtom at = MathAtom(new InsetMathColor(true, font.color()));
+               cur.handleNest(at, 0);
+       }
+}
+
+
+void InsetMathHull::edit(LCursor & cur, bool left)
+{
+       cur.push(*this);
+       left ? idxFirst(cur) : idxLast(cur);
+       // The inset formula dimension is not necessarily the same as the
+       // one of the instant preview image, so we have to indicate to the
+       // BufferView that a metrics update is needed. 
+       cur.updateFlags(Update::Force);
+}
+
+
+docstring const InsetMathHull::editMessage() const
+{
+       return _("Math editor mode");
+}
+
+
+void InsetMathHull::revealCodes(LCursor & cur) const
+{
+       if (!cur.inMathed())
+               return;
+       odocstringstream os;
+       cur.info(os);
+       cur.message(os.str());
+/*
+       // write something to the minibuffer
+       // translate to latex
+       cur.markInsert(bv);
+       ostringstream os;
+       write(NULL, os);
+       string str = os.str();
+       cur.markErase(bv);
+       string::size_type pos = 0;
+       string res;
+       for (string::iterator it = str.begin(); it != str.end(); ++it) {
+               if (*it == '\n')
+                       res += ' ';
+               else if (*it == '\0') {
+                       res += "  -X-  ";
+                       pos = it - str.begin();
+               }
+               else
+                       res += *it;
+       }
+       if (pos > 30)
+               res = res.substr(pos - 30);
+       if (res.size() > 60)
+               res = res.substr(0, 60);
+       cur.message(res);
+*/
+}
+
+
+InsetBase::Code InsetMathHull::lyxCode() const
+{
+       return MATH_CODE;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+
+
+#if 0
+bool InsetMathHull::searchForward(BufferView * bv, string const & str,
+                                    bool, bool)
+{
+#ifdef WITH_WARNINGS
+#warning completely broken
+#endif
+       static InsetMathHull * lastformula = 0;
+       static CursorBase current = DocIterator(ibegin(nucleus()));
+       static MathArray ar;
+       static string laststr;
+
+       if (lastformula != this || laststr != str) {
+               //lyxerr << "reset lastformula to " << this << endl;
+               lastformula = this;
+               laststr = str;
+               current = ibegin(nucleus());
+               ar.clear();
+               mathed_parse_cell(ar, str);
+       } else {
+               increment(current);
+       }
+       //lyxerr << "searching '" << str << "' in " << this << ar << endl;
+
+       for (DocIterator it = current; it != iend(nucleus()); increment(it)) {
+               CursorSlice & top = it.back();
+               MathArray const & a = top.asInsetMath()->cell(top.idx_);
+               if (a.matchpart(ar, top.pos_)) {
+                       bv->cursor().setSelection(it, ar.size());
+                       current = it;
+                       top.pos_ += ar.size();
+                       bv->update();
+                       return true;
+               }
+       }
+
+       //lyxerr << "not found!" << endl;
+       lastformula = 0;
+       return false;
+}
+#endif
+
+
+void InsetMathHull::write(Buffer const &, std::ostream & os) const
+{
+       odocstringstream oss;
+       WriteStream wi(oss, false, false);
+       oss << "Formula ";
+       write(wi);
+       os << to_utf8(oss.str());
+}
+
+
+void InsetMathHull::read(Buffer const &, LyXLex & lex)
+{
+       MathAtom at;
+       mathed_parse_normal(at, lex);
+       operator=(*at->asHullInset());
+}
+
+
+int InsetMathHull::plaintext(Buffer const &, odocstream & os,
+                             OutputParams const &) const
+{
+       if (0 && display()) {
+               Dimension dim;
+               TextMetricsInfo mi;
+               metricsT(mi, dim);
+               TextPainter tpain(dim.width(), dim.height());
+               drawT(tpain, 0, dim.ascent());
+               tpain.show(os, 3);
+               // reset metrics cache to "real" values
+               //metrics();
+               return tpain.textheight();
+       } else {
+               odocstringstream oss;
+               WriteStream wi(oss, false, true);
+               wi << cell(0);
+
+               docstring const str = oss.str();
+               os << str;
+               return str.size();
+       }
+}
+
+
+int InsetMathHull::docbook(Buffer const & buf, odocstream & os,
+                           OutputParams const & runparams) const
+{
+       MathStream ms(os);
+       int res = 0;
+       docstring name;
+       if (getType() == hullSimple)
+               name = from_ascii("inlineequation");
+       else
+               name = from_ascii("informalequation");
+
+       docstring bname = name;
+       if (!label(0).empty())
+               bname += " id='" + sgml::cleanID(buf, runparams, label(0)) + "'";
+       ms << MTag(bname);
+
+       odocstringstream ls;
+       if (runparams.flavor == OutputParams::XML) {
+               ms << MTag(from_ascii("alt role='tex' "));
+               // Workaround for db2latex: db2latex always includes equations with
+               // \ensuremath{} or \begin{display}\end{display}
+               // so we strip LyX' math environment
+               WriteStream wi(ls, false, false);
+               InsetMathGrid::write(wi);
+               ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&amp;"), "<", "&lt;"));
+               ms << ETag(from_ascii("alt"));
+               ms << MTag(from_ascii("math"));
+               ms << ETag(from_ascii("alt"));
+               ms << MTag(from_ascii("math"));
+               InsetMathGrid::mathmlize(ms);
+               ms << ETag(from_ascii("math"));
+       } else {
+               ms << MTag(from_ascii("alt role='tex'"));
+               res = latex(buf, ls, runparams);
+               ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&amp;"), "<", "&lt;"));
+               ms << ETag(from_ascii("alt"));
+       }
+
+       ms << from_ascii("<graphic fileref=\"eqn/");
+       if (!label(0).empty())
+               ms << sgml::cleanID(buf, runparams, label(0));
+       else
+               ms << sgml::uniqueID(from_ascii("anon"));
+
+       if (runparams.flavor == OutputParams::XML)
+               ms << from_ascii("\"/>");
+       else
+               ms << from_ascii("\">");
+
+       ms << ETag(name);
+       return ms.line() + res;
+}
+
+
+void InsetMathHull::textString(Buffer const & buf, odocstream & os) const
+{
+       plaintext(buf, os, OutputParams(0));
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathKern.C b/src/mathed/InsetMathKern.C
deleted file mode 100644 (file)
index c5cab3e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * \file InsetMathKern.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathKern.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "dimension.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathKern::InsetMathKern()
-{
-       dim_.asc = 0;
-       dim_.des = 0;
-}
-
-
-InsetMathKern::InsetMathKern(LyXLength const & w)
-       : wid_(w)
-{
-       dim_.asc = 0;
-       dim_.des = 0;
-}
-
-
-InsetMathKern::InsetMathKern(docstring const & s)
-       : wid_(to_utf8(s))
-{
-       dim_.asc = 0;
-       dim_.des = 0;
-}
-
-
-auto_ptr<InsetBase> InsetMathKern::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathKern(*this));
-}
-
-
-bool InsetMathKern::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       int wid_pixel = wid_.inPixels(0, mathed_char_width(mi.base.font, 'M'));
-       if (wid_pixel == dim_.wid)
-               return false;
-       dim_.wid = wid_pixel;
-       dim = dim_;
-       return true;
-}
-
-
-void InsetMathKern::draw(PainterInfo &, int, int) const
-{}
-
-
-void InsetMathKern::write(WriteStream & os) const
-{
-       os << "\\kern" << from_utf8(wid_.asLatexString()) << ' ';
-}
-
-
-void InsetMathKern::normalize(NormalStream & os) const
-{
-       os << "[kern " << from_utf8(wid_.asLatexString()) << ']';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathKern.cpp b/src/mathed/InsetMathKern.cpp
new file mode 100644 (file)
index 0000000..c5cab3e
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * \file InsetMathKern.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathKern.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "dimension.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathKern::InsetMathKern()
+{
+       dim_.asc = 0;
+       dim_.des = 0;
+}
+
+
+InsetMathKern::InsetMathKern(LyXLength const & w)
+       : wid_(w)
+{
+       dim_.asc = 0;
+       dim_.des = 0;
+}
+
+
+InsetMathKern::InsetMathKern(docstring const & s)
+       : wid_(to_utf8(s))
+{
+       dim_.asc = 0;
+       dim_.des = 0;
+}
+
+
+auto_ptr<InsetBase> InsetMathKern::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathKern(*this));
+}
+
+
+bool InsetMathKern::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       int wid_pixel = wid_.inPixels(0, mathed_char_width(mi.base.font, 'M'));
+       if (wid_pixel == dim_.wid)
+               return false;
+       dim_.wid = wid_pixel;
+       dim = dim_;
+       return true;
+}
+
+
+void InsetMathKern::draw(PainterInfo &, int, int) const
+{}
+
+
+void InsetMathKern::write(WriteStream & os) const
+{
+       os << "\\kern" << from_utf8(wid_.asLatexString()) << ' ';
+}
+
+
+void InsetMathKern::normalize(NormalStream & os) const
+{
+       os << "[kern " << from_utf8(wid_.asLatexString()) << ']';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathLefteqn.C b/src/mathed/InsetMathLefteqn.C
deleted file mode 100644 (file)
index 4122d78..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * \file InsetMathLefteqn.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathLefteqn.h"
-#include "MathData.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathLefteqn::InsetMathLefteqn()
-       : InsetMathNest(1)
-{}
-
-
-auto_ptr<InsetBase> InsetMathLefteqn::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathLefteqn(*this));
-}
-
-
-bool InsetMathLefteqn::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi, dim);
-       dim.asc += 2;
-       dim.des += 2;
-       dim.wid = 4;
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathLefteqn::draw(PainterInfo & pi, int x, int y) const
-{
-       cell(0).draw(pi, x + 2, y);
-       drawMarkers(pi, x, y);
-}
-
-
-docstring InsetMathLefteqn::name() const
-{
-       return from_ascii("lefteqn");
-}
-
-
-void InsetMathLefteqn::infoize(odocstream & os) const
-{
-       os << "Lefteqn ";
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathLefteqn.cpp b/src/mathed/InsetMathLefteqn.cpp
new file mode 100644 (file)
index 0000000..4122d78
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * \file InsetMathLefteqn.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathLefteqn.h"
+#include "MathData.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathLefteqn::InsetMathLefteqn()
+       : InsetMathNest(1)
+{}
+
+
+auto_ptr<InsetBase> InsetMathLefteqn::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathLefteqn(*this));
+}
+
+
+bool InsetMathLefteqn::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi, dim);
+       dim.asc += 2;
+       dim.des += 2;
+       dim.wid = 4;
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathLefteqn::draw(PainterInfo & pi, int x, int y) const
+{
+       cell(0).draw(pi, x + 2, y);
+       drawMarkers(pi, x, y);
+}
+
+
+docstring InsetMathLefteqn::name() const
+{
+       return from_ascii("lefteqn");
+}
+
+
+void InsetMathLefteqn::infoize(odocstream & os) const
+{
+       os << "Lefteqn ";
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathLim.C b/src/mathed/InsetMathLim.C
deleted file mode 100644 (file)
index ed333d9..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * \file InsetMathLim.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathLim.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "debug.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-using std::endl;
-
-
-InsetMathLim::InsetMathLim
-       (MathArray const & f, MathArray const & x, MathArray const & x0)
-       : InsetMathNest(3)
-{
-       cell(0) = f;
-       cell(1) = x;
-       cell(2) = x0;
-}
-
-
-auto_ptr<InsetBase> InsetMathLim::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathLim(*this));
-}
-
-
-void InsetMathLim::normalize(NormalStream & os) const
-{
-       os << "[lim " << cell(0) << ' ' << cell(1) << ' ' << cell(2) << ']';
-}
-
-
-bool InsetMathLim::metrics(MetricsInfo &, Dimension &) const
-{
-       lyxerr << "should not happen" << endl;
-       return true;
-}
-
-
-void InsetMathLim::draw(PainterInfo &, int, int) const
-{
-       lyxerr << "should not happen" << endl;
-}
-
-
-void InsetMathLim::maple(MapleStream & os) const
-{
-       os << "limit(" << cell(0) << ',' << cell(1) << '=' << cell(2) << ')';
-}
-
-
-void InsetMathLim::maxima(MaximaStream & os) const
-{
-       os << "limit(" << cell(0) << ',' << cell(1) << ',' << cell(2) << ')';
-}
-
-
-void InsetMathLim::mathematica(MathematicaStream & os) const
-{
-       os << "Limit[" << cell(0) << ',' << cell(1) << "-> " << cell(2) << ']';
-}
-
-
-void InsetMathLim::mathmlize(MathStream & os) const
-{
-       os << "lim(" << cell(0) << ',' << cell(1) << ',' << cell(2) << ')';
-}
-
-
-void InsetMathLim::write(WriteStream &) const
-{
-       lyxerr << "should not happen" << endl;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathLim.cpp b/src/mathed/InsetMathLim.cpp
new file mode 100644 (file)
index 0000000..ed333d9
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * \file InsetMathLim.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathLim.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "debug.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+using std::endl;
+
+
+InsetMathLim::InsetMathLim
+       (MathArray const & f, MathArray const & x, MathArray const & x0)
+       : InsetMathNest(3)
+{
+       cell(0) = f;
+       cell(1) = x;
+       cell(2) = x0;
+}
+
+
+auto_ptr<InsetBase> InsetMathLim::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathLim(*this));
+}
+
+
+void InsetMathLim::normalize(NormalStream & os) const
+{
+       os << "[lim " << cell(0) << ' ' << cell(1) << ' ' << cell(2) << ']';
+}
+
+
+bool InsetMathLim::metrics(MetricsInfo &, Dimension &) const
+{
+       lyxerr << "should not happen" << endl;
+       return true;
+}
+
+
+void InsetMathLim::draw(PainterInfo &, int, int) const
+{
+       lyxerr << "should not happen" << endl;
+}
+
+
+void InsetMathLim::maple(MapleStream & os) const
+{
+       os << "limit(" << cell(0) << ',' << cell(1) << '=' << cell(2) << ')';
+}
+
+
+void InsetMathLim::maxima(MaximaStream & os) const
+{
+       os << "limit(" << cell(0) << ',' << cell(1) << ',' << cell(2) << ')';
+}
+
+
+void InsetMathLim::mathematica(MathematicaStream & os) const
+{
+       os << "Limit[" << cell(0) << ',' << cell(1) << "-> " << cell(2) << ']';
+}
+
+
+void InsetMathLim::mathmlize(MathStream & os) const
+{
+       os << "lim(" << cell(0) << ',' << cell(1) << ',' << cell(2) << ')';
+}
+
+
+void InsetMathLim::write(WriteStream &) const
+{
+       lyxerr << "should not happen" << endl;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathMBox.C b/src/mathed/InsetMathMBox.C
deleted file mode 100644 (file)
index 875f9f8..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * \file InsetMathMBox.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathMBox.h"
-#include "MathData.h"
-#include "MathStream.h"
-
-#include "BufferView.h"
-#include "buffer.h"
-#include "bufferparams.h"
-#include "cursor.h"
-#include "debug.h"
-#include "metricsinfo.h"
-#include "output_latex.h"
-#include "outputparams.h"
-#include "paragraph.h"
-#include "texrow.h"
-#include "TextMetrics.h"
-
-namespace lyx {
-
-//using support::odocstream;
-
-using std::auto_ptr;
-using std::endl;
-
-
-InsetMathMBox::InsetMathMBox()
-{
-       text_.paragraphs().clear();
-       text_.paragraphs().push_back(Paragraph());
-}
-
-
-InsetMathMBox::InsetMathMBox(LyXLayout_ptr const & layout)
-{
-       text_.paragraphs().clear();
-       text_.paragraphs().push_back(Paragraph());
-       text_.paragraphs().back().layout(layout);
-}
-
-
-auto_ptr<InsetBase> InsetMathMBox::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathMBox(*this));
-}
-
-
-bool InsetMathMBox::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       TextMetrics & tm = mi.base.bv->textMetrics(&text_);
-       tm.metrics(mi, dim);
-       metricsMarkers2(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathMBox::draw(PainterInfo & pi, int x, int y) const
-{
-       text_.draw(pi, x + 1, y);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathMBox::write(Buffer const & buf, WriteStream & ws) const
-{
-       if (ws.latex()) {
-               ws << "\\mbox{\n";
-               TexRow texrow;
-               OutputParams runparams(&buf.params().encoding());
-               latexParagraphs(buf, text_.paragraphs(), ws.os(), texrow, runparams);
-               ws.addlines(texrow.rows());
-               ws << "}";
-       } else {
-               ws << "\\mbox{\n";
-               std::ostringstream os;
-               text_.write(buf, os);
-               ws.os() << from_utf8(os.str());
-               ws << "}";
-       }
-}
-
-
-int InsetMathMBox::latex(Buffer const & buf, odocstream & os,
-                       OutputParams const & runparams) const
-{
-       os << "\\mbox{\n";
-       TexRow texrow;
-       latexParagraphs(buf, text_.paragraphs(), os, texrow, runparams);
-       os << "}";
-       return texrow.rows();
-}
-
-
-void InsetMathMBox::doDispatch(LCursor & cur, FuncRequest & cmd)
-{
-       text_.dispatch(cur, cmd);
-}
-
-
-LyXText * InsetMathMBox::getText(int) const
-{
-       return &text_;
-}
-
-
-void InsetMathMBox::cursorPos(BufferView const & bv,
-               CursorSlice const & sl, bool boundary, int & x, int & y) const
-{
-       x = text_.cursorX(bv, sl, boundary);
-       y = text_.cursorY(bv, sl, boundary);
-}
-
-
-void InsetMathMBox::drawSelection(PainterInfo & pi, int x, int y) const
-{
-       text_.drawSelection(pi, x, y);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathMBox.cpp b/src/mathed/InsetMathMBox.cpp
new file mode 100644 (file)
index 0000000..875f9f8
--- /dev/null
@@ -0,0 +1,133 @@
+/**
+ * \file InsetMathMBox.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathMBox.h"
+#include "MathData.h"
+#include "MathStream.h"
+
+#include "BufferView.h"
+#include "buffer.h"
+#include "bufferparams.h"
+#include "cursor.h"
+#include "debug.h"
+#include "metricsinfo.h"
+#include "output_latex.h"
+#include "outputparams.h"
+#include "paragraph.h"
+#include "texrow.h"
+#include "TextMetrics.h"
+
+namespace lyx {
+
+//using support::odocstream;
+
+using std::auto_ptr;
+using std::endl;
+
+
+InsetMathMBox::InsetMathMBox()
+{
+       text_.paragraphs().clear();
+       text_.paragraphs().push_back(Paragraph());
+}
+
+
+InsetMathMBox::InsetMathMBox(LyXLayout_ptr const & layout)
+{
+       text_.paragraphs().clear();
+       text_.paragraphs().push_back(Paragraph());
+       text_.paragraphs().back().layout(layout);
+}
+
+
+auto_ptr<InsetBase> InsetMathMBox::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathMBox(*this));
+}
+
+
+bool InsetMathMBox::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       TextMetrics & tm = mi.base.bv->textMetrics(&text_);
+       tm.metrics(mi, dim);
+       metricsMarkers2(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathMBox::draw(PainterInfo & pi, int x, int y) const
+{
+       text_.draw(pi, x + 1, y);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathMBox::write(Buffer const & buf, WriteStream & ws) const
+{
+       if (ws.latex()) {
+               ws << "\\mbox{\n";
+               TexRow texrow;
+               OutputParams runparams(&buf.params().encoding());
+               latexParagraphs(buf, text_.paragraphs(), ws.os(), texrow, runparams);
+               ws.addlines(texrow.rows());
+               ws << "}";
+       } else {
+               ws << "\\mbox{\n";
+               std::ostringstream os;
+               text_.write(buf, os);
+               ws.os() << from_utf8(os.str());
+               ws << "}";
+       }
+}
+
+
+int InsetMathMBox::latex(Buffer const & buf, odocstream & os,
+                       OutputParams const & runparams) const
+{
+       os << "\\mbox{\n";
+       TexRow texrow;
+       latexParagraphs(buf, text_.paragraphs(), os, texrow, runparams);
+       os << "}";
+       return texrow.rows();
+}
+
+
+void InsetMathMBox::doDispatch(LCursor & cur, FuncRequest & cmd)
+{
+       text_.dispatch(cur, cmd);
+}
+
+
+LyXText * InsetMathMBox::getText(int) const
+{
+       return &text_;
+}
+
+
+void InsetMathMBox::cursorPos(BufferView const & bv,
+               CursorSlice const & sl, bool boundary, int & x, int & y) const
+{
+       x = text_.cursorX(bv, sl, boundary);
+       y = text_.cursorY(bv, sl, boundary);
+}
+
+
+void InsetMathMBox::drawSelection(PainterInfo & pi, int x, int y) const
+{
+       text_.drawSelection(pi, x, y);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathMacro.C b/src/mathed/InsetMathMacro.C
deleted file mode 100644 (file)
index 27b868c..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/**
- * \file InsetMathMacro.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathMacro.h"
-#include "MathSupport.h"
-#include "MathExtern.h"
-#include "MathStream.h"
-
-#include "buffer.h"
-#include "cursor.h"
-#include "debug.h"
-#include "BufferView.h"
-#include "LaTeXFeatures.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::max;
-using std::auto_ptr;
-using std::endl;
-using std::vector;
-
-
-/// This class is the value of a macro argument, technically 
-/// a wrapper of the cells of MathMacro.
-class MathMacroArgumentValue : public InsetMathDim {
-public:
-       ///
-       MathMacroArgumentValue(MathArray const * value, docstring const & macroName) 
-               : value_(value), macroName_(macroName) {}
-       ///
-       bool metrics(MetricsInfo & mi, Dimension & dim) const;
-       ///
-       void draw(PainterInfo &, int x, int y) const;
-       
-private:
-       std::auto_ptr<InsetBase> doClone() const;
-       MathArray const * value_;
-       docstring macroName_;
-};
-
-
-auto_ptr<InsetBase> MathMacroArgumentValue::doClone() const 
-{
-       return auto_ptr<InsetBase>(new MathMacroArgumentValue(*this));
-}
-
-
-bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const 
-{
-       // unlock outer macro in arguments, and lock it again later
-       MacroTable::globalMacros().get(macroName_).unlock();
-       value_->metrics(mi, dim);
-       MacroTable::globalMacros().get(macroName_).lock();
-       metricsMarkers2(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void MathMacroArgumentValue::draw(PainterInfo & pi, int x, int y) const 
-{
-       // unlock outer macro in arguments, and lock it again later
-       MacroTable::globalMacros().get(macroName_).unlock();
-       value_->draw(pi, x, y);
-       MacroTable::globalMacros().get(macroName_).lock();
-}
-
-
-MathMacro::MathMacro(docstring const & name, int numargs)
-       : InsetMathNest(numargs), name_(name)
-{}
-
-
-auto_ptr<InsetBase> MathMacro::doClone() const
-{
-       return auto_ptr<InsetBase>(new MathMacro(*this));
-}
-
-
-docstring MathMacro::name() const
-{
-       return name_;
-}
-
-
-void MathMacro::cursorPos(BufferView const & bv,
-               CursorSlice const & sl, bool boundary, int & x, int & y) const
-{
-       // We may have 0 arguments, but InsetMathNest requires at least one.
-       if (nargs() > 0)
-               InsetMathNest::cursorPos(bv, sl, boundary, x, y);
-}
-
-
-bool MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       if (!MacroTable::globalMacros().has(name())) {
-               mathed_string_dim(mi.base.font, "Unknown: " + name(), dim);
-       } else {
-               MacroData const & macro = MacroTable::globalMacros().get(name());
-               if (macro.locked()) {
-                       mathed_string_dim(mi.base.font, "Self reference: " + name(), dim);
-                       expanded_ = MathArray();
-               } else if (editing(mi.base.bv)) {
-                       // FIXME UNICODE
-                       asArray(macro.def(), tmpl_);
-                       LyXFont font = mi.base.font;
-                       augmentFont(font, from_ascii("lyxtex"));
-                       tmpl_.metrics(mi, dim);
-                       // FIXME UNICODE
-                       dim.wid += mathed_string_width(font, name()) + 10;
-                       // FIXME UNICODE
-                       int ww = mathed_string_width(font, from_ascii("#1: "));
-                       for (idx_type i = 0; i < nargs(); ++i) {
-                               MathArray const & c = cell(i);
-                               c.metrics(mi);
-                               dim.wid  = max(dim.wid, c.width() + ww);
-                               dim.des += c.height() + 10;
-                       }
-               } else {
-                       // create MathMacroArgumentValue object pointing to the cells of the macro
-                       MacroData const & macro = MacroTable::globalMacros().get(name());
-                       vector<MathArray> values(nargs());
-                       for (size_t i = 0; i != nargs(); ++i) 
-                               values[i].insert(0, MathAtom(new MathMacroArgumentValue(&cells_[i], name())));
-                       macro.expand(values, expanded_);
-                       
-                       MacroTable::globalMacros().get(name()).lock();
-                       expanded_.metrics(mi, dim);
-                       MacroTable::globalMacros().get(name()).unlock();
-               }
-       }
-       metricsMarkers2(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void MathMacro::draw(PainterInfo & pi, int x, int y) const
-{
-       if (!MacroTable::globalMacros().has(name())) {
-               // FIXME UNICODE
-               drawStrRed(pi, x, y, "Unknown: " + name());
-       } else {
-               MacroData const & macro = MacroTable::globalMacros().get(name());
-               if (macro.locked()) {
-                       // FIXME UNICODE
-                       drawStrRed(pi, x, y, "Self reference: " + name());
-               } else if (editing(pi.base.bv)) {
-                       LyXFont font = pi.base.font;
-                       augmentFont(font, from_ascii("lyxtex"));
-                       int h = y - dim_.ascent() + 2 + tmpl_.ascent();
-                       pi.pain.text(x + 3, h, name(), font);
-                       int const w = mathed_string_width(font, name());
-                       tmpl_.draw(pi, x + w + 12, h);
-                       h += tmpl_.descent();
-                       Dimension ldim;
-                       docstring t = from_ascii("#1: ");
-                       mathed_string_dim(font, t, ldim);
-                       for (idx_type i = 0; i < nargs(); ++i) {
-                               MathArray const & c = cell(i);
-                               h += max(c.ascent(), ldim.asc) + 5;
-                               c.draw(pi, x + ldim.wid, h);
-                               char_type str[] = { '#', '1', ':', '\0' };
-                               str[1] += static_cast<char_type>(i);
-                               pi.pain.text(x + 3, h, str, font);
-                               h += max(c.descent(), ldim.des) + 5;
-                       }
-               } else {
-                       MacroTable::globalMacros().get(name()).lock();
-                       expanded_.draw(pi, x, y);
-                       MacroTable::globalMacros().get(name()).unlock();
-               }
-       }
-       drawMarkers2(pi, x, y);
-}
-
-
-void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
-{
-       // We may have 0 arguments, but InsetMathNest requires at least one.
-       if (nargs() > 0)
-               InsetMathNest::drawSelection(pi, x, y);
-}
-
-
-void MathMacro::validate(LaTeXFeatures & features) const
-{
-       if (name() == "binom" || name() == "mathcircumflex")
-               features.require(to_utf8(name()));
-}
-
-
-InsetBase * MathMacro::editXY(LCursor & cur, int x, int y)
-{
-       // We may have 0 arguments, but InsetMathNest requires at least one.
-       if (nargs() > 0) {
-               // Prevent crash due to cold coordcache
-               // FIXME: This is only a workaround, the call of
-               // InsetMathNest::editXY is correct. The correct fix would
-               // ensure that the coordcache of the arguments is valid.
-               if (!editing(&cur.bv())) {
-                       edit(cur, true);
-                       return this;
-               }
-               return InsetMathNest::editXY(cur, x, y);
-       }
-       return this;
-}
-
-
-bool MathMacro::idxFirst(LCursor & cur) const 
-{
-       cur.updateFlags(Update::Force);
-       return InsetMathNest::idxFirst(cur);
-}
-
-
-bool MathMacro::idxLast(LCursor & cur) const 
-{
-       cur.updateFlags(Update::Force);
-       return InsetMathNest::idxLast(cur);
-}
-
-
-bool MathMacro::notifyCursorLeaves(LCursor & cur)
-{
-       cur.updateFlags(Update::Force);
-       return InsetMathNest::notifyCursorLeaves(cur);
-}
-
-
-void MathMacro::maple(MapleStream & os) const
-{
-       updateExpansion();
-       lyx::maple(expanded_, os);
-}
-
-
-void MathMacro::mathmlize(MathStream & os) const
-{
-       updateExpansion();
-       lyx::mathmlize(expanded_, os);
-}
-
-
-void MathMacro::octave(OctaveStream & os) const
-{
-       updateExpansion();
-       lyx::octave(expanded_, os);
-}
-
-
-void MathMacro::updateExpansion() const
-{
-       //expanded_.substitute(*this);
-}
-
-
-void MathMacro::infoize(odocstream & os) const
-{
-       os << "Macro: " << name();
-}
-
-
-void MathMacro::infoize2(odocstream & os) const
-{
-       os << "Macro: " << name();
-
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathMacro.cpp b/src/mathed/InsetMathMacro.cpp
new file mode 100644 (file)
index 0000000..27b868c
--- /dev/null
@@ -0,0 +1,290 @@
+/**
+ * \file InsetMathMacro.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathMacro.h"
+#include "MathSupport.h"
+#include "MathExtern.h"
+#include "MathStream.h"
+
+#include "buffer.h"
+#include "cursor.h"
+#include "debug.h"
+#include "BufferView.h"
+#include "LaTeXFeatures.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::max;
+using std::auto_ptr;
+using std::endl;
+using std::vector;
+
+
+/// This class is the value of a macro argument, technically 
+/// a wrapper of the cells of MathMacro.
+class MathMacroArgumentValue : public InsetMathDim {
+public:
+       ///
+       MathMacroArgumentValue(MathArray const * value, docstring const & macroName) 
+               : value_(value), macroName_(macroName) {}
+       ///
+       bool metrics(MetricsInfo & mi, Dimension & dim) const;
+       ///
+       void draw(PainterInfo &, int x, int y) const;
+       
+private:
+       std::auto_ptr<InsetBase> doClone() const;
+       MathArray const * value_;
+       docstring macroName_;
+};
+
+
+auto_ptr<InsetBase> MathMacroArgumentValue::doClone() const 
+{
+       return auto_ptr<InsetBase>(new MathMacroArgumentValue(*this));
+}
+
+
+bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const 
+{
+       // unlock outer macro in arguments, and lock it again later
+       MacroTable::globalMacros().get(macroName_).unlock();
+       value_->metrics(mi, dim);
+       MacroTable::globalMacros().get(macroName_).lock();
+       metricsMarkers2(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void MathMacroArgumentValue::draw(PainterInfo & pi, int x, int y) const 
+{
+       // unlock outer macro in arguments, and lock it again later
+       MacroTable::globalMacros().get(macroName_).unlock();
+       value_->draw(pi, x, y);
+       MacroTable::globalMacros().get(macroName_).lock();
+}
+
+
+MathMacro::MathMacro(docstring const & name, int numargs)
+       : InsetMathNest(numargs), name_(name)
+{}
+
+
+auto_ptr<InsetBase> MathMacro::doClone() const
+{
+       return auto_ptr<InsetBase>(new MathMacro(*this));
+}
+
+
+docstring MathMacro::name() const
+{
+       return name_;
+}
+
+
+void MathMacro::cursorPos(BufferView const & bv,
+               CursorSlice const & sl, bool boundary, int & x, int & y) const
+{
+       // We may have 0 arguments, but InsetMathNest requires at least one.
+       if (nargs() > 0)
+               InsetMathNest::cursorPos(bv, sl, boundary, x, y);
+}
+
+
+bool MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (!MacroTable::globalMacros().has(name())) {
+               mathed_string_dim(mi.base.font, "Unknown: " + name(), dim);
+       } else {
+               MacroData const & macro = MacroTable::globalMacros().get(name());
+               if (macro.locked()) {
+                       mathed_string_dim(mi.base.font, "Self reference: " + name(), dim);
+                       expanded_ = MathArray();
+               } else if (editing(mi.base.bv)) {
+                       // FIXME UNICODE
+                       asArray(macro.def(), tmpl_);
+                       LyXFont font = mi.base.font;
+                       augmentFont(font, from_ascii("lyxtex"));
+                       tmpl_.metrics(mi, dim);
+                       // FIXME UNICODE
+                       dim.wid += mathed_string_width(font, name()) + 10;
+                       // FIXME UNICODE
+                       int ww = mathed_string_width(font, from_ascii("#1: "));
+                       for (idx_type i = 0; i < nargs(); ++i) {
+                               MathArray const & c = cell(i);
+                               c.metrics(mi);
+                               dim.wid  = max(dim.wid, c.width() + ww);
+                               dim.des += c.height() + 10;
+                       }
+               } else {
+                       // create MathMacroArgumentValue object pointing to the cells of the macro
+                       MacroData const & macro = MacroTable::globalMacros().get(name());
+                       vector<MathArray> values(nargs());
+                       for (size_t i = 0; i != nargs(); ++i) 
+                               values[i].insert(0, MathAtom(new MathMacroArgumentValue(&cells_[i], name())));
+                       macro.expand(values, expanded_);
+                       
+                       MacroTable::globalMacros().get(name()).lock();
+                       expanded_.metrics(mi, dim);
+                       MacroTable::globalMacros().get(name()).unlock();
+               }
+       }
+       metricsMarkers2(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void MathMacro::draw(PainterInfo & pi, int x, int y) const
+{
+       if (!MacroTable::globalMacros().has(name())) {
+               // FIXME UNICODE
+               drawStrRed(pi, x, y, "Unknown: " + name());
+       } else {
+               MacroData const & macro = MacroTable::globalMacros().get(name());
+               if (macro.locked()) {
+                       // FIXME UNICODE
+                       drawStrRed(pi, x, y, "Self reference: " + name());
+               } else if (editing(pi.base.bv)) {
+                       LyXFont font = pi.base.font;
+                       augmentFont(font, from_ascii("lyxtex"));
+                       int h = y - dim_.ascent() + 2 + tmpl_.ascent();
+                       pi.pain.text(x + 3, h, name(), font);
+                       int const w = mathed_string_width(font, name());
+                       tmpl_.draw(pi, x + w + 12, h);
+                       h += tmpl_.descent();
+                       Dimension ldim;
+                       docstring t = from_ascii("#1: ");
+                       mathed_string_dim(font, t, ldim);
+                       for (idx_type i = 0; i < nargs(); ++i) {
+                               MathArray const & c = cell(i);
+                               h += max(c.ascent(), ldim.asc) + 5;
+                               c.draw(pi, x + ldim.wid, h);
+                               char_type str[] = { '#', '1', ':', '\0' };
+                               str[1] += static_cast<char_type>(i);
+                               pi.pain.text(x + 3, h, str, font);
+                               h += max(c.descent(), ldim.des) + 5;
+                       }
+               } else {
+                       MacroTable::globalMacros().get(name()).lock();
+                       expanded_.draw(pi, x, y);
+                       MacroTable::globalMacros().get(name()).unlock();
+               }
+       }
+       drawMarkers2(pi, x, y);
+}
+
+
+void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
+{
+       // We may have 0 arguments, but InsetMathNest requires at least one.
+       if (nargs() > 0)
+               InsetMathNest::drawSelection(pi, x, y);
+}
+
+
+void MathMacro::validate(LaTeXFeatures & features) const
+{
+       if (name() == "binom" || name() == "mathcircumflex")
+               features.require(to_utf8(name()));
+}
+
+
+InsetBase * MathMacro::editXY(LCursor & cur, int x, int y)
+{
+       // We may have 0 arguments, but InsetMathNest requires at least one.
+       if (nargs() > 0) {
+               // Prevent crash due to cold coordcache
+               // FIXME: This is only a workaround, the call of
+               // InsetMathNest::editXY is correct. The correct fix would
+               // ensure that the coordcache of the arguments is valid.
+               if (!editing(&cur.bv())) {
+                       edit(cur, true);
+                       return this;
+               }
+               return InsetMathNest::editXY(cur, x, y);
+       }
+       return this;
+}
+
+
+bool MathMacro::idxFirst(LCursor & cur) const 
+{
+       cur.updateFlags(Update::Force);
+       return InsetMathNest::idxFirst(cur);
+}
+
+
+bool MathMacro::idxLast(LCursor & cur) const 
+{
+       cur.updateFlags(Update::Force);
+       return InsetMathNest::idxLast(cur);
+}
+
+
+bool MathMacro::notifyCursorLeaves(LCursor & cur)
+{
+       cur.updateFlags(Update::Force);
+       return InsetMathNest::notifyCursorLeaves(cur);
+}
+
+
+void MathMacro::maple(MapleStream & os) const
+{
+       updateExpansion();
+       lyx::maple(expanded_, os);
+}
+
+
+void MathMacro::mathmlize(MathStream & os) const
+{
+       updateExpansion();
+       lyx::mathmlize(expanded_, os);
+}
+
+
+void MathMacro::octave(OctaveStream & os) const
+{
+       updateExpansion();
+       lyx::octave(expanded_, os);
+}
+
+
+void MathMacro::updateExpansion() const
+{
+       //expanded_.substitute(*this);
+}
+
+
+void MathMacro::infoize(odocstream & os) const
+{
+       os << "Macro: " << name();
+}
+
+
+void MathMacro::infoize2(odocstream & os) const
+{
+       os << "Macro: " << name();
+
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathMakebox.C b/src/mathed/InsetMathMakebox.C
deleted file mode 100644 (file)
index fb6a0b0..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * \file InsetMathMakebox.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Ling Li
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathMakebox.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathMakebox::InsetMathMakebox()
-       : InsetMathNest(3)
-{}
-
-
-auto_ptr<InsetBase> InsetMathMakebox::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathMakebox(*this));
-}
-
-
-bool InsetMathMakebox::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       FontSetChanger dummy(mi.base, from_ascii("textnormal"));
-       w_ = mathed_char_width(mi.base.font, '[');
-       InsetMathNest::metrics(mi);
-       dim   = cell(0).dim();
-       dim  += cell(1).dim();
-       dim  += cell(2).dim();
-       dim.wid += 4 * w_ + 4;
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathMakebox::draw(PainterInfo & pi, int x, int y) const
-{
-       FontSetChanger dummy(pi.base, from_ascii("textnormal"));
-       drawMarkers(pi, x, y);
-
-       drawStrBlack(pi, x, y, from_ascii("["));
-       x += w_;
-       cell(0).draw(pi, x, y);
-       x += cell(0).width();
-       drawStrBlack(pi, x, y, from_ascii("]"));
-       x += w_ + 2;
-
-       drawStrBlack(pi, x, y, from_ascii("["));
-       x += w_;
-       cell(1).draw(pi, x, y);
-       x += cell(1).width();
-       drawStrBlack(pi, x, y, from_ascii("]"));
-       x += w_ + 2;
-
-       cell(2).draw(pi, x, y);
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathMakebox::write(WriteStream & os) const
-{
-       os << "\\makebox";
-       os << '[' << cell(0) << ']';
-       if (cell(1).size())
-               os << '[' << cell(1) << ']';
-       os << '{' << cell(2) << '}';
-}
-
-
-void InsetMathMakebox::normalize(NormalStream & os) const
-{
-       os << "[makebox " << cell(0) << ' ' << cell(1) << ' ' << cell(2) << ']';
-}
-
-
-void InsetMathMakebox::infoize(odocstream & os) const
-{
-       os << "Makebox (width: " << cell(0)
-           << " pos: " << cell(1) << ")";
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathMakebox.cpp b/src/mathed/InsetMathMakebox.cpp
new file mode 100644 (file)
index 0000000..fb6a0b0
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * \file InsetMathMakebox.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Ling Li
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathMakebox.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathMakebox::InsetMathMakebox()
+       : InsetMathNest(3)
+{}
+
+
+auto_ptr<InsetBase> InsetMathMakebox::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathMakebox(*this));
+}
+
+
+bool InsetMathMakebox::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       FontSetChanger dummy(mi.base, from_ascii("textnormal"));
+       w_ = mathed_char_width(mi.base.font, '[');
+       InsetMathNest::metrics(mi);
+       dim   = cell(0).dim();
+       dim  += cell(1).dim();
+       dim  += cell(2).dim();
+       dim.wid += 4 * w_ + 4;
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathMakebox::draw(PainterInfo & pi, int x, int y) const
+{
+       FontSetChanger dummy(pi.base, from_ascii("textnormal"));
+       drawMarkers(pi, x, y);
+
+       drawStrBlack(pi, x, y, from_ascii("["));
+       x += w_;
+       cell(0).draw(pi, x, y);
+       x += cell(0).width();
+       drawStrBlack(pi, x, y, from_ascii("]"));
+       x += w_ + 2;
+
+       drawStrBlack(pi, x, y, from_ascii("["));
+       x += w_;
+       cell(1).draw(pi, x, y);
+       x += cell(1).width();
+       drawStrBlack(pi, x, y, from_ascii("]"));
+       x += w_ + 2;
+
+       cell(2).draw(pi, x, y);
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathMakebox::write(WriteStream & os) const
+{
+       os << "\\makebox";
+       os << '[' << cell(0) << ']';
+       if (cell(1).size())
+               os << '[' << cell(1) << ']';
+       os << '{' << cell(2) << '}';
+}
+
+
+void InsetMathMakebox::normalize(NormalStream & os) const
+{
+       os << "[makebox " << cell(0) << ' ' << cell(1) << ' ' << cell(2) << ']';
+}
+
+
+void InsetMathMakebox::infoize(odocstream & os) const
+{
+       os << "Makebox (width: " << cell(0)
+           << " pos: " << cell(1) << ")";
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathMatrix.C b/src/mathed/InsetMathMatrix.C
deleted file mode 100644 (file)
index feb56cb..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * \file InsetMathMatrix.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathMatrix.h"
-#include "MathData.h"
-#include "MathStream.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathMatrix::InsetMathMatrix(InsetMathGrid const & p)
-       : InsetMathGrid(p)
-{}
-
-
-auto_ptr<InsetBase> InsetMathMatrix::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathMatrix(*this));
-}
-
-
-void InsetMathMatrix::write(WriteStream & os) const
-{
-       InsetMathGrid::write(os);
-}
-
-
-void InsetMathMatrix::normalize(NormalStream & os) const
-{
-       InsetMathGrid::normalize(os);
-}
-
-
-void InsetMathMatrix::maple(MapleStream & os) const
-{
-       os << "matrix(" << int(nrows()) << ',' << int(ncols()) << ",[";
-       for (idx_type idx = 0; idx < nargs(); ++idx) {
-               if (idx)
-                       os << ',';
-               os << cell(idx);
-       }
-       os << "])";
-}
-
-
-void InsetMathMatrix::maxima(MaximaStream & os) const
-{
-       os << "matrix(";
-       for (row_type row = 0; row < nrows(); ++row) {
-               if (row)
-                       os << ',';
-               os << '[';
-               for (col_type col = 0; col < ncols(); ++col) {
-                       if (col)
-                               os << ',';
-                       os << cell(index(row, col));
-               }
-               os << ']';
-       }
-       os << ')';
-}
-
-
-void InsetMathMatrix::mathematica(MathematicaStream & os) const
-{
-       os << '{';
-       for (row_type row = 0; row < nrows(); ++row) {
-               if (row)
-                       os << ',';
-               os << '{';
-               for (col_type col = 0; col < ncols(); ++col) {
-                       if (col)
-                               os << ',';
-                       os << cell(index(row, col));
-               }
-               os << '}';
-       }
-       os << '}';
-}
-
-
-void InsetMathMatrix::mathmlize(MathStream & os) const
-{
-       InsetMathGrid::mathmlize(os);
-}
-
-
-void InsetMathMatrix::octave(OctaveStream & os) const
-{
-       os << '[';
-       for (row_type row = 0; row < nrows(); ++row) {
-               if (row)
-                       os << ';';
-               os << '[';
-               for (col_type col = 0; col < ncols(); ++col)
-                       os << cell(index(row, col)) << ' ';
-               os << ']';
-       }
-       os << ']';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathMatrix.cpp b/src/mathed/InsetMathMatrix.cpp
new file mode 100644 (file)
index 0000000..feb56cb
--- /dev/null
@@ -0,0 +1,115 @@
+/**
+ * \file InsetMathMatrix.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathMatrix.h"
+#include "MathData.h"
+#include "MathStream.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathMatrix::InsetMathMatrix(InsetMathGrid const & p)
+       : InsetMathGrid(p)
+{}
+
+
+auto_ptr<InsetBase> InsetMathMatrix::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathMatrix(*this));
+}
+
+
+void InsetMathMatrix::write(WriteStream & os) const
+{
+       InsetMathGrid::write(os);
+}
+
+
+void InsetMathMatrix::normalize(NormalStream & os) const
+{
+       InsetMathGrid::normalize(os);
+}
+
+
+void InsetMathMatrix::maple(MapleStream & os) const
+{
+       os << "matrix(" << int(nrows()) << ',' << int(ncols()) << ",[";
+       for (idx_type idx = 0; idx < nargs(); ++idx) {
+               if (idx)
+                       os << ',';
+               os << cell(idx);
+       }
+       os << "])";
+}
+
+
+void InsetMathMatrix::maxima(MaximaStream & os) const
+{
+       os << "matrix(";
+       for (row_type row = 0; row < nrows(); ++row) {
+               if (row)
+                       os << ',';
+               os << '[';
+               for (col_type col = 0; col < ncols(); ++col) {
+                       if (col)
+                               os << ',';
+                       os << cell(index(row, col));
+               }
+               os << ']';
+       }
+       os << ')';
+}
+
+
+void InsetMathMatrix::mathematica(MathematicaStream & os) const
+{
+       os << '{';
+       for (row_type row = 0; row < nrows(); ++row) {
+               if (row)
+                       os << ',';
+               os << '{';
+               for (col_type col = 0; col < ncols(); ++col) {
+                       if (col)
+                               os << ',';
+                       os << cell(index(row, col));
+               }
+               os << '}';
+       }
+       os << '}';
+}
+
+
+void InsetMathMatrix::mathmlize(MathStream & os) const
+{
+       InsetMathGrid::mathmlize(os);
+}
+
+
+void InsetMathMatrix::octave(OctaveStream & os) const
+{
+       os << '[';
+       for (row_type row = 0; row < nrows(); ++row) {
+               if (row)
+                       os << ';';
+               os << '[';
+               for (col_type col = 0; col < ncols(); ++col)
+                       os << cell(index(row, col)) << ' ';
+               os << ']';
+       }
+       os << ']';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathNest.C b/src/mathed/InsetMathNest.C
deleted file mode 100644 (file)
index 1d18ae0..0000000
+++ /dev/null
@@ -1,1469 +0,0 @@
-/**
- * \file InsetMathNest.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathNest.h"
-
-#include "InsetMathArray.h"
-#include "InsetMathBig.h"
-#include "InsetMathBox.h"
-#include "InsetMathBrace.h"
-#include "InsetMathColor.h"
-#include "InsetMathComment.h"
-#include "MathData.h"
-#include "InsetMathDelim.h"
-#include "MathFactory.h"
-#include "InsetMathHull.h"
-#include "MathStream.h"
-#include "MathMacroArgument.h"
-//#include "InsetMathMBox.h"
-#include "MathParser.h"
-#include "InsetMathScript.h"
-#include "InsetMathSpace.h"
-#include "InsetMathSymbol.h"
-#include "MathSupport.h"
-#include "InsetMathUnknown.h"
-#include "InsetMathRef.h"
-
-#include "BufferView.h"
-#include "CutAndPaste.h"
-#include "FuncStatus.h"
-#include "LColor.h"
-#include "bufferview_funcs.h"
-#include "coordcache.h"
-#include "cursor.h"
-#include "debug.h"
-#include "dispatchresult.h"
-#include "funcrequest.h"
-#include "gettext.h"
-#include "lyxtext.h"
-#include "outputparams.h"
-#include "undo.h"
-
-#include "support/lstrings.h"
-#include "support/textutils.h"
-
-#include "frontends/Clipboard.h"
-#include "frontends/Painter.h"
-#include "frontends/Selection.h"
-
-#include "funcrequest.h"
-#include "lyxserver.h"
-#include "lyxsocket.h"
-
-#include <sstream>
-
-
-namespace lyx {
-
-using cap::copySelection;
-using cap::grabAndEraseSelection;
-using cap::cutSelection;
-using cap::replaceSelection;
-using cap::selClearOrDel;
-
-using std::endl;
-using std::string;
-using std::istringstream;
-
-
-InsetMathNest::InsetMathNest(idx_type nargs)
-       : cells_(nargs), lock_(false)
-{}
-
-
-InsetMath::idx_type InsetMathNest::nargs() const
-{
-       return cells_.size();
-}
-
-
-void InsetMathNest::cursorPos(BufferView const & bv,
-               CursorSlice const & sl, bool /*boundary*/,
-               int & x, int & y) const
-{
-// FIXME: This is a hack. Ideally, the coord cache should not store
-// absolute positions, but relative ones. This would mean to call
-// setXY() not in MathArray::draw(), but in the parent insets' draw()
-// with the correctly adjusted x,y values. But this means that we'd have
-// to touch all (math)inset's draw() methods. Right now, we'll store
-// absolute value, and make them here relative, only to make them
-// absolute again when actually drawing the cursor. What a mess.
-       BOOST_ASSERT(ptr_cmp(&sl.inset(), this));
-       MathArray const & ar = sl.cell();
-       CoordCache const & coord_cache = bv.coordCache();
-       if (!coord_cache.getArrays().has(&ar)) {
-               // this can (semi-)legally happen if we just created this cell
-               // and it never has been drawn before. So don't ASSERT.
-               //lyxerr << "no cached data for array " << &ar << endl;
-               x = 0;
-               y = 0;
-               return;
-       }
-       Point const pt = coord_cache.getArrays().xy(&ar);
-       if (!coord_cache.getInsets().has(this)) {
-               // same as above
-               //lyxerr << "no cached data for inset " << this << endl;
-               x = 0;
-               y = 0;
-               return;
-       }
-       Point const pt2 = coord_cache.getInsets().xy(this);
-       //lyxerr << "retrieving position cache for MathArray "
-       //      << pt.x_ << ' ' << pt.y_ << std::endl;
-       x = pt.x_ - pt2.x_ + ar.pos2x(sl.pos());
-       y = pt.y_ - pt2.y_;
-//     lyxerr << "pt.y_ : " << pt.y_ << " pt2_.y_ : " << pt2.y_
-//             << " asc: " << ascent() << "  des: " << descent()
-//             << " ar.asc: " << ar.ascent() << " ar.des: " << ar.descent() << endl;
-       // move cursor visually into empty cells ("blue rectangles");
-       if (ar.empty())
-               x += 2;
-}
-
-
-void InsetMathNest::metrics(MetricsInfo const & mi) const
-{
-       MetricsInfo m = mi;
-       for (idx_type i = 0, n = nargs(); i != n; ++i)
-               cell(i).metrics(m);
-}
-
-
-bool InsetMathNest::idxNext(LCursor & cur) const
-{
-       BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
-       if (cur.idx() == cur.lastidx())
-               return false;
-       ++cur.idx();
-       cur.pos() = 0;
-       return true;
-}
-
-
-bool InsetMathNest::idxRight(LCursor & cur) const
-{
-       return idxNext(cur);
-}
-
-
-bool InsetMathNest::idxPrev(LCursor & cur) const
-{
-       BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
-       if (cur.idx() == 0)
-               return false;
-       --cur.idx();
-       cur.pos() = cur.lastpos();
-       return true;
-}
-
-
-bool InsetMathNest::idxLeft(LCursor & cur) const
-{
-       return idxPrev(cur);
-}
-
-
-bool InsetMathNest::idxFirst(LCursor & cur) const
-{
-       BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
-       if (nargs() == 0)
-               return false;
-       cur.idx() = 0;
-       cur.pos() = 0;
-       return true;
-}
-
-
-bool InsetMathNest::idxLast(LCursor & cur) const
-{
-       BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
-       if (nargs() == 0)
-               return false;
-       cur.idx() = cur.lastidx();
-       cur.pos() = cur.lastpos();
-       return true;
-}
-
-
-void InsetMathNest::dump() const
-{
-       odocstringstream oss;
-       WriteStream os(oss);
-       os << "---------------------------------------------\n";
-       write(os);
-       os << "\n";
-       for (idx_type i = 0, n = nargs(); i != n; ++i)
-               os << cell(i) << "\n";
-       os << "---------------------------------------------\n";
-       lyxerr << to_utf8(oss.str());
-}
-
-
-void InsetMathNest::draw(PainterInfo & pi, int x, int y) const
-{
-#if 0
-       if (lock_)
-               pi.pain.fillRectangle(x, y - ascent(), width(), height(),
-                                       LColor::mathlockbg);
-#endif
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathNest::drawSelection(PainterInfo & pi, int x, int y) const
-{
-       BufferView & bv = *pi.base.bv;
-       // this should use the x/y values given, not the cached values
-       LCursor & cur = bv.cursor();
-       if (!cur.selection())
-               return;
-       if (!ptr_cmp(&cur.inset(), this))
-               return;
-
-       // FIXME: hack to get position cache warm
-       pi.pain.setDrawingEnabled(false);
-       draw(pi, x, y);
-       pi.pain.setDrawingEnabled(true);
-
-       CursorSlice s1 = cur.selBegin();
-       CursorSlice s2 = cur.selEnd();
-
-       //lyxerr << "InsetMathNest::drawing selection: "
-       //      << " s1: " << s1 << " s2: " << s2 << endl;
-       if (s1.idx() == s2.idx()) {
-               MathArray const & c = cell(s1.idx());
-               int x1 = c.xo(bv) + c.pos2x(s1.pos());
-               int y1 = c.yo(bv) - c.ascent();
-               int x2 = c.xo(bv) + c.pos2x(s2.pos());
-               int y2 = c.yo(bv) + c.descent();
-               pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
-       //lyxerr << "InsetMathNest::drawing selection 3: "
-       //      << " x1: " << x1 << " x2: " << x2
-       //      << " y1: " << y1 << " y2: " << y2 << endl;
-       } else {
-               for (idx_type i = 0; i < nargs(); ++i) {
-                       if (idxBetween(i, s1.idx(), s2.idx())) {
-                               MathArray const & c = cell(i);
-                               int x1 = c.xo(bv);
-                               int y1 = c.yo(bv) - c.ascent();
-                               int x2 = c.xo(bv) + c.width();
-                               int y2 = c.yo(bv) + c.descent();
-                               pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
-                       }
-               }
-       }
-}
-
-
-void InsetMathNest::validate(LaTeXFeatures & features) const
-{
-       for (idx_type i = 0; i < nargs(); ++i)
-               cell(i).validate(features);
-}
-
-
-void InsetMathNest::replace(ReplaceData & rep)
-{
-       for (idx_type i = 0; i < nargs(); ++i)
-               cell(i).replace(rep);
-}
-
-
-bool InsetMathNest::contains(MathArray const & ar) const
-{
-       for (idx_type i = 0; i < nargs(); ++i)
-               if (cell(i).contains(ar))
-                       return true;
-       return false;
-}
-
-
-bool InsetMathNest::lock() const
-{
-       return lock_;
-}
-
-
-void InsetMathNest::lock(bool l)
-{
-       lock_ = l;
-}
-
-
-bool InsetMathNest::isActive() const
-{
-       return nargs() > 0;
-}
-
-
-MathArray InsetMathNest::glue() const
-{
-       MathArray ar;
-       for (size_t i = 0; i < nargs(); ++i)
-               ar.append(cell(i));
-       return ar;
-}
-
-
-void InsetMathNest::write(WriteStream & os) const
-{
-       os << '\\' << name().c_str();
-       for (size_t i = 0; i < nargs(); ++i)
-               os << '{' << cell(i) << '}';
-       if (nargs() == 0)
-               os.pendingSpace(true);
-       if (lock_ && !os.latex()) {
-               os << "\\lyxlock";
-               os.pendingSpace(true);
-       }
-}
-
-
-void InsetMathNest::normalize(NormalStream & os) const
-{
-       os << '[' << name().c_str();
-       for (size_t i = 0; i < nargs(); ++i)
-               os << ' ' << cell(i);
-       os << ']';
-}
-
-
-int InsetMathNest::latex(Buffer const &, odocstream & os,
-                       OutputParams const & runparams) const
-{
-       WriteStream wi(os, runparams.moving_arg, true);
-       write(wi);
-       return wi.line();
-}
-
-
-bool InsetMathNest::notifyCursorLeaves(LCursor & /*cur*/)
-{
-#ifdef WITH_WARNINGS
-#warning look here
-#endif
-#if 0
-       MathArray & ar = cur.cell();
-       // remove base-only "scripts"
-       for (pos_type i = 0; i + 1 < ar.size(); ++i) {
-               InsetMathScript * p = operator[](i).nucleus()->asScriptInset();
-               if (p && p->nargs() == 1) {
-                       MathArray ar = p->nuc();
-                       erase(i);
-                       insert(i, ar);
-                       cur.adjust(i, ar.size() - 1);
-               }
-       }
-
-       // glue adjacent font insets of the same kind
-       for (pos_type i = 0; i + 1 < size(); ++i) {
-               InsetMathFont * p = operator[](i).nucleus()->asFontInset();
-               InsetMathFont const * q = operator[](i + 1)->asFontInset();
-               if (p && q && p->name() == q->name()) {
-                       p->cell(0).append(q->cell(0));
-                       erase(i + 1);
-                       cur.adjust(i, -1);
-               }
-       }
-#endif
-       return false;
-}
-
-
-void InsetMathNest::handleFont
-       (LCursor & cur, docstring const & arg, char const * const font)
-{
-       handleFont(cur, arg, from_ascii(font));
-}
-
-
-void InsetMathNest::handleFont
-       (LCursor & cur, docstring const & arg, docstring const & font)
-{
-       // this whole function is a hack and won't work for incremental font
-       // changes...
-
-       if (cur.inset().asInsetMath()->name() == font) {
-               recordUndoInset(cur, Undo::ATOMIC);
-               cur.handleFont(to_utf8(font));
-       } else {
-               recordUndo(cur, Undo::ATOMIC);
-               cur.handleNest(createInsetMath(font));
-               cur.insert(arg);
-       }
-}
-
-
-void InsetMathNest::handleFont2(LCursor & cur, docstring const & arg)
-{
-       recordUndo(cur, Undo::ATOMIC);
-       LyXFont font;
-       bool b;
-       bv_funcs::string2font(to_utf8(arg), font, b);
-       if (font.color() != LColor::inherit) {
-               MathAtom at = MathAtom(new InsetMathColor(true, font.color()));
-               cur.handleNest(at, 0);
-       }
-}
-
-
-void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
-{
-       //lyxerr << "InsetMathNest: request: " << cmd << std::endl;
-       //CursorSlice sl = cur.current();
-
-       switch (cmd.action) {
-
-       case LFUN_PASTE: {
-               recordUndo(cur);
-               cur.message(_("Paste"));
-               replaceSelection(cur);
-               docstring topaste;
-               if (cmd.argument().empty() && !theClipboard().isInternal())
-                       topaste = theClipboard().getAsText();
-               else {
-                       size_t n = 0;
-                       idocstringstream is(cmd.argument());
-                       is >> n;
-                       topaste = cap::getSelection(cur.buffer(), n);
-               }
-               cur.niceInsert(topaste);
-               cur.clearSelection(); // bug 393
-               cur.bv().switchKeyMap();
-               finishUndo();
-               break;
-       }
-
-       case LFUN_CUT:
-               recordUndo(cur);
-               cutSelection(cur, true, true);
-               cur.message(_("Cut"));
-               // Prevent stale position >= size crash
-               // Probably not necessary anymore, see eraseSelection (gb 2005-10-09)
-               cur.normalize();
-               break;
-
-       case LFUN_COPY:
-               copySelection(cur);
-               cur.message(_("Copy"));
-               break;
-
-       case LFUN_MOUSE_PRESS:
-               lfunMousePress(cur, cmd);
-               break;
-
-       case LFUN_MOUSE_MOTION:
-               lfunMouseMotion(cur, cmd);
-               break;
-
-       case LFUN_MOUSE_RELEASE:
-               lfunMouseRelease(cur, cmd);
-               break;
-
-       case LFUN_FINISHED_LEFT:
-               cur.bv().cursor() = cur;
-               break;
-
-       case LFUN_FINISHED_RIGHT:
-               ++cur.pos();
-               cur.bv().cursor() = cur;
-               break;
-
-       case LFUN_FINISHED_UP:
-               cur.bv().cursor() = cur;
-               break;
-
-       case LFUN_FINISHED_DOWN:
-               ++cur.pos();
-               cur.bv().cursor() = cur;
-               break;
-
-       case LFUN_CHAR_FORWARD:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-       case LFUN_CHAR_FORWARD_SELECT:
-               cur.selHandle(cmd.action == LFUN_CHAR_FORWARD_SELECT);
-               cur.autocorrect() = false;
-               cur.clearTargetX();
-               cur.macroModeClose();
-               if (cur.pos() != cur.lastpos() && cur.openable(cur.nextAtom())) {
-                       cur.pushLeft(*cur.nextAtom().nucleus());
-                       cur.inset().idxFirst(cur);
-               } else if (cur.posRight() || idxRight(cur)
-                       || cur.popRight() || cur.selection())
-                       ;
-               else {
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
-                       cur.undispatched();
-               }
-               break;
-
-       case LFUN_CHAR_BACKWARD:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-       case LFUN_CHAR_BACKWARD_SELECT:
-               cur.selHandle(cmd.action == LFUN_CHAR_BACKWARD_SELECT);
-               cur.autocorrect() = false;
-               cur.clearTargetX();
-               cur.macroModeClose();
-               if (cur.pos() != 0 && cur.openable(cur.prevAtom())) {
-                       cur.posLeft();
-                       cur.push(*cur.nextAtom().nucleus());
-                       cur.inset().idxLast(cur);
-               } else if (cur.posLeft() || idxLeft(cur)
-                       || cur.popLeft() || cur.selection())
-                       ;
-               else {
-                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
-                       cur.undispatched();
-               }
-               break;
-
-       case LFUN_UP:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-       case LFUN_UP_SELECT:
-               // FIXME Tried to use clearTargetX and macroModeClose, crashed on cur.up()
-               if (cur.inMacroMode()) {
-                       // Make Helge happy
-                       cur.macroModeClose();
-                       break;
-               }
-               cur.selHandle(cmd.action == LFUN_UP_SELECT);
-               if (!cur.up()) {
-                       cmd = FuncRequest(LFUN_FINISHED_UP);
-                       cur.undispatched();
-               }
-               // fixes bug 1598. Please check!
-               cur.normalize();
-               break;
-
-       case LFUN_DOWN:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-       case LFUN_DOWN_SELECT:
-               if (cur.inMacroMode()) {
-                       cur.macroModeClose();
-                       break;
-               }
-               cur.selHandle(cmd.action == LFUN_DOWN_SELECT);
-               if (!cur.down()) {
-                       cmd = FuncRequest(LFUN_FINISHED_DOWN);
-                       cur.undispatched();
-               }
-               // fixes bug 1598. Please check!
-               cur.normalize();
-               break;
-
-       case LFUN_MOUSE_DOUBLE:
-       case LFUN_MOUSE_TRIPLE:
-       case LFUN_WORD_SELECT:
-               cur.pos() = 0;
-               cur.idx() = 0;
-               cur.resetAnchor();
-               cur.selection() = true;
-               cur.pos() = cur.lastpos();
-               cur.idx() = cur.lastidx();
-               cap::saveSelection(cur);
-               break;
-
-       case LFUN_PARAGRAPH_UP:
-       case LFUN_PARAGRAPH_DOWN:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-       case LFUN_PARAGRAPH_UP_SELECT:
-       case LFUN_PARAGRAPH_DOWN_SELECT:
-               break;
-
-       case LFUN_LINE_BEGIN:
-       case LFUN_WORD_BACKWARD:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-       case LFUN_LINE_BEGIN_SELECT:
-       case LFUN_WORD_BACKWARD_SELECT:
-               cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT ||
-                               cmd.action == LFUN_LINE_BEGIN_SELECT);
-               cur.macroModeClose();
-               if (cur.pos() != 0) {
-                       cur.pos() = 0;
-               } else if (cur.col() != 0) {
-                       cur.idx() -= cur.col();
-                       cur.pos() = 0;
-               } else if (cur.idx() != 0) {
-                       cur.idx() = 0;
-                       cur.pos() = 0;
-               } else {
-                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
-                       cur.undispatched();
-               }
-               break;
-
-       case LFUN_WORD_FORWARD:
-       case LFUN_LINE_END:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-       case LFUN_WORD_FORWARD_SELECT:
-       case LFUN_LINE_END_SELECT:
-               cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT ||
-                               cmd.action == LFUN_LINE_END_SELECT);
-               cur.macroModeClose();
-               cur.clearTargetX();
-               if (cur.pos() != cur.lastpos()) {
-                       cur.pos() = cur.lastpos();
-               } else if (ncols() && (cur.col() != cur.lastcol())) {
-                       cur.idx() = cur.idx() - cur.col() + cur.lastcol();
-                       cur.pos() = cur.lastpos();
-               } else if (cur.idx() != cur.lastidx()) {
-                       cur.idx() = cur.lastidx();
-                       cur.pos() = cur.lastpos();
-               } else {
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
-                       cur.undispatched();
-               }
-               break;
-
-       case LFUN_SCREEN_UP_SELECT:
-       case LFUN_SCREEN_UP:
-               cmd = FuncRequest(LFUN_FINISHED_LEFT);
-               cur.undispatched();
-               break;
-
-       case LFUN_SCREEN_DOWN_SELECT:
-       case LFUN_SCREEN_DOWN:
-               cmd = FuncRequest(LFUN_FINISHED_RIGHT);
-               cur.undispatched();
-               break;
-
-       case LFUN_CELL_FORWARD:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-               cur.inset().idxNext(cur);
-               break;
-
-       case LFUN_CELL_BACKWARD:
-               cur.updateFlags(Update::Decoration | Update::FitCursor);
-               cur.inset().idxPrev(cur);
-               break;
-
-       case LFUN_WORD_DELETE_BACKWARD:
-       case LFUN_CHAR_DELETE_BACKWARD:
-               if (cur.pos() == 0)
-                       // May affect external cell:
-                       recordUndoInset(cur, Undo::ATOMIC);
-               else
-                       recordUndo(cur, Undo::ATOMIC);
-               // if the inset can not be removed from within, delete it
-               if (!cur.backspace()) {
-                       FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD);
-                       cur.innerText()->dispatch(cur, cmd);
-               }
-               break;
-
-       case LFUN_WORD_DELETE_FORWARD:
-       case LFUN_CHAR_DELETE_FORWARD:
-               if (cur.pos() == cur.lastpos())
-                       // May affect external cell:
-                       recordUndoInset(cur, Undo::ATOMIC);
-               else
-                       recordUndo(cur, Undo::ATOMIC);
-               // if the inset can not be removed from within, delete it
-               if (!cur.erase()) {
-                       FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD);
-                       cur.innerText()->dispatch(cur, cmd);
-               }
-               break;
-
-       case LFUN_ESCAPE:
-               if (cur.selection())
-                       cur.clearSelection();
-               else  {
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
-                       cur.undispatched();
-               }
-               break;
-
-       case LFUN_INSET_TOGGLE:
-               recordUndo(cur);
-               lock(!lock());
-               cur.popRight();
-               break;
-
-       case LFUN_SELF_INSERT:
-               if (cmd.argument().size() != 1) {
-                       recordUndo(cur);
-                       docstring const arg = cmd.argument();
-                       if (!interpretString(cur, arg))
-                               cur.insert(arg);
-                       break;
-               }
-               // Don't record undo steps if we are in macro mode and
-               // cmd.argument is the next character of the macro name.
-               // Otherwise we'll get an invalid cursor if we undo after
-               // the macro was finished and the macro is a known command,
-               // e.g. sqrt. LCursor::macroModeClose replaces in this case
-               // the InsetMathUnknown with name "frac" by an empty
-               // InsetMathFrac -> a pos value > 0 is invalid.
-               // A side effect is that an undo before the macro is finished
-               // undoes the complete macro, not only the last character.
-               if (!cur.inMacroMode())
-                       recordUndo(cur);
-
-               // spacial handling of space. If we insert an inset
-               // via macro mode, we want to put the cursor inside it
-               // if relevant. Think typing "\frac<space>".
-               if (cmd.argument()[0] == ' '
-                   && cur.inMacroMode() && cur.macroName() != "\\"
-                   && cur.macroModeClose()) {
-                       MathAtom const atom = cur.prevAtom();
-                       if (atom->asNestInset() && atom->nargs() > 0) {
-                               cur.posLeft();
-                               cur.pushLeft(*cur.nextInset());
-                       }
-               } else if (!interpretChar(cur, cmd.argument()[0])) {
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
-                       cur.undispatched();
-               }
-               break;
-
-       //case LFUN_SERVER_GET_XY:
-       //      sprintf(dispatch_buffer, "%d %d",);
-       //      break;
-
-       case LFUN_SERVER_SET_XY: {
-               lyxerr << "LFUN_SERVER_SET_XY broken!" << endl;
-               int x = 0;
-               int y = 0;
-               istringstream is(to_utf8(cmd.argument()));
-               is >> x >> y;
-               cur.setScreenPos(x, y);
-               break;
-       }
-
-       // Special casing for superscript in case of LyX handling
-       // dead-keys:
-       case LFUN_ACCENT_CIRCUMFLEX:
-               if (cmd.argument().empty()) {
-                       // do superscript if LyX handles
-                       // deadkeys
-                       recordUndo(cur, Undo::ATOMIC);
-                       script(cur, true, grabAndEraseSelection(cur));
-               }
-               break;
-
-       case LFUN_ACCENT_UMLAUT:
-       case LFUN_ACCENT_ACUTE:
-       case LFUN_ACCENT_GRAVE:
-       case LFUN_ACCENT_BREVE:
-       case LFUN_ACCENT_DOT:
-       case LFUN_ACCENT_MACRON:
-       case LFUN_ACCENT_CARON:
-       case LFUN_ACCENT_TILDE:
-       case LFUN_ACCENT_CEDILLA:
-       case LFUN_ACCENT_CIRCLE:
-       case LFUN_ACCENT_UNDERDOT:
-       case LFUN_ACCENT_TIE:
-       case LFUN_ACCENT_OGONEK:
-       case LFUN_ACCENT_HUNGARIAN_UMLAUT:
-               break;
-
-       //  Math fonts
-       case LFUN_FONT_FREE_APPLY:
-       case LFUN_FONT_FREE_UPDATE:
-               handleFont2(cur, cmd.argument());
-               break;
-
-       case LFUN_FONT_BOLD:
-               if (currentMode() == TEXT_MODE)
-                       handleFont(cur, cmd.argument(), "textbf");
-               else
-                       handleFont(cur, cmd.argument(), "mathbf");
-               break;
-       case LFUN_FONT_SANS:
-               if (currentMode() == TEXT_MODE)
-                       handleFont(cur, cmd.argument(), "textsf");
-               else
-                       handleFont(cur, cmd.argument(), "mathsf");
-               break;
-       case LFUN_FONT_EMPH:
-               if (currentMode() == TEXT_MODE)
-                       handleFont(cur, cmd.argument(), "emph");
-               else
-                       handleFont(cur, cmd.argument(), "mathcal");
-               break;
-       case LFUN_FONT_ROMAN:
-               if (currentMode() == TEXT_MODE)
-                       handleFont(cur, cmd.argument(), "textrm");
-               else
-                       handleFont(cur, cmd.argument(), "mathrm");
-               break;
-       case LFUN_FONT_CODE:
-               if (currentMode() == TEXT_MODE)
-                       handleFont(cur, cmd.argument(), "texttt");
-               else
-                       handleFont(cur, cmd.argument(), "mathtt");
-               break;
-       case LFUN_FONT_FRAK:
-               handleFont(cur, cmd.argument(), "mathfrak");
-               break;
-       case LFUN_FONT_ITAL:
-               if (currentMode() == TEXT_MODE)
-                       handleFont(cur, cmd.argument(), "textit");
-               else
-                       handleFont(cur, cmd.argument(), "mathit");
-               break;
-       case LFUN_FONT_NOUN:
-               if (currentMode() == TEXT_MODE)
-                       // FIXME: should be "noun"
-                       handleFont(cur, cmd.argument(), "textsc");
-               else
-                       handleFont(cur, cmd.argument(), "mathbb");
-               break;
-       /*
-       case LFUN_FONT_FREE_APPLY:
-               handleFont(cur, cmd.argument(), "textrm");
-               break;
-       */
-       case LFUN_FONT_DEFAULT:
-               handleFont(cur, cmd.argument(), "textnormal");
-               break;
-
-       case LFUN_MATH_MODE: {
-#if 1
-               // ignore math-mode on when already in math mode
-               if (currentMode() == InsetBase::MATH_MODE && cmd.argument() == "on")
-                       break;
-               cur.macroModeClose();
-               docstring const save_selection = grabAndEraseSelection(cur);
-               selClearOrDel(cur);
-               //cur.plainInsert(MathAtom(new InsetMathMBox(cur.bv())));
-               cur.plainInsert(MathAtom(new InsetMathBox(from_ascii("mbox"))));
-               cur.posLeft();
-               cur.pushLeft(*cur.nextInset());
-               cur.niceInsert(save_selection);
-#else
-               if (currentMode() == InsetBase::TEXT_MODE) {
-                       cur.niceInsert(MathAtom(new InsetMathHull("simple")));
-                       cur.message(_("create new math text environment ($...$)"));
-               } else {
-                       handleFont(cur, cmd.argument(), "textrm");
-                       cur.message(_("entered math text mode (textrm)"));
-               }
-#endif
-               break;
-       }
-
-       case LFUN_MATH_SIZE:
-#if 0
-               recordUndo(cur);
-               cur.setSize(arg);
-#endif
-               break;
-
-       case LFUN_MATH_MATRIX: {
-               recordUndo(cur, Undo::ATOMIC);
-               unsigned int m = 1;
-               unsigned int n = 1;
-               docstring v_align;
-               docstring h_align;
-               idocstringstream is(cmd.argument());
-               is >> m >> n >> v_align >> h_align;
-               if (m < 1)
-                       m = 1;
-               if (n < 1)
-                       n = 1;
-               v_align += 'c';
-               cur.niceInsert(
-                       MathAtom(new InsetMathArray(from_ascii("array"), m, n, (char)v_align[0], h_align)));
-               break;
-       }
-
-       case LFUN_MATH_DELIM: {
-               docstring ls;
-               docstring rs = support::split(cmd.argument(), ls, ' ');
-               // Reasonable default values
-               if (ls.empty())
-                       ls = '(';
-               if (rs.empty())
-                       rs = ')';
-               recordUndo(cur, Undo::ATOMIC);
-               cur.handleNest(MathAtom(new InsetMathDelim(ls, rs)));
-               break;
-       }
-
-       case LFUN_MATH_BIGDELIM: {
-               docstring const lname  = from_utf8(cmd.getArg(0));
-               docstring const ldelim = from_utf8(cmd.getArg(1));
-               docstring const rname  = from_utf8(cmd.getArg(2));
-               docstring const rdelim = from_utf8(cmd.getArg(3));
-               latexkeys const * l = in_word_set(lname);
-               bool const have_l = l && l->inset == "big" &&
-                                   InsetMathBig::isBigInsetDelim(ldelim);
-               l = in_word_set(rname);
-               bool const have_r = l && l->inset == "big" &&
-                                   InsetMathBig::isBigInsetDelim(rdelim);
-               // We mimic LFUN_MATH_DELIM in case we have an empty left
-               // or right delimiter.
-               if (have_l || have_r) {
-                       recordUndo(cur, Undo::ATOMIC);
-                       docstring const selection = grabAndEraseSelection(cur);
-                       selClearOrDel(cur);
-                       if (have_l)
-                               cur.insert(MathAtom(new InsetMathBig(lname,
-                                                               ldelim)));
-                       cur.niceInsert(selection);
-                       if (have_r)
-                               cur.insert(MathAtom(new InsetMathBig(rname,
-                                                               rdelim)));
-               }
-               // Don't call cur.undispatched() if we did nothing, this would
-               // lead to infinite recursion via LyXText::dispatch().
-               break;
-       }
-
-       case LFUN_SPACE_INSERT:
-       case LFUN_MATH_SPACE:
-               recordUndo(cur, Undo::ATOMIC);
-               cur.insert(MathAtom(new InsetMathSpace(from_ascii(","))));
-               break;
-
-       case LFUN_ERT_INSERT:
-               // interpret this as if a backslash was typed
-               recordUndo(cur, Undo::ATOMIC);
-               interpretChar(cur, '\\');
-               break;
-
-       case LFUN_MATH_SUBSCRIPT:
-               // interpret this as if a _ was typed
-               recordUndo(cur, Undo::ATOMIC);
-               interpretChar(cur, '_');
-               break;
-
-       case LFUN_MATH_SUPERSCRIPT:
-               // interpret this as if a ^ was typed
-               recordUndo(cur, Undo::ATOMIC);
-               interpretChar(cur, '^');
-               break;
-
-       case LFUN_QUOTE_INSERT:
-               // interpret this as if a straight " was typed
-               recordUndo(cur, Undo::ATOMIC);
-               interpretChar(cur, '\"');
-               break;
-
-// FIXME: We probably should swap parts of "math-insert" and "self-insert"
-// handling such that "self-insert" works on "arbitrary stuff" too, and
-// math-insert only handles special math things like "matrix".
-       case LFUN_MATH_INSERT: {
-               recordUndo(cur, Undo::ATOMIC);
-               if (cmd.argument() == "^" || cmd.argument() == "_") {
-                       interpretChar(cur, cmd.argument()[0]);
-               } else
-                       cur.niceInsert(cmd.argument());
-               break;
-               }
-
-       case LFUN_DIALOG_SHOW_NEW_INSET: {
-               docstring const & name = cmd.argument();
-               string data;
-               if (name == "ref") {
-                       RefInset tmp(name);
-                       data = tmp.createDialogStr(to_utf8(name));
-               }
-               cur.bv().showInsetDialog(to_utf8(name), data, 0);
-               break;
-       }
-
-       case LFUN_INSET_INSERT: {
-               MathArray ar;
-               if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
-                       recordUndo(cur);
-                       cur.insert(ar);
-               } else
-                       cur.undispatched();
-               break;
-       }
-
-       default:
-               InsetMathDim::doDispatch(cur, cmd);
-               break;
-       }
-}
-
-
-bool InsetMathNest::getStatus(LCursor & cur, FuncRequest const & cmd,
-               FuncStatus & flag) const
-{
-       // the font related toggles
-       //string tc = "mathnormal";
-       bool ret = true;
-       string const arg = to_utf8(cmd.argument());
-       switch (cmd.action) {
-       case LFUN_TABULAR_FEATURE:
-               flag.enabled(false);
-               break;
-#if 0
-       case LFUN_TABULAR_FEATURE:
-               // FIXME: check temporarily disabled
-               // valign code
-               char align = mathcursor::valign();
-               if (align == '\0') {
-                       enable = false;
-                       break;
-               }
-               if (cmd.argument().empty()) {
-                       flag.clear();
-                       break;
-               }
-               if (!contains("tcb", cmd.argument()[0])) {
-                       enable = false;
-                       break;
-               }
-               flag.setOnOff(cmd.argument()[0] == align);
-               break;
-#endif
-       /// We have to handle them since 1.4 blocks all unhandled actions
-       case LFUN_FONT_ITAL:
-       case LFUN_FONT_BOLD:
-       case LFUN_FONT_SANS:
-       case LFUN_FONT_EMPH:
-       case LFUN_FONT_CODE:
-       case LFUN_FONT_NOUN:
-       case LFUN_FONT_ROMAN:
-       case LFUN_FONT_DEFAULT:
-               flag.enabled(true);
-               break;
-       case LFUN_MATH_MUTATE:
-               //flag.setOnOff(mathcursor::formula()->hullType() == to_utf8(cmd.argument()));
-               flag.setOnOff(false);
-               break;
-
-       // we just need to be in math mode to enable that
-       case LFUN_MATH_SIZE:
-       case LFUN_MATH_SPACE:
-       case LFUN_MATH_LIMITS:
-       case LFUN_MATH_NONUMBER:
-       case LFUN_MATH_NUMBER:
-       case LFUN_MATH_EXTERN:
-               flag.enabled(true);
-               break;
-
-       case LFUN_FONT_FRAK:
-               flag.enabled(currentMode() != TEXT_MODE);
-               break;
-
-       case LFUN_MATH_INSERT: {
-               bool const textarg =
-                       arg == "\\textbf"   || arg == "\\textsf" ||
-                       arg == "\\textrm"   || arg == "\\textmd" ||
-                       arg == "\\textit"   || arg == "\\textsc" ||
-                       arg == "\\textsl"   || arg == "\\textup" ||
-                       arg == "\\texttt"   || arg == "\\textbb" ||
-                       arg == "\\textnormal";
-               flag.enabled(currentMode() != TEXT_MODE || textarg);
-               break;
-       }
-
-       case LFUN_MATH_MATRIX:
-               flag.enabled(currentMode() == MATH_MODE);
-               break;
-
-       case LFUN_INSET_INSERT: {
-               // Don't test createMathInset_fromDialogStr(), since
-               // getStatus is not called with a valid reference and the
-               // dialog would not be applyable.
-               string const name = cmd.getArg(0);
-               flag.enabled(name == "ref");
-               break;
-       }
-
-       case LFUN_MATH_DELIM:
-       case LFUN_MATH_BIGDELIM:
-               // Don't do this with multi-cell selections
-               flag.enabled(cur.selBegin().idx() == cur.selEnd().idx());
-               break;
-
-       default:
-               ret = false;
-               break;
-       }
-       return ret;
-}
-
-
-void InsetMathNest::edit(LCursor & cur, bool left)
-{
-       cur.push(*this);
-       cur.idx() = left ? 0 : cur.lastidx();
-       cur.pos() = left ? 0 : cur.lastpos();
-       cur.resetAnchor();
-       //lyxerr << "InsetMathNest::edit, cur:\n" << cur << endl;
-}
-
-
-InsetBase * InsetMathNest::editXY(LCursor & cur, int x, int y)
-{
-       int idx_min = 0;
-       int dist_min = 1000000;
-       for (idx_type i = 0, n = nargs(); i != n; ++i) {
-               int const d = cell(i).dist(cur.bv(), x, y);
-               if (d < dist_min) {
-                       dist_min = d;
-                       idx_min = i;
-               }
-       }
-       MathArray & ar = cell(idx_min);
-       cur.push(*this);
-       cur.idx() = idx_min;
-       cur.pos() = ar.x2pos(x - ar.xo(cur.bv()));
-
-       //lyxerr << "found cell : " << idx_min << " pos: " << cur.pos() << endl;
-       if (dist_min == 0) {
-               // hit inside cell
-               for (pos_type i = 0, n = ar.size(); i < n; ++i)
-                       if (ar[i]->covers(cur.bv(), x, y))
-                               return ar[i].nucleus()->editXY(cur, x, y);
-       }
-       return this;
-}
-
-
-void InsetMathNest::lfunMousePress(LCursor & cur, FuncRequest & cmd)
-{
-       //lyxerr << "## lfunMousePress: buttons: " << cmd.button() << endl;
-       BufferView & bv = cur.bv();
-       if (cmd.button() == mouse_button::button1) {
-               //lyxerr << "## lfunMousePress: setting cursor to: " << cur << endl;
-               bv.mouseSetCursor(cur);
-               // Update the cursor update flags as needed:
-               //
-               // Update::Decoration: tells to update the decoration (visual box
-               //                     corners that define the inset)/
-               // Update::FitCursor: adjust the screen to the cursor position if
-               //                    needed
-               // cur.result().update(): don't overwrite previously set flags.
-               cur.updateFlags(Update::Decoration | Update::FitCursor | cur.result().update());
-       } else if (cmd.button() == mouse_button::button2) {
-               MathArray ar;
-               if (cap::selection()) {
-                       // See comment in LyXText::dispatch why we do this
-                       cap::copySelectionToStack();
-                       cmd = FuncRequest(LFUN_PASTE, "0");
-                       doDispatch(cur, cmd);
-               } else
-                       asArray(theSelection().get(), ar);
-
-               cur.insert(ar);
-               bv.mouseSetCursor(cur);
-       }
-}
-
-
-void InsetMathNest::lfunMouseMotion(LCursor & cur, FuncRequest & cmd)
-{
-       // only select with button 1
-       if (cmd.button() == mouse_button::button1) {
-               LCursor & bvcur = cur.bv().cursor();
-               if (bvcur.anchor_.hasPart(cur)) {
-                       //lyxerr << "## lfunMouseMotion: cursor: " << cur << endl;
-                       bvcur.setCursor(cur);
-                       bvcur.selection() = true;
-                       //lyxerr << "MOTION " << bvcur << endl;
-               } else
-                       cur.undispatched();
-       }
-}
-
-
-void InsetMathNest::lfunMouseRelease(LCursor & cur, FuncRequest & cmd)
-{
-       //lyxerr << "## lfunMouseRelease: buttons: " << cmd.button() << endl;
-
-       if (cmd.button() == mouse_button::button1) {
-               if (!cur.selection())
-                       cur.noUpdate();
-               else {
-                       LCursor & bvcur = cur.bv().cursor();
-                       bvcur.selection() = true;
-                       cap::saveSelection(bvcur);
-               }
-               return;
-       }
-
-       cur.undispatched();
-}
-
-
-bool InsetMathNest::interpretChar(LCursor & cur, char_type c)
-{
-       //lyxerr << "interpret 2: '" << c << "'" << endl;
-       docstring save_selection;
-       if (c == '^' || c == '_')
-               save_selection = grabAndEraseSelection(cur);
-
-       cur.clearTargetX();
-
-       // handle macroMode
-       if (cur.inMacroMode()) {
-               docstring name = cur.macroName();
-
-               /// are we currently typing '#1' or '#2' or...?
-               if (name == "\\#") {
-                       cur.backspace();
-                       int n = c - '0';
-                       if (n >= 1 && n <= 9)
-                               cur.insert(new MathMacroArgument(n));
-                       return true;
-               }
-
-               if (isAlphaASCII(c)) {
-                       cur.activeMacro()->setName(name + docstring(1, c));
-                       return true;
-               }
-
-               // handle 'special char' macros
-               if (name == "\\") {
-                       // remove the '\\'
-                       if (c == '\\') {
-                               cur.backspace();
-                               if (currentMode() == InsetMath::TEXT_MODE)
-                                       cur.niceInsert(createInsetMath("textbackslash"));
-                               else
-                                       cur.niceInsert(createInsetMath("backslash"));
-                       } else if (c == '{') {
-                               cur.backspace();
-                               cur.niceInsert(MathAtom(new InsetMathBrace));
-                       } else if (c == '%') {
-                               cur.backspace();
-                               cur.niceInsert(MathAtom(new InsetMathComment));
-                       } else if (c == '#') {
-                               BOOST_ASSERT(cur.activeMacro());
-                               cur.activeMacro()->setName(name + docstring(1, c));
-                       } else {
-                               cur.backspace();
-                               cur.niceInsert(createInsetMath(docstring(1, c)));
-                       }
-                       return true;
-               }
-
-               // One character big delimiters. The others are handled in
-               // interpretString().
-               latexkeys const * l = in_word_set(name.substr(1));
-               if (name[0] == '\\' && l && l->inset == "big") {
-                       docstring delim;
-                       switch (c) {
-                       case '{':
-                               delim = from_ascii("\\{");
-                               break;
-                       case '}':
-                               delim = from_ascii("\\}");
-                               break;
-                       default:
-                               delim = docstring(1, c);
-                               break;
-                       }
-                       if (InsetMathBig::isBigInsetDelim(delim)) {
-                               // name + delim ared a valid InsetMathBig.
-                               // We can't use cur.macroModeClose() because
-                               // it does not handle delim.
-                               InsetMathUnknown * p = cur.activeMacro();
-                               p->finalize();
-                               --cur.pos();
-                               cur.cell().erase(cur.pos());
-                               cur.plainInsert(MathAtom(
-                                       new InsetMathBig(name.substr(1), delim)));
-                               return true;
-                       }
-               }
-
-               // leave macro mode and try again if necessary
-               cur.macroModeClose();
-               if (c == '{')
-                       cur.niceInsert(MathAtom(new InsetMathBrace));
-               else if (c != ' ')
-                       interpretChar(cur, c);
-               return true;
-       }
-
-       // This is annoying as one has to press <space> far too often.
-       // Disable it.
-
-#if 0
-               // leave autocorrect mode if necessary
-               if (autocorrect() && c == ' ') {
-                       autocorrect() = false;
-                       return true;
-               }
-#endif
-
-       // just clear selection on pressing the space bar
-       if (cur.selection() && c == ' ') {
-               cur.selection() = false;
-               return true;
-       }
-
-       selClearOrDel(cur);
-
-       if (c == '\\') {
-               //lyxerr << "starting with macro" << endl;
-               cur.insert(MathAtom(new InsetMathUnknown(from_ascii("\\"), false)));
-               return true;
-       }
-
-       if (c == '\n') {
-               if (currentMode() == InsetMath::TEXT_MODE)
-                       cur.insert(c);
-               return true;
-       }
-
-       if (c == ' ') {
-               if (currentMode() == InsetMath::TEXT_MODE) {
-                       // insert spaces in text mode,
-                       // but suppress direct insertion of two spaces in a row
-                       // the still allows typing  '<space>a<space>' and deleting the 'a', but
-                       // it is better than nothing...
-                       if (!cur.pos() != 0 || cur.prevAtom()->getChar() != ' ') {
-                               cur.insert(c);
-                               // FIXME: we have to enable full redraw here because of the
-                               // visual box corners that define the inset. If we know for
-                               // sure that we stay within the same cell we can optimize for
-                               // that using:
-                               //cur.updateFlags(Update::SinglePar | Update::FitCursor);
-                       }
-                       return true;
-               }
-               if (cur.pos() != 0 && cur.prevAtom()->asSpaceInset()) {
-                       cur.prevAtom().nucleus()->asSpaceInset()->incSpace();
-                       // FIXME: we have to enable full redraw here because of the
-                       // visual box corners that define the inset. If we know for
-                       // sure that we stay within the same cell we can optimize for
-                       // that using:
-                       //cur.updateFlags(Update::SinglePar | Update::FitCursor);
-                       return true;
-               }
-
-               if (cur.popRight()) {
-                       // FIXME: we have to enable full redraw here because of the
-                       // visual box corners that define the inset. If we know for
-                       // sure that we stay within the same cell we can optimize for
-                       // that using:
-                       //cur.updateFlags(Update::FitCursor);
-                       return true;
-               }
-
-               // if we are at the very end, leave the formula
-               return cur.pos() != cur.lastpos();
-       }
-
-       // These shouldn't work in text mode:
-       if (currentMode() != InsetMath::TEXT_MODE) {
-               if (c == '_') {
-                       script(cur, false, save_selection);
-                       return true;
-               }
-               if (c == '^') {
-                       script(cur, true, save_selection);
-                       return true;
-               }
-               if (c == '~') {
-                       cur.niceInsert(createInsetMath("sim"));
-                       return true;
-               }
-       }
-
-       if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' ||
-           c == '%' || c == '_' || c == '^') {
-               cur.niceInsert(createInsetMath(docstring(1, c)));
-               return true;
-       }
-
-
-       // try auto-correction
-       //if (autocorrect() && hasPrevAtom() && math_autocorrect(prevAtom(), c))
-       //      return true;
-
-       // no special circumstances, so insert the character without any fuss
-       cur.insert(c);
-       cur.autocorrect() = true;
-       return true;
-}
-
-
-bool InsetMathNest::interpretString(LCursor & cur, docstring const & str)
-{
-       // Create a InsetMathBig from cur.cell()[cur.pos() - 1] and t if
-       // possible
-       if (!cur.empty() && cur.pos() > 0 &&
-           cur.cell()[cur.pos() - 1]->asUnknownInset()) {
-               if (InsetMathBig::isBigInsetDelim(str)) {
-                       docstring prev = asString(cur.cell()[cur.pos() - 1]);
-                       if (prev[0] == '\\') {
-                               prev = prev.substr(1);
-                               latexkeys const * l = in_word_set(prev);
-                               if (l && l->inset == "big") {
-                                       cur.cell()[cur.pos() - 1] =
-                                               MathAtom(new InsetMathBig(prev, str));
-                                       return true;
-                               }
-                       }
-               }
-       }
-       return false;
-}
-
-
-bool InsetMathNest::script(LCursor & cur, bool up, 
-               docstring const & save_selection)
-{
-       // Hack to get \^ and \_ working
-       //lyxerr << "handling script: up: " << up << endl;
-       if (cur.inMacroMode() && cur.macroName() == "\\") {
-               if (up)
-                       cur.niceInsert(createInsetMath("mathcircumflex"));
-               else
-                       interpretChar(cur, '_');
-               return true;
-       }
-
-       cur.macroModeClose();
-       if (asScriptInset() && cur.idx() == 0) {
-               // we are in a nucleus of a script inset, move to _our_ script
-               InsetMathScript * inset = asScriptInset();
-               //lyxerr << " going to cell " << inset->idxOfScript(up) << endl;
-               inset->ensure(up);
-               cur.idx() = inset->idxOfScript(up);
-               cur.pos() = 0;
-       } else if (cur.pos() != 0 && cur.prevAtom()->asScriptInset()) {
-               --cur.pos();
-               InsetMathScript * inset = cur.nextAtom().nucleus()->asScriptInset();
-               cur.push(*inset);
-               inset->ensure(up);
-               cur.idx() = inset->idxOfScript(up);
-               cur.pos() = cur.lastpos();
-       } else {
-               // convert the thing to our left to a scriptinset or create a new
-               // one if in the very first position of the array
-               if (cur.pos() == 0) {
-                       //lyxerr << "new scriptinset" << endl;
-                       cur.insert(new InsetMathScript(up));
-               } else {
-                       //lyxerr << "converting prev atom " << endl;
-                       cur.prevAtom() = MathAtom(new InsetMathScript(cur.prevAtom(), up));
-               }
-               --cur.pos();
-               InsetMathScript * inset = cur.nextAtom().nucleus()->asScriptInset();
-               // See comment in MathParser.cpp for special handling of {}-bases
-
-               cur.push(*inset);
-               cur.idx() = 1;
-               cur.pos() = 0;
-       }
-       //lyxerr << "inserting selection 1:\n" << save_selection << endl;
-       cur.niceInsert(save_selection);
-       cur.resetAnchor();
-       //lyxerr << "inserting selection 2:\n" << save_selection << endl;
-       return true;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp
new file mode 100644 (file)
index 0000000..1d18ae0
--- /dev/null
@@ -0,0 +1,1469 @@
+/**
+ * \file InsetMathNest.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathNest.h"
+
+#include "InsetMathArray.h"
+#include "InsetMathBig.h"
+#include "InsetMathBox.h"
+#include "InsetMathBrace.h"
+#include "InsetMathColor.h"
+#include "InsetMathComment.h"
+#include "MathData.h"
+#include "InsetMathDelim.h"
+#include "MathFactory.h"
+#include "InsetMathHull.h"
+#include "MathStream.h"
+#include "MathMacroArgument.h"
+//#include "InsetMathMBox.h"
+#include "MathParser.h"
+#include "InsetMathScript.h"
+#include "InsetMathSpace.h"
+#include "InsetMathSymbol.h"
+#include "MathSupport.h"
+#include "InsetMathUnknown.h"
+#include "InsetMathRef.h"
+
+#include "BufferView.h"
+#include "CutAndPaste.h"
+#include "FuncStatus.h"
+#include "LColor.h"
+#include "bufferview_funcs.h"
+#include "coordcache.h"
+#include "cursor.h"
+#include "debug.h"
+#include "dispatchresult.h"
+#include "funcrequest.h"
+#include "gettext.h"
+#include "lyxtext.h"
+#include "outputparams.h"
+#include "undo.h"
+
+#include "support/lstrings.h"
+#include "support/textutils.h"
+
+#include "frontends/Clipboard.h"
+#include "frontends/Painter.h"
+#include "frontends/Selection.h"
+
+#include "funcrequest.h"
+#include "lyxserver.h"
+#include "lyxsocket.h"
+
+#include <sstream>
+
+
+namespace lyx {
+
+using cap::copySelection;
+using cap::grabAndEraseSelection;
+using cap::cutSelection;
+using cap::replaceSelection;
+using cap::selClearOrDel;
+
+using std::endl;
+using std::string;
+using std::istringstream;
+
+
+InsetMathNest::InsetMathNest(idx_type nargs)
+       : cells_(nargs), lock_(false)
+{}
+
+
+InsetMath::idx_type InsetMathNest::nargs() const
+{
+       return cells_.size();
+}
+
+
+void InsetMathNest::cursorPos(BufferView const & bv,
+               CursorSlice const & sl, bool /*boundary*/,
+               int & x, int & y) const
+{
+// FIXME: This is a hack. Ideally, the coord cache should not store
+// absolute positions, but relative ones. This would mean to call
+// setXY() not in MathArray::draw(), but in the parent insets' draw()
+// with the correctly adjusted x,y values. But this means that we'd have
+// to touch all (math)inset's draw() methods. Right now, we'll store
+// absolute value, and make them here relative, only to make them
+// absolute again when actually drawing the cursor. What a mess.
+       BOOST_ASSERT(ptr_cmp(&sl.inset(), this));
+       MathArray const & ar = sl.cell();
+       CoordCache const & coord_cache = bv.coordCache();
+       if (!coord_cache.getArrays().has(&ar)) {
+               // this can (semi-)legally happen if we just created this cell
+               // and it never has been drawn before. So don't ASSERT.
+               //lyxerr << "no cached data for array " << &ar << endl;
+               x = 0;
+               y = 0;
+               return;
+       }
+       Point const pt = coord_cache.getArrays().xy(&ar);
+       if (!coord_cache.getInsets().has(this)) {
+               // same as above
+               //lyxerr << "no cached data for inset " << this << endl;
+               x = 0;
+               y = 0;
+               return;
+       }
+       Point const pt2 = coord_cache.getInsets().xy(this);
+       //lyxerr << "retrieving position cache for MathArray "
+       //      << pt.x_ << ' ' << pt.y_ << std::endl;
+       x = pt.x_ - pt2.x_ + ar.pos2x(sl.pos());
+       y = pt.y_ - pt2.y_;
+//     lyxerr << "pt.y_ : " << pt.y_ << " pt2_.y_ : " << pt2.y_
+//             << " asc: " << ascent() << "  des: " << descent()
+//             << " ar.asc: " << ar.ascent() << " ar.des: " << ar.descent() << endl;
+       // move cursor visually into empty cells ("blue rectangles");
+       if (ar.empty())
+               x += 2;
+}
+
+
+void InsetMathNest::metrics(MetricsInfo const & mi) const
+{
+       MetricsInfo m = mi;
+       for (idx_type i = 0, n = nargs(); i != n; ++i)
+               cell(i).metrics(m);
+}
+
+
+bool InsetMathNest::idxNext(LCursor & cur) const
+{
+       BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
+       if (cur.idx() == cur.lastidx())
+               return false;
+       ++cur.idx();
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathNest::idxRight(LCursor & cur) const
+{
+       return idxNext(cur);
+}
+
+
+bool InsetMathNest::idxPrev(LCursor & cur) const
+{
+       BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
+       if (cur.idx() == 0)
+               return false;
+       --cur.idx();
+       cur.pos() = cur.lastpos();
+       return true;
+}
+
+
+bool InsetMathNest::idxLeft(LCursor & cur) const
+{
+       return idxPrev(cur);
+}
+
+
+bool InsetMathNest::idxFirst(LCursor & cur) const
+{
+       BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
+       if (nargs() == 0)
+               return false;
+       cur.idx() = 0;
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathNest::idxLast(LCursor & cur) const
+{
+       BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
+       if (nargs() == 0)
+               return false;
+       cur.idx() = cur.lastidx();
+       cur.pos() = cur.lastpos();
+       return true;
+}
+
+
+void InsetMathNest::dump() const
+{
+       odocstringstream oss;
+       WriteStream os(oss);
+       os << "---------------------------------------------\n";
+       write(os);
+       os << "\n";
+       for (idx_type i = 0, n = nargs(); i != n; ++i)
+               os << cell(i) << "\n";
+       os << "---------------------------------------------\n";
+       lyxerr << to_utf8(oss.str());
+}
+
+
+void InsetMathNest::draw(PainterInfo & pi, int x, int y) const
+{
+#if 0
+       if (lock_)
+               pi.pain.fillRectangle(x, y - ascent(), width(), height(),
+                                       LColor::mathlockbg);
+#endif
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathNest::drawSelection(PainterInfo & pi, int x, int y) const
+{
+       BufferView & bv = *pi.base.bv;
+       // this should use the x/y values given, not the cached values
+       LCursor & cur = bv.cursor();
+       if (!cur.selection())
+               return;
+       if (!ptr_cmp(&cur.inset(), this))
+               return;
+
+       // FIXME: hack to get position cache warm
+       pi.pain.setDrawingEnabled(false);
+       draw(pi, x, y);
+       pi.pain.setDrawingEnabled(true);
+
+       CursorSlice s1 = cur.selBegin();
+       CursorSlice s2 = cur.selEnd();
+
+       //lyxerr << "InsetMathNest::drawing selection: "
+       //      << " s1: " << s1 << " s2: " << s2 << endl;
+       if (s1.idx() == s2.idx()) {
+               MathArray const & c = cell(s1.idx());
+               int x1 = c.xo(bv) + c.pos2x(s1.pos());
+               int y1 = c.yo(bv) - c.ascent();
+               int x2 = c.xo(bv) + c.pos2x(s2.pos());
+               int y2 = c.yo(bv) + c.descent();
+               pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
+       //lyxerr << "InsetMathNest::drawing selection 3: "
+       //      << " x1: " << x1 << " x2: " << x2
+       //      << " y1: " << y1 << " y2: " << y2 << endl;
+       } else {
+               for (idx_type i = 0; i < nargs(); ++i) {
+                       if (idxBetween(i, s1.idx(), s2.idx())) {
+                               MathArray const & c = cell(i);
+                               int x1 = c.xo(bv);
+                               int y1 = c.yo(bv) - c.ascent();
+                               int x2 = c.xo(bv) + c.width();
+                               int y2 = c.yo(bv) + c.descent();
+                               pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
+                       }
+               }
+       }
+}
+
+
+void InsetMathNest::validate(LaTeXFeatures & features) const
+{
+       for (idx_type i = 0; i < nargs(); ++i)
+               cell(i).validate(features);
+}
+
+
+void InsetMathNest::replace(ReplaceData & rep)
+{
+       for (idx_type i = 0; i < nargs(); ++i)
+               cell(i).replace(rep);
+}
+
+
+bool InsetMathNest::contains(MathArray const & ar) const
+{
+       for (idx_type i = 0; i < nargs(); ++i)
+               if (cell(i).contains(ar))
+                       return true;
+       return false;
+}
+
+
+bool InsetMathNest::lock() const
+{
+       return lock_;
+}
+
+
+void InsetMathNest::lock(bool l)
+{
+       lock_ = l;
+}
+
+
+bool InsetMathNest::isActive() const
+{
+       return nargs() > 0;
+}
+
+
+MathArray InsetMathNest::glue() const
+{
+       MathArray ar;
+       for (size_t i = 0; i < nargs(); ++i)
+               ar.append(cell(i));
+       return ar;
+}
+
+
+void InsetMathNest::write(WriteStream & os) const
+{
+       os << '\\' << name().c_str();
+       for (size_t i = 0; i < nargs(); ++i)
+               os << '{' << cell(i) << '}';
+       if (nargs() == 0)
+               os.pendingSpace(true);
+       if (lock_ && !os.latex()) {
+               os << "\\lyxlock";
+               os.pendingSpace(true);
+       }
+}
+
+
+void InsetMathNest::normalize(NormalStream & os) const
+{
+       os << '[' << name().c_str();
+       for (size_t i = 0; i < nargs(); ++i)
+               os << ' ' << cell(i);
+       os << ']';
+}
+
+
+int InsetMathNest::latex(Buffer const &, odocstream & os,
+                       OutputParams const & runparams) const
+{
+       WriteStream wi(os, runparams.moving_arg, true);
+       write(wi);
+       return wi.line();
+}
+
+
+bool InsetMathNest::notifyCursorLeaves(LCursor & /*cur*/)
+{
+#ifdef WITH_WARNINGS
+#warning look here
+#endif
+#if 0
+       MathArray & ar = cur.cell();
+       // remove base-only "scripts"
+       for (pos_type i = 0; i + 1 < ar.size(); ++i) {
+               InsetMathScript * p = operator[](i).nucleus()->asScriptInset();
+               if (p && p->nargs() == 1) {
+                       MathArray ar = p->nuc();
+                       erase(i);
+                       insert(i, ar);
+                       cur.adjust(i, ar.size() - 1);
+               }
+       }
+
+       // glue adjacent font insets of the same kind
+       for (pos_type i = 0; i + 1 < size(); ++i) {
+               InsetMathFont * p = operator[](i).nucleus()->asFontInset();
+               InsetMathFont const * q = operator[](i + 1)->asFontInset();
+               if (p && q && p->name() == q->name()) {
+                       p->cell(0).append(q->cell(0));
+                       erase(i + 1);
+                       cur.adjust(i, -1);
+               }
+       }
+#endif
+       return false;
+}
+
+
+void InsetMathNest::handleFont
+       (LCursor & cur, docstring const & arg, char const * const font)
+{
+       handleFont(cur, arg, from_ascii(font));
+}
+
+
+void InsetMathNest::handleFont
+       (LCursor & cur, docstring const & arg, docstring const & font)
+{
+       // this whole function is a hack and won't work for incremental font
+       // changes...
+
+       if (cur.inset().asInsetMath()->name() == font) {
+               recordUndoInset(cur, Undo::ATOMIC);
+               cur.handleFont(to_utf8(font));
+       } else {
+               recordUndo(cur, Undo::ATOMIC);
+               cur.handleNest(createInsetMath(font));
+               cur.insert(arg);
+       }
+}
+
+
+void InsetMathNest::handleFont2(LCursor & cur, docstring const & arg)
+{
+       recordUndo(cur, Undo::ATOMIC);
+       LyXFont font;
+       bool b;
+       bv_funcs::string2font(to_utf8(arg), font, b);
+       if (font.color() != LColor::inherit) {
+               MathAtom at = MathAtom(new InsetMathColor(true, font.color()));
+               cur.handleNest(at, 0);
+       }
+}
+
+
+void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
+{
+       //lyxerr << "InsetMathNest: request: " << cmd << std::endl;
+       //CursorSlice sl = cur.current();
+
+       switch (cmd.action) {
+
+       case LFUN_PASTE: {
+               recordUndo(cur);
+               cur.message(_("Paste"));
+               replaceSelection(cur);
+               docstring topaste;
+               if (cmd.argument().empty() && !theClipboard().isInternal())
+                       topaste = theClipboard().getAsText();
+               else {
+                       size_t n = 0;
+                       idocstringstream is(cmd.argument());
+                       is >> n;
+                       topaste = cap::getSelection(cur.buffer(), n);
+               }
+               cur.niceInsert(topaste);
+               cur.clearSelection(); // bug 393
+               cur.bv().switchKeyMap();
+               finishUndo();
+               break;
+       }
+
+       case LFUN_CUT:
+               recordUndo(cur);
+               cutSelection(cur, true, true);
+               cur.message(_("Cut"));
+               // Prevent stale position >= size crash
+               // Probably not necessary anymore, see eraseSelection (gb 2005-10-09)
+               cur.normalize();
+               break;
+
+       case LFUN_COPY:
+               copySelection(cur);
+               cur.message(_("Copy"));
+               break;
+
+       case LFUN_MOUSE_PRESS:
+               lfunMousePress(cur, cmd);
+               break;
+
+       case LFUN_MOUSE_MOTION:
+               lfunMouseMotion(cur, cmd);
+               break;
+
+       case LFUN_MOUSE_RELEASE:
+               lfunMouseRelease(cur, cmd);
+               break;
+
+       case LFUN_FINISHED_LEFT:
+               cur.bv().cursor() = cur;
+               break;
+
+       case LFUN_FINISHED_RIGHT:
+               ++cur.pos();
+               cur.bv().cursor() = cur;
+               break;
+
+       case LFUN_FINISHED_UP:
+               cur.bv().cursor() = cur;
+               break;
+
+       case LFUN_FINISHED_DOWN:
+               ++cur.pos();
+               cur.bv().cursor() = cur;
+               break;
+
+       case LFUN_CHAR_FORWARD:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+       case LFUN_CHAR_FORWARD_SELECT:
+               cur.selHandle(cmd.action == LFUN_CHAR_FORWARD_SELECT);
+               cur.autocorrect() = false;
+               cur.clearTargetX();
+               cur.macroModeClose();
+               if (cur.pos() != cur.lastpos() && cur.openable(cur.nextAtom())) {
+                       cur.pushLeft(*cur.nextAtom().nucleus());
+                       cur.inset().idxFirst(cur);
+               } else if (cur.posRight() || idxRight(cur)
+                       || cur.popRight() || cur.selection())
+                       ;
+               else {
+                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cur.undispatched();
+               }
+               break;
+
+       case LFUN_CHAR_BACKWARD:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+       case LFUN_CHAR_BACKWARD_SELECT:
+               cur.selHandle(cmd.action == LFUN_CHAR_BACKWARD_SELECT);
+               cur.autocorrect() = false;
+               cur.clearTargetX();
+               cur.macroModeClose();
+               if (cur.pos() != 0 && cur.openable(cur.prevAtom())) {
+                       cur.posLeft();
+                       cur.push(*cur.nextAtom().nucleus());
+                       cur.inset().idxLast(cur);
+               } else if (cur.posLeft() || idxLeft(cur)
+                       || cur.popLeft() || cur.selection())
+                       ;
+               else {
+                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                       cur.undispatched();
+               }
+               break;
+
+       case LFUN_UP:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+       case LFUN_UP_SELECT:
+               // FIXME Tried to use clearTargetX and macroModeClose, crashed on cur.up()
+               if (cur.inMacroMode()) {
+                       // Make Helge happy
+                       cur.macroModeClose();
+                       break;
+               }
+               cur.selHandle(cmd.action == LFUN_UP_SELECT);
+               if (!cur.up()) {
+                       cmd = FuncRequest(LFUN_FINISHED_UP);
+                       cur.undispatched();
+               }
+               // fixes bug 1598. Please check!
+               cur.normalize();
+               break;
+
+       case LFUN_DOWN:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+       case LFUN_DOWN_SELECT:
+               if (cur.inMacroMode()) {
+                       cur.macroModeClose();
+                       break;
+               }
+               cur.selHandle(cmd.action == LFUN_DOWN_SELECT);
+               if (!cur.down()) {
+                       cmd = FuncRequest(LFUN_FINISHED_DOWN);
+                       cur.undispatched();
+               }
+               // fixes bug 1598. Please check!
+               cur.normalize();
+               break;
+
+       case LFUN_MOUSE_DOUBLE:
+       case LFUN_MOUSE_TRIPLE:
+       case LFUN_WORD_SELECT:
+               cur.pos() = 0;
+               cur.idx() = 0;
+               cur.resetAnchor();
+               cur.selection() = true;
+               cur.pos() = cur.lastpos();
+               cur.idx() = cur.lastidx();
+               cap::saveSelection(cur);
+               break;
+
+       case LFUN_PARAGRAPH_UP:
+       case LFUN_PARAGRAPH_DOWN:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+       case LFUN_PARAGRAPH_UP_SELECT:
+       case LFUN_PARAGRAPH_DOWN_SELECT:
+               break;
+
+       case LFUN_LINE_BEGIN:
+       case LFUN_WORD_BACKWARD:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+       case LFUN_LINE_BEGIN_SELECT:
+       case LFUN_WORD_BACKWARD_SELECT:
+               cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT ||
+                               cmd.action == LFUN_LINE_BEGIN_SELECT);
+               cur.macroModeClose();
+               if (cur.pos() != 0) {
+                       cur.pos() = 0;
+               } else if (cur.col() != 0) {
+                       cur.idx() -= cur.col();
+                       cur.pos() = 0;
+               } else if (cur.idx() != 0) {
+                       cur.idx() = 0;
+                       cur.pos() = 0;
+               } else {
+                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                       cur.undispatched();
+               }
+               break;
+
+       case LFUN_WORD_FORWARD:
+       case LFUN_LINE_END:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+       case LFUN_WORD_FORWARD_SELECT:
+       case LFUN_LINE_END_SELECT:
+               cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT ||
+                               cmd.action == LFUN_LINE_END_SELECT);
+               cur.macroModeClose();
+               cur.clearTargetX();
+               if (cur.pos() != cur.lastpos()) {
+                       cur.pos() = cur.lastpos();
+               } else if (ncols() && (cur.col() != cur.lastcol())) {
+                       cur.idx() = cur.idx() - cur.col() + cur.lastcol();
+                       cur.pos() = cur.lastpos();
+               } else if (cur.idx() != cur.lastidx()) {
+                       cur.idx() = cur.lastidx();
+                       cur.pos() = cur.lastpos();
+               } else {
+                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cur.undispatched();
+               }
+               break;
+
+       case LFUN_SCREEN_UP_SELECT:
+       case LFUN_SCREEN_UP:
+               cmd = FuncRequest(LFUN_FINISHED_LEFT);
+               cur.undispatched();
+               break;
+
+       case LFUN_SCREEN_DOWN_SELECT:
+       case LFUN_SCREEN_DOWN:
+               cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+               cur.undispatched();
+               break;
+
+       case LFUN_CELL_FORWARD:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+               cur.inset().idxNext(cur);
+               break;
+
+       case LFUN_CELL_BACKWARD:
+               cur.updateFlags(Update::Decoration | Update::FitCursor);
+               cur.inset().idxPrev(cur);
+               break;
+
+       case LFUN_WORD_DELETE_BACKWARD:
+       case LFUN_CHAR_DELETE_BACKWARD:
+               if (cur.pos() == 0)
+                       // May affect external cell:
+                       recordUndoInset(cur, Undo::ATOMIC);
+               else
+                       recordUndo(cur, Undo::ATOMIC);
+               // if the inset can not be removed from within, delete it
+               if (!cur.backspace()) {
+                       FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD);
+                       cur.innerText()->dispatch(cur, cmd);
+               }
+               break;
+
+       case LFUN_WORD_DELETE_FORWARD:
+       case LFUN_CHAR_DELETE_FORWARD:
+               if (cur.pos() == cur.lastpos())
+                       // May affect external cell:
+                       recordUndoInset(cur, Undo::ATOMIC);
+               else
+                       recordUndo(cur, Undo::ATOMIC);
+               // if the inset can not be removed from within, delete it
+               if (!cur.erase()) {
+                       FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD);
+                       cur.innerText()->dispatch(cur, cmd);
+               }
+               break;
+
+       case LFUN_ESCAPE:
+               if (cur.selection())
+                       cur.clearSelection();
+               else  {
+                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cur.undispatched();
+               }
+               break;
+
+       case LFUN_INSET_TOGGLE:
+               recordUndo(cur);
+               lock(!lock());
+               cur.popRight();
+               break;
+
+       case LFUN_SELF_INSERT:
+               if (cmd.argument().size() != 1) {
+                       recordUndo(cur);
+                       docstring const arg = cmd.argument();
+                       if (!interpretString(cur, arg))
+                               cur.insert(arg);
+                       break;
+               }
+               // Don't record undo steps if we are in macro mode and
+               // cmd.argument is the next character of the macro name.
+               // Otherwise we'll get an invalid cursor if we undo after
+               // the macro was finished and the macro is a known command,
+               // e.g. sqrt. LCursor::macroModeClose replaces in this case
+               // the InsetMathUnknown with name "frac" by an empty
+               // InsetMathFrac -> a pos value > 0 is invalid.
+               // A side effect is that an undo before the macro is finished
+               // undoes the complete macro, not only the last character.
+               if (!cur.inMacroMode())
+                       recordUndo(cur);
+
+               // spacial handling of space. If we insert an inset
+               // via macro mode, we want to put the cursor inside it
+               // if relevant. Think typing "\frac<space>".
+               if (cmd.argument()[0] == ' '
+                   && cur.inMacroMode() && cur.macroName() != "\\"
+                   && cur.macroModeClose()) {
+                       MathAtom const atom = cur.prevAtom();
+                       if (atom->asNestInset() && atom->nargs() > 0) {
+                               cur.posLeft();
+                               cur.pushLeft(*cur.nextInset());
+                       }
+               } else if (!interpretChar(cur, cmd.argument()[0])) {
+                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cur.undispatched();
+               }
+               break;
+
+       //case LFUN_SERVER_GET_XY:
+       //      sprintf(dispatch_buffer, "%d %d",);
+       //      break;
+
+       case LFUN_SERVER_SET_XY: {
+               lyxerr << "LFUN_SERVER_SET_XY broken!" << endl;
+               int x = 0;
+               int y = 0;
+               istringstream is(to_utf8(cmd.argument()));
+               is >> x >> y;
+               cur.setScreenPos(x, y);
+               break;
+       }
+
+       // Special casing for superscript in case of LyX handling
+       // dead-keys:
+       case LFUN_ACCENT_CIRCUMFLEX:
+               if (cmd.argument().empty()) {
+                       // do superscript if LyX handles
+                       // deadkeys
+                       recordUndo(cur, Undo::ATOMIC);
+                       script(cur, true, grabAndEraseSelection(cur));
+               }
+               break;
+
+       case LFUN_ACCENT_UMLAUT:
+       case LFUN_ACCENT_ACUTE:
+       case LFUN_ACCENT_GRAVE:
+       case LFUN_ACCENT_BREVE:
+       case LFUN_ACCENT_DOT:
+       case LFUN_ACCENT_MACRON:
+       case LFUN_ACCENT_CARON:
+       case LFUN_ACCENT_TILDE:
+       case LFUN_ACCENT_CEDILLA:
+       case LFUN_ACCENT_CIRCLE:
+       case LFUN_ACCENT_UNDERDOT:
+       case LFUN_ACCENT_TIE:
+       case LFUN_ACCENT_OGONEK:
+       case LFUN_ACCENT_HUNGARIAN_UMLAUT:
+               break;
+
+       //  Math fonts
+       case LFUN_FONT_FREE_APPLY:
+       case LFUN_FONT_FREE_UPDATE:
+               handleFont2(cur, cmd.argument());
+               break;
+
+       case LFUN_FONT_BOLD:
+               if (currentMode() == TEXT_MODE)
+                       handleFont(cur, cmd.argument(), "textbf");
+               else
+                       handleFont(cur, cmd.argument(), "mathbf");
+               break;
+       case LFUN_FONT_SANS:
+               if (currentMode() == TEXT_MODE)
+                       handleFont(cur, cmd.argument(), "textsf");
+               else
+                       handleFont(cur, cmd.argument(), "mathsf");
+               break;
+       case LFUN_FONT_EMPH:
+               if (currentMode() == TEXT_MODE)
+                       handleFont(cur, cmd.argument(), "emph");
+               else
+                       handleFont(cur, cmd.argument(), "mathcal");
+               break;
+       case LFUN_FONT_ROMAN:
+               if (currentMode() == TEXT_MODE)
+                       handleFont(cur, cmd.argument(), "textrm");
+               else
+                       handleFont(cur, cmd.argument(), "mathrm");
+               break;
+       case LFUN_FONT_CODE:
+               if (currentMode() == TEXT_MODE)
+                       handleFont(cur, cmd.argument(), "texttt");
+               else
+                       handleFont(cur, cmd.argument(), "mathtt");
+               break;
+       case LFUN_FONT_FRAK:
+               handleFont(cur, cmd.argument(), "mathfrak");
+               break;
+       case LFUN_FONT_ITAL:
+               if (currentMode() == TEXT_MODE)
+                       handleFont(cur, cmd.argument(), "textit");
+               else
+                       handleFont(cur, cmd.argument(), "mathit");
+               break;
+       case LFUN_FONT_NOUN:
+               if (currentMode() == TEXT_MODE)
+                       // FIXME: should be "noun"
+                       handleFont(cur, cmd.argument(), "textsc");
+               else
+                       handleFont(cur, cmd.argument(), "mathbb");
+               break;
+       /*
+       case LFUN_FONT_FREE_APPLY:
+               handleFont(cur, cmd.argument(), "textrm");
+               break;
+       */
+       case LFUN_FONT_DEFAULT:
+               handleFont(cur, cmd.argument(), "textnormal");
+               break;
+
+       case LFUN_MATH_MODE: {
+#if 1
+               // ignore math-mode on when already in math mode
+               if (currentMode() == InsetBase::MATH_MODE && cmd.argument() == "on")
+                       break;
+               cur.macroModeClose();
+               docstring const save_selection = grabAndEraseSelection(cur);
+               selClearOrDel(cur);
+               //cur.plainInsert(MathAtom(new InsetMathMBox(cur.bv())));
+               cur.plainInsert(MathAtom(new InsetMathBox(from_ascii("mbox"))));
+               cur.posLeft();
+               cur.pushLeft(*cur.nextInset());
+               cur.niceInsert(save_selection);
+#else
+               if (currentMode() == InsetBase::TEXT_MODE) {
+                       cur.niceInsert(MathAtom(new InsetMathHull("simple")));
+                       cur.message(_("create new math text environment ($...$)"));
+               } else {
+                       handleFont(cur, cmd.argument(), "textrm");
+                       cur.message(_("entered math text mode (textrm)"));
+               }
+#endif
+               break;
+       }
+
+       case LFUN_MATH_SIZE:
+#if 0
+               recordUndo(cur);
+               cur.setSize(arg);
+#endif
+               break;
+
+       case LFUN_MATH_MATRIX: {
+               recordUndo(cur, Undo::ATOMIC);
+               unsigned int m = 1;
+               unsigned int n = 1;
+               docstring v_align;
+               docstring h_align;
+               idocstringstream is(cmd.argument());
+               is >> m >> n >> v_align >> h_align;
+               if (m < 1)
+                       m = 1;
+               if (n < 1)
+                       n = 1;
+               v_align += 'c';
+               cur.niceInsert(
+                       MathAtom(new InsetMathArray(from_ascii("array"), m, n, (char)v_align[0], h_align)));
+               break;
+       }
+
+       case LFUN_MATH_DELIM: {
+               docstring ls;
+               docstring rs = support::split(cmd.argument(), ls, ' ');
+               // Reasonable default values
+               if (ls.empty())
+                       ls = '(';
+               if (rs.empty())
+                       rs = ')';
+               recordUndo(cur, Undo::ATOMIC);
+               cur.handleNest(MathAtom(new InsetMathDelim(ls, rs)));
+               break;
+       }
+
+       case LFUN_MATH_BIGDELIM: {
+               docstring const lname  = from_utf8(cmd.getArg(0));
+               docstring const ldelim = from_utf8(cmd.getArg(1));
+               docstring const rname  = from_utf8(cmd.getArg(2));
+               docstring const rdelim = from_utf8(cmd.getArg(3));
+               latexkeys const * l = in_word_set(lname);
+               bool const have_l = l && l->inset == "big" &&
+                                   InsetMathBig::isBigInsetDelim(ldelim);
+               l = in_word_set(rname);
+               bool const have_r = l && l->inset == "big" &&
+                                   InsetMathBig::isBigInsetDelim(rdelim);
+               // We mimic LFUN_MATH_DELIM in case we have an empty left
+               // or right delimiter.
+               if (have_l || have_r) {
+                       recordUndo(cur, Undo::ATOMIC);
+                       docstring const selection = grabAndEraseSelection(cur);
+                       selClearOrDel(cur);
+                       if (have_l)
+                               cur.insert(MathAtom(new InsetMathBig(lname,
+                                                               ldelim)));
+                       cur.niceInsert(selection);
+                       if (have_r)
+                               cur.insert(MathAtom(new InsetMathBig(rname,
+                                                               rdelim)));
+               }
+               // Don't call cur.undispatched() if we did nothing, this would
+               // lead to infinite recursion via LyXText::dispatch().
+               break;
+       }
+
+       case LFUN_SPACE_INSERT:
+       case LFUN_MATH_SPACE:
+               recordUndo(cur, Undo::ATOMIC);
+               cur.insert(MathAtom(new InsetMathSpace(from_ascii(","))));
+               break;
+
+       case LFUN_ERT_INSERT:
+               // interpret this as if a backslash was typed
+               recordUndo(cur, Undo::ATOMIC);
+               interpretChar(cur, '\\');
+               break;
+
+       case LFUN_MATH_SUBSCRIPT:
+               // interpret this as if a _ was typed
+               recordUndo(cur, Undo::ATOMIC);
+               interpretChar(cur, '_');
+               break;
+
+       case LFUN_MATH_SUPERSCRIPT:
+               // interpret this as if a ^ was typed
+               recordUndo(cur, Undo::ATOMIC);
+               interpretChar(cur, '^');
+               break;
+
+       case LFUN_QUOTE_INSERT:
+               // interpret this as if a straight " was typed
+               recordUndo(cur, Undo::ATOMIC);
+               interpretChar(cur, '\"');
+               break;
+
+// FIXME: We probably should swap parts of "math-insert" and "self-insert"
+// handling such that "self-insert" works on "arbitrary stuff" too, and
+// math-insert only handles special math things like "matrix".
+       case LFUN_MATH_INSERT: {
+               recordUndo(cur, Undo::ATOMIC);
+               if (cmd.argument() == "^" || cmd.argument() == "_") {
+                       interpretChar(cur, cmd.argument()[0]);
+               } else
+                       cur.niceInsert(cmd.argument());
+               break;
+               }
+
+       case LFUN_DIALOG_SHOW_NEW_INSET: {
+               docstring const & name = cmd.argument();
+               string data;
+               if (name == "ref") {
+                       RefInset tmp(name);
+                       data = tmp.createDialogStr(to_utf8(name));
+               }
+               cur.bv().showInsetDialog(to_utf8(name), data, 0);
+               break;
+       }
+
+       case LFUN_INSET_INSERT: {
+               MathArray ar;
+               if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
+                       recordUndo(cur);
+                       cur.insert(ar);
+               } else
+                       cur.undispatched();
+               break;
+       }
+
+       default:
+               InsetMathDim::doDispatch(cur, cmd);
+               break;
+       }
+}
+
+
+bool InsetMathNest::getStatus(LCursor & cur, FuncRequest const & cmd,
+               FuncStatus & flag) const
+{
+       // the font related toggles
+       //string tc = "mathnormal";
+       bool ret = true;
+       string const arg = to_utf8(cmd.argument());
+       switch (cmd.action) {
+       case LFUN_TABULAR_FEATURE:
+               flag.enabled(false);
+               break;
+#if 0
+       case LFUN_TABULAR_FEATURE:
+               // FIXME: check temporarily disabled
+               // valign code
+               char align = mathcursor::valign();
+               if (align == '\0') {
+                       enable = false;
+                       break;
+               }
+               if (cmd.argument().empty()) {
+                       flag.clear();
+                       break;
+               }
+               if (!contains("tcb", cmd.argument()[0])) {
+                       enable = false;
+                       break;
+               }
+               flag.setOnOff(cmd.argument()[0] == align);
+               break;
+#endif
+       /// We have to handle them since 1.4 blocks all unhandled actions
+       case LFUN_FONT_ITAL:
+       case LFUN_FONT_BOLD:
+       case LFUN_FONT_SANS:
+       case LFUN_FONT_EMPH:
+       case LFUN_FONT_CODE:
+       case LFUN_FONT_NOUN:
+       case LFUN_FONT_ROMAN:
+       case LFUN_FONT_DEFAULT:
+               flag.enabled(true);
+               break;
+       case LFUN_MATH_MUTATE:
+               //flag.setOnOff(mathcursor::formula()->hullType() == to_utf8(cmd.argument()));
+               flag.setOnOff(false);
+               break;
+
+       // we just need to be in math mode to enable that
+       case LFUN_MATH_SIZE:
+       case LFUN_MATH_SPACE:
+       case LFUN_MATH_LIMITS:
+       case LFUN_MATH_NONUMBER:
+       case LFUN_MATH_NUMBER:
+       case LFUN_MATH_EXTERN:
+               flag.enabled(true);
+               break;
+
+       case LFUN_FONT_FRAK:
+               flag.enabled(currentMode() != TEXT_MODE);
+               break;
+
+       case LFUN_MATH_INSERT: {
+               bool const textarg =
+                       arg == "\\textbf"   || arg == "\\textsf" ||
+                       arg == "\\textrm"   || arg == "\\textmd" ||
+                       arg == "\\textit"   || arg == "\\textsc" ||
+                       arg == "\\textsl"   || arg == "\\textup" ||
+                       arg == "\\texttt"   || arg == "\\textbb" ||
+                       arg == "\\textnormal";
+               flag.enabled(currentMode() != TEXT_MODE || textarg);
+               break;
+       }
+
+       case LFUN_MATH_MATRIX:
+               flag.enabled(currentMode() == MATH_MODE);
+               break;
+
+       case LFUN_INSET_INSERT: {
+               // Don't test createMathInset_fromDialogStr(), since
+               // getStatus is not called with a valid reference and the
+               // dialog would not be applyable.
+               string const name = cmd.getArg(0);
+               flag.enabled(name == "ref");
+               break;
+       }
+
+       case LFUN_MATH_DELIM:
+       case LFUN_MATH_BIGDELIM:
+               // Don't do this with multi-cell selections
+               flag.enabled(cur.selBegin().idx() == cur.selEnd().idx());
+               break;
+
+       default:
+               ret = false;
+               break;
+       }
+       return ret;
+}
+
+
+void InsetMathNest::edit(LCursor & cur, bool left)
+{
+       cur.push(*this);
+       cur.idx() = left ? 0 : cur.lastidx();
+       cur.pos() = left ? 0 : cur.lastpos();
+       cur.resetAnchor();
+       //lyxerr << "InsetMathNest::edit, cur:\n" << cur << endl;
+}
+
+
+InsetBase * InsetMathNest::editXY(LCursor & cur, int x, int y)
+{
+       int idx_min = 0;
+       int dist_min = 1000000;
+       for (idx_type i = 0, n = nargs(); i != n; ++i) {
+               int const d = cell(i).dist(cur.bv(), x, y);
+               if (d < dist_min) {
+                       dist_min = d;
+                       idx_min = i;
+               }
+       }
+       MathArray & ar = cell(idx_min);
+       cur.push(*this);
+       cur.idx() = idx_min;
+       cur.pos() = ar.x2pos(x - ar.xo(cur.bv()));
+
+       //lyxerr << "found cell : " << idx_min << " pos: " << cur.pos() << endl;
+       if (dist_min == 0) {
+               // hit inside cell
+               for (pos_type i = 0, n = ar.size(); i < n; ++i)
+                       if (ar[i]->covers(cur.bv(), x, y))
+                               return ar[i].nucleus()->editXY(cur, x, y);
+       }
+       return this;
+}
+
+
+void InsetMathNest::lfunMousePress(LCursor & cur, FuncRequest & cmd)
+{
+       //lyxerr << "## lfunMousePress: buttons: " << cmd.button() << endl;
+       BufferView & bv = cur.bv();
+       if (cmd.button() == mouse_button::button1) {
+               //lyxerr << "## lfunMousePress: setting cursor to: " << cur << endl;
+               bv.mouseSetCursor(cur);
+               // Update the cursor update flags as needed:
+               //
+               // Update::Decoration: tells to update the decoration (visual box
+               //                     corners that define the inset)/
+               // Update::FitCursor: adjust the screen to the cursor position if
+               //                    needed
+               // cur.result().update(): don't overwrite previously set flags.
+               cur.updateFlags(Update::Decoration | Update::FitCursor | cur.result().update());
+       } else if (cmd.button() == mouse_button::button2) {
+               MathArray ar;
+               if (cap::selection()) {
+                       // See comment in LyXText::dispatch why we do this
+                       cap::copySelectionToStack();
+                       cmd = FuncRequest(LFUN_PASTE, "0");
+                       doDispatch(cur, cmd);
+               } else
+                       asArray(theSelection().get(), ar);
+
+               cur.insert(ar);
+               bv.mouseSetCursor(cur);
+       }
+}
+
+
+void InsetMathNest::lfunMouseMotion(LCursor & cur, FuncRequest & cmd)
+{
+       // only select with button 1
+       if (cmd.button() == mouse_button::button1) {
+               LCursor & bvcur = cur.bv().cursor();
+               if (bvcur.anchor_.hasPart(cur)) {
+                       //lyxerr << "## lfunMouseMotion: cursor: " << cur << endl;
+                       bvcur.setCursor(cur);
+                       bvcur.selection() = true;
+                       //lyxerr << "MOTION " << bvcur << endl;
+               } else
+                       cur.undispatched();
+       }
+}
+
+
+void InsetMathNest::lfunMouseRelease(LCursor & cur, FuncRequest & cmd)
+{
+       //lyxerr << "## lfunMouseRelease: buttons: " << cmd.button() << endl;
+
+       if (cmd.button() == mouse_button::button1) {
+               if (!cur.selection())
+                       cur.noUpdate();
+               else {
+                       LCursor & bvcur = cur.bv().cursor();
+                       bvcur.selection() = true;
+                       cap::saveSelection(bvcur);
+               }
+               return;
+       }
+
+       cur.undispatched();
+}
+
+
+bool InsetMathNest::interpretChar(LCursor & cur, char_type c)
+{
+       //lyxerr << "interpret 2: '" << c << "'" << endl;
+       docstring save_selection;
+       if (c == '^' || c == '_')
+               save_selection = grabAndEraseSelection(cur);
+
+       cur.clearTargetX();
+
+       // handle macroMode
+       if (cur.inMacroMode()) {
+               docstring name = cur.macroName();
+
+               /// are we currently typing '#1' or '#2' or...?
+               if (name == "\\#") {
+                       cur.backspace();
+                       int n = c - '0';
+                       if (n >= 1 && n <= 9)
+                               cur.insert(new MathMacroArgument(n));
+                       return true;
+               }
+
+               if (isAlphaASCII(c)) {
+                       cur.activeMacro()->setName(name + docstring(1, c));
+                       return true;
+               }
+
+               // handle 'special char' macros
+               if (name == "\\") {
+                       // remove the '\\'
+                       if (c == '\\') {
+                               cur.backspace();
+                               if (currentMode() == InsetMath::TEXT_MODE)
+                                       cur.niceInsert(createInsetMath("textbackslash"));
+                               else
+                                       cur.niceInsert(createInsetMath("backslash"));
+                       } else if (c == '{') {
+                               cur.backspace();
+                               cur.niceInsert(MathAtom(new InsetMathBrace));
+                       } else if (c == '%') {
+                               cur.backspace();
+                               cur.niceInsert(MathAtom(new InsetMathComment));
+                       } else if (c == '#') {
+                               BOOST_ASSERT(cur.activeMacro());
+                               cur.activeMacro()->setName(name + docstring(1, c));
+                       } else {
+                               cur.backspace();
+                               cur.niceInsert(createInsetMath(docstring(1, c)));
+                       }
+                       return true;
+               }
+
+               // One character big delimiters. The others are handled in
+               // interpretString().
+               latexkeys const * l = in_word_set(name.substr(1));
+               if (name[0] == '\\' && l && l->inset == "big") {
+                       docstring delim;
+                       switch (c) {
+                       case '{':
+                               delim = from_ascii("\\{");
+                               break;
+                       case '}':
+                               delim = from_ascii("\\}");
+                               break;
+                       default:
+                               delim = docstring(1, c);
+                               break;
+                       }
+                       if (InsetMathBig::isBigInsetDelim(delim)) {
+                               // name + delim ared a valid InsetMathBig.
+                               // We can't use cur.macroModeClose() because
+                               // it does not handle delim.
+                               InsetMathUnknown * p = cur.activeMacro();
+                               p->finalize();
+                               --cur.pos();
+                               cur.cell().erase(cur.pos());
+                               cur.plainInsert(MathAtom(
+                                       new InsetMathBig(name.substr(1), delim)));
+                               return true;
+                       }
+               }
+
+               // leave macro mode and try again if necessary
+               cur.macroModeClose();
+               if (c == '{')
+                       cur.niceInsert(MathAtom(new InsetMathBrace));
+               else if (c != ' ')
+                       interpretChar(cur, c);
+               return true;
+       }
+
+       // This is annoying as one has to press <space> far too often.
+       // Disable it.
+
+#if 0
+               // leave autocorrect mode if necessary
+               if (autocorrect() && c == ' ') {
+                       autocorrect() = false;
+                       return true;
+               }
+#endif
+
+       // just clear selection on pressing the space bar
+       if (cur.selection() && c == ' ') {
+               cur.selection() = false;
+               return true;
+       }
+
+       selClearOrDel(cur);
+
+       if (c == '\\') {
+               //lyxerr << "starting with macro" << endl;
+               cur.insert(MathAtom(new InsetMathUnknown(from_ascii("\\"), false)));
+               return true;
+       }
+
+       if (c == '\n') {
+               if (currentMode() == InsetMath::TEXT_MODE)
+                       cur.insert(c);
+               return true;
+       }
+
+       if (c == ' ') {
+               if (currentMode() == InsetMath::TEXT_MODE) {
+                       // insert spaces in text mode,
+                       // but suppress direct insertion of two spaces in a row
+                       // the still allows typing  '<space>a<space>' and deleting the 'a', but
+                       // it is better than nothing...
+                       if (!cur.pos() != 0 || cur.prevAtom()->getChar() != ' ') {
+                               cur.insert(c);
+                               // FIXME: we have to enable full redraw here because of the
+                               // visual box corners that define the inset. If we know for
+                               // sure that we stay within the same cell we can optimize for
+                               // that using:
+                               //cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                       }
+                       return true;
+               }
+               if (cur.pos() != 0 && cur.prevAtom()->asSpaceInset()) {
+                       cur.prevAtom().nucleus()->asSpaceInset()->incSpace();
+                       // FIXME: we have to enable full redraw here because of the
+                       // visual box corners that define the inset. If we know for
+                       // sure that we stay within the same cell we can optimize for
+                       // that using:
+                       //cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                       return true;
+               }
+
+               if (cur.popRight()) {
+                       // FIXME: we have to enable full redraw here because of the
+                       // visual box corners that define the inset. If we know for
+                       // sure that we stay within the same cell we can optimize for
+                       // that using:
+                       //cur.updateFlags(Update::FitCursor);
+                       return true;
+               }
+
+               // if we are at the very end, leave the formula
+               return cur.pos() != cur.lastpos();
+       }
+
+       // These shouldn't work in text mode:
+       if (currentMode() != InsetMath::TEXT_MODE) {
+               if (c == '_') {
+                       script(cur, false, save_selection);
+                       return true;
+               }
+               if (c == '^') {
+                       script(cur, true, save_selection);
+                       return true;
+               }
+               if (c == '~') {
+                       cur.niceInsert(createInsetMath("sim"));
+                       return true;
+               }
+       }
+
+       if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' ||
+           c == '%' || c == '_' || c == '^') {
+               cur.niceInsert(createInsetMath(docstring(1, c)));
+               return true;
+       }
+
+
+       // try auto-correction
+       //if (autocorrect() && hasPrevAtom() && math_autocorrect(prevAtom(), c))
+       //      return true;
+
+       // no special circumstances, so insert the character without any fuss
+       cur.insert(c);
+       cur.autocorrect() = true;
+       return true;
+}
+
+
+bool InsetMathNest::interpretString(LCursor & cur, docstring const & str)
+{
+       // Create a InsetMathBig from cur.cell()[cur.pos() - 1] and t if
+       // possible
+       if (!cur.empty() && cur.pos() > 0 &&
+           cur.cell()[cur.pos() - 1]->asUnknownInset()) {
+               if (InsetMathBig::isBigInsetDelim(str)) {
+                       docstring prev = asString(cur.cell()[cur.pos() - 1]);
+                       if (prev[0] == '\\') {
+                               prev = prev.substr(1);
+                               latexkeys const * l = in_word_set(prev);
+                               if (l && l->inset == "big") {
+                                       cur.cell()[cur.pos() - 1] =
+                                               MathAtom(new InsetMathBig(prev, str));
+                                       return true;
+                               }
+                       }
+               }
+       }
+       return false;
+}
+
+
+bool InsetMathNest::script(LCursor & cur, bool up, 
+               docstring const & save_selection)
+{
+       // Hack to get \^ and \_ working
+       //lyxerr << "handling script: up: " << up << endl;
+       if (cur.inMacroMode() && cur.macroName() == "\\") {
+               if (up)
+                       cur.niceInsert(createInsetMath("mathcircumflex"));
+               else
+                       interpretChar(cur, '_');
+               return true;
+       }
+
+       cur.macroModeClose();
+       if (asScriptInset() && cur.idx() == 0) {
+               // we are in a nucleus of a script inset, move to _our_ script
+               InsetMathScript * inset = asScriptInset();
+               //lyxerr << " going to cell " << inset->idxOfScript(up) << endl;
+               inset->ensure(up);
+               cur.idx() = inset->idxOfScript(up);
+               cur.pos() = 0;
+       } else if (cur.pos() != 0 && cur.prevAtom()->asScriptInset()) {
+               --cur.pos();
+               InsetMathScript * inset = cur.nextAtom().nucleus()->asScriptInset();
+               cur.push(*inset);
+               inset->ensure(up);
+               cur.idx() = inset->idxOfScript(up);
+               cur.pos() = cur.lastpos();
+       } else {
+               // convert the thing to our left to a scriptinset or create a new
+               // one if in the very first position of the array
+               if (cur.pos() == 0) {
+                       //lyxerr << "new scriptinset" << endl;
+                       cur.insert(new InsetMathScript(up));
+               } else {
+                       //lyxerr << "converting prev atom " << endl;
+                       cur.prevAtom() = MathAtom(new InsetMathScript(cur.prevAtom(), up));
+               }
+               --cur.pos();
+               InsetMathScript * inset = cur.nextAtom().nucleus()->asScriptInset();
+               // See comment in MathParser.cpp for special handling of {}-bases
+
+               cur.push(*inset);
+               cur.idx() = 1;
+               cur.pos() = 0;
+       }
+       //lyxerr << "inserting selection 1:\n" << save_selection << endl;
+       cur.niceInsert(save_selection);
+       cur.resetAnchor();
+       //lyxerr << "inserting selection 2:\n" << save_selection << endl;
+       return true;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathNumber.C b/src/mathed/InsetMathNumber.C
deleted file mode 100644 (file)
index 0a56cb0..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * \file InsetMathNumber.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathNumber.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::auto_ptr;
-using std::vector;
-
-InsetMathNumber::InsetMathNumber(docstring const & s)
-       : str_(s)
-{}
-
-
-auto_ptr<InsetBase> InsetMathNumber::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathNumber(*this));
-}
-
-
-bool InsetMathNumber::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       mathed_string_dim(mi.base.font, str_, dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathNumber::draw(PainterInfo & pi, int x, int y) const
-{
-       pi.draw(x, y, str_);
-}
-
-
-void InsetMathNumber::normalize(NormalStream & os) const
-{
-       os << "[number " << str_ << ']';
-}
-
-
-void InsetMathNumber::maple(MapleStream & os) const
-{
-       os << str_;
-}
-
-
-void InsetMathNumber::mathematica(MathematicaStream & os) const
-{
-       os << str_;
-}
-
-
-void InsetMathNumber::octave(OctaveStream & os) const
-{
-       os << str_;
-}
-
-
-void InsetMathNumber::mathmlize(MathStream & os) const
-{
-       os << "<mi> " << str_ << " </mi>";
-}
-
-
-void InsetMathNumber::write(WriteStream & os) const
-{
-       os << str_;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathNumber.cpp b/src/mathed/InsetMathNumber.cpp
new file mode 100644 (file)
index 0000000..0a56cb0
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * \file InsetMathNumber.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathNumber.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::auto_ptr;
+using std::vector;
+
+InsetMathNumber::InsetMathNumber(docstring const & s)
+       : str_(s)
+{}
+
+
+auto_ptr<InsetBase> InsetMathNumber::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathNumber(*this));
+}
+
+
+bool InsetMathNumber::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       mathed_string_dim(mi.base.font, str_, dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathNumber::draw(PainterInfo & pi, int x, int y) const
+{
+       pi.draw(x, y, str_);
+}
+
+
+void InsetMathNumber::normalize(NormalStream & os) const
+{
+       os << "[number " << str_ << ']';
+}
+
+
+void InsetMathNumber::maple(MapleStream & os) const
+{
+       os << str_;
+}
+
+
+void InsetMathNumber::mathematica(MathematicaStream & os) const
+{
+       os << str_;
+}
+
+
+void InsetMathNumber::octave(OctaveStream & os) const
+{
+       os << str_;
+}
+
+
+void InsetMathNumber::mathmlize(MathStream & os) const
+{
+       os << "<mi> " << str_ << " </mi>";
+}
+
+
+void InsetMathNumber::write(WriteStream & os) const
+{
+       os << str_;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathOverset.C b/src/mathed/InsetMathOverset.C
deleted file mode 100644 (file)
index 2157a62..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * \file InsetMathOverset.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathOverset.h"
-#include "MathData.h"
-#include "MathStream.h"
-
-#include "cursor.h"
-#include "LaTeXFeatures.h"
-
-
-namespace lyx {
-
-using std::max;
-using std::auto_ptr;
-
-
-auto_ptr<InsetBase> InsetMathOverset::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathOverset(*this));
-}
-
-
-bool InsetMathOverset::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(1).metrics(mi);
-       FracChanger dummy(mi.base);
-       cell(0).metrics(mi);
-       dim.wid = max(cell(0).width(), cell(1).width()) + 4;
-       dim.asc = cell(1).ascent() + cell(0).height() + 4;
-       dim.des = cell(1).descent();
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathOverset::draw(PainterInfo & pi, int x, int y) const
-{
-       int m  = x + width() / 2;
-       int yo = y - cell(1).ascent() + cell(0).descent() - 1;
-       cell(1).draw(pi, m - cell(1).width() / 2, y);
-       FracChanger dummy(pi.base);
-       cell(0).draw(pi, m - cell(0).width() / 2, yo);
-       drawMarkers(pi, x, y);
-}
-
-
-bool InsetMathOverset::idxFirst(LCursor & cur) const
-{
-       cur.idx() = 1;
-       cur.pos() = 0;
-       return true;
-}
-
-
-bool InsetMathOverset::idxLast(LCursor & cur) const
-{
-       cur.idx() = 1;
-       cur.pos() = cur.lastpos();
-       return true;
-}
-
-
-void InsetMathOverset::write(WriteStream & os) const
-{
-       os << "\\overset{" << cell(0) << "}{" << cell(1) << '}';
-}
-
-
-void InsetMathOverset::normalize(NormalStream & os) const
-{
-       os << "[overset " << cell(0) << ' ' << cell(1) << ']';
-}
-
-
-void InsetMathOverset::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-       InsetMathNest::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathOverset.cpp b/src/mathed/InsetMathOverset.cpp
new file mode 100644 (file)
index 0000000..2157a62
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+ * \file InsetMathOverset.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathOverset.h"
+#include "MathData.h"
+#include "MathStream.h"
+
+#include "cursor.h"
+#include "LaTeXFeatures.h"
+
+
+namespace lyx {
+
+using std::max;
+using std::auto_ptr;
+
+
+auto_ptr<InsetBase> InsetMathOverset::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathOverset(*this));
+}
+
+
+bool InsetMathOverset::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(1).metrics(mi);
+       FracChanger dummy(mi.base);
+       cell(0).metrics(mi);
+       dim.wid = max(cell(0).width(), cell(1).width()) + 4;
+       dim.asc = cell(1).ascent() + cell(0).height() + 4;
+       dim.des = cell(1).descent();
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathOverset::draw(PainterInfo & pi, int x, int y) const
+{
+       int m  = x + width() / 2;
+       int yo = y - cell(1).ascent() + cell(0).descent() - 1;
+       cell(1).draw(pi, m - cell(1).width() / 2, y);
+       FracChanger dummy(pi.base);
+       cell(0).draw(pi, m - cell(0).width() / 2, yo);
+       drawMarkers(pi, x, y);
+}
+
+
+bool InsetMathOverset::idxFirst(LCursor & cur) const
+{
+       cur.idx() = 1;
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathOverset::idxLast(LCursor & cur) const
+{
+       cur.idx() = 1;
+       cur.pos() = cur.lastpos();
+       return true;
+}
+
+
+void InsetMathOverset::write(WriteStream & os) const
+{
+       os << "\\overset{" << cell(0) << "}{" << cell(1) << '}';
+}
+
+
+void InsetMathOverset::normalize(NormalStream & os) const
+{
+       os << "[overset " << cell(0) << ' ' << cell(1) << ']';
+}
+
+
+void InsetMathOverset::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+       InsetMathNest::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathPar.C b/src/mathed/InsetMathPar.C
deleted file mode 100644 (file)
index 8cc933e..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * \file InsetMathPar.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathPar.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-
-using std::auto_ptr;
-
-
-InsetMathPar::InsetMathPar(MathArray const & ar)
-{
-       cells_[0] = ar;
-}
-
-
-bool InsetMathPar::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       dim = dim_;
-       FontSetChanger dummy1(mi.base, "textnormal");
-       InsetMathGrid::metrics(mi);
-       if (dim_ == dim)
-               return false;
-       dim = dim_;
-       return true;
-}
-
-
-void InsetMathPar::draw(PainterInfo & pi, int x, int y) const
-{
-       FontSetChanger dummy1(pi.base, "textnormal");
-       InsetMathGrid::draw(pi, x, y);
-}
-
-
-void InsetMathPar::write(WriteStream & os) const
-{
-       for (idx_type i = 0; i < nargs(); ++i)
-               os << cell(i) << "\n";
-}
-
-
-void InsetMathPar::infoize(odocstream & os) const
-{
-       os << "Type: Paragraph ";
-}
-
-
-auto_ptr<InsetBase> InsetMathPar::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathPar(*this));
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathPar.cpp b/src/mathed/InsetMathPar.cpp
new file mode 100644 (file)
index 0000000..8cc933e
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * \file InsetMathPar.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathPar.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+
+using std::auto_ptr;
+
+
+InsetMathPar::InsetMathPar(MathArray const & ar)
+{
+       cells_[0] = ar;
+}
+
+
+bool InsetMathPar::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       dim = dim_;
+       FontSetChanger dummy1(mi.base, "textnormal");
+       InsetMathGrid::metrics(mi);
+       if (dim_ == dim)
+               return false;
+       dim = dim_;
+       return true;
+}
+
+
+void InsetMathPar::draw(PainterInfo & pi, int x, int y) const
+{
+       FontSetChanger dummy1(pi.base, "textnormal");
+       InsetMathGrid::draw(pi, x, y);
+}
+
+
+void InsetMathPar::write(WriteStream & os) const
+{
+       for (idx_type i = 0; i < nargs(); ++i)
+               os << cell(i) << "\n";
+}
+
+
+void InsetMathPar::infoize(odocstream & os) const
+{
+       os << "Type: Paragraph ";
+}
+
+
+auto_ptr<InsetBase> InsetMathPar::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathPar(*this));
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathPhantom.C b/src/mathed/InsetMathPhantom.C
deleted file mode 100644 (file)
index e4374dc..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * \file InsetMathPhantom.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Georg Baum
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathPhantom.h"
-#include "MathStream.h"
-#include "MathStream.h"
-
-#include "LColor.h"
-
-#include "frontends/Painter.h"
-
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-
-InsetMathPhantom::InsetMathPhantom(Kind k)
-       : InsetMathNest(1), kind_(k)
-{}
-
-
-std::auto_ptr<InsetBase> InsetMathPhantom::doClone() const
-{
-       return std::auto_ptr<InsetBase>(new InsetMathPhantom(*this));
-}
-
-
-bool InsetMathPhantom::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathPhantom::draw(PainterInfo & pi, int x, int y) const
-{
-       static int const arrow_size = 4;
-
-       // We first draw the text and then an arrow
-       LColor_color const origcol = pi.base.font.color();
-       pi.base.font.setColor(LColor::special);
-       cell(0).draw(pi, x + 1, y);
-       pi.base.font.setColor(origcol);
-
-       if (kind_ == phantom || kind_ == vphantom) {
-               // y1---------
-               //           / \.
-               // y2-----  / | \.
-               //            |
-               //            |
-               // y3-----  \ | /
-               //           \ /
-               // y4---------
-               //          | | |
-               //         /  |  \.
-               //        x1  x2 x3
-
-               int const x2 = x + dim_.wid / 2;
-               int const x1 = x2 - arrow_size;
-               int const x3 = x2 + arrow_size;
-
-               int const y1 = y - dim_.asc;
-               int const y2 = y1 + arrow_size;
-               int const y4 = y + dim_.des;
-               int const y3 = y4 - arrow_size;
-
-               // top arrow
-               pi.pain.line(x2, y1, x1, y2, LColor::added_space);
-               pi.pain.line(x2, y1, x3, y2, LColor::added_space);
-
-               // bottom arrow
-               pi.pain.line(x2, y4, x1, y3, LColor::added_space);
-               pi.pain.line(x2, y4, x3, y3, LColor::added_space);
-
-               // joining line
-               pi.pain.line(x2, y1, x2, y4, LColor::added_space);
-       }
-
-       if (kind_ == phantom || kind_ == hphantom) {
-               // y1----   /          \.
-               //        /              \.
-               // y2--- <---------------->
-               //        \              /
-               // y3----   \          /
-               //       |   |        |   |
-               //      x1  x2       x3  x4
-
-               int const x1 = x;
-               int const x2 = x + arrow_size;
-               int const x4 = x + dim_.wid;
-               int const x3 = x4 - arrow_size;
-
-               int const y2 = y + (dim_.des - dim_.asc) / 2;
-               int const y1 = y2 - arrow_size;
-               int const y3 = y2 + arrow_size;
-
-               // left arrow
-               pi.pain.line(x1, y2, x2, y3, LColor::added_space);
-               pi.pain.line(x1, y2, x2, y1, LColor::added_space);
-
-               // right arrow
-               pi.pain.line(x4, y2, x3, y3, LColor::added_space);
-               pi.pain.line(x4, y2, x3, y1, LColor::added_space);
-
-               // joining line
-               pi.pain.line(x1, y2, x4, y2, LColor::added_space);
-       }
-
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathPhantom::write(WriteStream & os) const
-{
-       switch (kind_) {
-       case phantom:
-               os << "\\phantom{";
-               break;
-       case vphantom:
-               os << "\\vphantom{";
-               break;
-       case hphantom:
-               os << "\\hphantom{";
-               break;
-       }
-       os << cell(0) << '}';
-}
-
-
-void InsetMathPhantom::normalize(NormalStream & os) const
-{
-       switch (kind_) {
-       case phantom:
-               os << "[phantom ";
-               break;
-       case vphantom:
-               os << "[vphantom ";
-               break;
-       case hphantom:
-               os << "[hphantom ";
-               break;
-       }
-       os << cell(0) << ']';
-}
-
-
-void InsetMathPhantom::infoize(odocstream & os) const
-{
-       switch (kind_) {
-       case phantom:
-               os << "Phantom";
-               break;
-       case vphantom:
-               os << "Vphantom";
-               break;
-       case hphantom:
-               os << "Hphantom";
-               break;
-       }
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathPhantom.cpp b/src/mathed/InsetMathPhantom.cpp
new file mode 100644 (file)
index 0000000..e4374dc
--- /dev/null
@@ -0,0 +1,177 @@
+/**
+ * \file InsetMathPhantom.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Georg Baum
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathPhantom.h"
+#include "MathStream.h"
+#include "MathStream.h"
+
+#include "LColor.h"
+
+#include "frontends/Painter.h"
+
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+
+InsetMathPhantom::InsetMathPhantom(Kind k)
+       : InsetMathNest(1), kind_(k)
+{}
+
+
+std::auto_ptr<InsetBase> InsetMathPhantom::doClone() const
+{
+       return std::auto_ptr<InsetBase>(new InsetMathPhantom(*this));
+}
+
+
+bool InsetMathPhantom::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathPhantom::draw(PainterInfo & pi, int x, int y) const
+{
+       static int const arrow_size = 4;
+
+       // We first draw the text and then an arrow
+       LColor_color const origcol = pi.base.font.color();
+       pi.base.font.setColor(LColor::special);
+       cell(0).draw(pi, x + 1, y);
+       pi.base.font.setColor(origcol);
+
+       if (kind_ == phantom || kind_ == vphantom) {
+               // y1---------
+               //           / \.
+               // y2-----  / | \.
+               //            |
+               //            |
+               // y3-----  \ | /
+               //           \ /
+               // y4---------
+               //          | | |
+               //         /  |  \.
+               //        x1  x2 x3
+
+               int const x2 = x + dim_.wid / 2;
+               int const x1 = x2 - arrow_size;
+               int const x3 = x2 + arrow_size;
+
+               int const y1 = y - dim_.asc;
+               int const y2 = y1 + arrow_size;
+               int const y4 = y + dim_.des;
+               int const y3 = y4 - arrow_size;
+
+               // top arrow
+               pi.pain.line(x2, y1, x1, y2, LColor::added_space);
+               pi.pain.line(x2, y1, x3, y2, LColor::added_space);
+
+               // bottom arrow
+               pi.pain.line(x2, y4, x1, y3, LColor::added_space);
+               pi.pain.line(x2, y4, x3, y3, LColor::added_space);
+
+               // joining line
+               pi.pain.line(x2, y1, x2, y4, LColor::added_space);
+       }
+
+       if (kind_ == phantom || kind_ == hphantom) {
+               // y1----   /          \.
+               //        /              \.
+               // y2--- <---------------->
+               //        \              /
+               // y3----   \          /
+               //       |   |        |   |
+               //      x1  x2       x3  x4
+
+               int const x1 = x;
+               int const x2 = x + arrow_size;
+               int const x4 = x + dim_.wid;
+               int const x3 = x4 - arrow_size;
+
+               int const y2 = y + (dim_.des - dim_.asc) / 2;
+               int const y1 = y2 - arrow_size;
+               int const y3 = y2 + arrow_size;
+
+               // left arrow
+               pi.pain.line(x1, y2, x2, y3, LColor::added_space);
+               pi.pain.line(x1, y2, x2, y1, LColor::added_space);
+
+               // right arrow
+               pi.pain.line(x4, y2, x3, y3, LColor::added_space);
+               pi.pain.line(x4, y2, x3, y1, LColor::added_space);
+
+               // joining line
+               pi.pain.line(x1, y2, x4, y2, LColor::added_space);
+       }
+
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathPhantom::write(WriteStream & os) const
+{
+       switch (kind_) {
+       case phantom:
+               os << "\\phantom{";
+               break;
+       case vphantom:
+               os << "\\vphantom{";
+               break;
+       case hphantom:
+               os << "\\hphantom{";
+               break;
+       }
+       os << cell(0) << '}';
+}
+
+
+void InsetMathPhantom::normalize(NormalStream & os) const
+{
+       switch (kind_) {
+       case phantom:
+               os << "[phantom ";
+               break;
+       case vphantom:
+               os << "[vphantom ";
+               break;
+       case hphantom:
+               os << "[hphantom ";
+               break;
+       }
+       os << cell(0) << ']';
+}
+
+
+void InsetMathPhantom::infoize(odocstream & os) const
+{
+       switch (kind_) {
+       case phantom:
+               os << "Phantom";
+               break;
+       case vphantom:
+               os << "Vphantom";
+               break;
+       case hphantom:
+               os << "Hphantom";
+               break;
+       }
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathRef.C b/src/mathed/InsetMathRef.C
deleted file mode 100644 (file)
index 0817fc6..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
- * \file InsetMathRef.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathRef.h"
-
-#include "BufferView.h"
-#include "LaTeXFeatures.h"
-#include "buffer.h"
-#include "cursor.h"
-#include "debug.h"
-#include "funcrequest.h"
-#include "FuncStatus.h"
-#include "gettext.h"
-#include "MathData.h"
-#include "MathFactory.h"
-#include "MathSupport.h"
-#include "outputparams.h"
-#include "sgml.h"
-
-#include "insets/InsetCommand.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::auto_ptr;
-using std::endl;
-
-
-RefInset::RefInset()
-       : CommandInset(from_ascii("ref"))
-{}
-
-
-RefInset::RefInset(docstring const & data)
-       : CommandInset(data)
-{}
-
-
-auto_ptr<InsetBase> RefInset::doClone() const
-{
-       return auto_ptr<InsetBase>(new RefInset(*this));
-}
-
-
-void RefInset::infoize(odocstream & os) const
-{
-       os << "Ref: " << cell(0);
-}
-
-
-void RefInset::doDispatch(LCursor & cur, FuncRequest & cmd)
-{
-       switch (cmd.action) {
-       case LFUN_INSET_MODIFY:
-               if (cmd.getArg(0) == "ref") {
-                       MathArray ar;
-                       if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
-                               *this = *ar[0].nucleus()->asRefInset();
-                               break;
-                       }
-               }
-               cur.undispatched();
-               break;
-
-       case LFUN_INSET_DIALOG_UPDATE: {
-               string const data = createDialogStr("ref");
-               cur.bv().updateDialog("ref", data);
-               break;
-       }
-
-       case LFUN_MOUSE_RELEASE:
-               if (cmd.button() == mouse_button::button3) {
-                       lyxerr << "trying to goto ref '" << to_utf8(asString(cell(0))) << "'" << endl;
-                       cur.bv().dispatch(FuncRequest(LFUN_LABEL_GOTO, asString(cell(0))));
-                       break;
-               }
-               if (cmd.button() == mouse_button::button1) {
-                       // Eventually trigger dialog with button 3, not 1
-                       string const data = createDialogStr("ref");
-                       cur.bv().showInsetDialog("ref", data, this);
-                       break;
-               }
-               cur.undispatched();
-               break;
-
-       case LFUN_MOUSE_PRESS:
-       case LFUN_MOUSE_MOTION:
-               // eat other mouse commands
-               break;
-
-       default:
-               CommandInset::doDispatch(cur, cmd);
-               break;
-       }
-}
-
-
-bool RefInset::getStatus(LCursor & cur, FuncRequest const & cmd,
-                        FuncStatus & status) const
-{
-       switch (cmd.action) {
-       // we handle these
-       case LFUN_INSET_MODIFY:
-       case LFUN_INSET_DIALOG_UPDATE:
-       case LFUN_MOUSE_RELEASE:
-       case LFUN_MOUSE_PRESS:
-       case LFUN_MOUSE_MOTION:
-               status.enabled(true);
-               return true;
-       default:
-               return CommandInset::getStatus(cur, cmd, status);
-       }
-}
-
-
-docstring const RefInset::screenLabel() const
-{
-       docstring str;
-       for (int i = 0; !types[i].latex_name.empty(); ++i) {
-               if (commandname() == types[i].latex_name) {
-                       str = _(to_utf8(types[i].short_gui_name));
-                       break;
-               }
-       }
-       str += asString(cell(0));
-
-       //if (/* !isLatex && */ !cell(0).empty()) {
-       //      str += "||";
-       //      str += asString(cell(1));
-       //}
-       return str;
-}
-
-
-void RefInset::validate(LaTeXFeatures & features) const
-{
-       if (commandname() == "vref" || commandname() == "vpageref")
-               features.require("varioref");
-       else if (commandname() == "prettyref")
-               features.require("prettyref");
-}
-
-
-int RefInset::docbook(Buffer const & buf, odocstream & os,
-                      OutputParams const & runparams) const
-{
-       if (cell(1).empty()) {
-               os << "<xref linkend=\""
-                  << sgml::cleanID(buf, runparams, asString(cell(0)));
-               if (runparams.flavor == OutputParams::XML)
-                       os << "\"/>";
-               else
-                       os << "\">";
-       } else {
-               os << "<link linkend=\""
-                  << sgml::cleanID(buf, runparams, asString(cell(0)))
-                  << "\">"
-                  << asString(cell(1))
-                  << "</link>";
-       }
-
-       return 0;
-}
-
-
-string const RefInset::createDialogStr(string const & name) const
-{
-       InsetCommandParams icp(to_ascii(commandname()));
-       icp["reference"] = asString(cell(0));
-       if (!cell(1).empty())
-               icp["name"] = asString(cell(1));
-       return InsetCommandMailer::params2string(name, icp);
-}
-
-
-RefInset::ref_type_info RefInset::types[] = {
-       { from_ascii("ref"),       from_ascii(N_("Standard")),              from_ascii(N_("Ref: "))},
-       { from_ascii("eqref"),     from_ascii(N_("Equation")),              from_ascii(N_("EqRef: "))},
-       { from_ascii("pageref"),   from_ascii(N_("Page Number")),           from_ascii(N_("Page: "))},
-       { from_ascii("vpageref"),  from_ascii(N_("Textual Page Number")),   from_ascii(N_("TextPage: "))},
-       { from_ascii("vref"),      from_ascii(N_("Standard+Textual Page")), from_ascii(N_("Ref+Text: "))},
-       { from_ascii("prettyref"), from_ascii(N_("PrettyRef")),             from_ascii(N_("FormatRef: "))},
-       { from_ascii(""), from_ascii(""), from_ascii("") }
-};
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathRef.cpp b/src/mathed/InsetMathRef.cpp
new file mode 100644 (file)
index 0000000..0817fc6
--- /dev/null
@@ -0,0 +1,197 @@
+/**
+ * \file InsetMathRef.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathRef.h"
+
+#include "BufferView.h"
+#include "LaTeXFeatures.h"
+#include "buffer.h"
+#include "cursor.h"
+#include "debug.h"
+#include "funcrequest.h"
+#include "FuncStatus.h"
+#include "gettext.h"
+#include "MathData.h"
+#include "MathFactory.h"
+#include "MathSupport.h"
+#include "outputparams.h"
+#include "sgml.h"
+
+#include "insets/InsetCommand.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::auto_ptr;
+using std::endl;
+
+
+RefInset::RefInset()
+       : CommandInset(from_ascii("ref"))
+{}
+
+
+RefInset::RefInset(docstring const & data)
+       : CommandInset(data)
+{}
+
+
+auto_ptr<InsetBase> RefInset::doClone() const
+{
+       return auto_ptr<InsetBase>(new RefInset(*this));
+}
+
+
+void RefInset::infoize(odocstream & os) const
+{
+       os << "Ref: " << cell(0);
+}
+
+
+void RefInset::doDispatch(LCursor & cur, FuncRequest & cmd)
+{
+       switch (cmd.action) {
+       case LFUN_INSET_MODIFY:
+               if (cmd.getArg(0) == "ref") {
+                       MathArray ar;
+                       if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
+                               *this = *ar[0].nucleus()->asRefInset();
+                               break;
+                       }
+               }
+               cur.undispatched();
+               break;
+
+       case LFUN_INSET_DIALOG_UPDATE: {
+               string const data = createDialogStr("ref");
+               cur.bv().updateDialog("ref", data);
+               break;
+       }
+
+       case LFUN_MOUSE_RELEASE:
+               if (cmd.button() == mouse_button::button3) {
+                       lyxerr << "trying to goto ref '" << to_utf8(asString(cell(0))) << "'" << endl;
+                       cur.bv().dispatch(FuncRequest(LFUN_LABEL_GOTO, asString(cell(0))));
+                       break;
+               }
+               if (cmd.button() == mouse_button::button1) {
+                       // Eventually trigger dialog with button 3, not 1
+                       string const data = createDialogStr("ref");
+                       cur.bv().showInsetDialog("ref", data, this);
+                       break;
+               }
+               cur.undispatched();
+               break;
+
+       case LFUN_MOUSE_PRESS:
+       case LFUN_MOUSE_MOTION:
+               // eat other mouse commands
+               break;
+
+       default:
+               CommandInset::doDispatch(cur, cmd);
+               break;
+       }
+}
+
+
+bool RefInset::getStatus(LCursor & cur, FuncRequest const & cmd,
+                        FuncStatus & status) const
+{
+       switch (cmd.action) {
+       // we handle these
+       case LFUN_INSET_MODIFY:
+       case LFUN_INSET_DIALOG_UPDATE:
+       case LFUN_MOUSE_RELEASE:
+       case LFUN_MOUSE_PRESS:
+       case LFUN_MOUSE_MOTION:
+               status.enabled(true);
+               return true;
+       default:
+               return CommandInset::getStatus(cur, cmd, status);
+       }
+}
+
+
+docstring const RefInset::screenLabel() const
+{
+       docstring str;
+       for (int i = 0; !types[i].latex_name.empty(); ++i) {
+               if (commandname() == types[i].latex_name) {
+                       str = _(to_utf8(types[i].short_gui_name));
+                       break;
+               }
+       }
+       str += asString(cell(0));
+
+       //if (/* !isLatex && */ !cell(0).empty()) {
+       //      str += "||";
+       //      str += asString(cell(1));
+       //}
+       return str;
+}
+
+
+void RefInset::validate(LaTeXFeatures & features) const
+{
+       if (commandname() == "vref" || commandname() == "vpageref")
+               features.require("varioref");
+       else if (commandname() == "prettyref")
+               features.require("prettyref");
+}
+
+
+int RefInset::docbook(Buffer const & buf, odocstream & os,
+                      OutputParams const & runparams) const
+{
+       if (cell(1).empty()) {
+               os << "<xref linkend=\""
+                  << sgml::cleanID(buf, runparams, asString(cell(0)));
+               if (runparams.flavor == OutputParams::XML)
+                       os << "\"/>";
+               else
+                       os << "\">";
+       } else {
+               os << "<link linkend=\""
+                  << sgml::cleanID(buf, runparams, asString(cell(0)))
+                  << "\">"
+                  << asString(cell(1))
+                  << "</link>";
+       }
+
+       return 0;
+}
+
+
+string const RefInset::createDialogStr(string const & name) const
+{
+       InsetCommandParams icp(to_ascii(commandname()));
+       icp["reference"] = asString(cell(0));
+       if (!cell(1).empty())
+               icp["name"] = asString(cell(1));
+       return InsetCommandMailer::params2string(name, icp);
+}
+
+
+RefInset::ref_type_info RefInset::types[] = {
+       { from_ascii("ref"),       from_ascii(N_("Standard")),              from_ascii(N_("Ref: "))},
+       { from_ascii("eqref"),     from_ascii(N_("Equation")),              from_ascii(N_("EqRef: "))},
+       { from_ascii("pageref"),   from_ascii(N_("Page Number")),           from_ascii(N_("Page: "))},
+       { from_ascii("vpageref"),  from_ascii(N_("Textual Page Number")),   from_ascii(N_("TextPage: "))},
+       { from_ascii("vref"),      from_ascii(N_("Standard+Textual Page")), from_ascii(N_("Ref+Text: "))},
+       { from_ascii("prettyref"), from_ascii(N_("PrettyRef")),             from_ascii(N_("FormatRef: "))},
+       { from_ascii(""), from_ascii(""), from_ascii("") }
+};
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathRoot.C b/src/mathed/InsetMathRoot.C
deleted file mode 100644 (file)
index 0d81239..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * \file InsetMathRoot.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathRoot.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "cursor.h"
-#include "LColor.h"
-
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-using std::max;
-using std::auto_ptr;
-
-
-
-InsetMathRoot::InsetMathRoot()
-       : InsetMathNest(2)
-{}
-
-
-auto_ptr<InsetBase> InsetMathRoot::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathRoot(*this));
-}
-
-
-bool InsetMathRoot::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       InsetMathNest::metrics(mi);
-       dim.asc = max(cell(0).ascent()  + 5, cell(1).ascent())  + 2;
-       dim.des = max(cell(0).descent() - 5, cell(1).descent()) + 2;
-       dim.wid = cell(0).width() + cell(1).width() + 10;
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathRoot::draw(PainterInfo & pi, int x, int y) const
-{
-       int const w = cell(0).width();
-       // the "exponent"
-       cell(0).draw(pi, x, y - 5 - cell(0).descent());
-       // the "base"
-       cell(1).draw(pi, x + w + 8, y);
-       int const a = dim_.ascent();
-       int const d = dim_.descent();
-       int xp[5];
-       int yp[5];
-       xp[0] = x + dim_.width();  yp[0] = y - a + 1;
-       xp[1] = x + w + 4;         yp[1] = y - a + 1;
-       xp[2] = x + w;             yp[2] = y + d;
-       xp[3] = x + w - 2;         yp[3] = y + (d - a)/2 + 2;
-       xp[4] = x + w - 5;         yp[4] = y + (d - a)/2 + 4;
-       pi.pain.lines(xp, yp, 5, LColor::math);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathRoot::write(WriteStream & os) const
-{
-       os << "\\sqrt[" << cell(0) << "]{" << cell(1) << '}';
-}
-
-
-void InsetMathRoot::normalize(NormalStream & os) const
-{
-       os << "[root " << cell(0) << ' ' << cell(1) << ']';
-}
-
-
-bool InsetMathRoot::idxUpDown(LCursor & cur, bool up) const
-{
-       LCursor::idx_type const target = up ? 0 : 1;
-       if (cur.idx() == target)
-               return false;
-       cur.idx() = target;
-       cur.pos() = up ? cur.lastpos() : 0;
-       return true;
-}
-
-
-void InsetMathRoot::maple(MapleStream & os) const
-{
-       os << '(' << cell(1) << ")^(1/(" << cell(0) <<"))";
-}
-
-
-void InsetMathRoot::mathematica(MathematicaStream & os) const
-{
-       os << '(' << cell(1) << ")^(1/(" << cell(0) <<"))";
-}
-
-
-void InsetMathRoot::octave(OctaveStream & os) const
-{
-       os << '(' << cell(1) << ")^(1/(" << cell(0) <<"))";
-}
-
-
-void InsetMathRoot::mathmlize(MathStream & os) const
-{
-       os << MTag("mroot") << cell(1) << cell(0) << ETag("mroot");
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathRoot.cpp b/src/mathed/InsetMathRoot.cpp
new file mode 100644 (file)
index 0000000..0d81239
--- /dev/null
@@ -0,0 +1,123 @@
+/**
+ * \file InsetMathRoot.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathRoot.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "cursor.h"
+#include "LColor.h"
+
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+using std::max;
+using std::auto_ptr;
+
+
+
+InsetMathRoot::InsetMathRoot()
+       : InsetMathNest(2)
+{}
+
+
+auto_ptr<InsetBase> InsetMathRoot::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathRoot(*this));
+}
+
+
+bool InsetMathRoot::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       InsetMathNest::metrics(mi);
+       dim.asc = max(cell(0).ascent()  + 5, cell(1).ascent())  + 2;
+       dim.des = max(cell(0).descent() - 5, cell(1).descent()) + 2;
+       dim.wid = cell(0).width() + cell(1).width() + 10;
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathRoot::draw(PainterInfo & pi, int x, int y) const
+{
+       int const w = cell(0).width();
+       // the "exponent"
+       cell(0).draw(pi, x, y - 5 - cell(0).descent());
+       // the "base"
+       cell(1).draw(pi, x + w + 8, y);
+       int const a = dim_.ascent();
+       int const d = dim_.descent();
+       int xp[5];
+       int yp[5];
+       xp[0] = x + dim_.width();  yp[0] = y - a + 1;
+       xp[1] = x + w + 4;         yp[1] = y - a + 1;
+       xp[2] = x + w;             yp[2] = y + d;
+       xp[3] = x + w - 2;         yp[3] = y + (d - a)/2 + 2;
+       xp[4] = x + w - 5;         yp[4] = y + (d - a)/2 + 4;
+       pi.pain.lines(xp, yp, 5, LColor::math);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathRoot::write(WriteStream & os) const
+{
+       os << "\\sqrt[" << cell(0) << "]{" << cell(1) << '}';
+}
+
+
+void InsetMathRoot::normalize(NormalStream & os) const
+{
+       os << "[root " << cell(0) << ' ' << cell(1) << ']';
+}
+
+
+bool InsetMathRoot::idxUpDown(LCursor & cur, bool up) const
+{
+       LCursor::idx_type const target = up ? 0 : 1;
+       if (cur.idx() == target)
+               return false;
+       cur.idx() = target;
+       cur.pos() = up ? cur.lastpos() : 0;
+       return true;
+}
+
+
+void InsetMathRoot::maple(MapleStream & os) const
+{
+       os << '(' << cell(1) << ")^(1/(" << cell(0) <<"))";
+}
+
+
+void InsetMathRoot::mathematica(MathematicaStream & os) const
+{
+       os << '(' << cell(1) << ")^(1/(" << cell(0) <<"))";
+}
+
+
+void InsetMathRoot::octave(OctaveStream & os) const
+{
+       os << '(' << cell(1) << ")^(1/(" << cell(0) <<"))";
+}
+
+
+void InsetMathRoot::mathmlize(MathStream & os) const
+{
+       os << MTag("mroot") << cell(1) << cell(0) << ETag("mroot");
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathScript.C b/src/mathed/InsetMathScript.C
deleted file mode 100644 (file)
index 3080b60..0000000
+++ /dev/null
@@ -1,715 +0,0 @@
-/**
- * \file InsetMathScript.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathScript.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "InsetMathSymbol.h"
-#include "InsetMathFont.h"
-#include "dispatchresult.h"
-#include "cursor.h"
-#include "debug.h"
-#include "funcrequest.h"
-#include "undo.h"
-
-#include <boost/assert.hpp>
-
-
-namespace lyx {
-
-using std::string;
-using std::max;
-using std::auto_ptr;
-using std::endl;
-
-
-
-InsetMathScript::InsetMathScript()
-       : InsetMathNest(1), cell_1_is_up_(false), limits_(0)
-{}
-
-
-InsetMathScript::InsetMathScript(bool up)
-       : InsetMathNest(2), cell_1_is_up_(up), limits_(0)
-{}
-
-
-InsetMathScript::InsetMathScript(MathAtom const & at, bool up)
-       : InsetMathNest(2), cell_1_is_up_(up), limits_(0)
-{
-       BOOST_ASSERT(nargs() >= 1);
-       cell(0).push_back(at);
-}
-
-
-auto_ptr<InsetBase> InsetMathScript::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathScript(*this));
-}
-
-
-InsetMathScript const * InsetMathScript::asScriptInset() const
-{
-       return this;
-}
-
-
-InsetMathScript * InsetMathScript::asScriptInset()
-{
-       return this;
-}
-
-
-bool InsetMathScript::idxFirst(LCursor & cur) const
-{
-       cur.idx() = 0;
-       cur.pos() = 0;
-       return true;
-}
-
-
-bool InsetMathScript::idxLast(LCursor & cur) const
-{
-       cur.idx() = 0;
-       cur.pos() = nuc().size();
-       return true;
-}
-
-
-MathArray const & InsetMathScript::down() const
-{
-       if (nargs() == 3)
-               return cell(2);
-       BOOST_ASSERT(nargs() > 1);
-       return cell(1);
-}
-
-
-MathArray & InsetMathScript::down()
-{
-       if (nargs() == 3)
-               return cell(2);
-       BOOST_ASSERT(nargs() > 1);
-       return cell(1);
-}
-
-
-MathArray const & InsetMathScript::up() const
-{
-       BOOST_ASSERT(nargs() > 1);
-       return cell(1);
-}
-
-
-MathArray & InsetMathScript::up()
-{
-       BOOST_ASSERT(nargs() > 1);
-       return cell(1);
-}
-
-
-void InsetMathScript::ensure(bool up)
-{
-       if (nargs() == 1) {
-               // just nucleus so far
-               cells_.push_back(MathArray());
-               cell_1_is_up_ = up;
-       } else if (nargs() == 2 && !has(up)) {
-               if (up) {
-                       cells_.push_back(cell(1));
-                       cell(1).clear();
-               } else {
-                       cells_.push_back(MathArray());
-               }
-       }
-}
-
-
-MathArray const & InsetMathScript::nuc() const
-{
-       return cell(0);
-}
-
-
-MathArray & InsetMathScript::nuc()
-{
-       return cell(0);
-}
-
-
-namespace {
-
-bool isAlphaSymbol(MathAtom const & at)
-{
-       if (at->asCharInset() ||
-                       (at->asSymbolInset() &&
-                        at->asSymbolInset()->isOrdAlpha()))
-               return true;
-
-       if (at->asFontInset()) {
-               MathArray const & ar = at->asFontInset()->cell(0);
-               for (size_t i = 0; i < ar.size(); ++i) {
-                       if (!(ar[i]->asCharInset() ||
-                                       (ar[i]->asSymbolInset() &&
-                                        ar[i]->asSymbolInset()->isOrdAlpha())))
-                               return false;
-               }
-               return true;
-       }
-       return false;
-}
-
-} // namespace anon
-
-
-int InsetMathScript::dy01(int asc, int des, int what) const
-{
-       int dasc = 0;
-       int slevel = 0;
-       bool isCharBox = nuc().size() ? isAlphaSymbol(nuc().back()) : false;
-       if (hasDown()) {
-               dasc = down().ascent();
-               slevel = nuc().slevel();
-               int ascdrop = dasc - slevel;
-               int desdrop = isCharBox ? 0 : des + nuc().sshift();
-               int mindes = nuc().mindes();
-               des = max(desdrop, ascdrop);
-               des = max(mindes, des);
-       }
-       if (hasUp()) {
-               int minasc = nuc().minasc();
-               int ascdrop = isCharBox ? 0 : asc - up().mindes();
-               int udes = up().descent();
-               asc = udes + nuc().sshift();
-               asc = max(ascdrop, asc);
-               asc = max(minasc, asc);
-               if (hasDown()) {
-                       int del = asc - udes - dasc;
-                       if (del + des <= 2) {
-                               int newdes = 2 - del;
-                               del = slevel - asc + udes;
-                               if (del > 0) {
-                                       asc += del;
-                                       newdes -= del;
-                               }
-                               des = max(des, newdes);
-                       }
-               }
-       }
-       return what ? asc : des;
-}
-
-
-int InsetMathScript::dy0() const
-{
-       int nd = ndes();
-       if (!hasDown())
-               return nd;
-       int des = down().ascent();
-       if (hasLimits())
-               des += nd + 2;
-       else {
-               int na = nasc();
-               des = dy01(na, nd, 0);
-       }
-       return des;
-}
-
-
-int InsetMathScript::dy1() const
-{
-       int na = nasc();
-       if (!hasUp())
-               return na;
-       int asc = up().descent();
-       if (hasLimits())
-               asc += na + 2;
-       else {
-               int nd = ndes();
-               asc = dy01(na, nd, 1);
-       }
-       asc = max(asc, 5);
-       return asc;
-}
-
-
-int InsetMathScript::dx0() const
-{
-       BOOST_ASSERT(hasDown());
-       return hasLimits() ? (dim_.wid - down().width()) / 2 : nwid();
-}
-
-
-int InsetMathScript::dx1() const
-{
-       BOOST_ASSERT(hasUp());
-       return hasLimits() ? (dim_.wid - up().width()) / 2 : nwid() + nker();
-}
-
-
-int InsetMathScript::dxx() const
-{
-       return hasLimits() ? (dim_.wid - nwid()) / 2  :  0;
-}
-
-
-int InsetMathScript::nwid() const
-{
-       return nuc().size() ? nuc().width() : 2;
-}
-
-
-int InsetMathScript::nasc() const
-{
-       return nuc().size() ? nuc().ascent() : 5;
-}
-
-
-int InsetMathScript::ndes() const
-{
-       return nuc().size() ? nuc().descent() : 0;
-}
-
-
-int InsetMathScript::nker() const
-{
-       if (nuc().size()) {
-               int kerning = nuc().kerning();
-               return kerning > 0 ? kerning : 0;
-       }
-       return 0;
-}
-
-
-bool InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi);
-       ScriptChanger dummy(mi.base);
-       if (nargs() > 1)
-               cell(1).metrics(mi);
-       if (nargs() > 2)
-               cell(2).metrics(mi);
-       dim.wid = 0;
-       if (hasLimits()) {
-               dim.wid = nwid();
-               if (hasUp())
-                       dim.wid = max(dim.wid, up().width());
-               if (hasDown())
-                       dim.wid = max(dim.wid, down().width());
-       } else {
-               if (hasUp())
-                       dim.wid = max(dim.wid, nker() + up().width());
-               if (hasDown())
-                       dim.wid = max(dim.wid, down().width());
-               dim.wid += nwid();
-       }
-       int na = nasc();
-       if (hasUp()) {
-               int asc = dy1() + up().ascent();
-               dim.asc = max(na, asc);
-       } else
-               dim.asc = na;
-       int nd = ndes();
-       if (hasDown()) {
-               int des = dy0() + down().descent();
-               dim.des = max(nd, des);
-       } else
-               dim.des = nd;
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathScript::draw(PainterInfo & pi, int x, int y) const
-{
-       if (nuc().size())
-               nuc().draw(pi, x + dxx(), y);
-       else {
-               nuc().setXY(*pi.base.bv, x + dxx(), y);
-               if (editing(pi.base.bv))
-                        pi.draw(x + dxx(), y, char_type('.'));
-       }
-       ScriptChanger dummy(pi.base);
-       if (hasUp())
-               up().draw(pi, x + dx1(), y - dy1());
-       if (hasDown())
-               down().draw(pi, x + dx0(), y + dy0());
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathScript::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       if (hasUp())
-               up().metricsT(mi, dim);
-       if (hasDown())
-               down().metricsT(mi, dim);
-       nuc().metricsT(mi, dim);
-}
-
-
-void InsetMathScript::drawT(TextPainter & pain, int x, int y) const
-{
-       if (nuc().size())
-               nuc().drawT(pain, x + dxx(), y);
-       if (hasUp())
-               up().drawT(pain, x + dx1(), y - dy1());
-       if (hasDown())
-               down().drawT(pain, x + dx0(), y + dy0());
-}
-
-
-
-bool InsetMathScript::hasLimits() const
-{
-       // obvious cases
-       if (limits_ == 1)
-               return true;
-       if (limits_ == -1)
-               return false;
-
-       // we can only display limits if the nucleus wants some
-       if (!nuc().size())
-               return false;
-       if (!nuc().back()->isScriptable())
-               return false;
-
-       if (nuc().back()->asSymbolInset()) {
-               // \intop is an alias for \int\limits, \ointop == \oint\limits
-               if (nuc().back()->asSymbolInset()->name().find(from_ascii("intop")) != string::npos)
-                       return true;
-               // per default \int has limits beside the \int even in displayed formulas
-               if (nuc().back()->asSymbolInset()->name().find(from_ascii("int")) != string::npos)
-                       return false;
-       }
-
-       // assume "real" limits for everything else
-       return true;
-}
-
-
-void InsetMathScript::removeScript(bool up)
-{
-       if (nargs() == 2) {
-               if (up == cell_1_is_up_)
-                       cells_.pop_back();
-       } else if (nargs() == 3) {
-               if (up == true) {
-                       swap(cells_[1], cells_[2]);
-                       cell_1_is_up_ = false;
-               } else {
-                       cell_1_is_up_ = true;
-               }
-               cells_.pop_back();
-       }
-}
-
-
-bool InsetMathScript::has(bool up) const
-{
-       return idxOfScript(up);
-}
-
-
-bool InsetMathScript::hasUp() const
-{
-       //lyxerr << "1up: " << bool(cell_1_is_up_) << endl;
-       //lyxerr << "hasUp: " << bool(idxOfScript(true)) << endl;
-       return idxOfScript(true);
-}
-
-
-bool InsetMathScript::hasDown() const
-{
-       //lyxerr << "1up: " << bool(cell_1_is_up_) << endl;
-       //lyxerr << "hasDown: " << bool(idxOfScript(false)) << endl;
-       return idxOfScript(false);
-}
-
-
-InsetBase::idx_type InsetMathScript::idxOfScript(bool up) const
-{
-       if (nargs() == 1)
-               return 0;
-       if (nargs() == 2)
-               return (cell_1_is_up_ == up) ? 1 : 0;
-       if (nargs() == 3)
-               return up ? 1 : 2;
-       BOOST_ASSERT(false);
-       // Silence compiler
-       return 0;
-}
-
-
-bool InsetMathScript::idxRight(LCursor &) const
-{
-       return false;
-}
-
-
-bool InsetMathScript::idxLeft(LCursor &) const
-{
-       return false;
-}
-
-
-bool InsetMathScript::idxUpDown(LCursor & cur, bool up) const
-{
-       // in nucleus?
-       if (cur.idx() == 0) {
-               // don't go up/down if there is no cell in this direction
-               if (!has(up))
-                       return false;
-               // go up/down only if in the last position
-               // or in the first position of something with displayed limits
-               if (cur.pos() == cur.lastpos() || (cur.pos() == 0 && hasLimits())) {
-                       cur.idx() = idxOfScript(up);
-                       cur.pos() = 0;
-                       return true;
-               }
-               return false;
-       }
-
-       // Are we 'up'?
-       if (has(up) && cur.idx() == idxOfScript(true)) {
-               // can't go further up
-               if (up)
-                       return false;
-               // otherwise go to last position in the nucleus
-               cur.idx() = 0;
-               cur.pos() = cur.lastpos();
-               return true;
-       }
-
-       // Are we 'down'?
-       if (has(up) && cur.idx() == idxOfScript(false)) {
-               // can't go further down
-               if (!up)
-                       return false;
-               // otherwise go to last position in the nucleus
-               cur.idx() = 0;
-               cur.pos() = cur.lastpos();
-               return true;
-       }
-
-       return false;
-}
-
-
-void InsetMathScript::write(WriteStream & os) const
-{
-       if (nuc().size()) {
-               os << nuc();
-               //if (nuc().back()->takesLimits()) {
-                       if (limits_ == -1)
-                               os << "\\nolimits ";
-                       if (limits_ == 1)
-                               os << "\\limits ";
-               //}
-       } else {
-               if (os.firstitem())
-                       LYXERR(Debug::MATHED) << "suppressing {} when writing"
-                                             << endl;
-               else
-                       os << "{}";
-       }
-
-       if (hasDown() /*&& down().size()*/)
-               os << "_{" << down() << '}';
-
-       if (hasUp() /*&& up().size()*/)
-               os << "^{" << up() << '}';
-
-       if (lock_ && !os.latex())
-               os << "\\lyxlock ";
-}
-
-
-void InsetMathScript::normalize(NormalStream & os) const
-{
-       bool d = hasDown() && down().size();
-       bool u = hasUp() && up().size();
-
-       if (u && d)
-               os << "[subsup ";
-       else if (u)
-               os << "[sup ";
-       else if (d)
-               os << "[sub ";
-
-       if (nuc().size())
-               os << nuc() << ' ';
-       else
-               os << "[par]";
-
-       if (u && d)
-               os << down() << ' ' << up() << ']';
-       else if (d)
-               os << down() << ']';
-       else if (u)
-               os << up() << ']';
-}
-
-
-void InsetMathScript::maple(MapleStream & os) const
-{
-       if (nuc().size())
-               os << nuc();
-       if (hasDown() && down().size())
-               os << '[' << down() << ']';
-       if (hasUp() && up().size())
-               os << "^(" << up() << ')';
-}
-
-
-void InsetMathScript::mathematica(MathematicaStream & os) const
-{
-       bool d = hasDown() && down().size();
-       bool u = hasUp() && up().size();
-
-       if (nuc().size()) {
-               if (d)
-                       os << "Subscript[" << nuc();
-               else
-                       os << nuc();
-       }
-
-       if (u)
-               os << "^(" << up() << ')';
-
-       if (nuc().size()) {
-               if (d)
-                       os << ',' << down() << ']';
-       }
-}
-
-
-void InsetMathScript::mathmlize(MathStream & os) const
-{
-       bool d = hasDown() && down().size();
-       bool u = hasUp() && up().size();
-
-       if (u && d)
-               os << MTag("msubsup");
-       else if (u)
-               os << MTag("msup");
-       else if (d)
-               os << MTag("msub");
-
-       if (nuc().size())
-               os << nuc();
-       else
-               os << "<mrow/>";
-
-       if (u && d)
-               os << down() << up() << ETag("msubsup");
-       else if (u)
-               os << up() << ETag("msup");
-       else if (d)
-               os << down() << ETag("msub");
-}
-
-
-void InsetMathScript::octave(OctaveStream & os) const
-{
-       if (nuc().size())
-               os << nuc();
-       if (hasDown() && down().size())
-               os << '[' << down() << ']';
-       if (hasUp() && up().size())
-               os << "^(" << up() << ')';
-}
-
-
-void InsetMathScript::infoize(odocstream & os) const
-{
-       os << "Scripts";
-}
-
-
-void InsetMathScript::infoize2(odocstream & os) const
-{
-       if (limits_)
-               os << (limits_ == 1 ? ", Displayed limits" : ", Inlined limits");
-}
-
-
-bool InsetMathScript::notifyCursorLeaves(LCursor & cur)
-{
-       InsetMathNest::notifyCursorLeaves(cur);
-
-       //lyxerr << "InsetMathScript::notifyCursorLeaves: 1 " << cur << endl;
-
-       // remove empty scripts if possible
-       if (nargs() > 2) {
-               // Case of two scripts. In this case, 1 = super, 2 = sub
-               if (cur.idx() == 2 && cell(2).empty()) {
-                       // must be a subscript...
-                       recordUndoInset(cur);
-                       removeScript(false);
-                       return true;
-               } else if (cur.idx() == 1 && cell(1).empty()) {
-                       // must be a superscript...
-                       recordUndoInset(cur);
-                       removeScript(true);
-                       return true;
-               }
-       } else if (nargs() > 1 && cur.idx() == 1 && cell(1).empty()) {
-               // could be either subscript or super script
-               recordUndoInset(cur);
-               removeScript(cell_1_is_up_);
-               // Let the script inset commit suicide. This is
-               // modelled on LCursor.pullArg(), but tries not to
-               // invoke notifyCursorLeaves again and does not touch
-               // cur (since the top slice will be deleted
-               // afterwards))
-               MathArray ar = cell(0);
-               LCursor tmpcur = cur;
-               tmpcur.pop();
-               tmpcur.cell().erase(tmpcur.pos());
-               tmpcur.cell().insert(tmpcur.pos(), ar);
-               return true;
-       }
-
-       //lyxerr << "InsetMathScript::notifyCursorLeaves: 2 " << cur << endl;
-       return false;
-}
-
-
-void InsetMathScript::doDispatch(LCursor & cur, FuncRequest & cmd)
-{
-       //lyxerr << "InsetMathScript: request: " << cmd << std::endl;
-
-       if (cmd.action == LFUN_MATH_LIMITS) {
-               if (!cmd.argument().empty()) {
-                       if (cmd.argument() == "limits")
-                               limits_ = 1;
-                       else if (cmd.argument() == "nolimits")
-                               limits_ = -1;
-                       else
-                               limits_ = 0;
-               } else if (limits_ == 0)
-                       limits_ = hasLimits() ? -1 : 1;
-               else
-                       limits_ = 0;
-               return;
-       }
-
-       InsetMathNest::doDispatch(cur, cmd);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathScript.cpp b/src/mathed/InsetMathScript.cpp
new file mode 100644 (file)
index 0000000..3080b60
--- /dev/null
@@ -0,0 +1,715 @@
+/**
+ * \file InsetMathScript.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathScript.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "InsetMathSymbol.h"
+#include "InsetMathFont.h"
+#include "dispatchresult.h"
+#include "cursor.h"
+#include "debug.h"
+#include "funcrequest.h"
+#include "undo.h"
+
+#include <boost/assert.hpp>
+
+
+namespace lyx {
+
+using std::string;
+using std::max;
+using std::auto_ptr;
+using std::endl;
+
+
+
+InsetMathScript::InsetMathScript()
+       : InsetMathNest(1), cell_1_is_up_(false), limits_(0)
+{}
+
+
+InsetMathScript::InsetMathScript(bool up)
+       : InsetMathNest(2), cell_1_is_up_(up), limits_(0)
+{}
+
+
+InsetMathScript::InsetMathScript(MathAtom const & at, bool up)
+       : InsetMathNest(2), cell_1_is_up_(up), limits_(0)
+{
+       BOOST_ASSERT(nargs() >= 1);
+       cell(0).push_back(at);
+}
+
+
+auto_ptr<InsetBase> InsetMathScript::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathScript(*this));
+}
+
+
+InsetMathScript const * InsetMathScript::asScriptInset() const
+{
+       return this;
+}
+
+
+InsetMathScript * InsetMathScript::asScriptInset()
+{
+       return this;
+}
+
+
+bool InsetMathScript::idxFirst(LCursor & cur) const
+{
+       cur.idx() = 0;
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathScript::idxLast(LCursor & cur) const
+{
+       cur.idx() = 0;
+       cur.pos() = nuc().size();
+       return true;
+}
+
+
+MathArray const & InsetMathScript::down() const
+{
+       if (nargs() == 3)
+               return cell(2);
+       BOOST_ASSERT(nargs() > 1);
+       return cell(1);
+}
+
+
+MathArray & InsetMathScript::down()
+{
+       if (nargs() == 3)
+               return cell(2);
+       BOOST_ASSERT(nargs() > 1);
+       return cell(1);
+}
+
+
+MathArray const & InsetMathScript::up() const
+{
+       BOOST_ASSERT(nargs() > 1);
+       return cell(1);
+}
+
+
+MathArray & InsetMathScript::up()
+{
+       BOOST_ASSERT(nargs() > 1);
+       return cell(1);
+}
+
+
+void InsetMathScript::ensure(bool up)
+{
+       if (nargs() == 1) {
+               // just nucleus so far
+               cells_.push_back(MathArray());
+               cell_1_is_up_ = up;
+       } else if (nargs() == 2 && !has(up)) {
+               if (up) {
+                       cells_.push_back(cell(1));
+                       cell(1).clear();
+               } else {
+                       cells_.push_back(MathArray());
+               }
+       }
+}
+
+
+MathArray const & InsetMathScript::nuc() const
+{
+       return cell(0);
+}
+
+
+MathArray & InsetMathScript::nuc()
+{
+       return cell(0);
+}
+
+
+namespace {
+
+bool isAlphaSymbol(MathAtom const & at)
+{
+       if (at->asCharInset() ||
+                       (at->asSymbolInset() &&
+                        at->asSymbolInset()->isOrdAlpha()))
+               return true;
+
+       if (at->asFontInset()) {
+               MathArray const & ar = at->asFontInset()->cell(0);
+               for (size_t i = 0; i < ar.size(); ++i) {
+                       if (!(ar[i]->asCharInset() ||
+                                       (ar[i]->asSymbolInset() &&
+                                        ar[i]->asSymbolInset()->isOrdAlpha())))
+                               return false;
+               }
+               return true;
+       }
+       return false;
+}
+
+} // namespace anon
+
+
+int InsetMathScript::dy01(int asc, int des, int what) const
+{
+       int dasc = 0;
+       int slevel = 0;
+       bool isCharBox = nuc().size() ? isAlphaSymbol(nuc().back()) : false;
+       if (hasDown()) {
+               dasc = down().ascent();
+               slevel = nuc().slevel();
+               int ascdrop = dasc - slevel;
+               int desdrop = isCharBox ? 0 : des + nuc().sshift();
+               int mindes = nuc().mindes();
+               des = max(desdrop, ascdrop);
+               des = max(mindes, des);
+       }
+       if (hasUp()) {
+               int minasc = nuc().minasc();
+               int ascdrop = isCharBox ? 0 : asc - up().mindes();
+               int udes = up().descent();
+               asc = udes + nuc().sshift();
+               asc = max(ascdrop, asc);
+               asc = max(minasc, asc);
+               if (hasDown()) {
+                       int del = asc - udes - dasc;
+                       if (del + des <= 2) {
+                               int newdes = 2 - del;
+                               del = slevel - asc + udes;
+                               if (del > 0) {
+                                       asc += del;
+                                       newdes -= del;
+                               }
+                               des = max(des, newdes);
+                       }
+               }
+       }
+       return what ? asc : des;
+}
+
+
+int InsetMathScript::dy0() const
+{
+       int nd = ndes();
+       if (!hasDown())
+               return nd;
+       int des = down().ascent();
+       if (hasLimits())
+               des += nd + 2;
+       else {
+               int na = nasc();
+               des = dy01(na, nd, 0);
+       }
+       return des;
+}
+
+
+int InsetMathScript::dy1() const
+{
+       int na = nasc();
+       if (!hasUp())
+               return na;
+       int asc = up().descent();
+       if (hasLimits())
+               asc += na + 2;
+       else {
+               int nd = ndes();
+               asc = dy01(na, nd, 1);
+       }
+       asc = max(asc, 5);
+       return asc;
+}
+
+
+int InsetMathScript::dx0() const
+{
+       BOOST_ASSERT(hasDown());
+       return hasLimits() ? (dim_.wid - down().width()) / 2 : nwid();
+}
+
+
+int InsetMathScript::dx1() const
+{
+       BOOST_ASSERT(hasUp());
+       return hasLimits() ? (dim_.wid - up().width()) / 2 : nwid() + nker();
+}
+
+
+int InsetMathScript::dxx() const
+{
+       return hasLimits() ? (dim_.wid - nwid()) / 2  :  0;
+}
+
+
+int InsetMathScript::nwid() const
+{
+       return nuc().size() ? nuc().width() : 2;
+}
+
+
+int InsetMathScript::nasc() const
+{
+       return nuc().size() ? nuc().ascent() : 5;
+}
+
+
+int InsetMathScript::ndes() const
+{
+       return nuc().size() ? nuc().descent() : 0;
+}
+
+
+int InsetMathScript::nker() const
+{
+       if (nuc().size()) {
+               int kerning = nuc().kerning();
+               return kerning > 0 ? kerning : 0;
+       }
+       return 0;
+}
+
+
+bool InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi);
+       ScriptChanger dummy(mi.base);
+       if (nargs() > 1)
+               cell(1).metrics(mi);
+       if (nargs() > 2)
+               cell(2).metrics(mi);
+       dim.wid = 0;
+       if (hasLimits()) {
+               dim.wid = nwid();
+               if (hasUp())
+                       dim.wid = max(dim.wid, up().width());
+               if (hasDown())
+                       dim.wid = max(dim.wid, down().width());
+       } else {
+               if (hasUp())
+                       dim.wid = max(dim.wid, nker() + up().width());
+               if (hasDown())
+                       dim.wid = max(dim.wid, down().width());
+               dim.wid += nwid();
+       }
+       int na = nasc();
+       if (hasUp()) {
+               int asc = dy1() + up().ascent();
+               dim.asc = max(na, asc);
+       } else
+               dim.asc = na;
+       int nd = ndes();
+       if (hasDown()) {
+               int des = dy0() + down().descent();
+               dim.des = max(nd, des);
+       } else
+               dim.des = nd;
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathScript::draw(PainterInfo & pi, int x, int y) const
+{
+       if (nuc().size())
+               nuc().draw(pi, x + dxx(), y);
+       else {
+               nuc().setXY(*pi.base.bv, x + dxx(), y);
+               if (editing(pi.base.bv))
+                        pi.draw(x + dxx(), y, char_type('.'));
+       }
+       ScriptChanger dummy(pi.base);
+       if (hasUp())
+               up().draw(pi, x + dx1(), y - dy1());
+       if (hasDown())
+               down().draw(pi, x + dx0(), y + dy0());
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathScript::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       if (hasUp())
+               up().metricsT(mi, dim);
+       if (hasDown())
+               down().metricsT(mi, dim);
+       nuc().metricsT(mi, dim);
+}
+
+
+void InsetMathScript::drawT(TextPainter & pain, int x, int y) const
+{
+       if (nuc().size())
+               nuc().drawT(pain, x + dxx(), y);
+       if (hasUp())
+               up().drawT(pain, x + dx1(), y - dy1());
+       if (hasDown())
+               down().drawT(pain, x + dx0(), y + dy0());
+}
+
+
+
+bool InsetMathScript::hasLimits() const
+{
+       // obvious cases
+       if (limits_ == 1)
+               return true;
+       if (limits_ == -1)
+               return false;
+
+       // we can only display limits if the nucleus wants some
+       if (!nuc().size())
+               return false;
+       if (!nuc().back()->isScriptable())
+               return false;
+
+       if (nuc().back()->asSymbolInset()) {
+               // \intop is an alias for \int\limits, \ointop == \oint\limits
+               if (nuc().back()->asSymbolInset()->name().find(from_ascii("intop")) != string::npos)
+                       return true;
+               // per default \int has limits beside the \int even in displayed formulas
+               if (nuc().back()->asSymbolInset()->name().find(from_ascii("int")) != string::npos)
+                       return false;
+       }
+
+       // assume "real" limits for everything else
+       return true;
+}
+
+
+void InsetMathScript::removeScript(bool up)
+{
+       if (nargs() == 2) {
+               if (up == cell_1_is_up_)
+                       cells_.pop_back();
+       } else if (nargs() == 3) {
+               if (up == true) {
+                       swap(cells_[1], cells_[2]);
+                       cell_1_is_up_ = false;
+               } else {
+                       cell_1_is_up_ = true;
+               }
+               cells_.pop_back();
+       }
+}
+
+
+bool InsetMathScript::has(bool up) const
+{
+       return idxOfScript(up);
+}
+
+
+bool InsetMathScript::hasUp() const
+{
+       //lyxerr << "1up: " << bool(cell_1_is_up_) << endl;
+       //lyxerr << "hasUp: " << bool(idxOfScript(true)) << endl;
+       return idxOfScript(true);
+}
+
+
+bool InsetMathScript::hasDown() const
+{
+       //lyxerr << "1up: " << bool(cell_1_is_up_) << endl;
+       //lyxerr << "hasDown: " << bool(idxOfScript(false)) << endl;
+       return idxOfScript(false);
+}
+
+
+InsetBase::idx_type InsetMathScript::idxOfScript(bool up) const
+{
+       if (nargs() == 1)
+               return 0;
+       if (nargs() == 2)
+               return (cell_1_is_up_ == up) ? 1 : 0;
+       if (nargs() == 3)
+               return up ? 1 : 2;
+       BOOST_ASSERT(false);
+       // Silence compiler
+       return 0;
+}
+
+
+bool InsetMathScript::idxRight(LCursor &) const
+{
+       return false;
+}
+
+
+bool InsetMathScript::idxLeft(LCursor &) const
+{
+       return false;
+}
+
+
+bool InsetMathScript::idxUpDown(LCursor & cur, bool up) const
+{
+       // in nucleus?
+       if (cur.idx() == 0) {
+               // don't go up/down if there is no cell in this direction
+               if (!has(up))
+                       return false;
+               // go up/down only if in the last position
+               // or in the first position of something with displayed limits
+               if (cur.pos() == cur.lastpos() || (cur.pos() == 0 && hasLimits())) {
+                       cur.idx() = idxOfScript(up);
+                       cur.pos() = 0;
+                       return true;
+               }
+               return false;
+       }
+
+       // Are we 'up'?
+       if (has(up) && cur.idx() == idxOfScript(true)) {
+               // can't go further up
+               if (up)
+                       return false;
+               // otherwise go to last position in the nucleus
+               cur.idx() = 0;
+               cur.pos() = cur.lastpos();
+               return true;
+       }
+
+       // Are we 'down'?
+       if (has(up) && cur.idx() == idxOfScript(false)) {
+               // can't go further down
+               if (!up)
+                       return false;
+               // otherwise go to last position in the nucleus
+               cur.idx() = 0;
+               cur.pos() = cur.lastpos();
+               return true;
+       }
+
+       return false;
+}
+
+
+void InsetMathScript::write(WriteStream & os) const
+{
+       if (nuc().size()) {
+               os << nuc();
+               //if (nuc().back()->takesLimits()) {
+                       if (limits_ == -1)
+                               os << "\\nolimits ";
+                       if (limits_ == 1)
+                               os << "\\limits ";
+               //}
+       } else {
+               if (os.firstitem())
+                       LYXERR(Debug::MATHED) << "suppressing {} when writing"
+                                             << endl;
+               else
+                       os << "{}";
+       }
+
+       if (hasDown() /*&& down().size()*/)
+               os << "_{" << down() << '}';
+
+       if (hasUp() /*&& up().size()*/)
+               os << "^{" << up() << '}';
+
+       if (lock_ && !os.latex())
+               os << "\\lyxlock ";
+}
+
+
+void InsetMathScript::normalize(NormalStream & os) const
+{
+       bool d = hasDown() && down().size();
+       bool u = hasUp() && up().size();
+
+       if (u && d)
+               os << "[subsup ";
+       else if (u)
+               os << "[sup ";
+       else if (d)
+               os << "[sub ";
+
+       if (nuc().size())
+               os << nuc() << ' ';
+       else
+               os << "[par]";
+
+       if (u && d)
+               os << down() << ' ' << up() << ']';
+       else if (d)
+               os << down() << ']';
+       else if (u)
+               os << up() << ']';
+}
+
+
+void InsetMathScript::maple(MapleStream & os) const
+{
+       if (nuc().size())
+               os << nuc();
+       if (hasDown() && down().size())
+               os << '[' << down() << ']';
+       if (hasUp() && up().size())
+               os << "^(" << up() << ')';
+}
+
+
+void InsetMathScript::mathematica(MathematicaStream & os) const
+{
+       bool d = hasDown() && down().size();
+       bool u = hasUp() && up().size();
+
+       if (nuc().size()) {
+               if (d)
+                       os << "Subscript[" << nuc();
+               else
+                       os << nuc();
+       }
+
+       if (u)
+               os << "^(" << up() << ')';
+
+       if (nuc().size()) {
+               if (d)
+                       os << ',' << down() << ']';
+       }
+}
+
+
+void InsetMathScript::mathmlize(MathStream & os) const
+{
+       bool d = hasDown() && down().size();
+       bool u = hasUp() && up().size();
+
+       if (u && d)
+               os << MTag("msubsup");
+       else if (u)
+               os << MTag("msup");
+       else if (d)
+               os << MTag("msub");
+
+       if (nuc().size())
+               os << nuc();
+       else
+               os << "<mrow/>";
+
+       if (u && d)
+               os << down() << up() << ETag("msubsup");
+       else if (u)
+               os << up() << ETag("msup");
+       else if (d)
+               os << down() << ETag("msub");
+}
+
+
+void InsetMathScript::octave(OctaveStream & os) const
+{
+       if (nuc().size())
+               os << nuc();
+       if (hasDown() && down().size())
+               os << '[' << down() << ']';
+       if (hasUp() && up().size())
+               os << "^(" << up() << ')';
+}
+
+
+void InsetMathScript::infoize(odocstream & os) const
+{
+       os << "Scripts";
+}
+
+
+void InsetMathScript::infoize2(odocstream & os) const
+{
+       if (limits_)
+               os << (limits_ == 1 ? ", Displayed limits" : ", Inlined limits");
+}
+
+
+bool InsetMathScript::notifyCursorLeaves(LCursor & cur)
+{
+       InsetMathNest::notifyCursorLeaves(cur);
+
+       //lyxerr << "InsetMathScript::notifyCursorLeaves: 1 " << cur << endl;
+
+       // remove empty scripts if possible
+       if (nargs() > 2) {
+               // Case of two scripts. In this case, 1 = super, 2 = sub
+               if (cur.idx() == 2 && cell(2).empty()) {
+                       // must be a subscript...
+                       recordUndoInset(cur);
+                       removeScript(false);
+                       return true;
+               } else if (cur.idx() == 1 && cell(1).empty()) {
+                       // must be a superscript...
+                       recordUndoInset(cur);
+                       removeScript(true);
+                       return true;
+               }
+       } else if (nargs() > 1 && cur.idx() == 1 && cell(1).empty()) {
+               // could be either subscript or super script
+               recordUndoInset(cur);
+               removeScript(cell_1_is_up_);
+               // Let the script inset commit suicide. This is
+               // modelled on LCursor.pullArg(), but tries not to
+               // invoke notifyCursorLeaves again and does not touch
+               // cur (since the top slice will be deleted
+               // afterwards))
+               MathArray ar = cell(0);
+               LCursor tmpcur = cur;
+               tmpcur.pop();
+               tmpcur.cell().erase(tmpcur.pos());
+               tmpcur.cell().insert(tmpcur.pos(), ar);
+               return true;
+       }
+
+       //lyxerr << "InsetMathScript::notifyCursorLeaves: 2 " << cur << endl;
+       return false;
+}
+
+
+void InsetMathScript::doDispatch(LCursor & cur, FuncRequest & cmd)
+{
+       //lyxerr << "InsetMathScript: request: " << cmd << std::endl;
+
+       if (cmd.action == LFUN_MATH_LIMITS) {
+               if (!cmd.argument().empty()) {
+                       if (cmd.argument() == "limits")
+                               limits_ = 1;
+                       else if (cmd.argument() == "nolimits")
+                               limits_ = -1;
+                       else
+                               limits_ = 0;
+               } else if (limits_ == 0)
+                       limits_ = hasLimits() ? -1 : 1;
+               else
+                       limits_ = 0;
+               return;
+       }
+
+       InsetMathNest::doDispatch(cur, cmd);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathSize.C b/src/mathed/InsetMathSize.C
deleted file mode 100644 (file)
index 23eb698..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * \file InsetMathSize.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathSize.h"
-#include "MathData.h"
-#include "MathParser.h"
-#include "MathStream.h"
-
-#include "support/convert.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathSize::InsetMathSize(latexkeys const * l)
-       : InsetMathNest(1), key_(l), style_(Styles(convert<int>(l->extra)))
-{}
-
-
-auto_ptr<InsetBase> InsetMathSize::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathSize(*this));
-}
-
-
-bool InsetMathSize::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       StyleChanger dummy(mi.base, style_);
-       cell(0).metrics(mi, dim);
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathSize::draw(PainterInfo & pi, int x, int y) const
-{
-       StyleChanger dummy(pi.base, style_);
-       cell(0).draw(pi, x + 1, y);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathSize::write(WriteStream & os) const
-{
-       os << "{\\" << key_->name << ' ' << cell(0) << '}';
-}
-
-
-void InsetMathSize::normalize(NormalStream & os) const
-{
-       os << '[' << key_->name << ' ' << cell(0) << ']';
-}
-
-
-void InsetMathSize::infoize(odocstream & os) const
-{
-       os << "Size: " << key_->name;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathSize.cpp b/src/mathed/InsetMathSize.cpp
new file mode 100644 (file)
index 0000000..23eb698
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ * \file InsetMathSize.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathSize.h"
+#include "MathData.h"
+#include "MathParser.h"
+#include "MathStream.h"
+
+#include "support/convert.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathSize::InsetMathSize(latexkeys const * l)
+       : InsetMathNest(1), key_(l), style_(Styles(convert<int>(l->extra)))
+{}
+
+
+auto_ptr<InsetBase> InsetMathSize::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathSize(*this));
+}
+
+
+bool InsetMathSize::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       StyleChanger dummy(mi.base, style_);
+       cell(0).metrics(mi, dim);
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathSize::draw(PainterInfo & pi, int x, int y) const
+{
+       StyleChanger dummy(pi.base, style_);
+       cell(0).draw(pi, x + 1, y);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathSize::write(WriteStream & os) const
+{
+       os << "{\\" << key_->name << ' ' << cell(0) << '}';
+}
+
+
+void InsetMathSize::normalize(NormalStream & os) const
+{
+       os << '[' << key_->name << ' ' << cell(0) << ']';
+}
+
+
+void InsetMathSize::infoize(odocstream & os) const
+{
+       os << "Size: " << key_->name;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathSpace.C b/src/mathed/InsetMathSpace.C
deleted file mode 100644 (file)
index 8d3df09..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * \file InsetMathSpace.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathSpace.h"
-#include "MathData.h"
-#include "MathStream.h"
-
-#include "LaTeXFeatures.h"
-#include "LColor.h"
-
-#include "frontends/Painter.h"
-
-using std::string;
-using std::auto_ptr;
-
-
-namespace lyx {
-
-char const * latex_mathspace[] = {
-       "!", "negmedspace", "negthickspace",  // negative space
-       ",", ":", ";", "quad", "qquad",       // positive space
-       "lyxnegspace", "lyxposspace"          // LyX special ("unvisible space")
-};
-
-int const nSpace = sizeof(latex_mathspace)/sizeof(char *);
-
-namespace {
-
-int spaceToWidth(int space)
-{
-       switch (space) {
-               case 0: return 6;
-               case 1: return 8;
-               case 2: return 10;
-               case 3: return 6;
-               case 4: return 8;
-               case 5: return 10;
-               case 6: return 20;
-               case 7: return 40;
-               case 8: return -2;
-               case 9: return  2;
-               default: return 6;
-       }
-}
-
-} // anon namespace
-
-InsetMathSpace::InsetMathSpace(int sp)
-       : space_(sp)
-{
-       dim_.asc = 4;
-       dim_.des = 0;
-       dim_.wid = spaceToWidth(space_);
-}
-
-
-InsetMathSpace::InsetMathSpace(docstring const & name)
-       : space_(1)
-{
-       dim_.asc = 4;
-       dim_.des = 0;
-       for (int i = 0; i < nSpace; ++i)
-               if (latex_mathspace[i] == name)
-                       space_ = i;
-       dim_.wid = spaceToWidth(space_);
-}
-
-
-auto_ptr<InsetBase> InsetMathSpace::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathSpace(*this));
-}
-
-
-bool InsetMathSpace::metrics(MetricsInfo &, Dimension & dim) const
-{
-       dim.wid = width();
-       dim.asc = ascent();
-       dim.des = descent();
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathSpace::draw(PainterInfo & pi, int x, int y) const
-{
-       // Sadly, HP-UX CC can't handle that kind of initialization.
-       // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
-       if (space_ >= nSpace - 2)
-               return;
-
-       int xp[4];
-       int yp[4];
-       int w = width();
-
-       xp[0] = ++x;        yp[0] = y - 3;
-       xp[1] = x;          yp[1] = y;
-       xp[2] = x + w - 2;  yp[2] = y;
-       xp[3] = x + w - 2;  yp[3] = y - 3;
-
-       pi.pain.lines(xp, yp, 4, (space_ < 3) ? LColor::latex : LColor::math);
-}
-
-
-void InsetMathSpace::incSpace()
-{
-       space_ = (space_ + 1) % (nSpace - 2);
-       dim_.wid = spaceToWidth(space_);
-}
-
-
-void InsetMathSpace::validate(LaTeXFeatures & features) const
-{
-       if (space_ >= 0 && space_< nSpace) {
-               if ((latex_mathspace[space_] == string("negmedspace"))
-                || (latex_mathspace[space_] == string("negthickspace")))
-                       features.require("amsmath");
-       }
-}
-
-
-void InsetMathSpace::maple(MapleStream & os) const
-{
-       os << ' ';
-}
-
-void InsetMathSpace::mathematica(MathematicaStream & os) const
-{
-       os << ' ';
-}
-
-
-void InsetMathSpace::octave(OctaveStream & os) const
-{
-       os << ' ';
-}
-
-
-void InsetMathSpace::normalize(NormalStream & os) const
-{
-       os << "[space " << int(space_) << "] ";
-}
-
-
-void InsetMathSpace::write(WriteStream & os) const
-{
-       if (space_ >= 0 && space_ < nSpace) {
-               os << '\\' << latex_mathspace[space_];
-               os.pendingSpace(true);
-       }
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathSpace.cpp b/src/mathed/InsetMathSpace.cpp
new file mode 100644 (file)
index 0000000..8d3df09
--- /dev/null
@@ -0,0 +1,165 @@
+/**
+ * \file InsetMathSpace.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathSpace.h"
+#include "MathData.h"
+#include "MathStream.h"
+
+#include "LaTeXFeatures.h"
+#include "LColor.h"
+
+#include "frontends/Painter.h"
+
+using std::string;
+using std::auto_ptr;
+
+
+namespace lyx {
+
+char const * latex_mathspace[] = {
+       "!", "negmedspace", "negthickspace",  // negative space
+       ",", ":", ";", "quad", "qquad",       // positive space
+       "lyxnegspace", "lyxposspace"          // LyX special ("unvisible space")
+};
+
+int const nSpace = sizeof(latex_mathspace)/sizeof(char *);
+
+namespace {
+
+int spaceToWidth(int space)
+{
+       switch (space) {
+               case 0: return 6;
+               case 1: return 8;
+               case 2: return 10;
+               case 3: return 6;
+               case 4: return 8;
+               case 5: return 10;
+               case 6: return 20;
+               case 7: return 40;
+               case 8: return -2;
+               case 9: return  2;
+               default: return 6;
+       }
+}
+
+} // anon namespace
+
+InsetMathSpace::InsetMathSpace(int sp)
+       : space_(sp)
+{
+       dim_.asc = 4;
+       dim_.des = 0;
+       dim_.wid = spaceToWidth(space_);
+}
+
+
+InsetMathSpace::InsetMathSpace(docstring const & name)
+       : space_(1)
+{
+       dim_.asc = 4;
+       dim_.des = 0;
+       for (int i = 0; i < nSpace; ++i)
+               if (latex_mathspace[i] == name)
+                       space_ = i;
+       dim_.wid = spaceToWidth(space_);
+}
+
+
+auto_ptr<InsetBase> InsetMathSpace::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathSpace(*this));
+}
+
+
+bool InsetMathSpace::metrics(MetricsInfo &, Dimension & dim) const
+{
+       dim.wid = width();
+       dim.asc = ascent();
+       dim.des = descent();
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathSpace::draw(PainterInfo & pi, int x, int y) const
+{
+       // Sadly, HP-UX CC can't handle that kind of initialization.
+       // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
+       if (space_ >= nSpace - 2)
+               return;
+
+       int xp[4];
+       int yp[4];
+       int w = width();
+
+       xp[0] = ++x;        yp[0] = y - 3;
+       xp[1] = x;          yp[1] = y;
+       xp[2] = x + w - 2;  yp[2] = y;
+       xp[3] = x + w - 2;  yp[3] = y - 3;
+
+       pi.pain.lines(xp, yp, 4, (space_ < 3) ? LColor::latex : LColor::math);
+}
+
+
+void InsetMathSpace::incSpace()
+{
+       space_ = (space_ + 1) % (nSpace - 2);
+       dim_.wid = spaceToWidth(space_);
+}
+
+
+void InsetMathSpace::validate(LaTeXFeatures & features) const
+{
+       if (space_ >= 0 && space_< nSpace) {
+               if ((latex_mathspace[space_] == string("negmedspace"))
+                || (latex_mathspace[space_] == string("negthickspace")))
+                       features.require("amsmath");
+       }
+}
+
+
+void InsetMathSpace::maple(MapleStream & os) const
+{
+       os << ' ';
+}
+
+void InsetMathSpace::mathematica(MathematicaStream & os) const
+{
+       os << ' ';
+}
+
+
+void InsetMathSpace::octave(OctaveStream & os) const
+{
+       os << ' ';
+}
+
+
+void InsetMathSpace::normalize(NormalStream & os) const
+{
+       os << "[space " << int(space_) << "] ";
+}
+
+
+void InsetMathSpace::write(WriteStream & os) const
+{
+       if (space_ >= 0 && space_ < nSpace) {
+               os << '\\' << latex_mathspace[space_];
+               os.pendingSpace(true);
+       }
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathSplit.C b/src/mathed/InsetMathSplit.C
deleted file mode 100644 (file)
index a8575ac..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * \file InsetMathSplit.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathSplit.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-
-#include "funcrequest.h"
-#include "FuncStatus.h"
-#include "gettext.h"
-#include "LaTeXFeatures.h"
-
-#include "support/lstrings.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-using support::bformat;
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathSplit::InsetMathSplit(docstring const & name, char valign)
-       : InsetMathGrid(1, 1, valign, docstring()), name_(name)
-{
-}
-
-
-auto_ptr<InsetBase> InsetMathSplit::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathSplit(*this));
-}
-
-
-char InsetMathSplit::defaultColAlign(col_type col)
-{
-       if (name_ == "split")
-               return 'l';
-       if (name_ == "gathered")
-               return 'c';
-       if (name_ == "aligned")
-               return (col & 1) ? 'l' : 'r';
-       if (name_ == "alignedat")
-               return (col & 1) ? 'l' : 'r';
-       return 'l';
-}
-
-
-void InsetMathSplit::draw(PainterInfo & pi, int x, int y) const
-{
-       InsetMathGrid::draw(pi, x, y);
-       setPosCache(pi, x, y);
-}
-
-
-bool InsetMathSplit::getStatus(LCursor & cur, FuncRequest const & cmd,
-               FuncStatus & flag) const
-{
-       switch (cmd.action) {
-       case LFUN_TABULAR_FEATURE: {
-               docstring const & s = cmd.argument();
-               if (s == "add-vline-left" || s == "add-vline-right") {
-                       flag.message(bformat(
-                               from_utf8(N_("Can't add vertical grid lines in '%1$s'")),       name_));
-                       flag.enabled(false);
-                       return true;
-               }
-               return InsetMathGrid::getStatus(cur, cmd, flag);
-       }
-       default:
-               return InsetMathGrid::getStatus(cur, cmd, flag);
-       }
-}
-
-
-void InsetMathSplit::write(WriteStream & ws) const
-{
-       if (ws.fragile())
-               ws << "\\protect";
-       ws << "\\begin{" << name_ << '}';
-       if (name_ != "split" && valign() != 'c')
-               ws << '[' << valign() << ']';
-       if (name_ == "alignedat")
-               ws << '{' << static_cast<unsigned int>((ncols() + 1)/2) << '}';
-       InsetMathGrid::write(ws);
-       if (ws.fragile())
-               ws << "\\protect";
-       ws << "\\end{" << name_ << "}\n";
-}
-
-
-void InsetMathSplit::infoize(odocstream & os) const
-{
-       docstring name = name_;
-       name[0] = support::uppercase(name[0]);
-       os << name << ' ';
-}
-
-
-void InsetMathSplit::validate(LaTeXFeatures & features) const
-{
-       if (name_ == "split" || name_ == "gathered" || name_ == "aligned" ||
-           name_ == "alignedat")
-               features.require("amsmath");
-       InsetMathGrid::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathSplit.cpp b/src/mathed/InsetMathSplit.cpp
new file mode 100644 (file)
index 0000000..a8575ac
--- /dev/null
@@ -0,0 +1,121 @@
+/**
+ * \file InsetMathSplit.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathSplit.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+
+#include "funcrequest.h"
+#include "FuncStatus.h"
+#include "gettext.h"
+#include "LaTeXFeatures.h"
+
+#include "support/lstrings.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+using support::bformat;
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathSplit::InsetMathSplit(docstring const & name, char valign)
+       : InsetMathGrid(1, 1, valign, docstring()), name_(name)
+{
+}
+
+
+auto_ptr<InsetBase> InsetMathSplit::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathSplit(*this));
+}
+
+
+char InsetMathSplit::defaultColAlign(col_type col)
+{
+       if (name_ == "split")
+               return 'l';
+       if (name_ == "gathered")
+               return 'c';
+       if (name_ == "aligned")
+               return (col & 1) ? 'l' : 'r';
+       if (name_ == "alignedat")
+               return (col & 1) ? 'l' : 'r';
+       return 'l';
+}
+
+
+void InsetMathSplit::draw(PainterInfo & pi, int x, int y) const
+{
+       InsetMathGrid::draw(pi, x, y);
+       setPosCache(pi, x, y);
+}
+
+
+bool InsetMathSplit::getStatus(LCursor & cur, FuncRequest const & cmd,
+               FuncStatus & flag) const
+{
+       switch (cmd.action) {
+       case LFUN_TABULAR_FEATURE: {
+               docstring const & s = cmd.argument();
+               if (s == "add-vline-left" || s == "add-vline-right") {
+                       flag.message(bformat(
+                               from_utf8(N_("Can't add vertical grid lines in '%1$s'")),       name_));
+                       flag.enabled(false);
+                       return true;
+               }
+               return InsetMathGrid::getStatus(cur, cmd, flag);
+       }
+       default:
+               return InsetMathGrid::getStatus(cur, cmd, flag);
+       }
+}
+
+
+void InsetMathSplit::write(WriteStream & ws) const
+{
+       if (ws.fragile())
+               ws << "\\protect";
+       ws << "\\begin{" << name_ << '}';
+       if (name_ != "split" && valign() != 'c')
+               ws << '[' << valign() << ']';
+       if (name_ == "alignedat")
+               ws << '{' << static_cast<unsigned int>((ncols() + 1)/2) << '}';
+       InsetMathGrid::write(ws);
+       if (ws.fragile())
+               ws << "\\protect";
+       ws << "\\end{" << name_ << "}\n";
+}
+
+
+void InsetMathSplit::infoize(odocstream & os) const
+{
+       docstring name = name_;
+       name[0] = support::uppercase(name[0]);
+       os << name << ' ';
+}
+
+
+void InsetMathSplit::validate(LaTeXFeatures & features) const
+{
+       if (name_ == "split" || name_ == "gathered" || name_ == "aligned" ||
+           name_ == "alignedat")
+               features.require("amsmath");
+       InsetMathGrid::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathSqrt.C b/src/mathed/InsetMathSqrt.C
deleted file mode 100644 (file)
index 55d773c..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * \file InsetMathSqrt.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathSqrt.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "TextPainter.h"
-#include "LColor.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-
-
-InsetMathSqrt::InsetMathSqrt()
-       : InsetMathNest(1)
-{}
-
-
-auto_ptr<InsetBase> InsetMathSqrt::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathSqrt(*this));
-}
-
-
-bool InsetMathSqrt::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(0).metrics(mi, dim);
-       dim.asc += 4;
-       dim.des += 2;
-       dim.wid += 12;
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathSqrt::draw(PainterInfo & pi, int x, int y) const
-{
-       cell(0).draw(pi, x + 10, y);
-       int const a = dim_.ascent();
-       int const d = dim_.descent();
-       int xp[4];
-       int yp[4];
-       xp[0] = x + dim_.width(); yp[0] = y - a + 1;
-       xp[1] = x + 8;            yp[1] = y - a + 1;
-       xp[2] = x + 5;            yp[2] = y + d - 1;
-       xp[3] = x;                yp[3] = y + (d - a)/2;
-       pi.pain.lines(xp, yp, 4, LColor::math);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathSqrt::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       cell(0).metricsT(mi, dim);
-       dim.asc += 1;
-       dim.wid += 2;
-}
-
-
-void InsetMathSqrt::drawT(TextPainter & pain, int x, int y) const
-{
-       cell(0).drawT(pain, x + 2, y);
-       pain.horizontalLine(x + 2, y - cell(0).ascent(), cell(0).width(), '_');
-       pain.verticalLine  (x + 1, y - cell(0).ascent() + 1, cell(0).height());
-       pain.draw(x, y + cell(0).descent(), '\\');
-}
-
-
-void InsetMathSqrt::write(WriteStream & os) const
-{
-       os << "\\sqrt{" << cell(0) << '}';
-}
-
-
-void InsetMathSqrt::normalize(NormalStream & os) const
-{
-       os << "[sqrt " << cell(0) << ']';
-}
-
-void InsetMathSqrt::maple(MapleStream & os) const
-{
-       os << "sqrt(" << cell(0) << ')';
-}
-
-void InsetMathSqrt::mathematica(MathematicaStream & os) const
-{
-       os << "Sqrt[" << cell(0) << ']';
-}
-
-
-void InsetMathSqrt::octave(OctaveStream & os) const
-{
-       os << "sqrt(" << cell(0) << ')';
-}
-
-
-void InsetMathSqrt::mathmlize(MathStream & os) const
-{
-       os << MTag("msqrt") << cell(0) << ETag("msqrt");
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathSqrt.cpp b/src/mathed/InsetMathSqrt.cpp
new file mode 100644 (file)
index 0000000..55d773c
--- /dev/null
@@ -0,0 +1,118 @@
+/**
+ * \file InsetMathSqrt.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathSqrt.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "TextPainter.h"
+#include "LColor.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+
+
+InsetMathSqrt::InsetMathSqrt()
+       : InsetMathNest(1)
+{}
+
+
+auto_ptr<InsetBase> InsetMathSqrt::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathSqrt(*this));
+}
+
+
+bool InsetMathSqrt::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(0).metrics(mi, dim);
+       dim.asc += 4;
+       dim.des += 2;
+       dim.wid += 12;
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathSqrt::draw(PainterInfo & pi, int x, int y) const
+{
+       cell(0).draw(pi, x + 10, y);
+       int const a = dim_.ascent();
+       int const d = dim_.descent();
+       int xp[4];
+       int yp[4];
+       xp[0] = x + dim_.width(); yp[0] = y - a + 1;
+       xp[1] = x + 8;            yp[1] = y - a + 1;
+       xp[2] = x + 5;            yp[2] = y + d - 1;
+       xp[3] = x;                yp[3] = y + (d - a)/2;
+       pi.pain.lines(xp, yp, 4, LColor::math);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathSqrt::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       cell(0).metricsT(mi, dim);
+       dim.asc += 1;
+       dim.wid += 2;
+}
+
+
+void InsetMathSqrt::drawT(TextPainter & pain, int x, int y) const
+{
+       cell(0).drawT(pain, x + 2, y);
+       pain.horizontalLine(x + 2, y - cell(0).ascent(), cell(0).width(), '_');
+       pain.verticalLine  (x + 1, y - cell(0).ascent() + 1, cell(0).height());
+       pain.draw(x, y + cell(0).descent(), '\\');
+}
+
+
+void InsetMathSqrt::write(WriteStream & os) const
+{
+       os << "\\sqrt{" << cell(0) << '}';
+}
+
+
+void InsetMathSqrt::normalize(NormalStream & os) const
+{
+       os << "[sqrt " << cell(0) << ']';
+}
+
+void InsetMathSqrt::maple(MapleStream & os) const
+{
+       os << "sqrt(" << cell(0) << ')';
+}
+
+void InsetMathSqrt::mathematica(MathematicaStream & os) const
+{
+       os << "Sqrt[" << cell(0) << ']';
+}
+
+
+void InsetMathSqrt::octave(OctaveStream & os) const
+{
+       os << "sqrt(" << cell(0) << ')';
+}
+
+
+void InsetMathSqrt::mathmlize(MathStream & os) const
+{
+       os << MTag("msqrt") << cell(0) << ETag("msqrt");
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathStackrel.C b/src/mathed/InsetMathStackrel.C
deleted file mode 100644 (file)
index 9f1a9ba..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * \file InsetMathStackrel.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathStackrel.h"
-#include "MathData.h"
-#include "MathStream.h"
-
-
-namespace lyx {
-
-
-using std::max;
-using std::auto_ptr;
-
-
-InsetMathStackrel::InsetMathStackrel()
-{}
-
-
-auto_ptr<InsetBase> InsetMathStackrel::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathStackrel(*this));
-}
-
-
-bool InsetMathStackrel::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(1).metrics(mi);
-       FracChanger dummy(mi.base);
-       cell(0).metrics(mi);
-       dim.wid = max(cell(0).width(), cell(1).width()) + 4;
-       dim.asc = cell(1).ascent() + cell(0).height() + 4;
-       dim.des = cell(1).descent();
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathStackrel::draw(PainterInfo & pi, int x, int y) const
-{
-       int m  = x + dim_.width() / 2;
-       int yo = y - cell(1).ascent() - cell(0).descent() - 1;
-       cell(1).draw(pi, m - cell(1).width() / 2, y);
-       FracChanger dummy(pi.base);
-       cell(0).draw(pi, m - cell(0).width() / 2, yo);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathStackrel::write(WriteStream & os) const
-{
-       os << "\\stackrel{" << cell(0) << "}{" << cell(1) << '}';
-}
-
-
-void InsetMathStackrel::normalize(NormalStream & os) const
-{
-       os << "[stackrel " << cell(0) << ' ' << cell(1) << ']';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathStackrel.cpp b/src/mathed/InsetMathStackrel.cpp
new file mode 100644 (file)
index 0000000..9f1a9ba
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * \file InsetMathStackrel.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathStackrel.h"
+#include "MathData.h"
+#include "MathStream.h"
+
+
+namespace lyx {
+
+
+using std::max;
+using std::auto_ptr;
+
+
+InsetMathStackrel::InsetMathStackrel()
+{}
+
+
+auto_ptr<InsetBase> InsetMathStackrel::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathStackrel(*this));
+}
+
+
+bool InsetMathStackrel::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(1).metrics(mi);
+       FracChanger dummy(mi.base);
+       cell(0).metrics(mi);
+       dim.wid = max(cell(0).width(), cell(1).width()) + 4;
+       dim.asc = cell(1).ascent() + cell(0).height() + 4;
+       dim.des = cell(1).descent();
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathStackrel::draw(PainterInfo & pi, int x, int y) const
+{
+       int m  = x + dim_.width() / 2;
+       int yo = y - cell(1).ascent() - cell(0).descent() - 1;
+       cell(1).draw(pi, m - cell(1).width() / 2, y);
+       FracChanger dummy(pi.base);
+       cell(0).draw(pi, m - cell(0).width() / 2, yo);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathStackrel::write(WriteStream & os) const
+{
+       os << "\\stackrel{" << cell(0) << "}{" << cell(1) << '}';
+}
+
+
+void InsetMathStackrel::normalize(NormalStream & os) const
+{
+       os << "[stackrel " << cell(0) << ' ' << cell(1) << ']';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathString.C b/src/mathed/InsetMathString.C
deleted file mode 100644 (file)
index ab4a137..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * \file InsetMathString.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathString.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-
-
-namespace lyx {
-
-using std::auto_ptr;
-using std::vector;
-
-
-InsetMathString::InsetMathString(docstring const & s)
-       : str_(s)
-{}
-
-
-auto_ptr<InsetBase> InsetMathString::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathString(*this));
-}
-
-
-bool InsetMathString::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       mathed_string_dim(mi.base.font, str_, dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathString::draw(PainterInfo & pi, int x, int y) const
-{
-       pi.draw(x, y, str_);
-}
-
-
-void InsetMathString::normalize(NormalStream & os) const
-{
-       os << "[string " << str_ << ' ' << "mathalpha" << ']';
-}
-
-
-void InsetMathString::maple(MapleStream & os) const
-{
-       if (/*code_ != LM_TC_VAR ||*/ str_.size() <= 1) {
-               os << ' ' << str_ << ' ';
-               return;
-       }
-
-       // insert '*' between adjacent chars if type is LM_TC_VAR
-       os << str_[0];
-       for (size_t i = 1; i < str_.size(); ++i)
-               os << str_[i];
-}
-
-
-void InsetMathString::mathematica(MathematicaStream & os) const
-{
-       os << ' ' << str_ << ' ';
-}
-
-
-void InsetMathString::octave(OctaveStream & os) const
-{
-       if (/*code_ != LM_TC_VAR ||*/ str_.size() <= 1) {
-               os << ' ' << str_ << ' ';
-               return;
-       }
-
-       // insert '*' between adjacent chars if type is LM_TC_VAR
-       os << str_[0];
-       for (size_t i = 1; i < str_.size(); ++i)
-               os << str_[i];
-}
-
-
-void InsetMathString::mathmlize(MathStream & os) const
-{
-/*
-       if (code_ == LM_TC_VAR)
-               os << "<mi> " << str_ << " </mi>";
-       else if (code_ == LM_TC_CONST)
-               os << "<mn> " << str_ << " </mn>";
-       else if (code_ == LM_TC_RM || code_ == LM_TC_TEXTRM)
-               os << "<mtext> " << str_ <<  " </mtext>";
-       else
-*/
-               os << str_;
-}
-
-
-void InsetMathString::write(WriteStream & os) const
-{
-       os << str_;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathString.cpp b/src/mathed/InsetMathString.cpp
new file mode 100644 (file)
index 0000000..ab4a137
--- /dev/null
@@ -0,0 +1,113 @@
+/**
+ * \file InsetMathString.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathString.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+
+
+namespace lyx {
+
+using std::auto_ptr;
+using std::vector;
+
+
+InsetMathString::InsetMathString(docstring const & s)
+       : str_(s)
+{}
+
+
+auto_ptr<InsetBase> InsetMathString::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathString(*this));
+}
+
+
+bool InsetMathString::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       mathed_string_dim(mi.base.font, str_, dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathString::draw(PainterInfo & pi, int x, int y) const
+{
+       pi.draw(x, y, str_);
+}
+
+
+void InsetMathString::normalize(NormalStream & os) const
+{
+       os << "[string " << str_ << ' ' << "mathalpha" << ']';
+}
+
+
+void InsetMathString::maple(MapleStream & os) const
+{
+       if (/*code_ != LM_TC_VAR ||*/ str_.size() <= 1) {
+               os << ' ' << str_ << ' ';
+               return;
+       }
+
+       // insert '*' between adjacent chars if type is LM_TC_VAR
+       os << str_[0];
+       for (size_t i = 1; i < str_.size(); ++i)
+               os << str_[i];
+}
+
+
+void InsetMathString::mathematica(MathematicaStream & os) const
+{
+       os << ' ' << str_ << ' ';
+}
+
+
+void InsetMathString::octave(OctaveStream & os) const
+{
+       if (/*code_ != LM_TC_VAR ||*/ str_.size() <= 1) {
+               os << ' ' << str_ << ' ';
+               return;
+       }
+
+       // insert '*' between adjacent chars if type is LM_TC_VAR
+       os << str_[0];
+       for (size_t i = 1; i < str_.size(); ++i)
+               os << str_[i];
+}
+
+
+void InsetMathString::mathmlize(MathStream & os) const
+{
+/*
+       if (code_ == LM_TC_VAR)
+               os << "<mi> " << str_ << " </mi>";
+       else if (code_ == LM_TC_CONST)
+               os << "<mn> " << str_ << " </mn>";
+       else if (code_ == LM_TC_RM || code_ == LM_TC_TEXTRM)
+               os << "<mtext> " << str_ <<  " </mtext>";
+       else
+*/
+               os << str_;
+}
+
+
+void InsetMathString::write(WriteStream & os) const
+{
+       os << str_;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathSubstack.C b/src/mathed/InsetMathSubstack.C
deleted file mode 100644 (file)
index ef494f7..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * \file InsetMathSubstack.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "LaTeXFeatures.h"
-#include "InsetMathSubstack.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "support/std_ostream.h"
-
-#include "funcrequest.h"
-#include "FuncStatus.h"
-#include "gettext.h"
-
-#include "support/lstrings.h"
-
-
-namespace lyx {
-
-using support::bformat;
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathSubstack::InsetMathSubstack()
-       : InsetMathGrid(1, 1)
-{}
-
-
-auto_ptr<InsetBase> InsetMathSubstack::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathSubstack(*this));
-}
-
-
-bool InsetMathSubstack::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       if (mi.base.style == LM_ST_DISPLAY) {
-               StyleChanger dummy(mi.base, LM_ST_TEXT);
-               InsetMathGrid::metrics(mi, dim);
-       } else {
-               InsetMathGrid::metrics(mi, dim);
-       }
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathSubstack::draw(PainterInfo & pi, int x, int y) const
-{
-       InsetMathGrid::draw(pi, x + 1, y);
-}
-
-
-bool InsetMathSubstack::getStatus(LCursor & cur, FuncRequest const & cmd,
-               FuncStatus & flag) const
-{
-       switch (cmd.action) {
-       case LFUN_TABULAR_FEATURE: {
-               string const name("substack");
-               docstring const & s = cmd.argument();
-               if (s == "add-vline-left" || s == "add-vline-right") {
-                       flag.message(bformat(
-                               from_utf8(N_("Can't add vertical grid lines in '%1$s'")), lyx::from_utf8(name)));
-                       flag.enabled(false);
-                       return true;
-               }
-               return InsetMathGrid::getStatus(cur, cmd, flag);
-       }
-       default:
-               return InsetMathGrid::getStatus(cur, cmd, flag);
-       }
-}
-
-
-void InsetMathSubstack::infoize(odocstream & os) const
-{
-       os << "Substack ";
-}
-
-
-void InsetMathSubstack::write(WriteStream & os) const
-{
-       os << "\\substack{";
-       InsetMathGrid::write(os);
-       os << "}\n";
-}
-
-
-void InsetMathSubstack::normalize(NormalStream & os) const
-{
-       os << "[substack ";
-       InsetMathGrid::normalize(os);
-       os << ']';
-}
-
-
-void InsetMathSubstack::maple(MapleStream & os) const
-{
-       os << "substack(";
-       InsetMathGrid::maple(os);
-       os << ')';
-}
-
-
-void InsetMathSubstack::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-       InsetMathGrid::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathSubstack.cpp b/src/mathed/InsetMathSubstack.cpp
new file mode 100644 (file)
index 0000000..ef494f7
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * \file InsetMathSubstack.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "LaTeXFeatures.h"
+#include "InsetMathSubstack.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "support/std_ostream.h"
+
+#include "funcrequest.h"
+#include "FuncStatus.h"
+#include "gettext.h"
+
+#include "support/lstrings.h"
+
+
+namespace lyx {
+
+using support::bformat;
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathSubstack::InsetMathSubstack()
+       : InsetMathGrid(1, 1)
+{}
+
+
+auto_ptr<InsetBase> InsetMathSubstack::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathSubstack(*this));
+}
+
+
+bool InsetMathSubstack::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (mi.base.style == LM_ST_DISPLAY) {
+               StyleChanger dummy(mi.base, LM_ST_TEXT);
+               InsetMathGrid::metrics(mi, dim);
+       } else {
+               InsetMathGrid::metrics(mi, dim);
+       }
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathSubstack::draw(PainterInfo & pi, int x, int y) const
+{
+       InsetMathGrid::draw(pi, x + 1, y);
+}
+
+
+bool InsetMathSubstack::getStatus(LCursor & cur, FuncRequest const & cmd,
+               FuncStatus & flag) const
+{
+       switch (cmd.action) {
+       case LFUN_TABULAR_FEATURE: {
+               string const name("substack");
+               docstring const & s = cmd.argument();
+               if (s == "add-vline-left" || s == "add-vline-right") {
+                       flag.message(bformat(
+                               from_utf8(N_("Can't add vertical grid lines in '%1$s'")), lyx::from_utf8(name)));
+                       flag.enabled(false);
+                       return true;
+               }
+               return InsetMathGrid::getStatus(cur, cmd, flag);
+       }
+       default:
+               return InsetMathGrid::getStatus(cur, cmd, flag);
+       }
+}
+
+
+void InsetMathSubstack::infoize(odocstream & os) const
+{
+       os << "Substack ";
+}
+
+
+void InsetMathSubstack::write(WriteStream & os) const
+{
+       os << "\\substack{";
+       InsetMathGrid::write(os);
+       os << "}\n";
+}
+
+
+void InsetMathSubstack::normalize(NormalStream & os) const
+{
+       os << "[substack ";
+       InsetMathGrid::normalize(os);
+       os << ']';
+}
+
+
+void InsetMathSubstack::maple(MapleStream & os) const
+{
+       os << "substack(";
+       InsetMathGrid::maple(os);
+       os << ')';
+}
+
+
+void InsetMathSubstack::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+       InsetMathGrid::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathSymbol.C b/src/mathed/InsetMathSymbol.C
deleted file mode 100644 (file)
index 87aff39..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/**
- * \file InsetMathSymbol.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathSymbol.h"
-#include "dimension.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "MathParser.h"
-#include "MathAtom.h"
-#include "LaTeXFeatures.h"
-#include "debug.h"
-
-#include "support/textutils.h"
-
-namespace lyx {
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathSymbol::InsetMathSymbol(latexkeys const * l)
-       : sym_(l), h_(0), scriptable_(false), font_cache_(LyXFont::ALL_IGNORE)
-{}
-
-
-InsetMathSymbol::InsetMathSymbol(char const * name)
-       : sym_(in_word_set(from_ascii(name))), h_(0), scriptable_(false),
-       font_cache_(LyXFont::ALL_IGNORE)
-{}
-
-
-InsetMathSymbol::InsetMathSymbol(docstring const & name)
-       : sym_(in_word_set(name)), h_(0), scriptable_(false), font_cache_(LyXFont::ALL_IGNORE)
-{}
-
-
-auto_ptr<InsetBase> InsetMathSymbol::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathSymbol(*this));
-}
-
-
-docstring InsetMathSymbol::name() const
-{
-       return sym_->name;
-}
-
-
-bool InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       //lyxerr << "metrics: symbol: '" << sym_->name
-       //      << "' in font: '" << sym_->inset
-       //      << "' drawn as: '" << sym_->draw
-       //      << "'" << std::endl;
-
-       bool dim_unchanged = (mi.base.font == font_cache_);
-       if (dim_unchanged)
-               dim = dim_;
-       else {
-               font_cache_ = mi.base.font;
-               int const em = mathed_char_width(mi.base.font, 'M');
-               FontSetChanger dummy(mi.base, sym_->inset);
-               mathed_string_dim(mi.base.font, sym_->draw, dim);
-               docstring::const_reverse_iterator rit = sym_->draw.rbegin();
-               kerning_ = mathed_char_kerning(mi.base.font, *rit);
-               // correct height for broken cmex and wasy font
-               if (sym_->inset == "cmex" || sym_->inset == "wasy") {
-                       h_ = 4 * dim.des / 5;
-                       dim.asc += h_;
-                       dim.des -= h_;
-               }
-               // seperate things a bit
-               if (isRelOp())
-                       dim.wid += static_cast<int>(0.5 * em + 0.5);
-               else
-                       dim.wid += static_cast<int>(0.1667 * em + 0.5);
-
-               dim_ = dim;
-       }
-
-       scriptable_ = false;
-       if (mi.base.style == LM_ST_DISPLAY)
-               if (sym_->inset == "cmex" || sym_->inset == "esint" ||
-                   sym_->extra == "funclim")
-                       scriptable_ = true;
-
-       return dim_unchanged;
-}
-
-
-void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
-{
-       //lyxerr << "metrics: symbol: '" << sym_->name
-       //      << "' in font: '" << sym_->inset
-       //      << "' drawn as: '" << sym_->draw
-       //      << "'" << std::endl;
-       int const em = mathed_char_width(pi.base.font, 'M');
-       if (isRelOp())
-               x += static_cast<int>(0.25*em+0.5);
-       else
-               x += static_cast<int>(0.0833*em+0.5);
-
-       FontSetChanger dummy(pi.base, sym_->inset.c_str());
-       pi.draw(x, y - h_, sym_->draw);
-}
-
-
-bool InsetMathSymbol::isRelOp() const
-{
-       return sym_->extra == "mathrel";
-}
-
-
-bool InsetMathSymbol::isOrdAlpha() const
-{
-       return sym_->extra == "mathord" || sym_->extra == "mathalpha";
-}
-
-
-bool InsetMathSymbol::isScriptable() const
-{
-       return scriptable_;
-}
-
-
-bool InsetMathSymbol::takesLimits() const
-{
-       return
-               sym_->inset == "cmex" ||
-               sym_->inset == "lyxboldsymb" ||
-               sym_->inset == "esint" ||
-               sym_->extra == "funclim";
-}
-
-
-void InsetMathSymbol::validate(LaTeXFeatures & features) const
-{
-       if (!sym_->requires.empty())
-               features.require(to_utf8(sym_->requires));
-}
-
-
-void InsetMathSymbol::normalize(NormalStream & os) const
-{
-       os << "[symbol " << name() << ']';
-}
-
-
-void InsetMathSymbol::maple(MapleStream & os) const
-{
-       if (name() == "cdot")
-               os << '*';
-       else if (name() == "infty")
-               os << "infinity";
-       else
-               os << name();
-}
-
-void InsetMathSymbol::maxima(MaximaStream & os) const
-{
-       if (name() == "cdot")
-               os << '*';
-       else if (name() == "infty")
-               os << "inf";
-       else if (name() == "pi")
-               os << "%pi";
-       else
-               os << name();
-}
-
-
-void InsetMathSymbol::mathematica(MathematicaStream & os) const
-{
-       if ( name() == "pi")    { os << "Pi"; return;}
-       if ( name() == "infty") { os << "Infinity"; return;}
-       if ( name() == "cdot")  { os << '*'; return;}
-       os << name();
-}
-
-
-char const * MathMLtype(docstring const & s)
-{
-       if (s == "mathop")
-               return "mo";
-       return "mi";
-}
-
-
-void InsetMathSymbol::mathmlize(MathStream & os) const
-{
-       char const * type = MathMLtype(sym_->extra);
-       os << '<' << type << "> ";
-       if (sym_->xmlname == "x") // unknown so far
-               os << name();
-       else
-               os << sym_->xmlname;
-       os << " </" << type << '>';
-}
-
-
-void InsetMathSymbol::octave(OctaveStream & os) const
-{
-       if (name() == "cdot")
-               os << '*';
-       else
-               os << name();
-}
-
-
-void InsetMathSymbol::write(WriteStream & os) const
-{
-       os << '\\' << name();
-
-       // $,#, etc. In theory the restriction based on catcodes, but then
-       // we do not handle catcodes very well, let alone cat code changes,
-       // so being outside the alpha range is good enough.
-       if (name().size() == 1 && !isAlphaASCII(name()[0]))
-               return;
-
-       os.pendingSpace(true);
-}
-
-
-void InsetMathSymbol::infoize2(odocstream & os) const
-{
-       os << "Symbol: " << name();
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathSymbol.cpp b/src/mathed/InsetMathSymbol.cpp
new file mode 100644 (file)
index 0000000..87aff39
--- /dev/null
@@ -0,0 +1,240 @@
+/**
+ * \file InsetMathSymbol.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathSymbol.h"
+#include "dimension.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "MathParser.h"
+#include "MathAtom.h"
+#include "LaTeXFeatures.h"
+#include "debug.h"
+
+#include "support/textutils.h"
+
+namespace lyx {
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathSymbol::InsetMathSymbol(latexkeys const * l)
+       : sym_(l), h_(0), scriptable_(false), font_cache_(LyXFont::ALL_IGNORE)
+{}
+
+
+InsetMathSymbol::InsetMathSymbol(char const * name)
+       : sym_(in_word_set(from_ascii(name))), h_(0), scriptable_(false),
+       font_cache_(LyXFont::ALL_IGNORE)
+{}
+
+
+InsetMathSymbol::InsetMathSymbol(docstring const & name)
+       : sym_(in_word_set(name)), h_(0), scriptable_(false), font_cache_(LyXFont::ALL_IGNORE)
+{}
+
+
+auto_ptr<InsetBase> InsetMathSymbol::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathSymbol(*this));
+}
+
+
+docstring InsetMathSymbol::name() const
+{
+       return sym_->name;
+}
+
+
+bool InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       //lyxerr << "metrics: symbol: '" << sym_->name
+       //      << "' in font: '" << sym_->inset
+       //      << "' drawn as: '" << sym_->draw
+       //      << "'" << std::endl;
+
+       bool dim_unchanged = (mi.base.font == font_cache_);
+       if (dim_unchanged)
+               dim = dim_;
+       else {
+               font_cache_ = mi.base.font;
+               int const em = mathed_char_width(mi.base.font, 'M');
+               FontSetChanger dummy(mi.base, sym_->inset);
+               mathed_string_dim(mi.base.font, sym_->draw, dim);
+               docstring::const_reverse_iterator rit = sym_->draw.rbegin();
+               kerning_ = mathed_char_kerning(mi.base.font, *rit);
+               // correct height for broken cmex and wasy font
+               if (sym_->inset == "cmex" || sym_->inset == "wasy") {
+                       h_ = 4 * dim.des / 5;
+                       dim.asc += h_;
+                       dim.des -= h_;
+               }
+               // seperate things a bit
+               if (isRelOp())
+                       dim.wid += static_cast<int>(0.5 * em + 0.5);
+               else
+                       dim.wid += static_cast<int>(0.1667 * em + 0.5);
+
+               dim_ = dim;
+       }
+
+       scriptable_ = false;
+       if (mi.base.style == LM_ST_DISPLAY)
+               if (sym_->inset == "cmex" || sym_->inset == "esint" ||
+                   sym_->extra == "funclim")
+                       scriptable_ = true;
+
+       return dim_unchanged;
+}
+
+
+void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
+{
+       //lyxerr << "metrics: symbol: '" << sym_->name
+       //      << "' in font: '" << sym_->inset
+       //      << "' drawn as: '" << sym_->draw
+       //      << "'" << std::endl;
+       int const em = mathed_char_width(pi.base.font, 'M');
+       if (isRelOp())
+               x += static_cast<int>(0.25*em+0.5);
+       else
+               x += static_cast<int>(0.0833*em+0.5);
+
+       FontSetChanger dummy(pi.base, sym_->inset.c_str());
+       pi.draw(x, y - h_, sym_->draw);
+}
+
+
+bool InsetMathSymbol::isRelOp() const
+{
+       return sym_->extra == "mathrel";
+}
+
+
+bool InsetMathSymbol::isOrdAlpha() const
+{
+       return sym_->extra == "mathord" || sym_->extra == "mathalpha";
+}
+
+
+bool InsetMathSymbol::isScriptable() const
+{
+       return scriptable_;
+}
+
+
+bool InsetMathSymbol::takesLimits() const
+{
+       return
+               sym_->inset == "cmex" ||
+               sym_->inset == "lyxboldsymb" ||
+               sym_->inset == "esint" ||
+               sym_->extra == "funclim";
+}
+
+
+void InsetMathSymbol::validate(LaTeXFeatures & features) const
+{
+       if (!sym_->requires.empty())
+               features.require(to_utf8(sym_->requires));
+}
+
+
+void InsetMathSymbol::normalize(NormalStream & os) const
+{
+       os << "[symbol " << name() << ']';
+}
+
+
+void InsetMathSymbol::maple(MapleStream & os) const
+{
+       if (name() == "cdot")
+               os << '*';
+       else if (name() == "infty")
+               os << "infinity";
+       else
+               os << name();
+}
+
+void InsetMathSymbol::maxima(MaximaStream & os) const
+{
+       if (name() == "cdot")
+               os << '*';
+       else if (name() == "infty")
+               os << "inf";
+       else if (name() == "pi")
+               os << "%pi";
+       else
+               os << name();
+}
+
+
+void InsetMathSymbol::mathematica(MathematicaStream & os) const
+{
+       if ( name() == "pi")    { os << "Pi"; return;}
+       if ( name() == "infty") { os << "Infinity"; return;}
+       if ( name() == "cdot")  { os << '*'; return;}
+       os << name();
+}
+
+
+char const * MathMLtype(docstring const & s)
+{
+       if (s == "mathop")
+               return "mo";
+       return "mi";
+}
+
+
+void InsetMathSymbol::mathmlize(MathStream & os) const
+{
+       char const * type = MathMLtype(sym_->extra);
+       os << '<' << type << "> ";
+       if (sym_->xmlname == "x") // unknown so far
+               os << name();
+       else
+               os << sym_->xmlname;
+       os << " </" << type << '>';
+}
+
+
+void InsetMathSymbol::octave(OctaveStream & os) const
+{
+       if (name() == "cdot")
+               os << '*';
+       else
+               os << name();
+}
+
+
+void InsetMathSymbol::write(WriteStream & os) const
+{
+       os << '\\' << name();
+
+       // $,#, etc. In theory the restriction based on catcodes, but then
+       // we do not handle catcodes very well, let alone cat code changes,
+       // so being outside the alpha range is good enough.
+       if (name().size() == 1 && !isAlphaASCII(name()[0]))
+               return;
+
+       os.pendingSpace(true);
+}
+
+
+void InsetMathSymbol::infoize2(odocstream & os) const
+{
+       os << "Symbol: " << name();
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathTFrac.C b/src/mathed/InsetMathTFrac.C
deleted file mode 100644 (file)
index 84ed2b8..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * \file InsetMathDFrac.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathTFrac.h"
-
-#include "MathData.h"
-#include "MathStream.h"
-
-#include "LaTeXFeatures.h"
-#include "LColor.h"
-
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-
-using std::string;
-using std::max;
-using std::auto_ptr;
-
-
-InsetMathTFrac::InsetMathTFrac()
-       : InsetMathFrac()
-{}
-
-
-auto_ptr<InsetBase> InsetMathTFrac::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathTFrac(*this));
-}
-
-
-bool InsetMathTFrac::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       StyleChanger dummy(mi.base, LM_ST_SCRIPT);
-       cell(0).metrics(mi);
-       cell(1).metrics(mi);
-       dim.wid = max(cell(0).width(), cell(1).width()) + 2;
-       dim.asc = cell(0).height() + 2 + 5;
-       dim.des = cell(1).height() + 2 - 5;
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathTFrac::draw(PainterInfo & pi, int x, int y) const
-{
-       StyleChanger dummy(pi.base, LM_ST_SCRIPT);
-       int m = x + dim_.wid / 2;
-       cell(0).draw(pi, m - cell(0).width() / 2, y - cell(0).descent() - 2 - 5);
-       cell(1).draw(pi, m - cell(1).width() / 2, y + cell(1).ascent()  + 2 - 5);
-       pi.pain.line(x + 1, y - 5, x + dim_.wid - 2, y - 5, LColor::math);
-       setPosCache(pi, x, y);
-}
-
-
-docstring InsetMathTFrac::name() const
-{
-       return from_ascii("tfrac");
-}
-
-
-void InsetMathTFrac::mathmlize(MathStream & os) const
-{
-       os << MTag("mtfrac") << cell(0) << cell(1) << ETag("mtfrac");
-}
-
-
-void InsetMathTFrac::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-       InsetMathNest::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathTFrac.cpp b/src/mathed/InsetMathTFrac.cpp
new file mode 100644 (file)
index 0000000..84ed2b8
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * \file InsetMathDFrac.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathTFrac.h"
+
+#include "MathData.h"
+#include "MathStream.h"
+
+#include "LaTeXFeatures.h"
+#include "LColor.h"
+
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+
+using std::string;
+using std::max;
+using std::auto_ptr;
+
+
+InsetMathTFrac::InsetMathTFrac()
+       : InsetMathFrac()
+{}
+
+
+auto_ptr<InsetBase> InsetMathTFrac::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathTFrac(*this));
+}
+
+
+bool InsetMathTFrac::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       StyleChanger dummy(mi.base, LM_ST_SCRIPT);
+       cell(0).metrics(mi);
+       cell(1).metrics(mi);
+       dim.wid = max(cell(0).width(), cell(1).width()) + 2;
+       dim.asc = cell(0).height() + 2 + 5;
+       dim.des = cell(1).height() + 2 - 5;
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathTFrac::draw(PainterInfo & pi, int x, int y) const
+{
+       StyleChanger dummy(pi.base, LM_ST_SCRIPT);
+       int m = x + dim_.wid / 2;
+       cell(0).draw(pi, m - cell(0).width() / 2, y - cell(0).descent() - 2 - 5);
+       cell(1).draw(pi, m - cell(1).width() / 2, y + cell(1).ascent()  + 2 - 5);
+       pi.pain.line(x + 1, y - 5, x + dim_.wid - 2, y - 5, LColor::math);
+       setPosCache(pi, x, y);
+}
+
+
+docstring InsetMathTFrac::name() const
+{
+       return from_ascii("tfrac");
+}
+
+
+void InsetMathTFrac::mathmlize(MathStream & os) const
+{
+       os << MTag("mtfrac") << cell(0) << cell(1) << ETag("mtfrac");
+}
+
+
+void InsetMathTFrac::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+       InsetMathNest::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathTabular.C b/src/mathed/InsetMathTabular.C
deleted file mode 100644 (file)
index 7445044..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * \file InsetMathTabular.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathTabular.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-
-#include "support/lstrings.h"
-#include "support/std_ostream.h"
-
-#include <iterator>
-
-
-namespace lyx {
-
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathTabular::InsetMathTabular(docstring const & name, int m, int n)
-       : InsetMathGrid(m, n), name_(name)
-{}
-
-
-InsetMathTabular::InsetMathTabular(docstring const & name, int m, int n,
-               char valign, docstring const & halign)
-       : InsetMathGrid(m, n, valign, halign), name_(name)
-{}
-
-
-InsetMathTabular::InsetMathTabular(docstring const & name, char valign,
-               docstring const & halign)
-       : InsetMathGrid(valign, halign), name_(name)
-{}
-
-
-auto_ptr<InsetBase> InsetMathTabular::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathTabular(*this));
-}
-
-
-bool InsetMathTabular::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       FontSetChanger dummy(mi.base, "textnormal");
-       InsetMathGrid::metrics(mi, dim);
-       dim.wid += 6;
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathTabular::draw(PainterInfo & pi, int x, int y) const
-{
-       FontSetChanger dummy(pi.base, "textnormal");
-       InsetMathGrid::drawWithMargin(pi, x, y, 4, 2);
-}
-
-
-void InsetMathTabular::write(WriteStream & os) const
-{
-       if (os.fragile())
-               os << "\\protect";
-       os << "\\begin{" << name_ << '}';
-
-       if (v_align_ == 't' || v_align_ == 'b')
-               os << '[' << char(v_align_) << ']';
-       os << '{' << halign() << "}\n";
-
-       InsetMathGrid::write(os);
-
-       if (os.fragile())
-               os << "\\protect";
-       os << "\\end{" << name_ << '}';
-       // adding a \n here is bad if the tabular is the last item
-       // in an \eqnarray...
-}
-
-
-void InsetMathTabular::infoize(odocstream & os) const
-{
-       docstring name = name_;
-       name[0] = support::uppercase(name[0]);
-       os << name << ' ';
-}
-
-
-void InsetMathTabular::normalize(NormalStream & os) const
-{
-       os << '[' << name_ << ' ';
-       InsetMathGrid::normalize(os);
-       os << ']';
-}
-
-
-void InsetMathTabular::maple(MapleStream & os) const
-{
-       os << "array(";
-       InsetMathGrid::maple(os);
-       os << ')';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathTabular.cpp b/src/mathed/InsetMathTabular.cpp
new file mode 100644 (file)
index 0000000..7445044
--- /dev/null
@@ -0,0 +1,117 @@
+/**
+ * \file InsetMathTabular.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathTabular.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+
+#include "support/lstrings.h"
+#include "support/std_ostream.h"
+
+#include <iterator>
+
+
+namespace lyx {
+
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathTabular::InsetMathTabular(docstring const & name, int m, int n)
+       : InsetMathGrid(m, n), name_(name)
+{}
+
+
+InsetMathTabular::InsetMathTabular(docstring const & name, int m, int n,
+               char valign, docstring const & halign)
+       : InsetMathGrid(m, n, valign, halign), name_(name)
+{}
+
+
+InsetMathTabular::InsetMathTabular(docstring const & name, char valign,
+               docstring const & halign)
+       : InsetMathGrid(valign, halign), name_(name)
+{}
+
+
+auto_ptr<InsetBase> InsetMathTabular::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathTabular(*this));
+}
+
+
+bool InsetMathTabular::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       FontSetChanger dummy(mi.base, "textnormal");
+       InsetMathGrid::metrics(mi, dim);
+       dim.wid += 6;
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathTabular::draw(PainterInfo & pi, int x, int y) const
+{
+       FontSetChanger dummy(pi.base, "textnormal");
+       InsetMathGrid::drawWithMargin(pi, x, y, 4, 2);
+}
+
+
+void InsetMathTabular::write(WriteStream & os) const
+{
+       if (os.fragile())
+               os << "\\protect";
+       os << "\\begin{" << name_ << '}';
+
+       if (v_align_ == 't' || v_align_ == 'b')
+               os << '[' << char(v_align_) << ']';
+       os << '{' << halign() << "}\n";
+
+       InsetMathGrid::write(os);
+
+       if (os.fragile())
+               os << "\\protect";
+       os << "\\end{" << name_ << '}';
+       // adding a \n here is bad if the tabular is the last item
+       // in an \eqnarray...
+}
+
+
+void InsetMathTabular::infoize(odocstream & os) const
+{
+       docstring name = name_;
+       name[0] = support::uppercase(name[0]);
+       os << name << ' ';
+}
+
+
+void InsetMathTabular::normalize(NormalStream & os) const
+{
+       os << '[' << name_ << ' ';
+       InsetMathGrid::normalize(os);
+       os << ']';
+}
+
+
+void InsetMathTabular::maple(MapleStream & os) const
+{
+       os << "array(";
+       InsetMathGrid::maple(os);
+       os << ')';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathUnderset.C b/src/mathed/InsetMathUnderset.C
deleted file mode 100644 (file)
index 577d49e..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * \file InsetMathUnderset.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathUnderset.h"
-#include "MathData.h"
-#include "MathStream.h"
-
-#include "cursor.h"
-#include "LaTeXFeatures.h"
-
-
-namespace lyx {
-
-using std::max;
-using std::auto_ptr;
-
-
-
-auto_ptr<InsetBase> InsetMathUnderset::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathUnderset(*this));
-}
-
-
-bool InsetMathUnderset::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       cell(1).metrics(mi);
-       FracChanger dummy(mi.base);
-       cell(0).metrics(mi);
-       dim.wid = max(cell(0).width(), cell(1).width()) + 4;
-       dim.asc = cell(1).ascent();
-       dim.des = cell(1).descent() + cell(0).height() + 4;
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathUnderset::draw(PainterInfo & pi, int x, int y) const
-{
-       int m  = x + width() / 2;
-       int yo = y + cell(1).descent() + cell(0).ascent() + 1;
-       cell(1).draw(pi, m - cell(1).width() / 2, y);
-       FracChanger dummy(pi.base);
-       cell(0).draw(pi, m - cell(0).width() / 2, yo);
-       drawMarkers(pi, x, y);
-}
-
-
-bool InsetMathUnderset::idxFirst(LCursor & cur) const
-{
-       cur.idx() = 1;
-       cur.pos() = 0;
-       return true;
-}
-
-
-bool InsetMathUnderset::idxLast(LCursor & cur) const
-{
-       cur.idx() = 1;
-       cur.pos() = cur.lastpos();
-       return true;
-}
-
-
-bool InsetMathUnderset::idxUpDown(LCursor & cur, bool up) const
-{
-       idx_type target = up; // up ? 1 : 0, since upper cell has idx 1
-       if (cur.idx() == target)
-               return false;
-       cur.idx() = target;
-       cur.pos() = cur.cell().x2pos(cur.x_target());
-       return true;
-}
-
-
-void InsetMathUnderset::write(WriteStream & os) const
-{
-       os << "\\underset{" << cell(0) << "}{" << cell(1) << '}';
-}
-
-
-void InsetMathUnderset::normalize(NormalStream & os) const
-{
-       os << "[underset " << cell(0) << ' ' << cell(1) << ']';
-}
-
-
-void InsetMathUnderset::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-       InsetMathNest::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathUnderset.cpp b/src/mathed/InsetMathUnderset.cpp
new file mode 100644 (file)
index 0000000..577d49e
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * \file InsetMathUnderset.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathUnderset.h"
+#include "MathData.h"
+#include "MathStream.h"
+
+#include "cursor.h"
+#include "LaTeXFeatures.h"
+
+
+namespace lyx {
+
+using std::max;
+using std::auto_ptr;
+
+
+
+auto_ptr<InsetBase> InsetMathUnderset::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathUnderset(*this));
+}
+
+
+bool InsetMathUnderset::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       cell(1).metrics(mi);
+       FracChanger dummy(mi.base);
+       cell(0).metrics(mi);
+       dim.wid = max(cell(0).width(), cell(1).width()) + 4;
+       dim.asc = cell(1).ascent();
+       dim.des = cell(1).descent() + cell(0).height() + 4;
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathUnderset::draw(PainterInfo & pi, int x, int y) const
+{
+       int m  = x + width() / 2;
+       int yo = y + cell(1).descent() + cell(0).ascent() + 1;
+       cell(1).draw(pi, m - cell(1).width() / 2, y);
+       FracChanger dummy(pi.base);
+       cell(0).draw(pi, m - cell(0).width() / 2, yo);
+       drawMarkers(pi, x, y);
+}
+
+
+bool InsetMathUnderset::idxFirst(LCursor & cur) const
+{
+       cur.idx() = 1;
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathUnderset::idxLast(LCursor & cur) const
+{
+       cur.idx() = 1;
+       cur.pos() = cur.lastpos();
+       return true;
+}
+
+
+bool InsetMathUnderset::idxUpDown(LCursor & cur, bool up) const
+{
+       idx_type target = up; // up ? 1 : 0, since upper cell has idx 1
+       if (cur.idx() == target)
+               return false;
+       cur.idx() = target;
+       cur.pos() = cur.cell().x2pos(cur.x_target());
+       return true;
+}
+
+
+void InsetMathUnderset::write(WriteStream & os) const
+{
+       os << "\\underset{" << cell(0) << "}{" << cell(1) << '}';
+}
+
+
+void InsetMathUnderset::normalize(NormalStream & os) const
+{
+       os << "[underset " << cell(0) << ' ' << cell(1) << ']';
+}
+
+
+void InsetMathUnderset::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+       InsetMathNest::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathUnknown.C b/src/mathed/InsetMathUnknown.C
deleted file mode 100644 (file)
index e26e918..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * \file InsetMathUnknown.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathUnknown.h"
-#include "MathSupport.h"
-#include "MathAtom.h"
-#include "MathStream.h"
-#include "MathStream.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::auto_ptr;
-using std::vector;
-
-
-InsetMathUnknown::InsetMathUnknown(docstring const & nm, bool final, bool black)
-       : name_(nm), final_(final), black_(black)
-{}
-
-
-auto_ptr<InsetBase> InsetMathUnknown::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathUnknown(*this));
-}
-
-
-docstring InsetMathUnknown::name() const
-{
-       return name_;
-}
-
-
-void InsetMathUnknown::setName(docstring const & name)
-{
-       name_ = name;
-}
-
-
-void InsetMathUnknown::normalize(NormalStream & os) const
-{
-       os << "[unknown " << name_ << ']';
-}
-
-
-bool InsetMathUnknown::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       mathed_string_dim(mi.base.font, name_, dim);
-       docstring::const_reverse_iterator rit = name_.rbegin();
-       kerning_ = mathed_char_kerning(mi.base.font, *rit);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathUnknown::draw(PainterInfo & pi, int x, int y) const
-{
-       if (black_)
-               drawStrBlack(pi, x, y, name_);
-       else
-               drawStrRed(pi, x, y, name_);
-       setPosCache(pi, x, y);
-}
-
-
-void InsetMathUnknown::finalize()
-{
-       final_ = true;
-}
-
-
-bool InsetMathUnknown::final() const
-{
-       return final_;
-}
-
-
-void InsetMathUnknown::maple(MapleStream & os) const
-{
-       os << name_;
-}
-
-
-void InsetMathUnknown::mathematica(MathematicaStream & os) const
-{
-       os << name_;
-}
-
-
-void InsetMathUnknown::mathmlize(MathStream & os) const
-{
-       os << MTag("mi") << name_ << ETag("mi");
-}
-
-
-void InsetMathUnknown::octave(OctaveStream & os) const
-{
-       os << name_;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathUnknown.cpp b/src/mathed/InsetMathUnknown.cpp
new file mode 100644 (file)
index 0000000..e26e918
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ * \file InsetMathUnknown.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathUnknown.h"
+#include "MathSupport.h"
+#include "MathAtom.h"
+#include "MathStream.h"
+#include "MathStream.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::auto_ptr;
+using std::vector;
+
+
+InsetMathUnknown::InsetMathUnknown(docstring const & nm, bool final, bool black)
+       : name_(nm), final_(final), black_(black)
+{}
+
+
+auto_ptr<InsetBase> InsetMathUnknown::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathUnknown(*this));
+}
+
+
+docstring InsetMathUnknown::name() const
+{
+       return name_;
+}
+
+
+void InsetMathUnknown::setName(docstring const & name)
+{
+       name_ = name;
+}
+
+
+void InsetMathUnknown::normalize(NormalStream & os) const
+{
+       os << "[unknown " << name_ << ']';
+}
+
+
+bool InsetMathUnknown::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       mathed_string_dim(mi.base.font, name_, dim);
+       docstring::const_reverse_iterator rit = name_.rbegin();
+       kerning_ = mathed_char_kerning(mi.base.font, *rit);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathUnknown::draw(PainterInfo & pi, int x, int y) const
+{
+       if (black_)
+               drawStrBlack(pi, x, y, name_);
+       else
+               drawStrRed(pi, x, y, name_);
+       setPosCache(pi, x, y);
+}
+
+
+void InsetMathUnknown::finalize()
+{
+       final_ = true;
+}
+
+
+bool InsetMathUnknown::final() const
+{
+       return final_;
+}
+
+
+void InsetMathUnknown::maple(MapleStream & os) const
+{
+       os << name_;
+}
+
+
+void InsetMathUnknown::mathematica(MathematicaStream & os) const
+{
+       os << name_;
+}
+
+
+void InsetMathUnknown::mathmlize(MathStream & os) const
+{
+       os << MTag("mi") << name_ << ETag("mi");
+}
+
+
+void InsetMathUnknown::octave(OctaveStream & os) const
+{
+       os << name_;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathXArrow.C b/src/mathed/InsetMathXArrow.C
deleted file mode 100644 (file)
index dbd16ac..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * \file InsetMathXArrow.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathXArrow.h"
-#include "MathData.h"
-#include "MathStream.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-
-#include "LaTeXFeatures.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::auto_ptr;
-
-
-InsetMathXArrow::InsetMathXArrow(docstring const & name)
-       : InsetMathFracBase(), name_(name)
-{}
-
-
-auto_ptr<InsetBase> InsetMathXArrow::doClone() const
-{
-       return auto_ptr<InsetBase>(new InsetMathXArrow(*this));
-}
-
-
-bool InsetMathXArrow::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       ScriptChanger dummy(mi.base);
-       cell(0).metrics(mi);
-       cell(1).metrics(mi);
-       dim.wid = std::max(cell(0).width(), cell(1).width()) + 10;
-       dim.asc = cell(0).height() + 10;
-       dim.des = cell(1).height();
-       metricsMarkers(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathXArrow::draw(PainterInfo & pi, int x, int y) const
-{
-       ScriptChanger dummy(pi.base);
-       cell(0).draw(pi, x + 5, y - 10);
-       cell(1).draw(pi, x + 5, y + cell(1).height());
-       mathed_draw_deco(pi, x + 1, y - 7, width() - 2, 5, name_);
-       drawMarkers(pi, x, y);
-}
-
-
-void InsetMathXArrow::write(WriteStream & os) const
-{
-       os << '\\' << name_;
-       if (cell(1).size())
-               os << '[' << cell(1) << ']';
-       os << '{' << cell(0) << '}';
-}
-
-
-void InsetMathXArrow::normalize(NormalStream & os) const
-{
-       os << "[xarrow " << name_ << ' ' <<  cell(0) << ' ' << cell(1) << ']';
-}
-
-
-void InsetMathXArrow::validate(LaTeXFeatures & features) const
-{
-       features.require("amsmath");
-       InsetMathNest::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathXArrow.cpp b/src/mathed/InsetMathXArrow.cpp
new file mode 100644 (file)
index 0000000..dbd16ac
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * \file InsetMathXArrow.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathXArrow.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+
+#include "LaTeXFeatures.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::auto_ptr;
+
+
+InsetMathXArrow::InsetMathXArrow(docstring const & name)
+       : InsetMathFracBase(), name_(name)
+{}
+
+
+auto_ptr<InsetBase> InsetMathXArrow::doClone() const
+{
+       return auto_ptr<InsetBase>(new InsetMathXArrow(*this));
+}
+
+
+bool InsetMathXArrow::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       ScriptChanger dummy(mi.base);
+       cell(0).metrics(mi);
+       cell(1).metrics(mi);
+       dim.wid = std::max(cell(0).width(), cell(1).width()) + 10;
+       dim.asc = cell(0).height() + 10;
+       dim.des = cell(1).height();
+       metricsMarkers(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathXArrow::draw(PainterInfo & pi, int x, int y) const
+{
+       ScriptChanger dummy(pi.base);
+       cell(0).draw(pi, x + 5, y - 10);
+       cell(1).draw(pi, x + 5, y + cell(1).height());
+       mathed_draw_deco(pi, x + 1, y - 7, width() - 2, 5, name_);
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathXArrow::write(WriteStream & os) const
+{
+       os << '\\' << name_;
+       if (cell(1).size())
+               os << '[' << cell(1) << ']';
+       os << '{' << cell(0) << '}';
+}
+
+
+void InsetMathXArrow::normalize(NormalStream & os) const
+{
+       os << "[xarrow " << name_ << ' ' <<  cell(0) << ' ' << cell(1) << ']';
+}
+
+
+void InsetMathXArrow::validate(LaTeXFeatures & features) const
+{
+       features.require("amsmath");
+       InsetMathNest::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathXYArrow.C b/src/mathed/InsetMathXYArrow.C
deleted file mode 100644 (file)
index fb0f302..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/**
- * \file InsetMathXYArrow.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathXYArrow.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "frontends/Painter.h"
-#include "debug.h"
-
-
-namespace lyx {
-
-
-using std::max;
-
-
-InsetMathXYArrow::InsetMathXYArrow()
-       : InsetMathNest(2)
-{}
-
-
-std::auto_ptr<InsetBase> InsetMathXYArrow::clone() const
-{
-       return std::auto_ptr<InsetBase>(new InsetMathXYArrow(*this));
-}
-
-
-InsetMathXYMatrix const * InsetMathXYArrow::targetMatrix() const
-{
-       return target_;
-}
-
-
-MathArray const & InsetMathXYArrow::targetCell() const
-{
-#if 0
-       InsetMathXYMatrix const * p = targetMatrix();
-       int x = 0;
-       int y = 0;
-       MathArray const & t = cell(0);
-       for (MathArray::const_iterator it = t.begin(); it != t.end(); ++it) {
-               switch ((*it)->getChar()) {
-                       case 'l': --x; break;
-                       case 'r': ++x; break;
-                       case 'u': --y; break;
-                       case 'd': ++y; break;
-               }
-       }
-       //lyxerr << "target: x: " << x << " y: " << y << endl;
-       InsetMath::idx_type n = mi_.idx + p->ncols() * y + x;
-       if (n >= p->nargs()) {
-               lyxerr << "source: n: " << mi_.idx << "\n"
-                      << "target: n: " << n << " out of range" << endl;
-               n = 0;
-       }
-       return p->cell(n);
-#else
-       static MathArray dummy;
-       return dummy;
-#endif
-}
-
-
-MathArray const & InsetMathXYArrow::sourceCell() const
-{
-#if 0
-       return targetMatrix()->cell(mi_.idx);
-#else
-       static MathArray dummy;
-       return dummy;
-#endif
-}
-
-
-bool InsetMathXYArrow::metrics(MetricsInfo & mi) const
-{
-       InsetMathNest::metrics(mi);
-       mi_   = mi;
-       FontSetChanger dummy(mi.base, "textrm");
-#if 0
-       target_ = mi.inset ? mi.inset->asXYMatrixInset() : 0;
-
-       if (editing()) {
-               int w    = mathed_string_width(mi.base.font, from_ascii("target: "));
-               width_   = w + max(cell(0).width(), cell(1).width());
-               ascent_  = cell(0).ascent();
-               descent_ = cell(0).descent() + cell(1).height() + 10;
-       } else {
-               width_   = 0;
-               ascent_  = 0;
-               descent_ = 0;
-               //mathed_string_dim(font_, "X", ascent_, descent_, width_);
-       }
-#endif
-}
-
-
-void InsetMathXYArrow::draw(PainterInfo & pi, int x, int y) const
-{
-       metrics(mi_);
-       FontSetChanger dummy(pi.base, "textrm");
-
-       if (editing()) {
-
-#if 0
-
-               int lasc;
-               int ldes;
-               int lwid;
-               mathed_string_dim(pi.base.font, "target: ", lasc, ldes, lwid);
-
-               cell(0).draw(pi, x + lwid, y);
-               pi.base.text(x + 3, y, "target");
-               y += max(cell(0).descent(), ldes) + 5;
-
-               y += max(cell(1).ascent(), lasc) + 5;
-               cell(1).draw(pi, x + lwid, y);
-               pi.base.text(x + 3, y, "label");
-
-#endif
-
-       } else {
-
-               pi.pain.text(x, y, "X");
-               MathArray const & s = sourceCell();
-               MathArray const & t = targetCell();
-               pi.pain.line(s.xm(), s.ym(), t.xm(), t.ym(), LColor::math);
-               cell(1).draw(pi, (s.xm() + t.xm())/2, (s.ym() + t.ym())/2);
-
-       }
-}
-
-
-void InsetMathXYArrow::write(WriteStream & os) const
-{
-       os << "\\ar";
-       if (cell(0).size())
-               os << '[' << cell(0) << ']';
-       if (cell(1).size())
-               os << (up_ ? '^' : '_') << '{' << cell(1) << '}';
-       os << " ";
-}
-
-
-void InsetMathXYArrow::normalize(NormalStream & os) const
-{
-       os << "[xyarrow ";
-       InsetMathNest::normalize(os);
-       os << ']';
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathXYArrow.cpp b/src/mathed/InsetMathXYArrow.cpp
new file mode 100644 (file)
index 0000000..fb0f302
--- /dev/null
@@ -0,0 +1,162 @@
+/**
+ * \file InsetMathXYArrow.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathXYArrow.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "frontends/Painter.h"
+#include "debug.h"
+
+
+namespace lyx {
+
+
+using std::max;
+
+
+InsetMathXYArrow::InsetMathXYArrow()
+       : InsetMathNest(2)
+{}
+
+
+std::auto_ptr<InsetBase> InsetMathXYArrow::clone() const
+{
+       return std::auto_ptr<InsetBase>(new InsetMathXYArrow(*this));
+}
+
+
+InsetMathXYMatrix const * InsetMathXYArrow::targetMatrix() const
+{
+       return target_;
+}
+
+
+MathArray const & InsetMathXYArrow::targetCell() const
+{
+#if 0
+       InsetMathXYMatrix const * p = targetMatrix();
+       int x = 0;
+       int y = 0;
+       MathArray const & t = cell(0);
+       for (MathArray::const_iterator it = t.begin(); it != t.end(); ++it) {
+               switch ((*it)->getChar()) {
+                       case 'l': --x; break;
+                       case 'r': ++x; break;
+                       case 'u': --y; break;
+                       case 'd': ++y; break;
+               }
+       }
+       //lyxerr << "target: x: " << x << " y: " << y << endl;
+       InsetMath::idx_type n = mi_.idx + p->ncols() * y + x;
+       if (n >= p->nargs()) {
+               lyxerr << "source: n: " << mi_.idx << "\n"
+                      << "target: n: " << n << " out of range" << endl;
+               n = 0;
+       }
+       return p->cell(n);
+#else
+       static MathArray dummy;
+       return dummy;
+#endif
+}
+
+
+MathArray const & InsetMathXYArrow::sourceCell() const
+{
+#if 0
+       return targetMatrix()->cell(mi_.idx);
+#else
+       static MathArray dummy;
+       return dummy;
+#endif
+}
+
+
+bool InsetMathXYArrow::metrics(MetricsInfo & mi) const
+{
+       InsetMathNest::metrics(mi);
+       mi_   = mi;
+       FontSetChanger dummy(mi.base, "textrm");
+#if 0
+       target_ = mi.inset ? mi.inset->asXYMatrixInset() : 0;
+
+       if (editing()) {
+               int w    = mathed_string_width(mi.base.font, from_ascii("target: "));
+               width_   = w + max(cell(0).width(), cell(1).width());
+               ascent_  = cell(0).ascent();
+               descent_ = cell(0).descent() + cell(1).height() + 10;
+       } else {
+               width_   = 0;
+               ascent_  = 0;
+               descent_ = 0;
+               //mathed_string_dim(font_, "X", ascent_, descent_, width_);
+       }
+#endif
+}
+
+
+void InsetMathXYArrow::draw(PainterInfo & pi, int x, int y) const
+{
+       metrics(mi_);
+       FontSetChanger dummy(pi.base, "textrm");
+
+       if (editing()) {
+
+#if 0
+
+               int lasc;
+               int ldes;
+               int lwid;
+               mathed_string_dim(pi.base.font, "target: ", lasc, ldes, lwid);
+
+               cell(0).draw(pi, x + lwid, y);
+               pi.base.text(x + 3, y, "target");
+               y += max(cell(0).descent(), ldes) + 5;
+
+               y += max(cell(1).ascent(), lasc) + 5;
+               cell(1).draw(pi, x + lwid, y);
+               pi.base.text(x + 3, y, "label");
+
+#endif
+
+       } else {
+
+               pi.pain.text(x, y, "X");
+               MathArray const & s = sourceCell();
+               MathArray const & t = targetCell();
+               pi.pain.line(s.xm(), s.ym(), t.xm(), t.ym(), LColor::math);
+               cell(1).draw(pi, (s.xm() + t.xm())/2, (s.ym() + t.ym())/2);
+
+       }
+}
+
+
+void InsetMathXYArrow::write(WriteStream & os) const
+{
+       os << "\\ar";
+       if (cell(0).size())
+               os << '[' << cell(0) << ']';
+       if (cell(1).size())
+               os << (up_ ? '^' : '_') << '{' << cell(1) << '}';
+       os << " ";
+}
+
+
+void InsetMathXYArrow::normalize(NormalStream & os) const
+{
+       os << "[xyarrow ";
+       InsetMathNest::normalize(os);
+       os << ']';
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathXYMatrix.C b/src/mathed/InsetMathXYMatrix.C
deleted file mode 100644 (file)
index f8de6c7..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
- * \file InsetMathXYMatrix.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMathXYMatrix.h"
-#include "MathStream.h"
-
-#include "LaTeXFeatures.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-
-InsetMathXYMatrix::InsetMathXYMatrix(LyXLength const & s, char c)
-       : InsetMathGrid(1, 1), spacing_(s), spacing_code_(c)
-{}
-
-
-std::auto_ptr<InsetBase> InsetMathXYMatrix::doClone() const
-{
-       return std::auto_ptr<InsetBase>(new InsetMathXYMatrix(*this));
-}
-
-
-int InsetMathXYMatrix::colsep() const
-{
-       return 40;
-}
-
-
-int InsetMathXYMatrix::rowsep() const
-{
-       return 40;
-}
-
-
-bool InsetMathXYMatrix::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       if (mi.base.style == LM_ST_DISPLAY)
-               mi.base.style = LM_ST_TEXT;
-       InsetMathGrid::metrics(mi, dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void InsetMathXYMatrix::write(WriteStream & os) const
-{
-       os << "\\xymatrix";
-       switch (spacing_code_) {
-       case 'R':
-       case 'C':
-       case 'M':
-       case 'W':
-       case 'H':
-       case 'L':
-               os << '@' << spacing_code_ << '='
-                  << from_ascii(spacing_.asLatexString());
-               break;
-       default:
-               if (!spacing_.empty())
-                       os << "@=" << from_ascii(spacing_.asLatexString());
-       }
-       os << '{';
-       InsetMathGrid::write(os);
-       os << "}\n";
-}
-
-
-void InsetMathXYMatrix::infoize(odocstream & os) const
-{
-       os << "xymatrix ";
-       switch (spacing_code_) {
-       case 'R':
-       case 'C':
-       case 'M':
-       case 'W':
-       case 'H':
-       case 'L':
-               os << spacing_code_ << ' '
-                  << from_ascii(spacing_.asLatexString()) << ' ';
-               break;
-       default:
-               if (!spacing_.empty())
-                       os << from_ascii(spacing_.asLatexString()) << ' ';
-       }
-       InsetMathGrid::infoize(os);
-}
-
-
-void InsetMathXYMatrix::normalize(NormalStream & os) const
-{
-       os << "[xymatrix ";
-       InsetMathGrid::normalize(os);
-       os << ']';
-}
-
-
-void InsetMathXYMatrix::maple(MapleStream & os) const
-{
-       os << "xymatrix(";
-       InsetMathGrid::maple(os);
-       os << ')';
-}
-
-
-void InsetMathXYMatrix::validate(LaTeXFeatures & features) const
-{
-       features.require("xy");
-       InsetMathGrid::validate(features);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathXYMatrix.cpp b/src/mathed/InsetMathXYMatrix.cpp
new file mode 100644 (file)
index 0000000..f8de6c7
--- /dev/null
@@ -0,0 +1,125 @@
+/**
+ * \file InsetMathXYMatrix.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMathXYMatrix.h"
+#include "MathStream.h"
+
+#include "LaTeXFeatures.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+
+InsetMathXYMatrix::InsetMathXYMatrix(LyXLength const & s, char c)
+       : InsetMathGrid(1, 1), spacing_(s), spacing_code_(c)
+{}
+
+
+std::auto_ptr<InsetBase> InsetMathXYMatrix::doClone() const
+{
+       return std::auto_ptr<InsetBase>(new InsetMathXYMatrix(*this));
+}
+
+
+int InsetMathXYMatrix::colsep() const
+{
+       return 40;
+}
+
+
+int InsetMathXYMatrix::rowsep() const
+{
+       return 40;
+}
+
+
+bool InsetMathXYMatrix::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (mi.base.style == LM_ST_DISPLAY)
+               mi.base.style = LM_ST_TEXT;
+       InsetMathGrid::metrics(mi, dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void InsetMathXYMatrix::write(WriteStream & os) const
+{
+       os << "\\xymatrix";
+       switch (spacing_code_) {
+       case 'R':
+       case 'C':
+       case 'M':
+       case 'W':
+       case 'H':
+       case 'L':
+               os << '@' << spacing_code_ << '='
+                  << from_ascii(spacing_.asLatexString());
+               break;
+       default:
+               if (!spacing_.empty())
+                       os << "@=" << from_ascii(spacing_.asLatexString());
+       }
+       os << '{';
+       InsetMathGrid::write(os);
+       os << "}\n";
+}
+
+
+void InsetMathXYMatrix::infoize(odocstream & os) const
+{
+       os << "xymatrix ";
+       switch (spacing_code_) {
+       case 'R':
+       case 'C':
+       case 'M':
+       case 'W':
+       case 'H':
+       case 'L':
+               os << spacing_code_ << ' '
+                  << from_ascii(spacing_.asLatexString()) << ' ';
+               break;
+       default:
+               if (!spacing_.empty())
+                       os << from_ascii(spacing_.asLatexString()) << ' ';
+       }
+       InsetMathGrid::infoize(os);
+}
+
+
+void InsetMathXYMatrix::normalize(NormalStream & os) const
+{
+       os << "[xymatrix ";
+       InsetMathGrid::normalize(os);
+       os << ']';
+}
+
+
+void InsetMathXYMatrix::maple(MapleStream & os) const
+{
+       os << "xymatrix(";
+       InsetMathGrid::maple(os);
+       os << ')';
+}
+
+
+void InsetMathXYMatrix::validate(LaTeXFeatures & features) const
+{
+       features.require("xy");
+       InsetMathGrid::validate(features);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathAtom.C b/src/mathed/MathAtom.C
deleted file mode 100644 (file)
index 87a569d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * \file MathAtom.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MathAtom.h"
-#include "InsetMath.h"
-
-
-namespace lyx {
-
-using std::swap;
-
-
-MathAtom::MathAtom()
-       : nucleus_(0)
-{}
-
-
-MathAtom::MathAtom(InsetBase * p)
-       : nucleus_(static_cast<InsetMath *>(p))
-{}
-
-
-MathAtom::MathAtom(MathAtom const & at)
-       : nucleus_(0)
-{
-       if (at.nucleus_)
-               nucleus_ = static_cast<InsetMath*>(at.nucleus_->clone().release());
-}
-
-
-MathAtom & MathAtom::operator=(MathAtom const & at)
-{
-       if (&at == this)
-               return *this;
-       MathAtom tmp(at);
-       swap(tmp.nucleus_, nucleus_);
-       return *this;
-}
-
-
-MathAtom::~MathAtom()
-{
-       delete nucleus_;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathAtom.cpp b/src/mathed/MathAtom.cpp
new file mode 100644 (file)
index 0000000..87a569d
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * \file MathAtom.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "MathAtom.h"
+#include "InsetMath.h"
+
+
+namespace lyx {
+
+using std::swap;
+
+
+MathAtom::MathAtom()
+       : nucleus_(0)
+{}
+
+
+MathAtom::MathAtom(InsetBase * p)
+       : nucleus_(static_cast<InsetMath *>(p))
+{}
+
+
+MathAtom::MathAtom(MathAtom const & at)
+       : nucleus_(0)
+{
+       if (at.nucleus_)
+               nucleus_ = static_cast<InsetMath*>(at.nucleus_->clone().release());
+}
+
+
+MathAtom & MathAtom::operator=(MathAtom const & at)
+{
+       if (&at == this)
+               return *this;
+       MathAtom tmp(at);
+       swap(tmp.nucleus_, nucleus_);
+       return *this;
+}
+
+
+MathAtom::~MathAtom()
+{
+       delete nucleus_;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathAutoCorrect.C b/src/mathed/MathAutoCorrect.C
deleted file mode 100644 (file)
index c275a93..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/**
- * \file MathAutoCorrect.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MathAutoCorrect.h"
-#include "MathData.h"
-#include "InsetMath.h"
-#include "MathSupport.h"
-#include "MathParser.h"
-#include "debug.h"
-
-#include "support/filetools.h" //  LibFileSearch
-
-#include <fstream>
-#include <sstream>
-
-
-namespace lyx {
-
-using support::libFileSearch;
-
-using std::string;
-using std::ifstream;
-using std::endl;
-using std::vector;
-
-namespace {
-
-class Correction {
-public:
-       ///
-       Correction() {}
-       ///
-       bool correct(MathAtom & at, char_type c) const;
-       ///
-       bool read(idocstream & is);
-       ///
-       void write(odocstream & os) const;
-private:
-       ///
-       MathAtom from1_;
-       ///
-       char_type from2_;
-       ///
-       MathAtom to_;
-};
-
-
-bool Correction::read(idocstream & is)
-{
-       docstring s1, s2, s3;
-       is >> s1 >> s2 >> s3;
-       if (!is)
-               return false;
-       if (s2.size() != 1)
-               return false;
-       MathArray ar1, ar3;
-       mathed_parse_cell(ar1, s1);
-       mathed_parse_cell(ar3, s3);
-       if (ar1.size() != 1 || ar3.size() != 1)
-               return false;
-       from1_ = ar1.front();
-       from2_ = s2[0];
-       to_    = ar3.front();
-       return true;
-}
-
-
-void Correction::write(odocstream & os) const
-{
-       os << "from: '" << from1_ << "' and '" << from2_
-          << "' to '" << to_ << '\'' << endl;
-}
-
-
-bool Correction::correct(MathAtom & at, char_type c) const
-{
-       //LYXERR(Debug::MATHED)
-       //      << "trying to correct ar: " << at << " from: '" << from1_ << '\'' << endl;
-       if (from2_ != c)
-               return false;
-       if (asString(at) != asString(from1_))
-               return false;
-       LYXERR(Debug::MATHED)
-               << "match found! subst in " << at
-               << " from: '" << from1_ << "' to '" << to_ << '\'' << endl;
-       at = to_;
-       return true;
-}
-
-
-idocstream & operator>>(idocstream & is, Correction & corr)
-{
-       corr.read(is);
-       return is;
-}
-
-
-odocstream & operator<<(odocstream & os, Correction & corr)
-{
-       corr.write(os);
-       return os;
-}
-
-
-
-
-class Corrections {
-public:
-       ///
-       typedef vector<Correction>::const_iterator const_iterator;
-       ///
-       Corrections() {}
-       ///
-       void insert(const Correction & corr) { data_.push_back(corr); }
-       ///
-       bool correct(MathAtom & at, char_type c) const;
-private:
-       ///
-       vector<Correction> data_;
-};
-
-
-bool Corrections::correct(MathAtom & at, char_type c) const
-{
-       for (const_iterator it = data_.begin(); it != data_.end(); ++it)
-               if (it->correct(at, c))
-                       return true;
-       return false;
-}
-
-
-Corrections theCorrections;
-
-void initAutoCorrect()
-{
-       LYXERR(Debug::MATHED) << "reading autocorrect file" << endl;
-       support::FileName const file = libFileSearch(string(), "autocorrect");
-       if (file.empty()) {
-               lyxerr << "Could not find autocorrect file" << endl;
-               return;
-       }
-
-       string line;
-       ifstream is(file.toFilesystemEncoding().c_str());
-       while (getline(is, line)) {
-               if (line.size() == 0 || line[0] == '#') {
-                       //LYXERR(Debug::MATHED) << "ignoring line '" << line << '\'' << endl;
-                       continue;
-               }
-               idocstringstream il(from_utf8(line));
-
-               //LYXERR(Debug::MATHED) << "line '" << line << '\'' << endl;
-               Correction corr;
-               if (corr.read(il)) {
-                       //LYXERR(Debug::MATHED) << "parsed: '" << corr << '\'' << endl;
-                       theCorrections.insert(corr);
-               }
-       }
-
-       LYXERR(Debug::MATHED) << "done reading autocorrections." << endl;
-}
-
-
-} // namespace anon
-
-
-bool math_autocorrect(MathAtom & at, char c)
-{
-       static bool initialized = false;
-
-       if (!initialized) {
-               initAutoCorrect();
-               initialized = true;
-       }
-
-       return theCorrections.correct(at, c);
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathAutoCorrect.cpp b/src/mathed/MathAutoCorrect.cpp
new file mode 100644 (file)
index 0000000..c275a93
--- /dev/null
@@ -0,0 +1,189 @@
+/**
+ * \file MathAutoCorrect.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "MathAutoCorrect.h"
+#include "MathData.h"
+#include "InsetMath.h"
+#include "MathSupport.h"
+#include "MathParser.h"
+#include "debug.h"
+
+#include "support/filetools.h" //  LibFileSearch
+
+#include <fstream>
+#include <sstream>
+
+
+namespace lyx {
+
+using support::libFileSearch;
+
+using std::string;
+using std::ifstream;
+using std::endl;
+using std::vector;
+
+namespace {
+
+class Correction {
+public:
+       ///
+       Correction() {}
+       ///
+       bool correct(MathAtom & at, char_type c) const;
+       ///
+       bool read(idocstream & is);
+       ///
+       void write(odocstream & os) const;
+private:
+       ///
+       MathAtom from1_;
+       ///
+       char_type from2_;
+       ///
+       MathAtom to_;
+};
+
+
+bool Correction::read(idocstream & is)
+{
+       docstring s1, s2, s3;
+       is >> s1 >> s2 >> s3;
+       if (!is)
+               return false;
+       if (s2.size() != 1)
+               return false;
+       MathArray ar1, ar3;
+       mathed_parse_cell(ar1, s1);
+       mathed_parse_cell(ar3, s3);
+       if (ar1.size() != 1 || ar3.size() != 1)
+               return false;
+       from1_ = ar1.front();
+       from2_ = s2[0];
+       to_    = ar3.front();
+       return true;
+}
+
+
+void Correction::write(odocstream & os) const
+{
+       os << "from: '" << from1_ << "' and '" << from2_
+          << "' to '" << to_ << '\'' << endl;
+}
+
+
+bool Correction::correct(MathAtom & at, char_type c) const
+{
+       //LYXERR(Debug::MATHED)
+       //      << "trying to correct ar: " << at << " from: '" << from1_ << '\'' << endl;
+       if (from2_ != c)
+               return false;
+       if (asString(at) != asString(from1_))
+               return false;
+       LYXERR(Debug::MATHED)
+               << "match found! subst in " << at
+               << " from: '" << from1_ << "' to '" << to_ << '\'' << endl;
+       at = to_;
+       return true;
+}
+
+
+idocstream & operator>>(idocstream & is, Correction & corr)
+{
+       corr.read(is);
+       return is;
+}
+
+
+odocstream & operator<<(odocstream & os, Correction & corr)
+{
+       corr.write(os);
+       return os;
+}
+
+
+
+
+class Corrections {
+public:
+       ///
+       typedef vector<Correction>::const_iterator const_iterator;
+       ///
+       Corrections() {}
+       ///
+       void insert(const Correction & corr) { data_.push_back(corr); }
+       ///
+       bool correct(MathAtom & at, char_type c) const;
+private:
+       ///
+       vector<Correction> data_;
+};
+
+
+bool Corrections::correct(MathAtom & at, char_type c) const
+{
+       for (const_iterator it = data_.begin(); it != data_.end(); ++it)
+               if (it->correct(at, c))
+                       return true;
+       return false;
+}
+
+
+Corrections theCorrections;
+
+void initAutoCorrect()
+{
+       LYXERR(Debug::MATHED) << "reading autocorrect file" << endl;
+       support::FileName const file = libFileSearch(string(), "autocorrect");
+       if (file.empty()) {
+               lyxerr << "Could not find autocorrect file" << endl;
+               return;
+       }
+
+       string line;
+       ifstream is(file.toFilesystemEncoding().c_str());
+       while (getline(is, line)) {
+               if (line.size() == 0 || line[0] == '#') {
+                       //LYXERR(Debug::MATHED) << "ignoring line '" << line << '\'' << endl;
+                       continue;
+               }
+               idocstringstream il(from_utf8(line));
+
+               //LYXERR(Debug::MATHED) << "line '" << line << '\'' << endl;
+               Correction corr;
+               if (corr.read(il)) {
+                       //LYXERR(Debug::MATHED) << "parsed: '" << corr << '\'' << endl;
+                       theCorrections.insert(corr);
+               }
+       }
+
+       LYXERR(Debug::MATHED) << "done reading autocorrections." << endl;
+}
+
+
+} // namespace anon
+
+
+bool math_autocorrect(MathAtom & at, char c)
+{
+       static bool initialized = false;
+
+       if (!initialized) {
+               initAutoCorrect();
+               initialized = true;
+       }
+
+       return theCorrections.correct(at, c);
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathData.C b/src/mathed/MathData.C
deleted file mode 100644 (file)
index b063903..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-/**
- * \file MathData.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MathData.h"
-#include "InsetMathFont.h"
-#include "InsetMathScript.h"
-#include "InsetMathMacro.h"
-#include "MathMacroTable.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "MathReplace.h"
-
-#include "BufferView.h"
-#include "buffer.h"
-#include "cursor.h"
-#include "debug.h"
-#include "LColor.h"
-
-#include "frontends/FontMetrics.h"
-#include "frontends/Painter.h"
-
-#include <boost/assert.hpp>
-
-
-namespace lyx {
-
-using std::abs;
-using std::endl;
-using std::min;
-using std::ostringstream;
-using std::string;
-using std::vector;
-
-
-MathArray::MathArray(const_iterator from, const_iterator to)
-       : base_type(from, to)
-{}
-
-
-MathAtom & MathArray::operator[](pos_type pos)
-{
-       BOOST_ASSERT(pos < size());
-       return base_type::operator[](pos);
-}
-
-
-MathAtom const & MathArray::operator[](pos_type pos) const
-{
-       BOOST_ASSERT(pos < size());
-       return base_type::operator[](pos);
-}
-
-
-void MathArray::insert(size_type pos, MathAtom const & t)
-{
-       base_type::insert(begin() + pos, t);
-}
-
-
-void MathArray::insert(size_type pos, MathArray const & ar)
-{
-       BOOST_ASSERT(pos <= size());
-       base_type::insert(begin() + pos, ar.begin(), ar.end());
-}
-
-
-void MathArray::append(MathArray const & ar)
-{
-       insert(size(), ar);
-}
-
-
-void MathArray::erase(size_type pos)
-{
-       if (pos < size())
-               erase(pos, pos + 1);
-}
-
-
-void MathArray::erase(iterator pos1, iterator pos2)
-{
-       base_type::erase(pos1, pos2);
-}
-
-
-void MathArray::erase(iterator pos)
-{
-       base_type::erase(pos);
-}
-
-
-void MathArray::erase(size_type pos1, size_type pos2)
-{
-       base_type::erase(begin() + pos1, begin() + pos2);
-}
-
-
-void MathArray::dump2() const
-{
-       odocstringstream os;
-       NormalStream ns(os);
-       for (const_iterator it = begin(); it != end(); ++it)
-               ns << *it << ' ';
-       lyxerr << to_utf8(os.str());
-}
-
-
-void MathArray::dump() const
-{
-       odocstringstream os;
-       NormalStream ns(os);
-       for (const_iterator it = begin(); it != end(); ++it)
-               ns << '<' << *it << '>';
-       lyxerr << to_utf8(os.str());
-}
-
-
-void MathArray::validate(LaTeXFeatures & features) const
-{
-       for (const_iterator it = begin(); it != end(); ++it)
-               (*it)->validate(features);
-}
-
-
-bool MathArray::match(MathArray const & ar) const
-{
-       return size() == ar.size() && matchpart(ar, 0);
-}
-
-
-bool MathArray::matchpart(MathArray const & ar, pos_type pos) const
-{
-       if (size() < ar.size() + pos)
-               return false;
-       const_iterator it = begin() + pos;
-       for (const_iterator jt = ar.begin(); jt != ar.end(); ++jt, ++it)
-               if (asString(*it) != asString(*jt))
-                       return false;
-       return true;
-}
-
-
-void MathArray::replace(ReplaceData & rep)
-{
-       for (size_type i = 0; i < size(); ++i) {
-               if (find1(rep.from, i)) {
-                       // match found
-                       lyxerr << "match found!" << endl;
-                       erase(i, i + rep.from.size());
-                       insert(i, rep.to);
-               }
-       }
-
-#ifdef WITH_WARNINGS
-#warning temporarily disabled
-       // for (const_iterator it = begin(); it != end(); ++it)
-       //      it->nucleus()->replace(rep);
-#endif
-}
-
-
-bool MathArray::find1(MathArray const & ar, size_type pos) const
-{
-       lyxerr << "finding '" << ar << "' in '" << *this << "'" << endl;
-       for (size_type i = 0, n = ar.size(); i < n; ++i)
-               if (asString(operator[](pos + i)) != asString(ar[i]))
-                       return false;
-       return true;
-}
-
-
-MathArray::size_type MathArray::find(MathArray const & ar) const
-{
-       for (int i = 0, last = size() - ar.size(); i < last; ++i)
-               if (find1(ar, i))
-                       return i;
-       return size();
-}
-
-
-MathArray::size_type MathArray::find_last(MathArray const & ar) const
-{
-       for (int i = size() - ar.size(); i >= 0; --i)
-               if (find1(ar, i))
-                       return i;
-       return size();
-}
-
-
-bool MathArray::contains(MathArray const & ar) const
-{
-       if (find(ar) != size())
-               return true;
-       for (const_iterator it = begin(); it != end(); ++it)
-               if ((*it)->contains(ar))
-                       return true;
-       return false;
-}
-
-
-void MathArray::touch() const
-{
-}
-
-
-bool MathArray::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       dim = dim_;
-       metrics(mi);
-       if (dim_ == dim)
-               return false;
-       dim = dim_;
-       return true;
-}
-
-
-namespace {
-
-bool isInside(DocIterator const & it, MathArray const & ar,
-       pos_type p1, pos_type p2)
-{
-       for (size_t i = 0; i != it.depth(); ++i) {
-               CursorSlice const & sl = it[i];
-               if (sl.inset().inMathed() && &sl.cell() == &ar)
-                       return p1 <= sl.pos() && sl.pos() < p2;
-       }
-       return false;
-}
-
-}
-
-
-
-void MathArray::metrics(MetricsInfo & mi) const
-{
-       frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
-       dim_ = fm.dimension('I');
-       int xascent = fm.dimension('x').ascent();
-       if (xascent >= dim_.asc)
-               xascent = (2 * dim_.asc) / 3;
-       minasc_ = xascent;
-       mindes_ = (3 * xascent) / 4;
-       slevel_ = (4 * xascent) / 5;
-       sshift_ = xascent / 4;
-       kerning_ = 0;
-
-       if (empty())
-               return;
-
-       dim_.asc = 0;
-       dim_.wid = 0;
-       Dimension d;
-       //BufferView & bv  = *mi.base.bv;
-       //Buffer const & buf = *bv.buffer();
-       for (size_t i = 0, n = size(); i != n; ++i) {
-               MathAtom const & at = operator[](i);
-#if 0
-               MathMacro const * mac = at->asMacro();
-               if (mac && buf.hasMacro(mac->name())) {
-                       MacroData const & tmpl = buf.getMacro(mac->name());
-                       int numargs = tmpl.numargs();
-                       if (i + numargs > n)
-                               numargs = n - i - 1;
-                       lyxerr << "metrics:found macro: " << mac->name()
-                               << " numargs: " << numargs << endl;
-                       if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
-                               MathArray args(begin() + i + 1, begin() + i + numargs + 1);
-                               MathArray exp;
-                               tmpl.expand(args, exp);
-                               mac->setExpansion(exp, args);
-                               mac->metricsExpanded(mi, d);
-                               dim_.wid += mac->widthExpanded();
-                               i += numargs;
-                               continue;
-                       }
-               }
-#endif
-               at->metrics(mi, d);
-               dim_ += d;
-               if (i == n - 1)
-                       kerning_ = at->kerning();
-       }
-}
-
-
-void MathArray::draw(PainterInfo & pi, int x, int y) const
-{
-       //lyxerr << "MathArray::draw: x: " << x << " y: " << y << endl;
-       BufferView & bv  = *pi.base.bv;
-       setXY(bv, x, y);
-
-       if (empty()) {
-               pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
-               return;
-       }
-
-       // don't draw outside the workarea
-       if (y + descent() <= 0
-               || y - ascent() >= bv.workHeight()
-               || x + width() <= 0
-               || x >= bv. workWidth())
-               return;
-
-       for (size_t i = 0, n = size(); i != n; ++i) {
-               MathAtom const & at = operator[](i);
-#if 0
-       Buffer const & buf = bv.buffer();
-               // special macro handling
-               MathMacro const * mac = at->asMacro();
-               if (mac && buf.hasMacro(mac->name())) {
-                       MacroData const & tmpl = buf.getMacro(mac->name());
-                       int numargs = tmpl.numargs();
-                       if (i + numargs > n)
-                               numargs = n - i - 1;
-                       if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
-                               mac->drawExpanded(pi, x, y);
-                               x += mac->widthExpanded();
-                               i += numargs;
-                               continue;
-                       }
-               }
-#endif
-               bv.coordCache().insets().add(at.nucleus(), x, y);
-               at->drawSelection(pi, x, y);
-               at->draw(pi, x, y);
-               x += at->width();
-       }
-}
-
-
-void MathArray::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       dim.clear();
-       Dimension d;
-       for (const_iterator it = begin(); it != end(); ++it) {
-               (*it)->metricsT(mi, d);
-               dim += d;
-       }
-}
-
-
-void MathArray::drawT(TextPainter & pain, int x, int y) const
-{
-       //lyxerr << "x: " << x << " y: " << y << ' ' << pain.workAreaHeight() << endl;
-
-       // FIXME: Abdel 16/10/2006
-       // This drawT() method is never used, this is dead code.
-
-       for (const_iterator it = begin(), et = end(); it != et; ++it) {
-               (*it)->drawT(pain, x, y);
-               //x += (*it)->width_;
-               x += 2;
-       }
-}
-
-
-int MathArray::pos2x(size_type pos) const
-{
-       return pos2x(pos, 0);
-}
-
-
-int MathArray::pos2x(size_type pos, int glue) const
-{
-       int x = 0;
-       size_type target = min(pos, size());
-       for (size_type i = 0; i < target; ++i) {
-               const_iterator it = begin() + i;
-               if ((*it)->getChar() == ' ')
-                       x += glue;
-               //lyxerr << "char: " << (*it)->getChar()
-               //      << "width: " << (*it)->width() << std::endl;
-               x += (*it)->width();
-       }
-       return x;
-}
-
-
-MathArray::size_type MathArray::x2pos(int targetx) const
-{
-       return x2pos(targetx, 0);
-}
-
-
-MathArray::size_type MathArray::x2pos(int targetx, int glue) const
-{
-       const_iterator it = begin();
-       int lastx = 0;
-       int currx = 0;
-       // find first position after targetx
-       for (; currx < targetx && it < end(); ++it) {
-               lastx = currx;
-               if ((*it)->getChar() == ' ')
-                       currx += glue;
-               currx += (*it)->width();
-       }
-
-       /**
-        * If we are not at the beginning of the array, go to the left
-        * of the inset if one of the following two condition holds:
-        * - the current inset is editable (so that the cursor tip is
-        *   deeper than us): in this case, we want all intermediate
-        *   cursor slices to be before insets;
-        * - the mouse is closer to the left side of the inset than to
-        *   the right one.
-        * See bug 1918 for details.
-        **/
-       if (it != begin() && currx >= targetx
-           && ((*boost::prior(it))->asNestInset()
-               || abs(lastx - targetx) < abs(currx - targetx))) {
-               --it;
-       }
-
-       return it - begin();
-}
-
-
-int MathArray::dist(BufferView const & bv, int x, int y) const
-{
-       int xx = 0;
-       int yy = 0;
-
-       const int xo_ = xo(bv);
-       const int yo_ = yo(bv);
-
-       if (x < xo_)
-               xx = xo_ - x;
-       else if (x > xo_ + width())
-               xx = x - xo_ - width();
-
-       if (y < yo_ - ascent())
-               yy = yo_ - ascent() - y;
-       else if (y > yo_ + descent())
-               yy = y - yo_ - descent();
-
-       return xx + yy;
-}
-
-
-void MathArray::setXY(BufferView & bv, int x, int y) const
-{
-       //lyxerr << "setting position cache for MathArray " << this << std::endl;
-       bv.coordCache().arrays().add(this, x, y);
-}
-
-
-int MathArray::xo(BufferView const & bv) const
-{
-       return bv.coordCache().getArrays().x(this);
-}
-
-
-int MathArray::yo(BufferView const & bv) const
-{
-       return bv.coordCache().getArrays().y(this);
-}
-
-
-std::ostream & operator<<(std::ostream & os, MathArray const & ar)
-{
-       odocstringstream oss;
-       NormalStream ns(oss);
-       ns << ar;
-       return os << to_utf8(oss.str());
-}
-
-
-odocstream & operator<<(odocstream & os, MathArray const & ar)
-{
-       NormalStream ns(os);
-       ns << ar;
-       return os;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathData.cpp b/src/mathed/MathData.cpp
new file mode 100644 (file)
index 0000000..b063903
--- /dev/null
@@ -0,0 +1,485 @@
+/**
+ * \file MathData.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "MathData.h"
+#include "InsetMathFont.h"
+#include "InsetMathScript.h"
+#include "InsetMathMacro.h"
+#include "MathMacroTable.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "MathReplace.h"
+
+#include "BufferView.h"
+#include "buffer.h"
+#include "cursor.h"
+#include "debug.h"
+#include "LColor.h"
+
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
+#include <boost/assert.hpp>
+
+
+namespace lyx {
+
+using std::abs;
+using std::endl;
+using std::min;
+using std::ostringstream;
+using std::string;
+using std::vector;
+
+
+MathArray::MathArray(const_iterator from, const_iterator to)
+       : base_type(from, to)
+{}
+
+
+MathAtom & MathArray::operator[](pos_type pos)
+{
+       BOOST_ASSERT(pos < size());
+       return base_type::operator[](pos);
+}
+
+
+MathAtom const & MathArray::operator[](pos_type pos) const
+{
+       BOOST_ASSERT(pos < size());
+       return base_type::operator[](pos);
+}
+
+
+void MathArray::insert(size_type pos, MathAtom const & t)
+{
+       base_type::insert(begin() + pos, t);
+}
+
+
+void MathArray::insert(size_type pos, MathArray const & ar)
+{
+       BOOST_ASSERT(pos <= size());
+       base_type::insert(begin() + pos, ar.begin(), ar.end());
+}
+
+
+void MathArray::append(MathArray const & ar)
+{
+       insert(size(), ar);
+}
+
+
+void MathArray::erase(size_type pos)
+{
+       if (pos < size())
+               erase(pos, pos + 1);
+}
+
+
+void MathArray::erase(iterator pos1, iterator pos2)
+{
+       base_type::erase(pos1, pos2);
+}
+
+
+void MathArray::erase(iterator pos)
+{
+       base_type::erase(pos);
+}
+
+
+void MathArray::erase(size_type pos1, size_type pos2)
+{
+       base_type::erase(begin() + pos1, begin() + pos2);
+}
+
+
+void MathArray::dump2() const
+{
+       odocstringstream os;
+       NormalStream ns(os);
+       for (const_iterator it = begin(); it != end(); ++it)
+               ns << *it << ' ';
+       lyxerr << to_utf8(os.str());
+}
+
+
+void MathArray::dump() const
+{
+       odocstringstream os;
+       NormalStream ns(os);
+       for (const_iterator it = begin(); it != end(); ++it)
+               ns << '<' << *it << '>';
+       lyxerr << to_utf8(os.str());
+}
+
+
+void MathArray::validate(LaTeXFeatures & features) const
+{
+       for (const_iterator it = begin(); it != end(); ++it)
+               (*it)->validate(features);
+}
+
+
+bool MathArray::match(MathArray const & ar) const
+{
+       return size() == ar.size() && matchpart(ar, 0);
+}
+
+
+bool MathArray::matchpart(MathArray const & ar, pos_type pos) const
+{
+       if (size() < ar.size() + pos)
+               return false;
+       const_iterator it = begin() + pos;
+       for (const_iterator jt = ar.begin(); jt != ar.end(); ++jt, ++it)
+               if (asString(*it) != asString(*jt))
+                       return false;
+       return true;
+}
+
+
+void MathArray::replace(ReplaceData & rep)
+{
+       for (size_type i = 0; i < size(); ++i) {
+               if (find1(rep.from, i)) {
+                       // match found
+                       lyxerr << "match found!" << endl;
+                       erase(i, i + rep.from.size());
+                       insert(i, rep.to);
+               }
+       }
+
+#ifdef WITH_WARNINGS
+#warning temporarily disabled
+       // for (const_iterator it = begin(); it != end(); ++it)
+       //      it->nucleus()->replace(rep);
+#endif
+}
+
+
+bool MathArray::find1(MathArray const & ar, size_type pos) const
+{
+       lyxerr << "finding '" << ar << "' in '" << *this << "'" << endl;
+       for (size_type i = 0, n = ar.size(); i < n; ++i)
+               if (asString(operator[](pos + i)) != asString(ar[i]))
+                       return false;
+       return true;
+}
+
+
+MathArray::size_type MathArray::find(MathArray const & ar) const
+{
+       for (int i = 0, last = size() - ar.size(); i < last; ++i)
+               if (find1(ar, i))
+                       return i;
+       return size();
+}
+
+
+MathArray::size_type MathArray::find_last(MathArray const & ar) const
+{
+       for (int i = size() - ar.size(); i >= 0; --i)
+               if (find1(ar, i))
+                       return i;
+       return size();
+}
+
+
+bool MathArray::contains(MathArray const & ar) const
+{
+       if (find(ar) != size())
+               return true;
+       for (const_iterator it = begin(); it != end(); ++it)
+               if ((*it)->contains(ar))
+                       return true;
+       return false;
+}
+
+
+void MathArray::touch() const
+{
+}
+
+
+bool MathArray::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       dim = dim_;
+       metrics(mi);
+       if (dim_ == dim)
+               return false;
+       dim = dim_;
+       return true;
+}
+
+
+namespace {
+
+bool isInside(DocIterator const & it, MathArray const & ar,
+       pos_type p1, pos_type p2)
+{
+       for (size_t i = 0; i != it.depth(); ++i) {
+               CursorSlice const & sl = it[i];
+               if (sl.inset().inMathed() && &sl.cell() == &ar)
+                       return p1 <= sl.pos() && sl.pos() < p2;
+       }
+       return false;
+}
+
+}
+
+
+
+void MathArray::metrics(MetricsInfo & mi) const
+{
+       frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
+       dim_ = fm.dimension('I');
+       int xascent = fm.dimension('x').ascent();
+       if (xascent >= dim_.asc)
+               xascent = (2 * dim_.asc) / 3;
+       minasc_ = xascent;
+       mindes_ = (3 * xascent) / 4;
+       slevel_ = (4 * xascent) / 5;
+       sshift_ = xascent / 4;
+       kerning_ = 0;
+
+       if (empty())
+               return;
+
+       dim_.asc = 0;
+       dim_.wid = 0;
+       Dimension d;
+       //BufferView & bv  = *mi.base.bv;
+       //Buffer const & buf = *bv.buffer();
+       for (size_t i = 0, n = size(); i != n; ++i) {
+               MathAtom const & at = operator[](i);
+#if 0
+               MathMacro const * mac = at->asMacro();
+               if (mac && buf.hasMacro(mac->name())) {
+                       MacroData const & tmpl = buf.getMacro(mac->name());
+                       int numargs = tmpl.numargs();
+                       if (i + numargs > n)
+                               numargs = n - i - 1;
+                       lyxerr << "metrics:found macro: " << mac->name()
+                               << " numargs: " << numargs << endl;
+                       if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
+                               MathArray args(begin() + i + 1, begin() + i + numargs + 1);
+                               MathArray exp;
+                               tmpl.expand(args, exp);
+                               mac->setExpansion(exp, args);
+                               mac->metricsExpanded(mi, d);
+                               dim_.wid += mac->widthExpanded();
+                               i += numargs;
+                               continue;
+                       }
+               }
+#endif
+               at->metrics(mi, d);
+               dim_ += d;
+               if (i == n - 1)
+                       kerning_ = at->kerning();
+       }
+}
+
+
+void MathArray::draw(PainterInfo & pi, int x, int y) const
+{
+       //lyxerr << "MathArray::draw: x: " << x << " y: " << y << endl;
+       BufferView & bv  = *pi.base.bv;
+       setXY(bv, x, y);
+
+       if (empty()) {
+               pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
+               return;
+       }
+
+       // don't draw outside the workarea
+       if (y + descent() <= 0
+               || y - ascent() >= bv.workHeight()
+               || x + width() <= 0
+               || x >= bv. workWidth())
+               return;
+
+       for (size_t i = 0, n = size(); i != n; ++i) {
+               MathAtom const & at = operator[](i);
+#if 0
+       Buffer const & buf = bv.buffer();
+               // special macro handling
+               MathMacro const * mac = at->asMacro();
+               if (mac && buf.hasMacro(mac->name())) {
+                       MacroData const & tmpl = buf.getMacro(mac->name());
+                       int numargs = tmpl.numargs();
+                       if (i + numargs > n)
+                               numargs = n - i - 1;
+                       if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
+                               mac->drawExpanded(pi, x, y);
+                               x += mac->widthExpanded();
+                               i += numargs;
+                               continue;
+                       }
+               }
+#endif
+               bv.coordCache().insets().add(at.nucleus(), x, y);
+               at->drawSelection(pi, x, y);
+               at->draw(pi, x, y);
+               x += at->width();
+       }
+}
+
+
+void MathArray::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       dim.clear();
+       Dimension d;
+       for (const_iterator it = begin(); it != end(); ++it) {
+               (*it)->metricsT(mi, d);
+               dim += d;
+       }
+}
+
+
+void MathArray::drawT(TextPainter & pain, int x, int y) const
+{
+       //lyxerr << "x: " << x << " y: " << y << ' ' << pain.workAreaHeight() << endl;
+
+       // FIXME: Abdel 16/10/2006
+       // This drawT() method is never used, this is dead code.
+
+       for (const_iterator it = begin(), et = end(); it != et; ++it) {
+               (*it)->drawT(pain, x, y);
+               //x += (*it)->width_;
+               x += 2;
+       }
+}
+
+
+int MathArray::pos2x(size_type pos) const
+{
+       return pos2x(pos, 0);
+}
+
+
+int MathArray::pos2x(size_type pos, int glue) const
+{
+       int x = 0;
+       size_type target = min(pos, size());
+       for (size_type i = 0; i < target; ++i) {
+               const_iterator it = begin() + i;
+               if ((*it)->getChar() == ' ')
+                       x += glue;
+               //lyxerr << "char: " << (*it)->getChar()
+               //      << "width: " << (*it)->width() << std::endl;
+               x += (*it)->width();
+       }
+       return x;
+}
+
+
+MathArray::size_type MathArray::x2pos(int targetx) const
+{
+       return x2pos(targetx, 0);
+}
+
+
+MathArray::size_type MathArray::x2pos(int targetx, int glue) const
+{
+       const_iterator it = begin();
+       int lastx = 0;
+       int currx = 0;
+       // find first position after targetx
+       for (; currx < targetx && it < end(); ++it) {
+               lastx = currx;
+               if ((*it)->getChar() == ' ')
+                       currx += glue;
+               currx += (*it)->width();
+       }
+
+       /**
+        * If we are not at the beginning of the array, go to the left
+        * of the inset if one of the following two condition holds:
+        * - the current inset is editable (so that the cursor tip is
+        *   deeper than us): in this case, we want all intermediate
+        *   cursor slices to be before insets;
+        * - the mouse is closer to the left side of the inset than to
+        *   the right one.
+        * See bug 1918 for details.
+        **/
+       if (it != begin() && currx >= targetx
+           && ((*boost::prior(it))->asNestInset()
+               || abs(lastx - targetx) < abs(currx - targetx))) {
+               --it;
+       }
+
+       return it - begin();
+}
+
+
+int MathArray::dist(BufferView const & bv, int x, int y) const
+{
+       int xx = 0;
+       int yy = 0;
+
+       const int xo_ = xo(bv);
+       const int yo_ = yo(bv);
+
+       if (x < xo_)
+               xx = xo_ - x;
+       else if (x > xo_ + width())
+               xx = x - xo_ - width();
+
+       if (y < yo_ - ascent())
+               yy = yo_ - ascent() - y;
+       else if (y > yo_ + descent())
+               yy = y - yo_ - descent();
+
+       return xx + yy;
+}
+
+
+void MathArray::setXY(BufferView & bv, int x, int y) const
+{
+       //lyxerr << "setting position cache for MathArray " << this << std::endl;
+       bv.coordCache().arrays().add(this, x, y);
+}
+
+
+int MathArray::xo(BufferView const & bv) const
+{
+       return bv.coordCache().getArrays().x(this);
+}
+
+
+int MathArray::yo(BufferView const & bv) const
+{
+       return bv.coordCache().getArrays().y(this);
+}
+
+
+std::ostream & operator<<(std::ostream & os, MathArray const & ar)
+{
+       odocstringstream oss;
+       NormalStream ns(oss);
+       ns << ar;
+       return os << to_utf8(oss.str());
+}
+
+
+odocstream & operator<<(odocstream & os, MathArray const & ar)
+{
+       NormalStream ns(os);
+       ns << ar;
+       return os;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathExtern.C b/src/mathed/MathExtern.C
deleted file mode 100644 (file)
index 36ca801..0000000
+++ /dev/null
@@ -1,1452 +0,0 @@
-/**
- * \file MathExtern.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-// This file contains most of the magic that extracts "context
-// information" from the unstructered layout-oriented stuff in an
-// MathArray.
-
-#include <config.h>
-
-#include "MathExtern.h"
-#include "InsetMathArray.h"
-#include "InsetMathChar.h"
-#include "InsetMathDelim.h"
-#include "MathData.h"
-#include "InsetMathDiff.h"
-#include "InsetMathExFunc.h"
-#include "InsetMathExInt.h"
-#include "InsetMathFont.h"
-#include "InsetMathFrac.h"
-#include "InsetMathLim.h"
-#include "InsetMathMatrix.h"
-#include "MathStream.h"
-#include "InsetMathNumber.h"
-#include "InsetMathScript.h"
-#include "InsetMathString.h"
-#include "InsetMathSymbol.h"
-#include "MathParser.h"
-#include "debug.h"
-#include "support/filetools.h"
-#include "support/lstrings.h"
-#include "support/lyxlib.h"
-#include "frontends/controllers/ControlMath.h"
-
-#include <algorithm>
-#include <sstream>
-#include <fstream>
-
-
-namespace lyx {
-
-using support::cmd_ret;
-using support::getVectorFromString;
-using support::libFileSearch;
-using support::runCommand;
-using support::FileName;
-using support::quoteName;
-using support::tempName;
-using support::unlink;
-using support::subst;
-
-using frontend::function_names;
-
-using std::endl;
-using std::find_if;
-using std::auto_ptr;
-using std::istringstream;
-using std::ostream;
-using std::swap;
-using std::string;
-using std::vector;
-
-static size_t const npos = lyx::docstring::npos;
-
-// define a function for tests
-typedef bool TestItemFunc(MathAtom const &);
-
-// define a function for replacing subexpressions
-typedef MathAtom ReplaceArgumentFunc(const MathArray & ar);
-
-
-
-// try to extract a super/subscript
-// modify iterator position to point behind the thing
-bool extractScript(MathArray & ar,
-       MathArray::iterator & pos, MathArray::iterator last, bool superscript)
-{
-       // nothing to get here
-       if (pos == last)
-               return false;
-
-       // is this a scriptinset?
-       if (!(*pos)->asScriptInset())
-               return false;
-
-       // do we want superscripts only?
-       if (superscript && !(*pos)->asScriptInset()->hasUp())
-               return false;
-
-       // it is a scriptinset, use it.
-       ar.push_back(*pos);
-       ++pos;
-       return true;
-}
-
-
-// try to extract an "argument" to some function.
-// returns position behind the argument
-MathArray::iterator extractArgument(MathArray & ar,
-       MathArray::iterator pos, MathArray::iterator last, bool function = false)
-{
-       // nothing to get here
-       if (pos == last)
-               return pos;
-
-       // something delimited _is_ an argument
-       if ((*pos)->asDelimInset()) {
-               // leave out delimiters if this is a function argument
-               if (function) {
-                       MathArray const & arg = (*pos)->asDelimInset()->cell(0);
-                       MathArray::const_iterator cur = arg.begin();
-                       MathArray::const_iterator end = arg.end();
-                       while (cur != end)
-                               ar.push_back(*cur++);
-               } else
-                       ar.push_back(*pos);
-               ++pos;
-               if (pos == last)
-                       return pos;
-               // if there's one, get following superscript only if this
-               // isn't a function argument
-               if (!function)
-                       extractScript(ar, pos, last, true);
-               return pos;
-       }
-
-       // always take the first thing, no matter what it is
-       ar.push_back(*pos);
-
-       // go ahead if possible
-       ++pos;
-       if (pos == last)
-               return pos;
-
-       // if the next item is a super/subscript, it most certainly belongs
-       // to the thing we have
-       extractScript(ar, pos, last, false);
-       if (pos == last)
-               return pos;
-
-       // but it might be more than that.
-       // FIXME: not implemented
-       //for (MathArray::iterator it = pos + 1; it != last; ++it) {
-       //      // always take the first thing, no matter
-       //      if (it == pos) {
-       //              ar.push_back(*it);
-       //              continue;
-       //      }
-       //}
-       return pos;
-}
-
-
-// returns sequence of char with same code starting at it up to end
-// it might be less, though...
-docstring charSequence
-       (MathArray::const_iterator it, MathArray::const_iterator end)
-{
-       docstring s;
-       for (; it != end && (*it)->asCharInset(); ++it)
-               s += (*it)->getChar();
-       return s;
-}
-
-
-void extractStrings(MathArray & ar)
-{
-       //lyxerr << "\nStrings from: " << ar << endl;
-       for (size_t i = 0; i < ar.size(); ++i) {
-               if (!ar[i]->asCharInset())
-                       continue;
-               docstring s = charSequence(ar.begin() + i, ar.end());
-               ar[i] = MathAtom(new InsetMathString(s));
-               ar.erase(i + 1, i + s.size());
-       }
-       //lyxerr << "\nStrings to: " << ar << endl;
-}
-
-
-void extractMatrices(MathArray & ar)
-{
-       //lyxerr << "\nMatrices from: " << ar << endl;
-       // first pass for explicitly delimited stuff
-       for (size_t i = 0; i < ar.size(); ++i) {
-               if (!ar[i]->asDelimInset())
-                       continue;
-               MathArray const & arr = ar[i]->asDelimInset()->cell(0);
-               if (arr.size() != 1)
-                       continue;
-               if (!arr.front()->asGridInset())
-                       continue;
-               ar[i] = MathAtom(new InsetMathMatrix(*(arr.front()->asGridInset())));
-       }
-
-       // second pass for AMS "pmatrix" etc
-       for (size_t i = 0; i < ar.size(); ++i)
-               if (ar[i]->asAMSArrayInset())
-                       ar[i] = MathAtom(new InsetMathMatrix(*(ar[i]->asGridInset())));
-       //lyxerr << "\nMatrices to: " << ar << endl;
-}
-
-
-// convert this inset somehow to a string
-bool extractString(MathAtom const & at, docstring & str)
-{
-       if (at->getChar()) {
-               str = docstring(1, at->getChar());
-               return true;
-       }
-       if (at->asStringInset()) {
-               str = at->asStringInset()->str();
-               return true;
-       }
-       return false;
-}
-
-
-// is this a known function?
-bool isKnownFunction(docstring const & str)
-{
-       for (int i = 0; *function_names[i]; ++i) {
-               if (str == function_names[i])
-                       return true;
-       }
-       return false;
-}
-
-
-// extract a function name from this inset
-bool extractFunctionName(MathAtom const & at, docstring & str)
-{
-       if (at->asSymbolInset()) {
-               str = at->asSymbolInset()->name();
-               return isKnownFunction(str);
-       }
-       if (at->asUnknownInset()) {
-               // assume it is well known...
-               str = at->name();
-               return true;
-       }
-       if (at->asFontInset() && at->name() == "mathrm") {
-               // assume it is well known...
-               MathArray const & ar = at->asFontInset()->cell(0);
-               str = charSequence(ar.begin(), ar.end());
-               return ar.size() == str.size();
-       }
-       return false;
-}
-
-
-// convert this inset somehow to a number
-bool extractNumber(MathArray const & ar, int & i)
-{
-       idocstringstream is(charSequence(ar.begin(), ar.end()));
-       is >> i;
-       return is;
-}
-
-
-bool extractNumber(MathArray const & ar, double & d)
-{
-       idocstringstream is(charSequence(ar.begin(), ar.end()));
-       is >> d;
-       return is;
-}
-
-
-bool testString(MathAtom const & at, docstring const & str)
-{
-       docstring s;
-       return extractString(at, s) && str == s;
-}
-
-
-bool testString(MathAtom const & at, char const * const str)
-{
-       return testString(at, from_ascii(str));
-}
-
-// search end of nested sequence
-MathArray::iterator endNestSearch(
-       MathArray::iterator it,
-       MathArray::iterator last,
-       TestItemFunc testOpen,
-       TestItemFunc testClose
-)
-{
-       for (int level = 0; it != last; ++it) {
-               if (testOpen(*it))
-                       ++level;
-               if (testClose(*it))
-                       --level;
-               if (level == 0)
-                       break;
-       }
-       return it;
-}
-
-
-// replace nested sequences by a real Insets
-void replaceNested(
-       MathArray & ar,
-       TestItemFunc testOpen,
-       TestItemFunc testClose,
-       ReplaceArgumentFunc replaceArg
-)
-{
-       // use indices rather than iterators for the loop  because we are going
-       // to modify the array.
-       for (size_t i = 0; i < ar.size(); ++i) {
-               // check whether this is the begin of the sequence
-               if (!testOpen(ar[i]))
-                       continue;
-
-               // search end of sequence
-               MathArray::iterator it = ar.begin() + i;
-               MathArray::iterator jt = endNestSearch(it, ar.end(), testOpen, testClose);
-               if (jt == ar.end())
-                       continue;
-
-               // replace the original stuff by the new inset
-               ar[i] = replaceArg(MathArray(it + 1, jt));
-               ar.erase(it + 1, jt + 1);
-       }
-}
-
-
-
-//
-// split scripts into seperate super- and subscript insets. sub goes in
-// front of super...
-//
-
-void splitScripts(MathArray & ar)
-{
-       //lyxerr << "\nScripts from: " << ar << endl;
-       for (size_t i = 0; i < ar.size(); ++i) {
-               InsetMathScript const * script = ar[i]->asScriptInset();
-
-               // is this a script inset and do we also have a superscript?
-               if (!script || !script->hasUp())
-                       continue;
-
-               // we must have a nucleus if we only have a superscript
-               if (!script->hasDown() && script->nuc().size() == 0)
-                       continue;
-
-               if (script->nuc().size() == 1) {
-                       // leave alone sums and integrals
-                       InsetMathSymbol const * sym =
-                               script->nuc().front()->asSymbolInset();
-                       if (sym && (sym->name() == "sum" || sym->name() == "int"))
-                               continue;
-               }
-
-               // create extra script inset and move superscript over
-               InsetMathScript * p = ar[i].nucleus()->asScriptInset();
-               auto_ptr<InsetMathScript> q(new InsetMathScript(true));
-               swap(q->up(), p->up());
-               p->removeScript(true);
-
-               // if we don't have a subscript, get rid of the ScriptInset
-               if (!script->hasDown()) {
-                       MathArray arg(p->nuc());
-                       MathArray::const_iterator it = arg.begin();
-                       MathArray::const_iterator et = arg.end();
-                       ar.erase(i);
-                       while (it != et)
-                               ar.insert(i++, *it++);
-               } else
-                       ++i;
-
-               // insert new inset behind
-               ar.insert(i, MathAtom(q.release()));
-       }
-       //lyxerr << "\nScripts to: " << ar << endl;
-}
-
-
-//
-// extract exp(...)
-//
-
-void extractExps(MathArray & ar)
-{
-       //lyxerr << "\nExps from: " << ar << endl;
-       for (size_t i = 0; i + 1 < ar.size(); ++i) {
-               // is this 'e'?
-               if (ar[i]->getChar() != 'e')
-                       continue;
-
-               // we need an exponent but no subscript
-               InsetMathScript const * sup = ar[i + 1]->asScriptInset();
-               if (!sup || sup->hasDown())
-                       continue;
-
-               // create a proper exp-inset as replacement
-               ar[i] = MathAtom(new InsetMathExFunc(from_ascii("exp"), sup->cell(1)));
-               ar.erase(i + 1);
-       }
-       //lyxerr << "\nExps to: " << ar << endl;
-}
-
-
-//
-// extract det(...)  from |matrix|
-//
-void extractDets(MathArray & ar)
-{
-       //lyxerr << "\ndet from: " << ar << endl;
-       for (MathArray::iterator it = ar.begin(); it != ar.end(); ++it) {
-               InsetMathDelim const * del = (*it)->asDelimInset();
-               if (!del)
-                       continue;
-               if (!del->isAbs())
-                       continue;
-               *it = MathAtom(new InsetMathExFunc(from_ascii("det"), del->cell(0)));
-       }
-       //lyxerr << "\ndet to: " << ar << endl;
-}
-
-
-//
-// search numbers
-//
-
-bool isDigitOrSimilar(char_type c)
-{
-       return ('0' <= c && c <= '9') || c == '.';
-}
-
-
-// returns sequence of digits
-docstring digitSequence
-       (MathArray::const_iterator it, MathArray::const_iterator end)
-{
-       docstring s;
-       for (; it != end && (*it)->asCharInset(); ++it) {
-               if (!isDigitOrSimilar((*it)->getChar()))
-                       break;
-               s += (*it)->getChar();
-       }
-       return s;
-}
-
-
-void extractNumbers(MathArray & ar)
-{
-       //lyxerr << "\nNumbers from: " << ar << endl;
-       for (size_t i = 0; i < ar.size(); ++i) {
-               if (!ar[i]->asCharInset())
-                       continue;
-               if (!isDigitOrSimilar(ar[i]->asCharInset()->getChar()))
-                       continue;
-
-               docstring s = digitSequence(ar.begin() + i, ar.end());
-
-               ar[i] = MathAtom(new InsetMathNumber(s));
-               ar.erase(i + 1, i + s.size());
-       }
-       //lyxerr << "\nNumbers to: " << ar << endl;
-}
-
-
-
-//
-// search delimiters
-//
-
-bool testOpenParen(MathAtom const & at)
-{
-       return testString(at, "(");
-}
-
-
-bool testCloseParen(MathAtom const & at)
-{
-       return testString(at, ")");
-}
-
-
-MathAtom replaceParenDelims(const MathArray & ar)
-{
-       return MathAtom(new InsetMathDelim(from_ascii("("), from_ascii(")"), ar));
-}
-
-
-bool testOpenBracket(MathAtom const & at)
-{
-       return testString(at, "[");
-}
-
-
-bool testCloseBracket(MathAtom const & at)
-{
-       return testString(at, "]");
-}
-
-
-MathAtom replaceBracketDelims(const MathArray & ar)
-{
-       return MathAtom(new InsetMathDelim(from_ascii("["), from_ascii("]"), ar));
-}
-
-
-// replace '('...')' and '['...']' sequences by a real InsetMathDelim
-void extractDelims(MathArray & ar)
-{
-       //lyxerr << "\nDelims from: " << ar << endl;
-       replaceNested(ar, testOpenParen, testCloseParen, replaceParenDelims);
-       replaceNested(ar, testOpenBracket, testCloseBracket, replaceBracketDelims);
-       //lyxerr << "\nDelims to: " << ar << endl;
-}
-
-
-
-//
-// search well-known functions
-//
-
-
-// replace 'f' '(...)' and 'f' '^n' '(...)' sequences by a real InsetMathExFunc
-// assume 'extractDelims' ran before
-void extractFunctions(MathArray & ar)
-{
-       // we need at least two items...
-       if (ar.size() < 2)
-               return;
-
-       //lyxerr << "\nFunctions from: " << ar << endl;
-       for (size_t i = 0; i + 1 < ar.size(); ++i) {
-               MathArray::iterator it = ar.begin() + i;
-               MathArray::iterator jt = it + 1;
-
-               docstring name;
-               // is it a function?
-               // it certainly is if it is well known...
-               if (!extractFunctionName(*it, name)) {
-                       // is this a user defined function?
-                       // it it probably not, if it doesn't have a name.
-                       if (!extractString(*it, name))
-                               continue;
-                       // it is not if it has no argument
-                       if (jt == ar.end())
-                               continue;
-                       // guess so, if this is followed by
-                       // a DelimInset with a single item in the cell
-                       InsetMathDelim const * del = (*jt)->asDelimInset();
-                       if (!del || del->cell(0).size() != 1)
-                               continue;
-                       // fall trough into main branch
-               }
-
-               // do we have an exponent like in
-               // 'sin' '^2' 'x' -> 'sin(x)' '^2'
-               MathArray exp;
-               extractScript(exp, jt, ar.end(), true);
-
-               // create a proper inset as replacement
-               auto_ptr<InsetMathExFunc> p(new InsetMathExFunc(name));
-
-               // jt points to the "argument". Get hold of this.
-               MathArray::iterator st = extractArgument(p->cell(0), jt, ar.end(), true);
-
-               // replace the function name by a real function inset
-               *it = MathAtom(p.release());
-
-               // remove the source of the argument from the array
-               ar.erase(it + 1, st);
-
-               // re-insert exponent
-               ar.insert(i + 1, exp);
-               //lyxerr << "\nFunctions to: " << ar << endl;
-       }
-}
-
-
-//
-// search integrals
-//
-
-bool testSymbol(MathAtom const & at, docstring const & name)
-{
-       return at->asSymbolInset() && at->asSymbolInset()->name() == name;
-}
-
-
-bool testSymbol(MathAtom const & at, char const * const name)
-{
-       return at->asSymbolInset() && at->asSymbolInset()->name() == from_ascii(name);
-}
-
-
-bool testIntSymbol(MathAtom const & at)
-{
-       return testSymbol(at, from_ascii("int"));
-}
-
-
-bool testIntegral(MathAtom const & at)
-{
-       return
-        testIntSymbol(at) ||
-               ( at->asScriptInset()
-                 && at->asScriptInset()->nuc().size()
-                       && testIntSymbol(at->asScriptInset()->nuc().back()) );
-}
-
-
-
-bool testIntDiff(MathAtom const & at)
-{
-       return testString(at, "d");
-}
-
-
-// replace '\int' ['_^'] x 'd''x'(...)' sequences by a real InsetMathExInt
-// assume 'extractDelims' ran before
-void extractIntegrals(MathArray & ar)
-{
-       // we need at least three items...
-       if (ar.size() < 3)
-               return;
-
-       //lyxerr << "\nIntegrals from: " << ar << endl;
-       for (size_t i = 0; i + 1 < ar.size(); ++i) {
-               MathArray::iterator it = ar.begin() + i;
-
-               // search 'd'
-               MathArray::iterator jt =
-                       endNestSearch(it, ar.end(), testIntegral, testIntDiff);
-
-               // something sensible found?
-               if (jt == ar.end())
-                       continue;
-
-               // is this a integral name?
-               if (!testIntegral(*it))
-                       continue;
-
-               // core ist part from behind the scripts to the 'd'
-               auto_ptr<InsetMathExInt> p(new InsetMathExInt(from_ascii("int")));
-
-               // handle scripts if available
-               if (!testIntSymbol(*it)) {
-                       p->cell(2) = (*it)->asScriptInset()->down();
-                       p->cell(3) = (*it)->asScriptInset()->up();
-               }
-               p->cell(0) = MathArray(it + 1, jt);
-
-               // use the "thing" behind the 'd' as differential
-               MathArray::iterator tt = extractArgument(p->cell(1), jt + 1, ar.end());
-
-               // remove used parts
-               ar.erase(it + 1, tt);
-               *it = MathAtom(p.release());
-       }
-       //lyxerr << "\nIntegrals to: " << ar << endl;
-}
-
-
-bool testTermDelimiter(MathAtom const & at)
-{
-       return testString(at, "+") || testString(at, "-");
-}
-
-
-// try to extract a "term", i.e., something delimited by '+' or '-'.
-// returns position behind the term
-MathArray::iterator extractTerm(MathArray & ar,
-       MathArray::iterator pos, MathArray::iterator last)
-{
-       while (pos != last && !testTermDelimiter(*pos)) {
-               ar.push_back(*pos);
-               ++pos;
-       }
-       return pos;
-}
-
-
-//
-// search sums
-//
-
-
-bool testEqualSign(MathAtom const & at)
-{
-       return testString(at, "=");
-}
-
-
-bool testSumSymbol(MathAtom const & p)
-{
-       return testSymbol(p, from_ascii("sum"));
-}
-
-
-bool testSum(MathAtom const & at)
-{
-       return
-        testSumSymbol(at) ||
-               ( at->asScriptInset()
-                 && at->asScriptInset()->nuc().size()
-                       && testSumSymbol(at->asScriptInset()->nuc().back()) );
-}
-
-
-// replace '\sum' ['_^'] f(x) sequences by a real InsetMathExInt
-// assume 'extractDelims' ran before
-void extractSums(MathArray & ar)
-{
-       // we need at least two items...
-       if (ar.size() < 2)
-               return;
-
-       //lyxerr << "\nSums from: " << ar << endl;
-       for (size_t i = 0; i + 1 < ar.size(); ++i) {
-               MathArray::iterator it = ar.begin() + i;
-
-               // is this a sum name?
-               if (!testSum(ar[i]))
-                       continue;
-
-               // create a proper inset as replacement
-               auto_ptr<InsetMathExInt> p(new InsetMathExInt(from_ascii("sum")));
-
-               // collect lower bound and summation index
-               InsetMathScript const * sub = ar[i]->asScriptInset();
-               if (sub && sub->hasDown()) {
-                       // try to figure out the summation index from the subscript
-                       MathArray const & ar = sub->down();
-                       MathArray::const_iterator xt =
-                               find_if(ar.begin(), ar.end(), &testEqualSign);
-                       if (xt != ar.end()) {
-                               // we found a '=', use everything in front of that as index,
-                               // and everything behind as lower index
-                               p->cell(1) = MathArray(ar.begin(), xt);
-                               p->cell(2) = MathArray(xt + 1, ar.end());
-                       } else {
-                               // use everything as summation index, don't use scripts.
-                               p->cell(1) = ar;
-                       }
-               }
-
-               // collect upper bound
-               if (sub && sub->hasUp())
-                       p->cell(3) = sub->up();
-
-               // use something  behind the script as core
-               MathArray::iterator tt = extractTerm(p->cell(0), it + 1, ar.end());
-
-               // cleanup
-               ar.erase(it + 1, tt);
-               *it = MathAtom(p.release());
-       }
-       //lyxerr << "\nSums to: " << ar << endl;
-}
-
-
-//
-// search differential stuff
-//
-
-// tests for 'd' or '\partial'
-bool testDiffItem(MathAtom const & at)
-{
-       if (testString(at, "d") || testSymbol(at, "partial"))
-               return true;
-
-       // we may have d^n .../d and splitScripts() has not yet seen it
-       InsetMathScript const * sup = at->asScriptInset();
-       if (sup && !sup->hasDown() && sup->hasUp() && sup->nuc().size() == 1) {
-               MathAtom const & ma = sup->nuc().front();
-               return testString(ma, "d") || testSymbol(ma, "partial");
-       }
-       return false;
-}
-
-
-bool testDiffArray(MathArray const & ar)
-{
-       return ar.size() && testDiffItem(ar.front());
-}
-
-
-bool testDiffFrac(MathAtom const & at)
-{
-       return
-               at->asFracInset()
-                       && testDiffArray(at->asFracInset()->cell(0))
-                       && testDiffArray(at->asFracInset()->cell(1));
-}
-
-
-void extractDiff(MathArray & ar)
-{
-       //lyxerr << "\nDiffs from: " << ar << endl;
-       for (size_t i = 0; i < ar.size(); ++i) {
-               MathArray::iterator it = ar.begin() + i;
-
-               // is this a "differential fraction"?
-               if (!testDiffFrac(*it))
-                       continue;
-
-               InsetMathFrac const * f = (*it)->asFracInset();
-               if (!f) {
-                       lyxerr << "should not happen" << endl;
-                       continue;
-               }
-
-               // create a proper diff inset
-               auto_ptr<InsetMathDiff> diff(new InsetMathDiff);
-
-               // collect function, let jt point behind last used item
-               MathArray::iterator jt = it + 1;
-               //int n = 1;
-               MathArray numer(f->cell(0));
-               splitScripts(numer);
-               if (numer.size() > 1 && numer[1]->asScriptInset()) {
-                       // this is something like  d^n f(x) / d... or  d^n / d...
-                       // FIXME
-                       //n = 1;
-                       if (numer.size() > 2)
-                               diff->cell(0) = MathArray(numer.begin() + 2, numer.end());
-                       else
-                               jt = extractTerm(diff->cell(0), jt, ar.end());
-               } else {
-                       // simply d f(x) / d... or  d/d...
-                       if (numer.size() > 1)
-                               diff->cell(0) = MathArray(numer.begin() + 1, numer.end());
-                       else
-                               jt = extractTerm(diff->cell(0), jt, ar.end());
-               }
-
-               // collect denominator parts
-               MathArray denom(f->cell(1));
-               splitScripts(denom);
-               for (MathArray::iterator dt = denom.begin(); dt != denom.end();) {
-                       // find the next 'd'
-                       MathArray::iterator et
-                               = find_if(dt + 1, denom.end(), &testDiffItem);
-
-                       // point before this
-                       MathArray::iterator st = et - 1;
-                       InsetMathScript const * script = (*st)->asScriptInset();
-                       if (script && script->hasUp()) {
-                               // things like   d.../dx^n
-                               int mult = 1;
-                               if (extractNumber(script->up(), mult)) {
-                                       //lyxerr << "mult: " << mult << endl;
-                                       for (int i = 0; i < mult; ++i)
-                                               diff->addDer(MathArray(dt + 1, st));
-                               }
-                       } else {
-                               // just  d.../dx
-                               diff->addDer(MathArray(dt + 1, et));
-                       }
-                       dt = et;
-               }
-
-               // cleanup
-               ar.erase(it + 1, jt);
-               *it = MathAtom(diff.release());
-       }
-       //lyxerr << "\nDiffs to: " << ar << endl;
-}
-
-
-//
-// search limits
-//
-
-
-bool testRightArrow(MathAtom const & at)
-{
-       return testSymbol(at, "to") || testSymbol(at, "rightarrow");
-}
-
-
-
-// replace '\lim_{x->x0} f(x)' sequences by a real InsetMathLim
-// assume 'extractDelims' ran before
-void extractLims(MathArray & ar)
-{
-       //lyxerr << "\nLimits from: " << ar << endl;
-       for (size_t i = 0; i < ar.size(); ++i) {
-               MathArray::iterator it = ar.begin() + i;
-
-               // must be a script inset with a subscript (without superscript)
-               InsetMathScript const * sub = (*it)->asScriptInset();
-               if (!sub || !sub->hasDown() || sub->hasUp() || sub->nuc().size() != 1)
-                       continue;
-
-               // is this a limit function?
-               if (!testSymbol(sub->nuc().front(), "lim"))
-                       continue;
-
-               // subscript must contain a -> symbol
-               MathArray const & s = sub->down();
-               MathArray::const_iterator st = find_if(s.begin(), s.end(), &testRightArrow);
-               if (st == s.end())
-                       continue;
-
-               // the -> splits the subscript int x and x0
-               MathArray x  = MathArray(s.begin(), st);
-               MathArray x0 = MathArray(st + 1, s.end());
-
-               // use something behind the script as core
-               MathArray f;
-               MathArray::iterator tt = extractTerm(f, it + 1, ar.end());
-
-               // cleanup
-               ar.erase(it + 1, tt);
-
-               // create a proper inset as replacement
-               *it = MathAtom(new InsetMathLim(f, x, x0));
-       }
-       //lyxerr << "\nLimits to: " << ar << endl;
-}
-
-
-//
-// combine searches
-//
-
-void extractStructure(MathArray & ar)
-{
-       //lyxerr << "\nStructure from: " << ar << endl;
-       splitScripts(ar);
-       extractDelims(ar);
-       extractIntegrals(ar);
-       extractSums(ar);
-       extractNumbers(ar);
-       extractMatrices(ar);
-       extractFunctions(ar);
-       extractDets(ar);
-       extractDiff(ar);
-       extractExps(ar);
-       extractLims(ar);
-       extractStrings(ar);
-       //lyxerr << "\nStructure to: " << ar << endl;
-}
-
-
-void write(MathArray const & dat, WriteStream & wi)
-{
-       MathArray ar = dat;
-       extractStrings(ar);
-       wi.firstitem() = true;
-       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) {
-               (*it)->write(wi);
-               wi.firstitem() = false;
-       }
-}
-
-
-void normalize(MathArray const & ar, NormalStream & os)
-{
-       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
-               (*it)->normalize(os);
-}
-
-
-void octave(MathArray const & dat, OctaveStream & os)
-{
-       MathArray ar = dat;
-       extractStructure(ar);
-       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
-               (*it)->octave(os);
-}
-
-
-void maple(MathArray const & dat, MapleStream & os)
-{
-       MathArray ar = dat;
-       extractStructure(ar);
-       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
-               (*it)->maple(os);
-}
-
-
-void maxima(MathArray const & dat, MaximaStream & os)
-{
-       MathArray ar = dat;
-       extractStructure(ar);
-       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
-               (*it)->maxima(os);
-}
-
-
-void mathematica(MathArray const & dat, MathematicaStream & os)
-{
-       MathArray ar = dat;
-       extractStructure(ar);
-       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
-               (*it)->mathematica(os);
-}
-
-
-void mathmlize(MathArray const & dat, MathStream & os)
-{
-       MathArray ar = dat;
-       extractStructure(ar);
-       if (ar.size() == 0)
-               os << "<mrow/>";
-       else if (ar.size() == 1)
-               os << ar.front();
-       else {
-               os << MTag("mrow");
-               for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
-                       (*it)->mathmlize(os);
-               os << ETag("mrow");
-       }
-}
-
-
-
-
-namespace {
-
-       std::string captureOutput(std::string const & cmd, std::string const & data)
-       {
-               // In order to avoid parsing problems with command interpreters
-               // we pass input data through a file
-               FileName const cas_tmpfile(tempName(FileName(), "casinput"));
-               if (cas_tmpfile.empty()) {
-                       lyxerr << "Warning: cannot create temporary file."
-                              << endl;
-                       return std::string();
-               }
-               std::ofstream os(cas_tmpfile.toFilesystemEncoding().c_str());
-               os << data << endl;
-               os.close();
-               std::string command =  cmd + " < "
-                       + quoteName(cas_tmpfile.toFilesystemEncoding());
-               lyxerr << "calling: " << cmd
-                      << "\ninput: '" << data << "'" << endl;
-               cmd_ret const ret = runCommand(command);
-               unlink(cas_tmpfile);
-               return ret.second;
-       }
-
-       size_t get_matching_brace(std::string const & str, size_t i)
-       {
-               int count = 1;
-               size_t n = str.size();
-               while (i < n) {
-                       i = str.find_first_of("{}", i+1);
-                       if (i == npos)
-                               return i;
-                       if (str[i] == '{')
-                               ++count;
-                       else
-                               --count;
-                       if (count == 0)
-                               return i;
-               }
-               return npos;
-       }
-
-       size_t get_matching_brace_back(std::string const & str, size_t i)
-       {
-               int count = 1;
-               while (i > 0) {
-                       i = str.find_last_of("{}", i-1);
-                       if (i == npos)
-                               return i;
-                       if (str[i] == '}')
-                               ++count;
-                       else
-                               --count;
-                       if (count == 0)
-                               return i;
-               }
-               return npos;
-       }
-
-       MathArray pipeThroughMaxima(docstring const &, MathArray const & ar)
-       {
-               odocstringstream os;
-               MaximaStream ms(os);
-               ms << ar;
-               docstring expr = os.str();
-               docstring const header = from_ascii("simpsum:true;");
-
-               std::string out;
-               for (int i = 0; i < 100; ++i) { // at most 100 attempts
-                       // try to fix missing '*' the hard way
-                       //
-                       // > echo "2x;" | maxima
-                       // ...
-                       // (C1) Incorrect syntax: x is not an infix operator
-                       // 2x;
-                       //  ^
-                       //
-                       lyxerr << "checking expr: '" << to_utf8(expr) << "'" << endl;
-                       docstring full = header + "tex(" + expr + ");";
-                       out = captureOutput("maxima", to_utf8(full));
-
-                       // leave loop if expression syntax is probably ok
-                       if (out.find("Incorrect syntax") == npos)
-                               break;
-
-                       // search line with "Incorrect syntax"
-                       istringstream is(out);
-                       std::string line;
-                       while (is) {
-                               getline(is, line);
-                               if (line.find("Incorrect syntax") != npos)
-                                       break;
-                       }
-
-                       // 2nd next line is the one with caret
-                       getline(is, line);
-                       getline(is, line);
-                       size_t pos = line.find('^');
-                       lyxerr << "found caret at pos: '" << pos << "'" << endl;
-                       if (pos == npos || pos < 4)
-                               break; // caret position not found
-                       pos -= 4; // skip the "tex(" part
-                       if (expr[pos] == '*')
-                               break; // two '*' in a row are definitely bad
-                       expr.insert(pos, from_ascii("*"));
-               }
-
-               vector<std::string> tmp = getVectorFromString(out, "$$");
-               if (tmp.size() < 2)
-                       return MathArray();
-
-               out = subst(tmp[1], "\\>", std::string());
-               lyxerr << "output: '" << out << "'" << endl;
-
-               // Ugly code that tries to make the result prettier
-               size_t i = out.find("\\mathchoice");
-               while (i != npos) {
-                       size_t j = get_matching_brace(out, i + 12);
-                       size_t k = get_matching_brace(out, j + 1);
-                       k = get_matching_brace(out, k + 1);
-                       k = get_matching_brace(out, k + 1);
-                       std::string mid = out.substr(i + 13, j - i - 13);
-                       if (mid.find("\\over") != npos)
-                               mid = '{' + mid + '}';
-                       out = out.substr(0,i)
-                               + mid
-                               + out.substr(k + 1);
-                       //lyxerr << "output: " << out << endl;
-                       i = out.find("\\mathchoice", i);
-                       break;
-               }
-
-               i = out.find("\\over");
-               while (i != npos) {
-                       size_t j = get_matching_brace_back(out, i - 1);
-                       if (j == npos || j == 0)
-                               break;
-                       size_t k = get_matching_brace(out, i + 5);
-                       if (k == npos || k + 1 == out.size())
-                               break;
-                       out = out.substr(0,j - 1)
-                               + "\\frac"
-                               + out.substr(j,i - j)
-                               + out.substr(i + 5,k - i - 4)
-                               + out.substr(k + 2);
-                       //lyxerr << "output: " << out << endl;
-                       i = out.find("\\over", i + 4);
-               }
-               MathArray res;
-               mathed_parse_cell(res, from_utf8(out));
-               return res;
-       }
-
-
-       MathArray pipeThroughMaple(docstring const & extra, MathArray const & ar)
-       {
-               std::string header = "readlib(latex):\n";
-
-               // remove the \\it for variable names
-               //"#`latex/csname_font` := `\\it `:"
-               header +=
-                       "`latex/csname_font` := ``:\n";
-
-               // export matrices in (...) instead of [...]
-               header +=
-                       "`latex/latex/matrix` := "
-                               "subs(`[`=`(`, `]`=`)`,"
-                                       "eval(`latex/latex/matrix`)):\n";
-
-               // replace \\cdots with proper '*'
-               header +=
-                       "`latex/latex/*` := "
-                               "subs(`\\,`=`\\cdot `,"
-                                       "eval(`latex/latex/*`)):\n";
-
-               // remove spurious \\noalign{\\medskip} in matrix output
-               header +=
-                       "`latex/latex/matrix`:= "
-                               "subs(`\\\\\\\\\\\\noalign{\\\\medskip}` = `\\\\\\\\`,"
-                                       "eval(`latex/latex/matrix`)):\n";
-
-               //"#`latex/latex/symbol` "
-               //      " := subs((\\'_\\' = \\'`\\_`\\',eval(`latex/latex/symbol`)): ";
-
-               std::string trailer = "quit;";
-               odocstringstream os;
-               MapleStream ms(os);
-               ms << ar;
-               std::string expr = to_utf8(os.str());
-               lyxerr << "ar: '" << ar << "'\n"
-                      << "ms: '" << expr << "'" << endl;
-
-               for (int i = 0; i < 100; ++i) { // at most 100 attempts
-                       // try to fix missing '*' the hard way by using mint
-                       //
-                       // ... > echo "1A;" | mint -i 1 -S -s -q
-                       // on line     1: 1A;
-                       //                 ^ syntax error -
-                       //                   Probably missing an operator such as * p
-                       //
-                       lyxerr << "checking expr: '" << expr << "'" << endl;
-                       string out = captureOutput("mint -i 1 -S -s -q -q", expr + ';');
-                       if (out.empty())
-                               break; // expression syntax is ok
-                       istringstream is(out);
-                       string line;
-                       getline(is, line);
-                       if (line.find("on line") != 0)
-                               break; // error message not identified
-                       getline(is, line);
-                       size_t pos = line.find('^');
-                       if (pos == string::npos || pos < 15)
-                               break; // caret position not found
-                       pos -= 15; // skip the "on line ..." part
-                       if (expr[pos] == '*' || (pos > 0 && expr[pos - 1] == '*'))
-                               break; // two '*' in a row are definitely bad
-                       expr.insert(pos, 1, '*');
-               }
-
-               // FIXME UNICODE Is utf8 encoding correct?
-               string full = "latex(" + to_utf8(extra) + '(' + expr + "));";
-               string out = captureOutput("maple -q", header + full + trailer);
-
-               // change \_ into _
-
-               //
-               MathArray res;
-               mathed_parse_cell(res, from_utf8(out));
-               return res;
-       }
-
-
-       MathArray pipeThroughOctave(docstring const &, MathArray const & ar)
-       {
-               odocstringstream os;
-               OctaveStream vs(os);
-               vs << ar;
-               string expr = to_utf8(os.str());
-               string out;
-
-               lyxerr << "pipe: ar: '" << ar << "'\n"
-                      << "pipe: expr: '" << expr << "'" << endl;
-
-               for (int i = 0; i < 100; ++i) { // at most 100 attempts
-                       //
-                       // try to fix missing '*' the hard way
-                       // parse error:
-                       // >>> ([[1 2 3 ];[2 3 1 ];[3 1 2 ]])([[1 2 3 ];[2 3 1 ];[3 1 2 ]])
-                       //                                   ^
-                       //
-                       lyxerr << "checking expr: '" << expr << "'" << endl;
-                       out = captureOutput("octave -q 2>&1", expr);
-                       lyxerr << "output: '" << out << "'" << endl;
-
-                       // leave loop if expression syntax is probably ok
-                       if (out.find("parse error:") == string::npos)
-                               break;
-
-                       // search line with single caret
-                       istringstream is(out);
-                       string line;
-                       while (is) {
-                               getline(is, line);
-                               lyxerr << "skipping line: '" << line << "'" << endl;
-                               if (line.find(">>> ") != string::npos)
-                                       break;
-                       }
-
-                       // found line with error, next line is the one with caret
-                       getline(is, line);
-                       size_t pos = line.find('^');
-                       lyxerr << "caret line: '" << line << "'" << endl;
-                       lyxerr << "found caret at pos: '" << pos << "'" << endl;
-                       if (pos == string::npos || pos < 4)
-                               break; // caret position not found
-                       pos -= 4; // skip the ">>> " part
-                       if (expr[pos] == '*')
-                               break; // two '*' in a row are definitely bad
-                       expr.insert(pos, 1, '*');
-               }
-
-               // remove 'ans = ' taking into account that there may be an
-               // ansi control sequence before, such as '\033[?1034hans = '
-               size_t i = out.find("ans = ");
-               if (i == string::npos)
-                       return MathArray();
-               out = out.substr(i + 6);
-
-               // parse output as matrix or single number
-               MathAtom at(new InsetMathArray(from_ascii("array"), from_utf8(out)));
-               InsetMathArray const * mat = at->asArrayInset();
-               MathArray res;
-               if (mat->ncols() == 1 && mat->nrows() == 1)
-                       res.append(mat->cell(0));
-               else {
-                       res.push_back(MathAtom(new InsetMathDelim(from_ascii("("), from_ascii(")"))));
-                       res.back().nucleus()->cell(0).push_back(at);
-               }
-               return res;
-       }
-
-
-       string fromMathematicaName(string const & name)
-       {
-               if (name == "Sin")    return "sin";
-               if (name == "Sinh")   return "sinh";
-               if (name == "ArcSin") return "arcsin";
-               if (name == "Cos")    return "cos";
-               if (name == "Cosh")   return "cosh";
-               if (name == "ArcCos") return "arccos";
-               if (name == "Tan")    return "tan";
-               if (name == "Tanh")   return "tanh";
-               if (name == "ArcTan") return "arctan";
-               if (name == "Cot")    return "cot";
-               if (name == "Coth")   return "coth";
-               if (name == "Csc")    return "csc";
-               if (name == "Sec")    return "sec";
-               if (name == "Exp")    return "exp";
-               if (name == "Log")    return "log";
-               if (name == "Arg" )   return "arg";
-               if (name == "Det" )   return "det";
-               if (name == "GCD" )   return "gcd";
-               if (name == "Max" )   return "max";
-               if (name == "Min" )   return "min";
-               if (name == "Erf" )   return "erf";
-               if (name == "Erfc" )  return "erfc";
-               return name;
-       }
-
-
-       void prettifyMathematicaOutput(string & out, string const & macroName,
-                       bool roman, bool translate)
-       {
-               string const macro = "\\" + macroName + "{";
-               size_t const len = macro.length();
-               size_t i = out.find(macro);
-
-               while (i != npos) {
-                       size_t const j = get_matching_brace(out, i + len);
-                       string const name = out.substr(i + len, j - i - len);
-                       out = out.substr(0, i)
-                               + (roman ? "\\mathrm{" : "")
-                               + (translate ? fromMathematicaName(name) : name)
-                               + out.substr(roman ? j : j + 1);
-                       //lyxerr << "output: " << out << endl;
-                       i = out.find(macro, i);
-               }
-       }
-
-
-       MathArray pipeThroughMathematica(docstring const &, MathArray const & ar)
-       {
-               odocstringstream os;
-               MathematicaStream ms(os);
-               ms << ar;
-               // FIXME UNICODE Is utf8 encoding correct?
-               string const expr = to_utf8(os.str());
-               string out;
-
-               lyxerr << "expr: '" << expr << "'" << endl;
-
-               string const full = "TeXForm[" + expr + "]";
-               out = captureOutput("math", full);
-               lyxerr << "output: '" << out << "'" << endl;
-
-               size_t pos1 = out.find("Out[1]//TeXForm= ");
-               size_t pos2 = out.find("In[2]:=");
-
-               if (pos1 == string::npos || pos2 == string::npos)
-                       return MathArray();
-
-               // get everything from pos1+17 to pos2
-               out = out.substr(pos1 + 17, pos2 - pos1 - 17);
-               out = subst(subst(out, '\r', ' '), '\n', ' ');
-
-               // tries to make the result prettier
-               prettifyMathematicaOutput(out, "Mfunction", true, true);
-               prettifyMathematicaOutput(out, "Muserfunction", true, false);
-               prettifyMathematicaOutput(out, "Mvariable", false, false);
-
-               MathArray res;
-               mathed_parse_cell(res, from_utf8(out));
-               return res;
-       }
-
-}
-
-
-MathArray pipeThroughExtern(string const & lang, docstring const & extra,
-       MathArray const & ar)
-{
-       if (lang == "octave")
-               return pipeThroughOctave(extra, ar);
-
-       if (lang == "maxima")
-               return pipeThroughMaxima(extra, ar);
-
-       if (lang == "maple")
-               return pipeThroughMaple(extra, ar);
-
-       if (lang == "mathematica")
-               return pipeThroughMathematica(extra, ar);
-
-       // create normalized expression
-       odocstringstream os;
-       NormalStream ns(os);
-       os << '[' << extra << ' ';
-       ns << ar;
-       os << ']';
-       // FIXME UNICODE Is utf8 encoding correct?
-       string data = to_utf8(os.str());
-
-       // search external script
-       support::FileName const file = libFileSearch("mathed", "extern_" + lang);
-       if (file.empty()) {
-               lyxerr << "converter to '" << lang << "' not found" << endl;
-               return MathArray();
-       }
-
-       // run external sript
-       string out = captureOutput(file.absFilename(), data);
-       MathArray res;
-       mathed_parse_cell(res, from_utf8(out));
-       return res;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathExtern.cpp b/src/mathed/MathExtern.cpp
new file mode 100644 (file)
index 0000000..36ca801
--- /dev/null
@@ -0,0 +1,1452 @@
+/**
+ * \file MathExtern.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+// This file contains most of the magic that extracts "context
+// information" from the unstructered layout-oriented stuff in an
+// MathArray.
+
+#include <config.h>
+
+#include "MathExtern.h"
+#include "InsetMathArray.h"
+#include "InsetMathChar.h"
+#include "InsetMathDelim.h"
+#include "MathData.h"
+#include "InsetMathDiff.h"
+#include "InsetMathExFunc.h"
+#include "InsetMathExInt.h"
+#include "InsetMathFont.h"
+#include "InsetMathFrac.h"
+#include "InsetMathLim.h"
+#include "InsetMathMatrix.h"
+#include "MathStream.h"
+#include "InsetMathNumber.h"
+#include "InsetMathScript.h"
+#include "InsetMathString.h"
+#include "InsetMathSymbol.h"
+#include "MathParser.h"
+#include "debug.h"
+#include "support/filetools.h"
+#include "support/lstrings.h"
+#include "support/lyxlib.h"
+#include "frontends/controllers/ControlMath.h"
+
+#include <algorithm>
+#include <sstream>
+#include <fstream>
+
+
+namespace lyx {
+
+using support::cmd_ret;
+using support::getVectorFromString;
+using support::libFileSearch;
+using support::runCommand;
+using support::FileName;
+using support::quoteName;
+using support::tempName;
+using support::unlink;
+using support::subst;
+
+using frontend::function_names;
+
+using std::endl;
+using std::find_if;
+using std::auto_ptr;
+using std::istringstream;
+using std::ostream;
+using std::swap;
+using std::string;
+using std::vector;
+
+static size_t const npos = lyx::docstring::npos;
+
+// define a function for tests
+typedef bool TestItemFunc(MathAtom const &);
+
+// define a function for replacing subexpressions
+typedef MathAtom ReplaceArgumentFunc(const MathArray & ar);
+
+
+
+// try to extract a super/subscript
+// modify iterator position to point behind the thing
+bool extractScript(MathArray & ar,
+       MathArray::iterator & pos, MathArray::iterator last, bool superscript)
+{
+       // nothing to get here
+       if (pos == last)
+               return false;
+
+       // is this a scriptinset?
+       if (!(*pos)->asScriptInset())
+               return false;
+
+       // do we want superscripts only?
+       if (superscript && !(*pos)->asScriptInset()->hasUp())
+               return false;
+
+       // it is a scriptinset, use it.
+       ar.push_back(*pos);
+       ++pos;
+       return true;
+}
+
+
+// try to extract an "argument" to some function.
+// returns position behind the argument
+MathArray::iterator extractArgument(MathArray & ar,
+       MathArray::iterator pos, MathArray::iterator last, bool function = false)
+{
+       // nothing to get here
+       if (pos == last)
+               return pos;
+
+       // something delimited _is_ an argument
+       if ((*pos)->asDelimInset()) {
+               // leave out delimiters if this is a function argument
+               if (function) {
+                       MathArray const & arg = (*pos)->asDelimInset()->cell(0);
+                       MathArray::const_iterator cur = arg.begin();
+                       MathArray::const_iterator end = arg.end();
+                       while (cur != end)
+                               ar.push_back(*cur++);
+               } else
+                       ar.push_back(*pos);
+               ++pos;
+               if (pos == last)
+                       return pos;
+               // if there's one, get following superscript only if this
+               // isn't a function argument
+               if (!function)
+                       extractScript(ar, pos, last, true);
+               return pos;
+       }
+
+       // always take the first thing, no matter what it is
+       ar.push_back(*pos);
+
+       // go ahead if possible
+       ++pos;
+       if (pos == last)
+               return pos;
+
+       // if the next item is a super/subscript, it most certainly belongs
+       // to the thing we have
+       extractScript(ar, pos, last, false);
+       if (pos == last)
+               return pos;
+
+       // but it might be more than that.
+       // FIXME: not implemented
+       //for (MathArray::iterator it = pos + 1; it != last; ++it) {
+       //      // always take the first thing, no matter
+       //      if (it == pos) {
+       //              ar.push_back(*it);
+       //              continue;
+       //      }
+       //}
+       return pos;
+}
+
+
+// returns sequence of char with same code starting at it up to end
+// it might be less, though...
+docstring charSequence
+       (MathArray::const_iterator it, MathArray::const_iterator end)
+{
+       docstring s;
+       for (; it != end && (*it)->asCharInset(); ++it)
+               s += (*it)->getChar();
+       return s;
+}
+
+
+void extractStrings(MathArray & ar)
+{
+       //lyxerr << "\nStrings from: " << ar << endl;
+       for (size_t i = 0; i < ar.size(); ++i) {
+               if (!ar[i]->asCharInset())
+                       continue;
+               docstring s = charSequence(ar.begin() + i, ar.end());
+               ar[i] = MathAtom(new InsetMathString(s));
+               ar.erase(i + 1, i + s.size());
+       }
+       //lyxerr << "\nStrings to: " << ar << endl;
+}
+
+
+void extractMatrices(MathArray & ar)
+{
+       //lyxerr << "\nMatrices from: " << ar << endl;
+       // first pass for explicitly delimited stuff
+       for (size_t i = 0; i < ar.size(); ++i) {
+               if (!ar[i]->asDelimInset())
+                       continue;
+               MathArray const & arr = ar[i]->asDelimInset()->cell(0);
+               if (arr.size() != 1)
+                       continue;
+               if (!arr.front()->asGridInset())
+                       continue;
+               ar[i] = MathAtom(new InsetMathMatrix(*(arr.front()->asGridInset())));
+       }
+
+       // second pass for AMS "pmatrix" etc
+       for (size_t i = 0; i < ar.size(); ++i)
+               if (ar[i]->asAMSArrayInset())
+                       ar[i] = MathAtom(new InsetMathMatrix(*(ar[i]->asGridInset())));
+       //lyxerr << "\nMatrices to: " << ar << endl;
+}
+
+
+// convert this inset somehow to a string
+bool extractString(MathAtom const & at, docstring & str)
+{
+       if (at->getChar()) {
+               str = docstring(1, at->getChar());
+               return true;
+       }
+       if (at->asStringInset()) {
+               str = at->asStringInset()->str();
+               return true;
+       }
+       return false;
+}
+
+
+// is this a known function?
+bool isKnownFunction(docstring const & str)
+{
+       for (int i = 0; *function_names[i]; ++i) {
+               if (str == function_names[i])
+                       return true;
+       }
+       return false;
+}
+
+
+// extract a function name from this inset
+bool extractFunctionName(MathAtom const & at, docstring & str)
+{
+       if (at->asSymbolInset()) {
+               str = at->asSymbolInset()->name();
+               return isKnownFunction(str);
+       }
+       if (at->asUnknownInset()) {
+               // assume it is well known...
+               str = at->name();
+               return true;
+       }
+       if (at->asFontInset() && at->name() == "mathrm") {
+               // assume it is well known...
+               MathArray const & ar = at->asFontInset()->cell(0);
+               str = charSequence(ar.begin(), ar.end());
+               return ar.size() == str.size();
+       }
+       return false;
+}
+
+
+// convert this inset somehow to a number
+bool extractNumber(MathArray const & ar, int & i)
+{
+       idocstringstream is(charSequence(ar.begin(), ar.end()));
+       is >> i;
+       return is;
+}
+
+
+bool extractNumber(MathArray const & ar, double & d)
+{
+       idocstringstream is(charSequence(ar.begin(), ar.end()));
+       is >> d;
+       return is;
+}
+
+
+bool testString(MathAtom const & at, docstring const & str)
+{
+       docstring s;
+       return extractString(at, s) && str == s;
+}
+
+
+bool testString(MathAtom const & at, char const * const str)
+{
+       return testString(at, from_ascii(str));
+}
+
+// search end of nested sequence
+MathArray::iterator endNestSearch(
+       MathArray::iterator it,
+       MathArray::iterator last,
+       TestItemFunc testOpen,
+       TestItemFunc testClose
+)
+{
+       for (int level = 0; it != last; ++it) {
+               if (testOpen(*it))
+                       ++level;
+               if (testClose(*it))
+                       --level;
+               if (level == 0)
+                       break;
+       }
+       return it;
+}
+
+
+// replace nested sequences by a real Insets
+void replaceNested(
+       MathArray & ar,
+       TestItemFunc testOpen,
+       TestItemFunc testClose,
+       ReplaceArgumentFunc replaceArg
+)
+{
+       // use indices rather than iterators for the loop  because we are going
+       // to modify the array.
+       for (size_t i = 0; i < ar.size(); ++i) {
+               // check whether this is the begin of the sequence
+               if (!testOpen(ar[i]))
+                       continue;
+
+               // search end of sequence
+               MathArray::iterator it = ar.begin() + i;
+               MathArray::iterator jt = endNestSearch(it, ar.end(), testOpen, testClose);
+               if (jt == ar.end())
+                       continue;
+
+               // replace the original stuff by the new inset
+               ar[i] = replaceArg(MathArray(it + 1, jt));
+               ar.erase(it + 1, jt + 1);
+       }
+}
+
+
+
+//
+// split scripts into seperate super- and subscript insets. sub goes in
+// front of super...
+//
+
+void splitScripts(MathArray & ar)
+{
+       //lyxerr << "\nScripts from: " << ar << endl;
+       for (size_t i = 0; i < ar.size(); ++i) {
+               InsetMathScript const * script = ar[i]->asScriptInset();
+
+               // is this a script inset and do we also have a superscript?
+               if (!script || !script->hasUp())
+                       continue;
+
+               // we must have a nucleus if we only have a superscript
+               if (!script->hasDown() && script->nuc().size() == 0)
+                       continue;
+
+               if (script->nuc().size() == 1) {
+                       // leave alone sums and integrals
+                       InsetMathSymbol const * sym =
+                               script->nuc().front()->asSymbolInset();
+                       if (sym && (sym->name() == "sum" || sym->name() == "int"))
+                               continue;
+               }
+
+               // create extra script inset and move superscript over
+               InsetMathScript * p = ar[i].nucleus()->asScriptInset();
+               auto_ptr<InsetMathScript> q(new InsetMathScript(true));
+               swap(q->up(), p->up());
+               p->removeScript(true);
+
+               // if we don't have a subscript, get rid of the ScriptInset
+               if (!script->hasDown()) {
+                       MathArray arg(p->nuc());
+                       MathArray::const_iterator it = arg.begin();
+                       MathArray::const_iterator et = arg.end();
+                       ar.erase(i);
+                       while (it != et)
+                               ar.insert(i++, *it++);
+               } else
+                       ++i;
+
+               // insert new inset behind
+               ar.insert(i, MathAtom(q.release()));
+       }
+       //lyxerr << "\nScripts to: " << ar << endl;
+}
+
+
+//
+// extract exp(...)
+//
+
+void extractExps(MathArray & ar)
+{
+       //lyxerr << "\nExps from: " << ar << endl;
+       for (size_t i = 0; i + 1 < ar.size(); ++i) {
+               // is this 'e'?
+               if (ar[i]->getChar() != 'e')
+                       continue;
+
+               // we need an exponent but no subscript
+               InsetMathScript const * sup = ar[i + 1]->asScriptInset();
+               if (!sup || sup->hasDown())
+                       continue;
+
+               // create a proper exp-inset as replacement
+               ar[i] = MathAtom(new InsetMathExFunc(from_ascii("exp"), sup->cell(1)));
+               ar.erase(i + 1);
+       }
+       //lyxerr << "\nExps to: " << ar << endl;
+}
+
+
+//
+// extract det(...)  from |matrix|
+//
+void extractDets(MathArray & ar)
+{
+       //lyxerr << "\ndet from: " << ar << endl;
+       for (MathArray::iterator it = ar.begin(); it != ar.end(); ++it) {
+               InsetMathDelim const * del = (*it)->asDelimInset();
+               if (!del)
+                       continue;
+               if (!del->isAbs())
+                       continue;
+               *it = MathAtom(new InsetMathExFunc(from_ascii("det"), del->cell(0)));
+       }
+       //lyxerr << "\ndet to: " << ar << endl;
+}
+
+
+//
+// search numbers
+//
+
+bool isDigitOrSimilar(char_type c)
+{
+       return ('0' <= c && c <= '9') || c == '.';
+}
+
+
+// returns sequence of digits
+docstring digitSequence
+       (MathArray::const_iterator it, MathArray::const_iterator end)
+{
+       docstring s;
+       for (; it != end && (*it)->asCharInset(); ++it) {
+               if (!isDigitOrSimilar((*it)->getChar()))
+                       break;
+               s += (*it)->getChar();
+       }
+       return s;
+}
+
+
+void extractNumbers(MathArray & ar)
+{
+       //lyxerr << "\nNumbers from: " << ar << endl;
+       for (size_t i = 0; i < ar.size(); ++i) {
+               if (!ar[i]->asCharInset())
+                       continue;
+               if (!isDigitOrSimilar(ar[i]->asCharInset()->getChar()))
+                       continue;
+
+               docstring s = digitSequence(ar.begin() + i, ar.end());
+
+               ar[i] = MathAtom(new InsetMathNumber(s));
+               ar.erase(i + 1, i + s.size());
+       }
+       //lyxerr << "\nNumbers to: " << ar << endl;
+}
+
+
+
+//
+// search delimiters
+//
+
+bool testOpenParen(MathAtom const & at)
+{
+       return testString(at, "(");
+}
+
+
+bool testCloseParen(MathAtom const & at)
+{
+       return testString(at, ")");
+}
+
+
+MathAtom replaceParenDelims(const MathArray & ar)
+{
+       return MathAtom(new InsetMathDelim(from_ascii("("), from_ascii(")"), ar));
+}
+
+
+bool testOpenBracket(MathAtom const & at)
+{
+       return testString(at, "[");
+}
+
+
+bool testCloseBracket(MathAtom const & at)
+{
+       return testString(at, "]");
+}
+
+
+MathAtom replaceBracketDelims(const MathArray & ar)
+{
+       return MathAtom(new InsetMathDelim(from_ascii("["), from_ascii("]"), ar));
+}
+
+
+// replace '('...')' and '['...']' sequences by a real InsetMathDelim
+void extractDelims(MathArray & ar)
+{
+       //lyxerr << "\nDelims from: " << ar << endl;
+       replaceNested(ar, testOpenParen, testCloseParen, replaceParenDelims);
+       replaceNested(ar, testOpenBracket, testCloseBracket, replaceBracketDelims);
+       //lyxerr << "\nDelims to: " << ar << endl;
+}
+
+
+
+//
+// search well-known functions
+//
+
+
+// replace 'f' '(...)' and 'f' '^n' '(...)' sequences by a real InsetMathExFunc
+// assume 'extractDelims' ran before
+void extractFunctions(MathArray & ar)
+{
+       // we need at least two items...
+       if (ar.size() < 2)
+               return;
+
+       //lyxerr << "\nFunctions from: " << ar << endl;
+       for (size_t i = 0; i + 1 < ar.size(); ++i) {
+               MathArray::iterator it = ar.begin() + i;
+               MathArray::iterator jt = it + 1;
+
+               docstring name;
+               // is it a function?
+               // it certainly is if it is well known...
+               if (!extractFunctionName(*it, name)) {
+                       // is this a user defined function?
+                       // it it probably not, if it doesn't have a name.
+                       if (!extractString(*it, name))
+                               continue;
+                       // it is not if it has no argument
+                       if (jt == ar.end())
+                               continue;
+                       // guess so, if this is followed by
+                       // a DelimInset with a single item in the cell
+                       InsetMathDelim const * del = (*jt)->asDelimInset();
+                       if (!del || del->cell(0).size() != 1)
+                               continue;
+                       // fall trough into main branch
+               }
+
+               // do we have an exponent like in
+               // 'sin' '^2' 'x' -> 'sin(x)' '^2'
+               MathArray exp;
+               extractScript(exp, jt, ar.end(), true);
+
+               // create a proper inset as replacement
+               auto_ptr<InsetMathExFunc> p(new InsetMathExFunc(name));
+
+               // jt points to the "argument". Get hold of this.
+               MathArray::iterator st = extractArgument(p->cell(0), jt, ar.end(), true);
+
+               // replace the function name by a real function inset
+               *it = MathAtom(p.release());
+
+               // remove the source of the argument from the array
+               ar.erase(it + 1, st);
+
+               // re-insert exponent
+               ar.insert(i + 1, exp);
+               //lyxerr << "\nFunctions to: " << ar << endl;
+       }
+}
+
+
+//
+// search integrals
+//
+
+bool testSymbol(MathAtom const & at, docstring const & name)
+{
+       return at->asSymbolInset() && at->asSymbolInset()->name() == name;
+}
+
+
+bool testSymbol(MathAtom const & at, char const * const name)
+{
+       return at->asSymbolInset() && at->asSymbolInset()->name() == from_ascii(name);
+}
+
+
+bool testIntSymbol(MathAtom const & at)
+{
+       return testSymbol(at, from_ascii("int"));
+}
+
+
+bool testIntegral(MathAtom const & at)
+{
+       return
+        testIntSymbol(at) ||
+               ( at->asScriptInset()
+                 && at->asScriptInset()->nuc().size()
+                       && testIntSymbol(at->asScriptInset()->nuc().back()) );
+}
+
+
+
+bool testIntDiff(MathAtom const & at)
+{
+       return testString(at, "d");
+}
+
+
+// replace '\int' ['_^'] x 'd''x'(...)' sequences by a real InsetMathExInt
+// assume 'extractDelims' ran before
+void extractIntegrals(MathArray & ar)
+{
+       // we need at least three items...
+       if (ar.size() < 3)
+               return;
+
+       //lyxerr << "\nIntegrals from: " << ar << endl;
+       for (size_t i = 0; i + 1 < ar.size(); ++i) {
+               MathArray::iterator it = ar.begin() + i;
+
+               // search 'd'
+               MathArray::iterator jt =
+                       endNestSearch(it, ar.end(), testIntegral, testIntDiff);
+
+               // something sensible found?
+               if (jt == ar.end())
+                       continue;
+
+               // is this a integral name?
+               if (!testIntegral(*it))
+                       continue;
+
+               // core ist part from behind the scripts to the 'd'
+               auto_ptr<InsetMathExInt> p(new InsetMathExInt(from_ascii("int")));
+
+               // handle scripts if available
+               if (!testIntSymbol(*it)) {
+                       p->cell(2) = (*it)->asScriptInset()->down();
+                       p->cell(3) = (*it)->asScriptInset()->up();
+               }
+               p->cell(0) = MathArray(it + 1, jt);
+
+               // use the "thing" behind the 'd' as differential
+               MathArray::iterator tt = extractArgument(p->cell(1), jt + 1, ar.end());
+
+               // remove used parts
+               ar.erase(it + 1, tt);
+               *it = MathAtom(p.release());
+       }
+       //lyxerr << "\nIntegrals to: " << ar << endl;
+}
+
+
+bool testTermDelimiter(MathAtom const & at)
+{
+       return testString(at, "+") || testString(at, "-");
+}
+
+
+// try to extract a "term", i.e., something delimited by '+' or '-'.
+// returns position behind the term
+MathArray::iterator extractTerm(MathArray & ar,
+       MathArray::iterator pos, MathArray::iterator last)
+{
+       while (pos != last && !testTermDelimiter(*pos)) {
+               ar.push_back(*pos);
+               ++pos;
+       }
+       return pos;
+}
+
+
+//
+// search sums
+//
+
+
+bool testEqualSign(MathAtom const & at)
+{
+       return testString(at, "=");
+}
+
+
+bool testSumSymbol(MathAtom const & p)
+{
+       return testSymbol(p, from_ascii("sum"));
+}
+
+
+bool testSum(MathAtom const & at)
+{
+       return
+        testSumSymbol(at) ||
+               ( at->asScriptInset()
+                 && at->asScriptInset()->nuc().size()
+                       && testSumSymbol(at->asScriptInset()->nuc().back()) );
+}
+
+
+// replace '\sum' ['_^'] f(x) sequences by a real InsetMathExInt
+// assume 'extractDelims' ran before
+void extractSums(MathArray & ar)
+{
+       // we need at least two items...
+       if (ar.size() < 2)
+               return;
+
+       //lyxerr << "\nSums from: " << ar << endl;
+       for (size_t i = 0; i + 1 < ar.size(); ++i) {
+               MathArray::iterator it = ar.begin() + i;
+
+               // is this a sum name?
+               if (!testSum(ar[i]))
+                       continue;
+
+               // create a proper inset as replacement
+               auto_ptr<InsetMathExInt> p(new InsetMathExInt(from_ascii("sum")));
+
+               // collect lower bound and summation index
+               InsetMathScript const * sub = ar[i]->asScriptInset();
+               if (sub && sub->hasDown()) {
+                       // try to figure out the summation index from the subscript
+                       MathArray const & ar = sub->down();
+                       MathArray::const_iterator xt =
+                               find_if(ar.begin(), ar.end(), &testEqualSign);
+                       if (xt != ar.end()) {
+                               // we found a '=', use everything in front of that as index,
+                               // and everything behind as lower index
+                               p->cell(1) = MathArray(ar.begin(), xt);
+                               p->cell(2) = MathArray(xt + 1, ar.end());
+                       } else {
+                               // use everything as summation index, don't use scripts.
+                               p->cell(1) = ar;
+                       }
+               }
+
+               // collect upper bound
+               if (sub && sub->hasUp())
+                       p->cell(3) = sub->up();
+
+               // use something  behind the script as core
+               MathArray::iterator tt = extractTerm(p->cell(0), it + 1, ar.end());
+
+               // cleanup
+               ar.erase(it + 1, tt);
+               *it = MathAtom(p.release());
+       }
+       //lyxerr << "\nSums to: " << ar << endl;
+}
+
+
+//
+// search differential stuff
+//
+
+// tests for 'd' or '\partial'
+bool testDiffItem(MathAtom const & at)
+{
+       if (testString(at, "d") || testSymbol(at, "partial"))
+               return true;
+
+       // we may have d^n .../d and splitScripts() has not yet seen it
+       InsetMathScript const * sup = at->asScriptInset();
+       if (sup && !sup->hasDown() && sup->hasUp() && sup->nuc().size() == 1) {
+               MathAtom const & ma = sup->nuc().front();
+               return testString(ma, "d") || testSymbol(ma, "partial");
+       }
+       return false;
+}
+
+
+bool testDiffArray(MathArray const & ar)
+{
+       return ar.size() && testDiffItem(ar.front());
+}
+
+
+bool testDiffFrac(MathAtom const & at)
+{
+       return
+               at->asFracInset()
+                       && testDiffArray(at->asFracInset()->cell(0))
+                       && testDiffArray(at->asFracInset()->cell(1));
+}
+
+
+void extractDiff(MathArray & ar)
+{
+       //lyxerr << "\nDiffs from: " << ar << endl;
+       for (size_t i = 0; i < ar.size(); ++i) {
+               MathArray::iterator it = ar.begin() + i;
+
+               // is this a "differential fraction"?
+               if (!testDiffFrac(*it))
+                       continue;
+
+               InsetMathFrac const * f = (*it)->asFracInset();
+               if (!f) {
+                       lyxerr << "should not happen" << endl;
+                       continue;
+               }
+
+               // create a proper diff inset
+               auto_ptr<InsetMathDiff> diff(new InsetMathDiff);
+
+               // collect function, let jt point behind last used item
+               MathArray::iterator jt = it + 1;
+               //int n = 1;
+               MathArray numer(f->cell(0));
+               splitScripts(numer);
+               if (numer.size() > 1 && numer[1]->asScriptInset()) {
+                       // this is something like  d^n f(x) / d... or  d^n / d...
+                       // FIXME
+                       //n = 1;
+                       if (numer.size() > 2)
+                               diff->cell(0) = MathArray(numer.begin() + 2, numer.end());
+                       else
+                               jt = extractTerm(diff->cell(0), jt, ar.end());
+               } else {
+                       // simply d f(x) / d... or  d/d...
+                       if (numer.size() > 1)
+                               diff->cell(0) = MathArray(numer.begin() + 1, numer.end());
+                       else
+                               jt = extractTerm(diff->cell(0), jt, ar.end());
+               }
+
+               // collect denominator parts
+               MathArray denom(f->cell(1));
+               splitScripts(denom);
+               for (MathArray::iterator dt = denom.begin(); dt != denom.end();) {
+                       // find the next 'd'
+                       MathArray::iterator et
+                               = find_if(dt + 1, denom.end(), &testDiffItem);
+
+                       // point before this
+                       MathArray::iterator st = et - 1;
+                       InsetMathScript const * script = (*st)->asScriptInset();
+                       if (script && script->hasUp()) {
+                               // things like   d.../dx^n
+                               int mult = 1;
+                               if (extractNumber(script->up(), mult)) {
+                                       //lyxerr << "mult: " << mult << endl;
+                                       for (int i = 0; i < mult; ++i)
+                                               diff->addDer(MathArray(dt + 1, st));
+                               }
+                       } else {
+                               // just  d.../dx
+                               diff->addDer(MathArray(dt + 1, et));
+                       }
+                       dt = et;
+               }
+
+               // cleanup
+               ar.erase(it + 1, jt);
+               *it = MathAtom(diff.release());
+       }
+       //lyxerr << "\nDiffs to: " << ar << endl;
+}
+
+
+//
+// search limits
+//
+
+
+bool testRightArrow(MathAtom const & at)
+{
+       return testSymbol(at, "to") || testSymbol(at, "rightarrow");
+}
+
+
+
+// replace '\lim_{x->x0} f(x)' sequences by a real InsetMathLim
+// assume 'extractDelims' ran before
+void extractLims(MathArray & ar)
+{
+       //lyxerr << "\nLimits from: " << ar << endl;
+       for (size_t i = 0; i < ar.size(); ++i) {
+               MathArray::iterator it = ar.begin() + i;
+
+               // must be a script inset with a subscript (without superscript)
+               InsetMathScript const * sub = (*it)->asScriptInset();
+               if (!sub || !sub->hasDown() || sub->hasUp() || sub->nuc().size() != 1)
+                       continue;
+
+               // is this a limit function?
+               if (!testSymbol(sub->nuc().front(), "lim"))
+                       continue;
+
+               // subscript must contain a -> symbol
+               MathArray const & s = sub->down();
+               MathArray::const_iterator st = find_if(s.begin(), s.end(), &testRightArrow);
+               if (st == s.end())
+                       continue;
+
+               // the -> splits the subscript int x and x0
+               MathArray x  = MathArray(s.begin(), st);
+               MathArray x0 = MathArray(st + 1, s.end());
+
+               // use something behind the script as core
+               MathArray f;
+               MathArray::iterator tt = extractTerm(f, it + 1, ar.end());
+
+               // cleanup
+               ar.erase(it + 1, tt);
+
+               // create a proper inset as replacement
+               *it = MathAtom(new InsetMathLim(f, x, x0));
+       }
+       //lyxerr << "\nLimits to: " << ar << endl;
+}
+
+
+//
+// combine searches
+//
+
+void extractStructure(MathArray & ar)
+{
+       //lyxerr << "\nStructure from: " << ar << endl;
+       splitScripts(ar);
+       extractDelims(ar);
+       extractIntegrals(ar);
+       extractSums(ar);
+       extractNumbers(ar);
+       extractMatrices(ar);
+       extractFunctions(ar);
+       extractDets(ar);
+       extractDiff(ar);
+       extractExps(ar);
+       extractLims(ar);
+       extractStrings(ar);
+       //lyxerr << "\nStructure to: " << ar << endl;
+}
+
+
+void write(MathArray const & dat, WriteStream & wi)
+{
+       MathArray ar = dat;
+       extractStrings(ar);
+       wi.firstitem() = true;
+       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) {
+               (*it)->write(wi);
+               wi.firstitem() = false;
+       }
+}
+
+
+void normalize(MathArray const & ar, NormalStream & os)
+{
+       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+               (*it)->normalize(os);
+}
+
+
+void octave(MathArray const & dat, OctaveStream & os)
+{
+       MathArray ar = dat;
+       extractStructure(ar);
+       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+               (*it)->octave(os);
+}
+
+
+void maple(MathArray const & dat, MapleStream & os)
+{
+       MathArray ar = dat;
+       extractStructure(ar);
+       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+               (*it)->maple(os);
+}
+
+
+void maxima(MathArray const & dat, MaximaStream & os)
+{
+       MathArray ar = dat;
+       extractStructure(ar);
+       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+               (*it)->maxima(os);
+}
+
+
+void mathematica(MathArray const & dat, MathematicaStream & os)
+{
+       MathArray ar = dat;
+       extractStructure(ar);
+       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+               (*it)->mathematica(os);
+}
+
+
+void mathmlize(MathArray const & dat, MathStream & os)
+{
+       MathArray ar = dat;
+       extractStructure(ar);
+       if (ar.size() == 0)
+               os << "<mrow/>";
+       else if (ar.size() == 1)
+               os << ar.front();
+       else {
+               os << MTag("mrow");
+               for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+                       (*it)->mathmlize(os);
+               os << ETag("mrow");
+       }
+}
+
+
+
+
+namespace {
+
+       std::string captureOutput(std::string const & cmd, std::string const & data)
+       {
+               // In order to avoid parsing problems with command interpreters
+               // we pass input data through a file
+               FileName const cas_tmpfile(tempName(FileName(), "casinput"));
+               if (cas_tmpfile.empty()) {
+                       lyxerr << "Warning: cannot create temporary file."
+                              << endl;
+                       return std::string();
+               }
+               std::ofstream os(cas_tmpfile.toFilesystemEncoding().c_str());
+               os << data << endl;
+               os.close();
+               std::string command =  cmd + " < "
+                       + quoteName(cas_tmpfile.toFilesystemEncoding());
+               lyxerr << "calling: " << cmd
+                      << "\ninput: '" << data << "'" << endl;
+               cmd_ret const ret = runCommand(command);
+               unlink(cas_tmpfile);
+               return ret.second;
+       }
+
+       size_t get_matching_brace(std::string const & str, size_t i)
+       {
+               int count = 1;
+               size_t n = str.size();
+               while (i < n) {
+                       i = str.find_first_of("{}", i+1);
+                       if (i == npos)
+                               return i;
+                       if (str[i] == '{')
+                               ++count;
+                       else
+                               --count;
+                       if (count == 0)
+                               return i;
+               }
+               return npos;
+       }
+
+       size_t get_matching_brace_back(std::string const & str, size_t i)
+       {
+               int count = 1;
+               while (i > 0) {
+                       i = str.find_last_of("{}", i-1);
+                       if (i == npos)
+                               return i;
+                       if (str[i] == '}')
+                               ++count;
+                       else
+                               --count;
+                       if (count == 0)
+                               return i;
+               }
+               return npos;
+       }
+
+       MathArray pipeThroughMaxima(docstring const &, MathArray const & ar)
+       {
+               odocstringstream os;
+               MaximaStream ms(os);
+               ms << ar;
+               docstring expr = os.str();
+               docstring const header = from_ascii("simpsum:true;");
+
+               std::string out;
+               for (int i = 0; i < 100; ++i) { // at most 100 attempts
+                       // try to fix missing '*' the hard way
+                       //
+                       // > echo "2x;" | maxima
+                       // ...
+                       // (C1) Incorrect syntax: x is not an infix operator
+                       // 2x;
+                       //  ^
+                       //
+                       lyxerr << "checking expr: '" << to_utf8(expr) << "'" << endl;
+                       docstring full = header + "tex(" + expr + ");";
+                       out = captureOutput("maxima", to_utf8(full));
+
+                       // leave loop if expression syntax is probably ok
+                       if (out.find("Incorrect syntax") == npos)
+                               break;
+
+                       // search line with "Incorrect syntax"
+                       istringstream is(out);
+                       std::string line;
+                       while (is) {
+                               getline(is, line);
+                               if (line.find("Incorrect syntax") != npos)
+                                       break;
+                       }
+
+                       // 2nd next line is the one with caret
+                       getline(is, line);
+                       getline(is, line);
+                       size_t pos = line.find('^');
+                       lyxerr << "found caret at pos: '" << pos << "'" << endl;
+                       if (pos == npos || pos < 4)
+                               break; // caret position not found
+                       pos -= 4; // skip the "tex(" part
+                       if (expr[pos] == '*')
+                               break; // two '*' in a row are definitely bad
+                       expr.insert(pos, from_ascii("*"));
+               }
+
+               vector<std::string> tmp = getVectorFromString(out, "$$");
+               if (tmp.size() < 2)
+                       return MathArray();
+
+               out = subst(tmp[1], "\\>", std::string());
+               lyxerr << "output: '" << out << "'" << endl;
+
+               // Ugly code that tries to make the result prettier
+               size_t i = out.find("\\mathchoice");
+               while (i != npos) {
+                       size_t j = get_matching_brace(out, i + 12);
+                       size_t k = get_matching_brace(out, j + 1);
+                       k = get_matching_brace(out, k + 1);
+                       k = get_matching_brace(out, k + 1);
+                       std::string mid = out.substr(i + 13, j - i - 13);
+                       if (mid.find("\\over") != npos)
+                               mid = '{' + mid + '}';
+                       out = out.substr(0,i)
+                               + mid
+                               + out.substr(k + 1);
+                       //lyxerr << "output: " << out << endl;
+                       i = out.find("\\mathchoice", i);
+                       break;
+               }
+
+               i = out.find("\\over");
+               while (i != npos) {
+                       size_t j = get_matching_brace_back(out, i - 1);
+                       if (j == npos || j == 0)
+                               break;
+                       size_t k = get_matching_brace(out, i + 5);
+                       if (k == npos || k + 1 == out.size())
+                               break;
+                       out = out.substr(0,j - 1)
+                               + "\\frac"
+                               + out.substr(j,i - j)
+                               + out.substr(i + 5,k - i - 4)
+                               + out.substr(k + 2);
+                       //lyxerr << "output: " << out << endl;
+                       i = out.find("\\over", i + 4);
+               }
+               MathArray res;
+               mathed_parse_cell(res, from_utf8(out));
+               return res;
+       }
+
+
+       MathArray pipeThroughMaple(docstring const & extra, MathArray const & ar)
+       {
+               std::string header = "readlib(latex):\n";
+
+               // remove the \\it for variable names
+               //"#`latex/csname_font` := `\\it `:"
+               header +=
+                       "`latex/csname_font` := ``:\n";
+
+               // export matrices in (...) instead of [...]
+               header +=
+                       "`latex/latex/matrix` := "
+                               "subs(`[`=`(`, `]`=`)`,"
+                                       "eval(`latex/latex/matrix`)):\n";
+
+               // replace \\cdots with proper '*'
+               header +=
+                       "`latex/latex/*` := "
+                               "subs(`\\,`=`\\cdot `,"
+                                       "eval(`latex/latex/*`)):\n";
+
+               // remove spurious \\noalign{\\medskip} in matrix output
+               header +=
+                       "`latex/latex/matrix`:= "
+                               "subs(`\\\\\\\\\\\\noalign{\\\\medskip}` = `\\\\\\\\`,"
+                                       "eval(`latex/latex/matrix`)):\n";
+
+               //"#`latex/latex/symbol` "
+               //      " := subs((\\'_\\' = \\'`\\_`\\',eval(`latex/latex/symbol`)): ";
+
+               std::string trailer = "quit;";
+               odocstringstream os;
+               MapleStream ms(os);
+               ms << ar;
+               std::string expr = to_utf8(os.str());
+               lyxerr << "ar: '" << ar << "'\n"
+                      << "ms: '" << expr << "'" << endl;
+
+               for (int i = 0; i < 100; ++i) { // at most 100 attempts
+                       // try to fix missing '*' the hard way by using mint
+                       //
+                       // ... > echo "1A;" | mint -i 1 -S -s -q
+                       // on line     1: 1A;
+                       //                 ^ syntax error -
+                       //                   Probably missing an operator such as * p
+                       //
+                       lyxerr << "checking expr: '" << expr << "'" << endl;
+                       string out = captureOutput("mint -i 1 -S -s -q -q", expr + ';');
+                       if (out.empty())
+                               break; // expression syntax is ok
+                       istringstream is(out);
+                       string line;
+                       getline(is, line);
+                       if (line.find("on line") != 0)
+                               break; // error message not identified
+                       getline(is, line);
+                       size_t pos = line.find('^');
+                       if (pos == string::npos || pos < 15)
+                               break; // caret position not found
+                       pos -= 15; // skip the "on line ..." part
+                       if (expr[pos] == '*' || (pos > 0 && expr[pos - 1] == '*'))
+                               break; // two '*' in a row are definitely bad
+                       expr.insert(pos, 1, '*');
+               }
+
+               // FIXME UNICODE Is utf8 encoding correct?
+               string full = "latex(" + to_utf8(extra) + '(' + expr + "));";
+               string out = captureOutput("maple -q", header + full + trailer);
+
+               // change \_ into _
+
+               //
+               MathArray res;
+               mathed_parse_cell(res, from_utf8(out));
+               return res;
+       }
+
+
+       MathArray pipeThroughOctave(docstring const &, MathArray const & ar)
+       {
+               odocstringstream os;
+               OctaveStream vs(os);
+               vs << ar;
+               string expr = to_utf8(os.str());
+               string out;
+
+               lyxerr << "pipe: ar: '" << ar << "'\n"
+                      << "pipe: expr: '" << expr << "'" << endl;
+
+               for (int i = 0; i < 100; ++i) { // at most 100 attempts
+                       //
+                       // try to fix missing '*' the hard way
+                       // parse error:
+                       // >>> ([[1 2 3 ];[2 3 1 ];[3 1 2 ]])([[1 2 3 ];[2 3 1 ];[3 1 2 ]])
+                       //                                   ^
+                       //
+                       lyxerr << "checking expr: '" << expr << "'" << endl;
+                       out = captureOutput("octave -q 2>&1", expr);
+                       lyxerr << "output: '" << out << "'" << endl;
+
+                       // leave loop if expression syntax is probably ok
+                       if (out.find("parse error:") == string::npos)
+                               break;
+
+                       // search line with single caret
+                       istringstream is(out);
+                       string line;
+                       while (is) {
+                               getline(is, line);
+                               lyxerr << "skipping line: '" << line << "'" << endl;
+                               if (line.find(">>> ") != string::npos)
+                                       break;
+                       }
+
+                       // found line with error, next line is the one with caret
+                       getline(is, line);
+                       size_t pos = line.find('^');
+                       lyxerr << "caret line: '" << line << "'" << endl;
+                       lyxerr << "found caret at pos: '" << pos << "'" << endl;
+                       if (pos == string::npos || pos < 4)
+                               break; // caret position not found
+                       pos -= 4; // skip the ">>> " part
+                       if (expr[pos] == '*')
+                               break; // two '*' in a row are definitely bad
+                       expr.insert(pos, 1, '*');
+               }
+
+               // remove 'ans = ' taking into account that there may be an
+               // ansi control sequence before, such as '\033[?1034hans = '
+               size_t i = out.find("ans = ");
+               if (i == string::npos)
+                       return MathArray();
+               out = out.substr(i + 6);
+
+               // parse output as matrix or single number
+               MathAtom at(new InsetMathArray(from_ascii("array"), from_utf8(out)));
+               InsetMathArray const * mat = at->asArrayInset();
+               MathArray res;
+               if (mat->ncols() == 1 && mat->nrows() == 1)
+                       res.append(mat->cell(0));
+               else {
+                       res.push_back(MathAtom(new InsetMathDelim(from_ascii("("), from_ascii(")"))));
+                       res.back().nucleus()->cell(0).push_back(at);
+               }
+               return res;
+       }
+
+
+       string fromMathematicaName(string const & name)
+       {
+               if (name == "Sin")    return "sin";
+               if (name == "Sinh")   return "sinh";
+               if (name == "ArcSin") return "arcsin";
+               if (name == "Cos")    return "cos";
+               if (name == "Cosh")   return "cosh";
+               if (name == "ArcCos") return "arccos";
+               if (name == "Tan")    return "tan";
+               if (name == "Tanh")   return "tanh";
+               if (name == "ArcTan") return "arctan";
+               if (name == "Cot")    return "cot";
+               if (name == "Coth")   return "coth";
+               if (name == "Csc")    return "csc";
+               if (name == "Sec")    return "sec";
+               if (name == "Exp")    return "exp";
+               if (name == "Log")    return "log";
+               if (name == "Arg" )   return "arg";
+               if (name == "Det" )   return "det";
+               if (name == "GCD" )   return "gcd";
+               if (name == "Max" )   return "max";
+               if (name == "Min" )   return "min";
+               if (name == "Erf" )   return "erf";
+               if (name == "Erfc" )  return "erfc";
+               return name;
+       }
+
+
+       void prettifyMathematicaOutput(string & out, string const & macroName,
+                       bool roman, bool translate)
+       {
+               string const macro = "\\" + macroName + "{";
+               size_t const len = macro.length();
+               size_t i = out.find(macro);
+
+               while (i != npos) {
+                       size_t const j = get_matching_brace(out, i + len);
+                       string const name = out.substr(i + len, j - i - len);
+                       out = out.substr(0, i)
+                               + (roman ? "\\mathrm{" : "")
+                               + (translate ? fromMathematicaName(name) : name)
+                               + out.substr(roman ? j : j + 1);
+                       //lyxerr << "output: " << out << endl;
+                       i = out.find(macro, i);
+               }
+       }
+
+
+       MathArray pipeThroughMathematica(docstring const &, MathArray const & ar)
+       {
+               odocstringstream os;
+               MathematicaStream ms(os);
+               ms << ar;
+               // FIXME UNICODE Is utf8 encoding correct?
+               string const expr = to_utf8(os.str());
+               string out;
+
+               lyxerr << "expr: '" << expr << "'" << endl;
+
+               string const full = "TeXForm[" + expr + "]";
+               out = captureOutput("math", full);
+               lyxerr << "output: '" << out << "'" << endl;
+
+               size_t pos1 = out.find("Out[1]//TeXForm= ");
+               size_t pos2 = out.find("In[2]:=");
+
+               if (pos1 == string::npos || pos2 == string::npos)
+                       return MathArray();
+
+               // get everything from pos1+17 to pos2
+               out = out.substr(pos1 + 17, pos2 - pos1 - 17);
+               out = subst(subst(out, '\r', ' '), '\n', ' ');
+
+               // tries to make the result prettier
+               prettifyMathematicaOutput(out, "Mfunction", true, true);
+               prettifyMathematicaOutput(out, "Muserfunction", true, false);
+               prettifyMathematicaOutput(out, "Mvariable", false, false);
+
+               MathArray res;
+               mathed_parse_cell(res, from_utf8(out));
+               return res;
+       }
+
+}
+
+
+MathArray pipeThroughExtern(string const & lang, docstring const & extra,
+       MathArray const & ar)
+{
+       if (lang == "octave")
+               return pipeThroughOctave(extra, ar);
+
+       if (lang == "maxima")
+               return pipeThroughMaxima(extra, ar);
+
+       if (lang == "maple")
+               return pipeThroughMaple(extra, ar);
+
+       if (lang == "mathematica")
+               return pipeThroughMathematica(extra, ar);
+
+       // create normalized expression
+       odocstringstream os;
+       NormalStream ns(os);
+       os << '[' << extra << ' ';
+       ns << ar;
+       os << ']';
+       // FIXME UNICODE Is utf8 encoding correct?
+       string data = to_utf8(os.str());
+
+       // search external script
+       support::FileName const file = libFileSearch("mathed", "extern_" + lang);
+       if (file.empty()) {
+               lyxerr << "converter to '" << lang << "' not found" << endl;
+               return MathArray();
+       }
+
+       // run external sript
+       string out = captureOutput(file.absFilename(), data);
+       MathArray res;
+       mathed_parse_cell(res, from_utf8(out));
+       return res;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathFactory.C b/src/mathed/MathFactory.C
deleted file mode 100644 (file)
index 6cb6e70..0000000
+++ /dev/null
@@ -1,428 +0,0 @@
-/**
- * \file MathFactory.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MathFactory.h"
-
-#include "InsetMathAMSArray.h"
-#include "InsetMathArray.h"
-#include "InsetMathBinom.h"
-#include "InsetMathBoldSymbol.h"
-#include "InsetMathBoxed.h"
-#include "InsetMathBox.h"
-#include "InsetMathCases.h"
-#include "InsetMathColor.h"
-#include "InsetMathDecoration.h"
-#include "InsetMathDFrac.h"
-#include "InsetMathDots.h"
-#include "InsetMathFBox.h"
-#include "InsetMathFont.h"
-#include "InsetMathFontOld.h"
-#include "InsetMathFrac.h"
-#include "InsetMathFrameBox.h"
-#include "InsetMathKern.h"
-#include "InsetMathLefteqn.h"
-#include "InsetMathMacro.h"
-#include "InsetMathMakebox.h"
-#include "InsetMathOverset.h"
-#include "InsetMathPhantom.h"
-#include "InsetMathRef.h"
-#include "InsetMathRoot.h"
-#include "InsetMathSize.h"
-#include "InsetMathSpace.h"
-#include "InsetMathSplit.h"
-#include "InsetMathSqrt.h"
-#include "InsetMathStackrel.h"
-#include "InsetMathSubstack.h"
-#include "InsetMathSymbol.h"
-#include "InsetMathTabular.h"
-#include "InsetMathTFrac.h"
-#include "InsetMathUnderset.h"
-#include "InsetMathUnknown.h"
-#include "InsetMathXArrow.h"
-#include "InsetMathXYMatrix.h"
-#include "MathMacroArgument.h"
-#include "MathMacroTable.h"
-#include "MathParser.h"
-#include "MathSupport.h"
-
-#include "debug.h"
-
-#include "insets/InsetCommand.h"
-
-#include "support/filetools.h" // LibFileSearch
-#include "support/lstrings.h"
-
-#include "frontends/FontLoader.h"
-
-
-namespace lyx {
-
-using support::libFileSearch;
-using support::split;
-
-using std::string;
-using std::endl;
-using std::istringstream;
-using std::vector;
-
-bool has_math_fonts;
-
-
-namespace {
-
-// file scope
-typedef std::map<docstring, latexkeys> WordList;
-
-WordList theWordList;
-
-
-bool math_font_available(docstring & name)
-{
-       LyXFont f;
-       augmentFont(f, name);
-
-       // Do we have the font proper?
-       if (theFontLoader().available(f))
-               return true;
-
-       // can we fake it?
-       if (name == "eufrak") {
-               name = from_ascii("lyxfakefrak");
-               return true;
-       }
-
-       LYXERR(Debug::MATHED)
-               << "font " << to_utf8(name) << " not available and I can't fake it"
-               << endl;
-       return false;
-}
-
-
-void initSymbols()
-{
-       support::FileName const filename = libFileSearch(string(), "symbols");
-       LYXERR(Debug::MATHED) << "read symbols from " << filename << endl;
-       if (filename.empty()) {
-               lyxerr << "Could not find symbols file" << endl;
-               return;
-       }
-
-       std::ifstream fs(filename.toFilesystemEncoding().c_str());
-       string line;
-       bool skip = false;
-       while (getline(fs, line)) {
-               int charid     = 0;
-               int fallbackid = 0;
-               if (line.empty() || line[0] == '#')
-                       continue;
-
-               // special case of iffont/else/endif
-               if (line.size() >= 7 && line.substr(0, 6) == "iffont") {
-                       istringstream is(line);
-                       string tmp;
-                       is >> tmp;
-                       is >> tmp;
-                       docstring t = from_utf8(tmp);
-                       skip = !math_font_available(t);
-                       continue;
-               } else if (line.size() >= 4 && line.substr(0, 4) == "else") {
-                       skip = !skip;
-               } else if (line.size() >= 5 && line.substr(0, 5) == "endif") {
-                       skip = false;
-                       continue;
-               } else if (skip)
-                       continue;
-
-               // special case of pre-defined macros
-               if (line.size() > 8 && line.substr(0, 5) == "\\def\\") {
-                       //lyxerr << "macro definition: '" << line << '\'' << endl;
-                       istringstream is(line);
-                       string macro;
-                       string requires;
-                       is >> macro >> requires;
-                       MacroTable::globalMacros().insert(from_utf8(macro), requires);
-                       continue;
-               }
-
-               idocstringstream is(from_utf8(line));
-               latexkeys tmp;
-               is >> tmp.name >> tmp.inset;
-               if (isFontName(tmp.inset))
-                       is >> charid >> fallbackid >> tmp.extra >> tmp.xmlname;
-               else
-                       is >> tmp.extra;
-               // requires is optional
-               if (is)
-                       is >> tmp.requires;
-               else {
-                       LYXERR(Debug::MATHED) << "skipping line '" << line << '\'' << endl;
-                       LYXERR(Debug::MATHED)
-                               << to_utf8(tmp.name) << ' ' << to_utf8(tmp.inset) << ' ' << to_utf8(tmp.extra) << endl;
-                       continue;
-               }
-
-               if (isFontName(tmp.inset)) {
-                       // tmp.inset _is_ the fontname here.
-                       // create fallbacks if necessary
-
-                       // store requirements as long as we can
-                       if (tmp.requires.empty() &&
-                           (tmp.inset == "msa" || tmp.inset == "msb"))
-                               tmp.requires = from_ascii("amssymb");
-                       else if (tmp.inset == "wasy")
-                               tmp.requires = from_ascii("wasysym");
-
-                       // symbol font is not available sometimes
-                       docstring symbol_font = from_ascii("lyxsymbol");
-
-                       if (tmp.extra == "func" || tmp.extra == "funclim" || tmp.extra == "special") {
-                               LYXERR(Debug::MATHED) << "symbol abuse for " << to_utf8(tmp.name) << endl;
-                               tmp.draw = tmp.name;
-                       } else if (math_font_available(tmp.inset)) {
-                               LYXERR(Debug::MATHED) << "symbol available for " << to_utf8(tmp.name) << endl;
-                               tmp.draw.push_back(char_type(charid));
-                       } else if (fallbackid && math_font_available(symbol_font)) {
-                               if (tmp.inset == "cmex")
-                                       tmp.inset = from_ascii("lyxsymbol");
-                               else
-                                       tmp.inset = from_ascii("lyxboldsymbol");
-                               LYXERR(Debug::MATHED) << "symbol fallback for " << to_utf8(tmp.name) << endl;
-                               tmp.draw.push_back(char_type(fallbackid));
-                       } else {
-                               LYXERR(Debug::MATHED) << "faking " << to_utf8(tmp.name) << endl;
-                               tmp.draw = tmp.name;
-                               tmp.inset = from_ascii("lyxtex");
-                       }
-               } else {
-                       // it's a proper inset
-                       LYXERR(Debug::MATHED) << "inset " << to_utf8(tmp.inset)
-                                             << " used for " << to_utf8(tmp.name)
-                                             << endl;
-               }
-
-               if (theWordList.find(tmp.name) != theWordList.end())
-                       LYXERR(Debug::MATHED)
-                               << "readSymbols: inset " << to_utf8(tmp.name)
-                               << " already exists." << endl;
-               else
-                       theWordList[tmp.name] = tmp;
-
-               LYXERR(Debug::MATHED)
-                       << "read symbol '" << to_utf8(tmp.name)
-                       << "  inset: " << to_utf8(tmp.inset)
-                       << "  draw: " << int(tmp.draw.empty() ? 0 : tmp.draw[0])
-                       << "  extra: " << to_utf8(tmp.extra)
-                       << "  requires: " << to_utf8(tmp.requires)
-                       << '\'' << endl;
-       }
-       docstring tmp = from_ascii("cmm");
-       docstring tmp2 = from_ascii("cmsy");
-       has_math_fonts = math_font_available(tmp) && math_font_available(tmp2);
-}
-
-
-} // namespace anon
-
-
-void initMath()
-{
-       static bool initialized = false;
-       if (!initialized) {
-               initialized = true;
-               initParser();
-               initSymbols();
-       }
-}
-
-
-latexkeys const * in_word_set(docstring const & str)
-{
-       WordList::iterator it = theWordList.find(str);
-       return it != theWordList.end() ? &(it->second) : 0;
-}
-
-
-MathAtom createInsetMath(char const * const s)
-{
-       return createInsetMath(from_utf8(s));
-}
-
-
-MathAtom createInsetMath(docstring const & s)
-{
-       //lyxerr << "creating inset with name: '" << s << '\'' << endl;
-       latexkeys const * l = in_word_set(s);
-       if (l) {
-               docstring const & inset = l->inset;
-               //lyxerr << " found inset: '" << inset << '\'' << endl;
-               if (inset == "ref")
-                       return MathAtom(new RefInset(l->name));
-               if (inset == "overset")
-                       return MathAtom(new InsetMathOverset);
-               if (inset == "underset")
-                       return MathAtom(new InsetMathUnderset);
-               if (inset == "decoration")
-                       return MathAtom(new InsetMathDecoration(l));
-               if (inset == "space")
-                       return MathAtom(new InsetMathSpace(l->name));
-               if (inset == "dots")
-                       return MathAtom(new InsetMathDots(l));
-               if (inset == "mbox")
-                       // return MathAtom(new InsetMathMBox);
-                       // InsetMathMBox is proposed to replace InsetMathBox,
-                       // but is not ready yet (it needs a BufferView for
-                       // construction)
-                       return MathAtom(new InsetMathBox(l->name));
-//             if (inset == "fbox")
-//                     return MathAtom(new InsetMathFBox(l));
-               if (inset == "style")
-                       return MathAtom(new InsetMathSize(l));
-               if (inset == "font")
-                       return MathAtom(new InsetMathFont(l));
-               if (inset == "oldfont")
-                       return MathAtom(new InsetMathFontOld(l));
-               if (inset == "matrix")
-                       return MathAtom(new InsetMathAMSArray(s));
-               if (inset == "split")
-                       return MathAtom(new InsetMathSplit(s));
-               if (inset == "big")
-                       // we can't create a InsetMathBig, since the argument
-                       // is missing.
-                       return MathAtom(new InsetMathUnknown(s));
-               return MathAtom(new InsetMathSymbol(l));
-       }
-
-       if (s.size() == 2 && s[0] == '#' && s[1] >= '1' && s[1] <= '9')
-               return MathAtom(new MathMacroArgument(s[1] - '0'));
-       if (s.size() == 3 && s[0] == '\\' && s[1] == '#'
-                       && s[2] >= '1' && s[2] <= '9')
-               return MathAtom(new MathMacroArgument(s[2] - '0'));
-       if (s == "boxed")
-               return MathAtom(new InsetMathBoxed());
-       if (s == "fbox")
-               return MathAtom(new InsetMathFBox());
-       if (s == "framebox")
-               return MathAtom(new InsetMathFrameBox);
-       if (s == "makebox")
-               return MathAtom(new InsetMathMakebox);
-       if (s == "kern")
-               return MathAtom(new InsetMathKern);
-       if (s.substr(0, 8) == "xymatrix") {
-               char spacing_code = '\0';
-               LyXLength spacing;
-               size_t const len = s.length();
-               size_t i = 8;
-               if (i < len && s[i] == '@') {
-                       ++i;
-                       if (i < len) {
-                               switch (s[i]) {
-                               case 'R':
-                               case 'C':
-                               case 'M':
-                               case 'W':
-                               case 'H':
-                               case 'L':
-                                       spacing_code = static_cast<char>(s[i]);
-                                       ++i;
-                                       break;
-                               }
-                       }
-                       if (i < len && s[i] == '=') {
-                               ++i;
-                               spacing = LyXLength(to_ascii(s.substr(i)));
-                       }
-               }
-               return MathAtom(new InsetMathXYMatrix(spacing, spacing_code));
-       }
-       if (s == "xrightarrow" || s == "xleftarrow")
-               return MathAtom(new InsetMathXArrow(s));
-       if (s == "split" || s == "gathered" || s == "aligned" || s == "alignedat")
-               return MathAtom(new InsetMathSplit(s));
-       if (s == "cases")
-               return MathAtom(new InsetMathCases);
-       if (s == "substack")
-               return MathAtom(new InsetMathSubstack);
-       if (s == "subarray" || s == "array")
-               return MathAtom(new InsetMathArray(s, 1, 1));
-       if (s == "sqrt")
-               return MathAtom(new InsetMathSqrt);
-       if (s == "root")
-               return MathAtom(new InsetMathRoot);
-       if (s == "tabular")
-               return MathAtom(new InsetMathTabular(s, 1, 1));
-       if (s == "stackrel")
-               return MathAtom(new InsetMathStackrel);
-       if (s == "binom" || s == "choose")
-               return MathAtom(new InsetMathBinom(s == "choose"));
-       if (s == "frac")
-               return MathAtom(new InsetMathFrac);
-       if (s == "over")
-               return MathAtom(new InsetMathFrac(InsetMathFrac::OVER));
-       if (s == "nicefrac")
-               return MathAtom(new InsetMathFrac(InsetMathFrac::NICEFRAC));
-       //if (s == "infer")
-       //      return MathAtom(new MathInferInset);
-       if (s == "atop")
-               return MathAtom(new InsetMathFrac(InsetMathFrac::ATOP));
-       if (s == "lefteqn")
-               return MathAtom(new InsetMathLefteqn);
-       if (s == "boldsymbol")
-               return MathAtom(new InsetMathBoldSymbol);
-       if (s == "color" || s == "normalcolor")
-               return MathAtom(new InsetMathColor(true));
-       if (s == "textcolor")
-               return MathAtom(new InsetMathColor(false));
-       if (s == "dfrac")
-               return MathAtom(new InsetMathDFrac);
-       if (s == "tfrac")
-               return MathAtom(new InsetMathTFrac);
-       if (s == "hphantom")
-               return MathAtom(new InsetMathPhantom(InsetMathPhantom::hphantom));
-       if (s == "phantom")
-               return MathAtom(new InsetMathPhantom(InsetMathPhantom::phantom));
-       if (s == "vphantom")
-               return MathAtom(new InsetMathPhantom(InsetMathPhantom::vphantom));
-
-       if (MacroTable::globalMacros().has(s))
-               return MathAtom(new MathMacro(s,
-                       MacroTable::globalMacros().get(s).numargs()));
-       //if (MacroTable::localMacros().has(s))
-       //      return MathAtom(new MathMacro(s,
-       //              MacroTable::localMacros().get(s).numargs()));
-
-       //lyxerr << "creating unknown inset '" << s << "'" << endl;
-       return MathAtom(new InsetMathUnknown(s));
-}
-
-
-bool createInsetMath_fromDialogStr(docstring const & str, MathArray & ar)
-{
-       // An example str:
-       // "ref LatexCommand ref\nreference \"sec:Title\"\n\\end_inset\n\n";
-       docstring name;
-       docstring body = split(str, name, ' ');
-
-       if (name != "ref" )
-               return false;
-
-       InsetCommandParams icp("ref");
-       // FIXME UNICODE
-       InsetCommandMailer::string2params("ref", to_utf8(str), icp);
-       mathed_parse_cell(ar, icp.getCommand());
-       if (ar.size() != 1)
-               return false;
-
-       return ar[0].nucleus();
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathFactory.cpp b/src/mathed/MathFactory.cpp
new file mode 100644 (file)
index 0000000..6cb6e70
--- /dev/null
@@ -0,0 +1,428 @@
+/**
+ * \file MathFactory.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "MathFactory.h"
+
+#include "InsetMathAMSArray.h"
+#include "InsetMathArray.h"
+#include "InsetMathBinom.h"
+#include "InsetMathBoldSymbol.h"
+#include "InsetMathBoxed.h"
+#include "InsetMathBox.h"
+#include "InsetMathCases.h"
+#include "InsetMathColor.h"
+#include "InsetMathDecoration.h"
+#include "InsetMathDFrac.h"
+#include "InsetMathDots.h"
+#include "InsetMathFBox.h"
+#include "InsetMathFont.h"
+#include "InsetMathFontOld.h"
+#include "InsetMathFrac.h"
+#include "InsetMathFrameBox.h"
+#include "InsetMathKern.h"
+#include "InsetMathLefteqn.h"
+#include "InsetMathMacro.h"
+#include "InsetMathMakebox.h"
+#include "InsetMathOverset.h"
+#include "InsetMathPhantom.h"
+#include "InsetMathRef.h"
+#include "InsetMathRoot.h"
+#include "InsetMathSize.h"
+#include "InsetMathSpace.h"
+#include "InsetMathSplit.h"
+#include "InsetMathSqrt.h"
+#include "InsetMathStackrel.h"
+#include "InsetMathSubstack.h"
+#include "InsetMathSymbol.h"
+#include "InsetMathTabular.h"
+#include "InsetMathTFrac.h"
+#include "InsetMathUnderset.h"
+#include "InsetMathUnknown.h"
+#include "InsetMathXArrow.h"
+#include "InsetMathXYMatrix.h"
+#include "MathMacroArgument.h"
+#include "MathMacroTable.h"
+#include "MathParser.h"
+#include "MathSupport.h"
+
+#include "debug.h"
+
+#include "insets/InsetCommand.h"
+
+#include "support/filetools.h" // LibFileSearch
+#include "support/lstrings.h"
+
+#include "frontends/FontLoader.h"
+
+
+namespace lyx {
+
+using support::libFileSearch;
+using support::split;
+
+using std::string;
+using std::endl;
+using std::istringstream;
+using std::vector;
+
+bool has_math_fonts;
+
+
+namespace {
+
+// file scope
+typedef std::map<docstring, latexkeys> WordList;
+
+WordList theWordList;
+
+
+bool math_font_available(docstring & name)
+{
+       LyXFont f;
+       augmentFont(f, name);
+
+       // Do we have the font proper?
+       if (theFontLoader().available(f))
+               return true;
+
+       // can we fake it?
+       if (name == "eufrak") {
+               name = from_ascii("lyxfakefrak");
+               return true;
+       }
+
+       LYXERR(Debug::MATHED)
+               << "font " << to_utf8(name) << " not available and I can't fake it"
+               << endl;
+       return false;
+}
+
+
+void initSymbols()
+{
+       support::FileName const filename = libFileSearch(string(), "symbols");
+       LYXERR(Debug::MATHED) << "read symbols from " << filename << endl;
+       if (filename.empty()) {
+               lyxerr << "Could not find symbols file" << endl;
+               return;
+       }
+
+       std::ifstream fs(filename.toFilesystemEncoding().c_str());
+       string line;
+       bool skip = false;
+       while (getline(fs, line)) {
+               int charid     = 0;
+               int fallbackid = 0;
+               if (line.empty() || line[0] == '#')
+                       continue;
+
+               // special case of iffont/else/endif
+               if (line.size() >= 7 && line.substr(0, 6) == "iffont") {
+                       istringstream is(line);
+                       string tmp;
+                       is >> tmp;
+                       is >> tmp;
+                       docstring t = from_utf8(tmp);
+                       skip = !math_font_available(t);
+                       continue;
+               } else if (line.size() >= 4 && line.substr(0, 4) == "else") {
+                       skip = !skip;
+               } else if (line.size() >= 5 && line.substr(0, 5) == "endif") {
+                       skip = false;
+                       continue;
+               } else if (skip)
+                       continue;
+
+               // special case of pre-defined macros
+               if (line.size() > 8 && line.substr(0, 5) == "\\def\\") {
+                       //lyxerr << "macro definition: '" << line << '\'' << endl;
+                       istringstream is(line);
+                       string macro;
+                       string requires;
+                       is >> macro >> requires;
+                       MacroTable::globalMacros().insert(from_utf8(macro), requires);
+                       continue;
+               }
+
+               idocstringstream is(from_utf8(line));
+               latexkeys tmp;
+               is >> tmp.name >> tmp.inset;
+               if (isFontName(tmp.inset))
+                       is >> charid >> fallbackid >> tmp.extra >> tmp.xmlname;
+               else
+                       is >> tmp.extra;
+               // requires is optional
+               if (is)
+                       is >> tmp.requires;
+               else {
+                       LYXERR(Debug::MATHED) << "skipping line '" << line << '\'' << endl;
+                       LYXERR(Debug::MATHED)
+                               << to_utf8(tmp.name) << ' ' << to_utf8(tmp.inset) << ' ' << to_utf8(tmp.extra) << endl;
+                       continue;
+               }
+
+               if (isFontName(tmp.inset)) {
+                       // tmp.inset _is_ the fontname here.
+                       // create fallbacks if necessary
+
+                       // store requirements as long as we can
+                       if (tmp.requires.empty() &&
+                           (tmp.inset == "msa" || tmp.inset == "msb"))
+                               tmp.requires = from_ascii("amssymb");
+                       else if (tmp.inset == "wasy")
+                               tmp.requires = from_ascii("wasysym");
+
+                       // symbol font is not available sometimes
+                       docstring symbol_font = from_ascii("lyxsymbol");
+
+                       if (tmp.extra == "func" || tmp.extra == "funclim" || tmp.extra == "special") {
+                               LYXERR(Debug::MATHED) << "symbol abuse for " << to_utf8(tmp.name) << endl;
+                               tmp.draw = tmp.name;
+                       } else if (math_font_available(tmp.inset)) {
+                               LYXERR(Debug::MATHED) << "symbol available for " << to_utf8(tmp.name) << endl;
+                               tmp.draw.push_back(char_type(charid));
+                       } else if (fallbackid && math_font_available(symbol_font)) {
+                               if (tmp.inset == "cmex")
+                                       tmp.inset = from_ascii("lyxsymbol");
+                               else
+                                       tmp.inset = from_ascii("lyxboldsymbol");
+                               LYXERR(Debug::MATHED) << "symbol fallback for " << to_utf8(tmp.name) << endl;
+                               tmp.draw.push_back(char_type(fallbackid));
+                       } else {
+                               LYXERR(Debug::MATHED) << "faking " << to_utf8(tmp.name) << endl;
+                               tmp.draw = tmp.name;
+                               tmp.inset = from_ascii("lyxtex");
+                       }
+               } else {
+                       // it's a proper inset
+                       LYXERR(Debug::MATHED) << "inset " << to_utf8(tmp.inset)
+                                             << " used for " << to_utf8(tmp.name)
+                                             << endl;
+               }
+
+               if (theWordList.find(tmp.name) != theWordList.end())
+                       LYXERR(Debug::MATHED)
+                               << "readSymbols: inset " << to_utf8(tmp.name)
+                               << " already exists." << endl;
+               else
+                       theWordList[tmp.name] = tmp;
+
+               LYXERR(Debug::MATHED)
+                       << "read symbol '" << to_utf8(tmp.name)
+                       << "  inset: " << to_utf8(tmp.inset)
+                       << "  draw: " << int(tmp.draw.empty() ? 0 : tmp.draw[0])
+                       << "  extra: " << to_utf8(tmp.extra)
+                       << "  requires: " << to_utf8(tmp.requires)
+                       << '\'' << endl;
+       }
+       docstring tmp = from_ascii("cmm");
+       docstring tmp2 = from_ascii("cmsy");
+       has_math_fonts = math_font_available(tmp) && math_font_available(tmp2);
+}
+
+
+} // namespace anon
+
+
+void initMath()
+{
+       static bool initialized = false;
+       if (!initialized) {
+               initialized = true;
+               initParser();
+               initSymbols();
+       }
+}
+
+
+latexkeys const * in_word_set(docstring const & str)
+{
+       WordList::iterator it = theWordList.find(str);
+       return it != theWordList.end() ? &(it->second) : 0;
+}
+
+
+MathAtom createInsetMath(char const * const s)
+{
+       return createInsetMath(from_utf8(s));
+}
+
+
+MathAtom createInsetMath(docstring const & s)
+{
+       //lyxerr << "creating inset with name: '" << s << '\'' << endl;
+       latexkeys const * l = in_word_set(s);
+       if (l) {
+               docstring const & inset = l->inset;
+               //lyxerr << " found inset: '" << inset << '\'' << endl;
+               if (inset == "ref")
+                       return MathAtom(new RefInset(l->name));
+               if (inset == "overset")
+                       return MathAtom(new InsetMathOverset);
+               if (inset == "underset")
+                       return MathAtom(new InsetMathUnderset);
+               if (inset == "decoration")
+                       return MathAtom(new InsetMathDecoration(l));
+               if (inset == "space")
+                       return MathAtom(new InsetMathSpace(l->name));
+               if (inset == "dots")
+                       return MathAtom(new InsetMathDots(l));
+               if (inset == "mbox")
+                       // return MathAtom(new InsetMathMBox);
+                       // InsetMathMBox is proposed to replace InsetMathBox,
+                       // but is not ready yet (it needs a BufferView for
+                       // construction)
+                       return MathAtom(new InsetMathBox(l->name));
+//             if (inset == "fbox")
+//                     return MathAtom(new InsetMathFBox(l));
+               if (inset == "style")
+                       return MathAtom(new InsetMathSize(l));
+               if (inset == "font")
+                       return MathAtom(new InsetMathFont(l));
+               if (inset == "oldfont")
+                       return MathAtom(new InsetMathFontOld(l));
+               if (inset == "matrix")
+                       return MathAtom(new InsetMathAMSArray(s));
+               if (inset == "split")
+                       return MathAtom(new InsetMathSplit(s));
+               if (inset == "big")
+                       // we can't create a InsetMathBig, since the argument
+                       // is missing.
+                       return MathAtom(new InsetMathUnknown(s));
+               return MathAtom(new InsetMathSymbol(l));
+       }
+
+       if (s.size() == 2 && s[0] == '#' && s[1] >= '1' && s[1] <= '9')
+               return MathAtom(new MathMacroArgument(s[1] - '0'));
+       if (s.size() == 3 && s[0] == '\\' && s[1] == '#'
+                       && s[2] >= '1' && s[2] <= '9')
+               return MathAtom(new MathMacroArgument(s[2] - '0'));
+       if (s == "boxed")
+               return MathAtom(new InsetMathBoxed());
+       if (s == "fbox")
+               return MathAtom(new InsetMathFBox());
+       if (s == "framebox")
+               return MathAtom(new InsetMathFrameBox);
+       if (s == "makebox")
+               return MathAtom(new InsetMathMakebox);
+       if (s == "kern")
+               return MathAtom(new InsetMathKern);
+       if (s.substr(0, 8) == "xymatrix") {
+               char spacing_code = '\0';
+               LyXLength spacing;
+               size_t const len = s.length();
+               size_t i = 8;
+               if (i < len && s[i] == '@') {
+                       ++i;
+                       if (i < len) {
+                               switch (s[i]) {
+                               case 'R':
+                               case 'C':
+                               case 'M':
+                               case 'W':
+                               case 'H':
+                               case 'L':
+                                       spacing_code = static_cast<char>(s[i]);
+                                       ++i;
+                                       break;
+                               }
+                       }
+                       if (i < len && s[i] == '=') {
+                               ++i;
+                               spacing = LyXLength(to_ascii(s.substr(i)));
+                       }
+               }
+               return MathAtom(new InsetMathXYMatrix(spacing, spacing_code));
+       }
+       if (s == "xrightarrow" || s == "xleftarrow")
+               return MathAtom(new InsetMathXArrow(s));
+       if (s == "split" || s == "gathered" || s == "aligned" || s == "alignedat")
+               return MathAtom(new InsetMathSplit(s));
+       if (s == "cases")
+               return MathAtom(new InsetMathCases);
+       if (s == "substack")
+               return MathAtom(new InsetMathSubstack);
+       if (s == "subarray" || s == "array")
+               return MathAtom(new InsetMathArray(s, 1, 1));
+       if (s == "sqrt")
+               return MathAtom(new InsetMathSqrt);
+       if (s == "root")
+               return MathAtom(new InsetMathRoot);
+       if (s == "tabular")
+               return MathAtom(new InsetMathTabular(s, 1, 1));
+       if (s == "stackrel")
+               return MathAtom(new InsetMathStackrel);
+       if (s == "binom" || s == "choose")
+               return MathAtom(new InsetMathBinom(s == "choose"));
+       if (s == "frac")
+               return MathAtom(new InsetMathFrac);
+       if (s == "over")
+               return MathAtom(new InsetMathFrac(InsetMathFrac::OVER));
+       if (s == "nicefrac")
+               return MathAtom(new InsetMathFrac(InsetMathFrac::NICEFRAC));
+       //if (s == "infer")
+       //      return MathAtom(new MathInferInset);
+       if (s == "atop")
+               return MathAtom(new InsetMathFrac(InsetMathFrac::ATOP));
+       if (s == "lefteqn")
+               return MathAtom(new InsetMathLefteqn);
+       if (s == "boldsymbol")
+               return MathAtom(new InsetMathBoldSymbol);
+       if (s == "color" || s == "normalcolor")
+               return MathAtom(new InsetMathColor(true));
+       if (s == "textcolor")
+               return MathAtom(new InsetMathColor(false));
+       if (s == "dfrac")
+               return MathAtom(new InsetMathDFrac);
+       if (s == "tfrac")
+               return MathAtom(new InsetMathTFrac);
+       if (s == "hphantom")
+               return MathAtom(new InsetMathPhantom(InsetMathPhantom::hphantom));
+       if (s == "phantom")
+               return MathAtom(new InsetMathPhantom(InsetMathPhantom::phantom));
+       if (s == "vphantom")
+               return MathAtom(new InsetMathPhantom(InsetMathPhantom::vphantom));
+
+       if (MacroTable::globalMacros().has(s))
+               return MathAtom(new MathMacro(s,
+                       MacroTable::globalMacros().get(s).numargs()));
+       //if (MacroTable::localMacros().has(s))
+       //      return MathAtom(new MathMacro(s,
+       //              MacroTable::localMacros().get(s).numargs()));
+
+       //lyxerr << "creating unknown inset '" << s << "'" << endl;
+       return MathAtom(new InsetMathUnknown(s));
+}
+
+
+bool createInsetMath_fromDialogStr(docstring const & str, MathArray & ar)
+{
+       // An example str:
+       // "ref LatexCommand ref\nreference \"sec:Title\"\n\\end_inset\n\n";
+       docstring name;
+       docstring body = split(str, name, ' ');
+
+       if (name != "ref" )
+               return false;
+
+       InsetCommandParams icp("ref");
+       // FIXME UNICODE
+       InsetCommandMailer::string2params("ref", to_utf8(str), icp);
+       mathed_parse_cell(ar, icp.getCommand());
+       if (ar.size() != 1)
+               return false;
+
+       return ar[0].nucleus();
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathMacroArgument.C b/src/mathed/MathMacroArgument.C
deleted file mode 100644 (file)
index 4d2badb..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * \file MathMacroArgument.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MathMacroArgument.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "debug.h"
-
-
-namespace lyx {
-
-using std::endl;
-using std::auto_ptr;
-using std::size_t;
-using std::vector;
-
-
-MathMacroArgument::MathMacroArgument(size_t n)
-       : number_(n)
-{
-       if (n < 1 || n > 9) {
-               lyxerr << "MathMacroArgument::MathMacroArgument: wrong Argument id: "
-                       << n << endl;
-       }
-       // The profiler tells us not to use 
-       // str_ = '#' + convert<docstring>(n);
-       // so we do the conversion of n to ASCII manually.
-       // This works because 1 <= n <= 9.
-       str_.resize(2);
-       str_[0] = '#';
-       str_[1] = '0' + n;
-}
-
-
-auto_ptr<InsetBase> MathMacroArgument::doClone() const
-{
-       return auto_ptr<InsetBase>(new MathMacroArgument(*this));
-}
-
-
-void MathMacroArgument::write(WriteStream & os) const
-{
-       os << str_;
-}
-
-
-bool MathMacroArgument::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       mathed_string_dim(mi.base.font, str_, dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void MathMacroArgument::draw(PainterInfo & pi, int x, int y) const
-{
-       drawStrRed(pi, x, y, str_);
-       setPosCache(pi, x, y);
-}
-
-
-void MathMacroArgument::normalize(NormalStream & os) const
-{
-       os << "[macroarg " << str_ << "] ";
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathMacroArgument.cpp b/src/mathed/MathMacroArgument.cpp
new file mode 100644 (file)
index 0000000..4d2badb
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * \file MathMacroArgument.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "MathMacroArgument.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "debug.h"
+
+
+namespace lyx {
+
+using std::endl;
+using std::auto_ptr;
+using std::size_t;
+using std::vector;
+
+
+MathMacroArgument::MathMacroArgument(size_t n)
+       : number_(n)
+{
+       if (n < 1 || n > 9) {
+               lyxerr << "MathMacroArgument::MathMacroArgument: wrong Argument id: "
+                       << n << endl;
+       }
+       // The profiler tells us not to use 
+       // str_ = '#' + convert<docstring>(n);
+       // so we do the conversion of n to ASCII manually.
+       // This works because 1 <= n <= 9.
+       str_.resize(2);
+       str_[0] = '#';
+       str_[1] = '0' + n;
+}
+
+
+auto_ptr<InsetBase> MathMacroArgument::doClone() const
+{
+       return auto_ptr<InsetBase>(new MathMacroArgument(*this));
+}
+
+
+void MathMacroArgument::write(WriteStream & os) const
+{
+       os << str_;
+}
+
+
+bool MathMacroArgument::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       mathed_string_dim(mi.base.font, str_, dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void MathMacroArgument::draw(PainterInfo & pi, int x, int y) const
+{
+       drawStrRed(pi, x, y, str_);
+       setPosCache(pi, x, y);
+}
+
+
+void MathMacroArgument::normalize(NormalStream & os) const
+{
+       os << "[macroarg " << str_ << "] ";
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathMacroTable.C b/src/mathed/MathMacroTable.C
deleted file mode 100644 (file)
index 779dc10..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * \file MathMacroTable.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MathMacroTable.h"
-#include "MathMacroTemplate.h"
-#include "MathMacroArgument.h"
-#include "MathSupport.h"
-#include "InsetMathSqrt.h"
-
-#include "debug.h"
-#include "dociterator.h"
-
-#include <boost/assert.hpp>
-
-#include <sstream>
-
-
-namespace lyx {
-
-using std::endl;
-using std::istringstream;
-using std::map;
-using std::pair;
-using std::string;
-using std::vector;
-using std::size_t;
-
-
-MacroData::MacroData()
-       : numargs_(0), lockCount_(0)
-{}
-
-
-MacroData::MacroData(docstring const & def, int numargs, docstring const & disp, string const & requires)
-       : def_(def), numargs_(numargs), disp_(disp), requires_(requires), lockCount_(0)
-{}
-
-
-void MacroData::expand(vector<MathArray> const & args, MathArray & to) const
-{
-       InsetMathSqrt inset; // Hack. Any inset with a cell would do.
-       // FIXME UNICODE
-       asArray(disp_.empty() ? def_ : disp_, inset.cell(0));
-       //lyxerr << "MathData::expand: args: " << args << endl;
-       //lyxerr << "MathData::expand: ar: " << inset.cell(0) << endl;
-       for (DocIterator it = doc_iterator_begin(inset); it; it.forwardChar()) {
-               if (!it.nextInset())
-                       continue;
-               if (it.nextInset()->lyxCode() != InsetBase::MATHMACROARG_CODE)
-                       continue;
-               //it.cell().erase(it.pos());
-               //it.cell().insert(it.pos(), it.nextInset()->asInsetMath()
-               size_t n = static_cast<MathMacroArgument*>(it.nextInset())->number();
-               if (n <= args.size()) {
-                       it.cell().erase(it.pos());
-                       it.cell().insert(it.pos(), args[n - 1]);
-               }
-       }
-       //lyxerr << "MathData::expand: res: " << inset.cell(0) << endl;
-       to = inset.cell(0);
-}
-
-
-// The global table.
-MacroTable & MacroTable::globalMacros()
-{
-       static MacroTable theGlobalMacros;
-       return theGlobalMacros;
-}
-
-
-bool MacroTable::has(docstring const & name) const
-{
-       return find(name) != end();
-}
-
-
-MacroData const & MacroTable::get(docstring const & name) const
-{
-       const_iterator it = find(name);
-       BOOST_ASSERT(it != end());
-       return it->second;
-}
-
-
-void MacroTable::insert(docstring const & name, MacroData const & data)
-{
-       //lyxerr << "MacroTable::insert: " << to_utf8(name) << endl;
-       operator[](name) = data;
-}
-
-
-void MacroTable::insert(docstring const & def, string const & requires)
-{
-       //lyxerr << "MacroTable::insert, def: " << to_utf8(def) << endl;
-       MathMacroTemplate mac(def);
-       MacroData data = mac.asMacroData();
-       data.requires() = requires;
-       insert(mac.name(), data);
-}
-
-
-void MacroTable::dump()
-{
-       lyxerr << "\n------------------------------------------" << endl;
-       for (const_iterator it = begin(); it != end(); ++it)
-               lyxerr << to_utf8(it->first)
-                       << " [" << to_utf8(it->second.def()) << "] : "
-                       << " [" << to_utf8(it->second.disp()) << "] : "
-                       << endl;
-       lyxerr << "------------------------------------------" << endl;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathMacroTable.cpp b/src/mathed/MathMacroTable.cpp
new file mode 100644 (file)
index 0000000..779dc10
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * \file MathMacroTable.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "MathMacroTable.h"
+#include "MathMacroTemplate.h"
+#include "MathMacroArgument.h"
+#include "MathSupport.h"
+#include "InsetMathSqrt.h"
+
+#include "debug.h"
+#include "dociterator.h"
+
+#include <boost/assert.hpp>
+
+#include <sstream>
+
+
+namespace lyx {
+
+using std::endl;
+using std::istringstream;
+using std::map;
+using std::pair;
+using std::string;
+using std::vector;
+using std::size_t;
+
+
+MacroData::MacroData()
+       : numargs_(0), lockCount_(0)
+{}
+
+
+MacroData::MacroData(docstring const & def, int numargs, docstring const & disp, string const & requires)
+       : def_(def), numargs_(numargs), disp_(disp), requires_(requires), lockCount_(0)
+{}
+
+
+void MacroData::expand(vector<MathArray> const & args, MathArray & to) const
+{
+       InsetMathSqrt inset; // Hack. Any inset with a cell would do.
+       // FIXME UNICODE
+       asArray(disp_.empty() ? def_ : disp_, inset.cell(0));
+       //lyxerr << "MathData::expand: args: " << args << endl;
+       //lyxerr << "MathData::expand: ar: " << inset.cell(0) << endl;
+       for (DocIterator it = doc_iterator_begin(inset); it; it.forwardChar()) {
+               if (!it.nextInset())
+                       continue;
+               if (it.nextInset()->lyxCode() != InsetBase::MATHMACROARG_CODE)
+                       continue;
+               //it.cell().erase(it.pos());
+               //it.cell().insert(it.pos(), it.nextInset()->asInsetMath()
+               size_t n = static_cast<MathMacroArgument*>(it.nextInset())->number();
+               if (n <= args.size()) {
+                       it.cell().erase(it.pos());
+                       it.cell().insert(it.pos(), args[n - 1]);
+               }
+       }
+       //lyxerr << "MathData::expand: res: " << inset.cell(0) << endl;
+       to = inset.cell(0);
+}
+
+
+// The global table.
+MacroTable & MacroTable::globalMacros()
+{
+       static MacroTable theGlobalMacros;
+       return theGlobalMacros;
+}
+
+
+bool MacroTable::has(docstring const & name) const
+{
+       return find(name) != end();
+}
+
+
+MacroData const & MacroTable::get(docstring const & name) const
+{
+       const_iterator it = find(name);
+       BOOST_ASSERT(it != end());
+       return it->second;
+}
+
+
+void MacroTable::insert(docstring const & name, MacroData const & data)
+{
+       //lyxerr << "MacroTable::insert: " << to_utf8(name) << endl;
+       operator[](name) = data;
+}
+
+
+void MacroTable::insert(docstring const & def, string const & requires)
+{
+       //lyxerr << "MacroTable::insert, def: " << to_utf8(def) << endl;
+       MathMacroTemplate mac(def);
+       MacroData data = mac.asMacroData();
+       data.requires() = requires;
+       insert(mac.name(), data);
+}
+
+
+void MacroTable::dump()
+{
+       lyxerr << "\n------------------------------------------" << endl;
+       for (const_iterator it = begin(); it != end(); ++it)
+               lyxerr << to_utf8(it->first)
+                       << " [" << to_utf8(it->second.def()) << "] : "
+                       << " [" << to_utf8(it->second.disp()) << "] : "
+                       << endl;
+       lyxerr << "------------------------------------------" << endl;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathMacroTemplate.C b/src/mathed/MathMacroTemplate.C
deleted file mode 100644 (file)
index 24cb74a..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/**
- * \file math_macrotemplate.C
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MathMacroTemplate.h"
-#include "MathStream.h"
-#include "MathParser.h"
-#include "MathSupport.h"
-
-#include "cursor.h"
-#include "debug.h"
-#include "gettext.h"
-#include "lyxlex.h"
-#include "LColor.h"
-
-#include "frontends/FontMetrics.h"
-#include "frontends/Painter.h"
-
-#include "support/lstrings.h"
-
-
-namespace lyx {
-
-using support::bformat;
-
-using std::auto_ptr;
-using std::ostream;
-using std::endl;
-
-
-MathMacroTemplate::MathMacroTemplate()
-       : InsetMathNest(2), numargs_(0), name_(), type_(from_ascii("newcommand"))
-{
-       initMath();
-}
-
-
-MathMacroTemplate::MathMacroTemplate(docstring const & name, int numargs,
-               docstring const & type, MathArray const & ar1, MathArray const & ar2)
-       : InsetMathNest(2), numargs_(numargs), name_(name), type_(type)
-{
-       initMath();
-
-       if (numargs_ > 9)
-               lyxerr << "MathMacroTemplate::MathMacroTemplate: wrong # of arguments: "
-                       << numargs_ << std::endl;
-       cell(0) = ar1;
-       cell(1) = ar2;
-}
-
-
-MathMacroTemplate::MathMacroTemplate(docstring const & str)
-       : InsetMathNest(2), numargs_(0), name_()
-{
-       initMath();
-
-       MathArray ar;
-       mathed_parse_cell(ar, str);
-       if (ar.size() != 1 || !ar[0]->asMacroTemplate()) {
-               lyxerr << "Cannot read macro from '" << ar << "'" << endl;
-               return;
-       }
-       operator=( *(ar[0]->asMacroTemplate()) );
-}
-
-
-auto_ptr<InsetBase> MathMacroTemplate::doClone() const
-{
-       return auto_ptr<InsetBase>(new MathMacroTemplate(*this));
-}
-
-
-void MathMacroTemplate::edit(LCursor & cur, bool)
-{
-       //lyxerr << "MathMacroTemplate: edit left/right" << endl;
-       cur.push(*this);
-}
-
-
-int MathMacroTemplate::numargs() const
-{
-       return numargs_;
-}
-
-
-void MathMacroTemplate::numargs(int numargs)
-{
-       numargs_ = numargs;
-}
-
-
-docstring MathMacroTemplate::name() const
-{
-       return name_;
-}
-
-
-docstring MathMacroTemplate::prefix() const
-{
-       return bformat(_(" Macro: %1$s: "), name_);
-}
-
-
-bool MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       bool lockMacro = MacroTable::globalMacros().has(name_);
-       if (lockMacro)
-               MacroTable::globalMacros().get(name_).lock();
-
-       cell(0).metrics(mi);
-       cell(1).metrics(mi);
-       docstring dp = prefix();
-       dim.wid = cell(0).width() + cell(1).width() + 20
-               + theFontMetrics(mi.base.font).width(dp);
-       dim.asc = std::max(cell(0).ascent(),  cell(1).ascent())  + 7;
-       dim.des = std::max(cell(0).descent(), cell(1).descent()) + 7;
-       
-       if (lockMacro)
-               MacroTable::globalMacros().get(name_).unlock();
-       
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void MathMacroTemplate::draw(PainterInfo & p, int x, int y) const
-{
-       bool lockMacro = MacroTable::globalMacros().has(name_);
-       if (lockMacro)
-               MacroTable::globalMacros().get(name_).lock();
-       
-       setPosCache(p, x, y);
-
-       // label
-       LyXFont font = p.base.font;
-       font.setColor(LColor::math);
-
-       PainterInfo pi(p.base.bv, p.pain);
-       pi.base.style = LM_ST_TEXT;
-       pi.base.font  = font;
-
-       int const a = y - dim_.asc + 1;
-       int const w = dim_.wid - 2;
-       int const h = dim_.height() - 2;
-
-       // LColor::mathbg used to be "AntiqueWhite" but is "linen" now, too
-       // the next line would overwrite the selection!
-       //pi.pain.fillRectangle(x, a, w, h, LColor::mathmacrobg);
-       pi.pain.rectangle(x, a, w, h, LColor::mathframe);
-
-#ifdef WITH_WARNINGS
-#warning FIXME
-#endif
-#if 0
-       LCursor & cur = p.base.bv->cursor();
-       if (cur.isInside(this))
-               cur.drawSelection(pi);
-#endif
-       docstring dp = prefix();
-       pi.pain.text(x + 2, y, dp, font);
-       // FIXME: Painter text should retain the drawn text width
-       x += theFontMetrics(font).width(dp) + 6;
-
-       int const w0 = cell(0).width();
-       int const w1 = cell(1).width();
-       cell(0).draw(pi, x + 2, y + 1);
-       pi.pain.rectangle(x, y - dim_.ascent() + 3,
-               w0 + 4, dim_.height() - 6, LColor::mathline);
-       cell(1).draw(pi, x + 8 + w0, y + 1);
-       pi.pain.rectangle(x + w0 + 6, y - dim_.ascent() + 3,
-               w1 + 4, dim_.height() - 6, LColor::mathline);
-       
-       if (lockMacro)
-               MacroTable::globalMacros().get(name_).unlock();
-}
-
-
-void MathMacroTemplate::read(Buffer const &, LyXLex & lex)
-{
-       MathArray ar;
-       mathed_parse_cell(ar, lex.getStream());
-       if (ar.size() != 1 || !ar[0]->asMacroTemplate()) {
-               lyxerr << "Cannot read macro from '" << ar << "'" << endl;
-               lyxerr << "Read: " << to_utf8(asString(ar)) << endl;
-               return;
-       }
-       operator=( *(ar[0]->asMacroTemplate()) );
-}
-
-
-void MathMacroTemplate::write(Buffer const &, std::ostream & os) const
-{
-       odocstringstream oss;
-       WriteStream wi(oss, false, false);
-       oss << "FormulaMacro\n";
-       write(wi);
-       os << to_utf8(oss.str());
-}
-
-
-void MathMacroTemplate::write(WriteStream & os) const
-{
-       if (type_ == "def") {
-               os << "\\def\\" << name_.c_str();
-               for (int i = 1; i <= numargs_; ++i)
-                       os << '#' << i;
-       } else {
-               // newcommand or renewcommand
-               os << "\\" << type_.c_str() << "{\\" << name_.c_str() << '}';
-               if (numargs_ > 0)
-                       os << '[' << numargs_ << ']';
-       }
-
-       os << '{' << cell(0) << "}";
-
-       if (os.latex()) {
-               // writing .tex. done.
-               os << "\n";
-       } else {
-               // writing .lyx, write special .tex export only if necessary
-               if (!cell(1).empty())
-                       os << "\n{" << cell(1) << '}';
-       }
-}
-
-
-int MathMacroTemplate::plaintext(Buffer const &, odocstream & os,
-                                 OutputParams const &) const
-{
-       static docstring const str = '[' + _("math macro") + ']';
-
-       os << str;
-       return str.size();
-}
-
-
-MacroData MathMacroTemplate::asMacroData() const
-{
-       return MacroData(asString(cell(0)), numargs(), asString(cell(1)), std::string());
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathMacroTemplate.cpp b/src/mathed/MathMacroTemplate.cpp
new file mode 100644 (file)
index 0000000..24cb74a
--- /dev/null
@@ -0,0 +1,253 @@
+/**
+ * \file math_macrotemplate.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "MathMacroTemplate.h"
+#include "MathStream.h"
+#include "MathParser.h"
+#include "MathSupport.h"
+
+#include "cursor.h"
+#include "debug.h"
+#include "gettext.h"
+#include "lyxlex.h"
+#include "LColor.h"
+
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
+#include "support/lstrings.h"
+
+
+namespace lyx {
+
+using support::bformat;
+
+using std::auto_ptr;
+using std::ostream;
+using std::endl;
+
+
+MathMacroTemplate::MathMacroTemplate()
+       : InsetMathNest(2), numargs_(0), name_(), type_(from_ascii("newcommand"))
+{
+       initMath();
+}
+
+
+MathMacroTemplate::MathMacroTemplate(docstring const & name, int numargs,
+               docstring const & type, MathArray const & ar1, MathArray const & ar2)
+       : InsetMathNest(2), numargs_(numargs), name_(name), type_(type)
+{
+       initMath();
+
+       if (numargs_ > 9)
+               lyxerr << "MathMacroTemplate::MathMacroTemplate: wrong # of arguments: "
+                       << numargs_ << std::endl;
+       cell(0) = ar1;
+       cell(1) = ar2;
+}
+
+
+MathMacroTemplate::MathMacroTemplate(docstring const & str)
+       : InsetMathNest(2), numargs_(0), name_()
+{
+       initMath();
+
+       MathArray ar;
+       mathed_parse_cell(ar, str);
+       if (ar.size() != 1 || !ar[0]->asMacroTemplate()) {
+               lyxerr << "Cannot read macro from '" << ar << "'" << endl;
+               return;
+       }
+       operator=( *(ar[0]->asMacroTemplate()) );
+}
+
+
+auto_ptr<InsetBase> MathMacroTemplate::doClone() const
+{
+       return auto_ptr<InsetBase>(new MathMacroTemplate(*this));
+}
+
+
+void MathMacroTemplate::edit(LCursor & cur, bool)
+{
+       //lyxerr << "MathMacroTemplate: edit left/right" << endl;
+       cur.push(*this);
+}
+
+
+int MathMacroTemplate::numargs() const
+{
+       return numargs_;
+}
+
+
+void MathMacroTemplate::numargs(int numargs)
+{
+       numargs_ = numargs;
+}
+
+
+docstring MathMacroTemplate::name() const
+{
+       return name_;
+}
+
+
+docstring MathMacroTemplate::prefix() const
+{
+       return bformat(_(" Macro: %1$s: "), name_);
+}
+
+
+bool MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       bool lockMacro = MacroTable::globalMacros().has(name_);
+       if (lockMacro)
+               MacroTable::globalMacros().get(name_).lock();
+
+       cell(0).metrics(mi);
+       cell(1).metrics(mi);
+       docstring dp = prefix();
+       dim.wid = cell(0).width() + cell(1).width() + 20
+               + theFontMetrics(mi.base.font).width(dp);
+       dim.asc = std::max(cell(0).ascent(),  cell(1).ascent())  + 7;
+       dim.des = std::max(cell(0).descent(), cell(1).descent()) + 7;
+       
+       if (lockMacro)
+               MacroTable::globalMacros().get(name_).unlock();
+       
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void MathMacroTemplate::draw(PainterInfo & p, int x, int y) const
+{
+       bool lockMacro = MacroTable::globalMacros().has(name_);
+       if (lockMacro)
+               MacroTable::globalMacros().get(name_).lock();
+       
+       setPosCache(p, x, y);
+
+       // label
+       LyXFont font = p.base.font;
+       font.setColor(LColor::math);
+
+       PainterInfo pi(p.base.bv, p.pain);
+       pi.base.style = LM_ST_TEXT;
+       pi.base.font  = font;
+
+       int const a = y - dim_.asc + 1;
+       int const w = dim_.wid - 2;
+       int const h = dim_.height() - 2;
+
+       // LColor::mathbg used to be "AntiqueWhite" but is "linen" now, too
+       // the next line would overwrite the selection!
+       //pi.pain.fillRectangle(x, a, w, h, LColor::mathmacrobg);
+       pi.pain.rectangle(x, a, w, h, LColor::mathframe);
+
+#ifdef WITH_WARNINGS
+#warning FIXME
+#endif
+#if 0
+       LCursor & cur = p.base.bv->cursor();
+       if (cur.isInside(this))
+               cur.drawSelection(pi);
+#endif
+       docstring dp = prefix();
+       pi.pain.text(x + 2, y, dp, font);
+       // FIXME: Painter text should retain the drawn text width
+       x += theFontMetrics(font).width(dp) + 6;
+
+       int const w0 = cell(0).width();
+       int const w1 = cell(1).width();
+       cell(0).draw(pi, x + 2, y + 1);
+       pi.pain.rectangle(x, y - dim_.ascent() + 3,
+               w0 + 4, dim_.height() - 6, LColor::mathline);
+       cell(1).draw(pi, x + 8 + w0, y + 1);
+       pi.pain.rectangle(x + w0 + 6, y - dim_.ascent() + 3,
+               w1 + 4, dim_.height() - 6, LColor::mathline);
+       
+       if (lockMacro)
+               MacroTable::globalMacros().get(name_).unlock();
+}
+
+
+void MathMacroTemplate::read(Buffer const &, LyXLex & lex)
+{
+       MathArray ar;
+       mathed_parse_cell(ar, lex.getStream());
+       if (ar.size() != 1 || !ar[0]->asMacroTemplate()) {
+               lyxerr << "Cannot read macro from '" << ar << "'" << endl;
+               lyxerr << "Read: " << to_utf8(asString(ar)) << endl;
+               return;
+       }
+       operator=( *(ar[0]->asMacroTemplate()) );
+}
+
+
+void MathMacroTemplate::write(Buffer const &, std::ostream & os) const
+{
+       odocstringstream oss;
+       WriteStream wi(oss, false, false);
+       oss << "FormulaMacro\n";
+       write(wi);
+       os << to_utf8(oss.str());
+}
+
+
+void MathMacroTemplate::write(WriteStream & os) const
+{
+       if (type_ == "def") {
+               os << "\\def\\" << name_.c_str();
+               for (int i = 1; i <= numargs_; ++i)
+                       os << '#' << i;
+       } else {
+               // newcommand or renewcommand
+               os << "\\" << type_.c_str() << "{\\" << name_.c_str() << '}';
+               if (numargs_ > 0)
+                       os << '[' << numargs_ << ']';
+       }
+
+       os << '{' << cell(0) << "}";
+
+       if (os.latex()) {
+               // writing .tex. done.
+               os << "\n";
+       } else {
+               // writing .lyx, write special .tex export only if necessary
+               if (!cell(1).empty())
+                       os << "\n{" << cell(1) << '}';
+       }
+}
+
+
+int MathMacroTemplate::plaintext(Buffer const &, odocstream & os,
+                                 OutputParams const &) const
+{
+       static docstring const str = '[' + _("math macro") + ']';
+
+       os << str;
+       return str.size();
+}
+
+
+MacroData MathMacroTemplate::asMacroData() const
+{
+       return MacroData(asString(cell(0)), numargs(), asString(cell(1)), std::string());
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathParser.C b/src/mathed/MathParser.C
deleted file mode 100644 (file)
index c985057..0000000
+++ /dev/null
@@ -1,1511 +0,0 @@
-/**
- * \file MathParser.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-/*
-
-If someone desperately needs partial "structures" (such as a few
-cells of an array inset or similar) (s)he could uses the
-following hack as starting point to write some macros:
-
-  \newif\ifcomment
-  \commentfalse
-  \ifcomment
-         \def\makeamptab{\catcode`\&=4\relax}
-         \def\makeampletter{\catcode`\&=11\relax}
-    \def\b{\makeampletter\expandafter\makeamptab\bi}
-    \long\def\bi#1\e{}
-  \else
-    \def\b{}\def\e{}
-  \fi
-
-  ...
-
-  \[\begin{array}{ccc}
-1
-&
-
-  \end{array}\]
-
-*/
-
-
-#include <config.h>
-
-#include "MathParser.h"
-
-#include "InsetMathArray.h"
-#include "InsetMathBig.h"
-#include "InsetMathBrace.h"
-#include "InsetMathChar.h"
-#include "InsetMathColor.h"
-#include "InsetMathComment.h"
-#include "InsetMathDelim.h"
-#include "InsetMathEnv.h"
-#include "InsetMathKern.h"
-#include "InsetMathMacro.h"
-#include "InsetMathPar.h"
-#include "InsetMathRef.h"
-#include "InsetMathRoot.h"
-#include "InsetMathScript.h"
-#include "InsetMathSplit.h"
-#include "InsetMathSqrt.h"
-#include "InsetMathTabular.h"
-#include "MathMacroTemplate.h"
-#include "MathFactory.h"
-#include "MathMacroArgument.h"
-#include "MathSupport.h"
-
-#include "lyxlex.h"
-#include "debug.h"
-
-#include "support/convert.h"
-
-#include <sstream>
-
-
-namespace lyx {
-
-using std::endl;
-using std::fill;
-
-using std::string;
-using std::ios;
-using std::istream;
-using std::ostream;
-using std::vector;
-
-
-//#define FILEDEBUG
-
-
-namespace {
-
-InsetMath::mode_type asMode(InsetMath::mode_type oldmode, docstring const & str)
-{
-       //lyxerr << "handling mode: '" << str << "'" << endl;
-       if (str == "mathmode")
-               return InsetMath::MATH_MODE;
-       if (str == "textmode" || str == "forcetext")
-               return InsetMath::TEXT_MODE;
-       return oldmode;
-}
-
-
-bool stared(docstring const & s)
-{
-       size_t const n = s.size();
-       return n && s[n - 1] == '*';
-}
-
-
-/*!
- * Add the row \p cellrow to \p grid.
- * \returns wether the row could be added. Adding a row can fail for
- * environments like "equation" that have a fixed number of rows.
- */
-bool addRow(InsetMathGrid & grid, InsetMathGrid::row_type & cellrow,
-           docstring const & vskip, bool allow_pagebreak = true)
-{
-       ++cellrow;
-       if (cellrow == grid.nrows()) {
-               //lyxerr << "adding row " << cellrow << endl;
-               grid.addRow(cellrow - 1);
-               if (cellrow == grid.nrows()) {
-                       // We can't add a row to this grid, so let's
-                       // append the content of this cell to the previous
-                       // one.
-                       // This does not happen in well formed .lyx files,
-                       // but LyX versions 1.3.x and older could create
-                       // such files and tex2lyx can still do that.
-                       --cellrow;
-                       lyxerr << "ignoring extra row";
-                       if (!vskip.empty())
-                               lyxerr << " with extra space " << to_utf8(vskip);
-                       if (!allow_pagebreak)
-                               lyxerr << " with no page break allowed";
-                       lyxerr << '.' << endl;
-                       return false;
-               }
-       }
-       grid.vcrskip(LyXLength(to_utf8(vskip)), cellrow - 1);
-       grid.rowinfo(cellrow - 1).allow_pagebreak_ = allow_pagebreak;
-       return true;
-}
-
-
-/*!
- * Add the column \p cellcol to \p grid.
- * \returns wether the column could be added. Adding a column can fail for
- * environments like "eqnarray" that have a fixed number of columns.
- */
-bool addCol(InsetMathGrid & grid, InsetMathGrid::col_type & cellcol)
-{
-       ++cellcol;
-       if (cellcol == grid.ncols()) {
-               //lyxerr << "adding column " << cellcol << endl;
-               grid.addCol(cellcol - 1);
-               if (cellcol == grid.ncols()) {
-                       // We can't add a column to this grid, so let's
-                       // append the content of this cell to the previous
-                       // one.
-                       // This does not happen in well formed .lyx files,
-                       // but LyX versions 1.3.x and older could create
-                       // such files and tex2lyx can still do that.
-                       --cellcol;
-                       lyxerr << "ignoring extra column." << endl;
-                       return false;
-               }
-       }
-       return true;
-}
-
-
-/*!
- * Check wether the last row is empty and remove it if yes.
- * Otherwise the following code
- * \verbatim
-\begin{array}{|c|c|}
-\hline
-1 & 2 \\ \hline
-3 & 4 \\ \hline
-\end{array}
- * \endverbatim
- * will result in a grid with 3 rows (+ the dummy row that is always present),
- * because the last '\\' opens a new row.
- */
-void delEmptyLastRow(InsetMathGrid & grid)
-{
-       InsetMathGrid::row_type const row = grid.nrows() - 1;
-       for (InsetMathGrid::col_type col = 0; col < grid.ncols(); ++col) {
-               if (!grid.cell(grid.index(row, col)).empty())
-                       return;
-       }
-       // Copy the row information of the empty row (which would contain the
-       // last hline in the example above) to the dummy row and delete the
-       // empty row.
-       grid.rowinfo(row + 1) = grid.rowinfo(row);
-       grid.delRow(row);
-}
-
-
-// These are TeX's catcodes
-enum CatCode {
-       catEscape,     // 0    backslash
-       catBegin,      // 1    {
-       catEnd,        // 2    }
-       catMath,       // 3    $
-       catAlign,      // 4    &
-       catNewline,    // 5    ^^M
-       catParameter,  // 6    #
-       catSuper,      // 7    ^
-       catSub,        // 8    _
-       catIgnore,     // 9
-       catSpace,      // 10   space
-       catLetter,     // 11   a-zA-Z
-       catOther,      // 12   none of the above
-       catActive,     // 13   ~
-       catComment,    // 14   %
-       catInvalid     // 15   <delete>
-};
-
-CatCode theCatcode[128];
-
-
-inline CatCode catcode(char_type c)
-{
-       /* The only characters that are not catOther lie in the pure ASCII
-        * range. Therefore theCatcode has only 128 entries.
-        * TeX itself deals with 8bit characters, so if needed this table
-        * could be enlarged to 256 entries.
-        * Any larger value does not make sense, since the fact that we use
-        * unicode internally does not change Knuth's TeX engine.
-        * Apart from that a table for the full 21bit UCS4 range would waste
-        * too much memory. */
-       if (c >= 128)
-               return catOther;
-
-       return theCatcode[c];
-}
-
-
-enum {
-       FLAG_ALIGN      = 1 << 0,  //  next & or \\ ends the parsing process
-       FLAG_BRACE_LAST = 1 << 1,  //  next closing brace ends the parsing
-       FLAG_RIGHT      = 1 << 2,  //  next \\right ends the parsing process
-       FLAG_END        = 1 << 3,  //  next \\end ends the parsing process
-       FLAG_BRACK_LAST = 1 << 4,  //  next closing bracket ends the parsing
-       FLAG_TEXTMODE   = 1 << 5,  //  we are in a box
-       FLAG_ITEM       = 1 << 6,  //  read a (possibly braced token)
-       FLAG_LEAVE      = 1 << 7,  //  leave the loop at the end
-       FLAG_SIMPLE     = 1 << 8,  //  next $ leaves the loop
-       FLAG_EQUATION   = 1 << 9,  //  next \] leaves the loop
-       FLAG_SIMPLE2    = 1 << 10, //  next \) leaves the loop
-       FLAG_OPTION     = 1 << 11, //  read [...] style option
-       FLAG_BRACED     = 1 << 12  //  read {...} style argument
-};
-
-
-//
-// Helper class for parsing
-//
-
-class Token {
-public:
-       ///
-       Token() : cs_(), char_(0), cat_(catIgnore) {}
-       ///
-       Token(char_type c, CatCode cat) : cs_(), char_(c), cat_(cat) {}
-       ///
-       explicit Token(docstring const & cs) : cs_(cs), char_(0), cat_(catIgnore) {}
-
-       ///
-       docstring const & cs() const { return cs_; }
-       ///
-       CatCode cat() const { return cat_; }
-       ///
-       char_type character() const { return char_; }
-       ///
-       docstring asString() const { return cs_.size() ? cs_ : docstring(1, char_); }
-       ///
-       docstring asInput() const { return cs_.size() ? '\\' + cs_ : docstring(1, char_); }
-
-private:
-       ///
-       docstring cs_;
-       ///
-       char_type char_;
-       ///
-       CatCode cat_;
-};
-
-
-ostream & operator<<(ostream & os, Token const & t)
-{
-       if (t.cs().size()) {
-               docstring const & cs = t.cs();
-               // FIXME: For some strange reason, the stream operator instanciate
-               // a new Token before outputting the contents of t.cs().
-               // Because of this the line 
-               //     os << '\\' << cs;
-               // below becomes recursive.
-               // In order to avoid that we return early:
-               if (cs == "\\")
-                       return os;
-               os << '\\' << to_utf8(cs);
-       }
-       else if (t.cat() == catLetter)
-               os << t.character();
-       else
-               os << '[' << t.character() << ',' << t.cat() << ']';
-       return os;
-}
-
-
-class Parser {
-public:
-       ///
-       typedef  InsetMath::mode_type mode_type;
-
-       ///
-       Parser(LyXLex & lex);
-       /// Only use this for reading from .lyx file format, for the reason
-       /// see Parser::tokenize(std::istream &).
-       Parser(istream & is);
-       ///
-       Parser(docstring const & str);
-
-       ///
-       bool parse(MathAtom & at);
-       ///
-       void parse(MathArray & array, unsigned flags, mode_type mode);
-       ///
-       void parse1(InsetMathGrid & grid, unsigned flags, mode_type mode,
-               bool numbered);
-       ///
-       MathArray parse(unsigned flags, mode_type mode);
-       ///
-       int lineno() const { return lineno_; }
-       ///
-       void putback();
-
-private:
-       ///
-       void parse2(MathAtom & at, unsigned flags, mode_type mode, bool numbered);
-       /// get arg delimited by 'left' and 'right'
-       docstring getArg(char_type left, char_type right);
-       ///
-       char_type getChar();
-       ///
-       void error(string const & msg);
-       void error(docstring const & msg) { error(to_utf8(msg)); }
-       /// dump contents to screen
-       void dump() const;
-       /// Only use this for reading from .lyx file format (see
-       /// implementation for reason)
-       void tokenize(istream & is);
-       ///
-       void tokenize(docstring const & s);
-       ///
-       void skipSpaceTokens(idocstream & is, char_type c);
-       ///
-       void push_back(Token const & t);
-       ///
-       void pop_back();
-       ///
-       Token const & prevToken() const;
-       ///
-       Token const & nextToken() const;
-       ///
-       Token const & getToken();
-       /// skips spaces if any
-       void skipSpaces();
-       ///
-       void lex(docstring const & s);
-       ///
-       bool good() const;
-       ///
-       docstring parse_verbatim_item();
-       ///
-       docstring parse_verbatim_option();
-
-       ///
-       int lineno_;
-       ///
-       vector<Token> tokens_;
-       ///
-       unsigned pos_;
-       /// Stack of active environments
-       vector<docstring> environments_;
-};
-
-
-Parser::Parser(LyXLex & lexer)
-       : lineno_(lexer.getLineNo()), pos_(0)
-{
-       tokenize(lexer.getStream());
-       lexer.eatLine();
-}
-
-
-Parser::Parser(istream & is)
-       : lineno_(0), pos_(0)
-{
-       tokenize(is);
-}
-
-
-Parser::Parser(docstring const & str)
-       : lineno_(0), pos_(0)
-{
-       tokenize(str);
-}
-
-
-void Parser::push_back(Token const & t)
-{
-       tokens_.push_back(t);
-}
-
-
-void Parser::pop_back()
-{
-       tokens_.pop_back();
-}
-
-
-Token const & Parser::prevToken() const
-{
-       static const Token dummy;
-       return pos_ > 0 ? tokens_[pos_ - 1] : dummy;
-}
-
-
-Token const & Parser::nextToken() const
-{
-       static const Token dummy;
-       return good() ? tokens_[pos_] : dummy;
-}
-
-
-Token const & Parser::getToken()
-{
-       static const Token dummy;
-       //lyxerr << "looking at token " << tokens_[pos_] << " pos: " << pos_ << endl;
-       return good() ? tokens_[pos_++] : dummy;
-}
-
-
-void Parser::skipSpaces()
-{
-       while (nextToken().cat() == catSpace || nextToken().cat() == catNewline)
-               getToken();
-}
-
-
-void Parser::putback()
-{
-       --pos_;
-}
-
-
-bool Parser::good() const
-{
-       return pos_ < tokens_.size();
-}
-
-
-char_type Parser::getChar()
-{
-       if (!good())
-               error("The input stream is not well...");
-       return tokens_[pos_++].character();
-}
-
-
-docstring Parser::getArg(char_type left, char_type right)
-{
-       skipSpaces();
-
-       docstring result;
-       char_type c = getChar();
-
-       if (c != left)
-               putback();
-       else
-               while ((c = getChar()) != right && good())
-                       result += c;
-
-       return result;
-}
-
-
-void Parser::skipSpaceTokens(idocstream & is, char_type c)
-{
-       // skip trailing spaces
-       while (catcode(c) == catSpace || catcode(c) == catNewline)
-               if (!is.get(c))
-                       break;
-       //lyxerr << "putting back: " << c << endl;
-       is.putback(c);
-}
-
-
-void Parser::tokenize(istream & is)
-{
-       // eat everything up to the next \end_inset or end of stream
-       // and store it in s for further tokenization
-       string s;
-       char c;
-       while (is.get(c)) {
-               s += c;
-               if (s.size() >= 10 && s.substr(s.size() - 10) == "\\end_inset") {
-                       s = s.substr(0, s.size() - 10);
-                       break;
-               }
-       }
-       // Remove the space after \end_inset
-       if (is.get(c) && c != ' ')
-               is.unget();
-
-       // tokenize buffer
-       tokenize(from_utf8(s));
-}
-
-
-void Parser::tokenize(docstring const & buffer)
-{
-       idocstringstream is(buffer, ios::in | ios::binary);
-
-       char_type c;
-       while (is.get(c)) {
-               //lyxerr << "reading c: " << c << endl;
-
-               switch (catcode(c)) {
-                       case catNewline: {
-                               ++lineno_;
-                               is.get(c);
-                               if (catcode(c) == catNewline)
-                                       ; //push_back(Token("par"));
-                               else {
-                                       push_back(Token('\n', catNewline));
-                                       is.putback(c);
-                               }
-                               break;
-                       }
-
-/*
-                       case catComment: {
-                               while (is.get(c) && catcode(c) != catNewline)
-                                       ;
-                               ++lineno_;
-                               break;
-                       }
-*/
-
-                       case catEscape: {
-                               is.get(c);
-                               if (!is) {
-                                       error("unexpected end of input");
-                               } else {
-                                       docstring s(1, c);
-                                       if (catcode(c) == catLetter) {
-                                               // collect letters
-                                               while (is.get(c) && catcode(c) == catLetter)
-                                                       s += c;
-                                               skipSpaceTokens(is, c);
-                                       }
-                                       push_back(Token(s));
-                               }
-                               break;
-                       }
-
-                       case catSuper:
-                       case catSub: {
-                               push_back(Token(c, catcode(c)));
-                               is.get(c);
-                               skipSpaceTokens(is, c);
-                               break;
-                       }
-
-                       case catIgnore: {
-                               lyxerr << "ignoring a char: " << int(c) << endl;
-                               break;
-                       }
-
-                       default:
-                               push_back(Token(c, catcode(c)));
-               }
-       }
-
-#ifdef FILEDEBUG
-       dump();
-#endif
-}
-
-
-void Parser::dump() const
-{
-       lyxerr << "\nTokens: ";
-       for (unsigned i = 0; i < tokens_.size(); ++i) {
-               if (i == pos_)
-                       lyxerr << " <#> ";
-               lyxerr << tokens_[i];
-       }
-       lyxerr << " pos: " << pos_ << endl;
-}
-
-
-void Parser::error(string const & msg)
-{
-       lyxerr << "Line ~" << lineno_ << ": Math parse error: " << msg << endl;
-       dump();
-       //exit(1);
-}
-
-
-bool Parser::parse(MathAtom & at)
-{
-       skipSpaces();
-       MathArray ar;
-       parse(ar, false, InsetMath::UNDECIDED_MODE);
-       if (ar.size() != 1 || ar.front()->getType() == hullNone) {
-               lyxerr << "unusual contents found: " << ar << endl;
-               at = MathAtom(new InsetMathPar(ar));
-               //if (at->nargs() > 0)
-               //      at.nucleus()->cell(0) = ar;
-               //else
-               //      lyxerr << "unusual contents found: " << ar << endl;
-               return true;
-       }
-       at = ar[0];
-       return true;
-}
-
-
-docstring Parser::parse_verbatim_option()
-{
-       skipSpaces();
-       docstring res;
-       if (nextToken().character() == '[') {
-               Token t = getToken();
-               for (Token t = getToken(); t.character() != ']' && good(); t = getToken()) {
-                       if (t.cat() == catBegin) {
-                               putback();
-                               res += '{' + parse_verbatim_item() + '}';
-                       } else
-                               res += t.asString();
-               }
-       }
-       return res;
-}
-
-
-docstring Parser::parse_verbatim_item()
-{
-       skipSpaces();
-       docstring res;
-       if (nextToken().cat() == catBegin) {
-               Token t = getToken();
-               for (Token t = getToken(); t.cat() != catEnd && good(); t = getToken()) {
-                       if (t.cat() == catBegin) {
-                               putback();
-                               res += '{' + parse_verbatim_item() + '}';
-                       }
-                       else
-                               res += t.asString();
-               }
-       }
-       return res;
-}
-
-
-MathArray Parser::parse(unsigned flags, mode_type mode)
-{
-       MathArray ar;
-       parse(ar, flags, mode);
-       return ar;
-}
-
-
-void Parser::parse(MathArray & array, unsigned flags, mode_type mode)
-{
-       InsetMathGrid grid(1, 1);
-       parse1(grid, flags, mode, false);
-       array = grid.cell(0);
-}
-
-
-void Parser::parse2(MathAtom & at, const unsigned flags, const mode_type mode,
-       const bool numbered)
-{
-       parse1(*(at.nucleus()->asGridInset()), flags, mode, numbered);
-}
-
-
-void Parser::parse1(InsetMathGrid & grid, unsigned flags,
-       const mode_type mode, const bool numbered)
-{
-       int limits = 0;
-       InsetMathGrid::row_type cellrow = 0;
-       InsetMathGrid::col_type cellcol = 0;
-       MathArray * cell = &grid.cell(grid.index(cellrow, cellcol));
-
-       if (grid.asHullInset())
-               grid.asHullInset()->numbered(cellrow, numbered);
-
-       //dump();
-       //lyxerr << " flags: " << flags << endl;
-       //lyxerr << " mode: " << mode  << endl;
-       //lyxerr << "grid: " << grid << endl;
-
-       while (good()) {
-               Token const & t = getToken();
-
-#ifdef FILEDEBUG
-               lyxerr << "t: " << t << " flags: " << flags << endl;
-               lyxerr << "mode: " << mode  << endl;
-               cell->dump();
-               lyxerr << endl;
-#endif
-
-               if (flags & FLAG_ITEM) {
-
-                       if (t.cat() == catBegin) {
-                               // skip the brace and collect everything to the next matching
-                               // closing brace
-                               parse1(grid, FLAG_BRACE_LAST, mode, numbered);
-                               return;
-                       }
-
-                       // handle only this single token, leave the loop if done
-                       flags = FLAG_LEAVE;
-               }
-
-
-               if (flags & FLAG_BRACED) {
-                       if (t.cat() == catSpace)
-                               continue;
-
-                       if (t.cat() != catBegin) {
-                               error("opening brace expected");
-                               return;
-                       }
-
-                       // skip the brace and collect everything to the next matching
-                       // closing brace
-                       flags = FLAG_BRACE_LAST;
-               }
-
-
-               if (flags & FLAG_OPTION) {
-                       if (t.cat() == catOther && t.character() == '[') {
-                               MathArray ar;
-                               parse(ar, FLAG_BRACK_LAST, mode);
-                               cell->append(ar);
-                       } else {
-                               // no option found, put back token and we are done
-                               putback();
-                       }
-                       return;
-               }
-
-               //
-               // cat codes
-               //
-               if (t.cat() == catMath) {
-                       if (mode != InsetMath::MATH_MODE) {
-                               // we are inside some text mode thingy, so opening new math is allowed
-                               Token const & n = getToken();
-                               if (n.cat() == catMath) {
-                                       // TeX's $$...$$ syntax for displayed math
-                                       cell->push_back(MathAtom(new InsetMathHull(hullEquation)));
-                                       parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false);
-                                       getToken(); // skip the second '$' token
-                               } else {
-                                       // simple $...$  stuff
-                                       putback();
-                                       cell->push_back(MathAtom(new InsetMathHull(hullSimple)));
-                                       parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false);
-                               }
-                       }
-
-                       else if (flags & FLAG_SIMPLE) {
-                               // this is the end of the formula
-                               return;
-                       }
-
-                       else {
-                               error("something strange in the parser");
-                               break;
-                       }
-               }
-
-               else if (t.cat() == catLetter)
-                       cell->push_back(MathAtom(new InsetMathChar(t.character())));
-
-               else if (t.cat() == catSpace && mode != InsetMath::MATH_MODE) {
-                       if (cell->empty() || cell->back()->getChar() != ' ')
-                               cell->push_back(MathAtom(new InsetMathChar(t.character())));
-               }
-
-               else if (t.cat() == catNewline && mode != InsetMath::MATH_MODE) {
-                       if (cell->empty() || cell->back()->getChar() != ' ')
-                               cell->push_back(MathAtom(new InsetMathChar(' ')));
-               }
-
-               else if (t.cat() == catParameter) {
-                       Token const & n = getToken();
-                       cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0')));
-               }
-
-               else if (t.cat() == catActive)
-                       cell->push_back(MathAtom(new InsetMathChar(t.character())));
-
-               else if (t.cat() == catBegin) {
-                       MathArray ar;
-                       parse(ar, FLAG_BRACE_LAST, mode);
-                       // do not create a BraceInset if they were written by LyX
-                       // this helps to keep the annoyance of  "a choose b"  to a minimum
-                       if (ar.size() == 1 && ar[0]->extraBraces())
-                               cell->append(ar);
-                       else
-                               cell->push_back(MathAtom(new InsetMathBrace(ar)));
-               }
-
-               else if (t.cat() == catEnd) {
-                       if (flags & FLAG_BRACE_LAST)
-                               return;
-                       error("found '}' unexpectedly");
-                       //BOOST_ASSERT(false);
-                       //add(cell, '}', LM_TC_TEX);
-               }
-
-               else if (t.cat() == catAlign) {
-                       //lyxerr << " column now " << (cellcol + 1)
-                       //       << " max: " << grid.ncols() << endl;
-                       if (flags & FLAG_ALIGN)
-                               return;
-                       if (addCol(grid, cellcol))
-                               cell = &grid.cell(grid.index(cellrow, cellcol));
-               }
-
-               else if (t.cat() == catSuper || t.cat() == catSub) {
-                       bool up = (t.cat() == catSuper);
-                       // we need no new script inset if the last thing was a scriptinset,
-                       // which has that script already not the same script already
-                       if (!cell->size())
-                               cell->push_back(MathAtom(new InsetMathScript(up)));
-                       else if (cell->back()->asScriptInset() &&
-                                       !cell->back()->asScriptInset()->has(up))
-                               cell->back().nucleus()->asScriptInset()->ensure(up);
-                       else if (cell->back()->asScriptInset())
-                               cell->push_back(MathAtom(new InsetMathScript(up)));
-                       else
-                               cell->back() = MathAtom(new InsetMathScript(cell->back(), up));
-                       InsetMathScript * p = cell->back().nucleus()->asScriptInset();
-                       // special handling of {}-bases
-                       // Here we could remove the brace inset for things
-                       // like {a'}^2 and add the braces back in
-                       // InsetMathScript::write().
-                       // We do not do it, since it is not possible to detect
-                       // reliably whether the braces are needed because the
-                       // nucleus contains more than one symbol, or whether
-                       // they are needed for unknown commands like \xx{a}_0
-                       // or \yy{a}{b}_0. This was done in revision 14819
-                       // in an unreliable way. See this thread
-                       // http://www.mail-archive.com/lyx-devel%40lists.lyx.org/msg104917.html
-                       // for more details.
-                       parse(p->cell(p->idxOfScript(up)), FLAG_ITEM, mode);
-                       if (limits) {
-                               p->limits(limits);
-                               limits = 0;
-                       }
-               }
-
-               else if (t.character() == ']' && (flags & FLAG_BRACK_LAST)) {
-                       //lyxerr << "finished reading option" << endl;
-                       return;
-               }
-
-               else if (t.cat() == catOther)
-                       cell->push_back(MathAtom(new InsetMathChar(t.character())));
-
-               else if (t.cat() == catComment) {
-                       docstring s;
-                       while (good()) {
-                               Token const & t = getToken();
-                               if (t.cat() == catNewline)
-                                       break;
-                               s += t.asString();
-                       }
-                       cell->push_back(MathAtom(new InsetMathComment(s)));
-                       skipSpaces();
-               }
-
-               //
-               // control sequences
-               //
-
-               else if (t.cs() == "lyxlock") {
-                       if (cell->size())
-                               cell->back().nucleus()->lock(true);
-               }
-
-               else if (t.cs() == "def" ||
-                       t.cs() == "newcommand" ||
-                       t.cs() == "renewcommand")
-               {
-                       docstring const type = t.cs();
-                       docstring name;
-                       int nargs = 0;
-                       if (t.cs() == "def") {
-                               // get name
-                               name = getToken().cs();
-
-                               // read parameter
-                               docstring pars;
-                               while (good() && nextToken().cat() != catBegin) {
-                                       pars += getToken().cs();
-                                       ++nargs;
-                               }
-                               nargs /= 2;
-                               //lyxerr << "read \\def parameter list '" << pars << "'" << endl;
-
-                       } else { // t.cs() == "newcommand" || t.cs() == "renewcommand"
-
-                               if (getToken().cat() != catBegin) {
-                                       error("'{' in \\newcommand expected (1) ");
-                                       return;
-                               }
-
-                               name = getToken().cs();
-
-                               if (getToken().cat() != catEnd) {
-                                       error("'}' in \\newcommand expected");
-                                       return;
-                               }
-
-                               docstring const arg = getArg('[', ']');
-                               if (!arg.empty())
-                                       nargs = convert<int>(arg);
-
-                       }
-
-                       MathArray ar1;
-                       parse(ar1, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
-
-                       // we cannot handle recursive stuff at all
-                       //MathArray test;
-                       //test.push_back(createInsetMath(name));
-                       //if (ar1.contains(test)) {
-                       //      error("we cannot handle recursive macros at all.");
-                       //      return;
-                       //}
-
-                       // is a version for display attached?
-                       skipSpaces();
-                       MathArray ar2;
-                       if (nextToken().cat() == catBegin)
-                               parse(ar2, FLAG_ITEM, InsetMath::MATH_MODE);
-
-                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, type,
-                               ar1, ar2)));
-               }
-
-               else if (t.cs() == "(") {
-                       cell->push_back(MathAtom(new InsetMathHull(hullSimple)));
-                       parse2(cell->back(), FLAG_SIMPLE2, InsetMath::MATH_MODE, false);
-               }
-
-               else if (t.cs() == "[") {
-                       cell->push_back(MathAtom(new InsetMathHull(hullEquation)));
-                       parse2(cell->back(), FLAG_EQUATION, InsetMath::MATH_MODE, false);
-               }
-
-               else if (t.cs() == "protect")
-                       // ignore \\protect, will hopefully be re-added during output
-                       ;
-
-               else if (t.cs() == "end") {
-                       if (flags & FLAG_END) {
-                               // eat environment name
-                               docstring const name = getArg('{', '}');
-                               if (environments_.empty())
-                                       error("'found \\end{" + name +
-                                             "}' without matching '\\begin{" +
-                                             name + "}'");
-                               else if (name != environments_.back())
-                                       error("'\\end{" + name +
-                                             "}' does not match '\\begin{" +
-                                             environments_.back() + "}'");
-                               else {
-                                       environments_.pop_back();
-                                       // Delete empty last row in matrix
-                                       // like insets.
-                                       // If you abuse InsetMathGrid for
-                                       // non-matrix like structures you
-                                       // probably need to refine this test.
-                                       // Right now we only have to test for
-                                       // single line hull insets.
-                                       if (grid.nrows() > 1)
-                                               delEmptyLastRow(grid);
-                                       return;
-                               }
-                       } else
-                               error("found 'end' unexpectedly");
-               }
-
-               else if (t.cs() == ")") {
-                       if (flags & FLAG_SIMPLE2)
-                               return;
-                       error("found '\\)' unexpectedly");
-               }
-
-               else if (t.cs() == "]") {
-                       if (flags & FLAG_EQUATION)
-                               return;
-                       error("found '\\]' unexpectedly");
-               }
-
-               else if (t.cs() == "\\") {
-                       if (flags & FLAG_ALIGN)
-                               return;
-                       bool added;
-                       if (nextToken().asInput() == "*") {
-                               getToken();
-                               added = addRow(grid, cellrow, docstring(), false);
-                       } else
-                               added = addRow(grid, cellrow, getArg('[', ']'));
-                       if (added) {
-                               cellcol = 0;
-                               if (grid.asHullInset())
-                                       grid.asHullInset()->numbered(
-                                                       cellrow, numbered);
-                               cell = &grid.cell(grid.index(cellrow,
-                                                            cellcol));
-                       }
-               }
-
-#if 0
-               else if (t.cs() == "multicolumn") {
-                       // extract column count and insert dummy cells
-                       MathArray count;
-                       parse(count, FLAG_ITEM, mode);
-                       int cols = 1;
-                       if (!extractNumber(count, cols)) {
-                               lyxerr << " can't extract number of cells from " << count << endl;
-                       }
-                       // resize the table if necessary
-                       for (int i = 0; i < cols; ++i) {
-                               if (addCol(grid, cellcol)) {
-                                       cell = &grid.cell(grid.index(
-                                                       cellrow, cellcol));
-                                       // mark this as dummy
-                                       grid.cellinfo(grid.index(
-                                               cellrow, cellcol)).dummy_ = true;
-                               }
-                       }
-                       // the last cell is the real thing, not a dummy
-                       grid.cellinfo(grid.index(cellrow, cellcol)).dummy_ = false;
-
-                       // read special alignment
-                       MathArray align;
-                       parse(align, FLAG_ITEM, mode);
-                       //grid.cellinfo(grid.index(cellrow, cellcol)).align_ = extractString(align);
-
-                       // parse the remaining contents into the "real" cell
-                       parse(*cell, FLAG_ITEM, mode);
-               }
-#endif
-
-               else if (t.cs() == "limits")
-                       limits = 1;
-
-               else if (t.cs() == "nolimits")
-                       limits = -1;
-
-               else if (t.cs() == "nonumber") {
-                       if (grid.asHullInset())
-                               grid.asHullInset()->numbered(cellrow, false);
-               }
-
-               else if (t.cs() == "number") {
-                       if (grid.asHullInset())
-                               grid.asHullInset()->numbered(cellrow, true);
-               }
-
-               else if (t.cs() == "hline") {
-                       grid.rowinfo(cellrow).lines_ ++;
-               }
-
-               else if (t.cs() == "sqrt") {
-                       MathArray ar;
-                       parse(ar, FLAG_OPTION, mode);
-                       if (ar.size()) {
-                               cell->push_back(MathAtom(new InsetMathRoot));
-                               cell->back().nucleus()->cell(0) = ar;
-                               parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
-                       } else {
-                               cell->push_back(MathAtom(new InsetMathSqrt));
-                               parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
-                       }
-               }
-
-               else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") {
-                       cell->push_back(createInsetMath(t.cs()));
-                       parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
-                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
-               }
-
-               else if (t.cs() == "ref" || t.cs() == "prettyref" ||
-                               t.cs() == "pageref" || t.cs() == "vpageref" || t.cs() == "vref") {
-                       cell->push_back(MathAtom(new RefInset(t.cs())));
-                       parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
-                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
-               }
-
-               else if (t.cs() == "left") {
-                       skipSpaces();
-                       Token const & tl = getToken();
-                       // \| and \Vert are equivalent, and InsetMathDelim
-                       // can't handle \|
-                       // FIXME: fix this in InsetMathDelim itself!
-                       docstring const l = tl.cs() == "|" ? from_ascii("Vert") : tl.asString();
-                       MathArray ar;
-                       parse(ar, FLAG_RIGHT, mode);
-                       if (!good())
-                               break;
-                       skipSpaces();
-                       Token const & tr = getToken();
-                       docstring const r = tr.cs() == "|" ? from_ascii("Vert") : tr.asString();
-                       cell->push_back(MathAtom(new InsetMathDelim(l, r, ar)));
-               }
-
-               else if (t.cs() == "right") {
-                       if (flags & FLAG_RIGHT)
-                               return;
-                       //lyxerr << "got so far: '" << cell << "'" << endl;
-                       error("Unmatched right delimiter");
-                       return;
-               }
-
-               else if (t.cs() == "begin") {
-                       docstring const name = getArg('{', '}');
-                       environments_.push_back(name);
-
-                       if (name == "array" || name == "subarray") {
-                               docstring const valign = parse_verbatim_option() + 'c';
-                               docstring const halign = parse_verbatim_item();
-                               cell->push_back(MathAtom(new InsetMathArray(name, (char)valign[0], halign)));
-                               parse2(cell->back(), FLAG_END, mode, false);
-                       }
-
-                       else if (name == "tabular") {
-                               docstring const valign = parse_verbatim_option() + 'c';
-                               docstring const halign = parse_verbatim_item();
-                               cell->push_back(MathAtom(new InsetMathTabular(name, (char)valign[0], halign)));
-                               parse2(cell->back(), FLAG_END, InsetMath::TEXT_MODE, false);
-                       }
-
-                       else if (name == "split" || name == "cases") {
-                               cell->push_back(createInsetMath(name));
-                               parse2(cell->back(), FLAG_END, mode, false);
-                       }
-
-                       else if (name == "alignedat") {
-                               docstring const valign = parse_verbatim_option() + 'c';
-                               // ignore this for a while
-                               getArg('{', '}');
-                               cell->push_back(MathAtom(new InsetMathSplit(name, (char)valign[0])));
-                               parse2(cell->back(), FLAG_END, mode, false);
-                       }
-
-                       else if (name == "math") {
-                               cell->push_back(MathAtom(new InsetMathHull(hullSimple)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, true);
-                       }
-
-                       else if (name == "equation" || name == "equation*"
-                                       || name == "displaymath") {
-                               cell->push_back(MathAtom(new InsetMathHull(hullEquation)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, (name == "equation"));
-                       }
-
-                       else if (name == "eqnarray" || name == "eqnarray*") {
-                               cell->push_back(MathAtom(new InsetMathHull(hullEqnArray)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
-                       }
-
-                       else if (name == "align" || name == "align*") {
-                               cell->push_back(MathAtom(new InsetMathHull(hullAlign)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
-                       }
-
-                       else if (name == "flalign" || name == "flalign*") {
-                               cell->push_back(MathAtom(new InsetMathHull(hullFlAlign)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
-                       }
-
-                       else if (name == "alignat" || name == "alignat*") {
-                               // ignore this for a while
-                               getArg('{', '}');
-                               cell->push_back(MathAtom(new InsetMathHull(hullAlignAt)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
-                       }
-
-                       else if (name == "xalignat" || name == "xalignat*") {
-                               // ignore this for a while
-                               getArg('{', '}');
-                               cell->push_back(MathAtom(new InsetMathHull(hullXAlignAt)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
-                       }
-
-                       else if (name == "xxalignat") {
-                               // ignore this for a while
-                               getArg('{', '}');
-                               cell->push_back(MathAtom(new InsetMathHull(hullXXAlignAt)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
-                       }
-
-                       else if (name == "multline" || name == "multline*") {
-                               cell->push_back(MathAtom(new InsetMathHull(hullMultline)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
-                       }
-
-                       else if (name == "gather" || name == "gather*") {
-                               cell->push_back(MathAtom(new InsetMathHull(hullGather)));
-                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
-                       }
-
-                       else if (latexkeys const * l = in_word_set(name)) {
-                               if (l->inset == "matrix") {
-                                       cell->push_back(createInsetMath(name));
-                                       parse2(cell->back(), FLAG_END, mode, false);
-                               } else if (l->inset == "split") {
-                                       docstring const valign = parse_verbatim_option() + 'c';
-                                       cell->push_back(MathAtom(new InsetMathSplit(name, (char)valign[0])));
-                                       parse2(cell->back(), FLAG_END, mode, false);
-                               } else {
-                                       dump();
-                                       lyxerr << "found math environment `" << to_utf8(name)
-                                              << "' in symbols file with unsupported inset `"
-                                              << to_utf8(l->inset) << "'." << endl;
-                                       // create generic environment inset
-                                       cell->push_back(MathAtom(new InsetMathEnv(name)));
-                                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
-                               }
-                       }
-
-                       else {
-                               dump();
-                               lyxerr << "found unknown math environment '" << to_utf8(name)
-                                       << "'" << endl;
-                               // create generic environment inset
-                               cell->push_back(MathAtom(new InsetMathEnv(name)));
-                               parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
-                       }
-               }
-
-               else if (t.cs() == "kern") {
-#ifdef WITH_WARNINGS
-#warning A hack...
-#endif
-                       docstring s;
-                       while (true) {
-                               Token const & t = getToken();
-                               if (!good()) {
-                                       putback();
-                                       break;
-                               }
-                               s += t.character();
-                               if (isValidLength(to_utf8(s)))
-                                       break;
-                       }
-                       cell->push_back(MathAtom(new InsetMathKern(s)));
-               }
-
-               else if (t.cs() == "label") {
-                       // FIXME: This is swallowed in inline formulas
-                       docstring label = parse_verbatim_item();
-                       MathArray ar;
-                       asArray(label, ar);
-                       if (grid.asHullInset()) {
-                               grid.asHullInset()->label(cellrow, label);
-                       } else {
-                               cell->push_back(createInsetMath(t.cs()));
-                               cell->push_back(MathAtom(new InsetMathBrace(ar)));
-                       }
-               }
-
-               else if (t.cs() == "choose" || t.cs() == "over" || t.cs() == "atop") {
-                       MathAtom at = createInsetMath(t.cs());
-                       at.nucleus()->cell(0) = *cell;
-                       cell->clear();
-                       parse(at.nucleus()->cell(1), flags, mode);
-                       cell->push_back(at);
-                       return;
-               }
-
-               else if (t.cs() == "color") {
-                       docstring const color = parse_verbatim_item();
-                       cell->push_back(MathAtom(new InsetMathColor(true, color)));
-                       parse(cell->back().nucleus()->cell(0), flags, mode);
-                       return;
-               }
-
-               else if (t.cs() == "textcolor") {
-                       docstring const color = parse_verbatim_item();
-                       cell->push_back(MathAtom(new InsetMathColor(false, color)));
-                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE);
-               }
-
-               else if (t.cs() == "normalcolor") {
-                       cell->push_back(createInsetMath(t.cs()));
-                       parse(cell->back().nucleus()->cell(0), flags, mode);
-                       return;
-               }
-
-               else if (t.cs() == "substack") {
-                       cell->push_back(createInsetMath(t.cs()));
-                       parse2(cell->back(), FLAG_ITEM, mode, false);
-               }
-
-               else if (t.cs() == "xymatrix") {
-                       odocstringstream os;
-                       while (good() && nextToken().cat() != catBegin)
-                               os << getToken().asInput();
-                       cell->push_back(createInsetMath(t.cs() + os.str()));
-                       parse2(cell->back(), FLAG_ITEM, mode, false);
-               }
-
-               else if (t.cs() == "framebox" || t.cs() == "makebox") {
-                       cell->push_back(createInsetMath(t.cs()));
-                       parse(cell->back().nucleus()->cell(0), FLAG_OPTION, InsetMath::TEXT_MODE);
-                       parse(cell->back().nucleus()->cell(1), FLAG_OPTION, InsetMath::TEXT_MODE);
-                       parse(cell->back().nucleus()->cell(2), FLAG_ITEM, InsetMath::TEXT_MODE);
-               }
-
-               else if (t.cs() == "tag") {
-                       if (nextToken().character() == '*') {
-                               getToken();
-                               cell->push_back(createInsetMath(t.cs() + '*'));
-                       } else
-                               cell->push_back(createInsetMath(t.cs()));
-                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE);
-               }
-
-#if 0
-               else if (t.cs() == "infer") {
-                       MathArray ar;
-                       parse(ar, FLAG_OPTION, mode);
-                       cell->push_back(createInsetMath(t.cs()));
-                       parse2(cell->back(), FLAG_ITEM, mode, false);
-               }
-
-               // Disabled
-               else if (1 && t.cs() == "ar") {
-                       auto_ptr<InsetMathXYArrow> p(new InsetMathXYArrow);
-                       // try to read target
-                       parse(p->cell(0), FLAG_OTPTION, mode);
-                       // try to read label
-                       if (nextToken().cat() == catSuper || nextToken().cat() == catSub) {
-                               p->up_ = nextToken().cat() == catSuper;
-                               getToken();
-                               parse(p->cell(1), FLAG_ITEM, mode);
-                               //lyxerr << "read label: " << p->cell(1) << endl;
-                       }
-
-                       cell->push_back(MathAtom(p.release()));
-                       //lyxerr << "read cell: " << cell << endl;
-               }
-#endif
-
-               else if (t.cs().size()) {
-                       latexkeys const * l = in_word_set(t.cs());
-                       if (l) {
-                               if (l->inset == "big") {
-                                       skipSpaces();
-                                       docstring const delim = getToken().asInput();
-                                       if (InsetMathBig::isBigInsetDelim(delim))
-                                               cell->push_back(MathAtom(
-                                                       new InsetMathBig(t.cs(), delim)));
-                                       else {
-                                               cell->push_back(createInsetMath(t.cs()));
-                                               putback();
-                                       }
-                               }
-
-                               else if (l->inset == "font") {
-                                       cell->push_back(createInsetMath(t.cs()));
-                                       parse(cell->back().nucleus()->cell(0),
-                                               FLAG_ITEM, asMode(mode, l->extra));
-                               }
-
-                               else if (l->inset == "oldfont") {
-                                       cell->push_back(createInsetMath(t.cs()));
-                                       parse(cell->back().nucleus()->cell(0),
-                                               flags | FLAG_ALIGN, asMode(mode, l->extra));
-                                       if (prevToken().cat() != catAlign &&
-                                           prevToken().cs() != "\\")
-                                               return;
-                                       putback();
-                               }
-
-                               else if (l->inset == "style") {
-                                       cell->push_back(createInsetMath(t.cs()));
-                                       parse(cell->back().nucleus()->cell(0),
-                                               flags | FLAG_ALIGN, mode);
-                                       if (prevToken().cat() != catAlign &&
-                                           prevToken().cs() != "\\")
-                                               return;
-                                       putback();
-                               }
-
-                               else {
-                                       MathAtom at = createInsetMath(t.cs());
-                                       for (InsetMath::idx_type i = 0; i < at->nargs(); ++i)
-                                               parse(at.nucleus()->cell(i),
-                                                       FLAG_ITEM, asMode(mode, l->extra));
-                                       cell->push_back(at);
-                               }
-                       }
-
-                       else {
-                               MathAtom at = createInsetMath(t.cs());
-                               InsetMath::mode_type m = mode;
-                               //if (m == InsetMath::UNDECIDED_MODE)
-                               //lyxerr << "default creation: m1: " << m << endl;
-                               if (at->currentMode() != InsetMath::UNDECIDED_MODE)
-                                       m = at->currentMode();
-                               //lyxerr << "default creation: m2: " << m << endl;
-                               InsetMath::idx_type start = 0;
-                               // this fails on \bigg[...\bigg]
-                               //MathArray opt;
-                               //parse(opt, FLAG_OPTION, InsetMath::VERBATIM_MODE);
-                               //if (opt.size()) {
-                               //      start = 1;
-                               //      at.nucleus()->cell(0) = opt;
-                               //}
-                               for (InsetMath::idx_type i = start; i < at->nargs(); ++i) {
-                                       parse(at.nucleus()->cell(i), FLAG_ITEM, m);
-                                       skipSpaces();
-                               }
-                               cell->push_back(at);
-                       }
-               }
-
-
-               if (flags & FLAG_LEAVE) {
-                       flags &= ~FLAG_LEAVE;
-                       break;
-               }
-       }
-}
-
-
-
-} // anonymous namespace
-
-
-void mathed_parse_cell(MathArray & ar, docstring const & str)
-{
-       Parser(str).parse(ar, 0, InsetMath::MATH_MODE);
-}
-
-
-void mathed_parse_cell(MathArray & ar, istream & is)
-{
-       Parser(is).parse(ar, 0, InsetMath::MATH_MODE);
-}
-
-
-bool mathed_parse_normal(MathAtom & t, docstring const & str)
-{
-       return Parser(str).parse(t);
-}
-
-
-bool mathed_parse_normal(MathAtom & t, LyXLex & lex)
-{
-       return Parser(lex).parse(t);
-}
-
-
-void mathed_parse_normal(InsetMathGrid & grid, docstring const & str)
-{
-       Parser(str).parse1(grid, 0, InsetMath::MATH_MODE, false);
-}
-
-
-void initParser()
-{
-       fill(theCatcode, theCatcode + 128, catOther);
-       fill(theCatcode + 'a', theCatcode + 'z' + 1, catLetter);
-       fill(theCatcode + 'A', theCatcode + 'Z' + 1, catLetter);
-
-       theCatcode[int('\\')] = catEscape;
-       theCatcode[int('{')]  = catBegin;
-       theCatcode[int('}')]  = catEnd;
-       theCatcode[int('$')]  = catMath;
-       theCatcode[int('&')]  = catAlign;
-       theCatcode[int('\n')] = catNewline;
-       theCatcode[int('#')]  = catParameter;
-       theCatcode[int('^')]  = catSuper;
-       theCatcode[int('_')]  = catSub;
-       theCatcode[int(0x7f)] = catIgnore;
-       theCatcode[int(' ')]  = catSpace;
-       theCatcode[int('\t')] = catSpace;
-       theCatcode[int('\r')] = catNewline;
-       theCatcode[int('~')]  = catActive;
-       theCatcode[int('%')]  = catComment;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathParser.cpp b/src/mathed/MathParser.cpp
new file mode 100644 (file)
index 0000000..c985057
--- /dev/null
@@ -0,0 +1,1511 @@
+/**
+ * \file MathParser.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+/*
+
+If someone desperately needs partial "structures" (such as a few
+cells of an array inset or similar) (s)he could uses the
+following hack as starting point to write some macros:
+
+  \newif\ifcomment
+  \commentfalse
+  \ifcomment
+         \def\makeamptab{\catcode`\&=4\relax}
+         \def\makeampletter{\catcode`\&=11\relax}
+    \def\b{\makeampletter\expandafter\makeamptab\bi}
+    \long\def\bi#1\e{}
+  \else
+    \def\b{}\def\e{}
+  \fi
+
+  ...
+
+  \[\begin{array}{ccc}
+1
+&
+
+  \end{array}\]
+
+*/
+
+
+#include <config.h>
+
+#include "MathParser.h"
+
+#include "InsetMathArray.h"
+#include "InsetMathBig.h"
+#include "InsetMathBrace.h"
+#include "InsetMathChar.h"
+#include "InsetMathColor.h"
+#include "InsetMathComment.h"
+#include "InsetMathDelim.h"
+#include "InsetMathEnv.h"
+#include "InsetMathKern.h"
+#include "InsetMathMacro.h"
+#include "InsetMathPar.h"
+#include "InsetMathRef.h"
+#include "InsetMathRoot.h"
+#include "InsetMathScript.h"
+#include "InsetMathSplit.h"
+#include "InsetMathSqrt.h"
+#include "InsetMathTabular.h"
+#include "MathMacroTemplate.h"
+#include "MathFactory.h"
+#include "MathMacroArgument.h"
+#include "MathSupport.h"
+
+#include "lyxlex.h"
+#include "debug.h"
+
+#include "support/convert.h"
+
+#include <sstream>
+
+
+namespace lyx {
+
+using std::endl;
+using std::fill;
+
+using std::string;
+using std::ios;
+using std::istream;
+using std::ostream;
+using std::vector;
+
+
+//#define FILEDEBUG
+
+
+namespace {
+
+InsetMath::mode_type asMode(InsetMath::mode_type oldmode, docstring const & str)
+{
+       //lyxerr << "handling mode: '" << str << "'" << endl;
+       if (str == "mathmode")
+               return InsetMath::MATH_MODE;
+       if (str == "textmode" || str == "forcetext")
+               return InsetMath::TEXT_MODE;
+       return oldmode;
+}
+
+
+bool stared(docstring const & s)
+{
+       size_t const n = s.size();
+       return n && s[n - 1] == '*';
+}
+
+
+/*!
+ * Add the row \p cellrow to \p grid.
+ * \returns wether the row could be added. Adding a row can fail for
+ * environments like "equation" that have a fixed number of rows.
+ */
+bool addRow(InsetMathGrid & grid, InsetMathGrid::row_type & cellrow,
+           docstring const & vskip, bool allow_pagebreak = true)
+{
+       ++cellrow;
+       if (cellrow == grid.nrows()) {
+               //lyxerr << "adding row " << cellrow << endl;
+               grid.addRow(cellrow - 1);
+               if (cellrow == grid.nrows()) {
+                       // We can't add a row to this grid, so let's
+                       // append the content of this cell to the previous
+                       // one.
+                       // This does not happen in well formed .lyx files,
+                       // but LyX versions 1.3.x and older could create
+                       // such files and tex2lyx can still do that.
+                       --cellrow;
+                       lyxerr << "ignoring extra row";
+                       if (!vskip.empty())
+                               lyxerr << " with extra space " << to_utf8(vskip);
+                       if (!allow_pagebreak)
+                               lyxerr << " with no page break allowed";
+                       lyxerr << '.' << endl;
+                       return false;
+               }
+       }
+       grid.vcrskip(LyXLength(to_utf8(vskip)), cellrow - 1);
+       grid.rowinfo(cellrow - 1).allow_pagebreak_ = allow_pagebreak;
+       return true;
+}
+
+
+/*!
+ * Add the column \p cellcol to \p grid.
+ * \returns wether the column could be added. Adding a column can fail for
+ * environments like "eqnarray" that have a fixed number of columns.
+ */
+bool addCol(InsetMathGrid & grid, InsetMathGrid::col_type & cellcol)
+{
+       ++cellcol;
+       if (cellcol == grid.ncols()) {
+               //lyxerr << "adding column " << cellcol << endl;
+               grid.addCol(cellcol - 1);
+               if (cellcol == grid.ncols()) {
+                       // We can't add a column to this grid, so let's
+                       // append the content of this cell to the previous
+                       // one.
+                       // This does not happen in well formed .lyx files,
+                       // but LyX versions 1.3.x and older could create
+                       // such files and tex2lyx can still do that.
+                       --cellcol;
+                       lyxerr << "ignoring extra column." << endl;
+                       return false;
+               }
+       }
+       return true;
+}
+
+
+/*!
+ * Check wether the last row is empty and remove it if yes.
+ * Otherwise the following code
+ * \verbatim
+\begin{array}{|c|c|}
+\hline
+1 & 2 \\ \hline
+3 & 4 \\ \hline
+\end{array}
+ * \endverbatim
+ * will result in a grid with 3 rows (+ the dummy row that is always present),
+ * because the last '\\' opens a new row.
+ */
+void delEmptyLastRow(InsetMathGrid & grid)
+{
+       InsetMathGrid::row_type const row = grid.nrows() - 1;
+       for (InsetMathGrid::col_type col = 0; col < grid.ncols(); ++col) {
+               if (!grid.cell(grid.index(row, col)).empty())
+                       return;
+       }
+       // Copy the row information of the empty row (which would contain the
+       // last hline in the example above) to the dummy row and delete the
+       // empty row.
+       grid.rowinfo(row + 1) = grid.rowinfo(row);
+       grid.delRow(row);
+}
+
+
+// These are TeX's catcodes
+enum CatCode {
+       catEscape,     // 0    backslash
+       catBegin,      // 1    {
+       catEnd,        // 2    }
+       catMath,       // 3    $
+       catAlign,      // 4    &
+       catNewline,    // 5    ^^M
+       catParameter,  // 6    #
+       catSuper,      // 7    ^
+       catSub,        // 8    _
+       catIgnore,     // 9
+       catSpace,      // 10   space
+       catLetter,     // 11   a-zA-Z
+       catOther,      // 12   none of the above
+       catActive,     // 13   ~
+       catComment,    // 14   %
+       catInvalid     // 15   <delete>
+};
+
+CatCode theCatcode[128];
+
+
+inline CatCode catcode(char_type c)
+{
+       /* The only characters that are not catOther lie in the pure ASCII
+        * range. Therefore theCatcode has only 128 entries.
+        * TeX itself deals with 8bit characters, so if needed this table
+        * could be enlarged to 256 entries.
+        * Any larger value does not make sense, since the fact that we use
+        * unicode internally does not change Knuth's TeX engine.
+        * Apart from that a table for the full 21bit UCS4 range would waste
+        * too much memory. */
+       if (c >= 128)
+               return catOther;
+
+       return theCatcode[c];
+}
+
+
+enum {
+       FLAG_ALIGN      = 1 << 0,  //  next & or \\ ends the parsing process
+       FLAG_BRACE_LAST = 1 << 1,  //  next closing brace ends the parsing
+       FLAG_RIGHT      = 1 << 2,  //  next \\right ends the parsing process
+       FLAG_END        = 1 << 3,  //  next \\end ends the parsing process
+       FLAG_BRACK_LAST = 1 << 4,  //  next closing bracket ends the parsing
+       FLAG_TEXTMODE   = 1 << 5,  //  we are in a box
+       FLAG_ITEM       = 1 << 6,  //  read a (possibly braced token)
+       FLAG_LEAVE      = 1 << 7,  //  leave the loop at the end
+       FLAG_SIMPLE     = 1 << 8,  //  next $ leaves the loop
+       FLAG_EQUATION   = 1 << 9,  //  next \] leaves the loop
+       FLAG_SIMPLE2    = 1 << 10, //  next \) leaves the loop
+       FLAG_OPTION     = 1 << 11, //  read [...] style option
+       FLAG_BRACED     = 1 << 12  //  read {...} style argument
+};
+
+
+//
+// Helper class for parsing
+//
+
+class Token {
+public:
+       ///
+       Token() : cs_(), char_(0), cat_(catIgnore) {}
+       ///
+       Token(char_type c, CatCode cat) : cs_(), char_(c), cat_(cat) {}
+       ///
+       explicit Token(docstring const & cs) : cs_(cs), char_(0), cat_(catIgnore) {}
+
+       ///
+       docstring const & cs() const { return cs_; }
+       ///
+       CatCode cat() const { return cat_; }
+       ///
+       char_type character() const { return char_; }
+       ///
+       docstring asString() const { return cs_.size() ? cs_ : docstring(1, char_); }
+       ///
+       docstring asInput() const { return cs_.size() ? '\\' + cs_ : docstring(1, char_); }
+
+private:
+       ///
+       docstring cs_;
+       ///
+       char_type char_;
+       ///
+       CatCode cat_;
+};
+
+
+ostream & operator<<(ostream & os, Token const & t)
+{
+       if (t.cs().size()) {
+               docstring const & cs = t.cs();
+               // FIXME: For some strange reason, the stream operator instanciate
+               // a new Token before outputting the contents of t.cs().
+               // Because of this the line 
+               //     os << '\\' << cs;
+               // below becomes recursive.
+               // In order to avoid that we return early:
+               if (cs == "\\")
+                       return os;
+               os << '\\' << to_utf8(cs);
+       }
+       else if (t.cat() == catLetter)
+               os << t.character();
+       else
+               os << '[' << t.character() << ',' << t.cat() << ']';
+       return os;
+}
+
+
+class Parser {
+public:
+       ///
+       typedef  InsetMath::mode_type mode_type;
+
+       ///
+       Parser(LyXLex & lex);
+       /// Only use this for reading from .lyx file format, for the reason
+       /// see Parser::tokenize(std::istream &).
+       Parser(istream & is);
+       ///
+       Parser(docstring const & str);
+
+       ///
+       bool parse(MathAtom & at);
+       ///
+       void parse(MathArray & array, unsigned flags, mode_type mode);
+       ///
+       void parse1(InsetMathGrid & grid, unsigned flags, mode_type mode,
+               bool numbered);
+       ///
+       MathArray parse(unsigned flags, mode_type mode);
+       ///
+       int lineno() const { return lineno_; }
+       ///
+       void putback();
+
+private:
+       ///
+       void parse2(MathAtom & at, unsigned flags, mode_type mode, bool numbered);
+       /// get arg delimited by 'left' and 'right'
+       docstring getArg(char_type left, char_type right);
+       ///
+       char_type getChar();
+       ///
+       void error(string const & msg);
+       void error(docstring const & msg) { error(to_utf8(msg)); }
+       /// dump contents to screen
+       void dump() const;
+       /// Only use this for reading from .lyx file format (see
+       /// implementation for reason)
+       void tokenize(istream & is);
+       ///
+       void tokenize(docstring const & s);
+       ///
+       void skipSpaceTokens(idocstream & is, char_type c);
+       ///
+       void push_back(Token const & t);
+       ///
+       void pop_back();
+       ///
+       Token const & prevToken() const;
+       ///
+       Token const & nextToken() const;
+       ///
+       Token const & getToken();
+       /// skips spaces if any
+       void skipSpaces();
+       ///
+       void lex(docstring const & s);
+       ///
+       bool good() const;
+       ///
+       docstring parse_verbatim_item();
+       ///
+       docstring parse_verbatim_option();
+
+       ///
+       int lineno_;
+       ///
+       vector<Token> tokens_;
+       ///
+       unsigned pos_;
+       /// Stack of active environments
+       vector<docstring> environments_;
+};
+
+
+Parser::Parser(LyXLex & lexer)
+       : lineno_(lexer.getLineNo()), pos_(0)
+{
+       tokenize(lexer.getStream());
+       lexer.eatLine();
+}
+
+
+Parser::Parser(istream & is)
+       : lineno_(0), pos_(0)
+{
+       tokenize(is);
+}
+
+
+Parser::Parser(docstring const & str)
+       : lineno_(0), pos_(0)
+{
+       tokenize(str);
+}
+
+
+void Parser::push_back(Token const & t)
+{
+       tokens_.push_back(t);
+}
+
+
+void Parser::pop_back()
+{
+       tokens_.pop_back();
+}
+
+
+Token const & Parser::prevToken() const
+{
+       static const Token dummy;
+       return pos_ > 0 ? tokens_[pos_ - 1] : dummy;
+}
+
+
+Token const & Parser::nextToken() const
+{
+       static const Token dummy;
+       return good() ? tokens_[pos_] : dummy;
+}
+
+
+Token const & Parser::getToken()
+{
+       static const Token dummy;
+       //lyxerr << "looking at token " << tokens_[pos_] << " pos: " << pos_ << endl;
+       return good() ? tokens_[pos_++] : dummy;
+}
+
+
+void Parser::skipSpaces()
+{
+       while (nextToken().cat() == catSpace || nextToken().cat() == catNewline)
+               getToken();
+}
+
+
+void Parser::putback()
+{
+       --pos_;
+}
+
+
+bool Parser::good() const
+{
+       return pos_ < tokens_.size();
+}
+
+
+char_type Parser::getChar()
+{
+       if (!good())
+               error("The input stream is not well...");
+       return tokens_[pos_++].character();
+}
+
+
+docstring Parser::getArg(char_type left, char_type right)
+{
+       skipSpaces();
+
+       docstring result;
+       char_type c = getChar();
+
+       if (c != left)
+               putback();
+       else
+               while ((c = getChar()) != right && good())
+                       result += c;
+
+       return result;
+}
+
+
+void Parser::skipSpaceTokens(idocstream & is, char_type c)
+{
+       // skip trailing spaces
+       while (catcode(c) == catSpace || catcode(c) == catNewline)
+               if (!is.get(c))
+                       break;
+       //lyxerr << "putting back: " << c << endl;
+       is.putback(c);
+}
+
+
+void Parser::tokenize(istream & is)
+{
+       // eat everything up to the next \end_inset or end of stream
+       // and store it in s for further tokenization
+       string s;
+       char c;
+       while (is.get(c)) {
+               s += c;
+               if (s.size() >= 10 && s.substr(s.size() - 10) == "\\end_inset") {
+                       s = s.substr(0, s.size() - 10);
+                       break;
+               }
+       }
+       // Remove the space after \end_inset
+       if (is.get(c) && c != ' ')
+               is.unget();
+
+       // tokenize buffer
+       tokenize(from_utf8(s));
+}
+
+
+void Parser::tokenize(docstring const & buffer)
+{
+       idocstringstream is(buffer, ios::in | ios::binary);
+
+       char_type c;
+       while (is.get(c)) {
+               //lyxerr << "reading c: " << c << endl;
+
+               switch (catcode(c)) {
+                       case catNewline: {
+                               ++lineno_;
+                               is.get(c);
+                               if (catcode(c) == catNewline)
+                                       ; //push_back(Token("par"));
+                               else {
+                                       push_back(Token('\n', catNewline));
+                                       is.putback(c);
+                               }
+                               break;
+                       }
+
+/*
+                       case catComment: {
+                               while (is.get(c) && catcode(c) != catNewline)
+                                       ;
+                               ++lineno_;
+                               break;
+                       }
+*/
+
+                       case catEscape: {
+                               is.get(c);
+                               if (!is) {
+                                       error("unexpected end of input");
+                               } else {
+                                       docstring s(1, c);
+                                       if (catcode(c) == catLetter) {
+                                               // collect letters
+                                               while (is.get(c) && catcode(c) == catLetter)
+                                                       s += c;
+                                               skipSpaceTokens(is, c);
+                                       }
+                                       push_back(Token(s));
+                               }
+                               break;
+                       }
+
+                       case catSuper:
+                       case catSub: {
+                               push_back(Token(c, catcode(c)));
+                               is.get(c);
+                               skipSpaceTokens(is, c);
+                               break;
+                       }
+
+                       case catIgnore: {
+                               lyxerr << "ignoring a char: " << int(c) << endl;
+                               break;
+                       }
+
+                       default:
+                               push_back(Token(c, catcode(c)));
+               }
+       }
+
+#ifdef FILEDEBUG
+       dump();
+#endif
+}
+
+
+void Parser::dump() const
+{
+       lyxerr << "\nTokens: ";
+       for (unsigned i = 0; i < tokens_.size(); ++i) {
+               if (i == pos_)
+                       lyxerr << " <#> ";
+               lyxerr << tokens_[i];
+       }
+       lyxerr << " pos: " << pos_ << endl;
+}
+
+
+void Parser::error(string const & msg)
+{
+       lyxerr << "Line ~" << lineno_ << ": Math parse error: " << msg << endl;
+       dump();
+       //exit(1);
+}
+
+
+bool Parser::parse(MathAtom & at)
+{
+       skipSpaces();
+       MathArray ar;
+       parse(ar, false, InsetMath::UNDECIDED_MODE);
+       if (ar.size() != 1 || ar.front()->getType() == hullNone) {
+               lyxerr << "unusual contents found: " << ar << endl;
+               at = MathAtom(new InsetMathPar(ar));
+               //if (at->nargs() > 0)
+               //      at.nucleus()->cell(0) = ar;
+               //else
+               //      lyxerr << "unusual contents found: " << ar << endl;
+               return true;
+       }
+       at = ar[0];
+       return true;
+}
+
+
+docstring Parser::parse_verbatim_option()
+{
+       skipSpaces();
+       docstring res;
+       if (nextToken().character() == '[') {
+               Token t = getToken();
+               for (Token t = getToken(); t.character() != ']' && good(); t = getToken()) {
+                       if (t.cat() == catBegin) {
+                               putback();
+                               res += '{' + parse_verbatim_item() + '}';
+                       } else
+                               res += t.asString();
+               }
+       }
+       return res;
+}
+
+
+docstring Parser::parse_verbatim_item()
+{
+       skipSpaces();
+       docstring res;
+       if (nextToken().cat() == catBegin) {
+               Token t = getToken();
+               for (Token t = getToken(); t.cat() != catEnd && good(); t = getToken()) {
+                       if (t.cat() == catBegin) {
+                               putback();
+                               res += '{' + parse_verbatim_item() + '}';
+                       }
+                       else
+                               res += t.asString();
+               }
+       }
+       return res;
+}
+
+
+MathArray Parser::parse(unsigned flags, mode_type mode)
+{
+       MathArray ar;
+       parse(ar, flags, mode);
+       return ar;
+}
+
+
+void Parser::parse(MathArray & array, unsigned flags, mode_type mode)
+{
+       InsetMathGrid grid(1, 1);
+       parse1(grid, flags, mode, false);
+       array = grid.cell(0);
+}
+
+
+void Parser::parse2(MathAtom & at, const unsigned flags, const mode_type mode,
+       const bool numbered)
+{
+       parse1(*(at.nucleus()->asGridInset()), flags, mode, numbered);
+}
+
+
+void Parser::parse1(InsetMathGrid & grid, unsigned flags,
+       const mode_type mode, const bool numbered)
+{
+       int limits = 0;
+       InsetMathGrid::row_type cellrow = 0;
+       InsetMathGrid::col_type cellcol = 0;
+       MathArray * cell = &grid.cell(grid.index(cellrow, cellcol));
+
+       if (grid.asHullInset())
+               grid.asHullInset()->numbered(cellrow, numbered);
+
+       //dump();
+       //lyxerr << " flags: " << flags << endl;
+       //lyxerr << " mode: " << mode  << endl;
+       //lyxerr << "grid: " << grid << endl;
+
+       while (good()) {
+               Token const & t = getToken();
+
+#ifdef FILEDEBUG
+               lyxerr << "t: " << t << " flags: " << flags << endl;
+               lyxerr << "mode: " << mode  << endl;
+               cell->dump();
+               lyxerr << endl;
+#endif
+
+               if (flags & FLAG_ITEM) {
+
+                       if (t.cat() == catBegin) {
+                               // skip the brace and collect everything to the next matching
+                               // closing brace
+                               parse1(grid, FLAG_BRACE_LAST, mode, numbered);
+                               return;
+                       }
+
+                       // handle only this single token, leave the loop if done
+                       flags = FLAG_LEAVE;
+               }
+
+
+               if (flags & FLAG_BRACED) {
+                       if (t.cat() == catSpace)
+                               continue;
+
+                       if (t.cat() != catBegin) {
+                               error("opening brace expected");
+                               return;
+                       }
+
+                       // skip the brace and collect everything to the next matching
+                       // closing brace
+                       flags = FLAG_BRACE_LAST;
+               }
+
+
+               if (flags & FLAG_OPTION) {
+                       if (t.cat() == catOther && t.character() == '[') {
+                               MathArray ar;
+                               parse(ar, FLAG_BRACK_LAST, mode);
+                               cell->append(ar);
+                       } else {
+                               // no option found, put back token and we are done
+                               putback();
+                       }
+                       return;
+               }
+
+               //
+               // cat codes
+               //
+               if (t.cat() == catMath) {
+                       if (mode != InsetMath::MATH_MODE) {
+                               // we are inside some text mode thingy, so opening new math is allowed
+                               Token const & n = getToken();
+                               if (n.cat() == catMath) {
+                                       // TeX's $$...$$ syntax for displayed math
+                                       cell->push_back(MathAtom(new InsetMathHull(hullEquation)));
+                                       parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false);
+                                       getToken(); // skip the second '$' token
+                               } else {
+                                       // simple $...$  stuff
+                                       putback();
+                                       cell->push_back(MathAtom(new InsetMathHull(hullSimple)));
+                                       parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false);
+                               }
+                       }
+
+                       else if (flags & FLAG_SIMPLE) {
+                               // this is the end of the formula
+                               return;
+                       }
+
+                       else {
+                               error("something strange in the parser");
+                               break;
+                       }
+               }
+
+               else if (t.cat() == catLetter)
+                       cell->push_back(MathAtom(new InsetMathChar(t.character())));
+
+               else if (t.cat() == catSpace && mode != InsetMath::MATH_MODE) {
+                       if (cell->empty() || cell->back()->getChar() != ' ')
+                               cell->push_back(MathAtom(new InsetMathChar(t.character())));
+               }
+
+               else if (t.cat() == catNewline && mode != InsetMath::MATH_MODE) {
+                       if (cell->empty() || cell->back()->getChar() != ' ')
+                               cell->push_back(MathAtom(new InsetMathChar(' ')));
+               }
+
+               else if (t.cat() == catParameter) {
+                       Token const & n = getToken();
+                       cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0')));
+               }
+
+               else if (t.cat() == catActive)
+                       cell->push_back(MathAtom(new InsetMathChar(t.character())));
+
+               else if (t.cat() == catBegin) {
+                       MathArray ar;
+                       parse(ar, FLAG_BRACE_LAST, mode);
+                       // do not create a BraceInset if they were written by LyX
+                       // this helps to keep the annoyance of  "a choose b"  to a minimum
+                       if (ar.size() == 1 && ar[0]->extraBraces())
+                               cell->append(ar);
+                       else
+                               cell->push_back(MathAtom(new InsetMathBrace(ar)));
+               }
+
+               else if (t.cat() == catEnd) {
+                       if (flags & FLAG_BRACE_LAST)
+                               return;
+                       error("found '}' unexpectedly");
+                       //BOOST_ASSERT(false);
+                       //add(cell, '}', LM_TC_TEX);
+               }
+
+               else if (t.cat() == catAlign) {
+                       //lyxerr << " column now " << (cellcol + 1)
+                       //       << " max: " << grid.ncols() << endl;
+                       if (flags & FLAG_ALIGN)
+                               return;
+                       if (addCol(grid, cellcol))
+                               cell = &grid.cell(grid.index(cellrow, cellcol));
+               }
+
+               else if (t.cat() == catSuper || t.cat() == catSub) {
+                       bool up = (t.cat() == catSuper);
+                       // we need no new script inset if the last thing was a scriptinset,
+                       // which has that script already not the same script already
+                       if (!cell->size())
+                               cell->push_back(MathAtom(new InsetMathScript(up)));
+                       else if (cell->back()->asScriptInset() &&
+                                       !cell->back()->asScriptInset()->has(up))
+                               cell->back().nucleus()->asScriptInset()->ensure(up);
+                       else if (cell->back()->asScriptInset())
+                               cell->push_back(MathAtom(new InsetMathScript(up)));
+                       else
+                               cell->back() = MathAtom(new InsetMathScript(cell->back(), up));
+                       InsetMathScript * p = cell->back().nucleus()->asScriptInset();
+                       // special handling of {}-bases
+                       // Here we could remove the brace inset for things
+                       // like {a'}^2 and add the braces back in
+                       // InsetMathScript::write().
+                       // We do not do it, since it is not possible to detect
+                       // reliably whether the braces are needed because the
+                       // nucleus contains more than one symbol, or whether
+                       // they are needed for unknown commands like \xx{a}_0
+                       // or \yy{a}{b}_0. This was done in revision 14819
+                       // in an unreliable way. See this thread
+                       // http://www.mail-archive.com/lyx-devel%40lists.lyx.org/msg104917.html
+                       // for more details.
+                       parse(p->cell(p->idxOfScript(up)), FLAG_ITEM, mode);
+                       if (limits) {
+                               p->limits(limits);
+                               limits = 0;
+                       }
+               }
+
+               else if (t.character() == ']' && (flags & FLAG_BRACK_LAST)) {
+                       //lyxerr << "finished reading option" << endl;
+                       return;
+               }
+
+               else if (t.cat() == catOther)
+                       cell->push_back(MathAtom(new InsetMathChar(t.character())));
+
+               else if (t.cat() == catComment) {
+                       docstring s;
+                       while (good()) {
+                               Token const & t = getToken();
+                               if (t.cat() == catNewline)
+                                       break;
+                               s += t.asString();
+                       }
+                       cell->push_back(MathAtom(new InsetMathComment(s)));
+                       skipSpaces();
+               }
+
+               //
+               // control sequences
+               //
+
+               else if (t.cs() == "lyxlock") {
+                       if (cell->size())
+                               cell->back().nucleus()->lock(true);
+               }
+
+               else if (t.cs() == "def" ||
+                       t.cs() == "newcommand" ||
+                       t.cs() == "renewcommand")
+               {
+                       docstring const type = t.cs();
+                       docstring name;
+                       int nargs = 0;
+                       if (t.cs() == "def") {
+                               // get name
+                               name = getToken().cs();
+
+                               // read parameter
+                               docstring pars;
+                               while (good() && nextToken().cat() != catBegin) {
+                                       pars += getToken().cs();
+                                       ++nargs;
+                               }
+                               nargs /= 2;
+                               //lyxerr << "read \\def parameter list '" << pars << "'" << endl;
+
+                       } else { // t.cs() == "newcommand" || t.cs() == "renewcommand"
+
+                               if (getToken().cat() != catBegin) {
+                                       error("'{' in \\newcommand expected (1) ");
+                                       return;
+                               }
+
+                               name = getToken().cs();
+
+                               if (getToken().cat() != catEnd) {
+                                       error("'}' in \\newcommand expected");
+                                       return;
+                               }
+
+                               docstring const arg = getArg('[', ']');
+                               if (!arg.empty())
+                                       nargs = convert<int>(arg);
+
+                       }
+
+                       MathArray ar1;
+                       parse(ar1, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
+
+                       // we cannot handle recursive stuff at all
+                       //MathArray test;
+                       //test.push_back(createInsetMath(name));
+                       //if (ar1.contains(test)) {
+                       //      error("we cannot handle recursive macros at all.");
+                       //      return;
+                       //}
+
+                       // is a version for display attached?
+                       skipSpaces();
+                       MathArray ar2;
+                       if (nextToken().cat() == catBegin)
+                               parse(ar2, FLAG_ITEM, InsetMath::MATH_MODE);
+
+                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, type,
+                               ar1, ar2)));
+               }
+
+               else if (t.cs() == "(") {
+                       cell->push_back(MathAtom(new InsetMathHull(hullSimple)));
+                       parse2(cell->back(), FLAG_SIMPLE2, InsetMath::MATH_MODE, false);
+               }
+
+               else if (t.cs() == "[") {
+                       cell->push_back(MathAtom(new InsetMathHull(hullEquation)));
+                       parse2(cell->back(), FLAG_EQUATION, InsetMath::MATH_MODE, false);
+               }
+
+               else if (t.cs() == "protect")
+                       // ignore \\protect, will hopefully be re-added during output
+                       ;
+
+               else if (t.cs() == "end") {
+                       if (flags & FLAG_END) {
+                               // eat environment name
+                               docstring const name = getArg('{', '}');
+                               if (environments_.empty())
+                                       error("'found \\end{" + name +
+                                             "}' without matching '\\begin{" +
+                                             name + "}'");
+                               else if (name != environments_.back())
+                                       error("'\\end{" + name +
+                                             "}' does not match '\\begin{" +
+                                             environments_.back() + "}'");
+                               else {
+                                       environments_.pop_back();
+                                       // Delete empty last row in matrix
+                                       // like insets.
+                                       // If you abuse InsetMathGrid for
+                                       // non-matrix like structures you
+                                       // probably need to refine this test.
+                                       // Right now we only have to test for
+                                       // single line hull insets.
+                                       if (grid.nrows() > 1)
+                                               delEmptyLastRow(grid);
+                                       return;
+                               }
+                       } else
+                               error("found 'end' unexpectedly");
+               }
+
+               else if (t.cs() == ")") {
+                       if (flags & FLAG_SIMPLE2)
+                               return;
+                       error("found '\\)' unexpectedly");
+               }
+
+               else if (t.cs() == "]") {
+                       if (flags & FLAG_EQUATION)
+                               return;
+                       error("found '\\]' unexpectedly");
+               }
+
+               else if (t.cs() == "\\") {
+                       if (flags & FLAG_ALIGN)
+                               return;
+                       bool added;
+                       if (nextToken().asInput() == "*") {
+                               getToken();
+                               added = addRow(grid, cellrow, docstring(), false);
+                       } else
+                               added = addRow(grid, cellrow, getArg('[', ']'));
+                       if (added) {
+                               cellcol = 0;
+                               if (grid.asHullInset())
+                                       grid.asHullInset()->numbered(
+                                                       cellrow, numbered);
+                               cell = &grid.cell(grid.index(cellrow,
+                                                            cellcol));
+                       }
+               }
+
+#if 0
+               else if (t.cs() == "multicolumn") {
+                       // extract column count and insert dummy cells
+                       MathArray count;
+                       parse(count, FLAG_ITEM, mode);
+                       int cols = 1;
+                       if (!extractNumber(count, cols)) {
+                               lyxerr << " can't extract number of cells from " << count << endl;
+                       }
+                       // resize the table if necessary
+                       for (int i = 0; i < cols; ++i) {
+                               if (addCol(grid, cellcol)) {
+                                       cell = &grid.cell(grid.index(
+                                                       cellrow, cellcol));
+                                       // mark this as dummy
+                                       grid.cellinfo(grid.index(
+                                               cellrow, cellcol)).dummy_ = true;
+                               }
+                       }
+                       // the last cell is the real thing, not a dummy
+                       grid.cellinfo(grid.index(cellrow, cellcol)).dummy_ = false;
+
+                       // read special alignment
+                       MathArray align;
+                       parse(align, FLAG_ITEM, mode);
+                       //grid.cellinfo(grid.index(cellrow, cellcol)).align_ = extractString(align);
+
+                       // parse the remaining contents into the "real" cell
+                       parse(*cell, FLAG_ITEM, mode);
+               }
+#endif
+
+               else if (t.cs() == "limits")
+                       limits = 1;
+
+               else if (t.cs() == "nolimits")
+                       limits = -1;
+
+               else if (t.cs() == "nonumber") {
+                       if (grid.asHullInset())
+                               grid.asHullInset()->numbered(cellrow, false);
+               }
+
+               else if (t.cs() == "number") {
+                       if (grid.asHullInset())
+                               grid.asHullInset()->numbered(cellrow, true);
+               }
+
+               else if (t.cs() == "hline") {
+                       grid.rowinfo(cellrow).lines_ ++;
+               }
+
+               else if (t.cs() == "sqrt") {
+                       MathArray ar;
+                       parse(ar, FLAG_OPTION, mode);
+                       if (ar.size()) {
+                               cell->push_back(MathAtom(new InsetMathRoot));
+                               cell->back().nucleus()->cell(0) = ar;
+                               parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
+                       } else {
+                               cell->push_back(MathAtom(new InsetMathSqrt));
+                               parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                       }
+               }
+
+               else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") {
+                       cell->push_back(createInsetMath(t.cs()));
+                       parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
+                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+               }
+
+               else if (t.cs() == "ref" || t.cs() == "prettyref" ||
+                               t.cs() == "pageref" || t.cs() == "vpageref" || t.cs() == "vref") {
+                       cell->push_back(MathAtom(new RefInset(t.cs())));
+                       parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
+                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+               }
+
+               else if (t.cs() == "left") {
+                       skipSpaces();
+                       Token const & tl = getToken();
+                       // \| and \Vert are equivalent, and InsetMathDelim
+                       // can't handle \|
+                       // FIXME: fix this in InsetMathDelim itself!
+                       docstring const l = tl.cs() == "|" ? from_ascii("Vert") : tl.asString();
+                       MathArray ar;
+                       parse(ar, FLAG_RIGHT, mode);
+                       if (!good())
+                               break;
+                       skipSpaces();
+                       Token const & tr = getToken();
+                       docstring const r = tr.cs() == "|" ? from_ascii("Vert") : tr.asString();
+                       cell->push_back(MathAtom(new InsetMathDelim(l, r, ar)));
+               }
+
+               else if (t.cs() == "right") {
+                       if (flags & FLAG_RIGHT)
+                               return;
+                       //lyxerr << "got so far: '" << cell << "'" << endl;
+                       error("Unmatched right delimiter");
+                       return;
+               }
+
+               else if (t.cs() == "begin") {
+                       docstring const name = getArg('{', '}');
+                       environments_.push_back(name);
+
+                       if (name == "array" || name == "subarray") {
+                               docstring const valign = parse_verbatim_option() + 'c';
+                               docstring const halign = parse_verbatim_item();
+                               cell->push_back(MathAtom(new InsetMathArray(name, (char)valign[0], halign)));
+                               parse2(cell->back(), FLAG_END, mode, false);
+                       }
+
+                       else if (name == "tabular") {
+                               docstring const valign = parse_verbatim_option() + 'c';
+                               docstring const halign = parse_verbatim_item();
+                               cell->push_back(MathAtom(new InsetMathTabular(name, (char)valign[0], halign)));
+                               parse2(cell->back(), FLAG_END, InsetMath::TEXT_MODE, false);
+                       }
+
+                       else if (name == "split" || name == "cases") {
+                               cell->push_back(createInsetMath(name));
+                               parse2(cell->back(), FLAG_END, mode, false);
+                       }
+
+                       else if (name == "alignedat") {
+                               docstring const valign = parse_verbatim_option() + 'c';
+                               // ignore this for a while
+                               getArg('{', '}');
+                               cell->push_back(MathAtom(new InsetMathSplit(name, (char)valign[0])));
+                               parse2(cell->back(), FLAG_END, mode, false);
+                       }
+
+                       else if (name == "math") {
+                               cell->push_back(MathAtom(new InsetMathHull(hullSimple)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, true);
+                       }
+
+                       else if (name == "equation" || name == "equation*"
+                                       || name == "displaymath") {
+                               cell->push_back(MathAtom(new InsetMathHull(hullEquation)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, (name == "equation"));
+                       }
+
+                       else if (name == "eqnarray" || name == "eqnarray*") {
+                               cell->push_back(MathAtom(new InsetMathHull(hullEqnArray)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+                       }
+
+                       else if (name == "align" || name == "align*") {
+                               cell->push_back(MathAtom(new InsetMathHull(hullAlign)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+                       }
+
+                       else if (name == "flalign" || name == "flalign*") {
+                               cell->push_back(MathAtom(new InsetMathHull(hullFlAlign)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+                       }
+
+                       else if (name == "alignat" || name == "alignat*") {
+                               // ignore this for a while
+                               getArg('{', '}');
+                               cell->push_back(MathAtom(new InsetMathHull(hullAlignAt)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+                       }
+
+                       else if (name == "xalignat" || name == "xalignat*") {
+                               // ignore this for a while
+                               getArg('{', '}');
+                               cell->push_back(MathAtom(new InsetMathHull(hullXAlignAt)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+                       }
+
+                       else if (name == "xxalignat") {
+                               // ignore this for a while
+                               getArg('{', '}');
+                               cell->push_back(MathAtom(new InsetMathHull(hullXXAlignAt)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+                       }
+
+                       else if (name == "multline" || name == "multline*") {
+                               cell->push_back(MathAtom(new InsetMathHull(hullMultline)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+                       }
+
+                       else if (name == "gather" || name == "gather*") {
+                               cell->push_back(MathAtom(new InsetMathHull(hullGather)));
+                               parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+                       }
+
+                       else if (latexkeys const * l = in_word_set(name)) {
+                               if (l->inset == "matrix") {
+                                       cell->push_back(createInsetMath(name));
+                                       parse2(cell->back(), FLAG_END, mode, false);
+                               } else if (l->inset == "split") {
+                                       docstring const valign = parse_verbatim_option() + 'c';
+                                       cell->push_back(MathAtom(new InsetMathSplit(name, (char)valign[0])));
+                                       parse2(cell->back(), FLAG_END, mode, false);
+                               } else {
+                                       dump();
+                                       lyxerr << "found math environment `" << to_utf8(name)
+                                              << "' in symbols file with unsupported inset `"
+                                              << to_utf8(l->inset) << "'." << endl;
+                                       // create generic environment inset
+                                       cell->push_back(MathAtom(new InsetMathEnv(name)));
+                                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                               }
+                       }
+
+                       else {
+                               dump();
+                               lyxerr << "found unknown math environment '" << to_utf8(name)
+                                       << "'" << endl;
+                               // create generic environment inset
+                               cell->push_back(MathAtom(new InsetMathEnv(name)));
+                               parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                       }
+               }
+
+               else if (t.cs() == "kern") {
+#ifdef WITH_WARNINGS
+#warning A hack...
+#endif
+                       docstring s;
+                       while (true) {
+                               Token const & t = getToken();
+                               if (!good()) {
+                                       putback();
+                                       break;
+                               }
+                               s += t.character();
+                               if (isValidLength(to_utf8(s)))
+                                       break;
+                       }
+                       cell->push_back(MathAtom(new InsetMathKern(s)));
+               }
+
+               else if (t.cs() == "label") {
+                       // FIXME: This is swallowed in inline formulas
+                       docstring label = parse_verbatim_item();
+                       MathArray ar;
+                       asArray(label, ar);
+                       if (grid.asHullInset()) {
+                               grid.asHullInset()->label(cellrow, label);
+                       } else {
+                               cell->push_back(createInsetMath(t.cs()));
+                               cell->push_back(MathAtom(new InsetMathBrace(ar)));
+                       }
+               }
+
+               else if (t.cs() == "choose" || t.cs() == "over" || t.cs() == "atop") {
+                       MathAtom at = createInsetMath(t.cs());
+                       at.nucleus()->cell(0) = *cell;
+                       cell->clear();
+                       parse(at.nucleus()->cell(1), flags, mode);
+                       cell->push_back(at);
+                       return;
+               }
+
+               else if (t.cs() == "color") {
+                       docstring const color = parse_verbatim_item();
+                       cell->push_back(MathAtom(new InsetMathColor(true, color)));
+                       parse(cell->back().nucleus()->cell(0), flags, mode);
+                       return;
+               }
+
+               else if (t.cs() == "textcolor") {
+                       docstring const color = parse_verbatim_item();
+                       cell->push_back(MathAtom(new InsetMathColor(false, color)));
+                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE);
+               }
+
+               else if (t.cs() == "normalcolor") {
+                       cell->push_back(createInsetMath(t.cs()));
+                       parse(cell->back().nucleus()->cell(0), flags, mode);
+                       return;
+               }
+
+               else if (t.cs() == "substack") {
+                       cell->push_back(createInsetMath(t.cs()));
+                       parse2(cell->back(), FLAG_ITEM, mode, false);
+               }
+
+               else if (t.cs() == "xymatrix") {
+                       odocstringstream os;
+                       while (good() && nextToken().cat() != catBegin)
+                               os << getToken().asInput();
+                       cell->push_back(createInsetMath(t.cs() + os.str()));
+                       parse2(cell->back(), FLAG_ITEM, mode, false);
+               }
+
+               else if (t.cs() == "framebox" || t.cs() == "makebox") {
+                       cell->push_back(createInsetMath(t.cs()));
+                       parse(cell->back().nucleus()->cell(0), FLAG_OPTION, InsetMath::TEXT_MODE);
+                       parse(cell->back().nucleus()->cell(1), FLAG_OPTION, InsetMath::TEXT_MODE);
+                       parse(cell->back().nucleus()->cell(2), FLAG_ITEM, InsetMath::TEXT_MODE);
+               }
+
+               else if (t.cs() == "tag") {
+                       if (nextToken().character() == '*') {
+                               getToken();
+                               cell->push_back(createInsetMath(t.cs() + '*'));
+                       } else
+                               cell->push_back(createInsetMath(t.cs()));
+                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE);
+               }
+
+#if 0
+               else if (t.cs() == "infer") {
+                       MathArray ar;
+                       parse(ar, FLAG_OPTION, mode);
+                       cell->push_back(createInsetMath(t.cs()));
+                       parse2(cell->back(), FLAG_ITEM, mode, false);
+               }
+
+               // Disabled
+               else if (1 && t.cs() == "ar") {
+                       auto_ptr<InsetMathXYArrow> p(new InsetMathXYArrow);
+                       // try to read target
+                       parse(p->cell(0), FLAG_OTPTION, mode);
+                       // try to read label
+                       if (nextToken().cat() == catSuper || nextToken().cat() == catSub) {
+                               p->up_ = nextToken().cat() == catSuper;
+                               getToken();
+                               parse(p->cell(1), FLAG_ITEM, mode);
+                               //lyxerr << "read label: " << p->cell(1) << endl;
+                       }
+
+                       cell->push_back(MathAtom(p.release()));
+                       //lyxerr << "read cell: " << cell << endl;
+               }
+#endif
+
+               else if (t.cs().size()) {
+                       latexkeys const * l = in_word_set(t.cs());
+                       if (l) {
+                               if (l->inset == "big") {
+                                       skipSpaces();
+                                       docstring const delim = getToken().asInput();
+                                       if (InsetMathBig::isBigInsetDelim(delim))
+                                               cell->push_back(MathAtom(
+                                                       new InsetMathBig(t.cs(), delim)));
+                                       else {
+                                               cell->push_back(createInsetMath(t.cs()));
+                                               putback();
+                                       }
+                               }
+
+                               else if (l->inset == "font") {
+                                       cell->push_back(createInsetMath(t.cs()));
+                                       parse(cell->back().nucleus()->cell(0),
+                                               FLAG_ITEM, asMode(mode, l->extra));
+                               }
+
+                               else if (l->inset == "oldfont") {
+                                       cell->push_back(createInsetMath(t.cs()));
+                                       parse(cell->back().nucleus()->cell(0),
+                                               flags | FLAG_ALIGN, asMode(mode, l->extra));
+                                       if (prevToken().cat() != catAlign &&
+                                           prevToken().cs() != "\\")
+                                               return;
+                                       putback();
+                               }
+
+                               else if (l->inset == "style") {
+                                       cell->push_back(createInsetMath(t.cs()));
+                                       parse(cell->back().nucleus()->cell(0),
+                                               flags | FLAG_ALIGN, mode);
+                                       if (prevToken().cat() != catAlign &&
+                                           prevToken().cs() != "\\")
+                                               return;
+                                       putback();
+                               }
+
+                               else {
+                                       MathAtom at = createInsetMath(t.cs());
+                                       for (InsetMath::idx_type i = 0; i < at->nargs(); ++i)
+                                               parse(at.nucleus()->cell(i),
+                                                       FLAG_ITEM, asMode(mode, l->extra));
+                                       cell->push_back(at);
+                               }
+                       }
+
+                       else {
+                               MathAtom at = createInsetMath(t.cs());
+                               InsetMath::mode_type m = mode;
+                               //if (m == InsetMath::UNDECIDED_MODE)
+                               //lyxerr << "default creation: m1: " << m << endl;
+                               if (at->currentMode() != InsetMath::UNDECIDED_MODE)
+                                       m = at->currentMode();
+                               //lyxerr << "default creation: m2: " << m << endl;
+                               InsetMath::idx_type start = 0;
+                               // this fails on \bigg[...\bigg]
+                               //MathArray opt;
+                               //parse(opt, FLAG_OPTION, InsetMath::VERBATIM_MODE);
+                               //if (opt.size()) {
+                               //      start = 1;
+                               //      at.nucleus()->cell(0) = opt;
+                               //}
+                               for (InsetMath::idx_type i = start; i < at->nargs(); ++i) {
+                                       parse(at.nucleus()->cell(i), FLAG_ITEM, m);
+                                       skipSpaces();
+                               }
+                               cell->push_back(at);
+                       }
+               }
+
+
+               if (flags & FLAG_LEAVE) {
+                       flags &= ~FLAG_LEAVE;
+                       break;
+               }
+       }
+}
+
+
+
+} // anonymous namespace
+
+
+void mathed_parse_cell(MathArray & ar, docstring const & str)
+{
+       Parser(str).parse(ar, 0, InsetMath::MATH_MODE);
+}
+
+
+void mathed_parse_cell(MathArray & ar, istream & is)
+{
+       Parser(is).parse(ar, 0, InsetMath::MATH_MODE);
+}
+
+
+bool mathed_parse_normal(MathAtom & t, docstring const & str)
+{
+       return Parser(str).parse(t);
+}
+
+
+bool mathed_parse_normal(MathAtom & t, LyXLex & lex)
+{
+       return Parser(lex).parse(t);
+}
+
+
+void mathed_parse_normal(InsetMathGrid & grid, docstring const & str)
+{
+       Parser(str).parse1(grid, 0, InsetMath::MATH_MODE, false);
+}
+
+
+void initParser()
+{
+       fill(theCatcode, theCatcode + 128, catOther);
+       fill(theCatcode + 'a', theCatcode + 'z' + 1, catLetter);
+       fill(theCatcode + 'A', theCatcode + 'Z' + 1, catLetter);
+
+       theCatcode[int('\\')] = catEscape;
+       theCatcode[int('{')]  = catBegin;
+       theCatcode[int('}')]  = catEnd;
+       theCatcode[int('$')]  = catMath;
+       theCatcode[int('&')]  = catAlign;
+       theCatcode[int('\n')] = catNewline;
+       theCatcode[int('#')]  = catParameter;
+       theCatcode[int('^')]  = catSuper;
+       theCatcode[int('_')]  = catSub;
+       theCatcode[int(0x7f)] = catIgnore;
+       theCatcode[int(' ')]  = catSpace;
+       theCatcode[int('\t')] = catSpace;
+       theCatcode[int('\r')] = catNewline;
+       theCatcode[int('~')]  = catActive;
+       theCatcode[int('%')]  = catComment;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathStream.C b/src/mathed/MathStream.C
deleted file mode 100644 (file)
index 83c9545..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-/**
- * \file MathStream.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetMath.h"
-#include "MathData.h"
-#include "MathExtern.h"
-#include "MathStream.h"
-
-#include "support/lyxalgo.h"
-#include "support/textutils.h"
-
-
-namespace lyx {
-
-using std::strlen;
-
-
-
-
-//////////////////////////////////////////////////////////////////////
-
-
-NormalStream & operator<<(NormalStream & ns, MathAtom const & at)
-{
-       at->normalize(ns);
-       return ns;
-}
-
-
-NormalStream & operator<<(NormalStream & ns, MathArray const & ar)
-{
-       normalize(ar, ns);
-       return ns;
-}
-
-
-NormalStream & operator<<(NormalStream & ns, docstring const & s)
-{
-       ns.os() << s;
-       return ns;
-}
-
-
-NormalStream & operator<<(NormalStream & ns, const std::string & s)
-{
-       ns.os() << from_utf8(s);
-       return ns;
-}
-
-
-NormalStream & operator<<(NormalStream & ns, char const * s)
-{
-       ns.os() << s;
-       return ns;
-}
-
-
-NormalStream & operator<<(NormalStream & ns, char c)
-{
-       ns.os() << c;
-       return ns;
-}
-
-
-NormalStream & operator<<(NormalStream & ns, int i)
-{
-       ns.os() << i;
-       return ns;
-}
-
-
-
-/////////////////////////////////////////////////////////////////
-
-
-WriteStream & operator<<(WriteStream & ws, docstring const & s)
-{
-       if (ws.pendingSpace() && s.length() > 0) {
-               if (isAlphaASCII(s[0]))
-                       ws.os() << ' ';
-               ws.pendingSpace(false);
-       }
-       ws.os() << s;
-       int lf = 0;
-       docstring::const_iterator dit = s.begin();
-       docstring::const_iterator end = s.end();
-       for (; dit != end; ++dit)
-               if ((*dit) == '\n')
-                       ++lf;
-       ws.addlines(lf);
-       return ws;
-}
-
-
-WriteStream::WriteStream(odocstream & os, bool fragile, bool latex)
-       : os_(os), fragile_(fragile), firstitem_(false), latex_(latex),
-         pendingspace_(false), line_(0)
-{}
-
-
-WriteStream::WriteStream(odocstream & os)
-       : os_(os), fragile_(false), firstitem_(false), latex_(false),
-         pendingspace_(false), line_(0)
-{}
-
-
-WriteStream::~WriteStream()
-{
-       if (pendingspace_)
-               os_ << ' ';
-}
-
-
-void WriteStream::addlines(unsigned int n)
-{
-       line_ += n;
-}
-
-
-void WriteStream::pendingSpace(bool how)
-{
-       pendingspace_ = how;
-}
-
-
-WriteStream & operator<<(WriteStream & ws, MathAtom const & at)
-{
-       at->write(ws);
-       return ws;
-}
-
-
-WriteStream & operator<<(WriteStream & ws, MathArray const & ar)
-{
-       write(ar, ws);
-       return ws;
-}
-
-
-WriteStream & operator<<(WriteStream & ws, char const * s)
-{
-       if (ws.pendingSpace() && strlen(s) > 0) {
-               if (isAlphaASCII(s[0]))
-                       ws.os() << ' ';
-               ws.pendingSpace(false);
-       }
-       ws.os() << s;
-       ws.addlines(int(count(s, s + strlen(s), '\n')));
-       return ws;
-}
-
-
-WriteStream & operator<<(WriteStream & ws, char c)
-{
-       if (ws.pendingSpace()) {
-               if (isAlphaASCII(c))
-                       ws.os() << ' ';
-               ws.pendingSpace(false);
-       }
-       ws.os() << c;
-       if (c == '\n')
-               ws.addlines(1);
-       return ws;
-}
-
-
-WriteStream & operator<<(WriteStream & ws, int i)
-{
-       ws.os() << i;
-       return ws;
-}
-
-
-WriteStream & operator<<(WriteStream & ws, unsigned int i)
-{
-       ws.os() << i;
-       return ws;
-}
-
-
-//////////////////////////////////////////////////////////////////////
-
-
-MathStream::MathStream(odocstream & os)
-       : os_(os), tab_(0), line_(0), lastchar_(0)
-{}
-
-
-MathStream & operator<<(MathStream & ms, MathAtom const & at)
-{
-       at->mathmlize(ms);
-       return ms;
-}
-
-
-MathStream & operator<<(MathStream & ms, MathArray const & ar)
-{
-       mathmlize(ar, ms);
-       return ms;
-}
-
-
-MathStream & operator<<(MathStream & ms, char const * s)
-{
-       ms.os() << s;
-       return ms;
-}
-
-
-MathStream & operator<<(MathStream & ms, char c)
-{
-       ms.os() << c;
-       return ms;
-}
-
-
-MathStream & operator<<(MathStream & ms, MTag const & t)
-{
-       ++ms.tab();
-       ms.cr();
-       ms.os() << '<' << t.tag_ << '>';
-       return ms;
-}
-
-
-MathStream & operator<<(MathStream & ms, ETag const & t)
-{
-       ms.cr();
-       if (ms.tab() > 0)
-               --ms.tab();
-       ms.os() << "</" << t.tag_ << '>';
-       return ms;
-}
-
-
-void MathStream::cr()
-{
-       os() << '\n';
-       for (int i = 0; i < tab(); ++i)
-               os() << ' ';
-}
-
-
-MathStream & operator<<(MathStream & ms, docstring const & s)
-{
-       ms.os() << s;
-       return ms;
-}
-
-//////////////////////////////////////////////////////////////////////
-
-
-MapleStream & operator<<(MapleStream & ms, MathAtom const & at)
-{
-       at->maple(ms);
-       return ms;
-}
-
-
-MapleStream & operator<<(MapleStream & ms, MathArray const & ar)
-{
-       maple(ar, ms);
-       return ms;
-}
-
-
-MapleStream & operator<<(MapleStream & ms, char const * s)
-{
-       ms.os() << s;
-       return ms;
-}
-
-
-MapleStream & operator<<(MapleStream & ms, char c)
-{
-       ms.os() << c;
-       return ms;
-}
-
-
-MapleStream & operator<<(MapleStream & ms, int i)
-{
-       ms.os() << i;
-       return ms;
-}
-
-
-MapleStream & operator<<(MapleStream & ms, char_type c)
-{
-       ms.os().put(c);
-       return ms;
-}
-
-
-MapleStream & operator<<(MapleStream & ms, docstring const & s)
-{
-       ms.os() << s;
-       return ms;
-}
-
-
-//////////////////////////////////////////////////////////////////////
-
-
-MaximaStream & operator<<(MaximaStream & ms, MathAtom const & at)
-{
-       at->maxima(ms);
-       return ms;
-}
-
-
-MaximaStream & operator<<(MaximaStream & ms, MathArray const & ar)
-{
-       maxima(ar, ms);
-       return ms;
-}
-
-
-MaximaStream & operator<<(MaximaStream & ms, char const * s)
-{
-       ms.os() << s;
-       return ms;
-}
-
-
-MaximaStream & operator<<(MaximaStream & ms, char c)
-{
-       ms.os() << c;
-       return ms;
-}
-
-
-MaximaStream & operator<<(MaximaStream & ms, int i)
-{
-       ms.os() << i;
-       return ms;
-}
-
-
-MaximaStream & operator<<(MaximaStream & ms, docstring const & s)
-{
-       ms.os() << s;
-       return ms;
-}
-
-
-MaximaStream & operator<<(MaximaStream & ms, char_type c)
-{
-       ms.os().put(c);
-       return ms;
-}
-
-
-//////////////////////////////////////////////////////////////////////
-
-
-MathematicaStream & operator<<(MathematicaStream & ms, MathAtom const & at)
-{
-       at->mathematica(ms);
-       return ms;
-}
-
-
-MathematicaStream & operator<<(MathematicaStream & ms, MathArray const & ar)
-{
-       mathematica(ar, ms);
-       return ms;
-}
-
-
-MathematicaStream & operator<<(MathematicaStream & ms, char const * s)
-{
-       ms.os() << s;
-       return ms;
-}
-
-
-MathematicaStream & operator<<(MathematicaStream & ms, char c)
-{
-       ms.os() << c;
-       return ms;
-}
-
-
-MathematicaStream & operator<<(MathematicaStream & ms, int i)
-{
-       ms.os() << i;
-       return ms;
-}
-
-
-MathematicaStream & operator<<(MathematicaStream & ms, docstring const & s)
-{
-       ms.os() << s;
-       return ms;
-}
-
-
-MathematicaStream & operator<<(MathematicaStream & ms, char_type c)
-{
-       ms.os().put(c);
-       return ms;
-}
-
-
-//////////////////////////////////////////////////////////////////////
-
-
-OctaveStream & operator<<(OctaveStream & ns, MathAtom const & at)
-{
-       at->octave(ns);
-       return ns;
-}
-
-
-OctaveStream & operator<<(OctaveStream & ns, MathArray const & ar)
-{
-       octave(ar, ns);
-       return ns;
-}
-
-
-OctaveStream & operator<<(OctaveStream & ns, char const * s)
-{
-       ns.os() << s;
-       return ns;
-}
-
-
-OctaveStream & operator<<(OctaveStream & ns, char c)
-{
-       ns.os() << c;
-       return ns;
-}
-
-
-OctaveStream & operator<<(OctaveStream & ns, int i)
-{
-       ns.os() << i;
-       return ns;
-}
-
-
-OctaveStream & operator<<(OctaveStream & ns, docstring const & s)
-{
-       ns.os() << s;
-       return ns;
-}
-
-
-OctaveStream & operator<<(OctaveStream & ns, char_type c)
-{
-       ns.os().put(c);
-       return ns;
-}
-
-
-OctaveStream & operator<<(OctaveStream & os, std::string const & s)
-{
-       os.os() << from_utf8(s);
-       return os;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathStream.cpp b/src/mathed/MathStream.cpp
new file mode 100644 (file)
index 0000000..83c9545
--- /dev/null
@@ -0,0 +1,474 @@
+/**
+ * \file MathStream.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetMath.h"
+#include "MathData.h"
+#include "MathExtern.h"
+#include "MathStream.h"
+
+#include "support/lyxalgo.h"
+#include "support/textutils.h"
+
+
+namespace lyx {
+
+using std::strlen;
+
+
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+NormalStream & operator<<(NormalStream & ns, MathAtom const & at)
+{
+       at->normalize(ns);
+       return ns;
+}
+
+
+NormalStream & operator<<(NormalStream & ns, MathArray const & ar)
+{
+       normalize(ar, ns);
+       return ns;
+}
+
+
+NormalStream & operator<<(NormalStream & ns, docstring const & s)
+{
+       ns.os() << s;
+       return ns;
+}
+
+
+NormalStream & operator<<(NormalStream & ns, const std::string & s)
+{
+       ns.os() << from_utf8(s);
+       return ns;
+}
+
+
+NormalStream & operator<<(NormalStream & ns, char const * s)
+{
+       ns.os() << s;
+       return ns;
+}
+
+
+NormalStream & operator<<(NormalStream & ns, char c)
+{
+       ns.os() << c;
+       return ns;
+}
+
+
+NormalStream & operator<<(NormalStream & ns, int i)
+{
+       ns.os() << i;
+       return ns;
+}
+
+
+
+/////////////////////////////////////////////////////////////////
+
+
+WriteStream & operator<<(WriteStream & ws, docstring const & s)
+{
+       if (ws.pendingSpace() && s.length() > 0) {
+               if (isAlphaASCII(s[0]))
+                       ws.os() << ' ';
+               ws.pendingSpace(false);
+       }
+       ws.os() << s;
+       int lf = 0;
+       docstring::const_iterator dit = s.begin();
+       docstring::const_iterator end = s.end();
+       for (; dit != end; ++dit)
+               if ((*dit) == '\n')
+                       ++lf;
+       ws.addlines(lf);
+       return ws;
+}
+
+
+WriteStream::WriteStream(odocstream & os, bool fragile, bool latex)
+       : os_(os), fragile_(fragile), firstitem_(false), latex_(latex),
+         pendingspace_(false), line_(0)
+{}
+
+
+WriteStream::WriteStream(odocstream & os)
+       : os_(os), fragile_(false), firstitem_(false), latex_(false),
+         pendingspace_(false), line_(0)
+{}
+
+
+WriteStream::~WriteStream()
+{
+       if (pendingspace_)
+               os_ << ' ';
+}
+
+
+void WriteStream::addlines(unsigned int n)
+{
+       line_ += n;
+}
+
+
+void WriteStream::pendingSpace(bool how)
+{
+       pendingspace_ = how;
+}
+
+
+WriteStream & operator<<(WriteStream & ws, MathAtom const & at)
+{
+       at->write(ws);
+       return ws;
+}
+
+
+WriteStream & operator<<(WriteStream & ws, MathArray const & ar)
+{
+       write(ar, ws);
+       return ws;
+}
+
+
+WriteStream & operator<<(WriteStream & ws, char const * s)
+{
+       if (ws.pendingSpace() && strlen(s) > 0) {
+               if (isAlphaASCII(s[0]))
+                       ws.os() << ' ';
+               ws.pendingSpace(false);
+       }
+       ws.os() << s;
+       ws.addlines(int(count(s, s + strlen(s), '\n')));
+       return ws;
+}
+
+
+WriteStream & operator<<(WriteStream & ws, char c)
+{
+       if (ws.pendingSpace()) {
+               if (isAlphaASCII(c))
+                       ws.os() << ' ';
+               ws.pendingSpace(false);
+       }
+       ws.os() << c;
+       if (c == '\n')
+               ws.addlines(1);
+       return ws;
+}
+
+
+WriteStream & operator<<(WriteStream & ws, int i)
+{
+       ws.os() << i;
+       return ws;
+}
+
+
+WriteStream & operator<<(WriteStream & ws, unsigned int i)
+{
+       ws.os() << i;
+       return ws;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+MathStream::MathStream(odocstream & os)
+       : os_(os), tab_(0), line_(0), lastchar_(0)
+{}
+
+
+MathStream & operator<<(MathStream & ms, MathAtom const & at)
+{
+       at->mathmlize(ms);
+       return ms;
+}
+
+
+MathStream & operator<<(MathStream & ms, MathArray const & ar)
+{
+       mathmlize(ar, ms);
+       return ms;
+}
+
+
+MathStream & operator<<(MathStream & ms, char const * s)
+{
+       ms.os() << s;
+       return ms;
+}
+
+
+MathStream & operator<<(MathStream & ms, char c)
+{
+       ms.os() << c;
+       return ms;
+}
+
+
+MathStream & operator<<(MathStream & ms, MTag const & t)
+{
+       ++ms.tab();
+       ms.cr();
+       ms.os() << '<' << t.tag_ << '>';
+       return ms;
+}
+
+
+MathStream & operator<<(MathStream & ms, ETag const & t)
+{
+       ms.cr();
+       if (ms.tab() > 0)
+               --ms.tab();
+       ms.os() << "</" << t.tag_ << '>';
+       return ms;
+}
+
+
+void MathStream::cr()
+{
+       os() << '\n';
+       for (int i = 0; i < tab(); ++i)
+               os() << ' ';
+}
+
+
+MathStream & operator<<(MathStream & ms, docstring const & s)
+{
+       ms.os() << s;
+       return ms;
+}
+
+//////////////////////////////////////////////////////////////////////
+
+
+MapleStream & operator<<(MapleStream & ms, MathAtom const & at)
+{
+       at->maple(ms);
+       return ms;
+}
+
+
+MapleStream & operator<<(MapleStream & ms, MathArray const & ar)
+{
+       maple(ar, ms);
+       return ms;
+}
+
+
+MapleStream & operator<<(MapleStream & ms, char const * s)
+{
+       ms.os() << s;
+       return ms;
+}
+
+
+MapleStream & operator<<(MapleStream & ms, char c)
+{
+       ms.os() << c;
+       return ms;
+}
+
+
+MapleStream & operator<<(MapleStream & ms, int i)
+{
+       ms.os() << i;
+       return ms;
+}
+
+
+MapleStream & operator<<(MapleStream & ms, char_type c)
+{
+       ms.os().put(c);
+       return ms;
+}
+
+
+MapleStream & operator<<(MapleStream & ms, docstring const & s)
+{
+       ms.os() << s;
+       return ms;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+MaximaStream & operator<<(MaximaStream & ms, MathAtom const & at)
+{
+       at->maxima(ms);
+       return ms;
+}
+
+
+MaximaStream & operator<<(MaximaStream & ms, MathArray const & ar)
+{
+       maxima(ar, ms);
+       return ms;
+}
+
+
+MaximaStream & operator<<(MaximaStream & ms, char const * s)
+{
+       ms.os() << s;
+       return ms;
+}
+
+
+MaximaStream & operator<<(MaximaStream & ms, char c)
+{
+       ms.os() << c;
+       return ms;
+}
+
+
+MaximaStream & operator<<(MaximaStream & ms, int i)
+{
+       ms.os() << i;
+       return ms;
+}
+
+
+MaximaStream & operator<<(MaximaStream & ms, docstring const & s)
+{
+       ms.os() << s;
+       return ms;
+}
+
+
+MaximaStream & operator<<(MaximaStream & ms, char_type c)
+{
+       ms.os().put(c);
+       return ms;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+MathematicaStream & operator<<(MathematicaStream & ms, MathAtom const & at)
+{
+       at->mathematica(ms);
+       return ms;
+}
+
+
+MathematicaStream & operator<<(MathematicaStream & ms, MathArray const & ar)
+{
+       mathematica(ar, ms);
+       return ms;
+}
+
+
+MathematicaStream & operator<<(MathematicaStream & ms, char const * s)
+{
+       ms.os() << s;
+       return ms;
+}
+
+
+MathematicaStream & operator<<(MathematicaStream & ms, char c)
+{
+       ms.os() << c;
+       return ms;
+}
+
+
+MathematicaStream & operator<<(MathematicaStream & ms, int i)
+{
+       ms.os() << i;
+       return ms;
+}
+
+
+MathematicaStream & operator<<(MathematicaStream & ms, docstring const & s)
+{
+       ms.os() << s;
+       return ms;
+}
+
+
+MathematicaStream & operator<<(MathematicaStream & ms, char_type c)
+{
+       ms.os().put(c);
+       return ms;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+OctaveStream & operator<<(OctaveStream & ns, MathAtom const & at)
+{
+       at->octave(ns);
+       return ns;
+}
+
+
+OctaveStream & operator<<(OctaveStream & ns, MathArray const & ar)
+{
+       octave(ar, ns);
+       return ns;
+}
+
+
+OctaveStream & operator<<(OctaveStream & ns, char const * s)
+{
+       ns.os() << s;
+       return ns;
+}
+
+
+OctaveStream & operator<<(OctaveStream & ns, char c)
+{
+       ns.os() << c;
+       return ns;
+}
+
+
+OctaveStream & operator<<(OctaveStream & ns, int i)
+{
+       ns.os() << i;
+       return ns;
+}
+
+
+OctaveStream & operator<<(OctaveStream & ns, docstring const & s)
+{
+       ns.os() << s;
+       return ns;
+}
+
+
+OctaveStream & operator<<(OctaveStream & ns, char_type c)
+{
+       ns.os().put(c);
+       return ns;
+}
+
+
+OctaveStream & operator<<(OctaveStream & os, std::string const & s)
+{
+       os.os() << from_utf8(s);
+       return os;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathSupport.C b/src/mathed/MathSupport.C
deleted file mode 100644 (file)
index 8f3aacb..0000000
+++ /dev/null
@@ -1,714 +0,0 @@
-/**
- * \file MathSupport.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MathSupport.h"
-#include "MathData.h"
-#include "InsetMath.h"
-#include "MathStream.h"
-#include "MathParser.h"
-
-#include "debug.h"
-#include "LColor.h"
-
-#include "frontends/FontLoader.h"
-#include "frontends/FontMetrics.h"
-#include "frontends/Painter.h"
-
-#include <map>
-#include <sstream>
-
-
-namespace lyx {
-
-using frontend::Painter;
-
-using std::max;
-using std::endl;
-using std::vector;
-
-
-///
-class Matrix {
-public:
-       ///
-       Matrix(int, double, double);
-       ///
-       void transform(double &, double &);
-private:
-       ///
-       double m_[2][2];
-};
-
-
-Matrix::Matrix(int code, double x, double y)
-{
-       double const cs = (code & 1) ? 0 : (1 - code);
-       double const sn = (code & 1) ? (2 - code) : 0;
-       m_[0][0] =  cs * x;
-       m_[0][1] =  sn * x;
-       m_[1][0] = -sn * y;
-       m_[1][1] =  cs * y;
-}
-
-
-void Matrix::transform(double & x, double & y)
-{
-       double xx = m_[0][0] * x + m_[0][1] * y;
-       double yy = m_[1][0] * x + m_[1][1] * y;
-       x = xx;
-       y = yy;
-}
-
-
-
-namespace {
-
-/*
- * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
- * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
- */
-
-
-double const parenthHigh[] = {
-       2, 13,
-       0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
-       0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
-       0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
-       0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
-       0.9840, 0.9986,
-       0
-};
-
-
-double const parenth[] = {
-       2, 13,
-       0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
-       0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
-       0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
-       0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
-       0.9930, 0.9919,
-       0
-};
-
-
-double const brace[] = {
-       2, 21,
-       0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
-       0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
-       0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
-       0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
-       0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
-       0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
-       0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
-       0
-};
-
-
-double const arrow[] = {
-       4, 7,
-       0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
-       0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
-       0.9500, 0.7500,
-       3, 0.5000, 0.1500, 0.5000, 0.9500,
-       0
-};
-
-
-double const Arrow[] = {
-       4, 7,
-       0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
-       0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
-       0.9500, 0.7500,
-       3, 0.3500, 0.5000, 0.3500, 0.9500,
-       3, 0.6500, 0.5000, 0.6500, 0.9500,
-       0
-};
-
-
-double const udarrow[] = {
-       2, 3,
-       0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
-       2, 3,
-       0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
-       1, 0.5, 0.2,  0.5, 0.8,
-       0
-};
-
-
-double const Udarrow[] = {
-       2, 3,
-       0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
-       2, 3,
-       0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
-       1, 0.35, 0.2, 0.35, 0.8,
-       1, 0.65, 0.2, 0.65, 0.8,
-       0
-};
-
-
-double const brack[] = {
-       2, 4,
-       0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
-       0
-};
-
-
-double const corner[] = {
-       2, 3,
-       0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
-       0
-};
-
-
-double const angle[] = {
-       2, 3,
-       1, 0,  0.05, 0.5,  1, 1,
-       0
-};
-
-
-double const slash[] = {
-       1, 0.95, 0.05, 0.05, 0.95,
-       0
-};
-
-
-double const hline[] = {
-       1, 0.00, 0.5, 1.0, 0.5,
-       0
-};
-
-
-double const ddot[] = {
-       1, 0.2, 0.5,  0.3, 0.5,
-       1, 0.7, 0.5,  0.8, 0.5,
-       0
-};
-
-
-double const dddot[] = {
-       1, 0.1, 0.5,  0.2, 0.5,
-       1, 0.45, 0.5, 0.55, 0.5,
-       1, 0.8, 0.5,  0.9, 0.5,
-       0
-};
-
-
-double const hline3[] = {
-       1, 0.1,   0,  0.15,  0,
-       1, 0.475, 0,  0.525, 0,
-       1, 0.85,  0,  0.9,   0,
-       0
-};
-
-
-double const dline3[] = {
-       1, 0.1,   0.1,   0.15,  0.15,
-       1, 0.475, 0.475, 0.525, 0.525,
-       1, 0.85,  0.85,  0.9,   0.9,
-       0
-};
-
-
-double const hlinesmall[] = {
-       1, 0.4, 0.5, 0.6, 0.5,
-       0
-};
-
-
-double const ring[] = {
-       2, 5,
-       0.5, 0.8,  0.8, 0.5,  0.5, 0.2,  0.2, 0.5,  0.5, 0.8,
-       0
-};
-
-
-double const vert[] = {
-       1, 0.5, 0.05,  0.5, 0.95,
-       0
-};
-
-
-double const  Vert[] = {
-       1, 0.3, 0.05,  0.3, 0.95,
-       1, 0.7, 0.05,  0.7, 0.95,
-       0
-};
-
-
-double const tilde[] = {
-       2, 4,
-       0.00, 0.8,  0.25, 0.2,  0.75, 0.8,  1.00, 0.2,
-       0
-};
-
-
-struct deco_struct {
-       double const * data;
-       int angle;
-};
-
-struct named_deco_struct {
-       char const * name;
-       double const * data;
-       int angle;
-};
-
-named_deco_struct deco_table[] = {
-       // Decorations
-       {"widehat",             angle,    3 },
-       {"widetilde",           tilde,    0 },
-       {"underbar",            hline,    0 },
-       {"underline",           hline,    0 },
-       {"overline",            hline,    0 },
-       {"underbrace",          brace,    1 },
-       {"overbrace",           brace,    3 },
-       {"overleftarrow",       arrow,    1 },
-       {"overrightarrow",      arrow,    3 },
-       {"overleftrightarrow",  udarrow,  1 },
-       {"xleftarrow",          arrow,    1 },
-       {"xrightarrow",         arrow,    3 },
-       {"underleftarrow",      arrow,    1 },
-       {"underrightarrow",     arrow,    3 },
-       {"underleftrightarrow", udarrow,  1 },
-
-       // Delimiters
-       {"(",              parenth,    0 },
-       {")",              parenth,    2 },
-       {"{",              brace,      0 },
-       {"}",              brace,      2 },
-       {"lbrace",         brace,      0 },
-       {"rbrace",         brace,      2 },
-       {"[",              brack,      0 },
-       {"]",              brack,      2 },
-       {"|",              vert,       0 },
-       {"/",              slash,      0 },
-       {"slash",          slash,      0 },
-       {"vert",           vert,       0 },
-       {"Vert",           Vert,       0 },
-       {"'",              slash,      1 },
-       {"\\",             slash,      1 },
-       {"backslash",      slash,      1 },
-       {"langle",         angle,      0 },
-       {"lceil",          corner,     0 },
-       {"lfloor",         corner,     1 },
-       {"rangle",         angle,      2 },
-       {"rceil",          corner,     3 },
-       {"rfloor",         corner,     2 },
-       {"downarrow",      arrow,      2 },
-       {"Downarrow",      Arrow,      2 },
-       {"uparrow",        arrow,      0 },
-       {"Uparrow",        Arrow,      0 },
-       {"updownarrow",    udarrow,    0 },
-       {"Updownarrow",    Udarrow,    0 },
-
-       // Accents
-       {"ddot",           ddot,       0 },
-       {"dddot",          dddot,      0 },
-       {"hat",            angle,      3 },
-       {"grave",          slash,      1 },
-       {"acute",          slash,      0 },
-       {"tilde",          tilde,      0 },
-       {"bar",            hline,      0 },
-       {"dot",            hlinesmall, 0 },
-       {"check",          angle,      1 },
-       {"breve",          parenth,    1 },
-       {"vec",            arrow,      3 },
-       {"mathring",       ring,       0 },
-
-       // Dots
-       {"dots",           hline3,     0 },
-       {"ldots",          hline3,     0 },
-       {"cdots",          hline3,     0 },
-       {"vdots",          hline3,     1 },
-       {"ddots",          dline3,     0 },
-       {"dotsb",          hline3,     0 },
-       {"dotsc",          hline3,     0 },
-       {"dotsi",          hline3,     0 },
-       {"dotsm",          hline3,     0 },
-       {"dotso",          hline3,     0 }
-};
-
-
-std::map<docstring, deco_struct> deco_list;
-
-// sort the table on startup
-class init_deco_table {
-public:
-       init_deco_table() {
-               unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
-               for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
-                       deco_struct d;
-                       d.data  = p->data;
-                       d.angle = p->angle;
-                       deco_list[from_ascii(p->name)] = d;
-               }
-       }
-};
-
-static init_deco_table dummy;
-
-
-deco_struct const * search_deco(docstring const & name)
-{
-       std::map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
-       return p == deco_list.end() ? 0 : &(p->second);
-}
-
-
-} // namespace anon
-
-
-int mathed_char_width(LyXFont const & font, char_type c)
-{
-       return theFontMetrics(font).width(c);
-}
-
-
-int mathed_char_kerning(LyXFont const & font, char_type c)
-{
-       frontend::FontMetrics const & fm = theFontMetrics(font);
-       return fm.rbearing(c) - fm.width(c);
-}
-
-
-void mathed_string_dim(LyXFont const & font,
-                      docstring const & s,
-                      Dimension & dim)
-{
-       frontend::FontMetrics const & fm = theFontMetrics(font);
-       dim.asc = 0;
-       dim.des = 0;
-       for (docstring::const_iterator it = s.begin();
-            it != s.end();
-            ++it) {
-               dim.asc = max(dim.asc, fm.ascent(*it));
-               dim.des = max(dim.des, fm.descent(*it));
-       }
-       dim.wid = fm.width(s);
-}
-
-
-int mathed_string_width(LyXFont const & font, docstring const & s)
-{
-       return theFontMetrics(font).width(s);
-}
-
-
-void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
-       docstring const & name)
-{
-       if (name == ".") {
-               pi.pain.line(x + w/2, y, x + w/2, y + h,
-                         LColor::cursor, Painter::line_onoffdash);
-               return;
-       }
-
-       deco_struct const * mds = search_deco(name);
-       if (!mds) {
-               lyxerr << "Deco was not found. Programming error?" << endl;
-               lyxerr << "name: '" << to_utf8(name) << "'" << endl;
-               return;
-       }
-
-       int const n = (w < h) ? w : h;
-       int const r = mds->angle;
-       double const * d = mds->data;
-
-       if (h > 70 && (name == "(" || name == ")"))
-               d = parenthHigh;
-
-       Matrix mt(r, w, h);
-       Matrix sqmt(r, n, n);
-
-       if (r > 0 && r < 3)
-               y += h;
-
-       if (r >= 2)
-               x += w;
-
-       for (int i = 0; d[i]; ) {
-               int code = int(d[i++]);
-               if (code & 1) {  // code == 1 || code == 3
-                       double xx = d[i++];
-                       double yy = d[i++];
-                       double x2 = d[i++];
-                       double y2 = d[i++];
-                       if (code == 3)
-                               sqmt.transform(xx, yy);
-                       else
-                               mt.transform(xx, yy);
-                       mt.transform(x2, y2);
-                       pi.pain.line(
-                               int(x + xx + 0.5), int(y + yy + 0.5),
-                               int(x + x2 + 0.5), int(y + y2 + 0.5),
-                               LColor::math);
-               } else {
-                       int xp[32];
-                       int yp[32];
-                       int const n = int(d[i++]);
-                       for (int j = 0; j < n; ++j) {
-                               double xx = d[i++];
-                               double yy = d[i++];
-//          lyxerr << ' ' << xx << ' ' << yy << ' ';
-                               if (code == 4)
-                                       sqmt.transform(xx, yy);
-                               else
-                                       mt.transform(xx, yy);
-                               xp[j] = int(x + xx + 0.5);
-                               yp[j] = int(y + yy + 0.5);
-                               //  lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
-                       }
-                       pi.pain.lines(xp, yp, n, LColor::math);
-               }
-       }
-}
-
-
-void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
-{
-       LyXFont f = pi.base.font;
-       f.setColor(LColor::latex);
-       pi.pain.text(x, y, str, f);
-}
-
-
-void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
-{
-       LyXFont f = pi.base.font;
-       f.setColor(LColor::foreground);
-       pi.pain.text(x, y, str, f);
-}
-
-
-void math_font_max_dim(LyXFont const & font, int & asc, int & des)
-{
-       frontend::FontMetrics const & fm = theFontMetrics(font);
-       asc = fm.maxAscent();
-       des = fm.maxDescent();
-}
-
-
-struct fontinfo {
-       std::string cmd_;
-       LyXFont::FONT_FAMILY family_;
-       LyXFont::FONT_SERIES series_;
-       LyXFont::FONT_SHAPE  shape_;
-       LColor::color        color_;
-};
-
-
-LyXFont::FONT_FAMILY const inh_family = LyXFont::INHERIT_FAMILY;
-LyXFont::FONT_SERIES const inh_series = LyXFont::INHERIT_SERIES;
-LyXFont::FONT_SHAPE  const inh_shape  = LyXFont::INHERIT_SHAPE;
-
-
-// mathnormal should be the first, otherwise the fallback further down
-// does not work
-fontinfo fontinfos[] = {
-       // math fonts
-       {"mathnormal",    LyXFont::ROMAN_FAMILY, LyXFont::MEDIUM_SERIES,
-                         LyXFont::ITALIC_SHAPE, LColor::math},
-       {"mathbf",        inh_family, LyXFont::BOLD_SERIES,
-                         inh_shape, LColor::math},
-       {"mathcal",       LyXFont::CMSY_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"mathfrak",      LyXFont::EUFRAK_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"mathrm",        LyXFont::ROMAN_FAMILY, inh_series,
-                         LyXFont::UP_SHAPE, LColor::math},
-       {"mathsf",        LyXFont::SANS_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"mathbb",        LyXFont::MSB_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"mathtt",        LyXFont::TYPEWRITER_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"mathit",        inh_family, inh_series,
-                         LyXFont::ITALIC_SHAPE, LColor::math},
-       {"cmex",          LyXFont::CMEX_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"cmm",           LyXFont::CMM_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"cmr",           LyXFont::CMR_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"cmsy",          LyXFont::CMSY_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"eufrak",        LyXFont::EUFRAK_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"msa",           LyXFont::MSA_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"msb",           LyXFont::MSB_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"wasy",          LyXFont::WASY_FAMILY, inh_series,
-                         inh_shape, LColor::none},
-       {"esint",         LyXFont::ESINT_FAMILY, inh_series,
-                         inh_shape, LColor::none},
-
-       // Text fonts
-       {"text",          inh_family, inh_series,
-                         inh_shape, LColor::foreground},
-       {"textbf",        inh_family, LyXFont::BOLD_SERIES,
-                         inh_shape, LColor::foreground},
-       {"textit",        inh_family, inh_series,
-                         LyXFont::ITALIC_SHAPE, LColor::foreground},
-       {"textmd",        inh_family, LyXFont::MEDIUM_SERIES,
-                         inh_shape, LColor::foreground},
-       {"textnormal",    inh_family, inh_series,
-                         LyXFont::UP_SHAPE, LColor::foreground},
-       {"textrm",        LyXFont::ROMAN_FAMILY,
-                         inh_series, LyXFont::UP_SHAPE,LColor::foreground},
-       {"textsc",        inh_family, inh_series,
-                         LyXFont::SMALLCAPS_SHAPE, LColor::foreground},
-       {"textsf",        LyXFont::SANS_FAMILY, inh_series,
-                         inh_shape, LColor::foreground},
-       {"textsl",        inh_family, inh_series,
-                         LyXFont::SLANTED_SHAPE, LColor::foreground},
-       {"texttt",        LyXFont::TYPEWRITER_FAMILY, inh_series,
-                         inh_shape, LColor::foreground},
-       {"textup",        inh_family, inh_series,
-                         LyXFont::UP_SHAPE, LColor::foreground},
-
-       // TIPA support
-       {"textipa",       inh_family, inh_series,
-                         inh_shape, LColor::foreground},
-
-       // LyX internal usage
-       {"lyxtex",        inh_family, inh_series,
-                         LyXFont::UP_SHAPE, LColor::latex},
-       {"lyxsymbol",     LyXFont::SYMBOL_FAMILY, inh_series,
-                         inh_shape, LColor::math},
-       {"lyxboldsymbol", LyXFont::SYMBOL_FAMILY, LyXFont::BOLD_SERIES,
-                         inh_shape, LColor::math},
-       {"lyxblacktext",  LyXFont::ROMAN_FAMILY, LyXFont::MEDIUM_SERIES,
-                         LyXFont::UP_SHAPE, LColor::foreground},
-       {"lyxnochange",   inh_family, inh_series,
-                         inh_shape, LColor::foreground},
-       {"lyxfakebb",     LyXFont::TYPEWRITER_FAMILY, LyXFont::BOLD_SERIES,
-                         LyXFont::UP_SHAPE, LColor::math},
-       {"lyxfakecal",    LyXFont::SANS_FAMILY, LyXFont::MEDIUM_SERIES,
-                         LyXFont::ITALIC_SHAPE, LColor::math},
-       {"lyxfakefrak",   LyXFont::ROMAN_FAMILY, LyXFont::BOLD_SERIES,
-                         LyXFont::ITALIC_SHAPE, LColor::math}
-};
-
-
-fontinfo * lookupFont(docstring const & name0)
-{
-       //lyxerr << "searching font '" << name << "'" << endl;
-       int const n = sizeof(fontinfos) / sizeof(fontinfo);
-       std::string name = to_utf8(name0);
-       for (int i = 0; i < n; ++i)
-               if (fontinfos[i].cmd_ == name) {
-                       //lyxerr << "found '" << i << "'" << endl;
-                       return fontinfos + i;
-               }
-       return 0;
-}
-
-
-fontinfo * searchFont(docstring const & name)
-{
-       fontinfo * f = lookupFont(name);
-       return f ? f : fontinfos;
-       // this should be mathnormal
-       //return searchFont("mathnormal");
-}
-
-
-bool isFontName(docstring const & name)
-{
-       return lookupFont(name);
-}
-
-
-LyXFont getFont(docstring const & name)
-{
-       LyXFont font;
-       augmentFont(font, name);
-       return font;
-}
-
-
-void fakeFont(docstring const & orig, docstring const & fake)
-{
-       fontinfo * forig = searchFont(orig);
-       fontinfo * ffake = searchFont(fake);
-       if (forig && ffake) {
-               forig->family_ = ffake->family_;
-               forig->series_ = ffake->series_;
-               forig->shape_  = ffake->shape_;
-               forig->color_  = ffake->color_;
-       } else {
-               lyxerr << "Can't fake font '" << to_utf8(orig) << "' with '"
-                      << to_utf8(fake) << "'" << endl;
-       }
-}
-
-
-void augmentFont(LyXFont & font, docstring const & name)
-{
-       static bool initialized = false;
-       if (!initialized) {
-               initialized = true;
-               // fake fonts if necessary
-               if (!theFontLoader().available(getFont(from_ascii("mathfrak"))))
-                       fakeFont(from_ascii("mathfrak"), from_ascii("lyxfakefrak"));
-               if (!theFontLoader().available(getFont(from_ascii("mathcal"))))
-                       fakeFont(from_ascii("mathcal"), from_ascii("lyxfakecal"));
-       }
-       fontinfo * info = searchFont(name);
-       if (info->family_ != inh_family)
-               font.setFamily(info->family_);
-       if (info->series_ != inh_series)
-               font.setSeries(info->series_);
-       if (info->shape_ != inh_shape)
-               font.setShape(info->shape_);
-       if (info->color_ != LColor::none)
-               font.setColor(info->color_);
-}
-
-
-docstring asString(MathArray const & ar)
-{
-       odocstringstream os;
-       WriteStream ws(os);
-       ws << ar;
-       return os.str();
-}
-
-
-void asArray(docstring const & str, MathArray & ar)
-{
-       mathed_parse_cell(ar, str);
-}
-
-
-docstring asString(InsetMath const & inset)
-{
-       odocstringstream os;
-       WriteStream ws(os);
-       inset.write(ws);
-       return os.str();
-}
-
-
-docstring asString(MathAtom const & at)
-{
-       odocstringstream os;
-       WriteStream ws(os);
-       at->write(ws);
-       return os.str();
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathSupport.cpp b/src/mathed/MathSupport.cpp
new file mode 100644 (file)
index 0000000..8f3aacb
--- /dev/null
@@ -0,0 +1,714 @@
+/**
+ * \file MathSupport.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "MathSupport.h"
+#include "MathData.h"
+#include "InsetMath.h"
+#include "MathStream.h"
+#include "MathParser.h"
+
+#include "debug.h"
+#include "LColor.h"
+
+#include "frontends/FontLoader.h"
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
+#include <map>
+#include <sstream>
+
+
+namespace lyx {
+
+using frontend::Painter;
+
+using std::max;
+using std::endl;
+using std::vector;
+
+
+///
+class Matrix {
+public:
+       ///
+       Matrix(int, double, double);
+       ///
+       void transform(double &, double &);
+private:
+       ///
+       double m_[2][2];
+};
+
+
+Matrix::Matrix(int code, double x, double y)
+{
+       double const cs = (code & 1) ? 0 : (1 - code);
+       double const sn = (code & 1) ? (2 - code) : 0;
+       m_[0][0] =  cs * x;
+       m_[0][1] =  sn * x;
+       m_[1][0] = -sn * y;
+       m_[1][1] =  cs * y;
+}
+
+
+void Matrix::transform(double & x, double & y)
+{
+       double xx = m_[0][0] * x + m_[0][1] * y;
+       double yy = m_[1][0] * x + m_[1][1] * y;
+       x = xx;
+       y = yy;
+}
+
+
+
+namespace {
+
+/*
+ * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
+ * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
+ */
+
+
+double const parenthHigh[] = {
+       2, 13,
+       0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
+       0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
+       0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
+       0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
+       0.9840, 0.9986,
+       0
+};
+
+
+double const parenth[] = {
+       2, 13,
+       0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
+       0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
+       0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
+       0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
+       0.9930, 0.9919,
+       0
+};
+
+
+double const brace[] = {
+       2, 21,
+       0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
+       0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
+       0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
+       0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
+       0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
+       0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
+       0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
+       0
+};
+
+
+double const arrow[] = {
+       4, 7,
+       0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
+       0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
+       0.9500, 0.7500,
+       3, 0.5000, 0.1500, 0.5000, 0.9500,
+       0
+};
+
+
+double const Arrow[] = {
+       4, 7,
+       0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
+       0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
+       0.9500, 0.7500,
+       3, 0.3500, 0.5000, 0.3500, 0.9500,
+       3, 0.6500, 0.5000, 0.6500, 0.9500,
+       0
+};
+
+
+double const udarrow[] = {
+       2, 3,
+       0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
+       2, 3,
+       0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
+       1, 0.5, 0.2,  0.5, 0.8,
+       0
+};
+
+
+double const Udarrow[] = {
+       2, 3,
+       0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
+       2, 3,
+       0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
+       1, 0.35, 0.2, 0.35, 0.8,
+       1, 0.65, 0.2, 0.65, 0.8,
+       0
+};
+
+
+double const brack[] = {
+       2, 4,
+       0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
+       0
+};
+
+
+double const corner[] = {
+       2, 3,
+       0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
+       0
+};
+
+
+double const angle[] = {
+       2, 3,
+       1, 0,  0.05, 0.5,  1, 1,
+       0
+};
+
+
+double const slash[] = {
+       1, 0.95, 0.05, 0.05, 0.95,
+       0
+};
+
+
+double const hline[] = {
+       1, 0.00, 0.5, 1.0, 0.5,
+       0
+};
+
+
+double const ddot[] = {
+       1, 0.2, 0.5,  0.3, 0.5,
+       1, 0.7, 0.5,  0.8, 0.5,
+       0
+};
+
+
+double const dddot[] = {
+       1, 0.1, 0.5,  0.2, 0.5,
+       1, 0.45, 0.5, 0.55, 0.5,
+       1, 0.8, 0.5,  0.9, 0.5,
+       0
+};
+
+
+double const hline3[] = {
+       1, 0.1,   0,  0.15,  0,
+       1, 0.475, 0,  0.525, 0,
+       1, 0.85,  0,  0.9,   0,
+       0
+};
+
+
+double const dline3[] = {
+       1, 0.1,   0.1,   0.15,  0.15,
+       1, 0.475, 0.475, 0.525, 0.525,
+       1, 0.85,  0.85,  0.9,   0.9,
+       0
+};
+
+
+double const hlinesmall[] = {
+       1, 0.4, 0.5, 0.6, 0.5,
+       0
+};
+
+
+double const ring[] = {
+       2, 5,
+       0.5, 0.8,  0.8, 0.5,  0.5, 0.2,  0.2, 0.5,  0.5, 0.8,
+       0
+};
+
+
+double const vert[] = {
+       1, 0.5, 0.05,  0.5, 0.95,
+       0
+};
+
+
+double const  Vert[] = {
+       1, 0.3, 0.05,  0.3, 0.95,
+       1, 0.7, 0.05,  0.7, 0.95,
+       0
+};
+
+
+double const tilde[] = {
+       2, 4,
+       0.00, 0.8,  0.25, 0.2,  0.75, 0.8,  1.00, 0.2,
+       0
+};
+
+
+struct deco_struct {
+       double const * data;
+       int angle;
+};
+
+struct named_deco_struct {
+       char const * name;
+       double const * data;
+       int angle;
+};
+
+named_deco_struct deco_table[] = {
+       // Decorations
+       {"widehat",             angle,    3 },
+       {"widetilde",           tilde,    0 },
+       {"underbar",            hline,    0 },
+       {"underline",           hline,    0 },
+       {"overline",            hline,    0 },
+       {"underbrace",          brace,    1 },
+       {"overbrace",           brace,    3 },
+       {"overleftarrow",       arrow,    1 },
+       {"overrightarrow",      arrow,    3 },
+       {"overleftrightarrow",  udarrow,  1 },
+       {"xleftarrow",          arrow,    1 },
+       {"xrightarrow",         arrow,    3 },
+       {"underleftarrow",      arrow,    1 },
+       {"underrightarrow",     arrow,    3 },
+       {"underleftrightarrow", udarrow,  1 },
+
+       // Delimiters
+       {"(",              parenth,    0 },
+       {")",              parenth,    2 },
+       {"{",              brace,      0 },
+       {"}",              brace,      2 },
+       {"lbrace",         brace,      0 },
+       {"rbrace",         brace,      2 },
+       {"[",              brack,      0 },
+       {"]",              brack,      2 },
+       {"|",              vert,       0 },
+       {"/",              slash,      0 },
+       {"slash",          slash,      0 },
+       {"vert",           vert,       0 },
+       {"Vert",           Vert,       0 },
+       {"'",              slash,      1 },
+       {"\\",             slash,      1 },
+       {"backslash",      slash,      1 },
+       {"langle",         angle,      0 },
+       {"lceil",          corner,     0 },
+       {"lfloor",         corner,     1 },
+       {"rangle",         angle,      2 },
+       {"rceil",          corner,     3 },
+       {"rfloor",         corner,     2 },
+       {"downarrow",      arrow,      2 },
+       {"Downarrow",      Arrow,      2 },
+       {"uparrow",        arrow,      0 },
+       {"Uparrow",        Arrow,      0 },
+       {"updownarrow",    udarrow,    0 },
+       {"Updownarrow",    Udarrow,    0 },
+
+       // Accents
+       {"ddot",           ddot,       0 },
+       {"dddot",          dddot,      0 },
+       {"hat",            angle,      3 },
+       {"grave",          slash,      1 },
+       {"acute",          slash,      0 },
+       {"tilde",          tilde,      0 },
+       {"bar",            hline,      0 },
+       {"dot",            hlinesmall, 0 },
+       {"check",          angle,      1 },
+       {"breve",          parenth,    1 },
+       {"vec",            arrow,      3 },
+       {"mathring",       ring,       0 },
+
+       // Dots
+       {"dots",           hline3,     0 },
+       {"ldots",          hline3,     0 },
+       {"cdots",          hline3,     0 },
+       {"vdots",          hline3,     1 },
+       {"ddots",          dline3,     0 },
+       {"dotsb",          hline3,     0 },
+       {"dotsc",          hline3,     0 },
+       {"dotsi",          hline3,     0 },
+       {"dotsm",          hline3,     0 },
+       {"dotso",          hline3,     0 }
+};
+
+
+std::map<docstring, deco_struct> deco_list;
+
+// sort the table on startup
+class init_deco_table {
+public:
+       init_deco_table() {
+               unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
+               for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
+                       deco_struct d;
+                       d.data  = p->data;
+                       d.angle = p->angle;
+                       deco_list[from_ascii(p->name)] = d;
+               }
+       }
+};
+
+static init_deco_table dummy;
+
+
+deco_struct const * search_deco(docstring const & name)
+{
+       std::map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
+       return p == deco_list.end() ? 0 : &(p->second);
+}
+
+
+} // namespace anon
+
+
+int mathed_char_width(LyXFont const & font, char_type c)
+{
+       return theFontMetrics(font).width(c);
+}
+
+
+int mathed_char_kerning(LyXFont const & font, char_type c)
+{
+       frontend::FontMetrics const & fm = theFontMetrics(font);
+       return fm.rbearing(c) - fm.width(c);
+}
+
+
+void mathed_string_dim(LyXFont const & font,
+                      docstring const & s,
+                      Dimension & dim)
+{
+       frontend::FontMetrics const & fm = theFontMetrics(font);
+       dim.asc = 0;
+       dim.des = 0;
+       for (docstring::const_iterator it = s.begin();
+            it != s.end();
+            ++it) {
+               dim.asc = max(dim.asc, fm.ascent(*it));
+               dim.des = max(dim.des, fm.descent(*it));
+       }
+       dim.wid = fm.width(s);
+}
+
+
+int mathed_string_width(LyXFont const & font, docstring const & s)
+{
+       return theFontMetrics(font).width(s);
+}
+
+
+void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
+       docstring const & name)
+{
+       if (name == ".") {
+               pi.pain.line(x + w/2, y, x + w/2, y + h,
+                         LColor::cursor, Painter::line_onoffdash);
+               return;
+       }
+
+       deco_struct const * mds = search_deco(name);
+       if (!mds) {
+               lyxerr << "Deco was not found. Programming error?" << endl;
+               lyxerr << "name: '" << to_utf8(name) << "'" << endl;
+               return;
+       }
+
+       int const n = (w < h) ? w : h;
+       int const r = mds->angle;
+       double const * d = mds->data;
+
+       if (h > 70 && (name == "(" || name == ")"))
+               d = parenthHigh;
+
+       Matrix mt(r, w, h);
+       Matrix sqmt(r, n, n);
+
+       if (r > 0 && r < 3)
+               y += h;
+
+       if (r >= 2)
+               x += w;
+
+       for (int i = 0; d[i]; ) {
+               int code = int(d[i++]);
+               if (code & 1) {  // code == 1 || code == 3
+                       double xx = d[i++];
+                       double yy = d[i++];
+                       double x2 = d[i++];
+                       double y2 = d[i++];
+                       if (code == 3)
+                               sqmt.transform(xx, yy);
+                       else
+                               mt.transform(xx, yy);
+                       mt.transform(x2, y2);
+                       pi.pain.line(
+                               int(x + xx + 0.5), int(y + yy + 0.5),
+                               int(x + x2 + 0.5), int(y + y2 + 0.5),
+                               LColor::math);
+               } else {
+                       int xp[32];
+                       int yp[32];
+                       int const n = int(d[i++]);
+                       for (int j = 0; j < n; ++j) {
+                               double xx = d[i++];
+                               double yy = d[i++];
+//          lyxerr << ' ' << xx << ' ' << yy << ' ';
+                               if (code == 4)
+                                       sqmt.transform(xx, yy);
+                               else
+                                       mt.transform(xx, yy);
+                               xp[j] = int(x + xx + 0.5);
+                               yp[j] = int(y + yy + 0.5);
+                               //  lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
+                       }
+                       pi.pain.lines(xp, yp, n, LColor::math);
+               }
+       }
+}
+
+
+void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
+{
+       LyXFont f = pi.base.font;
+       f.setColor(LColor::latex);
+       pi.pain.text(x, y, str, f);
+}
+
+
+void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
+{
+       LyXFont f = pi.base.font;
+       f.setColor(LColor::foreground);
+       pi.pain.text(x, y, str, f);
+}
+
+
+void math_font_max_dim(LyXFont const & font, int & asc, int & des)
+{
+       frontend::FontMetrics const & fm = theFontMetrics(font);
+       asc = fm.maxAscent();
+       des = fm.maxDescent();
+}
+
+
+struct fontinfo {
+       std::string cmd_;
+       LyXFont::FONT_FAMILY family_;
+       LyXFont::FONT_SERIES series_;
+       LyXFont::FONT_SHAPE  shape_;
+       LColor::color        color_;
+};
+
+
+LyXFont::FONT_FAMILY const inh_family = LyXFont::INHERIT_FAMILY;
+LyXFont::FONT_SERIES const inh_series = LyXFont::INHERIT_SERIES;
+LyXFont::FONT_SHAPE  const inh_shape  = LyXFont::INHERIT_SHAPE;
+
+
+// mathnormal should be the first, otherwise the fallback further down
+// does not work
+fontinfo fontinfos[] = {
+       // math fonts
+       {"mathnormal",    LyXFont::ROMAN_FAMILY, LyXFont::MEDIUM_SERIES,
+                         LyXFont::ITALIC_SHAPE, LColor::math},
+       {"mathbf",        inh_family, LyXFont::BOLD_SERIES,
+                         inh_shape, LColor::math},
+       {"mathcal",       LyXFont::CMSY_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"mathfrak",      LyXFont::EUFRAK_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"mathrm",        LyXFont::ROMAN_FAMILY, inh_series,
+                         LyXFont::UP_SHAPE, LColor::math},
+       {"mathsf",        LyXFont::SANS_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"mathbb",        LyXFont::MSB_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"mathtt",        LyXFont::TYPEWRITER_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"mathit",        inh_family, inh_series,
+                         LyXFont::ITALIC_SHAPE, LColor::math},
+       {"cmex",          LyXFont::CMEX_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"cmm",           LyXFont::CMM_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"cmr",           LyXFont::CMR_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"cmsy",          LyXFont::CMSY_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"eufrak",        LyXFont::EUFRAK_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"msa",           LyXFont::MSA_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"msb",           LyXFont::MSB_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"wasy",          LyXFont::WASY_FAMILY, inh_series,
+                         inh_shape, LColor::none},
+       {"esint",         LyXFont::ESINT_FAMILY, inh_series,
+                         inh_shape, LColor::none},
+
+       // Text fonts
+       {"text",          inh_family, inh_series,
+                         inh_shape, LColor::foreground},
+       {"textbf",        inh_family, LyXFont::BOLD_SERIES,
+                         inh_shape, LColor::foreground},
+       {"textit",        inh_family, inh_series,
+                         LyXFont::ITALIC_SHAPE, LColor::foreground},
+       {"textmd",        inh_family, LyXFont::MEDIUM_SERIES,
+                         inh_shape, LColor::foreground},
+       {"textnormal",    inh_family, inh_series,
+                         LyXFont::UP_SHAPE, LColor::foreground},
+       {"textrm",        LyXFont::ROMAN_FAMILY,
+                         inh_series, LyXFont::UP_SHAPE,LColor::foreground},
+       {"textsc",        inh_family, inh_series,
+                         LyXFont::SMALLCAPS_SHAPE, LColor::foreground},
+       {"textsf",        LyXFont::SANS_FAMILY, inh_series,
+                         inh_shape, LColor::foreground},
+       {"textsl",        inh_family, inh_series,
+                         LyXFont::SLANTED_SHAPE, LColor::foreground},
+       {"texttt",        LyXFont::TYPEWRITER_FAMILY, inh_series,
+                         inh_shape, LColor::foreground},
+       {"textup",        inh_family, inh_series,
+                         LyXFont::UP_SHAPE, LColor::foreground},
+
+       // TIPA support
+       {"textipa",       inh_family, inh_series,
+                         inh_shape, LColor::foreground},
+
+       // LyX internal usage
+       {"lyxtex",        inh_family, inh_series,
+                         LyXFont::UP_SHAPE, LColor::latex},
+       {"lyxsymbol",     LyXFont::SYMBOL_FAMILY, inh_series,
+                         inh_shape, LColor::math},
+       {"lyxboldsymbol", LyXFont::SYMBOL_FAMILY, LyXFont::BOLD_SERIES,
+                         inh_shape, LColor::math},
+       {"lyxblacktext",  LyXFont::ROMAN_FAMILY, LyXFont::MEDIUM_SERIES,
+                         LyXFont::UP_SHAPE, LColor::foreground},
+       {"lyxnochange",   inh_family, inh_series,
+                         inh_shape, LColor::foreground},
+       {"lyxfakebb",     LyXFont::TYPEWRITER_FAMILY, LyXFont::BOLD_SERIES,
+                         LyXFont::UP_SHAPE, LColor::math},
+       {"lyxfakecal",    LyXFont::SANS_FAMILY, LyXFont::MEDIUM_SERIES,
+                         LyXFont::ITALIC_SHAPE, LColor::math},
+       {"lyxfakefrak",   LyXFont::ROMAN_FAMILY, LyXFont::BOLD_SERIES,
+                         LyXFont::ITALIC_SHAPE, LColor::math}
+};
+
+
+fontinfo * lookupFont(docstring const & name0)
+{
+       //lyxerr << "searching font '" << name << "'" << endl;
+       int const n = sizeof(fontinfos) / sizeof(fontinfo);
+       std::string name = to_utf8(name0);
+       for (int i = 0; i < n; ++i)
+               if (fontinfos[i].cmd_ == name) {
+                       //lyxerr << "found '" << i << "'" << endl;
+                       return fontinfos + i;
+               }
+       return 0;
+}
+
+
+fontinfo * searchFont(docstring const & name)
+{
+       fontinfo * f = lookupFont(name);
+       return f ? f : fontinfos;
+       // this should be mathnormal
+       //return searchFont("mathnormal");
+}
+
+
+bool isFontName(docstring const & name)
+{
+       return lookupFont(name);
+}
+
+
+LyXFont getFont(docstring const & name)
+{
+       LyXFont font;
+       augmentFont(font, name);
+       return font;
+}
+
+
+void fakeFont(docstring const & orig, docstring const & fake)
+{
+       fontinfo * forig = searchFont(orig);
+       fontinfo * ffake = searchFont(fake);
+       if (forig && ffake) {
+               forig->family_ = ffake->family_;
+               forig->series_ = ffake->series_;
+               forig->shape_  = ffake->shape_;
+               forig->color_  = ffake->color_;
+       } else {
+               lyxerr << "Can't fake font '" << to_utf8(orig) << "' with '"
+                      << to_utf8(fake) << "'" << endl;
+       }
+}
+
+
+void augmentFont(LyXFont & font, docstring const & name)
+{
+       static bool initialized = false;
+       if (!initialized) {
+               initialized = true;
+               // fake fonts if necessary
+               if (!theFontLoader().available(getFont(from_ascii("mathfrak"))))
+                       fakeFont(from_ascii("mathfrak"), from_ascii("lyxfakefrak"));
+               if (!theFontLoader().available(getFont(from_ascii("mathcal"))))
+                       fakeFont(from_ascii("mathcal"), from_ascii("lyxfakecal"));
+       }
+       fontinfo * info = searchFont(name);
+       if (info->family_ != inh_family)
+               font.setFamily(info->family_);
+       if (info->series_ != inh_series)
+               font.setSeries(info->series_);
+       if (info->shape_ != inh_shape)
+               font.setShape(info->shape_);
+       if (info->color_ != LColor::none)
+               font.setColor(info->color_);
+}
+
+
+docstring asString(MathArray const & ar)
+{
+       odocstringstream os;
+       WriteStream ws(os);
+       ws << ar;
+       return os.str();
+}
+
+
+void asArray(docstring const & str, MathArray & ar)
+{
+       mathed_parse_cell(ar, str);
+}
+
+
+docstring asString(InsetMath const & inset)
+{
+       odocstringstream os;
+       WriteStream ws(os);
+       inset.write(ws);
+       return os.str();
+}
+
+
+docstring asString(MathAtom const & at)
+{
+       odocstringstream os;
+       WriteStream ws(os);
+       at->write(ws);
+       return os.str();
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/TextPainter.C b/src/mathed/TextPainter.C
deleted file mode 100644 (file)
index fa8ca99..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * \file TextPainter.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "TextPainter.h"
-#include "support/std_ostream.h"
-
-
-namespace lyx {
-
-
-TextPainter::TextPainter(int xmax, int ymax)
-       : xmax_(xmax), ymax_(ymax), data_(xmax_ * (ymax_ + 1), ' ')
-{}
-
-
-char_type & TextPainter::at(int x, int y)
-{
-       return data_[y * xmax_ + x];
-}
-
-
-char_type TextPainter::at(int x, int y) const
-{
-       return data_[y * xmax_ + x];
-}
-
-
-void TextPainter::draw(int x, int y, char_type const * str)
-{
-       //cerr << "drawing string '" << str << "' at " << x << ',' << y << endl;
-       for (int i = 0; *str && x + i < xmax_; ++i, ++str)
-               at(x + i, y) = *str;
-       //show();
-}
-
-
-void TextPainter::horizontalLine(int x, int y, int n, char_type c)
-{
-       for (int i = 0; i < n && i + x < xmax_; ++i)
-               at(x + i, y) = c;
-}
-
-
-void TextPainter::verticalLine(int x, int y, int n, char_type c)
-{
-       for (int i = 0; i < n && i + y < ymax_; ++i)
-               at(x, y + i) = c;
-}
-
-
-void TextPainter::draw(int x, int y, char_type c)
-{
-       //cerr << "drawing char '" << c << "' at " << x << ',' << y << endl;
-       at(x, y) = c;
-       //show();
-}
-
-
-void TextPainter::show(odocstream & os, int offset) const
-{
-       os << '\n';
-       for (int j = 0; j <= ymax_; ++j) {
-               for (int i = 0; i < offset; ++i)
-                       os << ' ';
-               for (int i = 0; i < xmax_; ++i)
-                       os << at(i, j);
-               os << '\n';
-       }
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/TextPainter.cpp b/src/mathed/TextPainter.cpp
new file mode 100644 (file)
index 0000000..fa8ca99
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * \file TextPainter.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "TextPainter.h"
+#include "support/std_ostream.h"
+
+
+namespace lyx {
+
+
+TextPainter::TextPainter(int xmax, int ymax)
+       : xmax_(xmax), ymax_(ymax), data_(xmax_ * (ymax_ + 1), ' ')
+{}
+
+
+char_type & TextPainter::at(int x, int y)
+{
+       return data_[y * xmax_ + x];
+}
+
+
+char_type TextPainter::at(int x, int y) const
+{
+       return data_[y * xmax_ + x];
+}
+
+
+void TextPainter::draw(int x, int y, char_type const * str)
+{
+       //cerr << "drawing string '" << str << "' at " << x << ',' << y << endl;
+       for (int i = 0; *str && x + i < xmax_; ++i, ++str)
+               at(x + i, y) = *str;
+       //show();
+}
+
+
+void TextPainter::horizontalLine(int x, int y, int n, char_type c)
+{
+       for (int i = 0; i < n && i + x < xmax_; ++i)
+               at(x + i, y) = c;
+}
+
+
+void TextPainter::verticalLine(int x, int y, int n, char_type c)
+{
+       for (int i = 0; i < n && i + y < ymax_; ++i)
+               at(x, y + i) = c;
+}
+
+
+void TextPainter::draw(int x, int y, char_type c)
+{
+       //cerr << "drawing char '" << c << "' at " << x << ',' << y << endl;
+       at(x, y) = c;
+       //show();
+}
+
+
+void TextPainter::show(odocstream & os, int offset) const
+{
+       os << '\n';
+       for (int j = 0; j <= ymax_; ++j) {
+               for (int i = 0; i < offset; ++i)
+                       os << ' ';
+               for (int i = 0; i < xmax_; ++i)
+                       os << at(i, j);
+               os << '\n';
+       }
+}
+
+
+} // namespace lyx