Index: Aura.lua
===================================================================
--- Aura.lua	(revision 46451)
+++ Aura.lua	(working copy)
@@ -32,6 +32,7 @@
 local GetPlayerBuffApplications = GetPlayerBuffApplications
 local GetPlayerBuffTimeLeft = GetPlayerBuffTimeLeft
 local math_floor = math.floor
+local math_ceil = math.ceil
 local math_min = math.min
 local table_sort = table.sort
 local unpack = unpack
@@ -1184,18 +1185,21 @@
 		end
 	end
 
+	local num_buffs = #list
+
 	for i = #buffs, #list+1, -1 do
-		clear_buff_frame(buffs[i])
-		buffs[i] = nil
+		buffs[i]:Hide()
 	end
 
 	local do_buff_highlight = db.highlight.Buffs
 	local do_buff_highlight_type = db.highlightType.Buffs
 	local buff_highlight_colors = PitBull_Aura.db.profile.colors.buffs
+	local zoom_aura = PitBull_Aura.db.profile.zoomAura
 	local show_cooldown = profile.cooldown
 	local show_cooldown_text = profile.cooldownText
 	local cooldown_text_alpha = profile.cooldownTextAlpha
 
+	local must_relayout
 	for i, v in ipairs(list) do
 		local num, name, texture, applications, duration, timeLeft = unpack(v)
 		list[i] = del(v)
@@ -1205,27 +1209,25 @@
 		if not buffFrame then
 			buffFrame = newFrame("Button", auraFrame)
 			buffs[i] = buffFrame
+			buffFrame.unanchored = true
+			must_relayout = true
 
 			icon = newFrame("Texture", buffFrame, "BACKGROUND")
-			if PitBull_Aura.db.profile.zoomAura then
+			if zoom_aura then
 				icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
 			end
 			buffFrame.icon = icon
 			icon:ClearAllPoints()
 			icon:SetAllPoints(buffFrame)
 		else
+			buffFrame:Show()
 			text = buffFrame.text
 			icon = buffFrame.icon
 		end
 
 		icon:SetTexture(texture)
 
-		if not applications or applications <= 1 then
-			if text then
-				buffFrame.text = delFrame(text)
-				text = nil
-			end
-		else
+		if applications and applications > 1 then
 			if not text then
 				text = newFrame("FontString", buffFrame, "OVERLAY")
 				buffFrame.text = text
@@ -1236,6 +1238,8 @@
 				text:SetPoint("BOTTOMRIGHT", buffFrame, "BOTTOMRIGHT", 0, 0)
 			end
 			text:SetText(applications)
+		elseif text then
+			buffFrame.text = delFrame(text)
 		end
 		local border = buffFrame.border
 		if do_buff_highlight or (not texture and configMode) then
@@ -1251,10 +1255,8 @@
 			else
 				border:SetVertexColor(unpack(buff_highlight_colors["nil"]))
 			end
-		else
-			if border then
-				buffFrame.border = delFrame(border)
-			end
+		elseif border then
+			buffFrame.border = delFrame(border)
 		end
 
 		local cooldownText = buffFrame.cooldownText
@@ -1358,22 +1360,23 @@
 		end
 	end
 	list = del(list)
-	local num_buffs = #buffs
+	auraFrame.num_buffs = num_buffs
 
+	auraFrame:SetHeight(math_ceil(num_buffs / max_buffs_per_row) * size)
+	if not must_relayout then 
+		return
+	end
+	
 	local lastrow = 1
+	local direction = db.buffdirection
+	local pos_a = 0
+	local pos_b = 0
+	local group_grow = db.grow
+	local group_flip = db.flip
 
-	if num_buffs == 0 then
-		auraFrame.buffs = del(buffs)
-	else
-		local direction = db.buffdirection
-		local pos_a = 0
-		local pos_b = 0
-		local group_grow = db.grow
-		local group_flip = db.flip
-
-		for i = 1, num_buffs do
-			local buff = buffs[i]
-			buff:Show()
+	for i = 1, num_buffs do
+		local buff = buffs[i]
+		if buff.unanchored then
 			buff:ClearAllPoints()
 			-- Workaround, find and fix invalid sizes.
 			buff:SetWidth(size)
