Sign in to follow this  
Followers 0
E1M1

Need help with syntax highlighting using scintilla (I use UDF) control [How to make my window highlight style.conf.8?]

3 posts in this topic

#1 ·  Posted (edited)

Hello

I am trying to make scite like window that would highlight syntax. I am currently using scintilla to do this. Here's is my full project Click to download . I am trying to make make it highlight IP address, But I cant find how. I copied IP highlighting from conf.properties, but I cant find way to make my script do anything with style.conf.8.

SciteInclude.au3

LoadHighlight($hwnd, $file) is what does highlighting I would like some one to tell mee what I need to edit in this function.

#include-once
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include "Scintilla.h.au3"
Global Const $MARGIN_SCRIPT_FOLD_INDEX = 1
Dim $sci, $_FILENAME
Global $default_style = "0x000000,0xFFFFFF,10,Courier New,0,0,0"

; Generic error handler for DllCall
Func errDllCall($err, $ext, $erl = @ScriptLineNumber)
    Local $ret = 0

    If $err <> 0 Then
        ConsoleWrite("(" & $erl & ") := @error:=" & $err & ", @extended:=" & $ext & @LF)
        $ret = 1
    EndIf
    Return $ret
EndFunc   ;==>errDllCall

; API Wraper function
Func CreateWindowEx($dwExStyle, $lpClassName, $lpWindowName = "", $dwStyle = -1, $x = 0, $y = 0, $nWidth = 0, $nHeight = 0, $hwndParent = 0, $hMenu = 0, $hInstance = 0, $lParm = 0)
    Local $ret
    If $hInstance = 0 Then
        ;TODO: Do we need to provide the instance handle?
        $ret = DllCall("user32.dll", "long", "GetWindowLong", "hwnd", $hwndParent, "int", -6); $GWL_HINSTANCE=-6
        $hInstance = $ret[0]
    EndIf
    $ret = DllCall("user32.dll", "hwnd", "CreateWindowEx", "long", $dwExStyle, _
            "str", $lpClassName, "str", $lpWindowName, _
            "long", $dwStyle, "int", $x, "int", $y, "int", $nWidth, "int", $nHeight, _
            "hwnd", $hwndParent, "hwnd", $hMenu, "long", $hInstance, "ptr", $lParm)
    If errDllCall(@error, @extended) Then Exit
    Return $ret[0]
EndFunc   ;==>CreateWindowEx

; API Wraper function
Func LoadLibrary($lpFileName)
    Local $ret
    $ret = DllCall("kernel32.dll", "int", "LoadLibrary", "str", $lpFileName)
    If errDllCall(@error, @extended) Then Exit
    Return $ret[0]
EndFunc   ;==>LoadLibrary

; API Wraper function
Func SendMessage($hwnd, $msg, $wp, $lp)
    Local $ret
    $ret = DllCall("user32.dll", "long", "SendMessageA", "long", $hwnd, "long", $msg, "long", $wp, "long", $lp)
    Return $ret[0]
EndFunc   ;==>SendMessage

; API Wraper function
Func SendMessageString($hwnd, $msg, $wp, $str)
    Local $ret
    ; TODO: VB Any translated to ptr ???
    $ret = DllCall("user32.dll", "long", "SendMessageA", "long", $hwnd, "long", $msg, "long", $wp, "str", $str)
    Return $ret[0]
EndFunc   ;==>SendMessageString

; API Wraper function
Func SetWindowPos($hwnd, $style, $left, $top, $width, $height, $flags)
    ;TODO: Verify implementation.
    Local $ret
    $ret = DllCall("user32.dll", "long", "SetWindowPos", "long", $hwnd, "long", $style, _
            "long", $left, "long", $top, "long", $width, "long", $height, _
            "long", $flags)
    If errDllCall(@error, @extended) Then Exit
    Return $ret[0]
EndFunc   ;==>SetWindowPos

