local M,d="\077\117\108\116\105\076\105\110\101\069\100\105\116\066\111\120",33 local l=LibStub and LibStub("\065\099\101\071\085\073-\051\046\048",true)if not l or(l:GetWidgetVersion(M)or 0)>=d then return end local U=pairs local j,v=GetCursorInfo,ClearCursor local x,C=CreateFrame,UIParent local i=_G if not AceGUIMultiLineEditBoxInsertLink then hooksecurefunc("\067\104\097\116\069\100\105\116\095\073\110\115\101\114\116\076\105\110\107",function(...)return i.AceGUIMultiLineEditBoxInsertLink(...)end)end function i.AceGUIMultiLineEditBoxInsertLink(d)for M=1,l:GetWidgetCount(M),1 do local l=i[("\077\117\108\116\105\076\105\110\101\069\100\105\116\066\111\120\037\117\069\100\105\116"):format(M)]if l and(l:IsVisible()and l:HasFocus())then l:Insert(d)return true end end end local function A(M)M:SetHeight((M.numlines*14+(M.disablebutton and 19 or 41))+M.labelHeight)if M.labelHeight==0 then M.scrollBar:SetPoint("\084\079\080",M.frame,"\084\079\080",0,-23)else M.scrollBar:SetPoint("\084\079\080",M.label,"\066\079\084\084\079\077",0,-19)end if M.disablebutton then M.scrollBar:SetPoint("\066\079\084\084\079\077",M.frame,"\066\079\084\084\079\077",0,21)M.scrollBG:SetPoint("\066\079\084\084\079\077\076\069\070\084",0,4)else M.scrollBar:SetPoint("\066\079\084\084\079\077",M.button,"\084\079\080",0,18)M.scrollBG:SetPoint("\066\079\084\084\079\077\076\069\070\084",M.button,"\084\079\080\076\069\070\084")end end local function m(M)M=M.obj M.editBox:ClearFocus()if not M:Fire("\079\110\069\110\116\101\114\080\114\101\115\115\101\100",M.editBox:GetText())then M.button:Disable()end end local function f(M,d,l,U,j)M,l=M.obj.scrollFrame,-l local v=M:GetVerticalScroll()if l<v then M:SetVerticalScroll(l)else l=(l+j)-M:GetHeight()if l>v then M:SetVerticalScroll(l)end end end local function K(M)M:HighlightText(0,0)M.obj:Fire("\079\110\069\100\105\116\070\111\099\117\115\076\111\115\116")end local function P(M)M=M.obj if not M.entered then M.entered=true M:Fire("\079\110\069\110\116\101\114")end end local function Q(M)M=M.obj if M.entered then M.entered=nil M:Fire("\079\110\076\101\097\118\101")end end local function N(M)M=M.obj.editBox M:SetFocus()M:SetCursorPosition(M:GetNumLetters())end local function r(M)local d,l,U,x=j()if d=="\115\112\101\108\108"then if C_Spell and C_Spell.GetSpellName then U=C_Spell.GetSpellName(x)else U=GetSpellInfo(l,U)end elseif d~="\105\116\101\109"then return end v()M=M.obj local C=M.editBox if not C:HasFocus()then C:SetFocus()C:SetCursorPosition(C:GetNumLetters())end C:Insert(U)M.button:Enable()end local function B(M,d,l)M.obj.editBox:SetWidth(d)end local function z(M,d)if d then M=M.obj M:Fire("\079\110\084\101\120\116\067\104\097\110\103\101\100",M.editBox:GetText())M.button:Enable()end end local function J(M)M:HighlightText(0,0)M:SetCursorPosition(M:GetNumLetters())M:SetCursorPosition(0)M.obj.button:Disable()end local function s(M,d)local l=M.obj.editBox l:SetHitRectInsets(0,0,d,(l:GetHeight()-d)-M:GetHeight())end local function D(M,d,l)if l==0 then M.obj.editBox:SetHitRectInsets(0,0,0,0)else s(M,M:GetVerticalScroll())end end local function g(M)M.obj.editBox:SetFocus()M:SetScript("\079\110\083\104\111\119",nil)end local function G(M)l:SetFocus(M.obj)M.obj:Fire("\079\110\069\100\105\116\070\111\099\117\115\071\097\105\110\101\100")end local L={OnAcquire=function(M)M.editBox:SetText("")M:SetDisabled(false)M:SetWidth(200)M:DisableButton(false)M:SetNumLines()M.entered=nil M:SetMaxLetters(0)end;OnRelease=function(M)M:ClearFocus()end;SetDisabled=function(M,d)local l=M.editBox if d then l:ClearFocus()l:EnableMouse(false)l:SetTextColor(.5,.5,.5)M.label:SetTextColor(.5,.5,.5)M.scrollFrame:EnableMouse(false)M.button:Disable()else l:EnableMouse(true)l:SetTextColor(1,1,1)M.label:SetTextColor(1,.82,0)M.scrollFrame:EnableMouse(true)end end,SetLabel=function(M,d)if d and d~=""then M.label:SetText(d)if M.labelHeight~=10 then M.labelHeight=10 M.label:Show()end elseif M.labelHeight~=0 then M.labelHeight=0 M.label:Hide()end A(M)end;SetNumLines=function(M,d)if not d or d<4 then d=4 end M.numlines=d A(M)end;SetText=function(M,d)M.editBox:SetText(d)end;GetText=function(M)return M.editBox:GetText()end;SetMaxLetters=function(M,d)M.editBox:SetMaxLetters(d or 0)end,DisableButton=function(M,d)M.disablebutton=d if d then M.button:Hide()else M.button:Show()end A(M)end,ClearFocus=function(M)M.editBox:ClearFocus()M.frame:SetScript("\079\110\083\104\111\119",nil)end;SetFocus=function(M)M.editBox:SetFocus()if not M.frame:IsShown()then M.frame:SetScript("\079\110\083\104\111\119",g)end end,HighlightText=function(M,d,l)M.editBox:HighlightText(d,l)end,GetCursorPosition=function(M)return M.editBox:GetCursorPosition()end;SetCursorPosition=function(M,...)return M.editBox:SetCursorPosition(...)end}local F={bgFile="\073\110\116\101\114\102\097\099\101\092\084\111\111\108\116\105\112\115\092\085\073-\084\111\111\108\116\105\112-\066\097\099\107\103\114\111\117\110\100";edgeFile="\073\110\116\101\114\102\097\099\101\092\084\111\111\108\116\105\112\115\092\085\073-\084\111\111\108\116\105\112-\066\111\114\100\101\114";edgeSize=16,insets={left=4,right=3,top=4;bottom=3}}local function h()local d=x("\070\114\097\109\101",nil,C)d:Hide()local j=l:GetNextWidgetNum(M)local v=d:CreateFontString(nil,"\079\086\069\082\076\065\089","\071\097\109\101\070\111\110\116\078\111\114\109\097\108\083\109\097\108\108")v:SetPoint("\084\079\080\076\069\070\084",d,"\084\079\080\076\069\070\084",0,-4)v:SetPoint("\084\079\080\082\073\071\072\084",d,"\084\079\080\082\073\071\072\084",0,-4)v:SetJustifyH("\076\069\070\084")v:SetText(ACCEPT)v:SetHeight(10)local A=x("\066\117\116\116\111\110",("\037\115\037\100\066\117\116\116\111\110"):format(M,j),d,"\085\073\080\097\110\101\108\066\117\116\116\111\110\084\101\109\112\108\097\116\101")A:SetPoint("\066\079\084\084\079\077\076\069\070\084",0,4)A:SetHeight(22)A:SetWidth(v:GetStringWidth()+24)A:SetText(ACCEPT)A:SetScript("\079\110\067\108\105\099\107",m)A:Disable()local g=A:GetFontString()g:ClearAllPoints()g:SetPoint("\084\079\080\076\069\070\084",A,"\084\079\080\076\069\070\084",5,-5)g:SetPoint("\066\079\084\084\079\077\082\073\071\072\084",A,"\066\079\084\084\079\077\082\073\071\072\084",-5,1)g:SetJustifyV("\077\073\068\068\076\069")local h=x("\070\114\097\109\101",nil,d,"\066\097\099\107\100\114\111\112\084\101\109\112\108\097\116\101")h:SetBackdrop(F)h:SetBackdropColor(0,0,0)h:SetBackdropBorderColor(.4,.4,.4)local O=x("\083\099\114\111\108\108\070\114\097\109\101",("\037\115\037\100\083\099\114\111\108\108\070\114\097\109\101"):format(M,j),d,"\085\073\080\097\110\101\108\083\099\114\111\108\108\070\114\097\109\101\084\101\109\112\108\097\116\101")local X=i[O:GetName().."\083\099\114\111\108\108\066\097\114"]X:ClearAllPoints()X:SetPoint("\084\079\080",v,"\066\079\084\084\079\077",0,-19)X:SetPoint("\066\079\084\084\079\077",A,"\084\079\080",0,18)X:SetPoint("\082\073\071\072\084",d,"\082\073\071\072\084")h:SetPoint("\084\079\080\082\073\071\072\084",X,"\084\079\080\076\069\070\084",0,19)h:SetPoint("\066\079\084\084\079\077\076\069\070\084",A,"\084\079\080\076\069\070\084")O:SetPoint("\084\079\080\076\069\070\084",h,"\084\079\080\076\069\070\084",5,-6)O:SetPoint("\066\079\084\084\079\077\082\073\071\072\084",h,"\066\079\084\084\079\077\082\073\071\072\084",-4,4)O:SetScript("\079\110\069\110\116\101\114",P)O:SetScript("\079\110\076\101\097\118\101",Q)O:SetScript("\079\110\077\111\117\115\101\085\112",N)O:SetScript("\079\110\082\101\099\101\105\118\101\068\114\097\103",r)O:SetScript("\079\110\083\105\122\101\067\104\097\110\103\101\100",B)O:HookScript("\079\110\086\101\114\116\105\099\097\108\083\099\114\111\108\108",s)O:HookScript("\079\110\083\099\114\111\108\108\082\097\110\103\101\067\104\097\110\103\101\100",D)local H=x("\069\100\105\116\066\111\120",("\037\115\037\100\069\100\105\116"):format(M,j),O)H:SetAllPoints()H:SetFontObject(ChatFontNormal)H:SetMultiLine(true)H:EnableMouse(true)H:SetAutoFocus(false)H:SetCountInvisibleLetters(false)H:SetScript("\079\110\067\117\114\115\111\114\067\104\097\110\103\101\100",f)H:SetScript("\079\110\069\100\105\116\070\111\099\117\115\076\111\115\116",K)H:SetScript("\079\110\069\110\116\101\114",P)H:SetScript("\079\110\069\115\099\097\112\101\080\114\101\115\115\101\100",H.ClearFocus)H:SetScript("\079\110\076\101\097\118\101",Q)H:SetScript("\079\110\077\111\117\115\101\068\111\119\110",r)H:SetScript("\079\110\082\101\099\101\105\118\101\068\114\097\103",r)H:SetScript("\079\110\084\101\120\116\067\104\097\110\103\101\100",z)H:SetScript("\079\110\084\101\120\116\083\101\116",J)H:SetScript("\079\110\069\100\105\116\070\111\099\117\115\071\097\105\110\101\100",G)O:SetScrollChild(H)local q={button=A,editBox=H;frame=d,label=v;labelHeight=10,numlines=4;scrollBar=X,scrollBG=h;scrollFrame=O,type=M}for M,d in U(L)do q[M]=d end A.obj,H.obj,O.obj=q,q,q return l:RegisterAsWidget(q)end l:RegisterWidgetType(M,h,d)
local Type, Version = "MultiLineEditBox", 33
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end

