Tips to speed up this code? (Windows)

Just starting out? Need help? Post your questions and find answers here.
firace
Addict
Addict
Posts: 903
Joined: Wed Nov 09, 2011 8:58 am

Tips to speed up this code? (Windows)

Post by firace »

Any ideas to speed up this little real-time syntax highlighting code (based on some nice procedures by freak)?
I know scintilla is a much more powerful option of course, but still wanted to play around with the low-level way.

Code: Select all

Procedure Editor_Select(Gadget, LineStart.l, CharStart.l, LineEnd.l, CharEnd.l)      ;;; thanks freak 2005!!
  sel.CHARRANGE 
  sel\cpMin = SendMessage_(GadgetID(Gadget), #EM_LINEINDEX, LineStart, 0) + CharStart - 1 
  
  If LineEnd = -1 
    LineEnd = SendMessage_(GadgetID(Gadget), #EM_GETLINECOUNT, 0, 0)-1 
  EndIf 
  sel\cpMax = SendMessage_(GadgetID(Gadget), #EM_LINEINDEX, LineEnd, 0) 
  
  If CharEnd = -1 
    sel\cpMax + SendMessage_(GadgetID(Gadget), #EM_LINELENGTH, sel\cpMax, 0) 
  Else 
    sel\cpMax + CharEnd - 1 
  EndIf 
  SendMessage_(GadgetID(Gadget), #EM_EXSETSEL, 0, @sel) 
EndProcedure 

Procedure Editor_Color(Gadget, Color.l) 
  format.CHARFORMAT2 
  format\cbSize = SizeOf(CHARFORMAT2) 
  format\dwMask = #CFM_COLOR 
  format\crTextColor = Color 
  SendMessage_(GadgetID(Gadget), #EM_SETCHARFORMAT, #SCF_SELECTION, @format) 
EndProcedure 


Procedure Highlight(gad, t$, color)
  Shared Line$, LineNumber
  
      wordstart = FindString(Line$, t$, 1)
    While wordstart <> 0
      
      wordend = wordstart + Len(t$) 
      
      Editor_Select(gad, LineNumber, wordstart, LineNumber, wordend)
      Debug "x" + Second(Date())
      
      Editor_Color(gad, color)
      
      wordstart = FindString(Line$, t$, wordend)
    Wend
    
EndProcedure   

Procedure ColoringRoutine(gad)
  Shared Line$, LineNumber
  
  SendMessage_(GadgetID(gad),#WM_SETREDRAW,0,0)
  
  SendMessage_(GadgetID(gad), #EM_HIDESELECTION, 1,0)    
  
  SendMessage_(GadgetID(gad),#EM_GETSEL,@CurrentStartPos, @Line)
  Line = SendMessage_(GadgetID(gad),#EM_LINEFROMCHAR, CurrentStartPos,0)
  
  For LineNumber = (line - 20)  To (line + 20)
    
    Line$ = UCase(GetGadgetItemText(gad, LineNumber, 0))
    
Highlight(gad, "0", $0000FF)
Highlight(gad, "1", $0000FF)
Highlight(gad, "2", $0000FF)
Highlight(gad, "3", $0000FF)
Highlight(gad, "4", $0000FF)
Highlight(gad, "5", $0000FF)
Highlight(gad, "6", $0000FF)
Highlight(gad, "7", $0000FF)
Highlight(gad, "8", $0000FF)
Highlight(gad, "9", $0000FF)
Highlight(gad, "SYNTAX", $FF0000)
    
  Next LineNumber
      
  SendMessage_(GadgetID(gad), #EM_SETSEL, CurrentStartPos,CurrentStartPos)
  
  SendMessage_(GadgetID(gad), #EM_HIDESELECTION, 0,0)    
  
  Editor_Color(gad, $000000)
  
  SendMessage_(GadgetID(gad),#WM_SETREDRAW,1, 0)
  InvalidateRect_(GadgetID(gad), 0, 1)
  
  
EndProcedure   

Procedure FillList()
  Shared prevupd 
  
  If Abs(ElapsedMilliseconds()-prevupd) > 200
    
    ColoringRoutine(1)
    
    prevupd = ElapsedMilliseconds()
  EndIf
  SetWindowTitle(0, Str(Len(GetGadgetText(1))) + " ch")
  
EndProcedure



#Editor = 1

OpenWindow(0, 0, 0, 500, 500, "EditorGadget", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)

LoadFont(1, "Consolas", 14) : SetGadgetFont(-1, FontID(1))
EditorGadget(#Editor, 10, 10, 480, 480)

AddGadgetItem(#Editor, -1, "There are " + Str(Random(1000000)) + " ways to write a syntax highlighter.")
AddGadgetItem(#Editor, -1, "Nothing to highlight in this line.")


BindGadgetEvent(#Editor,@FillList(),#PB_EventType_Change )

ColoringRoutine(#Editor)


Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: Tips to speed up this code? (Windows)

Post by BarryG »

I can't see what's meant to be sped up? When I run it, I see two lines of text and the first line has a red number and a blue word "syntax".
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Tips to speed up this code? (Windows)

Post by infratec »

Don't use FindString().

Here in the forum are many examples how to replace it by a way that the whole string is done in one go
which does not always start the string search from the beginning again and uses a pointer.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Tips to speed up this code? (Windows)

Post by Mijikai »

Here is another way to highlight maybe this helps or is of interest.

Code: Select all

Procedure.i SyntaxHighlight(Handle.i,PosStart.i,PosEnd.i,Signature.s,Color.i);<- Handle = GadgetID(Edit)
  Protected search.FINDTEXTEX
  Protected format.CHARFORMAT2
  search\chrg\cpMin = PosStart
  search\chrg\cpMax = PosEnd
  search\lpstrText = @Signature
  SendMessage_(Handle,#EM_FINDTEXTEXW,#FR_DOWN|#FR_WHOLEWORD,@search)
  If search\chrgText\cpMin = -1 And search\chrgText\cpMax = -1
    ProcedureReturn #False  
  Else
    format\cbSize = SizeOf(CHARFORMAT2)
    format\dwMask = #CFM_COLOR
    format\crTextColor = Color
    SendMessage_(Handle,#EM_EXGETSEL,#Null,@search\chrg)
    SendMessage_(Handle,#EM_SETSEL,search\chrgText\cpMin,search\chrgText\cpMax)   
    SendMessage_(Handle,#EM_SETCHARFORMAT,#SCF_SELECTION,@format)
    SendMessage_(Handle,#EM_SETSEL,search\chrg\cpMin,search\chrg\cpMax)
    ProcedureReturn #True
  EndIf
EndProcedure
Edit:
In one post i found the suggestion to use event masks in order to improve the performance.
Before an operation the eventmask is set to ENM_NONE and then restored.
EM_SETEVENTMASK -> ENM_NONE
Last edited by Mijikai on Sun Sep 12, 2021 12:50 pm, edited 3 times in total.
firace
Addict
Addict
Posts: 903
Joined: Wed Nov 09, 2011 8:58 am

Re: Tips to speed up this code? (Windows)

Post by firace »

@infratec: thanks for the tip! will look into it.
@barryg: you're right, the example code was fast. the slow performance becomes apparent for longer editorgadget contents.

See updated example below.
I have just noticed another issue though: if I type additional text somewhere in the middle of the contents, the cursor and current line position get messed up (the edited line jumps down to the bottom of the view, which is a little confusing). Not sure what I'm doing wrong.

Code: Select all

Procedure Editor_Select(Gadget, LineStart.l, CharStart.l, LineEnd.l, CharEnd.l)      ;;; thanks freak 2005!!
  sel.CHARRANGE 
  sel\cpMin = SendMessage_(GadgetID(Gadget), #EM_LINEINDEX, LineStart, 0) + CharStart - 1 
  
  If LineEnd = -1 
    LineEnd = SendMessage_(GadgetID(Gadget), #EM_GETLINECOUNT, 0, 0)-1 
  EndIf 
  sel\cpMax = SendMessage_(GadgetID(Gadget), #EM_LINEINDEX, LineEnd, 0) 
  
  If CharEnd = -1 
    sel\cpMax + SendMessage_(GadgetID(Gadget), #EM_LINELENGTH, sel\cpMax, 0) 
  Else 
    sel\cpMax + CharEnd - 1 
  EndIf 
  SendMessage_(GadgetID(Gadget), #EM_EXSETSEL, 0, @sel) 
EndProcedure 

Procedure Editor_BackColor(Gadget, Color.l)
  format.CHARFORMAT2
  format\cbSize = SizeOf(CHARFORMAT2)
  format\dwMask = $4000000  ; = #CFM_BACKCOLOR
  format\crBackColor = Color
  SendMessage_(GadgetID(Gadget), #EM_SETCHARFORMAT, #SCF_SELECTION, @format)
EndProcedure

Procedure Editor_Color(Gadget, Color.l) 
  format.CHARFORMAT2 
  format\cbSize = SizeOf(CHARFORMAT2) 
  format\dwMask = #CFM_COLOR 
  format\crTextColor = Color 
  SendMessage_(GadgetID(Gadget), #EM_SETCHARFORMAT, #SCF_SELECTION, @format) 
EndProcedure 


Procedure Highlight(gad, t$, color)
  Shared Line$, LineNumber
  
  wordstart = FindString(Line$, t$, 1)
  While wordstart <> 0
    
    wordend = wordstart + Len(t$) 
    
    Editor_Select(gad, LineNumber, wordstart, LineNumber, wordend)
    ;     Debug "x" + Second(Date())
    
    Editor_Color(gad, color)
    ;     Editor_BackColor(gad, 0)
    
    wordstart = FindString(Line$, t$, wordend)
  Wend
  
EndProcedure   

Procedure ColoringRoutine(gad)
  Shared Line$, LineNumber
  
  SendMessage_(GadgetID(gad),#WM_SETREDRAW,0,0)
  
  SendMessage_(GadgetID(gad), #EM_HIDESELECTION, 1,0)    
  
  SendMessage_(GadgetID(gad), #EM_GETSCROLLPOS, 0, @position)
  Debug "P: " + position
  SendMessage_(GadgetID(gad),#EM_GETSEL,@CurrentStartPos, @Line)
  Line =  SendMessage_(GadgetID(gad), #EM_GETFIRSTVISIBLELINE, 0, 0)+1 
  
  For LineNumber = (line - 20)  To (line + 20)
    
    Editor_Select(gad, LineNumber, 1, LineNumber, -1)
    
    Editor_BackColor(gad, $fefefe)
    Editor_Color(gad, 0)
    
    Line$ = UCase(GetGadgetItemText(gad, LineNumber, 0))
    
    Highlight(gad, "0", $0000FF)
    Highlight(gad, "1", $0000FF)
    Highlight(gad, "2", $0000FF)
    Highlight(gad, "3", $0000FF)
    Highlight(gad, "4", $0000FF)
    Highlight(gad, "5", $0000FF)
    Highlight(gad, "6", $0000FF)
    Highlight(gad, "7", $0000FF)
    Highlight(gad, "8", $0000FF)
    Highlight(gad, "9", $0000FF)
    Highlight(gad, "SYNTAX", $FF0000)
    Highlight(gad, "HIGHLIGHT", $10A0A0)
    
  Next LineNumber
  
  SendMessage_(GadgetID(gad), #EM_SETSEL, CurrentStartPos,CurrentStartPos)
  SendMessage_(GadgetID(gad), #EM_SETSCROLLPOS, 0, @position)
  
  SendMessage_(GadgetID(gad), #EM_HIDESELECTION, 0,0)    
  
  Editor_Color(gad, $000000)
  
  SendMessage_(GadgetID(gad),#WM_SETREDRAW,1, 0)
  InvalidateRect_(GadgetID(gad), 0, 1)  
EndProcedure   

Procedure FillList()
  Shared prevupd 
  Static prevsize
  
  size = Len(GetGadgetText(333))
  If size <> prevsize
    If Abs(ElapsedMilliseconds()-prevupd) > 200 Or size > prevsize + 10
      
      ColoringRoutine(333)
      
      prevupd = ElapsedMilliseconds()
      prevsize = size
      
    EndIf
    SetWindowTitle(0, Str(size) + " ch")
  EndIf 
  
EndProcedure

OpenWindow(0, 0, 0, 700, 500, "EditorGadget", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)

LoadFont(1, "Consolas", 14) : SetGadgetFont(-1, FontID(1))
EditorGadget(333, 10, 10, 680, 480)

For jj = 1 To 1000
AddGadgetItem(333, -1, "There are " + Str(Random(1000000)) + " ways to write a syntax highlighter.")
AddGadgetItem(333, -1, "Nothing to highlight in this line.")
AddGadgetItem(333, -1, "There are " + Str(Random(1000000)) + " ways to write a syntax highlighter.")
AddGadgetItem(333, -1, "Nothing to highlight in this line.")
Next

SetActiveGadget(333)

BindGadgetEvent(333,@FillList(),#PB_EventType_Change )

; ColoringRoutine(333)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: Tips to speed up this code? (Windows)

Post by BarryG »

firace wrote: Sun Sep 12, 2021 12:38 pm@barryg: you're right, the example code was fast. the slow performance becomes apparent for longer editorgadget contents.
Maybe the code I was given here can help? -> viewtopic.php?f=13&t=75556
Post Reply