Scintilla: how to delete multiple lines at once?

Just starting out? Need help? Post your questions and find answers here.
novablue
Enthusiast
Enthusiast
Posts: 177
Joined: Sun Nov 27, 2016 6:38 am

Scintilla: how to delete multiple lines at once?

Post by novablue »

Hi, i want to delete multiple lines from an external Scintilla gadget, for example line 5 to 50. Currently i am deleting each line one by one which can get really slow. surely there must be a better way to delete multiple lines at once?

Code: Select all

Define I.i
Define IDE_HwndScintilla.i = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
Define StartLine.i = 5
Define EndLine.i = 50

SendMessage_(IDE_HwndScintilla, #SCI_GOTOLINE, StartLine, 0)
For I=1 To EndLine-StartLine
	SendMessage_(IDE_HwndScintilla, #SCI_LINEDELETE, 0, 0)
Next
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Scintilla: how to delete multiple lines at once?

Post by srod »

I have used the following. Try it, see if it is any quicker than your routine.

Code: Select all

Procedure Sci_DeleteLines(id, fromLine, toLine)
  Protected numLines, lineLength, startPos, endPos
  If IsGadget(id) And GadgetType(id) = #PB_GadgetType_Scintilla And toLine >= fromLine And fromLine >=0 And toLine >=0
    If ScintillaSendMessage(id, #SCI_GETLENGTH)
      numLines = ScintillaSendMessage(id, #SCI_GETLINECOUNT)
      If toLine >= numLines
        toLine = numLines-1
      EndIf
      If fromLine >= numLines
        fromLine = numLines-1
      EndIf
        startPos = ScintillaSendMessage(id, #SCI_POSITIONFROMLINE, fromLine)
        endPos = ScintillaSendMessage(id, #SCI_POSITIONFROMLINE, toLine) + ScintillaSendMessage(id, #SCI_LINELENGTH, toLine)
        ;We may have to delete the EOL characters in the previous line.
          If fromLine And fromLine = numLines - 1
            Select ScintillaSendMessage(id, #SCI_GETEOLMODE)
              Case #SC_EOL_CRLF
                startPos-2
              Default
                startpos-1
            EndSelect
          EndIf
        ;We now replace the text with an empty string.
          ScintillaSendMessage(id, #SCI_SETTARGETSTART, startPos)
          ScintillaSendMessage(id, #SCI_SETTARGETEND, endPos)
          ScintillaSendMessage(id, #SCI_REPLACETARGET, -1, @"")
    EndIf
  EndIf
EndProcedure
**EDIT : just realised that you are working with the PB IDE editor so you'll need to edit my routine somewhat - removing all references to gadget# and switching ScintillaSendMessage() with SendMessage_() etc. I see no reason why it won't work though.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Scintilla: how to delete multiple lines at once?

Post by srod »

A version for working with external scintilla controls. Tested and works fine with a scintilla control created in the running program.

Code: Select all

Procedure Sci_DeleteLines(hWnd, fromLine, toLine)
  Protected numLines, lineLength, startPos, endPos
  If toLine >= fromLine And fromLine >=0 And toLine >=0
    If SendMessage_(hWnd, #SCI_GETLENGTH, 0, 0)
      numLines = SendMessage_(hWnd, #SCI_GETLINECOUNT, 0, 0)
      startPos = SendMessage_(hWnd, #SCI_POSITIONFROMLINE, fromLine, 0)
      endPos = SendMessage_(hWnd, #SCI_POSITIONFROMLINE, toLine, 0) + SendMessage_(hWnd, #SCI_LINELENGTH, toLine, 0)
      ;We may have to delete the EOL characters in the previous line.
        If fromLine And fromLine = numLines - 1
          Select SendMessage_(hWnd, #SCI_GETEOLMODE, 0, 0)
            Case #SC_EOL_CRLF
              startPos-2
            Default
              startpos-1
          EndSelect
        EndIf
      ;We now replace the text with an empty string.
        SendMessage_(hWnd, #SCI_SETTARGETSTART, startPos, 0)
        SendMessage_(hWnd, #SCI_SETTARGETEND, endPos, 0)
        SendMessage_(hWnd, #SCI_REPLACETARGET, -1, @"")
    EndIf
  EndIf
EndProcedure
I may look like a mule, but I'm not a complete ass.
novablue
Enthusiast
Enthusiast
Posts: 177
Joined: Sun Nov 27, 2016 6:38 am

Re: Scintilla: how to delete multiple lines at once?

Post by novablue »

Thanks this is much better. I had to replace:

Code: Select all

SendMessage_(hWnd, #SCI_REPLACETARGET, -1, @"")
With:

Code: Select all

SendMessage_(hWnd, #SCI_REPLACETARGET, -1, 0)
Or i would get random characters in the IDE, which brings me to my next question: how can i replace the lines with text? So far i have been doing this but of course it changes the current cursor position:

Code: Select all

SendMessage_(IDE_HwndScintilla, #SCI_GOTOLINE, InsertFrom, 0)
String$ = "Hello"
StringToIDE$ = Space(StringByteLength(String$, #PB_UTF8))
PokeS(@StringToIDE$, String$, -1, #PB_UTF8)
SendMessage_(IDE_HwndScintilla, #EM_REPLACESEL, 0, PeekS(@StringToIDE$))
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Scintilla: how to delete multiple lines at once?

Post by srod »

Something similar to before might do it. You might need to monkey around with this a bit.

Must admit I would be a little surprised if this works on a Scintilla control created in another process as we are effectively passing a UTF8 buffer across to the other process!

Code: Select all

Procedure Sci_ReplaceLines(hWnd, fromLine, toLine, text$)
  Protected numLines, lineLength, startPos, endPos, utf8Text
  If toLine >= fromLine And fromLine >=0 And toLine >=0
    If SendMessage_(hWnd, #SCI_GETLENGTH, 0, 0)
      utf8Text = UTF8(text$)
      If utf8Text
        numLines = SendMessage_(hWnd, #SCI_GETLINECOUNT, 0, 0)
        startPos = SendMessage_(hWnd, #SCI_POSITIONFROMLINE, fromLine, 0)
        endPos = SendMessage_(hWnd, #SCI_POSITIONFROMLINE, toLine, 0) + SendMessage_(hWnd, #SCI_LINELENGTH, toLine, 0)
        ;We may have to delete the EOL characters in the previous line.
          If fromLine And fromLine = numLines - 1
            Select SendMessage_(hWnd, #SCI_GETEOLMODE, 0, 0)
              Case #SC_EOL_CRLF
                startPos-2
              Default
                startpos-1
            EndSelect
          EndIf
        ;We now replace the text.
          SendMessage_(hWnd, #SCI_SETTARGETSTART, startPos, 0)
          SendMessage_(hWnd, #SCI_SETTARGETEND, endPos, 0)
          SendMessage_(hWnd, #SCI_REPLACETARGET, -1, utf8Text)
        FreeMemory(utf8Text)
      EndIf
    EndIf
  EndIf
EndProcedure
I may look like a mule, but I'm not a complete ass.
Post Reply