Attribute VB_Name = "modStyles"
Option Explicit

Public ChatColor() As CHATCOLOR_STRUCT, UserColor() As USERCOLOR_STRUCT, ChatEvent() As CHATEVENT_STRUCT
Public colSelf As Long, colSilence As Long, colFilter As Long, colIdleL As Long, colIdleM As Long, colIdleH As Long, colInvisible As Long
Public TimeStamp As TIMESTAMP_STRUCT, ClanColor As CLANCOLOR_STRUCT, PingColor As PINGCOLOR_STRUCT, CurrentStyle As String, strLog As String
Public Type TIMESTAMP_STRUCT
    ts_layout As String
    ts_color As Long
    ts_format As String
End Type
Public Type CHATCOLOR_STRUCT
    cc_colorstr As String
    cc_color As Long
End Type
Public Type CLANCOLOR_STRUCT
    cl_initiate As Long
    cl_peon As Long
    cl_grunt As Long
    cl_shaman As Long
    cl_chief As Long
    cl_clan As Long
    cl_yourclan As Long
End Type
Public Type USERCOLOR_STRUCT
    uc_flag As Long
    uc_color As Long
End Type
Public Type PINGCOLOR_STRUCT
    pc_ext As Long
    pc_vhi As Long
    pc_hi As Long
    pc_med As Long
    pc_lo As Long
    pc_vlo As Long
    pc_zero As Long
    pc_neg As Long
End Type
Public Type CHATEVENT_STRUCT
    ce_eid As Long
    ce_string As String
End Type

Public Sub LoadStyle(strStyle As String)
    On Error Resume Next
    ReDim ChatColor(0), UserColor(0), ChatEvent(0)
    If LenB(strStyle) = 0 Then strStyle = "MirageBot"
    Dim F As New FileSystemObject, TS As TextStream, File As String
    File = AppData & "Styles\" & strStyle & ".ini"
    If F.FileExists(File) = False Then Exit Sub
    Set TS = F.OpenTextFile(File, ForReading)
    Do Until TS.AtEndOfStream
        Dim LN As String, Bracket As Boolean, Section As String
        LN = TS.ReadLine
        Select Case LCase$(Trim$(LN))
        Case "timestamp {":     Bracket = True: Section = "ts": GoTo NextLine:
        Case "chat_colors {":   Bracket = True: Section = "cc": GoTo NextLine:
        Case "user_colors {":   Bracket = True: Section = "uc": GoTo NextLine:
        Case "clan_colors {":   Bracket = True: Section = "cl": GoTo NextLine:
        Case "ping_colors {":   Bracket = True: Section = "pc": GoTo NextLine:
        Case "events {":        Bracket = True: Section = "ce": GoTo NextLine:
        Case "}":               Bracket = False: Section = vbNS: GoTo NextLine:
        End Select
        'ignore comments
        If Left$(LN, 2) = "//" Then GoTo NextLine:
        'check if inside a bracket
        If Bracket Then
            'check for colon
            If InStr(LN, ":") > 0 Then
                'split by colon
                Dim Splt() As String
                Splt() = Split(Trim$(LN), ":", 2)
                'check for semi-colon terminator
                If InStr(Splt(1), ";") > 0 Then
                    Dim Field As String, Value As String
                    'get trimmed field
                    Field = Replace$(Trim$(Splt(0)), vbTab, vbNS)
                    'get text before semi-colon
                    Value = Replace$(Trim$(Split(Splt(1), ";")(0)), vbTab, vbNS)
                    'handle ln depending on section
                    Select Case Section
                    Case "ts"
                        Select Case LCase$(Field)
                        Case "layout":      TimeStamp.ts_layout = Replace$(Value, "$sp", " ")   '//layout: [%TIME%];
                        Case "format":      TimeStamp.ts_format = Value                         '//color: #white#;
                        Case "color":       TimeStamp.ts_color = Hex2Color(Value)               '//format: HH:MM:SS;
                        End Select
                    Case "cc"
                        If LenB(ChatColor(0).cc_colorstr) = 0 Then
                            ChatColor(0).cc_colorstr = LCase$(Field)
                            ChatColor(0).cc_color = Hex2Color(Value)
                        Else
                            ReDim Preserve ChatColor(UBound(ChatColor) + 1)
                            ChatColor(UBound(ChatColor)).cc_colorstr = LCase$(Field)
                            ChatColor(UBound(ChatColor)).cc_color = Hex2Color(Value)
                        End If
                    Case "uc"
                        Select Case LCase$(Field)
                        Case "self":        colSelf = Hex2Color(Value)
                        Case "invisible":   colInvisible = Hex2Color(Value)
                        Case "silenced":    colSilence = Hex2Color(Value)
                        Case "filtered":    colFilter = Hex2Color(Value)
                        Case "idlel":       colIdleL = Hex2Color(Value)
                        Case "idlem":       colIdleM = Hex2Color(Value)
                        Case "idleh":       colIdleH = Hex2Color(Value)
                        Case Else
                            If Left$(Field, 2) = "0x" Then
                                If UserColor(0).uc_color = 0 Then
                                    UserColor(0).uc_flag = Val("&H0" & Mid$(Field, 3))
                                    UserColor(0).uc_color = Hex2Color(Value)
                                Else
                                    ReDim Preserve UserColor(UBound(UserColor) + 1)
                                    UserColor(UBound(UserColor)).uc_flag = Val("&H0" & Mid$(Field, 3))
                                    UserColor(UBound(UserColor)).uc_color = Hex2Color(Value)
                                End If
                            End If
                        End Select
                    Case "cl"
                        Select Case LCase$(Field)
                            Case "0x00":        ClanColor.cl_initiate = Hex2Color(Value)       '//Initiate
                            Case "0x01":        ClanColor.cl_peon = Hex2Color(Value)        '//Peon
                            Case "0x02":        ClanColor.cl_grunt = Hex2Color(Value)       '//Grunt
                            Case "0x03":        ClanColor.cl_shaman = Hex2Color(Value)      '//Shaman
                            Case "0x04":        ClanColor.cl_chief = Hex2Color(Value)       '//Chieftain
                            Case "clan":        ClanColor.cl_clan = Hex2Color(Value)        '//Someone's Clan
                            Case "yourclan":    ClanColor.cl_yourclan = Hex2Color(Value)    '//Your Clan
                        End Select
                    Case "pc"
                        Select Case Field
                            Case ">600":        PingColor.pc_ext = Hex2Color(Value)
                            Case ">500":        PingColor.pc_vhi = Hex2Color(Value)
                            Case ">400":        PingColor.pc_hi = Hex2Color(Value)
                            Case ">300":        PingColor.pc_med = Hex2Color(Value)
                            Case ">200":        PingColor.pc_lo = Hex2Color(Value)
                            Case ">9":          PingColor.pc_vlo = Hex2Color(Value)
                            Case "=0":          PingColor.pc_zero = Hex2Color(Value)
                            Case "<0":          PingColor.pc_neg = Hex2Color(Value)
                        End Select
                    Case "ce"
                        If Left$(Field, 2) = "0x" Then
                            If LenB(ChatEvent(0).ce_string) = 0 Then
                                ChatEvent(0).ce_eid = Val("&H0" & Mid$(Field, 3))
                                ChatEvent(0).ce_string = Value
                            Else
                                ReDim Preserve ChatEvent(UBound(ChatEvent) + 1)
                                ChatEvent(UBound(ChatEvent)).ce_eid = Val("&H0" & Mid$(Field, 3))
                                ChatEvent(UBound(ChatEvent)).ce_string = Value
                            End If
                        End If
                    End Select
                End If
            End If
        End If
