From 2703125698914e1f2f440b94ac03902f218ebc38 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 28 May 2010 16:55:12 -0700 Subject: Backed out changeset: 13b29333f1db --- indra/llui/lltextbase.cpp | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index d7bbb8a56e..851fb966ec 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -957,18 +957,7 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent) { if (width != getRect().getWidth() || height != getRect().getHeight()) { - //EXT-4288 - //to keep consistance scrolling behaviour - //when scrolling from top and from bottom... - bool is_scrolled_to_end = (mScroller!=NULL) && scrolledToEnd(); - LLUICtrl::reshape( width, height, called_from_parent ); - - if (is_scrolled_to_end) - { - deselect(); - endOfDoc(); - } // do this first after reshape, because other things depend on // up-to-date mVisibleTextRect -- cgit v1.2.3 From 2646eb816677ccda533396235c2270989424d618 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Sat, 29 May 2010 13:31:37 -0700 Subject: EXT-7557 - About Second Life > Credits does not open with scrollbar all the way at the top also made floaters not update title label every time they are resized --- indra/llui/llfloater.cpp | 2 +- indra/llui/lltextbase.cpp | 127 ++++++++++++++++++++++++++++++---------------- 2 files changed, 84 insertions(+), 45 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 6babaf936b..d77c5ead4e 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -330,6 +330,7 @@ void LLFloater::addDragHandle() addChild(mDragHandle); } layoutDragHandle(); + applyTitle(); } void LLFloater::layoutDragHandle() @@ -348,7 +349,6 @@ void LLFloater::layoutDragHandle() } mDragHandle->setRect(rect); updateTitleButtons(); - applyTitle(); } void LLFloater::addResizeCtrls() diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 0e542ad05c..616033f77f 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -962,8 +962,20 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent) { if (width != getRect().getWidth() || height != getRect().getHeight()) { + bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false; + LLUICtrl::reshape( width, height, called_from_parent ); - + + if (mScroller && scrolled_to_bottom && mTrackEnd) + { + // keep bottom of text buffer visible + // do this here as well as in reflow to handle case + // where shrinking from top, which causes buffer to temporarily + // not be scrolled to the bottom, since the scroll index + // specified the _top_ of the visible document region + mScroller->goToBottom(); + } + // do this first after reshape, because other things depend on // up-to-date mVisibleTextRect updateRects(); @@ -1105,6 +1117,34 @@ void LLTextBase::reflow() updateSegments(); + if (mReflowIndex == S32_MAX) + { + return; + } + + bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false; + + LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos); + bool follow_selection = getLocalRect().overlaps(cursor_rect); // cursor is (potentially) visible + + // store in top-left relative coordinates to avoid issues with horizontal scrollbar appearing and disappearing + cursor_rect.mTop = mVisibleTextRect.mTop - cursor_rect.mTop; + cursor_rect.mBottom = mVisibleTextRect.mTop - cursor_rect.mBottom; + + S32 first_line = getFirstVisibleLine(); + + // if scroll anchor not on first line, update it to first character of first line + if (!mLineInfoList.empty() + && (mScrollIndex < mLineInfoList[first_line].mDocIndexStart + || mScrollIndex >= mLineInfoList[first_line].mDocIndexEnd)) + { + mScrollIndex = mLineInfoList[first_line].mDocIndexStart; + } + LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex); + // store in top-left relative coordinates to avoid issues with horizontal scrollbar appearing and disappearing + first_char_rect.mTop = mVisibleTextRect.mTop - first_char_rect.mTop; + first_char_rect.mBottom = mVisibleTextRect.mTop - first_char_rect.mBottom; + S32 reflow_count = 0; while(mReflowIndex < S32_MAX) { @@ -1118,6 +1158,7 @@ void LLTextBase::reflow() lldebugs << "Breaking out of reflow due to possible infinite loop in " << getName() << llendl; break; } + S32 start_index = mReflowIndex; mReflowIndex = S32_MAX; @@ -1125,25 +1166,6 @@ void LLTextBase::reflow() // to force inlined widgets with follows set to shrink mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight()); - bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false; - - LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos); - bool follow_selection = mVisibleTextRect.overlaps(old_cursor_rect); // cursor is visible - old_cursor_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom); - - S32 first_line = getFirstVisibleLine(); - - // if scroll anchor not on first line, update it to first character of first line - if (!mLineInfoList.empty() - && (mScrollIndex < mLineInfoList[first_line].mDocIndexStart - || mScrollIndex >= mLineInfoList[first_line].mDocIndexEnd)) - { - mScrollIndex = mLineInfoList[first_line].mDocIndexStart; - } - LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex); - // subtract off effect of horizontal scrollbar from local position of first char - first_char_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom); - S32 cur_top = 0; segment_set_t::iterator seg_iter = mSegments.begin(); @@ -1264,32 +1286,42 @@ void LLTextBase::reflow() segmentp->updateLayout(*this); } + } - // apply scroll constraints after reflowing text - if (!hasMouseCapture() && mScroller) + // apply scroll constraints after reflowing text + if (!hasMouseCapture() && mScroller) + { + if (scrolled_to_bottom && mTrackEnd) { - if (scrolled_to_bottom && mTrackEnd) - { - // keep bottom of text buffer visible - endOfDoc(); - } - else if (hasSelection() && follow_selection) - { - // keep cursor in same vertical position on screen when selecting text - LLRect new_cursor_rect_doc = getDocRectFromDocIndex(mCursorPos); - mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect); - } - else - { - // keep first line of text visible - LLRect new_first_char_rect = getDocRectFromDocIndex(mScrollIndex); - mScroller->scrollToShowRect(new_first_char_rect, first_char_rect); - } + // keep bottom of text buffer visible + endOfDoc(); } + else if (hasSelection() && follow_selection) + { + // keep cursor in same vertical position on screen when selecting text + LLRect new_cursor_rect_doc = getDocRectFromDocIndex(mCursorPos); + LLRect old_cursor_rect = cursor_rect; + old_cursor_rect.mTop = mVisibleTextRect.mTop - cursor_rect.mTop; + old_cursor_rect.mBottom = mVisibleTextRect.mTop - cursor_rect.mBottom; - // reset desired x cursor position - updateCursorXPos(); + mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect); + } + else + { + // keep first line of text visible + LLRect new_first_char_rect = getDocRectFromDocIndex(mScrollIndex); + + // pass in desired rect in the coordinate frame of the document viewport + LLRect old_first_char_rect = first_char_rect; + old_first_char_rect.mTop = mVisibleTextRect.mTop - first_char_rect.mTop; + old_first_char_rect.mBottom = mVisibleTextRect.mTop - first_char_rect.mBottom; + + mScroller->scrollToShowRect(new_first_char_rect, old_first_char_rect); + } } + + // reset desired x cursor position + updateCursorXPos(); } LLRect LLTextBase::getTextBoundingRect() @@ -1947,11 +1979,18 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const { + LLRect content_window_rect = mScroller ? mScroller->getContentWindowRect() : getLocalRect(); + if (mBorderVisible) + { + content_window_rect.stretch(-1); + } + LLRect local_rect; + if (mLineInfoList.empty()) { // return default height rect in upper left - local_rect = mVisibleTextRect; + local_rect = content_window_rect; local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight()); return local_rect; } @@ -1962,8 +2001,8 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const // compensate for scrolled, inset view of doc LLRect scrolled_view_rect = getVisibleDocumentRect(); local_rect = doc_rect; - local_rect.translate(mVisibleTextRect.mLeft - scrolled_view_rect.mLeft, - mVisibleTextRect.mBottom - scrolled_view_rect.mBottom); + local_rect.translate(content_window_rect.mLeft - scrolled_view_rect.mLeft, + content_window_rect.mBottom - scrolled_view_rect.mBottom); return local_rect; } -- cgit v1.2.3 From 1e090dafa6271ec2acb92441bcbbbbe058124be0 Mon Sep 17 00:00:00 2001 From: Andrew Dyukov Date: Tue, 1 Jun 2010 16:42:31 +0300 Subject: EXT-7087 ADDITIONAL FIX Style changes regarding image_flash attribute Removed default "FlashIconAbsent" value of image_flash button attribute. Changed check for presence of thic icon in code accordingly. --HG-- branch : product-engine --- indra/llui/llbutton.cpp | 4 ++-- indra/llui/llbutton.h | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index a8f72183fd..34f3049f2e 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -636,8 +636,8 @@ void LLButton::draw() if (mFlashing) { - // if we have icon for flashing, use it as image for button - if(flash && mImageFlash->getName() != "FlashIconAbsent") + // if button should flash and we have icon for flashing, use it as image for button + if(flash && mImageFlash) { // setting flash to false to avoid its further influence on glow flash = false; diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index b251c3d65d..9bd566d3c9 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -314,8 +314,7 @@ private: /* There are two ways an image can flash- by making changes in color according to flash_color attribute or by changing icon from current to the one specified in image_flash. Second way is used only if - the name of flash icon is different from "FlashIconAbsent" which is there by default. First way is used - otherwise. */ + flash icon name is set in attributes(by default it isn't). First way is used otherwise. */ LLPointer mImageFlash; LLUIColor mHighlightColor; -- cgit v1.2.3 From 71fe767d9a151c6e92d7cdb6b9ab820ce814de44 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 1 Jun 2010 18:28:46 -0700 Subject: EXT-7590 FIX Modal alerts obscure any modal alerts that they spawn the toast logic to set visibility on dialogs in reverse order was bringing older modal dialogs to the front --- indra/llui/llfloater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index d77c5ead4e..fad98e553f 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2519,7 +2519,7 @@ LLFloater *LLFloaterView::getBackmost() const void LLFloaterView::syncFloaterTabOrder() { - // look for a visible modal dialog, starting from first (should be only one) + // look for a visible modal dialog, starting from first LLModalDialog* modal_dialog = NULL; for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { -- cgit v1.2.3 From 8beb651d764032e47b976b7495a048174936e1e6 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 1 Jun 2010 18:33:41 -0700 Subject: EXT-7591 FIX Typing the first characters of a selection in a dropdown will ignore the first letter clear the searchstring on list focus lost, not setFocus, so that the act of popping open the list when you type the first letter doesn't clear the first letter from the search string --- indra/llui/llscrolllistctrl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 94eade06ad..d4d161f2c9 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -2949,7 +2949,6 @@ BOOL LLScrollListCtrl::operateOnAll(EOperation op) //virtual void LLScrollListCtrl::setFocus(BOOL b) { - mSearchString.clear(); // for tabbing into pristine scroll lists (Finder) if (!getFirstSelected()) { @@ -2994,6 +2993,9 @@ void LLScrollListCtrl::onFocusLost() { gFocusMgr.setMouseCapture(NULL); } + + mSearchString.clear(); + LLUICtrl::onFocusLost(); } -- cgit v1.2.3 From 9e7cf5c1bc9174d65c2541f54a3a70a2864519b7 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 2 Jun 2010 13:33:15 -0700 Subject: eliminated several warnings on startup --- indra/llui/lltextbase.cpp | 8 +++----- indra/llui/lltextparser.cpp | 40 ++++++++++++++-------------------------- indra/llui/lltextparser.h | 15 +++++++-------- 3 files changed, 24 insertions(+), 39 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 616033f77f..71c7811757 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1704,13 +1704,11 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen setCursorPos(old_length); - LLTextParser* highlight = LLTextParser::getInstance(); - - if (mParseHighlights && highlight) + if (mParseHighlights) { LLStyle::Params highlight_params(style_params); - - LLSD pieces = highlight->parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part); +. + LLSD pieces = LLTextParser::instance().parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part); for (S32 i = 0; i < pieces.size(); i++) { LLSD color_llsd = pieces[i]["color"]; diff --git a/indra/llui/lltextparser.cpp b/indra/llui/lltextparser.cpp index 76a39e3094..2493afcb5d 100644 --- a/indra/llui/lltextparser.cpp +++ b/indra/llui/lltextparser.cpp @@ -43,29 +43,14 @@ #include "v4color.h" #include "lldir.h" -// Routines used for parsing text for TextParsers and html - -LLTextParser* LLTextParser::sInstance = NULL; - // // Member Functions // -LLTextParser::~LLTextParser() -{ - sInstance=NULL; -} +LLTextParser::LLTextParser() +: mLoaded(false) +{} -// static -LLTextParser* LLTextParser::getInstance() -{ - if (!sInstance) - { - sInstance = new LLTextParser(); - sInstance->loadFromDisk(); - } - return sInstance; -} // Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency. @@ -105,6 +90,8 @@ S32 LLTextParser::findPattern(const std::string &text, LLSD highlight) LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index) { + loadKeywords(); + //evil recursive string atomizer. LLSD ret_llsd, start_llsd, middle_llsd, end_llsd; @@ -195,6 +182,8 @@ LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLC bool LLTextParser::parseFullLineHighlights(const std::string &text, LLColor4 *color) { + loadKeywords(); + for (S32 i=0;i { public: typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType; @@ -48,22 +49,20 @@ public: typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition; typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction; - static LLTextParser* getInstance(); - LLTextParser(){}; - ~LLTextParser(); + LLTextParser(); - S32 findPattern(const std::string &text, LLSD highlight); LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0); bool parseFullLineHighlights(const std::string &text, LLColor4 *color); +private: + S32 findPattern(const std::string &text, LLSD highlight); std::string getFileName(); - LLSD loadFromDisk(); + void loadKeywords(); bool saveToDisk(LLSD highlights); public: LLSD mHighlights; -private: - static LLTextParser* sInstance; + bool mLoaded; }; #endif -- cgit v1.2.3 From 6df66c35b38371ffaa20094dc2be140574e989c8 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 2 Jun 2010 14:43:45 -0700 Subject: fixed compile error --- indra/llui/lltextbase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 71c7811757..f0a8f70ae5 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1707,7 +1707,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen if (mParseHighlights) { LLStyle::Params highlight_params(style_params); -. + LLSD pieces = LLTextParser::instance().parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part); for (S32 i = 0; i < pieces.size(); i++) { -- cgit v1.2.3 From 5c263cdc64507cfa1f0f88712b45332894aab09e Mon Sep 17 00:00:00 2001 From: Yuri Chebotarev Date: Thu, 3 Jun 2010 10:38:03 +0300 Subject: EXT-6333 FIX introduce new segments - LLLineBreakSegment and LLImageSegment reviewed by Richard Nelson at https://codereview.productengine.com/secondlife/r/241/ --HG-- branch : product-engine --- indra/llui/lltextbase.cpp | 282 +++++++++++++++++++++++------------ indra/llui/lltextbase.h | 34 +++++ indra/llui/lltexteditor.cpp | 49 +++++- indra/llui/lltexteditor.h | 1 + indra/llui/llurlentry.h | 2 + indra/llui/llurlmatch.cpp | 3 +- indra/llui/llurlmatch.h | 7 +- indra/llui/llurlregistry.cpp | 6 +- indra/llui/tests/llurlmatch_test.cpp | 30 ++-- 9 files changed, 294 insertions(+), 120 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 78a6ab1eaa..ab9cd11769 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1562,7 +1562,7 @@ std::string LLTextBase::getText() const return getViewModel()->getValue().asString(); } -void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params) +void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params) { LLStyle::Params style_params(input_params); style_params.fillFrom(getDefaultStyleParams()); @@ -1598,8 +1598,7 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c part = (S32)LLTextParser::MIDDLE; } std::string subtext=text.substr(0,start); - appendAndHighlightText(subtext, prepend_newline, part, style_params); - prepend_newline = false; + appendAndHighlightTextImpl(subtext, part, style_params); } // output an optional icon before the Url @@ -1613,19 +1612,18 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c // Text will be replaced during rendering with the icon, // but string cannot be empty or the segment won't be // added (or drawn). - appendAndHighlightText(" ", prepend_newline, part, icon); - prepend_newline = false; + appendImageSegment(part, icon); } } // output the styled Url (unless we've been asked to suppress hyperlinking) if (match.isLinkDisabled()) { - appendAndHighlightText(match.getLabel(), prepend_newline, part, style_params); + appendAndHighlightTextImpl(match.getLabel(), part, style_params); } else { - appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params); + appendAndHighlightTextImpl(match.getLabel(), part, link_params); // set the tooltip for the Url label if (! match.getTooltip().empty()) @@ -1638,8 +1636,6 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c } } } - prepend_newline = false; - // move on to the rest of the text after the Url if (end < (S32)text.length()) { @@ -1652,13 +1648,41 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c break; } } - if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END; - if (end < (S32)text.length()) appendAndHighlightText(text, prepend_newline, part, style_params); + if (part != (S32)LLTextParser::WHOLE) + part=(S32)LLTextParser::END; + if (end < (S32)text.length()) + appendAndHighlightTextImpl(text, part, style_params); } else { - appendAndHighlightText(new_text, prepend_newline, part, style_params); + appendAndHighlightTextImpl(new_text, part, style_params); + } +} + +void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params) +{ + if (new_text.empty()) + return; + + if(prepend_newline) + appendLineBreakSegment(input_params); + std::string::size_type start = 0; + std::string::size_type pos = new_text.find("\n",start); + + while(pos!=-1) + { + if(pos!=start) + { + std::string str = std::string(new_text,start,pos-start); + appendTextImpl(str,input_params); + } + appendLineBreakSegment(input_params); + start = pos+1; + pos = new_text.find("\n",start); } + + std::string str = std::string(new_text,start,new_text.length()-start); + appendTextImpl(str,input_params); } void LLTextBase::needsReflow(S32 index) @@ -1667,10 +1691,28 @@ void LLTextBase::needsReflow(S32 index) mReflowIndex = llmin(mReflowIndex, index); } -void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& style_params) +void LLTextBase::appendLineBreakSegment(const LLStyle::Params& style_params) { - if (new_text.empty()) return; + segment_vec_t segments; + LLStyleConstSP sp(new LLStyle(style_params)); + segments.push_back(new LLLineBreakTextSegment(sp, getLength())); + insertStringNoUndo(getLength(), utf8str_to_wstring("\n"), &segments); +} + +void LLTextBase::appendImageSegment(S32 highlight_part, const LLStyle::Params& style_params) +{ + segment_vec_t segments; + LLStyleConstSP sp(new LLStyle(style_params)); + segments.push_back(new LLImageTextSegment(sp, getLength(),*this)); + + insertStringNoUndo(getLength(), utf8str_to_wstring(" "), &segments); +} + + + +void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params) +{ // Save old state S32 selection_start = mSelectionStart; S32 selection_end = mSelectionEnd; @@ -1698,14 +1740,8 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen highlight_params.color = lcolor; LLWString wide_text; - if (prepend_newline && (i == 0 || pieces.size() <= 1 )) - { - wide_text = utf8str_to_wstring(std::string("\n") + pieces[i]["text"].asString()); - } - else - { - wide_text = utf8str_to_wstring(pieces[i]["text"].asString()); - } + wide_text = utf8str_to_wstring(pieces[i]["text"].asString()); + S32 cur_length = getLength(); LLStyleConstSP sp(new LLStyle(highlight_params)); LLTextSegmentPtr segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this); @@ -1717,17 +1753,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen else { LLWString wide_text; - - // Add carriage return if not first line - if (getLength() != 0 - && prepend_newline) - { - wide_text = utf8str_to_wstring(std::string("\n") + new_text); - } - else - { - wide_text = utf8str_to_wstring(new_text); - } + wide_text = utf8str_to_wstring(new_text); segment_vec_t segments; S32 segment_start = old_length; @@ -1755,11 +1781,32 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen { setCursorPos(cursor_pos); } +} + +void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& style_params) +{ + if (new_text.empty()) return; + + if(prepend_newline) + appendLineBreakSegment(style_params); + + std::string::size_type start = 0; + std::string::size_type pos = new_text.find("\n",start); + + while(pos!=-1) + { + if(pos!=start) + { + std::string str = std::string(new_text,start,pos-start); + appendAndHighlightTextImpl(str,highlight_part, style_params); + } + appendLineBreakSegment(style_params); + start = pos+1; + pos = new_text.find("\n",start); + } - //if( !allow_undo ) - //{ - // blockUndo(); - //} + std::string str = std::string(new_text,start,new_text.length()-start); + appendAndHighlightTextImpl(str,highlight_part, style_params); } @@ -1852,14 +1899,19 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, S32 text_width, text_height; bool newline = segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height); + if(newline) + { + pos = segment_line_start + segmentp->getOffset(local_x - start_x, line_seg_offset, segment_line_length, round); + break; + } + // if we've reached a line of text *below* the mouse cursor, doc index is first character on that line if (hit_past_end_of_line && local_y - mVisibleTextRect.mBottom + visible_region.mBottom > line_iter->mRect.mTop) { pos = segment_line_start; break; } - if (local_x < start_x + text_width // cursor to left of right edge of text - || newline) // or this line ends with a newline, set doc pos to newline char + if (local_x < start_x + text_width) // cursor to left of right edge of text { // Figure out which character we're nearest to. S32 offset; @@ -1883,13 +1935,13 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, pos = segment_line_start + offset; break; } - else if (hit_past_end_of_line && segmentp->getEnd() >= line_iter->mDocIndexEnd - 1) + else if (hit_past_end_of_line && segmentp->getEnd() > line_iter->mDocIndexEnd - 1) { - // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd) - pos = llmin(getLength(), line_iter->mDocIndexEnd); + // segment wraps to next line, so just set doc pos to the end of the line + // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd) + pos = llmin(getLength(), line_iter->mDocIndexEnd); break; } - start_x += text_width; } @@ -2346,25 +2398,6 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec { if( end - start > 0 ) { - if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart)) - { - // ...for images, only render the image, not the underlying text, - // which is only a placeholder space - LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha; - LLUIImagePtr image = mStyle->getImage(); - S32 style_image_height = image->getHeight(); - S32 style_image_width = image->getWidth(); - // Text is drawn from the top of the draw_rect downward - S32 text_center = draw_rect.mTop - (mFontHeight / 2); - // Align image to center of text - S32 image_bottom = text_center - (style_image_height / 2); - image->draw(draw_rect.mLeft, image_bottom, - style_image_width, style_image_height, color); - - const S32 IMAGE_HPAD = 3; - return draw_rect.mLeft + style_image_width + IMAGE_HPAD; - } - return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect); } return draw_rect.mLeft; @@ -2377,11 +2410,6 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele const LLWString &text = mEditor.getWText(); - if ( text[seg_end-1] == '\n' ) - { - --seg_end; - } - F32 right_x = rect.mLeft; if (!mStyle->isVisible()) { @@ -2540,33 +2568,14 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt { height = 0; width = 0; - bool force_newline = false; if (num_chars > 0) { height = mFontHeight; const LLWString &text = mEditor.getWText(); // if last character is a newline, then return true, forcing line break - llwchar last_char = text[mStart + first_char + num_chars - 1]; - if (last_char == '\n') - { - force_newline = true; - // don't count newline in font width - width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars - 1); - } - else - { - width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); - } - } - - LLUIImagePtr image = mStyle->getImage(); - if( image.notNull()) - { - width += image->getWidth(); - height = llmax(height, image->getHeight()); + width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); } - - return force_newline; + return false; } S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const @@ -2589,15 +2598,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin num_pixels = llmax(0, num_pixels - image->getWidth()); } - // search for newline and if found, truncate there - S32 last_char = mStart + segment_offset; - for (; last_char != mEnd; ++last_char) - { - if (text[last_char] == '\n') - { - break; - } - } + S32 last_char = mEnd; // set max characters to length of segment, or to first newline max_chars = llmin(max_chars, last_char - (mStart + segment_offset)); @@ -2625,8 +2626,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin S32 last_char_in_run = mStart + segment_offset + num_chars; // check length first to avoid indexing off end of string if (last_char_in_run < mEnd - && (last_char_in_run >= mEditor.getLength() - || text[last_char_in_run] == '\n')) + && (last_char_in_run >= mEditor.getLength() )) { num_chars++; } @@ -2721,3 +2721,87 @@ void LLInlineViewSegment::linkToDocument(LLTextBase* editor) { editor->addDocumentChild(mView); } + +LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1) +{ + mFontHeight = llceil(style->getFont()->getLineHeight()); +} +LLLineBreakTextSegment::~LLLineBreakTextSegment() +{ +} +bool LLLineBreakTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +{ + width = 0; + height = mFontHeight; + + return true; +} +S32 LLLineBreakTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const +{ + return 1; +} +F32 LLLineBreakTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) +{ + return draw_rect.mLeft; +} + +LLImageTextSegment::LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor) + :LLTextSegment(pos,pos+1) + ,mStyle( style ) + ,mEditor(editor) +{ +} + +LLImageTextSegment::~LLImageTextSegment() +{ +} + +static const S32 IMAGE_HPAD = 3; + +bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +{ + width = 0; + height = llceil(mStyle->getFont()->getLineHeight());; + + LLUIImagePtr image = mStyle->getImage(); + if( image.notNull()) + { + width += image->getWidth() + IMAGE_HPAD; + height = llmax(height, image->getHeight() + IMAGE_HPAD ); + } + return false; +} + +S32 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const +{ + LLUIImagePtr image = mStyle->getImage(); + S32 image_width = image->getWidth(); + if(num_pixels>image_width + IMAGE_HPAD) + { + return 1; + } + + return 0; +} +F32 LLImageTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) +{ + if ( (start >= 0) && (end <= mEnd - mStart)) + { + LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha; + LLUIImagePtr image = mStyle->getImage(); + S32 style_image_height = image->getHeight(); + S32 style_image_width = image->getWidth(); + // Text is drawn from the top of the draw_rect downward + + S32 text_center = draw_rect.mTop - (draw_rect.getHeight() / 2); + // Align image to center of draw rect + S32 image_bottom = text_center - (style_image_height / 2); + image->draw(draw_rect.mLeft, image_bottom, + style_image_width, style_image_height, color); + + const S32 IMAGE_HPAD = 3; + return draw_rect.mLeft + style_image_width + IMAGE_HPAD; + } + return 0.0; +} + diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 8ed0680df9..176308c61a 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -316,6 +316,13 @@ protected: void needsScroll() { mScrollNeeded = TRUE; } void replaceUrlLabel(const std::string &url, const std::string &label); + void appendLineBreakSegment(const LLStyle::Params& style_params); + void appendImageSegment(S32 highlight_part, const LLStyle::Params& style_params); + + void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); + void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params); + + protected: // text segmentation and flow segment_set_t mSegments; @@ -507,5 +514,32 @@ private: bool mForceNewLine; }; +class LLLineBreakTextSegment : public LLTextSegment +{ +public: + + LLLineBreakTextSegment(LLStyleConstSP style,S32 pos); + ~LLLineBreakTextSegment(); + bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; + S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; + F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); + +private: + S32 mFontHeight; +}; + +class LLImageTextSegment : public LLTextSegment +{ +public: + LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor); + ~LLImageTextSegment(); + bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; + S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; + F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); + +private: + class LLTextBase& mEditor; + LLStyleConstSP mStyle; +}; #endif diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 4fd62045e8..c9474d66b7 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1083,6 +1083,28 @@ void LLTextEditor::addChar(llwchar wc) setCursorPos(mCursorPos + addChar( mCursorPos, wc )); } +void LLTextEditor::addLineBreakChar() +{ + if( !getEnabled() ) + { + return; + } + if( hasSelection() ) + { + deleteSelection(TRUE); + } + else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) + { + removeChar(mCursorPos); + } + + LLStyleConstSP sp(new LLStyle(LLStyle::Params())); + LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos); + + S32 pos = execute(new TextCmdAddChar(mCursorPos, FALSE, '\n', segment)); + + setCursorPos(mCursorPos + pos); +} BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask) @@ -1404,7 +1426,27 @@ void LLTextEditor::pasteHelper(bool is_primary) } // Insert the new text into the existing text. - setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE, LLTextSegmentPtr())); + + //paste text with linebreaks. + std::basic_string::size_type start = 0; + std::basic_string::size_type pos = clean_string.find('\n',start); + + while(pos!=-1) + { + if(pos!=start) + { + std::basic_string str = std::basic_string(clean_string,start,pos-start); + setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); + } + addLineBreakChar(); + + start = pos+1; + pos = clean_string.find('\n',start); + } + + std::basic_string str = std::basic_string(clean_string,start,clean_string.length()-start); + setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); + deselect(); onKeyStroke(); @@ -2169,7 +2211,10 @@ void LLTextEditor::autoIndent() } // Insert that number of spaces on the new line - addChar( '\n' ); + + //appendLineBreakSegment(LLStyle::Params());//addChar( '\n' ); + addLineBreakChar(); + for( i = 0; i < space_count; i++ ) { addChar( ' ' ); diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 9b3ab9414c..7b68974fd8 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -240,6 +240,7 @@ protected: // Undoable operations void addChar(llwchar c); // at mCursorPos S32 addChar(S32 pos, llwchar wc); + void addLineBreakChar(); S32 overwriteChar(S32 pos, llwchar wc); void removeChar(); S32 removeChar(S32 pos); diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 71f030677a..3c21fe8d61 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -94,6 +94,8 @@ public: /// is this a match for a URL that should not be hyperlinked? bool isLinkDisabled() const { return mDisabledLink; } + virtual LLUUID getID(const std::string &string) const { return LLUUID::null; } + protected: std::string getIDStringFromUrl(const std::string &url) const; std::string escapeUrl(const std::string &url) const; diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp index 72a199c220..7c96665ce4 100644 --- a/indra/llui/llurlmatch.cpp +++ b/indra/llui/llurlmatch.cpp @@ -51,7 +51,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url, const std::string &label, const std::string &tooltip, const std::string &icon, const LLUIColor& color, const std::string &menu, const std::string &location, - bool disabled_link) + bool disabled_link, const LLUUID& id) { mStart = start; mEnd = end; @@ -63,4 +63,5 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url, mMenuName = menu; mLocation = location; mDisabledLink = disabled_link; + mID = id; } diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h index e86762548b..78dd2c528f 100644 --- a/indra/llui/llurlmatch.h +++ b/indra/llui/llurlmatch.h @@ -90,7 +90,10 @@ public: void setValues(U32 start, U32 end, const std::string &url, const std::string &label, const std::string &tooltip, const std::string &icon, const LLUIColor& color, const std::string &menu, - const std::string &location, bool disabled_link); + const std::string &location, bool disabled_link + , const LLUUID& id ); + + const LLUUID& getID() const { return mID;} private: U32 mStart; @@ -101,6 +104,8 @@ private: std::string mIcon; std::string mMenuName; std::string mLocation; + + LLUUID mID; LLUIColor mColor; bool mDisabledLink; }; diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 4341286eb4..1f86f72faa 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -183,7 +183,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL match_entry->getColor(), match_entry->getMenuName(), match_entry->getLocation(url), - match_entry->isLinkDisabled()); + match_entry->isLinkDisabled(), + match_entry->getID(url)); return true; } @@ -217,7 +218,8 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr match.getColor(), match.getMenuName(), match.getLocation(), - match.isLinkDisabled()); + match.isLinkDisabled(), + match.getID()); return true; } return false; diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 24a32de268..06b850d233 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -54,7 +54,7 @@ namespace tut LLUrlMatch match; ensure("empty()", match.empty()); - match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false); + match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure("! empty()", ! match.empty()); } @@ -67,7 +67,7 @@ namespace tut LLUrlMatch match; ensure_equals("getStart() == 0", match.getStart(), 0); - match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getStart() == 10", match.getStart(), 10); } @@ -80,7 +80,7 @@ namespace tut LLUrlMatch match; ensure_equals("getEnd() == 0", match.getEnd(), 0); - match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getEnd() == 20", match.getEnd(), 20); } @@ -93,10 +93,10 @@ namespace tut LLUrlMatch match; ensure_equals("getUrl() == ''", match.getUrl(), ""); - match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/"); - match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getUrl() == '' (2)", match.getUrl(), ""); } @@ -109,10 +109,10 @@ namespace tut LLUrlMatch match; ensure_equals("getLabel() == ''", match.getLabel(), ""); - match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label"); - match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getLabel() == '' (2)", match.getLabel(), ""); } @@ -125,10 +125,10 @@ namespace tut LLUrlMatch match; ensure_equals("getTooltip() == ''", match.getTooltip(), ""); - match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info"); - match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getTooltip() == '' (2)", match.getTooltip(), ""); } @@ -141,10 +141,10 @@ namespace tut LLUrlMatch match; ensure_equals("getIcon() == ''", match.getIcon(), ""); - match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon"); - match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure_equals("getIcon() == '' (2)", match.getIcon(), ""); } @@ -157,10 +157,10 @@ namespace tut LLUrlMatch match; ensure("getMenuName() empty", match.getMenuName().empty()); - match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false); + match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false,LLUUID::null); ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml"); - match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure("getMenuName() empty (2)", match.getMenuName().empty()); } @@ -173,10 +173,10 @@ namespace tut LLUrlMatch match; ensure("getLocation() empty", match.getLocation().empty()); - match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false); + match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false,LLUUID::null); ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris"); - match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false); + match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null); ensure("getLocation() empty (2)", match.getLocation().empty()); } } -- cgit v1.2.3 From 46e1253ee11cd2aca41314ec4e9c053bddd7a0b4 Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Fri, 4 Jun 2010 14:25:51 -0700 Subject: DEV-50015 FIX Implement changes to the Buy L$ button in the top bar of the viewer reviewed by Mani --- indra/llui/lltextbase.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 55dbf50fd7..d86709c448 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1101,7 +1101,7 @@ S32 LLTextBase::getLeftOffset(S32 width) case LLFontGL::LEFT: return mHPad; case LLFontGL::HCENTER: - return mHPad + (mVisibleTextRect.getWidth() - width - mHPad) / 2; + return mHPad + llmax(0, (mVisibleTextRect.getWidth() - width - mHPad) / 2); case LLFontGL::RIGHT: return mVisibleTextRect.getWidth() - width; default: @@ -1207,11 +1207,6 @@ void LLTextBase::reflow() // grow line height as necessary based on reported height of this segment line_height = llmax(line_height, segment_height); remaining_pixels -= segment_width; - if (remaining_pixels < 0) - { - // getNumChars() and getDimensions() should return consistent results - remaining_pixels = 0; - } seg_offset += character_count; @@ -1893,7 +1888,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, { // Figure out which line we're nearest to. LLRect visible_region = getVisibleDocumentRect(); - + // binary search for line that starts before local_y line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mVisibleTextRect.mBottom + visible_region.mBottom, compare_bottom()); @@ -1903,7 +1898,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, } S32 pos = getLength(); - S32 start_x = mVisibleTextRect.mLeft + line_iter->mRect.mLeft; + S32 start_x = mVisibleTextRect.mLeft + line_iter->mRect.mLeft - visible_region.mLeft; segment_set_t::iterator line_seg_iter; S32 line_seg_offset; -- cgit v1.2.3