changeset 6:df3e27edbd60

Much work on history tab.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Wed, 15 Jun 2011 03:59:13 +0000
parents 7adbc59de8fe
children 9a37bd40eb5e
files LibFarmbuyer.lua abbreviations.lua bossmods.lua core.lua gui.lua
diffstat 5 files changed, 307 insertions(+), 115 deletions(-) [+]
line wrap: on
line diff
--- a/LibFarmbuyer.lua	Wed Apr 27 04:02:02 2011 +0000
+++ b/LibFarmbuyer.lua	Wed Jun 15 03:59:13 2011 +0000
@@ -44,9 +44,16 @@
   Runs F on the next frame refresh cycle.  Multiple calls in one cycle will
   stack LIFO.  Calls *while* processing the stack are safe, and will be stacked
   up for the next cycle.
+
+- safecall (func, ...)
+  A modified copy of the xpcall wrapper duplicated in every Ace3 file in the
+  whole damn library.
+
+- new(...), del(t), copy(t), clear()
+  Ditto for table recycling.
 ]]
 
-local MAJOR, MINOR = "LibFarmbuyer", 7
+local MAJOR, MINOR = "LibFarmbuyer", 9
 assert(LibStub,MAJOR.." requires LibStub")
 local lib = LibStub:NewLibrary(MAJOR, MINOR)
 if not lib then return end
@@ -54,7 +61,40 @@
 _G[MAJOR] = lib
 
 ----------------------------------------------------------------------
+--[[
+	Recycling functions yoinked from AceConfigDialog and tweaked
+]]
 local new, del, copy, clear
+do
+	local pool = setmetatable({},{__mode="k"})
+	function clear()
+		wipe(pool)
+	end
+	function new(...)  -- slightly modified variant, takes optional initializers
+		local t = next(pool)
+		if t then
+			pool[t] = nil
+			for i = 1, select('#',...) do
+				t[i] = select(i,...)
+			end
+			return t
+		else
+			return {...}
+		end
+	end
+	function copy(t)
+		local c = new()
+		for k, v in pairs(t) do
+			c[k] = v
+		end
+		return c
+	end
+	function del(t)
+		wipe(t)
+		pool[t] = true
+	end
+end
+lib.new, lib.del, lib.copy, lib.clear = new, del, copy, clear
 
 
 ----------------------------------------------------------------------
@@ -214,35 +254,60 @@
 
 
 ----------------------------------------------------------------------
--- Recycling functions yoinked from AceConfigDialog and tweaked
+--[[
+	safecall
+]]
 do
-	local pool = setmetatable({},{__mode="k"})
-	function clear()
-		wipe(pool)
+	local xpcall = xpcall
+
+	local function errorhandler(err)
+		--return geterrorhandler()(err)
+		--print("in error handler", err)
+		return err
 	end
