diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp
index 2dbc368d98933b668d4f96ff497c474284be3abe..d85006fa9cf912b69486c223bbb533231a4abaf3 100644
--- a/indra/llmath/v3color.cpp
+++ b/indra/llmath/v3color.cpp
@@ -42,3 +42,52 @@ std::ostream& operator<<(std::ostream& s, const LLColor3 &a)
 	s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }";
 	return s;
 }
+
+void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const
+{
+	F32 var_R = mV[VRED];
+	F32 var_G = mV[VGREEN];
+	F32 var_B = mV[VBLUE];
+
+	F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
+	F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
+
+	F32 del_Max = var_Max - var_Min;
+
+	F32 L = ( var_Max + var_Min ) / 2.0f;
+	F32 H = 0.0f;
+	F32 S = 0.0f;
+
+	if ( del_Max == 0.0f )
+	{
+	   H = 0.0f;
+	   S = 0.0f;
+	}
+	else
+	{
+		if ( L < 0.5 )
+			S = del_Max / ( var_Max + var_Min );
+		else
+			S = del_Max / ( 2.0f - var_Max - var_Min );
+
+		F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+		F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+		F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+
+		if ( var_R >= var_Max )
+			H = del_B - del_G;
+		else
+		if ( var_G >= var_Max )
+			H = ( 1.0f / 3.0f ) + del_R - del_B;
+		else
+		if ( var_B >= var_Max )
+			H = ( 2.0f / 3.0f ) + del_G - del_R;
+
+		if ( H < 0.0f ) H += 1.0f;
+		if ( H > 1.0f ) H -= 1.0f;
+	}
+
+	if (hue) *hue = H;
+	if (saturation) *saturation = S;
+	if (luminance) *luminance = L;
+}
\ No newline at end of file
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index 956cca614dcbf8e8c3e44de0bf248e54bab04d7c..779fda436e4917128ea619ba64227ee01c9da237 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -52,6 +52,8 @@ class LLColor3
 		mV[1] = (F32) sd[1].asReal();;
 		mV[2] = (F32) sd[2].asReal();;
 	}
+
+	void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
 	
 	const LLColor3&	setToBlack();					// Clears LLColor3 to (0, 0, 0)
 	const LLColor3&	setToWhite();					// Zero LLColor3 to (0, 0, 0)
diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp
index 83870941dffff12c991e1c89ca9f2b78cca451db..4e2287eee2198f9afc5020414b4b6591129c0a05 100644
--- a/indra/llmath/v4color.cpp
+++ b/indra/llmath/v4color.cpp
@@ -205,6 +205,55 @@ LLColor4	vec3to4(const LLColor3 &vec)
 	return temp;
 }
 
+void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const
+{
+	F32 var_R = mV[VRED];
+	F32 var_G = mV[VGREEN];
+	F32 var_B = mV[VBLUE];
+
+	F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
+	F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
+
+	F32 del_Max = var_Max - var_Min;
+
+	F32 L = ( var_Max + var_Min ) / 2.0f;
+	F32 H = 0.0f;
+	F32 S = 0.0f;
+
+	if ( del_Max == 0.0f )
+	{
+	   H = 0.0f;
+	   S = 0.0f;
+	}
+	else
+	{
+		if ( L < 0.5 )
+			S = del_Max / ( var_Max + var_Min );
+		else
+			S = del_Max / ( 2.0f - var_Max - var_Min );
+
+		F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+		F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+		F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+
+		if ( var_R >= var_Max )
+			H = del_B - del_G;
+		else
+		if ( var_G >= var_Max )
+			H = ( 1.0f / 3.0f ) + del_R - del_B;
+		else
+		if ( var_B >= var_Max )
+			H = ( 2.0f / 3.0f ) + del_G - del_R;
+
+		if ( H < 0.0f ) H += 1.0f;
+		if ( H > 1.0f ) H -= 1.0f;
+	}
+
+	if (hue) *hue = H;
+	if (saturation) *saturation = S;
+	if (luminance) *luminance = L;
+}
+
 // static
 BOOL LLColor4::parseColor(const char* buf, LLColor4* color)
 {
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 8fe5846e26f96576cde37964c136831ff8438705..ef9c5d476940b800c29136932cb47f0bdb609bcd 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -54,6 +54,8 @@ class LLColor4
 			mV[3] = (F32) sd[3].asReal();
 		}
 
+		void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
+
 		const LLColor4&	setToBlack();						// zero LLColor4 to (0, 0, 0, 1)
 		const LLColor4&	setToWhite();						// zero LLColor4 to (0, 0, 0, 1)
 
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index b85a0b65e6b47b6c6a9cf4db8d8d233c8787892d..94a8eb822d8e428b9f9499be799e086fa74d79c9 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -50,6 +50,7 @@ const F32 PIXEL_BORDER_THRESHOLD = 0.0001f;
 const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
 
 const F32 PAD_AMT = 0.5f;
