--[[
	Functions to implement slash commands for FlexBar
	Last Modified
		12/26/2004	Initial version
		08/12/2005  Changed calls for FB_ReformGroups to either FB_ReformGroup or FB_DisbandAllGroups - Sherkhan
		08/12/2005  Added Text3, ShadeText3, JustifyText3 Fields	- Sherkhan
--]]

local util = Utility_Class:New()
local nextcommand = 0;
local currentconfig = nil
local REQUIRED = true
local STRICT = true
local OPTIONAL = false
local NON_STRICT = false
local NO_DEFAULT = nil;

function FB_Command_AddCommands(scmd)
-- Populate the command object, scmd, with the commands we want available
-- args are command, function, group, usage
	scmd:AddCommand("info", FB_Command_ToggleButtonInfo, "misc",
		"/Flexbar Info")

	scmd:AddCommand("scripts", FB_Command_Scripts, "misc",
		"/Flexbar Scripts")

	scmd:AddCommand("events", FB_DisplayEventEditor, "misc",
		"/Flexbar Events")

	scmd:AddCommand("perf", FB_Show_PerformanceOptions, "misc",
		"/Flexbar Perf")

	scmd:AddCommand("autoitems", FB_DisplayAutoItems, "misc",
		"/Flexbar AutoItems")

	scmd:AddCommand("options", FB_ShowGlobalOptions, "misc",
		"/Flexbar Options")

	scmd:AddCommand("safeload", FB_Command_SafeLoad, "misc",
		"/Flexbar SafeLoad State=<'on' | 'off'>")
		scmd:AddParam("safeload","state",REQUIRED,STRICT,{"string"},{"on","On","off","Off"},NO_DEFAULT)
		
	scmd:AddCommand("loadprofile", FB_Command_LoadProfile, "misc",
		"/Flexbar LoadProfile Profile='profile'")
		scmd:AddParam("loadprofile","profile",REQUIRED,NON_STRICT,{"string"},nil,NO_DEFAULT)
		
	scmd:AddCommand("deleteprofile", FB_Command_DeleteProfile, "misc",
		"/Flexbar DeleteProfile Profile='profile' confirm='yes'")
		scmd:AddParam("deleteprofile","profile",REQUIRED,NON_STRICT,{"string"},nil,NO_DEFAULT)
		scmd:AddParam("deleteprofile","confirm",REQUIRED,STRICT,{"string"},{"yes","Yes"}, nil)
		
	scmd:AddCommand("saveprofile", FB_Command_SaveProfile, "misc",
		"/Flexbar SaveProfile Profile='profile'")
		scmd:AddParam("saveprofile","profile",REQUIRED,NON_STRICT,{"string"},nil,NO_DEFAULT)
		
	scmd:AddCommand("listprofiles", FB_Command_ListProfiles, "misc",
		"/FlexBar ListProfiles")
		
	scmd:AddCommand("remap", FB_Command_ReMap, "misc",
		"/FlexBar ReMap Button=<buttons> Base=<id> [Reset='True']")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("remap","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("remap","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("remap","base"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=120}, nil)
		scmd:AddParam("remap","toggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("remap","reset" ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("remap","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("remap","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("remap","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("remap","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("remap","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("remap","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("echo", FB_Command_Echo, "misc",
		"/FlexBar Echo Button=<buttons> Base=<id> [Reset='True']")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("echo","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("echo","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("echo","base"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("echo","toggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("echo","reset" ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("echo","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("echo","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("echo","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("echo","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("echo","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("echo","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("advanced", FB_Command_Advanced, "misc",
		"/FlexBar Advanced Button=<buttons> state=<'on' | 'off'>")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("advanced","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("advanced","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("advanced","state" ,REQUIRED,NON_STRICT,{"string"},{"on","On","off","Off"}, nil)

	scmd:AddCommand("use", FB_Command_Use, "misc",
		"/FlexBar Use Button=<buttons>")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("use","button",REQUIRED,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("use","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("use","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("use","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("use","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("use","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("use","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("runscript", FB_Command_RunScript, "misc",
		"/FlexBar RunScript Script='scriptname'")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("runscript","script",REQUIRED,NON_STRICT,{"string"},nil, nil)
		scmd:AddParam("runscript","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("runscript","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("runscript","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("runscript","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("runscript","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("runscript","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("runmacro", FB_Command_RunMacro, "misc",
		"/FlexBar RunMacro Macro='macroname'")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("runmacro","macro",REQUIRED,NON_STRICT,{"string","table"},nil, nil)
		scmd:AddParam("runmacro","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("runmacro","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("runmacro","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("runmacro","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("runmacro","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("runmacro","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("resetall", FB_Command_ResetAll, "misc",
		"/FlexBar ResetAll Confirm='yes'")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("resetall","confirm",REQUIRED,STRICT,{"string"},{"yes","Yes"}, nil)

	scmd:AddCommand("restore", FB_Command_Restore, "misc",
		"/FlexBar Restore Confirm='yes'")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("restore","confirm",REQUIRED,STRICT,{"string"},{"yes","Yes"}, nil)

	scmd:AddCommand("loadconfig", FB_Command_LoadConfig, "misc",
		"/FlexBar LoadConfig Config='ConfigName'")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("loadconfig","config",REQUIRED,NON_STRICT,{"string"},nil, nil)

	scmd:AddCommand("hidegrid", FB_Command_HideGrid, "misc",
		"/FlexBar HideGrid Button=<buttons>")
		scmd:AddParam("hidegrid","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("hidegrid","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("hidegrid","toggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("showgrid", FB_Command_ShowGrid, "misc",
		"/FlexBar ShowGrid Button=<buttons>")
		scmd:AddParam("showgrid","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("showgrid","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("showgrid","toggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("lockicon", FB_Command_LockIcon, "misc",
		"/FlexBar LockIcon Button=<buttons> [Off='true']")
		scmd:AddParam("lockicon","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("lockicon","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("lockicon","off"   ,OPTIONAL,STRICT,{"string"},{"true", "True"},nil)

	scmd:AddCommand("text", FB_Command_Text, "misc",
		"/FlexBar Text Button=<buttons> Text=<text>")
		scmd:AddParam("text","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("text","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("text","text"  ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("text","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("text","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("text","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("text","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("text","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("text","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("text2", FB_Command_Text2, "misc",
		"/FlexBar Text2 Button=<buttons> Text=<text>")
		scmd:AddParam("text2","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("text2","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("text2","text"  ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("text2","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("text2","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("text2","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("text2","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("text2","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("text2","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("text3", FB_Command_Text3, "misc",
		"/FlexBar Text3 Button=<buttons> Text=<text>")
		scmd:AddParam("text3","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("text3","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("text3","text"  ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("text3","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("text3","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("text3","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("text3","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("text3","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("text3","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("justifytext", FB_Command_JustifyText, "misc",
		"/FlexBar JustifyText Button=<buttons> Pos=<position>")
		scmd:AddParam("justifytext","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("justifytext","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("justifytext","pos"  ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("justifytext","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("justifytext","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("justifytext","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("justifytext","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("justifytext","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("justifytext","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("justifytext2", FB_Command_JustifyText2, "misc",
		"/FlexBar Justifytext2 Button=<buttons> Pos=<position>")
		scmd:AddParam("justifytext2","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("justifytext2","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("justifytext2","pos"  ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("justifytext2","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("justifytext2","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("justifytext2","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("justifytext2","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("justifytext2","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("justifytext2","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("justifytext3", FB_Command_JustifyText3, "misc",
		"/FlexBar Justifytext3 Button=<buttons> Pos=<position>")
		scmd:AddParam("justifytext3","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("justifytext3","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("justifytext3","pos"  ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("justifytext3","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("justifytext3","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("justifytext3","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("justifytext3","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("justifytext3","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("justifytext3","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("verbose", FB_Command_Verbose, "misc",
		"/FlexBar Verbose State=<'on' | 'off'>")
		scmd:AddParam("verbose","state",REQUIRED,STRICT,{"string"},{"on","On","Off","off"},"on")
		
	scmd:AddCommand("tooltip", FB_Command_Tooltip, "misc",
		"/FlexBar Tooltip State=<'on' | 'off'>")
		scmd:AddParam("tooltip","state",REQUIRED,STRICT,{"string"},{"on","On","Off","off"},"on")
		
	scmd:AddCommand("raise", FB_Command_Raise, "misc",
		"/FlexBar Raise Event=<event> Source=<source> In=<seconds>")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("raise","event" ,REQUIRED,NON_STRICT,{"string"},NO_BOUNDS,NO_DEFAULT)
		scmd:AddParam("raise","source",OPTIONAL,NON_STRICT,NO_TYPES,NO_BOUNDS,NO_DEFAULT)
		scmd:AddParam("raise","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("raise","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("raise","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("raise","in"    ,OPTIONAL,STRICT,{"number"},{lowerbound=0},0)
		scmd:AddParam("raise","name"  ,REQUIRED,NON_STRICT,{"string"},nil,NO_DEFAULT)
		scmd:AddParam("raise","toggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("raise","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("raise","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("flexscript", FB_Command_FlexScript, "appearance",
		"/FlexBar FlexScript ID=<ID> Texture='texture' Script='script' Name='Name' [Reset='true'] [Toggle='true']")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("flexscript","id"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("flexscript","texture" ,REQUIRED,STRICT,{"string"},nil, "")
		scmd:AddParam("flexscript","toggle"  ,OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("flexscript","reset"   ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("flexscript","name"  ,REQUIRED,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("flexscript","script",REQUIRED,NON_STRICT,{"string"},nil, nil)
		
	scmd:AddCommand("flexmacro", FB_Command_FlexMacro, "appearance",
		"/FlexBar FlexMacro ID=<ID> Texture='texture' Macro='macro' Name='Name' [Reset='true'] [Toggle='true']")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("flexmacro","id"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("flexmacro","texture" ,REQUIRED,STRICT,{"string"},nil, "")
		scmd:AddParam("flexmacro","toggle"  ,OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("flexmacro","reset"   ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("flexmacro","name"  ,REQUIRED,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("flexmacro","macro",REQUIRED,NON_STRICT,{"string","table"},nil, nil)
		
	scmd:AddCommand("flexpet", FB_Command_FlexPet, "appearance",
		"/FlexBar FlexPet ID=<ID> PetID=<petid> [Reset='true'] [Toggle='true']")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("flexpet","id"  	,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("flexpet","toggle"  ,OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("flexpet","reset"   ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("flexpet","petid"	,REQUIRED,NON_STRICT,{"number"},nil, nil)
		
	scmd:AddCommand("clearflex", FB_Command_ClearFlex, "appearance",
		"/FlexBar ClearFlex ID=<ID>")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("clearflex","id"  	,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		
	scmd:AddCommand("disable", FB_Command_Disable, "misc",
		"/FlexBar Disable Button=<buttons> state=<'on' | 'off'>")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("disable","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, NO_DEFAULT)
		scmd:AddParam("disable","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, NO_DEFAULT)
		scmd:AddParam("disable","state" ,REQUIRED,NON_STRICT,{"string"},{"on","On","off","Off"}, NO_DEFAULT)
		scmd:AddParam("disable","toggle",OPTIONAL,STRICT,{"string"},{"true"},NO_DEFAULT)
		scmd:AddParam("disable","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("disable","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("disable","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("disable","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("disable","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("disable","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)

	scmd:AddCommand("hide", FB_Command_Hide, "appearance",
		"/FlexBar Hide Button=<buttons>")
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("hide","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("hide","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("hide","toggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("hide","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("hide","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("hide","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("hide","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("hide","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("hide","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("show", FB_Command_Show, "appearance",
		"/FlexBar Show Button=<buttons>")
		scmd:AddParam("show","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("show","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("show","toggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("show","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("show","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("show","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("show","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("show","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("show","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("fade", FB_Command_Fade, "appearance",
		"/FlexBar Fade Button=<buttons> Alpha=<alpha>")
		scmd:AddParam("fade","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("fade","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("fade","alpha" ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=10},nil)
		scmd:AddParam("fade","toggle",OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=10},nil)
		scmd:AddParam("fade","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("fade","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("fade","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("fade","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("fade","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("fade","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("scale", FB_Command_Scale, "appearance",
		"/FlexBar Scale Button=<buttons> Scale=<scale>")
		scmd:AddParam("scale","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("scale","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("scale","scale" ,REQUIRED,STRICT,{"number"},{lowerbound=5,upperbound=50},nil)
		scmd:AddParam("scale","toggle",OPTIONAL,STRICT,{"number"},{lowerbound=5,upperbound=50},nil)
		scmd:AddParam("scale","reset" ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("scale","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("scale","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("scale","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("scale","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("scale","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("scale","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("shade", FB_Command_Shade, "appearance",
		"/FlexBar Shade Button=<buttons> Color=<[r g b]>")
		scmd:AddParam("shade","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("shade","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("shade","color" ,REQUIRED,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shade","toggle",OPTIONAL,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shade","reset" ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("shade","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("shade","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shade","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("shade","iftarg",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shade","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("shade","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("shade","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("shadetext", FB_Command_ShadeText, "appearance",
		"/FlexBar ShadeText Button=<buttons> Color=<[r g b]>")
		scmd:AddParam("shadetext","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("shadetext","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("shadetext","color" ,REQUIRED,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shadetext","toggle",OPTIONAL,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shadetext","reset" ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("shadetext","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("shadetext","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shadetext","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("shadetext","iftarg",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shadetext","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("shadetext","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("shadetext","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("shadetext2", FB_Command_ShadeText2, "appearance",
		"/FlexBar ShadeText2 Button=<buttons> Color=<[r g b]>")
		scmd:AddParam("shadetext2","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("shadetext2","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("shadetext2","color" ,REQUIRED,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shadetext2","toggle",OPTIONAL,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shadetext2","reset" ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("shadetext2","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("shadetext2","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shadetext2","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("shadetext2","iftarg",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shadetext2","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("shadetext2","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("shadetext2","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("shadetext3", FB_Command_ShadeText3, "appearance",
		"/FlexBar ShadeText3 Button=<buttons> Color=<[r g b]>")
		scmd:AddParam("shadetext3","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("shadetext3","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("shadetext3","color" ,REQUIRED,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shadetext3","toggle",OPTIONAL,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shadetext3","reset" ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("shadetext3","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("shadetext3","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shadetext3","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("shadetext3","iftarg",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shadetext3","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("shadetext3","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("shadetext3","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("shadetooltip", FB_Command_ShadeToolTip, "appearance",
		"/FlexBar ShadeToolTip Color=<[r g b]>")
		scmd:AddParam("shadetext","color" ,REQUIRED,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shadetext","toggle",OPTIONAL,STRICT,{"number","table"},{lowerbound=0,upperbound=10},nil)
		scmd:AddParam("shadetext","reset" ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("shadetext","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("shadetext","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shadetext","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("shadetext","iftarg",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("shadetext","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("shadetext","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("shadetext","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
	
	
	scmd:AddCommand("settexture", FB_Command_SetTexture, "appearance",
		"/FlexBar SetTexture Button=<button> Texture='texture' [Reset='True']")
		-- populate the parameter list for this command
		-- arguments are: command, parameter name, required, strict, types, allowed, default
		scmd:AddParam("settexture","id"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("settexture","texture" ,OPTIONAL,STRICT,{"string"},nil, "")
		scmd:AddParam("settexture","toggle"  ,OPTIONAL,STRICT,{"string"},{"true"},nil)
		scmd:AddParam("settexture","reset"   ,OPTIONAL,NON_STRICT,{"string"},{"true"},nil)
		scmd:AddParam("settexture","on"      ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("settexture","target"  ,OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("settexture","if"      ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("settexture","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("settexture","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("settexture","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("lock", FB_Command_Lock, "movement",
		"/FlexBar Lock Button=<buttons>")
		scmd:AddParam("lock","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons},nil)
		scmd:AddParam("lock","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons},nil)
		
	scmd:AddCommand("unlock", FB_Command_Unlock, "movement",
		"/FlexBar Unlock Button=<buttons>")
		scmd:AddParam("unlock","button",OPTIONAL,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons},nil)
		scmd:AddParam("unlock","group" ,OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons},nil)
		
	scmd:AddCommand("moveabs", FB_Command_MoveABS, "movement",
		"/FlexBar MoveABS Button=<button> XX=<x-coord> YY=<y-coord>")
		scmd:AddParam("moveabs","button",REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("moveabs","xx"    ,REQUIRED,STRICT,{"number"},nil,nil)
		scmd:AddParam("moveabs","yy"    ,REQUIRED,STRICT,{"number"},nil,nil)
		scmd:AddParam("moveabs","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("moveabs","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("moveabs","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("moveabs","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("moveabs","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("moveabs","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("moverel", FB_Command_MoveRel, "movement",
		"/FlexBar MoveRel Button=<button> trgBtn=<button> dX=<x-coord> dY=<y-coord>")
		scmd:AddParam("moverel","button",REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("moverel","trgbtn",REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("moverel","dx"    ,REQUIRED,STRICT,{"number"},nil,nil)
		scmd:AddParam("moverel","dy"    ,REQUIRED,STRICT,{"number"},nil,nil)
		scmd:AddParam("moverel","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("moverel","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("moverel","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("moverel","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("moverel","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("moverel","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("movetomouse", FB_Command_MoveToMouse, "movement",
		"/FlexBar MoveRel Button=<button> target=<button> dX=<x-coord> dY=<y-coord>")
		scmd:AddParam("movetomouse","button",REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("movetomouse","dx"    ,REQUIRED,STRICT,{"number"},nil,nil)
		scmd:AddParam("movetomouse","dy"    ,REQUIRED,STRICT,{"number"},nil,nil)
		scmd:AddParam("movetomouse","on"    ,OPTIONAL,NON_STRICT,{"string"},FBEventList,nil)
		scmd:AddParam("movetomouse","target",OPTIONAL,NON_STRICT,nil,nil,nil)
		scmd:AddParam("movetomouse","if"    ,OPTIONAL,NON_STRICT,{"string"},FBConditionList,nil)
		scmd:AddParam("movetomouse","in"    ,OPTIONAL,NON_STRICT,{"number"},nil,nil)
		scmd:AddParam("movetomouse","tname" ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("movetomouse","ttoggle",OPTIONAL,STRICT,{"string"},{"true"},nil)
		
	scmd:AddCommand("group", FB_Command_Group, "group",
		"/FlexBar Group Button=<buttons> Anchor=<button>")
		scmd:AddParam("group","button",REQUIRED,STRICT,{"number","table"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("group","anchor",REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons},nil)
		
	scmd:AddCommand("ungroup", FB_Command_Ungroup, "group",
		"/FlexBar Ungroup Group=<group>")
		scmd:AddParam("ungroup","group",REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		
	scmd:AddCommand("circlegroup", FB_Command_CircleGroup, "group",
		"/FlexBar CircleGroup Group=<group>")
		scmd:AddParam("circlegroup","group"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("circlegroup","padding",OPTIONAL,STRICT,{"number"},{lowerbound=0},0)
		
	scmd:AddCommand("horizontalgroup", FB_Command_HorizontalGroup, "group",
		"/FlexBar HorizontalGroup Group=<group> Height=<height> Padding=<pixels>")
		scmd:AddParam("horizontalgroup","group"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("horizontalgroup","padding",OPTIONAL,STRICT,{"number"},{lowerbound=0},0)
		scmd:AddParam("horizontalgroup","height" ,OPTIONAL,STRICT,{"number"},{lowerbound=1},1)
		
	scmd:AddCommand("verticalgroup", FB_Command_VerticalGroup, "group",
		"/FlexBar VerticalGroup Group=<group> Width=<width> Padding=<pixels>")
		scmd:AddParam("verticalgroup","group"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("verticalgroup","padding",OPTIONAL,STRICT,{"number"},{lowerbound=0},0)
		scmd:AddParam("verticalgroup","width" ,OPTIONAL,STRICT,{"number"},{lowerbound=1},1)
		
	scmd:AddCommand("menupopup", FB_Command_MenuPopUp, "group",
		"/FlexBar MenuPopUp Group=<group> Trigger=<button> Align=<alignment> Texture=<texture> Height=<height> Width=<width> Padding=<pixels>")
		scmd:AddParam("menupopup","group"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("menupopup","trigger"  ,REQUIRED,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons}, nil)
		scmd:AddParam("menupopup","align"  ,OPTIONAL,NON_STRICT,{"string"},nil,nil)
		scmd:AddParam("menupopup","padding",OPTIONAL,STRICT,{"number"},{lowerbound=0},0)
		scmd:AddParam("menupopup","height" ,OPTIONAL,STRICT,{"number"},{lowerbound=1},1)
		scmd:AddParam("menupopup","width" ,OPTIONAL,STRICT,{"number"},{lowerbound=1},1)
		scmd:AddParam("menupopup","texture" ,OPTIONAL,STRICT,{"string"},nil, "")
		
	scmd:AddCommand("listgroups", FB_Command_ListGroups, "group",
		"/FlexBar ListGroups [Group=<groups>]")
		scmd:AddParam("listgroups","group",OPTIONAL,STRICT,{"number"},{lowerbound=1,upperbound=FBNumButtons},nil)
		
	scmd:AddCommand("listevents", FB_Command_ListEvents, "events",
		"/FlexBar ListEvents")
		
	scmd:AddCommand("deleteevent", FB_Command_DeleteEvent, "events",
		"/FlexBar DeleteEvent event=<event number>")
		scmd:AddParam("deleteevent","event",REQUIRED,STRICT,{"number"},{lowerbound=1},nil)
		
	scmd:AddCommand("mischelp",  FB_Command_DisplayMisc, "main",
		"/FlexBar MiscHelp - for miscellaneous options")
	scmd:AddCommand("eventhelp", FB_Command_DisplayEvents, "main",
		"/FlexBar EventHelp - for options on events")
	scmd:AddCommand("grouphelp", FB_Command_DisplayGroup, "main",
		"/FlexBar GroupHelp - for options on grouping buttons")
	scmd:AddCommand("appearance", FB_Command_DisplayAppearance, "main",
		"/FlexBar Appearance - for options on button appearance")
	scmd:AddCommand("movement", FB_Command_DisplayMovement, "main",
		"/FlexBar Movement - for options on moving buttons")

	scmd:AddCommand("test", FB_Command_Test, "test",
		"/Flexbar Test arg1=<string> arg2=<number> arg3=<optional> arg4=<required>")
		scmd:AddParam("test","arg1",true,nil,{"string"},nil, nil)
		scmd:AddParam("test","arg2",true,nil,{"number"},{lowerbound=5, upperbound=10}, nil)
		scmd:AddParam("test","arg3",false,nil,{"number", "table"},{1,3,5}, 10)
		scmd:AddParam("test","arg4",true,true,{"string", "table"},{"true", "false"}, nil)
end

function FB_Command_Test(msg)
	local args = FBcmd:GetParameters(msg)
	if not FBcmd:CheckParams("test", args) then
		util:Print("not valid")
	else
		util:Print("valid")
	end
end

-- Usage display functions
function FB_Command_DisplayMisc()
	FBcmd:DisplayUsage("misc")
	util:Print(FB_DISPLAY_MISCHELP_ADD)
end

function FB_Command_DisplayAppearance()
	FBcmd:DisplayUsage("appearance")
	util:Print(FB_DISPLAY_APPHELP_ADD)
end

function FB_Command_DisplayGroup()
	FBcmd:DisplayUsage("group")
	util:Print(FB_DISPLAY_GROUPHELP_ADD)
end

function FB_Command_DisplayMovement()
	FBcmd:DisplayUsage("movement")
	util:Print(FB_DISPLAY_MOVEHELP_ADD)
end

function FB_Command_DisplayEvents()
	FBcmd:DisplayUsage("events")
end

-- Appearance command handlers

function FB_Command_Hide(msg)
-- Hide the buttons specified in Button=<buttons>
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args = FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("hide", args) then return end 
		-- In order to allow group= and button= interchangeably they had to both be optional
		-- check here for one or the other
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("hide", args) then return end
	end
	
	if FB_SetCommandTimer("hide", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	-- get button list
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if hidden and toggle exists then unhide
		if args["toggle"] and FBState[buttons[index]]["hidden"] then
			FBState[buttons[index]]["hidden"] = nil
		else
			FBState[buttons[index]]["hidden"] = true
		end
		-- Originally called ApplySettings at the end of the function - but the fact that
		-- On events go through here too requires that it not do potentially expensive operations
		-- So the call to apply the specific setting for only the buttons that are affected goes here
		FB_ApplyHidden(buttons[index])
		-- And we only save the changed setting
		FBSavedProfile[FBProfileName][buttons[index]].State["hidden"] = FBState[buttons[index]]["hidden"]
		FB_Report(button:GetName() .. " hidden")
	end
end

function FB_Command_Show(msg)
-- Show the buttons specified in Button=<buttons>
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("show", args) then return end 
		-- In order to allow group= and button= interchangeably they had to both be optional
		-- check here for one or the other
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("show", args) then return end
	end
	
	if FB_SetCommandTimer("show", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end
-- get button list
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end

	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if not hidden and toggle exists then hide
		if args["toggle"] and not FBState[buttons[index]]["hidden"] then
			FBState[buttons[index]]["hidden"] = true
		else
			FBState[buttons[index]]["hidden"] = nil
		end
		-- Originally called ApplySettings at the end of the function - but the fact that
		-- On events go through here too requires that it not do potentially expensive operations
		-- So the call to apply the specific setting for only the buttons that are affected goes here
		FB_ApplyHidden(buttons[index])
		-- And we only save the changed setting
		FBSavedProfile[FBProfileName][buttons[index]].State["hidden"] = FBState[buttons[index]]["hidden"]
		FB_Report(button:GetName() .. " unhidden")
	end
end

function FB_Command_Fade(msg)
-- Change the alpah for the buttons specified in Button=<buttons>
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("fade", args) then return end 
		-- In order to allow group= and button= interchangeably they had to both be optional
		-- check here for one or the other
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("fade", args) then return end
	end
	
	if FB_SetCommandTimer("fade", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if toggle, and button already has the set alpha, then toggle to toggle alpha
		if FBState[buttons[index]]["alpha"] == nil then FBState[buttons[index]]["alpha"] = 1 end
		if args["toggle"] and (FBState[buttons[index]]["alpha"]*10) == args["alpha"] then
			FBState[buttons[index]]["alpha"] = args["toggle"] / 10
		else
			FBState[buttons[index]]["alpha"] = args["alpha"] / 10
		end
		-- Originally called ApplySettings at the end of the function - but the fact that
		-- On events go through here too requires that it not do potentially expensive operations
		-- So the call to apply the specific setting for only the buttons that are affected goes here
		FB_ApplyAlpha(buttons[index])
		-- And we only save the changed setting
		FBSavedProfile[FBProfileName][buttons[index]].State["alpha"] = FBState[buttons[index]]["alpha"]
		FB_Report(button:GetName() .. format(" alpha set to %.2f",args["alpha"]/10))
	end
end

function FB_Command_Scale(msg)
-- Show the buttons specified in Button=<buttons>
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("scale", args) then return end 
		-- In order to allow group= and button= interchangeably they had to both be optional
		-- check here for one or the other
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("scale", args) then return end
	end
	
	if FB_SetCommandTimer("scale", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if toggle, and button already has the set alpha, then toggle to toggle alpha
		if FBState[buttons[index]]["scale"] == nil then FBState[buttons[index]]["scale"] = 1 end
		if args["toggle"] and (FBState[buttons[index]]["scale"]*10) == args["scale"] then
			FBState[buttons[index]]["scale"] = args["toggle"] / 10
		else
			FBState[buttons[index]]["scale"] = args["scale"] / 10
		end
		if args["reset"] then
			FBState[buttons[index]]["scale"] = nil
		end
		-- Originally called ApplySettings at the end of the function - but the fact that
		-- On events go through here too requires that it not do potentially expensive operations
		-- So the call to apply the specific setting for only the buttons that are affected goes here
		FB_ApplyScale(buttons[index])
		-- And we only save the changed setting
		FBSavedProfile[FBProfileName][buttons[index]].State["scale"] = FBState[buttons[index]]["scale"]
		if FBState[buttons[index]]["scale"] then 
			FB_Report(button:GetName() .. format(" scale set to %.2f",args["scale"]/10)) 
		else
			FB_Report(button:GetName() .. format(" scale is reset"))
		end
	end
end

local colortable = {1,1,1}
local colortable2 = {1,1,1}
function FB_Command_Shade(msg)
	local index
-- Shade the buttons specified in Button=<buttons> with the color in Color=
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("shade", args) then return end 
		-- In order to allow group= and button= interchangeably they had to both be optional
		-- check here for one or the other
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		-- advanced checks that aren't automatic
		if 	type(args["color"]) ~= "table" or args["color"][3] == nil or
			(args["toggle"] and (type(args["toggle"]) ~= "table" or args["toggle"][3] == nil)) then
			util:Print("Error: Color not in correct format")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("shade", args) then return end
	end

	if FB_SetCommandTimer("shade", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,3 do
		colortable[index] = args["color"][index] / 10
		if args["toggle"] then colortable2[index] = args["toggle"][index] / 10 end
	end
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if toggle, and button already the color specified, then toggle then go to toggle color
		if FBState[buttons[index]]["icon"] == nil then FBState[buttons[index]]["icon"] = {1, 1, 1} end
		if 	args["toggle"] and 
			colortable[1] == FBState[buttons[index]]["icon"][1] and
			colortable[2] == FBState[buttons[index]]["icon"][2] and
			colortable[3] == FBState[buttons[index]]["icon"][3] then
			colortable[1] = colortable2[1]
			colortable[2] = colortable2[2]
			colortable[3] = colortable2[3]
		elseif args["reset"] then
			colortable[1] = nil
			colortable[2] = nil
			colortable[3] = nil
			FBState[buttons[index]]["coloring"] = "resetting"
			FB_Report(button:GetName() .. " has had its color reset")
		end
		if colortable[1] then 
			FBState[buttons[index]]["icon"][1] = colortable[1] 
			FBState[buttons[index]]["icon"][2] = colortable[2] 
			FBState[buttons[index]]["icon"][3] = colortable[3] 
			FB_Report(button:GetName() .. format(" color set to %.2f, %.2f, %.2f",
				colortable[1],colortable[1],colortable[1]))
		else
			FBState[buttons[index]]["icon"] = nil
		end
		-- Simply having the state in effect will change the color, but save the changed setting
		-- and avoid a call to apply settings
		if FBState[buttons[index]]["icon"] then
			if not FBSavedProfile[FBProfileName][buttons[index]].State["icon"] then
				FBSavedProfile[FBProfileName][buttons[index]].State["icon"] = {}
			end
			FBSavedProfile[FBProfileName][buttons[index]].State["icon"][1] = colortable[1]
			FBSavedProfile[FBProfileName][buttons[index]].State["icon"][2] = colortable[2]
			FBSavedProfile[FBProfileName][buttons[index]].State["icon"][3] = colortable[3]
		else
			FBSavedProfile[FBProfileName][buttons[index]].State["icon"] = FBState[buttons[index]]["icon"]
		end
	end
end

function FB_Command_ShadeText(msg)
-- Shade the buttons specified in Button=<buttons> with the color in Color=
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("shadetext", args) then return end 
		-- In order to allow group= and button= interchangeably they had to both be optional
		-- check here for one or the other
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		-- advanced checks that aren't automatic
		if 	type(args["color"]) ~= "table" or args["color"][3] == nil or
			(args["toggle"] and (type(args["toggle"]) ~= "table" or args["toggle"][3] == nil)) then
			util:Print("Error: Color not in correct format")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("shadetext", args) then return end
	end

	if FB_SetCommandTimer("shadetext", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,3 do
		colortable[index] = args["color"][index] / 10
		if args["toggle"] then colortable2[index] = args["toggle"][index] / 10 end
	end
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if toggle, and button already the color specified, then toggle then go to toggle color
		if FBState[buttons[index]]["hotkeycolor"] == nil then FBState[buttons[index]]["hotkeycolor"] = {1, 1, 1} end
		if 	args["toggle"] and 
			colortable[1] == FBState[buttons[index]]["hotkeycolor"][1] and
			colortable[2] == FBState[buttons[index]]["hotkeycolor"][2] and
			colortable[3] == FBState[buttons[index]]["hotkeycolor"][3] then
			colortable[1] = colortable2[1]
			colortable[2] = colortable2[2]
			colortable[3] = colortable2[3]
		elseif args["reset"] then
			colortable[1] = nil
			colortable[2] = nil
			colortable[3] = nil
			FB_Report("text 1 has had its color reset")
			getglobal(button:GetName() .. "HotKey"):SetVertexColor(.6,.6,.6)
		end
		if colortable[1] then 
			FBState[buttons[index]]["hotkeycolor"][1] = colortable[1] 
			FBState[buttons[index]]["hotkeycolor"][2] = colortable[2] 
			FBState[buttons[index]]["hotkeycolor"][3] = colortable[3] 
			FB_Report(button:GetName() .. format(" color set to %.2f, %.2f, %.2f",
				colortable[1],colortable[2],colortable[3]))
		else
			FBState[buttons[index]]["hotkeycolor"] = nil
		end
		-- Simply having the state in effect will change the color, but save the changed setting
		-- and avoid a call to apply settings
		if FBState[buttons[index]]["hotkeycolor"] then
			if not FBSavedProfile[FBProfileName][buttons[index]].State["hotkeycolor"] then
				FBSavedProfile[FBProfileName][buttons[index]].State["hotkeycolor"] = {}
			end
			FBSavedProfile[FBProfileName][buttons[index]].State["hotkeycolor"][1] = colortable[1]
			FBSavedProfile[FBProfileName][buttons[index]].State["hotkeycolor"][2] = colortable[2]
			FBSavedProfile[FBProfileName][buttons[index]].State["hotkeycolor"][3] = colortable[3]
		else
			FBSavedProfile[FBProfileName][buttons[index]].State["hotkeycolor"] = FBState[buttons[index]]["hotkeycolor"]
		end
		FB_TextSub(buttons[index])
	end
end

function FB_Command_ShadeText2(msg)
-- Shade the buttons specified in Button=<buttons> with the color in Color=
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("shadetext2", args) then return end 
		-- In order to allow group= and button= interchangeably they had to both be optional
		-- check here for one or the other
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		-- advanced checks that aren't automatic
		if 	type(args["color"]) ~= "table" or args["color"][3] == nil or
			(args["toggle"] and (type(args["toggle"]) ~= "table" or args["toggle"][3] == nil)) then
			util:Print("Error: Color not in correct format")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("shadetext2", args) then return end
	end

	if FB_SetCommandTimer("shadetext2", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,3 do
		colortable[index] = args["color"][index] / 10
		if args["toggle"] then colortable2[index] = args["toggle"][index] / 10 end
	end
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if toggle, and button already the color specified, then toggle then go to toggle color
		if FBState[buttons[index]]["text2color"] == nil then FBState[buttons[index]]["text2color"] = {1, 1, 1} end
		if 	args["toggle"] and 
			colortable[1] == FBState[buttons[index]]["text2color"][1] and
			colortable[2] == FBState[buttons[index]]["text2color"][2] and
			colortable[3] == FBState[buttons[index]]["text2color"][3] then
			colortable[1] = colortable2[1]
			colortable[2] = colortable2[2]
			colortable[3] = colortable2[3]
		elseif args["reset"] then
			colortable[1] = nil
			colortable[2] = nil
			colortable[3] = nil
			FB_Report("text 1 has had its color reset")
			getglobal(button:GetName() .. "Text2"):SetVertexColor(.6,.6,.6)
		end
		if colortable[1] then 
			FBState[buttons[index]]["text2color"][1] = colortable[1]
			FBState[buttons[index]]["text2color"][2] = colortable[2]
			FBState[buttons[index]]["text2color"][3] = colortable[3]
			FB_Report(button:GetName() .. format(" color set to %.2f, %.2f, %.2f",
				colortable[1],colortable[2],colortable[3]))
		else
			FBState[buttons[index]]["text2color"] = nil
		end
		-- Simply having the state in effect will change the color, but save the changed setting
		-- and avoid a call to apply settings
		if FBState[buttons[index]]["text2color"] then
			if not FBSavedProfile[FBProfileName][buttons[index]].State["text2color"] then
				FBSavedProfile[FBProfileName][buttons[index]].State["text2color"] = {}
			end
			FBSavedProfile[FBProfileName][buttons[index]].State["text2color"][1] = colortable[1]
			FBSavedProfile[FBProfileName][buttons[index]].State["text2color"][2] = colortable[2]
			FBSavedProfile[FBProfileName][buttons[index]].State["text2color"][3] = colortable[3]
		else
			FBSavedProfile[FBProfileName][buttons[index]].State["text2color"] = FBState[buttons[index]]["text2color"]
		end
		FB_TextSub(buttons[index])
	end
end

function FB_Command_ShadeText3(msg)
-- Shade the buttons specified in Button=<buttons> with the color in Color=
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("shadetext3", args) then return end 
		-- In order to allow group= and button= interchangeably they had to both be optional
		-- check here for one or the other
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		-- advanced checks that aren't automatic
		if 	type(args["color"]) ~= "table" or args["color"][3] == nil or
			(args["toggle"] and (type(args["toggle"]) ~= "table" or args["toggle"][3] == nil)) then
			util:Print("Error: Color not in correct format")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("shadetext3", args) then return end
	end

	if FB_SetCommandTimer("shadetext3", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,3 do
		colortable[index] = args["color"][index] / 10
		if args["toggle"] then colortable2[index] = args["toggle"][index] / 10 end
	end
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if toggle, and button already the color specified, then toggle then go to toggle color
		if FBState[buttons[index]]["text3color"] == nil then FBState[buttons[index]]["text3color"] = {1, 1, 1} end
		if 	args["toggle"] and 
			colortable[1] == FBState[buttons[index]]["text3color"][1] and
			colortable[2] == FBState[buttons[index]]["text3color"][2] and
			colortable[3] == FBState[buttons[index]]["text3color"][3] then
			colortable[1] = colortable2[1]
			colortable[2] = colortable2[2]
			colortable[3] = colortable2[3]
		elseif args["reset"] then
			colortable[1] = nil
			colortable[2] = nil
			colortable[3] = nil
			FB_Report("text 1 has had its color reset")
			getglobal(button:GetName() .. "Text3"):SetVertexColor(.6,.6,.6)
		end
		if colortable[1] then 
			FBState[buttons[index]]["text3color"][1] = colortable[1]
			FBState[buttons[index]]["text3color"][2] = colortable[2]
			FBState[buttons[index]]["text3color"][3] = colortable[3]
			FB_Report(button:GetName() .. format(" color set to %.2f, %.2f, %.2f",
				colortable[1],colortable[2],colortable[3]))
		else
			FBState[buttons[index]]["text3color"] = nil
		end
		-- Simply having the state in effect will change the color, but save the changed setting
		-- and avoid a call to apply settings
		if FBState[buttons[index]]["text3color"] then
			if not FBSavedProfile[FBProfileName][buttons[index]].State["text3color"] then
				FBSavedProfile[FBProfileName][buttons[index]].State["text3color"] = {}
			end
			FBSavedProfile[FBProfileName][buttons[index]].State["text3color"][1] = colortable[1]
			FBSavedProfile[FBProfileName][buttons[index]].State["text3color"][2] = colortable[2]
			FBSavedProfile[FBProfileName][buttons[index]].State["text3color"][3] = colortable[3]
		else
			FBSavedProfile[FBProfileName][buttons[index]].State["text3color"] = FBState[buttons[index]]["text3color"]
		end
		FB_TextSub(buttons[index])
	end
end

function FB_Command_ShadeToolTip(msg)
	local index
-- Shade the buttons specified in Button=<buttons> with the color in Color=
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("shadetooltip", args) then return end 
		-- advanced checks that aren't automatic
		if 	type(args["color"]) ~= "table" or args["color"][3] == nil or
			(args["toggle"] and (type(args["toggle"]) ~= "table" or args["toggle"][3] == nil)) then
			util:Print("Error: Color not in correct format")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("shadetooltip", args) then return end
	end

	if FB_SetCommandTimer("shadetooltip", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local index
	for index = 1,3 do
		colortable[index] = args["color"][index] / 10
		if args["toggle"] then colortable2[index] = args["toggle"][index] / 10 end
	end
	-- Toggle code - if toggle, and button already the color specified, then toggle then go to toggle color
	if 	args["toggle"] and 
		colortable[1] == FBToggles["tooltipinfocolor"].r and
		colortable[2] == FBToggles["tooltipinfocolor"].g and
		colortable[3] == FBToggles["tooltipinfocolor"].b then
		colortable[1] = colortable2[1]
		colortable[2] = colortable2[2]
		colortable[3] = colortable2[3]
	elseif args["reset"] then
		colortable[1] = nil
		colortable[2] = nil
		colortable[3] = nil
		FB_Report("Tooltip info has had its color reset")
	end
	if colortable[1] then 
		FBToggles["tooltipinfocolor"].r = colortable[1] 
		FBToggles["tooltipinfocolor"].g = colortable[2] 
		FBToggles["tooltipinfocolor"].b = colortable[3] 
		FB_Report(format("Tooltip color set to %.2f, %.2f, %.2f",
			colortable[1],colortable[1],colortable[1]))
	end
end
function FB_Command_JustifyText(msg)
-- Justify Text
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("justifytext", args) then return end 
		-- Place advanced bounds checking here
		if args["pos"] and not FBAnchors[string.upper(args["pos"])] then
			util:Print("Error: pos must be one of : TOPLEFT, TOPRIGHT, TOP, BOTTOMLEFT, BOTTOMRIGHT, BOTTOM, CENTER, LEFT, RIGHT")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("justifytext", args) then return end
	end
	
	if FB_SetCommandTimer("justifytext", args) then return end

	-- check for conditional here
	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["justifytext"] = args["pos"]
		if args["pos"] then 
			FB_Report(button:GetName() .. "text now in " .. args["pos"])
		else
			FB_Report(button:GetName() .. "text position reset")
		end
		FBSavedProfile[FBProfileName][buttons[index]].State["justifytext"] = args["pos"]
		FB_ApplyTextPosition(buttons[index])
	end
end 

function FB_Command_JustifyText2(msg)
-- Justify Text
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("justifytext", args) then return end 
		if args["pos"] and not FBAnchors[string.upper(args["pos"])] then
			util:Print("Error: pos must be one of : TOPLEFT, TOPRIGHT, TOP, BOTTOMLEFT, BOTTOMRIGHT, BOTTOM, CENTER, LEFT, RIGHT")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("justifytext2", args) then return end
	end
	
	if FB_SetCommandTimer("justifytext2", args) then return end

	-- check for conditional here
	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["justifytext2"] = args["pos"]
		if args["pos"] then 
			FB_Report(button:GetName() .. "text2 now in " .. args["pos"])
		else
			FB_Report(button:GetName() .. "text2 position reset")
		end
		FBSavedProfile[FBProfileName][buttons[index]].State["justifytext2"] = args["pos"]
		FB_ApplyTextPosition(buttons[index])
	end
end 

function FB_Command_JustifyText3(msg)
-- Justify Text
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("justifytext", args) then return end 
		if args["pos"] and not FBAnchors[string.upper(args["pos"])] then
			util:Print("Error: pos must be one of : TOPLEFT, TOPRIGHT, TOP, BOTTOMLEFT, BOTTOMRIGHT, BOTTOM, CENTER, LEFT, RIGHT")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("justifytext3", args) then return end
	end
	
	if FB_SetCommandTimer("justifytext3", args) then return end

	-- check for conditional here
	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["justifytext3"] = args["pos"]
		if args["pos"] then 
			FB_Report(button:GetName() .. "text3 now in " .. args["pos"])
		else
			FB_Report(button:GetName() .. "text3 position reset")
		end
		FBSavedProfile[FBProfileName][buttons[index]].State["justifytext3"] = args["pos"]
		FB_ApplyTextPosition(buttons[index])
	end
end 

-- Movement command handlers

function FB_Command_Lock(msg)
-- Lock the buttons specified in Button=<buttons>
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("lock",args) then return end
-- check here for one or the other
	if (args["group"]==nil) and (args["button"]==nil) then
		util:Print("Error: You must specify a group or button")
	end
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end

	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["locked"] = true
		FB_Report(button:GetName() .. " locked")
	end
	
	FB_ApplySettings()
end

function FB_Command_Unlock(msg)
-- Unlock the buttons specified in Button=<buttons>
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("lock",args) then return end
-- check here for one or the other
	if (args["group"]==nil) and (args["button"]==nil) then
		util:Print("Error: You must specify a group or button")
	end
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["locked"] = nil
		FB_Report(button:GetName() .. " unlocked")
	end
	
	FB_ApplySettings()
end

function FB_Command_MoveABS(msg)
-- Move the specified button to a point relative to the bottom left of the screen
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("moveabs", args) then return end 
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("moveabs", args) then return end
	end
	
	if FB_SetCommandTimer("moveabs", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local button, frame = FB_GetWidgets(args["button"])
	
	-- if the button is in a group, but not the anchor, return
	if FBState[args["button"]]["group"] and FBState[args["button"]]["group"] ~= args["button"] then return end
	
	if FBState[args["button"]]["group"] then 
		FB_StoreGroupOffsetForMove(FBState[args["button"]]["group"])
	end
		
	FB_MoveButtonABS(args["button"], args["xx"], args["yy"])
	FB_Report(button:GetName() .. format(" moved to x=%d, y=%d", args["xx"], args["yy"]))
	if FBState[args["button"]]["group"] then 
		-- A group anchor was moved. Update Group coordinates and then Group Bounding Data
		FB_RestoreGroupOffsetAfterMove(FBState[args["button"]]["group"])
		FBGroupData[FBState[args["button"]]["group"]] = FB_GetBoundingButtons(FBState[args["button"]]["group"]) 
		FB_CheckGroups()
	end
end

function FB_Command_MoveRel(msg)
-- Move the specified button to the location relative to target
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("moverel", args) then return end 
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("moverel", args) then return end
	end
	
	if FB_SetCommandTimer("moverel", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local button, frame = FB_GetWidgets(args["button"])
	
	-- if the button is in a group, but not the anchor, return
	if FBState[args["button"]]["group"] and FBState[args["button"]]["group"] ~= args["button"] then return end
	
	if FBState[args["button"]]["group"] then 
		FB_StoreGroupOffsetForMove(FBState[args["button"]]["group"])
	end
		
	local target, frame = FB_GetWidgets(args["trgbtn"])
	local dx = args["dx"] / UIParent:GetScale()
	local dy = args["dy"] / UIParent:GetScale()
	FB_MoveButtonRel(args["button"],args["trgbtn"], dx, dy)
	FB_Report(button:GetName() .. format(" moved to x=%d, y=%d", args["dx"], args["dy"]) .. " with respect to " .. target:GetName())
	if FBState[args["button"]]["group"] then 
		-- A group anchor was moved. Update Group coordinates and then Group Bounding Data
		FB_RestoreGroupOffsetAfterMove(FBState[args["button"]]["group"])
		FBGroupData[FBState[args["button"]]["group"]] = FB_GetBoundingButtons(FBState[args["button"]]["group"]) 
		FB_CheckGroups()
	end
end

function FB_Command_MoveToMouse(msg)
-- Move the specified button to the location relative to mouse
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("movetomouse", args) then return end 
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("movetomouse", args) then return end
	end
	
	if FB_SetCommandTimer("movetomouse", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local button, frame = FB_GetWidgets(args["button"])

	-- if the button is in a group, but not the anchor, return
	if FBState[args["button"]]["group"] and FBState[args["button"]]["group"] ~= args["button"] then return end

	if FBState[args["button"]]["group"] then 
		FB_StoreGroupOffsetForMove(FBState[args["button"]]["group"])
	end
		
	local x,y = GetCursorPosition(UIParent)
	x = x / UIParent:GetScale()
	y = y / UIParent:GetScale()
	local dx = args["dx"] / UIParent:GetScale()
	local dy = args["dy"] / UIParent:GetScale()
	FB_MoveButtonABS(args["button"], x+dx, y+dy)
	FB_Report(button:GetName() .. format(" moved to x=%d, y=%d", x+args["dx"], y+args["dy"]))
	if FBState[args["button"]]["group"] then 
		-- A group anchor was moved. Update Group coordinates and then Group Bounding Data
		FB_RestoreGroupOffsetAfterMove(FBState[args["button"]]["group"])
		FBGroupData[FBState[args["button"]]["group"]] = FB_GetBoundingButtons(FBState[args["button"]]["group"]) 
		FB_CheckGroups()
	end
end

-- All group related slash command handlers here

function FB_Command_CircleGroup(msg)
-- Arrange the specified group into a circular formation
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("circlegroup",args) then return end
	local buttonnum=args["group"]
	local button, frame = FB_GetWidgets(args["group"])
	if FBState[buttonnum]["group"] ~= FB_GetButtonNum(button) then
		util:Echo(FB_NOGROUP_ERR, "green")
		return
	end
	FB_CircularGroup(args["group"], args["padding"])
	FB_Report(string.format(FB_AUTOARRANGE_RPT, args["group"]))
end

function FB_Command_VerticalGroup(msg)
-- Arrange the specified group into a vertical formation
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("verticalgroup",args) then return end
	local buttonnum=args["group"]
	local button, frame = FB_GetWidgets(args["group"])
	if FBState[buttonnum]["group"] ~= FB_GetButtonNum(button) then
		util:Echo(FB_NOGROUP_ERR, "green")
		return
	end
	FB_VerticalGroup(args["group"], args["width"], args["padding"])
	FB_Report(string.format(FB_AUTOARRANGE_RPT, args["group"]))
end

function FB_Command_HorizontalGroup(msg)
-- Arrange the specified group into a horizontal formation
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("horizontalgroup",args) then return end
	local buttonnum=args["group"]
	local button, frame = FB_GetWidgets(args["group"])
	if FBState[buttonnum]["group"] ~= FB_GetButtonNum(button) then
		util:Echo(FB_NOGROUP_ERR, "green")
		return
	end
	FB_HorizontalGroup(args["group"], args["height"], args["padding"])
	FB_Report(string.format(FB_AUTOARRANGE_RPT, args["group"]))
end
function FB_Command_MenuPopUp(msg)
-- Arrange the specified group into a popout menu
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("menupopup",args) then return end
	local buttonnum=args["group"]
	local alignment=string.upper(args["align"])
	local trigger=args["trigger"]
	local button, frame = FB_GetWidgets(args["group"])
	if FBState[buttonnum]["group"] ~= FB_GetButtonNum(button) then
		util:Echo(FB_NOGROUP_ERR, "green")
		return
	end
	if FBState[trigger]["group"] ~= FB_GetButtonNum(button) then
		util:Echo(string.format(FB_MENUPOPUP_TRIGGER_ERR, FB_GetButtonNum(button)), "green")
		return
	end
	if alignment == "HORIZONTAL" then
		FB_HorizontalGroup(args["group"], args["height"], args["padding"])
	elseif alignment == "VERTICAL" then
		FB_VerticalGroup(args["group"], args["width"], args["padding"])
	elseif alignment == "CIRCULAR" then
		FB_CircularGroup(args["group"], args["padding"])
	else
		util:Echo(string.format(FB_MENUPOPUP_ALIGN_ERR, args["align"]), "green")
		return
	end
	local buttonlist = FB_GetGroupMembers(buttonnum)
	local i, j, buttontext="[ "
	for i, j in pairs(buttonlist) do
		if j ~= trigger then
			buttontext = buttontext..j.." "
		end
	end
	buttontext = buttontext.."]"
	FB_Command_Show("show button="..buttontext.." on='mouseenterbutton' target="..trigger)
	FB_Command_Hide("hide button="..buttontext.." on='mouseleavegroup' target="..buttonnum)	
	if args["texture"] ~= "" then
		FB_Command_SetTexture("settexture id="..trigger.." texture="..args["texture"])
	end
end
function FB_Command_Group(msg)
-- Set a group for the buttons specified in Button=<buttons>
-- Group is anchored on button specified in Anchor=<button>
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("group",args) then return end
	local buttons = FB_GetButtonList(args["button"])
-- extended checks
-- Groups must have more than one members
	if buttons.n < 2 then 
		util:Echo(FB_GROUP_MEMBERS_ERR)
		return
	end
-- Anchor must also be a member of the set of buttons being made into a group
	local index
	local goodanchor = false
	for index = 1,buttons.n do
		if args["anchor"] == buttons[index] then goodanchor = true end
	end
	
	if not goodanchor then
		util:Echo(FB_GROUP_ANCHOR_ERR)
		return
	end
	
-- Good parameters - set the group
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["group"] = args["anchor"]
	end
	
-- Reform group
	FB_ReformGroup(args["anchor"])
	if FBVerbose then FB_Command_ListGroups("group="..args["anchor"]) end
end

function FB_Command_Ungroup(msg)
-- Ungroup the buttons specified in Button=<buttons>, and their groupmates
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("ungroup",args) then return end
	local buttons = FB_GetButtonList(args["group"])
	local index
	for index = 1,buttons.n do
		if FBState[buttons[index]]["group"] == buttons[index] then
			FB_Report(string.format(FB_UNGROUP_DISBAND_RPT, buttons[index]))
			local members = FB_GetGroupMembers(FBState[buttons[index]]["group"])
			local index2
			for index2 = 1, members.n do
				FBState[members[index2]]["group"] = nil
				FBState[members[index2]]["locked"] = nil
			end
		end
	end
	FB_ReformAllGroups()
end

function FB_Command_ListGroups(msg)
-- Show buttons in the groups in Group=
-- show all groups if group= ommitted
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("listgroups",args) then return end

	if (args["group"] == nil) then
		local index, value
		local groups = {}
		for index = 1, FBNumButtons do
			local button, frame = FB_GetWidgets(index)
			if FBState[index]["group"] == index then groups[index] = true end
		end
		local text = FB_LISTGROUPS_RPT
		for index = 1, FBNumButtons do
			if groups[index] then text = text .. " " .. index end
		end
		util:Print(text)
		return
	end

	if type(args["group"]) == "number" then
		buttons= FB_GetGroupMembers(args["group"])
	else
		FBcmd:DisplayUsage("group")
		return
	end
	
	local index
	local text = string.format(FB_LISTGROUPS_BUTTON_RPT, args["group"])
	for index = 1, buttons.n do
		text = text .. " " ..  buttons[index]
	end
	util:Print(text)
end

-- Event functions

function FB_Command_ListEvents(msg)
-- Show events
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("listevents",args) then return end
	
	local index, event
	for index, event in ipairs(FBEvents) do
		util:Print(index .. ") On " .. event["on"] .. " " .. event["targettext"] .. " : " .. event["command"])
	end
end

function FB_Command_DeleteEvent(msg)
-- Delete specified event
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("deleteevent",args) then return end
	table.remove(FBEvents,args["event"])
	FB_Report("Event " .. args["event"] .. " deleted")
	FB_CreateQuickDispatch()
	FBSavedProfile[FBProfileName].Events = util:TableCopy(FBEvents)
end

-- Miscellaneous command handlers

function FB_Command_Verbose(msg)
-- Set the feedback verbosity level
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("verbose",args) then return end
	if args["state"] ~= nil then
		if string.lower(args["state"]) == "on" then
			FBVerbose = true
			util:Print("Verbose mode Active", "green")
		else
			FBVerbose = nil;
			util:Print("Verbose mode Inactive", "yellow")
		end
	else
		FBcmd:DisplayUsage("misc")
	end
end

function FB_Command_Tooltip(msg)
-- Set the feedback verbosity level
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("verbose",args) then return end
	if args["state"] ~= nil then
		if string.lower(args["state"]) == "on" then
			FBNoTooltips = nil
			util:Print("Tooltips will now show", "green")
		else
			FBNoTooltips = true
			util:Print("Tooltips will not show", "yellow")
		end
	else
		FBcmd:DisplayUsage("misc")
	end
end

function FB_Command_LockIcon(msg)
-- Lock the icon to the buttons specified in Button=<buttons>
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("lockicon",args) then return end
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		if args["off"] then
			FBState[buttons[index]]["lockedicon"] = nil
			FB_Report(button:GetName() .. " has it's Icon unlocked click and drag to remove")
		else
			FBState[buttons[index]]["lockedicon"] = true
			FB_Report(button:GetName() .. " has it's Icon locked - shift click to remove")
		end
	end
	
	FB_ApplySettings()
end

function FB_Command_Text(msg)
-- template for new commands
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("text", args) then return end 
		-- Place advanced bounds checking here
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		if (args["text"]==nil) then
			args["text"] = ""
		end
		
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("text", args) then return end
	end
	
	if FB_SetCommandTimer("text", args) then return end

	-- check for conditional here
	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["hotkeytext"] = args["text"]
		FB_TextSub(buttons[index])
		FlexBarButton_UpdateUsable(button)
		FlexBarButton_UpdateHotkeys(button)
		FB_Report(button:GetName() .. " now has " .. args["text"] .. " as it's hotkey")
		FBSavedProfile[FBProfileName][buttons[index]].State["hotkeytext"] = args["text"]
	end
end 

function FB_Command_Text2(msg)
-- template for new commands
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("text2", args) then return end 
		-- Place advanced bounds checking here
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		if (args["text"]==nil) then
			args["text"] = ""
		end
		
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("text2", args) then return end
	end
	if FB_SetCommandTimer("text2", args) then return end

	-- check for conditional here
	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["text2"] = args["text"]
		FB_TextSub(buttons[index])
		FlexBarButton_UpdateUsable(button)
		FlexBarButton_UpdateHotkeys(button)
		FB_Report(button:GetName() .. " now has " .. args["text"] .. " as it's hotkey")
		FBSavedProfile[FBProfileName][buttons[index]].State["text2"] = args["text"]
	end
end 

function FB_Command_Text3(msg)
-- template for new commands
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("text3", args) then return end 
		-- Place advanced bounds checking here
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		if (args["text"]==nil) then
			args["text"] = ""
		end
		
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("text3", args) then return end
	end
	if FB_SetCommandTimer("text3", args) then return end

	-- check for conditional here
	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		FBState[buttons[index]]["text3"] = args["text"]
		FB_TextSub(buttons[index])
		FlexBarButton_UpdateUsable(button)
		FlexBarButton_UpdateHotkeys(button)
		FB_Report(button:GetName() .. " now has " .. args["text"] .. " as it's hotkey")
		FBSavedProfile[FBProfileName][buttons[index]].State["text3"] = args["text"]
	end
end 

function FB_Command_ReMap(msg)
-- Remap the bonus buttons to the specified base
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("remap", args) then return end 
		-- Get button list
		local buttons = FB_GetButtonList(args["button"])
		if (args["group"]) then
			buttons= FB_GetGroupMembers(args["group"])
		end
		-- Another check that can't be automated
		if args["base"] + buttons.n - 1 > 120 then
			util:Print("Error: Remap would make a button ID out of bounds")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("remap", args) then return end
	end
	
	if FB_SetCommandTimer("remap", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"]) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1, buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		local id = button:GetID()
		local waspet = FBSavedProfile[FBProfileName].FlexActions[id] and FBSavedProfile[FBProfileName].FlexActions[id]["action"] == "pet"
		-- if toggle is present AND button are already mapped to anything but default OR Reset is true
		-- then map them to the default, otherwise map them to base + index - 1.
		if 	(args["toggle"] and FBState[buttons[index]]["remap"]) or args["reset"] then
			FBState[buttons[index]]["remap"] = nil
			button:SetID(FBState[buttons[index]]["oldid"])
		else
			FBState[buttons[index]]["remap"] = index + args["base"] - 1
			button:SetID(FBState[buttons[index]]["remap"])
		end
		local id = button:GetID()
		local ispet = FBSavedProfile[FBProfileName].FlexActions[id] and FBSavedProfile[FBProfileName].FlexActions[id]["action"] == "pet"
		if waspet then FB_ResetPetItems(button) end
		if ispet then FBPetActions[buttons[index]] = true end
		FlexBarButton_Update(button)
		FlexBarButton_UpdateCooldown(button)
		FlexBarButton_UpdateState(button)
		FB_MimicPetButtons()
		FBSavedProfile[FBProfileName][buttons[index]].State["remap"] = FBState[buttons[index]]["remap"]
		FB_Report(button:GetName() .. " remapped to " .. button:GetID())
	end
end

function FB_Command_Echo(msg)
-- Have the specified buttons echo a second buttondown/up/click events
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("echo", args) then return end 
		-- Get button list
		local buttons = FB_GetButtonList(args["button"])
		if (args["group"]) then
			buttons= FB_GetGroupMembers(args["group"])
		end
		-- Another check that can't be automated
		if args["base"] + buttons.n - 1 > FBNumButtons then
			util:Print("Error: echo would make a button # out of bounds")
			return
		end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("echo", args) then return end
	end
	
	if FB_SetCommandTimer("echo", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"]) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1, buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- if toggle is present AND button are already echoing anything but default OR Reset is true
		-- then map them to the default, otherwise map them to base + index - 1.
		if 	(args["toggle"] and FBState[buttons[index]]["echo"]) or args["reset"] then
			FBState[buttons[index]]["echo"] = nil
		else
			FBState[buttons[index]]["echo"] = args["base"] + index - 1
		end
		
		FBSavedProfile[FBProfileName][buttons[index]].State["echo"] = FBState[buttons[index]]["echo"]
		if FBState[buttons[index]]["echo"] then
			FB_Report(button:GetName() .. " echoing " .. FBState[buttons[index]]["echo"])
		else
			FB_Report(button:GetName() .. " no longer echoing")
		end
	end
end

function FB_Command_HideGrid(msg)
-- Hide the button background if it doesn't have an action
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("hidegrid",args) then return end
-- check here for one or the other
	if (args["group"]==nil) and (args["button"]==nil) then
		util:Print("Error: You must specify a group or button")
	end
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		if args["toggle"] and (FBState[buttons[index]]["hidegrid"] or FBState[buttons[index]]["savedgrid"] )then
			FBState[buttons[index]]["hidegrid"] = nil
			FBState[buttons[index]]["savedgrid"] = nil
		elseif not FBSavedProfile[FBProfileName].FlexActions[button:GetID()] then
			FBState[buttons[index]]["hidegrid"] = true
		else
			FBState[buttons[index]]["savedgrid"] = true
		end
		if FBState[buttons[index]]["hidegrid"] then
			button.showgrid=0
			frame:DisableDrawLayer()
		else
			button.showgrid=1
			button:Show()
			frame:EnableDrawLayer()
		end
		FlexBarButton_Update(button)
		FlexBarButton_UpdateState(button)
		FB_Report(button:GetName() .. " has it's background hidden.  It will show when you drag an item")
	end
	
	FB_ApplySettings()
end

function FB_Command_ShowGrid(msg)
-- Hide the button background if it doesn't have an action
	local args = FBcmd:GetParameters(msg)
-- Check basic usage
	if not FBcmd:CheckParameters("showgrid",args) then return end
-- check here for one or the other
	if (args["group"]==nil) and (args["button"]==nil) then
		util:Print("Error: You must specify a group or button")
	end
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		if args["toggle"] and not FBState[buttons[index]]["hidegrid"] and not FBSavedProfile[FBProfileName].FlexActions[button:GetID()] then
			FBState[buttons[index]]["hidegrid"] = true
		elseif args["toggle"] and not FBState[buttons[index]]["savedgrid"] and FBSavedProfile[FBProfileName].FlexActions[button:GetID()] then
			FBState[buttons[index]]["savedgrid"] = true
		else
			FBState[buttons[index]]["hidegrid"] = nil
			FBState[buttons[index]]["savedgrid"] = nil
		end
		if FBState[buttons[index]]["hidegrid"] then
			button.showgrid=0
			frame:DisableDrawLayer()
		else
			button.showgrid=1
			button:Show()
			frame:EnableDrawLayer()
		end
		FlexBarButton_Update(button)
		FlexBarButton_UpdateState(button)
		FB_Report(button:GetName() .. " has it's background hidden.  It will show when you drag an item")
	end
	
	FB_ApplySettings()
end

function FB_Command_Advanced(msg)
-- Set it so that only a left click on this button will trigger it
	local args = FBcmd:GetParameters(msg)
	if not FBcmd:CheckParameters("advanced", args) then return end
-- check here for one or the other
	if (args["group"]==nil) and (args["button"]==nil) then
		util:Print("Error: You must specify a group or button")
	end
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end

	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		if string.lower(args["state"]) == "on" then
			FBState[buttons[index]]["advanced"] = true
			FB_Report(button:GetName() .. " will now only fire on a left click")
		else
			FBState[buttons[index]]["advanced"] = nil;
			FB_Report(button:GetName() .. " will now treat all clicks the same")
		end
	end
	FB_ApplySettings()
end

function FB_Command_Use(msg)
-- Use the buttons specified in Button=<buttons>
-- NOTE - this appears to ONLY work on clicks (right/left)
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("use", args) then return end 
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("use", args) then return end
	end
	
	if FB_SetCommandTimer("use", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

-- get button list
	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end
	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		local id = button:GetID()
		if(MacroFrame_SaveMacro) then
			MacroFrame_SaveMacro()
		end
		UseAction(id, 1)
	end
end

function FB_Command_ResetAll(msg)
-- Reset entire profile for character
	local args = FBcmd:GetParameters(msg)
	if not FBcmd:CheckParameters("resetall", args) then return end

	FBSavedProfile[FBProfileName] = nil
	-- Also get rid of old (pre 1.32) profile saved by name only
	FBSavedProfile[UnitName("player")] = nil
	ReloadUI()
end

function FB_Command_Restore(msg)
-- Reset entire profile for character
	local args = FBcmd:GetParameters(msg)
	if not FBcmd:CheckParameters("restore", args) then return end
	if not FBProfileBackup then
		util:Echo("No previous profile available", "yellow")
		return
	end
	
	local index
	for index = 1, FBNumButtons do
		local button = FB_GetWidgets(index)
		button:SetID(index)
	end
	FBSavedProfile[FBProfileName] = util:TableCopy(FBProfileBackup)
	ReloadUI()
end

function FB_Command_LoadConfig(msg)
-- Load a named config from the config file
-- the naive way to do this is a simple for loop - however that cause a small
-- problem by executing group commands to fast.
-- altered to do one command per second.
	local args = FBcmd:GetParameters(msg)
	if not FBcmd:CheckParameters("loadconfig", args) then return end
-- un auto-matable checks
	if type(getglobal(args["config"])) ~= "table" and not FBScripts[args["config"]] then
		util:Print("Error: " .. args["config"] .. " not a valid config file")
		return
	end

	if nextcommand ~= 0 then
		util:Echo("Error: Still processing last config file")
		return
	end
	
	FBProfileBackup = util:TableCopy(FBSavedProfile[FBProfileName])
	currentconfig = getglobal(args["config"])

	if not currentconfig then
		FB_Execute_ConfigString(FBScripts[args["config"]]) 
		return
	end
		
	local index, value
	local count = 0
	for index, value in ipairs(currentconfig) do
		count=count+1
	end
	currentconfig.n = count
	FBTimers["loadconfig"] = Timer_Class:New(2, nil, nil, nil, FB_Config) 
end

function FB_Config()
	nextcommand = nextcommand + 1
	if nextcommand > currentconfig.n then
		nextcommand = 0
		currentconfig = nil
		return
	end
	
	util:Echo(currentconfig[nextcommand], "green")
	FBcmd:Dispatch(currentconfig[nextcommand])
	FBTimers["loadconfig"] = Timer_Class:New(2, nil, nil, nil, FB_Config) 
end

function FB_Command_Disable(msg)
-- Disable the regular action on a key
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("disable", args) then return end 
		-- check for event here - return if specified.  FBEvents will be updated
		if (args["group"]==nil) and (args["button"]==nil) then
			util:Print("Error: You must specify a group or button")
		end
		if FB_GetEventMsg("disable", args) then return end
	end
	
	if FB_SetCommandTimer("disable", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	local buttons = FB_GetButtonList(args["button"])
	if (args["group"] and (type(args["group"]) == "number")) then
		buttons= FB_GetGroupMembers(args["group"])
	end

	local index
	for index = 1,buttons.n do
		local button, frame = FB_GetWidgets(buttons[index])
		-- Toggle code - if disabled and toggle exists then enable
		if (args["toggle"] and FBState[buttons[index]]["disabled"]) or string.lower(args["state"]) == 'off' then
			FBState[buttons[index]]["disabled"] = nil
			FB_Report(button:GetName() .. " enabled")
		elseif (args["toggle"] and not FBState[buttons[index]]["disabled"]) or string.lower(args["state"]) == 'on' then
			FBState[buttons[index]]["disabled"] = true
			FB_Report(button:GetName() .. " disabled")
		end
		-- And we only save the changed setting
		FBSavedProfile[FBProfileName][buttons[index]].State["disabled"] = FBState[buttons[index]]["disabled"]
	end
end 

function FB_Command_Raise(msg)
-- Raise an event
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("raise", args) then return end 
		if args["ttoggle"] then args["toggle"] = args["ttoggle"] end
		if args["tname"] then args["name"] = args["tname"] end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("raise", args) then return end
	end
	
	-- check for conditional here

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	if args["in"] then
	-- if toggle is specified and timer already exists - cancel timer
		if (args["toggle"] and FBTimers[args["name"]] and FBTimers[args["name"]]:GetRunning()) then
			FBTimers[args["name"]] = nil
		else
		-- otherwise set timer
			FBTimers[args["name"]] = Timer_Class:New(args["in"],false,nil,nil,function() FB_RaiseEvent(args["event"],args["source"]) end)
			FB_Report("Raising " .. args["event"] .. " in " .. args["in"] .. " seconds");
		end
	else
		FB_RaiseEvent(args["event"],args["source"])
		FB_Report("Raised " .. args["event"])
	end
end 

function FB_Command_SafeLoad(msg)
-- Enable Safeload
	local args = FBcmd:GetParameters(msg)
	-- basic usage test
	if not FBcmd:CheckParameters("safeload", args) then return end 

	if string.lower(args["state"]) == "on" then
		FBSafeLoad = true
		util:Echo("SAFE LOAD ENGAGED -- you will need to manually load your profile now", "green")
	else
		FBSafeLoad = nil
		util:Echo("SAFE LOAD DIS-ENGAGED -- profile will autoload now, if you experience lost configurations, re-enable safe load", "green")
	end
end 

function FB_Command_LoadProfile(msg)
-- load a profile and make current
	local args = FBcmd:GetParameters(msg)
	-- basic usage test
	if not FBcmd:CheckParameters("loadprofile", args) then return end 
	
	if not FBSavedProfile[args["profile"]] then
		util:Echo("No such profile: " .. args["profile"], "yellow")
	else
		FBSavedProfile[FBProfileName] = util:TableCopy(FBSavedProfile[args["profile"]])
		util:Echo("Making " .. args["profile"] .. " the current profile and reloading", "green")
		FB_LoadProfile()
	end
end 

function FB_Command_SaveProfile(msg)
-- Save the current profile
	local args = FBcmd:GetParameters(msg)
	-- basic usage test
	if not FBcmd:CheckParameters("saveprofile", args) then return end 
	
	FBSavedProfile[args["profile"]] = util:TableCopy(FBSavedProfile[FBProfileName])
	util:Echo("Profile: " .. args["profile"] .. " saved" )
end 
function FB_Command_DeleteProfile(msg)
-- load a profile and make current
	local args = FBcmd:GetParameters(msg)
	-- basic usage test
	if not FBcmd:CheckParameters("deleteprofile", args) then return end 
	
	if not FBSavedProfile[args["profile"]] then
		util:Echo("No such profile: " .. args["profile"], "yellow")
	else
		FBSavedProfile[args["profile"]] = nil
		util:Echo("Profile " .. args["profile"] .. " deleted.", "green")
	end
end 
function FB_Command_ListProfiles()
-- list all profiles
	local name, profile
	util:Print("FlexBar Profiles:")
	for name, profile in ipairs(FBSavedProfile) do
		util:Print("'"..name.."'")
	end
end
function FB_Command_ToggleButtonInfo()
	if FBButtonInfoShown then
		FB_RestoreButtonText()
	else
		FB_ShowButtonInfo()
	end
end

function FB_Command_Scripts()
-- toggle script editor window
	if FBScriptsFrame:IsVisible() then
		FBScriptsEditBox:ClearFocus()
		FBScriptsFrame:Hide()
	else
		FB_ShowScripts()
	end
end
function FB_Command_Events()
-- toggle script editor window

	if FBEventEditorFrame:IsVisible() then
		FBEventEditorFrame:Hide()
	else
		FB_DisplayEventEditor()
	end
end
function FB_Command_Performance()
-- toggle script editor window
	if FBPerformanceFrame:IsVisible() then
		FBPerformanceFrame:Hide()
	else
		FB_Show_PerformanceOptions()
	end
end
function FB_Command_AutoItems()
-- toggle script editor window
	if FBAutoItemsFrame:IsVisible() then
		FBAutoItemsFrame:Hide()
	else
		FB_DisplayAutoItems()
	end
end
function FB_Command_Options()
-- toggle script editor window
	if FBOptionsFrame:IsVisible() then
		FBOptionsFrame:Hide()
	else
		FB_ShowGlobalOptions()
	end
end

function FB_Command_RunScript(msg)
-- Run a script from FBScripts	
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("runscript", args) then return end 
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("runscript", args) then return end
	end
	-- check for conditional here

	if FB_SetCommandTimer("runscript", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	if FBScripts[args["script"]] then
	-- if script is in FBScripts then run from there
		RunScript(FBScripts[args["script"]])
	else
	-- otherwise assume string contains script
		RunScript(args["script"])
	end
end 

function FB_Command_RunMacro(msg)
-- Run a script from FBScripts
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("runmacro", args) then return end 
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("runmacro", args) then return end
	end
	
	-- check for conditional here

	if FB_SetCommandTimer("runmacro", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	if type(args["macro"]) == "table" then
		local index,command, longmacro
		longmacro = "\n"
		for index,command in ipairs(args["macro"]) do
			longmacro=longmacro..command.."\n"
		end
		FB_Execute_MultilineMacro(longmacro,"InLineMacro"..GetTime())
	elseif FBScripts[args["macro"]] then
	-- if macro is in FBScripts, run from there
		FB_Execute_MultilineMacro(FBScripts[args["macro"]],args["macro"])
	else
	-- otherwise assume macro is contained in the string
		FB_Execute_Command(args["macro"])
	end
end 

function FB_Command_SetTexture(msg)
-- Set a texture for an empty button.
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("settexture", args) then return end 
		-- Place advanced bounds checking here
		if string.lower(args["texture"]) == "%backpack" then
			args["texture"] = "Interface\\Buttons\\Button-BackPack-Up"
		end
		local _,_,bnum = string.find(string.lower(args["texture"]),"%%button(%d+)")
		if bnum then
			bnum = bnum + 0
			local button = FB_GetWidgets(bnum)
			if GetActionTexture(button:GetID()) then
				args["texture"] = GetActionTexture(button:GetID())
			else
				args["texture"] = ""
			end
		end
		local _,_,mnum = string.find(string.lower(args["texture"]),"%%macro(%d+)")
		if mnum then
			mnum = mnum + 0
			if mnum > GetNumMacroIcons() then 
				util:Print("Error: No such icon")
				return
			else
				args["texture"] = GetMacroIconInfo(mnum)
			end
		end
		if args["texture"] == "" then args["reset"] = "true" end
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("settexture", args) then return end
	end
	
	-- check for conditional here

	if FB_SetCommandTimer("settexture", args) then return end

	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end
	
	if 	(FBSavedProfile[FBProfileName].FlexActions[args["id"]] and
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["action"] == "settexture" and 
		args["toggle"]) or 
		args["reset"] == "true" then
		FBSavedProfile[FBProfileName].FlexActions[args["id"]] = nil
	else
		FBSavedProfile[FBProfileName].FlexActions[args["id"]] = {}
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["action"] = "settexture"
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["texture"] = args["texture"]
	end
	
	local index
	for index = 1,120 do
		local button = FB_GetWidgets(index)
		if button:GetID() == args["id"] then
			FlexBarButton_Update(button)
			FlexBarButton_UpdateUsable(button)
		end
	end
end 

function FB_Command_FlexScript(msg)
-- Set a texture for an empty button.
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("flexscript", args) then return end 
		-- Place advanced bounds checking here
		if 	HasAction(args["id"]) then
			util:Print("Error: Cannot place flexscript on ID with regular action")
		end
		if string.lower(args["texture"]) == "%backpack" then
			args["texture"] = "Interface\\Buttons\\Button-BackPack-Up"
		end
		local _,_,bnum = string.find(string.lower(args["texture"]),"%%button(%d+)")
		if bnum then
			bnum = bnum + 0
			local button = FB_GetWidgets(bnum)
			if GetActionTexture(button:GetID()) then
				args["texture"] = GetActionTexture(button:GetID())
			else
				args["texture"] = ""
			end
		end
		local _,_,mnum = string.find(string.lower(args["texture"]),"%%macro(%d+)")
		if mnum then
			mnum = mnum + 0
			if mnum > GetNumMacroIcons() then 
				util:Print("Error: No such icon")
				return
			else
				args["texture"] = GetMacroIconInfo(mnum)
			end
		end
		if args["texture"] == "" then args["reset"] = "true" end
	end
	
	
	if 	(FBSavedProfile[FBProfileName].FlexActions[args["id"]] and
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["action"] == "script" and 
		args["toggle"]) or 
		args["reset"] == "true" then
		FBSavedProfile[FBProfileName].FlexActions[args["id"]] = nil
	else
		FBSavedProfile[FBProfileName].FlexActions[args["id"]] = {}
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["action"] = "script"
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["texture"] = args["texture"]
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["script"] = args["script"]
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["name"] = args["name"]
	end
	
	local index
	for index = 1,120 do
		local button = FB_GetWidgets(index)
		if button:GetID() == args["id"] then
			local profile = FBSavedProfile[FBProfileName]
			local action = profile.FlexActions[args["id"]]
			local state = profile[index].State
			if action then 
				state["savedgrid"] = state["hidegrid"] 
				state["hidegrid"] = nil
			else
				state["hidegrid"] = state["savedgrid"]
				state["savedgrid"] = nil
			end
			FBState[index]["savedgrid"] = state["savedgrid"]
			FBState[index]["hidegrid"] = state["hidegrid"]
			FB_ApplyGrid(index)
			FlexBarButton_Update(button)
			FlexBarButton_UpdateUsable(button)
			FB_ResetPetItems(button)
		end
	end
	FB_GeneratePetIDList()
	FB_MimicPetButtons()
end 

function FB_Command_FlexMacro(msg)
-- Set a texture for an empty button.
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("flexmacro", args) then return end 
		-- Place advanced bounds checking here
		if 	HasAction(args["id"]) then
			util:Print("Error: Cannot place flexmacro on ID with regular action")
		end
		if string.lower(args["texture"]) == "%backpack" then
			args["texture"] = "Interface\\Buttons\\Button-BackPack-Up"
		end
		local _,_,bnum = string.find(string.lower(args["texture"]),"%%button(%d+)")
		if bnum then
			bnum = bnum + 0
			local button = FB_GetWidgets(bnum)
			if GetActionTexture(button:GetID()) then
				args["texture"] = GetActionTexture(button:GetID())
			else
				args["texture"] = ""
			end
		end
		local _,_,mnum = string.find(string.lower(args["texture"]),"%%macro(%d+)")
		if mnum then
			mnum = mnum + 0
			if mnum > GetNumMacroIcons() then 
				util:Print("Error: No such icon")
				return
			else
				args["texture"] = GetMacroIconInfo(mnum)
			end
		end
		if args["texture"] == "" then args["reset"] = "true" end
	end
	
	
	if 	(FBSavedProfile[FBProfileName].FlexActions[args["id"]] and
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["action"] == "macro" and 
		args["toggle"]) or 
		args["reset"] == "true" then
		FBSavedProfile[FBProfileName].FlexActions[args["id"]] = nil
	else
		FBSavedProfile[FBProfileName].FlexActions[args["id"]] = {}
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["action"] = "macro"
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["texture"] = args["texture"]
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["macro"] = args["macro"]
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["name"] = args["name"]
	end
	
	local index
	for index = 1,120 do
		local button = FB_GetWidgets(index)
		if button:GetID() == args["id"] then
			local profile = FBSavedProfile[FBProfileName]
			local action = profile.FlexActions[args["id"]]
			local state = profile[index].State
			if action then 
				state["savedgrid"] = state["hidegrid"] 
				state["hidegrid"] = nil
			else
				state["hidegrid"] = state["savedgrid"]
				state["savedgrid"] = nil
			end
			FBState[index]["savedgrid"] = state["savedgrid"]
			FBState[index]["hidegrid"] = state["hidegrid"]
			FB_ApplyGrid(index)
			FlexBarButton_Update(button)
			FlexBarButton_UpdateUsable(button)
			FB_ResetPetItems(button)
		end
	end
	FB_GeneratePetIDList()
	FB_MimicPetButtons()
end 

function FB_Command_FlexPet(msg)
-- Set a texture for an empty button.
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("flexpet", args) then return end 
		-- Place advanced bounds checking here
		if 	HasAction(args["id"]) then
			util:Print("Error: Cannot place flexpet on ID with regular action")
			return
		end
	end
	
	
	if 	(FBSavedProfile[FBProfileName].FlexActions[args["id"]] and
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["action"] == "pet" and 
		args["toggle"]) or 
		args["reset"] == "true" then
		FBSavedProfile[FBProfileName].FlexActions[args["id"]] = nil
	else
		FBSavedProfile[FBProfileName].FlexActions[args["id"]] = {}
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["action"] = "pet"
		FBSavedProfile[FBProfileName].FlexActions[args["id"]]["id"] = args["petid"]
	end
	
	local index
	for index = 1,120 do
		local button = FB_GetWidgets(index)
		if button:GetID() == args["id"] then
			local profile = FBSavedProfile[FBProfileName]
			local action = profile.FlexActions[args["id"]]
			local state = profile[index].State
			if action then 
				state["savedgrid"] = state["hidegrid"] 
				state["hidegrid"] = nil
			else
				state["hidegrid"] = state["savedgrid"]
				state["savedgrid"] = nil
			end
			FBState[index]["savedgrid"] = state["savedgrid"]
			FBState[index]["hidegrid"] = state["hidegrid"]
			FB_ApplyGrid(index)
			FB_ResetPetItems(button)
			FlexBarButton_Update(button)
			FlexBarButton_UpdateUsable(button)
		end
	end
	FB_GeneratePetIDList()
	FB_MimicPetButtons()
end 

function FB_Command_ClearFlex(msg)
-- Set a texture for an empty button.
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("clearflex", args) then return end 
		-- Place advanced bounds checking here
	end
	
	
	FBSavedProfile[FBProfileName].FlexActions[args["id"]] = nil
	
	local index
	for index = 1,120 do
		local button = FB_GetWidgets(index)
		if button:GetID() == args["id"] then
			local profile = FBSavedProfile[FBProfileName]
			local action = profile.FlexActions[args["id"]]
			local state = profile[index].State
			if action then 
				state["savedgrid"] = state["hidegrid"] 
				state["hidegrid"] = nil
			else
				state["hidegrid"] = state["savedgrid"]
				state["savedgrid"] = nil
			end
			FBState[index]["savedgrid"] = state["savedgrid"]
			FBState[index]["hidegrid"] = state["hidegrid"]
			FB_ApplyGrid(index)
			FB_ResetPetItems(button)
			FlexBarButton_Update(button)
			FlexBarButton_UpdateUsable(button)
		end
	end
end 

function FB_Command_Template(msg)
-- template for new commands
	local args
	if FBEventArgs then
	-- if FBEventArgs is non-nil, then we are coming from raise event, and quick dispatch is in effect
		args=FBEventArgs
	else
	-- otherwise this is from the command line and regular checking needs to occur
		args = FBcmd:GetParameters(msg)
		-- basic usage test
		if not FBcmd:CheckParameters("template", args) then return end 
		-- Place advanced bounds checking here
		-- check for event here - return if specified.  FBEvents will be updated
		if FB_GetEventMsg("template", args) then return end
	end
	
	-- check for conditional here
	if args["if"] then if not FB_CheckConditional(args["if"]) then return end end

	-- perform action here
end 