@@ -1403,14 +1406,16 @@
 					buff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_b, pos_a * group_grow)
 				end
 			end
-			if i ~= num_buffs and i % max_buffs_per_row == 0 then
-				lastrow = lastrow + 1
-				pos_a = pos_a + size
-				pos_b = 0
-			else
-				pos_b = pos_b + size
-			end
+			buff.unanchored = nil
 		end
+		buff:Show()
+		if i ~= num_buffs and i % max_buffs_per_row == 0 then
+			lastrow = lastrow + 1
+			pos_a = pos_a + size
+			pos_b = 0
+		else
+			pos_b = pos_b + size
+		end
 	end
 
 	if not split then
@@ -1517,9 +1522,10 @@
 		end
 	end
 
-	for j = #debuffs, #list+1, -1 do
-		clear_buff_frame(debuffs[j])
-		debuffs[j] = nil
+	local num_debuffs = #list
+
+	for i = #debuffs, #list+1, -1 do
+		debuffs[i]:Hide()
 	end
 
 	local do_debuff_highlight = db.highlight.Debuffs
@@ -1529,6 +1535,7 @@
 	local show_cooldown_text = profile.cooldownText
 	local cooldown_text_alpha = profile.cooldownTextAlpha
 
+	local must_relayout
 	for i, v in ipairs(list) do
 		local num, name, texture, applications, dispelType, duration, timeLeft = unpack(v)
 		list[i] = del(v)
@@ -1537,6 +1544,8 @@
 		if not debuffFrame then
 			debuffFrame = newFrame("Button", auraFrame)
 			debuffs[i] = debuffFrame
+			debuffFrame.unanchored = true
+			must_relayout = true
 
 			icon = newFrame("Texture", debuffFrame, "BACKGROUND")
 			if PitBull_Aura.db.profile.zoomAura then
@@ -1546,6 +1555,7 @@
 			icon:ClearAllPoints()
 			icon:SetAllPoints(debuffFrame)
 		else
+			debuffFrame:Show()
 			text = debuffFrame.text
 			icon = debuffFrame.icon
 		end
@@ -1689,43 +1699,46 @@
 			end
 		end
 	end
+
 	list = del(list)
 
-	local num_debuffs = #debuffs
+	if num_debuffs == 0 then return end
 
-	if num_debuffs == 0 then
-		auraFrame.debuffs = del(debuffs)
-	elseif split then
-		-- note that this is the top row that we"ll be using for the first few debuffs.  split mode they descend, nonsplit they ascend
+	if split then
+		if not must_relayout then return end
+		-- note that this is the top row that we'll be using for the first few debuffs.  split mode they descend, nonsplit they ascend
 		local direction = db.debuffdirection
 		local pos_a = 0
 		local pos_b = 0
 
 		for i = 1, num_debuffs do
 			local debuff = debuffs[i]
+			if debuff.unanchored then
+				debuff:ClearAllPoints()
+				-- Workaround, find and fix invalid sizes.
+				debuff:SetWidth(size)
+				debuff:SetHeight(size)
+				if direction == "Up then Left" then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", -pos_a, pos_b)
+				elseif direction == "Up then Right" then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_a, pos_b)
+				elseif direction == "Down then Left" then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", -pos_a, -pos_b)
+				elseif direction == "Down then Right" then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_a, -pos_b)
+				elseif direction == "Left then Up" then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", -pos_b, pos_a)
+				elseif direction == "Left then Down" then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", -pos_b, -pos_a)
+				elseif direction == "Right then Up" then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_b, pos_a)
+				elseif direction == "Right then Down" then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_b, -pos_a)
+				end
+				debuff.unanchored = nil
+			end
 			debuff:Show()
 			debuff:SetBackdropBorderColor(1,0,0)
-			debuff:ClearAllPoints()
-			-- Workaround, find and fix invalid sizes.
-			debuff:SetWidth(size)
-			debuff:SetHeight(size)
-			if direction == "Up then Left" then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", -pos_a, pos_b)
-			elseif direction == "Up then Right" then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_a, pos_b)
-			elseif direction == "Down then Left" then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", -pos_a, -pos_b)
-			elseif direction == "Down then Right" then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_a, -pos_b)
-			elseif direction == "Left then Up" then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", -pos_b, pos_a)
-			elseif direction == "Left then Down" then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", -pos_b, -pos_a)
-			elseif direction == "Right then Up" then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_b, pos_a)
-			elseif direction == "Right then Down" then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_b, -pos_a)
-			end
 			if i % max_debuffs_per_row == 0 then
 				pos_a = pos_a + size
 				pos_b = 0