Func LoadHighlight($hwnd, $file)
    If Not FileExists($file) Then
        MsgBox(16, "Error", "The highlighter file " & $file & " does not exist!")
        Return
    EndIf

    $cmdrun = IniRead($file, "", "run", "")
    $cmdbuild = IniRead($file, "", "build", "")
    $cmdcompile = IniRead($file, "", "compile", "")
    SetStyle($hwnd, $STYLE_DEFAULT, IniRead($file, "", "DefaultStyle", $default_style))
    SendMessageString($hwnd, $SCI_STYLECLEARALL, 0, 0)

    SendMessageString($hwnd, $SCI_SETLEXER, IniRead($file, "", "lex", 0), 0)
    $bits = SendMessageString($hwnd, $SCI_GETSTYLEBITSNEEDED, 0, 0)
    SendMessageString($hwnd, $SCI_SETSTYLEBITS, $bits, 0)

    $inif = FileRead($file)
    $arr = StringRegExp($inif, "(?m)^style([0-9]+)=(.*)", 3)
    For $i = 0 To UBound($arr) - 1 Step 2
        SetStyle($hwnd, $arr[$i], $arr[$i + 1])
    Next

    $arr = StringRegExp($inif, "(?m)(?s)(?U)^words([0-9]+)=(.*)\r\n\r\n", 3)
    For $i = 0 To UBound($arr) - 1 Step 2
        SendMessageString($hwnd, $SCI_SETKEYWORDS, $arr[$i], $arr[$i + 1])
    Next
EndFunc   ;==>LoadHighlight

Func SetStyle($hwnd, $style, $styletxt)
    $astyle = StringSplit($styletxt, ",")

    If UBound($astyle) < 8 Then
        ;MsgBox(16,"Warning","Incomplete style definition, skipping..."&@CRLF&$styletxt)
        Return
    EndIf

    SendMessage($hwnd, $SCI_STYLESETFORE, $style, $astyle[1])
    SendMessage($hwnd, $SCI_STYLESETBACK, $style, $astyle[2])
    If $astyle[3] >= 1 Then
        SendMessage($hwnd, $SCI_STYLESETSIZE, $style, $astyle[3])
    EndIf
    If $astyle[4] <> '' Then
        SendMessageString($hwnd, $SCI_STYLESETFONT, $style, $astyle[4])
    EndIf
    SendMessage($hwnd, $SCI_STYLESETBOLD, $style, $astyle[5])
    SendMessage($hwnd, $SCI_STYLESETITALIC, $style, $astyle[6])
    SendMessage($hwnd, $SCI_STYLESETUNDERLINE, $style, $astyle[7])
EndFunc   ;==>SetStyle

Func ShowLineNumbers($hwnd, $yn = True)
    $show_line_numbers = $yn
    If Not $yn Then
        SendMessage($hwnd, $SCI_SETMARGINWIDTHN, 0, 0)
    Else
        $pixelWidth = SendMessageString($hwnd, $SCI_TEXTWIDTH, $STYLE_LINENUMBER, "99999")
        SendMessage($hwnd, $SCI_SETMARGINWIDTHN, 0, $pixelWidth)
    EndIf
EndFunc   ;==>ShowLineNumbers

Func ShowFolds($hwnd, $yn = True)
    $show_folds = $yn
    If Not $yn Then
        SendMessage($hwnd, $SCI_SETMARGINWIDTHN, $MARGIN_SCRIPT_FOLD_INDEX, 0)
    Else
        SendMessage($hwnd, $SCI_SETMARGINWIDTHN, $MARGIN_SCRIPT_FOLD_INDEX, 20);
    EndIf
EndFunc   ;==>ShowFolds

