BINDING_HEADER_AAL_335_BINDINGS = "AAL Tweaks / WoW 3.3.5a";

--[[ 3.3.5a vs 1.12
 ■ Версия Lua > 5.0:
   table.getn(arg) надо заменять на select("#",...)  -- не следует использовать #{...} т.к. считает длину лишь до nil элемента
   arg[i] надо заменять на select(i,...)
 ■ GetItemInfo()  Дополнительный аргумент itemMinLevel
 ■ IsCurrentCast(index, BOOKTYPE_SPELL)  Отсутствует! Есть только IsCurrentAction(slot)
 ■ Функции TargetUnit() TargetLast...() и TargetNearest...() остаются PROTECTED
   из-за несовершенства модификации WoW.exe, причём не помогает вызов через
   функцию, добавляемую в WoW-335a\Interface\FrameXML\UIParent.lua
   Однако все эти операции, включая важную TargetLastTarget() можно выполнять
   через RunMacroText(), что даже удобнее, т.к. возможностей больше
 ■ CastSpellByName(spellName, target) вторым аргументом принимает не флаг, а
   строковый идентификатор цели, что позволяет обходиться без переключений и
   восстановлений цели. Аналогично UseContainerItem() и UseInventoryItem()
 ■ IsUsableSpell(name)~=nil или GetSpellCooldown(name)~=nil позволяют проверять
   наличие способности в SpellBook, что позволяет обойтись без отслеживания
   всех заклинаний. Работают и для Frostbolt (без CD), и для Dual Wield
   (Passive) и для Tailoring (проф.интерфейс).
   ... GetItemCooldown(name) не проверяет фактическое наличие вещи в
   экипировке или в сумках. Но можно проверять через IsUsableItem()
 ■ Нет функции IsCurrentCast() - проверять Rogue Stealth, Warrior stances,
   Druid forms, Priest Shadowform надо через GetShapeshiftFormInfo()
 ■ IsSpellPassive() переименована в IsPassiveSpell() с теми же аргументами
]]


--[[ ... работает, но пока не нужно
function AAL_TempTarget(macro)
  -- NB! После вызова AAL_TempTarget() и выполнения нужных действий с целью
  -- должна в том же "блоке кода" непременно вызываться AAL_RecallTarget(),
  -- причём "лишние" вызовы последней - вполне допустимы.
  aal_lasttarget = true
  RunMacroText(macro)
end

function AAL_RecallTarget()
  if aal_lasttarget then
     aal_lasttarget = nil
     RunMacroText("/targetlasttarget")
  end
end
]]


-- EQUIPMENT SUPPORT CODE

function AAL_GetBagsFreeSpace()
  local free = 0
  for bagID = 0,4 do
  for i = 1, GetContainerNumSlots(bagID) do
    local link = GetContainerItemLink(bagID, i)
    if link == nil then free = free + 1; end
  end
  end
  return free
end

function AAL_FindInBagsByTexture(icon)
  if icon == nil then return nil end
  for bagID = 0,4 do
  for i = 1, GetContainerNumSlots(bagID) do
    local link = GetContainerItemLink(bagID, i)
    if link ~= nil then
       local _,_, itemId = string.find(link, "item:(%d+):");
       local _,_,_,_,_,class,subclass,_,eqloc,texture = GetItemInfo( itemId )
       print(texture)
       if texture == icon then
          return bagID,i,eqloc
       end
    end
  end
  end
  return nil
end

function AAL_MainHandHasWeapon()
  return GetInventoryItemID("player", INVSLOT_MAINHAND)
  --[[   В БД практически не существует вещей для INVSLOT_MAINHAND, но не класса "Weapon"
  local _,_,_,_,_,itemType = GetItemInfo(GetInventoryItemLink("player", GetInventorySlotInfo("MainHandSlot")) or "")
  print('__', itemType)
  return itemType=="Weapon"
  ]]
end

function AAL_EquippedFishingPole()
  local main,_,_,_,_,_,mainsubtype = GetItemInfo(GetInventoryItemID("player", INVSLOT_MAINHAND) or "")
  if mainsubtype ~= nil and string.sub(mainsubtype,1,12) == "Fishing Pole" then return true end
  return false
end


-- SCAN RARE NPCs

