19f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/* 29f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * ConnectBot: simple, powerful, open-source SSH client for Android 39f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Copyright 2007 Kenny Root, Jeffrey Sharkey 49f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 59f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Licensed under the Apache License, Version 2.0 (the "License"); 69f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * you may not use this file except in compliance with the License. 79f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * You may obtain a copy of the License at 89f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 99f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * http://www.apache.org/licenses/LICENSE-2.0 109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Unless required by applicable law or agreed to in writing, software 129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * distributed under the License is distributed on an "AS IS" BASIS, 139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * See the License for the specific language governing permissions and 159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * limitations under the License. 169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage org.connectbot.util; 199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport de.mud.terminal.VDUBuffer; 219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/** 239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Keep track of a selection area for the terminal copying mechanism. 249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * If the orientation is flipped one way, swap the bottom and top or 259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * left and right to keep it in the correct orientation. 269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class SelectionArea { 289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int top; 299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int bottom; 309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int left; 319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int right; 329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int maxColumns; 339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int maxRows; 349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean selectingOrigin; 359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public SelectionArea() { 379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li reset(); 389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public final void reset() { 419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li top = left = bottom = right = 0; 429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li selectingOrigin = true; 439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param columns 479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param rows 489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setBounds(int columns, int rows) { 509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li maxColumns = columns - 1; 519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li maxRows = rows - 1; 529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int checkBounds(int value, int max) { 559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (value < 0) 569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return 0; 579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li else if (value > max) 589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return max; 599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li else 609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return value; 619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public boolean isSelectingOrigin() { 649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return selectingOrigin; 659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void finishSelectingOrigin() { 689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li selectingOrigin = false; 699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void decrementRow() { 729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (selectingOrigin) 739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setTop(top - 1); 749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li else 759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setBottom(bottom - 1); 769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void incrementRow() { 799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (selectingOrigin) 809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setTop(top + 1); 819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li else 829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setBottom(bottom + 1); 839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setRow(int row) { 869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (selectingOrigin) 879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setTop(row); 889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li else 899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setBottom(row); 909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void setTop(int top) { 939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.top = bottom = checkBounds(top, maxRows); 949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int getTop() { 979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return Math.min(top, bottom); 989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void setBottom(int bottom) { 1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.bottom = checkBounds(bottom, maxRows); 1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int getBottom() { 1059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return Math.max(top, bottom); 1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void decrementColumn() { 1099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (selectingOrigin) 1109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setLeft(left - 1); 1119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li else 1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setRight(right - 1); 1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void incrementColumn() { 1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (selectingOrigin) 1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setLeft(left + 1); 1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li else 1199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setRight(right + 1); 1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setColumn(int column) { 1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (selectingOrigin) 1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setLeft(column); 1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li else 1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setRight(column); 1279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void setLeft(int left) { 1309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.left = right = checkBounds(left, maxColumns); 1319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int getLeft() { 1349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return Math.min(left, right); 1359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void setRight(int right) { 1389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.right = checkBounds(right, maxColumns); 1399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int getRight() { 1429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return Math.max(left, right); 1439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public String copyFrom(VDUBuffer vb) { 1469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int size = (getRight() - getLeft() + 1) * (getBottom() - getTop() + 1); 1479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li StringBuffer buffer = new StringBuffer(size); 1499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for(int y = getTop(); y <= getBottom(); y++) { 1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int lastNonSpace = buffer.length(); 1529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (int x = getLeft(); x <= getRight(); x++) { 1549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // only copy printable chars 1559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li char c = vb.getChar(x, y); 1569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!Character.isDefined(c) || 1589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li (Character.isISOControl(c) && c != '\t')) 1599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li c = ' '; 1609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (c != ' ') 1629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li lastNonSpace = buffer.length(); 1639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(c); 1659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Don't leave a bunch of spaces in our copy buffer. 1689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (buffer.length() > lastNonSpace) 1699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.delete(lastNonSpace + 1, buffer.length()); 1709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (y != bottom) 1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append("\n"); 1739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return buffer.toString(); 1769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public String toString() { 1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li StringBuilder buffer = new StringBuilder(); 1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append("SelectionArea[top="); 1839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(top); 1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(", bottom="); 1859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(bottom); 1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(", left="); 1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(left); 1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(", right="); 1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(right); 1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(", maxColumns="); 1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(maxColumns); 1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(", maxRows="); 1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(maxRows); 1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(", isSelectingOrigin="); 1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append(isSelectingOrigin()); 1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.append("]"); 1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return buffer.toString(); 1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li} 201