Index: paragraph.h
===================================================================
--- paragraph.h	(Revision 17867)
+++ paragraph.h	(Arbeitskopie)
@@ -8,6 +8,7 @@
  * \author Lars Gullik Bjønnes
  * \author John Levon
  * \author André Pönitz
+ * \author Stefan Schimanski
  * \author Jürgen Vigna
  *
  * Full author contact details are available in file CREDITS.
@@ -363,6 +364,15 @@
 	/// \retval true if the cursor needs to be moved right.
 	bool checkBiblio(bool track_changes);
 
+	/// To resolve macros properly the paragraphs are numbered.
+	/// Every macro definition is stored with its paragraph number
+	/// as well. Only those macros with a smaller number become 
+	/// visible in a paragraph (plus those in the same paragraph, but
+	/// in an earlier inset.
+	unsigned int macrocontextPosition() const;
+	///
+	void setMacrocontextPosition(unsigned int pos);
+	
 public:
 	///
 	InsetList insetlist;
Index: TextMetrics.C
===================================================================
--- TextMetrics.C	(Revision 17867)
+++ TextMetrics.C	(Arbeitskopie)
@@ -8,6 +8,7 @@
  * \author Jean-Marc Lasgouttes
  * \author John Levon
  * \author André Pönitz
+ * \author Stefan Schimanski
  * \author Dekel Tsur
  * \author Jürgen Vigna
  * \author Abdelrazak Younes
@@ -35,6 +36,8 @@
 #include "metricsinfo.h"
 #include "ParagraphParameters.h"
 #include "vspace.h"
+#include "mathed/MathMacroTable.h"
+#include "mathed/MathMacroTemplate.h"
 
 #include "frontends/FontMetrics.h"
 #include "frontends/Painter.h"
@@ -203,15 +206,36 @@
 	// FIXME: We should always use getFont(), see documentation of
 	// noFontChange() in insetbase.h.
 	LyXFont const bufferfont = buffer.params().getFont();
+	MacroContext mc(buffer, par);
 	InsetList::const_iterator ii = par.insetlist.begin();
 	InsetList::const_iterator iend = par.insetlist.end();
 	for (; ii != iend; ++ii) {
+		// the macro must come here, _before_ the metric call, because
+		// the macro should see itself to detect recursions. To find out
+		// whether the macro definition is a redefinition it will look
+		// at the MacroData::redefinition_. So it doesn't get confused
+		// by the already existing macro definition of itself in the 
+		// macro context.
+		if (ii->inset->lyxCode() == InsetBase::MATHMACRO_CODE) {
+			// get macro data
+			MathMacroTemplate const & macroTemplate
+			= static_cast<MathMacroTemplate const &>(*ii->inset);
+			MacroData macro = macroTemplate.asMacroData();
+			
+			// redefinition?
+			macro.setRedefinition(mc.has(macroTemplate.name()));
+			
+			// register macro (possibly overwrite the previous one of this paragraph)
+			mc.insert(macroTemplate.name(), macroTemplate.asMacroData());
+		}
+
+		// do the metric calculation
 		Dimension dim;
 		int const w = max_width_ - text_->leftMargin(buffer, max_width_, pit, ii->pos)
 			- right_margin;
 		LyXFont const & font = ii->inset->noFontChange() ?
 			bufferfont : text_->getFont(buffer, par, ii->pos);
-		MetricsInfo mi(bv_, font, w);
+		MetricsInfo mi(bv_, font, w, mc);
 		changed |= ii->inset->metrics(mi, dim);
 	}
 
