summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-write/qtextedit.cpp
Unidiff
Diffstat (limited to 'noncore/apps/opie-write/qtextedit.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-write/qtextedit.cpp1495
1 files changed, 787 insertions, 708 deletions
diff --git a/noncore/apps/opie-write/qtextedit.cpp b/noncore/apps/opie-write/qtextedit.cpp
index 9c5ea79..82401c6 100644
--- a/noncore/apps/opie-write/qtextedit.cpp
+++ b/noncore/apps/opie-write/qtextedit.cpp
@@ -66,6 +66,8 @@
66 66
67using namespace Qt3; 67using namespace Qt3;
68 68
69static bool qt_enable_richtext_copy = FALSE;
70
69struct QUndoRedoInfoPrivate 71struct QUndoRedoInfoPrivate
70{ 72{
71 QTextString text; 73 QTextString text;
@@ -77,11 +79,16 @@ class QTextEditPrivate
77{ 79{
78public: 80public:
79 QTextEditPrivate() 81 QTextEditPrivate()
80 :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) {} 82 :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE)
83 {
84 for ( int i=0; i<7; i++ )
85 id[i] = 0;
86 }
81 int id[ 7 ]; 87 int id[ 7 ];
82 int preeditStart; 88 int preeditStart;
83 int preeditLength; 89 int preeditLength;
84 bool ensureCursorVisibleInShowEvent; 90 bool ensureCursorVisibleInShowEvent;
91 QString scrollToAnchor; // used to deferr scrollToAnchor() until the show event when we are resized
85}; 92};
86 93
87} 94}
@@ -90,31 +97,88 @@ static bool block_set_alignment = FALSE;
90 97
91/*! 98/*!
92 \class QTextEdit qtextedit.h 99 \class QTextEdit qtextedit.h
93 \brief The QTextEdit widget provides a sophisticated single-page rich text editor. 100 \brief The QTextEdit widget provides a powerful single-page rich text editor.
94 101
95 \ingroup basic 102 \ingroup basic
96 \ingroup text 103 \ingroup text
97 \mainclass 104 \mainclass
98 105
99 QTextEdit is an advanced WYSIWYG editor supporting rich text 106 \tableofcontents
100 formatting. It is optimized to handle large documents and to 107
101 respond quickly to user input. 108 \section1 Introduction and Concepts
109
110 QTextEdit is an advanced WYSIWYG viewer/editor supporting rich
111 text formatting using HTML-style tags. It is optimized to handle
112 large documents and to respond quickly to user input.
113
114 QTextEdit has three modes of operation:
115 \table
116 \header \i Mode \i Command \i Notes
117 \row \i Plain Text Editor \i setTextFormat(PlainText)
118 \i Set text with setText(); text() returns plain text. Text
119 attributes (e.g. colors) can be set, but plain text is always
120 returned.<sup>1.</sup>
121 \row \i Rich Text Editor \i setTextFormat(RichText)
122 \i Set text with setText(); text() returns rich text. Rich
123 text editing is fairly limited. You can't set margins or
124 insert images for example (although you can read and
125 correctly display files that have margins set and that
126 include images). This mode is mostly useful for editing small
127 amounts of rich text. <sup>2.</sup>
128 \row \i Text Viewer<sup>3.</sup> \i setReadOnly(TRUE)
129 \i Set text with setText() or append() (which has no undo
130 history so is faster and uses less memory); text() returns
131 plain or rich text depending on the textFormat(). This mode
132 can correctly display a large subset of HTML tags.
133 \endtable
134
135 <sup>1.</sup><small>We do \e not recommend using QTextEdit to
136 create syntax highlighting editors because the current API is
137 insufficient for this purpose. We hope to release a more complete
138 API that will support syntax highlighting in a later
139 release.</small>
140
141 <sup>2.</sup><small>A more complete API that supports setting
142 margins, images, etc., is planned for a later Qt release.</small>
143
144 <sup>3.</sup><small>Qt 3.1 will provide a Log Viewer mode which is
145 optimised for the fast and memory efficient display of large
146 amounts of read only text.</small>
147
148 We recommend that you always call setTextFormat() to set the mode
149 you want to use. If you use \c AutoText then setText() and
150 append() will try to determine whether the text they are given is
151 plain text or rich text. If you use \c RichText then setText() and
152 append() will assume that the text they are given is rich text.
153 insert() simply inserts the text it is given.
102 154
103 QTextEdit works on paragraphs and characters. A paragraph is a 155 QTextEdit works on paragraphs and characters. A paragraph is a
104 formatted string which is word-wrapped to fit into the width of 156 formatted string which is word-wrapped to fit into the width of
105 the widget. A document consists of zero or more paragraphs, 157 the widget. By default when reading plain text, two newlines
106 indexed from 0. Characters are indexed on a per-paragraph basis, 158 signify a paragraph. A document consists of zero or more
107 also indexed from 0. The words in the paragraph are aligned in 159 paragraphs, indexed from 0. Characters are indexed on a
108 accordance with the paragraph's alignment(). Paragraphs are 160 per-paragraph basis, also indexed from 0. The words in the
109 separated by hard line breaks. Each character within a paragraph 161 paragraph are aligned in accordance with the paragraph's
110 has its own attributes, for example, font and color. 162 alignment(). Paragraphs are separated by hard line breaks. Each
163 character within a paragraph has its own attributes, for example,
164 font and color.
165
166 The text edit documentation uses the following concepts:
167 \list
168 \i \e{current format} --
169 this is the format at the current cursor position, \e and it
170 is the format of the selected text if any.
171 \i \e{current paragraph} -- the paragraph which contains the
172 cursor.
173 \endlist
111 174
112 QTextEdit can display images (using QMimeSourceFactory), lists and 175 QTextEdit can display images (using QMimeSourceFactory), lists and
113 tables. If the text is too large to view within the text edit's 176 tables. If the text is too large to view within the text edit's
114 viewport, scrollbars will appear. The text edit can load both 177 viewport, scrollbars will appear. The text edit can load both
115 plain text and HTML files (a subset of HTML 3.2 and 4). The 178 plain text and HTML files (a subset of HTML 3.2 and 4). The
116 rendering style and the set of valid tags are defined by a 179 rendering style and the set of valid tags are defined by a
117 styleSheet(). Change the style sheet with \l{setStyleSheet()}; see 180 styleSheet(). Custom tags can be created and placed in a custom
181 style sheet. Change the style sheet with \l{setStyleSheet()}; see
118 QStyleSheet for details. The images identified by image tags are 182 QStyleSheet for details. The images identified by image tags are
119 displayed if they can be interpreted using the text edit's 183 displayed if they can be interpreted using the text edit's
120 \l{QMimeSourceFactory}; see setMimeSourceFactory(). 184 \l{QMimeSourceFactory}; see setMimeSourceFactory().
@@ -134,64 +198,29 @@ static bool block_set_alignment = FALSE;
134 you should call setTextFormat(Qt::PlainText) to preserve such 198 you should call setTextFormat(Qt::PlainText) to preserve such
135 text. 199 text.
136 200
137 The text edit documentation uses the following concepts: 201 Note that we do not intend to add a full-featured web browser
138 \list 202 widget to Qt (because that would easily double Qt's size and only
139 \i <i>current format</i> -- 203 a few applications would benefit from it). The rich
140 this is the format at the current cursor position, \e and it 204 text support in Qt is designed to provide a fast, portable and
141 is the format of the selected text if any. 205 efficient way to add reasonable online help facilities to
142 \i <i>current paragraph</i> -- the paragraph which contains the 206 applications, and to provide a basis for rich text editors.
143 cursor. 207 \section1 Using QTextEdit as a Display Widget
144 \endlist 208
209 QTextEdit can display a large HTML subset, including tables and
210 images.
145 211
146 The text is set or replaced using setText() which deletes any 212 The text is set or replaced using setText() which deletes any
147 existing text and replaces it with the text passed in the 213 existing text and replaces it with the text passed in the
148 setText() call. Text can be inserted with insert(), paste() and 214 setText() call. If you call setText() with legacy HTML (with
149 pasteSubType(). Text can also be cut(). The entire text is deleted 215 setTextFormat(RichText) in force), and then call text(), the text
150 with clear() and the selected text is deleted with 216 that is returned may have different markup, but will render the
151 removeSelectedText(). Selected (marked) text can also be deleted 217 same. Text can be inserted with insert(), paste(), pasteSubType()
152 with del() (which will delete the character to the right of the 218 and append(). Text that is appended does not go into the undo
153 cursor if no text is selected). 219 history; this makes append() faster and consumes less memory. Text
154 220 can also be cut(). The entire text is deleted with clear() and the
155 The current format's attributes are set with setItalic(), 221 selected text is deleted with removeSelectedText(). Selected
156 setBold(), setUnderline(), setFamily() (font family), 222 (marked) text can also be deleted with del() (which will delete
157 setPointSize(), setColor() and setCurrentFont(). The current 223 the character to the right of the cursor if no text is selected).
158 paragraph's style is set with setParagType() and its alignment is
159 set with setAlignment().
160
161 Use setSelection() to select text. The setSelectionAttributes()
162 function is used to indicate how selected text should be
163 displayed. Use hasSelectedText() to find out if any text is
164 selected. The currently selected text's position is available
165 using getSelection() and the selected text itself is returned by
166 selectedText(). The selection can be copied to the clipboard with
167 copy(), or cut to the clipboard with cut(). It can be deleted with
168 removeSelectedText(). The entire text can be selected (or
169 unselected) using selectAll(). QTextEdit supports multiple
170 selections. Most of the selection functions operate on the default
171 selection, selection 0. If the user presses a non-selecting key,
172 e.g. a cursor key without also holding down Shift, all selections
173 are cleared.
174
175 Set and get the position of the cursor with setCursorPosition()
176 and getCursorPosition() respectively. When the cursor is moved,
177 the signals currentFontChanged(), currentColorChanged() and
178 currentAlignmentChanged() are emitted to reflect the font, color
179 and alignment at the new cursor position.
180
181 If the text changes, the textChanged() signal is emitted, and if
182 the user inserts a new line by pressing Return or Enter,
183 returnPressed() is emitted. The isModified() function will return
184 TRUE if the text has been modified.
185
186 QTextEdit provides command-based undo and redo. To set the depth
187 of the command history use setUndoDepth() which defaults to 100
188 steps. To undo or redo the last operation call undo() or redo().
189 The signals undoAvailable() and redoAvailable() indicate whether
190 the undo and redo operations can be executed.
191
192 The indent() function is used to reindent a paragraph. It is
193 useful for code editors, for example in <em>Qt Designer</em>'s
194 code editor \e{Ctrl+I} invokes the indent() function.
195 224
196 Loading and saving text is achieved using setText() and text(), 225 Loading and saving text is achieved using setText() and text(),
197 for example: 226 for example:
@@ -243,6 +272,85 @@ static bool block_set_alignment = FALSE;
243 name="anchor">} with scrollToAnchor(). The find() function can be 272 name="anchor">} with scrollToAnchor(). The find() function can be
244 used to find and select a given string within the text. 273 used to find and select a given string within the text.
245 274
275 A read-only QTextEdit provides the same functionality as the
276 (obsolete) QTextView. (QTextView is still supplied for
277 compatibility with old code.)
278
279 \section2 Read-only key bindings
280
281 When QTextEdit is used read-only the key-bindings are limited to
282 navigation, and text may only be selected with the mouse:
283 \table
284 \header \i Keypresses \i Action
285 \row \i \e{UpArrow} \i Move one line up
286 \row \i \e{DownArrow} \i Move one line down
287 \row \i \e{LeftArrow} \i Move one character left
288 \row \i \e{RightArrow} \i Move one character right
289 \row \i \e{PageUp} \i Move one (viewport) page up
290 \row \i \e{PageDown} \i Move one (viewport) page down
291 \row \i \e{Home} \i Move to the beginning of the text
292 \row \i \e{End} \i Move to the end of the text
293 \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel)
294 \row \i \e{Ctrl+Wheel} \i Zoom the text
295 \endtable
296
297 The text edit may be able to provide some meta-information. For
298 example, the documentTitle() function will return the text from
299 within HTML \c{<title>} tags.
300
301 The text displayed in a text edit has a \e context. The context is
302 a path which the text edit's QMimeSourceFactory uses to resolve
303 the locations of files and images. It is passed to the
304 mimeSourceFactory() when quering data. (See QTextEdit() and
305 \l{context()}.)
306
307 \section1 Using QTextEdit as an Editor
308
309 All the information about using QTextEdit as a display widget also
310 applies here.
311
312 The current format's attributes are set with setItalic(),
313 setBold(), setUnderline(), setFamily() (font family),
314 setPointSize(), setColor() and setCurrentFont(). The current
315 paragraph's alignment is set with setAlignment().
316
317 Use setSelection() to select text. The setSelectionAttributes()
318 function is used to indicate how selected text should be
319 displayed. Use hasSelectedText() to find out if any text is
320 selected. The currently selected text's position is available
321 using getSelection() and the selected text itself is returned by
322 selectedText(). The selection can be copied to the clipboard with
323 copy(), or cut to the clipboard with cut(). It can be deleted with
324 removeSelectedText(). The entire text can be selected (or
325 unselected) using selectAll(). QTextEdit supports multiple
326 selections. Most of the selection functions operate on the default
327 selection, selection 0. If the user presses a non-selecting key,
328 e.g. a cursor key without also holding down Shift, all selections
329 are cleared.
330
331 Set and get the position of the cursor with setCursorPosition()
332 and getCursorPosition() respectively. When the cursor is moved,
333 the signals currentFontChanged(), currentColorChanged() and
334 currentAlignmentChanged() are emitted to reflect the font, color
335 and alignment at the new cursor position.
336
337 If the text changes, the textChanged() signal is emitted, and if
338 the user inserts a new line by pressing Return or Enter,
339 returnPressed() is emitted. The isModified() function will return
340 TRUE if the text has been modified.
341
342 QTextEdit provides command-based undo and redo. To set the depth
343 of the command history use setUndoDepth() which defaults to 100
344 steps. To undo or redo the last operation call undo() or redo().
345 The signals undoAvailable() and redoAvailable() indicate whether
346 the undo and redo operations can be executed.
347
348 The indent() function is used to reindent a paragraph. It is
349 useful for code editors, for example in <em>Qt Designer</em>'s
350 code editor \e{Ctrl+I} invokes the indent() function.
351
352 \section2 Editing key bindings
353
246 The list of key-bindings which are implemented for editing: 354 The list of key-bindings which are implemented for editing:
247 \table 355 \table
248 \header \i Keypresses \i Action 356 \header \i Keypresses \i Action
@@ -295,43 +403,6 @@ static bool block_set_alignment = FALSE;
295 can be changed to overwrite, where new text overwrites any text to 403 can be changed to overwrite, where new text overwrites any text to
296 the right of the cursor, using setOverwriteMode(). 404 the right of the cursor, using setOverwriteMode().
297 405
298 QTextEdit can also be used as read-only text viewer. Call
299 setReadOnly( TRUE ) to disable editing. A read-only QTextEdit
300 provides the same functionality as the (obsolete) QTextView.
301 (QTextView is still supplied for compatibility with old code.)
302
303 When QTextEdit is used read-only the key-bindings are limited to
304 navigation, and text may only be selected with the mouse:
305 \table
306 \header \i Keypresses \i Action
307 \row \i \e{UpArrow} \i Move one line up
308 \row \i \e{DownArrow} \i Move one line down
309 \row \i \e{LeftArrow} \i Move one character left
310 \row \i \e{RightArrow} \i Move one character right
311 \row \i \e{PageUp} \i Move one (viewport) page up
312 \row \i \e{PageDown} \i Move one (viewport) page down
313 \row \i \e{Home} \i Move to the beginning of the text
314 \row \i \e{End} \i Move to the end of the text
315 \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel)
316 \row \i \e{Ctrl+Wheel} \i Zoom the text
317 \endtable
318
319 The text edit may be able to provide some meta-information. For
320 example, the documentTitle() function will return the text from
321 within HTML \c{<title>} tags.
322
323 The text displayed in a text edit has a \e context. The context is
324 a path which the text edit's QMimeSourceFactory uses to resolve
325 the locations of files and images. It is passed to the
326 mimeSourceFactory() when quering data. (See QTextEdit() and
327 \l{context()}.)
328
329 Note that we do not intend to add a full-featured web browser
330 widget to Qt (because that would easily double Qt's size and only
331 a few applications would benefit from it). The rich
332 text support in Qt is designed to provide a fast, portable and
333 efficient way to add reasonable online help facilities to
334 applications, and to provide a basis for rich text editors.
335*/ 406*/
336 407
337/*! \enum QTextEdit::KeyboardAction 408/*! \enum QTextEdit::KeyboardAction
@@ -640,13 +711,15 @@ void QTextEdit::init()
640 inDnD = FALSE; 711 inDnD = FALSE;
641 712
642 doc->setFormatter( new QTextFormatterBreakWords ); 713 doc->setFormatter( new QTextFormatterBreakWords );
714 doc->formatCollection()->defaultFormat()->setFont( QScrollView::font() );
715 doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( QColorGroup::Text ) );
643 currentFormat = doc->formatCollection()->defaultFormat(); 716 currentFormat = doc->formatCollection()->defaultFormat();
644 currentAlignment = Qt3::AlignAuto; 717 currentAlignment = Qt3::AlignAuto;
645 718
646 viewport()->setBackgroundMode( PaletteBase ); 719 viewport()->setBackgroundMode( PaletteBase );
647 viewport()->setAcceptDrops( TRUE ); 720 viewport()->setAcceptDrops( TRUE );
648 resizeContents( 0, doc->lastParag() ? 721 resizeContents( 0, doc->lastParagraph() ?
649 ( doc->lastParag()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); 722 ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 );
650 723
651 setKeyCompression( TRUE ); 724 setKeyCompression( TRUE );
652 viewport()->setMouseTracking( TRUE ); 725 viewport()->setMouseTracking( TRUE );
@@ -658,7 +731,7 @@ void QTextEdit::init()
658 formatTimer = new QTimer( this ); 731 formatTimer = new QTimer( this );
659 connect( formatTimer, SIGNAL( timeout() ), 732 connect( formatTimer, SIGNAL( timeout() ),
660 this, SLOT( formatMore() ) ); 733 this, SLOT( formatMore() ) );
661 lastFormatted = doc->firstParag(); 734 lastFormatted = doc->firstParagraph();
662 735
663 scrollTimer = new QTimer( this ); 736 scrollTimer = new QTimer( this );
664 connect( scrollTimer, SIGNAL( timeout() ), 737 connect( scrollTimer, SIGNAL( timeout() ),
@@ -713,10 +786,10 @@ void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw
713 786
714 lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor ); 787 lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor );
715 788
716 if ( lastFormatted == doc->lastParag() ) 789 if ( lastFormatted == doc->lastParagraph() )
717 resizeContents( contentsWidth(), doc->height() ); 790 resizeContents( contentsWidth(), doc->height() );
718 791
719 if ( contentsHeight() < visibleHeight() && ( !doc->lastParag() || doc->lastParag()->isValid() ) && drawAll ) 792 if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll )
720 p->fillRect( 0, contentsHeight(), visibleWidth(), 793 p->fillRect( 0, contentsHeight(), visibleWidth(),
721 visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) ); 794 visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) );
722} 795}
@@ -813,10 +886,16 @@ bool QTextEdit::event( QEvent *e )
813 } 886 }
814 } 887 }
815 888
816 if ( e->type() == QEvent::Show && d->ensureCursorVisibleInShowEvent ) { 889 if ( e->type() == QEvent::Show ) {
817 sync(); 890 if ( d->ensureCursorVisibleInShowEvent ) {
818 ensureCursorVisible(); 891 sync();
819 d->ensureCursorVisibleInShowEvent = FALSE; 892 ensureCursorVisible();
893 d->ensureCursorVisibleInShowEvent = FALSE;
894 }
895 if ( !d->scrollToAnchor.isEmpty() ) {
896 scrollToAnchor( d->scrollToAnchor );
897 d->scrollToAnchor = QString::null;
898 }
820 } 899 }
821 return QWidget::event( e ); 900 return QWidget::event( e );
822} 901}
@@ -845,7 +924,7 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
845 selChanged = doc->removeSelection( i ) || selChanged; 924 selChanged = doc->removeSelection( i ) || selChanged;
846 925
847 if ( selChanged ) { 926 if ( selChanged ) {
848 cursor->parag()->document()->nextDoubleBuffered = TRUE; 927 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
849 repaintChanged(); 928 repaintChanged();
850 } 929 }
851 930
@@ -858,7 +937,7 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
858 // a bit hacky, but can't change this without introducing new enum values for move and keeping the 937 // a bit hacky, but can't change this without introducing new enum values for move and keeping the
859 // correct semantics and movement for BiDi and non BiDi text. 938 // correct semantics and movement for BiDi and non BiDi text.
860 CursorAction a; 939 CursorAction a;
861 if ( cursor->parag()->string()->isRightToLeft() == (e->key() == Key_Right) ) 940 if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) )
862 a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; 941 a = e->state() & ControlButton ? MoveWordBackward : MoveBackward;
863 else 942 else
864 a = e->state() & ControlButton ? MoveWordForward : MoveForward; 943 a = e->state() & ControlButton ? MoveWordForward : MoveForward;
@@ -886,12 +965,17 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
886 case Key_Return: case Key_Enter: 965 case Key_Return: case Key_Enter:
887 if ( doc->hasSelection( QTextDocument::Standard, FALSE ) ) 966 if ( doc->hasSelection( QTextDocument::Standard, FALSE ) )
888 removeSelectedText(); 967 removeSelectedText();
968 if ( textFormat() == Qt::RichText && ( e->state() & ControlButton ) ) {
969 // Ctrl-Enter inserts a line break in rich text mode
970 insert( QString( QChar( 0x2028) ), TRUE, FALSE, TRUE );
971 } else {
889#ifndef QT_NO_CURSOR 972#ifndef QT_NO_CURSOR
890 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 973 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
891#endif 974#endif
892 clearUndoRedoInfo = FALSE; 975 clearUndoRedoInfo = FALSE;
893 doKeyboardAction( ActionReturn ); 976 doKeyboardAction( ActionReturn );
894 emit returnPressed(); 977 emit returnPressed();
978 }
895 break; 979 break;
896 case Key_Delete: 980 case Key_Delete:
897#if defined (Q_WS_WIN) 981#if defined (Q_WS_WIN)
@@ -911,6 +995,10 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
911 case Key_Insert: 995 case Key_Insert:
912 if ( e->state() & ShiftButton ) 996 if ( e->state() & ShiftButton )
913 paste(); 997 paste();
998#if defined (Q_WS_WIN)
999 else if ( e->state() & ControlButton )
1000 copy();
1001#endif
914 break; 1002 break;
915 case Key_Backspace: 1003 case Key_Backspace:
916 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { 1004 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) {
@@ -918,10 +1006,6 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
918 break; 1006 break;
919 } 1007 }
920 1008
921 if ( !cursor->parag()->prev() &&
922 cursor->atParagStart() )
923 break;
924
925 doKeyboardAction( ActionBackspace ); 1009 doKeyboardAction( ActionBackspace );
926 clearUndoRedoInfo = FALSE; 1010 clearUndoRedoInfo = FALSE;
927 1011
@@ -943,41 +1027,50 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
943 ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) { 1027 ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) {
944 clearUndoRedoInfo = FALSE; 1028 clearUndoRedoInfo = FALSE;
945 if ( e->key() == Key_Tab ) { 1029 if ( e->key() == Key_Tab ) {
946 if ( textFormat() == Qt::RichText && 1030 if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() ) {
947 cursor->index() == 0 && cursor->parag()->style() && 1031 clearUndoRedo();
948 cursor->parag()->style()->displayMode() == 1032 undoRedoInfo.type = UndoRedoInfo::Style;
949 QStyleSheetItem::DisplayListItem ) { 1033 undoRedoInfo.id = cursor->paragraph()->paragId();
950 cursor->parag()->incDepth(); 1034 undoRedoInfo.eid = undoRedoInfo.id;
1035 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
1036 cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 );
1037 clearUndoRedo();
951 drawCursor( FALSE ); 1038 drawCursor( FALSE );
952 repaintChanged(); 1039 repaintChanged();
953 drawCursor( TRUE ); 1040 drawCursor( TRUE );
954 break; 1041 break;
955 } 1042 }
956 } 1043 }
957 if ( textFormat() == Qt::RichText && ( !cursor->parag()->style() || 1044
958 cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayBlock ) && 1045 if ( textFormat() == Qt::RichText && !cursor->paragraph()->isListItem() ) {
959 cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { 1046 if ( cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) {
960 setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); 1047 clearUndoRedo();
961 cursor->parag()->incDepth(); 1048 undoRedoInfo.type = UndoRedoInfo::Style;
962 drawCursor( FALSE ); 1049 undoRedoInfo.id = cursor->paragraph()->paragId();
963 repaintChanged(); 1050 undoRedoInfo.eid = undoRedoInfo.id;
964 drawCursor( TRUE ); 1051 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
965 } else { 1052 setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc );
966 if ( overWrite && !cursor->atParagEnd() ) 1053 clearUndoRedo();
967 cursor->remove(); 1054 drawCursor( FALSE );
968 QString t = e->text(); 1055 repaintChanged();
969 QTextParag *p = cursor->parag(); 1056 drawCursor( TRUE );
970 if ( p && p->string() && p->string()->isRightToLeft() ) { 1057 break;
971 QChar *c = (QChar *)t.unicode(); 1058 }
972 int l = t.length(); 1059 }
973 while( l-- ) { 1060 if ( overWrite && !cursor->atParagEnd() )
974 if ( c->mirrored() ) 1061 cursor->remove();
975 *c = c->mirroredChar(); 1062 QString t = e->text();
976 c++; 1063 QTextParagraph *p = cursor->paragraph();
977 } 1064 if ( p && p->string() && p->string()->isRightToLeft() ) {
1065 QChar *c = (QChar *)t.unicode();
1066 int l = t.length();
1067 while( l-- ) {
1068 if ( c->mirrored() )
1069 *c = c->mirroredChar();
1070 c++;
978 } 1071 }
979 insert( t, TRUE, FALSE, TRUE );
980 } 1072 }
1073 insert( t, TRUE, FALSE, TRUE );
981 break; 1074 break;
982 } else if ( e->state() & ControlButton ) { 1075 } else if ( e->state() & ControlButton ) {
983 switch ( e->key() ) { 1076 switch ( e->key() ) {
@@ -1019,7 +1112,7 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
1019 removeSelectedText(); 1112 removeSelectedText();
1020 break; 1113 break;
1021 } 1114 }
1022 if ( !cursor->parag()->prev() && 1115 if ( !cursor->paragraph()->prev() &&
1023 cursor->atParagStart() ) 1116 cursor->atParagStart() )
1024 break; 1117 break;
1025 1118
@@ -1036,7 +1129,10 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
1036 moveCursor( MoveUp, e->state() & ShiftButton ); 1129 moveCursor( MoveUp, e->state() & ShiftButton );
1037 break; 1130 break;
1038 case Key_Z: 1131 case Key_Z:
1039 undo(); 1132 if(e->state() & ShiftButton)
1133 redo();
1134 else
1135 undo();
1040 break; 1136 break;
1041 case Key_Y: 1137 case Key_Y:
1042 redo(); 1138 redo();
@@ -1063,7 +1159,7 @@ void QTextEdit::keyPressEvent( QKeyEvent *e )
1063 } 1159 }
1064 1160
1065 emit cursorPositionChanged( cursor ); 1161 emit cursorPositionChanged( cursor );
1066 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 1162 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
1067 if ( clearUndoRedoInfo ) 1163 if ( clearUndoRedoInfo )
1068 clearUndoRedo(); 1164 clearUndoRedo();
1069 changeIntervalTimer->start( 100, TRUE ); 1165 changeIntervalTimer->start( 100, TRUE );
@@ -1084,187 +1180,137 @@ void QTextEdit::doKeyboardAction( KeyboardAction action )
1084 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough 1180 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough
1085 return; 1181 return;
1086 1182
1087 lastFormatted = cursor->parag(); 1183 lastFormatted = cursor->paragraph();
1088 drawCursor( FALSE ); 1184 drawCursor( FALSE );
1089 bool doUpdateCurrentFormat = TRUE; 1185 bool doUpdateCurrentFormat = TRUE;
1090 1186
1091 switch ( action ) { 1187 switch ( action ) {
1092 case ActionDelete: { 1188 case ActionDelete:
1093 checkUndoRedoInfo( UndoRedoInfo::Delete ); 1189 if ( !cursor->atParagEnd() ) {
1094 if ( !undoRedoInfo.valid() ) { 1190 checkUndoRedoInfo( UndoRedoInfo::Delete );
1095 undoRedoInfo.id = cursor->parag()->paragId(); 1191 if ( !undoRedoInfo.valid() ) {
1096 undoRedoInfo.index = cursor->index(); 1192 undoRedoInfo.id = cursor->paragraph()->paragId();
1097 undoRedoInfo.d->text = QString::null; 1193 undoRedoInfo.index = cursor->index();
1098 } 1194 undoRedoInfo.d->text = QString::null;
1099 undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; 1195 }
1100 if ( cursor->parag()->at( cursor->index() )->format() ) { 1196 undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( cursor->index() ), TRUE );
1101 cursor->parag()->at( cursor->index() )->format()->addRef(); 1197 cursor->remove();
1102 undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); 1198 } else {
1103 } 1199 clearUndoRedo();
1104 QTextParag *old = cursor->parag(); 1200 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1105 if ( cursor->remove() ) { 1201 cursor->gotoNextLetter();
1106 if ( old != cursor->parag() && lastFormatted == old ) 1202 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1107 lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; 1203 removeSelectedText( QTextDocument::Temp );
1108 undoRedoInfo.d->text += "\n";
1109 } 1204 }
1110 } break; 1205 break;
1111 case ActionBackspace: 1206 case ActionBackspace:
1112 if ( textFormat() == Qt::RichText && 1207 if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() && cursor->index() == 0 ) {
1113 cursor->parag()->style() && 1208 clearUndoRedo();
1114 cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayListItem && 1209 undoRedoInfo.type = UndoRedoInfo::Style;
1115 cursor->index() == 0 ) { 1210 undoRedoInfo.id = cursor->paragraph()->paragId();
1116 cursor->parag()->decDepth(); 1211 undoRedoInfo.eid = undoRedoInfo.id;
1117 lastFormatted = cursor->parag(); 1212 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
1213 int ldepth = cursor->paragraph()->listDepth();
1214 ldepth = QMAX( ldepth-1, 0 );
1215 cursor->paragraph()->setListDepth( ldepth );
1216 if ( ldepth == 0 )
1217 cursor->paragraph()->setListItem( FALSE );
1218 clearUndoRedo();
1219 lastFormatted = cursor->paragraph();
1118 repaintChanged(); 1220 repaintChanged();
1119 drawCursor( TRUE ); 1221 drawCursor( TRUE );
1120 return; 1222 return;
1121 } 1223 }
1122 checkUndoRedoInfo( UndoRedoInfo::Delete ); 1224 if ( !cursor->atParagStart() ) {
1123 if ( !undoRedoInfo.valid() ) { 1225 checkUndoRedoInfo( UndoRedoInfo::Delete );
1124 undoRedoInfo.id = cursor->parag()->paragId(); 1226 if ( !undoRedoInfo.valid() ) {
1125 undoRedoInfo.index = cursor->index(); 1227 undoRedoInfo.id = cursor->paragraph()->paragId();
1126 undoRedoInfo.d->text = QString::null; 1228 undoRedoInfo.index = cursor->index();
1127 } 1229 undoRedoInfo.d->text = QString::null;
1128 cursor->gotoPreviousLetter(); 1230 }
1129 undoRedoInfo.d->text.prepend( QString( cursor->parag()->at( cursor->index() )->c ) ); 1231 cursor->gotoPreviousLetter();
1130 if ( cursor->parag()->at( cursor->index() )->format() ) { 1232 undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index() ), TRUE );
1131 cursor->parag()->at( cursor->index() )->format()->addRef();
1132 undoRedoInfo.d->text.at( 0 ).setFormat( cursor->parag()->at( cursor->index() )->format() );
1133 }
1134 undoRedoInfo.index = cursor->index();
1135 if ( cursor->remove() ) {
1136 undoRedoInfo.d->text.remove( 0, 1 );
1137 undoRedoInfo.d->text.prepend( "\n" );
1138 undoRedoInfo.index = cursor->index(); 1233 undoRedoInfo.index = cursor->index();
1139 undoRedoInfo.id = cursor->parag()->paragId(); 1234 cursor->remove();
1235 lastFormatted = cursor->paragraph();
1236 } else if ( cursor->paragraph()->prev() ){
1237 clearUndoRedo();
1238 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1239 cursor->gotoPreviousLetter();
1240 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1241 removeSelectedText( QTextDocument::Temp );
1140 } 1242 }
1141 lastFormatted = cursor->parag();
1142 break; 1243 break;
1143 case ActionReturn: { 1244 case ActionReturn:
1144 checkUndoRedoInfo( UndoRedoInfo::Return ); 1245 checkUndoRedoInfo( UndoRedoInfo::Return );
1145 if ( !undoRedoInfo.valid() ) { 1246 if ( !undoRedoInfo.valid() ) {
1146 undoRedoInfo.id = cursor->parag()->paragId(); 1247 undoRedoInfo.id = cursor->paragraph()->paragId();
1147 undoRedoInfo.index = cursor->index(); 1248 undoRedoInfo.index = cursor->index();
1148 undoRedoInfo.d->text = QString::null; 1249 undoRedoInfo.d->text = QString::null;
1149 } 1250 }
1150 undoRedoInfo.d->text += "\n"; 1251 undoRedoInfo.d->text += "\n";
1151 cursor->splitAndInsertEmptyParag(); 1252 cursor->splitAndInsertEmptyParagraph();
1152 if ( cursor->parag()->prev() ) { 1253 if ( cursor->paragraph()->prev() ) {
1153 lastFormatted = cursor->parag()->prev(); 1254 lastFormatted = cursor->paragraph()->prev();
1154 lastFormatted->invalidate( 0 ); 1255 lastFormatted->invalidate( 0 );
1155 } 1256 }
1156 doUpdateCurrentFormat = FALSE; 1257 doUpdateCurrentFormat = FALSE;
1157 } break;
1158 case ActionKill:
1159 checkUndoRedoInfo( UndoRedoInfo::Delete );
1160 if ( !undoRedoInfo.valid() ) {
1161 undoRedoInfo.id = cursor->parag()->paragId();
1162 undoRedoInfo.index = cursor->index();
1163 undoRedoInfo.d->text = QString::null;
1164 }
1165 if ( cursor->atParagEnd() ) {
1166 undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c;
1167 if ( cursor->parag()->at( cursor->index() )->format() ) {
1168 cursor->parag()->at( cursor->index() )->format()->addRef();
1169 undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() );
1170 }
1171 QTextParag *old = cursor->parag();
1172 if ( cursor->remove() ) {
1173 if ( old != cursor->parag() && lastFormatted == old )
1174 lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0;
1175 undoRedoInfo.d->text += "\n";
1176 }
1177 } else {
1178 int oldLen = undoRedoInfo.d->text.length();
1179 undoRedoInfo.d->text += cursor->parag()->string()->toString().mid( cursor->index() );
1180 for ( int i = cursor->index(); i < cursor->parag()->length(); ++i ) {
1181 if ( cursor->parag()->at( i )->format() ) {
1182 cursor->parag()->at( i )->format()->addRef();
1183 undoRedoInfo.d->text.at( oldLen + i - cursor->index() ).setFormat( cursor->parag()->at( i )->format() );
1184 }
1185 }
1186 undoRedoInfo.d->text.remove( undoRedoInfo.d->text.length() - 1, 1 );
1187 cursor->killLine();
1188 }
1189 break; 1258 break;
1259 case ActionKill:
1260 clearUndoRedo();
1261 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1262 if ( cursor->atParagEnd() )
1263 cursor->gotoNextLetter();
1264 else
1265 cursor->setIndex( cursor->paragraph()->length() - 1 );
1266 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1267 removeSelectedText( QTextDocument::Temp );
1268 break;
1190 } 1269 }
1191 1270
1192 formatMore(); 1271 formatMore();
1193 repaintChanged(); 1272 repaintChanged();
1194 ensureCursorVisible(); 1273 ensureCursorVisible();
1195 drawCursor( TRUE ); 1274 drawCursor( TRUE );
1196 1275 updateMicroFocusHint();
1197 if ( hasFocus() || viewport()->hasFocus() ) {
1198 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1199 if ( !readonly ) {
1200 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1201 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1202 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1203 }
1204 }
1205
1206 if ( doUpdateCurrentFormat ) 1276 if ( doUpdateCurrentFormat )
1207 updateCurrentFormat(); 1277 updateCurrentFormat();
1208 setModified(); 1278 setModified();
1209 emit textChanged(); 1279 emit textChanged();
1210} 1280}
1211 1281
1212void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, int oldLen, QTextString &text, bool fillStyles ) 1282void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles )
1213{ 1283{
1284 QDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly );
1214 c2.restoreState(); 1285 c2.restoreState();
1215 c1.restoreState(); 1286 c1.restoreState();
1216 if ( c1.parag() == c2.parag() ) { 1287 int lastIndex = text.length();
1217 for ( int i = c1.index(); i < c2.index(); ++i ) { 1288 if ( c1.paragraph() == c2.paragraph() ) {
1218 if ( c1.parag()->at( i )->format() ) { 1289 for ( int i = c1.index(); i < c2.index(); ++i )
1219 c1.parag()->at( i )->format()->addRef(); 1290 text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE );
1220 text.at( oldLen + i - c1.index() ).setFormat( c1.parag()->at( i )->format() );
1221 }
1222 }
1223 if ( fillStyles ) { 1291 if ( fillStyles ) {
1224 undoRedoInfo.oldAligns[ 0 ] = c1.parag()->alignment(); 1292 styleStream << (int) 1;
1225 undoRedoInfo.oldStyles << c1.parag()->styleSheetItems(); 1293 c1.paragraph()->writeStyleInformation( styleStream );
1226 undoRedoInfo.oldListStyles << c1.parag()->listStyle();
1227 } 1294 }
1228 } else { 1295 } else {
1229 int lastIndex = oldLen;
1230 int i; 1296 int i;
1231 for ( i = c1.index(); i < c1.parag()->length(); ++i ) { 1297 for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i )
1232 if ( c1.parag()->at( i )->format() ) { 1298 text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE );
1233 c1.parag()->at( i )->format()->addRef(); 1299 int num = 2; // start and end, being different
1234 text.at( lastIndex ).setFormat( c1.parag()->at( i )->format() ); 1300 text += "\n"; lastIndex++;
1235 lastIndex++; 1301 QTextParagraph *p = c1.paragraph()->next();
1236 } 1302 while ( p && p != c2.paragraph() ) {
1237 } 1303 for ( i = 0; i < p->length()-1; ++i )
1238 QTextParag *p = c1.parag()->next(); 1304 text.insert( lastIndex++ , p->at( i ), TRUE );
1239 while ( p && p != c2.parag() ) { 1305 text += "\n"; num++; lastIndex++;
1240 for ( int i = 0; i < p->length(); ++i ) {
1241 if ( p->at( i )->format() ) {
1242 p->at( i )->format()->addRef();
1243 text.at( i + lastIndex ).setFormat( p->at( i )->format() );
1244 }
1245 }
1246 lastIndex += p->length();
1247 p = p->next(); 1306 p = p->next();
1248 } 1307 }
1249 for ( i = 0; i < c2.index(); ++i ) { 1308 for ( i = 0; i < c2.index(); ++i )
1250 if ( c2.parag()->at( i )->format() ) { 1309 text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE );
1251 c2.parag()->at( i )->format()->addRef();
1252 text.at( i + lastIndex ).setFormat( c2.parag()->at( i )->format() );
1253 }
1254 }
1255 if ( fillStyles ) { 1310 if ( fillStyles ) {
1256 QTextParag *p = c1.parag(); 1311 styleStream << num;
1257 i = 0; 1312 for ( QTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() )
1258 while ( p ) { 1313 p->writeStyleInformation( styleStream );
1259 if ( i < (int)undoRedoInfo.oldAligns.size() )
1260 undoRedoInfo.oldAligns[ i ] = p->alignment();
1261 undoRedoInfo.oldStyles << p->styleSheetItems();
1262 undoRedoInfo.oldListStyles << p->listStyle();
1263 if ( p == c2.parag() )
1264 break;
1265 p = p->next();
1266 ++i;
1267 }
1268 } 1314 }
1269 } 1315 }
1270} 1316}
@@ -1294,9 +1340,11 @@ void QTextEdit::removeSelectedText( int selNum )
1294 return; 1340 return;
1295 1341
1296 QTextCursor c1 = doc->selectionStartCursor( selNum ); 1342 QTextCursor c1 = doc->selectionStartCursor( selNum );
1343 c1.restoreState();
1297 QTextCursor c2 = doc->selectionEndCursor( selNum ); 1344 QTextCursor c2 = doc->selectionEndCursor( selNum );
1345 c2.restoreState();
1298 1346
1299 // ### no support for editing tables yet 1347 // ### no support for editing tables yet, plus security for broken selections
1300 if ( c1.nestedDepth() || c2.nestedDepth() ) 1348 if ( c1.nestedDepth() || c2.nestedDepth() )
1301 return; 1349 return;
1302 1350
@@ -1312,14 +1360,13 @@ void QTextEdit::removeSelectedText( int selNum )
1312 doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index ); 1360 doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index );
1313 undoRedoInfo.d->text = QString::null; 1361 undoRedoInfo.d->text = QString::null;
1314 } 1362 }
1315 int oldLen = undoRedoInfo.d->text.length(); 1363 readFormats( c1, c2, undoRedoInfo.d->text, TRUE );
1316 undoRedoInfo.d->text = doc->selectedText( selNum, FALSE ); 1364
1317 undoRedoInfo.oldAligns.resize( undoRedoInfo.oldAligns.size() + QMAX( 0, c2.parag()->paragId() - c1.parag()->paragId() + 1 ) ); 1365
1318 readFormats( c1, c2, oldLen, undoRedoInfo.d->text, TRUE );
1319 doc->removeSelectedText( selNum, cursor ); 1366 doc->removeSelectedText( selNum, cursor );
1320 if ( cursor->isValid() ) { 1367 if ( cursor->isValid() ) {
1321 ensureCursorVisible(); 1368 ensureCursorVisible();
1322 lastFormatted = cursor->parag(); 1369 lastFormatted = cursor->paragraph();
1323 formatMore(); 1370 formatMore();
1324 repaintChanged(); 1371 repaintChanged();
1325 ensureCursorVisible(); 1372 ensureCursorVisible();
@@ -1334,18 +1381,10 @@ void QTextEdit::removeSelectedText( int selNum )
1334#ifndef QT_NO_CURSOR 1381#ifndef QT_NO_CURSOR
1335 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1382 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1336#endif 1383#endif
1337 if ( hasFocus() || viewport()->hasFocus() ) { 1384 updateMicroFocusHint();
1338 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1339 if ( !readonly ) {
1340 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1341 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1342 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1343 }
1344 }
1345 } else { 1385 } else {
1346 cursor->setDocument( doc ); 1386 delete cursor;
1347 cursor->setParag( doc->firstParag() ); 1387 cursor = new QTextCursor( doc );
1348 cursor->setIndex( 0 );
1349 drawCursor( TRUE ); 1388 drawCursor( TRUE );
1350 viewport()->repaint( TRUE ); 1389 viewport()->repaint( TRUE );
1351 } 1390 }
@@ -1365,10 +1404,10 @@ void QTextEdit::moveCursor( CursorAction action, bool select )
1365 drawCursor( FALSE ); 1404 drawCursor( FALSE );
1366 if ( select ) { 1405 if ( select ) {
1367 if ( !doc->hasSelection( QTextDocument::Standard ) ) 1406 if ( !doc->hasSelection( QTextDocument::Standard ) )
1368 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1407 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1369 moveCursor( action ); 1408 moveCursor( action );
1370 if ( doc->setSelectionEnd( QTextDocument::Standard, cursor ) ) { 1409 if ( doc->setSelectionEnd( QTextDocument::Standard, *cursor ) ) {
1371 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1410 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1372 repaintChanged(); 1411 repaintChanged();
1373 } else { 1412 } else {
1374 drawCursor( TRUE ); 1413 drawCursor( TRUE );
@@ -1383,7 +1422,7 @@ void QTextEdit::moveCursor( CursorAction action, bool select )
1383 ensureCursorVisible(); 1422 ensureCursorVisible();
1384 drawCursor( TRUE ); 1423 drawCursor( TRUE );
1385 } else { 1424 } else {
1386 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1425 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1387 repaintChanged(); 1426 repaintChanged();
1388 ensureCursorVisible(); 1427 ensureCursorVisible();
1389 drawCursor( TRUE ); 1428 drawCursor( TRUE );
@@ -1399,14 +1438,7 @@ void QTextEdit::moveCursor( CursorAction action, bool select )
1399 1438
1400 drawCursor( TRUE ); 1439 drawCursor( TRUE );
1401 updateCurrentFormat(); 1440 updateCurrentFormat();
1402 if ( hasFocus() || viewport()->hasFocus() ) { 1441 updateMicroFocusHint();
1403 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1404 if ( !readonly ) {
1405 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1406 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1407 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1408 }
1409 }
1410} 1442}
1411 1443
1412/*! \overload 1444/*! \overload
@@ -1449,19 +1481,11 @@ void QTextEdit::moveCursor( CursorAction action )
1449 cursor->gotoLineEnd(); 1481 cursor->gotoLineEnd();
1450 break; 1482 break;
1451 case MoveEnd: 1483 case MoveEnd:
1452 ensureFormatted( doc->lastParag() ); 1484 ensureFormatted( doc->lastParagraph() );
1453 cursor->gotoEnd(); 1485 cursor->gotoEnd();
1454 break; 1486 break;
1455 } 1487 }
1456 1488 updateMicroFocusHint();
1457 if ( hasFocus() || viewport()->hasFocus() ) {
1458 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1459 if ( !readonly ) {
1460 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1461 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1462 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1463 }
1464 }
1465 updateCurrentFormat(); 1489 updateCurrentFormat();
1466} 1490}
1467 1491
@@ -1470,6 +1494,8 @@ void QTextEdit::moveCursor( CursorAction action )
1470void QTextEdit::resizeEvent( QResizeEvent *e ) 1494void QTextEdit::resizeEvent( QResizeEvent *e )
1471{ 1495{
1472 QScrollView::resizeEvent( e ); 1496 QScrollView::resizeEvent( e );
1497 if ( doc->visibleWidth() == 0 )
1498 doResize();
1473} 1499}
1474 1500
1475/*! \reimp */ 1501/*! \reimp */
@@ -1477,12 +1503,15 @@ void QTextEdit::resizeEvent( QResizeEvent *e )
1477void QTextEdit::viewportResizeEvent( QResizeEvent *e ) 1503void QTextEdit::viewportResizeEvent( QResizeEvent *e )
1478{ 1504{
1479 QScrollView::viewportResizeEvent( e ); 1505 QScrollView::viewportResizeEvent( e );
1480 if ( e->oldSize().width() != e->size().width() ) 1506 if ( e->oldSize().width() != e->size().width() ) {
1507 bool stayAtBottom = e->oldSize().height() != e->size().height() &&
1508 contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height();
1481 doResize(); 1509 doResize();
1510 if ( stayAtBottom )
1511 scrollToBottom();
1512 }
1482} 1513}
1483 1514
1484static bool blockEnsureCursorVisible = FALSE;
1485
1486/*! 1515/*!
1487 Ensures that the cursor is visible by scrolling the text edit if 1516 Ensures that the cursor is visible by scrolling the text edit if
1488 necessary. 1517 necessary.
@@ -1492,20 +1521,18 @@ static bool blockEnsureCursorVisible = FALSE;
1492 1521
1493void QTextEdit::ensureCursorVisible() 1522void QTextEdit::ensureCursorVisible()
1494{ 1523{
1495 if ( blockEnsureCursorVisible )
1496 return;
1497 if ( !isVisible() ) { 1524 if ( !isVisible() ) {
1498 d->ensureCursorVisibleInShowEvent = TRUE; 1525 d->ensureCursorVisibleInShowEvent = TRUE;
1499 return; 1526 return;
1500 } 1527 }
1501 lastFormatted = cursor->parag(); 1528 lastFormatted = cursor->paragraph();
1502 formatMore(); 1529 formatMore();
1503 QTextStringChar *chr = cursor->parag()->at( cursor->index() ); 1530 QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
1504 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 1531 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
1505 int x = cursor->parag()->rect().x() + chr->x + cursor->offsetX(); 1532 int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX();
1506 int y = 0; int dummy; 1533 int y = 0; int dummy;
1507 cursor->parag()->lineHeightOfChar( cursor->index(), &dummy, &y ); 1534 cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
1508 y += cursor->parag()->rect().y() + cursor->offsetY(); 1535 y += cursor->paragraph()->rect().y() + cursor->offsetY();
1509 int w = 1; 1536 int w = 1;
1510 ensureVisible( x, y + h / 2, w, h / 2 + 2 ); 1537 ensureVisible( x, y + h / 2, w, h / 2 + 2 );
1511} 1538}
@@ -1517,38 +1544,38 @@ void QTextEdit::drawCursor( bool visible )
1517{ 1544{
1518 if ( !isUpdatesEnabled() || 1545 if ( !isUpdatesEnabled() ||
1519 !viewport()->isUpdatesEnabled() || 1546 !viewport()->isUpdatesEnabled() ||
1520 !cursor->parag() || 1547 !cursor->paragraph() ||
1521 !cursor->parag()->isValid() || 1548 !cursor->paragraph()->isValid() ||
1522 !selectedText().isEmpty() || 1549 !selectedText().isEmpty() ||
1523 ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) || 1550 ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) ||
1524 isReadOnly() ) 1551 isReadOnly() )
1525 return; 1552 return;
1526 1553
1527 QPainter p( viewport() ); 1554 QPainter p( viewport() );
1528 QRect r( cursor->topParag()->rect() ); 1555 QRect r( cursor->topParagraph()->rect() );
1529 cursor->parag()->setChanged( TRUE ); 1556 cursor->paragraph()->setChanged( TRUE );
1530 p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); 1557 p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() );
1531 QPixmap *pix = 0; 1558 QPixmap *pix = 0;
1532 QColorGroup cg( colorGroup() ); 1559 QColorGroup cg( colorGroup() );
1533 if ( cursor->parag()->background() ) 1560 if ( cursor->paragraph()->background() )
1534 cg.setBrush( QColorGroup::Base, *cursor->parag()->background() ); 1561 cg.setBrush( QColorGroup::Base, *cursor->paragraph()->background() );
1535 else if ( doc->paper() ) 1562 else if ( doc->paper() )
1536 cg.setBrush( QColorGroup::Base, *doc->paper() ); 1563 cg.setBrush( QColorGroup::Base, *doc->paper() );
1537 p.setBrushOrigin( -contentsX(), -contentsY() ); 1564 p.setBrushOrigin( -contentsX(), -contentsY() );
1538 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1565 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1539 if ( !cursor->nestedDepth() ) { 1566 if ( !cursor->nestedDepth() ) {
1540 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 1567 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
1541 int dist = 5; 1568 int dist = 5;
1542 if ( ( cursor->parag()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) 1569 if ( ( cursor->paragraph()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify )
1543 dist = 50; 1570 dist = 50;
1544 int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist; 1571 int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist;
1545 x = QMAX( x, 0 ); 1572 x = QMAX( x, 0 );
1546 p.setClipRect( QRect( x - contentsX(), 1573 p.setClipRect( QRect( x - contentsX(),
1547 r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); 1574 r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) );
1548 doc->drawParag( &p, cursor->parag(), x, 1575 doc->drawParagraph( &p, cursor->paragraph(), x,
1549 r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); 1576 r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor );
1550 } else { 1577 } else {
1551 doc->drawParag( &p, cursor->parag(), r.x() - cursor->totalOffsetX(), 1578 doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(),
1552 r.y() - cursor->totalOffsetY(), r.width(), r.height(), 1579 r.y() - cursor->totalOffsetY(), r.width(), r.height(),
1553 pix, cg, visible, cursor ); 1580 pix, cg, visible, cursor );
1554 } 1581 }
@@ -1602,9 +1629,9 @@ void QTextEdit::contentsMousePressEvent( QMouseEvent *e )
1602 if ( isReadOnly() && linksEnabled() ) { 1629 if ( isReadOnly() && linksEnabled() ) {
1603 QTextCursor c = *cursor; 1630 QTextCursor c = *cursor;
1604 placeCursor( e->pos(), &c, TRUE ); 1631 placeCursor( e->pos(), &c, TRUE );
1605 if ( c.parag() && c.parag()->at( c.index() ) && 1632 if ( c.paragraph() && c.paragraph()->at( c.index() ) &&
1606 c.parag()->at( c.index() )->isAnchor() ) { 1633 c.paragraph()->at( c.index() )->isAnchor() ) {
1607 pressedLink = c.parag()->at( c.index() )->anchorHref(); 1634 pressedLink = c.paragraph()->at( c.index() )->anchorHref();
1608 } 1635 }
1609 } 1636 }
1610 1637
@@ -1622,16 +1649,16 @@ void QTextEdit::contentsMousePressEvent( QMouseEvent *e )
1622 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1649 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1623 if ( !( e->state() & ShiftButton ) ) { 1650 if ( !( e->state() & ShiftButton ) ) {
1624 redraw = doc->removeSelection( QTextDocument::Standard ); 1651 redraw = doc->removeSelection( QTextDocument::Standard );
1625 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1652 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1626 } else { 1653 } else {
1627 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1654 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1628 } 1655 }
1629 } else { 1656 } else {
1630 if ( isReadOnly() || !( e->state() & ShiftButton ) ) { 1657 if ( isReadOnly() || !( e->state() & ShiftButton ) ) {
1631 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1658 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1632 } else { 1659 } else {
1633 doc->setSelectionStart( QTextDocument::Standard, &c ); 1660 doc->setSelectionStart( QTextDocument::Standard, c );
1634 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1661 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1635 } 1662 }
1636 } 1663 }
1637 1664
@@ -1714,7 +1741,7 @@ void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e )
1714 mousePressed = FALSE; 1741 mousePressed = FALSE;
1715 } 1742 }
1716 emit cursorPositionChanged( cursor ); 1743 emit cursorPositionChanged( cursor );
1717 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 1744 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
1718 if ( oldCursor != *cursor ) 1745 if ( oldCursor != *cursor )
1719 updateCurrentFormat(); 1746 updateCurrentFormat();
1720 inDoubleClick = FALSE; 1747 inDoubleClick = FALSE;
@@ -1744,13 +1771,13 @@ void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * )
1744{ 1771{
1745 QTextCursor c1 = *cursor; 1772 QTextCursor c1 = *cursor;
1746 QTextCursor c2 = *cursor; 1773 QTextCursor c2 = *cursor;
1747 if ( cursor->index() > 0 && !cursor->parag()->at( cursor->index()-1 )->c.isSpace() ) 1774 if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() )
1748 c1.gotoPreviousWord(); 1775 c1.gotoPreviousWord();
1749 if ( !cursor->parag()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) 1776 if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() )
1750 c2.gotoNextWord(); 1777 c2.gotoNextWord();
1751 1778
1752 doc->setSelectionStart( QTextDocument::Standard, &c1 ); 1779 doc->setSelectionStart( QTextDocument::Standard, c1 );
1753 doc->setSelectionEnd( QTextDocument::Standard, &c2 ); 1780 doc->setSelectionEnd( QTextDocument::Standard, c2 );
1754 1781
1755 *cursor = c2; 1782 *cursor = c2;
1756 1783
@@ -1806,9 +1833,42 @@ void QTextEdit::contentsDropEvent( QDropEvent *e )
1806 QString text; 1833 QString text;
1807 bool intern = FALSE; 1834 bool intern = FALSE;
1808 if ( QTextDrag::decode( e, text ) ) { 1835 if ( QTextDrag::decode( e, text ) ) {
1809 if ( ( e->source() == this || 1836 bool hasSel = doc->hasSelection( QTextDocument::Standard );
1810 e->source() == viewport() ) && 1837 bool internalDrag = e->source() == this || e->source() == viewport();
1811 e->action() == QDropEvent::Move ) { 1838 int dropId, dropIndex;
1839 QTextCursor insertCursor = *cursor;
1840 dropId = cursor->paragraph()->paragId();
1841 dropIndex = cursor->index();
1842 if ( hasSel && internalDrag ) {
1843 QTextCursor c1, c2;
1844 int selStartId, selStartIndex;
1845 int selEndId, selEndIndex;
1846 c1 = doc->selectionStartCursor( QTextDocument::Standard );
1847 c1.restoreState();
1848 c2 = doc->selectionEndCursor( QTextDocument::Standard );
1849 c2.restoreState();
1850 selStartId = c1.paragraph()->paragId();
1851 selStartIndex = c1.index();
1852 selEndId = c2.paragraph()->paragId();
1853 selEndIndex = c2.index();
1854 if ( ( ( dropId > selStartId ) ||
1855 ( dropId == selStartId && dropIndex > selStartIndex ) ) &&
1856 ( ( dropId < selEndId ) ||
1857 ( dropId == selEndId && dropIndex <= selEndIndex ) ) )
1858 insertCursor = c1;
1859 if ( dropId == selEndId && dropIndex > selEndIndex ) {
1860 insertCursor = c1;
1861 if ( selStartId == selEndId ) {
1862 insertCursor.setIndex( dropIndex -
1863 ( selEndIndex - selStartIndex ) );
1864 } else {
1865 insertCursor.setIndex( dropIndex - selEndIndex +
1866 selStartIndex );
1867 }
1868 }
1869 }
1870
1871 if ( internalDrag && e->action() == QDropEvent::Move ) {
1812 removeSelectedText(); 1872 removeSelectedText();
1813 intern = TRUE; 1873 intern = TRUE;
1814 } else { 1874 } else {
@@ -1818,7 +1878,8 @@ void QTextEdit::contentsDropEvent( QDropEvent *e )
1818#endif 1878#endif
1819 } 1879 }
1820 drawCursor( FALSE ); 1880 drawCursor( FALSE );
1821 placeCursor( e->pos(), cursor ); 1881 cursor->setParagraph( insertCursor.paragraph() );
1882 cursor->setIndex( insertCursor.index() );
1822 drawCursor( TRUE ); 1883 drawCursor( TRUE );
1823 if ( !cursor->nestedDepth() ) { 1884 if ( !cursor->nestedDepth() ) {
1824 insert( text, FALSE, TRUE, FALSE ); 1885 insert( text, FALSE, TRUE, FALSE );
@@ -1859,13 +1920,13 @@ void QTextEdit::handleMouseMove( const QPoint& pos )
1859 QTextCursor cr = *cursor; 1920 QTextCursor cr = *cursor;
1860 cr.gotoNextWord(); 1921 cr.gotoNextWord();
1861 1922
1862 int diff = QABS( oldCursor.parag()->at( oldCursor.index() )->x - mousePos.x() ); 1923 int diff = QABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() );
1863 int ldiff = QABS( cl.parag()->at( cl.index() )->x - mousePos.x() ); 1924 int ldiff = QABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() );
1864 int rdiff = QABS( cr.parag()->at( cr.index() )->x - mousePos.x() ); 1925 int rdiff = QABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() );
1865 1926
1866 1927
1867 if ( cursor->parag()->lineStartOfChar( cursor->index() ) != 1928 if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) !=
1868 oldCursor.parag()->lineStartOfChar( oldCursor.index() ) ) 1929 oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) )
1869 diff = 0xFFFFFF; 1930 diff = 0xFFFFFF;
1870 1931
1871 if ( rdiff < diff && rdiff < ldiff ) 1932 if ( rdiff < diff && rdiff < ldiff )
@@ -1880,7 +1941,7 @@ void QTextEdit::handleMouseMove( const QPoint& pos )
1880 1941
1881 bool redraw = FALSE; 1942 bool redraw = FALSE;
1882 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1943 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1883 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1944 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1884 } 1945 }
1885 1946
1886 if ( !redraw ) { 1947 if ( !redraw ) {
@@ -1890,9 +1951,9 @@ void QTextEdit::handleMouseMove( const QPoint& pos )
1890 drawCursor( TRUE ); 1951 drawCursor( TRUE );
1891 } 1952 }
1892 1953
1893 if ( currentFormat && currentFormat->key() != cursor->parag()->at( cursor->index() )->format()->key() ) { 1954 if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) {
1894 currentFormat->removeRef(); 1955 currentFormat->removeRef();
1895 currentFormat = doc->formatCollection()->format( cursor->parag()->at( cursor->index() )->format() ); 1956 currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() );
1896 if ( currentFormat->isMisspelled() ) { 1957 if ( currentFormat->isMisspelled() ) {
1897 currentFormat->removeRef(); 1958 currentFormat->removeRef();
1898 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); 1959 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
@@ -1902,8 +1963,8 @@ void QTextEdit::handleMouseMove( const QPoint& pos )
1902 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 1963 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
1903 } 1964 }
1904 1965
1905 if ( currentAlignment != cursor->parag()->alignment() ) { 1966 if ( currentAlignment != cursor->paragraph()->alignment() ) {
1906 currentAlignment = cursor->parag()->alignment(); 1967 currentAlignment = cursor->paragraph()->alignment();
1907 block_set_alignment = TRUE; 1968 block_set_alignment = TRUE;
1908 emit currentAlignmentChanged( currentAlignment ); 1969 emit currentAlignmentChanged( currentAlignment );
1909 block_set_alignment = FALSE; 1970 block_set_alignment = FALSE;
@@ -1925,18 +1986,30 @@ void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link )
1925 c = cursor; 1986 c = cursor;
1926 1987
1927 c->restoreState(); 1988 c->restoreState();
1928 QTextParag *s = doc->firstParag(); 1989 QTextParagraph *s = doc->firstParagraph();
1929 c->place( pos, s, link ); 1990 c->place( pos, s, link );
1991 updateMicroFocusHint();
1992}
1993
1994
1995void QTextEdit::updateMicroFocusHint()
1996{
1997 QTextCursor c( *cursor );
1998 if ( d->preeditStart != -1 )
1999 c.setIndex( d->preeditStart );
2000
1930 if ( hasFocus() || viewport()->hasFocus() ) { 2001 if ( hasFocus() || viewport()->hasFocus() ) {
1931 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 2002 int h = c.paragraph()->lineHeightOfChar( cursor->index() );
1932 if ( !readonly ) { 2003 if ( !readonly ) {
1933 QFont f = cursor->parag()->at( cursor->index() )->format()->font(); 2004 QFont f = c.paragraph()->at( c.index() )->format()->font();
1934 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), 2005 setMicroFocusHint( c.x() - contentsX() + frameWidth(),
1935 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); 2006 c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1936 } 2007 }
1937 } 2008 }
1938} 2009}
1939 2010
2011
2012
1940void QTextEdit::formatMore() 2013void QTextEdit::formatMore()
1941{ 2014{
1942 if ( !lastFormatted ) 2015 if ( !lastFormatted )
@@ -1944,7 +2017,7 @@ void QTextEdit::formatMore()
1944 2017
1945 int bottom = contentsHeight(); 2018 int bottom = contentsHeight();
1946 int lastBottom = -1; 2019 int lastBottom = -1;
1947 int to = !sender() ? 2 : 20; 2020 int to = 20;
1948 bool firstVisible = FALSE; 2021 bool firstVisible = FALSE;
1949 QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2022 QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
1950 for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) { 2023 for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) {
@@ -1961,10 +2034,14 @@ void QTextEdit::formatMore()
1961 lastBottom = -1; 2034 lastBottom = -1;
1962 } 2035 }
1963 2036
1964 if ( bottom > contentsHeight() ) 2037 if ( bottom > contentsHeight() ) {
1965 resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) ); 2038 resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) );
1966 else if ( lastBottom != -1 && lastBottom < contentsHeight() ) 2039 } else if ( lastBottom != -1 && lastBottom < contentsHeight() ) {
1967 resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) ); 2040 resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) );
2041 if ( contentsHeight() < visibleHeight() )
2042 updateContents( 0, contentsHeight(), visibleWidth(),
2043 visibleHeight() - contentsHeight() );
2044 }
1968 2045
1969 if ( lastFormatted ) 2046 if ( lastFormatted )
1970 formatTimer->start( interval, TRUE ); 2047 formatTimer->start( interval, TRUE );
@@ -1980,7 +2057,7 @@ void QTextEdit::doResize()
1980 resizeContents( 0, 0 ); 2057 resizeContents( 0, 0 );
1981 doc->setWidth( visibleWidth() ); 2058 doc->setWidth( visibleWidth() );
1982 doc->invalidate(); 2059 doc->invalidate();
1983 lastFormatted = doc->firstParag(); 2060 lastFormatted = doc->firstParagraph();
1984 interval = 0; 2061 interval = 0;
1985 formatMore(); 2062 formatMore();
1986 repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE ); 2063 repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE );
@@ -2001,16 +2078,7 @@ bool QTextEdit::eventFilter( QObject *o, QEvent *e )
2001 if ( e->type() == QEvent::FocusIn ) { 2078 if ( e->type() == QEvent::FocusIn ) {
2002 blinkTimer->start( QApplication::cursorFlashTime() / 2 ); 2079 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
2003 drawCursor( TRUE ); 2080 drawCursor( TRUE );
2004 2081 updateMicroFocusHint();
2005 if ( !readonly ) {
2006 // make sure the micro focus hint is updated...
2007 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2008 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2009 cursor->y() + cursor->parag()->rect().y() -
2010 contentsY() + frameWidth(), 0,
2011 cursor->parag()->lineHeightOfChar( cursor->index() ),
2012 TRUE );
2013 }
2014 } else if ( e->type() == QEvent::FocusOut ) { 2082 } else if ( e->type() == QEvent::FocusOut ) {
2015 blinkTimer->stop(); 2083 blinkTimer->stop();
2016 drawCursor( FALSE ); 2084 drawCursor( FALSE );
@@ -2020,14 +2088,14 @@ bool QTextEdit::eventFilter( QObject *o, QEvent *e )
2020 return QScrollView::eventFilter( o, e ); 2088 return QScrollView::eventFilter( o, e );
2021} 2089}
2022 2090
2023/*! 2091/*! Inserts \a text at the current cursor position. If \a indent is
2024 Inserts \a text at the current cursor position. If \a indent is TRUE, 2092 TRUE, the paragraph is re-indented. If \a checkNewLine is TRUE,
2025 the paragraph is re-indented. If \a checkNewLine is TRUE, newline 2093 newline characters in \a text result in hard line breaks (i.e. new
2026 characters in \a text result in hard line breaks (i.e. new 2094 paragraphs). If \a checkNewLine is FALSE and there are newlines in
2027 paragraphs). If \a checkNewLine is FALSE the behaviour of the editor 2095 \a text, the behavior is undefined. If \a checkNewLine is FALSE the
2028 is undefined if the \a text contains newlines. If \a removeSelected is 2096 behaviour of the editor is undefined if the \a text contains
2029 TRUE, any selected text (in selection 0) is removed before the text is 2097 newlines. If \a removeSelected is TRUE, any selected text (in
2030 inserted. 2098 selection 0) is removed before the text is inserted.
2031 2099
2032 \sa paste() pasteSubType() 2100 \sa paste() pasteSubType()
2033*/ 2101*/
@@ -2046,20 +2114,20 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo
2046 if ( undoEnabled && !isReadOnly() ) { 2114 if ( undoEnabled && !isReadOnly() ) {
2047 checkUndoRedoInfo( UndoRedoInfo::Insert ); 2115 checkUndoRedoInfo( UndoRedoInfo::Insert );
2048 if ( !undoRedoInfo.valid() ) { 2116 if ( !undoRedoInfo.valid() ) {
2049 undoRedoInfo.id = cursor->parag()->paragId(); 2117 undoRedoInfo.id = cursor->paragraph()->paragId();
2050 undoRedoInfo.index = cursor->index(); 2118 undoRedoInfo.index = cursor->index();
2051 undoRedoInfo.d->text = QString::null; 2119 undoRedoInfo.d->text = QString::null;
2052 } 2120 }
2053 oldLen = undoRedoInfo.d->text.length(); 2121 oldLen = undoRedoInfo.d->text.length();
2054 } 2122 }
2055 2123
2056 lastFormatted = checkNewLine && cursor->parag()->prev() ? 2124 lastFormatted = checkNewLine && cursor->paragraph()->prev() ?
2057 cursor->parag()->prev() : cursor->parag(); 2125 cursor->paragraph()->prev() : cursor->paragraph();
2058 QTextCursor oldCursor = *cursor; 2126 QTextCursor oldCursor = *cursor;
2059 cursor->insert( txt, checkNewLine ); 2127 cursor->insert( txt, checkNewLine );
2060 if ( doc->useFormatCollection() ) { 2128 if ( doc->useFormatCollection() ) {
2061 doc->setSelectionStart( QTextDocument::Temp, &oldCursor ); 2129 doc->setSelectionStart( QTextDocument::Temp, oldCursor );
2062 doc->setSelectionEnd( QTextDocument::Temp, cursor ); 2130 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
2063 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); 2131 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format );
2064 doc->removeSelection( QTextDocument::Temp ); 2132 doc->removeSelection( QTextDocument::Temp );
2065 } 2133 }
@@ -2075,41 +2143,35 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo
2075 undoRedoInfo.d->text += txt; 2143 undoRedoInfo.d->text += txt;
2076 if ( !doc->preProcessor() ) { 2144 if ( !doc->preProcessor() ) {
2077 for ( int i = 0; i < (int)txt.length(); ++i ) { 2145 for ( int i = 0; i < (int)txt.length(); ++i ) {
2078 if ( txt[ i ] != '\n' && c2.parag()->at( c2.index() )->format() ) { 2146 if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) {
2079 c2.parag()->at( c2.index() )->format()->addRef(); 2147 c2.paragraph()->at( c2.index() )->format()->addRef();
2080 undoRedoInfo.d->text.setFormat( oldLen + i, c2.parag()->at( c2.index() )->format(), TRUE ); 2148 undoRedoInfo.d->text.setFormat( oldLen + i, c2.paragraph()->at( c2.index() )->format(), TRUE );
2081 } 2149 }
2082 c2.gotoNextLetter(); 2150 c2.gotoNextLetter();
2083 } 2151 }
2084 } 2152 }
2085 } 2153 }
2086 2154
2087 setModified();
2088 emit textChanged();
2089 if ( !removeSelected ) { 2155 if ( !removeSelected ) {
2090 doc->setSelectionStart( QTextDocument::Standard, &oldCursor ); 2156 doc->setSelectionStart( QTextDocument::Standard, oldCursor );
2091 doc->setSelectionEnd( QTextDocument::Standard, cursor ); 2157 doc->setSelectionEnd( QTextDocument::Standard, *cursor );
2092 repaintChanged(); 2158 repaintChanged();
2093 } 2159 }
2094 if ( hasFocus() || viewport()->hasFocus() ) { 2160 updateMicroFocusHint();
2095 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 2161 setModified();
2096 if ( !readonly ) { 2162 emit textChanged();
2097 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2098 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2099 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2100 }
2101 }
2102} 2163}
2103 2164
2104/*! Inserts \a text in the paragraph \a para and position \a index */ 2165/*! Inserts \a text in the paragraph \a para and position \a index */
2105 2166
2106void QTextEdit::insertAt( const QString &text, int para, int index ) 2167void QTextEdit::insertAt( const QString &text, int para, int index )
2107{ 2168{
2108 QTextParag *p = doc->paragAt( para ); 2169 removeSelection( QTextDocument::Standard );
2170 QTextParagraph *p = doc->paragAt( para );
2109 if ( !p ) 2171 if ( !p )
2110 return; 2172 return;
2111 QTextCursor tmp = *cursor; 2173 QTextCursor tmp = *cursor;
2112 cursor->setParag( p ); 2174 cursor->setParagraph( p );
2113 cursor->setIndex( index ); 2175 cursor->setIndex( index );
2114 insert( text, FALSE, TRUE, FALSE ); 2176 insert( text, FALSE, TRUE, FALSE );
2115 *cursor = tmp; 2177 *cursor = tmp;
@@ -2122,13 +2184,13 @@ void QTextEdit::insertAt( const QString &text, int para, int index )
2122 2184
2123void QTextEdit::insertParagraph( const QString &text, int para ) 2185void QTextEdit::insertParagraph( const QString &text, int para )
2124{ 2186{
2125 QTextParag *p = doc->paragAt( para ); 2187 QTextParagraph *p = doc->paragAt( para );
2126 if ( p ) { 2188 if ( p ) {
2127 QTextCursor tmp( doc ); 2189 QTextCursor tmp( doc );
2128 tmp.setParag( p ); 2190 tmp.setParagraph( p );
2129 tmp.setIndex( 0 ); 2191 tmp.setIndex( 0 );
2130 tmp.insert( text, TRUE ); 2192 tmp.insert( text, TRUE );
2131 tmp.splitAndInsertEmptyParag(); 2193 tmp.splitAndInsertEmptyParagraph();
2132 repaintChanged(); 2194 repaintChanged();
2133 } else { 2195 } else {
2134 append( text ); 2196 append( text );
@@ -2139,28 +2201,28 @@ void QTextEdit::insertParagraph( const QString &text, int para )
2139 2201
2140void QTextEdit::removeParagraph( int para ) 2202void QTextEdit::removeParagraph( int para )
2141{ 2203{
2142 QTextParag *p = doc->paragAt( para ); 2204 QTextParagraph *p = doc->paragAt( para );
2143 if ( !p ) 2205 if ( !p )
2144 return; 2206 return;
2145 for ( int i = 0; i < doc->numSelections(); ++i ) 2207 for ( int i = 0; i < doc->numSelections(); ++i )
2146 doc->removeSelection( i ); 2208 doc->removeSelection( i );
2147 2209
2148 if ( p == doc->firstParag() && p == doc->lastParag() ) { 2210 if ( p == doc->firstParagraph() && p == doc->lastParagraph() ) {
2149 p->remove( 0, p->length() - 1 ); 2211 p->remove( 0, p->length() - 1 );
2150 repaintChanged(); 2212 repaintChanged();
2151 return; 2213 return;
2152 } 2214 }
2153 drawCursor( FALSE ); 2215 drawCursor( FALSE );
2154 bool resetCursor = cursor->parag() == p; 2216 bool resetCursor = cursor->paragraph() == p;
2155 if ( p->prev() ) 2217 if ( p->prev() )
2156 p->prev()->setNext( p->next() ); 2218 p->prev()->setNext( p->next() );
2157 else 2219 else
2158 doc->setFirstParag( p->next() ); 2220 doc->setFirstParagraph( p->next() );
2159 if ( p->next() ) 2221 if ( p->next() )
2160 p->next()->setPrev( p->prev() ); 2222 p->next()->setPrev( p->prev() );
2161 else 2223 else
2162 doc->setLastParag( p->prev() ); 2224 doc->setLastParagraph( p->prev() );
2163 QTextParag *start = p->next(); 2225 QTextParagraph *start = p->next();
2164 int h = p->rect().height(); 2226 int h = p->rect().height();
2165 delete p; 2227 delete p;
2166 p = start; 2228 p = start;
@@ -2174,7 +2236,7 @@ void QTextEdit::removeParagraph( int para )
2174 } 2236 }
2175 2237
2176 if ( resetCursor ) { 2238 if ( resetCursor ) {
2177 cursor->setParag( doc->firstParag() ); 2239 cursor->setParagraph( doc->firstParagraph() );
2178 cursor->setIndex( 0 ); 2240 cursor->setIndex( 0 );
2179 } 2241 }
2180 repaintChanged(); 2242 repaintChanged();
@@ -2217,16 +2279,9 @@ void QTextEdit::undo()
2217 ensureCursorVisible(); 2279 ensureCursorVisible();
2218 repaintChanged(); 2280 repaintChanged();
2219 drawCursor( TRUE ); 2281 drawCursor( TRUE );
2282 updateMicroFocusHint();
2220 setModified(); 2283 setModified();
2221 emit textChanged(); 2284 emit textChanged();
2222 if ( hasFocus() || viewport()->hasFocus() ) {
2223 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2224 if ( !readonly ) {
2225 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2226 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2227 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2228 }
2229 }
2230} 2285}
2231 2286
2232/*! 2287/*!
@@ -2262,16 +2317,9 @@ void QTextEdit::redo()
2262 repaintChanged(); 2317 repaintChanged();
2263 ensureCursorVisible(); 2318 ensureCursorVisible();
2264 drawCursor( TRUE ); 2319 drawCursor( TRUE );
2320 updateMicroFocusHint();
2265 setModified(); 2321 setModified();
2266 emit textChanged(); 2322 emit textChanged();
2267 if ( hasFocus() || viewport()->hasFocus() ) {
2268 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2269 if ( !readonly ) {
2270 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2271 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2272 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2273 }
2274 }
2275} 2323}
2276 2324
2277/*! 2325/*!
@@ -2289,14 +2337,7 @@ void QTextEdit::paste()
2289 if ( isReadOnly() ) 2337 if ( isReadOnly() )
2290 return; 2338 return;
2291 pasteSubType( "plain" ); 2339 pasteSubType( "plain" );
2292 if ( hasFocus() || viewport()->hasFocus() ) { 2340 updateMicroFocusHint();
2293 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2294 if ( !readonly ) {
2295 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2296 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2297 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2298 }
2299 }
2300#endif 2341#endif
2301} 2342}
2302 2343
@@ -2337,18 +2378,13 @@ void QTextEdit::cut()
2337 if ( isReadOnly() ) 2378 if ( isReadOnly() )
2338 return; 2379 return;
2339 2380
2340 if ( doc->hasSelection( QTextDocument::Standard ) ) { 2381 QString t;
2341 doc->copySelectedText( QTextDocument::Standard ); 2382 if ( doc->hasSelection( QTextDocument::Standard ) &&
2383 !( t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ) ).isEmpty() ) {
2384 QApplication::clipboard()->setText( t );
2342 removeSelectedText(); 2385 removeSelectedText();
2343 } 2386 }
2344 if ( hasFocus() || viewport()->hasFocus() ) { 2387 updateMicroFocusHint();
2345 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2346 if ( !readonly ) {
2347 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2348 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2349 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2350 }
2351 }
2352} 2388}
2353 2389
2354/*! Copies any selected text (from selection 0) to the clipboard. 2390/*! Copies any selected text (from selection 0) to the clipboard.
@@ -2358,8 +2394,10 @@ void QTextEdit::cut()
2358 2394
2359void QTextEdit::copy() 2395void QTextEdit::copy()
2360{ 2396{
2361 if ( !doc->selectedText( QTextDocument::Standard ).isEmpty() ) 2397 QString t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy );
2362 doc->copySelectedText( QTextDocument::Standard ); 2398 if ( doc->hasSelection( QTextDocument::Standard ) &&
2399 !t.isEmpty() && t.simplifyWhiteSpace() != "<selstart/>" )
2400 QApplication::clipboard()->setText( t );
2363} 2401}
2364 2402
2365/*! 2403/*!
@@ -2412,17 +2450,17 @@ void QTextEdit::setFormat( QTextFormat *f, int flags )
2412{ 2450{
2413 if ( doc->hasSelection( QTextDocument::Standard ) ) { 2451 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2414 drawCursor( FALSE ); 2452 drawCursor( FALSE );
2415 QString str = doc->selectedText( QTextDocument::Standard );
2416 QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard ); 2453 QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard );
2454 c1.restoreState();
2417 QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard ); 2455 QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard );
2456 c2.restoreState();
2418 clearUndoRedo(); 2457 clearUndoRedo();
2419 undoRedoInfo.type = UndoRedoInfo::Format; 2458 undoRedoInfo.type = UndoRedoInfo::Format;
2420 undoRedoInfo.id = c1.parag()->paragId(); 2459 undoRedoInfo.id = c1.paragraph()->paragId();
2421 undoRedoInfo.index = c1.index(); 2460 undoRedoInfo.index = c1.index();
2422 undoRedoInfo.eid = c2.parag()->paragId(); 2461 undoRedoInfo.eid = c2.paragraph()->paragId();
2423 undoRedoInfo.eindex = c2.index(); 2462 undoRedoInfo.eindex = c2.index();
2424 undoRedoInfo.d->text = str; 2463 readFormats( c1, c2, undoRedoInfo.d->text );
2425 readFormats( c1, c2, 0, undoRedoInfo.d->text );
2426 undoRedoInfo.format = f; 2464 undoRedoInfo.format = f;
2427 undoRedoInfo.flags = flags; 2465 undoRedoInfo.flags = flags;
2428 clearUndoRedo(); 2466 clearUndoRedo();
@@ -2443,12 +2481,12 @@ void QTextEdit::setFormat( QTextFormat *f, int flags )
2443 emit currentFontChanged( currentFormat->font() ); 2481 emit currentFontChanged( currentFormat->font() );
2444 emit currentColorChanged( currentFormat->color() ); 2482 emit currentColorChanged( currentFormat->color() );
2445 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 2483 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
2446 if ( cursor->index() == cursor->parag()->length() - 1 ) { 2484 if ( cursor->index() == cursor->paragraph()->length() - 1 ) {
2447 currentFormat->addRef(); 2485 currentFormat->addRef();
2448 cursor->parag()->string()->setFormat( cursor->index(), currentFormat, TRUE ); 2486 cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE );
2449 if ( cursor->parag()->length() == 1 ) { 2487 if ( cursor->paragraph()->length() == 1 ) {
2450 cursor->parag()->invalidate( 0 ); 2488 cursor->paragraph()->invalidate( 0 );
2451 cursor->parag()->format(); 2489 cursor->paragraph()->format();
2452 repaintChanged(); 2490 repaintChanged();
2453 } 2491 }
2454 } 2492 }
@@ -2467,7 +2505,12 @@ void QTextEdit::setPalette( const QPalette &p )
2467 } 2505 }
2468} 2506}
2469 2507
2470/*! 2508/*! \internal
2509
2510 \warning In Qt 3.1 we will provide a cleaer API for the
2511 functionality which is provided by this function and in Qt 4.0 this
2512 function will go away.
2513
2471 Sets the paragraph style of the current paragraph 2514 Sets the paragraph style of the current paragraph
2472 to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the 2515 to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the
2473 type of the list item is set to \a listStyle. 2516 type of the list item is set to \a listStyle.
@@ -2481,49 +2524,37 @@ void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::
2481 return; 2524 return;
2482 2525
2483 drawCursor( FALSE ); 2526 drawCursor( FALSE );
2484 if ( !doc->hasSelection( QTextDocument::Standard ) ) { 2527 QTextParagraph *start = cursor->paragraph();
2485 clearUndoRedo(); 2528 QTextParagraph *end = start;
2486 undoRedoInfo.type = UndoRedoInfo::ParagType; 2529 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2487 QValueList< QPtrVector<QStyleSheetItem> > oldStyles; 2530 start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph();
2488 undoRedoInfo.oldStyles.clear(); 2531 end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph();
2489 undoRedoInfo.oldStyles << cursor->parag()->styleSheetItems(); 2532 if ( end->paragId() < start->paragId() )
2490 undoRedoInfo.oldListStyles.clear(); 2533 return; // do not trust our selections
2491 undoRedoInfo.oldListStyles << cursor->parag()->listStyle(); 2534 }
2492 undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; 2535
2493 undoRedoInfo.listStyle = listStyle; 2536 clearUndoRedo();
2494 undoRedoInfo.id = cursor->parag()->paragId(); 2537 undoRedoInfo.type = UndoRedoInfo::Style;
2495 undoRedoInfo.eid = cursor->parag()->paragId(); 2538 undoRedoInfo.id = start->paragId();
2496 undoRedoInfo.d->text = " "; 2539 undoRedoInfo.eid = end->paragId();
2497 undoRedoInfo.index = 1; 2540 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
2498 clearUndoRedo(); 2541
2499 cursor->parag()->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); 2542 while ( start != end->next() ) {
2500 repaintChanged(); 2543 start->setListStyle( listStyle );
2501 } else { 2544 if ( dm == QStyleSheetItem::DisplayListItem ) {
2502 QTextParag *start = doc->selectionStart( QTextDocument::Standard ); 2545 start->setListItem( TRUE );
2503 QTextParag *end = doc->selectionEnd( QTextDocument::Standard ); 2546 if( start->listDepth() == 0 )
2504 lastFormatted = start; 2547 start->setListDepth( 1 );
2505 clearUndoRedo(); 2548 } else if ( start->isListItem() ) {
2506 undoRedoInfo.type = UndoRedoInfo::ParagType; 2549 start->setListItem( FALSE );
2507 undoRedoInfo.id = start->paragId(); 2550 start->setListDepth( QMAX( start->listDepth()-1, 0 ) );
2508 undoRedoInfo.eid = end->paragId();
2509 undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem;
2510 undoRedoInfo.listStyle = listStyle;
2511 undoRedoInfo.oldStyles.clear();
2512 undoRedoInfo.oldListStyles.clear();
2513 while ( start ) {
2514 undoRedoInfo.oldStyles << start->styleSheetItems();
2515 undoRedoInfo.oldListStyles << start->listStyle();
2516 start->setList( dm == QStyleSheetItem::DisplayListItem, listStyle );
2517 if ( start == end )
2518 break;
2519 start = start->next();
2520 } 2551 }
2521 undoRedoInfo.d->text = " "; 2552 start = start->next();
2522 undoRedoInfo.index = 1;
2523 clearUndoRedo();
2524 repaintChanged();
2525 formatMore();
2526 } 2553 }
2554
2555 clearUndoRedo();
2556 repaintChanged();
2557 formatMore();
2527 drawCursor( TRUE ); 2558 drawCursor( TRUE );
2528 setModified(); 2559 setModified();
2529 emit textChanged(); 2560 emit textChanged();
@@ -2534,7 +2565,6 @@ void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::
2534 are \c Qt::AlignLeft, \c Qt::AlignRight, Qt::AlignJustify and 2565 are \c Qt::AlignLeft, \c Qt::AlignRight, Qt::AlignJustify and
2535 Qt::AlignCenter (which centers horizontally). 2566 Qt::AlignCenter (which centers horizontally).
2536 2567
2537 \sa setParagType()
2538*/ 2568*/
2539 2569
2540void QTextEdit::setAlignment( int a ) 2570void QTextEdit::setAlignment( int a )
@@ -2543,50 +2573,29 @@ void QTextEdit::setAlignment( int a )
2543 return; 2573 return;
2544 2574
2545 drawCursor( FALSE ); 2575 drawCursor( FALSE );
2546 if ( !doc->hasSelection( QTextDocument::Standard ) ) { 2576 QTextParagraph *start = cursor->paragraph();
2547 if ( cursor->parag()->alignment() != a ) { 2577 QTextParagraph *end = start;
2548 clearUndoRedo(); 2578 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2549 undoRedoInfo.type = UndoRedoInfo::Alignment; 2579 start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph();
2550 QMemArray<int> oa( 1 ); 2580 end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph();
2551 oa[ 0 ] = cursor->parag()->alignment(); 2581 if ( end->paragId() < start->paragId() )
2552 undoRedoInfo.oldAligns = oa; 2582 return; // do not trust our selections
2553 undoRedoInfo.newAlign = a;
2554 undoRedoInfo.id = cursor->parag()->paragId();
2555 undoRedoInfo.eid = cursor->parag()->paragId();
2556 undoRedoInfo.d->text = " ";
2557 undoRedoInfo.index = 1;
2558 clearUndoRedo();
2559 cursor->parag()->setAlignment( a );
2560 repaintChanged();
2561 }
2562 } else {
2563 QTextParag *start = doc->selectionStart( QTextDocument::Standard );
2564 QTextParag *end = doc->selectionEnd( QTextDocument::Standard );
2565 lastFormatted = start;
2566 int len = end->paragId() - start->paragId() + 1;
2567 clearUndoRedo();
2568 undoRedoInfo.type = UndoRedoInfo::Alignment;
2569 undoRedoInfo.id = start->paragId();
2570 undoRedoInfo.eid = end->paragId();
2571 QMemArray<int> oa( QMAX( 0, len ) );
2572 int i = 0;
2573 while ( start ) {
2574 if ( i < (int)oa.size() )
2575 oa[ i ] = start->alignment();
2576 start->setAlignment( a );
2577 if ( start == end )
2578 break;
2579 start = start->next();
2580 ++i;
2581 }
2582 undoRedoInfo.oldAligns = oa;
2583 undoRedoInfo.newAlign = a;
2584 undoRedoInfo.d->text = " ";
2585 undoRedoInfo.index = 1;
2586 clearUndoRedo();
2587 repaintChanged();
2588 formatMore();
2589 } 2583 }
2584
2585 clearUndoRedo();
2586 undoRedoInfo.type = UndoRedoInfo::Style;
2587 undoRedoInfo.id = start->paragId();
2588 undoRedoInfo.eid = end->paragId();
2589 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
2590
2591 while ( start != end->next() ) {
2592 start->setAlignment( a );
2593 start = start->next();
2594 }
2595
2596 clearUndoRedo();
2597 repaintChanged();
2598 formatMore();
2590 drawCursor( TRUE ); 2599 drawCursor( TRUE );
2591 if ( currentAlignment != a ) { 2600 if ( currentAlignment != a ) {
2592 currentAlignment = a; 2601 currentAlignment = a;
@@ -2602,10 +2611,10 @@ void QTextEdit::updateCurrentFormat()
2602 if ( i > 0 ) 2611 if ( i > 0 )
2603 --i; 2612 --i;
2604 if ( doc->useFormatCollection() && 2613 if ( doc->useFormatCollection() &&
2605 ( !currentFormat || currentFormat->key() != cursor->parag()->at( i )->format()->key() ) ) { 2614 ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) {
2606 if ( currentFormat ) 2615 if ( currentFormat )
2607 currentFormat->removeRef(); 2616 currentFormat->removeRef();
2608 currentFormat = doc->formatCollection()->format( cursor->parag()->at( i )->format() ); 2617 currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() );
2609 if ( currentFormat->isMisspelled() ) { 2618 if ( currentFormat->isMisspelled() ) {
2610 currentFormat->removeRef(); 2619 currentFormat->removeRef();
2611 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); 2620 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
@@ -2615,8 +2624,8 @@ void QTextEdit::updateCurrentFormat()
2615 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 2624 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
2616 } 2625 }
2617 2626
2618 if ( currentAlignment != cursor->parag()->alignment() ) { 2627 if ( currentAlignment != cursor->paragraph()->alignment() ) {
2619 currentAlignment = cursor->parag()->alignment(); 2628 currentAlignment = cursor->paragraph()->alignment();
2620 block_set_alignment = TRUE; 2629 block_set_alignment = TRUE;
2621 emit currentAlignmentChanged( currentAlignment ); 2630 emit currentAlignmentChanged( currentAlignment );
2622 block_set_alignment = FALSE; 2631 block_set_alignment = FALSE;
@@ -2778,7 +2787,8 @@ QString QTextEdit::text( int para ) const
2778 2787
2779void QTextEdit::setText( const QString &text, const QString &context ) 2788void QTextEdit::setText( const QString &text, const QString &context )
2780{ 2789{
2781 if ( !isModified() && this->context() == context && this->text() == text ) 2790 if ( !isModified() && isReadOnly() &&
2791 this->context() == context && this->text() == text )
2782 return; 2792 return;
2783 2793
2784 emit undoAvailable( FALSE ); 2794 emit undoAvailable( FALSE );
@@ -2799,10 +2809,9 @@ void QTextEdit::setText( const QString &text, const QString &context )
2799 resizeContents( 0, 0 ); 2809 resizeContents( 0, 0 );
2800 } 2810 }
2801 2811
2802 cursor->setDocument( doc ); 2812 lastFormatted = doc->firstParagraph();
2803 lastFormatted = doc->firstParag(); 2813 delete cursor;
2804 cursor->setParag( doc->firstParag() ); 2814 cursor = new QTextCursor( doc );
2805 cursor->setIndex( 0 );
2806 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2815 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
2807 2816
2808 if ( isModified() ) 2817 if ( isModified() )
@@ -2810,6 +2819,7 @@ void QTextEdit::setText( const QString &text, const QString &context )
2810 emit textChanged(); 2819 emit textChanged();
2811 formatMore(); 2820 formatMore();
2812 updateCurrentFormat(); 2821 updateCurrentFormat();
2822 d->scrollToAnchor = QString::null;
2813} 2823}
2814 2824
2815/*! 2825/*!
@@ -2847,9 +2857,9 @@ void QTextEdit::setText( const QString &text, const QString &context )
2847 \a expr is found; otherwise returns FALSE. 2857 \a expr is found; otherwise returns FALSE.
2848 2858
2849 If \a para and \a index are both null the search begins from the 2859 If \a para and \a index are both null the search begins from the
2850 start of the text. If \a para and \a index are both not null, the 2860 current cursor position. If \a para and \a index are both not
2851 search begins from the \e *\a index character position in the \e 2861 null, the search begins from the \e *\a index character position
2852 *\a para paragraph. 2862 in the \e *\a para paragraph.
2853 2863
2854 If \a cs is TRUE the search is case sensitive, otherwise it is 2864 If \a cs is TRUE the search is case sensitive, otherwise it is
2855 case insensitive. If \a wo is TRUE the search looks for whole word 2865 case insensitive. If \a wo is TRUE the search looks for whole word
@@ -2873,14 +2883,34 @@ bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward,
2873 int *para, int *index ) 2883 int *para, int *index )
2874{ 2884{
2875 drawCursor( FALSE ); 2885 drawCursor( FALSE );
2876 doc->removeSelection( QTextDocument::Standard );
2877#ifndef QT_NO_CURSOR 2886#ifndef QT_NO_CURSOR
2878 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 2887 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
2879#endif 2888#endif
2880 bool found = doc->find( expr, cs, wo, forward, para, index, cursor ); 2889 QTextCursor findcur = *cursor;
2881 ensureCursorVisible(); 2890 if ( para && index ) {
2891 if ( doc->paragAt( *para ) )
2892 findcur.gotoPosition( doc->paragAt(*para), *index );
2893 else
2894 findcur.gotoEnd();
2895 } else if ( doc->hasSelection( QTextDocument::Standard ) ){
2896 // maks sure we do not find the same selection again
2897 if ( forward )
2898 findcur.gotoNextLetter();
2899 else
2900 findcur.gotoPreviousLetter();
2901 }
2902 removeSelection( QTextDocument::Standard );
2903 bool found = doc->find( findcur, expr, cs, wo, forward );
2904 if ( found ) {
2905 if ( para )
2906 *para = findcur.paragraph()->paragId();
2907 if ( index )
2908 *index = findcur.index();
2909 *cursor = findcur;
2910 repaintChanged();
2911 ensureCursorVisible();
2912 }
2882 drawCursor( TRUE ); 2913 drawCursor( TRUE );
2883 repaintChanged();
2884 return found; 2914 return found;
2885} 2915}
2886 2916
@@ -2902,7 +2932,7 @@ void QTextEdit::blinkCursor()
2902 2932
2903void QTextEdit::setCursorPosition( int para, int index ) 2933void QTextEdit::setCursorPosition( int para, int index )
2904{ 2934{
2905 QTextParag *p = doc->paragAt( para ); 2935 QTextParagraph *p = doc->paragAt( para );
2906 if ( !p ) 2936 if ( !p )
2907 return; 2937 return;
2908 2938
@@ -2910,12 +2940,13 @@ void QTextEdit::setCursorPosition( int para, int index )
2910 index = p->length() - 1; 2940 index = p->length() - 1;
2911 2941
2912 drawCursor( FALSE ); 2942 drawCursor( FALSE );
2913 cursor->setParag( p ); 2943 cursor->setParagraph( p );
2914 cursor->setIndex( index ); 2944 cursor->setIndex( index );
2915 ensureCursorVisible(); 2945 ensureCursorVisible();
2916 drawCursor( TRUE ); 2946 drawCursor( TRUE );
2947 updateCurrentFormat();
2917 emit cursorPositionChanged( cursor ); 2948 emit cursorPositionChanged( cursor );
2918 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 2949 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
2919} 2950}
2920 2951
2921/*! 2952/*!
@@ -2930,7 +2961,7 @@ void QTextEdit::getCursorPosition( int *para, int *index ) const
2930{ 2961{
2931 if ( !para || !index ) 2962 if ( !para || !index )
2932 return; 2963 return;
2933 *para = cursor->parag()->paragId(); 2964 *para = cursor->paragraph()->paragId();
2934 *index = cursor->index(); 2965 *index = cursor->index();
2935} 2966}
2936 2967
@@ -2958,10 +2989,10 @@ void QTextEdit::setSelection( int paraFrom, int indexFrom,
2958 } 2989 }
2959 if ( selNum > doc->numSelections() - 1 ) 2990 if ( selNum > doc->numSelections() - 1 )
2960 doc->addSelection( selNum ); 2991 doc->addSelection( selNum );
2961 QTextParag *p1 = doc->paragAt( paraFrom ); 2992 QTextParagraph *p1 = doc->paragAt( paraFrom );
2962 if ( !p1 ) 2993 if ( !p1 )
2963 return; 2994 return;
2964 QTextParag *p2 = doc->paragAt( paraTo ); 2995 QTextParagraph *p2 = doc->paragAt( paraTo );
2965 if ( !p2 ) 2996 if ( !p2 )
2966 return; 2997 return;
2967 2998
@@ -2973,12 +3004,12 @@ void QTextEdit::setSelection( int paraFrom, int indexFrom,
2973 drawCursor( FALSE ); 3004 drawCursor( FALSE );
2974 QTextCursor c = *cursor; 3005 QTextCursor c = *cursor;
2975 QTextCursor oldCursor = *cursor; 3006 QTextCursor oldCursor = *cursor;
2976 c.setParag( p1 ); 3007 c.setParagraph( p1 );
2977 c.setIndex( indexFrom ); 3008 c.setIndex( indexFrom );
2978 cursor->setParag( p2 ); 3009 cursor->setParagraph( p2 );
2979 cursor->setIndex( indexTo ); 3010 cursor->setIndex( indexTo );
2980 doc->setSelectionStart( selNum, &c ); 3011 doc->setSelectionStart( selNum, c );
2981 doc->setSelectionEnd( selNum, cursor ); 3012 doc->setSelectionEnd( selNum, *cursor );
2982 repaintChanged(); 3013 repaintChanged();
2983 ensureCursorVisible(); 3014 ensureCursorVisible();
2984 if ( selNum != QTextDocument::Standard ) 3015 if ( selNum != QTextDocument::Standard )
@@ -3056,7 +3087,7 @@ Qt::TextFormat QTextEdit::textFormat() const
3056 3087
3057int QTextEdit::paragraphs() const 3088int QTextEdit::paragraphs() const
3058{ 3089{
3059 return doc->lastParag()->paragId() + 1; 3090 return doc->lastParagraph()->paragId() + 1;
3060} 3091}
3061 3092
3062/*! 3093/*!
@@ -3066,7 +3097,7 @@ int QTextEdit::paragraphs() const
3066 3097
3067int QTextEdit::linesOfParagraph( int para ) const 3098int QTextEdit::linesOfParagraph( int para ) const
3068{ 3099{
3069 QTextParag *p = doc->paragAt( para ); 3100 QTextParagraph *p = doc->paragAt( para );
3070 if ( !p ) 3101 if ( !p )
3071 return -1; 3102 return -1;
3072 return p->lines(); 3103 return p->lines();
@@ -3079,7 +3110,7 @@ int QTextEdit::linesOfParagraph( int para ) const
3079 3110
3080int QTextEdit::paragraphLength( int para ) const 3111int QTextEdit::paragraphLength( int para ) const
3081{ 3112{
3082 QTextParag *p = doc->paragAt( para ); 3113 QTextParagraph *p = doc->paragAt( para );
3083 if ( !p ) 3114 if ( !p )
3084 return -1; 3115 return -1;
3085 return p->length() - 1; 3116 return p->length() - 1;
@@ -3095,7 +3126,7 @@ int QTextEdit::paragraphLength( int para ) const
3095 3126
3096int QTextEdit::lines() const 3127int QTextEdit::lines() const
3097{ 3128{
3098 QTextParag *p = doc->firstParag(); 3129 QTextParagraph *p = doc->firstParagraph();
3099 int l = 0; 3130 int l = 0;
3100 while ( p ) { 3131 while ( p ) {
3101 l += p->lines(); 3132 l += p->lines();
@@ -3115,7 +3146,7 @@ int QTextEdit::lines() const
3115 3146
3116int QTextEdit::lineOfChar( int para, int index ) 3147int QTextEdit::lineOfChar( int para, int index )
3117{ 3148{
3118 QTextParag *p = doc->paragAt( para ); 3149 QTextParagraph *p = doc->paragAt( para );
3119 if ( !p ) 3150 if ( !p )
3120 return -1; 3151 return -1;
3121 3152
@@ -3248,7 +3279,7 @@ void QTextEdit::startDrag()
3248#ifndef QT_NO_DRAGANDDROP 3279#ifndef QT_NO_DRAGANDDROP
3249 mousePressed = FALSE; 3280 mousePressed = FALSE;
3250 inDoubleClick = FALSE; 3281 inDoubleClick = FALSE;
3251 QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard ), viewport() ); 3282 QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ), viewport() );
3252 if ( isReadOnly() ) { 3283 if ( isReadOnly() ) {
3253 drag->dragCopy(); 3284 drag->dragCopy();
3254 } else { 3285 } else {
@@ -3285,22 +3316,20 @@ void QTextEdit::UndoRedoInfo::clear()
3285{ 3316{
3286 if ( valid() ) { 3317 if ( valid() ) {
3287 if ( type == Insert || type == Return ) 3318 if ( type == Insert || type == Return )
3288 doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); 3319 doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) );
3289 else if ( type == Format ) 3320 else if ( type == Format )
3290 doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); 3321 doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) );
3291 else if ( type == Alignment ) 3322 else if ( type == Style )
3292 doc->addCommand( new QTextAlignmentCommand( doc, id, eid, newAlign, oldAligns ) ); 3323 doc->addCommand( new QTextStyleCommand( doc, id, eid, styleInformation ) );
3293 else if ( type == ParagType ) 3324 else if ( type != Invalid ) {
3294 doc->addCommand( new QTextParagTypeCommand( doc, id, eid, list, listStyle, oldStyles, oldListStyles ) ); 3325 doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) );
3295 else if ( type != Invalid ) 3326 }
3296 doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) );
3297 } 3327 }
3328 type = Invalid;
3298 d->text = QString::null; 3329 d->text = QString::null;
3299 id = -1; 3330 id = -1;
3300 index = -1; 3331 index = -1;
3301 oldStyles.clear(); 3332 styleInformation = QByteArray();
3302 oldListStyles.clear();
3303 oldAligns.resize( 0 );
3304} 3333}
3305 3334
3306 3335
@@ -3340,7 +3369,7 @@ QTextEdit::UndoRedoInfo::~UndoRedoInfo()
3340 3369
3341bool QTextEdit::UndoRedoInfo::valid() const 3370bool QTextEdit::UndoRedoInfo::valid() const
3342{ 3371{
3343 return d->text.length() > 0 && id >= 0 && index >= 0; 3372 return id >= 0 && type != Invalid;
3344} 3373}
3345 3374
3346/*! 3375/*!
@@ -3409,10 +3438,7 @@ QBrush QTextEdit::paper() const
3409 3438
3410void QTextEdit::setLinkUnderline( bool b ) 3439void QTextEdit::setLinkUnderline( bool b )
3411{ 3440{
3412 if ( b == doc->underlineLinks() )
3413 return;
3414 doc->setUnderlineLinks( b ); 3441 doc->setUnderlineLinks( b );
3415 updateStyles();
3416} 3442}
3417 3443
3418bool QTextEdit::linkUnderline() const 3444bool QTextEdit::linkUnderline() const
@@ -3465,10 +3491,9 @@ int QTextEdit::heightForWidth( int w ) const
3465void QTextEdit::append( const QString &text ) 3491void QTextEdit::append( const QString &text )
3466{ 3492{
3467 // flush and clear the undo/redo stack if necessary 3493 // flush and clear the undo/redo stack if necessary
3468 if ( isReadOnly() && undoRedoInfo.valid() ) { 3494 undoRedoInfo.clear();
3469 undoRedoInfo.clear(); 3495 doc->commands()->clear();
3470 doc->commands()->clear(); 3496
3471 }
3472 doc->removeSelection( QTextDocument::Standard ); 3497 doc->removeSelection( QTextDocument::Standard );
3473 TextFormat f = doc->textFormat(); 3498 TextFormat f = doc->textFormat();
3474 if ( f == AutoText ) { 3499 if ( f == AutoText ) {
@@ -3477,35 +3502,37 @@ void QTextEdit::append( const QString &text )
3477 else 3502 else
3478 f = PlainText; 3503 f = PlainText;
3479 } 3504 }
3480 if ( f == PlainText ) { 3505
3481 QTextCursor oldc( *cursor ); 3506 drawCursor( FALSE );
3482 ensureFormatted( doc->lastParag() ); 3507 QTextCursor oldc( *cursor );
3483 bool scrollToEnd = contentsY() >= contentsHeight() - visibleHeight() - 3508 ensureFormatted( doc->lastParagraph() );
3484 ( horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0 ); 3509 bool atBottom = contentsY() >= contentsHeight() - visibleHeight();
3485 if ( !scrollToEnd ) 3510 cursor->gotoEnd();
3486 blockEnsureCursorVisible = TRUE; 3511 if ( cursor->index() > 0 )
3487 cursor->gotoEnd(); 3512 cursor->splitAndInsertEmptyParagraph();
3488 if ( cursor->index() > 0 ) 3513 QTextCursor oldCursor2 = *cursor;
3489 cursor->splitAndInsertEmptyParag(); 3514
3490 QTextCursor oldCursor2 = *cursor; 3515 if ( f == Qt::PlainText ) {
3491 cursor->insert( text, TRUE ); 3516 cursor->insert( text, TRUE );
3492 if ( doc->useFormatCollection() && currentFormat != cursor->parag()->at( cursor->index() )->format() ) { 3517 if ( doc->useFormatCollection() &&
3493 doc->setSelectionStart( QTextDocument::Temp, &oldCursor2 ); 3518 currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) {
3494 doc->setSelectionEnd( QTextDocument::Temp, cursor ); 3519 doc->setSelectionStart( QTextDocument::Temp, oldCursor2 );
3520 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
3495 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); 3521 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format );
3496 doc->removeSelection( QTextDocument::Temp ); 3522 doc->removeSelection( QTextDocument::Temp );
3497 } 3523 }
3498 formatMore(); 3524 } else {
3499 repaintChanged(); 3525 if ( cursor->paragraph()->prev() )
3500 ensureCursorVisible(); 3526 cursor->paragraph()->prev()->invalidate(0); // vertical margins might have to change
3501 drawCursor( TRUE );
3502 *cursor = oldc;
3503 if ( !scrollToEnd )
3504 blockEnsureCursorVisible = FALSE;
3505 } else if ( f == RichText ) {
3506 doc->setRichTextInternal( text ); 3527 doc->setRichTextInternal( text );
3507 repaintChanged();
3508 } 3528 }
3529 formatMore();
3530 repaintChanged();
3531 if ( atBottom )
3532 scrollToBottom();
3533 *cursor = oldc;
3534 if ( !isReadOnly() )
3535 cursorVisible = TRUE;
3509 setModified(); 3536 setModified();
3510 emit textChanged(); 3537 emit textChanged();
3511} 3538}
@@ -3617,7 +3644,7 @@ QString QTextEdit::documentTitle() const
3617 return doc->attributes()[ "title" ]; 3644 return doc->attributes()[ "title" ];
3618} 3645}
3619 3646
3620void QTextEdit::makeParagVisible( QTextParag *p ) 3647void QTextEdit::makeParagVisible( QTextParagraph *p )
3621{ 3648{
3622 setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) ); 3649 setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) );
3623} 3650}
@@ -3630,23 +3657,29 @@ void QTextEdit::makeParagVisible( QTextParag *p )
3630 3657
3631void QTextEdit::scrollToAnchor( const QString& name ) 3658void QTextEdit::scrollToAnchor( const QString& name )
3632{ 3659{
3660 if ( !isVisible() ) {
3661 d->scrollToAnchor = name;
3662 return;
3663 }
3633 if ( name.isEmpty() ) 3664 if ( name.isEmpty() )
3634 return; 3665 return;
3635 sync(); 3666 sync();
3636 QTextCursor cursor( doc ); 3667 QTextCursor cursor( doc );
3637 QTextParag* last = doc->lastParag(); 3668 QTextParagraph* last = doc->lastParagraph();
3638 do { 3669 for (;;) {
3639 QTextStringChar* c = cursor.parag()->at( cursor.index() ); 3670 QTextStringChar* c = cursor.paragraph()->at( cursor.index() );
3640 if( c->isAnchor() ) { 3671 if( c->isAnchor() ) {
3641 QString a = c->anchorName(); 3672 QString a = c->anchorName();
3642 if ( a == name || 3673 if ( a == name ||
3643 (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) { 3674 (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) {
3644 setContentsPos( contentsX(), QMIN( cursor.parag()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); 3675 setContentsPos( contentsX(), QMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) );
3645 return; 3676 break;
3646 } 3677 }
3647 } 3678 }
3679 if ( cursor.paragraph() == last && cursor.atParagEnd() )
3680 break;
3648 cursor.gotoNextLetter(); 3681 cursor.gotoNextLetter();
3649 } while( cursor.parag() != last || !cursor.atParagEnd() ); 3682 }
3650} 3683}
3651 3684
3652/*! If there is an anchor at position \a pos (in contents 3685/*! If there is an anchor at position \a pos (in contents
@@ -3658,7 +3691,7 @@ QString QTextEdit::anchorAt( const QPoint& pos )
3658{ 3691{
3659 QTextCursor c( doc ); 3692 QTextCursor c( doc );
3660 placeCursor( pos, &c ); 3693 placeCursor( pos, &c );
3661 return c.parag()->at( c.index() )->anchorHref(); 3694 return c.paragraph()->at( c.index() )->anchorHref();
3662} 3695}
3663 3696
3664void QTextEdit::documentWidthChanged( int w ) 3697void QTextEdit::documentWidthChanged( int w )
@@ -3666,15 +3699,13 @@ void QTextEdit::documentWidthChanged( int w )
3666 resizeContents( QMAX( visibleWidth(), w), contentsHeight() ); 3699 resizeContents( QMAX( visibleWidth(), w), contentsHeight() );
3667} 3700}
3668 3701
3669/*! 3702/*! \internal
3670 Updates all the rendering styles used to display the text. You will 3703
3671 probably want to call this function after calling setStyleSheet(). 3704 This function does nothing
3672*/ 3705*/
3673 3706
3674void QTextEdit::updateStyles() 3707void QTextEdit::updateStyles()
3675{ 3708{
3676 doc->updateStyles();
3677 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3678} 3709}
3679 3710
3680void QTextEdit::setDocument( QTextDocument *dc ) 3711void QTextEdit::setDocument( QTextDocument *dc )
@@ -3682,8 +3713,10 @@ void QTextEdit::setDocument( QTextDocument *dc )
3682 if ( dc == doc ) 3713 if ( dc == doc )
3683 return; 3714 return;
3684 doc = dc; 3715 doc = dc;
3685 cursor->setDocument( doc ); 3716 delete cursor;
3717 cursor = new QTextCursor( doc );
3686 clearUndoRedo(); 3718 clearUndoRedo();
3719 undoRedoInfo.doc = doc;
3687 lastFormatted = 0; 3720 lastFormatted = 0;
3688} 3721}
3689 3722
@@ -3703,7 +3736,52 @@ void QTextEdit::pasteSubType( const QCString& subtype )
3703{ 3736{
3704 QCString st = subtype; 3737 QCString st = subtype;
3705 QString t = QApplication::clipboard()->text(st); 3738 QString t = QApplication::clipboard()->text(st);
3739 if ( doc->hasSelection( QTextDocument::Standard ) )
3740 removeSelectedText();
3706 if ( !t.isEmpty() ) { 3741 if ( !t.isEmpty() ) {
3742 if ( t.startsWith( "<selstart/>" ) ) {
3743 t.remove( 0, 11 );
3744 QTextCursor oldC = *cursor;
3745 lastFormatted = cursor->paragraph();
3746 if ( lastFormatted->prev() )
3747 lastFormatted = lastFormatted->prev();
3748 doc->setRichTextInternal( t, cursor );
3749
3750 if ( undoEnabled && !isReadOnly() ) {
3751 doc->setSelectionStart( QTextDocument::Temp, oldC );
3752 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
3753
3754 checkUndoRedoInfo( UndoRedoInfo::Insert );
3755 if ( !undoRedoInfo.valid() ) {
3756 undoRedoInfo.id = oldC.paragraph()->paragId();
3757 undoRedoInfo.index = oldC.index();
3758 undoRedoInfo.d->text = QString::null;
3759 }
3760 int oldLen = undoRedoInfo.d->text.length();
3761 if ( !doc->preProcessor() ) {
3762 QString txt = doc->selectedText( QTextDocument::Temp );
3763 undoRedoInfo.d->text += txt;
3764 for ( int i = 0; i < (int)txt.length(); ++i ) {
3765 if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) {
3766 oldC.paragraph()->at( oldC.index() )->format()->addRef();
3767 undoRedoInfo.d->text.
3768 setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE );
3769 }
3770 oldC.gotoNextLetter();
3771 }
3772 }
3773 undoRedoInfo.clear();
3774 removeSelection( QTextDocument::Temp );
3775 }
3776
3777 formatMore();
3778 setModified();
3779 emit textChanged();
3780 repaintChanged();
3781 ensureCursorVisible();
3782 return;
3783 }
3784
3707#if defined(Q_OS_WIN32) 3785#if defined(Q_OS_WIN32)
3708 // Need to convert CRLF to LF 3786 // Need to convert CRLF to LF
3709 int index = t.find( QString::fromLatin1("\r\n"), 0 ); 3787 int index = t.find( QString::fromLatin1("\r\n"), 0 );
@@ -3838,7 +3916,7 @@ void QTextEdit::setWordWrap( WordWrap mode )
3838 doc->setMinimumWidth( -1 ); 3916 doc->setMinimumWidth( -1 );
3839 doc->invalidate(); 3917 doc->invalidate();
3840 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 3918 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3841 lastFormatted = doc->firstParag(); 3919 lastFormatted = doc->firstParagraph();
3842 interval = 0; 3920 interval = 0;
3843 formatMore(); 3921 formatMore();
3844 break; 3922 break;
@@ -3899,7 +3977,7 @@ void QTextEdit::setWrapColumnOrWidth( int value )
3899 } 3977 }
3900 doc->invalidate(); 3978 doc->invalidate();
3901 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 3979 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3902 lastFormatted = doc->firstParag(); 3980 lastFormatted = doc->firstParagraph();
3903 interval = 0; 3981 interval = 0;
3904 formatMore(); 3982 formatMore();
3905} 3983}
@@ -3952,7 +4030,7 @@ void QTextEdit::setWrapPolicy( WrapPolicy policy )
3952 document()->setFormatter( formatter ); 4030 document()->setFormatter( formatter );
3953 doc->invalidate(); 4031 doc->invalidate();
3954 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4032 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3955 lastFormatted = doc->firstParag(); 4033 lastFormatted = doc->firstParagraph();
3956 interval = 0; 4034 interval = 0;
3957 formatMore(); 4035 formatMore();
3958} 4036}
@@ -3979,14 +4057,13 @@ void QTextEdit::clear()
3979 if ( cursor->isValid() ) 4057 if ( cursor->isValid() )
3980 cursor->restoreState(); 4058 cursor->restoreState();
3981 doc->clear( TRUE ); 4059 doc->clear( TRUE );
3982 cursor->setDocument( doc ); 4060 delete cursor;
3983 cursor->setParag( doc->firstParag() ); 4061 cursor = new QTextCursor( doc );
3984 cursor->setIndex( 0 );
3985 lastFormatted = 0; 4062 lastFormatted = 0;
3986 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4063 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3987 4064
3988 emit cursorPositionChanged( cursor ); 4065 emit cursorPositionChanged( cursor );
3989 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 4066 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
3990} 4067}
3991 4068
3992int QTextEdit::undoDepth() const 4069int QTextEdit::undoDepth() const
@@ -4025,7 +4102,7 @@ void QTextEdit::setTabStopWidth( int ts )
4025{ 4102{
4026 document()->setTabStops( ts ); 4103 document()->setTabStops( ts );
4027 doc->invalidate(); 4104 doc->invalidate();
4028 lastFormatted = doc->firstParag(); 4105 lastFormatted = doc->firstParagraph();
4029 interval = 0; 4106 interval = 0;
4030 formatMore(); 4107 formatMore();
4031 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4108 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
@@ -4046,7 +4123,13 @@ void QTextEdit::clearUndoRedo()
4046 emit redoAvailable( doc->commands()->isRedoAvailable() ); 4123 emit redoAvailable( doc->commands()->isRedoAvailable() );
4047} 4124}
4048 4125
4049/*! This function gets the format of the character at position \a 4126/*! \internal
4127
4128 \warning In Qt 3.1 we will provide a cleaer API for the
4129 functionality which is provided by this function and in Qt 4.0 this
4130 function will go away.
4131
4132 This function gets the format of the character at position \a
4050 index in paragraph \a para. Sets \a font to the character's font, \a 4133 index in paragraph \a para. Sets \a font to the character's font, \a
4051 color to the character's color and \a verticalAlignment to the 4134 color to the character's color and \a verticalAlignment to the
4052 character's vertical alignment. 4135 character's vertical alignment.
@@ -4059,7 +4142,7 @@ bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, Vert
4059{ 4142{
4060 if ( !font || !color ) 4143 if ( !font || !color )
4061 return FALSE; 4144 return FALSE;
4062 QTextParag *p = doc->paragAt( para ); 4145 QTextParagraph *p = doc->paragAt( para );
4063 if ( !p ) 4146 if ( !p )
4064 return FALSE; 4147 return FALSE;
4065 if ( index < 0 || index >= p->length() ) 4148 if ( index < 0 || index >= p->length() )
@@ -4070,7 +4153,13 @@ bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, Vert
4070 return TRUE; 4153 return TRUE;
4071} 4154}
4072 4155
4073/*! This function gets the format of the paragraph \a para. Sets \a 4156/*! \internal
4157
4158 \warning In Qt 3.1 we will provide a cleaer API for the
4159 functionality which is provided by this function and in Qt 4.0 this
4160 function will go away.
4161
4162 This function gets the format of the paragraph \a para. Sets \a
4074 font to the paragraphs's font, \a color to the paragraph's color, \a 4163 font to the paragraphs's font, \a color to the paragraph's color, \a
4075 verticalAlignment to the paragraph's vertical alignment, \a 4164 verticalAlignment to the paragraph's vertical alignment, \a
4076 alignment to the paragraph's alignment, \a displayMode to the 4165 alignment to the paragraph's alignment, \a displayMode to the
@@ -4090,14 +4179,14 @@ bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color,
4090{ 4179{
4091 if ( !font || !color || !alignment || !displayMode || !listStyle ) 4180 if ( !font || !color || !alignment || !displayMode || !listStyle )
4092 return FALSE; 4181 return FALSE;
4093 QTextParag *p = doc->paragAt( para ); 4182 QTextParagraph *p = doc->paragAt( para );
4094 if ( !p ) 4183 if ( !p )
4095 return FALSE; 4184 return FALSE;
4096 *font = p->paragFormat()->font(); 4185 *font = p->at(0)->format()->font();
4097 *color = p->paragFormat()->color(); 4186 *color = p->at(0)->format()->color();
4098 *verticalAlignment = (VerticalAlignment)p->paragFormat()->vAlign(); 4187 *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign();
4099 *alignment = p->alignment(); 4188 *alignment = p->alignment();
4100 *displayMode = p->style() ? p->style()->displayMode() : QStyleSheetItem::DisplayBlock; 4189 *displayMode = p->isListItem() ? QStyleSheetItem::DisplayListItem : QStyleSheetItem::DisplayBlock;
4101 *listStyle = p->listStyle(); 4190 *listStyle = p->listStyle();
4102 *listDepth = p->listDepth(); 4191 *listDepth = p->listDepth();
4103 return TRUE; 4192 return TRUE;
@@ -4155,10 +4244,14 @@ QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos )
4155} 4244}
4156 4245
4157/*! \overload 4246/*! \overload
4247 \obsolete
4158 This function is called to create a right mouse button popup menu. 4248 This function is called to create a right mouse button popup menu.
4159 If you want to create a custom popup menu, reimplement this function 4249 If you want to create a custom popup menu, reimplement this function
4160 and return the created popup menu. Ownership of the popup menu is 4250 and return the created popup menu. Ownership of the popup menu is
4161 transferred to the caller. 4251 transferred to the caller.
4252
4253 This function is only called if createPopupMenu( const QPoint & )
4254 returns 0.
4162*/ 4255*/
4163 4256
4164QPopupMenu *QTextEdit::createPopupMenu() 4257QPopupMenu *QTextEdit::createPopupMenu()
@@ -4173,21 +4266,8 @@ void QTextEdit::setFont( const QFont &f )
4173 QFont old( QScrollView::font() ); 4266 QFont old( QScrollView::font() );
4174 QScrollView::setFont( f ); 4267 QScrollView::setFont( f );
4175 doc->setMinimumWidth( -1 ); 4268 doc->setMinimumWidth( -1 );
4176 4269 doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() );
4177 // ### that is a bit hacky 4270 lastFormatted = doc->firstParagraph();
4178 static short diff = 1;
4179 diff *= -1;
4180 doc->setWidth( visibleWidth() + diff );
4181
4182 int s = f.pointSize();
4183 bool usePixels = FALSE;
4184 if ( s == -1 ) {
4185 s = f.pixelSize();
4186 usePixels = TRUE;
4187 }
4188 doc->updateFontSizes( s, usePixels );
4189 doc->updateFontAttributes( f, old );
4190 lastFormatted = doc->firstParag();
4191 formatMore(); 4271 formatMore();
4192 repaintChanged(); 4272 repaintChanged();
4193} 4273}
@@ -4273,10 +4353,9 @@ void QTextEdit::zoomTo( int size )
4273 4353
4274void QTextEdit::sync() 4354void QTextEdit::sync()
4275{ 4355{
4276 QTextParag *p = lastFormatted; 4356 while ( lastFormatted ) {
4277 while ( p ) { 4357 lastFormatted->format();
4278 p->format(); 4358 lastFormatted = lastFormatted->next();
4279 p = p->next();
4280 } 4359 }
4281 resizeContents( contentsWidth(), doc->height() ); 4360 resizeContents( contentsWidth(), doc->height() );
4282} 4361}
@@ -4360,7 +4439,7 @@ QRect QTextEdit::paragraphRect( int para ) const
4360{ 4439{
4361 QTextEdit *that = (QTextEdit *)this; 4440 QTextEdit *that = (QTextEdit *)this;
4362 that->sync(); 4441 that->sync();
4363 QTextParag *p = doc->paragAt( para ); 4442 QTextParagraph *p = doc->paragAt( para );
4364 if ( !p ) 4443 if ( !p )
4365 return QRect( -1, -1, -1, -1 ); 4444 return QRect( -1, -1, -1, -1 );
4366 return p->rect(); 4445 return p->rect();
@@ -4374,9 +4453,9 @@ QRect QTextEdit::paragraphRect( int para ) const
4374int QTextEdit::paragraphAt( const QPoint &pos ) const 4453int QTextEdit::paragraphAt( const QPoint &pos ) const
4375{ 4454{
4376 QTextCursor c( doc ); 4455 QTextCursor c( doc );
4377 c.place( pos, doc->firstParag() ); 4456 c.place( pos, doc->firstParagraph() );
4378 if ( c.parag() ) 4457 if ( c.paragraph() )
4379 return c.parag()->paragId(); 4458 return c.paragraph()->paragId();
4380 return -1; 4459 return -1;
4381} 4460}
4382 4461
@@ -4390,10 +4469,10 @@ int QTextEdit::paragraphAt( const QPoint &pos ) const
4390int QTextEdit::charAt( const QPoint &pos, int *para ) const 4469int QTextEdit::charAt( const QPoint &pos, int *para ) const
4391{ 4470{
4392 QTextCursor c( doc ); 4471 QTextCursor c( doc );
4393 c.place( pos, doc->firstParag() ); 4472 c.place( pos, doc->firstParagraph() );
4394 if ( c.parag() ) { 4473 if ( c.paragraph() ) {
4395 if ( para ) 4474 if ( para )
4396 *para = c.parag()->paragId(); 4475 *para = c.paragraph()->paragId();
4397 return c.index(); 4476 return c.index();
4398 } 4477 }
4399 return -1; 4478 return -1;
@@ -4403,7 +4482,7 @@ int QTextEdit::charAt( const QPoint &pos, int *para ) const
4403 4482
4404void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg ) 4483void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg )
4405{ 4484{
4406 QTextParag *p = doc->paragAt( para ); 4485 QTextParagraph *p = doc->paragAt( para );
4407 if ( !p ) 4486 if ( !p )
4408 return; 4487 return;
4409 p->setBackgroundColor( bg ); 4488 p->setBackgroundColor( bg );
@@ -4416,7 +4495,7 @@ void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg )
4416 4495
4417void QTextEdit::clearParagraphBackground( int para ) 4496void QTextEdit::clearParagraphBackground( int para )
4418{ 4497{
4419 QTextParag *p = doc->paragAt( para ); 4498 QTextParagraph *p = doc->paragAt( para );
4420 if ( !p ) 4499 if ( !p )
4421 return; 4500 return;
4422 p->clearBackgroundColor(); 4501 p->clearBackgroundColor();
@@ -4430,7 +4509,7 @@ void QTextEdit::clearParagraphBackground( int para )
4430 4509
4431QColor QTextEdit::paragraphBackgroundColor( int para ) const 4510QColor QTextEdit::paragraphBackgroundColor( int para ) const
4432{ 4511{
4433 QTextParag *p = doc->paragAt( para ); 4512 QTextParagraph *p = doc->paragAt( para );
4434 if ( !p ) 4513 if ( !p )
4435 return QColor(); 4514 return QColor();
4436 QColor *c = p->backgroundColor(); 4515 QColor *c = p->backgroundColor();
@@ -4469,7 +4548,7 @@ bool QTextEdit::isRedoAvailable() const
4469 return doc->commands()->isRedoAvailable(); 4548 return doc->commands()->isRedoAvailable();
4470} 4549}
4471 4550
4472void QTextEdit::ensureFormatted( QTextParag *p ) 4551void QTextEdit::ensureFormatted( QTextParagraph *p )
4473{ 4552{
4474 while ( !p->isValid() ) { 4553 while ( !p->isValid() ) {
4475 if ( !lastFormatted ) 4554 if ( !lastFormatted )
@@ -4486,11 +4565,11 @@ void QTextEdit::updateCursor( const QPoint & pos )
4486 placeCursor( pos, &c, TRUE ); 4565 placeCursor( pos, &c, TRUE );
4487 4566
4488#ifndef QT_NO_NETWORKPROTOCOL 4567#ifndef QT_NO_NETWORKPROTOCOL
4489 if ( c.parag() && c.parag()->at( c.index() ) && 4568 if ( c.paragraph() && c.paragraph()->at( c.index() ) &&
4490 c.parag()->at( c.index() )->isAnchor() && 4569 c.paragraph()->at( c.index() )->isAnchor() &&
4491 !c.parag()->at( c.index() )->anchorHref().isEmpty() ) { 4570 !c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) {
4492 if ( c.index() < c.parag()->length() - 1 ) 4571 if ( c.index() < c.paragraph()->length() - 1 )
4493 onLink = c.parag()->at( c.index() )->anchorHref(); 4572 onLink = c.paragraph()->at( c.index() )->anchorHref();
4494 else 4573 else
4495 onLink = QString::null; 4574 onLink = QString::null;
4496 4575