+const F32 DROP_SHADOW_STRENGTH = 0.3f;
 
 F32 llfont_round_x(F32 x)
 {
@@ -114,7 +115,8 @@ void LLFontGL::init()
 		mImageGLp = new LLImageGL(FALSE);
 		//RN: use nearest mipmap filtering to obviate the need to do pixel-accurate positioning
 		mImageGLp->bind();
-		mImageGLp->setMipFilterNearest(TRUE, TRUE);
+		// we allow bilinear filtering to get sub-pixel positioning for drop shadows
+		//mImageGLp->setMipFilterNearest(TRUE, TRUE);
 	}
 	if (mRawImageGLp.isNull())
 	{
@@ -530,28 +532,8 @@ S32 LLFontGL::render(const LLWString &wstr,
 		return 0;
 	} 
 
-	if (style & DROP_SHADOW)
-	{
-		LLColor4 shadow_color = sShadowColor;
-		shadow_color[3] = color[3];
-		render(wstr, begin_offset,
-				x + 1.f / sScaleX, 
-				y - 1.f / sScaleY,
-				shadow_color,
-				halign, 
-				valign,
-				style & (~DROP_SHADOW),
-				max_chars,
-				max_pixels,
-			   	right_x,
-			   	use_embedded,
-				use_ellipses);
-	}
-
 	S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
 
-	BOOL render_bold = FALSE;
-
 	// HACK for better bolding
 	if (style & BOLD)
 	{
@@ -566,9 +548,17 @@ S32 LLFontGL::render(const LLWString &wstr,
 				max_chars, max_pixels,
 				right_x, use_embedded);
 		}
-		else
+	}
+
+	F32 drop_shadow_strength = 0.f;
+	if (style & DROP_SHADOW)
+	{
+		F32 luminance;
+		color.calcHSL(NULL, NULL, &luminance);
+		drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, DROP_SHADOW_STRENGTH);
+		if (luminance < 0.35f)
 		{
-			render_bold = TRUE;
+			style = style & ~DROP_SHADOW;
 		}
 	}
 
@@ -612,9 +602,6 @@ S32 LLFontGL::render(const LLWString &wstr,
 	}
 
 	F32 cur_x, cur_y, cur_render_x, cur_render_y;
-	F32 slant_offset;
-
-	slant_offset = ((style & ITALIC) ? ( -mAscender * 0.25f) : 0.f);
 
 	// Bind the font texture
 	
@@ -718,34 +705,13 @@ S32 LLFontGL::render(const LLWString &wstr,
 
 			glEnd();
 
-			glColor3f(1.f, 1.f, 1.f);
-
 			ext_image->bind();
 			const F32 ext_x = cur_render_x + (EXT_X_BEARING * sScaleX);
 			const F32 ext_y = cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight);
 
-			glBegin(GL_QUADS);
-			{
-				S32 num_passes = render_bold ? 2 : 1;
-				for (S32 pass = 0; pass < num_passes; pass++)
-				{
-					glTexCoord2f(1.f, 1.f);
-					glVertex2f(llfont_round_x(ext_x + ext_width  + (F32)(pass * BOLD_OFFSET)), 
-								llfont_round_y(ext_y + ext_height));
-
-					glTexCoord2f(0.f, 1.f);
-					glVertex2f(llfont_round_x(ext_x + (F32)(pass * BOLD_OFFSET)), 
-								llfont_round_y(ext_y + ext_height));
-
-					glTexCoord2f(0.f, 0.f);
-					glVertex2f(llfont_round_x(ext_x + (F32)(pass * BOLD_OFFSET)), llfont_round_y(ext_y));
-
-					glTexCoord2f(1.f, 0.f);
-					glVertex2f(llfont_round_x(ext_x + ext_width + (F32)(pass * BOLD_OFFSET)), 
-								llfont_round_y(ext_y));
-				}
-			}
-			glEnd();
+			LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);
+			LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y);
+			drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength);
 
 			if (!label.empty())
 			{
@@ -798,31 +764,21 @@ S32 LLFontGL::render(const LLWString &wstr,
 
 			// Draw the text at the appropriate location
 			//Specify vertices and texture coordinates
-			S32 num_passes = render_bold ? 2 : 1;
-			for (S32 pass = 0; pass < num_passes; pass++)
-			{
-				glTexCoord2f((fgi->mXBitmapOffset - PAD_AMT) * inv_width,
-					(fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height);
-				glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + (F32)(pass * BOLD_OFFSET) - PAD_AMT),
-					llfont_round_y(cur_render_y + (F32)fgi->mYBearing + PAD_AMT));
-				glTexCoord2f((fgi->mXBitmapOffset - PAD_AMT) * inv_width,
-					(fgi->mYBitmapOffset - PAD_AMT) * inv_height);
-				glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + slant_offset + (F32)(pass * BOLD_OFFSET) - PAD_AMT),
-					llfont_round_y(cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT));
-				glTexCoord2f((fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width,
-					(fgi->mYBitmapOffset - PAD_AMT) * inv_height);
-				glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + slant_offset + (F32)fgi->mWidth + (F32)(pass * BOLD_OFFSET) + PAD_AMT),
-					llfont_round_y(cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT));
-				glTexCoord2f((fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width,
-					(fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height);
-				glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + (F32)(pass * BOLD_OFFSET) + PAD_AMT),
-					llfont_round_y(cur_render_y + (F32)fgi->mYBearing + PAD_AMT));
-			}
+			LLRectf uv_rect((fgi->mXBitmapOffset - PAD_AMT) * inv_width,
+							(fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height,
+							(fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width,
+							(fgi->mYBitmapOffset - PAD_AMT) * inv_height);
+			LLRectf screen_rect(cur_render_x + (F32)fgi->mXBearing - PAD_AMT,
+								cur_render_y + (F32)fgi->mYBearing + PAD_AMT,
+								cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + PAD_AMT,
+								cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT);
 
-			chars_drawn++;
+			drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength);
 
+			chars_drawn++;
 			cur_x += fgi->mXAdvance;
 			cur_y += fgi->mYAdvance;
+
 			llwchar next_char = wstr[i+1];
 			if (next_char && (next_char < LAST_CHARACTER))
 			{
@@ -1328,6 +1284,89 @@ void LLFontGL::removeEmbeddedChar( llwchar wc )
 	}
 }
 
