Quantcast

Syncing with github

elfmagi [03-14-19 - 19:43]
Syncing with github
Filename
README.md
SuperGuildInviteReborn.toc
core/SGI_AddOn_Message.lua
core/SGI_Blacklist.lua
core/SGI_Constants.lua
core/SGI_Core.lua
core/SGI_Events.lua
core/SGI_Filter.lua
core/SGI_GUI.lua
core/SGI_System_Message.lua
core/SGI_Utils.lua
core/SuperScan.lua
libs/Alerts/Alerts.lua
libs/ChatIntercept/ChatIntercept.lua
libs/LibWho-2.0/Changelog-LibWho-2.0-2.0.146.txt
libs/LibWho-2.0/LibWho-2.0.toc
libs/LibWho-2.0/LibWho-2.0/LibWho-2.0.lua
libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
libs/LibWho-2.0/libs/LibStub/LibStub.lua
libs/LibWho-2.0/libs/LibStub/LibStub.toc
libs/LibWho-2.0/libs/LibStub/tests/test.lua
libs/LibWho-2.0/libs/LibStub/tests/test2.lua
libs/LibWho-2.0/libs/LibStub/tests/test3.lua
libs/LibWho-2.0/libs/LibStub/tests/test4.lua
libs/LibWho-2.0XX/LibWho-2.0.lua
libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
libs/LibWho-2.0XX/libs/LibStub/LibStub.lua
libs/LibWho-2.0XX/libs/LibStub/LibStub.toc
libs/LibWho-2.0XX/libs/LibStub/tests/test.lua
libs/LibWho-2.0XX/libs/LibStub/tests/test2.lua
libs/LibWho-2.0XX/libs/LibStub/tests/test3.lua
libs/LibWho-2.0XX/libs/LibStub/tests/test4.lua
locale/localization.lua
diff --git a/README.md b/README.md
index 344a833..3ae67db 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
 # SuperGuildInviteReborn
 Repository for addon hosted at:
-https://wow.curseforge.com/projects/superguildinvite-reborn
-https://www.wowinterface.com/downloads/info24080-SuperGuildInvite2.html#info
+[CurseForge](https://wow.curseforge.com/projects/superguildinvite-reborn)
+and also at [WoWInterface](https://www.wowinterface.com/downloads/info24080-SuperGuildInvite2.html#info)
+If you would like to show your appreciation, you can donate [Here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NE78S2XQG9D6Q)
diff --git a/SuperGuildInviteReborn.toc b/SuperGuildInviteReborn.toc
index e1dd175..2bc5e65 100644
--- a/SuperGuildInviteReborn.toc
+++ b/SuperGuildInviteReborn.toc
@@ -1,21 +1,12 @@
-## Interface: 70300
+## Interface: 80000
 ## Author: Janniie - Stormreaver EU
 ## Updated by: Snowenn - Zul'jin US
 ## Title: Super Guild Invite Reborn
-## Notes: Version 7.7.0
-## Version: 7.7.0
+## Notes: Version 8.0.0
+## Version: 8.0.0
 ## SavedVariables: SGI_DATA
 ## SavedVariablesPerCharacter: SGI_BACKUP
-
-libs\GuildShield\GuildShield.lua
-libs\ChatIntercept\ChatIntercept.lua
-libs\Alerts\Alerts.lua
-
-libs\LibWho-2.0\libs\LibStub\LibStub.lua
-libs\LibWho-2.0\libs\CallbackHandler-1.0\CallbackHandler-1.0.lua
-libs\LibWho-2.0\LibWho-2.0\LibWho-2.0.lua
-
-locale\localization.lua
+embeds.xml

 core\SGI_Constants.lua
 core\SGI_Core.lua
@@ -27,4 +18,4 @@ core\SuperScan.lua
 core\SGI_System_Message.lua
 core\SGI_Events.lua

-core\SGI_GUI.lua
+core\SGI_GUI.xml
diff --git a/core/SGI_AddOn_Message.lua b/core/SGI_AddOn_Message.lua
index 2b89e69..2c1773a 100644
--- a/core/SGI_AddOn_Message.lua
+++ b/core/SGI_AddOn_Message.lua
@@ -1,81 +1,81 @@
-local ID_REQUEST = "SGI_REQ";
-ID_MASSLOCK = "SGI_MASS";
-local ID_LOCK = "SGI_LOCK";
-local ID_SHIELD = "I_HAVE_SHIELD";
-local ID_VERSION = "SGI_VERSION";
-local ID_LIVE_SYNC = "SGI_LIVE_SYNC";
-local ID_PING = "SGI_PING";
-local ID_PONG = "SGI_PONG";
-local ID_STOP = "SGI_STOP";
-RegisterAddonMessagePrefix(ID_REQUEST);
-RegisterAddonMessagePrefix(ID_LOCK);
-RegisterAddonMessagePrefix(ID_SHIELD);
-RegisterAddonMessagePrefix(ID_MASSLOCK);
-RegisterAddonMessagePrefix(ID_VERSION);
-RegisterAddonMessagePrefix(ID_LIVE_SYNC);
-RegisterAddonMessagePrefix(ID_PING);
-RegisterAddonMessagePrefix(ID_STOP);
-
-
-function SGI:AddonMessage(event,...)
-	local ID, msg, channel, sender = ...;
-	if (not SGI_DATA[SGI_DATA_INDEX].debug and sender == UnitName("player")) then return end
-
-
-	if (ID == ID_SHIELD) then
-		SGI:LockPlayer(sender);
-		SGI:RemoveShielded(sender);
-		SGI:debug("SHIELD: "..ID.." "..msg.." "..sender);
-	elseif (ID == ID_LOCK) then
-		SGI:LockPlayer(sender);
-		SGI:debug("LOCKING: "..ID.." "..msg.." "..sender);
-	elseif (ID == ID_REQUEST) then
-		SGI:ShareLocks(sender);
-		SGI:debug("SHARING: "..ID.." "..msg.." "..sender);
-	elseif (ID == ID_MASSLOCK) then
-		SGI:ReceivedNewLocks(msg);
-		SGI:debug("RECEIVING: "..ID.." "..msg.." "..sender);
-	elseif (ID == ID_VERSION) then
-		SGI:debug("VERSION: "..ID.." "..msg.." "..sender);
-		local receivedVersion = msg;
-
-		if (new == SGI:CompareVersions(SGI.VERSION_MAJOR, receivedVersion)) then
-			SGI:print("|cffffff00A new version (|r|cff00A2FF"..new.."|r|cffffff00) of |r|cff16ABB5SuperGuildInvite|r|cffffff00 is available at curse.com!");
-			if Alerter and not SGI.VERSION_ALERT_COOLDOWN then
-				Alerter:SendAlert("|cffffff00A new version (|r|cff00A2FF"..new.."|r|cffffff00) of |r|cff16ABB5SuperGuildInvite|r|cffffff00 is available at curse.com!",1.5)
-				SGI.VERSION_ALERT_COOLDOWN = true;
-			end
-		end
-
-	elseif (ID == ID_LIVE_SYNC) then
-		SGI:debug("LIVESYNC: "..ID.." "..msg.." "..sender);
-		SGI:RemoveQueued(msg);
-	elseif (ID == ID_STOP) then
-
-	elseif (ID == ID_PING) then
-		SGI:PingedByJanniie(sender);
-	end
-end
-
-function SGI:LiveSync(player)
-	SendAddonMessage(ID_LIVE_SYNC, player, "GUILD");
-end
-
-function SGI:BroadcastVersion(target)
-	if (target == "GUILD") then
-		SendAddonMessage(ID_VERSION, SGI.VERSION_MAJOR, "GUILD");
-	else
-		SendAddonMessage(ID_VERSION, SGI.VERSION_MAJOR, "WHISPER", target);
-	end
-end
-
-function SGI:PingedByJanniie(sender)
-	SendAddonMessage("SGI_PONG", SGI.VERSION_MAJOR, "WHISPER", sender);
-end
-
-function SGI:RequestSync()
-	SendAddonMessage(ID_REQUEST, "", "GUILD");
-end
-
-
-SGI:debug(">> AddOn_Message.lua");
+local ID_REQUEST = "SGI_REQ";
+ID_MASSLOCK = "SGI_MASS";
+local ID_LOCK = "SGI_LOCK";
+local ID_SHIELD = "I_HAVE_SHIELD";
+local ID_VERSION = "SGI_VERSION";
+local ID_LIVE_SYNC = "SGI_LIVE_SYNC";
+local ID_PING = "SGI_PING";
+local ID_PONG = "SGI_PONG";
+local ID_STOP = "SGI_STOP";
+C_ChatInfo.RegisterAddonMessagePrefix(ID_REQUEST);
+C_ChatInfo.RegisterAddonMessagePrefix(ID_LOCK);
+C_ChatInfo.RegisterAddonMessagePrefix(ID_SHIELD);
+C_ChatInfo.RegisterAddonMessagePrefix(ID_MASSLOCK);
+C_ChatInfo.RegisterAddonMessagePrefix(ID_VERSION);
+C_ChatInfo.RegisterAddonMessagePrefix(ID_LIVE_SYNC);
+C_ChatInfo.RegisterAddonMessagePrefix(ID_PING);
+C_ChatInfo.RegisterAddonMessagePrefix(ID_STOP);
+
+
+function SGI:AddonMessage(event,...)
+	local ID, msg, channel, sender = ...;
+	if (not SGI_DATA[SGI_DATA_INDEX].debug and sender == UnitName("player")) then return end
+
+
+	if (ID == ID_SHIELD) then
+		SGI:LockPlayer(sender);
+		SGI:RemoveShielded(sender);
+		SGI:debug("SHIELD: "..ID.." "..msg.." "..sender);
+	elseif (ID == ID_LOCK) then
+		SGI:LockPlayer(sender);
+		SGI:debug("LOCKING: "..ID.." "..msg.." "..sender);
+	elseif (ID == ID_REQUEST) then
+		SGI:ShareLocks(sender);
+		SGI:debug("SHARING: "..ID.." "..msg.." "..sender);
+	elseif (ID == ID_MASSLOCK) then
+		SGI:ReceivedNewLocks(msg);
+		SGI:debug("RECEIVING: "..ID.." "..msg.." "..sender);
+	elseif (ID == ID_VERSION) then
+		SGI:debug("VERSION: "..ID.." "..msg.." "..sender);
+		local receivedVersion = msg;
+
+		if (new == SGI:CompareVersions(SGI.VERSION_MAJOR, receivedVersion)) then
+			SGI:print("|cffffff00A new version (|r|cff00A2FF"..new.."|r|cffffff00) of |r|cff16ABB5SuperGuildInvite|r|cffffff00 is available at curse.com!");
+			if Alerter and not SGI.VERSION_ALERT_COOLDOWN then
+				Alerter:SendAlert("|cffffff00A new version (|r|cff00A2FF"..new.."|r|cffffff00) of |r|cff16ABB5SuperGuildInvite|r|cffffff00 is available at curse.com!",1.5)
+				SGI.VERSION_ALERT_COOLDOWN = true;
+			end
+		end
+
+	elseif (ID == ID_LIVE_SYNC) then
+		SGI:debug("LIVESYNC: "..ID.." "..msg.." "..sender);
+		SGI:RemoveQueued(msg);
+	elseif (ID == ID_STOP) then
+
+	elseif (ID == ID_PING) then
+		SGI:PingedByJanniie(sender);
+	end
+end
+
+function SGI:LiveSync(player)
+	C_ChatInfo.SendAddonMessageLogged(ID_LIVE_SYNC, player, "GUILD");
+end
+
+function SGI:BroadcastVersion(target)
+	if (target == "GUILD") then
+		C_ChatInfo.SendAddonMessageLogged(ID_VERSION, SGI.VERSION_MAJOR, "GUILD");
+	else
+		C_ChatInfo.SendAddonMessageLogged(ID_VERSION, SGI.VERSION_MAJOR, "WHISPER", target);
+	end
+end
+
+function SGI:PingedByJanniie(sender)
+	C_ChatInfo.SendAddonMessageLogged("SGI_PONG", SGI.VERSION_MAJOR, "WHISPER", sender);
+end
+
+function SGI:RequestSync()
+	C_ChatInfo.SendAddonMessageLogged(ID_REQUEST, "", "GUILD");
+end
+
+
+SGI:debug(">> AddOn_Message.lua");
diff --git a/core/SGI_Blacklist.lua b/core/SGI_Blacklist.lua
index 7d61e01..4c228f7 100644
--- a/core/SGI_Blacklist.lua
+++ b/core/SGI_Blacklist.lua
@@ -1,114 +1,114 @@
-local MessageQueue = {};
-SGI.ForceStop = {};
-
-CreateFrame("Frame", "SGI_MESSAGE_TIMER");
-SGI_MESSAGE_TIMER.update = 0;
-SGI_MESSAGE_TIMER:SetScript("OnUpdate", function()
-	if (SGI_MESSAGE_TIMER.update < GetTime()) then
-
-		for i = 1,5 do
-			local key, messageToBeSent = next(MessageQueue);
-
-			if (key and messageToBeSent) then
-				if (SGI.ForceStop[messageToBeSent.receiver]) then
-					MessageQueue[key] = nil;
-					SGI.ForceStop[messageToBeSent.receiver] = nil;
-					SGI:debug("Forced sendstop!");
-					return;
-				end
-				SendAddonMessage(ID_MASSLOCK, messageToBeSent.msg, "WHISPER", messageToBeSent.receiver);
-				MessageQueue[key] = nil;
-				SGI:debug("Send AddonMessage ("..messageToBeSent.msg..") to "..messageToBeSent.receiver);
-
-			end
-		end
-		SGI_MESSAGE_TIMER.update = GetTime() + 2;
-	end
-end)
-
-local function AddMessage(message, receiver)
-	local newMessage = {
-		msg = message,
-		receiver = receiver,
-	};
-	tinsert(MessageQueue, newMessage);
-end
-
-function SGI:StopMassShare(player)
-	SGI.ForceStop[player] = true;
-end
-
-function SGI:IsSharing(player)
-	for key, message in pairs(MessageQueue) do
-		if (message.receiver == player) then
-			return true;
-		end
-	end
-end
-
-local function RemoveLock(name)
-	SGI_DATA.lock[name] = nil;
-end
-
-function SGI:IsLocked(name)
-	return SGI_DATA.lock[name];
-end
-
-function SGI:LockPlayer(name)
-	if (not SGI:IsLocked(name)) then
-		SGI_DATA.lock[name] = tonumber(date("%m"));
-	end
-end
-
-function SGI:UnlockPlayer(name)
-	RemoveLock(name);
-end
-
-function SGI:ShareLocks(name)
-	local part = ID_MASSLOCK;
-
-	for k,_ in pairs(SGI_DATA.lock) do
-		if (strlen(part..":"..k) > 250) then
-			AddMessage(part, name);
-			part = ID_MASSLOCK;
-		end
-		part = part..":"..k;
-	end
-
-	AddMessage(part, name);
-end
-
-function SGI:ReceivedNewLocks(rawLocks)
-	local locks = SGI:divideString(rawLocks, ":");
-
-	for k,_ in pairs(locks) do
-		SGI:LockPlayer(locks[k]);
-	end
-	SGI:debug("Received locks!");
-end
-
-function SGI:RemoveOutdatedLocks()
-	local month = tonumber(date("%m"));
-
-	for k,_ in pairs(SGI_DATA.lock) do
-		if (month - 1) > SGI_DATA.lock[k] or (month < SGI_DATA.lock[k] and month > 1) then
-			RemoveLock(k);
-		end
-	end
-
-end
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-SGI:debug(">> Blacklist.lua");
\ No newline at end of file
+local MessageQueue = {};
+SGI.ForceStop = {};
+
+CreateFrame("Frame", "SGI_MESSAGE_TIMER");
+SGI_MESSAGE_TIMER.update = 0;
+SGI_MESSAGE_TIMER:SetScript("OnUpdate", function()
+	if (SGI_MESSAGE_TIMER.update < GetTime()) then
+
+		for i = 1,5 do
+			local key, messageToBeSent = next(MessageQueue);
+
+			if (key and messageToBeSent) then
+				if (SGI.ForceStop[messageToBeSent.receiver]) then
+					MessageQueue[key] = nil;
+					SGI.ForceStop[messageToBeSent.receiver] = nil;
+					SGI:debug("Forced sendstop!");
+					return;
+				end
+				 C_ChatInfo.SendAddonMessageLogged(ID_MASSLOCK, messageToBeSent.msg, "WHISPER", messageToBeSent.receiver);
+				MessageQueue[key] = nil;
+				SGI:debug("Send AddonMessage ("..messageToBeSent.msg..") to "..messageToBeSent.receiver);
+
+			end
+		end
+		SGI_MESSAGE_TIMER.update = GetTime() + 2;
+	end
+end)
+
+local function AddMessage(message, receiver)
+	local newMessage = {
+		msg = message,
+		receiver = receiver,
+	};
+	tinsert(MessageQueue, newMessage);
+end
+
+function SGI:StopMassShare(player)
+	SGI.ForceStop[player] = true;
+end
+
+function SGI:IsSharing(player)
+	for key, message in pairs(MessageQueue) do
+		if (message.receiver == player) then
+			return true;
+		end
+	end
+end
+
+local function RemoveLock(name)
+	SGI_DATA.lock[name] = nil;
+end
+
+function SGI:IsLocked(name)
+	return SGI_DATA.lock[name];
+end
+
+function SGI:LockPlayer(name)
+	if (not SGI:IsLocked(name)) then
+		SGI_DATA.lock[name] = tonumber(date("%m"));
+	end
+end
+
+function SGI:UnlockPlayer(name)
+	RemoveLock(name);
+end
+
+function SGI:ShareLocks(name)
+	local part = ID_MASSLOCK;
+
+	for k,_ in pairs(SGI_DATA.lock) do
+		if (strlen(part..":"..k) > 250) then
+			AddMessage(part, name);
+			part = ID_MASSLOCK;
+		end
+		part = part..":"..k;
+	end
+
+	AddMessage(part, name);
+end
+
+function SGI:ReceivedNewLocks(rawLocks)
+	local locks = SGI:divideString(rawLocks, ":");
+
+	for k,_ in pairs(locks) do
+		SGI:LockPlayer(locks[k]);
+	end
+	SGI:debug("Received locks!");
+end
+
+function SGI:RemoveOutdatedLocks()
+	local month = tonumber(date("%m"));
+
+	for k,_ in pairs(SGI_DATA.lock) do
+		if (month - 1) > SGI_DATA.lock[k] or (month < SGI_DATA.lock[k] and month > 1) then
+			RemoveLock(k);
+		end
+	end
+
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+SGI:debug(">> Blacklist.lua");
diff --git a/core/SGI_Constants.lua b/core/SGI_Constants.lua
index 5f1f74b..4e9c9d2 100644
--- a/core/SGI_Constants.lua
+++ b/core/SGI_Constants.lua
@@ -1,73 +1,73 @@
-SGI = {};
-
--- General
-SGI.LOGO = "|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r ";
-SLASH_SUPERGUILDINVITE1 = "/sgi";
-SLASH_SUPERGUILDINVITE2 = "/superguildinvite";
-SGI_DATA_INDEX = UnitName("player").." - "..GetRealmName() or "?";
-SGI.VERSION_ALERT_COOLDOWN = false;
-
-SGI_MAX_LEVEL_SUPER_SCAN = 110;
-SGI_BREAK_POINT_SUPER_SCAN = 90;
-SGI_MIN_LEVEL_SUPER_SCAN = 1;
-
--- Version realted
-SGI.VERSION_MAJOR = "7.7";
-SGI.VERSION_MINOR = ".0";
-SGI.versionChanges = {
-	version = "Version |cff55EE55"..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.."|r",
-	items = {
-		"Added Races and bug fixes..",
-	},
-}
-
-SGI.CommonIssues = {
-	"Please post bug reports on WoWInterface or curseforge and I'll fix them.",
-	"Test2",
-	"Test3",
-}
-
-local function defaultFunc(L,key)
-	return "857C7C"
-end
-
-
-
-SGI_CLASS_COLORS = {
-	["DEATHKNIGHT"] = "C41F3B",
-	["DEMONHUNTER"] = "A330C9",
-	["DRUID"] = "FF7D0A",
-	["HUNTER"] = "ABD473",
-	["MAGE"] = "69CCF0",
-	["MONK"] = "00FF96",
-	["PALADIN"] = "F58CBA",
-	["PRIEST"] = "FFFFFF",
-	["ROGUE"] = "FFF569",
-	["SHAMAN"] = "0070DE",
-	["WARLOCK"] = "9482C9",
-	["WARRIOR"] = "C79C6E",
-}
-
-SGI_CLASS_COLORS = setmetatable(SGI_CLASS_COLORS, {__index=defaultFunc})
-
-
-local debugMode = false;
-local old = print
-function SGI:print(...)
-	if (SGI_DATA_INDEX == "?" or type(SGI_DATA) ~= "table") then return end
-	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"]) then
-		old("|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r|cffffff00",...,"|r")
-	end
-end
-function SGI:debug(...)
-	if (debugMode) then
-		old("|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r|cffff3300",...,"|r")
-	end
-end
-
-function SGI:DebugState(state)
-	debugMode = state;
-end
-
-SGI:debug("Loading SGI files:");
-SGI:debug(">> Constants.lua");
+SGI = {};
+
+-- General
+SGI.LOGO = "|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r ";
+SLASH_SUPERGUILDINVITE1 = "/sgi";
+SLASH_SUPERGUILDINVITE2 = "/superguildinvite";
+SGI_DATA_INDEX = UnitName("player").." - "..GetRealmName() or "?";
+SGI.VERSION_ALERT_COOLDOWN = false;
+
+SGI_MAX_LEVEL_SUPER_SCAN = 120;
+SGI_BREAK_POINT_SUPER_SCAN = 90;
+SGI_MIN_LEVEL_SUPER_SCAN = 1;
+
+-- Version realted
+SGI.VERSION_MAJOR = "8.0";
+SGI.VERSION_MINOR = ".1";
+SGI.versionChanges = {
+	version = "Version |cff55EE55"..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.."|r",
+	items = {
+		"Added Races and bug fixes..",
+	},
+}
+
+SGI.CommonIssues = {
+	"Please post bug reports on WoWInterface or curseforge and I'll fix them.",
+	"Test2",
+	"Test3",
+}
+
+local function defaultFunc(L,key)
+	return "857C7C"
+end
+
+
+
+SGI_CLASS_COLORS = {
+	["DEATHKNIGHT"] = "C41F3B",
+	["DEMONHUNTER"] = "A330C9",
+	["DRUID"] = "FF7D0A",
+	["HUNTER"] = "ABD473",
+	["MAGE"] = "69CCF0",
+	["MONK"] = "00FF96",
+	["PALADIN"] = "F58CBA",
+	["PRIEST"] = "FFFFFF",
+	["ROGUE"] = "FFF569",
+	["SHAMAN"] = "0070DE",
+	["WARLOCK"] = "9482C9",
+	["WARRIOR"] = "C79C6E",
+}
+
+SGI_CLASS_COLORS = setmetatable(SGI_CLASS_COLORS, {__index=defaultFunc})
+
+
+local debugMode = false;
+local old = print
+function SGI:print(...)
+	if (SGI_DATA_INDEX == "?" or type(SGI_DATA) ~= "table") then return end
+	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"]) then
+		old("|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r|cffffff00",...,"|r")
+	end
+end
+function SGI:debug(...)
+	if (debugMode) then
+		old("|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r|cffff3300",...,"|r")
+	end
+end
+
+function SGI:DebugState(state)
+	debugMode = state;
+end
+
+SGI:debug("Loading SGI files:");
+SGI:debug(">> Constants.lua");
diff --git a/core/SGI_Core.lua b/core/SGI_Core.lua
index 14ce9eb..8b2940e 100644
--- a/core/SGI_Core.lua
+++ b/core/SGI_Core.lua
@@ -1,190 +1,190 @@
-local L;
-
-
-function SGI:LoadLocale()
-	local Locale = GetLocale()
-	if SGI_Locale[Locale] then
-		SGI.L = SGI_Locale[Locale]
-		L = SGI.L;
-		SGI:print(L["English Locale loaded"]..L["Author"])
-		return true
-	else
-		SGI.L = SGI_Locale["enGB"]
-		SGI:print("|cffffff00Locale missing! Loaded English.|r")
-		return false
-	end
-
-end
-
-function SGI:FormatTime2(T)
-	local R,S,M,H = ""
-	T = floor(T)
-	H = floor(T/3600)
-	M = floor((T-3600*H)/60)
-	S = T-(3600*H + 60*M)
-
-	if T <= 0 then
-		return L[" < 1 sec"]
-	end
-
-	if H ~= 0 then
-		R =  R..H..L["h "]
-	end
-	if M ~= 0 then
-		R = R..M..L["m "]
-	end
-	if S ~= 0 then
-		R = R..S..L["s"]
-	end
-
-	return R
-end
-
-function SGI:FormatTime(T)
-	local R,S,M,H = ""
-	T = floor(T);
-	H = floor(T/3600)
-	M = floor((T-3600*H)/60)
-	S = T-(3600*H + 60*M)
-
-	if (T <= 0) then
-		return SGI.L[" < 1 sec"];
-	end
-
-	if (H > 0) then
-		R = R..H..":";
-	end
-	if (M > 9) then
-		R = R..M..":";
-	elseif (M > 0) then
-		R = R.."0"..M..":";
-	elseif (M == 0) then
-		R = R.."00:";
-	end
-	if (S > 9) then
-		R = R..S;
-	elseif (S > 0) then
-		R = R.."0"..S;
-	elseif (S == 0) then
-		R = R.."00";
-	end
-
-	return R;
-end
-
-
-function SGI:CountTable(T)
-	local i = 0
-	if type(T) ~= "table" then
-		return i
-	end
-	for k,_ in pairs(T) do
-		i = i + 1
-	end
-	return i
-end
-
-function SGI:GetClassColor(classFileName)
-	return SGI_CLASS_COLORS[classFileName];
-end
-
-function SGI:CompareVersions(V1, V2)
-	local p11 = tonumber(strsub(V1,1,strfind(V1,".",1,true)-1));
-	local p12 = tonumber(strsub(V1,strfind(V1,".",1,true)+1));
-	local p21 = tonumber(strsub(V2,1,strfind(V2,".",1,true)-1));
-	local p22 = tonumber(strsub(V2,strfind(V2,".",1,true)+1));
-
-	if (p11 == p21) then
-		if (p22 > p12) then
-			return V2;
-		else
-			return V1;
-		end
-	elseif (p21 > p11) then
-		return V2;
-	else
-		return V1;
-	end
-end
-
-function SGI:ResetFix()
-	if (not SGI_DATA.resetFix) then
-		SGI_DATA = {};
-		SGI_DATA.resetFix = true;
-	end
-end
-
-function SGI:divideString(str,div)
-	local out = {}
-	local i = 0
-	while strfind(str,div) do
-		i = i + 1
-		out[i] = strsub(str,1,strfind(str,div)-1)
-		str = strsub(str,strfind(str,div)+1)
-	end
-	out[i+1] = str
-	return out
-end
-
-local function FrameReset()
-	SGI_DATA[SGI_DATA_INDEX].settings.frames = {}
-	ReloadUI();
-end
-
-local reloadWarning = true;
-local reloadWarning2 = true;
-function SlashCmdList.SUPERGUILDINVITE(msg)
-
-	msg = strlower(msg);
-
-	if msg == "reset" then
-		local lock = SGI_DATA.lock
-		SGI_DATA = nil
-		SGI_EVENTS["PLAYER_LOGIN"]()
-		SGI_DATA.lock = lock
-	elseif (msg == "framereset") then
-		if (reloadWarning) then
-			SGI:print("WARNING: Reseting your frames requires a reload of the User Interface! If you wish to proceed, type \"/sgi framereset\" again!");
-			reloadWarning = false;
-		else
-			FrameReset();
-		end
-	elseif (msg == "opt" or msg == "options" or msp == "config" or msg == "settings" or msg == "show") then
-		SGI:ShowOptions();
-	elseif (msg == "debug") then
-		SGI_DATA[SGI_DATA_INDEX].debug = not SGI_DATA[SGI_DATA_INDEX].debug;
-		if (SGI_DATA[SGI_DATA_INDEX].debug) then
-			SGI:print("Activated debugging!");
-		else
-			SGI:print("Deactivated debugging!");
-		end
-		SGI:DebugState(SGI_DATA[SGI_DATA_INDEX].debug);
-	elseif (msg == "changes") then
-		SGI:ShowChanges();
-	elseif (msg == "stats") then
-		local amountScanned, amountGuildless, amountQueued, sessionTotal = SGI:GetSuperScanStats();
-		SGI:print("Scanned players this scan: |r|cff0062FF"..amountScanned.."|r");
-		SGI:print("Guildless players this scan: |r|cff0062FF"..amountGuildless.."|r");
-		SGI:print("Queued players this scan: |r|cff0062FF"..amountQueued.."|r");
-		SGI:print("Total players scanned this session: |r|cff0062FF"..sessionTotal.."|r");
-	elseif (msg == "unbind" or msg == "removekeybind") then
-		SGI:print("Cleared SGI invite keybind");
-		SGI_DATA[SGI_DATA_INDEX].keyBind = nil;
-	elseif (strfind(msg, "lock")) then
-		local name = strsub(msg, 6);
-		if (name) then
-			SGI:LockPlayer(name);
-		end
-	else
-		local temp = SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"];
-		SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"] = false;
-		SGI:print("|cffffff00Commands: |r|cff00A2FF/sgi or /superguildinvite|r")
-		SGI:print("|cff00A2FFreset |r|cffffff00to reset all data except locks|r")
-		SGI:print("|cff00A2FFframereset|r|cffffff00 resets the positions of the frames |r")
-		SGI:print("|cff00A2FFunbind|r|cffffff00 removes the saved keybind|r");
-		SGI:print("|cff00A2FFoptions|r|cffffff00 shows the options. Same effect as clicking the minimap button|r")
-		SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"] = temp;
-	end
-end
-
-SGI:debug(">> Core.lua");
\ No newline at end of file
+local L;
+
+
+function SGI:LoadLocale()
+	local Locale = GetLocale()
+	if SGI_Locale[Locale] then
+		SGI.L = SGI_Locale[Locale]
+		L = SGI.L;
+--		SGI:print(L["English Locale loaded"]..L["Author"])
+		return true
+	else
+		SGI.L = SGI_Locale["enGB"]
+--		SGI:print("|cffffff00Locale missing! Loaded English.|r")
+		return false
+	end
+
+end
+
+function SGI:FormatTime2(T)
+	local R,S,M,H = ""
+	T = floor(T)
+	H = floor(T/3600)
+	M = floor((T-3600*H)/60)
+	S = T-(3600*H + 60*M)
+
+	if T <= 0 then
+		return L[" < 1 sec"]
+	end
+
+	if H ~= 0 then
+		R =  R..H..L["h "]
+	end
+	if M ~= 0 then
+		R = R..M..L["m "]
+	end
+	if S ~= 0 then
+		R = R..S..L["s"]
+	end
+
+	return R
+end
+
+function SGI:FormatTime(T)
+	local R,S,M,H = ""
+	T = floor(T);
+	H = floor(T/3600)
+	M = floor((T-3600*H)/60)
+	S = T-(3600*H + 60*M)
+
+	if (T <= 0) then
+		return SGI.L[" < 1 sec"];
+	end
+
+	if (H > 0) then
+		R = R..H..":";
+	end
+	if (M > 9) then
+		R = R..M..":";
+	elseif (M > 0) then
+		R = R.."0"..M..":";
+	elseif (M == 0) then
+		R = R.."00:";
+	end
+	if (S > 9) then
+		R = R..S;
+	elseif (S > 0) then
+		R = R.."0"..S;
+	elseif (S == 0) then
+		R = R.."00";
+	end
+
+	return R;
+end
+
+
+function SGI:CountTable(T)
+	local i = 0
+	if type(T) ~= "table" then
+		return i
+	end
+	for k,_ in pairs(T) do
+		i = i + 1
+	end
+	return i
+end
+
+function SGI:GetClassColor(classFileName)
+	return SGI_CLASS_COLORS[classFileName];
+end
+
+function SGI:CompareVersions(V1, V2)
+	local p11 = tonumber(strsub(V1,1,strfind(V1,".",1,true)-1));
+	local p12 = tonumber(strsub(V1,strfind(V1,".",1,true)+1));
+	local p21 = tonumber(strsub(V2,1,strfind(V2,".",1,true)-1));
+	local p22 = tonumber(strsub(V2,strfind(V2,".",1,true)+1));
+
+	if (p11 == p21) then
+		if (p22 > p12) then
+			return V2;
+		else
+			return V1;
+		end
+	elseif (p21 > p11) then
+		return V2;
+	else
+		return V1;
+	end
+end
+
+function SGI:ResetFix()
+	if (not SGI_DATA.resetFix) then
+		SGI_DATA = {};
+		SGI_DATA.resetFix = true;
+	end
+end
+
+function SGI:divideString(str,div)
+	local out = {}
+	local i = 0
+	while strfind(str,div) do
+		i = i + 1
+		out[i] = strsub(str,1,strfind(str,div)-1)
+		str = strsub(str,strfind(str,div)+1)
+	end
+	out[i+1] = str
+	return out
+end
+
+local function FrameReset()
+	SGI_DATA[SGI_DATA_INDEX].settings.frames = {}
+	ReloadUI();
+end
+
+local reloadWarning = true;
+local reloadWarning2 = true;
+function SlashCmdList.SUPERGUILDINVITE(msg)
+
+	msg = strlower(msg);
+
+	if msg == "reset" then
+		local lock = SGI_DATA.lock
+		SGI_DATA = nil
+		SGI_EVENTS["ADDON_LOADED"]()
+		SGI_DATA.lock = lock
+	elseif (msg == "framereset") then
+		if (reloadWarning) then
+			SGI:print("WARNING: Reseting your frames requires a reload of the User Interface! If you wish to proceed, type \"/sgi framereset\" again!");
+			reloadWarning = false;
+		else
+			FrameReset();
+		end
+	elseif (msg == "opt" or msg == "options" or msp == "config" or msg == "settings" or msg == "show") then
+		SGI:ShowOptions();
+	elseif (msg == "debug") then
+		SGI_DATA[SGI_DATA_INDEX].debug = not SGI_DATA[SGI_DATA_INDEX].debug;
+		if (SGI_DATA[SGI_DATA_INDEX].debug) then
+			SGI:print("Activated debugging!");
+		else
+			SGI:print("Deactivated debugging!");
+		end
+		SGI:DebugState(SGI_DATA[SGI_DATA_INDEX].debug);
+	elseif (msg == "changes") then
+		SGI:ShowChanges();
+	elseif (msg == "stats") then
+		local amountScanned, amountGuildless, amountQueued, sessionTotal = SGI:GetSuperScanStats();
+		SGI:print("Scanned players this scan: |r|cff0062FF"..amountScanned.."|r");
+		SGI:print("Guildless players this scan: |r|cff0062FF"..amountGuildless.."|r");
+		SGI:print("Queued players this scan: |r|cff0062FF"..amountQueued.."|r");
+		SGI:print("Total players scanned this session: |r|cff0062FF"..sessionTotal.."|r");
+	elseif (msg == "unbind" or msg == "removekeybind") then
+		SGI:print("Cleared SGI invite keybind");
+		SGI_DATA[SGI_DATA_INDEX].keyBind = nil;
+	elseif (strfind(msg, "lock")) then
+		local name = strsub(msg, 6);
+		if (name) then
+			SGI:LockPlayer(name);
+		end
+	else
+		local temp = SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"];
+		SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"] = false;
+		SGI:print("|cffffff00Commands: |r|cff00A2FF/sgi or /superguildinvite|r")
+		SGI:print("|cff00A2FFreset |r|cffffff00to reset all data except locks|r")
+		SGI:print("|cff00A2FFframereset|r|cffffff00 resets the positions of the frames |r")
+		SGI:print("|cff00A2FFunbind|r|cffffff00 removes the saved keybind|r");
+		SGI:print("|cff00A2FFoptions|r|cffffff00 shows the options. Same effect as clicking the minimap button|r")
+		SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"] = temp;
+	end
+end
+
+SGI:debug(">> Core.lua");
diff --git a/core/SGI_Events.lua b/core/SGI_Events.lua
index 2926ea0..e8b438e 100644
--- a/core/SGI_Events.lua
+++ b/core/SGI_Events.lua
@@ -1,141 +1,165 @@
-CreateFrame("Frame","SGI_EVENT_HANDLER");
-SGI_EVENTS = {};
-
-function SGI_EVENTS:PLAYER_LOGIN()
-
-
-
-	-- Index used to separate settings for different characters.
-	SGI_DATA_INDEX = UnitName("player").." - "..GetRealmName();
-
-	-- Make sure the saved variables are correct.
-	--General settings:
-	if (type(SGI_DATA) ~= "table") then
-		SGI_DATA = {};
-	end
-
-	-- Fix transition from 6.x to 7.x
-	SGI:ResetFix()
-
-	if (type(SGI_DATA.lock) ~= "table") then
-		SGI_DATA.lock = {};
-	end
-	if (type(SGI_DATA.guildList) ~= "table") then
-		SGI_DATA.guildList = {}
-	end
-	if (type(SGI_DATA.guildList[GetRealmName()]) ~= "table") then
-		SGI_DATA.guildList[GetRealmName()] = {};
-	end
-
-	--Character based settings.
-	if type(SGI_DATA[SGI_DATA_INDEX]) ~= "table" then
-		SGI_DATA[SGI_DATA_INDEX] = {}
-	end
-	if type(SGI_DATA[SGI_DATA_INDEX].settings) ~= "table" then
-		SGI_DATA[SGI_DATA_INDEX].settings = {
-			inviteMode = 1,
-			lowLimit = SGI_MIN_LEVEL_SUPER_SCAN,
-			highLimit = SGI_MAX_LEVEL_SUPER_SCAN,
-			raceStart = SGI_MAX_LEVEL_SUPER_SCAN,
-			classStart = SGI_MAX_LEVEL_SUPER_SCAN,
-			interval = 5,
-			checkBox = {},
-			dropDown = {},
-			frames = {},
-			filters = {},
-		}
-	end
-	if type(SGI_DATA[SGI_DATA_INDEX].settings.whispers) ~= "table" then
-		SGI_DATA[SGI_DATA_INDEX].settings.whispers = {}
-	end
-	if type(SGI_BACKUP) ~= "table" then
-		SGI_BACKUP = SGI_DATA.lock
-	end
-
-	-- If there is a saved keybind, activate it.
-	if (SGI_DATA[SGI_DATA_INDEX].keyBind) then
-		SetBindingClick(SGI_DATA[SGI_DATA_INDEX].keyBind,"SGI_INVITE_BUTTON");
-	end
-
-	-- Anti spam. Users of the AddOn GuildShield are ignored.
-	GuildShield:Initiate(SGI.RemoveShielded);
-	-- Load locale
-	SGI:LoadLocale();
-	-- Load the minimap button
-	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_MINIMAP"]) then
-		SGI:ShowMinimapButton();
-	end
-	-- Activate the keybind, if any.
-	if (SGI_DATA[SGI_DATA_INDEX].keyBind) then
-		SetBindingClick(SGI_DATA[SGI_DATA_INDEX].keyBind, "SGI_INVITE_BUTTON2");
-	end
-	--Debugging, used for development
-	SGI:DebugState(SGI_DATA[SGI_DATA_INDEX].debug);
-	--Tell guildies what version you're running
-	SGI:BroadcastVersion("GUILD");
-	--Request lock sync from guildies
-	SGI:RequestSync();
-	--Remove locks that are > 2 months old
-	SGI:RemoveOutdatedLocks();
-	--Chat Intercept
-	ChatIntercept:StateSystem(SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_SYSTEM"]);
-	ChatIntercept:StateWhisper(SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_WHISPER"]);
-	ChatIntercept:StateRealm(true);
-	--Show changes, if needed
-	--SGI:debug((SGI_DATA[SGI_DATA_INDEX].settings.checkBox["SGI_CHANGES"] and "true" or "nil").." "..(SGI_DATA.showChanges and "true" or "nil"));
-	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["SGI_CHANGES"] and SGI_DATA.showChanges ~= SGI.VERSION_MAJOR) then
-		SGI:ShowChanges();
-		SGI_DATA.showChanges = SGI.VERSION_MAJOR;
-		SGI:debug("Show changes");
-	end
-	--Need to load the SuperScan frame for certain functions
-	SGI:CreateSmallSuperScanFrame();
-	SuperScanFrame:Hide();
-end
-
-function SGI_EVENTS:UPDATE_MOUSEOVER_UNIT()
-	-- Create a list of players and their guild (if any).
-	-- Used to prevent false positives.
-	if (UnitIsPlayer("mouseover")) then
-		local name = UnitName("mouseover");
-		local guild = GetGuildInfo("mouseover");
-		local realm = GetRealmName();
-
-		if (not guild or guild == "") then return end
-
-		if (type(SGI_DATA.guildList[realm][guild]) ~= "table") then
-			SGI_DATA.guildList[realm][guild] = {};
-		end
-		for k,v in pairs(SGI_DATA.guildList[realm][guild]) do
-			if (v == name) then
-				return;
-			end
-		end
-		tinsert(SGI_DATA.guildList[realm][guild], name);
-		--SGI_DATA.guildList[realm][name] = guild;
-	end
-end
-
-function SGI_EVENTS:PLAYER_LOGOUT()
-	SendAddonMessage("SGI_STOP", "", "GUILD");
-end
-
-function SGI_EVENTS:CHAT_MSG_ADDON(event, ...)
-	SGI:AddonMessage(event, ...);
-end
-
-function SGI_EVENTS:CHAT_MSG_SYSTEM(event, ...)
-	SGI:SystemMessage(event,message,...)
-end
-
-
-for event,_ in pairs(SGI_EVENTS) do
-	SGI_EVENT_HANDLER:RegisterEvent(event);
-end
-
-
-SGI_EVENT_HANDLER:SetScript("OnEvent", function(self,event,...)
-	SGI_EVENTS[event](self, event, ...);
-end)
-
-SGI:debug(">> Events.lua");
\ No newline at end of file
+CreateFrame("Frame","SGI_EVENT_HANDLER");
+SGI_EVENTS = {};
+
+function SGI_EVENTS:ADDON_LOADED()
+
+
+	-- Index used to separate settings for different characters.
+	SGI_DATA_INDEX = UnitName("player").." - "..GetRealmName();
+
+
+
+	-- Make sure the saved variables are correct.
+	--General settings:
+	if (type(SGI_DATA) ~= "table") then
+		SGI_DATA = {};
+	end
+
+	-- Fix transition from 6.x to 7.x
+	SGI:ResetFix()
+
+	if (type(SGI_DATA.lock) ~= "table") then
+		SGI_DATA.lock = {};
+	end
+	if (type(SGI_DATA.guildList) ~= "table") then
+		SGI_DATA.guildList = {}
+	end
+	if (type(SGI_DATA.guildList[GetRealmName()]) ~= "table") then
+		SGI_DATA.guildList[GetRealmName()] = {};
+	end
+
+	--Character based settings.
+	if type(SGI_DATA[SGI_DATA_INDEX]) ~= "table" then
+		SGI_DATA[SGI_DATA_INDEX] = {}
+	end
+	if type(SGI_DATA[SGI_DATA_INDEX].settings) ~= "table" then
+		SGI_DATA[SGI_DATA_INDEX].settings = {
+			inviteMode = 2,
+			lowLimit = SGI_MIN_LEVEL_SUPER_SCAN,
+			highLimit = SGI_MAX_LEVEL_SUPER_SCAN,
+			raceStart = SGI_MAX_LEVEL_SUPER_SCAN,
+			classStart = SGI_MAX_LEVEL_SUPER_SCAN,
+			interval = 5,
+			checkBox = {},
+			dropDown = {},
+			frames = {},
+			filters = {},
+		}
+	end
+	if type(SGI_DATA[SGI_DATA_INDEX].settings.whispers) ~= "table" then
+		SGI_DATA[SGI_DATA_INDEX].settings.whispers = {}
+	end
+	if type(SGI_BACKUP) ~= "table" then
+		SGI_BACKUP = SGI_DATA.lock
+	end
+
+	-- If there is a saved keybind, activate it.
+--	if (SGI_DATA[SGI_DATA_INDEX].keyBind) then
+--		SetBindingClick(SGI_DATA[SGI_DATA_INDEX].keyBind,"SGI_INVITE_BUTTON");
+--	end
+
+	-- Anti spam. Users of the AddOn GuildShield are ignored.
+--	GuildShield:Initiate(SGI.RemoveShielded);
+	-- Load locale
+	SGI:LoadLocale();
+	-- Load the minimap button
+	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_MINIMAP"]) then
+		SGI:ShowMinimapButton();
+	end
+--	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ADV_SCAN"]) then
+--		SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ADV_SCAN"] = FALSE;
+--	end
+
+
+
+
+
+	-- Removed Keybind button, too dangerous code.
+	-- Activate the keybind, if any.
+--	if (SGI_DATA[SGI_DATA_INDEX].keyBind) then
+--		SetBindingClick(SGI_DATA[SGI_DATA_INDEX].keyBind, "SGI_INVITE_BUTTON2");
+--	end
+
+
+
+	--Debugging, used for development
+--	SGI:DebugState(SGI_DATA[SGI_DATA_INDEX].debug);
+	--Tell guildies what version you're running
+	-- SGI:BroadcastVersion("GUILD"); legacy
+	--Request lock sync from guildies
+	--SGI:RequestSync();
+	--Remove locks that are > 2 months old
+	--SGI:RemoveOutdatedLocks();
+
+
+	--SGI_DATA[SGI_DATA_INDEX].settings.checkBox["Mute SGI"]=true
+	--SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_SYSTEM"]=true
+	--print(SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_SYSTEM"]);
+
+	--Chat Intercept
+			--ChatIntercept:StateSystem(SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_SYSTEM"]);
+	ChatIntercept:StateSystem(false);
+
+
+	ChatIntercept:StateWhisper(SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_WHISPER"]);
+	--ChatIntercept:StateRealm(true);
+
+	--Show changes, if needed
+	--SGI:debug((SGI_DATA[SGI_DATA_INDEX].settings.checkBox["SGI_CHANGES"] and "true" or "nil").." "..(SGI_DATA.showChanges and "true" or "nil"));
+	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["SGI_CHANGES"] and SGI_DATA.showChanges ~= SGI.VERSION_MAJOR) then
+--		SGI:ShowChanges();
+--		SGI_DATA.showChanges = SGI.VERSION_MAJOR;
+--		SGI:debug("Show changes");
+	end
+	--Need to load the SuperScan frame for certain functions
+	SGI:CreateSmallSuperScanFrame();
+	SuperScanFrame:Hide();
+
+end
+
+function SGI_EVENTS:UPDATE_MOUSEOVER_UNIT()
+	-- Create a list of players and their guild (if any).
+	-- Used to prevent false positives.
+	if (UnitIsPlayer("mouseover")) then
+		local name = UnitName("mouseover");
+		local guild = GetGuildInfo("mouseover");
+		local realm = GetRealmName();
+
+		if (not guild or guild == "") then return end
+
+		if (type(SGI_DATA.guildList[realm][guild]) ~= "table") then
+			SGI_DATA.guildList[realm][guild] = {};
+		end
+		for k,v in pairs(SGI_DATA.guildList[realm][guild]) do
+			if (v == name) then
+				return;
+			end
+		end
+		tinsert(SGI_DATA.guildList[realm][guild], name);
+		--SGI_DATA.guildList[realm][name] = guild;
+	end
+end
+
+function SGI_EVENTS:PLAYER_LOGOUT()
+	 C_ChatInfo.SendAddonMessageLogged("SGI_STOP", "", "GUILD");
+end
+
+function SGI_EVENTS:CHAT_MSG_ADDON(event, ...)
+	SGI:AddonMessage(event, ...);
+end
+
+function SGI_EVENTS:CHAT_MSG_SYSTEM(event, ...)
+	SGI:SystemMessage(event,message,...)
+end
+
+
+for event,_ in pairs(SGI_EVENTS) do
+	SGI_EVENT_HANDLER:RegisterEvent(event);
+end
+
+
+SGI_EVENT_HANDLER:SetScript("OnEvent", function(self,event,...)
+	SGI_EVENTS[event](self, event, ...);
+end)
+
+SGI:debug(">> Events.lua");
diff --git a/core/SGI_Filter.lua b/core/SGI_Filter.lua
index f9c6ad0..8b64d63 100644
--- a/core/SGI_Filter.lua
+++ b/core/SGI_Filter.lua
@@ -1,211 +1,211 @@
---[[
-	Filter structure:
-	 = {
-		nameFilter = "A",
-		exclusiveFilter = true,
-		maxLvl = 10,
-		minLvL = 1,
-		race = {
-			["Tauren"] = true,
-		},
-		class = {
-			["DEATHKNIGHT"] = true,
-		},
-	}
-
-
-
-
-]]
-
-local function AddFilter(filter)
-	tinsert(SGI_DATA[SGI_DATA_INDEX].settings.filters, filter);
-end
-
-function SGI:CreateFilter(nameOfFilter,class, name, minLvl, maxLvl, race, maxVowels, maxConsonants, active)
-
-	if (not nameOfFilter) then
-		return;
-	end
-
-	local filter = {
-		nameOfFilter = nameOfFilter,
-		race = race,
-		class = class,
-		name = name,
-		minLvl = minLvl,
-		maxLvl = maxLvl,
-		maxVowels = maxVowels,
-		maxConsonants = maxConsonants,
-		active = active,
-	}
-
-	AddFilter(filter);
-end
-
-function SGI:RemoveFilter(filterName)
-
-end
-
-local function GetMaxNumberConsequtiveVowels(word)
-
-	local vowels = {
-		["a"] = 1,
-		["o"] = 1,
-		["u"] = 1,
-		["y"] = 1,
-		["i"] = 1,
-		["e"] = 1,
-	}
-	local c = 0;
-	local max = 0;
-	for i = 1, strlen(word) do
-		if (vowels[strsub(word, i, i)]) then
-			c = c + 1;
-		else
-			c = 0;
-		end
-		if (c > max) then
-			max = c;
-		end
-	end
-
-	return max;
-
-end
-
-local function GetMaxNumberConsequtiveConsonants(word)
-	local vowels = {
-		["a"] = 1,
-		["o"] = 1,
-		["u"] = 1,
-		["y"] = 1,
-		["i"] = 1,
-		["e"] = 1,
-	}
-	local c = 0;
-	local max = 0;
-	for i = 1, strlen(word) do
-		if (vowels[strsub(word, i, i)]) then
-			c = 0;
-		else
-			c = c + 1;
-		end
-		if (c > max) then
-			max = c;
-		end
-	end
-
-	return max;
-end
-
-function SGI:TestCharacters(word)
-	local V = GetMaxNumberConsequtiveVowels(word);
-	local C = GetMaxNumberConsequtiveConsonants(word);
-
-	SGI:print("Vowels: "..V.." Consonants: "..C);
-end
-
-local function debugPlayer(player)
-	local text = "|cff"..SGI:GetClassColor(player.class)..player.name.."|r ("..player.level..") ("..player.race..")";
-	return text
-end
-
-local function match(filter, player)
-
-	--Is this filter for the players class/race?
-	if (type(filter.race) == "table" and SGI:CountTable(filter.race) ~= 0) then
-		if (not filter.race[player.race]) then
-			return false;
-		end
-	end
-
-	if (type(filter.class) == "table" and SGI:CountTable(filter.class) ~= 0) then
-		if (not filter.class[player.class]) then
-			return false;
-		end
-	end
-
-	-- Is the player within the level range?
-	if (type(filter.minLvl) == "number") then
-		if (filter.minLvl > player.level) then
-			return false;
-		end
-	end
-
-	if (type(filter.maxLvl) == "number") then
-		if (filter.maxLvl < player.level) then
-			return false;
-		end
-	end
-
-	if (type(filter.name) == "string" and filter.name ~= "") then
-		if not (strfind(player.name,filter.name)) then
-			return false;
-		end
-	end
-
-	if (type(filter.maxVowels) == "number") then
-		if (filter.maxVowels >= GetMaxNumberConsequtiveVowels(player.name)) then
-			return false;
-		end
-	end
-
-	if (type(filter.maxConsonants) == "number") then
-		if (filter.maxConsonants >= GetMaxNumberConsequtiveConsonants(player.name)) then
-			return false;
-		end
-	end
-
-	SGI:debug("Filter: "..filter.nameOfFilter.." "..debugPlayer(player));
-	return true;
-
-end
-
-local function GetActiveFilters()
-	local filters, activeFilters = SGI_DATA[SGI_DATA_INDEX].settings.filters, {};
-	if (type(filters) ~= "table") then
-		return {};
-	end
-	for k,_ in pairs(filters) do
-		if (filters[k]["active"]) then
-			activeFilters[k] = filters[k];
-		end
-	end
-	return activeFilters;
-end
-
-function SGI:FilterPlayer(player)
-	local filters = GetActiveFilters();--SGI_DATA[SGI_DATA_INDEX].settings.filters;
-
-	if (type(filters) ~= "table" or type(player) ~= "table") then
-		--if invalid parameter, return as filtered
-		SGI:debug("Error: Filter or player is not a table!");
-		return false;
-	end
-
-	for k,_ in pairs(filters) do
-		if (match(filters[k], player)) then
-			return false;
-		end
-	end
-
-	return true;
-
-end
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-SGI:debug(">> Filter.lua");
\ No newline at end of file
+--[[
+	Filter structure:
+	 = {
+		nameFilter = "A",
+		exclusiveFilter = true,
+		maxLvl = 10,
+		minLvL = 1,
+		race = {
+			["Tauren"] = true,
+		},
+		class = {
+			["DEATHKNIGHT"] = true,
+		},
+	}
+
+
+
+
+]]
+
+local function AddFilter(filter)
+	tinsert(SGI_DATA[SGI_DATA_INDEX].settings.filters, filter);
+end
+
+function SGI:CreateFilter(nameOfFilter,class, name, minLvl, maxLvl, race, maxVowels, maxConsonants, active)
+
+	if (not nameOfFilter) then
+		return;
+	end
+
+	local filter = {
+		nameOfFilter = nameOfFilter,
+		race = race,
+		class = class,
+		name = name,
+		minLvl = minLvl,
+		maxLvl = maxLvl,
+		maxVowels = maxVowels,
+		maxConsonants = maxConsonants,
+		active = active,
+	}
+
+	AddFilter(filter);
+end
+
+function SGI:RemoveFilter(filterName)
+
+end
+
+local function GetMaxNumberConsequtiveVowels(word)
+
+	local vowels = {
+		["a"] = 1,
+		["o"] = 1,
+		["u"] = 1,
+		["y"] = 1,
+		["i"] = 1,
+		["e"] = 1,
+	}
+	local c = 0;
+	local max = 0;
+	for i = 1, strlen(word) do
+		if (vowels[strsub(word, i, i)]) then
+			c = c + 1;
+		else
+			c = 0;
+		end
+		if (c > max) then
+			max = c;
+		end
+	end
+
+	return max;
+
+end
+
+local function GetMaxNumberConsequtiveConsonants(word)
+	local vowels = {
+		["a"] = 1,
+		["o"] = 1,
+		["u"] = 1,
+		["y"] = 1,
+		["i"] = 1,
+		["e"] = 1,
+	}
+	local c = 0;
+	local max = 0;
+	for i = 1, strlen(word) do
+		if (vowels[strsub(word, i, i)]) then
+			c = 0;
+		else
+			c = c + 1;
+		end
+		if (c > max) then
+			max = c;
+		end
+	end
+
+	return max;
+end
+
+function SGI:TestCharacters(word)
+	local V = GetMaxNumberConsequtiveVowels(word);
+	local C = GetMaxNumberConsequtiveConsonants(word);
+
+	SGI:print("Vowels: "..V.." Consonants: "..C);
+end
+
+local function debugPlayer(player)
+	local text = "|cff"..SGI:GetClassColor(player.class)..player.name.."|r ("..player.level..") ("..player.race..")";
+	return text
+end
+
+local function match(filter, player)
+
+	--Is this filter for the players class/race?
+	if (type(filter.race) == "table" and SGI:CountTable(filter.race) ~= 0) then
+		if (not filter.race[player.race]) then
+			return false;
+		end
+	end
+
+	if (type(filter.class) == "table" and SGI:CountTable(filter.class) ~= 0) then
+		if (not filter.class[player.class]) then
+			return false;
+		end
+	end
+
+	-- Is the player within the level range?
+	if (type(filter.minLvl) == "number") then
+		if (filter.minLvl > player.level) then
+			return false;
+		end
+	end
+
+	if (type(filter.maxLvl) == "number") then
+		if (filter.maxLvl < player.level) then
+			return false;
+		end
+	end
+
+	if (type(filter.name) == "string" and filter.name ~= "") then
+		if not (strfind(player.name,filter.name)) then
+			return false;
+		end
+	end
+
+	if (type(filter.maxVowels) == "number") then
+		if (filter.maxVowels >= GetMaxNumberConsequtiveVowels(player.name)) then
+			return false;
+		end
+	end
+
+	if (type(filter.maxConsonants) == "number") then
+		if (filter.maxConsonants >= GetMaxNumberConsequtiveConsonants(player.name)) then
+			return false;
+		end
+	end
+
+	SGI:debug("Filter: "..filter.nameOfFilter.." "..debugPlayer(player));
+	return true;
+
+end
+
+local function GetActiveFilters()
+	local filters, activeFilters = SGI_DATA[SGI_DATA_INDEX].settings.filters, {};
+	if (type(filters) ~= "table") then
+		return {};
+	end
+	for k,_ in pairs(filters) do
+		if (filters[k]["active"]) then
+			activeFilters[k] = filters[k];
+		end
+	end
+	return activeFilters;
+end
+
+function SGI:FilterPlayer(player)
+	local filters = GetActiveFilters();--SGI_DATA[SGI_DATA_INDEX].settings.filters;
+
+	if (type(filters) ~= "table" or type(player) ~= "table") then
+		--if invalid parameter, return as filtered
+		SGI:debug("Error: Filter or player is not a table!");
+		return false;
+	end
+
+	for k,_ in pairs(filters) do
+		if (match(filters[k], player)) then
+			return false;
+		end
+	end
+
+	return true;
+
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+SGI:debug(">> Filter.lua");
diff --git a/core/SGI_GUI.lua b/core/SGI_GUI.lua
index 2d82056..7b533b4 100644
--- a/core/SGI_GUI.lua
+++ b/core/SGI_GUI.lua
@@ -1,1785 +1,1816 @@
-
-local function onClickTester(self)
-	if self then
-		SGI:print("Click on "..self:GetName());
-	end
-end
-
-local function CreateButton(name, parent, width, height, label, anchor, onClick)
-	local f = CreateFrame("Button", name, parent, "UIPanelButtonTemplate");
-	f:SetWidth(width);
-	f:SetHeight(height);
-	f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall");
-	f.label:SetText(label);
-	f.label:SetPoint("CENTER");
-	f:SetWidth(width - 10);
-
-	if (type(anchor) == "table") then
-		f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs);
-	end
-
-	f:SetScript("OnClick", onClick);
-	return f;
-end
-
-local function CreateCheckbox(name, parent, label, anchor)
-	local f = CreateFrame("CheckButton", name, parent, "OptionsBaseCheckButtonTemplate");
-	f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	f.label:SetText(label);
-	f.label:SetPoint("LEFT", f, "RIGHT", 5, 1);
-
-	if (type(anchor) == "table") then
-		f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs);
-	end
-
-	f:HookScript("OnClick", function(self)
-		SGI_DATA[SGI_DATA_INDEX].settings.checkBox[name] = self:GetChecked()
-	end)
-	if SGI_DATA[SGI_DATA_INDEX].settings.checkBox[name] then
-		f:SetChecked()
-	end
-	return f;
-end
-
-local function CreateDropDown(name, parent, label, items, anchor)
-	local f = CreateFrame("Button", name, parent, "UIDropDownMenuTemplate");
-	f:ClearAllPoints();
-	f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs)
-	f:Show()
-
-	f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	f.label:SetPoint("BOTTOMLEFT", f, "TOPLEFT", 20, 5);
-	f.label:SetText(label);
-
-	local function OnClick(self)
-		UIDropDownMenu_SetSelectedID(f, self:GetID());
-		SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] = self:GetID();
-	end
-
-	local function initialize(self, level)
-		local info = UIDropDownMenu_CreateInfo();
-		for k,v in pairs(items) do
-			info = UIDropDownMenu_CreateInfo();
-			info.text = v;
-			info.value = v;
-			info.func = OnClick;
-			UIDropDownMenu_AddButton(info, level);
-		end
-	end
-
-	UIDropDownMenu_Initialize(f, initialize)
-	UIDropDownMenu_SetWidth(f, 100);
-	UIDropDownMenu_SetButtonWidth(f, 124)
-	SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] = SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] or 1
-	UIDropDownMenu_SetSelectedID(f, SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] or 1)
-	UIDropDownMenu_JustifyText(f, "LEFT")
-	return f
-end
-
-local function SetFramePosition(frame)
-	if (type(SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()]) ~= "table") then
-		if (frame:GetName() == "SGI_MiniMapButton") then
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = "CENTER", relativePoint = "CENTER", xOfs = -71, yOfs = -31};
-		else
-			frame:SetPoint("CENTER");
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = "CENTER", relativePoint = "CENTER", xOfs = 0, yOfs = 0};
-			return;
-		end
-	end
-	if (frame:GetName() == "SGI_MiniMapButton") then
-		frame:SetPoint(
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].point,
-			Minimap,
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].relativePoint,
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].xOfs,
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].yOfs
-		);
-	else
-		frame:SetPoint(
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].point,
-			UIParent,
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].relativePoint,
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].xOfs,
-			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].yOfs
-		);
-	end
-end
-
-local function SaveFramePosition(frame)
-	if (type(SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()]) ~= "table") then
-		SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {};
-	end
-	local point, parent, relativePoint, xOfs, yOfs = frame:GetPoint();
-	SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = point, relativePoint = relativePoint, xOfs = xOfs, yOfs = yOfs};
-end
-
-
-local function CreateInviteListFrame()
-	CreateFrame("Frame","SGI_Invites")
-	local SGI_QUEUE = SGI:GetInviteQueue();
-	SGI_Invites:SetWidth(370)
-	SGI_Invites:SetHeight(20*SGI:CountTable(SGI_QUEUE) + 40)
-	SGI_Invites:SetMovable(true)
-	SetFramePosition(SGI_Invites)
-	SGI_Invites:SetScript("OnMouseDown",function(self)
-		self:StartMoving()
-	end)
-	SGI_Invites:SetScript("OnMouseUp",function(self)
-		self:StopMovingOrSizing()
-		SaveFramePosition(SGI_Invites)
-	end)
-	local backdrop =
-	{
-		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background",
-		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
-		tile = true,
-		tileSize = 16,
-		edgeSize = 16,
-		insets = { left = 4, right = 4, top = 4, bottom = 4 }
-	}
-	SGI_Invites:SetBackdrop(backdrop)
-
-	SGI_Invites.text = SGI_Invites:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Invites.text:SetPoint("TOP",SGI_Invites,"TOP",-15,-15)
-	SGI_Invites.text:SetText(SGI.L["Click on the players you wish to invite"])
-	SGI_Invites.tooltip = CreateFrame("Frame","InviteTime",SGI_Invites,"GameTooltipTemplate")
-	SGI_Invites.tooltip.text = SGI_Invites.tooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Invites.tooltip:SetPoint("TOP",SGI_Invites,"BOTTOM",0,-2)
-	SGI_Invites.tooltip.text:SetText("Unknown")
-	SGI_Invites.tooltip.text:SetPoint("CENTER")
-
-	local close = CreateFrame("Button",nil,SGI_Invites,"UIPanelCloseButton")
-	close:SetPoint("TOPRIGHT",SGI_Invites,"TOPRIGHT",-4,-4)
-
-	SGI_Invites.items = {}
-	local update = 0
-	local toolUpdate = 0
-	SGI_Invites:SetScript("OnUpdate",function()
-		if (not SGI_Invites:IsShown() or GetTime() < update) then return end
-
-		SGI_QUEUE = SGI:GetInviteQueue();
-
-		for k,_ in pairs(SGI_Invites.items) do
-			SGI_Invites.items[k]:Hide()
-		end
-
-		local i = 0
-		local x,y = 10,-30
-		for i = 1,30 do
-			if not SGI_Invites.items[i] then
-				SGI_Invites.items[i] = CreateFrame("Button","InviteBar"..i,SGI_Invites)
-				SGI_Invites.items[i]:SetWidth(350)
-				SGI_Invites.items[i]:SetHeight(20)
-				SGI_Invites.items[i]:EnableMouse(true)
-				SGI_Invites.items[i]:SetPoint("TOP",SGI_Invites,"TOP",0,y)
-				SGI_Invites.items[i].text = SGI_Invites.items[i]:CreateFontString(nil,"OVERLAY","GameFontNormal")
-				SGI_Invites.items[i].text:SetPoint("LEFT",SGI_Invites.items[i],"LEFT",3,0)
-				SGI_Invites.items[i].text:SetJustifyH("LEFT")
-				SGI_Invites.items[i].text:SetWidth(SGI_Invites.items[i]:GetWidth()-10);
-				SGI_Invites.items[i].player = "unknown"
-				SGI_Invites.items[i]:RegisterForClicks("LeftButtonDown","RightButtonDown")
-				SGI_Invites.items[i]:SetScript("OnClick",SGI.SendGuildInvite)
-
-				SGI_Invites.items[i].highlight = SGI_Invites.items[i]:CreateTexture()
-				SGI_Invites.items[i].highlight:SetAllPoints()
-				SGI_Invites.items[i].highlight:SetTexture(1,1,0,0.2)
-				SGI_Invites.items[i].highlight:Hide()
-
-				SGI_Invites.items[i]:SetScript("OnEnter",function()
-					SGI_Invites.items[i].highlight:Show()
-					SGI_Invites.tooltip:Show()
-					SGI_Invites.items[i]:SetScript("OnUpdate",function()
-						if GetTime() > toolUpdate and SGI_QUEUE[SGI_Invites.items[i].player] then
-							SGI_Invites.tooltip.text:SetText("Found |cff"..SGI:GetClassColor(SGI_QUEUE[SGI_Invites.items[i].player].classFile)..SGI_Invites.items[i].player.."|r "..SGI:FormatTime(floor(GetTime()-SGI_QUEUE[SGI_Invites.items[i].player].found)).." ago")
-							local h,w = SGI_Invites.tooltip.text:GetHeight(),SGI_Invites.tooltip.text:GetWidth()
-							SGI_Invites.tooltip:SetWidth(w+20)
-							SGI_Invites.tooltip:SetHeight(h+20)
-							toolUpdate = GetTime() + 0.1
-						end
-					end)
-				end)
-				SGI_Invites.items[i]:SetScript("OnLeave",function()
-					SGI_Invites.items[i].highlight:Hide()
-					SGI_Invites.tooltip:Hide()
-					SGI_Invites.items[i]:SetScript("OnUpdate",nil)
-				end)
-			end
-			y = y - 20
-		end
-		i = 0
-		for k,_ in pairs(SGI_QUEUE) do
-			i = i + 1
-			local level,classFile,race,class,found = SGI_QUEUE[k].level, SGI_QUEUE[k].classFile, SGI_QUEUE[k].race, SGI_QUEUE[k].class, SGI_QUEUE[k].found
-			local Text = i..". |cff"..SGI:GetClassColor(classFile)..k.."|r Lvl "..level.." "..race.." |cff"..SGI:GetClassColor(classFile)..class.."|r"
-			SGI_Invites.items[i].text:SetText(Text)
-			SGI_Invites.items[i].player = k
-			SGI_Invites.items[i]:Show()
-			if i >= 30 then break end
-		end
-		SGI_Invites:SetHeight(i * 20 + 40)
-		update = GetTime() + 0.5
-	end)
-end
-
-
-function SGI:ShowInviteList()
-	if (not SGI_Invites) then
-		CreateInviteListFrame();
-	end
-	SGI_Invites:Show();
-end
-
-function SGI:HideInviteList()
-	if (SGI_Invites) then
-		SGI_Invites:Hide();
-	end
-end
-
-
-local function SSBtn3_OnClick(self)
-	if (SGI:IsScanning()) then
-		SGI:StopSuperScan();
-		self:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up");
-	else
-		SGI:StartSuperScan();
-		self:SetNormalTexture("Interface\\TimeManager\\PauseButton");
-	end
-end
-
-function SGI:CreateSmallSuperScanFrame()
-	CreateFrame("Frame", "SuperScanFrame");
-	SuperScanFrame:SetWidth(130);
-	SuperScanFrame:SetHeight(30);
-	local backdrop =
-	{
-		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background",
-		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
-		tile = true,
-		tileSize = 16,
-		edgeSize = 16,
-		insets = { left = 4, right = 4, top = 4, bottom = 4 }
-	}
-	SetFramePosition(SuperScanFrame)
-	SuperScanFrame:SetMovable(true)
-	SuperScanFrame:SetScript("OnMouseDown",function(self)
-		self:StartMoving()
-	end)
-	SuperScanFrame:SetScript("OnMouseUp",function(self)
-		self:StopMovingOrSizing()
-		SaveFramePosition(self)
-	end)
-	SuperScanFrame:SetBackdrop(backdrop)
-
-	local close = CreateFrame("Button",nil,SuperScanFrame,"UIPanelCloseButton")
-	close:SetPoint("LEFT",SuperScanFrame,"RIGHT",-5,0)
-
-	SuperScanFrame.time = SuperScanFrame:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SuperScanFrame.time:SetPoint("CENTER")
-	SuperScanFrame.time:SetText(format("|cff00ff00%d%%|r|cffffff00 %s|r",0,SGI:GetSuperScanETR()))
-
-	SuperScanFrame.progressTexture = SuperScanFrame:CreateTexture();
-	SuperScanFrame.progressTexture:SetPoint("LEFT", 5, 0);
-	SuperScanFrame.progressTexture:SetHeight(18);
-	SuperScanFrame.progressTexture:SetWidth(120);
-	SuperScanFrame.progressTexture:SetTexture(1,0.5,0,0.4);
-
-	local anchor = {
-		point = "TOPLEFT",
-		relativePoint = "BOTTOMLEFT",
-		xOfs = 0,
-		yOfs = 0,
-	}
-
-	SuperScanFrame.button1 = CreateButton("SGI_INVITE_BUTTON2", SuperScanFrame, 70, 30, format("Invite: %d",SGI:GetNumQueued()), anchor, SGI.SendGuildInvite)
-		anchor.xOfs = 85;
-	SuperScanFrame.button2 = CreateButton("SGI_PURGE_QUEUE", SuperScanFrame, 55, 30, "Purge", anchor, SGI.PurgeQueue);
-		anchor.xOfs = 57;
-	SuperScanFrame.button2 = CreateButton("SGI_SUPERSCAN_PLAYPAUSE", SuperScanFrame, 40,30,"",anchor,SSBtn3_OnClick);
-	SGI_SUPERSCAN_PLAYPAUSE:SetNormalTexture("Interface\\TimeManager\\PauseButton");
-
-	SuperScanFrame.nextUpdate = 0;
-	SuperScanFrame:SetScript("OnUpdate", function()
-		if (SuperScanFrame.nextUpdate < GetTime()) then
-
-			SuperScanFrame.button1.label:SetText(format("Invite: %d",SGI:GetNumQueued()));
-
-			if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then
-				local remainingTime = SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR);
-				local totalScanTime = SGI:GetTotalScanTime();
-				local percentageDone = (totalScanTime - remainingTime) / totalScanTime;
-				SuperScanFrame.time:SetText(format("|cff00ff00%d%%|r|cffffff00 %s|r",100*(percentageDone > 1 and 1 or percentageDone),SGI:FormatTime(remainingTime)))
-				SuperScanFrame.progressTexture:SetWidth(120 * (percentageDone > 1 and 1 or percentageDone));
-			end
-
-			SuperScanFrame.nextUpdate = GetTime() + 0.2;
-		end
-	end)
-
-
-	SuperScanFrame:Hide();
-	-- Interface\Buttons\UI-SpellbookIcon-NextPage-Up
-	-- Interface\TimeManager\PauseButton
-end
-
-function SGI:GetPercentageDone()
-	if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then
-		local remainingTime = SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR);
-		local totalScanTime = SGI:GetTotalScanTime();
-		local percentageDone = (totalScanTime - remainingTime) / totalScanTime;
-		return percentageDone * 100;
-	end
-	return 0;
-end
-
-function SGI:GetSuperScanTimeLeft()
-	if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then
-		return SGI:FormatTime(SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR));
-	end
-	return 0;
-end
-
-
-function SGI:ShowSuperScanFrame()
-	if (SuperScanFrame and not (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"])) then
-		SuperScanFrame:Show();
-	else
-		if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"]) then
-			SGI:CreateSmallSuperScanFrame();
-			SuperScanFrame:Hide();
-			return;
-		else
-			SGI:CreateSmallSuperScanFrame();
-			SuperScanFrame:Show();
-		end
-
-	end
-end
-
-function SGI:HideSuperScanFrame()
-	if (SuperScanFrame) then
-		SuperScanFrame:Hide();
-	end
-end
-
-local function CreateWhisperDefineFrame()
-
-end
-
-
-
-
-local KeyHarvestFrame = CreateFrame("Frame", "SGI_KeyHarvestFrame");
-KeyHarvestFrame:SetPoint("CENTER",0,200);
-KeyHarvestFrame:SetWidth(10);
-KeyHarvestFrame:SetHeight(10);
-KeyHarvestFrame.text = KeyHarvestFrame:CreateFontString(nil, "OVERLAY", "MovieSubtitleFont");
-KeyHarvestFrame.text:SetPoint("CENTER");
-KeyHarvestFrame.text:SetText("|cff00ff00Press the KEY you wish to bind now!|r");
-KeyHarvestFrame:Hide();
-
-function KeyHarvestFrame:GetNewKeybindKey()
-	KeyHarvestFrame:Show();
-	self:SetScript("OnKeyDown", function(self, key)
-		if (SetBindingClick(key, "SGI_INVITE_BUTTON2")) then
-			Alerter:SendAlert("|cff00ff00Successfully bound "..key.." to InviteButton!|r",1.5);
-			SGI:print("Successfully bound "..key.." to InviteButton!");
-			SGI_DATA[SGI_DATA_INDEX].keyBind = key;
-			BUTTON_KEYBIND.label:SetText("Set Keybind ("..key..")");
-		else
-			Alerter:SendAlert("|cffff0000Error binding "..key.." to InviteButton!|r",1.5);
-			SGI:print("Error binding "..key.." to InviteButton!");
-		end
-		self:EnableKeyboard(false);
-		KeyHarvestFrame:Hide();
-	end)
-	self:EnableKeyboard(true);
-
-end
-
-local function CreateWhisperDefineFrame()
-	CreateFrame("Frame","SGI_Whisper")
-	local backdrop =
-	{
-		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background",
-		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
-		tile = true,
-		tileSize = 16,
-		edgeSize = 16,
-		insets = { left = 4, right = 4, top = 4, bottom = 4 }
-	}
-	SGI_Whisper:SetWidth(500)
-	SGI_Whisper:SetHeight(365)
-	SGI_Whisper:SetBackdrop(backdrop)
-	SetFramePosition(SGI_Whisper)
-	SGI_Whisper:SetMovable(true)
-	SGI_Whisper:SetScript("OnMouseDown",function(self)
-		self:StartMoving()
-	end)
-	SGI_Whisper:SetScript("OnMouseUp",function(self)
-		self:StopMovingOrSizing()
-		SaveFramePosition(SGI_Whisper)
-	end)
-
-	local close = CreateFrame("Button",nil,SGI_Whisper,"UIPanelCloseButton")
-	close:SetPoint("TOPRIGHT",SGI_Whisper,"TOPRIGHT",-4,-4)
-
-	SGI_Whisper.title = SGI_Whisper:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_Whisper.title:SetText(SGI.L["SuperGuildInvite Custom Whisper"])
-	SGI_Whisper.title:SetPoint("TOP",SGI_Whisper,"TOP",0,-20)
-
-	SGI_Whisper.info = SGI_Whisper:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Whisper.info:SetPoint("TOPLEFT",SGI_Whisper,"TOPLEFT",33,-55)
-	SGI_Whisper.info:SetText(SGI.L["WhisperInstructions"])
-	SGI_Whisper.info:SetWidth(450)
-	SGI_Whisper.info:SetJustifyH("LEFT")
-
-	SGI_Whisper.edit = CreateFrame("EditBox",nil,SGI_Whisper)
-	SGI_Whisper.edit:SetWidth(450)
-	SGI_Whisper.edit:SetHeight(65)
-	SGI_Whisper.edit:SetMultiLine(true)
-	SGI_Whisper.edit:SetPoint("TOPLEFT",SGI_Whisper,"TOPLEFT",35,-110)
-	SGI_Whisper.edit:SetFontObject("GameFontNormal")
-	SGI_Whisper.edit:SetTextInsets(10,10,10,10)
-	SGI_Whisper.edit:SetMaxLetters(256)
-	SGI_Whisper.edit:SetBackdrop(backdrop)
-	SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "")
-	SGI_Whisper.edit:SetScript("OnHide",function()
-		SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "")
-	end)
-	SGI_Whisper.edit.text = SGI_Whisper.edit:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Whisper.edit.text:SetPoint("TOPLEFT",SGI_Whisper.edit,"TOPLEFT",10,13)
-	SGI_Whisper.edit.text:SetText(SGI.L["Enter your whisper"])
-
-	local yOfs = -20
-	SGI_Whisper.status = {}
-	for i = 1,6 do
-		SGI_Whisper.status[i] = {}
-		SGI_Whisper.status[i].box = CreateFrame("Frame",nil,SGI_Whisper)
-		SGI_Whisper.status[i].box:SetWidth(170)
-		SGI_Whisper.status[i].box:SetHeight(18)
-		SGI_Whisper.status[i].box:SetFrameStrata("HIGH")
-		SGI_Whisper.status[i].box.index = i
-		SGI_Whisper.status[i].box:SetPoint("LEFT",SGI_Whisper,"CENTER",50,yOfs)
-		SGI_Whisper.status[i].box:SetScript("OnEnter",function(self)
-			if SGI_DATA[SGI_DATA_INDEX].settings.whispers[self.index] then
-				GameTooltip:SetOwner(self,"ANCHOR_CURSOR")
-				GameTooltip:SetText(SGI:FormatWhisper(SGI_DATA[SGI_DATA_INDEX].settings.whispers[self.index],UnitName("Player")))
-			end
-		end)
-		SGI_Whisper.status[i].box:SetScript("OnLeave",function(self)
-			GameTooltip:Hide()
-		end)
-		SGI_Whisper.status[i].text = SGI_Whisper:CreateFontString(nil,nil,"GameFontNormal")
-		SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: ")
-		SGI_Whisper.status[i].text:SetWidth(200)
-		SGI_Whisper.status[i].text:SetJustifyH("LEFT")
-		SGI_Whisper.status[i].text:SetPoint("LEFT",SGI_Whisper,"CENTER",50,yOfs)
-		yOfs = yOfs - 18
-	end
-	local whispers = {
-		"Whisper #1",
-		"Whisper #2",
-		"Whisper #3",
-		"Whisper #4",
-		"Whisper #5",
-		"Whisper #6",
-	}
-
-	anchor = {}
-		anchor.point = "BOTTOMLEFT"
-		anchor.relativePoint = "BOTTOMLEFT"
-		anchor.xOfs = 50
-		anchor.yOfs = 120
-
-	--CreateDropDown(name, parent, label, items, anchor)
-	SGI_Whisper.drop = CreateDropDown("SGI_WHISPER_DROP",SGI_Whisper,SGI.L["Select whisper"],whispers,anchor)
-
-		anchor.xOfs = 100
-		anchor.yOfs = 20
-	--CreateButton(name, parent, width, height, label, anchor, onClick)
-	CreateButton("SGI_SAVEWHISPER",SGI_Whisper,120,30,SGI.L["Save"],anchor,function()
-		local text = SGI_Whisper.edit:GetText()
-		local ID = SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"]
-		SGI_DATA[SGI_DATA_INDEX].settings.whispers[ID] = text
-		SGI_Whisper.edit:SetText("")
-	end)
-	anchor.xOfs = 280
-	CreateButton("SGI_CANCELWHISPER",SGI_Whisper,120,30,SGI.L["Cancel"],anchor,function()
-		SGI_Whisper:Hide()
-	end)
-
-	SGI_Whisper.update = 0
-	SGI_Whisper.changed = false
-	SGI_Whisper:SetScript("OnUpdate",function()
-		if GetTime() > SGI_Whisper.update then
-			for i = 1,6 do
-				if type(SGI_DATA[SGI_DATA_INDEX].settings.whispers[i]) == "string" then
-					SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: |cff00ff00Good|r")
-				else
-					SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: |cffff0000Undefined|r")
-				end
-			end
-			local ID = SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"]
-			SGI_Whisper.status[ID].text:SetText("Whisper #"..ID.." status: |cffff8800Editing...|r")
-
-			if ID ~= SGI_Whisper.changed then
-				SGI_Whisper.changed = ID
-				SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "")
-			end
-
-			SGI_Whisper.update = GetTime() + 0.5
-		end
-	end)
-
-	SGI_Whisper:HookScript("OnHide", function() if (SGI_Options.showAgain) then SGI:ShowOptions() SGI_Options.showAgain = false end end)
-end
-
-local function ShowWhisperFrame()
-	if SGI_Whisper then
-		SGI_Whisper:Show()
-	else
-		CreateWhisperDefineFrame()
-		SGI_Whisper:Show()
-	end
-end
-
-local function HideWhisperFrame()
-	if SGI_Whisper then
-		SGI_Whisper:Hide()
-	end
-end
-
-local function CreateFilterFrame()
-	CreateFrame("Frame","SGI_Filters")
-	SGI_Filters:SetWidth(550)
-	SGI_Filters:SetHeight(380)
-	SetFramePosition(SGI_Filters)
-	SGI_Filters:SetMovable(true)
-	SGI_Filters:SetScript("OnMouseDown",function(self)
-		self:StartMoving()
-	end)
-	SGI_Filters:SetScript("OnMouseUp",function(self)
-		self:StopMovingOrSizing()
-		SaveFramePosition(SGI_Filters)
-	end)
-	local backdrop =
-	{
-		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background",
-		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
-		tile = true,
-		tileSize = 16,
-		edgeSize = 16,
-		insets = { left = 4, right = 4, top = 4, bottom = 4 }
-	}
-	SGI_Filters:SetBackdrop(backdrop)
-	local close = CreateFrame("Button",nil,SGI_Filters,"UIPanelCloseButton")
-	close:SetPoint("TOPRIGHT",SGI_Filters,"TOPRIGHT",-4,-4)
-
-	SGI_Filters.title = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge");
-	SGI_Filters.title:SetPoint("TOP", SGI_Filters, "TOP", 0, -15);
-	SGI_Filters.title:SetText("Edit filters");
-	SGI_Filters.underTitle = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_Filters.underTitle:SetPoint("TOP", SGI_Filters, "TOP", 0, -38);
-	SGI_Filters.underTitle:SetText("|cffff3300Any textbox left empty, except \"Filter name\" will be excluded from the filter|r");
-	SGI_Filters.underTitle:SetWidth(400);
-	SGI_Filters.bottomText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFOntNormal");
-	SGI_Filters.bottomText:SetPoint("BOTTOM", SGI_Filters, "BOTTOM", 0, 60);
-	SGI_Filters.bottomText:SetText("|cff00ff00In order to be filtered, a player has to match |r|cffFF3300ALL|r |cff00ff00criterias|r");
-
-	SGI_Filters.tooltip = CreateFrame("Frame", "FilterTooltip", SGI_Filters.tooltip, "GameTooltipTemplate");
-	SGI_Filters.tooltip:SetWidth(150);
-	SGI_Filters.tooltip.text = SGI_Filters.tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_Filters.tooltip.text:SetPoint("CENTER", SGI_Filters.tooltip, "CENTER", 0, 0);
-	SGI_Filters.tooltip.text:SetJustifyH("LEFT");
-
-	SGI_Filters.editBoxName = CreateFrame("EditBox", "SGI_EditBoxName", SGI_Filters);
-	SGI_Filters.editBoxName:SetWidth(150);
-	SGI_Filters.editBoxName:SetHeight(30);
-	SGI_Filters.editBoxName:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -90);
-	SGI_Filters.editBoxName:SetFontObject("GameFontNormal");
-	SGI_Filters.editBoxName:SetMaxLetters(65);
-	SGI_Filters.editBoxName:SetBackdrop(backdrop);
-	SGI_Filters.editBoxName:SetText("");
-	SGI_Filters.editBoxName:SetTextInsets(10,10,10,10);
-	SGI_Filters.editBoxName:SetScript("OnHide",function(self)
-		self:SetText("");
-	end)
-	SGI_Filters.editBoxName.title = SGI_Filters.editBoxName:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_Filters.editBoxName.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxName,"TOPLEFT", 0, 5);
-	SGI_Filters.editBoxName.title:SetText("Filter name");
-
-	SGI_Filters.editBoxNameFilter = CreateFrame("EditBox", "SGI_EditBoxNameFilter", SGI_Filters);
-	SGI_Filters.editBoxNameFilter:SetWidth(150);
-	SGI_Filters.editBoxNameFilter:SetHeight(30);
-	SGI_Filters.editBoxNameFilter:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -150);
-	SGI_Filters.editBoxNameFilter:SetFontObject("GameFontNormal");
-	SGI_Filters.editBoxNameFilter:SetMaxLetters(65);
-	SGI_Filters.editBoxNameFilter:SetBackdrop(backdrop);
-	SGI_Filters.editBoxNameFilter:SetText("");
-	SGI_Filters.editBoxNameFilter:SetTextInsets(10,10,10,10);
-	SGI_Filters.editBoxNameFilter:SetScript("OnHide",function(self)
-		self:SetText("");
-	end)
-	SGI_Filters.editBoxNameFilter:SetScript("OnEnter", function(self)
-		SGI_Filters.tooltip.text:SetText(SGI.L["Enter a phrase which you wish to include in the filter. If a player's name contains the phrase, they will not be queued"]);
-		SGI_Filters.tooltip.text:SetWidth(135);
-		SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12);
-		SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5);
-		SGI_Filters.tooltip:Show();
-	end)
-	SGI_Filters.editBoxNameFilter:SetScript("OnLeave", function()
-		SGI_Filters.tooltip:Hide()
-	end)
-
-	SGI_Filters.editBoxNameFilter.title = SGI_Filters.editBoxNameFilter:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_Filters.editBoxNameFilter.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxNameFilter,"TOPLEFT", 0, 5);
-	SGI_Filters.editBoxNameFilter.title:SetText("Name exceptions");
-
-	SGI_Filters.editBoxLvl = CreateFrame("EditBox", "SGI_EditBoxLvl", SGI_Filters);
-	SGI_Filters.editBoxLvl:SetWidth(150);
-	SGI_Filters.editBoxLvl:SetHeight(30);
-	SGI_Filters.editBoxLvl:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -210);
-	SGI_Filters.editBoxLvl:SetFontObject("GameFontNormal");
-	SGI_Filters.editBoxLvl:SetMaxLetters(65);
-	SGI_Filters.editBoxLvl:SetBackdrop(backdrop);
-	SGI_Filters.editBoxLvl:SetText("");
-	SGI_Filters.editBoxLvl:SetTextInsets(10,10,10,10);
-	SGI_Filters.editBoxLvl:SetScript("OnHide",function(self)
-		self:SetText("");
-	end)
-	SGI_Filters.editBoxLvl:SetScript("OnEnter", function(self)
-		SGI_Filters.tooltip.text:SetText(SGI.L["Enter the level range for the filter. \n\nExample: |cff00ff0055|r:|cff00A2FF58|r \n\nThis would result in only matching players that range from level |cff00ff0055|r to |cff00A2FF58|r (inclusive)"]);
-		SGI_Filters.tooltip.text:SetWidth(135);
-		SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12);
-		SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5);
-		SGI_Filters.tooltip:Show();
-	end)
-	SGI_Filters.editBoxLvl:SetScript("OnLeave", function()
-		SGI_Filters.tooltip:Hide()
-	end)
-
-	SGI_Filters.editBoxLvl.title = SGI_Filters.editBoxLvl:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_Filters.editBoxLvl.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxLvl,"TOPLEFT", 0, 5);
-	SGI_Filters.editBoxLvl.title:SetText("Level range (Min:Max)");
-
-	SGI_Filters.editBoxVC = CreateFrame("EditBox", "SGI_EditBoxVC", SGI_Filters);
-	SGI_Filters.editBoxVC:SetWidth(150);
-	SGI_Filters.editBoxVC:SetHeight(30);
-	SGI_Filters.editBoxVC:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -270);
-	SGI_Filters.editBoxVC:SetFontObject("GameFontNormal");
-	SGI_Filters.editBoxVC:SetMaxLetters(65);
-	SGI_Filters.editBoxVC:SetBackdrop(backdrop);
-	SGI_Filters.editBoxVC:SetText("");
-	SGI_Filters.editBoxVC:SetTextInsets(10,10,10,10);
-	SGI_Filters.editBoxVC:SetScript("OnHide",function(self)
-		self:SetText("");
-	end)
-
-	SGI_Filters.editBoxVC:SetScript("OnEnter", function(self)
-		SGI_Filters.tooltip.text:SetText(SGI.L["Enter the maximum amount of consecutive vowels and consonants a player's name can contain.\n\nExample: |cff00ff003|r:|cff00A2FF5|r\n\nThis would cause players with more than |cff00ff003|r vowels in a row or more than |cff00A2FF5|r consonants in a row not to be queued."]);
-		SGI_Filters.tooltip.text:SetWidth(135);
-		SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12);
-		SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5);
-		SGI_Filters.tooltip:Show();
-	end)
-	SGI_Filters.editBoxVC:SetScript("OnLeave", function()
-		SGI_Filters.tooltip:Hide()
-	end)
-
-	SGI_Filters.editBoxVC.title = SGI_Filters.editBoxVC:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_Filters.editBoxVC.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxVC,"TOPLEFT", 0, 5);
-	SGI_Filters.editBoxVC.title:SetText("Max Vowels/Cons (V:C)");
-
-	SGI_EditBoxName:SetScript("OnEnterPressed", function()
-		SGI_EditBoxNameFilter:SetFocus();
-	end);
-	SGI_EditBoxNameFilter:SetScript("OnEnterPressed", function()
-		SGI_EditBoxLvl:SetFocus();
-	end);
-	SGI_EditBoxLvl:SetScript("OnEnterPressed", function()
-		SGI_EditBoxVC:SetFocus();
-	end);
-	SGI_EditBoxVC:SetScript("OnEnterPressed", function()
-		SGI_EditBoxName:SetFocus();
-	end);
-	SGI_EditBoxName:SetScript("OnTabPressed", function()
-		SGI_EditBoxNameFilter:SetFocus();
-	end);
-	SGI_EditBoxNameFilter:SetScript("OnTabPressed", function()
-		SGI_EditBoxLvl:SetFocus();
-	end);
-	SGI_EditBoxLvl:SetScript("OnTabPressed", function()
-		SGI_EditBoxVC:SetFocus();
-	end);
-	SGI_EditBoxVC:SetScript("OnTabPressed", function()
-		SGI_EditBoxName:SetFocus();
-	end);
-
-	local CLASS = {
-			[SGI.L["Death Knight"]] = "DEATHKNIGHT",
-			[SGI.L["Demon Hunter"]] = "DEMONHUNTER",
-			[SGI.L["Druid"]] = "DRUID",
-			[SGI.L["Hunter"]] = "HUNTER",
-			[SGI.L["Mage"]] = "MAGE",
-			[SGI.L["Monk"]] = "MONK",
-			[SGI.L["Paladin"]] = "PALADIN",
-			[SGI.L["Priest"]] = "PRIEST",
-			[SGI.L["Rogue"]] = "ROGUE",
-			[SGI.L["Shaman"]] = "SHAMAN",
-			[SGI.L["Warlock"]] = "WARLOCK",
-			[SGI.L["Warrior"]] = "WARRIOR"
-	}
-	local Classes = {
-			SGI.L["Ignore"],
-			SGI.L["Death Knight"],
-			SGI.L["Demon Hunter"],
-			SGI.L["Druid"],
-			SGI.L["Hunter"],
-			SGI.L["Mage"],
-			SGI.L["Monk"],
-			SGI.L["Paladin"],
-			SGI.L["Priest"],
-			SGI.L["Rogue"],
-			SGI.L["Shaman"],
-			SGI.L["Warlock"],
-			SGI.L["Warrior"],
-	}
-	local Races = {}
-	if UnitFactionGroup("player") == "Horde" then
-		Races = {
-			SGI.L["Ignore"],
-			SGI.L["Orc"],
-			SGI.L["Blood Elf"],
-			SGI.L["Undead"],
-			SGI.L["Troll"],
-			SGI.L["Goblin"],
-			SGI.L["Tauren"],
-			SGI.L["Pandaren"],
-			SGI.L["Highmountain Tauren"],
-			SGI.L["Nightborne"],
-		}
-	else
-		Races = {
-			SGI.L["Ignore"],
-			SGI.L["Human"],
-			SGI.L["Dwarf"],
-			SGI.L["Worgen"],
-			SGI.L["Draenei"],
-			SGI.L["Night Elf"],
-			SGI.L["Gnome"],
-			SGI.L["Pandaren"],
-			SGI.L["Void Elf"],
-			SGI.L["Lightforged Draenei"],
-		}
-	end
-
-	SGI_Filters.classText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_Filters.raceText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-
-	SGI_Filters.classCheckBoxes = {};
-	local anchor = {
-		point = "TOPLEFT",
-		relativePoint = "TOPLEFT",
-		xOfs = 40,
-		yOfs = -90,
-	}
-	for k,_ in pairs(Classes) do
-		SGI_Filters.classCheckBoxes[k] = CreateCheckbox("CHECKBOX_FILTERS_CLASS_"..Classes[k], SGI_Filters, Classes[k], anchor)
-
-		anchor.yOfs = anchor.yOfs - 18;
-	end
-	SGI_Filters.classText:SetPoint("BOTTOM", SGI_Filters.classCheckBoxes[1], "TOP", -5, 3);
-	SGI_Filters.classText:SetText(SGI.L["Classes:"]);
-
-	if (SGI_Filters.classCheckBoxes[1]:GetChecked()) then
-		for i = 2,12 do
-			SGI_Filters.classCheckBoxes[i]:Hide();
-		end
-	else
-		for i = 2,12 do
-			SGI_Filters.classCheckBoxes[i]:Show();
-		end
-	end
-
-	SGI_Filters.classCheckBoxes[1]:HookScript("PostClick", function()
-		if (SGI_Filters.classCheckBoxes[1]:GetChecked()) then
-			for i = 2,12 do
-				SGI_Filters.classCheckBoxes[i]:Hide();
-			end
-		else
-			for i = 2,12 do
-				SGI_Filters.classCheckBoxes[i]:Show();
-			end
-		end
-	end)
-
-
-	SGI_Filters.raceCheckBoxes = {};
-	anchor = {
-		point = "TOPLEFT",
-		relativePoint = "TOPLEFT",
-		xOfs = 160,
-		yOfs = -90,
-	}
-	for k,_ in pairs(Races) do
-		SGI_Filters.raceCheckBoxes[k] = CreateCheckbox("CHECKBOX_FILTERS_RACE_"..Races[k], SGI_Filters, Races[k], anchor)
-		anchor.yOfs = anchor.yOfs - 18;
-	end
-
-	SGI_Filters.raceText:SetPoint("BOTTOM", SGI_Filters.raceCheckBoxes[1], "TOP", -5, 3);
-	SGI_Filters.raceText:SetText(SGI.L["Races:"]);
-
-	if (SGI_Filters.raceCheckBoxes[1]:GetChecked()) then
-		for i = 2,8 do
-			SGI_Filters.raceCheckBoxes[i]:Hide();
-		end
-	else
-		for i = 2,8 do
-			SGI_Filters.raceCheckBoxes[i]:Show();
-		end
-	end
-
-	SGI_Filters.raceCheckBoxes[1]:HookScript("PostClick", function()
-		if (SGI_Filters.raceCheckBoxes[1]:GetChecked()) then
-			for i = 2,8 do
-				SGI_Filters.raceCheckBoxes[i]:Hide();
-			end
-		else
-			for i = 2,8 do
-				SGI_Filters.raceCheckBoxes[i]:Show();
-			end
-		end
-	end)
-
-
-	local function GetFilterData()
-		local FilterName = SGI_EditBoxName:GetText();
-		SGI_EditBoxName:SetText("");
-		if (not FilterName or strlen(FilterName) < 1) then
-			return;
-		end
-		SGI:debug("Filter name: "..FilterName);
-		local V,C = SGI_EditBoxVC:GetText();
-		if (V and strlen(V) > 1) then
-			V,C = strsplit(":", V);
-			V = tonumber(V);
-			C = tonumber(C);
-			if (V == "") then V = nil end
-			if (C == "") then C = nil end
-			SGI:debug("Max Vowels: "..(V or "N/A")..", Max Consonants: "..(C or "N/A"));
-		end
-		SGI_EditBoxVC:SetText("");
-		local Min,Max = SGI_EditBoxLvl:GetText();
-		if (Min and strlen(Min) > 1) then
-			Min, Max = strsplit(":",Min);
-			Min = tonumber(Min);
-			Max = tonumber(Max);
-			SGI:debug("Level range: "..Min.." - "..Max);
-		end
-		SGI_EditBoxLvl:SetText("");
-
-		local ExceptionName = SGI_EditBoxNameFilter:GetText()
-		if (ExceptionName == "") then
-			ExceptionName = nil;
-		end
-		SGI_EditBoxNameFilter:SetText("");
-
-
-
-		local classes = {};
-		if (not SGI_Filters.classCheckBoxes[1]:GetChecked()) then
-			for k,_ in pairs(SGI_Filters.classCheckBoxes) do
-				if (SGI_Filters.classCheckBoxes[k]:GetChecked()) then
-					classes[CLASS[SGI_Filters.classCheckBoxes[k].label:GetText()]] = true;
-					SGI:debug(CLASS[SGI_Filters.classCheckBoxes[k].label:GetText()]);
-					SGI_Filters.classCheckBoxes[k]:SetChecked(false);
-				end
-			end
-		end
-
-		local races = {}
-		if (not SGI_Filters.raceCheckBoxes[1]:GetChecked()) then
-			for k,_ in pairs(SGI_Filters.raceCheckBoxes) do
-				if (SGI_Filters.raceCheckBoxes[k]:GetChecked()) then
-					races[SGI_Filters.raceCheckBoxes[k].label:GetText()] = true;
-					SGI:debug(SGI_Filters.raceCheckBoxes[k].label:GetText());
-					SGI_Filters.raceCheckBoxes[k]:SetChecked(false);
-				end
-			end
-		end
-		SGI:CreateFilter(FilterName,classes,ExceptionName,Min,Max,races,V,C);
-		SGI_FilterHandle.needRedraw = true;
-		return true;
-	end
-
-	anchor = {
-		point = "BOTTOM",
-		relativePoint = "BOTTOM",
-		xOfs = -60,
-		yOfs = 20,
-	}
-
-
-	SGI_Filters.button1 = CreateButton("BUTTON_SAVE_FILTER", SGI_Filters, 120, 30, SGI.L["Save"], anchor, GetFilterData);
-		anchor.xOfs = 60;
-	SGI_Filters.button2 = CreateButton("BUTTON_CANCEL_FILTER", SGI_Filters, 120, 30, SGI.L["Back"], anchor, function() SGI_Filters:Hide() end);
-
-	SGI_Filters:HookScript("OnHide", function() SGI:ShowFilterHandle() SGI_FilterHandle.showOpt = true end);
-
-end
-
-local function ShowFilterFrame()
-	if (not SGI_Filters) then
-		CreateFilterFrame();
-	end
-	SGI_Filters:Show();
-end
-
-
-local function CreateFilterHandleFrame()
-	CreateFrame("Frame","SGI_FilterHandle")
-	SGI_FilterHandle:SetWidth(450)
-	SGI_FilterHandle:SetHeight(350)
-	SetFramePosition(SGI_FilterHandle)
-	SGI_FilterHandle:SetMovable(true)
-	SGI_FilterHandle:SetScript("OnMouseDown",function(self)
-		self:StartMoving()
-	end)
-	SGI_FilterHandle:SetScript("OnMouseUp",function(self)
-		self:StopMovingOrSizing()
-		SaveFramePosition(SGI_FilterHandle)
-	end)
-	local backdrop =
-	{
-		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background",
-		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
-		tile = true,
-		tileSize = 16,
-		edgeSize = 16,
-		insets = { left = 4, right = 4, top = 4, bottom = 4 }
-	}
-	SGI_FilterHandle:SetBackdrop(backdrop)
-	local close = CreateFrame("Button",nil,SGI_FilterHandle,"UIPanelCloseButton")
-	close:SetPoint("TOPRIGHT",SGI_FilterHandle,"TOPRIGHT",-4,-4)
-
-	SGI_FilterHandle.title = SGI_FilterHandle:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_FilterHandle.title:SetText("Filters")
-	SGI_FilterHandle.title:SetPoint("TOP",SGI_FilterHandle,"TOP",0,-15)
-	SGI_FilterHandle.underTitle = SGI_FilterHandle:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_FilterHandle.underTitle:SetText("Click to toggle");
-	SGI_FilterHandle.underTitle:SetPoint("TOP", SGI_FilterHandle, "TOP", 0, -35);
-
-	local anchor = {}
-			anchor.point = "BOTTOM"
-			anchor.relativePoint = "BOTTOM"
-			anchor.xOfs = -60
-			anchor.yOfs = 30
-
-	SGI_FilterHandle.button1 = CreateButton("BUTTON_EDIT_FILTERS", SGI_FilterHandle, 120, 30, SGI.L["Add filters"], anchor, function() ShowFilterFrame() SGI_FilterHandle.showOpt = false SGI_FilterHandle.showSelf = true SGI_FilterHandle:Hide() end);
-		anchor.xOfs = 60
-	SGI_FilterHandle.button2 = CreateButton("BUTTON_EDIT_FILTERS", SGI_FilterHandle, 120, 30, SGI.L["Back"], anchor, function() close:Click() end);
-
-
-	SGI_FilterHandle.tooltip = CreateFrame("Frame", "SGI_HandleTooltip", SGI_FilterHandle, "GameTooltipTemplate");
-	SGI_FilterHandle.tooltip:SetWidth(150);
-	SGI_FilterHandle.tooltip.text = SGI_FilterHandle.tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	SGI_FilterHandle.tooltip.text:SetPoint("CENTER", SGI_FilterHandle.tooltip, "CENTER", 0, 0);
-	SGI_FilterHandle.tooltip.text:SetJustifyH("LEFT");
-
-	local function FormatTooltipFilterText(filter)
-		local text = "Filter name: "..filter.nameOfFilter.."\n";
-
-		if (filter.active) then
-			text = text.."|cff00ff00[ACTIVE]|r\n";
-		else
-			text = text.."|cffff0000[INACTIVE]|r\n";
-		end
-
-		if (filter.class) then
-			for k,v in pairs(filter.class) do
-				text = text.."|cff"..(SGI:GetClassColor(k)..k).."|r\n";
-			end
-		end
-
-		if (filter.race) then
-			for k,v in pairs(filter.race) do
-				text = text.."|cff16ABB5"..k.."|r\n";
-			end
-		end
-
-		if (filter.minLvl and filter.minLvl ~= "") then
-			text = text.."|cff00ff00"..filter.minLvl.."|r - ";
-			if (filter.maxLvl) then
-				text = text.."|cffff0000"..filter.maxLvl.."|r\n";
-			else
-				text = text.."\n";
-			end
-		end
-
-		if (filter.maxVowels and filter.maxVowels ~= "") then
-			text = text.."Vowels: |cff16ABB5"..filter.maxVowels.."|r\n";
-		end
-
-		if (filter.maxConsonants and filter.maxVowels ~= "") then
-			text = text.."Consonants: |cff16ABB5"..filter.maxConsonants.."|r\n";
-		end
-
-		if (filter.name and filter.name ~= "") then
-			text = text.."Name exception: |cff16ABB5"..filter.name.."|r";
-		end
-
-		return text;
-	end
-
-	SGI_FilterHandle.filterFrames = {}
-	SGI_FilterHandle.update = 0;
-	SGI_FilterHandle.needRedraw = false;
-	SGI_FilterHandle:SetScript("OnUpdate", function(self)
-		if (SGI_FilterHandle.update < GetTime()) then
-
-			local anchor = {}
-				anchor.xOfs = -175
-				anchor.yOfs = 110
-
-			local F = SGI_DATA[SGI_DATA_INDEX].settings.filters;
-
-			if (SGI_FilterHandle.needRedraw) then
-				for k,_ in pairs(SGI_FilterHandle.filterFrames) do
-					SGI_FilterHandle.filterFrames[k]:Hide();
-				end
-				SGI_FilterHandle.filterFrames = {};
-				SGI_FilterHandle.needRedraw = false;
-			end
-
-			for k,_ in pairs(F) do
-				if (not SGI_FilterHandle.filterFrames[k]) then
-					SGI_FilterHandle.filterFrames[k] = CreateFrame("Button", "FilterFrame"..k, SGI_FilterHandle);
-					SGI_FilterHandle.filterFrames[k]:SetWidth(80)
-					SGI_FilterHandle.filterFrames[k]:SetHeight(25);
-					SGI_FilterHandle.filterFrames[k]:EnableMouse(true);
-					SGI_FilterHandle.filterFrames[k]:SetPoint("CENTER", SGI_FilterHandle, "CENTER", anchor.xOfs, anchor.yOfs);
-					if mod(k,5) == 0 then
-						anchor.xOfs = -175
-						anchor.yOfs = anchor.yOfs - 30
-					else
-						anchor.xOfs = anchor.xOfs + 85
-					end
-					SGI_FilterHandle.filterFrames[k].text = SGI_FilterHandle.filterFrames[k]:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-					SGI_FilterHandle.filterFrames[k].text:SetPoint("LEFT", SGI_FilterHandle.filterFrames[k], "LEFT", 3, 0);
-					SGI_FilterHandle.filterFrames[k].text:SetJustifyH("LEFT");
-					SGI_FilterHandle.filterFrames[k].text:SetWidth(75);
-					SGI_FilterHandle.filterFrames[k]:EnableMouse(true);
-					SGI_FilterHandle.filterFrames[k]:RegisterForClicks("LeftButtonDown","RightButtonDown");
-					SGI_FilterHandle.filterFrames[k].highlight = SGI_FilterHandle.filterFrames[k]:CreateTexture();
-					SGI_FilterHandle.filterFrames[k].highlight:SetAllPoints();
-					if (SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active) then
-						SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2);
-					else
-						SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2);
-					end
-					SGI_FilterHandle.filterFrames[k]:SetScript("OnEnter", function(self)
-						self.highlight:SetTexture(1,1,0,0.2);
-						SGI:debug("Enter: YELLOW");
-
-						SGI_FilterHandle.tooltip.text:SetText(FormatTooltipFilterText(F[k]));
-						SGI_FilterHandle.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -3);
-						SGI_FilterHandle.tooltip:SetHeight(SGI_FilterHandle.tooltip.text:GetHeight() + 12);
-						SGI_FilterHandle.tooltip:SetWidth(SGI_FilterHandle.tooltip.text:GetWidth() + 10);
-						SGI_FilterHandle.tooltip:Show();
-					end)
-					SGI_FilterHandle.filterFrames[k]:SetScript("OnLeave", function(self)
-						if (F[k] and F[k].active) then--SGI_FilterHandle.filterFrames[k].state) then
-							SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2);
-							SGI:debug("Leave: GREEN");
-
-						else
-							SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2);
-							SGI:debug("Leave: RED");
-						end
-
-						SGI_FilterHandle.tooltip:Hide();
-					end)
-				end
-
-				SGI_FilterHandle.filterFrames[k].filter = F[k];
-				SGI_FilterHandle.filterFrames[k].text:SetText(F[k].nameOfFilter);
-				SGI_FilterHandle.filterFrames[k]:Show();
-
-				SGI_FilterHandle.filterFrames[k]:SetScript("OnClick", function(self, button)
-					SGI:debug(button);
-					if (button == "LeftButton") then
-						if (SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active) then
-							SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active = nil;
-							SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2);
-							SGI:debug("Click: RED");
-						else
-							SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active = true;
-							SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2);
-							SGI:debug("Click: GREEN");
-						end
-
-						SGI_FilterHandle.tooltip.text:SetText(FormatTooltipFilterText(F[k]));
-						SGI_FilterHandle.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -3);
-						SGI_FilterHandle.tooltip:SetHeight(SGI_FilterHandle.tooltip.text:GetHeight() + 12);
-						SGI_FilterHandle.tooltip:SetWidth(SGI_FilterHandle.tooltip.text:GetWidth() + 10);
-						SGI_FilterHandle.tooltip:Show();
-					else
-						SGI_DATA[SGI_DATA_INDEX].settings.filters[k] = nil;
-						SGI_FilterHandle.needRedraw = true;
-					end
-
-				end)
-
-			end
-
-			SGI_FilterHandle.update = GetTime() + 1;
-		end
-	end)
-	SGI_FilterHandle.showOpt = true;
-	SGI_FilterHandle:HookScript("OnHide", function() if SGI_FilterHandle.showOpt then SGI:ShowOptions() end end)
-end
-
-function SGI:ShowFilterHandle()
-	if (not SGI_FilterHandle) then
-		CreateFilterHandleFrame();
-	end
-	SGI_FilterHandle:Show()
-end
-
-local function ChangeLog()
-	CreateFrame("Frame","SGI_ChangeLog")
-	SGI_ChangeLog:SetWidth(550)
-	SGI_ChangeLog:SetHeight(350)
-	SGI_ChangeLog:SetBackdrop(
-	{
-		bgFile = "Interface/ACHIEVEMENTFRAME/UI-Achievement-Parchment-Horizontal",
-		edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
-		tile = false,
-		tileSize = 16,
-		edgeSize = 16,
-		insets = { left = 4, right = 4, top = 4, bottom = 4 }
-	}
-	)
-	SetFramePosition(SGI_ChangeLog)
-
-	local anchor = {}
-			anchor.point = "BOTTOMRIGHT"
-			anchor.relativePoint = "BOTTOMRIGHT"
-			anchor.xOfs = -210
-			anchor.yOfs = 10
-
-	SGI_ChangeLog.check1 = CreateCheckbox("SGI_CHANGES",SGI_ChangeLog,SGI.L["Don't show this after new updates"],anchor)
-		anchor.xOfs = -300
-	SGI_ChangeLog.button1 = CreateButton("SGI_CLOSE_CHANGES",SGI_ChangeLog,120,30,SGI.L["Close"],anchor,function() SGI_ChangeLog:Hide() SGI_DATA.showChanges = SGI.VERSION_MAJOR end)
-
-	SGI_ChangeLog.title = SGI_ChangeLog:CreateFontString()
-	SGI_ChangeLog.title:SetFont("Fonts\\FRIZQT__.TTF",22,"OUTLINE")
-	SGI_ChangeLog.title:SetText("|cffffff00<|r|cff16ABB5SuperGuildInvite|r|cff00ff00 Recent Changes|r|cffffff00>|r|cffffff00")
-	SGI_ChangeLog.title:SetPoint("TOP",SGI_ChangeLog,"TOP",0,-12)
-
-	SGI_ChangeLog.version = SGI_ChangeLog:CreateFontString()
-	SGI_ChangeLog.version:SetFont("Fonts\\FRIZQT__.TTF",16,"OUTLINE")
-	SGI_ChangeLog.version:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",15,-40)
-	SGI_ChangeLog.version:SetText("")
-
-	SGI_ChangeLog.items = {}
-	local y = -65
-	for i = 1,10 do
-		SGI_ChangeLog.items[i] = SGI_ChangeLog:CreateFontString()
-		SGI_ChangeLog.items[i]:SetFont("Fonts\\FRIZQT__.TTF",14,"OUTLINE")
-		SGI_ChangeLog.items[i]:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",30,y)
-		SGI_ChangeLog.items[i]:SetText("")
-		SGI_ChangeLog.items[i]:SetJustifyH("LEFT")
-		SGI_ChangeLog.items[i]:SetSpacing(3)
-		y = y - 17
-	end
-	SGI_ChangeLog.SetChange = function(changes)
-		local Y = -65
-		SGI_ChangeLog.version:SetText("|cff16ABB5"..changes.version.."|r")
-		for k,_ in pairs(changes.items) do
-			SGI_ChangeLog.items[k]:SetText("|cffffff00"..changes.items[k].."|r")
-			SGI_ChangeLog.items[k]:SetWidth(490)
-			SGI_ChangeLog.items[k]:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",30,Y)
-			Y = Y - SGI_ChangeLog.items[k]:GetHeight() - 5
-		end
-	end
-end
-
-function SGI:ShowChanges()
-	if ( SGI_ChangeLog ) then
-		SGI_ChangeLog:Show()
-	else
-		ChangeLog()
-		SGI_ChangeLog:Show()
-	end
-	SGI_ChangeLog.SetChange(SGI.versionChanges);
-end
-
-
-local function CreateTroubleShooter()
-	CreateFrame("Frame","SGI_TroubleShooter")
-	SGI_TroubleShooter:SetWidth(300)
-	SGI_TroubleShooter:SetHeight(100)
-	SetFramePosition(SGI_TroubleShooter)
-	SGI_TroubleShooter:SetMovable(true)
-	SGI_TroubleShooter:SetScript("OnMouseDown",function(self)
-		self:StartMoving()
-	end)
-	SGI_TroubleShooter:SetScript("OnMouseUp",function(self)
-		self:StopMovingOrSizing()
-		SaveFramePosition(SGI_TroubleShooter)
-	end)
-	local backdrop =
-	{
-		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background",
-		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
-		tile = true,
-		tileSize = 16,
-		edgeSize = 16,
-		insets = { left = 4, right = 4, top = 4, bottom = 4 }
-	}
-	SGI_TroubleShooter:SetBackdrop(backdrop)
-	local close = CreateFrame("Button",nil,SGI_TroubleShooter,"UIPanelCloseButton")
-	close:SetPoint("TOPRIGHT",SGI_TroubleShooter,"TOPRIGHT",-4,-4)
-
-	SGI_TroubleShooter.title = SGI_TroubleShooter:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_TroubleShooter.title:SetPoint("TOP",SGI_TroubleShooter,"TOP",0,-10)
-	SGI_TroubleShooter.title:SetText("Common issues")
-
-
-	local update = 0;
-
-	SGI_TroubleShooter.items = {};
-	SGI_TroubleShooter:SetScript("OnUpdate", function()
-		if (update < GetTime()) then
-
-
-
-
-			update = GetTime() + 0.5;
-		end
-	end)
-
-
-	SGI_TroubleShooter:HookScript("OnHide", function() if (SGI_Options.showAgain) then SGI_Options:Show() SGI_Options.showAgain = false end end);
-end
-
-function SGI:ShowTroubleShooter()
-	if (not SGI_TroubleShooter) then
-		CreateTroubleShooter();
-	end
-	SGI_TroubleShooter:Show();
-end
-
-
-local function OptBtn2_OnClick()
-	SGI:ShowSuperScanFrame();
-	SSBtn3_OnClick(SGI_SUPERSCAN_PLAYPAUSE2);
-end
-
-
-local function CreateOptions()
-	CreateFrame("Frame","SGI_Options")
-	SGI_Options:SetWidth(550)
-	SGI_Options:SetHeight(350)
-	SetFramePosition(SGI_Options)
-	SGI_Options:SetMovable(true)
-	SGI_Options:SetScript("OnMouseDown",function(self)
-		self:StartMoving()
-	end)
-	SGI_Options:SetScript("OnMouseUp",function(self)
-		self:StopMovingOrSizing()
-		SaveFramePosition(SGI_Options)
-	end)
-	local backdrop =
-	{
-		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background",
-		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
-		tile = true,
-		tileSize = 16,
-		edgeSize = 16,
-		insets = { left = 4, right = 4, top = 4, bottom = 4 }
-	}
-	SGI_Options:SetBackdrop(backdrop)
-	local close = CreateFrame("Button",nil,SGI_Options,"UIPanelCloseButton")
-	close:SetPoint("TOPRIGHT",SGI_Options,"TOPRIGHT",-4,-4)
-
-	SGI_Options.title = SGI_Options:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_Options.title:SetText("SuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options")
-	SGI_Options.title:SetPoint("TOP",SGI_Options,"TOP",0,-15)
-	SGI_Options.bottom = SGI_Options:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_Options.bottom:SetText("Written by Janniie - Stormreaver EU")
-	SGI_Options.bottom:SetPoint("BOTTOM",SGI_Options,"BOTTOM",0,1)
-
-	SGI_Options.optionHelpText = SGI_Options:CreateFontString(nil, "OVERLAY","GameFontNormal");
-	SGI_Options.optionHelpText:SetText("|cff00D2FFScroll to change levels|r");
-	SGI_Options.optionHelpText:SetPoint("TOP",SGI_Options,"TOP",100,-40);
-
-	local anchor = {}
-			anchor.point = "TOPLEFT"
-			anchor.relativePoint = "TOPLEFT"
-			anchor.xOfs = 7
-			anchor.yOfs = -50
-
-	local WhisperMode = {
-		SGI.L["Invite only"],
-		SGI.L["Invite, then whisper"],
-		SGI.L["Whisper only"],
-	}
-
-	local spacing = 25;
-
-	SGI_Options.dropDown1 = CreateDropDown("DROPDOWN_INVITE_MODE", SGI_Options, SGI.L["Invite Mode"], WhisperMode, anchor);
-		anchor.yOfs = anchor.yOfs - spacing - 7;
-		anchor.xOfs = anchor.xOfs + 13;
-	SGI_Options.checkBox1 = CreateCheckbox("CHECKBOX_SGI_MUTE", SGI_Options, SGI.L["Mute SGI"], anchor);
-		anchor.yOfs = anchor.yOfs - spacing;
-	SGI_Options.checkBox2 = CreateCheckbox("CHECKBOX_ADV_SCAN", SGI_Options, SGI.L["Advanced scan options"], anchor);
-		anchor.yOfs = anchor.yOfs - spacing;
-	SGI_Options.checkBox3 = CreateCheckbox("CHECKBOX_HIDE_SYSTEM", SGI_Options, SGI.L["Hide system messages"], anchor);
-		anchor.yOfs = anchor.yOfs - spacing;
-	SGI_Options.checkBox7 = CreateCheckbox("CHECKBOX_HIDE_WHISPER", SGI_Options, SGI.L["Hide outgoing whispers"], anchor);
-		anchor.yOfs = anchor.yOfs - spacing;
-	SGI_Options.checkBox4 = CreateCheckbox("CHECKBOX_HIDE_MINIMAP", SGI_Options, SGI.L["Hide minimap button"], anchor);
-		anchor.yOfs = anchor.yOfs - spacing;
-	SGI_Options.checkBox5 = CreateCheckbox("CHECKBOX_BACKGROUND_MODE", SGI_Options, SGI.L["Run SuperScan in the background"], anchor);
-		anchor.yOfs = anchor.yOfs - spacing;
-	SGI_Options.checkBox6 = CreateCheckbox("CHECKBOX_ENABLE_FILTERS", SGI_Options, SGI.L["Enable filtering"], anchor);
-
-	SGI_Options.checkBox3:HookScript("PostClick", function(self) ChatIntercept:StateSystem(self:GetChecked()) end);
-	SGI_Options.checkBox7:HookScript("PostClick", function(self) ChatIntercept:StateWhisper(self:GetChecked()) end);
-
-		anchor.point = "BOTTOMLEFT"
-		anchor.relativePoint = "BOTTOMLEFT"
-		anchor.xOfs = 20
-		anchor.yOfs = 45
-
-	--onClickTester
-	SGI_Options.button1 = CreateButton("BUTTON_CUSTOM_WHISPER", SGI_Options, 120, 30, SGI.L["Customize whisper"], anchor, function(self) ShowWhisperFrame() SGI_Options:Hide() SGI_Options.showAgain = true end);
-		anchor.xOfs = anchor.xOfs + 125;
-	SGI_Options.button2 = CreateButton("BUTTON_SUPER_SCAN", SGI_Options, 120, 30, SGI.L["SuperScan"], anchor, OptBtn2_OnClick);
-		anchor.xOfs = anchor.xOfs + 125;
-	SGI_Options.button3 = CreateButton("BUTTON_INVITE", SGI_Options, 120, 30, format(SGI.L["Invite: %d"],SGI:GetNumQueued()), anchor, SGI.SendGuildInvite);
-		anchor.xOfs = anchor.xOfs + 125;
-	SGI_Options.button4 = CreateButton("BUTTON_CHOOSE_INVITES", SGI_Options, 120, 30, SGI.L["Choose invites"], anchor, SGI.ShowInviteList);
-		anchor.yOfs = 80;
-	SGI_Options.button5 = CreateButton("BUTTON_EDIT_FILTERS", SGI_Options, 120, 30, SGI.L["Filters"], anchor, function() SGI:ShowFilterHandle() SGI_Options:Hide() end);
-		anchor.xOfs = anchor.xOfs - 125;
-	--SGI_Options.button6 = CreateButton("BUTTON_HELP", SGI_Options, 120, 30, SGI.L["Help"],anchor, function() SGI:ShowTroubleShooter() SGI_Options:Hide() SGI_Options.showAgain = true end);
-		--anchor.xOfs = anchor.xOfs - 125;
-	SGI_Options.button7 = CreateButton("BUTTON_KEYBIND", SGI_Options, 120, 30, SGI.L["Set Keybind ("..(SGI_DATA[SGI_DATA_INDEX].keyBind and SGI_DATA[SGI_DATA_INDEX].keyBind or "NONE")..")"], anchor, KeyHarvestFrame.GetNewKeybindKey);
-		anchor.xOfs = anchor.xOfs - 125;
-	--SGI_Options.button8 = CreateButton("BUTTON_FILTER", SGI_Options, 120, 30, SGI.L["Filters"], anchor, onClickTester);
-
-
-	SGI_Options.limitLow = CreateFrame("Frame","SGI_LowLimit",SGI_Options)
-	SGI_Options.limitLow:SetWidth(40)
-	SGI_Options.limitLow:SetHeight(40)
-	SGI_Options.limitLow:SetPoint("CENTER",SGI_Options,"CENTER",20,80)
-	SGI_Options.limitLow.text = SGI_Options.limitLow:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_Options.limitLow.text:SetPoint("CENTER")
-	SGI_Options.limitLow.texture = SGI_Options.limitLow:CreateTexture()
-	SGI_Options.limitLow.texture:SetAllPoints()
-	SGI_Options.limitLow.texture:SetTexture(1,1,0,0.2)
-	SGI_Options.limitLow.texture:Hide()
-	SGI_Options.limitTooltip = CreateFrame("Frame","LimitTool",SGI_Options.limitLow,"GameTooltipTemplate")
-
-	SGI_Options.limitTooltip:SetPoint("TOP",SGI_Options.limitLow,"BOTTOM")
-	SGI_Options.limitTooltip.text = SGI_Options.limitTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Options.limitTooltip.text:SetPoint("LEFT",SGI_Options.limitTooltip,"LEFT",12,0)
-	SGI_Options.limitTooltip.text:SetJustifyH("LEFT")
-	SGI_Options.limitTooltip.text:SetText(SGI.L["Highest and lowest level to search for"])
-	SGI_Options.limitTooltip.text:SetWidth(115)
-	SGI_Options.limitTooltip:SetWidth(130)
-	SGI_Options.limitTooltip:SetHeight(SGI_Options.limitTooltip.text:GetHeight() + 12)
-
-	SGI_Options.limitLow:SetScript("OnEnter",function()
-		SGI_Options.limitLow.texture:Show()
-		SGI_Options.limitTooltip:Show()
-	end)
-	SGI_Options.limitLow:SetScript("OnLeave",function()
-		SGI_Options.limitLow.texture:Hide()
-		SGI_Options.limitTooltip:Hide()
-	end)
-
-	SGI_Options.limitHigh = CreateFrame("Frame","SGI_HighLimit",SGI_Options)
-	SGI_Options.limitHigh:SetWidth(40)
-	SGI_Options.limitHigh:SetHeight(40)
-	SGI_Options.limitHigh:SetPoint("CENTER",SGI_Options,"CENTER",60,80)
-	SGI_Options.limitHigh.text = SGI_Options.limitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_Options.limitHigh.text:SetPoint("CENTER")
-	SGI_Options.limitHigh.texture = SGI_Options.limitHigh:CreateTexture()
-	SGI_Options.limitHigh.texture:SetAllPoints()
-	SGI_Options.limitHigh.texture:SetTexture(1,1,0,0.2)
-	SGI_Options.limitHigh.texture:Hide()
-
-	SGI_Options.limitHigh:SetScript("OnEnter",function()
-		SGI_Options.limitHigh.texture:Show()
-		SGI_Options.limitTooltip:Show()
-	end)
-	SGI_Options.limitHigh:SetScript("OnLeave",function()
-		SGI_Options.limitHigh.texture:Hide()
-		SGI_Options.limitTooltip:Hide()
-	end)
-
-	SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.."  - ")
-	SGI_Options.limitLow:SetScript("OnMouseWheel",function(self,delta)
-		if delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.lowLimit + 1 <= SGI_DATA[SGI_DATA_INDEX].settings.highLimit then
-			SGI_DATA[SGI_DATA_INDEX].settings.lowLimit = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit + 1
-			SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.." - ")
-		elseif delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.lowLimit - 1 >= SGI_MIN_LEVEL_SUPER_SCAN then
-			SGI_DATA[SGI_DATA_INDEX].settings.lowLimit = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit - 1
-			SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.." - ")
-		end
-	end)
-
-	SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit)
-	SGI_Options.limitHigh:SetScript("OnMouseWheel",function(self,delta)
-		if delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.highLimit + 1 <= SGI_MAX_LEVEL_SUPER_SCAN then
-			SGI_DATA[SGI_DATA_INDEX].settings.highLimit = SGI_DATA[SGI_DATA_INDEX].settings.highLimit + 1
-			SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit)
-		elseif delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.highLimit > SGI_DATA[SGI_DATA_INDEX].settings.lowLimit then
-			SGI_DATA[SGI_DATA_INDEX].settings.highLimit = SGI_DATA[SGI_DATA_INDEX].settings.highLimit - 1
-			SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit)
-		end
-	end)
-
-	SGI_Options.limitText = SGI_Options.limitLow:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Options.limitText:SetPoint("BOTTOM",SGI_Options.limitLow,"TOP",16,3)
-	SGI_Options.limitText:SetText(SGI.L["Level limits"])
-
-	SGI_Options.raceLimitHigh = CreateFrame("Frame","SGI_RaceLimitHigh",SGI_Options)
-	SGI_Options.raceLimitHigh:SetWidth(40)
-	SGI_Options.raceLimitHigh:SetHeight(40)
-	SGI_Options.raceLimitHigh:SetPoint("CENTER",SGI_Options,"CENTER",150,80)
-	SGI_Options.raceLimitHigh.text = SGI_Options.raceLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_Options.raceLimitHigh.text:SetPoint("CENTER")
-	SGI_Options.raceLimitHigh.texture = SGI_Options.raceLimitHigh:CreateTexture()
-	SGI_Options.raceLimitHigh.texture:SetAllPoints()
-	SGI_Options.raceLimitHigh.texture:SetTexture(1,1,0,0.2)
-	SGI_Options.raceLimitHigh.texture:Hide()
-	SGI_Options.raceTooltip = CreateFrame("Frame","LimitTool",SGI_Options.raceLimitHigh,"GameTooltipTemplate")
-
-	SGI_Options.raceTooltip:SetPoint("TOP",SGI_Options.raceLimitHigh,"BOTTOM")
-	SGI_Options.raceTooltip.text = SGI_Options.raceTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Options.raceTooltip.text:SetPoint("LEFT",SGI_Options.raceTooltip,"LEFT",12,0)
-	SGI_Options.raceTooltip.text:SetJustifyH("LEFT")
-	SGI_Options.raceTooltip.text:SetText(SGI.L["The level you wish to start dividing the search by race"])
-	SGI_Options.raceTooltip.text:SetWidth(110)
-	SGI_Options.raceTooltip:SetWidth(125)
-	SGI_Options.raceTooltip:SetHeight(SGI_Options.raceTooltip.text:GetHeight() + 12)
-
-	SGI_Options.raceLimitText = SGI_Options.raceLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Options.raceLimitText:SetPoint("BOTTOM",SGI_Options.raceLimitHigh,"TOP",0,3)
-	SGI_Options.raceLimitText:SetText(SGI.L["Racefilter Start:"])
-
-	SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart)
-	SGI_Options.raceLimitHigh:SetScript("OnMouseWheel",function(self,delta)
-		if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.raceStart > 1 then
-			SGI_DATA[SGI_DATA_INDEX].settings.raceStart = SGI_DATA[SGI_DATA_INDEX].settings.raceStart - 1
-			SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart)
-		elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.raceStart < SGI_MAX_LEVEL_SUPER_SCAN + 1 then
-			SGI_DATA[SGI_DATA_INDEX].settings.raceStart = SGI_DATA[SGI_DATA_INDEX].settings.raceStart + 1
-			SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart)
-			if SGI_DATA[SGI_DATA_INDEX].settings.raceStart > SGI_MAX_LEVEL_SUPER_SCAN then
-				SGI_Options.raceLimitHigh.text:SetText(SGI.L["OFF"])
-			end
-		end
-	end)
-
-	SGI_Options.raceLimitHigh:SetScript("OnEnter",function()
-		SGI_Options.raceLimitHigh.texture:Show()
-		SGI_Options.raceTooltip:Show()
-	end)
-	SGI_Options.raceLimitHigh:SetScript("OnLeave",function()
-		SGI_Options.raceLimitHigh.texture:Hide()
-		SGI_Options.raceTooltip:Hide()
-	end)
-
-	SGI_Options.classLimitHigh = CreateFrame("Frame","SGI_ClassLimitHigh",SGI_Options)
-	SGI_Options.classLimitHigh:SetWidth(40)
-	SGI_Options.classLimitHigh:SetHeight(40)
-	SGI_Options.classLimitHigh:SetPoint("CENTER",SGI_Options,"CENTER",150,10)
-	SGI_Options.classLimitHigh.text = SGI_Options.classLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_Options.classLimitHigh.text:SetPoint("CENTER")
-	SGI_Options.classLimitHigh.texture = SGI_Options.classLimitHigh:CreateTexture()
-	SGI_Options.classLimitHigh.texture:SetAllPoints()
-	SGI_Options.classLimitHigh.texture:SetTexture(1,1,0,0.2)
-	SGI_Options.classLimitHigh.texture:Hide()
-	SGI_Options.classTooltip = CreateFrame("Frame","LimitTool",SGI_Options.classLimitHigh,"GameTooltipTemplate")
-
-	SGI_Options.classTooltip:SetPoint("TOP",SGI_Options.classLimitHigh,"BOTTOM")
-	SGI_Options.classTooltip.text = SGI_Options.classTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Options.classTooltip.text:SetPoint("LEFT",SGI_Options.classTooltip,"LEFT",12,0)
-	SGI_Options.classTooltip.text:SetJustifyH("LEFT")
-	SGI_Options.classTooltip.text:SetText(SGI.L["The level you wish to divide the search by class"])
-	SGI_Options.classTooltip.text:SetWidth(110)
-
-	SGI_Options.classTooltip:SetWidth(125)
-	SGI_Options.classTooltip:SetHeight(SGI_Options.classTooltip.text:GetHeight() + 12)
-
-	SGI_Options.classLimitText = SGI_Options.classLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Options.classLimitText:SetPoint("BOTTOM",SGI_Options.classLimitHigh,"TOP",0,3)
-	SGI_Options.classLimitText:SetText(SGI.L["Classfilter Start:"])
-
-	SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart)
-	SGI_Options.classLimitHigh:SetScript("OnMouseWheel",function(self,delta)
-		if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.classStart > 1 then
-			SGI_DATA[SGI_DATA_INDEX].settings.classStart = SGI_DATA[SGI_DATA_INDEX].settings.classStart - 1
-			SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart)
-		elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.classStart < SGI_MAX_LEVEL_SUPER_SCAN + 1 then
-			SGI_DATA[SGI_DATA_INDEX].settings.classStart = SGI_DATA[SGI_DATA_INDEX].settings.classStart + 1
-			SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart)
-			if SGI_DATA[SGI_DATA_INDEX].settings.classStart > SGI_MAX_LEVEL_SUPER_SCAN then
-				SGI_Options.classLimitHigh.text:SetText(SGI.L["OFF"])
-			end
-		end
-	end)
-
-	SGI_Options.classLimitHigh:SetScript("OnEnter",function()
-		SGI_Options.classLimitHigh.texture:Show()
-		SGI_Options.classTooltip:Show()
-	end)
-	SGI_Options.classLimitHigh:SetScript("OnLeave",function()
-		SGI_Options.classLimitHigh.texture:Hide()
-		SGI_Options.classTooltip:Hide()
-	end)
-
-	SGI_Options.Interval = CreateFrame("Frame","SGI_Interval",SGI_Options)
-	SGI_Options.Interval:SetWidth(40)
-	SGI_Options.Interval:SetHeight(40)
-	SGI_Options.Interval:SetPoint("CENTER",SGI_Options,"CENTER",40,10)
-	SGI_Options.Interval.text = SGI_Options.Interval:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-	SGI_Options.Interval.text:SetPoint("CENTER")
-	SGI_Options.Interval.texture = SGI_Options.Interval:CreateTexture()
-	SGI_Options.Interval.texture:SetAllPoints()
-	SGI_Options.Interval.texture:SetTexture(1,1,0,0.2)
-	SGI_Options.Interval.texture:Hide()
-	SGI_Options.intervalTooltip = CreateFrame("Frame","LimitTool",SGI_Options.Interval,"GameTooltipTemplate")
-
-	SGI_Options.intervalTooltip:SetPoint("TOP",SGI_Options.Interval,"BOTTOM")
-	SGI_Options.intervalTooltip.text = SGI_Options.intervalTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Options.intervalTooltip.text:SetPoint("LEFT",SGI_Options.intervalTooltip,"LEFT",12,0)
-	SGI_Options.intervalTooltip.text:SetJustifyH("LEFT")
-	SGI_Options.intervalTooltip.text:SetText(SGI.L["Amount of levels to search every 7 seconds (higher numbers increase the risk of capping the search results)"])
-	SGI_Options.intervalTooltip.text:SetWidth(130)
-	SGI_Options.intervalTooltip:SetHeight(120)
-	SGI_Options.intervalTooltip:SetWidth(135)
-	SGI_Options.intervalTooltip:SetHeight(SGI_Options.intervalTooltip.text:GetHeight() + 12)
-
-	SGI_Options.intervalText = SGI_Options.Interval:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	SGI_Options.intervalText:SetPoint("BOTTOM",SGI_Options.Interval,"TOP",0,3)
-	SGI_Options.intervalText:SetText(SGI.L["Interval:"])
-
-	SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval)
-	SGI_Options.Interval:SetScript("OnMouseWheel",function(self,delta)
-		if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.interval > 1 then
-			SGI_DATA[SGI_DATA_INDEX].settings.interval = SGI_DATA[SGI_DATA_INDEX].settings.interval - 1
-			SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval)
-		elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.interval < 30 then
-			SGI_DATA[SGI_DATA_INDEX].settings.interval = SGI_DATA[SGI_DATA_INDEX].settings.interval + 1
-			SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval)
-		end
-	end)
-
-	SGI_Options.Interval:SetScript("OnEnter",function()
-		SGI_Options.Interval.texture:Show()
-		SGI_Options.intervalTooltip:Show()
-	end)
-	SGI_Options.Interval:SetScript("OnLeave",function()
-		SGI_Options.Interval.texture:Hide()
-		SGI_Options.intervalTooltip:Hide()
-	end)
-
-	anchor = {
-		point = "BOTTOMLEFT",
-		relativePoint = "BOTTOMLEFT",
-		xOfs = 4,
-		yOfs = 4,
-	}
-	SGI_Options.superScanText = SGI_Options:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge");
-	SGI_Options.superScanText:SetPoint("BOTTOMLEFT", SGI_Options, "BOTTOMLEFT", 35, 10);
-	SGI_Options.superScanText:SetText("SuperScan");
-	SGI_Options.buttonPlayPause = CreateButton("SGI_SUPERSCAN_PLAYPAUSE2", SGI_Options, 40,30,"",anchor,SSBtn3_OnClick);
-	SGI_SUPERSCAN_PLAYPAUSE2:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up");
-	SGI_SUPERSCAN_PLAYPAUSE2:Hide();
-	SGI_Options.superScanText:Hide();
-
-	SGI_Options.nextUpdate = 0;
-	SGI_Options:SetScript("OnUpdate", function()
-		if (SGI_Options.nextUpdate < GetTime()) then
-
-			if SGI_DATA[SGI_DATA_INDEX].settings.classStart > SGI_MAX_LEVEL_SUPER_SCAN then
-				SGI_Options.classLimitHigh.text:SetText(SGI.L["OFF"])
-			end
-
-			if SGI_DATA[SGI_DATA_INDEX].settings.raceStart > SGI_MAX_LEVEL_SUPER_SCAN then
-				SGI_Options.raceLimitHigh.text:SetText(SGI.L["OFF"])
-			end
-
-			if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"]) then
-				SGI_SUPERSCAN_PLAYPAUSE2:Show();
-				SGI_Options.superScanText:Show();
-				if SuperScanFrame then SuperScanFrame:Hide() end;
-			else
-				SGI_SUPERSCAN_PLAYPAUSE2:Hide();
-				SGI_Options.superScanText:Hide();
-				if (SGI:IsScanning()) then
-					SGI:ShowSuperScanFrame();
-				end
-			end
-
-			if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ADV_SCAN"]) then
-				if (not SGI_Options.Interval:IsShown()) then
-					SGI_Options.Interval:Show();
-				end
-				if (not SGI_Options.classLimitHigh:IsShown()) then
-					SGI_Options.classLimitHigh:Show();
-				end
-				if (not SGI_Options.raceLimitHigh:IsShown()) then
-					SGI_Options.raceLimitHigh:Show();
-				end
-			else
-				SGI_Options.Interval:Hide();
-				SGI_Options.classLimitHigh:Hide();
-				SGI_Options.raceLimitHigh:Hide();
-			end
-
-			BUTTON_INVITE.label:SetText(format(SGI.L["Invite: %d"],SGI:GetNumQueued()));
-			BUTTON_KEYBIND.label:SetText(SGI.L["Set Keybind ("..(SGI_DATA[SGI_DATA_INDEX].keyBind and SGI_DATA[SGI_DATA_INDEX].keyBind or "NONE")..")"]);
-
-			if (SGI_DATA[SGI_DATA_INDEX].debug) then
-				SGI_Options.title:SetText("|cffff3300(DEBUG MODE) |rSuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options")
-			else
-				SGI_Options.title:SetText("SuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options")
-			end
-
-			if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_MINIMAP"]) then
-				SGI:ShowMinimapButton();
-			else
-				SGI:HideMinimapButton();
-			end
-
-			SGI_Options.nextUpdate = GetTime() + 1;
-		end
-	end)
-
-end
-
-function SGI:ShowOptions()
-	if (not SGI_Options) then
-		CreateOptions();
-	end
-	SGI_Options:Show();
-end
-
-function SGI:HideOptions()
-	if (SGI_Options) then
-		SGI_Options:Hide();
-	end
-end
-
-
-local function CreateMinimapButton()
-	local f = CreateFrame("Button","SGI_MiniMapButton",Minimap)
-	f:SetWidth(32)
-	f:SetHeight(32)
-	f:SetFrameStrata("MEDIUM")
-	f:SetMovable(true)
-	SetFramePosition(f)
-
-	f:SetNormalTexture("Interface\\AddOns\\SuperGuildInviteReborn\\media\\SGI_MiniMapButton")
-	f:SetPushedTexture("Interface\\AddOns\\SuperGuildInviteReborn\\media\\SGI_MiniMapButtonPushed")
-	f:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
-
-	local tooltip = CreateFrame("Frame","SGI_TooltTipMini",f,"GameTooltipTemplate")
-	tooltip:SetPoint("BOTTOMRIGHT",f,"TOPLEFT",0,-3)
-	local toolstring = tooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
-	toolstring:SetPoint("TOPLEFT",tooltip,"TOPLEFT",5,-7)
-
-	local toolstring2 = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	local toolstring3 = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal");
-	toolstring2:SetPoint("TOPLEFT",tooltip,"TOPLEFT",7,-33);
-	toolstring3:SetPoint("TOPLEFT", tooltip, "TOPLEFT", 7, -46);
-	toolstring2:SetText(format("ETR: %s",SGI:GetSuperScanTimeLeft()));
-	toolstring3:SetText(format("%d%% done",floor(SGI:GetPercentageDone())));
-
-	local tUpdate = 0;
-	local function UpdateTooltip()
-		if (tUpdate < GetTime()) then
-			toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: %d|r",SGI:GetNumQueued()))
-			toolstring2:SetText(format("ETR: %s",SGI:GetSuperScanTimeLeft()));
-			toolstring3:SetText(format("%d%% done",floor(SGI:GetPercentageDone())));
-			--SGI:debug(format("ETR: %s",SGI:GetSuperScanETR()));
-			--SGI:debug(format("%d%% done",floor(SGI:GetPercentageDone())));
-			tUpdate = GetTime() + 0.2;
-		end
-	end
-
-	toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: |r|cffffff00%d|r",SGI:GetNumQueued()))
-	toolstring:SetJustifyH("LEFT");
-	tooltip:SetWidth(max(toolstring:GetWidth(),toolstring2:GetWidth(),toolstring3:GetWidth())+ 20)
-	tooltip:SetHeight(toolstring:GetHeight() + toolstring2:GetHeight() + toolstring3:GetHeight() + 15)
-	tooltip:Hide()
-	f:SetScript("OnEnter",function()
-		toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: %d|r",SGI:GetNumQueued()))
-		tooltip:Show()
-		tooltip:SetScript("OnUpdate",UpdateTooltip);
-	end)
-	f:SetScript("OnLeave",function()
-		tooltip:Hide()
-		tooltip:SetScript("OnUpdate", nil);
-	end)
-
-
-	local function moveButton(self)
-		local centerX, centerY = Minimap:GetCenter()
-		local x, y = GetCursorPosition()
-		x, y = x / self:GetEffectiveScale() - centerX, y / self:GetEffectiveScale() - centerY
-		centerX, centerY = math.abs(x), math.abs(y)
-		centerX, centerY = (centerX / math.sqrt(centerX^2 + centerY^2)) * 85, (centerY / sqrt(centerX^2 + centerY^2)) * 85
-		centerX = x < 0 and -centerX or centerX
-		centerY = y < 0 and -centerY or centerY
-		self:ClearAllPoints()
-		self:SetPoint("CENTER", centerX, centerY)
-	end
-
-	f:SetScript("OnMouseDown",function(self,button)
-		if button == "RightButton" then
-			self:SetScript("OnUpdate",moveButton)
-		end
-	end)
-	f:SetScript("OnMouseUp",function(self,button)
-		self:SetScript("OnUpdate",nil)
-		SaveFramePosition(self)
-	end)
-	f:SetScript("OnClick",function(self,button)
-		if SGI_Options and SGI_Options:IsShown() then
-			SGI:HideOptions()
-		else
-			SGI:ShowOptions()
-		end
-	end)
-end
-
-function SGI:ShowMinimapButton()
-	if (not SGI_MiniMapButton) then
-		CreateMinimapButton();
-	end
-	SGI_MiniMapButton:Show();
-end
-
-function SGI:HideMinimapButton()
-	if (SGI_MiniMapButton) then
-		SGI_MiniMapButton:Hide();
-	end
-end
-
-
-
-
-
-
-
-
-SGI:debug(">> GUI.lua");
+
+local function onClickTester(self)
+	if self then
+		SGI:print("Click on "..self:GetName());
+	end
+end
+
+local function CreateButton(name, parent, width, height, label, anchor, onClick)
+	local f = CreateFrame("Button", name, parent, "UIPanelButtonTemplate");
+	f:SetWidth(width);
+	f:SetHeight(height);
+	f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall");
+	f.label:SetText(label);
+	f.label:SetPoint("CENTER");
+	f:SetWidth(width - 10);
+
+	if (type(anchor) == "table") then
+		f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs);
+	end
+
+	f:SetScript("OnClick", onClick);
+	return f;
+end
+
+local function CreateCheckbox(name, parent, label, anchor)
+	local f = CreateFrame("CheckButton", name, parent, "ChatConfigCheckButtonTemplate");   --ChatConfigCheckButtonTemplate     OptionsBaseCheckButtonTemplate
+	f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	f.label:SetText(label);
+	f.label:SetPoint("LEFT", f, "RIGHT", 5, 1);
+
+	if (type(anchor) == "table") then
+		f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs);
+	end
+
+	f:HookScript("OnClick", function(self)
+		SGI_DATA[SGI_DATA_INDEX].settings.checkBox[name] = self:GetChecked()
+	end)
+	if SGI_DATA[SGI_DATA_INDEX].settings.checkBox[name] then
+		f:SetChecked()
+	end
+	return f;
+end
+
+local function CreateDropDown(name, parent, label, items, anchor)
+	local f = CreateFrame("Button", name, parent, "UIDropDownMenuTemplate");
+	f:ClearAllPoints();
+	f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs)
+	f:Show()
+
+	f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	f.label:SetPoint("BOTTOMLEFT", f, "TOPLEFT", 20, 5);
+	f.label:SetText(label);
+
+	local function OnClick(self)
+		UIDropDownMenu_SetSelectedID(f, self:GetID());
+		SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] = self:GetID();
+	end
+
+	local function initialize(self, level)
+		local info = UIDropDownMenu_CreateInfo();
+		for k,v in pairs(items) do
+			info = UIDropDownMenu_CreateInfo();
+			info.text = v;
+			info.value = v;
+			info.func = OnClick;
+			UIDropDownMenu_AddButton(info, level);
+		end
+	end
+
+	UIDropDownMenu_Initialize(f, initialize)
+	UIDropDownMenu_SetWidth(f, 100);
+	UIDropDownMenu_SetButtonWidth(f, 124)
+	SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] = SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] or 1
+	UIDropDownMenu_SetSelectedID(f, SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] or 1)
+	UIDropDownMenu_JustifyText(f, "LEFT")
+	return f
+end
+
+local function SetFramePosition(frame)
+	if (type(SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()]) ~= "table") then
+		if (frame:GetName() == "SGI_MiniMapButton") then
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = "CENTER", relativePoint = "CENTER", xOfs = -31, yOfs = -31};
+		else
+			frame:SetPoint("CENTER");
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = "CENTER", relativePoint = "CENTER", xOfs = 0, yOfs = 0};
+			return;
+		end
+	end
+	if (frame:GetName() == "SGI_MiniMapButton") then
+		frame:SetPoint(
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].point,
+			Minimap,
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].relativePoint,
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].xOfs,
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].yOfs
+		);
+	else
+		frame:SetPoint(
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].point,
+			UIParent,
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].relativePoint,
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].xOfs,
+			SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].yOfs
+		);
+	end
+end
+
+local function SaveFramePosition(frame)
+	if (type(SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()]) ~= "table") then
+		SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {};
+	end
+	local point, parent, relativePoint, xOfs, yOfs = frame:GetPoint();
+	SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = point, relativePoint = relativePoint, xOfs = xOfs, yOfs = yOfs};
+end
+
+
+local function CreateInviteListFrame()
+	CreateFrame("Frame","SGI_Invites")
+	local SGI_QUEUE = SGI:GetInviteQueue();
+	SGI_Invites:SetWidth(370)
+	SGI_Invites:SetHeight(20*SGI:CountTable(SGI_QUEUE) + 40)
+	SGI_Invites:SetMovable(true)
+	SetFramePosition(SGI_Invites)
+	SGI_Invites:SetScript("OnMouseDown",function(self)
+		self:StartMoving()
+	end)
+	SGI_Invites:SetScript("OnMouseUp",function(self)
+		self:StopMovingOrSizing()
+		SaveFramePosition(SGI_Invites)
+	end)
+	local backdrop =
+	{
+		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+		tile = true,
+		tileSize = 16,
+		edgeSize = 16,
+		insets = { left = 4, right = 4, top = 4, bottom = 4 }
+	}
+	SGI_Invites:SetBackdrop(backdrop)
+
+	SGI_Invites.text = SGI_Invites:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Invites.text:SetPoint("TOP",SGI_Invites,"TOP",-15,-15)
+	SGI_Invites.text:SetText(SGI.L["Click on the players you wish to invite"])
+	SGI_Invites.tooltip = CreateFrame("Frame","InviteTime",SGI_Invites,"GameTooltipTemplate")
+
+		--SGI_Invites.tooltip:SetOwner( WorldFrame, "ANCHOR_NONE" );
+
+
+	SGI_Invites.tooltip.text = SGI_Invites.tooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Invites.tooltip:SetPoint("TOP",SGI_Invites,"BOTTOM",0,-2)
+	SGI_Invites.tooltip.text:SetText("Unknown")
+	SGI_Invites.tooltip.text:SetPoint("CENTER")
+
+	local close = CreateFrame("Button",nil,SGI_Invites,"UIPanelCloseButton")
+	close:SetPoint("TOPRIGHT",SGI_Invites,"TOPRIGHT",-4,-4)
+
+	SGI_Invites.items = {}
+	local update = 0
+	local toolUpdate = 0
+	SGI_Invites:SetScript("OnUpdate",function()
+		if (not SGI_Invites:IsShown() or GetTime() < update) then return end
+
+		SGI_QUEUE = SGI:GetInviteQueue();
+
+		for k,_ in pairs(SGI_Invites.items) do
+			SGI_Invites.items[k]:Hide()
+		end
+
+		local i = 0
+		local x,y = 10,-30
+		for i = 1,30 do
+			if not SGI_Invites.items[i] then
+				SGI_Invites.items[i] = CreateFrame("Button","InviteBar"..i,SGI_Invites)
+				SGI_Invites.items[i]:SetWidth(350)
+				SGI_Invites.items[i]:SetHeight(20)
+				SGI_Invites.items[i]:EnableMouse(true)
+				SGI_Invites.items[i]:SetPoint("TOP",SGI_Invites,"TOP",0,y)
+				SGI_Invites.items[i].text = SGI_Invites.items[i]:CreateFontString(nil,"OVERLAY","GameFontNormal")
+				SGI_Invites.items[i].text:SetPoint("LEFT",SGI_Invites.items[i],"LEFT",3,0)
+				SGI_Invites.items[i].text:SetJustifyH("LEFT")
+				SGI_Invites.items[i].text:SetWidth(SGI_Invites.items[i]:GetWidth()-10);
+				SGI_Invites.items[i].player = "unknown"
+				SGI_Invites.items[i]:RegisterForClicks("LeftButtonDown","RightButtonDown")
+				SGI_Invites.items[i]:SetScript("OnClick",SGI.SendGuildInvite)
+
+				SGI_Invites.items[i].highlight = SGI_Invites.items[i]:CreateTexture()
+				SGI_Invites.items[i].highlight:SetAllPoints()
+				SGI_Invites.items[i].highlight:SetTexture(1,1,0,0.2)
+				SGI_Invites.items[i].highlight:Hide()
+
+				SGI_Invites.items[i]:SetScript("OnEnter",function()
+					SGI_Invites.items[i].highlight:Show()
+					SGI_Invites.tooltip:Show()
+					SGI_Invites.items[i]:SetScript("OnUpdate",function()
+						if GetTime() > toolUpdate and SGI_QUEUE[SGI_Invites.items[i].player] then
+							SGI_Invites.tooltip.text:SetText("Found |cff"..SGI:GetClassColor(SGI_QUEUE[SGI_Invites.items[i].player].classFile)..SGI_Invites.items[i].player.."|r "..SGI:FormatTime(floor(GetTime()-SGI_QUEUE[SGI_Invites.items[i].player].found)).." ago")
+							local h,w = SGI_Invites.tooltip.text:GetHeight(),SGI_Invites.tooltip.text:GetWidth()
+							SGI_Invites.tooltip:SetWidth(w+20)
+							SGI_Invites.tooltip:SetHeight(h+20)
+							toolUpdate = GetTime() + 0.1
+						end
+					end)
+				end)
+				SGI_Invites.items[i]:SetScript("OnLeave",function()
+					SGI_Invites.items[i].highlight:Hide()
+					SGI_Invites.tooltip:Hide()
+					SGI_Invites.items[i]:SetScript("OnUpdate",nil)
+				end)
+			end
+			y = y - 20
+		end
+		i = 0
+		for k,_ in pairs(SGI_QUEUE) do
+			i = i + 1
+			local level,classFile,race,class,found = SGI_QUEUE[k].level, SGI_QUEUE[k].classFile, SGI_QUEUE[k].race, SGI_QUEUE[k].class, SGI_QUEUE[k].found
+			local Text = i..". |cff"..SGI:GetClassColor(classFile)..k.."|r Lvl "..level.." "..race.." |cff"..SGI:GetClassColor(classFile)..class.."|r"
+			SGI_Invites.items[i].text:SetText(Text)
+			SGI_Invites.items[i].player = k
+			SGI_Invites.items[i]:Show()
+			if i >= 30 then break end
+		end
+		SGI_Invites:SetHeight(i * 20 + 40)
+		update = GetTime() + 0.5
+	end)
+end
+
+
+function SGI:ShowInviteList()
+	if (not SGI_Invites) then
+		CreateInviteListFrame();
+	end
+	SGI_Invites:Show();
+end
+
+function SGI:HideInviteList()
+	if (SGI_Invites) then
+		SGI_Invites:Hide();
+	end
+end
+
+
+local function SSBtn3_OnClick(self)
+	if (SGI:IsScanning()) then
+		SGI:StopSuperScan();
+		self:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up");
+	else
+		SGI:StartSuperScan();
+		self:SetNormalTexture("Interface\\TimeManager\\PauseButton");
+		SGI:ShowInviteList();
+	end
+end
+
+function SGI:CreateSmallSuperScanFrame()
+	CreateFrame("Frame", "SuperScanFrame");
+	SuperScanFrame:SetWidth(130);
+	SuperScanFrame:SetHeight(30);
+	local backdrop =
+	{
+		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+		tile = true,
+		tileSize = 16,
+		edgeSize = 16,
+		insets = { left = 4, right = 4, top = 4, bottom = 4 }
+	}
+	SetFramePosition(SuperScanFrame)
+	SuperScanFrame:SetMovable(true)
+	SuperScanFrame:SetScript("OnMouseDown",function(self)
+		self:StartMoving()
+	end)
+	SuperScanFrame:SetScript("OnMouseUp",function(self)
+		self:StopMovingOrSizing()
+		SaveFramePosition(self)
+	end)
+	SuperScanFrame:SetBackdrop(backdrop)
+
+	local close = CreateFrame("Button",nil,SuperScanFrame,"UIPanelCloseButton")
+	close:SetPoint("LEFT",SuperScanFrame,"RIGHT",-5,0)
+
+	SuperScanFrame.time = SuperScanFrame:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SuperScanFrame.time:SetPoint("CENTER")
+	--SuperScanFrame.time:SetText(format("|cff00ff00%d%%|r|cffffff00 %s|r    ",0,SGI:GetSuperScanETR()))
+
+	SuperScanFrame.progressTexture = SuperScanFrame:CreateTexture();
+	SuperScanFrame.progressTexture:SetPoint("LEFT", 5, 0);
+	SuperScanFrame.progressTexture:SetHeight(18);
+	SuperScanFrame.progressTexture:SetWidth(140);
+--	SuperScanFrame.progressTexture:SetTexture(1,0.5,0,0.4);
+	SuperScanFrame.progressTexture:SetTexture(0,0.0,0,0.0);
+	local anchor = {
+		point = "TOPLEFT",
+		relativePoint = "BOTTOMLEFT",
+		xOfs = 0,
+		yOfs = 0,
+	}
+
+	SuperScanFrame.button1 = CreateButton("SGI_INVITE_BUTTON2", SuperScanFrame, 70, 30, format("",SGI:GetNumQueued()), anchor, SGI.SendGuildInvite)
+		anchor.xOfs = 85;
+	SuperScanFrame.button2 = CreateButton("SGI_PURGE_QUEUE", SuperScanFrame, 55, 30, "Purge", anchor, SGI.PurgeQueue);
+		anchor.xOfs = 57;
+	SuperScanFrame.button2 = CreateButton("SGI_SUPERSCAN_PLAYPAUSE", SuperScanFrame, 40,30,"",anchor,SSBtn3_OnClick);
+	SGI_SUPERSCAN_PLAYPAUSE:SetNormalTexture("Interface\\TimeManager\\PauseButton");
+
+	SuperScanFrame.nextUpdate = 0;
+	SuperScanFrame:SetScript("OnUpdate", function()
+		if (SuperScanFrame.nextUpdate < GetTime()) then
+
+			SuperScanFrame.button1.label:SetText(format("Invite: %d",SGI:GetNumQueued()));
+
+			if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then
+				local remainingTime = SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR);
+				local totalScanTime = SGI:GetTotalScanTime();
+				local percentageDone = (totalScanTime - remainingTime) / totalScanTime;
+				SuperScanFrame.time:SetText(format("|cff00ff00%d%%|r|cffffff00 %s|r",100*(percentageDone > 1 and 1 or percentageDone),SGI:FormatTime(remainingTime)))
+				SuperScanFrame.progressTexture:SetWidth(120 * (percentageDone > 1 and 1 or percentageDone));
+			end
+
+			SuperScanFrame.nextUpdate = GetTime() + 0.2;
+		end
+	end)
+
+
+	SuperScanFrame:Hide();
+	-- Interface\Buttons\UI-SpellbookIcon-NextPage-Up
+	-- Interface\TimeManager\PauseButton
+end
+
+function SGI:GetPercentageDone()
+	if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then
+		local remainingTime = SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR);
+		local totalScanTime = SGI:GetTotalScanTime();
+		local percentageDone = (totalScanTime - remainingTime) / totalScanTime;
+		return percentageDone * 100;
+	end
+	return 0;
+end
+
+function SGI:GetSuperScanTimeLeft()
+	if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then
+		return SGI:FormatTime(SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR));
+	end
+	return 0;
+end
+
+
+function SGI:ShowSuperScanFrame()
+	if (SuperScanFrame and not (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"])) then
+		SuperScanFrame:Show();
+	else
+		if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"]) then
+			SGI:CreateSmallSuperScanFrame();
+			SuperScanFrame:Hide();
+			return;
+		else
+			SGI:CreateSmallSuperScanFrame();
+			SuperScanFrame:Show();
+		end
+
+	end
+end
+
+function SGI:HideSuperScanFrame()
+	if (SuperScanFrame) then
+		SuperScanFrame:Hide();
+	end
+end
+
+local function CreateWhisperDefineFrame()
+
+end
+
+
+
+
+--local KeyHarvestFrame = CreateFrame("Frame", "SGI_KeyHarvestFrame");
+--KeyHarvestFrame:SetPoint("CENTER",0,200);
+--KeyHarvestFrame:SetWidth(10);
+--KeyHarvestFrame:SetHeight(10);
+--KeyHarvestFrame.text = KeyHarvestFrame:CreateFontString(nil, "OVERLAY", "MovieSubtitleFont");
+--KeyHarvestFrame.text:SetPoint("CENTER");
+--KeyHarvestFrame.text:SetText("|cff00ff00Press the KEY you wish to bind now!|r");
+--KeyHarvestFrame:Hide();
+
+--function KeyHarvestFrame:GetNewKeybindKey()
+--	KeyHarvestFrame:Show();
+--	self:SetScript("OnKeyDown", function(self, key)
+--		if (SetBindingClick(key, "SGI_INVITE_BUTTON2")) then
+--			Alerter:SendAlert("|cff00ff00Successfully bound "..key.." to InviteButton!|r",1.5);
+--			SGI:print("Successfully bound "..key.." to InviteButton!");
+--			SGI_DATA[SGI_DATA_INDEX].keyBind = key;
+--			BUTTON_KEYBIND.label:SetText("Set Keybind ("..key..")");
+--		else
+--			Alerter:SendAlert("|cffff0000Error binding "..key.." to InviteButton!|r",1.5);
+--			SGI:print("Error binding "..key.." to InviteButton!");
+--		end
+--		self:EnableKeyboard(false);
+--		KeyHarvestFrame:Hide();
+--	end)
+--	self:EnableKeyboard(true);
+--
+--end
+
+local function CreateWhisperDefineFrame()
+	CreateFrame("Frame","SGI_Whisper")
+	local backdrop =
+	{
+		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+		tile = true,
+		tileSize = 16,
+		edgeSize = 16,
+		insets = { left = 4, right = 4, top = 4, bottom = 4 }
+	}
+	SGI_Whisper:SetWidth(500)
+	SGI_Whisper:SetHeight(365)
+	SGI_Whisper:SetBackdrop(backdrop)
+	SetFramePosition(SGI_Whisper)
+	SGI_Whisper:SetMovable(true)
+	SGI_Whisper:SetScript("OnMouseDown",function(self)
+		self:StartMoving()
+	end)
+	SGI_Whisper:SetScript("OnMouseUp",function(self)
+		self:StopMovingOrSizing()
+		SaveFramePosition(SGI_Whisper)
+	end)
+
+	local close = CreateFrame("Button",nil,SGI_Whisper,"UIPanelCloseButton")
+	close:SetPoint("TOPRIGHT",SGI_Whisper,"TOPRIGHT",-4,-4)
+
+	SGI_Whisper.title = SGI_Whisper:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_Whisper.title:SetText(SGI.L["SuperGuildInvite Custom Whisper"])
+	SGI_Whisper.title:SetPoint("TOP",SGI_Whisper,"TOP",0,-20)
+
+	SGI_Whisper.info = SGI_Whisper:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Whisper.info:SetPoint("TOPLEFT",SGI_Whisper,"TOPLEFT",33,-55)
+	SGI_Whisper.info:SetText(SGI.L["WhisperInstructions"])
+	SGI_Whisper.info:SetWidth(450)
+	SGI_Whisper.info:SetJustifyH("LEFT")
+
+	SGI_Whisper.edit = CreateFrame("EditBox",nil,SGI_Whisper)
+	SGI_Whisper.edit:SetWidth(450)
+	SGI_Whisper.edit:SetHeight(65)
+	SGI_Whisper.edit:SetMultiLine(true)
+	SGI_Whisper.edit:SetPoint("TOPLEFT",SGI_Whisper,"TOPLEFT",35,-110)
+	SGI_Whisper.edit:SetFontObject("GameFontNormal")
+	SGI_Whisper.edit:SetTextInsets(10,10,10,10)
+	SGI_Whisper.edit:SetMaxLetters(256)
+	SGI_Whisper.edit:SetBackdrop(backdrop)
+	SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "")
+	SGI_Whisper.edit:SetScript("OnHide",function()
+		SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "")
+	end)
+	SGI_Whisper.edit.text = SGI_Whisper.edit:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Whisper.edit.text:SetPoint("TOPLEFT",SGI_Whisper.edit,"TOPLEFT",10,13)
+	SGI_Whisper.edit.text:SetText(SGI.L["Enter your whisper"])
+
+	local yOfs = -20
+	SGI_Whisper.status = {}
+	for i = 1,6 do
+		SGI_Whisper.status[i] = {}
+		SGI_Whisper.status[i].box = CreateFrame("Frame",nil,SGI_Whisper)
+		SGI_Whisper.status[i].box:SetWidth(170)
+		SGI_Whisper.status[i].box:SetHeight(18)
+		SGI_Whisper.status[i].box:SetFrameStrata("HIGH")
+		SGI_Whisper.status[i].box.index = i
+		SGI_Whisper.status[i].box:SetPoint("LEFT",SGI_Whisper,"CENTER",50,yOfs)
+		SGI_Whisper.status[i].box:SetScript("OnEnter",function(self)
+			if SGI_DATA[SGI_DATA_INDEX].settings.whispers[self.index] then
+				GameTooltip:SetOwner(self,"ANCHOR_CURSOR")
+				GameTooltip:SetText(SGI:FormatWhisper(SGI_DATA[SGI_DATA_INDEX].settings.whispers[self.index],UnitName("Player")))
+			end
+		end)
+		SGI_Whisper.status[i].box:SetScript("OnLeave",function(self)
+			GameTooltip:Hide()
+		end)
+		SGI_Whisper.status[i].text = SGI_Whisper:CreateFontString(nil,nil,"GameFontNormal")
+		SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: ")
+		SGI_Whisper.status[i].text:SetWidth(200)
+		SGI_Whisper.status[i].text:SetJustifyH("LEFT")
+		SGI_Whisper.status[i].text:SetPoint("LEFT",SGI_Whisper,"CENTER",50,yOfs)
+		yOfs = yOfs - 18
+	end
+	local whispers = {
+		"Whisper #1",
+		"Whisper #2",
+		"Whisper #3",
+		"Whisper #4",
+		"Whisper #5",
+		"Whisper #6",
+	}
+
+	anchor = {}
+		anchor.point = "BOTTOMLEFT"
+		anchor.relativePoint = "BOTTOMLEFT"
+		anchor.xOfs = 50
+		anchor.yOfs = 120
+
+	--CreateDropDown(name, parent, label, items, anchor)
+	SGI_Whisper.drop = CreateDropDown("SGI_WHISPER_DROP",SGI_Whisper,SGI.L["Select whisper"],whispers,anchor)
+
+		anchor.xOfs = 100
+		anchor.yOfs = 20
+	--CreateButton(name, parent, width, height, label, anchor, onClick)
+	CreateButton("SGI_SAVEWHISPER",SGI_Whisper,120,30,SGI.L["Save"],anchor,function()
+		local text = SGI_Whisper.edit:GetText()
+		local ID = SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"]
+		SGI_DATA[SGI_DATA_INDEX].settings.whispers[ID] = text
+		SGI_Whisper.edit:SetText("")
+	end)
+	anchor.xOfs = 280
+	CreateButton("SGI_CANCELWHISPER",SGI_Whisper,120,30,SGI.L["Cancel"],anchor,function()
+		SGI_Whisper:Hide()
+	end)
+
+	SGI_Whisper.update = 0
+	SGI_Whisper.changed = false
+	SGI_Whisper:SetScript("OnUpdate",function()
+		if GetTime() > SGI_Whisper.update then
+			for i = 1,6 do
+				if type(SGI_DATA[SGI_DATA_INDEX].settings.whispers[i]) == "string" then
+					SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: |cff00ff00Good|r")
+				else
+					SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: |cffff0000Undefined|r")
+				end
+			end
+			local ID = SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"]
+			SGI_Whisper.status[ID].text:SetText("Whisper #"..ID.." status: |cffff8800Editing...|r")
+
+			if ID ~= SGI_Whisper.changed then
+				SGI_Whisper.changed = ID
+				SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "")
+			end
+
+			SGI_Whisper.update = GetTime() + 0.5
+		end
+	end)
+
+	SGI_Whisper:HookScript("OnHide", function() if (SGI_Options.showAgain) then SGI:ShowOptions() SGI_Options.showAgain = false end end)
+end
+
+local function ShowWhisperFrame()
+	if SGI_Whisper then
+		SGI_Whisper:Show()
+	else
+		CreateWhisperDefineFrame()
+		SGI_Whisper:Show()
+	end
+end
+
+local function HideWhisperFrame()
+	if SGI_Whisper then
+		SGI_Whisper:Hide()
+	end
+end
+
+local function CreateFilterFrame()
+	CreateFrame("Frame","SGI_Filters")
+	SGI_Filters:SetWidth(550)
+	SGI_Filters:SetHeight(380)
+	SetFramePosition(SGI_Filters)
+	SGI_Filters:SetMovable(true)
+	SGI_Filters:SetScript("OnMouseDown",function(self)
+		self:StartMoving()
+	end)
+	SGI_Filters:SetScript("OnMouseUp",function(self)
+		self:StopMovingOrSizing()
+		SaveFramePosition(SGI_Filters)
+	end)
+	local backdrop =
+	{
+		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+		tile = true,
+		tileSize = 16,
+		edgeSize = 16,
+		insets = { left = 4, right = 4, top = 4, bottom = 4 }
+	}
+	SGI_Filters:SetBackdrop(backdrop)
+	local close = CreateFrame("Button",nil,SGI_Filters,"UIPanelCloseButton")
+	close:SetPoint("TOPRIGHT",SGI_Filters,"TOPRIGHT",-4,-4)
+
+	SGI_Filters.title = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge");
+	SGI_Filters.title:SetPoint("TOP", SGI_Filters, "TOP", 0, -15);
+	SGI_Filters.title:SetText("Edit filters");
+	SGI_Filters.underTitle = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_Filters.underTitle:SetPoint("TOP", SGI_Filters, "TOP", 0, -38);
+	SGI_Filters.underTitle:SetText("|cffff3300Any textbox left empty, except \"Filter name\" will be excluded from the filter|r");
+	SGI_Filters.underTitle:SetWidth(400);
+	SGI_Filters.bottomText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFOntNormal");
+	SGI_Filters.bottomText:SetPoint("BOTTOM", SGI_Filters, "BOTTOM", 0, 60);
+	SGI_Filters.bottomText:SetText("|cff00ff00In order to be filtered, a player has to match |r|cffFF3300ALL|r |cff00ff00criterias|r");
+
+	SGI_Filters.tooltip = CreateFrame("Frame", "FilterTooltip", SGI_Filters.tooltip, "GameTooltipTemplate");
+
+
+
+
+	SGI_Filters.tooltip:SetWidth(150);
+	SGI_Filters.tooltip.text = SGI_Filters.tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_Filters.tooltip.text:SetPoint("CENTER", SGI_Filters.tooltip, "CENTER", 0, 0);
+	SGI_Filters.tooltip.text:SetJustifyH("LEFT");
+
+	SGI_Filters.editBoxName = CreateFrame("EditBox", "SGI_EditBoxName", SGI_Filters);
+	SGI_Filters.editBoxName:SetWidth(150);
+	SGI_Filters.editBoxName:SetHeight(30);
+	SGI_Filters.editBoxName:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -90);
+	SGI_Filters.editBoxName:SetFontObject("GameFontNormal");
+	SGI_Filters.editBoxName:SetMaxLetters(65);
+	SGI_Filters.editBoxName:SetBackdrop(backdrop);
+	SGI_Filters.editBoxName:SetText("");
+	SGI_Filters.editBoxName:SetTextInsets(10,10,10,10);
+	SGI_Filters.editBoxName:SetScript("OnHide",function(self)
+		self:SetText("");
+	end)
+	SGI_Filters.editBoxName.title = SGI_Filters.editBoxName:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_Filters.editBoxName.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxName,"TOPLEFT", 0, 5);
+	SGI_Filters.editBoxName.title:SetText("Filter name");
+
+	SGI_Filters.editBoxNameFilter = CreateFrame("EditBox", "SGI_EditBoxNameFilter", SGI_Filters);
+	SGI_Filters.editBoxNameFilter:SetWidth(150);
+	SGI_Filters.editBoxNameFilter:SetHeight(30);
+	SGI_Filters.editBoxNameFilter:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -150);
+	SGI_Filters.editBoxNameFilter:SetFontObject("GameFontNormal");
+	SGI_Filters.editBoxNameFilter:SetMaxLetters(65);
+	SGI_Filters.editBoxNameFilter:SetBackdrop(backdrop);
+	SGI_Filters.editBoxNameFilter:SetText("");
+	SGI_Filters.editBoxNameFilter:SetTextInsets(10,10,10,10);
+	SGI_Filters.editBoxNameFilter:SetScript("OnHide",function(self)
+		self:SetText("");
+	end)
+	SGI_Filters.editBoxNameFilter:SetScript("OnEnter", function(self)
+		SGI_Filters.tooltip.text:SetText(SGI.L["Enter a phrase which you wish to include in the filter. If a player's name contains the phrase, they will not be queued"]);
+		SGI_Filters.tooltip.text:SetWidth(135);
+		SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12);
+		SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5);
+		SGI_Filters.tooltip:Show();
+	end)
+	SGI_Filters.editBoxNameFilter:SetScript("OnLeave", function()
+		SGI_Filters.tooltip:Hide()
+	end)
+
+	SGI_Filters.editBoxNameFilter.title = SGI_Filters.editBoxNameFilter:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_Filters.editBoxNameFilter.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxNameFilter,"TOPLEFT", 0, 5);
+	SGI_Filters.editBoxNameFilter.title:SetText("Name exceptions");
+
+	SGI_Filters.editBoxLvl = CreateFrame("EditBox", "SGI_EditBoxLvl", SGI_Filters);
+	SGI_Filters.editBoxLvl:SetWidth(150);
+	SGI_Filters.editBoxLvl:SetHeight(30);
+	SGI_Filters.editBoxLvl:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -210);
+	SGI_Filters.editBoxLvl:SetFontObject("GameFontNormal");
+	SGI_Filters.editBoxLvl:SetMaxLetters(65);
+	SGI_Filters.editBoxLvl:SetBackdrop(backdrop);
+	SGI_Filters.editBoxLvl:SetText("");
+	SGI_Filters.editBoxLvl:SetTextInsets(10,10,10,10);
+	SGI_Filters.editBoxLvl:SetScript("OnHide",function(self)
+		self:SetText("");
+	end)
+	SGI_Filters.editBoxLvl:SetScript("OnEnter", function(self)
+		SGI_Filters.tooltip.text:SetText(SGI.L["Enter the level range for the filter. \n\nExample: |cff00ff0055|r:|cff00A2FF58|r \n\nThis would result in only matching players that range from level |cff00ff0055|r to |cff00A2FF58|r (inclusive)"]);
+		SGI_Filters.tooltip.text:SetWidth(135);
+		SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12);
+		SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5);
+		SGI_Filters.tooltip:Show();
+	end)
+	SGI_Filters.editBoxLvl:SetScript("OnLeave", function()
+		SGI_Filters.tooltip:Hide()
+	end)
+
+	SGI_Filters.editBoxLvl.title = SGI_Filters.editBoxLvl:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_Filters.editBoxLvl.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxLvl,"TOPLEFT", 0, 5);
+	SGI_Filters.editBoxLvl.title:SetText("Level range (Min:Max)");
+
+	SGI_Filters.editBoxVC = CreateFrame("EditBox", "SGI_EditBoxVC", SGI_Filters);
+	SGI_Filters.editBoxVC:SetWidth(150);
+	SGI_Filters.editBoxVC:SetHeight(30);
+	SGI_Filters.editBoxVC:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -270);
+	SGI_Filters.editBoxVC:SetFontObject("GameFontNormal");
+	SGI_Filters.editBoxVC:SetMaxLetters(65);
+	SGI_Filters.editBoxVC:SetBackdrop(backdrop);
+	SGI_Filters.editBoxVC:SetText("");
+	SGI_Filters.editBoxVC:SetTextInsets(10,10,10,10);
+	SGI_Filters.editBoxVC:SetScript("OnHide",function(self)
+		self:SetText("");
+	end)
+
+	SGI_Filters.editBoxVC:SetScript("OnEnter", function(self)
+		SGI_Filters.tooltip.text:SetText(SGI.L["Enter the maximum amount of consecutive vowels and consonants a player's name can contain.\n\nExample: |cff00ff003|r:|cff00A2FF5|r\n\nThis would cause players with more than |cff00ff003|r vowels in a row or more than |cff00A2FF5|r consonants in a row not to be queued."]);
+		SGI_Filters.tooltip.text:SetWidth(135);
+		SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12);
+		SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5);
+		SGI_Filters.tooltip:Show();
+	end)
+	SGI_Filters.editBoxVC:SetScript("OnLeave", function()
+		SGI_Filters.tooltip:Hide()
+	end)
+
+	SGI_Filters.editBoxVC.title = SGI_Filters.editBoxVC:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_Filters.editBoxVC.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxVC,"TOPLEFT", 0, 5);
+	SGI_Filters.editBoxVC.title:SetText("Max Vowels/Cons (V:C)");
+
+	SGI_EditBoxName:SetScript("OnEnterPressed", function()
+		SGI_EditBoxNameFilter:SetFocus();
+	end);
+	SGI_EditBoxNameFilter:SetScript("OnEnterPressed", function()
+		SGI_EditBoxLvl:SetFocus();
+	end);
+	SGI_EditBoxLvl:SetScript("OnEnterPressed", function()
+		SGI_EditBoxVC:SetFocus();
+	end);
+	SGI_EditBoxVC:SetScript("OnEnterPressed", function()
+		SGI_EditBoxName:SetFocus();
+	end);
+	SGI_EditBoxName:SetScript("OnTabPressed", function()
+		SGI_EditBoxNameFilter:SetFocus();
+	end);
+	SGI_EditBoxNameFilter:SetScript("OnTabPressed", function()
+		SGI_EditBoxLvl:SetFocus();
+	end);
+	SGI_EditBoxLvl:SetScript("OnTabPressed", function()
+		SGI_EditBoxVC:SetFocus();
+	end);
+	SGI_EditBoxVC:SetScript("OnTabPressed", function()
+		SGI_EditBoxName:SetFocus();
+	end);
+
+	local CLASS = {
+			[SGI.L["Death Knight"]] = "DEATHKNIGHT",
+			[SGI.L["Demon Hunter"]] = "DEMONHUNTER",
+			[SGI.L["Druid"]] = "DRUID",
+			[SGI.L["Hunter"]] = "HUNTER",
+			[SGI.L["Mage"]] = "MAGE",
+			[SGI.L["Monk"]] = "MONK",
+			[SGI.L["Paladin"]] = "PALADIN",
+			[SGI.L["Priest"]] = "PRIEST",
+			[SGI.L["Rogue"]] = "ROGUE",
+			[SGI.L["Shaman"]] = "SHAMAN",
+			[SGI.L["Warlock"]] = "WARLOCK",
+			[SGI.L["Warrior"]] = "WARRIOR"
+	}
+	local Classes = {
+			SGI.L["Ignore"],
+			SGI.L["Death Knight"],
+			SGI.L["Demon Hunter"],
+			SGI.L["Druid"],
+			SGI.L["Hunter"],
+			SGI.L["Mage"],
+			SGI.L["Monk"],
+			SGI.L["Paladin"],
+			SGI.L["Priest"],
+			SGI.L["Rogue"],
+			SGI.L["Shaman"],
+			SGI.L["Warlock"],
+			SGI.L["Warrior"],
+	}
+	local Races = {}
+	if UnitFactionGroup("player") == "Horde" then
+		Races = {
+			SGI.L["Ignore"],
+			SGI.L["Orc"],
+			SGI.L["Blood Elf"],
+			SGI.L["Undead"],
+			SGI.L["Troll"],
+			SGI.L["Goblin"],
+			SGI.L["Tauren"],
+			SGI.L["Pandaren"],
+			SGI.L["Highmountain Tauren"],
+			SGI.L["Nightborne"],
+			SGI.L["Mag'har Orc"],
+			SGI.L["Zandalari Troll"],
+		}
+	else
+		Races = {
+			SGI.L["Ignore"],
+			SGI.L["Human"],
+			SGI.L["Dwarf"],
+			SGI.L["Worgen"],
+			SGI.L["Draenei"],
+			SGI.L["Night Elf"],
+			SGI.L["Gnome"],
+			SGI.L["Pandaren"],
+			SGI.L["Void Elf"],
+			SGI.L["Lightforged Draenei"],
+			SGI.L["Dark Iron Dwarf"],
+		}
+	end
+
+	SGI_Filters.classText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_Filters.raceText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+
+	SGI_Filters.classCheckBoxes = {};
+	local anchor = {
+		point = "TOPLEFT",
+		relativePoint = "TOPLEFT",
+		xOfs = 40,
+		yOfs = -90,
+	}
+	for k,_ in pairs(Classes) do
+		SGI_Filters.classCheckBoxes[k] = CreateCheckbox("CHECKBOX_FILTERS_CLASS_"..Classes[k], SGI_Filters, Classes[k], anchor)
+
+		anchor.yOfs = anchor.yOfs - 18;
+	end
+	SGI_Filters.classText:SetPoint("BOTTOM", SGI_Filters.classCheckBoxes[1], "TOP", -5, 3);
+	SGI_Filters.classText:SetText(SGI.L["Classes:"]);
+
+	if (SGI_Filters.classCheckBoxes[1]:GetChecked()) then
+		for i = 2,12 do
+			SGI_Filters.classCheckBoxes[i]:Hide();
+		end
+	else
+		for i = 2,12 do
+			SGI_Filters.classCheckBoxes[i]:Show();
+		end
+	end
+
+	SGI_Filters.classCheckBoxes[1]:HookScript("PostClick", function()
+		if (SGI_Filters.classCheckBoxes[1]:GetChecked()) then
+			for i = 2,12 do
+				SGI_Filters.classCheckBoxes[i]:Hide();
+			end
+		else
+			for i = 2,12 do
+				SGI_Filters.classCheckBoxes[i]:Show();
+			end
+		end
+	end)
+
+
+	SGI_Filters.raceCheckBoxes = {};
+	anchor = {
+		point = "TOPLEFT",
+		relativePoint = "TOPLEFT",
+		xOfs = 160,
+		yOfs = -90,
+	}
+	for k,_ in pairs(Races) do
+		SGI_Filters.raceCheckBoxes[k] = CreateCheckbox("CHECKBOX_FILTERS_RACE_"..Races[k], SGI_Filters, Races[k], anchor)
+		anchor.yOfs = anchor.yOfs - 18;
+	end
+
+	SGI_Filters.raceText:SetPoint("BOTTOM", SGI_Filters.raceCheckBoxes[1], "TOP", -5, 3);
+	SGI_Filters.raceText:SetText(SGI.L["Races:"]);
+
+	if (SGI_Filters.raceCheckBoxes[1]:GetChecked()) then
+		for i = 2,8 do
+			SGI_Filters.raceCheckBoxes[i]:Hide();
+		end
+	else
+		for i = 2,8 do
+			SGI_Filters.raceCheckBoxes[i]:Show();
+		end
+	end
+
+	SGI_Filters.raceCheckBoxes[1]:HookScript("PostClick", function()
+		if (SGI_Filters.raceCheckBoxes[1]:GetChecked()) then
+			for i = 2,8 do
+				SGI_Filters.raceCheckBoxes[i]:Hide();
+			end
+		else
+			for i = 2,8 do
+				SGI_Filters.raceCheckBoxes[i]:Show();
+			end
+		end
+	end)
+
+
+	local function GetFilterData()
+		local FilterName = SGI_EditBoxName:GetText();
+		SGI_EditBoxName:SetText("");
+		if (not FilterName or strlen(FilterName) < 1) then
+			return;
+		end
+		SGI:debug("Filter name: "..FilterName);
+		local V,C = SGI_EditBoxVC:GetText();
+		if (V and strlen(V) > 1) then
+			V,C = strsplit(":", V);
+			V = tonumber(V);
+			C = tonumber(C);
+			if (V == "") then V = nil end
+			if (C == "") then C = nil end
+			SGI:debug("Max Vowels: "..(V or "N/A")..", Max Consonants: "..(C or "N/A"));
+		end
+		SGI_EditBoxVC:SetText("");
+		local Min,Max = SGI_EditBoxLvl:GetText();
+		if (Min and strlen(Min) > 1) then
+			Min, Max = strsplit(":",Min);
+			Min = tonumber(Min);
+			Max = tonumber(Max);
+			SGI:debug("Level range: "..Min.." - "..Max);
+		end
+		SGI_EditBoxLvl:SetText("");
+
+		local ExceptionName = SGI_EditBoxNameFilter:GetText()
+		if (ExceptionName == "") then
+			ExceptionName = nil;
+		end
+		SGI_EditBoxNameFilter:SetText("");
+
+
+
+		local classes = {};
+		if (not SGI_Filters.classCheckBoxes[1]:GetChecked()) then
+			for k,_ in pairs(SGI_Filters.classCheckBoxes) do
+				if (SGI_Filters.classCheckBoxes[k]:GetChecked()) then
+					classes[CLASS[SGI_Filters.classCheckBoxes[k].label:GetText()]] = true;
+					SGI:debug(CLASS[SGI_Filters.classCheckBoxes[k].label:GetText()]);
+					SGI_Filters.classCheckBoxes[k]:SetChecked(false);
+				end
+			end
+		end
+
+		local races = {}
+		if (not SGI_Filters.raceCheckBoxes[1]:GetChecked()) then
+			for k,_ in pairs(SGI_Filters.raceCheckBoxes) do
+				if (SGI_Filters.raceCheckBoxes[k]:GetChecked()) then
+					races[SGI_Filters.raceCheckBoxes[k].label:GetText()] = true;
+					SGI:debug(SGI_Filters.raceCheckBoxes[k].label:GetText());
+					SGI_Filters.raceCheckBoxes[k]:SetChecked(false);
+				end
+			end
+		end
+		SGI:CreateFilter(FilterName,classes,ExceptionName,Min,Max,races,V,C);
+		SGI_FilterHandle.needRedraw = true;
+		return true;
+	end
+
+	anchor = {
+		point = "BOTTOM",
+		relativePoint = "BOTTOM",
+		xOfs = -60,
+		yOfs = 20,
+	}
+
+
+	SGI_Filters.button1 = CreateButton("BUTTON_SAVE_FILTER", SGI_Filters, 120, 30, SGI.L["Save"], anchor, GetFilterData);
+		anchor.xOfs = 60;
+	SGI_Filters.button2 = CreateButton("BUTTON_CANCEL_FILTER", SGI_Filters, 120, 30, SGI.L["Back"], anchor, function() SGI_Filters:Hide() end);
+
+	SGI_Filters:HookScript("OnHide", function() SGI:ShowFilterHandle() SGI_FilterHandle.showOpt = true end);
+
+end
+
+local function ShowFilterFrame()
+	if (not SGI_Filters) then
+		CreateFilterFrame();
+	end
+	SGI_Filters:Show();
+end
+
+
+local function CreateFilterHandleFrame()
+	CreateFrame("Frame","SGI_FilterHandle")
+	SGI_FilterHandle:SetWidth(450)
+	SGI_FilterHandle:SetHeight(350)
+	SetFramePosition(SGI_FilterHandle)
+	SGI_FilterHandle:SetMovable(true)
+	SGI_FilterHandle:SetScript("OnMouseDown",function(self)
+		self:StartMoving()
+	end)
+	SGI_FilterHandle:SetScript("OnMouseUp",function(self)
+		self:StopMovingOrSizing()
+		SaveFramePosition(SGI_FilterHandle)
+	end)
+	local backdrop =
+	{
+		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+		tile = true,
+		tileSize = 16,
+		edgeSize = 16,
+		insets = { left = 4, right = 4, top = 4, bottom = 4 }
+	}
+	SGI_FilterHandle:SetBackdrop(backdrop)
+	local close = CreateFrame("Button",nil,SGI_FilterHandle,"UIPanelCloseButton")
+	close:SetPoint("TOPRIGHT",SGI_FilterHandle,"TOPRIGHT",-4,-4)
+
+	SGI_FilterHandle.title = SGI_FilterHandle:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_FilterHandle.title:SetText("Filters")
+	SGI_FilterHandle.title:SetPoint("TOP",SGI_FilterHandle,"TOP",0,-15)
+	SGI_FilterHandle.underTitle = SGI_FilterHandle:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_FilterHandle.underTitle:SetText("Click to toggle");
+	SGI_FilterHandle.underTitle:SetPoint("TOP", SGI_FilterHandle, "TOP", 0, -35);
+
+	local anchor = {}
+			anchor.point = "BOTTOM"
+			anchor.relativePoint = "BOTTOM"
+			anchor.xOfs = -60
+			anchor.yOfs = 30
+
+	SGI_FilterHandle.button1 = CreateButton("BUTTON_EDIT_FILTERS", SGI_FilterHandle, 120, 30, SGI.L["Add filters"], anchor, function() ShowFilterFrame() SGI_FilterHandle.showOpt = false SGI_FilterHandle.showSelf = true SGI_FilterHandle:Hide() end);
+		anchor.xOfs = 60
+	SGI_FilterHandle.button2 = CreateButton("BUTTON_EDIT_FILTERS", SGI_FilterHandle, 120, 30, SGI.L["Back"], anchor, function() close:Click() end);
+
+
+	SGI_FilterHandle.tooltip = CreateFrame("Frame", "SGI_HandleTooltip", SGI_FilterHandle, "GameTooltipTemplate");
+	SGI_FilterHandle.tooltip:SetWidth(150);
+	SGI_FilterHandle.tooltip.text = SGI_FilterHandle.tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+	SGI_FilterHandle.tooltip.text:SetPoint("CENTER", SGI_FilterHandle.tooltip, "CENTER", 0, 0);
+	SGI_FilterHandle.tooltip.text:SetJustifyH("LEFT");
+
+	local function FormatTooltipFilterText(filter)
+		local text = "Filter name: "..filter.nameOfFilter.."\n";
+
+		if (filter.active) then
+			text = text.."|cff00ff00[ACTIVE]|r\n";
+		else
+			text = text.."|cffff0000[INACTIVE]|r\n";
+		end
+
+		if (filter.class) then
+			for k,v in pairs(filter.class) do
+				text = text.."|cff"..(SGI:GetClassColor(k)..k).."|r\n";
+			end
+		end
+
+		if (filter.race) then
+			for k,v in pairs(filter.race) do
+				text = text.."|cff16ABB5"..k.."|r\n";
+			end
+		end
+
+		if (filter.minLvl and filter.minLvl ~= "") then
+			text = text.."|cff00ff00"..filter.minLvl.."|r - ";
+			if (filter.maxLvl) then
+				text = text.."|cffff0000"..filter.maxLvl.."|r\n";
+			else
+				text = text.."\n";
+			end
+		end
+
+		if (filter.maxVowels and filter.maxVowels ~= "") then
+			text = text.."Vowels: |cff16ABB5"..filter.maxVowels.."|r\n";
+		end
+
+		if (filter.maxConsonants and filter.maxVowels ~= "") then
+			text = text.."Consonants: |cff16ABB5"..filter.maxConsonants.."|r\n";
+		end
+
+		if (filter.name and filter.name ~= "") then
+			text = text.."Name exception: |cff16ABB5"..filter.name.."|r";
+		end
+
+		return text;
+	end
+
+	SGI_FilterHandle.filterFrames = {}
+	SGI_FilterHandle.update = 0;
+	SGI_FilterHandle.needRedraw = false;
+	SGI_FilterHandle:SetScript("OnUpdate", function(self)
+		if (SGI_FilterHandle.update < GetTime()) then
+
+			local anchor = {}
+				anchor.xOfs = -175
+				anchor.yOfs = 110
+
+			local F = SGI_DATA[SGI_DATA_INDEX].settings.filters;
+
+			if (SGI_FilterHandle.needRedraw) then
+				for k,_ in pairs(SGI_FilterHandle.filterFrames) do
+					SGI_FilterHandle.filterFrames[k]:Hide();
+				end
+				SGI_FilterHandle.filterFrames = {};
+				SGI_FilterHandle.needRedraw = false;
+			end
+
+			for k,_ in pairs(F) do
+				if (not SGI_FilterHandle.filterFrames[k]) then
+					SGI_FilterHandle.filterFrames[k] = CreateFrame("Button", "FilterFrame"..k, SGI_FilterHandle);
+					SGI_FilterHandle.filterFrames[k]:SetWidth(80)
+					SGI_FilterHandle.filterFrames[k]:SetHeight(25);
+					SGI_FilterHandle.filterFrames[k]:EnableMouse(true);
+					SGI_FilterHandle.filterFrames[k]:SetPoint("CENTER", SGI_FilterHandle, "CENTER", anchor.xOfs, anchor.yOfs);
+					if mod(k,5) == 0 then
+						anchor.xOfs = -175
+						anchor.yOfs = anchor.yOfs - 30
+					else
+						anchor.xOfs = anchor.xOfs + 85
+					end
+					SGI_FilterHandle.filterFrames[k].text = SGI_FilterHandle.filterFrames[k]:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+					SGI_FilterHandle.filterFrames[k].text:SetPoint("LEFT", SGI_FilterHandle.filterFrames[k], "LEFT", 3, 0);
+					SGI_FilterHandle.filterFrames[k].text:SetJustifyH("LEFT");
+					SGI_FilterHandle.filterFrames[k].text:SetWidth(75);
+					SGI_FilterHandle.filterFrames[k]:EnableMouse(true);
+					SGI_FilterHandle.filterFrames[k]:RegisterForClicks("LeftButtonDown","RightButtonDown");
+					SGI_FilterHandle.filterFrames[k].highlight = SGI_FilterHandle.filterFrames[k]:CreateTexture();
+					SGI_FilterHandle.filterFrames[k].highlight:SetAllPoints();
+					if (SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active) then
+						SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2);
+					else
+						SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2);
+					end
+					SGI_FilterHandle.filterFrames[k]:SetScript("OnEnter", function(self)
+						self.highlight:SetTexture(1,1,0,0.2);
+						SGI:debug("Enter: YELLOW");
+
+						SGI_FilterHandle.tooltip.text:SetText(FormatTooltipFilterText(F[k]));
+						SGI_FilterHandle.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -3);
+						SGI_FilterHandle.tooltip:SetHeight(SGI_FilterHandle.tooltip.text:GetHeight() + 12);
+						SGI_FilterHandle.tooltip:SetWidth(SGI_FilterHandle.tooltip.text:GetWidth() + 10);
+						SGI_FilterHandle.tooltip:Show();
+					end)
+					SGI_FilterHandle.filterFrames[k]:SetScript("OnLeave", function(self)
+						if (F[k] and F[k].active) then--SGI_FilterHandle.filterFrames[k].state) then
+							SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2);
+							SGI:debug("Leave: GREEN");
+
+						else
+							SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2);
+							SGI:debug("Leave: RED");
+						end
+
+						SGI_FilterHandle.tooltip:Hide();
+					end)
+				end
+
+				SGI_FilterHandle.filterFrames[k].filter = F[k];
+				SGI_FilterHandle.filterFrames[k].text:SetText(F[k].nameOfFilter);
+				SGI_FilterHandle.filterFrames[k]:Show();
+
+				SGI_FilterHandle.filterFrames[k]:SetScript("OnClick", function(self, button)
+					SGI:debug(button);
+					if (button == "LeftButton") then
+						if (SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active) then
+							SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active = nil;
+							SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2);
+							SGI:debug("Click: RED");
+						else
+							SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active = true;
+							SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2);
+							SGI:debug("Click: GREEN");
+						end
+
+						SGI_FilterHandle.tooltip.text:SetText(FormatTooltipFilterText(F[k]));
+						SGI_FilterHandle.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -3);
+						SGI_FilterHandle.tooltip:SetHeight(SGI_FilterHandle.tooltip.text:GetHeight() + 12);
+						SGI_FilterHandle.tooltip:SetWidth(SGI_FilterHandle.tooltip.text:GetWidth() + 10);
+						SGI_FilterHandle.tooltip:Show();
+					else
+						SGI_DATA[SGI_DATA_INDEX].settings.filters[k] = nil;
+						SGI_FilterHandle.needRedraw = true;
+					end
+
+				end)
+
+			end
+
+			SGI_FilterHandle.update = GetTime() + 1;
+		end
+	end)
+	SGI_FilterHandle.showOpt = true;
+	SGI_FilterHandle:HookScript("OnHide", function() if SGI_FilterHandle.showOpt then SGI:ShowOptions() end end)
+end
+
+function SGI:ShowFilterHandle()
+	if (not SGI_FilterHandle) then
+		CreateFilterHandleFrame();
+	end
+	SGI_FilterHandle:Show()
+end
+
+local function ChangeLog()
+	CreateFrame("Frame","SGI_ChangeLog")
+	SGI_ChangeLog:SetWidth(550)
+	SGI_ChangeLog:SetHeight(350)
+	SGI_ChangeLog:SetBackdrop(
+	{
+		bgFile = "Interface/ACHIEVEMENTFRAME/UI-Achievement-Parchment-Horizontal",
+		edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
+		tile = false,
+		tileSize = 16,
+		edgeSize = 16,
+		insets = { left = 4, right = 4, top = 4, bottom = 4 }
+	}
+	)
+	SetFramePosition(SGI_ChangeLog)
+
+	local anchor = {}
+			anchor.point = "BOTTOMRIGHT"
+			anchor.relativePoint = "BOTTOMRIGHT"
+			anchor.xOfs = -210
+			anchor.yOfs = 10
+
+	SGI_ChangeLog.check1 = CreateCheckbox("SGI_CHANGES",SGI_ChangeLog,SGI.L["Don't show this after new updates"],anchor)
+		anchor.xOfs = -300
+	SGI_ChangeLog.button1 = CreateButton("SGI_CLOSE_CHANGES",SGI_ChangeLog,120,30,SGI.L["Close"],anchor,function() SGI_ChangeLog:Hide() SGI_DATA.showChanges = SGI.VERSION_MAJOR end)
+
+	SGI_ChangeLog.title = SGI_ChangeLog:CreateFontString()
+	SGI_ChangeLog.title:SetFont("Fonts\\FRIZQT__.TTF",22,"OUTLINE")
+	SGI_ChangeLog.title:SetText("|cffffff00<|r|cff16ABB5SuperGuildInvite|r|cff00ff00 Recent Changes|r|cffffff00>|r|cffffff00")
+	SGI_ChangeLog.title:SetPoint("TOP",SGI_ChangeLog,"TOP",0,-12)
+
+	SGI_ChangeLog.version = SGI_ChangeLog:CreateFontString()
+	SGI_ChangeLog.version:SetFont("Fonts\\FRIZQT__.TTF",16,"OUTLINE")
+	SGI_ChangeLog.version:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",15,-40)
+	SGI_ChangeLog.version:SetText("")
+
+	SGI_ChangeLog.items = {}
+	local y = -65
+	for i = 1,10 do
+		SGI_ChangeLog.items[i] = SGI_ChangeLog:CreateFontString()
+		SGI_ChangeLog.items[i]:SetFont("Fonts\\FRIZQT__.TTF",14,"OUTLINE")
+		SGI_ChangeLog.items[i]:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",30,y)
+		SGI_ChangeLog.items[i]:SetText("")
+		SGI_ChangeLog.items[i]:SetJustifyH("LEFT")
+		SGI_ChangeLog.items[i]:SetSpacing(3)
+		y = y - 17
+	end
+	SGI_ChangeLog.SetChange = function(changes)
+		local Y = -65
+		SGI_ChangeLog.version:SetText("|cff16ABB5"..changes.version.."|r")
+		for k,_ in pairs(changes.items) do
+			SGI_ChangeLog.items[k]:SetText("|cffffff00"..changes.items[k].."|r")
+			SGI_ChangeLog.items[k]:SetWidth(490)
+			SGI_ChangeLog.items[k]:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",30,Y)
+			Y = Y - SGI_ChangeLog.items[k]:GetHeight() - 5
+		end
+	end
+end
+
+function SGI:ShowChanges()
+	if ( SGI_ChangeLog ) then
+		SGI_ChangeLog:Show()
+	else
+		ChangeLog()
+		SGI_ChangeLog:Show()
+	end
+	SGI_ChangeLog.SetChange(SGI.versionChanges);
+end
+
+
+local function CreateTroubleShooter()
+	CreateFrame("Frame","SGI_TroubleShooter")
+	SGI_TroubleShooter:SetWidth(300)
+	SGI_TroubleShooter:SetHeight(100)
+	SetFramePosition(SGI_TroubleShooter)
+	SGI_TroubleShooter:SetMovable(true)
+	SGI_TroubleShooter:SetScript("OnMouseDown",function(self)
+		self:StartMoving()
+	end)
+	SGI_TroubleShooter:SetScript("OnMouseUp",function(self)
+		self:StopMovingOrSizing()
+		SaveFramePosition(SGI_TroubleShooter)
+	end)
+	local backdrop =
+	{
+		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+		tile = true,
+		tileSize = 16,
+		edgeSize = 16,
+		insets = { left = 4, right = 4, top = 4, bottom = 4 }
+	}
+	SGI_TroubleShooter:SetBackdrop(backdrop)
+	local close = CreateFrame("Button",nil,SGI_TroubleShooter,"UIPanelCloseButton")
+	close:SetPoint("TOPRIGHT",SGI_TroubleShooter,"TOPRIGHT",-4,-4)
+
+	SGI_TroubleShooter.title = SGI_TroubleShooter:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_TroubleShooter.title:SetPoint("TOP",SGI_TroubleShooter,"TOP",0,-10)
+	SGI_TroubleShooter.title:SetText("Common issues")
+
+
+	local update = 0;
+
+	SGI_TroubleShooter.items = {};
+	SGI_TroubleShooter:SetScript("OnUpdate", function()
+		if (update < GetTime()) then
+
+
+
+
+			update = GetTime() + 0.5;
+		end
+	end)
+
+
+	SGI_TroubleShooter:HookScript("OnHide", function() if (SGI_Options.showAgain) then SGI_Options:Show() SGI_Options.showAgain = false end end);
+end
+
+function SGI:ShowTroubleShooter()
+	if (not SGI_TroubleShooter) then
+		CreateTroubleShooter();
+	end
+	SGI_TroubleShooter:Show();
+end
+
+
+local function OptBtn2_OnClick()
+	SGI:ShowSuperScanFrame();
+	SSBtn3_OnClick(SGI_SUPERSCAN_PLAYPAUSE2);
+end
+
+
+local function CreateOptions()
+	CreateFrame("Frame","SGI_Options")
+	SGI_Options:SetWidth(530)
+	SGI_Options:SetHeight(280)
+	SetFramePosition(SGI_Options)
+	SGI_Options:SetMovable(true)
+	SGI_Options:SetScript("OnMouseDown",function(self)
+		self:StartMoving()
+	end)
+	SGI_Options:SetScript("OnMouseUp",function(self)
+		self:StopMovingOrSizing()
+		SaveFramePosition(SGI_Options)
+	end)
+	local backdrop =
+	{
+		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+		tile = true,
+		tileSize = 16,
+		edgeSize = 16,
+		insets = { left = 4, right = 4, top = 4, bottom = 4 }
+	}
+	SGI_Options:SetBackdrop(backdrop)
+	local close = CreateFrame("Button",nil,SGI_Options,"UIPanelCloseButton")
+	close:SetPoint("TOPRIGHT",SGI_Options,"TOPRIGHT",-4,-4)
+
+	SGI_Options.title = SGI_Options:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_Options.title:SetText("SuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options")
+	SGI_Options.title:SetPoint("TOP",SGI_Options,"TOP",0,-15)
+	SGI_Options.bottom = SGI_Options:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_Options.bottom:SetText("Updated by a Fan")
+	SGI_Options.bottom:SetPoint("BOTTOM",SGI_Options,"BOTTOM",0,5)
+
+	SGI_Options.optionHelpText = SGI_Options:CreateFontString(nil, "OVERLAY","GameFontNormal");
+	SGI_Options.optionHelpText:SetText("|cff00D2FFScroll to change levels|r");
+	SGI_Options.optionHelpText:SetPoint("TOP",SGI_Options,"TOP",70,-110);
+
+	local anchor = {}
+			anchor.point = "TOPLEFT"
+			anchor.relativePoint = "TOPLEFT"
+			anchor.xOfs = 7
+			anchor.yOfs = -50
+
+	local WhisperMode = {
+		SGI.L["Invite only"],
+		SGI.L["Invite, then whisper"],
+		SGI.L["Whisper only"],
+	}
+
+	local spacing = 25;
+
+	SGI_Options.dropDown1 = CreateDropDown("DROPDOWN_INVITE_MODE", SGI_Options, SGI.L["Invite Mode"], WhisperMode, anchor);
+		anchor.yOfs = anchor.yOfs - spacing - 7;
+		anchor.xOfs = anchor.xOfs + 13;
+--	SGI_Options.checkBox1 = CreateCheckbox("CHECKBOX_MUTE_SGI", SGI_Options, SGI.L["Mute SGI"], anchor);
+--		anchor.yOfs = anchor.yOfs - spacing;
+	SGI_Options.checkBox2 = CreateCheckbox("CHECKBOX_ADV_SCAN", SGI_Options, SGI.L["Advanced scan options"], anchor);
+		anchor.yOfs = anchor.yOfs - spacing;
+--	SGI_Options.checkBox3 = CreateCheckbox("CHECKBOX_HIDE_SYSTEM", SGI_Options, SGI.L["Hide system messages"], anchor);
+--		anchor.yOfs = anchor.yOfs - spacing;
+	SGI_Options.checkBox7 = CreateCheckbox("CHECKBOX_HIDE_WHISPER", SGI_Options, SGI.L["Hide outgoing whispers"], anchor);
+		anchor.yOfs = anchor.yOfs - spacing;
+	SGI_Options.checkBox4 = CreateCheckbox("CHECKBOX_HIDE_MINIMAP", SGI_Options, SGI.L["Hide minimap button"], anchor);
+		anchor.yOfs = anchor.yOfs - spacing;
+	SGI_Options.checkBox5 = CreateCheckbox("CHECKBOX_BACKGROUND_MODE", SGI_Options, SGI.L["Run SuperScan in the background"], anchor);
+		anchor.yOfs = anchor.yOfs - spacing;
+	SGI_Options.checkBox6 = CreateCheckbox("CHECKBOX_ENABLE_FILTERS", SGI_Options, SGI.L["Enable filtering"], anchor);
+
+--	SGI_Options.checkBox3:HookScript("PostClick", function(self) ChatIntercept:StateSystem(self:GetChecked()) end);
+	SGI_Options.checkBox7:HookScript("PostClick", function(self) ChatIntercept:StateWhisper(self:GetChecked()) end);
+
+
+-- ANchor point for the bottom row of buttons
+
+		anchor.point = "BOTTOMLEFT"
+		anchor.relativePoint = "BOTTOMLEFT"
+		anchor.xOfs = 20
+		anchor.yOfs = 25
+
+	--onClickTester
+	SGI_Options.button1 = CreateButton("BUTTON_CUSTOM_WHISPER", SGI_Options, 120, 30, SGI.L["Edit whisper"], anchor, function(self) ShowWhisperFrame() SGI_Options:Hide() SGI_Options.showAgain = true end);
+		anchor.xOfs = anchor.xOfs + 125;
+	SGI_Options.button2 = CreateButton("BUTTON_SUPER_SCAN", SGI_Options, 120, 30, SGI.L["SuperScan"], anchor, OptBtn2_OnClick);
+		anchor.xOfs = anchor.xOfs + 125;
+	SGI_Options.button3 = CreateButton("BUTTON_INVITE", SGI_Options, 120, 30, format(SGI.L["Invite: %d"],SGI:GetNumQueued()), anchor, SGI.SendGuildInvite);
+		anchor.xOfs = anchor.xOfs + 125;
+	SGI_Options.button4 = CreateButton("BUTTON_CHOOSE_INVITES", SGI_Options, 120, 30, SGI.L["Choose invites"], anchor, SGI.ShowInviteList);
+		anchor.yOfs = 60;
+	SGI_Options.button5 = CreateButton("BUTTON_EDIT_FILTERS", SGI_Options, 120, 30, SGI.L["Filters"], anchor, function() SGI:ShowFilterHandle() SGI_Options:Hide() end);
+		anchor.xOfs = anchor.xOfs - 125;
+	--SGI_Options.button6 = CreateButton("BUTTON_HELP", SGI_Options, 120, 30, SGI.L["Help"],anchor, function() SGI:ShowTroubleShooter() SGI_Options:Hide() SGI_Options.showAgain = true end);
+		--anchor.xOfs = anchor.xOfs - 125;
+
+--Take out keybinding, no way to escape from it once you click it. Very dangerous and poor design.
+
+--	SGI_Options.button7 = CreateButton("BUTTON_KEYBIND", SGI_Options, 120, 30, SGI.L["Set Keybind ("..(SGI_DATA[SGI_DATA_INDEX].keyBind and SGI_DATA--[SGI_DATA_INDEX].keyBind or "NONE")..")"], anchor, KeyHarvestFrame.GetNewKeybindKey);
+--		anchor.xOfs = anchor.xOfs - 125;
+	--SGI_Options.button8 = CreateButton("BUTTON_FILTER", SGI_Options, 120, 30, SGI.L["Filters"], anchor, onClickTester);
+
+
+	SGI_Options.limitLow = CreateFrame("Frame","SGI_LowLimit",SGI_Options)
+	SGI_Options.limitLow:SetWidth(40)
+	SGI_Options.limitLow:SetHeight(40)
+	SGI_Options.limitLow:SetPoint("CENTER",SGI_Options,"CENTER",40,40)
+	SGI_Options.limitLow.text = SGI_Options.limitLow:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_Options.limitLow.text:SetPoint("CENTER")
+	SGI_Options.limitLow.texture = SGI_Options.limitLow:CreateTexture()
+	SGI_Options.limitLow.texture:SetAllPoints()
+	SGI_Options.limitLow.texture:SetTexture(1,1,0,0.2)
+	SGI_Options.limitLow.texture:Hide()
+	SGI_Options.limitTooltip = CreateFrame("Frame","LimitTool",SGI_Options.limitLow,"GameTooltipTemplate")
+
+	SGI_Options.limitTooltip:SetPoint("TOP",SGI_Options.limitLow,"BOTTOM")
+	SGI_Options.limitTooltip.text = SGI_Options.limitTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Options.limitTooltip.text:SetPoint("LEFT",SGI_Options.limitTooltip,"LEFT",12,0)
+	SGI_Options.limitTooltip.text:SetJustifyH("LEFT")
+	SGI_Options.limitTooltip.text:SetText(SGI.L["Highest and lowest level to search for"])
+	SGI_Options.limitTooltip.text:SetWidth(115)
+	SGI_Options.limitTooltip:SetWidth(130)
+	SGI_Options.limitTooltip:SetHeight(SGI_Options.limitTooltip.text:GetHeight() + 12)
+
+	SGI_Options.limitLow:SetScript("OnEnter",function()
+		SGI_Options.limitLow.texture:Show()
+		SGI_Options.limitTooltip:Show()
+	end)
+	SGI_Options.limitLow:SetScript("OnLeave",function()
+		SGI_Options.limitLow.texture:Hide()
+		SGI_Options.limitTooltip:Hide()
+	end)
+
+	SGI_Options.limitHigh = CreateFrame("Frame","SGI_HighLimit",SGI_Options)
+	SGI_Options.limitHigh:SetWidth(40)
+	SGI_Options.limitHigh:SetHeight(40)
+	SGI_Options.limitHigh:SetPoint("CENTER",SGI_Options,"CENTER",90,40)
+	SGI_Options.limitHigh.text = SGI_Options.limitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_Options.limitHigh.text:SetPoint("CENTER")
+	SGI_Options.limitHigh.texture = SGI_Options.limitHigh:CreateTexture()
+	SGI_Options.limitHigh.texture:SetAllPoints()
+	SGI_Options.limitHigh.texture:SetTexture(1,1,0,0.2)
+	SGI_Options.limitHigh.texture:Hide()
+
+	SGI_Options.limitHigh:SetScript("OnEnter",function()
+		SGI_Options.limitHigh.texture:Show()
+		SGI_Options.limitTooltip:Show()
+	end)
+	SGI_Options.limitHigh:SetScript("OnLeave",function()
+		SGI_Options.limitHigh.texture:Hide()
+		SGI_Options.limitTooltip:Hide()
+	end)
+
+	SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.."  - ")
+	SGI_Options.limitLow:SetScript("OnMouseWheel",function(self,delta)
+		if delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.lowLimit + 1 <= SGI_DATA[SGI_DATA_INDEX].settings.highLimit then
+			SGI_DATA[SGI_DATA_INDEX].settings.lowLimit = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit + 1
+			SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.." - ")
+		elseif delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.lowLimit - 1 >= SGI_MIN_LEVEL_SUPER_SCAN then
+			SGI_DATA[SGI_DATA_INDEX].settings.lowLimit = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit - 1
+			SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.." - ")
+		end
+	end)
+
+	SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit)
+	SGI_Options.limitHigh:SetScript("OnMouseWheel",function(self,delta)
+		if delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.highLimit + 1 <= SGI_MAX_LEVEL_SUPER_SCAN then
+			SGI_DATA[SGI_DATA_INDEX].settings.highLimit = SGI_DATA[SGI_DATA_INDEX].settings.highLimit + 1
+			SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit)
+		elseif delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.highLimit > SGI_DATA[SGI_DATA_INDEX].settings.lowLimit then
+			SGI_DATA[SGI_DATA_INDEX].settings.highLimit = SGI_DATA[SGI_DATA_INDEX].settings.highLimit - 1
+			SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit)
+		end
+	end)
+
+	SGI_Options.limitText = SGI_Options.limitLow:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Options.limitText:SetPoint("BOTTOM",SGI_Options.limitLow,"TOP",16,0)
+	SGI_Options.limitText:SetText(SGI.L["Level limits"])
+
+	SGI_Options.raceLimitHigh = CreateFrame("Frame","SGI_RaceLimitHigh",SGI_Options)
+	SGI_Options.raceLimitHigh:SetWidth(40)
+	SGI_Options.raceLimitHigh:SetHeight(40)
+	SGI_Options.raceLimitHigh:SetPoint("CENTER",SGI_Options,"CENTER",200,70)
+	SGI_Options.raceLimitHigh.text = SGI_Options.raceLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_Options.raceLimitHigh.text:SetPoint("CENTER")
+	SGI_Options.raceLimitHigh.texture = SGI_Options.raceLimitHigh:CreateTexture()
+	SGI_Options.raceLimitHigh.texture:SetAllPoints()
+	SGI_Options.raceLimitHigh.texture:SetTexture(1,1,0,0.2)
+	SGI_Options.raceLimitHigh.texture:Hide()
+	SGI_Options.raceTooltip = CreateFrame("Frame","LimitTool",SGI_Options.raceLimitHigh,"GameTooltipTemplate")
+
+	SGI_Options.raceTooltip:SetPoint("TOP",SGI_Options.raceLimitHigh,"BOTTOM")
+	SGI_Options.raceTooltip.text = SGI_Options.raceTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Options.raceTooltip.text:SetPoint("LEFT",SGI_Options.raceTooltip,"LEFT",12,0)
+	SGI_Options.raceTooltip.text:SetJustifyH("LEFT")
+	SGI_Options.raceTooltip.text:SetText(SGI.L["The level you wish to start dividing the search by race"])
+	SGI_Options.raceTooltip.text:SetWidth(110)
+	SGI_Options.raceTooltip:SetWidth(125)
+	SGI_Options.raceTooltip:SetHeight(SGI_Options.raceTooltip.text:GetHeight() + 12)
+
+	SGI_Options.raceLimitText = SGI_Options.raceLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Options.raceLimitText:SetPoint("BOTTOM",SGI_Options.raceLimitHigh,"TOP",0,3)
+	SGI_Options.raceLimitText:SetText(SGI.L["Racefilter Start:"])
+
+	SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart)
+	SGI_Options.raceLimitHigh:SetScript("OnMouseWheel",function(self,delta)
+		if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.raceStart > 1 then
+			SGI_DATA[SGI_DATA_INDEX].settings.raceStart = SGI_DATA[SGI_DATA_INDEX].settings.raceStart - 1
+			SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart)
+		elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.raceStart < SGI_MAX_LEVEL_SUPER_SCAN + 1 then
+			SGI_DATA[SGI_DATA_INDEX].settings.raceStart = SGI_DATA[SGI_DATA_INDEX].settings.raceStart + 1
+			SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart)
+			if SGI_DATA[SGI_DATA_INDEX].settings.raceStart > SGI_MAX_LEVEL_SUPER_SCAN then
+				SGI_Options.raceLimitHigh.text:SetText(SGI.L["OFF"])
+			end
+		end
+	end)
+
+	SGI_Options.raceLimitHigh:SetScript("OnEnter",function()
+		SGI_Options.raceLimitHigh.texture:Show()
+		SGI_Options.raceTooltip:Show()
+	end)
+	SGI_Options.raceLimitHigh:SetScript("OnLeave",function()
+		SGI_Options.raceLimitHigh.texture:Hide()
+		SGI_Options.raceTooltip:Hide()
+	end)
+
+	SGI_Options.classLimitHigh = CreateFrame("Frame","SGI_ClassLimitHigh",SGI_Options)
+	SGI_Options.classLimitHigh:SetWidth(40)
+	SGI_Options.classLimitHigh:SetHeight(40)
+	SGI_Options.classLimitHigh:SetPoint("CENTER",SGI_Options,"CENTER",200,20)
+	SGI_Options.classLimitHigh.text = SGI_Options.classLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_Options.classLimitHigh.text:SetPoint("CENTER")
+	SGI_Options.classLimitHigh.texture = SGI_Options.classLimitHigh:CreateTexture()
+	SGI_Options.classLimitHigh.texture:SetAllPoints()
+	SGI_Options.classLimitHigh.texture:SetTexture(1,1,0,0.2)
+	SGI_Options.classLimitHigh.texture:Hide()
+	SGI_Options.classTooltip = CreateFrame("Frame","LimitTool",SGI_Options.classLimitHigh,"GameTooltipTemplate")
+
+	SGI_Options.classTooltip:SetPoint("TOP",SGI_Options.classLimitHigh,"BOTTOM")
+	SGI_Options.classTooltip.text = SGI_Options.classTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Options.classTooltip.text:SetPoint("LEFT",SGI_Options.classTooltip,"LEFT",12,0)
+	SGI_Options.classTooltip.text:SetJustifyH("LEFT")
+	SGI_Options.classTooltip.text:SetText(SGI.L["The level you wish to divide the search by class"])
+	SGI_Options.classTooltip.text:SetWidth(110)
+
+	SGI_Options.classTooltip:SetWidth(125)
+	SGI_Options.classTooltip:SetHeight(SGI_Options.classTooltip.text:GetHeight() + 12)
+
+	SGI_Options.classLimitText = SGI_Options.classLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Options.classLimitText:SetPoint("BOTTOM",SGI_Options.classLimitHigh,"TOP",0,3)
+	SGI_Options.classLimitText:SetText(SGI.L["Classfilter Start:"])
+
+	SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart)
+	SGI_Options.classLimitHigh:SetScript("OnMouseWheel",function(self,delta)
+		if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.classStart > 1 then
+			SGI_DATA[SGI_DATA_INDEX].settings.classStart = SGI_DATA[SGI_DATA_INDEX].settings.classStart - 1
+			SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart)
+		elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.classStart < SGI_MAX_LEVEL_SUPER_SCAN + 1 then
+			SGI_DATA[SGI_DATA_INDEX].settings.classStart = SGI_DATA[SGI_DATA_INDEX].settings.classStart + 1
+			SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart)
+			if SGI_DATA[SGI_DATA_INDEX].settings.classStart > SGI_MAX_LEVEL_SUPER_SCAN then
+				SGI_Options.classLimitHigh.text:SetText(SGI.L["OFF"])
+			end
+		end
+	end)
+
+	SGI_Options.classLimitHigh:SetScript("OnEnter",function()
+		SGI_Options.classLimitHigh.texture:Show()
+		SGI_Options.classTooltip:Show()
+	end)
+	SGI_Options.classLimitHigh:SetScript("OnLeave",function()
+		SGI_Options.classLimitHigh.texture:Hide()
+		SGI_Options.classTooltip:Hide()
+	end)
+
+	SGI_Options.Interval = CreateFrame("Frame","SGI_Interval",SGI_Options)
+	SGI_Options.Interval:SetWidth(40)
+	SGI_Options.Interval:SetHeight(40)
+	SGI_Options.Interval:SetPoint("CENTER",SGI_Options,"CENTER",200,-30)
+	SGI_Options.Interval.text = SGI_Options.Interval:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+	SGI_Options.Interval.text:SetPoint("CENTER")
+	SGI_Options.Interval.texture = SGI_Options.Interval:CreateTexture()
+	SGI_Options.Interval.texture:SetAllPoints()
+	SGI_Options.Interval.texture:SetTexture(1,1,0,0.2)
+	SGI_Options.Interval.texture:Hide()
+	SGI_Options.intervalTooltip = CreateFrame("Frame","LimitTool",SGI_Options.Interval,"GameTooltipTemplate")
+
+	SGI_Options.intervalTooltip:SetPoint("TOP",SGI_Options.Interval,"BOTTOM")
+	SGI_Options.intervalTooltip.text = SGI_Options.intervalTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Options.intervalTooltip.text:SetPoint("LEFT",SGI_Options.intervalTooltip,"LEFT",12,0)
+	SGI_Options.intervalTooltip.text:SetJustifyH("LEFT")
+	SGI_Options.intervalTooltip.text:SetText(SGI.L["Amount of levels to search every 7 seconds (higher numbers increase the risk of capping the search results)"])
+	SGI_Options.intervalTooltip.text:SetWidth(130)
+	SGI_Options.intervalTooltip:SetHeight(120)
+	SGI_Options.intervalTooltip:SetWidth(135)
+	SGI_Options.intervalTooltip:SetHeight(SGI_Options.intervalTooltip.text:GetHeight() + 12)
+
+	SGI_Options.intervalText = SGI_Options.Interval:CreateFontString(nil,"OVERLAY","GameFontNormal")
+	SGI_Options.intervalText:SetPoint("BOTTOM",SGI_Options.Interval,"TOP",0,3)
+	SGI_Options.intervalText:SetText(SGI.L["Interval:"])
+
+	SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval)
+	SGI_Options.Interval:SetScript("OnMouseWheel",function(self,delta)
+		if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.interval > 1 then
+			SGI_DATA[SGI_DATA_INDEX].settings.interval = SGI_DATA[SGI_DATA_INDEX].settings.interval - 1
+			SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval)
+		elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.interval < 30 then
+			SGI_DATA[SGI_DATA_INDEX].settings.interval = SGI_DATA[SGI_DATA_INDEX].settings.interval + 1
+			SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval)
+		end
+	end)
+
+	SGI_Options.Interval:SetScript("OnEnter",function()
+		SGI_Options.Interval.texture:Show()
+		SGI_Options.intervalTooltip:Show()
+	end)
+	SGI_Options.Interval:SetScript("OnLeave",function()
+		SGI_Options.Interval.texture:Hide()
+		SGI_Options.intervalTooltip:Hide()
+	end)
+
+	anchor = {
+		point = "BOTTOMLEFT",
+		relativePoint = "BOTTOMLEFT",
+		xOfs = 4,
+		yOfs = 4,
+	}
+	SGI_Options.superScanText = SGI_Options:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge");
+	SGI_Options.superScanText:SetPoint("BOTTOMLEFT", SGI_Options, "BOTTOMLEFT", 35, 10);
+	SGI_Options.superScanText:SetText("SuperScan");
+	SGI_Options.buttonPlayPause = CreateButton("SGI_SUPERSCAN_PLAYPAUSE2", SGI_Options, 40,30,"",anchor,SSBtn3_OnClick);
+	SGI_SUPERSCAN_PLAYPAUSE2:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up");
+	SGI_SUPERSCAN_PLAYPAUSE2:Hide();
+	SGI_Options.superScanText:Hide();
+
+	SGI_Options.nextUpdate = GetTime();
+	SGI_Options:SetScript("OnUpdate", function()
+
+		if (SGI_Options.nextUpdate < GetTime()) then
+
+
+
+			if SGI_DATA[SGI_DATA_INDEX].settings.classStart > SGI_MAX_LEVEL_SUPER_SCAN then
+				SGI_Options.classLimitHigh.text:SetText(SGI.L["OFF"])
+			end
+
+			if SGI_DATA[SGI_DATA_INDEX].settings.raceStart > SGI_MAX_LEVEL_SUPER_SCAN then
+				SGI_Options.raceLimitHigh.text:SetText(SGI.L["OFF"])
+			end
+
+			if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"]) then
+				SGI_SUPERSCAN_PLAYPAUSE2:Show();
+				SGI_Options.superScanText:Show();
+				if SuperScanFrame then SuperScanFrame:Hide() end;
+			else
+				SGI_SUPERSCAN_PLAYPAUSE2:Hide();
+				SGI_Options.superScanText:Hide();
+				if (SGI:IsScanning()) then
+					SGI:ShowSuperScanFrame();
+				end
+			end
+
+			if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ADV_SCAN"]) then
+
+
+			-- print ( SGI_Options.nextUpdate)
+
+				if (not SGI_Options.Interval:IsShown()) then
+					SGI_Options.Interval:Show();
+				end
+				if (not SGI_Options.classLimitHigh:IsShown()) then
+					SGI_Options.classLimitHigh:Show();
+				end
+				if (not SGI_Options.raceLimitHigh:IsShown()) then
+					SGI_Options.raceLimitHigh:Show();
+				end
+			else
+				SGI_Options.Interval:Hide();
+				SGI_Options.classLimitHigh:Hide();
+				SGI_Options.raceLimitHigh:Hide();
+			end
+
+		--SGI_Options.Interval:Show();
+		--SGI_Options.classLimitHigh:Show();
+		--SGI_Options.raceLimitHigh:Show();
+
+
+
+			BUTTON_INVITE.label:SetText(format(SGI.L["Invite: %d"],SGI:GetNumQueued()));
+			--BUTTON_KEYBIND.label:SetText(SGI.L["Set Keybind ("..(SGI_DATA[SGI_DATA_INDEX].keyBind and SGI_DATA[SGI_DATA_INDEX].keyBind or "NONE")..")"]);
+
+			if (SGI_DATA[SGI_DATA_INDEX].debug) then
+				SGI_Options.title:SetText("|cffff3300(DEBUG MODE) |rSuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options")
+			else
+				SGI_Options.title:SetText("SuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options")
+			end
+
+			if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_MINIMAP"]) then
+				SGI:ShowMinimapButton();
+			else
+				SGI:HideMinimapButton();
+			end
+
+			SGI_Options.nextUpdate = GetTime() + 1;
+		end
+	end)
+
+end
+
+function SGI:ShowOptions()
+	if (not SGI_Options) then
+		CreateOptions();
+	end
+	SGI_Options:Show();
+end
+
+function SGI:HideOptions()
+	if (SGI_Options) then
+		SGI_Options:Hide();
+	end
+end
+
+
+local function CreateMinimapButton()
+	local f = CreateFrame("Button","SGI_MiniMapButton",Minimap)
+	f:SetWidth(32)
+	f:SetHeight(32)
+	f:SetFrameStrata("MEDIUM")
+	f:SetMovable(true)
+	SetFramePosition(f)
+
+	f:SetNormalTexture("Interface\\AddOns\\SuperGuildInviteReborn\\media\\SGI_MiniMapButton")
+	f:SetPushedTexture("Interface\\AddOns\\SuperGuildInviteReborn\\media\\SGI_MiniMapButtonPushed")
+	f:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
+
+--	local tooltip = CreateFrame("Frame","SGI_TooltTipMini",f,"GameTooltipTemplate")
+--	tooltip:SetPoint("BOTTOMRIGHT",f,"TOPLEFT",0,-3)
+--	local toolstring = tooltip:CreateFontString(nil,"OVERLAY","GameFontNormal")
+--	toolstring:SetPoint("TOPLEFT",tooltip,"TOPLEFT",5,-7)
+
+--	local toolstring2 = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+--	local toolstring3 = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal");
+--	toolstring2:SetPoint("TOPLEFT",tooltip,"TOPLEFT",7,-33);
+--	toolstring3:SetPoint("TOPLEFT", tooltip, "TOPLEFT", 7, -46);
+--	toolstring2:SetText(format("ETR: %s",SGI:GetSuperScanTimeLeft()));
+--	toolstring3:SetText(format("%d%% done",floor(SGI:GetPercentageDone())));
+
+--	local tUpdate = 0;
+--	local function UpdateTooltip()
+--		if (tUpdate < GetTime()) then
+--			toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: %d|r",SGI:GetNumQueued()))
+--			toolstring2:SetText(format("ETR: %s",SGI:GetSuperScanTimeLeft()));
+--			toolstring3:SetText(format("%d%% done",floor(SGI:GetPercentageDone())));
+			--SGI:debug(format("ETR: %s",SGI:GetSuperScanETR()));
+			--SGI:debug(format("%d%% done",floor(SGI:GetPercentageDone())));
+--			tUpdate = GetTime() + 0.2;
+--		end
+--	end
+
+--	toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: |r|cffffff00%d|r",SGI:GetNumQueued()))
+--	toolstring:SetJustifyH("LEFT");
+--	tooltip:SetWidth(max(toolstring:GetWidth(),toolstring2:GetWidth(),toolstring3:GetWidth())+ 20)
+--	tooltip:SetHeight(toolstring:GetHeight() + toolstring2:GetHeight() + toolstring3:GetHeight() + 15)
+--	tooltip:Hide()
+--	f:SetScript("OnEnter",function()
+--		toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: %d|r",SGI:GetNumQueued()))
+--		tooltip:Show()
+--		tooltip:SetScript("OnUpdate",UpdateTooltip);
+--	end)
+--	f:SetScript("OnLeave",function()
+--		tooltip:Hide()
+--		tooltip:SetScript("OnUpdate", nil);
+--	end)
+
+
+	local function moveButton(self)
+		local centerX, centerY = Minimap:GetCenter()
+		local x, y = GetCursorPosition()
+		x, y = x / self:GetEffectiveScale() - centerX, y / self:GetEffectiveScale() - centerY
+		centerX, centerY = math.abs(x), math.abs(y)
+		centerX, centerY = (centerX / math.sqrt(centerX^2 + centerY^2)) * 85, (centerY / sqrt(centerX^2 + centerY^2)) * 85
+		centerX = x < 0 and -centerX or centerX
+		centerY = y < 0 and -centerY or centerY
+		self:ClearAllPoints()
+		self:SetPoint("CENTER", centerX, centerY)
+	end
+
+	f:SetScript("OnMouseDown",function(self,button)
+		if button == "RightButton" then
+			self:SetScript("OnUpdate",moveButton)
+		end
+	end)
+	f:SetScript("OnMouseUp",function(self,button)
+		self:SetScript("OnUpdate",nil)
+		SaveFramePosition(self)
+	end)
+	f:SetScript("OnClick",function(self,button)
+		if SGI_Options and SGI_Options:IsShown() then
+			SGI:HideOptions()
+		else
+			SGI:ShowOptions()
+		end
+	end)
+end
+
+function SGI:ShowMinimapButton()
+	if (not SGI_MiniMapButton) then
+		CreateMinimapButton();
+	end
+	SGI_MiniMapButton:Show();
+end
+
+function SGI:HideMinimapButton()
+	if (SGI_MiniMapButton) then
+		SGI_MiniMapButton:Hide();
+	end
+end
+
+
+
+
+
+
+
+
+SGI:debug(">> GUI.lua");
diff --git a/core/SGI_System_Message.lua b/core/SGI_System_Message.lua
index 8360690..4981b60 100644
--- a/core/SGI_System_Message.lua
+++ b/core/SGI_System_Message.lua
@@ -1,134 +1,134 @@
-local function ProcessSystemMsg(msg)
-	local place = strfind(ERR_GUILD_INVITE_S,"%s",1,true)
-	if (place) then
-		local n = strsub(msg,place)
-		local name = strsub(n,1,(strfind(n,"%s") or 2)-1)
-		if format(ERR_GUILD_INVITE_S,name) == msg then
-			return "invite",name
-		end
-	end
-
-	place = strfind(ERR_GUILD_DECLINE_S,"%s",1,true)
-	if (place) then
-		n = strsub(msg,place)
-		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
-		if format(ERR_GUILD_DECLINE_S,name) == msg then
-			return "decline",name
-		end
-	end
-
-	place = strfind(ERR_ALREADY_IN_GUILD_S,"%s",1,true)
-	if (place) then
-		n = strsub(msg,place)
-		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
-		if format(ERR_ALREADY_IN_GUILD_S,name) == msg then
-			return "guilded",name
-		end
-	end
-
-	place = strfind(ERR_ALREADY_INVITED_TO_GUILD_S,"%s",1,true)
-	if (place) then
-		n = strsub(msg,place)
-		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
-		if format(ERR_ALREADY_INVITED_TO_GUILD_S,name) == msg then
-			return "already",name
-		end
-	end
-
-	place = strfind(ERR_GUILD_DECLINE_AUTO_S,"%s",1,true)
-	if (place) then
-		n = strsub(msg,place)
-		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
-		if format(ERR_GUILD_DECLINE_AUTO_S,name) == msg then
-			return "auto",name
-		end
-	end
-
-	place = strfind(ERR_GUILD_JOIN_S,"%s",1,true)
-	if (place) then
-		n = strsub(msg,place)
-		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
-		if format(ERR_GUILD_JOIN_S,name) == msg then
-			return "join",name
-		end
-	end
-
-	place = strfind(ERR_GUILD_PLAYER_NOT_FOUND_S,"%s",1,true)
-	if (place) then
-		n = strsub(msg,place)
-		name = strsub(n,1,(strfind(n,"%s") or 2)-2)
-		if format(ERR_GUILD_PLAYER_NOT_FOUND_S,name) == msg then
-			return "miss",name
-		end
-	end
-
-	place = strfind(ERR_CHAT_PLAYER_NOT_FOUND_S,"%s",1,true)
-	if (place) then
-		n = strsub(msg,place)
-		name = strsub(n,1,(strfind(n,"%s") or 2)-2)
-		if format(ERR_CHAT_PLAYER_NOT_FOUND_S,name) == msg then
-			return "out",name
-		end
-	end
-
-	return "unregistered message", "N/A";
-end
-
-function SGI:SystemMessage(event,_,message,...)
-
-	local type, name = ProcessSystemMsg(message);
-	SGI:debug("Type: "..type.." Name: "..name);
-
-	if (type == "invite") then
-		if (SGI:IsRegisteredForWhisper(name)) then
-			SGI:SendWhisper(SGI:FormatWhisper(SGI:PickRandomWhisper(), name), name, 1);
-		end
-	elseif (type == "decline") then
-		SGI:UnregisterForWhisper(name);
-	elseif (type == "auto") then
-		SGI:LockPlayer(name);
-		SGI:UnregisterForWhisper(name);
-	elseif (type == "guilded") then
-		SGI:LockPlayer(name);
-		SGI:UnregisterForWhisper(name);
-	elseif (type == "already") then
-		SGI:LockPlayer(name);
-		SGI:UnregisterForWhisper(name);
-	elseif (type == "join") then
-
-		if (CanEditOfficerNote()) then
-			for i = 1,GetNumGuildMembers() do
-				local n = GetGuildRosterInfo(i);
-				if (n == name) then
-					GuildRosterSetOfficerNote(i, date());
-				end
-			end
-		elseif (CanEditPublicNote()) then
-			for i = 1,GetNumGuildMembers() do
-				local n = GetGuildRosterInfo(i);
-				if (n == name) then
-					GuildRosterSetPublicNote(i, date());
-				end
-			end
-		end
-
-	elseif (type == "miss") then
-		if (SGI:IsSharing(name)) then
-			SGI:StopMassShare(name);
-			debug("Stopped mass share!");
-		end
-		SGI:print(format(SGI.L["Unable to invite %s. They will not be locked."],name));
-		SGI:UnlockPlayer(name);
-		SGI:UnregisterForWhisper(name);
-	elseif (type == "out") then
-		-- hmm...
-		if (SGI:IsSharing(name)) then
-			SGI:StopMassShare(name);
-			debug("Stopped mass share!");
-		end
-		SGI:RemoveQueued(name);
-	end
-
-end
-
-SGI:debug(">> System_Message.lua");
+local function ProcessSystemMsg(msg)
+	local place = strfind(ERR_GUILD_INVITE_S,"%s",1,true)
+	if (place) then
+		local n = strsub(msg,place)
+		local name = strsub(n,1,(strfind(n,"%s") or 2)-1)
+		if format(ERR_GUILD_INVITE_S,name) == msg then
+			return "invite",name
+		end
+	end
+
+	place = strfind(ERR_GUILD_DECLINE_S,"%s",1,true)
+	if (place) then
+		n = strsub(msg,place)
+		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
+		if format(ERR_GUILD_DECLINE_S,name) == msg then
+			return "decline",name
+		end
+	end
+
+	place = strfind(ERR_ALREADY_IN_GUILD_S,"%s",1,true)
+	if (place) then
+		n = strsub(msg,place)
+		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
+		if format(ERR_ALREADY_IN_GUILD_S,name) == msg then
+			return "guilded",name
+		end
+	end
+
+	place = strfind(ERR_ALREADY_INVITED_TO_GUILD_S,"%s",1,true)
+	if (place) then
+		n = strsub(msg,place)
+		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
+		if format(ERR_ALREADY_INVITED_TO_GUILD_S,name) == msg then
+			return "already",name
+		end
+	end
+
+	place = strfind(ERR_GUILD_DECLINE_AUTO_S,"%s",1,true)
+	if (place) then
+		n = strsub(msg,place)
+		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
+		if format(ERR_GUILD_DECLINE_AUTO_S,name) == msg then
+			return "auto",name
+		end
+	end
+
+	place = strfind(ERR_GUILD_JOIN_S,"%s",1,true)
+	if (place) then
+		n = strsub(msg,place)
+		name = strsub(n,1,(strfind(n,"%s") or 2)-1)
+		if format(ERR_GUILD_JOIN_S,name) == msg then
+			return "join",name
+		end
+	end
+
+	place = strfind(ERR_GUILD_PLAYER_NOT_FOUND_S,"%s",1,true)
+	if (place) then
+		n = strsub(msg,place)
+		name = strsub(n,1,(strfind(n,"%s") or 2)-2)
+		if format(ERR_GUILD_PLAYER_NOT_FOUND_S,name) == msg then
+			return "miss",name
+		end
+	end
+
+	place = strfind(ERR_CHAT_PLAYER_NOT_FOUND_S,"%s",1,true)
+	if (place) then
+		n = strsub(msg,place)
+		name = strsub(n,1,(strfind(n,"%s") or 2)-2)
+		if format(ERR_CHAT_PLAYER_NOT_FOUND_S,name) == msg then
+			return "out",name
+		end
+	end
+
+	return "unregistered message", "N/A";
+end
+
+function SGI:SystemMessage(event,_,message,...)
+
+	local type, name = ProcessSystemMsg(message);
+	SGI:debug("Type: "..type.." Name: "..name);
+
+	if (type == "invite") then
+		if (SGI:IsRegisteredForWhisper(name)) then
+			SGI:SendWhisper(SGI:FormatWhisper(SGI:PickRandomWhisper(), name), name, 1);
+		end
+	elseif (type == "decline") then
+		SGI:UnregisterForWhisper(name);
+	elseif (type == "auto") then
+		SGI:LockPlayer(name);
+		SGI:UnregisterForWhisper(name);
+	elseif (type == "guilded") then
+		SGI:LockPlayer(name);
+		SGI:UnregisterForWhisper(name);
+	elseif (type == "already") then
+		SGI:LockPlayer(name);
+		SGI:UnregisterForWhisper(name);
+--[[	elseif (type == "join") then
+
+		if (CanEditOfficerNote()) then
+			for i = 1,GetNumGuildMembers() do
+				local n = GetGuildRosterInfo(i);
+				if (n == name) then
+					GuildRosterSetOfficerNote(i, date());
+				end
+			end
+		elseif (CanEditPublicNote()) then
+			for i = 1,GetNumGuildMembers() do
+				local n = GetGuildRosterInfo(i);
+				if (n == name) then
+					GuildRosterSetPublicNote(i, date());
+				end
+			end
+		end
+]]-- Optional, could cause disconnects if large guild.
+	elseif (type == "miss") then
+		if (SGI:IsSharing(name)) then
+			SGI:StopMassShare(name);
+			debug("Stopped mass share!");
+		end
+		SGI:print(format(SGI.L["Unable to invite %s. They will not be locked."],name));
+		SGI:UnlockPlayer(name);
+		SGI:UnregisterForWhisper(name);
+	elseif (type == "out") then
+		-- hmm...
+		if (SGI:IsSharing(name)) then
+			SGI:StopMassShare(name);
+			debug("Stopped mass share!");
+		end
+		SGI:RemoveQueued(name);
+	end
+
+end
+
+SGI:debug(">> System_Message.lua");
diff --git a/core/SGI_Utils.lua b/core/SGI_Utils.lua
index fad7031..701dcf6 100644
--- a/core/SGI_Utils.lua
+++ b/core/SGI_Utils.lua
@@ -1,59 +1,59 @@
-
-function SGI:FormatTime(T)
-	local R,S,M,H = ""
-	T = floor(T)
-	H = floor(T/3600)
-	M = floor((T-3600*H)/60)
-	S = T-(3600*H + 60*M)
-
-	if T <= 0 then
-		return L["less than 1 second"]
-	end
-
-	if H ~= 0 then
-		R =  R..H..L[" hours "]
-	end
-	if M ~= 0 then
-		R = R..M..L[" minutes "]
-	end
-	if S ~= 0 then
-		R = R..S..L[" seconds"]
-	end
-
-	return R
-end
-
-function SGI:CountTable(T)
-	local i = 0
-	if type(T) ~= "table" then
-		return i
-	end
-	for k,_ in pairs(T) do
-		i = i + 1
-	end
-	return i
-end
-
---[[
-function SGI.
-
-function SGI.
-
-function SGI.
-
-function SGI.
-
-function SGI.
-function SGI.
-
-function SGI.
-
-function SGI.
-function SGI.
-function SGI.
-function SGI.
-function SGI.
-function SGI.
-function SGI.
-function SGI.
-]]
\ No newline at end of file
+
+function SGI:FormatTime(T)
+	local R,S,M,H = ""
+	T = floor(T)
+	H = floor(T/3600)
+	M = floor((T-3600*H)/60)
+	S = T-(3600*H + 60*M)
+
+	if T <= 0 then
+		return L["less than 1 second"]
+	end
+
+	if H ~= 0 then
+		R =  R..H..L[" hours "]
+	end
+	if M ~= 0 then
+		R = R..M..L[" minutes "]
+	end
+	if S ~= 0 then
+		R = R..S..L[" seconds"]
+	end
+
+	return R
+end
+
+function SGI:CountTable(T)
+	local i = 0
+	if type(T) ~= "table" then
+		return i
+	end
+	for k,_ in pairs(T) do
+		i = i + 1
+	end
+	return i
+end
+
+--[[
+function SGI.
+
+function SGI.
+
+function SGI.
+
+function SGI.
+
+function SGI.
+function SGI.
+
+function SGI.
+
+function SGI.
+function SGI.
+function SGI.
+function SGI.
+function SGI.
+function SGI.
+function SGI.
+function SGI.
+]]
diff --git a/core/SuperScan.lua b/core/SuperScan.lua
index a4347be..948e1bf 100644
--- a/core/SuperScan.lua
+++ b/core/SuperScan.lua
@@ -1,677 +1,744 @@
-SGI.superScan = {};
-SGI.libWho = {};
-
-
-CreateFrame("Frame", "SGI_SUPER_SCAN");
-CreateFrame("Frame", "SGI_ANTI_SPAM_FRAME");
-CreateFrame("Frame", "SGI_WHISPER_QUEUE_FRAME");
-
-LibStub:GetLibrary("LibWho-2.0"):Embed(SGI.libWho);
-
-local start-- = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit;
-local stop-- = SGI_DATA[SGI_DATA_INDEX].settings.highLimit;
-local race-- = SGI_DATA[SGI_DATA_INDEX].settings.raceStart;
-local class-- = SGI_DATA[SGI_DATA_INDEX].settings.classStart;
-local interval-- = SGI_DATA[SGI_DATA_INDEX].settings.interval;
-
--- Fix for WhoLib bug
-local oldFlags;
-
-local superScanIntervalTime = 8;
-local superScanLast = 0;
-local superScanProgress = 1;
-local whoQueryList;
-local whoSent = false;
-local whoMaster = false;
-local scanInProgress = false;
-local shouldHideFriendsFrame = false;
-local SGI_QUEUE = {};
-local SGI_ANTI_SPAM = {};
-local SGI_TEMP_BAN = {};
-local whisperWaiting = {};
-local whisperQueue = {};
-local sessionTotal = 0;
-local amountScanned = 0;
-local amountGuildless = 0;
-local amountQueued = 0;
-local superScanLap = 1;
-
-local raceClassCombos = {
-	["Alliance"] = {
-		["Human"] = {
-			"Paladin",
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Warrior",
-			"Warlock",
-			"Death Knight",
-			"Monk",
-		},
-		["Draenei"] = {
-			"Hunter",
-			"Mage",
-			"Paladin",
-			"Priest",
-			"Shaman",
-			"Death Knight",
-			"Warrior",
-			"Monk",
-		},
-		["Gnome"] = {
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Warlock",
-			"Warrior",
-			"Death Knight",
-			"Monk",
-		},
-		["Dwarf"] = {
-			"Hunter",
-			"Mage",
-			"Paladin",
-			"Priest",
-			"Rogue",
-			"Shaman",
-			"Warlock",
-			"Warrior",
-			"Death Knight",
-			"Monk",
-		},
-		["Night Elf"] = {
-			"Druid",
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Warrior",
-			"Death Knight",
-			"Demon Hunter",
-			"Monk",
-		},
-		["Worgen"] = {
-			"Druid",
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Warlock",
-			"Warrior",
-			"Death Knight",
-		},
-		["Pandaren"] = {
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Shaman",
-			"Warrior",
-			"Monk",
-		},
-	},
-	["Horde"] = {
-		["Blood Elf"] = {
-			"Paladin",
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Warlock",
-			"Warrior",
-			"Death Knight",
-			"Demon Hunter",
-			"Monk",
-		},
-		["Orc"] = {
-			"Hunter",
-			"Mage",
-			"Rogue",
-			"Shaman",
-			"Warlock",
-			"Warrior",
-			"Death Knight",
-			"Monk",
-		},
-		["Goblin"] = {
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Shaman",
-			"Warlock",
-			"Warrior",
-			"Death Knight",
-		},
-		["Tauren"] = {
-			"Druid",
-			"Hunter",
-			"Paladin",
-			"Priest",
-			"Shaman",
-			"Warrior",
-			"Death Knight",
-			"Monk",
-		},
-		["Troll"] = {
-			"Druid",
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Shaman",
-			"Warlock",
-			"Warrior",
-			"Death Knight",
-			"Monk",
-		},
-		["Undead"] = {
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Warlock",
-			"Warrior",
-			"Death Knight",
-			"Monk",
-		},
-		["Pandaren"] = {
-			"Hunter",
-			"Mage",
-			"Priest",
-			"Rogue",
-			"Shaman",
-			"Warrior",
-			"Monk",
-		},
-	},
-}
-
-local GetTime = GetTime;
-local strfind = strfind;
-local strsub = strsub;
-local tonumber = tonumber;
-
-local L = SGI.L;
-
-function SGI:PickRandomWhisper()
-	local i = 0
-	local tbl = {}
-	for k,_ in pairs(SGI_DATA[SGI_DATA_INDEX].settings.whispers) do
-		i = i + 1
-		tbl[i] = SGI_DATA[SGI_DATA_INDEX].settings.whispers[k]
-	end
-	if #tbl == 0 then
-		return SGI_DATA[SGI_DATA_INDEX].settings.whisper
-	end
-	return tbl[random(#tbl)]
-end
-
-function SGI:FormatWhisper(msg, name)
-	local whisper = msg
-	if not msg then SGI:print("You have not set your whispers!") msg = "<NO WHISPER SET>" whisper = "<NO WHISPER SET>" end
-	if not name then name = "ExampleName" end
-	local guildName,guildLevel = GetGuildInfo(UnitName("Player"))--,GetGuildLevel()
-	if not guildName then guildName = "<InvalidName>" end
-	if not guildLevel then guildLevel = "<InvalidLevel>" end
-	if strfind(msg,"PLAYER") then
-		whisper = strsub(msg,1,strfind(msg,"PLAYER")-1)..name..strsub(msg,strfind(msg,"PLAYER")+6)
-	end
-	if strfind(whisper,"NAME") then
-		whisper = strsub(whisper,1,strfind(whisper,"NAME")-1)..guildName..strsub(whisper,strfind(whisper,"NAME")+4)
-	end
-	if strfind(whisper,"LEVEL") then
-		whisper = strsub(whisper,1,strfind(whisper,"LEVEL")-1)..guildLevel..strsub(whisper,strfind(whisper,"LEVEL")+5)
-	end
-	return whisper
-end
-
-local function QueueInvite(name,level,classFile,race,class,found)
-	SGI_QUEUE[name] = {
-		level = level,
-		class = class,
-		classFile = classFile,
-		race = race,
-		found = found,
-	}
-	GuildShield:IsShielded(name)
-end
-
-local function PutOnHold(name,level,classFile,race,class,found)
-	SGI_ANTI_SPAM[name] = {
-		level = level,
-		class = class,
-		classFile = classFile,
-		race = race,
-		found = found,
-	}
-	GuildShield:IsShielded(name)
-end
-
-SGI_ANTI_SPAM_FRAME.t = 0;
-SGI_ANTI_SPAM_FRAME:SetScript("OnUpdate", function()
-	if (SGI_ANTI_SPAM_FRAME.t < GetTime()) then
-		for k,_ in pairs(SGI_ANTI_SPAM) do
-			if (SGI_ANTI_SPAM[k].found + 4 < GetTime()) then
-				SGI_QUEUE[k] = SGI_ANTI_SPAM[k];
-				SGI_ANTI_SPAM[k] = nil;
-				amountQueued = amountQueued + 1;
-			end
-		end
-		SGI_ANTI_SPAM_FRAME.t = GetTime() + 0.5;
-	end
-end)
-
-SGI_WHISPER_QUEUE_FRAME.t = 0;
-SGI_WHISPER_QUEUE_FRAME:SetScript("OnUpdate", function()
-	if (SGI_WHISPER_QUEUE_FRAME.t < GetTime()) then
-
-		for k,_ in pairs(whisperQueue) do
-			if (whisperQueue[k].t < GetTime()) then
-				ChatIntercept:InterceptNextWhisper();
-				SendChatMessage(whisperQueue[k].msg, "WHISPER", nil, k);
-				whisperQueue[k] = nil;
-			end
-		end
-
-		SGI_WHISPER_QUEUE_FRAME.t = GetTime() + 0.5;
-
-	end
-end)
-
-local function ValidateName(player)
-	--Check:
-	-- Lock
-	-- filter
-	-- guild list
-
-	if (SGI_DATA.lock[player.name]) then
-		return false;
-	end
-
-	if (SGI_DATA.guildList[GetRealmName()][player.name]) then
-		return false;
-	end
-
-	if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ENABLE_FILTERS"] and not SGI:FilterPlayer(player)) then
-		return false;
-	end
-
-	return true;
-end
-
-local function TrimRealmName(name)
-	if (type(name) ~= "string") then SGI:debug("TrimRealmName: No name!") return end
-
-	local myRealm = GetRealmName();
-
-	if (type(myRealm) ~= "string") then SGI:debug("TrimRealmName: No realmName!") return end
-
-	if (strfind(name, myRealm)) then
-		if (strfind(name, "-")) then
-			local n = strsub(name,1,strfind(name,"-")-1);
-			return n;
-		end
-	end
-	return name;
-end
-
-local function WhoResultCallback(query, results, complete)
-	if (whoSent) then
-		whoSent = false;
-		SGI:debug("...got reply");
-
-		flags = oldFlags;
-
-		superScanProgress = superScanProgress + 1;
-		local ETR = (#whoQueryList - superScanProgress + 1) * superScanIntervalTime;
-		if (SuperScanFrame) then
-			SuperScanFrame.ETR = ETR;
-			SuperScanFrame.lastETR = GetTime();
-		end
-
-		local numResults = 0;
-
-		for _, result in pairs(results) do
-			amountScanned = amountScanned + 1;
-			numResults = numResults + 1;
-
-			result.Name = TrimRealmName(result.Name);
-
-			SGI:BroadcastVersion(result.Name)
-
-			if (result.Guild == "") then
-				local player = {
-					name = result.Name,
-					level = result.Level,
-					race = result.Race,
-					class = result.NoLocaleClass,
-				}
-				amountGuildless = amountGuildless + 1;
-				if (ValidateName(player)) then
-					PutOnHold(result.Name, result.Level, result.NoLocaleClass, result.Race, result.Class, GetTime());
-				end
-			end
-		end
-		SGI:debug("Scan result: "..numResults);
-	end
-end
-
-local function SuperScan()
-	if (GetTime() > superScanLast + superScanIntervalTime) then
-		if (superScanProgress == (#whoQueryList + 1)) then
-			superScanProgress = 1;
-			superScanLast = GetTime();
-			amountGuildless = 0;
-			sessionTotal = sessionTotal + amountScanned;
-			amountScanned = 0;
-		else
-			oldFlags = flags;
-			flags = nil;
-			--SendWho(tostring(whoQueryList[superScanProgress]))
-			SGI.libWho:Who(tostring(whoQueryList[superScanProgress]),{queue = SGI.libWho.WHOLIB_QUERY_QUIET, callback = WhoResultCallback});
-			whoSent = true;
-			superScanLast = GetTime();
-			SGI:debug("Sent query: "..whoQueryList[superScanProgress].."...");
-		end
-	end
-end
-
-local function CreateSuperScanQuery(start, stop, interval, class, race)
-
-	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ADV_SCAN"]) then
-		interval = 5;
-		class = 999;
-		race = 999;
-	end
-
-	local SGI_BREAK_POINT_SUPER_SCAN = 90;
-
-	whoQueryList = {};
-	local current = start;
-	local Classes = {
-			SGI.L["Death Knight"],
-			SGI.L["Demon Hunter"],
-			SGI.L["Druid"],
-			SGI.L["Hunter"],
-			SGI.L["Mage"],
-			SGI.L["Monk"],
-			SGI.L["Paladin"],
-			SGI.L["Priest"],
-			SGI.L["Rogue"],
-			SGI.L["Shaman"],
-			SGI.L["Warlock"],
-			SGI.L["Warrior"],
-	}
-	local Races = {}
-	if UnitFactionGroup("player") == "Horde" then
-		Races = {
-			SGI.L["Orc"],
-			SGI.L["Blood Elf"],
-			SGI.L["Undead"],
-			SGI.L["Troll"],
-			SGI.L["Goblin"],
-			SGI.L["Tauren"],
-			SGI.L["Pandaren"],
-		}
-	else
-		Races = {
-			SGI.L["Human"],
-			SGI.L["Dwarf"],
-			SGI.L["Worgen"],
-			SGI.L["Draenei"],
-			SGI.L["Night Elf"],
-			SGI.L["Gnome"],
-			SGI.L["Pandaren"],
-		}
-	end
-
-	if (start < SGI_BREAK_POINT_SUPER_SCAN) then
-		while (current + interval < ( (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN)) do
-
-			if (current + interval >= race and current + interval >= class) then
-				for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do
-					for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do
-						tinsert(whoQueryList, current.."- -"..(current + interval - 1).." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]);
-					end
-				end
-			elseif (current + interval >= race) then
-				for k, _ in pairs(Races) do
-					tinsert(whoQueryList, current.."- -"..(current + interval - 1).." r-"..Races[k]);
-				end
-			elseif (current + interval >= class) then
-				for k, _ in pairs(Classes) do
-					tinsert(whoQueryList, current.."- -"..(current + interval - 1).." c-"..Classes[k]);
-				end
-			else
-				tinsert(whoQueryList, current.."- -"..(current + interval - 1));
-			end
-
-			current = current + interval;
-		end
-
-		if ( current < ( (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN ) ) then
-			local t_stop = (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN;
-			if (t_stop >= race and t_stop >= class) then
-				for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do
-					for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do
-						tinsert(whoQueryList, current.."- -"..(t_stop).." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]);
-					end
-				end
-			elseif (t_stop >= race) then
-				for k, _ in pairs(Races) do
-					tinsert(whoQueryList, current.."- -"..(t_stop).." r-"..Races[k]);
-				end
-			elseif (t_stop >= class) then
-				for k, _ in pairs(Classes) do
-					tinsert(whoQueryList, current.."- -"..(t_stop).." c-"..Classes[k]);
-				end
-			else
-				tinsert(whoQueryList, current.."- -"..(t_stop));
-			end
-			current = t_stop + 1;
-		end
-	end
-	if (stop < current) then return end;
-
-	while (current <= stop) do
-		if (current >= race and current >= class) then
-			for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do
-				for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do
-					tinsert(whoQueryList, current.." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]);
-				end
-			end
-		elseif (current >= race) then
-			for k,_ in pairs(Races) do
-				tinsert(whoQueryList, current.." r-"..Races[k]);
-			end
-		elseif (current >= class) then
-			for k,_ in pairs(Classes) do
-				tinsert(whoQueryList, current.." c-"..Classes[k]);
-			end
-		else
-			tinsert(whoQueryList, current);
-		end
-		current = current + 1;
-	end
-end
-
-local function CanResume()
-	local s = SGI_DATA[SGI_DATA_INDEX].settings;
-	return (start == s.lowLimit and stop == s.highLimit and race == s.raceStart and class == s.classStart and interval == s.interval);
-end
-
-local function ResetSuperScan()
-	start = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit;
-	stop = SGI_DATA[SGI_DATA_INDEX].settings.highLimit;
-	race = SGI_DATA[SGI_DATA_INDEX].settings.raceStart;
-	class = SGI_DATA[SGI_DATA_INDEX].settings.classStart;
-	interval = SGI_DATA[SGI_DATA_INDEX].settings.interval;
-
-	amountGuildless = 0;
-	sessionTotal = sessionTotal + amountScanned;
-	amountScanned = 0;
-	superScanProgress = 1;
-	CreateSuperScanQuery(start, stop, interval, class, race);
-end
-
-function SGI:StartSuperScan()
-	if (not CanResume()) then
-		ResetSuperScan();
-	end
-
-	if (SuperScanFrame) then
-		SuperScanFrame.lastETR = GetTime();
-	end
-
-	scanInProgress = true;
-	SGI_SUPER_SCAN:SetScript("OnUpdate", SuperScan);
-end
-
-function SGI:StopSuperScan()
-
-	scanInProgress = false;
-	SGI_SUPER_SCAN:SetScript("OnUpdate", nil);
-	SGI:debug(FriendsFrame:IsShown());
-	--FriendsMicroButton:Click();
-	--FriendsFrameCloseButton:Click();
-end
-
-function SGI:RemoveQueued(name)
-	SGI:LockPlayer(name);
-	SGI_QUEUE[name] = nil;
-	SGI_ANTI_SPAM[name] = nil;
-
-	local nameTrim = TrimRealmName(name);
-
-	SGI_ANTI_SPAM[nameTrim] = nil
-	SGI_QUEUE[nameTrim] = nil;
-
-	SGI:debug("RemoveQueued(name) removed "..nameTrim);
-end
-
-function SGI:UnregisterForWhisper(name)
-	whisperWaiting[name] = nil;
-	whisperQueue[name] = nil;
-end
-
-function SGI:SendWhisper(message, name, delay)
-	whisperQueue[name] = {msg = message, t = delay + GetTime()};
-	whisperWaiting[name] = nil;
-end
-
-function SGI:RegisterForWhisper(name)
-	whisperWaiting[name] = true;
-end
-
-function SGI:IsRegisteredForWhisper(name)
-	return whisperWaiting[name];
-end
-
-
-
-function SGI:SendGuildInvite(button)
-	local name = self.player
-	if not name then name = next(SGI_QUEUE) button = "LeftButton" end
-	if not name then return end
-
-	if (SGI:IsLocked(name)) then
-		SGI:RemoveQueued(name);
-		return;
-	end
-
-	if (UnitIsInMyGuild(name)) then
-		SGI:LockPlayer(name);
-		SGI:RemoveQueued(name);
-		return;
-	end
-
-	if (button == "LeftButton") then
-
-		if (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 1) then
-
-			GuildInvite(name);
-			SGI:LockPlayer(name);
-			--SGI:print("Only Invite: "..name);
-
-		elseif (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 2) then
-
-			GuildInvite(name);
-			SGI:RegisterForWhisper(name);
-			SGI:LockPlayer(name);
-			--SGI:print("Invite, then whisper: "..name);
-
-		elseif (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 3) then
-
-			SGI:SendWhisper(SGI:FormatWhisper(SGI:PickRandomWhisper(), name), name, 4);
-			SGI:LockPlayer(name);
-			--SGI:print("Only whisper: "..name);
-
-		else
-			SGI:print(SGI.L["You need to specify the mode in which you wish to invite"])
-			SGI:print(SGI.L["Go to Options and select your Invite Mode"])
-		end
-		GuildShield:IsShielded(name);
-		SGI:LiveSync(name)
-	end
-
-	SGI:RemoveQueued(name);
-end
-
-function SGI:RemoveShielded(player)
-	SGI:debug(player);
-	if (not player) then  SGI:debug("Error: No player name provided!") return end
-
-	local playerTrim = TrimRealmName(player);
-
-	SGI_ANTI_SPAM[playerTrim] = nil
-	SGI_QUEUE[playerTrim] = nil;
-	SGI:LockPlayer(playerTrim);
-
-	SGI_ANTI_SPAM[player] = nil
-	SGI_QUEUE[player] = nil;
-	SGI:LockPlayer(player);
-	SGI:print("|cffffff00Removed |r|cff00A2FF"..player.."|r|cffffff00 because they are shielded.|r")
-end
-
-function SGI:GetNumQueued()
-	return SGI:CountTable(SGI_QUEUE);
-end
-
-function SGI:PurgeQueue()
-	SGI_QUEUE = {};
-	SGI_ANTI_SPAM = {};
-end
-
-function SGI:GetSuperScanETR()
-	if (whoQueryList) then
-		return SGI:FormatTime((#whoQueryList - superScanProgress + 1) * superScanIntervalTime);
-	else
-		return 0;
-	end
-end
-
-function SGI:GetSuperScanProgress()
-	return floor((superScanProgress - 1) / #whoQueryList);
-end
-
-function SGI:GetTotalScanTime()
-	return ((#whoQueryList - 1) * superScanIntervalTime);
-end
-
-function SGI:IsScanning()
-	return scanInProgress;
-end
-
-function SGI:GetInviteQueue()
-	return SGI_QUEUE;
-end
-
-function SGI:GetSuperScanStats()
-	return amountScanned, amountGuildless, amountQueued, sessionTotal;
-end
-
-
-
-SGI:debug(">> SuperScan.lua");
\ No newline at end of file
+SGI.superScan = {};
+SGI.libWho = {};
+
+
+CreateFrame("Frame", "SGI_SUPER_SCAN");
+CreateFrame("Frame", "SGI_ANTI_SPAM_FRAME");
+CreateFrame("Frame", "SGI_WHISPER_QUEUE_FRAME");
+
+LibStub:GetLibrary("LibWho-2.0"):Embed(SGI.libWho);
+
+local start-- = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit;
+local stop-- = SGI_DATA[SGI_DATA_INDEX].settings.highLimit;
+local race-- = SGI_DATA[SGI_DATA_INDEX].settings.raceStart;
+local class-- = SGI_DATA[SGI_DATA_INDEX].settings.classStart;
+local interval-- = SGI_DATA[SGI_DATA_INDEX].settings.interval;
+
+-- Fix for WhoLib bug
+local oldFlags;
+
+local superScanIntervalTime = 8;
+local superScanLast = 0;
+local superScanProgress = 1;
+local whoQueryList;
+local whoSent = false;
+local whoMaster = false;
+local scanInProgress = false;
+local shouldHideFriendsFrame = false;
+local SGI_QUEUE = {};
+local SGI_ANTI_SPAM = {};
+local SGI_TEMP_BAN = {};
+local whisperWaiting = {};
+local whisperQueue = {};
+local sessionTotal = 0;
+local amountScanned = 0;
+local amountGuildless = 0;
+local amountQueued = 0;
+local superScanLap = 1;
+
+local raceClassCombos = {
+	["Alliance"] = {
+		["Human"] = {
+			"Paladin",
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Warrior",
+			"Warlock",
+			"Death Knight",
+			"Monk",
+		},
+		["Draenei"] = {
+			"Hunter",
+			"Mage",
+			"Paladin",
+			"Priest",
+			"Shaman",
+			"Death Knight",
+			"Warrior",
+			"Monk",
+		},
+		["Gnome"] = {
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Warlock",
+			"Warrior",
+			"Death Knight",
+			"Monk",
+		},
+		["Dwarf"] = {
+			"Hunter",
+			"Mage",
+			"Paladin",
+			"Priest",
+			"Rogue",
+			"Shaman",
+			"Warlock",
+			"Warrior",
+			"Death Knight",
+			"Monk",
+		},
+		["Night Elf"] = {
+			"Druid",
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Warrior",
+			"Death Knight",
+			"Demon Hunter",
+			"Monk",
+		},
+		["Worgen"] = {
+			"Druid",
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Warlock",
+			"Warrior",
+			"Death Knight",
+		},
+		["Pandaren"] = {
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Shaman",
+			"Warrior",
+			"Monk",
+		},
+		["Void Elf"] = {
+			"Hunter",
+			"Mage",
+			"Monk",
+			"Priest",
+			"Rogue",
+			"Warlock",
+			"Warrior",
+		},
+		["Lightforged Draenei"] = {
+			"Hunter",
+			"Mage",
+			"Paladin",
+			"Priest",
+			"Warrior",
+		},
+		["Dark Iron Dwarf"] = {
+			"Hunter",
+			"Mage",
+			"Monk",
+			"Paladin",
+			"Priest",
+			"Rogue",
+			"Shaman",
+			"Warlock",
+			"Warrior",
+		},
+		["Kul'Tiran Human"] = { --not sure if this is correct naming
+			"Druid", -- only known class at the moment
+		},
+	},
+	["Horde"] = {
+		["Blood Elf"] = {
+			"Paladin",
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Warlock",
+			"Warrior",
+			"Death Knight",
+			"Demon Hunter",
+			"Monk",
+		},
+		["Orc"] = {
+			"Hunter",
+			"Mage",
+			"Rogue",
+			"Shaman",
+			"Warlock",
+			"Warrior",
+			"Death Knight",
+			"Monk",
+		},
+		["Goblin"] = {
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Shaman",
+			"Warlock",
+			"Warrior",
+			"Death Knight",
+		},
+		["Tauren"] = {
+			"Druid",
+			"Hunter",
+			"Paladin",
+			"Priest",
+			"Shaman",
+			"Warrior",
+			"Death Knight",
+			"Monk",
+		},
+		["Troll"] = {
+			"Druid",
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Shaman",
+			"Warlock",
+			"Warrior",
+			"Death Knight",
+			"Monk",
+		},
+		["Undead"] = {
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Warlock",
+			"Warrior",
+			"Death Knight",
+			"Monk",
+		},
+		["Pandaren"] = {
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Shaman",
+			"Warrior",
+			"Monk",
+		},
+		["Highmountain Tauren"] = {
+			"Druid",
+			"Hunter",
+			"Monk",
+			"Shaman",
+			"Warrior",
+		},
+		["Nightborne"] = {
+			"Hunter",
+			"Mage",
+			"Monk",
+			"Priest",
+			"Rogue",
+			"Warlock",
+			"Warrior",
+		},
+		["Mag'har Orc"] = {
+			"Hunter",
+			"Mage",
+			"Monk",
+			"Priest",
+			"Rogue",
+			"Shaman",
+			"Warrior",
+		},
+		["Zandalari Troll"] = {
+			"Druid",
+			"Hunter",
+			"Mage",
+			"Priest",
+			"Rogue",
+			"Shaman",
+			"Warlock",
+			"Warrior",
+		},
+	},
+}
+
+local GetTime = GetTime;
+local strfind = strfind;
+local strsub = strsub;
+local tonumber = tonumber;
+
+local L = SGI.L;
+
+function SGI:PickRandomWhisper()
+	local i = 0
+	local tbl = {}
+	for k,_ in pairs(SGI_DATA[SGI_DATA_INDEX].settings.whispers) do
+		i = i + 1
+		tbl[i] = SGI_DATA[SGI_DATA_INDEX].settings.whispers[k]
+	end
+	if #tbl == 0 then
+		return SGI_DATA[SGI_DATA_INDEX].settings.whisper
+	end
+	return tbl[random(#tbl)]
+end
+
+function SGI:FormatWhisper(msg, name)
+	local whisper = msg
+	if not msg then SGI:print("You have not set your whispers!") msg = "<NO WHISPER SET>" whisper = "<NO WHISPER SET>" end
+	if not name then name = "ExampleName" end
+	local guildName,guildLevel = GetGuildInfo(UnitName("Player"))--,GetGuildLevel()
+	if not guildName then guildName = "<InvalidName>" end
+	if not guildLevel then guildLevel = "<InvalidLevel>" end
+	if strfind(msg,"PLAYER") then
+		whisper = strsub(msg,1,strfind(msg,"PLAYER")-1)..name..strsub(msg,strfind(msg,"PLAYER")+6)
+	end
+	if strfind(whisper,"NAME") then
+		whisper = strsub(whisper,1,strfind(whisper,"NAME")-1)..guildName..strsub(whisper,strfind(whisper,"NAME")+4)
+	end
+	if strfind(whisper,"LEVEL") then
+		whisper = strsub(whisper,1,strfind(whisper,"LEVEL")-1)..guildLevel..strsub(whisper,strfind(whisper,"LEVEL")+5)
+	end
+	return whisper
+end
+
+local function QueueInvite(name,level,classFile,race,class,found)
+	SGI_QUEUE[name] = {
+		level = level,
+		class = class,
+		classFile = classFile,
+		race = race,
+		found = found,
+	}
+	--GuildShield:IsShielded(name)
+end
+
+local function PutOnHold(name,level,classFile,race,class,found)
+	SGI_ANTI_SPAM[name] = {
+		level = level,
+		class = class,
+		classFile = classFile,
+		race = race,
+		found = found,
+	}
+	--GuildShield:IsShielded(name)
+end
+
+SGI_ANTI_SPAM_FRAME.t = 0;
+SGI_ANTI_SPAM_FRAME:SetScript("OnUpdate", function()
+	if (SGI_ANTI_SPAM_FRAME.t < GetTime()) then
+		for k,_ in pairs(SGI_ANTI_SPAM) do
+			if (SGI_ANTI_SPAM[k].found + 4 < GetTime()) then
+				SGI_QUEUE[k] = SGI_ANTI_SPAM[k];
+				SGI_ANTI_SPAM[k] = nil;
+				amountQueued = amountQueued + 1;
+			end
+		end
+		SGI_ANTI_SPAM_FRAME.t = GetTime() + 0.5;
+	end
+end)
+
+SGI_WHISPER_QUEUE_FRAME.t = 0;
+SGI_WHISPER_QUEUE_FRAME:SetScript("OnUpdate", function()
+	if (SGI_WHISPER_QUEUE_FRAME.t < GetTime()) then
+
+		for k,_ in pairs(whisperQueue) do
+			if (whisperQueue[k].t < GetTime()) then
+				ChatIntercept:InterceptNextWhisper();
+				SendChatMessage(whisperQueue[k].msg, "WHISPER", nil, k);
+				whisperQueue[k] = nil;
+			end
+		end
+
+		SGI_WHISPER_QUEUE_FRAME.t = GetTime() + 0.5;
+
+	end
+end)
+
+local function ValidateName(player)
+	--Check:
+	-- Lock
+	-- filter
+	-- guild list
+
+	if (SGI_DATA.lock[player.name]) then
+		return false;
+	end
+
+	if (SGI_DATA.guildList[GetRealmName()][player.name]) then
+		return false;
+	end
+
+	if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ENABLE_FILTERS"] and not SGI:FilterPlayer(player)) then
+		return false;
+	end
+
+	return true;
+end
+
+local function TrimRealmName(name)
+	if (type(name) ~= "string") then SGI:debug("TrimRealmName: No name!") return end
+
+	local myRealm = GetRealmName();
+
+	if (type(myRealm) ~= "string") then SGI:debug("TrimRealmName: No realmName!") return end
+
+	if (strfind(name, myRealm)) then
+		if (strfind(name, "-")) then
+			local n = strsub(name,1,strfind(name,"-")-1);
+			return n;
+		end
+	end
+	return name;
+end
+
+local function WhoResultCallback(query, results, complete)
+	if (whoSent) then
+		whoSent = false;
+		SGI:debug("...got reply");
+
+		flags = oldFlags;
+
+		superScanProgress = superScanProgress + 1;
+		local ETR = (#whoQueryList - superScanProgress + 1) * superScanIntervalTime;
+		if (SuperScanFrame) then
+			SuperScanFrame.ETR = ETR;
+			SuperScanFrame.lastETR = GetTime();
+		end
+
+		local numResults = 0;
+
+		for _, result in pairs(results) do
+			amountScanned = amountScanned + 1;
+			numResults = numResults + 1;
+
+			result.Name = TrimRealmName(result.Name);
+
+			SGI:BroadcastVersion(result.Name)
+
+			if (result.Guild == "") then
+				local player = {
+					name = result.Name,
+					level = result.Level,
+					race = result.Race,
+					class = result.NoLocaleClass,
+				}
+				amountGuildless = amountGuildless + 1;
+				if (ValidateName(player)) then
+					PutOnHold(result.Name, result.Level, result.NoLocaleClass, result.Race, result.Class, GetTime());
+				end
+			end
+		end
+		SGI:debug("Scan result: "..numResults);
+	end
+end
+
+local function SuperScan()
+	if (GetTime() > superScanLast + superScanIntervalTime) then
+		if (superScanProgress == (#whoQueryList + 1)) then
+			superScanProgress = 1;
+			superScanLast = GetTime();
+			amountGuildless = 0;
+			sessionTotal = sessionTotal + amountScanned;
+			amountScanned = 0;
+		else
+			oldFlags = flags;
+			flags = nil;
+			--SendWho(tostring(whoQueryList[superScanProgress]))
+			SGI.libWho:Who(tostring(whoQueryList[superScanProgress]),{queue = SGI.libWho.WHOLIB_QUERY_QUIET, callback = WhoResultCallback});
+			whoSent = true;
+			superScanLast = GetTime();
+			SGI:debug("Sent query: "..whoQueryList[superScanProgress].."...");
+		end
+		superScanLast = GetTime();
+	end
+
+end
+
+local function CreateSuperScanQuery(start, stop, interval, class, race)
+
+	if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ADV_SCAN"]) then
+		interval = 5;
+		class = 999;
+		race = 999;
+	end
+
+	local SGI_BREAK_POINT_SUPER_SCAN = 90;
+
+	whoQueryList = {};
+	local current = start;
+	local Classes = {
+			SGI.L["Death Knight"],
+			SGI.L["Demon Hunter"],
+			SGI.L["Druid"],
+			SGI.L["Hunter"],
+			SGI.L["Mage"],
+			SGI.L["Monk"],
+			SGI.L["Paladin"],
+			SGI.L["Priest"],
+			SGI.L["Rogue"],
+			SGI.L["Shaman"],
+			SGI.L["Warlock"],
+			SGI.L["Warrior"],
+	}
+	local Races = {}
+	if UnitFactionGroup("player") == "Horde" then
+		Races = {
+			SGI.L["Orc"],
+			SGI.L["Blood Elf"],
+			SGI.L["Undead"],
+			SGI.L["Troll"],
+			SGI.L["Goblin"],
+			SGI.L["Tauren"],
+			SGI.L["Pandaren"],
+		}
+	else
+		Races = {
+			SGI.L["Human"],
+			SGI.L["Dwarf"],
+			SGI.L["Worgen"],
+			SGI.L["Draenei"],
+			SGI.L["Night Elf"],
+			SGI.L["Gnome"],
+			SGI.L["Pandaren"],
+		}
+	end
+
+	if (start < SGI_BREAK_POINT_SUPER_SCAN) then
+		while (current + interval < ( (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN)) do
+
+			if (current + interval >= race and current + interval >= class) then
+				for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do
+					for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do
+						tinsert(whoQueryList, current.."- -"..(current + interval - 1).." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]);
+					end
+				end
+			elseif (current + interval >= race) then
+				for k, _ in pairs(Races) do
+					tinsert(whoQueryList, current.."- -"..(current + interval - 1).." r-"..Races[k]);
+				end
+			elseif (current + interval >= class) then
+				for k, _ in pairs(Classes) do
+					tinsert(whoQueryList, current.."- -"..(current + interval - 1).." c-"..Classes[k]);
+				end
+			else
+				tinsert(whoQueryList, current.."- -"..(current + interval - 1));
+			end
+
+			current = current + interval;
+		end
+
+		if ( current < ( (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN ) ) then
+			local t_stop = (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN;
+			if (t_stop >= race and t_stop >= class) then
+				for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do
+					for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do
+						tinsert(whoQueryList, current.."- -"..(t_stop).." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]);
+					end
+				end
+			elseif (t_stop >= race) then
+				for k, _ in pairs(Races) do
+					tinsert(whoQueryList, current.."- -"..(t_stop).." r-"..Races[k]);
+				end
+			elseif (t_stop >= class) then
+				for k, _ in pairs(Classes) do
+					tinsert(whoQueryList, current.."- -"..(t_stop).." c-"..Classes[k]);
+				end
+			else
+				tinsert(whoQueryList, current.."- -"..(t_stop));
+			end
+			current = t_stop + 1;
+		end
+	end
+	if (stop < current) then return end;
+
+	while (current <= stop) do
+		if (current >= race and current >= class) then
+			for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do
+				for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do
+					tinsert(whoQueryList, current.." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]);
+				end
+			end
+		elseif (current >= race) then
+			for k,_ in pairs(Races) do
+				tinsert(whoQueryList, current.." r-"..Races[k]);
+			end
+		elseif (current >= class) then
+			for k,_ in pairs(Classes) do
+				tinsert(whoQueryList, current.." c-"..Classes[k]);
+			end
+		else
+			tinsert(whoQueryList, current);
+		end
+		current = current + 1;
+	end
+end
+
+local function CanResume()
+	local s = SGI_DATA[SGI_DATA_INDEX].settings;
+	return (start == s.lowLimit and stop == s.highLimit and race == s.raceStart and class == s.classStart and interval == s.interval);
+end
+
+local function ResetSuperScan()
+	start = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit;
+	stop = SGI_DATA[SGI_DATA_INDEX].settings.highLimit;
+	race = SGI_DATA[SGI_DATA_INDEX].settings.raceStart;
+	class = SGI_DATA[SGI_DATA_INDEX].settings.classStart;
+	interval = SGI_DATA[SGI_DATA_INDEX].settings.interval;
+
+	amountGuildless = 0;
+	sessionTotal = sessionTotal + amountScanned;
+	amountScanned = 0;
+	superScanProgress = 1;
+	CreateSuperScanQuery(start, stop, interval, class, race);
+end
+
+function SGI:StartSuperScan()
+	if (not CanResume()) then
+		ResetSuperScan();
+	end
+
+	if (SuperScanFrame) then
+		SuperScanFrame.lastETR = GetTime();
+	end
+
+	scanInProgress = true;
+	SGI_SUPER_SCAN:SetScript("OnUpdate", SuperScan);
+end
+
+function SGI:StopSuperScan()
+
+	scanInProgress = false;
+	SGI_SUPER_SCAN:SetScript("OnUpdate", nil);
+	SGI:debug(FriendsFrame:IsShown());
+	--FriendsMicroButton:Click();
+	--FriendsFrameCloseButton:Click();
+end
+
+function SGI:RemoveQueued(name)
+	SGI:LockPlayer(name);
+	SGI_QUEUE[name] = nil;
+	SGI_ANTI_SPAM[name] = nil;
+
+	local nameTrim = TrimRealmName(name);
+
+	SGI_ANTI_SPAM[nameTrim] = nil
+	SGI_QUEUE[nameTrim] = nil;
+
+	SGI:debug("RemoveQueued(name) removed "..nameTrim);
+end
+
+function SGI:UnregisterForWhisper(name)
+	whisperWaiting[name] = nil;
+	whisperQueue[name] = nil;
+end
+
+function SGI:SendWhisper(message, name, delay)
+	whisperQueue[name] = {msg = message, t = delay + GetTime()};
+	whisperWaiting[name] = nil;
+end
+
+function SGI:RegisterForWhisper(name)
+	whisperWaiting[name] = true;
+end
+
+function SGI:IsRegisteredForWhisper(name)
+	return whisperWaiting[name];
+end
+
+
+
+function SGI:SendGuildInvite(button)
+	local name = self.player
+	if not name then name = next(SGI_QUEUE) button = "LeftButton" end
+	if not name then return end
+
+	if (SGI:IsLocked(name)) then
+		SGI:RemoveQueued(name);
+		return;
+	end
+
+	if (UnitIsInMyGuild(name)) then
+		SGI:LockPlayer(name);
+		SGI:RemoveQueued(name);
+		return;
+	end
+
+	if (button == "LeftButton") then
+
+		if (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 1) then
+
+			GuildInvite(name);
+			SGI:LockPlayer(name);
+			--SGI:print("Only Invite: "..name);
+
+		elseif (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 2) then
+
+			GuildInvite(name);
+			SGI:RegisterForWhisper(name);
+			SGI:LockPlayer(name);
+			--SGI:print("Invite, then whisper: "..name);
+
+		elseif (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 3) then
+
+			SGI:SendWhisper(SGI:FormatWhisper(SGI:PickRandomWhisper(), name), name, 4);
+			SGI:LockPlayer(name);
+			--SGI:print("Only whisper: "..name);
+
+		else
+			SGI:print(SGI.L["You need to specify the mode in which you wish to invite"])
+			SGI:print(SGI.L["Go to Options and select your Invite Mode"])
+		end
+		--GuildShield:IsShielded(name);
+		SGI:LiveSync(name)
+	end
+
+	SGI:RemoveQueued(name);
+end
+
+function SGI:RemoveShielded(player)
+	SGI:debug(player);
+	if (not player) then  SGI:debug("Error: No player name provided!") return end
+
+	local playerTrim = TrimRealmName(player);
+
+	SGI_ANTI_SPAM[playerTrim] = nil
+	SGI_QUEUE[playerTrim] = nil;
+	SGI:LockPlayer(playerTrim);
+
+	SGI_ANTI_SPAM[player] = nil
+	SGI_QUEUE[player] = nil;
+	SGI:LockPlayer(player);
+	SGI:print("|cffffff00Removed |r|cff00A2FF"..player.."|r|cffffff00 because they are shielded.|r")
+end
+
+function SGI:GetNumQueued()
+	return SGI:CountTable(SGI_QUEUE);
+end
+
+function SGI:PurgeQueue()
+	SGI_QUEUE = {};
+	SGI_ANTI_SPAM = {};
+end
+
+function SGI:GetSuperScanETR()
+	if (whoQueryList) then
+		return SGI:FormatTime((#whoQueryList - superScanProgress + 1) * superScanIntervalTime);
+	else
+		return 0;
+	end
+end
+
+function SGI:GetSuperScanProgress()
+	return floor((superScanProgress - 1) / #whoQueryList);
+end
+
+function SGI:GetTotalScanTime()
+	return ((#whoQueryList - 1) * superScanIntervalTime);
+end
+
+function SGI:IsScanning()
+	return scanInProgress;
+end
+
+function SGI:GetInviteQueue()
+	return SGI_QUEUE;
+end
+
+function SGI:GetSuperScanStats()
+	return amountScanned, amountGuildless, amountQueued, sessionTotal;
+end
+
+
+
+SGI:debug(">> SuperScan.lua");
diff --git a/libs/Alerts/Alerts.lua b/libs/Alerts/Alerts.lua
index 775b063..1734f97 100644
--- a/libs/Alerts/Alerts.lua
+++ b/libs/Alerts/Alerts.lua
@@ -1,56 +1,56 @@
-Alerter = CreateFrame("Frame")
-Alerter.items = {}
-Alerter.update = 0
-Alerter.free = {
-	[1] = true,
-	[2] = true,
-	[3] = true,
-	[4] = true,
-	[5] = true,
-}
-Alerter.wipe = {}
-
-local Alerts = {}
-
-do
-	yOfs = 250
-	for i = 1,5 do
-		Alerter.items[i] = Alerter:CreateFontString()
-		Alerter.items[i]:SetFont("Fonts\\FRIZQT__.TTF",40,"OUTLINE")
-		Alerter.items[i]:SetPoint("CENTER",ALERT,"CENTER",0,yOfs)
-		yOfs = yOfs - 50
-	end
-end
-
-function Alerter:SendAlert(msg,duration)
-	tinsert(Alerts,{m=msg,t=GetTime()+duration})
-end
-
-Alerter:SetScript("OnUpdate",function()
-	if Alerter.update < GetTime() then
-
-		for k,_ in pairs(Alerter.wipe) do
-			if Alerter.wipe[k] < GetTime() then
-				Alerter.items[k]:SetText("")
-				Alerter.wipe[k] = nil
-				Alerter.free[k] = true
-			end
-		end
-
-
-		for k,_ in pairs(Alerts) do
-			for j,_ in pairs(Alerter.free) do
-				if Alerter.free[j] then
-					Alerter.items[j]:SetText(Alerts[k].m)
-					Alerter.wipe[j] = Alerts[k].t
-					Alerter.free[j] = false
-					Alerts[k] = nil
-					break
-				end
-			end
-		end
-
-
-		Alerter.update = GetTime() + 0.2
-	end
-end)
\ No newline at end of file
+Alerter = CreateFrame("Frame")
+Alerter.items = {}
+Alerter.update = 0
+Alerter.free = {
+	[1] = true,
+	[2] = true,
+	[3] = true,
+	[4] = true,
+	[5] = true,
+}
+Alerter.wipe = {}
+
+local Alerts = {}
+
+do
+	yOfs = 250
+	for i = 1,5 do
+		Alerter.items[i] = Alerter:CreateFontString()
+		Alerter.items[i]:SetFont("Fonts\\FRIZQT__.TTF",40,"OUTLINE")
+		Alerter.items[i]:SetPoint("CENTER",ALERT,"CENTER",0,yOfs)
+		yOfs = yOfs - 50
+	end
+end
+
+function Alerter:SendAlert(msg,duration)
+	tinsert(Alerts,{m=msg,t=GetTime()+duration})
+end
+
+Alerter:SetScript("OnUpdate",function()
+	if Alerter.update < GetTime() then
+
+		for k,_ in pairs(Alerter.wipe) do
+			if Alerter.wipe[k] < GetTime() then
+				Alerter.items[k]:SetText("")
+				Alerter.wipe[k] = nil
+				Alerter.free[k] = true
+			end
+		end
+
+
+		for k,_ in pairs(Alerts) do
+			for j,_ in pairs(Alerter.free) do
+				if Alerter.free[j] then
+					Alerter.items[j]:SetText(Alerts[k].m)
+					Alerter.wipe[j] = Alerts[k].t
+					Alerter.free[j] = false
+					Alerts[k] = nil
+					break
+				end
+			end
+		end
+
+
+		Alerter.update = GetTime() + 0.2
+	end
+end)
diff --git a/libs/ChatIntercept/ChatIntercept.lua b/libs/ChatIntercept/ChatIntercept.lua
index 1022b86..33a53dc 100644
--- a/libs/ChatIntercept/ChatIntercept.lua
+++ b/libs/ChatIntercept/ChatIntercept.lua
@@ -1,124 +1,127 @@
--- Format: ["SYSTEM"] = { pattern1, pattern2, pattern3, ...}
-local messagesToHide = {
-	ERR_GUILD_INVITE_S,
-	ERR_GUILD_DECLINE_S,
-	ERR_ALREADY_IN_GUILD_S,
-	ERR_ALREADY_INVITED_TO_GUILD_S,
-	ERR_GUILD_DECLINE_AUTO_S,
-	ERR_GUILD_PLAYER_NOT_FOUND_S,
-	ERR_CHAT_PLAYER_NOT_FOUND_S,
-}
-
-local RealmCleanup = {
-	ERR_CHAT_PLAYER_NOT_FOUND_S,
-}
-
-local chatFilters = {}
-local OnInt = {}
-local WhisperFilterActive = false;
-
-local function check(msg)
-	local place
-	local n
-	local name
-	for k,_ in pairs(messagesToHide) do
-		place = strfind(messagesToHide[k],"%s",1,true)
-		if place then
-			name = strfind(msg," ",place,true)
-			if name then
-				n = strsub(msg,place,name-1)
-				if format(messagesToHide[k],n) == msg then
-					return true
-				else
-					n = strsub(msg,place,name-2)
-					if format(messagesToHide[k],n) == msg then
-						return true
-					end
-				end
-			end
-		end
-	end
-end
-
-local function check2(msg)
-	local place
-	local n
-	local name
-	for k,_ in pairs(RealmCleanup) do
-		place = strfind(RealmCleanup[k],"%s",1,true)
-		if place then
-			name = strfind(msg," ",place,true)
-			if name then
-				n = strsub(msg,place,name-1)
-				if format(RealmCleanup[k],n) == msg then
-					return true
-				else
-					n = strsub(msg,place,name-2)
-					if format(RealmCleanup[k],n) == msg then
-						return true
-					end
-				end
-			end
-		end
-	end
-end
-
-local function HideOutWhispers(self, event, msg, sender)
-	if (sender == UnitName("player")) then
-		ChatFrame_RemoveMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers);
-		SGI:debug("Blocked outgoing whisper!");
-		return true;
-	end
-end
-
-local function HideSystemMessage(self, event, msg)
-	if (check(msg)) then
-		SGI:debug("Blocked message: "..msg);
-		return true;
-	end
-end
-
-local function HideRealmConflictMessage(self, event, msg)
-	if (check2(msg)) then
-		SGI:debug("Blocked message: "..msg.." from check2()");
-		return true;
-	end
-end
-
-ChatIntercept = {}
-function ChatIntercept:StateSystem(on)
-	if (on) then
-		ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", HideSystemMessage);
-		print("|cffffff00ChatIntercept [|r|cff16ABB5System Messages|r|cffffff00] is now |r|cff00ff00ACTIVE|r");
-	else
-		ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM", HideSystemMessage);
-		print("|cffffff00ChatIntercept [|r|cff16ABB5System Messages|r|cffffff00] is now |r|cffff0000INACTIVE|r");
-	end
-end
-
-function ChatIntercept:StateRealm(state)
-	if (state) then
-		ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", HideRealmConflictMessage);
-		SGI:debug("Blocking realm conflict messages");
-	else
-		ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM",HideRealmConflictMessage);
-		SGI:debug("Not blocking realm conflict messages");
-	end
-end
-
-function ChatIntercept:StateWhisper(on)
-	WhisperFilterActive = on;
-	if (on) then
-		--ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers);
-		print("|cffffff00ChatIntercept [|r|cff16ABB5Whispers|r|cffffff00] is now |r|cff00ff00ACTIVE|r");
-	else
-		--ChatFrame_RemoveMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers);
-		print("|cffffff00ChatIntercept [|r|cff16ABB5Whispers|r|cffffff00] is now |r|cffff0000INACTIVE|r");
-	end
-end
-
-function ChatIntercept:InterceptNextWhisper()
-	if (WhisperFilterActive) then
-		ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers);
-	end
-end
\ No newline at end of file
+-- Format: ["SYSTEM"] = { pattern1, pattern2, pattern3, ...}
+local messagesToHide = {
+	ERR_GUILD_INVITE_S,
+	ERR_GUILD_DECLINE_S,
+	ERR_ALREADY_IN_GUILD_S,
+	ERR_ALREADY_INVITED_TO_GUILD_S,
+	ERR_GUILD_DECLINE_AUTO_S,
+	ERR_GUILD_PLAYER_NOT_FOUND_S,
+	ERR_CHAT_PLAYER_NOT_FOUND_S,
+}
+
+local RealmCleanup = {
+	ERR_CHAT_PLAYER_NOT_FOUND_S,
+}
+
+local chatFilters = {}
+local OnInt = {}
+local WhisperFilterActive = false;
+
+local function check(msg)
+	local place
+	local n
+	local name
+	for k,_ in pairs(messagesToHide) do
+		place = strfind(messagesToHide[k],"%s",1,true)
+		if place then
+			name = strfind(msg," ",place,true)
+			if name then
+				n = strsub(msg,place,name-1)
+				if format(messagesToHide[k],n) == msg then
+					return true
+				else
+					n = strsub(msg,place,name-2)
+					if format(messagesToHide[k],n) == msg then
+						return true
+					end
+				end
+			end
+		end
+	end
+end
+
+local function check2(msg)
+	local place
+	local n
+	local name
+	for k,_ in pairs(RealmCleanup) do
+		place = strfind(RealmCleanup[k],"%s",1,true)
+		if place then
+			name = strfind(msg," ",place,true)
+			if name then
+				n = strsub(msg,place,name-1)
+				if format(RealmCleanup[k],n) == msg then
+					return true
+				else
+					n = strsub(msg,place,name-2)
+					if format(RealmCleanup[k],n) == msg then
+						return true
+					end
+				end
+			end
+		end
+	end
+end
+
+local function HideOutWhispers(self, event, msg, sender)
+	if (sender == UnitName("player")) then
+		ChatFrame_RemoveMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers);
+		SGI:debug("Blocked outgoing whisper!");
+		return true;
+	end
+end
+
+local function HideSystemMessage(self, event, msg)
+	if (check(msg)) then
+		SGI:debug("Blocked message: "..msg);
+		return true;
+	end
+end
+
+local function HideRealmConflictMessage(self, event, msg)
+	if (check2(msg)) then
+		SGI:debug("Blocked message: "..msg.." from check2()");
+		return true;
+	end
+end
+
+ChatIntercept = {}
+function ChatIntercept:StateSystem(on)
+	if (on) then
+		ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", HideSystemMessage);
+--		print("|cffffff00ChatIntercept [|r|cff16ABB5System Messages|r|cffffff00] is now |r|cff00ff00ACTIVE|r");
+	else
+		ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM", HideSystemMessage);
+--		print("|cffffff00ChatIntercept [|r|cff16ABB5System Messages|r|cffffff00] is now |r|cffff0000INACTIVE|r");
+	end
+end
+
+function ChatIntercept:StateRealm(state)
+	if (state) then
+		ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", HideRealmConflictMessage);
+--		SGI:debug("Blocking realm conflict messages");
+	else
+		ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM",HideRealmConflictMessage);
+--		SGI:debug("Not blocking realm conflict messages");
+	end
+end
+
+function ChatIntercept:StateWhisper(on)
+
+	if (on) then
+		ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers);
+			WhisperFilterActive = on;
+--		print("|cffffff00ChatIntercept [|r|cff16ABB5Whispers|r|cffffff00] is now |r|cff00ff00ACTIVE|r");
+	else
+		ChatFrame_RemoveMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers);
+			WhisperFilterActive = nill;
+--		print("|cffffff00ChatIntercept [|r|cff16ABB5Whispers|r|cffffff00] is now |r|cffff0000INACTIVE|r");
+	end
+end
+
+function ChatIntercept:InterceptNextWhisper()
+
+	if (WhisperFilterActive) then
+		ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers);
+	end
+end
diff --git a/libs/LibWho-2.0/Changelog-LibWho-2.0-2.0.146.txt b/libs/LibWho-2.0/Changelog-LibWho-2.0-2.0.146.txt
index 802fe25..9cbfe5b 100644
--- a/libs/LibWho-2.0/Changelog-LibWho-2.0-2.0.146.txt
+++ b/libs/LibWho-2.0/Changelog-LibWho-2.0-2.0.146.txt
@@ -1,25 +1,25 @@
-------------------------------------------------------------------------
-r146 | mysticalos | 2015-02-24 16:45:37 +0000 (Tue, 24 Feb 2015) | 1 line
-Changed paths:
-   A /tags/2.0.146 (from /trunk:145)
-
-Tagging as 2.0.146
-------------------------------------------------------------------------
-r145 | MysticalOS | 2015-02-24 16:43:23 +0000 (Tue, 24 Feb 2015) | 1 line
-Changed paths:
-   M /trunk/LibWho-2.0.toc
-
-ToC
-------------------------------------------------------------------------
-r143 | sylvanaar | 2015-02-01 17:28:35 +0000 (Sun, 01 Feb 2015) | 1 line
-Changed paths:
-   M /trunk/LibWho-2.0/LibWho-2.0.lua
-
-Fix compatibility error with Swatter. Issue #25
-------------------------------------------------------------------------
-r142 | sylvanaar | 2015-02-01 17:26:11 +0000 (Sun, 01 Feb 2015) | 1 line
-Changed paths:
-   M /trunk/LibWho-2.0/LibWho-2.0.lua
-
-Fix 0/1 false/true errors. Issue #24
-------------------------------------------------------------------------
+------------------------------------------------------------------------
+r146 | mysticalos | 2015-02-24 16:45:37 +0000 (Tue, 24 Feb 2015) | 1 line
+Changed paths:
+   A /tags/2.0.146 (from /trunk:145)
+
+Tagging as 2.0.146
+------------------------------------------------------------------------
+r145 | MysticalOS | 2015-02-24 16:43:23 +0000 (Tue, 24 Feb 2015) | 1 line
+Changed paths:
+   M /trunk/LibWho-2.0.toc
+
+ToC
+------------------------------------------------------------------------
+r143 | sylvanaar | 2015-02-01 17:28:35 +0000 (Sun, 01 Feb 2015) | 1 line
+Changed paths:
+   M /trunk/LibWho-2.0/LibWho-2.0.lua
+
+Fix compatibility error with Swatter. Issue #25
+------------------------------------------------------------------------
+r142 | sylvanaar | 2015-02-01 17:26:11 +0000 (Sun, 01 Feb 2015) | 1 line
+Changed paths:
+   M /trunk/LibWho-2.0/LibWho-2.0.lua
+
+Fix 0/1 false/true errors. Issue #24
+------------------------------------------------------------------------
diff --git a/libs/LibWho-2.0/LibWho-2.0.toc b/libs/LibWho-2.0/LibWho-2.0.toc
index 4a2fe9e..0f8ae68 100644
--- a/libs/LibWho-2.0/LibWho-2.0.toc
+++ b/libs/LibWho-2.0/LibWho-2.0.toc
@@ -1,23 +1,23 @@
-## Interface: 60100
-## X-Curse-Packaged-Version: 2.0.146
-## X-Curse-Project-Name: WhoLib
-## X-Curse-Project-ID: wholib
-## X-Curse-Repository-ID: wow/wholib/mainline
-
-## Title: Lib: LibWho-2.0
-## Notes: Queing of /who and SendWho() queries and a much better interface (see docs), with gurantee to be executed & callback.
-## Version: 2.0.145
-## Author: ALeX Kazik, Sylvanaar, Pazza
-## eMail: wow@kazik.de
-## X-Category: Library
-
-## OptionalDeps: LibStub, CallbackHandler-1.0
-
-## LoadOnDemand: 1
-
-#@no-lib-strip@
-libs\LibStub\LibStub.lua
-libs\CallbackHandler-1.0\CallbackHandler-1.0.lua
-#@end-no-lib-strip@
-
-LibWho-2.0\LibWho-2.0.lua
+## Interface: 60100
+## X-Curse-Packaged-Version: 2.0.146
+## X-Curse-Project-Name: WhoLib
+## X-Curse-Project-ID: wholib
+## X-Curse-Repository-ID: wow/wholib/mainline
+
+## Title: Lib: LibWho-2.0
+## Notes: Queing of /who and SendWho() queries and a much better interface (see docs), with gurantee to be executed & callback.
+## Version: 2.0.145
+## Author: ALeX Kazik, Sylvanaar, Pazza
+## eMail: wow@kazik.de
+## X-Category: Library
+
+## OptionalDeps: LibStub, CallbackHandler-1.0
+
+## LoadOnDemand: 1
+
+#@no-lib-strip@
+libs\LibStub\LibStub.lua
+libs\CallbackHandler-1.0\CallbackHandler-1.0.lua
+#@end-no-lib-strip@
+
+LibWho-2.0\LibWho-2.0.lua
diff --git a/libs/LibWho-2.0/LibWho-2.0/LibWho-2.0.lua b/libs/LibWho-2.0/LibWho-2.0/LibWho-2.0.lua
index 64c859b..47d5780 100644
--- a/libs/LibWho-2.0/LibWho-2.0/LibWho-2.0.lua
+++ b/libs/LibWho-2.0/LibWho-2.0/LibWho-2.0.lua
@@ -1,948 +1,948 @@
----
---- check for an already loaded old WhoLib
----
-
-if WhoLibByALeX or WhoLib then
-	-- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail!
-	error("an other WhoLib is already running - disable them first!\n")
-	return
-end -- if
-
----
---- check version
----
-
-assert(LibStub, "LibWho-2.0 requires LibStub")
-
-
-local major_version = 'LibWho-2.0'
-local minor_version = tonumber("145") or 99999
-
-local lib = LibStub:NewLibrary(major_version, minor_version)
-
-
-if not lib then
-	return	-- already loaded and no upgrade necessary
-end
-
-lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
-local callbacks = lib.callbacks
-
-local am = {}
-local om = getmetatable(lib)
-if om then
-	for k, v in pairs(om) do am[k] = v end
-end
-am.__tostring = function() return major_version end
-setmetatable(lib, am)
-
-local function dbgfunc(...) if lib.Debug then print(...) end end
-local function NOP() return end
-local dbg = NOP
-
----
---- initalize base
----
-
-if type(lib['hooked']) ~= 'table' then
-	lib['hooked'] = {}
-end -- if
-
-if type(lib['hook']) ~= 'table' then
-	lib['hook'] = {}
-end -- if
-
-if type(lib['events']) ~= 'table' then
-	lib['events'] = {}
-end -- if
-
-if type(lib['embeds']) ~= 'table' then
-	lib['embeds'] = {}
-end -- if
-
-if type(lib['frame']) ~= 'table' then
-	lib['frame'] = CreateFrame('Frame', major_version);
-end -- if
-lib['frame']:Hide()
-
-lib.Queue = {[1]={}, [2]={}, [3]={}}
-lib.WhoInProgress = false
-lib.Result = nil
-lib.Args = nil
-lib.Total = nil
-lib.Quiet = nil
-lib.Debug = false
-lib.Cache = {}
-lib.CacheQueue = {}
-lib.SetWhoToUIState = false
-
-
-lib.MinInterval = 2.5
-lib.MaxInterval = 10
-
----
---- locale
----
-
-if (GetLocale() == "ruRU") then
-	lib.L = {
-		['console_queued'] = 'Добавлено в очередь "/who %s"',
-		['console_query'] = 'Результат "/who %s"',
-		['gui_wait'] = '- Пожалуйста подождите -',
-	}
-else
-	-- enUS is the default
-	lib.L = {
-		['console_queued'] = 'Added "/who %s" to queue',
-		['console_query'] = 'Result of "/who %s"',
-		['gui_wait'] = '- Please Wait -',
-	}
-end -- if
-
-
----
---- external functions/constants
----
-
-lib['external'] = {
-	'WHOLIB_QUEUE_USER',
-	'WHOLIB_QUEUE_QUIET',
-	'WHOLIB_QUEUE_SCANNING',
-	'WHOLIB_FLAG_ALWAYS_CALLBACK',
-	'Who',
-	'UserInfo',
-	'CachedUserInfo',
-	'GetWhoLibDebug',
-	'SetWhoLibDebug',
---	'RegisterWhoLibEvent',
-}
-
--- queues
-lib['WHOLIB_QUEUE_USER'] = 1
-lib['WHOLIB_QUEUE_QUIET'] = 2
-lib['WHOLIB_QUEUE_SCANNING'] = 3
-
-
-
-local queue_all = {
-	[1] = 'WHOLIB_QUEUE_USER',
-	[2] = 'WHOLIB_QUEUE_QUIET',
-	[3] = 'WHOLIB_QUEUE_SCANNING',
-}
-
-local queue_quiet = {
-	[2] = 'WHOLIB_QUEUE_QUIET',
-	[3] = 'WHOLIB_QUEUE_SCANNING',
-}
-
--- bit masks!
-lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1
-
-function lib:Reset()
-    self.Queue = {[1]={}, [2]={}, [3]={}}
-    self.Cache = {}
-    self.CacheQueue = {}
-end
-
-function lib.Who(defhandler, query, opts)
-	local self, args, usage = lib, {}, 'Who(query, [opts])'
-
-	args.query = self:CheckArgument(usage, 'query', 'string', query)
-	opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
-	args.queue = self:CheckPreset(usage, 'opts.queue', queue_all, opts.queue, self.WHOLIB_QUEUE_SCANNING)
-	args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
-	args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler)
-	-- now args - copied and verified from opts
-
-	if args.queue == self.WHOLIB_QUEUE_USER then
-		if WhoFrame:IsShown() then
-			self:GuiWho(args.query)
-		else
-			self:ConsoleWho(args.query)
-		end
-	else
-		self:AskWho(args)
-	end
-end
-
-local function ignoreRealm(name)
-	local _, realm = string.split("-", name)
- 	local connectedServers = GetAutoCompleteRealms()
- 	if connectedServers then
-		for i = 1, #connectedServers do
- 	 		if realm == connectedServers[i] then return false end
-		end
- 	end
-    return true
-end
-
-function lib.UserInfo(defhandler, name, opts)
-	local self, args, usage = lib, {}, 'UserInfo(name, [opts])'
-	local now = time()
-
-    name = self:CheckArgument(usage, 'name', 'string', name)
-    if name:len() == 0 then return end
-
-    --There is no api to tell connected realms from cross realm by name. As such, we check known connections table before excluding who inquiry
-    --UnitRealmRelationship and UnitIsSameServer don't work with "name". They require unitID so they are useless here
-    if name:find("%-") and ignoreRealm(name) then return end
-
-	args.name = self:CapitalizeInitial(name)
-	opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
-	args.queue = self:CheckPreset(usage, 'opts.queue', queue_quiet, opts.queue, self.WHOLIB_QUEUE_SCANNING)
-	args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
-	args.timeout = self:CheckArgument(usage, 'opts.timeout', 'number', opts.timeout, 5)
-	args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback,  opts.handler, defhandler)
-
-	-- now args - copied and verified from opts
-	local cachedName = self.Cache[args.name]
-
-	if(cachedName ~= nil)then
-		-- user is in cache
-		if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then
-			-- cache is valid and timeout is in range
-			--dbg('Info(' .. args.name ..') returned immedeatly')
-			if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then
-				self:RaiseCallback(args, cachedName.data)
-				return false
-			else
-				return self:DupAll(self:ReturnUserInfo(args.name))
-			end
-		elseif(cachedName.valid == false)then
-			-- query is already running (first try)
-			if(args.callback ~= nil)then
-				tinsert(cachedName.callback, args)
-			end
-			--dbg('Info(' .. args.name ..') returned cause it\'s already searching')
-			return nil
-		end
-	else
-		self.Cache[args.name] = {valid=false, inqueue=false, callback={}, data={Name = args.name}, last=now }
-	end
-
-	local cachedName = self.Cache[args.name]
-
-	if(cachedName.inqueue)then
-		-- query is running!
-		if(args.callback ~= nil)then
-			tinsert(cachedName.callback, args)
-		end
-		dbg('Info(' .. args.name ..') returned cause it\'s already searching')
-		return nil
-	end
-	if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon
-    if args.name and args.name:len() > 0 then
-    	local query = 'и-"' .. args.name .. '"'
-    	cachedName.inqueue = true
-    	if(args.callback ~= nil)then
-    		tinsert(cachedName.callback, args)
-    	end
-    	self.CacheQueue[query] = args.name
-    	dbg('Info(' .. args.name ..') added to queue')
-    	self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
-    end
-	else
-	    if args.name and args.name:len() > 0 then
-    	local query = 'n-"' .. args.name .. '"'
-    	cachedName.inqueue = true
-    	if(args.callback ~= nil)then
-    		tinsert(cachedName.callback, args)
-    	end
-    	self.CacheQueue[query] = args.name
-    	dbg('Info(' .. args.name ..') added to queue')
-    	self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
-    end
-	end
-	return nil
-end
-
-function lib.CachedUserInfo(_, name)
-	local self, usage = lib, 'CachedUserInfo(name)'
-
-	name = self:CapitalizeInitial(self:CheckArgument(usage, 'name', 'string', name))
-
-	if self.Cache[name] == nil then
-		return nil
-	else
-		return self:DupAll(self:ReturnUserInfo(name))
-	end
-end
-
-function lib.GetWhoLibDebug(_, mode)
-    return lib.Debug
-end
-
-function lib.SetWhoLibDebug(_, mode)
-    lib.Debug = mode
-	dbg = mode and dbgfunc or NOP
-end
-
---function lib.RegisterWhoLibEvent(defhandler, event, callback, handler)
---	local self, usage = lib, 'RegisterWhoLibEvent(event, callback, [handler])'
---
---	self:CheckPreset(usage, 'event', self.events, event)
---	local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true)
---	table.insert(self.events[event], {callback=callback, handler=handler})
---end
-
--- non-embedded externals
-
-function lib.Embed(_, handler)
-	local self, usage = lib, 'Embed(handler)'
-
-	self:CheckArgument(usage, 'handler', 'table', handler)
-
-	for _,name in pairs(self.external) do
-		handler[name] = self[name]
-	end -- do
-	 self['embeds'][handler] = true
-
-	return handler
-end
-
-function lib.Library(_)
-	local self = lib
-
-	return self:Embed({})
-end
-
----
---- internal functions
----
-
-function lib:AllQueuesEmpty()
-    local queueCount = #self.Queue[1] + #self.Queue[2] + #self.Queue[3] + #self.CacheQueue
-
-    -- Be sure that we have cleared the in-progress status
-    if self.WhoInProgress then
-        queueCount = queueCount + 1
-    end
-
-	return queueCount == 0
-end
-
-local queryInterval = 5
-
-function lib:GetQueryInterval() return queryInterval end
-
-function lib:AskWhoNextIn5sec()
-	if self.frame:IsShown() then return end
-
-	dbg("Waiting to send next who")
-	self.Timeout_time = queryInterval
-	self['frame']:Show()
-end
-
-function lib:CancelPendingWhoNext()
-	lib['frame']:Hide()
-end
-
-lib['frame']:SetScript("OnUpdate", function(frame, elapsed)
-	lib.Timeout_time = lib.Timeout_time - elapsed
-	if lib.Timeout_time <= 0 then
-		lib['frame']:Hide()
-		lib:AskWhoNext()
-	end -- if
-end);
-
-
--- queue scheduler
-local queue_weights = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
-local queue_bounds = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
-
--- allow for single queries from the user to get processed faster
-local lastInstantQuery = time()
-local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min
-
-function lib:UpdateWeights()
-   local weightsum, sum, count = 0, 0, 0
-   for k,v in pairs(queue_weights) do
-        sum = sum + v
-        weightsum = weightsum + v * #self.Queue[k]
-   end
-
-   if weightsum == 0 then
-        for k,v in pairs(queue_weights) do queue_bounds[k] = v end
-        return
-   end
-
-   local adjust = sum / weightsum
-
-   for k,v in pairs(queue_bounds) do
-        queue_bounds[k] = queue_weights[k] * adjust * #self.Queue[k]
-   end
-end
-
-function lib:GetNextFromScheduler()
-   self:UpdateWeights()
-
-   -- Since an addon could just fill up the user q for instant processing
-   -- we have to limit instants to 1 per INSTANT_QUERY_MIN_INTERVAL
-   -- and only try instant fulfilment if it will empty the user queue
-   if #self.Queue[1] == 1 then
-		if time() - lastInstantQuery > INSTANT_QUERY_MIN_INTERVAL then
-			dbg("INSTANT")
-			lastInstantQuery = time()
-			return 1, self.Queue[1]
-		end
-   end
-
-   local n,i = math.random(),0
-   repeat
-        i=i+1
-        n = n - queue_bounds[i]
-   until i>=#self.Queue or n <= 0
-
-   dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i]))
-
-   if #self.Queue[i] > 0 then
-        dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i]))
-       return i, self.Queue[i]
-   else
-        dbg("Queues empty, waiting")
-   end
-end
-
-lib.queue_bounds = queue_bounds
-
-function lib:AskWhoNext()
-	if lib.frame:IsShown() then
-		dbg("Already waiting")
-		return
-	end
-
-	self:CancelPendingWhoNext()
-
-	if self.WhoInProgress then
-		-- if we had a who going, it didnt complete
-		dbg("TIMEOUT: "..self.Args.query)
-		local args = self.Args
-		self.Args = nil
---		if args.info and self.CacheQueue[args.query] ~= nil then
-			dbg("Requeing "..args.query)
-			tinsert(self.Queue[args.queue], args)
-			if args.console_show ~= nil then
-				DEFAULT_CHAT_FRAME:AddMessage(("Timeout on result of '%s' - retrying..."):format(args.query),1,1,0)
-				args.console_show = true
-			end
---		end
-
-		if queryInterval < lib.MaxInterval then
-			queryInterval = queryInterval + 0.5
-			dbg("--Throttling down to 1 who per " .. queryInterval .. "s")
-		end
-	end
-
-
-	self.WhoInProgress = false
-
-	local v,k,args = nil
-    local kludge = 10
-	repeat
-        k,v = self:GetNextFromScheduler()
-        if not k then break end
-		if(WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET)then
-			break
-		end
-		if(#v > 0)then
-			args = tremove(v, 1)
-			break
-		end
-        kludge = kludge - 1
-	until kludge <= 0
-
-	if args then
-		self.WhoInProgress = true
-		self.Result = {}
-		self.Args = args
-		self.Total = -1
-		if(args.console_show == true)then
-			DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0)
-
-		end
-
-		if args.queue == self.WHOLIB_QUEUE_USER then
-			WhoFrameEditBox:SetText(args.query)
-			self.Quiet = false
-
-			if args.whotoui then
-    			self.hooked.SetWhoToUI(args.whotoui)
-    		else
-    			self.hooked.SetWhoToUI(args.gui and true or false)
-			end
-		else
-			self.hooked.SetWhoToUI(true)
-			self.Quiet = true
-		end
-
-		dbg("QUERY: "..args.query)
-		self.hooked.SendWho(args.query)
-	else
-		self.Args = nil
-		self.WhoInProgress = false
-	end
-
-    -- Keep processing the who queue if there is more work
-	if not self:AllQueuesEmpty() then
-		self:AskWhoNextIn5sec()
-    else
-        dbg("*** Done processing requests ***")
-	end
-end
-
-function lib:AskWho(args)
-	tinsert(self.Queue[args.queue], args)
-	dbg('[' .. args.queue .. '] added "' .. args.query .. '", queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3])
-	self:TriggerEvent('WHOLIB_QUERY_ADDED')
-
-	self:AskWhoNext()
-end
-
-function lib:ReturnWho()
-    if not self.Args then
-        self.Quiet = nil
-        return
-    end
-
-	if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then
-		self.Quiet = nil
-	end
-
-	if queryInterval > self.MinInterval then
-		queryInterval = queryInterval - 0.5
-		dbg("--Throttling up to 1 who per " .. queryInterval .. "s")
-	end
-
-	self.WhoInProgress = false
-	dbg("RESULT: "..self.Args.query)
-	dbg('[' .. self.Args.queue .. '] returned "' .. self.Args.query .. '", total=' .. self.Total ..' , queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3])
-	local now = time()
-	local complete = (self.Total == #self.Result) and (self.Total < MAX_WHOS_FROM_SERVER)
-	for _,v in pairs(self.Result)do
-		if(self.Cache[v.Name] == nil)then
-			self.Cache[v.Name] = { inqueue = false, callback = {} }
-		end
-
-		local cachedName = self.Cache[v.Name]
-
-		cachedName.valid = true -- is now valid
-		cachedName.data = v -- update data
-		cachedName.data.Online = true -- player is online
-		cachedName.last = now -- update timestamp
-		if(cachedName.inqueue)then
-			if(self.Args.info and self.CacheQueue[self.Args.query] == v.Name)then
-				-- found by the query which was created to -> remove us from query
-				self.CacheQueue[self.Args.query] = nil
-			else
-				-- found by another query
-				for k2,v2 in pairs(self.CacheQueue) do
-					if(v2 == v.Name)then
-						for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do
-							for k3,v3 in pairs(self.Queue[i]) do
-								if(v3.query == k2 and v3.info)then
-									-- remove the query which was generated for this user, cause another query was faster...
-									dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'")
-									table.remove(self.Queue[i], k3)
-									self.CacheQueue[k2] = nil
-								end
-							end
-						end
-					end
-				end
-			end
-			dbg('Info(' .. v.Name ..') returned: on')
-			for _,v2 in pairs(cachedName.callback) do
-				self:RaiseCallback(v2, self:ReturnUserInfo(v.Name))
-			end
-			cachedName.callback = {}
-		end
-		cachedName.inqueue = false -- query is done
-	end
-	if(self.Args.info and self.CacheQueue[self.Args.query])then
-		-- the query did not deliver the result => not online!
-		local name = self.CacheQueue[self.Args.query]
-		local cachedName = self.Cache[name]
-		if (cachedName.inqueue)then
-			-- nothing found (yet)
-			cachedName.valid = true -- is now valid
-			cachedName.inqueue = false -- query is done?
-			cachedName.last = now -- update timestamp
-			if(complete)then
-				cachedName.data.Online = false -- player is offline
-			else
-				cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed)
-			end
-		end
-		dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn'))
-		for _,v in pairs(cachedName.callback) do
-			self:RaiseCallback(v, self:ReturnUserInfo(name))
-		end
-		cachedName.callback = {}
-		self.CacheQueue[self.Args.query] = nil
-	end
-	self:RaiseCallback(self.Args, self.Args.query, self.Result, complete, self.Args.info)
-	self:TriggerEvent('WHOLIB_QUERY_RESULT', self.Args.query, self.Result, complete, self.Args.info)
-
-	if not self:AllQueuesEmpty() then
-		self:AskWhoNextIn5sec()
-	end
-end
-
-function lib:GuiWho(msg)
-	if(msg == self.L['gui_wait'])then
-		return
-	end
-
-	for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do
-		if(v.gui == true)then
-			return
-		end
-	end
-	if(self.WhoInProgress)then
-		WhoFrameEditBox:SetText(self.L['gui_wait'])
-	end
-	self.savedText = msg
-	self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true})
-	WhoFrameEditBox:ClearFocus();
-end
-
-function lib:ConsoleWho(msg)
-	--WhoFrameEditBox:SetText(msg)
-	local console_show = false
-	local q1 = self.Queue[self.WHOLIB_QUEUE_USER]
-	local q1count = #q1
-
-	if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop
-		return
-	end
-
-	if(q1count > 0 and q1[q1count].console_show == false)then -- display 'queued' if console and not yet shown
-		DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], q1[q1count].query), 1, 1, 0)
-		q1[q1count].console_show = true
-	end
-	if(q1count > 0 or self.WhoInProgress)then
-		DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0)
-		console_show = true
-	end
-	self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show})
-end
-
-function lib:ReturnUserInfo(name)
-	if(name ~= nil and self ~= nil and self.Cache ~= nil and self.Cache[name] ~= nil) then
-		return self.Cache[name].data, (time() - self.Cache[name].last) / 60
-	end
-end
-
-function lib:RaiseCallback(args, ...)
-	if type(args.callback) == 'function' then
-		args.callback(self:DupAll(...))
-	elseif args.callback then -- must be a string
-		args.handler[args.callback](args.handler, self:DupAll(...))
-	end -- if
-end
-
--- Argument checking
-
-function lib:CheckArgument(func, name, argtype, arg, defarg)
-	if arg == nil and defarg ~= nil then
-		return defarg
-	elseif type(arg) == argtype then
-		return arg
-	else
-		error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3)
-	end -- if
-end
-
-function lib:CheckPreset(func, name, preset, arg, defarg)
-	if arg == nil and defarg ~= nil then
-		return defarg
-	elseif arg ~= nil and preset[arg] ~= nil then
-		return arg
-	else
-		local p = {}
-		for k,v in pairs(preset) do
-			if type(v) ~= 'string' then
-				table.insert(p, k)
-			else
-				table.insert(p, v)
-			end -- if
-		end -- for
-		error(string.format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3)
-	end -- if
-end
-
-function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil)
-	if not nonil and callback == nil then
-		-- no callback: ignore handler
-		return nil, nil
-	elseif type(callback) == 'function' then
-		-- simple function
-		if handler ~= nil then
-			error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3)
-		end -- if
-	elseif type(callback) == 'string' then
-		-- method
-		if handler == nil then
-			handler = defhandler
-		end -- if
-		if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then
-			error(string.format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3)
-		end -- if
-	else
-		error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3)
-	end -- if
-
-	return callback, handler
-end
-
--- helpers
-
-function lib:simple_dump(x)
-	if type(x) == 'string' then
-		return 'string \''..x..'\''
-	elseif type(x) == 'number' then
-		return 'number '..x
-	else
-		return type(x)
-	end
-end
-
-function lib:Dup(from)
-	local to = {}
-
-	for k,v in pairs(from) do
-		if type(v) == 'table' then
-			to[k] = self:Dup(v)
-		else
-			to[k] = v
-		end -- if
-	end -- for
-
-	return to
-end
-
-function lib:DupAll(x, ...)
-	if type(x) == 'table' then
-		return self:Dup(x), self:DupAll(...)
-	elseif x ~= nil then
-		return x, self:DupAll(...)
-	else
-		return nil
-	end -- if
-end
-
-local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)"
-
-function lib:CapitalizeInitial(name)
-    return name:gsub(MULTIBYTE_FIRST_CHAR, string.upper, 1)
-end
-
----
---- user events (Using CallbackHandler)
----
-
-lib.PossibleEvents = {
-	'WHOLIB_QUERY_RESULT',
-	'WHOLIB_QUERY_ADDED',
-}
-
-function lib:TriggerEvent(event, ...)
-    callbacks:Fire(event, ...)
-end
-
----
---- slash commands
----
-
-SlashCmdList['WHO'] = function(msg)
-	dbg("console /who: "..msg)
-	-- new /who function
-	--local self = lib
-
-	if(msg == '')then
-		lib:GuiWho(WhoFrame_GetDefaultWhoCommand())
-	elseif(WhoFrame:IsVisible())then
-		lib:GuiWho(msg)
-	else
-		lib:ConsoleWho(msg)
-	end
-end
-
-SlashCmdList['WHOLIB_DEBUG'] = function()
-	-- /wholibdebug: toggle debug on/off
-	local self = lib
-
-    self:SetWhoLibDebug(not self.Debug)
-end
-
-SLASH_WHOLIB_DEBUG1 = '/wholibdebug'
-
-
----
---- hook activation
----
-
--- functions to hook
-local hooks = {
-	'SendWho',
-	'WhoFrameEditBox_OnEnterPressed',
---	'FriendsFrame_OnEvent',
-	'SetWhoToUI',
-}
-
--- hook all functions (which are not yet hooked)
-for _, name in pairs(hooks) do
-	if not lib['hooked'][name] then
-		lib['hooked'][name] = _G[name]
-		_G[name] = function(...)
-			lib.hook[name](lib, ...)
-		end -- function
-	end -- if
-end -- for
-
--- fake 'WhoFrame:Hide' as hooked
-table.insert(hooks, 'WhoFrame_Hide')
-
--- check for unused hooks -> remove function
-for name, _ in pairs(lib['hook']) do
-	if not hooks[name] then
-		lib['hook'][name] = function() end
-	end -- if
-end -- for
-
--- secure hook 'WhoFrame:Hide'
-if not lib['hooked']['WhoFrame_Hide'] then
-	lib['hooked']['WhoFrame_Hide'] = true
-	hooksecurefunc(WhoFrame, 'Hide', function(...)
-			lib['hook']['WhoFrame_Hide'](lib, ...)
-		end -- function
-	)
-end -- if
-
-
-
------ Coroutine based implementation (future)
---function lib:sendWhoResult(val)
---    coroutine.yield(val)
---end
---
---function lib:sendWaitState(val)
---    coroutine.yield(val)
---end
---
---function lib:producer()
---    return coroutine.create(
---    function()
---        lib:AskWhoNext()
---        lib:sendWaitState(true)
---
---        -- Resumed look for data
---
---    end)
---end
-
-
-
-
-
----
---- hook replacements
----
-
-function lib.hook.SendWho(self, msg)
-	dbg("SendWho: "..msg)
-	lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0})
-end
-
-function lib.hook.WhoFrameEditBox_OnEnterPressed(self)
-	lib:GuiWho(WhoFrameEditBox:GetText())
-end
-
---[[
-function lib.hook.FriendsFrame_OnEvent(self, ...)
-	if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then
-		lib.hooked.FriendsFrame_OnEvent(...)
-	end
-end
-]]
-
-hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event)
-		if(event == "WHO_LIST_UPDATE") then
-			self:UnregisterEvent("WHO_LIST_UPDATE");
-		end
-	end);
-
-
-function lib.hook.SetWhoToUI(self, state)
-	lib.SetWhoToUIState = state
-end
-
-function lib.hook.WhoFrame_Hide(self)
-	if(not lib.WhoInProgress)then
-		lib:AskWhoNextIn5sec()
-	end
-end
-
-
----
---- WoW events
----
-
-local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+')
-
-
-function lib:CHAT_MSG_SYSTEM(arg1)
-	if arg1 and arg1:find(who_pattern) then
-		lib:ProcessWhoResults()
-	end
-end
-
-FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE")
-
-function lib:WHO_LIST_UPDATE()
-    if not lib.Quiet then
-		WhoList_Update()
-        FriendsFrame_Update()
-    end
-
-    lib:ProcessWhoResults()
-end
-
-function lib:ProcessWhoResults()
-	local num
-	self.Total, num = GetNumWhoResults()
-	for i=1, num do
-		local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i)
-		self.Result[i] = {Name=charname, Guild=guildname, Level=level, Race=race, Class=class, Zone=zone, NoLocaleClass=nonlocalclass, Sex=sex }
-	end
-
-	self:ReturnWho()
-end
-
----
---- event activation
----
-
-lib['frame']:UnregisterAllEvents();
-
-lib['frame']:SetScript("OnEvent", function(frame, event, ...)
-	lib[event](lib, ...)
-end);
-
-for _,name in pairs({
-	'CHAT_MSG_SYSTEM',
-	'WHO_LIST_UPDATE',
-}) do
-	lib['frame']:RegisterEvent(name);
-end -- for
-
-
----
---- re-embed
----
-
-for target,_ in pairs(lib['embeds']) do
-	if type(target) == 'table' then
-		lib:Embed(target)
-	end -- if
-end -- for
+---
+--- check for an already loaded old WhoLib
+---
+
+if WhoLibByALeX or WhoLib then
+	-- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail!
+	error("an other WhoLib is already running - disable them first!\n")
+	return
+end -- if
+
+---
+--- check version
+---
+
+assert(LibStub, "LibWho-2.0 requires LibStub")
+
+
+local major_version = 'LibWho-2.0'
+local minor_version = tonumber("145") or 99999
+
+local lib = LibStub:NewLibrary(major_version, minor_version)
+
+
+if not lib then
+	return	-- already loaded and no upgrade necessary
+end
+
+lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
+local callbacks = lib.callbacks
+
+local am = {}
+local om = getmetatable(lib)
+if om then
+	for k, v in pairs(om) do am[k] = v end
+end
+am.__tostring = function() return major_version end
+setmetatable(lib, am)
+
+local function dbgfunc(...) if lib.Debug then print(...) end end
+local function NOP() return end
+local dbg = NOP
+
+---
+--- initalize base
+---
+
+if type(lib['hooked']) ~= 'table' then
+	lib['hooked'] = {}
+end -- if
+
+if type(lib['hook']) ~= 'table' then
+	lib['hook'] = {}
+end -- if
+
+if type(lib['events']) ~= 'table' then
+	lib['events'] = {}
+end -- if
+
+if type(lib['embeds']) ~= 'table' then
+	lib['embeds'] = {}
+end -- if
+
+if type(lib['frame']) ~= 'table' then
+	lib['frame'] = CreateFrame('Frame', major_version);
+end -- if
+lib['frame']:Hide()
+
+lib.Queue = {[1]={}, [2]={}, [3]={}}
+lib.WhoInProgress = false
+lib.Result = nil
+lib.Args = nil
+lib.Total = nil
+lib.Quiet = nil
+lib.Debug = false
+lib.Cache = {}
+lib.CacheQueue = {}
+lib.SetWhoToUIState = false
+
+
+lib.MinInterval = 2.5
+lib.MaxInterval = 10
+
+---
+--- locale
+---
+
+if (GetLocale() == "ruRU") then
+	lib.L = {
+		['console_queued'] = 'Добавлено в очередь "/who %s"',
+		['console_query'] = 'Результат "/who %s"',
+		['gui_wait'] = '- Пожалуйста подождите -',
+	}
+else
+	-- enUS is the default
+	lib.L = {
+		['console_queued'] = 'Added "/who %s" to queue',
+		['console_query'] = 'Result of "/who %s"',
+		['gui_wait'] = '- Please Wait -',
+	}
+end -- if
+
+
+---
+--- external functions/constants
+---
+
+lib['external'] = {
+	'WHOLIB_QUEUE_USER',
+	'WHOLIB_QUEUE_QUIET',
+	'WHOLIB_QUEUE_SCANNING',
+	'WHOLIB_FLAG_ALWAYS_CALLBACK',
+	'Who',
+	'UserInfo',
+	'CachedUserInfo',
+	'GetWhoLibDebug',
+	'SetWhoLibDebug',
+--	'RegisterWhoLibEvent',
+}
+
+-- queues
+lib['WHOLIB_QUEUE_USER'] = 1
+lib['WHOLIB_QUEUE_QUIET'] = 2
+lib['WHOLIB_QUEUE_SCANNING'] = 3
+
+
+
+local queue_all = {
+	[1] = 'WHOLIB_QUEUE_USER',
+	[2] = 'WHOLIB_QUEUE_QUIET',
+	[3] = 'WHOLIB_QUEUE_SCANNING',
+}
+
+local queue_quiet = {
+	[2] = 'WHOLIB_QUEUE_QUIET',
+	[3] = 'WHOLIB_QUEUE_SCANNING',
+}
+
+-- bit masks!
+lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1
+
+function lib:Reset()
+    self.Queue = {[1]={}, [2]={}, [3]={}}
+    self.Cache = {}
+    self.CacheQueue = {}
+end
+
+function lib.Who(defhandler, query, opts)
+	local self, args, usage = lib, {}, 'Who(query, [opts])'
+
+	args.query = self:CheckArgument(usage, 'query', 'string', query)
+	opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
+	args.queue = self:CheckPreset(usage, 'opts.queue', queue_all, opts.queue, self.WHOLIB_QUEUE_SCANNING)
+	args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
+	args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler)
+	-- now args - copied and verified from opts
+
+	if args.queue == self.WHOLIB_QUEUE_USER then
+		if WhoFrame:IsShown() then
+			self:GuiWho(args.query)
+		else
+			self:ConsoleWho(args.query)
+		end
+	else
+		self:AskWho(args)
+	end
+end
+
+local function ignoreRealm(name)
+	local _, realm = string.split("-", name)
+ 	local connectedServers = GetAutoCompleteRealms()
+ 	if connectedServers then
+		for i = 1, #connectedServers do
+ 	 		if realm == connectedServers[i] then return false end
+		end
+ 	end
+    return true
+end
+
+function lib.UserInfo(defhandler, name, opts)
+	local self, args, usage = lib, {}, 'UserInfo(name, [opts])'
+	local now = time()
+
+    name = self:CheckArgument(usage, 'name', 'string', name)
+    if name:len() == 0 then return end
+
+    --There is no api to tell connected realms from cross realm by name. As such, we check known connections table before excluding who inquiry
+    --UnitRealmRelationship and UnitIsSameServer don't work with "name". They require unitID so they are useless here
+    if name:find("%-") and ignoreRealm(name) then return end
+
+	args.name = self:CapitalizeInitial(name)
+	opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
+	args.queue = self:CheckPreset(usage, 'opts.queue', queue_quiet, opts.queue, self.WHOLIB_QUEUE_SCANNING)
+	args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
+	args.timeout = self:CheckArgument(usage, 'opts.timeout', 'number', opts.timeout, 5)
+	args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback,  opts.handler, defhandler)
+
+	-- now args - copied and verified from opts
+	local cachedName = self.Cache[args.name]
+
+	if(cachedName ~= nil)then
+		-- user is in cache
+		if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then
+			-- cache is valid and timeout is in range
+			--dbg('Info(' .. args.name ..') returned immedeatly')
+			if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then
+				self:RaiseCallback(args, cachedName.data)
+				return false
+			else
+				return self:DupAll(self:ReturnUserInfo(args.name))
+			end
+		elseif(cachedName.valid == false)then
+			-- query is already running (first try)
+			if(args.callback ~= nil)then
+				tinsert(cachedName.callback, args)
+			end
+			--dbg('Info(' .. args.name ..') returned cause it\'s already searching')
+			return nil
+		end
+	else
+		self.Cache[args.name] = {valid=false, inqueue=false, callback={}, data={Name = args.name}, last=now }
+	end
+
+	local cachedName = self.Cache[args.name]
+
+	if(cachedName.inqueue)then
+		-- query is running!
+		if(args.callback ~= nil)then
+			tinsert(cachedName.callback, args)
+		end
+		dbg('Info(' .. args.name ..') returned cause it\'s already searching')
+		return nil
+	end
+	if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon
+    if args.name and args.name:len() > 0 then
+    	local query = 'и-"' .. args.name .. '"'
+    	cachedName.inqueue = true
+    	if(args.callback ~= nil)then
+    		tinsert(cachedName.callback, args)
+    	end
+    	self.CacheQueue[query] = args.name
+    	dbg('Info(' .. args.name ..') added to queue')
+    	self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
+    end
+	else
+	    if args.name and args.name:len() > 0 then
+    	local query = 'n-"' .. args.name .. '"'
+    	cachedName.inqueue = true
+    	if(args.callback ~= nil)then
+    		tinsert(cachedName.callback, args)
+    	end
+    	self.CacheQueue[query] = args.name
+    	dbg('Info(' .. args.name ..') added to queue')
+    	self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
+    end
+	end
+	return nil
+end
+
+function lib.CachedUserInfo(_, name)
+	local self, usage = lib, 'CachedUserInfo(name)'
+
+	name = self:CapitalizeInitial(self:CheckArgument(usage, 'name', 'string', name))
+
+	if self.Cache[name] == nil then
+		return nil
+	else
+		return self:DupAll(self:ReturnUserInfo(name))
+	end
+end
+
+function lib.GetWhoLibDebug(_, mode)
+    return lib.Debug
+end
+
+function lib.SetWhoLibDebug(_, mode)
+    lib.Debug = mode
+	dbg = mode and dbgfunc or NOP
+end
+
+--function lib.RegisterWhoLibEvent(defhandler, event, callback, handler)
+--	local self, usage = lib, 'RegisterWhoLibEvent(event, callback, [handler])'
+--
+--	self:CheckPreset(usage, 'event', self.events, event)
+--	local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true)
+--	table.insert(self.events[event], {callback=callback, handler=handler})
+--end
+
+-- non-embedded externals
+
+function lib.Embed(_, handler)
+	local self, usage = lib, 'Embed(handler)'
+
+	self:CheckArgument(usage, 'handler', 'table', handler)
+
+	for _,name in pairs(self.external) do
+		handler[name] = self[name]
+	end -- do
+	 self['embeds'][handler] = true
+
+	return handler
+end
+
+function lib.Library(_)
+	local self = lib
+
+	return self:Embed({})
+end
+
+---
+--- internal functions
+---
+
+function lib:AllQueuesEmpty()
+    local queueCount = #self.Queue[1] + #self.Queue[2] + #self.Queue[3] + #self.CacheQueue
+
+    -- Be sure that we have cleared the in-progress status
+    if self.WhoInProgress then
+        queueCount = queueCount + 1
+    end
+
+	return queueCount == 0
+end
+
+local queryInterval = 5
+
+function lib:GetQueryInterval() return queryInterval end
+
+function lib:AskWhoNextIn5sec()
+	if self.frame:IsShown() then return end
+
+	dbg("Waiting to send next who")
+	self.Timeout_time = queryInterval
+	self['frame']:Show()
+end
+
+function lib:CancelPendingWhoNext()
+	lib['frame']:Hide()
+end
+
+lib['frame']:SetScript("OnUpdate", function(frame, elapsed)
+	lib.Timeout_time = lib.Timeout_time - elapsed
+	if lib.Timeout_time <= 0 then
+		lib['frame']:Hide()
+		lib:AskWhoNext()
+	end -- if
+end);
+
+
+-- queue scheduler
+local queue_weights = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
+local queue_bounds = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
+
+-- allow for single queries from the user to get processed faster
+local lastInstantQuery = time()
+local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min
+
+function lib:UpdateWeights()
+   local weightsum, sum, count = 0, 0, 0
+   for k,v in pairs(queue_weights) do
+        sum = sum + v
+        weightsum = weightsum + v * #self.Queue[k]
+   end
+
+   if weightsum == 0 then
+        for k,v in pairs(queue_weights) do queue_bounds[k] = v end
+        return
+   end
+
+   local adjust = sum / weightsum
+
+   for k,v in pairs(queue_bounds) do
+        queue_bounds[k] = queue_weights[k] * adjust * #self.Queue[k]
+   end
+end
+
+function lib:GetNextFromScheduler()
+   self:UpdateWeights()
+
+   -- Since an addon could just fill up the user q for instant processing
+   -- we have to limit instants to 1 per INSTANT_QUERY_MIN_INTERVAL
+   -- and only try instant fulfilment if it will empty the user queue
+   if #self.Queue[1] == 1 then
+		if time() - lastInstantQuery > INSTANT_QUERY_MIN_INTERVAL then
+			dbg("INSTANT")
+			lastInstantQuery = time()
+			return 1, self.Queue[1]
+		end
+   end
+
+   local n,i = math.random(),0
+   repeat
+        i=i+1
+        n = n - queue_bounds[i]
+   until i>=#self.Queue or n <= 0
+
+   dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i]))
+
+   if #self.Queue[i] > 0 then
+        dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i]))
+       return i, self.Queue[i]
+   else
+        dbg("Queues empty, waiting")
+   end
+end
+
+lib.queue_bounds = queue_bounds
+
+function lib:AskWhoNext()
+	if lib.frame:IsShown() then
+		dbg("Already waiting")
+		return
+	end
+
+	self:CancelPendingWhoNext()
+
+	if self.WhoInProgress then
+		-- if we had a who going, it didnt complete
+		dbg("TIMEOUT: "..self.Args.query)
+		local args = self.Args
+		self.Args = nil
+--		if args.info and self.CacheQueue[args.query] ~= nil then
+			dbg("Requeing "..args.query)
+			tinsert(self.Queue[args.queue], args)
+			if args.console_show ~= nil then
+				DEFAULT_CHAT_FRAME:AddMessage(("Timeout on result of '%s' - retrying..."):format(args.query),1,1,0)
+				args.console_show = true
+			end
+--		end
+
+		if queryInterval < lib.MaxInterval then
+			queryInterval = queryInterval + 0.5
+			dbg("--Throttling down to 1 who per " .. queryInterval .. "s")
+		end
+	end
+
+
+	self.WhoInProgress = false
+
+	local v,k,args = nil
+    local kludge = 10
+	repeat
+        k,v = self:GetNextFromScheduler()
+        if not k then break end
+		if(WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET)then
+			break
+		end
+		if(#v > 0)then
+			args = tremove(v, 1)
+			break
+		end
+        kludge = kludge - 1
+	until kludge <= 0
+
+	if args then
+		self.WhoInProgress = true
+		self.Result = {}
+		self.Args = args
+		self.Total = -1
+		if(args.console_show == true)then
+			DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0)
+
+		end
+
+		if args.queue == self.WHOLIB_QUEUE_USER then
+			WhoFrameEditBox:SetText(args.query)
+			self.Quiet = false
+
+			if args.whotoui then
+    			self.hooked.SetWhoToUI(args.whotoui)
+    		else
+    			self.hooked.SetWhoToUI(args.gui and true or false)
+			end
+		else
+			self.hooked.SetWhoToUI(true)
+			self.Quiet = true
+		end
+
+		dbg("QUERY: "..args.query)
+		self.hooked.SendWho(args.query)
+	else
+		self.Args = nil
+		self.WhoInProgress = false
+	end
+
+    -- Keep processing the who queue if there is more work
+	if not self:AllQueuesEmpty() then
+		self:AskWhoNextIn5sec()
+    else
+        dbg("*** Done processing requests ***")
+	end
+end
+
+function lib:AskWho(args)
+	tinsert(self.Queue[args.queue], args)
+	dbg('[' .. args.queue .. '] added "' .. args.query .. '", queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3])
+	self:TriggerEvent('WHOLIB_QUERY_ADDED')
+
+	self:AskWhoNext()
+end
+
+function lib:ReturnWho()
+    if not self.Args then
+        self.Quiet = nil
+        return
+    end
+
+	if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then
+		self.Quiet = nil
+	end
+
+	if queryInterval > self.MinInterval then
+		queryInterval = queryInterval - 0.5
+		dbg("--Throttling up to 1 who per " .. queryInterval .. "s")
+	end
+
+	self.WhoInProgress = false
+	dbg("RESULT: "..self.Args.query)
+	dbg('[' .. self.Args.queue .. '] returned "' .. self.Args.query .. '", total=' .. self.Total ..' , queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3])
+	local now = time()
+	local complete = (self.Total == #self.Result) and (self.Total < MAX_WHOS_FROM_SERVER)
+	for _,v in pairs(self.Result)do
+		if(self.Cache[v.Name] == nil)then
+			self.Cache[v.Name] = { inqueue = false, callback = {} }
+		end
+
+		local cachedName = self.Cache[v.Name]
+
+		cachedName.valid = true -- is now valid
+		cachedName.data = v -- update data
+		cachedName.data.Online = true -- player is online
+		cachedName.last = now -- update timestamp
+		if(cachedName.inqueue)then
+			if(self.Args.info and self.CacheQueue[self.Args.query] == v.Name)then
+				-- found by the query which was created to -> remove us from query
+				self.CacheQueue[self.Args.query] = nil
+			else
+				-- found by another query
+				for k2,v2 in pairs(self.CacheQueue) do
+					if(v2 == v.Name)then
+						for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do
+							for k3,v3 in pairs(self.Queue[i]) do
+								if(v3.query == k2 and v3.info)then
+									-- remove the query which was generated for this user, cause another query was faster...
+									dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'")
+									table.remove(self.Queue[i], k3)
+									self.CacheQueue[k2] = nil
+								end
+							end
+						end
+					end
+				end
+			end
+			dbg('Info(' .. v.Name ..') returned: on')
+			for _,v2 in pairs(cachedName.callback) do
+				self:RaiseCallback(v2, self:ReturnUserInfo(v.Name))
+			end
+			cachedName.callback = {}
+		end
+		cachedName.inqueue = false -- query is done
+	end
+	if(self.Args.info and self.CacheQueue[self.Args.query])then
+		-- the query did not deliver the result => not online!
+		local name = self.CacheQueue[self.Args.query]
+		local cachedName = self.Cache[name]
+		if (cachedName.inqueue)then
+			-- nothing found (yet)
+			cachedName.valid = true -- is now valid
+			cachedName.inqueue = false -- query is done?
+			cachedName.last = now -- update timestamp
+			if(complete)then
+				cachedName.data.Online = false -- player is offline
+			else
+				cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed)
+			end
+		end
+		dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn'))
+		for _,v in pairs(cachedName.callback) do
+			self:RaiseCallback(v, self:ReturnUserInfo(name))
+		end
+		cachedName.callback = {}
+		self.CacheQueue[self.Args.query] = nil
+	end
+	self:RaiseCallback(self.Args, self.Args.query, self.Result, complete, self.Args.info)
+	self:TriggerEvent('WHOLIB_QUERY_RESULT', self.Args.query, self.Result, complete, self.Args.info)
+
+	if not self:AllQueuesEmpty() then
+		self:AskWhoNextIn5sec()
+	end
+end
+
+function lib:GuiWho(msg)
+	if(msg == self.L['gui_wait'])then
+		return
+	end
+
+	for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do
+		if(v.gui == true)then
+			return
+		end
+	end
+	if(self.WhoInProgress)then
+		WhoFrameEditBox:SetText(self.L['gui_wait'])
+	end
+	self.savedText = msg
+	self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true})
+	WhoFrameEditBox:ClearFocus();
+end
+
+function lib:ConsoleWho(msg)
+	--WhoFrameEditBox:SetText(msg)
+	local console_show = false
+	local q1 = self.Queue[self.WHOLIB_QUEUE_USER]
+	local q1count = #q1
+
+	if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop
+		return
+	end
+
+	if(q1count > 0 and q1[q1count].console_show == false)then -- display 'queued' if console and not yet shown
+		DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], q1[q1count].query), 1, 1, 0)
+		q1[q1count].console_show = true
+	end
+	if(q1count > 0 or self.WhoInProgress)then
+		DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0)
+		console_show = true
+	end
+	self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show})
+end
+
+function lib:ReturnUserInfo(name)
+	if(name ~= nil and self ~= nil and self.Cache ~= nil and self.Cache[name] ~= nil) then
+		return self.Cache[name].data, (time() - self.Cache[name].last) / 60
+	end
+end
+
+function lib:RaiseCallback(args, ...)
+	if type(args.callback) == 'function' then
+		args.callback(self:DupAll(...))
+	elseif args.callback then -- must be a string
+		args.handler[args.callback](args.handler, self:DupAll(...))
+	end -- if
+end
+
+-- Argument checking
+
+function lib:CheckArgument(func, name, argtype, arg, defarg)
+	if arg == nil and defarg ~= nil then
+		return defarg
+	elseif type(arg) == argtype then
+		return arg
+	else
+		error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3)
+	end -- if
+end
+
+function lib:CheckPreset(func, name, preset, arg, defarg)
+	if arg == nil and defarg ~= nil then
+		return defarg
+	elseif arg ~= nil and preset[arg] ~= nil then
+		return arg
+	else
+		local p = {}
+		for k,v in pairs(preset) do
+			if type(v) ~= 'string' then
+				table.insert(p, k)
+			else
+				table.insert(p, v)
+			end -- if
+		end -- for
+		error(string.format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3)
+	end -- if
+end
+
+function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil)
+	if not nonil and callback == nil then
+		-- no callback: ignore handler
+		return nil, nil
+	elseif type(callback) == 'function' then
+		-- simple function
+		if handler ~= nil then
+			error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3)
+		end -- if
+	elseif type(callback) == 'string' then
+		-- method
+		if handler == nil then
+			handler = defhandler
+		end -- if
+		if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then
+			error(string.format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3)
+		end -- if
+	else
+		error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3)
+	end -- if
+
+	return callback, handler
+end
+
+-- helpers
+
+function lib:simple_dump(x)
+	if type(x) == 'string' then
+		return 'string \''..x..'\''
+	elseif type(x) == 'number' then
+		return 'number '..x
+	else
+		return type(x)
+	end
+end
+
+function lib:Dup(from)
+	local to = {}
+
+	for k,v in pairs(from) do
+		if type(v) == 'table' then
+			to[k] = self:Dup(v)
+		else
+			to[k] = v
+		end -- if
+	end -- for
+
+	return to
+end
+
+function lib:DupAll(x, ...)
+	if type(x) == 'table' then
+		return self:Dup(x), self:DupAll(...)
+	elseif x ~= nil then
+		return x, self:DupAll(...)
+	else
+		return nil
+	end -- if
+end
+
+local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)"
+
+function lib:CapitalizeInitial(name)
+    return name:gsub(MULTIBYTE_FIRST_CHAR, string.upper, 1)
+end
+
+---
+--- user events (Using CallbackHandler)
+---
+
+lib.PossibleEvents = {
+	'WHOLIB_QUERY_RESULT',
+	'WHOLIB_QUERY_ADDED',
+}
+
+function lib:TriggerEvent(event, ...)
+    callbacks:Fire(event, ...)
+end
+
+---
+--- slash commands
+---
+
+SlashCmdList['WHO'] = function(msg)
+	dbg("console /who: "..msg)
+	-- new /who function
+	--local self = lib
+
+	if(msg == '')then
+		lib:GuiWho(WhoFrame_GetDefaultWhoCommand())
+	elseif(WhoFrame:IsVisible())then
+		lib:GuiWho(msg)
+	else
+		lib:ConsoleWho(msg)
+	end
+end
+
+SlashCmdList['WHOLIB_DEBUG'] = function()
+	-- /wholibdebug: toggle debug on/off
+	local self = lib
+
+    self:SetWhoLibDebug(not self.Debug)
+end
+
+SLASH_WHOLIB_DEBUG1 = '/wholibdebug'
+
+
+---
+--- hook activation
+---
+
+-- functions to hook
+local hooks = {
+	'SendWho',
+	'WhoFrameEditBox_OnEnterPressed',
+--	'FriendsFrame_OnEvent',
+	'SetWhoToUI',
+}
+
+-- hook all functions (which are not yet hooked)
+for _, name in pairs(hooks) do
+	if not lib['hooked'][name] then
+		lib['hooked'][name] = _G[name]
+		_G[name] = function(...)
+			lib.hook[name](lib, ...)
+		end -- function
+	end -- if
+end -- for
+
+-- fake 'WhoFrame:Hide' as hooked
+table.insert(hooks, 'WhoFrame_Hide')
+
+-- check for unused hooks -> remove function
+for name, _ in pairs(lib['hook']) do
+	if not hooks[name] then
+		lib['hook'][name] = function() end
+	end -- if
+end -- for
+
+-- secure hook 'WhoFrame:Hide'
+if not lib['hooked']['WhoFrame_Hide'] then
+	lib['hooked']['WhoFrame_Hide'] = true
+	hooksecurefunc(WhoFrame, 'Hide', function(...)
+			lib['hook']['WhoFrame_Hide'](lib, ...)
+		end -- function
+	)
+end -- if
+
+
+
+----- Coroutine based implementation (future)
+--function lib:sendWhoResult(val)
+--    coroutine.yield(val)
+--end
+--
+--function lib:sendWaitState(val)
+--    coroutine.yield(val)
+--end
+--
+--function lib:producer()
+--    return coroutine.create(
+--    function()
+--        lib:AskWhoNext()
+--        lib:sendWaitState(true)
+--
+--        -- Resumed look for data
+--
+--    end)
+--end
+
+
+
+
+
+---
+--- hook replacements
+---
+
+function lib.hook.SendWho(self, msg)
+	dbg("SendWho: "..msg)
+	lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0})
+end
+
+function lib.hook.WhoFrameEditBox_OnEnterPressed(self)
+	lib:GuiWho(WhoFrameEditBox:GetText())
+end
+
+--[[
+function lib.hook.FriendsFrame_OnEvent(self, ...)
+	if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then
+		lib.hooked.FriendsFrame_OnEvent(...)
+	end
+end
+]]
+
+hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event)
+		if(event == "WHO_LIST_UPDATE") then
+			self:UnregisterEvent("WHO_LIST_UPDATE");
+		end
+	end);
+
+
+function lib.hook.SetWhoToUI(self, state)
+	lib.SetWhoToUIState = state
+end
+
+function lib.hook.WhoFrame_Hide(self)
+	if(not lib.WhoInProgress)then
+		lib:AskWhoNextIn5sec()
+	end
+end
+
+
+---
+--- WoW events
+---
+
+local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+')
+
+
+function lib:CHAT_MSG_SYSTEM(arg1)
+	if arg1 and arg1:find(who_pattern) then
+		lib:ProcessWhoResults()
+	end
+end
+
+FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE")
+
+function lib:WHO_LIST_UPDATE()
+    if not lib.Quiet then
+		WhoList_Update()
+        FriendsFrame_Update()
+    end
+
+    lib:ProcessWhoResults()
+end
+
+function lib:ProcessWhoResults()
+	local num
+	self.Total, num = GetNumWhoResults()
+	for i=1, num do
+		local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i)
+		self.Result[i] = {Name=charname, Guild=guildname, Level=level, Race=race, Class=class, Zone=zone, NoLocaleClass=nonlocalclass, Sex=sex }
+	end
+
+	self:ReturnWho()
+end
+
+---
+--- event activation
+---
+
+lib['frame']:UnregisterAllEvents();
+
+lib['frame']:SetScript("OnEvent", function(frame, event, ...)
+	lib[event](lib, ...)
+end);
+
+for _,name in pairs({
+	'CHAT_MSG_SYSTEM',
+	'WHO_LIST_UPDATE',
+}) do
+	lib['frame']:RegisterEvent(name);
+end -- for
+
+
+---
+--- re-embed
+---
+
+for target,_ in pairs(lib['embeds']) do
+	if type(target) == 'table' then
+		lib:Embed(target)
+	end -- if
+end -- for
diff --git a/libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua b/libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
index 2a64013..e0fe1af 100644
--- a/libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
+++ b/libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
@@ -1,238 +1,240 @@
---[[ $Id: CallbackHandler-1.0.lua 18 2014-10-16 02:52:20Z mikk $ ]]
-local MAJOR, MINOR = "CallbackHandler-1.0", 6
-local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
-
-if not CallbackHandler then return end -- No upgrade needed
-
-local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-
--- Lua APIs
-local tconcat = table.concat
-local assert, error, loadstring = assert, error, loadstring
-local setmetatable, rawset, rawget = setmetatable, rawset, rawget
-local next, select, pairs, type, tostring = next, select, pairs, type, tostring
-
--- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
--- List them here for Mikk's FindGlobals script
--- GLOBALS: geterrorhandler
-
-local xpcall = xpcall
-
-local function errorhandler(err)
-	return geterrorhandler()(err)
-end
-
-local function CreateDispatcher(argCount)
-	local code = [[
-	local next, xpcall, eh = ...
-
-	local method, ARGS
-	local function call() method(ARGS) end
-
-	local function dispatch(handlers, ...)
-		local index
-		index, method = next(handlers)
-		if not method then return end
-		local OLD_ARGS = ARGS
-		ARGS = ...
-		repeat
-			xpcall(call, eh)
-			index, method = next(handlers, index)
-		until not method
-		ARGS = OLD_ARGS
-	end
-
-	return dispatch
-	]]
-
-	local ARGS, OLD_ARGS = {}, {}
-	for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
-	code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
-	return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
-end
-
-local Dispatchers = setmetatable({}, {__index=function(self, argCount)
-	local dispatcher = CreateDispatcher(argCount)
-	rawset(self, argCount, dispatcher)
-	return dispatcher
-end})
-
---------------------------------------------------------------------------
--- CallbackHandler:New
---
---   target            - target object to embed public APIs in
---   RegisterName      - name of the callback registration API, default "RegisterCallback"
---   UnregisterName    - name of the callback unregistration API, default "UnregisterCallback"
---   UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
-
-function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName)
-
-	RegisterName = RegisterName or "RegisterCallback"
-	UnregisterName = UnregisterName or "UnregisterCallback"
-	if UnregisterAllName==nil then	-- false is used to indicate "don't want this method"
-		UnregisterAllName = "UnregisterAllCallbacks"
-	end
-
-	-- we declare all objects and exported APIs inside this closure to quickly gain access
-	-- to e.g. function names, the "target" parameter, etc
-
-
-	-- Create the registry object
-	local events = setmetatable({}, meta)
-	local registry = { recurse=0, events=events }
-
-	-- registry:Fire() - fires the given event/message into the registry
-	function registry:Fire(eventname, ...)
-		if not rawget(events, eventname) or not next(events[eventname]) then return end
-		local oldrecurse = registry.recurse
-		registry.recurse = oldrecurse + 1
-
-		Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
-
-		registry.recurse = oldrecurse
-
-		if registry.insertQueue and oldrecurse==0 then
-			-- Something in one of our callbacks wanted to register more callbacks; they got queued
-			for eventname,callbacks in pairs(registry.insertQueue) do
-				local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
-				for self,func in pairs(callbacks) do
-					events[eventname][self] = func
-					-- fire OnUsed callback?
-					if first and registry.OnUsed then
-						registry.OnUsed(registry, target, eventname)
-						first = nil
-					end
-				end
-			end
-			registry.insertQueue = nil
-		end
-	end
-
-	-- Registration of a callback, handles:
-	--   self["method"], leads to self["method"](self, ...)
-	--   self with function ref, leads to functionref(...)
-	--   "addonId" (instead of self) with function ref, leads to functionref(...)
-	-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
-	target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
-		if type(eventname) ~= "string" then
-			error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
-		end
-
-		method = method or eventname
-
-		local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
-
-		if type(method) ~= "string" and type(method) ~= "function" then
-			error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
-		end
-
-		local regfunc
-
-		if type(method) == "string" then
-			-- self["method"] calling style
-			if type(self) ~= "table" then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
-			elseif self==target then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
-			elseif type(self[method]) ~= "function" then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
-			end
-
-			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
-				local arg=select(1,...)
-				regfunc = function(...) self[method](self,arg,...) end
-			else
-				regfunc = function(...) self[method](self,...) end
-			end
-		else
-			-- function ref with self=object or self="addonId" or self=thread
-			if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
-				error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
-			end
-
-			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
-				local arg=select(1,...)
-				regfunc = function(...) method(arg,...) end
-			else
-				regfunc = method
-			end
-		end
-
-
-		if events[eventname][self] or registry.recurse<1 then
-		-- if registry.recurse<1 then
-			-- we're overwriting an existing entry, or not currently recursing. just set it.
-			events[eventname][self] = regfunc
-			-- fire OnUsed callback?
-			if registry.OnUsed and first then
-				registry.OnUsed(registry, target, eventname)
-			end
-		else
-			-- we're currently processing a callback in this registry, so delay the registration of this new entry!
-			-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
-			registry.insertQueue = registry.insertQueue or setmetatable({},meta)
-			registry.insertQueue[eventname][self] = regfunc
-		end
-	end
-
-	-- Unregister a callback
-	target[UnregisterName] = function(self, eventname)
-		if not self or self==target then
-			error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
-		end
-		if type(eventname) ~= "string" then
-			error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
-		end
-		if rawget(events, eventname) and events[eventname][self] then
-			events[eventname][self] = nil
-			-- Fire OnUnused callback?
-			if registry.OnUnused and not next(events[eventname]) then
-				registry.OnUnused(registry, target, eventname)
-			end
-		end
-		if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
-			registry.insertQueue[eventname][self] = nil
-		end
-	end
-
-	-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
-	if UnregisterAllName then
-		target[UnregisterAllName] = function(...)
-			if select("#",...)<1 then
-				error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
-			end
-			if select("#",...)==1 and ...==target then
-				error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
-			end
-
-
-			for i=1,select("#",...) do
-				local self = select(i,...)
-				if registry.insertQueue then
-					for eventname, callbacks in pairs(registry.insertQueue) do
-						if callbacks[self] then
-							callbacks[self] = nil
-						end
-					end
-				end
-				for eventname, callbacks in pairs(events) do
-					if callbacks[self] then
-						callbacks[self] = nil
-						-- Fire OnUnused callback?
-						if registry.OnUnused and not next(callbacks) then
-							registry.OnUnused(registry, target, eventname)
-						end
-					end
-				end
-			end
-		end
-	end
-
-	return registry
-end
-
-
--- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
--- try to upgrade old implicit embeds since the system is selfcontained and
--- relies on closures to work.
-
+--[[ $Id: CallbackHandler-1.0.lua 14 2010-08-09 00:43:38Z mikk $ ]]
+local MAJOR, MINOR = "CallbackHandler-1.0", 6
+local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not CallbackHandler then return end -- No upgrade needed
+
+local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
+
+-- Lua APIs
+local tconcat = table.concat
+local assert, error, loadstring = assert, error, loadstring
+local setmetatable, rawset, rawget = setmetatable, rawset, rawget
+local next, select, pairs, type, tostring = next, select, pairs, type, tostring
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: geterrorhandler
+
+local xpcall = xpcall
+
+local function errorhandler(err)
+	return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+	local code = [[
+	local next, xpcall, eh = ...
+
+	local method, ARGS
+	local function call() method(ARGS) end
+
+	local function dispatch(handlers, ...)
+		local index
+		index, method = next(handlers)
+		if not method then return end
+		local OLD_ARGS = ARGS
+		ARGS = ...
+		repeat
+			xpcall(call, eh)
+			index, method = next(handlers, index)
+		until not method
+		ARGS = OLD_ARGS
+	end
+
+	return dispatch
+	]]
+
+	local ARGS, OLD_ARGS = {}, {}
+	for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
+	code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
+	return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {__index=function(self, argCount)
+	local dispatcher = CreateDispatcher(argCount)
+	rawset(self, argCount, dispatcher)
+	return dispatcher
+end})
+
+--------------------------------------------------------------------------
+-- CallbackHandler:New
+--
+--   target            - target object to embed public APIs in
+--   RegisterName      - name of the callback registration API, default "RegisterCallback"
+--   UnregisterName    - name of the callback unregistration API, default "UnregisterCallback"
+--   UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
+
+function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
+	-- TODO: Remove this after beta has gone out
+	assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
+
+	RegisterName = RegisterName or "RegisterCallback"
+	UnregisterName = UnregisterName or "UnregisterCallback"
+	if UnregisterAllName==nil then	-- false is used to indicate "don't want this method"
+		UnregisterAllName = "UnregisterAllCallbacks"
+	end
+
+	-- we declare all objects and exported APIs inside this closure to quickly gain access
+	-- to e.g. function names, the "target" parameter, etc
+
+
+	-- Create the registry object
+	local events = setmetatable({}, meta)
+	local registry = { recurse=0, events=events }
+
+	-- registry:Fire() - fires the given event/message into the registry
+	function registry:Fire(eventname, ...)
+		if not rawget(events, eventname) or not next(events[eventname]) then return end
+		local oldrecurse = registry.recurse
+		registry.recurse = oldrecurse + 1
+
+		Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
+
+		registry.recurse = oldrecurse
+
+		if registry.insertQueue and oldrecurse==0 then
+			-- Something in one of our callbacks wanted to register more callbacks; they got queued
+			for eventname,callbacks in pairs(registry.insertQueue) do
+				local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+				for self,func in pairs(callbacks) do
+					events[eventname][self] = func
+					-- fire OnUsed callback?
+					if first and registry.OnUsed then
+						registry.OnUsed(registry, target, eventname)
+						first = nil
+					end
+				end
+			end
+			registry.insertQueue = nil
+		end
+	end
+
+	-- Registration of a callback, handles:
+	--   self["method"], leads to self["method"](self, ...)
+	--   self with function ref, leads to functionref(...)
+	--   "addonId" (instead of self) with function ref, leads to functionref(...)
+	-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
+	target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
+		if type(eventname) ~= "string" then
+			error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
+		end
+
+		method = method or eventname
+
+		local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+
+		if type(method) ~= "string" and type(method) ~= "function" then
+			error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
+		end
+
+		local regfunc
+
+		if type(method) == "string" then
+			-- self["method"] calling style
+			if type(self) ~= "table" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
+			elseif self==target then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
+			elseif type(self[method]) ~= "function" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) self[method](self,arg,...) end
+			else
+				regfunc = function(...) self[method](self,...) end
+			end
+		else
+			-- function ref with self=object or self="addonId" or self=thread
+			if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
+				error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) method(arg,...) end
+			else
+				regfunc = method
+			end
+		end
+
+
+		if events[eventname][self] or registry.recurse<1 then
+		-- if registry.recurse<1 then
+			-- we're overwriting an existing entry, or not currently recursing. just set it.
+			events[eventname][self] = regfunc
+			-- fire OnUsed callback?
+			if registry.OnUsed and first then
+				registry.OnUsed(registry, target, eventname)
+			end
+		else
+			-- we're currently processing a callback in this registry, so delay the registration of this new entry!
+			-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
+			registry.insertQueue = registry.insertQueue or setmetatable({},meta)
+			registry.insertQueue[eventname][self] = regfunc
+		end
+	end
+
+	-- Unregister a callback
+	target[UnregisterName] = function(self, eventname)
+		if not self or self==target then
+			error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
+		end
+		if type(eventname) ~= "string" then
+			error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
+		end
+		if rawget(events, eventname) and events[eventname][self] then
+			events[eventname][self] = nil
+			-- Fire OnUnused callback?
+			if registry.OnUnused and not next(events[eventname]) then
+				registry.OnUnused(registry, target, eventname)
+			end
+		end
+		if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
+			registry.insertQueue[eventname][self] = nil
+		end
+	end
+
+	-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
+	if UnregisterAllName then
+		target[UnregisterAllName] = function(...)
+			if select("#",...)<1 then
+				error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
+			end
+			if select("#",...)==1 and ...==target then
+				error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
+			end
+
+
+			for i=1,select("#",...) do
+				local self = select(i,...)
+				if registry.insertQueue then
+					for eventname, callbacks in pairs(registry.insertQueue) do
+						if callbacks[self] then
+							callbacks[self] = nil
+						end
+					end
+				end
+				for eventname, callbacks in pairs(events) do
+					if callbacks[self] then
+						callbacks[self] = nil
+						-- Fire OnUnused callback?
+						if registry.OnUnused and not next(callbacks) then
+							registry.OnUnused(registry, target, eventname)
+						end
+					end
+				end
+			end
+		end
+	end
+
+	return registry
+end
+
+
+-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
+-- try to upgrade old implicit embeds since the system is selfcontained and
+-- relies on closures to work.
+
diff --git a/libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml b/libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
index 876df83..a5b22a7 100644
--- a/libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
+++ b/libs/LibWho-2.0/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
@@ -1,4 +1,4 @@
-<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
-..\FrameXML\UI.xsd">
-	<Script file="CallbackHandler-1.0.lua"/>
-</Ui>
\ No newline at end of file
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
+..\FrameXML\UI.xsd">
+	<Script file="CallbackHandler-1.0.lua"/>
+</Ui>
diff --git a/libs/LibWho-2.0/libs/LibStub/LibStub.lua b/libs/LibWho-2.0/libs/LibStub/LibStub.lua
index 7e9b5cd..7e7b76d 100644
--- a/libs/LibWho-2.0/libs/LibStub/LibStub.lua
+++ b/libs/LibWho-2.0/libs/LibStub/LibStub.lua
@@ -1,51 +1,51 @@
--- $Id: LibStub.lua 103 2014-10-16 03:02:50Z mikk $
--- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/addons/libstub/ for more info
--- LibStub is hereby placed in the Public Domain
--- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
-local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
-local LibStub = _G[LIBSTUB_MAJOR]
-
--- Check to see is this version of the stub is obsolete
-if not LibStub or LibStub.minor < LIBSTUB_MINOR then
-	LibStub = LibStub or {libs = {}, minors = {} }
-	_G[LIBSTUB_MAJOR] = LibStub
-	LibStub.minor = LIBSTUB_MINOR
-
-	-- LibStub:NewLibrary(major, minor)
-	-- major (string) - the major version of the library
-	-- minor (string or number ) - the minor version of the library
-	--
-	-- returns nil if a newer or same version of the lib is already present
-	-- returns empty library object or old library object if upgrade is needed
-	function LibStub:NewLibrary(major, minor)
-		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
-		minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
-
-		local oldminor = self.minors[major]
-		if oldminor and oldminor >= minor then return nil end
-		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
-		return self.libs[major], oldminor
-	end
-
-	-- LibStub:GetLibrary(major, [silent])
-	-- major (string) - the major version of the library
-	-- silent (boolean) - if true, library is optional, silently return nil if its not found
-	--
-	-- throws an error if the library can not be found (except silent is set)
-	-- returns the library object if found
-	function LibStub:GetLibrary(major, silent)
-		if not self.libs[major] and not silent then
-			error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
-		end
-		return self.libs[major], self.minors[major]
-	end
-
-	-- LibStub:IterateLibraries()
-	--
-	-- Returns an iterator for the currently registered libraries
-	function LibStub:IterateLibraries()
-		return pairs(self.libs)
-	end
-
-	setmetatable(LibStub, { __call = LibStub.GetLibrary })
-end
+-- $Id: LibStub.lua 103 2014-10-16 03:02:50Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/addons/libstub/ for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+	LibStub = LibStub or {libs = {}, minors = {} }
+	_G[LIBSTUB_MAJOR] = LibStub
+	LibStub.minor = LIBSTUB_MINOR
+
+	-- LibStub:NewLibrary(major, minor)
+	-- major (string) - the major version of the library
+	-- minor (string or number ) - the minor version of the library
+	--
+	-- returns nil if a newer or same version of the lib is already present
+	-- returns empty library object or old library object if upgrade is needed
+	function LibStub:NewLibrary(major, minor)
+		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+		minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+		local oldminor = self.minors[major]
+		if oldminor and oldminor >= minor then return nil end
+		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+		return self.libs[major], oldminor
+	end
+
+	-- LibStub:GetLibrary(major, [silent])
+	-- major (string) - the major version of the library
+	-- silent (boolean) - if true, library is optional, silently return nil if its not found
+	--
+	-- throws an error if the library can not be found (except silent is set)
+	-- returns the library object if found
+	function LibStub:GetLibrary(major, silent)
+		if not self.libs[major] and not silent then
+			error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+		end
+		return self.libs[major], self.minors[major]
+	end
+
+	-- LibStub:IterateLibraries()
+	--
+	-- Returns an iterator for the currently registered libraries
+	function LibStub:IterateLibraries()
+		return pairs(self.libs)
+	end
+
+	setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/libs/LibWho-2.0/libs/LibStub/LibStub.toc b/libs/LibWho-2.0/libs/LibStub/LibStub.toc
index ac4a1c4..12077be 100644
--- a/libs/LibWho-2.0/libs/LibStub/LibStub.toc
+++ b/libs/LibWho-2.0/libs/LibStub/LibStub.toc
@@ -1,13 +1,13 @@
-## Interface: 60000
-## Title: Lib: LibStub
-## Notes: Universal Library Stub
-## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
-## X-Website: http://www.wowace.com/addons/libstub/
-## X-Category: Library
-## X-License: Public Domain
-## X-Curse-Packaged-Version: 1.0.2.60000
-## X-Curse-Project-Name: LibStub
-## X-Curse-Project-ID: libstub
-## X-Curse-Repository-ID: wow/libstub/mainline
-
-LibStub.lua
+## Interface: 60000
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: 1.0.2.60000
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/libs/LibWho-2.0/libs/LibStub/tests/test.lua b/libs/LibWho-2.0/libs/LibStub/tests/test.lua
index 276ddab..fb3bcbd 100644
--- a/libs/LibWho-2.0/libs/LibStub/tests/test.lua
+++ b/libs/LibWho-2.0/libs/LibStub/tests/test.lua
@@ -1,41 +1,41 @@
-debugstack = debug.traceback
-strmatch = string.match
-
-loadfile("../LibStub.lua")()
-
-local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
-assert(lib) -- should return the library table
-assert(not oldMinor) -- should not return the old minor, since it didn't exist
-
--- the following is to create data and then be able to check if the same data exists after the fact
-function lib:MyMethod()
-end
-local MyMethod = lib.MyMethod
-lib.MyTable = {}
-local MyTable = lib.MyTable
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
-assert(not newLib) -- should not return since out of date
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
-assert(not newLib) -- should not return since out of date
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
-assert(newLib) -- library table
-assert(rawequal(newLib, lib)) -- should be the same reference as the previous
-assert(newOldMinor == 1) -- should return the minor version of the previous version
-
-assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
-assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
-assert(newLib) -- library table
-assert(newOldMinor == 2) -- previous version was 2
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
-assert(newLib)
-assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
-assert(newLib)
-assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
diff --git a/libs/LibWho-2.0/libs/LibStub/tests/test2.lua b/libs/LibWho-2.0/libs/LibStub/tests/test2.lua
index eae7172..af431dd 100644
--- a/libs/LibWho-2.0/libs/LibStub/tests/test2.lua
+++ b/libs/LibWho-2.0/libs/LibStub/tests/test2.lua
@@ -1,27 +1,27 @@
-debugstack = debug.traceback
-strmatch = string.match
-
-loadfile("../LibStub.lua")()
-
-for major, library in LibStub:IterateLibraries() do
-	-- check that MyLib doesn't exist yet, by iterating through all the libraries
-	assert(major ~= "MyLib")
-end
-
-assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
-assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
-local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
-assert(lib) -- check it exists
-assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
-
-assert(LibStub:NewLibrary("MyLib", 2))	-- create a new version
-
-local count=0
-for major, library in LibStub:IterateLibraries() do
-	-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
-	if major == "MyLib" then -- we found it!
-		count = count +1
-		assert(rawequal(library, lib)) -- verify that the references are equal
-	end
-end
-assert(count == 1) -- verify that we actually found it, and only once
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+	-- check that MyLib doesn't exist yet, by iterating through all the libraries
+	assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2))	-- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+	-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+	if major == "MyLib" then -- we found it!
+		count = count +1
+		assert(rawequal(library, lib)) -- verify that the references are equal
+	end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/libs/LibWho-2.0/libs/LibStub/tests/test3.lua b/libs/LibWho-2.0/libs/LibStub/tests/test3.lua
index 30f7b94..3c06002 100644
--- a/libs/LibWho-2.0/libs/LibStub/tests/test3.lua
+++ b/libs/LibWho-2.0/libs/LibStub/tests/test3.lua
@@ -1,14 +1,14 @@
-debugstack = debug.traceback
-strmatch = string.match
-
-loadfile("../LibStub.lua")()
-
-local proxy = newproxy() -- non-string
-
-assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
-local success, ret = pcall(LibStub.GetLibrary, proxy, true)
-assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
-
-assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
-
-assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
diff --git a/libs/LibWho-2.0/libs/LibStub/tests/test4.lua b/libs/LibWho-2.0/libs/LibStub/tests/test4.lua
index 43eb338..294623b 100644
--- a/libs/LibWho-2.0/libs/LibStub/tests/test4.lua
+++ b/libs/LibWho-2.0/libs/LibStub/tests/test4.lua
@@ -1,41 +1,41 @@
-debugstack = debug.traceback
-strmatch = string.match
-
-loadfile("../LibStub.lua")()
-
-
--- Pretend like loaded libstub is old and doesn't have :IterateLibraries
-assert(LibStub.minor)
-LibStub.minor = LibStub.minor - 0.0001
-LibStub.IterateLibraries = nil
-
-loadfile("../LibStub.lua")()
-
-assert(type(LibStub.IterateLibraries)=="function")
-
-
--- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
-LibStub.IterateLibraries = 123
-
-loadfile("../LibStub.lua")()
-
-assert(LibStub.IterateLibraries == 123)
-
-
--- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
-LibStub.minor = LibStub.minor + 0.0001
-
-loadfile("../LibStub.lua")()
-
-assert(LibStub.IterateLibraries == 123)
-
-
--- Again with a huge number
-LibStub.minor = LibStub.minor + 1234567890
-
-loadfile("../LibStub.lua")()
-
-assert(LibStub.IterateLibraries == 123)
-
-
-print("OK")
\ No newline at end of file
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
diff --git a/libs/LibWho-2.0XX/LibWho-2.0.lua b/libs/LibWho-2.0XX/LibWho-2.0.lua
index 7abeb6c..30cf02a 100644
--- a/libs/LibWho-2.0XX/LibWho-2.0.lua
+++ b/libs/LibWho-2.0XX/LibWho-2.0.lua
@@ -1,948 +1,948 @@
----
---- check for an already loaded old WhoLib
----
-
-if WhoLibByALeX or WhoLib then
-	-- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail!
-	error("an other WhoLib is already running - disable them first!\n")
-	return
-end -- if
-
----
---- check version
----
-
-assert(LibStub, "LibWho-2.0 requires LibStub")
-
-
-local major_version = 'LibWho-2.0'
-local minor_version = tonumber("136") or 99999
-
-local lib = LibStub:NewLibrary(major_version, minor_version)
-
-
-if not lib then
-	return	-- already loaded and no upgrade necessary
-end
-
-lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
-local callbacks = lib.callbacks
-
-local am = {}
-local om = getmetatable(lib)
-if om then
-	for k, v in pairs(om) do am[k] = v end
-end
-am.__tostring = function() return major_version end
-setmetatable(lib, am)
-
-local function dbgfunc(...) if lib.Debug then print(...) end end
-local function NOP() return end
-local dbg = NOP
-
----
---- initalize base
----
-
-if type(lib['hooked']) ~= 'table' then
-	lib['hooked'] = {}
-end -- if
-
-if type(lib['hook']) ~= 'table' then
-	lib['hook'] = {}
-end -- if
-
-if type(lib['events']) ~= 'table' then
-	lib['events'] = {}
-end -- if
-
-if type(lib['embeds']) ~= 'table' then
-	lib['embeds'] = {}
-end -- if
-
-if type(lib['frame']) ~= 'table' then
-	lib['frame'] = CreateFrame('Frame', major_version);
-end -- if
-lib['frame']:Hide()
-
-lib.Queue = {[1]={}, [2]={}, [3]={}}
-lib.WhoInProgress = false
-lib.Result = nil
-lib.Args = nil
-lib.Total = nil
-lib.Quiet = nil
-lib.Debug = false
-lib.Cache = {}
-lib.CacheQueue = {}
-lib.SetWhoToUIState = 0
-
-
-lib.MinInterval = 2.5
-lib.MaxInterval = 10
-
----
---- locale
----
-
-if (GetLocale() == "ruRU") then
-	lib.L = {
-		['console_queued'] = 'Добавлено в очередь "/who %s"',
-		['console_query'] = 'Результат "/who %s"',
-		['gui_wait'] = '- Пожалуйста подождите -',
-	}
-else
-	-- enUS is the default
-	lib.L = {
-		['console_queued'] = 'Added "/who %s" to queue',
-		['console_query'] = 'Result of "/who %s"',
-		['gui_wait'] = '- Please Wait -',
-	}
-end -- if
-
-
----
---- external functions/constants
----
-
-lib['external'] = {
-	'WHOLIB_QUEUE_USER',
-	'WHOLIB_QUEUE_QUIET',
-	'WHOLIB_QUEUE_SCANNING',
-	'WHOLIB_FLAG_ALWAYS_CALLBACK',
-	'Who',
-	'UserInfo',
-	'CachedUserInfo',
-	'GetWhoLibDebug',
-	'SetWhoLibDebug',
---	'RegisterWhoLibEvent',
-}
-
--- queues
-lib['WHOLIB_QUEUE_USER'] = 1
-lib['WHOLIB_QUEUE_QUIET'] = 2
-lib['WHOLIB_QUEUE_SCANNING'] = 3
-
-
-
-local queue_all = {
-	[1] = 'WHOLIB_QUEUE_USER',
-	[2] = 'WHOLIB_QUEUE_QUIET',
-	[3] = 'WHOLIB_QUEUE_SCANNING',
-}
-
-local queue_quiet = {
-	[2] = 'WHOLIB_QUEUE_QUIET',
-	[3] = 'WHOLIB_QUEUE_SCANNING',
-}
-
--- bit masks!
-lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1
-
-function lib:Reset()
-    self.Queue = {[1]={}, [2]={}, [3]={}}
-    self.Cache = {}
-    self.CacheQueue = {}
-end
-
-function lib.Who(defhandler, query, opts)
-	local self, args, usage = lib, {}, 'Who(query, [opts])'
-
-	args.query = self:CheckArgument(usage, 'query', 'string', query)
-	opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
-	args.queue = self:CheckPreset(usage, 'opts.queue', queue_all, opts.queue, self.WHOLIB_QUEUE_SCANNING)
-	args.flags = self:CheckArgument(usage, 'opts.flags', 'number', flags, 0)
-	args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler)
-	-- now args - copied and verified from opts
-
-	if args.queue == self.WHOLIB_QUEUE_USER then
-		if WhoFrame:IsShown() then
-			self:GuiWho(args.query)
-		else
-			self:ConsoleWho(args.query)
-		end
-	else
-		self:AskWho(args)
-	end
-end
-
-local function ignoreRealm(name)
-	local _, realm = string.split("-", name)
- 	local connectedServers = GetAutoCompleteRealms()
- 	if connectedServers then
-		for i = 1, #connectedServers do
- 	 		if realm == connectedServers[i] then return false end
-		end
- 	end
-    return true
-end
-
-function lib.UserInfo(defhandler, name, opts)
-	local self, args, usage = lib, {}, 'UserInfo(name, [opts])'
-	local now = time()
-
-    name = self:CheckArgument(usage, 'name', 'string', name)
-    if name:len() == 0 then return end
-
-    --There is no api to tell connected realms from cross realm by name. As such, we check known connections table before excluding who inquiry
-    --UnitRealmRelationship and UnitIsSameServer don't work with "name". They require unitID so they are useless here
-    if name:find("%-") and ignoreRealm(name) then return end
-
-	args.name = self:CapitalizeInitial(name)
-	opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
-	args.queue = self:CheckPreset(usage, 'opts.queue', queue_quiet, opts.queue, self.WHOLIB_QUEUE_SCANNING)
-	args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
-	args.timeout = self:CheckArgument(usage, 'opts.timeout', 'number', opts.timeout, 5)
-	args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback,  opts.handler, defhandler)
-
-	-- now args - copied and verified from opts
-	local cachedName = self.Cache[args.name]
-
-	if(cachedName ~= nil)then
-		-- user is in cache
-		if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then
-			-- cache is valid and timeout is in range
-			--dbg('Info(' .. args.name ..') returned immedeatly')
-			if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then
-				self:RaiseCallback(args, cachedName.data)
-				return false
-			else
-				return self:DupAll(self:ReturnUserInfo(args.name))
-			end
-		elseif(cachedName.valid == false)then
-			-- query is already running (first try)
-			if(args.callback ~= nil)then
-				tinsert(cachedName.callback, args)
-			end
-			--dbg('Info(' .. args.name ..') returned cause it\'s already searching')
-			return nil
-		end
-	else
-		self.Cache[args.name] = {valid=false, inqueue=false, callback={}, data={Name = args.name}, last=now }
-	end
-
-	local cachedName = self.Cache[args.name]
-
-	if(cachedName.inqueue)then
-		-- query is running!
-		if(args.callback ~= nil)then
-			tinsert(cachedName.callback, args)
-		end
-		dbg('Info(' .. args.name ..') returned cause it\'s already searching')
-		return nil
-	end
-	if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon
-    if args.name and args.name:len() > 0 then
-    	local query = 'и-"' .. args.name .. '"'
-    	cachedName.inqueue = true
-    	if(args.callback ~= nil)then
-    		tinsert(cachedName.callback, args)
-    	end
-    	self.CacheQueue[query] = args.name
-    	dbg('Info(' .. args.name ..') added to queue')
-    	self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
-    end
-	else
-	    if args.name and args.name:len() > 0 then
-    	local query = 'n-"' .. args.name .. '"'
-    	cachedName.inqueue = true
-    	if(args.callback ~= nil)then
-    		tinsert(cachedName.callback, args)
-    	end
-    	self.CacheQueue[query] = args.name
-    	dbg('Info(' .. args.name ..') added to queue')
-    	self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
-    end
-	end
-	return nil
-end
-
-function lib.CachedUserInfo(_, name)
-	local self, usage = lib, 'CachedUserInfo(name)'
-
-	name = self:CapitalizeInitial(self:CheckArgument(usage, 'name', 'string', name))
-
-	if self.Cache[name] == nil then
-		return nil
-	else
-		return self:DupAll(self:ReturnUserInfo(name))
-	end
-end
-
-function lib.GetWhoLibDebug(_, mode)
-    return lib.Debug
-end
-
-function lib.SetWhoLibDebug(_, mode)
-    lib.Debug = mode
-	dbg = mode and dbgfunc or NOP
-end
-
---function lib.RegisterWhoLibEvent(defhandler, event, callback, handler)
---	local self, usage = lib, 'RegisterWhoLibEvent(event, callback, [handler])'
---
---	self:CheckPreset(usage, 'event', self.events, event)
---	local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true)
---	table.insert(self.events[event], {callback=callback, handler=handler})
---end
-
--- non-embedded externals
-
-function lib.Embed(_, handler)
-	local self, usage = lib, 'Embed(handler)'
-
-	self:CheckArgument(usage, 'handler', 'table', handler)
-
-	for _,name in pairs(self.external) do
-		handler[name] = self[name]
-	end -- do
-	 self['embeds'][handler] = true
-
-	return handler
-end
-
-function lib.Library(_)
-	local self = lib
-
-	return self:Embed({})
-end
-
----
---- internal functions
----
-
-function lib:AllQueuesEmpty()
-    local queueCount = #self.Queue[1] + #self.Queue[2] + #self.Queue[3] + #self.CacheQueue
-
-    -- Be sure that we have cleared the in-progress status
-    if self.WhoInProgress then
-        queueCount = queueCount + 1
-    end
-
-	return queueCount == 0
-end
-
-local queryInterval = 5
-
-function lib:GetQueryInterval() return queryInterval end
-
-function lib:AskWhoNextIn5sec()
-	if self.frame:IsShown() then return end
-
-	dbg("Waiting to send next who")
-	self.Timeout_time = queryInterval
-	self['frame']:Show()
-end
-
-function lib:CancelPendingWhoNext()
-	lib['frame']:Hide()
-end
-
-lib['frame']:SetScript("OnUpdate", function(frame, elapsed)
-	lib.Timeout_time = lib.Timeout_time - elapsed
-	if lib.Timeout_time <= 0 then
-		lib['frame']:Hide()
-		lib:AskWhoNext()
-	end -- if
-end);
-
-
--- queue scheduler
-local queue_weights = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
-local queue_bounds = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
-
--- allow for single queries from the user to get processed faster
-local lastInstantQuery = time()
-local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min
-
-function lib:UpdateWeights()
-   local weightsum, sum, count = 0, 0, 0
-   for k,v in pairs(queue_weights) do
-        sum = sum + v
-        weightsum = weightsum + v * #self.Queue[k]
-   end
-
-   if weightsum == 0 then
-        for k,v in pairs(queue_weights) do queue_bounds[k] = v end
-        return
-   end
-
-   local adjust = sum / weightsum
-
-   for k,v in pairs(queue_bounds) do
-        queue_bounds[k] = queue_weights[k] * adjust * #self.Queue[k]
-   end
-end
-
-function lib:GetNextFromScheduler()
-   self:UpdateWeights()
-
-   -- Since an addon could just fill up the user q for instant processing
-   -- we have to limit instants to 1 per INSTANT_QUERY_MIN_INTERVAL
-   -- and only try instant fulfilment if it will empty the user queue
-   if #self.Queue[1] == 1 then
-		if time() - lastInstantQuery > INSTANT_QUERY_MIN_INTERVAL then
-			dbg("INSTANT")
-			lastInstantQuery = time()
-			return 1, self.Queue[1]
-		end
-   end
-
-   local n,i = math.random(),0
-   repeat
-        i=i+1
-        n = n - queue_bounds[i]
-   until i>=#self.Queue or n <= 0
-
-   dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i]))
-
-   if #self.Queue[i] > 0 then
-        dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i]))
-       return i, self.Queue[i]
-   else
-        dbg("Queues empty, waiting")
-   end
-end
-
-lib.queue_bounds = queue_bounds
-
-function lib:AskWhoNext()
-	if lib.frame:IsShown() then
-		dbg("Already waiting")
-		return
-	end
-
-	self:CancelPendingWhoNext()
-
-	if self.WhoInProgress then
-		-- if we had a who going, it didnt complete
-		dbg("TIMEOUT: "..self.Args.query)
-		local args = self.Args
-		self.Args = nil
---		if args.info and self.CacheQueue[args.query] ~= nil then
-			dbg("Requeing "..args.query)
-			tinsert(self.Queue[args.queue], args)
-			if args.console_show ~= nil then
-				DEFAULT_CHAT_FRAME:AddMessage(("Timeout on result of '%s' - retrying..."):format(args.query),1,1,0)
-				args.console_show = true
-			end
---		end
-
-		if queryInterval < lib.MaxInterval then
-			queryInterval = queryInterval + 0.5
-			dbg("--Throttling down to 1 who per " .. queryInterval .. "s")
-		end
-	end
-
-
-	self.WhoInProgress = false
-
-	local v,k,args = nil
-    local kludge = 10
-	repeat
-        k,v = self:GetNextFromScheduler()
-        if not k then break end
-		if(WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET)then
-			break
-		end
-		if(#v > 0)then
-			args = tremove(v, 1)
-			break
-		end
-        kludge = kludge - 1
-	until kludge <= 0
-
-	if args then
-		self.WhoInProgress = true
-		self.Result = {}
-		self.Args = args
-		self.Total = -1
-		if(args.console_show == true)then
-			DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0)
-
-		end
-
-		if args.queue == self.WHOLIB_QUEUE_USER then
-			WhoFrameEditBox:SetText(args.query)
-			self.Quiet = false
-
-			if args.whotoui then
-    			self.hooked.SetWhoToUI(args.whotoui)
-    		else
-    			self.hooked.SetWhoToUI(args.gui and 1 or 0)
-			end
-		else
-			self.hooked.SetWhoToUI(1)
-			self.Quiet = true
-		end
-
-		dbg("QUERY: "..args.query)
-		self.hooked.SendWho(args.query)
-	else
-		self.Args = nil
-		self.WhoInProgress = false
-	end
-
-    -- Keep processing the who queue if there is more work
-	if not self:AllQueuesEmpty() then
-		self:AskWhoNextIn5sec()
-    else
-        dbg("*** Done processing requests ***")
-	end
-end
-
-function lib:AskWho(args)
-	tinsert(self.Queue[args.queue], args)
-	dbg('[' .. args.queue .. '] added "' .. args.query .. '", queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3])
-	self:TriggerEvent('WHOLIB_QUERY_ADDED')
-
-	self:AskWhoNext()
-end
-
-function lib:ReturnWho()
-    if not self.Args then
-        self.Quiet = nil
-        return
-    end
-
-	if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then
-		self.Quiet = nil
-	end
-
-	if queryInterval > self.MinInterval then
-		queryInterval = queryInterval - 0.5
-		dbg("--Throttling up to 1 who per " .. queryInterval .. "s")
-	end
-
-	self.WhoInProgress = false
-	dbg("RESULT: "..self.Args.query)
-	dbg('[' .. self.Args.queue .. '] returned "' .. self.Args.query .. '", total=' .. self.Total ..' , queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3])
-	local now = time()
-	local complete = (self.Total == #self.Result) and (self.Total < MAX_WHOS_FROM_SERVER)
-	for _,v in pairs(self.Result)do
-		if(self.Cache[v.Name] == nil)then
-			self.Cache[v.Name] = { inqueue = false, callback = {} }
-		end
-
-		local cachedName = self.Cache[v.Name]
-
-		cachedName.valid = true -- is now valid
-		cachedName.data = v -- update data
-		cachedName.data.Online = true -- player is online
-		cachedName.last = now -- update timestamp
-		if(cachedName.inqueue)then
-			if(self.Args.info and self.CacheQueue[self.Args.query] == v.Name)then
-				-- found by the query which was created to -> remove us from query
-				self.CacheQueue[self.Args.query] = nil
-			else
-				-- found by another query
-				for k2,v2 in pairs(self.CacheQueue) do
-					if(v2 == v.Name)then
-						for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do
-							for k3,v3 in pairs(self.Queue[i]) do
-								if(v3.query == k2 and v3.info)then
-									-- remove the query which was generated for this user, cause another query was faster...
-									dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'")
-									table.remove(self.Queue[i], k3)
-									self.CacheQueue[k2] = nil
-								end
-							end
-						end
-					end
-				end
-			end
-			dbg('Info(' .. v.Name ..') returned: on')
-			for _,v2 in pairs(cachedName.callback) do
-				self:RaiseCallback(v2, self:ReturnUserInfo(v.Name))
-			end
-			cachedName.callback = {}
-		end
-		cachedName.inqueue = false -- query is done
-	end
-	if(self.Args.info and self.CacheQueue[self.Args.query])then
-		-- the query did not deliver the result => not online!
-		local name = self.CacheQueue[self.Args.query]
-		local cachedName = self.Cache[name]
-		if (cachedName.inqueue)then
-			-- nothing found (yet)
-			cachedName.valid = true -- is now valid
-			cachedName.inqueue = false -- query is done?
-			cachedName.last = now -- update timestamp
-			if(complete)then
-				cachedName.data.Online = false -- player is offline
-			else
-				cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed)
-			end
-		end
-		dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn'))
-		for _,v in pairs(cachedName.callback) do
-			self:RaiseCallback(v, self:ReturnUserInfo(name))
-		end
-		cachedName.callback = {}
-		self.CacheQueue[self.Args.query] = nil
-	end
-	self:RaiseCallback(self.Args, self.Args.query, self.Result, complete, self.Args.info)
-	self:TriggerEvent('WHOLIB_QUERY_RESULT', self.Args.query, self.Result, complete, self.Args.info)
-
-	if not self:AllQueuesEmpty() then
-		self:AskWhoNextIn5sec()
-	end
-end
-
-function lib:GuiWho(msg)
-	if(msg == self.L['gui_wait'])then
-		return
-	end
-
-	for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do
-		if(v.gui == true)then
-			return
-		end
-	end
-	if(self.WhoInProgress)then
-		WhoFrameEditBox:SetText(self.L['gui_wait'])
-	end
-	self.savedText = msg
-	self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true})
-	WhoFrameEditBox:ClearFocus();
-end
-
-function lib:ConsoleWho(msg)
-	--WhoFrameEditBox:SetText(msg)
-	local console_show = false
-	local q1 = self.Queue[self.WHOLIB_QUEUE_USER]
-	local q1count = #q1
-
-	if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop
-		return
-	end
-
-	if(q1count > 0 and q1[q1count].console_show == false)then -- display 'queued' if console and not yet shown
-		DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], q1[q1count].query), 1, 1, 0)
-		q1[q1count].console_show = true
-	end
-	if(q1count > 0 or self.WhoInProgress)then
-		DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0)
-		console_show = true
-	end
-	self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show})
-end
-
-function lib:ReturnUserInfo(name)
-	if(name ~= nil and self ~= nil and self.Cache ~= nil and self.Cache[name] ~= nil) then
-		return self.Cache[name].data, (time() - self.Cache[name].last) / 60
-	end
-end
-
-function lib:RaiseCallback(args, ...)
-	if type(args.callback) == 'function' then
-		args.callback(self:DupAll(...))
-	elseif args.callback then -- must be a string
-		args.handler[args.callback](args.handler, self:DupAll(...))
-	end -- if
-end
-
--- Argument checking
-
-function lib:CheckArgument(func, name, argtype, arg, defarg)
-	if arg == nil and defarg ~= nil then
-		return defarg
-	elseif type(arg) == argtype then
-		return arg
-	else
-		error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3)
-	end -- if
-end
-
-function lib:CheckPreset(func, name, preset, arg, defarg)
-	if arg == nil and defarg ~= nil then
-		return defarg
-	elseif arg ~= nil and preset[arg] ~= nil then
-		return arg
-	else
-		local p = {}
-		for k,v in pairs(preset) do
-			if type(v) ~= 'string' then
-				table.insert(p, k)
-			else
-				table.insert(p, v)
-			end -- if
-		end -- for
-		error(string.format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3)
-	end -- if
-end
-
-function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil)
-	if not nonil and callback == nil then
-		-- no callback: ignore handler
-		return nil, nil
-	elseif type(callback) == 'function' then
-		-- simple function
-		if handler ~= nil then
-			error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3)
-		end -- if
-	elseif type(callback) == 'string' then
-		-- method
-		if handler == nil then
-			handler = defhandler
-		end -- if
-		if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then
-			error(string.format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3)
-		end -- if
-	else
-		error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3)
-	end -- if
-
-	return callback, handler
-end
-
--- helpers
-
-function lib:simple_dump(x)
-	if type(x) == 'string' then
-		return 'string \''..x..'\''
-	elseif type(x) == 'number' then
-		return 'number '..x
-	else
-		return type(x)
-	end
-end
-
-function lib:Dup(from)
-	local to = {}
-
-	for k,v in pairs(from) do
-		if type(v) == 'table' then
-			to[k] = self:Dup(v)
-		else
-			to[k] = v
-		end -- if
-	end -- for
-
-	return to
-end
-
-function lib:DupAll(x, ...)
-	if type(x) == 'table' then
-		return self:Dup(x), self:DupAll(...)
-	elseif x ~= nil then
-		return x, self:DupAll(...)
-	else
-		return nil
-	end -- if
-end
-
-local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)"
-
-function lib:CapitalizeInitial(name)
-    return name:gsub(MULTIBYTE_FIRST_CHAR, string.upper, 1)
-end
-
----
---- user events (Using CallbackHandler)
----
-
-lib.PossibleEvents = {
-	'WHOLIB_QUERY_RESULT',
-	'WHOLIB_QUERY_ADDED',
-}
-
-function lib:TriggerEvent(event, ...)
-    callbacks:Fire(event, ...)
-end
-
----
---- slash commands
----
-
-SlashCmdList['WHO'] = function(msg)
-	dbg("console /who: "..msg)
-	-- new /who function
-	--local self = lib
-
-	if(msg == '')then
-		lib:GuiWho(WhoFrame_GetDefaultWhoCommand())
-	elseif(WhoFrame:IsVisible())then
-		lib:GuiWho(msg)
-	else
-		lib:ConsoleWho(msg)
-	end
-end
-
-SlashCmdList['WHOLIB_DEBUG'] = function()
-	-- /wholibdebug: toggle debug on/off
-	local self = lib
-
-    self:SetWhoLibDebug(not self.Debug)
-end
-
-SLASH_WHOLIB_DEBUG1 = '/wholibdebug'
-
-
----
---- hook activation
----
-
--- functions to hook
-local hooks = {
-	'SendWho',
-	'WhoFrameEditBox_OnEnterPressed',
---	'FriendsFrame_OnEvent',
-	'SetWhoToUI',
-}
-
--- hook all functions (which are not yet hooked)
-for _, name in pairs(hooks) do
-	if not lib['hooked'][name] then
-		lib['hooked'][name] = _G[name]
-		_G[name] = function(...)
-			lib.hook[name](lib, ...)
-		end -- function
-	end -- if
-end -- for
-
--- fake 'WhoFrame:Hide' as hooked
-table.insert(hooks, 'WhoFrame_Hide')
-
--- check for unused hooks -> remove function
-for name, _ in pairs(lib['hook']) do
-	if not hooks[name] then
-		lib['hook'][name] = function() end
-	end -- if
-end -- for
-
--- secure hook 'WhoFrame:Hide'
-if not lib['hooked']['WhoFrame_Hide'] then
-	lib['hooked']['WhoFrame_Hide'] = true
-	hooksecurefunc(WhoFrame, 'Hide', function(...)
-			lib['hook']['WhoFrame_Hide'](lib, ...)
-		end -- function
-	)
-end -- if
-
-
-
------ Coroutine based implementation (future)
---function lib:sendWhoResult(val)
---    coroutine.yield(val)
---end
---
---function lib:sendWaitState(val)
---    coroutine.yield(val)
---end
---
---function lib:producer()
---    return coroutine.create(
---    function()
---        lib:AskWhoNext()
---        lib:sendWaitState(true)
---
---        -- Resumed look for data
---
---    end)
---end
-
-
-
-
-
----
---- hook replacements
----
-
-function lib.hook.SendWho(self, msg)
-	dbg("SendWho: "..msg)
-	lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0})
-end
-
-function lib.hook.WhoFrameEditBox_OnEnterPressed(self)
-	lib:GuiWho(WhoFrameEditBox:GetText())
-end
-
---[[
-function lib.hook.FriendsFrame_OnEvent(self, ...)
-	if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then
-		lib.hooked.FriendsFrame_OnEvent(...)
-	end
-end
-]]
-
-hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event)
-		if(event == "WHO_LIST_UPDATE") then
-			self:UnregisterEvent("WHO_LIST_UPDATE");
-		end
-	end);
-
-
-function lib.hook.SetWhoToUI(self, state)
-	lib.SetWhoToUIState = state
-end
-
-function lib.hook.WhoFrame_Hide(self)
-	if(not lib.WhoInProgress)then
-		lib:AskWhoNextIn5sec()
-	end
-end
-
-
----
---- WoW events
----
-
-local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+')
-
-
-function lib:CHAT_MSG_SYSTEM(arg1)
-	if arg1 and arg1:find(who_pattern) then
-		lib:ProcessWhoResults()
-	end
-end
-
-FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE")
-
-function lib:WHO_LIST_UPDATE()
-    if not lib.Quiet then
-		WhoList_Update()
-        FriendsFrame_Update()
-    end
-
-    lib:ProcessWhoResults()
-end
-
-function lib:ProcessWhoResults()
-	local num
-	self.Total, num = GetNumWhoResults()
-	for i=1, num do
-		local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i)
-		self.Result[i] = {Name=charname, Guild=guildname, Level=level, Race=race, Class=class, Zone=zone, NoLocaleClass=nonlocalclass, Sex=sex }
-	end
-
-	self:ReturnWho()
-end
-
----
---- event activation
----
-
-lib['frame']:UnregisterAllEvents();
-
-lib['frame']:SetScript("OnEvent", function(frame, event, ...)
-	lib[event](lib, ...)
-end);
-
-for _,name in pairs({
-	'CHAT_MSG_SYSTEM',
-	'WHO_LIST_UPDATE',
-}) do
-	lib['frame']:RegisterEvent(name);
-end -- for
-
-
----
---- re-embed
----
-
-for target,_ in pairs(lib['embeds']) do
-	if type(target) == 'table' then
-		lib:Embed(target)
-	end -- if
-end -- for
+---
+--- check for an already loaded old WhoLib
+---
+
+if WhoLibByALeX or WhoLib then
+	-- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail!
+	error("an other WhoLib is already running - disable them first!\n")
+	return
+end -- if
+
+---
+--- check version
+---
+
+assert(LibStub, "LibWho-2.0 requires LibStub")
+
+
+local major_version = 'LibWho-2.0'
+local minor_version = tonumber("136") or 99999
+
+local lib = LibStub:NewLibrary(major_version, minor_version)
+
+
+if not lib then
+	return	-- already loaded and no upgrade necessary
+end
+
+lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
+local callbacks = lib.callbacks
+
+local am = {}
+local om = getmetatable(lib)
+if om then
+	for k, v in pairs(om) do am[k] = v end
+end
+am.__tostring = function() return major_version end
+setmetatable(lib, am)
+
+local function dbgfunc(...) if lib.Debug then print(...) end end
+local function NOP() return end
+local dbg = NOP
+
+---
+--- initalize base
+---
+
+if type(lib['hooked']) ~= 'table' then
+	lib['hooked'] = {}
+end -- if
+
+if type(lib['hook']) ~= 'table' then
+	lib['hook'] = {}
+end -- if
+
+if type(lib['events']) ~= 'table' then
+	lib['events'] = {}
+end -- if
+
+if type(lib['embeds']) ~= 'table' then
+	lib['embeds'] = {}
+end -- if
+
+if type(lib['frame']) ~= 'table' then
+	lib['frame'] = CreateFrame('Frame', major_version);
+end -- if
+lib['frame']:Hide()
+
+lib.Queue = {[1]={}, [2]={}, [3]={}}
+lib.WhoInProgress = false
+lib.Result = nil
+lib.Args = nil
+lib.Total = nil
+lib.Quiet = nil
+lib.Debug = false
+lib.Cache = {}
+lib.CacheQueue = {}
+lib.SetWhoToUIState = 0
+
+
+lib.MinInterval = 2.5
+lib.MaxInterval = 10
+
+---
+--- locale
+---
+
+if (GetLocale() == "ruRU") then
+	lib.L = {
+		['console_queued'] = 'Добавлено в очередь "/who %s"',
+		['console_query'] = 'Результат "/who %s"',
+		['gui_wait'] = '- Пожалуйста подождите -',
+	}
+else
+	-- enUS is the default
+	lib.L = {
+		['console_queued'] = 'Added "/who %s" to queue',
+		['console_query'] = 'Result of "/who %s"',
+		['gui_wait'] = '- Please Wait -',
+	}
+end -- if
+
+
+---
+--- external functions/constants
+---
+
+lib['external'] = {
+	'WHOLIB_QUEUE_USER',
+	'WHOLIB_QUEUE_QUIET',
+	'WHOLIB_QUEUE_SCANNING',
+	'WHOLIB_FLAG_ALWAYS_CALLBACK',
+	'Who',
+	'UserInfo',
+	'CachedUserInfo',
+	'GetWhoLibDebug',
+	'SetWhoLibDebug',
+--	'RegisterWhoLibEvent',
+}
+
+-- queues
+lib['WHOLIB_QUEUE_USER'] = 1
+lib['WHOLIB_QUEUE_QUIET'] = 2
+lib['WHOLIB_QUEUE_SCANNING'] = 3
+
+
+
+local queue_all = {
+	[1] = 'WHOLIB_QUEUE_USER',
+	[2] = 'WHOLIB_QUEUE_QUIET',
+	[3] = 'WHOLIB_QUEUE_SCANNING',
+}
+
+local queue_quiet = {
+	[2] = 'WHOLIB_QUEUE_QUIET',
+	[3] = 'WHOLIB_QUEUE_SCANNING',
+}
+
+-- bit masks!
+lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1
+
+function lib:Reset()
+    self.Queue = {[1]={}, [2]={}, [3]={}}
+    self.Cache = {}
+    self.CacheQueue = {}
+end
+
+function lib.Who(defhandler, query, opts)
+	local self, args, usage = lib, {}, 'Who(query, [opts])'
+
+	args.query = self:CheckArgument(usage, 'query', 'string', query)
+	opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
+	args.queue = self:CheckPreset(usage, 'opts.queue', queue_all, opts.queue, self.WHOLIB_QUEUE_SCANNING)
+	args.flags = self:CheckArgument(usage, 'opts.flags', 'number', flags, 0)
+	args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler)
+	-- now args - copied and verified from opts
+
+	if args.queue == self.WHOLIB_QUEUE_USER then
+		if WhoFrame:IsShown() then
+			self:GuiWho(args.query)
+		else
+			self:ConsoleWho(args.query)
+		end
+	else
+		self:AskWho(args)
+	end
+end
+
+local function ignoreRealm(name)
+	local _, realm = string.split("-", name)
+ 	local connectedServers = GetAutoCompleteRealms()
+ 	if connectedServers then
+		for i = 1, #connectedServers do
+ 	 		if realm == connectedServers[i] then return false end
+		end
+ 	end
+    return true
+end
+
+function lib.UserInfo(defhandler, name, opts)
+	local self, args, usage = lib, {}, 'UserInfo(name, [opts])'
+	local now = time()
+
+    name = self:CheckArgument(usage, 'name', 'string', name)
+    if name:len() == 0 then return end
+
+    --There is no api to tell connected realms from cross realm by name. As such, we check known connections table before excluding who inquiry
+    --UnitRealmRelationship and UnitIsSameServer don't work with "name". They require unitID so they are useless here
+    if name:find("%-") and ignoreRealm(name) then return end
+
+	args.name = self:CapitalizeInitial(name)
+	opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
+	args.queue = self:CheckPreset(usage, 'opts.queue', queue_quiet, opts.queue, self.WHOLIB_QUEUE_SCANNING)
+	args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
+	args.timeout = self:CheckArgument(usage, 'opts.timeout', 'number', opts.timeout, 5)
+	args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback,  opts.handler, defhandler)
+
+	-- now args - copied and verified from opts
+	local cachedName = self.Cache[args.name]
+
+	if(cachedName ~= nil)then
+		-- user is in cache
+		if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then
+			-- cache is valid and timeout is in range
+			--dbg('Info(' .. args.name ..') returned immedeatly')
+			if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then
+				self:RaiseCallback(args, cachedName.data)
+				return false
+			else
+				return self:DupAll(self:ReturnUserInfo(args.name))
+			end
+		elseif(cachedName.valid == false)then
+			-- query is already running (first try)
+			if(args.callback ~= nil)then
+				tinsert(cachedName.callback, args)
+			end
+			--dbg('Info(' .. args.name ..') returned cause it\'s already searching')
+			return nil
+		end
+	else
+		self.Cache[args.name] = {valid=false, inqueue=false, callback={}, data={Name = args.name}, last=now }
+	end
+
+	local cachedName = self.Cache[args.name]
+
+	if(cachedName.inqueue)then
+		-- query is running!
+		if(args.callback ~= nil)then
+			tinsert(cachedName.callback, args)
+		end
+		dbg('Info(' .. args.name ..') returned cause it\'s already searching')
+		return nil
+	end
+	if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon
+    if args.name and args.name:len() > 0 then
+    	local query = 'и-"' .. args.name .. '"'
+    	cachedName.inqueue = true
+    	if(args.callback ~= nil)then
+    		tinsert(cachedName.callback, args)
+    	end
+    	self.CacheQueue[query] = args.name
+    	dbg('Info(' .. args.name ..') added to queue')
+    	self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
+    end
+	else
+	    if args.name and args.name:len() > 0 then
+    	local query = 'n-"' .. args.name .. '"'
+    	cachedName.inqueue = true
+    	if(args.callback ~= nil)then
+    		tinsert(cachedName.callback, args)
+    	end
+    	self.CacheQueue[query] = args.name
+    	dbg('Info(' .. args.name ..') added to queue')
+    	self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
+    end
+	end
+	return nil
+end
+
+function lib.CachedUserInfo(_, name)
+	local self, usage = lib, 'CachedUserInfo(name)'
+
+	name = self:CapitalizeInitial(self:CheckArgument(usage, 'name', 'string', name))
+
+	if self.Cache[name] == nil then
+		return nil
+	else
+		return self:DupAll(self:ReturnUserInfo(name))
+	end
+end
+
+function lib.GetWhoLibDebug(_, mode)
+    return lib.Debug
+end
+
+function lib.SetWhoLibDebug(_, mode)
+    lib.Debug = mode
+	dbg = mode and dbgfunc or NOP
+end
+
+--function lib.RegisterWhoLibEvent(defhandler, event, callback, handler)
+--	local self, usage = lib, 'RegisterWhoLibEvent(event, callback, [handler])'
+--
+--	self:CheckPreset(usage, 'event', self.events, event)
+--	local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true)
+--	table.insert(self.events[event], {callback=callback, handler=handler})
+--end
+
+-- non-embedded externals
+
+function lib.Embed(_, handler)
+	local self, usage = lib, 'Embed(handler)'
+
+	self:CheckArgument(usage, 'handler', 'table', handler)
+
+	for _,name in pairs(self.external) do
+		handler[name] = self[name]
+	end -- do
+	 self['embeds'][handler] = true
+
+	return handler
+end
+
+function lib.Library(_)
+	local self = lib
+
+	return self:Embed({})
+end
+
+---
+--- internal functions
+---
+
+function lib:AllQueuesEmpty()
+    local queueCount = #self.Queue[1] + #self.Queue[2] + #self.Queue[3] + #self.CacheQueue
+
+    -- Be sure that we have cleared the in-progress status
+    if self.WhoInProgress then
+        queueCount = queueCount + 1
+    end
+
+	return queueCount == 0
+end
+
+local queryInterval = 5
+
+function lib:GetQueryInterval() return queryInterval end
+
+function lib:AskWhoNextIn5sec()
+	if self.frame:IsShown() then return end
+
+	dbg("Waiting to send next who")
+	self.Timeout_time = queryInterval
+	self['frame']:Show()
+end
+
+function lib:CancelPendingWhoNext()
+	lib['frame']:Hide()
+end
+
+lib['frame']:SetScript("OnUpdate", function(frame, elapsed)
+	lib.Timeout_time = lib.Timeout_time - elapsed
+	if lib.Timeout_time <= 0 then
+		lib['frame']:Hide()
+		lib:AskWhoNext()
+	end -- if
+end);
+
+
+-- queue scheduler
+local queue_weights = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
+local queue_bounds = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
+
+-- allow for single queries from the user to get processed faster
+local lastInstantQuery = time()
+local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min
+
+function lib:UpdateWeights()
+   local weightsum, sum, count = 0, 0, 0
+   for k,v in pairs(queue_weights) do
+        sum = sum + v
+        weightsum = weightsum + v * #self.Queue[k]
+   end
+
+   if weightsum == 0 then
+        for k,v in pairs(queue_weights) do queue_bounds[k] = v end
+        return
+   end
+
+   local adjust = sum / weightsum
+
+   for k,v in pairs(queue_bounds) do
+        queue_bounds[k] = queue_weights[k] * adjust * #self.Queue[k]
+   end
+end
+
+function lib:GetNextFromScheduler()
+   self:UpdateWeights()
+
+   -- Since an addon could just fill up the user q for instant processing
+   -- we have to limit instants to 1 per INSTANT_QUERY_MIN_INTERVAL
+   -- and only try instant fulfilment if it will empty the user queue
+   if #self.Queue[1] == 1 then
+		if time() - lastInstantQuery > INSTANT_QUERY_MIN_INTERVAL then
+			dbg("INSTANT")
+			lastInstantQuery = time()
+			return 1, self.Queue[1]
+		end
+   end
+
+   local n,i = math.random(),0
+   repeat
+        i=i+1
+        n = n - queue_bounds[i]
+   until i>=#self.Queue or n <= 0
+
+   dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i]))
+
+   if #self.Queue[i] > 0 then
+        dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i]))
+       return i, self.Queue[i]
+   else
+        dbg("Queues empty, waiting")
+   end
+end
+
+lib.queue_bounds = queue_bounds
+
+function lib:AskWhoNext()
+	if lib.frame:IsShown() then
+		dbg("Already waiting")
+		return
+	end
+
+	self:CancelPendingWhoNext()
+
+	if self.WhoInProgress then
+		-- if we had a who going, it didnt complete
+		dbg("TIMEOUT: "..self.Args.query)
+		local args = self.Args
+		self.Args = nil
+--		if args.info and self.CacheQueue[args.query] ~= nil then
+			dbg("Requeing "..args.query)
+			tinsert(self.Queue[args.queue], args)
+			if args.console_show ~= nil then
+				DEFAULT_CHAT_FRAME:AddMessage(("Timeout on result of '%s' - retrying..."):format(args.query),1,1,0)
+				args.console_show = true
+			end
+--		end
+
+		if queryInterval < lib.MaxInterval then
+			queryInterval = queryInterval + 0.5
+			dbg("--Throttling down to 1 who per " .. queryInterval .. "s")
+		end
+	end
+
+
+	self.WhoInProgress = false
+
+	local v,k,args = nil
+    local kludge = 10
+	repeat
+        k,v = self:GetNextFromScheduler()
+        if not k then break end
+		if(WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET)then
+			break
+		end
+		if(#v > 0)then
+			args = tremove(v, 1)
+			break
+		end
+        kludge = kludge - 1
+	until kludge <= 0
+
+	if args then
+		self.WhoInProgress = true
+		self.Result = {}
+		self.Args = args
+		self.Total = -1
+		if(args.console_show == true)then
+			DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0)
+
+		end
+
+		if args.queue == self.WHOLIB_QUEUE_USER then
+			WhoFrameEditBox:SetText(args.query)
+			self.Quiet = false
+
+			if args.whotoui then
+    			self.hooked.SetWhoToUI(args.whotoui)
+    		else
+    			self.hooked.SetWhoToUI(args.gui and 1 or 0)
+			end
+		else
+			self.hooked.SetWhoToUI(1)
+			self.Quiet = true
+		end
+
+		dbg("QUERY: "..args.query)
+		self.hooked.SendWho(args.query)
+	else
+		self.Args = nil
+		self.WhoInProgress = false
+	end
+
+    -- Keep processing the who queue if there is more work
+	if not self:AllQueuesEmpty() then
+		self:AskWhoNextIn5sec()
+    else
+        dbg("*** Done processing requests ***")
+	end
+end
+
+function lib:AskWho(args)
+	tinsert(self.Queue[args.queue], args)
+	dbg('[' .. args.queue .. '] added "' .. args.query .. '", queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3])
+	self:TriggerEvent('WHOLIB_QUERY_ADDED')
+
+	self:AskWhoNext()
+end
+
+function lib:ReturnWho()
+    if not self.Args then
+        self.Quiet = nil
+        return
+    end
+
+	if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then
+		self.Quiet = nil
+	end
+
+	if queryInterval > self.MinInterval then
+		queryInterval = queryInterval - 0.5
+		dbg("--Throttling up to 1 who per " .. queryInterval .. "s")
+	end
+
+	self.WhoInProgress = false
+	dbg("RESULT: "..self.Args.query)
+	dbg('[' .. self.Args.queue .. '] returned "' .. self.Args.query .. '", total=' .. self.Total ..' , queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3])
+	local now = time()
+	local complete = (self.Total == #self.Result) and (self.Total < MAX_WHOS_FROM_SERVER)
+	for _,v in pairs(self.Result)do
+		if(self.Cache[v.Name] == nil)then
+			self.Cache[v.Name] = { inqueue = false, callback = {} }
+		end
+
+		local cachedName = self.Cache[v.Name]
+
+		cachedName.valid = true -- is now valid
+		cachedName.data = v -- update data
+		cachedName.data.Online = true -- player is online
+		cachedName.last = now -- update timestamp
+		if(cachedName.inqueue)then
+			if(self.Args.info and self.CacheQueue[self.Args.query] == v.Name)then
+				-- found by the query which was created to -> remove us from query
+				self.CacheQueue[self.Args.query] = nil
+			else
+				-- found by another query
+				for k2,v2 in pairs(self.CacheQueue) do
+					if(v2 == v.Name)then
+						for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do
+							for k3,v3 in pairs(self.Queue[i]) do
+								if(v3.query == k2 and v3.info)then
+									-- remove the query which was generated for this user, cause another query was faster...
+									dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'")
+									table.remove(self.Queue[i], k3)
+									self.CacheQueue[k2] = nil
+								end
+							end
+						end
+					end
+				end
+			end
+			dbg('Info(' .. v.Name ..') returned: on')
+			for _,v2 in pairs(cachedName.callback) do
+				self:RaiseCallback(v2, self:ReturnUserInfo(v.Name))
+			end
+			cachedName.callback = {}
+		end
+		cachedName.inqueue = false -- query is done
+	end
+	if(self.Args.info and self.CacheQueue[self.Args.query])then
+		-- the query did not deliver the result => not online!
+		local name = self.CacheQueue[self.Args.query]
+		local cachedName = self.Cache[name]
+		if (cachedName.inqueue)then
+			-- nothing found (yet)
+			cachedName.valid = true -- is now valid
+			cachedName.inqueue = false -- query is done?
+			cachedName.last = now -- update timestamp
+			if(complete)then
+				cachedName.data.Online = false -- player is offline
+			else
+				cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed)
+			end
+		end
+		dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn'))
+		for _,v in pairs(cachedName.callback) do
+			self:RaiseCallback(v, self:ReturnUserInfo(name))
+		end
+		cachedName.callback = {}
+		self.CacheQueue[self.Args.query] = nil
+	end
+	self:RaiseCallback(self.Args, self.Args.query, self.Result, complete, self.Args.info)
+	self:TriggerEvent('WHOLIB_QUERY_RESULT', self.Args.query, self.Result, complete, self.Args.info)
+
+	if not self:AllQueuesEmpty() then
+		self:AskWhoNextIn5sec()
+	end
+end
+
+function lib:GuiWho(msg)
+	if(msg == self.L['gui_wait'])then
+		return
+	end
+
+	for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do
+		if(v.gui == true)then
+			return
+		end
+	end
+	if(self.WhoInProgress)then
+		WhoFrameEditBox:SetText(self.L['gui_wait'])
+	end
+	self.savedText = msg
+	self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true})
+	WhoFrameEditBox:ClearFocus();
+end
+
+function lib:ConsoleWho(msg)
+	--WhoFrameEditBox:SetText(msg)
+	local console_show = false
+	local q1 = self.Queue[self.WHOLIB_QUEUE_USER]
+	local q1count = #q1
+
+	if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop
+		return
+	end
+
+	if(q1count > 0 and q1[q1count].console_show == false)then -- display 'queued' if console and not yet shown
+		DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], q1[q1count].query), 1, 1, 0)
+		q1[q1count].console_show = true
+	end
+	if(q1count > 0 or self.WhoInProgress)then
+		DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0)
+		console_show = true
+	end
+	self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show})
+end
+
+function lib:ReturnUserInfo(name)
+	if(name ~= nil and self ~= nil and self.Cache ~= nil and self.Cache[name] ~= nil) then
+		return self.Cache[name].data, (time() - self.Cache[name].last) / 60
+	end
+end
+
+function lib:RaiseCallback(args, ...)
+	if type(args.callback) == 'function' then
+		args.callback(self:DupAll(...))
+	elseif args.callback then -- must be a string
+		args.handler[args.callback](args.handler, self:DupAll(...))
+	end -- if
+end
+
+-- Argument checking
+
+function lib:CheckArgument(func, name, argtype, arg, defarg)
+	if arg == nil and defarg ~= nil then
+		return defarg
+	elseif type(arg) == argtype then
+		return arg
+	else
+		error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3)
+	end -- if
+end
+
+function lib:CheckPreset(func, name, preset, arg, defarg)
+	if arg == nil and defarg ~= nil then
+		return defarg
+	elseif arg ~= nil and preset[arg] ~= nil then
+		return arg
+	else
+		local p = {}
+		for k,v in pairs(preset) do
+			if type(v) ~= 'string' then
+				table.insert(p, k)
+			else
+				table.insert(p, v)
+			end -- if
+		end -- for
+		error(string.format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3)
+	end -- if
+end
+
+function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil)
+	if not nonil and callback == nil then
+		-- no callback: ignore handler
+		return nil, nil
+	elseif type(callback) == 'function' then
+		-- simple function
+		if handler ~= nil then
+			error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3)
+		end -- if
+	elseif type(callback) == 'string' then
+		-- method
+		if handler == nil then
+			handler = defhandler
+		end -- if
+		if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then
+			error(string.format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3)
+		end -- if
+	else
+		error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3)
+	end -- if
+
+	return callback, handler
+end
+
+-- helpers
+
+function lib:simple_dump(x)
+	if type(x) == 'string' then
+		return 'string \''..x..'\''
+	elseif type(x) == 'number' then
+		return 'number '..x
+	else
+		return type(x)
+	end
+end
+
+function lib:Dup(from)
+	local to = {}
+
+	for k,v in pairs(from) do
+		if type(v) == 'table' then
+			to[k] = self:Dup(v)
+		else
+			to[k] = v
+		end -- if
+	end -- for
+
+	return to
+end
+
+function lib:DupAll(x, ...)
+	if type(x) == 'table' then
+		return self:Dup(x), self:DupAll(...)
+	elseif x ~= nil then
+		return x, self:DupAll(...)
+	else
+		return nil
+	end -- if
+end
+
+local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)"
+
+function lib:CapitalizeInitial(name)
+    return name:gsub(MULTIBYTE_FIRST_CHAR, string.upper, 1)
+end
+
+---
+--- user events (Using CallbackHandler)
+---
+
+lib.PossibleEvents = {
+	'WHOLIB_QUERY_RESULT',
+	'WHOLIB_QUERY_ADDED',
+}
+
+function lib:TriggerEvent(event, ...)
+    callbacks:Fire(event, ...)
+end
+
+---
+--- slash commands
+---
+
+SlashCmdList['WHO'] = function(msg)
+	dbg("console /who: "..msg)
+	-- new /who function
+	--local self = lib
+
+	if(msg == '')then
+		lib:GuiWho(WhoFrame_GetDefaultWhoCommand())
+	elseif(WhoFrame:IsVisible())then
+		lib:GuiWho(msg)
+	else
+		lib:ConsoleWho(msg)
+	end
+end
+
+SlashCmdList['WHOLIB_DEBUG'] = function()
+	-- /wholibdebug: toggle debug on/off
+	local self = lib
+
+    self:SetWhoLibDebug(not self.Debug)
+end
+
+SLASH_WHOLIB_DEBUG1 = '/wholibdebug'
+
+
+---
+--- hook activation
+---
+
+-- functions to hook
+local hooks = {
+	'SendWho',
+	'WhoFrameEditBox_OnEnterPressed',
+--	'FriendsFrame_OnEvent',
+	'SetWhoToUI',
+}
+
+-- hook all functions (which are not yet hooked)
+for _, name in pairs(hooks) do
+	if not lib['hooked'][name] then
+		lib['hooked'][name] = _G[name]
+		_G[name] = function(...)
+			lib.hook[name](lib, ...)
+		end -- function
+	end -- if
+end -- for
+
+-- fake 'WhoFrame:Hide' as hooked
+table.insert(hooks, 'WhoFrame_Hide')
+
+-- check for unused hooks -> remove function
+for name, _ in pairs(lib['hook']) do
+	if not hooks[name] then
+		lib['hook'][name] = function() end
+	end -- if
+end -- for
+
+-- secure hook 'WhoFrame:Hide'
+if not lib['hooked']['WhoFrame_Hide'] then
+	lib['hooked']['WhoFrame_Hide'] = true
+	hooksecurefunc(WhoFrame, 'Hide', function(...)
+			lib['hook']['WhoFrame_Hide'](lib, ...)
+		end -- function
+	)
+end -- if
+
+
+
+----- Coroutine based implementation (future)
+--function lib:sendWhoResult(val)
+--    coroutine.yield(val)
+--end
+--
+--function lib:sendWaitState(val)
+--    coroutine.yield(val)
+--end
+--
+--function lib:producer()
+--    return coroutine.create(
+--    function()
+--        lib:AskWhoNext()
+--        lib:sendWaitState(true)
+--
+--        -- Resumed look for data
+--
+--    end)
+--end
+
+
+
+
+
+---
+--- hook replacements
+---
+
+function lib.hook.SendWho(self, msg)
+	dbg("SendWho: "..msg)
+	lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0})
+end
+
+function lib.hook.WhoFrameEditBox_OnEnterPressed(self)
+	lib:GuiWho(WhoFrameEditBox:GetText())
+end
+
+--[[
+function lib.hook.FriendsFrame_OnEvent(self, ...)
+	if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then
+		lib.hooked.FriendsFrame_OnEvent(...)
+	end
+end
+]]
+
+hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event)
+		if(event == "WHO_LIST_UPDATE") then
+			self:UnregisterEvent("WHO_LIST_UPDATE");
+		end
+	end);
+
+
+function lib.hook.SetWhoToUI(self, state)
+	lib.SetWhoToUIState = state
+end
+
+function lib.hook.WhoFrame_Hide(self)
+	if(not lib.WhoInProgress)then
+		lib:AskWhoNextIn5sec()
+	end
+end
+
+
+---
+--- WoW events
+---
+
+local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+')
+
+
+function lib:CHAT_MSG_SYSTEM(arg1)
+	if arg1 and arg1:find(who_pattern) then
+		lib:ProcessWhoResults()
+	end
+end
+
+FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE")
+
+function lib:WHO_LIST_UPDATE()
+    if not lib.Quiet then
+		WhoList_Update()
+        FriendsFrame_Update()
+    end
+
+    lib:ProcessWhoResults()
+end
+
+function lib:ProcessWhoResults()
+	local num
+	self.Total, num = GetNumWhoResults()
+	for i=1, num do
+		local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i)
+		self.Result[i] = {Name=charname, Guild=guildname, Level=level, Race=race, Class=class, Zone=zone, NoLocaleClass=nonlocalclass, Sex=sex }
+	end
+
+	self:ReturnWho()
+end
+
+---
+--- event activation
+---
+
+lib['frame']:UnregisterAllEvents();
+
+lib['frame']:SetScript("OnEvent", function(frame, event, ...)
+	lib[event](lib, ...)
+end);
+
+for _,name in pairs({
+	'CHAT_MSG_SYSTEM',
+	'WHO_LIST_UPDATE',
+}) do
+	lib['frame']:RegisterEvent(name);
+end -- for
+
+
+---
+--- re-embed
+---
+
+for target,_ in pairs(lib['embeds']) do
+	if type(target) == 'table' then
+		lib:Embed(target)
+	end -- if
+end -- for
diff --git a/libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua b/libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
index 274016c..e0fe1af 100644
--- a/libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
+++ b/libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
@@ -1,240 +1,240 @@
---[[ $Id: CallbackHandler-1.0.lua 14 2010-08-09 00:43:38Z mikk $ ]]
-local MAJOR, MINOR = "CallbackHandler-1.0", 6
-local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
-
-if not CallbackHandler then return end -- No upgrade needed
-
-local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-
--- Lua APIs
-local tconcat = table.concat
-local assert, error, loadstring = assert, error, loadstring
-local setmetatable, rawset, rawget = setmetatable, rawset, rawget
-local next, select, pairs, type, tostring = next, select, pairs, type, tostring
-
--- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
--- List them here for Mikk's FindGlobals script
--- GLOBALS: geterrorhandler
-
-local xpcall = xpcall
-
-local function errorhandler(err)
-	return geterrorhandler()(err)
-end
-
-local function CreateDispatcher(argCount)
-	local code = [[
-	local next, xpcall, eh = ...
-
-	local method, ARGS
-	local function call() method(ARGS) end
-
-	local function dispatch(handlers, ...)
-		local index
-		index, method = next(handlers)
-		if not method then return end
-		local OLD_ARGS = ARGS
-		ARGS = ...
-		repeat
-			xpcall(call, eh)
-			index, method = next(handlers, index)
-		until not method
-		ARGS = OLD_ARGS
-	end
-
-	return dispatch
-	]]
-
-	local ARGS, OLD_ARGS = {}, {}
-	for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
-	code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
-	return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
-end
-
-local Dispatchers = setmetatable({}, {__index=function(self, argCount)
-	local dispatcher = CreateDispatcher(argCount)
-	rawset(self, argCount, dispatcher)
-	return dispatcher
-end})
-
---------------------------------------------------------------------------
--- CallbackHandler:New
---
---   target            - target object to embed public APIs in
---   RegisterName      - name of the callback registration API, default "RegisterCallback"
---   UnregisterName    - name of the callback unregistration API, default "UnregisterCallback"
---   UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
-
-function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
-	-- TODO: Remove this after beta has gone out
-	assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
-
-	RegisterName = RegisterName or "RegisterCallback"
-	UnregisterName = UnregisterName or "UnregisterCallback"
-	if UnregisterAllName==nil then	-- false is used to indicate "don't want this method"
-		UnregisterAllName = "UnregisterAllCallbacks"
-	end
-
-	-- we declare all objects and exported APIs inside this closure to quickly gain access
-	-- to e.g. function names, the "target" parameter, etc
-
-
-	-- Create the registry object
-	local events = setmetatable({}, meta)
-	local registry = { recurse=0, events=events }
-
-	-- registry:Fire() - fires the given event/message into the registry
-	function registry:Fire(eventname, ...)
-		if not rawget(events, eventname) or not next(events[eventname]) then return end
-		local oldrecurse = registry.recurse
-		registry.recurse = oldrecurse + 1
-
-		Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
-
-		registry.recurse = oldrecurse
-
-		if registry.insertQueue and oldrecurse==0 then
-			-- Something in one of our callbacks wanted to register more callbacks; they got queued
-			for eventname,callbacks in pairs(registry.insertQueue) do
-				local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
-				for self,func in pairs(callbacks) do
-					events[eventname][self] = func
-					-- fire OnUsed callback?
-					if first and registry.OnUsed then
-						registry.OnUsed(registry, target, eventname)
-						first = nil
-					end
-				end
-			end
-			registry.insertQueue = nil
-		end
-	end
-
-	-- Registration of a callback, handles:
-	--   self["method"], leads to self["method"](self, ...)
-	--   self with function ref, leads to functionref(...)
-	--   "addonId" (instead of self) with function ref, leads to functionref(...)
-	-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
-	target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
-		if type(eventname) ~= "string" then
-			error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
-		end
-
-		method = method or eventname
-
-		local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
-
-		if type(method) ~= "string" and type(method) ~= "function" then
-			error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
-		end
-
-		local regfunc
-
-		if type(method) == "string" then
-			-- self["method"] calling style
-			if type(self) ~= "table" then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
-			elseif self==target then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
-			elseif type(self[method]) ~= "function" then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
-			end
-
-			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
-				local arg=select(1,...)
-				regfunc = function(...) self[method](self,arg,...) end
-			else
-				regfunc = function(...) self[method](self,...) end
-			end
-		else
-			-- function ref with self=object or self="addonId" or self=thread
-			if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
-				error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
-			end
-
-			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
-				local arg=select(1,...)
-				regfunc = function(...) method(arg,...) end
-			else
-				regfunc = method
-			end
-		end
-
-
-		if events[eventname][self] or registry.recurse<1 then
-		-- if registry.recurse<1 then
-			-- we're overwriting an existing entry, or not currently recursing. just set it.
-			events[eventname][self] = regfunc
-			-- fire OnUsed callback?
-			if registry.OnUsed and first then
-				registry.OnUsed(registry, target, eventname)
-			end
-		else
-			-- we're currently processing a callback in this registry, so delay the registration of this new entry!
-			-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
-			registry.insertQueue = registry.insertQueue or setmetatable({},meta)
-			registry.insertQueue[eventname][self] = regfunc
-		end
-	end
-
-	-- Unregister a callback
-	target[UnregisterName] = function(self, eventname)
-		if not self or self==target then
-			error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
-		end
-		if type(eventname) ~= "string" then
-			error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
-		end
-		if rawget(events, eventname) and events[eventname][self] then
-			events[eventname][self] = nil
-			-- Fire OnUnused callback?
-			if registry.OnUnused and not next(events[eventname]) then
-				registry.OnUnused(registry, target, eventname)
-			end
-		end
-		if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
-			registry.insertQueue[eventname][self] = nil
-		end
-	end
-
-	-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
-	if UnregisterAllName then
-		target[UnregisterAllName] = function(...)
-			if select("#",...)<1 then
-				error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
-			end
-			if select("#",...)==1 and ...==target then
-				error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
-			end
-
-
-			for i=1,select("#",...) do
-				local self = select(i,...)
-				if registry.insertQueue then
-					for eventname, callbacks in pairs(registry.insertQueue) do
-						if callbacks[self] then
-							callbacks[self] = nil
-						end
-					end
-				end
-				for eventname, callbacks in pairs(events) do
-					if callbacks[self] then
-						callbacks[self] = nil
-						-- Fire OnUnused callback?
-						if registry.OnUnused and not next(callbacks) then
-							registry.OnUnused(registry, target, eventname)
-						end
-					end
-				end
-			end
-		end
-	end
-
-	return registry
-end
-
-
--- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
--- try to upgrade old implicit embeds since the system is selfcontained and
--- relies on closures to work.
-
+--[[ $Id: CallbackHandler-1.0.lua 14 2010-08-09 00:43:38Z mikk $ ]]
+local MAJOR, MINOR = "CallbackHandler-1.0", 6
+local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not CallbackHandler then return end -- No upgrade needed
+
+local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
+
+-- Lua APIs
+local tconcat = table.concat
+local assert, error, loadstring = assert, error, loadstring
+local setmetatable, rawset, rawget = setmetatable, rawset, rawget
+local next, select, pairs, type, tostring = next, select, pairs, type, tostring
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: geterrorhandler
+
+local xpcall = xpcall
+
+local function errorhandler(err)
+	return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+	local code = [[
+	local next, xpcall, eh = ...
+
+	local method, ARGS
+	local function call() method(ARGS) end
+
+	local function dispatch(handlers, ...)
+		local index
+		index, method = next(handlers)
+		if not method then return end
+		local OLD_ARGS = ARGS
+		ARGS = ...
+		repeat
+			xpcall(call, eh)
+			index, method = next(handlers, index)
+		until not method
+		ARGS = OLD_ARGS
+	end
+
+	return dispatch
+	]]
+
+	local ARGS, OLD_ARGS = {}, {}
+	for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
+	code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
+	return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {__index=function(self, argCount)
+	local dispatcher = CreateDispatcher(argCount)
+	rawset(self, argCount, dispatcher)
+	return dispatcher
+end})
+
+--------------------------------------------------------------------------
+-- CallbackHandler:New
+--
+--   target            - target object to embed public APIs in
+--   RegisterName      - name of the callback registration API, default "RegisterCallback"
+--   UnregisterName    - name of the callback unregistration API, default "UnregisterCallback"
+--   UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
+
+function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
+	-- TODO: Remove this after beta has gone out
+	assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
+
+	RegisterName = RegisterName or "RegisterCallback"
+	UnregisterName = UnregisterName or "UnregisterCallback"
+	if UnregisterAllName==nil then	-- false is used to indicate "don't want this method"
+		UnregisterAllName = "UnregisterAllCallbacks"
+	end
+
+	-- we declare all objects and exported APIs inside this closure to quickly gain access
+	-- to e.g. function names, the "target" parameter, etc
+
+
+	-- Create the registry object
+	local events = setmetatable({}, meta)
+	local registry = { recurse=0, events=events }
+
+	-- registry:Fire() - fires the given event/message into the registry
+	function registry:Fire(eventname, ...)
+		if not rawget(events, eventname) or not next(events[eventname]) then return end
+		local oldrecurse = registry.recurse
+		registry.recurse = oldrecurse + 1
+
+		Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
+
+		registry.recurse = oldrecurse
+
+		if registry.insertQueue and oldrecurse==0 then
+			-- Something in one of our callbacks wanted to register more callbacks; they got queued
+			for eventname,callbacks in pairs(registry.insertQueue) do
+				local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+				for self,func in pairs(callbacks) do
+					events[eventname][self] = func
+					-- fire OnUsed callback?
+					if first and registry.OnUsed then
+						registry.OnUsed(registry, target, eventname)
+						first = nil
+					end
+				end
+			end
+			registry.insertQueue = nil
+		end
+	end
+
+	-- Registration of a callback, handles:
+	--   self["method"], leads to self["method"](self, ...)
+	--   self with function ref, leads to functionref(...)
+	--   "addonId" (instead of self) with function ref, leads to functionref(...)
+	-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
+	target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
+		if type(eventname) ~= "string" then
+			error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
+		end
+
+		method = method or eventname
+
+		local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+
+		if type(method) ~= "string" and type(method) ~= "function" then
+			error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
+		end
+
+		local regfunc
+
+		if type(method) == "string" then
+			-- self["method"] calling style
+			if type(self) ~= "table" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
+			elseif self==target then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
+			elseif type(self[method]) ~= "function" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) self[method](self,arg,...) end
+			else
+				regfunc = function(...) self[method](self,...) end
+			end
+		else
+			-- function ref with self=object or self="addonId" or self=thread
+			if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
+				error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) method(arg,...) end
+			else
+				regfunc = method
+			end
+		end
+
+
+		if events[eventname][self] or registry.recurse<1 then
+		-- if registry.recurse<1 then
+			-- we're overwriting an existing entry, or not currently recursing. just set it.
+			events[eventname][self] = regfunc
+			-- fire OnUsed callback?
+			if registry.OnUsed and first then
+				registry.OnUsed(registry, target, eventname)
+			end
+		else
+			-- we're currently processing a callback in this registry, so delay the registration of this new entry!
+			-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
+			registry.insertQueue = registry.insertQueue or setmetatable({},meta)
+			registry.insertQueue[eventname][self] = regfunc
+		end
+	end
+
+	-- Unregister a callback
+	target[UnregisterName] = function(self, eventname)
+		if not self or self==target then
+			error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
+		end
+		if type(eventname) ~= "string" then
+			error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
+		end
+		if rawget(events, eventname) and events[eventname][self] then
+			events[eventname][self] = nil
+			-- Fire OnUnused callback?
+			if registry.OnUnused and not next(events[eventname]) then
+				registry.OnUnused(registry, target, eventname)
+			end
+		end
+		if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
+			registry.insertQueue[eventname][self] = nil
+		end
+	end
+
+	-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
+	if UnregisterAllName then
+		target[UnregisterAllName] = function(...)
+			if select("#",...)<1 then
+				error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
+			end
+			if select("#",...)==1 and ...==target then
+				error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
+			end
+
+
+			for i=1,select("#",...) do
+				local self = select(i,...)
+				if registry.insertQueue then
+					for eventname, callbacks in pairs(registry.insertQueue) do
+						if callbacks[self] then
+							callbacks[self] = nil
+						end
+					end
+				end
+				for eventname, callbacks in pairs(events) do
+					if callbacks[self] then
+						callbacks[self] = nil
+						-- Fire OnUnused callback?
+						if registry.OnUnused and not next(callbacks) then
+							registry.OnUnused(registry, target, eventname)
+						end
+					end
+				end
+			end
+		end
+	end
+
+	return registry
+end
+
+
+-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
+-- try to upgrade old implicit embeds since the system is selfcontained and
+-- relies on closures to work.
+
diff --git a/libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml b/libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
index 876df83..a5b22a7 100644
--- a/libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
+++ b/libs/LibWho-2.0XX/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
@@ -1,4 +1,4 @@
-<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
-..\FrameXML\UI.xsd">
-	<Script file="CallbackHandler-1.0.lua"/>
-</Ui>
\ No newline at end of file
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
+..\FrameXML\UI.xsd">
+	<Script file="CallbackHandler-1.0.lua"/>
+</Ui>
diff --git a/libs/LibWho-2.0XX/libs/LibStub/LibStub.lua b/libs/LibWho-2.0XX/libs/LibStub/LibStub.lua
index ae1900e..f5fc919 100644
--- a/libs/LibWho-2.0XX/libs/LibStub/LibStub.lua
+++ b/libs/LibWho-2.0XX/libs/LibStub/LibStub.lua
@@ -1,51 +1,51 @@
--- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
--- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
--- LibStub is hereby placed in the Public Domain
--- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
-local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
-local LibStub = _G[LIBSTUB_MAJOR]
-
--- Check to see is this version of the stub is obsolete
-if not LibStub or LibStub.minor < LIBSTUB_MINOR then
-	LibStub = LibStub or {libs = {}, minors = {} }
-	_G[LIBSTUB_MAJOR] = LibStub
-	LibStub.minor = LIBSTUB_MINOR
-
-	-- LibStub:NewLibrary(major, minor)
-	-- major (string) - the major version of the library
-	-- minor (string or number ) - the minor version of the library
-	--
-	-- returns nil if a newer or same version of the lib is already present
-	-- returns empty library object or old library object if upgrade is needed
-	function LibStub:NewLibrary(major, minor)
-		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
-		minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
-
-		local oldminor = self.minors[major]
-		if oldminor and oldminor >= minor then return nil end
-		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
-		return self.libs[major], oldminor
-	end
-
-	-- LibStub:GetLibrary(major, [silent])
-	-- major (string) - the major version of the library
-	-- silent (boolean) - if true, library is optional, silently return nil if its not found
-	--
-	-- throws an error if the library can not be found (except silent is set)
-	-- returns the library object if found
-	function LibStub:GetLibrary(major, silent)
-		if not self.libs[major] and not silent then
-			error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
-		end
-		return self.libs[major], self.minors[major]
-	end
-
-	-- LibStub:IterateLibraries()
-	--
-	-- Returns an iterator for the currently registered libraries
-	function LibStub:IterateLibraries()
-		return pairs(self.libs)
-	end
-
-	setmetatable(LibStub, { __call = LibStub.GetLibrary })
-end
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+	LibStub = LibStub or {libs = {}, minors = {} }
+	_G[LIBSTUB_MAJOR] = LibStub
+	LibStub.minor = LIBSTUB_MINOR
+
+	-- LibStub:NewLibrary(major, minor)
+	-- major (string) - the major version of the library
+	-- minor (string or number ) - the minor version of the library
+	--
+	-- returns nil if a newer or same version of the lib is already present
+	-- returns empty library object or old library object if upgrade is needed
+	function LibStub:NewLibrary(major, minor)
+		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+		minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+		local oldminor = self.minors[major]
+		if oldminor and oldminor >= minor then return nil end
+		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+		return self.libs[major], oldminor
+	end
+
+	-- LibStub:GetLibrary(major, [silent])
+	-- major (string) - the major version of the library
+	-- silent (boolean) - if true, library is optional, silently return nil if its not found
+	--
+	-- throws an error if the library can not be found (except silent is set)
+	-- returns the library object if found
+	function LibStub:GetLibrary(major, silent)
+		if not self.libs[major] and not silent then
+			error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+		end
+		return self.libs[major], self.minors[major]
+	end
+
+	-- LibStub:IterateLibraries()
+	--
+	-- Returns an iterator for the currently registered libraries
+	function LibStub:IterateLibraries()
+		return pairs(self.libs)
+	end
+
+	setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/libs/LibWho-2.0XX/libs/LibStub/LibStub.toc b/libs/LibWho-2.0XX/libs/LibStub/LibStub.toc
index e39aa26..f798fbc 100644
--- a/libs/LibWho-2.0XX/libs/LibStub/LibStub.toc
+++ b/libs/LibWho-2.0XX/libs/LibStub/LibStub.toc
@@ -1,13 +1,13 @@
-## Interface: 50001
-## Title: Lib: LibStub
-## Notes: Universal Library Stub
-## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
-## X-Website: http://www.wowace.com/addons/libstub/
-## X-Category: Library
-## X-License: Public Domain
-## X-Curse-Packaged-Version: 1.0.3-50001
-## X-Curse-Project-Name: LibStub
-## X-Curse-Project-ID: libstub
-## X-Curse-Repository-ID: wow/libstub/mainline
-
-LibStub.lua
+## Interface: 50001
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: 1.0.3-50001
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/libs/LibWho-2.0XX/libs/LibStub/tests/test.lua b/libs/LibWho-2.0XX/libs/LibStub/tests/test.lua
index 276ddab..fb3bcbd 100644
--- a/libs/LibWho-2.0XX/libs/LibStub/tests/test.lua
+++ b/libs/LibWho-2.0XX/libs/LibStub/tests/test.lua
@@ -1,41 +1,41 @@
-debugstack = debug.traceback
-strmatch = string.match
-
-loadfile("../LibStub.lua")()
-
-local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
-assert(lib) -- should return the library table
-assert(not oldMinor) -- should not return the old minor, since it didn't exist
-
--- the following is to create data and then be able to check if the same data exists after the fact
-function lib:MyMethod()
-end
-local MyMethod = lib.MyMethod
-lib.MyTable = {}
-local MyTable = lib.MyTable
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
-assert(not newLib) -- should not return since out of date
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
-assert(not newLib) -- should not return since out of date
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
-assert(newLib) -- library table
-assert(rawequal(newLib, lib)) -- should be the same reference as the previous
-assert(newOldMinor == 1) -- should return the minor version of the previous version
-
-assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
-assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
-assert(newLib) -- library table
-assert(newOldMinor == 2) -- previous version was 2
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
-assert(newLib)
-assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
-
-local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
-assert(newLib)
-assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
diff --git a/libs/LibWho-2.0XX/libs/LibStub/tests/test2.lua b/libs/LibWho-2.0XX/libs/LibStub/tests/test2.lua
index eae7172..af431dd 100644
--- a/libs/LibWho-2.0XX/libs/LibStub/tests/test2.lua
+++ b/libs/LibWho-2.0XX/libs/LibStub/tests/test2.lua
@@ -1,27 +1,27 @@
-debugstack = debug.traceback
-strmatch = string.match
-
-loadfile("../LibStub.lua")()
-
-for major, library in LibStub:IterateLibraries() do
-	-- check that MyLib doesn't exist yet, by iterating through all the libraries
-	assert(major ~= "MyLib")
-end
-
-assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
-assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
-local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
-assert(lib) -- check it exists
-assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
-
-assert(LibStub:NewLibrary("MyLib", 2))	-- create a new version
-
-local count=0
-for major, library in LibStub:IterateLibraries() do
-	-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
-	if major == "MyLib" then -- we found it!
-		count = count +1
-		assert(rawequal(library, lib)) -- verify that the references are equal
-	end
-end
-assert(count == 1) -- verify that we actually found it, and only once
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+	-- check that MyLib doesn't exist yet, by iterating through all the libraries
+	assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2))	-- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+	-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+	if major == "MyLib" then -- we found it!
+		count = count +1
+		assert(rawequal(library, lib)) -- verify that the references are equal
+	end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/libs/LibWho-2.0XX/libs/LibStub/tests/test3.lua b/libs/LibWho-2.0XX/libs/LibStub/tests/test3.lua
index 30f7b94..3c06002 100644
--- a/libs/LibWho-2.0XX/libs/LibStub/tests/test3.lua
+++ b/libs/LibWho-2.0XX/libs/LibStub/tests/test3.lua
@@ -1,14 +1,14 @@
-debugstack = debug.traceback
-strmatch = string.match
-
-loadfile("../LibStub.lua")()
-
-local proxy = newproxy() -- non-string
-
-assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
-local success, ret = pcall(LibStub.GetLibrary, proxy, true)
-assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
-
-assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
-
-assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
diff --git a/libs/LibWho-2.0XX/libs/LibStub/tests/test4.lua b/libs/LibWho-2.0XX/libs/LibStub/tests/test4.lua
index 43eb338..294623b 100644
--- a/libs/LibWho-2.0XX/libs/LibStub/tests/test4.lua
+++ b/libs/LibWho-2.0XX/libs/LibStub/tests/test4.lua
@@ -1,41 +1,41 @@
-debugstack = debug.traceback
-strmatch = string.match
-
-loadfile("../LibStub.lua")()
-
-
--- Pretend like loaded libstub is old and doesn't have :IterateLibraries
-assert(LibStub.minor)
-LibStub.minor = LibStub.minor - 0.0001
-LibStub.IterateLibraries = nil
-
-loadfile("../LibStub.lua")()
-
-assert(type(LibStub.IterateLibraries)=="function")
-
-
--- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
-LibStub.IterateLibraries = 123
-
-loadfile("../LibStub.lua")()
-
-assert(LibStub.IterateLibraries == 123)
-
-
--- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
-LibStub.minor = LibStub.minor + 0.0001
-
-loadfile("../LibStub.lua")()
-
-assert(LibStub.IterateLibraries == 123)
-
-
--- Again with a huge number
-LibStub.minor = LibStub.minor + 1234567890
-
-loadfile("../LibStub.lua")()
-
-assert(LibStub.IterateLibraries == 123)
-
-
-print("OK")
\ No newline at end of file
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
diff --git a/locale/localization.lua b/locale/localization.lua
index cda79f9..c8c46a7 100644
--- a/locale/localization.lua
+++ b/locale/localization.lua
@@ -1,452 +1,463 @@
-SGI_Locale = {}
-
-local function defaultFunc(L,key)
-	return key
-end
-
-local English = setmetatable({}, {__index=defaultFunc})
-	English["English Locale loaded"] = "English Locale loaded"
-	English["Enable whispers"] = "Enable whispers"
-	English["Level limits"] = nil
-	English["Invite Mode"] = nil
-	English["Whisper only"] = nil
-	English["Invite and whisper"] = nil
-	English["Invite only"] = nil
-	English["Mute SGI"] = nil
-	English["Filter 55-58 Death Knights"] = nil
-	English["Do a more thorough search"] = nil
-	English["Customize whisper"] = nil
-	English["SuperScan"] = nil
-	English["Invite: %d"] = nil
-	English["Choose Invites"] = nil
-	English["Exceptions"] = nil
-	English["Help"] = nil
-	English["The level you wish to start dividing the search by race"] = nil
-	English["Racefilter Start:"] = nil
-	English["The level you wish to divide the search by class"] = nil
-	English["Classfilter Start:"] = nil
-	English["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = nil
-	English["Interval:"] = nil
-	English["SuperGuildInvite Custom Whisper"] = nil
-	English["WhisperInstructions"] = "Create a customized whisper to send people you invite! If you enter the words (must be caps) |cff00ff00NAME|r, |cff0000ffLEVEL|r or |cffff0000PLAYER|r these will be replaced by your Guildname, Guildlevel and the recieving players name"
-	English["Enter your whisper"] = nil
-	English["Save"] = nil
-	English["Cancel"] = nil
-	English["less than 1 second"] = nil
-	English[" hours "] = nil
-	English[" minutes "] = nil
-	English[" seconds"] = nil
-	English[" remaining"] = nil
-	English["Purge Queue"] = nil
-	English["Click to toggle SuperScan"] = nil
-	English["Click on the players you wish to invite"] = nil
-	English["Scan Completed"] = nil
-	English["Who sent: "] = nil
-	English["SuperScan was started"] = nil
-	English["SuperScan was stopped"] = nil
-	English["PlayersScanned"] = "Players Scanned: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)"
-	English["PlayersGuildLess"] = "Guildless Players: |cff44FF44%d|r (|cff44FF44%d%%|r)"
-	English["InvitesQueued"] = "Invites Queued: |cff44FF44%d|r"
-	English["ExceptionsInstructions"] = "You can add exception phrases that when found in a name will cause the player to be ignore by SuperGuildInvite. You can add several exceptions at once, seperated by a comma (,)."
-	English["SGI Exceptions"] = nil
-	English["Enter exceptions"] = nil
-	English["Go to Options and select your Invite Mode"] = nil
-	English["You need to specify the mode in which you wish to invite"] = nil
-	English["Unable to invite %s. They are already in a guild."] = nil
-	English["Unable to invite %s. They will not be blacklisted."] = nil
-
-	--Trouble shooter--
-	English["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r"
-	English["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r"
-	English["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r"
-	English["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r"
-	English["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r"
-	English["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r"
-	English["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r"
-	English["Enabled whispers"] = nil
-	English['Changed invite mode to "Invite and Whisper"'] = nil
-	English["Mute has been turned off"] = nil
-	English['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = nil
-
-
-
-	English["Shaman"] = nil
-	English["Death Knight"] = nil
-	English["Mage"] = nil
-	English["Priest"] = nil
-	English["Rogue"] = nil
-	English["Paladin"] = nil
-	English["Warlock"] = nil
-	English["Druid"] = nil
-	English["Warrior"] = nil
-	English["Hunter"] = nil
-	English["Monk"] = nil
-
-	English["Human"] = nil
-	English["Gnome"] = nil
-	English["Dwarf"] = nil
-	English["NightElf"] = nil
-	English["Draenei"] = nil
-	English["Worgen"] = nil
-	English["Pandaren"] = nil
-	English["Undead"] = nil
-	English["Orc"] = nil
-	English["Troll"] = nil
-	English["Tauren"] = nil
-	English["BloodElf"] = nil
-	English["Goblin"] = nil
-
-	English["Author"] = "|cff00A2FF Written by Janniie - Stormreaver EU.|r"
-
-German = setmetatable({}, {__index=defaultFunc})
-	German["English Locale loaded"] = "German Locale loaded"
-	German["Enable whispers"] = "aktivieren Sie flüstert"
-	German["Level limits"] = "Levelbeschränkungen"
-	German["Invite Mode"] = "Einladungsart"
-	German["Whisper only"] = "Nur anflüstern"
-	German["Invite and whisper"] = "Einladen und anflüstern"
-	German["Invite only"] = "Nur einladen"
-	German["Mute SGI"] = "SGI stummschalten"
-	German["Filter 55-58 Death Knights"] = "Level 55-58 Todesritter filtern"
-	German["Do a more thorough search"] = "Gründlichere Suche ausführen"
-	German["Customize whisper"] = "Flüsternachricht anpassen"
-	German["SuperScan"] = "SuperScan"
-	German["Invite: %d"] = "Einladen: %d"
-	German["Choose Invites"] = "einladungen auswählen"
-	German["Exceptions"] = "Ausnahmen"
-	German["Help"] = "Hilfe"
-	German["SuperGuildInvite Custom Whisper"] = "SuperGuildInvite eigene Flüsternachricht"
-	German["WhisperInstructions"] = "Erstelle eine eigene Flüsternachricht, die an die Leute gesendet wird, die du einlädst! Wenn du die worte |cff00ff00NAME|r, |cff0000ffLEVEL|r oder |cffff0000PLAYER|r (in Großbuchstaben) benutzt werden diese durch Gildenname, Gildenlevel und den Namen des Empfängers ersetzt."
-	German["Enter your whisper"] = "Flüsternachricht eingeben"
-	German["Save"] = "Speichern"
-	German["Cancel"] = "Abbrechen"
-	German["less than 1 second"] = "weniger als 1 Sekunden verbleibend"
-	German[" hours "] = " Stunden "
-	German[" minutes "] = " minute "
-	German[" seconds"] = " Sekunden"
-	German[" remaining"] = " verbleibend"
-	German["Purge Queue"] = "Warteschlange leeren"
-	German["Click to toggle SuperScan"] = "Klicken um SuperScan zu beenden"
-	German["Click on the players you wish to invite"] = "Klicke die Spieler an, die du einladen willst"
-	German["Scan Completed"] = "Suchlauf beendet"
-	German["Who sent: "] = "Wer-Abfrage gesendet: "
-	German["SuperScan was started"] = "SuperScan wurde gestartet"
-	German["SuperScan was stopped"] = "SuperScan wurde gestoppt"
-	German["PlayersScanned"] = "Spieler durchsucht: |cff44FF44%d|r (Insgesamt: |cff44FF44%d|r)"
-	German["PlayersGuildLess"] = "gildenlose Spieler: |cff44FF44%d|r"
-	German["InvitesQueued"] = "Einladungen in Warteschlange: |cff44FF44%d|r"
-	German["ExceptionsInstructions"] = "Hier kannst du Ausnahmen eingeben, die, wenn sie in einem Namen gefunden werden, dazu führen daß SGI diesen Spieler ignoriert. Du kannst mehrere Ausnahmen durch ein Komma (,) getrennt eingeben."
-	German["SGI Exceptions"] = "SGI Ausnahmen"
-	German["Go to Options and select your Invite Mode"] = "Gehen Sie auf Optionen und wählen Sie Einladungsart"
-	German["You need to specify the mode in which you wish to invite"] = "Sie müssen den Modus, in dem Sie einladen möchten festlegen"
-	German["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = "Anzahl der Level nach denen etwa alle 7 Sekunden gesucht wird (höhere Zahlen erhöhen das Risiko, daß nicht alle Suchergebnisse bearbeitet werden)."
-	German["The level you wish to divide the search by class"] = "Level ab dem nach Klasse gesucht wird."
-	German["The level you wish to divide the search by race"] = "Level ab dem nach Rasse gesucht wird."
-
-	German["not sending"] = "|cffff8800Warum verschicke ich keine Flüsternachrichten?|r |cff00A2FFMöglicherweise hast du das Kästchen nicht angekreuzt.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
-	German["to specify"] = "|cffff8800Ich bekomme eine Nachricht, daß ich die Einladungsart auswählen soll wenn ich jemanden einladen möchte.|r|cff00A2FF Das passiert wenn du nicht das Auswahlmenü in den Optionen benutzt hast um auszuwählen wie du Leute einlädst.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
-	German["I checked the box"] = "|cffff8800Ich verschicke keine Flüsternachrichten beim Einladen, obwohl ich das Kästchen angekreuzt habe.|r|cff00A2FF Das passiert wenn du nur einladen im Auswahlmenü ausgewählt hast.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
-	German["whisper to everyone"] = "|cffff8800Ich verschicke Flüsternachrichten an jeden den ich einlade ODER ich möchte nur Flüsternachrichten senden aber das AddOn macht beides!|r|cff00A2FF Das passiert weil du einladen und anflüstern im Auswahlmenü ausgewählt hast.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
-	German["can't get SGI to invite"] = "|cffff8800SGI lädt keine Leute ein und schickt ausschließlich Flüsternachrichten.|r|cff00A2FF DU hast nur diese Option im Auswahlmenü ausgewählt.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
-	German["can't see any messages"] = "|cffff8800Ich sehe keinerlei Ausgabe von SGI.|r|cff00A2FF Du hast SGI in den Optionen stummgeschaltet.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
-	German["None of the above"] = "|cffff8800Keine der obenstehenden Lösungen löst mein Problem!|r|cff00A2FF Es könnte ein Problem mit der Lokalisation (Sprache) geben, die du benutzt. Du kannst versuchen mit /sgi locale:deDE die deutschen Sprachoptionen zu laden (frFR für Französisch). Bitte schick mir eine Nachricht an:|r|cff00ff00 SuperGuildInvite@gmail.com|r"
-	German["Enabled whispers"] = "Flüsternachrichten eingeschaltet"
-	German['Changed invite mode to "Invite and Whisper"'] = "Einladungsart auf einladen und anflüstern geändert"
-	German["Mute has been turned off"] = "Stummschaltung wurde ausgeschaltet"
-	German['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = "Einladungsmodus auf nur einladen geändert. Wenn du nur anflüstern wolltest, gehe in die Optionen und ändere es dort."
-	German["Enter exceptions"] = "Ausnahmen eingeben"
-	German["Highest and lowest level to search for"] = "Höchster und niedrigster Level nach dem gesucht wird"
-
-
-	German["Shaman"] = "Schamane"
-	German["Death Knight"] = "Todesritter"
-	German["Mage"] = "Magier"
-	German["Priest"] = "Priester"
-	German["Rogue"] = "Schurke"
-	German["Paladin"] = "Paladin"
-	German["Warlock"] = "Hexenmeister"
-	German["Druid"] = "Druide"
-	German["Warrior"] = "Krieger"
-	German["Hunter"] = "Jäger"
-	German["Monk"] = "Mönch"
-
-	German["Human"] = "Mensch"
-	German["Gnome"] = "Gnom"
-	German["Dwarf"] = "Zwerg"
-	German["NightElf"] = "Nachtelf"
-	German["Draenei"] = "Draenei"
-	German["Worgen"] = "Worgen"
-	German["Pandaren"] = "Pandaren"
-	German["Undead"] = "Untoter"
-	German["Orc"] = "Ork"
-	German["Troll"] = "Troll"
-	German["Tauren"] = "Taure"
-	German["BloodElf"] = "Blutelf"
-	German["Goblin"] = "Goblin"
-
-	German["Author"] = "|cff00A2FF Translated by Nephthis - Durotan (EU).|r"
-
-local French = setmetatable({}, {__index=defaultFunc})
-	French["English Locale loaded"] = "French Locale loaded"
-    French["Enable whispers"] = "Activer les chuchotements"
-    French["Level limits"] = "Limites de niveau"
-    French["Invite Mode"] = "Mode d'invitation"
-    French["Whisper only"] = "Message seulement"
-    French["Invite and whisper"] = "Invitation et message"
-    French["Invite only"] = "Invitation seulement"
-    French["Mute SGI"] = "Mute SGI"
-    French["Filter 55-58 Death Knights"] = "Filtrer les Chevaliers de la mort 55-58"
-    French["Do a more thorough search"] = "Faire une recherche plus minutieuse"
-    French["Customize whisper"] = "Personnaliser le message"
-    French["SuperScan"] = "SuperScan"
-    French["Invite: %d"] = "Inviter: %d"
-    French["Choose Invites"] = "Choisir les invitations"
-    French["Exceptions"] = "Exceptions"
-    French["Help"] = "Aide"
-    French["SuperGuildInvite Custom Whisper"] = "SuperGuildInvite message personnalisé"
-    French["WhisperInstructions"] = "Créé un message personnalisé à envoyer aux personne que vous invitez ! Si vous entrez les mots (doivent être en majuscule) |cff00ff00NAME|r, |cff0000ffLEVEL|r ou |cffff0000PLAYER|r ils seront remplacés par le NomDeLaGuilde, NiveauDeLaGuilde et NomDuJoueurInvité."
-    French["Enter your whisper"] = "Entrez votre message"
-    French["Save"] = "Sauvegarder"
-    French["Cancel"] = "Annuler"
-    French["less than 1 second"] = "moins d'1 seconde"
-    French[" hours "] = " heures "
-    French[" minutes "] = " minutes "
-    French[" seconds"] = " secondes "
-    French[" remaining"] = " restante(s)"
-    French["Purge Queue"] = "Vider la liste"
-    French["Click to toggle SuperScan"] = "Cliquez pour afficher SuperScan"
-    French["Click on the players you wish to invite"] = "Cliquez sur les joueurs que vous souhaitez inviter"
-    French["Scan Completed"] = "Scan terminé"
-    French["Who sent: "] = "Qui envoyé: "
-    French["SuperScan was started"] = "SuperScan démarré"
-    French["SuperScan was stopped"] = "SuperScan arrêté"
-    French["PlayersScanned"] = "Joueurs scannés: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)"
-    French["PlayersGuildLess"] = "Joueurs sans guilde: |cff44FF44%d|r (|cff44FF44%d%%|r)"
-    French["InvitesQueued"] = "Invitations listées: |cff44FF44%d|r"
-    French["ExceptionsInstructions"] = "Vous pouvez ajouter des exceptions, si le nom d'un joueur correspond à l'une d'elles, SuperGuildInvite l'ignorera. Vous pouvez ajouter plusieurs exceptions à la fois, pour cela séparez les par une virgule (,)."
-    French["SGI Exceptions"] = "SGI Exceptions"
-    French["Author"] = "|cff00A2FF Translated by Anonymous, you know who you are and thank you :)|r"
-    French["Go to Options and select your Invite Mode"] = "Allez dans Options et sélectionnez votre Mode d'invitation."
-    French["You need to specify the mode in which you wish to invite"] = "Vous devez spécifier le mode dans lequel vous souhaitez inviter."
-    French["not sending"] = "|cffff8800Pourquoi je n'envoie aucun message ?|r |cff00A2FFPeut-être parce que vous n'avez pas coché l'option.|r|cff00ff00 Cliquez sur ce message pour corriger.|r"
-    French["to specify"] = "|cffff8800J'ai un message m'indiquant que je dois spécifier le mode d'invitation quand j'essaye d'inviter !|r|cff00A2FF Ceci arrive quand vous n'avez pas utilisé le menu déroulant dans les options pour choisir votre mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r"
-    French["I checked the box"] = "|cffff8800Je n'envoie aucun message lorsque j'invite alors que j'ai coché la case !|r|cff00A2FF C'est parce que vous avez choisi \"Invitation seulement\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r"
-    French["whisper to everyone"] = "|cffff8800Je continue d'envoyer des invitations, or je veux seulement envoyer un message et ne pas inviter !|r|cff00A2FF C'est parce que vous avez choisi \"Invitation et message\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r"
-    French["can't get SGI to invite"] = "|cffff8800SGI n'invite personne, il envoie seulement des message.|r|cff00A2FF C'est parce que vous avez choisi \"Message seulement\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r"
-    French["can't see any messages"] = "|cffff8800Je ne vois plus aucun message de SGI !|r|cff00A2FF C'est parce que vous avez muté SGI dans les options.|r|cff00ff00 Cliquez pour corriger.|r"
-    French["None of the above"] = "|cffff8800Aucune des solutions n'a corrigé mon problème !|r|cff00A2FF Il peut y avoir une erreur avec le langage que vous utilisez. Vous pouvez essayer de charger votre langue manuellement : /sgi locale:frFR charge la langue française (deDE pour allemande). Merci de me contacter à :|r|cff00ff00 SuperGuildInvite@gmail.com|r"
-    French["Enabled whispers"] = "Cuchotements activés."
-    French['Changed invite mode to "Invite and Whisper"'] = 'Mode d\'invitation changé en "Invitation et message".'
-    French["Mute has been turned off"] = 'Mute désactivé.'
-    French['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = 'Mode d\'invitation changé en "Inviter seulement". Si vous voulez envoyer un "Message seulement" choisissez-le dans les options.'
-    French["Enter exceptions"] = 'Entrez les exceptions'
-
-    French["Shaman"] = "Chaman"
-    French["Death Knight"] = "Chevalier de la mort"
-    French["Mage"] = "Mage"
-    French["Priest"] = "Prêtre"
-    French["Rogue"] = "Voleur"
-    French["Paladin"] = "Paladin"
-    French["Warlock"] = "Démoniste"
-    French["Druid"] =  "Druide"
-    French["Warrior"] = "Guerrier"
-    French["Hunter"] = "Chasseur"
-    French["Monk"] = "Moine"
-
-    French["Human"] = "Humain"
-    French["Gnome"] = "Gnome"
-    French["Dwarf"] = "Nain"
-    French["NightElf"] = "Elfe de la nuit"
-    French["Draenei"] = "Draeneï"
-    French["Worgen"] = "Worgen"
-    French["Pandaren"] = "Pandaren"
-    French["Undead"] = "Mort-vivant"
-    French["Orc"] = "Orc"
-    French["Troll"] = "Troll"
-    French["Tauren"] = "Tauren"
-    French["BloodElf"] = "Elfe de sang"
-    French["Goblin"] = "Gobelin"
-
-local Spanish = setmetatable({}, {__index=defaultFunc})
-	Spanish["English Locale loaded"] = "Spanish Locale loaded"
-	Spanish["Enable whispers"] = nil
-	Spanish["Level limits"] = nil
-	Spanish["Invite Mode"] = nil
-	Spanish["Whisper only"] = nil
-	Spanish["Invite and whisper"] = nil
-	Spanish["Invite only"] = nil
-	Spanish["Mute SGI"] = nil
-	Spanish["Filter 55-58 Death Knights"] = nil
-	Spanish["Do a more thorough search"] = nil
-	Spanish["Customize whisper"] = nil
-	Spanish["SuperScan"] = nil
-	Spanish["Invite: %d"] = nil
-	Spanish["Choose Invites"] = nil
-	Spanish["Exceptions"] = nil
-	Spanish["Help"] = nil
-	Spanish["SuperGuildInvite Custom Whisper"] = nil
-	Spanish["WhisperInstructions"] = nil
-	Spanish["Enter your whisper"] = nil
-	Spanish["Save"] = nil
-	Spanish["Cancel"] = nil
-	Spanish["less than 1 second"] = nil
-	Spanish[" hours "] = nil
-	Spanish[" minutes "] = nil
-	Spanish[" seconds"] = nil
-	Spanish[" remaining"] = nil
-	Spanish["Purge Queue"] = nil
-	Spanish["Click to toggle SuperScan"] = nil
-	Spanish["Click on the players you wish to invite"] = nil
-	Spanish["Scan Completed"] = nil
-	Spanish["Who sent: "] = nil
-	Spanish["SuperScan was started"] = nil
-	Spanish["SuperScan was stopped"] = nil
-	Spanish["PlayersScanned"] = nil
-	Spanish["PlayersGuildLess"] = nil
-	Spanish["InvitesQueued"] = nil
-	Spanish["ExceptionsInstructions"] = nil
-	Spanish["SGI Exceptions"] = nil
-	Spanish["Author"] = nil
-	Spanish["Go to Options and select your Invite Mode"] = nil
-	Spanish["You need to specify the mode in which you wish to invite"] = nil
-	Spanish["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r"
-	Spanish["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r"
-	Spanish["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r"
-	Spanish["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r"
-	Spanish["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r"
-	Spanish["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r"
-	Spanish["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r"
-	Spanish["Enabled whispers"] = nil
-	Spanish['Changed invite mode to "Invite and Whisper"'] = nil
-	Spanish["Mute has been turned off"] = nil
-	Spanish['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = nil
-	Spanish["Enter exceptions"] = nil
-
-	Spanish["Shaman"] = nil
-	Spanish["Death Knight"] = nil
-	Spanish["Mage"] = nil
-	Spanish["Priest"] = nil
-	Spanish["Rogue"] = nil
-	Spanish["Paladin"] = nil
-	Spanish["Warlock"] = nil
-	Spanish["Druid"] = nil
-	Spanish["Warrior"] = nil
-	Spanish["Hunter"] = nil
-	Spanish["Monk"] = nil
-
-	Spanish["Human"] = nil
-	Spanish["Gnome"] = nil
-	Spanish["Dwarf"] = nil
-	Spanish["NightElf"] = nil
-	Spanish["Draenei"] = nil
-	Spanish["Worgen"] = nil
-	Spanish["Pandaren"] = nil
-	Spanish["Undead"] = nil
-	Spanish["Orc"] = nil
-	Spanish["Troll"] = nil
-	Spanish["Tauren"] = nil
-	Spanish["BloodElf"] = nil
-	Spanish["Goblin"] = nil
-
-local Russian = setmetatable({}, {__index=defaultFunc})
-    Russian["Russian Locale loaded"] = "Russian Locale loaded"
-    Russian["Enable whispers"] = "Разрешить сообщения"
-    Russian["Level limits"] = "Лимит уровней"
-    Russian["Invite Mode"] = "Режим приглашения"
-    Russian["Whisper only"] = "Только сообщение"
-    Russian["Invite and whisper"] = "Приглашение и сообщение"
-    Russian["Invite only"] = "Только приглашение"
-    Russian["Mute SGI"] = "Мут SGI"
-    Russian["Filter 55-58 Death Knights"] = "Фильтровать Рыцарей Смерти 55-58 уровня"
-    Russian["Do a more thorough search"] = "Глубокий поиск"
-    Russian["Customize whisper"] = "Настроить Сообщение"
-    Russian["SuperScan"] = "СуперСканирование"
-    Russian["Invite: %d"] = "Пригласить: %d"
-    Russian["Choose Invites"] = "Выбрать Приглашения"
-    Russian["Exceptions"] = "Исключения"
-    Russian["Help"] = "Помощь"
-    Russian["The level you wish to start dividing the search by race"] = "Уровень, с которого включается рассовый фильтр"
-    Russian["Racefilter Start:"] = "Рассовый Фильтр"
-    Russian["The level you wish to divide the search by class"] = "Уровень, с которого включается классовый фильтр"
-    Russian["Classfilter Start:"] = "Классовый Фильтр"
-    Russian["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = "Интервал уровней для поиска каждые ~7 секунд (больший интервал приводит к риску достигнуть лимита поиска в 49 человек)"
-    Russian["Interval:"] = "Интервал"
-    Russian["SuperGuildInvite Custom Whisper"] = "сообщение по умолчанию SGI"
-    Russian["WhisperInstructions"] = "Create a customized whisper to send people you invite! If you enter the words (must be caps) |cff00ff00NAME|r, |cff0000ffLEVEL|r or |cffff0000PLAYER|r these will be replaced by your Guildname, Guildlevel and the recieving players name"
-    Russian["Enter your whisper"] = "Введите свое сообщение"
-    Russian["Save"] = "Сохранить"
-    Russian["Cancel"] = "Отмена"
-    Russian["less than 1 second"] = "Менее 1 секунды"
-    Russian[" hours "] = " Часов "
-    Russian[" minutes "] = " Минут "
-    Russian[" seconds"] = " Секунд "
-    Russian[" remaining"] = "осталось"
-    Russian["Purge Queue"] = "Очистить Очередь"
-    Russian["Click to toggle SuperScan"] = "Нажмите чтобы переключить СуперСкан"
-    Russian["Click on the players you wish to invite"] = "Нажмите на игроков которых хотите пригласить"
-    Russian["Scan Completed"] = "Сканирование завершено"
-    Russian["Who sent: "] = "Кто отправлено: "
-    Russian["SuperScan was started"] = "СуперСканирование началось"
-    Russian["SuperScan was stopped"] = "Суперсканирование остановлено"
-    Russian["PlayersScanned"] = "Players Scanned: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)"
-    Russian["PlayersGuildLess"] = "Guildless Players: |cff44FF44%d|r (|cff44FF44%d%%|r)"
-    Russian["InvitesQueued"] = "Invites Queued: |cff44FF44%d|r"
-    Russian["ExceptionsInstructions"] = "You can add exception phrases that when found in a name will cause the player to be ignore by SuperGuildInvite. You can add several exceptions at once, seperated by a comma (,)."
-    Russian["SGI Exceptions"] = "Исключения SGI"
-    Russian["Enter exceptions"] = "Ввести исключения"
-    Russian["Go to Options and select your Invite Mode"] = "Откройте настройки и выберите режим приглашения"
-    Russian["You need to specify the mode in which you wish to invite"] = "Вы должны выбрать режим приглашения"
-    Russian["Unable to invite %s. They are already in a guild."] = "Невозможно пришласить %s. Он уже в гильдии"
-    Russian["Unable to invite %s. They will not be blacklisted."] = "Невозможно пришласить %s. Он не будет занесен в черный список"
-
-    --Trouble shooter--
-    Russian["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r"
-    Russian["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r"
-    Russian["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r"
-    Russian["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r"
-    Russian["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r"
-    Russian["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r"
-    Russian["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r"
-    Russian["Enabled whispers"] = "Разрешить сообщения"
-    Russian['Changed invite mode to "Invite and Whisper"'] = "Режим приглашения изменен на 'приглашение и сообщение'"
-    Russian["Mute has been turned off"] = "Мут был выключен"
-    Russian['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = "Режим приглашения изменен на 'только' пригласить. Если вы хотите приглашать людей, смените режим"
-
-
-
-    Russian["Shaman"] = "Шаман"
-    Russian["Death Knight"] = "Рыцарь Смерти"
-    Russian["Mage"] = "Маг"
-    Russian["Priest"] = "Жрец"
-    Russian["Rogue"] = "Разбойник"
-    Russian["Paladin"] = "Паладин"
-    Russian["Warlock"] = "Чернокнижник"
-    Russian["Druid"] = "Друид"
-    Russian["Warrior"] = "Воин"
-    Russian["Hunter"] = "Охотник"
-    Russian["Monk"] = "Монах"
-
-    Russian["Human"] = "Человек"
-    Russian["Gnome"] = "Гном"
-    Russian["Dwarf"] = "Дворф"
-    Russian["NightElf"] = "Ночной Эльф"
-    Russian["Draenei"] = "Дреней"
-    Russian["Worgen"] = "Ворген"
-    Russian["Pandaren"] = "Пандарен"
-    Russian["Undead"] = "Нежить"
-    Russian["Orc"] = "Орк"
-    Russian["Troll"] = "Тролль"
-    Russian["Tauren"] = "Таурен"
-    Russian["BloodElf"] = "Эльф Крови"
-    Russian["Goblin"] = "Гоблин"
-
-    Russian["Author"] = "|cff00A2FF Переведено игроком Вовочкин - Гордунни.|r"
-
-
-SGI_Locale["enGB"] = English
-SGI_Locale["enUS"] = English
-SGI_Locale["deDE"] = German
-SGI_Locale["frFR"] = French
---SGI_Locale["ruRU"] = Russian Can't be added because of client issues.
---SGI_Locale["esES"] = Spanish
---SGI_Locale["esMX"] = Spanish
+SGI_Locale = {}
+
+local function defaultFunc(L,key)
+	return key
+end
+
+local English = setmetatable({}, {__index=defaultFunc})
+	English["English Locale loaded"] = "English Locale loaded"
+	English["Enable whispers"] = "Enable whispers"
+	English["Level limits"] = nil
+	English["Invite Mode"] = nil
+	English["Whisper only"] = nil
+	English["Invite and whisper"] = nil
+	English["Invite only"] = nil
+	English["Mute SGI"] = nil
+	English["Filter 55-58 Death Knights"] = nil
+	English["Do a more thorough search"] = nil
+	English["Customize whisper"] = nil
+	English["SuperScan"] = nil
+	English["Invite: %d"] = nil
+	English["Choose Invites"] = nil
+	English["Exceptions"] = nil
+	English["Help"] = nil
+	English["The level you wish to start dividing the search by race"] = nil
+	English["Racefilter Start:"] = nil
+	English["The level you wish to divide the search by class"] = nil
+	English["Classfilter Start:"] = nil
+	English["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = nil
+	English["Interval:"] = nil
+	English["SuperGuildInvite Custom Whisper"] = nil
+	English["WhisperInstructions"] = "Create a customized whisper to send people you invite! If you enter the words (must be caps) |cff00ff00NAME|r, |cff0000ffLEVEL|r or |cffff0000PLAYER|r these will be replaced by your Guildname, Guildlevel and the recieving players name"
+	English["Enter your whisper"] = nil
+	English["Save"] = nil
+	English["Cancel"] = nil
+	English["less than 1 second"] = nil
+	English[" hours "] = nil
+	English[" minutes "] = nil
+	English[" seconds"] = nil
+	English[" remaining"] = nil
+	English["Purge Queue"] = nil
+	English["Click to toggle SuperScan"] = nil
+	English["Click on the players you wish to invite"] = nil
+	English["Scan Completed"] = nil
+	English["Who sent: "] = nil
+	English["SuperScan was started"] = nil
+	English["SuperScan was stopped"] = nil
+	English["PlayersScanned"] = "Players Scanned: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)"
+	English["PlayersGuildLess"] = "Guildless Players: |cff44FF44%d|r (|cff44FF44%d%%|r)"
+	English["InvitesQueued"] = "Invites Queued: |cff44FF44%d|r"
+	English["ExceptionsInstructions"] = "You can add exception phrases that when found in a name will cause the player to be ignore by SuperGuildInvite. You can add several exceptions at once, seperated by a comma (,)."
+	English["SGI Exceptions"] = nil
+	English["Enter exceptions"] = nil
+	English["Go to Options and select your Invite Mode"] = nil
+	English["You need to specify the mode in which you wish to invite"] = nil
+	English["Unable to invite %s. They are already in a guild."] = nil
+	English["Unable to invite %s. They will not be blacklisted."] = nil
+
+	--Trouble shooter--
+	English["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r"
+	English["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r"
+	English["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r"
+	English["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r"
+	English["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r"
+	English["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r"
+	English["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r"
+	English["Enabled whispers"] = nil
+	English['Changed invite mode to "Invite and Whisper"'] = nil
+	English["Mute has been turned off"] = nil
+	English['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = nil
+
+
+
+	English["Shaman"] = nil
+	English["Death Knight"] = nil
+	English["Mage"] = nil
+	English["Priest"] = nil
+	English["Rogue"] = nil
+	English["Paladin"] = nil
+	English["Warlock"] = nil
+	English["Druid"] = nil
+	English["Warrior"] = nil
+	English["Hunter"] = nil
+	English["Monk"] = nil
+	English["Demon Hunter"] = nil
+
+	English["Human"] = nil
+	English["Gnome"] = nil
+	English["Dwarf"] = nil
+	English["NightElf"] = nil
+	English["Draenei"] = nil
+	English["Worgen"] = nil
+	English["Pandaren"] = nil
+	English["Undead"] = nil
+	English["Orc"] = nil
+	English["Troll"] = nil
+	English["Tauren"] = nil
+	English["BloodElf"] = nil
+	English["Goblin"] = nil
+	English["Nightborne"] = nil
+	English["VoidElf"] = nil
+	English["LightforgedDraenei"] = nil
+	English["HighmountainTauren"] = nil
+	English["Mag'harOrc"] = nil
+	English["Kul'TiranHuman"] = nil
+	English["ZandalariTroll"] = nil
+	English["DarkIronDwarf"] = nil
+
+	English["Author"] = "|cff00A2FF Written by Janniie - Stormreaver EU.|r"
+
+German = setmetatable({}, {__index=defaultFunc})
+	German["English Locale loaded"] = "German Locale loaded"
+	German["Enable whispers"] = "aktivieren Sie flüstert"
+	German["Level limits"] = "Levelbeschränkungen"
+	German["Invite Mode"] = "Einladungsart"
+	German["Whisper only"] = "Nur anflüstern"
+	German["Invite and whisper"] = "Einladen und anflüstern"
+	German["Invite only"] = "Nur einladen"
+	German["Mute SGI"] = "SGI stummschalten"
+	German["Filter 55-58 Death Knights"] = "Level 55-58 Todesritter filtern"
+	German["Do a more thorough search"] = "Gründlichere Suche ausführen"
+	German["Customize whisper"] = "Flüsternachricht anpassen"
+	German["SuperScan"] = "SuperScan"
+	German["Invite: %d"] = "Einladen: %d"
+	German["Choose Invites"] = "einladungen auswählen"
+	German["Exceptions"] = "Ausnahmen"
+	German["Help"] = "Hilfe"
+	German["SuperGuildInvite Custom Whisper"] = "SuperGuildInvite eigene Flüsternachricht"
+	German["WhisperInstructions"] = "Erstelle eine eigene Flüsternachricht, die an die Leute gesendet wird, die du einlädst! Wenn du die worte |cff00ff00NAME|r, |cff0000ffLEVEL|r oder |cffff0000PLAYER|r (in Großbuchstaben) benutzt werden diese durch Gildenname, Gildenlevel und den Namen des Empfängers ersetzt."
+	German["Enter your whisper"] = "Flüsternachricht eingeben"
+	German["Save"] = "Speichern"
+	German["Cancel"] = "Abbrechen"
+	German["less than 1 second"] = "weniger als 1 Sekunden verbleibend"
+	German[" hours "] = " Stunden "
+	German[" minutes "] = " minute "
+	German[" seconds"] = " Sekunden"
+	German[" remaining"] = " verbleibend"
+	German["Purge Queue"] = "Warteschlange leeren"
+	German["Click to toggle SuperScan"] = "Klicken um SuperScan zu beenden"
+	German["Click on the players you wish to invite"] = "Klicke die Spieler an, die du einladen willst"
+	German["Scan Completed"] = "Suchlauf beendet"
+	German["Who sent: "] = "Wer-Abfrage gesendet: "
+	German["SuperScan was started"] = "SuperScan wurde gestartet"
+	German["SuperScan was stopped"] = "SuperScan wurde gestoppt"
+	German["PlayersScanned"] = "Spieler durchsucht: |cff44FF44%d|r (Insgesamt: |cff44FF44%d|r)"
+	German["PlayersGuildLess"] = "gildenlose Spieler: |cff44FF44%d|r"
+	German["InvitesQueued"] = "Einladungen in Warteschlange: |cff44FF44%d|r"
+	German["ExceptionsInstructions"] = "Hier kannst du Ausnahmen eingeben, die, wenn sie in einem Namen gefunden werden, dazu führen daß SGI diesen Spieler ignoriert. Du kannst mehrere Ausnahmen durch ein Komma (,) getrennt eingeben."
+	German["SGI Exceptions"] = "SGI Ausnahmen"
+	German["Go to Options and select your Invite Mode"] = "Gehen Sie auf Optionen und wählen Sie Einladungsart"
+	German["You need to specify the mode in which you wish to invite"] = "Sie müssen den Modus, in dem Sie einladen möchten festlegen"
+	German["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = "Anzahl der Level nach denen etwa alle 7 Sekunden gesucht wird (höhere Zahlen erhöhen das Risiko, daß nicht alle Suchergebnisse bearbeitet werden)."
+	German["The level you wish to divide the search by class"] = "Level ab dem nach Klasse gesucht wird."
+	German["The level you wish to divide the search by race"] = "Level ab dem nach Rasse gesucht wird."
+
+	German["not sending"] = "|cffff8800Warum verschicke ich keine Flüsternachrichten?|r |cff00A2FFMöglicherweise hast du das Kästchen nicht angekreuzt.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
+	German["to specify"] = "|cffff8800Ich bekomme eine Nachricht, daß ich die Einladungsart auswählen soll wenn ich jemanden einladen möchte.|r|cff00A2FF Das passiert wenn du nicht das Auswahlmenü in den Optionen benutzt hast um auszuwählen wie du Leute einlädst.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
+	German["I checked the box"] = "|cffff8800Ich verschicke keine Flüsternachrichten beim Einladen, obwohl ich das Kästchen angekreuzt habe.|r|cff00A2FF Das passiert wenn du nur einladen im Auswahlmenü ausgewählt hast.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
+	German["whisper to everyone"] = "|cffff8800Ich verschicke Flüsternachrichten an jeden den ich einlade ODER ich möchte nur Flüsternachrichten senden aber das AddOn macht beides!|r|cff00A2FF Das passiert weil du einladen und anflüstern im Auswahlmenü ausgewählt hast.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
+	German["can't get SGI to invite"] = "|cffff8800SGI lädt keine Leute ein und schickt ausschließlich Flüsternachrichten.|r|cff00A2FF DU hast nur diese Option im Auswahlmenü ausgewählt.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
+	German["can't see any messages"] = "|cffff8800Ich sehe keinerlei Ausgabe von SGI.|r|cff00A2FF Du hast SGI in den Optionen stummgeschaltet.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r"
+	German["None of the above"] = "|cffff8800Keine der obenstehenden Lösungen löst mein Problem!|r|cff00A2FF Es könnte ein Problem mit der Lokalisation (Sprache) geben, die du benutzt. Du kannst versuchen mit /sgi locale:deDE die deutschen Sprachoptionen zu laden (frFR für Französisch). Bitte schick mir eine Nachricht an:|r|cff00ff00 SuperGuildInvite@gmail.com|r"
+	German["Enabled whispers"] = "Flüsternachrichten eingeschaltet"
+	German['Changed invite mode to "Invite and Whisper"'] = "Einladungsart auf einladen und anflüstern geändert"
+	German["Mute has been turned off"] = "Stummschaltung wurde ausgeschaltet"
+	German['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = "Einladungsmodus auf nur einladen geändert. Wenn du nur anflüstern wolltest, gehe in die Optionen und ändere es dort."
+	German["Enter exceptions"] = "Ausnahmen eingeben"
+	German["Highest and lowest level to search for"] = "Höchster und niedrigster Level nach dem gesucht wird"
+
+
+	German["Shaman"] = "Schamane"
+	German["Death Knight"] = "Todesritter"
+	German["Mage"] = "Magier"
+	German["Priest"] = "Priester"
+	German["Rogue"] = "Schurke"
+	German["Paladin"] = "Paladin"
+	German["Warlock"] = "Hexenmeister"
+	German["Druid"] = "Druide"
+	German["Warrior"] = "Krieger"
+	German["Hunter"] = "Jäger"
+	German["Monk"] = "Mönch"
+	German["Demon Hunter"] = "Dämonenjäger"
+
+	German["Human"] = "Mensch"
+	German["Gnome"] = "Gnom"
+	German["Dwarf"] = "Zwerg"
+	German["NightElf"] = "Nachtelf"
+	German["Draenei"] = "Draenei"
+	German["Worgen"] = "Worgen"
+	German["Pandaren"] = "Pandaren"
+	German["Undead"] = "Untoter"
+	German["Orc"] = "Ork"
+	German["Troll"] = "Troll"
+	German["Tauren"] = "Taure"
+	German["BloodElf"] = "Blutelf"
+	German["Goblin"] = "Goblin"
+
+	German["Author"] = "|cff00A2FF Translated by Nephthis - Durotan (EU).|r"
+
+local French = setmetatable({}, {__index=defaultFunc})
+	French["English Locale loaded"] = "French Locale loaded"
+    French["Enable whispers"] = "Activer les chuchotements"
+    French["Level limits"] = "Limites de niveau"
+    French["Invite Mode"] = "Mode d'invitation"
+    French["Whisper only"] = "Message seulement"
+    French["Invite and whisper"] = "Invitation et message"
+    French["Invite only"] = "Invitation seulement"
+    French["Mute SGI"] = "Mute SGI"
+    French["Filter 55-58 Death Knights"] = "Filtrer les Chevaliers de la mort 55-58"
+    French["Do a more thorough search"] = "Faire une recherche plus minutieuse"
+    French["Customize whisper"] = "Personnaliser le message"
+    French["SuperScan"] = "SuperScan"
+    French["Invite: %d"] = "Inviter: %d"
+    French["Choose Invites"] = "Choisir les invitations"
+    French["Exceptions"] = "Exceptions"
+    French["Help"] = "Aide"
+    French["SuperGuildInvite Custom Whisper"] = "SuperGuildInvite message personnalisé"
+    French["WhisperInstructions"] = "Créé un message personnalisé à envoyer aux personne que vous invitez ! Si vous entrez les mots (doivent être en majuscule) |cff00ff00NAME|r, |cff0000ffLEVEL|r ou |cffff0000PLAYER|r ils seront remplacés par le NomDeLaGuilde, NiveauDeLaGuilde et NomDuJoueurInvité."
+    French["Enter your whisper"] = "Entrez votre message"
+    French["Save"] = "Sauvegarder"
+    French["Cancel"] = "Annuler"
+    French["less than 1 second"] = "moins d'1 seconde"
+    French[" hours "] = " heures "
+    French[" minutes "] = " minutes "
+    French[" seconds"] = " secondes "
+    French[" remaining"] = " restante(s)"
+    French["Purge Queue"] = "Vider la liste"
+    French["Click to toggle SuperScan"] = "Cliquez pour afficher SuperScan"
+    French["Click on the players you wish to invite"] = "Cliquez sur les joueurs que vous souhaitez inviter"
+    French["Scan Completed"] = "Scan terminé"
+    French["Who sent: "] = "Qui envoyé: "
+    French["SuperScan was started"] = "SuperScan démarré"
+    French["SuperScan was stopped"] = "SuperScan arrêté"
+    French["PlayersScanned"] = "Joueurs scannés: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)"
+    French["PlayersGuildLess"] = "Joueurs sans guilde: |cff44FF44%d|r (|cff44FF44%d%%|r)"
+    French["InvitesQueued"] = "Invitations listées: |cff44FF44%d|r"
+    French["ExceptionsInstructions"] = "Vous pouvez ajouter des exceptions, si le nom d'un joueur correspond à l'une d'elles, SuperGuildInvite l'ignorera. Vous pouvez ajouter plusieurs exceptions à la fois, pour cela séparez les par une virgule (,)."
+    French["SGI Exceptions"] = "SGI Exceptions"
+    French["Author"] = "|cff00A2FF Translated by Anonymous, you know who you are and thank you :)|r"
+    French["Go to Options and select your Invite Mode"] = "Allez dans Options et sélectionnez votre Mode d'invitation."
+    French["You need to specify the mode in which you wish to invite"] = "Vous devez spécifier le mode dans lequel vous souhaitez inviter."
+    French["not sending"] = "|cffff8800Pourquoi je n'envoie aucun message ?|r |cff00A2FFPeut-être parce que vous n'avez pas coché l'option.|r|cff00ff00 Cliquez sur ce message pour corriger.|r"
+    French["to specify"] = "|cffff8800J'ai un message m'indiquant que je dois spécifier le mode d'invitation quand j'essaye d'inviter !|r|cff00A2FF Ceci arrive quand vous n'avez pas utilisé le menu déroulant dans les options pour choisir votre mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r"
+    French["I checked the box"] = "|cffff8800Je n'envoie aucun message lorsque j'invite alors que j'ai coché la case !|r|cff00A2FF C'est parce que vous avez choisi \"Invitation seulement\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r"
+    French["whisper to everyone"] = "|cffff8800Je continue d'envoyer des invitations, or je veux seulement envoyer un message et ne pas inviter !|r|cff00A2FF C'est parce que vous avez choisi \"Invitation et message\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r"
+    French["can't get SGI to invite"] = "|cffff8800SGI n'invite personne, il envoie seulement des message.|r|cff00A2FF C'est parce que vous avez choisi \"Message seulement\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r"
+    French["can't see any messages"] = "|cffff8800Je ne vois plus aucun message de SGI !|r|cff00A2FF C'est parce que vous avez muté SGI dans les options.|r|cff00ff00 Cliquez pour corriger.|r"
+    French["None of the above"] = "|cffff8800Aucune des solutions n'a corrigé mon problème !|r|cff00A2FF Il peut y avoir une erreur avec le langage que vous utilisez. Vous pouvez essayer de charger votre langue manuellement : /sgi locale:frFR charge la langue française (deDE pour allemande). Merci de me contacter à :|r|cff00ff00 SuperGuildInvite@gmail.com|r"
+    French["Enabled whispers"] = "Cuchotements activés."
+    French['Changed invite mode to "Invite and Whisper"'] = 'Mode d\'invitation changé en "Invitation et message".'
+    French["Mute has been turned off"] = 'Mute désactivé.'
+    French['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = 'Mode d\'invitation changé en "Inviter seulement". Si vous voulez envoyer un "Message seulement" choisissez-le dans les options.'
+    French["Enter exceptions"] = 'Entrez les exceptions'
+
+    French["Shaman"] = "Chaman"
+    French["Death Knight"] = "Chevalier de la mort"
+    French["Mage"] = "Mage"
+    French["Priest"] = "Prêtre"
+    French["Rogue"] = "Voleur"
+    French["Paladin"] = "Paladin"
+    French["Warlock"] = "Démoniste"
+    French["Druid"] =  "Druide"
+    French["Warrior"] = "Guerrier"
+    French["Hunter"] = "Chasseur"
+    French["Monk"] = "Moine"
+	French["Demon Hunter"] = "Chasseur de démons"
+
+    French["Human"] = "Humain"
+    French["Gnome"] = "Gnome"
+    French["Dwarf"] = "Nain"
+    French["NightElf"] = "Elfe de la nuit"
+    French["Draenei"] = "Draeneï"
+    French["Worgen"] = "Worgen"
+    French["Pandaren"] = "Pandaren"
+    French["Undead"] = "Mort-vivant"
+    French["Orc"] = "Orc"
+    French["Troll"] = "Troll"
+    French["Tauren"] = "Tauren"
+    French["BloodElf"] = "Elfe de sang"
+    French["Goblin"] = "Gobelin"
+
+local Spanish = setmetatable({}, {__index=defaultFunc})
+	Spanish["English Locale loaded"] = "Spanish Locale loaded"
+	Spanish["Enable whispers"] = nil
+	Spanish["Level limits"] = nil
+	Spanish["Invite Mode"] = nil
+	Spanish["Whisper only"] = nil
+	Spanish["Invite and whisper"] = nil
+	Spanish["Invite only"] = nil
+	Spanish["Mute SGI"] = nil
+	Spanish["Filter 55-58 Death Knights"] = nil
+	Spanish["Do a more thorough search"] = nil
+	Spanish["Customize whisper"] = nil
+	Spanish["SuperScan"] = nil
+	Spanish["Invite: %d"] = nil
+	Spanish["Choose Invites"] = nil
+	Spanish["Exceptions"] = nil
+	Spanish["Help"] = nil
+	Spanish["SuperGuildInvite Custom Whisper"] = nil
+	Spanish["WhisperInstructions"] = nil
+	Spanish["Enter your whisper"] = nil
+	Spanish["Save"] = nil
+	Spanish["Cancel"] = nil
+	Spanish["less than 1 second"] = nil
+	Spanish[" hours "] = nil
+	Spanish[" minutes "] = nil
+	Spanish[" seconds"] = nil
+	Spanish[" remaining"] = nil
+	Spanish["Purge Queue"] = nil
+	Spanish["Click to toggle SuperScan"] = nil
+	Spanish["Click on the players you wish to invite"] = nil
+	Spanish["Scan Completed"] = nil
+	Spanish["Who sent: "] = nil
+	Spanish["SuperScan was started"] = nil
+	Spanish["SuperScan was stopped"] = nil
+	Spanish["PlayersScanned"] = nil
+	Spanish["PlayersGuildLess"] = nil
+	Spanish["InvitesQueued"] = nil
+	Spanish["ExceptionsInstructions"] = nil
+	Spanish["SGI Exceptions"] = nil
+	Spanish["Author"] = nil
+	Spanish["Go to Options and select your Invite Mode"] = nil
+	Spanish["You need to specify the mode in which you wish to invite"] = nil
+	Spanish["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r"
+	Spanish["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r"
+	Spanish["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r"
+	Spanish["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r"
+	Spanish["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r"
+	Spanish["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r"
+	Spanish["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r"
+	Spanish["Enabled whispers"] = nil
+	Spanish['Changed invite mode to "Invite and Whisper"'] = nil
+	Spanish["Mute has been turned off"] = nil
+	Spanish['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = nil
+	Spanish["Enter exceptions"] = nil
+
+	Spanish["Shaman"] = nil
+	Spanish["Death Knight"] = nil
+	Spanish["Mage"] = nil
+	Spanish["Priest"] = nil
+	Spanish["Rogue"] = nil
+	Spanish["Paladin"] = nil
+	Spanish["Warlock"] = nil
+	Spanish["Druid"] = nil
+	Spanish["Warrior"] = nil
+	Spanish["Hunter"] = nil
+	Spanish["Monk"] = nil
+
+	Spanish["Human"] = nil
+	Spanish["Gnome"] = nil
+	Spanish["Dwarf"] = nil
+	Spanish["NightElf"] = nil
+	Spanish["Draenei"] = nil
+	Spanish["Worgen"] = nil
+	Spanish["Pandaren"] = nil
+	Spanish["Undead"] = nil
+	Spanish["Orc"] = nil
+	Spanish["Troll"] = nil
+	Spanish["Tauren"] = nil
+	Spanish["BloodElf"] = nil
+	Spanish["Goblin"] = nil
+
+local Russian = setmetatable({}, {__index=defaultFunc})
+    Russian["Russian Locale loaded"] = "Russian Locale loaded"
+    Russian["Enable whispers"] = "Разрешить сообщения"
+    Russian["Level limits"] = "Лимит уровней"
+    Russian["Invite Mode"] = "Режим приглашения"
+    Russian["Whisper only"] = "Только сообщение"
+    Russian["Invite and whisper"] = "Приглашение и сообщение"
+    Russian["Invite only"] = "Только приглашение"
+    Russian["Mute SGI"] = "Мут SGI"
+    Russian["Filter 55-58 Death Knights"] = "Фильтровать Рыцарей Смерти 55-58 уровня"
+    Russian["Do a more thorough search"] = "Глубокий поиск"
+    Russian["Customize whisper"] = "Настроить Сообщение"
+    Russian["SuperScan"] = "СуперСканирование"
+    Russian["Invite: %d"] = "Пригласить: %d"
+    Russian["Choose Invites"] = "Выбрать Приглашения"
+    Russian["Exceptions"] = "Исключения"
+    Russian["Help"] = "Помощь"
+    Russian["The level you wish to start dividing the search by race"] = "Уровень, с которого включается рассовый фильтр"
+    Russian["Racefilter Start:"] = "Рассовый Фильтр"
+    Russian["The level you wish to divide the search by class"] = "Уровень, с которого включается классовый фильтр"
+    Russian["Classfilter Start:"] = "Классовый Фильтр"
+    Russian["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = "Интервал уровней для поиска каждые ~7 секунд (больший интервал приводит к риску достигнуть лимита поиска в 49 человек)"
+    Russian["Interval:"] = "Интервал"
+    Russian["SuperGuildInvite Custom Whisper"] = "сообщение по умолчанию SGI"
+    Russian["WhisperInstructions"] = "Create a customized whisper to send people you invite! If you enter the words (must be caps) |cff00ff00NAME|r, |cff0000ffLEVEL|r or |cffff0000PLAYER|r these will be replaced by your Guildname, Guildlevel and the recieving players name"
+    Russian["Enter your whisper"] = "Введите свое сообщение"
+    Russian["Save"] = "Сохранить"
+    Russian["Cancel"] = "Отмена"
+    Russian["less than 1 second"] = "Менее 1 секунды"
+    Russian[" hours "] = " Часов "
+    Russian[" minutes "] = " Минут "
+    Russian[" seconds"] = " Секунд "
+    Russian[" remaining"] = "осталось"
+    Russian["Purge Queue"] = "Очистить Очередь"
+    Russian["Click to toggle SuperScan"] = "Нажмите чтобы переключить СуперСкан"
+    Russian["Click on the players you wish to invite"] = "Нажмите на игроков которых хотите пригласить"
+    Russian["Scan Completed"] = "Сканирование завершено"
+    Russian["Who sent: "] = "Кто отправлено: "
+    Russian["SuperScan was started"] = "СуперСканирование началось"
+    Russian["SuperScan was stopped"] = "Суперсканирование остановлено"
+    Russian["PlayersScanned"] = "Players Scanned: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)"
+    Russian["PlayersGuildLess"] = "Guildless Players: |cff44FF44%d|r (|cff44FF44%d%%|r)"
+    Russian["InvitesQueued"] = "Invites Queued: |cff44FF44%d|r"
+    Russian["ExceptionsInstructions"] = "You can add exception phrases that when found in a name will cause the player to be ignore by SuperGuildInvite. You can add several exceptions at once, seperated by a comma (,)."
+    Russian["SGI Exceptions"] = "Исключения SGI"
+    Russian["Enter exceptions"] = "Ввести исключения"
+    Russian["Go to Options and select your Invite Mode"] = "Откройте настройки и выберите режим приглашения"
+    Russian["You need to specify the mode in which you wish to invite"] = "Вы должны выбрать режим приглашения"
+    Russian["Unable to invite %s. They are already in a guild."] = "Невозможно пришласить %s. Он уже в гильдии"
+    Russian["Unable to invite %s. They will not be blacklisted."] = "Невозможно пришласить %s. Он не будет занесен в черный список"
+
+    --Trouble shooter--
+    Russian["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r"
+    Russian["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r"
+    Russian["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r"
+    Russian["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r"
+    Russian["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r"
+    Russian["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r"
+    Russian["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r"
+    Russian["Enabled whispers"] = "Разрешить сообщения"
+    Russian['Changed invite mode to "Invite and Whisper"'] = "Режим приглашения изменен на 'приглашение и сообщение'"
+    Russian["Mute has been turned off"] = "Мут был выключен"
+    Russian['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = "Режим приглашения изменен на 'только' пригласить. Если вы хотите приглашать людей, смените режим"
+
+
+
+    Russian["Shaman"] = "Шаман"
+    Russian["Death Knight"] = "Рыцарь Смерти"
+    Russian["Mage"] = "Маг"
+    Russian["Priest"] = "Жрец"
+    Russian["Rogue"] = "Разбойник"
+    Russian["Paladin"] = "Паладин"
+    Russian["Warlock"] = "Чернокнижник"
+    Russian["Druid"] = "Друид"
+    Russian["Warrior"] = "Воин"
+    Russian["Hunter"] = "Охотник"
+    Russian["Monk"] = "Монах"
+
+    Russian["Human"] = "Человек"
+    Russian["Gnome"] = "Гном"
+    Russian["Dwarf"] = "Дворф"
+    Russian["NightElf"] = "Ночной Эльф"
+    Russian["Draenei"] = "Дреней"
+    Russian["Worgen"] = "Ворген"
+    Russian["Pandaren"] = "Пандарен"
+    Russian["Undead"] = "Нежить"
+    Russian["Orc"] = "Орк"
+    Russian["Troll"] = "Тролль"
+    Russian["Tauren"] = "Таурен"
+    Russian["BloodElf"] = "Эльф Крови"
+    Russian["Goblin"] = "Гоблин"
+
+    Russian["Author"] = "|cff00A2FF Переведено игроком Вовочкин - Гордунни.|r"
+
+
+SGI_Locale["enGB"] = English
+SGI_Locale["enUS"] = English
+SGI_Locale["deDE"] = German
+SGI_Locale["frFR"] = French
+--SGI_Locale["ruRU"] = Russian Can't be added because of client issues.
+--SGI_Locale["esES"] = Spanish
+--SGI_Locale["esMX"] = Spanish