00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "qtextedit.h"
00039
00040 #include "qrichtext_p.h"
00041 #include "qlistbox.h"
00042 #include "qclipboard.h"
00043 #include "qpopupmenu.h"
00044
00045 #define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k)
00046
00047 using namespace Qt3;
00048
00049 static bool qt_enable_richtext_copy = FALSE;
00050
00051 struct QUndoRedoInfoPrivate
00052 {
00053 QTextString text;
00054 };
00055
00056 namespace Qt3 {
00057
00058 class QTextEditPrivate
00059 {
00060 public:
00061 QTextEditPrivate()
00062 :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE)
00063 {
00064 for ( int i=0; i<7; i++ )
00065 id[i] = 0;
00066 }
00067 int id[ 7 ];
00068 int preeditStart;
00069 int preeditLength;
00070 bool ensureCursorVisibleInShowEvent;
00071 QString scrollToAnchor;
00072 };
00073
00074 }
00075
00076 static bool block_set_alignment = FALSE;
00077
00625 QTextEdit::QTextEdit( QWidget *parent, const char *name )
00626 : QScrollView( parent, name, WStaticContents | WRepaintNoErase | WResizeNoErase ),
00627 doc( new QTextDocument( 0 ) ), undoRedoInfo( doc )
00628 {
00629 init();
00630 }
00631
00653 QTextEdit::QTextEdit( const QString& text, const QString& context,
00654 QWidget *parent, const char *name)
00655 : QScrollView( parent, name, WStaticContents | WRepaintNoErase | WResizeNoErase ),
00656 doc( new QTextDocument( 0 ) ), undoRedoInfo( doc )
00657 {
00658 init();
00659 setText( text, context );
00660 }
00661
00664 QTextEdit::~QTextEdit()
00665 {
00666 delete undoRedoInfo.d;
00667 undoRedoInfo.d = 0;
00668 delete cursor;
00669 delete doc;
00670 delete d;
00671 }
00672
00673 void QTextEdit::init()
00674 {
00675 setFrameStyle( Sunken );
00676 setVScrollBarMode( AlwaysOn );
00677 undoEnabled = TRUE;
00678 readonly = TRUE;
00679 setReadOnly( FALSE );
00680 d = new QTextEditPrivate;
00681 connect( doc, SIGNAL( minimumWidthChanged(int) ),
00682 this, SLOT( documentWidthChanged(int) ) );
00683
00684 mousePressed = FALSE;
00685 inDoubleClick = FALSE;
00686 modified = FALSE;
00687 onLink = QString::null;
00688 overWrite = FALSE;
00689 wrapMode = WidgetWidth;
00690 wrapWidth = -1;
00691 wPolicy = AtWhiteSpace;
00692 inDnD = FALSE;
00693
00694 doc->setFormatter( new QTextFormatterBreakWords );
00695 doc->formatCollection()->defaultFormat()->setFont( QScrollView::font() );
00696 doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( QColorGroup::Text ) );
00697 currentFormat = doc->formatCollection()->defaultFormat();
00698 currentAlignment = Qt3::AlignAuto;
00699
00700 viewport()->setBackgroundMode( PaletteBase );
00701 viewport()->setAcceptDrops( TRUE );
00702 resizeContents( 0, doc->lastParagraph() ?
00703 ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 );
00704
00705 setKeyCompression( TRUE );
00706 viewport()->setMouseTracking( TRUE );
00707 #ifndef QT_NO_CURSOR
00708 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
00709 #endif
00710 cursor = new QTextCursor( doc );
00711
00712 formatTimer = new QTimer( this );
00713 connect( formatTimer, SIGNAL( timeout() ),
00714 this, SLOT( formatMore() ) );
00715 lastFormatted = doc->firstParagraph();
00716
00717 scrollTimer = new QTimer( this );
00718 connect( scrollTimer, SIGNAL( timeout() ),
00719 this, SLOT( autoScrollTimerDone() ) );
00720
00721 interval = 0;
00722 changeIntervalTimer = new QTimer( this );
00723 connect( changeIntervalTimer, SIGNAL( timeout() ),
00724 this, SLOT( doChangeInterval() ) );
00725
00726 cursorVisible = TRUE;
00727 blinkTimer = new QTimer( this );
00728 connect( blinkTimer, SIGNAL( timeout() ),
00729 this, SLOT( blinkCursor() ) );
00730
00731 #ifndef QT_NO_DRAGANDDROP
00732 dragStartTimer = new QTimer( this );
00733 connect( dragStartTimer, SIGNAL( timeout() ),
00734 this, SLOT( startDrag() ) );
00735 #endif
00736
00737
00738 formatMore();
00739
00740 blinkCursorVisible = FALSE;
00741
00742 viewport()->setFocusProxy( this );
00743 viewport()->setFocusPolicy( WheelFocus );
00744 viewport()->installEventFilter( this );
00745 installEventFilter( this );
00746 }
00747
00748 void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw, int ch )
00749 {
00750 bool drawCur = hasFocus() || viewport()->hasFocus();
00751 if ( hasSelectedText() || isReadOnly() || !cursorVisible )
00752 drawCur = FALSE;
00753 QColorGroup g = colorGroup();
00754 if ( doc->paper() )
00755 g.setBrush( QColorGroup::Base, *doc->paper() );
00756
00757 if ( contentsY() < doc->y() ) {
00758 p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(),
00759 g.brush( QColorGroup::Base ) );
00760 }
00761 if ( drawAll && doc->width() - contentsX() < cx + cw ) {
00762 p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch,
00763 g.brush( QColorGroup::Base ) );
00764 }
00765
00766 p->setBrushOrigin( -contentsX(), -contentsY() );
00767
00768 lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor );
00769
00770 if ( lastFormatted == doc->lastParagraph() )
00771 resizeContents( contentsWidth(), doc->height() );
00772
00773 if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll )
00774 p->fillRect( 0, contentsHeight(), visibleWidth(),
00775 visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) );
00776 }
00777
00780 void QTextEdit::drawContents( QPainter *p, int cx, int cy, int cw, int ch )
00781 {
00782 paintDocument( TRUE, p, cx, cy, cw, ch );
00783 int v;
00784 p->setPen( foregroundColor() );
00785 if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) {
00786 int l = int(cy / v) * v;
00787 while ( l < cy + ch ) {
00788 p->drawLine( cx, l, cx + cw - 1, l );
00789 l += v;
00790 }
00791 }
00792
00793 }
00794
00797 void QTextEdit::drawContents( QPainter * )
00798 {
00799 }
00800
00803 bool QTextEdit::event( QEvent *e )
00804 {
00805 if ( e->type() == QEvent::AccelOverride && !isReadOnly() ) {
00806 QKeyEvent* ke = (QKeyEvent*) e;
00807 if ( ke->state() == NoButton || ke->state() == Keypad ) {
00808 if ( ke->key() < Key_Escape ) {
00809 ke->accept();
00810 } else {
00811 switch ( ke->key() ) {
00812 case Key_Return:
00813 case Key_Enter:
00814 case Key_Delete:
00815 case Key_Home:
00816 case Key_End:
00817 case Key_Backspace:
00818 ke->accept();
00819 default:
00820 break;
00821 }
00822 }
00823 } else if ( ke->state() & ControlButton ) {
00824 switch ( ke->key() ) {
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 case Key_C:
00839 case Key_V:
00840 case Key_X:
00841 case Key_Y:
00842 case Key_Z:
00843 case Key_Left:
00844 case Key_Right:
00845 case Key_Up:
00846 case Key_Down:
00847 case Key_Home:
00848 case Key_End:
00849 case Key_Tab:
00850 #if defined (Q_WS_WIN)
00851 case Key_Insert:
00852 case Key_Delete:
00853 #endif
00854 ke->accept();
00855 default:
00856 break;
00857 }
00858 } else {
00859 switch ( ke->key() ) {
00860 #if defined (Q_WS_WIN)
00861 case Key_Insert:
00862 ke->accept();
00863 #endif
00864 default:
00865 break;
00866 }
00867 }
00868 }
00869
00870 if ( e->type() == QEvent::Show ) {
00871 if ( d->ensureCursorVisibleInShowEvent ) {
00872 sync();
00873 ensureCursorVisible();
00874 d->ensureCursorVisibleInShowEvent = FALSE;
00875 }
00876 if ( !d->scrollToAnchor.isEmpty() ) {
00877 scrollToAnchor( d->scrollToAnchor );
00878 d->scrollToAnchor = QString::null;
00879 }
00880 }
00881 return QWidget::event( e );
00882 }
00883
00890 void QTextEdit::keyPressEvent( QKeyEvent *e )
00891 {
00892 changeIntervalTimer->stop();
00893 interval = 10;
00894 bool unknown = FALSE;
00895 if ( isReadOnly() ) {
00896 if ( !handleReadOnlyKeyEvent( e ) )
00897 QScrollView::keyPressEvent( e );
00898 changeIntervalTimer->start( 100, TRUE );
00899 return;
00900 }
00901
00902
00903 bool selChanged = FALSE;
00904 for ( int i = 1; i < doc->numSelections(); ++i )
00905 selChanged = doc->removeSelection( i ) || selChanged;
00906
00907 if ( selChanged ) {
00908 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
00909 repaintChanged();
00910 }
00911
00912 bool clearUndoRedoInfo = TRUE;
00913
00914
00915 switch ( e->key() ) {
00916 case Key_Left:
00917 case Key_Right: {
00918
00919
00920 CursorAction a;
00921 if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) )
00922 a = e->state() & ControlButton ? MoveWordBackward : MoveBackward;
00923 else
00924 a = e->state() & ControlButton ? MoveWordForward : MoveForward;
00925 moveCursor( a, e->state() & ShiftButton );
00926 break;
00927 }
00928 case Key_Up:
00929 moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton );
00930 break;
00931 case Key_Down:
00932 moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton );
00933 break;
00934 case Key_Home:
00935 moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton );
00936 break;
00937 case Key_End:
00938 moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton );
00939 break;
00940 case Key_Prior:
00941 moveCursor( MovePgUp, e->state() & ShiftButton );
00942 break;
00943 case Key_Next:
00944 moveCursor( MovePgDown, e->state() & ShiftButton );
00945 break;
00946 case Key_Return: case Key_Enter:
00947 if ( doc->hasSelection( QTextDocument::Standard, FALSE ) )
00948 removeSelectedText();
00949 if ( textFormat() == Qt::RichText && ( e->state() & ControlButton ) ) {
00950
00951 insert( QString( QChar( 0x2028) ), TRUE, FALSE, TRUE );
00952 } else {
00953 #ifndef QT_NO_CURSOR
00954 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
00955 #endif
00956 clearUndoRedoInfo = FALSE;
00957 doKeyboardAction( ActionReturn );
00958 emit returnPressed();
00959 }
00960 break;
00961 case Key_Delete:
00962 #if defined (Q_WS_WIN)
00963 if ( e->state() & ShiftButton ) {
00964 cut();
00965 break;
00966 } else
00967 #endif
00968 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) {
00969 removeSelectedText();
00970 break;
00971 }
00972 doKeyboardAction( ActionDelete );
00973 clearUndoRedoInfo = FALSE;
00974
00975 break;
00976 case Key_Insert:
00977 if ( e->state() & ShiftButton )
00978 paste();
00979 #if defined (Q_WS_WIN)
00980 else if ( e->state() & ControlButton )
00981 copy();
00982 #endif
00983 break;
00984 case Key_Backspace:
00985 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) {
00986 removeSelectedText();
00987 break;
00988 }
00989
00990 doKeyboardAction( ActionBackspace );
00991 clearUndoRedoInfo = FALSE;
00992
00993 break;
00994 case Key_F16:
00995 copy();
00996 break;
00997 case Key_F18:
00998 paste();
00999 break;
01000 case Key_F20:
01001 cut();
01002 break;
01003 default: {
01004 if ( e->text().length() &&
01005 ( !( e->state() & ControlButton ) &&
01006 !( e->state() & AltButton ) ||
01007 ( ( e->state() & ControlButton | AltButton ) == (ControlButton|AltButton) ) ) &&
01008 ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) {
01009 clearUndoRedoInfo = FALSE;
01010 if ( e->key() == Key_Tab ) {
01011 if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() ) {
01012 clearUndoRedo();
01013 undoRedoInfo.type = UndoRedoInfo::Style;
01014 undoRedoInfo.id = cursor->paragraph()->paragId();
01015 undoRedoInfo.eid = undoRedoInfo.id;
01016 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
01017 cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 );
01018 clearUndoRedo();
01019 drawCursor( FALSE );
01020 repaintChanged();
01021 drawCursor( TRUE );
01022 break;
01023 }
01024 }
01025
01026 if ( textFormat() == Qt::RichText && !cursor->paragraph()->isListItem() ) {
01027 if ( cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) {
01028 clearUndoRedo();
01029 undoRedoInfo.type = UndoRedoInfo::Style;
01030 undoRedoInfo.id = cursor->paragraph()->paragId();
01031 undoRedoInfo.eid = undoRedoInfo.id;
01032 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
01033 setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc );
01034 clearUndoRedo();
01035 drawCursor( FALSE );
01036 repaintChanged();
01037 drawCursor( TRUE );
01038 break;
01039 }
01040 }
01041 if ( overWrite && !cursor->atParagEnd() )
01042 cursor->remove();
01043 QString t = e->text();
01044 QTextParagraph *p = cursor->paragraph();
01045 if ( p && p->string() && p->string()->isRightToLeft() ) {
01046 QChar *c = (QChar *)t.unicode();
01047 int l = t.length();
01048 while( l-- ) {
01049 if ( c->mirrored() )
01050 *c = c->mirroredChar();
01051 c++;
01052 }
01053 }
01054 insert( t, TRUE, FALSE, TRUE );
01055 break;
01056 } else if ( e->state() & ControlButton ) {
01057 switch ( e->key() ) {
01058 case Key_C: case Key_F16:
01059 copy();
01060 break;
01061 case Key_V:
01062 paste();
01063 break;
01064 case Key_X:
01065 cut();
01066 break;
01067 case Key_I: case Key_T: case Key_Tab:
01068 indent();
01069 break;
01070 case Key_A:
01071 #if defined(Q_WS_X11)
01072 moveCursor( MoveLineStart, e->state() & ShiftButton );
01073 #else
01074 selectAll( TRUE );
01075 #endif
01076 break;
01077 case Key_B:
01078 moveCursor( MoveBackward, e->state() & ShiftButton );
01079 break;
01080 case Key_F:
01081 moveCursor( MoveForward, e->state() & ShiftButton );
01082 break;
01083 case Key_D:
01084 if ( doc->hasSelection( QTextDocument::Standard ) ) {
01085 removeSelectedText();
01086 break;
01087 }
01088 doKeyboardAction( ActionDelete );
01089 clearUndoRedoInfo = FALSE;
01090 break;
01091 case Key_H:
01092 if ( doc->hasSelection( QTextDocument::Standard ) ) {
01093 removeSelectedText();
01094 break;
01095 }
01096 if ( !cursor->paragraph()->prev() &&
01097 cursor->atParagStart() )
01098 break;
01099
01100 doKeyboardAction( ActionBackspace );
01101 clearUndoRedoInfo = FALSE;
01102 break;
01103 case Key_E:
01104 moveCursor( MoveLineEnd, e->state() & ShiftButton );
01105 break;
01106 case Key_N:
01107 moveCursor( MoveDown, e->state() & ShiftButton );
01108 break;
01109 case Key_P:
01110 moveCursor( MoveUp, e->state() & ShiftButton );
01111 break;
01112 case Key_Z:
01113 if(e->state() & ShiftButton)
01114 redo();
01115 else
01116 undo();
01117 break;
01118 case Key_Y:
01119 redo();
01120 break;
01121 case Key_K:
01122 doKeyboardAction( ActionKill );
01123 break;
01124 #if defined(Q_WS_WIN)
01125 case Key_Insert:
01126 copy();
01127 break;
01128 case Key_Delete:
01129 del();
01130 break;
01131 #endif
01132 default:
01133 unknown = FALSE;
01134 break;
01135 }
01136 } else {
01137 unknown = TRUE;
01138 }
01139 }
01140 }
01141
01142 emit cursorPositionChanged( cursor );
01143 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
01144 if ( clearUndoRedoInfo )
01145 clearUndoRedo();
01146 changeIntervalTimer->start( 100, TRUE );
01147 if ( unknown )
01148 e->ignore();
01149 }
01150
01156 void QTextEdit::doKeyboardAction( KeyboardAction action )
01157 {
01158 if ( isReadOnly() )
01159 return;
01160
01161 if ( cursor->nestedDepth() != 0 )
01162 return;
01163
01164 lastFormatted = cursor->paragraph();
01165 drawCursor( FALSE );
01166 bool doUpdateCurrentFormat = TRUE;
01167
01168 switch ( action ) {
01169 case ActionDelete:
01170 if ( !cursor->atParagEnd() ) {
01171 checkUndoRedoInfo( UndoRedoInfo::Delete );
01172 if ( !undoRedoInfo.valid() ) {
01173 undoRedoInfo.id = cursor->paragraph()->paragId();
01174 undoRedoInfo.index = cursor->index();
01175 undoRedoInfo.d->text = QString::null;
01176 }
01177 undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( cursor->index() ), TRUE );
01178 cursor->remove();
01179 } else {
01180 clearUndoRedo();
01181 doc->setSelectionStart( QTextDocument::Temp, *cursor );
01182 cursor->gotoNextLetter();
01183 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
01184 removeSelectedText( QTextDocument::Temp );
01185 }
01186 break;
01187 case ActionBackspace:
01188 if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() && cursor->index() == 0 ) {
01189 clearUndoRedo();
01190 undoRedoInfo.type = UndoRedoInfo::Style;
01191 undoRedoInfo.id = cursor->paragraph()->paragId();
01192 undoRedoInfo.eid = undoRedoInfo.id;
01193 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
01194 int ldepth = cursor->paragraph()->listDepth();
01195 ldepth = QMAX( ldepth-1, 0 );
01196 cursor->paragraph()->setListDepth( ldepth );
01197 if ( ldepth == 0 )
01198 cursor->paragraph()->setListItem( FALSE );
01199 clearUndoRedo();
01200 lastFormatted = cursor->paragraph();
01201 repaintChanged();
01202 drawCursor( TRUE );
01203 return;
01204 }
01205 if ( !cursor->atParagStart() ) {
01206 checkUndoRedoInfo( UndoRedoInfo::Delete );
01207 if ( !undoRedoInfo.valid() ) {
01208 undoRedoInfo.id = cursor->paragraph()->paragId();
01209 undoRedoInfo.index = cursor->index();
01210 undoRedoInfo.d->text = QString::null;
01211 }
01212 cursor->gotoPreviousLetter();
01213 undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index() ), TRUE );
01214 undoRedoInfo.index = cursor->index();
01215 cursor->remove();
01216 lastFormatted = cursor->paragraph();
01217 } else if ( cursor->paragraph()->prev() ){
01218 clearUndoRedo();
01219 doc->setSelectionStart( QTextDocument::Temp, *cursor );
01220 cursor->gotoPreviousLetter();
01221 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
01222 removeSelectedText( QTextDocument::Temp );
01223 }
01224 break;
01225 case ActionReturn:
01226 checkUndoRedoInfo( UndoRedoInfo::Return );
01227 if ( !undoRedoInfo.valid() ) {
01228 undoRedoInfo.id = cursor->paragraph()->paragId();
01229 undoRedoInfo.index = cursor->index();
01230 undoRedoInfo.d->text = QString::null;
01231 }
01232 undoRedoInfo.d->text += "\n";
01233 cursor->splitAndInsertEmptyParagraph();
01234 if ( cursor->paragraph()->prev() ) {
01235 lastFormatted = cursor->paragraph()->prev();
01236 lastFormatted->invalidate( 0 );
01237 }
01238 doUpdateCurrentFormat = FALSE;
01239 break;
01240 case ActionKill:
01241 clearUndoRedo();
01242 doc->setSelectionStart( QTextDocument::Temp, *cursor );
01243 if ( cursor->atParagEnd() )
01244 cursor->gotoNextLetter();
01245 else
01246 cursor->setIndex( cursor->paragraph()->length() - 1 );
01247 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
01248 removeSelectedText( QTextDocument::Temp );
01249 break;
01250 }
01251
01252 formatMore();
01253 repaintChanged();
01254 ensureCursorVisible();
01255 drawCursor( TRUE );
01256 updateMicroFocusHint();
01257 if ( doUpdateCurrentFormat )
01258 updateCurrentFormat();
01259 setModified();
01260 emit textChanged();
01261 }
01262
01263 void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles )
01264 {
01265 QDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly );
01266 c2.restoreState();
01267 c1.restoreState();
01268 int lastIndex = text.length();
01269 if ( c1.paragraph() == c2.paragraph() ) {
01270 for ( int i = c1.index(); i < c2.index(); ++i )
01271 text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE );
01272 if ( fillStyles ) {
01273 styleStream << (int) 1;
01274 c1.paragraph()->writeStyleInformation( styleStream );
01275 }
01276 } else {
01277 int i;
01278 for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i )
01279 text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE );
01280 int num = 2;
01281 text += "\n"; lastIndex++;
01282 QTextParagraph *p = c1.paragraph()->next();
01283 while ( p && p != c2.paragraph() ) {
01284 for ( i = 0; i < p->length()-1; ++i )
01285 text.insert( lastIndex++ , p->at( i ), TRUE );
01286 text += "\n"; num++; lastIndex++;
01287 p = p->next();
01288 }
01289 for ( i = 0; i < c2.index(); ++i )
01290 text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE );
01291 if ( fillStyles ) {
01292 styleStream << num;
01293 for ( QTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() )
01294 p->writeStyleInformation( styleStream );
01295 }
01296 }
01297 }
01298
01305 void QTextEdit::removeSelection( int selNum )
01306 {
01307 doc->removeSelection( selNum );
01308 repaintChanged();
01309 }
01310
01318 void QTextEdit::removeSelectedText( int selNum )
01319 {
01320 if ( isReadOnly() )
01321 return;
01322
01323 QTextCursor c1 = doc->selectionStartCursor( selNum );
01324 c1.restoreState();
01325 QTextCursor c2 = doc->selectionEndCursor( selNum );
01326 c2.restoreState();
01327
01328
01329 if ( c1.nestedDepth() || c2.nestedDepth() )
01330 return;
01331
01332 for ( int i = 0; i < (int)doc->numSelections(); ++i ) {
01333 if ( i == selNum )
01334 continue;
01335 doc->removeSelection( i );
01336 }
01337
01338 drawCursor( FALSE );
01339 checkUndoRedoInfo( UndoRedoInfo::RemoveSelected );
01340 if ( !undoRedoInfo.valid() ) {
01341 doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index );
01342 undoRedoInfo.d->text = QString::null;
01343 }
01344 readFormats( c1, c2, undoRedoInfo.d->text, TRUE );
01345
01346
01347 doc->removeSelectedText( selNum, cursor );
01348 if ( cursor->isValid() ) {
01349 ensureCursorVisible();
01350 lastFormatted = cursor->paragraph();
01351 formatMore();
01352 repaintChanged();
01353 ensureCursorVisible();
01354 drawCursor( TRUE );
01355 clearUndoRedo();
01356 #if defined(Q_WS_WIN)
01357
01358
01359 if ( contentsHeight() < visibleHeight() )
01360 viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE );
01361 #endif
01362 #ifndef QT_NO_CURSOR
01363 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
01364 #endif
01365 updateMicroFocusHint();
01366 } else {
01367 delete cursor;
01368 cursor = new QTextCursor( doc );
01369 drawCursor( TRUE );
01370 viewport()->repaint( TRUE );
01371 }
01372 setModified();
01373 emit textChanged();
01374 emit selectionChanged();
01375 }
01376
01383 void QTextEdit::moveCursor( CursorAction action, bool select )
01384 {
01385 drawCursor( FALSE );
01386 if ( select ) {
01387 if ( !doc->hasSelection( QTextDocument::Standard ) )
01388 doc->setSelectionStart( QTextDocument::Standard, *cursor );
01389 moveCursor( action );
01390 if ( doc->setSelectionEnd( QTextDocument::Standard, *cursor ) ) {
01391 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
01392 repaintChanged();
01393 } else {
01394 drawCursor( TRUE );
01395 }
01396 ensureCursorVisible();
01397 emit selectionChanged();
01398 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
01399 } else {
01400 bool redraw = doc->removeSelection( QTextDocument::Standard );
01401 moveCursor( action );
01402 if ( !redraw ) {
01403 ensureCursorVisible();
01404 drawCursor( TRUE );
01405 } else {
01406 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
01407 repaintChanged();
01408 ensureCursorVisible();
01409 drawCursor( TRUE );
01410 #ifndef QT_NO_CURSOR
01411 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
01412 #endif
01413 }
01414 if ( redraw ) {
01415 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
01416 emit selectionChanged();
01417 }
01418 }
01419
01420 drawCursor( TRUE );
01421 updateCurrentFormat();
01422 updateMicroFocusHint();
01423 }
01424
01428 void QTextEdit::moveCursor( CursorAction action )
01429 {
01430 switch ( action ) {
01431 case MoveBackward:
01432 cursor->gotoPreviousLetter();
01433 break;
01434 case MoveWordBackward:
01435 cursor->gotoPreviousWord();
01436 break;
01437 case MoveForward:
01438 cursor->gotoNextLetter();
01439 break;
01440 case MoveWordForward:
01441 cursor->gotoNextWord();
01442 break;
01443 case MoveUp:
01444 cursor->gotoUp();
01445 break;
01446 case MovePgUp:
01447 cursor->gotoPageUp( visibleHeight() );
01448 break;
01449 case MoveDown:
01450 cursor->gotoDown();
01451 break;
01452 case MovePgDown:
01453 cursor->gotoPageDown( visibleHeight() );
01454 break;
01455 case MoveLineStart:
01456 cursor->gotoLineStart();
01457 break;
01458 case MoveHome:
01459 cursor->gotoHome();
01460 break;
01461 case MoveLineEnd:
01462 cursor->gotoLineEnd();
01463 break;
01464 case MoveEnd:
01465 ensureFormatted( doc->lastParagraph() );
01466 cursor->gotoEnd();
01467 break;
01468 }
01469 updateMicroFocusHint();
01470 updateCurrentFormat();
01471 }
01472
01475 void QTextEdit::resizeEvent( QResizeEvent *e )
01476 {
01477 QScrollView::resizeEvent( e );
01478 if ( doc->visibleWidth() == 0 )
01479 doResize();
01480 }
01481
01484 void QTextEdit::viewportResizeEvent( QResizeEvent *e )
01485 {
01486 QScrollView::viewportResizeEvent( e );
01487 if ( e->oldSize().width() != e->size().width() ) {
01488 bool stayAtBottom = e->oldSize().height() != e->size().height() &&
01489 contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height();
01490 doResize();
01491 if ( stayAtBottom )
01492 scrollToBottom();
01493 }
01494 }
01495
01503 void QTextEdit::ensureCursorVisible()
01504 {
01505 if ( !isVisible() ) {
01506 d->ensureCursorVisibleInShowEvent = TRUE;
01507 return;
01508 }
01509 lastFormatted = cursor->paragraph();
01510 formatMore();
01511 QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
01512 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
01513 int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX();
01514 int y = 0; int dummy;
01515 cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
01516 y += cursor->paragraph()->rect().y() + cursor->offsetY();
01517 int w = 1;
01518 ensureVisible( x, y + h / 2, w, h / 2 + 2 );
01519 }
01520
01524 void QTextEdit::drawCursor( bool visible )
01525 {
01526 if ( !isUpdatesEnabled() ||
01527 !viewport()->isUpdatesEnabled() ||
01528 !cursor->paragraph() ||
01529 !cursor->paragraph()->isValid() ||
01530 !selectedText().isEmpty() ||
01531 ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) ||
01532 isReadOnly() )
01533 return;
01534
01535 QPainter p( viewport() );
01536 QRect r( cursor->topParagraph()->rect() );
01537 cursor->paragraph()->setChanged( TRUE );
01538 p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() );
01539 QPixmap *pix = 0;
01540 QColorGroup cg( colorGroup() );
01541 if ( cursor->paragraph()->background() )
01542 cg.setBrush( QColorGroup::Base, *cursor->paragraph()->background() );
01543 else if ( doc->paper() )
01544 cg.setBrush( QColorGroup::Base, *doc->paper() );
01545 p.setBrushOrigin( -contentsX(), -contentsY() );
01546 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
01547 if ( !cursor->nestedDepth() ) {
01548 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
01549 int dist = 5;
01550 if ( ( cursor->paragraph()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify )
01551 dist = 50;
01552 int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist;
01553 x = QMAX( x, 0 );
01554 p.setClipRect( QRect( x - contentsX(),
01555 r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) );
01556 doc->drawParagraph( &p, cursor->paragraph(), x,
01557 r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor );
01558 } else {
01559 doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(),
01560 r.y() - cursor->totalOffsetY(), r.width(), r.height(),
01561 pix, cg, visible, cursor );
01562 }
01563 cursorVisible = visible;
01564 }
01565
01566 enum {
01567 IdUndo = 0,
01568 IdRedo = 1,
01569 IdCut = 2,
01570 IdCopy = 3,
01571 IdPaste = 4,
01572 IdClear = 5,
01573 IdSelectAll = 6
01574 };
01575
01577 #ifndef QT_NO_WHEELEVENT
01578 void QTextEdit::contentsWheelEvent( QWheelEvent *e )
01579 {
01580 if ( isReadOnly() ) {
01581 if ( e->state() & ControlButton ) {
01582 if ( e->delta() > 0 )
01583 zoomOut();
01584 else if ( e->delta() < 0 )
01585 zoomIn();
01586 return;
01587 }
01588 }
01589 QScrollView::contentsWheelEvent( e );
01590 }
01591 #endif
01592
01595 void QTextEdit::contentsMousePressEvent( QMouseEvent *e )
01596 {
01597 clearUndoRedo();
01598 QTextCursor oldCursor = *cursor;
01599 QTextCursor c = *cursor;
01600 mousePos = e->pos();
01601 mightStartDrag = FALSE;
01602 pressedLink = QString::null;
01603
01604 if ( e->button() == LeftButton ) {
01605 mousePressed = TRUE;
01606 drawCursor( FALSE );
01607 placeCursor( e->pos() );
01608 ensureCursorVisible();
01609
01610 if ( isReadOnly() && linksEnabled() ) {
01611 QTextCursor c = *cursor;
01612 placeCursor( e->pos(), &c, TRUE );
01613 if ( c.paragraph() && c.paragraph()->at( c.index() ) &&
01614 c.paragraph()->at( c.index() )->isAnchor() ) {
01615 pressedLink = c.paragraph()->at( c.index() )->anchorHref();
01616 }
01617 }
01618
01619 #ifndef QT_NO_DRAGANDDROP
01620 if ( doc->inSelection( QTextDocument::Standard, e->pos() ) ) {
01621 mightStartDrag = TRUE;
01622 drawCursor( TRUE );
01623 dragStartTimer->start( QApplication::startDragTime(), TRUE );
01624 dragStartPos = e->pos();
01625 return;
01626 }
01627 #endif
01628
01629 bool redraw = FALSE;
01630 if ( doc->hasSelection( QTextDocument::Standard ) ) {
01631 if ( !( e->state() & ShiftButton ) ) {
01632 redraw = doc->removeSelection( QTextDocument::Standard );
01633 doc->setSelectionStart( QTextDocument::Standard, *cursor );
01634 } else {
01635 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
01636 }
01637 } else {
01638 if ( isReadOnly() || !( e->state() & ShiftButton ) ) {
01639 doc->setSelectionStart( QTextDocument::Standard, *cursor );
01640 } else {
01641 doc->setSelectionStart( QTextDocument::Standard, c );
01642 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
01643 }
01644 }
01645
01646 for ( int i = 1; i < doc->numSelections(); ++i )
01647 redraw = doc->removeSelection( i ) || redraw;
01648
01649 if ( !redraw ) {
01650 drawCursor( TRUE );
01651 } else {
01652 repaintChanged();
01653 #ifndef QT_NO_CURSOR
01654 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
01655 #endif
01656 }
01657 } else if ( e->button() == MidButton ) {
01658 bool redraw = doc->removeSelection( QTextDocument::Standard );
01659 if ( !redraw ) {
01660 drawCursor( TRUE );
01661 } else {
01662 repaintChanged();
01663 #ifndef QT_NO_CURSOR
01664 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
01665 #endif
01666 }
01667 }
01668
01669 if ( *cursor != oldCursor )
01670 updateCurrentFormat();
01671 }
01672
01675 void QTextEdit::contentsMouseMoveEvent( QMouseEvent *e )
01676 {
01677 if ( mousePressed ) {
01678 #ifndef QT_NO_DRAGANDDROP
01679 if ( mightStartDrag ) {
01680 dragStartTimer->stop();
01681 if ( ( e->pos() - dragStartPos ).manhattanLength() > QApplication::startDragDistance() )
01682 startDrag();
01683 #ifndef QT_NO_CURSOR
01684 if ( !isReadOnly() )
01685 viewport()->setCursor( ibeamCursor );
01686 #endif
01687 return;
01688 }
01689 #endif
01690 mousePos = e->pos();
01691 handleMouseMove( mousePos );
01692 oldMousePos = mousePos;
01693 }
01694
01695 #ifndef QT_NO_CURSOR
01696 if ( !isReadOnly() && !mousePressed ) {
01697 if ( doc->hasSelection( QTextDocument::Standard ) && doc->inSelection( QTextDocument::Standard, e->pos() ) )
01698 viewport()->setCursor( arrowCursor );
01699 else
01700 viewport()->setCursor( ibeamCursor );
01701 }
01702 #endif
01703 updateCursor( e->pos() );
01704 }
01705
01708 void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e )
01709 {
01710 QTextCursor oldCursor = *cursor;
01711 if ( scrollTimer->isActive() )
01712 scrollTimer->stop();
01713 #ifndef QT_NO_DRAGANDDROP
01714 if ( dragStartTimer->isActive() )
01715 dragStartTimer->stop();
01716 if ( mightStartDrag ) {
01717 selectAll( FALSE );
01718 mousePressed = FALSE;
01719 }
01720 #endif
01721 if ( mousePressed ) {
01722 mousePressed = FALSE;
01723 }
01724 emit cursorPositionChanged( cursor );
01725 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
01726 if ( oldCursor != *cursor )
01727 updateCurrentFormat();
01728 inDoubleClick = FALSE;
01729
01730 #ifndef QT_NO_NETWORKPROTOCOL
01731 if ( !onLink.isEmpty() && onLink == pressedLink && linksEnabled() ) {
01732 QUrl u( doc->context(), onLink, TRUE );
01733 emitLinkClicked( u.toString( FALSE, FALSE ) );
01734
01735
01736
01737
01738 updateCursor( e->pos() );
01739 }
01740 #endif
01741 drawCursor( TRUE );
01742 if ( !doc->hasSelection( QTextDocument::Standard, TRUE ) )
01743 doc->removeSelection( QTextDocument::Standard );
01744
01745 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
01746 emit selectionChanged();
01747 }
01748
01751 void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * )
01752 {
01753 QTextCursor c1 = *cursor;
01754 QTextCursor c2 = *cursor;
01755 if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() )
01756 c1.gotoPreviousWord();
01757 if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() )
01758 c2.gotoNextWord();
01759
01760 doc->setSelectionStart( QTextDocument::Standard, c1 );
01761 doc->setSelectionEnd( QTextDocument::Standard, c2 );
01762
01763 *cursor = c2;
01764
01765 repaintChanged();
01766
01767 inDoubleClick = TRUE;
01768 mousePressed = TRUE;
01769 }
01770
01771 #ifndef QT_NO_DRAGANDDROP
01772
01775 void QTextEdit::contentsDragEnterEvent( QDragEnterEvent *e )
01776 {
01777 if ( isReadOnly() || !QTextDrag::canDecode( e ) ) {
01778 e->ignore();
01779 return;
01780 }
01781 e->acceptAction();
01782 inDnD = TRUE;
01783 }
01784
01787 void QTextEdit::contentsDragMoveEvent( QDragMoveEvent *e )
01788 {
01789 if ( isReadOnly() || !QTextDrag::canDecode( e ) ) {
01790 e->ignore();
01791 return;
01792 }
01793 drawCursor( FALSE );
01794 placeCursor( e->pos(), cursor );
01795 drawCursor( TRUE );
01796 e->acceptAction();
01797 }
01798
01801 void QTextEdit::contentsDragLeaveEvent( QDragLeaveEvent * )
01802 {
01803 inDnD = FALSE;
01804 }
01805
01808 void QTextEdit::contentsDropEvent( QDropEvent *e )
01809 {
01810 if ( isReadOnly() )
01811 return;
01812 inDnD = FALSE;
01813 e->acceptAction();
01814 QString text;
01815 bool intern = FALSE;
01816 if ( QTextDrag::decode( e, text ) ) {
01817 bool hasSel = doc->hasSelection( QTextDocument::Standard );
01818 bool internalDrag = e->source() == this || e->source() == viewport();
01819 int dropId, dropIndex;
01820 QTextCursor insertCursor = *cursor;
01821 dropId = cursor->paragraph()->paragId();
01822 dropIndex = cursor->index();
01823 if ( hasSel && internalDrag ) {
01824 QTextCursor c1, c2;
01825 int selStartId, selStartIndex;
01826 int selEndId, selEndIndex;
01827 c1 = doc->selectionStartCursor( QTextDocument::Standard );
01828 c1.restoreState();
01829 c2 = doc->selectionEndCursor( QTextDocument::Standard );
01830 c2.restoreState();
01831 selStartId = c1.paragraph()->paragId();
01832 selStartIndex = c1.index();
01833 selEndId = c2.paragraph()->paragId();
01834 selEndIndex = c2.index();
01835 if ( ( ( dropId > selStartId ) ||
01836 ( dropId == selStartId && dropIndex > selStartIndex ) ) &&
01837 ( ( dropId < selEndId ) ||
01838 ( dropId == selEndId && dropIndex <= selEndIndex ) ) )
01839 insertCursor = c1;
01840 if ( dropId == selEndId && dropIndex > selEndIndex ) {
01841 insertCursor = c1;
01842 if ( selStartId == selEndId ) {
01843 insertCursor.setIndex( dropIndex -
01844 ( selEndIndex - selStartIndex ) );
01845 } else {
01846 insertCursor.setIndex( dropIndex - selEndIndex +
01847 selStartIndex );
01848 }
01849 }
01850 }
01851
01852 if ( internalDrag && e->action() == QDropEvent::Move ) {
01853 removeSelectedText();
01854 intern = TRUE;
01855 } else {
01856 doc->removeSelection( QTextDocument::Standard );
01857 #ifndef QT_NO_CURSOR
01858 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
01859 #endif
01860 }
01861 drawCursor( FALSE );
01862 cursor->setParagraph( insertCursor.paragraph() );
01863 cursor->setIndex( insertCursor.index() );
01864 drawCursor( TRUE );
01865 if ( !cursor->nestedDepth() ) {
01866 insert( text, FALSE, TRUE, FALSE );
01867 } else {
01868 if ( intern )
01869 undo();
01870 e->ignore();
01871 }
01872 }
01873 }
01874
01875 #endif
01876
01877 void QTextEdit::autoScrollTimerDone()
01878 {
01879 if ( mousePressed )
01880 handleMouseMove( viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ) );
01881 }
01882
01883 void QTextEdit::handleMouseMove( const QPoint& pos )
01884 {
01885 if ( !mousePressed )
01886 return;
01887
01888 if ( !scrollTimer->isActive() && pos.y() < contentsY() || pos.y() > contentsY() + visibleHeight() )
01889 scrollTimer->start( 100, FALSE );
01890 else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() )
01891 scrollTimer->stop();
01892
01893 drawCursor( FALSE );
01894 QTextCursor oldCursor = *cursor;
01895
01896 placeCursor( pos );
01897
01898 if ( inDoubleClick ) {
01899 QTextCursor cl = *cursor;
01900 cl.gotoPreviousWord();
01901 QTextCursor cr = *cursor;
01902 cr.gotoNextWord();
01903
01904 int diff = QABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() );
01905 int ldiff = QABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() );
01906 int rdiff = QABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() );
01907
01908
01909 if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) !=
01910 oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) )
01911 diff = 0xFFFFFF;
01912
01913 if ( rdiff < diff && rdiff < ldiff )
01914 *cursor = cr;
01915 else if ( ldiff < diff && ldiff < rdiff )
01916 *cursor = cl;
01917 else
01918 *cursor = oldCursor;
01919
01920 }
01921 ensureCursorVisible();
01922
01923 bool redraw = FALSE;
01924 if ( doc->hasSelection( QTextDocument::Standard ) ) {
01925 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
01926 }
01927
01928 if ( !redraw ) {
01929 drawCursor( TRUE );
01930 } else {
01931 repaintChanged();
01932 drawCursor( TRUE );
01933 }
01934
01935 if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) {
01936 currentFormat->removeRef();
01937 currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() );
01938 if ( currentFormat->isMisspelled() ) {
01939 currentFormat->removeRef();
01940 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
01941 }
01942 emit currentFontChanged( currentFormat->font() );
01943 emit currentColorChanged( currentFormat->color() );
01944 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
01945 }
01946
01947 if ( currentAlignment != cursor->paragraph()->alignment() ) {
01948 currentAlignment = cursor->paragraph()->alignment();
01949 block_set_alignment = TRUE;
01950 emit currentAlignmentChanged( currentAlignment );
01951 block_set_alignment = FALSE;
01952 }
01953 }
01954
01964 void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link )
01965 {
01966 if ( !c )
01967 c = cursor;
01968
01969 c->restoreState();
01970 QTextParagraph *s = doc->firstParagraph();
01971 c->place( pos, s, link );
01972 updateMicroFocusHint();
01973 }
01974
01975
01976 void QTextEdit::updateMicroFocusHint()
01977 {
01978 QTextCursor c( *cursor );
01979 if ( d->preeditStart != -1 )
01980 c.setIndex( d->preeditStart );
01981
01982 if ( hasFocus() || viewport()->hasFocus() ) {
01983 int h = c.paragraph()->lineHeightOfChar( cursor->index() );
01984 if ( !readonly ) {
01985 QFont f = c.paragraph()->at( c.index() )->format()->font();
01986 setMicroFocusHint( c.x() - contentsX() + frameWidth(),
01987 c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
01988 }
01989 }
01990 }
01991
01992
01993
01994 void QTextEdit::formatMore()
01995 {
01996 if ( !lastFormatted )
01997 return;
01998
01999 int bottom = contentsHeight();
02000 int lastBottom = -1;
02001 int to = 20;
02002 bool firstVisible = FALSE;
02003 QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
02004 for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) {
02005 lastFormatted->format();
02006 if ( i == 0 )
02007 firstVisible = lastFormatted->rect().intersects( cr );
02008 else if ( firstVisible )
02009 firstVisible = lastFormatted->rect().intersects( cr );
02010 bottom = QMAX( bottom, lastFormatted->rect().top() +
02011 lastFormatted->rect().height() );
02012 lastBottom = lastFormatted->rect().top() + lastFormatted->rect().height();
02013 lastFormatted = lastFormatted->next();
02014 if ( lastFormatted )
02015 lastBottom = -1;
02016 }
02017
02018 if ( bottom > contentsHeight() ) {
02019 resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) );
02020 } else if ( lastBottom != -1 && lastBottom < contentsHeight() ) {
02021 resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) );
02022 if ( contentsHeight() < visibleHeight() )
02023 updateContents( 0, contentsHeight(), visibleWidth(),
02024 visibleHeight() - contentsHeight() );
02025 }
02026
02027 if ( lastFormatted )
02028 formatTimer->start( interval, TRUE );
02029 else
02030 interval = QMAX( 0, interval );
02031 }
02032
02033 void QTextEdit::doResize()
02034 {
02035 if ( wrapMode == FixedPixelWidth )
02036 return;
02037 doc->setMinimumWidth( -1 );
02038 resizeContents( 0, 0 );
02039 doc->setWidth( visibleWidth() );
02040 doc->invalidate();
02041 lastFormatted = doc->firstParagraph();
02042 interval = 0;
02043 formatMore();
02044 repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE );
02045 }
02046
02049 void QTextEdit::doChangeInterval()
02050 {
02051 interval = 0;
02052 }
02053
02056 bool QTextEdit::eventFilter( QObject *o, QEvent *e )
02057 {
02058 if ( o == this || o == viewport() ) {
02059 if ( e->type() == QEvent::FocusIn ) {
02060 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
02061 drawCursor( TRUE );
02062 updateMicroFocusHint();
02063 } else if ( e->type() == QEvent::FocusOut ) {
02064 blinkTimer->stop();
02065 drawCursor( FALSE );
02066 }
02067 }
02068
02069 return QScrollView::eventFilter( o, e );
02070 }
02071
02084 void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected )
02085 {
02086 if ( cursor->nestedDepth() != 0 )
02087 return;
02088 QString txt( text );
02089 drawCursor( FALSE );
02090 if ( !isReadOnly() && doc->hasSelection( QTextDocument::Standard ) && removeSelected )
02091 removeSelectedText();
02092 QTextCursor c2 = *cursor;
02093 int oldLen = 0;
02094
02095 if ( undoEnabled && !isReadOnly() ) {
02096 checkUndoRedoInfo( UndoRedoInfo::Insert );
02097 if ( !undoRedoInfo.valid() ) {
02098 undoRedoInfo.id = cursor->paragraph()->paragId();
02099 undoRedoInfo.index = cursor->index();
02100 undoRedoInfo.d->text = QString::null;
02101 }
02102 oldLen = undoRedoInfo.d->text.length();
02103 }
02104
02105 lastFormatted = checkNewLine && cursor->paragraph()->prev() ?
02106 cursor->paragraph()->prev() : cursor->paragraph();
02107 QTextCursor oldCursor = *cursor;
02108 cursor->insert( txt, checkNewLine );
02109 if ( doc->useFormatCollection() ) {
02110 doc->setSelectionStart( QTextDocument::Temp, oldCursor );
02111 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
02112 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format );
02113 doc->removeSelection( QTextDocument::Temp );
02114 }
02115
02116 if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) )
02117 cursor->indent();
02118 formatMore();
02119 repaintChanged();
02120 ensureCursorVisible();
02121 drawCursor( TRUE );
02122
02123 if ( undoEnabled && !isReadOnly() ) {
02124 undoRedoInfo.d->text += txt;
02125 if ( !doc->preProcessor() ) {
02126 for ( int i = 0; i < (int)txt.length(); ++i ) {
02127 if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) {
02128 c2.paragraph()->at( c2.index() )->format()->addRef();
02129 undoRedoInfo.d->text.setFormat( oldLen + i, c2.paragraph()->at( c2.index() )->format(), TRUE );
02130 }
02131 c2.gotoNextLetter();
02132 }
02133 }
02134 }
02135
02136 if ( !removeSelected ) {
02137 doc->setSelectionStart( QTextDocument::Standard, oldCursor );
02138 doc->setSelectionEnd( QTextDocument::Standard, *cursor );
02139 repaintChanged();
02140 }
02141 updateMicroFocusHint();
02142 setModified();
02143 emit textChanged();
02144 }
02145
02148 void QTextEdit::insertAt( const QString &text, int para, int index )
02149 {
02150 removeSelection( QTextDocument::Standard );
02151 QTextParagraph *p = doc->paragAt( para );
02152 if ( !p )
02153 return;
02154 QTextCursor tmp = *cursor;
02155 cursor->setParagraph( p );
02156 cursor->setIndex( index );
02157 insert( text, FALSE, TRUE, FALSE );
02158 *cursor = tmp;
02159 removeSelection( QTextDocument::Standard );
02160 }
02161
02166 void QTextEdit::insertParagraph( const QString &text, int para )
02167 {
02168 QTextParagraph *p = doc->paragAt( para );
02169 if ( p ) {
02170 QTextCursor tmp( doc );
02171 tmp.setParagraph( p );
02172 tmp.setIndex( 0 );
02173 tmp.insert( text, TRUE );
02174 tmp.splitAndInsertEmptyParagraph();
02175 repaintChanged();
02176 } else {
02177 append( text );
02178 }
02179 }
02180
02183 void QTextEdit::removeParagraph( int para )
02184 {
02185 QTextParagraph *p = doc->paragAt( para );
02186 if ( !p )
02187 return;
02188 for ( int i = 0; i < doc->numSelections(); ++i )
02189 doc->removeSelection( i );
02190
02191 if ( p == doc->firstParagraph() && p == doc->lastParagraph() ) {
02192 p->remove( 0, p->length() - 1 );
02193 repaintChanged();
02194 return;
02195 }
02196 drawCursor( FALSE );
02197 bool resetCursor = cursor->paragraph() == p;
02198 if ( p->prev() )
02199 p->prev()->setNext( p->next() );
02200 else
02201 doc->setFirstParagraph( p->next() );
02202 if ( p->next() )
02203 p->next()->setPrev( p->prev() );
02204 else
02205 doc->setLastParagraph( p->prev() );
02206 QTextParagraph *start = p->next();
02207 int h = p->rect().height();
02208 delete p;
02209 p = start;
02210 int dy = -h;
02211 while ( p ) {
02212 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 );
02213 p->move( dy );
02214 p->invalidate( 0 );
02215 p->setEndState( -1 );
02216 p = p->next();
02217 }
02218
02219 if ( resetCursor ) {
02220 cursor->setParagraph( doc->firstParagraph() );
02221 cursor->setIndex( 0 );
02222 }
02223 repaintChanged();
02224 drawCursor( TRUE );
02225 }
02226
02236 void QTextEdit::undo()
02237 {
02238
02239
02240
02241 clearUndoRedo();
02242 if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled )
02243 return;
02244
02245 for ( int i = 0; i < (int)doc->numSelections(); ++i )
02246 doc->removeSelection( i );
02247
02248 #ifndef QT_NO_CURSOR
02249 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
02250 #endif
02251
02252 clearUndoRedo();
02253 drawCursor( FALSE );
02254 QTextCursor *c = doc->undo( cursor );
02255 if ( !c ) {
02256 drawCursor( TRUE );
02257 return;
02258 }
02259 lastFormatted = 0;
02260 ensureCursorVisible();
02261 repaintChanged();
02262 drawCursor( TRUE );
02263 updateMicroFocusHint();
02264 setModified();
02265 emit textChanged();
02266 }
02267
02277 void QTextEdit::redo()
02278 {
02279 if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled )
02280 return;
02281
02282 for ( int i = 0; i < (int)doc->numSelections(); ++i )
02283 doc->removeSelection( i );
02284
02285 #ifndef QT_NO_CURSOR
02286 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
02287 #endif
02288
02289 clearUndoRedo();
02290 drawCursor( FALSE );
02291 QTextCursor *c = doc->redo( cursor );
02292 if ( !c ) {
02293 drawCursor( TRUE );
02294 return;
02295 }
02296 lastFormatted = 0;
02297 ensureCursorVisible();
02298 repaintChanged();
02299 ensureCursorVisible();
02300 drawCursor( TRUE );
02301 updateMicroFocusHint();
02302 setModified();
02303 emit textChanged();
02304 }
02305
02315 void QTextEdit::paste()
02316 {
02317 #ifndef QT_NO_CLIPBOARD
02318 if ( isReadOnly() )
02319 return;
02320 pasteSubType( "plain" );
02321 updateMicroFocusHint();
02322 #endif
02323 }
02324
02325 void QTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t )
02326 {
02327 if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) {
02328 clearUndoRedo();
02329 }
02330 undoRedoInfo.type = t;
02331 }
02332
02339 void QTextEdit::repaintChanged()
02340 {
02341 if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() )
02342 return;
02343 QPainter p( viewport() );
02344 p.translate( -contentsX(), -contentsY() );
02345 paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() );
02346 }
02347
02357 void QTextEdit::cut()
02358 {
02359 if ( isReadOnly() )
02360 return;
02361
02362 QString t;
02363 if ( doc->hasSelection( QTextDocument::Standard ) &&
02364 !( t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ) ).isEmpty() ) {
02365 QApplication::clipboard()->setText( t );
02366 removeSelectedText();
02367 }
02368 updateMicroFocusHint();
02369 }
02370
02376 void QTextEdit::copy()
02377 {
02378 QString t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy );
02379 if ( doc->hasSelection( QTextDocument::Standard ) &&
02380 !t.isEmpty() && t.simplifyWhiteSpace() != "<selstart/>" )
02381 QApplication::clipboard()->setText( t );
02382 }
02383
02388 void QTextEdit::indent()
02389 {
02390 if ( isReadOnly() )
02391 return;
02392
02393 drawCursor( FALSE );
02394 if ( !doc->hasSelection( QTextDocument::Standard ) )
02395 cursor->indent();
02396 else
02397 doc->indentSelection( QTextDocument::Standard );
02398 repaintChanged();
02399 drawCursor( TRUE );
02400 setModified();
02401 emit textChanged();
02402 }
02403
02410 bool QTextEdit::focusNextPrevChild( bool n )
02411 {
02412 if ( !isReadOnly() || !linksEnabled() )
02413 return FALSE;
02414 bool b = doc->focusNextPrevChild( n );
02415 repaintChanged();
02416 if ( b )
02417
02418
02419 makeParagVisible( doc->focusIndicator.parag );
02420 return b;
02421 }
02422
02430 void QTextEdit::setFormat( QTextFormat *f, int flags )
02431 {
02432 if ( doc->hasSelection( QTextDocument::Standard ) ) {
02433 drawCursor( FALSE );
02434 QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard );
02435 c1.restoreState();
02436 QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard );
02437 c2.restoreState();
02438 clearUndoRedo();
02439 undoRedoInfo.type = UndoRedoInfo::Format;
02440 undoRedoInfo.id = c1.paragraph()->paragId();
02441 undoRedoInfo.index = c1.index();
02442 undoRedoInfo.eid = c2.paragraph()->paragId();
02443 undoRedoInfo.eindex = c2.index();
02444 readFormats( c1, c2, undoRedoInfo.d->text );
02445 undoRedoInfo.format = f;
02446 undoRedoInfo.flags = flags;
02447 clearUndoRedo();
02448 doc->setFormat( QTextDocument::Standard, f, flags );
02449 repaintChanged();
02450 formatMore();
02451 drawCursor( TRUE );
02452 setModified();
02453 emit textChanged();
02454 }
02455 if ( currentFormat && currentFormat->key() != f->key() ) {
02456 currentFormat->removeRef();
02457 currentFormat = doc->formatCollection()->format( f );
02458 if ( currentFormat->isMisspelled() ) {
02459 currentFormat->removeRef();
02460 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
02461 }
02462 emit currentFontChanged( currentFormat->font() );
02463 emit currentColorChanged( currentFormat->color() );
02464 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
02465 if ( cursor->index() == cursor->paragraph()->length() - 1 ) {
02466 currentFormat->addRef();
02467 cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE );
02468 if ( cursor->paragraph()->length() == 1 ) {
02469 cursor->paragraph()->invalidate( 0 );
02470 cursor->paragraph()->format();
02471 repaintChanged();
02472 }
02473 }
02474 }
02475 }
02476
02479 void QTextEdit::setPalette( const QPalette &p )
02480 {
02481 QScrollView::setPalette( p );
02482 if ( textFormat() == PlainText ) {
02483 QTextFormat *f = doc->formatCollection()->defaultFormat();
02484 f->setColor( colorGroup().text() );
02485 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
02486 }
02487 }
02488
02502 void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle )
02503 {
02504 if ( isReadOnly() )
02505 return;
02506
02507 drawCursor( FALSE );
02508 QTextParagraph *start = cursor->paragraph();
02509 QTextParagraph *end = start;
02510 if ( doc->hasSelection( QTextDocument::Standard ) ) {
02511 start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph();
02512 end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph();
02513 if ( end->paragId() < start->paragId() )
02514 return;
02515 }
02516
02517 clearUndoRedo();
02518 undoRedoInfo.type = UndoRedoInfo::Style;
02519 undoRedoInfo.id = start->paragId();
02520 undoRedoInfo.eid = end->paragId();
02521 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
02522
02523 while ( start != end->next() ) {
02524 start->setListStyle( listStyle );
02525 if ( dm == QStyleSheetItem::DisplayListItem ) {
02526 start->setListItem( TRUE );
02527 if( start->listDepth() == 0 )
02528 start->setListDepth( 1 );
02529 } else if ( start->isListItem() ) {
02530 start->setListItem( FALSE );
02531 start->setListDepth( QMAX( start->listDepth()-1, 0 ) );
02532 }
02533 start = start->next();
02534 }
02535
02536 clearUndoRedo();
02537 repaintChanged();
02538 formatMore();
02539 drawCursor( TRUE );
02540 setModified();
02541 emit textChanged();
02542 }
02543
02551 void QTextEdit::setAlignment( int a )
02552 {
02553 if ( isReadOnly() || block_set_alignment )
02554 return;
02555
02556 drawCursor( FALSE );
02557 QTextParagraph *start = cursor->paragraph();
02558 QTextParagraph *end = start;
02559 if ( doc->hasSelection( QTextDocument::Standard ) ) {
02560 start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph();
02561 end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph();
02562 if ( end->paragId() < start->paragId() )
02563 return;
02564 }
02565
02566 clearUndoRedo();
02567 undoRedoInfo.type = UndoRedoInfo::Style;
02568 undoRedoInfo.id = start->paragId();
02569 undoRedoInfo.eid = end->paragId();
02570 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
02571
02572 while ( start != end->next() ) {
02573 start->setAlignment( a );
02574 start = start->next();
02575 }
02576
02577 clearUndoRedo();
02578 repaintChanged();
02579 formatMore();
02580 drawCursor( TRUE );
02581 if ( currentAlignment != a ) {
02582 currentAlignment = a;
02583 emit currentAlignmentChanged( currentAlignment );
02584 }
02585 setModified();
02586 emit textChanged();
02587 }
02588
02589 void QTextEdit::updateCurrentFormat()
02590 {
02591 int i = cursor->index();
02592 if ( i > 0 )
02593 --i;
02594 if ( doc->useFormatCollection() &&
02595 ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) {
02596 if ( currentFormat )
02597 currentFormat->removeRef();
02598 currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() );
02599 if ( currentFormat->isMisspelled() ) {
02600 currentFormat->removeRef();
02601 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
02602 }
02603 emit currentFontChanged( currentFormat->font() );
02604 emit currentColorChanged( currentFormat->color() );
02605 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
02606 }
02607
02608 if ( currentAlignment != cursor->paragraph()->alignment() ) {
02609 currentAlignment = cursor->paragraph()->alignment();
02610 block_set_alignment = TRUE;
02611 emit currentAlignmentChanged( currentAlignment );
02612 block_set_alignment = FALSE;
02613 }
02614 }
02615
02623 void QTextEdit::setItalic( bool b )
02624 {
02625 QTextFormat f( *currentFormat );
02626 f.setItalic( b );
02627 QTextFormat *f2 = doc->formatCollection()->format( &f );
02628 setFormat( f2, QTextFormat::Italic );
02629 }
02630
02638 void QTextEdit::setBold( bool b )
02639 {
02640 QTextFormat f( *currentFormat );
02641 f.setBold( b );
02642 QTextFormat *f2 = doc->formatCollection()->format( &f );
02643 setFormat( f2, QTextFormat::Bold );
02644 }
02645
02653 void QTextEdit::setUnderline( bool b )
02654 {
02655 QTextFormat f( *currentFormat );
02656 f.setUnderline( b );
02657 QTextFormat *f2 = doc->formatCollection()->format( &f );
02658 setFormat( f2, QTextFormat::Underline );
02659 }
02660
02667 void QTextEdit::setFamily( const QString &fontFamily )
02668 {
02669 QTextFormat f( *currentFormat );
02670 f.setFamily( fontFamily );
02671 QTextFormat *f2 = doc->formatCollection()->format( &f );
02672 setFormat( f2, QTextFormat::Family );
02673 }
02674
02684 void QTextEdit::setPointSize( int s )
02685 {
02686 QTextFormat f( *currentFormat );
02687 f.setPointSize( s );
02688 QTextFormat *f2 = doc->formatCollection()->format( &f );
02689 setFormat( f2, QTextFormat::Size );
02690 }
02691
02698 void QTextEdit::setColor( const QColor &c )
02699 {
02700 QTextFormat f( *currentFormat );
02701 f.setColor( c );
02702 QTextFormat *f2 = doc->formatCollection()->format( &f );
02703 setFormat( f2, QTextFormat::Color );
02704 }
02705
02712 void QTextEdit::setVerticalAlignment( VerticalAlignment a )
02713 {
02714 QTextFormat f( *currentFormat );
02715 f.setVAlign( (QTextFormat::VerticalAlignment)a );
02716 QTextFormat *f2 = doc->formatCollection()->format( &f );
02717 setFormat( f2, QTextFormat::VAlign );
02718 }
02719
02720 void QTextEdit::setFontInternal( const QFont &f_ )
02721 {
02722 QTextFormat f( *currentFormat );
02723 f.setFont( f_ );
02724 QTextFormat *f2 = doc->formatCollection()->format( &f );
02725 setFormat( f2, QTextFormat::Font );
02726 }
02727
02728
02729 QString QTextEdit::text() const
02730 {
02731 if ( isReadOnly() )
02732 return doc->originalText();
02733 return doc->text();
02734 }
02735
02744 QString QTextEdit::text( int para ) const
02745 {
02746 return doc->text( para );
02747 }
02748
02769 void QTextEdit::setText( const QString &text, const QString &context )
02770 {
02771 if ( !isModified() && isReadOnly() &&
02772 this->context() == context && this->text() == text )
02773 return;
02774
02775 emit undoAvailable( FALSE );
02776 emit redoAvailable( FALSE );
02777 undoRedoInfo.clear();
02778 doc->commands()->clear();
02779
02780 lastFormatted = 0;
02781 cursor->restoreState();
02782 doc->setText( text, context );
02783
02784 if ( wrapMode == FixedPixelWidth ) {
02785 resizeContents( wrapWidth, 0 );
02786 doc->setWidth( wrapWidth );
02787 doc->setMinimumWidth( wrapWidth );
02788 } else {
02789 doc->setMinimumWidth( -1 );
02790 resizeContents( 0, 0 );
02791 }
02792
02793 lastFormatted = doc->firstParagraph();
02794 delete cursor;
02795 cursor = new QTextCursor( doc );
02796 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
02797
02798 if ( isModified() )
02799 setModified( FALSE );
02800 emit textChanged();
02801 formatMore();
02802 updateCurrentFormat();
02803 d->scrollToAnchor = QString::null;
02804 }
02805
02863 bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward,
02864 int *para, int *index )
02865 {
02866 drawCursor( FALSE );
02867 #ifndef QT_NO_CURSOR
02868 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
02869 #endif
02870 QTextCursor findcur = *cursor;
02871 if ( para && index ) {
02872 if ( doc->paragAt( *para ) )
02873 findcur.gotoPosition( doc->paragAt(*para), *index );
02874 else
02875 findcur.gotoEnd();
02876 } else if ( doc->hasSelection( QTextDocument::Standard ) ){
02877
02878 if ( forward )
02879 findcur.gotoNextLetter();
02880 else
02881 findcur.gotoPreviousLetter();
02882 }
02883 removeSelection( QTextDocument::Standard );
02884 bool found = doc->find( findcur, expr, cs, wo, forward );
02885 if ( found ) {
02886 if ( para )
02887 *para = findcur.paragraph()->paragId();
02888 if ( index )
02889 *index = findcur.index();
02890 *cursor = findcur;
02891 repaintChanged();
02892 ensureCursorVisible();
02893 }
02894 drawCursor( TRUE );
02895 return found;
02896 }
02897
02898 void QTextEdit::blinkCursor()
02899 {
02900 if ( !cursorVisible )
02901 return;
02902 bool cv = cursorVisible;
02903 blinkCursorVisible = !blinkCursorVisible;
02904 drawCursor( blinkCursorVisible );
02905 cursorVisible = cv;
02906 }
02907
02914 void QTextEdit::setCursorPosition( int para, int index )
02915 {
02916 QTextParagraph *p = doc->paragAt( para );
02917 if ( !p )
02918 return;
02919
02920 if ( index > p->length() - 1 )
02921 index = p->length() - 1;
02922
02923 drawCursor( FALSE );
02924 cursor->setParagraph( p );
02925 cursor->setIndex( index );
02926 ensureCursorVisible();
02927 drawCursor( TRUE );
02928 updateCurrentFormat();
02929 emit cursorPositionChanged( cursor );
02930 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
02931 }
02932
02941 void QTextEdit::getCursorPosition( int *para, int *index ) const
02942 {
02943 if ( !para || !index )
02944 return;
02945 *para = cursor->paragraph()->paragId();
02946 *index = cursor->index();
02947 }
02948
02964 void QTextEdit::setSelection( int paraFrom, int indexFrom,
02965 int paraTo, int indexTo, int selNum )
02966 {
02967 if ( doc->hasSelection( selNum ) ) {
02968 doc->removeSelection( selNum );
02969 repaintChanged();
02970 }
02971 if ( selNum > doc->numSelections() - 1 )
02972 doc->addSelection( selNum );
02973 QTextParagraph *p1 = doc->paragAt( paraFrom );
02974 if ( !p1 )
02975 return;
02976 QTextParagraph *p2 = doc->paragAt( paraTo );
02977 if ( !p2 )
02978 return;
02979
02980 if ( indexFrom > p1->length() - 1 )
02981 indexFrom = p1->length() - 1;
02982 if ( indexTo > p2->length() - 1 )
02983 indexTo = p2->length() - 1;
02984
02985 drawCursor( FALSE );
02986 QTextCursor c = *cursor;
02987 QTextCursor oldCursor = *cursor;
02988 c.setParagraph( p1 );
02989 c.setIndex( indexFrom );
02990 cursor->setParagraph( p2 );
02991 cursor->setIndex( indexTo );
02992 doc->setSelectionStart( selNum, c );
02993 doc->setSelectionEnd( selNum, *cursor );
02994 repaintChanged();
02995 ensureCursorVisible();
02996 if ( selNum != QTextDocument::Standard )
02997 *cursor = oldCursor;
02998 drawCursor( TRUE );
02999 }
03000
03021 void QTextEdit::getSelection( int *paraFrom, int *indexFrom,
03022 int *paraTo, int *indexTo, int selNum ) const
03023 {
03024 if ( !paraFrom || !paraTo || !indexFrom || !indexTo )
03025 return;
03026 if ( !doc->hasSelection( selNum ) ) {
03027 *paraFrom = -1;
03028 *indexFrom = -1;
03029 *paraTo = -1;
03030 *indexTo = -1;
03031 return;
03032 }
03033
03034 doc->selectionStart( selNum, *paraFrom, *indexFrom );
03035 doc->selectionEnd( selNum, *paraTo, *indexTo );
03036 }
03037
03055 void QTextEdit::setTextFormat( TextFormat format )
03056 {
03057 doc->setTextFormat( format );
03058 }
03059
03060 Qt::TextFormat QTextEdit::textFormat() const
03061 {
03062 return doc->textFormat();
03063 }
03064
03069 int QTextEdit::paragraphs() const
03070 {
03071 return doc->lastParagraph()->paragId() + 1;
03072 }
03073
03079 int QTextEdit::linesOfParagraph( int para ) const
03080 {
03081 QTextParagraph *p = doc->paragAt( para );
03082 if ( !p )
03083 return -1;
03084 return p->lines();
03085 }
03086
03092 int QTextEdit::paragraphLength( int para ) const
03093 {
03094 QTextParagraph *p = doc->paragAt( para );
03095 if ( !p )
03096 return -1;
03097 return p->length() - 1;
03098 }
03099
03108 int QTextEdit::lines() const
03109 {
03110 QTextParagraph *p = doc->firstParagraph();
03111 int l = 0;
03112 while ( p ) {
03113 l += p->lines();
03114 p = p->next();
03115 }
03116
03117 return l;
03118 }
03119
03128 int QTextEdit::lineOfChar( int para, int index )
03129 {
03130 QTextParagraph *p = doc->paragAt( para );
03131 if ( !p )
03132 return -1;
03133
03134 int idx, line;
03135 QTextStringChar *c = p->lineStartOfChar( index, &idx, &line );
03136 if ( !c )
03137 return -1;
03138
03139 return line;
03140 }
03141
03142 void QTextEdit::setModified( bool m )
03143 {
03144 bool oldModified = modified;
03145 modified = m;
03146 if ( modified && doc->oTextValid )
03147 doc->invalidateOriginalText();
03148 if ( oldModified != modified )
03149 emit modificationChanged( modified );
03150 }
03151
03156 bool QTextEdit::isModified() const
03157 {
03158 return modified;
03159 }
03160
03161 void QTextEdit::setModified()
03162 {
03163 if ( !isModified() )
03164 setModified( TRUE );
03165 }
03166
03173 bool QTextEdit::italic() const
03174 {
03175 return currentFormat->font().italic();
03176 }
03177
03184 bool QTextEdit::bold() const
03185 {
03186 return currentFormat->font().bold();
03187 }
03188
03196 bool QTextEdit::underline() const
03197 {
03198 return currentFormat->font().underline();
03199 }
03200
03207 QString QTextEdit::family() const
03208 {
03209 return currentFormat->font().family();
03210 }
03211
03219 int QTextEdit::pointSize() const
03220 {
03221 return currentFormat->font().pointSize();
03222 }
03223
03230 QColor QTextEdit::color() const
03231 {
03232 return currentFormat->color();
03233 }
03234
03242 QFont QTextEdit::font() const
03243 {
03244 return currentFormat->font();
03245 }
03246
03253 int QTextEdit::alignment() const
03254 {
03255 return currentAlignment;
03256 }
03257
03258 void QTextEdit::startDrag()
03259 {
03260 #ifndef QT_NO_DRAGANDDROP
03261 mousePressed = FALSE;
03262 inDoubleClick = FALSE;
03263 QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ), viewport() );
03264 if ( isReadOnly() ) {
03265 drag->dragCopy();
03266 } else {
03267 if ( drag->drag() && QDragObject::target() != this && QDragObject::target() != viewport() )
03268 removeSelectedText();
03269 }
03270 #endif
03271 }
03272
03282 void QTextEdit::selectAll( bool select )
03283 {
03284 if ( !select )
03285 doc->removeSelection( QTextDocument::Standard );
03286 else
03287 doc->selectAll( QTextDocument::Standard );
03288 repaintChanged();
03289 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
03290 emit selectionChanged();
03291 #ifndef QT_NO_CURSOR
03292 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
03293 #endif
03294 }
03295
03296 void QTextEdit::UndoRedoInfo::clear()
03297 {
03298 if ( valid() ) {
03299 if ( type == Insert || type == Return )
03300 doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) );
03301 else if ( type == Format )
03302 doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) );
03303 else if ( type == Style )
03304 doc->addCommand( new QTextStyleCommand( doc, id, eid, styleInformation ) );
03305 else if ( type != Invalid ) {
03306 doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) );
03307 }
03308 }
03309 type = Invalid;
03310 d->text = QString::null;
03311 id = -1;
03312 index = -1;
03313 styleInformation = QByteArray();
03314 }
03315
03316
03326 void QTextEdit::del()
03327 {
03328 if ( doc->hasSelection( QTextDocument::Standard ) ) {
03329 removeSelectedText();
03330 return;
03331 }
03332
03333 doKeyboardAction( ActionDelete );
03334 }
03335
03336
03337 QTextEdit::UndoRedoInfo::UndoRedoInfo( QTextDocument *dc )
03338 : type( Invalid ), doc( dc )
03339 {
03340 d = new QUndoRedoInfoPrivate;
03341 d->text = QString::null;
03342 id = -1;
03343 index = -1;
03344 }
03345
03346 QTextEdit::UndoRedoInfo::~UndoRedoInfo()
03347 {
03348 delete d;
03349 }
03350
03351 bool QTextEdit::UndoRedoInfo::valid() const
03352 {
03353 return id >= 0 && type != Invalid;
03354 }
03355
03362 void QTextEdit::resetFormat()
03363 {
03364 setAlignment( Qt3::AlignAuto );
03365 setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc );
03366 setFormat( doc->formatCollection()->defaultFormat(), QTextFormat::Format );
03367 }
03368
03374 QStyleSheet* QTextEdit::styleSheet() const
03375 {
03376 return doc->styleSheet();
03377 }
03378
03385 void QTextEdit::setStyleSheet( QStyleSheet* styleSheet )
03386 {
03387 doc->setStyleSheet( styleSheet );
03388 }
03389
03398 void QTextEdit::setPaper( const QBrush& pap )
03399 {
03400 doc->setPaper( new QBrush( pap ) );
03401 viewport()->setBackgroundColor( pap.color() );
03402 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
03403 }
03404
03405 QBrush QTextEdit::paper() const
03406 {
03407 if ( doc->paper() )
03408 return *doc->paper();
03409 return QBrush();
03410 }
03411
03420 void QTextEdit::setLinkUnderline( bool b )
03421 {
03422 doc->setUnderlineLinks( b );
03423 }
03424
03425 bool QTextEdit::linkUnderline() const
03426 {
03427 return doc->underlineLinks();
03428 }
03429
03436 void QTextEdit::setMimeSourceFactory( QMimeSourceFactory* factory )
03437 {
03438 doc->setMimeSourceFactory( factory );
03439 }
03440
03447 QMimeSourceFactory* QTextEdit::mimeSourceFactory() const
03448 {
03449 return doc->mimeSourceFactory();
03450 }
03451
03457 int QTextEdit::heightForWidth( int w ) const
03458 {
03459 int oldw = doc->width();
03460 doc->doLayout( 0, w );
03461 int h = doc->height();
03462 doc->setWidth( oldw );
03463 doc->invalidate();
03464 ( (QTextEdit*)this )->formatMore();
03465 return h;
03466 }
03467
03472 void QTextEdit::append( const QString &text )
03473 {
03474
03475 undoRedoInfo.clear();
03476 doc->commands()->clear();
03477
03478 doc->removeSelection( QTextDocument::Standard );
03479 TextFormat f = doc->textFormat();
03480 if ( f == AutoText ) {
03481 if ( QStyleSheet::mightBeRichText( text ) )
03482 f = RichText;
03483 else
03484 f = PlainText;
03485 }
03486
03487 drawCursor( FALSE );
03488 QTextCursor oldc( *cursor );
03489 ensureFormatted( doc->lastParagraph() );
03490 bool atBottom = contentsY() >= contentsHeight() - visibleHeight();
03491 cursor->gotoEnd();
03492 if ( cursor->index() > 0 )
03493 cursor->splitAndInsertEmptyParagraph();
03494 QTextCursor oldCursor2 = *cursor;
03495
03496 if ( f == Qt::PlainText ) {
03497 cursor->insert( text, TRUE );
03498 if ( doc->useFormatCollection() &&
03499 currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) {
03500 doc->setSelectionStart( QTextDocument::Temp, oldCursor2 );
03501 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
03502 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format );
03503 doc->removeSelection( QTextDocument::Temp );
03504 }
03505 } else {
03506 if ( cursor->paragraph()->prev() )
03507 cursor->paragraph()->prev()->invalidate(0);
03508 doc->setRichTextInternal( text );
03509 }
03510 formatMore();
03511 repaintChanged();
03512 if ( atBottom )
03513 scrollToBottom();
03514 *cursor = oldc;
03515 if ( !isReadOnly() )
03516 cursorVisible = TRUE;
03517 setModified();
03518 emit textChanged();
03519 }
03520
03525 bool QTextEdit::hasSelectedText() const
03526 {
03527 return doc->hasSelection( QTextDocument::Standard );
03528 }
03529
03541 QString QTextEdit::selectedText() const
03542 {
03543 return doc->selectedText( QTextDocument::Standard );
03544 }
03545
03546 bool QTextEdit::handleReadOnlyKeyEvent( QKeyEvent *e )
03547 {
03548 switch( e->key() ) {
03549 case Key_Down:
03550 setContentsPos( contentsX(), contentsY() + 10 );
03551 break;
03552 case Key_Up:
03553 setContentsPos( contentsX(), contentsY() - 10 );
03554 break;
03555 case Key_Left:
03556 setContentsPos( contentsX() - 10, contentsY() );
03557 break;
03558 case Key_Right:
03559 setContentsPos( contentsX() + 10, contentsY() );
03560 break;
03561 case Key_PageUp:
03562 setContentsPos( contentsX(), contentsY() - visibleHeight() );
03563 break;
03564 case Key_PageDown:
03565 setContentsPos( contentsX(), contentsY() + visibleHeight() );
03566 break;
03567 case Key_Home:
03568 setContentsPos( contentsX(), 0 );
03569 break;
03570 case Key_End:
03571 setContentsPos( contentsX(), contentsHeight() - visibleHeight() );
03572 break;
03573 case Key_F16:
03574 copy();
03575 break;
03576 #ifndef QT_NO_NETWORKPROTOCOL
03577 case Key_Return:
03578 case Key_Enter:
03579 case Key_Space: {
03580 if ( !doc->focusIndicator.href.isEmpty() ) {
03581 QUrl u( doc->context(), doc->focusIndicator.href, TRUE );
03582 emitLinkClicked( u.toString( FALSE, FALSE ) );
03583 #ifndef QT_NO_CURSOR
03584 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
03585 #endif
03586 }
03587 } break;
03588 #endif
03589 default:
03590 if ( e->state() & ControlButton ) {
03591 switch ( e->key() ) {
03592 case Key_C: case Key_F16:
03593 copy();
03594 break;
03595 }
03596 }
03597 return FALSE;
03598 }
03599 return TRUE;
03600 }
03601
03609 QString QTextEdit::context() const
03610 {
03611 return doc->context();
03612 }
03613
03623 QString QTextEdit::documentTitle() const
03624 {
03625 return doc->attributes()[ "title" ];
03626 }
03627
03628 void QTextEdit::makeParagVisible( QTextParagraph *p )
03629 {
03630 setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) );
03631 }
03632
03639 void QTextEdit::scrollToAnchor( const QString& name )
03640 {
03641 if ( !isVisible() ) {
03642 d->scrollToAnchor = name;
03643 return;
03644 }
03645 if ( name.isEmpty() )
03646 return;
03647 sync();
03648 QTextCursor cursor( doc );
03649 QTextParagraph* last = doc->lastParagraph();
03650 for (;;) {
03651 QTextStringChar* c = cursor.paragraph()->at( cursor.index() );
03652 if( c->isAnchor() ) {
03653 QString a = c->anchorName();
03654 if ( a == name ||
03655 (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) {
03656 setContentsPos( contentsX(), QMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) );
03657 break;
03658 }
03659 }
03660 if ( cursor.paragraph() == last && cursor.atParagEnd() )
03661 break;
03662 cursor.gotoNextLetter();
03663 }
03664 }
03665
03671 QString QTextEdit::anchorAt( const QPoint& pos )
03672 {
03673 QTextCursor c( doc );
03674 placeCursor( pos, &c );
03675 return c.paragraph()->at( c.index() )->anchorHref();
03676 }
03677
03678 void QTextEdit::documentWidthChanged( int w )
03679 {
03680 resizeContents( QMAX( visibleWidth(), w), contentsHeight() );
03681 }
03682
03688 void QTextEdit::updateStyles()
03689 {
03690 }
03691
03692 void QTextEdit::setDocument( QTextDocument *dc )
03693 {
03694 if ( dc == doc )
03695 return;
03696 doc = dc;
03697 delete cursor;
03698 cursor = new QTextCursor( doc );
03699 clearUndoRedo();
03700 undoRedoInfo.doc = doc;
03701 lastFormatted = 0;
03702 }
03703
03704 #ifndef QT_NO_CLIPBOARD
03705
03716 void QTextEdit::pasteSubType( const QCString& subtype )
03717 {
03718 QCString st = subtype;
03719 QString t = QApplication::clipboard()->text(st);
03720 if ( doc->hasSelection( QTextDocument::Standard ) )
03721 removeSelectedText();
03722 if ( !t.isEmpty() ) {
03723 if ( t.startsWith( "<selstart/>" ) ) {
03724 t.remove( 0, 11 );
03725 QTextCursor oldC = *cursor;
03726 lastFormatted = cursor->paragraph();
03727 if ( lastFormatted->prev() )
03728 lastFormatted = lastFormatted->prev();
03729 doc->setRichTextInternal( t, cursor );
03730
03731 if ( undoEnabled && !isReadOnly() ) {
03732 doc->setSelectionStart( QTextDocument::Temp, oldC );
03733 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
03734
03735 checkUndoRedoInfo( UndoRedoInfo::Insert );
03736 if ( !undoRedoInfo.valid() ) {
03737 undoRedoInfo.id = oldC.paragraph()->paragId();
03738 undoRedoInfo.index = oldC.index();
03739 undoRedoInfo.d->text = QString::null;
03740 }
03741 int oldLen = undoRedoInfo.d->text.length();
03742 if ( !doc->preProcessor() ) {
03743 QString txt = doc->selectedText( QTextDocument::Temp );
03744 undoRedoInfo.d->text += txt;
03745 for ( int i = 0; i < (int)txt.length(); ++i ) {
03746 if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) {
03747 oldC.paragraph()->at( oldC.index() )->format()->addRef();
03748 undoRedoInfo.d->text.
03749 setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE );
03750 }
03751 oldC.gotoNextLetter();
03752 }
03753 }
03754 undoRedoInfo.clear();
03755 removeSelection( QTextDocument::Temp );
03756 }
03757
03758 formatMore();
03759 setModified();
03760 emit textChanged();
03761 repaintChanged();
03762 ensureCursorVisible();
03763 return;
03764 }
03765
03766 #if defined(Q_OS_WIN32)
03767
03768 int index = t.find( QString::fromLatin1("\r\n"), 0 );
03769 while ( index != -1 ) {
03770 t.replace( index, 2, QChar('\n') );
03771 index = t.find( "\r\n", index );
03772 }
03773 #elif defined(Q_OS_MAC)
03774
03775 for( unsigned int index = 0; index < t.length(); index++ )
03776 if(t[index] == '\r')
03777 t[index] = '\n';
03778 #endif
03779 for ( int i=0; (uint) i<t.length(); i++ ) {
03780 if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' )
03781 t[ i ] = ' ';
03782 }
03783 if ( !t.isEmpty() )
03784 insert( t, FALSE, TRUE, TRUE );
03785 }
03786 }
03787
03788 #ifndef QT_NO_MIMECLIPBOARD
03789
03795 void QTextEdit::pasteSpecial( const QPoint& pt )
03796 {
03797 QCString st = pickSpecial( QApplication::clipboard()->data(), TRUE, pt );
03798 if ( !st.isEmpty() )
03799 pasteSubType( st );
03800 }
03801 #endif
03802 #ifndef QT_NO_MIME
03803 QCString QTextEdit::pickSpecial( QMimeSource* ms, bool always_ask, const QPoint& pt )
03804 {
03805 if ( ms ) {
03806 #ifndef QT_NO_POPUPMENU
03807 QPopupMenu popup( this, "qt_pickspecial_menu" );
03808 QString fmt;
03809 int n = 0;
03810 QDict<void> done;
03811 for (int i = 0; !( fmt = ms->format( i ) ).isNull(); i++) {
03812 int semi = fmt.find( ";" );
03813 if ( semi >= 0 )
03814 fmt = fmt.left( semi );
03815 if ( fmt.left( 5 ) == "text/" ) {
03816 fmt = fmt.mid( 5 );
03817 if ( !done.find( fmt ) ) {
03818 done.insert( fmt,(void*)1 );
03819 popup.insertItem( fmt, i );
03820 n++;
03821 }
03822 }
03823 }
03824 if ( n ) {
03825 int i = n ==1 && !always_ask ? popup.idAt( 0 ) : popup.exec( pt );
03826 if ( i >= 0 )
03827 return popup.text(i).latin1();
03828 }
03829 #else
03830 QString fmt;
03831 for (int i = 0; !( fmt = ms->format( i ) ).isNull(); i++) {
03832 int semi = fmt.find( ";" );
03833 if ( semi >= 0 )
03834 fmt = fmt.left( semi );
03835 if ( fmt.left( 5 ) == "text/" ) {
03836 fmt = fmt.mid( 5 );
03837 return fmt.latin1();
03838 }
03839 }
03840 #endif
03841 }
03842 return QCString();
03843 }
03844 #endif // QT_NO_MIME
03845 #endif // QT_NO_CLIPBOARD
03846
03887 void QTextEdit::setWordWrap( WordWrap mode )
03888 {
03889 if ( wrapMode == mode )
03890 return;
03891 wrapMode = mode;
03892 switch ( mode ) {
03893 case NoWrap:
03894 document()->formatter()->setWrapEnabled( FALSE );
03895 document()->formatter()->setWrapAtColumn( -1 );
03896 doc->setWidth( visibleWidth() );
03897 doc->setMinimumWidth( -1 );
03898 doc->invalidate();
03899 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
03900 lastFormatted = doc->firstParagraph();
03901 interval = 0;
03902 formatMore();
03903 break;
03904 case WidgetWidth:
03905 document()->formatter()->setWrapEnabled( TRUE );
03906 document()->formatter()->setWrapAtColumn( -1 );
03907 doResize();
03908 break;
03909 case FixedPixelWidth:
03910 document()->formatter()->setWrapEnabled( TRUE );
03911 document()->formatter()->setWrapAtColumn( -1 );
03912 if ( wrapWidth < 0 )
03913 wrapWidth = 200;
03914 setWrapColumnOrWidth( wrapWidth );
03915 break;
03916 case FixedColumnWidth:
03917 if ( wrapWidth < 0 )
03918 wrapWidth = 80;
03919 document()->formatter()->setWrapEnabled( TRUE );
03920 document()->formatter()->setWrapAtColumn( wrapWidth );
03921 setWrapColumnOrWidth( wrapWidth );
03922 break;
03923 }
03924 }
03925
03926 QTextEdit::WordWrap QTextEdit::wordWrap() const
03927 {
03928 return wrapMode;
03929 }
03930
03943 void QTextEdit::setWrapColumnOrWidth( int value )
03944 {
03945 wrapWidth = value;
03946 if ( wrapMode == FixedColumnWidth ) {
03947 document()->formatter()->setWrapAtColumn( wrapWidth );
03948 resizeContents( 0, 0 );
03949 doc->setWidth( visibleWidth() );
03950 doc->setMinimumWidth( -1 );
03951 } else if (wrapMode == FixedPixelWidth ) {
03952 document()->formatter()->setWrapAtColumn( -1 );
03953 resizeContents( wrapWidth, 0 );
03954 doc->setWidth( wrapWidth );
03955 doc->setMinimumWidth( wrapWidth );
03956 } else {
03957 return;
03958 }
03959 doc->invalidate();
03960 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
03961 lastFormatted = doc->firstParagraph();
03962 interval = 0;
03963 formatMore();
03964 }
03965
03966 int QTextEdit::wrapColumnOrWidth() const
03967 {
03968 if ( wrapMode == WidgetWidth )
03969 return visibleWidth();
03970 return wrapWidth;
03971 }
03972
03973
03999 void QTextEdit::setWrapPolicy( WrapPolicy policy )
04000 {
04001 if ( wPolicy == policy )
04002 return;
04003 wPolicy = policy;
04004 QTextFormatter *formatter;
04005 if ( policy == AtWhiteSpace )
04006 formatter = new QTextFormatterBreakWords;
04007 else
04008 formatter = new QTextFormatterBreakInWords;
04009 formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() );
04010 formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) );
04011 document()->setFormatter( formatter );
04012 doc->invalidate();
04013 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
04014 lastFormatted = doc->firstParagraph();
04015 interval = 0;
04016 formatMore();
04017 }
04018
04019 QTextEdit::WrapPolicy QTextEdit::wrapPolicy() const
04020 {
04021 return wPolicy;
04022 }
04023
04031 void QTextEdit::clear()
04032 {
04033
04034 doc->selectAll( QTextDocument::Temp );
04035 removeSelectedText( QTextDocument::Temp );
04036
04037 setContentsPos( 0, 0 );
04038 if ( cursor->isValid() )
04039 cursor->restoreState();
04040 doc->clear( TRUE );
04041 delete cursor;
04042 cursor = new QTextCursor( doc );
04043 lastFormatted = 0;
04044 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
04045
04046 emit cursorPositionChanged( cursor );
04047 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
04048 }
04049
04050 int QTextEdit::undoDepth() const
04051 {
04052 return document()->undoDepth();
04053 }
04054
04061 int QTextEdit::length() const
04062 {
04063 return document()->length();
04064 }
04065
04072 int QTextEdit::tabStopWidth() const
04073 {
04074 return document()->tabStopWidth();
04075 }
04076
04077 void QTextEdit::setUndoDepth( int d )
04078 {
04079 document()->setUndoDepth( d );
04080 }
04081
04082 void QTextEdit::setTabStopWidth( int ts )
04083 {
04084 document()->setTabStops( ts );
04085 doc->invalidate();
04086 lastFormatted = doc->firstParagraph();
04087 interval = 0;
04088 formatMore();
04089 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
04090 }
04091
04094 QSize QTextEdit::sizeHint() const
04095 {
04096
04097 return QSize( 100, 100 );
04098 }
04099
04100 void QTextEdit::clearUndoRedo()
04101 {
04102 undoRedoInfo.clear();
04103 emit undoAvailable( doc->commands()->isUndoAvailable() );
04104 emit redoAvailable( doc->commands()->isRedoAvailable() );
04105 }
04106
04122 bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment )
04123 {
04124 if ( !font || !color )
04125 return FALSE;
04126 QTextParagraph *p = doc->paragAt( para );
04127 if ( !p )
04128 return FALSE;
04129 if ( index < 0 || index >= p->length() )
04130 return FALSE;
04131 *font = p->at( index )->format()->font();
04132 *color = p->at( index )->format()->color();
04133 *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign();
04134 return TRUE;
04135 }
04136
04155 bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color,
04156 VerticalAlignment *verticalAlignment, int *alignment,
04157 QStyleSheetItem::DisplayMode *displayMode,
04158 QStyleSheetItem::ListStyle *listStyle,
04159 int *listDepth )
04160 {
04161 if ( !font || !color || !alignment || !displayMode || !listStyle )
04162 return FALSE;
04163 QTextParagraph *p = doc->paragAt( para );
04164 if ( !p )
04165 return FALSE;
04166 *font = p->at(0)->format()->font();
04167 *color = p->at(0)->format()->color();
04168 *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign();
04169 *alignment = p->alignment();
04170 *displayMode = p->isListItem() ? QStyleSheetItem::DisplayListItem : QStyleSheetItem::DisplayBlock;
04171 *listStyle = p->listStyle();
04172 *listDepth = p->listDepth();
04173 return TRUE;
04174 }
04175
04176
04177
04187 QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos )
04188 {
04189 #ifndef QT_NO_POPUPMENU
04190 QPopupMenu *popup = new QPopupMenu( this, "qt_edit_menu" );
04191 if ( !isReadOnly() ) {
04192 d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) );
04193 d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) );
04194 popup->insertSeparator();
04195 }
04196 #ifndef QT_NO_CLIPBOARD
04197 if ( !isReadOnly() )
04198 d->id[ IdCut ] = popup->insertItem( tr( "Cu&t" ) + ACCEL_KEY( X ) );
04199 d->id[ IdCopy ] = popup->insertItem( tr( "&Copy" ) + ACCEL_KEY( C ) );
04200 if ( !isReadOnly() )
04201 d->id[ IdPaste ] = popup->insertItem( tr( "&Paste" ) + ACCEL_KEY( V ) );
04202 #endif
04203 if ( !isReadOnly() ) {
04204 d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) );
04205 popup->insertSeparator();
04206 }
04207 #if defined(Q_WS_X11)
04208 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) );
04209 #else
04210 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) );
04211 #endif
04212 popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() );
04213 popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() );
04214 #ifndef QT_NO_CLIPBOARD
04215 popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( QTextDocument::Standard, TRUE ) );
04216 popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( QTextDocument::Standard, TRUE ) );
04217 popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
04218 #endif
04219 popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !text().isEmpty() );
04220 popup->setItemEnabled( d->id[ IdSelectAll ], (bool)text().length() );
04221 return popup;
04222 #else
04223 return 0;
04224 #endif
04225 }
04226
04238 QPopupMenu *QTextEdit::createPopupMenu()
04239 {
04240 return 0;
04241 }
04242
04245 void QTextEdit::setFont( const QFont &f )
04246 {
04247 QFont old( QScrollView::font() );
04248 QScrollView::setFont( f );
04249 doc->setMinimumWidth( -1 );
04250 doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() );
04251 lastFormatted = doc->firstParagraph();
04252 formatMore();
04253 repaintChanged();
04254 }
04255
04288 void QTextEdit::zoomIn( int range )
04289 {
04290 QFont f( QScrollView::font() );
04291 f.setPointSize( f.pointSize() + range );
04292 setFont( f );
04293 }
04294
04302 void QTextEdit::zoomOut( int range )
04303 {
04304 QFont f( QScrollView::font() );
04305 f.setPointSize( QMAX( 1, f.pointSize() - range ) );
04306 setFont( f );
04307 }
04308
04314 void QTextEdit::zoomTo( int size )
04315 {
04316 QFont f( QScrollView::font() );
04317 f.setPointSize( size );
04318 setFont( f );
04319 }
04320
04335 void QTextEdit::sync()
04336 {
04337 while ( lastFormatted ) {
04338 lastFormatted->format();
04339 lastFormatted = lastFormatted->next();
04340 }
04341 resizeContents( contentsWidth(), doc->height() );
04342 }
04343
04346 void QTextEdit::setEnabled( bool b )
04347 {
04348 QScrollView::setEnabled( b );
04349 if ( !b ) {
04350 blinkTimer->stop();
04351 drawCursor( FALSE );
04352 }
04353 if ( textFormat() == PlainText ) {
04354 QTextFormat *f = doc->formatCollection()->defaultFormat();
04355 f->setColor( colorGroup().text() );
04356 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
04357 }
04358 if ( b ) {
04359 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
04360 drawCursor( TRUE );
04361 }
04362 }
04363
04373 void QTextEdit::setSelectionAttributes( int selNum, const QColor &back, bool invertText )
04374 {
04375 if ( selNum < 1 )
04376 return;
04377 if ( selNum > doc->numSelections() )
04378 doc->addSelection( selNum );
04379 doc->setSelectionColor( selNum, back );
04380 doc->setInvertSelectionText( selNum, invertText );
04381 }
04382
04384 void QTextEdit::windowActivationChange( bool )
04385 {
04386 if ( !isVisible() )
04387 return;
04388
04389 if ( palette().active() != palette().inactive() )
04390 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
04391 }
04392
04393 void QTextEdit::setReadOnly( bool b )
04394 {
04395 if ( readonly == b )
04396 return;
04397 readonly = b;
04398 #ifndef QT_NO_CURSOR
04399 if ( readonly )
04400 viewport()->setCursor( arrowCursor );
04401 else
04402 viewport()->setCursor( ibeamCursor );
04403 #endif
04404 }
04405
04409 void QTextEdit::scrollToBottom()
04410 {
04411 sync();
04412 setContentsPos( contentsX(), contentsHeight() - visibleHeight() );
04413 }
04414
04419 QRect QTextEdit::paragraphRect( int para ) const
04420 {
04421 QTextEdit *that = (QTextEdit *)this;
04422 that->sync();
04423 QTextParagraph *p = doc->paragAt( para );
04424 if ( !p )
04425 return QRect( -1, -1, -1, -1 );
04426 return p->rect();
04427 }
04428
04434 int QTextEdit::paragraphAt( const QPoint &pos ) const
04435 {
04436 QTextCursor c( doc );
04437 c.place( pos, doc->firstParagraph() );
04438 if ( c.paragraph() )
04439 return c.paragraph()->paragId();
04440 return -1;
04441 }
04442
04450 int QTextEdit::charAt( const QPoint &pos, int *para ) const
04451 {
04452 QTextCursor c( doc );
04453 c.place( pos, doc->firstParagraph() );
04454 if ( c.paragraph() ) {
04455 if ( para )
04456 *para = c.paragraph()->paragId();
04457 return c.index();
04458 }
04459 return -1;
04460 }
04461
04464 void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg )
04465 {
04466 QTextParagraph *p = doc->paragAt( para );
04467 if ( !p )
04468 return;
04469 p->setBackgroundColor( bg );
04470 repaintChanged();
04471 }
04472
04477 void QTextEdit::clearParagraphBackground( int para )
04478 {
04479 QTextParagraph *p = doc->paragAt( para );
04480 if ( !p )
04481 return;
04482 p->clearBackgroundColor();
04483 repaintChanged();
04484 }
04485
04491 QColor QTextEdit::paragraphBackgroundColor( int para ) const
04492 {
04493 QTextParagraph *p = doc->paragAt( para );
04494 if ( !p )
04495 return QColor();
04496 QColor *c = p->backgroundColor();
04497 if ( c )
04498 return *c;
04499 return QColor();
04500 }
04501
04508 void QTextEdit::setUndoRedoEnabled( bool b )
04509 {
04510 undoEnabled = b;
04511 }
04512
04513 bool QTextEdit::isUndoRedoEnabled() const
04514 {
04515 return undoEnabled;
04516 }
04517
04520 bool QTextEdit::isUndoAvailable() const
04521 {
04522 return doc->commands()->isUndoAvailable() || undoRedoInfo.valid();
04523 }
04524
04527 bool QTextEdit::isRedoAvailable() const
04528 {
04529 return doc->commands()->isRedoAvailable();
04530 }
04531
04532 void QTextEdit::ensureFormatted( QTextParagraph *p )
04533 {
04534 while ( !p->isValid() ) {
04535 if ( !lastFormatted )
04536 return;
04537 formatMore();
04538 }
04539 }
04540
04542 void QTextEdit::updateCursor( const QPoint & pos )
04543 {
04544 if ( isReadOnly() && linksEnabled() ) {
04545 QTextCursor c = *cursor;
04546 placeCursor( pos, &c, TRUE );
04547
04548 #ifndef QT_NO_NETWORKPROTOCOL
04549 if ( c.paragraph() && c.paragraph()->at( c.index() ) &&
04550 c.paragraph()->at( c.index() )->isAnchor() &&
04551 !c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) {
04552 if ( c.index() < c.paragraph()->length() - 1 )
04553 onLink = c.paragraph()->at( c.index() )->anchorHref();
04554 else
04555 onLink = QString::null;
04556
04557 #ifndef QT_NO_CURSOR
04558 viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor );
04559 #endif
04560 QUrl u( doc->context(), onLink, TRUE );
04561 emitHighlighted( u.toString( FALSE, FALSE ) );
04562 } else {
04563 #ifndef QT_NO_CURSOR
04564 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
04565 #endif
04566 onLink = QString::null;
04567 emitHighlighted( QString::null );
04568 }
04569 #endif
04570 }
04571 }
04572
04573 void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c )
04574 {
04575 placeCursor( pos, c, FALSE );
04576 }