local rareNpcList = {

-- Instances
[-2] = {
"Panzor the Invincible",
"Pyromancer Loregrain",
"Verek",
"Warder Stilgiss",
"Lord Hel'nurath",
"Tsu'zee",
"Dark Iron Ambassador",
"Bannok Grimaxe",
"Burning Felguard",
"Crystal Fang",
"Ghok Bashguud",
"Spirestone Battle Lord",
"Spirestone Butcher",
"Spirestone Lord Magus",
"Cursed Centaur",
"Meshlok the Harvester",
"Ragglesnout",
"Blind Hunter",
"Earthcaller Halmgar",
"Azshir the Sleepless",
"Fallen Champion",
"Ironspine",
"Deathsworn Captain",
"Bruegal Ironknuckle",
"Hearthsinger Forresten",
"Skul",
"Stonespine",
"Veyzhak the Cannibal",
"Zekkis",
"Miner Johnson",
"Digmaster Shovelphlange",
"Goraluk Anvilcrack",
"Jed Runewatcher",
"Deviate Faerie Dragon",
"Dustwraith",
"Sandarr Dunereaver",
"Zerillis",
},

-- Kalimdor
[1] = {
"Akkrilus",
"Apothecary Falthis",
"Branch Snapper",
"Darkslayer Mordenthal",
"Eck'alom",
"Lady Vespia",
"Mist Howler",
"Mugglefin",
"Oakpaw",
"Prince Raze",
"Rorgish Jowl",
"Terrowulf Packlord",
"Ursol'lok",
"Antilos",
"Gatekeeper Rageroar",
"General Fangferror",
"Lady Sesspira",
"Magister Hawkhelm",
"Master Feardred",
"Monnos the Elder",
"Scalebeard",
"The Evalcharr",
"Varo'then's Ghost",
"Carnivous the Breaker",
"Firecaller Radison",
"Flagglemurk the Cruel",
"Lady Moongazer",
"Lady Vespira",
"Licillin",
"Lord Sinslayer",
"Shadowclaw",
"Strider Clutchmother",
"Alshirr Banebreath",
"Death Howl",
"Dessecus",
"Immolatus",
"Mongress",
"Olm the Wise",
"Ragepaw",
"The Ongar",
"Blackmoss the Fetid",
"Duskstalker",
"Fury Shelda",
"Grimmaw",
"Threggil",
"Uruson",
"Azurous",
"General Colbatann",
"Grizzle Snowpaw",
"Kashoch the Reaver",
"Lady Hederine",
"Mezzir the Howler",
"Rak'shiri",
"Captain Flat Tusk",
"Death Flayer",
"Felweaver Scornn",
"Geolord Mottle",
"Warlord Kolkanis",
"Watch Commander Zalaphil",
"Brimgore",
"Burgle Eye",
"Darkmist Widow",
"Dart",
"Drogoth the Roamer",
"Hayoc",
"Lord Angler",
"Oozeworm",
"Ripscale",
"The Rot",
"Enforcer Emilgund",
"Ghost Howl",
"Mazzranache",
"Sister Hatelash",
"Snagglespear",
"The Rake",
"Aean Swiftriver",
"Ambassador Bloodrage",
"Azzere the Skyblade",
"Brokespear",
"Brontus",
"Captain Gerogg Hammertoe",
"Digger Flameforge",
"Dishu",
"Elder Mystic Razorsnout",
"Engineer Whirleygig",
"Foreman Grills",
"Geopriest Gukk'rok",
"Gesharahan",
"Hagg Taurenbane",
"Hannah Bladeleaf",
"Heggin Stonewhisker",
"Humar the Pridelord",
"Malgin Barleybrew",
"Marcus Bel",
"Rathorian",
"Rocklance",
"Silithid Harvester",
"Sister Rathtalon",
"Sludge Beast",
"Snort the Heckler",
"Stonearm",
"Swiftmane",
"Swinegart Spearhide",
"Takk the Leaper",
"Thora Feathermoon",
"Thunderstomp",
"Achellios the Banished",
"Gibblesnik",
"Harb Foulmountain",
"Heartrazor",
"Ironeye the Invincible",
"Silithid Ravager",
"Vile Sting",
"Accursed Slitherblade",
"Crusty",
"Giggler",
"Hissperak",
"Kaskk",
"Prince Kellen",
"Antilus the Soarer",
"Arash-ethis",
"Bloodroar the Stalker",
"Diamond Head",
"Gnarl Leafbrother",
"Lady Szallah",
"Old Grizzlegut",
"Qirot",
"Snarler",
"Gretheer",
"Grubthor",
"Huricanian",
"Krellack",
"Lapress",
"Rex Ashil",
"Setis",
"Twilight Lord Everun",
"Twilight Marauder Morna",
"Twilight Prophet",
"Zora",
"Brother Ravenoak",
"Foreman Rigger",
"Nal'taszar",
"Pridewing Patriarch",
"Sentinel Amarassan",
"Sister Riven",
"Sorrow Wing",
"Taskmaster Whipfang",
"Vengeful Ancient",
"Cyclok the Mad",
"Greater Firebird",
"Haarka the Ravenous",
"Jin'Zallah the Sandbringer",
"Kregg Keelhaul",
"Murderous Blisterpaw",
"Omgorn the Lost",
"Soriid the Devourer",
"Warleader Krazzilak",
"Clutchmother Zavas",
"Gruff",
"King Mosh",
"Ravasaur Matriarch",
"Uhk'loc",
"Boahn",
"Trigore the Lasher",

"Mushgog",
"Skarr the Unbreakable",
"The Razza",

-- Draenei zones
"Fenissa the Assassin",
},

-- EasternKingdoms
[2] = {
"Araga",
"Cranky Benj",
"Gravis Slipknot",
"Jimmy the Bleeder",
"Lo'Grosh",
"Narillasanz",
"Skhowl",
"Stone Fury",
"Darbel Montrose",
"Foulbelly",
"Geomancer Flintdagger",
"Kovork",
"Molok the Crusher",
"Nimar the Slayer",
"Prince Nazjak",
"Ruul Onestone",
"Singer",
"Zalas Witherbark",
"Deathspeaker Selendre",
"Duggan Wildhammer",
"Gish the Unmoving",
"Hed'mush the Rotting",
"High General Abbendis",
"Baron Bloodbane",
"Lord Darkscythe",
"Nerubian Overseer",
"Ranger Lord Hawkspear",
"Warlord Thresh'jin",
"Zul'Brin Warpbranch",
"Big Samras",
"Creepthess",
"Lady Zephris",
"Ro'Bark",
"Scargil",
"Tamra Stormpike",
"Foreman Jerris",
"Foreman Marcrid",
"Foulmane",
"Lord Maldazzar",
"Putridius",
"Scarlet Executioner",
"Scarlet High Clerist",
"Scarlet Interrogator",
"Scarlet Judge",
"Scarlet Smith",
"The Husk",
"Grimungous",
"Ironback",
"Jalinde Summerdrake",
"Mith'rethis the Enchanter",
"Old Cliff Jumper",
"Razortalon",
"Retherokk the Berserker",
"The Reak",
"Witherheart the Stalker",
"Zul'arek Hatefowler",
"Bayne",
"Deeb",
"Farmer Solliden",
"Fellicent's Shade",
"Lost Soul",
"Muad",
"Ressan the Needler",
"Sri'skulk",
"Tormented Spirit",
"Dalaran Spellscribe",
"Gorefang",
"Krethis Shadowspinner",
"Old Vicejaw",
"Ravenclaw Regent",
"Rot Hide Bruiser",
"Snarlmane",
"Scarshield Quartermaster",
"The Behemoth",
"Bjarn",
"Edan the Howler",
"Gibblewilt",
"Great Father Arctikus",
"Hammerspine",
"Timber",
"7:XT",
"Anathemus",
"Barnabus",
"Broken Tooth",
"Rumbler",
"Shadowforge Commander",
"Siege Golem",
"War Golem",
"Zaricotl",
"Akubar the Seer",
"Clack the Reaver",
"Deatheye",
"Dreadscorn",
"Dreadwhisper",
"Grunter",
"Magronos the Unyielding",
"Mojo the Twisted",
"Ravage",
"Spiteflayer",
"Deathmaw",
"Gorgon'och",
"Gruklash",
"Hahk'Zor",
"Hematos",
"Malfunctioning Reaver",
"Terrorspark",
"Thauris Balgarr",
"Volchan",
"Morick Darkbrew",
"Boss Galgosh",
"Emogg the Crusher",
"Grizlak",
"Gosh-Haldir",
"Large Loch Crocolisk",
"Lord Condar",
"Magosh",
"Shanda the Spinner",
"Faulty War Golem",
"Highlord Mastrogonde",
"Rekk'tilac",
"Scald",
"Shleipnarr",
"Slave Master Blackheart",
"Smoldar",
"Dragonmaw Battlemaster",
"Garneg Charskull",
"Gnawbone",
"Leech Widow",
"Ma'ruk Wyrmscale",
"Mirelow",
"Razormaw Matriarch",
"Sludginn",
"Commander Felstrom",
"Fenros",
"Lord Malathrom",
"Lupos",
"Marina DeSirrus",
"Naraxis",
"Nefaru",
"The Unknown Soldier",
"Gug Fatcandle",
"Fedfennel",
"Gruff Swiftbite",
"Morgaine the Sly",
"Mother Fang",
"Narg the Taskmaster",
"Thuros Lightfingers",
"Boulderheart",
"Chatter",
"Kazon",
"Ribchaser",
"Rohh the Silent",
"Seeker Aqualon",
"Snarlflare",
"Squiddic",
"Sewer Beast",
"Gluggle",
"High Priestess Hai'watna",
"Kurmokk",
"Lord Sakrasis",
"Mosh'Ogg Butcher",
"Rippa",
"Roloch",
"Scale Belly",
"Verifonix",
"Fingat",
"Gilmorian",
"Lord Captain Wyrmak",
"Lost One Chieftain",
"Lost One Cook",
"Molt Thorn",
"Brack",
"Foe Reaper 4000",
"Leprithus",
"Master Digger",
"Sergeant Brashclaw",
"Slark",
"Vultros",
"Jade",

"Brainwashed Noble",
"Marisa du'Paige",

-- Blood Elf zones
"Eldinarcus",
"Tregla",
"Dr. Whitherlimb",
},

-- Outlands (без территорий Draenei и Blood Elves)
[3] = {
"Hemathion",
"Morcrush",
"Speaker Mar'grom",
"Fulgorge",
"Mekthorg the Wild",
"Vorakem Doomspeaker",
"Bro'Gaz the Clanless",
"Goretooth",
"Voidhunter Yar",
"Chief Engineer Lorthander",
"Ever-Core the Punisher",
"Nuramoc",
"Ambassador Jerrikar",
"Collidus the Warp-Watcher",
"Kraator",
"Crippler",
"Doomsayer Jurim",
"Okrek",
"Bog Lurker",
"Coilfang Emissary",
"Marticar",
},

-- Northrend
[4] = {
"Fumblub Gearwind",
"Icehorn",
"Old Crystalbark",
"Vern",
"Crazed Indu'le Survivor",
"Scarlet Highlord Daion",
"Tukemuth",
"Arcturis",
"Grocklar",
"Seething Hate",
"Syreian the Bonecarver",
"King Ping",
"Perobas the Bloodthirster",
"Vigdis the War Maiden",
"High Thane Jorfus",
"Hildana Deathstealer",
"Putridus the Ancient",
"Aotona",
"King Krush",
"Loque'nahak",
"Dirkee",
"Skoll",
"Time-Lost Proto Drake",
"Vyragosa",
"Gondria",
"Griegen",
"Terror Spinner",
"Zul'drak Sentinel",
}
}