+
+void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
+{
+	glTexCoord2f(uv_rect.mRight, uv_rect.mTop);
+	glVertex2f(llfont_round_x(screen_rect.mRight), 
+				llfont_round_y(screen_rect.mTop));
+
+	glTexCoord2f(uv_rect.mLeft, uv_rect.mTop);
+	glVertex2f(llfont_round_x(screen_rect.mLeft), 
+				llfont_round_y(screen_rect.mTop));
+
+	glTexCoord2f(uv_rect.mLeft, uv_rect.mBottom);
+	glVertex2f(llfont_round_x(screen_rect.mLeft + slant_amt), 
+				llfont_round_y(screen_rect.mBottom));
+
+	glTexCoord2f(uv_rect.mRight, uv_rect.mBottom);
+	glVertex2f(llfont_round_x(screen_rect.mRight + slant_amt), 
+				llfont_round_y(screen_rect.mBottom));
+}
+
+void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_strength) const
+{
+	F32 slant_offset;
+	slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f);
+
+	glBegin(GL_QUADS);
+	{
+		//FIXME: bold and drop shadow are mutually exclusive only for convenience
+		//Allow both when we need them.
+		if (style & BOLD)
+		{
+			glColor4fv(color.mV);
+			for (S32 pass = 0; pass < 2; pass++)
+			{
+				LLRectf screen_rect_offset = screen_rect;
+
+				screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
+				renderQuad(screen_rect_offset, uv_rect, slant_offset);
+			}
+		}
+		else if (style & DROP_SHADOW)
+		{
+			LLColor4 shadow_color = LLFontGL::sShadowColor;
+			shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
+			glColor4fv(shadow_color.mV);
+			for (S32 pass = 0; pass < 5; pass++)
+			{
+				LLRectf screen_rect_offset = screen_rect;
+
+				switch(pass)
+				{
+				case 0:
+					screen_rect_offset.translate(-1.f, -1.f);
+					break;
+				case 1:
+					screen_rect_offset.translate(1.f, -1.f);
+					break;
+				case 2:
+					screen_rect_offset.translate(1.f, 1.f);
+					break;
+				case 3:
+					screen_rect_offset.translate(-1.f, 1.f);
+					break;
+				case 4:
+					screen_rect_offset.translate(0, -2.f);
+					break;
+				}
+			
+				renderQuad(screen_rect_offset, uv_rect, slant_offset);
+			}
+			glColor4fv(color.mV);
+			renderQuad(screen_rect, uv_rect, slant_offset);
+		}
+		else // normal rendering
+		{
+			glColor4fv(color.mV);
+			renderQuad(screen_rect, uv_rect, slant_offset);
+		}
+
+	}
+	glEnd();
+}
+
 // static
 LLString LLFontGL::nameFromFont(const LLFontGL* fontp)
 {
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index 789879a5ca8a2cb7e2b86837afd1a6436ddd3bea..75e12f0475f7d53fd59caff4293321b9b8bcc7db 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -14,6 +14,7 @@
 #include "llimagegl.h"
 #include "v2math.h"
 #include "llcoord.h"
+#include "llrect.h"
 
 class LLColor4;
 
@@ -187,6 +188,8 @@ class LLFontGL : public LLFont
 	const embedded_data_t* getEmbeddedCharData(const llwchar wch) const;
 	F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const;
 	void clearEmbeddedChars();
+	void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const;
+	void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_fade) const;
 
 public:
 	static F32 sVertDPI;
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index e439cd0accca0b8a88007eb1547af4c3f633404f..f13e0d54b98c4d532ddff8012477b6fafc9aaf24 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -782,6 +782,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
 			mTextEntry->setCommitOnFocusLost(FALSE);
 			mTextEntry->setText(cur_label);
 			mTextEntry->setIgnoreTab(TRUE);
