summaryrefslogtreecommitdiff
path: root/NET/worlds/console/GammaTextArea.java
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-12 22:33:32 -0800
committerFuwn <[email protected]>2026-02-12 22:33:32 -0800
commitc7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch)
treedf9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/console/GammaTextArea.java
downloadworldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz
worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip
Initial commit
Diffstat (limited to 'NET/worlds/console/GammaTextArea.java')
-rw-r--r--NET/worlds/console/GammaTextArea.java923
1 files changed, 923 insertions, 0 deletions
diff --git a/NET/worlds/console/GammaTextArea.java b/NET/worlds/console/GammaTextArea.java
new file mode 100644
index 0000000..d470e42
--- /dev/null
+++ b/NET/worlds/console/GammaTextArea.java
@@ -0,0 +1,923 @@
+package NET.worlds.console;
+
+import NET.worlds.core.IniFile;
+import NET.worlds.scape.SendURLAction;
+import NET.worlds.scape.TeleportAction;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.PopupMenu;
+import java.awt.Scrollbar;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class GammaTextArea extends Panel implements AdjustmentListener, ActionListener {
+ private static final long serialVersionUID = 4042890054976563288L;
+ public static final int SCROLLBARS_BOTH = 1;
+ public static final int SCROLLBARS_VERTICAL_ONLY = 2;
+ public static final int SCROLLBARS_HORIZONTAL_ONLY = 3;
+ public static final int SCROLLBARS_NONE = 4;
+ protected static final int _margin = 2;
+ private int _width;
+ private int _height;
+ private StyledTextCanvas _canvas;
+ private String _string;
+ private Font _font;
+ private int _currentStyle;
+ private String _currentFontName;
+ private int _currentPointSize;
+ private Color _currentColor;
+ private GammaTextScrollbar _vertBar;
+ private GammaTextScrollbar _horzBar;
+ private int _numLines;
+ private int _canvasLines;
+ private int _scrollLine;
+ private Vector<String> _lines;
+ private Vector<Integer> _pos;
+ private int _lastpos = 0;
+ protected int _curpos = 0;
+ protected boolean _hasFocus;
+ protected int selectionStart = -1;
+ protected int selectionEnd = -1;
+ private static final Color skyblue = new Color(135, 206, 255);
+ private PopupMenu rightMenu;
+ private MenuItem textCopyItem = new MenuItem(Console.message("Copy"));
+ private MenuItem textCopyTextItem = new MenuItem(Console.message("Copy Text"));
+ private MenuItem textCopyAllItem = new MenuItem(Console.message("Copy All"));
+ private MenuItem textCopyAllTextItem = new MenuItem(Console.message("Copy All Text"));
+ private MenuItem textOpenURLItem = new MenuItem(Console.message("Open URL"));
+ static Color bgColor = null;
+ private int _numColumns;
+ private int _numRows;
+ private static int scrollWheelStep = IniFile.gamma().getIniInt("ScrollWheelStep", 3);
+ public static String boldStartTag = "<b>";
+ public static String boldEndTag = "</b>";
+ public static String italicStartTag = "<i>";
+ public static String italicEndTag = "</i>";
+ public static String colorStartMagentaTag = "<color=\"#FF00FF\">";
+ public static String colorStartBlueTag = "<color=\"#0000FF\">";
+ public static String colorStartRedTag = "<color=\"#FF0000\">";
+ public static String colorStartGreenTag = "<color=\"#00FF00\">";
+ public static String colorEndTag = "</color>";
+ public static String colorMagenta2Tag = "<color=magenta>";
+ public static String colorBlue2Tag = "<color=blue>";
+ public static String colorRed2Tag = "<color=red>";
+ public static String colorGreen2Tag = "<color=green>";
+ public static String colorCyanTag = "<color=cyan>";
+ public static String colorDarkGrayTag = "<color=darkgray>";
+ public static String colorGrayTag = "<color=gray>";
+ public static String colorOrangeTag = "<color=orange>";
+ public static String colorPinkTag = "<color=pink>";
+ public static String colorYellowTag = "<color=yellow>";
+ public static String colorWhiteTag = "<color=white>";
+ public static String colorLightGrayTag = "<color=lightgray>";
+ public static EmoteHandler emotes = new EmoteHandler();
+ protected static String[] tagList = new String[]{
+ boldStartTag,
+ boldEndTag,
+ italicStartTag,
+ italicEndTag,
+ colorStartMagentaTag,
+ colorStartRedTag,
+ colorStartGreenTag,
+ colorStartBlueTag,
+ colorEndTag,
+ colorMagenta2Tag,
+ colorBlue2Tag,
+ colorRed2Tag,
+ colorGreen2Tag,
+ colorCyanTag,
+ colorDarkGrayTag,
+ colorGrayTag,
+ colorOrangeTag,
+ colorPinkTag,
+ colorYellowTag,
+ colorWhiteTag,
+ colorLightGrayTag
+ };
+ private int lastWidth = 0;
+ protected boolean selectionConversion = false;
+ protected int _initialSelection = -1;
+
+ @Override
+ public Font getFont() {
+ return this._font;
+ }
+
+ @Override
+ public int getWidth() {
+ return this._width;
+ }
+
+ @Override
+ public int getHeight() {
+ return this._height;
+ }
+
+ public synchronized void setWidth(int w) {
+ this._width = w - 4;
+ }
+
+ public synchronized void setHeight(int h) {
+ this._height = h - 4;
+ }
+
+ public Vector<String> getLines() {
+ return this._lines;
+ }
+
+ public int getScrollLine() {
+ return this._scrollLine;
+ }
+
+ public int getCanvasLines() {
+ return this._canvasLines;
+ }
+
+ public int getNumLines() {
+ return this._numLines;
+ }
+
+ public boolean getHasFocus() {
+ return this._hasFocus;
+ }
+
+ public Scrollbar getVertScrollbar() {
+ return this._vertBar;
+ }
+
+ static Color getBackgroundColor() {
+ if (bgColor == null) {
+ int bgR = IniFile.override().getIniInt("chatBgR", 255);
+ int bgG = IniFile.override().getIniInt("chatBgG", 255);
+ int bgB = IniFile.override().getIniInt("chatBgB", 203);
+ bgColor = new Color(bgR, bgG, bgB);
+ }
+
+ return bgColor;
+ }
+
+ GammaTextArea(String text, int rows, int columns, int scrollbars) {
+ this._string = text;
+ this._numColumns = columns;
+ this._numRows = rows;
+ this._currentFontName = Console.message("GammaTextFont");
+ this._currentStyle = 0;
+ this._currentPointSize = IniFile.gamma().getIniInt("ChatFontSize", 12);
+ this._currentColor = Color.black;
+ this._canvas = new StyledTextCanvas();
+ this.setFontSize(this._currentPointSize);
+ this._lines = new Vector<String>();
+ this._pos = new Vector<Integer>();
+ this._lastpos = 0;
+ this._hasFocus = false;
+ this._numLines = this._scrollLine = this._canvasLines = 0;
+ switch (scrollbars) {
+ case 1:
+ this._vertBar = new GammaTextScrollbar(1);
+ this._horzBar = new GammaTextScrollbar(0);
+ break;
+ case 2:
+ this._vertBar = new GammaTextScrollbar(1);
+ this._horzBar = null;
+ break;
+ case 3:
+ this._vertBar = null;
+ this._horzBar = new GammaTextScrollbar(0);
+ break;
+ case 4:
+ this._vertBar = this._horzBar = null;
+ }
+
+ GridBagLayout gridbag = new GridBagLayout();
+ this.setLayout(gridbag);
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = 1;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ gridbag.setConstraints(this._canvas, c);
+ this.add(this._canvas);
+ if (this._vertBar != null) {
+ c = new GridBagConstraints();
+ c.fill = 3;
+ c.gridwidth = 0;
+ gridbag.setConstraints(this._vertBar, c);
+ this.add(this._vertBar);
+ this._vertBar.addAdjustmentListener(this);
+ }
+
+ if (this._horzBar != null) {
+ c = new GridBagConstraints();
+ c.fill = 2;
+ c.gridwidth = 1;
+ this.add(this._horzBar);
+ this._horzBar.addAdjustmentListener(this);
+ }
+
+ this.enableEvents(131231L);
+ this._canvas.repaint();
+ }
+
+ public synchronized void setFontSize(int fontsize) {
+ this._currentPointSize = fontsize;
+ this._font = new Font(this._currentFontName, this._currentStyle, this._currentPointSize);
+ this.recalcSize();
+ }
+
+ public synchronized void setRows(int rows) {
+ this._numRows = rows;
+ this.recalcSize();
+ }
+
+ public synchronized void recalcSize() {
+ FontMetrics fm = this._canvas.getFontMetrics(this._font);
+
+ assert fm != null;
+
+ int w = fm.charWidth('M') * this._numColumns;
+ int h = fm.getHeight() * this._numRows;
+ this.setWidth(w);
+ this.setHeight(h);
+ this._canvas.setSize(w, h);
+ this.setWidth(w);
+ this.setHeight(h);
+ }
+
+ @Override
+ public void update(Graphics g) {
+ this.paint(g);
+ }
+
+ @Override
+ protected synchronized void processMouseEvent(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ if (this.rightMenu != null && this.rightMenu.isEnabled()) {
+ this.hideRightMenu();
+ } else {
+ this.showRightMenu(e.getX(), e.getY());
+ }
+ }
+
+ super.processMouseEvent(e);
+ }
+
+ @Override
+ protected synchronized void processFocusEvent(FocusEvent e) {
+ if (e.getID() == 1004) {
+ this._hasFocus = true;
+ } else if (e.getID() == 1005) {
+ this._hasFocus = false;
+ }
+
+ this._canvas.repaint();
+ super.processFocusEvent(e);
+ }
+
+ @Override
+ protected synchronized void processKeyEvent(KeyEvent e) {
+ this._canvas.dispatchEvent(e);
+ super.processKeyEvent(e);
+ }
+
+ @Override
+ protected synchronized void processMouseWheelEvent(MouseWheelEvent e) {
+ if (e.getID() == 507) {
+ int move = 0;
+ if (e.getScrollType() == 0) {
+ move = e.getScrollAmount() * e.getWheelRotation();
+ } else {
+ move = scrollWheelStep * e.getWheelRotation();
+ }
+
+ if (move != 0) {
+ this._vertBar.setValue(this._vertBar.getValue() + move);
+ this.requestFocus();
+ this._canvas.sendDelayedMouseEvent(e);
+ this.adjustmentValueChanged(null);
+ }
+ }
+
+ super.processMouseWheelEvent(e);
+ }
+
+ @Override
+ public synchronized void adjustmentValueChanged(AdjustmentEvent e) {
+ this._scrollLine = this._vertBar.getValue();
+ this._canvas.repaint();
+ }
+
+ public void setEditable(boolean b) {
+ if (b) {
+ System.out.println("Can't set GammaTextArea to be editable.");
+ }
+ }
+
+ public synchronized String getText() {
+ return this._string;
+ }
+
+ public synchronized void setText(String s) {
+ this._string = s;
+ this.wordWrapAll();
+ this._scrollLine = this._numLines - this._canvasLines;
+ if (this._scrollLine < 0) {
+ this._scrollLine = 0;
+ }
+
+ this.setScrollBounds();
+ }
+
+ @Override
+ public synchronized void repaint() {
+ this._canvas.repaint();
+ super.repaint();
+ }
+
+ @Override
+ public synchronized void paint(Graphics g) {
+ this._canvas.paint(g);
+ super.paint(g);
+ }
+
+ protected synchronized void wordWrapAll() {
+ this._lines.removeAllElements();
+ this._pos.removeAllElements();
+ this._numLines = 0;
+ this._lastpos = 0;
+ this.wordWrap(this._string);
+ }
+
+ protected synchronized boolean isLastLineVisible() {
+ return !this._canvas.mouseActive && (this.selectionStart < 0 || this.selectionEnd <= this.selectionStart)
+ ? this._scrollLine >= this._numLines - this._canvasLines || this._numLines <= this._canvasLines
+ : false;
+ }
+
+ protected synchronized boolean handleTag(Graphics g, String word, int x, int y) {
+ String lower = word.toLowerCase();
+ if (word.charAt(0) == '<') {
+ for (int i = 0; i < tagList.length; i++) {
+ if (lower.equals(tagList[i].toLowerCase())) {
+ switch (i) {
+ case 0:
+ this._currentStyle |= 1;
+ break;
+ case 1:
+ this._currentStyle &= -2;
+ break;
+ case 2:
+ this._currentStyle |= 2;
+ break;
+ case 3:
+ this._currentStyle &= -3;
+ break;
+ case 4:
+ this._currentColor = Color.magenta;
+ break;
+ case 5:
+ this._currentColor = Color.red;
+ break;
+ case 6:
+ this._currentColor = Color.green;
+ break;
+ case 7:
+ this._currentColor = Color.blue;
+ break;
+ case 8:
+ this._currentColor = Color.black;
+ break;
+ case 9:
+ this._currentColor = Color.magenta;
+ break;
+ case 10:
+ this._currentColor = Color.blue;
+ break;
+ case 11:
+ this._currentColor = Color.red;
+ break;
+ case 12:
+ this._currentColor = Color.green;
+ break;
+ case 13:
+ this._currentColor = Color.cyan;
+ break;
+ case 14:
+ this._currentColor = Color.darkGray;
+ break;
+ case 15:
+ this._currentColor = Color.gray;
+ break;
+ case 16:
+ this._currentColor = Color.orange;
+ break;
+ case 17:
+ this._currentColor = Color.pink;
+ break;
+ case 18:
+ this._currentColor = Color.yellow;
+ break;
+ case 19:
+ this._currentColor = Color.white;
+ break;
+ case 20:
+ this._currentColor = Color.lightGray;
+ }
+
+ try {
+ this._font = new Font(this._currentFontName, this._currentStyle, this._currentPointSize);
+ } catch (IllegalArgumentException var8) {
+ }
+
+ return true;
+ }
+ }
+ }
+
+ if (lower.startsWith("<color=\"#") && word.length() > 15) {
+ int color = 0;
+
+ try {
+ int end = word.lastIndexOf(34);
+ if (end < 10 || end > 15) {
+ end = 15;
+ }
+
+ color = Integer.parseInt(word.substring(9, end).trim(), 16);
+ } catch (Exception var10) {
+ }
+
+ this._currentColor = new Color(color);
+
+ try {
+ this._font = new Font(this._currentFontName, this._currentStyle, this._currentPointSize);
+ } catch (IllegalArgumentException var9) {
+ }
+
+ return true;
+ } else {
+ return this.handleSmiley(g, lower, x, y);
+ }
+ }
+
+ private synchronized boolean handleSmiley(Graphics g, String lower, int x, int y) {
+ ImageCanvas image = emotes.getImage(lower);
+ if (image != null) {
+ this.drawImage(g, image, x, y);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private synchronized void drawImage(Graphics g, ImageCanvas image, int x, int y) {
+ if (image != null && image.loaded_) {
+ Dimension size = image.imageSize();
+ if (g != null) {
+ image.paint(g, x, (int)(y - size.getHeight()));
+ }
+
+ this.lastWidth = (int)(this.lastWidth - (size.getWidth() + 8.0));
+ }
+ }
+
+ protected void ClearTags(Graphics g) {
+ if (this._currentStyle != 0) {
+ this._currentStyle = 0;
+ this._font = new Font(this._currentFontName, this._currentStyle, this._currentPointSize);
+ }
+
+ if (this._currentColor != Color.black) {
+ this._currentColor = Color.black;
+ }
+
+ g.setFont(this._font);
+ g.setColor(this._currentColor);
+ }
+
+ protected synchronized void wordWrap(String newText) {
+ int canvasWidth = this._width;
+ if (canvasWidth > 0) {
+ StringTokenizer rawLines = new StringTokenizer(newText, "\n\r");
+
+ while (rawLines.hasMoreTokens()) {
+ String rawLine = rawLines.nextToken();
+ StringTokenizer words = new StringTokenizer(rawLine, "\n\r\t -", true);
+ int lineWidth = 0;
+ String thisLine = "";
+ this.lastWidth = 0;
+ FontMetrics fm = this._canvas.getFontMetrics(this._font);
+
+ assert fm != null;
+
+ while (words.hasMoreTokens()) {
+ String word = words.nextToken();
+ if (!word.equals("\n") && !word.equals("\r")) {
+ if (this.handleTag(null, word, 0, 0)) {
+ lineWidth -= this.lastWidth;
+ thisLine = thisLine + word;
+ if (words.hasMoreTokens()) {
+ thisLine = thisLine + words.nextToken();
+ }
+
+ this.lastWidth = 0;
+ fm = this._canvas.getFontMetrics(this._font);
+
+ assert fm != null;
+ } else {
+ this.lastWidth = fm.stringWidth(word);
+ if (this.lastWidth >= canvasWidth) {
+ if (!thisLine.equals("")) {
+ this._pos.addElement(this._lastpos);
+ this._lastpos = this._lastpos + thisLine.length();
+ this._lines.addElement(thisLine.trim());
+ this._numLines++;
+ lineWidth = 0;
+ }
+
+ while (this.lastWidth >= canvasWidth) {
+ word = this.breakWord(word, fm);
+ lineWidth = this.lastWidth = 0;
+ thisLine = "";
+ if (word != null && word.length() > 0) {
+ this.lastWidth = fm.stringWidth(word);
+ }
+ }
+ }
+
+ lineWidth += this.lastWidth;
+ if (lineWidth > 0 && word != null && word.length() > 0) {
+ if (lineWidth >= canvasWidth) {
+ this._pos.addElement(this._lastpos);
+ this._lastpos = this._lastpos + thisLine.length();
+ this._lines.addElement(thisLine.trim());
+ this._numLines++;
+ lineWidth = this.lastWidth;
+ thisLine = "";
+ }
+
+ thisLine = thisLine + word;
+ }
+ }
+ }
+ }
+
+ if (!thisLine.equals("")) {
+ this._pos.addElement(this._lastpos);
+ this._lastpos = this._lastpos + thisLine.length() + 1;
+ this._numLines++;
+ this._lines.addElement(thisLine.trim());
+ }
+ }
+ }
+ }
+
+ protected String breakWord(String longWord, FontMetrics fm) {
+ int lineWidth = 0;
+ String thisLine = "";
+
+ for (int c = 0; c < longWord.length(); c++) {
+ char ch = longWord.charAt(c);
+ lineWidth += fm.charWidth(ch);
+ if (lineWidth >= this._width) {
+ this._pos.addElement(this._lastpos);
+ this._lastpos = this._lastpos + thisLine.length();
+ this._lines.addElement(thisLine);
+ this._numLines++;
+ lineWidth = fm.charWidth(ch);
+ thisLine = "";
+ }
+
+ thisLine = thisLine + ch;
+ }
+
+ if (thisLine.length() > 0) {
+ this._pos.addElement(this._lastpos);
+ this._lastpos = this._lastpos + thisLine.length();
+ this._lines.addElement(thisLine);
+ this._numLines++;
+ }
+
+ return "";
+ }
+
+ public synchronized void rewrap() {
+ if (this._width > 0 && this._height > 0) {
+ this.wordWrapAll();
+ this._scrollLine = this._numLines - this._canvasLines;
+ if (this._scrollLine < 0) {
+ this._scrollLine = 0;
+ }
+
+ this.setScrollBounds();
+ this._canvas.repaint();
+ }
+ }
+
+ public synchronized void setScrollBounds() {
+ FontMetrics fm = this._canvas.getFontMetrics(this._font);
+
+ assert fm != null;
+
+ int lineHeight = fm.getHeight();
+ this._canvasLines = (this._height + fm.getDescent()) / lineHeight;
+ if (this._vertBar != null) {
+ if (this._numLines <= this._canvasLines) {
+ this._vertBar.setEnabled(false);
+ } else {
+ this._vertBar.setEnabled(true);
+ this._vertBar.setValues(this._scrollLine, this._canvasLines, 0, this._numLines);
+ this._vertBar.setBlockIncrement(this._canvasLines);
+ }
+ }
+ }
+
+ public synchronized void append(String s) {
+ this._string = this._string + s;
+ this.wordWrap(s);
+ this._scrollLine = this._numLines - this._canvasLines;
+ if (this._scrollLine < 0) {
+ this._scrollLine = 0;
+ }
+
+ this.setScrollBounds();
+ }
+
+ public synchronized void replaceRange(String s, int start, int end) {
+ String newString = this._string.substring(0, start) + s + this._string.substring(end);
+ this._string = newString;
+ }
+
+ public synchronized void drawLine(Graphics g, int lineNum, int y) {
+ if (lineNum < this._pos.size()) {
+ String thisLine = this._lines.elementAt(lineNum);
+
+ assert thisLine != null;
+
+ this._curpos = this._pos.elementAt(lineNum);
+ StringTokenizer st = new StringTokenizer(thisLine, " \n\r", true);
+ int x = 0;
+ this.lastWidth = 0;
+
+ while (st.hasMoreTokens()) {
+ String word = st.nextToken();
+ if (!this.handleTag(g, word, 2 + x, y + 2)) {
+ this.drawString(g, word, 2 + x, y + 2);
+ this.lastWidth = g.getFontMetrics().stringWidth(word);
+ x += this.lastWidth;
+ } else {
+ x -= this.lastWidth;
+ if (st.hasMoreTokens()) {
+ this._curpos = this._curpos + st.nextToken().length();
+ }
+
+ this.lastWidth = 0;
+ g.setFont(this._font);
+ g.setColor(this._currentColor);
+ this._curpos = this._curpos + word.length();
+ }
+ }
+
+ this.ClearTags(g);
+ }
+ }
+
+ private void drawString(Graphics g, String text, int x, int y) {
+ FontMetrics fm = g.getFontMetrics();
+ if (this.selectionConversion) {
+ int height = fm.getHeight();
+ int pos = -1;
+ if (y - height < this._canvas.mouseY) {
+ if (y < this._canvas.mouseY) {
+ if (y < this._canvas.mouseY) {
+ if (this.selectionStart >= 0) {
+ pos = this._curpos + text.length();
+ }
+ } else {
+ this.selectionConversion = false;
+ }
+ } else if (x <= this._canvas.mouseX) {
+ if (this._canvas.mouseX > x + g.getFontMetrics().stringWidth(text)) {
+ if (this.selectionStart >= 0 && this._curpos >= this.selectionStart) {
+ pos = this._curpos + text.length();
+ }
+ } else {
+ if (this._canvas.mouseDoubleClick) {
+ this._canvas.mouseDoubleClick = false;
+ this.selectionStart = this._initialSelection = this._curpos;
+ this.selectionEnd = this._curpos + text.length();
+ pos = -1;
+ } else {
+ int i = 0;
+
+ while (i < text.length() - 1 && x + fm.stringWidth(text.substring(0, i + 1)) < this._canvas.mouseX) {
+ i++;
+ }
+
+ pos = this._curpos + i;
+ }
+
+ this.selectionConversion = false;
+ }
+ } else {
+ this.selectionConversion = false;
+ }
+ } else if (this.selectionStart >= 0 && this._curpos >= this.selectionStart) {
+ this.selectionConversion = false;
+ }
+
+ if (pos >= 0) {
+ if (this.selectionStart < 0) {
+ this.selectionStart = this._initialSelection = pos;
+ this.selectionEnd = this.selectionStart + 1;
+ } else if (pos < this._initialSelection) {
+ this.selectionStart = pos;
+ this.selectionEnd = this._initialSelection + 1;
+ } else {
+ this.selectionStart = this._initialSelection;
+ this.selectionEnd = pos + 1;
+ }
+ }
+ }
+
+ if (this.selectionStart >= 0 && this.selectionEnd > this.selectionStart) {
+ int startdist = this.selectionStart - this._curpos;
+ if (startdist > 0) {
+ if (startdist < text.length()) {
+ int end = text.length();
+ if (this._curpos + end >= this.selectionEnd) {
+ end = this.selectionEnd - this._curpos;
+ }
+
+ this.drawHighlight(g, text.substring(startdist, end), x + fm.stringWidth(text.substring(0, startdist)), y);
+ }
+ } else if (this.selectionEnd > this._curpos) {
+ if (this.selectionEnd - this._curpos < text.length()) {
+ this.drawHighlight(g, text.substring(0, this.selectionEnd - this._curpos), x, y);
+ } else {
+ this.drawHighlight(g, text, x, y);
+ }
+ }
+ }
+
+ g.drawString(text, x, y);
+ this._curpos = this._curpos + text.length();
+ }
+
+ private void drawHighlight(Graphics g, String text, int x, int y) {
+ if (text != null && text.length() > 0) {
+ Color c = g.getColor();
+ g.setColor(skyblue);
+ int height = g.getFontMetrics().getHeight();
+ g.fillRect(x, y - (height - 2), g.getFontMetrics().stringWidth(text), height);
+ g.setColor(c);
+ }
+ }
+
+ public int getSelectionStart() {
+ return this.selectionStart;
+ }
+
+ public int getSelectionEnd() {
+ return this.selectionEnd;
+ }
+
+ public void setSelectionStart(int position) {
+ this.selectionStart = position;
+ }
+
+ public void setSelectionEnd(int position) {
+ this.selectionEnd = position;
+ }
+
+ public synchronized String getSelectionText() {
+ if (this.selectionStart >= 0 && this.selectionEnd > this.selectionStart) {
+ return this.selectionEnd >= this.getText().length()
+ ? this.getText().substring(this.selectionStart)
+ : this.getText().substring(this.selectionStart, this.selectionEnd);
+ } else {
+ return "";
+ }
+ }
+
+ private void initRightMenu() {
+ this.rightMenu = new PopupMenu();
+ this.rightMenu.add(this.textCopyItem);
+ this.rightMenu.add(this.textCopyTextItem);
+ if (this.selectionStart >= 0 && this.selectionEnd > this.selectionStart) {
+ this.textCopyItem.setEnabled(true);
+ this.textCopyTextItem.setEnabled(true);
+ } else {
+ this.textCopyItem.setEnabled(false);
+ this.textCopyTextItem.setEnabled(false);
+ }
+
+ this.rightMenu.add(this.textCopyAllItem);
+ this.rightMenu.add(this.textCopyAllTextItem);
+ this.rightMenu.add(this.textOpenURLItem);
+ this.rightMenu.addActionListener(this);
+ this.add(this.rightMenu);
+ }
+
+ private void showRightMenu(int x, int y) {
+ if (this.rightMenu == null) {
+ this.initRightMenu();
+ }
+
+ this.rightMenu.show(this, x, y);
+ }
+
+ private void hideRightMenu() {
+ this.remove(this.rightMenu);
+ this.rightMenu = null;
+ }
+
+ @Override
+ public synchronized void actionPerformed(ActionEvent e) {
+ String text = null;
+ boolean doClean = false;
+ if (e.getActionCommand() == this.textCopyItem.getActionCommand()) {
+ text = this.getSelectionText();
+ this.selectionStart = this.selectionEnd = -1;
+ this.repaint();
+ } else if (e.getActionCommand() == this.textCopyTextItem.getActionCommand()) {
+ text = this.getSelectionText();
+ doClean = true;
+ this.selectionStart = this.selectionEnd = -1;
+ this.repaint();
+ } else if (e.getActionCommand() == this.textCopyAllItem.getActionCommand()) {
+ text = this.getText();
+ } else if (e.getActionCommand() == this.textCopyAllTextItem.getActionCommand()) {
+ text = this.getText();
+ doClean = true;
+ } else if (e.getActionCommand() == this.textOpenURLItem.getActionCommand()) {
+ text = this.getSelectionText().trim();
+ if (text != null && text.length() > 5) {
+ if (!text.startsWith("http://") && !text.startsWith("https://") && !text.startsWith("world:")) {
+ text = "http://" + text;
+ }
+
+ if (text.startsWith("world:") || text.contains(".world#") || (text.startsWith("http") || text.startsWith("file:")) && text.endsWith(".world")) {
+ if (text.startsWith("world:")) {
+ text = text.substring(6);
+ }
+
+ TeleportAction.teleport(text, null);
+ } else {
+ new SendURLAction(text).startBrowser();
+ }
+
+ this.selectionStart = this.selectionEnd = -1;
+ this.repaint();
+ }
+
+ this.hideRightMenu();
+ return;
+ }
+
+ if (doClean) {
+ StringTokenizer st = new StringTokenizer(text, " \n\r", true);
+ String newText = "";
+
+ while (st.hasMoreTokens()) {
+ String word = st.nextToken();
+ if (!this.handleTag(null, word, 0, 0)) {
+ newText = newText + word;
+ } else {
+ if (newText.length() > 0 && newText.substring(newText.length() - 1).toCharArray()[0] == ' ') {
+ newText = newText.substring(0, newText.length() - 1);
+ }
+
+ if (st.hasMoreTokens()) {
+ st.nextToken();
+ }
+ }
+ }
+
+ text = newText;
+ }
+
+ if (text != null && text.length() > 0) {
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ clipboard.setContents(new StringSelection(text), null);
+ }
+
+ this.hideRightMenu();
+ }
+}