diff options
Diffstat (limited to 'linden/indra/llui/lltexteditor.cpp')
-rw-r--r-- | linden/indra/llui/lltexteditor.cpp | 328 |
1 files changed, 211 insertions, 117 deletions
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp index 71522e5..e56002f 100644 --- a/linden/indra/llui/lltexteditor.cpp +++ b/linden/indra/llui/lltexteditor.cpp | |||
@@ -36,13 +36,11 @@ | |||
36 | #include "lltexteditor.h" | 36 | #include "lltexteditor.h" |
37 | 37 | ||
38 | #include "llfontgl.h" | 38 | #include "llfontgl.h" |
39 | #include "llgl.h" | ||
40 | #include "llrender.h" | 39 | #include "llrender.h" |
41 | #include "llui.h" | 40 | #include "llui.h" |
42 | #include "lluictrlfactory.h" | 41 | #include "lluictrlfactory.h" |
43 | #include "llrect.h" | 42 | #include "llrect.h" |
44 | #include "llfocusmgr.h" | 43 | #include "llfocusmgr.h" |
45 | #include "sound_ids.h" | ||
46 | #include "lltimer.h" | 44 | #include "lltimer.h" |
47 | #include "llmath.h" | 45 | #include "llmath.h" |
48 | 46 | ||
@@ -58,7 +56,6 @@ | |||
58 | #include "llcontrol.h" | 56 | #include "llcontrol.h" |
59 | #include "llimagegl.h" | 57 | #include "llimagegl.h" |
60 | #include "llwindow.h" | 58 | #include "llwindow.h" |
61 | #include "llglheaders.h" | ||
62 | #include <queue> | 59 | #include <queue> |
63 | 60 | ||
64 | // | 61 | // |
@@ -75,6 +72,8 @@ const S32 UI_TEXTEDITOR_BUFFER_BLOCK_SIZE = 512; | |||
75 | const S32 UI_TEXTEDITOR_BORDER = 1; | 72 | const S32 UI_TEXTEDITOR_BORDER = 1; |
76 | const S32 UI_TEXTEDITOR_H_PAD = 4; | 73 | const S32 UI_TEXTEDITOR_H_PAD = 4; |
77 | const S32 UI_TEXTEDITOR_V_PAD_TOP = 4; | 74 | const S32 UI_TEXTEDITOR_V_PAD_TOP = 4; |
75 | const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32; | ||
76 | const S32 UI_TEXTEDITOR_LINE_NUMBER_DIGITS = 4; | ||
78 | const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds | 77 | const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds |
79 | const S32 CURSOR_THICKNESS = 2; | 78 | const S32 CURSOR_THICKNESS = 2; |
80 | const S32 SPACES_PER_TAB = 4; | 79 | const S32 SPACES_PER_TAB = 4; |
@@ -88,8 +87,9 @@ const S32 PREEDIT_STANDOUT_GAP = 1; | |||
88 | const S32 PREEDIT_STANDOUT_POSITION = 2; | 87 | const S32 PREEDIT_STANDOUT_POSITION = 2; |
89 | const S32 PREEDIT_STANDOUT_THICKNESS = 2; | 88 | const S32 PREEDIT_STANDOUT_THICKNESS = 2; |
90 | 89 | ||
90 | |||
91 | LLColor4 LLTextEditor::mLinkColor = LLColor4::blue; | 91 | LLColor4 LLTextEditor::mLinkColor = LLColor4::blue; |
92 | void (* LLTextEditor::mURLcallback)(const char*) = NULL; | 92 | void (* LLTextEditor::mURLcallback)(const std::string&) = NULL; |
93 | bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL; | 93 | bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL; |
94 | bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL; | 94 | bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL; |
95 | 95 | ||
@@ -107,7 +107,7 @@ public: | |||
107 | virtual BOOL execute( LLTextEditor* editor, S32* delta ) | 107 | virtual BOOL execute( LLTextEditor* editor, S32* delta ) |
108 | { | 108 | { |
109 | *delta = insert(editor, getPosition(), mWString ); | 109 | *delta = insert(editor, getPosition(), mWString ); |
110 | LLWString::truncate(mWString, *delta); | 110 | LLWStringUtil::truncate(mWString, *delta); |
111 | //mWString = wstring_truncate(mWString, *delta); | 111 | //mWString = wstring_truncate(mWString, *delta); |
112 | return (*delta != 0); | 112 | return (*delta != 0); |
113 | } | 113 | } |
@@ -145,7 +145,7 @@ public: | |||
145 | virtual BOOL execute( LLTextEditor* editor, S32* delta ) | 145 | virtual BOOL execute( LLTextEditor* editor, S32* delta ) |
146 | { | 146 | { |
147 | *delta = insert(editor, getPosition(), mWString); | 147 | *delta = insert(editor, getPosition(), mWString); |
148 | LLWString::truncate(mWString, *delta); | 148 | LLWStringUtil::truncate(mWString, *delta); |
149 | //mWString = wstring_truncate(mWString, *delta); | 149 | //mWString = wstring_truncate(mWString, *delta); |
150 | return (*delta != 0); | 150 | return (*delta != 0); |
151 | } | 151 | } |
@@ -243,10 +243,10 @@ private: | |||
243 | /////////////////////////////////////////////////////////////////// | 243 | /////////////////////////////////////////////////////////////////// |
244 | 244 | ||
245 | LLTextEditor::LLTextEditor( | 245 | LLTextEditor::LLTextEditor( |
246 | const LLString& name, | 246 | const std::string& name, |
247 | const LLRect& rect, | 247 | const LLRect& rect, |
248 | S32 max_length, // In bytes | 248 | S32 max_length, // In bytes |
249 | const LLString &default_text, | 249 | const std::string &default_text, |
250 | const LLFontGL* font, | 250 | const LLFontGL* font, |
251 | BOOL allow_embedded_items) | 251 | BOOL allow_embedded_items) |
252 | : | 252 | : |
@@ -260,6 +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 | mOnScrollEndCallback( NULL ), | 264 | mOnScrollEndCallback( NULL ), |
264 | mOnScrollEndData( NULL ), | 265 | mOnScrollEndData( NULL ), |
265 | mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ), | 266 | mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ), |
@@ -271,6 +272,7 @@ LLTextEditor::LLTextEditor( | |||
271 | mFocusBgColor( LLUI::sColorsGroup->getColor( "TextBgFocusColor" ) ), | 272 | mFocusBgColor( LLUI::sColorsGroup->getColor( "TextBgFocusColor" ) ), |
272 | mReadOnly(FALSE), | 273 | mReadOnly(FALSE), |
273 | mWordWrap( FALSE ), | 274 | mWordWrap( FALSE ), |
275 | mShowLineNumbers ( FALSE ), | ||
274 | mTabsToNextField( TRUE ), | 276 | mTabsToNextField( TRUE ), |
275 | mCommitOnFocusLost( FALSE ), | 277 | mCommitOnFocusLost( FALSE ), |
276 | mHideScrollbarForShortDocs( FALSE ), | 278 | mHideScrollbarForShortDocs( FALSE ), |
@@ -311,7 +313,7 @@ LLTextEditor::LLTextEditor( | |||
311 | SCROLLBAR_SIZE, | 313 | SCROLLBAR_SIZE, |
312 | getRect().getHeight() - 1); | 314 | getRect().getHeight() - 1); |
313 | S32 lines_in_doc = getLineCount(); | 315 | S32 lines_in_doc = getLineCount(); |
314 | mScrollbar = new LLScrollbar( "Scrollbar", scroll_rect, | 316 | mScrollbar = new LLScrollbar( std::string("Scrollbar"), scroll_rect, |
315 | LLScrollbar::VERTICAL, | 317 | LLScrollbar::VERTICAL, |
316 | lines_in_doc, | 318 | lines_in_doc, |
317 | 0, | 319 | 0, |
@@ -325,7 +327,7 @@ LLTextEditor::LLTextEditor( | |||
325 | mScrollbar->setOnScrollEndCallback(mOnScrollEndCallback, mOnScrollEndData); | 327 | mScrollbar->setOnScrollEndCallback(mOnScrollEndCallback, mOnScrollEndData); |
326 | addChild(mScrollbar); | 328 | addChild(mScrollbar); |
327 | 329 | ||
328 | mBorder = new LLViewBorder( "text ed border", LLRect(0, getRect().getHeight(), getRect().getWidth(), 0), LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, UI_TEXTEDITOR_BORDER ); | 330 | mBorder = new LLViewBorder( std::string("text ed border"), LLRect(0, getRect().getHeight(), getRect().getWidth(), 0), LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, UI_TEXTEDITOR_BORDER ); |
329 | addChild( mBorder ); | 331 | addChild( mBorder ); |
330 | 332 | ||
331 | appendText(default_text, FALSE, FALSE); | 333 | appendText(default_text, FALSE, FALSE); |
@@ -333,7 +335,7 @@ LLTextEditor::LLTextEditor( | |||
333 | resetDirty(); // Update saved text state | 335 | resetDirty(); // Update saved text state |
334 | 336 | ||
335 | mParseHTML=FALSE; | 337 | mParseHTML=FALSE; |
336 | mHTML=""; | 338 | mHTML.clear(); |
337 | } | 339 | } |
338 | 340 | ||
339 | 341 | ||
@@ -399,7 +401,8 @@ void LLTextEditor::updateLineStartList(S32 startpos) | |||
399 | { | 401 | { |
400 | mLineStartList.push_back(line_info(seg_idx,seg_offset)); | 402 | mLineStartList.push_back(line_info(seg_idx,seg_offset)); |
401 | BOOL line_ended = FALSE; | 403 | BOOL line_ended = FALSE; |
402 | S32 line_width = 0; | 404 | S32 start_x = mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0; |
405 | S32 line_width = start_x; | ||
403 | while(!line_ended && seg_idx < seg_num) | 406 | while(!line_ended && seg_idx < seg_num) |
404 | { | 407 | { |
405 | LLTextSegment* segment = mSegments[seg_idx]; | 408 | LLTextSegment* segment = mSegments[seg_idx]; |
@@ -429,7 +432,7 @@ void LLTextEditor::updateLineStartList(S32 startpos) | |||
429 | const llwchar* str = mWText.c_str() + start_idx; | 432 | const llwchar* str = mWText.c_str() + start_idx; |
430 | S32 drawn = mGLFont->maxDrawableChars(str, (F32)abs(mTextRect.getWidth()) - line_width, | 433 | S32 drawn = mGLFont->maxDrawableChars(str, (F32)abs(mTextRect.getWidth()) - line_width, |
431 | end_idx - start_idx, mWordWrap, mAllowEmbeddedItems ); | 434 | end_idx - start_idx, mWordWrap, mAllowEmbeddedItems ); |
432 | if( 0 == drawn && line_width == 0) | 435 | if( 0 == drawn && line_width == start_x) |
433 | { | 436 | { |
434 | // If at the beginning of a line, draw at least one character, even if it doesn't all fit. | 437 | // If at the beginning of a line, draw at least one character, even if it doesn't all fit. |
435 | drawn = 1; | 438 | drawn = 1; |
@@ -496,7 +499,7 @@ BOOL LLTextEditor::truncate() | |||
496 | 499 | ||
497 | void LLTextEditor::setText(const LLStringExplicit &utf8str) | 500 | void LLTextEditor::setText(const LLStringExplicit &utf8str) |
498 | { | 501 | { |
499 | // LLString::removeCRLF(utf8str); | 502 | // LLStringUtil::removeCRLF(utf8str); |
500 | mUTF8Text = utf8str_removeCRLF(utf8str); | 503 | mUTF8Text = utf8str_removeCRLF(utf8str); |
501 | // mUTF8Text = utf8str; | 504 | // mUTF8Text = utf8str; |
502 | mWText = utf8str_to_wstring(mUTF8Text); | 505 | mWText = utf8str_to_wstring(mUTF8Text); |
@@ -538,7 +541,7 @@ void LLTextEditor::setValue(const LLSD& value) | |||
538 | setText(value.asString()); | 541 | setText(value.asString()); |
539 | } | 542 | } |
540 | 543 | ||
541 | const LLString& LLTextEditor::getText() const | 544 | const std::string& LLTextEditor::getText() const |
542 | { | 545 | { |
543 | if (!mTextIsUpToDate) | 546 | if (!mTextIsUpToDate) |
544 | { | 547 | { |
@@ -591,7 +594,7 @@ void LLTextEditor::setHideScrollbarForShortDocs(BOOL b) | |||
591 | } | 594 | } |
592 | } | 595 | } |
593 | 596 | ||
594 | void LLTextEditor::selectNext(const LLString& search_text_in, BOOL case_insensitive, BOOL wrap) | 597 | void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap) |
595 | { | 598 | { |
596 | if (search_text_in.empty()) | 599 | if (search_text_in.empty()) |
597 | { | 600 | { |
@@ -602,8 +605,8 @@ void LLTextEditor::selectNext(const LLString& search_text_in, BOOL case_insensit | |||
602 | LLWString search_text = utf8str_to_wstring(search_text_in); | 605 | LLWString search_text = utf8str_to_wstring(search_text_in); |
603 | if (case_insensitive) | 606 | if (case_insensitive) |
604 | { | 607 | { |
605 | LLWString::toLower(text); | 608 | LLWStringUtil::toLower(text); |
606 | LLWString::toLower(search_text); | 609 | LLWStringUtil::toLower(search_text); |
607 | } | 610 | } |
608 | 611 | ||
609 | if (mIsSelecting) | 612 | if (mIsSelecting) |
@@ -641,7 +644,7 @@ void LLTextEditor::selectNext(const LLString& search_text_in, BOOL case_insensit | |||
641 | mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size())); | 644 | mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size())); |
642 | } | 645 | } |
643 | 646 | ||
644 | BOOL LLTextEditor::replaceText(const LLString& search_text_in, const LLString& replace_text, | 647 | BOOL LLTextEditor::replaceText(const std::string& search_text_in, const std::string& replace_text, |
645 | BOOL case_insensitive, BOOL wrap) | 648 | BOOL case_insensitive, BOOL wrap) |
646 | { | 649 | { |
647 | BOOL replaced = FALSE; | 650 | BOOL replaced = FALSE; |
@@ -659,8 +662,8 @@ BOOL LLTextEditor::replaceText(const LLString& search_text_in, const LLString& r | |||
659 | 662 | ||
660 | if (case_insensitive) | 663 | if (case_insensitive) |
661 | { | 664 | { |
662 | LLWString::toLower(selected_text); | 665 | LLWStringUtil::toLower(selected_text); |
663 | LLWString::toLower(search_text); | 666 | LLWStringUtil::toLower(search_text); |
664 | } | 667 | } |
665 | 668 | ||
666 | if (selected_text == search_text) | 669 | if (selected_text == search_text) |
@@ -674,7 +677,7 @@ BOOL LLTextEditor::replaceText(const LLString& search_text_in, const LLString& r | |||
674 | return replaced; | 677 | return replaced; |
675 | } | 678 | } |
676 | 679 | ||
677 | void LLTextEditor::replaceTextAll(const LLString& search_text, const LLString& replace_text, BOOL case_insensitive) | 680 | void LLTextEditor::replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive) |
678 | { | 681 | { |
679 | S32 cur_pos = mScrollbar->getDocPos(); | 682 | S32 cur_pos = mScrollbar->getDocPos(); |
680 | 683 | ||
@@ -800,7 +803,12 @@ void LLTextEditor::getSelectedSegments(std::vector<const LLTextSegment*>& segmen | |||
800 | 803 | ||
801 | S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const | 804 | S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const |
802 | { | 805 | { |
803 | // If round is true, if the position is on the right half of a character, the cursor | 806 | if(mShowLineNumbers) |
807 | { | ||
808 | local_x -= UI_TEXTEDITOR_LINE_NUMBER_MARGIN; | ||
809 | } | ||
810 | |||
811 | // If round is true, if the position is on the right half of a character, the cursor | ||
804 | // will be put to its right. If round is false, the cursor will always be put to the | 812 | // will be put to its right. If round is false, the cursor will always be put to the |
805 | // character's left. | 813 | // character's left. |
806 | 814 | ||
@@ -1061,7 +1069,7 @@ void LLTextEditor::selectAll() | |||
1061 | } | 1069 | } |
1062 | 1070 | ||
1063 | 1071 | ||
1064 | BOOL LLTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) | 1072 | BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) |
1065 | { | 1073 | { |
1066 | for ( child_list_const_iter_t child_it = getChildList()->begin(); | 1074 | for ( child_list_const_iter_t child_it = getChildList()->begin(); |
1067 | child_it != getChildList()->end(); ++child_it) | 1075 | child_it != getChildList()->end(); ++child_it) |
@@ -1392,7 +1400,7 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) | |||
1392 | BOOL LLTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask, | 1400 | BOOL LLTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask, |
1393 | BOOL drop, EDragAndDropType cargo_type, void *cargo_data, | 1401 | BOOL drop, EDragAndDropType cargo_type, void *cargo_data, |
1394 | EAcceptance *accept, | 1402 | EAcceptance *accept, |
1395 | LLString& tooltip_msg) | 1403 | std::string& tooltip_msg) |
1396 | { | 1404 | { |
1397 | *accept = ACCEPT_NO; | 1405 | *accept = ACCEPT_NO; |
1398 | 1406 | ||
@@ -1879,7 +1887,7 @@ void LLTextEditor::paste() | |||
1879 | 1887 | ||
1880 | // Clean up string (replace tabs and remove characters that our fonts don't support). | 1888 | // Clean up string (replace tabs and remove characters that our fonts don't support). |
1881 | LLWString clean_string(paste); | 1889 | LLWString clean_string(paste); |
1882 | LLWString::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB); | 1890 | LLWStringUtil::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB); |
1883 | if( mAllowEmbeddedItems ) | 1891 | if( mAllowEmbeddedItems ) |
1884 | { | 1892 | { |
1885 | const llwchar LF = 10; | 1893 | const llwchar LF = 10; |
@@ -2469,20 +2477,15 @@ void LLTextEditor::drawBackground() | |||
2469 | S32 right = getRect().getWidth(); | 2477 | S32 right = getRect().getWidth(); |
2470 | S32 bottom = 0; | 2478 | S32 bottom = 0; |
2471 | 2479 | ||
2472 | LLColor4 bg_color = mReadOnlyBgColor; | 2480 | LLColor4 bg_color = mReadOnly ? mReadOnlyBgColor |
2473 | 2481 | : gFocusMgr.getKeyboardFocus() == this ? mFocusBgColor : mWriteableBgColor; | |
2474 | if( !mReadOnly ) | 2482 | if( mShowLineNumbers ) { |
2475 | { | 2483 | gl_rect_2d(left, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN, bottom, mReadOnlyBgColor ); // line number area always read-only |
2476 | if (gFocusMgr.getKeyboardFocus() == this) | 2484 | gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, right, bottom, bg_color); // body text area to the right of line numbers |
2477 | { | 2485 | gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN-1, bottom, LLColor4::grey3); // separator |
2478 | bg_color = mFocusBgColor; | 2486 | } else { |
2479 | } | 2487 | gl_rect_2d(left, top, right, bottom, bg_color); // body text area |
2480 | else | ||
2481 | { | ||
2482 | bg_color = mWriteableBgColor; | ||
2483 | } | ||
2484 | } | 2488 | } |
2485 | gl_rect_2d(left, top, right, bottom, bg_color); | ||
2486 | 2489 | ||
2487 | LLView::draw(); | 2490 | LLView::draw(); |
2488 | } | 2491 | } |
@@ -2570,7 +2573,7 @@ void LLTextEditor::drawSelectionBackground() | |||
2570 | { | 2573 | { |
2571 | // extend selection slightly beyond end of line | 2574 | // extend selection slightly beyond end of line |
2572 | // to indicate selection of newline character (use "n" character to determine width) | 2575 | // to indicate selection of newline character (use "n" character to determine width) |
2573 | const LLWString nstr(utf8str_to_wstring(LLString("n"))); | 2576 | const LLWString nstr(utf8str_to_wstring(std::string("n"))); |
2574 | line_endings.push(mTextRect.mLeft + mGLFont->getWidth(line, 0, line_end - line_start, mAllowEmbeddedItems) + mGLFont->getWidth(nstr.c_str())); | 2577 | line_endings.push(mTextRect.mLeft + mGLFont->getWidth(line, 0, line_end - line_start, mAllowEmbeddedItems) + mGLFont->getWidth(nstr.c_str())); |
2575 | } | 2578 | } |
2576 | 2579 | ||
@@ -2595,12 +2598,13 @@ void LLTextEditor::drawSelectionBackground() | |||
2595 | const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor; | 2598 | const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor; |
2596 | F32 alpha = hasFocus() ? 1.f : 0.5f; | 2599 | F32 alpha = hasFocus() ? 1.f : 0.5f; |
2597 | gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); | 2600 | gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); |
2601 | S32 margin_offset = mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0; | ||
2598 | 2602 | ||
2599 | if( selection_left_y == selection_right_y ) | 2603 | if( selection_left_y == selection_right_y ) |
2600 | { | 2604 | { |
2601 | // Draw from selection start to selection end | 2605 | // Draw from selection start to selection end |
2602 | gl_rect_2d( selection_left_x, selection_left_y + line_height + 1, | 2606 | gl_rect_2d( selection_left_x + margin_offset, selection_left_y + line_height + 1, |
2603 | selection_right_x, selection_right_y); | 2607 | selection_right_x + margin_offset, selection_right_y); |
2604 | } | 2608 | } |
2605 | else | 2609 | else |
2606 | { | 2610 | { |
@@ -2612,16 +2616,16 @@ void LLTextEditor::drawSelectionBackground() | |||
2612 | 2616 | ||
2613 | S32 line_end = line_endings.front(); | 2617 | S32 line_end = line_endings.front(); |
2614 | line_endings.pop(); | 2618 | line_endings.pop(); |
2615 | gl_rect_2d( selection_left_x, selection_left_y + line_height + 1, | 2619 | gl_rect_2d( selection_left_x + margin_offset, selection_left_y + line_height + 1, |
2616 | line_end, selection_left_y ); | 2620 | line_end + margin_offset, selection_left_y ); |
2617 | 2621 | ||
2618 | S32 line_num = left_line_num + 1; | 2622 | S32 line_num = left_line_num + 1; |
2619 | while(line_endings.size()) | 2623 | while(line_endings.size()) |
2620 | { | 2624 | { |
2621 | S32 vert_offset = -(line_num - left_line_num) * line_height; | 2625 | S32 vert_offset = -(line_num - left_line_num) * line_height; |
2622 | // Draw the block between the two lines | 2626 | // Draw the block between the two lines |
2623 | gl_rect_2d( mTextRect.mLeft, selection_left_y + vert_offset + line_height + 1, | 2627 | gl_rect_2d( mTextRect.mLeft + margin_offset, selection_left_y + vert_offset + line_height + 1, |
2624 | line_endings.front(), selection_left_y + vert_offset); | 2628 | line_endings.front() + margin_offset, selection_left_y + vert_offset); |
2625 | line_endings.pop(); | 2629 | line_endings.pop(); |
2626 | line_num++; | 2630 | line_num++; |
2627 | } | 2631 | } |
@@ -2631,8 +2635,8 @@ void LLTextEditor::drawSelectionBackground() | |||
2631 | { | 2635 | { |
2632 | selection_right_x += CURSOR_THICKNESS; | 2636 | selection_right_x += CURSOR_THICKNESS; |
2633 | } | 2637 | } |
2634 | gl_rect_2d( mTextRect.mLeft, selection_right_y + line_height + 1, | 2638 | gl_rect_2d( mTextRect.mLeft + margin_offset, selection_right_y + line_height + 1, |
2635 | selection_right_x, selection_right_y ); | 2639 | selection_right_x + margin_offset, selection_right_y ); |
2636 | } | 2640 | } |
2637 | } | 2641 | } |
2638 | } | 2642 | } |
@@ -2695,6 +2699,11 @@ void LLTextEditor::drawCursor() | |||
2695 | cur_pos++; | 2699 | cur_pos++; |
2696 | } | 2700 | } |
2697 | 2701 | ||
2702 | if(mShowLineNumbers) | ||
2703 | { | ||
2704 | cursor_left += UI_TEXTEDITOR_LINE_NUMBER_MARGIN; | ||
2705 | } | ||
2706 | |||
2698 | // Draw the cursor | 2707 | // Draw the cursor |
2699 | if( cursor_visible ) | 2708 | if( cursor_visible ) |
2700 | { | 2709 | { |
@@ -2707,7 +2716,7 @@ void LLTextEditor::drawCursor() | |||
2707 | if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) | 2716 | if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) |
2708 | { | 2717 | { |
2709 | cursor_left += CURSOR_THICKNESS; | 2718 | cursor_left += CURSOR_THICKNESS; |
2710 | const LLWString space(utf8str_to_wstring(LLString(" "))); | 2719 | const LLWString space(utf8str_to_wstring(std::string(" "))); |
2711 | F32 spacew = mGLFont->getWidthF32(space.c_str()); | 2720 | F32 spacew = mGLFont->getWidthF32(space.c_str()); |
2712 | if (mCursorPos == line_end) | 2721 | if (mCursorPos == line_end) |
2713 | { | 2722 | { |
@@ -2861,10 +2870,7 @@ void LLTextEditor::drawText() | |||
2861 | { | 2870 | { |
2862 | const LLWString &text = mWText; | 2871 | const LLWString &text = mWText; |
2863 | const S32 text_len = getLength(); | 2872 | const S32 text_len = getLength(); |
2864 | if( text_len <= 0 ) | 2873 | if( text_len <= 0 ) return; |
2865 | { | ||
2866 | return; | ||
2867 | } | ||
2868 | S32 selection_left = -1; | 2874 | S32 selection_left = -1; |
2869 | S32 selection_right = -1; | 2875 | S32 selection_right = -1; |
2870 | // Draw selection even if we don't have keyboard focus for search/replace | 2876 | // Draw selection even if we don't have keyboard focus for search/replace |
@@ -2876,14 +2882,26 @@ void LLTextEditor::drawText() | |||
2876 | 2882 | ||
2877 | LLGLSUIDefault gls_ui; | 2883 | LLGLSUIDefault gls_ui; |
2878 | 2884 | ||
2879 | S32 cur_line = mScrollbar->getDocPos(); | 2885 | // There are several concepts that are important for understanding the following drawing code. |
2886 | // The document is logically a sequence of characters (stored in a LLWString). | ||
2887 | // Variables below with "start" or "end" in their names refer to positions or offsets into it. | ||
2888 | // Next there are two kinds of "line" variables to understand. Newline characters in the | ||
2889 | // character sequence represent logical lines. These are what get numbered and so variables | ||
2890 | // representing this kind of line have "num" in their names. | ||
2891 | // The others represent line fragments or displayed lines which the scrollbar deals with. | ||
2892 | // When the "show line numbers" property is turned on, we draw line numbers to the left of the | ||
2893 | // beginning of each logical line and not in front of wrapped "continuation" display lines. -MG | ||
2894 | |||
2895 | S32 cur_line = mScrollbar->getDocPos(); // scrollbar counts each wrap as a new line. | ||
2880 | S32 num_lines = getLineCount(); | 2896 | S32 num_lines = getLineCount(); |
2881 | if (cur_line >= num_lines) | 2897 | if (cur_line >= num_lines) return; |
2882 | { | ||
2883 | return; | ||
2884 | } | ||
2885 | |||
2886 | S32 line_start = getLineStart(cur_line); | 2898 | S32 line_start = getLineStart(cur_line); |
2899 | S32 prev_start = getLineStart(cur_line-1); | ||
2900 | S32 cur_line_num = getLineForPosition(line_start); // doesn't count wraps. i.e. only counts newlines. | ||
2901 | S32 prev_line_num = getLineForPosition(prev_start); | ||
2902 | BOOL cur_line_is_continuation = cur_line_num > 0 && cur_line_num == prev_line_num; | ||
2903 | BOOL line_wraps = FALSE; | ||
2904 | |||
2887 | LLTextSegment t(line_start); | 2905 | LLTextSegment t(line_start); |
2888 | segment_list_t::iterator seg_iter; | 2906 | segment_list_t::iterator seg_iter; |
2889 | seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &t, LLTextSegment::compare()); | 2907 | seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &t, LLTextSegment::compare()); |
@@ -2902,12 +2920,36 @@ void LLTextEditor::drawText() | |||
2902 | next_start = getLineStart(cur_line + 1); | 2920 | next_start = getLineStart(cur_line + 1); |
2903 | line_end = next_start; | 2921 | line_end = next_start; |
2904 | } | 2922 | } |
2905 | if ( text[line_end-1] == '\n' ) | 2923 | line_wraps = text[line_end-1] != '\n'; |
2924 | if ( ! line_wraps ) | ||
2906 | { | 2925 | { |
2907 | --line_end; | 2926 | --line_end; // don't attempt to draw the newline char. |
2908 | } | 2927 | } |
2909 | 2928 | ||
2910 | F32 text_x = (F32)mTextRect.mLeft; | 2929 | F32 text_start = (F32)mTextRect.mLeft; |
2930 | F32 text_x = text_start + (mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0); | ||
2931 | |||
2932 | // draw the line numbers | ||
2933 | if( mShowLineNumbers && !cur_line_is_continuation) | ||
2934 | { | ||
2935 | const LLFontGL *num_font = LLFontGL::sMonospace; | ||
2936 | F32 y_top = text_y + ((F32)llround(num_font->getLineHeight()) / 2); | ||
2937 | const LLWString ltext = utf8str_to_wstring(llformat("%*d", UI_TEXTEDITOR_LINE_NUMBER_DIGITS, cur_line_num )); | ||
2938 | BOOL is_cur_line = getCurrentLine() == cur_line_num; | ||
2939 | const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL; | ||
2940 | const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor; | ||
2941 | num_font->render( | ||
2942 | ltext, // string to draw | ||
2943 | 0, // begin offset | ||
2944 | 3., // x | ||
2945 | y_top, // y | ||
2946 | fg_color, | ||
2947 | LLFontGL::LEFT, // horizontal alignment | ||
2948 | LLFontGL::VCENTER, // vertical alignment | ||
2949 | style, | ||
2950 | S32_MAX, // max chars | ||
2951 | UI_TEXTEDITOR_LINE_NUMBER_MARGIN); // max pixels | ||
2952 | } | ||
2911 | 2953 | ||
2912 | S32 seg_start = line_start; | 2954 | S32 seg_start = line_start; |
2913 | while( seg_start < line_end ) | 2955 | while( seg_start < line_end ) |
@@ -2952,16 +2994,28 @@ void LLTextEditor::drawText() | |||
2952 | 2994 | ||
2953 | drawClippedSegment( text, seg_start, clipped_end, text_x, text_y, selection_left, selection_right, style, &text_x ); | 2995 | drawClippedSegment( text, seg_start, clipped_end, text_x, text_y, selection_left, selection_right, style, &text_x ); |
2954 | 2996 | ||
2997 | if( text_x == text_start && mShowLineNumbers ) | ||
2998 | { | ||
2999 | text_x += UI_TEXTEDITOR_LINE_NUMBER_MARGIN; | ||
3000 | } | ||
3001 | |||
2955 | // Note: text_x is incremented by drawClippedSegment() | 3002 | // Note: text_x is incremented by drawClippedSegment() |
2956 | seg_start += clipped_len; | 3003 | seg_start += clipped_len; |
2957 | } | 3004 | } |
2958 | } | 3005 | } |
2959 | 3006 | ||
2960 | // move down one line | 3007 | // move down one line |
2961 | text_y -= (F32)line_height; | 3008 | text_y -= (F32)line_height; |
3009 | |||
3010 | if( line_wraps ) | ||
3011 | { | ||
3012 | cur_line_num--; | ||
3013 | } | ||
3014 | cur_line_is_continuation = line_wraps; // so as to not not number the continuation lines | ||
2962 | 3015 | ||
2963 | line_start = next_start; | 3016 | line_start = next_start; |
2964 | cur_line++; | 3017 | cur_line++; |
3018 | cur_line_num++; | ||
2965 | } | 3019 | } |
2966 | } | 3020 | } |
2967 | 3021 | ||
@@ -3083,7 +3137,7 @@ void LLTextEditor::onTabInto() | |||
3083 | // virtual | 3137 | // virtual |
3084 | void LLTextEditor::clear() | 3138 | void LLTextEditor::clear() |
3085 | { | 3139 | { |
3086 | setText(LLString::null); | 3140 | setText(LLStringUtil::null); |
3087 | } | 3141 | } |
3088 | 3142 | ||
3089 | // Start or stop the editor from accepting text-editing keystrokes | 3143 | // Start or stop the editor from accepting text-editing keystrokes |
@@ -3260,8 +3314,7 @@ void LLTextEditor::setCursorAndScrollToEnd() | |||
3260 | updateScrollFromCursor(); | 3314 | updateScrollFromCursor(); |
3261 | } | 3315 | } |
3262 | 3316 | ||
3263 | 3317 | void LLTextEditor::getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap ) | |
3264 | void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap ) | ||
3265 | { | 3318 | { |
3266 | if( include_wordwrap ) | 3319 | if( include_wordwrap ) |
3267 | { | 3320 | { |
@@ -3273,7 +3326,7 @@ void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wo | |||
3273 | S32 line_count = 0; | 3326 | S32 line_count = 0; |
3274 | S32 line_start = 0; | 3327 | S32 line_start = 0; |
3275 | S32 i; | 3328 | S32 i; |
3276 | for( i = 0; text[i] && (i < mCursorPos); i++ ) | 3329 | for( i = 0; text[i] && (i < position); i++ ) |
3277 | { | 3330 | { |
3278 | if( '\n' == text[i] ) | 3331 | if( '\n' == text[i] ) |
3279 | { | 3332 | { |
@@ -3286,6 +3339,23 @@ void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wo | |||
3286 | } | 3339 | } |
3287 | } | 3340 | } |
3288 | 3341 | ||
3342 | void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap ) | ||
3343 | { | ||
3344 | getLineAndColumnForPosition(mCursorPos, line, col, include_wordwrap); | ||
3345 | } | ||
3346 | |||
3347 | S32 LLTextEditor::getCurrentLine() | ||
3348 | { | ||
3349 | return getLineForPosition(mCursorPos); | ||
3350 | } | ||
3351 | |||
3352 | S32 LLTextEditor::getLineForPosition(S32 position) | ||
3353 | { | ||
3354 | S32 line, col; | ||
3355 | getLineAndColumnForPosition(position, &line, &col, FALSE); | ||
3356 | return line; | ||
3357 | } | ||
3358 | |||
3289 | 3359 | ||
3290 | void LLTextEditor::endOfLine() | 3360 | void LLTextEditor::endOfLine() |
3291 | { | 3361 | { |
@@ -3364,20 +3434,26 @@ void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent) | |||
3364 | { | 3434 | { |
3365 | LLView::reshape( width, height, called_from_parent ); | 3435 | LLView::reshape( width, height, called_from_parent ); |
3366 | 3436 | ||
3367 | // if scrolled to bottom, stay at bottom | 3437 | // do this first after reshape, because other things depend on |
3368 | // unless user is editing text | 3438 | // up-to-date mTextRect |
3369 | if (mScrolledToBottom && mTrackBottom && !hasFocus()) | ||
3370 | { | ||
3371 | endOfDoc(); | ||
3372 | } | ||
3373 | |||
3374 | updateTextRect(); | 3439 | updateTextRect(); |
3440 | |||
3441 | updateLineStartList(); | ||
3442 | |||
3443 | // propagate shape information to scrollbar | ||
3444 | mScrollbar->setDocSize( getLineCount() ); | ||
3375 | 3445 | ||
3376 | S32 line_height = llround( mGLFont->getLineHeight() ); | 3446 | S32 line_height = llround( mGLFont->getLineHeight() ); |
3377 | S32 page_lines = mTextRect.getHeight() / line_height; | 3447 | S32 page_lines = mTextRect.getHeight() / line_height; |
3378 | mScrollbar->setPageSize( page_lines ); | 3448 | mScrollbar->setPageSize( page_lines ); |
3379 | 3449 | ||
3380 | updateLineStartList(); | 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 | } | ||
3381 | } | 3457 | } |
3382 | 3458 | ||
3383 | void LLTextEditor::autoIndent() | 3459 | void LLTextEditor::autoIndent() |
@@ -3411,7 +3487,7 @@ void LLTextEditor::autoIndent() | |||
3411 | } | 3487 | } |
3412 | 3488 | ||
3413 | // Inserts new text at the cursor position | 3489 | // Inserts new text at the cursor position |
3414 | void LLTextEditor::insertText(const LLString &new_text) | 3490 | void LLTextEditor::insertText(const std::string &new_text) |
3415 | { | 3491 | { |
3416 | BOOL enabled = getEnabled(); | 3492 | BOOL enabled = getEnabled(); |
3417 | setEnabled( TRUE ); | 3493 | setEnabled( TRUE ); |
@@ -3431,11 +3507,11 @@ void LLTextEditor::insertText(const LLString &new_text) | |||
3431 | } | 3507 | } |
3432 | 3508 | ||
3433 | 3509 | ||
3434 | void LLTextEditor::appendColoredText(const LLString &new_text, | 3510 | void LLTextEditor::appendColoredText(const std::string &new_text, |
3435 | bool allow_undo, | 3511 | bool allow_undo, |
3436 | bool prepend_newline, | 3512 | bool prepend_newline, |
3437 | const LLColor4 &color, | 3513 | const LLColor4 &color, |
3438 | const LLString& font_name) | 3514 | const std::string& font_name) |
3439 | { | 3515 | { |
3440 | LLStyleSP style(new LLStyle); | 3516 | LLStyleSP style(new LLStyle); |
3441 | style->setVisible(true); | 3517 | style->setVisible(true); |
@@ -3444,7 +3520,7 @@ void LLTextEditor::appendColoredText(const LLString &new_text, | |||
3444 | appendStyledText(new_text, allow_undo, prepend_newline, &style); | 3520 | appendStyledText(new_text, allow_undo, prepend_newline, &style); |
3445 | } | 3521 | } |
3446 | 3522 | ||
3447 | void LLTextEditor::appendStyledText(const LLString &new_text, | 3523 | void LLTextEditor::appendStyledText(const std::string &new_text, |
3448 | bool allow_undo, | 3524 | bool allow_undo, |
3449 | bool prepend_newline, | 3525 | bool prepend_newline, |
3450 | const LLStyleSP *stylep) | 3526 | const LLStyleSP *stylep) |
@@ -3453,7 +3529,7 @@ void LLTextEditor::appendStyledText(const LLString &new_text, | |||
3453 | { | 3529 | { |
3454 | 3530 | ||
3455 | S32 start=0,end=0; | 3531 | S32 start=0,end=0; |
3456 | LLString text = new_text; | 3532 | std::string text = new_text; |
3457 | while ( findHTML(text, &start, &end) ) | 3533 | while ( findHTML(text, &start, &end) ) |
3458 | { | 3534 | { |
3459 | LLStyleSP html(new LLStyle); | 3535 | LLStyleSP html(new LLStyle); |
@@ -3487,7 +3563,7 @@ void LLTextEditor::appendStyledText(const LLString &new_text, | |||
3487 | } | 3563 | } |
3488 | 3564 | ||
3489 | // Appends new text to end of document | 3565 | // Appends new text to end of document |
3490 | void LLTextEditor::appendText(const LLString &new_text, bool allow_undo, bool prepend_newline, | 3566 | void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline, |
3491 | const LLStyleSP *stylep) | 3567 | const LLStyleSP *stylep) |
3492 | { | 3568 | { |
3493 | // Save old state | 3569 | // Save old state |
@@ -3507,7 +3583,7 @@ void LLTextEditor::appendText(const LLString &new_text, bool allow_undo, bool pr | |||
3507 | if (getLength() != 0 | 3583 | if (getLength() != 0 |
3508 | && prepend_newline) | 3584 | && prepend_newline) |
3509 | { | 3585 | { |
3510 | LLString final_text = "\n"; | 3586 | std::string final_text = "\n"; |
3511 | final_text += new_text; | 3587 | final_text += new_text; |
3512 | append(utf8str_to_wstring(final_text), TRUE); | 3588 | append(utf8str_to_wstring(final_text), TRUE); |
3513 | } | 3589 | } |
@@ -3543,6 +3619,10 @@ void LLTextEditor::appendText(const LLString &new_text, bool allow_undo, bool pr | |||
3543 | { | 3619 | { |
3544 | mSelectionStart = selection_start; | 3620 | mSelectionStart = selection_start; |
3545 | mSelectionEnd = selection_end; | 3621 | mSelectionEnd = selection_end; |
3622 | |||
3623 | |||
3624 | |||
3625 | |||
3546 | mIsSelecting = was_selecting; | 3626 | mIsSelecting = was_selecting; |
3547 | setCursorPos(cursor_pos); | 3627 | setCursorPos(cursor_pos); |
3548 | } | 3628 | } |
@@ -3559,6 +3639,14 @@ void LLTextEditor::appendText(const LLString &new_text, bool allow_undo, bool pr | |||
3559 | { | 3639 | { |
3560 | blockUndo(); | 3640 | blockUndo(); |
3561 | } | 3641 | } |
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 | } | ||
3562 | } | 3650 | } |
3563 | 3651 | ||
3564 | void LLTextEditor::removeTextFromEnd(S32 num_chars) | 3652 | void LLTextEditor::removeTextFromEnd(S32 num_chars) |
@@ -3688,20 +3776,18 @@ void LLTextEditor::updateTextRect() | |||
3688 | getRect().getHeight() - 2 * UI_TEXTEDITOR_BORDER - UI_TEXTEDITOR_V_PAD_TOP ); | 3776 | getRect().getHeight() - 2 * UI_TEXTEDITOR_BORDER - UI_TEXTEDITOR_V_PAD_TOP ); |
3689 | } | 3777 | } |
3690 | 3778 | ||
3691 | void LLTextEditor::loadKeywords(const LLString& filename, | 3779 | void LLTextEditor::loadKeywords(const std::string& filename, |
3692 | const LLDynamicArray<const char*>& funcs, | 3780 | const std::vector<std::string>& funcs, |
3693 | const LLDynamicArray<const char*>& tooltips, | 3781 | const std::vector<std::string>& tooltips, |
3694 | const LLColor3& color) | 3782 | const LLColor3& color) |
3695 | { | 3783 | { |
3696 | if(mKeywords.loadFromFile(filename)) | 3784 | if(mKeywords.loadFromFile(filename)) |
3697 | { | 3785 | { |
3698 | S32 count = funcs.count(); | 3786 | S32 count = llmin(funcs.size(), tooltips.size()); |
3699 | LLString name; | ||
3700 | for(S32 i = 0; i < count; i++) | 3787 | for(S32 i = 0; i < count; i++) |
3701 | { | 3788 | { |
3702 | name = funcs.get(i); | 3789 | std::string name = utf8str_trim(funcs[i]); |
3703 | name = utf8str_trim(name); | 3790 | mKeywords.addToken(LLKeywordToken::WORD, name, color, tooltips[i] ); |
3704 | mKeywords.addToken(LLKeywordToken::WORD, name.c_str(), color, tooltips.get(i) ); | ||
3705 | } | 3791 | } |
3706 | 3792 | ||
3707 | mKeywords.findSegments( &mSegments, mWText, mDefaultColor ); | 3793 | mKeywords.findSegments( &mSegments, mWText, mDefaultColor ); |
@@ -3843,9 +3929,9 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask) | |||
3843 | //Special handling for slurls | 3929 | //Special handling for slurls |
3844 | if ( (mSecondlifeURLcallback!=NULL) && !(*mSecondlifeURLcallback)(mHTML) ) | 3930 | if ( (mSecondlifeURLcallback!=NULL) && !(*mSecondlifeURLcallback)(mHTML) ) |
3845 | { | 3931 | { |
3846 | if (mURLcallback!=NULL) (*mURLcallback)(mHTML.c_str()); | 3932 | if (mURLcallback!=NULL) (*mURLcallback)(mHTML); |
3847 | } | 3933 | } |
3848 | mHTML=""; | 3934 | mHTML.clear(); |
3849 | } | 3935 | } |
3850 | } | 3936 | } |
3851 | 3937 | ||
@@ -3897,7 +3983,7 @@ void LLTextEditor::setOnScrollEndCallback(void (*callback)(void*), void* userdat | |||
3897 | /////////////////////////////////////////////////////////////////// | 3983 | /////////////////////////////////////////////////////////////////// |
3898 | // Hack for Notecards | 3984 | // Hack for Notecards |
3899 | 3985 | ||
3900 | BOOL LLTextEditor::importBuffer(const LLString& buffer ) | 3986 | BOOL LLTextEditor::importBuffer(const char* buffer, S32 length ) |
3901 | { | 3987 | { |
3902 | std::istringstream instream(buffer); | 3988 | std::istringstream instream(buffer); |
3903 | 3989 | ||
@@ -3986,7 +4072,7 @@ BOOL LLTextEditor::importBuffer(const LLString& buffer ) | |||
3986 | return success; | 4072 | return success; |
3987 | } | 4073 | } |
3988 | 4074 | ||
3989 | BOOL LLTextEditor::exportBuffer(LLString &buffer ) | 4075 | BOOL LLTextEditor::exportBuffer(std::string &buffer ) |
3990 | { | 4076 | { |
3991 | std::ostringstream outstream(buffer); | 4077 | std::ostringstream outstream(buffer); |
3992 | 4078 | ||
@@ -4003,7 +4089,11 @@ BOOL LLTextEditor::exportBuffer(LLString &buffer ) | |||
4003 | ////////////////////////////////////////////////////////////////////////// | 4089 | ////////////////////////////////////////////////////////////////////////// |
4004 | // LLTextSegment | 4090 | // LLTextSegment |
4005 | 4091 | ||
4006 | LLTextSegment::LLTextSegment(S32 start) : mStart(start) | 4092 | LLTextSegment::LLTextSegment(S32 start) : |
4093 | mStart(start), | ||
4094 | mEnd(0), | ||
4095 | mToken(NULL), | ||
4096 | mIsDefault(FALSE) | ||
4007 | { | 4097 | { |
4008 | } | 4098 | } |
4009 | LLTextSegment::LLTextSegment( const LLStyleSP& style, S32 start, S32 end ) : | 4099 | LLTextSegment::LLTextSegment( const LLStyleSP& style, S32 start, S32 end ) : |
@@ -4015,7 +4105,7 @@ LLTextSegment::LLTextSegment( const LLStyleSP& style, S32 start, S32 end ) : | |||
4015 | { | 4105 | { |
4016 | } | 4106 | } |
4017 | LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end, BOOL is_visible) : | 4107 | LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end, BOOL is_visible) : |
4018 | mStyle(new LLStyle(is_visible,color,"")), | 4108 | mStyle(new LLStyle(is_visible,color,LLStringUtil::null)), |
4019 | mStart( start), | 4109 | mStart( start), |
4020 | mEnd( end ), | 4110 | mEnd( end ), |
4021 | mToken(NULL), | 4111 | mToken(NULL), |
@@ -4023,7 +4113,7 @@ LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end, BOOL is | |||
4023 | { | 4113 | { |
4024 | } | 4114 | } |
4025 | LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end ) : | 4115 | LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end ) : |
4026 | mStyle(new LLStyle(TRUE, color,"" )), | 4116 | mStyle(new LLStyle(TRUE, color,LLStringUtil::null )), |
4027 | mStart( start), | 4117 | mStart( start), |
4028 | mEnd( end ), | 4118 | mEnd( end ), |
4029 | mToken(NULL), | 4119 | mToken(NULL), |
@@ -4031,7 +4121,7 @@ LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end ) : | |||
4031 | { | 4121 | { |
4032 | } | 4122 | } |
4033 | LLTextSegment::LLTextSegment( const LLColor3& color, S32 start, S32 end ) : | 4123 | LLTextSegment::LLTextSegment( const LLColor3& color, S32 start, S32 end ) : |
4034 | mStyle(new LLStyle(TRUE, color,"" )), | 4124 | mStyle(new LLStyle(TRUE, color,LLStringUtil::null )), |
4035 | mStart( start), | 4125 | mStart( start), |
4036 | mEnd( end ), | 4126 | mEnd( end ), |
4037 | mToken(NULL), | 4127 | mToken(NULL), |
@@ -4039,7 +4129,7 @@ LLTextSegment::LLTextSegment( const LLColor3& color, S32 start, S32 end ) : | |||
4039 | { | 4129 | { |
4040 | } | 4130 | } |
4041 | 4131 | ||
4042 | BOOL LLTextSegment::getToolTip(LLString& msg) const | 4132 | BOOL LLTextSegment::getToolTip(std::string& msg) const |
4043 | { | 4133 | { |
4044 | if (mToken && !mToken->getToolTip().empty()) | 4134 | if (mToken && !mToken->getToolTip().empty()) |
4045 | { | 4135 | { |
@@ -4094,7 +4184,7 @@ LLXMLNodePtr LLTextEditor::getXML(bool save_children) const | |||
4094 | // static | 4184 | // static |
4095 | LLView* LLTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) | 4185 | LLView* LLTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) |
4096 | { | 4186 | { |
4097 | LLString name("text_editor"); | 4187 | std::string name("text_editor"); |
4098 | node->getAttributeString("name", name); | 4188 | node->getAttributeString("name", name); |
4099 | 4189 | ||
4100 | LLRect rect; | 4190 | LLRect rect; |
@@ -4108,7 +4198,7 @@ LLView* LLTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory | |||
4108 | 4198 | ||
4109 | LLFontGL* font = LLView::selectFont(node); | 4199 | LLFontGL* font = LLView::selectFont(node); |
4110 | 4200 | ||
4111 | LLString text = node->getTextContents().substr(0, max_text_length - 1); | 4201 | std::string text = node->getTextContents().substr(0, max_text_length - 1); |
4112 | 4202 | ||
4113 | LLTextEditor* text_editor = new LLTextEditor(name, | 4203 | LLTextEditor* text_editor = new LLTextEditor(name, |
4114 | rect, | 4204 | rect, |
@@ -4134,6 +4224,8 @@ void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node) | |||
4134 | node->getAttributeBOOL("word_wrap", word_wrap); | 4224 | node->getAttributeBOOL("word_wrap", word_wrap); |
4135 | setWordWrap(word_wrap); | 4225 | setWordWrap(word_wrap); |
4136 | 4226 | ||
4227 | node->getAttributeBOOL("show_line_numbers", mShowLineNumbers); | ||
4228 | |||
4137 | node->getAttributeBOOL("track_bottom", mTrackBottom); | 4229 | node->getAttributeBOOL("track_bottom", mTrackBottom); |
4138 | 4230 | ||
4139 | LLColor4 color; | 4231 | LLColor4 color; |
@@ -4160,26 +4252,29 @@ void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node) | |||
4160 | } | 4252 | } |
4161 | 4253 | ||
4162 | /////////////////////////////////////////////////////////////////// | 4254 | /////////////////////////////////////////////////////////////////// |
4163 | S32 LLTextEditor::findHTMLToken(const LLString &line, S32 pos, BOOL reverse) const | 4255 | // Refactoring note: We may eventually want to replace this with boost::regex or |
4256 | // boost::tokenizer capabilities since we've already fixed at least two JIRAs | ||
4257 | // concerning logic issues associated with this function. | ||
4258 | S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const | ||
4164 | { | 4259 | { |
4165 | LLString openers=" \t('\"[{<>"; | 4260 | std::string openers=" \t\n('\"[{<>"; |
4166 | LLString closers=" \t)'\"]}><;"; | 4261 | std::string closers=" \t\n)'\"]}><;"; |
4167 | 4262 | ||
4168 | S32 m2; | 4263 | S32 m2 = 0; |
4169 | S32 retval; | 4264 | S32 retval = 0; |
4170 | 4265 | ||
4171 | if (reverse) | 4266 | if (reverse) |
4172 | { | 4267 | { |
4173 | 4268 | ||
4174 | for (retval=pos; retval>0; retval--) | 4269 | for (retval=pos; retval >= 0; retval--) |
4175 | { | 4270 | { |
4176 | m2 = openers.find(line.substr(retval,1)); | 4271 | m2 = openers.find(line.substr(retval,1)); |
4177 | if (m2 >= 0) | 4272 | if (m2 >= 0) |
4178 | { | 4273 | { |
4179 | retval++; | ||
4180 | break; | 4274 | break; |
4181 | } | 4275 | } |
4182 | } | 4276 | } |
4277 | return retval+1; | ||
4183 | } | 4278 | } |
4184 | else | 4279 | else |
4185 | { | 4280 | { |
@@ -4192,12 +4287,11 @@ S32 LLTextEditor::findHTMLToken(const LLString &line, S32 pos, BOOL reverse) con | |||
4192 | break; | 4287 | break; |
4193 | } | 4288 | } |
4194 | } | 4289 | } |
4195 | } | 4290 | return retval; |
4196 | 4291 | } | |
4197 | return retval; | ||
4198 | } | 4292 | } |
4199 | 4293 | ||
4200 | BOOL LLTextEditor::findHTML(const LLString &line, S32 *begin, S32 *end) const | 4294 | BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const |
4201 | { | 4295 | { |
4202 | 4296 | ||
4203 | S32 m1,m2,m3; | 4297 | S32 m1,m2,m3; |
@@ -4214,7 +4308,7 @@ BOOL LLTextEditor::findHTML(const LLString &line, S32 *begin, S32 *end) const | |||
4214 | m2 = line.substr(*begin,(m1 - *begin)).find("http"); | 4308 | m2 = line.substr(*begin,(m1 - *begin)).find("http"); |
4215 | m3 = line.substr(*begin,(m1 - *begin)).find("secondlife"); | 4309 | m3 = line.substr(*begin,(m1 - *begin)).find("secondlife"); |
4216 | 4310 | ||
4217 | LLString badneighbors=".,<>?';\"][}{=-+_)(*&^%$#@!~`\t\r\n\\"; | 4311 | std::string badneighbors=".,<>?';\"][}{=-+_)(*&^%$#@!~`\t\r\n\\"; |
4218 | 4312 | ||
4219 | if (m2 >= 0 || m3>=0) | 4313 | if (m2 >= 0 || m3>=0) |
4220 | { | 4314 | { |
@@ -4240,7 +4334,7 @@ BOOL LLTextEditor::findHTML(const LLString &line, S32 *begin, S32 *end) const | |||
4240 | 4334 | ||
4241 | if ( ( *end - m1 ) > 2 && m1 > *begin) | 4335 | if ( ( *end - m1 ) > 2 && m1 > *begin) |
4242 | { | 4336 | { |
4243 | LLString badneighbors=".,<>/?';\"][}{=-+_)(*&^%$#@!~`"; | 4337 | std::string badneighbors=".,<>/?';\"][}{=-+_)(*&^%$#@!~`"; |
4244 | m2 = badneighbors.find(line.substr(m1+1,1)); | 4338 | m2 = badneighbors.find(line.substr(m1+1,1)); |
4245 | m3 = badneighbors.find(line.substr(m1-1,1)); | 4339 | m3 = badneighbors.find(line.substr(m1-1,1)); |
4246 | if (m3<0 && m2<0) | 4340 | if (m3<0 && m2<0) |
@@ -4256,8 +4350,8 @@ BOOL LLTextEditor::findHTML(const LLString &line, S32 *begin, S32 *end) const | |||
4256 | { | 4350 | { |
4257 | S32 strpos, strpos2; | 4351 | S32 strpos, strpos2; |
4258 | 4352 | ||
4259 | LLString url = line.substr(*begin,*end - *begin); | 4353 | std::string url = line.substr(*begin,*end - *begin); |
4260 | LLString slurlID = "slurl.com/secondlife/"; | 4354 | std::string slurlID = "slurl.com/secondlife/"; |
4261 | strpos = url.find(slurlID); | 4355 | strpos = url.find(slurlID); |
4262 | 4356 | ||
4263 | if (strpos < 0) | 4357 | if (strpos < 0) |