vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--------------------------------------------------------------------------
-- ImprovedErrorFrame.lua 
--------------------------------------------------------------------------
--[[

Original ImprovedErrorFrame - Vjeux
ImprovedErrorFrame without FrameXML - AnduinLothar

ImprovedErrorFrame v2 - Sinaloit
        - Now adds a minimap button when errors are present, no more windows
          popping up every time you get an error. Click the button to view
          the errors.
Icons provided by Moonfire

v2.0
- Restructured code
- Error messages now reveal an error button rather than a popup on occurance
  clicking on button shows frame with error messages
- Error button flashes when shown, hidden if no bugs
- Error button is mobile, orbits the Minimap
        Shift-Left Click to drag, Shift-Right Click to reset

v2.1
- Added Report button back, only shows up if ImprovedErrorFrame.displayReportButton = true
  Set this value if you want to be able to have people report errors
- Added ImprovedErrorFrame_Report_OnClick() to be hooked by any AddOn that wants to know
  when the Report button was clicked, passes ImprovedErrorFrame.errorMessageList
- Added slash command (/ief) to allow user to choose frame or button appearing on error


v2.2
- Added IMPROVEDERRORFRAME_REV variable
- AddOn names/files are now stored in the errorMessageList
- Added ability to turn off blinking on notification icon
- Changed blinking to simply turning off/on highlight
- Added localization strings
- Streamlined the code a little
- Uses Sky for slashCommand registration if present else default method

v2.3
- Added Khoas/Cosmos Registration if present
- Added tooltip to ErrorButton
- Added option to display count of errors
- Added option to always have ErrorButton present (button is disabled if no messages)
- Added sound when 1st error notification occurs
- Added option to disable sound

v2.4
- Fixed Cosmos Registration
- Added line and parsedErr to errorList
- Fixed some state errors with toggles
- Khaos Registration now working correctly

v2.5
- Fixed Always show to always show, even after camping when not using Cosmos/Khaos
- Removed extraneous calls to ImprovedErrorFrame.change<blah> in Khaos commands
- changeBlink/Count functions now are aware of button being disabled

v2.6
- Fixed file pattern match to work on files with more than 1 period
- Renamed ping.mp3 to ErrorSound.mp3 for more clarity
- Fixed string.find in IEFSetOptions to work with 1 word commands

v2.7
- Changed Bug Count to Red
- Fixed error sound for each error if minimap was open.
- Instead of rescheduling IEFNotify every time checks if present 1st
- Always shown button now enables properly when error occurs

v2.8
- Added depedencies to Khaos Registration
- Changed Report button to hide IEFF before calling OnClick, now hook order doesn't matter
- Added a header to the IEFF so that its more obvious what it is
- Resolved issue with multiple sounds from getting same error repeatedly as only error
- Rechecked code and made compliant with new errorButtonActive setting

v2.81
- Fixed issue with error text overlapping header.

v2.82
- German localization added Thanks to StarDust

v2.9
- Added option for an empty button during flashing for easier count reading.

v2.95
- French Localization added thanks to Sasmira
- Khaos registration changed slightly, no more queue choice, unchecking IEF does this now.
- convertRev now translates tables of revisions or passed strings.

v2.97
- Fixed default value error for Cosmos Registration for Empty
- Added XMLDebug, allows you to enable verbose FrameXML.log

$Id: ImprovedErrorFrame.lua 2121 2005-07-12 14:20:21Z Sinaloit $
$Rev: 2121 $
$LastChangedBy: Sinaloit $
$Date: 2005-07-13 00:20:21 +1000 (Wed, 13 Jul 2005) $
]]--

-- Revision tag
IMPROVEDERRORFRAME_REV = "$Rev: 2121 $";

IEF_TEST_FLAG = nil;
IEF_TEST_FLAG2 = nil;
-- ImprovedErrorFrame Defines
local IEF_ERROR_MESSAGE_PAGE_MAX = 10;
local IEF_ERROR_MESSAGE_MAX = 999;
local IEF_ERROR_MESSAGE_INFINITE = 20;
local IEF_BLINK_DELAY  = 2;
IEF_MSG_NEW      = 0; -- Message added, not scheduled to be shown yet
IEF_MSG_SHOWN    = 1; -- Message scheduled to be seen by user
IEF_MSG_VIEWED   = 2; -- Message was viewed by user

ImprovedErrorSettings = {
        -- Show error when it occurs
        displayOnError = false;
        -- To Blink or not to Blink
        blinkNotification = true;
        -- Display count of errors
        displayCount = true;
        -- Display even when no errors pending
        alwaysShow = false;
        -- Prevent sound from playing when error occurs
        gagNoise = false;
        -- Empty out the icon when blinking (allows numbers to be seen easier)
        emptyButton = false;
        -- Verbose XML errror logging
        XMLDebug = false;
};