NextLine:
    Loop
    TS.Close
    CurrentStyle = strStyle
'    Dim I As Integer
'    With frmBot.mnuStyle
'        For I = 0 To .UBound
'            .Item(I).Checked = LCase$(.Item(I).Caption) = LCase$(CurrentStyle)
'        Next I
'    End With
    WriteINI AppSettings, "Settings", "TheStyle", strStyle
    RefreshChannel
End Sub

Public Function GetPingColor(ByVal Ping As Long) As Long
    If Ping = -1 Then GetPingColor = PingColor.pc_neg: Exit Function
    If Ping > 600 Then GetPingColor = PingColor.pc_ext: Exit Function
    If Ping > 500 Then GetPingColor = PingColor.pc_vhi: Exit Function
    If Ping > 400 Then GetPingColor = PingColor.pc_hi: Exit Function
    If Ping > 300 Then GetPingColor = PingColor.pc_med: Exit Function
    If Ping > 200 Then GetPingColor = PingColor.pc_lo: Exit Function
    If Ping > 9 Then GetPingColor = PingColor.pc_vlo: Exit Function
    GetPingColor = PingColor.pc_zero
    If GetPingColor = -1 Then GetPingColor = vbWhite
End Function

Private Function GetChatColor(ByVal strColor As String)
    Dim I As Integer
    strColor = LCase$(strColor)
    For I = 0 To UBound(ChatColor)
        If ChatColor(I).cc_colorstr = strColor Then GetChatColor = ChatColor(I).cc_color: Exit Function
    Next I
    GetChatColor = vbWhite
End Function