-	function new(...)  -- slightly modified variant, takes optional initializers
-		local t = next(pool)
-		if t then
-			pool[t] = nil
-			for i = 1, select('#',...) do
-				t[i] = select(i,...)
-			end
-			return t
-		else
-			return {...}
+
+	local template = ([[
+		local xpcall, eh = ...
+		local method, ARGS
+		local function call() return method(ARGS) end
+
+		local function dispatch (func, ...)
+			 method = func
+			 if not method then return end
+			 ARGS = ...
+			 return xpcall (call, eh)
 		end
+
+		return dispatch
+	]]):gsub('\t','  ')
+
+	local function CreateDispatcher(argCount)
+		local ARGS = {}
+		for i = 1, argCount do ARGS[i] = "arg"..i end
+		local code = template:gsub("ARGS", table.concat(ARGS, ", "))
+		return assert(loadstring(code, "LibF/safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
 	end
-	function copy(t)
-		local c = new()
-		for k, v in pairs(t) do
-			c[k] = v
+
+	local Dispatchers = setmetatable({
+		[0] = function(func)
+			return xpcall (func, errorhandler)
 		end
-		return c
-	end
-	function del(t)
-		wipe(t)
-		pool[t] = true
+	}, {
+		__index = function (Ds, argCount)
+			local dispatcher = CreateDispatcher(argCount)
+			Ds[argCount] = dispatcher
+			return dispatcher
+		end
+	})
+
+	function lib.safecall (func, ...)
+		if type(func) == 'function' then
+			return Dispatchers[select('#', ...)](func, ...)
+		end
 	end
 end
 
+
+----------------------------------------------------------------------
+
 -- vim: noet
--- a/abbreviations.lua	Wed Apr 27 04:02:02 2011 +0000
+++ b/abbreviations.lua	Wed Jun 15 03:59:13 2011 +0000
@@ -6,6 +6,7 @@
 	["Bastion of Twilight"] = "BoT",
 	["Blackwing Descent"] = "BWD",
 	["Throne of the Four Winds"] = "To4W",
+	--["Firelands"] = "Firelands",
 
 	-------- WotLK
 	["Icecrown Citadel"] = "ICC",
@@ -18,9 +19,18 @@
 addon.boss_abbrev = {
 	-------- Cata
 	-- BoT
+	["Halfus Wyrmbreaker"] = "Halfass Wyrmbreaker",
+	["Valiona & Theralion"] = "Wonder Twins! Form of: Loot",
 	-- BWD
-	-- Throne
+	["Magmaw"] = "Earwig",
+	["Omnotron Defense System"] = "Nomnomtron Defense System",
+	["Chimaeron"] = "k-eye-MAIR-on",
+	["Atramedes"] = "at-ruh-MEE-deez",
+	["Nefarian's End"] = "Nef II:  Electric Boogaloo",
+	-- To4W
 	["Al'Akir"] = "Big Al",
+	-- Firelands
+	--["Lord Rhyolith"] = "LEFT, LEFT, LEFT RIGHT LEFT",
 
 	-------- WotLK
 	-- ToC
--- a/bossmods.lua	Wed Apr 27 04:02:02 2011 +0000
+++ b/bossmods.lua	Wed Jun 15 03:59:13 2011 +0000
@@ -19,18 +19,19 @@
 - The callback for (3) must check if OL is appropriately active.
 
 ------ Constants
------- Locals
+------ Globals
 ------ Deadly Boss Mods
 ]]
 
 ------ Constants
 
------- Locals
+------ Globals
 local flib = LibStub("LibFarmbuyer")
 local pprint, tabledump = addon.pprint, flib.tabledump
 
 -- Lua
-local pairs, ipairs, tinsert, tremove, tonumber = pairs, ipairs, table.insert, table.remove, tonumber
+local pairs, ipairs, tinsert, tremove = pairs, ipairs, table.insert, table.remove
+local tonumber = tonumber
 
 -- WoW
 local GetRaidRosterInfo = GetRaidRosterInfo
--- a/core.lua	Wed Apr 27 04:02:02 2011 +0000
+++ b/core.lua	Wed Jun 15 03:59:13 2011 +0000
@@ -18,7 +18,7 @@
 ------ Saved variables
 ------ Constants
 ------ Addon member data
------- Locals
+------ Globals
 ------ Expiring caches
 ------ Ace3 framework stuff
 ------ Event handlers
@@ -84,7 +84,7 @@
 local flib = LibStub("LibFarmbuyer")
 addon.author_debug = flib.author_debug
 
--- Play cute games with namespaces here just to save typing.
+-- Play cute games with namespaces here just to save typing.  WTB Lua 5.2 PST.
 do local _G = _G setfenv (1, addon)
 
 	revision		= 15
@@ -149,7 +149,7 @@
                 "AceTimer-3.0", "AceComm-3.0", "AceConsole-3.0", "AceEvent-3.0")
 
 
------- Locals
+------ Globals
 local g_loot			= nil
 local g_restore_p		= nil
 local g_saved_tmp		= nil   -- restoring across a clear
@@ -326,7 +326,7 @@
 		end
 	end
 	option_defaults = nil
-	-- transition/remove old options
+	-- transition&remove old options
 	opts["forum_use_itemid"] = nil
 	if opts["forum_format"] then
 		opts.forum["Custom..."] = opts["forum_format"]
@@ -348,13 +348,14 @@
 	local r = assert(GetRealmName())
 	self.history_all[r] = self:_prep_new_history_category (self.history_all[r], r)
 	self.history = self.history_all[r]