Func WM_NOTIFY($hWndGUI, $MsgID, $wParam, $lParam)
    #forceref $hWndGUI, $MsgID, $wParam
    Local $tagNMHDR, $event
    ;$tagNMHDR = DllStructCreate("int;int;int", $lParam);NMHDR (hwndFrom, idFrom, code)
    $tagNMHDR = DllStructCreate("int;int;int;int;int;int;int;ptr;int;int;int;int;int;int;int;int;int;int;int", $lParam)
    If @error Then Return

    $hwndFrom = DllStructGetData($tagNMHDR, 1)
    $idFrom = DllStructGetData($tagNMHDR, 2)
    $event = DllStructGetData($tagNMHDR, 3)
    $position = DllStructGetData($tagNMHDR, 4)
    $ch = DllStructGetData($tagNMHDR, 5)
    $modifiers = DllStructGetData($tagNMHDR, 6)
    $modificationType = DllStructGetData($tagNMHDR, 7)
    $char = DllStructGetData($tagNMHDR, 8)
    $length = DllStructGetData($tagNMHDR, 9)
    $linesAdded = DllStructGetData($tagNMHDR, 10)
    $message = DllStructGetData($tagNMHDR, 11)
    $uptr_t = DllStructGetData($tagNMHDR, 12)
    $sptr_t = DllStructGetData($tagNMHDR, 13)
    $line = DllStructGetData($tagNMHDR, 14)
    $foldLevelNow = DllStructGetData($tagNMHDR, 15)
    $foldLevelPrev = DllStructGetData($tagNMHDR, 16)
    $margin = DllStructGetData($tagNMHDR, 17)
    $listType = DllStructGetData($tagNMHDR, 18)
    $x = DllStructGetData($tagNMHDR, 19)
    $y = DllStructGetData($tagNMHDR, 20)
    $line_number = SendMessage($sci, $SCI_LINEFROMPOSITION, $position, 0)
    Select
        Case $hwndFrom = $sci
            Select
                Case $event = $SCN_MARGINCLICK
                    SendMessage($sci, $SCI_TOGGLEFOLD, $line_number, 0)
            EndSelect
    EndSelect
    $tagNMHDR = 0
    $event = 0
    $lParam = 0
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func SetProperty($hwnd, $property, $value)
    Local $ret
    If IsInt($property) Then
        $prop_type = "int"
    ElseIf IsString($property) Then
        $prop_type = "str"
    EndIf

    If IsInt($value) Then
        $val_type = "int"
    ElseIf IsString($value) Then
        $val_type = "str"
    EndIf

    $ret = DllCall("user32.dll", "int", "SendMessageA", "hwnd", $hwnd, "int", $SCI_SETPROPERTY, $prop_type, $property, $val_type, $value)
    Return $ret[0]
EndFunc   ;==>SetProperty

Func InitFolds($hwnd)
    SetProperty($hwnd, "fold", "1")
    SetProperty($hwnd, "fold.compact", "1")
    SetProperty($hwnd, "fold.comment", "1")
    SetProperty($hwnd, "fold.preprocessor", "1")
    SendMessage($hwnd, $SCI_SETMARGINTYPEN, $MARGIN_SCRIPT_FOLD_INDEX, $SC_MARGIN_SYMBOL)
    SendMessage($hwnd, $SCI_SETMARGINMASKN, $MARGIN_SCRIPT_FOLD_INDEX, $SC_MASK_FOLDERS)
    SendMessage($hwnd, $SCI_MARKERDEFINE, $SC_MARKNUM_FOLDER, $SC_MARK_BOXPLUS)
    SendMessage($hwnd, $SCI_MARKERDEFINE, $SC_MARKNUM_FOLDEROPEN, $SC_MARK_BOXMINUS)
    SendMessage($hwnd, $SCI_MARKERDEFINE, $SC_MARKNUM_FOLDEREND, $SC_MARK_BOXPLUSCONNECTED)
    SendMessage($hwnd, $SCI_MARKERSETBACK, $SC_MARKNUM_FOLDEREND, "0xFFCCFF")
    SendMessage($hwnd, $SCI_MARKERDEFINE, $SC_MARKNUM_FOLDERMIDTAIL, $SC_MARK_LCORNER)
    SendMessage($hwnd, $SCI_MARKERSETBACK, $SC_MARKNUM_FOLDERMIDTAIL, "0xFFCCFF")
    SendMessage($hwnd, $SCI_MARKERDEFINE, $SC_MARKNUM_FOLDEROPENMID, $SC_MARK_BOXMINUSCONNECTED)
    SendMessage($hwnd, $SCI_MARKERSETBACK, $SC_MARKNUM_FOLDEROPENMID, "0xFFCCFF")
    SendMessage($hwnd, $SCI_MARKERDEFINE, $SC_MARKNUM_FOLDERSUB, $SC_MARK_VLINE)
    SendMessage($hwnd, $SCI_MARKERSETBACK, $SC_MARKNUM_FOLDERSUB, "0xFFCCFF")
    SendMessage($hwnd, $SCI_MARKERDEFINE, $SC_MARKNUM_FOLDERTAIL, $SC_MARK_LCORNER)
    SendMessage($hwnd, $SCI_MARKERSETBACK, $SC_MARKNUM_FOLDERTAIL, "0xFFCCFF")
    SendMessage($hwnd, $SCI_SETFOLDFLAGS, 16, 0)
    SendMessage($hwnd, $SCI_SETMARGINSENSITIVEN, 1, 1)
    ShowFolds($hwnd)
