/** * Copyright (c) 2009, 2010 Mark Feber, MulgaSoft * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package com.mulgasoft.emacsplus.commands; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.TextSelection; import org.eclipse.ui.texteditor.ITextEditor; import com.mulgasoft.emacsplus.MarkUtils; /** * Implements: mark-paragraph * * Put point and mark around this or next paragraph * * If current selection is empty and inside a paragraph, mark the enclosing paragraph, * else the following or preceding one(s) depending on the value of the universal arg. * If current selection is not empty, mark the following, or preceding paragraph (or * paragraph section, if the entire paragraph is not currently selected). * * @author Mark Feber - initial API and implementation */ public class ParagraphMarkHandler extends ParagraphHandler { /** * @see com.mulgasoft.emacsplus.commands.EmacsPlusCmdHandler#transform(ITextEditor, IDocument, ITextSelection, ExecutionEvent) */ @Override protected int transform(ITextEditor editor, IDocument document, ITextSelection currentSelection, ExecutionEvent event) throws BadLocationException { boolean forward = getUniversalCount() > 0; if (forward && isAtBottom(editor,document,currentSelection)) { // nowhere to go & Emacs doesn't beep in this state // Emacs actually selects the previous paragraph in this state which seems wrong } else if (!forward && isAtTop(editor,currentSelection)) { // nowhere to go & Emacs doesn't beep in this state // Emacs actually selects the following paragraph in this state which seems wrong } else if (currentSelection.getLength() == 0) { // select entire paragraph int line = document.getLineOfOffset(getCursorOffset(editor,currentSelection)); // are we inside a paragraph? if (!isBlank(document,line)) { int begin = (forward ? getParagraphOffset(editor,false) : getParagraphOffset(editor,true)); setSelection(editor,currentSelection); // restore for movement in reverse direction int end = (forward ? getParagraphOffset(editor,true) : getParagraphOffset(editor,false)); // invert selection so cursor appears at correct end ITextSelection selection = new TextSelection(document, end, begin - end); setMark(editor,end); setSelection(editor,selection); MarkUtils.revealRange(editor, end, 0); } else { setMark(editor,currentSelection.getOffset()); nextParagraph(editor, document, currentSelection, forward); } } else { nextParagraph(editor, document, currentSelection, forward); } return NO_OFFSET; } private void nextParagraph(ITextEditor editor, IDocument document, ITextSelection selection, boolean forward) { int cursorOffset = MarkUtils.getCursorOffset(editor); int offset = NO_OFFSET; MarkUtils.setSelection(editor,getMark(editor),0); // select next in appropriate direction try { if (forward) { int line = document.getLineOfOffset(getCursorOffset(editor,selection)); // are we at the beginning of a multi-line blank section? if (isBlank(document,line) && isBlank(document,line+1)) { // then jump over it getParagraphOffset(editor,true); } offset = getParagraphOffset(editor,true); } else { offset = getParagraphOffset(editor,false); } } catch (BadLocationException e) { // should only happen if we're already at the end // restore the selection highlight reverseSelection(editor,document,selection); } catch (IndexOutOfBoundsException e) { // should only happen if we've moved to the top // work around bug in org.eclipse.jface.text.TextViewer.findAndSelect() // where it doesn't check for 0 offset & 0 length offset = 0; } if (offset != NO_OFFSET) { setMark(editor,offset,false); setSelection(editor,new TextSelection(document, offset, (cursorOffset - offset))); MarkUtils.revealRange(editor, offset, 0); } } private void reverseSelection(ITextEditor editor, IDocument document, ITextSelection selection) { // invert selection so cursor appears at correct end int end = selection.getOffset() + selection.getLength(); setSelection(editor,new TextSelection(document,end,-selection.getLength())); } }