Index: metricsinfo.h
===================================================================
--- metricsinfo.h	(Revision 17867)
+++ metricsinfo.h	(Arbeitskopie)
@@ -5,6 +5,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author André Pönitz
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -21,6 +22,7 @@
 namespace lyx {
 
 namespace frontend { class Painter; }
+class MacroContext;
 
 
 /// Standard Sizes (mode styles)
@@ -66,12 +68,12 @@
 class MetricsInfo {
 public:
 	///
-	MetricsInfo();
-	///
-	MetricsInfo(BufferView * bv, LyXFont const & font, int textwidth);
+	MetricsInfo(BufferView * bv, LyXFont const & font, int textwidth, MacroContext const & mc);
 
 	///
 	MetricsBase base;
+	/// The context to resolve macros
+	MacroContext const & macrocontext;
 };
 
 
Index: paragraph_pimpl.C
===================================================================
--- paragraph_pimpl.C	(Revision 17867)
+++ paragraph_pimpl.C	(Arbeitskopie)
@@ -66,6 +66,7 @@
 {
 	inset_owner = 0;
 	id_ = paragraph_id++;
+	macrocontext_position_ = 0;
 }
 
 
Index: mathed/InsetMathBrace.h
===================================================================
--- mathed/InsetMathBrace.h	(Revision 17867)
+++ mathed/InsetMathBrace.h	(Arbeitskopie)
@@ -25,8 +25,6 @@
 	InsetMathBrace();
 	///
 	InsetMathBrace(MathArray const & ar);
-	///
-	InsetMathBrace const * asBraceInset() const { return this; }
 	/// we write extra braces in any case...
 	bool extraBraces() const { return true; }
 	///
@@ -47,6 +45,11 @@
 	void mathmlize(MathStream &) const;
 	///
 	void infoize(odocstream & os) const;
+	
+	/// identifies brace insets
+	InsetMathBrace * asBraceInset() { return this; }
+	/// identifies brace insets
+	InsetMathBrace const * asBraceInset() const { return this; }
 private:
 	virtual std::auto_ptr<InsetBase> doClone() const;
 };
Index: mathed/MathData.C
===================================================================
--- mathed/MathData.C	(Revision 17867)
+++ mathed/MathData.C	(Arbeitskopie)
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author André Pönitz
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -14,6 +15,7 @@
 #include "InsetMathFont.h"
 #include "InsetMathScript.h"
 #include "InsetMathMacro.h"
+#include "InsetMathBrace.h"
 #include "MathMacroTable.h"
 #include "MathStream.h"
 #include "MathSupport.h"
@@ -239,7 +241,6 @@
 }
 
 
-
 void MathArray::metrics(MetricsInfo & mi) const
 {
 	frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
@@ -256,37 +257,16 @@
 	if (empty())
 		return;
 
+	const_cast<MathArray*>(this)->updateMacros(mi);
+	
 	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) {
+	Dimension d;	
+	for (size_t i = 0; i != size(); ++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)
+		if (i == size() - 1)
 			kerning_ = at->kerning();
 	}
 }
@@ -312,23 +292,6 @@
 
 	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);
@@ -363,6 +326,72 @@
 }
 
 
