WoWInterface SVN hebChat

[/] [trunk/] [core.lua] - Rev 3

Go to most recent revision | Compare with Previous | Blame | View Log

-- Author      : Animor
-- Create Date : 10/1/2011 1:08:04 PM

----------------------------------------
-- Libs
----------------------------------------
hebChat                                 = LibStub("AceAddon-3.0"):NewAddon("hebChat", "AceEvent-3.0")
local AceConfigDialog   = LibStub("AceConfigDialog-3.0")

--------------------------------------
-- General variables and Declarations
--------------------------------------

local addonName = ...
local origChatEdit_OnTextChanged        = ChatEdit_OnTextChanged
local origChatEdit_OnTabPressed         = ChatEdit_OnTabPressed
local origChatEdit_UpdateHeader         = ChatEdit_UpdateHeader
local origFCF_OpenTemporaryWindow       = FCF_OpenTemporaryWindow
local origSendChatMessage                       = SendChatMessage
local origBNSendWhisper                         = BNSendWhisper
local _G                                                        = _G

BINDING_HEADER_HEBCHAT = "Animor's hebChat"

hebChat.wimLoaded = false
hebChat.guildMemberMobile = {}
hebChat.guildMemberMobileInform = {}

-- Fonts table
hebChat.fontsName = {
        ["Default Font"]                = "Default Font",
        ["Arial"]                               = "Arial",
        ["Tahoma"]                              = "Tahoma",
        ["Times New Roman"]     = "Times New Roman",
        ["Sans Serif"]                  = "Sans Serif",
        ["Miriam"]                              = "Miriam",
        ["Courier"]                             = "Courier",
        ["David"]                               = "David",
        ["David Bold"]                  = "David Bold",
        ["FrankRuehl"]                  = "FrankRuehl",
        ["Levenim"]                             = "Levenim",
        ["Narkisim"]                    = "Narkisim",
        ["Gisha"]                               = "Gisha",
}

hebChat.fonts = {
        ["Default Font"]                = "Fonts\\ARIALN.TTF",
        ["Arial"]                               = "Interface\\AddOns\\hebChat\\Fonts\\arial.ttf",
        ["Tahoma"]                              = "Interface\\AddOns\\hebChat\\Fonts\\tahoma.ttf",
        ["Times New Roman"]     = "Interface\\AddOns\\hebChat\\Fonts\\times.ttf",
        ["Sans Serif"]                  = "Interface\\AddOns\\hebChat\\Fonts\\micross.ttf",
        ["Miriam"]                              = "Interface\\AddOns\\hebChat\\Fonts\\mriam.ttf",
        ["Courier"]                             = "Interface\\AddOns\\hebChat\\Fonts\\courbd.ttf",
        ["David"]                               = "Interface\\AddOns\\hebChat\\Fonts\\david.ttf",
        ["David Bold"]                  = "Interface\\AddOns\\hebChat\\Fonts\\davidbd.ttf",
        ["FrankRuehl"]                  = "Interface\\AddOns\\hebChat\\Fonts\\frank.ttf",
        ["Levenim"]                             = "Interface\\AddOns\\hebChat\\Fonts\\lvnm.ttf",
        ["Narkisim"]                    = "Interface\\AddOns\\hebChat\\Fonts\\nrkis.ttf",
        ["Gisha"]                               = "Interface\\AddOns\\hebChat\\Fonts\\gisha.ttf",       
}

-- Font Objects table
hebChat.fObjects = {}

-- Save number of chars to identify delete
hebChat.lastText = ""

-- Saved variables      

---------------
-- Delay Frame
---------------
if not hebChatDelayFrame then
        hebChatDelayFrame = CreateFrame("Frame")
        hebChatDelayFrame:Hide()
end

hebChatDelayFrame:SetScript("OnUpdate", function(self, elapsed)
        self.delaySec = self.delaySec - elapsed
        if self.delaySec <= 0 then
                self:Hide()
                self.func()
        end
end)

function hebChatDelayFrame:delay(delaySec, func)
        hebChatDelayFrame.func = func
        hebChatDelayFrame.delaySec = delaySec
        hebChatDelayFrame:Show()
end

-----------
-- Loading
-----------

-- Open configuration panel via slash commands
local function hebChatOpenConfig()
        InterfaceOptionsFrame_OpenToCategory(hebChat.configPanel)
 end

-- Show/Hide graphic button and make it movable
function hebChat:hebChatLangButton_OnLoad(frame)
        frame:RegisterForDrag("LeftButton")
end
 
-- -- Even handling
-- hebChat:SetScript("OnEvent", 
        -- function(self, event, ...)   
                -- if self[event] then
                        -- return self[event](...)
                -- end
        -- end
-- )