EndFunc   ;==>InitFolds

Func CreateSciTE($parent, $left, $top, $width, $height, $linenumbers = True, $folds = True, $whitespaces = False, $tab_width = 4)
    Local $GWL_HINSTANCE = -6
    Local $sci
    Local $hLib = LoadLibrary("SciLexer.DLL")

    Local $hInstance = 0
    $sci = CreateWindowEx($WS_EX_CLIENTEDGE, "Scintilla", _
            "TEST", BitOR($WS_CHILD, $WS_VISIBLE), $left, $top, $width, $height, _
            $parent, 0, $hInstance, 0)
    SetWindowPos($sci, 0, $left, $top, $width, $height, 0)
    GUIRegisterMsg(0x004E, "WM_NOTIFY")
    LoadHighlight($sci, @ScriptDir & "\highlight.properties")
    ShowLineNumbers($sci, $linenumbers)
    InitFolds($sci)
    ShowFolds($sci, $folds)
    ShowWhitespaces($sci, $whitespaces)
    SendMessage($sci, $SCI_SETTABWIDTH, $tab_width, 0)
    SetStyle($sci, $STYLE_LINENUMBER, "0x000000,0xA8A8A8,10,Courier New,0,0,0")

    ClearCmdKey($sci, 0x47, $SCMOD_CTRL);unbind the default ctrl+g action
    ClearCmdKey($sci, 0x4E, $SCMOD_CTRL);unbind the default ctrl+n action
    ClearCmdKey($sci, 0x4F, $SCMOD_CTRL);unbind the default ctrl+o action
    ClearCmdKey($sci, 0x53, $SCMOD_CTRL);unbind the default ctrl+s action
    ClearCmdKey($sci, 0x46, $SCMOD_CTRL);unbind the default ctrl+f action
    ClearCmdKey($sci, 0x53, $SCMOD_SHIFT);unbind the default shift+s action
    ClearCmdKey($sci, 0x46, $SCMOD_SHIFT);unbind the default shift+f action

    Return $sci
EndFunc   ;==>CreateSciTE

Func OpenFile($hwnd)
    If SendMessage($hwnd, $SCI_GETMODIFY, 0, 0) <> 0 Then
        $ans = MsgBox(3 + 32, "Confirm", "Do you want to save your changes to this file?")
        Switch $ans
            Case 2 ; cancel
                Return
            Case 6 ;yes
                SaveFile($hwnd, $_FILENAME)
        EndSwitch
    EndIf

    $from = FileOpenDialog("Open file...", "", "All files (*.*)")
    If $from = '' Then
        Return False
    EndIf
    $_FILENAME = $from

    SendMessage($hwnd, $SCI_CLEARALL, 0, 0)
    SendMessage($hwnd, $SCI_EMPTYUNDOBUFFER, 0, 0)
    SendMessage($hwnd, $SCI_SETSAVEPOINT, 0, 0)
    SendMessage($hwnd, $SCI_CANCEL, 0, 0)
    SendMessage($hwnd, $SCI_SETUNDOCOLLECTION, 0, 0)

    ;DetectHighlighter($_FILENAME)
    $file = FileOpen($from, 0)
    While 1
        $buffer = FileRead($file, 1024)
        If @error = -1 Then ExitLoop
        SendMessageString($hwnd, $SCI_APPENDTEXT, StringLen($buffer), $buffer)
    WEnd
    FileClose($file)
    SendMessage($hwnd, $SCI_SETUNDOCOLLECTION, 1, 0)
    SendMessage($hwnd, $SCI_EMPTYUNDOBUFFER, 0, 0)
    SendMessage($hwnd, $SCI_SETSAVEPOINT, 0, 0)
    SendMessage($hwnd, $SCI_GOTOPOS, 0, 0)
    Return $_FILENAME
