diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 6063fc155aba418b556f7c689fcbc44e3153892c..b4fdbfeb0e63fddfbdaa60ee52816a46401efb15 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -261,7 +261,8 @@ void	LLComboBox::resetDirty()
 // add item "name" to menu
 LLScrollListItem* LLComboBox::add(const LLString& name, EAddPosition pos, BOOL enabled)
 {
-	LLScrollListItem* item = mList->addSimpleItem(name, pos, enabled);
+	LLScrollListItem* item = mList->addSimpleElement(name, pos);
+	item->setEnabled(enabled);
 	mList->selectFirstItem();
 	return item;
 }
@@ -269,7 +270,8 @@ LLScrollListItem* LLComboBox::add(const LLString& name, EAddPosition pos, BOOL e
 // add item "name" with a unique id to menu
 LLScrollListItem* LLComboBox::add(const LLString& name, const LLUUID& id, EAddPosition pos, BOOL enabled )
 {
-	LLScrollListItem* item = mList->addSimpleItem(name, LLSD(id), pos, enabled);
+	LLScrollListItem* item = mList->addSimpleElement(name, pos, id);
+	item->setEnabled(enabled);
 	mList->selectFirstItem();
 	return item;
 }
@@ -277,7 +279,8 @@ LLScrollListItem* LLComboBox::add(const LLString& name, const LLUUID& id, EAddPo
 // add item "name" with attached userdata
 LLScrollListItem* LLComboBox::add(const LLString& name, void* userdata, EAddPosition pos, BOOL enabled )
 {
-	LLScrollListItem* item = mList->addSimpleItem(name, pos, enabled);
+	LLScrollListItem* item = mList->addSimpleElement(name, pos);
+	item->setEnabled(enabled);
 	item->setUserdata( userdata );
 	mList->selectFirstItem();
 	return item;
@@ -286,7 +289,8 @@ LLScrollListItem* LLComboBox::add(const LLString& name, void* userdata, EAddPosi
 // add item "name" with attached generic data
 LLScrollListItem* LLComboBox::add(const LLString& name, LLSD value, EAddPosition pos, BOOL enabled )
 {
-	LLScrollListItem* item = mList->addSimpleItem(name, value, pos, enabled);
+	LLScrollListItem* item = mList->addSimpleElement(name, pos, value);
+	item->setEnabled(enabled);
 	mList->selectFirstItem();
 	return item;
 }
@@ -306,7 +310,7 @@ void LLComboBox::sortByName()
 // Returns TRUE if the item was found.
 BOOL LLComboBox::setSimple(const LLStringExplicit& name)
 {
-	BOOL found = mList->selectSimpleItem(name, FALSE);
+	BOOL found = mList->selectItemByLabel(name, FALSE);
 
 	if (found)
 	{
@@ -325,14 +329,14 @@ void LLComboBox::setValue(const LLSD& value)
 		LLScrollListItem* item = mList->getFirstSelected();
 		if (item)
 		{
-			setLabel( mList->getSimpleSelectedItem() );
+			setLabel( mList->getSelectedItemLabel() );
 		}
 	}
 }
 
 const LLString LLComboBox::getSimple() const
 {
-	const LLString res = mList->getSimpleSelectedItem();
+	const LLString res = mList->getSelectedItemLabel();
 	if (res.empty() && mAllowTextEntry)
 	{
 		return mTextEntry->getText();
@@ -343,9 +347,9 @@ const LLString LLComboBox::getSimple() const
 	}
 }
 
-const LLString LLComboBox::getSimpleSelectedItem(S32 column) const
+const LLString LLComboBox::getSelectedItemLabel(S32 column) const
 {
-	return mList->getSimpleSelectedItem(column);
+	return mList->getSelectedItemLabel(column);
 }
 
 // virtual
@@ -371,7 +375,7 @@ void LLComboBox::setLabel(const LLStringExplicit& name)
 	if ( mTextEntry )
 	{
 		mTextEntry->setText(name);
-		if (mList->selectSimpleItem(name, FALSE))
+		if (mList->selectItemByLabel(name, FALSE))
 		{
 			mTextEntry->setTentative(FALSE);
 		}
@@ -393,7 +397,7 @@ void LLComboBox::setLabel(const LLStringExplicit& name)
 
 BOOL LLComboBox::remove(const LLString& name)
 {
-	BOOL found = mList->selectSimpleItem(name);
+	BOOL found = mList->selectItemByLabel(name);
 
 	if (found)
 	{
@@ -468,7 +472,7 @@ BOOL LLComboBox::setCurrentByIndex( S32 index )
 	BOOL found = mList->selectNthItem( index );
 	if (found)
 	{
-		setLabel(mList->getSimpleSelectedItem());
+		setLabel(mList->getSelectedItemLabel());
 	}
 	return found;
 }
@@ -658,7 +662,7 @@ void LLComboBox::hideList()
 	LLString orig_selection = mAllowTextEntry ? mTextEntry->getText() : mButton->getLabelSelected();
 
 	// assert selection in list
-	mList->selectSimpleItem(orig_selection, FALSE);
+	mList->selectItemByLabel(orig_selection, FALSE);
 
 	mButton->setToggleState(FALSE);
 	mList->setVisible(FALSE);
@@ -720,7 +724,7 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
 	// Note: item is the LLScrollListCtrl
 	LLComboBox *self = (LLComboBox *) userdata;
 
-	const LLString name = self->mList->getSimpleSelectedItem();
+	const LLString name = self->mList->getSelectedItemLabel();
 
 	S32 cur_id = self->getCurrentIndex();
 	if (cur_id != -1)
@@ -738,7 +742,7 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
 		// invalid selection, just restore existing value
 		LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected();
 
-		self->mList->selectSimpleItem(orig_selection);
+		self->mList->selectItemByLabel(orig_selection);
 	}
 	self->onCommit();
 
@@ -851,7 +855,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
 	if (key == KEY_BACKSPACE || 
 		key == KEY_DELETE)
 	{
-		if (self->mList->selectSimpleItem(line_editor->getText(), FALSE))
+		if (self->mList->selectItemByLabel(line_editor->getText(), FALSE))
 		{
 			line_editor->setTentative(FALSE);
 		}
@@ -931,11 +935,11 @@ void LLComboBox::updateSelection()
 		}
 	}
 
-	if (mList->selectSimpleItem(full_string, FALSE))
+	if (mList->selectItemByLabel(full_string, FALSE))
 	{
 		mTextEntry->setTentative(FALSE);
 	}
-	else if (!mList->selectSimpleItemByPrefix(left_wstring, FALSE))
+	else if (!mList->selectItemByPrefix(left_wstring, FALSE))
 	{
 		mList->deselectAllItems();
 		mTextEntry->setText(wstring_to_utf8str(user_wstring));
@@ -943,7 +947,7 @@ void LLComboBox::updateSelection()
 	}
 	else
 	{
-		LLWString selected_item = utf8str_to_wstring(mList->getSimpleSelectedItem());
+		LLWString selected_item = utf8str_to_wstring(mList->getSelectedItemLabel());
 		LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size());
 		mTextEntry->setText(wstring_to_utf8str(wtext));
 		mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size());
@@ -1028,7 +1032,7 @@ BOOL LLComboBox::setCurrentByID(const LLUUID& id)
 
 	if (found)
 	{
-		setLabel(mList->getSimpleSelectedItem());
+		setLabel(mList->getSelectedItemLabel());
 	}
 
 	return found;
@@ -1043,14 +1047,14 @@ BOOL LLComboBox::setSelectedByValue(LLSD value, BOOL selected)
 	BOOL found = mList->setSelectedByValue(value, selected);
 	if (found)
 	{
-		setLabel(mList->getSimpleSelectedItem());
+		setLabel(mList->getSelectedItemLabel());
 	}
 	return found;
 }
 
-LLSD LLComboBox::getSimpleSelectedValue()
+LLSD LLComboBox::getSelectedValue()
 {
-	return mList->getSimpleSelectedValue();
+	return mList->getSelectedValue();
 }
 
 BOOL LLComboBox::isSelected(LLSD value)
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 6e77007aef1d58abb97e3dbf5bd036e1680924b0..303ba83e92b76cdccb05d20f4c080fdebb144bf0 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -118,12 +118,12 @@ class LLComboBox
 
 	void			sortByName(); // Sort the entries in the combobox by name
 
-	// Select current item by name using selectSimpleItem.  Returns FALSE if not found.
+	// Select current item by name using selectItemByLabel.  Returns FALSE if not found.
 	BOOL			setSimple(const LLStringExplicit& name);
 	// Get name of current item. Returns an empty string if not found.
 	const LLString	getSimple() const;
 	// Get contents of column x of selected row
-	const LLString getSimpleSelectedItem(S32 column = 0) const;
+	const LLString getSelectedItemLabel(S32 column = 0) const;
 
 	// Sets the label, which doesn't have to exist in the label.
 	// This is probably a UI abuse.
@@ -160,7 +160,7 @@ class LLComboBox
 	virtual BOOL	setCurrentByID( const LLUUID& id );
 	virtual LLUUID	getCurrentID();				// LLUUID::null if no items in menu
 	virtual BOOL	setSelectedByValue(LLSD value, BOOL selected);
-	virtual LLSD	getSimpleSelectedValue();
+	virtual LLSD	getSelectedValue();
 	virtual BOOL	isSelected(LLSD value);
 	virtual BOOL	operateOnSelection(EOperation op);
 	virtual BOOL	operateOnAll(EOperation op);
diff --git a/indra/llui/llctrlselectioninterface.h b/indra/llui/llctrlselectioninterface.h
index 688c0a2499706f8da9a9f38fcecca61dbd28f3c1..77811d049b3483d0fc4645d08afabb9e59a3b3fa 100644
--- a/indra/llui/llctrlselectioninterface.h
+++ b/indra/llui/llctrlselectioninterface.h
@@ -68,7 +68,7 @@ class LLCtrlSelectionInterface
 			BOOL	selectByValue(LLSD value);
 			BOOL	deselectByValue(LLSD value);
 	virtual BOOL	setSelectedByValue(LLSD value, BOOL selected) = 0;
-	virtual LLSD	getSimpleSelectedValue() = 0;
+	virtual LLSD	getSelectedValue() = 0;
 
 	virtual BOOL	isSelected(LLSD value) = 0;
 
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index 5b9a35353390f81e968999c34af0ce50fe681ba5..53541f512867bae140bfd4f5dbfcf0d045da11fd 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -473,7 +473,7 @@ BOOL	LLRadioGroup::setSelectedByValue(LLSD value, BOOL selected)
 	return FALSE;
 }
 
-LLSD	LLRadioGroup::getSimpleSelectedValue()
+LLSD	LLRadioGroup::getSelectedValue()
 {
 	return getValue();	
 }
diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h
index aa19b3a3d0b856aa38f17c454d855fd2a98f0ac2..5db1baeaec675c3e614ed4160bdc117079d32da7 100644
--- a/indra/llui/llradiogroup.h
+++ b/indra/llui/llradiogroup.h
@@ -122,7 +122,7 @@ class LLRadioGroup
 	/*virtual*/ BOOL	setCurrentByID( const LLUUID& id );
 	/*virtual*/ LLUUID	getCurrentID();				// LLUUID::null if no items in menu
 	/*virtual*/ BOOL	setSelectedByValue(LLSD value, BOOL selected);
-	/*virtual*/ LLSD	getSimpleSelectedValue();
+	/*virtual*/ LLSD	getSelectedValue();
 	/*virtual*/ BOOL	isSelected(LLSD value);
 	/*virtual*/ BOOL	operateOnSelection(EOperation op);
 	/*virtual*/ BOOL	operateOnAll(EOperation op);
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 0c81b2da0832952009c5fc2229760897045637a5..346b120c395e626168f461c8193f649bf68ceaff 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -113,19 +113,13 @@ struct SortScrollListItem
 //
 // LLScrollListIcon
 //
-LLScrollListIcon::LLScrollListIcon(LLImageGL* icon, S32 width, LLUUID image_id)
-	: mIcon(icon),
-	  mImageUUID(image_id.asString()),
-	  mColor(LLColor4::white)
+LLScrollListIcon::LLScrollListIcon(const LLUUID& icon_id, S32 width)
+	: LLScrollListCell(width),
+	  mColor(LLColor4::white),
+	  mImageUUID(icon_id)
 {
-	if (width)
-	{
-		mWidth = width;
-	}
-	else
-	{
-		mWidth = icon->getWidth();
-	}
+	// don't use default image specified by LLUUID::null, use no image in that case
+	mIcon = icon_id.isNull() ? NULL : LLUI::sImageProvider->getImageByID(icon_id);
 }
 
 LLScrollListIcon::~LLScrollListIcon()
@@ -136,7 +130,7 @@ void LLScrollListIcon::setValue(LLSD value)
 {
 	mImageUUID = value.asUUID();
 	// don't use default image specified by LLUUID::null, use no image in that case
-	mIcon = mImageUUID.isNull() ? NULL : LLUI::sImageProvider->getImageByID(value.asUUID());
+	mIcon = mImageUUID.isNull() ? NULL : LLUI::sImageProvider->getImageByID(mImageUUID);
 }
 
 
@@ -145,7 +139,18 @@ void LLScrollListIcon::setColor(const LLColor4& color)
 	mColor = color;
 }
 