ImprovedErrorFrame = {
        -- Current Error Message
        messagePrint = "";

        --[[
        --      List of all current Errors, both viewed and unviewed
        --
        --      Table Structure:
        --              .err            = error message
        --              .count          = number of occurances
        --              .status         = IEF_MSG_NEW or IEF_MSG_SHOWN or IEF_MSG_VIEWED
        --              .AddOn          = name of addon that generated the error
        --              .fileName       = file name error occured in
        --              .line           = line number error occured on
        --              .parsedErr      = Just the error message no file/line number
        --              .errDate        = date/time error occured
        --              .reported       = error has been reported
        --]]
        errorMessageList = { };
        -- Display the report button, set by some other AddOn
        displayReportButton = false;
        -- Indicates if errorButton is active
        errorButtonActive = false;

        -- Previous function handlers
        oldFuncs = {
                oldERRORMESSAGE = _ERRORMESSAGE;
                oldMessage = message;
        };

        -- Error reporting function, this loads before Sea so we have to have our own.
        Print = function(msg, r, g, b, frame)
                if (not r) then r = 1.0; end
                if (not g) then g = 1.0; end
                if (not b) then b = 1.0; end
                if (frame) then
                        frame:AddMessage(msg, r, g, b);
                else
                        if ( DEFAULT_CHAT_FRAME ) then
                                DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b);
                        end
                end
        end;

        -- Replaces old error handling functions and adds the Frame to the UI Panel list
        enable = function()
                _ERRORMESSAGE = ImprovedErrorFrame.newErrorMessage;
                message = ImprovedErrorFrame.newErrorMessage;
                UIPanelWindows["ImprovedErrorFrameFrame"] = { area = "center", pushable = 0 }; -- Allows the frame to be closed by Escape
        end;

        -- Returns error handling functions to original and removes Frame from UI Panel List
        disable = function()
                _ERRORMESSAGE = ImprovedErrorFrame.oldFuncs.oldERRORMESSAGE;
                message = ImprovedErrorFrame.oldFuncs.oldMessage;
                UIPanelWindows["ImprovedErrorFrameFrame"] = nil;
        end;    

        -- Slash command handler
        IEFSetOptions = function(msg)
                msg = string.lower(msg);
                local change = false;
                local _, _, option, setting = string.find(msg, "(%w+) *(%w*)");
                if (option == IEF_NOTIFY_OPT) then
                        if (setting == IEF_ON) then
                                ImprovedErrorSettings.displayOnError = false;
                        elseif (setting == IEF_OFF) then
                                ImprovedErrorSettings.displayOnError = true;
                        else
                                ImprovedErrorSettings.displayOnError = not ImprovedErrorSettings.displayOnError;
                        end
                        if (ImprovedErrorSettings.displayOnError) then
                                ImprovedErrorFrame.Print(IEF_NOTIFY_OFF);
                        else
                                ImprovedErrorFrame.Print(IEF_NOTIFY_ON);
                        end
                        change = true;
                elseif (Chronos and (option == IEF_BLINK_OPT)) then
                        if (setting == IEF_ON) then
                                ImprovedErrorSettings.blinkNotification = true;
                        elseif (setting == IEF_OFF) then
                                ImprovedErrorSettings.blinkNotification = false;
                        else
                                ImprovedErrorSettings.blinkNotification = not ImprovedErrorSettings.blinkNotification;
                        end
                        if (ImprovedErrorSettings.blinkNotification) then
                                ImprovedErrorFrame.Print(IEF_BLINK_ON);
                        else
                                ImprovedErrorFrame.Print(IEF_BLINK_OFF);
                        end
                        ImprovedErrorFrame.changeBlink();
                        change = true;
                elseif (option == IEF_COUNT_OPT) then
                        if (setting == IEF_ON) then
                                ImprovedErrorSettings.displayCount = true;
                        elseif (setting == IEF_OFF) then
                                ImprovedErrorSettings.displayCount = false;
                        else
                                ImprovedErrorSettings.displayCount = not ImprovedErrorSettings.displayCount;
                        end
                        if (ImprovedErrorSettings.displayCount) then
                                ImprovedErrorFrame.Print(IEF_COUNT_ON);
                        else
                                ImprovedErrorFrame.Print(IEF_COUNT_OFF);
                        end
                        ImprovedErrorFrame.changeCount();
                        change = true;
                elseif (option == IEF_ALWAYS_OPT) then
                        if (setting == IEF_ON) then
                                ImprovedErrorSettings.alwaysShow = true;
                        elseif (setting == IEF_OFF) then
                                ImprovedErrorSettings.alwaysShow = false;
                        else
                                ImprovedErrorSettings.alwaysShow = not ImprovedErrorSettings.alwaysShow;
                        end
                        if (ImprovedErrorSettings.alwaysShow) then
                                ImprovedErrorFrame.Print(IEF_ALWAYS_ON);
                        else
                                ImprovedErrorFrame.Print(IEF_ALWAYS_OFF);
                        end
                        ImprovedErrorFrame.changeAlways();
                        change = true;
                elseif (option == IEF_SOUND_OPT) then
                        if (setting == IEF_ON) then
                                ImprovedErrorSettings.gagNoise = false;
                        elseif (setting == IEF_OFF) then
                                ImprovedErrorSettings.gagNoise = true;
                        else
                                ImprovedErrorSettings.gagNoise = not ImprovedErrorSettings.gagNoise;
                        end
                        if (ImprovedErrorSettings.gagNoise) then
                                ImprovedErrorFrame.Print(IEF_SOUND_OFF);
                        else
                                ImprovedErrorFrame.Print(IEF_SOUND_ON);
                        end
                        change = true;
                elseif (Chronos and option == IEF_EMPTY_OPT) then
                        if (setting == IEF_ON) then
                                ImprovedErrorSettings.emptyButton = true;
                        elseif (setting == IEF_OFF) then
                                ImprovedErrorSettings.emptyButton = false;
                        else
                                ImprovedErrorSettings.emptyButton = not ImprovedErrorSettings.emptyButton;
                        end
                        if (ImprovedErrorSettings.emptyButton) then
                                ImprovedErrorFrame.Print(IEF_EMPTY_ON);
                        else
                                ImprovedErrorFrame.Print(IEF_EMPTY_OFF);
                        end
                        change = true;
                elseif (option == IEF_DEBUG_OPT) then
                        if (setting == IEF_ON) then
                                ImprovedErrorSettings.XMLDebug = 1;
                        elseif (setting == IEF_OFF) then
                                ImprovedErrorSettings.XMLDebug = 0;
                        else
                                if (ImprovedErrorSettings.XMLDebug == 1) then
                                        ImprovedErrorSettings.XMLDebug = 0;
                                else
                                        ImprovedErrorSettings.XMLDebug = 1;
                                end
                        end
                        SetCVar("XMLDebug", ImprovedErrorSettings.XMLDebug);
                        if (ImprovedErrorSettings.XMLDebug == 1) then
                                ImprovedErrorFrame.Print(IEF_DEBUG_ON);
                        else
                                ImprovedErrorFrame.Print(IEF_DEBUG_OFF);
                        end
                        change = true;
                end
                if (change) then
                        ImprovedErrorFrame.syncCosmosToVars();
                        return;
                end
                ImprovedErrorFrame.displayOptions();
        end;

        -- Starts/stops blinking if needed based on blinkNotification value
        changeBlink = function(msg)
                if (ImprovedErrorSettings.blinkNotification and IEFMinimapButton:IsVisible()) then
                        if (ImprovedErrorFrame.errorButtonActive) then
                                if (not Chronos.isScheduledByName("IEFNotify")) then
                                        Chronos.scheduleByName("IEFNotify", IEF_BLINK_DELAY, ImprovedErrorFrame.buttonFlash, true);
                                end
                        end
                else
                        Chronos.unscheduleByName("IEFNotify");
                        IEFMinimapButton:UnlockHighlight();
                        if (ImprovedErrorSettings.emptyButton) then
                                IEFMinimapButton:SetNormalTexture("Interface\\AddOns\\ImprovedErrorFrame\\Skin\\ErrorButton-Up");
                        end
                end
        end;

        -- Shows number on the button if it should be based on displayCount value
        changeCount = function(msg)
                if (ImprovedErrorSettings.displayCount and IEFMinimapButton:IsVisible()) then
                        if (ImprovedErrorFrame.errorButtonActive) then
                                IEFMinimapButton:SetText(ImprovedErrorFrame.countErrors());
                        end
                else
                        IEFMinimapButton:SetText("");
                end
        end;

        -- Makes appropriate changes based on the alwaysShow value
        changeAlways = function(msg)
                if (ImprovedErrorSettings.alwaysShow) then
                        if (not IEFMinimapButton:IsVisible()) then
                                IEFMinimapButton:Show();
                                IEFMinimapButton:Disable();
                        end
                else
                        if (IEFMinimapButton:IsVisible() and not ImprovedErrorFrame.errorButtonActive) then
                                IEFMinimapButton:Enable();
                                IEFMinimapButton:Hide();
                        end
                end
        end;

        changeEmpty = function(msg)
                if (not ImprovedErrorSettings.emptyButton) then
                        IEFMinimapButton:SetNormalTexture("Interface\\AddOns\\ImprovedErrorFrame\\Skin\\ErrorButton-Up");
                end
        end;

        -- Print Format String and current settings
        displayOptions = function()
                if (Chronos) then
                        ImprovedErrorFrame.Print(IEF_FORMAT_STR);
                else
                        ImprovedErrorFrame.Print(IEF_FORMAT_STR_NOCHRON);
                end
                ImprovedErrorFrame.Print(IEF_CURRENT_SETTINGS);
                if (ImprovedErrorSettings.displayOnError) then
                        ImprovedErrorFrame.Print("    "..IEF_NOTIFY_OFF);
                else
                        ImprovedErrorFrame.Print("    "..IEF_NOTIFY_ON);
                end
                if (Chronos) then
                        if (ImprovedErrorSettings.blinkNotification) then
                                ImprovedErrorFrame.Print("    "..IEF_BLINK_ON);
                        else
                                ImprovedErrorFrame.Print("    "..IEF_BLINK_OFF);
                        end
                        if (ImprovedErrorSettings.emptyButton) then
                                ImprovedErrorFrame.Print("    "..IEF_EMPTY_ON);
                        else
                                ImprovedErrorFrame.Print("    "..IEF_EMPTY_OFF);
                        end
                end
                if (ImprovedErrorSettings.displayCount) then
                        ImprovedErrorFrame.Print("    "..IEF_COUNT_ON);
                else
                        ImprovedErrorFrame.Print("    "..IEF_COUNT_OFF);
                end
                if (ImprovedErrorSettings.alwaysShow) then
                        ImprovedErrorFrame.Print("    "..IEF_ALWAYS_ON);
                else
                        ImprovedErrorFrame.Print("    "..IEF_ALWAYS_OFF);
                end
                if (ImprovedErrorSettings.gagNoise) then
                        ImprovedErrorFrame.Print("    "..IEF_SOUND_OFF);
                else
                        ImprovedErrorFrame.Print("    "..IEF_SOUND_ON);
                end
                if (ImprovedErrorSettings.XMLDebug) then
                        ImprovedErrorFrame.Print("    "..IEF_DEBUG_ON);
                else
                        ImprovedErrorFrame.Print("    "..IEF_DEBUG_OFF);
                end
        end;

        -- Ran when AddOn starts
        onLoad = function()
                -- Convert Revision into a number
                convertRev("IMPROVEDERRORFRAME_REV");

                -- Load XMLDebug from CVar.
                -- (Must use CVars as regular variables aren't available until too late)
                RegisterCVar("XMLDebug", 0);
                ImprovedErrorSettings.XMLDebug = tonumber(GetCVar("XMLDebug"));

IEF_TEST_FLAG = ImprovedErrorSettings.XMLDebug;
                if (ImprovedErrorSettings.XMLDebug == 1) then
IEF_TEST_FLAG2 = true;
                        FrameXML_Debug(1);
                else
IEF_TEST_FLAG2 = false;
                        FrameXML_Debug(0);
                end

                -- Perform onLoad tasks
                ImprovedErrorFrame.enable();
                this:RegisterEvent("VARIABLES_LOADED");
        end;

        -- Event handler function
        onEvent = function(event)
                if (event == "VARIABLES_LOADED") then
                        if (Khaos) then
                                ImprovedErrorFrame.KhaosRegister();
                        else
                                if (Cosmos_RegisterConfiguration) then
                                        ImprovedErrorFrame.CosmosRegister();
                                end
                                if (Sky) then
                                        Sky.registerSlashCommand(
                                                {
                                                        id = "ImprovedErrorFrameCommand";
                                                        commands = { "/ief" };
                                                        onExecute = ImprovedErrorFrame.IEFSetOptions;
                                                        helpText = IEF_HELP_TEXT;
                                                }
                                        );
                                else
                                        SlashCmdList["IEFRAME"] = ImprovedErrorFrame.IEFSetOptions;
                                        SLASH_IEFRAME1 = "/ief";
                                end
                        end
                        if (ImprovedErrorSettings.alwaysShow) then
                                if (not IEFMinimapButton:IsVisible()) then
                                        IEFMinimapButton:Show();
                                        IEFMinimapButton:Disable();
                                end
                        end
                end
        end;

        -- Register Option set w/ Khaos
        KhaosRegister = function()
                Khaos.registerOptionSet("debug",
                        {
                                id = "ImprovedErrorFrame";
                                text = IEF_OPTION_TEXT;
                                helptext = IEF_OPTION_HELP;
                                difficulty = 1;
                                default = true;
                                callback = function(state)
                                        ImprovedErrorSettings.displayOnError = not state;
                                end;
                                options = {
                                        {
                                                id = "IEFHeader";
                                                text = IEF_HEADER_TEXT;
                                                helptext = IEF_HEADER_HELP;
                                                type = K_HEADER;
                                                difficulty = 1;
                                        };
                                        {
                                                id = "IEFBlink";
                                                text = IEF_BLINK_TEXT;
                                                helptext = IEF_BLINK_HELP;
                                                type = K_TEXT;
                                                value = true;
                                                check = true;
                                                difficulty = 1;
                                                callback = function(state)
                                                        ImprovedErrorSettings.blinkNotification = state.checked;
                                                        ImprovedErrorFrame.changeBlink();
                                                end;
                                                feedback = function(state)
                                                        if (state.checked) then
                                                                return IEF_BLINK_ON;
                                                        else
                                                                return IEF_BLINK_OFF;
                                                        end
                                                end;
                                                default = {
                                                        checked = true;
                                                };
                                                disabled = {
                                                        checked = false;
                                                };
                                        };
                                        {
                                                id = "IEFCount";
                                                text = IEF_COUNT_TEXT;
                                                helptext = IEF_COUNT_HELP;
                                                type = K_TEXT;
                                                value = true;
                                                check = true;
                                                difficulty = 1;
                                                callback = function(state)
                                                        ImprovedErrorSettings.displayCount = state.checked;
                                                        ImprovedErrorFrame.changeCount();
                                                end;
                                                feedback = function(state)
                                                        if (state.checked) then
                                                                return IEF_COUNT_ON;
                                                        else
                                                                return IEF_COUNT_OFF;
                                                        end
                                                end;
                                                default = {
                                                        checked = true;
                                                };
                                                disabled = {
                                                        checked = false;
                                                };
                                        };
                                        {
                                                id = "IEFAlways";
                                                text = IEF_ALWAYS_TEXT;
                                                helptext = IEF_ALWAYS_HELP;
                                                type = K_TEXT;
                                                value = true;
                                                check = true;
                                                difficulty = 1;
                                                callback = function(state)
                                                        ImprovedErrorSettings.alwaysShow = state.checked;
                                                        ImprovedErrorFrame.changeAlways();
                                                end;
                                                feedback = function(state)
                                                        if (state.checked) then
                                                                return IEF_ALWAYS_ON;
                                                        else
                                                                return IEF_ALWAYS_OFF;
                                                        end
                                                end;
                                                default = {
                                                        checked = false;
                                                };
                                                disabled = {
                                                        checked = false;
                                                };
                                        };
                                        {
                                                id = "IEFSound";
                                                text = IEF_SOUND_TEXT;
                                                helptext = IEF_SOUND_HELP;
                                                type = K_TEXT;
                                                value = true;
                                                check = true;
                                                difficulty = 1;
                                                callback = function(state)
                                                        ImprovedErrorSettings.gagNoise = not state.checked;
                                                end;
                                                feedback = function(state)
                                                        if (state.checked) then
                                                                return IEF_SOUND_ON;
                                                        else
                                                                return IEF_SOUND_OFF;
                                                        end
                                                end;
                                                default = {
                                                        checked = true;
                                                };
                                                disabled = {
                                                        checked = false;
                                                };
                                        };
                                        {
                                                id = "IEFEmpty";
                                                text = IEF_EMPTY_TEXT;
                                                helptext = IEF_EMPTY_HELP;
                                                type = K_TEXT;
                                                value = true;
                                                check = true;
                                                difficulty = 1;
                                                callback = function(state)
                                                        ImprovedErrorSettings.emptyButton = state.checked;
                                                        ImprovedErrorFrame.changeEmpty();
                                                end;
                                                feedback = function(state)
                                                        if (state.checked) then
                                                                return IEF_EMPTY_ON;
                                                        else
                                                                return IEF_EMPTY_OFF;
                                                        end
                                                end;
                                                default = {
                                                        checked = false;
                                                };
                                                disabled = {
                                                        checked = false;
                                                };
                                        };
                                        {
                                                id = "IEFDebug";
                                                text = IEF_DEBUG_TEXT;
                                                helptext = IEF_DEBUG_HELP;
                                                type = K_TEXT;
                                                value = true;
                                                check = true;
                                                difficulty = 4;
                                                callback = function(state)
                                                        ImprovedErrorSettings.XMLDebug = ImprovedErrorFrame.convertVar(state.checked);
                                                        SetCVar("XMLDebug", ImprovedErrorSettings.XMLDebug);
                                                end;
                                                feedback = function(state)
                                                        if (state.checked) then
                                                                return IEF_DEBUG_ON;
                                                        else
                                                                return IEF_DEBUG_OFF;
                                                        end
                                                end;
                                                default = {
                                                        checked = false;
                                                };
                                                disabled = {
                                                        checked = false;
                                                };
                                        };
                                };
                                commands = {
                                        {
                                                id = "ImprovedErrorFrameCommand";
                                                commands = { "/ief" };
                                                helpText = IEF_HELP_TEXT;
                                                parseTree = {
                                                        [IEF_NOTIFY_OPT] = {
                                                                [1] = {
                                                                        callback = function(msg)
                                                                                if (msg == IEF_ON) then
                                                                                        ImprovedErrorSettings.displayOnError = false;
                                                                                elseif (msg == IEF_OFF) then
                                                                                        ImprovedErrorSettings.displayOnError = true;
                                                                                else
                                                                                        ImprovedErrorSettings.displayOnError = not ImprovedErrorSettings.displayOnError;
                                                                                end
                                                                                Khaos.setSetKey("sets", "ImprovedErrorFrame", not ImprovedErrorSettings.displayOnError)
                                                                                if (ImprovedErrorSettings.displayOnError) then
                                                                                        ImprovedErrorFrame.Print(IEF_NOTIFY_OFF);
                                                                                else
                                                                                        ImprovedErrorFrame.Print(IEF_NOTIFY_ON);
                                                                                end
                                                                        end;
                                                                };
                                                        };
                                                        [IEF_BLINK_OPT] = {
                                                                [1] = {
                                                                        key = "IEFBlink";
                                                                        stringMap = {
                                                                                [IEF_ON] = { checked = true; };
                                                                                [IEF_OFF] = { checked = false; };
                                                                                ["default"] = { checked = "~IEFBlink.checked" };
                                                                        };
                                                                };
                                                                [2] = {
                                                                        callback = function(msg)
                                                                                if (ImprovedErrorSettings.blinkNotification) then
                                                                                        ImprovedErrorFrame.Print(IEF_BLINK_ON);
                                                                                else
                                                                                        ImprovedErrorFrame.Print(IEF_BLINK_OFF);
                                                                                end
                                                                        end;
                                                                };
                                                        };
                                                        [IEF_COUNT_OPT] = {
                                                                [1] = {
                                                                        key = "IEFCount";
                                                                        stringMap = {
                                                                                [IEF_ON] = { checked = true; };
                                                                                [IEF_OFF] = { checked = false; };
                                                                                ["default"] = { checked = "~IEFCount.checked" };
                                                                        };
                                                                };
                                                                [2] = {
                                                                        callback = function(msg)
                                                                                if (ImprovedErrorSettings.displayCount) then
                                                                                        ImprovedErrorFrame.Print(IEF_COUNT_ON);
                                                                                else
                                                                                        ImprovedErrorFrame.Print(IEF_COUNT_OFF);
                                                                                end
                                                                        end;
                                                                };
                                                        };
                                                        [IEF_ALWAYS_OPT] = {
                                                                [1] = {
                                                                        key = "IEFAlways";
                                                                        stringMap = {
                                                                                [IEF_ON] = { checked = true; };
                                                                                [IEF_OFF] = { checked = false; };
                                                                                ["default"] = { checked = "~IEFAlways.checked" };
                                                                        };
                                                                };
                                                                [2] = {
                                                                        callback = function(msg)
                                                                                if (ImprovedErrorSettings.alwaysShow) then
                                                                                        ImprovedErrorFrame.Print(IEF_ALWAYS_ON);
                                                                                else
                                                                                        ImprovedErrorFrame.Print(IEF_ALWAYS_OFF);
                                                                                end
                                                                        end;
                                                                };

                                                        };
                                                        [IEF_SOUND_OPT] = {
                                                                [1] = {
                                                                        key = "IEFSound";
                                                                        stringMap = {
                                                                                [IEF_ON] = { checked = false; };
                                                                                [IEF_OFF] = { checked = true; };
                                                                                ["default"] = { checked = "~IEFSound.checked" };
                                                                        };
                                                                };
                                                                [2] = {
                                                                        callback = function(msg)
                                                                                if (ImprovedErrorSettings.gagNoise) then
                                                                                        ImprovedErrorFrame.Print(IEF_SOUND_OFF);
                                                                                else
                                                                                        ImprovedErrorFrame.Print(IEF_SOUND_ON);
                                                                                end
                                                                        end;
                                                                };
                                                        };
                                                        [IEF_EMPTY_OPT] = {
                                                                [1] = {
                                                                        key = "IEFEmpty";
                                                                        stringMap = {
                                                                                [IEF_ON] = { checked = true; };
                                                                                [IEF_OFF] = { checked = false; };
                                                                                ["default"] = { checked = "~IEFEmpty.checked" };
                                                                        };
                                                                };
                                                                [2] = {
                                                                        callback = function(msg)
                                                                                if (ImprovedErrorSettings.emptyButton) then
                                                                                        ImprovedErrorFrame.Print(IEF_EMPTY_ON);
                                                                                else
                                                                                        ImprovedErrorFrame.Print(IEF_EMPTY_OFF);
                                                                                end
                                                                        end;
                                                                };
                                                        };
                                                        [IEF_DEBUG_OPT] = {
                                                                [1] = {
                                                                        key = "IEFDebug";
                                                                        stringMap = {
                                                                                [IEF_ON] = { checked = true; };
                                                                                [IEF_OFF] = { checked = false; };
                                                                                ["default"] = { checked = "~IEFDebug.checked" };
                                                                        };
                                                                };
                                                                [2] = {
                                                                        callback = function(msg)
                                                                                if (ImprovedErrorSettings.XMLDebug == 1) then
                                                                                        ImprovedErrorFrame.Print(IEF_DEBUG_ON);
                                                                                else
                                                                                        ImprovedErrorFrame.Print(IEF_DEBUG_OFF);
                                                                                end
                                                                        end;
                                                                };
                                                        };
                                                        ["default"] = {
                                                                callback = function(msg)
                                                                        ImprovedErrorFrame.displayOptions();
                                                                end;
                                                        };
                                                };
                                        };
                                };
                        }
                );
        end;

        -- Register everything with Cosmos
        CosmosRegister = function()
                Cosmos_RegisterConfiguration(
                        "COS_IEF",
                        "SECTION",
                        IEF_OPTION_TEXT,
                        IEF_OPTION_HELP
                );
                Cosmos_RegisterConfiguration(
                        "COS_IEF_SEPARATOR",
                        "SEPARATOR",
                        IEF_HEADER_TEXT,
                        IEF_HEADER_HELP
                );
                Cosmos_RegisterConfiguration(
                        "COS_IEF_NOTIFY_OPT",
                        "CHECKBOX",
                        IEF_NOTIFY_TEXT,
                        IEF_NOTIFY_HELP,
                        function(value, checked)
                                ImprovedErrorSettings.displayOnError = (value < 1);
                        end,
                        ImprovedErrorFrame.convertVar(not ImprovedErrorSettings.displayOnError)
                );
                Cosmos_RegisterConfiguration(
                        "COS_IEF_BLINK_OPT",
                        "CHECKBOX",
                        IEF_BLINK_TEXT,
                        IEF_BLINK_HELP,
                        function(value, checked)
                                ImprovedErrorSettings.blinkNotification = (value > 0);
                                ImprovedErrorFrame.changeBlink();
                        end,
                        ImprovedErrorFrame.convertVar(ImprovedErrorSettings.blinkNotification)
                );
                Cosmos_RegisterConfiguration(
                        "COS_IEF_COUNT_OPT",
                        "CHECKBOX",
                        IEF_COUNT_TEXT,
                        IEF_COUNT_HELP,
                        function(value, checked)
                                ImprovedErrorSettings.displayCount = (value > 0);
                                ImprovedErrorFrame.changeCount();
                        end,
                        ImprovedErrorFrame.convertVar(ImprovedErrorSettings.displayCount)
                );
                Cosmos_RegisterConfiguration(
                        "COS_IEF_ALWAYS_OPT",
                        "CHECKBOX",
                        IEF_ALWAYS_TEXT,
                        IEF_ALWAYS_HELP,
                        function(value, checked)
                                ImprovedErrorSettings.alwaysShow = (value > 0);
                                ImprovedErrorFrame.changeAlways();
                        end,
                        ImprovedErrorFrame.convertVar(ImprovedErrorSettings.alwaysShow)
                );
                Cosmos_RegisterConfiguration(
                        "COS_IEF_SOUND_OPT",
                        "CHECKBOX",
                        IEF_SOUND_TEXT,
                        IEF_SOUND_HELP,
                        function(value, checked)
                                ImprovedErrorSettings.gagNoise = (value < 1);
                        end,
                        ImprovedErrorFrame.convertVar(not ImprovedErrorSettings.gagNoise)
                );
                Cosmos_RegisterConfiguration(
                        "COS_IEF_EMPTY_OPT",
                        "CHECKBOX",
                        IEF_EMPTY_TEXT,
                        IEF_EMPTY_HELP,
                        function(value, checked)
                                ImprovedErrorSettings.emptyButton = (value > 0);
                                ImprovedErrorFrame.changeEmpty();
                        end,
                        ImprovedErrorFrame.convertVar(ImprovedErrorSettings.emptyButton)
                );
                Cosmos_RegisterConfiguration(
                        "COS_IEF_DEBUG_OPT",
                        "CHECKBOX",
                        IEF_DEBUG_TEXT,
                        IEF_DEBUG_HELP,
                        function(value, checked)
                                ImprovedErrorSettings.XMLDebug = value;
                                SetCVar("XMLDebug", ImprovedErrorSettings.XMLDebug);
                        end,
                        ImprovedErrorFrame.convertVar(ImprovedErrorSettings.XMLDebug)
                );
                ImprovedErrorFrame.syncVarsToCosmos();
        end;

        -- Cosmos uses 0 & 1 not false/true so we need to convert
        convertVar = function(varVal)
                if (varVal) then
                        return 1;
                else
                        return 0;
                end
        end;

        -- Sync changed variables to Cosmos Vars
        syncCosmosToVars = function()
                if (Cosmos_RegisterConfiguration) then
                        Cosmos_UpdateValue("COS_IEF_NOTIFY_OPT", CSM_CHECKONOFF, ImprovedErrorFrame.convertVar(not ImprovedErrorSettings.displayOnError));
                        Cosmos_SetCVar("COS_IEF_NOTIFY_OPT_X", ImprovedErrorFrame.convertVar(not ImprovedErrorSettings.displayOnError));
                        Cosmos_UpdateValue("COS_IEF_BLINK_OPT", CSM_CHECKONOFF, ImprovedErrorFrame.convertVar(ImprovedErrorSettings.blinkNotification));
                        Cosmos_SetCVar("COS_IEF_BLINK_OPT_X", ImprovedErrorFrame.convertVar(ImprovedErrorSettings.blinkNotification));
                        Cosmos_UpdateValue("COS_IEF_COUNT_OPT", CSM_CHECKONOFF, ImprovedErrorFrame.convertVar(ImprovedErrorSettings.displayCount));
                        Cosmos_SetCVar("COS_IEF_COUNT_OPT_X", ImprovedErrorFrame.convertVar(ImprovedErrorSettings.displayCount));
                        Cosmos_UpdateValue("COS_IEF_ALWAYS_OPT", CSM_CHECKONOFF, ImprovedErrorFrame.convertVar(ImprovedErrorSettings.alwaysShow));
                        Cosmos_SetCVar("COS_IEF_ALWAYS_OPT_X", ImprovedErrorFrame.convertVar(ImprovedErrorSettings.alwaysShow));
                        Cosmos_UpdateValue("COS_IEF_SOUND_OPT", CSM_CHECKONOFF, ImprovedErrorFrame.convertVar(not ImprovedErrorSettings.gagNoise));
                        Cosmos_SetCVar("COS_IEF_SOUND_OPT_X", ImprovedErrorFrame.convertVar(not ImprovedErrorSettings.gagNoise));
                        Cosmos_UpdateValue("COS_IEF_EMPTY_OPT", CSM_CHECKONOFF, ImprovedErrorFrame.convertVar(ImprovedErrorSettings.emptyButton));
                        Cosmos_SetCVar("COS_IEF_EMPTY_OPT_X", ImprovedErrorFrame.convertVar(ImprovedErrorSettings.emptyButton));
                        Cosmos_UpdateValue("COS_IEF_DEBUG_OPT", CSM_CHECKONOFF, ImprovedErrorSettings.XMLDebug);
                        Cosmos_SetCVar("COS_IEF_DEBUG_OPT_X", ImprovedErrorSettings.XMLDebug);
                        if (CosmosMasterFrame:IsVisible() and (not CosmosMasterFrame_IsLoading)) then
                                CosmosMaster_DrawData();
                        end
                end
        end;

        -- Sync variables to Cosmos Vars
        syncVarsToCosmos = function()
                if (not Cosmos_RegisterConfiguration) then
                        return;
                end
                local cosVar = getglobal("COS_IEF_NOTIFY_OPT_X");
                if (cosVar) then
                        ImprovedErrorSettings.displayOnError = (cosVar < 1);
                end
                cosVar = getglobal("COS_IEF_BLINK_OPT_X");
                if (cosVar) then
                        ImprovedErrorSettings.blinkNotification = (cosVar > 0);
                end
                cosVar = getglobal("COS_IEF_COUNT_OPT_X");
                if (cosVar) then
                        ImprovedErrorSettings.displayCount = (cosVar > 0);
                end
                cosVar = getglobal("COS_IEF_ALWAYS_OPT_X");
                if (cosVar) then
                        ImprovedErrorSettings.alwaysShow = (cosVar > 0);
                end
                cosVar = getglobal("COS_IEF_SOUND_OPT_X");
                if (cosVar) then
                        ImprovedErrorSettings.gagNoise = (cosVar < 1);
                end
                cosVar = getglobal("COS_IEF_EMPTY_OPT_X");
                if (cosVar) then
                        ImprovedErrorSettings.emptyButton = (cosVar > 0);
                end
                cosVar = getglobal("COS_IEF_DEBUG_OPT_X");
                if (cosVar) then
                        ImprovedErrorSettings.XMLDebug = cosVar;
                end
        end;

        -- Flags messages as shown, also builds the ImprovedErrorFrame.messagePrint message
        populateErrors = function()
                local errorMessageList = ImprovedErrorFrame.errorMessageList;
                local shown = 0;
                ImprovedErrorFrame.messagePrint = "\n";
                for i = 1, table.getn(errorMessageList), 1 do
                        if (shown >= IEF_ERROR_MESSAGE_PAGE_MAX) then
                                break;
                        end
                        local curMes = errorMessageList[i];
                        if (curMes.status < IEF_MSG_VIEWED) then
                                curMes.status = IEF_MSG_SHOWN;
                                shown = shown + 1;

                                local _, _, file, line, error = string.find(curMes.err, "^%[string \"(.+)\"%]:([^:]+):(.+)");
                                local count = curMes.count;
                                if (file and not curMes.AddOn and not curMes.fileName) then
                                        local patternStr;
                                        if (string.sub(file, -3) == "...") then
                                                patternStr = ".+\\(.+)\\(.+%.%.%.)$";
                                        else
                                                patternStr = ".+\\(.+)\\(.+%....)$";
                                        end
                                        local _, _, AddOnName, fileName = string.find(file, patternStr);
                                        if (AddOnName and not curMes.AddOn) then
                                                curMes.AddOn = AddOnName;
                                        end
                                        if (fileName and not curMes.fileName) then
                                                curMes.fileName = fileName;
                                        end
                                        if (line and not curMes.line) then
                                                curMes.line = line;
                                        end
                                        if (error and not curMes.parsedErr) then
                                                curMes.parsedErr = error;
                                        end
                                end
                                if (curMes.fileName) then
                                        if (string.sub(curMes.fileName, -3) ~= "...") then
                                                ImprovedErrorFrame.messagePrint = ImprovedErrorFrame.messagePrint..IEF_FILE..file.."\n"..IEF_LINE..line.."\n"..IEF_COUNT..count.."\n|cFFFF0000"..IEF_ERROR..error.."|r";
                                        else
                                                ImprovedErrorFrame.messagePrint = ImprovedErrorFrame.messagePrint..IEF_STRING..file.."\n"..IEF_LINE..line.."\n"..IEF_COUNT..count.."\n|cFFFF0000"..IEF_ERROR..error.."|r";
                                        end
                                else 
                                        ImprovedErrorFrame.messagePrint = ImprovedErrorFrame.messagePrint..IEF_COUNT..count.."\n|cFFFF0000"..IEF_ERROR..curMes.err.."|r";
                                end
                                if (i ~= table.getn(errorMessageList)) then
                                        ImprovedErrorFrame.messagePrint = ImprovedErrorFrame.messagePrint.."\n--------------------------------------------------\n";
                                end
                        end
                end
        end;

        -- Called after IEFFrame is hidden, turns off button if no more errors to view. Updates count if more.
        updateStatus = function()
                local numErrors = ImprovedErrorFrame.countErrors();
                if (numErrors > 0) then
                        ImprovedErrorFrame.errorNotify(numErrors);
                else
                        IEFMinimapButton:UnlockHighlight();
                        if (ImprovedErrorSettings.emptyButton) then
                                IEFMinimapButton:SetNormalTexture("Interface\\AddOns\\ImprovedErrorFrame\\Skin\\ErrorButton-Up");
                        end
                        IEFMinimapButton:SetText("");
                        ImprovedErrorFrame.errorButtonActive = false;
                        if (ImprovedErrorSettings.alwaysShow) then
                                IEFMinimapButton:Disable();
                        else
                                IEFMinimapButton:Hide();
                        end
                        if (Chronos) then
                                Chronos.unscheduleByName("IEFNotify");
                        end
                end
        end;

        -- Reoccuring function to toggle Textures on the IEFMinimapButton
        buttonFlash = function(toggle)
                if (toggle) then
                        IEFMinimapButton:LockHighlight();
                        if (ImprovedErrorSettings.emptyButton) then
                                IEFMinimapButton:SetNormalTexture("Interface\\AddOns\\ImprovedErrorFrame\\Skin\\ErrorButton-Blank");
                        end
                else
                        IEFMinimapButton:UnlockHighlight();
                        if (ImprovedErrorSettings.emptyButton) then
                                IEFMinimapButton:SetNormalTexture("Interface\\AddOns\\ImprovedErrorFrame\\Skin\\ErrorButton-Up");
                        end
                end
                if (ImprovedErrorFrame.errorButtonActive) then
                        Chronos.scheduleByName("IEFNotify", IEF_BLINK_DELAY, ImprovedErrorFrame.buttonFlash, not toggle);
                end
        end;

        -- Counts number of errors left to be viewed, returns that number
        countErrors = function()
                local errorMessageList = ImprovedErrorFrame.errorMessageList;
                local numErrors = 0;
                for k,v in errorMessageList do
                        if (v.status < IEF_MSG_VIEWED) then
                                numErrors = numErrors + 1;
                        end
                end
                return numErrors;
        end;

        -- Show the IEFMinimap button and start the texture toggling, passed the # of unviewed errors
        errorNotify = function(numErrors)
                if (not ImprovedErrorFrame.errorButtonActive) then
                        ImprovedErrorFrame.errorButtonActive = true;
                        if (not ImprovedErrorSettings.gagNoise) then
                                PlaySoundFile("Interface\\AddOns\\ImprovedErrorFrame\\Sound\\ErrorSound.mp3");
                        end
                        if (ImprovedErrorSettings.alwaysShow) then
                                IEFMinimapButton:Enable();
                        else
                                IEFMinimapButton:Show();
                        end
                        if (ImprovedErrorSettings.blinkNotification and Chronos) then
                                if (not Chronos.isScheduledByName("IEFNotify")) then
                                        Chronos.scheduleByName("IEFNotify", IEF_BLINK_DELAY, ImprovedErrorFrame.buttonFlash, true);
                                end
                        end
                end
                if (ImprovedErrorSettings.displayCount) then
                        IEFMinimapButton:SetText(numErrors);
                end
        end;

        --[[
        --      Called after errors occur, builds error list and behaves according to invoked.
        --
        --      Arguments:
        --              invoked - called by button click?
        --                        if true show frame, otherwise just notify.
        --]]
        showErrors = function(invoked)
                local numErrors = ImprovedErrorFrame.countErrors()
                if (numErrors) then
                        if (not ImprovedErrorFrameFrame:IsVisible() and not ImprovedErrorSettings.displayOnError and not invoked) then
                                ImprovedErrorFrame.errorNotify(numErrors);
                                return;
                        end
                        ImprovedErrorFrame.populateErrors();
                        if (not ImprovedErrorFrameFrame:IsVisible()) then
                                if (ImprovedErrorFrame.displayReportButton) then
                                        ImprovedErrorFrameReportButton:Show();
                                else
                                        ImprovedErrorFrameReportButton:Hide();
                                end
                                ImprovedErrorFrameCloseButton:Show();
                                ScriptErrorsScrollFrameOne:Show();
                                ImprovedErrorFrameFrameButton:Hide();
                                if (ImprovedErrorSettings.displayOnError) then
                                        ImprovedErrorFrameFrameHeaderText:SetText(IEF_ERROR_TEXT);
                                else
                                        ImprovedErrorFrameFrameHeaderText:SetText(IEF_TITLE_TEXT);
                                end
                                ImprovedErrorFrameFrame:Show();
                        end

                        ScriptErrorsScrollFrameOneText:SetText(ImprovedErrorFrame.messagePrint);
                        ScriptErrorsScrollFrameOneText:ClearFocus();
                end
        end;

        --[[
        --      New _ERRORMESSAGE handler, increments count if error exists already. If the message is new then
        --      it is printed to the DEFAULT_CHAT_FRAME and added to the table of errors. the showErrors function
        --      is then called.
        --]]
        newErrorMessage = function(errorMessage)
                local errorMessageList = ImprovedErrorFrame.errorMessageList;
                debuginfo();
                if (not errorMessage) then return; end
                --if (table.getn(errorMessageList) >= IEF_ERROR_MESSAGE_MAX) then return; end

                local foundMes = false;
                for curNum, curMes in errorMessageList do
                        if (curMes.err == errorMessage) then
                                if (curMes.count.."" ~= IEF_INFINITE) then
                                        curMes.count = curMes.count + 1;
                                        if (curMes.count > IEF_ERROR_MESSAGE_INFINITE) then
                                                curMes.count = IEF_INFINITE;
                                        end
                                        curMes.status = IEF_MSG_NEW;
                                else
                                        if (curMes.status >= IEF_MSG_VIEWED) then
                                                return;
                                        end
                                end
                                foundMes = true;
                                break;
                        end
                end

                if (not foundMes) then
                        ImprovedErrorFrame.Print(errorMessage);
                end

                if ((not foundMes) and (table.getn(errorMessageList) < IEF_ERROR_MESSAGE_MAX)) then 
                        table.insert(errorMessageList, { err = errorMessage, count = 1, status = IEF_MSG_NEW, reported = false, errDate = date() });
                end

                --if (table.getn(errorMessageList) > 0 and ImprovedErrorFrameFrame:IsVisible()) then return; end
                ImprovedErrorFrame.showErrors(false);
        end;

        -- Button related functions that wont be hooked.
        -- Shamelessly copied from AnduinLothar with his permission
        Button = {
                onLoad = function()
                        this:RegisterEvent("VARIABLES_LOADED");
                end;
                -- Set the IEFMinimap button to whatever position it was moved to on startup.
                onEvent = function(event)
                        if (event == "VARIABLES_LOADED") then
                                if ((IEFMinimapButton_OffsetX) and (IEFMinimapButton_OffsetY)) then
                                        this:SetPoint("CENTER", "Minimap", "CENTER", IEFMinimapButton_OffsetX, IEFMinimapButton_OffsetY);
                                end
                        end
                end;
                -- Reset IEFMinimapButton to the default position.
                reset = function()
                        IEFMinimapButton:ClearAllPoints();
                        IEFMinimapButton_OffsetX = 12;
                        IEFMinimapButton_OffsetY = -80;
                        IEFMinimapButton:SetPoint("CENTER", "Minimap", "CENTER", IEFMinimapButton_OffsetX, IEFMinimapButton_OffsetY);
                end;
                -- Ensures the button travels around the minimap when dragged, not around your screen
                onUpdate = function()
                        if (this.isMoving) then
                                local mouseX, mouseY = GetCursorPosition();
                                local centerX, centerY = Minimap:GetCenter();
                                local scale = Minimap:GetScale();
                                mouseX = mouseX / scale;
                                mouseY = mouseY / scale;
                                local radius = (Minimap:GetWidth()/2) + (this:GetWidth()/3);
                                local x = math.abs(mouseX - centerX);
                                local y = math.abs(mouseY - centerY);
                                local xSign = 1;
                                local ySign = 1;
                                if not (mouseX >= centerX) then
                                        xSign = -1;
                                end
                                if not (mouseY >= centerY) then
                                        ySign = -1;
                                end
                                local angle = math.atan(x/y);
                                x = math.sin(angle)*radius;
                                y = math.cos(angle)*radius;
                                this.currentX = xSign*x;
                                this.currentY = ySign*y;
                                this:SetPoint("CENTER", "Minimap", "CENTER", this.currentX, this.currentY);
                        end
                end;
        }
}