+void MathArray::updateMacros(MetricsInfo & mi) {
+	// go over the array and look for macros
+	for (size_t i = 0; i != size(); ++i) {
+		InsetMath * at = operator[](i).nucleus();
+		MathMacro * macroInset = at->asMacro();
+		if (macroInset) {
+			// get arity of macro or 0 if unknown
+			size_t numargs = 0;
+			if (mi.macrocontext.has(macroInset->name())) {
+				MacroData const & macro = mi.macrocontext.get(macroInset->name());
+				numargs = macro.numargs();
+			}
+			
+			// arity of macro changed?
+			if (macroInset->nargs() != numargs) {
+				// detach all arguments
+				std::vector<MathArray> detachedArgs;
+				macroInset->detachArguments(detachedArgs);
+				
+				// too many arguments in the macro inset?
+				if (detachedArgs.size() > numargs) {
+					// insert overlap back as braces
+					std::vector<MathArray> overlap(detachedArgs.begin()+numargs, detachedArgs.end());
+					detachedArgs.erase(detachedArgs.begin()+numargs, detachedArgs.end());
+					for (size_t j = 0; j < overlap.size(); ++j) {
+						MathArray const & arg = overlap[j];
+						if (arg.size() == 1)
+							insert(i+j+1, arg[0]);
+						else
+							insert(i+j+1, MathAtom(new InsetMathBrace(arg)));
+					}
+					i += overlap.size();
+				} else {
+					// insert some cells from the array into the macro inset
+					size_t missingArgs = numargs-detachedArgs.size();
+					size_t j;
+					for (j = 0; j < missingArgs && i+1+j < size(); ++j) {
+						MathAtom & cell = operator[](i+1+j);
+						InsetMathBrace const * brace = cell->asBraceInset();
+						if (brace) {
+							// found brace, convert into argument
+							detachedArgs.push_back(brace->cell(0));
+						} else {
+							MathArray array;
+							array.insert(0, cell);
+							detachedArgs.push_back(array);
+						}
+					}
+					
+					// remove them from the array
+					erase(begin()+i+1, begin()+i+1+j);
+					
+					// enough for the macro inset now?
+					// Add some empty ones of necessary
+					for (; j < missingArgs; ++j)
+						detachedArgs.insert(detachedArgs.end(), MathArray());
+				}
+				
+				// attach arguments back to macro inset
+				macroInset->attachArguments(detachedArgs);
+			}
+		}
+	}
+}
+
+
 int MathArray::pos2x(size_type pos) const
 {
 	return pos2x(pos, 0);
Index: mathed/MathMacroTable.C
===================================================================
--- mathed/MathMacroTable.C	(Revision 17867)
+++ mathed/MathMacroTable.C	(Arbeitskopie)
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author André Pönitz
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -15,6 +16,7 @@
 #include "MathMacroArgument.h"
 #include "MathSupport.h"
 #include "InsetMathSqrt.h"
+#include "buffer.h"
 
 #include "debug.h"
 #include "dociterator.h"
@@ -36,12 +38,12 @@
 
 
 MacroData::MacroData()
-	: numargs_(0), lockCount_(0)
+	: numargs_(0), lockCount_(0), redefinition_(false)
 {}
 
 
 MacroData::MacroData(docstring const & def, int numargs, docstring const & disp, string const & requires)
-	: def_(def), numargs_(numargs), disp_(disp), requires_(requires), lockCount_(0)
+	: def_(def), numargs_(numargs), disp_(disp), requires_(requires), lockCount_(0), redefinition_(false)
 {}
 
 
@@ -121,4 +123,38 @@
 }
 
 
+MacroContext::MacroContext(Buffer const & buf, Paragraph const & par)
+	: buf_(buf), par_(par)
+{
+}
+
+
+bool MacroContext::has(docstring const & name) const
+{
+	// check if it's a local macro
+	if (macros_.has(name))
+		return true;
+	
+	// otherwise ask the buffer
+	return buf_.hasMacro(name, par_);
+}
+
+
+MacroData const & MacroContext::get(docstring const & name) const
+{
+	// check if it's a local macro
+	if (macros_.has(name))
+		return macros_.get(name);
+	
+	// ask the buffer for its macros
+	return buf_.getMacro(name, par_);
+}
+
+
+void MacroContext::insert(docstring const & name, MacroData const & data)
+{
+	macros_.insert(name, data);
+}
+
+
 } // namespace lyx
Index: mathed/MathData.h
===================================================================
--- mathed/MathData.h	(Revision 17867)
+++ mathed/MathData.h	(Arbeitskopie)
@@ -7,6 +7,7 @@
  * \author Alejandro Aguilar Sierra
  * \author André Pönitz
  * \author Lars Gullik Bjønnes
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -172,6 +173,9 @@
 	mutable int sshift_;
 	mutable int kerning_;
 
+	/// attach/detach brace inset to macros
+	void updateMacros(MetricsInfo & mi);
+	
 private:
 	/// is this an exact match at this position?
 	bool find1(MathArray const & ar, size_type pos) const;
