aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/lltexteditor.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:34 -0500
committerJacek Antonelli2008-08-15 23:45:34 -0500
commitcd17687f01420952712a500107e0f93e7ab8d5f8 (patch)
treece48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/llui/lltexteditor.cpp
parentSecond Life viewer sources 1.19.0.5 (diff)
downloadmeta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz
Second Life viewer sources 1.19.1.0
Diffstat (limited to 'linden/indra/llui/lltexteditor.cpp')
-rw-r--r--linden/indra/llui/lltexteditor.cpp828
1 files changed, 362 insertions, 466 deletions
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp
index 9061ca3..545fddb 100644
--- a/linden/indra/llui/lltexteditor.cpp
+++ b/linden/indra/llui/lltexteditor.cpp
@@ -37,6 +37,7 @@
37 37
38#include "llfontgl.h" 38#include "llfontgl.h"
39#include "llgl.h" 39#include "llgl.h"
40#include "llglimmediate.h"
40#include "llui.h" 41#include "llui.h"
41#include "lluictrlfactory.h" 42#include "lluictrlfactory.h"
42#include "llrect.h" 43#include "llrect.h"
@@ -63,15 +64,12 @@
63// 64//
64// Globals 65// Globals
65// 66//
66
67BOOL gDebugTextEditorTips = FALSE; 67BOOL gDebugTextEditorTips = FALSE;
68 68
69// 69//
70// Constants 70// Constants
71// 71//
72
73const S32 UI_TEXTEDITOR_BUFFER_BLOCK_SIZE = 512; 72const S32 UI_TEXTEDITOR_BUFFER_BLOCK_SIZE = 512;
74
75const S32 UI_TEXTEDITOR_BORDER = 1; 73const S32 UI_TEXTEDITOR_BORDER = 1;
76const S32 UI_TEXTEDITOR_H_PAD = 4; 74const S32 UI_TEXTEDITOR_H_PAD = 4;
77const S32 UI_TEXTEDITOR_V_PAD_TOP = 4; 75const S32 UI_TEXTEDITOR_V_PAD_TOP = 4;
@@ -93,67 +91,33 @@ void (* LLTextEditor::mURLcallback)(const char*) = NULL;
93bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL; 91bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL;
94bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL; 92bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL;
95 93
96///////////////////////////////////////////////////////////////////
97//virtuals
98BOOL LLTextCmd::canExtend(S32 pos)
99{
100 return FALSE;
101}
102
103void LLTextCmd::blockExtensions()
104{
105}
106
107BOOL LLTextCmd::extendAndExecute( LLTextEditor* editor, S32 pos, llwchar c, S32* delta )
108{
109 llassert(0);
110 return 0;
111}
112
113BOOL LLTextCmd::hasExtCharValue( llwchar value )
114{
115 return FALSE;
116}
117
118// Utility funcs
119S32 LLTextCmd::insert(LLTextEditor* editor, S32 pos, const LLWString &wstr)
120{
121 return editor->insertStringNoUndo( pos, wstr );
122}
123S32 LLTextCmd::remove(LLTextEditor* editor, S32 pos, S32 length)
124{
125 return editor->removeStringNoUndo( pos, length );
126}
127S32 LLTextCmd::overwrite(LLTextEditor* editor, S32 pos, llwchar wc)
128{
129 return editor->overwriteCharNoUndo(pos, wc);
130}
131 94
132/////////////////////////////////////////////////////////////////// 95///////////////////////////////////////////////////////////////////
133 96
134class LLTextCmdInsert : public LLTextCmd 97class LLTextEditor::LLTextCmdInsert : public LLTextEditor::LLTextCmd
135{ 98{
136public: 99public:
137 LLTextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws) 100 LLTextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws)
138 : LLTextCmd(pos, group_with_next), mWString(ws) 101 : LLTextCmd(pos, group_with_next), mWString(ws)
139 { 102 {
140 } 103 }
104 virtual ~LLTextCmdInsert() {}
141 virtual BOOL execute( LLTextEditor* editor, S32* delta ) 105 virtual BOOL execute( LLTextEditor* editor, S32* delta )
142 { 106 {
143 *delta = insert(editor, mPos, mWString ); 107 *delta = insert(editor, getPosition(), mWString );
144 LLWString::truncate(mWString, *delta); 108 LLWString::truncate(mWString, *delta);
145 //mWString = wstring_truncate(mWString, *delta); 109 //mWString = wstring_truncate(mWString, *delta);
146 return (*delta != 0); 110 return (*delta != 0);
147 } 111 }
148 virtual S32 undo( LLTextEditor* editor ) 112 virtual S32 undo( LLTextEditor* editor )
149 { 113 {
150 remove(editor, mPos, mWString.length() ); 114 remove(editor, getPosition(), mWString.length() );
151 return mPos; 115 return getPosition();
152 } 116 }
153 virtual S32 redo( LLTextEditor* editor ) 117 virtual S32 redo( LLTextEditor* editor )
154 { 118 {
155 insert(editor, mPos, mWString ); 119 insert(editor, getPosition(), mWString );
156 return mPos + mWString.length(); 120 return getPosition() + mWString.length();
157 } 121 }
158 122
159private: 123private:
@@ -161,8 +125,7 @@ private:
161}; 125};
162 126
163/////////////////////////////////////////////////////////////////// 127///////////////////////////////////////////////////////////////////
164 128class LLTextEditor::LLTextCmdAddChar : public LLTextEditor::LLTextCmd
165class LLTextCmdAddChar : public LLTextCmd
166{ 129{
167public: 130public:
168 LLTextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc) 131 LLTextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc)
@@ -173,13 +136,13 @@ public:
173 { 136 {
174 mBlockExtensions = TRUE; 137 mBlockExtensions = TRUE;
175 } 138 }
176 virtual BOOL canExtend(S32 pos) 139 virtual BOOL canExtend(S32 pos) const
177 { 140 {
178 return !mBlockExtensions && (pos == mPos + (S32)mWString.length()); 141 return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length());
179 } 142 }
180 virtual BOOL execute( LLTextEditor* editor, S32* delta ) 143 virtual BOOL execute( LLTextEditor* editor, S32* delta )
181 { 144 {
182 *delta = insert(editor, mPos, mWString); 145 *delta = insert(editor, getPosition(), mWString);
183 LLWString::truncate(mWString, *delta); 146 LLWString::truncate(mWString, *delta);
184 //mWString = wstring_truncate(mWString, *delta); 147 //mWString = wstring_truncate(mWString, *delta);
185 return (*delta != 0); 148 return (*delta != 0);
@@ -198,13 +161,13 @@ public:
198 } 161 }
199 virtual S32 undo( LLTextEditor* editor ) 162 virtual S32 undo( LLTextEditor* editor )
200 { 163 {
201 remove(editor, mPos, mWString.length() ); 164 remove(editor, getPosition(), mWString.length() );
202 return mPos; 165 return getPosition();
203 } 166 }
204 virtual S32 redo( LLTextEditor* editor ) 167 virtual S32 redo( LLTextEditor* editor )
205 { 168 {
206 insert(editor, mPos, mWString ); 169 insert(editor, getPosition(), mWString );
207 return mPos + mWString.length(); 170 return getPosition() + mWString.length();
208 } 171 }
209 172
210private: 173private:
@@ -215,7 +178,7 @@ private:
215 178
216/////////////////////////////////////////////////////////////////// 179///////////////////////////////////////////////////////////////////
217 180
218class LLTextCmdOverwriteChar : public LLTextCmd 181class LLTextEditor::LLTextCmdOverwriteChar : public LLTextEditor::LLTextCmd
219{ 182{
220public: 183public:
221 LLTextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc) 184 LLTextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
@@ -223,20 +186,20 @@ public:
223 186
224 virtual BOOL execute( LLTextEditor* editor, S32* delta ) 187 virtual BOOL execute( LLTextEditor* editor, S32* delta )
225 { 188 {
226 mOldChar = editor->getWChar(mPos); 189 mOldChar = editor->getWChar(getPosition());
227 overwrite(editor, mPos, mChar); 190 overwrite(editor, getPosition(), mChar);
228 *delta = 0; 191 *delta = 0;
229 return TRUE; 192 return TRUE;
230 } 193 }
231 virtual S32 undo( LLTextEditor* editor ) 194 virtual S32 undo( LLTextEditor* editor )
232 { 195 {
233 overwrite(editor, mPos, mOldChar); 196 overwrite(editor, getPosition(), mOldChar);
234 return mPos; 197 return getPosition();
235 } 198 }
236 virtual S32 redo( LLTextEditor* editor ) 199 virtual S32 redo( LLTextEditor* editor )
237 { 200 {
238 overwrite(editor, mPos, mChar); 201 overwrite(editor, getPosition(), mChar);
239 return mPos+1; 202 return getPosition()+1;
240 } 203 }
241 204
242private: 205private:
@@ -246,7 +209,7 @@ private:
246 209
247/////////////////////////////////////////////////////////////////// 210///////////////////////////////////////////////////////////////////
248 211
249class LLTextCmdRemove : public LLTextCmd 212class LLTextEditor::LLTextCmdRemove : public LLTextEditor::LLTextCmd
250{ 213{
251public: 214public:
252 LLTextCmdRemove( S32 pos, BOOL group_with_next, S32 len ) : 215 LLTextCmdRemove( S32 pos, BOOL group_with_next, S32 len ) :
@@ -255,30 +218,27 @@ public:
255 } 218 }
256 virtual BOOL execute( LLTextEditor* editor, S32* delta ) 219 virtual BOOL execute( LLTextEditor* editor, S32* delta )
257 { 220 {
258 mWString = editor->getWSubString(mPos, mLen); 221 mWString = editor->getWSubString(getPosition(), mLen);
259 *delta = remove(editor, mPos, mLen ); 222 *delta = remove(editor, getPosition(), mLen );
260 return (*delta != 0); 223 return (*delta != 0);
261 } 224 }
262 virtual S32 undo( LLTextEditor* editor ) 225 virtual S32 undo( LLTextEditor* editor )
263 { 226 {
264 insert(editor, mPos, mWString ); 227 insert(editor, getPosition(), mWString );
265 return mPos + mWString.length(); 228 return getPosition() + mWString.length();
266 } 229 }
267 virtual S32 redo( LLTextEditor* editor ) 230 virtual S32 redo( LLTextEditor* editor )
268 { 231 {
269 remove(editor, mPos, mLen ); 232 remove(editor, getPosition(), mLen );
270 return mPos; 233 return getPosition();
271 } 234 }
272private: 235private:
273 LLWString mWString; 236 LLWString mWString;
274 S32 mLen; 237 S32 mLen;
275}; 238};
276 239
277///////////////////////////////////////////////////////////////////
278 240
279// 241///////////////////////////////////////////////////////////////////
280// Member functions
281//
282 242
283LLTextEditor::LLTextEditor( 243LLTextEditor::LLTextEditor(
284 const LLString& name, 244 const LLString& name,
@@ -309,7 +269,7 @@ LLTextEditor::LLTextEditor(
309 mFocusBgColor( LLUI::sColorsGroup->getColor( "TextBgFocusColor" ) ), 269 mFocusBgColor( LLUI::sColorsGroup->getColor( "TextBgFocusColor" ) ),
310 mReadOnly(FALSE), 270 mReadOnly(FALSE),
311 mWordWrap( FALSE ), 271 mWordWrap( FALSE ),
312 mTabToNextField( TRUE ), 272 mTabsToNextField( TRUE ),
313 mCommitOnFocusLost( FALSE ), 273 mCommitOnFocusLost( FALSE ),
314 mHideScrollbarForShortDocs( FALSE ), 274 mHideScrollbarForShortDocs( FALSE ),
315 mTakesNonScrollClicks( TRUE ), 275 mTakesNonScrollClicks( TRUE ),
@@ -344,10 +304,10 @@ LLTextEditor::LLTextEditor(
344 // Init the scrollbar 304 // Init the scrollbar
345 LLRect scroll_rect; 305 LLRect scroll_rect;
346 scroll_rect.setOriginAndSize( 306 scroll_rect.setOriginAndSize(
347 mRect.getWidth() - UI_TEXTEDITOR_BORDER - SCROLLBAR_SIZE, 307 getRect().getWidth() - UI_TEXTEDITOR_BORDER - SCROLLBAR_SIZE,
348 UI_TEXTEDITOR_BORDER, 308 UI_TEXTEDITOR_BORDER,
349 SCROLLBAR_SIZE, 309 SCROLLBAR_SIZE,
350 mRect.getHeight() - 2 * UI_TEXTEDITOR_BORDER ); 310 getRect().getHeight() - 2 * UI_TEXTEDITOR_BORDER );
351 S32 lines_in_doc = getLineCount(); 311 S32 lines_in_doc = getLineCount();
352 mScrollbar = new LLScrollbar( "Scrollbar", scroll_rect, 312 mScrollbar = new LLScrollbar( "Scrollbar", scroll_rect,
353 LLScrollbar::VERTICAL, 313 LLScrollbar::VERTICAL,
@@ -363,7 +323,7 @@ LLTextEditor::LLTextEditor(
363 mScrollbar->setOnScrollEndCallback(mOnScrollEndCallback, mOnScrollEndData); 323 mScrollbar->setOnScrollEndCallback(mOnScrollEndCallback, mOnScrollEndData);
364 addChild(mScrollbar); 324 addChild(mScrollbar);
365 325
366 mBorder = new LLViewBorder( "text ed border", LLRect(0, mRect.getHeight(), mRect.getWidth(), 0), LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, UI_TEXTEDITOR_BORDER ); 326 mBorder = new LLViewBorder( "text ed border", LLRect(0, getRect().getHeight(), getRect().getWidth(), 0), LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, UI_TEXTEDITOR_BORDER );
367 addChild( mBorder ); 327 addChild( mBorder );
368 328
369 appendText(default_text, FALSE, FALSE); 329 appendText(default_text, FALSE, FALSE);
@@ -392,12 +352,6 @@ LLTextEditor::~LLTextEditor()
392 std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); 352 std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
393} 353}
394 354
395//virtual
396LLString LLTextEditor::getWidgetTag() const
397{
398 return LL_TEXT_EDITOR_TAG;
399}
400
401void LLTextEditor::setTrackColor( const LLColor4& color ) 355void LLTextEditor::setTrackColor( const LLColor4& color )
402{ 356{
403 mScrollbar->setTrackColor(color); 357 mScrollbar->setTrackColor(color);
@@ -422,7 +376,7 @@ void LLTextEditor::updateLineStartList(S32 startpos)
422{ 376{
423 updateSegments(); 377 updateSegments();
424 378
425 bindEmbeddedChars( mGLFont ); 379 bindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) );
426 380
427 S32 seg_num = mSegments.size(); 381 S32 seg_num = mSegments.size();
428 S32 seg_idx = 0; 382 S32 seg_idx = 0;
@@ -471,7 +425,7 @@ void LLTextEditor::updateLineStartList(S32 startpos)
471 else 425 else
472 { 426 {
473 const llwchar* str = mWText.c_str() + start_idx; 427 const llwchar* str = mWText.c_str() + start_idx;
474 S32 drawn = mGLFont->maxDrawableChars(str, (F32)mTextRect.getWidth() - line_width, 428 S32 drawn = mGLFont->maxDrawableChars(str, (F32)abs(mTextRect.getWidth()) - line_width,
475 end_idx - start_idx, mWordWrap, mAllowEmbeddedItems ); 429 end_idx - start_idx, mWordWrap, mAllowEmbeddedItems );
476 if( 0 == drawn && line_width == 0) 430 if( 0 == drawn && line_width == 0)
477 { 431 {
@@ -499,7 +453,7 @@ void LLTextEditor::updateLineStartList(S32 startpos)
499 } 453 }
500 } 454 }
501 455
502 unbindEmbeddedChars(mGLFont); 456 unbindEmbeddedChars(const_cast<LLFontGL*>(mGLFont));
503 457
504 mScrollbar->setDocSize( getLineCount() ); 458 mScrollbar->setDocSize( getLineCount() );
505 459
@@ -515,11 +469,6 @@ void LLTextEditor::updateLineStartList(S32 startpos)
515// LLTextEditor 469// LLTextEditor
516// Public methods 470// Public methods
517 471
518//static
519BOOL LLTextEditor::isPartOfWord(llwchar c) { return (c == '_') || isalnum(c); }
520
521
522
523BOOL LLTextEditor::truncate() 472BOOL LLTextEditor::truncate()
524{ 473{
525 BOOL did_truncate = FALSE; 474 BOOL did_truncate = FALSE;
@@ -581,6 +530,7 @@ void LLTextEditor::setWText(const LLWString &wtext)
581 resetDirty(); 530 resetDirty();
582} 531}
583 532
533// virtual
584void LLTextEditor::setValue(const LLSD& value) 534void LLTextEditor::setValue(const LLSD& value)
585{ 535{
586 setText(value.asString()); 536 setText(value.asString());
@@ -600,6 +550,7 @@ const LLString& LLTextEditor::getText() const
600 return mUTF8Text; 550 return mUTF8Text;
601} 551}
602 552
553// virtual
603LLSD LLTextEditor::getValue() const 554LLSD LLTextEditor::getValue() const
604{ 555{
605 return LLSD(getText()); 556 return LLSD(getText());
@@ -622,7 +573,10 @@ void LLTextEditor::setBorderVisible(BOOL b)
622 mBorder->setVisible(b); 573 mBorder->setVisible(b);
623} 574}
624 575
625 576BOOL LLTextEditor::isBorderVisible() const
577{
578 return mBorder->getVisible();
579}
626 580
627void LLTextEditor::setHideScrollbarForShortDocs(BOOL b) 581void LLTextEditor::setHideScrollbarForShortDocs(BOOL b)
628{ 582{
@@ -734,12 +688,6 @@ void LLTextEditor::replaceTextAll(const LLString& search_text, const LLString& r
734 mScrollbar->setDocPos(cur_pos); 688 mScrollbar->setDocPos(cur_pos);
735} 689}
736 690
737void LLTextEditor::setTakesNonScrollClicks(BOOL b)
738{
739 mTakesNonScrollClicks = b;
740}
741
742
743// Picks a new cursor position based on the screen size of text being drawn. 691// Picks a new cursor position based on the screen size of text being drawn.
744void LLTextEditor::setCursorAtLocalPos( S32 local_x, S32 local_y, BOOL round ) 692void LLTextEditor::setCursorAtLocalPos( S32 local_x, S32 local_y, BOOL round )
745{ 693{
@@ -774,11 +722,6 @@ S32 LLTextEditor::nextWordPos(S32 cursorPos) const
774 return cursorPos; 722 return cursorPos;
775} 723}
776 724
777S32 LLTextEditor::getLineCount() const
778{
779 return mLineStartList.size();
780}
781
782S32 LLTextEditor::getLineStart( S32 line ) const 725S32 LLTextEditor::getLineStart( S32 line ) const
783{ 726{
784 S32 num_lines = getLineCount(); 727 S32 num_lines = getLineCount();
@@ -796,7 +739,7 @@ S32 LLTextEditor::getLineStart( S32 line ) const
796} 739}
797 740
798// Given an offset into text (pos), find the corresponding line (from the start of the doc) and an offset into the line. 741// Given an offset into text (pos), find the corresponding line (from the start of the doc) and an offset into the line.
799void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp ) 742void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp ) const
800{ 743{
801 if (mLineStartList.empty()) 744 if (mLineStartList.empty())
802 { 745 {
@@ -809,7 +752,7 @@ void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp )
809 getSegmentAndOffset( startpos, &seg_idx, &seg_offset ); 752 getSegmentAndOffset( startpos, &seg_idx, &seg_offset );
810 753
811 line_info tline(seg_idx, seg_offset); 754 line_info tline(seg_idx, seg_offset);
812 line_list_t::iterator iter = std::upper_bound(mLineStartList.begin(), mLineStartList.end(), tline, line_info_compare()); 755 line_list_t::const_iterator iter = std::upper_bound(mLineStartList.begin(), mLineStartList.end(), tline, line_info_compare());
813 if (iter != mLineStartList.begin()) --iter; 756 if (iter != mLineStartList.begin()) --iter;
814 *linep = iter - mLineStartList.begin(); 757 *linep = iter - mLineStartList.begin();
815 S32 line_start = mSegments[iter->mSegment]->getStart() + iter->mOffset; 758 S32 line_start = mSegments[iter->mSegment]->getStart() + iter->mOffset;
@@ -817,7 +760,7 @@ void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp )
817 } 760 }
818} 761}
819 762
820void LLTextEditor::getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) 763void LLTextEditor::getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) const
821{ 764{
822 if (mSegments.empty()) 765 if (mSegments.empty())
823 { 766 {
@@ -826,46 +769,21 @@ void LLTextEditor::getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp
826 } 769 }
827 770
828 LLTextSegment tseg(startpos); 771 LLTextSegment tseg(startpos);
829 segment_list_t::iterator seg_iter; 772 segment_list_t::const_iterator seg_iter;
830 seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &tseg, LLTextSegment::compare()); 773 seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &tseg, LLTextSegment::compare());
831 if (seg_iter != mSegments.begin()) --seg_iter; 774 if (seg_iter != mSegments.begin()) --seg_iter;
832 *segidxp = seg_iter - mSegments.begin(); 775 *segidxp = seg_iter - mSegments.begin();
833 *offsetp = startpos - (*seg_iter)->getStart(); 776 *offsetp = startpos - (*seg_iter)->getStart();
834} 777}
835 778
836const LLWString& LLTextEditor::getWText() const 779const LLTextSegment* LLTextEditor::getPreviousSegment()
837{
838 return mWText;
839}
840
841S32 LLTextEditor::getLength() const
842{
843 return mWText.length();
844}
845
846llwchar LLTextEditor::getWChar(S32 pos)
847{
848 return mWText[pos];
849}
850
851LLWString LLTextEditor::getWSubString(S32 pos, S32 len)
852{
853 return mWText.substr(pos, len);
854}
855
856LLTextSegment* LLTextEditor::getCurrentSegment()
857{
858 return getSegmentAtOffset(mCursorPos);
859}
860
861LLTextSegment* LLTextEditor::getPreviousSegment()
862{ 780{
863 // find segment index at character to left of cursor (or rightmost edge of selection) 781 // find segment index at character to left of cursor (or rightmost edge of selection)
864 S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1); 782 S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1);
865 return idx >= 0 ? mSegments[idx] : NULL; 783 return idx >= 0 ? mSegments[idx] : NULL;
866} 784}
867 785
868void LLTextEditor::getSelectedSegments(std::vector<LLTextSegment*>& segments) 786void LLTextEditor::getSelectedSegments(std::vector<const LLTextSegment*>& segments)
869{ 787{
870 S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos; 788 S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
871 S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos; 789 S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
@@ -878,7 +796,7 @@ void LLTextEditor::getSelectedSegments(std::vector<LLTextSegment*>& segments)
878 } 796 }
879} 797}
880 798
881S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) 799S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
882{ 800{
883 // If round is true, if the position is on the right half of a character, the cursor 801 // If round is true, if the position is on the right half of a character, the cursor
884 // will be put to its right. If round is false, the cursor will always be put to the 802 // will be put to its right. If round is false, the cursor will always be put to the
@@ -916,13 +834,13 @@ S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL rou
916 if (mAllowEmbeddedItems) 834 if (mAllowEmbeddedItems)
917 { 835 {
918 // Figure out which character we're nearest to. 836 // Figure out which character we're nearest to.
919 bindEmbeddedChars(mGLFont); 837 bindEmbeddedChars(const_cast<LLFontGL*>(mGLFont));
920 pos = mGLFont->charFromPixelOffset(mWText.c_str(), line_start, 838 pos = mGLFont->charFromPixelOffset(mWText.c_str(), line_start,
921 (F32)(local_x - mTextRect.mLeft), 839 (F32)(local_x - mTextRect.mLeft),
922 (F32)(mTextRect.getWidth()), 840 (F32)(mTextRect.getWidth()),
923 line_len, 841 line_len,
924 round, TRUE); 842 round, TRUE);
925 unbindEmbeddedChars(mGLFont); 843 unbindEmbeddedChars(const_cast<LLFontGL*>(mGLFont));
926 } 844 }
927 else 845 else
928 { 846 {
@@ -958,8 +876,8 @@ void LLTextEditor::setCursorPos(S32 offset)
958 mDesiredXPixel = -1; 876 mDesiredXPixel = -1;
959} 877}
960 878
961 879// virtual
962BOOL LLTextEditor::canDeselect() 880BOOL LLTextEditor::canDeselect() const
963{ 881{
964 return hasSelection(); 882 return hasSelection();
965} 883}
@@ -1126,12 +1044,13 @@ void LLTextEditor::indentSelectedLines( S32 spaces )
1126 } 1044 }
1127} 1045}
1128 1046
1129 1047//virtual
1130BOOL LLTextEditor::canSelectAll() 1048BOOL LLTextEditor::canSelectAll() const
1131{ 1049{
1132 return TRUE; 1050 return TRUE;
1133} 1051}
1134 1052
1053// virtual
1135void LLTextEditor::selectAll() 1054void LLTextEditor::selectAll()
1136{ 1055{
1137 mSelectionStart = getLength(); 1056 mSelectionStart = getLength();
@@ -1143,7 +1062,7 @@ void LLTextEditor::selectAll()
1143BOOL LLTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) 1062BOOL LLTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
1144{ 1063{
1145 for ( child_list_const_iter_t child_it = getChildList()->begin(); 1064 for ( child_list_const_iter_t child_it = getChildList()->begin();
1146 child_it != getChildList()->end(); ++child_it) 1065 child_it != getChildList()->end(); ++child_it)
1147 { 1066 {
1148 LLView* viewp = *child_it; 1067 LLView* viewp = *child_it;
1149 S32 local_x = x - viewp->getRect().mLeft; 1068 S32 local_x = x - viewp->getRect().mLeft;
@@ -1159,7 +1078,7 @@ BOOL LLTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rec
1159 return TRUE; 1078 return TRUE;
1160 } 1079 }
1161 1080
1162 LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); 1081 const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
1163 if( cur_segment ) 1082 if( cur_segment )
1164 { 1083 {
1165 BOOL has_tool_tip = FALSE; 1084 BOOL has_tool_tip = FALSE;
@@ -1267,7 +1186,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
1267 } 1186 }
1268 1187
1269 // Delay cursor flashing 1188 // Delay cursor flashing
1270 mKeystrokeTimer.reset(); 1189 resetKeystrokeTimer();
1271 1190
1272 return handled; 1191 return handled;
1273} 1192}
@@ -1320,7 +1239,7 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
1320 if( handled ) 1239 if( handled )
1321 { 1240 {
1322 // Delay cursor flashing 1241 // Delay cursor flashing
1323 mKeystrokeTimer.reset(); 1242 resetKeystrokeTimer();
1324 } 1243 }
1325 1244
1326 // Opaque 1245 // Opaque
@@ -1329,7 +1248,7 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
1329 // Check to see if we're over an HTML-style link 1248 // Check to see if we're over an HTML-style link
1330 if( !mSegments.empty() ) 1249 if( !mSegments.empty() )
1331 { 1250 {
1332 LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); 1251 const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
1333 if( cur_segment ) 1252 if( cur_segment )
1334 { 1253 {
1335 if(cur_segment->getStyle().isLink()) 1254 if(cur_segment->getStyle().isLink())
@@ -1353,7 +1272,7 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
1353 if( !handled ) 1272 if( !handled )
1354 { 1273 {
1355 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl; 1274 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
1356 if (!mScrollbar->getVisible() || x < mRect.getWidth() - SCROLLBAR_SIZE) 1275 if (!mScrollbar->getVisible() || x < getRect().getWidth() - SCROLLBAR_SIZE)
1357 { 1276 {
1358 getWindow()->setCursor(UI_CURSOR_IBEAM); 1277 getWindow()->setCursor(UI_CURSOR_IBEAM);
1359 } 1278 }
@@ -1411,7 +1330,7 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
1411 } 1330 }
1412 1331
1413 // Delay cursor flashing 1332 // Delay cursor flashing
1414 mKeystrokeTimer.reset(); 1333 resetKeystrokeTimer();
1415 1334
1416 if( hasMouseCapture() ) 1335 if( hasMouseCapture() )
1417 { 1336 {
@@ -1467,7 +1386,7 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
1467 mIsSelecting = FALSE; 1386 mIsSelecting = FALSE;
1468 1387
1469 // delay cursor flashing 1388 // delay cursor flashing
1470 mKeystrokeTimer.reset(); 1389 resetKeystrokeTimer();
1471 1390
1472 handled = TRUE; 1391 handled = TRUE;
1473 } 1392 }
@@ -1548,50 +1467,51 @@ S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc)
1548// a pseudo-tab (up to for spaces in a row) 1467// a pseudo-tab (up to for spaces in a row)
1549void LLTextEditor::removeCharOrTab() 1468void LLTextEditor::removeCharOrTab()
1550{ 1469{
1551 if( getEnabled() ) 1470 if( !getEnabled() )
1552 { 1471 {
1553 if( mCursorPos > 0 ) 1472 return;
1554 { 1473 }
1555 S32 chars_to_remove = 1; 1474 if( mCursorPos > 0 )
1475 {
1476 S32 chars_to_remove = 1;
1556 1477
1557 const LLWString &text = mWText; 1478 const LLWString &text = mWText;
1558 if (text[mCursorPos - 1] == ' ') 1479 if (text[mCursorPos - 1] == ' ')
1480 {
1481 // Try to remove a "tab"
1482 S32 line, offset;
1483 getLineAndOffset(mCursorPos, &line, &offset);
1484 if (offset > 0)
1559 { 1485 {
1560 // Try to remove a "tab" 1486 chars_to_remove = offset % SPACES_PER_TAB;
1561 S32 line, offset; 1487 if( chars_to_remove == 0 )
1562 getLineAndOffset(mCursorPos, &line, &offset);
1563 if (offset > 0)
1564 { 1488 {
1565 chars_to_remove = offset % SPACES_PER_TAB; 1489 chars_to_remove = SPACES_PER_TAB;
1566 if( chars_to_remove == 0 ) 1490 }
1567 {
1568 chars_to_remove = SPACES_PER_TAB;
1569 }
1570 1491
1571 for( S32 i = 0; i < chars_to_remove; i++ ) 1492 for( S32 i = 0; i < chars_to_remove; i++ )
1493 {
1494 if (text[ mCursorPos - i - 1] != ' ')
1572 { 1495 {
1573 if (text[ mCursorPos - i - 1] != ' ') 1496 // Fewer than a full tab's worth of spaces, so
1574 { 1497 // just delete a single character.
1575 // Fewer than a full tab's worth of spaces, so 1498 chars_to_remove = 1;
1576 // just delete a single character. 1499 break;
1577 chars_to_remove = 1;
1578 break;
1579 }
1580 } 1500 }
1581 } 1501 }
1582 } 1502 }
1583
1584 for (S32 i = 0; i < chars_to_remove; i++)
1585 {
1586 setCursorPos(mCursorPos - 1);
1587 remove( mCursorPos, 1, FALSE );
1588 }
1589 } 1503 }
1590 else 1504
1505 for (S32 i = 0; i < chars_to_remove; i++)
1591 { 1506 {
1592 reportBadKeystroke(); 1507 setCursorPos(mCursorPos - 1);
1508 remove( mCursorPos, 1, FALSE );
1593 } 1509 }
1594 } 1510 }
1511 else
1512 {
1513 reportBadKeystroke();
1514 }
1595} 1515}
1596 1516
1597// Remove a single character from the text 1517// Remove a single character from the text
@@ -1602,17 +1522,18 @@ S32 LLTextEditor::removeChar(S32 pos)
1602 1522
1603void LLTextEditor::removeChar() 1523void LLTextEditor::removeChar()
1604{ 1524{
1605 if (getEnabled()) 1525 if (!getEnabled())
1606 { 1526 {
1607 if (mCursorPos > 0) 1527 return;
1608 { 1528 }
1609 setCursorPos(mCursorPos - 1); 1529 if (mCursorPos > 0)
1610 removeChar(mCursorPos); 1530 {
1611 } 1531 setCursorPos(mCursorPos - 1);
1612 else 1532 removeChar(mCursorPos);
1613 { 1533 }
1614 reportBadKeystroke(); 1534 else
1615 } 1535 {
1536 reportBadKeystroke();
1616 } 1537 }
1617} 1538}
1618 1539
@@ -1639,19 +1560,20 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc)
1639 1560
1640void LLTextEditor::addChar(llwchar wc) 1561void LLTextEditor::addChar(llwchar wc)
1641{ 1562{
1642 if( getEnabled() ) 1563 if( !getEnabled() )
1643 { 1564 {
1644 if( hasSelection() ) 1565 return;
1645 {
1646 deleteSelection(TRUE);
1647 }
1648 else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
1649 {
1650 removeChar(mCursorPos);
1651 }
1652
1653 setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
1654 } 1566 }
1567 if( hasSelection() )
1568 {
1569 deleteSelection(TRUE);
1570 }
1571 else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
1572 {
1573 removeChar(mCursorPos);
1574 }
1575
1576 setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
1655} 1577}
1656 1578
1657 1579
@@ -1747,7 +1669,6 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask)
1747 } 1669 }
1748 } 1670 }
1749 1671
1750
1751 if( !handled && mHandleEditKeysDirectly ) 1672 if( !handled && mHandleEditKeysDirectly )
1752 { 1673 {
1753 if( (MASK_CONTROL & mask) && ('A' == key) ) 1674 if( (MASK_CONTROL & mask) && ('A' == key) )
@@ -1900,7 +1821,8 @@ void LLTextEditor::deleteSelection(BOOL group_with_next_op )
1900 } 1821 }
1901} 1822}
1902 1823
1903BOOL LLTextEditor::canCut() 1824// virtual
1825BOOL LLTextEditor::canCut() const
1904{ 1826{
1905 return !mReadOnly && hasSelection(); 1827 return !mReadOnly && hasSelection();
1906} 1828}
@@ -1908,36 +1830,37 @@ BOOL LLTextEditor::canCut()
1908// cut selection to clipboard 1830// cut selection to clipboard
1909void LLTextEditor::cut() 1831void LLTextEditor::cut()
1910{ 1832{
1911 if( canCut() ) 1833 if( !canCut() )
1912 { 1834 {
1913 S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); 1835 return;
1914 S32 length = abs( mSelectionStart - mSelectionEnd );
1915 gClipboard.copyFromSubstring( mWText, left_pos, length, mSourceID );
1916 deleteSelection( FALSE );
1917
1918 updateLineStartList();
1919 updateScrollFromCursor();
1920 } 1836 }
1837 S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
1838 S32 length = abs( mSelectionStart - mSelectionEnd );
1839 gClipboard.copyFromSubstring( mWText, left_pos, length, mSourceID );
1840 deleteSelection( FALSE );
1841
1842 updateLineStartList();
1843 updateScrollFromCursor();
1921} 1844}
1922 1845
1923BOOL LLTextEditor::canCopy() 1846BOOL LLTextEditor::canCopy() const
1924{ 1847{
1925 return hasSelection(); 1848 return hasSelection();
1926} 1849}
1927 1850
1928
1929// copy selection to clipboard 1851// copy selection to clipboard
1930void LLTextEditor::copy() 1852void LLTextEditor::copy()
1931{ 1853{
1932 if( canCopy() ) 1854 if( !canCopy() )
1933 { 1855 {
1934 S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); 1856 return;
1935 S32 length = abs( mSelectionStart - mSelectionEnd );
1936 gClipboard.copyFromSubstring(mWText, left_pos, length, mSourceID);
1937 } 1857 }
1858 S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
1859 S32 length = abs( mSelectionStart - mSelectionEnd );
1860 gClipboard.copyFromSubstring(mWText, left_pos, length, mSourceID);
1938} 1861}
1939 1862
1940BOOL LLTextEditor::canPaste() 1863BOOL LLTextEditor::canPaste() const
1941{ 1864{
1942 return !mReadOnly && gClipboard.canPasteString(); 1865 return !mReadOnly && gClipboard.canPasteString();
1943} 1866}
@@ -1946,47 +1869,49 @@ BOOL LLTextEditor::canPaste()
1946// paste from clipboard 1869// paste from clipboard
1947void LLTextEditor::paste() 1870void LLTextEditor::paste()
1948{ 1871{
1949 if (canPaste()) 1872 if (!canPaste())
1873 {
1874 return;
1875 }
1876 LLUUID source_id;
1877 LLWString paste = gClipboard.getPasteWString(&source_id);
1878 if (paste.empty())
1950 { 1879 {
1951 LLUUID source_id; 1880 return;
1952 LLWString paste = gClipboard.getPasteWString(&source_id); 1881 }
1953 if (!paste.empty()) 1882 // Delete any selected characters (the paste replaces them)
1883 if( hasSelection() )
1884 {
1885 deleteSelection(TRUE);
1886 }
1887
1888 // Clean up string (replace tabs and remove characters that our fonts don't support).
1889 LLWString clean_string(paste);
1890 LLWString::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB);
1891 if( mAllowEmbeddedItems )
1892 {
1893 const llwchar LF = 10;
1894 S32 len = clean_string.length();
1895 for( S32 i = 0; i < len; i++ )
1954 { 1896 {
1955 // Delete any selected characters (the paste replaces them) 1897 llwchar wc = clean_string[i];
1956 if( hasSelection() ) 1898 if( (wc < LLFont::FIRST_CHAR) && (wc != LF) )
1957 { 1899 {
1958 deleteSelection(TRUE); 1900 clean_string[i] = LL_UNKNOWN_CHAR;
1959 } 1901 }
1960 1902 else if (wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR)
1961 // Clean up string (replace tabs and remove characters that our fonts don't support).
1962 LLWString clean_string(paste);
1963 LLWString::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB);
1964 if( mAllowEmbeddedItems )
1965 { 1903 {
1966 const llwchar LF = 10; 1904 clean_string[i] = pasteEmbeddedItem(wc);
1967 S32 len = clean_string.length();
1968 for( S32 i = 0; i < len; i++ )
1969 {
1970 llwchar wc = clean_string[i];
1971 if( (wc < LLFont::FIRST_CHAR) && (wc != LF) )
1972 {
1973 clean_string[i] = LL_UNKNOWN_CHAR;
1974 }
1975 else if (wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR)
1976 {
1977 clean_string[i] = pasteEmbeddedItem(wc);
1978 }
1979 }
1980 } 1905 }
1981
1982 // Insert the new text into the existing text.
1983 setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE));
1984 deselect();
1985
1986 updateLineStartList();
1987 updateScrollFromCursor();
1988 } 1906 }
1989 } 1907 }
1908
1909 // Insert the new text into the existing text.
1910 setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE));
1911 deselect();
1912
1913 updateLineStartList();
1914 updateScrollFromCursor();
1990} 1915}
1991 1916
1992 1917
@@ -2240,7 +2165,7 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
2240 { 2165 {
2241 // Special case for TAB. If want to move to next field, report 2166 // Special case for TAB. If want to move to next field, report
2242 // not handled and let the parent take care of field movement. 2167 // not handled and let the parent take care of field movement.
2243 if (KEY_TAB == key && mTabToNextField) 2168 if (KEY_TAB == key && mTabsToNextField)
2244 { 2169 {
2245 return FALSE; 2170 return FALSE;
2246 } 2171 }
@@ -2296,7 +2221,7 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
2296 2221
2297 if( handled ) 2222 if( handled )
2298 { 2223 {
2299 mKeystrokeTimer.reset(); 2224 resetKeystrokeTimer();
2300 2225
2301 // Most keystrokes will make the selection box go away, but not all will. 2226 // Most keystrokes will make the selection box go away, but not all will.
2302 if( !selection_modified && 2227 if( !selection_modified &&
@@ -2350,7 +2275,7 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_pare
2350 2275
2351 if( handled ) 2276 if( handled )
2352 { 2277 {
2353 mKeystrokeTimer.reset(); 2278 resetKeystrokeTimer();
2354 2279
2355 // 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.
2356 deselect(); 2281 deselect();
@@ -2364,58 +2289,58 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_pare
2364} 2289}
2365 2290
2366 2291
2367 2292// virtual
2368BOOL LLTextEditor::canDoDelete() 2293BOOL LLTextEditor::canDoDelete() const
2369{ 2294{
2370 return !mReadOnly && ( hasSelection() || (mCursorPos < getLength()) ); 2295 return !mReadOnly && ( hasSelection() || (mCursorPos < getLength()) );
2371} 2296}
2372 2297
2373void LLTextEditor::doDelete() 2298void LLTextEditor::doDelete()
2374{ 2299{
2375 if( canDoDelete() ) 2300 if( !canDoDelete() )
2376 { 2301 {
2377 if( hasSelection() ) 2302 return;
2303 }
2304 if( hasSelection() )
2305 {
2306 deleteSelection(FALSE);
2307 }
2308 else
2309 if( mCursorPos < getLength() )
2310 {
2311 S32 i;
2312 S32 chars_to_remove = 1;
2313 const LLWString &text = mWText;
2314 if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) )
2378 { 2315 {
2379 deleteSelection(FALSE); 2316 // Try to remove a full tab's worth of spaces
2380 } 2317 S32 line, offset;
2381 else 2318 getLineAndOffset( mCursorPos, &line, &offset );
2382 if( mCursorPos < getLength() ) 2319 chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
2383 { 2320 if( chars_to_remove == 0 )
2384 S32 i;
2385 S32 chars_to_remove = 1;
2386 const LLWString &text = mWText;
2387 if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) )
2388 { 2321 {
2389 // Try to remove a full tab's worth of spaces 2322 chars_to_remove = SPACES_PER_TAB;
2390 S32 line, offset;
2391 getLineAndOffset( mCursorPos, &line, &offset );
2392 chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
2393 if( chars_to_remove == 0 )
2394 {
2395 chars_to_remove = SPACES_PER_TAB;
2396 }
2397
2398 for( i = 0; i < chars_to_remove; i++ )
2399 {
2400 if( text[mCursorPos + i] != ' ' )
2401 {
2402 chars_to_remove = 1;
2403 break;
2404 }
2405 }
2406 } 2323 }
2407 2324
2408
2409 for( i = 0; i < chars_to_remove; i++ ) 2325 for( i = 0; i < chars_to_remove; i++ )
2410 { 2326 {
2411 setCursorPos(mCursorPos + 1); 2327 if( text[mCursorPos + i] != ' ' )
2412 removeChar(); 2328 {
2329 chars_to_remove = 1;
2330 break;
2331 }
2413 } 2332 }
2414 } 2333 }
2415 2334
2416 updateLineStartList(); 2335 for( i = 0; i < chars_to_remove; i++ )
2417 updateScrollFromCursor(); 2336 {
2337 setCursorPos(mCursorPos + 1);
2338 removeChar();
2339 }
2418 } 2340 }
2341
2342 updateLineStartList();
2343 updateScrollFromCursor();
2419} 2344}
2420 2345
2421//---------------------------------------------------------------------------- 2346//----------------------------------------------------------------------------
@@ -2429,65 +2354,66 @@ void LLTextEditor::blockUndo()
2429 mUndoStack.clear(); 2354 mUndoStack.clear();
2430} 2355}
2431 2356
2432 2357// virtual
2433BOOL LLTextEditor::canUndo() 2358BOOL LLTextEditor::canUndo() const
2434{ 2359{
2435 return !mReadOnly && mLastCmd != NULL; 2360 return !mReadOnly && mLastCmd != NULL;
2436} 2361}
2437 2362
2438void LLTextEditor::undo() 2363void LLTextEditor::undo()
2439{ 2364{
2440 if( canUndo() ) 2365 if( !canUndo() )
2441 { 2366 {
2442 deselect(); 2367 return;
2443 2368 }
2444 S32 pos = 0; 2369 deselect();
2445 do 2370 S32 pos = 0;
2446 { 2371 do
2447 pos = mLastCmd->undo(this); 2372 {
2448 undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd); 2373 pos = mLastCmd->undo(this);
2449 if (iter != mUndoStack.end()) 2374 undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
2450 ++iter; 2375 if (iter != mUndoStack.end())
2451 if (iter != mUndoStack.end()) 2376 ++iter;
2452 mLastCmd = *iter; 2377 if (iter != mUndoStack.end())
2453 else 2378 mLastCmd = *iter;
2454 mLastCmd = NULL; 2379 else
2380 mLastCmd = NULL;
2455 2381
2456 } while( mLastCmd && mLastCmd->groupWithNext() ); 2382 } while( mLastCmd && mLastCmd->groupWithNext() );
2457 2383
2458 setCursorPos(pos); 2384 setCursorPos(pos);
2459 2385
2460 updateLineStartList(); 2386 updateLineStartList();
2461 updateScrollFromCursor(); 2387 updateScrollFromCursor();
2462 }
2463} 2388}
2464 2389
2465BOOL LLTextEditor::canRedo() 2390BOOL LLTextEditor::canRedo() const
2466{ 2391{
2467 return !mReadOnly && (mUndoStack.size() > 0) && (mLastCmd != mUndoStack.front()); 2392 return !mReadOnly && (mUndoStack.size() > 0) && (mLastCmd != mUndoStack.front());
2468} 2393}
2469 2394
2470void LLTextEditor::redo() 2395void LLTextEditor::redo()
2471{ 2396{
2472 if( canRedo() ) 2397 if( !canRedo() )
2473 { 2398 {
2474 deselect(); 2399 return;
2475 2400 }
2476 S32 pos = 0; 2401 deselect();
2477 do 2402 S32 pos = 0;
2403 do
2404 {
2405 if( !mLastCmd )
2478 { 2406 {
2479 if( !mLastCmd ) 2407 mLastCmd = mUndoStack.back();
2480 { 2408 }
2481 mLastCmd = mUndoStack.back(); 2409 else
2482 } 2410 {
2411 undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
2412 if (iter != mUndoStack.begin())
2413 mLastCmd = *(--iter);
2483 else 2414 else
2484 { 2415 mLastCmd = NULL;
2485 undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd); 2416 }
2486 if (iter != mUndoStack.begin())
2487 mLastCmd = *(--iter);
2488 else
2489 mLastCmd = NULL;
2490 }
2491 2417
2492 if( mLastCmd ) 2418 if( mLastCmd )
2493 { 2419 {
@@ -2500,9 +2426,8 @@ void LLTextEditor::redo()
2500 2426
2501 setCursorPos(pos); 2427 setCursorPos(pos);
2502 2428
2503 updateLineStartList(); 2429 updateLineStartList();
2504 updateScrollFromCursor(); 2430 updateScrollFromCursor();
2505 }
2506} 2431}
2507 2432
2508void LLTextEditor::onFocusReceived() 2433void LLTextEditor::onFocusReceived()
@@ -2548,8 +2473,8 @@ void LLTextEditor::setEnabled(BOOL enabled)
2548void LLTextEditor::drawBackground() 2473void LLTextEditor::drawBackground()
2549{ 2474{
2550 S32 left = 0; 2475 S32 left = 0;
2551 S32 top = mRect.getHeight(); 2476 S32 top = getRect().getHeight();
2552 S32 right = mRect.getWidth(); 2477 S32 right = getRect().getWidth();
2553 S32 bottom = 0; 2478 S32 bottom = 0;
2554 2479
2555 LLColor4 bg_color = mReadOnlyBgColor; 2480 LLColor4 bg_color = mReadOnlyBgColor;
@@ -2677,7 +2602,7 @@ void LLTextEditor::drawSelectionBackground()
2677 LLGLSNoTexture no_texture; 2602 LLGLSNoTexture no_texture;
2678 const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor; 2603 const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor;
2679 F32 alpha = hasFocus() ? 1.f : 0.5f; 2604 F32 alpha = hasFocus() ? 1.f : 0.5f;
2680 glColor4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); 2605 gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha );
2681 2606
2682 if( selection_left_y == selection_right_y ) 2607 if( selection_left_y == selection_right_y )
2683 { 2608 {
@@ -2805,14 +2730,14 @@ void LLTextEditor::drawCursor()
2805 2730
2806 LLGLSNoTexture no_texture; 2731 LLGLSNoTexture no_texture;
2807 2732
2808 glColor4fv( mCursorColor.mV ); 2733 gGL.color4fv( mCursorColor.mV );
2809 2734
2810 gl_rect_2d(llfloor(cursor_left), llfloor(cursor_top), 2735 gl_rect_2d(llfloor(cursor_left), llfloor(cursor_top),
2811 llfloor(cursor_right), llfloor(cursor_bottom)); 2736 llfloor(cursor_right), llfloor(cursor_bottom));
2812 2737
2813 if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection() && text[mCursorPos] != '\n') 2738 if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection() && text[mCursorPos] != '\n')
2814 { 2739 {
2815 LLTextSegment* segmentp = getSegmentAtOffset(mCursorPos); 2740 const LLTextSegment* segmentp = getSegmentAtOffset(mCursorPos);
2816 LLColor4 text_color; 2741 LLColor4 text_color;
2817 if (segmentp) 2742 if (segmentp)
2818 { 2743 {
@@ -2826,7 +2751,6 @@ void LLTextEditor::drawCursor()
2826 { 2751 {
2827 text_color = mFgColor; 2752 text_color = mFgColor;
2828 } 2753 }
2829 LLGLSTexture texture;
2830 mGLFont->render(text, mCursorPos, next_char_left, cursor_bottom + line_height, 2754 mGLFont->render(text, mCursorPos, next_char_left, cursor_bottom + line_height,
2831 LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], 1.f), 2755 LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], 1.f),
2832 LLFontGL::LEFT, LLFontGL::TOP, 2756 LLFontGL::LEFT, LLFontGL::TOP,
@@ -2945,122 +2869,118 @@ void LLTextEditor::drawText()
2945{ 2869{
2946 const LLWString &text = mWText; 2870 const LLWString &text = mWText;
2947 const S32 text_len = getLength(); 2871 const S32 text_len = getLength();
2872 if( text_len <= 0 )
2873 {
2874 return;
2875 }
2876 S32 selection_left = -1;
2877 S32 selection_right = -1;
2878 // Draw selection even if we don't have keyboard focus for search/replace
2879 if( hasSelection())
2880 {
2881 selection_left = llmin( mSelectionStart, mSelectionEnd );
2882 selection_right = llmax( mSelectionStart, mSelectionEnd );
2883 }
2948 2884
2949 if( text_len > 0 ) 2885 LLGLSUIDefault gls_ui;
2886
2887 S32 cur_line = mScrollbar->getDocPos();
2888 S32 num_lines = getLineCount();
2889 if (cur_line >= num_lines)
2890 {
2891 return;
2892 }
2893
2894 S32 line_start = getLineStart(cur_line);
2895 LLTextSegment t(line_start);
2896 segment_list_t::iterator seg_iter;
2897 seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &t, LLTextSegment::compare());
2898 if (seg_iter == mSegments.end() || (*seg_iter)->getStart() > line_start) --seg_iter;
2899 LLTextSegment* cur_segment = *seg_iter;
2900
2901 S32 line_height = llround( mGLFont->getLineHeight() );
2902 F32 text_y = (F32)(mTextRect.mTop - line_height);
2903 while((mTextRect.mBottom <= text_y) && (cur_line < num_lines))
2950 { 2904 {
2951 S32 selection_left = -1; 2905 S32 next_start = -1;
2952 S32 selection_right = -1; 2906 S32 line_end = text_len;
2953 // Draw selection even if we don't have keyboard focus for search/replace 2907
2954 if( hasSelection()) 2908 if ((cur_line + 1) < num_lines)
2955 { 2909 {
2956 selection_left = llmin( mSelectionStart, mSelectionEnd ); 2910 next_start = getLineStart(cur_line + 1);
2957 selection_right = llmax( mSelectionStart, mSelectionEnd ); 2911 line_end = next_start;
2958 } 2912 }
2959 2913 if ( text[line_end-1] == '\n' )
2960 LLGLSUIDefault gls_ui;
2961
2962 S32 cur_line = mScrollbar->getDocPos();
2963 S32 num_lines = getLineCount();
2964 if (cur_line >= num_lines)
2965 { 2914 {
2966 return; 2915 --line_end;
2967 } 2916 }
2968 2917
2969 S32 line_start = getLineStart(cur_line); 2918 F32 text_x = (F32)mTextRect.mLeft;
2970 LLTextSegment t(line_start);
2971 segment_list_t::iterator seg_iter;
2972 seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &t, LLTextSegment::compare());
2973 if (seg_iter == mSegments.end() || (*seg_iter)->getStart() > line_start) --seg_iter;
2974 LLTextSegment* cur_segment = *seg_iter;
2975
2976 S32 line_height = llround( mGLFont->getLineHeight() );
2977 F32 text_y = (F32)(mTextRect.mTop - line_height);
2978 while((mTextRect.mBottom <= text_y) && (cur_line < num_lines))
2979 {
2980 S32 next_start = -1;
2981 S32 line_end = text_len;
2982 2919
2983 if ((cur_line + 1) < num_lines) 2920 S32 seg_start = line_start;
2984 { 2921 while( seg_start < line_end )
2985 next_start = getLineStart(cur_line + 1); 2922 {
2986 line_end = next_start; 2923 while( cur_segment->getEnd() <= seg_start )
2987 }
2988 if ( text[line_end-1] == '\n' )
2989 { 2924 {
2990 --line_end; 2925 seg_iter++;
2926 if (seg_iter == mSegments.end())
2927 {
2928 llwarns << "Ran off the segmentation end!" << llendl;
2929 return;
2930 }
2931 cur_segment = *seg_iter;
2991 } 2932 }
2992 2933
2993 F32 text_x = (F32)mTextRect.mLeft; 2934 // Draw a segment within the line
2994 2935 S32 clipped_end = llmin( line_end, cur_segment->getEnd() );
2995 S32 seg_start = line_start; 2936 S32 clipped_len = clipped_end - seg_start;
2996 while( seg_start < line_end ) 2937 if( clipped_len > 0 )
2997 { 2938 {
2998 while( cur_segment->getEnd() <= seg_start ) 2939 LLStyle style = cur_segment->getStyle();
2940 if ( style.isImage() && (cur_segment->getStart() >= seg_start) && (cur_segment->getStart() <= clipped_end))
2999 { 2941 {
3000 seg_iter++; 2942 LLImageGL *image = style.getImage();
3001 if (seg_iter == mSegments.end()) 2943 gl_draw_scaled_image( llround(text_x), llround(text_y)+line_height-style.mImageHeight, style.mImageWidth, style.mImageHeight, image, LLColor4::white );
3002 {
3003 llwarns << "Ran off the segmentation end!" << llendl;
3004 return;
3005 }
3006 cur_segment = *seg_iter;
3007 } 2944 }
3008
3009 // Draw a segment within the line
3010 S32 clipped_end = llmin( line_end, cur_segment->getEnd() );
3011 S32 clipped_len = clipped_end - seg_start;
3012 if( clipped_len > 0 )
3013 {
3014 LLStyle style = cur_segment->getStyle();
3015 if ( style.isImage() && (cur_segment->getStart() >= seg_start) && (cur_segment->getStart() <= clipped_end))
3016 {
3017 LLImageGL *image = style.getImage();
3018
3019 gl_draw_scaled_image( llround(text_x), llround(text_y)+line_height-style.mImageHeight, style.mImageWidth, style.mImageHeight, image, LLColor4::white );
3020
3021 }
3022 2945
3023 if (cur_segment == mHoverSegment && style.getIsEmbeddedItem()) 2946 if (cur_segment == mHoverSegment && style.getIsEmbeddedItem())
3024 { 2947 {
3025 style.mUnderline = TRUE; 2948 style.mUnderline = TRUE;
3026 } 2949 }
3027 2950
3028 S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); 2951 S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
3029 2952
3030 if ( (mParseHTML) && (left_pos > seg_start) && (left_pos < clipped_end) && mIsSelecting && (mSelectionStart == mSelectionEnd) ) 2953 if ( (mParseHTML) && (left_pos > seg_start) && (left_pos < clipped_end) && mIsSelecting && (mSelectionStart == mSelectionEnd) )
3031 { 2954 {
3032 mHTML = style.getLinkHREF(); 2955 mHTML = style.getLinkHREF();
3033 } 2956 }
3034 2957
3035 drawClippedSegment( text, seg_start, clipped_end, text_x, text_y, selection_left, selection_right, style, &text_x ); 2958 drawClippedSegment( text, seg_start, clipped_end, text_x, text_y, selection_left, selection_right, style, &text_x );
3036 2959
3037 // Note: text_x is incremented by drawClippedSegment() 2960 // Note: text_x is incremented by drawClippedSegment()
3038 seg_start += clipped_len; 2961 seg_start += clipped_len;
3039 }
3040 } 2962 }
2963 }
3041 2964
3042 // move down one line 2965 // move down one line
3043 text_y -= (F32)line_height; 2966 text_y -= (F32)line_height;
3044 2967
3045 line_start = next_start; 2968 line_start = next_start;
3046 cur_line++; 2969 cur_line++;
3047 }
3048 } 2970 }
3049} 2971}
3050 2972
3051// Draws a single text segment, reversing the color for selection if needed. 2973// Draws a single text segment, reversing the color for selection if needed.
3052void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyle& style, F32* right_x ) 2974void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyle& style, F32* right_x )
3053{ 2975{
3054 const LLFontGL* font = mGLFont;
3055
3056 LLColor4 color;
3057
3058 if (!style.isVisible()) 2976 if (!style.isVisible())
3059 { 2977 {
3060 return; 2978 return;
3061 } 2979 }
3062 2980
3063 color = style.getColor(); 2981 const LLFontGL* font = mGLFont;
2982
2983 LLColor4 color = style.getColor();
3064 2984
3065 if ( style.getFontString()[0] ) 2985 if ( style.getFontString()[0] )
3066 { 2986 {
@@ -3131,12 +3051,14 @@ void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32
3131 3051
3132void LLTextEditor::draw() 3052void LLTextEditor::draw()
3133{ 3053{
3134 if( getVisible() ) 3054 if( !getVisible() )
3135 { 3055 {
3136 { 3056 return;
3137 LLLocalClipRect clip(LLRect(0, mRect.getHeight(), mRect.getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0)); 3057 }
3058 {
3059 LLLocalClipRect clip(LLRect(0, getRect().getHeight(), getRect().getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0));
3138 3060
3139 bindEmbeddedChars( mGLFont ); 3061 bindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) );
3140 3062
3141 drawBackground(); 3063 drawBackground();
3142 drawSelectionBackground(); 3064 drawSelectionBackground();
@@ -3144,34 +3066,30 @@ void LLTextEditor::draw()
3144 drawText(); 3066 drawText();
3145 drawCursor(); 3067 drawCursor();
3146 3068
3147 unbindEmbeddedChars( mGLFont ); 3069 unbindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) );
3148 3070
3149 //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret 3071 //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
3150 // when in readonly mode 3072 // when in readonly mode
3151 mBorder->setKeyboardFocusHighlight( gFocusMgr.getKeyboardFocus() == this);// && !mReadOnly); 3073 mBorder->setKeyboardFocusHighlight( gFocusMgr.getKeyboardFocus() == this);// && !mReadOnly);
3152 }
3153 LLView::draw(); // Draw children (scrollbar and border)
3154 } 3074 }
3155 3075
3156 // remember if we are supposed to be at the bottom of the buffer 3076 // remember if we are supposed to be at the bottom of the buffer
3157 mScrolledToBottom = isScrolledToBottom(); 3077 mScrolledToBottom = isScrolledToBottom();
3158}
3159 3078
3160void LLTextEditor::reportBadKeystroke() 3079 LLView::draw(); // Draw children (scrollbar and border)
3161{
3162 make_ui_sound("UISndBadKeystroke");
3163} 3080}
3164 3081
3165 3082
3166void LLTextEditor::onTabInto() 3083void LLTextEditor::onTabInto()
3167{ 3084{
3168 // selecting all on tabInto causes users to hit tab twice and replace their text with a tab character 3085 // selecting all on tabInto causes users to hit tab twice and replace their text with a tab character
3169 // theoretically, one could selectAll if mTabToNextField is true, but we couldn't think of a use case 3086 // theoretically, one could selectAll if mTabsToNextField is true, but we couldn't think of a use case
3170 // where you'd want to select all anyway 3087 // where you'd want to select all anyway
3171 // preserve insertion point when returning to the editor 3088 // preserve insertion point when returning to the editor
3172 //selectAll(); 3089 //selectAll();
3173} 3090}
3174 3091
3092// virtual
3175void LLTextEditor::clear() 3093void LLTextEditor::clear()
3176{ 3094{
3177 setText(LLString::null); 3095 setText(LLString::null);
@@ -3200,7 +3118,7 @@ void LLTextEditor::setFocus( BOOL new_state )
3200 gEditMenuHandler = this; 3118 gEditMenuHandler = this;
3201 3119
3202 // Don't start the cursor flashing right away 3120 // Don't start the cursor flashing right away
3203 mKeystrokeTimer.reset(); 3121 resetKeystrokeTimer();
3204 } 3122 }
3205 else 3123 else
3206 { 3124 {
@@ -3214,6 +3132,7 @@ void LLTextEditor::setFocus( BOOL new_state )
3214 } 3132 }
3215} 3133}
3216 3134
3135// virtual
3217BOOL LLTextEditor::acceptsTextInput() const 3136BOOL LLTextEditor::acceptsTextInput() const
3218{ 3137{
3219 return !mReadOnly; 3138 return !mReadOnly;
@@ -3268,7 +3187,7 @@ void LLTextEditor::changePage( S32 delta )
3268 3187
3269void LLTextEditor::changeLine( S32 delta ) 3188void LLTextEditor::changeLine( S32 delta )
3270{ 3189{
3271 bindEmbeddedChars( mGLFont ); 3190 bindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) );
3272 3191
3273 S32 line, offset; 3192 S32 line, offset;
3274 getLineAndOffset( mCursorPos, &line, &offset ); 3193 getLineAndOffset( mCursorPos, &line, &offset );
@@ -3295,7 +3214,7 @@ void LLTextEditor::changeLine( S32 delta )
3295 } 3214 }
3296 else 3215 else
3297 { 3216 {
3298 unbindEmbeddedChars( mGLFont ); 3217 unbindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) );
3299 return; 3218 return;
3300 } 3219 }
3301 3220
@@ -3320,7 +3239,7 @@ void LLTextEditor::changeLine( S32 delta )
3320 3239
3321 // put desired position into remember-buffer after setCursorPos() 3240 // put desired position into remember-buffer after setCursorPos()
3322 mDesiredXPixel = desired_x_pixel; 3241 mDesiredXPixel = desired_x_pixel;
3323 unbindEmbeddedChars( mGLFont ); 3242 unbindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) );
3324} 3243}
3325 3244
3326BOOL LLTextEditor::isScrolledToTop() 3245BOOL LLTextEditor::isScrolledToTop()
@@ -3768,20 +3687,14 @@ BOOL LLTextEditor::tryToRevertToPristineState()
3768 return isPristine(); // TRUE => success 3687 return isPristine(); // TRUE => success
3769} 3688}
3770 3689
3771// virtual Return TRUE if changes have been made
3772BOOL LLTextEditor::isDirty() const
3773{
3774 return( mLastCmd != NULL || (mPristineCmd && (mPristineCmd != mLastCmd)) );
3775}
3776
3777 3690
3778void LLTextEditor::updateTextRect() 3691void LLTextEditor::updateTextRect()
3779{ 3692{
3780 mTextRect.setOriginAndSize( 3693 mTextRect.setOriginAndSize(
3781 UI_TEXTEDITOR_BORDER + UI_TEXTEDITOR_H_PAD, 3694 UI_TEXTEDITOR_BORDER + UI_TEXTEDITOR_H_PAD,
3782 UI_TEXTEDITOR_BORDER, 3695 UI_TEXTEDITOR_BORDER,
3783 mRect.getWidth() - SCROLLBAR_SIZE - 2 * (UI_TEXTEDITOR_BORDER + UI_TEXTEDITOR_H_PAD), 3696 getRect().getWidth() - SCROLLBAR_SIZE - 2 * (UI_TEXTEDITOR_BORDER + UI_TEXTEDITOR_H_PAD),
3784 mRect.getHeight() - 2 * UI_TEXTEDITOR_BORDER - UI_TEXTEDITOR_V_PAD_TOP ); 3697 getRect().getHeight() - 2 * UI_TEXTEDITOR_BORDER - UI_TEXTEDITOR_V_PAD_TOP );
3785} 3698}
3786 3699
3787void LLTextEditor::loadKeywords(const LLString& filename, 3700void LLTextEditor::loadKeywords(const LLString& filename,
@@ -3862,8 +3775,7 @@ void LLTextEditor::pruneSegments()
3862 } 3775 }
3863 else 3776 else
3864 { 3777 {
3865 llwarns << "Tried to erase end of empty LLTextEditor" 3778 llwarns << "Tried to erase end of empty LLTextEditor" << llendl;
3866 << llendl;
3867 } 3779 }
3868} 3780}
3869 3781
@@ -3949,21 +3861,9 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask)
3949 return FALSE; 3861 return FALSE;
3950} 3862}
3951 3863
3952llwchar LLTextEditor::pasteEmbeddedItem(llwchar ext_char)
3953{
3954 return ext_char;
3955}
3956
3957void LLTextEditor::bindEmbeddedChars(const LLFontGL* font)
3958{
3959}
3960
3961void LLTextEditor::unbindEmbeddedChars(const LLFontGL* font)
3962{
3963}
3964 3864
3965// Finds the text segment (if any) at the give local screen position 3865// Finds the text segment (if any) at the give local screen position
3966LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) 3866const LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) const
3967{ 3867{
3968 // Find the cursor position at the requested local screen position 3868 // Find the cursor position at the requested local screen position
3969 S32 offset = getCursorPosFromLocalCoord( x, y, FALSE ); 3869 S32 offset = getCursorPosFromLocalCoord( x, y, FALSE );
@@ -3971,13 +3871,13 @@ LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y )
3971 return idx >= 0 ? mSegments[idx] : NULL; 3871 return idx >= 0 ? mSegments[idx] : NULL;
3972} 3872}
3973 3873
3974LLTextSegment* LLTextEditor::getSegmentAtOffset(S32 offset) 3874const LLTextSegment* LLTextEditor::getSegmentAtOffset(S32 offset) const
3975{ 3875{
3976 S32 idx = getSegmentIdxAtOffset(offset); 3876 S32 idx = getSegmentIdxAtOffset(offset);
3977 return idx >= 0 ? mSegments[idx] : NULL; 3877 return idx >= 0 ? mSegments[idx] : NULL;
3978} 3878}
3979 3879
3980S32 LLTextEditor::getSegmentIdxAtOffset(S32 offset) 3880S32 LLTextEditor::getSegmentIdxAtOffset(S32 offset) const
3981{ 3881{
3982 if (mSegments.empty() || offset < 0 || offset >= getLength()) 3882 if (mSegments.empty() || offset < 0 || offset >= getLength())
3983 { 3883 {
@@ -4149,7 +4049,7 @@ LLTextSegment::LLTextSegment( const LLColor3& color, S32 start, S32 end ) :
4149{ 4049{
4150} 4050}
4151 4051
4152BOOL LLTextSegment::getToolTip(LLString& msg) 4052BOOL LLTextSegment::getToolTip(LLString& msg) const
4153{ 4053{
4154 if (mToken && !mToken->getToolTip().empty()) 4054 if (mToken && !mToken->getToolTip().empty())
4155 { 4055 {
@@ -4162,7 +4062,7 @@ BOOL LLTextSegment::getToolTip(LLString& msg)
4162 4062
4163 4063
4164 4064
4165void LLTextSegment::dump() 4065void LLTextSegment::dump() const
4166{ 4066{
4167 llinfos << "Segment [" << 4067 llinfos << "Segment [" <<
4168// mColor.mV[VX] << ", " << 4068// mColor.mV[VX] << ", " <<
@@ -4182,13 +4082,9 @@ LLXMLNodePtr LLTextEditor::getXML(bool save_children) const
4182 // Attributes 4082 // Attributes
4183 4083
4184 node->createChild("max_length", TRUE)->setIntValue(getMaxLength()); 4084 node->createChild("max_length", TRUE)->setIntValue(getMaxLength());
4185
4186 node->createChild("embedded_items", TRUE)->setBoolValue(mAllowEmbeddedItems); 4085 node->createChild("embedded_items", TRUE)->setBoolValue(mAllowEmbeddedItems);
4187
4188 node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont)); 4086 node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
4189
4190 node->createChild("word_wrap", TRUE)->setBoolValue(mWordWrap); 4087 node->createChild("word_wrap", TRUE)->setBoolValue(mWordWrap);
4191
4192 node->createChild("hide_scrollbar", TRUE)->setBoolValue(mHideScrollbarForShortDocs); 4088 node->createChild("hide_scrollbar", TRUE)->setBoolValue(mHideScrollbarForShortDocs);
4193 4089
4194 addColorXML(node, mCursorColor, "cursor_color", "TextCursorColor"); 4090 addColorXML(node, mCursorColor, "cursor_color", "TextCursorColor");
@@ -4274,7 +4170,7 @@ void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node)
4274} 4170}
4275 4171
4276/////////////////////////////////////////////////////////////////// 4172///////////////////////////////////////////////////////////////////
4277S32 LLTextEditor::findHTMLToken(const LLString &line, S32 pos, BOOL reverse) 4173S32 LLTextEditor::findHTMLToken(const LLString &line, S32 pos, BOOL reverse) const
4278{ 4174{
4279 LLString openers=" \t('\"[{<>"; 4175 LLString openers=" \t('\"[{<>";
4280 LLString closers=" \t)'\"]}><;"; 4176 LLString closers=" \t)'\"]}><;";
@@ -4311,7 +4207,7 @@ S32 LLTextEditor::findHTMLToken(const LLString &line, S32 pos, BOOL reverse)
4311 return retval; 4207 return retval;
4312} 4208}
4313 4209
4314BOOL LLTextEditor::findHTML(const LLString &line, S32 *begin, S32 *end) 4210BOOL LLTextEditor::findHTML(const LLString &line, S32 *begin, S32 *end) const
4315{ 4211{
4316 4212
4317 S32 m1,m2,m3; 4213 S32 m1,m2,m3;