ScriptErrors.Show = function()
        message(ScriptErrors_Message:GetText());
end

-- Converts SVN Rev tag to just a number, pass name of global variable with tag in quotes.
function convertRev(revStr)
        if (type(revStr) == "table") then
                for k,v in revStr do
                        local _, _, revNum = string.find(v, "^%$Rev: (%d+) %$");
                        if (revNum) then
                                revStr[k] = revNum;
                        end
                end
        elseif (type(revStr) == "string") then
                local _, _, revNum = string.find(getglobal(revStr), "^%$Rev: (%d+) %$");
                if (revNum) then
                        setglobal(revStr, revNum);
                end
        end
end

-- ==========================================================
-- == Hookable IEFMinimap functions
-- ==========================================================
function IEFMinimapButton_OnMouseDown()
        if (IsShiftKeyDown() and MouseIsOver(IEFMinimapButton)) then
                if ( arg1 == "RightButton" ) then
                        --wait for reset
                else
                        this.isMoving = true;
                end
        end
end

function IEFMinimapButton_OnMouseUp()
        if (this.isMoving) then
                this.isMoving = false;
                IEFMinimapButton_OffsetX = this.currentX;
                IEFMinimapButton_OffsetY = this.currentY;
        elseif (MouseIsOver(IEFMinimapButton)) then
                if (IsShiftKeyDown() and (arg1 == "RightButton")) then
                        ImprovedErrorFrame.Button.reset();
                elseif (ImprovedErrorFrame.errorButtonActive) then
                        ImprovedErrorFrame.showErrors(true);
                end
        end
end

function IEFMinimapButton_OnHide()
        this.isMoving = false;
end

-- Empty function to be hooked by error reporting AddOns
function ImprovedErrorFrame_Report_OnClick(errorList)
        --[[
        --  Hook this function if you care when the report button is clicked
        --  the table of errors is passed, see the notes at the top for the
        --  structure.
        --]]
end