-	OuroLootSV_hist = nil
+	--OuroLootSV_hist = nil
 
 	_init(self)
 	self.OnInitialize = nil
 end
 
 function addon:OnEnable()
+	--if not OuroLootSV_hist.PLAYER_LOGOUT then print"did not safely logout?" end; OuroLootSV_hist.PLAYER_LOGOUT = nil
 	self:RegisterEvent "PLAYER_LOGOUT"
 	self:RegisterEvent "RAID_ROSTER_UPDATE"
 
@@ -405,17 +406,18 @@
 	then
 		g_loot.autoshard = self.sharder
 		g_loot.threshold = self.threshold
-		--OuroLootSV = g_loot
-		--for i,e in ipairs(OuroLootSV) do
 		for i,e in ipairs(g_loot) do
 			e.cols = nil
 		end
 		OuroLootSV = g_loot
 	end
-	self.history.kind = nil
-	self.history.st = nil
-	self.history.byname = nil
+	for r,t in pairs(self.history_all) do if type(t) == 'table' then
+		t.realm = nil
+		t.st = nil
+		t.byname = nil
+	end end
 	OuroLootSV_hist = self.history_all
+	--OuroLootSV_hist.PLAYER_LOGOUT = true
 end
 
 function addon:RAID_ROSTER_UPDATE (event)
@@ -446,12 +448,17 @@
 	-- Recent loot cache
 	addon.recent_loot = create_new_cache ('loot', comm_cleanup_ttl)
 
-	local GetItemInfo = GetItemInfo
+	local GetItemInfo, GetItemIcon = GetItemInfo, GetItemIcon
 
 	-- 'from' and onwards only present if this is triggered by a broadcast
 	function addon:_do_loot (local_override, recipient, itemid, count, from, extratext)
-		local iname, ilink, iquality, _,_,_,_,_,_, itexture = GetItemInfo(itemid)
-		if not iname then return end   -- sigh
+		local itexture = GetItemIcon(itemid)
+		--local iname, ilink, iquality, _,_,_,_,_,_, itexture = GetItemInfo(itemid)
+		local iname, ilink, iquality = GetItemInfo(itemid)
+		if (not iname) or (not itexture) then
+			iname, ilink, iquality, itexture = 
+				UNKNOWN..': '..itemid, 'item:6948', ITEM_QUALITY_COMMON, [[ICONS\INV_Misc_QuestionMark]]
+		end
 		self.dprint('loot',">>_do_loot, R:", recipient, "I:", itemid, "C:", count, "frm:", from, "ex:", extratext)
 
 		local i
@@ -1171,6 +1178,9 @@
 --   ["OtherRealm"] = ......
 -- }
 do
+	local tsort = table.sort
+	local comp = function(L,R) return L.when > R.when end
+
 	-- Builds the map of names to array indices, using passed table or
 	-- self.history, and stores the result into its 'byname' field.  Also
 	-- called from the GUI code at least once.
@@ -1187,8 +1197,9 @@
 	function addon:_prep_new_history_category (prev_table, realmname)
 		local t = prev_table or {
 			--kind = 'realm',
-			realm = realmname,
+			--realm = realmname,
 		}
