--[[ Name: Prat 3.0 (chatsections.lua) Revision: $Revision: 79217 $ Author(s): Sylvaanar (sylvanaar@mindspring.com) Inspired By: Prat 2.0, Prat, and idChat2 by Industrial Website: http://files.wowace.com/Prat/ Documentation: http://www.wowace.com/wiki/Prat Forum: http://www.wowace.com/forums/index.php?topic=6243.0 SVN: http://svn.wowace.com/wowace/trunk/Prat/ Description: Implements the chat string sectioning service ]] --[[ BEGIN STANDARD HEADER ]]-- -- Imports local _G = _G local LibStub = LibStub local setmetatable = setmetatable local pairs, ipairs = pairs, ipairs local tinsert, tremove, tconcat = table.insert, table.remove, table.concat local string = string local strsub = string.sub local strsplit = strsplit local tonumber, tostring = tonumber, tostring local strlower = strlower local strlen = strlen local type = type local next, wipe = next, wipe --local function RunOldMessageEventFilters(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) -- local filter = false -- local chatFilters = _G.ChatFrame_GetMessageEventFilters and _G.ChatFrame_GetMessageEventFilters(event) -- local newarg1 = arg1 -- -- if chatFilters then -- for _, filterFunc in next, chatFilters do -- filter, newarg1 = filterFunc(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) -- if filter then -- return true -- end -- arg1 = newarg1 or arg1 -- end -- end -- -- return filter, arg1 --end -- arg1, filterthisout = RunMessageEventFilters(event, arg1) local newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12 local function RunMessageEventFilters(frame, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) local filter = false local chatFilters = _G.ChatFrame_GetMessageEventFilters and _G.ChatFrame_GetMessageEventFilters(event) if chatFilters then for _, filterFunc in next, chatFilters do filter, newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12 = filterFunc(frame, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) if filter then return true elseif ( newarg1 ) then arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 = newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12 end end end return filter, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 end -- Isolate the environment setfenv(1, SVC_NAMESPACE) --[[ END STANDARD HEADER ]]-- -- This is the structure of the chat message once it is split -- section delimiters are uppercase inside and lower case outside -- ie. cC CHANNEL Cc = [ channame ] SplitMessageSrc = { -- todo, incidicate which module uses which field, and remove unused fields PRE = "", nN = "", CHANLINK = "", NN = "", cC = "", CHANNELNUM = "", CC = "", CHANNEL = "", zZ = "", ZONE = "", Zz = "", Cc = "", TYPEPREFIX = "", Nn = "", fF = "", FLAG = "", Ff = "", pP = "", lL = "", -- link start PLAYERLINK= "", PLAYERLINKDATA = "", LL = "", -- link text start PLAYER = "", sS = "", SERVER = "", Ss = "", Ll = "", -- link text end Pp = "", TYPEPOSTFIX = "", mM = "", gG = "", LANGUAGE = "", Gg = "", MESSAGE = "", Mm = "", POST = "", } SplitMessageIdx = { "PRE", "nN", "CHANLINK", "NN", "cC", "CHANNELNUM", "CC", "CHANNEL", -- Zone is not usually included -- "zZ", -- "ZONE", -- "Zz", "Cc", "TYPEPREFIX", "Nn", "fF", "FLAG", "Ff", "pP", "lL", "PLAYERLINK", "PLAYERLINKDATA", "LL", "PLAYER", "sS", "SERVER", "Ss", "Ll", "Pp", "TYPEPOSTFIX", "mM", "gG", "LANGUAGE", "Gg", "MESSAGE", "Mm", "POST", } SplitMessage = {} SplitMessageOrg = {} SplitMessageOut = { MESSAGE = "", TYPE = "", TARGET = "", CHANNEL = "", LANGUAGE = "", } setmetatable(SplitMessageOrg, { __index=SplitMessageSrc }) setmetatable(SplitMessage, { __index=SplitMessageOrg }) do local t = {} function BuildChatText(message, index) local index = index or SplitMessageIdx --todo local s = message for k in pairs(t) do t[k] = nil end for i,v in ipairs(index) do tinsert(t, s[v]) end return tconcat(t, "") end end function RegisterMessageItem(itemname, anchorvar, relativepos) --[[ RegisterMessageItem: API to allow other modules to inject new items into the components making up a chat message. Primarily intended to help resolve conflicts between modules. - itemname = name of the variable to be injected - aftervar = the position in the chat message after which the item will be displayed - relativepos = "before" or "after" Leave aftervar blank to position the item at the beginning of the list. If you would like to change the item's position in the chat message, call :RegisterMessageItem() again with a different value for aftervar. Example: -------- The mod Prat_ExampleMod counts the number of times people say the word "Example" and you would like to display the count for a player before their name in a chat message. Default chat message structure contains: ... cC CHANNEL Cc .. pP PLAYER Pp ... This means that the module should use the following: RegisterMessageItem('NUMEXAMPLES', 'Cc') Which would then alter the structure of chat messages to be: .. CHANNEL Cc .. NUMEXAMPLES .. pP PLAYER ... ]] local pos = 1 if SplitMessageSrc[itemname] then -- ResetSeparators(itemname) local oldpos = GetMessageItemIdx(itemname) if oldpos ~= 0 then tremove(SplitMessageIdx, oldpos) end end if anchorvar then pos = GetMessageItemIdx(anchorvar) + (relativepos == "before" and 0 or 1) end tinsert(SplitMessageIdx, pos, itemname) SplitMessageSrc[itemname] = "" end function GetMessageItemIdx(itemname) for i, v in ipairs(SplitMessageIdx) do if v == itemname then return i end end return 0 end function ClearChatSections(message) if message then wipe(message) end -- for k,v in pairs(message) do -- message[k] = SplitMessageSrc[k] and nil -- WTF? -- end end local function safestr(s) return s or "" end function SplitChatMessage(frame, event, ...) local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 = ... ClearChatSections(SplitMessageOrg) ClearChatSections(SplitMessage) if ( strsub((event or ""), 1, 8) == "CHAT_MSG" ) then local type = strsub(event, 10) local info = _G.ChatTypeInfo[type] local s = SplitMessageOrg s.GUID = arg12 --[===[@debug@ s.ARGS = { ... } if CHAT_PLAYER_GUIDS then if s.GUID and s.GUID:len() > 0 then s.GUIDINFO = { _G.GetPlayerInfoByGUID(s.GUID) } end end --@end-debug@]===] -- if NEW_CHATFILTERS then local kill, newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12 = RunMessageEventFilters(frame, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) if kill then return true end if newarg1 ~= nil then arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 = newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12 end -- else -- local kill, newarg1 = RunOldMessageEventFilters(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) -- if kill then -- return true -- end -- -- arg1 = newarg1 or arg1 -- end if ((type == "PARTY_LEADER") and (_G.HasLFGRestrictions())) then type = "PARTY_GUIDE" event = "CHAT_MSG_PARTY_GUIDE" end s.CHATTYPE = type s.EVENT = event s.MESSAGE = safestr(arg1) local chatget = _G["CHAT_"..type.."_GET"] if chatget then local chatlink = chatget:match("|H(channel:[^|]-)|h[^|]-|h") if chatlink then s.CHANLINK = chatlink s.nN = "|H" s.NN = "|h" s.Nn = "|h" chatget = chatget:gsub("|Hchannel:[^|]-|h([^|]-)|h", "%1") end s.TYPEPREFIX, s.TYPEPOSTFIX = string.match(_G.TEXT(chatget), "(.*)%%s(.*)") end s.TYPEPOSTFIX = safestr(s.TYPEPOSTFIX) s.TYPEPREFIX = safestr(s.TYPEPREFIX) local arg2 = safestr(arg2) if strlen(arg2) > 0 then if ( strsub(type, 1, 7) == "MONSTER" or type == "RAID_BOSS_EMOTE" or type == "CHANNEL_NOTICE" or type == "CHANNEL_NOTICE_USER") then -- no link else local plr, svr = strsplit("-", arg2) s.pP = "[" s.lL = "|Hplayer:" s.PLAYERLINK = arg2 s.LL = "|h" s.PLAYER = plr if svr and strlen(svr) > 0 then s.sS = "-" s.SERVER = svr end if arg11 then s.PLAYERLINKDATA = ":"..safestr(arg11) end s.Ll = "|h" s.Pp = "]" end end -- If we are handling notices, format them like bliz if (type == "CHANNEL_NOTICE_USER") then local chatnotice = _G["CHAT_"..arg1.."_NOTICE"]:gsub("|Hchannel:[^|]-|h[^|]-|h", ""):trim() if strlen(arg5) > 0 then -- TWO users in this notice (E.G. x kicked y) s.MESSAGE = chatnotice:format(arg2, arg5) elseif ( arg1 == "INVITE" ) then s.MESSAGE = chatnotice:format(arg4, arg2) else s.MESSAGE = chatnotice:format(arg2) end elseif type == "CHANNEL_NOTICE" then if ( arg10 > 0 ) then arg4 = arg4.." "..arg10; end if arg1 == "YOU_JOINED" or arg1 == "YOU_LEFT" or arg1 == "YOU_CHANGED" or arg1 == "SUSPENDED" then s.MESSAGE = _G["CHAT_"..arg1.."_NOTICE"]:format(arg8, arg4):trim() else s.MESSAGE = _G["CHAT_"..arg1.."_NOTICE"]:gsub("|Hchannel:[^|]-|h[^|]-|h", ""):trim() end end local arg6 = safestr(arg6) if strlen(arg6) > 0 then s.fF = "" -- 2.4 Change if arg6 == "GM" then s.FLAG = "|TInterface\\ChatFrame\\UI-ChatIcon-Blizz.blp:0:2:0:-3|t " elseif ( arg6 == "DEV" ) then --Add Blizzard Icon, this was sent by a Dev s.FLAG = "|TInterface\\ChatFrame\\UI-ChatIcon-Blizz.blp:0:2:0:-3|t "; else s.FLAG = _G["CHAT_FLAG_"..arg6] end s.Ff = "" end local arg3 = safestr(arg3) if ( (strlen(arg3) > 0) and (arg3 ~= "Universal") and (arg3 ~= frame.defaultLanguage) ) then s.gG = "[" s.LANGUAGE = arg3 s.Gg = "] " else s.LANGUAGE_NOSHOW = arg3 end local arg9 = safestr(arg9) if strlen(arg9) > 0 then -- local bracket, post_bracket = string.match(s.TYPEPREFIX, "%[(.*)%](.*)") -- bracket = safestr(bracket) -- if strlen(bracket) > 0 then -- s.cC = "[" -- s.Cc = "]" -- s.CHANNEL = bracket -- s.TYPEPREFIX = safestr(post_bracket) -- end if strlen(safestr(arg8)) > 0 and arg8 > 0 then s.CHANNELNUM = tostring(arg8) s.CC = ". " s.nN = "|H" s.NN = "|h" s.Nn = "|h" s.CHANLINK = "channel:"..tostring(arg8) end if arg7 > 0 then s.cC = "[" s.Cc = "] " s.CHANNEL, s.zZ, s.ZONE = string.match(arg9, "(.*)(%s%-%s)(.*)") if s.CHANNEL:len() == 0 then s.CHANNEL = arg9 end s.CHANNEL = safestr(s.CHANNEL) s.zZ = safestr(s.zZ) s.ZONE = safestr(s.ZONE) s.Zz = "" else if strlen(arg9) > 0 then s.CHANNEL = arg9 s.cC = "[" s.Cc = "] " end end end -- local _, fontHeight = _G.GetChatWindowInfo(frame:GetID()); -- -- if ( fontHeight == 0 ) then -- --fontHeight will be 0 if it's still at the default (14) -- fontHeight = 14; -- end local arg7 = tonumber(arg7) -- 2.4 -- Search for icon links and replace them with texture links. if arg7 and ( arg7 < 1 or ( arg7 >= 1 and _G.CHAT_SHOW_ICONS ~= "0" ) ) then local term; for tag in string.gmatch(arg1, "%b{}") do term = strlower(string.gsub(tag, "[{}]", "")); if ( _G.ICON_TAG_LIST[term] and _G.ICON_LIST[_G.ICON_TAG_LIST[term]] ) then s.MESSAGE = string.gsub(s.MESSAGE , tag, _G.ICON_LIST[_G.ICON_TAG_LIST[term]] .. "0|t"); -- -- This would allow for ignoring unknown icon tags -- -- else -- s.MESSAGE = string.gsub(s.MESSAGE, tag, ""); end end end if type == "SYSTEM" or strsub(type,1,11) == "ACHIEVEMENT" or strsub(type,1,18) == "GUILD_ACHIEVEMENT" then if strsub(type,1,11) == "ACHIEVEMENT" or strsub(type,1,18) == "GUILD_ACHIEVEMENT" then s.MESSAGE = s.MESSAGE:format("") end local pl, p, rest = string.match(s.MESSAGE, "|Hplayer:(.-)|h%[(.-)%]|h(.+)") if pl and p then local plr, svr = strsplit("-", pl) s.pP = "[" s.lL = "|Hplayer:" s.PLAYERLINK = pl s.LL = "|h" s.PLAYER = plr s.Ll = "|h" s.Pp = "]" s.MESSAGE = rest if svr and strlen(svr) > 0 then s.sS = "-" s.SERVER = svr end if arg11 then s.PLAYERLINKDATA = ":"..safestr(arg11) end end end s.ORG = SplitMessageOrg return SplitMessage, info end end local NULL_INFO = {r = 1.0, g = 1.0, b = 1.0, id = 0 }