-void LLScrollListIcon::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const	
+S32	LLScrollListIcon::getWidth() const 
+{
+	// if no specified fix width, use width of icon
+	if (mWidth == 0)
+	{
+		return mIcon->getWidth();
+	}
+	return mWidth;
+}
+
+
+void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_color) const	
 {
 	if (mIcon)
 	{
@@ -178,7 +183,7 @@ LLScrollListCheck::~LLScrollListCheck()
 	delete mCheckBox;
 }
 
-void LLScrollListCheck::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const
+void LLScrollListCheck::draw(const LLColor4& color, const LLColor4& highlight_color) const
 {
 	mCheckBox->draw();
 }
@@ -196,14 +201,14 @@ BOOL LLScrollListCheck::handleClick()
 //
 // LLScrollListSeparator
 //
-LLScrollListSeparator::LLScrollListSeparator(S32 width) : mWidth(width)
+LLScrollListSeparator::LLScrollListSeparator(S32 width) : LLScrollListCell(width)
 {
 }
 
-void LLScrollListSeparator::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const
+void LLScrollListSeparator::draw(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);
+	gl_line_2d(5, 8, llmax(5, getWidth() - 5), 8, color);
 }
 
 //
@@ -212,11 +217,11 @@ void LLScrollListSeparator::drawToWidth(S32 width, const LLColor4& color, const
 U32 LLScrollListText::sCount = 0;
 
 LLScrollListText::LLScrollListText( const LLString& text, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible)
-:	mText( text ),
+:	LLScrollListCell(width),
+	mText( text ),
 	mFont( font ),
 	mFontStyle( font_style ),
 	mFontAlignment( font_alignment ),
-	mWidth( width ),
 	mVisible( visible ),
 	mHighlightCount( 0 ),
 	mHighlightOffset( 0 )
@@ -266,14 +271,8 @@ void LLScrollListText::setText(const LLStringExplicit& text)
 	mText = text;
 }
 
-void LLScrollListText::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const
+void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_color) const
 {
-	// If the user has specified a small minimum width, use that.
-	if (mWidth > 0 && mWidth < width)
-	{
-		width = mWidth;
-	}
-
 	const LLColor4* display_color;
 	if (mColor)
 	{
@@ -295,10 +294,10 @@ void LLScrollListText::drawToWidth(S32 width, const LLColor4& color, const LLCol
 			left = mFont->getWidth(mText.getString(), 0, mHighlightOffset);
 			break;
 		case LLFontGL::RIGHT:
-			left = width - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
+			left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
 			break;
 		case LLFontGL::HCENTER:
-			left = (width - mFont->getWidth(mText.getString())) / 2;
+			left = (getWidth() - mFont->getWidth(mText.getString())) / 2;
 			break;
 		}
 		gl_segmented_rect_2d_tex(left - 2, 
@@ -320,10 +319,10 @@ void LLScrollListText::drawToWidth(S32 width, const LLColor4& color, const LLCol
 		start_x = 0.f;
 		break;
 	case LLFontGL::RIGHT:
-		start_x = (F32)width;
+		start_x = (F32)getWidth();
 		break;
 	case LLFontGL::HCENTER:
-		start_x = (F32)width * 0.5f;
+		start_x = (F32)getWidth() * 0.5f;
 		break;
 	}
 	mFont->render(mText.getWString(), 0, 
@@ -333,8 +332,10 @@ void LLScrollListText::drawToWidth(S32 width, const LLColor4& color, const LLCol
 						LLFontGL::BOTTOM, 
 						mFontStyle,
 						string_chars, 
-						width,
-						&right_x, FALSE, TRUE);
+						getWidth(),
+						&right_x, 
+						FALSE, 
+						TRUE);
 }
 
 
@@ -389,11 +390,110 @@ LLString LLScrollListItem::getContentsCSV()
 	return ret;
 }
 
+void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
+{
+	// draw background rect
+	LLRect bg_rect = rect;
+	// pad background rectangle to separate it from contents
+	bg_rect.stretch(LIST_BORDER_PAD, 0);
+	{
+		LLGLSNoTexture no_texture;
+		glColor4fv(bg_color.mV);
+		gl_rect_2d( bg_rect );
+	}
+
+	S32 cur_x = rect.mLeft;
+	S32 num_cols = getNumColumns();
+	S32 cur_col = 0;
+
+	for (LLScrollListCell* cell = getColumn(0); cur_col < num_cols; cell = getColumn(++cur_col))
+	{
+		// Two ways a cell could be hidden
+		if (cell->getWidth() < 0
+			|| !cell->getVisible()) continue;
+
+		LLUI::pushMatrix();
+		{
+			LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f);
+
+			cell->draw( fg_color, highlight_color );
+		}
+		LLUI::popMatrix();
+		
+		cur_x += cell->getWidth() + column_padding;
+	}
+}
+
+
 void LLScrollListItem::setEnabled(BOOL b)
 {
 	mEnabled = b;
 }
 
+//---------------------------------------------------------------------------
+// LLScrollListItemComment
+//---------------------------------------------------------------------------
+LLScrollListItemComment::LLScrollListItemComment(const LLString& comment_string, const LLColor4& color)
+: LLScrollListItem(FALSE),
+	mColor(color)
+{
+	addColumn( comment_string, gResMgr->getRes( LLFONT_SANSSERIF_SMALL ) );
+}
+
+void LLScrollListItemComment::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
+{
+	LLScrollListCell* cell = getColumn(0);
+	if (cell)
+	{
+		// Two ways a cell could be hidden
+		if (cell->getWidth() < 0
+			|| !cell->getVisible()) return;
+
+		LLUI::pushMatrix();
+		{
+			LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f);
+
+			// force first cell to be width of entire item
+			cell->setWidth(rect.getWidth());
+			cell->draw( mColor, highlight_color );
+		}
+		LLUI::popMatrix();
+	}
+}
+
+//---------------------------------------------------------------------------
+// LLScrollListItemSeparator
+//---------------------------------------------------------------------------
+LLScrollListItemSeparator::LLScrollListItemSeparator()
+: LLScrollListItem(FALSE)
+{
+	LLScrollListSeparator* cell = new LLScrollListSeparator(0);
+	setNumColumns(1);
+	setColumn(0, cell);
+}
+
+void LLScrollListItemSeparator::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
+{
+	//TODO* move LLScrollListSeparator::draw into here and get rid of it
+	LLScrollListCell* cell = getColumn(0);
+	if (cell)
+	{
+		// Two ways a cell could be hidden
+		if (cell->getWidth() < 0
+			|| !cell->getVisible()) return;
+
+		LLUI::pushMatrix();
+		{
+			LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f);
+
+			// force first cell to be width of entire item
+			cell->setWidth(rect.getWidth());
+			cell->draw( fg_color, highlight_color );
+		}
+		LLUI::popMatrix();
+	}
+}
+
 //---------------------------------------------------------------------------
 // LLScrollListCtrl
 //---------------------------------------------------------------------------
