diff Core.lua @ 0:823e33465b6e

Initial commit
author Zerotorescue
date Fri, 03 Sep 2010 12:43:36 +0200
parents
children 6f17035de058
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core.lua	Fri Sep 03 12:43:36 2010 +0200
@@ -0,0 +1,728 @@
+MailOpener = LibStub("AceAddon-3.0"):NewAddon("MailOpener", "AceEvent-3.0", "AceTimer-3.0");
+
+local enabled = true;
+local MailOpenerConfig, lastAmount, lastQuickAuctionsStatus, opening, freshList, mailboxEmptySoundPlayed;
+
+function MailOpener:OnInitialize()
+	local defaults = {
+		global = {
+			uses = 0;
+		},
+		profile = {
+			general = {
+				defaultStatus = "_enabled",
+				defaultQAStatus = "__remember",
+				continueOpeningStackableItems = false,
+				autoDisableQAAutoMail = true,
+				autoReenableQAAutoMail = false,
+				autoSetBackQAAutoMail = true,
+				continueOpening = false,
+				waitTime = 5,
+				initialDelay = 0.5,
+			},
+			modules = {
+				Collected = true,
+			},
+			notifications = {
+				welcome = true,
+				bye = true,
+				finishedCurrentBatch = true,
+				mailboxIsEmpty = true,
+				
+				skipped = {
+					all = true,
+					inventoryFull = true,
+					keepFreeSpaceLimit = true,
+					GMMail = true,
+					COD = true,
+					normalGoldMail = true,
+					normalItemsMail = true,
+					AHexpired = true,
+					AHsuccess = true,
+					AHwon = true,
+					AHcanceled = true,
+					AHoutbid = true,
+					other = true,
+				},
+				processed = {
+					all = true,
+					normalGoldMail = true,
+					normalItemsMail = true,
+					AHexpired = true,
+					AHsuccess = true,
+					AHwon = true,
+					AHcanceled = true,
+					AHoutbid = true,
+					other = true,
+				},
+				
+				bagsFullSound = false,
+				bagsFullSoundFile = "Sound\\Spells\\SimonGame_Visual_BadPress.wav",
+				bagsFullSoundFileName = "Simon Error",
+				bagsFullSoundOnlyOnce = true,
+				mailboxEmptySound = false,
+				mailboxEmptySoundFile = "Sound\\Spells\\SimonGame_Visual_GameStart.wav",
+				mailboxEmptySoundFileName = "Simon Start",
+				mailboxEmptySoundOnlyOnce = true,
+			},
+		},
+	};
+	
+	-- Register our saved variables database
+	self.db = LibStub("AceDB-3.0"):New("MailOpenerDB", defaults, true);
+	
+	-- Set these as object variables so we can use them in our modules
+	if select(6, GetAddOnInfo("Postal")) == nil then
+		self.PostalEnabled = true;
+		
+		-- Ensure this addon is loaded if AddonLoader is installed
+		if AddonLoader and AddonLoader.LoadAddOn and not Postal then
+			AddonLoader:LoadAddOn("Postal");
+		end
+	end
+	
+	if select(6, GetAddOnInfo("QuickAuctions")) == nil then
+		self.QuickAuctionsEnabled = true;
+		
+		-- Ensure this addon is loaded if AddonLoader is installed
+		if AddonLoader and AddonLoader.LoadAddOn then
+			AddonLoader:LoadAddOn("QuickAuctions");
+		end
+	end
+	
+	-- Don't enable the config module until we need it
+	for name, module in self:IterateModules() do
+		if name == "Config" then
+			module:SetEnabledState(false);
+		elseif self.db.profile.modules[name] ~= nil then
+			if self.db.profile.modules[name] then
+				self:Debug("|cff00ff00Enabling|r module: " .. name);
+			else
+				self:Debug("|cffff0000Disabling|r module: " .. name);
+			end
+			
+			module:SetEnabledState(self.db.profile.modules[name]);
+		end
+	end
+	
+	-- Make the open all checkbox
+	local check = CreateFrame("CheckButton", "cbMailOpenerEnable", MailFrame, "ChatConfigCheckButtonTemplate");
+	check:SetHeight(26);
+	check:SetWidth(26);
+	check:SetChecked(enabled);
+	check:SetHitRectInsets(0, -80, 0, 0);
+	check:SetScript("OnClick", function(self)
+		if self:GetChecked() then
+			MailOpener:Enable();
+		else
+			MailOpener:Disable();
+		end
+	end);
+	check.tooltip = "Toggle Mail Opener on or off.";
+	check:SetPoint("TOPLEFT", MailFrame, "TOPLEFT", 68, -13)
+	
+	if self.QuickAuctionsEnabled then
+		-- QA is enabled so move the checkbox further to the right
+		
+		check:SetPoint("TOPLEFT", MailFrame, "TOPLEFT", 155, -13);
+	end
+	
+	-- Get reference to the text field
+	local checkboxText = _G[check:GetName() .. "Text"];
+	checkboxText:SetText("Mail Opener");
+	-- We like this color more
+	checkboxText:SetTextColor(1, 0.8, 0, 1);
+	
+	self.cbOpenAll = check;
+	
+	-- Make the config button
+	local button = CreateFrame("Button", "btnMailOpenerConfig", MailFrame, "UIPanelButtonTemplate")
+	button:SetText("Config")
+	button:SetHeight(23)
+	button:SetWidth(55)
+	if self.PostalEnabled then
+		button:SetPoint("TOPRIGHT", MailFrame, "TOPRIGHT", -75, -13);
+	else
+		button:SetPoint("TOPRIGHT", MailFrame, "TOPRIGHT", -55, -13);
+	end
+	button:SetScript("OnClick", function()
+		MailOpener:EnableConfigModule();
+		
+		MailOpenerConfig:Show();
+	
+		if MailOpener.db.global.uses >= 15 then
+			MailOpener:ShowBetaPopup();
+		end
+	end);
+	
+	self.btnConfig = button;
+
+	-- Disable the AddonLoader slash commands
+	SLASH_MO1 = nil;
+	SLASH_MAILOPEN1 = nil;
+	SLASH_MAILOPENER1 = nil;
+	
+	-- Register our own slash commands
+	SLASH_MAILOPENER1 = "/mo";
+	SLASH_MAILOPENER2 = "/mailopen";
+	SLASH_MAILOPENER3 = "/mailopener";
+	SlashCmdList["MAILOPENER"] = function(msg)
+		MailOpener:EnableConfigModule();
+		
+		MailOpenerConfig:CommandHandler(msg);
+	end
+		
+	 -- Attempt to remove the interface options added by AddonLoader (if enabled)
+	if AddonLoader and AddonLoader.RemoveInterfaceOptions then
+		AddonLoader:RemoveInterfaceOptions("Mail Opener");
+	end
+	
+	-- Now create our own options frame
+	local frame = CreateFrame("Frame", nil, UIParent);
+	frame:Hide();
+	frame.name = "Mail Opener";
+	frame:HookScript("OnShow", function(self)
+		-- Enable the config module
+		MailOpener:EnableConfigModule();
+		
+		-- Load the options and add it to the blizzard interface list
+		MailOpenerConfig:Load();
+		
+		-- Refresh the frame to instantly show the right options
+		InterfaceOptionsFrame_OpenToCategory(self.name)
+	end);
+	-- And add it to the interface options
+	InterfaceOptions_AddCategory(frame);
+	
+	-- If the above becomes impossible this is another way to load the config module when required due to Interface/AddOns options
+	--InterfaceOptionsFrameTab2:HookScript("OnClick", function()
+	--	-- Load the config module
+	--	MailOpener:EnableConfigModule();
+		
+	--	-- Load the options and add it to the blizzard interface list
+	--	MailOpenerConfig:Load();
+	--end);
+end
+
+function MailOpener:OnEnable()
+	self:RegisterEvent("MAIL_SHOW");
+	self:RegisterEvent("PLAYER_ENTERING_WORLD");
+	
+	self.btnConfig:Show();
+	
+	-- Reset variables
+	lastAmount = 0;
+	self.debugChannel = nil;
+	
+	self.db.global.uses = ( self.db.global.uses + 1 );
+	
+	if self.db.global.uses == 15 then
+		self:ShowBetaPopup();
+	end
+	
+	-- If we were toggling this addon on while the mailbox is opened we must register all events again
+	if MailFrame:IsVisible() then
+		self:MAIL_SHOW();
+	end
+end
+
+function MailOpener:OnDisable()
+	self:UnregisterEvent("MAIL_SHOW");
+	
+	self.btnConfig:Hide();
+	
+	enabled = false;
+	MailOpener:Stop();
+end
+
+-- We must disable Quick Auction's auto mail (if set up that way in the settings) before opening the mailbox or it will instantly start sending stuff
+function MailOpener:PLAYER_ENTERING_WORLD()
+	self:UnregisterEvent("PLAYER_ENTERING_WORLD");
+	
+	self:ToggleQAStatus();
+end
+
+-- Fired when the mailbox is opened
+function MailOpener:MAIL_SHOW()
+	-- To stop the timer when the mailbox is closed
+	self:RegisterEvent("MAIL_CLOSED", "Stop");
+	self:RegisterEvent("PLAYER_LEAVING_WORLD", "Stop");
+	
+	-- To set the timer for when to refresh again
+	self:RegisterEvent("MAIL_INBOX_UPDATE");
+	
+	-- We need to know when opening has completed
+	self:RegisterMessage("MO_OPEN_COMPLETE");
+	
+	self:Debug("defaultStatus:" .. self.db.profile.general.defaultStatus);
+	-- Change the mail opening status according to our settings
+	if self.db.profile.general.defaultStatus == "_enabled" then
+		enabled = true;
+	else
+		enabled = false;
+	end
+	self.cbOpenAll:SetChecked(enabled);
+	
+	self:ToggleQAStatus();
+	
+	-- Hide the InboxTooMuchMail warning to allow room for our mail remaining info line
+	InboxTooMuchMail:Hide()
+	InboxTooMuchMail.Show = function() end
+	
+	if self.QuickAuctionsEnabled then
+		-- Go through all children of the mail frame to find the post button
+		local kids = { InboxFrame:GetChildren() };
+		
+		for _, child in ipairs(kids) do
+			if child then
+				local width = floor( child:GetWidth() + .5 );
+				local height = floor( child:GetHeight() + .5 );
+				
+				-- The open all button has a static width and height
+				if width == 130 and height == 24 then
+					child:Hide();
+					break;
+				end
+			end
+		end
+	end
+	
+	if self.db.profile.notifications.welcome then
+		-- Welcome notification
+		local _, c = UnitClass("player");
+		c = RAID_CLASS_COLORS[c];
+		c = string.format("|cff%02x%02x%02x", c.r * 255 + 0.5, c.g * 255 + 0.5, c.b * 255 + 0.5);
+	
+		print("|cff15ff00Mail Opener|r: Welcome back "..c..UnitName("player").."|r. Requesting new mail from the local Postal Service, your mail will automatically be opened when it becomes available.");
+	end
+	
+	mailboxEmptySoundPlayed = nil;
+	
+	self:Recheck();
+	
+	if self.db.profile.general.continueOpening then
+		self:ScheduleOpen(true);
+	end
+end
+
+-- Fired after a successful server sync
+-- Fired when mail is deleted (which happens after taking all attachments from a mail sent by the game)
+function MailOpener:MAIL_INBOX_UPDATE()
+	local current, total = GetInboxNumItems();
+	
+	local tempLastAmount = lastAmount;
+	lastAmount = current;
+	
+	if current ~= tempLastAmount then
+		self:Debug("MAIL_INBOX_UPDATE - lastAmount:" .. tempLastAmount .. " - current:" .. current);
+	end
+	
+	if current > tempLastAmount then
+		-- New messages arrived in our mailbox, so this was a refresh, so set a timer
+		
+		-- Yell that we successfully synced with the server
+		self:SendMessage("MO_SERVER_SYNCED");
+		
+		-- This list is fresh
+		freshList = true;
+		mailboxEmptySoundPlayed = nil;
+		
+		-- Stop previous timer
+		self:CancelTimer(self.tmrRecheck, true);
+		-- More will arrive in 60 seconds
+		self.tmrRecheck = self:ScheduleTimer(function()
+			self:Debug("tmrRecheck 61 finished");
+			
+			-- We can get a fresh list now, so query the server
+			freshList = false;
+			
+			-- Look for mail
+			self:Recheck();
+		end, 61);
+		self:Debug("tmrRecheck 61");
+		
+		if not IsShiftKeyDown() then
+			-- Allow overriding of mailopening with the shift key
+			
+			-- Open the current mail
+			self:ScheduleOpen(false);
+		end
+	elseif (current == 50 and tempLastAmount == 50) then
+		if not IsShiftKeyDown() then
+			-- Allow overriding of mailopening with the shift key
+			
+			-- Open the current mail
+			self:ScheduleOpen(false);
+		end
+	end
+	
+	tempLastAmount = current;
+end
+
+function MailOpener:ScheduleOpen(continued)
+	if lastAmount > 0 then
+		local waitTime;
+		if continued then
+			waitTime = self.db.profile.general.waitTime;
+		else
+			-- Even though this is not a continuation and should be instant, we set a .5 second timer to prevent multiple calls of the OpenNow function
+			waitTime = self.db.profile.general.initialDelay;
+		end
+		
+		-- Stop previous timer
+		self:CancelTimer(self.tmrOpenNow, true);
+		-- Schedule the next open
+		self.tmrOpenNow = self:ScheduleTimer("OpenNow", waitTime);
+	end
+end
+
+function MailOpener:OpenNow()
+	self:Debug("OpenNow (" .. ((opening and "1") or "0") .. ")");
+	if not opening and MailFrame:IsVisible() then
+		self:Debug("OpenNow");
+			
+		-- BeanCounter is the only addon hiding the mail close button while busy, so we can look for that
+		local BeanCounterActive = not InboxCloseButton:IsVisible();
+		
+		if not BeanCounterActive then
+			-- BeanCounter is INACTIVE
+			
+			self:CancelTimer(self.tmrTryAgain, true); -- Insurance
+			
+			if QuickAuctionsAutoMail then
+				-- Remember the last known quick auctions status
+				lastQuickAuctionsStatus = QuickAuctionsAutoMail:GetChecked();
+			end
+			if self.db.profile.general.autoDisableQAAutoMail and self.QuickAuctionsEnabled and QuickAuctionsAutoMail and QuickAuctionsAutoMail:GetChecked() then
+				-- If auto disable "QA Auto mail" is enabled and QA's auto mail is currently toggled on, turn it off
+				-- We need to do this with a :click to trigger the right events
+				
+				self:Debug("Turning automail |cffff0000off|r.");
+				
+				QuickAuctionsAutoMail:Click();
+			end
+			
+			opening = true;
+			
+			self:Debug("MO_OPEN_MAIL");
+			
+			-- Summon the mail opening gods
+			self:SendMessage("MO_OPEN_MAIL");
+		else
+			-- BeanCounter is ACTIVE
+			self:Debug("BeanCounter active, waiting .5 seconds...");
+			
+			self:CancelTimer(self.tmrTryAgain, true); -- Insurance
+			-- Wait with summoning until BeanCounter is done, try again every 0.5 seconds
+			self.tmrTryAgain = self:ScheduleTimer("OpenNow", 0.5);
+		end
+	end
+end
+
+function MailOpener:MO_OPEN_COMPLETE()
+	opening = false;
+		
+	local current, total = GetInboxNumItems();
+	
+	if (total - current) == 0 then
+		-- Play the sound
+		if self.db.profile.notifications.mailboxEmptySound and (not MailOpener.db.profile.notifications.mailboxEmptySoundOnlyOnce or not mailboxEmptySoundPlayed) then
+			PlaySoundFile(self.db.profile.notifications.mailboxEmptySoundFile);
+			mailboxEmptySoundPlayed = true;
+		end
+	end
+	
+	if self.db.profile.general.autoReenableQAAutoMail and self.QuickAuctionsEnabled and QuickAuctionsAutoMail and not QuickAuctionsAutoMail:GetChecked() then
+		-- If auto re-enable "QA Auto mail" is enabled and QA's auto mail is currently toggled OFF, turn it on
+		-- We need to do this with a :click to trigger the right events
+		
+		self:Debug("Turning automail |cff00ff00on|r.");
+		
+		QuickAuctionsAutoMail:Click();
+	elseif self.db.profile.general.autoSetBackQAAutoMail and self.QuickAuctionsEnabled and QuickAuctionsAutoMail and lastQuickAuctionsStatus ~= QuickAuctionsAutoMail:GetChecked() then
+		-- If auto set back "QA Auto mail" is enabled and QA's auto mail is currently not the same as it was before starting, toggle it
+		-- We need to do this with a :click to trigger the right events
+		
+		if lastQuickAuctionsStatus then
+			self:Debug("Turning automail |cff00ff00on|r.");
+		else
+			self:Debug("Turning automail |cffff0000off|r.");
+		end
+			
+		QuickAuctionsAutoMail:Click();
+	end
+	
+	if self.db.profile.general.continueOpening then
+		self:ScheduleOpen(true);
+	end
+end
+
+-- Run another CheckInbox
+function MailOpener:Recheck()
+	self:Debug("|cffffff00Recheck|r");
+	
+	-- Freshlist prevents this from being run too often
+	-- It is set to true after a server sync
+	-- and set to false 61 seconds afterwards with a recheck called instantly after it
+	if not freshList and MailFrame:IsVisible() then
+		self:Debug("|cff00ff00Recheck|r");
+		
+		-- If this isn't a fresh list (so messages weren't received within the last 60 seconds) and the mailbox wasn't closed
+	
+		-- BeanCounter is the only addon hiding the mail close button while busy, so we can look for that
+		local BeanCounterActive = not InboxCloseButton:IsVisible();
+		
+		if not BeanCounterActive then
+			-- Query the server
+			CheckInbox();
+		end
+		
+		-- Stop previous timer
+		self:CancelTimer(self.tmrRecheck, true);
+		-- Keep trying until it works
+		self.tmrRecheck = self:ScheduleTimer("Recheck", 2);
+		
+		self:Debug("tmrRecheck 2");
+	end
+end
+
+-- Stop checking for new mail and unregister the events we needed
+function MailOpener:Stop()
+	if self.db.profile.notifications.bye then
+		print("|cff15ff00Mail Opener|r: Have a nice day. :)");
+	end
+	
+	opening = false;
+	
+	-- We won't need this anymore
+	self:UnregisterEvent("MAIL_CLOSED");
+	self:UnregisterEvent("PLAYER_LEAVING_WORLD");
+	self:UnregisterEvent("MAIL_INBOX_UPDATE");
+	
+	-- Messages
+	self:UnregisterMessage("MO_OPEN_COMPLETE");
+	
+	-- Timers
+	self:CancelTimer(self.tmrTryAgain, true);
+	self:CancelTimer(self.tmrOpenNow, true);
+	
+	-- If we wait with disabling QA automail until MAIL_SHOW, QA will beat us to it and already start sending stuff
+	self:ToggleQAStatus();
+end
+
+function MailOpener:Debug(t)
+	if not self.debugChannel and self.debugChannel ~= false then
+		-- We want to check just once, so if you add a debug channel later just do a /reload (registering an event for this is wasted resources)
+		self.debugChannel = false;
+		
+		for i = 1, NUM_CHAT_WINDOWS do
+			local name = GetChatWindowInfo(i);
+			
+			if name:upper() == "DEBUG" then
+				self.debugChannel = _G["ChatFrame" .. i];
+			end
+		end
+	end
+	
+	if self.debugChannel then
+		self.debugChannel:AddMessage(t);
+	end
+end
+
+-- Enable our config module if it's disabled and make a reference to it
+function MailOpener:EnableConfigModule()
+	if not MailOpenerConfig then
+		MailOpenerConfig = self:GetModule("Config");
+		MailOpenerConfig:Enable();
+	end
+end
+
+-- Toggle Postal's opening modules on or off
+function MailOpener:TogglePostalModule(name, status)
+	if MailOpener.PostalEnabled and Postal then
+		-- Postal must be enabled
+		
+		-- Remember the setting in Postal
+		Postal.db.profile.ModuleEnabledState[name] = status;
+		
+		-- Toggle module
+		if status then
+			Postal:GetModule(name):Enable();
+		else
+			Postal:GetModule(name):Disable();
+		end
+	end
+end
+
+-- Change Quick Auction's auto mail status based on our prefered settings
+function MailOpener:ToggleQAStatus()
+	self:Debug("defaultQAStatus:" .. self.db.profile.general.defaultQAStatus);
+	
+	if self.QuickAuctionsEnabled and self.db.profile.general.defaultQAStatus ~= "__remember" and QuickAuctionsAutoMail then
+		if self.db.profile.general.defaultQAStatus == "_enabled" and not QuickAuctionsAutoMail:GetChecked() then
+			self:Debug("Turning automail |cff00ff00on|r.");
+			
+			QuickAuctionsAutoMail:Click();
+		elseif self.db.profile.general.defaultQAStatus == "disabled" and QuickAuctionsAutoMail:GetChecked() then
+			self:Debug("Turning automail |cffff0000off|r.");
+			
+			QuickAuctionsAutoMail:Click();
+		end
+	end
+end
+
+function MailOpener:FormatMoney(copper)
+	local gold = floor( copper / 10000 );
+	local silver = floor( ( copper - ( gold * 10000 ) ) / 100 );
+	local copper = mod(copper, 100);
+	
+	if gold > 0 then
+		return format(GOLD_AMOUNT_TEXTURE .. " " .. SILVER_AMOUNT_TEXTURE .. " " .. COPPER_AMOUNT_TEXTURE, gold, 0, 0, silver, 0, 0, copper, 0, 0);
+	elseif silver > 0 then
+		return format(SILVER_AMOUNT_TEXTURE .. " " .. COPPER_AMOUNT_TEXTURE, silver, 0, 0, copper, 0, 0);
+	else
+		return format(COPPER_AMOUNT_TEXTURE, copper, 0, 0);
+	end
+end
+
+StaticPopupDialogs["MailOpenerCopyWindow"] = {
+	text = "Please CTRL-C to copy.",
+	button2 = CLOSE,
+	hasEditBox = 1,
+	hasWideEditBox = 1,
+	OnShow = function()
+		local editBox = _G[this:GetName().."WideEditBox"];
+		if editBox and MailOpener.currentPopupContents then
+			editBox:SetText(MailOpener.currentPopupContents);
+			editBox:SetFocus();
+			editBox:HighlightText(0);
+		end
+		
+		-- Position the close button in the middle
+		local button = _G[this:GetName().."Button2"];
+		if button then
+			-- Remove previous know position
+			button:ClearAllPoints();
+			button:SetWidth(200);
+			-- Reposition in the center
+			button:SetPoint("CENTER", editBox, "CENTER", 0, -30);
+		end
+	end,
+	EditBoxOnEscapePressed = function()
+		this:GetParent():Hide();
+	end,
+	timeout = 0,
+	whileDead = 1,
+	hideOnEscape = 1,
+	maxLetters = 1024,
+}
+
+function MailOpener:ShowBetaPopup()
+	function TableDump(key, val, jumps)
+		local cache = "";
+		
+		if not jumps then
+			jumps = 0;
+		end
+		
+		local spacer = "";
+		if jumps > 0 then
+			for i = 1, jumps do
+				spacer = spacer .. "    ";
+			end
+		end
+		
+		if type(val) == "table" then
+			cache = cache .. spacer .. key .. " = {\n";
+			foreach(val, function(k, v)
+				cache = cache .. TableDump(k, v, (jumps + 1));
+			end);
+			cache = cache .. spacer .. "},\n";
+		else
+			cache = cache .. spacer .. key .. " = " .. tostring(val) .. ",\n";
+		end
+		
+		return cache;
+	end
+	
+	local cache = "";
+	foreach(MailOpener.db.profile, function(k, v)
+		cache = cache .. TableDump(k, v, 0);
+	end);
+	
+	local AceGUI = LibStub("AceGUI-3.0");
+	local frame = AceGUI:Create("Frame");
+	frame:SetTitle("Mail Opener ALPHA");
+	frame:SetWidth(575);
+	frame:SetHeight(375);
+	
+	-- Add a normal description label
+	local desc = AceGUI:Create("Label");
+	desc:SetText("|cff00ff00After you have been using Mail Opener for a while and configured it just as you want it to be, please report your favorite settings by copying the text below at either of the below links. Thanks in advance!|r\n\n");
+	desc:SetFont(GameFontHighlightSmall:GetFont(), 13);
+	desc:SetFullWidth(true);
+	frame:AddChild(desc);
+	
+	-- Add a MultiLineEditBox
+	local settingsMLEEB = AceGUI:Create("MultiLineEditBox");
+	settingsMLEEB:SetText(cache);
+	settingsMLEEB:SetLabel("Hit CTRL-A to select all and CTRL-C to copy the text. You can then use CTRL-V to paste.");
+	settingsMLEEB:SetFullWidth(true);
+	settingsMLEEB:SetNumLines(8);
+	settingsMLEEB:DisableButton(true);
+	settingsMLEEB:SetCallback("OnTextChanged", function()
+		settingsMLEEB:SetText(cache);
+	end);
+	frame:AddChild(settingsMLEEB);
+	
+	-- Empty line between the two links
+	local label = AceGUI:Create("Label");
+	label:SetText("Please post the above text at either of these two links:");
+	label:SetFullWidth(true);
+	frame:AddChild(label);
+	
+	local desc1 = AceGUI:Create("InteractiveLabel");
+	desc1:SetText("|cff00bbbb[http://wow.curseforge.com/addons/mailopener/create-ticket/]|r");
+	desc1:SetFont(GameFontHighlightSmall:GetFont(), 13);
+	desc1:SetFullWidth(true);
+	desc1:SetCallback("OnClick", function()
+		MailOpener.currentPopupContents = "http://wow.curseforge.com/addons/mailopener/create-ticket/";
+		
+		StaticPopup_Show("MailOpenerCopyWindow");
+	end);
+	desc1:SetCallback("OnEnter", function()
+		frame:SetStatusText("Click to copy this URL.");
+	end);
+	desc1:SetCallback("OnLeave", function()
+		frame:SetStatusText("");
+	end);
+	frame:AddChild(desc1);
+	
+	-- Empty line between the two links
+	local spacer = AceGUI:Create("Label");
+	spacer:SetText(" ");
+	frame:AddChild(spacer);
+	
+	local desc2 = AceGUI:Create("InteractiveLabel");
+	desc2:SetText("|cff00bbbb[http://20kleveling.com/JMTCforum/posting.php?mode=reply&f=9&t=1403]|r");
+	desc2:SetFont(GameFontHighlightSmall:GetFont(), 13);
+	desc2:SetFullWidth(true);
+	desc2:SetCallback("OnClick", function()
+		MailOpener.currentPopupContents = "http://20kleveling.com/JMTCforum/posting.php?mode=reply&f=9&t=1403";
+		
+		StaticPopup_Show("MailOpenerCopyWindow");
+	end);
+	desc2:SetCallback("OnEnter", function()
+		frame:SetStatusText("Click to copy this URL.");
+	end);
+	desc2:SetCallback("OnLeave", function()
+		frame:SetStatusText("");
+	end);
+	frame:AddChild(desc2);
+	
+	-- Empty line between the two links
+	local label = AceGUI:Create("Label");
+	label:SetText("\n\nps. You can always view this window again at a later time by clicking the \"Config\" button in the mail frame.\nps2. The information above is completely Mail Opener related. It will be used to determine the best default settings.");
+	label:SetFullWidth(true);
+	frame:AddChild(label);
+end
\ No newline at end of file