+		t.realm = realmname
 
 		--[[
 		t.cols = setmetatable({
@@ -1204,6 +1215,7 @@
 	end
 
 	-- Maps a name to an array index, creating new tables if needed.  Returns
+	-- the index and the table at that index.
 	function addon:get_loot_history (name)
 		local i
 		i = self.history.byname[name]
@@ -1212,18 +1224,52 @@
 			self.history[i] = { name=name }
 			self.history.byname[name] = i
 		end
-		return self.history[i]
+		return i, self.history[i]
 	end
 
 	function addon:_addHistoryEntry (lootindex)
 		local e = g_loot[lootindex]
-		local h = self:get_loot_history(e.person)
+		if e.kind ~= 'loot' then return end
+
+		local i,h = self:get_loot_history(e.person)
 		local n = {
 			id = e.id,
 			when = self:format_timestamp (g_today, e),
 			count = e.count,
 		}
-		h[#h+1] = n
+		tinsert (h, 1, n)
+	end
+
+	function addon:rewrite_history (realmname)
+		local r = assert(realmname)
+		self.history_all[r] = self:_prep_new_history_category (nil, r)
+		self.history = self.history_all[r]
+
+		local g_today_real = g_today
+		for i,e in ipairs(g_loot) do
+			if e.kind == 'time' then
+				g_today = e
+			elseif e.kind == 'loot' then
+				self:_addHistoryEntry(i)
+			end
+		end
+		g_today = g_today_real
+		self.hist_clean = nil
+
+		-- safety measure:  resort players' tables based on formatted timestamp
+		for i,h in ipairs(self.history) do
+			tsort (h, comp)
+		end
+	end
+
+	function addon:preen_history (realmname)
+		local r = assert(realmname)
+		for i,h in ipairs(self.history) do
+			tsort (h, comp)
+			while #h > 1 do
+				tremove (h)
+			end
+		end
 	end
 end
 
--- a/gui.lua	Wed Apr 27 04:02:02 2011 +0000
+++ b/gui.lua	Wed Jun 15 03:59:13 2011 +0000
@@ -3,7 +3,7 @@
 --[[
 Purely the AceGUI-related routines, and the subroutines needed for support.
 ------ Constants
------- Locals
+------ Globals
 ------ Behind the scenes routines
 ------ Main GUI Window
 ------ Popup dialogs
@@ -38,7 +38,7 @@
 local time_column1_used_mt = addon.time_column1_used_mt
 
 
------- Locals
+------ Globals
 local GUI = LibStub("AceGUI-3.0")
 local flib = LibStub("LibFarmbuyer")
 
@@ -240,6 +240,8 @@
 
 do
 	function addon:_fill_out_hist_data (opt_starting_index)
+		local new, del = flib.new, flib.del
+
 		-- Clearing history finishes this function with #hist==0 and hist_clean==0.
 		-- The next call typically detects this (#<1) and handles it.  If loot is
 		-- recorded before then, it results in hist_clean==0 and #hist==1, which
@@ -249,6 +251,7 @@
 			opt_starting_index = nil
 		end
 		if not self.history.st then
+			--print"creating ST!"
 			self.history.st = {
 				--[[{ kind = "realm",
 				  cols = setmetatable({
@@ -257,39 +260,62 @@
 			    }]]
 			}
 		end
+
+		-- for now
+		if self.hist_clean == #self.history then return end
+
 		local st = self.history.st
-		for i = (opt_starting_index or self.hist_clean or 1), #self.history do
-			local h = self.history[i]
-			local sti = i
-			if not st[sti] then
-				st[sti] = { kind = "history" }
-			end
-			local sth = st[sti]   -- corresponding ST entry for h
+		--print("starting history loop, #st ==", #st, "#history ==", #self.history)
+		for i,t in ipairs(st) do
+			del(t.cols[1])
+			del(t.cols[2])
+			del(t.cols[3])
+			del(t.cols)
+			del(t)
+			st[i] = nil
+		end
 
-			sth.cols = sth.cols or {
-				{ value = h.name },
-				{},--{ value = h[1].id },
-				{},--{ value = h[1].when },
-			}
+		--for i = (opt_starting_index or self.hist_clean or 1), #self.history do
+		local cache_okay = true
+		for pi,player in ipairs(self.history) do
+			local col1 = new()
+			col1.OLi   = pi
+			col1.OLn   = #player
+			col1.value = player.name   -- may spiffy this up in future
 
-			if sth.shown ~= h[1].id then
-				-- things have changed, redo the row with new data
-				local itexture = GetItemIcon(h[1].id)
-				local iname, ilink, iquality = GetItemInfo(h[1].id)
+			for li,loot in ipairs(player) do
+				local col2 = new()
+				col2.OLi   = li
+				local col3 = new()
+				col3.value = loot.when
+
+				local itexture = GetItemIcon(loot.id)
+				local iname, ilink, iquality = GetItemInfo(loot.id)
 				local textured
 				if itexture and iname then
-					textured = eoi_st_textured_item_format:format (itexture, self.quality_hexes[iquality], iname, h[1].count or "")
-					sth.shown = h[1].id
+					textured = eoi_st_textured_item_format:format (itexture,
+						self.quality_hexes[iquality], iname, loot.count or "")
 				else
-					textured = eoi_st_textured_item_format:format ([[ICONS\INV_Misc_QuestionMark]], self.quality_hexes[1], 'UNKNOWN', "")
+					textured = eoi_st_textured_item_format:format ([[ICONS\INV_Misc_QuestionMark]],
+						self.quality_hexes[ITEM_QUALITY_COMMON], 'UNKNOWN - TRY AGAIN', "")
+					cache_okay = false
 				end
-				sth.cols[2].value = textured
-				sth.cols[3].value = h[1].when
+				col2.value = textured
+
+				local dotcols = new (col1, col2, col3)
+				local st_entry = new()
+				st_entry.kind = 'history'
+				st_entry.OLwho = player.name
+				st_entry.cols = dotcols
+				tinsert (st, st_entry)
 			end
+		end
 
-		end
-		self.hist_clean = #self.history
+		--print("finished history loop, #st ==", #st)
+		self.hist_clean = cache_okay and #self.history or nil
 	end
+
+
 end
 
 
@@ -312,9 +338,9 @@
 	["opt"] = {title=[[Options]], desc=[[Options for fine-tuning behavior]]},
 	--["adv"] = {title=[[Advanced]], desc=[[Debugging and testing]]},
 }
-if addon.author_debug then
+--if addon.author_debug then
 _taborder = { "eoi", "hist", "help", "opt" }
-else _taborder = { "eoi", "help", "opt" } end
+--else _taborder = { "eoi", "help", "opt" } end
 
 --[[
 This is a table of callback functions, each responsible for drawing a tab
@@ -356,7 +382,7 @@
 		name, arg = strsplit('%',name)
 		if name == "--" then
 			tinsert (initial, {
-				disabled = true, text = "",
+				disabled = true, notCheckable = true, text = "",
 			})
 		else
 			if not funcs[name] then
@@ -706,25 +732,8 @@
 	return true  -- do not do anything further
 end
 
-local function hist_st_OnClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, ...)
-	if (row == nil) or (realrow == nil) then return false end  -- click column header, do default resorting
-	local h = data[realrow]
-	local kind = h.kind
-
-
-	return true  -- do not do anything further
-end
-
-local function hist_st_OnDoubleClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, ...)
-	if (row == nil) or (realrow == nil) then return true end  -- they clicked on column header, suppress reordering
-	local h = data[realrow]
-	local kind = h.kind
-
-	return true  -- do not do anything further
-end
-
 -- Used for EOI column 2 and Hist column 1.  Both are player name columns.
-local function eoi_st_col2_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...) 
+local function eoi_st_col2_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...)
 	if not fShow then
 		cellFrame.text:SetText("")
 		if cellFrame.icontexture then
@@ -784,8 +793,8 @@
 	},
 }
 
-local rowfilter_all
-local rowfilter_by_name = function (st, e)
+local player_filter_all
+local player_filter_by_name = function (st, e)
 	if e.kind ~= 'loot' then return true end
 	return e.person == _d:GetUserData("player filter name")
 end
@@ -861,7 +870,7 @@
 	-- No need to keep creating function closures that all just "return true",
 	-- instead we grab the one made inside lib-st.  There's no "get filter" API
 	-- so we just reach inside.
-	rowfilter_all = ST.Filter
+	player_filter_all = ST.Filter
 
 	-- Now set up the future drawing function...
 	tabs_OnGroupSelected["eoi"] = function(container,specials)
@@ -869,8 +878,8 @@
 		local st = _d:GetUserData("eoiST")
 
 		-- This is actually required each time
-		_d:SetUserData ("player filter clear", rowfilter_all)
-		_d:SetUserData ("player filter by name", rowfilter_by_name)
+		_d:SetUserData ("player filter clear", player_filter_all)
+		_d:SetUserData ("player filter by name", player_filter_by_name)
 
 		st:OuroLoot_Refresh()
 		st_widget:WrapST(st)
@@ -893,10 +902,10 @@
 		b:SetFullWidth(true)
 		b:SetCallback("OnClick", function (_b)
 			local st = _d:GetUserData("eoiST")
-			st:SetFilter(rowfilter_all)
+			st:SetFilter(player_filter_all)
 			_b:SetDisabled(true)
 		end)
-		b:SetDisabled(st.Filter == rowfilter_all)
+		b:SetDisabled(st.Filter == player_filter_all)
 		specials:AddChild(b)
 
 		local people = { "<nobody>" }
@@ -1012,12 +1021,28 @@
 		},
 	}
 
+	local hist_normal_status = [[Click on a row to view all history for that player only.  (Click column headers to re-sort.)]]
+	local hist_name_status = [[Right-click on any row to return to normal history display.]]
+
+	local history_filter_by_recent = function (st, e)
+		if e.kind ~= 'history' then return true end
+		return e.cols[2].OLi == 1
+	end
+
+	local history_filter_who
+	local history_filter_by_name = function (st, e)
+		if e.kind ~= 'history' then return true end
+		return e.OLwho == history_filter_who
+	end
+
 	-- Loot column
-	local function hist_st_col2_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...) 
+	local function hist_st_col2_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...)
+		print("col2 DCU", realrow)
 	end
 
 	-- Formatted timestamp column
-	local function hist_st_col3_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...) 
+	local function hist_st_col3_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...)
+		print("col3 DCU", realrow)
 		if not fShow then
 			cellFrame.text:SetText("")
 			return
@@ -1036,6 +1061,33 @@
 		--end
 	end
 
+	local function hist_st_OnClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, ...)
+		if (row == nil) or (realrow == nil) then return false end  -- click column header, do default resorting
+		local h = data[realrow]
+		local kind = h.kind
+
+		if history_filter_who and button == "RightButton" then  -- now filtering and wanting not to
+			history_filter_who = nil
+			stable:SetFilter(history_filter_by_recent)
+			setstatus(hist_normal_status)
+		elseif (not history_filter_who) and button == "LeftButton" then  -- not filtering and wanting to
+			history_filter_who = h.OLwho
+			stable:SetFilter(history_filter_by_name)
+			setstatus(hist_name_status)
+		end
+
+		return true  -- do not do anything further
+	end
+
+	--[[
+	local function hist_st_OnDoubleClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, ...)
+		if (row == nil) or (realrow == nil) then return true end  -- they clicked on column header, suppress reordering
+		local h = data[realrow]
+		local kind = h.kind
+
+		return true  -- do not do anything further
+	end]]
+
 	tabs_OnGroupSelected["hist"] = function(container,specials)
 		histST = LibStub("ScrollingTable"):CreateST(hist_st_cols,eoi_st_displayed_rows,eoi_st_rowheight)
 		if addon.author_debug then