-- ADDON_LOADED event
function hebChat:OnInitialize()

        -- Init saved variables
        self.defaults = {
                globalEn                = true,
                graphicButtonEN = true,
                currentLang             = "EN",
                currentFont             = "Arial",
                hebFont                 = "Arial",
                defaultFont             = "Default Font",       
                currentFontSize = 13,
                hebFontSize             = 13,
                defaultFontSize = 14,
                showWarning             = true,
                langButtonSize  = 30,
        }

        if not hebChatDB then
                hebChatDB = {}
        end

        for k, v in pairs(self.defaults) do
                if type(hebChatDB[k]) ~= type(v) then
                        hebChatDB[k] = v
                end
        end

        -- Register to PLAYER_ENTERING_WORLD
        hebChat:RegisterEvent("PLAYER_ENTERING_WORLD")

        -- Set chat frame fonts according to configuration
        hebChat:setChatFont()

        -- Hook ChatEdit_OnTextChanged
        ChatEdit_OnTextChanged  = hebChat.ChatEdit_OnTextChanged

        -- Hook SendChatMessage
        SendChatMessage = hebChat.SendChatMessage

        -- Hook BNSendWhisper
        BNSendWhisper   = hebChat.BNSendWhisper

        -- Hook ChatEdit_OnTabPressed
        ChatEdit_OnTabPressed = hebChat.ChatEdit_OnTabPressed
        
        -- Hook ChatEdit_UpdateHeader
        ChatEdit_UpdateHeader = hebChat.ChatEdit_UpdateHeader

        -- Hook FCF_OpenTemporaryWindow
        FCF_OpenTemporaryWindow = hebChat.FCF_OpenTemporaryWindow
        
        -- Init font Dropdown list
        hebChat:createFontObjects()     
        
        -- Graphic button enable button
        hebChatLangButton:SetSize(hebChatDB.langButtonSize, hebChatDB.langButtonSize)
        hebChat:langButtonSetFont()
        hebChatLangButton:SetText(hebChatDB.currentLang)
        if (hebChatDB.globalEn and hebChatDB.graphicButtonEN) then
                hebChatLangButton:Show()
        else
                hebChatLangButton:Hide()
        end                     
                        
        -- Slash commands
        SLASH_HEBCHAT1 = "/heb"
        SLASH_HEBCHAT2 = "/hebchat"
        SlashCmdList["HEBCHAT"] = hebChatOpenConfig
        
        -- Fix wrapping
        ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_WHISPER", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_WHISPER_INFORM", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_CONVERSATION", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID_LEADER", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY_LEADER", hebChat.hebChatFixWrap)
        ChatFrame_AddMessageEventFilter("CHAT_MSG_GUILD", hebChat.hebChatFixWrap)               
        ChatFrame_AddMessageEventFilter("CHAT_MSG_OFFICER", hebChat.hebChatFixWrap)
        
        -- Fontstring to measure string width
        hebChat.textWidthFrame = CreateFrame("Frame", nil, UIParent)
        hebChat.textWidthFrame:Hide()
        hebChat.textWidthFrame.text = hebChat.textWidthFrame:CreateFontString()
        hebChat.textWidthFrame.text:SetAllPoints(hebChat.textWidthFrame)        
        hebChat.textWidthFrame.text:SetFont(hebChat.fonts[hebChatDB.currentFont], hebChatDB.currentFontSize)            
        
        -- String table to fix wrapping
        hebChat.newStringTable = {}

        -- Save number of chars to identify delete
        hebChat.lastText = ""
                                        
        -- Welcome message
        local enableString = (hebChatDB.globalEn and " enabled") or (not hebChatDB.globalEn and " disabled")            
        DEFAULT_CHAT_FRAME:AddMessage ("Animor's hebChat v"..GetAddOnMetadata(addonName, "Version")..enableString..": type /heb or /hebchat for configuration.", 1, 0, 1)
        
        -- Config Panel
        LibStub("AceConfig-3.0"):RegisterOptionsTable("hebChat", self.options)
        hebChat.configPanel = AceConfigDialog:AddToBlizOptions("hebChat", "hebChat")

        end