@@ -418,7 +518,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
 	mNeedsScroll(FALSE),
 	mCanSelect(TRUE),
 	mDisplayColumnHeaders(FALSE),
-	mCollapseEmptyColumns(FALSE),
 	mMaxItemCount(INT_MAX), 
 	mMaxContentWidth(0),
 	mBackgroundVisible( TRUE ),
@@ -437,13 +536,9 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
 	mOnSortChangedCallback( NULL ),
 	mHighlightedItem(-1),
 	mBorder(NULL),
-	mDefaultColumnName("SIMPLE"),
 	mSearchColumn(0),
 	mNumDynamicWidthColumns(0),
 	mTotalStaticColumnWidth(0),
-	mSortAscending(TRUE),
-	mSecondarySortColumn(-1),
-	mSecondarySortAscending(TRUE),
 	mSorted(TRUE),
 	mDirty(FALSE),
 	mOriginalSelection(-1),
@@ -693,7 +788,7 @@ LLRect LLScrollListCtrl::getRequiredRect()
 }
 
 
-BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos )
+BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL requires_column )
 {
 	BOOL not_too_big = getItemCount() < mMaxItemCount;
 	if (not_too_big)
@@ -734,6 +829,16 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos )
 			break;
 		}
 	
+		// create new column on demand
+		if (mColumns.empty() && requires_column)
+		{
+			LLSD new_column;
+			new_column["name"] = "default_column";
+			new_column["label"] = "";
+			new_column["dynamicwidth"] = TRUE;
+			addColumn(new_column);
+		}
+
 		updateLineHeightInsert(item);
 		calcMaxContentWidth(item);
 
@@ -917,11 +1022,6 @@ void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
 
 }
 
-void LLScrollListCtrl::setCollapseEmptyColumns(BOOL collapse)
-{
-	mCollapseEmptyColumns = collapse;
-}
-
 BOOL LLScrollListCtrl::selectFirstItem()
 {
 	BOOL success = FALSE;
@@ -1255,46 +1355,31 @@ void LLScrollListCtrl::deselectAllItems(BOOL no_commit_on_change)
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// "Simple" interface: use this when you're creating a list that contains only unique strings, only
-// one of which can be selected at a time.
+// Use this to add comment text such as "Searching", which ignores column settings of list
 
-LLScrollListItem* LLScrollListCtrl::addSimpleItem(const LLString& item_text, EAddPosition pos, BOOL enabled)
+LLScrollListItem* LLScrollListCtrl::addCommentText(const LLString& comment_text, EAddPosition pos)
 {
 	LLScrollListItem* item = NULL;
 	if (getItemCount() < mMaxItemCount)
 	{
 		// simple items have their LLSD data set to their label
-		item = new LLScrollListItem( LLSD(item_text) );
-		item->setEnabled(enabled);
-		item->addColumn( item_text, gResMgr->getRes( LLFONT_SANSSERIF_SMALL ) );
-		addItem( item, pos );
-
-		// create new column on demand for "simple" items
-		if (mColumns.empty())
-		{
-			LLSD new_column;
-			new_column["name"] = mDefaultColumnName;
-			new_column["label"] = "";
-			new_column["dynamicwidth"] = TRUE;
-			addColumn(new_column);
-		}
+		// always draw comment text with "enabled" color
+		item = new LLScrollListItemComment( comment_text, mFgSelectedColor );
+		addItem( item, pos, FALSE );
 	}
 	return item;
 }
 
 LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos)
 {
-	LLSD item;	
-	item["enabled"] = FALSE;
-	item["columns"][0]["type"] = "separator";
-	item["columns"][0]["column"] = mDefaultColumnName;
-
-	return addElement(item, pos);
+	LLScrollListItem* item = new LLScrollListItemSeparator();
+	addItem(item, pos, FALSE);
+	return item;
 }
 
 // Selects first enabled item of the given name.
 // Returns false if item not found.
-BOOL LLScrollListCtrl::selectSimpleItem(const LLString& label, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByLabel(const LLString& label, BOOL case_sensitive)
 {
 	//RN: assume no empty items
 	if (label.empty())
@@ -1339,14 +1424,14 @@ BOOL LLScrollListCtrl::selectSimpleItem(const LLString& label, BOOL case_sensiti
 }
 
 
-BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLString& target, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByPrefix(const LLString& target, BOOL case_sensitive)
 {
-	return selectSimpleItemByPrefix(utf8str_to_wstring(target), case_sensitive);
+	return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive);
 }
 
 // Selects first enabled item that has a name where the name's first part matched the target string.
 // Returns false if item not found.
-BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive)
 {
 	BOOL found = FALSE;
 
@@ -1420,7 +1505,7 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca
 	return found;
 }
 
-const LLString LLScrollListCtrl::getSimpleSelectedItem(S32 column) const
+const LLString LLScrollListCtrl::getSelectedItemLabel(S32 column) const
 {
 	LLScrollListItem* item;
 
@@ -1449,30 +1534,6 @@ LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const LLString& item_text,
 	return item;
 }
 
-LLScrollListItem* LLScrollListCtrl::addSimpleItem(const LLString& item_text, LLSD sd, EAddPosition pos, BOOL enabled, S32 column_width)
-{
-	LLScrollListItem* item = NULL;
-	if (getItemCount() < mMaxItemCount)
-	{
-		item = new LLScrollListItem( sd );
-		item->setEnabled(enabled);
-		item->addColumn(item_text, gResMgr->getRes(LLFONT_SANSSERIF_SMALL), column_width);
-		addItem( item, pos );
-
-		// create new column on demand
-		if (mColumns.empty())
-		{
-			LLSD new_column;
-			new_column["name"] = "default_column";
-			new_column["label"] = "";
-			new_column["dynamicwidth"] = TRUE;
-			addColumn(new_column);
-		}
-	}
-	return item;
-}
-
-
 // Select the line or lines that match this UUID
 BOOL LLScrollListCtrl::selectByID( const LLUUID& id )
 {
@@ -1538,7 +1599,7 @@ LLUUID LLScrollListCtrl::getStringUUIDSelectedItem()
 	return LLUUID::null;
 }
 
-LLSD LLScrollListCtrl::getSimpleSelectedValue()
+LLSD LLScrollListCtrl::getSelectedValue()
 {
 	LLScrollListItem* item = getFirstSelected();
 
@@ -1567,7 +1628,6 @@ void LLScrollListCtrl::drawItems()
 	{
 		LLLocalClipRect clip(mItemListRect);
 
-		S32 cur_x = x;
 		S32 cur_y = y;
 		
 		mDrewSelected = FALSE;
@@ -1575,15 +1635,19 @@ void LLScrollListCtrl::drawItems()
 		S32 line = 0;
 		S32 max_columns = 0;
 
+		LLColor4 highlight_color = LLColor4::white;
+		F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout");
+		highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f);
+
 		item_list::iterator iter;
 		for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
 		{
 			LLScrollListItem* item = *iter;
 			
 			item_rect.setOriginAndSize( 
-				cur_x, 
+				x, 
 				cur_y, 
-				mScrollbar->getVisible() ? mItemListRect.getWidth() : mItemListRect.getWidth() + mScrollbar->getRect().getWidth(),
+				mItemListRect.getWidth(),
 				mLineHeight );
 
 			//llinfos << item_rect.getWidth() << llendl;
@@ -1596,83 +1660,35 @@ void LLScrollListCtrl::drawItems()
 			max_columns = llmax(max_columns, item->getNumColumns());
 
 			LLColor4 fg_color;
-			LLRect bg_rect = item_rect;
-			// pad background rectangle to separate it from contents
-			bg_rect.stretch(LIST_BORDER_PAD, 0);
-			LLColor4 bg_color(0.f, 0.f, 0.f, 0.f);
+			LLColor4 bg_color(LLColor4::transparent);
 
 			if( mScrollLines <= line && line < mScrollLines + num_page_lines )
 			{
+				fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor);
 				if( item->getSelected() && mCanSelect)
 				{
 					// Draw background of selected item
 					bg_color = mBgSelectedColor;
-					fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor);
 				}
 				else if (mHighlightedItem == line && mCanSelect)
 				{
 					bg_color = mHighlightedColor;
-					fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
 				}
 				else 
 				{
-					if (mDrawStripes && (line%2 == 0) && (max_columns > 1))
+					if (mDrawStripes && (line % 2 == 0) && (max_columns > 1))
 					{
 						bg_color = mBgStripeColor;
 					}
-					fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
 				}
 
 				if (!item->getEnabled())
 				{
 					bg_color = mBgReadOnlyColor;
 				}
-				// draw background rect
-				{
-					LLGLSNoTexture no_texture;
-					glColor4fv(bg_color.mV);
-					gl_rect_2d( bg_rect );
-				}
 
-				S32 line_x = cur_x;
-				{
-					S32 num_cols = item->getNumColumns();
-					S32 cur_col = 0;
-					S32 dynamic_width = 0;
-					S32 dynamic_remainder = 0;
-					if(mNumDynamicWidthColumns > 0)
-					{
-						dynamic_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
-						dynamic_remainder = (mItemListRect.getWidth() - mTotalStaticColumnWidth) % mNumDynamicWidthColumns;
-					}
+				item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding);
 
-					for (LLScrollListCell* cell = item->getColumn(0); cur_col < num_cols; cell = item->getColumn(++cur_col))
-					{
-						S32 cell_width = cell->getWidth();
-						if(mColumnsIndexed.size() > (U32)cur_col && mColumnsIndexed[cur_col] && mColumnsIndexed[cur_col]->mDynamicWidth)
-						{							
-							cell_width = dynamic_width + (--dynamic_remainder ? 1 : 0);
-							cell->setWidth(cell_width);
-						}
-						// Two ways a cell could be hidden
-						if (cell_width < 0
-							|| !cell->getVisible()) continue;
-
-						LLUI::pushMatrix();
-						LLUI::translate((F32) cur_x, (F32) cur_y, 0.0f);
-						S32 space_left = mItemListRect.mRight - cur_x;
-						LLColor4 highlight_color = LLColor4::white;
-						F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout");
-
-						highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f);
-						cell->drawToWidth( space_left, fg_color, highlight_color );
-						LLUI::popMatrix();
-						
-						cur_x += cell_width + mColumnPadding;
-
-					}
-				} 
-				cur_x = line_x;			
 				cur_y -= mLineHeight;
 			}
 			line++;