-- Lua APIs
local pairs = pairs

-- WoW APIs
local GetCursorInfo, ClearCursor = GetCursorInfo, ClearCursor
local CreateFrame, UIParent = CreateFrame, UIParent
local _G = _G

--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]

if not AceGUIMultiLineEditBoxInsertLink then
	-- upgradeable hook
	hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIMultiLineEditBoxInsertLink(...) end)
end

function _G.AceGUIMultiLineEditBoxInsertLink(text)
	for i = 1, AceGUI:GetWidgetCount(Type) do
		local editbox = _G[("MultiLineEditBox%uEdit"):format(i)]
		if editbox and editbox:IsVisible() and editbox:HasFocus() then
			editbox:Insert(text)
			return true
		end
	end
end


local function Layout(self)
	self:SetHeight(self.numlines * 14 + (self.disablebutton and 19 or 41) + self.labelHeight)

	if self.labelHeight == 0 then
		self.scrollBar:SetPoint("TOP", self.frame, "TOP", 0, -23)
	else
		self.scrollBar:SetPoint("TOP", self.label, "BOTTOM", 0, -19)
	end

	if self.disablebutton then
		self.scrollBar:SetPoint("BOTTOM", self.frame, "BOTTOM", 0, 21)
		self.scrollBG:SetPoint("BOTTOMLEFT", 0, 4)
	else
		self.scrollBar:SetPoint("BOTTOM", self.button, "TOP", 0, 18)
		self.scrollBG:SetPoint("BOTTOMLEFT", self.button, "TOPLEFT")
	end