Index: mathed/MathMacroTemplate.C
===================================================================
--- mathed/MathMacroTemplate.C	(Revision 17867)
+++ mathed/MathMacroTemplate.C	(Arbeitskopie)
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author André Pönitz
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -105,27 +106,33 @@
 
 docstring MathMacroTemplate::prefix() const
 {
-	return bformat(_(" Macro: %1$s: "), name_);
+	if (type_ == from_ascii("renewcommand"))
+		return bformat(_("Redefining Macro \\%1$s: "), name_);
+	else
+		return bformat(_("Macro \\%1$s: "), name_);
 }
 
 
 bool MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
 {
-	bool lockMacro = MacroTable::globalMacros().has(name_);
-	if (lockMacro)
-		MacroTable::globalMacros().get(name_).lock();
-
+	MacroData const & macro = mi.macrocontext.get(name_);
+	if (type_ == from_ascii("newcommand") || type_ == from_ascii("renewcommand")) {
+		// use the MacroData::redefinition_ information instead of MacroContext::has
+		// because the macro is known here already anyway to detect recursive definitions
+		type_ = macro.redefinition() ? from_ascii("renewcommand") : from_ascii("newcommand"); 
+	}
+		
+	macro.lock();
 	cell(0).metrics(mi);
 	cell(1).metrics(mi);
+	macro.unlock();
+	
 	docstring dp = prefix();
 	dim.wid = cell(0).width() + cell(1).width() + 20
 		+ theFontMetrics(mi.base.font).width(dp);
 	dim.asc = std::max(cell(0).ascent(),  cell(1).ascent())  + 7;
 	dim.des = std::max(cell(0).descent(), cell(1).descent()) + 7;
 	
-	if (lockMacro)
-		MacroTable::globalMacros().get(name_).unlock();
-	
 	if (dim_ == dim)
 		return false;
 	dim_ = dim;
@@ -135,10 +142,6 @@
 
 void MathMacroTemplate::draw(PainterInfo & p, int x, int y) const
 {
-	bool lockMacro = MacroTable::globalMacros().has(name_);
-	if (lockMacro)
-		MacroTable::globalMacros().get(name_).lock();
-	
 	setPosCache(p, x, y);
 
 	// label
@@ -179,9 +182,6 @@
 	cell(1).draw(pi, x + 8 + w0, y + 1);
 	pi.pain.rectangle(x + w0 + 6, y - dim_.ascent() + 3,
 		w1 + 4, dim_.height() - 6, LColor::mathline);
-	
-	if (lockMacro)
-		MacroTable::globalMacros().get(name_).unlock();
 }
 
 
Index: mathed/MathMacroTable.h
===================================================================
--- mathed/MathMacroTable.h	(Revision 17867)
+++ mathed/MathMacroTable.h	(Arbeitskopie)
@@ -4,7 +4,8 @@
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
- * \author AndrÃ© PÃ¶nitz
+ * \author André Pönitz
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -22,6 +23,8 @@
 namespace lyx {
 
 class MathArray;
+class Paragraph;
+class Buffer;
 
 ///
 class MacroData {
@@ -42,13 +45,19 @@
 	std::string requires() const { return requires_; }
 	///
 	std::string & requires() { return requires_; }
-	/// lock while being drawn
+	
+	/// lock while being drawn to avoid recursions
 	int lock() const { return ++lockCount_; }
 	/// is it being drawn?
 	bool locked() const { return lockCount_ != 0; }
+ 	///
+	void unlock() const { --lockCount_; BOOST_ASSERT(lockCount_ >= 0); } 	
+	
 	///
-	void unlock() const { --lockCount_; BOOST_ASSERT(lockCount_ >= 0); } 	
-
+	bool redefinition() const { return redefinition_; }
+	///
+	void setRedefinition(bool redefined) { redefinition_ = redefined; }
+	
 private:
 	///
 	docstring def_;
@@ -60,6 +69,8 @@
 	std::string requires_;
 	///
 	mutable int lockCount_;
+	///
+	bool redefinition_;
 };
 
 
@@ -83,11 +94,36 @@
 
 	/// the global list
 	static MacroTable & globalMacros();
-	/// the local list hack
-	//static MacroTable & localMacros();
 };
 
 
+// The MacroContext is used during metrics calculation to resolve
+// macro instances according to the position of them in the buffer
+// document. Only macro definition in front of the macro instance
+// are visible and are resolved.
+
+class MacroContext {
+public:
+	/// construct context for insets in par (not including the ones defined in par itself)
+	MacroContext(Buffer const & buf, Paragraph const & par);
+	
+	/// Look for macro
+	bool has(docstring const & name) const;
+	/// Lookup macro
+	MacroData const & get(docstring const & name) const;
+	
+	/// Insert pre-digested macro definition
+	void insert(docstring const & name, MacroData const & data);
+	
+private:
+	/// context local macros
+	MacroTable macros_;
+	///
+	Buffer const & buf_;
+	///
+	Paragraph const & par_;
+};
+
 } // namespace lyx
 
 #endif