+			mTextEntry->setFollowsAll();
 			addChild(mTextEntry);
 			mMaxChars = max_chars;
 		}
@@ -789,6 +790,8 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
 		{
 			mTextEntry->setVisible(TRUE);
 		}
+
+		mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
 	}
 	else if (!allow && mAllowTextEntry)
 	{
@@ -799,6 +802,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
 		{
 			mTextEntry->setVisible(FALSE);
 		}
+		mButton->setFollowsAll();
 	}
 	mAllowTextEntry = allow;
 	mTextEntryTentative = set_tentative;	
@@ -834,6 +838,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
 		else
 		{
 			line_editor->setTentative(self->mTextEntryTentative);
+			self->mList->deselectAllItems();
 		}
 		return;
 	}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 1f71de1c8724bb2cc6a380b479d71e9cea0136e1..c3364a7a350b4552e3e867feb5316e031569c249 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -38,6 +38,8 @@ extern BOOL gNoRender;
 
 const S32 MINIMIZED_WIDTH = 160;
 const S32 CLOSE_BOX_FROM_TOP = 1;
+// use this to control "jumping" behavior when Ctrl-Tabbing
+const S32 TABBED_FLOATER_OFFSET = 0;
 
 LLString	LLFloater::sButtonActiveImageNames[BUTTON_COUNT] = 
 {
@@ -2169,32 +2171,27 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
 
 void LLFloaterView::draw()
 {
-	if( getVisible() )
-	{
-		refresh();
-
-		// hide focused floater if in cycle mode, so that it can be drawn on top
-		LLFloater* focused_floater = getFocusedFloater();
-		BOOL floater_visible = FALSE;
-		if (mFocusCycleMode && focused_floater)
-		{
-			floater_visible = focused_floater->getVisible();
-			focused_floater->setVisible(FALSE);
-		}
+	refresh();
 
-		// And actually do the draw
-		LLView::draw();
+	// hide focused floater if in cycle mode, so that it can be drawn on top
+	LLFloater* focused_floater = getFocusedFloater();
 
-		// manually draw focused floater on top when in cycle mode
-		if (mFocusCycleMode && focused_floater)
+	if (mFocusCycleMode && focused_floater)
+	{
+		child_list_const_iter_t child_it = getChildList()->begin();
+		for (;child_it != getChildList()->end(); ++child_it)
 		{
-			// draw focused item on top for better feedback
-			focused_floater->setVisible(floater_visible);
-			if (floater_visible)
+			if ((*child_it) != focused_floater)
 			{
-				drawChild(focused_floater);
+				drawChild(*child_it);
 			}
 		}
+
+		drawChild(focused_floater, -TABBED_FLOATER_OFFSET, TABBED_FLOATER_OFFSET);
+	}
+	else
+	{
+		LLView::draw();
 	}
 }
 
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 98dddfb542039febe65b7551dbd4aa70ae0ff999..f442855aca3c3e13e11d6d0c55c7d52961a5cf81 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -135,6 +135,19 @@ BOOL LLScrollListCheck::handleClick()
 	return TRUE; 
 }
 
+//
+// LLScrollListSeparator
+//
+LLScrollListSeparator::LLScrollListSeparator(S32 width) : mWidth(width)
+{
+}
+
+void LLScrollListSeparator::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const
+{
+	//*FIXME: use dynamic item heights and make separators narrow, and inactive
+	gl_line_2d(5, 8, llmax(5, width - 5), 8, color);
+}
+
 //
 // LLScrollListText
 //
@@ -2750,6 +2763,10 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
 														LLRect(0, 0, width, width), "label");
 			new_item->setColumn(index, new LLScrollListCheck(ctrl,width));
 		}
+		else if (type == "separator")
+		{
+			new_item->setColumn(index, new LLScrollListSeparator(width));
+		}
 		else
 		{
 			new_item->setColumn(index, new LLScrollListText(value.asString(), font, width, font_style, font_alignment));
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 99218ab3c4bbeb87c89f62d9fb202c69daa0a519..7a0a32c87ed59577bc3a4027fa50f033d7ad5c7f 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -48,6 +48,21 @@ class LLScrollListCell
 	virtual	void	setEnabled(BOOL enable) { }
 };
 
+class LLScrollListSeparator : public LLScrollListCell
+{
+public:
+	LLScrollListSeparator(S32 width);
+	virtual ~LLScrollListSeparator() {};
+	virtual void			drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const;		// truncate to given width, if possible
+	virtual S32				getWidth() const {return mWidth;}
+	virtual S32				getHeight() const { return 5; };
+	virtual void			setWidth(S32 width) {mWidth = width; }
+	virtual BOOL			isText() { return FALSE; }
+
+protected:
+	S32 mWidth;
+};
+
 class LLScrollListText : public LLScrollListCell
 {
 public:
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 366b1956c4e047637fd061808ff29af7aa9eea89..651a42174245cb541d880c6551f803923e8e74d0 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -793,6 +793,31 @@ LLWString LLTextEditor::getWSubString(S32 pos, S32 len)
 	return mWText.substr(pos, len);
 }
 