function AAL_TargetRareNPC()
  --ClearTarget()
  local tarList
  if IsInInstance() then tarList = rareNpcList[-2]
  else 
     SetMapToCurrentZone();
     tarList = rareNpcList[ GetCurrentMapContinent() ]
     if tarList == nil then return end
  end

  local npc
  UIErrorsFrame:UnregisterEvent("UI_ERROR_MESSAGE")
  for i = 1, 1000 do
    npc = tarList[i]
    if npc == nil then break end
    RunMacroText("/targetexact "..npc)
    if UnitName("target") == npc --[[UnitExists("target")]] then
       table.remove(tarList, i)
       table.insert(tarList, npc)
       --DEFAULT_CHAT_FRAME:AddMessage("Your sixth sense reveals nearby presense of "..npc, 0.59,0.68,0.92)
       break
    end
  end
  UIErrorsFrame:RegisterEvent("UI_ERROR_MESSAGE")
  if npc == nil then
     UIErrorsFrame:AddMessage("Your sixth sense reveals no one",1,0,0)
  end
end


-- BUFF / DEBUFF DETECTION CODE

function AAL_IsAura(...)
  for j = 1, 100 do
    local name = UnitAura("player", j, "HELPFUL")
    if name == nil then break end
    for i = 1,select("#",...) do
      if name == select(i,...) then return j,i; end
    end
  end
  return nil
