view LibFarmbuyer.lua @ 66:43913e02a1ef

Detect LFR loot as best we can, and bundle it into the same warning given for heroic loot formatted by name only. Less tedious method of bumping data revisions.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Fri, 27 Apr 2012 10:11:56 +0000
parents 81d5449621f8
children 8442272a8418
line wrap: on
line source
--[[
Not really meant for public use.  Stuff that I keep using everywhere and
got tired of reimplementing, or even copy-and-pasting.  The notes here are
reminders to myself.

Library contents:
- author_debug
  Evaluates to true if I'm hacking on something.

- tableprint(t[,f])
  A single print() call to the contents of T, including nils; strings are
  cleaned up with respect to embedded '|'/control chars.  If a function F is
  passed, calls that instead of print().  Returns the accumulated string and
  either T or the returned values of F, depending on which was used.

- safeprint(...)
  Same as tableprint() on the argument list.  Returns the results of tableprint.
  Generates some garbage.

- safeiprint(...)
  Same as safeprint() but with <index> numbers inserted.  Returns the results
  of tableprint.  Generates some garbage.
  Ex:  safeiprint(a,b,c)  -->  <1>,a,<2>,b,<3>,c

- safefprint/safefiprint(f,...)
  Takes a function F as first parameter, for passing to tableprint().

- t = StaticPopup(t)
  Fills out "typical" settings inside T, especially if T contains any kind
  of editbox:
   + cannot accept an empty editbox
   + pressing Enter runs OnAccept (also will not accept empty editbox)
   + editbox grabs keyboard focus
   + OnAccept runs with editbox's text in dialog.usertext
  Returns T.

- nullfunc()
  Empty placeholder function.  Will be less useful if WoW ever moves to Lua 5.2.
  This is a fascinating and educational place to insert print calls...

- tabledump(t)/dumptable(t)
  If author_debug, this runs the builtin /dump command on T.  Otherwise nothing.

- DoOnceNextUpdate(f)
  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", 16
assert(LibStub,MAJOR.." requires LibStub")
local lib = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end

_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


----------------------------------------------------------------------
--[[
	safeprint
]]
local tconcat, tostring, tonumber = table.concat, tostring, tonumber
local function undocontrol(c)
	return ("\\%.3d"):format(c:byte())
end
function lib.safeprint(...)
	local args = { n=select('#',...), ... }
	return lib.tableprint(args)
end
function lib.safefprint(f,...)
	local args = { n=select('#',...), ... }
	return lib.tableprint(args,f)
end
function lib.safeiprint(...)
	local args = { n=select('#',...), ... }
	local last = args.n
	while last > 0 do
		table.insert (args, last, "<"..last..">")
		last = last - 1
	end
	args.n = 2 * args.n
	return lib.tableprint(args)
end
function lib.safefiprint(f,...)
	local args = { n=select('#',...), ... }
	local last = args.n
	while last > 0 do
		table.insert (args, last, "<"..last..">")
		last = last - 1
	end
	args.n = 2 * args.n
	return lib.tableprint(args,f)
end
function lib.tableprint(t,f)
	for i = 1, (tonumber(t.n) or #t) do
		t[i] = tostring(t[i]):gsub('\124','\124\124')
		                     :gsub('(%c)', undocontrol)
	end
	local msg = tconcat(t,' ', 1, tonumber(t.n) or #t)
	if type(f) == 'function' then
		return msg,f(msg)
	else
		print(msg)
		return msg,t
	end
end

-- See below for global versions.


----------------------------------------------------------------------
local StaticPopupDialogs = _G.StaticPopupDialogs

local function EditBoxOnTextChanged_notempty (editbox) -- this is also called when first shown
	if editbox:GetText() ~= "" then
		editbox:GetParent().button1:Enable()
	else
		editbox:GetParent().button1:Disable()
	end
end
local function EditBoxOnEnterPressed_accept (editbox)
	if editbox:GetText() == "" then return end
	local dialog = editbox:GetParent()
	StaticPopupDialogs[dialog.which].OnAccept (dialog, dialog.data, dialog.data2)
	dialog:Hide()
end
local function OnShow_witheditbox (dialog, data)
	local info = StaticPopupDialogs[dialog.which]
	--dialog[info.hasWideEditBox and "wideEditBox" or "editBox"]:SetFocus()
	dialog.editBox:SetFocus()
    if info.farm_OnShow then
        return info.farm_OnShow (dialog, data)
    end
end
local function OnAccept_witheditbox (dialog, data, data2)
	local info = StaticPopupDialogs[dialog.which]
	--dialog.usertext = dialog[info.hasWideEditBox and "wideEditBox" or "editBox"]:GetText():trim()
	dialog.usertext = dialog.editBox:GetText():trim()
    if info.farm_OnAccept then
        return info.farm_OnAccept (dialog, data, data2)
    end
end
local function OnHide_cleanup (dialog)
	dialog.data = nil
	dialog.data2 = nil
end

--[[
	StaticPopup
]]
function lib.StaticPopup (t)
	if t.hasEditBox then
		t.EditBoxOnTextChanged = EditBoxOnTextChanged_notempty
		t.EditBoxOnEnterPressed = EditBoxOnEnterPressed_accept
		if t.OnShow then
			t.farm_OnShow = t.OnShow
		end
		t.OnShow = OnShow_witheditbox
		if t.OnAccept then
			t.farm_OnAccept = t.OnAccept
		end
		t.OnAccept = OnAccept_witheditbox
		-- this calls OnCancel with "clicked", unless noCancelOnEscape is set
		t.EditBoxOnEscapePressed = StaticPopup_EscapePressed
	end

	if not t.OnHide then
		t.OnHide = OnHide_cleanup
	end

	t.timeout = 0
	t.whileDead = true
	t.hideOnEscape = true
	t.enterClicksFirstButton = true
	t.preferredIndex = 3  -- http://forums.wowace.com/showthread.php?t=19960

	return t
end


----------------------------------------------------------------------
--[[
This is ugly, but at least it all gets GC'd almost immediately.
]]
function lib.nullfunc() end

if ({
	["Bandwagon"] = true, ["Kilvin"] = true, ["Waterfaucet"] = true,
	["Farmbuyer"] = true, ["Oxdeadbeef"] = true, ["Pointystick"] = true,
	["Angryhobbit"] = true, ["Malrubius"] = true, ["Hemogoblin"] = true,
	["Ossipago"] = true,
})[UnitName("player")] then
	lib.author_debug = true
	_G.safeprint = lib.safeprint
	_G.safeiprint = lib.safeiprint
	function lib.tabledump(t)
		_G.UIParentLoadAddOn("Blizzard_DebugTools")
		_G.LibF_DEBUG = t
		_G.SlashCmdList.DUMP("LibF_DEBUG")
	end
else
	lib.tabledump = lib.nullfunc
end
lib.dumptable = lib.tabledump


----------------------------------------------------------------------
--[[
	DoOnceNextUpdate
]]
do
	local frame = CreateFrame("Frame", "LibFarmbuyerDONUFrame")
	frame:Hide()
	frame:SetScript("OnUpdate", function()
		frame:Hide()
		local q = frame.nexttime
		local tmp
		frame.nexttime = nil
		while q do
			tmp = q
			q.f(frame)
			q = q.n
			del(tmp)
		end
	end)

	function lib.DoOnceNextUpdate (func)
		local nextt = new()
		nextt.f = func
		nextt.n = frame.nexttime
		frame.nexttime = nextt
		frame:Show()
	end
end


----------------------------------------------------------------------
--[[
	safecall
]]
do
	local xpcall = xpcall

	local function errorhandler(err)
		--return geterrorhandler()(err)
		--print("in error handler", err)
		return err
	end

	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", tconcat(ARGS, ", "))
		return assert(loadstring(code, "LibF/safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
	end

	local Dispatchers = setmetatable({
		[0] = function(func)
			return xpcall (func, errorhandler)
		end
	}, {
		__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