summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-write/qtextedit.cpp
Unidiff
Diffstat (limited to 'noncore/apps/opie-write/qtextedit.cpp') (more/less context) (show whitespace changes)
-rw-r--r--noncore/apps/opie-write/qtextedit.cpp1375
1 files changed, 727 insertions, 648 deletions
diff --git a/noncore/apps/opie-write/qtextedit.cpp b/noncore/apps/opie-write/qtextedit.cpp
index 9c5ea79..82401c6 100644
--- a/noncore/apps/opie-write/qtextedit.cpp
+++ b/noncore/apps/opie-write/qtextedit.cpp
@@ -45,174 +45,203 @@
45#include "qfont.h" 45#include "qfont.h"
46#include "qcolor.h" 46#include "qcolor.h"
47#include "qstyle.h" 47#include "qstyle.h"
48#include "qsize.h" 48#include "qsize.h"
49#include "qevent.h" 49#include "qevent.h"
50#include "qtimer.h" 50#include "qtimer.h"
51#include "qapplication.h" 51#include "qapplication.h"
52#include "qlistbox.h" 52#include "qlistbox.h"
53#include "qvbox.h" 53#include "qvbox.h"
54#include "qapplication.h" 54#include "qapplication.h"
55#include "qclipboard.h" 55#include "qclipboard.h"
56#include "qcolordialog.h" 56#include "qcolordialog.h"
57#include "qfontdialog.h" 57#include "qfontdialog.h"
58#include "qstylesheet.h" 58#include "qstylesheet.h"
59#include "qdragobject.h" 59#include "qdragobject.h"
60#include "qurl.h" 60#include "qurl.h"
61#include "qcursor.h" 61#include "qcursor.h"
62#include "qregexp.h" 62#include "qregexp.h"
63#include "qpopupmenu.h" 63#include "qpopupmenu.h"
64 64
65#define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k) 65#define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k)
66 66
67using namespace Qt3; 67using namespace Qt3;
68 68
69static bool qt_enable_richtext_copy = FALSE;
70
69struct QUndoRedoInfoPrivate 71struct QUndoRedoInfoPrivate
70{ 72{
71 QTextString text; 73 QTextString text;
72}; 74};
73 75
74namespace Qt3 { 76namespace Qt3 {
75 77
76class QTextEditPrivate 78class QTextEditPrivate
77{ 79{
78public: 80public:
79 QTextEditPrivate() 81 QTextEditPrivate()
80 :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) {} 82 :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE)
83 {
84 for ( int i=0; i<7; i++ )
85 id[i] = 0;
86 }
81 int id[ 7 ]; 87 int id[ 7 ];
82 int preeditStart; 88 int preeditStart;
83 int preeditLength; 89 int preeditLength;
84 bool ensureCursorVisibleInShowEvent; 90 bool ensureCursorVisibleInShowEvent;
91 QString scrollToAnchor; // used to deferr scrollToAnchor() until the show event when we are resized
85}; 92};
86 93
87} 94}
88 95
89static bool block_set_alignment = FALSE; 96static bool block_set_alignment = FALSE;
90 97
91/*! 98/*!
92 \class QTextEdit qtextedit.h 99 \class QTextEdit qtextedit.h
93 \brief The QTextEdit widget provides a sophisticated single-page rich text editor. 100 \brief The QTextEdit widget provides a powerful single-page rich text editor.
94 101
95 \ingroup basic 102 \ingroup basic
96 \ingroup text 103 \ingroup text
97 \mainclass 104 \mainclass
98 105
99 QTextEdit is an advanced WYSIWYG editor supporting rich text 106 \tableofcontents
100 formatting. It is optimized to handle large documents and to 107
101 respond quickly to user input. 108 \section1 Introduction and Concepts
109
110 QTextEdit is an advanced WYSIWYG viewer/editor supporting rich
111 text formatting using HTML-style tags. It is optimized to handle
112 large documents and to respond quickly to user input.
113
114 QTextEdit has three modes of operation:
115 \table
116 \header \i Mode \i Command \i Notes
117 \row \i Plain Text Editor \i setTextFormat(PlainText)
118 \i Set text with setText(); text() returns plain text. Text
119 attributes (e.g. colors) can be set, but plain text is always
120 returned.<sup>1.</sup>
121 \row \i Rich Text Editor \i setTextFormat(RichText)
122 \i Set text with setText(); text() returns rich text. Rich
123 text editing is fairly limited. You can't set margins or
124 insert images for example (although you can read and
125 correctly display files that have margins set and that
126 include images). This mode is mostly useful for editing small
127 amounts of rich text. <sup>2.</sup>
128 \row \i Text Viewer<sup>3.</sup> \i setReadOnly(TRUE)
129 \i Set text with setText() or append() (which has no undo
130 history so is faster and uses less memory); text() returns
131 plain or rich text depending on the textFormat(). This mode
132 can correctly display a large subset of HTML tags.
133 \endtable
134
135 <sup>1.</sup><small>We do \e not recommend using QTextEdit to
136 create syntax highlighting editors because the current API is
137 insufficient for this purpose. We hope to release a more complete
138 API that will support syntax highlighting in a later
139 release.</small>
140
141 <sup>2.</sup><small>A more complete API that supports setting
142 margins, images, etc., is planned for a later Qt release.</small>
143
144 <sup>3.</sup><small>Qt 3.1 will provide a Log Viewer mode which is
145 optimised for the fast and memory efficient display of large
146 amounts of read only text.</small>
147
148 We recommend that you always call setTextFormat() to set the mode
149 you want to use. If you use \c AutoText then setText() and
150 append() will try to determine whether the text they are given is
151 plain text or rich text. If you use \c RichText then setText() and
152 append() will assume that the text they are given is rich text.
153 insert() simply inserts the text it is given.
102 154
103 QTextEdit works on paragraphs and characters. A paragraph is a 155 QTextEdit works on paragraphs and characters. A paragraph is a
104 formatted string which is word-wrapped to fit into the width of 156 formatted string which is word-wrapped to fit into the width of
105 the widget. A document consists of zero or more paragraphs, 157 the widget. By default when reading plain text, two newlines
106 indexed from 0. Characters are indexed on a per-paragraph basis, 158 signify a paragraph. A document consists of zero or more
107 also indexed from 0. The words in the paragraph are aligned in 159 paragraphs, indexed from 0. Characters are indexed on a
108 accordance with the paragraph's alignment(). Paragraphs are 160 per-paragraph basis, also indexed from 0. The words in the
109 separated by hard line breaks. Each character within a paragraph 161 paragraph are aligned in accordance with the paragraph's
110 has its own attributes, for example, font and color. 162 alignment(). Paragraphs are separated by hard line breaks. Each
163 character within a paragraph has its own attributes, for example,
164 font and color.
165
166 The text edit documentation uses the following concepts:
167 \list
168 \i \e{current format} --
169 this is the format at the current cursor position, \e and it
170 is the format of the selected text if any.
171 \i \e{current paragraph} -- the paragraph which contains the
172 cursor.
173 \endlist
111 174
112 QTextEdit can display images (using QMimeSourceFactory), lists and 175 QTextEdit can display images (using QMimeSourceFactory), lists and
113 tables. If the text is too large to view within the text edit's 176 tables. If the text is too large to view within the text edit's
114 viewport, scrollbars will appear. The text edit can load both 177 viewport, scrollbars will appear. The text edit can load both
115 plain text and HTML files (a subset of HTML 3.2 and 4). The 178 plain text and HTML files (a subset of HTML 3.2 and 4). The
116 rendering style and the set of valid tags are defined by a 179 rendering style and the set of valid tags are defined by a
117 styleSheet(). Change the style sheet with \l{setStyleSheet()}; see 180 styleSheet(). Custom tags can be created and placed in a custom
181 style sheet. Change the style sheet with \l{setStyleSheet()}; see
118 QStyleSheet for details. The images identified by image tags are 182 QStyleSheet for details. The images identified by image tags are
119 displayed if they can be interpreted using the text edit's 183 displayed if they can be interpreted using the text edit's
120 \l{QMimeSourceFactory}; see setMimeSourceFactory(). 184 \l{QMimeSourceFactory}; see setMimeSourceFactory().
121 185
122 If you want a text browser with more navigation use QTextBrowser. 186 If you want a text browser with more navigation use QTextBrowser.
123 If you just need to display a small piece of rich text use QLabel 187 If you just need to display a small piece of rich text use QLabel
124 or QSimpleRichText. 188 or QSimpleRichText.
125 189
126 If you create a new QTextEdit, and want to allow the user to edit 190 If you create a new QTextEdit, and want to allow the user to edit
127 rich text, call setTextFormat(Qt::RichText) to ensure that the 191 rich text, call setTextFormat(Qt::RichText) to ensure that the
128 text is treated as rich text. (Rich text uses HTML tags to set 192 text is treated as rich text. (Rich text uses HTML tags to set
129 text formatting attributes. See QStyleSheet for information on the 193 text formatting attributes. See QStyleSheet for information on the
130 HTML tags that are supported.). If you don't call setTextFormat() 194 HTML tags that are supported.). If you don't call setTextFormat()
131 explicitly the text edit will guess from the text itself whether 195 explicitly the text edit will guess from the text itself whether
132 it is rich text or plain text. This means that if the text looks 196 it is rich text or plain text. This means that if the text looks
133 like HTML or XML it will probably be interpreted as rich text, so 197 like HTML or XML it will probably be interpreted as rich text, so
134 you should call setTextFormat(Qt::PlainText) to preserve such 198 you should call setTextFormat(Qt::PlainText) to preserve such
135 text. 199 text.
136 200
137 The text edit documentation uses the following concepts: 201 Note that we do not intend to add a full-featured web browser
138 \list 202 widget to Qt (because that would easily double Qt's size and only
139 \i <i>current format</i> -- 203 a few applications would benefit from it). The rich
140 this is the format at the current cursor position, \e and it 204 text support in Qt is designed to provide a fast, portable and
141 is the format of the selected text if any. 205 efficient way to add reasonable online help facilities to
142 \i <i>current paragraph</i> -- the paragraph which contains the 206 applications, and to provide a basis for rich text editors.
143 cursor. 207 \section1 Using QTextEdit as a Display Widget
144 \endlist 208
209 QTextEdit can display a large HTML subset, including tables and
210 images.
145 211
146 The text is set or replaced using setText() which deletes any 212 The text is set or replaced using setText() which deletes any
147 existing text and replaces it with the text passed in the 213 existing text and replaces it with the text passed in the
148 setText() call. Text can be inserted with insert(), paste() and 214 setText() call. If you call setText() with legacy HTML (with
149 pasteSubType(). Text can also be cut(). The entire text is deleted 215 setTextFormat(RichText) in force), and then call text(), the text
150 with clear() and the selected text is deleted with 216 that is returned may have different markup, but will render the
151 removeSelectedText(). Selected (marked) text can also be deleted 217 same. Text can be inserted with insert(), paste(), pasteSubType()
152 with del() (which will delete the character to the right of the 218 and append(). Text that is appended does not go into the undo
153 cursor if no text is selected). 219 history; this makes append() faster and consumes less memory. Text
154 220 can also be cut(). The entire text is deleted with clear() and the
155 The current format's attributes are set with setItalic(), 221 selected text is deleted with removeSelectedText(). Selected
156 setBold(), setUnderline(), setFamily() (font family), 222 (marked) text can also be deleted with del() (which will delete
157 setPointSize(), setColor() and setCurrentFont(). The current 223 the character to the right of the cursor if no text is selected).
158 paragraph's style is set with setParagType() and its alignment is
159 set with setAlignment().
160
161 Use setSelection() to select text. The setSelectionAttributes()
162 function is used to indicate how selected text should be
163 displayed. Use hasSelectedText() to find out if any text is
164 selected. The currently selected text's position is available
165 using getSelection() and the selected text itself is returned by
166 selectedText(). The selection can be copied to the clipboard with
167 copy(), or cut to the clipboard with cut(). It can be deleted with
168 removeSelectedText(). The entire text can be selected (or
169 unselected) using selectAll(). QTextEdit supports multiple
170 selections. Most of the selection functions operate on the default
171 selection, selection 0. If the user presses a non-selecting key,
172 e.g. a cursor key without also holding down Shift, all selections
173 are cleared.
174
175 Set and get the position of the cursor with setCursorPosition()
176 and getCursorPosition() respectively. When the cursor is moved,
177 the signals currentFontChanged(), currentColorChanged() and
178 currentAlignmentChanged() are emitted to reflect the font, color
179 and alignment at the new cursor position.
180
181 If the text changes, the textChanged() signal is emitted, and if
182 the user inserts a new line by pressing Return or Enter,
183 returnPressed() is emitted. The isModified() function will return
184 TRUE if the text has been modified.
185
186 QTextEdit provides command-based undo and redo. To set the depth
187 of the command history use setUndoDepth() which defaults to 100
188 steps. To undo or redo the last operation call undo() or redo().
189 The signals undoAvailable() and redoAvailable() indicate whether
190 the undo and redo operations can be executed.
191
192 The indent() function is used to reindent a paragraph. It is
193 useful for code editors, for example in <em>Qt Designer</em>'s
194 code editor \e{Ctrl+I} invokes the indent() function.
195 224
196 Loading and saving text is achieved using setText() and text(), 225 Loading and saving text is achieved using setText() and text(),
197 for example: 226 for example:
198 \code 227 \code
199 QFile file( fileName ); // Read the text from a file 228 QFile file( fileName ); // Read the text from a file
200 if ( file.open( IO_ReadOnly ) ) { 229 if ( file.open( IO_ReadOnly ) ) {
201 QTextStream ts( &file ); 230 QTextStream ts( &file );
202 textEdit->setText( ts.read() ); 231 textEdit->setText( ts.read() );
203 } 232 }
204 \endcode 233 \endcode
205 \code 234 \code
206 QFile file( fileName ); // Write the text to a file 235 QFile file( fileName ); // Write the text to a file
207 if ( file.open( IO_WriteOnly ) ) { 236 if ( file.open( IO_WriteOnly ) ) {
208 QTextStream ts( &file ); 237 QTextStream ts( &file );
209 ts << textEdit->text(); 238 ts << textEdit->text();
210 textEdit->setModified( FALSE ); 239 textEdit->setModified( FALSE );
211 } 240 }
212 \endcode 241 \endcode
213 242
214 By default the text edit wraps words at whitespace to fit within 243 By default the text edit wraps words at whitespace to fit within
215 the text edit widget. The setWordWrap() function is used to 244 the text edit widget. The setWordWrap() function is used to
216 specify the kind of word wrap you want, or \c NoWrap if you don't 245 specify the kind of word wrap you want, or \c NoWrap if you don't
217 want any wrapping. Call setWordWrap() to set a fixed pixel width 246 want any wrapping. Call setWordWrap() to set a fixed pixel width
218 \c FixedPixelWidth, or character column (e.g. 80 column) \c 247 \c FixedPixelWidth, or character column (e.g. 80 column) \c
@@ -222,48 +251,127 @@ static bool block_set_alignment = FALSE;
222 anywhere with setWrapPolicy(). 251 anywhere with setWrapPolicy().
223 252
224 The background color is set differently than other widgets, using 253 The background color is set differently than other widgets, using
225 setPaper(). You specify a brush style which could be a plain color 254 setPaper(). You specify a brush style which could be a plain color
226 or a complex pixmap. 255 or a complex pixmap.
227 256
228 Hypertext links are automatically underlined; this can be changed 257 Hypertext links are automatically underlined; this can be changed
229 with setLinkUnderline(). The tab stop width is set with 258 with setLinkUnderline(). The tab stop width is set with
230 setTabStopWidth(). 259 setTabStopWidth().
231 260
232 The zoomIn() and zoomOut() functions can be used to resize the 261 The zoomIn() and zoomOut() functions can be used to resize the
233 text by increasing (decreasing for zoomOut()) the point size used. 262 text by increasing (decreasing for zoomOut()) the point size used.
234 Images are not affected by the zoom functions. 263 Images are not affected by the zoom functions.
235 264
236 The lines() function returns the number of lines in the text and 265 The lines() function returns the number of lines in the text and
237 paragraphs() returns the number of paragraphs. The number of lines 266 paragraphs() returns the number of paragraphs. The number of lines
238 within a particular paragraph is returned by linesOfParagraph(). 267 within a particular paragraph is returned by linesOfParagraph().
239 The length of the entire text in characters is returned by 268 The length of the entire text in characters is returned by
240 length(). 269 length().
241 270
242 You can scroll to an anchor in the text, e.g. \c{<a 271 You can scroll to an anchor in the text, e.g. \c{<a
243 name="anchor">} with scrollToAnchor(). The find() function can be 272 name="anchor">} with scrollToAnchor(). The find() function can be
244 used to find and select a given string within the text. 273 used to find and select a given string within the text.
245 274
275 A read-only QTextEdit provides the same functionality as the
276 (obsolete) QTextView. (QTextView is still supplied for
277 compatibility with old code.)
278
279 \section2 Read-only key bindings
280
281 When QTextEdit is used read-only the key-bindings are limited to
282 navigation, and text may only be selected with the mouse:
283 \table
284 \header \i Keypresses \i Action
285 \row \i \e{UpArrow} \i Move one line up
286 \row \i \e{DownArrow} \i Move one line down
287 \row \i \e{LeftArrow} \i Move one character left
288 \row \i \e{RightArrow} \i Move one character right
289 \row \i \e{PageUp} \i Move one (viewport) page up
290 \row \i \e{PageDown} \i Move one (viewport) page down
291 \row \i \e{Home} \i Move to the beginning of the text
292 \row \i \e{End} \i Move to the end of the text
293 \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel)
294 \row \i \e{Ctrl+Wheel} \i Zoom the text
295 \endtable
296
297 The text edit may be able to provide some meta-information. For
298 example, the documentTitle() function will return the text from
299 within HTML \c{<title>} tags.
300
301 The text displayed in a text edit has a \e context. The context is
302 a path which the text edit's QMimeSourceFactory uses to resolve
303 the locations of files and images. It is passed to the
304 mimeSourceFactory() when quering data. (See QTextEdit() and
305 \l{context()}.)
306
307 \section1 Using QTextEdit as an Editor
308
309 All the information about using QTextEdit as a display widget also
310 applies here.
311
312 The current format's attributes are set with setItalic(),
313 setBold(), setUnderline(), setFamily() (font family),
314 setPointSize(), setColor() and setCurrentFont(). The current
315 paragraph's alignment is set with setAlignment().
316
317 Use setSelection() to select text. The setSelectionAttributes()
318 function is used to indicate how selected text should be
319 displayed. Use hasSelectedText() to find out if any text is
320 selected. The currently selected text's position is available
321 using getSelection() and the selected text itself is returned by
322 selectedText(). The selection can be copied to the clipboard with
323 copy(), or cut to the clipboard with cut(). It can be deleted with
324 removeSelectedText(). The entire text can be selected (or
325 unselected) using selectAll(). QTextEdit supports multiple
326 selections. Most of the selection functions operate on the default
327 selection, selection 0. If the user presses a non-selecting key,
328 e.g. a cursor key without also holding down Shift, all selections
329 are cleared.
330
331 Set and get the position of the cursor with setCursorPosition()
332 and getCursorPosition() respectively. When the cursor is moved,
333 the signals currentFontChanged(), currentColorChanged() and
334 currentAlignmentChanged() are emitted to reflect the font, color
335 and alignment at the new cursor position.
336
337 If the text changes, the textChanged() signal is emitted, and if
338 the user inserts a new line by pressing Return or Enter,
339 returnPressed() is emitted. The isModified() function will return
340 TRUE if the text has been modified.
341
342 QTextEdit provides command-based undo and redo. To set the depth
343 of the command history use setUndoDepth() which defaults to 100
344 steps. To undo or redo the last operation call undo() or redo().
345 The signals undoAvailable() and redoAvailable() indicate whether
346 the undo and redo operations can be executed.
347
348 The indent() function is used to reindent a paragraph. It is
349 useful for code editors, for example in <em>Qt Designer</em>'s
350 code editor \e{Ctrl+I} invokes the indent() function.
351
352 \section2 Editing key bindings
353
246 The list of key-bindings which are implemented for editing: 354 The list of key-bindings which are implemented for editing:
247 \table 355 \table
248 \header \i Keypresses \i Action 356 \header \i Keypresses \i Action
249 \row \i \e{Backspace} \i Delete the character to the left of the cursor 357 \row \i \e{Backspace} \i Delete the character to the left of the cursor
250 \row \i \e{Delete} \i Delete the character to the right of the cursor 358 \row \i \e{Delete} \i Delete the character to the right of the cursor
251 \row \i \e{Ctrl+A} \i Move the cursor to the beginning of the line 359 \row \i \e{Ctrl+A} \i Move the cursor to the beginning of the line
252 \row \i \e{Ctrl+B} \i Move the cursor one character left 360 \row \i \e{Ctrl+B} \i Move the cursor one character left
253 \row \i \e{Ctrl+C} \i Copy the marked text to the clipboard (also 361 \row \i \e{Ctrl+C} \i Copy the marked text to the clipboard (also
254 \e{Ctrl+Insert} under Windows) 362 \e{Ctrl+Insert} under Windows)
255 \row \i \e{Ctrl+D} \i Delete the character to the right of the cursor 363 \row \i \e{Ctrl+D} \i Delete the character to the right of the cursor
256 \row \i \e{Ctrl+E} \i Move the cursor to the end of the line 364 \row \i \e{Ctrl+E} \i Move the cursor to the end of the line
257 \row \i \e{Ctrl+F} \i Move the cursor one character right 365 \row \i \e{Ctrl+F} \i Move the cursor one character right
258 \row \i \e{Ctrl+H} \i Delete the character to the left of the cursor 366 \row \i \e{Ctrl+H} \i Delete the character to the left of the cursor
259 \row \i \e{Ctrl+K} \i Delete to end of line 367 \row \i \e{Ctrl+K} \i Delete to end of line
260 \row \i \e{Ctrl+N} \i Move the cursor one line down 368 \row \i \e{Ctrl+N} \i Move the cursor one line down
261 \row \i \e{Ctrl+P} \i Move the cursor one line up 369 \row \i \e{Ctrl+P} \i Move the cursor one line up
262 \row \i \e{Ctrl+V} \i Paste the clipboard text into line edit 370 \row \i \e{Ctrl+V} \i Paste the clipboard text into line edit
263 (also \e{Shift+Insert} under Windows) 371 (also \e{Shift+Insert} under Windows)
264 \row \i \e{Ctrl+X} \i Cut the marked text, copy to clipboard 372 \row \i \e{Ctrl+X} \i Cut the marked text, copy to clipboard
265 (also \e{Shift+Delete} under Windows) 373 (also \e{Shift+Delete} under Windows)
266 \row \i \e{Ctrl+Z} \i Undo the last operation 374 \row \i \e{Ctrl+Z} \i Undo the last operation
267 \row \i \e{Ctrl+Y} \i Redo the last operation 375 \row \i \e{Ctrl+Y} \i Redo the last operation
268 \row \i \e{LeftArrow} \i Move the cursor one character left 376 \row \i \e{LeftArrow} \i Move the cursor one character left
269 \row \i \e{Ctrl+LeftArrow} \i Move the cursor one word left 377 \row \i \e{Ctrl+LeftArrow} \i Move the cursor one word left
@@ -274,85 +382,48 @@ static bool block_set_alignment = FALSE;
274 \row \i \e{DownArrow} \i Move the cursor one line down 382 \row \i \e{DownArrow} \i Move the cursor one line down
275 \row \i \e{Ctrl+Down Arrow} \i Move the cursor one word down 383 \row \i \e{Ctrl+Down Arrow} \i Move the cursor one word down
276 \row \i \e{PageUp} \i Move the cursor one page up 384 \row \i \e{PageUp} \i Move the cursor one page up
277 \row \i \e{PageDown} \i Move the cursor one page down 385 \row \i \e{PageDown} \i Move the cursor one page down
278 \row \i \e{Home} \i Move the cursor to the beginning of the line 386 \row \i \e{Home} \i Move the cursor to the beginning of the line
279 \row \i \e{Ctrl+Home} \i Move the cursor to the beginning of the text 387 \row \i \e{Ctrl+Home} \i Move the cursor to the beginning of the text
280 \row \i \e{End} \i Move the cursor to the end of the line 388 \row \i \e{End} \i Move the cursor to the end of the line
281 \row \i \e{Ctrl+End} \i Move the cursor to the end of the text 389 \row \i \e{Ctrl+End} \i Move the cursor to the end of the text
282 \row \i \e{Shift+Wheel} \i Scroll the page horizontally 390 \row \i \e{Shift+Wheel} \i Scroll the page horizontally
283 (the Wheel is the mouse wheel) 391 (the Wheel is the mouse wheel)
284 \row \i \e{Ctrl+Wheel} \i Zoom the text 392 \row \i \e{Ctrl+Wheel} \i Zoom the text
285 \endtable 393 \endtable
286 394
287 To select (mark) text hold down the Shift key whilst pressing one 395 To select (mark) text hold down the Shift key whilst pressing one
288 of the movement keystrokes, for example, <i>Shift+Right Arrow</i> 396 of the movement keystrokes, for example, <i>Shift+Right Arrow</i>
289 will select the character to the right, and <i>Shift+Ctrl+Right 397 will select the character to the right, and <i>Shift+Ctrl+Right
290 Arrow</i> will select the word to the right, etc. 398 Arrow</i> will select the word to the right, etc.
291 399
292 By default the text edit widget operates in insert mode so all 400 By default the text edit widget operates in insert mode so all
293 text that the user enters is inserted into the text edit and any 401 text that the user enters is inserted into the text edit and any
294 text to the right of the cursor is moved out of the way. The mode 402 text to the right of the cursor is moved out of the way. The mode
295 can be changed to overwrite, where new text overwrites any text to 403 can be changed to overwrite, where new text overwrites any text to
296 the right of the cursor, using setOverwriteMode(). 404 the right of the cursor, using setOverwriteMode().
297 405
298 QTextEdit can also be used as read-only text viewer. Call
299 setReadOnly( TRUE ) to disable editing. A read-only QTextEdit
300 provides the same functionality as the (obsolete) QTextView.
301 (QTextView is still supplied for compatibility with old code.)
302
303 When QTextEdit is used read-only the key-bindings are limited to
304 navigation, and text may only be selected with the mouse:
305 \table
306 \header \i Keypresses \i Action
307 \row \i \e{UpArrow} \i Move one line up
308 \row \i \e{DownArrow} \i Move one line down
309 \row \i \e{LeftArrow} \i Move one character left
310 \row \i \e{RightArrow} \i Move one character right
311 \row \i \e{PageUp} \i Move one (viewport) page up
312 \row \i \e{PageDown} \i Move one (viewport) page down
313 \row \i \e{Home} \i Move to the beginning of the text
314 \row \i \e{End} \i Move to the end of the text
315 \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel)
316 \row \i \e{Ctrl+Wheel} \i Zoom the text
317 \endtable
318
319 The text edit may be able to provide some meta-information. For
320 example, the documentTitle() function will return the text from
321 within HTML \c{<title>} tags.
322
323 The text displayed in a text edit has a \e context. The context is
324 a path which the text edit's QMimeSourceFactory uses to resolve
325 the locations of files and images. It is passed to the
326 mimeSourceFactory() when quering data. (See QTextEdit() and
327 \l{context()}.)
328
329 Note that we do not intend to add a full-featured web browser
330 widget to Qt (because that would easily double Qt's size and only
331 a few applications would benefit from it). The rich
332 text support in Qt is designed to provide a fast, portable and
333 efficient way to add reasonable online help facilities to
334 applications, and to provide a basis for rich text editors.
335*/ 406*/
336 407
337/*! \enum QTextEdit::KeyboardAction 408/*! \enum QTextEdit::KeyboardAction
338 409
339 This enum is used by doKeyboardAction() to specify which action 410 This enum is used by doKeyboardAction() to specify which action
340 should be executed: 411 should be executed:
341 412
342 \value ActionBackspace Delete the character to the left of the 413 \value ActionBackspace Delete the character to the left of the
343 cursor. 414 cursor.
344 415
345 \value ActionDelete Delete the character to the right of the cursor. 416 \value ActionDelete Delete the character to the right of the cursor.
346 417
347 \value ActionReturn Split the paragraph at the cursor position. 418 \value ActionReturn Split the paragraph at the cursor position.
348 419
349 \value ActionKill If the cursor is not at the end of the paragraph, 420 \value ActionKill If the cursor is not at the end of the paragraph,
350 delete the text from the cursor position until the end of the 421 delete the text from the cursor position until the end of the
351 paragraph. If the cursor is at the end of the paragraph, delete the 422 paragraph. If the cursor is at the end of the paragraph, delete the
352 hard line break at the end of the paragraph - this will cause this 423 hard line break at the end of the paragraph - this will cause this
353 paragraph to be joined with the following paragraph. 424 paragraph to be joined with the following paragraph.
354*/ 425*/
355 426
356/*! \enum QTextEdit::VerticalAlignment 427/*! \enum QTextEdit::VerticalAlignment
357 428
358 This enum is used to set the vertical alignment of the text. 429 This enum is used to set the vertical alignment of the text.
@@ -619,67 +690,69 @@ QTextEdit::~QTextEdit()
619 delete d; 690 delete d;
620} 691}
621 692
622void QTextEdit::init() 693void QTextEdit::init()
623{ 694{
624 setFrameStyle( Sunken ); 695 setFrameStyle( Sunken );
625 undoEnabled = TRUE; 696 undoEnabled = TRUE;
626 readonly = TRUE; 697 readonly = TRUE;
627 setReadOnly( FALSE ); 698 setReadOnly( FALSE );
628 d = new QTextEditPrivate; 699 d = new QTextEditPrivate;
629 connect( doc, SIGNAL( minimumWidthChanged( int ) ), 700 connect( doc, SIGNAL( minimumWidthChanged( int ) ),
630 this, SLOT( documentWidthChanged( int ) ) ); 701 this, SLOT( documentWidthChanged( int ) ) );
631 702
632 mousePressed = FALSE; 703 mousePressed = FALSE;
633 inDoubleClick = FALSE; 704 inDoubleClick = FALSE;
634 modified = FALSE; 705 modified = FALSE;
635 onLink = QString::null; 706 onLink = QString::null;
636 overWrite = FALSE; 707 overWrite = FALSE;
637 wrapMode = WidgetWidth; 708 wrapMode = WidgetWidth;
638 wrapWidth = -1; 709 wrapWidth = -1;
639 wPolicy = AtWhiteSpace; 710 wPolicy = AtWhiteSpace;
640 inDnD = FALSE; 711 inDnD = FALSE;
641 712
642 doc->setFormatter( new QTextFormatterBreakWords ); 713 doc->setFormatter( new QTextFormatterBreakWords );
714 doc->formatCollection()->defaultFormat()->setFont( QScrollView::font() );
715 doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( QColorGroup::Text ) );
643 currentFormat = doc->formatCollection()->defaultFormat(); 716 currentFormat = doc->formatCollection()->defaultFormat();
644 currentAlignment = Qt3::AlignAuto; 717 currentAlignment = Qt3::AlignAuto;
645 718
646 viewport()->setBackgroundMode( PaletteBase ); 719 viewport()->setBackgroundMode( PaletteBase );
647 viewport()->setAcceptDrops( TRUE ); 720 viewport()->setAcceptDrops( TRUE );
648 resizeContents( 0, doc->lastParag() ? 721 resizeContents( 0, doc->lastParagraph() ?
649 ( doc->lastParag()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); 722 ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 );
650 723
651 setKeyCompression( TRUE ); 724 setKeyCompression( TRUE );
652 viewport()->setMouseTracking( TRUE ); 725 viewport()->setMouseTracking( TRUE );
653#ifndef QT_NO_CURSOR 726#ifndef QT_NO_CURSOR
654 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 727 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
655#endif 728#endif
656 cursor = new QTextCursor( doc ); 729 cursor = new QTextCursor( doc );
657 730
658 formatTimer = new QTimer( this ); 731 formatTimer = new QTimer( this );
659 connect( formatTimer, SIGNAL( timeout() ), 732 connect( formatTimer, SIGNAL( timeout() ),
660 this, SLOT( formatMore() ) ); 733 this, SLOT( formatMore() ) );
661 lastFormatted = doc->firstParag(); 734 lastFormatted = doc->firstParagraph();
662 735
663 scrollTimer = new QTimer( this ); 736 scrollTimer = new QTimer( this );
664 connect( scrollTimer, SIGNAL( timeout() ), 737 connect( scrollTimer, SIGNAL( timeout() ),
665 this, SLOT( autoScrollTimerDone() ) ); 738 this, SLOT( autoScrollTimerDone() ) );
666 739
667 interval = 0; 740 interval = 0;
668 changeIntervalTimer = new QTimer( this ); 741 changeIntervalTimer = new QTimer( this );
669 connect( changeIntervalTimer, SIGNAL( timeout() ), 742 connect( changeIntervalTimer, SIGNAL( timeout() ),
670 this, SLOT( doChangeInterval() ) ); 743 this, SLOT( doChangeInterval() ) );
671 744
672 cursorVisible = TRUE; 745 cursorVisible = TRUE;
673 blinkTimer = new QTimer( this ); 746 blinkTimer = new QTimer( this );
674 connect( blinkTimer, SIGNAL( timeout() ), 747 connect( blinkTimer, SIGNAL( timeout() ),
675 this, SLOT( blinkCursor() ) ); 748 this, SLOT( blinkCursor() ) );
676 749
677#ifndef QT_NO_DRAGANDDROP 750#ifndef QT_NO_DRAGANDDROP
678 dragStartTimer = new QTimer( this ); 751 dragStartTimer = new QTimer( this );
679 connect( dragStartTimer, SIGNAL( timeout() ), 752 connect( dragStartTimer, SIGNAL( timeout() ),
680 this, SLOT( startDrag() ) ); 753 this, SLOT( startDrag() ) );
681#endif 754#endif
682 755
683 756
684 formatMore(); 757 formatMore();
685 758
@@ -692,52 +765,52 @@ void QTextEdit::init()
692} 765}
693 766
694void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw, int ch ) 767void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw, int ch )
695{ 768{
696 bool drawCur = hasFocus() || viewport()->hasFocus(); 769 bool drawCur = hasFocus() || viewport()->hasFocus();
697 if ( hasSelectedText() || isReadOnly() || !cursorVisible ) 770 if ( hasSelectedText() || isReadOnly() || !cursorVisible )
698 drawCur = FALSE; 771 drawCur = FALSE;
699 QColorGroup g = colorGroup(); 772 QColorGroup g = colorGroup();
700 if ( doc->paper() ) 773 if ( doc->paper() )
701 g.setBrush( QColorGroup::Base, *doc->paper() ); 774 g.setBrush( QColorGroup::Base, *doc->paper() );
702 775
703 if ( contentsY() < doc->y() ) { 776 if ( contentsY() < doc->y() ) {
704 p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(), 777 p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(),
705 g.brush( QColorGroup::Base ) ); 778 g.brush( QColorGroup::Base ) );
706 } 779 }
707 if ( drawAll && doc->width() - contentsX() < cx + cw ) { 780 if ( drawAll && doc->width() - contentsX() < cx + cw ) {
708 p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch, 781 p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch,
709 g.brush( QColorGroup::Base ) ); 782 g.brush( QColorGroup::Base ) );
710 } 783 }
711 784
712 p->setBrushOrigin( -contentsX(), -contentsY() ); 785 p->setBrushOrigin( -contentsX(), -contentsY() );
713 786
714 lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor ); 787 lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor );
715 788
716 if ( lastFormatted == doc->lastParag() ) 789 if ( lastFormatted == doc->lastParagraph() )
717 resizeContents( contentsWidth(), doc->height() ); 790 resizeContents( contentsWidth(), doc->height() );
718 791
719 if ( contentsHeight() < visibleHeight() && ( !doc->lastParag() || doc->lastParag()->isValid() ) && drawAll ) 792 if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll )
720 p->fillRect( 0, contentsHeight(), visibleWidth(), 793 p->fillRect( 0, contentsHeight(), visibleWidth(),
721 visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) ); 794 visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) );
722} 795}
723 796
724/*! \reimp */ 797/*! \reimp */
725 798
726void QTextEdit::drawContents( QPainter *p, int cx, int cy, int cw, int ch ) 799void QTextEdit::drawContents( QPainter *p, int cx, int cy, int cw, int ch )
727{ 800{
728 paintDocument( TRUE, p, cx, cy, cw, ch ); 801 paintDocument( TRUE, p, cx, cy, cw, ch );
729 int v; 802 int v;
730 p->setPen( foregroundColor() ); 803 p->setPen( foregroundColor() );
731 if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) { 804 if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) {
732 int l = int(cy / v) * v; 805 int l = int(cy / v) * v;
733 while ( l < cy + ch ) { 806 while ( l < cy + ch ) {
734 p->drawLine( cx, l, cx + cw - 1, l ); 807 p->drawLine( cx, l, cx + cw - 1, l );
735 l += v; 808 l += v;
736 } 809 }
737 } 810 }
738 811
739} 812}
740 813
741/*! \reimp */ 814/*! \reimp */
742 815
743void QTextEdit::drawContents( QPainter * ) 816void QTextEdit::drawContents( QPainter * )
@@ -792,784 +865,738 @@ bool QTextEdit::event( QEvent *e )
792 case Key_Down: 865 case Key_Down:
793 case Key_Home: 866 case Key_Home:
794 case Key_End: 867 case Key_End:
795 case Key_Tab: 868 case Key_Tab:
796#if defined (Q_WS_WIN) 869#if defined (Q_WS_WIN)
797 case Key_Insert: 870 case Key_Insert:
798 case Key_Delete: 871 case Key_Delete:
799#endif 872#endif
800 ke->accept(); 873 ke->accept();
801 default: 874 default:
802 break; 875 break;
803 } 876 }
804 } else { 877 } else {
805 switch ( ke->key() ) { 878 switch ( ke->key() ) {
806#if defined (Q_WS_WIN) 879#if defined (Q_WS_WIN)
807 case Key_Insert: 880 case Key_Insert:
808 ke->accept(); 881 ke->accept();
809#endif 882#endif
810 default: 883 default:
811 break; 884 break;
812 } 885 }
813 } 886 }
814 } 887 }
815 888
816 if ( e->type() == QEvent::Show && d->ensureCursorVisibleInShowEvent ) { 889 if ( e->type() == QEvent::Show ) {
890 if ( d->ensureCursorVisibleInShowEvent ) {
817 sync(); 891 sync();
818 ensureCursorVisible(); 892 ensureCursorVisible();
819 d->ensureCursorVisibleInShowEvent = FALSE; 893 d->ensureCursorVisibleInShowEvent = FALSE;
820 } 894 }
895 if ( !d->scrollToAnchor.isEmpty() ) {
896 scrollToAnchor( d->scrollToAnchor );
897 d->scrollToAnchor = QString::null;
898 }
899 }
821 return QWidget::event( e ); 900 return QWidget::event( e );
822} 901}
823 902
824/*! 903/*!
825 Processes the key event, \a e. 904 Processes the key event, \a e.
826 By default key events are used to provide keyboard navigation and 905 By default key events are used to provide keyboard navigation and
827 text editing. 906 text editing.
828*/ 907*/
829 908
830void QTextEdit::keyPressEvent( QKeyEvent *e ) 909void QTextEdit::keyPressEvent( QKeyEvent *e )
831{ 910{
832 changeIntervalTimer->stop(); 911 changeIntervalTimer->stop();
833 interval = 10; 912 interval = 10;
834 bool unknown = FALSE; 913 bool unknown = FALSE;
835 if ( isReadOnly() ) { 914 if ( isReadOnly() ) {
836 if ( !handleReadOnlyKeyEvent( e ) ) 915 if ( !handleReadOnlyKeyEvent( e ) )
837 QScrollView::keyPressEvent( e ); 916 QScrollView::keyPressEvent( e );
838 changeIntervalTimer->start( 100, TRUE ); 917 changeIntervalTimer->start( 100, TRUE );
839 return; 918 return;
840 } 919 }
841 920
842 921
843 bool selChanged = FALSE; 922 bool selChanged = FALSE;
844 for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection 923 for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection
845 selChanged = doc->removeSelection( i ) || selChanged; 924 selChanged = doc->removeSelection( i ) || selChanged;
846 925
847 if ( selChanged ) { 926 if ( selChanged ) {
848 cursor->parag()->document()->nextDoubleBuffered = TRUE; 927 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
849 repaintChanged(); 928 repaintChanged();
850 } 929 }
851 930
852 bool clearUndoRedoInfo = TRUE; 931 bool clearUndoRedoInfo = TRUE;
853 932
854 933
855 switch ( e->key() ) { 934 switch ( e->key() ) {
856 case Key_Left: 935 case Key_Left:
857 case Key_Right: { 936 case Key_Right: {
858 // a bit hacky, but can't change this without introducing new enum values for move and keeping the 937 // a bit hacky, but can't change this without introducing new enum values for move and keeping the
859 // correct semantics and movement for BiDi and non BiDi text. 938 // correct semantics and movement for BiDi and non BiDi text.
860 CursorAction a; 939 CursorAction a;
861 if ( cursor->parag()->string()->isRightToLeft() == (e->key() == Key_Right) ) 940 if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) )
862 a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; 941 a = e->state() & ControlButton ? MoveWordBackward : MoveBackward;
863 else 942 else
864 a = e->state() & ControlButton ? MoveWordForward : MoveForward; 943 a = e->state() & ControlButton ? MoveWordForward : MoveForward;
865 moveCursor( a, e->state() & ShiftButton ); 944 moveCursor( a, e->state() & ShiftButton );
866 break; 945 break;
867 } 946 }
868 case Key_Up: 947 case Key_Up:
869 moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton ); 948 moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton );
870 break; 949 break;
871 case Key_Down: 950 case Key_Down:
872 moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton ); 951 moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton );
873 break; 952 break;
874 case Key_Home: 953 case Key_Home:
875 moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton ); 954 moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton );
876 break; 955 break;
877 case Key_End: 956 case Key_End:
878 moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton ); 957 moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton );
879 break; 958 break;
880 case Key_Prior: 959 case Key_Prior:
881 moveCursor( MovePgUp, e->state() & ShiftButton ); 960 moveCursor( MovePgUp, e->state() & ShiftButton );
882 break; 961 break;
883 case Key_Next: 962 case Key_Next:
884 moveCursor( MovePgDown, e->state() & ShiftButton ); 963 moveCursor( MovePgDown, e->state() & ShiftButton );
885 break; 964 break;
886 case Key_Return: case Key_Enter: 965 case Key_Return: case Key_Enter:
887 if ( doc->hasSelection( QTextDocument::Standard, FALSE ) ) 966 if ( doc->hasSelection( QTextDocument::Standard, FALSE ) )
888 removeSelectedText(); 967 removeSelectedText();
968 if ( textFormat() == Qt::RichText && ( e->state() & ControlButton ) ) {
969 // Ctrl-Enter inserts a line break in rich text mode
970 insert( QString( QChar( 0x2028) ), TRUE, FALSE, TRUE );
971 } else {
889#ifndef QT_NO_CURSOR 972#ifndef QT_NO_CURSOR
890 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 973 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
891#endif 974#endif
892 clearUndoRedoInfo = FALSE; 975 clearUndoRedoInfo = FALSE;
893 doKeyboardAction( ActionReturn ); 976 doKeyboardAction( ActionReturn );
894 emit returnPressed(); 977 emit returnPressed();
978 }
895 break; 979 break;
896 case Key_Delete: 980 case Key_Delete:
897#if defined (Q_WS_WIN) 981#if defined (Q_WS_WIN)
898 if ( e->state() & ShiftButton ) { 982 if ( e->state() & ShiftButton ) {
899 cut(); 983 cut();
900 break; 984 break;
901 } else 985 } else
902#endif 986#endif
903 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { 987 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) {
904 removeSelectedText(); 988 removeSelectedText();
905 break; 989 break;
906 } 990 }
907 doKeyboardAction( ActionDelete ); 991 doKeyboardAction( ActionDelete );
908 clearUndoRedoInfo = FALSE; 992 clearUndoRedoInfo = FALSE;
909 993
910 break; 994 break;
911 case Key_Insert: 995 case Key_Insert:
912 if ( e->state() & ShiftButton ) 996 if ( e->state() & ShiftButton )
913 paste(); 997 paste();
998#if defined (Q_WS_WIN)
999 else if ( e->state() & ControlButton )
1000 copy();
1001#endif
914 break; 1002 break;
915 case Key_Backspace: 1003 case Key_Backspace:
916 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { 1004 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) {
917 removeSelectedText(); 1005 removeSelectedText();
918 break; 1006 break;
919 } 1007 }
920 1008
921 if ( !cursor->parag()->prev() &&
922 cursor->atParagStart() )
923 break;
924
925 doKeyboardAction( ActionBackspace ); 1009 doKeyboardAction( ActionBackspace );
926 clearUndoRedoInfo = FALSE; 1010 clearUndoRedoInfo = FALSE;
927 1011
928 break; 1012 break;
929 case Key_F16: // Copy key on Sun keyboards 1013 case Key_F16: // Copy key on Sun keyboards
930 copy(); 1014 copy();
931 break; 1015 break;
932 case Key_F18: // Paste key on Sun keyboards 1016 case Key_F18: // Paste key on Sun keyboards
933 paste(); 1017 paste();
934 break; 1018 break;
935 case Key_F20: // Cut key on Sun keyboards 1019 case Key_F20: // Cut key on Sun keyboards
936 cut(); 1020 cut();
937 break; 1021 break;
938 default: { 1022 default: {
939 if ( e->text().length() && 1023 if ( e->text().length() &&
940 ( !( e->state() & ControlButton ) && 1024 ( !( e->state() & ControlButton ) &&
941 !( e->state() & AltButton ) || 1025 !( e->state() & AltButton ) ||
942 ( ( e->state() & ControlButton | AltButton ) == (ControlButton|AltButton) ) ) && 1026 ( ( e->state() & ControlButton | AltButton ) == (ControlButton|AltButton) ) ) &&
943 ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) { 1027 ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) {
944 clearUndoRedoInfo = FALSE; 1028 clearUndoRedoInfo = FALSE;
945 if ( e->key() == Key_Tab ) { 1029 if ( e->key() == Key_Tab ) {
946 if ( textFormat() == Qt::RichText && 1030 if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() ) {
947 cursor->index() == 0 && cursor->parag()->style() && 1031 clearUndoRedo();
948 cursor->parag()->style()->displayMode() == 1032 undoRedoInfo.type = UndoRedoInfo::Style;
949 QStyleSheetItem::DisplayListItem ) { 1033 undoRedoInfo.id = cursor->paragraph()->paragId();
950 cursor->parag()->incDepth(); 1034 undoRedoInfo.eid = undoRedoInfo.id;
1035 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
1036 cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 );
1037 clearUndoRedo();
951 drawCursor( FALSE ); 1038 drawCursor( FALSE );
952 repaintChanged(); 1039 repaintChanged();
953 drawCursor( TRUE ); 1040 drawCursor( TRUE );
954 break; 1041 break;
955 } 1042 }
956 } 1043 }
957 if ( textFormat() == Qt::RichText && ( !cursor->parag()->style() || 1044
958 cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayBlock ) && 1045 if ( textFormat() == Qt::RichText && !cursor->paragraph()->isListItem() ) {
959 cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { 1046 if ( cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) {
1047 clearUndoRedo();
1048 undoRedoInfo.type = UndoRedoInfo::Style;
1049 undoRedoInfo.id = cursor->paragraph()->paragId();
1050 undoRedoInfo.eid = undoRedoInfo.id;
1051 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
960 setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); 1052 setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc );
961 cursor->parag()->incDepth(); 1053 clearUndoRedo();
962 drawCursor( FALSE ); 1054 drawCursor( FALSE );
963 repaintChanged(); 1055 repaintChanged();
964 drawCursor( TRUE ); 1056 drawCursor( TRUE );
965 } else { 1057 break;
1058 }
1059 }
966 if ( overWrite && !cursor->atParagEnd() ) 1060 if ( overWrite && !cursor->atParagEnd() )
967 cursor->remove(); 1061 cursor->remove();
968 QString t = e->text(); 1062 QString t = e->text();
969 QTextParag *p = cursor->parag(); 1063 QTextParagraph *p = cursor->paragraph();
970 if ( p && p->string() && p->string()->isRightToLeft() ) { 1064 if ( p && p->string() && p->string()->isRightToLeft() ) {
971 QChar *c = (QChar *)t.unicode(); 1065 QChar *c = (QChar *)t.unicode();
972 int l = t.length(); 1066 int l = t.length();
973 while( l-- ) { 1067 while( l-- ) {
974 if ( c->mirrored() ) 1068 if ( c->mirrored() )
975 *c = c->mirroredChar(); 1069 *c = c->mirroredChar();
976 c++; 1070 c++;
977 } 1071 }
978 } 1072 }
979 insert( t, TRUE, FALSE, TRUE ); 1073 insert( t, TRUE, FALSE, TRUE );
980 }
981 break; 1074 break;
982 } else if ( e->state() & ControlButton ) { 1075 } else if ( e->state() & ControlButton ) {
983 switch ( e->key() ) { 1076 switch ( e->key() ) {
984 case Key_C: case Key_F16: // Copy key on Sun keyboards 1077 case Key_C: case Key_F16: // Copy key on Sun keyboards
985 copy(); 1078 copy();
986 break; 1079 break;
987 case Key_V: 1080 case Key_V:
988 paste(); 1081 paste();
989 break; 1082 break;
990 case Key_X: 1083 case Key_X:
991 cut(); 1084 cut();
992 break; 1085 break;
993 case Key_I: case Key_T: case Key_Tab: 1086 case Key_I: case Key_T: case Key_Tab:
994 indent(); 1087 indent();
995 break; 1088 break;
996 case Key_A: 1089 case Key_A:
997#if defined(Q_WS_X11) 1090#if defined(Q_WS_X11)
998 moveCursor( MoveLineStart, e->state() & ShiftButton ); 1091 moveCursor( MoveLineStart, e->state() & ShiftButton );
999#else 1092#else
1000 selectAll( TRUE ); 1093 selectAll( TRUE );
1001#endif 1094#endif
1002 break; 1095 break;
1003 case Key_B: 1096 case Key_B:
1004 moveCursor( MoveBackward, e->state() & ShiftButton ); 1097 moveCursor( MoveBackward, e->state() & ShiftButton );
1005 break; 1098 break;
1006 case Key_F: 1099 case Key_F:
1007 moveCursor( MoveForward, e->state() & ShiftButton ); 1100 moveCursor( MoveForward, e->state() & ShiftButton );
1008 break; 1101 break;
1009 case Key_D: 1102 case Key_D:
1010 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1103 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1011 removeSelectedText(); 1104 removeSelectedText();
1012 break; 1105 break;
1013 } 1106 }
1014 doKeyboardAction( ActionDelete ); 1107 doKeyboardAction( ActionDelete );
1015 clearUndoRedoInfo = FALSE; 1108 clearUndoRedoInfo = FALSE;
1016 break; 1109 break;
1017 case Key_H: 1110 case Key_H:
1018 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1111 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1019 removeSelectedText(); 1112 removeSelectedText();
1020 break; 1113 break;
1021 } 1114 }
1022 if ( !cursor->parag()->prev() && 1115 if ( !cursor->paragraph()->prev() &&
1023 cursor->atParagStart() ) 1116 cursor->atParagStart() )
1024 break; 1117 break;
1025 1118
1026 doKeyboardAction( ActionBackspace ); 1119 doKeyboardAction( ActionBackspace );
1027 clearUndoRedoInfo = FALSE; 1120 clearUndoRedoInfo = FALSE;
1028 break; 1121 break;
1029 case Key_E: 1122 case Key_E:
1030 moveCursor( MoveLineEnd, e->state() & ShiftButton ); 1123 moveCursor( MoveLineEnd, e->state() & ShiftButton );
1031 break; 1124 break;
1032 case Key_N: 1125 case Key_N:
1033 moveCursor( MoveDown, e->state() & ShiftButton ); 1126 moveCursor( MoveDown, e->state() & ShiftButton );
1034 break; 1127 break;
1035 case Key_P: 1128 case Key_P:
1036 moveCursor( MoveUp, e->state() & ShiftButton ); 1129 moveCursor( MoveUp, e->state() & ShiftButton );
1037 break; 1130 break;
1038 case Key_Z: 1131 case Key_Z:
1132 if(e->state() & ShiftButton)
1133 redo();
1134 else
1039 undo(); 1135 undo();
1040 break; 1136 break;
1041 case Key_Y: 1137 case Key_Y:
1042 redo(); 1138 redo();
1043 break; 1139 break;
1044 case Key_K: 1140 case Key_K:
1045 doKeyboardAction( ActionKill ); 1141 doKeyboardAction( ActionKill );
1046 break; 1142 break;
1047#if defined(Q_WS_WIN) 1143#if defined(Q_WS_WIN)
1048 case Key_Insert: 1144 case Key_Insert:
1049 copy(); 1145 copy();
1050 break; 1146 break;
1051 case Key_Delete: 1147 case Key_Delete:
1052 del(); 1148 del();
1053 break; 1149 break;
1054#endif 1150#endif
1055 default: 1151 default:
1056 unknown = FALSE; 1152 unknown = FALSE;
1057 break; 1153 break;
1058 } 1154 }
1059 } else { 1155 } else {
1060 unknown = TRUE; 1156 unknown = TRUE;
1061 } 1157 }
1062 } 1158 }
1063 } 1159 }
1064 1160
1065 emit cursorPositionChanged( cursor ); 1161 emit cursorPositionChanged( cursor );
1066 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 1162 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
1067 if ( clearUndoRedoInfo ) 1163 if ( clearUndoRedoInfo )
1068 clearUndoRedo(); 1164 clearUndoRedo();
1069 changeIntervalTimer->start( 100, TRUE ); 1165 changeIntervalTimer->start( 100, TRUE );
1070 if ( unknown ) 1166 if ( unknown )
1071 e->ignore(); 1167 e->ignore();
1072} 1168}
1073 1169
1074/*! 1170/*!
1075 Executes keyboard action \a action. This is normally called by 1171 Executes keyboard action \a action. This is normally called by
1076 a key event handler. 1172 a key event handler.
1077*/ 1173*/
1078 1174
1079void QTextEdit::doKeyboardAction( KeyboardAction action ) 1175void QTextEdit::doKeyboardAction( KeyboardAction action )
1080{ 1176{
1081 if ( isReadOnly() ) 1177 if ( isReadOnly() )
1082 return; 1178 return;
1083 1179
1084 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough 1180 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough
1085 return; 1181 return;
1086 1182
1087 lastFormatted = cursor->parag(); 1183 lastFormatted = cursor->paragraph();
1088 drawCursor( FALSE ); 1184 drawCursor( FALSE );
1089 bool doUpdateCurrentFormat = TRUE; 1185 bool doUpdateCurrentFormat = TRUE;
1090 1186
1091 switch ( action ) { 1187 switch ( action ) {
1092 case ActionDelete: { 1188 case ActionDelete:
1189 if ( !cursor->atParagEnd() ) {
1093 checkUndoRedoInfo( UndoRedoInfo::Delete ); 1190 checkUndoRedoInfo( UndoRedoInfo::Delete );
1094 if ( !undoRedoInfo.valid() ) { 1191 if ( !undoRedoInfo.valid() ) {
1095 undoRedoInfo.id = cursor->parag()->paragId(); 1192 undoRedoInfo.id = cursor->paragraph()->paragId();
1096 undoRedoInfo.index = cursor->index(); 1193 undoRedoInfo.index = cursor->index();
1097 undoRedoInfo.d->text = QString::null; 1194 undoRedoInfo.d->text = QString::null;
1098 } 1195 }
1099 undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; 1196 undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( cursor->index() ), TRUE );
1100 if ( cursor->parag()->at( cursor->index() )->format() ) { 1197 cursor->remove();
1101 cursor->parag()->at( cursor->index() )->format()->addRef(); 1198 } else {
1102 undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); 1199 clearUndoRedo();
1103 } 1200 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1104 QTextParag *old = cursor->parag(); 1201 cursor->gotoNextLetter();
1105 if ( cursor->remove() ) { 1202 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1106 if ( old != cursor->parag() && lastFormatted == old ) 1203 removeSelectedText( QTextDocument::Temp );
1107 lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0;
1108 undoRedoInfo.d->text += "\n";
1109 } 1204 }
1110 } break; 1205 break;
1111 case ActionBackspace: 1206 case ActionBackspace:
1112 if ( textFormat() == Qt::RichText && 1207 if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() && cursor->index() == 0 ) {
1113 cursor->parag()->style() && 1208 clearUndoRedo();
1114 cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayListItem && 1209 undoRedoInfo.type = UndoRedoInfo::Style;
1115 cursor->index() == 0 ) { 1210 undoRedoInfo.id = cursor->paragraph()->paragId();
1116 cursor->parag()->decDepth(); 1211 undoRedoInfo.eid = undoRedoInfo.id;
1117 lastFormatted = cursor->parag(); 1212 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
1213 int ldepth = cursor->paragraph()->listDepth();
1214 ldepth = QMAX( ldepth-1, 0 );
1215 cursor->paragraph()->setListDepth( ldepth );
1216 if ( ldepth == 0 )
1217 cursor->paragraph()->setListItem( FALSE );
1218 clearUndoRedo();
1219 lastFormatted = cursor->paragraph();
1118 repaintChanged(); 1220 repaintChanged();
1119 drawCursor( TRUE ); 1221 drawCursor( TRUE );
1120 return; 1222 return;
1121 } 1223 }
1224 if ( !cursor->atParagStart() ) {
1122 checkUndoRedoInfo( UndoRedoInfo::Delete ); 1225 checkUndoRedoInfo( UndoRedoInfo::Delete );
1123 if ( !undoRedoInfo.valid() ) { 1226 if ( !undoRedoInfo.valid() ) {
1124 undoRedoInfo.id = cursor->parag()->paragId(); 1227 undoRedoInfo.id = cursor->paragraph()->paragId();
1125 undoRedoInfo.index = cursor->index(); 1228 undoRedoInfo.index = cursor->index();
1126 undoRedoInfo.d->text = QString::null; 1229 undoRedoInfo.d->text = QString::null;
1127 } 1230 }
1128 cursor->gotoPreviousLetter(); 1231 cursor->gotoPreviousLetter();
1129 undoRedoInfo.d->text.prepend( QString( cursor->parag()->at( cursor->index() )->c ) ); 1232 undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index() ), TRUE );
1130 if ( cursor->parag()->at( cursor->index() )->format() ) {
1131 cursor->parag()->at( cursor->index() )->format()->addRef();
1132 undoRedoInfo.d->text.at( 0 ).setFormat( cursor->parag()->at( cursor->index() )->format() );
1133 }
1134 undoRedoInfo.index = cursor->index();
1135 if ( cursor->remove() ) {
1136 undoRedoInfo.d->text.remove( 0, 1 );
1137 undoRedoInfo.d->text.prepend( "\n" );
1138 undoRedoInfo.index = cursor->index(); 1233 undoRedoInfo.index = cursor->index();
1139 undoRedoInfo.id = cursor->parag()->paragId(); 1234 cursor->remove();
1235 lastFormatted = cursor->paragraph();
1236 } else if ( cursor->paragraph()->prev() ){
1237 clearUndoRedo();
1238 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1239 cursor->gotoPreviousLetter();
1240 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1241 removeSelectedText( QTextDocument::Temp );
1140 } 1242 }
1141 lastFormatted = cursor->parag();
1142 break; 1243 break;
1143 case ActionReturn: { 1244 case ActionReturn:
1144 checkUndoRedoInfo( UndoRedoInfo::Return ); 1245 checkUndoRedoInfo( UndoRedoInfo::Return );
1145 if ( !undoRedoInfo.valid() ) { 1246 if ( !undoRedoInfo.valid() ) {
1146 undoRedoInfo.id = cursor->parag()->paragId(); 1247 undoRedoInfo.id = cursor->paragraph()->paragId();
1147 undoRedoInfo.index = cursor->index(); 1248 undoRedoInfo.index = cursor->index();
1148 undoRedoInfo.d->text = QString::null; 1249 undoRedoInfo.d->text = QString::null;
1149 } 1250 }
1150 undoRedoInfo.d->text += "\n"; 1251 undoRedoInfo.d->text += "\n";
1151 cursor->splitAndInsertEmptyParag(); 1252 cursor->splitAndInsertEmptyParagraph();
1152 if ( cursor->parag()->prev() ) { 1253 if ( cursor->paragraph()->prev() ) {
1153 lastFormatted = cursor->parag()->prev(); 1254 lastFormatted = cursor->paragraph()->prev();
1154 lastFormatted->invalidate( 0 ); 1255 lastFormatted->invalidate( 0 );
1155 } 1256 }
1156 doUpdateCurrentFormat = FALSE; 1257 doUpdateCurrentFormat = FALSE;
1157 } break; 1258 break;
1158 case ActionKill: 1259 case ActionKill:
1159 checkUndoRedoInfo( UndoRedoInfo::Delete ); 1260 clearUndoRedo();
1160 if ( !undoRedoInfo.valid() ) { 1261 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1161 undoRedoInfo.id = cursor->parag()->paragId(); 1262 if ( cursor->atParagEnd() )
1162 undoRedoInfo.index = cursor->index(); 1263 cursor->gotoNextLetter();
1163 undoRedoInfo.d->text = QString::null; 1264 else
1164 } 1265 cursor->setIndex( cursor->paragraph()->length() - 1 );
1165 if ( cursor->atParagEnd() ) { 1266 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1166 undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; 1267 removeSelectedText( QTextDocument::Temp );
1167 if ( cursor->parag()->at( cursor->index() )->format() ) {
1168 cursor->parag()->at( cursor->index() )->format()->addRef();
1169 undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() );
1170 }
1171 QTextParag *old = cursor->parag();
1172 if ( cursor->remove() ) {
1173 if ( old != cursor->parag() && lastFormatted == old )
1174 lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0;
1175 undoRedoInfo.d->text += "\n";
1176 }
1177 } else {
1178 int oldLen = undoRedoInfo.d->text.length();
1179 undoRedoInfo.d->text += cursor->parag()->string()->toString().mid( cursor->index() );
1180 for ( int i = cursor->index(); i < cursor->parag()->length(); ++i ) {
1181 if ( cursor->parag()->at( i )->format() ) {
1182 cursor->parag()->at( i )->format()->addRef();
1183 undoRedoInfo.d->text.at( oldLen + i - cursor->index() ).setFormat( cursor->parag()->at( i )->format() );
1184 }
1185 }
1186 undoRedoInfo.d->text.remove( undoRedoInfo.d->text.length() - 1, 1 );
1187 cursor->killLine();
1188 }
1189 break; 1268 break;
1190 } 1269 }
1191 1270
1192 formatMore(); 1271 formatMore();
1193 repaintChanged(); 1272 repaintChanged();
1194 ensureCursorVisible(); 1273 ensureCursorVisible();
1195 drawCursor( TRUE ); 1274 drawCursor( TRUE );
1196 1275 updateMicroFocusHint();
1197 if ( hasFocus() || viewport()->hasFocus() ) {
1198 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1199 if ( !readonly ) {
1200 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1201 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1202 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1203 }
1204 }
1205
1206 if ( doUpdateCurrentFormat ) 1276 if ( doUpdateCurrentFormat )
1207 updateCurrentFormat(); 1277 updateCurrentFormat();
1208 setModified(); 1278 setModified();
1209 emit textChanged(); 1279 emit textChanged();
1210} 1280}
1211 1281
1212void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, int oldLen, QTextString &text, bool fillStyles ) 1282void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles )
1213{ 1283{
1284 QDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly );
1214 c2.restoreState(); 1285 c2.restoreState();
1215 c1.restoreState(); 1286 c1.restoreState();
1216 if ( c1.parag() == c2.parag() ) { 1287 int lastIndex = text.length();
1217 for ( int i = c1.index(); i < c2.index(); ++i ) { 1288 if ( c1.paragraph() == c2.paragraph() ) {
1218 if ( c1.parag()->at( i )->format() ) { 1289 for ( int i = c1.index(); i < c2.index(); ++i )
1219 c1.parag()->at( i )->format()->addRef(); 1290 text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE );
1220 text.at( oldLen + i - c1.index() ).setFormat( c1.parag()->at( i )->format() );
1221 }
1222 }
1223 if ( fillStyles ) { 1291 if ( fillStyles ) {
1224 undoRedoInfo.oldAligns[ 0 ] = c1.parag()->alignment(); 1292 styleStream << (int) 1;
1225 undoRedoInfo.oldStyles << c1.parag()->styleSheetItems(); 1293 c1.paragraph()->writeStyleInformation( styleStream );
1226 undoRedoInfo.oldListStyles << c1.parag()->listStyle();
1227 } 1294 }
1228 } else { 1295 } else {
1229 int lastIndex = oldLen;
1230 int i; 1296 int i;
1231 for ( i = c1.index(); i < c1.parag()->length(); ++i ) { 1297 for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i )
1232 if ( c1.parag()->at( i )->format() ) { 1298 text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE );
1233 c1.parag()->at( i )->format()->addRef(); 1299 int num = 2; // start and end, being different
1234 text.at( lastIndex ).setFormat( c1.parag()->at( i )->format() ); 1300 text += "\n"; lastIndex++;
1235 lastIndex++; 1301 QTextParagraph *p = c1.paragraph()->next();
1236 } 1302 while ( p && p != c2.paragraph() ) {
1237 } 1303 for ( i = 0; i < p->length()-1; ++i )
1238 QTextParag *p = c1.parag()->next(); 1304 text.insert( lastIndex++ , p->at( i ), TRUE );
1239 while ( p && p != c2.parag() ) { 1305 text += "\n"; num++; lastIndex++;
1240 for ( int i = 0; i < p->length(); ++i ) {
1241 if ( p->at( i )->format() ) {
1242 p->at( i )->format()->addRef();
1243 text.at( i + lastIndex ).setFormat( p->at( i )->format() );
1244 }
1245 }
1246 lastIndex += p->length();
1247 p = p->next(); 1306 p = p->next();
1248 } 1307 }
1249 for ( i = 0; i < c2.index(); ++i ) { 1308 for ( i = 0; i < c2.index(); ++i )
1250 if ( c2.parag()->at( i )->format() ) { 1309 text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE );
1251 c2.parag()->at( i )->format()->addRef();
1252 text.at( i + lastIndex ).setFormat( c2.parag()->at( i )->format() );
1253 }
1254 }
1255 if ( fillStyles ) { 1310 if ( fillStyles ) {
1256 QTextParag *p = c1.parag(); 1311 styleStream << num;
1257 i = 0; 1312 for ( QTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() )
1258 while ( p ) { 1313 p->writeStyleInformation( styleStream );
1259 if ( i < (int)undoRedoInfo.oldAligns.size() )
1260 undoRedoInfo.oldAligns[ i ] = p->alignment();
1261 undoRedoInfo.oldStyles << p->styleSheetItems();
1262 undoRedoInfo.oldListStyles << p->listStyle();
1263 if ( p == c2.parag() )
1264 break;
1265 p = p->next();
1266 ++i;
1267 }
1268 } 1314 }
1269 } 1315 }
1270} 1316}
1271 1317
1272/*! Removes the selection \a selNum (by default 0). This does not 1318/*! Removes the selection \a selNum (by default 0). This does not
1273 remove the selected text. 1319 remove the selected text.
1274 1320
1275 \sa removeSelectedText() 1321 \sa removeSelectedText()
1276*/ 1322*/
1277 1323
1278void QTextEdit::removeSelection( int selNum ) 1324void QTextEdit::removeSelection( int selNum )
1279{ 1325{
1280 doc->removeSelection( selNum ); 1326 doc->removeSelection( selNum );
1281 repaintChanged(); 1327 repaintChanged();
1282} 1328}
1283 1329
1284/*! Deletes the selected text (i.e. the default selection's text) of 1330/*! Deletes the selected text (i.e. the default selection's text) of
1285 the selection \a selNum (by default, 0). If there is no selected text 1331 the selection \a selNum (by default, 0). If there is no selected text
1286 nothing happens. 1332 nothing happens.
1287 1333
1288 \sa selectedText removeSelection() 1334 \sa selectedText removeSelection()
1289*/ 1335*/
1290 1336
1291void QTextEdit::removeSelectedText( int selNum ) 1337void QTextEdit::removeSelectedText( int selNum )
1292{ 1338{
1293 if ( isReadOnly() ) 1339 if ( isReadOnly() )
1294 return; 1340 return;
1295 1341
1296 QTextCursor c1 = doc->selectionStartCursor( selNum ); 1342 QTextCursor c1 = doc->selectionStartCursor( selNum );
1343 c1.restoreState();
1297 QTextCursor c2 = doc->selectionEndCursor( selNum ); 1344 QTextCursor c2 = doc->selectionEndCursor( selNum );
1345 c2.restoreState();
1298 1346
1299 // ### no support for editing tables yet 1347 // ### no support for editing tables yet, plus security for broken selections
1300 if ( c1.nestedDepth() || c2.nestedDepth() ) 1348 if ( c1.nestedDepth() || c2.nestedDepth() )
1301 return; 1349 return;
1302 1350
1303 for ( int i = 0; i < (int)doc->numSelections(); ++i ) { 1351 for ( int i = 0; i < (int)doc->numSelections(); ++i ) {
1304 if ( i == selNum ) 1352 if ( i == selNum )
1305 continue; 1353 continue;
1306 doc->removeSelection( i ); 1354 doc->removeSelection( i );
1307 } 1355 }
1308 1356
1309 drawCursor( FALSE ); 1357 drawCursor( FALSE );
1310 checkUndoRedoInfo( UndoRedoInfo::RemoveSelected ); 1358 checkUndoRedoInfo( UndoRedoInfo::RemoveSelected );
1311 if ( !undoRedoInfo.valid() ) { 1359 if ( !undoRedoInfo.valid() ) {
1312 doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index ); 1360 doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index );
1313 undoRedoInfo.d->text = QString::null; 1361 undoRedoInfo.d->text = QString::null;
1314 } 1362 }
1315 int oldLen = undoRedoInfo.d->text.length(); 1363 readFormats( c1, c2, undoRedoInfo.d->text, TRUE );
1316 undoRedoInfo.d->text = doc->selectedText( selNum, FALSE ); 1364
1317 undoRedoInfo.oldAligns.resize( undoRedoInfo.oldAligns.size() + QMAX( 0, c2.parag()->paragId() - c1.parag()->paragId() + 1 ) ); 1365
1318 readFormats( c1, c2, oldLen, undoRedoInfo.d->text, TRUE );
1319 doc->removeSelectedText( selNum, cursor ); 1366 doc->removeSelectedText( selNum, cursor );
1320 if ( cursor->isValid() ) { 1367 if ( cursor->isValid() ) {
1321 ensureCursorVisible(); 1368 ensureCursorVisible();
1322 lastFormatted = cursor->parag(); 1369 lastFormatted = cursor->paragraph();
1323 formatMore(); 1370 formatMore();
1324 repaintChanged(); 1371 repaintChanged();
1325 ensureCursorVisible(); 1372 ensureCursorVisible();
1326 drawCursor( TRUE ); 1373 drawCursor( TRUE );
1327 clearUndoRedo(); 1374 clearUndoRedo();
1328#if defined(Q_WS_WIN) 1375#if defined(Q_WS_WIN)
1329 // there seems to be a problem with repainting or erasing the area 1376 // there seems to be a problem with repainting or erasing the area
1330 // of the scrollview which is not the contents on windows 1377 // of the scrollview which is not the contents on windows
1331 if ( contentsHeight() < visibleHeight() ) 1378 if ( contentsHeight() < visibleHeight() )
1332 viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE ); 1379 viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE );
1333#endif 1380#endif
1334#ifndef QT_NO_CURSOR 1381#ifndef QT_NO_CURSOR
1335 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1382 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1336#endif 1383#endif
1337 if ( hasFocus() || viewport()->hasFocus() ) { 1384 updateMicroFocusHint();
1338 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1339 if ( !readonly ) {
1340 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1341 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1342 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1343 }
1344 }
1345 } else { 1385 } else {
1346 cursor->setDocument( doc ); 1386 delete cursor;
1347 cursor->setParag( doc->firstParag() ); 1387 cursor = new QTextCursor( doc );
1348 cursor->setIndex( 0 );
1349 drawCursor( TRUE ); 1388 drawCursor( TRUE );
1350 viewport()->repaint( TRUE ); 1389 viewport()->repaint( TRUE );
1351 } 1390 }
1352 setModified(); 1391 setModified();
1353 emit textChanged(); 1392 emit textChanged();
1354 emit selectionChanged(); 1393 emit selectionChanged();
1355} 1394}
1356 1395
1357/*! Moves the text cursor according to \a action. This is normally 1396/*! Moves the text cursor according to \a action. This is normally
1358 used by some key event handler. \a select specifies whether the text 1397 used by some key event handler. \a select specifies whether the text
1359 between the current cursor position and the new position should be 1398 between the current cursor position and the new position should be
1360 selected. 1399 selected.
1361*/ 1400*/
1362 1401
1363void QTextEdit::moveCursor( CursorAction action, bool select ) 1402void QTextEdit::moveCursor( CursorAction action, bool select )
1364{ 1403{
1365 drawCursor( FALSE ); 1404 drawCursor( FALSE );
1366 if ( select ) { 1405 if ( select ) {
1367 if ( !doc->hasSelection( QTextDocument::Standard ) ) 1406 if ( !doc->hasSelection( QTextDocument::Standard ) )
1368 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1407 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1369 moveCursor( action ); 1408 moveCursor( action );
1370 if ( doc->setSelectionEnd( QTextDocument::Standard, cursor ) ) { 1409 if ( doc->setSelectionEnd( QTextDocument::Standard, *cursor ) ) {
1371 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1410 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1372 repaintChanged(); 1411 repaintChanged();
1373 } else { 1412 } else {
1374 drawCursor( TRUE ); 1413 drawCursor( TRUE );
1375 } 1414 }
1376 ensureCursorVisible(); 1415 ensureCursorVisible();
1377 emit selectionChanged(); 1416 emit selectionChanged();
1378 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); 1417 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
1379 } else { 1418 } else {
1380 bool redraw = doc->removeSelection( QTextDocument::Standard ); 1419 bool redraw = doc->removeSelection( QTextDocument::Standard );
1381 moveCursor( action ); 1420 moveCursor( action );
1382 if ( !redraw ) { 1421 if ( !redraw ) {
1383 ensureCursorVisible(); 1422 ensureCursorVisible();
1384 drawCursor( TRUE ); 1423 drawCursor( TRUE );
1385 } else { 1424 } else {
1386 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1425 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1387 repaintChanged(); 1426 repaintChanged();
1388 ensureCursorVisible(); 1427 ensureCursorVisible();
1389 drawCursor( TRUE ); 1428 drawCursor( TRUE );
1390#ifndef QT_NO_CURSOR 1429#ifndef QT_NO_CURSOR
1391 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1430 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1392#endif 1431#endif
1393 } 1432 }
1394 if ( redraw ) { 1433 if ( redraw ) {
1395 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); 1434 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
1396 emit selectionChanged(); 1435 emit selectionChanged();
1397 } 1436 }
1398 } 1437 }
1399 1438
1400 drawCursor( TRUE ); 1439 drawCursor( TRUE );
1401 updateCurrentFormat(); 1440 updateCurrentFormat();
1402 if ( hasFocus() || viewport()->hasFocus() ) { 1441 updateMicroFocusHint();
1403 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1404 if ( !readonly ) {
1405 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1406 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1407 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1408 }
1409 }
1410} 1442}
1411 1443
1412/*! \overload 1444/*! \overload
1413*/ 1445*/
1414 1446
1415void QTextEdit::moveCursor( CursorAction action ) 1447void QTextEdit::moveCursor( CursorAction action )
1416{ 1448{
1417 switch ( action ) { 1449 switch ( action ) {
1418 case MoveBackward: 1450 case MoveBackward:
1419 cursor->gotoPreviousLetter(); 1451 cursor->gotoPreviousLetter();
1420 break; 1452 break;
1421 case MoveWordBackward: 1453 case MoveWordBackward:
1422 cursor->gotoPreviousWord(); 1454 cursor->gotoPreviousWord();
1423 break; 1455 break;
1424 case MoveForward: 1456 case MoveForward:
1425 cursor->gotoNextLetter(); 1457 cursor->gotoNextLetter();
1426 break; 1458 break;
1427 case MoveWordForward: 1459 case MoveWordForward:
1428 cursor->gotoNextWord(); 1460 cursor->gotoNextWord();
1429 break; 1461 break;
1430 case MoveUp: 1462 case MoveUp:
1431 cursor->gotoUp(); 1463 cursor->gotoUp();
1432 break; 1464 break;
1433 case MovePgUp: 1465 case MovePgUp:
1434 cursor->gotoPageUp( visibleHeight() ); 1466 cursor->gotoPageUp( visibleHeight() );
1435 break; 1467 break;
1436 case MoveDown: 1468 case MoveDown:
1437 cursor->gotoDown(); 1469 cursor->gotoDown();
1438 break; 1470 break;
1439 case MovePgDown: 1471 case MovePgDown:
1440 cursor->gotoPageDown( visibleHeight() ); 1472 cursor->gotoPageDown( visibleHeight() );
1441 break; 1473 break;
1442 case MoveLineStart: 1474 case MoveLineStart:
1443 cursor->gotoLineStart(); 1475 cursor->gotoLineStart();
1444 break; 1476 break;
1445 case MoveHome: 1477 case MoveHome:
1446 cursor->gotoHome(); 1478 cursor->gotoHome();
1447 break; 1479 break;
1448 case MoveLineEnd: 1480 case MoveLineEnd:
1449 cursor->gotoLineEnd(); 1481 cursor->gotoLineEnd();
1450 break; 1482 break;
1451 case MoveEnd: 1483 case MoveEnd:
1452 ensureFormatted( doc->lastParag() ); 1484 ensureFormatted( doc->lastParagraph() );
1453 cursor->gotoEnd(); 1485 cursor->gotoEnd();
1454 break; 1486 break;
1455 } 1487 }
1456 1488 updateMicroFocusHint();
1457 if ( hasFocus() || viewport()->hasFocus() ) {
1458 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1459 if ( !readonly ) {
1460 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1461 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1462 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1463 }
1464 }
1465 updateCurrentFormat(); 1489 updateCurrentFormat();
1466} 1490}
1467 1491
1468/*! \reimp */ 1492/*! \reimp */
1469 1493
1470void QTextEdit::resizeEvent( QResizeEvent *e ) 1494void QTextEdit::resizeEvent( QResizeEvent *e )
1471{ 1495{
1472 QScrollView::resizeEvent( e ); 1496 QScrollView::resizeEvent( e );
1497 if ( doc->visibleWidth() == 0 )
1498 doResize();
1473} 1499}
1474 1500
1475/*! \reimp */ 1501/*! \reimp */
1476 1502
1477void QTextEdit::viewportResizeEvent( QResizeEvent *e ) 1503void QTextEdit::viewportResizeEvent( QResizeEvent *e )
1478{ 1504{
1479 QScrollView::viewportResizeEvent( e ); 1505 QScrollView::viewportResizeEvent( e );
1480 if ( e->oldSize().width() != e->size().width() ) 1506 if ( e->oldSize().width() != e->size().width() ) {
1507 bool stayAtBottom = e->oldSize().height() != e->size().height() &&
1508 contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height();
1481 doResize(); 1509 doResize();
1510 if ( stayAtBottom )
1511 scrollToBottom();
1512 }
1482} 1513}
1483
1484static bool blockEnsureCursorVisible = FALSE;
1485 1514
1486/*! 1515/*!
1487 Ensures that the cursor is visible by scrolling the text edit if 1516 Ensures that the cursor is visible by scrolling the text edit if
1488 necessary. 1517 necessary.
1489 1518
1490 \sa setCursorPosition() 1519 \sa setCursorPosition()
1491*/ 1520*/
1492 1521
1493void QTextEdit::ensureCursorVisible() 1522void QTextEdit::ensureCursorVisible()
1494{ 1523{
1495 if ( blockEnsureCursorVisible )
1496 return;
1497 if ( !isVisible() ) { 1524 if ( !isVisible() ) {
1498 d->ensureCursorVisibleInShowEvent = TRUE; 1525 d->ensureCursorVisibleInShowEvent = TRUE;
1499 return; 1526 return;
1500 } 1527 }
1501 lastFormatted = cursor->parag(); 1528 lastFormatted = cursor->paragraph();
1502 formatMore(); 1529 formatMore();
1503 QTextStringChar *chr = cursor->parag()->at( cursor->index() ); 1530 QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
1504 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 1531 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
1505 int x = cursor->parag()->rect().x() + chr->x + cursor->offsetX(); 1532 int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX();
1506 int y = 0; int dummy; 1533 int y = 0; int dummy;
1507 cursor->parag()->lineHeightOfChar( cursor->index(), &dummy, &y ); 1534 cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
1508 y += cursor->parag()->rect().y() + cursor->offsetY(); 1535 y += cursor->paragraph()->rect().y() + cursor->offsetY();
1509 int w = 1; 1536 int w = 1;
1510 ensureVisible( x, y + h / 2, w, h / 2 + 2 ); 1537 ensureVisible( x, y + h / 2, w, h / 2 + 2 );
1511} 1538}
1512 1539
1513/*! 1540/*!
1514 \internal 1541 \internal
1515*/ 1542*/
1516void QTextEdit::drawCursor( bool visible ) 1543void QTextEdit::drawCursor( bool visible )
1517{ 1544{
1518 if ( !isUpdatesEnabled() || 1545 if ( !isUpdatesEnabled() ||
1519 !viewport()->isUpdatesEnabled() || 1546 !viewport()->isUpdatesEnabled() ||
1520 !cursor->parag() || 1547 !cursor->paragraph() ||
1521 !cursor->parag()->isValid() || 1548 !cursor->paragraph()->isValid() ||
1522 !selectedText().isEmpty() || 1549 !selectedText().isEmpty() ||
1523 ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) || 1550 ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) ||
1524 isReadOnly() ) 1551 isReadOnly() )
1525 return; 1552 return;
1526 1553
1527 QPainter p( viewport() ); 1554 QPainter p( viewport() );
1528 QRect r( cursor->topParag()->rect() ); 1555 QRect r( cursor->topParagraph()->rect() );
1529 cursor->parag()->setChanged( TRUE ); 1556 cursor->paragraph()->setChanged( TRUE );
1530 p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); 1557 p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() );
1531 QPixmap *pix = 0; 1558 QPixmap *pix = 0;
1532 QColorGroup cg( colorGroup() ); 1559 QColorGroup cg( colorGroup() );
1533 if ( cursor->parag()->background() ) 1560 if ( cursor->paragraph()->background() )
1534 cg.setBrush( QColorGroup::Base, *cursor->parag()->background() ); 1561 cg.setBrush( QColorGroup::Base, *cursor->paragraph()->background() );
1535 else if ( doc->paper() ) 1562 else if ( doc->paper() )
1536 cg.setBrush( QColorGroup::Base, *doc->paper() ); 1563 cg.setBrush( QColorGroup::Base, *doc->paper() );
1537 p.setBrushOrigin( -contentsX(), -contentsY() ); 1564 p.setBrushOrigin( -contentsX(), -contentsY() );
1538 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1565 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1539 if ( !cursor->nestedDepth() ) { 1566 if ( !cursor->nestedDepth() ) {
1540 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 1567 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
1541 int dist = 5; 1568 int dist = 5;
1542 if ( ( cursor->parag()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) 1569 if ( ( cursor->paragraph()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify )
1543 dist = 50; 1570 dist = 50;
1544 int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist; 1571 int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist;
1545 x = QMAX( x, 0 ); 1572 x = QMAX( x, 0 );
1546 p.setClipRect( QRect( x - contentsX(), 1573 p.setClipRect( QRect( x - contentsX(),
1547 r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); 1574 r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) );
1548 doc->drawParag( &p, cursor->parag(), x, 1575 doc->drawParagraph( &p, cursor->paragraph(), x,
1549 r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); 1576 r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor );
1550 } else { 1577 } else {
1551 doc->drawParag( &p, cursor->parag(), r.x() - cursor->totalOffsetX(), 1578 doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(),
1552 r.y() - cursor->totalOffsetY(), r.width(), r.height(), 1579 r.y() - cursor->totalOffsetY(), r.width(), r.height(),
1553 pix, cg, visible, cursor ); 1580 pix, cg, visible, cursor );
1554 } 1581 }
1555 cursorVisible = visible; 1582 cursorVisible = visible;
1556} 1583}
1557 1584
1558enum { 1585enum {
1559 IdUndo = 0, 1586 IdUndo = 0,
1560 IdRedo = 1, 1587 IdRedo = 1,
1561 IdCut = 2, 1588 IdCut = 2,
1562 IdCopy = 3, 1589 IdCopy = 3,
1563 IdPaste = 4, 1590 IdPaste = 4,
1564 IdClear = 5, 1591 IdClear = 5,
1565 IdSelectAll = 6 1592 IdSelectAll = 6
1566}; 1593};
1567 1594
1568/*! \reimp */ 1595/*! \reimp */
1569#ifndef QT_NO_WHEELEVENT 1596#ifndef QT_NO_WHEELEVENT
1570void QTextEdit::contentsWheelEvent( QWheelEvent *e ) 1597void QTextEdit::contentsWheelEvent( QWheelEvent *e )
1571{ 1598{
1572 if ( isReadOnly() ) { 1599 if ( isReadOnly() ) {
1573 if ( e->state() & ControlButton ) { 1600 if ( e->state() & ControlButton ) {
1574 if ( e->delta() > 0 ) 1601 if ( e->delta() > 0 )
1575 zoomOut(); 1602 zoomOut();
@@ -1581,78 +1608,78 @@ void QTextEdit::contentsWheelEvent( QWheelEvent *e )
1581 QScrollView::contentsWheelEvent( e ); 1608 QScrollView::contentsWheelEvent( e );
1582} 1609}
1583#endif 1610#endif
1584 1611
1585/*! \reimp */ 1612/*! \reimp */
1586 1613
1587void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) 1614void QTextEdit::contentsMousePressEvent( QMouseEvent *e )
1588{ 1615{
1589 clearUndoRedo(); 1616 clearUndoRedo();
1590 QTextCursor oldCursor = *cursor; 1617 QTextCursor oldCursor = *cursor;
1591 QTextCursor c = *cursor; 1618 QTextCursor c = *cursor;
1592 mousePos = e->pos(); 1619 mousePos = e->pos();
1593 mightStartDrag = FALSE; 1620 mightStartDrag = FALSE;
1594 pressedLink = QString::null; 1621 pressedLink = QString::null;
1595 1622
1596 if ( e->button() == LeftButton ) { 1623 if ( e->button() == LeftButton ) {
1597 mousePressed = TRUE; 1624 mousePressed = TRUE;
1598 drawCursor( FALSE ); 1625 drawCursor( FALSE );
1599 placeCursor( e->pos() ); 1626 placeCursor( e->pos() );
1600 ensureCursorVisible(); 1627 ensureCursorVisible();
1601 1628
1602 if ( isReadOnly() && linksEnabled() ) { 1629 if ( isReadOnly() && linksEnabled() ) {
1603 QTextCursor c = *cursor; 1630 QTextCursor c = *cursor;
1604 placeCursor( e->pos(), &c, TRUE ); 1631 placeCursor( e->pos(), &c, TRUE );
1605 if ( c.parag() && c.parag()->at( c.index() ) && 1632 if ( c.paragraph() && c.paragraph()->at( c.index() ) &&
1606 c.parag()->at( c.index() )->isAnchor() ) { 1633 c.paragraph()->at( c.index() )->isAnchor() ) {
1607 pressedLink = c.parag()->at( c.index() )->anchorHref(); 1634 pressedLink = c.paragraph()->at( c.index() )->anchorHref();
1608 } 1635 }
1609 } 1636 }
1610 1637
1611#ifndef QT_NO_DRAGANDDROP 1638#ifndef QT_NO_DRAGANDDROP
1612 if ( doc->inSelection( QTextDocument::Standard, e->pos() ) ) { 1639 if ( doc->inSelection( QTextDocument::Standard, e->pos() ) ) {
1613 mightStartDrag = TRUE; 1640 mightStartDrag = TRUE;
1614 drawCursor( TRUE ); 1641 drawCursor( TRUE );
1615 dragStartTimer->start( QApplication::startDragTime(), TRUE ); 1642 dragStartTimer->start( QApplication::startDragTime(), TRUE );
1616 dragStartPos = e->pos(); 1643 dragStartPos = e->pos();
1617 return; 1644 return;
1618 } 1645 }
1619#endif 1646#endif
1620 1647
1621 bool redraw = FALSE; 1648 bool redraw = FALSE;
1622 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1649 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1623 if ( !( e->state() & ShiftButton ) ) { 1650 if ( !( e->state() & ShiftButton ) ) {
1624 redraw = doc->removeSelection( QTextDocument::Standard ); 1651 redraw = doc->removeSelection( QTextDocument::Standard );
1625 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1652 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1626 } else { 1653 } else {
1627 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1654 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1628 } 1655 }
1629 } else { 1656 } else {
1630 if ( isReadOnly() || !( e->state() & ShiftButton ) ) { 1657 if ( isReadOnly() || !( e->state() & ShiftButton ) ) {
1631 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1658 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1632 } else { 1659 } else {
1633 doc->setSelectionStart( QTextDocument::Standard, &c ); 1660 doc->setSelectionStart( QTextDocument::Standard, c );
1634 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1661 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1635 } 1662 }
1636 } 1663 }
1637 1664
1638 for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection 1665 for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection
1639 redraw = doc->removeSelection( i ) || redraw; 1666 redraw = doc->removeSelection( i ) || redraw;
1640 1667
1641 if ( !redraw ) { 1668 if ( !redraw ) {
1642 drawCursor( TRUE ); 1669 drawCursor( TRUE );
1643 } else { 1670 } else {
1644 repaintChanged(); 1671 repaintChanged();
1645#ifndef QT_NO_CURSOR 1672#ifndef QT_NO_CURSOR
1646 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1673 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1647#endif 1674#endif
1648 } 1675 }
1649 } else if ( e->button() == MidButton ) { 1676 } else if ( e->button() == MidButton ) {
1650 bool redraw = doc->removeSelection( QTextDocument::Standard ); 1677 bool redraw = doc->removeSelection( QTextDocument::Standard );
1651 if ( !redraw ) { 1678 if ( !redraw ) {
1652 drawCursor( TRUE ); 1679 drawCursor( TRUE );
1653 } else { 1680 } else {
1654 repaintChanged(); 1681 repaintChanged();
1655#ifndef QT_NO_CURSOR 1682#ifndef QT_NO_CURSOR
1656 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1683 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1657#endif 1684#endif
1658 } 1685 }
@@ -1693,85 +1720,85 @@ void QTextEdit::contentsMouseMoveEvent( QMouseEvent *e )
1693 } 1720 }
1694#endif 1721#endif
1695 updateCursor( e->pos() ); 1722 updateCursor( e->pos() );
1696} 1723}
1697 1724
1698/*! \reimp */ 1725/*! \reimp */
1699 1726
1700void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e ) 1727void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e )
1701{ 1728{
1702 QTextCursor oldCursor = *cursor; 1729 QTextCursor oldCursor = *cursor;
1703 if ( scrollTimer->isActive() ) 1730 if ( scrollTimer->isActive() )
1704 scrollTimer->stop(); 1731 scrollTimer->stop();
1705#ifndef QT_NO_DRAGANDDROP 1732#ifndef QT_NO_DRAGANDDROP
1706 if ( dragStartTimer->isActive() ) 1733 if ( dragStartTimer->isActive() )
1707 dragStartTimer->stop(); 1734 dragStartTimer->stop();
1708 if ( mightStartDrag ) { 1735 if ( mightStartDrag ) {
1709 selectAll( FALSE ); 1736 selectAll( FALSE );
1710 mousePressed = FALSE; 1737 mousePressed = FALSE;
1711 } 1738 }
1712#endif 1739#endif
1713 if ( mousePressed ) { 1740 if ( mousePressed ) {
1714 mousePressed = FALSE; 1741 mousePressed = FALSE;
1715 } 1742 }
1716 emit cursorPositionChanged( cursor ); 1743 emit cursorPositionChanged( cursor );
1717 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 1744 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
1718 if ( oldCursor != *cursor ) 1745 if ( oldCursor != *cursor )
1719 updateCurrentFormat(); 1746 updateCurrentFormat();
1720 inDoubleClick = FALSE; 1747 inDoubleClick = FALSE;
1721 1748
1722#ifndef QT_NO_NETWORKPROTOCOL 1749#ifndef QT_NO_NETWORKPROTOCOL
1723 if ( !onLink.isEmpty() && onLink == pressedLink && linksEnabled() ) { 1750 if ( !onLink.isEmpty() && onLink == pressedLink && linksEnabled() ) {
1724 QUrl u( doc->context(), onLink, TRUE ); 1751 QUrl u( doc->context(), onLink, TRUE );
1725 emitLinkClicked( u.toString( FALSE, FALSE ) ); 1752 emitLinkClicked( u.toString( FALSE, FALSE ) );
1726 1753
1727 // emitting linkClicked() may result in that the cursor winds 1754 // emitting linkClicked() may result in that the cursor winds
1728 // up hovering over a different valid link - check this and 1755 // up hovering over a different valid link - check this and
1729 // set the appropriate cursor shape 1756 // set the appropriate cursor shape
1730 updateCursor( e->pos() ); 1757 updateCursor( e->pos() );
1731 } 1758 }
1732#endif 1759#endif
1733 drawCursor( TRUE ); 1760 drawCursor( TRUE );
1734 if ( !doc->hasSelection( QTextDocument::Standard, TRUE ) ) 1761 if ( !doc->hasSelection( QTextDocument::Standard, TRUE ) )
1735 doc->removeSelection( QTextDocument::Standard ); 1762 doc->removeSelection( QTextDocument::Standard );
1736 1763
1737 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); 1764 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
1738 emit selectionChanged(); 1765 emit selectionChanged();
1739} 1766}
1740 1767
1741/*! \reimp */ 1768/*! \reimp */
1742 1769
1743void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * ) 1770void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * )
1744{ 1771{
1745 QTextCursor c1 = *cursor; 1772 QTextCursor c1 = *cursor;
1746 QTextCursor c2 = *cursor; 1773 QTextCursor c2 = *cursor;
1747 if ( cursor->index() > 0 && !cursor->parag()->at( cursor->index()-1 )->c.isSpace() ) 1774 if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() )
1748 c1.gotoPreviousWord(); 1775 c1.gotoPreviousWord();
1749 if ( !cursor->parag()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) 1776 if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() )
1750 c2.gotoNextWord(); 1777 c2.gotoNextWord();
1751 1778
1752 doc->setSelectionStart( QTextDocument::Standard, &c1 ); 1779 doc->setSelectionStart( QTextDocument::Standard, c1 );
1753 doc->setSelectionEnd( QTextDocument::Standard, &c2 ); 1780 doc->setSelectionEnd( QTextDocument::Standard, c2 );
1754 1781
1755 *cursor = c2; 1782 *cursor = c2;
1756 1783
1757 repaintChanged(); 1784 repaintChanged();
1758 1785
1759 inDoubleClick = TRUE; 1786 inDoubleClick = TRUE;
1760 mousePressed = TRUE; 1787 mousePressed = TRUE;
1761} 1788}
1762 1789
1763#ifndef QT_NO_DRAGANDDROP 1790#ifndef QT_NO_DRAGANDDROP
1764 1791
1765/*! \reimp */ 1792/*! \reimp */
1766 1793
1767void QTextEdit::contentsDragEnterEvent( QDragEnterEvent *e ) 1794void QTextEdit::contentsDragEnterEvent( QDragEnterEvent *e )
1768{ 1795{
1769 if ( isReadOnly() || !QTextDrag::canDecode( e ) ) { 1796 if ( isReadOnly() || !QTextDrag::canDecode( e ) ) {
1770 e->ignore(); 1797 e->ignore();
1771 return; 1798 return;
1772 } 1799 }
1773 e->acceptAction(); 1800 e->acceptAction();
1774 inDnD = TRUE; 1801 inDnD = TRUE;
1775} 1802}
1776 1803
1777/*! \reimp */ 1804/*! \reimp */
@@ -1785,602 +1812,613 @@ void QTextEdit::contentsDragMoveEvent( QDragMoveEvent *e )
1785 drawCursor( FALSE ); 1812 drawCursor( FALSE );
1786 placeCursor( e->pos(), cursor ); 1813 placeCursor( e->pos(), cursor );
1787 drawCursor( TRUE ); 1814 drawCursor( TRUE );
1788 e->acceptAction(); 1815 e->acceptAction();
1789} 1816}
1790 1817
1791/*! \reimp */ 1818/*! \reimp */
1792 1819
1793void QTextEdit::contentsDragLeaveEvent( QDragLeaveEvent * ) 1820void QTextEdit::contentsDragLeaveEvent( QDragLeaveEvent * )
1794{ 1821{
1795 inDnD = FALSE; 1822 inDnD = FALSE;
1796} 1823}
1797 1824
1798/*! \reimp */ 1825/*! \reimp */
1799 1826
1800void QTextEdit::contentsDropEvent( QDropEvent *e ) 1827void QTextEdit::contentsDropEvent( QDropEvent *e )
1801{ 1828{
1802 if ( isReadOnly() ) 1829 if ( isReadOnly() )
1803 return; 1830 return;
1804 inDnD = FALSE; 1831 inDnD = FALSE;
1805 e->acceptAction(); 1832 e->acceptAction();
1806 QString text; 1833 QString text;
1807 bool intern = FALSE; 1834 bool intern = FALSE;
1808 if ( QTextDrag::decode( e, text ) ) { 1835 if ( QTextDrag::decode( e, text ) ) {
1809 if ( ( e->source() == this || 1836 bool hasSel = doc->hasSelection( QTextDocument::Standard );
1810 e->source() == viewport() ) && 1837 bool internalDrag = e->source() == this || e->source() == viewport();
1811 e->action() == QDropEvent::Move ) { 1838 int dropId, dropIndex;
1839 QTextCursor insertCursor = *cursor;
1840 dropId = cursor->paragraph()->paragId();
1841 dropIndex = cursor->index();
1842 if ( hasSel && internalDrag ) {
1843 QTextCursor c1, c2;
1844 int selStartId, selStartIndex;
1845 int selEndId, selEndIndex;
1846 c1 = doc->selectionStartCursor( QTextDocument::Standard );
1847 c1.restoreState();
1848 c2 = doc->selectionEndCursor( QTextDocument::Standard );
1849 c2.restoreState();
1850 selStartId = c1.paragraph()->paragId();
1851 selStartIndex = c1.index();
1852 selEndId = c2.paragraph()->paragId();
1853 selEndIndex = c2.index();
1854 if ( ( ( dropId > selStartId ) ||
1855 ( dropId == selStartId && dropIndex > selStartIndex ) ) &&
1856 ( ( dropId < selEndId ) ||
1857 ( dropId == selEndId && dropIndex <= selEndIndex ) ) )
1858 insertCursor = c1;
1859 if ( dropId == selEndId && dropIndex > selEndIndex ) {
1860 insertCursor = c1;
1861 if ( selStartId == selEndId ) {
1862 insertCursor.setIndex( dropIndex -
1863 ( selEndIndex - selStartIndex ) );
1864 } else {
1865 insertCursor.setIndex( dropIndex - selEndIndex +
1866 selStartIndex );
1867 }
1868 }
1869 }
1870
1871 if ( internalDrag && e->action() == QDropEvent::Move ) {
1812 removeSelectedText(); 1872 removeSelectedText();
1813 intern = TRUE; 1873 intern = TRUE;
1814 } else { 1874 } else {
1815 doc->removeSelection( QTextDocument::Standard ); 1875 doc->removeSelection( QTextDocument::Standard );
1816#ifndef QT_NO_CURSOR 1876#ifndef QT_NO_CURSOR
1817 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1877 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1818#endif 1878#endif
1819 } 1879 }
1820 drawCursor( FALSE ); 1880 drawCursor( FALSE );
1821 placeCursor( e->pos(), cursor ); 1881 cursor->setParagraph( insertCursor.paragraph() );
1882 cursor->setIndex( insertCursor.index() );
1822 drawCursor( TRUE ); 1883 drawCursor( TRUE );
1823 if ( !cursor->nestedDepth() ) { 1884 if ( !cursor->nestedDepth() ) {
1824 insert( text, FALSE, TRUE, FALSE ); 1885 insert( text, FALSE, TRUE, FALSE );
1825 } else { 1886 } else {
1826 if ( intern ) 1887 if ( intern )
1827 undo(); 1888 undo();
1828 e->ignore(); 1889 e->ignore();
1829 } 1890 }
1830 } 1891 }
1831} 1892}
1832 1893
1833#endif 1894#endif
1834 1895
1835void QTextEdit::autoScrollTimerDone() 1896void QTextEdit::autoScrollTimerDone()
1836{ 1897{
1837 if ( mousePressed ) 1898 if ( mousePressed )
1838 handleMouseMove( viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ) ); 1899 handleMouseMove( viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ) );
1839} 1900}
1840 1901
1841void QTextEdit::handleMouseMove( const QPoint& pos ) 1902void QTextEdit::handleMouseMove( const QPoint& pos )
1842{ 1903{
1843 if ( !mousePressed ) 1904 if ( !mousePressed )
1844 return; 1905 return;
1845 1906
1846 if ( !scrollTimer->isActive() && pos.y() < contentsY() || pos.y() > contentsY() + visibleHeight() ) 1907 if ( !scrollTimer->isActive() && pos.y() < contentsY() || pos.y() > contentsY() + visibleHeight() )
1847 scrollTimer->start( 100, FALSE ); 1908 scrollTimer->start( 100, FALSE );
1848 else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() ) 1909 else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() )
1849 scrollTimer->stop(); 1910 scrollTimer->stop();
1850 1911
1851 drawCursor( FALSE ); 1912 drawCursor( FALSE );
1852 QTextCursor oldCursor = *cursor; 1913 QTextCursor oldCursor = *cursor;
1853 1914
1854 placeCursor( pos ); 1915 placeCursor( pos );
1855 1916
1856 if ( inDoubleClick ) { 1917 if ( inDoubleClick ) {
1857 QTextCursor cl = *cursor; 1918 QTextCursor cl = *cursor;
1858 cl.gotoPreviousWord(); 1919 cl.gotoPreviousWord();
1859 QTextCursor cr = *cursor; 1920 QTextCursor cr = *cursor;
1860 cr.gotoNextWord(); 1921 cr.gotoNextWord();
1861 1922
1862 int diff = QABS( oldCursor.parag()->at( oldCursor.index() )->x - mousePos.x() ); 1923 int diff = QABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() );
1863 int ldiff = QABS( cl.parag()->at( cl.index() )->x - mousePos.x() ); 1924 int ldiff = QABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() );
1864 int rdiff = QABS( cr.parag()->at( cr.index() )->x - mousePos.x() ); 1925 int rdiff = QABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() );
1865 1926
1866 1927
1867 if ( cursor->parag()->lineStartOfChar( cursor->index() ) != 1928 if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) !=
1868 oldCursor.parag()->lineStartOfChar( oldCursor.index() ) ) 1929 oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) )
1869 diff = 0xFFFFFF; 1930 diff = 0xFFFFFF;
1870 1931
1871 if ( rdiff < diff && rdiff < ldiff ) 1932 if ( rdiff < diff && rdiff < ldiff )
1872 *cursor = cr; 1933 *cursor = cr;
1873 else if ( ldiff < diff && ldiff < rdiff ) 1934 else if ( ldiff < diff && ldiff < rdiff )
1874 *cursor = cl; 1935 *cursor = cl;
1875 else 1936 else
1876 *cursor = oldCursor; 1937 *cursor = oldCursor;
1877 1938
1878 } 1939 }
1879 ensureCursorVisible(); 1940 ensureCursorVisible();
1880 1941
1881 bool redraw = FALSE; 1942 bool redraw = FALSE;
1882 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1943 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1883 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1944 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1884 } 1945 }
1885 1946
1886 if ( !redraw ) { 1947 if ( !redraw ) {
1887 drawCursor( TRUE ); 1948 drawCursor( TRUE );
1888 } else { 1949 } else {
1889 repaintChanged(); 1950 repaintChanged();
1890 drawCursor( TRUE ); 1951 drawCursor( TRUE );
1891 } 1952 }
1892 1953
1893 if ( currentFormat && currentFormat->key() != cursor->parag()->at( cursor->index() )->format()->key() ) { 1954 if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) {
1894 currentFormat->removeRef(); 1955 currentFormat->removeRef();
1895 currentFormat = doc->formatCollection()->format( cursor->parag()->at( cursor->index() )->format() ); 1956 currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() );
1896 if ( currentFormat->isMisspelled() ) { 1957 if ( currentFormat->isMisspelled() ) {
1897 currentFormat->removeRef(); 1958 currentFormat->removeRef();
1898 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); 1959 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
1899 } 1960 }
1900 emit currentFontChanged( currentFormat->font() ); 1961 emit currentFontChanged( currentFormat->font() );
1901 emit currentColorChanged( currentFormat->color() ); 1962 emit currentColorChanged( currentFormat->color() );
1902 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 1963 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
1903 } 1964 }
1904 1965
1905 if ( currentAlignment != cursor->parag()->alignment() ) { 1966 if ( currentAlignment != cursor->paragraph()->alignment() ) {
1906 currentAlignment = cursor->parag()->alignment(); 1967 currentAlignment = cursor->paragraph()->alignment();
1907 block_set_alignment = TRUE; 1968 block_set_alignment = TRUE;
1908 emit currentAlignmentChanged( currentAlignment ); 1969 emit currentAlignmentChanged( currentAlignment );
1909 block_set_alignment = FALSE; 1970 block_set_alignment = FALSE;
1910 } 1971 }
1911} 1972}
1912 1973
1913/*! 1974/*!
1914 \fn void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c ) 1975 \fn void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c )
1915 Places the cursor \a c at the character which is closest to position 1976 Places the cursor \a c at the character which is closest to position
1916 \a pos (in contents coordinates). If \a c is 0, the default text 1977 \a pos (in contents coordinates). If \a c is 0, the default text
1917 cursor is used. 1978 cursor is used.
1918 1979
1919 \sa setCursorPosition() 1980 \sa setCursorPosition()
1920*/ 1981*/
1921 1982
1922void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link ) 1983void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link )
1923{ 1984{
1924 if ( !c ) 1985 if ( !c )
1925 c = cursor; 1986 c = cursor;
1926 1987
1927 c->restoreState(); 1988 c->restoreState();
1928 QTextParag *s = doc->firstParag(); 1989 QTextParagraph *s = doc->firstParagraph();
1929 c->place( pos, s, link ); 1990 c->place( pos, s, link );
1991 updateMicroFocusHint();
1992}
1993
1994
1995void QTextEdit::updateMicroFocusHint()
1996{
1997 QTextCursor c( *cursor );
1998 if ( d->preeditStart != -1 )
1999 c.setIndex( d->preeditStart );
2000
1930 if ( hasFocus() || viewport()->hasFocus() ) { 2001 if ( hasFocus() || viewport()->hasFocus() ) {
1931 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 2002 int h = c.paragraph()->lineHeightOfChar( cursor->index() );
1932 if ( !readonly ) { 2003 if ( !readonly ) {
1933 QFont f = cursor->parag()->at( cursor->index() )->format()->font(); 2004 QFont f = c.paragraph()->at( c.index() )->format()->font();
1934 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), 2005 setMicroFocusHint( c.x() - contentsX() + frameWidth(),
1935 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); 2006 c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1936 } 2007 }
1937 } 2008 }
1938} 2009}
1939 2010
2011
2012
1940void QTextEdit::formatMore() 2013void QTextEdit::formatMore()
1941{ 2014{
1942 if ( !lastFormatted ) 2015 if ( !lastFormatted )
1943 return; 2016 return;
1944 2017
1945 int bottom = contentsHeight(); 2018 int bottom = contentsHeight();
1946 int lastBottom = -1; 2019 int lastBottom = -1;
1947 int to = !sender() ? 2 : 20; 2020 int to = 20;
1948 bool firstVisible = FALSE; 2021 bool firstVisible = FALSE;
1949 QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2022 QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
1950 for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) { 2023 for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) {
1951 lastFormatted->format(); 2024 lastFormatted->format();
1952 if ( i == 0 ) 2025 if ( i == 0 )
1953 firstVisible = lastFormatted->rect().intersects( cr ); 2026 firstVisible = lastFormatted->rect().intersects( cr );
1954 else if ( firstVisible ) 2027 else if ( firstVisible )
1955 firstVisible = lastFormatted->rect().intersects( cr ); 2028 firstVisible = lastFormatted->rect().intersects( cr );
1956 bottom = QMAX( bottom, lastFormatted->rect().top() + 2029 bottom = QMAX( bottom, lastFormatted->rect().top() +
1957 lastFormatted->rect().height() ); 2030 lastFormatted->rect().height() );
1958 lastBottom = lastFormatted->rect().top() + lastFormatted->rect().height(); 2031 lastBottom = lastFormatted->rect().top() + lastFormatted->rect().height();
1959 lastFormatted = lastFormatted->next(); 2032 lastFormatted = lastFormatted->next();
1960 if ( lastFormatted ) 2033 if ( lastFormatted )
1961 lastBottom = -1; 2034 lastBottom = -1;
1962 } 2035 }
1963 2036
1964 if ( bottom > contentsHeight() ) 2037 if ( bottom > contentsHeight() ) {
1965 resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) ); 2038 resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) );
1966 else if ( lastBottom != -1 && lastBottom < contentsHeight() ) 2039 } else if ( lastBottom != -1 && lastBottom < contentsHeight() ) {
1967 resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) ); 2040 resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) );
2041 if ( contentsHeight() < visibleHeight() )
2042 updateContents( 0, contentsHeight(), visibleWidth(),
2043 visibleHeight() - contentsHeight() );
2044 }
1968 2045
1969 if ( lastFormatted ) 2046 if ( lastFormatted )
1970 formatTimer->start( interval, TRUE ); 2047 formatTimer->start( interval, TRUE );
1971 else 2048 else
1972 interval = QMAX( 0, interval ); 2049 interval = QMAX( 0, interval );
1973} 2050}
1974 2051
1975void QTextEdit::doResize() 2052void QTextEdit::doResize()
1976{ 2053{
1977 if ( wrapMode == FixedPixelWidth ) 2054 if ( wrapMode == FixedPixelWidth )
1978 return; 2055 return;
1979 doc->setMinimumWidth( -1 ); 2056 doc->setMinimumWidth( -1 );
1980 resizeContents( 0, 0 ); 2057 resizeContents( 0, 0 );
1981 doc->setWidth( visibleWidth() ); 2058 doc->setWidth( visibleWidth() );
1982 doc->invalidate(); 2059 doc->invalidate();
1983 lastFormatted = doc->firstParag(); 2060 lastFormatted = doc->firstParagraph();
1984 interval = 0; 2061 interval = 0;
1985 formatMore(); 2062 formatMore();
1986 repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE ); 2063 repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE );
1987} 2064}
1988 2065
1989/*! \internal */ 2066/*! \internal */
1990 2067
1991void QTextEdit::doChangeInterval() 2068void QTextEdit::doChangeInterval()
1992{ 2069{
1993 interval = 0; 2070 interval = 0;
1994} 2071}
1995 2072
1996/*! \reimp */ 2073/*! \reimp */
1997 2074
1998bool QTextEdit::eventFilter( QObject *o, QEvent *e ) 2075bool QTextEdit::eventFilter( QObject *o, QEvent *e )
1999{ 2076{
2000 if ( o == this || o == viewport() ) { 2077 if ( o == this || o == viewport() ) {
2001 if ( e->type() == QEvent::FocusIn ) { 2078 if ( e->type() == QEvent::FocusIn ) {
2002 blinkTimer->start( QApplication::cursorFlashTime() / 2 ); 2079 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
2003 drawCursor( TRUE ); 2080 drawCursor( TRUE );
2004 2081 updateMicroFocusHint();
2005 if ( !readonly ) {
2006 // make sure the micro focus hint is updated...
2007 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2008 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2009 cursor->y() + cursor->parag()->rect().y() -
2010 contentsY() + frameWidth(), 0,
2011 cursor->parag()->lineHeightOfChar( cursor->index() ),
2012 TRUE );
2013 }
2014 } else if ( e->type() == QEvent::FocusOut ) { 2082 } else if ( e->type() == QEvent::FocusOut ) {
2015 blinkTimer->stop(); 2083 blinkTimer->stop();
2016 drawCursor( FALSE ); 2084 drawCursor( FALSE );
2017 } 2085 }
2018 } 2086 }
2019 2087
2020 return QScrollView::eventFilter( o, e ); 2088 return QScrollView::eventFilter( o, e );
2021} 2089}
2022 2090
2023/*! 2091/*! Inserts \a text at the current cursor position. If \a indent is
2024 Inserts \a text at the current cursor position. If \a indent is TRUE, 2092 TRUE, the paragraph is re-indented. If \a checkNewLine is TRUE,
2025 the paragraph is re-indented. If \a checkNewLine is TRUE, newline 2093 newline characters in \a text result in hard line breaks (i.e. new
2026 characters in \a text result in hard line breaks (i.e. new 2094 paragraphs). If \a checkNewLine is FALSE and there are newlines in
2027 paragraphs). If \a checkNewLine is FALSE the behaviour of the editor 2095 \a text, the behavior is undefined. If \a checkNewLine is FALSE the
2028 is undefined if the \a text contains newlines. If \a removeSelected is 2096 behaviour of the editor is undefined if the \a text contains
2029 TRUE, any selected text (in selection 0) is removed before the text is 2097 newlines. If \a removeSelected is TRUE, any selected text (in
2030 inserted. 2098 selection 0) is removed before the text is inserted.
2031 2099
2032 \sa paste() pasteSubType() 2100 \sa paste() pasteSubType()
2033*/ 2101*/
2034 2102
2035void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected ) 2103void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected )
2036{ 2104{
2037 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough 2105 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough
2038 return; 2106 return;
2039 QString txt( text ); 2107 QString txt( text );
2040 drawCursor( FALSE ); 2108 drawCursor( FALSE );
2041 if ( !isReadOnly() && doc->hasSelection( QTextDocument::Standard ) && removeSelected ) 2109 if ( !isReadOnly() && doc->hasSelection( QTextDocument::Standard ) && removeSelected )
2042 removeSelectedText(); 2110 removeSelectedText();
2043 QTextCursor c2 = *cursor; 2111 QTextCursor c2 = *cursor;
2044 int oldLen = 0; 2112 int oldLen = 0;
2045 2113
2046 if ( undoEnabled && !isReadOnly() ) { 2114 if ( undoEnabled && !isReadOnly() ) {
2047 checkUndoRedoInfo( UndoRedoInfo::Insert ); 2115 checkUndoRedoInfo( UndoRedoInfo::Insert );
2048 if ( !undoRedoInfo.valid() ) { 2116 if ( !undoRedoInfo.valid() ) {
2049 undoRedoInfo.id = cursor->parag()->paragId(); 2117 undoRedoInfo.id = cursor->paragraph()->paragId();
2050 undoRedoInfo.index = cursor->index(); 2118 undoRedoInfo.index = cursor->index();
2051 undoRedoInfo.d->text = QString::null; 2119 undoRedoInfo.d->text = QString::null;
2052 } 2120 }
2053 oldLen = undoRedoInfo.d->text.length(); 2121 oldLen = undoRedoInfo.d->text.length();
2054 } 2122 }
2055 2123
2056 lastFormatted = checkNewLine && cursor->parag()->prev() ? 2124 lastFormatted = checkNewLine && cursor->paragraph()->prev() ?
2057 cursor->parag()->prev() : cursor->parag(); 2125 cursor->paragraph()->prev() : cursor->paragraph();
2058 QTextCursor oldCursor = *cursor; 2126 QTextCursor oldCursor = *cursor;
2059 cursor->insert( txt, checkNewLine ); 2127 cursor->insert( txt, checkNewLine );
2060 if ( doc->useFormatCollection() ) { 2128 if ( doc->useFormatCollection() ) {
2061 doc->setSelectionStart( QTextDocument::Temp, &oldCursor ); 2129 doc->setSelectionStart( QTextDocument::Temp, oldCursor );
2062 doc->setSelectionEnd( QTextDocument::Temp, cursor ); 2130 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
2063 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); 2131 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format );
2064 doc->removeSelection( QTextDocument::Temp ); 2132 doc->removeSelection( QTextDocument::Temp );
2065 } 2133 }
2066 2134
2067 if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) ) 2135 if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) )
2068 cursor->indent(); 2136 cursor->indent();
2069 formatMore(); 2137 formatMore();
2070 repaintChanged(); 2138 repaintChanged();
2071 ensureCursorVisible(); 2139 ensureCursorVisible();
2072 drawCursor( TRUE ); 2140 drawCursor( TRUE );
2073 2141
2074 if ( undoEnabled && !isReadOnly() ) { 2142 if ( undoEnabled && !isReadOnly() ) {
2075 undoRedoInfo.d->text += txt; 2143 undoRedoInfo.d->text += txt;
2076 if ( !doc->preProcessor() ) { 2144 if ( !doc->preProcessor() ) {
2077 for ( int i = 0; i < (int)txt.length(); ++i ) { 2145 for ( int i = 0; i < (int)txt.length(); ++i ) {
2078 if ( txt[ i ] != '\n' && c2.parag()->at( c2.index() )->format() ) { 2146 if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) {
2079 c2.parag()->at( c2.index() )->format()->addRef(); 2147 c2.paragraph()->at( c2.index() )->format()->addRef();
2080 undoRedoInfo.d->text.setFormat( oldLen + i, c2.parag()->at( c2.index() )->format(), TRUE ); 2148 undoRedoInfo.d->text.setFormat( oldLen + i, c2.paragraph()->at( c2.index() )->format(), TRUE );
2081 } 2149 }
2082 c2.gotoNextLetter(); 2150 c2.gotoNextLetter();
2083 } 2151 }
2084 } 2152 }
2085 } 2153 }
2086 2154
2087 setModified();
2088 emit textChanged();
2089 if ( !removeSelected ) { 2155 if ( !removeSelected ) {
2090 doc->setSelectionStart( QTextDocument::Standard, &oldCursor ); 2156 doc->setSelectionStart( QTextDocument::Standard, oldCursor );
2091 doc->setSelectionEnd( QTextDocument::Standard, cursor ); 2157 doc->setSelectionEnd( QTextDocument::Standard, *cursor );
2092 repaintChanged(); 2158 repaintChanged();
2093 } 2159 }
2094 if ( hasFocus() || viewport()->hasFocus() ) { 2160 updateMicroFocusHint();
2095 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 2161 setModified();
2096 if ( !readonly ) { 2162 emit textChanged();
2097 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2098 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2099 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2100 }
2101 }
2102} 2163}
2103 2164
2104/*! Inserts \a text in the paragraph \a para and position \a index */ 2165/*! Inserts \a text in the paragraph \a para and position \a index */
2105 2166
2106void QTextEdit::insertAt( const QString &text, int para, int index ) 2167void QTextEdit::insertAt( const QString &text, int para, int index )
2107{ 2168{
2108 QTextParag *p = doc->paragAt( para ); 2169 removeSelection( QTextDocument::Standard );
2170 QTextParagraph *p = doc->paragAt( para );
2109 if ( !p ) 2171 if ( !p )
2110 return; 2172 return;
2111 QTextCursor tmp = *cursor; 2173 QTextCursor tmp = *cursor;
2112 cursor->setParag( p ); 2174 cursor->setParagraph( p );
2113 cursor->setIndex( index ); 2175 cursor->setIndex( index );
2114 insert( text, FALSE, TRUE, FALSE ); 2176 insert( text, FALSE, TRUE, FALSE );
2115 *cursor = tmp; 2177 *cursor = tmp;
2116 removeSelection( QTextDocument::Standard ); 2178 removeSelection( QTextDocument::Standard );
2117} 2179}
2118 2180
2119/*! Inserts \a text as the paragraph at position \a para. If \a para 2181/*! Inserts \a text as the paragraph at position \a para. If \a para
2120 is -1, the text is appended. 2182 is -1, the text is appended.
2121*/ 2183*/
2122 2184
2123void QTextEdit::insertParagraph( const QString &text, int para ) 2185void QTextEdit::insertParagraph( const QString &text, int para )
2124{ 2186{
2125 QTextParag *p = doc->paragAt( para ); 2187 QTextParagraph *p = doc->paragAt( para );
2126 if ( p ) { 2188 if ( p ) {
2127 QTextCursor tmp( doc ); 2189 QTextCursor tmp( doc );
2128 tmp.setParag( p ); 2190 tmp.setParagraph( p );
2129 tmp.setIndex( 0 ); 2191 tmp.setIndex( 0 );
2130 tmp.insert( text, TRUE ); 2192 tmp.insert( text, TRUE );
2131 tmp.splitAndInsertEmptyParag(); 2193 tmp.splitAndInsertEmptyParagraph();
2132 repaintChanged(); 2194 repaintChanged();
2133 } else { 2195 } else {
2134 append( text ); 2196 append( text );
2135 } 2197 }
2136} 2198}
2137 2199
2138/*! Removes the paragraph \a para */ 2200/*! Removes the paragraph \a para */
2139 2201
2140void QTextEdit::removeParagraph( int para ) 2202void QTextEdit::removeParagraph( int para )
2141{ 2203{
2142 QTextParag *p = doc->paragAt( para ); 2204 QTextParagraph *p = doc->paragAt( para );
2143 if ( !p ) 2205 if ( !p )
2144 return; 2206 return;
2145 for ( int i = 0; i < doc->numSelections(); ++i ) 2207 for ( int i = 0; i < doc->numSelections(); ++i )
2146 doc->removeSelection( i ); 2208 doc->removeSelection( i );
2147 2209
2148 if ( p == doc->firstParag() && p == doc->lastParag() ) { 2210 if ( p == doc->firstParagraph() && p == doc->lastParagraph() ) {
2149 p->remove( 0, p->length() - 1 ); 2211 p->remove( 0, p->length() - 1 );
2150 repaintChanged(); 2212 repaintChanged();
2151 return; 2213 return;
2152 } 2214 }
2153 drawCursor( FALSE ); 2215 drawCursor( FALSE );
2154 bool resetCursor = cursor->parag() == p; 2216 bool resetCursor = cursor->paragraph() == p;
2155 if ( p->prev() ) 2217 if ( p->prev() )
2156 p->prev()->setNext( p->next() ); 2218 p->prev()->setNext( p->next() );
2157 else 2219 else
2158 doc->setFirstParag( p->next() ); 2220 doc->setFirstParagraph( p->next() );
2159 if ( p->next() ) 2221 if ( p->next() )
2160 p->next()->setPrev( p->prev() ); 2222 p->next()->setPrev( p->prev() );
2161 else 2223 else
2162 doc->setLastParag( p->prev() ); 2224 doc->setLastParagraph( p->prev() );
2163 QTextParag *start = p->next(); 2225 QTextParagraph *start = p->next();
2164 int h = p->rect().height(); 2226 int h = p->rect().height();
2165 delete p; 2227 delete p;
2166 p = start; 2228 p = start;
2167 int dy = -h; 2229 int dy = -h;
2168 while ( p ) { 2230 while ( p ) {
2169 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); 2231 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 );
2170 p->move( dy ); 2232 p->move( dy );
2171 p->invalidate( 0 ); 2233 p->invalidate( 0 );
2172 p->setEndState( -1 ); 2234 p->setEndState( -1 );
2173 p = p->next(); 2235 p = p->next();
2174 } 2236 }
2175 2237
2176 if ( resetCursor ) { 2238 if ( resetCursor ) {
2177 cursor->setParag( doc->firstParag() ); 2239 cursor->setParagraph( doc->firstParagraph() );
2178 cursor->setIndex( 0 ); 2240 cursor->setIndex( 0 );
2179 } 2241 }
2180 repaintChanged(); 2242 repaintChanged();
2181 drawCursor( TRUE ); 2243 drawCursor( TRUE );
2182} 2244}
2183 2245
2184/*! 2246/*!
2185 Undoes the last operation. 2247 Undoes the last operation.
2186 2248
2187 If there is no operation to undo, e.g. there is no undo step in the 2249 If there is no operation to undo, e.g. there is no undo step in the
2188 undo/redo history, nothing happens. 2250 undo/redo history, nothing happens.
2189 2251
2190 \sa undoAvailable() redo() undoDepth() 2252 \sa undoAvailable() redo() undoDepth()
2191*/ 2253*/
2192 2254
2193void QTextEdit::undo() 2255void QTextEdit::undo()
2194{ 2256{
2195 // XXX FIXME The next line is here because there may be a command 2257 // XXX FIXME The next line is here because there may be a command
2196 // that needs to be 'flushed'. The FIXME is because I am not 2258 // that needs to be 'flushed'. The FIXME is because I am not
2197 // 100% certain this is the right call to do this. 2259 // 100% certain this is the right call to do this.
2198 clearUndoRedo(); 2260 clearUndoRedo();
2199 if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled ) 2261 if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled )
2200 return; 2262 return;
2201 2263
2202 for ( int i = 0; i < (int)doc->numSelections(); ++i ) 2264 for ( int i = 0; i < (int)doc->numSelections(); ++i )
2203 doc->removeSelection( i ); 2265 doc->removeSelection( i );
2204 2266
2205#ifndef QT_NO_CURSOR 2267#ifndef QT_NO_CURSOR
2206 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 2268 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
2207#endif 2269#endif
2208 2270
2209 clearUndoRedo(); 2271 clearUndoRedo();
2210 drawCursor( FALSE ); 2272 drawCursor( FALSE );
2211 QTextCursor *c = doc->undo( cursor ); 2273 QTextCursor *c = doc->undo( cursor );
2212 if ( !c ) { 2274 if ( !c ) {
2213 drawCursor( TRUE ); 2275 drawCursor( TRUE );
2214 return; 2276 return;
2215 } 2277 }
2216 lastFormatted = 0; 2278 lastFormatted = 0;
2217 ensureCursorVisible(); 2279 ensureCursorVisible();
2218 repaintChanged(); 2280 repaintChanged();
2219 drawCursor( TRUE ); 2281 drawCursor( TRUE );
2282 updateMicroFocusHint();
2220 setModified(); 2283 setModified();
2221 emit textChanged(); 2284 emit textChanged();
2222 if ( hasFocus() || viewport()->hasFocus() ) {
2223 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2224 if ( !readonly ) {
2225 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2226 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2227 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2228 }
2229 }
2230} 2285}
2231 2286
2232/*! 2287/*!
2233 Redoes the last operation. 2288 Redoes the last operation.
2234 2289
2235 If there is no operation to redo, e.g. there is no redo step in the 2290 If there is no operation to redo, e.g. there is no redo step in the
2236 undo/redo history, nothing happens. 2291 undo/redo history, nothing happens.
2237 2292
2238 \sa redoAvailable() undo() undoDepth() 2293 \sa redoAvailable() undo() undoDepth()
2239*/ 2294*/
2240 2295
2241void QTextEdit::redo() 2296void QTextEdit::redo()
2242{ 2297{
2243 if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled ) 2298 if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled )
2244 return; 2299 return;
2245 2300
2246 for ( int i = 0; i < (int)doc->numSelections(); ++i ) 2301 for ( int i = 0; i < (int)doc->numSelections(); ++i )
2247 doc->removeSelection( i ); 2302 doc->removeSelection( i );
2248 2303
2249#ifndef QT_NO_CURSOR 2304#ifndef QT_NO_CURSOR
2250 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 2305 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
2251#endif 2306#endif
2252 2307
2253 clearUndoRedo(); 2308 clearUndoRedo();
2254 drawCursor( FALSE ); 2309 drawCursor( FALSE );
2255 QTextCursor *c = doc->redo( cursor ); 2310 QTextCursor *c = doc->redo( cursor );
2256 if ( !c ) { 2311 if ( !c ) {
2257 drawCursor( TRUE ); 2312 drawCursor( TRUE );
2258 return; 2313 return;
2259 } 2314 }
2260 lastFormatted = 0; 2315 lastFormatted = 0;
2261 ensureCursorVisible(); 2316 ensureCursorVisible();
2262 repaintChanged(); 2317 repaintChanged();
2263 ensureCursorVisible(); 2318 ensureCursorVisible();
2264 drawCursor( TRUE ); 2319 drawCursor( TRUE );
2320 updateMicroFocusHint();
2265 setModified(); 2321 setModified();
2266 emit textChanged(); 2322 emit textChanged();
2267 if ( hasFocus() || viewport()->hasFocus() ) {
2268 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2269 if ( !readonly ) {
2270 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2271 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2272 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2273 }
2274 }
2275} 2323}
2276 2324
2277/*! 2325/*!
2278 Pastes the text from the clipboard into the text edit at the current 2326 Pastes the text from the clipboard into the text edit at the current
2279 cursor position. Only plain text is pasted. 2327 cursor position. Only plain text is pasted.
2280 2328
2281 If there is no text in the clipboard nothing happens. 2329 If there is no text in the clipboard nothing happens.
2282 2330
2283 \sa pasteSubType() cut() QTextEdit::copy() 2331 \sa pasteSubType() cut() QTextEdit::copy()
2284*/ 2332*/
2285 2333
2286void QTextEdit::paste() 2334void QTextEdit::paste()
2287{ 2335{
2288#ifndef QT_NO_CLIPBOARD 2336#ifndef QT_NO_CLIPBOARD
2289 if ( isReadOnly() ) 2337 if ( isReadOnly() )
2290 return; 2338 return;
2291 pasteSubType( "plain" ); 2339 pasteSubType( "plain" );
2292 if ( hasFocus() || viewport()->hasFocus() ) { 2340 updateMicroFocusHint();
2293 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2294 if ( !readonly ) {
2295 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2296 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2297 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2298 }
2299 }
2300#endif 2341#endif
2301} 2342}
2302 2343
2303void QTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t ) 2344void QTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t )
2304{ 2345{
2305 if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) { 2346 if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) {
2306 clearUndoRedo(); 2347 clearUndoRedo();
2307 } 2348 }
2308 undoRedoInfo.type = t; 2349 undoRedoInfo.type = t;
2309} 2350}
2310 2351
2311/*! Repaints any paragraphs that have changed. 2352/*! Repaints any paragraphs that have changed.
2312 2353
2313 Although used extensively internally you shouldn't need to call this 2354 Although used extensively internally you shouldn't need to call this
2314 yourself. 2355 yourself.
2315*/ 2356*/
2316 2357
2317void QTextEdit::repaintChanged() 2358void QTextEdit::repaintChanged()
2318{ 2359{
2319 if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() ) 2360 if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() )
2320 return; 2361 return;
2321 QPainter p( viewport() ); 2362 QPainter p( viewport() );
2322 p.translate( -contentsX(), -contentsY() ); 2363 p.translate( -contentsX(), -contentsY() );
2323 paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2364 paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() );
2324} 2365}
2325 2366
2326/*! 2367/*!
2327 Copies the selected text (from selection 0) to the clipboard and 2368 Copies the selected text (from selection 0) to the clipboard and
2328 deletes it from the text edit. 2369 deletes it from the text edit.
2329 2370
2330 If there is no selected text (in selection 0) nothing happens. 2371 If there is no selected text (in selection 0) nothing happens.
2331 2372
2332 \sa QTextEdit::copy() paste() pasteSubType() 2373 \sa QTextEdit::copy() paste() pasteSubType()
2333*/ 2374*/
2334 2375
2335void QTextEdit::cut() 2376void QTextEdit::cut()
2336{ 2377{
2337 if ( isReadOnly() ) 2378 if ( isReadOnly() )
2338 return; 2379 return;
2339 2380
2340 if ( doc->hasSelection( QTextDocument::Standard ) ) { 2381 QString t;
2341 doc->copySelectedText( QTextDocument::Standard ); 2382 if ( doc->hasSelection( QTextDocument::Standard ) &&
2383 !( t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ) ).isEmpty() ) {
2384 QApplication::clipboard()->setText( t );
2342 removeSelectedText(); 2385 removeSelectedText();
2343 } 2386 }
2344 if ( hasFocus() || viewport()->hasFocus() ) { 2387 updateMicroFocusHint();
2345 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2346 if ( !readonly ) {
2347 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2348 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2349 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2350 }
2351 }
2352} 2388}
2353 2389
2354/*! Copies any selected text (from selection 0) to the clipboard. 2390/*! Copies any selected text (from selection 0) to the clipboard.
2355 2391
2356 \sa hasSelectedText() copyAvailable() 2392 \sa hasSelectedText() copyAvailable()
2357 */ 2393 */
2358 2394
2359void QTextEdit::copy() 2395void QTextEdit::copy()
2360{ 2396{
2361 if ( !doc->selectedText( QTextDocument::Standard ).isEmpty() ) 2397 QString t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy );
2362 doc->copySelectedText( QTextDocument::Standard ); 2398 if ( doc->hasSelection( QTextDocument::Standard ) &&
2399 !t.isEmpty() && t.simplifyWhiteSpace() != "<selstart/>" )
2400 QApplication::clipboard()->setText( t );
2363} 2401}
2364 2402
2365/*! 2403/*!
2366 Re-indents the current paragraph. 2404 Re-indents the current paragraph.
2367*/ 2405*/
2368 2406
2369void QTextEdit::indent() 2407void QTextEdit::indent()
2370{ 2408{
2371 if ( isReadOnly() ) 2409 if ( isReadOnly() )
2372 return; 2410 return;
2373 2411
2374 drawCursor( FALSE ); 2412 drawCursor( FALSE );
2375 if ( !doc->hasSelection( QTextDocument::Standard ) ) 2413 if ( !doc->hasSelection( QTextDocument::Standard ) )
2376 cursor->indent(); 2414 cursor->indent();
2377 else 2415 else
2378 doc->indentSelection( QTextDocument::Standard ); 2416 doc->indentSelection( QTextDocument::Standard );
2379 repaintChanged(); 2417 repaintChanged();
2380 drawCursor( TRUE ); 2418 drawCursor( TRUE );
2381 setModified(); 2419 setModified();
2382 emit textChanged(); 2420 emit textChanged();
2383} 2421}
2384 2422
2385/*! Reimplemented to allow tabbing through links. 2423/*! Reimplemented to allow tabbing through links.
2386 If \a n is TRUE the tab moves the focus to the next child; if \a n 2424 If \a n is TRUE the tab moves the focus to the next child; if \a n
@@ -2391,253 +2429,224 @@ void QTextEdit::indent()
2391bool QTextEdit::focusNextPrevChild( bool n ) 2429bool QTextEdit::focusNextPrevChild( bool n )
2392{ 2430{
2393 if ( !isReadOnly() || !linksEnabled() ) 2431 if ( !isReadOnly() || !linksEnabled() )
2394 return FALSE; 2432 return FALSE;
2395 bool b = doc->focusNextPrevChild( n ); 2433 bool b = doc->focusNextPrevChild( n );
2396 repaintChanged(); 2434 repaintChanged();
2397 if ( b ) 2435 if ( b )
2398 //##### this does not work with tables. The focusIndicator 2436 //##### this does not work with tables. The focusIndicator
2399 //should really be a QTextCursor. Fix 3.1 2437 //should really be a QTextCursor. Fix 3.1
2400 makeParagVisible( doc->focusIndicator.parag ); 2438 makeParagVisible( doc->focusIndicator.parag );
2401 return b; 2439 return b;
2402} 2440}
2403 2441
2404/*! 2442/*!
2405 \internal 2443 \internal
2406 2444
2407 This functions sets the current format to \a f. Only the fields of \a 2445 This functions sets the current format to \a f. Only the fields of \a
2408 f which are specified by the \a flags are used. 2446 f which are specified by the \a flags are used.
2409*/ 2447*/
2410 2448
2411void QTextEdit::setFormat( QTextFormat *f, int flags ) 2449void QTextEdit::setFormat( QTextFormat *f, int flags )
2412{ 2450{
2413 if ( doc->hasSelection( QTextDocument::Standard ) ) { 2451 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2414 drawCursor( FALSE ); 2452 drawCursor( FALSE );
2415 QString str = doc->selectedText( QTextDocument::Standard );
2416 QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard ); 2453 QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard );
2454 c1.restoreState();
2417 QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard ); 2455 QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard );
2456 c2.restoreState();
2418 clearUndoRedo(); 2457 clearUndoRedo();
2419 undoRedoInfo.type = UndoRedoInfo::Format; 2458 undoRedoInfo.type = UndoRedoInfo::Format;
2420 undoRedoInfo.id = c1.parag()->paragId(); 2459 undoRedoInfo.id = c1.paragraph()->paragId();
2421 undoRedoInfo.index = c1.index(); 2460 undoRedoInfo.index = c1.index();
2422 undoRedoInfo.eid = c2.parag()->paragId(); 2461 undoRedoInfo.eid = c2.paragraph()->paragId();
2423 undoRedoInfo.eindex = c2.index(); 2462 undoRedoInfo.eindex = c2.index();
2424 undoRedoInfo.d->text = str; 2463 readFormats( c1, c2, undoRedoInfo.d->text );
2425 readFormats( c1, c2, 0, undoRedoInfo.d->text );
2426 undoRedoInfo.format = f; 2464 undoRedoInfo.format = f;
2427 undoRedoInfo.flags = flags; 2465 undoRedoInfo.flags = flags;
2428 clearUndoRedo(); 2466 clearUndoRedo();
2429 doc->setFormat( QTextDocument::Standard, f, flags ); 2467 doc->setFormat( QTextDocument::Standard, f, flags );
2430 repaintChanged(); 2468 repaintChanged();
2431 formatMore(); 2469 formatMore();
2432 drawCursor( TRUE ); 2470 drawCursor( TRUE );
2433 setModified(); 2471 setModified();
2434 emit textChanged(); 2472 emit textChanged();
2435 } 2473 }
2436 if ( currentFormat && currentFormat->key() != f->key() ) { 2474 if ( currentFormat && currentFormat->key() != f->key() ) {
2437 currentFormat->removeRef(); 2475 currentFormat->removeRef();
2438 currentFormat = doc->formatCollection()->format( f ); 2476 currentFormat = doc->formatCollection()->format( f );
2439 if ( currentFormat->isMisspelled() ) { 2477 if ( currentFormat->isMisspelled() ) {
2440 currentFormat->removeRef(); 2478 currentFormat->removeRef();
2441 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); 2479 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
2442 } 2480 }
2443 emit currentFontChanged( currentFormat->font() ); 2481 emit currentFontChanged( currentFormat->font() );
2444 emit currentColorChanged( currentFormat->color() ); 2482 emit currentColorChanged( currentFormat->color() );
2445 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 2483 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
2446 if ( cursor->index() == cursor->parag()->length() - 1 ) { 2484 if ( cursor->index() == cursor->paragraph()->length() - 1 ) {
2447 currentFormat->addRef(); 2485 currentFormat->addRef();
2448 cursor->parag()->string()->setFormat( cursor->index(), currentFormat, TRUE ); 2486 cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE );
2449 if ( cursor->parag()->length() == 1 ) { 2487 if ( cursor->paragraph()->length() == 1 ) {
2450 cursor->parag()->invalidate( 0 ); 2488 cursor->paragraph()->invalidate( 0 );
2451 cursor->parag()->format(); 2489 cursor->paragraph()->format();
2452 repaintChanged(); 2490 repaintChanged();
2453 } 2491 }
2454 } 2492 }
2455 } 2493 }
2456} 2494}
2457 2495
2458/*! \reimp */ 2496/*! \reimp */
2459 2497
2460void QTextEdit::setPalette( const QPalette &p ) 2498void QTextEdit::setPalette( const QPalette &p )
2461{ 2499{
2462 QScrollView::setPalette( p ); 2500 QScrollView::setPalette( p );
2463 if ( textFormat() == PlainText ) { 2501 if ( textFormat() == PlainText ) {
2464 QTextFormat *f = doc->formatCollection()->defaultFormat(); 2502 QTextFormat *f = doc->formatCollection()->defaultFormat();
2465 f->setColor( colorGroup().text() ); 2503 f->setColor( colorGroup().text() );
2466 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2504 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
2467 } 2505 }
2468} 2506}
2469 2507
2470/*! 2508/*! \internal
2509
2510 \warning In Qt 3.1 we will provide a cleaer API for the
2511 functionality which is provided by this function and in Qt 4.0 this
2512 function will go away.
2513
2471 Sets the paragraph style of the current paragraph 2514 Sets the paragraph style of the current paragraph
2472 to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the 2515 to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the
2473 type of the list item is set to \a listStyle. 2516 type of the list item is set to \a listStyle.
2474 2517
2475 \sa setAlignment() 2518 \sa setAlignment()
2476*/ 2519*/
2477 2520
2478void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle ) 2521void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle )
2479{ 2522{
2480 if ( isReadOnly() ) 2523 if ( isReadOnly() )
2481 return; 2524 return;
2482 2525
2483 drawCursor( FALSE ); 2526 drawCursor( FALSE );
2484 if ( !doc->hasSelection( QTextDocument::Standard ) ) { 2527 QTextParagraph *start = cursor->paragraph();
2485 clearUndoRedo(); 2528 QTextParagraph *end = start;
2486 undoRedoInfo.type = UndoRedoInfo::ParagType; 2529 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2487 QValueList< QPtrVector<QStyleSheetItem> > oldStyles; 2530 start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph();
2488 undoRedoInfo.oldStyles.clear(); 2531 end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph();
2489 undoRedoInfo.oldStyles << cursor->parag()->styleSheetItems(); 2532 if ( end->paragId() < start->paragId() )
2490 undoRedoInfo.oldListStyles.clear(); 2533 return; // do not trust our selections
2491 undoRedoInfo.oldListStyles << cursor->parag()->listStyle(); 2534 }
2492 undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; 2535
2493 undoRedoInfo.listStyle = listStyle;
2494 undoRedoInfo.id = cursor->parag()->paragId();
2495 undoRedoInfo.eid = cursor->parag()->paragId();
2496 undoRedoInfo.d->text = " ";
2497 undoRedoInfo.index = 1;
2498 clearUndoRedo();
2499 cursor->parag()->setList( dm == QStyleSheetItem::DisplayListItem, listStyle );
2500 repaintChanged();
2501 } else {
2502 QTextParag *start = doc->selectionStart( QTextDocument::Standard );
2503 QTextParag *end = doc->selectionEnd( QTextDocument::Standard );
2504 lastFormatted = start;
2505 clearUndoRedo(); 2536 clearUndoRedo();
2506 undoRedoInfo.type = UndoRedoInfo::ParagType; 2537 undoRedoInfo.type = UndoRedoInfo::Style;
2507 undoRedoInfo.id = start->paragId(); 2538 undoRedoInfo.id = start->paragId();
2508 undoRedoInfo.eid = end->paragId(); 2539 undoRedoInfo.eid = end->paragId();
2509 undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; 2540 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
2510 undoRedoInfo.listStyle = listStyle; 2541
2511 undoRedoInfo.oldStyles.clear(); 2542 while ( start != end->next() ) {
2512 undoRedoInfo.oldListStyles.clear(); 2543 start->setListStyle( listStyle );
2513 while ( start ) { 2544 if ( dm == QStyleSheetItem::DisplayListItem ) {
2514 undoRedoInfo.oldStyles << start->styleSheetItems(); 2545 start->setListItem( TRUE );
2515 undoRedoInfo.oldListStyles << start->listStyle(); 2546 if( start->listDepth() == 0 )
2516 start->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); 2547 start->setListDepth( 1 );
2517 if ( start == end ) 2548 } else if ( start->isListItem() ) {
2518 break; 2549 start->setListItem( FALSE );
2550 start->setListDepth( QMAX( start->listDepth()-1, 0 ) );
2551 }
2519 start = start->next(); 2552 start = start->next();
2520 } 2553 }
2521 undoRedoInfo.d->text = " "; 2554
2522 undoRedoInfo.index = 1;
2523 clearUndoRedo(); 2555 clearUndoRedo();
2524 repaintChanged(); 2556 repaintChanged();
2525 formatMore(); 2557 formatMore();
2526 }
2527 drawCursor( TRUE ); 2558 drawCursor( TRUE );
2528 setModified(); 2559 setModified();
2529 emit textChanged(); 2560 emit textChanged();
2530} 2561}
2531 2562
2532/*! 2563/*!
2533 Sets the alignment of the current paragraph to \a a. Valid alignments 2564 Sets the alignment of the current paragraph to \a a. Valid alignments
2534 are \c Qt::AlignLeft, \c Qt::AlignRight, Qt::AlignJustify and 2565 are \c Qt::AlignLeft, \c Qt::AlignRight, Qt::AlignJustify and
2535 Qt::AlignCenter (which centers horizontally). 2566 Qt::AlignCenter (which centers horizontally).
2536 2567
2537 \sa setParagType()
2538*/ 2568*/
2539 2569
2540void QTextEdit::setAlignment( int a ) 2570void QTextEdit::setAlignment( int a )
2541{ 2571{
2542 if ( isReadOnly() || block_set_alignment ) 2572 if ( isReadOnly() || block_set_alignment )
2543 return; 2573 return;
2544 2574
2545 drawCursor( FALSE ); 2575 drawCursor( FALSE );
2546 if ( !doc->hasSelection( QTextDocument::Standard ) ) { 2576 QTextParagraph *start = cursor->paragraph();
2547 if ( cursor->parag()->alignment() != a ) { 2577 QTextParagraph *end = start;
2548 clearUndoRedo(); 2578 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2549 undoRedoInfo.type = UndoRedoInfo::Alignment; 2579 start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph();
2550 QMemArray<int> oa( 1 ); 2580 end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph();
2551 oa[ 0 ] = cursor->parag()->alignment(); 2581 if ( end->paragId() < start->paragId() )
2552 undoRedoInfo.oldAligns = oa; 2582 return; // do not trust our selections
2553 undoRedoInfo.newAlign = a;
2554 undoRedoInfo.id = cursor->parag()->paragId();
2555 undoRedoInfo.eid = cursor->parag()->paragId();
2556 undoRedoInfo.d->text = " ";
2557 undoRedoInfo.index = 1;
2558 clearUndoRedo();
2559 cursor->parag()->setAlignment( a );
2560 repaintChanged();
2561 } 2583 }
2562 } else { 2584
2563 QTextParag *start = doc->selectionStart( QTextDocument::Standard );
2564 QTextParag *end = doc->selectionEnd( QTextDocument::Standard );
2565 lastFormatted = start;
2566 int len = end->paragId() - start->paragId() + 1;
2567 clearUndoRedo(); 2585 clearUndoRedo();
2568 undoRedoInfo.type = UndoRedoInfo::Alignment; 2586 undoRedoInfo.type = UndoRedoInfo::Style;
2569 undoRedoInfo.id = start->paragId(); 2587 undoRedoInfo.id = start->paragId();
2570 undoRedoInfo.eid = end->paragId(); 2588 undoRedoInfo.eid = end->paragId();
2571 QMemArray<int> oa( QMAX( 0, len ) ); 2589 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
2572 int i = 0; 2590
2573 while ( start ) { 2591 while ( start != end->next() ) {
2574 if ( i < (int)oa.size() )
2575 oa[ i ] = start->alignment();
2576 start->setAlignment( a ); 2592 start->setAlignment( a );
2577 if ( start == end )
2578 break;
2579 start = start->next(); 2593 start = start->next();
2580 ++i;
2581 } 2594 }
2582 undoRedoInfo.oldAligns = oa; 2595
2583 undoRedoInfo.newAlign = a;
2584 undoRedoInfo.d->text = " ";
2585 undoRedoInfo.index = 1;
2586 clearUndoRedo(); 2596 clearUndoRedo();
2587 repaintChanged(); 2597 repaintChanged();
2588 formatMore(); 2598 formatMore();
2589 }
2590 drawCursor( TRUE ); 2599 drawCursor( TRUE );
2591 if ( currentAlignment != a ) { 2600 if ( currentAlignment != a ) {
2592 currentAlignment = a; 2601 currentAlignment = a;
2593 emit currentAlignmentChanged( currentAlignment ); 2602 emit currentAlignmentChanged( currentAlignment );
2594 } 2603 }
2595 setModified(); 2604 setModified();
2596 emit textChanged(); 2605 emit textChanged();
2597} 2606}
2598 2607
2599void QTextEdit::updateCurrentFormat() 2608void QTextEdit::updateCurrentFormat()
2600{ 2609{
2601 int i = cursor->index(); 2610 int i = cursor->index();
2602 if ( i > 0 ) 2611 if ( i > 0 )
2603 --i; 2612 --i;
2604 if ( doc->useFormatCollection() && 2613 if ( doc->useFormatCollection() &&
2605 ( !currentFormat || currentFormat->key() != cursor->parag()->at( i )->format()->key() ) ) { 2614 ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) {
2606 if ( currentFormat ) 2615 if ( currentFormat )
2607 currentFormat->removeRef(); 2616 currentFormat->removeRef();
2608 currentFormat = doc->formatCollection()->format( cursor->parag()->at( i )->format() ); 2617 currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() );
2609 if ( currentFormat->isMisspelled() ) { 2618 if ( currentFormat->isMisspelled() ) {
2610 currentFormat->removeRef(); 2619 currentFormat->removeRef();
2611 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); 2620 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
2612 } 2621 }
2613 emit currentFontChanged( currentFormat->font() ); 2622 emit currentFontChanged( currentFormat->font() );
2614 emit currentColorChanged( currentFormat->color() ); 2623 emit currentColorChanged( currentFormat->color() );
2615 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 2624 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
2616 } 2625 }
2617 2626
2618 if ( currentAlignment != cursor->parag()->alignment() ) { 2627 if ( currentAlignment != cursor->paragraph()->alignment() ) {
2619 currentAlignment = cursor->parag()->alignment(); 2628 currentAlignment = cursor->paragraph()->alignment();
2620 block_set_alignment = TRUE; 2629 block_set_alignment = TRUE;
2621 emit currentAlignmentChanged( currentAlignment ); 2630 emit currentAlignmentChanged( currentAlignment );
2622 block_set_alignment = FALSE; 2631 block_set_alignment = FALSE;
2623 } 2632 }
2624} 2633}
2625 2634
2626/*! 2635/*!
2627 If \a b is TRUE sets the current format to italic; otherwise sets 2636 If \a b is TRUE sets the current format to italic; otherwise sets
2628 the current format to non-italic. 2637 the current format to non-italic.
2629 2638
2630 \sa italic() 2639 \sa italic()
2631*/ 2640*/
2632 2641
2633void QTextEdit::setItalic( bool b ) 2642void QTextEdit::setItalic( bool b )
2634{ 2643{
2635 QTextFormat f( *currentFormat ); 2644 QTextFormat f( *currentFormat );
2636 f.setItalic( b ); 2645 f.setItalic( b );
2637 QTextFormat *f2 = doc->formatCollection()->format( &f ); 2646 QTextFormat *f2 = doc->formatCollection()->format( &f );
2638 setFormat( f2, QTextFormat::Italic ); 2647 setFormat( f2, QTextFormat::Italic );
2639} 2648}
2640 2649
2641/*! 2650/*!
2642 If \a b is TRUE sets the current format to bold; otherwise sets the 2651 If \a b is TRUE sets the current format to bold; otherwise sets the
2643 current format to non-bold. 2652 current format to non-bold.
@@ -2757,249 +2766,271 @@ QString QTextEdit::text( int para ) const
2757} 2766}
2758 2767
2759/*! 2768/*!
2760 \overload 2769 \overload
2761 2770
2762 Changes the text of the text edit to the string \a text and the 2771 Changes the text of the text edit to the string \a text and the
2763 context to \a context. Any previous text is removed. 2772 context to \a context. Any previous text is removed.
2764 2773
2765 \a text may be interpreted either as plain text or as rich text, 2774 \a text may be interpreted either as plain text or as rich text,
2766 depending on the textFormat(). The default setting is \c AutoText, 2775 depending on the textFormat(). The default setting is \c AutoText,
2767 i.e. the text edit autodetects the format from \a text. 2776 i.e. the text edit autodetects the format from \a text.
2768 2777
2769 The optional \a context is a path which the text edit's 2778 The optional \a context is a path which the text edit's
2770 QMimeSourceFactory uses to resolve the locations of files and images. 2779 QMimeSourceFactory uses to resolve the locations of files and images.
2771 (See \l{QTextEdit::QTextEdit()}.) It is passed to the text edit's 2780 (See \l{QTextEdit::QTextEdit()}.) It is passed to the text edit's
2772 QMimeSourceFactory when quering data. 2781 QMimeSourceFactory when quering data.
2773 2782
2774 Note that the undo/redo history is cleared by this function. 2783 Note that the undo/redo history is cleared by this function.
2775 2784
2776 \sa text(), setTextFormat() 2785 \sa text(), setTextFormat()
2777*/ 2786*/
2778 2787
2779void QTextEdit::setText( const QString &text, const QString &context ) 2788void QTextEdit::setText( const QString &text, const QString &context )
2780{ 2789{
2781 if ( !isModified() && this->context() == context && this->text() == text ) 2790 if ( !isModified() && isReadOnly() &&
2791 this->context() == context && this->text() == text )
2782 return; 2792 return;
2783 2793
2784 emit undoAvailable( FALSE ); 2794 emit undoAvailable( FALSE );
2785 emit redoAvailable( FALSE ); 2795 emit redoAvailable( FALSE );
2786 undoRedoInfo.clear(); 2796 undoRedoInfo.clear();
2787 doc->commands()->clear(); 2797 doc->commands()->clear();
2788 2798
2789 lastFormatted = 0; 2799 lastFormatted = 0;
2790 cursor->restoreState(); 2800 cursor->restoreState();
2791 doc->setText( text, context ); 2801 doc->setText( text, context );
2792 2802
2793 if ( wrapMode == FixedPixelWidth ) { 2803 if ( wrapMode == FixedPixelWidth ) {
2794 resizeContents( wrapWidth, 0 ); 2804 resizeContents( wrapWidth, 0 );
2795 doc->setWidth( wrapWidth ); 2805 doc->setWidth( wrapWidth );
2796 doc->setMinimumWidth( wrapWidth ); 2806 doc->setMinimumWidth( wrapWidth );
2797 } else { 2807 } else {
2798 doc->setMinimumWidth( -1 ); 2808 doc->setMinimumWidth( -1 );
2799 resizeContents( 0, 0 ); 2809 resizeContents( 0, 0 );
2800 } 2810 }
2801 2811
2802 cursor->setDocument( doc ); 2812 lastFormatted = doc->firstParagraph();
2803 lastFormatted = doc->firstParag(); 2813 delete cursor;
2804 cursor->setParag( doc->firstParag() ); 2814 cursor = new QTextCursor( doc );
2805 cursor->setIndex( 0 );
2806 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2815 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
2807 2816
2808 if ( isModified() ) 2817 if ( isModified() )
2809 setModified( FALSE ); 2818 setModified( FALSE );
2810 emit textChanged(); 2819 emit textChanged();
2811 formatMore(); 2820 formatMore();
2812 updateCurrentFormat(); 2821 updateCurrentFormat();
2822 d->scrollToAnchor = QString::null;
2813} 2823}
2814 2824
2815/*! 2825/*!
2816 \property QTextEdit::text 2826 \property QTextEdit::text
2817 \brief the text edit's text 2827 \brief the text edit's text
2818 2828
2819 There is no default text. 2829 There is no default text.
2820 2830
2821 On setting, any previous text is deleted. 2831 On setting, any previous text is deleted.
2822 2832
2823 The text may be interpreted either as plain text or as rich text, 2833 The text may be interpreted either as plain text or as rich text,
2824 depending on the textFormat(). The default setting is \c AutoText, 2834 depending on the textFormat(). The default setting is \c AutoText,
2825 i.e. the text edit autodetects the format of the text. 2835 i.e. the text edit autodetects the format of the text.
2826 2836
2827 For richtext, calling text() on an editable QTextEdit will cause the text 2837 For richtext, calling text() on an editable QTextEdit will cause the text
2828 to be regenerated from the textedit. This may mean that the QString returned 2838 to be regenerated from the textedit. This may mean that the QString returned
2829 may not be exactly the same as the one that was set. 2839 may not be exactly the same as the one that was set.
2830 2840
2831 \sa textFormat 2841 \sa textFormat
2832*/ 2842*/
2833 2843
2834 2844
2835/*! 2845/*!
2836 \property QTextEdit::readOnly 2846 \property QTextEdit::readOnly
2837 \brief whether the text edit is read-only 2847 \brief whether the text edit is read-only
2838 2848
2839 In a read-only text edit the user can only navigate through the text 2849 In a read-only text edit the user can only navigate through the text
2840 and select text; modifying the text is not possible. 2850 and select text; modifying the text is not possible.
2841 2851
2842 This property's default is FALSE. 2852 This property's default is FALSE.
2843*/ 2853*/
2844 2854
2845/*! 2855/*!
2846 Finds the next occurrence of the string, \a expr. Returns TRUE if 2856 Finds the next occurrence of the string, \a expr. Returns TRUE if
2847 \a expr is found; otherwise returns FALSE. 2857 \a expr is found; otherwise returns FALSE.
2848 2858
2849 If \a para and \a index are both null the search begins from the 2859 If \a para and \a index are both null the search begins from the
2850 start of the text. If \a para and \a index are both not null, the 2860 current cursor position. If \a para and \a index are both not
2851 search begins from the \e *\a index character position in the \e 2861 null, the search begins from the \e *\a index character position
2852 *\a para paragraph. 2862 in the \e *\a para paragraph.
2853 2863
2854 If \a cs is TRUE the search is case sensitive, otherwise it is 2864 If \a cs is TRUE the search is case sensitive, otherwise it is
2855 case insensitive. If \a wo is TRUE the search looks for whole word 2865 case insensitive. If \a wo is TRUE the search looks for whole word
2856 matches only; otherwise it searches for any matching text. If \a 2866 matches only; otherwise it searches for any matching text. If \a
2857 forward is TRUE (the default) the search works forward from the 2867 forward is TRUE (the default) the search works forward from the
2858 starting position to the end of the text, otherwise it works 2868 starting position to the end of the text, otherwise it works
2859 backwards to the beginning of the text. 2869 backwards to the beginning of the text.
2860 2870
2861 If \a expr is found the function returns TRUE. If \a index and \a 2871 If \a expr is found the function returns TRUE. If \a index and \a
2862 para are not null, the number of the paragraph in which the first 2872 para are not null, the number of the paragraph in which the first
2863 character of the match was found is put into \e *\a para, and the 2873 character of the match was found is put into \e *\a para, and the
2864 index position of that character within the paragraph is put into 2874 index position of that character within the paragraph is put into
2865 \e *\a index. 2875 \e *\a index.
2866 2876
2867 If \a expr is not found the function returns FALSE. If \a index 2877 If \a expr is not found the function returns FALSE. If \a index
2868 and \a para are not null and \a expr is not found, \e *\a index 2878 and \a para are not null and \a expr is not found, \e *\a index
2869 and \e *\a para are undefined. 2879 and \e *\a para are undefined.
2870*/ 2880*/
2871 2881
2872bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward, 2882bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward,
2873 int *para, int *index ) 2883 int *para, int *index )
2874{ 2884{
2875 drawCursor( FALSE ); 2885 drawCursor( FALSE );
2876 doc->removeSelection( QTextDocument::Standard );
2877#ifndef QT_NO_CURSOR 2886#ifndef QT_NO_CURSOR
2878 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 2887 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
2879#endif 2888#endif
2880 bool found = doc->find( expr, cs, wo, forward, para, index, cursor ); 2889 QTextCursor findcur = *cursor;
2890 if ( para && index ) {
2891 if ( doc->paragAt( *para ) )
2892 findcur.gotoPosition( doc->paragAt(*para), *index );
2893 else
2894 findcur.gotoEnd();
2895 } else if ( doc->hasSelection( QTextDocument::Standard ) ){
2896 // maks sure we do not find the same selection again
2897 if ( forward )
2898 findcur.gotoNextLetter();
2899 else
2900 findcur.gotoPreviousLetter();
2901 }
2902 removeSelection( QTextDocument::Standard );
2903 bool found = doc->find( findcur, expr, cs, wo, forward );
2904 if ( found ) {
2905 if ( para )
2906 *para = findcur.paragraph()->paragId();
2907 if ( index )
2908 *index = findcur.index();
2909 *cursor = findcur;
2910 repaintChanged();
2881 ensureCursorVisible(); 2911 ensureCursorVisible();
2912 }
2882 drawCursor( TRUE ); 2913 drawCursor( TRUE );
2883 repaintChanged();
2884 return found; 2914 return found;
2885} 2915}
2886 2916
2887void QTextEdit::blinkCursor() 2917void QTextEdit::blinkCursor()
2888{ 2918{
2889 if ( !cursorVisible ) 2919 if ( !cursorVisible )
2890 return; 2920 return;
2891 bool cv = cursorVisible; 2921 bool cv = cursorVisible;
2892 blinkCursorVisible = !blinkCursorVisible; 2922 blinkCursorVisible = !blinkCursorVisible;
2893 drawCursor( blinkCursorVisible ); 2923 drawCursor( blinkCursorVisible );
2894 cursorVisible = cv; 2924 cursorVisible = cv;
2895} 2925}
2896 2926
2897/*! 2927/*!
2898 Sets the cursor to position \a index in paragraph \a para. 2928 Sets the cursor to position \a index in paragraph \a para.
2899 2929
2900 \sa getCursorPosition() 2930 \sa getCursorPosition()
2901*/ 2931*/
2902 2932
2903void QTextEdit::setCursorPosition( int para, int index ) 2933void QTextEdit::setCursorPosition( int para, int index )
2904{ 2934{
2905 QTextParag *p = doc->paragAt( para ); 2935 QTextParagraph *p = doc->paragAt( para );
2906 if ( !p ) 2936 if ( !p )
2907 return; 2937 return;
2908 2938
2909 if ( index > p->length() - 1 ) 2939 if ( index > p->length() - 1 )
2910 index = p->length() - 1; 2940 index = p->length() - 1;
2911 2941
2912 drawCursor( FALSE ); 2942 drawCursor( FALSE );
2913 cursor->setParag( p ); 2943 cursor->setParagraph( p );
2914 cursor->setIndex( index ); 2944 cursor->setIndex( index );
2915 ensureCursorVisible(); 2945 ensureCursorVisible();
2916 drawCursor( TRUE ); 2946 drawCursor( TRUE );
2947 updateCurrentFormat();
2917 emit cursorPositionChanged( cursor ); 2948 emit cursorPositionChanged( cursor );
2918 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 2949 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
2919} 2950}
2920 2951
2921/*! 2952/*!
2922 This function sets the \e *\a para and \e *\a index parameters to the 2953 This function sets the \e *\a para and \e *\a index parameters to the
2923 current cursor position. \a para and \a index must be non-null int 2954 current cursor position. \a para and \a index must be non-null int
2924 pointers. 2955 pointers.
2925 2956
2926 \sa setCursorPosition() 2957 \sa setCursorPosition()
2927 */ 2958 */
2928 2959
2929void QTextEdit::getCursorPosition( int *para, int *index ) const 2960void QTextEdit::getCursorPosition( int *para, int *index ) const
2930{ 2961{
2931 if ( !para || !index ) 2962 if ( !para || !index )
2932 return; 2963 return;
2933 *para = cursor->parag()->paragId(); 2964 *para = cursor->paragraph()->paragId();
2934 *index = cursor->index(); 2965 *index = cursor->index();
2935} 2966}
2936 2967
2937/*! Sets a selection which starts at position \a indexFrom in 2968/*! Sets a selection which starts at position \a indexFrom in
2938 paragraph \a paraFrom and ends at position \a indexTo in paragraph 2969 paragraph \a paraFrom and ends at position \a indexTo in paragraph
2939 \a paraTo. Existing selections which have a different id (selNum) 2970 \a paraTo. Existing selections which have a different id (selNum)
2940 are not removed, existing selections which have the same id as \a 2971 are not removed, existing selections which have the same id as \a
2941 selNum are removed. 2972 selNum are removed.
2942 2973
2943 Uses the selection settings of selection \a selNum. If \a selNum is 0, 2974 Uses the selection settings of selection \a selNum. If \a selNum is 0,
2944 this is the default selection. 2975 this is the default selection.
2945 2976
2946 The cursor is moved to the end of the selection if \a selNum is 0, 2977 The cursor is moved to the end of the selection if \a selNum is 0,
2947 otherwise the cursor position remains unchanged. 2978 otherwise the cursor position remains unchanged.
2948 2979
2949 \sa getSelection() selectedText 2980 \sa getSelection() selectedText
2950*/ 2981*/
2951 2982
2952void QTextEdit::setSelection( int paraFrom, int indexFrom, 2983void QTextEdit::setSelection( int paraFrom, int indexFrom,
2953 int paraTo, int indexTo, int selNum ) 2984 int paraTo, int indexTo, int selNum )
2954{ 2985{
2955 if ( doc->hasSelection( selNum ) ) { 2986 if ( doc->hasSelection( selNum ) ) {
2956 doc->removeSelection( selNum ); 2987 doc->removeSelection( selNum );
2957 repaintChanged(); 2988 repaintChanged();
2958 } 2989 }
2959 if ( selNum > doc->numSelections() - 1 ) 2990 if ( selNum > doc->numSelections() - 1 )
2960 doc->addSelection( selNum ); 2991 doc->addSelection( selNum );
2961 QTextParag *p1 = doc->paragAt( paraFrom ); 2992 QTextParagraph *p1 = doc->paragAt( paraFrom );
2962 if ( !p1 ) 2993 if ( !p1 )
2963 return; 2994 return;
2964 QTextParag *p2 = doc->paragAt( paraTo ); 2995 QTextParagraph *p2 = doc->paragAt( paraTo );
2965 if ( !p2 ) 2996 if ( !p2 )
2966 return; 2997 return;
2967 2998
2968 if ( indexFrom > p1->length() - 1 ) 2999 if ( indexFrom > p1->length() - 1 )
2969 indexFrom = p1->length() - 1; 3000 indexFrom = p1->length() - 1;
2970 if ( indexTo > p2->length() - 1 ) 3001 if ( indexTo > p2->length() - 1 )
2971 indexTo = p2->length() - 1; 3002 indexTo = p2->length() - 1;
2972 3003
2973 drawCursor( FALSE ); 3004 drawCursor( FALSE );
2974 QTextCursor c = *cursor; 3005 QTextCursor c = *cursor;
2975 QTextCursor oldCursor = *cursor; 3006 QTextCursor oldCursor = *cursor;
2976 c.setParag( p1 ); 3007 c.setParagraph( p1 );
2977 c.setIndex( indexFrom ); 3008 c.setIndex( indexFrom );
2978 cursor->setParag( p2 ); 3009 cursor->setParagraph( p2 );
2979 cursor->setIndex( indexTo ); 3010 cursor->setIndex( indexTo );
2980 doc->setSelectionStart( selNum, &c ); 3011 doc->setSelectionStart( selNum, c );
2981 doc->setSelectionEnd( selNum, cursor ); 3012 doc->setSelectionEnd( selNum, *cursor );
2982 repaintChanged(); 3013 repaintChanged();
2983 ensureCursorVisible(); 3014 ensureCursorVisible();
2984 if ( selNum != QTextDocument::Standard ) 3015 if ( selNum != QTextDocument::Standard )
2985 *cursor = oldCursor; 3016 *cursor = oldCursor;
2986 drawCursor( TRUE ); 3017 drawCursor( TRUE );
2987} 3018}
2988 3019
2989/*! 3020/*!
2990 If there is a selection, \e *\a paraFrom is set to the number of the 3021 If there is a selection, \e *\a paraFrom is set to the number of the
2991 paragraph in which the selection begins and \e *\a paraTo is set to 3022 paragraph in which the selection begins and \e *\a paraTo is set to
2992 the number of the paragraph in which the selection ends. (They could 3023 the number of the paragraph in which the selection ends. (They could
2993 be the same.) \e *\a indexFrom is set to the index at which the 3024 be the same.) \e *\a indexFrom is set to the index at which the
2994 selection begins within \e *\a paraFrom, and \e *\a indexTo is set to 3025 selection begins within \e *\a paraFrom, and \e *\a indexTo is set to
2995 the index at which the selection ends within \e *\a paraTo. 3026 the index at which the selection ends within \e *\a paraTo.
2996 3027
2997 If there is no selection, \e *\a paraFrom, \e *\a indexFrom, \e *\a 3028 If there is no selection, \e *\a paraFrom, \e *\a indexFrom, \e *\a
2998 paraTo and \e *\a indexTo are all set to -1. 3029 paraTo and \e *\a indexTo are all set to -1.
2999 3030
3000 \a paraFrom, \a indexFrom, \a paraTo and \a indexTo must be non-null 3031 \a paraFrom, \a indexFrom, \a paraTo and \a indexTo must be non-null
3001 int pointers. 3032 int pointers.
3002 3033
3003 The \a selNum is the number of the selection (multiple selections 3034 The \a selNum is the number of the selection (multiple selections
3004 are supported). It defaults to 0 (the default selection). 3035 are supported). It defaults to 0 (the default selection).
3005 3036
@@ -3035,108 +3066,108 @@ void QTextEdit::getSelection( int *paraFrom, int *indexFrom,
3035 \i RichText - rich text rendering. The available styles are 3066 \i RichText - rich text rendering. The available styles are
3036 defined in the default stylesheet QStyleSheet::defaultSheet(). 3067 defined in the default stylesheet QStyleSheet::defaultSheet().
3037 \i AutoText - this is the default. The text edit autodetects 3068 \i AutoText - this is the default. The text edit autodetects
3038 which rendering style is best, \c PlainText or \c RichText. This is 3069 which rendering style is best, \c PlainText or \c RichText. This is
3039 done by using the QStyleSheet::mightBeRichText() function. 3070 done by using the QStyleSheet::mightBeRichText() function.
3040 \endlist 3071 \endlist
3041*/ 3072*/
3042 3073
3043void QTextEdit::setTextFormat( TextFormat format ) 3074void QTextEdit::setTextFormat( TextFormat format )
3044{ 3075{
3045 doc->setTextFormat( format ); 3076 doc->setTextFormat( format );
3046} 3077}
3047 3078
3048Qt::TextFormat QTextEdit::textFormat() const 3079Qt::TextFormat QTextEdit::textFormat() const
3049{ 3080{
3050 return doc->textFormat(); 3081 return doc->textFormat();
3051} 3082}
3052 3083
3053/*! 3084/*!
3054 Returns the number of paragraphs in the text; this could be 0. 3085 Returns the number of paragraphs in the text; this could be 0.
3055*/ 3086*/
3056 3087
3057int QTextEdit::paragraphs() const 3088int QTextEdit::paragraphs() const
3058{ 3089{
3059 return doc->lastParag()->paragId() + 1; 3090 return doc->lastParagraph()->paragId() + 1;
3060} 3091}
3061 3092
3062/*! 3093/*!
3063 Returns the number of lines in paragraph \a para, or -1 if there 3094 Returns the number of lines in paragraph \a para, or -1 if there
3064 is no paragraph with index \a para. 3095 is no paragraph with index \a para.
3065*/ 3096*/
3066 3097
3067int QTextEdit::linesOfParagraph( int para ) const 3098int QTextEdit::linesOfParagraph( int para ) const
3068{ 3099{
3069 QTextParag *p = doc->paragAt( para ); 3100 QTextParagraph *p = doc->paragAt( para );
3070 if ( !p ) 3101 if ( !p )
3071 return -1; 3102 return -1;
3072 return p->lines(); 3103 return p->lines();
3073} 3104}
3074 3105
3075/*! 3106/*!
3076 Returns the length of the paragraph \a para (number of 3107 Returns the length of the paragraph \a para (number of
3077 characters), or -1 if there is no paragraph with index \a para 3108 characters), or -1 if there is no paragraph with index \a para
3078*/ 3109*/
3079 3110
3080int QTextEdit::paragraphLength( int para ) const 3111int QTextEdit::paragraphLength( int para ) const
3081{ 3112{
3082 QTextParag *p = doc->paragAt( para ); 3113 QTextParagraph *p = doc->paragAt( para );
3083 if ( !p ) 3114 if ( !p )
3084 return -1; 3115 return -1;
3085 return p->length() - 1; 3116 return p->length() - 1;
3086} 3117}
3087 3118
3088/*! 3119/*!
3089 Returns the number of lines in the text edit; this could be 0. 3120 Returns the number of lines in the text edit; this could be 0.
3090 3121
3091 \warning This function may be slow. Lines change all the time 3122 \warning This function may be slow. Lines change all the time
3092 during word wrapping, so this function has to iterate over all the 3123 during word wrapping, so this function has to iterate over all the
3093 paragraphs and get the number of lines from each one individually. 3124 paragraphs and get the number of lines from each one individually.
3094*/ 3125*/
3095 3126
3096int QTextEdit::lines() const 3127int QTextEdit::lines() const
3097{ 3128{
3098 QTextParag *p = doc->firstParag(); 3129 QTextParagraph *p = doc->firstParagraph();
3099 int l = 0; 3130 int l = 0;
3100 while ( p ) { 3131 while ( p ) {
3101 l += p->lines(); 3132 l += p->lines();
3102 p = p->next(); 3133 p = p->next();
3103 } 3134 }
3104 3135
3105 return l; 3136 return l;
3106} 3137}
3107 3138
3108/*! 3139/*!
3109 Returns the line number of the line in paragraph \a para in which 3140 Returns the line number of the line in paragraph \a para in which
3110 the character at position \a index appears. The \a index position is 3141 the character at position \a index appears. The \a index position is
3111 relative to the beginning of the paragraph. If there is no such 3142 relative to the beginning of the paragraph. If there is no such
3112 paragraph or no such character at the \a index position (e.g. the 3143 paragraph or no such character at the \a index position (e.g. the
3113 index is out of range) -1 is returned. 3144 index is out of range) -1 is returned.
3114*/ 3145*/
3115 3146
3116int QTextEdit::lineOfChar( int para, int index ) 3147int QTextEdit::lineOfChar( int para, int index )
3117{ 3148{
3118 QTextParag *p = doc->paragAt( para ); 3149 QTextParagraph *p = doc->paragAt( para );
3119 if ( !p ) 3150 if ( !p )
3120 return -1; 3151 return -1;
3121 3152
3122 int idx, line; 3153 int idx, line;
3123 QTextStringChar *c = p->lineStartOfChar( index, &idx, &line ); 3154 QTextStringChar *c = p->lineStartOfChar( index, &idx, &line );
3124 if ( !c ) 3155 if ( !c )
3125 return -1; 3156 return -1;
3126 3157
3127 return line; 3158 return line;
3128} 3159}
3129 3160
3130void QTextEdit::setModified( bool m ) 3161void QTextEdit::setModified( bool m )
3131{ 3162{
3132 bool oldModified = modified; 3163 bool oldModified = modified;
3133 modified = m; 3164 modified = m;
3134 if ( modified && doc->oTextValid ) 3165 if ( modified && doc->oTextValid )
3135 doc->invalidateOriginalText(); 3166 doc->invalidateOriginalText();
3136 if ( oldModified != modified ) 3167 if ( oldModified != modified )
3137 emit modificationChanged( modified ); 3168 emit modificationChanged( modified );
3138} 3169}
3139 3170
3140/*! \property QTextEdit::modified 3171/*! \property QTextEdit::modified
3141 \brief whether the document has been modified by the user 3172 \brief whether the document has been modified by the user
3142*/ 3173*/
@@ -3227,141 +3258,139 @@ QColor QTextEdit::color() const
3227 3258
3228*/ 3259*/
3229 3260
3230QFont QTextEdit::font() const 3261QFont QTextEdit::font() const
3231{ 3262{
3232 return currentFormat->font(); 3263 return currentFormat->font();
3233} 3264}
3234 3265
3235/*! 3266/*!
3236 Returns the alignment of the current paragraph. 3267 Returns the alignment of the current paragraph.
3237 3268
3238 \sa setAlignment() 3269 \sa setAlignment()
3239*/ 3270*/
3240 3271
3241int QTextEdit::alignment() const 3272int QTextEdit::alignment() const
3242{ 3273{
3243 return currentAlignment; 3274 return currentAlignment;
3244} 3275}
3245 3276
3246void QTextEdit::startDrag() 3277void QTextEdit::startDrag()
3247{ 3278{
3248#ifndef QT_NO_DRAGANDDROP 3279#ifndef QT_NO_DRAGANDDROP
3249 mousePressed = FALSE; 3280 mousePressed = FALSE;
3250 inDoubleClick = FALSE; 3281 inDoubleClick = FALSE;
3251 QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard ), viewport() ); 3282 QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ), viewport() );
3252 if ( isReadOnly() ) { 3283 if ( isReadOnly() ) {
3253 drag->dragCopy(); 3284 drag->dragCopy();
3254 } else { 3285 } else {
3255 if ( drag->drag() && QDragObject::target() != this && QDragObject::target() != viewport() ) 3286 if ( drag->drag() && QDragObject::target() != this && QDragObject::target() != viewport() )
3256 removeSelectedText(); 3287 removeSelectedText();
3257 } 3288 }
3258#endif 3289#endif
3259} 3290}
3260 3291
3261/*! 3292/*!
3262 If \a select is TRUE (the default), all the text is selected as 3293 If \a select is TRUE (the default), all the text is selected as
3263 selection 0. 3294 selection 0.
3264 If \a select is FALSE any selected text is unselected, i.e., the 3295 If \a select is FALSE any selected text is unselected, i.e., the
3265 default selection (selection 0) is cleared. 3296 default selection (selection 0) is cleared.
3266 3297
3267 \sa selectedText 3298 \sa selectedText
3268*/ 3299*/
3269 3300
3270void QTextEdit::selectAll( bool select ) 3301void QTextEdit::selectAll( bool select )
3271{ 3302{
3272 if ( !select ) 3303 if ( !select )
3273 doc->removeSelection( QTextDocument::Standard ); 3304 doc->removeSelection( QTextDocument::Standard );
3274 else 3305 else
3275 doc->selectAll( QTextDocument::Standard ); 3306 doc->selectAll( QTextDocument::Standard );
3276 repaintChanged(); 3307 repaintChanged();
3277 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); 3308 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
3278 emit selectionChanged(); 3309 emit selectionChanged();
3279#ifndef QT_NO_CURSOR 3310#ifndef QT_NO_CURSOR
3280 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 3311 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
3281#endif 3312#endif
3282} 3313}
3283 3314
3284void QTextEdit::UndoRedoInfo::clear() 3315void QTextEdit::UndoRedoInfo::clear()
3285{ 3316{
3286 if ( valid() ) { 3317 if ( valid() ) {
3287 if ( type == Insert || type == Return ) 3318 if ( type == Insert || type == Return )
3288 doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); 3319 doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) );
3289 else if ( type == Format ) 3320 else if ( type == Format )
3290 doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); 3321 doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) );
3291 else if ( type == Alignment ) 3322 else if ( type == Style )
3292 doc->addCommand( new QTextAlignmentCommand( doc, id, eid, newAlign, oldAligns ) ); 3323 doc->addCommand( new QTextStyleCommand( doc, id, eid, styleInformation ) );
3293 else if ( type == ParagType ) 3324 else if ( type != Invalid ) {
3294 doc->addCommand( new QTextParagTypeCommand( doc, id, eid, list, listStyle, oldStyles, oldListStyles ) ); 3325 doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) );
3295 else if ( type != Invalid ) 3326 }
3296 doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) );
3297 } 3327 }
3328 type = Invalid;
3298 d->text = QString::null; 3329 d->text = QString::null;
3299 id = -1; 3330 id = -1;
3300 index = -1; 3331 index = -1;
3301 oldStyles.clear(); 3332 styleInformation = QByteArray();
3302 oldListStyles.clear();
3303 oldAligns.resize( 0 );
3304} 3333}
3305 3334
3306 3335
3307/*! 3336/*!
3308 If there is some selected text (in selection 0) it is deleted. If 3337 If there is some selected text (in selection 0) it is deleted. If
3309 there is no selected text (in selection 0) the character to the 3338 there is no selected text (in selection 0) the character to the
3310 right of the text cursor is deleted. 3339 right of the text cursor is deleted.
3311 3340
3312 \sa removeSelectedText() cut() 3341 \sa removeSelectedText() cut()
3313 3342
3314*/ 3343*/
3315 3344
3316void QTextEdit::del() 3345void QTextEdit::del()
3317{ 3346{
3318 if ( doc->hasSelection( QTextDocument::Standard ) ) { 3347 if ( doc->hasSelection( QTextDocument::Standard ) ) {
3319 removeSelectedText(); 3348 removeSelectedText();
3320 return; 3349 return;
3321 } 3350 }
3322 3351
3323 doKeyboardAction( ActionDelete ); 3352 doKeyboardAction( ActionDelete );
3324} 3353}
3325 3354
3326 3355
3327QTextEdit::UndoRedoInfo::UndoRedoInfo( QTextDocument *dc ) 3356QTextEdit::UndoRedoInfo::UndoRedoInfo( QTextDocument *dc )
3328 : type( Invalid ), doc( dc ) 3357 : type( Invalid ), doc( dc )
3329{ 3358{
3330 d = new QUndoRedoInfoPrivate; 3359 d = new QUndoRedoInfoPrivate;
3331 d->text = QString::null; 3360 d->text = QString::null;
3332 id = -1; 3361 id = -1;
3333 index = -1; 3362 index = -1;
3334} 3363}
3335 3364
3336QTextEdit::UndoRedoInfo::~UndoRedoInfo() 3365QTextEdit::UndoRedoInfo::~UndoRedoInfo()
3337{ 3366{
3338 delete d; 3367 delete d;
3339} 3368}
3340 3369
3341bool QTextEdit::UndoRedoInfo::valid() const 3370bool QTextEdit::UndoRedoInfo::valid() const
3342{ 3371{
3343 return d->text.length() > 0 && id >= 0 && index >= 0; 3372 return id >= 0 && type != Invalid;
3344} 3373}
3345 3374
3346/*! 3375/*!
3347 \internal 3376 \internal
3348 3377
3349 Resets the current format to the default format. 3378 Resets the current format to the default format.
3350*/ 3379*/
3351 3380
3352void QTextEdit::resetFormat() 3381void QTextEdit::resetFormat()
3353{ 3382{
3354 setAlignment( Qt3::AlignAuto ); 3383 setAlignment( Qt3::AlignAuto );
3355 setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc ); 3384 setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc );
3356 setFormat( doc->formatCollection()->defaultFormat(), QTextFormat::Format ); 3385 setFormat( doc->formatCollection()->defaultFormat(), QTextFormat::Format );
3357} 3386}
3358 3387
3359/*! Returns the QStyleSheet which is currently used in this text edit. 3388/*! Returns the QStyleSheet which is currently used in this text edit.
3360 3389
3361 \sa setStyleSheet() 3390 \sa setStyleSheet()
3362 */ 3391 */
3363 3392
3364QStyleSheet* QTextEdit::styleSheet() const 3393QStyleSheet* QTextEdit::styleSheet() const
3365{ 3394{
3366 return doc->styleSheet(); 3395 return doc->styleSheet();
3367} 3396}
@@ -3388,52 +3417,49 @@ void QTextEdit::setStyleSheet( QStyleSheet* styleSheet )
3388void QTextEdit::setPaper( const QBrush& pap ) 3417void QTextEdit::setPaper( const QBrush& pap )
3389{ 3418{
3390 doc->setPaper( new QBrush( pap ) ); 3419 doc->setPaper( new QBrush( pap ) );
3391 viewport()->setBackgroundColor( pap.color() ); 3420 viewport()->setBackgroundColor( pap.color() );
3392 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 3421 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3393} 3422}
3394 3423
3395QBrush QTextEdit::paper() const 3424QBrush QTextEdit::paper() const
3396{ 3425{
3397 if ( doc->paper() ) 3426 if ( doc->paper() )
3398 return *doc->paper(); 3427 return *doc->paper();
3399 return QBrush(); 3428 return QBrush();
3400} 3429}
3401 3430
3402/*! 3431/*!
3403 \property QTextEdit::linkUnderline 3432 \property QTextEdit::linkUnderline
3404 \brief whether hypertext links will be underlined 3433 \brief whether hypertext links will be underlined
3405 3434
3406 If TRUE (the default) hypertext links will be displayed underlined. 3435 If TRUE (the default) hypertext links will be displayed underlined.
3407 If FALSE links will not be displayed underlined. 3436 If FALSE links will not be displayed underlined.
3408*/ 3437*/
3409 3438
3410void QTextEdit::setLinkUnderline( bool b ) 3439void QTextEdit::setLinkUnderline( bool b )
3411{ 3440{
3412 if ( b == doc->underlineLinks() )
3413 return;
3414 doc->setUnderlineLinks( b ); 3441 doc->setUnderlineLinks( b );
3415 updateStyles();
3416} 3442}
3417 3443
3418bool QTextEdit::linkUnderline() const 3444bool QTextEdit::linkUnderline() const
3419{ 3445{
3420 return doc->underlineLinks(); 3446 return doc->underlineLinks();
3421} 3447}
3422 3448
3423/*! Sets the text edit's mimesource factory to \a factory. See 3449/*! Sets the text edit's mimesource factory to \a factory. See
3424 QMimeSourceFactory for further details. 3450 QMimeSourceFactory for further details.
3425 3451
3426 \sa mimeSourceFactory() 3452 \sa mimeSourceFactory()
3427 */ 3453 */
3428 3454
3429void QTextEdit::setMimeSourceFactory( QMimeSourceFactory* factory ) 3455void QTextEdit::setMimeSourceFactory( QMimeSourceFactory* factory )
3430{ 3456{
3431 doc->setMimeSourceFactory( factory ); 3457 doc->setMimeSourceFactory( factory );
3432} 3458}
3433 3459
3434/*! Returns the QMimeSourceFactory which is currently used by this 3460/*! Returns the QMimeSourceFactory which is currently used by this
3435 text edit. 3461 text edit.
3436 3462
3437 \sa setMimeSourceFactory() 3463 \sa setMimeSourceFactory()
3438*/ 3464*/
3439 3465
@@ -3444,89 +3470,90 @@ QMimeSourceFactory* QTextEdit::mimeSourceFactory() const
3444 3470
3445/*! 3471/*!
3446 Returns how many pixels high the text edit needs to be to display 3472 Returns how many pixels high the text edit needs to be to display
3447 all the text if the text edit is \a w pixels wide. 3473 all the text if the text edit is \a w pixels wide.
3448*/ 3474*/
3449 3475
3450int QTextEdit::heightForWidth( int w ) const 3476int QTextEdit::heightForWidth( int w ) const
3451{ 3477{
3452 int oldw = doc->width(); 3478 int oldw = doc->width();
3453 doc->doLayout( 0, w ); 3479 doc->doLayout( 0, w );
3454 int h = doc->height(); 3480 int h = doc->height();
3455 doc->setWidth( oldw ); 3481 doc->setWidth( oldw );
3456 doc->invalidate(); 3482 doc->invalidate();
3457 ( (QTextEdit*)this )->formatMore(); 3483 ( (QTextEdit*)this )->formatMore();
3458 return h; 3484 return h;
3459} 3485}
3460 3486
3461/*! Appends the text \a text to the end of the text edit. 3487/*! Appends the text \a text to the end of the text edit.
3462 Note that the undo/redo history is cleared by this function. 3488 Note that the undo/redo history is cleared by this function.
3463 */ 3489 */
3464 3490
3465void QTextEdit::append( const QString &text ) 3491void QTextEdit::append( const QString &text )
3466{ 3492{
3467 // flush and clear the undo/redo stack if necessary 3493 // flush and clear the undo/redo stack if necessary
3468 if ( isReadOnly() && undoRedoInfo.valid() ) {
3469 undoRedoInfo.clear(); 3494 undoRedoInfo.clear();
3470 doc->commands()->clear(); 3495 doc->commands()->clear();
3471 } 3496
3472 doc->removeSelection( QTextDocument::Standard ); 3497 doc->removeSelection( QTextDocument::Standard );
3473 TextFormat f = doc->textFormat(); 3498 TextFormat f = doc->textFormat();
3474 if ( f == AutoText ) { 3499 if ( f == AutoText ) {
3475 if ( QStyleSheet::mightBeRichText( text ) ) 3500 if ( QStyleSheet::mightBeRichText( text ) )
3476 f = RichText; 3501 f = RichText;
3477 else 3502 else
3478 f = PlainText; 3503 f = PlainText;
3479 } 3504 }
3480 if ( f == PlainText ) { 3505
3506 drawCursor( FALSE );
3481 QTextCursor oldc( *cursor ); 3507 QTextCursor oldc( *cursor );
3482 ensureFormatted( doc->lastParag() ); 3508 ensureFormatted( doc->lastParagraph() );
3483 bool scrollToEnd = contentsY() >= contentsHeight() - visibleHeight() - 3509 bool atBottom = contentsY() >= contentsHeight() - visibleHeight();
3484 ( horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0 );
3485 if ( !scrollToEnd )
3486 blockEnsureCursorVisible = TRUE;
3487 cursor->gotoEnd(); 3510 cursor->gotoEnd();
3488 if ( cursor->index() > 0 ) 3511 if ( cursor->index() > 0 )
3489 cursor->splitAndInsertEmptyParag(); 3512 cursor->splitAndInsertEmptyParagraph();
3490 QTextCursor oldCursor2 = *cursor; 3513 QTextCursor oldCursor2 = *cursor;
3514
3515 if ( f == Qt::PlainText ) {
3491 cursor->insert( text, TRUE ); 3516 cursor->insert( text, TRUE );
3492 if ( doc->useFormatCollection() && currentFormat != cursor->parag()->at( cursor->index() )->format() ) { 3517 if ( doc->useFormatCollection() &&
3493 doc->setSelectionStart( QTextDocument::Temp, &oldCursor2 ); 3518 currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) {
3494 doc->setSelectionEnd( QTextDocument::Temp, cursor ); 3519 doc->setSelectionStart( QTextDocument::Temp, oldCursor2 );
3520 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
3495 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); 3521 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format );
3496 doc->removeSelection( QTextDocument::Temp ); 3522 doc->removeSelection( QTextDocument::Temp );
3497 } 3523 }
3524 } else {
3525 if ( cursor->paragraph()->prev() )
3526 cursor->paragraph()->prev()->invalidate(0); // vertical margins might have to change
3527 doc->setRichTextInternal( text );
3528 }
3498 formatMore(); 3529 formatMore();
3499 repaintChanged(); 3530 repaintChanged();
3500 ensureCursorVisible(); 3531 if ( atBottom )
3501 drawCursor( TRUE ); 3532 scrollToBottom();
3502 *cursor = oldc; 3533 *cursor = oldc;
3503 if ( !scrollToEnd ) 3534 if ( !isReadOnly() )
3504 blockEnsureCursorVisible = FALSE; 3535 cursorVisible = TRUE;
3505 } else if ( f == RichText ) {
3506 doc->setRichTextInternal( text );
3507 repaintChanged();
3508 }
3509 setModified(); 3536 setModified();
3510 emit textChanged(); 3537 emit textChanged();
3511} 3538}
3512 3539
3513/*! \property QTextEdit::hasSelectedText 3540/*! \property QTextEdit::hasSelectedText
3514 \brief whether some text is selected in selection 0 3541 \brief whether some text is selected in selection 0
3515 */ 3542 */
3516 3543
3517bool QTextEdit::hasSelectedText() const 3544bool QTextEdit::hasSelectedText() const
3518{ 3545{
3519 return doc->hasSelection( QTextDocument::Standard ); 3546 return doc->hasSelection( QTextDocument::Standard );
3520} 3547}
3521 3548
3522/*!\property QTextEdit::selectedText 3549/*!\property QTextEdit::selectedText
3523 \brief The selected text (from selection 0) or an empty string if 3550 \brief The selected text (from selection 0) or an empty string if
3524 there is no currently selected text (in selection 0). 3551 there is no currently selected text (in selection 0).
3525 3552
3526 The text is always returned as \c PlainText regardless of the text 3553 The text is always returned as \c PlainText regardless of the text
3527 format. In a future version of Qt an HTML subset \e may be returned 3554 format. In a future version of Qt an HTML subset \e may be returned
3528 depending on the text format. 3555 depending on the text format.
3529 3556
3530 \sa hasSelectedText 3557 \sa hasSelectedText
3531 */ 3558 */
3532 3559
@@ -3596,135 +3623,186 @@ bool QTextEdit::handleReadOnlyKeyEvent( QKeyEvent *e )
3596 uses to resolve the locations of files and images. 3623 uses to resolve the locations of files and images.
3597 3624
3598 \sa text 3625 \sa text
3599*/ 3626*/
3600 3627
3601QString QTextEdit::context() const 3628QString QTextEdit::context() const
3602{ 3629{
3603 return doc->context(); 3630 return doc->context();
3604} 3631}
3605 3632
3606/*! 3633/*!
3607 \property QTextEdit::documentTitle 3634 \property QTextEdit::documentTitle
3608 \brief the title of the document parsed from the text. 3635 \brief the title of the document parsed from the text.
3609 3636
3610 For \c PlainText the title will be an empty string. For \c RichText 3637 For \c PlainText the title will be an empty string. For \c RichText
3611 the title will be the text between the \c{<title>} tags, if present, 3638 the title will be the text between the \c{<title>} tags, if present,
3612 otherwise an empty string. 3639 otherwise an empty string.
3613*/ 3640*/
3614 3641
3615QString QTextEdit::documentTitle() const 3642QString QTextEdit::documentTitle() const
3616{ 3643{
3617 return doc->attributes()[ "title" ]; 3644 return doc->attributes()[ "title" ];
3618} 3645}
3619 3646
3620void QTextEdit::makeParagVisible( QTextParag *p ) 3647void QTextEdit::makeParagVisible( QTextParagraph *p )
3621{ 3648{
3622 setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) ); 3649 setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) );
3623} 3650}
3624 3651
3625/*! Scrolls the text edit to make the text at the anchor called \a name 3652/*! Scrolls the text edit to make the text at the anchor called \a name
3626 visible, if it can be found in the document. If the anchor isn't found 3653 visible, if it can be found in the document. If the anchor isn't found
3627 no scrolling will occur. An anchor is defined using the HTML anchor 3654 no scrolling will occur. An anchor is defined using the HTML anchor
3628 tag, e.g. \c{<a name="target">}. 3655 tag, e.g. \c{<a name="target">}.
3629*/ 3656*/
3630 3657
3631void QTextEdit::scrollToAnchor( const QString& name ) 3658void QTextEdit::scrollToAnchor( const QString& name )
3632{ 3659{
3660 if ( !isVisible() ) {
3661 d->scrollToAnchor = name;
3662 return;
3663 }
3633 if ( name.isEmpty() ) 3664 if ( name.isEmpty() )
3634 return; 3665 return;
3635 sync(); 3666 sync();
3636 QTextCursor cursor( doc ); 3667 QTextCursor cursor( doc );
3637 QTextParag* last = doc->lastParag(); 3668 QTextParagraph* last = doc->lastParagraph();
3638 do { 3669 for (;;) {
3639 QTextStringChar* c = cursor.parag()->at( cursor.index() ); 3670 QTextStringChar* c = cursor.paragraph()->at( cursor.index() );
3640 if( c->isAnchor() ) { 3671 if( c->isAnchor() ) {
3641 QString a = c->anchorName(); 3672 QString a = c->anchorName();
3642 if ( a == name || 3673 if ( a == name ||
3643 (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) { 3674 (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) {
3644 setContentsPos( contentsX(), QMIN( cursor.parag()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); 3675 setContentsPos( contentsX(), QMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) );
3645 return; 3676 break;
3646 } 3677 }
3647 } 3678 }
3679 if ( cursor.paragraph() == last && cursor.atParagEnd() )
3680 break;
3648 cursor.gotoNextLetter(); 3681 cursor.gotoNextLetter();
3649 } while( cursor.parag() != last || !cursor.atParagEnd() ); 3682 }
3650} 3683}
3651 3684
3652/*! If there is an anchor at position \a pos (in contents 3685/*! If there is an anchor at position \a pos (in contents
3653 coordinates), its name is returned, otherwise an empty string is 3686 coordinates), its name is returned, otherwise an empty string is
3654 returned. 3687 returned.
3655*/ 3688*/
3656 3689
3657QString QTextEdit::anchorAt( const QPoint& pos ) 3690QString QTextEdit::anchorAt( const QPoint& pos )
3658{ 3691{
3659 QTextCursor c( doc ); 3692 QTextCursor c( doc );
3660 placeCursor( pos, &c ); 3693 placeCursor( pos, &c );
3661 return c.parag()->at( c.index() )->anchorHref(); 3694 return c.paragraph()->at( c.index() )->anchorHref();
3662} 3695}
3663 3696
3664void QTextEdit::documentWidthChanged( int w ) 3697void QTextEdit::documentWidthChanged( int w )
3665{ 3698{
3666 resizeContents( QMAX( visibleWidth(), w), contentsHeight() ); 3699 resizeContents( QMAX( visibleWidth(), w), contentsHeight() );
3667} 3700}
3668 3701
3669/*! 3702/*! \internal
3670 Updates all the rendering styles used to display the text. You will 3703
3671 probably want to call this function after calling setStyleSheet(). 3704 This function does nothing
3672*/ 3705*/
3673 3706
3674void QTextEdit::updateStyles() 3707void QTextEdit::updateStyles()
3675{ 3708{
3676 doc->updateStyles();
3677 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3678} 3709}
3679 3710
3680void QTextEdit::setDocument( QTextDocument *dc ) 3711void QTextEdit::setDocument( QTextDocument *dc )
3681{ 3712{
3682 if ( dc == doc ) 3713 if ( dc == doc )
3683 return; 3714 return;
3684 doc = dc; 3715 doc = dc;
3685 cursor->setDocument( doc ); 3716 delete cursor;
3717 cursor = new QTextCursor( doc );
3686 clearUndoRedo(); 3718 clearUndoRedo();
3719 undoRedoInfo.doc = doc;
3687 lastFormatted = 0; 3720 lastFormatted = 0;
3688} 3721}
3689 3722
3690#ifndef QT_NO_CLIPBOARD 3723#ifndef QT_NO_CLIPBOARD
3691 3724
3692/*! 3725/*!
3693 Pastes the text with format \a subtype from the clipboard into the 3726 Pastes the text with format \a subtype from the clipboard into the
3694 text edit at the current cursor position. The \a subtype can be 3727 text edit at the current cursor position. The \a subtype can be
3695 "plain" or "html". 3728 "plain" or "html".
3696 3729
3697 If there is no text with format \a subtype in the clipboard nothing 3730 If there is no text with format \a subtype in the clipboard nothing
3698 happens. 3731 happens.
3699 3732
3700 \sa paste() cut() QTextEdit::copy() 3733 \sa paste() cut() QTextEdit::copy()
3701*/ 3734*/
3702void QTextEdit::pasteSubType( const QCString& subtype ) 3735void QTextEdit::pasteSubType( const QCString& subtype )
3703{ 3736{
3704 QCString st = subtype; 3737 QCString st = subtype;
3705 QString t = QApplication::clipboard()->text(st); 3738 QString t = QApplication::clipboard()->text(st);
3739 if ( doc->hasSelection( QTextDocument::Standard ) )
3740 removeSelectedText();
3706 if ( !t.isEmpty() ) { 3741 if ( !t.isEmpty() ) {
3742 if ( t.startsWith( "<selstart/>" ) ) {
3743 t.remove( 0, 11 );
3744 QTextCursor oldC = *cursor;
3745 lastFormatted = cursor->paragraph();
3746 if ( lastFormatted->prev() )
3747 lastFormatted = lastFormatted->prev();
3748 doc->setRichTextInternal( t, cursor );
3749
3750 if ( undoEnabled && !isReadOnly() ) {
3751 doc->setSelectionStart( QTextDocument::Temp, oldC );
3752 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
3753
3754 checkUndoRedoInfo( UndoRedoInfo::Insert );
3755 if ( !undoRedoInfo.valid() ) {
3756 undoRedoInfo.id = oldC.paragraph()->paragId();
3757 undoRedoInfo.index = oldC.index();
3758 undoRedoInfo.d->text = QString::null;
3759 }
3760 int oldLen = undoRedoInfo.d->text.length();
3761 if ( !doc->preProcessor() ) {
3762 QString txt = doc->selectedText( QTextDocument::Temp );
3763 undoRedoInfo.d->text += txt;
3764 for ( int i = 0; i < (int)txt.length(); ++i ) {
3765 if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) {
3766 oldC.paragraph()->at( oldC.index() )->format()->addRef();
3767 undoRedoInfo.d->text.
3768 setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE );
3769 }
3770 oldC.gotoNextLetter();
3771 }
3772 }
3773 undoRedoInfo.clear();
3774 removeSelection( QTextDocument::Temp );
3775 }
3776
3777 formatMore();
3778 setModified();
3779 emit textChanged();
3780 repaintChanged();
3781 ensureCursorVisible();
3782 return;
3783 }
3784
3707#if defined(Q_OS_WIN32) 3785#if defined(Q_OS_WIN32)
3708 // Need to convert CRLF to LF 3786 // Need to convert CRLF to LF
3709 int index = t.find( QString::fromLatin1("\r\n"), 0 ); 3787 int index = t.find( QString::fromLatin1("\r\n"), 0 );
3710 while ( index != -1 ) { 3788 while ( index != -1 ) {
3711 t.replace( index, 2, QChar('\n') ); 3789 t.replace( index, 2, QChar('\n') );
3712 index = t.find( "\r\n", index ); 3790 index = t.find( "\r\n", index );
3713 } 3791 }
3714#elif defined(Q_OS_MAC) 3792#elif defined(Q_OS_MAC)
3715 //need to convert CR to LF 3793 //need to convert CR to LF
3716 for( unsigned int index = 0; index < t.length(); index++ ) 3794 for( unsigned int index = 0; index < t.length(); index++ )
3717 if(t[index] == '\r') 3795 if(t[index] == '\r')
3718 t[index] = '\n'; 3796 t[index] = '\n';
3719#endif 3797#endif
3720 for ( int i=0; (uint) i<t.length(); i++ ) { 3798 for ( int i=0; (uint) i<t.length(); i++ ) {
3721 if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' ) 3799 if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' )
3722 t[ i ] = ' '; 3800 t[ i ] = ' ';
3723 } 3801 }
3724 if ( !t.isEmpty() ) 3802 if ( !t.isEmpty() )
3725 insert( t, FALSE, TRUE, TRUE ); 3803 insert( t, FALSE, TRUE, TRUE );
3726 } 3804 }
3727} 3805}
3728 3806
3729#ifndef QT_NO_MIMECLIPBOARD 3807#ifndef QT_NO_MIMECLIPBOARD
3730/*! 3808/*!
@@ -3817,49 +3895,49 @@ QCString QTextEdit::pickSpecial( QMimeSource* ms, bool always_ask, const QPoint&
3817 3895
3818 The default mode is \c WidgetWidth which causes words to be wrapped 3896 The default mode is \c WidgetWidth which causes words to be wrapped
3819 at the right edge of the text edit. Wrapping occurs at whitespace, 3897 at the right edge of the text edit. Wrapping occurs at whitespace,
3820 keeping whole words intact. If you want wrapping to occur within 3898 keeping whole words intact. If you want wrapping to occur within
3821 words use setWrapPolicy(). If you set a wrap mode of \c 3899 words use setWrapPolicy(). If you set a wrap mode of \c
3822 FixedPixelWidth or \c FixedColumnWidth you should also call 3900 FixedPixelWidth or \c FixedColumnWidth you should also call
3823 setWrapColumnOrWidth() with the width you want. 3901 setWrapColumnOrWidth() with the width you want.
3824 3902
3825 \sa WordWrap, wrapColumnOrWidth, wrapPolicy, 3903 \sa WordWrap, wrapColumnOrWidth, wrapPolicy,
3826*/ 3904*/
3827 3905
3828void QTextEdit::setWordWrap( WordWrap mode ) 3906void QTextEdit::setWordWrap( WordWrap mode )
3829{ 3907{
3830 if ( wrapMode == mode ) 3908 if ( wrapMode == mode )
3831 return; 3909 return;
3832 wrapMode = mode; 3910 wrapMode = mode;
3833 switch ( mode ) { 3911 switch ( mode ) {
3834 case NoWrap: 3912 case NoWrap:
3835 document()->formatter()->setWrapEnabled( FALSE ); 3913 document()->formatter()->setWrapEnabled( FALSE );
3836 document()->formatter()->setWrapAtColumn( -1 ); 3914 document()->formatter()->setWrapAtColumn( -1 );
3837 doc->setWidth( visibleWidth() ); 3915 doc->setWidth( visibleWidth() );
3838 doc->setMinimumWidth( -1 ); 3916 doc->setMinimumWidth( -1 );
3839 doc->invalidate(); 3917 doc->invalidate();
3840 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 3918 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3841 lastFormatted = doc->firstParag(); 3919 lastFormatted = doc->firstParagraph();
3842 interval = 0; 3920 interval = 0;
3843 formatMore(); 3921 formatMore();
3844 break; 3922 break;
3845 case WidgetWidth: 3923 case WidgetWidth:
3846 document()->formatter()->setWrapEnabled( TRUE ); 3924 document()->formatter()->setWrapEnabled( TRUE );
3847 document()->formatter()->setWrapAtColumn( -1 ); 3925 document()->formatter()->setWrapAtColumn( -1 );
3848 doResize(); 3926 doResize();
3849 break; 3927 break;
3850 case FixedPixelWidth: 3928 case FixedPixelWidth:
3851 document()->formatter()->setWrapEnabled( TRUE ); 3929 document()->formatter()->setWrapEnabled( TRUE );
3852 document()->formatter()->setWrapAtColumn( -1 ); 3930 document()->formatter()->setWrapAtColumn( -1 );
3853 if ( wrapWidth < 0 ) 3931 if ( wrapWidth < 0 )
3854 wrapWidth = 200; 3932 wrapWidth = 200;
3855 setWrapColumnOrWidth( wrapWidth ); 3933 setWrapColumnOrWidth( wrapWidth );
3856 break; 3934 break;
3857 case FixedColumnWidth: 3935 case FixedColumnWidth:
3858 if ( wrapWidth < 0 ) 3936 if ( wrapWidth < 0 )
3859 wrapWidth = 80; 3937 wrapWidth = 80;
3860 document()->formatter()->setWrapEnabled( TRUE ); 3938 document()->formatter()->setWrapEnabled( TRUE );
3861 document()->formatter()->setWrapAtColumn( wrapWidth ); 3939 document()->formatter()->setWrapAtColumn( wrapWidth );
3862 setWrapColumnOrWidth( wrapWidth ); 3940 setWrapColumnOrWidth( wrapWidth );
3863 break; 3941 break;
3864 } 3942 }
3865} 3943}
@@ -3878,49 +3956,49 @@ QTextEdit::WordWrap QTextEdit::wordWrap() const
3878 be wrapped. If the wrap mode is \c FixedColumnWidth, the value is 3956 be wrapped. If the wrap mode is \c FixedColumnWidth, the value is
3879 the column number (in character columns) from the left edge of the 3957 the column number (in character columns) from the left edge of the
3880 text edit at which text should be wrapped. 3958 text edit at which text should be wrapped.
3881 3959
3882 \sa wordWrap 3960 \sa wordWrap
3883 */ 3961 */
3884void QTextEdit::setWrapColumnOrWidth( int value ) 3962void QTextEdit::setWrapColumnOrWidth( int value )
3885{ 3963{
3886 wrapWidth = value; 3964 wrapWidth = value;
3887 if ( wrapMode == FixedColumnWidth ) { 3965 if ( wrapMode == FixedColumnWidth ) {
3888 document()->formatter()->setWrapAtColumn( wrapWidth ); 3966 document()->formatter()->setWrapAtColumn( wrapWidth );
3889 resizeContents( 0, 0 ); 3967 resizeContents( 0, 0 );
3890 doc->setWidth( visibleWidth() ); 3968 doc->setWidth( visibleWidth() );
3891 doc->setMinimumWidth( -1 ); 3969 doc->setMinimumWidth( -1 );
3892 } else if (wrapMode == FixedPixelWidth ) { 3970 } else if (wrapMode == FixedPixelWidth ) {
3893 document()->formatter()->setWrapAtColumn( -1 ); 3971 document()->formatter()->setWrapAtColumn( -1 );
3894 resizeContents( wrapWidth, 0 ); 3972 resizeContents( wrapWidth, 0 );
3895 doc->setWidth( wrapWidth ); 3973 doc->setWidth( wrapWidth );
3896 doc->setMinimumWidth( wrapWidth ); 3974 doc->setMinimumWidth( wrapWidth );
3897 } else { 3975 } else {
3898 return; 3976 return;
3899 } 3977 }
3900 doc->invalidate(); 3978 doc->invalidate();
3901 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 3979 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3902 lastFormatted = doc->firstParag(); 3980 lastFormatted = doc->firstParagraph();
3903 interval = 0; 3981 interval = 0;
3904 formatMore(); 3982 formatMore();
3905} 3983}
3906 3984
3907int QTextEdit::wrapColumnOrWidth() const 3985int QTextEdit::wrapColumnOrWidth() const
3908{ 3986{
3909 if ( wrapMode == WidgetWidth ) 3987 if ( wrapMode == WidgetWidth )
3910 return visibleWidth(); 3988 return visibleWidth();
3911 return wrapWidth; 3989 return wrapWidth;
3912} 3990}
3913 3991
3914 3992
3915/*! \enum QTextEdit::WrapPolicy 3993/*! \enum QTextEdit::WrapPolicy
3916 3994
3917 This enum defines where text can be wrapped in word wrap mode. 3995 This enum defines where text can be wrapped in word wrap mode.
3918 3996
3919 The following values are valid: 3997 The following values are valid:
3920 \value AtWhiteSpace Break lines at whitespace, e.g. spaces or 3998 \value AtWhiteSpace Break lines at whitespace, e.g. spaces or
3921 newlines. 3999 newlines.
3922 \value Anywhere Break anywhere, including within words. 4000 \value Anywhere Break anywhere, including within words.
3923 \value AtWordBoundary Don't use this deprecated value (it is a 4001 \value AtWordBoundary Don't use this deprecated value (it is a
3924 synonym for AtWhiteSpace which you should use instead). 4002 synonym for AtWhiteSpace which you should use instead).
3925 4003
3926 \sa setWrapPolicy() 4004 \sa setWrapPolicy()
@@ -3931,194 +4009,205 @@ int QTextEdit::wrapColumnOrWidth() const
3931 \brief the word wrap policy, at whitespace or anywhere 4009 \brief the word wrap policy, at whitespace or anywhere
3932 4010
3933 Defines where text can be wrapped when word wrap mode is not 4011 Defines where text can be wrapped when word wrap mode is not
3934 \c NoWrap. The choices are \c AtWhiteSpace (the default) and \c 4012 \c NoWrap. The choices are \c AtWhiteSpace (the default) and \c
3935 Anywhere. 4013 Anywhere.
3936 4014
3937 \sa wordWrap 4015 \sa wordWrap
3938 */ 4016 */
3939 4017
3940void QTextEdit::setWrapPolicy( WrapPolicy policy ) 4018void QTextEdit::setWrapPolicy( WrapPolicy policy )
3941{ 4019{
3942 if ( wPolicy == policy ) 4020 if ( wPolicy == policy )
3943 return; 4021 return;
3944 wPolicy = policy; 4022 wPolicy = policy;
3945 QTextFormatter *formatter; 4023 QTextFormatter *formatter;
3946 if ( policy == AtWhiteSpace ) 4024 if ( policy == AtWhiteSpace )
3947 formatter = new QTextFormatterBreakWords; 4025 formatter = new QTextFormatterBreakWords;
3948 else 4026 else
3949 formatter = new QTextFormatterBreakInWords; 4027 formatter = new QTextFormatterBreakInWords;
3950 formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() ); 4028 formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() );
3951 formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) ); 4029 formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) );
3952 document()->setFormatter( formatter ); 4030 document()->setFormatter( formatter );
3953 doc->invalidate(); 4031 doc->invalidate();
3954 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4032 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3955 lastFormatted = doc->firstParag(); 4033 lastFormatted = doc->firstParagraph();
3956 interval = 0; 4034 interval = 0;
3957 formatMore(); 4035 formatMore();
3958} 4036}
3959 4037
3960QTextEdit::WrapPolicy QTextEdit::wrapPolicy() const 4038QTextEdit::WrapPolicy QTextEdit::wrapPolicy() const
3961{ 4039{
3962 return wPolicy; 4040 return wPolicy;
3963} 4041}
3964 4042
3965/*! 4043/*!
3966 Deletes all the text in the text edit. 4044 Deletes all the text in the text edit.
3967 4045
3968 \sa cut() removeSelectedText() setText() 4046 \sa cut() removeSelectedText() setText()
3969 4047
3970*/ 4048*/
3971 4049
3972void QTextEdit::clear() 4050void QTextEdit::clear()
3973{ 4051{
3974 // make clear undoable 4052 // make clear undoable
3975 doc->selectAll( QTextDocument::Temp ); 4053 doc->selectAll( QTextDocument::Temp );
3976 removeSelectedText( QTextDocument::Temp ); 4054 removeSelectedText( QTextDocument::Temp );
3977 4055
3978 setContentsPos( 0, 0 ); 4056 setContentsPos( 0, 0 );
3979 if ( cursor->isValid() ) 4057 if ( cursor->isValid() )
3980 cursor->restoreState(); 4058 cursor->restoreState();
3981 doc->clear( TRUE ); 4059 doc->clear( TRUE );
3982 cursor->setDocument( doc ); 4060 delete cursor;
3983 cursor->setParag( doc->firstParag() ); 4061 cursor = new QTextCursor( doc );
3984 cursor->setIndex( 0 );
3985 lastFormatted = 0; 4062 lastFormatted = 0;
3986 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4063 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3987 4064
3988 emit cursorPositionChanged( cursor ); 4065 emit cursorPositionChanged( cursor );
3989 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 4066 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
3990} 4067}
3991 4068
3992int QTextEdit::undoDepth() const 4069int QTextEdit::undoDepth() const
3993{ 4070{
3994 return document()->undoDepth(); 4071 return document()->undoDepth();
3995} 4072}
3996 4073
3997/*! 4074/*!
3998 \property QTextEdit::length 4075 \property QTextEdit::length
3999 \brief the number of characters in the text 4076 \brief the number of characters in the text
4000 4077
4001*/ 4078*/
4002 4079
4003int QTextEdit::length() const 4080int QTextEdit::length() const
4004{ 4081{
4005 return document()->length(); 4082 return document()->length();
4006} 4083}
4007 4084
4008/*! 4085/*!
4009 \property QTextEdit::tabStopWidth 4086 \property QTextEdit::tabStopWidth
4010 \brief the tab stop width in pixels 4087 \brief the tab stop width in pixels
4011 4088
4012*/ 4089*/
4013 4090
4014int QTextEdit::tabStopWidth() const 4091int QTextEdit::tabStopWidth() const
4015{ 4092{
4016 return document()->tabStopWidth(); 4093 return document()->tabStopWidth();
4017} 4094}
4018 4095
4019void QTextEdit::setUndoDepth( int d ) 4096void QTextEdit::setUndoDepth( int d )
4020{ 4097{
4021 document()->setUndoDepth( d ); 4098 document()->setUndoDepth( d );
4022} 4099}
4023 4100
4024void QTextEdit::setTabStopWidth( int ts ) 4101void QTextEdit::setTabStopWidth( int ts )
4025{ 4102{
4026 document()->setTabStops( ts ); 4103 document()->setTabStops( ts );
4027 doc->invalidate(); 4104 doc->invalidate();
4028 lastFormatted = doc->firstParag(); 4105 lastFormatted = doc->firstParagraph();
4029 interval = 0; 4106 interval = 0;
4030 formatMore(); 4107 formatMore();
4031 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4108 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
4032} 4109}
4033 4110
4034/*! \reimp */ 4111/*! \reimp */
4035 4112
4036QSize QTextEdit::sizeHint() const 4113QSize QTextEdit::sizeHint() const
4037{ 4114{
4038 // ### calculate a reasonable one 4115 // ### calculate a reasonable one
4039 return QSize( 100, 100 ); 4116 return QSize( 100, 100 );
4040} 4117}
4041 4118
4042void QTextEdit::clearUndoRedo() 4119void QTextEdit::clearUndoRedo()
4043{ 4120{
4044 undoRedoInfo.clear(); 4121 undoRedoInfo.clear();
4045 emit undoAvailable( doc->commands()->isUndoAvailable() ); 4122 emit undoAvailable( doc->commands()->isUndoAvailable() );
4046 emit redoAvailable( doc->commands()->isRedoAvailable() ); 4123 emit redoAvailable( doc->commands()->isRedoAvailable() );
4047} 4124}
4048 4125
4049/*! This function gets the format of the character at position \a 4126/*! \internal
4127
4128 \warning In Qt 3.1 we will provide a cleaer API for the
4129 functionality which is provided by this function and in Qt 4.0 this
4130 function will go away.
4131
4132 This function gets the format of the character at position \a
4050 index in paragraph \a para. Sets \a font to the character's font, \a 4133 index in paragraph \a para. Sets \a font to the character's font, \a
4051 color to the character's color and \a verticalAlignment to the 4134 color to the character's color and \a verticalAlignment to the
4052 character's vertical alignment. 4135 character's vertical alignment.
4053 4136
4054 Returns FALSE if \a para or \a index is out of range otherwise 4137 Returns FALSE if \a para or \a index is out of range otherwise
4055 returns TRUE. 4138 returns TRUE.
4056*/ 4139*/
4057 4140
4058bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment ) 4141bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment )
4059{ 4142{
4060 if ( !font || !color ) 4143 if ( !font || !color )
4061 return FALSE; 4144 return FALSE;
4062 QTextParag *p = doc->paragAt( para ); 4145 QTextParagraph *p = doc->paragAt( para );
4063 if ( !p ) 4146 if ( !p )
4064 return FALSE; 4147 return FALSE;
4065 if ( index < 0 || index >= p->length() ) 4148 if ( index < 0 || index >= p->length() )
4066 return FALSE; 4149 return FALSE;
4067 *font = p->at( index )->format()->font(); 4150 *font = p->at( index )->format()->font();
4068 *color = p->at( index )->format()->color(); 4151 *color = p->at( index )->format()->color();
4069 *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign(); 4152 *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign();
4070 return TRUE; 4153 return TRUE;
4071} 4154}
4072 4155
4073/*! This function gets the format of the paragraph \a para. Sets \a 4156/*! \internal
4157
4158 \warning In Qt 3.1 we will provide a cleaer API for the
4159 functionality which is provided by this function and in Qt 4.0 this
4160 function will go away.
4161
4162 This function gets the format of the paragraph \a para. Sets \a
4074 font to the paragraphs's font, \a color to the paragraph's color, \a 4163 font to the paragraphs's font, \a color to the paragraph's color, \a
4075 verticalAlignment to the paragraph's vertical alignment, \a 4164 verticalAlignment to the paragraph's vertical alignment, \a
4076 alignment to the paragraph's alignment, \a displayMode to the 4165 alignment to the paragraph's alignment, \a displayMode to the
4077 paragraph's display mode, \a listStyle to the paragraph's list style 4166 paragraph's display mode, \a listStyle to the paragraph's list style
4078 (if the display mode is QStyleSheetItem::DisplayListItem) and \a 4167 (if the display mode is QStyleSheetItem::DisplayListItem) and \a
4079 listDepth to the depth of the list (if the display mode is 4168 listDepth to the depth of the list (if the display mode is
4080 QStyleSheetItem::DisplayListItem). 4169 QStyleSheetItem::DisplayListItem).
4081 4170
4082 Returns FALSE if \a para is out of range otherwise returns TRUE. 4171 Returns FALSE if \a para is out of range otherwise returns TRUE.
4083*/ 4172*/
4084 4173
4085bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color, 4174bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color,
4086 VerticalAlignment *verticalAlignment, int *alignment, 4175 VerticalAlignment *verticalAlignment, int *alignment,
4087 QStyleSheetItem::DisplayMode *displayMode, 4176 QStyleSheetItem::DisplayMode *displayMode,
4088 QStyleSheetItem::ListStyle *listStyle, 4177 QStyleSheetItem::ListStyle *listStyle,
4089 int *listDepth ) 4178 int *listDepth )
4090{ 4179{
4091 if ( !font || !color || !alignment || !displayMode || !listStyle ) 4180 if ( !font || !color || !alignment || !displayMode || !listStyle )
4092 return FALSE; 4181 return FALSE;
4093 QTextParag *p = doc->paragAt( para ); 4182 QTextParagraph *p = doc->paragAt( para );
4094 if ( !p ) 4183 if ( !p )
4095 return FALSE; 4184 return FALSE;
4096 *font = p->paragFormat()->font(); 4185 *font = p->at(0)->format()->font();
4097 *color = p->paragFormat()->color(); 4186 *color = p->at(0)->format()->color();
4098 *verticalAlignment = (VerticalAlignment)p->paragFormat()->vAlign(); 4187 *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign();
4099 *alignment = p->alignment(); 4188 *alignment = p->alignment();
4100 *displayMode = p->style() ? p->style()->displayMode() : QStyleSheetItem::DisplayBlock; 4189 *displayMode = p->isListItem() ? QStyleSheetItem::DisplayListItem : QStyleSheetItem::DisplayBlock;
4101 *listStyle = p->listStyle(); 4190 *listStyle = p->listStyle();
4102 *listDepth = p->listDepth(); 4191 *listDepth = p->listDepth();
4103 return TRUE; 4192 return TRUE;
4104} 4193}
4105 4194
4106 4195
4107 4196
4108/*! 4197/*!
4109 4198
4110 This function is called to create a right mouse button popup menu 4199 This function is called to create a right mouse button popup menu
4111 at the document position \a pos. If you want to create a custom 4200 at the document position \a pos. If you want to create a custom
4112 popup menu, reimplement this function and return the created 4201 popup menu, reimplement this function and return the created
4113 popup menu. Ownership of the popup menu is transferred to the 4202 popup menu. Ownership of the popup menu is transferred to the
4114 caller. 4203 caller.
4115*/ 4204*/
4116 4205
4117QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos ) 4206QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos )
4118{ 4207{
4119#ifndef QT_NO_POPUPMENU 4208#ifndef QT_NO_POPUPMENU
4120 QPopupMenu *popup = new QPopupMenu( this, "qt_edit_menu" ); 4209 QPopupMenu *popup = new QPopupMenu( this, "qt_edit_menu" );
4121 if ( !isReadOnly() ) { 4210 if ( !isReadOnly() ) {
4122 d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) ); 4211 d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) );
4123 d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) ); 4212 d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) );
4124 popup->insertSeparator(); 4213 popup->insertSeparator();
@@ -4134,81 +4223,72 @@ QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos )
4134 d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) ); 4223 d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) );
4135 popup->insertSeparator(); 4224 popup->insertSeparator();
4136 } 4225 }
4137#if defined(Q_WS_X11) 4226#if defined(Q_WS_X11)
4138 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) ); 4227 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) );
4139#else 4228#else
4140 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) ); 4229 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) );
4141#endif 4230#endif
4142 popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() ); 4231 popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() );
4143 popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() ); 4232 popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() );
4144#ifndef QT_NO_CLIPBOARD 4233#ifndef QT_NO_CLIPBOARD
4145 popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( QTextDocument::Standard, TRUE ) ); 4234 popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( QTextDocument::Standard, TRUE ) );
4146 popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( QTextDocument::Standard, TRUE ) ); 4235 popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( QTextDocument::Standard, TRUE ) );
4147 popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !QApplication::clipboard()->text().isEmpty() ); 4236 popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
4148#endif 4237#endif
4149 popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !text().isEmpty() ); 4238 popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !text().isEmpty() );
4150 popup->setItemEnabled( d->id[ IdSelectAll ], (bool)text().length() ); 4239 popup->setItemEnabled( d->id[ IdSelectAll ], (bool)text().length() );
4151 return popup; 4240 return popup;
4152#else 4241#else
4153 return 0; 4242 return 0;
4154#endif 4243#endif
4155} 4244}
4156 4245
4157/*! \overload 4246/*! \overload
4247 \obsolete
4158 This function is called to create a right mouse button popup menu. 4248 This function is called to create a right mouse button popup menu.
4159 If you want to create a custom popup menu, reimplement this function 4249 If you want to create a custom popup menu, reimplement this function
4160 and return the created popup menu. Ownership of the popup menu is 4250 and return the created popup menu. Ownership of the popup menu is
4161 transferred to the caller. 4251 transferred to the caller.
4252
4253 This function is only called if createPopupMenu( const QPoint & )
4254 returns 0.
4162*/ 4255*/
4163 4256
4164QPopupMenu *QTextEdit::createPopupMenu() 4257QPopupMenu *QTextEdit::createPopupMenu()
4165{ 4258{
4166 return 0; 4259 return 0;
4167} 4260}
4168 4261
4169/*! \reimp */ 4262/*! \reimp */
4170 4263
4171void QTextEdit::setFont( const QFont &f ) 4264void QTextEdit::setFont( const QFont &f )
4172{ 4265{
4173 QFont old( QScrollView::font() ); 4266 QFont old( QScrollView::font() );
4174 QScrollView::setFont( f ); 4267 QScrollView::setFont( f );
4175 doc->setMinimumWidth( -1 ); 4268 doc->setMinimumWidth( -1 );
4176 4269 doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() );
4177 // ### that is a bit hacky 4270 lastFormatted = doc->firstParagraph();
4178 static short diff = 1;
4179 diff *= -1;
4180 doc->setWidth( visibleWidth() + diff );
4181
4182 int s = f.pointSize();
4183 bool usePixels = FALSE;
4184 if ( s == -1 ) {
4185 s = f.pixelSize();
4186 usePixels = TRUE;
4187 }
4188 doc->updateFontSizes( s, usePixels );
4189 doc->updateFontAttributes( f, old );
4190 lastFormatted = doc->firstParag();
4191 formatMore(); 4271 formatMore();
4192 repaintChanged(); 4272 repaintChanged();
4193} 4273}
4194 4274
4195/*! \fn QTextEdit::zoomIn() 4275/*! \fn QTextEdit::zoomIn()
4196 4276
4197 \overload 4277 \overload
4198 4278
4199 Zooms in on the text by by making the base font size one 4279 Zooms in on the text by by making the base font size one
4200 point larger and recalculating all font sizes. This does not change 4280 point larger and recalculating all font sizes. This does not change
4201 the size of any images. 4281 the size of any images.
4202 4282
4203 \sa zoomOut() 4283 \sa zoomOut()
4204 4284
4205*/ 4285*/
4206 4286
4207/*! \fn QTextEdit::zoomOut() 4287/*! \fn QTextEdit::zoomOut()
4208 4288
4209 \overload 4289 \overload
4210 4290
4211 Zooms out on the text by by making the base font size one 4291 Zooms out on the text by by making the base font size one
4212 point smaller and recalculating all font sizes. This does not change 4292 point smaller and recalculating all font sizes. This does not change
4213 the size of any images. 4293 the size of any images.
4214 4294
@@ -4252,52 +4332,51 @@ void QTextEdit::zoomOut( int range )
4252 4332
4253void QTextEdit::zoomTo( int size ) 4333void QTextEdit::zoomTo( int size )
4254{ 4334{
4255 QFont f( QScrollView::font() ); 4335 QFont f( QScrollView::font() );
4256 f.setPointSize( size ); 4336 f.setPointSize( size );
4257 setFont( f ); 4337 setFont( f );
4258} 4338}
4259 4339
4260/*! 4340/*!
4261 \internal 4341 \internal
4262 4342
4263 QTextEdit is optimized for large amounts text. One of its 4343 QTextEdit is optimized for large amounts text. One of its
4264 optimizations is to format only the visible text, formatting the rest 4344 optimizations is to format only the visible text, formatting the rest
4265 on demand, e.g. as the user scrolls, so you don't usually need to 4345 on demand, e.g. as the user scrolls, so you don't usually need to
4266 call this function. 4346 call this function.
4267 4347
4268 In some situations you may want to force the whole text 4348 In some situations you may want to force the whole text
4269 to be formatted. For example, if after calling setText(), you wanted 4349 to be formatted. For example, if after calling setText(), you wanted
4270 to know the height of the document (using contentsHeight()), you 4350 to know the height of the document (using contentsHeight()), you
4271 would call this function first. 4351 would call this function first.
4272*/ 4352*/
4273 4353
4274void QTextEdit::sync() 4354void QTextEdit::sync()
4275{ 4355{
4276 QTextParag *p = lastFormatted; 4356 while ( lastFormatted ) {
4277 while ( p ) { 4357 lastFormatted->format();
4278 p->format(); 4358 lastFormatted = lastFormatted->next();
4279 p = p->next();
4280 } 4359 }
4281 resizeContents( contentsWidth(), doc->height() ); 4360 resizeContents( contentsWidth(), doc->height() );
4282} 4361}
4283 4362
4284/*! \reimp */ 4363/*! \reimp */
4285 4364
4286void QTextEdit::setEnabled( bool b ) 4365void QTextEdit::setEnabled( bool b )
4287{ 4366{
4288 QScrollView::setEnabled( b ); 4367 QScrollView::setEnabled( b );
4289 if ( !b ) { 4368 if ( !b ) {
4290 blinkTimer->stop(); 4369 blinkTimer->stop();
4291 drawCursor( FALSE ); 4370 drawCursor( FALSE );
4292 } 4371 }
4293 if ( textFormat() == PlainText ) { 4372 if ( textFormat() == PlainText ) {
4294 QTextFormat *f = doc->formatCollection()->defaultFormat(); 4373 QTextFormat *f = doc->formatCollection()->defaultFormat();
4295 f->setColor( colorGroup().text() ); 4374 f->setColor( colorGroup().text() );
4296 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4375 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
4297 } 4376 }
4298 if ( b ) { 4377 if ( b ) {
4299 blinkTimer->start( QApplication::cursorFlashTime() / 2 ); 4378 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
4300 drawCursor( TRUE ); 4379 drawCursor( TRUE );
4301 } 4380 }
4302} 4381}
4303 4382
@@ -4339,178 +4418,178 @@ void QTextEdit::setReadOnly( bool b )
4339 if ( readonly ) 4418 if ( readonly )
4340 viewport()->setCursor( arrowCursor ); 4419 viewport()->setCursor( arrowCursor );
4341 else 4420 else
4342 viewport()->setCursor( ibeamCursor ); 4421 viewport()->setCursor( ibeamCursor );
4343#endif 4422#endif
4344} 4423}
4345 4424
4346/*! Scrolls to the bottom of the document and does formatting if 4425/*! Scrolls to the bottom of the document and does formatting if
4347 required */ 4426 required */
4348 4427
4349void QTextEdit::scrollToBottom() 4428void QTextEdit::scrollToBottom()
4350{ 4429{
4351 sync(); 4430 sync();
4352 setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); 4431 setContentsPos( contentsX(), contentsHeight() - visibleHeight() );
4353} 4432}
4354 4433
4355/*! Returns the rectangle of the paragraph \a para in contents 4434/*! Returns the rectangle of the paragraph \a para in contents
4356 coordinates, or an invalid rectangle if \a para is out of range. 4435 coordinates, or an invalid rectangle if \a para is out of range.
4357*/ 4436*/
4358 4437
4359QRect QTextEdit::paragraphRect( int para ) const 4438QRect QTextEdit::paragraphRect( int para ) const
4360{ 4439{
4361 QTextEdit *that = (QTextEdit *)this; 4440 QTextEdit *that = (QTextEdit *)this;
4362 that->sync(); 4441 that->sync();
4363 QTextParag *p = doc->paragAt( para ); 4442 QTextParagraph *p = doc->paragAt( para );
4364 if ( !p ) 4443 if ( !p )
4365 return QRect( -1, -1, -1, -1 ); 4444 return QRect( -1, -1, -1, -1 );
4366 return p->rect(); 4445 return p->rect();
4367} 4446}
4368 4447
4369/*! 4448/*!
4370 Returns the paragraph which is at position \a pos (in contents 4449 Returns the paragraph which is at position \a pos (in contents
4371 coordinates), or -1 if there is no paragraph with index \a pos. 4450 coordinates), or -1 if there is no paragraph with index \a pos.
4372*/ 4451*/
4373 4452
4374int QTextEdit::paragraphAt( const QPoint &pos ) const 4453int QTextEdit::paragraphAt( const QPoint &pos ) const
4375{ 4454{
4376 QTextCursor c( doc ); 4455 QTextCursor c( doc );
4377 c.place( pos, doc->firstParag() ); 4456 c.place( pos, doc->firstParagraph() );
4378 if ( c.parag() ) 4457 if ( c.paragraph() )
4379 return c.parag()->paragId(); 4458 return c.paragraph()->paragId();
4380 return -1; 4459 return -1;
4381} 4460}
4382 4461
4383/*! 4462/*!
4384 Returns the index of the character (relative to its paragraph) at 4463 Returns the index of the character (relative to its paragraph) at
4385 position \a pos (in contents coordinates). If \a para is not null, 4464 position \a pos (in contents coordinates). If \a para is not null,
4386 \e *\a para is set to this paragraph. If there is no character at 4465 \e *\a para is set to this paragraph. If there is no character at
4387 \a pos, -1 is returned. 4466 \a pos, -1 is returned.
4388*/ 4467*/
4389 4468
4390int QTextEdit::charAt( const QPoint &pos, int *para ) const 4469int QTextEdit::charAt( const QPoint &pos, int *para ) const
4391{ 4470{
4392 QTextCursor c( doc ); 4471 QTextCursor c( doc );
4393 c.place( pos, doc->firstParag() ); 4472 c.place( pos, doc->firstParagraph() );
4394 if ( c.parag() ) { 4473 if ( c.paragraph() ) {
4395 if ( para ) 4474 if ( para )
4396 *para = c.parag()->paragId(); 4475 *para = c.paragraph()->paragId();
4397 return c.index(); 4476 return c.index();
4398 } 4477 }
4399 return -1; 4478 return -1;
4400} 4479}
4401 4480
4402/*! Sets the background color of the paragraph \a para to \a bg */ 4481/*! Sets the background color of the paragraph \a para to \a bg */
4403 4482
4404void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg ) 4483void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg )
4405{ 4484{
4406 QTextParag *p = doc->paragAt( para ); 4485 QTextParagraph *p = doc->paragAt( para );
4407 if ( !p ) 4486 if ( !p )
4408 return; 4487 return;
4409 p->setBackgroundColor( bg ); 4488 p->setBackgroundColor( bg );
4410 repaintChanged(); 4489 repaintChanged();
4411} 4490}
4412 4491
4413/*! Clears the background color of the paragraph \a para, so that the 4492/*! Clears the background color of the paragraph \a para, so that the
4414 default color is used again. 4493 default color is used again.
4415*/ 4494*/
4416 4495
4417void QTextEdit::clearParagraphBackground( int para ) 4496void QTextEdit::clearParagraphBackground( int para )
4418{ 4497{
4419 QTextParag *p = doc->paragAt( para ); 4498 QTextParagraph *p = doc->paragAt( para );
4420 if ( !p ) 4499 if ( !p )
4421 return; 4500 return;
4422 p->clearBackgroundColor(); 4501 p->clearBackgroundColor();
4423 repaintChanged(); 4502 repaintChanged();
4424} 4503}
4425 4504
4426/*! Returns the background color of the paragraph \a para or an 4505/*! Returns the background color of the paragraph \a para or an
4427 invalid color if \a para is out of range or the paragraph has no 4506 invalid color if \a para is out of range or the paragraph has no
4428 background set 4507 background set
4429*/ 4508*/
4430 4509
4431QColor QTextEdit::paragraphBackgroundColor( int para ) const 4510QColor QTextEdit::paragraphBackgroundColor( int para ) const
4432{ 4511{
4433 QTextParag *p = doc->paragAt( para ); 4512 QTextParagraph *p = doc->paragAt( para );
4434 if ( !p ) 4513 if ( !p )
4435 return QColor(); 4514 return QColor();
4436 QColor *c = p->backgroundColor(); 4515 QColor *c = p->backgroundColor();
4437 if ( c ) 4516 if ( c )
4438 return *c; 4517 return *c;
4439 return QColor(); 4518 return QColor();
4440} 4519}
4441 4520
4442/*! \property QTextEdit::undoRedoEnabled 4521/*! \property QTextEdit::undoRedoEnabled
4443 \brief whether undo/redo is enabled 4522 \brief whether undo/redo is enabled
4444 4523
4445 The default is TRUE. 4524 The default is TRUE.
4446*/ 4525*/
4447 4526
4448void QTextEdit::setUndoRedoEnabled( bool b ) 4527void QTextEdit::setUndoRedoEnabled( bool b )
4449{ 4528{
4450 undoEnabled = b; 4529 undoEnabled = b;
4451} 4530}
4452 4531
4453bool QTextEdit::isUndoRedoEnabled() const 4532bool QTextEdit::isUndoRedoEnabled() const
4454{ 4533{
4455 return undoEnabled; 4534 return undoEnabled;
4456} 4535}
4457 4536
4458/*! Returns whether undo is available */ 4537/*! Returns whether undo is available */
4459 4538
4460bool QTextEdit::isUndoAvailable() const 4539bool QTextEdit::isUndoAvailable() const
4461{ 4540{
4462 return doc->commands()->isUndoAvailable() || undoRedoInfo.valid(); 4541 return doc->commands()->isUndoAvailable() || undoRedoInfo.valid();
4463} 4542}
4464 4543
4465/*! Returns whether redo is available */ 4544/*! Returns whether redo is available */
4466 4545
4467bool QTextEdit::isRedoAvailable() const 4546bool QTextEdit::isRedoAvailable() const
4468{ 4547{
4469 return doc->commands()->isRedoAvailable(); 4548 return doc->commands()->isRedoAvailable();
4470} 4549}
4471 4550
4472void QTextEdit::ensureFormatted( QTextParag *p ) 4551void QTextEdit::ensureFormatted( QTextParagraph *p )
4473{ 4552{
4474 while ( !p->isValid() ) { 4553 while ( !p->isValid() ) {
4475 if ( !lastFormatted ) 4554 if ( !lastFormatted )
4476 return; 4555 return;
4477 formatMore(); 4556 formatMore();
4478 } 4557 }
4479} 4558}
4480 4559
4481/*! \internal */ 4560/*! \internal */
4482void QTextEdit::updateCursor( const QPoint & pos ) 4561void QTextEdit::updateCursor( const QPoint & pos )
4483{ 4562{
4484 if ( isReadOnly() && linksEnabled() ) { 4563 if ( isReadOnly() && linksEnabled() ) {
4485 QTextCursor c = *cursor; 4564 QTextCursor c = *cursor;
4486 placeCursor( pos, &c, TRUE ); 4565 placeCursor( pos, &c, TRUE );
4487 4566
4488#ifndef QT_NO_NETWORKPROTOCOL 4567#ifndef QT_NO_NETWORKPROTOCOL
4489 if ( c.parag() && c.parag()->at( c.index() ) && 4568 if ( c.paragraph() && c.paragraph()->at( c.index() ) &&
4490 c.parag()->at( c.index() )->isAnchor() && 4569 c.paragraph()->at( c.index() )->isAnchor() &&
4491 !c.parag()->at( c.index() )->anchorHref().isEmpty() ) { 4570 !c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) {
4492 if ( c.index() < c.parag()->length() - 1 ) 4571 if ( c.index() < c.paragraph()->length() - 1 )
4493 onLink = c.parag()->at( c.index() )->anchorHref(); 4572 onLink = c.paragraph()->at( c.index() )->anchorHref();
4494 else 4573 else
4495 onLink = QString::null; 4574 onLink = QString::null;
4496 4575
4497#ifndef QT_NO_CURSOR 4576#ifndef QT_NO_CURSOR
4498 viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor ); 4577 viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor );
4499#endif 4578#endif
4500 QUrl u( doc->context(), onLink, TRUE ); 4579 QUrl u( doc->context(), onLink, TRUE );
4501 emitHighlighted( u.toString( FALSE, FALSE ) ); 4580 emitHighlighted( u.toString( FALSE, FALSE ) );
4502 } else { 4581 } else {
4503#ifndef QT_NO_CURSOR 4582#ifndef QT_NO_CURSOR
4504 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 4583 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
4505#endif 4584#endif
4506 onLink = QString::null; 4585 onLink = QString::null;
4507 emitHighlighted( QString::null ); 4586 emitHighlighted( QString::null );
4508 } 4587 }
4509#endif 4588#endif
4510 } 4589 }
4511} 4590}
4512 4591
4513void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c ) 4592void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c )
4514{ 4593{
4515 placeCursor( pos, c, FALSE ); 4594 placeCursor( pos, c, FALSE );
4516} 4595}