Public Function GetUserColor_Database(Index As Integer, Username As String) As Long
    'Check Database Color
    Dim F As Integer, r As RankingStruct
    F = frmBot.Bot(Index).Database.Find(Username)
    If F > -1 Then
        r = GetRankByID(frmBot.Bot(Index).Database.GetUser(F).RankID)
        If r.HasColor Then GetUserColor_Database = r.Color: Exit Function
    End If
    F = frmBot.Bot(Index).Database.FindPattern(Username)
    If F > -1 Then
        r = GetRankByID(frmBot.Bot(Index).Database.GetUser(F).RankID)
        If r.HasColor Then GetUserColor_Database = r.Color: Exit Function
    End If
    GetUserColor_Database = -1
End Function

Public Function GetUserColor(Index As Integer, Username As String, Flags As Long, Optional InChat As Boolean = False) As Long
    'Check for Your color
    If LCase$(frmBot.Bot(Index).Self.Username) = LCase$(Suffix(Username)) Then
        If colSelf <> 0 Then GetUserColor = colSelf: Exit Function
    End If
    'Check Database Color
    Dim colDB As Long
    colDB = GetUserColor_Database(Index, Username)
    If colDB > -1 Then GetUserColor = colDB: Exit Function
    'Check for Clan Color
    With frmBot.Bot(Index)
        If IsFiltered(Username, True) Then GetUserColor = colFilter: Exit Function
        Dim U As objUser
        Set U = .Users.GetByName(Username)
        If Not U Is Nothing And Not InChat Then
            If U.IsSilenced And colSilence > 0 Then GetUserColor = colSilence: Exit Function
            If U.IsInvisible And colInvisible > 0 Then GetUserColor = colInvisible: Exit Function
            If options.DisableIdleColors = False Then
                If U.IsIdle And colIdleL > 0 Then GetUserColor = colIdleL: Exit Function
                If U.IsIdler And colIdleM > 0 Then GetUserColor = colIdleM: Exit Function
                If U.IsIdlest And colIdleH > 0 Then GetUserColor = colIdleH: Exit Function
            End If
        End If
        If options.DisableClanColors = False Then
            If .Clan.InClan Then
                Dim CM As New objMember
                Set CM = .Clan.GetByName(Username)
                If Not CM Is Nothing Then
                    If LenB(CM.Username) > 0 Then
                        Select Case CM.Rank
                            Case 0: GetUserColor = ClanColor.cl_initiate: If GetUserColor = 0 Then GoTo FindColor Else Exit Function
                            Case 1: GetUserColor = ClanColor.cl_peon: If GetUserColor = 0 Then GoTo FindColor Else Exit Function
                            Case 2: GetUserColor = ClanColor.cl_grunt: If GetUserColor = 0 Then GoTo FindColor Else Exit Function
                            Case 3: GetUserColor = ClanColor.cl_shaman: If GetUserColor = 0 Then GoTo FindColor Else Exit Function
                            Case 4: GetUserColor = ClanColor.cl_chief: If GetUserColor = 0 Then GoTo FindColor Else Exit Function
                        End Select
                    End If
                End If
            End If
        End If
    End With
FindColor:
    'Check for Group Color
    Dim X As Long
    X = GetGroupColor(Suffix(Username))
    If X <> -1 Then GetUserColor = X: Exit Function
    'Check for User Color
    Dim I As Integer
    For I = 0 To UBound(UserColor)
        If UserColor(I).uc_flag And Flags Then
            GetUserColor = UserColor(I).uc_color: Exit Function
        End If
    Next I
    'No Color use Previous Color in Event String
    GetUserColor = -1
End Function

Public Sub OutputTime(rtb As RichTextBox)
    If TimeStamp.ts_color = vbBlack Then TimeStamp.ts_color = vbWhite
    With rtb
        If LenB(ChatFont) = 0 Then ChatFont = "Tahoma"
        If Val(ChatFontSize) = 0 Then ChatFontSize = 11
        If (UBound(Split(.Text, vbCrLf)) >= 349) Then
            .SelStart = 0
            .SelLength = (0.75 * Len(.Text))
            .SelText = vbNS
            .SelLength = (InStr(1, .Text, vbCrLf, vbTextCompare) + 1)
            .SelText = vbNS
        End If
        .SelStart = 2000000000
        .SelFontName = ChatFont
        .SelBold = False
        .SelUnderline = False
        .SelStrikeThru = False
        .SelItalic = False
        .SelHangingIndent = 1370
        .SelFontSize = ChatFontSize
        .SelColor = TimeStamp.ts_color
        .SelText = Replace$(TimeStamp.ts_layout, "$time", Format$(Time, TimeStamp.ts_format))
        .SelStart = 2000000000
        If rtb.Name = "rtbChat" Or rtb.Name = "rtbWhis" Then
            If options.Logging = 1 Then
                strLog = HTMLFormat(TimeStamp.ts_color, Replace$(TimeStamp.ts_layout, "$time", Format$(Time, TimeStamp.ts_format)))
            ElseIf options.Logging = 2 Then
                strLog = Replace$(TimeStamp.ts_layout, "$time", Format$(Time, TimeStamp.ts_format))
            End If
        End If
    End With