end

--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function OnClick(self)                                                     -- Button
	self = self.obj
	self.editBox:ClearFocus()
	if not self:Fire("OnEnterPressed", self.editBox:GetText()) then
		self.button:Disable()
	end
end

local function OnCursorChanged(self, _, y, _, cursorHeight)                      -- EditBox
	self, y = self.obj.scrollFrame, -y
	local offset = self:GetVerticalScroll()
	if y < offset then
		self:SetVerticalScroll(y)
	else
		y = y + cursorHeight - self:GetHeight()
		if y > offset then
			self:SetVerticalScroll(y)
		end
	end
end

local function OnEditFocusLost(self)                                             -- EditBox
	self:HighlightText(0, 0)
	self.obj:Fire("OnEditFocusLost")
end

local function OnEnter(self)                                                     -- EditBox / ScrollFrame
	self = self.obj
	if not self.entered then
		self.entered = true
		self:Fire("OnEnter")
	end
end

local function OnLeave(self)                                                     -- EditBox / ScrollFrame
	self = self.obj
	if self.entered then
		self.entered = nil
		self:Fire("OnLeave")
	end
end

local function OnMouseUp(self)                                                   -- ScrollFrame
	self = self.obj.editBox
	self:SetFocus()
	self:SetCursorPosition(self:GetNumLetters())
