You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
9.2 KiB
298 lines
9.2 KiB
--imports
|
|
local WIM = WIM;
|
|
local _G = _G;
|
|
local table = table;
|
|
local unpack = unpack;
|
|
local string = string;
|
|
local pairs = pairs;
|
|
local ipairs = ipairs;
|
|
local select = select;
|
|
|
|
--set namespace
|
|
setfenv(1, WIM);
|
|
|
|
local Emote = WIM.CreateModule("Emoticons", true);
|
|
|
|
-----------------------------------------------------
|
|
-- Emoticon Functions --
|
|
-----------------------------------------------------
|
|
|
|
local LinkRepository = {}; -- used for emotes and link parsing.
|
|
local tmpList = {};
|
|
|
|
-- Dri: keeping the special table as a helper for authors poking into WIM code to more easily add chars for parsing,
|
|
-- we could just as well construct a static specialstr for the replacement function manually and save us some string garbage.
|
|
local special = {"%", ":", "-", "^", "$", ")", "(", "]", "]", "~", "@", "#", "&", "*", "_", "+", "=", ",", ".", "?", "/", "\\", "{", "}", "|", "`", ";", "\"", "'"};
|
|
local specialrepl = "["
|
|
for _,token in ipairs(special) do
|
|
specialrepl = specialrepl.."%"..token
|
|
end
|
|
specialrepl = specialrepl.."]"
|
|
|
|
local function convertEmoteToPattern(theEmote)
|
|
theEmote = string.gsub(theEmote,specialrepl,"%%%0");
|
|
return theEmote;
|
|
--[[ local i; -- Dri: ticket 379 this loop hits the in combat script execution time limit since 5.1, looped gsub is costly, do it all-in-one instead
|
|
for i=1, #special do
|
|
theEmote = string.gsub(theEmote, "%"..special[i], "%%"..special[i]);
|
|
end
|
|
return theEmote;]]
|
|
end
|
|
|
|
local function getEmoteFilePath(theEmote)
|
|
local emoteTable = GetSelectedSkin().emoticons;
|
|
|
|
local tmp = emoteTable.definitions[theEmote];
|
|
-- if emote not found or if mal formed/linked emote, prevent infinate loop.
|
|
if(not tmp or tmp == theEmote) then
|
|
return "";
|
|
else
|
|
if(emoteTable.definitions[tmp]) then
|
|
return getEmoteFilePath(tmp);
|
|
else
|
|
return tmp;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function encodeColors(theMsg)
|
|
theMsg = string.gsub(theMsg, "|c", "\001\002");
|
|
theMsg = string.gsub(theMsg, "|r", "\001\003");
|
|
return theMsg;
|
|
end
|
|
|
|
local function decodeColors(theMsg)
|
|
theMsg = string.gsub(theMsg, "\001\002", "|c");
|
|
theMsg = string.gsub(theMsg, "\001\003", "|r");
|
|
return theMsg;
|
|
end
|
|
|
|
local function filterEmoticons(theMsg, smf)
|
|
-- sanitize string of any % characters
|
|
theMsg = string.gsub(theMsg, "%%", "%%%%");
|
|
|
|
--safety check...
|
|
if(not theMsg or theMsg == "") then
|
|
return "";
|
|
end
|
|
|
|
--check if special formatting is not wanted
|
|
if(smf and (smf.noEscapedStrings or smf.noEmoticons)) then
|
|
return theMsg;
|
|
end
|
|
|
|
--remove player hyperlink from message to circumvent misbehavior as of 8.1
|
|
local s,e = string.find(theMsg, ": ")
|
|
local playerLink
|
|
|
|
if e then
|
|
playerLink = string.sub(theMsg, 1, e)
|
|
theMsg = string.sub(theMsg, e+1)
|
|
elseif string.find(theMsg, "^|K") then
|
|
return theMsg
|
|
end
|
|
|
|
--safety check again...
|
|
if(not theMsg or theMsg == "") then
|
|
return playerLink or "";
|
|
end
|
|
|
|
--accomodate WoW's built in symbols and inherrit WoW's options whether to display them or not.
|
|
if ( 1 ) then
|
|
for tag in string.gmatch(theMsg, "%b{}") do
|
|
local term = string.lower(string.gsub(tag, "[{}]", ""));
|
|
if ( _G.ICON_TAG_LIST[term] and _G.ICON_LIST[_G.ICON_TAG_LIST[term]] ) then
|
|
theMsg = string.gsub(theMsg, tag, _G.ICON_LIST[_G.ICON_TAG_LIST[term]] .. "0|t");
|
|
end
|
|
end
|
|
end
|
|
|
|
local emoteTable = GetSelectedSkin().emoticons;
|
|
|
|
-- first as to not disrupt any links, lets remove them and put them back later.
|
|
-- local orig = theMsg;--This doesn't appear to be used at all, what was intent here?
|
|
-- clean out colors and wait to put back.
|
|
local results;
|
|
theMsg = encodeColors(theMsg);
|
|
repeat
|
|
theMsg, results = string.gsub(theMsg, "(|T[^|]+|t)", function(theLink)
|
|
table.insert(LinkRepository, theLink);
|
|
return "\001\004"..#LinkRepository;
|
|
end, 1);
|
|
until results == 0;
|
|
repeat
|
|
theMsg, results = string.gsub(theMsg, "(|K[^|]+|k[^|]+|k)", function(theLink)
|
|
table.insert(LinkRepository, theLink);
|
|
return "\001\004"..#LinkRepository;
|
|
end, 1);
|
|
until results == 0;
|
|
-- repeat
|
|
-- theMsg, results = string.gsub(theMsg, "(|A[^|]+|a)", function(theLink)
|
|
-- table.insert(LinkRepository, theLink);
|
|
-- return "\001\004"..#LinkRepository;
|
|
-- end, 1);
|
|
-- until results == 0;
|
|
repeat
|
|
theMsg, results = string.gsub(theMsg, "(|H[^|]+|h.-|h)", function(theLink)
|
|
table.insert(LinkRepository, theLink);
|
|
return "\001\004"..#LinkRepository;
|
|
end, 1);
|
|
until results == 0;
|
|
--restore color
|
|
|
|
-- lets exchange emotes...
|
|
local img;
|
|
for emote,_ in pairs(emoteTable.definitions) do
|
|
img = getEmoteFilePath(emote);
|
|
if(img and img ~= "") then
|
|
theMsg = string.gsub(theMsg, convertEmoteToPattern(emote), "|T"..img..":"..emoteTable.width..":"..emoteTable.height..":"..emoteTable.offset[1]..":"..emoteTable.offset[2].."|t");
|
|
end
|
|
end
|
|
|
|
-- put all the links back into the string...
|
|
for i=#LinkRepository, 1, -1 do
|
|
theMsg = string.gsub(theMsg, "\001\004"..i.."", LinkRepository[i]);
|
|
end
|
|
|
|
-- clear table to be recycled by next process
|
|
for key, _ in pairs(LinkRepository) do
|
|
LinkRepository[key] = nil;
|
|
end
|
|
|
|
-- desanitize string of any % characters
|
|
theMsg = string.gsub(theMsg, "%%%%", "%%");
|
|
|
|
return decodeColors((playerLink or "")..theMsg);
|
|
end
|
|
|
|
|
|
|
|
|
|
function Emote:OnEnable()
|
|
RegisterStringModifier(filterEmoticons, true);
|
|
end
|
|
|
|
function Emote:OnDisable()
|
|
UnregisterStringModifier(filterEmoticons);
|
|
end
|
|
|
|
|
|
local function clearTempTable()
|
|
for key, _ in pairs(tmpList) do
|
|
tmpList[key] = nil;
|
|
end
|
|
end
|
|
|
|
|
|
local function loadTable(tbl, ...)
|
|
clearTempTable();
|
|
for i=1, select("#", ...) do
|
|
local item = select(i, ...);
|
|
table.insert(tbl, item);
|
|
end
|
|
end
|
|
|
|
|
|
-- Extended Global
|
|
function GetEmotes()
|
|
clearTempTable();
|
|
local emotes = GetSelectedSkin().emoticons.definitions;
|
|
for k, v in pairs(emotes) do
|
|
if(emotes[v] == nil) then
|
|
table.insert(tmpList, k);
|
|
end
|
|
end
|
|
return unpack(tmpList);
|
|
end
|
|
|
|
function GetEmoteAlias(emote)
|
|
clearTempTable();
|
|
local emotes = GetSelectedSkin().emoticons.definitions;
|
|
for k, v in pairs(emotes) do
|
|
if(string.lower(v) == string.lower(emote)) then
|
|
table.insert(tmpList, k);
|
|
end
|
|
end
|
|
return unpack(tmpList);
|
|
end
|
|
|
|
function GetEmoteTexture(emote)
|
|
return getEmoteFilePath(emote);
|
|
end
|
|
|
|
|
|
|
|
-- define context menu
|
|
local emotesPerMenu = 14;
|
|
|
|
local info = {};
|
|
info.text = "MENU_MSGBOX";
|
|
local msgBoxMenu = AddContextMenu(info.text, info);
|
|
info = {};
|
|
info.text = WIM.L["Emoticons"];
|
|
info.notCheckable = true;
|
|
local emoticonsMenu = msgBoxMenu:AddSubItem(AddContextMenu("EMOTICON_LIST", info), 2);
|
|
|
|
local function emoteMenuClicked(self)
|
|
libs.DropDownMenu.CloseDropDownMenus();
|
|
if(MSG_CONTEXT_MENU_EDITBOX) then
|
|
MSG_CONTEXT_MENU_EDITBOX:Insert(self.value);
|
|
end
|
|
end
|
|
|
|
local emoteTmpList = {};
|
|
local function generateEmoticonList(self, button)
|
|
if(button ~= "RightButton") then
|
|
return;
|
|
end
|
|
local emoticonsMenu = GetContextMenu("EMOTICON_LIST");
|
|
local tbl = emoticonsMenu.menuTable;
|
|
--clear initial table
|
|
if(tbl) then
|
|
for k, _ in pairs(tbl) do
|
|
tbl[k] = nil;
|
|
end
|
|
end
|
|
|
|
loadTable(emoteTmpList, GetEmotes());
|
|
local EMOTICON_MORE = 1;
|
|
local info;
|
|
for i=1, #emoteTmpList do
|
|
if(i % emotesPerMenu == 0) then
|
|
local more = GetContextMenu("EMOTICON_MORE"..EMOTICON_MORE) or {};
|
|
more.text = "|cff69ccf0"..WIM.L["More"].."|r";
|
|
more.notCheckable = true;
|
|
if(more.menuTable) then
|
|
for k, _ in pairs(more.menuTable) do
|
|
more.menuTable[k] = nil;
|
|
end
|
|
end
|
|
emoticonsMenu:AddSubItem(GetContextMenu("MENU_SPACE"), 1);
|
|
emoticonsMenu:AddSubItem(AddContextMenu("EMOTICON_MORE"..EMOTICON_MORE, more), 1);
|
|
emoticonsMenu = GetContextMenu("EMOTICON_MORE"..EMOTICON_MORE);
|
|
EMOTICON_MORE = EMOTICON_MORE + 1;
|
|
end
|
|
|
|
info = GetContextMenu("EMOTICON_"..emoteTmpList[i]) or {};
|
|
info.text = "|T"..getEmoteFilePath(emoteTmpList[i])..":16:16:0:0|t "..emoteTmpList[i];
|
|
info.tooltipTitle = info.text
|
|
loadTable(tmpList, GetEmoteAlias(emoteTmpList[i]))
|
|
info.tooltipText = table.concat(tmpList, "\n");
|
|
if(info.tooltipText and info.tooltipText ~= "") then
|
|
info.tooltipText = "|cff69ccf0"..L["Also"]..":|r\n"..info.tooltipText
|
|
end
|
|
info.notCheckable = true;
|
|
info.value = emoteTmpList[i];
|
|
info.func = emoteMenuClicked;
|
|
emoticonsMenu:AddSubItem(AddContextMenu("EMOTICON_"..emoteTmpList[i], info));
|
|
end
|
|
for key, _ in pairs(emoteTmpList) do
|
|
emoteTmpList[key] = nil;
|
|
end
|
|
clearTempTable();
|
|
end
|
|
|
|
RegisterWidgetTrigger("msg_box", "whisper,chat,w2w", "OnMouseDown", generateEmoticonList);
|
|
|
|
|
|
|