@@ -1056,7 +1108,7 @@
 			OnEnter = eoi_st_OnEnter,
 			OnLeave = eoi_st_OnLeave,
 			OnClick = hist_st_OnClick,
-			--OnDoubleClick = eoi_st_OnDoubleClick,
+			--OnDoubleClick = hist_st_OnDoubleClick,
 		}
 		local oldrefresh = histST.Refresh
 		histST.Refresh = function (self, opt_index)
@@ -1068,8 +1120,12 @@
 			self:SortData()  -- calls hooked refresh
 		end
 
-		local function reset_current_realm()
-			local r = assert(GetRealmName())
+		histST:SetFilter(history_filter_by_recent)
+
+		-- Zaps history for the given realm, or the current (current-playing
+		-- realm, not currently-displayed realm) one if not specified.
+		local function reset_current_realm (opt_realmname)
+			local r = assert(opt_realmname or GetRealmName())
 			-- new .history table:
 			addon.history_all[r] = addon:_prep_new_history_category (nil, r)
 			addon.history = addon.history_all[r]
@@ -1077,7 +1133,6 @@
 			-- new .history.st table:
 			histST:OuroLoot_Refresh()
 			histST:SetData(addon.history.st)
-			addon:Print("You've clicked the history erase button!")
 		end
 
 		tabs_OnGroupSelected["hist"] = function(container,specials)