EndFunc   ;==>OpenFile

Func SaveFile($hwnd, $fn = "")
    If $fn = '' Then
        $fn = FileSaveDialog("Save file...", "", "All files (*.*)")
    EndIf

    If $fn <> '' Then
        $_FILENAME = $fn
        $len = SendMessage($hwnd, $SCI_GETLENGTH, 0, 0)
        $text = DllStructCreate("char[" & $len & "]")
        DllCall("user32.dll", "int", "SendMessageA", "hwnd", $hwnd, "int", $SCI_GETTEXT, "int", $len + 1, "ptr", DllStructGetPtr($text))
        ;MsgBox(0,0,DllStructGetData($text,1))
        $handle = FileOpen($_FILENAME, 2)
        FileWrite($handle, DllStructGetData($text, 1))
        FileClose($handle)
        $text = 0
        SendMessageString($hwnd, $SCI_SETUNDOCOLLECTION, 1, 0)
        SendMessageString($hwnd, $SCI_EMPTYUNDOBUFFER, 0, 0)
        SendMessageString($hwnd, $SCI_SETSAVEPOINT, 0, 0)
        Return True
    Else
        Return False
    EndIf
EndFunc   ;==>SaveFile

Func SciAddText($hwnd, $text)
    SendMessageString($hwnd, $SCI_ADDTEXT, StringLen($text), $text)
EndFunc   ;==>SciAddText

Func SciAppendText($hwnd, $text)
    SendMessageString($hwnd, $SCI_APPENDTEXT, StringLen($text), $text)
EndFunc   ;==>SciAppendText

Func SciGetCurrentPos($hwnd)
    Return SendMessage($hwnd, $SCI_GETCURRENTPOS, 0, 0)
EndFunc   ;==>SciGetCurrentPos

Func SciGetTextLen($hwnd)
    Return SendMessage($hwnd, $SCI_GETLENGTH, 0, 0)
EndFunc   ;==>SciGetCurrentPos

Func SciSetCurrentPos($hwnd, $x1, $x2)
    SendMessage($hwnd, $SCI_SETSELECTIonstart, $x1, 0)
    SendMessage($hwnd, $SCI_SETSELECTIonend, $x2, 0)
EndFunc   ;==>SciSetCurrentPos

Func SciGetText($hwnd)
    $len = SendMessage($hwnd, $SCI_GETLENGTH, 0, 0)
    $text = DllStructCreate("char[" & $len & "]")
    DllCall("user32.dll", "int", "SendMessageA", "hwnd", $hwnd, "int", $SCI_GETTEXT, "int", $len + 1, "ptr", DllStructGetPtr($text))
    Return DllStructGetData($text, 1)
EndFunc   ;==>SciGetText

Func SciClearAll($hwnd)
    SendMessageString($hwnd, $SCI_CLEARALL, 0, 0)
    SendMessage($hwnd, $SCI_EMPTYUNDOBUFFER, 0, 0)
    SendMessage($hwnd, $SCI_SETSAVEPOINT, 0, 0)
EndFunc   ;==>SciClearAll

Func GoToLine()
    $line = InputBox("Go to line", "Enter line number:", "", "", -1, 150)
    If StringIsInt($line) Then
        SendMessage($sci, $SCI_ENSUREVISIBLEENFORCEPOLICY, $line, 0);
        SendMessage($sci, $SCI_GOTOLINE, $line, 0)
    EndIf
EndFunc   ;==>GoToLine

Func ClearCmdKey($sci, $keycode, $modifier = 0)
    Return SendMessage($sci, $SCI_CLEARCMDKEY, BitShift($modifier, -16) + $keycode, 0);
EndFunc   ;==>ClearCmdKey

Func ShowWhitespaces($hwnd, $yn = False)
    $show_whitespaces = $yn
    If $yn Then
        SendMessage($hwnd, $SCI_SETVIEWWS, 1, 0)
    Else
        SendMessage($hwnd, $SCI_SETVIEWWS, 0, 0)
    EndIf
EndFunc   ;==>ShowWhitespaces

Here's highlight.properties

I added this to my properties file