End Sub

Public Sub OutputPart(rtb As RichTextBox, Color As Long, Message As String, _
        Optional DisableFormat As Boolean = True)
    Dim CurPos As Double, Muta As String
    If Color = vbBlack Then Color = vbWhite
    With rtb
        If Not options.RTFInj Then Message = Replace(Message, "\rtf", "rtf")
        If LenB(ChatFont) = 0 Then ChatFont = "Tahoma"
        If Val(ChatFontSize) = 0 Then ChatFontSize = 11
        If (UBound(Split(.Text, vbCrLf)) >= 349) Then
            .SelStart = 0
            .SelLength = (0.75 * Len(.Text))
            .SelText = vbNS
            .SelLength = (InStr(1, .Text, vbCrLf, vbTextCompare) + 1)
            .SelText = vbNS
        End If
        .SelStart = 2000000000
         CurPos = Len(.Text)
        .SelFontName = ChatFont
        .SelFontSize = ChatFontSize
        .SelBold = False
        .SelUnderline = False
        .SelStrikeThru = False
        .SelItalic = False
        .SelHangingIndent = 1370
        .SelColor = Color
        Muta = options.MutatorInList(Message)
        If LenB(Muta) Then
            Message = Muta
        End If
        .SelText = Message
        .SelStart = 2000000000
         If Not DisableFormat Then
            If options.Emoticons Then ReplaceEmoticons rtb, CurPos
            ReplaceColours rtb, CurPos
         End If
         ReplaceStyles rtb, CurPos
        If rtb.Name = "rtbChat" Or rtb.Name = "rtbWhis" Then
            If options.Logging = 1 Then
                strLog = strLog & HTMLFormat(Color, Message)
                If InStr(strLog, vbNewLine) Then
                    LogHTML rtb.Index, strLog, (rtb.Name = "rtbWhis")
                    strLog = vbNS
                End If
            ElseIf options.Logging = 2 Then
                strLog = strLog & Message
                If InStr(strLog, vbNewLine) Then
                    strLog = Replace$(strLog, "<b>", vbNS)
                    strLog = Replace$(strLog, "<i>", vbNS)
                    strLog = Replace$(strLog, "<s>", vbNS)
                    strLog = Replace$(strLog, "<u>", vbNS)
                    strLog = Replace$(strLog, "</b>", vbNS)
                    strLog = Replace$(strLog, "</i>", vbNS)
                    strLog = Replace$(strLog, "</s>", vbNS)
                    strLog = Replace$(strLog, "</u>", vbNS)
                    LogText rtb.Index, strLog, (rtb.Name = "rtbWhis")
                    strLog = vbNS
                End If
            End If
        End If
    End With
End Sub

Public Sub OutputFocus(rtb As RichTextBox, Index As Integer, EID As Long, _
        Optional Username As String = vbNS, _
        Optional Message As String = vbNS, _
        Optional Flags As Long = 0, _
        Optional Ping As Long = 0, _
        Optional Uptime As String = vbNS, _
        Optional Extra As String = vbNS, _
        Optional NoTime As Boolean = False)
On Error GoTo hErr:
    Dim ucol As Long, urank As String, xdb As objDbUser, xfind As Integer, cRank As String
    'get user color value
    If Index > -1 And LenB(Username) Then
1       ucol = GetUserColor(Index, Username, Flags, True)
        urank = GetAccess2(Username, Index).RankName
4       xfind = frmBot.Bot(Index).Clan.Find(Username)
5       If xfind <> -1 Then cRank = ClanRankToString(frmBot.Bot(Index).Clan.GetByIndex(xfind).Rank)
        Dim ServName As String
        If IsOnGateway(Username) Then
            ServName = Mid$(Username, InStrRev(Username, "@") + 1)
        Else
            ServName = frmBot.Bot(Index).Config.ServerName
        End If
    End If
    Dim GA As String
    GA = Alias.GetAlias(Username, ServName)
    If LenB(GA) = 0 Then GA = Username
    'output time first
6   If Not NoTime Then OutputTime rtb
    'loop thru chat event strings
    Dim I As Integer, lcol As Long