Index: mathed/InsetMath.h
===================================================================
--- mathed/InsetMath.h	(Revision 17867)
+++ mathed/InsetMath.h	(Arbeitskopie)
@@ -113,6 +113,7 @@
 	virtual InsetMathAMSArray const * asAMSArrayInset() const { return 0; }
 	virtual InsetMathArray          * asArrayInset()          { return 0; }
 	virtual InsetMathArray const    * asArrayInset() const    { return 0; }
+	virtual InsetMathBrace          * asBraceInset()          { return 0; }
 	virtual InsetMathBrace const    * asBraceInset() const    { return 0; }
 	virtual InsetMathChar const     * asCharInset() const     { return 0; }
 	virtual InsetMathDelim          * asDelimInset()          { return 0; }
Index: mathed/MathMacroTemplate.h
===================================================================
--- mathed/MathMacroTemplate.h	(Revision 17867)
+++ mathed/MathMacroTemplate.h	(Arbeitskopie)
@@ -77,7 +77,7 @@
 	///
 	docstring name_;
 	/// newcommand or renewcommand or def
-	docstring type_;
+	mutable docstring type_;
 };
 
 
Index: mathed/MathFactory.C
===================================================================
--- mathed/MathFactory.C	(Revision 17867)
+++ mathed/MathFactory.C	(Arbeitskopie)
@@ -392,15 +392,7 @@
 	if (s == "vphantom")
 		return MathAtom(new InsetMathPhantom(InsetMathPhantom::vphantom));
 
-	if (MacroTable::globalMacros().has(s))
-		return MathAtom(new MathMacro(s,
-			MacroTable::globalMacros().get(s).numargs()));
-	//if (MacroTable::localMacros().has(s))
-	//	return MathAtom(new MathMacro(s,
-	//		MacroTable::localMacros().get(s).numargs()));
-
-	//lyxerr << "creating unknown inset '" << s << "'" << endl;
-	return MathAtom(new InsetMathUnknown(s));
+	return MathAtom(new MathMacro(s));
 }
 
 
Index: mathed/InsetMathMacro.C
===================================================================
--- mathed/InsetMathMacro.C	(Revision 17867)
+++ mathed/InsetMathMacro.C	(Arbeitskopie)
@@ -5,6 +5,7 @@
  *
  * \author Alejandro Aguilar Sierra
  * \author André Pönitz
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -61,9 +62,13 @@
 bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const 
 {
 	// unlock outer macro in arguments, and lock it again later
-	MacroTable::globalMacros().get(macroName_).unlock();
+	// because a macro in its own argument does not harm
+	MacroData const & macro = mi.macrocontext.get(macroName_);
+	macro.unlock();
+ 	value_->metrics(mi, dim);
+	macro.lock();
+	
 	value_->metrics(mi, dim);
-	MacroTable::globalMacros().get(macroName_).lock();
 	metricsMarkers2(dim);
 	if (dim_ == dim)
 		return false;
@@ -74,15 +79,12 @@
 
 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)
+MathMacro::MathMacro(docstring const & name)
+	: InsetMathNest(0), name_(name), unknown_(false), recursive_(false)
 {}
 
 