-- PLAYER_ENTERING_WORLD event
function hebChat.PLAYER_ENTERING_WORLD(...)
        
        -- Set chat frame fonts according to configuration
        hebChat:setChatFont()
        
        -- Set Fonts again after 0.5[s] to bypass other addons fonts.
        hebChatDelayFrame:delay(0.5, hebChat.setChatFont)

        -- Display warning if Prat/Chatter and Misspelled are loaded
        if ((Prat3DB or ChatterDB) and Misspelled_DB and hebChatDB.showWarning) then            
                StaticPopupDialogs["hebChat Warning"] = {
                text = "Warning: Animor's hebChat will not work properly when either Prat3/Chatter and Misspelled are loaded.",
                button1 = OKAY,
                button2 = "Don't show again",
                OnCancel  = function()
                                                hebChatDB.showWarning = false
                                        end,
                timeout = 0,
                whileDead = true,
                hideOnEscape = false,           
                }
                
                StaticPopup_Show ("hebChat Warning")
        end     
        
         -- WIM support
         if (WIM3_Data) then
                
                -- Hook WIM history viewer
                if (not hebChat.wimLoaded) then
                        origWIMShowHistoryViewer = WIM.ShowHistoryViewer
                        WIM.ShowHistoryViewer = hebChat.ShowHistoryViewer
                        hebChat.wimLoaded = true
                end
                
                if (hebChatDB.globalEn) then
                        -- Convert WIM msg_box input to Hebrew 
                        WIM.RegisterWidgetTrigger("msg_box", "whisper,chat,w2w", "OnTextChanged", hebChat.text2Heb)                     
                        -- Toggle language on ctrl-tab while typing
                        WIM.RegisterWidgetTrigger("msg_box", "whisper,chat,w2w", "OnTabPressed", 
                        function()
                                if IsControlKeyDown() then
                                        hebChat:toggleLanguage();
                                end
                        end)
                        -- Handle text leftovers when switching WIM windows
                        WIM.RegisterWidgetTrigger("msg_box", "whisper,chat,w2w", "OnEditFocusGained", 
                        function(self)
                                if (self) then
                                        hebChat.lastText = self:GetText()
                                else
                                        hebChat.lastText = ""
                                end
            end)                        
                end
        end
end

------------------------
-- Global enable button 
------------------------
 
 function hebChat:globalEn_OnClick(value)
        if value then
                hebChatDB.globalEn                      = true
                hebChatDB.currentFontSize       = hebChatDB.hebFontSize
                hebChatDB.currentFont           = hebChatDB.hebFont
                if (hebChatDB.graphicButtonEN) then
                        hebChatLangButton:Show()
                end
        else
                hebChatDB.globalEn                      = false
                hebChatDB.currentFontSize       = hebChatDB.defaultFontSize
                hebChatDB.currentFont           = hebChatDB.defaultFont         
                hebChatLangButton:Hide()
        end
        self:setChatFont()              
 end 
 
 -- Check legit chat type
function hebChat:checkLegitChatType (chatType)
        if (chatType == "GUILD" or chatType == "OFFICER" or 
                chatType == "PARTY" or chatType == "RAID" or 
                chatType == "WHISPER" or chatType == "BN_CONVERSATION" or
                chatType == "BN_WHISPER") then
                return true
        else
                return false
        end
end

-------------------
-- Graphic button  
-------------------
 
 function hebChat:graphicButtonEN_OnClick(value)
        if value then
                hebChatDB.graphicButtonEN                       = true
                if (hebChatDB.globalEn) then
                        hebChatLangButton:Show()
                end
        else
                hebChatDB.graphicButtonEN                       = false
                hebChatLangButton:Hide()
        end     
 end 

 function hebChat:toggleLanguage()
        if (hebChatDB.currentLang == "EN") then
                hebChatDB.currentLang = "HE"
        else
                hebChatDB.currentLang = "EN"
        end
        hebChatLangButton:SetText(hebChatDB.currentLang)
 end 

-----------------------
-- Fonts 
-----------------------

-- Create font objects
function hebChat:createFontObjects()
        local fObject = nil
        for k, v in pairs(self.fonts) do
                fObject  = CreateFont(k)
                fObject:SetFont(v, 13)
                self.fObjects[k] = fObject
        end
end

function hebChat:langButtonSetFont()
        local langButtonFontObject = CreateFont("langButtonFont")
        langButtonFontObject:SetFont("Fonts\\FRIZQT__.TTF", hebChatDB.langButtonSize*0.4)
        hebChatLangButton:SetNormalFontObject(langButtonFontObject)
        hebChatLangButton:SetHighlightFontObject(langButtonFontObject)  
end

local function hebChatIsCurrentFont(fontName)
        if (fontName == hebChatDB.currentFont) then
                return true
        else
                return false
        end
end

-- Selecting a font from dropdown list
function hebChat:hebChatDropDownList_OnClick(arg1)

        hebChatDB.currentFont   = arg1
        if (hebChatDB.globalEn) then
                hebChatDB.hebFont               = arg1          
        else
                hebChatDB.defaultFont   = arg1
        end
                
        hebChat:setChatFont()   
end

--------------------
-- Font Size slider
--------------------
function hebChat:hebChatFontSizeSlider_OnValueChanged(value)
        if (hebChatDB.globalEn) then
                hebChatDB.hebFontSize           = value
                hebChatDB.currentFontSize       = value
        else
                hebChatDB.defaultFontSize       = value
                hebChatDB.currentFontSize       = value 
        end
        hebChat:setChatFont()
end