7   For I = 0 To UBound(ChatEvent)
        'found eid
8       If ChatEvent(I).ce_eid = EID Then
            Dim Buf As String, ssharp As Long, esharp As Long, scol As String, slen As Long, talk As Boolean, UI As Integer, Clan As String
            'get talk bool
9           talk = (EID = EID_TALK Or EID = EID_WHISPER Or EID = EID_WHISPERSENT Or EID = EID_EMOTE Or EID = &HA2 Or EID = &HA3 Or EID = &HA4)
            'get buf
10          Buf = ChatEvent(I).ce_string
            Buf = Replace$(Buf, "[#]", "¬")
            Buf = Replace$(Buf, "[]]", "§")
            Buf = Replace$(Buf, "[[]", "ª")
            Buf = Replace$(Buf, "[,]", "Ø")
11          Do Until Len(Buf) = 0
                'get first sharp
12              ssharp = InStr(1, Buf, "#")
13              If ssharp = 0 Then GoTo DoOutput:
                'get next sharp
14              esharp = InStr(ssharp + 1, Buf, "#")
15              If esharp = 0 Then GoTo DoOutput:
                'get color name
16              scol = Mid$(Buf, ssharp + 1, esharp - ssharp - 1)
                'get len for later
17              slen = InStr(esharp + 1, Buf, "#")
                'check if the color == #ucol#
18              If UCase$(scol) = "UCOL" Then
                    'get usercolor is not -1
19                  If ucol <> -1 Then lcol = ucol
                Else
                    'get chatcolor
20                  lcol = GetChatColor(scol)
                End If
DoOutput:
                Dim stmp As String, Stats As String
                'check length
                If slen > 0 Then
                    'get part
21                  stmp = Mid$(Buf, esharp + 1, slen - esharp - 1)
22                  Stats = DisplayStatInfo(Message)
23                  If LenB(Stats) = 0 Then
24                      If Left$(Message, 4) = "VD2D" Or Left$(Message, 4) = "PX2D" Then
25                          Stats = "open char"
                        Else
26                          Stats = "no stats"
                        End If
                    End If
                    'replace vars
                    Clan = ExtractClanName(Message)
                    If Index > -1 Then
                        If LenB(Clan) = 0 Then
                            UI = frmBot.Bot(Index).Users.Find(Username)
                            If UI > -1 Then
                                Clan = ExtractClanName(frmBot.Bot(Index).Users.GetByIndex(UI).Statstring)
                            End If
                        End If
                    End If
                    ReplaceAttr stmp, "$clan", Clan
                    ReplaceAttr stmp, "$flags_dec", Flags
                    ReplaceAttr stmp, "$flags_raw", LongToHex(Flags)
                    ReplaceAttr stmp, "$flags", FlagsToStr(Flags)
                    ReplaceAttr stmp, "$ping", Ping
                    ReplaceAttr stmp, "$client_raw", StrReverse$(Left$(Message, 4))
                    ReplaceAttr stmp, "$client", ProductToStr(StrReverse$(Left$(Message, 4)))
                    ReplaceAttr stmp, "$channel", Message
                    ReplaceAttr stmp, "$chflags_raw", LongToHex(Flags)
                    ReplaceAttr stmp, "$chflags_dec", Flags
                    ReplaceAttr stmp, "$chflags", ChanFlagsToStr(Flags)
                    ReplaceAttr stmp, "$rank", urank
                    ReplaceAttr stmp, "$crank", cRank
                    ReplaceAttr stmp, "$stats", Stats
                    ReplaceAttr stmp, "$user", GA
                    ReplaceAttr stmp, "$uptime", Uptime
                    ReplaceAttr stmp, "$message", Message
                    ReplaceAttr stmp, "$extra", Extra
                    'Replace Special Characters Again
                    stmp = Replace$(stmp, "§", "[")
                    stmp = Replace$(stmp, "ª", "]")
                    stmp = Replace$(stmp, "Ø", ",")
                    stmp = Replace$(stmp, "¬", "#")
                    'append part of string
                    OutputPart rtb, lcol, stmp, Not talk
                    'advance buffer
41                  Buf = Mid$(Buf, slen)
                Else
                    'check for more # chars
42                  If InStrB(Mid$(Buf, esharp + 1), "#") <> 0 Then
                        'skip to last #
43                      Buf = Mid$(Buf, esharp + 1)
                        'goto next part
                        GoTo NextItem:
                    Else
                        'get part
44                      stmp = Mid$(Buf, esharp + 1)
45                      Stats = DisplayStatInfo(Message)
                        If LenB(Stats) = 0 Then
