aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/lltexteditor.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-12-01 17:39:58 -0600
committerJacek Antonelli2008-12-01 17:40:06 -0600
commit7abecb48babe6a6f09bf6692ba55076546cfced9 (patch)
tree8d18a88513fb97adf32c10aae78f4be1984942db /linden/indra/llui/lltexteditor.cpp
parentSecond Life viewer sources 1.21.6 (diff)
downloadmeta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.zip
meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.gz
meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.bz2
meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.xz
Second Life viewer sources 1.22.0-RC
Diffstat (limited to 'linden/indra/llui/lltexteditor.cpp')
-rw-r--r--linden/indra/llui/lltexteditor.cpp144
1 files changed, 69 insertions, 75 deletions
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp
index e56002f..281dbe4 100644
--- a/linden/indra/llui/lltexteditor.cpp
+++ b/linden/indra/llui/lltexteditor.cpp
@@ -260,7 +260,7 @@ LLTextEditor::LLTextEditor(
260 mIsSelecting( FALSE ), 260 mIsSelecting( FALSE ),
261 mSelectionStart( 0 ), 261 mSelectionStart( 0 ),
262 mSelectionEnd( 0 ), 262 mSelectionEnd( 0 ),
263 mScrolledToBottom( FALSE ), 263 mScrolledToBottom( TRUE ),
264 mOnScrollEndCallback( NULL ), 264 mOnScrollEndCallback( NULL ),
265 mOnScrollEndData( NULL ), 265 mOnScrollEndData( NULL ),
266 mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ), 266 mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ),
@@ -277,14 +277,16 @@ LLTextEditor::LLTextEditor(
277 mCommitOnFocusLost( FALSE ), 277 mCommitOnFocusLost( FALSE ),
278 mHideScrollbarForShortDocs( FALSE ), 278 mHideScrollbarForShortDocs( FALSE ),
279 mTakesNonScrollClicks( TRUE ), 279 mTakesNonScrollClicks( TRUE ),
280 mTrackBottom( TRUE ), 280 mTrackBottom( FALSE ),
281 mAllowEmbeddedItems( allow_embedded_items ), 281 mAllowEmbeddedItems( allow_embedded_items ),
282 mAcceptCallingCardNames(FALSE), 282 mAcceptCallingCardNames(FALSE),
283 mHandleEditKeysDirectly( FALSE ), 283 mHandleEditKeysDirectly( FALSE ),
284 mMouseDownX(0), 284 mMouseDownX(0),
285 mMouseDownY(0), 285 mMouseDownY(0),
286 mLastSelectionX(-1), 286 mLastSelectionX(-1),
287 mLastSelectionY(-1) 287 mLastSelectionY(-1),
288 mReflowNeeded(FALSE),
289 mScrollNeeded(FALSE)
288{ 290{
289 mSourceID.generate(); 291 mSourceID.generate();
290 292
@@ -468,6 +470,13 @@ void LLTextEditor::updateLineStartList(S32 startpos)
468 mScrollbar->setVisible(!short_doc); 470 mScrollbar->setVisible(!short_doc);
469 } 471 }
470 472
473 // if scrolled to bottom, stay at bottom
474 // unless user is editing text
475 // do this after updating page size
476 if (mScrolledToBottom && mTrackBottom && !hasFocus())
477 {
478 endOfDoc();
479 }
471} 480}
472 481
473//////////////////////////////////////////////////////////// 482////////////////////////////////////////////////////////////
@@ -511,8 +520,7 @@ void LLTextEditor::setText(const LLStringExplicit &utf8str)
511 setCursorPos(0); 520 setCursorPos(0);
512 deselect(); 521 deselect();
513 522
514 updateLineStartList(); 523 needsReflow();
515 updateScrollFromCursor();
516 524
517 resetDirty(); 525 resetDirty();
518} 526}
@@ -529,8 +537,7 @@ void LLTextEditor::setWText(const LLWString &wtext)
529 setCursorPos(0); 537 setCursorPos(0);
530 deselect(); 538 deselect();
531 539
532 updateLineStartList(); 540 needsReflow();
533 updateScrollFromCursor();
534 541
535 resetDirty(); 542 resetDirty();
536} 543}
@@ -568,8 +575,7 @@ void LLTextEditor::setWordWrap(BOOL b)
568 setCursorPos(0); 575 setCursorPos(0);
569 deselect(); 576 deselect();
570 577
571 updateLineStartList(); 578 needsReflow();
572 updateScrollFromCursor();
573} 579}
574 580
575 581
@@ -734,6 +740,7 @@ S32 LLTextEditor::getLineStart( S32 line ) const
734 { 740 {
735 return 0; 741 return 0;
736 } 742 }
743
737 line = llclamp(line, 0, num_lines-1); 744 line = llclamp(line, 0, num_lines-1);
738 S32 segidx = mLineStartList[line].mSegment; 745 S32 segidx = mLineStartList[line].mSegment;
739 S32 segoffset = mLineStartList[line].mOffset; 746 S32 segoffset = mLineStartList[line].mOffset;
@@ -781,14 +788,14 @@ void LLTextEditor::getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp
781 *offsetp = startpos - (*seg_iter)->getStart(); 788 *offsetp = startpos - (*seg_iter)->getStart();
782} 789}
783 790
784const LLTextSegment* LLTextEditor::getPreviousSegment() 791const LLTextSegment* LLTextEditor::getPreviousSegment() const
785{ 792{
786 // find segment index at character to left of cursor (or rightmost edge of selection) 793 // find segment index at character to left of cursor (or rightmost edge of selection)
787 S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1); 794 S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1);
788 return idx >= 0 ? mSegments[idx] : NULL; 795 return idx >= 0 ? mSegments[idx] : NULL;
789} 796}
790 797
791void LLTextEditor::getSelectedSegments(std::vector<const LLTextSegment*>& segments) 798void LLTextEditor::getSelectedSegments(std::vector<const LLTextSegment*>& segments) const
792{ 799{
793 S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos; 800 S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
794 S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos; 801 S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
@@ -875,13 +882,12 @@ void LLTextEditor::setCursor(S32 row, S32 column)
875 } 882 }
876 doc += column; 883 doc += column;
877 setCursorPos(doc - mWText.c_str()); 884 setCursorPos(doc - mWText.c_str());
878 updateScrollFromCursor();
879} 885}
880 886
881void LLTextEditor::setCursorPos(S32 offset) 887void LLTextEditor::setCursorPos(S32 offset)
882{ 888{
883 mCursorPos = llclamp(offset, 0, (S32)getLength()); 889 mCursorPos = llclamp(offset, 0, (S32)getLength());
884 updateScrollFromCursor(); 890 needsScroll();
885 // reset desired x cursor position 891 // reset desired x cursor position
886 mDesiredXPixel = -1; 892 mDesiredXPixel = -1;
887} 893}
@@ -1222,8 +1228,6 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
1222 1228
1223 setCursorAtLocalPos( x, y, TRUE ); 1229 setCursorAtLocalPos( x, y, TRUE );
1224 mSelectionEnd = mCursorPos; 1230 mSelectionEnd = mCursorPos;
1225
1226 updateScrollFromCursor();
1227 } 1231 }
1228 1232
1229 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl; 1233 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
@@ -1317,8 +1321,6 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
1317 1321
1318 setCursorAtLocalPos( x, y, TRUE ); 1322 setCursorAtLocalPos( x, y, TRUE );
1319 endSelection(); 1323 endSelection();
1320
1321 updateScrollFromCursor();
1322 } 1324 }
1323 1325
1324 if( !hasSelection() ) 1326 if( !hasSelection() )
@@ -1839,8 +1841,7 @@ void LLTextEditor::cut()
1839 gClipboard.copyFromSubstring( mWText, left_pos, length, mSourceID ); 1841 gClipboard.copyFromSubstring( mWText, left_pos, length, mSourceID );
1840 deleteSelection( FALSE ); 1842 deleteSelection( FALSE );
1841 1843
1842 updateLineStartList(); 1844 needsReflow();
1843 updateScrollFromCursor();
1844} 1845}
1845 1846
1846BOOL LLTextEditor::canCopy() const 1847BOOL LLTextEditor::canCopy() const
@@ -1910,8 +1911,7 @@ void LLTextEditor::paste()
1910 setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE)); 1911 setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE));
1911 deselect(); 1912 deselect();
1912 1913
1913 updateLineStartList(); 1914 needsReflow();
1914 updateScrollFromCursor();
1915} 1915}
1916 1916
1917 1917
@@ -2235,9 +2235,9 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
2235 2235
2236 if(text_may_have_changed) 2236 if(text_may_have_changed)
2237 { 2237 {
2238 updateLineStartList(); 2238 needsReflow();
2239 } 2239 }
2240 updateScrollFromCursor(); 2240 needsScroll();
2241 } 2241 }
2242 } 2242 }
2243 2243
@@ -2280,8 +2280,7 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
2280 // Most keystrokes will make the selection box go away, but not all will. 2280 // Most keystrokes will make the selection box go away, but not all will.
2281 deselect(); 2281 deselect();
2282 2282
2283 updateLineStartList(); 2283 needsReflow();
2284 updateScrollFromCursor();
2285 } 2284 }
2286 } 2285 }
2287 2286
@@ -2339,8 +2338,7 @@ void LLTextEditor::doDelete()
2339 } 2338 }
2340 } 2339 }
2341 2340
2342 updateLineStartList(); 2341 needsReflow();
2343 updateScrollFromCursor();
2344} 2342}
2345 2343
2346//---------------------------------------------------------------------------- 2344//----------------------------------------------------------------------------
@@ -2383,8 +2381,7 @@ void LLTextEditor::undo()
2383 2381
2384 setCursorPos(pos); 2382 setCursorPos(pos);
2385 2383
2386 updateLineStartList(); 2384 needsReflow();
2387 updateScrollFromCursor();
2388} 2385}
2389 2386
2390BOOL LLTextEditor::canRedo() const 2387BOOL LLTextEditor::canRedo() const
@@ -2426,8 +2423,7 @@ void LLTextEditor::redo()
2426 2423
2427 setCursorPos(pos); 2424 setCursorPos(pos);
2428 2425
2429 updateLineStartList(); 2426 needsReflow();
2430 updateScrollFromCursor();
2431} 2427}
2432 2428
2433void LLTextEditor::onFocusReceived() 2429void LLTextEditor::onFocusReceived()
@@ -2594,7 +2590,7 @@ void LLTextEditor::drawSelectionBackground()
2594 BOOL selection_visible = (left_visible_pos <= selection_right) && (selection_left <= right_visible_pos); 2590 BOOL selection_visible = (left_visible_pos <= selection_right) && (selection_left <= right_visible_pos);
2595 if( selection_visible ) 2591 if( selection_visible )
2596 { 2592 {
2597 LLGLSNoTexture no_texture; 2593 gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
2598 const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor; 2594 const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor;
2599 F32 alpha = hasFocus() ? 1.f : 0.5f; 2595 F32 alpha = hasFocus() ? 1.f : 0.5f;
2600 gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); 2596 gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha );
@@ -2729,7 +2725,7 @@ void LLTextEditor::drawCursor()
2729 } 2725 }
2730 } 2726 }
2731 2727
2732 LLGLSNoTexture no_texture; 2728 gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
2733 2729
2734 gGL.color4fv( mCursorColor.mV ); 2730 gGL.color4fv( mCursorColor.mV );
2735 2731
@@ -3100,6 +3096,20 @@ void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32
3100 3096
3101void LLTextEditor::draw() 3097void LLTextEditor::draw()
3102{ 3098{
3099 // do on-demand reflow
3100 if (mReflowNeeded)
3101 {
3102 updateLineStartList();
3103 mReflowNeeded = FALSE;
3104 }
3105
3106 // then update scroll position, as cursor may have moved
3107 if (mScrollNeeded)
3108 {
3109 updateScrollFromCursor();
3110 mScrollNeeded = FALSE;
3111 }
3112
3103 { 3113 {
3104 LLLocalClipRect clip(LLRect(0, getRect().getHeight(), getRect().getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0)); 3114 LLLocalClipRect clip(LLRect(0, getRect().getHeight(), getRect().getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0));
3105 3115
@@ -3118,10 +3128,10 @@ void LLTextEditor::draw()
3118 mBorder->setKeyboardFocusHighlight( gFocusMgr.getKeyboardFocus() == this);// && !mReadOnly); 3128 mBorder->setKeyboardFocusHighlight( gFocusMgr.getKeyboardFocus() == this);// && !mReadOnly);
3119 } 3129 }
3120 3130
3131 LLView::draw(); // Draw children (scrollbar and border)
3132
3121 // remember if we are supposed to be at the bottom of the buffer 3133 // remember if we are supposed to be at the bottom of the buffer
3122 mScrolledToBottom = isScrolledToBottom(); 3134 mScrolledToBottom = isScrolledToBottom();
3123
3124 LLView::draw(); // Draw children (scrollbar and border)
3125} 3135}
3126 3136
3127 3137
@@ -3311,7 +3321,7 @@ void LLTextEditor::setCursorAndScrollToEnd()
3311{ 3321{
3312 deselect(); 3322 deselect();
3313 endOfDoc(); 3323 endOfDoc();
3314 updateScrollFromCursor(); 3324 needsScroll();
3315} 3325}
3316 3326
3317void LLTextEditor::getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap ) 3327void LLTextEditor::getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap )
@@ -3438,7 +3448,7 @@ void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
3438 // up-to-date mTextRect 3448 // up-to-date mTextRect
3439 updateTextRect(); 3449 updateTextRect();
3440 3450
3441 updateLineStartList(); 3451 needsReflow();
3442 3452
3443 // propagate shape information to scrollbar 3453 // propagate shape information to scrollbar
3444 mScrollbar->setDocSize( getLineCount() ); 3454 mScrollbar->setDocSize( getLineCount() );
@@ -3446,14 +3456,6 @@ void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
3446 S32 line_height = llround( mGLFont->getLineHeight() ); 3456 S32 line_height = llround( mGLFont->getLineHeight() );
3447 S32 page_lines = mTextRect.getHeight() / line_height; 3457 S32 page_lines = mTextRect.getHeight() / line_height;
3448 mScrollbar->setPageSize( page_lines ); 3458 mScrollbar->setPageSize( page_lines );
3449
3450 // if scrolled to bottom, stay at bottom
3451 // unless user is editing text
3452 // do this after updating page size
3453 if (mScrolledToBottom && mTrackBottom && !hasFocus())
3454 {
3455 endOfDoc();
3456 }
3457} 3459}
3458 3460
3459void LLTextEditor::autoIndent() 3461void LLTextEditor::autoIndent()
@@ -3500,8 +3502,7 @@ void LLTextEditor::insertText(const std::string &new_text)
3500 3502
3501 setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE )); 3503 setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE ));
3502 3504
3503 updateLineStartList(); 3505 needsReflow();
3504 updateScrollFromCursor();
3505 3506
3506 setEnabled( enabled ); 3507 setEnabled( enabled );
3507} 3508}
@@ -3600,7 +3601,7 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool
3600 mSegments.push_back(segment); 3601 mSegments.push_back(segment);
3601 } 3602 }
3602 3603
3603 updateLineStartList(old_length); 3604 needsReflow();
3604 3605
3605 // Set the cursor and scroll position 3606 // Set the cursor and scroll position
3606 // Maintain the scroll position unless the scroll was at the end of the doc (in which 3607 // Maintain the scroll position unless the scroll was at the end of the doc (in which
@@ -3639,14 +3640,6 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool
3639 { 3640 {
3640 blockUndo(); 3641 blockUndo();
3641 } 3642 }
3642
3643 // if scrolled to bottom, stay at bottom
3644 // unless user is editing text
3645 // do this after updating page size
3646 if (mScrolledToBottom && mTrackBottom && !hasFocus())
3647 {
3648 endOfDoc();
3649 }
3650} 3643}
3651 3644
3652void LLTextEditor::removeTextFromEnd(S32 num_chars) 3645void LLTextEditor::removeTextFromEnd(S32 num_chars)
@@ -3661,7 +3654,10 @@ void LLTextEditor::removeTextFromEnd(S32 num_chars)
3661 mSelectionEnd = llclamp(mSelectionEnd, 0, len); 3654 mSelectionEnd = llclamp(mSelectionEnd, 0, len);
3662 3655
3663 pruneSegments(); 3656 pruneSegments();
3657
3658 // pruneSegments will invalidate mLineStartList.
3664 updateLineStartList(); 3659 updateLineStartList();
3660 needsScroll();
3665} 3661}
3666 3662
3667/////////////////////////////////////////////////////////////////// 3663///////////////////////////////////////////////////////////////////
@@ -3759,8 +3755,7 @@ BOOL LLTextEditor::tryToRevertToPristineState()
3759 } 3755 }
3760 } 3756 }
3761 3757
3762 updateLineStartList(); 3758 needsReflow();
3763 updateScrollFromCursor();
3764 } 3759 }
3765 3760
3766 return isPristine(); // TRUE => success 3761 return isPristine(); // TRUE => success
@@ -3808,6 +3803,7 @@ void LLTextEditor::updateSegments()
3808 { 3803 {
3809 findEmbeddedItemSegments(); 3804 findEmbeddedItemSegments();
3810 } 3805 }
3806
3811 // Make sure we have at least one segment 3807 // Make sure we have at least one segment
3812 if (mSegments.size() == 1 && mSegments[0]->getIsDefault()) 3808 if (mSegments.size() == 1 && mSegments[0]->getIsDefault())
3813 { 3809 {
@@ -3824,6 +3820,7 @@ void LLTextEditor::updateSegments()
3824} 3820}
3825 3821
3826// Only effective if text was removed from the end of the editor 3822// Only effective if text was removed from the end of the editor
3823// *NOTE: Using this will invalidate references to mSegments from mLineStartList.
3827void LLTextEditor::pruneSegments() 3824void LLTextEditor::pruneSegments()
3828{ 3825{
3829 S32 len = mWText.length(); 3826 S32 len = mWText.length();
@@ -4066,9 +4063,7 @@ BOOL LLTextEditor::importBuffer(const char* buffer, S32 length )
4066 setCursorPos(0); 4063 setCursorPos(0);
4067 deselect(); 4064 deselect();
4068 4065
4069 updateLineStartList(); 4066 needsReflow();
4070 updateScrollFromCursor();
4071
4072 return success; 4067 return success;
4073} 4068}
4074 4069
@@ -4260,35 +4255,35 @@ S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse)
4260 std::string openers=" \t\n('\"[{<>"; 4255 std::string openers=" \t\n('\"[{<>";
4261 std::string closers=" \t\n)'\"]}><;"; 4256 std::string closers=" \t\n)'\"]}><;";
4262 4257
4263 S32 m2 = 0; 4258 S32 index = 0;
4264 S32 retval = 0;
4265 4259
4266 if (reverse) 4260 if (reverse)
4267 { 4261 {
4268 4262 for (index=pos; index >= 0; index--)
4269 for (retval=pos; retval >= 0; retval--)
4270 { 4263 {
4271 m2 = openers.find(line.substr(retval,1)); 4264 char c = line[index];
4265 S32 m2 = openers.find(c);
4272 if (m2 >= 0) 4266 if (m2 >= 0)
4273 { 4267 {
4274 break; 4268 return index+1;
4275 } 4269 }
4276 } 4270 }
4277 return retval+1;
4278 } 4271 }
4279 else 4272 else
4280 { 4273 {
4281 4274
4282 for (retval=pos; retval<(S32)line.length(); retval++) 4275 for (index=pos; index<(S32)line.length(); index++)
4283 { 4276 {
4284 m2 = closers.find(line.substr(retval,1)); 4277 char c = line[index];
4278 S32 m2 = closers.find(c);
4285 if (m2 >= 0) 4279 if (m2 >= 0)
4286 { 4280 {
4287 break; 4281 return index;
4288 } 4282 }
4289 } 4283 }
4290 return retval; 4284 }
4291 } 4285
4286 return index;
4292} 4287}
4293 4288
4294BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const 4289BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const
@@ -4476,9 +4471,8 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
4476 4471
4477 mPreeditStandouts = preedit_standouts; 4472 mPreeditStandouts = preedit_standouts;
4478 4473
4479 updateLineStartList(); 4474 needsReflow();
4480 setCursorPos(insert_preedit_at + caret_position); 4475 setCursorPos(insert_preedit_at + caret_position);
4481 // updateScrollFromCursor();
4482 4476
4483 // Update of the preedit should be caused by some key strokes. 4477 // Update of the preedit should be caused by some key strokes.
4484 mKeystrokeTimer.reset(); 4478 mKeystrokeTimer.reset();