/**
* 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.Position;
import org.eclipse.ui.console.IConsoleView;
import org.eclipse.ui.console.TextConsoleViewer;
import org.eclipse.ui.texteditor.ITextEditor;
import com.mulgasoft.emacsplus.MarkUtils;
/**
* Implements: set-mark-command
*
* Correct the Eclipse behavior of set-mark
*
* - Clears any previous selection
* - Supports pushing and popping of mark
*
* @author Mark Feber - initial API and implementation
*/
public class MarkSetHandler extends EmacsPlusNoEditHandler implements IConsoleDispatch {
/**
* @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 {
int offset = getCursorOffset(editor,currentSelection);
try {
boolean hadSel = currentSelection.getLength() > 0;
boolean markState = false; // deactivates mark
switch (getShift(event)) {
case CLEAR:
MarkUtils.setSelection(editor,offset,0);
break;
case SET:
MarkUtils.setSelection(editor,offset,0);
setMark(editor,offset);
markState = true;
break;
default:
EmacsMovementHandler.clearShifted(); // normal set mark always removes shift select flag
if (hadSel) {
// this will remove any selection, so internal mark code won't get confused
setCursorOffset(editor,offset);
}
if (getUniversalCount() >= 4) {
// Pop the new mark and use the old mark as pos
Position markAndPos = MarkUtils.popMark(editor,document);
if (markAndPos != null) {
int pos = markAndPos.getOffset();
selectAndReveal(editor,pos,pos);
setMark(editor,markAndPos.getLength(),false); // set it as current mark, but don't save again
}
} else if (getUniversalCount() > 1) {
// command version of push-mark without activating
setMark(editor,offset); // command version of C-<SPC> C-<SPC>
} else {
if (!isFlagMark()) {
setMark(editor,offset);
}
//if called with C-<SPC> C-<SPC>: Set the mark, pushing it onto the mark ring, without activating it.
markState = (hadSel || !isFlagMark());
}
}
setFlagMark(markState);
} catch (Exception e) {}
return NO_OFFSET;
}
private ShiftState getShift(ExecutionEvent event) {
try {
String shiftArg = event.getParameter(SHIFT_ARG);
if (shiftArg != null && shiftArg.length() > 0) {
return ShiftState.valueOf(shiftArg);
}
} catch (Exception e) {} //ignore
return ShiftState.NONE;
}
/**
* @see com.mulgasoft.emacsplus.commands.EmacsPlusCmdHandler#isLooping()
*/
@Override
protected boolean isLooping() {
return false;
}
/**
* Support simple mark on TextConsole
*
* @see com.mulgasoft.emacsplus.commands.IConsoleDispatch#consoleDispatch(TextConsoleViewer, IConsoleView, ExecutionEvent)
*/
public Object consoleDispatch(TextConsoleViewer viewer, IConsoleView activePart, ExecutionEvent event) {
int offset = viewer.getTextWidget().getCaretOffset();
viewer.setSelectedRange(offset, 0);
viewer.setMark(offset);
return null;
}
}