779 lines
20 KiB
C++
779 lines
20 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
|
**
|
|
** This file is part of the Edyuk project <http://edyuk.org>
|
|
**
|
|
** This file may be used under the terms of the GNU General Public License
|
|
** version 3 as published by the Free Software Foundation and appearing in the
|
|
** file GPL.txt included in the packaging of this file.
|
|
**
|
|
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
**
|
|
****************************************************************************/
|
|
|
|
/*!
|
|
\file qdocumentcursor.cpp
|
|
\brief Implementation of the QDocumentCursor class
|
|
*/
|
|
|
|
#include "qdocumentcursor.h"
|
|
|
|
/*!
|
|
\ingroup document
|
|
@{
|
|
*/
|
|
|
|
#include "qdocument_p.h"
|
|
|
|
#include "qdocumentline.h"
|
|
|
|
/*!
|
|
\class QDocumentCursor
|
|
|
|
\brief A cursor to navigate within documents and edit them
|
|
|
|
QDocumentCursor is a central class of the public API.
|
|
|
|
It is the best (as in fastest and easiest) way to iterate over
|
|
the content of a document.
|
|
|
|
It is also the only class that allows to perform editing operations.
|
|
|
|
A cursor position is defined by a line number and a text position
|
|
within the line.
|
|
|
|
Every cursor can have one or two cursor positions. In the later
|
|
case, they delimit a selection. The first position set (before
|
|
selecting) is referred to as the "anchor" and the other (if it
|
|
is different from the anchor) is the actual cursor position.
|
|
|
|
When the cursor does not have a selection, querying informations about
|
|
the anchor has the same result as querying informations about the cursor
|
|
position.
|
|
|
|
Informations you can get about both the anchor and the posiotion :
|
|
<ul>
|
|
<li>the line number : the logical line to which the cursor position
|
|
points inside the document <li>the column number : the logical text column to
|
|
which the cursor position points to, inside the pointed line. <li>the wrapped
|
|
line offset : when a cursor resides on a wrapped line, this indicates in
|
|
which part of the wrapped line it does <li>the document position : document
|
|
(x, y) coordinates corresponding to the place the cursor is drawn
|
|
</ul>
|
|
|
|
The visual line to which a given cursor resides can be obtained as
|
|
follows :
|
|
|
|
\code
|
|
int visual_line = cursor.document()->visualLine(cursor.lineNumber()) +
|
|
cursor.wrappedLineOffset(); \endcode
|
|
|
|
\note The line and column numbers passed to/returned by a cursor method
|
|
always start at zero.
|
|
|
|
\note Quick overview of the various coordinate systems :
|
|
<ul>
|
|
<li>document coordinates aka viewport coordinates : (x, y)
|
|
coords, in pixels, origin at the top left corner of the rectangle occupied by
|
|
the very first line of the document <li>text coordinates : (line, column) in
|
|
logical units (number of lines, number of characters) <li>visual text
|
|
coordinates : (line, column) in logical units but with a different mapping
|
|
</ul>
|
|
*/
|
|
|
|
QDocumentCursor::QDocumentCursor(QDocument *doc)
|
|
: m_handle(new QDocumentCursorHandle(doc)) {
|
|
m_handle->ref();
|
|
}
|
|
|
|
QDocumentCursor::QDocumentCursor(const QDocumentCursor &cursor) : m_handle(0) {
|
|
if (cursor.m_handle) {
|
|
m_handle = cursor.m_handle->clone();
|
|
m_handle->ref();
|
|
}
|
|
}
|
|
|
|
QDocumentCursor::QDocumentCursor(QDocument *doc, int line, int column)
|
|
: m_handle(new QDocumentCursorHandle(doc, line)) {
|
|
m_handle->ref();
|
|
|
|
m_handle->setColumnNumber(column);
|
|
}
|
|
|
|
/*
|
|
QDocumentCursor::QDocumentCursor(const QDocumentLine& line, int column)
|
|
: m_handle(new QDocumentCursorHandle(line.document(), line.lineNumber()))
|
|
{
|
|
m_handle->ref();
|
|
|
|
m_handle->setColumnNumber(column);
|
|
//movePosition(qMin(column, line.length()));
|
|
}
|
|
*/
|
|
|
|
QDocumentCursor::QDocumentCursor(QDocumentCursorHandle *handle)
|
|
: m_handle(handle) {
|
|
if (m_handle)
|
|
m_handle->ref();
|
|
}
|
|
|
|
QDocumentCursor::~QDocumentCursor() {
|
|
if (m_handle)
|
|
m_handle->deref();
|
|
}
|
|
|
|
QDocumentCursor QDocumentCursor::clone() const {
|
|
return m_handle ? QDocumentCursor(m_handle->clone()) : QDocumentCursor();
|
|
}
|
|
|
|
QDocumentCursor &QDocumentCursor::operator=(const QDocumentCursor &c) {
|
|
#if 0
|
|
if ( m_handle )
|
|
m_handle->deref();
|
|
|
|
m_handle = c.m_handle ? c.m_handle->clone() : 0;
|
|
//m_handle = c.m_handle;
|
|
|
|
if ( m_handle )
|
|
m_handle->ref();
|
|
#endif
|
|
|
|
if (c.m_handle) {
|
|
if (m_handle) {
|
|
m_handle->copy(c.m_handle);
|
|
} else {
|
|
m_handle = c.m_handle->clone();
|
|
m_handle->ref();
|
|
}
|
|
} else if (m_handle) {
|
|
|
|
// qWarning("Setting a cursor to null");
|
|
|
|
m_handle->deref();
|
|
m_handle = 0;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
\brief comparision operator
|
|
|
|
\note If any of the operand is an invalid cursor, false is returned
|
|
*/
|
|
bool QDocumentCursor::operator==(const QDocumentCursor &c) const {
|
|
if (!m_handle || !c.m_handle)
|
|
return false;
|
|
|
|
return m_handle->eq(c.m_handle);
|
|
}
|
|
|
|
/*!
|
|
\brief comparision operator
|
|
|
|
\note If any of the operand is an invalid cursor, true is returned (to
|
|
preserve logical consistency with == )
|
|
*/
|
|
bool QDocumentCursor::operator!=(const QDocumentCursor &c) const {
|
|
if (!m_handle || !c.m_handle)
|
|
return true;
|
|
|
|
return !m_handle->eq(c.m_handle);
|
|
}
|
|
|
|
/*!
|
|
\brief comparision operator
|
|
|
|
\note If any of the operand is an invalid cursor, false is returned
|
|
*/
|
|
bool QDocumentCursor::operator<(const QDocumentCursor &c) const {
|
|
if (!m_handle || !c.m_handle)
|
|
return false;
|
|
|
|
return m_handle->lt(c.m_handle);
|
|
}
|
|
|
|
/*!
|
|
\brief comparision operator
|
|
|
|
\note If any of the operand is an invalid cursor, false is returned
|
|
*/
|
|
bool QDocumentCursor::operator>(const QDocumentCursor &c) const {
|
|
if (!m_handle || !c.m_handle)
|
|
return false;
|
|
|
|
return m_handle->gt(c.m_handle);
|
|
}
|
|
|
|
/*!
|
|
\brief comparision operator
|
|
|
|
\note If any of the operand is an invalid cursor, false is returned
|
|
*/
|
|
bool QDocumentCursor::operator<=(const QDocumentCursor &c) const {
|
|
if (!m_handle || !c.m_handle)
|
|
return false;
|
|
|
|
return m_handle->lt(c.m_handle) || m_handle->eq(c.m_handle);
|
|
}
|
|
|
|
/*!
|
|
\brief comparision operator
|
|
|
|
\note If any of the operand is an invalid cursor, false is returned
|
|
*/
|
|
bool QDocumentCursor::operator>=(const QDocumentCursor &c) const {
|
|
if (!m_handle || !c.m_handle)
|
|
return false;
|
|
|
|
return m_handle->gt(c.m_handle) || m_handle->eq(c.m_handle);
|
|
}
|
|
|
|
/*!
|
|
\brief comparision operator
|
|
*/
|
|
bool QDocumentCursor::isNull() const {
|
|
return !m_handle || !m_handle->document() || !line().isValid();
|
|
}
|
|
|
|
/*!
|
|
\brief comparision operator
|
|
*/
|
|
bool QDocumentCursor::isValid() const {
|
|
return m_handle && m_handle->document() && line().isValid();
|
|
}
|
|
|
|
/*!
|
|
\return whether the cursor is at the end of the document
|
|
*/
|
|
bool QDocumentCursor::atEnd() const {
|
|
return m_handle ? m_handle->atEnd() : false;
|
|
}
|
|
|
|
/*!
|
|
\return whether the cursor is at the begining of the document
|
|
*/
|
|
bool QDocumentCursor::atStart() const {
|
|
return m_handle ? m_handle->atStart() : false;
|
|
}
|
|
|
|
/*!
|
|
\return whether the cursor is at the end of a block
|
|
*/
|
|
bool QDocumentCursor::atBlockEnd() const {
|
|
return m_handle ? m_handle->atBlockEnd() : false;
|
|
}
|
|
|
|
/*!
|
|
\return whether the cursor is at the start of a block
|
|
*/
|
|
bool QDocumentCursor::atBlockStart() const {
|
|
return m_handle ? m_handle->atBlockStart() : false;
|
|
}
|
|
|
|
/*!
|
|
\return whether the cursor is at the end of a line
|
|
|
|
\note this may only differ from atBlockEnd() on wrapped lines
|
|
*/
|
|
bool QDocumentCursor::atLineEnd() const {
|
|
return m_handle ? m_handle->atLineEnd() : false;
|
|
}
|
|
|
|
/*!
|
|
\return whether the cursor is at the start of a line
|
|
|
|
\note this may only differ from atBlockStart() on wrapped lines
|
|
*/
|
|
bool QDocumentCursor::atLineStart() const {
|
|
return m_handle ? m_handle->atLineStart() : false;
|
|
}
|
|
|
|
/*!
|
|
\return the document on which this cursor operates
|
|
*/
|
|
QDocument *QDocumentCursor::document() const {
|
|
return m_handle ? m_handle->document() : 0;
|
|
}
|
|
|
|
/*!
|
|
\return the text position (within the whole document) at which this
|
|
cursor is
|
|
|
|
\note available for compat with QTextCursor and ridiculously slow :
|
|
avoid whenever possible
|
|
*/
|
|
int QDocumentCursor::position() const {
|
|
return m_handle ? m_handle->position() : -1;
|
|
}
|
|
|
|
/*!
|
|
\return the text column of the anchor
|
|
*/
|
|
int QDocumentCursor::anchorColumnNumber() const {
|
|
return m_handle ? m_handle->anchorColumnNumber() : -1;
|
|
}
|
|
|
|
/*!
|
|
\return the "visual" text column of the cursor
|
|
|
|
\note this may only differ from columnNumber() when there are tabs on
|
|
the line
|
|
*/
|
|
int QDocumentCursor::visualColumnNumber() const {
|
|
return m_handle ? m_handle->visualColumnNumber() : -1;
|
|
}
|
|
|
|
/*!
|
|
\return the text column of the cursor
|
|
*/
|
|
int QDocumentCursor::columnNumber() const {
|
|
return m_handle ? m_handle->columnNumber() : -1;
|
|
}
|
|
|
|
/*!
|
|
\brief Set the text column of the cursor
|
|
\param c text column to set
|
|
\param m move mode (determines whether text will be selected)
|
|
*/
|
|
void QDocumentCursor::setColumnNumber(int c, MoveMode m) {
|
|
if (m_handle)
|
|
m_handle->setColumnNumber(c, m);
|
|
}
|
|
|
|
/*!
|
|
\return The line number to which the cursor points
|
|
*/
|
|
int QDocumentCursor::lineNumber() const {
|
|
return m_handle ? m_handle->lineNumber() : -1;
|
|
}
|
|
|
|
/*!
|
|
\return The line number to which the cursor points
|
|
*/
|
|
int QDocumentCursor::anchorLineNumber() const {
|
|
return m_handle ? m_handle->anchorLineNumber() : -1;
|
|
}
|
|
|
|
/*!
|
|
\return The wrapped line on which the cursor resides
|
|
|
|
Wrapped line are "sublines" of logical lines.
|
|
*/
|
|
int QDocumentCursor::wrappedLineOffset() const {
|
|
return line().wrappedLineForCursor(columnNumber());
|
|
}
|
|
|
|
/*!
|
|
\return The line number on which the anchor resides
|
|
*/
|
|
int QDocumentCursor::anchorWrappedLineOffset() const {
|
|
return anchorLine().wrappedLineForCursor(anchorColumnNumber());
|
|
}
|
|
|
|
/*!
|
|
\return the document position at which the cursor is
|
|
|
|
Document position and viewport position are two terms used
|
|
interchangeably. The only difference is the former refers to model perception
|
|
(QDocument) whereas the later refers to view perception (QEditor)
|
|
*/
|
|
QPoint QDocumentCursor::documentPosition() const {
|
|
return m_handle ? m_handle->documentPosition() : QPoint();
|
|
}
|
|
|
|
/*!
|
|
\return the document position of the anchor
|
|
*/
|
|
QPoint QDocumentCursor::anchorDocumentPosition() const {
|
|
return m_handle ? m_handle->anchorDocumentPosition() : QPoint();
|
|
}
|
|
|
|
QPolygon QDocumentCursor::documentRegion() const {
|
|
return m_handle ? m_handle->documentRegion() : QPolygon();
|
|
}
|
|
|
|
/*!
|
|
\return The line object on which the cursor resides
|
|
*/
|
|
QDocumentLine QDocumentCursor::line() const {
|
|
return m_handle ? m_handle->line() : QDocumentLine();
|
|
}
|
|
|
|
/*!
|
|
\return The line object on which the anchor resides
|
|
*/
|
|
QDocumentLine QDocumentCursor::anchorLine() const {
|
|
return m_handle ? m_handle->anchorLine() : QDocumentLine();
|
|
}
|
|
|
|
/*!
|
|
\brief Shift cursor position (text column) by a number of columns
|
|
(characters)
|
|
*/
|
|
void QDocumentCursor::shift(int offset) {
|
|
if (m_handle)
|
|
m_handle->shift(offset);
|
|
}
|
|
|
|
/*!
|
|
\brief Moves the cursor position
|
|
\param offset number of times the selected move will be done
|
|
\param op movement type
|
|
\param m movement mode (whether to select)
|
|
\return true on succes
|
|
*/
|
|
bool QDocumentCursor::movePosition(int offset, MoveOperation op, MoveMode m) {
|
|
return m_handle ? m_handle->movePosition(offset, op, m) : false;
|
|
}
|
|
|
|
/*!
|
|
\brief Jump to another cursor position
|
|
\param line target line number
|
|
\param colum target text column
|
|
*/
|
|
void QDocumentCursor::moveTo(int line, int column) {
|
|
if (m_handle)
|
|
m_handle->moveTo(line, column);
|
|
}
|
|
|
|
/*!
|
|
\brief Jump to the position of another cursor
|
|
\param c target cursor
|
|
*/
|
|
void QDocumentCursor::moveTo(const QDocumentCursor &c) {
|
|
if (m_handle)
|
|
m_handle->moveTo(c);
|
|
}
|
|
|
|
/*!
|
|
\brief Jump to another cursor position
|
|
\param l target line
|
|
\param column target text column
|
|
|
|
\note Calls QDocumentLine::lineNumber() => SLOW : avoid whenever
|
|
possible
|
|
*/
|
|
void QDocumentCursor::moveTo(const QDocumentLine &l, int column) {
|
|
if (m_handle)
|
|
m_handle->moveTo(l.lineNumber(), column);
|
|
}
|
|
|
|
/*!
|
|
\return the character at the position immediately after the cursor
|
|
*/
|
|
QChar QDocumentCursor::nextChar() const {
|
|
return m_handle ? m_handle->nextChar() : QChar();
|
|
}
|
|
|
|
/*!
|
|
\return the character at the position immediately before the cursor
|
|
*/
|
|
QChar QDocumentCursor::previousChar() const {
|
|
return m_handle ? m_handle->previousChar() : QChar();
|
|
}
|
|
|
|
/*!
|
|
\brief Delete the character at the position immediately after the cursor
|
|
*/
|
|
void QDocumentCursor::deleteChar() {
|
|
if (m_handle)
|
|
m_handle->deleteChar();
|
|
}
|
|
|
|
/*!
|
|
\brief Delete the character at the position immediately before the
|
|
cursor
|
|
*/
|
|
void QDocumentCursor::deletePreviousChar() {
|
|
if (m_handle)
|
|
m_handle->deletePreviousChar();
|
|
}
|
|
|
|
/*!
|
|
\brief erase the whole line the cursor is on, newline included
|
|
*/
|
|
void QDocumentCursor::eraseLine() {
|
|
if (m_handle)
|
|
m_handle->eraseLine();
|
|
}
|
|
|
|
/*!
|
|
\brief insert a new line at the cursor position
|
|
*/
|
|
void QDocumentCursor::insertLine(bool keepAnchor) {
|
|
if (m_handle)
|
|
m_handle->insertText(QStringLiteral("\n"), keepAnchor);
|
|
}
|
|
|
|
/*!
|
|
\brief insert some text at the cursor position
|
|
|
|
Selected text will be removed before insertion happens.
|
|
|
|
\note Nothing happens if \a s is empty
|
|
*/
|
|
void QDocumentCursor::insertText(const QString &s, bool keepAnchor,
|
|
const QString &sfmtID) {
|
|
if (m_handle)
|
|
m_handle->insertText(s, keepAnchor, sfmtID);
|
|
}
|
|
|
|
/*!
|
|
\return A cursor pointing at the position of the selection start.
|
|
|
|
Selection start is the position of the selection that is nearest to
|
|
document start.
|
|
|
|
\note an invalid cursor is returned when the cursor does not have a
|
|
selection
|
|
*/
|
|
QDocumentCursor QDocumentCursor::selectionStart() const {
|
|
return m_handle ? m_handle->selectionStart() : QDocumentCursor();
|
|
}
|
|
|
|
/*!
|
|
\return A cursor pointing at the position of the selection end.
|
|
|
|
Selection end is the position of the selection that is nearest to
|
|
document end.
|
|
|
|
\note an invalid cursor is returned when the cursor does not have a
|
|
selection
|
|
*/
|
|
QDocumentCursor QDocumentCursor::selectionEnd() const {
|
|
return m_handle ? m_handle->selectionEnd() : QDocumentCursor();
|
|
}
|
|
|
|
/*!
|
|
\return The selected text
|
|
*/
|
|
QString QDocumentCursor::selectedText() const {
|
|
return m_handle ? m_handle->selectedText() : QString();
|
|
}
|
|
|
|
/*!
|
|
\brief Remove the selected text
|
|
*/
|
|
void QDocumentCursor::removeSelectedText() {
|
|
if (m_handle)
|
|
m_handle->removeSelectedText();
|
|
}
|
|
|
|
/*!
|
|
\brief Replace the selected text
|
|
|
|
This method differs from insertText() in two ways :
|
|
<ul>
|
|
<li>if \a text is empty the selection WILL be removed
|
|
<li>after the replacement happens this command will
|
|
cause the cursor to select the new text (note that this
|
|
information is NOT preserved by the undo/redo stack
|
|
however).
|
|
</ul>
|
|
*/
|
|
void QDocumentCursor::replaceSelectedText(const QString &text) {
|
|
if (m_handle)
|
|
m_handle->replaceSelectedText(text);
|
|
}
|
|
|
|
/*!
|
|
\brief Begin an edit block
|
|
|
|
Edit blocks are command groups. All the commands in an edit block
|
|
are executed in a row when the edit block is ended with endEditBlock().
|
|
|
|
Edit blocks are considered as a single command as far as the undo/redo
|
|
stack is concerned.
|
|
|
|
Edit blocks can be nested but that isn't of much use
|
|
*/
|
|
void QDocumentCursor::beginEditBlock() {
|
|
if (m_handle)
|
|
m_handle->beginEditBlock();
|
|
}
|
|
|
|
/*!
|
|
\brief End an edit block
|
|
*/
|
|
void QDocumentCursor::endEditBlock() {
|
|
if (m_handle)
|
|
m_handle->endEditBlock();
|
|
}
|
|
|
|
/*!
|
|
\return Whether the cursor is silent
|
|
*/
|
|
bool QDocumentCursor::isSilent() const {
|
|
return m_handle ? m_handle->isSilent() : true;
|
|
}
|
|
|
|
/*!
|
|
\brief Set whether the cursor is silent
|
|
*/
|
|
void QDocumentCursor::setSilent(bool y) {
|
|
if (m_handle)
|
|
m_handle->setSilent(y);
|
|
}
|
|
|
|
/*!
|
|
\return whether the cursor is auto updated
|
|
|
|
An auto updated cursor will remain on the actual line it points
|
|
to when the document is modified.
|
|
|
|
\code
|
|
QDocumentCursor c1(10, 0, document), c2(10, 0, document), c(5, 0,
|
|
document);
|
|
|
|
c1.setAutoUpdated(true);
|
|
|
|
c.insertLine();
|
|
|
|
// at this point c2 still points to line 10 whereas c1 points to line 11
|
|
\endcode
|
|
*/
|
|
bool QDocumentCursor::isAutoUpdated() const {
|
|
return m_handle ? m_handle->isAutoUpdated() : true;
|
|
}
|
|
|
|
/*!
|
|
\brief Set whether the cursor is aut updated
|
|
*/
|
|
void QDocumentCursor::setAutoUpdated(bool y) {
|
|
if (m_handle)
|
|
m_handle->setAutoUpdated(y);
|
|
}
|
|
|
|
/*!
|
|
\brief Refresh the column memory of the cursor
|
|
|
|
This set the current column memory to the current column position.
|
|
|
|
\note It is not recommended to call that yourself. The various
|
|
movement method should do that perfectly fine.
|
|
*/
|
|
void QDocumentCursor::refreshColumnMemory() {
|
|
if (m_handle)
|
|
m_handle->refreshColumnMemory();
|
|
}
|
|
|
|
/*!
|
|
\return Whether the cursor has column memory
|
|
|
|
The column memory is a feature that allow a cursor
|
|
to remember its biggest column number so that moving
|
|
back and forth (with movePosition()) on lines of
|
|
different width does not result in the column to change.
|
|
|
|
*/
|
|
bool QDocumentCursor::hasColumnMemory() const {
|
|
return m_handle ? m_handle->hasColumnMemory() : false;
|
|
}
|
|
|
|
/*!
|
|
\brief Set whether the cursor use column memory
|
|
*/
|
|
void QDocumentCursor::setColumnMemory(bool y) {
|
|
if (m_handle)
|
|
m_handle->setColumnMemory(y);
|
|
}
|
|
|
|
/*!
|
|
\return whether the cursor has a selection
|
|
*/
|
|
bool QDocumentCursor::hasSelection() const {
|
|
return m_handle ? m_handle->hasSelection() : false;
|
|
}
|
|
|
|
/*!
|
|
\brief clear the selection
|
|
*/
|
|
void QDocumentCursor::clearSelection() {
|
|
if (m_handle)
|
|
m_handle->clearSelection();
|
|
}
|
|
|
|
/*!
|
|
\brief Select something
|
|
*/
|
|
void QDocumentCursor::select(SelectionType t) {
|
|
if (m_handle)
|
|
m_handle->select(t);
|
|
}
|
|
|
|
/*!
|
|
\brief Set the selection boundary
|
|
|
|
Select text between the current cursor anchor and the one
|
|
of \a c.
|
|
|
|
\note We mean ANCHOR. If the cursor already has a selection the
|
|
anchor will not change, but the position will be set to that of
|
|
\a c.
|
|
*/
|
|
void QDocumentCursor::setSelectionBoundary(const QDocumentCursor &c) {
|
|
if (m_handle)
|
|
m_handle->setSelectionBoundary(c);
|
|
}
|
|
|
|
/*!
|
|
\return whether a given cursor is within the selection
|
|
*/
|
|
bool QDocumentCursor::isWithinSelection(const QDocumentCursor &c) const {
|
|
return m_handle ? m_handle->isWithinSelection(c) : false;
|
|
}
|
|
|
|
/*!
|
|
\return selection information
|
|
|
|
\note The QDocumentSelection object is not updated if the selection
|
|
changes later on : use it right away and do not store it.
|
|
*/
|
|
QDocumentSelection QDocumentCursor::selection() const {
|
|
QDocumentSelection s;
|
|
|
|
if (isNull() || !hasSelection()) {
|
|
qDebug("NULL selection");
|
|
|
|
s.startLine = -1;
|
|
s.endLine = -1;
|
|
|
|
s.start = -1;
|
|
s.end = -1;
|
|
} else if (m_handle->m_begLine == m_handle->m_endLine) {
|
|
|
|
s.startLine = m_handle->m_begLine;
|
|
s.endLine = m_handle->m_begLine;
|
|
|
|
s.start = qMin(m_handle->m_begOffset, m_handle->m_endOffset);
|
|
s.end = qMax(m_handle->m_begOffset, m_handle->m_endOffset);
|
|
|
|
} else if (m_handle->m_begLine > m_handle->m_endLine) {
|
|
|
|
s.startLine = m_handle->m_endLine;
|
|
s.endLine = m_handle->m_begLine;
|
|
|
|
s.start = m_handle->m_endOffset;
|
|
s.end = m_handle->m_begOffset;
|
|
|
|
// qDebug("[(%i,%i);(%i,%i)]", s.startLine.lineNumber(), s.start,
|
|
// s.endLine.lineNumber(), s.end);
|
|
} else {
|
|
s.startLine = m_handle->m_begLine;
|
|
s.endLine = m_handle->m_endLine;
|
|
|
|
s.start = m_handle->m_begOffset;
|
|
s.end = m_handle->m_endOffset;
|
|
|
|
// qDebug("[(%i,%i);(%i,%i)]", s.startLine.lineNumber(), s.start,
|
|
// s.endLine.lineNumber(), s.end);
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
/*! @} */
|