+LLTextSegment*	LLTextEditor::getCurrentSegment()
+{
+	return getSegmentAtOffset(mCursorPos);
+}
+
+LLTextSegment*	LLTextEditor::getPreviousSegment()
+{
+	// find segment index at character to left of cursor (or rightmost edge of selection)
+	S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1);
+	return idx >= 0 ? mSegments[idx] : NULL;
+}
+
+void LLTextEditor::getSelectedSegments(std::vector<LLTextSegment*>& segments)
+{
+	S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
+	S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
+	S32 first_idx = llmax(0, getSegmentIdxAtOffset(left));
+	S32 last_idx = llmax(0, first_idx, getSegmentIdxAtOffset(right));
+
+	for (S32 idx = first_idx; idx <= last_idx; ++idx)
+	{
+		segments.push_back(mSegments[idx]);
+	}
+}
+
 S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round )
 {
 		// If round is true, if the position is on the right half of a character, the cursor
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 21db32b33fe018b6efe6a9358a849b6b1042fa4d..d95230f0dc2ecad5b5930bbb56f919f621849e91 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -221,6 +221,10 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler
 	llwchar			getWChar(S32 pos);
 	LLWString		getWSubString(S32 pos, S32 len);
 	
+	LLTextSegment*	getCurrentSegment();
+	LLTextSegment*  getPreviousSegment();
+	void getSelectedSegments(std::vector<LLTextSegment*>& segments);
+
 protected:
  	S32				getLength() const;
 	void			getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp );
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index 8af0dd410f30c89068ffa538e8339cc357c7d138..c3962bffb825c42af5c8ab3bd28a330c04a43f7d 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -275,59 +275,6 @@ destroyUI ()
 	}
 }
 
-//////////////////////////////////////////////////////////////////////////////
-//
-void
-LLFloaterColorPicker::
-rgbToHsl ( F32 rValIn, F32 gValIn, F32 bValIn, F32& hValOut, F32& sValOut, F32& lValOut )
-{
-	F32 var_R = ( rValIn );
-	F32 var_G = ( gValIn );
-	F32 var_B = ( bValIn );
-
-	F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
-	F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
-
-	F32 del_Max = var_Max - var_Min;
-
-	F32 L = ( var_Max + var_Min ) / 2.0f;
-	F32 H = 0.0f;
-	F32 S = 0.0f;
-
-	if ( del_Max == 0.0f )
-	{
-	   H = 0.0f;
-	   S = 0.0f;
-	}
-	else
-	{
-		if ( L < 0.5 )
-			S = del_Max / ( var_Max + var_Min );
-		else
-			S = del_Max / ( 2.0f - var_Max - var_Min );
-
-		F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
-		F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
-		F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
-
-		if ( var_R >= var_Max )
-			H = del_B - del_G;
-		else
-		if ( var_G >= var_Max )
-			H = ( 1.0f / 3.0f ) + del_R - del_B;
-		else
-		if ( var_B >= var_Max )
-			H = ( 2.0f / 3.0f ) + del_G - del_R;
-
-		if ( H < 0.0f ) H += 1.0f;
-		if ( H > 1.0f ) H -= 1.0f;
-	}
-
-	// scale to meet calculation requirements
-	hValOut = H * 360.0f / 360.0f;
-	sValOut = S * 100.0f / 100.0f;
-	lValOut = L * 100.0f / 100.0f;
-}
 
 //////////////////////////////////////////////////////////////////////////////
 //
@@ -407,7 +354,7 @@ setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
 	curB = curBIn;
 
 	// update corresponding HSL values and
-	rgbToHsl ( curR, curG, curB, curH, curS, curL );
+	LLColor3(curRIn, curGIn, curBIn).calcHSL(&curH, &curS, &curL);
 
 	// color changed so update text fields (fixes SL-16968)
     // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
@@ -706,7 +653,10 @@ getComplimentaryColor ( LLColor4& backgroundColor )
 {
 	// going to base calculation on luminance
 	F32 hVal, sVal, lVal;
-	rgbToHsl ( backgroundColor [ 0 ], backgroundColor [ 1 ], backgroundColor [ 2 ], hVal, sVal, lVal );
+	backgroundColor.calcHSL(&hVal, &sVal, &lVal);
+	hVal *= 360.f;
+	sVal *= 100.f;
+	lVal *= 100.f;
 
 	// fairly simple heuristic for now...!
 	if ( lVal < 0.5f )
diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h
index 7660aa8c2db837a1b71249a95e0666292e5d46f6..2a93c26501e1145e60b48e2e6d06096f12556162 100644
--- a/indra/newview/llfloatercolorpicker.h
+++ b/indra/newview/llfloatercolorpicker.h
@@ -91,7 +91,6 @@ class LLFloaterColorPicker
 
 		// convert RGB to HSL and vice-versa
 		void hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut );
-		void rgbToHsl ( F32 rValIn, F32 gValIn, F32 bValIn, F32& hValOut, F32& sValOut, F32& lValOut );
 		F32	 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn );
 
 		void setActive(BOOL active);
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 97b4a982d25c6e4fa306b3c1a8a6d4d860758ad3..6a9965dbfb17b942a5d996aca377b2bedca512db 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -57,6 +57,7 @@
 #include "llviewertexteditor.h"
 #include "llviewerwindow.h"
 #include "llvieweruictrlfactory.h"
+#include "llwebbrowserctrl.h"
 #include "lluictrlfactory.h"
 
 #include "viewer.h"
@@ -115,6 +116,9 @@ const S32 SCRIPT_SEARCH_HEIGHT = 120;
 const S32 SCRIPT_SEARCH_LABEL_WIDTH = 50;
 const S32 SCRIPT_SEARCH_BUTTON_WIDTH = 80;
 const S32 TEXT_EDIT_COLUMN_HEIGHT = 16;
+const S32 MAX_HISTORY_COUNT = 10;
+const F32 LIVE_HELP_REFRESH_TIME = 1.f;
+
 /// ---------------------------------------------------------------------------
 /// LLFloaterScriptSearch
 /// ---------------------------------------------------------------------------
@@ -254,6 +258,7 @@ void LLFloaterScriptSearch::open()		/*Flawfinder: ignore*/
 	LLFloater::open();		/*Flawfinder: ignore*/
 	childSetFocus("search_text", TRUE); 
 }
+
 /// ---------------------------------------------------------------------------
 /// LLScriptEdCore
 /// ---------------------------------------------------------------------------
@@ -276,7 +281,9 @@ LLScriptEdCore::LLScriptEdCore(
 	mLoadCallback( load_callback ),
 	mSaveCallback( save_callback ),
 	mUserdata( userdata ),
-	mForceClose( FALSE )
+	mForceClose( FALSE ),
+	mLastHelpToken(NULL),
+	mLiveHelpHistorySize(0)
 {
 	setFollowsAll();
 	setBorderVisible(FALSE);
@@ -336,14 +343,13 @@ LLScriptEdCore::LLScriptEdCore(
 
 	initMenu();
 		
-	
 	// Do the work that addTabPanel() normally does.
 	//LLRect tab_panel_rect( 0, mRect.getHeight(), mRect.getWidth(), 0 );
 	//tab_panel_rect.stretch( -LLPANEL_BORDER_WIDTH );
 	//mCodePanel->setFollowsAll();
 	//mCodePanel->translate( tab_panel_rect.mLeft - mCodePanel->getRect().mLeft, tab_panel_rect.mBottom - mCodePanel->getRect().mBottom);
 	//mCodePanel->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
-		
+	
 }
 
 LLScriptEdCore::~LLScriptEdCore()
@@ -402,6 +408,9 @@ void LLScriptEdCore::initMenu()
 	menuItem->setMenuCallback(onBtnHelp, this);
 	menuItem->setEnabledCallback(NULL);
 
+	menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "LSL Wiki Help...");
+	menuItem->setMenuCallback(onBtnDynamicHelp, this);
+	menuItem->setEnabledCallback(NULL);
 }
 
 BOOL LLScriptEdCore::hasChanged(void* userdata)
@@ -431,9 +440,135 @@ void LLScriptEdCore::draw()
 		childSetText("line_col", "");
 	}
 
+	updateDynamicHelp();
+
 	LLPanel::draw();
 }
 