# whitespace (SCE_CONF_DEFAULT)
style.conf.0=fore:#808080,$(font.base)
# Comment (SCE_CONF_COMMENT)
style.conf.1=fore:#007F00,$(font.comment)
# Number (SCE_CONF_NUMBER)
style.conf.2=fore:#007F7F
# identifier (SCE_CONF_IDENTIFIER)
style.conf.9=fore:#00007F,bold
# extensions (like .gz, .tgz, .html) (SCE_CONF_EXTENSION)
style.conf.4=fore:#000000,back:#FFE0FF
# parameters for Apache Runtime directives (SCE_CONF_PARAMETER)
style.conf.5=fore:#000000,back:#FFE0FF
# Double quoted string (SCE_CONF_STRING)
style.conf.6=fore:#7F007F,$(font.monospace)
# Operators (SCE_CONF_OPERATOR)
style.conf.7=bold
# IP address (SCE_CONF_IP)
style.conf.8=fore:#007F7F,bold
# Apache Runtime Directive (SCE_CONF_DIRECTIVE)
style.conf.3=fore:#000000,back:#A0FFA0

Full .properties file is here.

[]
name=AutoIt syntax highlighter
author=lokster
ext=.au3
lex=60
DefaultStyle=0x000000,0xFFFFFF,10,Courier New,0,0,0

words1= info

words7= debug

words0=and byref case const continuecase continueloop default dim
    do else elseif endfunc endif endselect endswitch endwith enum exit exitloop false
    for func global if in local next not or redim return select step switch then to true
    until wend while with downloading reloading UDP

words2=@appdatacommondir

words4=plugin

words5=start end

words6= error

style.conf.8=$(font.base)
style0=0x000000,0xFFFFFF,10,Courier New,0,0,0
style1=0x339900,0xFFFFFF,10,Courier New,0,0,0
style2=0x009966,0xFFFFFF,10,Courier New,0,0,0
style3=0xA933AC,0xFFFFFF,10,Courier New,1,0,0
style4=0xAA0000,0xFFFFFF,10,Courier New,1,1,0
style5=0xFF0000,0xFFFFFF,10,Courier New,1,0,0
style6=0xBBBBBB,0xFFFFFF,10,Courier New,1,0,0
style7=0xCC9999,0xFFFFFF,10,Courier New,1,0,0
style8=0x0000FF,0xFFFFFF,10,Courier New,1,0,0
style9=0x000090,0xFFFFFF,10,Courier New,1,0,0
style10=0x0080FF,0xFFFFFF,10,Courier New,1,0,0
style11=0x00c000,0xFFFFFF,10,Courier New,0,0,0
style12=0xF00FA0,0xFFFFFF,10,Courier New,0,1,0
style13=0x0000FF,0xFFFFFF,10,Courier New,1,0,0
style14=0xFF0000,0xFFFFFF,10,Courier New,1,1,0
style15=0xFF8000,0xFFFFFF,10,Courier New,1,1,0

# whitespace (SCE_CONF_DEFAULT)
style.conf.0=fore:#808080,$(font.base)
# Comment (SCE_CONF_COMMENT)
style.conf.1=fore:#007F00,$(font.comment)
# Number (SCE_CONF_NUMBER)
style.conf.2=fore:#007F7F
# identifier (SCE_CONF_IDENTIFIER)
style.conf.9=fore:#00007F,bold
# extensions (like .gz, .tgz, .html) (SCE_CONF_EXTENSION)
style.conf.4=fore:#000000,back:#FFE0FF
# parameters for Apache Runtime directives (SCE_CONF_PARAMETER)
style.conf.5=fore:#000000,back:#FFE0FF
# Double quoted string (SCE_CONF_STRING)
style.conf.6=fore:#7F007F,$(font.monospace)
# Operators (SCE_CONF_OPERATOR)
style.conf.7=bold
# IP address (SCE_CONF_IP)
style.conf.8=fore:#007F7F,bold
# Apache Runtime Directive (SCE_CONF_DIRECTIVE)
style.conf.3=fore:#000000,back:#A0FFA0

But I cant find way to make scite control highlight style.conf.8

Edited by E1M1

edited

Share this post


Link to post
Share on other sites



bump


edited

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

bump, firt topic edited to make it easier to follow

Edited by E1M1

edited

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0