@@ -1088,6 +1143,7 @@
 			st_widget.tail_offset = 0
 			container:SetLayout("Fill")
 			container:AddChild(st_widget)
+			setstatus(hist_normal_status)
 
 			local b
 			do
@@ -1102,26 +1158,32 @@
 				b:SetList(realms)
 				b:SetValue(current)
 				b:SetCallback("OnValueChanged", function(_dd,event,choice)
-					print("chose realm", choice, realms[choice])
+					local r = realms[choice]
+					addon.history = addon:_prep_new_history_category (addon.history_all[r], r)
+					addon.hist_clean = nil
+					histST:OuroLoot_Refresh()
+					histST:SetData(addon.history.st)
+					-- Reset filters to normal
+					history_filter_who = nil
+					histST:SetFilter(history_filter_by_recent)
+					setstatus(hist_normal_status)
+					return addon:redisplay()
 				end)
 				specials:AddChild(b)
 			end
 
-			--[[
-			b = GUI:Create("Spacer")
-			b:SetFullWidth(true)
-			b:SetHeight(10)
-			specials:AddChild(b)
-			]]
+			--[[ b = GUI:Create("Spacer") b:SetFullWidth(true) b:SetHeight(10) specials:AddChild(b) ]]
 
 			b = mkbutton("Regenerate",
 				[[Erases all history entries from the displayed realm, and regenerates it from current loot information.]])
 			b:SetFullWidth(true)
 			b:SetDisabled (#addon.history == 0)
 			b:SetCallback("OnClick", function(_b)
+				addon:rewrite_history (addon.history.realm)
+				histST:OuroLoot_Refresh()
+				histST:SetData(addon.history.st)
 				addon:Print("%s history has been regenerated.", addon.history.realm)
 				return addon:redisplay()
-				--return tabs_OnGroupSelected_func(container,"OnGroupSelected","hist")
 			end)
 			specials:AddChild(b)
 
@@ -1129,7 +1191,8 @@
 				[[No confirmation!  |cffff1010Erases absolutely all> history entries from the displayed realm.]])
 			b:SetFullWidth(true)
 			b:SetCallback("OnClick", function (_b)
-				reset_current_realm()
+				reset_current_realm(addon.history.realm)
+				addon:Print("Stimpy, you idiot!  You've pushed the history erase button!")
 				return addon:redisplay()
 			end)
 			specials:AddChild(b)