@@ -2235,7 +2251,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
 						}
 					}
 				}
-				else if (selectSimpleItemByPrefix(wstring_to_utf8str(mSearchString), FALSE))
+				else if (selectItemByPrefix(wstring_to_utf8str(mSearchString), FALSE))
 				{
 					mNeedsScroll = TRUE;
 					// update search string only on successful match
@@ -2274,7 +2290,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
 	// type ahead search is case insensitive
 	uni_char = LLStringOps::toLower((llwchar)uni_char);
 
-	if (selectSimpleItemByPrefix(wstring_to_utf8str(mSearchString + (llwchar)uni_char), FALSE))
+	if (selectItemByPrefix(wstring_to_utf8str(mSearchString + (llwchar)uni_char), FALSE))
 	{
 		// update search string only on successful match
 		mNeedsScroll = TRUE;
@@ -2463,7 +2479,7 @@ BOOL LLScrollListCtrl::setSort(S32 column, BOOL ascending)
 		
 		// remove any existing sort criterion referencing this column
 		// and add the new one
-		remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column)); 
+		mSortColumns.erase(remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column)), mSortColumns.end()); 
 		mSortColumns.push_back(new_sort_column);
 
 		// did the sort criteria change?
@@ -2702,9 +2718,6 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
 	BOOL draw_heading = FALSE;
 	node->getAttributeBOOL("draw_heading", draw_heading);
 
-	BOOL collapse_empty_columns = FALSE;
-	node->getAttributeBOOL("collapse_empty_columns", collapse_empty_columns);
-
 	S32 search_column = 0;
 	node->getAttributeS32("search_column", search_column);
 
@@ -2725,7 +2738,6 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
 		node->getAttributeS32("heading_height", heading_height);
 		scroll_list->setHeadingHeight(heading_height);
 	}
-	scroll_list->setCollapseEmptyColumns(collapse_empty_columns);
 
 	scroll_list->setScrollListParameters(node);
 
@@ -2765,7 +2777,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
 			LLString tooltip;
 			child->getAttributeString("tool_tip", tooltip);
 
-			if(!columndynamicwidth) total_static += columnwidth;
+			if(!columndynamicwidth) total_static += llmax(0, columnwidth);
 
 			F32 columnrelwidth = 0.f;
 			child->getAttributeF32("relwidth", columnrelwidth);
@@ -2840,7 +2852,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
 		while(token_iter != tokens.end())
 		{
 			const char* line = token_iter->c_str();
-			scroll_list->addSimpleItem(line);
+			scroll_list->addSimpleElement(line);
 			++token_iter;
 		}
 	}
@@ -2937,10 +2949,6 @@ BOOL	LLScrollListCtrl::canDeselect()
 void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
 {
 	LLString name = column["name"].asString();
-	if (mColumns.empty())
-	{
-		mDefaultColumnName = name;
-	}
 	// if no column name provided, just use ordinal as name
 	if (name.empty())
 	{
@@ -3011,6 +3019,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
 			sendChildToFront(mScrollbar);
 		}
 	}
+
 	updateColumns();
 }
 
@@ -3129,6 +3138,11 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
 	S32 col_index = 0 ;
 	for (itor = columns.beginArray(); itor != columns.endArray(); ++itor)
 	{
+		if (itor->isUndefined())
+		{
+			// skip unused columns in item passed in
+			continue;
+		}
 		LLString column = (*itor)["column"].asString();
 
 		LLScrollListColumn* columnp = NULL;
@@ -3154,9 +3168,18 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
 			LLSD new_column;
 			new_column["name"] = column;
 			new_column["label"] = column;
-			new_column["width"] = (*itor)["width"];
+			// if width supplied for column, use it, otherwise 
+			// use adaptive width
+			if (itor->has("width"))
+			{
+				new_column["width"] = (*itor)["width"];
+			}
+			else
+			{
+				new_column["dynamicwidth"] = true;
+			}
 			addColumn(new_column);
-			columnp = &mColumns.find(column)->second;
+			columnp = &mColumns[column];
 			new_item->setNumColumns(mColumns.size());
 		}
 
@@ -3182,9 +3205,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
 		if (type == "icon")
 		{
 			LLUUID image_id = value.asUUID();
-			// don't use special image with UUID::null, just don't draw an image
-			LLImageGL* icon = image_id.isNull() ? NULL : LLUI::sImageProvider->getImageByID(image_id);
-			LLScrollListIcon* cell = new LLScrollListIcon(icon, width, image_id);
+			LLScrollListIcon* cell = new LLScrollListIcon(value.asUUID(), width);
 			if (has_color)
 			{
 				cell->setColor(color);
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 001e10184b65d46c0ea8d7865fbb7a3c46c612df..aa0af7dcd89d6cc0147095e946e45031ffc13c08 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -56,22 +56,26 @@ class LLResizeBar;
 class LLScrollListCell
 {
 public:
+	LLScrollListCell(S32 width = 0) : mWidth(width) {};
 	virtual ~LLScrollListCell() {};
-	virtual void			drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const = 0;		// truncate to given width, if possible
-	virtual S32				getWidth() const = 0;
+	virtual void			draw(const LLColor4& color, const LLColor4& highlight_color) const = 0;		// truncate to given width, if possible
+	virtual S32				getWidth() const {return mWidth;}
 	virtual S32				getContentWidth() const { return 0; }
 	virtual S32				getHeight() const = 0;
 	virtual const LLSD		getValue() const { return LLString::null; }
 	virtual void			setValue(LLSD value) { }
 	virtual BOOL			getVisible() const { return TRUE; }
-	virtual void			setWidth(S32 width) = 0;
+	virtual void			setWidth(S32 width) { mWidth = width; }
 	virtual void			highlightText(S32 offset, S32 num_chars) {}
 	virtual BOOL			isText() = 0;
-	virtual void			setColor(const LLColor4&) = 0;
+	virtual void			setColor(const LLColor4&) {}
 	virtual void			onCommit() {};
 
 	virtual BOOL	handleClick() { return FALSE; }
 	virtual	void	setEnabled(BOOL enable) { }
+
+protected:
+	S32 mWidth;
 };
 
 class LLScrollListSeparator : public LLScrollListCell
@@ -79,15 +83,9 @@ 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 void			draw(const LLColor4& color, const LLColor4& highlight_color) const;		// truncate to given width, if possible
 	virtual S32				getHeight() const { return 5; };
-	virtual void			setWidth(S32 width) {mWidth = width; }
-	virtual void			setColor(const LLColor4&) {};
 	virtual BOOL			isText() { return FALSE; }
-
-protected:
-	S32 mWidth;
 };
 
 class LLScrollListText : public LLScrollListCell
@@ -96,10 +94,8 @@ class LLScrollListText : public LLScrollListCell
 	LLScrollListText( const LLString& text, const LLFontGL* font, S32 width = 0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE);
 	/*virtual*/ ~LLScrollListText();
 
-	virtual void    drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const;
-	virtual S32		getWidth() const			{ return mWidth; }
+	virtual void    draw(const LLColor4& color, const LLColor4& highlight_color) const;
 	virtual S32		getContentWidth() const;
-	virtual void	setWidth(S32 width)			{ mWidth = width; }
 	virtual S32		getHeight() const			{ return llround(mFont->getLineHeight()); }
 	virtual const LLSD		getValue() const		{ return LLSD(mText.getString()); }
 	virtual BOOL	getVisible() const  { return mVisible; }
@@ -117,7 +113,6 @@ class LLScrollListText : public LLScrollListCell
 	LLColor4*		mColor;
 	U8				mFontStyle;
 	LLFontGL::HAlign mFontAlignment;
-	S32				mWidth;
 	BOOL			mVisible;
 	S32				mHighlightCount;
 	S32				mHighlightOffset;
@@ -130,13 +125,13 @@ class LLScrollListText : public LLScrollListCell
 class LLScrollListIcon : public LLScrollListCell
 {
 public:
-	LLScrollListIcon( LLImageGL* icon, S32 width = 0, LLUUID image_id = LLUUID::null);
+	LLScrollListIcon( const LLUUID& icon_id, S32 width = 0);
 	/*virtual*/ ~LLScrollListIcon();
-	virtual void	drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const;
-	virtual S32		getWidth() const			{ return mWidth; }
+	virtual void	draw(const LLColor4& color, const LLColor4& highlight_color) const;
+	virtual S32		getWidth() const;
 	virtual S32		getHeight() const			{ return mIcon ? mIcon->getHeight() : 0; }
+	// used as sort criterion
 	virtual const LLSD		getValue() const { return LLSD(mImageUUID); }
-	virtual void	setWidth(S32 width)			{ mWidth = width; }
 	virtual void	setColor(const LLColor4&);
 	virtual BOOL	isText() { return FALSE; }
 	virtual void	setValue(LLSD value);
@@ -144,7 +139,6 @@ class LLScrollListIcon : public LLScrollListCell
 private:
 	LLPointer<LLImageGL> mIcon;
 	LLUUID mImageUUID;
-	S32 mWidth;
 	LLColor4 mColor;
 };
 
@@ -153,24 +147,20 @@ class LLScrollListCheck : public LLScrollListCell
 public:
 	LLScrollListCheck( LLCheckBoxCtrl* check_box, S32 width = 0);
 	/*virtual*/ ~LLScrollListCheck();
-	virtual void	drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const;
-	virtual S32		getWidth() const			{ return mWidth; }
+	virtual void	draw(const LLColor4& color, const LLColor4& highlight_color) const;
 	virtual S32		getHeight() const			{ return 0; } 
-	virtual void	setWidth(S32 width)			{ mWidth = width; }
 	virtual const LLSD	getValue() const { return mCheckBox->getValue(); }
 	virtual void	setValue(LLSD value) { mCheckBox->setValue(value); }
 	virtual void	onCommit() { mCheckBox->onCommit(); }
 
 	virtual BOOL	handleClick();
 	virtual void	setEnabled(BOOL enable)		{ mCheckBox->setEnabled(enable); }
-	virtual void	setColor(const LLColor4& color) {};
 
 	LLCheckBoxCtrl*	getCheckBox()				{ return mCheckBox; }
 	virtual BOOL	isText() { return FALSE; }
 
 private:
 	LLCheckBoxCtrl* mCheckBox;
-	S32 mWidth;
 };
 
 class LLScrollListColumn
