/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.ui.text;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.ICharacterPairMatcher;
import org.eclipse.php.internal.core.documentModel.parser.regions.IPHPScriptRegion;
import org.eclipse.php.internal.ui.editor.PHPPairMatcher;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
import org.eclipse.wst.sse.ui.internal.text.DocumentRegionEdgeMatcher;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
public class PHPDocumentRegionEdgeMatcher extends DocumentRegionEdgeMatcher {
protected final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
/**
* @param validContexts
* @param nextMatcher
*/
public PHPDocumentRegionEdgeMatcher() {
super(new String[] { DOMRegionContext.XML_TAG_NAME, DOMRegionContext.XML_COMMENT_TEXT,
DOMRegionContext.XML_CDATA_TEXT, DOMRegionContext.XML_PI_OPEN, DOMRegionContext.XML_PI_CONTENT },
new PHPPairMatcher(BRACKETS));
}
@Override
public IRegion match(IDocument document, int offset) {
if (offset < 0 || offset > document.getLength())
return null;
IRegion match = null;
if (!fRegionTypes.isEmpty() && document instanceof IStructuredDocument) {
IStructuredDocumentRegion docRegion = ((IStructuredDocument) document).getRegionAtCharacterOffset(offset);
if (docRegion != null) {
// look at the previous document region first since its end ==
// this one's start
if (docRegion.getPrevious() != null && docRegion.getPrevious().getEndOffset() == offset
&& fRegionTypes.contains(docRegion.getPrevious().getType())) {
fAnchor = ICharacterPairMatcher.RIGHT;
match = new Region(docRegion.getPrevious().getStartOffset(), 1);
}
// check for offset in the last text region for a match to
// document region start offset
else if (fRegionTypes.contains(docRegion.getType())
&& docRegion.getStartOffset(docRegion.getLastRegion()) <= offset
&& offset <= docRegion.getEndOffset(docRegion.getLastRegion())) {
fAnchor = ICharacterPairMatcher.RIGHT;
match = new Region(docRegion.getStartOffset(), 1);
}
// check for offset in the first text region for a match to
// document region end offset
else if (fRegionTypes.contains(docRegion.getType())) {
if (docRegion.getStartOffset(docRegion.getFirstRegion()) <= offset
&& offset <= docRegion.getEndOffset(docRegion.getFirstRegion())) {
fAnchor = ICharacterPairMatcher.LEFT;
match = new Region(docRegion.getEndOffset() - 1, 1);
}
}
if (match == null) {
/* Now check the text region */
ITextRegion currentTextRegion = docRegion.getRegionAtCharacterOffset(offset);
// in case of container we have to extract the
// PhpScriptRegion
if (currentTextRegion instanceof ITextRegionContainer) {
ITextRegionContainer container = (ITextRegionContainer) currentTextRegion;
currentTextRegion = container.getRegionAtCharacterOffset(offset);
}
if (currentTextRegion instanceof IPHPScriptRegion) {
IPHPScriptRegion scriptRegion = (IPHPScriptRegion) currentTextRegion;
try {
currentTextRegion = scriptRegion
.getPHPToken(offset - docRegion.getStartOffset(scriptRegion));
if (currentTextRegion.getTextLength() > 1) {
int offsetAtNearEdge = offset;
if (offset == docRegion.getTextEndOffset(currentTextRegion)) {
offsetAtNearEdge = offset - 1;
} else if (offset == docRegion.getStartOffset(currentTextRegion) + 1) {
offsetAtNearEdge = offset - 1;
}
if (offsetAtNearEdge == docRegion.getStartOffset(currentTextRegion)) {
int end = docRegion.getTextEndOffset(currentTextRegion);
try {
if (document.getChar(offsetAtNearEdge) == document.getChar(end - 1)) {
fAnchor = ICharacterPairMatcher.LEFT;
match = new Region(end - 1, 1);
}
} catch (BadLocationException e) {
// nothing, not important enough
}
} else if (offsetAtNearEdge == docRegion.getTextEndOffset(currentTextRegion) - 1) {
int start = docRegion.getStartOffset(currentTextRegion);
if (document.getChar(offsetAtNearEdge) == document.getChar(start)) {
fAnchor = ICharacterPairMatcher.RIGHT;
match = new Region(start, 1);
}
}
}
} catch (BadLocationException e) {
// nothing, not important enough
}
}
}
}
}
try {
// blank char
if (match != null && match.getLength() == 1) {
char currChar = document.getChar(match.getOffset());
// System.out.println((int) currChar);
if (currChar == 32 || currChar == 9) {
match = null;
}
}
} catch (BadLocationException e) {
}
if (match == null && fNextMatcher != null) {
fAnchor = -1;
match = fNextMatcher.match(document, offset);
}
return match;
}
}