1 /****************************************************************************
2 **
3 ** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
4 **
5 ** This file is part of the Edyuk project <http://edyuk.org>
6 **
7 ** This file may be used under the terms of the GNU General Public License
8 ** version 3 as published by the Free Software Foundation and appearing in the
9 ** file GPL.txt included in the packaging of this file.
10 **
11 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13 **
14 ****************************************************************************/
15
16 /*!
17 \file qdocumentcursor.cpp
18 \brief Implementation of the QDocumentCursor class
19 */
20
21 #include "qdocumentcursor.h"
22
23 /*!
24 \ingroup document
25 @{
26 */
27
28 #include "qdocument_p.h"
29
30 #include "qdocumentline.h"
31
32 /*!
33 \class QDocumentCursor
34
35 \brief A cursor to navigate within documents and edit them
36
37 QDocumentCursor is a central class of the public API.
38
39 It is the best (as in fastest and easiest) way to iterate over
40 the content of a document.
41
42 It is also the only class that allows to perform editing operations.
43
44 A cursor position is defined by a line number and a text position
45 within the line.
46
47 Every cursor can have one or two cursor positions. In the later
48 case, they delimit a selection. The first position set (before
49 selecting) is referred to as the "anchor" and the other (if it
50 is different from the anchor) is the actual cursor position.
51
52 When the cursor does not have a selection, querying informations about
53 the anchor has the same result as querying informations about the cursor
54 position.
55
56 Informations you can get about both the anchor and the posiotion :
57 <ul>
58 <li>the line number : the logical line to which the cursor position points inside the document
59 <li>the column number : the logical text column to which the cursor position points to, inside the pointed line.
60 <li>the wrapped line offset : when a cursor resides on a wrapped line, this indicates in which part of
61 the wrapped line it does
62 <li>the document position : document (x, y) coordinates corresponding to the place the cursor is drawn
63 </ul>
64
65 The visual line to which a given cursor resides can be obtained as follows :
66
67 \code
68 int visual_line = cursor.document()->visualLine(cursor.lineNumber()) + cursor.wrappedLineOffset();
69 \endcode
70
71 \note The line and column numbers passed to/returned by a cursor method
72 always start at zero.
73
74 \note Quick overview of the various coordinate systems :
75 <ul>
76 <li>document coordinates aka viewport coordinates : (x, y) coords, in pixels, origin at the top left corner of
77 the rectangle occupied by the very first line of the document
78 <li>text coordinates : (line, column) in logical units (number of lines, number of characters)
79 <li>visual text coordinates : (line, column) in logical units but with a different mapping
80 </ul>
81 */
82
QDocumentCursor(QDocument * doc)83 QDocumentCursor::QDocumentCursor(QDocument *doc)
84 : QObject(nullptr),m_handle(new QDocumentCursorHandle(doc))
85 {
86 m_handle->ref();
87 }
88
QDocumentCursor(const QDocumentCursor & from,const QDocumentCursor & to)89 QDocumentCursor::QDocumentCursor(const QDocumentCursor& from, const QDocumentCursor& to): QObject(nullptr){
90 Q_ASSERT(from.document() == to.document());
91 Q_ASSERT(from.handle());
92 Q_ASSERT(to.handle());
93 Q_ASSERT(from.hasSelection() == false);
94 Q_ASSERT(to.hasSelection() == false);
95
96 m_handle = new QDocumentCursorHandle(from.document());
97 m_handle->m_endLine = from.lineNumber();
98 m_handle->m_endOffset = from.columnNumber();
99 m_handle->m_begLine = to.lineNumber();
100 m_handle->m_begOffset = to.columnNumber();
101 }
102
QDocumentCursor(const QDocumentCursor & cursor)103 QDocumentCursor::QDocumentCursor(const QDocumentCursor& cursor)
104 : QObject(nullptr),m_handle(nullptr)
105 {
106 if ( cursor.m_handle )
107 {
108 m_handle = cursor.m_handle->clone(true);
109 m_handle->ref();
110 }
111 }
112
QDocumentCursor(const QDocumentCursor & cursor,const bool cloneAutoUpdateFlag)113 QDocumentCursor::QDocumentCursor(const QDocumentCursor& cursor, const bool cloneAutoUpdateFlag)
114 : QObject(nullptr),m_handle(nullptr)
115 {
116 if ( cursor.m_handle )
117 {
118 m_handle = cursor.m_handle->clone(cloneAutoUpdateFlag);
119 m_handle->ref();
120 }
121 }
122
123
124
QDocumentCursor(QDocument * doc,int line,int column,int lineTo,int columnTo)125 QDocumentCursor::QDocumentCursor(QDocument *doc, int line, int column, int lineTo, int columnTo)
126 : QObject(nullptr),m_handle(new QDocumentCursorHandle(doc, line, column, lineTo, columnTo))
127 {
128 m_handle->ref();
129 }
130
131 /*
132 QDocumentCursor::QDocumentCursor(const QDocumentLine& line, int column)
133 : m_handle(new QDocumentCursorHandle(line.document(), line.lineNumber()))
134 {
135 m_handle->ref();
136
137 m_handle->setColumnNumber(column);
138 //movePosition(qMin(column, line.length()));
139 }
140 */
141
QDocumentCursor(QDocumentCursorHandle * handle)142 QDocumentCursor::QDocumentCursor(QDocumentCursorHandle *handle)
143 : QObject(nullptr),m_handle(handle)
144 {
145 if ( m_handle )
146 m_handle->ref();
147 }
148
~QDocumentCursor()149 QDocumentCursor::~QDocumentCursor()
150 {
151 if ( m_handle )
152 m_handle->deref();
153 }
154
clone(bool cloneAutoUpdatedFlag) const155 QDocumentCursor QDocumentCursor::clone(bool cloneAutoUpdatedFlag) const
156 {
157 return m_handle ? QDocumentCursor(m_handle->clone(cloneAutoUpdatedFlag)) : QDocumentCursor();
158 }
159
operator =(const QDocumentCursor & c)160 QDocumentCursor& QDocumentCursor::operator = (const QDocumentCursor& c)
161 {
162 #if 0
163 if ( m_handle )
164 m_handle->deref();
165
166 m_handle = c.m_handle ? c.m_handle->clone() : 0;
167 //m_handle = c.m_handle;
168
169 if ( m_handle )
170 m_handle->ref();
171 #endif
172
173 if ( c.m_handle )
174 {
175 if ( m_handle )
176 {
177 m_handle->copy(c.m_handle); //warning: this is inconsistent, a copied cursor is never auto updated,
178 } else { //but the clones is. (there was however a reason for this behaviour)
179 m_handle = c.m_handle->clone(true);
180 m_handle->ref();
181 }
182 } else if ( m_handle ) {
183
184 //qWarning("Setting a cursor to null");
185
186 m_handle->deref();
187 m_handle = nullptr;
188 }
189
190 return *this;
191 }
192
193 /*!
194 \brief comparision operator
195
196 \note If any of the operand is an invalid cursor, false is returned
197 */
operator ==(const QDocumentCursor & c) const198 bool QDocumentCursor::operator == (const QDocumentCursor& c) const
199 {
200 if ( !m_handle || !c.m_handle )
201 return false;
202
203 return m_handle->eq(c.m_handle);
204 }
205
206 /*!
207 \brief comparision operator
208
209 \note If any of the operand is an invalid cursor, true is returned (to preserve logical consistency with == )
210 */
operator !=(const QDocumentCursor & c) const211 bool QDocumentCursor::operator != (const QDocumentCursor& c) const
212 {
213 if ( !m_handle || !c.m_handle )
214 return true;
215
216 return !m_handle->eq(c.m_handle);
217 }
218
219 /*!
220 \brief comparision operator
221
222 \note If any of the operand is an invalid cursor, false is returned
223 */
operator <(const QDocumentCursor & c) const224 bool QDocumentCursor::operator < (const QDocumentCursor& c) const
225 {
226 if ( !m_handle || !c.m_handle )
227 return false;
228
229 return m_handle->lt(c.m_handle);
230 }
231
232 /*!
233 \brief comparision operator
234
235 \note If any of the operand is an invalid cursor, false is returned
236 */
operator >(const QDocumentCursor & c) const237 bool QDocumentCursor::operator > (const QDocumentCursor& c) const
238 {
239 if ( !m_handle || !c.m_handle )
240 return false;
241
242 return m_handle->gt(c.m_handle);
243 }
244
245 /*!
246 \brief comparision operator
247
248 \note If any of the operand is an invalid cursor, false is returned
249 */
operator <=(const QDocumentCursor & c) const250 bool QDocumentCursor::operator <= (const QDocumentCursor& c) const
251 {
252 if ( !m_handle || !c.m_handle )
253 return false;
254
255 return m_handle->lt(c.m_handle) || m_handle->eq(c.m_handle);
256 }
257
258 /*!
259 \brief comparision operator
260
261 \note If any of the operand is an invalid cursor, false is returned
262 */
operator >=(const QDocumentCursor & c) const263 bool QDocumentCursor::operator >= (const QDocumentCursor& c) const
264 {
265 if ( !m_handle || !c.m_handle )
266 return false;
267
268 return m_handle->gt(c.m_handle) || m_handle->eq(c.m_handle);
269 }
270
271 /*!
272 \brief comparision operator
273 */
isNull() const274 bool QDocumentCursor::isNull() const
275 {
276 return !m_handle || !m_handle->document() || !line().isValid();
277 }
278
beginBoundaryLarger(const QDocumentCursor & c) const279 bool QDocumentCursor::beginBoundaryLarger (const QDocumentCursor& c) const{
280 if (!m_handle || !c.m_handle) return false;
281 int line1, col1;
282 m_handle->beginBoundary(line1,col1);
283 int line2, col2;
284 c.m_handle->beginBoundary(line2,col2);
285 if (line1==line2)
286 return col1>col2;
287 else
288 return line1>line2;
289 }
290
equalBoundaries(const QDocumentCursor & c) const291 bool QDocumentCursor::equalBoundaries(const QDocumentCursor& c) const{
292 if (!m_handle) return false;
293 if (m_handle == c.m_handle) return true;
294 return m_handle->equalBoundaries(c.m_handle);
295 }
296
equal(const QDocumentCursor & c) const297 bool QDocumentCursor::equal(const QDocumentCursor& c) const{
298 if (!m_handle) return false;
299 if (m_handle == c.m_handle) return true;
300 return m_handle->equal(c.m_handle);
301 }
302
303
304 /*!
305 Returns if my right boundary is larger (line/offset) than c
306 */
endBoundaryLarger(const QDocumentCursor & c) const307 bool QDocumentCursor::endBoundaryLarger (const QDocumentCursor& c) const{
308 if (!m_handle || !c.m_handle) return false;
309 int line1, col1;
310 m_handle->endBoundary(line1,col1);
311 int line2, col2;
312 c.m_handle->endBoundary(line2,col2);
313 if (line1==line2)
314 return col1>col2;
315 else
316 return line1>line2;
317 }
318
beginBoundary(int & begline,int & begcol) const319 void QDocumentCursor::beginBoundary(int& begline, int& begcol) const{
320 if (!m_handle) {
321 begline=-1;
322 begcol=-1;
323 return;
324 }
325 m_handle->beginBoundary(begline, begcol);
326 }
endBoundary(int & endline,int & endcol) const327 void QDocumentCursor::endBoundary(int& endline, int& endcol) const{
328 if (!m_handle) {
329 endline=-1;
330 endcol=-1;
331 return;
332 }
333 m_handle->endBoundary(endline, endcol);
334 }
boundaries(int & begline,int & begcol,int & endline,int & endcol) const335 void QDocumentCursor::boundaries(int& begline, int& begcol, int& endline, int& endcol) const{
336 if (!m_handle) {
337 begline=begcol=endline=endcol=-1;
338 return;
339 }
340 m_handle->boundaries(begline,begcol,endline,endcol);
341 }
342
343
344 /*!
345 \brief comparision operator
346 */
isValid() const347 bool QDocumentCursor::isValid() const
348 {
349 return m_handle && m_handle->document() && line().isValid();
350 }
351
352 /*!
353 \return whether the cursor is at the end of the document
354 */
atEnd() const355 bool QDocumentCursor::atEnd() const
356 {
357 return m_handle ? m_handle->atEnd() : false;
358 }
359
360 /*!
361 \return whether the cursor is at the begining of the document
362 */
atStart() const363 bool QDocumentCursor::atStart() const
364 {
365 return m_handle ? m_handle->atStart() : false;
366 }
367
368 /*!
369 \return whether the cursor is at the end of a block
370 */
atBlockEnd() const371 bool QDocumentCursor::atBlockEnd() const
372 {
373 return m_handle ? m_handle->atBlockEnd() : false;
374 }
375
376 /*!
377 \return whether the cursor is at the start of a block
378 */
atBlockStart() const379 bool QDocumentCursor::atBlockStart() const
380 {
381 return m_handle ? m_handle->atBlockStart() : false;
382 }
383
384 /*!
385 \return whether the cursor is at the end of a line
386
387 \note this may only differ from atBlockEnd() on wrapped lines
388 */
atLineEnd() const389 bool QDocumentCursor::atLineEnd() const
390 {
391 return m_handle ? m_handle->atLineEnd() : false;
392 }
393
394 /*!
395 \return whether the cursor is at the start of a line
396
397 \note this may only differ from atBlockStart() on wrapped lines
398 */
atLineStart() const399 bool QDocumentCursor::atLineStart() const
400 {
401 return m_handle ? m_handle->atLineStart() : false;
402 }
403
404 /*!
405 \return the document on which this cursor operates
406 */
document() const407 QDocument* QDocumentCursor::document() const
408 {
409 return m_handle ? m_handle->document() : nullptr;
410 }
411
412 /*!
413 \return the text column of the anchor
414 */
anchorColumnNumber() const415 int QDocumentCursor::anchorColumnNumber() const
416 {
417 return m_handle ? m_handle->anchorColumnNumber() : -1;
418 }
419
startLineNumber() const420 int QDocumentCursor::startLineNumber() const{
421 return m_handle ? m_handle->startLineNumber() : -1;
422 }
startColumnNumber() const423 int QDocumentCursor::startColumnNumber() const{
424 return m_handle ? m_handle->startColumnNumber() : -1;
425 }
426
endLineNumber() const427 int QDocumentCursor::endLineNumber() const{
428 return m_handle ? m_handle->endLineNumber() : -1;
429 }
endColumnNumber() const430 int QDocumentCursor::endColumnNumber() const{
431 return m_handle ? m_handle->endColumnNumber() : -1;
432 }
433
434
435 /*!
436 \return the "visual" text column of the cursor
437
438 \note this may only differ from columnNumber() when there are tabs on the line
439 */
visualColumnNumber() const440 int QDocumentCursor::visualColumnNumber() const
441 {
442 return m_handle ? m_handle->visualColumnNumber() : -1;
443 }
444
445 /*!
446 \return the text column of the cursor
447 */
columnNumber() const448 int QDocumentCursor::columnNumber() const
449 {
450 return m_handle ? m_handle->columnNumber() : -1;
451 }
452
453
setLineNumber(int l,MoveMode m)454 void QDocumentCursor::setLineNumber(int l, MoveMode m)
455 {
456 if ( m_handle )
457 m_handle->setLineNumber(l, m);
458 }
459
460 /*!
461 \brief Set the text column of the cursor
462 \param c text column to set
463 \param m move mode (determines whether text will be selected)
464 */
setColumnNumber(int c,MoveMode m)465 void QDocumentCursor::setColumnNumber(int c, MoveMode m)
466 {
467 if ( m_handle )
468 m_handle->setColumnNumber(c, m);
469 }
470
setAnchorLineNumber(int c) const471 void QDocumentCursor::setAnchorLineNumber(int c) const{
472 if ( m_handle )
473 m_handle->setAnchorLineNumber(c);
474 }
475
setAnchorColumnNumber(int c) const476 void QDocumentCursor::setAnchorColumnNumber(int c) const{
477 if ( m_handle )
478 m_handle->setAnchorColumnNumber(c);
479 }
480
481
482 /*!
483 \return The line number to which the cursor points
484 */
lineNumber() const485 int QDocumentCursor::lineNumber() const
486 {
487 return m_handle ? m_handle->lineNumber() : -1;
488 }
489
490 /*!
491 \return The line number to which the cursor points
492 */
anchorLineNumber() const493 int QDocumentCursor::anchorLineNumber() const
494 {
495 return m_handle ? m_handle->anchorLineNumber() : -1;
496 }
497
498 /*!
499 \return The wrapped line on which the cursor resides
500
501 Wrapped line are "sublines" of logical lines.
502 */
wrappedLineOffset() const503 int QDocumentCursor::wrappedLineOffset() const
504 {
505 return line().wrappedLineForCursor(columnNumber());
506 }
507
508 /*!
509 \return The line number on which the anchor resides
510 */
anchorWrappedLineOffset() const511 int QDocumentCursor::anchorWrappedLineOffset() const
512 {
513 return anchorLine().wrappedLineForCursor(anchorColumnNumber());
514 }
515
516 /*!
517 \return the document position at which the cursor is
518
519 Document position and viewport position are two terms used interchangeably.
520 The only difference is the former refers to model perception (QDocument)
521 whereas the later refers to view perception (QEditor)
522 */
documentPosition() const523 QPointF QDocumentCursor::documentPosition() const
524 {
525 return m_handle ? m_handle->documentPosition() : QPointF();
526 }
527
528 /*!
529 \return the document position of the anchor
530 */
anchorDocumentPosition() const531 QPointF QDocumentCursor::anchorDocumentPosition() const
532 {
533 return m_handle ? m_handle->anchorDocumentPosition() : QPointF();
534 }
535
documentRegion() const536 QPolygonF QDocumentCursor::documentRegion() const
537 {
538 return m_handle ? m_handle->documentRegion() : QPolygonF();
539 }
540
541 /*!
542 \return The line object on which the cursor resides
543 */
line() const544 QDocumentLine QDocumentCursor::line() const
545 {
546 return m_handle ? m_handle->line() : QDocumentLine();
547 }
548
549 /*!
550 \return The line object on which the anchor resides
551 */
anchorLine() const552 QDocumentLine QDocumentCursor::anchorLine() const
553 {
554 return m_handle ? m_handle->anchorLine() : QDocumentLine();
555 }
556
557 /*!
558 \brief Shift cursor position (text column) by a number of columns (characters)
559 */
shift(int offset)560 void QDocumentCursor::shift(int offset)
561 {
562 if ( m_handle )
563 m_handle->shift(offset);
564 }
565
566 /*!
567 \brief Set the text position of the cursor (within the whole document)
568
569 Remark made about position() applies.
570 */
setPosition(int pos,MoveMode m)571 void QDocumentCursor::setPosition(int pos, MoveMode m)
572 {
573 if ( m_handle )
574 m_handle->setPosition(pos, m);
575 }
576
577 /*!
578 \brief Moves the cursor position
579 \param offset number of times the selected move will be done
580 \param op movement type
581 \param m movement mode (whether to select)
582 \return true on succes
583 */
movePosition(int offset,MoveOperation op,MoveMode m)584 bool QDocumentCursor::movePosition(int offset, MoveOperation op, MoveMode m)
585 {
586 return m_handle ? m_handle->movePosition(offset, op, m) : false;
587 }
588
589 /*!
590 \brief Jump to another cursor position
591 \param line target line number
592 \param colum target text column
593 */
moveTo(int line,int column,MoveMode m)594 void QDocumentCursor::moveTo(int line, int column, MoveMode m)
595 {
596 if ( m_handle )
597 m_handle->moveTo(line, column,m);
598 }
599
600
601 /*!
602 \brief Jump to the position of another cursor
603 \param c target cursor
604 */
moveTo(const QDocumentCursor & c,MoveMode m)605 void QDocumentCursor::moveTo(const QDocumentCursor &c, MoveMode m)
606 {
607 if ( m_handle )
608 m_handle->moveTo(c,m);
609 }
610
611 /*!
612 \brief Jump to another cursor position
613 \param l target line
614 \param column target text column
615
616 \note Calls QDocumentLine::lineNumber() => SLOW : avoid whenever possible
617 */
618 /*void QDocumentCursor::moveTo(const QDocumentLine &l, int column, MoveMode m)
619 {
620 if ( m_handle )
621 m_handle->moveTo(l.lineNumber(), column, m);
622 }*/
623
624 /*!
625 \return the character at the position immediately after the cursor
626 */
nextChar() const627 QChar QDocumentCursor::nextChar() const
628 {
629 return m_handle ? m_handle->nextChar() : QChar();
630 }
631
632 /*!
633 \return the character at the position immediately before the cursor
634 */
previousChar() const635 QChar QDocumentCursor::previousChar() const
636 {
637 return m_handle ? m_handle->previousChar() : QChar();
638 }
639
640 /*!
641 \brief Delete the character at the position immediately after the cursor
642 */
deleteChar()643 void QDocumentCursor::deleteChar()
644 {
645 if ( m_handle )
646 m_handle->deleteChar();
647 }
648
649 /*!
650 \brief Delete the character at the position immediately before the cursor
651 */
deletePreviousChar()652 void QDocumentCursor::deletePreviousChar()
653 {
654 if ( m_handle )
655 m_handle->deletePreviousChar();
656 }
657
658 /*!
659 \brief erase the whole line the cursor is on, newline included
660 */
eraseLine()661 void QDocumentCursor::eraseLine()
662 {
663 if ( m_handle )
664 m_handle->eraseLine();
665 }
666
667 /*!
668 \brief insert a new line at the cursor position
669 */
insertLine(bool keepAnchor)670 void QDocumentCursor::insertLine(bool keepAnchor)
671 {
672 if ( m_handle )
673 m_handle->insertText("\n", keepAnchor);
674 }
675
676 /*!
677 \brief insert some text at the cursor position
678
679 Selected text will be removed before insertion happens.
680
681 \note Nothing happens if \a s is empty
682 */
insertText(const QString & s,bool keepAnchor)683 void QDocumentCursor::insertText(const QString& s, bool keepAnchor)
684 {
685 if ( m_handle )
686 m_handle->insertText(s, keepAnchor);
687 }
688
689 /*!
690 \return A cursor pointing at the position of the selection start.
691
692 Selection start is the position of the selection that is nearest to document start.
693
694 \note an invalid cursor is returned when the cursor does not have a selection
695 */
selectionStart() const696 QDocumentCursor QDocumentCursor::selectionStart() const
697 {
698 return m_handle ? m_handle->selectionStart() : QDocumentCursor();
699 }
700
701 /*!
702 \return A cursor pointing at the position of the selection end.
703
704 Selection end is the position of the selection that is nearest to document end.
705
706 \note an invalid cursor is returned when the cursor does not have a selection
707 */
selectionEnd() const708 QDocumentCursor QDocumentCursor::selectionEnd() const
709 {
710 return m_handle ? m_handle->selectionEnd() : QDocumentCursor();
711 }
712
713 /*!
714 \return A cursor pointing at the position of the anchor.
715 */
anchorCursor() const716 QDocumentCursor QDocumentCursor::anchorCursor() const
717 {
718 return m_handle ? m_handle->anchorCursor() : QDocumentCursor();
719 }
720
721 /*!
722 \return The selected text
723 */
selectedText() const724 QString QDocumentCursor::selectedText() const
725 {
726 return m_handle ? m_handle->selectedText() : QString();
727 }
728
729
730 /*!
731 \brief Remove the selected text
732 */
removeSelectedText()733 void QDocumentCursor::removeSelectedText()
734 {
735 if ( m_handle )
736 m_handle->removeSelectedText();
737 }
738
739 /*!
740 \brief Replace the selected text
741
742 This method differs from insertText() in two ways :
743 <ul>
744 <li>if \a text is empty the selection WILL be removed
745 <li>after the replacement happens this command will
746 cause the cursor to select the new text (note that this
747 information is NOT preserved by the undo/redo stack
748 however).
749 </ul>
750 */
replaceSelectedText(const QString & text)751 void QDocumentCursor::replaceSelectedText(const QString& text)
752 {
753 if ( m_handle )
754 m_handle->replaceSelectedText(text);
755 }
756
757 /*!
758 \brief Begin an edit block
759
760 Edit blocks are command groups. All the commands in an edit block
761 are executed in a row when the edit block is ended with endEditBlock().
762
763 Edit blocks are considered as a single command as far as the undo/redo
764 stack is concerned.
765
766 Edit blocks can be nested but that isn't of much use
767 */
beginEditBlock()768 void QDocumentCursor::beginEditBlock()
769 {
770 if ( m_handle )
771 m_handle->beginEditBlock();
772 }
773
774 /*!
775 \brief End an edit block
776 */
endEditBlock()777 void QDocumentCursor::endEditBlock()
778 {
779 if ( m_handle )
780 m_handle->endEditBlock();
781 }
782
783 /*!
784 \return Whether the cursor is silent
785 */
isSilent() const786 bool QDocumentCursor::isSilent() const
787 {
788 return m_handle ? m_handle->isSilent() : true;
789 }
790
791 /*!
792 \brief Set whether the cursor is silent
793 */
setSilent(bool y)794 void QDocumentCursor::setSilent(bool y)
795 {
796 if ( m_handle )
797 m_handle->setSilent(y);
798
799 }
800
801 /*!
802 \return whether the cursor is auto updated
803
804 An auto updated cursor will remain on the actual line it points
805 to when the document is modified.
806
807 \code
808 QDocumentCursor c1(10, 0, document), c2(10, 0, document), c(5, 0, document);
809
810 c1.setAutoUpdated(true);
811
812 c.insertLine();
813
814 // at this point c2 still points to line 10 whereas c1 points to line 11
815 \endcode
816 */
isAutoUpdated() const817 bool QDocumentCursor::isAutoUpdated() const
818 {
819 return m_handle ? m_handle->isAutoUpdated() : true;
820 }
821
822 /*!
823 \brief Set whether the cursor is aut updated
824 */
setAutoUpdated(bool y)825 void QDocumentCursor::setAutoUpdated(bool y)
826 {
827 if ( m_handle )
828 m_handle->setAutoUpdated(y);
829 }
830
isAutoErasable() const831 bool QDocumentCursor::isAutoErasable() const{
832 return m_handle ? m_handle->isAutoErasable() : true;
833 }
setAutoErasable(bool y)834 void QDocumentCursor::setAutoErasable(bool y){
835 if ( m_handle )
836 m_handle->setAutoErasable(y);
837 }
838
839
840 /*!
841 \brief Refresh the column memory of the cursor
842
843 This set the current column memory to the current column position.
844
845 \note It is not recommended to call that yourself. The various
846 movement method should do that perfectly fine.
847 */
refreshColumnMemory()848 void QDocumentCursor::refreshColumnMemory()
849 {
850 if ( m_handle )
851 m_handle->refreshColumnMemory();
852
853 }
854
855 /*!
856 \return Whether the cursor has column memory
857
858 The column memory is a feature that allow a cursor
859 to remember its biggest column number so that moving
860 back and forth (with movePosition()) on lines of
861 different width does not result in the column to change.
862
863 */
hasColumnMemory() const864 bool QDocumentCursor::hasColumnMemory() const
865 {
866 return m_handle ? m_handle->hasColumnMemory() : false;
867 }
868
869 /*!
870 \brief Set whether the cursor use column memory
871 */
setColumnMemory(bool y)872 void QDocumentCursor::setColumnMemory(bool y)
873 {
874 if ( m_handle )
875 m_handle->setColumnMemory(y);
876
877 }
878
879 /*!
880 \return whether the cursor has a selection
881 */
hasSelection() const882 bool QDocumentCursor::hasSelection() const
883 {
884 return m_handle ? m_handle->hasSelection() : false;
885 }
886
887 /*!
888 * \return true if there is an selection and the anchor is before the cursor
889 */
isForwardSelection() const890 bool QDocumentCursor::isForwardSelection() const
891 {
892 return m_handle ? m_handle->isForwardSelection() : false;
893 }
894
895 /*!
896 \brief clear the selection
897 */
clearSelection()898 void QDocumentCursor::clearSelection()
899 {
900 if ( m_handle )
901 m_handle->clearSelection();
902
903 }
904
905 /*!
906 * \brief exchanges cursor and anchor positions
907 */
flipSelection()908 void QDocumentCursor::flipSelection() {
909 if ( m_handle )
910 m_handle->flipSelection();
911 }
912
913 /*!
914 \brief Select something
915 */
select(SelectionType t)916 void QDocumentCursor::select(SelectionType t)
917 {
918 if ( m_handle )
919 m_handle->select(t);
920
921 }
922
923 /*!
924 \brief Expand a current selection
925 */
expandSelect(QDocumentCursor::SelectionType t)926 void QDocumentCursor::expandSelect(QDocumentCursor::SelectionType t)
927 {
928 if ( m_handle )
929 m_handle->expandSelect(t);
930 }
931
932 /*!
933 \brief Set the selection boundary
934
935 Select text between the current cursor anchor and the one
936 of \a c.
937
938 \note We mean ANCHOR. If the cursor already has a selection the
939 anchor will not change, but the position will be set to that of
940 \a c.
941 */
setSelectionBoundary(const QDocumentCursor & c)942 void QDocumentCursor::setSelectionBoundary(const QDocumentCursor& c)
943 {
944 if ( m_handle )
945 m_handle->setSelectionBoundary(c);
946 }
947
select(int line,int column,int lineTo,int columnTo)948 void QDocumentCursor::select(int line, int column, int lineTo, int columnTo){
949 if ( m_handle )
950 m_handle->select(line, column, lineTo, columnTo);
951 }
952
selectColumns(int column,int columnTo)953 void QDocumentCursor::selectColumns(int column, int columnTo){
954 if ( m_handle )
955 m_handle->select(lineNumber(), column, lineNumber(), columnTo);
956 }
957
958 /*!
959 \return whether the given cursor c is within the selection of this (ignores selection of c)
960 */
isWithinSelection(const QDocumentCursor & c) const961 bool QDocumentCursor::isWithinSelection(const QDocumentCursor& c) const
962 {
963 return m_handle ? m_handle->isWithinSelection(c) : false;
964 }
965
966 /*!
967 Creates a new cursor whose selection is the largest region which is contained in the selection of both
968 (returns c if c has no selection but is within the selection of c and returns an invalid cursor if
969 this has no selection)
970 */
intersect(const QDocumentCursor & c) const971 QDocumentCursor QDocumentCursor::intersect(const QDocumentCursor& c) const{
972 return m_handle ? m_handle->intersect(c) : QDocumentCursor();
973 }
974
975 /*!
976 Sets the selection given by lbeg/cbeg/lend/cend to the largest selection which is contained in
977 the selection of this cursor and the passed boundaries
978 (it sets all to -1 if such a selection doesn't exists)
979 */
intersectBoundaries(int & lbeg,int & cbeg,int & lend,int & cend) const980 void QDocumentCursor::intersectBoundaries(int& lbeg, int& cbeg, int& lend, int& cend) const{
981 if (m_handle)
982 m_handle->intersectBoundaries(lbeg, cbeg, lend, cend);
983 }
984
985
986
getMatchingPair(QDocumentCursor & from,QDocumentCursor & to,bool maximal) const987 void QDocumentCursor::getMatchingPair(QDocumentCursor& from, QDocumentCursor& to, bool maximal) const{
988 if (m_handle)
989 m_handle->getMatchingPair(from, to, maximal);
990 else
991 from = to = QDocumentCursor();
992
993 }
994
995 /*!
996 \return selection information
997
998 \note The QDocumentSelection object is not updated if the selection
999 changes later on : use it right away and do not store it.
1000 */
selection() const1001 QDocumentSelection QDocumentCursor::selection() const
1002 {
1003 QDocumentSelection s;
1004
1005 if ( isNull() || !hasSelection() )
1006 {
1007 qDebug("NULL selection");
1008
1009 s.startLine = -1;
1010 s.endLine = -1;
1011
1012 s.start = -1;
1013 s.end = -1;
1014 } else if ( m_handle->m_begLine == m_handle->m_endLine ) {
1015
1016 s.startLine = m_handle->m_begLine;
1017 s.endLine = m_handle->m_begLine;
1018
1019 s.start = qMin(m_handle->m_begOffset, m_handle->m_endOffset);
1020 s.end = qMax(m_handle->m_begOffset, m_handle->m_endOffset);
1021
1022 } else if ( m_handle->m_begLine > m_handle->m_endLine ) {
1023
1024 s.startLine = m_handle->m_endLine;
1025 s.endLine = m_handle->m_begLine;
1026
1027 s.start = m_handle->m_endOffset;
1028 s.end = m_handle->m_begOffset;
1029
1030 //qDebug("[(%i,%i);(%i,%i)]", s.startLine.lineNumber(), s.start, s.endLine.lineNumber(), s.end);
1031 } else {
1032 s.startLine = m_handle->m_begLine;
1033 s.endLine = m_handle->m_endLine;
1034
1035 s.start = m_handle->m_begOffset;
1036 s.end = m_handle->m_endOffset;
1037
1038 //qDebug("[(%i,%i);(%i,%i)]", s.startLine.lineNumber(), s.start, s.endLine.lineNumber(), s.end);
1039 }
1040
1041 return s;
1042 }
1043
isRTL() const1044 bool QDocumentCursor::isRTL() const{
1045 return m_handle && m_handle->isRTL();
1046 }
1047
sort(QDocumentCursor & from,QDocumentCursor & to)1048 void QDocumentCursor::sort(QDocumentCursor& from, QDocumentCursor& to){
1049 if (from < to) return;
1050 QDocumentCursorHandle* temp = to.m_handle;
1051 to.m_handle = from.m_handle;
1052 from.m_handle = temp;
1053 }
1054
1055 /*! @} */
1056
1057