summaryrefslogtreecommitdiff
path: root/indra/llui/lltextbase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/lltextbase.cpp')
-rw-r--r--indra/llui/lltextbase.cpp135
1 files changed, 118 insertions, 17 deletions
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 349dbc3405..7aeeae298f 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -598,7 +598,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
pos = getEditableIndex(pos, true);
- segment_set_t::iterator seg_iter = getSegIterContaining(pos);
+ segment_set_t::iterator seg_iter = getEditableSegIterContaining(pos);
LLTextSegmentPtr default_segment;
@@ -1192,7 +1192,10 @@ void LLTextBase::reflow()
// shrink document to minimum size (visible portion of text widget)
// to force inlined widgets with follows set to shrink
- mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight());
+ if (mWordWrap)
+ {
+ mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight());
+ }
S32 cur_top = 0;
@@ -1510,8 +1513,48 @@ void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg
}
}
+LLTextBase::segment_set_t::iterator LLTextBase::getEditableSegIterContaining(S32 index)
+{
+ segment_set_t::iterator it = getSegIterContaining(index);
+ segment_set_t::iterator orig_it = it;
+
+ if (it == mSegments.end()) return it;
+
+ if (!(*it)->canEdit()
+ && index == (*it)->getStart()
+ && it != mSegments.begin())
+ {
+ it--;
+ if ((*it)->canEdit())
+ {
+ return it;
+ }
+ }
+ return orig_it;
+}
+
+LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaining(S32 index) const
+{
+ segment_set_t::const_iterator it = getSegIterContaining(index);
+ segment_set_t::const_iterator orig_it = it;
+ if (it == mSegments.end()) return it;
+
+ if (!(*it)->canEdit()
+ && index == (*it)->getStart()
+ && it != mSegments.begin())
+ {
+ it--;
+ if ((*it)->canEdit())
+ {
+ return it;
+ }
+ }
+ return orig_it;
+}
+
LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
{
+
static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment();
if (index > getLength()) { return mSegments.end(); }
@@ -2024,8 +2067,17 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
}
else if (hit_past_end_of_line && segmentp->getEnd() >= line_iter->mDocIndexEnd)
{
- // segment wraps to next line, so just set doc pos to the end of the line
- pos = llclamp(line_iter->mDocIndexEnd - 1, 0, getLength());
+ if (getLineNumFromDocIndex(line_iter->mDocIndexEnd - 1) == line_iter->mLineNum)
+ {
+ // if segment wraps to the next line we should step one char back
+ // to compensate for the space char between words
+ // which is removed due to wrapping
+ pos = llclamp(line_iter->mDocIndexEnd - 1, 0, getLength());
+ }
+ else
+ {
+ pos = llclamp(line_iter->mDocIndexEnd, 0, getLength());
+ }
break;
}
start_x += text_width;
@@ -2108,7 +2160,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
{
// return default height rect in upper left
local_rect = content_window_rect;
- local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
+ local_rect.mBottom = local_rect.mTop - mDefaultFont->getLineHeight();
return local_rect;
}
@@ -2331,6 +2383,9 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)
void LLTextBase::updateRects()
{
+ LLRect old_text_rect = mVisibleTextRect;
+ mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
+
if (mLineInfoList.empty())
{
mTextBoundingRect = LLRect(0, mVPad, mHPad, 0);
@@ -2346,10 +2401,24 @@ void LLTextBase::updateRects()
}
mTextBoundingRect.mTop += mVPad;
- // subtract a pixel off the bottom to deal with rounding errors in measuring font height
- mTextBoundingRect.mBottom -= 1;
- S32 delta_pos = -mTextBoundingRect.mBottom;
+ S32 delta_pos = 0;
+
+ switch(mVAlign)
+ {
+ case LLFontGL::TOP:
+ delta_pos = llmax(mVisibleTextRect.getHeight() - mTextBoundingRect.mTop, -mTextBoundingRect.mBottom);
+ break;
+ case LLFontGL::VCENTER:
+ delta_pos = (llmax(mVisibleTextRect.getHeight() - mTextBoundingRect.mTop, -mTextBoundingRect.mBottom) + (mVisibleTextRect.mBottom - mTextBoundingRect.mBottom)) / 2;
+ break;
+ case LLFontGL::BOTTOM:
+ delta_pos = mVisibleTextRect.mBottom - mTextBoundingRect.mBottom;
+ break;
+ case LLFontGL::BASELINE:
+ // do nothing
+ break;
+ }
// move line segments to fit new document rect
for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
{
@@ -2359,8 +2428,9 @@ void LLTextBase::updateRects()
}
// update document container dimensions according to text contents
- LLRect doc_rect = mTextBoundingRect;
+ LLRect doc_rect;
// use old mVisibleTextRect constraint document to width of viewable region
+ doc_rect.mBottom = llmin(mVisibleTextRect.mBottom, mTextBoundingRect.mBottom);
doc_rect.mLeft = 0;
// allow horizontal scrolling?
@@ -2370,11 +2440,22 @@ void LLTextBase::updateRects()
doc_rect.mRight = mScroller
? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
: mVisibleTextRect.getWidth();
+ doc_rect.mTop = llmax(mVisibleTextRect.mTop, mTextBoundingRect.mTop);
if (!mScroller)
{
// push doc rect to top of text widget
- doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop);
+ switch(mVAlign)
+ {
+ case LLFontGL::TOP:
+ doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop);
+ break;
+ case LLFontGL::VCENTER:
+ doc_rect.translate(0, (mVisibleTextRect.getHeight() - doc_rect.mTop) / 2);
+ case LLFontGL::BOTTOM:
+ default:
+ break;
+ }
}
mDocumentView->setShape(doc_rect);
@@ -2382,7 +2463,6 @@ void LLTextBase::updateRects()
//update mVisibleTextRect *after* mDocumentView has been resized
// so that scrollbars are added if document needs to scroll
// since mVisibleTextRect does not include scrollbars
- LLRect old_text_rect = mVisibleTextRect;
mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
//FIXME: replace border with image?
if (mBorderVisible)
@@ -2395,9 +2475,27 @@ void LLTextBase::updateRects()
}
// update document container again, using new mVisibleTextRect (that has scrollbars enabled as needed)
+ doc_rect.mBottom = llmin(mVisibleTextRect.mBottom, mTextBoundingRect.mBottom);
+ doc_rect.mLeft = 0;
doc_rect.mRight = mScroller
? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
: mVisibleTextRect.getWidth();
+ doc_rect.mTop = llmax(mVisibleTextRect.mTop, mTextBoundingRect.mTop);
+ if (!mScroller)
+ {
+ // push doc rect to top of text widget
+ switch(mVAlign)
+ {
+ case LLFontGL::TOP:
+ doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop);
+ break;
+ case LLFontGL::VCENTER:
+ doc_rect.translate(0, (mVisibleTextRect.getHeight() - doc_rect.mTop) / 2);
+ case LLFontGL::BOTTOM:
+ default:
+ break;
+ }
+ }
mDocumentView->setShape(doc_rect);
}
@@ -2509,7 +2607,10 @@ BOOL LLTextSegment::handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }
BOOL LLTextSegment::handleHover(S32 x, S32 y, MASK mask) { return FALSE; }
BOOL LLTextSegment::handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }
BOOL LLTextSegment::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; }
-std::string LLTextSegment::getName() const { return ""; }
+const std::string& LLTextSegment::getName() const
+{
+ return LLStringUtil::null;
+}
void LLTextSegment::onMouseCaptureLost() {}
void LLTextSegment::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}
void LLTextSegment::localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}
@@ -2525,7 +2626,7 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e
mToken(NULL),
mEditor(editor)
{
- mFontHeight = llceil(mStyle->getFont()->getLineHeight());
+ mFontHeight = mStyle->getFont()->getLineHeight();
LLUIImagePtr image = mStyle->getImage();
if (image.notNull())
@@ -2541,7 +2642,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32
{
mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color));
- mFontHeight = llceil(mStyle->getFont()->getLineHeight());
+ mFontHeight = mStyle->getFont()->getLineHeight();
}
LLNormalTextSegment::~LLNormalTextSegment()
@@ -2909,11 +3010,11 @@ LLLineBreakTextSegment::LLLineBreakTextSegment(S32 pos):LLTextSegment(pos,pos+1)
{
LLStyleSP s( new LLStyle(LLStyle::Params().visible(true)));
- mFontHeight = llceil(s->getFont()->getLineHeight());
+ mFontHeight = s->getFont()->getLineHeight();
}
LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1)
{
- mFontHeight = llceil(style->getFont()->getLineHeight());
+ mFontHeight = style->getFont()->getLineHeight();
}
LLLineBreakTextSegment::~LLLineBreakTextSegment()
{
@@ -2950,7 +3051,7 @@ 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());;
+ height = mStyle->getFont()->getLineHeight();
LLUIImagePtr image = mStyle->getImage();
if( num_chars>0 && image.notNull())