+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
-
--- /dev/null
+/**
+ * \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
+
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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 << "<"; break;
- case '>': ms << ">"; break;
- case '&': ms << "&"; break;
- default: ms.os().put(char_); break;
- }
-}
-
-
-bool InsetMathChar::isRelOp() const
-{
- return char_ == '=' || char_ == '<' || char_ == '>';
-}
-
-
-} // namespace lyx
--- /dev/null
+/**
+ * \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 << "<"; break;
+ case '>': ms << ">"; break;
+ case '&': ms << "&"; break;
+ default: ms.os().put(char_); break;
+ }
+}
+
+
+bool InsetMathChar::isRelOp() const
+{
+ return char_ == '=' || char_ == '<' || char_ == '>';
+}
+
+
+} // namespace lyx
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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> ⁢ </mo>"
- << MTag("mrow") << "<mo> ⅆ </mo>"
- << cell(1) << ETag("mrow");
-}
-
-
-void InsetMathExInt::write(WriteStream &) const
-{
- lyxerr << "should not happen" << endl;
-}
-
-
-} // namespace lyx
--- /dev/null
+/**
+ * \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> ⁢ </mo>"
+ << MTag("mrow") << "<mo> ⅆ </mo>"
+ << cell(1) << ETag("mrow");
+}
+
+
+void InsetMathExInt::write(WriteStream &) const
+{
+ lyxerr << "should not happen" << endl;
+}
+
+
+} // namespace lyx
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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()), "&", "&"), "<", "<"));
- 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()), "&", "&"), "<", "<"));
- 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
--- /dev/null
+/**
+ * \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()), "&", "&"), "<", "<"));
+ 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()), "&", "&"), "<", "<"));
+ 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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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
+++ /dev/null
-/**
- * \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
--- /dev/null
+/**
+ * \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