blob: af1a57a92ca5fb4654ffdc3c6897bc8594eb4b07 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 - 2006 Mylar committers 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
*******************************************************************************/
package org.eclipse.mylyn.internal.tasks.ui.editors;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.URLHyperlink;
import org.eclipse.mylyn.tasks.ui.TasksUiUtil;
/**
* @author Rob Elves
*/
public class TaskEditorUrlHyperlinkDetector implements IHyperlinkDetector {
// URL BNF: http://www.foad.org/~abigail/Perl/url2.html
// Source:
// http://www.truerwords.net/articles/ut/urlactivation.html#expressions
// Original pattern: (^|[
// \\t\\r\\n])((ftp|http|https|gopher|mailto|news|nntp|telnet|wais|file|prospero|aim|webcal):(([A-Za-z0-9$_.+!*(),;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*(),;/?:@&~=%-]*))?([A-Za-z0-9$_+!*();/?:~-]))
private static final Pattern urlPattern = Pattern
.compile(
"((ftp|http|https|gopher|mailto|news|nntp|telnet|wais|file|prospero|aim|webcal):(([A-Za-z0-9$_.+!*,;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*,;/?:@&~=%-]*))?([A-Za-z0-9$_+!*;/?:~-]))",
Pattern.CASE_INSENSITIVE);
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
if (region == null || textViewer == null)
return null;
IDocument document = textViewer.getDocument();
List<IHyperlink> hyperlinksFound = new ArrayList<IHyperlink>();
int offset = region.getOffset();
if (document == null)
return null;
IRegion lineInfo;
String line;
try {
lineInfo = document.getLineInformationOfOffset(offset);
line = document.get(lineInfo.getOffset(), lineInfo.getLength());
} catch (BadLocationException ex) {
return null;
}
int offsetInLine = offset - lineInfo.getOffset();
Matcher m = urlPattern.matcher(line);
while (m.find()) {
if (offsetInLine >= m.start() && offsetInLine <= m.end()) {
IHyperlink link = extractHyperlink(lineInfo.getOffset(), m);
if (link != null)
hyperlinksFound.add(link);
}
}
if (hyperlinksFound.size() > 0) {
return hyperlinksFound.toArray(new IHyperlink[hyperlinksFound.size()]);
}
return null;
}
private TaskEditorUrlHyperlink extractHyperlink(int lineOffset, Matcher m) {
int start = m.start();
int end = m.end();
if (end == -1)
end = m.group().length();
start += lineOffset;
end += lineOffset;
IRegion sregion = new Region(start, end - start);
return new TaskEditorUrlHyperlink(sregion, m.group());
}
static class TaskEditorUrlHyperlink extends URLHyperlink {
public TaskEditorUrlHyperlink(IRegion region, String urlString) {
super(region, urlString);
}
@Override
public void open() {
// TODO: if url is to a repository task, open task instead of url
TasksUiUtil.openBrowser(getURLString());
}
}
}