@@ -329,8 +319,8 @@ class LLScrollListItem
 	void	addColumn( const LLString& text, const LLFontGL* font, S32 width = 0 , U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, BOOL visible = TRUE)
 				{ mColumns.push_back( new LLScrollListText(text, font, width, font_style, font_alignment, LLColor4::black, FALSE, visible) ); }
 
-	void	addColumn( LLImageGL* icon, S32 width = 0 )
-				{ mColumns.push_back( new LLScrollListIcon(icon, width) ); }
+	void	addColumn( const LLUUID& icon_id, S32 width = 0 )
+				{ mColumns.push_back( new LLScrollListIcon(icon_id, width) ); }
 
 	void	addColumn( LLCheckBoxCtrl* check, S32 width = 0 )
 				{ mColumns.push_back( new LLScrollListCheck(check,width) ); }
@@ -345,6 +335,8 @@ class LLScrollListItem
 
 	LLString getContentsCSV();
 
+	virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
+
 private:
 	BOOL	mSelected;
 	BOOL	mEnabled;
@@ -353,6 +345,23 @@ class LLScrollListItem
 	std::vector<LLScrollListCell *> mColumns;
 };
 
+class LLScrollListItemComment : public LLScrollListItem
+{
+public:
+	LLScrollListItemComment(const LLString& comment_string, const LLColor4& color);
+
+	/*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
+private:
+	LLColor4 mColor;
+};
+
+class LLScrollListItemSeparator : public LLScrollListItem
+{
+public:
+	LLScrollListItemSeparator();
+
+	/*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
+};
 
 class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, 
 	public LLCtrlListInterface, public LLCtrlScrollInterface
@@ -397,7 +406,6 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
 	// Simple add element. Takes a single array of:
 	// [ "value" => value, "font" => font, "font-style" => style ]
-	virtual LLScrollListItem* addSimpleElement(const LLString& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
 	virtual void clearRows(); // clears all elements
 	virtual void sortByColumn(LLString name, BOOL ascending);
 
@@ -453,20 +461,21 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	S32				getItemIndex( LLScrollListItem* item );
 	S32				getItemIndex( LLUUID& item_id );
 
+	LLScrollListItem* addCommentText( const LLString& comment_text, EAddPosition pos = ADD_BOTTOM);
+	LLScrollListItem* addSeparator(EAddPosition pos);
+
 	// "Simple" interface: use this when you're creating a list that contains only unique strings, only
 	// one of which can be selected at a time.
-	LLScrollListItem* addSimpleItem( const LLString& item_text, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE );
-	// Add an item with an associated LLSD
-	LLScrollListItem* addSimpleItem(const LLString& item_text, LLSD sd, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0 );
-	LLScrollListItem* addSeparator(EAddPosition pos);
+	virtual LLScrollListItem* addSimpleElement(const LLString& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
+
 
-	BOOL			selectSimpleItem( const LLString& item, BOOL case_sensitive = TRUE );		// FALSE if item not found
-	BOOL			selectSimpleItemByPrefix(const LLString& target, BOOL case_sensitive);
-	BOOL			selectSimpleItemByPrefix(const LLWString& target, BOOL case_sensitive);
-	const LLString	getSimpleSelectedItem(S32 column = 0) const;
-	LLSD			getSimpleSelectedValue();
+	BOOL			selectItemByLabel( const LLString& item, BOOL case_sensitive = TRUE );		// FALSE if item not found
+	BOOL			selectItemByPrefix(const LLString& target, BOOL case_sensitive = TRUE);
+	BOOL			selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE);
+	const LLString	getSelectedItemLabel(S32 column = 0) const;
+	LLSD			getSelectedValue();
 
-	// DEPRECATED: Use LLSD versions of addSimpleItem() and getSimpleSelectedValue().
+	// DEPRECATED: Use LLSD versions of addCommentText() and getSelectedValue().
 	// "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which
 	// has an associated, unique UUID, and only one of which can be selected at a time.
 	LLScrollListItem*	addStringUUIDItem(const LLString& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0);
@@ -604,7 +613,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	// to the caller to delete the item)
 
 	// returns FALSE if item faile to be added to list, does NOT delete 'item'
-	BOOL			addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM );
+	BOOL			addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM, BOOL requires_column = TRUE );
 	void			selectPrevItem(BOOL extend_selection);
 	void			selectNextItem(BOOL extend_selection);
 	void			drawItems();
@@ -636,7 +645,6 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	BOOL			mNeedsScroll;
 	BOOL			mCanSelect;
 	BOOL			mDisplayColumnHeaders;
-	BOOL			mCollapseEmptyColumns;
 
 	typedef std::deque<LLScrollListItem *> item_list;
 	item_list		mItemList;
@@ -672,16 +680,10 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	LLWString		mSearchString;
 	LLFrameTimer	mSearchTimer;
 	
-	LLString		mDefaultColumnName;
-
 	S32				mSearchColumn;
 	S32				mNumDynamicWidthColumns;
 	S32				mTotalStaticColumnWidth;
 
-	S32				mSortColumn;
-	S32				mSecondarySortColumn;
-	BOOL			mSecondarySortAscending;
-	BOOL			mSortAscending;
 	BOOL			mSorted;
 	
 	std::map<LLString, LLScrollListColumn> mColumns;
diff --git a/indra/newview/linux_tools/client-readme-voice.txt b/indra/newview/linux_tools/client-readme-voice.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ff1d4b23b9fa54156edc6239f73e6413e3c2da20
--- /dev/null
+++ b/indra/newview/linux_tools/client-readme-voice.txt
@@ -0,0 +1,91 @@
+Second Life - Linux Voice Support README
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+WHAT IS IT?
+-=-=-=-=-=-
+
+Linux Voice Support is a new feature in testing which allows users
+of the Linux Second Life client to participate in voice-chat with other
+residents and groups inside Second Life, with an appropriate
+headset/microphone.
+
+Linux Voice Support is currently EXPERIMENTAL and is known to still
+have some compatibility issues.
+
+REQUIREMENTS
+-=-=-=-=-=-=
+
+* A headset/microphone supported by your chosen version of Linux
+* The ALSA sound system (you probably already have this -
+  i.e. the alsa-base and alsa-utils packages on Ubuntu)
+
+Success with Linux Voice support has been reported on the following
+systems:
+* Ubuntu 7.04 (Feisty) with Intel HDA audio chipset
+* Ubuntu 6.06 (Dapper) with Intel ICH5/CMI9761A+ audio chipset
+* Ubuntu 6.06 (Dapper) with SigmaTel STAC2997 audio chipset
+* Fedora Core 6 with (unknown) audio chipset
+
+Problems with Linux Voice support have been reported on the following
+systems:
+* Ubuntu 6.06 (Dapper) with Creative EMU10K1 audio chipset
+
+KNOWN PROBLEMS
+-=-=-=-=-=-=-=
+
+* The 'Input Level' meter in the Voice Chat Device Settings dialog
+  does not respond to audio input.
+
+* The Input/Output options in the Voice Chat Device Settings dialog
+  do not list all of the available audio devices, so only the 'default'
+  device may be selected.
+
+TROUBLESHOOTING
+-=-=-=-=-=-=-=-
+
+PROBLEM 1: I don't see a white dot over the head of my avatar or other
+  Voice-using avatars.
+SOLUTION:
+a. Ensure that 'Enable voice chat' is enabled in the Voice Chat
+  preferences window and that you are in a voice-enabled area (you
+  will see a blue headphone icon in the SL menu-bar).
+b. If the above does not help, exit Second Life and ensure that any
+  remaining 'SLVoice' processes (as reported by 'ps', 'top' or similar)
+  are killed.
+
+PROBLEM 2: I have a white dot over my head but I never see (or hear!) anyone
+  except myself listed in the Active Speakers dialog when I'm sure that other
+  residents nearby are active Voice users.
+SOLUTION: This is an incompatibility between the Voice support and your
+  system's audio (ALSA) driver version/configuration.
+a. Back-up and remove your ~/.asoundrc file, re-test.
+b. Check for updates to your kernel, kernel modules and ALSA-related
+  packages using your Linux distribution's package-manager - install these,
+  reboot and re-test.
+c. Update to the latest version of ALSA manually.  For a guide, see the
+  'Update to the Latest Version of ALSA' section of this page:
+  <https://help.ubuntu.com/community/HdaIntelSoundHowto> or the official
+  documentation on the ALSA site: <http://www.alsa-project.org/> - reboot
+  and re-test.
+
+PROBLEM 3: I can hear other people, but they cannot hear me.
+SOLUTION:
+a. Ensure that you have the 'Talk' button activated while you are trying to
+  speak.
+b. Ensure that your microphone jack is inserted into the correct socket of your
+  sound card, where appropriate.
+c. Use your system mixer-setting program or the 'alsamixer' program to ensure
+  that microphone input is set as the active input source and is not muted.
+d. Verify that audio input works in other applications, i.e. Audacity
+
+PROBLEM 4: Other people just hear bursts of loud noise when I speak.
+SOLUTION:
+a. Use your system mixer-setting program or the 'alsamixer' program to ensure
+  that microphone Gain/Boost is not set too high.
+
+FURTHER PROBLEMS?
+-=-=-=-=-=-=-=-=-
+
+Please report further issues to the public Second Life issue-tracker
+at <http://jira.secondlife.com/> (please note, however, that this is not
+a support forum).
diff --git a/indra/newview/linux_tools/client-readme.txt b/indra/newview/linux_tools/client-readme.txt
index 832dff4209445790e27c9b8bfe97f507b470123d..89454e2ade03566db22b3a11f2e1861b3ed0fa18 100644
--- a/indra/newview/linux_tools/client-readme.txt
+++ b/indra/newview/linux_tools/client-readme.txt
@@ -100,8 +100,6 @@ you wish.
 These are the most commonly-encountered known issues which are specific to
 the Alpha release of the Linux client.
 
-* VOICE COMMUNICATION - this is not yet available in the Linux client.
-
 * VISUAL EFFECTS AND PERFORMANCE - many Linux graphics drivers are not as
   robust as their counterparts for other operating systems, so some advanced
   Second Life graphical features have been DISABLED by default to aid
@@ -112,7 +110,6 @@ the Alpha release of the Linux client.
   Linux client and are therefore known not to work properly:
   * Movie recording
   * Full Unicode font rendering
-  * Auto-updater
 
 * UPLOAD / SAVE / COLOR-PICKER DIALOGS - These only appear when the client
   is in 'windowed' mode, not 'fullscreen' mode.
@@ -130,6 +127,9 @@ The client prints a lot of diagnostic information to the console it was
 run from.  Most of this is also replicated in ~/.secondlife/logs/SecondLife.log
 - this is helpful to read when troubleshooting, especially 'WARNING' lines.
 
+VOICE PROBLEMS?  See the separate README-linux-voice.txt file for Voice
+troubleshooting information.
+
 PROBLEM 1:- Second Life fails to start up, with a warning on the console like:
    'Error creating window.' or
    'Unable to create window, be sure screen is set at 32-bit color' or
@@ -249,11 +249,14 @@ the 'Search' button at the bottom of the window and then selecting the
 'Groups' tab and searching for 'Linux'.  This group is useful for discussing
 Linux issues with fellow Linux client users who are online.
 
+The Second Life Issue Tracker:
+<http://jira.secondlife.com/>
+This is the right place for finding known issues and reporting new
+bugs in all Second Life releases if you find that the Troubleshooting
+section in this file hasn't helped (please note, however, that this is
+not a support forum).
+
 Linux Client Alpha Testers forum:
 <http://forums.secondlife.com/forumdisplay.php?forumid=263>
-This is a good place for discussing Linux-specific Second Life problems
-if you find that the Troubleshooting section in this file hasn't helped.
-When reporting problems here, please include information about the
-Second Life version you are running, your graphics card, graphics driver,
-and Linux distribution.
-
+This is a forum where Linux Client users can help each other out and
+discuss the latest updates.
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index 35efbc13b87172a6e673a91bdd69f2460aef1aaa..4ed06099fc205b13864bacc639d07ddeaaafba4b 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -117,7 +117,5 @@ echo
 echo '*********************************************************'
 echo 'This is an ALPHA release of the Second Life linux client.'
 echo 'Thank you for testing!'
-echo 'You can visit the Linux Client Alpha Testers forum at:'
-echo 'http://forums.secondlife.com/forumdisplay.php?forumid=263'
 echo 'Please see README-linux.txt before reporting problems.'
 echo
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 78365e66f185dd0a90b566a02315ced35fc0e18f..1798aea122e6944e47f4c457ca021d3e4a2f02ae 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -639,7 +639,7 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl, void* data)
 		{
 			return;
 		}
-		const std::string& trigger = gestures->getSimpleSelectedValue().asString();
+		const std::string& trigger = gestures->getSelectedValue().asString();
 
 		// pretend the user chatted the trigger string, to invoke
 		// substitution and logging.
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index cebd51d4daefb7a526ef3149b243192017e34533..1a4d3c16fd81e4afef60567ef211621397beed17 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -203,7 +203,7 @@ BOOL LLFloaterScriptQueue::start()
 	snprintf(buffer, sizeof(buffer), "Starting %s of %d items.", mStartString, mObjectIDs.count()); 		/* Flawfinder: ignore */
 	
 	LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output");
-	list->addSimpleItem(buffer);
+	list->addCommentText(buffer);
 
 	return nextObject();
 }
