This pair of patches is for
http://bugzilla.lyx.org/show_bug.cgi?id=1987

   Test case:
   1. New document
   2. Change layout of empty paragraph to "Date"
   3. Change document class to "Broadway"
   => Crash

I began by trying to move more code (in particular the
LFUN_TEXTCLASS_APPLY) into LFUN_BUFFERPARAMS_APPLY. I think this is
sound, and it fixes the bug (what happens is that LFUN_TEXTCLASS_APPLY
changes the layouts of the paragraphs when needed, but does not touch
the textclass itself; thus, if there is an update before
LFUN_BUFFERPARAMS_APPLY is run, the code that sets the layout bar
crashes).

The result is classcrash.diff below, which contains several contents
telling where more cleanup can/should be done.

Then it occurred to me that it is enough to just set the textclass in
LFUN_TEXTCLASS_APPLY.

JMarc

Index: src/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ChangeLog,v
retrieving revision 1.2280
diff -u -p -r1.2280 ChangeLog
--- src/ChangeLog	15 Sep 2005 16:00:27 -0000	1.2280
+++ src/ChangeLog	16 Sep 2005 10:54:38 -0000
@@ -1,3 +1,8 @@
+2005-09-16  Jean-Marc Lasgouttes  <[EMAIL PROTECTED]>
+
+	* lyxfunc.C (dispatch): make LFUN_BUFFERPARAMS_APPLY perform the
+	task previously devoted to LFUN_TEXTCLASS_APPLY (bug 1987).
+
 2005-09-14  Michael Gerz  <[EMAIL PROTECTED]>
 
 	* lyxfunc.C: update display after LFUN_ALL_INSETS_TOGGLE
