/**
- * \file text.C
+ * \file src/text.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
#include <config.h>
#include "lyxtext.h"
-#include "paragraph.h"
-#include "gettext.h"
-#include "bufferparams.h"
+
#include "buffer.h"
+#include "bufferparams.h"
+#include "BufferView.h"
#include "debug.h"
-#include "intl.h"
-#include "lyxrc.h"
#include "encoding.h"
-#include "frontends/LyXView.h"
-#include "frontends/Painter.h"
-#include "frontends/font_metrics.h"
-#include "frontends/screen.h"
-#include "frontends/WorkArea.h"
-#include "bufferview_funcs.h"
-#include "BufferView.h"
+#include "funcrequest.h"
+#include "gettext.h"
#include "language.h"
+#include "LColor.h"
+#include "lyxlength.h"
+#include "lyxrc.h"
+#include "lyxrow.h"
+#include "lyxrow_funcs.h"
+#include "paragraph.h"
+#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
-#include "undo_funcs.h"
+#include "rowpainter.h"
#include "text_funcs.h"
+#include "undo_funcs.h"
+#include "vspace.h"
#include "WordLangTuple.h"
-#include "paragraph_funcs.h"
-#include "rowpainter.h"
-#include "lyxrow_funcs.h"
-#include "metricsinfo.h"
+
+#include "frontends/font_metrics.h"
+#include "frontends/LyXView.h"
#include "insets/insettext.h"
-#include "support/textutils.h"
-#include "support/LAssert.h"
#include "support/lstrings.h"
+#include "support/textutils.h"
-#include <algorithm>
+using bv_funcs::number;
-using namespace lyx::support;
+using lyx::pos_type;
+using lyx::word_location;
+
+using lyx::support::contains;
+using lyx::support::lowercase;
+using lyx::support::uppercase;
using std::max;
-using std::min;
using std::endl;
-using std::pair;
+using std::string;
-using lyx::pos_type;
-using lyx::word_location;
-
-using namespace bv_funcs;
/// top, right, bottom pixel margin
extern int const PAPER_MARGIN = 20;
BufferView * LyXText::bv()
{
- Assert(bv_owner != 0);
+ BOOST_ASSERT(bv_owner != 0);
return bv_owner;
}
BufferView * LyXText::bv() const
{
- Assert(bv_owner != 0);
+ BOOST_ASSERT(bv_owner != 0);
return bv_owner;
}
for (height = 0; pit != end; ++pit) {
RowList::iterator rit = pit->rows.begin();
RowList::iterator rend = pit->rows.end();
- for ( ; rit != rend ; rit = ++rit) {
+ for ( ; rit != rend ; ++rit) {
rit->y(height);
height += rit->height();
}
{
if (pos >= pit->size()) {
lyxerr << "in singleWidth(), pos: " << pos << endl;
- Assert(false);
+ BOOST_ASSERT(false);
return 0;
}
if (c == Paragraph::META_INSET) {
InsetOld * tmpinset = pit->getInset(pos);
- Assert(tmpinset);
+ BOOST_ASSERT(tmpinset);
if (tmpinset->lyxCode() == InsetOld::HFILL_CODE) {
// Because of the representation as vertical lines
return 3;
void LyXText::computeBidiTables(ParagraphList::iterator pit,
- Buffer const * buf, RowList::iterator row) const
+ Buffer const & buf, RowList::iterator row) const
{
bidi_same_direction = true;
if (!lyxrc.rtl_support) {
}
bidi_start = row->pos();
- bidi_end = lastPrintablePos(*pit, row);
+ bidi_end = lastPos(*pit, row);
if (bidi_start > bidi_end) {
bidi_start = -1;
vis2log_list[bidi_end + 1 - bidi_start] = -1;
log2vis_list[bidi_end + 1 - bidi_start] = -1;
+ BufferParams const & bufparams = buf.params();
pos_type stack[2];
bool const rtl_par =
- pit->isRightToLeftPar(buf->params);
+ pit->isRightToLeftPar(bufparams);
int level = 0;
bool rtl = false;
bool rtl0 = false;
!pit->isLineSeparator(lpos + 1) &&
!pit->isNewline(lpos + 1))
? lpos + 1 : lpos;
- LyXFont font = pit->getFontSettings(buf->params, pos);
+ LyXFont font = pit->getFontSettings(bufparams, pos);
if (pos != lpos && 0 < lpos && rtl0 && font.isRightToLeft() &&
font.number() == LyXFont::ON &&
- pit->getFontSettings(buf->params, lpos - 1).number()
+ pit->getFontSettings(bufparams, lpos - 1).number()
== LyXFont::ON) {
- font = pit->getFontSettings(buf->params, lpos);
+ font = pit->getFontSettings(bufparams, lpos);
is_space = false;
}
// This method requires a previous call to ComputeBidiTables()
-bool LyXText::isBoundary(Buffer const * buf, Paragraph const & par,
+bool LyXText::isBoundary(Buffer const & buf, Paragraph const & par,
pos_type pos) const
{
if (!lyxrc.rtl_support || pos == 0)
bool const rtl = bidi_level(pos - 1) % 2;
bool const rtl2 = bidi_InRange(pos)
? bidi_level(pos) % 2
- : par.isRightToLeftPar(buf->params);
+ : par.isRightToLeftPar(buf.params());
return rtl != rtl2;
}
-bool LyXText::isBoundary(Buffer const * buf, Paragraph const & par,
+bool LyXText::isBoundary(Buffer const & buf, Paragraph const & par,
pos_type pos, LyXFont const & font) const
{
if (!lyxrc.rtl_support)
bool const rtl = font.isVisibleRightToLeft();
bool const rtl2 = bidi_InRange(pos)
? bidi_level(pos) % 2
- : par.isRightToLeftPar(buf->params);
+ : par.isRightToLeftPar(buf.params());
return rtl != rtl2;
}
int LyXText::leftMargin(ParagraphList::iterator pit, Row const & row) const
{
LyXTextClass const & tclass =
- bv()->buffer()->params.getLyXTextClass();
+ bv()->buffer()->params().getLyXTextClass();
LyXLayout_ptr const & layout = pit->layout();
string parindent = layout->parindent;
(pit->inInset()->owner()->lyxCode() != InsetOld::TABULAR_CODE &&
pit->inInset()->owner()->lyxCode() != InsetOld::ERT_CODE))
&& (pit->layout() != tclass.defaultLayout() ||
- bv()->buffer()->params.paragraph_separation ==
+ bv()->buffer()->params().paragraph_separation ==
BufferParams::PARSEP_INDENT)) {
x += font_metrics::signedWidth(parindent,
tclass.defaultfont());
int LyXText::rightMargin(ParagraphList::iterator pit,
- Buffer const & buf, Row const & row) const
+ Buffer const & buf, Row const &) const
{
- LyXTextClass const & tclass = buf.params.getLyXTextClass();
+ LyXTextClass const & tclass = buf.params().getLyXTextClass();
LyXLayout_ptr const & layout = pit->layout();
return PAPER_MARGIN
Row const & row) const
{
// maximum pixel width of a row.
- int width = workWidth()
+ int width = workWidth()
- rightMargin(pit, *bv()->buffer(), row);
// inset->textWidth() returns -1 via workWidth(),
int w;
// get the pure distance
- pos_type const last = lastPrintablePos(*pit, row);
+ pos_type const last = lastPos(*pit, row);
LyXLayout_ptr const & layout = pit->layout();
font = getFont(pit, i);
endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
}
- w += singleWidth(pit, i, c, font);
+ w += singleWidth(pit, i, c, font);
++i;
}
}
{
pos_type last = pit->beginningOfBody();
- Assert(last > 0);
+ BOOST_ASSERT(last > 0);
// -1 because a label ends either with a space that is in the label,
// or with the beginning of a footnote that is outside the label.
}
-LColor::color LyXText::backgroundColor() const
+LColor_color LyXText::backgroundColor() const
{
if (inset_owner)
return inset_owner->backgroundColor();
if (!pit->params().spacing().isDefault())
spacing_val = pit->params().spacing().getValue();
else
- spacing_val = bv()->buffer()->params.spacing.getValue();
+ spacing_val = bv()->buffer()->params().spacing().getValue();
//lyxerr << "spacing_val = " << spacing_val << endl;
int maxasc = int(font_metrics::maxAscent(font) *
// is it a top line?
if (!rit->pos()) {
-
+ BufferParams const & bufparams = bv()->buffer()->params();
// some parksips VERY EASY IMPLEMENTATION
- if (bv()->buffer()->params.paragraph_separation ==
+ if (bv()->buffer()->params().paragraph_separation ==
BufferParams::PARSEP_SKIP)
{
if (layout->isParagraph()
&& pit->getDepth() == 0
&& pit != ownerParagraphs().begin())
{
- maxasc += bv()->buffer()->params.getDefSkip().inPixels(*bv());
+ maxasc += bufparams.getDefSkip().inPixels(*bv());
} else if (pit != ownerParagraphs().begin() &&
boost::prior(pit)->layout()->isParagraph() &&
boost::prior(pit)->getDepth() == 0)
{
// is it right to use defskip here too? (AS)
- maxasc += bv()->buffer()->params.getDefSkip().inPixels(*bv());
+ maxasc += bufparams.getDefSkip().inPixels(*bv());
}
}
// This is special code for the chapter, since the label of this
// layout is printed in an extra row
- if (layout->labeltype == LABEL_COUNTER_CHAPTER
- && bv()->buffer()->params.secnumdepth >= 0)
- {
+ if (layout->counter == "chapter" && bufparams.secnumdepth >= 0) {
float spacing_val = 1.0;
if (!pit->params().spacing().isDefault()) {
spacing_val = pit->params().spacing().getValue();
} else {
- spacing_val = bv()->buffer()->params.spacing.getValue();
+ spacing_val = bufparams.spacing().getValue();
}
labeladdon = int(font_metrics::maxDescent(labelfont) *
if (!pit->params().spacing().isDefault()) {
spacing_val = pit->params().spacing().getValue();
} else {
- spacing_val = bv()->buffer()->params.spacing.getValue();
+ spacing_val = bufparams.spacing().getValue();
}
labeladdon = int(
void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout)
{
// allow only if at start or end, or all previous is new text
- if (cursor.pos() && cursor.pos() != cursor.par()->size()
- && cursor.par()->isChangeEdited(0, cursor.pos()))
+ if (cursor.pos() && cursor.pos() != cursorPar()->size()
+ && cursorPar()->isChangeEdited(0, cursor.pos()))
return;
LyXTextClass const & tclass =
- bv()->buffer()->params.getLyXTextClass();
- LyXLayout_ptr const & layout = cursor.par()->layout();
+ bv()->buffer()->params().getLyXTextClass();
+ LyXLayout_ptr const & layout = cursorPar()->layout();
// this is only allowed, if the current paragraph is not empty or caption
// and if it has not the keepempty flag active
- if (cursor.par()->empty() && !cursor.par()->allowEmpty()
+ if (cursorPar()->empty() && !cursorPar()->allowEmpty()
&& layout->labeltype != LABEL_SENSITIVE)
return;
- recordUndo(bv(), Undo::ATOMIC, cursor.par());
+ recordUndo(bv(), Undo::ATOMIC, cursorPar());
// Always break behind a space
//
// It is better to erase the space (Dekel)
- if (cursor.pos() < cursor.par()->size()
- && cursor.par()->isLineSeparator(cursor.pos()))
- cursor.par()->erase(cursor.pos());
+ if (cursor.pos() < cursorPar()->size()
+ && cursorPar()->isLineSeparator(cursor.pos()))
+ cursorPar()->erase(cursor.pos());
// break the paragraph
if (keep_layout)
// breakParagraph call should return a bool if it inserts the
// paragraph before or behind and we should react on that one
// but we can fix this in 1.3.0 (Jug 20020509)
- bool const isempty = (cursor.par()->allowEmpty() && cursor.par()->empty());
- ::breakParagraph(bv()->buffer()->params, paragraphs, cursor.par(),
+ bool const isempty = (cursorPar()->allowEmpty() && cursorPar()->empty());
+ ::breakParagraph(bv()->buffer()->params(), paragraphs, cursorPar(),
cursor.pos(), keep_layout);
#warning Trouble Point! (Lgb)
// When ::breakParagraph is called from within an inset we must
// ensure that the correct ParagraphList is used. Today that is not
// the case and the Buffer::paragraphs is used. Not good. (Lgb)
- ParagraphList::iterator next_par = boost::next(cursor.par());
+ ParagraphList::iterator next_par = boost::next(cursorPar());
// well this is the caption hack since one caption is really enough
if (layout->labeltype == LABEL_SENSITIVE) {
if (!cursor.pos())
// set to standard-layout
- cursor.par()->applyLayout(tclass.defaultLayout());
+ cursorPar()->applyLayout(tclass.defaultLayout());
else
// set to standard-layout
next_par->applyLayout(tclass.defaultLayout());
// This touches only the screen-update. Otherwise we would may have
// an empty row on the screen
if (cursor.pos() && cursorRow()->pos() == cursor.pos()
- && !cursor.par()->isNewline(cursor.pos() - 1))
+ && !cursorPar()->isNewline(cursor.pos() - 1))
{
cursorLeft(bv());
}
next_par->erase(0);
updateCounters();
- redoParagraph(cursor.par());
+ redoParagraph(cursorPar());
redoParagraph(next_par);
// This check is necessary. Otherwise the new empty paragraph will
if (cursor.pos() || isempty)
setCursor(next_par, 0);
else
- setCursor(cursor.par(), 0);
+ setCursor(cursorPar(), 0);
}
void LyXText::redoParagraph()
{
clearSelection();
- redoParagraph(cursor.par());
+ redoParagraph(cursorPar());
setCursorIntern(cursor.par(), cursor.pos());
}
// same Paragraph one to the right and make a rebreak
void LyXText::insertChar(char c)
{
- recordUndo(bv(), Undo::INSERT, cursor.par());
+ recordUndo(bv(), Undo::INSERT, cursorPar());
// When the free-spacing option is set for the current layout,
// disable the double-space checking
- bool const freeSpacing = cursor.par()->layout()->free_spacing ||
- cursor.par()->isFreeSpacing();
+ bool const freeSpacing = cursorPar()->layout()->free_spacing ||
+ cursorPar()->isFreeSpacing();
if (lyxrc.auto_number) {
static string const number_operators = "+-/*";
if (!IsDigit(c) && !contains(number_operators, c) &&
!(contains(number_seperators, c) &&
cursor.pos() >= 1 &&
- cursor.pos() < cursor.par()->size() &&
- getFont(cursor.par(), cursor.pos()).number() == LyXFont::ON &&
- getFont(cursor.par(), cursor.pos() - 1).number() == LyXFont::ON)
+ cursor.pos() < cursorPar()->size() &&
+ getFont(cursorPar(), cursor.pos()).number() == LyXFont::ON &&
+ getFont(cursorPar(), cursor.pos() - 1).number() == LyXFont::ON)
)
number(bv()); // Set current_font.number to OFF
} else if (IsDigit(c) &&
number(bv()); // Set current_font.number to ON
if (cursor.pos() > 0) {
- char const c = cursor.par()->getChar(cursor.pos() - 1);
+ char const c = cursorPar()->getChar(cursor.pos() - 1);
if (contains(number_unary_operators, c) &&
(cursor.pos() == 1 ||
- cursor.par()->isSeparator(cursor.pos() - 2) ||
- cursor.par()->isNewline(cursor.pos() - 2))
+ cursorPar()->isSeparator(cursor.pos() - 2) ||
+ cursorPar()->isNewline(cursor.pos() - 2))
) {
setCharFont(
- cursor.par(),
+ cursorPar(),
cursor.pos() - 1,
current_font);
} else if (contains(number_seperators, c) &&
cursor.pos() >= 2 &&
getFont(
- cursor.par(),
+ cursorPar(),
cursor.pos() - 2).number() == LyXFont::ON) {
setCharFont(
- cursor.par(),
+ cursorPar(),
cursor.pos() - 1,
current_font);
}
if (!freeSpacing && IsLineSeparatorChar(c)) {
if ((cursor.pos() > 0
- && cursor.par()->isLineSeparator(cursor.pos() - 1))
+ && cursorPar()->isLineSeparator(cursor.pos() - 1))
|| (cursor.pos() > 0
- && cursor.par()->isNewline(cursor.pos() - 1))
+ && cursorPar()->isNewline(cursor.pos() - 1))
|| (cursor.pos() == 0)) {
static bool sent_space_message = false;
if (!sent_space_message) {
// Here case LyXText::InsertInset already inserted the character
if (c != Paragraph::META_INSET)
- cursor.par()->insertChar(cursor.pos(), c);
+ cursorPar()->insertChar(cursor.pos(), c);
- setCharFont(cursor.par(), cursor.pos(), rawtmpfont);
+ setCharFont(cursorPar(), cursor.pos(), rawtmpfont);
current_font = rawtmpfont;
real_current_font = realtmpfont;
- redoParagraph(cursor.par());
+ redoParagraph(cursorPar());
setCursor(cursor.par(), cursor.pos() + 1, false, cursor.boundary());
charInserted();
double x = 0;
bool const is_rtl =
- pit->isRightToLeftPar(bv()->buffer()->params);
+ pit->isRightToLeftPar(bv()->buffer()->params());
if (is_rtl)
x = workWidth() > 0 ? rightMargin(pit, *bv()->buffer(), *rit) : 0;
else
switch (align) {
case LYX_ALIGN_BLOCK:
- {
+ {
int const ns = numberOfSeparators(*pit, rit);
- RowList::iterator next_row = boost::next(rit);
+ RowList::iterator next_row = boost::next(rit);
if (ns
&& next_row != pit->rows.end()
- && !pit->isNewline(next_row->pos() - 1)
+ && !pit->isNewline(next_row->pos() - 1)
) {
- fill_separator = w / ns;
- } else if (is_rtl) {
+ fill_separator = w / ns;
+ } else if (is_rtl) {
x += w;
}
break;
}
}
- computeBidiTables(pit, bv()->buffer(), rit);
+ computeBidiTables(pit, *bv()->buffer(), rit);
if (is_rtl) {
pos_type body_pos = pit->beginningOfBody();
pos_type last = lastPos(*pit, rit);
void LyXText::cursorRightOneWord()
{
- ::cursorRightOneWord(cursor, ownerParagraphs());
- setCursor(cursor.par(), cursor.pos());
+ ::cursorRightOneWord(*this, cursor, ownerParagraphs());
+ setCursor(cursorPar(), cursor.pos());
}
void LyXText::cursorLeftOneWord()
{
LyXCursor tmpcursor = cursor;
- ::cursorLeftOneWord(tmpcursor, ownerParagraphs());
- setCursor(tmpcursor.par(), tmpcursor.pos());
+ ::cursorLeftOneWord(*this, tmpcursor, ownerParagraphs());
+ setCursor(getPar(tmpcursor), tmpcursor.pos());
}
void LyXText::selectWord(word_location loc)
{
LyXCursor from = cursor;
- LyXCursor to;
- ::getWord(from, to, loc, ownerParagraphs());
+ LyXCursor to = cursor;
+ ::getWord(*this, from, to, loc, ownerParagraphs());
if (cursor != from)
setCursor(from.par(), from.pos());
if (to == from)
void LyXText::acceptChange()
{
- if (!selection.set() && cursor.par()->size())
+ if (!selection.set() && cursorPar()->size())
return;
if (selection.start.par() == selection.end.par()) {
LyXCursor & startc = selection.start;
LyXCursor & endc = selection.end;
- recordUndo(bv(), Undo::INSERT, startc.par());
- startc.par()->acceptChange(startc.pos(), endc.pos());
+ recordUndo(bv(), Undo::INSERT, getPar(startc));
+ getPar(startc)->acceptChange(startc.pos(), endc.pos());
finishUndo();
clearSelection();
- redoParagraph(startc.par());
+ redoParagraph(getPar(startc));
setCursorIntern(startc.par(), 0);
}
#warning handle multi par selection
void LyXText::rejectChange()
{
- if (!selection.set() && cursor.par()->size())
+ if (!selection.set() && cursorPar()->size())
return;
if (selection.start.par() == selection.end.par()) {
LyXCursor & startc = selection.start;
LyXCursor & endc = selection.end;
- recordUndo(bv(), Undo::INSERT, startc.par());
- startc.par()->rejectChange(startc.pos(), endc.pos());
+ recordUndo(bv(), Undo::INSERT, getPar(startc));
+ getPar(startc)->rejectChange(startc.pos(), endc.pos());
finishUndo();
clearSelection();
- redoParagraph(startc.par());
+ redoParagraph(getPar(startc));
setCursorIntern(startc.par(), 0);
}
#warning handle multi par selection
// This function is only used by the spellchecker for NextWord().
// It doesn't handle LYX_ACCENTs and probably never will.
-WordLangTuple const
-LyXText::selectNextWordToSpellcheck(float & value)
+WordLangTuple const LyXText::selectNextWordToSpellcheck(float & value)
{
if (the_locking_inset) {
WordLangTuple word = the_locking_inset->selectNextWordToSpellcheck(bv(), value);
return word;
}
// we have to go on checking so move cursor to the next char
- if (cursor.pos() == cursor.par()->size()) {
- if (boost::next(cursor.par()) == ownerParagraphs().end())
+ if (cursor.pos() == cursorPar()->size()) {
+ if (cursor.par() + 1 == int(ownerParagraphs().size()))
return word;
- cursor.par(boost::next(cursor.par()));
+ cursor.par(cursor.par() + 1);
cursor.pos(0);
} else
- cursor.pos(cursor.pos() + 1);
+ cursor.pos(cursor.pos() + 1);
}
- ParagraphList::iterator tmppit = cursor.par();
+ int const tmppar = cursor.par();
// If this is not the very first word, skip rest of
// current word because we are probably in the middle
// of a word if there is text here.
- if (cursor.pos() || cursor.par() != ownerParagraphs().begin()) {
- while (cursor.pos() < cursor.par()->size()
- && cursor.par()->isLetter(cursor.pos()))
+ if (cursor.pos() || cursor.par() != 0) {
+ while (cursor.pos() < cursorPar()->size()
+ && cursorPar()->isLetter(cursor.pos()))
cursor.pos(cursor.pos() + 1);
}
// Now, skip until we have real text (will jump paragraphs)
while (true) {
- ParagraphList::iterator cpit = cursor.par();
- pos_type const cpos(cursor.pos());
+ ParagraphList::iterator cpit = cursorPar();
+ pos_type const cpos = cursor.pos();
if (cpos == cpit->size()) {
- if (boost::next(cpit) != ownerParagraphs().end()) {
- cursor.par(boost::next(cpit));
+ if (cursor.par() + 1 != int(ownerParagraphs().size())) {
+ cursor.par(cursor.par() + 1);
cursor.pos(0);
continue;
}
}
// now check if we hit an inset so it has to be a inset containing text!
- if (cursor.pos() < cursor.par()->size() &&
- cursor.par()->isInset(cursor.pos())) {
+ if (cursor.pos() < cursorPar()->size() &&
+ cursorPar()->isInset(cursor.pos())) {
// lock the inset!
FuncRequest cmd(bv(), LFUN_INSET_EDIT, "left");
- cursor.par()->getInset(cursor.pos())->localDispatch(cmd);
+ cursorPar()->getInset(cursor.pos())->localDispatch(cmd);
// now call us again to do the above trick
// but obviously we have to start from down below ;)
return bv()->text->selectNextWordToSpellcheck(value);
}
// Update the value if we changed paragraphs
- if (cursor.par() != tmppit) {
+ if (cursor.par() != tmppar) {
setCursor(cursor.par(), cursor.pos());
value = float(cursor.y())/float(height);
}
// Start the selection from here
selection.cursor = cursor;
- string lang_code = getFont(cursor.par(), cursor.pos()).language()->code();
+ string lang_code = getFont(cursorPar(), cursor.pos()).language()->code();
// and find the end of the word (insets like optional hyphens
// and ligature break are part of a word)
- while (cursor.pos() < cursor.par()->size()
- && cursor.par()->isLetter(cursor.pos())
- && !isDeletedText(*cursor.par(), cursor.pos()))
+ while (cursor.pos() < cursorPar()->size()
+ && cursorPar()->isLetter(cursor.pos())
+ && !isDeletedText(*cursorPar(), cursor.pos()))
cursor.pos(cursor.pos() + 1);
// Finally, we copy the word to a string and return it
if (selection.cursor.pos() < cursor.pos()) {
pos_type i;
for (i = selection.cursor.pos(); i < cursor.pos(); ++i) {
- if (!cursor.par()->isInset(i))
- str += cursor.par()->getChar(i);
+ if (!cursorPar()->isInset(i))
+ str += cursorPar()->getChar(i);
}
}
return WordLangTuple(str, lang_code);
selection.cursor = cursor;
// now find the end of the word
- while (cursor.pos() < cursor.par()->size()
- && cursor.par()->isLetter(cursor.pos()))
+ while (cursor.pos() < cursorPar()->size()
+ && cursorPar()->isLetter(cursor.pos()))
cursor.pos(cursor.pos() + 1);
- setCursor(cursor.par(), cursor.pos());
+ setCursor(cursorPar(), cursor.pos());
// finally set the selection
setSelection();
// Delete from cursor up to the end of the current or next word.
void LyXText::deleteWordForward()
{
- if (cursor.par()->empty())
+ if (cursorPar()->empty())
cursorRight(bv());
else {
LyXCursor tmpcursor = cursor;
// Delete from cursor to start of current or prior word.
void LyXText::deleteWordBackward()
{
- if (cursor.par()->empty())
+ if (cursorPar()->empty())
cursorLeft(bv());
else {
LyXCursor tmpcursor = cursor;
// Kill to end of line.
void LyXText::deleteLineForward()
{
- if (cursor.par()->empty())
+ if (cursorPar()->empty())
// Paragraph is empty, so we just go to the right
cursorRight(bv());
else {
to = selection.end;
} else {
from = cursor;
- ::getWord(from, to, lyx::PARTIAL_WORD, ownerParagraphs());
+ ::getWord(*this, from, to, lyx::PARTIAL_WORD, ownerParagraphs());
setCursor(to.par(), to.pos() + 1);
}
- recordUndo(bv(), Undo::ATOMIC, from.par(), to.par());
+ recordUndo(bv(), Undo::ATOMIC, getPar(from), getPar(to));
pos_type pos = from.pos();
- ParagraphList::iterator pit = from.par();
+ int par = from.par();
- while (pit != ownerParagraphs().end() &&
- (pos != to.pos() || pit != to.par())) {
+ while (par != int(ownerParagraphs().size()) &&
+ (pos != to.pos() || par != to.par())) {
+ ParagraphList::iterator pit = getPar(par);
if (pos == pit->size()) {
- ++pit;
+ ++par;
pos = 0;
continue;
}
unsigned char c = pit->getChar(pos);
- if (!IsInsetChar(c)) {
+ if (c != Paragraph::META_INSET) {
switch (action) {
case text_lowercase:
c = lowercase(c);
// this is a very easy implementation
LyXCursor old_cursor = cursor;
- int const old_cur_par_id = old_cursor.par()->id();
+ int const old_cur_par_id = cursorPar()->id();
int const old_cur_par_prev_id =
- (old_cursor.par() != ownerParagraphs().begin() ?
- boost::prior(old_cursor.par())->id() : -1);
+ old_cursor.par() ? getPar(old_cursor.par() - 1)->id() : -1;
// just move to the right
cursorRight(bv());
// CHECK Look at the comment here.
// This check is not very good...
- // The cursorRightIntern calls DeleteEmptyParagrapgMechanism
+ // The cursorRightIntern calls DeleteEmptyParagraphMechanism
// and that can very well delete the par or par->previous in
// old_cursor. Will a solution where we compare paragraph id's
//work better?
- if ((cursor.par() != ownerParagraphs().begin() ? boost::prior(cursor.par())->id() : -1)
- == old_cur_par_prev_id
- && cursor.par()->id() != old_cur_par_id) {
+ int iid = cursor.par() ? getPar(cursor.par() - 1)->id() : -1;
+ if (iid == old_cur_par_prev_id && cursorPar()->id() != old_cur_par_id) {
// delete-empty-paragraph-mechanism has done it
return;
}
LyXCursor tmpcursor = cursor;
// to make sure undo gets the right cursor position
cursor = old_cursor;
- recordUndo(bv(), Undo::DELETE, cursor.par());
+ recordUndo(bv(), Undo::DELETE, cursorPar());
cursor = tmpcursor;
backspace();
}
void LyXText::backspace()
{
// Get the font that is used to calculate the baselineskip
- pos_type lastpos = cursor.par()->size();
+ ParagraphList::iterator pit = cursorPar();
+ pos_type lastpos = pit->size();
if (cursor.pos() == 0) {
// The cursor is at the beginning of a paragraph,
// so the the backspace will collapse two paragraphs into one.
// but it's not allowed unless it's new
- if (cursor.par()->isChangeEdited(0, cursor.par()->size()))
+ if (pit->isChangeEdited(0, pit->size()))
return;
// we may paste some paragraphs
// is it an empty paragraph?
- if (lastpos == 0
- || (lastpos == 1 && cursor.par()->isSeparator(0))) {
+ if (lastpos == 0 || (lastpos == 1 && pit->isSeparator(0))) {
// This is an empty paragraph and we delete it just
// by moving the cursor one step
// left and let the DeleteEmptyParagraphMechanism
// handle the actual deletion of the paragraph.
- if (cursor.par() != ownerParagraphs().begin()) {
- ParagraphList::iterator tmppit = boost::prior(cursor.par());
- if (cursor.par()->layout() == tmppit->layout()
- && cursor.par()->getAlign() == tmppit->getAlign()) {
+ if (cursor.par()) {
+ ParagraphList::iterator tmppit = getPar(cursor.par() - 1);
+ if (cursorPar()->layout() == tmppit->layout()
+ && cursorPar()->getAlign() == tmppit->getAlign()) {
// Inherit bottom DTD from the paragraph below.
// (the one we are deleting)
- tmppit->params().lineBottom(cursor.par()->params().lineBottom());
- tmppit->params().spaceBottom(cursor.par()->params().spaceBottom());
- tmppit->params().pagebreakBottom(cursor.par()->params().pagebreakBottom());
+ tmppit->params().lineBottom(cursorPar()->params().lineBottom());
+ tmppit->params().spaceBottom(cursorPar()->params().spaceBottom());
+ tmppit->params().pagebreakBottom(cursorPar()->params().pagebreakBottom());
}
cursorLeft(bv());
}
}
- if (cursor.par() != ownerParagraphs().begin()) {
+ if (cursorPar() != ownerParagraphs().begin()) {
recordUndo(bv(), Undo::DELETE,
- boost::prior(cursor.par()),
- cursor.par());
+ boost::prior(cursorPar()),
+ cursorPar());
}
- ParagraphList::iterator tmppit = cursor.par();
+ ParagraphList::iterator tmppit = cursorPar();
// We used to do cursorLeftIntern() here, but it is
// not a good idea since it triggers the auto-delete
// mechanism. So we do a cursorLeftIntern()-lite,
// without the dreaded mechanism. (JMarc)
- if (cursor.par() != ownerParagraphs().begin()) {
+ if (cursor.par() != 0) {
// steps into the above paragraph.
- setCursorIntern(boost::prior(cursor.par()),
- boost::prior(cursor.par())->size(),
+ setCursorIntern(cursor.par() - 1,
+ getPar(cursor.par() - 1)->size(),
false);
}
// Pasting is not allowed, if the paragraphs have different
// layout. I think it is a real bug of all other
// word processors to allow it. It confuses the user.
- //Correction: Pasting is always allowed with standard-layout
- LyXTextClass const & tclass =
- bv()->buffer()->params.getLyXTextClass();
+ // Correction: Pasting is always allowed with standard-layout
+ Buffer & buf = *bv()->buffer();
+ BufferParams const & bufparams = buf.params();
+ LyXTextClass const & tclass = bufparams.getLyXTextClass();
- if (cursor.par() != tmppit
- && (cursor.par()->layout() == tmppit->layout()
+ if (cursorPar() != tmppit
+ && (cursorPar()->layout() == tmppit->layout()
|| tmppit->layout() == tclass.defaultLayout())
- && cursor.par()->getAlign() == tmppit->getAlign()) {
- mergeParagraph(bv()->buffer()->params,
- bv()->buffer()->paragraphs, cursor.par());
+ && cursorPar()->getAlign() == tmppit->getAlign()) {
+ mergeParagraph(bufparams,
+ buf.paragraphs(), cursorPar());
- if (cursor.pos() && cursor.par()->isSeparator(cursor.pos() - 1))
+ if (cursor.pos() && cursorPar()->isSeparator(cursor.pos() - 1))
cursor.pos(cursor.pos() - 1);
// the row may have changed, block, hfills etc.
} else {
// this is the code for a normal backspace, not pasting
// any paragraphs
- recordUndo(bv(), Undo::DELETE, cursor.par());
+ recordUndo(bv(), Undo::DELETE, cursorPar());
// We used to do cursorLeftIntern() here, but it is
// not a good idea since it triggers the auto-delete
// mechanism. So we do a cursorLeftIntern()-lite,
// without the dreaded mechanism. (JMarc)
setCursorIntern(cursor.par(), cursor.pos() - 1,
false, cursor.boundary());
- cursor.par()->erase(cursor.pos());
+ cursorPar()->erase(cursor.pos());
}
- lastpos = cursor.par()->size();
+ lastpos = cursorPar()->size();
if (cursor.pos() == lastpos)
setCurrentFont();
}
+ParagraphList::iterator LyXText::cursorPar() const
+{
+ return getPar(cursor.par());
+}
+
+
+ParagraphList::iterator LyXText::getPar(LyXCursor const & cur) const
+{
+ return getPar(cur.par());
+}
+
+
+ParagraphList::iterator LyXText::getPar(int par) const
+{
+ BOOST_ASSERT(par >= 0);
+ BOOST_ASSERT(par < ownerParagraphs().size());
+ ParagraphList::iterator pit = ownerParagraphs().begin();
+ std::advance(pit, par);
+ return pit;
+}
+
+
+
RowList::iterator LyXText::cursorRow() const
{
- return getRow(cursor.par(), cursor.pos());
+ return getRow(cursorPar(), cursor.pos());
}
RowList::iterator LyXText::getRow(LyXCursor const & cur) const
{
- return getRow(cur.par(), cur.pos());
+ return getRow(getPar(cur), cur.pos());
}
// returns pointer to some fancy row 'below' specified row
RowList::iterator LyXText::cursorIRow() const
{
- return getRow(cursor.par(), cursor.pos());
+ return getRow(cursorPar(), cursor.pos());
}
int LyXText::getDepth() const
{
- return cursor.par()->getDepth();
+ return cursorPar()->getDepth();
}
if (rit != pit->rows.begin())
--rit;
else {
- Assert(pit != ownerParagraphs().begin());
+ BOOST_ASSERT(pit != ownerParagraphs().begin());
--pit;
rit = boost::prior(pit->rows.end());
}
}
-bool LyXText::noRows() const
+string LyXText::selectionAsString(Buffer const & buffer, bool label) const
+{
+ if (!selection.set())
+ return string();
+
+ // should be const ...
+ ParagraphList::iterator startpit = getPar(selection.start);
+ ParagraphList::iterator endpit = getPar(selection.end);
+ size_t const startpos = selection.start.pos();
+ size_t const endpos = selection.end.pos();
+
+ if (startpit == endpit)
+ return startpit->asString(buffer, startpos, endpos, label);
+
+ // First paragraph in selection
+ string result =
+ startpit->asString(buffer, startpos, startpit->size(), label) + "\n\n";
+
+ // The paragraphs in between (if any)
+ ParagraphList::iterator pit = startpit;
+ for (++pit; pit != endpit; ++pit)
+ result += pit->asString(buffer, 0, pit->size(), label) + "\n\n";
+
+ // Last paragraph in selection
+ result += endpit->asString(buffer, 0, endpos, label);
+
+ return result;
+}
+
+
+int LyXText::parOffset(ParagraphList::iterator pit) const
{
- return ownerParagraphs().begin()->rows.empty();
+ return std::distance(ownerParagraphs().begin(), pit);
}