+void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
+{
+	LLFloater* help_floater = LLFloater::getFloaterByHandle(mLiveHelpHandle);
+	if (!help_floater) return;
+
+	// update back and forward buttons
+	LLButton* fwd_button = LLUICtrlFactory::getButtonByName(help_floater, "fwd_btn");
+	LLButton* back_button = LLUICtrlFactory::getButtonByName(help_floater, "back_btn");
+	LLWebBrowserCtrl* browser = LLUICtrlFactory::getWebBrowserCtrlByName(help_floater, "lsl_guide_html");
+	back_button->setEnabled(browser->canNavigateBack());
+	fwd_button->setEnabled(browser->canNavigateForward());
+
+	if (!immediate && !gSavedSettings.getBOOL("ScriptHelpFollowsCursor"))
+	{
+		return;
+	}
+
+	LLTextSegment* segment = NULL;
+	std::vector<LLTextSegment*> selected_segments;
+	mEditor->getSelectedSegments(selected_segments);
+
+	// try segments in selection range first
+	std::vector<LLTextSegment*>::iterator segment_iter;
+	for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter)
+	{
+		if((*segment_iter)->getToken() && (*segment_iter)->getToken()->getType() == LLKeywordToken::WORD)
+		{
+			segment = *segment_iter;
+			break;
+		}
+	}
+
+	// then try previous segment in case we just typed it
+	if (!segment)
+	{
+		LLTextSegment* test_segment = mEditor->getPreviousSegment();
+		if(test_segment->getToken() && test_segment->getToken()->getType() == LLKeywordToken::WORD)
+		{
+			segment = test_segment;
+		}
+	}
+
+	if (segment)
+	{
+		if (segment->getToken() != mLastHelpToken)
+		{
+			mLastHelpToken = segment->getToken();
+			mLiveHelpTimer.start();
+		}
+		if (immediate || (mLiveHelpTimer.getStarted() && mLiveHelpTimer.getElapsedTimeF32() > LIVE_HELP_REFRESH_TIME))
+		{
+			LLString help_string = mEditor->getText().substr(segment->getStart(), segment->getEnd() - segment->getStart());
+			setHelpPage(help_string);
+			mLiveHelpTimer.stop();
+		}
+	}
+	else
+	{
+		setHelpPage("");
+	}
+}
+
+void LLScriptEdCore::setHelpPage(const LLString& help_string)
+{
+	LLFloater* help_floater = LLFloater::getFloaterByHandle(mLiveHelpHandle);
+	if (!help_floater) return;
+	
+	LLWebBrowserCtrl* web_browser = gUICtrlFactory->getWebBrowserCtrlByName(help_floater, "lsl_guide_html");
+	if (!web_browser) return;
+
+	LLComboBox* history_combo = gUICtrlFactory->getComboBoxByName(help_floater, "history_combo");
+	if (!history_combo) return;
+
+	LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
+	url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir());
+	url_string.setArg("[LSL_STRING]", help_string);
+
+	addHelpItemToHistory(help_string);
+	web_browser->navigateTo(url_string);
+}
+
+void LLScriptEdCore::addHelpItemToHistory(const LLString& help_string)
+{
+	if (help_string.empty()) return;
+
+	LLFloater* help_floater = LLFloater::getFloaterByHandle(mLiveHelpHandle);
+	if (!help_floater) return;
+
+	LLComboBox* history_combo = gUICtrlFactory->getComboBoxByName(help_floater, "history_combo");
+	if (!history_combo) return;
+
+	// separate history items from full item list
+	if (mLiveHelpHistorySize == 0)
+	{
+		LLSD row;
+		row["columns"][0]["type"] = "separator";
+		history_combo->addElement(row, ADD_TOP);
+	}
+	// delete all history items over history limit
+	while(mLiveHelpHistorySize > MAX_HISTORY_COUNT - 1)
+	{
+		history_combo->remove(mLiveHelpHistorySize - 1);
+		mLiveHelpHistorySize--;
+	}
+
+	history_combo->setSimple(help_string);
+	S32 index = history_combo->getCurrentIndex();
+
+	// if help string exists in the combo box
+	if (index >= 0)
+	{
+		S32 cur_index = history_combo->getCurrentIndex();
+		if (cur_index < mLiveHelpHistorySize)
+		{
+			// item found in history, bubble up to top
+			history_combo->remove(history_combo->getCurrentIndex());
+			mLiveHelpHistorySize--;
+		}
+	}
+	history_combo->add(help_string, LLSD(help_string), ADD_TOP);
+	history_combo->selectFirstItem();
+	mLiveHelpHistorySize++;
+}
+
 BOOL LLScriptEdCore::canClose()
 {
 	if(mForceClose || mEditor->isPristine())
@@ -497,6 +632,92 @@ void LLScriptEdCore::onBtnHelp(void* userdata)
 			userdata);
 }
 
