PlanetSquires Forums

Support Forums => General Board => Topic started by: Paul Squires on September 12, 2015, 02:23:24 AM

Title: CSED - move lines
Post by: Paul Squires on September 12, 2015, 02:23:24 AM
Hi Jose,

I am re-writing my JellyFish Editor for FreeBASIC and I implemented code to move line(s) in the edit window using the keyboard shortcuts CTRL+SHIFT+UP and CTRL+SHIFT+DOWN. It is a very convenient feature because otherwise you need to cut the line, move cursor to insert line, and then paste. It also works with multiple lines.

I have been stealing so much from your CSED Editor (especially the Scintilla stuff) that I thought I would post it here in case you would ever like to add it to your editor. This code is based on C++ code found in the NotePad++ editor.

My code uses the SendMessage functionality rather than the Scintilla direct function pointers.



' call the functions
'      Case IDC_FRMMAIN_MNUMOVEUPCURRENTLINE
'         Function = Doc_MoveCurrentLines(GetCodeWindowFromCurrentTab, False)
'      Case IDC_FRMMAIN_MNUMOVEDOWNCURRENTLINE
'         Function = Doc_MoveCurrentLines(GetCodeWindowFromCurrentTab, True)


''
''
Function Doc_GetSelectedLineRange( ByVal hWindow   as HWnd, _
                                   ByRef startLine as Integer, _
                                   ByRef endLine   as Integer, _
                                   ByRef startPos  as Integer, _
                                   ByRef endPos    as Integer _
                                   ) as Integer
   
   startPos  = SendMessage(hWindow, SCI_GETSELECTIONSTART, 0, 0)
   endPos    = SendMessage(hWindow, SCI_GETSELECTIONEND, 0, 0)
   startLine = SendMessage(hWindow, SCI_LINEFROMPOSITION, startPos, 0)
   endLine   = SendMessage(hWindow, SCI_LINEFROMPOSITION, endPos, 0)

   Dim nCol as Integer = SendMessage(hWindow, SCI_GETCOLUMN, endPos, 0)
   If (nCol = 0) And (endLine > startLine) Then endLine = endLine - 1

   Function = 0
End Function

''
''
Function Doc_CurrentLineUp( ByVal hWindow as HWnd ) as Integer
   Dim currentLine as Integer = Doc_GetCurrentLineNumber(hWindow)
   If (currentLine <> 0) Then
      SendMessage(hWindow, SCI_BEGINUNDOACTION, 0, 0)
      currentLine = currentLine -1
      SendMessage(hWindow, SCI_LINETRANSPOSE, 0, 0)
      SendMessage(hWindow, SCI_GOTOLINE, currentLine, 0)
      SendMessage(hWindow, SCI_ENDUNDOACTION, 0, 0)
   End If
   Function = 0
End Function

''
''
Function Doc_CurrentLineDown( ByVal hWindow as HWnd ) as Integer
   Dim currentLine as Integer = Doc_GetCurrentLineNumber(hWindow)
   If currentLine <> SendMessage(hWindow, SCI_GETLINECOUNT, 0, 0) - 1 Then
      SendMessage(hWindow, SCI_BEGINUNDOACTION, 0, 0)
      currentLine = currentLine + 1
      SendMessage(hWindow, SCI_GOTOLINE, currentLine, 0)
      SendMessage(hWindow, SCI_LINETRANSPOSE, 0, 0)
      SendMessage(hWindow, SCI_ENDUNDOACTION, 0, 0)
   End If
   Function = 0
End Function
 
''
''
Function Doc_MoveCurrentLines( ByVal hWindow as HWnd, ByVal flagMoveDown as Integer  ) as Integer

   Dim startPos    as Integer     ' // Starting position
   Dim endPos      as Integer     ' // Ending position
   Dim startLine   as Integer     ' // Starting line
   Dim endLine     as Integer     ' // Ending line
   Dim line2swap   as Integer
   Dim nbChar      as Integer
   Dim nTextLen    as Integer
   
   Doc_GetSelectedLineRange( hWindow, startLine, endLine, startPos, endPos )

   Dim noSel      as Integer = (startLine = endLine)
   Dim nbSelLines as Integer = (endLine - startLine + 1)

   If flagMoveDown Then
      nTextLen  = SendMessage(hWindow, SCI_GETTEXTLENGTH, 0, 0)
      If (startLine = -1) Or (endLine >= SendMessage(hWindow, SCI_LINEFROMPOSITION, nTextLen, 0)) Then
           Exit Function
      End If
     line2swap = endLine + 1
      If (line2swap + 1) = SendMessage(hWindow, SCI_GETLINECOUNT, 0, 0) Then nbChar += 2    ' cr/lf
   Else
      If (startLine <= 0) Then Exit Function
      line2swap = startLine - 1
   End If
   
   nbChar = nbChar + SendMessage(hWindow, SCI_LINELENGTH, line2swap, 0)
   
   SendMessage(hWindow, SCI_BEGINUNDOACTION, 0, 0)
   SendMessage(hWindow, SCI_GOTOLINE, line2swap, 0)

   For i as Integer = 0 To nbSelLines - 1
      If flagMoveDown Then
         Doc_CurrentLineUp(hWindow)
      Else
         Doc_CurrentLineDown(hWindow)
      End If   
   Next
   SendMessage(hWindow, SCI_ENDUNDOACTION, 0, 0)

   If flagMoveDown Then
      SendMessage(hWindow, SCI_SETSELECTIONSTART, startPos + nbChar, 0)
      SendMessage(hWindow, SCI_SETSELECTIONEND, IIf(noSel, startPos + nbChar, endPos + nbChar), 0)
   Else
      SendMessage(hWindow, SCI_SETSELECTIONSTART, startPos - nbChar, 0)
      SendMessage(hWindow, SCI_SETSELECTIONEND, IIf(noSel, startPos - nbChar, endPos - nbChar), 0)
   End If
   
   Function = 0
End Function



Title: Re: CSED - move lines
Post by: José Roca on September 12, 2015, 03:36:17 AM
Good tip. Thanks for sharing.

I'm no longer in the business of making code editors. Too time consuming.

So if you are writing one in FreeBasic, maybe I will end using it. Currently, I'm using an adaptation of CSED for my FreeBasic tests.

I wrote CSED for PB during the beta testing of the PBWin 10 / PBCC 6 compilers as a non trivial way of thorughly testing both the compilers and my new headers. This is why it uses many of the new features, such classes, unicode, collections, etc. This way, I discovered many bugs that maybe I could have not discover using trivial tests.

When I released it, I said that it was a "template" that others could use as a starting point to build other versions.