@@ -109,14 +111,19 @@
 
 bool MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
 {
-	if (!MacroTable::globalMacros().has(name())) {
-		mathed_string_dim(mi.base.font, "Unknown: " + name(), dim);
+	if (!mi.macrocontext.has(name())) {
+		unknown_ = true;
+		mathed_string_dim(mi.base.font, "\\" + name(), dim);
 	} else {
-		MacroData const & macro = MacroTable::globalMacros().get(name());
+		unknown_ = false;
+		MacroData const & macro = mi.macrocontext.get(name());
 		if (macro.locked()) {
+			recursive_ = true;
 			mathed_string_dim(mi.base.font, "Self reference: " + name(), dim);
 			expanded_ = MathArray();
 		} else if (editing(mi.base.bv)) {
+			recursive_ = false;
+			
 			// FIXME UNICODE
 			asArray(macro.def(), tmpl_);
 			LyXFont font = mi.base.font;
@@ -133,16 +140,17 @@
 				dim.des += c.height() + 10;
 			}
 		} else {
+			recursive_ = false;
+			
 			// create MathMacroArgumentValue object pointing to the cells of the macro
-			MacroData const & macro = MacroTable::globalMacros().get(name());
+			MacroData const & macro = mi.macrocontext.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();
+			macro.lock();
 			expanded_.metrics(mi, dim);
-			MacroTable::globalMacros().get(name()).unlock();
+			macro.unlock();
 		}
 	}
 	metricsMarkers2(dim);
@@ -155,39 +163,34 @@
 
 void MathMacro::draw(PainterInfo & pi, int x, int y) const
 {
-	if (!MacroTable::globalMacros().has(name())) {
+	if (unknown_) {
 		// 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();
+		drawStrRed(pi, x, y, "\\" + name());
+	} else if (recursive_) {
+		// 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 {
+		expanded_.draw(pi, x, y);
 	}
 	drawMarkers2(pi, x, y);
 }
@@ -211,21 +214,26 @@
 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;
-		}
+	if (nargs() > 0 && !recursive_) 
 		return InsetMathNest::editXY(cur, x, y);
-	}
-	return this;
+	else 
+		return this;
 }
 
 
+void MathMacro::detachArguments(std::vector<MathArray> &args)
+{
+	args = cells_;
+	cells_ = std::vector<MathArray>();
+}
+
+
+void MathMacro::attachArguments(std::vector<MathArray> const &args)
+{
+	cells_ = args;
+}
+
+
 bool MathMacro::idxFirst(LCursor & cur) const 
 {
 	cur.updateFlags(Update::Force);
@@ -249,31 +257,22 @@
 
 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();
@@ -283,7 +282,6 @@
 void MathMacro::infoize2(odocstream & os) const
 {
 	os << "Macro: " << name();
-
 }
 
 
Index: mathed/InsetMathMacro.h
===================================================================
--- mathed/InsetMathMacro.h	(Revision 17867)
+++ mathed/InsetMathMacro.h	(Arbeitskopie)
@@ -6,6 +6,7 @@
  *
  * \author Alejandro Aguilar Sierra
  * \author André Pönitz
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -26,8 +27,12 @@
 class MathMacro : public InsetMathNest {
 public:
 	/// A macro can be built from an existing template
-	MathMacro(docstring const & name, int numargs);
+	MathMacro(docstring const & name);
 	///
+	virtual MathMacro * asMacro() { return this; }
+	///
+	virtual MathMacro const * asMacro() const { return this; }
+	///
 	void draw(PainterInfo & pi, int x, int y) const;
 	///
 	void drawExpanded(PainterInfo & pi, int x, int y) const;
@@ -38,6 +43,8 @@
 	{ drawMarkers2(pi, x, y); }
 	///
 	bool metrics(MetricsInfo & mi, Dimension & dim) const;
+	///
+	bool metricsExpanded(MetricsInfo & mi, Dimension & dim) const;
 	/// get cursor position
 	void cursorPos(BufferView const & bv, CursorSlice const & sl,
 		bool boundary, int & x, int & y) const;
@@ -52,9 +59,11 @@
 	///
 	docstring name() const;
 	///
-	void setExpansion(MathArray const & exp, MathArray const & args) const;
-
+	void detachArguments(std::vector<MathArray> &args);
 	///
+	void attachArguments(std::vector<MathArray> const &args);
+	
+	///
 	void validate(LaTeXFeatures &) const;
 
 	///
@@ -70,14 +79,14 @@
 
 private:
 	virtual std::auto_ptr<InsetBase> doClone() const;
-	///
-	void updateExpansion() const;
-	///
-	void expand() const;
-
+	
 	/// name of macro
 	docstring name_;
-	/// the unexpanded macro defintition
+	/// unknown macro?
+	mutable bool unknown_;
+	/// recursive macro?
+	mutable bool recursive_;
+	/// the macro template
 	mutable MathArray tmpl_;
 	/// the macro substituted with our args
 	mutable MathArray expanded_;
Index: buffer.C
===================================================================
--- buffer.C	(Revision 17867)
+++ buffer.C	(Arbeitskopie)
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Lars Gullik Bjønnes
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -188,10 +189,12 @@
 	InsetText inset;
 
 	///
-	MacroTable macros;
+	TocBackend toc_backend;
 
-	///
-	TocBackend toc_backend;
+	/// macro table
+	typedef std::map<unsigned int, MacroData, std::greater<int> > PositionToMacroMap;
+	typedef std::map<docstring, PositionToMacroMap> NameToPositionMacroMap;
+	NameToPositionMacroMap macros;
 };
 
 
@@ -729,10 +732,6 @@
 				       from_utf8(filename.absFilename())));
 	}
 
