2003-08-23 00:17:00 +00:00
|
|
|
|
/**
|
2007-11-29 21:10:35 +00:00
|
|
|
|
* \file src/Text.cpp
|
2003-08-23 00:17:00 +00:00
|
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
|
* Licence details can be found in the file COPYING.
|
2002-03-21 17:27:08 +00:00
|
|
|
|
*
|
2003-08-23 00:17:00 +00:00
|
|
|
|
* \author Asger Alstrup
|
|
|
|
|
* \author Lars Gullik Bj<EFBFBD>nnes
|
2007-06-08 14:24:57 +00:00
|
|
|
|
* \author Dov Feldstern
|
2003-08-23 00:17:00 +00:00
|
|
|
|
* \author Jean-Marc Lasgouttes
|
|
|
|
|
* \author John Levon
|
|
|
|
|
* \author Andr<EFBFBD> P<EFBFBD>nitz
|
2007-06-04 18:41:56 +00:00
|
|
|
|
* \author Stefan Schimanski
|
2003-08-23 00:17:00 +00:00
|
|
|
|
* \author Dekel Tsur
|
|
|
|
|
* \author J<EFBFBD>rgen Vigna
|
2002-03-21 17:27:08 +00:00
|
|
|
|
*
|
2003-08-23 00:17:00 +00:00
|
|
|
|
* Full author contact details are available in file CREDITS.
|
|
|
|
|
*/
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
#include "Text.h"
|
2003-09-06 23:36:02 +00:00
|
|
|
|
|
2007-04-26 04:41:58 +00:00
|
|
|
|
#include "Author.h"
|
|
|
|
|
#include "Buffer.h"
|
2005-02-25 11:55:36 +00:00
|
|
|
|
#include "buffer_funcs.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
|
#include "BufferParams.h"
|
2003-09-06 23:36:02 +00:00
|
|
|
|
#include "BufferView.h"
|
2007-10-18 15:29:51 +00:00
|
|
|
|
#include "Changes.h"
|
2007-04-26 14:56:30 +00:00
|
|
|
|
#include "Cursor.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
|
#include "ParIterator.h"
|
2004-03-25 09:16:36 +00:00
|
|
|
|
#include "CutAndPaste.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
|
#include "DispatchResult.h"
|
|
|
|
|
#include "Encoding.h"
|
|
|
|
|
#include "ErrorList.h"
|
|
|
|
|
#include "FuncRequest.h"
|
2004-03-25 09:16:36 +00:00
|
|
|
|
#include "factory.h"
|
2004-03-01 10:46:58 +00:00
|
|
|
|
#include "FontIterator.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
|
#include "Language.h"
|
2007-04-28 12:58:49 +00:00
|
|
|
|
#include "Length.h"
|
2007-04-26 11:30:54 +00:00
|
|
|
|
#include "Lexer.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
|
#include "LyXRC.h"
|
|
|
|
|
#include "Paragraph.h"
|
2003-09-06 23:36:02 +00:00
|
|
|
|
#include "paragraph_funcs.h"
|
2001-06-25 00:06:33 +00:00
|
|
|
|
#include "ParagraphParameters.h"
|
2007-11-07 23:34:45 +00:00
|
|
|
|
#include "TextClass.h"
|
2007-10-11 09:59:01 +00:00
|
|
|
|
#include "TextMetrics.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
|
#include "VSpace.h"
|
2002-08-13 14:40:38 +00:00
|
|
|
|
#include "WordLangTuple.h"
|
2003-09-06 23:36:02 +00:00
|
|
|
|
|
2007-04-25 01:24:38 +00:00
|
|
|
|
#include "insets/InsetText.h"
|
|
|
|
|
#include "insets/InsetBibitem.h"
|
|
|
|
|
#include "insets/InsetCaption.h"
|
|
|
|
|
#include "insets/InsetHFill.h"
|
|
|
|
|
#include "insets/InsetLine.h"
|
|
|
|
|
#include "insets/InsetNewline.h"
|
2007-11-23 02:10:00 +00:00
|
|
|
|
#include "insets/InsetNewpage.h"
|
2007-04-25 01:24:38 +00:00
|
|
|
|
#include "insets/InsetOptArg.h"
|
|
|
|
|
#include "insets/InsetSpace.h"
|
|
|
|
|
#include "insets/InsetSpecialChar.h"
|
|
|
|
|
#include "insets/InsetTabular.h"
|
2001-11-15 00:39:11 +00:00
|
|
|
|
|
2007-11-29 21:10:35 +00:00
|
|
|
|
#include "support/convert.h"
|
|
|
|
|
#include "support/debug.h"
|
2007-11-01 22:17:22 +00:00
|
|
|
|
#include "support/docstream.h"
|
2007-11-29 21:10:35 +00:00
|
|
|
|
#include "support/gettext.h"
|
2001-11-15 00:39:11 +00:00
|
|
|
|
#include "support/lstrings.h"
|
2003-09-06 23:36:02 +00:00
|
|
|
|
#include "support/textutils.h"
|
2004-07-24 10:55:30 +00:00
|
|
|
|
|
2007-10-02 18:27:20 +00:00
|
|
|
|
#include <boost/next_prior.hpp>
|
2005-09-26 09:20:15 +00:00
|
|
|
|
|
2004-07-24 10:55:30 +00:00
|
|
|
|
#include <sstream>
|
2001-11-15 00:39:11 +00:00
|
|
|
|
|
2007-12-12 10:16:00 +00:00
|
|
|
|
using namespace std;
|
2007-12-12 18:57:56 +00:00
|
|
|
|
using namespace lyx::support;
|
2003-09-09 22:13:45 +00:00
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
namespace lyx {
|
2003-06-30 23:56:22 +00:00
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
using cap::cutSelection;
|
|
|
|
|
using cap::pasteParagraphList;
|
|
|
|
|
|
2003-10-23 09:06:18 +00:00
|
|
|
|
namespace {
|
|
|
|
|
|
2007-04-26 11:30:54 +00:00
|
|
|
|
void readParToken(Buffer const & buf, Paragraph & par, Lexer & lex,
|
2007-04-29 18:17:15 +00:00
|
|
|
|
string const & token, Font & font, Change & change, ErrorList & errorList)
|
2004-03-25 09:16:36 +00:00
|
|
|
|
{
|
|
|
|
|
BufferParams const & bp = buf.params();
|
|
|
|
|
|
|
|
|
|
if (token[0] != '\\') {
|
2006-10-21 00:16:43 +00:00
|
|
|
|
docstring dstr = lex.getDocString();
|
2007-10-22 13:09:16 +00:00
|
|
|
|
par.appendString(dstr, font, change);
|
|
|
|
|
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\begin_layout") {
|
|
|
|
|
lex.eatLine();
|
2007-07-11 13:39:08 +00:00
|
|
|
|
docstring layoutname = lex.getDocString();
|
2004-03-25 09:16:36 +00:00
|
|
|
|
|
2007-10-28 18:51:54 +00:00
|
|
|
|
font = Font(inherit_font, bp.language);
|
2006-10-11 20:01:32 +00:00
|
|
|
|
change = Change(Change::UNCHANGED);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
|
2008-02-28 01:42:02 +00:00
|
|
|
|
DocumentClass const & tclass = bp.documentClass();
|
2004-03-25 09:16:36 +00:00
|
|
|
|
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
if (layoutname.empty())
|
2004-03-25 09:16:36 +00:00
|
|
|
|
layoutname = tclass.defaultLayoutName();
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
|
It used to be that things like InsetFlex, InsetCaption, and the like used the default layout, whatever that is---usually Standard. That gave rise to bug 2178, the solution to which is to define a new empty layout, which insets like these use instead of the default. See r22966.
So, when we have an older LyX file, it will look like this:
\begin_inset ERT
status open
\begin_layout Standard
this that
\end_layout
\end_inset
which is now invalid, because ERT uses only PlainLayout. So I had put some code into Text::readParToken, where the layout for a paragraph gets set as it is read:
if (par.forceEmptyLayout()) {
// in this case only the empty layout is allowed
layoutname = tclass.emptyLayoutName();
} else if (par.useEmptyLayout()) {
// in this case, default layout maps to empty layout
if (layoutname == tclass.defaultLayoutName())
layoutname = tclass.emptyLayoutName();
} else {
// otherwise, the empty layout maps to the default
if (layoutname == tclass.emptyLayoutName())
layoutname = tclass.defaultLayoutName();
}
This turns out not to work, because par.forceEmptyLayout() and par.useEmptyLayout() always return false here, because par.inInset() always returns a null pointer, because the paragraph's inset hasn't yet been set when Text::readParagraph() gets called from Text::read() gets called from InsetText::read(). The solution is to set the paragraph's inset when it is created, which means passing a pointer to the various read() routines along the way.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23057 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-19 02:35:07 +00:00
|
|
|
|
if (par.forceEmptyLayout()) {
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
// in this case only the empty layout is allowed
|
|
|
|
|
layoutname = tclass.emptyLayoutName();
|
It used to be that things like InsetFlex, InsetCaption, and the like used the default layout, whatever that is---usually Standard. That gave rise to bug 2178, the solution to which is to define a new empty layout, which insets like these use instead of the default. See r22966.
So, when we have an older LyX file, it will look like this:
\begin_inset ERT
status open
\begin_layout Standard
this that
\end_layout
\end_inset
which is now invalid, because ERT uses only PlainLayout. So I had put some code into Text::readParToken, where the layout for a paragraph gets set as it is read:
if (par.forceEmptyLayout()) {
// in this case only the empty layout is allowed
layoutname = tclass.emptyLayoutName();
} else if (par.useEmptyLayout()) {
// in this case, default layout maps to empty layout
if (layoutname == tclass.defaultLayoutName())
layoutname = tclass.emptyLayoutName();
} else {
// otherwise, the empty layout maps to the default
if (layoutname == tclass.emptyLayoutName())
layoutname = tclass.defaultLayoutName();
}
This turns out not to work, because par.forceEmptyLayout() and par.useEmptyLayout() always return false here, because par.inInset() always returns a null pointer, because the paragraph's inset hasn't yet been set when Text::readParagraph() gets called from Text::read() gets called from InsetText::read(). The solution is to set the paragraph's inset when it is created, which means passing a pointer to the various read() routines along the way.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23057 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-19 02:35:07 +00:00
|
|
|
|
} else if (par.useEmptyLayout()) {
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
// in this case, default layout maps to empty layout
|
|
|
|
|
if (layoutname == tclass.defaultLayoutName())
|
|
|
|
|
layoutname = tclass.emptyLayoutName();
|
|
|
|
|
} else {
|
|
|
|
|
// otherwise, the empty layout maps to the default
|
|
|
|
|
if (layoutname == tclass.emptyLayoutName())
|
|
|
|
|
layoutname = tclass.defaultLayoutName();
|
2004-03-25 09:16:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool hasLayout = tclass.hasLayout(layoutname);
|
|
|
|
|
|
|
|
|
|
if (!hasLayout) {
|
2006-09-11 08:54:10 +00:00
|
|
|
|
errorList.push_back(ErrorItem(_("Unknown layout"),
|
|
|
|
|
bformat(_("Layout '%1$s' does not exist in textclass '%2$s'\nTrying to use the default instead.\n"),
|
2007-07-11 13:39:08 +00:00
|
|
|
|
layoutname, from_utf8(tclass.name())), par.id(), 0, par.size()));
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
layoutname = par.useEmptyLayout() ?
|
|
|
|
|
tclass.emptyLayoutName() :
|
|
|
|
|
tclass.defaultLayoutName();
|
2004-03-25 09:16:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-02-28 01:42:02 +00:00
|
|
|
|
par.setLayout(bp.documentClass()[layoutname]);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
|
|
|
|
|
// Test whether the layout is obsolete.
|
2007-08-23 19:59:07 +00:00
|
|
|
|
LayoutPtr const & layout = par.layout();
|
2004-03-25 09:16:36 +00:00
|
|
|
|
if (!layout->obsoleted_by().empty())
|
2008-02-28 01:42:02 +00:00
|
|
|
|
par.setLayout(bp.documentClass()[layout->obsoleted_by()]);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
|
|
|
|
|
par.params().read(lex);
|
|
|
|
|
|
|
|
|
|
} else if (token == "\\end_layout") {
|
2007-11-29 21:10:35 +00:00
|
|
|
|
LYXERR0("Solitary \\end_layout in line " << lex.getLineNo() << "\n"
|
|
|
|
|
<< "Missing \\begin_layout ?");
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\end_inset") {
|
2007-11-29 21:10:35 +00:00
|
|
|
|
LYXERR0("Solitary \\end_inset in line " << lex.getLineNo() << "\n"
|
|
|
|
|
<< "Missing \\begin_inset ?");
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\begin_inset") {
|
2007-04-29 13:39:47 +00:00
|
|
|
|
Inset * inset = readInset(lex, buf);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
if (inset)
|
|
|
|
|
par.insertInset(par.size(), inset, font, change);
|
|
|
|
|
else {
|
|
|
|
|
lex.eatLine();
|
2006-11-22 09:15:38 +00:00
|
|
|
|
docstring line = lex.getDocString();
|
2006-09-11 08:54:10 +00:00
|
|
|
|
errorList.push_back(ErrorItem(_("Unknown Inset"), line,
|
2004-03-25 09:16:36 +00:00
|
|
|
|
par.id(), 0, par.size()));
|
|
|
|
|
}
|
|
|
|
|
} else if (token == "\\family") {
|
|
|
|
|
lex.next();
|
2007-10-28 18:51:54 +00:00
|
|
|
|
setLyXFamily(lex.getString(), font.fontInfo());
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\series") {
|
|
|
|
|
lex.next();
|
2007-10-28 18:51:54 +00:00
|
|
|
|
setLyXSeries(lex.getString(), font.fontInfo());
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\shape") {
|
|
|
|
|
lex.next();
|
2007-10-28 18:51:54 +00:00
|
|
|
|
setLyXShape(lex.getString(), font.fontInfo());
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\size") {
|
|
|
|
|
lex.next();
|
2007-10-28 18:51:54 +00:00
|
|
|
|
setLyXSize(lex.getString(), font.fontInfo());
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\lang") {
|
|
|
|
|
lex.next();
|
|
|
|
|
string const tok = lex.getString();
|
|
|
|
|
Language const * lang = languages.getLanguage(tok);
|
|
|
|
|
if (lang) {
|
|
|
|
|
font.setLanguage(lang);
|
|
|
|
|
} else {
|
|
|
|
|
font.setLanguage(bp.language);
|
|
|
|
|
lex.printError("Unknown language `$$Token'");
|
|
|
|
|
}
|
|
|
|
|
} else if (token == "\\numeric") {
|
|
|
|
|
lex.next();
|
2007-10-28 18:51:54 +00:00
|
|
|
|
font.fontInfo().setNumber(font.setLyXMisc(lex.getString()));
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\emph") {
|
|
|
|
|
lex.next();
|
2007-10-28 18:51:54 +00:00
|
|
|
|
font.fontInfo().setEmph(font.setLyXMisc(lex.getString()));
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\bar") {
|
|
|
|
|
lex.next();
|
|
|
|
|
string const tok = lex.getString();
|
|
|
|
|
|
|
|
|
|
if (tok == "under")
|
2007-10-28 18:51:54 +00:00
|
|
|
|
font.fontInfo().setUnderbar(FONT_ON);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
else if (tok == "no")
|
2007-10-28 18:51:54 +00:00
|
|
|
|
font.fontInfo().setUnderbar(FONT_OFF);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
else if (tok == "default")
|
2007-10-28 18:51:54 +00:00
|
|
|
|
font.fontInfo().setUnderbar(FONT_INHERIT);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
else
|
|
|
|
|
lex.printError("Unknown bar font flag "
|
|
|
|
|
"`$$Token'");
|
|
|
|
|
} else if (token == "\\noun") {
|
|
|
|
|
lex.next();
|
2007-10-28 18:51:54 +00:00
|
|
|
|
font.fontInfo().setNoun(font.setLyXMisc(lex.getString()));
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\color") {
|
|
|
|
|
lex.next();
|
2007-10-28 18:51:54 +00:00
|
|
|
|
setLyXColor(lex.getString(), font.fontInfo());
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\InsetSpace" || token == "\\SpecialChar") {
|
|
|
|
|
|
|
|
|
|
// Insets don't make sense in a free-spacing context! ---Kayvan
|
|
|
|
|
if (par.isFreeSpacing()) {
|
|
|
|
|
if (token == "\\InsetSpace")
|
2007-10-22 13:09:16 +00:00
|
|
|
|
par.appendChar(' ', font, change);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
else if (lex.isOK()) {
|
|
|
|
|
lex.next();
|
|
|
|
|
string const next_token = lex.getString();
|
|
|
|
|
if (next_token == "\\-")
|
2007-10-22 13:09:16 +00:00
|
|
|
|
par.appendChar('-', font, change);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
else {
|
|
|
|
|
lex.printError("Token `$$Token' "
|
|
|
|
|
"is in free space "
|
|
|
|
|
"paragraph layout!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2007-04-29 13:39:47 +00:00
|
|
|
|
auto_ptr<Inset> inset;
|
2004-03-25 09:16:36 +00:00
|
|
|
|
if (token == "\\SpecialChar" )
|
|
|
|
|
inset.reset(new InsetSpecialChar);
|
|
|
|
|
else
|
|
|
|
|
inset.reset(new InsetSpace);
|
2008-02-27 20:43:16 +00:00
|
|
|
|
inset->read(lex);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
par.insertInset(par.size(), inset.release(),
|
|
|
|
|
font, change);
|
|
|
|
|
}
|
|
|
|
|
} else if (token == "\\backslash") {
|
2007-10-22 13:09:16 +00:00
|
|
|
|
par.appendChar('\\', font, change);
|
2007-11-25 18:34:37 +00:00
|
|
|
|
} else if (token == "\\linebreak") {
|
|
|
|
|
auto_ptr<Inset> inset(new InsetLinebreak);
|
2008-02-27 20:43:16 +00:00
|
|
|
|
inset->read(lex);
|
2007-11-25 18:34:37 +00:00
|
|
|
|
par.insertInset(par.size(), inset.release(), font, change);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\newline") {
|
2007-04-29 13:39:47 +00:00
|
|
|
|
auto_ptr<Inset> inset(new InsetNewline);
|
2008-02-27 20:43:16 +00:00
|
|
|
|
inset->read(lex);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
par.insertInset(par.size(), inset.release(), font, change);
|
|
|
|
|
} else if (token == "\\LyXTable") {
|
2007-04-29 13:39:47 +00:00
|
|
|
|
auto_ptr<Inset> inset(new InsetTabular(buf));
|
2008-02-27 20:43:16 +00:00
|
|
|
|
inset->read(lex);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
par.insertInset(par.size(), inset.release(), font, change);
|
|
|
|
|
} else if (token == "\\hfill") {
|
|
|
|
|
par.insertInset(par.size(), new InsetHFill, font, change);
|
|
|
|
|
} else if (token == "\\lyxline") {
|
|
|
|
|
par.insertInset(par.size(), new InsetLine, font, change);
|
|
|
|
|
} else if (token == "\\newpage") {
|
2007-11-23 02:10:00 +00:00
|
|
|
|
par.insertInset(par.size(), new InsetNewpage, font, change);
|
|
|
|
|
} else if (token == "\\pagebreak") {
|
2004-03-25 09:16:36 +00:00
|
|
|
|
par.insertInset(par.size(), new InsetPagebreak, font, change);
|
2006-11-25 15:09:01 +00:00
|
|
|
|
} else if (token == "\\clearpage") {
|
|
|
|
|
par.insertInset(par.size(), new InsetClearPage, font, change);
|
|
|
|
|
} else if (token == "\\cleardoublepage") {
|
|
|
|
|
par.insertInset(par.size(), new InsetClearDoublePage, font, change);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\change_unchanged") {
|
|
|
|
|
change = Change(Change::UNCHANGED);
|
|
|
|
|
} else if (token == "\\change_inserted") {
|
2004-10-05 12:56:22 +00:00
|
|
|
|
lex.eatLine();
|
2007-12-12 19:28:07 +00:00
|
|
|
|
istringstream is(lex.getString());
|
2006-07-06 08:18:51 +00:00
|
|
|
|
unsigned int aid;
|
2007-11-29 08:55:43 +00:00
|
|
|
|
time_t ct;
|
2004-03-25 09:16:36 +00:00
|
|
|
|
is >> aid >> ct;
|
2006-06-07 17:05:25 +00:00
|
|
|
|
if (aid >= bp.author_map.size()) {
|
2006-09-11 08:54:10 +00:00
|
|
|
|
errorList.push_back(ErrorItem(_("Change tracking error"),
|
|
|
|
|
bformat(_("Unknown author index for insertion: %1$d\n"), aid),
|
2006-06-07 17:05:25 +00:00
|
|
|
|
par.id(), 0, par.size()));
|
|
|
|
|
change = Change(Change::UNCHANGED);
|
|
|
|
|
} else
|
|
|
|
|
change = Change(Change::INSERTED, bp.author_map[aid], ct);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else if (token == "\\change_deleted") {
|
2004-10-05 12:56:22 +00:00
|
|
|
|
lex.eatLine();
|
2007-12-12 19:28:07 +00:00
|
|
|
|
istringstream is(lex.getString());
|
2006-07-06 08:18:51 +00:00
|
|
|
|
unsigned int aid;
|
2007-11-29 08:55:43 +00:00
|
|
|
|
time_t ct;
|
2004-03-25 09:16:36 +00:00
|
|
|
|
is >> aid >> ct;
|
2006-06-07 17:05:25 +00:00
|
|
|
|
if (aid >= bp.author_map.size()) {
|
2006-09-11 08:54:10 +00:00
|
|
|
|
errorList.push_back(ErrorItem(_("Change tracking error"),
|
|
|
|
|
bformat(_("Unknown author index for deletion: %1$d\n"), aid),
|
2006-06-07 17:05:25 +00:00
|
|
|
|
par.id(), 0, par.size()));
|
|
|
|
|
change = Change(Change::UNCHANGED);
|
|
|
|
|
} else
|
|
|
|
|
change = Change(Change::DELETED, bp.author_map[aid], ct);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
} else {
|
|
|
|
|
lex.eatLine();
|
2006-09-11 08:54:10 +00:00
|
|
|
|
errorList.push_back(ErrorItem(_("Unknown token"),
|
2006-10-21 00:16:43 +00:00
|
|
|
|
bformat(_("Unknown token: %1$s %2$s\n"), from_utf8(token),
|
2006-11-22 09:15:38 +00:00
|
|
|
|
lex.getDocString()),
|
2004-03-25 09:16:36 +00:00
|
|
|
|
par.id(), 0, par.size()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-26 11:30:54 +00:00
|
|
|
|
void readParagraph(Buffer const & buf, Paragraph & par, Lexer & lex,
|
2006-10-21 00:16:43 +00:00
|
|
|
|
ErrorList & errorList)
|
2004-03-25 09:16:36 +00:00
|
|
|
|
{
|
|
|
|
|
lex.nextToken();
|
|
|
|
|
string token = lex.getString();
|
2007-04-29 18:17:15 +00:00
|
|
|
|
Font font;
|
2006-10-11 20:01:32 +00:00
|
|
|
|
Change change(Change::UNCHANGED);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
|
|
|
|
|
while (lex.isOK()) {
|
2006-08-13 16:16:43 +00:00
|
|
|
|
readParToken(buf, par, lex, token, font, change, errorList);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
|
|
|
|
|
lex.nextToken();
|
|
|
|
|
token = lex.getString();
|
|
|
|
|
|
|
|
|
|
if (token.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (token == "\\end_layout") {
|
|
|
|
|
//Ok, paragraph finished
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-15 20:04:51 +00:00
|
|
|
|
LYXERR(Debug::PARSER, "Handling paragraph token: `" << token << '\'');
|
2004-03-25 09:16:36 +00:00
|
|
|
|
if (token == "\\begin_layout" || token == "\\end_document"
|
|
|
|
|
|| token == "\\end_inset" || token == "\\begin_deeper"
|
|
|
|
|
|| token == "\\end_deeper") {
|
|
|
|
|
lex.pushToken(token);
|
|
|
|
|
lyxerr << "Paragraph ended in line "
|
|
|
|
|
<< lex.getLineNo() << "\n"
|
|
|
|
|
<< "Missing \\end_layout.\n";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-03-11 13:31:41 +00:00
|
|
|
|
// Final change goes to paragraph break:
|
2006-05-08 20:30:52 +00:00
|
|
|
|
par.setChange(par.size(), change);
|
2006-04-05 23:56:29 +00:00
|
|
|
|
|
2005-06-16 15:15:33 +00:00
|
|
|
|
// Initialize begin_of_body_ on load; redoParagraph maintains
|
|
|
|
|
par.setBeginOfBody();
|
2004-03-25 09:16:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-10-23 09:06:18 +00:00
|
|
|
|
} // namespace anon
|
|
|
|
|
|
|
|
|
|
|
2007-08-14 16:59:59 +00:00
|
|
|
|
bool Text::empty() const
|
|
|
|
|
{
|
|
|
|
|
return pars_.empty() || (pars_.size() == 1 && pars_[0].empty()
|
|
|
|
|
// FIXME: Should we consider the labeled type as empty too?
|
|
|
|
|
&& pars_[0].layout()->labeltype == LABEL_NO_LABEL);
|
|
|
|
|
}
|
|
|
|
|
|
2003-03-17 16:25:00 +00:00
|
|
|
|
|
2008-02-23 16:45:38 +00:00
|
|
|
|
double Text::spacing(Buffer const & buffer, Paragraph const & par) const
|
2003-03-17 16:25:00 +00:00
|
|
|
|
{
|
2004-04-08 15:03:33 +00:00
|
|
|
|
if (par.params().spacing().isDefault())
|
Move BufferView cached pointer out of LyXText:
* LyXText
- bv(), bv_owner, : deleted.
- These methods now need a (Buffer const &) argument: getFont(), applyOuterFont(), getLayoutFont(), getLabelFont(), setCharFont(), setLayout(), singleWidth(), leftMargin(), rightMargin(), computeRowMetrics(), isMainText(), spacing(), isRTL(), cursorX(), rowBreakPoint(), setRowWidth(), labelFill(), labelEnd().
- These methods now need a (BufferView const &) argument and are propably candidates for future removal when 1.6 is opened for development: redoParagraph(), x2pos(), getRowNearY(), getColumnNearX(), checkInsetHit(), setHeightOfRow().
- recUndo(): now need a LCursor argument.
* CoordCache::get(LyXText const *, pit_type):
- now const.
- use const_iterator instead of iterator.
* FontIterator:
- add (Buffer const &) argument to ctor
- buffer_: new const reference to applicable BufferView.
* InsetBase
- xo(), yo(), covers() and neverIndent() are now const.
* InsetText::setViewCache(): deleted
All other changes are due to the LyXText and InsetBase API changes.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@15618 a592a061-630c-0410-9148-cb99ea01b6c8
2006-10-30 12:45:33 +00:00
|
|
|
|
return buffer.params().spacing().getValue();
|
2004-04-08 15:03:33 +00:00
|
|
|
|
return par.params().spacing().getValue();
|
2003-03-17 16:25:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-10-08 13:17:15 +00:00
|
|
|
|
void Text::breakParagraph(Cursor & cur, bool inverse_logic)
|
2000-02-10 17:53:36 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2006-03-11 13:31:41 +00:00
|
|
|
|
|
2004-02-12 16:36:01 +00:00
|
|
|
|
Paragraph & cpar = cur.paragraph();
|
2004-11-24 21:53:46 +00:00
|
|
|
|
pit_type cpit = cur.pit();
|
2004-02-12 16:36:01 +00:00
|
|
|
|
|
2008-02-28 01:42:02 +00:00
|
|
|
|
DocumentClass const & tclass = cur.buffer().params().documentClass();
|
2007-08-23 19:59:07 +00:00
|
|
|
|
LayoutPtr const & layout = cpar.layout();
|
2000-09-23 04:57:18 +00:00
|
|
|
|
|
2004-01-09 09:04:33 +00:00
|
|
|
|
// this is only allowed, if the current paragraph is not empty
|
|
|
|
|
// or caption and if it has not the keepempty flag active
|
2006-11-26 11:53:33 +00:00
|
|
|
|
if (cur.lastpos() == 0 && !cpar.allowEmpty() &&
|
|
|
|
|
layout->labeltype != LABEL_SENSITIVE)
|
2002-05-29 12:58:23 +00:00
|
|
|
|
return;
|
2002-03-21 17:27:08 +00:00
|
|
|
|
|
2004-01-09 09:04:33 +00:00
|
|
|
|
// a layout change may affect also the following paragraph
|
Move BufferView cached pointer out of LyXText:
* LyXText
- bv(), bv_owner, : deleted.
- These methods now need a (Buffer const &) argument: getFont(), applyOuterFont(), getLayoutFont(), getLabelFont(), setCharFont(), setLayout(), singleWidth(), leftMargin(), rightMargin(), computeRowMetrics(), isMainText(), spacing(), isRTL(), cursorX(), rowBreakPoint(), setRowWidth(), labelFill(), labelEnd().
- These methods now need a (BufferView const &) argument and are propably candidates for future removal when 1.6 is opened for development: redoParagraph(), x2pos(), getRowNearY(), getColumnNearX(), checkInsetHit(), setHeightOfRow().
- recUndo(): now need a LCursor argument.
* CoordCache::get(LyXText const *, pit_type):
- now const.
- use const_iterator instead of iterator.
* FontIterator:
- add (Buffer const &) argument to ctor
- buffer_: new const reference to applicable BufferView.
* InsetBase
- xo(), yo(), covers() and neverIndent() are now const.
* InsetText::setViewCache(): deleted
All other changes are due to the LyXText and InsetBase API changes.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@15618 a592a061-630c-0410-9148-cb99ea01b6c8
2006-10-30 12:45:33 +00:00
|
|
|
|
recUndo(cur, cur.pit(), undoSpan(cur.pit()) - 1);
|
2000-02-10 17:53:36 +00:00
|
|
|
|
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// Always break behind a space
|
|
|
|
|
// It is better to erase the space (Dekel)
|
2004-02-12 16:36:01 +00:00
|
|
|
|
if (cur.pos() != cur.lastpos() && cpar.isLineSeparator(cur.pos()))
|
2006-10-21 17:05:20 +00:00
|
|
|
|
cpar.eraseChar(cur.pos(), cur.buffer().params().trackChanges);
|
2002-05-29 12:58:23 +00:00
|
|
|
|
|
2006-11-26 11:53:33 +00:00
|
|
|
|
// What should the layout for the new paragraph be?
|
2007-10-08 13:17:15 +00:00
|
|
|
|
bool keep_layout = inverse_logic ?
|
|
|
|
|
!layout->isEnvironment()
|
|
|
|
|
: layout->isEnvironment();
|
2005-01-31 16:29:48 +00:00
|
|
|
|
|
|
|
|
|
// We need to remember this before we break the paragraph, because
|
|
|
|
|
// that invalidates the layout variable
|
|
|
|
|
bool sensitive = layout->labeltype == LABEL_SENSITIVE;
|
2002-05-29 12:58:23 +00:00
|
|
|
|
|
2005-01-31 16:29:48 +00:00
|
|
|
|
// we need to set this before we insert the paragraph.
|
2004-02-12 16:36:01 +00:00
|
|
|
|
bool const isempty = cpar.allowEmpty() && cpar.empty();
|
2005-01-31 16:29:48 +00:00
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
lyx::breakParagraph(cur.buffer().params(), paragraphs(), cpit,
|
2007-10-08 13:17:15 +00:00
|
|
|
|
cur.pos(), keep_layout);
|
2005-01-31 16:29:48 +00:00
|
|
|
|
|
|
|
|
|
// After this, neither paragraph contains any rows!
|
2000-09-23 04:57:18 +00:00
|
|
|
|
|
2004-11-24 21:53:46 +00:00
|
|
|
|
cpit = cur.pit();
|
|
|
|
|
pit_type next_par = cpit + 1;
|
2003-08-15 08:03:54 +00:00
|
|
|
|
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// well this is the caption hack since one caption is really enough
|
2005-01-31 16:29:48 +00:00
|
|
|
|
if (sensitive) {
|
2004-08-15 00:01:45 +00:00
|
|
|
|
if (cur.pos() == 0)
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// set to standard-layout
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
//FIXME Check if this should be emptyLayout() in some cases
|
2004-03-25 09:16:36 +00:00
|
|
|
|
pars_[cpit].applyLayout(tclass.defaultLayout());
|
2002-05-29 12:58:23 +00:00
|
|
|
|
else
|
|
|
|
|
// set to standard-layout
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
//FIXME Check if this should be emptyLayout() in some cases
|
2004-03-25 09:16:36 +00:00
|
|
|
|
pars_[next_par].applyLayout(tclass.defaultLayout());
|
2002-05-29 12:58:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-01-07 12:01:26 +00:00
|
|
|
|
while (!pars_[next_par].empty() && pars_[next_par].isNewline(0)) {
|
|
|
|
|
if (!pars_[next_par].eraseChar(0, cur.buffer().params().trackChanges))
|
|
|
|
|
break; // the character couldn't be deleted physically due to change tracking
|
|
|
|
|
}
|
2003-04-13 02:23:30 +00:00
|
|
|
|
|
2007-07-11 13:20:19 +00:00
|
|
|
|
updateLabels(cur.buffer());
|
2002-03-21 17:27:08 +00:00
|
|
|
|
|
2006-12-29 23:54:48 +00:00
|
|
|
|
// A singlePar update is not enough in this case.
|
|
|
|
|
cur.updateFlags(Update::Force);
|
2006-11-17 17:42:52 +00:00
|
|
|
|
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// This check is necessary. Otherwise the new empty paragraph will
|
|
|
|
|
// be deleted automatically. And it is more friendly for the user!
|
2004-02-12 16:36:01 +00:00
|
|
|
|
if (cur.pos() != 0 || isempty)
|
2007-03-30 20:41:38 +00:00
|
|
|
|
setCursor(cur, cur.pit() + 1, 0);
|
2002-05-29 12:58:23 +00:00
|
|
|
|
else
|
2007-03-30 20:41:38 +00:00
|
|
|
|
setCursor(cur, cur.pit(), 0);
|
2000-02-10 17:53:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// insert a character, moves all the following breaks in the
|
2002-06-24 20:28:12 +00:00
|
|
|
|
// same Paragraph one to the right and make a rebreak
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::insertChar(Cursor & cur, char_type c)
|
1999-09-27 18:44:28 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2004-03-08 21:14:45 +00:00
|
|
|
|
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndo(INSERT_UNDO);
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2007-09-02 21:48:49 +00:00
|
|
|
|
TextMetrics const & tm = cur.bv().textMetrics(this);
|
Move BufferView cached pointer out of LyXText:
* LyXText
- bv(), bv_owner, : deleted.
- These methods now need a (Buffer const &) argument: getFont(), applyOuterFont(), getLayoutFont(), getLabelFont(), setCharFont(), setLayout(), singleWidth(), leftMargin(), rightMargin(), computeRowMetrics(), isMainText(), spacing(), isRTL(), cursorX(), rowBreakPoint(), setRowWidth(), labelFill(), labelEnd().
- These methods now need a (BufferView const &) argument and are propably candidates for future removal when 1.6 is opened for development: redoParagraph(), x2pos(), getRowNearY(), getColumnNearX(), checkInsetHit(), setHeightOfRow().
- recUndo(): now need a LCursor argument.
* CoordCache::get(LyXText const *, pit_type):
- now const.
- use const_iterator instead of iterator.
* FontIterator:
- add (Buffer const &) argument to ctor
- buffer_: new const reference to applicable BufferView.
* InsetBase
- xo(), yo(), covers() and neverIndent() are now const.
* InsetText::setViewCache(): deleted
All other changes are due to the LyXText and InsetBase API changes.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@15618 a592a061-630c-0410-9148-cb99ea01b6c8
2006-10-30 12:45:33 +00:00
|
|
|
|
Buffer const & buffer = cur.buffer();
|
2004-02-13 07:30:59 +00:00
|
|
|
|
Paragraph & par = cur.paragraph();
|
|
|
|
|
// try to remove this
|
2004-11-24 21:53:46 +00:00
|
|
|
|
pit_type const pit = cur.pit();
|
2000-03-09 03:36:48 +00:00
|
|
|
|
|
2004-02-13 07:30:59 +00:00
|
|
|
|
bool const freeSpacing = par.layout()->free_spacing ||
|
|
|
|
|
par.isFreeSpacing();
|
2000-02-29 02:19:17 +00:00
|
|
|
|
|
2000-10-09 12:30:52 +00:00
|
|
|
|
if (lyxrc.auto_number) {
|
2006-10-21 00:16:43 +00:00
|
|
|
|
static docstring const number_operators = from_ascii("+-/*");
|
|
|
|
|
static docstring const number_unary_operators = from_ascii("+-");
|
|
|
|
|
static docstring const number_seperators = from_ascii(".,:");
|
2001-01-15 14:05:45 +00:00
|
|
|
|
|
2007-10-28 18:51:54 +00:00
|
|
|
|
if (cur.current_font.fontInfo().number() == FONT_ON) {
|
2006-04-08 09:09:57 +00:00
|
|
|
|
if (!isDigit(c) && !contains(number_operators, c) &&
|
2001-01-15 14:05:45 +00:00
|
|
|
|
!(contains(number_seperators, c) &&
|
2004-02-13 07:30:59 +00:00
|
|
|
|
cur.pos() != 0 &&
|
|
|
|
|
cur.pos() != cur.lastpos() &&
|
2008-02-27 23:03:26 +00:00
|
|
|
|
tm.displayFont(pit, cur.pos()).fontInfo().number() == FONT_ON &&
|
|
|
|
|
tm.displayFont(pit, cur.pos() - 1).fontInfo().number() == FONT_ON)
|
2002-02-16 15:59:55 +00:00
|
|
|
|
)
|
2004-02-13 11:05:29 +00:00
|
|
|
|
number(cur); // Set current_font.number to OFF
|
2006-04-08 09:09:57 +00:00
|
|
|
|
} else if (isDigit(c) &&
|
2007-09-02 13:35:48 +00:00
|
|
|
|
cur.real_current_font.isVisibleRightToLeft()) {
|
2004-02-13 11:05:29 +00:00
|
|
|
|
number(cur); // Set current_font.number to ON
|
2000-10-09 12:30:52 +00:00
|
|
|
|
|
2004-02-13 07:30:59 +00:00
|
|
|
|
if (cur.pos() != 0) {
|
2006-04-09 02:30:40 +00:00
|
|
|
|
char_type const c = par.getChar(cur.pos() - 1);
|
2001-01-15 14:05:45 +00:00
|
|
|
|
if (contains(number_unary_operators, c) &&
|
2004-02-13 07:30:59 +00:00
|
|
|
|
(cur.pos() == 1
|
|
|
|
|
|| par.isSeparator(cur.pos() - 2)
|
|
|
|
|
|| par.isNewline(cur.pos() - 2))
|
2002-02-16 15:59:55 +00:00
|
|
|
|
) {
|
2007-09-02 21:48:49 +00:00
|
|
|
|
setCharFont(buffer, pit, cur.pos() - 1, cur.current_font,
|
|
|
|
|
tm.font_);
|
2004-02-13 07:30:59 +00:00
|
|
|
|
} else if (contains(number_seperators, c)
|
|
|
|
|
&& cur.pos() >= 2
|
2008-02-27 23:03:26 +00:00
|
|
|
|
&& tm.displayFont(pit, cur.pos() - 2).fontInfo().number() == FONT_ON) {
|
2007-09-02 21:48:49 +00:00
|
|
|
|
setCharFont(buffer, pit, cur.pos() - 1, cur.current_font,
|
|
|
|
|
tm.font_);
|
2000-10-09 12:30:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-06-08 14:24:57 +00:00
|
|
|
|
// In Bidi text, we want spaces to be treated in a special way: spaces
|
|
|
|
|
// which are between words in different languages should get the
|
|
|
|
|
// paragraph's language; otherwise, spaces should keep the language
|
|
|
|
|
// they were originally typed in. This is only in effect while typing;
|
|
|
|
|
// after the text is already typed in, the user can always go back and
|
|
|
|
|
// explicitly set the language of a space as desired. But 99.9% of the
|
|
|
|
|
// time, what we're doing here is what the user actually meant.
|
|
|
|
|
//
|
|
|
|
|
// The following cases are the ones in which the language of the space
|
|
|
|
|
// should be changed to match that of the containing paragraph. In the
|
|
|
|
|
// depictions, lowercase is LTR, uppercase is RTL, underscore (_)
|
|
|
|
|
// represents a space, pipe (|) represents the cursor position (so the
|
|
|
|
|
// character before it is the one just typed in). The different cases
|
|
|
|
|
// are depicted logically (not visually), from left to right:
|
|
|
|
|
//
|
|
|
|
|
// 1. A_a|
|
|
|
|
|
// 2. a_A|
|
|
|
|
|
//
|
|
|
|
|
// Theoretically, there are other situations that we should, perhaps, deal
|
|
|
|
|
// with (e.g.: a|_A, A|_a). In practice, though, there really isn't any
|
|
|
|
|
// point (to understand why, just try to create this situation...).
|
|
|
|
|
|
|
|
|
|
if ((cur.pos() >= 2) && (par.isLineSeparator(cur.pos() - 1))) {
|
|
|
|
|
// get font in front and behind the space in question. But do NOT
|
|
|
|
|
// use getFont(cur.pos()) because the character c is not inserted yet
|
2008-02-27 23:03:26 +00:00
|
|
|
|
Font const pre_space_font = tm.displayFont(cur.pit(), cur.pos() - 2);
|
2007-09-02 13:35:48 +00:00
|
|
|
|
Font const & post_space_font = cur.real_current_font;
|
2007-06-08 14:24:57 +00:00
|
|
|
|
bool pre_space_rtl = pre_space_font.isVisibleRightToLeft();
|
|
|
|
|
bool post_space_rtl = post_space_font.isVisibleRightToLeft();
|
|
|
|
|
|
|
|
|
|
if (pre_space_rtl != post_space_rtl) {
|
|
|
|
|
// Set the space's language to match the language of the
|
|
|
|
|
// adjacent character whose direction is the paragraph's
|
|
|
|
|
// direction; don't touch other properties of the font
|
|
|
|
|
Language const * lang =
|
2007-09-04 10:27:55 +00:00
|
|
|
|
(pre_space_rtl == par.isRTL(buffer.params())) ?
|
2007-06-08 14:24:57 +00:00
|
|
|
|
pre_space_font.language() : post_space_font.language();
|
|
|
|
|
|
2008-02-27 23:03:26 +00:00
|
|
|
|
Font space_font = tm.displayFont(cur.pit(), cur.pos() - 1);
|
2007-06-08 14:24:57 +00:00
|
|
|
|
space_font.setLanguage(lang);
|
|
|
|
|
par.setFont(cur.pos() - 1, space_font);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Next check, if there will be two blanks together or a blank at
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// the beginning of a paragraph.
|
|
|
|
|
// I decided to handle blanks like normal characters, the main
|
|
|
|
|
// difference are the special checks when calculating the row.fill
|
|
|
|
|
// (blank does not count at the end of a row) and the check here
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2004-02-13 07:30:59 +00:00
|
|
|
|
// When the free-spacing option is set for the current layout,
|
|
|
|
|
// disable the double-space checking
|
2006-04-08 09:09:57 +00:00
|
|
|
|
if (!freeSpacing && isLineSeparatorChar(c)) {
|
2004-02-13 07:30:59 +00:00
|
|
|
|
if (cur.pos() == 0) {
|
2001-05-09 15:20:58 +00:00
|
|
|
|
static bool sent_space_message = false;
|
|
|
|
|
if (!sent_space_message) {
|
2006-09-11 08:54:10 +00:00
|
|
|
|
cur.message(_("You cannot insert a space at the "
|
|
|
|
|
"beginning of a paragraph. Please read the Tutorial."));
|
2004-02-13 07:30:59 +00:00
|
|
|
|
sent_space_message = true;
|
|
|
|
|
}
|
2005-01-31 16:29:48 +00:00
|
|
|
|
return;
|
2004-02-13 07:30:59 +00:00
|
|
|
|
}
|
|
|
|
|
BOOST_ASSERT(cur.pos() > 0);
|
2006-10-23 16:22:05 +00:00
|
|
|
|
if ((par.isLineSeparator(cur.pos() - 1) || par.isNewline(cur.pos() - 1))
|
|
|
|
|
&& !par.isDeleted(cur.pos() - 1)) {
|
2004-02-13 07:30:59 +00:00
|
|
|
|
static bool sent_space_message = false;
|
|
|
|
|
if (!sent_space_message) {
|
2006-09-11 08:54:10 +00:00
|
|
|
|
cur.message(_("You cannot type two spaces this way. "
|
|
|
|
|
"Please read the Tutorial."));
|
2001-05-09 15:20:58 +00:00
|
|
|
|
sent_space_message = true;
|
|
|
|
|
}
|
1999-12-13 00:05:34 +00:00
|
|
|
|
return;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-03-13 10:30:28 +00:00
|
|
|
|
|
2007-09-02 13:35:48 +00:00
|
|
|
|
par.insertChar(cur.pos(), c, cur.current_font, cur.buffer().params().trackChanges);
|
2008-01-12 21:38:51 +00:00
|
|
|
|
cur.checkBufferStructure();
|
2006-11-12 14:47:20 +00:00
|
|
|
|
|
2006-12-29 23:54:48 +00:00
|
|
|
|
// cur.updateFlags(Update::Force);
|
|
|
|
|
setCursor(cur.top(), cur.pit(), cur.pos() + 1);
|
2007-10-18 11:51:17 +00:00
|
|
|
|
charInserted(cur);
|
1999-12-13 00:05:34 +00:00
|
|
|
|
}
|
2002-03-21 17:27:08 +00:00
|
|
|
|
|
1999-12-13 00:05:34 +00:00
|
|
|
|
|
2007-10-18 11:51:17 +00:00
|
|
|
|
void Text::charInserted(Cursor & cur)
|
1999-12-13 00:05:34 +00:00
|
|
|
|
{
|
2008-02-21 19:42:34 +00:00
|
|
|
|
Paragraph & par = cur.paragraph();
|
|
|
|
|
|
2003-10-27 11:44:10 +00:00
|
|
|
|
// Here we call finishUndo for every 20 characters inserted.
|
2003-04-13 12:56:48 +00:00
|
|
|
|
// This is from my experience how emacs does it. (Lgb)
|
2001-06-04 23:57:32 +00:00
|
|
|
|
static unsigned int counter;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
if (counter < 20) {
|
|
|
|
|
++counter;
|
|
|
|
|
} else {
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.finishUndo();
|
1999-09-27 18:44:28 +00:00
|
|
|
|
counter = 0;
|
|
|
|
|
}
|
2008-02-21 19:42:34 +00:00
|
|
|
|
|
|
|
|
|
// register word if a non-letter was entered
|
|
|
|
|
if (cur.pos() > 1
|
|
|
|
|
&& par.isLetter(cur.pos() - 2)
|
|
|
|
|
&& !par.isLetter(cur.pos() - 1)) {
|
|
|
|
|
// get the word in front of cursor
|
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2008-03-04 15:05:16 +00:00
|
|
|
|
cur.paragraph().updateWords(cur.top());
|
2008-02-21 19:42:34 +00:00
|
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
1999-12-13 00:05:34 +00:00
|
|
|
|
|
2000-06-28 13:35:52 +00:00
|
|
|
|
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// the cursor set functions have a special mechanism. When they
|
|
|
|
|
// realize, that you left an empty paragraph, they will delete it.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2007-10-28 20:35:57 +00:00
|
|
|
|
bool Text::cursorForwardOneWord(Cursor & cur)
|
1999-09-27 18:44:28 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2005-02-08 02:06:39 +00:00
|
|
|
|
|
2007-04-26 14:56:30 +00:00
|
|
|
|
Cursor old = cur;
|
2005-02-08 02:06:39 +00:00
|
|
|
|
|
|
|
|
|
if (old.pos() == old.lastpos() && old.pit() != old.lastpit()) {
|
|
|
|
|
++old.pit();
|
|
|
|
|
old.pos() = 0;
|
2004-02-12 16:36:01 +00:00
|
|
|
|
} else {
|
|
|
|
|
// Advance through word.
|
2005-02-08 02:06:39 +00:00
|
|
|
|
while (old.pos() != old.lastpos() && old.paragraph().isLetter(old.pos()))
|
|
|
|
|
++old.pos();
|
2006-02-24 12:58:31 +00:00
|
|
|
|
// Skip through trailing nonword stuff.
|
|
|
|
|
while (old.pos() != old.lastpos() && !old.paragraph().isLetter(old.pos()))
|
|
|
|
|
++old.pos();
|
2004-02-12 16:36:01 +00:00
|
|
|
|
}
|
2005-02-08 02:06:39 +00:00
|
|
|
|
return setCursor(cur, old.pit(), old.pos());
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-10-28 20:35:57 +00:00
|
|
|
|
bool Text::cursorBackwardOneWord(Cursor & cur)
|
1999-09-27 18:44:28 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2005-02-08 02:06:39 +00:00
|
|
|
|
|
2007-04-26 14:56:30 +00:00
|
|
|
|
Cursor old = cur;
|
2005-02-08 02:06:39 +00:00
|
|
|
|
|
|
|
|
|
if (old.pos() == 0 && old.pit() != 0) {
|
|
|
|
|
--old.pit();
|
|
|
|
|
old.pos() = old.lastpos();
|
2004-04-03 08:37:12 +00:00
|
|
|
|
} else {
|
2004-02-12 16:36:01 +00:00
|
|
|
|
// Skip through initial nonword stuff.
|
2005-02-08 02:06:39 +00:00
|
|
|
|
while (old.pos() != 0 && !old.paragraph().isLetter(old.pos() - 1))
|
|
|
|
|
--old.pos();
|
2004-02-12 16:36:01 +00:00
|
|
|
|
// Advance through word.
|
2005-02-08 02:06:39 +00:00
|
|
|
|
while (old.pos() != 0 && old.paragraph().isLetter(old.pos() - 1))
|
|
|
|
|
--old.pos();
|
2004-02-12 16:36:01 +00:00
|
|
|
|
}
|
2005-02-08 02:06:39 +00:00
|
|
|
|
return setCursor(cur, old.pit(), old.pos());
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-05-29 12:58:23 +00:00
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::selectWord(Cursor & cur, word_location loc)
|
2001-06-27 14:10:35 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2004-03-01 17:12:09 +00:00
|
|
|
|
CursorSlice from = cur.top();
|
|
|
|
|
CursorSlice to = cur.top();
|
2003-11-11 10:08:35 +00:00
|
|
|
|
getWord(from, to, loc);
|
2004-03-01 17:12:09 +00:00
|
|
|
|
if (cur.top() != from)
|
2004-11-24 21:53:46 +00:00
|
|
|
|
setCursor(cur, from.pit(), from.pos());
|
2001-07-27 16:07:33 +00:00
|
|
|
|
if (to == from)
|
|
|
|
|
return;
|
2004-02-13 07:30:59 +00:00
|
|
|
|
cur.resetAnchor();
|
2004-11-24 21:53:46 +00:00
|
|
|
|
setCursor(cur, to.pit(), to.pos());
|
2004-02-13 07:30:59 +00:00
|
|
|
|
cur.setSelection();
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// Select the word currently under the cursor when no
|
2002-06-24 20:28:12 +00:00
|
|
|
|
// selection is currently set
|
2007-04-29 23:33:02 +00:00
|
|
|
|
bool Text::selectWordWhenUnderCursor(Cursor & cur, word_location loc)
|
1999-09-27 18:44:28 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2004-02-13 07:30:59 +00:00
|
|
|
|
if (cur.selection())
|
2004-01-20 14:25:24 +00:00
|
|
|
|
return false;
|
2004-02-13 07:30:59 +00:00
|
|
|
|
selectWord(cur, loc);
|
|
|
|
|
return cur.selection();
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::acceptOrRejectChanges(Cursor & cur, ChangeOp op)
|
2003-02-08 19:18:01 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2006-11-25 23:30:58 +00:00
|
|
|
|
|
2007-01-21 21:20:51 +00:00
|
|
|
|
if (!cur.selection())
|
2003-02-08 19:18:01 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndoSelection();
|
2006-11-25 23:30:58 +00:00
|
|
|
|
|
2007-01-23 21:53:16 +00:00
|
|
|
|
pit_type begPit = cur.selectionBegin().pit();
|
|
|
|
|
pit_type endPit = cur.selectionEnd().pit();
|
2006-04-05 23:56:29 +00:00
|
|
|
|
|
2007-01-23 21:53:16 +00:00
|
|
|
|
pos_type begPos = cur.selectionBegin().pos();
|
|
|
|
|
pos_type endPos = cur.selectionEnd().pos();
|
|
|
|
|
|
|
|
|
|
// keep selection info, because endPos becomes invalid after the first loop
|
|
|
|
|
bool endsBeforeEndOfPar = (endPos < pars_[endPit].size());
|
|
|
|
|
|
|
|
|
|
// first, accept/reject changes within each individual paragraph (do not consider end-of-par)
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-01-23 21:53:16 +00:00
|
|
|
|
for (pit_type pit = begPit; pit <= endPit; ++pit) {
|
|
|
|
|
pos_type parSize = pars_[pit].size();
|
|
|
|
|
|
|
|
|
|
// ignore empty paragraphs; otherwise, an assertion will fail for
|
|
|
|
|
// acceptChanges(bparams, 0, 0) or rejectChanges(bparams, 0, 0)
|
|
|
|
|
if (parSize == 0)
|
2007-01-21 21:20:51 +00:00
|
|
|
|
continue;
|
2006-11-26 14:49:35 +00:00
|
|
|
|
|
2007-01-21 21:20:51 +00:00
|
|
|
|
// do not consider first paragraph if the cursor starts at pos size()
|
2007-01-23 21:53:16 +00:00
|
|
|
|
if (pit == begPit && begPos == parSize)
|
2007-01-21 21:20:51 +00:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// do not consider last paragraph if the cursor ends at pos 0
|
2007-05-28 22:27:45 +00:00
|
|
|
|
if (pit == endPit && endPos == 0)
|
2007-01-21 21:20:51 +00:00
|
|
|
|
break; // last iteration anyway
|
|
|
|
|
|
2007-01-23 21:53:16 +00:00
|
|
|
|
pos_type left = (pit == begPit ? begPos : 0);
|
|
|
|
|
pos_type right = (pit == endPit ? endPos : parSize);
|
|
|
|
|
|
2007-01-25 21:18:36 +00:00
|
|
|
|
if (op == ACCEPT) {
|
2007-01-23 21:53:16 +00:00
|
|
|
|
pars_[pit].acceptChanges(cur.buffer().params(), left, right);
|
|
|
|
|
} else {
|
|
|
|
|
pars_[pit].rejectChanges(cur.buffer().params(), left, right);
|
|
|
|
|
}
|
2007-01-21 21:20:51 +00:00
|
|
|
|
}
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-01-23 21:53:16 +00:00
|
|
|
|
// next, accept/reject imaginary end-of-par characters
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-01-23 21:53:16 +00:00
|
|
|
|
for (pit_type pit = begPit; pit <= endPit; ++pit) {
|
2007-01-21 21:20:51 +00:00
|
|
|
|
pos_type pos = pars_[pit].size();
|
|
|
|
|
|
2007-01-23 21:53:16 +00:00
|
|
|
|
// skip if the selection ends before the end-of-par
|
|
|
|
|
if (pit == endPit && endsBeforeEndOfPar)
|
|
|
|
|
break; // last iteration anyway
|
2007-01-21 21:20:51 +00:00
|
|
|
|
|
2007-01-23 21:53:16 +00:00
|
|
|
|
// skip if this is not the last paragraph of the document
|
|
|
|
|
// note: the user should be able to accept/reject the par break of the last par!
|
2007-04-29 13:39:47 +00:00
|
|
|
|
if (pit == endPit && pit + 1 != int(pars_.size()))
|
2007-01-23 21:53:16 +00:00
|
|
|
|
break; // last iteration anway
|
2007-01-21 21:20:51 +00:00
|
|
|
|
|
2007-01-25 21:18:36 +00:00
|
|
|
|
if (op == ACCEPT) {
|
2007-01-21 21:20:51 +00:00
|
|
|
|
if (pars_[pit].isInserted(pos)) {
|
|
|
|
|
pars_[pit].setChange(pos, Change(Change::UNCHANGED));
|
2007-01-23 21:53:16 +00:00
|
|
|
|
} else if (pars_[pit].isDeleted(pos)) {
|
2007-04-29 13:39:47 +00:00
|
|
|
|
if (pit + 1 == int(pars_.size())) {
|
2007-01-23 21:53:16 +00:00
|
|
|
|
// we cannot remove a par break at the end of the last paragraph;
|
2007-01-21 21:20:51 +00:00
|
|
|
|
// instead, we mark it unchanged
|
|
|
|
|
pars_[pit].setChange(pos, Change(Change::UNCHANGED));
|
|
|
|
|
} else {
|
|
|
|
|
mergeParagraph(cur.buffer().params(), pars_, pit);
|
2007-01-23 21:53:16 +00:00
|
|
|
|
--endPit;
|
|
|
|
|
--pit;
|
2007-01-21 21:20:51 +00:00
|
|
|
|
}
|
2007-01-04 23:02:37 +00:00
|
|
|
|
}
|
2007-01-23 21:53:16 +00:00
|
|
|
|
} else {
|
2007-01-23 13:25:50 +00:00
|
|
|
|
if (pars_[pit].isDeleted(pos)) {
|
|
|
|
|
pars_[pit].setChange(pos, Change(Change::UNCHANGED));
|
2007-01-23 21:53:16 +00:00
|
|
|
|
} else if (pars_[pit].isInserted(pos)) {
|
2007-04-29 13:39:47 +00:00
|
|
|
|
if (pit + 1 == int(pars_.size())) {
|
2007-01-23 21:53:16 +00:00
|
|
|
|
// we mark the par break at the end of the last paragraph unchanged
|
2007-01-23 13:25:50 +00:00
|
|
|
|
pars_[pit].setChange(pos, Change(Change::UNCHANGED));
|
|
|
|
|
} else {
|
|
|
|
|
mergeParagraph(cur.buffer().params(), pars_, pit);
|
2007-01-23 21:53:16 +00:00
|
|
|
|
--endPit;
|
|
|
|
|
--pit;
|
2007-01-23 13:25:50 +00:00
|
|
|
|
}
|
2007-01-04 23:02:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2006-03-11 13:31:41 +00:00
|
|
|
|
}
|
2007-01-23 13:25:50 +00:00
|
|
|
|
|
|
|
|
|
// finally, invoke the DEPM
|
2007-01-25 21:18:36 +00:00
|
|
|
|
|
|
|
|
|
deleteEmptyParagraphMechanism(begPit, endPit, cur.buffer().params().trackChanges);
|
|
|
|
|
|
2007-05-28 22:27:45 +00:00
|
|
|
|
//
|
2007-01-23 13:25:50 +00:00
|
|
|
|
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.finishUndo();
|
2006-03-11 13:31:41 +00:00
|
|
|
|
cur.clearSelection();
|
2007-01-23 21:53:16 +00:00
|
|
|
|
setCursorIntern(cur, begPit, begPos);
|
2007-01-04 23:02:37 +00:00
|
|
|
|
cur.updateFlags(Update::Force);
|
2007-01-23 13:25:50 +00:00
|
|
|
|
updateLabels(cur.buffer());
|
2003-02-08 19:18:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-03-03 23:19:01 +00:00
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::acceptChanges(BufferParams const & bparams)
|
2007-01-25 22:28:15 +00:00
|
|
|
|
{
|
2007-06-26 14:11:42 +00:00
|
|
|
|
lyx::acceptChanges(pars_, bparams);
|
|
|
|
|
deleteEmptyParagraphMechanism(0, pars_.size() - 1, bparams.trackChanges);
|
2007-01-25 22:28:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::rejectChanges(BufferParams const & bparams)
|
2007-01-25 22:28:15 +00:00
|
|
|
|
{
|
2007-02-20 17:27:06 +00:00
|
|
|
|
pit_type pars_size = static_cast<pit_type>(pars_.size());
|
2007-01-25 22:28:15 +00:00
|
|
|
|
|
|
|
|
|
// first, reject changes within each individual paragraph
|
2007-05-28 22:27:45 +00:00
|
|
|
|
// (do not consider end-of-par)
|
2007-01-25 22:28:15 +00:00
|
|
|
|
for (pit_type pit = 0; pit < pars_size; ++pit) {
|
2007-05-28 22:27:45 +00:00
|
|
|
|
if (!pars_[pit].empty()) // prevent assertion failure
|
2007-01-25 22:28:15 +00:00
|
|
|
|
pars_[pit].rejectChanges(bparams, 0, pars_[pit].size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// next, reject imaginary end-of-par characters
|
|
|
|
|
for (pit_type pit = 0; pit < pars_size; ++pit) {
|
|
|
|
|
pos_type pos = pars_[pit].size();
|
|
|
|
|
|
|
|
|
|
if (pars_[pit].isDeleted(pos)) {
|
|
|
|
|
pars_[pit].setChange(pos, Change(Change::UNCHANGED));
|
|
|
|
|
} else if (pars_[pit].isInserted(pos)) {
|
|
|
|
|
if (pit == pars_size - 1) {
|
|
|
|
|
// we mark the par break at the end of the last
|
|
|
|
|
// paragraph unchanged
|
|
|
|
|
pars_[pit].setChange(pos, Change(Change::UNCHANGED));
|
|
|
|
|
} else {
|
|
|
|
|
mergeParagraph(bparams, pars_, pit);
|
|
|
|
|
--pit;
|
|
|
|
|
--pars_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// finally, invoke the DEPM
|
|
|
|
|
deleteEmptyParagraphMechanism(0, pars_size - 1, bparams.trackChanges);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::deleteWordForward(Cursor & cur)
|
1999-09-27 18:44:28 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2004-02-12 16:36:01 +00:00
|
|
|
|
if (cur.lastpos() == 0)
|
2007-10-22 22:18:52 +00:00
|
|
|
|
cursorForward(cur);
|
1999-09-27 18:44:28 +00:00
|
|
|
|
else {
|
2004-01-20 14:25:24 +00:00
|
|
|
|
cur.resetAnchor();
|
2004-02-12 16:36:01 +00:00
|
|
|
|
cur.selection() = true;
|
2007-10-28 20:35:57 +00:00
|
|
|
|
cursorForwardOneWord(cur);
|
2004-01-20 14:25:24 +00:00
|
|
|
|
cur.setSelection();
|
2004-02-13 11:05:29 +00:00
|
|
|
|
cutSelection(cur, true, false);
|
2008-01-12 21:38:51 +00:00
|
|
|
|
cur.checkBufferStructure();
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::deleteWordBackward(Cursor & cur)
|
1999-09-27 18:44:28 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2004-02-12 16:36:01 +00:00
|
|
|
|
if (cur.lastpos() == 0)
|
2007-10-22 22:18:52 +00:00
|
|
|
|
cursorBackward(cur);
|
2002-05-29 12:58:23 +00:00
|
|
|
|
else {
|
2004-01-20 14:25:24 +00:00
|
|
|
|
cur.resetAnchor();
|
2004-02-12 16:36:01 +00:00
|
|
|
|
cur.selection() = true;
|
2007-10-28 20:35:57 +00:00
|
|
|
|
cursorBackwardOneWord(cur);
|
2004-01-20 14:25:24 +00:00
|
|
|
|
cur.setSelection();
|
2004-02-13 11:05:29 +00:00
|
|
|
|
cutSelection(cur, true, false);
|
2008-01-12 21:38:51 +00:00
|
|
|
|
cur.checkBufferStructure();
|
2002-05-29 12:58:23 +00:00
|
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-06-24 20:28:12 +00:00
|
|
|
|
// Kill to end of line.
|
2007-10-24 07:49:24 +00:00
|
|
|
|
void Text::changeCase(Cursor & cur, TextCase action)
|
2000-02-10 17:53:36 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2004-01-13 14:13:51 +00:00
|
|
|
|
CursorSlice from;
|
|
|
|
|
CursorSlice to;
|
2001-03-09 00:56:42 +00:00
|
|
|
|
|
2008-01-28 10:50:24 +00:00
|
|
|
|
bool gotsel = false;
|
2004-01-20 14:25:24 +00:00
|
|
|
|
if (cur.selection()) {
|
2004-01-26 10:13:15 +00:00
|
|
|
|
from = cur.selBegin();
|
2004-01-20 14:25:24 +00:00
|
|
|
|
to = cur.selEnd();
|
2008-01-28 10:50:24 +00:00
|
|
|
|
gotsel = true;
|
2001-06-27 14:10:35 +00:00
|
|
|
|
} else {
|
2004-03-18 13:28:49 +00:00
|
|
|
|
from = cur.top();
|
2006-10-21 00:16:43 +00:00
|
|
|
|
getWord(from, to, PARTIAL_WORD);
|
2007-10-28 20:35:57 +00:00
|
|
|
|
cursorForwardOneWord(cur);
|
2001-06-27 14:10:35 +00:00
|
|
|
|
}
|
2001-03-09 00:56:42 +00:00
|
|
|
|
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndoSelection();
|
2001-06-27 15:33:55 +00:00
|
|
|
|
|
2007-03-25 17:11:30 +00:00
|
|
|
|
pit_type begPit = from.pit();
|
|
|
|
|
pit_type endPit = to.pit();
|
2001-06-27 18:29:18 +00:00
|
|
|
|
|
2007-03-25 17:11:30 +00:00
|
|
|
|
pos_type begPos = from.pos();
|
|
|
|
|
pos_type endPos = to.pos();
|
|
|
|
|
|
2007-03-27 12:51:47 +00:00
|
|
|
|
pos_type right = 0; // needed after the for loop
|
2007-03-25 17:11:30 +00:00
|
|
|
|
|
|
|
|
|
for (pit_type pit = begPit; pit <= endPit; ++pit) {
|
2007-10-24 07:32:25 +00:00
|
|
|
|
Paragraph & par = pars_[pit];
|
2007-10-24 08:32:20 +00:00
|
|
|
|
pos_type const pos = (pit == begPit ? begPos : 0);
|
|
|
|
|
right = (pit == endPit ? endPos : par.size());
|
2007-10-24 07:49:24 +00:00
|
|
|
|
par.changeCase(cur.buffer().params(), pos, right, action);
|
2001-06-27 15:33:55 +00:00
|
|
|
|
}
|
2007-03-25 17:11:30 +00:00
|
|
|
|
|
|
|
|
|
// the selection may have changed due to logically-only deleted chars
|
2008-01-28 10:50:24 +00:00
|
|
|
|
if (gotsel) {
|
|
|
|
|
setCursor(cur, begPit, begPos);
|
|
|
|
|
cur.resetAnchor();
|
|
|
|
|
setCursor(cur, endPit, right);
|
|
|
|
|
cur.setSelection();
|
|
|
|
|
} else
|
|
|
|
|
setCursor(cur, endPit, right);
|
2007-03-25 17:11:30 +00:00
|
|
|
|
|
2008-01-12 21:38:51 +00:00
|
|
|
|
cur.checkBufferStructure();
|
2000-02-10 17:53:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-05-14 09:24:17 +00:00
|
|
|
|
bool Text::handleBibitems(Cursor & cur)
|
|
|
|
|
{
|
|
|
|
|
if (cur.paragraph().layout()->labeltype != LABEL_BIBLIO)
|
|
|
|
|
return false;
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
|
|
|
|
|
if (cur.pos() != 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
BufferParams const & bufparams = cur.buffer().params();
|
|
|
|
|
Paragraph const & par = cur.paragraph();
|
|
|
|
|
Cursor prevcur = cur;
|
|
|
|
|
if (cur.pit() > 0) {
|
|
|
|
|
--prevcur.pit();
|
|
|
|
|
prevcur.pos() = prevcur.lastpos();
|
|
|
|
|
}
|
|
|
|
|
Paragraph const & prevpar = prevcur.paragraph();
|
|
|
|
|
|
2007-05-14 09:24:17 +00:00
|
|
|
|
// if a bibitem is deleted, merge with previous paragraph
|
|
|
|
|
// if this is a bibliography item as well
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
if (cur.pit() > 0 && par.layout() == prevpar.layout()) {
|
|
|
|
|
cur.recordUndo(ATOMIC_UNDO, prevcur.pit());
|
|
|
|
|
mergeParagraph(bufparams, cur.text()->paragraphs(),
|
|
|
|
|
prevcur.pit());
|
|
|
|
|
updateLabels(cur.buffer());
|
|
|
|
|
setCursorIntern(cur, prevcur.pit(), prevcur.pos());
|
|
|
|
|
cur.updateFlags(Update::Force);
|
2007-05-14 09:24:17 +00:00
|
|
|
|
return true;
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// otherwise reset to default
|
2008-02-28 01:42:02 +00:00
|
|
|
|
cur.paragraph().setEmptyOrDefaultLayout(bufparams.documentClass());
|
2008-02-28 14:58:22 +00:00
|
|
|
|
return true;
|
2007-05-14 09:24:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
bool Text::erase(Cursor & cur)
|
2000-02-10 17:53:36 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2005-12-19 12:30:34 +00:00
|
|
|
|
bool needsUpdate = false;
|
2006-11-07 23:02:44 +00:00
|
|
|
|
Paragraph & par = cur.paragraph();
|
2005-07-17 16:12:48 +00:00
|
|
|
|
|
2004-04-13 06:27:29 +00:00
|
|
|
|
if (cur.pos() != cur.lastpos()) {
|
2006-11-07 23:02:44 +00:00
|
|
|
|
// this is the code for a normal delete, not pasting
|
|
|
|
|
// any paragraphs
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndo(DELETE_UNDO);
|
2008-02-13 14:16:51 +00:00
|
|
|
|
bool const was_inset = cur.paragraph().isInset(cur.pos());
|
|
|
|
|
if(!par.eraseChar(cur.pos(), cur.buffer().params().trackChanges))
|
2007-01-20 16:59:13 +00:00
|
|
|
|
// the character has been logically deleted only => skip it
|
2007-08-13 13:36:19 +00:00
|
|
|
|
cur.top().forwardPos();
|
2008-02-13 14:16:51 +00:00
|
|
|
|
|
|
|
|
|
if (was_inset)
|
|
|
|
|
updateLabels(cur.buffer());
|
|
|
|
|
else
|
|
|
|
|
cur.checkBufferStructure();
|
2006-11-07 23:02:44 +00:00
|
|
|
|
needsUpdate = true;
|
2006-11-26 00:04:25 +00:00
|
|
|
|
} else {
|
|
|
|
|
if (cur.pit() == cur.lastpit())
|
|
|
|
|
return dissolveInset(cur);
|
|
|
|
|
|
2006-11-24 22:12:04 +00:00
|
|
|
|
if (!par.isMergedOnEndOfParDeletion(cur.buffer().params().trackChanges)) {
|
2006-11-07 23:02:44 +00:00
|
|
|
|
par.setChange(cur.pos(), Change(Change::DELETED));
|
|
|
|
|
cur.forwardPos();
|
|
|
|
|
needsUpdate = true;
|
2005-07-17 16:12:48 +00:00
|
|
|
|
} else {
|
2006-11-07 23:02:44 +00:00
|
|
|
|
setCursorIntern(cur, cur.pit() + 1, 0);
|
|
|
|
|
needsUpdate = backspacePos0(cur);
|
2005-07-17 16:12:48 +00:00
|
|
|
|
}
|
2006-11-24 22:12:04 +00:00
|
|
|
|
}
|
2006-09-09 15:27:44 +00:00
|
|
|
|
|
2007-05-14 09:24:17 +00:00
|
|
|
|
needsUpdate |= handleBibitems(cur);
|
|
|
|
|
|
2006-11-13 16:59:10 +00:00
|
|
|
|
if (needsUpdate) {
|
2006-11-17 17:42:52 +00:00
|
|
|
|
// Make sure the cursor is correct. Is this really needed?
|
|
|
|
|
// No, not really... at least not here!
|
2006-12-29 23:54:48 +00:00
|
|
|
|
cur.text()->setCursor(cur.top(), cur.pit(), cur.pos());
|
2008-01-12 21:38:51 +00:00
|
|
|
|
cur.checkBufferStructure();
|
2006-11-13 16:59:10 +00:00
|
|
|
|
}
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2005-12-19 12:30:34 +00:00
|
|
|
|
return needsUpdate;
|
2000-02-10 17:53:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
bool Text::backspacePos0(Cursor & cur)
|
2000-02-10 17:53:36 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2006-11-07 23:02:44 +00:00
|
|
|
|
if (cur.pit() == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
2005-12-19 12:30:34 +00:00
|
|
|
|
bool needsUpdate = false;
|
2002-03-21 17:27:08 +00:00
|
|
|
|
|
2006-11-07 23:02:44 +00:00
|
|
|
|
BufferParams const & bufparams = cur.buffer().params();
|
2008-02-28 01:42:02 +00:00
|
|
|
|
DocumentClass const & tclass = bufparams.documentClass();
|
2006-11-07 23:02:44 +00:00
|
|
|
|
ParagraphList & plist = cur.text()->paragraphs();
|
|
|
|
|
Paragraph const & par = cur.paragraph();
|
2007-04-26 14:56:30 +00:00
|
|
|
|
Cursor prevcur = cur;
|
2006-11-07 23:02:44 +00:00
|
|
|
|
--prevcur.pit();
|
|
|
|
|
prevcur.pos() = prevcur.lastpos();
|
|
|
|
|
Paragraph const & prevpar = prevcur.paragraph();
|
2006-04-05 23:56:29 +00:00
|
|
|
|
|
2006-11-07 23:02:44 +00:00
|
|
|
|
// is it an empty paragraph?
|
2007-05-28 22:27:45 +00:00
|
|
|
|
if (cur.lastpos() == 0
|
2006-11-07 23:02:44 +00:00
|
|
|
|
|| (cur.lastpos() == 1 && par.isSeparator(0))) {
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndo(ATOMIC_UNDO, prevcur.pit(), cur.pit());
|
2006-11-07 23:02:44 +00:00
|
|
|
|
plist.erase(boost::next(plist.begin(), cur.pit()));
|
|
|
|
|
needsUpdate = true;
|
2006-03-11 13:31:41 +00:00
|
|
|
|
}
|
2006-11-07 23:02:44 +00:00
|
|
|
|
// is previous par empty?
|
2007-05-28 22:27:45 +00:00
|
|
|
|
else if (prevcur.lastpos() == 0
|
2006-11-07 23:02:44 +00:00
|
|
|
|
|| (prevcur.lastpos() == 1 && prevpar.isSeparator(0))) {
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndo(ATOMIC_UNDO, prevcur.pit(), cur.pit());
|
2006-11-07 23:02:44 +00:00
|
|
|
|
plist.erase(boost::next(plist.begin(), prevcur.pit()));
|
|
|
|
|
needsUpdate = true;
|
2006-03-11 13:31:41 +00:00
|
|
|
|
}
|
|
|
|
|
// Pasting is not allowed, if the paragraphs have different
|
2006-11-24 22:12:04 +00:00
|
|
|
|
// layouts. I think it is a real bug of all other
|
2006-03-11 13:31:41 +00:00
|
|
|
|
// word processors to allow it. It confuses the user.
|
|
|
|
|
// Correction: Pasting is always allowed with standard-layout
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
|
// or the empty layout.
|
2006-11-07 23:02:44 +00:00
|
|
|
|
else if (par.layout() == prevpar.layout()
|
2008-03-06 20:01:30 +00:00
|
|
|
|
|| tclass.isDefaultLayout(*par.layout())
|
|
|
|
|
|| tclass.isEmptyLayout(*par.layout())) {
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndo(ATOMIC_UNDO, prevcur.pit());
|
2006-11-07 23:02:44 +00:00
|
|
|
|
mergeParagraph(bufparams, plist, prevcur.pit());
|
2006-03-11 13:31:41 +00:00
|
|
|
|
needsUpdate = true;
|
2006-11-07 23:02:44 +00:00
|
|
|
|
}
|
2003-08-11 09:09:01 +00:00
|
|
|
|
|
2006-11-07 23:02:44 +00:00
|
|
|
|
if (needsUpdate) {
|
|
|
|
|
updateLabels(cur.buffer());
|
|
|
|
|
setCursorIntern(cur, prevcur.pit(), prevcur.pos());
|
2006-03-11 13:31:41 +00:00
|
|
|
|
}
|
2006-11-07 23:02:44 +00:00
|
|
|
|
|
2006-03-11 13:31:41 +00:00
|
|
|
|
return needsUpdate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
bool Text::backspace(Cursor & cur)
|
2006-03-11 13:31:41 +00:00
|
|
|
|
{
|
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
|
|
|
|
bool needsUpdate = false;
|
|
|
|
|
if (cur.pos() == 0) {
|
2006-09-08 14:08:26 +00:00
|
|
|
|
if (cur.pit() == 0)
|
|
|
|
|
return dissolveInset(cur);
|
|
|
|
|
|
2006-11-25 00:31:44 +00:00
|
|
|
|
Paragraph & prev_par = pars_[cur.pit() - 1];
|
2006-03-11 13:31:41 +00:00
|
|
|
|
|
2006-11-25 00:31:44 +00:00
|
|
|
|
if (!prev_par.isMergedOnEndOfParDeletion(cur.buffer().params().trackChanges)) {
|
|
|
|
|
prev_par.setChange(prev_par.size(), Change(Change::DELETED));
|
|
|
|
|
setCursorIntern(cur, cur.pit() - 1, prev_par.size());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2006-11-07 23:02:44 +00:00
|
|
|
|
// The cursor is at the beginning of a paragraph, so
|
|
|
|
|
// the backspace will collapse two paragraphs into one.
|
2006-03-11 13:31:41 +00:00
|
|
|
|
needsUpdate = backspacePos0(cur);
|
|
|
|
|
|
2000-02-10 17:53:36 +00:00
|
|
|
|
} else {
|
2002-05-29 12:58:23 +00:00
|
|
|
|
// this is the code for a normal backspace, not pasting
|
2002-06-24 20:28:12 +00:00
|
|
|
|
// any paragraphs
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndo(DELETE_UNDO);
|
2007-10-22 22:18:52 +00:00
|
|
|
|
// We used to do cursorBackwardIntern() here, but it is
|
2000-03-28 16:18:02 +00:00
|
|
|
|
// not a good idea since it triggers the auto-delete
|
2007-10-22 22:18:52 +00:00
|
|
|
|
// mechanism. So we do a cursorBackwardIntern()-lite,
|
2000-03-28 16:18:02 +00:00
|
|
|
|
// without the dreaded mechanism. (JMarc)
|
2004-11-24 21:53:46 +00:00
|
|
|
|
setCursorIntern(cur, cur.pit(), cur.pos() - 1,
|
2004-02-12 16:36:01 +00:00
|
|
|
|
false, cur.boundary());
|
2008-02-13 14:16:51 +00:00
|
|
|
|
bool const was_inset = cur.paragraph().isInset(cur.pos());
|
2006-10-21 17:05:20 +00:00
|
|
|
|
cur.paragraph().eraseChar(cur.pos(), cur.buffer().params().trackChanges);
|
2008-02-13 14:16:51 +00:00
|
|
|
|
if (was_inset)
|
|
|
|
|
updateLabels(cur.buffer());
|
|
|
|
|
else
|
|
|
|
|
cur.checkBufferStructure();
|
2000-02-10 17:53:36 +00:00
|
|
|
|
}
|
2000-05-30 19:31:11 +00:00
|
|
|
|
|
2004-02-12 16:36:01 +00:00
|
|
|
|
if (cur.pos() == cur.lastpos())
|
2007-09-02 13:35:48 +00:00
|
|
|
|
cur.setCurrentFont();
|
2002-03-21 17:27:08 +00:00
|
|
|
|
|
2007-05-14 09:24:17 +00:00
|
|
|
|
needsUpdate |= handleBibitems(cur);
|
|
|
|
|
|
2006-12-29 23:54:48 +00:00
|
|
|
|
// A singlePar update is not enough in this case.
|
|
|
|
|
// cur.updateFlags(Update::Force);
|
|
|
|
|
setCursor(cur.top(), cur.pit(), cur.pos());
|
2005-12-19 12:30:34 +00:00
|
|
|
|
|
|
|
|
|
return needsUpdate;
|
2000-02-10 17:53:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
bool Text::dissolveInset(Cursor & cur) {
|
2006-09-08 14:08:26 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
|
|
|
|
|
2007-08-21 13:03:55 +00:00
|
|
|
|
if (isMainText(cur.bv().buffer()) || cur.inset().nargs() != 1)
|
2006-09-08 14:08:26 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndoInset();
|
2007-12-18 07:10:55 +00:00
|
|
|
|
cur.mark() = false;
|
2006-09-08 14:08:26 +00:00
|
|
|
|
cur.selHandle(false);
|
|
|
|
|
// save position
|
2006-10-21 00:16:43 +00:00
|
|
|
|
pos_type spos = cur.pos();
|
|
|
|
|
pit_type spit = cur.pit();
|
2006-09-08 14:08:26 +00:00
|
|
|
|
ParagraphList plist;
|
2006-09-09 15:27:44 +00:00
|
|
|
|
if (cur.lastpit() != 0 || cur.lastpos() != 0)
|
2006-09-08 14:08:26 +00:00
|
|
|
|
plist = paragraphs();
|
2007-11-05 19:41:16 +00:00
|
|
|
|
cur.popBackward();
|
2006-09-08 14:08:26 +00:00
|
|
|
|
// store cursor offset
|
|
|
|
|
if (spit == 0)
|
|
|
|
|
spos += cur.pos();
|
|
|
|
|
spit += cur.pit();
|
2006-10-19 17:46:50 +00:00
|
|
|
|
Buffer & b = cur.buffer();
|
2006-10-21 17:05:20 +00:00
|
|
|
|
cur.paragraph().eraseChar(cur.pos(), b.params().trackChanges);
|
2006-09-08 14:08:26 +00:00
|
|
|
|
if (!plist.empty()) {
|
2006-12-28 10:24:45 +00:00
|
|
|
|
// ERT paragraphs have the Language latex_language.
|
|
|
|
|
// This is invalid outside of ERT, so we need to
|
|
|
|
|
// change it to the buffer language.
|
|
|
|
|
ParagraphList::iterator it = plist.begin();
|
|
|
|
|
ParagraphList::iterator it_end = plist.end();
|
2007-10-20 10:03:45 +00:00
|
|
|
|
for (; it != it_end; it++)
|
|
|
|
|
it->changeLanguage(b.params(), latex_language, b.language());
|
2006-11-12 16:11:51 +00:00
|
|
|
|
|
2008-02-28 01:42:02 +00:00
|
|
|
|
pasteParagraphList(cur, plist, b.params().documentClassPtr(),
|
2006-09-08 14:08:26 +00:00
|
|
|
|
b.errorList("Paste"));
|
|
|
|
|
// restore position
|
2007-12-12 19:28:07 +00:00
|
|
|
|
cur.pit() = min(cur.lastpit(), spit);
|
|
|
|
|
cur.pos() = min(cur.lastpos(), spos);
|
2006-09-08 14:08:26 +00:00
|
|
|
|
}
|
|
|
|
|
cur.clearSelection();
|
|
|
|
|
cur.resetAnchor();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::getWord(CursorSlice & from, CursorSlice & to,
|
2008-02-26 00:38:30 +00:00
|
|
|
|
word_location const loc) const
|
2003-11-11 10:08:35 +00:00
|
|
|
|
{
|
2004-11-24 21:53:46 +00:00
|
|
|
|
Paragraph const & from_par = pars_[from.pit()];
|
2003-11-11 10:08:35 +00:00
|
|
|
|
switch (loc) {
|
2006-10-21 00:16:43 +00:00
|
|
|
|
case WHOLE_WORD_STRICT:
|
2004-02-12 16:36:01 +00:00
|
|
|
|
if (from.pos() == 0 || from.pos() == from_par.size()
|
2004-11-18 14:58:54 +00:00
|
|
|
|
|| !from_par.isLetter(from.pos())
|
|
|
|
|
|| !from_par.isLetter(from.pos() - 1)) {
|
2003-11-11 10:08:35 +00:00
|
|
|
|
to = from;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// no break here, we go to the next
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
case WHOLE_WORD:
|
2004-06-29 15:43:25 +00:00
|
|
|
|
// If we are already at the beginning of a word, do nothing
|
2004-11-18 14:58:54 +00:00
|
|
|
|
if (!from.pos() || !from_par.isLetter(from.pos() - 1))
|
2004-06-29 15:43:25 +00:00
|
|
|
|
break;
|
|
|
|
|
// no break here, we go to the next
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
case PREVIOUS_WORD:
|
2003-11-11 10:08:35 +00:00
|
|
|
|
// always move the cursor to the beginning of previous word
|
2004-11-18 14:58:54 +00:00
|
|
|
|
while (from.pos() && from_par.isLetter(from.pos() - 1))
|
2004-06-29 15:43:25 +00:00
|
|
|
|
--from.pos();
|
2003-11-11 10:08:35 +00:00
|
|
|
|
break;
|
2006-10-21 00:16:43 +00:00
|
|
|
|
case NEXT_WORD:
|
2007-11-29 21:10:35 +00:00
|
|
|
|
LYXERR0("Text::getWord: NEXT_WORD not implemented yet");
|
2003-11-11 10:08:35 +00:00
|
|
|
|
break;
|
2006-10-21 00:16:43 +00:00
|
|
|
|
case PARTIAL_WORD:
|
2004-06-29 15:43:25 +00:00
|
|
|
|
// no need to move the 'from' cursor
|
2003-11-11 10:08:35 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
to = from;
|
2008-02-26 00:38:30 +00:00
|
|
|
|
Paragraph const & to_par = pars_[to.pit()];
|
2004-11-18 14:58:54 +00:00
|
|
|
|
while (to.pos() < to_par.size() && to_par.isLetter(to.pos()))
|
2004-02-12 16:36:01 +00:00
|
|
|
|
++to.pos();
|
2003-11-11 10:08:35 +00:00
|
|
|
|
}
|
2003-12-02 12:39:14 +00:00
|
|
|
|
|
|
|
|
|
|
2007-12-12 19:28:07 +00:00
|
|
|
|
void Text::write(Buffer const & buf, ostream & os) const
|
2003-12-02 12:39:14 +00:00
|
|
|
|
{
|
|
|
|
|
ParagraphList::const_iterator pit = paragraphs().begin();
|
|
|
|
|
ParagraphList::const_iterator end = paragraphs().end();
|
2006-10-21 00:16:43 +00:00
|
|
|
|
depth_type dth = 0;
|
2003-12-02 12:39:14 +00:00
|
|
|
|
for (; pit != end; ++pit)
|
2008-02-27 20:43:16 +00:00
|
|
|
|
pit->write(os, buf.params(), dth);
|
2007-08-12 14:56:49 +00:00
|
|
|
|
|
|
|
|
|
// Close begin_deeper
|
|
|
|
|
for(; dth > 0; --dth)
|
|
|
|
|
os << "\n\\end_deeper";
|
2003-12-02 12:39:14 +00:00
|
|
|
|
}
|
2003-12-03 15:27:16 +00:00
|
|
|
|
|
|
|
|
|
|
It used to be that things like InsetFlex, InsetCaption, and the like used the default layout, whatever that is---usually Standard. That gave rise to bug 2178, the solution to which is to define a new empty layout, which insets like these use instead of the default. See r22966.
So, when we have an older LyX file, it will look like this:
\begin_inset ERT
status open
\begin_layout Standard
this that
\end_layout
\end_inset
which is now invalid, because ERT uses only PlainLayout. So I had put some code into Text::readParToken, where the layout for a paragraph gets set as it is read:
if (par.forceEmptyLayout()) {
// in this case only the empty layout is allowed
layoutname = tclass.emptyLayoutName();
} else if (par.useEmptyLayout()) {
// in this case, default layout maps to empty layout
if (layoutname == tclass.defaultLayoutName())
layoutname = tclass.emptyLayoutName();
} else {
// otherwise, the empty layout maps to the default
if (layoutname == tclass.emptyLayoutName())
layoutname = tclass.defaultLayoutName();
}
This turns out not to work, because par.forceEmptyLayout() and par.useEmptyLayout() always return false here, because par.inInset() always returns a null pointer, because the paragraph's inset hasn't yet been set when Text::readParagraph() gets called from Text::read() gets called from InsetText::read(). The solution is to set the paragraph's inset when it is created, which means passing a pointer to the various read() routines along the way.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23057 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-19 02:35:07 +00:00
|
|
|
|
bool Text::read(Buffer const & buf, Lexer & lex,
|
2008-02-19 03:46:11 +00:00
|
|
|
|
ErrorList & errorList, InsetText * insetPtr)
|
2004-01-28 16:21:29 +00:00
|
|
|
|
{
|
2006-10-21 00:16:43 +00:00
|
|
|
|
depth_type depth = 0;
|
2003-12-03 15:27:16 +00:00
|
|
|
|
|
|
|
|
|
while (lex.isOK()) {
|
|
|
|
|
lex.nextToken();
|
2004-07-25 00:04:42 +00:00
|
|
|
|
string const token = lex.getString();
|
2003-12-03 15:27:16 +00:00
|
|
|
|
|
|
|
|
|
if (token.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
if (token == "\\end_inset")
|
2004-03-18 12:53:43 +00:00
|
|
|
|
break;
|
2003-12-03 15:27:16 +00:00
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
if (token == "\\end_body")
|
2004-08-16 00:16:17 +00:00
|
|
|
|
continue;
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
if (token == "\\begin_body")
|
2004-08-16 00:16:17 +00:00
|
|
|
|
continue;
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
if (token == "\\end_document")
|
2004-03-18 12:53:43 +00:00
|
|
|
|
return false;
|
2003-12-03 15:27:16 +00:00
|
|
|
|
|
|
|
|
|
if (token == "\\begin_layout") {
|
|
|
|
|
lex.pushToken(token);
|
|
|
|
|
|
|
|
|
|
Paragraph par;
|
|
|
|
|
par.params().depth(depth);
|
2007-10-28 18:51:54 +00:00
|
|
|
|
par.setFont(0, Font(inherit_font, buf.params().language));
|
It used to be that things like InsetFlex, InsetCaption, and the like used the default layout, whatever that is---usually Standard. That gave rise to bug 2178, the solution to which is to define a new empty layout, which insets like these use instead of the default. See r22966.
So, when we have an older LyX file, it will look like this:
\begin_inset ERT
status open
\begin_layout Standard
this that
\end_layout
\end_inset
which is now invalid, because ERT uses only PlainLayout. So I had put some code into Text::readParToken, where the layout for a paragraph gets set as it is read:
if (par.forceEmptyLayout()) {
// in this case only the empty layout is allowed
layoutname = tclass.emptyLayoutName();
} else if (par.useEmptyLayout()) {
// in this case, default layout maps to empty layout
if (layoutname == tclass.defaultLayoutName())
layoutname = tclass.emptyLayoutName();
} else {
// otherwise, the empty layout maps to the default
if (layoutname == tclass.emptyLayoutName())
layoutname = tclass.defaultLayoutName();
}
This turns out not to work, because par.forceEmptyLayout() and par.useEmptyLayout() always return false here, because par.inInset() always returns a null pointer, because the paragraph's inset hasn't yet been set when Text::readParagraph() gets called from Text::read() gets called from InsetText::read(). The solution is to set the paragraph's inset when it is created, which means passing a pointer to the various read() routines along the way.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23057 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-19 02:35:07 +00:00
|
|
|
|
par.setInsetOwner(insetPtr);
|
2004-03-25 09:16:36 +00:00
|
|
|
|
pars_.push_back(par);
|
2003-12-03 15:27:16 +00:00
|
|
|
|
|
|
|
|
|
// FIXME: goddamn InsetTabular makes us pass a Buffer
|
|
|
|
|
// not BufferParams
|
2006-10-21 00:16:43 +00:00
|
|
|
|
lyx::readParagraph(buf, pars_.back(), lex, errorList);
|
2003-12-03 15:27:16 +00:00
|
|
|
|
|
2008-02-26 13:07:59 +00:00
|
|
|
|
// register the words in the global word list
|
|
|
|
|
CursorSlice sl = CursorSlice(*insetPtr);
|
|
|
|
|
sl.pit() = pars_.size() - 1;
|
2008-03-04 15:05:16 +00:00
|
|
|
|
pars_.back().updateWords(sl);
|
2003-12-03 15:27:16 +00:00
|
|
|
|
} else if (token == "\\begin_deeper") {
|
|
|
|
|
++depth;
|
|
|
|
|
} else if (token == "\\end_deeper") {
|
2007-11-29 21:10:35 +00:00
|
|
|
|
if (!depth)
|
2003-12-03 15:27:16 +00:00
|
|
|
|
lex.printError("\\end_deeper: " "depth is already null");
|
2007-11-29 21:10:35 +00:00
|
|
|
|
else
|
2003-12-03 15:27:16 +00:00
|
|
|
|
--depth;
|
|
|
|
|
} else {
|
2007-11-29 21:10:35 +00:00
|
|
|
|
LYXERR0("Handling unknown body token: `" << token << '\'');
|
2003-12-03 15:27:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-08-14 18:41:27 +00:00
|
|
|
|
return true;
|
2003-12-03 15:27:16 +00:00
|
|
|
|
}
|
2003-12-10 09:45:32 +00:00
|
|
|
|
|
2004-02-13 07:30:59 +00:00
|
|
|
|
// Returns the current font and depth as a message.
|
2007-04-29 23:33:02 +00:00
|
|
|
|
docstring Text::currentState(Cursor & cur)
|
2004-02-13 07:30:59 +00:00
|
|
|
|
{
|
2004-02-13 11:05:29 +00:00
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
2004-04-08 15:03:33 +00:00
|
|
|
|
Buffer & buf = cur.buffer();
|
2004-02-13 07:30:59 +00:00
|
|
|
|
Paragraph const & par = cur.paragraph();
|
2006-12-21 13:58:28 +00:00
|
|
|
|
odocstringstream os;
|
2004-02-13 07:30:59 +00:00
|
|
|
|
|
2006-10-06 18:53:35 +00:00
|
|
|
|
if (buf.params().trackChanges)
|
2007-01-08 22:38:49 +00:00
|
|
|
|
os << _("[Change Tracking] ");
|
2006-03-11 13:31:41 +00:00
|
|
|
|
|
2006-10-22 16:47:42 +00:00
|
|
|
|
Change change = par.lookupChange(cur.pos());
|
|
|
|
|
|
|
|
|
|
if (change.type != Change::UNCHANGED) {
|
2004-04-08 15:03:33 +00:00
|
|
|
|
Author const & a = buf.params().authors().get(change.author);
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << _("Change: ") << a.name();
|
2004-02-13 07:30:59 +00:00
|
|
|
|
if (!a.email().empty())
|
|
|
|
|
os << " (" << a.email() << ")";
|
2006-12-21 13:58:28 +00:00
|
|
|
|
// FIXME ctime is english, we should translate that
|
|
|
|
|
os << _(" at ") << ctime(&change.changetime);
|
2004-02-13 07:30:59 +00:00
|
|
|
|
os << " : ";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// I think we should only show changes from the default
|
|
|
|
|
// font. (Asger)
|
2006-02-05 13:20:16 +00:00
|
|
|
|
// No, from the document font (MV)
|
2007-09-02 13:35:48 +00:00
|
|
|
|
Font font = cur.real_current_font;
|
2007-10-28 18:51:54 +00:00
|
|
|
|
font.fontInfo().reduce(buf.params().getFont().fontInfo());
|
2004-02-13 07:30:59 +00:00
|
|
|
|
|
2006-12-21 14:31:19 +00:00
|
|
|
|
os << bformat(_("Font: %1$s"), font.stateText(&buf.params()));
|
2004-02-13 07:30:59 +00:00
|
|
|
|
|
|
|
|
|
// The paragraph depth
|
2004-03-18 13:28:49 +00:00
|
|
|
|
int depth = cur.paragraph().getDepth();
|
2004-02-13 07:30:59 +00:00
|
|
|
|
if (depth > 0)
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << bformat(_(", Depth: %1$d"), depth);
|
2004-02-13 07:30:59 +00:00
|
|
|
|
|
|
|
|
|
// The paragraph spacing, but only if different from
|
|
|
|
|
// buffer spacing.
|
|
|
|
|
Spacing const & spacing = par.params().spacing();
|
|
|
|
|
if (!spacing.isDefault()) {
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << _(", Spacing: ");
|
2004-02-13 07:30:59 +00:00
|
|
|
|
switch (spacing.getSpace()) {
|
|
|
|
|
case Spacing::Single:
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << _("Single");
|
2004-02-13 07:30:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case Spacing::Onehalf:
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << _("OneHalf");
|
2004-02-13 07:30:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case Spacing::Double:
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << _("Double");
|
2004-02-13 07:30:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case Spacing::Other:
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << _("Other (") << from_ascii(spacing.getValueAsString()) << ')';
|
2004-02-13 07:30:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case Spacing::Default:
|
|
|
|
|
// should never happen, do nothing
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-08-13 20:26:26 +00:00
|
|
|
|
|
2004-02-13 07:30:59 +00:00
|
|
|
|
#ifdef DEVEL_VERSION
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << _(", Inset: ") << &cur.inset();
|
|
|
|
|
os << _(", Paragraph: ") << cur.pit();
|
|
|
|
|
os << _(", Id: ") << par.id();
|
|
|
|
|
os << _(", Position: ") << cur.pos();
|
2007-01-29 18:08:13 +00:00
|
|
|
|
// FIXME: Why is the check for par.size() needed?
|
|
|
|
|
// We are called with cur.pos() == par.size() quite often.
|
|
|
|
|
if (!par.empty() && cur.pos() < par.size()) {
|
2007-01-29 09:40:04 +00:00
|
|
|
|
// Force output of code point, not character
|
|
|
|
|
size_t const c = par.getChar(cur.pos());
|
2007-12-12 19:28:07 +00:00
|
|
|
|
os << _(", Char: 0x") << hex << c;
|
2007-01-29 09:40:04 +00:00
|
|
|
|
}
|
2006-12-21 13:58:28 +00:00
|
|
|
|
os << _(", Boundary: ") << cur.boundary();
|
2004-11-30 01:59:49 +00:00
|
|
|
|
// Row & row = cur.textRow();
|
|
|
|
|
// os << bformat(_(", Row b:%1$d e:%2$d"), row.pos(), row.endpos());
|
2004-02-13 07:30:59 +00:00
|
|
|
|
#endif
|
|
|
|
|
return os.str();
|
|
|
|
|
}
|
2004-02-13 13:51:12 +00:00
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
docstring Text::getPossibleLabel(Cursor & cur) const
|
2004-02-13 13:51:12 +00:00
|
|
|
|
{
|
2004-11-24 21:53:46 +00:00
|
|
|
|
pit_type pit = cur.pit();
|
2004-02-13 13:51:12 +00:00
|
|
|
|
|
2007-08-23 19:59:07 +00:00
|
|
|
|
LayoutPtr layout = pars_[pit].layout();
|
2004-02-13 13:51:12 +00:00
|
|
|
|
|
2007-03-16 11:36:36 +00:00
|
|
|
|
docstring text;
|
2008-02-27 20:43:16 +00:00
|
|
|
|
docstring par_text = pars_[pit].asString(false);
|
2007-11-07 15:30:08 +00:00
|
|
|
|
string piece;
|
|
|
|
|
// the return string of math matrices might contain linebreaks
|
2007-11-10 11:05:38 +00:00
|
|
|
|
par_text = subst(par_text, '\n', '-');
|
2004-02-13 13:51:12 +00:00
|
|
|
|
for (int i = 0; i < lyxrc.label_init_length; ++i) {
|
|
|
|
|
if (par_text.empty())
|
|
|
|
|
break;
|
2006-11-11 11:27:47 +00:00
|
|
|
|
docstring head;
|
2004-02-13 13:51:12 +00:00
|
|
|
|
par_text = split(par_text, head, ' ');
|
|
|
|
|
// Is it legal to use spaces in labels ?
|
|
|
|
|
if (i > 0)
|
|
|
|
|
text += '-';
|
|
|
|
|
text += head;
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-16 11:36:36 +00:00
|
|
|
|
// No need for a prefix if the user said so.
|
|
|
|
|
if (lyxrc.label_init_length <= 0)
|
|
|
|
|
return text;
|
|
|
|
|
|
|
|
|
|
// Will contain the label type.
|
|
|
|
|
docstring name;
|
|
|
|
|
|
|
|
|
|
// For section, subsection, etc...
|
|
|
|
|
if (layout->latextype == LATEX_PARAGRAPH && pit != 0) {
|
2007-08-23 19:59:07 +00:00
|
|
|
|
LayoutPtr const & layout2 = pars_[pit - 1].layout();
|
2007-03-16 11:36:36 +00:00
|
|
|
|
if (layout2->latextype != LATEX_PARAGRAPH) {
|
|
|
|
|
--pit;
|
|
|
|
|
layout = layout2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (layout->latextype != LATEX_PARAGRAPH)
|
|
|
|
|
name = from_ascii(layout->latexname());
|
|
|
|
|
|
|
|
|
|
// for captions, we just take the caption type
|
2007-10-13 09:04:52 +00:00
|
|
|
|
Inset * caption_inset = cur.innerInsetOfType(CAPTION_CODE);
|
2007-03-16 11:36:36 +00:00
|
|
|
|
if (caption_inset)
|
|
|
|
|
name = from_ascii(static_cast<InsetCaption *>(caption_inset)->type());
|
|
|
|
|
|
2007-05-08 15:10:08 +00:00
|
|
|
|
// If none of the above worked, we'll see if we're inside various
|
|
|
|
|
// types of insets and take our abbreviation from them.
|
2007-03-16 11:36:36 +00:00
|
|
|
|
if (name.empty()) {
|
2007-10-13 09:04:52 +00:00
|
|
|
|
InsetCode const codes[] = {
|
|
|
|
|
FLOAT_CODE,
|
|
|
|
|
WRAP_CODE,
|
|
|
|
|
FOOT_CODE
|
2007-05-08 15:10:08 +00:00
|
|
|
|
};
|
|
|
|
|
for (unsigned int i = 0; i < (sizeof codes / sizeof codes[0]); ++i) {
|
|
|
|
|
Inset * float_inset = cur.innerInsetOfType(codes[i]);
|
|
|
|
|
if (float_inset) {
|
|
|
|
|
name = float_inset->name();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-03-16 11:36:36 +00:00
|
|
|
|
}
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-03-16 11:36:36 +00:00
|
|
|
|
// Create a correct prefix for prettyref
|
|
|
|
|
if (name == "theorem")
|
|
|
|
|
name = from_ascii("thm");
|
2007-05-08 15:10:08 +00:00
|
|
|
|
else if (name == "Foot")
|
|
|
|
|
name = from_ascii("fn");
|
2007-05-14 20:42:14 +00:00
|
|
|
|
else if (name == "listing")
|
|
|
|
|
name = from_ascii("lst");
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-03-16 11:36:36 +00:00
|
|
|
|
if (!name.empty())
|
|
|
|
|
text = name.substr(0, 3) + ':' + text;
|
|
|
|
|
|
2004-02-13 13:51:12 +00:00
|
|
|
|
return text;
|
|
|
|
|
}
|
2004-02-16 11:58:51 +00:00
|
|
|
|
|
|
|
|
|
|
2007-04-29 23:33:02 +00:00
|
|
|
|
void Text::charsTranspose(Cursor & cur)
|
2006-11-17 09:03:30 +00:00
|
|
|
|
{
|
|
|
|
|
BOOST_ASSERT(this == cur.text());
|
|
|
|
|
|
|
|
|
|
pos_type pos = cur.pos();
|
|
|
|
|
|
|
|
|
|
// If cursor is at beginning or end of paragraph, do nothing.
|
|
|
|
|
if (pos == cur.lastpos() || pos == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Paragraph & par = cur.paragraph();
|
|
|
|
|
|
2007-05-28 22:27:45 +00:00
|
|
|
|
// Get the positions of the characters to be transposed.
|
2006-11-17 09:03:30 +00:00
|
|
|
|
pos_type pos1 = pos - 1;
|
|
|
|
|
pos_type pos2 = pos;
|
|
|
|
|
|
|
|
|
|
// In change tracking mode, ignore deleted characters.
|
|
|
|
|
while (pos2 < cur.lastpos() && par.isDeleted(pos2))
|
|
|
|
|
++pos2;
|
|
|
|
|
if (pos2 == cur.lastpos())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
while (pos1 >= 0 && par.isDeleted(pos1))
|
|
|
|
|
--pos1;
|
|
|
|
|
if (pos1 < 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Don't do anything if one of the "characters" is not regular text.
|
|
|
|
|
if (par.isInset(pos1) || par.isInset(pos2))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Store the characters to be transposed (including font information).
|
|
|
|
|
char_type char1 = par.getChar(pos1);
|
2007-04-29 18:17:15 +00:00
|
|
|
|
Font const font1 =
|
2006-11-17 09:03:30 +00:00
|
|
|
|
par.getFontSettings(cur.buffer().params(), pos1);
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2006-11-17 09:03:30 +00:00
|
|
|
|
char_type char2 = par.getChar(pos2);
|
2007-04-29 18:17:15 +00:00
|
|
|
|
Font const font2 =
|
2006-11-17 09:03:30 +00:00
|
|
|
|
par.getFontSettings(cur.buffer().params(), pos2);
|
|
|
|
|
|
|
|
|
|
// And finally, we are ready to perform the transposition.
|
|
|
|
|
// Track the changes if Change Tracking is enabled.
|
|
|
|
|
bool const trackChanges = cur.buffer().params().trackChanges;
|
|
|
|
|
|
2007-10-18 11:51:17 +00:00
|
|
|
|
cur.recordUndo();
|
2006-11-17 09:03:30 +00:00
|
|
|
|
|
|
|
|
|
par.eraseChar(pos2, trackChanges);
|
|
|
|
|
par.eraseChar(pos1, trackChanges);
|
|
|
|
|
par.insertChar(pos1, char2, font2, trackChanges);
|
|
|
|
|
par.insertChar(pos2, char1, font1, trackChanges);
|
|
|
|
|
|
2008-01-12 21:38:51 +00:00
|
|
|
|
cur.checkBufferStructure();
|
2007-03-12 11:23:41 +00:00
|
|
|
|
|
2006-11-17 09:03:30 +00:00
|
|
|
|
// After the transposition, move cursor to after the transposition.
|
|
|
|
|
setCursor(cur, cur.pit(), pos2);
|
|
|
|
|
cur.forwardPos();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-12-21 20:42:46 +00:00
|
|
|
|
DocIterator Text::macrocontextPosition() const
|
|
|
|
|
{
|
|
|
|
|
return macrocontext_position_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Text::setMacrocontextPosition(DocIterator const & pos)
|
|
|
|
|
{
|
|
|
|
|
macrocontext_position_ = pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
} // namespace lyx
|