]> git.lyx.org Git - lyx.git/commitdiff
Fix a few rename inconsistencies discovered by JMarc in insets and mathed, step 2
authorBo Peng <bpeng@lyx.org>
Wed, 25 Apr 2007 16:12:54 +0000 (16:12 +0000)
committerBo Peng <bpeng@lyx.org>
Wed, 25 Apr 2007 16:12:54 +0000 (16:12 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@17992 a592a061-630c-0410-9148-cb99ea01b6c8

22 files changed:
src/insets/InsetCitation.cpp [new file with mode: 0644]
src/insets/InsetCitation.h [new file with mode: 0644]
src/insets/InsetCite.cpp [deleted file]
src/insets/InsetCite.h [deleted file]
src/insets/InsetPageBreak.cpp [deleted file]
src/insets/InsetPageBreak.h [deleted file]
src/insets/InsetPagebreak.cpp [new file with mode: 0644]
src/insets/InsetPagebreak.h [new file with mode: 0644]
src/mathed/CommandInset.cpp [new file with mode: 0644]
src/mathed/CommandInset.h [new file with mode: 0644]
src/mathed/InsetMathCommand.cpp [deleted file]
src/mathed/InsetMathCommand.h [deleted file]
src/mathed/InsetMathMacro.cpp [deleted file]
src/mathed/InsetMathMacro.h [deleted file]
src/mathed/MathArray.cpp [new file with mode: 0644]
src/mathed/MathArray.h [new file with mode: 0644]
src/mathed/MathData.cpp [deleted file]
src/mathed/MathData.h [deleted file]
src/mathed/MathMacro.cpp [new file with mode: 0644]
src/mathed/MathMacro.h [new file with mode: 0644]
src/mathed/MathReplace.h [deleted file]
src/mathed/ReplaceData.h [new file with mode: 0644]

diff --git a/src/insets/InsetCitation.cpp b/src/insets/InsetCitation.cpp
new file mode 100644 (file)
index 0000000..e7f3fc8
--- /dev/null
@@ -0,0 +1,470 @@
+/**
+ * \file InsetCitation.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ * \author Herbert Voß
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetCitation.h"
+
+#include "buffer.h"
+#include "bufferparams.h"
+#include "debug.h"
+#include "dispatchresult.h"
+#include "funcrequest.h"
+#include "LaTeXFeatures.h"
+
+#include "frontends/controllers/biblio.h"
+
+#include "support/fs_extras.h"
+#include "support/lstrings.h"
+
+#include <algorithm>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/exception.hpp>
+
+
+namespace lyx {
+
+using support::ascii_lowercase;
+using support::contains;
+using support::FileName;
+using support::getStringFromVector;
+using support::getVectorFromString;
+using support::ltrim;
+using support::rtrim;
+using support::split;
+using support::tokenPos;
+
+using std::endl;
+using std::replace;
+using std::string;
+using std::ostream;
+using std::vector;
+using std::map;
+
+namespace fs = boost::filesystem;
+
+
+namespace {
+
+docstring const getNatbibLabel(Buffer const & buffer,
+                           string const & citeType, string const & keyList,
+                           docstring const & before, docstring const & after,
+                           biblio::CiteEngine engine)
+{
+       // Only start the process off after the buffer is loaded from file.
+       if (!buffer.fully_loaded())
+               return docstring();
+
+       // Cache the labels
+       typedef std::map<Buffer const *, biblio::InfoMap> CachedMap;
+       static CachedMap cached_keys;
+
+       // and cache the timestamp of the bibliography files.
+       static std::map<FileName, time_t> bibfileStatus;
+
+       biblio::InfoMap infomap;
+
+       vector<FileName> const & bibfilesCache = buffer.getBibfilesCache();
+       // compare the cached timestamps with the actual ones.
+       bool changed = false;
+       for (vector<FileName>::const_iterator it = bibfilesCache.begin();
+                       it != bibfilesCache.end(); ++ it) {
+               FileName const f = *it;
+               try {
+                       std::time_t lastw = fs::last_write_time(f.toFilesystemEncoding());
+                       if (lastw != bibfileStatus[f]) {
+                               changed = true;
+                               bibfileStatus[f] = lastw;
+                       }
+               }
+               catch (fs::filesystem_error & fserr) {
+                       changed = true;
+                       lyxerr << "Couldn't find or read bibtex file "
+                              << f << endl;
+                       LYXERR(Debug::DEBUG) << "Fs error: "
+                                            << fserr.what() << endl;
+               }
+       }
+
+       // build the keylist only if the bibfiles have been changed
+       if (cached_keys[&buffer].empty() || bibfileStatus.empty() || changed) {
+               typedef vector<std::pair<string, docstring> > InfoType;
+               InfoType bibkeys;
+               buffer.fillWithBibKeys(bibkeys);
+
+               InfoType::const_iterator bit  = bibkeys.begin();
+               InfoType::const_iterator bend = bibkeys.end();
+
+               for (; bit != bend; ++bit)
+                       infomap[bit->first] = bit->second;
+
+               cached_keys[&buffer] = infomap;
+       } else
+               // use the cached keys
+               infomap = cached_keys[&buffer];
+
+       if (infomap.empty())
+               return docstring();
+
+       // the natbib citation-styles
+       // CITET:       author (year)
+       // CITEP:       (author,year)
+       // CITEALT:     author year
+       // CITEALP:     author, year
+       // CITEAUTHOR:  author
+       // CITEYEAR:    year
+       // CITEYEARPAR: (year)
+       // jurabib supports these plus
+       // CITE:        author/<before field>
+
+       // We don't currently use the full or forceUCase fields.
+       string cite_type = biblio::asValidLatexCommand(citeType, engine);
+       if (cite_type[0] == 'C')
+               cite_type = string(1, 'c') + cite_type.substr(1);
+       if (cite_type[cite_type.size() - 1] == '*')
+               cite_type = cite_type.substr(0, cite_type.size() - 1);
+
+       docstring before_str;
+       if (!before.empty()) {
+               // In CITET and CITEALT mode, the "before" string is
+               // attached to the label associated with each and every key.
+               // In CITEP, CITEALP and CITEYEARPAR mode, it is attached
+               // to the front of the whole only.
+               // In other modes, it is not used at all.
+               if (cite_type == "citet" ||
+                   cite_type == "citealt" ||
+                   cite_type == "citep" ||
+                   cite_type == "citealp" ||
+                   cite_type == "citeyearpar")
+                       before_str = before + ' ';
+               // In CITE (jurabib), the "before" string is used to attach
+               // the annotator (of legal texts) to the author(s) of the
+               // first reference.
+               else if (cite_type == "cite")
+                       before_str = '/' + before;
+       }
+
+       docstring after_str;
+       if (!after.empty()) {
+               // The "after" key is appended only to the end of the whole.
+               after_str = ", " + after;
+       }
+
+       // One day, these might be tunable (as they are in BibTeX).
+       char const op  = '('; // opening parenthesis.
+       char const cp  = ')'; // closing parenthesis.
+       // puctuation mark separating citation entries.
+       char const * const sep = ";";
+
+       docstring const op_str(' ' + docstring(1, op));
+       docstring const cp_str(docstring(1, cp) + ' ');
+       docstring const sep_str(from_ascii(sep) + ' ');
+
+       docstring label;
+       vector<string> keys = getVectorFromString(keyList);
+       vector<string>::const_iterator it  = keys.begin();
+       vector<string>::const_iterator end = keys.end();
+       for (; it != end; ++it) {
+               // get the bibdata corresponding to the key
+               docstring const author(biblio::getAbbreviatedAuthor(infomap, *it));
+               docstring const year(biblio::getYear(infomap, *it));
+
+               // Something isn't right. Fail safely.
+               if (author.empty() || year.empty())
+                       return docstring();
+
+               // authors1/<before>;  ... ;
+               //  authors_last, <after>
+               if (cite_type == "cite" && engine == biblio::ENGINE_JURABIB) {
+                       if (it == keys.begin())
+                               label += author + before_str + sep_str;
+                       else
+                               label += author + sep_str;
+
+               // (authors1 (<before> year);  ... ;
+               //  authors_last (<before> year, <after>)
+               } else if (cite_type == "citet") {
+                       switch (engine) {
+                       case biblio::ENGINE_NATBIB_AUTHORYEAR:
+                               label += author + op_str + before_str +
+                                       year + cp + sep_str;
+                               break;
+                       case biblio::ENGINE_NATBIB_NUMERICAL:
+                               // FIXME UNICODE
+                               label += author + op_str + before_str +
+                                       '#' + from_utf8(*it) + cp + sep_str;
+                               break;
+                       case biblio::ENGINE_JURABIB:
+                               label += before_str + author + op_str +
+                                       year + cp + sep_str;
+                               break;
+                       case biblio::ENGINE_BASIC:
+                               break;
+                       }
+
+               // author, year; author, year; ...
+               } else if (cite_type == "citep" ||
+                          cite_type == "citealp") {
+                       if (engine == biblio::ENGINE_NATBIB_NUMERICAL) {
+                               // FIXME UNICODE
+                               label += from_utf8(*it) + sep_str;
+                       } else {
+                               label += author + ", " + year + sep_str;
+                       }
+
+               // (authors1 <before> year;
+               //  authors_last <before> year, <after>)
+               } else if (cite_type == "citealt") {
+                       switch (engine) {
+                       case biblio::ENGINE_NATBIB_AUTHORYEAR:
+                               label += author + ' ' + before_str +
+                                       year + sep_str;
+                               break;
+                       case biblio::ENGINE_NATBIB_NUMERICAL:
+                               // FIXME UNICODE
+                               label += author + ' ' + before_str +
+                                       '#' + from_utf8(*it) + sep_str;
+                               break;
+                       case biblio::ENGINE_JURABIB:
+                               label += before_str + author + ' ' +
+                                       year + sep_str;
+                               break;
+                       case biblio::ENGINE_BASIC:
+                               break;
+                       }
+
+               // author; author; ...
+               } else if (cite_type == "citeauthor") {
+                       label += author + sep_str;
+
+               // year; year; ...
+               } else if (cite_type == "citeyear" ||
+                          cite_type == "citeyearpar") {
+                       label += year + sep_str;
+               }
+       }
+       label = rtrim(rtrim(label), sep);
+
+       if (!after_str.empty()) {
+               if (cite_type == "citet") {
+                       // insert "after" before last ')'
+                       label.insert(label.size() - 1, after_str);
+               } else {
+                       bool const add =
+                               !(engine == biblio::ENGINE_NATBIB_NUMERICAL &&
+                                 (cite_type == "citeauthor" ||
+                                  cite_type == "citeyear"));
+                       if (add)
+                               label += after_str;
+               }
+       }
+
+       if (!before_str.empty() && (cite_type == "citep" ||
+                                   cite_type == "citealp" ||
+                                   cite_type == "citeyearpar")) {
+               label = before_str + label;
+       }
+
+       if (cite_type == "citep" || cite_type == "citeyearpar")
+               label = op + label + cp;
+
+       return label;
+}
+
+
+docstring const getBasicLabel(docstring const & keyList, docstring const & after)
+{
+       docstring keys(keyList);
+       docstring label;
+
+       if (contains(keys, ',')) {
+               // Final comma allows while loop to cover all keys
+               keys = ltrim(split(keys, label, ',')) + ',';
+               while (contains(keys, ',')) {
+                       docstring key;
+                       keys = ltrim(split(keys, key, ','));
+                       label += ", " + key;
+               }
+       } else
+               label = keys;
+
+       if (!after.empty())
+               label += ", " + after;
+
+       return '[' + label + ']';
+}
+
+} // anon namespace
+
+
+InsetCitation::InsetCitation(InsetCommandParams const & p)
+       : InsetCommand(p, "citation")
+{}
+
+
+docstring const InsetCitation::generateLabel(Buffer const & buffer) const
+{
+       docstring const before = getParam("before");
+       docstring const after  = getParam("after");
+
+       docstring label;
+       biblio::CiteEngine const engine = buffer.params().getEngine();
+       if (engine != biblio::ENGINE_BASIC) {
+               // FIXME UNICODE
+               label = getNatbibLabel(buffer, getCmdName(), to_utf8(getParam("key")),
+                                      before, after, engine);
+       }
+
+       // Fallback to fail-safe
+       if (label.empty()) {
+               label = getBasicLabel(getParam("key"), after);
+       }
+
+       return label;
+}
+
+
+docstring const InsetCitation::getScreenLabel(Buffer const & buffer) const
+{
+       biblio::CiteEngine const engine = buffer.params().getEngine();
+       if (cache.params == params() && cache.engine == engine)
+               return cache.screen_label;
+
+       // The label has changed, so we have to re-create it.
+       docstring const glabel = generateLabel(buffer);
+
+       unsigned int const maxLabelChars = 45;
+
+       docstring label = glabel;
+       if (label.size() > maxLabelChars) {
+               label.erase(maxLabelChars-3);
+               label += "...";
+       }
+
+       cache.engine  = engine;
+       cache.params = params();
+       cache.generated_label = glabel;
+       cache.screen_label = label;
+
+       return label;
+}
+
+
+int InsetCitation::plaintext(Buffer const & buffer, odocstream & os,
+                             OutputParams const &) const
+{
+       docstring str;
+
+       if (cache.params == params() &&
+           cache.engine == buffer.params().getEngine())
+               str = cache.generated_label;
+       else
+               str = generateLabel(buffer);
+
+       os << str;
+       return str.size();
+}
+
+
+namespace {
+
+docstring const cleanupWhitespace(docstring const & citelist)
+{
+       docstring::const_iterator it  = citelist.begin();
+       docstring::const_iterator end = citelist.end();
+       // Paranoia check: make sure that there is no whitespace in here
+       // -- at least not behind commas or at the beginning
+       docstring result;
+       char_type last = ',';
+       for (; it != end; ++it) {
+               if (*it != ' ')
+                       last = *it;
+               if (*it != ' ' || last != ',')
+                       result += *it;
+       }
+       return result;
+}
+
+// end anon namyspace
+}
+
+int InsetCitation::docbook(Buffer const &, odocstream & os,
+                           OutputParams const &) const
+{
+       os << "<citation>"
+           << cleanupWhitespace(getParam("key"))
+           << "</citation>";
+       return 0;
+}
+
+
+int InsetCitation::textString(Buffer const & buf, odocstream & os,
+                      OutputParams const & op) const
+{
+       return plaintext(buf, os, op);
+}
+
+
+// Have to overwrite the default InsetCommand method in order to check that
+// the \cite command is valid. Eg, the user has natbib enabled, inputs some
+// citations and then changes his mind, turning natbib support off. The output
+// should revert to \cite[]{}
+int InsetCitation::latex(Buffer const & buffer, odocstream & os,
+                         OutputParams const &) const
+{
+       biblio::CiteEngine cite_engine = buffer.params().getEngine();
+       // FIXME UNICODE
+       docstring const cite_str = from_utf8(
+               biblio::asValidLatexCommand(getCmdName(), cite_engine));
+
+       os << "\\" << cite_str;
+
+       docstring const & before = getParam("before");
+       docstring const & after  = getParam("after");
+       if (!before.empty() && cite_engine != biblio::ENGINE_BASIC)
+               os << '[' << before << "][" << after << ']';
+       else if (!after.empty())
+               os << '[' << after << ']';
+
+       os << '{' << cleanupWhitespace(getParam("key")) << '}';
+
+       return 0;
+}
+
+
+void InsetCitation::validate(LaTeXFeatures & features) const
+{
+       switch (features.bufferParams().getEngine()) {
+       case biblio::ENGINE_BASIC:
+               break;
+       case biblio::ENGINE_NATBIB_AUTHORYEAR:
+       case biblio::ENGINE_NATBIB_NUMERICAL:
+               features.require("natbib");
+               break;
+       case biblio::ENGINE_JURABIB:
+               features.require("jurabib");
+               break;
+       }
+}
+
+
+void InsetCitation::replaceContents(string const & from, string const & to)
+{
+       if (tokenPos(getContents(), ',', from) != -1) {
+               vector<string> items = getVectorFromString(getContents());
+               replace(items.begin(), items.end(), from, to);
+               setContents(getStringFromVector(items));
+       }
+}
+
+
+} // namespace lyx
diff --git a/src/insets/InsetCitation.h b/src/insets/InsetCitation.h
new file mode 100644 (file)
index 0000000..f0fd1d7
--- /dev/null
@@ -0,0 +1,83 @@
+// -*- C++ -*-
+/**
+ * \file InsetCitation.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ * \author Herbert Voß
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef INSET_CITE_H
+#define INSET_CITE_H
+
+
+#include "InsetCommand.h"
+
+#include "frontends/controllers/biblio.h"
+
+
+namespace lyx {
+
+
+/** Used to insert citations
+ */
+class InsetCitation : public InsetCommand {
+public:
+       ///
+       InsetCitation(InsetCommandParams const &);
+       ///
+       docstring const getScreenLabel(Buffer const &) const;
+       ///
+       EDITABLE editable() const { return IS_EDITABLE; }
+       ///
+       InsetBase::Code lyxCode() const { return InsetBase::CITE_CODE; }
+       ///
+       int latex(Buffer const &, odocstream &,
+                 OutputParams const &) const;
+       ///
+       int plaintext(Buffer const &, odocstream &,
+                     OutputParams const &) const;
+       ///
+       int docbook(Buffer const &, odocstream &,
+                   OutputParams const &) const;
+       /// the string that is passed to the TOC
+       virtual int textString(Buffer const &, odocstream &,
+               OutputParams const &) const;
+       ///
+       void validate(LaTeXFeatures &) const;
+       ///
+       void replaceContents(std::string const & from, std::string const & to);
+
+private:
+       virtual std::auto_ptr<InsetBase> doClone() const
+       {
+               return std::auto_ptr<InsetBase>(new InsetCitation(params()));
+       }
+
+       /// This function does the donkey work of creating the pretty label
+       docstring const generateLabel(Buffer const &) const;
+
+       class Cache {
+       public:
+               ///
+               Cache() : engine(biblio::ENGINE_BASIC), params("cite") {}
+               ///
+               biblio::CiteEngine engine;
+               ///
+               InsetCommandParams params;
+               ///
+               docstring generated_label;
+               ///
+               docstring screen_label;
+       };
+       ///
+       mutable Cache cache;
+};
+
+
+} // namespace lyx
+
+#endif // INSET_CITE_H
diff --git a/src/insets/InsetCite.cpp b/src/insets/InsetCite.cpp
deleted file mode 100644 (file)
index e7f3fc8..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-/**
- * \file InsetCitation.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- * \author Herbert Voß
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetCitation.h"
-
-#include "buffer.h"
-#include "bufferparams.h"
-#include "debug.h"
-#include "dispatchresult.h"
-#include "funcrequest.h"
-#include "LaTeXFeatures.h"
-
-#include "frontends/controllers/biblio.h"
-
-#include "support/fs_extras.h"
-#include "support/lstrings.h"
-
-#include <algorithm>
-
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/exception.hpp>
-
-
-namespace lyx {
-
-using support::ascii_lowercase;
-using support::contains;
-using support::FileName;
-using support::getStringFromVector;
-using support::getVectorFromString;
-using support::ltrim;
-using support::rtrim;
-using support::split;
-using support::tokenPos;
-
-using std::endl;
-using std::replace;
-using std::string;
-using std::ostream;
-using std::vector;
-using std::map;
-
-namespace fs = boost::filesystem;
-
-
-namespace {
-
-docstring const getNatbibLabel(Buffer const & buffer,
-                           string const & citeType, string const & keyList,
-                           docstring const & before, docstring const & after,
-                           biblio::CiteEngine engine)
-{
-       // Only start the process off after the buffer is loaded from file.
-       if (!buffer.fully_loaded())
-               return docstring();
-
-       // Cache the labels
-       typedef std::map<Buffer const *, biblio::InfoMap> CachedMap;
-       static CachedMap cached_keys;
-
-       // and cache the timestamp of the bibliography files.
-       static std::map<FileName, time_t> bibfileStatus;
-
-       biblio::InfoMap infomap;
-
-       vector<FileName> const & bibfilesCache = buffer.getBibfilesCache();
-       // compare the cached timestamps with the actual ones.
-       bool changed = false;
-       for (vector<FileName>::const_iterator it = bibfilesCache.begin();
-                       it != bibfilesCache.end(); ++ it) {
-               FileName const f = *it;
-               try {
-                       std::time_t lastw = fs::last_write_time(f.toFilesystemEncoding());
-                       if (lastw != bibfileStatus[f]) {
-                               changed = true;
-                               bibfileStatus[f] = lastw;
-                       }
-               }
-               catch (fs::filesystem_error & fserr) {
-                       changed = true;
-                       lyxerr << "Couldn't find or read bibtex file "
-                              << f << endl;
-                       LYXERR(Debug::DEBUG) << "Fs error: "
-                                            << fserr.what() << endl;
-               }
-       }
-
-       // build the keylist only if the bibfiles have been changed
-       if (cached_keys[&buffer].empty() || bibfileStatus.empty() || changed) {
-               typedef vector<std::pair<string, docstring> > InfoType;
-               InfoType bibkeys;
-               buffer.fillWithBibKeys(bibkeys);
-
-               InfoType::const_iterator bit  = bibkeys.begin();
-               InfoType::const_iterator bend = bibkeys.end();
-
-               for (; bit != bend; ++bit)
-                       infomap[bit->first] = bit->second;
-
-               cached_keys[&buffer] = infomap;
-       } else
-               // use the cached keys
-               infomap = cached_keys[&buffer];
-
-       if (infomap.empty())
-               return docstring();
-
-       // the natbib citation-styles
-       // CITET:       author (year)
-       // CITEP:       (author,year)
-       // CITEALT:     author year
-       // CITEALP:     author, year
-       // CITEAUTHOR:  author
-       // CITEYEAR:    year
-       // CITEYEARPAR: (year)
-       // jurabib supports these plus
-       // CITE:        author/<before field>
-
-       // We don't currently use the full or forceUCase fields.
-       string cite_type = biblio::asValidLatexCommand(citeType, engine);
-       if (cite_type[0] == 'C')
-               cite_type = string(1, 'c') + cite_type.substr(1);
-       if (cite_type[cite_type.size() - 1] == '*')
-               cite_type = cite_type.substr(0, cite_type.size() - 1);
-
-       docstring before_str;
-       if (!before.empty()) {
-               // In CITET and CITEALT mode, the "before" string is
-               // attached to the label associated with each and every key.
-               // In CITEP, CITEALP and CITEYEARPAR mode, it is attached
-               // to the front of the whole only.
-               // In other modes, it is not used at all.
-               if (cite_type == "citet" ||
-                   cite_type == "citealt" ||
-                   cite_type == "citep" ||
-                   cite_type == "citealp" ||
-                   cite_type == "citeyearpar")
-                       before_str = before + ' ';
-               // In CITE (jurabib), the "before" string is used to attach
-               // the annotator (of legal texts) to the author(s) of the
-               // first reference.
-               else if (cite_type == "cite")
-                       before_str = '/' + before;
-       }
-
-       docstring after_str;
-       if (!after.empty()) {
-               // The "after" key is appended only to the end of the whole.
-               after_str = ", " + after;
-       }
-
-       // One day, these might be tunable (as they are in BibTeX).
-       char const op  = '('; // opening parenthesis.
-       char const cp  = ')'; // closing parenthesis.
-       // puctuation mark separating citation entries.
-       char const * const sep = ";";
-
-       docstring const op_str(' ' + docstring(1, op));
-       docstring const cp_str(docstring(1, cp) + ' ');
-       docstring const sep_str(from_ascii(sep) + ' ');
-
-       docstring label;
-       vector<string> keys = getVectorFromString(keyList);
-       vector<string>::const_iterator it  = keys.begin();
-       vector<string>::const_iterator end = keys.end();
-       for (; it != end; ++it) {
-               // get the bibdata corresponding to the key
-               docstring const author(biblio::getAbbreviatedAuthor(infomap, *it));
-               docstring const year(biblio::getYear(infomap, *it));
-
-               // Something isn't right. Fail safely.
-               if (author.empty() || year.empty())
-                       return docstring();
-
-               // authors1/<before>;  ... ;
-               //  authors_last, <after>
-               if (cite_type == "cite" && engine == biblio::ENGINE_JURABIB) {
-                       if (it == keys.begin())
-                               label += author + before_str + sep_str;
-                       else
-                               label += author + sep_str;
-
-               // (authors1 (<before> year);  ... ;
-               //  authors_last (<before> year, <after>)
-               } else if (cite_type == "citet") {
-                       switch (engine) {
-                       case biblio::ENGINE_NATBIB_AUTHORYEAR:
-                               label += author + op_str + before_str +
-                                       year + cp + sep_str;
-                               break;
-                       case biblio::ENGINE_NATBIB_NUMERICAL:
-                               // FIXME UNICODE
-                               label += author + op_str + before_str +
-                                       '#' + from_utf8(*it) + cp + sep_str;
-                               break;
-                       case biblio::ENGINE_JURABIB:
-                               label += before_str + author + op_str +
-                                       year + cp + sep_str;
-                               break;
-                       case biblio::ENGINE_BASIC:
-                               break;
-                       }
-
-               // author, year; author, year; ...
-               } else if (cite_type == "citep" ||
-                          cite_type == "citealp") {
-                       if (engine == biblio::ENGINE_NATBIB_NUMERICAL) {
-                               // FIXME UNICODE
-                               label += from_utf8(*it) + sep_str;
-                       } else {
-                               label += author + ", " + year + sep_str;
-                       }
-
-               // (authors1 <before> year;
-               //  authors_last <before> year, <after>)
-               } else if (cite_type == "citealt") {
-                       switch (engine) {
-                       case biblio::ENGINE_NATBIB_AUTHORYEAR:
-                               label += author + ' ' + before_str +
-                                       year + sep_str;
-                               break;
-                       case biblio::ENGINE_NATBIB_NUMERICAL:
-                               // FIXME UNICODE
-                               label += author + ' ' + before_str +
-                                       '#' + from_utf8(*it) + sep_str;
-                               break;
-                       case biblio::ENGINE_JURABIB:
-                               label += before_str + author + ' ' +
-                                       year + sep_str;
-                               break;
-                       case biblio::ENGINE_BASIC:
-                               break;
-                       }
-
-               // author; author; ...
-               } else if (cite_type == "citeauthor") {
-                       label += author + sep_str;
-
-               // year; year; ...
-               } else if (cite_type == "citeyear" ||
-                          cite_type == "citeyearpar") {
-                       label += year + sep_str;
-               }
-       }
-       label = rtrim(rtrim(label), sep);
-
-       if (!after_str.empty()) {
-               if (cite_type == "citet") {
-                       // insert "after" before last ')'
-                       label.insert(label.size() - 1, after_str);
-               } else {
-                       bool const add =
-                               !(engine == biblio::ENGINE_NATBIB_NUMERICAL &&
-                                 (cite_type == "citeauthor" ||
-                                  cite_type == "citeyear"));
-                       if (add)
-                               label += after_str;
-               }
-       }
-
-       if (!before_str.empty() && (cite_type == "citep" ||
-                                   cite_type == "citealp" ||
-                                   cite_type == "citeyearpar")) {
-               label = before_str + label;
-       }
-
-       if (cite_type == "citep" || cite_type == "citeyearpar")
-               label = op + label + cp;
-
-       return label;
-}
-
-
-docstring const getBasicLabel(docstring const & keyList, docstring const & after)
-{
-       docstring keys(keyList);
-       docstring label;
-
-       if (contains(keys, ',')) {
-               // Final comma allows while loop to cover all keys
-               keys = ltrim(split(keys, label, ',')) + ',';
-               while (contains(keys, ',')) {
-                       docstring key;
-                       keys = ltrim(split(keys, key, ','));
-                       label += ", " + key;
-               }
-       } else
-               label = keys;
-
-       if (!after.empty())
-               label += ", " + after;
-
-       return '[' + label + ']';
-}
-
-} // anon namespace
-
-
-InsetCitation::InsetCitation(InsetCommandParams const & p)
-       : InsetCommand(p, "citation")
-{}
-
-
-docstring const InsetCitation::generateLabel(Buffer const & buffer) const
-{
-       docstring const before = getParam("before");
-       docstring const after  = getParam("after");
-
-       docstring label;
-       biblio::CiteEngine const engine = buffer.params().getEngine();
-       if (engine != biblio::ENGINE_BASIC) {
-               // FIXME UNICODE
-               label = getNatbibLabel(buffer, getCmdName(), to_utf8(getParam("key")),
-                                      before, after, engine);
-       }
-
-       // Fallback to fail-safe
-       if (label.empty()) {
-               label = getBasicLabel(getParam("key"), after);
-       }
-
-       return label;
-}
-
-
-docstring const InsetCitation::getScreenLabel(Buffer const & buffer) const
-{
-       biblio::CiteEngine const engine = buffer.params().getEngine();
-       if (cache.params == params() && cache.engine == engine)
-               return cache.screen_label;
-
-       // The label has changed, so we have to re-create it.
-       docstring const glabel = generateLabel(buffer);
-
-       unsigned int const maxLabelChars = 45;
-
-       docstring label = glabel;
-       if (label.size() > maxLabelChars) {
-               label.erase(maxLabelChars-3);
-               label += "...";
-       }
-
-       cache.engine  = engine;
-       cache.params = params();
-       cache.generated_label = glabel;
-       cache.screen_label = label;
-
-       return label;
-}
-
-
-int InsetCitation::plaintext(Buffer const & buffer, odocstream & os,
-                             OutputParams const &) const
-{
-       docstring str;
-
-       if (cache.params == params() &&
-           cache.engine == buffer.params().getEngine())
-               str = cache.generated_label;
-       else
-               str = generateLabel(buffer);
-
-       os << str;
-       return str.size();
-}
-
-
-namespace {
-
-docstring const cleanupWhitespace(docstring const & citelist)
-{
-       docstring::const_iterator it  = citelist.begin();
-       docstring::const_iterator end = citelist.end();
-       // Paranoia check: make sure that there is no whitespace in here
-       // -- at least not behind commas or at the beginning
-       docstring result;
-       char_type last = ',';
-       for (; it != end; ++it) {
-               if (*it != ' ')
-                       last = *it;
-               if (*it != ' ' || last != ',')
-                       result += *it;
-       }
-       return result;
-}
-
-// end anon namyspace
-}
-
-int InsetCitation::docbook(Buffer const &, odocstream & os,
-                           OutputParams const &) const
-{
-       os << "<citation>"
-           << cleanupWhitespace(getParam("key"))
-           << "</citation>";
-       return 0;
-}
-
-
-int InsetCitation::textString(Buffer const & buf, odocstream & os,
-                      OutputParams const & op) const
-{
-       return plaintext(buf, os, op);
-}
-
-
-// Have to overwrite the default InsetCommand method in order to check that
-// the \cite command is valid. Eg, the user has natbib enabled, inputs some
-// citations and then changes his mind, turning natbib support off. The output
-// should revert to \cite[]{}
-int InsetCitation::latex(Buffer const & buffer, odocstream & os,
-                         OutputParams const &) const
-{
-       biblio::CiteEngine cite_engine = buffer.params().getEngine();
-       // FIXME UNICODE
-       docstring const cite_str = from_utf8(
-               biblio::asValidLatexCommand(getCmdName(), cite_engine));
-
-       os << "\\" << cite_str;
-
-       docstring const & before = getParam("before");
-       docstring const & after  = getParam("after");
-       if (!before.empty() && cite_engine != biblio::ENGINE_BASIC)
-               os << '[' << before << "][" << after << ']';
-       else if (!after.empty())
-               os << '[' << after << ']';
-
-       os << '{' << cleanupWhitespace(getParam("key")) << '}';
-
-       return 0;
-}
-
-
-void InsetCitation::validate(LaTeXFeatures & features) const
-{
-       switch (features.bufferParams().getEngine()) {
-       case biblio::ENGINE_BASIC:
-               break;
-       case biblio::ENGINE_NATBIB_AUTHORYEAR:
-       case biblio::ENGINE_NATBIB_NUMERICAL:
-               features.require("natbib");
-               break;
-       case biblio::ENGINE_JURABIB:
-               features.require("jurabib");
-               break;
-       }
-}
-
-
-void InsetCitation::replaceContents(string const & from, string const & to)
-{
-       if (tokenPos(getContents(), ',', from) != -1) {
-               vector<string> items = getVectorFromString(getContents());
-               replace(items.begin(), items.end(), from, to);
-               setContents(getStringFromVector(items));
-       }
-}
-
-
-} // namespace lyx
diff --git a/src/insets/InsetCite.h b/src/insets/InsetCite.h
deleted file mode 100644 (file)
index f0fd1d7..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-// -*- C++ -*-
-/**
- * \file InsetCitation.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- * \author Herbert Voß
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef INSET_CITE_H
-#define INSET_CITE_H
-
-
-#include "InsetCommand.h"
-
-#include "frontends/controllers/biblio.h"
-
-
-namespace lyx {
-
-
-/** Used to insert citations
- */
-class InsetCitation : public InsetCommand {
-public:
-       ///
-       InsetCitation(InsetCommandParams const &);
-       ///
-       docstring const getScreenLabel(Buffer const &) const;
-       ///
-       EDITABLE editable() const { return IS_EDITABLE; }
-       ///
-       InsetBase::Code lyxCode() const { return InsetBase::CITE_CODE; }
-       ///
-       int latex(Buffer const &, odocstream &,
-                 OutputParams const &) const;
-       ///
-       int plaintext(Buffer const &, odocstream &,
-                     OutputParams const &) const;
-       ///
-       int docbook(Buffer const &, odocstream &,
-                   OutputParams const &) const;
-       /// the string that is passed to the TOC
-       virtual int textString(Buffer const &, odocstream &,
-               OutputParams const &) const;
-       ///
-       void validate(LaTeXFeatures &) const;
-       ///
-       void replaceContents(std::string const & from, std::string const & to);
-
-private:
-       virtual std::auto_ptr<InsetBase> doClone() const
-       {
-               return std::auto_ptr<InsetBase>(new InsetCitation(params()));
-       }
-
-       /// This function does the donkey work of creating the pretty label
-       docstring const generateLabel(Buffer const &) const;
-
-       class Cache {
-       public:
-               ///
-               Cache() : engine(biblio::ENGINE_BASIC), params("cite") {}
-               ///
-               biblio::CiteEngine engine;
-               ///
-               InsetCommandParams params;
-               ///
-               docstring generated_label;
-               ///
-               docstring screen_label;
-       };
-       ///
-       mutable Cache cache;
-};
-
-
-} // namespace lyx
-
-#endif // INSET_CITE_H
diff --git a/src/insets/InsetPageBreak.cpp b/src/insets/InsetPageBreak.cpp
deleted file mode 100644 (file)
index 65683cb..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * \file InsetPagebreak.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 "InsetPagebreak.h"
-
-#include "debug.h"
-#include "gettext.h"
-#include "LColor.h"
-#include "lyxtext.h"
-#include "metricsinfo.h"
-#include "outputparams.h"
-#include "TextMetrics.h"
-
-#include "frontends/FontMetrics.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-using frontend::Painter;
-
-using std::endl;
-using std::ostream;
-
-
-void InsetPagebreak::read(Buffer const &, LyXLex &)
-{
-       /* Nothing to read */
-}
-
-
-void InsetPagebreak::write(Buffer const &, ostream & os) const
-{
-       os << "\n" << getCmdName() << '\n';
-}
-
-
-bool InsetPagebreak::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       dim.asc = defaultRowHeight();
-       dim.des = defaultRowHeight();
-       dim.wid = mi.base.textwidth;
-       bool const changed = dim_ != dim;
-       dim_ = dim;
-       return changed;
-}
-
-
-void InsetPagebreak::draw(PainterInfo & pi, int x, int y) const
-{
-       LyXFont font;
-       font.setColor(LColor::pagebreak);
-       font.decSize();
-
-       int w = 0;
-       int a = 0;
-       int d = 0;
-       theFontMetrics(font).rectText(insetLabel(), w, a, d);
-
-       int const text_start = int(x + (dim_.wid - w) / 2);
-       int const text_end = text_start + w;
-
-       pi.pain.rectText(text_start, y + d, insetLabel(), font,
-               LColor::none, LColor::none);
-
-       pi.pain.line(x, y, text_start, y,
-                  LColor::pagebreak, Painter::line_onoffdash);
-       pi.pain.line(text_end, y, int(x + dim_.wid), y,
-                  LColor::pagebreak, Painter::line_onoffdash);
-}
-
-
-int InsetPagebreak::latex(Buffer const &, odocstream & os,
-                          OutputParams const &) const
-{
-       os << from_ascii(getCmdName()) << "{}";
-       return 0;
-}
-
-
-int InsetPagebreak::plaintext(Buffer const &, odocstream & os,
-                              OutputParams const &) const
-{
-       os << '\n';
-       return PLAINTEXT_NEWLINE;
-}
-
-
-int InsetPagebreak::docbook(Buffer const &, odocstream & os,
-                            OutputParams const &) const
-{
-       os << '\n';
-       return 0;
-}
-
-
-} // namespace lyx
diff --git a/src/insets/InsetPageBreak.h b/src/insets/InsetPageBreak.h
deleted file mode 100644 (file)
index b018f58..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// -*- C++ -*-
-/**
- * \file InsetPagebreak.h
- * 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.
- */
-
-#ifndef INSET_PAGEBREAK_H
-#define INSET_PAGEBREAK_H
-
-
-#include "Inset.h"
-#include "gettext.h"
-
-
-namespace lyx {
-
-class InsetPagebreak : public InsetOld {
-public:
-       InsetPagebreak() {}
-
-       InsetBase::Code lyxCode() const { return InsetBase::PAGEBREAK_CODE; }
-
-       bool metrics(MetricsInfo &, Dimension &) const;
-
-       void draw(PainterInfo & pi, int x, int y) const;
-
-       int latex(Buffer const &, odocstream &,
-                 OutputParams const &) const;
-
-       int plaintext(Buffer const &, odocstream &,
-                     OutputParams const &) const;
-
-       int docbook(Buffer const &, odocstream &,
-                   OutputParams const &) const;
-
-       void read(Buffer const &, LyXLex & lex);
-
-       virtual void write(Buffer const & buf, std::ostream & os) const;
-       /// We don't need \begin_inset and \end_inset
-       bool directWrite() const { return true; }
-
-       bool display() const { return true; }
-
-       virtual docstring insetLabel() const { return _("Page Break"); }
-
-       virtual std::string getCmdName() const { return "\\newpage"; }
-
-private:
-       virtual std::auto_ptr<InsetBase> doClone() const
-       {
-               return std::auto_ptr<InsetBase>(new InsetPagebreak);
-       }
-};
-
-
-class InsetClearPage : public InsetPagebreak {
-public:
-       InsetClearPage() {}
-
-       docstring insetLabel() const { return _("Clear Page"); }
-       
-       std::string getCmdName() const { return "\\clearpage"; }
-
-private:
-       virtual std::auto_ptr<InsetBase> doClone() const
-       {
-               return std::auto_ptr<InsetBase>(new InsetClearPage);
-       }
-};
-
-
-class InsetClearDoublePage : public InsetPagebreak {
-public:
-       InsetClearDoublePage() {}
-
-       docstring insetLabel() const { return _("Clear Double Page"); }
-       
-       std::string getCmdName() const { return "\\cleardoublepage"; }
-
-private:
-       virtual std::auto_ptr<InsetBase> doClone() const
-       {
-               return std::auto_ptr<InsetBase>(new InsetClearDoublePage);
-       }
-};
-
-} // namespace lyx
-
-#endif // INSET_PAGEBREAK_H
diff --git a/src/insets/InsetPagebreak.cpp b/src/insets/InsetPagebreak.cpp
new file mode 100644 (file)
index 0000000..65683cb
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * \file InsetPagebreak.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 "InsetPagebreak.h"
+
+#include "debug.h"
+#include "gettext.h"
+#include "LColor.h"
+#include "lyxtext.h"
+#include "metricsinfo.h"
+#include "outputparams.h"
+#include "TextMetrics.h"
+
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+using frontend::Painter;
+
+using std::endl;
+using std::ostream;
+
+
+void InsetPagebreak::read(Buffer const &, LyXLex &)
+{
+       /* Nothing to read */
+}
+
+
+void InsetPagebreak::write(Buffer const &, ostream & os) const
+{
+       os << "\n" << getCmdName() << '\n';
+}
+
+
+bool InsetPagebreak::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       dim.asc = defaultRowHeight();
+       dim.des = defaultRowHeight();
+       dim.wid = mi.base.textwidth;
+       bool const changed = dim_ != dim;
+       dim_ = dim;
+       return changed;
+}
+
+
+void InsetPagebreak::draw(PainterInfo & pi, int x, int y) const
+{
+       LyXFont font;
+       font.setColor(LColor::pagebreak);
+       font.decSize();
+
+       int w = 0;
+       int a = 0;
+       int d = 0;
+       theFontMetrics(font).rectText(insetLabel(), w, a, d);
+
+       int const text_start = int(x + (dim_.wid - w) / 2);
+       int const text_end = text_start + w;
+
+       pi.pain.rectText(text_start, y + d, insetLabel(), font,
+               LColor::none, LColor::none);
+
+       pi.pain.line(x, y, text_start, y,
+                  LColor::pagebreak, Painter::line_onoffdash);
+       pi.pain.line(text_end, y, int(x + dim_.wid), y,
+                  LColor::pagebreak, Painter::line_onoffdash);
+}
+
+
+int InsetPagebreak::latex(Buffer const &, odocstream & os,
+                          OutputParams const &) const
+{
+       os << from_ascii(getCmdName()) << "{}";
+       return 0;
+}
+
+
+int InsetPagebreak::plaintext(Buffer const &, odocstream & os,
+                              OutputParams const &) const
+{
+       os << '\n';
+       return PLAINTEXT_NEWLINE;
+}
+
+
+int InsetPagebreak::docbook(Buffer const &, odocstream & os,
+                            OutputParams const &) const
+{
+       os << '\n';
+       return 0;
+}
+
+
+} // namespace lyx
diff --git a/src/insets/InsetPagebreak.h b/src/insets/InsetPagebreak.h
new file mode 100644 (file)
index 0000000..b018f58
--- /dev/null
@@ -0,0 +1,94 @@
+// -*- C++ -*-
+/**
+ * \file InsetPagebreak.h
+ * 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.
+ */
+
+#ifndef INSET_PAGEBREAK_H
+#define INSET_PAGEBREAK_H
+
+
+#include "Inset.h"
+#include "gettext.h"
+
+
+namespace lyx {
+
+class InsetPagebreak : public InsetOld {
+public:
+       InsetPagebreak() {}
+
+       InsetBase::Code lyxCode() const { return InsetBase::PAGEBREAK_CODE; }
+
+       bool metrics(MetricsInfo &, Dimension &) const;
+
+       void draw(PainterInfo & pi, int x, int y) const;
+
+       int latex(Buffer const &, odocstream &,
+                 OutputParams const &) const;
+
+       int plaintext(Buffer const &, odocstream &,
+                     OutputParams const &) const;
+
+       int docbook(Buffer const &, odocstream &,
+                   OutputParams const &) const;
+
+       void read(Buffer const &, LyXLex & lex);
+
+       virtual void write(Buffer const & buf, std::ostream & os) const;
+       /// We don't need \begin_inset and \end_inset
+       bool directWrite() const { return true; }
+
+       bool display() const { return true; }
+
+       virtual docstring insetLabel() const { return _("Page Break"); }
+
+       virtual std::string getCmdName() const { return "\\newpage"; }
+
+private:
+       virtual std::auto_ptr<InsetBase> doClone() const
+       {
+               return std::auto_ptr<InsetBase>(new InsetPagebreak);
+       }
+};
+
+
+class InsetClearPage : public InsetPagebreak {
+public:
+       InsetClearPage() {}
+
+       docstring insetLabel() const { return _("Clear Page"); }
+       
+       std::string getCmdName() const { return "\\clearpage"; }
+
+private:
+       virtual std::auto_ptr<InsetBase> doClone() const
+       {
+               return std::auto_ptr<InsetBase>(new InsetClearPage);
+       }
+};
+
+
+class InsetClearDoublePage : public InsetPagebreak {
+public:
+       InsetClearDoublePage() {}
+
+       docstring insetLabel() const { return _("Clear Double Page"); }
+       
+       std::string getCmdName() const { return "\\cleardoublepage"; }
+
+private:
+       virtual std::auto_ptr<InsetBase> doClone() const
+       {
+               return std::auto_ptr<InsetBase>(new InsetClearDoublePage);
+       }
+};
+
+} // namespace lyx
+
+#endif // INSET_PAGEBREAK_H
diff --git a/src/mathed/CommandInset.cpp b/src/mathed/CommandInset.cpp
new file mode 100644 (file)
index 0000000..23de2c5
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * \file CommandInset.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 "CommandInset.h"
+#include "MathArray.h"
+#include "MathStream.h"
+#include "dispatchresult.h"
+#include "funcrequest.h"
+
+#include <sstream>
+
+
+namespace lyx {
+
+using std::auto_ptr;
+using std::string;
+
+CommandInset::CommandInset(docstring const & name)
+       : InsetMathNest(2), name_(name), set_label_(false)
+{
+       lock_ = true;
+}
+
+
+auto_ptr<InsetBase> CommandInset::doClone() const
+{
+       return auto_ptr<InsetBase>(new CommandInset(*this));
+}
+
+
+bool CommandInset::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (!set_label_) {
+               set_label_ = true;
+               button_.update(screenLabel(), true);
+       }
+       button_.metrics(mi, dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+InsetBase * CommandInset::editXY(LCursor & cur, int /*x*/, int /*y*/)
+{
+       edit(cur, true);
+       return this;
+}
+
+
+void CommandInset::draw(PainterInfo & pi, int x, int y) const
+{
+       button_.draw(pi, x, y);
+       setPosCache(pi, x, y);
+}
+
+
+void CommandInset::write(WriteStream & os) const
+{
+       os << '\\' << name_.c_str();
+       if (cell(1).size())
+               os << '[' << cell(1) << ']';
+       os << '{' << cell(0) << '}';
+}
+
+
+docstring const CommandInset::screenLabel() const
+{
+       return name_;
+}
+
+} // namespace lyx
diff --git a/src/mathed/CommandInset.h b/src/mathed/CommandInset.h
new file mode 100644 (file)
index 0000000..bac6ddc
--- /dev/null
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+/**
+ * \file CommandInset.h
+ * 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.
+ */
+
+
+#ifndef COMMAND_INSET_H
+#define COMMAND_INSET_H
+
+#include "InsetMathNest.h"
+
+#include "insets/RenderButton.h"
+
+
+namespace lyx {
+
+
+/// Inset for things like \name[options]{contents}
+class CommandInset : public InsetMathNest {
+public:
+       ///
+       explicit CommandInset(docstring const & name);
+       ///
+       bool metrics(MetricsInfo & mi, Dimension & dim) const;
+       ///
+       void draw(PainterInfo & pi, int x, int y) const;
+       ///
+       InsetBase * editXY(LCursor &, int, int);
+       ///
+       void write(WriteStream & os) const;
+       //
+       // void infoize(odocstream & os) const;
+       ///
+       virtual docstring const screenLabel() const;
+       ///
+       docstring const & commandname() const { return name_; }
+private:
+       virtual std::auto_ptr<InsetBase> doClone() const;
+
+       ///
+       docstring name_;
+       ///
+       mutable bool set_label_;
+       ///
+       mutable RenderButton button_;
+};
+
+
+} // namespace lyx
+
+#endif
diff --git a/src/mathed/InsetMathCommand.cpp b/src/mathed/InsetMathCommand.cpp
deleted file mode 100644 (file)
index 23de2c5..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * \file CommandInset.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 "CommandInset.h"
-#include "MathArray.h"
-#include "MathStream.h"
-#include "dispatchresult.h"
-#include "funcrequest.h"
-
-#include <sstream>
-
-
-namespace lyx {
-
-using std::auto_ptr;
-using std::string;
-
-CommandInset::CommandInset(docstring const & name)
-       : InsetMathNest(2), name_(name), set_label_(false)
-{
-       lock_ = true;
-}
-
-
-auto_ptr<InsetBase> CommandInset::doClone() const
-{
-       return auto_ptr<InsetBase>(new CommandInset(*this));
-}
-
-
-bool CommandInset::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       if (!set_label_) {
-               set_label_ = true;
-               button_.update(screenLabel(), true);
-       }
-       button_.metrics(mi, dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-InsetBase * CommandInset::editXY(LCursor & cur, int /*x*/, int /*y*/)
-{
-       edit(cur, true);
-       return this;
-}
-
-
-void CommandInset::draw(PainterInfo & pi, int x, int y) const
-{
-       button_.draw(pi, x, y);
-       setPosCache(pi, x, y);
-}
-
-
-void CommandInset::write(WriteStream & os) const
-{
-       os << '\\' << name_.c_str();
-       if (cell(1).size())
-               os << '[' << cell(1) << ']';
-       os << '{' << cell(0) << '}';
-}
-
-
-docstring const CommandInset::screenLabel() const
-{
-       return name_;
-}
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathCommand.h b/src/mathed/InsetMathCommand.h
deleted file mode 100644 (file)
index bac6ddc..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// -*- C++ -*-
-/**
- * \file CommandInset.h
- * 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.
- */
-
-
-#ifndef COMMAND_INSET_H
-#define COMMAND_INSET_H
-
-#include "InsetMathNest.h"
-
-#include "insets/RenderButton.h"
-
-
-namespace lyx {
-
-
-/// Inset for things like \name[options]{contents}
-class CommandInset : public InsetMathNest {
-public:
-       ///
-       explicit CommandInset(docstring const & name);
-       ///
-       bool metrics(MetricsInfo & mi, Dimension & dim) const;
-       ///
-       void draw(PainterInfo & pi, int x, int y) const;
-       ///
-       InsetBase * editXY(LCursor &, int, int);
-       ///
-       void write(WriteStream & os) const;
-       //
-       // void infoize(odocstream & os) const;
-       ///
-       virtual docstring const screenLabel() const;
-       ///
-       docstring const & commandname() const { return name_; }
-private:
-       virtual std::auto_ptr<InsetBase> doClone() const;
-
-       ///
-       docstring name_;
-       ///
-       mutable bool set_label_;
-       ///
-       mutable RenderButton button_;
-};
-
-
-} // namespace lyx
-
-#endif
diff --git a/src/mathed/InsetMathMacro.cpp b/src/mathed/InsetMathMacro.cpp
deleted file mode 100644 (file)
index 1cde0ec..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/**
- * \file MathMacro.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 "MathMacro.h"
-#include "MathSupport.h"
-#include "MathExtern.h"
-#include "MathStream.h"
-
-#include "buffer.h"
-#include "cursor.h"
-#include "debug.h"
-#include "BufferView.h"
-#include "LaTeXFeatures.h"
-#include "frontends/Painter.h"
-
-
-namespace lyx {
-
-using std::string;
-using std::max;
-using std::auto_ptr;
-using std::endl;
-using std::vector;
-
-
-/// This class is the value of a macro argument, technically 
-/// a wrapper of the cells of MathMacro.
-class MathMacroArgumentValue : public InsetMathDim {
-public:
-       ///
-       MathMacroArgumentValue(MathArray const * value, docstring const & macroName) 
-               : value_(value), macroName_(macroName) {}
-       ///
-       bool metrics(MetricsInfo & mi, Dimension & dim) const;
-       ///
-       void draw(PainterInfo &, int x, int y) const;
-       
-private:
-       std::auto_ptr<InsetBase> doClone() const;
-       MathArray const * value_;
-       docstring macroName_;
-};
-
-
-auto_ptr<InsetBase> MathMacroArgumentValue::doClone() const 
-{
-       return auto_ptr<InsetBase>(new MathMacroArgumentValue(*this));
-}
-
-
-bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const 
-{
-       // unlock outer macro in arguments, and lock it again later
-       MacroTable::globalMacros().get(macroName_).unlock();
-       value_->metrics(mi, dim);
-       MacroTable::globalMacros().get(macroName_).lock();
-       metricsMarkers2(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void MathMacroArgumentValue::draw(PainterInfo & pi, int x, int y) const 
-{
-       // unlock outer macro in arguments, and lock it again later
-       MacroTable::globalMacros().get(macroName_).unlock();
-       value_->draw(pi, x, y);
-       MacroTable::globalMacros().get(macroName_).lock();
-}
-
-
-MathMacro::MathMacro(docstring const & name, int numargs)
-       : InsetMathNest(numargs), name_(name)
-{}
-
-
-auto_ptr<InsetBase> MathMacro::doClone() const
-{
-       return auto_ptr<InsetBase>(new MathMacro(*this));
-}
-
-
-docstring MathMacro::name() const
-{
-       return name_;
-}
-
-
-void MathMacro::cursorPos(BufferView const & bv,
-               CursorSlice const & sl, bool boundary, int & x, int & y) const
-{
-       // We may have 0 arguments, but InsetMathNest requires at least one.
-       if (nargs() > 0)
-               InsetMathNest::cursorPos(bv, sl, boundary, x, y);
-}
-
-
-bool MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       if (!MacroTable::globalMacros().has(name())) {
-               mathed_string_dim(mi.base.font, "Unknown: " + name(), dim);
-       } else {
-               MacroData const & macro = MacroTable::globalMacros().get(name());
-               if (macro.locked()) {
-                       mathed_string_dim(mi.base.font, "Self reference: " + name(), dim);
-                       expanded_ = MathArray();
-               } else if (editing(mi.base.bv)) {
-                       // FIXME UNICODE
-                       asArray(macro.def(), tmpl_);
-                       LyXFont font = mi.base.font;
-                       augmentFont(font, from_ascii("lyxtex"));
-                       tmpl_.metrics(mi, dim);
-                       // FIXME UNICODE
-                       dim.wid += mathed_string_width(font, name()) + 10;
-                       // FIXME UNICODE
-                       int ww = mathed_string_width(font, from_ascii("#1: "));
-                       for (idx_type i = 0; i < nargs(); ++i) {
-                               MathArray const & c = cell(i);
-                               c.metrics(mi);
-                               dim.wid  = max(dim.wid, c.width() + ww);
-                               dim.des += c.height() + 10;
-                       }
-               } else {
-                       // create MathMacroArgumentValue object pointing to the cells of the macro
-                       MacroData const & macro = MacroTable::globalMacros().get(name());
-                       vector<MathArray> values(nargs());
-                       for (size_t i = 0; i != nargs(); ++i) 
-                               values[i].insert(0, MathAtom(new MathMacroArgumentValue(&cells_[i], name())));
-                       macro.expand(values, expanded_);
-                       
-                       MacroTable::globalMacros().get(name()).lock();
-                       expanded_.metrics(mi, dim);
-                       MacroTable::globalMacros().get(name()).unlock();
-               }
-       }
-       metricsMarkers2(dim);
-       if (dim_ == dim)
-               return false;
-       dim_ = dim;
-       return true;
-}
-
-
-void MathMacro::draw(PainterInfo & pi, int x, int y) const
-{
-       if (!MacroTable::globalMacros().has(name())) {
-               // FIXME UNICODE
-               drawStrRed(pi, x, y, "Unknown: " + name());
-       } else {
-               MacroData const & macro = MacroTable::globalMacros().get(name());
-               if (macro.locked()) {
-                       // FIXME UNICODE
-                       drawStrRed(pi, x, y, "Self reference: " + name());
-               } else if (editing(pi.base.bv)) {
-                       LyXFont font = pi.base.font;
-                       augmentFont(font, from_ascii("lyxtex"));
-                       int h = y - dim_.ascent() + 2 + tmpl_.ascent();
-                       pi.pain.text(x + 3, h, name(), font);
-                       int const w = mathed_string_width(font, name());
-                       tmpl_.draw(pi, x + w + 12, h);
-                       h += tmpl_.descent();
-                       Dimension ldim;
-                       docstring t = from_ascii("#1: ");
-                       mathed_string_dim(font, t, ldim);
-                       for (idx_type i = 0; i < nargs(); ++i) {
-                               MathArray const & c = cell(i);
-                               h += max(c.ascent(), ldim.asc) + 5;
-                               c.draw(pi, x + ldim.wid, h);
-                               char_type str[] = { '#', '1', ':', '\0' };
-                               str[1] += static_cast<char_type>(i);
-                               pi.pain.text(x + 3, h, str, font);
-                               h += max(c.descent(), ldim.des) + 5;
-                       }
-               } else {
-                       MacroTable::globalMacros().get(name()).lock();
-                       expanded_.draw(pi, x, y);
-                       MacroTable::globalMacros().get(name()).unlock();
-               }
-       }
-       drawMarkers2(pi, x, y);
-}
-
-
-void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
-{
-       // We may have 0 arguments, but InsetMathNest requires at least one.
-       if (nargs() > 0)
-               InsetMathNest::drawSelection(pi, x, y);
-}
-
-
-void MathMacro::validate(LaTeXFeatures & features) const
-{
-       if (name() == "binom" || name() == "mathcircumflex")
-               features.require(to_utf8(name()));
-}
-
-
-InsetBase * MathMacro::editXY(LCursor & cur, int x, int y)
-{
-       // We may have 0 arguments, but InsetMathNest requires at least one.
-       if (nargs() > 0) {
-               // Prevent crash due to cold coordcache
-               // FIXME: This is only a workaround, the call of
-               // InsetMathNest::editXY is correct. The correct fix would
-               // ensure that the coordcache of the arguments is valid.
-               if (!editing(&cur.bv())) {
-                       edit(cur, true);
-                       return this;
-               }
-               return InsetMathNest::editXY(cur, x, y);
-       }
-       return this;
-}
-
-
-bool MathMacro::idxFirst(LCursor & cur) const 
-{
-       cur.updateFlags(Update::Force);
-       return InsetMathNest::idxFirst(cur);
-}
-
-
-bool MathMacro::idxLast(LCursor & cur) const 
-{
-       cur.updateFlags(Update::Force);
-       return InsetMathNest::idxLast(cur);
-}
-
-
-bool MathMacro::notifyCursorLeaves(LCursor & cur)
-{
-       cur.updateFlags(Update::Force);
-       return InsetMathNest::notifyCursorLeaves(cur);
-}
-
-
-void MathMacro::maple(MapleStream & os) const
-{
-       updateExpansion();
-       lyx::maple(expanded_, os);
-}
-
-
-void MathMacro::mathmlize(MathStream & os) const
-{
-       updateExpansion();
-       lyx::mathmlize(expanded_, os);
-}
-
-
-void MathMacro::octave(OctaveStream & os) const
-{
-       updateExpansion();
-       lyx::octave(expanded_, os);
-}
-
-
-void MathMacro::updateExpansion() const
-{
-       //expanded_.substitute(*this);
-}
-
-
-void MathMacro::infoize(odocstream & os) const
-{
-       os << "Macro: " << name();
-}
-
-
-void MathMacro::infoize2(odocstream & os) const
-{
-       os << "Macro: " << name();
-
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/InsetMathMacro.h b/src/mathed/InsetMathMacro.h
deleted file mode 100644 (file)
index b4ff0a4..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// -*- C++ -*-
-/**
- * \file MathMacro.h
- * 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.
- */
-
-#ifndef MATH_MACRO_H
-#define MATH_MACRO_H
-
-#include "InsetMathNest.h"
-#include "MathArray.h"
-#include "InsetMathNest.h"
-#include "MathMacroTable.h"
-
-
-namespace lyx {
-
-
-/// This class contains the data for a macro.
-class MathMacro : public InsetMathNest {
-public:
-       /// A macro can be built from an existing template
-       MathMacro(docstring const & name, int numargs);
-       ///
-       void draw(PainterInfo & pi, int x, int y) const;
-       ///
-       void drawExpanded(PainterInfo & pi, int x, int y) const;
-       /// draw selection background
-       void drawSelection(PainterInfo & pi, int x, int y) const;
-       /// draw decorations.
-       void drawDecoration(PainterInfo & pi, int x, int y) const
-       { drawMarkers2(pi, x, y); }
-       ///
-       bool metrics(MetricsInfo & mi, Dimension & dim) const;
-       /// get cursor position
-       void cursorPos(BufferView const & bv, CursorSlice const & sl,
-               bool boundary, int & x, int & y) const;
-       ///
-       InsetBase * editXY(LCursor & cur, int x, int y);
-       /// target pos when we enter the inset from the left by pressing "Right"
-       bool idxFirst(LCursor &) const;
-       /// target pos when we enter the inset from the right by pressing "Left"
-       bool idxLast(LCursor &) const;
-       ///
-       virtual bool notifyCursorLeaves(LCursor &);
-       ///
-       docstring name() const;
-       ///
-       void setExpansion(MathArray const & exp, MathArray const & args) const;
-
-       ///
-       void validate(LaTeXFeatures &) const;
-
-       ///
-       void maple(MapleStream &) const;
-       ///
-       void mathmlize(MathStream &) const;
-       ///
-       void octave(OctaveStream &) const;
-       ///
-       void infoize(odocstream &) const;
-       ///
-       void infoize2(odocstream &) const;
-
-private:
-       virtual std::auto_ptr<InsetBase> doClone() const;
-       ///
-       void updateExpansion() const;
-       ///
-       void expand() const;
-
-       /// name of macro
-       docstring name_;
-       /// the unexpanded macro defintition
-       mutable MathArray tmpl_;
-       /// the macro substituted with our args
-       mutable MathArray expanded_;
-};
-
-
-
-
-} // namespace lyx
-#endif
diff --git a/src/mathed/MathArray.cpp b/src/mathed/MathArray.cpp
new file mode 100644 (file)
index 0000000..805f8b5
--- /dev/null
@@ -0,0 +1,485 @@
+/**
+ * \file MathArray.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 "MathArray.h"
+#include "InsetMathFont.h"
+#include "InsetMathScript.h"
+#include "MathMacro.h"
+#include "MathMacroTable.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+#include "ReplaceData.h"
+
+#include "BufferView.h"
+#include "buffer.h"
+#include "cursor.h"
+#include "debug.h"
+#include "LColor.h"
+
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
+#include <boost/assert.hpp>
+
+
+namespace lyx {
+
+using std::abs;
+using std::endl;
+using std::min;
+using std::ostringstream;
+using std::string;
+using std::vector;
+
+
+MathArray::MathArray(const_iterator from, const_iterator to)
+       : base_type(from, to)
+{}
+
+
+MathAtom & MathArray::operator[](pos_type pos)
+{
+       BOOST_ASSERT(pos < size());
+       return base_type::operator[](pos);
+}
+
+
+MathAtom const & MathArray::operator[](pos_type pos) const
+{
+       BOOST_ASSERT(pos < size());
+       return base_type::operator[](pos);
+}
+
+
+void MathArray::insert(size_type pos, MathAtom const & t)
+{
+       base_type::insert(begin() + pos, t);
+}
+
+
+void MathArray::insert(size_type pos, MathArray const & ar)
+{
+       BOOST_ASSERT(pos <= size());
+       base_type::insert(begin() + pos, ar.begin(), ar.end());
+}
+
+
+void MathArray::append(MathArray const & ar)
+{
+       insert(size(), ar);
+}
+
+
+void MathArray::erase(size_type pos)
+{
+       if (pos < size())
+               erase(pos, pos + 1);
+}
+
+
+void MathArray::erase(iterator pos1, iterator pos2)
+{
+       base_type::erase(pos1, pos2);
+}
+
+
+void MathArray::erase(iterator pos)
+{
+       base_type::erase(pos);
+}
+
+
+void MathArray::erase(size_type pos1, size_type pos2)
+{
+       base_type::erase(begin() + pos1, begin() + pos2);
+}
+
+
+void MathArray::dump2() const
+{
+       odocstringstream os;
+       NormalStream ns(os);
+       for (const_iterator it = begin(); it != end(); ++it)
+               ns << *it << ' ';
+       lyxerr << to_utf8(os.str());
+}
+
+
+void MathArray::dump() const
+{
+       odocstringstream os;
+       NormalStream ns(os);
+       for (const_iterator it = begin(); it != end(); ++it)
+               ns << '<' << *it << '>';
+       lyxerr << to_utf8(os.str());
+}
+
+
+void MathArray::validate(LaTeXFeatures & features) const
+{
+       for (const_iterator it = begin(); it != end(); ++it)
+               (*it)->validate(features);
+}
+
+
+bool MathArray::match(MathArray const & ar) const
+{
+       return size() == ar.size() && matchpart(ar, 0);
+}
+
+
+bool MathArray::matchpart(MathArray const & ar, pos_type pos) const
+{
+       if (size() < ar.size() + pos)
+               return false;
+       const_iterator it = begin() + pos;
+       for (const_iterator jt = ar.begin(); jt != ar.end(); ++jt, ++it)
+               if (asString(*it) != asString(*jt))
+                       return false;
+       return true;
+}
+
+
+void MathArray::replace(ReplaceData & rep)
+{
+       for (size_type i = 0; i < size(); ++i) {
+               if (find1(rep.from, i)) {
+                       // match found
+                       lyxerr << "match found!" << endl;
+                       erase(i, i + rep.from.size());
+                       insert(i, rep.to);
+               }
+       }
+
+#ifdef WITH_WARNINGS
+#warning temporarily disabled
+       // for (const_iterator it = begin(); it != end(); ++it)
+       //      it->nucleus()->replace(rep);
+#endif
+}
+
+
+bool MathArray::find1(MathArray const & ar, size_type pos) const
+{
+       lyxerr << "finding '" << ar << "' in '" << *this << "'" << endl;
+       for (size_type i = 0, n = ar.size(); i < n; ++i)
+               if (asString(operator[](pos + i)) != asString(ar[i]))
+                       return false;
+       return true;
+}
+
+
+MathArray::size_type MathArray::find(MathArray const & ar) const
+{
+       for (int i = 0, last = size() - ar.size(); i < last; ++i)
+               if (find1(ar, i))
+                       return i;
+       return size();
+}
+
+
+MathArray::size_type MathArray::find_last(MathArray const & ar) const
+{
+       for (int i = size() - ar.size(); i >= 0; --i)
+               if (find1(ar, i))
+                       return i;
+       return size();
+}
+
+
+bool MathArray::contains(MathArray const & ar) const
+{
+       if (find(ar) != size())
+               return true;
+       for (const_iterator it = begin(); it != end(); ++it)
+               if ((*it)->contains(ar))
+                       return true;
+       return false;
+}
+
+
+void MathArray::touch() const
+{
+}
+
+
+bool MathArray::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       dim = dim_;
+       metrics(mi);
+       if (dim_ == dim)
+               return false;
+       dim = dim_;
+       return true;
+}
+
+
+namespace {
+
+bool isInside(DocIterator const & it, MathArray const & ar,
+       pos_type p1, pos_type p2)
+{
+       for (size_t i = 0; i != it.depth(); ++i) {
+               CursorSlice const & sl = it[i];
+               if (sl.inset().inMathed() && &sl.cell() == &ar)
+                       return p1 <= sl.pos() && sl.pos() < p2;
+       }
+       return false;
+}
+
+}
+
+
+
+void MathArray::metrics(MetricsInfo & mi) const
+{
+       frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
+       dim_ = fm.dimension('I');
+       int xascent = fm.dimension('x').ascent();
+       if (xascent >= dim_.asc)
+               xascent = (2 * dim_.asc) / 3;
+       minasc_ = xascent;
+       mindes_ = (3 * xascent) / 4;
+       slevel_ = (4 * xascent) / 5;
+       sshift_ = xascent / 4;
+       kerning_ = 0;
+
+       if (empty())
+               return;
+
+       dim_.asc = 0;
+       dim_.wid = 0;
+       Dimension d;
+       //BufferView & bv  = *mi.base.bv;
+       //Buffer const & buf = *bv.buffer();
+       for (size_t i = 0, n = size(); i != n; ++i) {
+               MathAtom const & at = operator[](i);
+#if 0
+               MathMacro const * mac = at->asMacro();
+               if (mac && buf.hasMacro(mac->name())) {
+                       MacroData const & tmpl = buf.getMacro(mac->name());
+                       int numargs = tmpl.numargs();
+                       if (i + numargs > n)
+                               numargs = n - i - 1;
+                       lyxerr << "metrics:found macro: " << mac->name()
+                               << " numargs: " << numargs << endl;
+                       if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
+                               MathArray args(begin() + i + 1, begin() + i + numargs + 1);
+                               MathArray exp;
+                               tmpl.expand(args, exp);
+                               mac->setExpansion(exp, args);
+                               mac->metricsExpanded(mi, d);
+                               dim_.wid += mac->widthExpanded();
+                               i += numargs;
+                               continue;
+                       }
+               }
+#endif
+               at->metrics(mi, d);
+               dim_ += d;
+               if (i == n - 1)
+                       kerning_ = at->kerning();
+       }
+}
+
+
+void MathArray::draw(PainterInfo & pi, int x, int y) const
+{
+       //lyxerr << "MathArray::draw: x: " << x << " y: " << y << endl;
+       BufferView & bv  = *pi.base.bv;
+       setXY(bv, x, y);
+
+       if (empty()) {
+               pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
+               return;
+       }
+
+       // don't draw outside the workarea
+       if (y + descent() <= 0
+               || y - ascent() >= bv.workHeight()
+               || x + width() <= 0
+               || x >= bv. workWidth())
+               return;
+
+       for (size_t i = 0, n = size(); i != n; ++i) {
+               MathAtom const & at = operator[](i);
+#if 0
+       Buffer const & buf = bv.buffer();
+               // special macro handling
+               MathMacro const * mac = at->asMacro();
+               if (mac && buf.hasMacro(mac->name())) {
+                       MacroData const & tmpl = buf.getMacro(mac->name());
+                       int numargs = tmpl.numargs();
+                       if (i + numargs > n)
+                               numargs = n - i - 1;
+                       if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
+                               mac->drawExpanded(pi, x, y);
+                               x += mac->widthExpanded();
+                               i += numargs;
+                               continue;
+                       }
+               }
+#endif
+               bv.coordCache().insets().add(at.nucleus(), x, y);
+               at->drawSelection(pi, x, y);
+               at->draw(pi, x, y);
+               x += at->width();
+       }
+}
+
+
+void MathArray::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       dim.clear();
+       Dimension d;
+       for (const_iterator it = begin(); it != end(); ++it) {
+               (*it)->metricsT(mi, d);
+               dim += d;
+       }
+}
+
+
+void MathArray::drawT(TextPainter & pain, int x, int y) const
+{
+       //lyxerr << "x: " << x << " y: " << y << ' ' << pain.workAreaHeight() << endl;
+
+       // FIXME: Abdel 16/10/2006
+       // This drawT() method is never used, this is dead code.
+
+       for (const_iterator it = begin(), et = end(); it != et; ++it) {
+               (*it)->drawT(pain, x, y);
+               //x += (*it)->width_;
+               x += 2;
+       }
+}
+
+
+int MathArray::pos2x(size_type pos) const
+{
+       return pos2x(pos, 0);
+}
+
+
+int MathArray::pos2x(size_type pos, int glue) const
+{
+       int x = 0;
+       size_type target = min(pos, size());
+       for (size_type i = 0; i < target; ++i) {
+               const_iterator it = begin() + i;
+               if ((*it)->getChar() == ' ')
+                       x += glue;
+               //lyxerr << "char: " << (*it)->getChar()
+               //      << "width: " << (*it)->width() << std::endl;
+               x += (*it)->width();
+       }
+       return x;
+}
+
+
+MathArray::size_type MathArray::x2pos(int targetx) const
+{
+       return x2pos(targetx, 0);
+}
+
+
+MathArray::size_type MathArray::x2pos(int targetx, int glue) const
+{
+       const_iterator it = begin();
+       int lastx = 0;
+       int currx = 0;
+       // find first position after targetx
+       for (; currx < targetx && it < end(); ++it) {
+               lastx = currx;
+               if ((*it)->getChar() == ' ')
+                       currx += glue;
+               currx += (*it)->width();
+       }
+
+       /**
+        * If we are not at the beginning of the array, go to the left
+        * of the inset if one of the following two condition holds:
+        * - the current inset is editable (so that the cursor tip is
+        *   deeper than us): in this case, we want all intermediate
+        *   cursor slices to be before insets;
+        * - the mouse is closer to the left side of the inset than to
+        *   the right one.
+        * See bug 1918 for details.
+        **/
+       if (it != begin() && currx >= targetx
+           && ((*boost::prior(it))->asNestInset()
+               || abs(lastx - targetx) < abs(currx - targetx))) {
+               --it;
+       }
+
+       return it - begin();
+}
+
+
+int MathArray::dist(BufferView const & bv, int x, int y) const
+{
+       int xx = 0;
+       int yy = 0;
+
+       const int xo_ = xo(bv);
+       const int yo_ = yo(bv);
+
+       if (x < xo_)
+               xx = xo_ - x;
+       else if (x > xo_ + width())
+               xx = x - xo_ - width();
+
+       if (y < yo_ - ascent())
+               yy = yo_ - ascent() - y;
+       else if (y > yo_ + descent())
+               yy = y - yo_ - descent();
+
+       return xx + yy;
+}
+
+
+void MathArray::setXY(BufferView & bv, int x, int y) const
+{
+       //lyxerr << "setting position cache for MathArray " << this << std::endl;
+       bv.coordCache().arrays().add(this, x, y);
+}
+
+
+int MathArray::xo(BufferView const & bv) const
+{
+       return bv.coordCache().getArrays().x(this);
+}
+
+
+int MathArray::yo(BufferView const & bv) const
+{
+       return bv.coordCache().getArrays().y(this);
+}
+
+
+std::ostream & operator<<(std::ostream & os, MathArray const & ar)
+{
+       odocstringstream oss;
+       NormalStream ns(oss);
+       ns << ar;
+       return os << to_utf8(oss.str());
+}
+
+
+odocstream & operator<<(odocstream & os, MathArray const & ar)
+{
+       NormalStream ns(os);
+       ns << ar;
+       return os;
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathArray.h b/src/mathed/MathArray.h
new file mode 100644 (file)
index 0000000..5582a46
--- /dev/null
@@ -0,0 +1,188 @@
+// -*- C++ -*-
+/**
+ * \file MathArray.h
+ * 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
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef MATH_DATA_H
+#define MATH_DATA_H
+
+#include <vector>
+
+#include "MathAtom.h"
+#include "dimension.h"
+
+#include "support/docstream.h"
+
+
+namespace lyx {
+
+class BufferView;
+class LaTeXFeatures;
+class ReplaceData;
+class MetricsInfo;
+class PainterInfo;
+class TextMetricsInfo;
+class TextPainter;
+
+
+class MathArray : private std::vector<MathAtom> {
+public:
+       /// re-use inhertited stuff
+       typedef std::vector<MathAtom> base_type;
+       using base_type::const_iterator;
+       using base_type::iterator;
+       using base_type::size_type;
+       using base_type::difference_type;
+       using base_type::size;
+       using base_type::empty;
+       using base_type::clear;
+       using base_type::begin;
+       using base_type::end;
+       using base_type::push_back;
+       using base_type::pop_back;
+       using base_type::back;
+       using base_type::front;
+       ///
+       typedef size_type idx_type;
+       typedef size_type pos_type;
+
+public:
+       ///
+       MathArray() {}
+       ///
+       MathArray(const_iterator from, const_iterator to);
+       ///
+       void append(MathArray const & ar);
+
+       /// inserts single atom at position pos
+       void insert(size_type pos, MathAtom const & at);
+       /// inserts multiple atoms at position pos
+       void insert(size_type pos, MathArray const & ar);
+
+       /// erase range from pos1 to pos2
+       void erase(iterator pos1, iterator pos2);
+       /// erase single atom
+       void erase(iterator pos);
+       /// erase range from pos1 to pos2
+       void erase(size_type pos1, size_type pos2);
+       /// erase single atom
+       void erase(size_type pos);
+
+       ///
+       void dump() const;
+       ///
+       void dump2() const;
+       ///
+       void replace(ReplaceData &);
+       ///
+       void substitute(MathArray const & m);
+
+       /// looks for exact match
+       bool match(MathArray const & ar) const;
+       /// looks for inclusion match starting at pos
+       bool matchpart(MathArray const & ar, pos_type pos) const;
+       /// looks for containment, return == size mean not found
+       size_type find(MathArray const & ar) const;
+       /// looks for containment, return == size mean not found
+       size_type find_last(MathArray const & ar) const;
+       ///
+       bool contains(MathArray const & ar) const;
+       ///
+       void validate(LaTeXFeatures &) const;
+
+       /// checked write access
+       MathAtom & operator[](pos_type);
+       /// checked read access
+       MathAtom const & operator[](pos_type) const;
+       /// rebuild cached metrics information
+       void metrics(MetricsInfo & mi) const;
+       /// rebuild cached metrics information
+       bool metrics(MetricsInfo & mi, Dimension & dim) const;
+       /// redraw cell using cache metrics information
+       void draw(PainterInfo & pi, int x, int y) const;
+       /// rebuild cached metrics information
+       void metricsT(TextMetricsInfo const & mi, Dimension & dim) const;
+       /// redraw cell using cache metrics information
+       void drawT(TextPainter & pi, int x, int y) const;
+       /// mark cell for re-drawing
+       void touch() const;
+
+       /// access to cached x coordinate of last drawing
+       int xo(BufferView const & bv) const;
+       /// access to cached y coordinate of last drawing
+       int yo(BufferView const & bv) const;
+       /// access to cached x coordinate of mid point of last drawing
+       int xm(BufferView const & bv) const { return xo(bv) + dim_.wid / 2; }
+       /// access to cached y coordinate of mid point of last drawing
+       int ym(BufferView const & bv) const { return yo(bv) + (dim_.des - dim_.asc) / 2; }
+       /// write access to coordinate;
+       void setXY(BufferView & bv, int x, int y) const;
+       /// returns x coordinate of given position in the array
+       int pos2x(size_type pos) const;
+       /// returns position of given x coordinate
+       int pos2x(size_type pos, int glue) const;
+       /// returns position of given x coordinate
+       size_type x2pos(int pos) const;
+       /// returns position of given x coordinate fstarting from a certain pos
+       size_type x2pos(int targetx, int glue) const;
+       /// returns distance of this cell to the point given by x and y
+       // assumes valid position and size cache
+       int dist(BufferView const & bv, int x, int y) const;
+
+       /// ascent of this cell above the baseline
+       int ascent() const { return dim_.asc; }
+       /// descent of this cell below the baseline
+       int descent() const { return dim_.des; }
+       /// height of the cell
+       int height() const { return dim_.asc + dim_.des; }
+       /// width of this cell
+       int width() const { return dim_.wid; }
+       /// dimensions of cell
+       Dimension const & dim() const { return dim_; }
+       /// dimensions of cell
+       void setDim(Dimension const & d) const { dim_ = d; }
+       /// minimum ascent offset for superscript
+       int minasc() const { return minasc_; }
+       /// minimum descent offset for subscript
+       int mindes() const { return mindes_; }
+       /// level above/below which super/subscript should extend
+       int slevel() const { return slevel_; }
+       /// additional super/subscript shift
+       int sshift() const { return sshift_; }
+       /// superscript kerning
+       int kerning() const { return kerning_; }
+       /// 
+       void swap(MathArray & ar) { base_type::swap(ar); }
+
+protected:
+       /// cached dimensions of cell
+       mutable Dimension dim_;
+       /// cached values for super/subscript placement
+       mutable int minasc_;
+       mutable int mindes_;
+       mutable int slevel_;
+       mutable int sshift_;
+       mutable int kerning_;
+
+private:
+       /// is this an exact match at this position?
+       bool find1(MathArray const & ar, size_type pos) const;
+};
+
+///
+std::ostream & operator<<(std::ostream & os, MathArray const & ar);
+///
+odocstream & operator<<(odocstream & os, MathArray const & ar);
+
+
+} // namespace lyx
+
+#endif
diff --git a/src/mathed/MathData.cpp b/src/mathed/MathData.cpp
deleted file mode 100644 (file)
index 805f8b5..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-/**
- * \file MathArray.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 "MathArray.h"
-#include "InsetMathFont.h"
-#include "InsetMathScript.h"
-#include "MathMacro.h"
-#include "MathMacroTable.h"
-#include "MathStream.h"
-#include "MathSupport.h"
-#include "ReplaceData.h"
-
-#include "BufferView.h"
-#include "buffer.h"
-#include "cursor.h"
-#include "debug.h"
-#include "LColor.h"
-
-#include "frontends/FontMetrics.h"
-#include "frontends/Painter.h"
-
-#include <boost/assert.hpp>
-
-
-namespace lyx {
-
-using std::abs;
-using std::endl;
-using std::min;
-using std::ostringstream;
-using std::string;
-using std::vector;
-
-
-MathArray::MathArray(const_iterator from, const_iterator to)
-       : base_type(from, to)
-{}
-
-
-MathAtom & MathArray::operator[](pos_type pos)
-{
-       BOOST_ASSERT(pos < size());
-       return base_type::operator[](pos);
-}
-
-
-MathAtom const & MathArray::operator[](pos_type pos) const
-{
-       BOOST_ASSERT(pos < size());
-       return base_type::operator[](pos);
-}
-
-
-void MathArray::insert(size_type pos, MathAtom const & t)
-{
-       base_type::insert(begin() + pos, t);
-}
-
-
-void MathArray::insert(size_type pos, MathArray const & ar)
-{
-       BOOST_ASSERT(pos <= size());
-       base_type::insert(begin() + pos, ar.begin(), ar.end());
-}
-
-
-void MathArray::append(MathArray const & ar)
-{
-       insert(size(), ar);
-}
-
-
-void MathArray::erase(size_type pos)
-{
-       if (pos < size())
-               erase(pos, pos + 1);
-}
-
-
-void MathArray::erase(iterator pos1, iterator pos2)
-{
-       base_type::erase(pos1, pos2);
-}
-
-
-void MathArray::erase(iterator pos)
-{
-       base_type::erase(pos);
-}
-
-
-void MathArray::erase(size_type pos1, size_type pos2)
-{
-       base_type::erase(begin() + pos1, begin() + pos2);
-}
-
-
-void MathArray::dump2() const
-{
-       odocstringstream os;
-       NormalStream ns(os);
-       for (const_iterator it = begin(); it != end(); ++it)
-               ns << *it << ' ';
-       lyxerr << to_utf8(os.str());
-}
-
-
-void MathArray::dump() const
-{
-       odocstringstream os;
-       NormalStream ns(os);
-       for (const_iterator it = begin(); it != end(); ++it)
-               ns << '<' << *it << '>';
-       lyxerr << to_utf8(os.str());
-}
-
-
-void MathArray::validate(LaTeXFeatures & features) const
-{
-       for (const_iterator it = begin(); it != end(); ++it)
-               (*it)->validate(features);
-}
-
-
-bool MathArray::match(MathArray const & ar) const
-{
-       return size() == ar.size() && matchpart(ar, 0);
-}
-
-
-bool MathArray::matchpart(MathArray const & ar, pos_type pos) const
-{
-       if (size() < ar.size() + pos)
-               return false;
-       const_iterator it = begin() + pos;
-       for (const_iterator jt = ar.begin(); jt != ar.end(); ++jt, ++it)
-               if (asString(*it) != asString(*jt))
-                       return false;
-       return true;
-}
-
-
-void MathArray::replace(ReplaceData & rep)
-{
-       for (size_type i = 0; i < size(); ++i) {
-               if (find1(rep.from, i)) {
-                       // match found
-                       lyxerr << "match found!" << endl;
-                       erase(i, i + rep.from.size());
-                       insert(i, rep.to);
-               }
-       }
-
-#ifdef WITH_WARNINGS
-#warning temporarily disabled
-       // for (const_iterator it = begin(); it != end(); ++it)
-       //      it->nucleus()->replace(rep);
-#endif
-}
-
-
-bool MathArray::find1(MathArray const & ar, size_type pos) const
-{
-       lyxerr << "finding '" << ar << "' in '" << *this << "'" << endl;
-       for (size_type i = 0, n = ar.size(); i < n; ++i)
-               if (asString(operator[](pos + i)) != asString(ar[i]))
-                       return false;
-       return true;
-}
-
-
-MathArray::size_type MathArray::find(MathArray const & ar) const
-{
-       for (int i = 0, last = size() - ar.size(); i < last; ++i)
-               if (find1(ar, i))
-                       return i;
-       return size();
-}
-
-
-MathArray::size_type MathArray::find_last(MathArray const & ar) const
-{
-       for (int i = size() - ar.size(); i >= 0; --i)
-               if (find1(ar, i))
-                       return i;
-       return size();
-}
-
-
-bool MathArray::contains(MathArray const & ar) const
-{
-       if (find(ar) != size())
-               return true;
-       for (const_iterator it = begin(); it != end(); ++it)
-               if ((*it)->contains(ar))
-                       return true;
-       return false;
-}
-
-
-void MathArray::touch() const
-{
-}
-
-
-bool MathArray::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       dim = dim_;
-       metrics(mi);
-       if (dim_ == dim)
-               return false;
-       dim = dim_;
-       return true;
-}
-
-
-namespace {
-
-bool isInside(DocIterator const & it, MathArray const & ar,
-       pos_type p1, pos_type p2)
-{
-       for (size_t i = 0; i != it.depth(); ++i) {
-               CursorSlice const & sl = it[i];
-               if (sl.inset().inMathed() && &sl.cell() == &ar)
-                       return p1 <= sl.pos() && sl.pos() < p2;
-       }
-       return false;
-}
-
-}
-
-
-
-void MathArray::metrics(MetricsInfo & mi) const
-{
-       frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
-       dim_ = fm.dimension('I');
-       int xascent = fm.dimension('x').ascent();
-       if (xascent >= dim_.asc)
-               xascent = (2 * dim_.asc) / 3;
-       minasc_ = xascent;
-       mindes_ = (3 * xascent) / 4;
-       slevel_ = (4 * xascent) / 5;
-       sshift_ = xascent / 4;
-       kerning_ = 0;
-
-       if (empty())
-               return;
-
-       dim_.asc = 0;
-       dim_.wid = 0;
-       Dimension d;
-       //BufferView & bv  = *mi.base.bv;
-       //Buffer const & buf = *bv.buffer();
-       for (size_t i = 0, n = size(); i != n; ++i) {
-               MathAtom const & at = operator[](i);
-#if 0
-               MathMacro const * mac = at->asMacro();
-               if (mac && buf.hasMacro(mac->name())) {
-                       MacroData const & tmpl = buf.getMacro(mac->name());
-                       int numargs = tmpl.numargs();
-                       if (i + numargs > n)
-                               numargs = n - i - 1;
-                       lyxerr << "metrics:found macro: " << mac->name()
-                               << " numargs: " << numargs << endl;
-                       if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
-                               MathArray args(begin() + i + 1, begin() + i + numargs + 1);
-                               MathArray exp;
-                               tmpl.expand(args, exp);
-                               mac->setExpansion(exp, args);
-                               mac->metricsExpanded(mi, d);
-                               dim_.wid += mac->widthExpanded();
-                               i += numargs;
-                               continue;
-                       }
-               }
-#endif
-               at->metrics(mi, d);
-               dim_ += d;
-               if (i == n - 1)
-                       kerning_ = at->kerning();
-       }
-}
-
-
-void MathArray::draw(PainterInfo & pi, int x, int y) const
-{
-       //lyxerr << "MathArray::draw: x: " << x << " y: " << y << endl;
-       BufferView & bv  = *pi.base.bv;
-       setXY(bv, x, y);
-
-       if (empty()) {
-               pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
-               return;
-       }
-
-       // don't draw outside the workarea
-       if (y + descent() <= 0
-               || y - ascent() >= bv.workHeight()
-               || x + width() <= 0
-               || x >= bv. workWidth())
-               return;
-
-       for (size_t i = 0, n = size(); i != n; ++i) {
-               MathAtom const & at = operator[](i);
-#if 0
-       Buffer const & buf = bv.buffer();
-               // special macro handling
-               MathMacro const * mac = at->asMacro();
-               if (mac && buf.hasMacro(mac->name())) {
-                       MacroData const & tmpl = buf.getMacro(mac->name());
-                       int numargs = tmpl.numargs();
-                       if (i + numargs > n)
-                               numargs = n - i - 1;
-                       if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
-                               mac->drawExpanded(pi, x, y);
-                               x += mac->widthExpanded();
-                               i += numargs;
-                               continue;
-                       }
-               }
-#endif
-               bv.coordCache().insets().add(at.nucleus(), x, y);
-               at->drawSelection(pi, x, y);
-               at->draw(pi, x, y);
-               x += at->width();
-       }
-}
-
-
-void MathArray::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
-{
-       dim.clear();
-       Dimension d;
-       for (const_iterator it = begin(); it != end(); ++it) {
-               (*it)->metricsT(mi, d);
-               dim += d;
-       }
-}
-
-
-void MathArray::drawT(TextPainter & pain, int x, int y) const
-{
-       //lyxerr << "x: " << x << " y: " << y << ' ' << pain.workAreaHeight() << endl;
-
-       // FIXME: Abdel 16/10/2006
-       // This drawT() method is never used, this is dead code.
-
-       for (const_iterator it = begin(), et = end(); it != et; ++it) {
-               (*it)->drawT(pain, x, y);
-               //x += (*it)->width_;
-               x += 2;
-       }
-}
-
-
-int MathArray::pos2x(size_type pos) const
-{
-       return pos2x(pos, 0);
-}
-
-
-int MathArray::pos2x(size_type pos, int glue) const
-{
-       int x = 0;
-       size_type target = min(pos, size());
-       for (size_type i = 0; i < target; ++i) {
-               const_iterator it = begin() + i;
-               if ((*it)->getChar() == ' ')
-                       x += glue;
-               //lyxerr << "char: " << (*it)->getChar()
-               //      << "width: " << (*it)->width() << std::endl;
-               x += (*it)->width();
-       }
-       return x;
-}
-
-
-MathArray::size_type MathArray::x2pos(int targetx) const
-{
-       return x2pos(targetx, 0);
-}
-
-
-MathArray::size_type MathArray::x2pos(int targetx, int glue) const
-{
-       const_iterator it = begin();
-       int lastx = 0;
-       int currx = 0;
-       // find first position after targetx
-       for (; currx < targetx && it < end(); ++it) {
-               lastx = currx;
-               if ((*it)->getChar() == ' ')
-                       currx += glue;
-               currx += (*it)->width();
-       }
-
-       /**
-        * If we are not at the beginning of the array, go to the left
-        * of the inset if one of the following two condition holds:
-        * - the current inset is editable (so that the cursor tip is
-        *   deeper than us): in this case, we want all intermediate
-        *   cursor slices to be before insets;
-        * - the mouse is closer to the left side of the inset than to
-        *   the right one.
-        * See bug 1918 for details.
-        **/
-       if (it != begin() && currx >= targetx
-           && ((*boost::prior(it))->asNestInset()
-               || abs(lastx - targetx) < abs(currx - targetx))) {
-               --it;
-       }
-
-       return it - begin();
-}
-
-
-int MathArray::dist(BufferView const & bv, int x, int y) const
-{
-       int xx = 0;
-       int yy = 0;
-
-       const int xo_ = xo(bv);
-       const int yo_ = yo(bv);
-
-       if (x < xo_)
-               xx = xo_ - x;
-       else if (x > xo_ + width())
-               xx = x - xo_ - width();
-
-       if (y < yo_ - ascent())
-               yy = yo_ - ascent() - y;
-       else if (y > yo_ + descent())
-               yy = y - yo_ - descent();
-
-       return xx + yy;
-}
-
-
-void MathArray::setXY(BufferView & bv, int x, int y) const
-{
-       //lyxerr << "setting position cache for MathArray " << this << std::endl;
-       bv.coordCache().arrays().add(this, x, y);
-}
-
-
-int MathArray::xo(BufferView const & bv) const
-{
-       return bv.coordCache().getArrays().x(this);
-}
-
-
-int MathArray::yo(BufferView const & bv) const
-{
-       return bv.coordCache().getArrays().y(this);
-}
-
-
-std::ostream & operator<<(std::ostream & os, MathArray const & ar)
-{
-       odocstringstream oss;
-       NormalStream ns(oss);
-       ns << ar;
-       return os << to_utf8(oss.str());
-}
-
-
-odocstream & operator<<(odocstream & os, MathArray const & ar)
-{
-       NormalStream ns(os);
-       ns << ar;
-       return os;
-}
-
-
-} // namespace lyx
diff --git a/src/mathed/MathData.h b/src/mathed/MathData.h
deleted file mode 100644 (file)
index 5582a46..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-// -*- C++ -*-
-/**
- * \file MathArray.h
- * 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
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef MATH_DATA_H
-#define MATH_DATA_H
-
-#include <vector>
-
-#include "MathAtom.h"
-#include "dimension.h"
-
-#include "support/docstream.h"
-
-
-namespace lyx {
-
-class BufferView;
-class LaTeXFeatures;
-class ReplaceData;
-class MetricsInfo;
-class PainterInfo;
-class TextMetricsInfo;
-class TextPainter;
-
-
-class MathArray : private std::vector<MathAtom> {
-public:
-       /// re-use inhertited stuff
-       typedef std::vector<MathAtom> base_type;
-       using base_type::const_iterator;
-       using base_type::iterator;
-       using base_type::size_type;
-       using base_type::difference_type;
-       using base_type::size;
-       using base_type::empty;
-       using base_type::clear;
-       using base_type::begin;
-       using base_type::end;
-       using base_type::push_back;
-       using base_type::pop_back;
-       using base_type::back;
-       using base_type::front;
-       ///
-       typedef size_type idx_type;
-       typedef size_type pos_type;
-
-public:
-       ///
-       MathArray() {}
-       ///
-       MathArray(const_iterator from, const_iterator to);
-       ///
-       void append(MathArray const & ar);
-
-       /// inserts single atom at position pos
-       void insert(size_type pos, MathAtom const & at);
-       /// inserts multiple atoms at position pos
-       void insert(size_type pos, MathArray const & ar);
-
-       /// erase range from pos1 to pos2
-       void erase(iterator pos1, iterator pos2);
-       /// erase single atom
-       void erase(iterator pos);
-       /// erase range from pos1 to pos2
-       void erase(size_type pos1, size_type pos2);
-       /// erase single atom
-       void erase(size_type pos);
-
-       ///
-       void dump() const;
-       ///
-       void dump2() const;
-       ///
-       void replace(ReplaceData &);
-       ///
-       void substitute(MathArray const & m);
-
-       /// looks for exact match
-       bool match(MathArray const & ar) const;
-       /// looks for inclusion match starting at pos
-       bool matchpart(MathArray const & ar, pos_type pos) const;
-       /// looks for containment, return == size mean not found
-       size_type find(MathArray const & ar) const;
-       /// looks for containment, return == size mean not found
-       size_type find_last(MathArray const & ar) const;
-       ///
-       bool contains(MathArray const & ar) const;
-       ///
-       void validate(LaTeXFeatures &) const;
-
-       /// checked write access
-       MathAtom & operator[](pos_type);
-       /// checked read access
-       MathAtom const & operator[](pos_type) const;
-       /// rebuild cached metrics information
-       void metrics(MetricsInfo & mi) const;
-       /// rebuild cached metrics information
-       bool metrics(MetricsInfo & mi, Dimension & dim) const;
-       /// redraw cell using cache metrics information
-       void draw(PainterInfo & pi, int x, int y) const;
-       /// rebuild cached metrics information
-       void metricsT(TextMetricsInfo const & mi, Dimension & dim) const;
-       /// redraw cell using cache metrics information
-       void drawT(TextPainter & pi, int x, int y) const;
-       /// mark cell for re-drawing
-       void touch() const;
-
-       /// access to cached x coordinate of last drawing
-       int xo(BufferView const & bv) const;
-       /// access to cached y coordinate of last drawing
-       int yo(BufferView const & bv) const;
-       /// access to cached x coordinate of mid point of last drawing
-       int xm(BufferView const & bv) const { return xo(bv) + dim_.wid / 2; }
-       /// access to cached y coordinate of mid point of last drawing
-       int ym(BufferView const & bv) const { return yo(bv) + (dim_.des - dim_.asc) / 2; }
-       /// write access to coordinate;
-       void setXY(BufferView & bv, int x, int y) const;
-       /// returns x coordinate of given position in the array
-       int pos2x(size_type pos) const;
-       /// returns position of given x coordinate
-       int pos2x(size_type pos, int glue) const;
-       /// returns position of given x coordinate
-       size_type x2pos(int pos) const;
-       /// returns position of given x coordinate fstarting from a certain pos
-       size_type x2pos(int targetx, int glue) const;
-       /// returns distance of this cell to the point given by x and y
-       // assumes valid position and size cache
-       int dist(BufferView const & bv, int x, int y) const;
-
-       /// ascent of this cell above the baseline
-       int ascent() const { return dim_.asc; }
-       /// descent of this cell below the baseline
-       int descent() const { return dim_.des; }
-       /// height of the cell
-       int height() const { return dim_.asc + dim_.des; }
-       /// width of this cell
-       int width() const { return dim_.wid; }
-       /// dimensions of cell
-       Dimension const & dim() const { return dim_; }
-       /// dimensions of cell
-       void setDim(Dimension const & d) const { dim_ = d; }
-       /// minimum ascent offset for superscript
-       int minasc() const { return minasc_; }
-       /// minimum descent offset for subscript
-       int mindes() const { return mindes_; }
-       /// level above/below which super/subscript should extend
-       int slevel() const { return slevel_; }
-       /// additional super/subscript shift
-       int sshift() const { return sshift_; }
-       /// superscript kerning
-       int kerning() const { return kerning_; }
-       /// 
-       void swap(MathArray & ar) { base_type::swap(ar); }
-
-protected:
-       /// cached dimensions of cell
-       mutable Dimension dim_;
-       /// cached values for super/subscript placement
-       mutable int minasc_;
-       mutable int mindes_;
-       mutable int slevel_;
-       mutable int sshift_;
-       mutable int kerning_;
-
-private:
-       /// is this an exact match at this position?
-       bool find1(MathArray const & ar, size_type pos) const;
-};
-
-///
-std::ostream & operator<<(std::ostream & os, MathArray const & ar);
-///
-odocstream & operator<<(odocstream & os, MathArray const & ar);
-
-
-} // namespace lyx
-
-#endif
diff --git a/src/mathed/MathMacro.cpp b/src/mathed/MathMacro.cpp
new file mode 100644 (file)
index 0000000..1cde0ec
--- /dev/null
@@ -0,0 +1,290 @@
+/**
+ * \file MathMacro.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 "MathMacro.h"
+#include "MathSupport.h"
+#include "MathExtern.h"
+#include "MathStream.h"
+
+#include "buffer.h"
+#include "cursor.h"
+#include "debug.h"
+#include "BufferView.h"
+#include "LaTeXFeatures.h"
+#include "frontends/Painter.h"
+
+
+namespace lyx {
+
+using std::string;
+using std::max;
+using std::auto_ptr;
+using std::endl;
+using std::vector;
+
+
+/// This class is the value of a macro argument, technically 
+/// a wrapper of the cells of MathMacro.
+class MathMacroArgumentValue : public InsetMathDim {
+public:
+       ///
+       MathMacroArgumentValue(MathArray const * value, docstring const & macroName) 
+               : value_(value), macroName_(macroName) {}
+       ///
+       bool metrics(MetricsInfo & mi, Dimension & dim) const;
+       ///
+       void draw(PainterInfo &, int x, int y) const;
+       
+private:
+       std::auto_ptr<InsetBase> doClone() const;
+       MathArray const * value_;
+       docstring macroName_;
+};
+
+
+auto_ptr<InsetBase> MathMacroArgumentValue::doClone() const 
+{
+       return auto_ptr<InsetBase>(new MathMacroArgumentValue(*this));
+}
+
+
+bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const 
+{
+       // unlock outer macro in arguments, and lock it again later
+       MacroTable::globalMacros().get(macroName_).unlock();
+       value_->metrics(mi, dim);
+       MacroTable::globalMacros().get(macroName_).lock();
+       metricsMarkers2(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void MathMacroArgumentValue::draw(PainterInfo & pi, int x, int y) const 
+{
+       // unlock outer macro in arguments, and lock it again later
+       MacroTable::globalMacros().get(macroName_).unlock();
+       value_->draw(pi, x, y);
+       MacroTable::globalMacros().get(macroName_).lock();
+}
+
+
+MathMacro::MathMacro(docstring const & name, int numargs)
+       : InsetMathNest(numargs), name_(name)
+{}
+
+
+auto_ptr<InsetBase> MathMacro::doClone() const
+{
+       return auto_ptr<InsetBase>(new MathMacro(*this));
+}
+
+
+docstring MathMacro::name() const
+{
+       return name_;
+}
+
+
+void MathMacro::cursorPos(BufferView const & bv,
+               CursorSlice const & sl, bool boundary, int & x, int & y) const
+{
+       // We may have 0 arguments, but InsetMathNest requires at least one.
+       if (nargs() > 0)
+               InsetMathNest::cursorPos(bv, sl, boundary, x, y);
+}
+
+
+bool MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (!MacroTable::globalMacros().has(name())) {
+               mathed_string_dim(mi.base.font, "Unknown: " + name(), dim);
+       } else {
+               MacroData const & macro = MacroTable::globalMacros().get(name());
+               if (macro.locked()) {
+                       mathed_string_dim(mi.base.font, "Self reference: " + name(), dim);
+                       expanded_ = MathArray();
+               } else if (editing(mi.base.bv)) {
+                       // FIXME UNICODE
+                       asArray(macro.def(), tmpl_);
+                       LyXFont font = mi.base.font;
+                       augmentFont(font, from_ascii("lyxtex"));
+                       tmpl_.metrics(mi, dim);
+                       // FIXME UNICODE
+                       dim.wid += mathed_string_width(font, name()) + 10;
+                       // FIXME UNICODE
+                       int ww = mathed_string_width(font, from_ascii("#1: "));
+                       for (idx_type i = 0; i < nargs(); ++i) {
+                               MathArray const & c = cell(i);
+                               c.metrics(mi);
+                               dim.wid  = max(dim.wid, c.width() + ww);
+                               dim.des += c.height() + 10;
+                       }
+               } else {
+                       // create MathMacroArgumentValue object pointing to the cells of the macro
+                       MacroData const & macro = MacroTable::globalMacros().get(name());
+                       vector<MathArray> values(nargs());
+                       for (size_t i = 0; i != nargs(); ++i) 
+                               values[i].insert(0, MathAtom(new MathMacroArgumentValue(&cells_[i], name())));
+                       macro.expand(values, expanded_);
+                       
+                       MacroTable::globalMacros().get(name()).lock();
+                       expanded_.metrics(mi, dim);
+                       MacroTable::globalMacros().get(name()).unlock();
+               }
+       }
+       metricsMarkers2(dim);
+       if (dim_ == dim)
+               return false;
+       dim_ = dim;
+       return true;
+}
+
+
+void MathMacro::draw(PainterInfo & pi, int x, int y) const
+{
+       if (!MacroTable::globalMacros().has(name())) {
+               // FIXME UNICODE
+               drawStrRed(pi, x, y, "Unknown: " + name());
+       } else {
+               MacroData const & macro = MacroTable::globalMacros().get(name());
+               if (macro.locked()) {
+                       // FIXME UNICODE
+                       drawStrRed(pi, x, y, "Self reference: " + name());
+               } else if (editing(pi.base.bv)) {
+                       LyXFont font = pi.base.font;
+                       augmentFont(font, from_ascii("lyxtex"));
+                       int h = y - dim_.ascent() + 2 + tmpl_.ascent();
+                       pi.pain.text(x + 3, h, name(), font);
+                       int const w = mathed_string_width(font, name());
+                       tmpl_.draw(pi, x + w + 12, h);
+                       h += tmpl_.descent();
+                       Dimension ldim;
+                       docstring t = from_ascii("#1: ");
+                       mathed_string_dim(font, t, ldim);
+                       for (idx_type i = 0; i < nargs(); ++i) {
+                               MathArray const & c = cell(i);
+                               h += max(c.ascent(), ldim.asc) + 5;
+                               c.draw(pi, x + ldim.wid, h);
+                               char_type str[] = { '#', '1', ':', '\0' };
+                               str[1] += static_cast<char_type>(i);
+                               pi.pain.text(x + 3, h, str, font);
+                               h += max(c.descent(), ldim.des) + 5;
+                       }
+               } else {
+                       MacroTable::globalMacros().get(name()).lock();
+                       expanded_.draw(pi, x, y);
+                       MacroTable::globalMacros().get(name()).unlock();
+               }
+       }
+       drawMarkers2(pi, x, y);
+}
+
+
+void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
+{
+       // We may have 0 arguments, but InsetMathNest requires at least one.
+       if (nargs() > 0)
+               InsetMathNest::drawSelection(pi, x, y);
+}
+
+
+void MathMacro::validate(LaTeXFeatures & features) const
+{
+       if (name() == "binom" || name() == "mathcircumflex")
+               features.require(to_utf8(name()));
+}
+
+
+InsetBase * MathMacro::editXY(LCursor & cur, int x, int y)
+{
+       // We may have 0 arguments, but InsetMathNest requires at least one.
+       if (nargs() > 0) {
+               // Prevent crash due to cold coordcache
+               // FIXME: This is only a workaround, the call of
+               // InsetMathNest::editXY is correct. The correct fix would
+               // ensure that the coordcache of the arguments is valid.
+               if (!editing(&cur.bv())) {
+                       edit(cur, true);
+                       return this;
+               }
+               return InsetMathNest::editXY(cur, x, y);
+       }
+       return this;
+}
+
+
+bool MathMacro::idxFirst(LCursor & cur) const 
+{
+       cur.updateFlags(Update::Force);
+       return InsetMathNest::idxFirst(cur);
+}
+
+
+bool MathMacro::idxLast(LCursor & cur) const 
+{
+       cur.updateFlags(Update::Force);
+       return InsetMathNest::idxLast(cur);
+}
+
+
+bool MathMacro::notifyCursorLeaves(LCursor & cur)
+{
+       cur.updateFlags(Update::Force);
+       return InsetMathNest::notifyCursorLeaves(cur);
+}
+
+
+void MathMacro::maple(MapleStream & os) const
+{
+       updateExpansion();
+       lyx::maple(expanded_, os);
+}
+
+
+void MathMacro::mathmlize(MathStream & os) const
+{
+       updateExpansion();
+       lyx::mathmlize(expanded_, os);
+}
+
+
+void MathMacro::octave(OctaveStream & os) const
+{
+       updateExpansion();
+       lyx::octave(expanded_, os);
+}
+
+
+void MathMacro::updateExpansion() const
+{
+       //expanded_.substitute(*this);
+}
+
+
+void MathMacro::infoize(odocstream & os) const
+{
+       os << "Macro: " << name();
+}
+
+
+void MathMacro::infoize2(odocstream & os) const
+{
+       os << "Macro: " << name();
+
+}
+
+
+} // namespace lyx
diff --git a/src/mathed/MathMacro.h b/src/mathed/MathMacro.h
new file mode 100644 (file)
index 0000000..b4ff0a4
--- /dev/null
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+/**
+ * \file MathMacro.h
+ * 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.
+ */
+
+#ifndef MATH_MACRO_H
+#define MATH_MACRO_H
+
+#include "InsetMathNest.h"
+#include "MathArray.h"
+#include "InsetMathNest.h"
+#include "MathMacroTable.h"
+
+
+namespace lyx {
+
+
+/// This class contains the data for a macro.
+class MathMacro : public InsetMathNest {
+public:
+       /// A macro can be built from an existing template
+       MathMacro(docstring const & name, int numargs);
+       ///
+       void draw(PainterInfo & pi, int x, int y) const;
+       ///
+       void drawExpanded(PainterInfo & pi, int x, int y) const;
+       /// draw selection background
+       void drawSelection(PainterInfo & pi, int x, int y) const;
+       /// draw decorations.
+       void drawDecoration(PainterInfo & pi, int x, int y) const
+       { drawMarkers2(pi, x, y); }
+       ///
+       bool metrics(MetricsInfo & mi, Dimension & dim) const;
+       /// get cursor position
+       void cursorPos(BufferView const & bv, CursorSlice const & sl,
+               bool boundary, int & x, int & y) const;
+       ///
+       InsetBase * editXY(LCursor & cur, int x, int y);
+       /// target pos when we enter the inset from the left by pressing "Right"
+       bool idxFirst(LCursor &) const;
+       /// target pos when we enter the inset from the right by pressing "Left"
+       bool idxLast(LCursor &) const;
+       ///
+       virtual bool notifyCursorLeaves(LCursor &);
+       ///
+       docstring name() const;
+       ///
+       void setExpansion(MathArray const & exp, MathArray const & args) const;
+
+       ///
+       void validate(LaTeXFeatures &) const;
+
+       ///
+       void maple(MapleStream &) const;
+       ///
+       void mathmlize(MathStream &) const;
+       ///
+       void octave(OctaveStream &) const;
+       ///
+       void infoize(odocstream &) const;
+       ///
+       void infoize2(odocstream &) const;
+
+private:
+       virtual std::auto_ptr<InsetBase> doClone() const;
+       ///
+       void updateExpansion() const;
+       ///
+       void expand() const;
+
+       /// name of macro
+       docstring name_;
+       /// the unexpanded macro defintition
+       mutable MathArray tmpl_;
+       /// the macro substituted with our args
+       mutable MathArray expanded_;
+};
+
+
+
+
+} // namespace lyx
+#endif
diff --git a/src/mathed/MathReplace.h b/src/mathed/MathReplace.h
deleted file mode 100644 (file)
index dc8eb6b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// -*- C++ -*-
-/**
- * \file ReplaceData.h
- * 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.
- */
-
-#ifndef MATH_REPLACE_H
-#define MATH_REPLACE_H
-
-
-#include "MathArray.h"
-
-
-namespace lyx {
-
-class ReplaceData {
-public:
-       ///
-       MathArray from;
-       ///
-       MathArray to;
-};
-
-
-} // namespace lyx
-
-#endif
diff --git a/src/mathed/ReplaceData.h b/src/mathed/ReplaceData.h
new file mode 100644 (file)
index 0000000..dc8eb6b
--- /dev/null
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+/**
+ * \file ReplaceData.h
+ * 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.
+ */
+
+#ifndef MATH_REPLACE_H
+#define MATH_REPLACE_H
+
+
+#include "MathArray.h"
+
+
+namespace lyx {
+
+class ReplaceData {
+public:
+       ///
+       MathArray from;
+       ///
+       MathArray to;
+};
+
+
+} // namespace lyx
+
+#endif