-	//lyxerr << "removing " << MacroTable::localMacros().size()
-	//	<< " temporary macro entries" << endl;
-	//MacroTable::localMacros().clear();
-
 	pimpl_->file_fully_loaded = true;
 	return success;
 }
@@ -1570,47 +1569,100 @@
 }
 
 
-MacroData const & Buffer::getMacro(docstring const & name) const
+bool Buffer::hasMacro(docstring const & name, Paragraph const & par) const
 {
-	return pimpl_->macros.get(name);
+	Impl::PositionToMacroMap::iterator it;
+	it = pimpl_->macros[name].upper_bound(par.macrocontextPosition());
+	if( it != pimpl_->macros[name].end() )
+		return true;
+	
+	// If there is a master buffer, query that
+	const Buffer *master = getMasterBuffer();
+	if (master && master!=this)
+		return master->hasMacro(name);
+	
+	return false;
 }
 
 
 bool Buffer::hasMacro(docstring const & name) const
 {
-	return pimpl_->macros.has(name);
+	if( !pimpl_->macros[name].empty() )
+		return true;
+	
+	// If there is a master buffer, query that
+	const Buffer *master = getMasterBuffer();
+	if (master && master!=this)
+		return master->hasMacro(name);
+		
+	return false;
 }
 
 
-void Buffer::insertMacro(docstring const & name, MacroData const & data)
+MacroData const & Buffer::getMacro(docstring const & name, Paragraph const & par) const
 {
-	MacroTable::globalMacros().insert(name, data);
-	pimpl_->macros.insert(name, data);
+	Impl::PositionToMacroMap::iterator it;
+	it = pimpl_->macros[name].upper_bound(par.macrocontextPosition());
+	if( it != pimpl_->macros[name].end() )
+		return it->second;
+	
+	// If there is a master buffer, query that
+	const Buffer *master = getMasterBuffer();
+	if (master && master!=this)
+		return master->getMacro(name);
+	
+	BOOST_ASSERT(false);
 }
 
+	
+MacroData const & Buffer::getMacro(docstring const & name) const
+{
+	Impl::PositionToMacroMap::iterator it;
+	it = pimpl_->macros[name].begin();
+	if( it != pimpl_->macros[name].end() )
+		return it->second;
+	
+	// If there is a master buffer, query that
+	const Buffer *master = getMasterBuffer();
+	if (master && master!=this)
+		return master->getMacro(name);
+	
+	BOOST_ASSERT(false);
+}
 
-void Buffer::buildMacros()
+
+void Buffer::updateMacros()
 {
-	// Start with global table.
-	pimpl_->macros = MacroTable::globalMacros();
-
-	// Now add our own.
-	ParagraphList const & pars = text().paragraphs();
+	// start with empty table
+	pimpl_->macros = Impl::NameToPositionMacroMap();
+		
+	// Iterate over buffer
+	ParagraphList & pars = text().paragraphs();
 	for (size_t i = 0, n = pars.size(); i != n; ++i) {
+		// set position again
+		pars[i].setMacrocontextPosition(i);
+				
 		//lyxerr << "searching main par " << i
 		//	<< " for macro definitions" << std::endl;
 		InsetList const & insets = pars[i].insetlist;
 		InsetList::const_iterator it = insets.begin();
 		InsetList::const_iterator end = insets.end();
 		for ( ; it != end; ++it) {
-			//lyxerr << "found inset code " << it->inset->lyxCode() << std::endl;
 			if (it->inset->lyxCode() == InsetBase::MATHMACRO_CODE) {
-				MathMacroTemplate const & mac
-					= static_cast<MathMacroTemplate const &>(*it->inset);
-				insertMacro(mac.name(), mac.asMacroData());
+				// get macro data
+				MathMacroTemplate const & macroTemplate
+				= static_cast<MathMacroTemplate const &>(*it->inset);
+				MacroData macro = macroTemplate.asMacroData();
+
+				// redefinition?
+				macro.setRedefinition(hasMacro(macroTemplate.name()));
+				
+				// register macro (possibly overwrite the previous one of this paragraph)
+				pimpl_->macros[macroTemplate.name()][i] = macroTemplate.asMacroData();
 			}
 		}
 	}
+	
 }
 
 
