Added initial support for hyperlinking.
diff --git a/com.google.eclipse.tm.terminal/META-INF/MANIFEST.MF b/com.google.eclipse.tm.terminal/META-INF/MANIFEST.MF
index 80445a7..b2cd922 100644
--- a/com.google.eclipse.tm.terminal/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.tm.terminal/META-INF/MANIFEST.MF
@@ -7,7 +7,8 @@
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime,
- org.eclipse.ui
+ org.eclipse.ui,
+ org.eclipse.jface.text
Bundle-ActivationPolicy: lazy
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/HttpHyperlinkFactory.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/HttpHyperlinkFactory.java
new file mode 100644
index 0000000..0a6a04b
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/HttpHyperlinkFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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.google.eclipse.terminal.ui.hyperlink;
+
+import java.util.*;
+import java.util.regex.*;
+
+import org.eclipse.jface.text.*;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class HttpHyperlinkFactory implements IHyperlinkFactory {
+ private static Pattern URL_PATTERN = Pattern.compile("http(s)?:\\/{2}[\\d\\w-]+(\\.[\\d\\w-]+)*(?:(?:\\/[^\\s/]*))*(\\:[\\d]+)?"); //$NON-NLS-1$
+
+ @Override public List<IHyperlink> hyperlinksIn(int column, String text) {
+ if (text == null) {
+ return NO_HYPERLINKS;
+ }
+ List<IHyperlink> hyperlinks = new ArrayList<IHyperlink>();
+ Matcher matcher = URL_PATTERN.matcher(text);
+ int start = 0;
+ while (matcher.find(start)) {
+ String url = matcher.group().trim();
+ if (url.isEmpty()) {
+ continue;
+ }
+ IRegion region = new Region(column + matcher.start(), url.length());
+ hyperlinks.add(new UrlHyperlink(region, url));
+ start = matcher.end();
+ }
+ return hyperlinks.isEmpty() ? NO_HYPERLINKS : hyperlinks;
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/IHyperlinkFactory.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/IHyperlinkFactory.java
new file mode 100644
index 0000000..cb9688a
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/IHyperlinkFactory.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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.google.eclipse.terminal.ui.hyperlink;
+
+import static java.util.Collections.emptyList;
+
+import java.util.List;
+
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public interface IHyperlinkFactory {
+ List<IHyperlink> NO_HYPERLINKS = emptyList();
+
+ List<IHyperlink> hyperlinksIn(int column, String text);
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/UrlHyperlink.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/UrlHyperlink.java
new file mode 100644
index 0000000..ba63446
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/UrlHyperlink.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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.google.eclipse.terminal.ui.hyperlink;
+
+import java.net.*;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.URLHyperlink;
+import org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
+import org.eclipse.ui.*;
+import org.eclipse.ui.browser.*;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class UrlHyperlink extends URLHyperlink {
+ public UrlHyperlink(IRegion region, String urlString) {
+ super(region, urlString);
+ }
+
+ @Override public void open() {
+ // Create the browser
+ IWorkbenchBrowserSupport support= PlatformUI.getWorkbench().getBrowserSupport();
+ IWebBrowser browser;
+ try {
+ browser= support.createBrowser(null);
+ } catch (PartInitException e) {
+ logErrorOpeningUrl(e);
+ return;
+ }
+ URL url = null;
+ try {
+ url = new URL(getURLString());
+ browser.openURL(url);
+ } catch (PartInitException e) {
+ openInExternalBrowser(url);
+ } catch (MalformedURLException e) {
+ logErrorOpeningUrl(e);
+ }
+ }
+
+ private void openInExternalBrowser(URL url) {
+ try {
+ PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL(url);
+ } catch (Exception e) {
+ logErrorOpeningUrl(e);
+ }
+ }
+
+ private void logErrorOpeningUrl(Exception e) {
+ e.printStackTrace();
+ String format = "Unable to open URL '%s'"; //$NON-NLS-1$
+ TerminalPlugin.log(String.format(format, getURLString()), e);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java
index d768582..ce5940b 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java
@@ -17,10 +17,12 @@
*******************************************************************************/
package org.eclipse.tm.internal.terminal.control.impl;
+import static org.eclipse.core.runtime.IStatus.ERROR;
+
import java.net.MalformedURLException;
import java.net.URL;
-import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.*;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.tm.internal.terminal.control.actions.ImageConsts;
@@ -81,4 +83,8 @@
ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(url);
imageRegistry.put(strKey, imageDescriptor);
}
+
+ public static void log(String message, Exception error) {
+ getDefault().getLog().log(new Status(ERROR, PLUGIN_ID, message, error));
+ }
}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java
index 362aa26..2944b40 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java
@@ -10,6 +10,9 @@
*******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;
+import java.util.List;
+
+import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.tm.terminal.model.Style;
public interface IVT100EmulatorBackend {
@@ -169,4 +172,5 @@
int getColumns();
+ List<IHyperlink> hyperlinksAt(int line);
}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java
index c4d57ab..4140843 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java
@@ -11,7 +11,9 @@
package org.eclipse.tm.internal.terminal.emulator;
import java.io.PrintStream;
+import java.util.List;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.tm.terminal.model.Style;
public class VT100BackendTraceDecorator implements IVT100EmulatorBackend {
@@ -141,4 +143,8 @@
fBackend.setStyle(style);
}
+ @Override
+ public List<IHyperlink> hyperlinksAt(int line) {
+ return fBackend.hyperlinksAt(line);
+ }
}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java
index 65ef50c..c82c6b0 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java
@@ -20,18 +20,14 @@
*******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
+import java.io.*;
+import java.util.List;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.tm.internal.terminal.control.impl.ITerminalControlForText;
-import org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
-import org.eclipse.tm.internal.terminal.provisional.api.Logger;
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-import org.eclipse.tm.terminal.model.Style;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.swt.events.*;
+import org.eclipse.tm.internal.terminal.control.impl.*;
+import org.eclipse.tm.internal.terminal.provisional.api.*;
+import org.eclipse.tm.terminal.model.*;
/**
* This class processes character data received from the remote host and
@@ -133,10 +129,11 @@
ansiParameters[i] = new StringBuffer();
}
setInputStreamReader(reader);
- if(TerminalPlugin.isOptionEnabled("org.eclipse.tm.terminal/debug/log/VT100Backend")) //$NON-NLS-1$
- text=new VT100BackendTraceDecorator(new VT100EmulatorBackend(data),System.out);
- else
- text=new VT100EmulatorBackend(data);
+ if(TerminalPlugin.isOptionEnabled("org.eclipse.tm.terminal/debug/log/VT100Backend")) {
+ text=new VT100BackendTraceDecorator(new VT100EmulatorBackend(data),System.out);
+ } else {
+ text=new VT100EmulatorBackend(data);
+ }
// text.setDimensions(24, 80);
Style style=Style.getStyle("BLACK", "WHITE"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -182,7 +179,8 @@
* This method is required by interface ControlListener. It allows us to
* know when the StyledText widget is moved.
*/
- public void controlMoved(ControlEvent event) {
+ @Override
+ public void controlMoved(ControlEvent event) {
Logger.log("entered"); //$NON-NLS-1$
// Empty.
}
@@ -191,7 +189,8 @@
* This method is required by interface ControlListener. It allows us to
* know when the StyledText widget is resized.
*/
- public void controlResized(ControlEvent event) {
+ @Override
+ public void controlResized(ControlEvent event) {
Logger.log("entered"); //$NON-NLS-1$
adjustTerminalDimensions();
}
@@ -212,8 +211,9 @@
public void fontChanged() {
Logger.log("entered"); //$NON-NLS-1$
- if (text != null)
- adjustTerminalDimensions();
+ if (text != null) {
+ adjustTerminalDimensions();
+ }
}
// /**
// * This method executes in the Display thread to process data received from
@@ -289,7 +289,9 @@
case '\n':
processNewline(); // Newline (Control-J)
if(fCrAfterNewLine)
- processCarriageReturn(); // Carriage Return (Control-M)
+ {
+ processCarriageReturn(); // Carriage Return (Control-M)
+ }
break;
case '\r':
@@ -607,8 +609,9 @@
private void processAnsiCommand_G() {
int targetColumn = 1;
- if (ansiParameters[0].length() > 0)
- targetColumn = getAnsiParameter(0) - 1;
+ if (ansiParameters[0].length() > 0) {
+ targetColumn = getAnsiParameter(0) - 1;
+ }
moveCursor(relativeCursorLine(), targetColumn);
}
@@ -628,10 +631,11 @@
private void processAnsiCommand_J() {
int ansiParameter;
- if (ansiParameters[0].length() == 0)
- ansiParameter = 0;
- else
- ansiParameter = getAnsiParameter(0);
+ if (ansiParameters[0].length() == 0) {
+ ansiParameter = 0;
+ } else {
+ ansiParameter = getAnsiParameter(0);
+ }
switch (ansiParameter) {
case 0:
@@ -848,8 +852,9 @@
// Do nothing if the numeric parameter was not 6 (which means report cursor
// position).
- if (getAnsiParameter(0) != 6)
- return;
+ if (getAnsiParameter(0) != 6) {
+ return;
+ }
// Send the ANSI cursor position (which is 1-based) to the remote endpoint.
@@ -890,8 +895,9 @@
String parameter = ansiParameters[parameterIndex].toString();
- if (parameter.length() == 0)
- return 1;
+ if (parameter.length() == 0) {
+ return 1;
+ }
int parameterValue = 1;
@@ -918,8 +924,9 @@
if (ch == ';') {
++nextAnsiParameter;
} else {
- if (nextAnsiParameter < ansiParameters.length)
- ansiParameters[nextAnsiParameter].append(ch);
+ if (nextAnsiParameter < ansiParameters.length) {
+ ansiParameters[nextAnsiParameter].append(ch);
+ }
}
}
/**
@@ -1061,8 +1068,9 @@
}
private ITerminalConnector getConnector() {
- if(terminal.getTerminalConnector()!=null)
- return terminal.getTerminalConnector();
+ if(terminal.getTerminalConnector()!=null) {
+ return terminal.getTerminalConnector();
+ }
return null;
}
@@ -1150,14 +1158,16 @@
c = fReader.read();
}
// TODO: better end of file handling
- if(c==-1)
- c=0;
+ if(c==-1) {
+ c=0;
+ }
return (char)c;
}
private boolean hasNextChar() throws IOException {
- if(fNextChar>=0)
- return true;
+ if(fNextChar>=0) {
+ return true;
+ }
return fReader.ready();
}
@@ -1180,4 +1190,8 @@
public void setCrAfterNewLine(boolean crAfterNewLine) {
fCrAfterNewLine = crAfterNewLine;
}
+
+ public List<IHyperlink> hyperlinksAt(int line) {
+ return text.hyperlinksAt(line);
+ }
}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java
index 3941862..a31ab2a 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java
@@ -1,18 +1,25 @@
/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, Inc. 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:
+ * 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:
* Michael Scharf (Wind River) - initial API and implementation
* Anton Leherbauer (Wind River) - [206329] Changing terminal size right after connect does not scroll properly
*******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-import org.eclipse.tm.terminal.model.Style;
+import static java.util.Collections.emptyList;
+
+import java.util.*;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.tm.terminal.model.*;
+
+import com.google.eclipse.terminal.ui.hyperlink.*;
/**
*
@@ -26,7 +33,7 @@
* {@link #widthInColumns} - 1. We track the cursor column using this field
* to avoid having to recompute it repeatly using StyledText method calls.
* <p>
- *
+ *
* The StyledText widget that displays text has a vertical bar (called the
* "caret") that appears _between_ character cells, but ANSI terminals have
* the concept of a cursor that appears _in_ a character cell, so we need a
@@ -35,7 +42,7 @@
* class is that the cursor is logically in column N when the caret is
* physically positioned immediately to the _left_ of column N.
* <p>
- *
+ *
* When fCursorColumn is N, the next character output to the terminal appears
* in column N. When a character is output to the rightmost column on a
* given line (column widthInColumns - 1), the cursor moves to column 0 on
@@ -52,14 +59,18 @@
int fLines;
int fColumns;
final private ITerminalTextData fTerminal;
+
+ private final IHyperlinkFactory urlHyperlinkFactory = new HttpHyperlinkFactory();
+ private final Map<Integer, List<IHyperlink>> hyperlinks = new HashMap<Integer, List<IHyperlink>>();
+
public VT100EmulatorBackend(ITerminalTextData terminal) {
fTerminal=terminal;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#clearAll()
*/
- public void clearAll() {
+ public void clearAll() {
synchronized (fTerminal) {
// clear the history
int n=fTerminal.getHeight();
@@ -74,10 +85,12 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setDimensions(int, int)
*/
- public void setDimensions(int lines, int cols) {
+ public void setDimensions(int lines, int cols) {
synchronized (fTerminal) {
if(lines==fLines && cols==fColumns)
- return; // nothing to do
+ {
+ return; // nothing to do
+ }
// relative cursor line
int cl=getCursorLine();
int cc=getCursorColumn();
@@ -102,7 +115,7 @@
setCursor(cl, cc);
}
}
-
+
int toAbsoluteLine(int line) {
synchronized (fTerminal) {
return fTerminal.getHeight()-fLines+line;
@@ -111,7 +124,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#insertCharacters(int)
*/
- public void insertCharacters(int charactersToInsert) {
+ public void insertCharacters(int charactersToInsert) {
synchronized (fTerminal) {
int line=toAbsoluteLine(fCursorLine);
int n=charactersToInsert;
@@ -130,19 +143,19 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseToEndOfScreen()
*/
- public void eraseToEndOfScreen() {
+ public void eraseToEndOfScreen() {
synchronized (fTerminal) {
eraseLineToEnd();
for (int line = toAbsoluteLine(fCursorLine+1); line < toAbsoluteLine(fLines); line++) {
fTerminal.cleanLine(line);
}
}
-
+
}
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseToCursor()
*/
- public void eraseToCursor() {
+ public void eraseToCursor() {
synchronized (fTerminal) {
for (int line = toAbsoluteLine(0); line < toAbsoluteLine(fCursorLine); line++) {
fTerminal.cleanLine(line);
@@ -153,7 +166,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseAll()
*/
- public void eraseAll() {
+ public void eraseAll() {
synchronized (fTerminal) {
for (int line = toAbsoluteLine(0); line < toAbsoluteLine(fLines); line++) {
fTerminal.cleanLine(line);
@@ -163,7 +176,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseLine()
*/
- public void eraseLine() {
+ public void eraseLine() {
synchronized (fTerminal) {
fTerminal.cleanLine(toAbsoluteLine(fCursorLine));
}
@@ -171,33 +184,36 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseLineToEnd()
*/
- public void eraseLineToEnd() {
+ public void eraseLineToEnd() {
synchronized (fTerminal) {
int line=toAbsoluteLine(fCursorLine);
for (int col = fCursorColumn; col < fColumns; col++) {
fTerminal.setChar(line, col, '\000', null);
}
}
- }
+ }
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseLineToCursor()
*/
- public void eraseLineToCursor() {
+ @Override
+ public void eraseLineToCursor() {
synchronized (fTerminal) {
int line=toAbsoluteLine(fCursorLine);
for (int col = 0; col <= fCursorColumn; col++) {
fTerminal.setChar(line, col, '\000', null);
}
}
- }
+ }
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#insertLines(int)
*/
- public void insertLines(int n) {
+ @Override
+ public void insertLines(int n) {
synchronized (fTerminal) {
- if(!isCusorInScrollingRegion())
- return;
+ if(!isCusorInScrollingRegion()) {
+ return;
+ }
assert n>0;
int line=toAbsoluteLine(fCursorLine);
int nLines=fTerminal.getHeight()-line;
@@ -207,7 +223,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#deleteCharacters(int)
*/
- public void deleteCharacters(int n) {
+ public void deleteCharacters(int n) {
synchronized (fTerminal) {
int line=toAbsoluteLine(fCursorLine);
for (int col = fCursorColumn+n; col < fColumns; col++) {
@@ -224,10 +240,12 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#deleteLines(int)
*/
- public void deleteLines(int n) {
+ @Override
+ public void deleteLines(int n) {
synchronized (fTerminal) {
- if(!isCusorInScrollingRegion())
- return;
+ if(!isCusorInScrollingRegion()) {
+ return;
+ }
assert n>0;
int line=toAbsoluteLine(fCursorLine);
int nLines=fTerminal.getHeight()-line;
@@ -242,7 +260,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getDefaultStyle()
*/
- public Style getDefaultStyle() {
+ public Style getDefaultStyle() {
synchronized (fTerminal) {
return fDefaultStyle;
}
@@ -251,7 +269,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setDefaultStyle(org.eclipse.tm.terminal.model.Style)
*/
- public void setDefaultStyle(Style defaultStyle) {
+ public void setDefaultStyle(Style defaultStyle) {
synchronized (fTerminal) {
fDefaultStyle = defaultStyle;
}
@@ -260,17 +278,18 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getStyle()
*/
- public Style getStyle() {
+ public Style getStyle() {
synchronized (fTerminal) {
- if(fStyle==null)
- return fDefaultStyle;
+ if(fStyle==null) {
+ return fDefaultStyle;
+ }
return fStyle;
}
}
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setStyle(org.eclipse.tm.terminal.model.Style)
*/
- public void setStyle(Style style) {
+ public void setStyle(Style style) {
synchronized (fTerminal) {
fStyle=style;
}
@@ -278,10 +297,16 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#appendString(java.lang.String)
*/
- public void appendString(String buffer) {
+ public void appendString(String buffer) {
synchronized (fTerminal) {
char[] chars=buffer.toCharArray();
int line=toAbsoluteLine(fCursorLine);
+ int originalLine = line;
+ List<IHyperlink> found = emptyList();
+ if (buffer != null) {
+ found = urlHyperlinkFactory.hyperlinksIn(fCursorColumn, buffer);
+ hyperlinks.put(new Integer(line), found);
+ }
int i=0;
while (i < chars.length) {
int n=Math.min(fColumns-fCursorColumn,chars.length-i);
@@ -297,9 +322,25 @@
setCursorColumn(col);
}
}
+ drawHyperlinks(found, originalLine);
}
}
+ private void drawHyperlinks(List<IHyperlink> hyperlinks, int line) {
+ for (IHyperlink hyperlink : hyperlinks) {
+ IRegion region = hyperlink.getHyperlinkRegion();
+ int start = region.getOffset();
+ int end = start + region.getLength();
+ for (int column = start; column < end; column++) {
+ Style style = fTerminal.getStyle(line, column);
+ if (style != null) {
+ style = style.setUnderline(true);
+ fTerminal.setChar(line, column, fTerminal.getChar(line, column), style);
+ }
+ }
+ }
+ }
+
/**
* MUST be called from a synchronized block!
*/
@@ -307,8 +348,9 @@
if(fCursorLine+1>=fLines) {
int h=fTerminal.getHeight();
fTerminal.addLine();
- if(h!=fTerminal.getHeight())
- setCursorLine(fCursorLine+1);
+ if(h!=fTerminal.getHeight()) {
+ setCursorLine(fCursorLine+1);
+ }
} else {
setCursorLine(fCursorLine+1);
}
@@ -316,7 +358,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#processNewline()
*/
- public void processNewline() {
+ public void processNewline() {
synchronized (fTerminal) {
doNewline();
}
@@ -324,7 +366,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getCursorLine()
*/
- public int getCursorLine() {
+ public int getCursorLine() {
synchronized (fTerminal) {
return fCursorLine;
}
@@ -332,7 +374,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getCursorColumn()
*/
- public int getCursorColumn() {
+ public int getCursorColumn() {
synchronized (fTerminal) {
return fCursorColumn;
}
@@ -340,7 +382,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setCursor(int, int)
*/
- public void setCursor(int targetLine, int targetColumn) {
+ public void setCursor(int targetLine, int targetColumn) {
synchronized (fTerminal) {
setCursorLine(targetLine);
setCursorColumn(targetColumn);
@@ -350,12 +392,13 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setCursorColumn(int)
*/
- public void setCursorColumn(int targetColumn) {
+ public void setCursorColumn(int targetColumn) {
synchronized (fTerminal) {
- if(targetColumn<0)
- targetColumn=0;
- else if(targetColumn>=fColumns)
- targetColumn=fColumns-1;
+ if(targetColumn<0) {
+ targetColumn=0;
+ } else if(targetColumn>=fColumns) {
+ targetColumn=fColumns-1;
+ }
fCursorColumn=targetColumn;
// We make the assumption that nobody is changing the
// terminal cursor except this class!
@@ -367,12 +410,13 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setCursorLine(int)
*/
- public void setCursorLine(int targetLine) {
+ public void setCursorLine(int targetLine) {
synchronized (fTerminal) {
- if(targetLine<0)
- targetLine=0;
- else if(targetLine>=fLines)
- targetLine=fLines-1;
+ if(targetLine<0) {
+ targetLine=0;
+ } else if(targetLine>=fLines) {
+ targetLine=fLines-1;
+ }
fCursorLine=targetLine;
// We make the assumption that nobody is changing the
// terminal cursor except this class!
@@ -384,7 +428,7 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getLines()
*/
- public int getLines() {
+ public int getLines() {
synchronized (fTerminal) {
return fLines;
}
@@ -393,9 +437,17 @@
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getColumns()
*/
- public int getColumns() {
+ public int getColumns() {
synchronized (fTerminal) {
return fColumns;
}
}
+
+ public List<IHyperlink> hyperlinksAt(int line) {
+ List<IHyperlink> found = hyperlinks.get(new Integer(line));
+ if (found == null) {
+ return emptyList();
+ }
+ return found;
+ }
}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
index a69e07a..b8a70ca 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
@@ -35,10 +35,13 @@
import java.io.*;
import java.net.SocketException;
+import java.util.List;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
@@ -572,7 +575,24 @@
snapshot.updateSnapshot(false);
ITextCanvasModel canvasModel=new PollingTextCanvasModel(snapshot);
fCtlText=new TextCanvas(fWndParent,canvasModel,SWT.NONE,new TextLineRenderer(fCtlText,canvasModel));
-
+ fCtlText.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseUp(MouseEvent e) {
+ Point p = fCtlText.screenPointToCell(e.x, e.y);
+ if (p == null) {
+ return;
+ }
+ List<IHyperlink> hyperlinks = fTerminalText.hyperlinksAt(p.y);
+ for (IHyperlink hyperlink : hyperlinks) {
+ IRegion region = hyperlink.getHyperlinkRegion();
+ int start = region.getOffset();
+ int end = start + region.getLength() - 1;
+ if (p.x >= start && p.x <= end) {
+ hyperlink.open();
+ }
+ }
+ }
+ });
fCtlText.setLayoutData(new GridData(GridData.FILL_BOTH));
fCtlText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
index 181604c..7b60217 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
@@ -429,5 +429,9 @@
fCellRenderer.setFont(font);
redraw();
}
+
+ @Override public Point screenPointToCell(int x, int y) {
+ return super.screenPointToCell(x, y);
+ }
}