end


-- SPELLCAST CODE


function AAL_Cast(...)
  local tar = nil
  local chkRange = -100 -- не проверять по расстоянию

  for i = 1,select("#",...) do
    local name = select(i,...)

    if name == nil then -- do nothing
    elseif type(name) == "number" then chkRange = name
    elseif type(name) == "boolean" then tar = name and "player" or "target"
    else
      -- Односимвольный префикс .*-$ категории mana/rage/energy/Health, например в AAL_Cast(".20 Frostbolt")
      local prefix = string.sub(name,1,1)
      if prefix < "0" then name = string.sub(name,2); end

      -- Число перед названием действия исключает его применение если
      -- мана/ярость/энергия/жизнь меньше заданной величины
      local reqPercent
      local p1, p2 = string.find(name, "^%d+ +")
      if p1 ~= nil then
         reqPercent = tonumber(string.sub(name,p1,p2))
         name = string.sub(name, p2+1)
      end

      local function notEnoughPower(hardmin, pwt)
        local m = UnitPower("player", pwt)
        if reqPercent == nil then return m < hardmin; end
        return m < reqPercent * UnitPowerMax("player", pwt) / 100
      end

      if chkRange > 0 and not CheckInteractDistance(tar or "target", chkRange)  -- AAL_Cast(3, ...)  можно, если цель ближе 10 ярдов
         or chkRange < 0 and chkRange > -100 and CheckInteractDistance(tar or "target", -chkRange) then  -- AAL_Cast(-3, ...) можно, если цель дальше 10 ярдов
      elseif prefix == "." and notEnoughPower(5, 0) then -- mana
      elseif prefix == "*" and notEnoughPower(5, 1) then -- rage
      elseif prefix == "-" and notEnoughPower(25, 3) then -- energy
      elseif prefix == "$" and UnitHealth("player")*100 / UnitHealthMax("player") < reqPercent then -- Health

      elseif name >= "a" and name <= "z" then tar = name  -- названия целей с маленькой буквы: "pet", "targettarget" и т.п.
      elseif name >= "0" and name <= "9" then -- номер слота, например AAL_Cast("8")
        local slot = tonumber(name)
        if IsUsableAction(slot) and GetActionCooldown(slot) == 0 and (chkRange == 0 or IsActionInRange(slot, t) ~= 0) then
           UseAction(slot, tar)
           return i
        end
      elseif IsUsableSpell(name) and -- проверяет mana/rage/energy
             GetSpellCooldown(name) == 0 and
             (chkRange == 0 or IsSpellInRange(name, t) ~= 0) -- выдаёт 0 или 1 только для адекватных заклинаний и цели, nil для неадекватных
      then
        local t = tar
        if t == nil then t = UnitExists("target") and "target"  or "player" end
        if not UnitBuff(t, name) and not UnitDebuff(t, name)
        then
           CastSpellByName(name, tar)
           -- To cast spells that contains parentheses in the spell name: CastSpellByName("Faerie Fire (Feral)()"
           return i
        end
      elseif IsUsableItem(name) and GetItemCooldown(name) == 0 and (chkRange == 0 or IsItemInRange(name, t) ~= 0) then
        local _,_,_,_,_,class = GetItemInfo( name )
        if not (class=="Armor" or class=="Weapon") or IsEquippedItem(name) then
           RunMacroText("/use "..name)
           return i
        end
      end
    end
  end
  return nil
end


function AAL_UseOrCreateItem(...)
  local item
  for i = 1, select("#",...), 2 do
    item = select(i,...)
    if IsUsableItem(item) and AAL_Cast(item) then return -i/2;
    elseif AAL_Cast( select(i+1,...) ) then return i/2;
    end
  end
  UIErrorsFrame:AddMessage("Cannot create "..item,1,0,0)
  return nil
end


function AAL_CreateItems(...)
  local item
  for i = 1, select("#",...), 2 do
    item = select(i,...)
    if not IsUsableItem(item) and AAL_Cast( select(i+1,...) ) then return i/2; end
  end
  UIErrorsFrame:AddMessage("Cannot create "..item,1,0,0)
  return nil
end


function AAL_CastHealRank(tar, needHP, ...)
  local name
  local rank
  local n = 0
  for i = 1, select("#",...) do
    local argv = select(i,...)
    if type(argv) == "string" then name = argv; n = n+1; rank = 0
    else
       rank = rank + 1
       -- нулевое значение порога означает: пропустить этот rank
       -- if argv < 0 and needHP <= -argv and AAL_Cast(tar, name) then return n, rank; -- отрицательное значение порога означает: применить максимальный доступный rank
       if argv > 0 and needHP <= argv and AAL_Cast(tar, name.."(Rank "..tostring(rank)..")") then return n, rank;
       end
    end
  end
  return nil
end



function AAL_PetCast(...)
  for k = 1,select("#",...) do
    local name = select(k,...)
    local iFound

    for i = 1, 5000 do
      local spell, rank = GetSpellName(i, BOOKTYPE_PET)
      if spell == nil then break end

      if iFound ~= nil and spell ~= name then
         -- Предполагается, что rank'и идут подряд и последний по порядку будет самым высоким
         break
      end
      if not IsPassiveSpell(i, BOOKTYPE_PET) then
         local ranked
         if rank and rank ~= "" then ranked = spell.."("..rank..")" end

         if (ranked == nil and name == spell) or name == ranked then
            iFound = i
            break
         end
         if name == spell then iFound = i; end
      end
    end

    if iFound ~= nil then
       local _, duration = GetSpellCooldown(iFound, BOOKTYPE_PET)
       --print("AAL_PetCast Found:", "#"..k, name, "["..iFound.."]", duration)
       if duration <= 0 then
          CastSpell(iFound, BOOKTYPE_PET)
          return k
       end
    end
  end
  return nil
end


-- Название не найдено: nil. Найдено и соответствует: true. Найдено и не соответствует: false
function AAL_CheckPetAction(action_name, param)
  for i=1, 100 do
    local name,_,texture,_,isActive = GetPetActionInfo(i)
    if name == nil then return nil end
    if name == action_name then
       if param == nil then return isActive == 1 end
       return not not string.find(texture, param, 1,true)
    end
  end
end


-- Быстрый поиск по названию в многостраничной книге умений мультиклассового персонажа
-- и управление опциями автоматических действий из "командной строки"

function AAL_SlashSB(msg)
  SetCVar("ShowAllSpellRanks", 1) -- иначе будет позиционировать неправильно

  while true do
    local _, _, opt, val, tail = string.find(msg, "^ *(%a+)([+-]?) *(.*)")
    val = (val ~= "-")

    --[[
    if     opt == "mr" then aalcfg.magres  = val
    elseif opt == "nb" then aalcfg.noblock = val
    elseif opt == "nc" then aalcfg.nocleave= val
    elseif opt == "nd" then aalcfg.nodrink = val
    ]] if false then
    else break
    end

    msg = tail
  end

  if msg == "" then
     print("/b: Opens Spellbook at specific spell name, e.g. /b Seal of")
     --[[
     print("     opts  magres:", aalcfg.magres and "mr+" or "mr-",
      " noblock:", aalcfg.noblock and "nb+" or "nb-",
      " nocleave:", aalcfg.nocleave and "nc+" or "nc-",
      " nodrink:", aalcfg.nodrink and "nd+" or "nd-")
     ]]
     return
  end

  local exact = IsUsableSpell(msg)
  if not exact then
     msg = string.lower(msg)
  end
  local k = nil
  local pos_k = 9999
  for i = 1, 5000 do
    local spell, rank = GetSpellName(i, BOOKTYPE_SPELL)
    if not spell then break end
    if exact and spell == msg then
       k = i
       break
    end
    local pos = string.find(string.lower(spell.." "..rank), msg, 1,true)
    if pos and pos < pos_k then
       pos_k = pos
       k = i -- найдена подстрока; выбирается вариант, где она ближе к началу названия
    end
  end

  if not k then print("/b: the Spellbook has no spell \""..msg.."\""); return end
  for tab=1, 100 do
    local tabname,_,i,nSpells = GetSpellTabInfo(tab)
    if not tabname then break end
    if k <= i + nSpells then
       local page = ceil((k-i)/SPELLS_PER_PAGE)
       SpellBookFrame.bookType = BOOKTYPE_SPELL
       SpellBookSkillLineTab_OnClick(nil, tab)
       SPELLBOOK_PAGENUMBERS[tab] = page
       if SpellBookFrame:IsVisible() then SpellBookFrame_Update(1)
       else ToggleSpellBook( SpellBookFrame.bookType )
       end
       break
    end
  end
end


-- ONLOAD CODE

SlashCmdList["AALsb"] = AAL_SlashSB;
SLASH_AALsb1 = "/b";

GAR_LOOK_DEG = 0

SetCVar("questPOI", false)

SetConsoleKey("NUMLOCK")

if ChatFrameEditBox ~= nil then
   ChatFrameEditBox:SetAltArrowKeyMode(false)
else
   for i=1,7 do
     local curr = getglobal("ChatFrame"..i.."EditBox")
     if curr ~= nil then curr:SetAltArrowKeyMode(false) end
   end
end