46                          If Left$(Message, 4) = "VD2D" Or Left$(Message, 4) = "PX2D" Then
                                Stats = "open char"
                            Else
                                Stats = "no stats"
                            End If
                        End If
                        'replace vars
                        Clan = ExtractClanName(Message)
                        If Index > -1 Then
                            If LenB(Clan) = 0 Then
                                UI = frmBot.Bot(Index).Users.Find(Username)
                                If UI > -1 Then
                                    Clan = ExtractClanName(frmBot.Bot(Index).Users.GetByIndex(UI).Statstring)
                                End If
                            End If
                        End If
                        ReplaceAttr stmp, "$clan", Clan
                        ReplaceAttr stmp, "$flags_dec", Flags
                        ReplaceAttr stmp, "$flags_raw", LongToHex(Flags)
                        ReplaceAttr stmp, "$flags", FlagsToStr(Flags)
                        ReplaceAttr stmp, "$ping", Ping
                        ReplaceAttr stmp, "$client_raw", StrReverse$(Left$(Message, 4))
                        ReplaceAttr stmp, "$client", ProductToStr(StrReverse$(Left$(Message, 4)))
                        ReplaceAttr stmp, "$channel", Message
                        ReplaceAttr stmp, "$chflags_raw", LongToHex(Flags)
                        ReplaceAttr stmp, "$chflags_dec", Flags
                        ReplaceAttr stmp, "$chflags", ChanFlagsToStr(Flags)
                        ReplaceAttr stmp, "$rank", urank
                        ReplaceAttr stmp, "$crank", cRank
                        ReplaceAttr stmp, "$stats", Stats
                        ReplaceAttr stmp, "$user", GA
                        ReplaceAttr stmp, "$uptime", Uptime
                        ReplaceAttr stmp, "$message", Message
                        ReplaceAttr stmp, "$extra", Extra
                        'Replace Special Characters Again
                        stmp = Replace$(stmp, "§", "[")
                        stmp = Replace$(stmp, "ª", "]")
                        stmp = Replace$(stmp, "Ø", ",")
                        stmp = Replace$(stmp, "¬", "#")
                        'append part of string
                        OutputPart rtb, lcol, stmp, Not talk
                        'clear buffer
                        Buf = vbNS
                    End If
                End If
            Loop
        End If
NextItem:
    Next
    'finally newline
60  OutputPart rtb, 0, vbNewLine
Exit Sub
hErr:
    ErrorHandler Err.Number, Err.Description, Erl, "Styles", "OutputFocus"
End Sub

Public Sub ReplaceAttr(ByRef stmp As String, attr As String, Value As Variant)
On Error GoTo hErr:
    Dim O As Integer
    Dim Pos As Integer, Content As String, br As Integer, br2 As Integer, Values() As String, ea() As String, E As Integer, Found As Boolean
    O = 1
1   Pos = InStr(O, stmp, attr)
    If Pos = 0 Then
2       stmp = Replace$(stmp, attr, Value)
    Else
3       While Pos <> 0
            'Get Start Bracket
4           If Mid$(stmp, Pos + Len(attr), 1) = "[" Then
5               Content = Mid$(stmp, Pos + Len(attr) + 1)
                
                'Get End Bracket
6               br2 = InStr(Pos + Len(attr) + 1, stmp, "]") + 1
7               br = InStr(Content, "]")
8               If br <> 0 Then
                    'Get Content Within
9                   Content = Left$(Content, br - 1)
                    'Check for Commas
10                  If InStr(Content, ",") Then
                        'Split by Comma
11                      Values = Split(Content, ",")
                        'Check Bounds
12                      If UBound(Values) = 2 Then
                            'Check for Multiple Values
13                          If InStr(Values(0), "|") <> 0 Then
14                              ea = Split(Values(0), "|")
15                              For E = 0 To UBound(ea)
16                                If ea(E) = Value Then
                                        Found = True
                                        Exit For
                                    End If
                                Next
                                If Found Then
                                    'show values(1)
17                                  stmp = Left$(stmp, Pos - 1) & Replace$(Values(1), "value", Value) & Mid$(stmp, br2)
                                Else
                                    'show values(2)
18                                  stmp = Left$(stmp, Pos - 1) & Replace$(Values(2), "value", Value) & Mid$(stmp, br2)
                                End If
                                O = br2
                            Else
                                If Values(0) = Value Then
                                    'show values(1)
19                                  stmp = Left$(stmp, Pos - 1) & Replace$(Values(1), "value", Value) & Mid$(stmp, br2)
                                Else
                                    'show values(2)