@@ -1741,7 +1754,7 @@
 		end
 
 		local max_buffs_per_row = math_floor(auraFrame_width / buffsize)
-		local num_buffs = auraFrame.buffs and #auraFrame.buffs or 0
+		local num_buffs = auraFrame.num_buffs or 0
 
 		local num_buffs_bottomrow = num_buffs % max_buffs_per_row
 		local num_debuffs_toprow = num_debuffs % max_debuffs_per_row
@@ -1757,6 +1770,7 @@
 		-- if one row"s full and the other isnt, push it the pertaining value.
 		((num_debuffs_toprow == 0 and num_buffs_bottomrow > 0) and buffsize or 0) +
 		((num_debuffs_toprow > 0 and num_buffs_bottomrow == 0) and size or 0)
+		
 
 		local flip = db.flip
 		flip = (flip and buffs) or (not flip and not buffs)
@@ -1764,6 +1778,8 @@
 
 		offset = grow == 1 and offset - buffsize + size or grow * offset
 
+		if offset == auraFrame.offset and not must_relayout then return end
+
 		-- note that this will be the bottom row that we draw debuffs on.
 		local row = math_floor(num_debuffs / max_debuffs_per_row)
 		local pos_b = 0
@@ -1774,14 +1790,17 @@
 			local debuff = debuffs[i]
 			debuff:Show()
 			debuff:SetBackdropBorderColor(1,0,0)
-			debuff:ClearAllPoints()
-			-- Workaround, find and fix invalid sizes.
-			debuff:SetWidth(size)
-			debuff:SetHeight(size)
-			if flip then
-				debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_b, pos_a)
-			else
-				debuff:SetPoint("TOPRIGHT", auraFrame, "TOPRIGHT", -pos_b, pos_a)
+			if offset ~= auraFrame.offset or debuff.unanchored then
+				debuff:ClearAllPoints()
+				-- Workaround, find and fix invalid sizes.
+				debuff:SetWidth(size)
+				debuff:SetHeight(size)
+				if flip then
+					debuff:SetPoint("TOPLEFT", auraFrame, "TOPLEFT", pos_b, pos_a)
+				else
+					debuff:SetPoint("TOPRIGHT", auraFrame, "TOPRIGHT", -pos_b, pos_a)
+				end
+				debuff.unanchored = nil
 			end
 			if i % max_debuffs_per_row == 0 then
 				pos_b = 0
@@ -1790,6 +1809,7 @@
 				pos_b = pos_b + size
 			end
 		end
+		auraFrame.offset = offset
 	end
 end
 
@@ -1797,16 +1817,16 @@
 	if not frame.debuffhighlight then
 		return
 	end
-	local frameHighlight = PitBull_Aura.db.profile[frame.group].frameHighlight
+	local db = PitBull_Aura.db.profile[frame.group]
+	local frameHighlight = db.frameHighlight
 
-	local htexture, hdispel, hashighlight, checkagain
+	local hashighlight
 
-	if frameHighlight == "Never" or ((frameHighlight == "Cureable by me" or frameHighlight == "Cureable") and not UnitIsFriend("player", unit)) then
-	else
-		for i = 1, 40 do
-			if not hashighlight or hashighlight == "nil" or checkagain then -- if hashighlight is "nil" we keep trying there might be a curable debuff we prioritize those for highlighting
-				local _
-				_, _, htexture, _, hdispel = UnitDebuff(unit, i) -- ignore the raidfilter for frame highlighting
+	if frameHighlight ~= "Cureable by me" and frameHighlight ~= "Cureable" or UnitIsFriend("player", unit) then
+		local i = 1
+		while true do
+			if not hashighlight or hashighlight == "nil" then -- if hashighlight is "nil" we keep trying there might be a curable debuff we prioritize those for highlighting
+				local _, _, htexture, _, hdispel = UnitDebuff(unit, i) -- ignore the raidfilter for frame highlighting
 				if htexture then
 					if not hdispel then -- no dispel type set
 						if frameHighlight == "All Debuffs" then -- only set highlight to "nil"  if we want to show all debuffs