@@ -1140,17 +1203,20 @@
 			b:SetCallback("OnClick", function (_b)
 				addon.history_all = {}
 				reset_current_realm()
+				addon:Print("Stimpy, you idiot!  You've pushed the history erase button!")
 				return addon:redisplay()
 			end)
 			specials:AddChild(b)
 
 			b = mkbutton('hist_clear_old', "Clear Older",
-				[[Preserves only the latest loot entry for each player on the current realm, removing all earlier ones.]])
+				[[Preserves only the latest loot entry for each player on the displayed realm, removing all earlier ones.]])
 			b:SetFullWidth(true)
 			b:SetCallback("OnClick", function (_b)
+				addon:preen_history(addon.history.realm)
 				addon:Print("All loot prior to the most recent entries has been erased.")
+				addon.hist_clean = nil
+				histST:OuroLoot_Refresh()
 				return addon:redisplay()
-				--return tabs_OnGroupSelected_func(container,"OnGroupSelected","hist")
 			end)
 			specials:AddChild(b)
 		end
@@ -1158,7 +1224,7 @@
 	end
 end
 
--- Tab 5:  Help (content in lootaux.lua)
+-- Tab 5:  Help (content in verbage.lua)
 do
 	local tabs_help_OnGroupSelected_func = function (treeg,event,category)
 		treeg:ReleaseChildren()
@@ -1487,8 +1553,6 @@
 			grp:AddChild(w)
 		end
 
-		scroll:AddChild(grp)
-
 		addon.sender_list.sort()
 		if #addon.sender_list.namesI > 0 then
 			local senders = table.concat(addon.sender_list.namesI,'\n')   -- sigh
@@ -1504,6 +1568,8 @@
 			grp:AddChild(w)
 		end
 
+		scroll:AddChild(grp)
+
 		w = mkbutton("ReloadUI", [[Does what you think it does.  Loot information is written out and restored.]])
 		w:SetFullWidth(true)
 		w:SetCallback("OnClick", ReloadUI)
@@ -1625,6 +1691,7 @@
 		_d = _display:GetUserData("eoiST")
 		self.display = nil
 		GUI:Release(_display)
+		flib.clear()
 		collectgarbage()
 	end)