Index: paragraph_pimpl.h
===================================================================
--- paragraph_pimpl.h	(Revision 17867)
+++ paragraph_pimpl.h	(Arbeitskopie)
@@ -161,6 +161,10 @@
 	///
 	ParagraphParameters params;
 
+	/// position of the paragraph in the buffer. Only macros from
+	/// paragraphs strictly smaller are visible in this paragraph
+	unsigned int macrocontext_position_;
+	
 private:
 	///
 	pos_type size() const { return owner_->size(); }
Index: buffer.h
===================================================================
--- buffer.h	(Revision 17867)
+++ buffer.h	(Arbeitskopie)
@@ -357,14 +357,16 @@
 	//
 	// Macro handling
 	//
-	///
-	void buildMacros();
-	///
+	/// Collect macros in paragraphs
+	void updateMacros();
+	/// Look for macro defined before par (or in the master buffer)
+	bool hasMacro(docstring const & name, Paragraph const & par) const;
+	/// Look for macro defined anywhere in the buffer (or in the master buffer)
 	bool hasMacro(docstring const & name) const;
-	///
+	/// Return macro defined before par (or in the master buffer)
+	MacroData const & getMacro(docstring const & name, Paragraph const & par) const;
+	/// Return macro defined anywhere in the buffer (or in the master buffer)
 	MacroData const & getMacro(docstring const & name) const;
-	///
-	void insertMacro(docstring const & name, MacroData const & data);
 
 	///
 	void saveCursor(StableDocIterator cursor, StableDocIterator anchor);
Index: BufferView.C
===================================================================
--- BufferView.C	(Revision 17867)
+++ BufferView.C	(Arbeitskopie)
@@ -358,7 +358,7 @@
 
 	// Update macro store
 	if (!(cursor().inMathed() && cursor().inMacroMode()))
-		buffer_->buildMacros();
+		buffer_->updateMacros();
 
 	// Now do the first drawing step if needed. This consists on updating
 	// the CoordCache in updateMetrics().
Index: paragraph.C
===================================================================
--- paragraph.C	(Revision 17867)
+++ paragraph.C	(Arbeitskopie)
@@ -1640,4 +1640,16 @@
 	return true;
 }
 
+
+unsigned int Paragraph::macrocontextPosition() const
+{
+	return pimpl_->macrocontext_position_;
+}
+
+
+void Paragraph::setMacrocontextPosition(unsigned int pos)
+{
+	pimpl_->macrocontext_position_ = pos;
+}
+
 } // namespace lyx
Index: metricsinfo.C
===================================================================
--- metricsinfo.C	(Revision 17867)
+++ metricsinfo.C	(Arbeitskopie)
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author André Pönitz
+ * \author Stefan Schimanski
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -33,22 +34,16 @@
 
 
 MetricsBase::MetricsBase(BufferView * b, LyXFont const & f, int w)
-	: bv(b), font(f), style(LM_ST_TEXT), fontname("mathnormal"),
-	  textwidth(w)
+	: bv(b), font(f), style(LM_ST_TEXT), fontname("mathnormal"), textwidth(w)
 {}
 
 
-
-MetricsInfo::MetricsInfo()
+MetricsInfo::MetricsInfo(BufferView * bv, LyXFont const & font, int textwidth, 
+												 MacroContext const & mc)
+	: base(bv, font, textwidth), macrocontext(mc)
 {}
 
 
-MetricsInfo::MetricsInfo(BufferView * bv, LyXFont const & font, int textwidth)
-	: base(bv, font, textwidth)
-{}
-
-
-
 PainterInfo::PainterInfo(BufferView * bv, lyx::frontend::Painter & painter)
 	: pain(painter), ltr_pos(false), erased_(false)
 {