@@ -1823,6 +1843,7 @@
 						hashighlight = hdispel
 						break -- break here, we"ve got a cureable by me debuff...
 					end
+					i = i + 1
 				else
 					break
 				end
@@ -1831,7 +1852,8 @@
 	end
 
 	if hashighlight then
-		local style = PitBull_Aura.db.profile[frame.group].highlightStyle
+--[[
+		local style = db.highlightStyle
 		if style == "border" then
 			frame.debuffhighlight:SetTexture(debuffHighlightBorder_path)
 		elseif style == "thinborder" then
@@ -1841,6 +1863,7 @@
 		end
 		frame.debuffhighlight:SetBlendMode("ADD")
 		frame.debuffhighlight:SetAlpha(0.75)
+]]
 		local r,g,b = unpack(PitBull_Aura.db.profile.colors.debuffs[hashighlight])
 		frame.debuffhighlight:SetVertexColor(r,g,b)
 		frame.debuffhighlight:Show()
@@ -1874,21 +1897,13 @@
 	end
 end
 
-do
-	local mt = {__index = function(t,k)
-		t[k] = 0
-		return 0
-	end}
-	local shortframedelay = setmetatable({}, mt)
-	local longframedelay = setmetatable({}, mt)
-	function PitBull_Aura:OnUpdateFrame(unit, frame)
-		if not frame.auraFrame or self.db.profile[frame.group].hidden or not unitsShown[frame] then
-			return
-		end
-		if not IsWackyUnit[unit] then
-			self:UpdateAuras(unit, frame)
-		end
+function PitBull_Aura:OnUpdateFrame(unit, frame)
+	if not frame.auraFrame or self.db.profile[frame.group].hidden or not unitsShown[frame] then
+		return
 	end
+	if not IsWackyUnit[unit] then
+		self:UpdateAuras(unit, frame)
+	end
 end
 
 local num = 0
@@ -1935,12 +1950,12 @@
 
 function PitBull_Aura:OnUpdateFont(font, fontsize)
 	for unit,frame in PitBull:IterateUnitFrames() do
-		self:ClearAuras(unit, frame)
+		self:ClearAuras(frame)
 		self:UpdateAuras(unit, frame)
 	end
 end
 
-function PitBull_Aura:ClearAuras(unit, frame)
+function PitBull_Aura:ClearAuraBuffs(frame)
 	if not frame.auraFrame then
 		return
 	end
@@ -1952,7 +1967,9 @@
 		end
 		frame.auraFrame.buffs = del(buffs)
 	end
+end
 
+function PitBull_Aura:ClearAuraDebuffs(frame)
 	local debuffs
 	if frame.auraFrame2 then
 		debuffs = frame.auraFrame2.debuffs
@@ -1972,9 +1989,14 @@
 	end
 end
 
+function PitBull_Aura:ClearAuras(frame)
+	self:ClearAuraBuffs(frame)
+	self:ClearAuraDebuffs(frame)
+end
+
 function PitBull_Aura:OnClearUnitFrame(unit, frame)
 	if frame.auraFrame then
-		self:ClearAuras(unit, frame)
+		self:ClearAuras(frame)
 
 		frame.auraFrame = delFrame(frame.auraFrame)
 		if frame.auraFrame2 then
@@ -2010,7 +2032,7 @@
 	end
 	unitsShown[frame] = not now
 	if now then
-		self:ClearAuras(unit, frame)
+		self:ClearAuras(frame)
 	else
 		self:UpdateAuras(unit, frame)
 	end
@@ -2771,7 +2793,7 @@
 			set = function(value)
 				PitBull_Aura.db.profile.zoomAura = value
 				for unit, frame in PitBull:IterateUnitFrames() do
-					PitBull_Aura:ClearAuras(unit, frame)
+					PitBull_Aura:ClearAuras(frame)
 					PitBull_Aura:UpdateAuras(unit, frame)
 				end
 			end,
