diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index c0058d534df7391d925114f07c6e5c76e7bbf4db..66c2d7ab0bd12718e1d75fc542edb96e052312f4 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -319,7 +319,7 @@ void LLToolBar::resizeButtonsInRow(std::vector<LLToolBarButton*>& buttons_in_row
 	{
 		if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL)
 		{
-			button->reshape(llclamp(button->getRect().getWidth(), button->mMinWidth, button->mMaxWidth), max_row_girth);
+			button->reshape(button->mWidthRange.clamp(button->getRect().getWidth()), max_row_girth);
 		}
 		else // VERTICAL
 		{
@@ -378,10 +378,10 @@ void LLToolBar::updateLayoutAsNeeded()
 
 	BOOST_FOREACH(LLToolBarButton* button, mButtons)
 	{
-		button->reshape(button->mMinWidth, button->mDesiredHeight);
+		button->reshape(button->mWidthRange.getMin(), button->mDesiredHeight);
 		button->autoResize();
 
-		S32 button_clamped_width = llclamp(button->getRect().getWidth(), button->mMinWidth, button->mMaxWidth);
+		S32 button_clamped_width = button->mWidthRange.clamp(button->getRect().getWidth());
 		S32 button_length = (orientation == LLLayoutStack::HORIZONTAL)
 							? button_clamped_width
 							: button->getRect().getHeight();
@@ -396,7 +396,7 @@ void LLToolBar::updateLayoutAsNeeded()
 		{
 			if (orientation == LLLayoutStack::VERTICAL)
 			{	// row girth (width in this case) is clamped to allowable button widths
-				max_row_girth = llclamp(max_row_girth, button->mMinWidth, button->mMaxWidth);
+				max_row_girth = button->mWidthRange.clamp(max_row_girth);
 			}
 
 			// make buttons in current row all same girth
@@ -543,8 +543,7 @@ LLToolBarButton::LLToolBarButton(const Params& p)
 :	LLButton(p),
 	mMouseDownX(0),
 	mMouseDownY(0),
-	mMinWidth(p.min_button_width),
-	mMaxWidth(p.max_button_width),
+	mWidthRange(p.button_width),
 	mDesiredHeight(p.desired_height),
 	mId("")
 {}
diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h
index 5d64630fa61a46ef516c0fda33b911ca9cfdd363..48ca6c62b307c761658b481322d24e35e29c1890 100644
--- a/indra/llui/lltoolbar.h
+++ b/indra/llui/lltoolbar.h
@@ -41,13 +41,11 @@ class LLToolBarButton : public LLButton
 public:
 	struct Params : public LLInitParam::Block<Params, LLButton::Params>
 	{
-		Optional<S32>	min_button_width,
-						max_button_width,
-						desired_height;
+		Optional<LLUI::Range<S32> >	button_width;
+		Optional<S32>				desired_height;
 
 		Params()
-		:	min_button_width("min_button_width", 0),
-			max_button_width("max_button_width", S32_MAX),
+		:	button_width("button_width"),
 			desired_height("desired_height", 20)
 		{}
 
@@ -62,8 +60,7 @@ class LLToolBarButton : public LLButton
 	LLCommandId		mId;
 	S32				mMouseDownX;
 	S32				mMouseDownY;
-	S32				mMinWidth;
-	S32				mMaxWidth;
+	LLUI::Range<S32> mWidthRange;
 	S32				mDesiredHeight;
 };
 
diff --git a/indra/llui/lltoolbarview.cpp b/indra/llui/lltoolbarview.cpp
index 12247519ad73a36823f65d3b9958f76e4ff841d7..49d4bfdc3c2e2a93e7749699aa53a4c99a5443e5 100644
--- a/indra/llui/lltoolbarview.cpp
+++ b/indra/llui/lltoolbarview.cpp
@@ -169,8 +169,8 @@ bool LLToolBarView::loadToolbars(bool force_default)
 	{
 		if (toolbar_set.left_toolbar.button_display_mode.isProvided())
 		{
-			U32 button_type = toolbar_set.left_toolbar.button_display_mode;
-			mToolbarLeft->setButtonType((LLToolBarEnums::ButtonType)(button_type));
+			LLToolBarEnums::ButtonType button_type = toolbar_set.left_toolbar.button_display_mode;
+			mToolbarLeft->setButtonType(button_type);
 		}
 		BOOST_FOREACH(LLCommandId::Params& command, toolbar_set.left_toolbar.commands)
 		{
@@ -181,8 +181,8 @@ bool LLToolBarView::loadToolbars(bool force_default)
 	{
 		if (toolbar_set.right_toolbar.button_display_mode.isProvided())
 		{
-			U32 button_type = toolbar_set.right_toolbar.button_display_mode;
-			mToolbarRight->setButtonType((LLToolBarEnums::ButtonType)(button_type));
+			LLToolBarEnums::ButtonType button_type = toolbar_set.right_toolbar.button_display_mode;
+			mToolbarRight->setButtonType(button_type);
 		}
 		BOOST_FOREACH(LLCommandId::Params& command, toolbar_set.right_toolbar.commands)
 		{
@@ -193,8 +193,8 @@ bool LLToolBarView::loadToolbars(bool force_default)
 	{
 		if (toolbar_set.bottom_toolbar.button_display_mode.isProvided())
 		{
-			U32 button_type = toolbar_set.bottom_toolbar.button_display_mode;
-			mToolbarBottom->setButtonType((LLToolBarEnums::ButtonType)(button_type));
+			LLToolBarEnums::ButtonType button_type = toolbar_set.bottom_toolbar.button_display_mode;
+			mToolbarBottom->setButtonType(button_type);
 		}
 		BOOST_FOREACH(LLCommandId::Params& command, toolbar_set.bottom_toolbar.commands)
 		{
@@ -223,17 +223,17 @@ void LLToolBarView::saveToolbars() const
 	LLToolBarView::ToolbarSet toolbar_set;
 	if (mToolbarLeft)
 	{
-		toolbar_set.left_toolbar.button_display_mode = (int)(mToolbarLeft->getButtonType());
+		toolbar_set.left_toolbar.button_display_mode = mToolbarLeft->getButtonType();
 		addToToolset(mToolbarLeft->getCommandsList(),toolbar_set.left_toolbar);
 	}
 	if (mToolbarRight)
 	{
-		toolbar_set.right_toolbar.button_display_mode = (int)(mToolbarRight->getButtonType());
+		toolbar_set.right_toolbar.button_display_mode = mToolbarRight->getButtonType();
 		addToToolset(mToolbarRight->getCommandsList(),toolbar_set.right_toolbar);
 	}
 	if (mToolbarBottom)
 	{
-		toolbar_set.bottom_toolbar.button_display_mode = (int)(mToolbarBottom->getButtonType());
+		toolbar_set.bottom_toolbar.button_display_mode = mToolbarBottom->getButtonType();
 		addToToolset(mToolbarBottom->getCommandsList(),toolbar_set.bottom_toolbar);
 	}
 	
diff --git a/indra/llui/lltoolbarview.h b/indra/llui/lltoolbarview.h
index 20525a22ac3110c46e97dcd3a203ad354f149a5c..c67b8d9d64d632fec3d908d4cdf3f24475f65c81 100644
--- a/indra/llui/lltoolbarview.h
+++ b/indra/llui/lltoolbarview.h
@@ -50,8 +50,8 @@ class LLToolBarView : public LLUICtrl
 	// the user folder for the user specific (saved) settings
 	struct Toolbar : public LLInitParam::Block<Toolbar>
 	{
-		Mandatory<U32>                button_display_mode;
-		Multiple<LLCommandId::Params>	commands;
+		Mandatory<LLToolBarEnums::ButtonType>	button_display_mode;
+		Multiple<LLCommandId::Params>			commands;
 		Toolbar();
 	};
 	struct ToolbarSet : public LLInitParam::Block<ToolbarSet>
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 3afb7c65a90b604f06ae3cbaf821119b135cd919..9f6fccfef657fa8d500aeda60d9d8445a1c86fd7 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -147,6 +147,132 @@ class LLUI
 {
 	LOG_CLASS(LLUI);
 public:
+	//
+	// Classes
+	//
+
+	template <typename T>
+	struct Range 
+	{
+		typedef Range<T> self_t;
+
+		struct Params : public LLInitParam::Block<Params>
+		{
+			Optional<T>	minimum,
+						maximum;
+
+			Params()
+			:	minimum("min", 0),
+				maximum("max", S32_MAX)
+			{
+
+			}
+		};
+
+		// correct for inverted params
+		Range(const Params& p = Params())
+			:	mMin(p.minimum),
+			mMax(p.maximum)
+		{
+			sanitizeRange();
+		}
+
+		Range(T minimum, T maximum)
+			:	mMin(minimum),
+			mMax(maximum)
+		{
+			sanitizeRange();
+		}
+
+		S32 clamp(T input)
+		{
+			if (input < mMin) return mMin;
+			if (input > mMax) return mMax;
+			return input;
+		}
+
+		void setRange(T minimum, T maximum)
+		{
+			mMin = minimum;
+			mMax = maximum;
+			sanitizeRange();
+		}
+
+		S32 getMin() { return mMin; }
+		S32 getMax() { return mMax; }
+
+		bool operator==(const self_t& other) const
+		{
+			return mMin == other.mMin 
+				&& mMax == other.mMax;
+		}
+	private:
+		void sanitizeRange()
+		{
+			if (mMin > mMax)
+			{
+				llwarns << "Bad interval range (" << mMin << ", " << mMax << ")" << llendl;
+				// since max is usually the most dangerous one to ignore (buffer overflow, etc), prefer it
+				// in the case of a malformed range
+				mMin = mMax;
+			}
+		}
+
+
+		T	mMin,
+			mMax;
+	};
+
+	template<typename T>
+	struct ClampedValue : public Range<T>
+	{
+		typedef Range<T> range_t;
+
+		struct Params : public LLInitParam::Block<Params, typename range_t::Params>
+		{
+			Mandatory<S32> value;
+
+			Params()
+			:	value("", 0)
+			{
+				addSynonym(value, "value");
+			}
+		};
+
+		ClampedValue(const Params& p)
+		:	range_t(p)
+		{}
+
+		ClampedValue(const range_t& range)
+		:	range_t(range)
+		{
+			// set value here, after range has been sanitized
+			mValue = clamp(0);
+		}
+
+		ClampedValue(T value, const range_t& range = range_t())
+		:	range_t(range)
+		{
+			mValue = clamp(value);
+		}
+
+		T get()
+		{
+			return mValue;
+		}
+
+		void set(T value)
+		{
+			mValue = clamp(value);
+		}
+
+
+	private:
+		T mValue;
+	};
+
+	typedef ClampedValue<S32> ClampedS32;
+
 	//
 	// Methods
 	//
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index 3dce7a939f28b1bceb9dcaae447bdd1013f67b46..9db67a15c836a82fdc351af9585349822275e88e 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -87,6 +87,7 @@ namespace LLInitParam
 
 		void setValueName(const std::string& key) {}
 		std::string getValueName() const { return ""; }
+		std::string calcValueName(const T& value) const { return ""; }
 		void clearValueName() const {}
 
 		static bool getValueFromName(const std::string& name, T& value)
@@ -124,6 +125,22 @@ namespace LLInitParam
 			return mValueName; 
 		}
 
+		std::string calcValueName(const T& value) const
+		{
+			value_name_map_t* map = getValueNames();
+			for (value_name_map_t::iterator it = map->begin(), end_it = map->end();
+				it != end_it;
+				++it)
+			{
+				if (ParamCompare<T>::equals(it->second, value))
+				{
+					return it->first;
+				}
+			}
+
+			return "";
+		}
+
 		void clearValueName() const
 		{
 			mValueName.clear();
@@ -709,18 +726,19 @@ namespace LLInitParam
 			{
 				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
 				{
-					if (!parser.writeValue(key, name_stack))
-					{
-						return;
-					}
+					parser.writeValue(key, name_stack);
 				}
 			}
 			// then try to serialize value directly
 			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue()))
 			{
-				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
+				if (!parser.writeValue(typed_param.getValue(), name_stack))
 				{
-					return;
+					std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
+					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))
+					{
+						parser.writeValue(calculated_key, name_stack);
+					}
 				}
 			}
 		}
@@ -1002,9 +1020,14 @@ namespace LLInitParam
 				if(key.empty())
 				// not parsed via name values, write out value directly
 				{
-					if (!parser.writeValue(*it, name_stack))
+					bool value_written == parser.writeValue(*it, name_stack);
+					if (!value_written)
 					{
-						break;
+						std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
+						if (!parser.writeValue(calculated_key, name_stack))
+						{
+							break;
+						}
 					}
 				}
 				else 
diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml
index 19dec78c639f8f552d20e606d6dc244d650baf65..a9345b3b0a6b46cfb8ed3849c79ef12321513752 100644
--- a/indra/newview/app_settings/toolbars.xml
+++ b/indra/newview/app_settings/toolbars.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <toolbars>
   <bottom_toolbar
-    button_display_mode="0">
+    button_display_mode="icons_with_text">
     <command name="chat"/>
     <command name="speak"/>
     <command name="places"/>
@@ -12,7 +12,7 @@
     <command name="howto"/>
   </bottom_toolbar>
   <left_toolbar
-    button_display_mode="1">
+    button_display_mode="icons_only">
     <command name="avatar"/>
     <command name="inventory"/>
     <command name="snapshot"/>
diff --git a/indra/newview/skins/default/xui/en/floater_toybox.xml b/indra/newview/skins/default/xui/en/floater_toybox.xml
index de39032cbf81ad1647fc50034fb4cd042da0b17f..972ae1487aefa0687ab5710734095c53539f3824 100644
--- a/indra/newview/skins/default/xui/en/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/en/floater_toybox.xml
@@ -48,8 +48,8 @@
     button_display_mode="icons_with_text"
     follows="all"
     left="20"
-    button_icon_and_text.max_button_width="140"
-    button_icon_and_text.min_button_width="70"
+    button_icon_and_text.button_width.max="140"
+    button_icon_and_text.button_width.min="70"
     name="toybox_toolbar"
     pad_left="5"
     pad_right="5"
diff --git a/indra/newview/skins/default/xui/en/widgets/toolbar.xml b/indra/newview/skins/default/xui/en/widgets/toolbar.xml
index 8422e3943d5decc43fa421cdb97b0a80ec25f03a..0c7e7cff5641efb5641ed99ee517b27de442fffa 100644
--- a/indra/newview/skins/default/xui/en/widgets/toolbar.xml
+++ b/indra/newview/skins/default/xui/en/widgets/toolbar.xml
@@ -12,8 +12,8 @@
                 bg_opaque_image_overlay="MouseGray"
                 background_opaque="true"/>
   <button_icon_and_text imgoverlay_label_space="7"
-                        min_button_width="70"
-                        max_button_width="140"
+                        button_width.min="70"
+                        button_width.max="140"
                         desired_height="24"
                         pad_left="10" 
                         pad_right="10"
@@ -25,8 +25,8 @@
   <button_icon pad_left="10"
                pad_right="10"
                desired_height="35"
-               min_button_width="35"
-               max_button_width="35"               
+               button_width.min="35"
+               button_width.max="35"               
                follows="left|top"
                label=""
                chrome="true"