Index: src/lyxfunc.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxfunc.C,v
retrieving revision 1.667
diff -u -p -r1.667 lyxfunc.C
--- src/lyxfunc.C	15 Sep 2005 16:00:29 -0000	1.667
+++ src/lyxfunc.C	16 Sep 2005 10:54:38 -0000
@@ -1454,14 +1454,16 @@ void LyXFunc::dispatch(FuncRequest const
 		}
 
 		case LFUN_BUFFERPARAMS_APPLY: {
-			biblio::CiteEngine const engine =
-				owner->buffer()->params().cite_engine;
+			// FIXME: we may want to move this code to
+			// buffer_funcs.C, especially if it inherits
+			// some code from ControlDocument. (JMarc)
+			Buffer & buf = *owner->buffer();
+			BufferParams old_params = buf.params();
 
 			istringstream ss(argument);
 			LyXLex lex(0,0);
 			lex.setStream(ss);
-			int const unknown_tokens =
-				owner->buffer()->readHeader(lex);
+			int const unknown_tokens = buf.readHeader(lex);
 
 			if (unknown_tokens != 0) {
 				lyxerr << "Warning in LFUN_BUFFERPARAMS_APPLY!\n"
@@ -1469,22 +1471,46 @@ void LyXFunc::dispatch(FuncRequest const
 				       << (unknown_tokens == 1 ? "" : "s")
 				       << endl;
 			}
-			if (engine == owner->buffer()->params().cite_engine)
-				break;
 
-			LCursor & cur = view()->cursor();
-			FuncRequest fr(LFUN_INSET_REFRESH);
+			BufferParams const & params = buf.params();
 
-			InsetBase & inset = owner->buffer()->inset();
-			InsetIterator it  = inset_iterator_begin(inset);
-			InsetIterator const end = inset_iterator_end(inset);
-			for (; it != end; ++it)
-				if (it->lyxCode() == InsetBase::CITE_CODE)
-					it->dispatch(cur, fr);
+			if (old_params.cite_engine != params.cite_engine) {
+
+				LCursor & cur = view()->cursor();
+				FuncRequest fr(LFUN_INSET_REFRESH);
+
+				InsetBase & inset = buf.inset();
+				InsetIterator it  = inset_iterator_begin(inset);
+				InsetIterator const end = inset_iterator_end(inset);
+				for (; it != end; ++it)
+					if (it->lyxCode() == InsetBase::CITE_CODE)
+						it->dispatch(cur, fr);
+			}
+
+			if (old_params.textclass != params.textclass) {
+				owner->message(_("Converting document to new document class..."));
+				textclasslist[params.textclass].load();
+				recordUndoFullDocument(view());
+				StableDocIterator backcur(view()->cursor());
+				ErrorList el;
+				lyx::cap::SwitchBetweenClasses(
+					old_params.textclass, 
+					params.textclass,
+					buf.paragraphs(), el);
+
+				view()->setCursor(backcur.asDocIterator(&(buf.inset())));
+				bufferErrors(buf, el);
+				view()->showErrorList(_("Class switch"));
+				updateCounters(buf);
+				update = true;
+			}
 			break;
 		}
 
 		case LFUN_TEXTCLASS_APPLY: {
+			//FIXME: the functionality of this is
+			//duplicated in LFUN_BUFFERPARAMS_APPLY; it is
+			//not clear that this LFUN should be kept. (JMarc)
 			recordUndoFullDocument(view());
 			Buffer * buffer = owner->buffer();
 
Index: src/frontends/controllers/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/controllers/ChangeLog,v
retrieving revision 1.497
diff -u -p -r1.497 ChangeLog
--- src/frontends/controllers/ChangeLog	15 Sep 2005 14:56:27 -0000	1.497
+++ src/frontends/controllers/ChangeLog	16 Sep 2005 10:54:38 -0000
@@ -1,3 +1,9 @@
+2005-09-16  Jean-Marc Lasgouttes  <[EMAIL PROTECTED]>
+
+	* ControlDocument.C (dispatchParams): do not invoke
+	LFUN_TEXTCLASS_APPLY, to avoid a spurious update that can cause a
+	crash. This job is now done by LFUN_BUFFERPARAMS_APPLY (bug 1987).
+
 2005-09-15  Jürgen Spitzmüller  <[EMAIL PROTECTED]>
 
 	* ControlDocument.C (dispatchParams): update bufferview at the end
Index: src/frontends/controllers/ControlDocument.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/controllers/ControlDocument.C,v
retrieving revision 1.56
diff -u -p -r1.56 ControlDocument.C
--- src/frontends/controllers/ControlDocument.C	15 Sep 2005 14:56:28 -0000	1.56
+++ src/frontends/controllers/ControlDocument.C	16 Sep 2005 10:54:38 -0000
@@ -87,25 +87,18 @@ void ControlDocument::dispatchParams()
 	// This must come first so that a language change is correctly noticed
 	setLanguage();
 
-	// Set the document class.
-	textclass_type const old_class =
-		kernel().buffer().params().textclass;
-	textclass_type const new_class = bp_->textclass;
-	if (new_class != old_class) {
-		string const name = textclasslist[new_class].name();
-		kernel().dispatch(FuncRequest(LFUN_TEXTCLASS_APPLY, name));
-	}
-
 	int const old_secnumdepth = kernel().buffer().params().secnumdepth;
 	int const new_secnumdepth = bp_->secnumdepth;
 
 	// Apply the BufferParams.
 	dispatch_bufferparams(kernel(), params(), LFUN_BUFFERPARAMS_APPLY);
 
+	// FIXME: this should be done by LFUN_BUFFERPARAMS_APPLY (JMarc)
 	// redo the numbering if necessary
 	if (new_secnumdepth != old_secnumdepth)
 		updateCounters(kernel().buffer());
 
+	// FIXME: this should be done by LFUN_BUFFERPARAMS_APPLY (JMarc)
 	// Generate the colours requested by each new branch.
 	BranchList & branchlist = params().branchlist();
 	if (!branchlist.empty()) {
Index: src/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ChangeLog,v
retrieving revision 1.2280
diff -u -p -r1.2280 ChangeLog
--- src/ChangeLog	15 Sep 2005 16:00:27 -0000	1.2280
+++ src/ChangeLog	16 Sep 2005 11:02:18 -0000
@@ -1,3 +1,8 @@
+2005-09-16  Jean-Marc Lasgouttes  <[EMAIL PROTECTED]>
+
+	* lyxfunc.C (dispatch): LFUN_TEXTCLASS_APPLY: actually set the
+	textclass (bug 1987); do not record undo if nothing is changed.
+
 2005-09-14  Michael Gerz  <[EMAIL PROTECTED]>
 
 	* lyxfunc.C: update display after LFUN_ALL_INSETS_TOGGLE
Index: src/lyxfunc.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxfunc.C,v
retrieving revision 1.667
diff -u -p -r1.667 lyxfunc.C
--- src/lyxfunc.C	15 Sep 2005 16:00:29 -0000	1.667
+++ src/lyxfunc.C	16 Sep 2005 11:02:18 -0000
@@ -1485,7 +1485,6 @@ void LyXFunc::dispatch(FuncRequest const
 		}
 
 		case LFUN_TEXTCLASS_APPLY: {
-			recordUndoFullDocument(view());
 			Buffer * buffer = owner->buffer();
 
 			lyx::textclass_type const old_class =
@@ -1505,6 +1504,8 @@ void LyXFunc::dispatch(FuncRequest const
 				break;
 
 			owner->message(_("Converting document to new document class..."));
+			recordUndoFullDocument(view());
+			buffer->params().textclass = new_class;
 			StableDocIterator backcur(view()->cursor());
 			ErrorList el;
 			lyx::cap::SwitchBetweenClasses(

Reply via email to