REM ***** MoveText ***** ' MoveText is an extension for OpenOffice.org 2.x which moves ' selected text (in Writer, the word processor) with the keyboard. ' The code of this extension is distributed under the LGPL and ' the CeCILL licenses. ' Copyright (C) 2008 Luc Sorel (luc.sorel at gmail.com) REM ***** LGPL ***** ' This library is free software; you can redistribute it and/or ' modify it under the terms of the GNU Lesser General Public ' License as published by the Free Software Foundation; either ' version 2.1 of the License, or (at your option) any later version. ' ' This library is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY; without even the implied warranty of ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ' Lesser General Public License for more details. ' ' You should have received a copy of the GNU Lesser General Public ' License along with this library; if not, write to the Free Software ' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA REM ***** CeCILL ***** ' This software is governed by the CeCILL license under French ' law and abiding by the rules of distribution of free software. ' You can use, modify and/or redistribute the software under the ' terms of the CeCILL license as circulated by CEA, CNRS and INRIA ' at the following URL "http://www.cecill.info". ' ' As a counterpart to the access to the source code and rights ' to copy, modify and redistribute granted by the license, users ' are provided only with a limited warranty and the software's author, ' the holder of the economic rights, and the successive licensors have ' only limited liability. ' ' In this respect, the user's attention is drawn to the risks ' associated with loading, using, modifying and/or developing ' or reproducing the software by the user in light of its specific ' status of free software, that may mean that it is complicated ' to manipulate, and that also therefore means that it is reserved ' for developers and experienced professionals having in-depth ' computer knowledge. Users are therefore encouraged to load and ' test the software's suitability as regards their requirements in ' conditions enabling the security of their systems and/or data ' to be ensured and, more generally, to use and operate it in ' the same conditions as regards security. ' ' The fact that you are presently reading this means that you have ' had knowledge of the CeCILL license and that you accept its terms. option explicit global LucSorelOOoMoveTextKeyHandler as object global isLucSorelOOoMoveTextActive as boolean REM Subs and functions dedicated to the key handler sub SetupMoveTextKeyHandler LucSorelOOoMoveTextKeyHandler = CreateUnoListener("MoveText_","com.sun.star.awt.XKeyHandler") thisComponent.currentController.addKeyHandler(LucSorelOOoMoveTextKeyHandler) ' Register the listener end sub sub RemoveMoveTextKeyHandler thisComponent.currentController.removeKeyHandler(LucSorelOOoMoveTextKeyHandler) end sub sub MoveText_disposing end sub function MoveText_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean MoveText_keyReleased = False end function function MoveText_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean dim isAltPressedWithoutShift, areAltAndShiftPressed, isAnArrowPressed as boolean 'Initialize the booleans isAltPressedWithoutShift = (((oKeyEvent.modifiers and com.sun.star.awt.KeyModifier.MOD2)<>0) and not((oKeyEvent.modifiers and com.sun.star.awt.KeyModifier.SHIFT) <> 0)) areAltAndShiftPressed = (((oKeyEvent.modifiers and com.sun.star.awt.KeyModifier.MOD2)<>0) and ((oKeyEvent.modifiers and com.sun.star.awt.KeyModifier.SHIFT) <> 0)) isAnArrowPressed = ((oKeyEvent.keyCode = com.sun.star.awt.Key.UP) or (oKeyEvent.keyCode = com.sun.star.awt.Key.DOWN) or (oKeyEvent.keyCode = com.sun.star.awt.Key.LEFT) or (oKeyEvent.keyCode = com.sun.star.awt.Key.RIGHT)) 'Handle the keyEvent MoveText_keyPressed = false 'Let other listeners handle the event if (isAltPressedWithoutShift and isAnArrowPressed) then 'MsgBox("an arrow + Alt have been pressed", 0, "MoveText extension") if (oKeyEvent.keyCode = com.sun.star.awt.Key.LEFT) then moveTextToLeft endif if (oKeyEvent.keyCode = com.sun.star.awt.Key.RIGHT) then moveTextToRight endif if (oKeyEvent.keyCode = com.sun.star.awt.Key.UP) then moveTextOneLineUp endif if (oKeyEvent.keyCode = com.sun.star.awt.Key.DOWN) then moveTextOneLineDown endif MoveText_keyPressed = true 'Do not let other listeners process this event exit function endif if (areAltAndShiftPressed and isAnArrowPressed) then 'MsgBox("an arrow + Alt + Shift have been pressed", 0, "MoveText extension") if (oKeyEvent.keyCode = com.sun.star.awt.Key.LEFT) then moveTextToLeftByWord endif if (oKeyEvent.keyCode = com.sun.star.awt.Key.RIGHT) then moveTextToRightByWord endif if (oKeyEvent.keyCode = com.sun.star.awt.Key.UP) then moveTextOneParagraphUp endif if (oKeyEvent.keyCode = com.sun.star.awt.Key.DOWN) then moveTextOneParagraphDown endif MoveText_keyPressed = true 'Do not let other listeners process this event exit function endif end function REM Subs and functions dedicated to textCursor handling sub moveTextOneParagraphDown dim canMove as boolean dim moveTextString, textCursorString as string dim writerDoc, writerDocText, viewCursor, textCursor as object 'Initialize variables writerDoc = thisComponent writerDocText = writerDoc.Text viewCursor = writerDoc.getCurrentController().getViewCursor() 'Get the first selection as the string to move if (IsAnythingSelected(writerDoc)) then moveTextString = writerDoc.getCurrentSelection().getByIndex(0).String endif viewCursor.String = "" textCursor = writerDocText.createTextCursorByRange(viewCursor.getEnd()) textCursorString = "" canMove = textCursor.goRight(1, false) viewCursor.goRight(1, false) do while (canMove and (InStr(1, textCursorString, chr(10)) = 0)) canMove = textCursor.goRight(1, true) textCursorString = textCursor.String textCursor.collapseToEnd() viewCursor.goRight(1, false) viewCursor.collapseToEnd() loop if (viewCursor.goRight(1, false)) then viewCursor.gotoStartOfLine(false) endif viewCursor.String=moveTextString viewCursor.collapseToStart() viewCursor.goRight(len(moveTextString), true) end sub sub moveTextOneParagraphUp dim canMove as boolean dim moveTextString, textCursorString as string dim writerDoc, writerDocText, viewCursor, textCursor as object 'Initialize variables writerDoc = thisComponent writerDocText = writerDoc.Text viewCursor = writerDoc.getCurrentController().getViewCursor() 'Get the first selection as the string to move if (IsAnythingSelected(writerDoc)) then moveTextString = writerDoc.getCurrentSelection().getByIndex(0).String endif viewCursor.String = "" textCursor = writerDocText.createTextCursorByRange(viewCursor.getStart()) textCursorString = "" canMove = textCursor.goLeft(1, false) viewCursor.goLeft(1, false) do while (canMove and (InStr(1, textCursorString, chr(10)) = 0)) canMove = textCursor.goLeft(1, true) textCursorString = textCursor.String textCursor.collapseToStart() viewCursor.goLeft(1, false) viewCursor.collapseToStart() loop if (canMove) then viewCursor.goRight(1, false) viewCursor.gotoStartOfLine(false) endif viewCursor.collapseToStart() viewCursor.String=moveTextString viewCursor.collapseToStart() viewCursor.goRight(len(moveTextString), true) end sub sub moveTextOneLineDown dim writerDoc, viewCursor as object dim moveTextString as string writerDoc = thisComponent viewCursor = writerDoc.getCurrentController().getViewCursor() 'Get the first selection as the string to move if (IsAnythingSelected(writerDoc)) then moveTextString = writerDoc.getCurrentSelection().getByIndex(0).String endif viewCursor.String = "" viewCursor.gotoEndOfLine(false) viewCursor.goRight(1, false) viewCursor.gotoStartOfLine(false) viewCursor.collapseToEnd() viewCursor.String=moveTextString viewCursor.collapseToStart() viewCursor.goRight(len(moveTextString), true) end sub sub moveTextOneLineUp dim writerDoc, viewCursor as object dim moveTextString as string writerDoc = thisComponent viewCursor = writerDoc.getCurrentController().getViewCursor() 'Get the first selection as the string to move if (IsAnythingSelected(writerDoc)) then moveTextString = writerDoc.getCurrentSelection().getByIndex(0).String endif viewCursor.String = "" viewCursor.goLeft(1, false) viewCursor.gotoStartOfLine(false) viewCursor.collapseToStart() viewCursor.String=moveTextString viewCursor.collapseToStart() viewCursor.goRight(len(moveTextString), true) end sub sub moveTextToRight dim writerDoc, viewCursor as object dim moveTextString as string 'Initialize variables writerDoc = thisComponent viewCursor = writerDoc.getCurrentController().getViewCursor() 'Get the first selection as the string to move if (IsAnythingSelected(writerDoc)) then moveTextString = writerDoc.getCurrentSelection().getByIndex(0).String endif viewCursor.String = "" viewCursor.goRight(1, false) viewCursor.collapseToEnd() viewCursor.String=moveTextString viewCursor.collapseToStart() viewCursor.goRight(len(moveTextString), true) end sub sub moveTextToLeft dim writerDoc, viewCursor as object dim moveTextString as string 'Initialize variables writerDoc = thisComponent viewCursor = writerDoc.getCurrentController().getViewCursor() 'Get the first selection as the string to move if (IsAnythingSelected(writerDoc)) then moveTextString = writerDoc.getCurrentSelection().getByIndex(0).String endif viewCursor.String = "" viewCursor.goLeft(1, true) 'The following test avoids being stuck after a bullet if (len(viewCursor.String)>1) then viewCursor.goLeft(1, false) viewCursor.gotoEndOfLine(false) endif viewCursor.collapseToStart() viewCursor.String=moveTextString end sub sub moveTextToRightByWord dim canMove as boolean dim moveTextString, textCursorString as string dim writerDoc, writerDocText, viewCursor, textCursor as object 'Initialize variables writerDoc = thisComponent writerDocText = writerDoc.Text viewCursor = writerDoc.getCurrentController().getViewCursor() 'Get the first selection as the string to move if (IsAnythingSelected(writerDoc)) then moveTextString = writerDoc.getCurrentSelection().getByIndex(0).String endif viewCursor.String = "" textCursor = writerDocText.createTextCursorByRange(viewCursor.getStart()) textCursorString = "" canMove = true do while (canMove and keepMoving(textCursorString)) canMove = textCursor.goRight(1, true) textCursorString = textCursor.String textCursor.collapseToEnd() viewCursor.goRight(1, false) loop viewCursor.collapseToEnd() viewCursor.String=moveTextString viewCursor.collapseToStart() viewCursor.goRight(len(moveTextString), true) end sub sub moveTextToLeftByWord dim canMove as boolean dim moveTextString, textCursorString as string dim writerDoc, writerDocText, viewCursor, textCursor as object 'Initialize variables writerDoc = thisComponent writerDocText = writerDoc.Text viewCursor = writerDoc.getCurrentController().getViewCursor() 'Get the first selection as the string to move if (IsAnythingSelected(writerDoc)) then moveTextString = writerDoc.getCurrentSelection().getByIndex(0).String endif viewCursor.String = "" textCursor = writerDocText.createTextCursorByRange(viewCursor.getStart()) textCursorString = "" canMove = true do while (canMove and keepMoving(textCursorString)) canMove = textCursor.goLeft(1, true) textCursorString = textCursor.String textCursor.collapseToStart() viewCursor.goLeft(1, false) loop 'The following test avoids being stuck after a bullet if (len(textCursorString)>1) then viewCursor.goLeft(1, false) endif viewCursor.collapseToStart() viewCursor.String=moveTextString viewCursor.collapseToEnd() viewCursor.goLeft(len(moveTextString), true) end sub function keepMoving(testString as String) as boolean keepMoving = true if (len(testString) > 1) then keepMoving = false exit function endif if (testString = " ") then keepMoving = false exit function endif if ((testString="(")or(testString=")")) then keepMoving = false exit function endif if ((testString="{")or(testString="}")) then keepMoving = false exit function endif if ((testString="[")or(testString="]")) then keepMoving = false exit function endif if ((testString="+")or(testString="-")or(testString="*")or(testString="/")or(testString="%")or(testString="|")) then keepMoving = false exit function endif if ((testString=",")or(testString="?")or(testString=";")or(testString=".")or(testString=":")or(testString="!")) then keepMoving = false exit function endif end function Function IsAnythingSelected(oDoc) As Boolean 'From Andrew Pytonyak Dim oSels 'All of the selections Dim oSel 'A single selection Dim oCursor 'A temporary cursor IsAnythingSelected = False If IsNull(oDoc) Then Exit Function oSels = oDoc.getCurrentSelection() If IsNull(oSels) Then Exit Function If oSels.getCount() = 0 Then Exit Function REM If there are multiple selections, then certainly something is selected If oSels.getCount() > 1 Then IsAnythingSelected = True Else oSel = oSels.getByIndex(0) oCursor = oSel.getText().CreateTextCursorByRange(oSel) If Not(oCursor.IsCollapsed()) Then IsAnythingSelected = True End If End Function REM Sub attached to the MoveText button Sub Main_MoveTextButton dim message as String message = "MoveText extension is active. Use these commands to move text selection:" message = message+chr(10)+" - Alt + [left/right]: move selection sideways by character" message = message+chr(10)+" - Alt + [up/down]: move selection one line above/below" message = message+chr(10)+" - Alt + Shift + [left/right]: move selection sideways by word" message = message+chr(10)+" - Alt + Shift + [up/down]: move selection one paragraph above/below" isLucSorelOOoMoveTextActive = not(isLucSorelOOoMoveTextActive) if (isLucSorelOOoMoveTextActive) then SetupMoveTextKeyHandler MsgBox(message, 0, "MoveText extension") else RemoveMoveTextKeyHandler MsgBox("MoveText extension is not active.", 0, "MoveText extension") endif End Sub