From 8ef99c38a5b7d10d3a121f70929d6e26b264dddb Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Wed, 4 Jan 2017 18:38:52 +0200
Subject: MAINT-918 Newline was not displayed correctly in chat window.

---
 indra/llui/lltextbase.cpp             | 46 +++++++++++++++++++++++++----------
 indra/llui/lltextbase.h               | 22 +++++++++++++----
 indra/newview/llexpandabletextbox.cpp |  4 +--
 indra/newview/llviewertexteditor.cpp  |  2 +-
 4 files changed, 53 insertions(+), 21 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 20be739286..88a5c3a587 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1522,6 +1522,7 @@ void LLTextBase::reflow()
 		}
 
 		S32 line_height = 0;
+		S32 seg_line_offset = line_count;
 
 		while(seg_iter != mSegments.end())
 		{
@@ -1534,7 +1535,8 @@ void LLTextBase::reflow()
 			S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX,
 														seg_offset, 
 														cur_index - line_start_index, 
-														S32_MAX);
+														S32_MAX,
+														line_count - seg_line_offset);
 
 			S32 segment_width, segment_height;
 			bool force_newline = segment->getDimensions(seg_offset, character_count, segment_width, segment_height);
@@ -1597,6 +1599,7 @@ void LLTextBase::reflow()
 				}
 				++seg_iter;
 				seg_offset = 0;
+				seg_line_offset = force_newline ? line_count + 1 : line_count;
 			}
 			if (force_newline) 
 			{
@@ -3065,7 +3068,7 @@ LLTextSegment::~LLTextSegment()
 
 bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { width = 0; height = 0; return false;}
 S32	LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; }
-S32	LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return 0; }
+S32	LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const { return 0; }
 void LLTextSegment::updateLayout(const LLTextBase& editor) {}
 F32	LLTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect) { return draw_rect.mLeft; }
 bool LLTextSegment::canEdit() const { return false; }
@@ -3335,7 +3338,7 @@ S32	LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset,
 											   round);
 }
 
-S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const
 {
 	const LLWString &text = getWText();
 
@@ -3352,7 +3355,7 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
 
 	// if no character yet displayed on this line, don't require word wrapping since
 	// we can just move to the next line, otherwise insist on it so we make forward progress
-	LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0) 
+	LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0)
 		? LLFontGL::WORD_BOUNDARY_IF_POSSIBLE 
 		: LLFontGL::ONLY_WORD_BOUNDARIES;
 	
@@ -3490,12 +3493,26 @@ LLInlineViewSegment::~LLInlineViewSegment()
 
 bool LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
 {
-	if (first_char == 0 && num_chars == 0) 
+	if (first_char == 0 && num_chars == 0)
 	{
-		// we didn't fit on a line, the widget will fall on the next line
-		// so dimensions here are 0
+		// We didn't fit on a line or were forced to new string
+		// the widget will fall on the next line, so width here is 0
 		width = 0;
-		height = 0;
+
+		if (mForceNewLine)
+		{
+			// Chat, string can't be smaller then font height even if it is empty
+			LLStyleSP s(new LLStyle(LLStyle::Params().visible(true)));
+			height = s->getFont()->getLineHeight();
+
+			return true; // new line
+		}
+		else
+		{
+			// height from previous segment in same string will be used, word-wrap
+			height = 0;
+		}
+
 	}
 	else
 	{
@@ -3506,13 +3523,16 @@ bool LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
 	return false;
 }
 
-S32	LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+S32	LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const
 {
 	// if putting a widget anywhere but at the beginning of a line
 	// and the widget doesn't fit or mForceNewLine is true
 	// then return 0 chars for that line, and all characters for the next
-	if (line_offset != 0 
-		&& (mForceNewLine || num_pixels < mView->getRect().getWidth())) 
+	if (mForceNewLine && line_ind == 0)
+	{
+		return 0;
+	}
+	else if (line_offset != 0 && num_pixels < mView->getRect().getWidth())
 	{
 		return 0;
 	}
@@ -3565,7 +3585,7 @@ bool LLLineBreakTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& w
 
 	return true;
 }
-S32	LLLineBreakTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+S32	LLLineBreakTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const
 {
 	return 1;
 }
@@ -3601,7 +3621,7 @@ bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width
 	return false;
 }
 
-S32	 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+S32	 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const
 {
 	LLUIImagePtr image = mStyle->getImage();
 	
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 3d3a6ca869..c7b6203445 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -64,7 +64,19 @@ public:
 
 	virtual bool				getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
 	virtual S32					getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
-	virtual S32					getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+
+	/**
+	* Get number of chars that fit into free part of current line.
+	*
+	* @param num_pixels - maximum width of rect
+	* @param segment_offset - symbol in segment we start processing line from
+	* @param line_offset - symbol in line after which segment starts
+	* @param max_chars - limit of symbols that will fit in current line
+	* @param line_ind - index of not word-wrapped string inside segment for multi-line segments.
+	* Two string separated by word-wrap will have same index.
+	* @return number of chars that will fit into current line
+	*/
+	virtual S32					getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
 	virtual void				updateLayout(const class LLTextBase& editor);
 	virtual F32					draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
 	virtual bool				canEdit() const;
@@ -116,7 +128,7 @@ public:
 
 	/*virtual*/ bool				getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
 	/*virtual*/ S32					getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
-	/*virtual*/ S32					getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+	/*virtual*/ S32					getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
 	/*virtual*/ F32					draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
 	/*virtual*/ bool				canEdit() const { return true; }
 	/*virtual*/ const LLColor4&		getColor() const					{ return mStyle->getColor(); }
@@ -201,7 +213,7 @@ public:
 	LLInlineViewSegment(const Params& p, S32 start, S32 end);
 	~LLInlineViewSegment();
 	/*virtual*/ bool		getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
-	/*virtual*/ S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+	/*virtual*/ S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
 	/*virtual*/ void		updateLayout(const class LLTextBase& editor);
 	/*virtual*/ F32			draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
 	/*virtual*/ bool		canEdit() const { return false; }
@@ -225,7 +237,7 @@ public:
 	LLLineBreakTextSegment(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;
+	S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
 	F32			draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
 
 private:
@@ -238,7 +250,7 @@ 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;
+	S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 char_offset, S32 max_chars, S32 line_ind) const;
 	F32			draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
 
 	/*virtual*/ BOOL	handleToolTip(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index f0331f20d8..314b859cea 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -63,10 +63,10 @@ public:
 	{ 
 		return start_offset;
 	}
-	/*virtual*/ S32		getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const 
+	/*virtual*/ S32		getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const
 	{ 
 		// require full line to ourselves
-		if (line_offset == 0) 
+		if (line_offset == 0)
 		{
 			// print all our text
 			return getEnd() - getStart(); 
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 7323a5b2f3..9e09971ced 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -191,7 +191,7 @@ public:
 		return false;
 	}
 
-	/*virtual*/ S32				getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const 
+	/*virtual*/ S32				getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const
 	{
 		// always draw at beginning of line
 		if (line_offset == 0)
-- 
cgit v1.2.3