Diffstat (limited to 'noncore/apps/opie-write/qtextedit.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/apps/opie-write/qtextedit.cpp | 1495 |
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 @@ -68,2 +68,4 @@ using namespace Qt3; +static bool qt_enable_richtext_copy = FALSE; + struct QUndoRedoInfoPrivate @@ -79,3 +81,7 @@ public: QTextEditPrivate() - :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) {} + :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) + { + for ( int i=0; i<7; i++ ) + id[i] = 0; + } int id[ 7 ]; @@ -84,2 +90,3 @@ public: bool ensureCursorVisibleInShowEvent; + QString scrollToAnchor; // used to deferr scrollToAnchor() until the show event when we are resized }; @@ -92,3 +99,3 @@ static bool block_set_alignment = FALSE; \class QTextEdit qtextedit.h - \brief The QTextEdit widget provides a sophisticated single-page rich text editor. + \brief The QTextEdit widget provides a powerful single-page rich text editor. @@ -98,5 +105,50 @@ static bool block_set_alignment = FALSE; - QTextEdit is an advanced WYSIWYG editor supporting rich text - formatting. It is optimized to handle large documents and to - respond quickly to user input. + \tableofcontents + + \section1 Introduction and Concepts + + QTextEdit is an advanced WYSIWYG viewer/editor supporting rich + text formatting using HTML-style tags. It is optimized to handle + large documents and to respond quickly to user input. + + QTextEdit has three modes of operation: + \table + \header \i Mode \i Command \i Notes + \row \i Plain Text Editor \i setTextFormat(PlainText) + \i Set text with setText(); text() returns plain text. Text + attributes (e.g. colors) can be set, but plain text is always + returned.<sup>1.</sup> + \row \i Rich Text Editor \i setTextFormat(RichText) + \i Set text with setText(); text() returns rich text. Rich + text editing is fairly limited. You can't set margins or + insert images for example (although you can read and + correctly display files that have margins set and that + include images). This mode is mostly useful for editing small + amounts of rich text. <sup>2.</sup> + \row \i Text Viewer<sup>3.</sup> \i setReadOnly(TRUE) + \i Set text with setText() or append() (which has no undo + history so is faster and uses less memory); text() returns + plain or rich text depending on the textFormat(). This mode + can correctly display a large subset of HTML tags. + \endtable + + <sup>1.</sup><small>We do \e not recommend using QTextEdit to + create syntax highlighting editors because the current API is + insufficient for this purpose. We hope to release a more complete + API that will support syntax highlighting in a later + release.</small> + + <sup>2.</sup><small>A more complete API that supports setting + margins, images, etc., is planned for a later Qt release.</small> + + <sup>3.</sup><small>Qt 3.1 will provide a Log Viewer mode which is + optimised for the fast and memory efficient display of large + amounts of read only text.</small> + + We recommend that you always call setTextFormat() to set the mode + you want to use. If you use \c AutoText then setText() and + append() will try to determine whether the text they are given is + plain text or rich text. If you use \c RichText then setText() and + append() will assume that the text they are given is rich text. + insert() simply inserts the text it is given. @@ -104,8 +156,19 @@ static bool block_set_alignment = FALSE; formatted string which is word-wrapped to fit into the width of - the widget. A document consists of zero or more paragraphs, - indexed from 0. Characters are indexed on a per-paragraph basis, - also indexed from 0. The words in the paragraph are aligned in - accordance with the paragraph's alignment(). Paragraphs are - separated by hard line breaks. Each character within a paragraph - has its own attributes, for example, font and color. + the widget. By default when reading plain text, two newlines + signify a paragraph. A document consists of zero or more + paragraphs, indexed from 0. Characters are indexed on a + per-paragraph basis, also indexed from 0. The words in the + paragraph are aligned in accordance with the paragraph's + alignment(). Paragraphs are separated by hard line breaks. Each + character within a paragraph has its own attributes, for example, + font and color. + + The text edit documentation uses the following concepts: + \list + \i \e{current format} -- + this is the format at the current cursor position, \e and it + is the format of the selected text if any. + \i \e{current paragraph} -- the paragraph which contains the + cursor. + \endlist @@ -116,3 +179,4 @@ static bool block_set_alignment = FALSE; rendering style and the set of valid tags are defined by a - styleSheet(). Change the style sheet with \l{setStyleSheet()}; see + styleSheet(). Custom tags can be created and placed in a custom + style sheet. Change the style sheet with \l{setStyleSheet()}; see QStyleSheet for details. The images identified by image tags are @@ -136,10 +200,12 @@ static bool block_set_alignment = FALSE; - The text edit documentation uses the following concepts: - \list - \i <i>current format</i> -- - this is the format at the current cursor position, \e and it - is the format of the selected text if any. - \i <i>current paragraph</i> -- the paragraph which contains the - cursor. - \endlist + Note that we do not intend to add a full-featured web browser + widget to Qt (because that would easily double Qt's size and only + a few applications would benefit from it). The rich + text support in Qt is designed to provide a fast, portable and + efficient way to add reasonable online help facilities to + applications, and to provide a basis for rich text editors. + \section1 Using QTextEdit as a Display Widget + + QTextEdit can display a large HTML subset, including tables and + images. @@ -147,49 +213,12 @@ static bool block_set_alignment = FALSE; existing text and replaces it with the text passed in the - setText() call. Text can be inserted with insert(), paste() and - pasteSubType(). Text can also be cut(). The entire text is deleted - with clear() and the selected text is deleted with - removeSelectedText(). Selected (marked) text can also be deleted - with del() (which will delete the character to the right of the - cursor if no text is selected). - - The current format's attributes are set with setItalic(), - setBold(), setUnderline(), setFamily() (font family), - setPointSize(), setColor() and setCurrentFont(). The current - paragraph's style is set with setParagType() and its alignment is - set with setAlignment(). - - Use setSelection() to select text. The setSelectionAttributes() - function is used to indicate how selected text should be - displayed. Use hasSelectedText() to find out if any text is - selected. The currently selected text's position is available - using getSelection() and the selected text itself is returned by - selectedText(). The selection can be copied to the clipboard with - copy(), or cut to the clipboard with cut(). It can be deleted with - removeSelectedText(). The entire text can be selected (or - unselected) using selectAll(). QTextEdit supports multiple - selections. Most of the selection functions operate on the default - selection, selection 0. If the user presses a non-selecting key, - e.g. a cursor key without also holding down Shift, all selections - are cleared. - - Set and get the position of the cursor with setCursorPosition() - and getCursorPosition() respectively. When the cursor is moved, - the signals currentFontChanged(), currentColorChanged() and - currentAlignmentChanged() are emitted to reflect the font, color - and alignment at the new cursor position. - - If the text changes, the textChanged() signal is emitted, and if - the user inserts a new line by pressing Return or Enter, - returnPressed() is emitted. The isModified() function will return - TRUE if the text has been modified. - - QTextEdit provides command-based undo and redo. To set the depth - of the command history use setUndoDepth() which defaults to 100 - steps. To undo or redo the last operation call undo() or redo(). - The signals undoAvailable() and redoAvailable() indicate whether - the undo and redo operations can be executed. - - The indent() function is used to reindent a paragraph. It is - useful for code editors, for example in <em>Qt Designer</em>'s - code editor \e{Ctrl+I} invokes the indent() function. + setText() call. If you call setText() with legacy HTML (with + setTextFormat(RichText) in force), and then call text(), the text + that is returned may have different markup, but will render the + same. Text can be inserted with insert(), paste(), pasteSubType() + and append(). Text that is appended does not go into the undo + history; this makes append() faster and consumes less memory. Text + can also be cut(). The entire text is deleted with clear() and the + selected text is deleted with removeSelectedText(). Selected + (marked) text can also be deleted with del() (which will delete + the character to the right of the cursor if no text is selected). @@ -245,2 +274,81 @@ static bool block_set_alignment = FALSE; + A read-only QTextEdit provides the same functionality as the + (obsolete) QTextView. (QTextView is still supplied for + compatibility with old code.) + + \section2 Read-only key bindings + + When QTextEdit is used read-only the key-bindings are limited to + navigation, and text may only be selected with the mouse: + \table + \header \i Keypresses \i Action + \row \i \e{UpArrow} \i Move one line up + \row \i \e{DownArrow} \i Move one line down + \row \i \e{LeftArrow} \i Move one character left + \row \i \e{RightArrow} \i Move one character right + \row \i \e{PageUp} \i Move one (viewport) page up + \row \i \e{PageDown} \i Move one (viewport) page down + \row \i \e{Home} \i Move to the beginning of the text + \row \i \e{End} \i Move to the end of the text + \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel) + \row \i \e{Ctrl+Wheel} \i Zoom the text + \endtable + + The text edit may be able to provide some meta-information. For + example, the documentTitle() function will return the text from + within HTML \c{<title>} tags. + + The text displayed in a text edit has a \e context. The context is + a path which the text edit's QMimeSourceFactory uses to resolve + the locations of files and images. It is passed to the + mimeSourceFactory() when quering data. (See QTextEdit() and + \l{context()}.) + + \section1 Using QTextEdit as an Editor + + All the information about using QTextEdit as a display widget also + applies here. + + The current format's attributes are set with setItalic(), + setBold(), setUnderline(), setFamily() (font family), + setPointSize(), setColor() and setCurrentFont(). The current + paragraph's alignment is set with setAlignment(). + + Use setSelection() to select text. The setSelectionAttributes() + function is used to indicate how selected text should be + displayed. Use hasSelectedText() to find out if any text is + selected. The currently selected text's position is available + using getSelection() and the selected text itself is returned by + selectedText(). The selection can be copied to the clipboard with + copy(), or cut to the clipboard with cut(). It can be deleted with + removeSelectedText(). The entire text can be selected (or + unselected) using selectAll(). QTextEdit supports multiple + selections. Most of the selection functions operate on the default + selection, selection 0. If the user presses a non-selecting key, + e.g. a cursor key without also holding down Shift, all selections + are cleared. + + Set and get the position of the cursor with setCursorPosition() + and getCursorPosition() respectively. When the cursor is moved, + the signals currentFontChanged(), currentColorChanged() and + currentAlignmentChanged() are emitted to reflect the font, color + and alignment at the new cursor position. + + If the text changes, the textChanged() signal is emitted, and if + the user inserts a new line by pressing Return or Enter, + returnPressed() is emitted. The isModified() function will return + TRUE if the text has been modified. + + QTextEdit provides command-based undo and redo. To set the depth + of the command history use setUndoDepth() which defaults to 100 + steps. To undo or redo the last operation call undo() or redo(). + The signals undoAvailable() and redoAvailable() indicate whether + the undo and redo operations can be executed. + + The indent() function is used to reindent a paragraph. It is + useful for code editors, for example in <em>Qt Designer</em>'s + code editor \e{Ctrl+I} invokes the indent() function. + + \section2 Editing key bindings + The list of key-bindings which are implemented for editing: @@ -297,39 +405,2 @@ static bool block_set_alignment = FALSE; - QTextEdit can also be used as read-only text viewer. Call - setReadOnly( TRUE ) to disable editing. A read-only QTextEdit - provides the same functionality as the (obsolete) QTextView. - (QTextView is still supplied for compatibility with old code.) - - When QTextEdit is used read-only the key-bindings are limited to - navigation, and text may only be selected with the mouse: - \table - \header \i Keypresses \i Action - \row \i \e{UpArrow} \i Move one line up - \row \i \e{DownArrow} \i Move one line down - \row \i \e{LeftArrow} \i Move one character left - \row \i \e{RightArrow} \i Move one character right - \row \i \e{PageUp} \i Move one (viewport) page up - \row \i \e{PageDown} \i Move one (viewport) page down - \row \i \e{Home} \i Move to the beginning of the text - \row \i \e{End} \i Move to the end of the text - \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel) - \row \i \e{Ctrl+Wheel} \i Zoom the text - \endtable - - The text edit may be able to provide some meta-information. For - example, the documentTitle() function will return the text from - within HTML \c{<title>} tags. - - The text displayed in a text edit has a \e context. The context is - a path which the text edit's QMimeSourceFactory uses to resolve - the locations of files and images. It is passed to the - mimeSourceFactory() when quering data. (See QTextEdit() and - \l{context()}.) - - Note that we do not intend to add a full-featured web browser - widget to Qt (because that would easily double Qt's size and only - a few applications would benefit from it). The rich - text support in Qt is designed to provide a fast, portable and - efficient way to add reasonable online help facilities to - applications, and to provide a basis for rich text editors. */ @@ -642,2 +713,4 @@ void QTextEdit::init() doc->setFormatter( new QTextFormatterBreakWords ); + doc->formatCollection()->defaultFormat()->setFont( QScrollView::font() ); + doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( QColorGroup::Text ) ); currentFormat = doc->formatCollection()->defaultFormat(); @@ -647,4 +720,4 @@ void QTextEdit::init() viewport()->setAcceptDrops( TRUE ); - resizeContents( 0, doc->lastParag() ? - ( doc->lastParag()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); + resizeContents( 0, doc->lastParagraph() ? + ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); @@ -660,3 +733,3 @@ void QTextEdit::init() this, SLOT( formatMore() ) ); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); @@ -715,6 +788,6 @@ void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw - if ( lastFormatted == doc->lastParag() ) + if ( lastFormatted == doc->lastParagraph() ) resizeContents( contentsWidth(), doc->height() ); - if ( contentsHeight() < visibleHeight() && ( !doc->lastParag() || doc->lastParag()->isValid() ) && drawAll ) + if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll ) p->fillRect( 0, contentsHeight(), visibleWidth(), @@ -815,6 +888,12 @@ bool QTextEdit::event( QEvent *e ) - if ( e->type() == QEvent::Show && d->ensureCursorVisibleInShowEvent ) { - sync(); - ensureCursorVisible(); - d->ensureCursorVisibleInShowEvent = FALSE; + if ( e->type() == QEvent::Show ) { + if ( d->ensureCursorVisibleInShowEvent ) { + sync(); + ensureCursorVisible(); + d->ensureCursorVisibleInShowEvent = FALSE; + } + if ( !d->scrollToAnchor.isEmpty() ) { + scrollToAnchor( d->scrollToAnchor ); + d->scrollToAnchor = QString::null; + } } @@ -847,3 +926,3 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) if ( selChanged ) { - cursor->parag()->document()->nextDoubleBuffered = TRUE; + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; repaintChanged(); @@ -860,3 +939,3 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) CursorAction a; - if ( cursor->parag()->string()->isRightToLeft() == (e->key() == Key_Right) ) + if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) ) a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; @@ -888,8 +967,13 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) removeSelectedText(); + if ( textFormat() == Qt::RichText && ( e->state() & ControlButton ) ) { + // Ctrl-Enter inserts a line break in rich text mode + insert( QString( QChar( 0x2028) ), TRUE, FALSE, TRUE ); + } else { #ifndef QT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); #endif - clearUndoRedoInfo = FALSE; - doKeyboardAction( ActionReturn ); - emit returnPressed(); + clearUndoRedoInfo = FALSE; + doKeyboardAction( ActionReturn ); + emit returnPressed(); + } break; @@ -913,2 +997,6 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) paste(); +#if defined (Q_WS_WIN) + else if ( e->state() & ControlButton ) + copy(); +#endif break; @@ -920,6 +1008,2 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) - if ( !cursor->parag()->prev() && - cursor->atParagStart() ) - break; - doKeyboardAction( ActionBackspace ); @@ -945,7 +1029,10 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) if ( e->key() == Key_Tab ) { - if ( textFormat() == Qt::RichText && - cursor->index() == 0 && cursor->parag()->style() && - cursor->parag()->style()->displayMode() == - QStyleSheetItem::DisplayListItem ) { - cursor->parag()->incDepth(); + if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 ); + clearUndoRedo(); drawCursor( FALSE ); @@ -956,26 +1043,32 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) } - if ( textFormat() == Qt::RichText && ( !cursor->parag()->style() || - cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayBlock ) && - cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { - setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); - cursor->parag()->incDepth(); - drawCursor( FALSE ); - repaintChanged(); - drawCursor( TRUE ); - } else { - if ( overWrite && !cursor->atParagEnd() ) - cursor->remove(); - QString t = e->text(); - QTextParag *p = cursor->parag(); - if ( p && p->string() && p->string()->isRightToLeft() ) { - QChar *c = (QChar *)t.unicode(); - int l = t.length(); - while( l-- ) { - if ( c->mirrored() ) - *c = c->mirroredChar(); - c++; - } + + if ( textFormat() == Qt::RichText && !cursor->paragraph()->isListItem() ) { + if ( cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); + clearUndoRedo(); + drawCursor( FALSE ); + repaintChanged(); + drawCursor( TRUE ); + break; + } + } + if ( overWrite && !cursor->atParagEnd() ) + cursor->remove(); + QString t = e->text(); + QTextParagraph *p = cursor->paragraph(); + if ( p && p->string() && p->string()->isRightToLeft() ) { + QChar *c = (QChar *)t.unicode(); + int l = t.length(); + while( l-- ) { + if ( c->mirrored() ) + *c = c->mirroredChar(); + c++; } - insert( t, TRUE, FALSE, TRUE ); } + insert( t, TRUE, FALSE, TRUE ); break; @@ -1021,3 +1114,3 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) } - if ( !cursor->parag()->prev() && + if ( !cursor->paragraph()->prev() && cursor->atParagStart() ) @@ -1038,3 +1131,6 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) case Key_Z: - undo(); + if(e->state() & ShiftButton) + redo(); + else + undo(); break; @@ -1065,3 +1161,3 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); if ( clearUndoRedoInfo ) @@ -1086,3 +1182,3 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) - lastFormatted = cursor->parag(); + lastFormatted = cursor->paragraph(); drawCursor( FALSE ); @@ -1091,28 +1187,34 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) switch ( action ) { - case ActionDelete: { - checkUndoRedoInfo( UndoRedoInfo::Delete ); - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); - undoRedoInfo.index = cursor->index(); - undoRedoInfo.d->text = QString::null; - } - undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; - if ( cursor->parag()->at( cursor->index() )->format() ) { - cursor->parag()->at( cursor->index() )->format()->addRef(); - undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); - } - QTextParag *old = cursor->parag(); - if ( cursor->remove() ) { - if ( old != cursor->parag() && lastFormatted == old ) - lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; - undoRedoInfo.d->text += "\n"; + case ActionDelete: + if ( !cursor->atParagEnd() ) { + checkUndoRedoInfo( UndoRedoInfo::Delete ); + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.index = cursor->index(); + undoRedoInfo.d->text = QString::null; + } + undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( cursor->index() ), TRUE ); + cursor->remove(); + } else { + clearUndoRedo(); + doc->setSelectionStart( QTextDocument::Temp, *cursor ); + cursor->gotoNextLetter(); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); + removeSelectedText( QTextDocument::Temp ); } - } break; + break; case ActionBackspace: - if ( textFormat() == Qt::RichText && - cursor->parag()->style() && - cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayListItem && - cursor->index() == 0 ) { - cursor->parag()->decDepth(); - lastFormatted = cursor->parag(); + if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() && cursor->index() == 0 ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + int ldepth = cursor->paragraph()->listDepth(); + ldepth = QMAX( ldepth-1, 0 ); + cursor->paragraph()->setListDepth( ldepth ); + if ( ldepth == 0 ) + cursor->paragraph()->setListItem( FALSE ); + clearUndoRedo(); + lastFormatted = cursor->paragraph(); repaintChanged(); @@ -1121,27 +1223,26 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) } - checkUndoRedoInfo( UndoRedoInfo::Delete ); - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); - undoRedoInfo.index = cursor->index(); - undoRedoInfo.d->text = QString::null; - } - cursor->gotoPreviousLetter(); - undoRedoInfo.d->text.prepend( QString( cursor->parag()->at( cursor->index() )->c ) ); - if ( cursor->parag()->at( cursor->index() )->format() ) { - cursor->parag()->at( cursor->index() )->format()->addRef(); - undoRedoInfo.d->text.at( 0 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); - } - undoRedoInfo.index = cursor->index(); - if ( cursor->remove() ) { - undoRedoInfo.d->text.remove( 0, 1 ); - undoRedoInfo.d->text.prepend( "\n" ); + if ( !cursor->atParagStart() ) { + checkUndoRedoInfo( UndoRedoInfo::Delete ); + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.index = cursor->index(); + undoRedoInfo.d->text = QString::null; + } + cursor->gotoPreviousLetter(); + undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index() ), TRUE ); undoRedoInfo.index = cursor->index(); - undoRedoInfo.id = cursor->parag()->paragId(); + cursor->remove(); + lastFormatted = cursor->paragraph(); + } else if ( cursor->paragraph()->prev() ){ + clearUndoRedo(); + doc->setSelectionStart( QTextDocument::Temp, *cursor ); + cursor->gotoPreviousLetter(); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); + removeSelectedText( QTextDocument::Temp ); } - lastFormatted = cursor->parag(); break; - case ActionReturn: { + case ActionReturn: checkUndoRedoInfo( UndoRedoInfo::Return ); if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); + undoRedoInfo.id = cursor->paragraph()->paragId(); undoRedoInfo.index = cursor->index(); @@ -1150,5 +1251,5 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) undoRedoInfo.d->text += "\n"; - cursor->splitAndInsertEmptyParag(); - if ( cursor->parag()->prev() ) { - lastFormatted = cursor->parag()->prev(); + cursor->splitAndInsertEmptyParagraph(); + if ( cursor->paragraph()->prev() ) { + lastFormatted = cursor->paragraph()->prev(); lastFormatted->invalidate( 0 ); @@ -1156,35 +1257,13 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) doUpdateCurrentFormat = FALSE; - } break; - case ActionKill: - checkUndoRedoInfo( UndoRedoInfo::Delete ); - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); - undoRedoInfo.index = cursor->index(); - undoRedoInfo.d->text = QString::null; - } - if ( cursor->atParagEnd() ) { - undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; - if ( cursor->parag()->at( cursor->index() )->format() ) { - cursor->parag()->at( cursor->index() )->format()->addRef(); - undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); - } - QTextParag *old = cursor->parag(); - if ( cursor->remove() ) { - if ( old != cursor->parag() && lastFormatted == old ) - lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; - undoRedoInfo.d->text += "\n"; - } - } else { - int oldLen = undoRedoInfo.d->text.length(); - undoRedoInfo.d->text += cursor->parag()->string()->toString().mid( cursor->index() ); - for ( int i = cursor->index(); i < cursor->parag()->length(); ++i ) { - if ( cursor->parag()->at( i )->format() ) { - cursor->parag()->at( i )->format()->addRef(); - undoRedoInfo.d->text.at( oldLen + i - cursor->index() ).setFormat( cursor->parag()->at( i )->format() ); - } - } - undoRedoInfo.d->text.remove( undoRedoInfo.d->text.length() - 1, 1 ); - cursor->killLine(); - } break; + case ActionKill: + clearUndoRedo(); + doc->setSelectionStart( QTextDocument::Temp, *cursor ); + if ( cursor->atParagEnd() ) + cursor->gotoNextLetter(); + else + cursor->setIndex( cursor->paragraph()->length() - 1 ); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); + removeSelectedText( QTextDocument::Temp ); + break; } @@ -1195,12 +1274,3 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) drawCursor( TRUE ); - - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } - + updateMicroFocusHint(); if ( doUpdateCurrentFormat ) @@ -1211,58 +1281,34 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) -void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, int oldLen, QTextString &text, bool fillStyles ) +void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles ) { + QDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly ); c2.restoreState(); c1.restoreState(); - if ( c1.parag() == c2.parag() ) { - for ( int i = c1.index(); i < c2.index(); ++i ) { - if ( c1.parag()->at( i )->format() ) { - c1.parag()->at( i )->format()->addRef(); - text.at( oldLen + i - c1.index() ).setFormat( c1.parag()->at( i )->format() ); - } - } + int lastIndex = text.length(); + if ( c1.paragraph() == c2.paragraph() ) { + for ( int i = c1.index(); i < c2.index(); ++i ) + text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE ); if ( fillStyles ) { - undoRedoInfo.oldAligns[ 0 ] = c1.parag()->alignment(); - undoRedoInfo.oldStyles << c1.parag()->styleSheetItems(); - undoRedoInfo.oldListStyles << c1.parag()->listStyle(); + styleStream << (int) 1; + c1.paragraph()->writeStyleInformation( styleStream ); } } else { - int lastIndex = oldLen; int i; - for ( i = c1.index(); i < c1.parag()->length(); ++i ) { - if ( c1.parag()->at( i )->format() ) { - c1.parag()->at( i )->format()->addRef(); - text.at( lastIndex ).setFormat( c1.parag()->at( i )->format() ); - lastIndex++; - } - } - QTextParag *p = c1.parag()->next(); - while ( p && p != c2.parag() ) { - for ( int i = 0; i < p->length(); ++i ) { - if ( p->at( i )->format() ) { - p->at( i )->format()->addRef(); - text.at( i + lastIndex ).setFormat( p->at( i )->format() ); - } - } - lastIndex += p->length(); + for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i ) + text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE ); + int num = 2; // start and end, being different + text += "\n"; lastIndex++; + QTextParagraph *p = c1.paragraph()->next(); + while ( p && p != c2.paragraph() ) { + for ( i = 0; i < p->length()-1; ++i ) + text.insert( lastIndex++ , p->at( i ), TRUE ); + text += "\n"; num++; lastIndex++; p = p->next(); } - for ( i = 0; i < c2.index(); ++i ) { - if ( c2.parag()->at( i )->format() ) { - c2.parag()->at( i )->format()->addRef(); - text.at( i + lastIndex ).setFormat( c2.parag()->at( i )->format() ); - } - } + for ( i = 0; i < c2.index(); ++i ) + text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE ); if ( fillStyles ) { - QTextParag *p = c1.parag(); - i = 0; - while ( p ) { - if ( i < (int)undoRedoInfo.oldAligns.size() ) - undoRedoInfo.oldAligns[ i ] = p->alignment(); - undoRedoInfo.oldStyles << p->styleSheetItems(); - undoRedoInfo.oldListStyles << p->listStyle(); - if ( p == c2.parag() ) - break; - p = p->next(); - ++i; - } + styleStream << num; + for ( QTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() ) + p->writeStyleInformation( styleStream ); } @@ -1296,5 +1342,7 @@ void QTextEdit::removeSelectedText( int selNum ) QTextCursor c1 = doc->selectionStartCursor( selNum ); + c1.restoreState(); QTextCursor c2 = doc->selectionEndCursor( selNum ); + c2.restoreState(); - // ### no support for editing tables yet + // ### no support for editing tables yet, plus security for broken selections if ( c1.nestedDepth() || c2.nestedDepth() ) @@ -1314,6 +1362,5 @@ void QTextEdit::removeSelectedText( int selNum ) } - int oldLen = undoRedoInfo.d->text.length(); - undoRedoInfo.d->text = doc->selectedText( selNum, FALSE ); - undoRedoInfo.oldAligns.resize( undoRedoInfo.oldAligns.size() + QMAX( 0, c2.parag()->paragId() - c1.parag()->paragId() + 1 ) ); - readFormats( c1, c2, oldLen, undoRedoInfo.d->text, TRUE ); + readFormats( c1, c2, undoRedoInfo.d->text, TRUE ); + + doc->removeSelectedText( selNum, cursor ); @@ -1321,3 +1368,3 @@ void QTextEdit::removeSelectedText( int selNum ) ensureCursorVisible(); - lastFormatted = cursor->parag(); + lastFormatted = cursor->paragraph(); formatMore(); @@ -1336,14 +1383,6 @@ void QTextEdit::removeSelectedText( int selNum ) #endif - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); } else { - cursor->setDocument( doc ); - cursor->setParag( doc->firstParag() ); - cursor->setIndex( 0 ); + delete cursor; + cursor = new QTextCursor( doc ); drawCursor( TRUE ); @@ -1367,6 +1406,6 @@ void QTextEdit::moveCursor( CursorAction action, bool select ) if ( !doc->hasSelection( QTextDocument::Standard ) ) - doc->setSelectionStart( QTextDocument::Standard, cursor ); + doc->setSelectionStart( QTextDocument::Standard, *cursor ); moveCursor( action ); - if ( doc->setSelectionEnd( QTextDocument::Standard, cursor ) ) { - cursor->parag()->document()->nextDoubleBuffered = TRUE; + if ( doc->setSelectionEnd( QTextDocument::Standard, *cursor ) ) { + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; repaintChanged(); @@ -1385,3 +1424,3 @@ void QTextEdit::moveCursor( CursorAction action, bool select ) } else { - cursor->parag()->document()->nextDoubleBuffered = TRUE; + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; repaintChanged(); @@ -1401,10 +1440,3 @@ void QTextEdit::moveCursor( CursorAction action, bool select ) updateCurrentFormat(); - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); } @@ -1451,3 +1483,3 @@ void QTextEdit::moveCursor( CursorAction action ) case MoveEnd: - ensureFormatted( doc->lastParag() ); + ensureFormatted( doc->lastParagraph() ); cursor->gotoEnd(); @@ -1455,11 +1487,3 @@ void QTextEdit::moveCursor( CursorAction action ) } - - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); updateCurrentFormat(); @@ -1472,2 +1496,4 @@ void QTextEdit::resizeEvent( QResizeEvent *e ) QScrollView::resizeEvent( e ); + if ( doc->visibleWidth() == 0 ) + doResize(); } @@ -1479,8 +1505,11 @@ void QTextEdit::viewportResizeEvent( QResizeEvent *e ) QScrollView::viewportResizeEvent( e ); - if ( e->oldSize().width() != e->size().width() ) + if ( e->oldSize().width() != e->size().width() ) { + bool stayAtBottom = e->oldSize().height() != e->size().height() && + contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height(); doResize(); + if ( stayAtBottom ) + scrollToBottom(); + } } -static bool blockEnsureCursorVisible = FALSE; - /*! @@ -1494,4 +1523,2 @@ void QTextEdit::ensureCursorVisible() { - if ( blockEnsureCursorVisible ) - return; if ( !isVisible() ) { @@ -1500,10 +1527,10 @@ void QTextEdit::ensureCursorVisible() } - lastFormatted = cursor->parag(); + lastFormatted = cursor->paragraph(); formatMore(); - QTextStringChar *chr = cursor->parag()->at( cursor->index() ); - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - int x = cursor->parag()->rect().x() + chr->x + cursor->offsetX(); + QTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); + int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX(); int y = 0; int dummy; - cursor->parag()->lineHeightOfChar( cursor->index(), &dummy, &y ); - y += cursor->parag()->rect().y() + cursor->offsetY(); + cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); + y += cursor->paragraph()->rect().y() + cursor->offsetY(); int w = 1; @@ -1519,4 +1546,4 @@ void QTextEdit::drawCursor( bool visible ) !viewport()->isUpdatesEnabled() || - !cursor->parag() || - !cursor->parag()->isValid() || + !cursor->paragraph() || + !cursor->paragraph()->isValid() || !selectedText().isEmpty() || @@ -1527,4 +1554,4 @@ void QTextEdit::drawCursor( bool visible ) QPainter p( viewport() ); - QRect r( cursor->topParag()->rect() ); - cursor->parag()->setChanged( TRUE ); + QRect r( cursor->topParagraph()->rect() ); + cursor->paragraph()->setChanged( TRUE ); p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); @@ -1532,4 +1559,4 @@ void QTextEdit::drawCursor( bool visible ) QColorGroup cg( colorGroup() ); - if ( cursor->parag()->background() ) - cg.setBrush( QColorGroup::Base, *cursor->parag()->background() ); + if ( cursor->paragraph()->background() ) + cg.setBrush( QColorGroup::Base, *cursor->paragraph()->background() ); else if ( doc->paper() ) @@ -1537,7 +1564,7 @@ void QTextEdit::drawCursor( bool visible ) p.setBrushOrigin( -contentsX(), -contentsY() ); - cursor->parag()->document()->nextDoubleBuffered = TRUE; + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; if ( !cursor->nestedDepth() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); int dist = 5; - if ( ( cursor->parag()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) + if ( ( cursor->paragraph()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) dist = 50; @@ -1547,6 +1574,6 @@ void QTextEdit::drawCursor( bool visible ) r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); - doc->drawParag( &p, cursor->parag(), x, + doc->drawParagraph( &p, cursor->paragraph(), x, r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); } else { - doc->drawParag( &p, cursor->parag(), r.x() - cursor->totalOffsetX(), + doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(), r.y() - cursor->totalOffsetY(), r.width(), r.height(), @@ -1604,5 +1631,5 @@ void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) placeCursor( e->pos(), &c, TRUE ); - if ( c.parag() && c.parag()->at( c.index() ) && - c.parag()->at( c.index() )->isAnchor() ) { - pressedLink = c.parag()->at( c.index() )->anchorHref(); + if ( c.paragraph() && c.paragraph()->at( c.index() ) && + c.paragraph()->at( c.index() )->isAnchor() ) { + pressedLink = c.paragraph()->at( c.index() )->anchorHref(); } @@ -1624,5 +1651,5 @@ void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) redraw = doc->removeSelection( QTextDocument::Standard ); - doc->setSelectionStart( QTextDocument::Standard, cursor ); + doc->setSelectionStart( QTextDocument::Standard, *cursor ); } else { - redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; + redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; } @@ -1630,6 +1657,6 @@ void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) if ( isReadOnly() || !( e->state() & ShiftButton ) ) { - doc->setSelectionStart( QTextDocument::Standard, cursor ); + doc->setSelectionStart( QTextDocument::Standard, *cursor ); } else { - doc->setSelectionStart( QTextDocument::Standard, &c ); - redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; + doc->setSelectionStart( QTextDocument::Standard, c ); + redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; } @@ -1716,3 +1743,3 @@ void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e ) emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); if ( oldCursor != *cursor ) @@ -1746,9 +1773,9 @@ void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * ) QTextCursor c2 = *cursor; - if ( cursor->index() > 0 && !cursor->parag()->at( cursor->index()-1 )->c.isSpace() ) + if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() ) c1.gotoPreviousWord(); - if ( !cursor->parag()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) + if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) c2.gotoNextWord(); - doc->setSelectionStart( QTextDocument::Standard, &c1 ); - doc->setSelectionEnd( QTextDocument::Standard, &c2 ); + doc->setSelectionStart( QTextDocument::Standard, c1 ); + doc->setSelectionEnd( QTextDocument::Standard, c2 ); @@ -1808,5 +1835,38 @@ void QTextEdit::contentsDropEvent( QDropEvent *e ) if ( QTextDrag::decode( e, text ) ) { - if ( ( e->source() == this || - e->source() == viewport() ) && - e->action() == QDropEvent::Move ) { + bool hasSel = doc->hasSelection( QTextDocument::Standard ); + bool internalDrag = e->source() == this || e->source() == viewport(); + int dropId, dropIndex; + QTextCursor insertCursor = *cursor; + dropId = cursor->paragraph()->paragId(); + dropIndex = cursor->index(); + if ( hasSel && internalDrag ) { + QTextCursor c1, c2; + int selStartId, selStartIndex; + int selEndId, selEndIndex; + c1 = doc->selectionStartCursor( QTextDocument::Standard ); + c1.restoreState(); + c2 = doc->selectionEndCursor( QTextDocument::Standard ); + c2.restoreState(); + selStartId = c1.paragraph()->paragId(); + selStartIndex = c1.index(); + selEndId = c2.paragraph()->paragId(); + selEndIndex = c2.index(); + if ( ( ( dropId > selStartId ) || + ( dropId == selStartId && dropIndex > selStartIndex ) ) && + ( ( dropId < selEndId ) || + ( dropId == selEndId && dropIndex <= selEndIndex ) ) ) + insertCursor = c1; + if ( dropId == selEndId && dropIndex > selEndIndex ) { + insertCursor = c1; + if ( selStartId == selEndId ) { + insertCursor.setIndex( dropIndex - + ( selEndIndex - selStartIndex ) ); + } else { + insertCursor.setIndex( dropIndex - selEndIndex + + selStartIndex ); + } + } + } + + if ( internalDrag && e->action() == QDropEvent::Move ) { removeSelectedText(); @@ -1820,3 +1880,4 @@ void QTextEdit::contentsDropEvent( QDropEvent *e ) drawCursor( FALSE ); - placeCursor( e->pos(), cursor ); + cursor->setParagraph( insertCursor.paragraph() ); + cursor->setIndex( insertCursor.index() ); drawCursor( TRUE ); @@ -1861,9 +1922,9 @@ void QTextEdit::handleMouseMove( const QPoint& pos ) - int diff = QABS( oldCursor.parag()->at( oldCursor.index() )->x - mousePos.x() ); - int ldiff = QABS( cl.parag()->at( cl.index() )->x - mousePos.x() ); - int rdiff = QABS( cr.parag()->at( cr.index() )->x - mousePos.x() ); + int diff = QABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() ); + int ldiff = QABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() ); + int rdiff = QABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() ); - if ( cursor->parag()->lineStartOfChar( cursor->index() ) != - oldCursor.parag()->lineStartOfChar( oldCursor.index() ) ) + if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) != + oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) ) diff = 0xFFFFFF; @@ -1882,3 +1943,3 @@ void QTextEdit::handleMouseMove( const QPoint& pos ) if ( doc->hasSelection( QTextDocument::Standard ) ) { - redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; + redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; } @@ -1892,5 +1953,5 @@ void QTextEdit::handleMouseMove( const QPoint& pos ) - if ( currentFormat && currentFormat->key() != cursor->parag()->at( cursor->index() )->format()->key() ) { + if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) { currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( cursor->parag()->at( cursor->index() )->format() ); + currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() ); if ( currentFormat->isMisspelled() ) { @@ -1904,4 +1965,4 @@ void QTextEdit::handleMouseMove( const QPoint& pos ) - if ( currentAlignment != cursor->parag()->alignment() ) { - currentAlignment = cursor->parag()->alignment(); + if ( currentAlignment != cursor->paragraph()->alignment() ) { + currentAlignment = cursor->paragraph()->alignment(); block_set_alignment = TRUE; @@ -1927,10 +1988,20 @@ void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link ) c->restoreState(); - QTextParag *s = doc->firstParag(); + QTextParagraph *s = doc->firstParagraph(); c->place( pos, s, link ); + updateMicroFocusHint(); +} + + +void QTextEdit::updateMicroFocusHint() +{ + QTextCursor c( *cursor ); + if ( d->preeditStart != -1 ) + c.setIndex( d->preeditStart ); + if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); + int h = c.paragraph()->lineHeightOfChar( cursor->index() ); if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); + QFont f = c.paragraph()->at( c.index() )->format()->font(); + setMicroFocusHint( c.x() - contentsX() + frameWidth(), + c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); } @@ -1939,2 +2010,4 @@ void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link ) + + void QTextEdit::formatMore() @@ -1946,3 +2019,3 @@ void QTextEdit::formatMore() int lastBottom = -1; - int to = !sender() ? 2 : 20; + int to = 20; bool firstVisible = FALSE; @@ -1963,6 +2036,10 @@ void QTextEdit::formatMore() - if ( bottom > contentsHeight() ) + if ( bottom > contentsHeight() ) { resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) ); - else if ( lastBottom != -1 && lastBottom < contentsHeight() ) - resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) ); + } else if ( lastBottom != -1 && lastBottom < contentsHeight() ) { + resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) ); + if ( contentsHeight() < visibleHeight() ) + updateContents( 0, contentsHeight(), visibleWidth(), + visibleHeight() - contentsHeight() ); + } @@ -1982,3 +2059,3 @@ void QTextEdit::doResize() doc->invalidate(); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; @@ -2003,12 +2080,3 @@ bool QTextEdit::eventFilter( QObject *o, QEvent *e ) drawCursor( TRUE ); - - if ( !readonly ) { - // make sure the micro focus hint is updated... - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - - contentsY() + frameWidth(), 0, - cursor->parag()->lineHeightOfChar( cursor->index() ), - TRUE ); - } + updateMicroFocusHint(); } else if ( e->type() == QEvent::FocusOut ) { @@ -2022,10 +2090,10 @@ bool QTextEdit::eventFilter( QObject *o, QEvent *e ) -/*! - Inserts \a text at the current cursor position. If \a indent is TRUE, - the paragraph is re-indented. If \a checkNewLine is TRUE, newline - characters in \a text result in hard line breaks (i.e. new - paragraphs). If \a checkNewLine is FALSE the behaviour of the editor - is undefined if the \a text contains newlines. If \a removeSelected is - TRUE, any selected text (in selection 0) is removed before the text is - inserted. +/*! Inserts \a text at the current cursor position. If \a indent is + TRUE, the paragraph is re-indented. If \a checkNewLine is TRUE, + newline characters in \a text result in hard line breaks (i.e. new + paragraphs). If \a checkNewLine is FALSE and there are newlines in + \a text, the behavior is undefined. If \a checkNewLine is FALSE the + behaviour of the editor is undefined if the \a text contains + newlines. If \a removeSelected is TRUE, any selected text (in + selection 0) is removed before the text is inserted. @@ -2048,3 +2116,3 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); + undoRedoInfo.id = cursor->paragraph()->paragId(); undoRedoInfo.index = cursor->index(); @@ -2055,4 +2123,4 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo - lastFormatted = checkNewLine && cursor->parag()->prev() ? - cursor->parag()->prev() : cursor->parag(); + lastFormatted = checkNewLine && cursor->paragraph()->prev() ? + cursor->paragraph()->prev() : cursor->paragraph(); QTextCursor oldCursor = *cursor; @@ -2060,4 +2128,4 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo if ( doc->useFormatCollection() ) { - doc->setSelectionStart( QTextDocument::Temp, &oldCursor ); - doc->setSelectionEnd( QTextDocument::Temp, cursor ); + doc->setSelectionStart( QTextDocument::Temp, oldCursor ); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); @@ -2077,5 +2145,5 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo for ( int i = 0; i < (int)txt.length(); ++i ) { - if ( txt[ i ] != '\n' && c2.parag()->at( c2.index() )->format() ) { - c2.parag()->at( c2.index() )->format()->addRef(); - undoRedoInfo.d->text.setFormat( oldLen + i, c2.parag()->at( c2.index() )->format(), TRUE ); + if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) { + c2.paragraph()->at( c2.index() )->format()->addRef(); + undoRedoInfo.d->text.setFormat( oldLen + i, c2.paragraph()->at( c2.index() )->format(), TRUE ); } @@ -2086,17 +2154,10 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo - setModified(); - emit textChanged(); if ( !removeSelected ) { - doc->setSelectionStart( QTextDocument::Standard, &oldCursor ); - doc->setSelectionEnd( QTextDocument::Standard, cursor ); + doc->setSelectionStart( QTextDocument::Standard, oldCursor ); + doc->setSelectionEnd( QTextDocument::Standard, *cursor ); repaintChanged(); } - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); + setModified(); + emit textChanged(); } @@ -2107,3 +2168,4 @@ void QTextEdit::insertAt( const QString &text, int para, int index ) { - QTextParag *p = doc->paragAt( para ); + removeSelection( QTextDocument::Standard ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -2111,3 +2173,3 @@ void QTextEdit::insertAt( const QString &text, int para, int index ) QTextCursor tmp = *cursor; - cursor->setParag( p ); + cursor->setParagraph( p ); cursor->setIndex( index ); @@ -2124,9 +2186,9 @@ void QTextEdit::insertParagraph( const QString &text, int para ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( p ) { QTextCursor tmp( doc ); - tmp.setParag( p ); + tmp.setParagraph( p ); tmp.setIndex( 0 ); tmp.insert( text, TRUE ); - tmp.splitAndInsertEmptyParag(); + tmp.splitAndInsertEmptyParagraph(); repaintChanged(); @@ -2141,3 +2203,3 @@ void QTextEdit::removeParagraph( int para ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -2147,3 +2209,3 @@ void QTextEdit::removeParagraph( int para ) - if ( p == doc->firstParag() && p == doc->lastParag() ) { + if ( p == doc->firstParagraph() && p == doc->lastParagraph() ) { p->remove( 0, p->length() - 1 ); @@ -2153,3 +2215,3 @@ void QTextEdit::removeParagraph( int para ) drawCursor( FALSE ); - bool resetCursor = cursor->parag() == p; + bool resetCursor = cursor->paragraph() == p; if ( p->prev() ) @@ -2157,3 +2219,3 @@ void QTextEdit::removeParagraph( int para ) else - doc->setFirstParag( p->next() ); + doc->setFirstParagraph( p->next() ); if ( p->next() ) @@ -2161,4 +2223,4 @@ void QTextEdit::removeParagraph( int para ) else - doc->setLastParag( p->prev() ); - QTextParag *start = p->next(); + doc->setLastParagraph( p->prev() ); + QTextParagraph *start = p->next(); int h = p->rect().height(); @@ -2176,3 +2238,3 @@ void QTextEdit::removeParagraph( int para ) if ( resetCursor ) { - cursor->setParag( doc->firstParag() ); + cursor->setParagraph( doc->firstParagraph() ); cursor->setIndex( 0 ); @@ -2219,12 +2281,5 @@ void QTextEdit::undo() drawCursor( TRUE ); + updateMicroFocusHint(); setModified(); emit textChanged(); - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } } @@ -2264,12 +2319,5 @@ void QTextEdit::redo() drawCursor( TRUE ); + updateMicroFocusHint(); setModified(); emit textChanged(); - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } } @@ -2291,10 +2339,3 @@ void QTextEdit::paste() pasteSubType( "plain" ); - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); #endif @@ -2339,14 +2380,9 @@ void QTextEdit::cut() - if ( doc->hasSelection( QTextDocument::Standard ) ) { - doc->copySelectedText( QTextDocument::Standard ); + QString t; + if ( doc->hasSelection( QTextDocument::Standard ) && + !( t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ) ).isEmpty() ) { + QApplication::clipboard()->setText( t ); removeSelectedText(); } - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); } @@ -2360,4 +2396,6 @@ void QTextEdit::copy() { - if ( !doc->selectedText( QTextDocument::Standard ).isEmpty() ) - doc->copySelectedText( QTextDocument::Standard ); + QString t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ); + if ( doc->hasSelection( QTextDocument::Standard ) && + !t.isEmpty() && t.simplifyWhiteSpace() != "<selstart/>" ) + QApplication::clipboard()->setText( t ); } @@ -2414,13 +2452,13 @@ void QTextEdit::setFormat( QTextFormat *f, int flags ) drawCursor( FALSE ); - QString str = doc->selectedText( QTextDocument::Standard ); QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard ); + c1.restoreState(); QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard ); + c2.restoreState(); clearUndoRedo(); undoRedoInfo.type = UndoRedoInfo::Format; - undoRedoInfo.id = c1.parag()->paragId(); + undoRedoInfo.id = c1.paragraph()->paragId(); undoRedoInfo.index = c1.index(); - undoRedoInfo.eid = c2.parag()->paragId(); + undoRedoInfo.eid = c2.paragraph()->paragId(); undoRedoInfo.eindex = c2.index(); - undoRedoInfo.d->text = str; - readFormats( c1, c2, 0, undoRedoInfo.d->text ); + readFormats( c1, c2, undoRedoInfo.d->text ); undoRedoInfo.format = f; @@ -2445,8 +2483,8 @@ void QTextEdit::setFormat( QTextFormat *f, int flags ) emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); - if ( cursor->index() == cursor->parag()->length() - 1 ) { + if ( cursor->index() == cursor->paragraph()->length() - 1 ) { currentFormat->addRef(); - cursor->parag()->string()->setFormat( cursor->index(), currentFormat, TRUE ); - if ( cursor->parag()->length() == 1 ) { - cursor->parag()->invalidate( 0 ); - cursor->parag()->format(); + cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE ); + if ( cursor->paragraph()->length() == 1 ) { + cursor->paragraph()->invalidate( 0 ); + cursor->paragraph()->format(); repaintChanged(); @@ -2469,3 +2507,8 @@ void QTextEdit::setPalette( const QPalette &p ) -/*! +/*! \internal + + \warning In Qt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in Qt 4.0 this + function will go away. + Sets the paragraph style of the current paragraph @@ -2483,45 +2526,33 @@ void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem:: drawCursor( FALSE ); - if ( !doc->hasSelection( QTextDocument::Standard ) ) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::ParagType; - QValueList< QPtrVector<QStyleSheetItem> > oldStyles; - undoRedoInfo.oldStyles.clear(); - undoRedoInfo.oldStyles << cursor->parag()->styleSheetItems(); - undoRedoInfo.oldListStyles.clear(); - undoRedoInfo.oldListStyles << cursor->parag()->listStyle(); - undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; - undoRedoInfo.listStyle = listStyle; - undoRedoInfo.id = cursor->parag()->paragId(); - undoRedoInfo.eid = cursor->parag()->paragId(); - undoRedoInfo.d->text = " "; - undoRedoInfo.index = 1; - clearUndoRedo(); - cursor->parag()->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); - repaintChanged(); - } else { - QTextParag *start = doc->selectionStart( QTextDocument::Standard ); - QTextParag *end = doc->selectionEnd( QTextDocument::Standard ); - lastFormatted = start; - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::ParagType; - undoRedoInfo.id = start->paragId(); - undoRedoInfo.eid = end->paragId(); - undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; - undoRedoInfo.listStyle = listStyle; - undoRedoInfo.oldStyles.clear(); - undoRedoInfo.oldListStyles.clear(); - while ( start ) { - undoRedoInfo.oldStyles << start->styleSheetItems(); - undoRedoInfo.oldListStyles << start->listStyle(); - start->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); - if ( start == end ) - break; - start = start->next(); + QTextParagraph *start = cursor->paragraph(); + QTextParagraph *end = start; + if ( doc->hasSelection( QTextDocument::Standard ) ) { + start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph(); + end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph(); + if ( end->paragId() < start->paragId() ) + return; // do not trust our selections + } + + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = start->paragId(); + undoRedoInfo.eid = end->paragId(); + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + + while ( start != end->next() ) { + start->setListStyle( listStyle ); + if ( dm == QStyleSheetItem::DisplayListItem ) { + start->setListItem( TRUE ); + if( start->listDepth() == 0 ) + start->setListDepth( 1 ); + } else if ( start->isListItem() ) { + start->setListItem( FALSE ); + start->setListDepth( QMAX( start->listDepth()-1, 0 ) ); } - undoRedoInfo.d->text = " "; - undoRedoInfo.index = 1; - clearUndoRedo(); - repaintChanged(); - formatMore(); + start = start->next(); } + + clearUndoRedo(); + repaintChanged(); + formatMore(); drawCursor( TRUE ); @@ -2536,3 +2567,2 @@ void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem:: - \sa setParagType() */ @@ -2545,46 +2575,25 @@ void QTextEdit::setAlignment( int a ) drawCursor( FALSE ); - if ( !doc->hasSelection( QTextDocument::Standard ) ) { - if ( cursor->parag()->alignment() != a ) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Alignment; - QMemArray<int> oa( 1 ); - oa[ 0 ] = cursor->parag()->alignment(); - undoRedoInfo.oldAligns = oa; - undoRedoInfo.newAlign = a; - undoRedoInfo.id = cursor->parag()->paragId(); - undoRedoInfo.eid = cursor->parag()->paragId(); - undoRedoInfo.d->text = " "; - undoRedoInfo.index = 1; - clearUndoRedo(); - cursor->parag()->setAlignment( a ); - repaintChanged(); - } - } else { - QTextParag *start = doc->selectionStart( QTextDocument::Standard ); - QTextParag *end = doc->selectionEnd( QTextDocument::Standard ); - lastFormatted = start; - int len = end->paragId() - start->paragId() + 1; - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Alignment; - undoRedoInfo.id = start->paragId(); - undoRedoInfo.eid = end->paragId(); - QMemArray<int> oa( QMAX( 0, len ) ); - int i = 0; - while ( start ) { - if ( i < (int)oa.size() ) - oa[ i ] = start->alignment(); - start->setAlignment( a ); - if ( start == end ) - break; - start = start->next(); - ++i; - } - undoRedoInfo.oldAligns = oa; - undoRedoInfo.newAlign = a; - undoRedoInfo.d->text = " "; - undoRedoInfo.index = 1; - clearUndoRedo(); - repaintChanged(); - formatMore(); + QTextParagraph *start = cursor->paragraph(); + QTextParagraph *end = start; + if ( doc->hasSelection( QTextDocument::Standard ) ) { + start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph(); + end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph(); + if ( end->paragId() < start->paragId() ) + return; // do not trust our selections } + + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = start->paragId(); + undoRedoInfo.eid = end->paragId(); + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + + while ( start != end->next() ) { + start->setAlignment( a ); + start = start->next(); + } + + clearUndoRedo(); + repaintChanged(); + formatMore(); drawCursor( TRUE ); @@ -2604,6 +2613,6 @@ void QTextEdit::updateCurrentFormat() if ( doc->useFormatCollection() && - ( !currentFormat || currentFormat->key() != cursor->parag()->at( i )->format()->key() ) ) { + ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) { if ( currentFormat ) currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( cursor->parag()->at( i )->format() ); + currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() ); if ( currentFormat->isMisspelled() ) { @@ -2617,4 +2626,4 @@ void QTextEdit::updateCurrentFormat() - if ( currentAlignment != cursor->parag()->alignment() ) { - currentAlignment = cursor->parag()->alignment(); + if ( currentAlignment != cursor->paragraph()->alignment() ) { + currentAlignment = cursor->paragraph()->alignment(); block_set_alignment = TRUE; @@ -2780,3 +2789,4 @@ void QTextEdit::setText( const QString &text, const QString &context ) { - if ( !isModified() && this->context() == context && this->text() == text ) + if ( !isModified() && isReadOnly() && + this->context() == context && this->text() == text ) return; @@ -2801,6 +2811,5 @@ void QTextEdit::setText( const QString &text, const QString &context ) - cursor->setDocument( doc ); - lastFormatted = doc->firstParag(); - cursor->setParag( doc->firstParag() ); - cursor->setIndex( 0 ); + lastFormatted = doc->firstParagraph(); + delete cursor; + cursor = new QTextCursor( doc ); updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); @@ -2812,2 +2821,3 @@ void QTextEdit::setText( const QString &text, const QString &context ) updateCurrentFormat(); + d->scrollToAnchor = QString::null; } @@ -2849,5 +2859,5 @@ void QTextEdit::setText( const QString &text, const QString &context ) If \a para and \a index are both null the search begins from the - start of the text. If \a para and \a index are both not null, the - search begins from the \e *\a index character position in the \e - *\a para paragraph. + current cursor position. If \a para and \a index are both not + null, the search begins from the \e *\a index character position + in the \e *\a para paragraph. @@ -2875,3 +2885,2 @@ bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward, drawCursor( FALSE ); - doc->removeSelection( QTextDocument::Standard ); #ifndef QT_NO_CURSOR @@ -2879,6 +2888,27 @@ bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward, #endif - bool found = doc->find( expr, cs, wo, forward, para, index, cursor ); - ensureCursorVisible(); + QTextCursor findcur = *cursor; + if ( para && index ) { + if ( doc->paragAt( *para ) ) + findcur.gotoPosition( doc->paragAt(*para), *index ); + else + findcur.gotoEnd(); + } else if ( doc->hasSelection( QTextDocument::Standard ) ){ + // maks sure we do not find the same selection again + if ( forward ) + findcur.gotoNextLetter(); + else + findcur.gotoPreviousLetter(); + } + removeSelection( QTextDocument::Standard ); + bool found = doc->find( findcur, expr, cs, wo, forward ); + if ( found ) { + if ( para ) + *para = findcur.paragraph()->paragId(); + if ( index ) + *index = findcur.index(); + *cursor = findcur; + repaintChanged(); + ensureCursorVisible(); + } drawCursor( TRUE ); - repaintChanged(); return found; @@ -2904,3 +2934,3 @@ void QTextEdit::setCursorPosition( int para, int index ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -2912,3 +2942,3 @@ void QTextEdit::setCursorPosition( int para, int index ) drawCursor( FALSE ); - cursor->setParag( p ); + cursor->setParagraph( p ); cursor->setIndex( index ); @@ -2916,4 +2946,5 @@ void QTextEdit::setCursorPosition( int para, int index ) drawCursor( TRUE ); + updateCurrentFormat(); emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); } @@ -2932,3 +2963,3 @@ void QTextEdit::getCursorPosition( int *para, int *index ) const return; - *para = cursor->parag()->paragId(); + *para = cursor->paragraph()->paragId(); *index = cursor->index(); @@ -2960,6 +2991,6 @@ void QTextEdit::setSelection( int paraFrom, int indexFrom, doc->addSelection( selNum ); - QTextParag *p1 = doc->paragAt( paraFrom ); + QTextParagraph *p1 = doc->paragAt( paraFrom ); if ( !p1 ) return; - QTextParag *p2 = doc->paragAt( paraTo ); + QTextParagraph *p2 = doc->paragAt( paraTo ); if ( !p2 ) @@ -2975,8 +3006,8 @@ void QTextEdit::setSelection( int paraFrom, int indexFrom, QTextCursor oldCursor = *cursor; - c.setParag( p1 ); + c.setParagraph( p1 ); c.setIndex( indexFrom ); - cursor->setParag( p2 ); + cursor->setParagraph( p2 ); cursor->setIndex( indexTo ); - doc->setSelectionStart( selNum, &c ); - doc->setSelectionEnd( selNum, cursor ); + doc->setSelectionStart( selNum, c ); + doc->setSelectionEnd( selNum, *cursor ); repaintChanged(); @@ -3058,3 +3089,3 @@ int QTextEdit::paragraphs() const { - return doc->lastParag()->paragId() + 1; + return doc->lastParagraph()->paragId() + 1; } @@ -3068,3 +3099,3 @@ int QTextEdit::linesOfParagraph( int para ) const { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -3081,3 +3112,3 @@ int QTextEdit::paragraphLength( int para ) const { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -3097,3 +3128,3 @@ int QTextEdit::lines() const { - QTextParag *p = doc->firstParag(); + QTextParagraph *p = doc->firstParagraph(); int l = 0; @@ -3117,3 +3148,3 @@ int QTextEdit::lineOfChar( int para, int index ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -3250,3 +3281,3 @@ void QTextEdit::startDrag() inDoubleClick = FALSE; - QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard ), viewport() ); + QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ), viewport() ); if ( isReadOnly() ) { @@ -3287,12 +3318,12 @@ void QTextEdit::UndoRedoInfo::clear() if ( type == Insert || type == Return ) - doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); + doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) ); else if ( type == Format ) doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); - else if ( type == Alignment ) - doc->addCommand( new QTextAlignmentCommand( doc, id, eid, newAlign, oldAligns ) ); - else if ( type == ParagType ) - doc->addCommand( new QTextParagTypeCommand( doc, id, eid, list, listStyle, oldStyles, oldListStyles ) ); - else if ( type != Invalid ) - doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); + else if ( type == Style ) + doc->addCommand( new QTextStyleCommand( doc, id, eid, styleInformation ) ); + else if ( type != Invalid ) { + doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) ); + } } + type = Invalid; d->text = QString::null; @@ -3300,5 +3331,3 @@ void QTextEdit::UndoRedoInfo::clear() index = -1; - oldStyles.clear(); - oldListStyles.clear(); - oldAligns.resize( 0 ); + styleInformation = QByteArray(); } @@ -3342,3 +3371,3 @@ bool QTextEdit::UndoRedoInfo::valid() const { - return d->text.length() > 0 && id >= 0 && index >= 0; + return id >= 0 && type != Invalid; } @@ -3411,6 +3440,3 @@ void QTextEdit::setLinkUnderline( bool b ) { - if ( b == doc->underlineLinks() ) - return; doc->setUnderlineLinks( b ); - updateStyles(); } @@ -3467,6 +3493,5 @@ void QTextEdit::append( const QString &text ) // flush and clear the undo/redo stack if necessary - if ( isReadOnly() && undoRedoInfo.valid() ) { - undoRedoInfo.clear(); - doc->commands()->clear(); - } + undoRedoInfo.clear(); + doc->commands()->clear(); + doc->removeSelection( QTextDocument::Standard ); @@ -3479,17 +3504,18 @@ void QTextEdit::append( const QString &text ) } - if ( f == PlainText ) { - QTextCursor oldc( *cursor ); - ensureFormatted( doc->lastParag() ); - bool scrollToEnd = contentsY() >= contentsHeight() - visibleHeight() - - ( horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0 ); - if ( !scrollToEnd ) - blockEnsureCursorVisible = TRUE; - cursor->gotoEnd(); - if ( cursor->index() > 0 ) - cursor->splitAndInsertEmptyParag(); - QTextCursor oldCursor2 = *cursor; - cursor->insert( text, TRUE ); - if ( doc->useFormatCollection() && currentFormat != cursor->parag()->at( cursor->index() )->format() ) { - doc->setSelectionStart( QTextDocument::Temp, &oldCursor2 ); - doc->setSelectionEnd( QTextDocument::Temp, cursor ); + + drawCursor( FALSE ); + QTextCursor oldc( *cursor ); + ensureFormatted( doc->lastParagraph() ); + bool atBottom = contentsY() >= contentsHeight() - visibleHeight(); + cursor->gotoEnd(); + if ( cursor->index() > 0 ) + cursor->splitAndInsertEmptyParagraph(); + QTextCursor oldCursor2 = *cursor; + + if ( f == Qt::PlainText ) { + cursor->insert( text, TRUE ); + if ( doc->useFormatCollection() && + currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) { + doc->setSelectionStart( QTextDocument::Temp, oldCursor2 ); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); @@ -3497,13 +3523,14 @@ void QTextEdit::append( const QString &text ) } - formatMore(); - repaintChanged(); - ensureCursorVisible(); - drawCursor( TRUE ); - *cursor = oldc; - if ( !scrollToEnd ) - blockEnsureCursorVisible = FALSE; - } else if ( f == RichText ) { + } else { + if ( cursor->paragraph()->prev() ) + cursor->paragraph()->prev()->invalidate(0); // vertical margins might have to change doc->setRichTextInternal( text ); - repaintChanged(); } + formatMore(); + repaintChanged(); + if ( atBottom ) + scrollToBottom(); + *cursor = oldc; + if ( !isReadOnly() ) + cursorVisible = TRUE; setModified(); @@ -3619,3 +3646,3 @@ QString QTextEdit::documentTitle() const -void QTextEdit::makeParagVisible( QTextParag *p ) +void QTextEdit::makeParagVisible( QTextParagraph *p ) { @@ -3632,2 +3659,6 @@ void QTextEdit::scrollToAnchor( const QString& name ) { + if ( !isVisible() ) { + d->scrollToAnchor = name; + return; + } if ( name.isEmpty() ) @@ -3636,5 +3667,5 @@ void QTextEdit::scrollToAnchor( const QString& name ) QTextCursor cursor( doc ); - QTextParag* last = doc->lastParag(); - do { - QTextStringChar* c = cursor.parag()->at( cursor.index() ); + QTextParagraph* last = doc->lastParagraph(); + for (;;) { + QTextStringChar* c = cursor.paragraph()->at( cursor.index() ); if( c->isAnchor() ) { @@ -3643,8 +3674,10 @@ void QTextEdit::scrollToAnchor( const QString& name ) (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) { - setContentsPos( contentsX(), QMIN( cursor.parag()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); - return; + setContentsPos( contentsX(), QMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); + break; } } + if ( cursor.paragraph() == last && cursor.atParagEnd() ) + break; cursor.gotoNextLetter(); - } while( cursor.parag() != last || !cursor.atParagEnd() ); + } } @@ -3660,3 +3693,3 @@ QString QTextEdit::anchorAt( const QPoint& pos ) placeCursor( pos, &c ); - return c.parag()->at( c.index() )->anchorHref(); + return c.paragraph()->at( c.index() )->anchorHref(); } @@ -3668,5 +3701,5 @@ void QTextEdit::documentWidthChanged( int w ) -/*! - Updates all the rendering styles used to display the text. You will - probably want to call this function after calling setStyleSheet(). +/*! \internal + + This function does nothing */ @@ -3675,4 +3708,2 @@ void QTextEdit::updateStyles() { - doc->updateStyles(); - updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); } @@ -3684,4 +3715,6 @@ void QTextEdit::setDocument( QTextDocument *dc ) doc = dc; - cursor->setDocument( doc ); + delete cursor; + cursor = new QTextCursor( doc ); clearUndoRedo(); + undoRedoInfo.doc = doc; lastFormatted = 0; @@ -3705,3 +3738,48 @@ void QTextEdit::pasteSubType( const QCString& subtype ) QString t = QApplication::clipboard()->text(st); + if ( doc->hasSelection( QTextDocument::Standard ) ) + removeSelectedText(); if ( !t.isEmpty() ) { + if ( t.startsWith( "<selstart/>" ) ) { + t.remove( 0, 11 ); + QTextCursor oldC = *cursor; + lastFormatted = cursor->paragraph(); + if ( lastFormatted->prev() ) + lastFormatted = lastFormatted->prev(); + doc->setRichTextInternal( t, cursor ); + + if ( undoEnabled && !isReadOnly() ) { + doc->setSelectionStart( QTextDocument::Temp, oldC ); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); + + checkUndoRedoInfo( UndoRedoInfo::Insert ); + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = oldC.paragraph()->paragId(); + undoRedoInfo.index = oldC.index(); + undoRedoInfo.d->text = QString::null; + } + int oldLen = undoRedoInfo.d->text.length(); + if ( !doc->preProcessor() ) { + QString txt = doc->selectedText( QTextDocument::Temp ); + undoRedoInfo.d->text += txt; + for ( int i = 0; i < (int)txt.length(); ++i ) { + if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) { + oldC.paragraph()->at( oldC.index() )->format()->addRef(); + undoRedoInfo.d->text. + setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE ); + } + oldC.gotoNextLetter(); + } + } + undoRedoInfo.clear(); + removeSelection( QTextDocument::Temp ); + } + + formatMore(); + setModified(); + emit textChanged(); + repaintChanged(); + ensureCursorVisible(); + return; + } + #if defined(Q_OS_WIN32) @@ -3840,3 +3918,3 @@ void QTextEdit::setWordWrap( WordWrap mode ) updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; @@ -3901,3 +3979,3 @@ void QTextEdit::setWrapColumnOrWidth( int value ) updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; @@ -3954,3 +4032,3 @@ void QTextEdit::setWrapPolicy( WrapPolicy policy ) updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; @@ -3981,5 +4059,4 @@ void QTextEdit::clear() doc->clear( TRUE ); - cursor->setDocument( doc ); - cursor->setParag( doc->firstParag() ); - cursor->setIndex( 0 ); + delete cursor; + cursor = new QTextCursor( doc ); lastFormatted = 0; @@ -3988,3 +4065,3 @@ void QTextEdit::clear() emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); } @@ -4027,3 +4104,3 @@ void QTextEdit::setTabStopWidth( int ts ) doc->invalidate(); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; @@ -4048,3 +4125,9 @@ void QTextEdit::clearUndoRedo() -/*! This function gets the format of the character at position \a +/*! \internal + + \warning In Qt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in Qt 4.0 this + function will go away. + + This function gets the format of the character at position \a index in paragraph \a para. Sets \a font to the character's font, \a @@ -4061,3 +4144,3 @@ bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, Vert return FALSE; - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -4072,3 +4155,9 @@ bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, Vert -/*! This function gets the format of the paragraph \a para. Sets \a +/*! \internal + + \warning In Qt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in Qt 4.0 this + function will go away. + + This function gets the format of the paragraph \a para. Sets \a font to the paragraphs's font, \a color to the paragraph's color, \a @@ -4092,10 +4181,10 @@ bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color, return FALSE; - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return FALSE; - *font = p->paragFormat()->font(); - *color = p->paragFormat()->color(); - *verticalAlignment = (VerticalAlignment)p->paragFormat()->vAlign(); + *font = p->at(0)->format()->font(); + *color = p->at(0)->format()->color(); + *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign(); *alignment = p->alignment(); - *displayMode = p->style() ? p->style()->displayMode() : QStyleSheetItem::DisplayBlock; + *displayMode = p->isListItem() ? QStyleSheetItem::DisplayListItem : QStyleSheetItem::DisplayBlock; *listStyle = p->listStyle(); @@ -4157,2 +4246,3 @@ QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos ) /*! \overload + \obsolete This function is called to create a right mouse button popup menu. @@ -4161,2 +4251,5 @@ QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos ) transferred to the caller. + + This function is only called if createPopupMenu( const QPoint & ) + returns 0. */ @@ -4175,17 +4268,4 @@ void QTextEdit::setFont( const QFont &f ) doc->setMinimumWidth( -1 ); - - // ### that is a bit hacky - static short diff = 1; - diff *= -1; - doc->setWidth( visibleWidth() + diff ); - - int s = f.pointSize(); - bool usePixels = FALSE; - if ( s == -1 ) { - s = f.pixelSize(); - usePixels = TRUE; - } - doc->updateFontSizes( s, usePixels ); - doc->updateFontAttributes( f, old ); - lastFormatted = doc->firstParag(); + doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() ); + lastFormatted = doc->firstParagraph(); formatMore(); @@ -4275,6 +4355,5 @@ void QTextEdit::sync() { - QTextParag *p = lastFormatted; - while ( p ) { - p->format(); - p = p->next(); + while ( lastFormatted ) { + lastFormatted->format(); + lastFormatted = lastFormatted->next(); } @@ -4362,3 +4441,3 @@ QRect QTextEdit::paragraphRect( int para ) const that->sync(); - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -4376,5 +4455,5 @@ int QTextEdit::paragraphAt( const QPoint &pos ) const QTextCursor c( doc ); - c.place( pos, doc->firstParag() ); - if ( c.parag() ) - return c.parag()->paragId(); + c.place( pos, doc->firstParagraph() ); + if ( c.paragraph() ) + return c.paragraph()->paragId(); return -1; @@ -4392,6 +4471,6 @@ int QTextEdit::charAt( const QPoint &pos, int *para ) const QTextCursor c( doc ); - c.place( pos, doc->firstParag() ); - if ( c.parag() ) { + c.place( pos, doc->firstParagraph() ); + if ( c.paragraph() ) { if ( para ) - *para = c.parag()->paragId(); + *para = c.paragraph()->paragId(); return c.index(); @@ -4405,3 +4484,3 @@ void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -4418,3 +4497,3 @@ void QTextEdit::clearParagraphBackground( int para ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -4432,3 +4511,3 @@ QColor QTextEdit::paragraphBackgroundColor( int para ) const { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) @@ -4471,3 +4550,3 @@ bool QTextEdit::isRedoAvailable() const -void QTextEdit::ensureFormatted( QTextParag *p ) +void QTextEdit::ensureFormatted( QTextParagraph *p ) { @@ -4488,7 +4567,7 @@ void QTextEdit::updateCursor( const QPoint & pos ) #ifndef QT_NO_NETWORKPROTOCOL - if ( c.parag() && c.parag()->at( c.index() ) && - c.parag()->at( c.index() )->isAnchor() && - !c.parag()->at( c.index() )->anchorHref().isEmpty() ) { - if ( c.index() < c.parag()->length() - 1 ) - onLink = c.parag()->at( c.index() )->anchorHref(); + if ( c.paragraph() && c.paragraph()->at( c.index() ) && + c.paragraph()->at( c.index() )->isAnchor() && + !c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) { + if ( c.index() < c.paragraph()->length() - 1 ) + onLink = c.paragraph()->at( c.index() )->anchorHref(); else |