Greetings!!

Just starting out? Need help? Post your questions and find answers here.
DARKGuy
User
User
Posts: 40
Joined: Thu Mar 11, 2004 10:08 pm
Contact:

Greetings!!

Post by DARKGuy »

I'm a bit newbie to PureBASIC, and a total newbie on this forum :). I've been making an image converter and I've learned a lot of things, but I've been wondering on how to make a syntax highlighting editor in PB. I've downloaded "Editor.Zip" fron the PB web page and it doesn't compile with my version (I downloaded and applied the 3.81 update!), it's always throwing errors about duplicated declarations and things like that. So I was wondering if anyone could give me some simple code to at least show me how to highlight a simple command...I don't know...something like this:

Code: Select all

Global command$="goto"
if Openwindow(...)
  EditorGadget(...)
  CheckSyntax() ;just a sample function
  if TheWord=command$
    ;don't know...something for colouring the text
  endif
endif
Of course I could try to read carefully the "SyntaxHighlighting.pb" but it's like a maze, because it includes some other .pb files and those contain code for the syntax highlighting functions and other functions, and I don't know what variables or functions the "SyntaxHighlighting.pb" uses, or how are they linked, you know, i'm lost...

I want just a simple example to work with :)

Thanks in advance :)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Checking syntax and highlighting 'as you type' is a little involved.

The following code will highlight, as you type, any occurrences of the word "test". This might not be the best method for searching for a list of 'keywords' etc. as I have ripped the routine out of a dedicated HTML editor which I have been working upon which involves some rather complicated syntax checking etc.

Code: Select all

Enumeration
  #MainWindow
EndEnumeration

;Gadget enumeration.
Enumeration
  #RichEdit
EndEnumeration

;Font enumeration
Enumeration
  #FontEdit
EndEnumeration

;Declare constants.
Enumeration
  #False
  #True
EndEnumeration

#COLOR_Text = $000000 : #EFFECTS_Text = 0
#COLOR_Symbol = $ff0000 : #EFFECTS_Symbol = #CFE_Italic