@@ -241,7 +241,7 @@ BOOL LLFloaterScriptQueue::nextObject()
 		mDone = TRUE;
 		char buffer[MAX_STRING];		/*Flawfinder: ignore*/
 		snprintf(buffer, sizeof(buffer), "Done.");				/* Flawfinder: ignore */
-		list->addSimpleItem(buffer);
+		list->addCommentText(buffer);
 		childSetEnabled("close",TRUE);
 	}
 	return successful_start;
@@ -444,7 +444,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
 	if(queue) 
 	{
 		LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(queue, "queue output");
-		list->addSimpleItem(buffer);
+		list->addCommentText(buffer);
 	}
 	delete data;
 }
@@ -625,7 +625,7 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj,
 				LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output");
 				char buffer[MAX_STRING];		 /*Flawfinder: ignore*/
 				snprintf(buffer, sizeof(buffer), "Resetting '%s'.", item->getName().c_str());		 	/* Flawfinder: ignore */
-				list->addSimpleItem(buffer);
+				list->addCommentText(buffer);
 				LLMessageSystem* msg = gMessageSystem;
 				msg->newMessageFast(_PREHASH_ScriptReset);
 				msg->nextBlockFast(_PREHASH_AgentData);
@@ -688,7 +688,7 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj,
 				LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output");
 				char buffer[MAX_STRING];  	/*Flawfinder: ignore*/
 				snprintf(buffer, sizeof(buffer), "Running '%s'.", item->getName().c_str());		 	/* Flawfinder: ignore */
-				list->addSimpleItem(buffer);
+				list->addCommentText(buffer);
 
 				LLMessageSystem* msg = gMessageSystem;
 				msg->newMessageFast(_PREHASH_SetScriptRunning);
@@ -753,7 +753,7 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj,
 				LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output");
 				char buffer[MAX_STRING];		 /*Flawfinder: ignore*/
 				snprintf(buffer, sizeof(buffer), "Not running '%s'.", item->getName().c_str());	 	/* Flawfinder: ignore */
-				list->addSimpleItem(buffer);
+				list->addCommentText(buffer);
 	
 				LLMessageSystem* msg = gMessageSystem;
 				msg->newMessageFast(_PREHASH_SetScriptRunning);
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 8dcd38c0bb24b834dd84bcfdcf796d03b9385a86..2cfcc47af3765c57cd18fd7d20a4ee0bbe8de678 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -112,7 +112,7 @@ BOOL LLFloaterAvatarPicker::postBuild()
 
 	if (mListNames)
 	{
-		mListNames->addSimpleElement("No results");
+		mListNames->addCommentText("No results");
 	}
 
 	mInventoryPanel = (LLInventoryPanel*)this->getCtrlByNameAndType("Inventory Panel", WIDGET_TYPE_INVENTORY_PANEL);
@@ -279,7 +279,7 @@ void LLFloaterAvatarPicker::find()
 	if (mListNames)
 	{
 		mListNames->deleteAllItems();	
-		mListNames->addSimpleElement("Searching...");
+		mListNames->addCommentText("Searching...");
 	}
 	
 	childSetEnabled("Select", FALSE);
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 2167e1f2ca3f622015fe3169599d6bc8d7ebed95..6dd55c169ba7a5a3d79998ccfff1cd54c1a7e768 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -1069,44 +1069,8 @@ BOOL LLPanelLandObjects::postBuild()
 	image_id.set( gViewerArt.getString("icon_group.tga") );
 	mIconGroup = gImageList.getImage(image_id, MIPMAP_FALSE, TRUE);
 
-	mCurrentSortColumn = 3; // sort by number of objects by default.
-	mCurrentSortAscending = FALSE;
-
-	// Column widths for various columns
-	const S32 SORTER_WIDTH		= 308;
-	const S32 DESC_BTN_WIDTH	= 64;
-	const S32 ICON_WIDTH		= 24;
-	mColWidth[0] = ICON_WIDTH;	// type icon
-	mColWidth[1] = -1;	// hidden type code
-	mColWidth[2] = SORTER_WIDTH - mColWidth[0] - DESC_BTN_WIDTH;
-	mColWidth[3] = DESC_BTN_WIDTH;			// info
-	mColWidth[4] = -1;						// type data 1
-	mColWidth[5] = -1;
-	mColWidth[6] = -1;	// type data 3
-	mColWidth[7] = -1;	// type data 4
-	mColWidth[8] = -1;	// type data 5
-
-	// Adjust description for other widths
-	S32 sum = 0;
-	for (S32 i = 0; i < 8; i++)
-	{
-		if (mColWidth[i] > 0)
-		{
-			sum += mColWidth[i];
-		}
-	}
-	mColWidth[8] = mRect.getWidth() - HPAD - sum - HPAD - HPAD;
-
-	mBtnType = LLUICtrlFactory::getButtonByName(this, "Type");
-	mBtnType->setClickedCallback(onClickType, this);
-
-	mBtnName = LLUICtrlFactory::getButtonByName(this, "Name");
-	mBtnName->setClickedCallback(onClickName, this);
-
-	mBtnDescription = LLUICtrlFactory::getButtonByName(this, "Count");
-	mBtnDescription->setClickedCallback(onClickDesc, this);
-	
 	mOwnerList = LLUICtrlFactory::getNameListByName(this, "owner list");