end

local function OnReceiveDrag(self)                                               -- EditBox / ScrollFrame
	local type, id, info, extra = GetCursorInfo()
	if type == "spell" then
		if C_Spell and C_Spell.GetSpellName then
			info = C_Spell.GetSpellName(extra)
		else
			info = GetSpellInfo(id, info)
		end
	elseif type ~= "item" then
		return
	end
	ClearCursor()
	self = self.obj
	local editBox = self.editBox
	if not editBox:HasFocus() then
		editBox:SetFocus()
		editBox:SetCursorPosition(editBox:GetNumLetters())
	end
	editBox:Insert(info)
	self.button:Enable()
end

local function OnSizeChanged(self, width, height)                                -- ScrollFrame
	self.obj.editBox:SetWidth(width)
end

local function OnTextChanged(self, userInput)                                    -- EditBox
	if userInput then
		self = self.obj
		self:Fire("OnTextChanged", self.editBox:GetText())
		self.button:Enable()
	end
end

local function OnTextSet(self)                                                   -- EditBox
	self:HighlightText(0, 0)
	self:SetCursorPosition(self:GetNumLetters())
	self:SetCursorPosition(0)
	self.obj.button:Disable()
end

local function OnVerticalScroll(self, offset)                                    -- ScrollFrame
	local editBox = self.obj.editBox
	editBox:SetHitRectInsets(0, 0, offset, editBox:GetHeight() - offset - self:GetHeight())