+// static 
+void LLScriptEdCore::onBtnDynamicHelp(void* userdata)
+{
+	LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
+
+	LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle);
+	if (live_help_floater)
+	{
+		live_help_floater->setFocus(TRUE);
+		corep->updateDynamicHelp(TRUE);
+
+		return;
+	}
+
+	live_help_floater = new LLFloater("lsl_help");
+	gUICtrlFactory->buildFloater(live_help_floater, "floater_lsl_guide.xml");
+	((LLFloater*)corep->getParent())->addDependentFloater(live_help_floater, TRUE);
+	live_help_floater->childSetCommitCallback("lock_check", onCheckLock, userdata);
+	live_help_floater->childSetValue("lock_check", gSavedSettings.getBOOL("ScriptHelpFollowsCursor"));
+	live_help_floater->childSetCommitCallback("history_combo", onHelpComboCommit, userdata);
+	live_help_floater->childSetAction("back_btn", onClickBack, userdata);
+	live_help_floater->childSetAction("fwd_btn", onClickForward, userdata);
+
+	LLWebBrowserCtrl* browser = LLUICtrlFactory::getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html");
+	browser->setAlwaysRefresh(TRUE);
+
+	LLComboBox* help_combo = LLUICtrlFactory::getComboBoxByName(live_help_floater, "history_combo");
+	LLKeywordToken *token;
+	LLKeywords::word_token_map_t::iterator token_it;
+	for (token_it = corep->mEditor->mKeywords.mWordTokenMap.begin(); 
+		token_it != corep->mEditor->mKeywords.mWordTokenMap.end(); 
+		++token_it)
+	{
+		token = token_it->second;
+		help_combo->add(wstring_to_utf8str(token->mToken));
+	}
+	help_combo->sortByName();
+
+	// re-initialize help variables
+	corep->mLastHelpToken = NULL;
+	corep->mLiveHelpHandle = live_help_floater->getHandle();
+	corep->mLiveHelpHistorySize = 0;
+	corep->updateDynamicHelp(TRUE);
+}
+
+//static 
+void LLScriptEdCore::onClickBack(void* userdata)
+{
+	LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
+	LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle);
+	if (live_help_floater)
+	{
+		LLWebBrowserCtrl* browserp = LLUICtrlFactory::getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html");
+		if (browserp)
+		{
+			browserp->navigateBack();
+		}
+	}
+}
+
+//static 
+void LLScriptEdCore::onClickForward(void* userdata)
+{
+	LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
+	LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle);
+	if (live_help_floater)
+	{
+		LLWebBrowserCtrl* browserp = LLUICtrlFactory::getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html");
+		if (browserp)
+		{
+			browserp->navigateForward();
+		}
+	}
+}
+
+// static
+void LLScriptEdCore::onCheckLock(LLUICtrl* ctrl, void* userdata)
+{
+	LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
+
+	// clear out token any time we lock the frame, so we will refresh web page immediately when unlocked
+	gSavedSettings.setBOOL("ScriptHelpFollowsCursor", ctrl->getValue().asBoolean());
+
+	corep->mLastHelpToken = NULL;
+}
+
 // static 
 void LLScriptEdCore::onBtnInsertSample(void* userdata)
 {
@@ -508,6 +729,27 @@ void LLScriptEdCore::onBtnInsertSample(void* userdata)
 	self->mEditor->insertText(self->mSampleText);
 }
 
+// static 
+void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata)
+{
+	LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
+
+	LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle);
+	if (live_help_floater)
+	{
+		LLWebBrowserCtrl* web_browser = gUICtrlFactory->getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html");
+
+		LLString help_string = ctrl->getValue().asString();
+
+		corep->addHelpItemToHistory(help_string);
+
+		LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
+		url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir());
+		url_string.setArg("[LSL_STRING]", help_string);
+		web_browser->navigateTo(url_string);
+	}
+}
+
 // static 
 void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata)
 {
@@ -519,6 +761,7 @@ void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata)
 		self->mEditor->insertText(self->mFunctions->getSimple());
 	}
 	self->mEditor->setFocus(TRUE);
+	self->setHelpPage(self->mFunctions->getSimple());
 }
 
 // static 
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index 5b15fda2227f9d762fb9f0656e3855f12610fb6f..54b27316f7879cd1822d1af066669c15a3af2247 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -15,6 +15,7 @@
 #include "llinventory.h"
 #include "llcombobox.h"
 #include "lliconctrl.h"
+#include "llframetimer.h"
 
 
 class LLMessageSystem;
@@ -26,6 +27,7 @@ class LLViewerObject;
 struct 	LLEntryAndEdCore;
 class LLMenuBarGL;
 class LLFloaterScriptSearch;
+class LLKeywordToken;
 
 // Inner, implementation class.  LLPreviewScript and LLLiveScriptEditor each own one of these.
 class LLScriptEdCore : public LLPanel
@@ -60,6 +62,11 @@ class LLScriptEdCore : public LLPanel
 
 	static void		onHelpWebDialog(S32 option, void* userdata);
 	static void		onBtnHelp(void* userdata);
+	static void		onBtnDynamicHelp(void* userdata);
+	static void		onCheckLock(LLUICtrl*, void*);
+	static void		onHelpComboCommit(LLUICtrl* ctrl, void* userdata);
+	static void		onClickBack(void* userdata);
+	static void		onClickForward(void* userdata);
 	static void		onBtnInsertSample(void*);
 	static void		onBtnInsertFunction(LLUICtrl*, void*);
 	static void		doSave( void* userdata, BOOL close_after_save );
@@ -91,6 +98,9 @@ class LLScriptEdCore : public LLPanel
 
 protected:
 	void deleteBridges();
+	void setHelpPage(const LLString& help_string);
+	void updateDynamicHelp(BOOL immediate = FALSE);
+	void addHelpItemToHistory(const LLString& help_string);
 
 	static void onErrorList(LLUICtrl*, void* user_data);
 
@@ -107,6 +117,10 @@ class LLScriptEdCore : public LLPanel
 	LLPanel*		mCodePanel;
 	LLScrollListCtrl* mErrorList;
 	LLDynamicArray<LLEntryAndEdCore*> mBridges;
+	LLViewHandle	mLiveHelpHandle;
+	LLKeywordToken* mLastHelpToken;
+	LLFrameTimer	mLiveHelpTimer;
+	S32				mLiveHelpHistorySize;
 };