---------------------------------------------------
-- Set chat frames font according to configuration 
---------------------------------------------------
function hebChat:setChatFont()
        local newFont   = ""
        local frame             = nil
        
        if (hebChat.fonts[hebChatDB.currentFont]) then
                newFont = hebChat.fonts[hebChatDB.currentFont]
        else
                newFont = hebChat.fonts["Default Font"]
        end 
                
        for i = 1, 30 do
                frame = _G["ChatFrame"..i]
                if frame then
                        frame:SetFont(newFont, hebChatDB.currentFontSize)
                        _G["ChatFrame"..i.."EditBox"]:SetFont(newFont, hebChatDB.currentFontSize)
                end
        end
        
        
        if (WIM3_Data) then
                -- Set WIM chatFrame default font
                WIM3_Data.fontSize = hebChatDB.currentFontSize - 2      
                if (hebChat.fObjects[hebChatDB.currentFont]) then
                        _G[WIM3_Data.skin.font] = hebChat.fObjects[hebChatDB.currentFont]
                        if (WIM3_HistoryFrame) then
                                WIM3_HistoryFrame.content.chatFrame:SetFontObject(hebChat.fObjects[hebChatDB.currentFont])
                                WIM3_HistoryFrame.content.textFrame.text:SetFontObject(hebChat.fObjects[hebChatDB.currentFont])                         
                        end
                end
                
                -- Set WIM msg_box default font
                local SelectedSkin = WIM:GetSelectedSkin()
                if (SelectedSkin) then
                        SelectedSkin.message_window.widgets.msg_box.font_height = hebChatDB.currentFontSize                     
                end
                
                -- Set WIM current chatFrames and msg_boxes fonts
                local WindowSoupBowl = WIM:GetWindowSoupBowl()
                local window_objects = WindowSoupBowl.windows
                for i=1, table.getn(window_objects) do                  
                        local chat_display = window_objects[i].obj.widgets.chat_display;                        
                        local msg_box = window_objects[i].obj.widgets.msg_box;
                        chat_display:SetFont(newFont, hebChatDB.currentFontSize)
                        msg_box:SetFont(newFont, hebChatDB.currentFontSize)
                end             
        end
end