end

local function OnScrollRangeChanged(self, xrange, yrange)
	if yrange == 0 then
		self.obj.editBox:SetHitRectInsets(0, 0, 0, 0)
	else
		OnVerticalScroll(self, self:GetVerticalScroll())
	end
end

local function OnShowFocus(frame)
	frame.obj.editBox:SetFocus()
	frame:SetScript("OnShow", nil)
end

local function OnEditFocusGained(frame)
	AceGUI:SetFocus(frame.obj)
	frame.obj:Fire("OnEditFocusGained")
end

--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
	["OnAcquire"] = function(self)
		self.editBox:SetText("")
		self:SetDisabled(false)
		self:SetWidth(200)
		self:DisableButton(false)
		self:SetNumLines()
		self.entered = nil
		self:SetMaxLetters(0)
	end,

	["OnRelease"] = function(self)
		self:ClearFocus()
	end,

	["SetDisabled"] = function(self, disabled)
		local editBox = self.editBox
		if disabled then
			editBox:ClearFocus()
			editBox:EnableMouse(false)
			editBox:SetTextColor(0.5, 0.5, 0.5)
			self.label:SetTextColor(0.5, 0.5, 0.5)
			self.scrollFrame:EnableMouse(false)
			self.button:Disable()
		else
			editBox:EnableMouse(true)
			editBox:SetTextColor(1, 1, 1)
			self.label:SetTextColor(1, 0.82, 0)
			self.scrollFrame:EnableMouse(true)
		end
	end,

	["SetLabel"] = function(self, text)
		if text and text ~= "" then
			self.label:SetText(text)
			if self.labelHeight ~= 10 then
				self.labelHeight = 10
				self.label:Show()
			end
		elseif self.labelHeight ~= 0 then
			self.labelHeight = 0
			self.label:Hide()
		end
		Layout(self)
	end,

	["SetNumLines"] = function(self, value)
		if not value or value < 4 then
			value = 4
		end
		self.numlines = value
		Layout(self)
	end,

	["SetText"] = function(self, text)
		self.editBox:SetText(text)
	end,

	["GetText"] = function(self)
		return self.editBox:GetText()
	end,

	["SetMaxLetters"] = function (self, num)
		self.editBox:SetMaxLetters(num or 0)
	end,

	["DisableButton"] = function(self, disabled)
		self.disablebutton = disabled
		if disabled then
			self.button:Hide()
		else
			self.button:Show()
		end
		Layout(self)
	end,

	["ClearFocus"] = function(self)
		self.editBox:ClearFocus()
		self.frame:SetScript("OnShow", nil)
	end,

	["SetFocus"] = function(self)
		self.editBox:SetFocus()
		if not self.frame:IsShown() then
			self.frame:SetScript("OnShow", OnShowFocus)
		end
	end,

	["HighlightText"] = function(self, from, to)
		self.editBox:HighlightText(from, to)
	end,

	["GetCursorPosition"] = function(self)
		return self.editBox:GetCursorPosition()
	end,

	["SetCursorPosition"] = function(self, ...)
		return self.editBox:SetCursorPosition(...)
	end,
}

--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local backdrop = {
	bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
	edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
	insets = { left = 4, right = 3, top = 4, bottom = 3 }
}