20                                  stmp = Left$(stmp, Pos - 1) & Replace$(Values(2), "value", Value) & Mid$(stmp, br2)
                                End If
                                O = br2
                            End If
                        Else
                            O = Len(stmp)
                        End If
                    Else
                        O = Len(stmp)
                    End If
                Else
                    O = Len(stmp)
                End If
            Else
                stmp = Left$(stmp, Pos - 1) & Value & Mid$(stmp, Pos + Len(attr))
                'stmp = Replace$(stmp, attr, value)
                O = Len(stmp)
            End If
            Pos = InStr(O, stmp, attr)
        Wend
    End If
    Exit Sub
hErr:
    ErrorHandler Err.Number, Err.Description, Erl, "Styles", "ReplaceAttr"
End Sub

Public Sub Output(rtb As RichTextBox, EID As Long, _
        Optional Username As String = vbNS, _
        Optional Message As String = vbNS, _
        Optional Flags As Long = 0, _
        Optional Ping As Long = 0, _
        Optional Uptime As String = 0, _
        Optional Extra As String = vbNS)
On Error GoTo hErr:
    If options.AutoLockAll Then Exit Sub
1   If frmBot.Bot(rtb.Index).IsLocked Then Exit Sub
    Dim ucol As Long, urank As String, xfind As Integer, xdb As objDbUser, cRank As String
    'get user color value
    If LenB(Username) Then
2       ucol = GetUserColor(rtb.Index, Username, Flags, True)
        urank = GetAccess2(Username, rtb.Index).RankName
7       xfind = frmBot.Bot(rtb.Index).Clan.Find(Username)
8       If xfind <> -1 Then cRank = ClanRankToString(frmBot.Bot(rtb.Index).Clan.GetByIndex(xfind).Rank)
        Dim ServName As String
        If IsOnGateway(Username) Then
            ServName = Mid$(Username, InStrRev(Username, "@") + 1)
        Else
            ServName = frmBot.Bot(rtb.Index).Config.ServerName
        End If
        Dim GA As String
        GA = Alias.GetAlias(Username, ServName)
        If LenB(GA) = 0 Then GA = Username
    End If
    'output time first
9   OutputTime rtb
    'loop thru chat event strings
    Dim I As Integer, lcol As Long
10  For I = 0 To UBound(ChatEvent)
        'found eid
11      If ChatEvent(I).ce_eid = EID Then
            Dim Clan As String, UI As Integer
            Dim Buf As String, ssharp As Long, esharp As Long, scol As String, slen As Long, talk As Boolean
            'get talk bool
12          talk = (EID = EID_TALK Or EID = EID_WHISPER Or EID = EID_WHISPERSENT Or EID = EID_EMOTE Or EID = &HA2 Or EID = &HA3 Or EID = &HA4)
            'get buf
13          Buf = ChatEvent(I).ce_string
14          Buf = Replace$(Buf, "[#]", "¬")
15          Buf = Replace$(Buf, "[]]", "§")
16          Buf = Replace$(Buf, "[[]", "ª")
17          Buf = Replace$(Buf, "[,]", "Ø")
18          Do Until Len(Buf) = 0
                'get first sharp
19              ssharp = InStr(1, Buf, "#")
20              If ssharp = 0 Then GoTo DoOutput:
                'get next sharp
21              esharp = InStr(ssharp + 1, Buf, "#")
22              If esharp = 0 Then GoTo DoOutput:
                'get color name
23              scol = Mid$(Buf, ssharp + 1, esharp - ssharp - 1)
                'get len for later
24              slen = InStr(esharp + 1, Buf, "#")
                'check if the color == #ucol#
25              If UCase$(scol) = "UCOL" Then
                    'get usercolor is not -1
26                  If ucol <> -1 Then lcol = ucol
                Else
                    'get chatcolor
27                  lcol = GetChatColor(scol)
                End If
DoOutput:
                Dim stmp As String, Stats As String
                'check length
                If slen > 0 Then
                    'get part
28                  stmp = Mid$(Buf, esharp + 1, slen - esharp - 1)
29                  Stats = DisplayStatInfo(Message)
30                  If LenB(Stats) = 0 Then
31                      If Left$(Message, 4) = "VD2D" Or Left$(Message, 4) = "PX2D" Then
32                          Stats = "open char"
                        Else
33                          Stats = "no stats"
                        End If
                    End If
                    'replace vars
34                  Clan = ExtractClanName(Message)
35                  If LenB(Clan) = 0 Then
36                      UI = frmBot.Bot(rtb.Index).Users.Find(Username)
37                      If UI > -1 Then
38                          Clan = ExtractClanName(frmBot.Bot(rtb.Index).Users.GetByIndex(UI).Statstring)
                        End If
                    End If