---------------------------
-- Text handling functions
---------------------------
-- Check if string contains hebrew char
local function isHeb(str)
        local byteArray = {}
        local hebCharfound = false
        local i = 1
        byteArray =  {string.byte(str, 1, strlenutf8(str))}
        while (i <= #byteArray and hebCharfound == false) do
                if (byteArray[i] == 215) then
                        hebCharfound = true
                end
                i = i + 1
        end     
        return hebCharfound
end

-- Deal with utf8 chars
local function chsize(char)
        -- UTF-8 Reference:
        -- 0xxxxxxx - 1 byte UTF-8 codepoint (ASCII character)
        -- 110yyyxx - First byte of a 2 byte UTF-8 codepoint
        -- 1110yyyy - First byte of a 3 byte UTF-8 codepoint
        -- 11110zzz - First byte of a 4 byte UTF-8 codepoint
        -- 10xxxxxx - Inner byte of a multi-byte UTF-8 codepoint 
    if not char then
        return 0
    elseif char > 240 then
        return 4
    elseif char > 225 then
        return 3
    elseif char > 192 then
        return 2
    else
        return 1
    end
end
 
-- This function can return a substring of a UTF-8 string, properly handling
-- UTF-8 codepoints.  Rather than taking a start index and optionally an end
-- index, it takes the string, the starting character, and the number of
-- characters to select from the string. 
local function utf8sub(str, startChar, numChars, verbose)
        local char                      = ""
        local startIndex        = 1
        local currentIndex      = 0
        
        -- if verbose then print ("startChar: "..startChar) end
        -- if verbose then print ("numChars: "..numChars) end
        
        while startChar > 1 do
                char = string.byte(str, startIndex)             
                startIndex = startIndex + chsize(char)
                startChar = startChar - 1
        end
 
        currentIndex = startIndex
 
        while numChars > 0 and currentIndex <= #str do
                char = string.byte(str, currentIndex)
                currentIndex = currentIndex + chsize(char)
                numChars = numChars -1
        end
        -- if verbose then print ("startIndex: "..startIndex) end
        -- if verbose then print ("currentIndex: "..currentIndex) end
        -- if verbose then print (str:sub(startIndex, currentIndex - 1)) end
        return str:sub(startIndex, currentIndex - 1)
end

-- identical to string.reverse except that it supports UTF-8
local function utf8reverse (str)

        local bytes = str:len()
        local pos = bytes
        local charbytes
        local newstr = ""

        while pos > 0 do
                c = str:byte(pos)
                while c >= 128 and c <= 191 do
                        pos = pos - 1
                        c = str:byte(pos)
                end

                charbytes = chsize(c)

                newstr = newstr .. str:sub(pos, pos + charbytes - 1)

                pos = pos - 1
        end

        return newstr
end

-- Convert char to hebrew
local function charHebConvert(origString, cursorPosition)
        local char                      = ""
        local charHeb           = ""
        local charByte1         = 0
        local charByte2         = 0
        local charIsHebrew      = false
        local charIsLatin       = false
        
                
        -- Get current chat 
        if (cursorPosition > 1) then            
                char = origString:sub(cursorPosition-1, cursorPosition)         
                charByte1, charByte2 = char:byte(1, #char)              
                if (charByte1 == 195 and charByte2) then                                
                        charIsLatin = true
                else
                        char = origString:sub(cursorPosition, cursorPosition)
                        charIsLatin = false
                end
        elseif (cursorPosition == 1) then
                char = origString:sub(cursorPosition, cursorPosition)
                charIsLatin = false
        else 
                -- cursorPosition == 0 (should not happen)
                char = ""
                charIsLatin = false
        end
        
        -- If required, convert char to Hebrew  
        if (charIsLatin and not hebChatDB.graphicButtonEN) then         
                -- Convert according to alt-shift hebrew mode
                charHeb = string.char(215, charByte2 - 16)
                charIsHebrew = true
        elseif (hebChatDB.graphicButtonEN and hebChatDB.currentLang == "HE") then               
                -- Convert according to keymap
                if (hebChat.hebSet[char]) then
                        charHeb                 = hebChat.hebSet[char]                  
                        charIsHebrew    = true                  
                else
                        charHeb                 = char
                        charIsHebrew    = false
                end     
        else
                -- Do not Convert
                charHeb                 = char
                charIsHebrew    = false
        end     
        
        return charIsHebrew, charHeb
end
 
-- Convert editBox to hebrew
 function hebChat.text2Heb (editBox)
        local numOfChars                = 0
        local prevNumOfChars    = 0
        local cursorPosition    = 0
        local editBoxMaxLetters = 0
        local typedCharHeb              = ""
        local preString                 = ""
        local postString                = ""
        local origString                = ""
        local newString                 = ""
        local stringPreEn               = ""    
        local stringEn                  = ""
        local stringPostEn              = ""
        local punc1                             = ""
        local digit                             = ""
        local digit1                    = ""
        local digit2                    = ""
        local punc2                             = ""
        local restPostString    = ""
        local typedCharIsHebrew = nil
        local preStringFind             = nil
        
        editBoxMaxLetters = editBox:GetMaxLetters()
        if (editBoxMaxLetters == 0) then
                -- WIM fix
                editBoxMaxLetters = 255
        end
        origString = editBox:GetText()  
        numOfChars = strlenutf8(origString)
        prevNumOfChars = strlenutf8(hebChat.lastText)
        newString = origString                                                                                          -- init value
        cursorPosition = editBox:GetCursorPosition()
                
        if ( (#origString > editBoxMaxLetters - 2) and (#origString > #hebChat.lastText) and isHeb(origString) ) then           
                -- editBox reached max letters limit - restore last string
                newString = hebChat.lastText
                editBox:SetText(newString)
                editBox:SetCursorPosition(0)                    
        elseif (numOfChars ~= prevNumOfChars - 1 and numOfChars ~= prevNumOfChars and numOfChars < prevNumOfChars + 2) then     
                -- Do not convert for delete/backspace or links 
                
                -- Typed char in string
                typedCharIsHebrew, typedCharHeb = charHebConvert(origString, cursorPosition)

                -- Extract the string after type char
                if (cursorPosition < #origString) then
                        postString = origString:sub(cursorPosition + 1, #origString)
                else
                        postString = ""
                end                                     
                if (typedCharIsHebrew) then
                        -- Hebrew char in Hebrew or mixed-Hebrew string
                        
                        -- Extract the string before typed char
                        if (hebChatDB.graphicButtonEN) then
                                -- 1 byte char typed
                                if (cursorPosition > 1) then
                                        preString = string.sub(origString, 1, cursorPosition - 1)
                                else
                                        preString = ""
                                end
                        else
                                -- 2 byte latin char typed
                                if (cursorPosition > 2) then
                                        preString = string.sub(origString, 1, cursorPosition - 2)
                                else
                                        preString = ""
                                end                     
                        end
                        
                        stringPreEn, preStringFind, stringEn, stringPostEn = preString:match("(.-)(([%w%s%p]*[%w]+)([%p%s]+))$")                        
                        
                        if (origString:match("^/[%a -_]*$")) then
                                -- do not convert slash commands
                        elseif (preStringFind) then                             
                                -- last chars before Hebrew char are white space or punctuation char, then English char.
                                newString = stringPreEn..typedCharHeb..string.reverse(stringPostEn)..stringEn..postString
                                editBox:SetText(newString)                                      
                                editBox:SetCursorPosition(#stringPreEn)                         
                        elseif (preString:find("^[%p%s]+$")) then                               
                                -- Only chars before Hebrew char are white spaces or punctuation chars.
                                newString = typedCharHeb..string.reverse(preString)..postString
                                editBox:SetText(newString)
                                editBox:SetCursorPosition(0)                            
                        elseif (preString:find("^[%p%s%d]+$")) then                             
                                -- Hebrew Char after a number
                                punc1, digit, punc2 = preString:match("^([%s%p]*)([%d%s]-)([%s%p]*)$")
                                newString = typedCharHeb..string.reverse(punc2)..digit..punc1..postString
                                editBox:SetText(newString)
                                editBox:SetCursorPosition(0)                                                    
                        elseif (typedCharHeb:find("[%p]") and postString:find("[%s%p%d]*[א-ת]+") and preString:find("^[%a]+[%a%d%s]*$")) then
                                -- Punctuation char after Hebrew and before English
                                newString = typedCharHeb..preString..postString
                                editBox:SetText(newString)
                                editBox:SetCursorPosition(0)                            
                        else                            
                                -- Normal typing of Hebrew Char                 
                                newString = preString..typedCharHeb..postString
                                editBox:SetText(newString)
                                if (hebChatDB.graphicButtonEN) then
                                        -- 1 byte char typed 
                                        editBox:SetCursorPosition(cursorPosition - 1)                                   
                                else
                                        -- 2 byte latin char typed
                                        editBox:SetCursorPosition(cursorPosition - 2)                                   
                                end
                        end             
                elseif (typedCharHeb ~= "") then
                        -- Non-Hebrew char
                        
                        -- Extract the string before typed char
                        if (cursorPosition > 1) then
                                preString = string.sub(origString, 1, cursorPosition - 1)
                        else
                                preString = ""
                        end
                        
                        
                        if (typedCharHeb:find("[%d]") and postString:find("^[%p]*[%d%p]+[%s%d%p]*[א-ת]+.*")) then
                                -- Number (i.e. several digits) after Hebrew chars.                             
                                punc1, digit, restPostString = postString:match("^([%p]*)([%d%p]+)([%s%d%p]*[א-ת]+.*)")
                                if digit:find("%p+$") then
                                        -- Punctuation char just after hebrew and before digit
                                        digit1, digit2 = digit:match("(.-)(%p+)$")
                                        newString = preString..digit1..punc1..typedCharHeb..digit2..restPostString
                                else
                                        -- No punctuation char just after hebrew
                                        newString = preString..digit..punc1..typedCharHeb..restPostString
                                end                             
                                editBox:SetText(newString)
                                editBox:SetCursorPosition(cursorPosition - 1)                           
                        elseif (typedCharHeb:find("[%p]") and postString:find("[%s%p%d]*[א-ת]+") and preString:find("^[%a]+$")) then
                                -- Punctuation char after Hebrew and before English             
                                newString = typedCharHeb..preString..postString
                                editBox:SetText(newString)
                                editBox:SetCursorPosition(0)                            
                        elseif (typedCharHeb:find("[%p%s%d]") and postString:find("[%s%p%d]*[א-ת]+")) then
                                --  White space, digit or punctuation char after hebrew char                            
                                newString = preString..typedCharHeb..postString
                                editBox:SetText(newString)
                                if (not preString:find("[%w]+[%s]?$")) then                                     
                                        -- Move cursor back if there is no non-Hebrew on the left.
                                        editBox:SetCursorPosition(cursorPosition - 1)                                   
                                end                     
                        elseif (postString:find("^%p+%a+") and preString == "") then
                                punc1, stringEn, restPostString  = postString:match("^(%p+)([%a%p]+)(.*)")
                                newString = stringEn..punc1..typedCharHeb..restPostString
                                editBox:SetText(newString)
                                editBox:SetCursorPosition(#(stringEn..punc1..typedCharHeb))                             
                        else
                                -- Other non-Hebrew char                                
                        end --  if (typedCharIsHebrew)                          
                else
                        -- No char.
                end
        end
        hebChat.lastText = newString;
 end -- function text2Heb (editBox)

 -- Fix editBox wrapping for Hebrew text
function hebChat.hebChatFixWrap(chatFrame, event, msg, author, ...)
        local _, _, _, _, _, _, _, _, _, _, _, isMobile = ...
        local remainingString                   = ""
        wipe (hebChat.newStringTable)
        local newString                                 = ""
        local lineString                                = ""
        local lineStringBkp                             = ""
        local remainingStringBkp                = ""
        local chatFrameWidth                    = chatFrame:GetWidth()
        local effectiveChatFrameWidth   = 0
        local header                                    = ""
        local header1                                   = ""
        local header2                                   = ""
        local headerWidth1                              = 0
        local headerWidth2                              = 0
        local currentChar                               = ""
        local inLink                                    = false
        local _                                                 

        -- WIM unkown width bypass
        if (chatFrameWidth == 0) then
                chatFrameWidth = 330
        end             
        
        -- Populate mobile guild members array
        if isMobile then
                hebChat.guildMemberMobile[author] = true
        elseif hebChat.guildMemberMobile[author] then
                hebChat.guildMemberMobile[author] = false
                hebChat.guildMemberMobileInform[author] = false
        end
        
        -- In case of hebrew char       
        if isHeb(msg) and hebChatDB.globalEn then
                
                -- Remove addon prefix
                if msg:find("^%*hebChat addon%* ") then
                        _, msg = msg:match("^(%*hebChat addon%* )(.*)")
                end

                -- Remote guild chat (mobile appliaction)
                -- Do not reverse INFORM whispers text if the author was not recognized as isMobile by the time the message was sent. Do not reverse links.
                if isMobile and (hebChat.guildMemberMobileInform[author] or (event ~= "CHAT_MSG_WHISPER_INFORM" and event ~= "CHAT_MSG_BN_WHISPER_INFORM")) and not msg:find("|H.+|h") then
                        msg = utf8reverse(msg)
                end                     
                
                -- Calculate header widths
                if (event == "CHAT_MSG_WHISPER" or event == "CHAT_MSG_BN_WHISPER") then
                        header1 = "["..author.."] whispers: "
                        header2 = "[55:55] [W From] ["..author.."]: "
                elseif (event == "CHAT_MSG_WHISPER_INFORM" or event == "CHAT_MSG_BN_WHISPER_INFORM") then
                        header1 = "To ["..author.."]: "
                        header2 = "[55:55] [W To] ["..author.."]: "
                elseif (event == "CHAT_MSG_GUILD") then
                        header1 = "[Guild] ["..author.."]: "
                        header2 = "[55:55] [G] ["..author.."]: "
                elseif (event == "CHAT_MSG_OFFICER") then
                        header1 = "[Officer] ["..author.."]: "
                        header2 = "[55:55] [O] ["..author.."]: "
                elseif (event == "CHAT_MSG_RAID") then
                        header1 = "[Raid] ["..author.."]: "     
                        header2 = "[55:55] [R] ["..author.."]: "        
                elseif (event == "CHAT_MSG_RAID_LEADER") then
                        header1 = "[Raid Leader] ["..author.."]: "
                        header2 = "[55:55] [RL] ["..author.."]: "
                elseif (event == "CHAT_MSG_PARTY") then
                        header1 = "[Party] ["..author.."]: "
                        header2 = "[55:55] [P] ["..author.."]: "
                elseif (event == "CHAT_MSG_PARTY_LEADER") then
                        header1 = "[Party Leader] ["..author.."]: "     
                        header2 = "[55:55] [PL] ["..author.."]: "       
                elseif (event == "CHAT_MSG_BN_CONVERSATION") then
                        header1 = "11. [Conversation] ["..author.."]: "
                        header2 = "[55:55] [Conversation] ["..author.."]: "
                else
                        header1 = ""
                        header2 = ""
                end             
                
                if Prat3DB or ChatterDB then
                        header = header2.."55:88:"
                elseif ElvData then
                        header = header2
                else
                        -- Default UI timestamps are enabled.
                        if CHAT_TIMESTAMP_FORMAT then
                                header1 = "55:55 "..header1
                        end
                        header = header1
                end             
                                
                -- hebChat.textWidthFrame.text:SetFont(hebChat.fonts[hebChatDB.currentFont][2], hebChatDB.currentFontSize)
                hebChat.textWidthFrame.text:SetFont(hebChat.fonts[hebChatDB.currentFont], hebChatDB.currentFontSize)
                
                hebChat.textWidthFrame.text:SetText(header)
                headerWidth1 = hebChat.textWidthFrame.text:GetStringWidth()
                
                hebChat.textWidthFrame.text:SetText("[2")
                headerWidth2 = hebChat.textWidthFrame.text:GetStringWidth()     
                -- first line effective width           
                effectiveChatFrameWidth = chatFrameWidth - headerWidth1 - 10
                                
                -- Prepare for outer while loop
                remainingString = msg
                hebChat.textWidthFrame.text:SetText(remainingString)
                        
                while (hebChat.textWidthFrame.text:GetStringWidth() > effectiveChatFrameWidth)  do                      
                        -- Prepare for inner while loop         
                        hebChat.textWidthFrame.text:SetText(lineString) 
                        while (hebChat.textWidthFrame.text:GetStringWidth() <= effectiveChatFrameWidth) or inLink do                    
                                -- Extract last char
                                currentChar = (utf8sub(remainingString, strlenutf8(remainingString), 1))
                                -- Check if inside link
                                if (currentChar == "|" and utf8sub(lineString, 1, 1) == "r" and not inLink) then
                                        inLink = true                   
                                elseif (inLink and currentChar == "|" and utf8sub(lineString, 1, 1) == "c") then
                                        inLink = false
                                end                             
                                -- Add current chat to line string
                                lineString              = currentChar..lineString
                                remainingString = utf8sub(remainingString, 1, strlenutf8(remainingString) - 1)                          
                                -- Store current lineString between words and not in link and move last space to end of line
                                if (lineString:find("^%s") and not inLink) then
                                        lineStringBkp           = utf8sub(lineString, 2, strlenutf8(lineString) - 1)..utf8sub(lineString, 1, 1)                         
                                        remainingStringBkp      = remainingString                               
                                end                     
                                -- Prepare for next while loop check 
                                hebChat.textWidthFrame.text:SetText(lineString)
                        end -- Inner while loop
                        -- out of inner while loop: lineString is wider than frame width
                        
                        if (#lineStringBkp ~= 0) then
                                -- Add the bkp line, at word boundary
                                remainingString = remainingStringBkp
                                table.insert(hebChat.newStringTable, lineStringBkp.."\n")
                        else
                                -- Single word longer than width - just add the word                            
                                table.insert(hebChat.newStringTable, lineString)
                        end
                                
                        
                        -- Prepare for outer while loop 
                        hebChat.textWidthFrame.text:SetText(remainingString)
                        -- non-first line effective width
                        effectiveChatFrameWidth = chatFrameWidth - headerWidth2 - 10
                        -- reset strings
                        lineStringBkp   = ""
                        lineString              = ""            
                end -- Outer while loop 
                table.insert (hebChat.newStringTable, remainingString)
                newString = table.concat(hebChat.newStringTable)        
                return false, newString, author, ...            
        else
                return false
        end -- if (isHeb(msg))
end -- function hebChat.hebChatFixWrap

-----------
-- Hooking
-----------

-- Hook ChatEdit_OnTextChanged - convert to Hebrew when text in changed in chat editBox.
function hebChat:ChatEdit_OnTextChanged(userInput, ...)
        if (ACTIVE_CHAT_EDIT_BOX and userInput and hebChat:checkLegitChatType(ACTIVE_CHAT_EDIT_BOX:GetAttribute("chatType")) and hebChatDB.globalEn) then               
                hebChat.text2Heb(ACTIVE_CHAT_EDIT_BOX)          
        end
        return origChatEdit_OnTextChanged(self, userInput, ...)
end

-- Hook SendChatMessage - Post process text: add prefix, reverse Hebrew when whispering to mobile client
function hebChat.SendChatMessage(msg, chatType, lang, channel, ...)
        if hebChatDB.globalEn and hebChat:checkLegitChatType(chatType) and isHeb(msg) then
                -- Reverse message sent in whisper to mobile user.
                if chatType == "WHISPER" and hebChat.guildMemberMobile[channel] then
                        -- Do not convert links
                        if not msg:find("|c.+|r") then
                                msg = utf8reverse(msg)
                        end
                        hebChat.guildMemberMobileInform[channel] = true
                -- if target is not mobile whisper, and chat is whisper or guild, add prefix with info about the addon (for users that don't have it).
                elseif (chatType == "WHISPER" or chatType == "GUILD") and msg:len() < 240 then
                        msg = "*hebChat addon* "..msg
                end
        end
        return origSendChatMessage(msg, chatType, lang, channel, ...)
end

-- Hook BNSendWhisper - Post process text: add prefix
function hebChat.BNSendWhisper(presenceID, msg, ...)
        if hebChatDB.globalEn and isHeb(msg) then
                msg = "*hebChat addon* "..msg
        end
        return origBNSendWhisper(presenceID, msg, ...)
end

-- Hook ChatEdit_OnTabPressed - toggle language when ctrl-tab is hit
function hebChat:ChatEdit_OnTabPressed(...)
        if IsControlKeyDown() then
                hebChat:toggleLanguage();       
        else -- Switch whisper targets only if ctrl is not held down.
                return origChatEdit_OnTabPressed(self, ...)
        end     
end

-- Hook ChatEdit_UpdateHeader - update bkp text when switching chat windows.
function hebChat:ChatEdit_UpdateHeader(...)     
        if (ACTIVE_CHAT_EDIT_BOX) then
                hebChat.lastText = ACTIVE_CHAT_EDIT_BOX:GetText()
        else
                hebChat.lastText = ""
        end             
        return origChatEdit_UpdateHeader(self, ...)
end

-- Hook FCF_OpenTemporaryWindow - set chat font when new chat window is created.
function hebChat.FCF_OpenTemporaryWindow(...)   
        hebChatDelayFrame:delay(0.1, hebChat.setChatFont)
        return origFCF_OpenTemporaryWindow(...)

end
-- Hook WIM history viewer
function hebChat:ShowHistoryViewer(...) 
        origWIMShowHistoryViewer(...)
        if (hebChat.fObjects[hebChatDB.currentFont]) then
                WIM3_HistoryFrame.content.chatFrame:SetFontObject(hebChat.fObjects[hebChatDB.currentFont])
                WIM3_HistoryFrame.content.textFrame.text:SetFontObject(hebChat.fObjects[hebChatDB.currentFont])
        end
end

Go to most recent revision | Compare with Previous | Blame