;Load fonts.
LoadFont(#FontEdit, "Times New Roman", 12)


;Declare procedures.
Declare HighlightLine(Line)
Declare WindowCallback(hWnd, uMsg, wParam, lParam)

;- Open main window and display gadgets.
OpenWindow(#MainWindow,0,0,400,400,  #PB_Window_Invisible | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget,"") 
ShowWindow_(WindowID(#MainWindow), #SW_maximize)
CreateGadgetList(WindowID(#MainWindow)) 
  EditorGadget (#RichEdit,0,50,3*WindowWidth()/4,WindowHeight()-50)
  SetGadgetFont(#RichEdit, UseFont(#FontEdit))
  SendMessage_(GadgetID(#RichEdit), #EM_SETBKGNDCOLOR, 0, $b6fcf8); Set background colour.
;Allow the trapping of the EN_CHANGE message which occurs after the contents of the editor gadget
;has changed.
  SendMessage_(GadgetID(#RichEdit), #EM_SETEVENTMASK, 0, #ENM_CHANGE)

  ActivateGadget(#RichEdit)
  SetWindowCallback(@WindowCallback())

;Main message loop..
  Repeat
    EventID=WaitWindowEvent()
  Until EventID=#PB_EventCloseWindow



;The following procedure scans the given line of text in the richedit control looking for occurrences of
;the word "test". Such words are coloured and set to italic.
Procedure HighlightLine(Line)
Protected LineText.s, Format.CHARFORMAT, StartPos, Endpos, Left, Right, Flag.b
  LineText = LCase(GetGadgetItemText(#RichEdit, Line,0))
;Get the character index's of both ends of the line.
  StartPos = sendmessage_(GadgetID(#RichEdit),#EM_LINEINDEX, Line,0)
  EndPos = StartPos + Len(LineText)
  Format\cbSize = SizeOf(CHARFORMAT)      
  Format\dwMask = #CFM_COLOR | #CFM_BOLD | #CFM_ITALIC
  Left = StartPos
  Repeat
;Identify possible occurrences of "test".
    Right = FindString(LineText, "test", Left-StartPos+1) + StartPos
    If Right = StartPos;No occurrences found so colour entire line with the default text colour.
      SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, Left, EndPos)
      Format\crTextColor = #COLOR_Text : Format\dwEffects = #EFFECTS_Text
      SendMessage_(GadgetID(#RichEdit), #EM_SETCHARFORMAT, #SCF_SELECTION, @Format)    
      Left = EndPos
    Else
      SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, Left, Right-1)
      Format\crTextColor = #COLOR_Text : Format\dwEffects = #EFFECTS_Text
      SendMessage_(GadgetID(#RichEdit), #EM_SETCHARFORMAT, #SCF_SELECTION, @Format)    
      Left = Right-1 : Right + 3
      SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, Left, Right);Highlight the word "test"
      Left = Right
      Format\crTextColor = #COLOR_Symbol : Format\dwEffects = #EFFECTS_Symbol
      SendMessage_(GadgetID(#RichEdit), #EM_SETCHARFORMAT, #SCF_SELECTION, @Format)    
    EndIf
  Until Left = EndPos
EndProcedure


;The following call back procedure is responsible for syntax highlighting etc.
;It does this by intercepting the #EN_CHANGE command message which fires whenever
;text in the rich edit control has changed. We then examine the entire line containing the text.
Procedure WindowCallback(hWnd, uMsg, wParam, lParam)
  Protected ReturnValue, Chr.CHARRANGE, Line, CurrentStartPos
  ReturnValue = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_COMMAND
      If wParam >>16 = #EN_CHANGE And lparam = GadgetID(#RichEdit)
;The following returns the index (0-based) of the line containing the current character.
        Sendmessage_(GadgetID(#RichEdit),#EM_GETSEL,@CurrentStartPos, @Line)
        Line = sendmessage_(GadgetID(#RichEdit),#EM_LINEFROMCHAR, CurrentStartPos,0)
        SendMessage_(GadgetID(#RichEdit), #EM_HIDESELECTION, 1,0)    
        HighlightLine(Line)
        If GetAsyncKeyState_(#VK_return) & 1 = 1;  Bit 0 is set if the enter key was pressed since the last check.
;Investigate the previous line.
            HighlightLine(Line-1)
        EndIf
        SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, CurrentStartPos,CurrentStartPos); Return cursor to its correct position.
        SendMessage_(GadgetID(#RichEdit),#EM_SETMODIFY,0,0)
        SendMessage_(GadgetID(#RichEdit), #EM_HIDESELECTION, 0,0)    
      EndIf
  EndSelect
ProcedureReturn  ReturnValue
EndProcedure
Hope it helps.
I may look like a mule, but I'm not a complete ass.
DARKGuy
User
User
Posts: 40
Joined: Thu Mar 11, 2004 10:08 pm
Contact:

Post by DARKGuy »

Hey srod! that code looks very useful! I'm gonna test it now :). Whoa that HTML editor sounds cool! tell me when it's finished! :). I hope you don't mind if I try to adapt the code you're giving me to my editor :), if you want I can include you in the credits :)

thanks! gonna test it now! :)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Credits should really go to Timo, as it was through dissecting his LibraryDesigner program that I learnt how to use the rich edit functionality of an Editor gadget.

It might be worth you searching out a copy of his program as I certainly found it very useful.
I may look like a mule, but I'm not a complete ass.
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

BTW Welcome to the forums DARKGuy. :D
--Kale

Image
DARKGuy
User
User
Posts: 40
Joined: Thu Mar 11, 2004 10:08 pm
Contact:

Post by DARKGuy »

@srod:
Oh...from timo...all right, I've downloaded it right now but I've not opened the zip file *lol* but anyway...can you help me with this? :)

you know...that code works very good! but when I try to use a For...Next look to check for my own keywords (for now I'm using the keywords that the SyntaxHighlighting.pb uses) it doesn't work :(....sorry for asking too much... :)

Here's the code, the For...Next loop is in the HightlightLine procedure

Code: Select all

Declare HighlightLine(Line) 
Declare WindowCallback(hWnd, uMsg, wParam, lParam) 
Declare InitSyntaxHighlightning()
Dim ValidCharacters.b(255)
Enumeration 
#MainWindow
EndEnumeration 
;Gadget enumeration. 
Enumeration 
#RichEdit
EndEnumeration 
;Font enumeration 
Enumeration 
#FontEdit
EndEnumeration 
#COLOR_Text = $000000 : #EFFECTS_Text = 0 
#COLOR_Symbol = $ff00 : #EFFECTS_Symbol = #CFE_italic
#NbBasicKeywords = 64
If OpenWindow(#MainWindow,0,0,400,400,#PB_Window_Invisible | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget,"") 
  ShowWindow_(WindowID(#MainWindow), #SW_maximize) 
  
  If CreateGadgetList(WindowID(#MainWindow)) 
    If LoadFont(#FontEdit, "Courier New", 10)
      EditorGadget(#RichEdit,0,50,3*WindowWidth()/4,WindowHeight()-50)
      SetGadgetFont(#RichEdit, UseFont(#FontEdit)) 
      SendMessage_(GadgetID(#RichEdit), #EM_SETBKGNDCOLOR, 0, $b6fcf8); Set background colour
    Else
      MessageRequester("Fatal error","Can't open the 'Courier New' font")
    EndIf
  EndIf
  
  SendMessage_(GadgetID(#RichEdit), #EM_SETEVENTMASK, 0, #ENM_CHANGE) 
  ActivateGadget(#RichEdit) 
  SetWindowCallback(@WindowCallback())
  InitSyntaxHighlightning()
  
  ;Main message loop.. 
  Repeat 
    EventID=WaitWindowEvent() 
  Until EventID=#PB_EventCloseWindow 
  
EndIf
Procedure InitSyntaxHighlightning()
  ; Build the ValidCharacter table to have have a faster routine to detect
  ; if the char is a considered as a string or not. Nice improvement :)
 
  For k='0' To '9'            ; Tell than the ASCII from 0 to 9 are valid
    ValidCharacters(k) = 1
  Next
  For k='A' To 'Z'            ; Tell than the ASCII from A to Z are valid
    ValidCharacters(k) = 1
  Next
  For k='a' To 'z'            ; Tell than the ASCII from a to z are valid
    ValidCharacters(k) = 1
  Next
  ValidCharacters('_') = 1
  
  DataSection
    BasicKeywords:
  
    Data.s "And", "and"
    Data.s "CallDebugger"     , "calldebugger"
    Data.s "Case"             , "case"
    Data.s "CompilerCase"     , "compilercase"
    Data.s "CompilerDefault"  , "compilerdefault"
    Data.s "CompilerElse"     , "compilerelse"
    Data.s "CompilerEndIf"    , "compilerendif"
    Data.s "CompilerEndSelect", "compilerendselect"
    Data.s "CompilerIf"       , "compilerif"
    Data.s "CompilerSelect"   , "compilerselect"
    Data.s "Data"           , "data"
    Data.s "DataSection"    , "datasection"
    Data.s "Debug"          , "debug"
    Data.s "DebugLevel"     , "debuglevel"
    Data.s "Declare"        , "declare"
    Data.s "DeclareDLL"     , "declaredll"
    Data.s "Default"        , "default"
    Data.s "DefType"        , "deftype"
    Data.s "Dim"            , "dim"
    Data.s "DisableDebugger", "disabledebugger"
    Data.s "Else"         , "else"
    Data.s "ElseIf"       , "elseif"
    Data.s "EnableDebugger", "enabledebugger"
    Data.s "End"         , "end"
    Data.s "EndDataSection", "enddatasection"
    Data.s "EndIf"       , "endif"
    Data.s "EndProcedure", "endprocedure"
    Data.s "EndSelect"   , "endselect"
    Data.s "EndStructure", "endstructure"
    Data.s "EndStructureUnion", "endstructureunion"
    Data.s "FakeEndSelect", "fakeendselect"
    Data.s "FakeReturn"   , "fakereturn"
    Data.s "For"          , "for"
    Data.s "ForEver"      , "forever"
    Data.s "Global", "global"
    Data.s "Gosub", "gosub"
    Data.s "Goto" , "goto"
    Data.s "If", "if"
    Data.s "IncludeBinary", "includebinary"
    Data.s "IncludeFile", "includefile"
    Data.s "IncludePath", "includepath"
    Data.s "NewList", "newlist"
    Data.s "Next", "next"
    Data.s "Or", "or"
    Data.s "Procedure"      , "procedure"
    Data.s "ProcedureDLL"   , "proceduredll"
    Data.s "ProcedureReturn", "procedurereturn"
    Data.s "Protected"      , "protected"
    Data.s "Read", "read"
    Data.s "Repeat", "repeat"
    Data.s "Restore", "restore"
    Data.s "Return", "return"
    Data.s "Select", "select"
    Data.s "Shared", "shared"
    Data.s "Step", "step"
    Data.s "Structure", "structure"
    Data.s "StructureUnion", "structureunion"
    
    Data.s "To", "to"
    Data.s "Until", "until"
    Data.s "Wend" , "wend"
    Data.s "While", "while"
    Data.s "XIncludeFile" , "xincludefile"
    Data.s "XOr" , "xor"
  EndDataSection
  
EndProcedure
;The following procedure scans the given line of text in the richedit control looking 
;For occurrences of the word "test". Such words are coloured And set To italic. 
Procedure HighlightLine(Line) 
  Protected LineText.s, Format.CHARFORMAT, StartPos, Endpos, Left, Right, Flag.b 
  
  LineText = LCase(GetGadgetItemText(#RichEdit, Line,0)) 
  ;Get the character index's of both ends of the line. 
  StartPos = sendmessage_(GadgetID(#RichEdit),#EM_LINEINDEX, Line,0) 
  EndPos = StartPos + Len(LineText) 
  Format\cbSize = SizeOf(CHARFORMAT)
  Format\dwMask = #CFM_COLOR | #CFM_BOLD | #CFM_ITALIC 
  
  Left = StartPos 
  Restore BasicKeywords
  
  Repeat 
    ;Identify possible occurrences of "test"
    For a=0 To #NbBasicKeywords
      Read inst$
      Right = FindString(LineText, inst$, Left-StartPos+1) + StartPos 
      If Right = StartPos;No occurrences found so colour entire line with the default text colour
        SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, Left, EndPos) 
        Format\crTextColor = #COLOR_Text : Format\dwEffects = #EFFECTS_Text 
        SendMessage_(GadgetID(#RichEdit), #EM_SETCHARFORMAT, #SCF_SELECTION, @Format)
        Left = EndPos
        Goto ttt
      Else 
        SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, Left, Right-1) 
        Format\crTextColor = #COLOR_Text : Format\dwEffects = #EFFECTS_Text 
        SendMessage_(GadgetID(#RichEdit), #EM_SETCHARFORMAT, #SCF_SELECTION, @Format)
        Left = Right-1 : Right + 3 
        SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, Left, Right);Highlight the word "test" 
        Left = Right 
        Format\crTextColor = #COLOR_Symbol : Format\dwEffects = #EFFECTS_Symbol 
        SendMessage_(GadgetID(#RichEdit), #EM_SETCHARFORMAT, #SCF_SELECTION, @Format)
        Goto ttt
      EndIf
ttt:
    Next a
  Until Left = EndPos 
EndProcedure
;The following call back procedure is responsible for syntax highlighting etc. 
;It does this by intercepting the #EN_CHANGE command message which fires whenever 
;text in the rich edit control has changed. We then examine the entire line containing the text. 
Procedure WindowCallback(hWnd, uMsg, wParam, lParam) 
  Protected ReturnValue, Chr.CHARRANGE, Line, CurrentStartPos 
  ReturnValue = #PB_ProcessPureBasicEvents 
  Select uMsg 
    Case #WM_COMMAND 
      If wParam >>16 = #EN_CHANGE And lparam = GadgetID(#RichEdit) 
        ;The following returns the index (0-based) of the line containing the current character. 
        Sendmessage_(GadgetID(#RichEdit),#EM_GETSEL,@CurrentStartPos, @Line) 
        Line = sendmessage_(GadgetID(#RichEdit),#EM_LINEFROMCHAR, CurrentStartPos,0) 
        SendMessage_(GadgetID(#RichEdit), #EM_HIDESELECTION, 1,0)
        HighlightLine(Line) 
        If GetAsyncKeyState_(#VK_return) & 1 = 1;  Bit 0 is set if the enter key was pressed since the last check. 
          ;Investigate the previous line. 
          HighlightLine(Line-1) 
        EndIf 
        SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, CurrentStartPos,CurrentStartPos); Return cursor to its correct position. 
        SendMessage_(GadgetID(#RichEdit),#EM_SETMODIFY,0,0) 
        SendMessage_(GadgetID(#RichEdit), #EM_HIDESELECTION, 0,0)
      EndIf 
  EndSelect 
  ProcedureReturn(Returnvalue)
EndProcedure 
Thanks in advance :)

@kale:
Thanks kale!! it's good to see people welcoming you when you're new on the forums! :) :) :) :) :)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Apart from a couple of minor bugs the problem lie within the

Code: Select all

repeat
  for a = ...

  next a
until ...
structure.

Basically, the way I checked for HTML tags, HTML symbols, quotations etc. does not readily carry over to the kind of syntax checking that you required. I basically parsed each line from left to right without any backtracking, whilst you are repeatedly parsing the line once for each possible keyword. Personally I prefer a single parse through the line, but no problem.

I've edited your code and it now works, -also made it somewhat quicker.

Code: Select all

Declare HighlightLine(Line) 
Declare WindowCallback(hWnd, uMsg, wParam, lParam) 
Declare InitSyntaxHighlightning() 
Dim ValidCharacters.b(255) 
Enumeration 
#MainWindow 
EndEnumeration 
;Gadget enumeration. 
Enumeration 
#RichEdit 
EndEnumeration 
;Font enumeration 
Enumeration 
#FontEdit 
EndEnumeration 
#COLOR_Text = $000000 : #EFFECTS_Text = 0 
#COLOR_Symbol = $ff00 : #EFFECTS_Symbol = #CFE_italic 
#NbBasicKeywords = 126; ***NOT 64!
If OpenWindow(#MainWindow,0,0,400,400,#PB_Window_Invisible | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget,"") 
  ShowWindow_(WindowID(#MainWindow), #SW_maximize) 
  
  If CreateGadgetList(WindowID(#MainWindow)) 
    If LoadFont(#FontEdit, "Courier New", 10) 
      EditorGadget(#RichEdit,0,50,3*WindowWidth()/4,WindowHeight()-50) 
      SetGadgetFont(#RichEdit, UseFont(#FontEdit)) 
      SendMessage_(GadgetID(#RichEdit), #EM_SETBKGNDCOLOR, 0, $b6fcf8); Set background colour 
    Else 
      MessageRequester("Fatal error","Can't open the 'Courier New' font") 
    EndIf 
  EndIf 
  
  SendMessage_(GadgetID(#RichEdit), #EM_SETEVENTMASK, 0, #ENM_CHANGE) 
  ActivateGadget(#RichEdit) 
  SetWindowCallback(@WindowCallback()) 
  InitSyntaxHighlightning() 
  
  ;Main message loop.. 
  Repeat 
    EventID=WaitWindowEvent() 
  Until EventID=#PB_EventCloseWindow 
  
EndIf 
Procedure InitSyntaxHighlightning() 
  ; Build the ValidCharacter table to have have a faster routine to detect 
  ; if the char is a considered as a string or not. Nice improvement :) 

  For k='0' To '9'            ; Tell than the ASCII from 0 to 9 are valid 
    ValidCharacters(k) = 1 
  Next 
  For k='A' To 'Z'            ; Tell than the ASCII from A to Z are valid 
    ValidCharacters(k) = 1 
  Next 
  For k='a' To 'z'            ; Tell than the ASCII from a to z are valid 
    ValidCharacters(k) = 1 
  Next 
  ValidCharacters('_') = 1 
  
  DataSection 
    BasicKeywords: 
  
    Data.s "And", "and" 
    Data.s "CallDebugger"     , "calldebugger" 
    Data.s "Case"             , "case" 
    Data.s "CompilerCase"     , "compilercase" 
    Data.s "CompilerDefault"  , "compilerdefault" 
    Data.s "CompilerElse"     , "compilerelse" 
    Data.s "CompilerEndIf"    , "compilerendif" 
    Data.s "CompilerEndSelect", "compilerendselect" 
    Data.s "CompilerIf"       , "compilerif" 
    Data.s "CompilerSelect"   , "compilerselect" 
    Data.s "Data"           , "data" 
    Data.s "DataSection"    , "datasection" 
    Data.s "Debug"          , "debug" 
    Data.s "DebugLevel"     , "debuglevel" 
    Data.s "Declare"        , "declare" 
    Data.s "DeclareDLL"     , "declaredll" 
    Data.s "Default"        , "default" 
    Data.s "DefType"        , "deftype" 
    Data.s "Dim"            , "dim" 
    Data.s "DisableDebugger", "disabledebugger" 
    Data.s "Else"         , "else" 
    Data.s "ElseIf"       , "elseif" 
    Data.s "EnableDebugger", "enabledebugger" 
    Data.s "End"         , "end" 
    Data.s "EndDataSection", "enddatasection" 
    Data.s "EndIf"       , "endif" 
    Data.s "EndProcedure", "endprocedure" 
    Data.s "EndSelect"   , "endselect" 
    Data.s "EndStructure", "endstructure" 
    Data.s "EndStructureUnion", "endstructureunion" 
    Data.s "FakeEndSelect", "fakeendselect" 
    Data.s "FakeReturn"   , "fakereturn" 
    Data.s "For"          , "for" 
    Data.s "ForEver"      , "forever" 
    Data.s "Global", "global" 
    Data.s "Gosub", "gosub" 
    Data.s "Goto" , "goto" 
    Data.s "If", "if" 
    Data.s "IncludeBinary", "includebinary" 
    Data.s "IncludeFile", "includefile" 
    Data.s "IncludePath", "includepath" 
    Data.s "NewList", "newlist" 
    Data.s "Next", "next" 
    Data.s "Or", "or" 
    Data.s "Procedure"      , "procedure" 
    Data.s "ProcedureDLL"   , "proceduredll" 
    Data.s "ProcedureReturn", "procedurereturn" 
    Data.s "Protected"      , "protected" 
    Data.s "Read", "read" 
    Data.s "Repeat", "repeat" 
    Data.s "Restore", "restore" 
    Data.s "Return", "return" 
    Data.s "Select", "select" 
    Data.s "Shared", "shared" 
    Data.s "Step", "step" 
    Data.s "Structure", "structure" 
    Data.s "StructureUnion", "structureunion" 
    Data.s "To", "to" 
    Data.s "Until", "until" 
    Data.s "Wend" , "wend" 
    Data.s "While", "while" 
    Data.s "XIncludeFile" , "xincludefile" 
    Data.s "XOr" , "xor" 
  EndDataSection 
  
EndProcedure 
;The following procedure scans the given line of text in the richedit control looking 
;For occurrences of the word "test". Such words are coloured And set To italic. 
Procedure HighlightLine(Line) 
  Protected LineText.s, Format.CHARFORMAT, StartPos, Endpos, Left, Right, Flag.b 
  
 LineText = GetGadgetItemText(#RichEdit, Line,0);******
  ;Get the character index's of both ends of the line. 
  StartPos = sendmessage_(GadgetID(#RichEdit),#EM_LINEINDEX, Line,0) 
  EndPos = StartPos + Len(LineText) 
  Format\cbSize = SizeOf(CHARFORMAT) 
  Format\dwMask = #CFM_COLOR | #CFM_BOLD | #CFM_ITALIC 

;******First colour entire line with the default text colour,
  SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, 0, EndPos) 
  Format\crTextColor = #COLOR_Text : Format\dwEffects = #EFFECTS_Text 
  SendMessage_(GadgetID(#RichEdit), #EM_SETCHARFORMAT, #SCF_SELECTION, @Format) 
;******
  
  Restore BasicKeywords 
    For a=1 To #NbBasicKeywords 
      Left = StartPos 
      Read inst$
      Repeat
        Right = FindString(LineText, inst$, Left-StartPos+1) + StartPos 
        If Right = StartPos;No occurrences found.
          Left = EndPos 
        Else 
;******
          Left = Right-1 : Right + Len(inst$)-1 
;******
          SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, Left, Right);Highlight the word. 
          Left = Right 
          Format\crTextColor = #COLOR_Symbol : Format\dwEffects = #EFFECTS_Symbol 
          SendMessage_(GadgetID(#RichEdit), #EM_SETCHARFORMAT, #SCF_SELECTION, @Format) 
        EndIf 
      Until Left = EndPos  
    Next a 
EndProcedure 

;The following call back procedure is responsible for syntax highlighting etc. 
;It does this by intercepting the #EN_CHANGE command message which fires whenever 
;text in the rich edit control has changed. We then examine the entire line containing the text. 
Procedure WindowCallback(hWnd, uMsg, wParam, lParam) 
  Protected ReturnValue, Chr.CHARRANGE, Line, CurrentStartPos 
  ReturnValue = #PB_ProcessPureBasicEvents 
  Select uMsg 
    Case #WM_COMMAND 
      If wParam >>16 = #EN_CHANGE And lparam = GadgetID(#RichEdit) 
        ;The following returns the index (0-based) of the line containing the current character. 
        Sendmessage_(GadgetID(#RichEdit),#EM_GETSEL,@CurrentStartPos, @Line) 
        Line = sendmessage_(GadgetID(#RichEdit),#EM_LINEFROMCHAR, CurrentStartPos,0) 
        SendMessage_(GadgetID(#RichEdit), #EM_HIDESELECTION, 1,0) 
        HighlightLine(Line) 
        If GetAsyncKeyState_(#VK_return) & 1 = 1;  Bit 0 is set if the enter key was pressed since the last check. 
          ;Investigate the previous line. 
          HighlightLine(Line-1) 
        EndIf 
        SendMessage_(GadgetID(#RichEdit), #EM_SETSEL, CurrentStartPos,CurrentStartPos); Return cursor to its correct position. 
        SendMessage_(GadgetID(#RichEdit),#EM_SETMODIFY,0,0) 
        SendMessage_(GadgetID(#RichEdit), #EM_HIDESELECTION, 0,0) 
      EndIf 
  EndSelect 
  ProcedureReturn(Returnvalue) 
EndProcedure 
A couple of points to note:

i) You do not actually need to check for each keyword twice; e.g. "For", "for" etc. since you could just make a lowercase copy of the line being checked.
ii) At present, your code would highlight parts of words containing keywords, e.g. the "to" in "top" would be highlighted. Shouldn't be difficult to sort this out.
Last edited by srod on Sun Mar 14, 2004 12:42 pm, edited 1 time in total.
I may look like a mule, but I'm not a complete ass.
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

Hi srod,

Thanks for sharing this.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

No problem. I've shanghaied enough snippets of code over the months to make me feel that it is about time I gave something back!
I may look like a mule, but I'm not a complete ass.
DARKGuy
User
User
Posts: 40
Joined: Thu Mar 11, 2004 10:08 pm
Contact:

Post by DARKGuy »

hey srod! thanks!! :) I'm going to test it now :) so....the credits are for Timo (for that Librarymaker source) and srod for helping me so good :D :D :D anyway thank you guys :) when I finish my editor (I'm sure I'll post here when I have a problem :) ) I'll give it FOR FREE and I'll post a download link. Perhaps I'll include a 3D model viewer made in DarkBASIC :) and some converters from 3DS to OGRE or things like that hehe :)

THANKS!!!!!!!!!! :D
Post Reply