+	mOwnerList->sortByColumn(3, FALSE);
 	childSetCommitCallback("owner list", onCommitList, this);
 	mOwnerList->setDoubleClickCallback(onDoubleClickOwner);
 
@@ -1483,7 +1447,7 @@ void LLPanelLandObjects::onClickRefresh(void* userdata)
 
 	// ready the list for results
 	self->mOwnerList->deleteAllItems();
-	self->mOwnerList->addSimpleItem("Searching...");
+	self->mOwnerList->addCommentText("Searching...");
 	self->mOwnerList->setEnabled(FALSE);
 	self->mFirstReply = TRUE;
 
@@ -1544,24 +1508,24 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
 		LLScrollListItem *row = new LLScrollListItem( TRUE, NULL, owner_id);
 		if (is_group_owned)
 		{
-			row->addColumn(self->mIconGroup, self->mColWidth[0]);
-			row->addColumn(OWNER_GROUP, FONT, self->mColWidth[1]);
+			row->addColumn(self->mIconGroup.notNull() ? self->mIconGroup->getID() : LLUUID::null);
+			row->addColumn(OWNER_GROUP, FONT);
 		}
 		else if (is_online)
 		{
-			row->addColumn(self->mIconAvatarOnline, self->mColWidth[0]);
-			row->addColumn(OWNER_ONLINE, FONT, self->mColWidth[1]);
+			row->addColumn(self->mIconAvatarOnline.notNull() ? self->mIconAvatarOnline->getID() : LLUUID::null);
+			row->addColumn(OWNER_ONLINE, FONT);
 		}
 		else  // offline
 		{
-			row->addColumn(self->mIconAvatarOffline, self->mColWidth[0]);
-			row->addColumn(OWNER_OFFLINE, FONT, self->mColWidth[1]);
+			row->addColumn(self->mIconAvatarOffline.notNull() ? self->mIconAvatarOffline->getID() : LLUUID::null);
+			row->addColumn(OWNER_OFFLINE, FONT);
 		}
 		// Placeholder for name.
-		row->addColumn(LLString::null, FONT, self->mColWidth[2]);
+		row->addColumn(LLString::null, FONT);
 
 		snprintf(object_count_str, sizeof(object_count_str), "%d", object_count); 		/* Flawfinder: ignore */
-		row->addColumn(object_count_str, FONT, self->mColWidth[3]);
+		row->addColumn(object_count_str, FONT);
 
 		if (is_group_owned)
 		{
@@ -1575,12 +1539,10 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
 		lldebugs << "object owner " << owner_id << " (" << (is_group_owned ? "group" : "agent")
 				<< ") owns " << object_count << " objects." << llendl;
 	}
-	self->mOwnerList->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
-
 	// check for no results
 	if (0 == self->mOwnerList->getItemCount())
 	{
-		self->mOwnerList->addSimpleItem("None found.");
+		self->mOwnerList->addCommentText("None found.");
 	}
 	else
 	{
@@ -1588,21 +1550,6 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
 	}
 }
 
-void LLPanelLandObjects::sortBtnCore(S32 column)
-{
-	if (column == (S32)mCurrentSortColumn)  // is this already our sorted column?
-	{
-		mCurrentSortAscending = !mCurrentSortAscending;
-	}
-	else  // default to ascending first time a column is clicked
-	{
-		mCurrentSortColumn = column;
-		mCurrentSortAscending = TRUE;
-	}
-
-	mOwnerList->sortByColumn(column, mCurrentSortAscending);
-}
-
 // static
 void LLPanelLandObjects::onCommitList(LLUICtrl* ctrl, void* data)
 {
@@ -1639,28 +1586,6 @@ void LLPanelLandObjects::onCommitList(LLUICtrl* ctrl, void* data)
 	}
 }
 
-// static
-void LLPanelLandObjects::onClickType(void* userdata)
-{
-	// Sort on hidden type column
-	LLPanelLandObjects* self = (LLPanelLandObjects*)userdata;
-	self->sortBtnCore(1);
-}
-
-// static
-void LLPanelLandObjects::onClickDesc(void* userdata)
-{
-	LLPanelLandObjects* self = (LLPanelLandObjects*)userdata;
-	self->sortBtnCore(3);
-}
-
-// static
-void LLPanelLandObjects::onClickName(void* userdata)
-{
-	LLPanelLandObjects* self = (LLPanelLandObjects*)userdata;
-	self->sortBtnCore(2);
-}
-
 // static
 void LLPanelLandObjects::clickShowCore(LLPanelLandObjects* self, S32 return_type, uuid_list_t* list)
 {
@@ -2893,7 +2818,7 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata)
 			LLCtrlSelectionInterface* passcombo = self->childGetSelectionInterface("pass_combo");
 			if (passcombo)
 			{
-				if (passcombo->getSimpleSelectedValue().asString() == "group")
+				if (passcombo->getSelectedValue().asString() == "group")
 				{
 					use_access_list = FALSE;
 				}
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 4407e0b5b44b74c276eb38be08720d35888019df..8b77bb990a169e53026baead4a14df55d8ece044 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -250,9 +250,6 @@ class LLPanelLandObjects
 	static void onClickReturnOtherObjects(void*);
 	static void onClickReturnOwnerList(void*);
 	static void onClickRefresh(void*);
-	static void onClickType(void*);
-	static void onClickName(void*);
-	static void onClickDesc(void*);
 
 	static void onDoubleClickOwner(void*);	
 
@@ -264,7 +261,6 @@ class LLPanelLandObjects
 	virtual BOOL postBuild();
 
 protected:
-	void sortBtnCore(S32 column);
 
 	LLTextBox		*mParcelObjectBonus;
 	LLTextBox		*mSWTotalObjects;
@@ -284,19 +280,12 @@ class LLPanelLandObjects
 	S32				mOtherTime;
 	LLButton		*mBtnRefresh;
 	LLButton		*mBtnReturnOwnerList;
-	LLButton        *mBtnType;			// column 0
-	LLButton        *mBtnName;			// column 2
-	LLButton        *mBtnDescription;	// column 3
 	LLNameListCtrl	*mOwnerList;
 
 	LLPointer<LLViewerImage>	mIconAvatarOnline;
 	LLPointer<LLViewerImage>	mIconAvatarOffline;
 	LLPointer<LLViewerImage>	mIconGroup;
 
-	U32             mCurrentSortColumn;
-	BOOL            mCurrentSortAscending;
-	S32             mColWidth[12];
-
 	BOOL			mFirstReply;
 
 	uuid_list_t		mSelectedOwners;
diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp
index bccabb356fa498e64c41281955b94317dad700d8..b150c873feea9c121176089224a58812d85ea1d5 100644
--- a/indra/newview/llfloaterlandholdings.cpp
+++ b/indra/newview/llfloaterlandholdings.cpp
@@ -256,7 +256,7 @@ void LLFloaterLandHoldings::buttonCore(S32 which)
 	S32 index = list->getFirstSelectedIndex();
 	if (index < 0) return;
 
-	LLString location = list->getSimpleSelectedItem(3);
+	LLString location = list->getSelectedItemLabel(3);
 
 	F32 global_x = 0.f;
 	F32 global_y = 0.f;
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 6128909528fe16a1aa352e8a96fdfc1c424ab6be..2da9ed4e14d54764f2ee618f98aaddb74dce4871 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -665,7 +665,7 @@ LLSD LLFloaterReporter::gatherReport()
 	LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(this, "category_combo");
 	if (combo)
 	{
-		category_name = combo->getSimpleSelectedItem(); // want label, not value
+		category_name = combo->getSelectedItemLabel(); // want label, not value
 	}
 
 #if LL_WINDOWS
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 71e94cce93b94e37b8f4202bd8dfcace440e2e38..da298c56c4ff5e12eff3995d6cde9a090f021361 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1123,7 +1123,7 @@ void LLFloaterSnapshot::Impl::onCommitResolution(LLUICtrl* ctrl, void* data)
 	combo = LLUICtrlFactory::getComboBoxByName(view, "local_size_combo");
 	gSavedSettings.setS32("SnapshotLocalLastResolution", combo->getCurrentIndex());
 
-	std::string sdstring = combobox->getSimpleSelectedValue();
+	std::string sdstring = combobox->getSelectedValue();
 	LLSD sdres;
 	std::stringstream sstream(sdstring);
 	LLSDSerialize::fromNotation(sdres, sstream);
diff --git a/indra/newview/llfloatertelehub.cpp b/indra/newview/llfloatertelehub.cpp
index 95a47bb2acc9dae89f07e6029c9b1bd4bb97580a..9c837135d8e9f493bf3b4bbf8c7f9d4e53d12d12 100644
--- a/indra/newview/llfloatertelehub.cpp
+++ b/indra/newview/llfloatertelehub.cpp
@@ -305,7 +305,7 @@ void LLFloaterTelehub::unpackTelehubInfo(LLMessageSystem* msg)
 									mSpawnPointPos[i].mV[VX],
 									mSpawnPointPos[i].mV[VY],
 									mSpawnPointPos[i].mV[VZ]);
-			list->addSimpleItem(pos);
+			list->addSimpleElement(pos);
 		}
 		list->selectNthItem(mNumSpawn - 1);
 	}
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index b1bbb341fd890cef331a1f05837e3471c4254600..ce5a94520ce1bf9795b4c5d0a2ecd20335e512cd 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -1569,11 +1569,11 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
 		return;
 	}
 
