summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llbutton.cpp7
-rw-r--r--indra/llui/llbutton.h3
-rw-r--r--indra/llui/lldockablefloater.h3
-rw-r--r--indra/llui/lldockcontrol.h3
-rw-r--r--indra/llui/lldraghandle.cpp1
-rw-r--r--indra/llui/llflatlistview.cpp8
-rw-r--r--indra/llui/llfloater.cpp13
-rw-r--r--indra/llui/llhelp.h2
-rw-r--r--indra/llui/llmenugl.cpp2
-rw-r--r--indra/llui/llmenugl.h15
-rw-r--r--indra/llui/llpanel.h1
-rw-r--r--indra/llui/lltabcontainer.cpp2
-rw-r--r--indra/llui/lltextbase.cpp129
-rw-r--r--indra/llui/lltextbase.h8
-rw-r--r--indra/llui/lltextbox.cpp4
-rw-r--r--indra/llui/lltexteditor.cpp41
-rw-r--r--indra/llui/lluictrl.cpp29
-rw-r--r--indra/llui/lluictrl.h17
-rw-r--r--indra/llui/lluistring.cpp51
-rw-r--r--indra/llui/lluistring.h32
-rw-r--r--indra/llui/llurlentry.cpp25
-rw-r--r--indra/llui/llurlentry.h11
-rw-r--r--indra/llui/llurlregistry.cpp18
23 files changed, 254 insertions, 171 deletions
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 7721137e29..e9f6288f44 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -63,7 +63,6 @@ template class LLButton* LLView::getChild<class LLButton>(
// globals loaded from settings.xml
S32 LLBUTTON_H_PAD = 0;
-S32 LLBUTTON_V_PAD = 0;
S32 BTN_HEIGHT_SMALL= 0;
S32 BTN_HEIGHT = 0;
@@ -93,6 +92,7 @@ LLButton::Params::Params()
flash_color("flash_color"),
pad_right("pad_right", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")),
pad_left("pad_left", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")),
+ pad_bottom("pad_bottom"),
click_callback("click_callback"),
mouse_down_callback("mouse_down_callback"),
mouse_up_callback("mouse_up_callback"),
@@ -148,6 +148,7 @@ LLButton::LLButton(const LLButton::Params& p)
mHAlign(p.font_halign),
mLeftHPad(p.pad_left),
mRightHPad(p.pad_right),
+ mBottomVPad(p.pad_bottom),
mHoverGlowStrength(p.hover_glow_amount),
mCommitOnReturn(p.commit_on_return),
mFadeWhenDisabled(FALSE),
@@ -839,7 +840,9 @@ void LLButton::draw()
// LLFontGL::render expects S32 max_chars variable but process in a separate way -1 value.
// Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode.
// Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars.
- mLastDrawCharsCount = mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset),
+ mLastDrawCharsCount = mGLFont->render(label, 0,
+ (F32)x,
+ (F32)(mBottomVPad + y_offset),
label_color % alpha,
mHAlign, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 4c7400220d..5e28b8cdff 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -49,7 +49,6 @@
// PLEASE please use these "constants" when building your own buttons.
// They are loaded from settings.xml at run time.
extern S32 LLBUTTON_H_PAD;
-extern S32 LLBUTTON_V_PAD;
extern S32 BTN_HEIGHT_SMALL;
extern S32 BTN_HEIGHT;
@@ -105,6 +104,7 @@ public:
// layout
Optional<S32> pad_right;
Optional<S32> pad_left;
+ Optional<S32> pad_bottom; // under text label
// callbacks
Optional<CommitCallbackParam> click_callback, // alias -> commit_callback
@@ -310,6 +310,7 @@ private:
LLFontGL::HAlign mHAlign;
S32 mLeftHPad;
S32 mRightHPad;
+ S32 mBottomVPad; // under text label
F32 mHoverGlowStrength;
F32 mCurGlowStrength;
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 46491d8a29..2c339f4a3f 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -83,6 +83,8 @@ public:
virtual void onDockHidden();
virtual void onDockShown();
+ LLDockControl* getDockControl();
+
private:
/**
* Provides unique of dockable floater.
@@ -92,7 +94,6 @@ private:
protected:
void setDockControl(LLDockControl* dockControl);
- LLDockControl* getDockControl();
const LLUIImagePtr& getDockTongue();
private:
diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h
index 30a45bedc7..550955c4c5 100644
--- a/indra/llui/lldockcontrol.h
+++ b/indra/llui/lldockcontrol.h
@@ -76,6 +76,9 @@ public:
// gets a rect that bounds possible positions for a dockable control (EXT-1111)
void getAllowedRect(LLRect& rect);
+ S32 getTongueWidth() { return mDockTongue->getWidth(); }
+ S32 getTongueHeight() { return mDockTongue->getHeight(); }
+
private:
virtual void moveDockable();
private:
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index d9b98b1c28..a93c666648 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -112,6 +112,7 @@ void LLDragHandleTop::setTitle(const std::string& title)
params.font(font);
params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
params.font_shadow(LLFontGL::DROP_SHADOW_SOFT);
+ params.use_ellipses = true;
mTitleBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild( mTitleBox );
}
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 831ac66d06..64a4824a17 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -891,7 +891,13 @@ void LLFlatListView::setNoItemsCommentVisible(bool visible) const
// We have to update child rect here because of issues with rect after reshaping while creating LLTextbox
// It is possible to have invalid LLRect if Flat List is in LLAccordionTab
LLRect comment_rect = getLocalRect();
- comment_rect.stretch(-getBorderWidth());
+
+ // To see comment correctly (EXT - 3244) in mNoItemsCommentTextbox we must get border width
+ // of LLFlatListView (@see getBorderWidth()) and stretch mNoItemsCommentTextbox to this width
+ // But getBorderWidth() returns 0 if LLFlatListView not visible. So we have to get border width
+ // from 'scroll_border'
+ LLViewBorder* scroll_border = getChild<LLViewBorder>("scroll border");
+ comment_rect.stretch(-scroll_border->getBorderWidth());
mNoItemsCommentTextbox->setRect(comment_rect);
}
mNoItemsCommentTextbox->setVisible(visible);
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index fd7b64af02..5fd707fea3 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1649,6 +1649,7 @@ void LLFloater::draw()
}
else
{
+ //FIXME: get rid of this hack
// draw children
LLView* focused_child = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus());
BOOL focused_child_visible = FALSE;
@@ -2703,6 +2704,18 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
output_node, output_params, &default_params);
}
+ // Default floater position to top-left corner of screen
+ // However, some legacy floaters have explicit top or bottom
+ // coordinates set, so respect their wishes.
+ if (!params.rect.top.isProvided() && !params.rect.bottom.isProvided())
+ {
+ params.rect.top.set(0);
+ }
+ if (!params.rect.left.isProvided() && !params.rect.right.isProvided())
+ {
+ params.rect.left.set(0);
+ }
+
setupParams(params, parent);
initFromParams(params);
diff --git a/indra/llui/llhelp.h b/indra/llui/llhelp.h
index 82c3bc385f..938419d374 100644
--- a/indra/llui/llhelp.h
+++ b/indra/llui/llhelp.h
@@ -42,6 +42,8 @@ class LLHelp
virtual std::string defaultTopic() = 0;
// return topic to use before the user logs in
virtual std::string preLoginTopic() = 0;
+ // return topic to use for the top-level help, invoked by F1
+ virtual std::string f1HelpTopic() = 0;
};
#endif // headerguard
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 907f2352a0..fd5c2b7fef 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -761,7 +761,7 @@ void LLMenuItemCallGL::initFromParams(const Params& p)
{
if (p.on_visible.isProvided())
{
- mVisibleSignal.connect(initVisibleCallback(p.on_visible));
+ mVisibleSignal.connect(initEnableCallback(p.on_visible));
}
if (p.on_enable.isProvided())
{
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index cbb9b4d344..61e06f9e5f 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -175,9 +175,7 @@ protected:
// This function appends the character string representation of
// the current accelerator key and mask to the provided string.
void appendAcceleratorString( std::string& st ) const;
-
- void initMenuEnableCallback(const EnableCallbackParam& cb, enable_signal_t& sig);
-
+
protected:
KEY mAcceleratorKey;
MASK mAcceleratorMask;
@@ -249,7 +247,7 @@ public:
{
Optional<EnableCallbackParam > on_enable;
Optional<CommitCallbackParam > on_click;
- Optional<VisibleCallbackParam > on_visible;
+ Optional<EnableCallbackParam > on_visible;
Params()
: on_enable("on_enable"),
on_click("on_click"),
@@ -284,15 +282,10 @@ public:
{
return mEnableSignal.connect(cb);
}
-
- boost::signals2::connection setVisibleCallback( const visible_signal_t::slot_type& cb )
- {
- return mVisibleSignal.connect(cb);
- }
-
+
private:
enable_signal_t mEnableSignal;
- visible_signal_t mVisibleSignal;
+ enable_signal_t mVisibleSignal;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index a8bd5fd5e5..d0986a06d3 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -249,7 +249,6 @@ protected:
LLCallbackMap::map_t mFactoryMap;
CommitCallbackRegistry::ScopedRegistrar mCommitCallbackRegistrar;
EnableCallbackRegistry::ScopedRegistrar mEnableCallbackRegistrar;
- VisibleCallbackRegistry::ScopedRegistrar mVisibleCallbackRegistrar;
commit_signal_t* mVisibleSignal; // Called when visibility changes, passes new visibility as LLSD()
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index d7d61cf6cb..2d9106923e 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -906,7 +906,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
if (placeholder)
{
- btn_rect.translate(0, -LLBUTTON_V_PAD-2);
+ btn_rect.translate(0, -3); // *TODO: make configurable
LLTextBox::Params params;
params.name(trimmed_label);
params.rect(btn_rect);
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 2a9515171a..1f120a1483 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -312,7 +312,7 @@ void LLTextBase::drawSelectionBackground()
S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
- LLRect selection_rect = mTextRect;
+ LLRect selection_rect = mVisibleTextRect;
// Skip through the lines we aren't drawing.
LLRect content_display_rect = getVisibleDocumentRect();
@@ -391,7 +391,7 @@ void LLTextBase::drawSelectionBackground()
++rect_it)
{
LLRect selection_rect = *rect_it;
- selection_rect.translate(mTextRect.mLeft - content_display_rect.mLeft, mTextRect.mBottom - content_display_rect.mBottom);
+ selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom);
gl_rect_2d(selection_rect, selection_color);
}
}
@@ -538,10 +538,10 @@ void LLTextBase::drawText()
line_end = next_start;
}
- LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft,
- line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom,
+ LLRect text_rect(line.mRect.mLeft + mVisibleTextRect.mLeft - scrolled_view_rect.mLeft,
+ line.mRect.mTop - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom,
llmin(mDocumentView->getRect().getWidth(), line.mRect.mRight) - scrolled_view_rect.mLeft,
- line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom);
+ line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom);
// draw a single line of text
S32 seg_start = line_start;
@@ -561,14 +561,14 @@ void LLTextBase::drawText()
S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart();
- if (mUseEllipses
- && clipped_end == line_end
- && next_line == last_line
- && last_line < (S32)mLineInfoList.size())
+ if (mUseEllipses // using ellipses
+ && clipped_end == line_end // last segment on line
+ && next_line == last_line // this is the last visible line
+ && last_line < (S32)mLineInfoList.size()) // and there is more text to display
{
- // more text to go, but we can't fit it
- // so attempt to draw one extra character to force ellipses
- clipped_end++;
+ // more lines of text to go, but we can't fit them
+ // so shrink text rect to force ellipses
+ text_rect.mRight -= 2;
}
text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect));
@@ -949,7 +949,7 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
LLUICtrl::reshape( width, height, called_from_parent );
// do this first after reshape, because other things depend on
- // up-to-date mTextRect
+ // up-to-date mVisibleTextRect
updateRects();
needsReflow();
@@ -984,7 +984,7 @@ void LLTextBase::draw()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
- gl_rect_2d(mTextRect, bg_color, TRUE);
+ gl_rect_2d(mVisibleTextRect, bg_color, TRUE);
}
// draw document view
@@ -1053,9 +1053,9 @@ S32 LLTextBase::getLeftOffset(S32 width)
case LLFontGL::LEFT:
return mHPad;
case LLFontGL::HCENTER:
- return mHPad + (mTextRect.getWidth() - width - mHPad) / 2;
+ return mHPad + (mVisibleTextRect.getWidth() - width - mHPad) / 2;
case LLFontGL::RIGHT:
- return mTextRect.getWidth() - width;
+ return mVisibleTextRect.getWidth() - width;
default:
return mHPad;
}
@@ -1071,17 +1071,17 @@ void LLTextBase::reflow(S32 start_index)
while(mReflowNeeded)
{
- mReflowNeeded = FALSE;
+ mReflowNeeded = false;
// shrink document to minimum size (visible portion of text widget)
// to force inlined widgets with follows set to shrink
- mDocumentView->setShape(mTextRect);
+ mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight());
bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;
LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos);
- bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible
- old_cursor_rect.translate(-mTextRect.mLeft, -mTextRect.mBottom);
+ bool follow_selection = mVisibleTextRect.overlaps(old_cursor_rect); // cursor is visible
+ old_cursor_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom);
S32 first_line = getFirstVisibleLine();
@@ -1094,15 +1094,15 @@ void LLTextBase::reflow(S32 start_index)
}
LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex);
// subtract off effect of horizontal scrollbar from local position of first char
- first_char_rect.translate(-mTextRect.mLeft, -mTextRect.mBottom);
+ first_char_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom);
S32 cur_top = 0;
segment_set_t::iterator seg_iter = mSegments.begin();
S32 seg_offset = 0;
S32 line_start_index = 0;
- const S32 text_width = mTextRect.getWidth() - mHPad; // reserve room for margin
- S32 remaining_pixels = text_width;
+ const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin
+ S32 remaining_pixels = text_available_width;
LLWString text(getWText());
S32 line_count = 0;
@@ -1142,10 +1142,11 @@ void LLTextBase::reflow(S32 start_index)
S32 last_segment_char_on_line = segment->getStart() + seg_offset;
- S32 text_left = getLeftOffset(text_width - remaining_pixels);
+ S32 text_actual_width = text_available_width - remaining_pixels;
+ S32 text_left = getLeftOffset(text_actual_width);
LLRect line_rect(text_left,
cur_top,
- text_left + (text_width - remaining_pixels),
+ text_left + text_actual_width,
cur_top - line_height);
// if we didn't finish the current segment...
@@ -1160,7 +1161,7 @@ void LLTextBase::reflow(S32 start_index)
line_start_index = segment->getStart() + seg_offset;
cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
- remaining_pixels = text_width;
+ remaining_pixels = text_available_width;
line_height = 0;
}
// ...just consumed last segment..
@@ -1188,7 +1189,7 @@ void LLTextBase::reflow(S32 start_index)
line_start_index = segment->getStart() + seg_offset;
cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
line_height = 0;
- remaining_pixels = text_width;
+ remaining_pixels = text_available_width;
}
++seg_iter;
seg_offset = 0;
@@ -1238,10 +1239,10 @@ void LLTextBase::reflow(S32 start_index)
}
}
-LLRect LLTextBase::getContentsRect()
+LLRect LLTextBase::getTextBoundingRect()
{
reflow();
- return mContentsRect;
+ return mTextBoundingRect;
}
@@ -1760,7 +1761,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round
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 - mTextRect.mBottom + visible_region.mBottom, compare_bottom());
+ line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mVisibleTextRect.mBottom + visible_region.mBottom, compare_bottom());
if (line_iter == mLineInfoList.end())
{
@@ -1768,7 +1769,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round
}
S32 pos = getLength();
- S32 start_x = mTextRect.mLeft + line_iter->mRect.mLeft;
+ S32 start_x = mVisibleTextRect.mLeft + line_iter->mRect.mLeft;
segment_set_t::iterator line_seg_iter;
S32 line_seg_offset;
@@ -1879,7 +1880,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
if (mLineInfoList.empty())
{
// return default height rect in upper left
- local_rect = mTextRect;
+ local_rect = mVisibleTextRect;
local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
return local_rect;
}
@@ -1890,8 +1891,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(mTextRect.mLeft - scrolled_view_rect.mLeft,
- mTextRect.mBottom - scrolled_view_rect.mBottom);
+ local_rect.translate(mVisibleTextRect.mLeft - scrolled_view_rect.mLeft,
+ mVisibleTextRect.mBottom - scrolled_view_rect.mBottom);
return local_rect;
}
@@ -1991,7 +1992,7 @@ void LLTextBase::changeLine( S32 delta )
LLRect visible_region = getVisibleDocumentRect();
- S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mTextRect.mBottom - visible_region.mBottom, TRUE);
+ S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE);
setCursorPos(new_cursor_pos, true);
}
@@ -2067,54 +2068,64 @@ void LLTextBase::updateRects()
{
if (mLineInfoList.empty())
{
- mContentsRect = LLRect(0, mVPad, mHPad, 0);
+ mTextBoundingRect = LLRect(0, mVPad, mHPad, 0);
}
else
{
- mContentsRect = mLineInfoList.begin()->mRect;
+ mTextBoundingRect = mLineInfoList.begin()->mRect;
for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
line_iter != mLineInfoList.end();
++line_iter)
{
- mContentsRect.unionWith(line_iter->mRect);
+ mTextBoundingRect.unionWith(line_iter->mRect);
}
- mContentsRect.mTop += mVPad;
+ mTextBoundingRect.mTop += mVPad;
+ // subtract a pixel off the bottom to deal with rounding errors in measuring font height
+ mTextBoundingRect.mBottom -= 1;
- S32 delta_pos = -mContentsRect.mBottom;
+ S32 delta_pos = -mTextBoundingRect.mBottom;
// move line segments to fit new document rect
for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
{
it->mRect.translate(0, delta_pos);
}
- mContentsRect.translate(0, delta_pos);
+ mTextBoundingRect.translate(0, delta_pos);
}
// update document container dimensions according to text contents
- LLRect doc_rect = mContentsRect;
- // use old mTextRect constraint document to width of viewable region
+ LLRect doc_rect = mTextBoundingRect;
+ // use old mVisibleTextRect constraint document to width of viewable region
doc_rect.mLeft = 0;
- doc_rect.mRight = llmax(mTextRect.getWidth(), mContentsRect.mRight);
+
+ // allow horizontal scrolling?
+ // if so, use entire width of text contents
+ // otherwise, stop at width of mVisibleTextRect
+ doc_rect.mRight = mScroller
+ ? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
+ : mVisibleTextRect.getWidth();
mDocumentView->setShape(doc_rect);
- //update mTextRect *after* mDocumentView has been resized
+ //update mVisibleTextRect *after* mDocumentView has been resized
// so that scrollbars are added if document needs to scroll
- // since mTextRect does not include scrollbars
- LLRect old_text_rect = mTextRect;
- mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
+ // since mVisibleTextRect does not include scrollbars
+ LLRect old_text_rect = mVisibleTextRect;
+ mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
//FIXME: replace border with image?
if (mBorderVisible)
{
- mTextRect.stretch(-1);
+ mVisibleTextRect.stretch(-1);
}
- if (mTextRect != old_text_rect)
+ if (mVisibleTextRect != old_text_rect)
{
needsReflow();
}
- // update document container again, using new mTextRect
- doc_rect.mRight = llmax(mTextRect.getWidth(), mContentsRect.mRight);
+ // update document container again, using new mVisibleTextRect (that has scrollbars enabled as needed)
+ doc_rect.mRight = mScroller
+ ? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
+ : mVisibleTextRect.getWidth();
mDocumentView->setShape(doc_rect);
}
@@ -2152,7 +2163,7 @@ LLRect LLTextBase::getVisibleDocumentRect() const
LLRect doc_rect = mDocumentView->getLocalRect();
doc_rect.mLeft -= mDocumentView->getRect().mLeft;
// adjust for height of text above widget baseline
- doc_rect.mBottom = doc_rect.getHeight() - mTextRect.getHeight();
+ doc_rect.mBottom = doc_rect.getHeight() - mVisibleTextRect.getHeight();
return doc_rect;
}
}
@@ -2411,10 +2422,18 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
if (num_chars > 0)
{
LLWString text = mEditor.getWText();
- width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
// if last character is a newline, then return true, forcing line break
llwchar last_char = text[mStart + first_char + num_chars - 1];
- force_newline = (last_char == '\n');
+ 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);
+ }
}
else
{
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 0138ca3704..a1f8ba39ae 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -156,8 +156,8 @@ public:
void addDocumentChild(LLView* view);
void removeDocumentChild(LLView* view);
const LLView* getDocumentView() const { return mDocumentView; }
- LLRect getTextRect() { return mTextRect; }
- LLRect getContentsRect();
+ LLRect getVisibleTextRect() { return mVisibleTextRect; }
+ LLRect getTextBoundingRect();
LLRect getVisibleDocumentRect() const;
S32 getVPad() { return mVPad; }
@@ -311,8 +311,8 @@ protected:
// text segmentation and flow
segment_set_t mSegments;
line_list_t mLineInfoList;
- LLRect mTextRect; // The rect in which text is drawn. Excludes borders.
- LLRect mContentsRect;
+ LLRect mVisibleTextRect; // The rect in which text is drawn. Excludes borders.
+ LLRect mTextBoundingRect;
// colors
LLUIColor mCursorColor;
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 0bd0ab59fb..a1f5b5726b 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -134,12 +134,12 @@ void LLTextBox::setClickedCallback( boost::function<void (void*)> cb, void* user
S32 LLTextBox::getTextPixelWidth()
{
- return getContentsRect().getWidth();
+ return getTextBoundingRect().getWidth();
}
S32 LLTextBox::getTextPixelHeight()
{
- return getContentsRect().getHeight();
+ return getTextBoundingRect().getHeight();
}
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index e68affc36c..e8fc9475a5 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -758,8 +758,8 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
{
mScroller->autoScroll(x, y);
}
- S32 clamped_x = llclamp(x, mTextRect.mLeft, mTextRect.mRight);
- S32 clamped_y = llclamp(y, mTextRect.mBottom, mTextRect.mTop);
+ S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
+ S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
setCursorAtLocalPos( clamped_x, clamped_y, true );
mSelectionEnd = mCursorPos;
}
@@ -809,8 +809,8 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
{
mScroller->autoScroll(x, y);
}
- S32 clamped_x = llclamp(x, mTextRect.mLeft, mTextRect.mRight);
- S32 clamped_y = llclamp(y, mTextRect.mBottom, mTextRect.mTop);
+ S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
+ S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
setCursorAtLocalPos( clamped_x, clamped_y, true );
endSelection();
}
@@ -1887,9 +1887,10 @@ void LLTextEditor::doDelete()
removeChar();
}
- onKeyStroke();
}
+ onKeyStroke();
+
needsReflow();
}
@@ -2074,8 +2075,8 @@ void LLTextEditor::drawPreeditMarker()
const S32 line_height = llround( mDefaultFont->getLineHeight() );
S32 line_start = getLineStart(cur_line);
- S32 line_y = mTextRect.mTop - line_height;
- while((mTextRect.mBottom <= line_y) && (num_lines > cur_line))
+ S32 line_y = mVisibleTextRect.mTop - line_height;
+ while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line))
{
S32 next_start = -1;
S32 line_end = text_len;
@@ -2107,12 +2108,12 @@ void LLTextEditor::drawPreeditMarker()
continue;
}
- S32 preedit_left = mTextRect.mLeft;
+ S32 preedit_left = mVisibleTextRect.mLeft;
if (left > line_start)
{
preedit_left += mDefaultFont->getWidth(text, line_start, left - line_start);
}
- S32 preedit_right = mTextRect.mLeft;
+ S32 preedit_right = mVisibleTextRect.mLeft;
if (right < line_end)
{
preedit_right += mDefaultFont->getWidth(text, line_start, right - line_start);
@@ -2153,7 +2154,7 @@ void LLTextEditor::drawLineNumbers()
{
LLGLSUIDefault gls_ui;
LLRect scrolled_view_rect = getVisibleDocumentRect();
- LLRect content_rect = getTextRect();
+ LLRect content_rect = getVisibleTextRect();
LLLocalClipRect clip(content_rect);
S32 first_line = getFirstVisibleLine();
S32 num_lines = getLineCount();
@@ -2179,12 +2180,12 @@ void LLTextEditor::drawLineNumbers()
{
line_info& line = mLineInfoList[cur_line];
- if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom)
+ if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mVisibleTextRect.mBottom)
{
break;
}
- S32 line_bottom = line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom;
+ S32 line_bottom = line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom;
// draw the line numbers
if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop)
{
@@ -2215,8 +2216,8 @@ void LLTextEditor::draw()
{
{
// pad clipping rectangle so that cursor can draw at full width
- // when at left edge of mTextRect
- LLRect clip_rect(mTextRect);
+ // when at left edge of mVisibleTextRect
+ LLRect clip_rect(mVisibleTextRect);
clip_rect.stretch(1);
LLLocalClipRect clip(clip_rect);
drawPreeditMarker();
@@ -2780,7 +2781,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
if (control)
{
LLRect control_rect_screen;
- localRectToScreen(mTextRect, &control_rect_screen);
+ localRectToScreen(mVisibleTextRect, &control_rect_screen);
LLUI::screenRectToGL(control_rect_screen, control);
}
@@ -2831,8 +2832,8 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
if (coord)
{
- const S32 query_x = mTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start);
- const S32 query_y = mTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
+ const S32 query_x = mVisibleTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start);
+ const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
S32 query_screen_x, query_screen_y;
localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y);
LLUI::screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY);
@@ -2840,13 +2841,13 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
if (bounds)
{
- S32 preedit_left = mTextRect.mLeft;
+ S32 preedit_left = mVisibleTextRect.mLeft;
if (preedit_left_position > current_line_start)
{
preedit_left += mDefaultFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);
}
- S32 preedit_right = mTextRect.mLeft;
+ S32 preedit_right = mVisibleTextRect.mLeft;
if (preedit_right_position < current_line_end)
{
preedit_right += mDefaultFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);
@@ -2856,7 +2857,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
preedit_right += mDefaultFont->getWidth(text, current_line_start, current_line_end - current_line_start);
}
- const S32 preedit_top = mTextRect.mTop - (current_line - first_visible_line) * line_height;
+ const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height;
const S32 preedit_bottom = preedit_top - line_height;
const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom);
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 706712ec5e..6044908ca7 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -232,11 +232,6 @@ bool default_enable_handler(LLUICtrl* ctrl, const LLSD& param)
return true;
}
-bool default_visible_handler(LLUICtrl* ctrl, const LLSD& param)
-{
- return true;
-}
-
LLUICtrl::commit_signal_t::slot_type LLUICtrl::initCommitCallback(const CommitCallbackParam& cb)
{
@@ -290,30 +285,6 @@ LLUICtrl::enable_signal_t::slot_type LLUICtrl::initEnableCallback(const EnableCa
return default_enable_handler;
}
-LLUICtrl::visible_signal_t::slot_type LLUICtrl::initVisibleCallback(const VisibleCallbackParam& cb)
-{
- // Set the callback function
- if (cb.function.isProvided())
- {
- if (cb.parameter.isProvided())
- return boost::bind(cb.function(), this, cb.parameter);
- else
- return cb.function();
- }
- else
- {
- visible_callback_t* func = (VisibleCallbackRegistry::getValue(cb.function_name));
- if (func)
- {
- if (cb.parameter.isProvided())
- return boost::bind((*func), this, cb.parameter);
- else
- return visible_signal_t::slot_type(*func);
- }
- }
- return default_visible_handler;
-}
-
// virtual
void LLUICtrl::onMouseEnter(S32 x, S32 y, MASK mask)
{
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index b20ff5d798..b9a4f61e15 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -63,9 +63,6 @@ public:
typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> enable_callback_t;
typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t;
- typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> visible_callback_t;
- typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> visible_signal_t;
-
struct CallbackParam : public LLInitParam::Block<CallbackParam>
{
Ignored name;
@@ -83,16 +80,12 @@ public:
Optional<commit_callback_t> function;
};
+ // also used for visible callbacks
struct EnableCallbackParam : public LLInitParam::Block<EnableCallbackParam, CallbackParam >
{
Optional<enable_callback_t> function;
};
-
- struct VisibleCallbackParam : public LLInitParam::Block<VisibleCallbackParam, CallbackParam >
- {
- Optional<visible_callback_t> function;
- };
-
+
struct EnableControls : public LLInitParam::Choice<EnableControls>
{
Alternative<std::string> enabled;
@@ -148,7 +141,6 @@ protected:
commit_signal_t::slot_type initCommitCallback(const CommitCallbackParam& cb);
enable_signal_t::slot_type initEnableCallback(const EnableCallbackParam& cb);
- visible_signal_t::slot_type initVisibleCallback(const VisibleCallbackParam& cb);
// We need this virtual so we can override it with derived versions
virtual LLViewModel* getViewModel() const;
@@ -269,10 +261,9 @@ public:
{};
class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>{};
+ // the enable callback registry is also used for visiblity callbacks
class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>{};
- class VisibleCallbackRegistry : public CallbackRegistry<visible_callback_t, VisibleCallbackRegistry>{};
-
-
+
protected:
static bool controlListener(const LLSD& newvalue, LLHandle<LLUICtrl> handle, std::string type);
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index 3a1e656364..f7a53e87de 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -39,22 +39,23 @@ LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");
LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args)
- : mOrig(instring),
- mArgs(args)
+: mOrig(instring),
+ mArgs(args)
{
- format();
+ dirty();
}
void LLUIString::assign(const std::string& s)
{
mOrig = s;
- format();
+ dirty();
}
void LLUIString::setArgList(const LLStringUtil::format_map_t& args)
+
{
mArgs = args;
- format();
+ dirty();
}
void LLUIString::setArgs(const LLSD& sd)
@@ -68,40 +69,40 @@ void LLUIString::setArgs(const LLSD& sd)
{
setArg(sd_it->first, sd_it->second.asString());
}
- format();
+ dirty();
}
void LLUIString::setArg(const std::string& key, const std::string& replacement)
{
mArgs[key] = replacement;
- format();
+ dirty();
}
void LLUIString::truncate(S32 maxchars)
{
- if (mWResult.size() > (size_t)maxchars)
+ if (getUpdatedWResult().size() > (size_t)maxchars)
{
- LLWStringUtil::truncate(mWResult, maxchars);
- mResult = wstring_to_utf8str(mWResult);
+ LLWStringUtil::truncate(getUpdatedWResult(), maxchars);
+ mResult = wstring_to_utf8str(getUpdatedWResult());
}
}
void LLUIString::erase(S32 charidx, S32 len)
{
- mWResult.erase(charidx, len);
- mResult = wstring_to_utf8str(mWResult);
+ getUpdatedWResult().erase(charidx, len);
+ mResult = wstring_to_utf8str(getUpdatedWResult());
}
void LLUIString::insert(S32 charidx, const LLWString& wchars)
{
- mWResult.insert(charidx, wchars);
- mResult = wstring_to_utf8str(mWResult);
+ getUpdatedWResult().insert(charidx, wchars);
+ mResult = wstring_to_utf8str(getUpdatedWResult());
}
void LLUIString::replace(S32 charidx, llwchar wc)
{
- mWResult[charidx] = wc;
- mResult = wstring_to_utf8str(mWResult);
+ getUpdatedWResult()[charidx] = wc;
+ mResult = wstring_to_utf8str(getUpdatedWResult());
}
void LLUIString::clear()
@@ -112,8 +113,16 @@ void LLUIString::clear()
mWResult.clear();
}
-void LLUIString::format()
+void LLUIString::dirty()
{
+ mNeedsResult = true;
+ mNeedsWResult = true;
+}
+
+void LLUIString::updateResult() const
+{
+ mNeedsResult = false;
+
LLFastTimer timer(FTM_UI_STRING);
// optimize for empty strings (don't attempt string replacement)
@@ -129,5 +138,11 @@ void LLUIString::format()
LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs();
combined_args.insert(mArgs.begin(), mArgs.end());
LLStringUtil::format(mResult, combined_args);
- mWResult = utf8str_to_wstring(mResult);
+}
+
+void LLUIString::updateWResult() const
+{
+ mNeedsWResult = false;
+
+ mWResult = utf8str_to_wstring(getUpdatedResult());
}
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index 763de4d6a3..7ec0fd603a 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -76,19 +76,19 @@ public:
void setArgs(const class LLSD& sd);
void setArg(const std::string& key, const std::string& replacement);
- const std::string& getString() const { return mResult; }
- operator std::string() const { return mResult; }
+ const std::string& getString() const { return getUpdatedResult(); }
+ operator std::string() const { return getUpdatedResult(); }
- const LLWString& getWString() const { return mWResult; }
- operator LLWString() const { return mWResult; }
+ const LLWString& getWString() const { return getUpdatedWResult(); }
+ operator LLWString() const { return getUpdatedWResult(); }
- bool empty() const { return mWResult.empty(); }
- S32 length() const { return mWResult.size(); }
+ bool empty() const { return getUpdatedResult().empty(); }
+ S32 length() const { return getUpdatedWResult().size(); }
void clear();
void clearArgs() { mArgs.clear(); }
- // These utuilty functions are included for text editing.
+ // These utility functions are included for text editing.
// They do not affect mOrig and do not perform argument substitution
void truncate(S32 maxchars);
void erase(S32 charidx, S32 len);
@@ -96,12 +96,24 @@ public:
void replace(S32 charidx, llwchar wc);
private:
- void format();
+ // something changed, requiring reformatting of strings
+ void dirty();
+
+ std::string& getUpdatedResult() const { if (mNeedsResult) { updateResult(); } return mResult; }
+ LLWString& getUpdatedWResult() const{ if (mNeedsWResult) { updateWResult(); } return mWResult; }
+
+ // do actual work of updating strings (non-inlined)
+ void updateResult() const;
+ void updateWResult() const;
std::string mOrig;
- std::string mResult;
- LLWString mWResult; // for displaying
+ mutable std::string mResult;
+ mutable LLWString mWResult; // for displaying
LLStringUtil::format_map_t mArgs;
+
+ // controls lazy evaluation
+ mutable bool mNeedsResult;
+ mutable bool mNeedsWResult;
};
#endif // LL_LLUISTRING_H
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 7694d02837..7350457274 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -197,6 +197,31 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)
}
//
+// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
+//
+LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()
+{
+ mPattern = boost::regex("(\\bwww\\.\\S+\\.\\S+|\\S+.com\\S*|\\S+.net\\S*|\\S+.edu\\S*|\\S+.org\\S*)",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_http.xml";
+ mTooltip = LLTrans::getString("TooltipHttpUrl");
+}
+
+std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string)
+{
+ if (string.find("://") == std::string::npos)
+ {
+ return "http://" + escapeUrl(string);
+ }
+ return escapeUrl(string);
+}
+
+//
// LLUrlEntrySLURL Describes generic http: and https: Urls
//
LLUrlEntrySLURL::LLUrlEntrySLURL()
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index b3fb333fdd..4adffde99c 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -135,6 +135,17 @@ public:
};
///
+/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
+///
+class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryHTTPNoProtocol();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getUrl(const std::string &string);
+};
+
+///
/// LLUrlEntrySLURL Describes http://slurl.com/... Urls
///
class LLUrlEntrySLURL : public LLUrlEntryBase
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index f47db2db1a..afcff0d409 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -58,6 +58,9 @@ LLUrlRegistry::LLUrlRegistry()
//so it should be registered in the end of list
registerUrl(new LLUrlEntrySL());
registerUrl(new LLUrlEntrySLLabel());
+ // most common pattern is a URL without any protocol,
+ // e.g., "secondlife.com"
+ registerUrl(new LLUrlEntryHTTPNoProtocol());
}
LLUrlRegistry::~LLUrlRegistry()
@@ -118,10 +121,23 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en
return true;
}
+static bool stringHasUrl(const std::string &text)
+{
+ // fast heuristic test for a URL in a string. This is used
+ // to avoid lots of costly regex calls, BUT it needs to be
+ // kept in sync with the LLUrlEntry regexes we support.
+ return (text.find("://") != std::string::npos ||
+ text.find("www.") != std::string::npos ||
+ text.find(".com") != std::string::npos ||
+ text.find(".net") != std::string::npos ||
+ text.find(".edu") != std::string::npos ||
+ text.find(".org") != std::string::npos);
+}
+
bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
{
// avoid costly regexes if there is clearly no URL in the text
- if (text.find("://") == std::string::npos)
+ if (! stringHasUrl(text))
{
return false;
}