local function Constructor()
	local frame = CreateFrame("Frame", nil, UIParent)
	frame:Hide()

	local widgetNum = AceGUI:GetNextWidgetNum(Type)

	local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
	label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
	label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -4)
	label:SetJustifyH("LEFT")
	label:SetText(ACCEPT)
	label:SetHeight(10)

	local button = CreateFrame("Button", ("%s%dButton"):format(Type, widgetNum), frame, "UIPanelButtonTemplate")
	button:SetPoint("BOTTOMLEFT", 0, 4)
	button:SetHeight(22)
	button:SetWidth(label:GetStringWidth() + 24)
	button:SetText(ACCEPT)
	button:SetScript("OnClick", OnClick)
	button:Disable()

	local text = button:GetFontString()
	text:ClearAllPoints()
	text:SetPoint("TOPLEFT", button, "TOPLEFT", 5, -5)
	text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -5, 1)
	text:SetJustifyV("MIDDLE")

	local scrollBG = CreateFrame("Frame", nil, frame, "BackdropTemplate")
	scrollBG:SetBackdrop(backdrop)
	scrollBG:SetBackdropColor(0, 0, 0)
	scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)

	local scrollFrame = CreateFrame("ScrollFrame", ("%s%dScrollFrame"):format(Type, widgetNum), frame, "UIPanelScrollFrameTemplate")

	local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
	scrollBar:ClearAllPoints()
	scrollBar:SetPoint("TOP", label, "BOTTOM", 0, -19)
	scrollBar:SetPoint("BOTTOM", button, "TOP", 0, 18)
	scrollBar:SetPoint("RIGHT", frame, "RIGHT")

	scrollBG:SetPoint("TOPRIGHT", scrollBar, "TOPLEFT", 0, 19)
	scrollBG:SetPoint("BOTTOMLEFT", button, "TOPLEFT")

	scrollFrame:SetPoint("TOPLEFT", scrollBG, "TOPLEFT", 5, -6)
	scrollFrame:SetPoint("BOTTOMRIGHT", scrollBG, "BOTTOMRIGHT", -4, 4)
	scrollFrame:SetScript("OnEnter", OnEnter)
	scrollFrame:SetScript("OnLeave", OnLeave)
	scrollFrame:SetScript("OnMouseUp", OnMouseUp)
	scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
	scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
	scrollFrame:HookScript("OnVerticalScroll", OnVerticalScroll)
	scrollFrame:HookScript("OnScrollRangeChanged", OnScrollRangeChanged)

	local editBox = CreateFrame("EditBox", ("%s%dEdit"):format(Type, widgetNum), scrollFrame)
	editBox:SetAllPoints()
	editBox:SetFontObject(ChatFontNormal)
	editBox:SetMultiLine(true)
	editBox:EnableMouse(true)
	editBox:SetAutoFocus(false)
	editBox:SetCountInvisibleLetters(false)
	editBox:SetScript("OnCursorChanged", OnCursorChanged)
	editBox:SetScript("OnEditFocusLost", OnEditFocusLost)
	editBox:SetScript("OnEnter", OnEnter)
	editBox:SetScript("OnEscapePressed", editBox.ClearFocus)
	editBox:SetScript("OnLeave", OnLeave)
	editBox:SetScript("OnMouseDown", OnReceiveDrag)
	editBox:SetScript("OnReceiveDrag", OnReceiveDrag)
	editBox:SetScript("OnTextChanged", OnTextChanged)
	editBox:SetScript("OnTextSet", OnTextSet)
	editBox:SetScript("OnEditFocusGained", OnEditFocusGained)


	scrollFrame:SetScrollChild(editBox)

	local widget = {
		button      = button,
		editBox     = editBox,
		frame       = frame,
		label       = label,
		labelHeight = 10,
		numlines    = 4,
		scrollBar   = scrollBar,
		scrollBG    = scrollBG,
		scrollFrame = scrollFrame,
		type        = Type
	}
	for method, func in pairs(methods) do
		widget[method] = func
	end
	button.obj, editBox.obj, scrollFrame.obj = widget, widget, widget

	return AceGUI:RegisterAsWidget(widget)
end

AceGUI:RegisterWidgetType(Type, Constructor, Version)