39                  ReplaceAttr stmp, "$clan", Clan
40                  ReplaceAttr stmp, "$flags_dec", Flags
41                  ReplaceAttr stmp, "$flags_raw", LongToHex(Flags)
42                  ReplaceAttr stmp, "$flags", FlagsToStr(Flags)
43                  ReplaceAttr stmp, "$ping", Ping
44                  ReplaceAttr stmp, "$client_raw", StrReverse$(Left$(Message, 4))
45                  ReplaceAttr stmp, "$client", ProductToStr(StrReverse$(Left$(Message, 4)))
46                  ReplaceAttr stmp, "$channel", Message
47                  ReplaceAttr stmp, "$chflags_raw", LongToHex(Flags)
48                  ReplaceAttr stmp, "$chflags_dec", Flags
49                  ReplaceAttr stmp, "$chflags", ChanFlagsToStr(Flags)
50                  ReplaceAttr stmp, "$rank", urank
51                  ReplaceAttr stmp, "$crank", cRank
52                  ReplaceAttr stmp, "$stats", Stats
                    ReplaceAttr stmp, "$user", GA
54                  ReplaceAttr stmp, "$uptime", Uptime
55                  ReplaceAttr stmp, "$message", Message
                    ReplaceAttr stmp, "$extra", Extra
                    'Replace Special Characters Again
56                  stmp = Replace$(stmp, "§", "[")
57                  stmp = Replace$(stmp, "ª", "]")
58                  stmp = Replace$(stmp, "Ø", ",")
59                  stmp = Replace$(stmp, "¬", "#")
                    'append part of string
60                  OutputPart rtb, lcol, stmp, Not talk
                    'advance buffer
61                  Buf = Mid$(Buf, slen)
                Else
                    'check for more # chars
62                  If InStrB(Mid$(Buf, esharp + 1), "#") <> 0 Then
                        'skip to last #
63                      Buf = Mid$(Buf, esharp + 1)
                        'goto next part
                        GoTo NextItem:
                    Else
                        'get part
64                      stmp = Mid$(Buf, esharp + 1)
65                      Stats = DisplayStatInfo(Message)
66                      If LenB(Stats) = 0 Then
67                          If Left$(Message, 4) = "VD2D" Or Left$(Message, 4) = "PX2D" Then
68                              Stats = "open char"
                            Else
69                              Stats = "no stats"
                            End If
                        End If
                        'replace vars
70                      Clan = ExtractClanName(Message)
71                      If LenB(Clan) = 0 Then
72                          UI = frmBot.Bot(rtb.Index).Users.Find(Username)
73                          If UI > -1 Then
74                              Clan = ExtractClanName(frmBot.Bot(rtb.Index).Users.GetByIndex(UI).Statstring)
                            End If
                        End If
75                      ReplaceAttr stmp, "$clan", Clan
76                      ReplaceAttr stmp, "$flags_dec", Flags
77                      ReplaceAttr stmp, "$flags_raw", LongToHex(Flags)
78                      ReplaceAttr stmp, "$flags", FlagsToStr(Flags)
79                      ReplaceAttr stmp, "$ping", Ping
80                      ReplaceAttr stmp, "$client_raw", StrReverse$(Left$(Message, 4))
81                      ReplaceAttr stmp, "$client", ProductToStr(StrReverse$(Left$(Message, 4)))
82                      ReplaceAttr stmp, "$channel", Message
83                      ReplaceAttr stmp, "$chflags_raw", LongToHex(Flags)
84                      ReplaceAttr stmp, "$chflags_dec", Flags
85                      ReplaceAttr stmp, "$chflags", ChanFlagsToStr(Flags)
86                      ReplaceAttr stmp, "$rank", urank
87                      ReplaceAttr stmp, "$crank", cRank
88                      ReplaceAttr stmp, "$stats", Stats
89                      ReplaceAttr stmp, "$user", GA
90                      ReplaceAttr stmp, "$uptime", Uptime
91                      ReplaceAttr stmp, "$message", Message
                        ReplaceAttr stmp, "$extra", Extra
                        'Replace Special Characters Again
92                      stmp = Replace$(stmp, "§", "[")
93                      stmp = Replace$(stmp, "ª", "]")
94                      stmp = Replace$(stmp, "Ø", ",")
95                      stmp = Replace$(stmp, "¬", "#")
                        'append part of string
96                      OutputPart rtb, lcol, stmp, Not talk
                        'clear buffer
                        Buf = vbNS
                    End If
                End If
            Loop
        End If
NextItem:
    Next
    'finally newline
97  OutputPart rtb, 0, vbNewLine
Exit Sub
hErr:
    ErrorHandler Err.Number, Err.Description, Erl, "Styles", "Output"
End Sub