-	LLCtrlListInterface *list = childGetListInterface("search_results");
+	LLScrollListCtrl *list = gUICtrlFactory->getScrollListByName(this, "search_results");
 	if (!list) return;
 	list->operateOnAll(LLCtrlListInterface::OP_DELETE);
 
-	LLSD selected_value = list->getSimpleSelectedValue();
+	LLSD selected_value = list->getSelectedValue();
 
 	S32 name_length = mCompletingRegionName.length();
 
@@ -1628,7 +1628,7 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
 	}
 	else
 	{
-		list->addSimpleElement("None found.");
+		list->addCommentText("None found.");
 		list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
 	}
 }
@@ -1659,7 +1659,7 @@ void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata)
 	LLCtrlListInterface *list = self->childGetListInterface("search_results");
 	if (!list) return;
 
-	LLSD selected_value = list->getSimpleSelectedValue();
+	LLSD selected_value = list->getSelectedValue();
 	LLString sim_name = selected_value.asString();
 	if (sim_name.empty())
 	{
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index a47721be9d7302cf13ffec6a6d34517f1a248d72..9dd37cf47d7798f85469fc6110c867252e7a30b9 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -332,9 +332,6 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
 	BOOL draw_heading = FALSE;
 	node->getAttributeBOOL("draw_heading", draw_heading);
 
-	BOOL collapse_empty_columns = FALSE;
-	node->getAttributeBOOL("collapse_empty_columns", collapse_empty_columns);
-
 	S32 name_column_index = 0;
 	node->getAttributeS32("name_column_index", name_column_index);
 
@@ -355,7 +352,6 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
 		node->getAttributeS32("heading_height", heading_height);
 		name_list->setHeadingHeight(heading_height);
 	}
-	name_list->setCollapseEmptyColumns(collapse_empty_columns);
 
 	BOOL allow_calling_card_drop = FALSE;
 	if (node->getAttributeBOOL("allow_calling_card_drop", allow_calling_card_drop))
@@ -369,6 +365,7 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
 
 	LLSD columns;
 	S32 index = 0;
+	S32 total_static = 0;
 	LLXMLNodePtr child;
 	for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
 	{
@@ -380,6 +377,13 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
 			LLString columnname(labelname);
 			child->getAttributeString("name", columnname);
 
+			BOOL columndynamicwidth = FALSE;
+			child->getAttributeBOOL("dynamicwidth", columndynamicwidth);
+
+			LLString sortname(columnname);
+			child->getAttributeString("sort", sortname);
+		
+			S32 columnwidth = -1;
 			if (child->hasAttribute("relwidth"))
 			{
 				F32 columnrelwidth = 0.f;
@@ -388,7 +392,6 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
 			}
 			else
 			{
-				S32 columnwidth = -1;
 				child->getAttributeS32("width", columnwidth);
 				columns[index]["width"] = columnwidth;
 			}
@@ -396,14 +399,21 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
 			LLFontGL::HAlign h_align = LLFontGL::LEFT;
 			h_align = LLView::selectFontHAlign(child);
 
+			if(!columndynamicwidth) total_static += llmax(0, columnwidth);
+
 			columns[index]["name"] = columnname;
 			columns[index]["label"] = labelname;
 			columns[index]["halign"] = (S32)h_align;
+			columns[index]["dynamicwidth"] = columndynamicwidth;
+			columns[index]["sort"] = sortname;
+
 			index++;
 		}
 	}
+	name_list->setTotalStaticColumnWidth(total_static);
 	name_list->setColumnHeadings(columns);
 
+
 	for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
 	{
 		if (child->hasName("row"))
@@ -453,7 +463,7 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
 	while(token_iter != tokens.end())
 	{
 		const char* line = token_iter->c_str();
-		name_list->addSimpleItem(line);
+		name_list->addCommentText(line);
 		++token_iter;
 	}
 
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 4ee155931cc04e5ae18d836f3f806344ccd98075..0146214c4bd8139e2d85b6deb9a64918cb3323bc 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -2010,7 +2010,7 @@ void LLPanelAvatar::processAvatarGroupsReply(LLMessageSystem *msg, void**)
 		S32 group_count = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
 		if (0 == group_count)
 		{
-			if(group_list) group_list->addSimpleItem("None");
+			if(group_list) group_list->addCommentText("None");
 		}
 		else
 		{
diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index dbe24d40e030839c638b3d4a2c1fa4ec9c9fb230..7f12555fe2727b0aa72b25ba2e22086fafee024c 100644
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -665,7 +665,7 @@ BOOL LLPanelGroupLandMoney::postBuild()
 	{
 		if ( mImplementationp->mGroupParcelsp )
 		{
-			mImplementationp->mGroupParcelsp->addSimpleItem(
+			mImplementationp->mGroupParcelsp->addCommentText(
 							mImplementationp->mCantViewParcelsText);
 			mImplementationp->mGroupParcelsp->setEnabled(FALSE);
 		}
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index c7c7912bf2d0f74080320472b4afdb2978a987c6..9ac88a3cc2fdaf1a325b2cfd9f4ff87a78290a06 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -473,7 +473,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
 		if (1 == count && id.isNull())
 		{
 			// Only one entry, the dummy entry.
-			mNoticesList->addSimpleItem(mNoNoticesStr,ADD_BOTTOM,FALSE);
+			mNoticesList->addCommentText(mNoNoticesStr);
 			mNoticesList->setEnabled(FALSE);
 			return;
 		}
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index a67692afa6b7eea82a56206f44ea8f892943587f..1556f24afa4462f54985c7833a89b80c2e0eb801 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1681,7 +1681,7 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
 			retrieved << "Retrieving role member mappings...";
 		}
 		mMembersList->setEnabled(FALSE);
-		mMembersList->addSimpleItem(retrieved.str());
+		mMembersList->addCommentText(retrieved.str());
 	}
 }
 
@@ -1761,7 +1761,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
 		else
 		{
 			mMembersList->setEnabled(FALSE);
-			mMembersList->addSimpleItem("No match.");
+			mMembersList->addCommentText("No match.");
 		}
 	}
 	else
@@ -2674,7 +2674,7 @@ void LLPanelGroupActionsSubTab::handleActionSelect()
 			if (!rmd) continue;
 			if ((rmd->getRoleData().mRolePowers & power_mask) == power_mask)
 			{
-				mActionRoles->addSimpleItem(rmd->getRoleData().mRoleName);
+				mActionRoles->addSimpleElement(rmd->getRoleData().mRoleName);
 			}
 		}
 	}
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 06286927d4dd29ae9461d79e8378a4a80c2f606d..c6d721faebd4ce5049fdad9f7c92dfbbdcd19d5a 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1134,8 +1134,8 @@ LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect,
 void LLPreviewLSL::callbackLSLCompileSucceeded()
 {
 	llinfos << "LSL Bytecode saved" << llendl;
-	mScriptEd->mErrorList->addSimpleItem("Compile successful!");
-	mScriptEd->mErrorList->addSimpleItem("Save complete.");
+	mScriptEd->mErrorList->addCommentText("Compile successful!");
+	mScriptEd->mErrorList->addCommentText("Save complete.");
 	closeIfNeeded();
 }
 
@@ -1681,8 +1681,8 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id,
 												  bool is_script_running)
 {
 	lldebugs << "LSL Bytecode saved" << llendl;
-	mScriptEd->mErrorList->addSimpleItem("Compile successful!");
-	mScriptEd->mErrorList->addSimpleItem("Save complete.");
+	mScriptEd->mErrorList->addCommentText("Compile successful!");
+	mScriptEd->mErrorList->addCommentText("Save complete.");
 	closeIfNeeded();
 }
 
@@ -2207,7 +2207,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,
 	else
 	{
 		llinfos << "Compile worked!" << llendl;
-		mScriptEd->mErrorList->addSimpleItem("Compile successful, saving...");
+		mScriptEd->mErrorList->addCommentText("Compile successful, saving...");
 		if(gAssetStorage)
 		{
 			llinfos << "LLLiveLSLEditor::saveAsset "
@@ -2281,7 +2281,7 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use
 		if(self)
 		{
 			// Tell the user that the compile worked.
-			self->mScriptEd->mErrorList->addSimpleItem("Save complete.");
+			self->mScriptEd->mErrorList->addCommentText("Save complete.");
 			// close the window if this completes both uploads
 			self->getWindow()->decBusyCount();
 			self->mPendingUploads--;
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index c7d2cb73186c79305bd3c3b9bade09c16acf5eaa..6acaabe0284c03c3fe659ba66d485f7fd6cb35dd 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -448,6 +448,7 @@ def construct(self):
                 self.path("res/ll_icon.ico","secondlife.ico")
                 if self.prefix("linux_tools", ""):
                         self.path("client-readme.txt","README-linux.txt")
+                        self.path("client-readme-voice.txt","README-linux-voice.txt")
                         self.path("wrapper.sh","secondlife")
                         self.path("handle_secondlifeprotocol.sh")
                         self.path("register_secondlifeprotocol.sh")
@@ -517,6 +518,16 @@ def construct(self):
                         self.path("libllkdu.so", "../bin/libllkdu.so") # llkdu goes in bin for some reason
                         self.end_prefix("lib")
 
+                # Vivox runtimes
+                if self.prefix(src="vivox-runtime/i686-linux", dst=""):
+                        self.path("SLVoice")
+                        self.end_prefix()
+                if self.prefix(src="vivox-runtime/i686-linux", dst="lib"):
+                        self.path("libopenal.so.1")
+                        self.path("libortp.so")
+                        self.path("libvivoxsdk.so")
+                        self.path("libalut.so")
+                        self.end_prefix("lib")
 
 class Linux_x86_64Manifest(LinuxManifest):
         def construct(self):