1 22 23 package org.netbeans.lib.terminalemulator; 24 25 import java.awt.*; 26 import java.awt.event.*; 27 import java.awt.datatransfer.*; 28 import javax.swing.*; 29 import javax.accessibility.*; 30 31 import java.awt.font.*; 32 import java.awt.geom.Point2D ; 33 34 import java.util.HashSet ; 35 import java.util.Date ; 36 import java.util.LinkedList ; 37 import java.util.ListIterator ; 38 39 220 221 public class Term extends JComponent implements Accessible { 222 private State st = new State(); 223 private Sel sel = new Sel(this, st); 224 private Ops ops = new OpsImpl(); 225 226 private int top_margin = 0; private int bot_margin = 0; 228 229 private int cull_count = 0; 231 private static final int cull_frequency = 50; 232 233 protected int firsta = 0; 235 236 private int charsInPrehistory = 0; 239 240 private static final int modulo = Integer.MAX_VALUE/2; 241 242 private Screen screen; 243 private JScrollBar vscroll_bar; 244 private ScrollWrapper hscroll_wrapper; 245 private JScrollBar hscroll_bar; 246 private boolean has_focus; 247 248 private int n_putchar; 250 private int n_putchars; 251 private int n_linefeeds; 252 private int n_repaint; 253 private int n_paint; 254 255 MyFontMetrics metrics = null; 256 257 Buffer buf = new Buffer(80); 258 259 private RegionManager region_manager = new RegionManager(); 260 261 267 private Point left_down_point; 268 269 private Clipboard systemClipboard = getToolkit().getSystemClipboard(); 271 private Clipboard systemSelection = getToolkit().getSystemSelection(); 272 273 274 307 308 private class ScrollWrapper extends JComponent implements Accessible { 309 public JScrollBar scroll_bar; 310 311 public ScrollWrapper(JScrollBar scroll_bar) { 312 GridBagLayout gbl = new GridBagLayout(); 313 setLayout(gbl); 314 315 GridBagConstraints gbc = new GridBagConstraints(); 316 gbc.anchor = GridBagConstraints.WEST; 317 gbc.fill = GridBagConstraints.BOTH; 318 gbc.gridwidth = 1; 319 gbc.gridheight = 1; 320 gbc.weightx = 1.0f; 321 gbc.weighty = 1.0f; 322 int slop = vscroll_bar.getMaximumSize().width; 323 gbc.insets = new Insets(0, 0, 0, slop); 324 add(scroll_bar, gbc); 325 326 this.scroll_bar = scroll_bar; 327 } 328 329 protected void paintComponent(Graphics g) { 330 Dimension sz = getSize(); 333 g.clearRect(0, 0, sz.width, sz.height); 334 } 335 336 340 public AccessibleContext getAccessibleContext() { 341 if (accessible_context == null) { 342 accessible_context = new AccessibleScrollWrapper(); 343 } 344 return accessible_context; 345 } 346 private AccessibleContext accessible_context; 347 348 protected class AccessibleScrollWrapper extends AccessibleJComponent { 349 public AccessibleRole getAccessibleRole() { 350 return AccessibleRole.PANEL; 351 } 352 } 353 } 354 355 356 private class BaseTermStream extends TermStream { 357 public void flush() { 358 repaint(true); 359 } 360 361 public void putChar(char c) { 362 365 ckEventDispatchThread(); 366 { 368 n_putchar++; 369 putc_work(c); 370 } 371 possibly_repaint(true); 372 373 } 379 380 public void putChars(char buf[], int offset, int count) { 381 ckEventDispatchThread(); 382 { 384 n_putchars++; 385 for (int bx = 0; bx < count; bx++) { 386 putc_work(buf[offset+bx]); 387 } 388 } 389 possibly_repaint(true); 390 } 391 392 public void sendChar(char c) { 393 fireChar(c); 394 } 395 396 public void sendChars(char buf[], int offset, int count) { 397 fireChars(buf, offset, count); 398 } 399 } 400 401 private TermStream base_stream = new BaseTermStream(); 404 private TermStream dce_end = base_stream; 405 private TermStream dte_end = base_stream; 406 407 410 public void pushStream(TermStream stream) { 411 419 if (dce_end == base_stream) { 420 dte_end = stream; 422 stream.setToDCE(base_stream); 423 424 stream.setToDTE(base_stream); 426 dce_end = stream; 427 428 } else { 429 dte_end.setToDCE(stream); 431 stream.setToDCE(base_stream); 432 433 stream.setToDTE(dce_end); 435 dce_end = stream; 436 } 437 438 stream.setTerm(this); 439 } 440 441 444 public static final int DEBUG_OPS = 1<<0; 445 public static final int DEBUG_KEYS = 1<<1; 446 public static final int DEBUG_INPUT = 1<<2; 447 public static final int DEBUG_OUTPUT = 1<<3; 448 public static final int DEBUG_WRAP = 1<<4; 449 public static final int DEBUG_MARGINS = 1<<5; 450 451 private int debug_gutter_width = 0; 452 453 public void setDebugFlags(int flags) { 454 debug = flags; 455 } 456 457 private int debug = 0; 458 459 private boolean debugOps() { 460 return (debug & DEBUG_OPS) == DEBUG_OPS; 461 } 462 private boolean debugKeys() { 463 return (debug & DEBUG_KEYS) == DEBUG_KEYS; 464 } 465 private boolean debugWrap() { 466 return (debug & DEBUG_WRAP) == DEBUG_WRAP; 467 } 468 private boolean debugMargins() { 469 return true; 470 473 } 474 477 protected boolean debugInput() { 478 return (debug & DEBUG_INPUT) == DEBUG_INPUT; 479 } 480 483 protected boolean debugOutput() { 484 return (debug & DEBUG_OUTPUT) == DEBUG_OUTPUT; 485 } 486 487 488 498 499 private int topMargin() { 500 return (top_margin == 0)? 0: top_margin-1; 501 } 502 private int botMargin() { 503 return (bot_margin == 0)? st.rows-1: bot_margin-1; 504 } 505 506 514 private int beginx() { 515 return buf.nlines - st.rows; 516 } 517 518 private Line cursor_line() { 519 return buf.lineAt(st.cursor.row); 520 } 521 522 526 public void setWordDelineator(WordDelineator word_delineator) { 527 if (word_delineator == null) 528 this.word_delineator = default_word_delineator; 529 else 530 this.word_delineator = word_delineator; 531 } 532 535 public WordDelineator getWordDelineator() { 536 return this.word_delineator; 537 } 538 private WordDelineator default_word_delineator = new WordDelineator(); 539 WordDelineator word_delineator = default_word_delineator; 540 541 542 548 public void setInputListener(TermInputListener l) { 549 addInputListener(l); 550 } 551 552 557 public void addInputListener(TermInputListener l) { 558 input_listeners.add(l); 559 } 560 561 public void removeInputListener(TermInputListener l) { 562 input_listeners.remove(l); 563 } 564 565 private void fireChar(char c) { 566 ListIterator iter = input_listeners.listIterator(); 567 while (iter.hasNext()) { 568 TermInputListener l = (TermInputListener) iter.next(); 569 l.sendChar(c); 570 } 571 } 572 573 private void fireChars(char buf[], int offset, int count) { 574 ListIterator iter = input_listeners.listIterator(); 575 while (iter.hasNext()) { 576 TermInputListener l = (TermInputListener) iter.next(); 577 l.sendChars(buf, offset, count); 578 } 579 } 580 581 private LinkedList input_listeners = new LinkedList (); 582 583 584 591 public void setListener(TermListener l) { 592 addListener(l); 593 } 594 595 598 public void addListener(TermListener l) { 599 listeners.add(l); 600 } 601 602 605 public void removeListener(TermListener l) { 606 listeners.remove(l); 607 } 608 609 610 private void fireSizeChanged(Dimension cells, Dimension pixels) { 611 ListIterator iter = listeners.listIterator(); 612 while (iter.hasNext()) { 613 TermListener l = (TermListener) iter.next(); 614 l.sizeChanged(cells, pixels); 615 } 616 } 617 618 private LinkedList listeners = new LinkedList (); 619 620 626 public void setClickToType(boolean click_to_type) { 627 this.click_to_type = click_to_type; 628 } 629 public boolean isClickToType() { 630 return click_to_type; 631 } 632 private boolean click_to_type = true; 633 634 635 636 639 public void setReadOnly(boolean read_only) { 640 this.read_only = read_only; 641 } 642 643 646 public boolean isReadOnly() { 647 return read_only; 648 } 649 650 private boolean read_only = false; 651 652 653 654 655 658 public void clear() { 659 for (int row = 0; row < st.rows; row++) { 660 Line l = buf.lineAt(beginx() + row); 661 l.reset(); 662 } 663 regionManager().reset(); 664 } 665 666 671 public void clearHistoryNoRefresh() { 672 sel.cancel(true); 673 674 int old_cols = buf.visibleCols(); 675 buf = new Buffer(old_cols); 676 677 firsta = 0; 678 charsInPrehistory = 0; 679 680 st.firstx = 0; 681 st.firsty = 0; 682 st.cursor.row = 0; 683 st.cursor.col = 0; 684 st.attr = 0; 685 st.saveCursor(); st.restoreCursor(); 688 adjust_lines(st.rows); 689 690 st.firstx = 0; 691 st.firsty = 0; 692 693 regionManager().reset(); 694 695 screen.possiblyUpdateCaretText(); 696 } 697 698 704 public void clearHistory() { 705 clearHistoryNoRefresh(); 706 repaint(true); 707 } 708 709 712 public RegionManager regionManager() { 713 return region_manager; 714 } 715 716 public String textWithin(Coord begin, Coord end) { 717 if (begin == null || end == null) 718 return null; 719 720 final StringBuffer buf = new StringBuffer (); 721 722 visitLines(begin, end, false, new LineVisitor() { 723 public boolean visit(Line l, int row, int bcol, int ecol) { 724 buf.append(l.charArray(), bcol, ecol-bcol+1); 725 return true; 726 } 727 } ); 728 return buf.toString(); 729 } 730 731 public String getRowText(int row) { 732 Line line = buf.lineAt( row ); 733 if ( line == null ) 734 return null; 735 return line.stringBuffer().toString(); 736 } 737 738 750 public HashSet getKeyStrokeSet() { 751 return keystroke_set; 752 } 753 754 760 public void setKeyStrokeSet(HashSet keystroke_set) { 761 this.keystroke_set = keystroke_set; 762 763 771 } 772 773 private HashSet keystroke_set = new HashSet (); 774 775 788 private boolean passOn = true; 789 790 791 797 private boolean maybeConsume(KeyEvent e) { 798 799 if (e.isConsumed()) 800 return false; 801 802 KeyStroke ks = KeyStroke.getKeyStrokeForEvent(e); 803 804 809 810 if (keystroke_set == null || ! keystroke_set.contains(ks)) { 811 e.consume(); 812 return true; 813 } 814 return false; 815 } 816 817 818 827 void visitLines(Coord begin, Coord end, boolean newlines, 828 LineVisitor visitor) { 829 buf.visitLines(begin.toBCoord(firsta), end.toBCoord(firsta), newlines, visitor); 830 } 831 832 838 public void visitLogicalLines(Coord begin, Coord end, 839 final LogicalLineVisitor llv) { 840 841 LineVisitor tramp = new LineVisitor() { 843 String text = ""; int lineno = 0; 845 Coord begin = null; 846 Coord end = null; 847 848 public boolean visit(Line l, int brow, int bcol, int ecol) { 849 850 if (l.isWrapped()) { 851 if (begin == null) 852 begin = new Coord(new BCoord(brow, bcol), firsta); 853 text += l.text(bcol, ecol); 854 855 } else { 856 if (begin == null) 857 begin = new Coord(new BCoord(brow, bcol), firsta); 858 end = new Coord(new BCoord(brow, ecol), firsta); 859 text += l.text(bcol, ecol); 860 861 if (!llv.visit(lineno, begin, end, text)) 862 return false; 863 864 lineno++; 865 text = ""; begin = null; 867 end = null; 868 } 869 870 return true; 871 } 872 } ; 873 874 if (begin == null) 875 begin = new Coord(); 876 877 if (end == null) { 878 int lastrow = buf.nlines-1; 879 Line l = buf.lineAt(lastrow); 880 end = new Coord(new BCoord(lastrow, l.length()-1), firsta); 881 } 882 883 if (begin.compareTo(end) > 0) 884 return; 885 886 buf.visitLines(begin.toBCoord(firsta), end.toBCoord(firsta), false, tramp); 887 } 888 889 895 public void reverseVisitLogicalLines(Coord begin, Coord end, 896 final LogicalLineVisitor llv) { 897 898 LineVisitor tramp = new LineVisitor() { 900 String text = ""; int lineno = 0; 902 Coord begin = null; 903 Coord end = null; 904 905 public boolean visit(Line l, int brow, int bcol, int ecol) { 906 907 boolean line_is_continuation = false; 908 if (brow > 0 && buf.lineAt(brow-1).isWrapped()) 909 line_is_continuation = true; 910 911 if (line_is_continuation) { 912 if (end == null) 913 end = new Coord(new BCoord(brow, ecol), firsta); 914 text = l.text(bcol, ecol) + text; 915 916 } else { 917 if (end == null) 918 end = new Coord(new BCoord(brow, ecol), firsta); 919 begin = new Coord(new BCoord(brow, bcol), firsta); 920 text = l.text(bcol, ecol) + text; 921 922 if (!llv.visit(lineno, begin, end, text)) 923 return false; 924 925 lineno++; 926 text = ""; begin = null; 928 end = null; 929 } 930 931 return true; 932 } 933 } ; 934 935 if (begin == null) 936 begin = new Coord(); 937 938 if (end == null) { 939 int lastrow = buf.nlines-1; 940 Line l = buf.lineAt(lastrow); 941 end = new Coord(new BCoord(lastrow, l.length()-1), firsta); 942 } 943 944 if (begin.compareTo(end) > 0) 945 return; 946 947 buf.reverseVisitLines(begin.toBCoord(firsta), end.toBCoord(firsta), false, tramp); 948 } 949 950 984 public Extent extentInLogicalLine(Coord begin, int offset, int length) { 985 986 988 Coord from = (Coord) begin.clone(); 989 while (offset-- > 0) { 990 from = new Coord(buf.advance(from.toBCoord(firsta)), firsta); 991 } 992 993 Coord to = (Coord) from.clone(); 994 while (--length > 0) { 995 to = new Coord(buf.advance(to.toBCoord(firsta)), firsta); 996 } 997 998 return new Extent(from, to); 999 } 1000 1001 private boolean cursor_was_visible() { 1002 return st.cursor.row-1 >= st.firstx && 1003 st.cursor.row-1 < st.firstx + st.rows; 1004 } 1005 1006 1013 public void possiblyNormalize(Coord target) { 1014 if (target == null) 1015 return; 1016 1017 BCoord btarget = target.toBCoord(firsta); 1018 if (btarget.row >= st.firstx && btarget.row < st.firstx + st.rows) 1019 return; 1020 1021 st.firstx = btarget.row - (st.rows/2); 1022 if (st.firstx < 0) 1023 st.firstx = 0; 1024 else if (st.firstx + st.rows > buf.nlines) 1025 st.firstx = buf.nlines - st.rows; 1026 1027 repaint(true); 1028 } 1029 1030 1041 public void possiblyNormalize(ActiveRegion region) { 1042 if (region == null) 1043 return; 1044 1045 BCoord bbegin = region.begin.toBCoord(firsta); 1046 BCoord bend = region.end.toBCoord(firsta); 1047 if ( bbegin.row >= st.firstx && bend.row < st.firstx + st.rows ) 1048 return; 1049 1050 if ( bend.row - bbegin.row + 1 >= st.rows ) 1051 st.firstx = bbegin.row; 1053 else { 1054 st.firstx = bbegin.row - (st.rows/2); 1055 if (st.firstx < 0) 1056 st.firstx = 0; 1057 else if (st.firstx + st.rows > buf.nlines) 1058 st.firstx = buf.nlines - st.rows; 1059 else if (st.firstx + st.rows <= bend.row) 1060 st.firstx = bend.row - st.rows + 1; 1062 } 1063 1064 repaint(true); 1065 } 1066 1067 1071 public boolean isCoordVisible(Coord target) { 1072 BCoord btarget = target.toBCoord(firsta); 1073 if (btarget.row >= st.firstx && btarget.row < st.firstx + st.rows) 1074 return true; 1075 else 1076 return false; 1077 } 1078 1079 private void possiblyScrollOnInput() { 1080 if (!scroll_on_input) 1081 return; 1082 1083 if (st.cursor.row >= st.firstx && st.cursor.row < st.firstx + st.rows) { 1085 ; 1086 } else { 1087 st.firstx = buf.nlines - st.rows; 1088 repaint(true); 1089 } 1090 } 1091 1092 1113 1114 private int hscroll_count = 0; 1115 1116 private void hscrollReset(char c) { 1117 ckEventDispatchThread(); 1118 { 1120 if (c == '\n' || c == '\r') 1121 hscroll_count = 8; 1122 else 1123 hscroll_count += 8; 1124 } 1125 } 1126 1127 private void possiblyHScroll() { 1128 1129 1131 if (!horizontally_scrollable) 1132 return; 1133 1134 ckEventDispatchThread(); 1135 { 1137 if (hscroll_count > 0) { 1138 hscroll_count--; 1139 } else { 1140 return; 1141 } 1142 } 1143 1144 1149 1150 if (st.cursor.col >= st.firsty + buf.visibleCols()) { 1152 1155 st.firsty = st.cursor.col - buf.visibleCols() + 1; 1156 1157 buf.noteColumn(st.cursor.col+1); 1165 1166 repaint(true); 1167 1168 } else if (st.cursor.col - buf.visibleCols() < st.firsty) { 1169 1172 st.firsty = st.cursor.col - buf.visibleCols() + 1; 1173 if (st.firsty < 0) 1174 st.firsty = 0; 1175 else 1176 repaint(true); 1177 } 1178 } 1179 1180 1181 1186 1187 public void setAttribute(int value) { 1188 st.attr = Attr.setAttribute(st.attr, value); 1189 } 1190 1191 1197 public void setCharacterAttribute(Coord begin, Coord end, 1198 final int value, final boolean on ) { 1199 1200 visitLines(begin, end, false, new LineVisitor() { 1201 public boolean visit(Line l, int brow, int bcol, int ecol) { 1202 l.setCharacterAttribute(bcol, ecol, value, on); 1203 return true; 1204 } 1205 } ); 1206 1207 repaint(false); 1208 } 1209 1210 1215 public void setGlyph(int glyph_id, int background_id) { 1216 Line l = cursor_line(); 1217 l.glyph_glyph = glyph_id; 1218 l.glyph_rendition = background_id; 1219 } 1220 1221 1226 public void setRowGlyph(int row, int glyph_id, int background_id) { 1227 Coord c = new Coord(); 1228 c.row = row; 1229 c.col = 0; 1230 BCoord b = c.toBCoord(firsta); 1231 Line l = buf.lineAt(b.row); 1232 if (l == null) 1233 return; 1234 l.glyph_glyph = glyph_id; 1235 l.glyph_rendition = background_id; 1236 1237 possibly_repaint(false); 1238 } 1239 1240 1241 1252 1253 private void adjust_lines(int delta_row) { 1254 1255 if (delta_row > 0) { 1256 st.firstx -= delta_row; 1258 1259 while (st.firstx < 0) { 1261 buf.appendLine(); 1262 st.firstx++; 1263 } 1264 1265 } else if (delta_row < 0) { 1266 int orows = st.rows - delta_row; 1269 1274 1279 int allowed = buf.nlines - st.cursor.row - 1; 1280 1281 if (allowed < 0) 1282 allowed = 0; 1283 1284 int delete_from_bottom; 1285 if (allowed > -delta_row) { 1286 delete_from_bottom = -delta_row; 1289 } else { 1290 delete_from_bottom = allowed; 1292 st.firstx += (-delta_row - allowed); 1294 } 1295 1296 while (delete_from_bottom-- > 0) { 1298 buf.removeLineAt(buf.nlines-1); 1299 } 1300 1301 1302 } 1303 1305 adjust_scrollbar(); 1306 } 1307 1308 1311 public int getHistoryBuffSize () { 1312 return buf.nlines - st.rows; 1313 } 1314 1315 private void limit_lines() { 1316 1317 1321 1322 if (anchored) 1323 return; 1324 1325 int history = buf.nlines - st.rows; 1326 if (history < 0) 1327 history = 0; 1328 1329 int toremove = history - history_size; 1330 if (toremove > 0) { 1331 int charsRemoved = buf.removeLinesAt(0, toremove); 1332 1333 charsInPrehistory += charsRemoved; 1334 1335 st.adjust(-toremove); 1337 1338 firsta += toremove; 1339 1340 if (++cull_count % cull_frequency == 0) { 1342 1345 region_manager.cull(firsta); 1346 } 1347 1348 if (firsta + buf.nlines >= modulo) { 1350 int old_firsta = firsta; 1351 firsta = 0; 1352 1353 sel.relocate(old_firsta, firsta); 1354 region_manager.relocate(old_firsta, firsta); 1355 } 1356 } 1357 1358 sel.adjust(firsta, 0, firsta + buf.nlines); 1360 1361 adjust_scrollbar(); 1362 } 1363 1364 1370 private class Scroller extends Thread { 1371 public final static int UP = 1<<1; 1372 public final static int DOWN = 1<<2; 1373 public final static int LEFT = 1<<3; 1374 public final static int RIGHT = 1<<4; 1375 1376 private int direction; 1377 1378 public Scroller(int direction) { 1379 this.direction = direction; 1380 } 1381 1382 private boolean extend() { 1383 1384 ckEventDispatchThread(); 1385 { 1387 1388 if (sel.sel_extent == null) 1392 return false; 1393 1394 BCoord x = sel.sel_extent.toBCoord(firsta); 1395 BCoord v = toViewCoord(x); 1396 int r = v.row; 1397 int c = v.col; 1398 1399 if ((direction & DOWN) == DOWN) { 1400 lineDown(1); 1401 r = st.rows-1; 1402 c = buf.totalCols(); 1403 } else if ((direction & UP) == UP) { 1404 lineUp(1); 1405 r = 0; 1406 c = 0; 1407 } else { 1408 BCoord vc2 = toViewCoord(drag_point); 1409 r = vc2.row; 1410 c = vc2.col; 1411 } 1412 1413 1414 if ((direction & LEFT) == LEFT) { 1415 st.firsty --; 1416 if (st.firsty < 0) 1417 st.firsty = 0; 1418 c = 0; 1419 } else if ((direction & RIGHT) == RIGHT) { 1420 st.firsty ++; 1421 int limit = buf.totalCols() - buf.visibleCols(); 1422 if (limit < 0) 1423 limit = 0; 1424 if (st.firsty > limit) 1425 st.firsty = limit; 1426 c = st.firsty + buf.visibleCols(); 1427 } 1428 1429 BCoord vc = new BCoord(r, c); 1430 BCoord bc = toBufCoords(vc); 1431 sel.track(new Coord(bc, firsta)); 1432 repaint(true); 1433 return true; 1434 } 1435 } 1436 1437 public void run() { 1438 while (true) { 1439 1440 1452 1453 extend(); 1454 1455 try { 1456 sleep(10); 1458 } catch (InterruptedException x) { 1459 break; 1460 } 1461 } 1462 1465 } 1466 } 1467 1468 private Scroller scroller; 1469 private Point drag_point; 1470 1471 private int scrolling_direction = 0; 1472 1473 1474 private void scroll_to(int direction, MouseEvent e) { 1475 if (direction == scrolling_direction) { 1476 if (direction == 0) { 1477 BCoord bc = toBufCoords(toViewCoord(e.getPoint())); 1479 sel.track(new Coord(bc, firsta)); 1480 repaint(false); 1481 } 1482 return; 1483 } 1484 1485 1487 if (scroller != null) { 1489 scroller.interrupt(); 1490 scroller = null; 1491 } 1492 1493 if (direction == 0) { 1494 BCoord bc = toBufCoords(toViewCoord(e.getPoint())); 1495 sel.track(new Coord(bc, firsta)); 1496 repaint(false); 1497 } else { 1498 scroller = new Scroller(direction); 1499 scroller.start(); 1500 } 1501 1502 scrolling_direction = direction; 1503 } 1504 1505 1506 1509 public Term() { 1510 st.rows = 25; 1511 st.firstx = 0; 1512 st.firsty = 0; 1513 1514 standard_color[0] = Color.black; 1515 standard_color[1] = Color.red; 1516 standard_color[2] = Color.green; 1517 standard_color[3] = Color.yellow; 1518 standard_color[4] = Color.blue; 1519 standard_color[5] = Color.magenta; 1520 standard_color[6] = Color.cyan; 1521 standard_color[7] = Color.white; 1522 1523 custom_color[0] = Color.black; 1524 custom_color[1] = Color.black; 1525 custom_color[2] = Color.black; 1526 custom_color[3] = Color.black; 1527 custom_color[4] = Color.black; 1528 custom_color[5] = Color.black; 1529 custom_color[6] = Color.black; 1530 custom_color[7] = Color.black; 1531 1532 Font f = UIManager.getFont ("TextArea.font"); if (f == null) { 1534 f = UIManager.getFont ("controlFont"); } 1537 1538 if (f != null) { 1539 setFont(new Font("Monospaced", Font.PLAIN, f.getSize() + 1)); } else { 1541 setFont (new Font("Monospaced", Font.PLAIN, 12)); } 1543 1544 BorderLayout layout = new BorderLayout(); 1545 setLayout(layout); 1546 screen = new Screen(this, 1547 (buf.visibleCols() * metrics.width + 1548 glyph_gutter_width + 1549 debug_gutter_width), 1550 st.rows * metrics.height); 1551 1552 add(BorderLayout.CENTER, screen); 1553 screen.setBackground(null); screen.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); 1555 1556 adjust_lines(st.rows); 1557 st.cursor.row = 0; 1558 1559 vscroll_bar = new JScrollBar(JScrollBar.VERTICAL); 1560 add(BorderLayout.EAST, vscroll_bar); 1561 vscroll_bar.setValues(st.firstx, st.rows-1, 0, st.rows); 1562 vscroll_bar.setUnitIncrement(1); 1563 vscroll_bar.setEnabled(true); 1564 vscroll_bar.setFocusable(false); 1565 1566 vscroll_bar.addAdjustmentListener(new AdjustmentListener() { 1567 1568 public void adjustmentValueChanged(AdjustmentEvent e) { 1569 JScrollBar sb = (JScrollBar) e.getAdjustable(); 1570 switch(e.getAdjustmentType()) { 1571 case AdjustmentEvent.TRACK: 1572 1573 int pos = e.getValue(); 1574 1575 if (pos == st.firstx) 1579 break; 1580 1581 st.firstx = pos; 1583 1589 repaint(false); 1590 break; 1591 1592 default: 1593 1596 break; 1597 } 1598 } 1599 } ); 1600 1601 1602 hscroll_bar = new JScrollBar(JScrollBar.HORIZONTAL); 1603 hscroll_bar.setValues(st.firsty, buf.totalCols()-1, 0, buf.totalCols()); 1604 hscroll_bar.setUnitIncrement(1); 1605 hscroll_bar.setEnabled(true); 1606 hscroll_bar.setFocusable(false); 1607 1608 hscroll_wrapper = new ScrollWrapper(hscroll_bar); 1609 add(BorderLayout.SOUTH, hscroll_wrapper); 1610 1611 hscroll_bar.addAdjustmentListener(new AdjustmentListener() { 1612 1613 public void adjustmentValueChanged(AdjustmentEvent e) { 1614 JScrollBar sb = (JScrollBar) e.getAdjustable(); 1615 switch(e.getAdjustmentType()) { 1616 case AdjustmentEvent.TRACK: 1617 1618 int pos = e.getValue(); 1619 1620 if (pos == st.firsty) 1624 break; 1625 1626 st.firsty = pos; 1628 repaint(false); 1629 break; 1630 1631 default: 1632 1635 break; 1636 } 1637 } 1638 } ); 1639 1640 screen.addComponentListener(new ComponentAdapter() { 1641 1642 public void componentResized(ComponentEvent e) { 1643 Dimension size = screen.getSize(); 1644 sizeChanged(size.width, size.height); 1645 1646 repaint(true); 1649 } 1650 1651 } ); 1652 1653 screen.addKeyListener(new KeyListener() { 1654 1655 1661 boolean saw_return; 1668 1669 public void keyTyped(KeyEvent e) { 1670 char c = e.getKeyChar(); 1671 1672 if (debugKeys()) 1673 System.out.println("term: keyTyped: " + e); 1675 if (read_only) 1676 return; 1677 1678 if (c == 10 && saw_return) { 1679 saw_return = false; 1680 c = (char) 13; 1681 } 1682 1683 if (passOn && maybeConsume(e)) { 1684 on_char(c); 1685 possiblyScrollOnInput(); 1686 } 1687 1688 hscrollReset(c); 1689 } 1690 1691 public void keyPressed(KeyEvent e) { 1692 1695 1696 switch (e.getKeyCode()) { 1697 case KeyEvent.VK_COPY: 1698 copyToClipboard(); 1699 break; 1700 case KeyEvent.VK_PASTE: 1701 pasteFromClipboard(); 1702 break; 1703 case KeyEvent.VK_ENTER: 1704 saw_return = true; 1705 break; 1706 case KeyEvent.VK_PAGE_UP: 1707 if ( e.getModifiers() == Event.CTRL_MASK ) { 1708 pageLeft(1); 1709 } else { 1710 pageUp(1); 1711 } 1712 break; 1713 case KeyEvent.VK_PAGE_DOWN: 1714 if ( e.getModifiers() == Event.CTRL_MASK ) { 1715 pageRight(1); 1716 } else { 1717 pageDown(1); 1718 } 1719 break; 1720 1721 case KeyEvent.VK_UP: 1722 if (e.getModifiers() == Event.CTRL_MASK) { 1723 lineUp(1); 1724 } 1725 break; 1726 case KeyEvent.VK_DOWN: 1727 if (e.getModifiers() == Event.CTRL_MASK) { 1728 lineDown(1); 1729 } 1730 break; 1731 } 1732 passOn = maybeConsume(e); 1733 } 1734 1735 public void keyReleased(KeyEvent e) { 1736 1739 1740 if (e.getKeyCode() == KeyEvent.VK_ENTER) { 1741 1744 saw_return = false; 1745 } 1746 maybeConsume(e); 1747 } 1748 }); 1749 1750 screen.addMouseMotionListener(new MouseMotionListener() { 1751 1752 public void mouseDragged(MouseEvent e) { 1753 1756 1757 if ( SwingUtilities.isRightMouseButton( e ) ) 1759 return; 1760 1761 if (left_down_point != null) { 1762 BCoord bc = toBufCoords(toViewCoord(left_down_point)); 1763 sel.track(new Coord(bc, firsta)); 1764 left_down_point = null; 1765 } 1766 drag_point = e.getPoint(); 1767 1770 1771 int scroll_direction = 0; 1772 1773 if (drag_point.y < 0) { 1774 scroll_direction |= Scroller.UP; 1775 } else if (drag_point.y > screen.getSize().height) { 1776 scroll_direction |= Scroller.DOWN; 1777 } 1778 1779 if (drag_point.x < 0) { 1780 scroll_direction |= Scroller.LEFT; 1781 } else if (drag_point.x > screen.getSize().width) { 1782 scroll_direction |= Scroller.RIGHT; 1783 } 1784 1785 scroll_to(scroll_direction, e); 1786 } 1787 1788 public void mouseMoved(MouseEvent e) { 1789 1802 } 1803 }); 1804 1805 addMouseWheelHandler( screen, vscroll_bar ); 1806 1807 screen.addMouseListener(new MouseListener() { 1808 1809 public void mouseClicked(MouseEvent e) { 1810 BCoord bcoord = toBufCoords(toViewCoord(e.getPoint())); 1811 1812 if (SwingUtilities.isLeftMouseButton(e)) { 1813 1816 if (click_to_type) 1817 requestFocus(); 1818 1819 } else if ( SwingUtilities.isMiddleMouseButton(e)) { 1820 1824 pasteFromSelection(); 1825 } 1826 } 1827 1828 public void mousePressed(MouseEvent e) { 1829 1832 1833 if (SwingUtilities.isLeftMouseButton(e)) { 1834 1835 if (e.isShiftDown()) { 1836 BCoord bc = toBufCoords(toViewCoord(e.getPoint())); 1840 if (sel.extend(new Coord(bc, firsta))) { 1841 fireSelectionExtentChanged(); 1842 repaint(false); 1843 } 1844 return; 1845 } 1846 1847 if (sel.cancel(false)) 1848 repaint(false); 1849 1850 if (e.getClickCount() == 1) { 1851 left_down_point = (Point) e.getPoint().clone(); 1852 1853 } else if (e.getClickCount() == 2) { 1854 BCoord bcoord = toBufCoords(toViewCoord(e.getPoint())); 1855 BExtent word = buf.find_word(word_delineator, bcoord); 1856 sel.select_word(word.toExtent(firsta)); 1857 repaint(false); 1858 1859 } else if (e.getClickCount() == 3) { 1860 BCoord bcoord = toBufCoords(toViewCoord(e.getPoint())); 1861 sel.select_line(new Coord(bcoord, firsta)); 1862 repaint(false); 1863 1864 } 1865 1866 fireSelectionExtentChanged(); 1867 } 1868 } 1869 public void mouseReleased(MouseEvent e) { 1870 1873 if (SwingUtilities.isLeftMouseButton(e)) { 1874 1875 if (e.isShiftDown()) { 1876 return; 1878 } 1879 1880 if (scroller != null) { 1881 scroller.interrupt(); 1882 scroller = null; 1883 } 1884 1885 if (left_down_point == null) 1889 sel.done( ); 1890 left_down_point = null; 1891 } 1892 } 1893 1894 1895 1898 public void mouseEntered(MouseEvent e) { 1899 1902 if (!click_to_type) { 1903 requestFocus(); 1904 } 1905 } 1906 public void mouseExited(MouseEvent e) { 1907 1910 } 1911 1912 }); 1913 1914 screen.addFocusListener(new FocusListener() { 1915 public void focusGained(FocusEvent e) { 1916 1919 has_focus = true; 1920 repaint(false); 1921 } 1922 1923 public void focusLost(FocusEvent e) { 1924 1928 1929 has_focus = false; 1930 repaint(false); 1931 } 1932 } ); 1933 } 1934 1935 1936 1939 public void printStats(String message) { 1940 if (message != null) 1941 System.out.println(message); 1942 1943 if (message != null) 1944 System.out.print("\t"); buf.printStats(); 1946 1947 if (message != null) 1948 System.out.print("\t"); System.out.println("rows " + st.rows + " v cols " + buf.visibleCols() + " t cols " + buf.totalCols() + " history " + history_size + " firstx " + st.firstx + " firsty " + st.firsty + " firsta " + firsta + " gutter " + glyph_gutter_width); 1958 if (message != null) 1959 System.out.print("\t"); System.out.println("Cursor " + st.cursor + " topMargin " + topMargin() + " botMargin " + botMargin()); 1964 if (message != null) 1965 System.out.print("\t"); System.out.println("putChar " + n_putchar + " putChars " + n_putchars + " linefeeds " + n_linefeeds + " repaint " + n_repaint + " paint " + n_paint); } 1972 1973 public void paste() { 1974 pasteFromClipboard(); 1975 } 1976 1977 private void pasteHelp(Clipboard cb) { 1978 if (read_only) 1979 return; 1980 1981 Transferable contents = cb.getContents(screen); 1982 if (contents == null) 1983 return; 1984 1985 if (!contents.isDataFlavorSupported(DataFlavor.stringFlavor)) 1986 return; 1987 1988 try { 1989 String string; 1990 string = (String ) contents.getTransferData(DataFlavor.stringFlavor); 1991 1994 char ca[] = string.toCharArray(); 1995 sendChars(ca, 0, ca.length); 1996 } catch (Exception e) { 1997 ; 1998 } 1999 } 2000 2001 2012 public void pasteFromSelection() { 2013 2016 if (systemSelection == null) 2017 return; 2018 pasteHelp(systemSelection); 2019 } 2020 2021 2032 public void pasteFromClipboard() { 2033 pasteHelp(systemClipboard); 2034 } 2035 2036 2039 public void copy() { 2040 copyToClipboard(); 2041 } 2042 2043 2046 public void copyToClipboard() { 2047 String text = sel.getSelection(); 2048 if (text != null) { 2049 StringSelection ss = new StringSelection(text); 2050 systemClipboard.setContents(ss, sel); 2051 } 2052 } 2053 2054 2057 public void copyToSelection() { 2058 2061 2062 if (systemSelection == null) 2063 return; 2064 String text = sel.getSelection(); 2065 StringSelection ss = new StringSelection(text); systemSelection.setContents(ss, sel); 2067 } 2068 2069 private static Extent old_extent = null; 2070 2071 void fireSelectionExtentChanged() { 2072 Extent new_extent = getSelectionExtent(); 2073 firePropertyChange("selectionExtent", old_extent, new_extent); 2074 old_extent = new_extent; 2075 } 2076 2077 2082 public void setRows(int rows) { 2083 if (old_rows == -1) 2084 old_rows = st.rows; 2085 st.rows = rows; 2086 2087 updateScreenSize(); 2088 } 2089 2090 2093 public int getRows() { 2094 return st.rows; 2095 } 2096 2097 2102 public void setColumns(int cols) { 2103 buf.setVisibleCols(cols); 2104 updateScreenSize(); 2105 } 2106 2107 2110 void noteColumn(Line l, int capacity) { 2111 int vcapacity = l.bufToCell(metrics, capacity); 2112 buf.noteColumn(vcapacity); 2113 } 2114 2115 2118 void checkForMultiCell(char c) { 2119 metrics.checkForMultiCell(c); 2120 } 2121 2122 2125 public int getColumns() { 2126 return buf.visibleCols(); 2127 } 2128 2129 2153 2154 public void setRowsColumns(int rows, int columns) { 2155 2156 2159 if (old_rows == -1) 2160 old_rows = st.rows; 2161 st.rows = rows; 2162 buf.setVisibleCols(columns); 2163 2164 updateScreenSize(); 2165 } 2166 2167 2179 public void setSizeRounded(boolean size_rounded) { 2180 this.size_rounded = size_rounded; 2181 updateScreenSize(); 2182 } 2183 2184 2190 public boolean isSizeRounded() { 2191 return size_rounded; 2192 } 2193 2194 private boolean size_rounded = true; 2195 2196 2200 public void fillSizeInfo(Dimension cells, Dimension pixels) { 2201 cells.height = st.rows; 2202 cells.width = buf.visibleCols(); 2203 Dimension cpixels = screen.getSize(); 2204 pixels.width = cpixels.width - glyph_gutter_width - debug_gutter_width; 2205 pixels.height = cpixels.height; 2206 } 2207 2208 2212 protected void updateTtySize() { 2213 if (screen != null) { 2214 Dimension cells = new Dimension(buf.visibleCols(), st.rows); 2215 Dimension pixels = screen.getSize(); 2216 fireSizeChanged(cells, pixels); 2217 } 2218 } 2219 2220 2223 2224 BCoord toViewCoord(BCoord b) { 2225 2228 Line l = buf.lineAt(b.row); 2229 if (l != null) { int vc = buf.lineAt(b.row).bufToCell(metrics, b.col); 2233 BCoord v = new BCoord(b.row - st.firstx, vc - st.firsty); 2234 return v; 2235 } else { 2236 return null; 2237 } 2238 } 2239 2240 Point toPixel(BCoord v) { 2241 2244 Point p = new Point(v.col * metrics.width + 2245 glyph_gutter_width + 2246 debug_gutter_width, 2247 v.row * metrics.height); 2248 return p; 2249 } 2250 2251 2256 public Point toPixel(Coord target) { 2257 BCoord btarget = target.toBCoord(firsta); 2258 return toPixel( btarget ); 2259 } 2260 2261 2264 BCoord toViewCoord(Point p) { 2265 BCoord v = new BCoord(p.y / metrics.height, 2266 (p.x - glyph_gutter_width - debug_gutter_width) / metrics.width); 2267 v.clip(st.rows, buf.visibleCols()); 2268 2271 return v; 2272 } 2273 2274 BCoord toBufCoords(BCoord v) { 2275 2279 int brow = st.firstx + v.row; 2280 if (brow >= buf.nlines) 2281 brow = buf.nlines-1; 2282 int bc = buf.lineAt(brow).cellToBuf(metrics, st.firsty + v.col); 2283 BCoord b = new BCoord(brow, bc); 2284 2287 return b; 2288 } 2289 2290 2296 public Point mapToViewRowCol(Point p) { 2297 BCoord c = toViewCoord(p); 2298 return new Point(c.col, c.row); 2299 } 2300 2301 2307 public Point mapToBufRowCol(Point p) { 2308 BCoord c = toBufCoords(toViewCoord(p)); 2309 return new Point(c.col, c.row); 2310 } 2311 2312 private Color rendition_to_color(int rendition) { 2313 switch (rendition) { 2314 case 40: return standard_color[0]; 2315 case 41: return standard_color[1]; 2316 case 42: return standard_color[2]; 2317 case 43: return standard_color[3]; 2318 case 44: return standard_color[4]; 2319 case 45: return standard_color[5]; 2320 case 46: return standard_color[6]; 2321 case 47: return standard_color[7]; 2322 2323 case 58: return custom_color[0]; 2324 case 59: return custom_color[1]; 2325 case 60: return custom_color[2]; 2326 case 61: return custom_color[3]; 2327 case 62: return custom_color[4]; 2328 case 63: return custom_color[5]; 2329 case 64: return custom_color[6]; 2330 case 65: return custom_color[7]; 2331 2332 default: return null; 2333 } 2334 } 2335 2336 2337 private Color actual_foreground; 2338 private Color actual_background; 2339 private boolean check_selection; 2340 private int totcols; 2341 2342 private void do_run(Graphics g, int yoff, int xoff, int baseline, 2343 int brow, char buf[], Line l, 2344 int attr, int rbegin, int rend) { 2345 2346 2349 2350 int x; 2351 int rlength; 2352 int xlength; 2353 2354 if (metrics.isMultiCell()) { 2355 int vbegin = l.bufToCell(metrics, rbegin); 2356 int vend = l.bufToCell(metrics, rend+1)-1; 2357 x = xoff + (vbegin - st.firsty) * metrics.width; 2358 int vlength = vend - vbegin + 1; 2359 if (vlength <= 0) { 2360 2363 return; 2364 } 2365 rlength = rend - rbegin + 1; 2366 xlength = vlength * metrics.width; 2367 2368 } else { 2369 x = xoff + (rbegin - st.firsty) * metrics.width; 2370 rlength = rend - rbegin + 1; 2371 if (rlength <= 0) { 2372 2375 return; 2376 } 2377 xlength = rlength * metrics.width; 2378 } 2379 2380 boolean reverse = ((attr & Attr.REVERSE) == Attr.REVERSE); 2381 boolean active = ((attr & Attr.ACTIVE) == Attr.ACTIVE); 2382 2383 Color bg = null; 2385 2386 if (active) { 2387 bg = active_color; 2388 } else { 2389 bg = backgroundColor(reverse, attr); 2390 } 2391 2392 if (bg != null) { 2393 g.setColor(bg); 2395 g.fillRect(x, yoff, xlength, metrics.height - metrics.leading); 2396 } 2397 2398 Color fg = foregroundColor(reverse, attr); 2400 g.setColor(fg); 2401 2402 if ( (attr & Attr.UNDERSCORE) == Attr.UNDERSCORE) { 2404 int h = metrics.height - metrics.leading - 1; 2405 g.drawLine(x, yoff+h, x + xlength, yoff+h); 2406 } 2407 2408 myDrawChars(g, buf, l, rbegin, rlength, x, baseline); 2410 2411 if ( (attr & Attr.BRIGHT) == Attr.BRIGHT) { 2413 myDrawChars(g, buf, l, rbegin, rlength, x+1, baseline); 2414 } 2415 } 2416 2417 2418 2419 private final Point newp = new Point(); 2420 2421 2424 private void massage_glyphs(GlyphVector gv, int start, int n, Line l) { 2425 Point2D pos0 = gv.getGlyphPosition(0); 2426 2427 newp.y = (int) pos0.getY(); 2431 2432 int col = (int) pos0.getX(); 2433 for (int gx = 0; gx < n; gx++) { 2434 newp.x = col; 2435 gv.setGlyphPosition(gx, newp); 2436 col += l.width(metrics, start + gx) * metrics.width; 2437 } 2438 } 2439 2440 2488 2489 private void myDrawChars(Graphics g, char buf[], Line l, 2490 int start, int howmany, int xoff, int baseline) { 2491 if (metrics.isMultiCell()) { 2492 2496 Graphics2D g2 = (Graphics2D) g; 2497 FontRenderContext frc = g2.getFontRenderContext(); 2498 char[] tmp = new char[howmany]; 2501 System.arraycopy(buf, start, tmp, 0, howmany); 2502 GlyphVector gv = getFont().createGlyphVector(frc, tmp); 2503 massage_glyphs(gv, start, howmany, l); 2504 g2.drawGlyphVector(gv, xoff, baseline); 2505 } else { 2506 g.drawChars(buf, start, howmany, xoff, baseline); 2508 } 2509 } 2510 2511 2515 2516 private void paint_line_new(Graphics g, Line l, int brow, 2517 int xoff, int yoff, int baseline, 2518 Extent selx) { 2519 2520 int length = l.length(); 2521 if (length == 0) 2522 return; 2523 2524 int lastcol; 2525 int firstcol; 2526 2527 if (metrics.isMultiCell()) { 2528 2529 2532 2536 firstcol = l.cellToBuf(metrics, st.firsty); 2537 int inverse_firstcol = l.bufToCell(metrics, firstcol); 2538 int delta = st.firsty - inverse_firstcol; 2539 if (delta > 0) { 2540 2549 2550 firstcol++; 2551 int pdelta = delta * metrics.width; xoff += pdelta; 2553 } 2554 2555 lastcol = l.cellToBuf(metrics, st.firsty + buf.visibleCols() - 1); 2556 2557 2566 2567 } else { 2568 lastcol = st.firsty + buf.visibleCols() - 1; 2569 firstcol = st.firsty; 2570 } 2571 2572 2573 lastcol = Math.min(lastcol, length-1); 2574 if (firstcol > lastcol) 2575 return; 2576 int howmany = lastcol - firstcol + 1; 2577 2578 2579 2581 char buf[] = l.charArray(); 2582 2583 if (! l.hasAttributes()) { 2584 2585 if (debugWrap()) { 2586 if (l.isWrapped() && l.isAboutToWrap()) 2587 g.setColor(Color.red); else if (l.isAboutToWrap()) 2589 g.setColor(Color.orange); 2590 else if (l.isWrapped()) 2591 g.setColor(Color.magenta); 2592 } 2593 2594 myDrawChars(g, buf, l, firstcol, howmany, xoff, baseline); 2595 2596 2597 return; 2598 } 2599 2600 int attrs[] = l.attrArray(); 2601 2602 int sbegin = -1; 2604 int send = -1; 2605 if (check_selection && selx != null) { 2606 int arow = firsta + brow; 2607 Coord b = selx.begin; 2608 Coord e = selx.end; 2609 if (b.row <= arow && e.row >= arow) { 2610 if (b.row == e.row) { 2611 sbegin = b.col; 2612 send = e.col; 2613 } else if (arow == b.row) { 2614 sbegin = b.col; 2615 send = totcols; 2616 } else if (arow == e.row) { 2617 sbegin = 0; 2618 send = e.col; 2619 } else { 2620 sbegin = 0; 2621 send = totcols; 2622 } 2623 } 2624 } 2625 2626 2628 int rbegin = firstcol; 2629 int rend = rbegin; 2630 2631 while (true) { 2632 2633 2637 int attr = attrs[rbegin]; 2638 rend = rbegin+1; 2639 while (rend <= lastcol) { 2640 if (attrs[rend] != attr) 2641 break; 2642 rend++; 2643 } 2644 rend--; 2645 2646 2651 int alt_attr = (attr & ~ (Attr.BGCOLOR|Attr.FGCOLOR|Attr.REVERSE|Attr.ACTIVE)); 2652 if (sbegin == -1 || send < rbegin || sbegin > rend) { 2653 do_run(g, yoff, xoff, 2655 baseline, brow, buf, l, attr, rbegin, rend); 2656 2657 } else if (sbegin <= rbegin && send >= rend) { 2658 2662 do_run(g, yoff, xoff, 2663 baseline, brow, buf, l, alt_attr, rbegin, rend); 2664 2665 } else if (sbegin > rbegin && send < rend) { 2666 2671 do_run(g, yoff, xoff, 2672 baseline, brow, buf, l, attr, rbegin, sbegin-1); 2673 do_run(g, yoff, xoff, 2674 baseline, brow, buf, l, alt_attr, sbegin, send); 2675 do_run(g, yoff, xoff, 2676 baseline, brow, buf, l, attr, send+1, rend); 2677 2678 } else if (sbegin <= rbegin) { 2679 2683 do_run(g, yoff, xoff, 2685 baseline, brow, buf, l, alt_attr, rbegin, send); 2686 do_run(g, yoff, xoff, 2687 baseline, brow, buf, l, attr, send+1, rend); 2688 2689 } else if (send >= rend) { 2690 2695 do_run(g, yoff, xoff, 2696 baseline, brow, buf, l, attr, rbegin, sbegin-1); 2697 do_run(g, yoff, xoff, 2698 baseline, brow, buf, l, alt_attr, sbegin, rend); 2699 2700 } else { 2701 2704 } 2705 2706 if (rend+1 >= lastcol) 2707 break; 2708 2709 rbegin = rend + 1; 2711 } 2712 } 2713 2714 void do_paint(Graphics g) { 2715 ckEventDispatchThread(); 2716 2717 2725 if (st.firstx == -1) { 2726 2729 return; 2730 } 2731 2732 2735 2736 g.setFont(getFont()); 2740 2741 n_paint++; 2742 2743 if (reverse_video) { 2744 actual_foreground = getBackground(); 2745 actual_background = getForeground(); 2746 } else { 2747 actual_foreground = getForeground(); 2748 actual_background = getBackground(); 2749 } 2750 2751 g.setColor(actual_background); 2753 g.fillRect(0, 0, screen.getSize().width, screen.getSize().height); 2754 2755 2758 2759 int xoff = debug_gutter_width + glyph_gutter_width; 2760 2761 int lx = st.firstx; 2762 2763 for (int vrow = 0; vrow < st.rows; vrow++) { 2764 Line l = buf.lineAt(lx); 2765 if (l == null) 2766 break; 2768 int yoff = metrics.height*vrow; 2769 2770 Color background = rendition_to_color(l.glyph_rendition); 2771 if (background != null) { 2772 int rect_height = metrics.height - metrics.leading; 2773 g.setColor(background); 2774 g.fillRect(xoff, yoff, screen.getWidth(), rect_height); 2775 } 2776 2777 lx++; 2778 } 2779 2780 2781 if (!selection_xor) { 2782 2788 sel.paint(g); 2789 } 2790 2791 2792 g.setColor(actual_foreground); 2793 2794 Extent selx = sel.getExtent(); 2795 check_selection = (selx != null && !selection_xor); 2796 totcols = buf.totalCols(); 2797 2798 2801 lx = st.firstx; 2802 2803 for (int vrow = 0; vrow < st.rows; vrow++) { 2804 Line l = buf.lineAt(lx); 2805 if (l == null) { 2806 2809 printStats(null); 2810 break; 2811 } 2812 2813 xoff = 0; 2814 int yoff = metrics.height*vrow; 2815 int baseline = yoff + metrics.ascent; 2816 2817 if (debug_gutter_width > 0) { 2818 String buf = "" + (firsta + st.firstx + vrow); g.drawString(buf, xoff, baseline); 2820 } 2821 xoff += debug_gutter_width; 2822 2823 if (glyph_gutter_width > 0) { 2825 Image image = glyph_images[l.glyph_glyph]; 2826 if (image != null) { 2827 int gyoff = yoff; 2829 g.drawImage(image, xoff, gyoff, Color.white, null); 2830 } 2831 } 2832 xoff += glyph_gutter_width; 2833 2834 paint_line_new(g, l, vrow + st.firstx, xoff, yoff, baseline, selx); 2835 2836 g.setColor(actual_foreground); 2838 2839 lx++; 2840 } 2841 2842 paint_cursor(g); 2843 2844 if (selection_xor) 2845 sel.paint(g); 2846 2847 if (debugMargins()) 2848 paint_margins(g); 2849 2850 2855 } 2856 2857 private void paint_margins(Graphics g) { 2858 } 2859 2860 private void paint_cursor(Graphics g) { 2861 if (!cursor_visible) 2862 return; 2863 2864 if (st.cursor.row == -1) { 2866 return; 2869 } 2870 2871 int cursor_row = st.cursor.row - st.firstx; 2872 if (cursor_row >= st.rows) { 2873 return; } 2875 2876 int cursor_col = st.cursor.col - st.firsty; 2877 if (cursor_col >= buf.visibleCols()) { 2878 return; } else if (cursor_col < 0) { 2880 return; } 2882 2883 g.setXORMode(actual_background); 2884 int rect_x = cursor_col * metrics.width + 2885 glyph_gutter_width + 2886 debug_gutter_width; 2887 int rect_y = cursor_row * metrics.height; 2888 int rect_width = metrics.width; 2890 int rect_height = metrics.height - metrics.leading; 2891 if (has_focus) 2892 g.fillRect(rect_x, rect_y, rect_width, rect_height); 2893 else 2894 g.drawRect(rect_x, rect_y, rect_width, rect_height); 2895 } 2896 2897 private final boolean do_margins = true; 2898 2899 private boolean possiblyScrollDown() { 2900 2905 2906 if (!do_margins) { 2907 if (st.cursor.row >= st.firstx + st.rows) { 2908 st.firstx++; 2910 return true; 2911 } 2912 return false; 2913 } else { 2914 if (st.cursor.row >= st.firstx + botMargin() + 1) { 2916 if (topMargin() == 0) { 2918 if (scroll_on_output || cursor_was_visible() && track_cursor) 2919 st.firstx++; 2920 return true; 2921 } else { 2922 st.cursor.row = st.firstx + botMargin(); 2923 Line l = buf.moveLineFromTo(st.firstx + topMargin(), 2924 st.cursor.row); 2925 l.reset(); 2926 return false; 2927 } 2928 } 2929 return false; 2930 } 2931 } 2932 2933 2936 public void putChar(char c) { 2937 dce_end.putChar(c); 2938 } 2939 2940 2946 public void putChars(char buf[], int offset, int count) { 2947 dce_end.putChars(buf, offset, count); 2948 } 2949 2950 2966 public void flush() { 2967 dce_end.flush(); 2968 } 2969 2970 2975 private void reply(String str) { 2976 2979 for (int sx = 0; sx < str.length(); sx++) 2980 sendChar(str.charAt(sx)); 2981 } 2982 2983 2984 2988 private class OpsImpl implements Ops { 2989 2990 public void op_pause() { 2991 2992 Thread.currentThread().yield(); 2994 2995 3007 } 3008 3009 3010 public void op_char(char c) { 3011 if (debugOps()) 3012 System.out.println("op_char('" + c + "') = " + (int) c); 3014 Line l = cursor_line(); 3016 3017 int insertion_col = l.cellToBuf(metrics, st.cursor.col); 3018 if (debugOps()) { 3019 System.out.println("op_char(): st.cursor.col " + st.cursor.col + " insertion_col " + insertion_col); } 3022 if (!st.overstrike) { 3023 l.insertCharAt(Term.this, ' ', insertion_col, st.attr); 3025 } 3026 3027 int cwidth = metrics.wcwidth(c); 3028 if (l.isAboutToWrap() || 3029 (cwidth > 1 && 3030 st.cursor.col + cwidth > buf.visibleCols() && 3031 !horizontally_scrollable)) { 3032 3033 if (debugOps()) 3035 System.out.println("\twrapping it"); l.setWrapped(true); 3037 l.setAboutToWrap(false); 3038 op_line_feed(); 3039 op_carriage_return(); 3040 l = cursor_line(); 3041 insertion_col = 0; 3042 } 3044 3045 l.setCharAt(Term.this, c, insertion_col, st.attr); st.cursor.col += cwidth; 3047 3048 if (st.cursor.col >= buf.visibleCols() && !horizontally_scrollable) { 3049 if (debugOps()) 3050 System.out.println("\tabout to wrap"); l.setAboutToWrap(true); 3052 st.cursor.col -= cwidth; 3053 } 3054 } 3055 3056 public void op_attr(int attr) { 3057 if (debugOps()) 3058 System.out.println("op_attr(" + attr + ")"); setAttribute(attr); 3060 } 3061 3062 public void op_bel() { 3063 } 3066 3067 public void op_back_space() { 3068 if (debugOps()) 3070 System.out.println("op_back_space"); 3072 if (st.cursor.col > 0) { 3073 if (! cursor_line().isAboutToWrap()) { 3074 st.cursor.col--; 3075 } 3076 cursor_line().setAboutToWrap(false); 3077 3078 3082 if (st.cursor.col == 0) { 3083 if (st.cursor.row > 0) { 3084 if (debugOps()) 3086 System.out.println("\tchecking if prev is wrapped"); Line prev = buf.lineAt(st.cursor.row-1); 3088 if (prev.isWrapped()) { 3089 if (debugOps()) 3090 System.out.println("\tit is"); st.cursor.row--; 3092 3093 3100 3102 int last_col = prev.cellToBuf(metrics, buf.visibleCols()-1); 3103 st.cursor.col = prev.bufToCell(metrics, last_col); 3104 3105 prev.setWrapped(false); 3106 3107 prev.setAboutToWrap(true); 3111 } 3112 } 3113 } 3114 } 3115 } 3116 3117 public void op_line_feed() { 3118 if (debugOps()) 3122 System.out.println("op_line_feed"); Line last_line = cursor_line(); 3124 3130 st.cursor.row++; 3131 if (possiblyScrollDown()) { 3132 buf.addLineAt(st.cursor.row); 3133 limit_lines(); 3134 if (debugOps()) 3135 System.out.println("op_line_feed ADJUSTED"); } 3137 boolean atw = last_line.isAboutToWrap(); 3139 cursor_line().setAboutToWrap(atw); 3140 last_line.setAboutToWrap(false); 3141 3142 n_linefeeds++; 3143 3144 } 3147 3148 public void op_tab() { 3149 3154 if (debugOps()) 3155 System.out.println("op_tab"); 3157 if (st.cursor.col == buf.visibleCols()-1 && !horizontally_scrollable) 3158 return; 3159 3160 Line l = cursor_line(); 3161 int insert_col = l.cellToBuf(metrics, st.cursor.col); 3162 l.setCharAt(Term.this, ' ', insert_col, st.attr); 3163 st.cursor.col++; 3164 insert_col++; 3165 while ((st.cursor.col < buf.visibleCols()-1 || horizontally_scrollable) && 3167 (st.cursor.col % tab_size) != 0) { 3168 cursor_line().setCharAt(Term.this, ' ', insert_col, st.attr); 3169 st.cursor.col++; 3170 insert_col++; 3171 } 3172 } 3173 3174 public void op_carriage_return() { 3175 if (debugOps()) 3176 System.out.println("op_carriage_return"); st.cursor.col = 0; 3178 cursor_line().setAboutToWrap(false); 3179 } 3180 3181 public void op_al(int count) { 3182 if (debugOps()) 3184 System.out.println("op_al(" + count + ")"); 3186 Line l; 3187 while (count-- > 0) { 3188 boolean old_atw = cursor_line().setAboutToWrap(false); 3189 3190 if (!do_margins) { 3193 l = buf.moveLineFromTo(buf.nlines-1, st.cursor.row); 3194 } else { 3195 l = buf.moveLineFromTo(st.firstx + botMargin(), st.cursor.row); 3196 } 3197 l.reset(); 3198 3199 cursor_line().setAboutToWrap(old_atw); 3200 } 3201 3202 switch(sel.intersection(st.cursor.row - 1)) { 3203 case Sel.INT_NONE: 3204 case Sel.INT_ABOVE: 3205 case Sel.INT_ON: 3206 break; 3208 case Sel.INT_STRADDLES: 3209 sel.cancel(true); break; 3211 case Sel.INT_BELOW: 3212 sel.adjust(firsta, +1, firsta + buf.nlines); 3213 break; 3214 } 3215 } 3216 3217 public void op_bc(int count) { 3218 if (debugOps()) 3220 System.out.println("op_bc(" + count + ")"); 3222 while (count-- > 0) { 3223 if (st.cursor.col <= 0) 3224 return; 3225 st.cursor.col--; 3226 } 3227 cursor_line().setAboutToWrap(false); 3228 } 3229 3230 public void op_cm(int row, int col) { 3231 if (debugOps()) 3233 System.out.println("op_cm(row " + row + ", col " + col + ")"); 3235 3237 if (row == 0) 3239 row = 1; 3240 if (col == 0) 3241 col = 1; 3242 3243 if (row > st.rows) 3245 row = st.rows; 3246 if (col > buf.visibleCols()) 3247 col = buf.visibleCols(); 3248 3249 cursor_line().setAboutToWrap(false); 3250 st.cursor.row = beginx() + row - 1; 3251 st.cursor.col = col - 1; 3252 } 3254 3255 public void op_cl() { 3256 if (debugOps()) 3258 System.out.println("op_cl"); cursor_line().setAboutToWrap(false); 3260 clear(); 3261 st.cursor.row = beginx(); 3262 st.cursor.col = 0; 3263 } 3264 3265 public void op_ce() { 3266 if (debugOps()) 3268 System.out.println("op_ce"); 3270 Line l = cursor_line(); 3271 l.clearToEndFrom(Term.this, l.cellToBuf(metrics, st.cursor.col)); 3272 3273 switch(sel.intersection(st.cursor.row)) { 3274 case Sel.INT_NONE: 3275 case Sel.INT_ABOVE: 3276 case Sel.INT_BELOW: 3277 break; 3279 case Sel.INT_ON: 3280 case Sel.INT_STRADDLES: 3281 sel.cancel(true); break; 3283 } 3284 } 3285 3286 public void op_cd() { 3287 if (debugOps()) 3289 System.out.println("op_cd -- clear to end of screen"); 3291 for (int lx = st.cursor.row; lx < beginx() + st.rows; lx++) { 3292 Line l = buf.lineAt(lx); 3293 l.reset(); 3294 } 3295 3296 switch(sel.intersection(st.cursor.row)) { 3297 case Sel.INT_NONE: 3298 case Sel.INT_ABOVE: 3299 break; 3301 case Sel.INT_BELOW: 3302 case Sel.INT_ON: 3303 case Sel.INT_STRADDLES: 3304 sel.cancel(true); break; 3306 } 3307 } 3308 3309 public void op_dc(int count) { 3310 if (debugOps()) 3312 System.out.println("op_dc(" + count + ")"); if (count == 0) 3314 count = 1; 3315 Line l = cursor_line(); 3316 while (count-- > 0) 3317 l.deleteCharAt(l.cellToBuf(metrics, st.cursor.col)); 3318 } 3319 3320 public void op_dl(int count) { 3321 if (debugOps()) 3324 System.out.println("op_dl(" + count + ")"); 3326 Line l; 3327 while (count-- > 0) { 3328 boolean old_atw = cursor_line().setAboutToWrap(false); 3329 3330 if (!do_margins) { 3333 l = buf.moveLineFromTo(st.cursor.row, 3334 (beginx()+st.rows-1)-1); 3335 } else { 3336 l = buf.moveLineFromTo(st.cursor.row, 3337 (beginx()+botMargin())-1); 3338 } 3339 l.reset(); 3340 3341 cursor_line().setAboutToWrap(old_atw); 3342 } 3343 3344 switch(sel.intersection(st.cursor.row)) { 3345 case Sel.INT_NONE: 3346 case Sel.INT_ABOVE: 3347 break; 3349 case Sel.INT_ON: 3350 case Sel.INT_STRADDLES: 3351 sel.cancel(true); break; 3353 case Sel.INT_BELOW: 3354 sel.adjust(firsta, -1, firsta + buf.nlines); 3355 break; 3356 } 3357 } 3358 3359 public void op_do(int count) { 3360 3364 if (debugOps()) 3365 System.out.println("op_do(" + count + ") -- down"); 3367 boolean old_atw = cursor_line().setAboutToWrap(false); 3368 3369 while (count-- > 0) { 3370 st.cursor.row++; 3371 if (st.cursor.row >= buf.nlines) { 3372 3373 if (possiblyScrollDown()) { 3375 buf.addLineAt(st.cursor.row); 3376 limit_lines(); 3377 if (debugOps()) 3378 System.out.println("op_do ADJUSTED"); } 3380 } 3381 } 3382 cursor_line().setAboutToWrap(old_atw); 3383 } 3384 3385 public void op_ho() { 3386 if (debugOps()) 3388 System.out.println("op_ho -- home"); cursor_line().setAboutToWrap(false); 3390 st.cursor.row = beginx(); 3391 st.cursor.col = 0; 3392 } 3393 3394 public void op_ic(int count) { 3395 if (debugOps()) 3397 System.out.println("op_ic(" + count + ")"); 3399 Line l = cursor_line(); 3400 int insertion_col = l.cellToBuf(metrics, st.cursor.col); 3401 while (count-- > 0) { 3402 l.insertCharAt(Term.this, ' ', insertion_col, st.attr); 3403 } 3404 } 3406 3407 public void op_nd(int count) { 3408 if (debugOps()) 3410 System.out.println("op_nd(" + count + ")"); 3412 int vc = st.cursor.col; 3413 while (count-- > 0) { 3414 vc++; 3415 if (vc >= buf.visibleCols()) { 3416 if (debugOps()) 3417 System.out.println("\tbailing out at count " + count); vc--; 3419 break; 3420 } 3421 } 3422 st.cursor.col = vc; 3423 } 3424 3425 public void op_up(int count) { 3426 if (debugOps()) 3428 System.out.println("op_up(" + count + ")"); 3430 boolean old_atw = cursor_line().setAboutToWrap(false); 3431 Line l; 3432 while (count-- > 0) { 3433 st.cursor.row--; 3434 if (st.cursor.row < st.firstx) { 3435 st.cursor.row = st.firstx; 3436 if (!do_margins) { 3438 l = buf.moveLineFromTo(buf.nlines-1, st.cursor.row); 3439 } else { 3440 l = buf.moveLineFromTo(st.firstx + botMargin(), st.cursor.row); 3441 } 3442 l.reset(); 3443 } 3445 } 3446 cursor_line().setAboutToWrap(old_atw); 3447 } 3448 3449 public void op_sc() { 3450 if (debugOps()) 3452 System.out.println("op_sc()"); st.saveCursor(); 3454 } 3456 3457 public void op_rc() { 3458 if (debugOps()) 3460 System.out.println("op_rc()"); st.restoreCursor(); 3462 } 3463 3464 public void op_glyph(int glyph, int rendition) { 3465 if (debugOps()) { 3466 System.out.println("op_glyph(glyph " + glyph + ", rendition " + rendition + ")"); } 3469 setGlyph(glyph, rendition); 3470 } 3471 3472 public void op_reverse(boolean reverse_video) { 3473 setReverseVideo(reverse_video); 3474 } 3475 3476 public void op_cursor_visible(boolean visible) { 3477 setCursorVisible(visible); 3478 } 3479 3480 public void op_margin(int from, int to) { 3481 if (debugOps()) { 3482 System.out.println("op_margin(" + from + ", " + to + ")"); } 3485 3486 if (from < 0) 3487 top_margin = 0; 3488 else if (from > st.rows) 3489 top_margin = st.rows; 3490 else 3491 top_margin = from; 3492 3493 if (to < 0) 3494 bot_margin = 0; 3495 else if (to > st.rows) 3496 bot_margin = st.rows; 3497 else 3498 bot_margin = to; 3499 3500 if (top_margin > bot_margin) { 3501 int tmp = top_margin; 3502 top_margin = bot_margin; 3503 bot_margin = tmp; 3504 } 3505 } 3506 3507 long last_time = System.currentTimeMillis(); 3508 3509 public void op_time(boolean repaint) { 3510 long time = System.currentTimeMillis(); 3511 long elapsed = time - last_time; 3512 Date d = new Date (time); 3513 String date_str = d.toString(); 3514 String elapsed_str = "" + elapsed/1000 + "." + elapsed%1000; String output1 = date_str + " Elapsed (sec): " + elapsed_str; String output2 = "putChar " + n_putchar + " putChars " + n_putchars + " linefeeds " + n_linefeeds + " repaint " + n_repaint + " paint " + n_paint; 3522 setAttribute(41); 3524 3526 for (int sx = 0; sx < output1.length(); sx++) 3527 op_char(output1.charAt(sx)); 3528 op_line_feed(); 3529 op_carriage_return(); 3530 for (int sx = 0; sx < output2.length(); sx++) 3531 op_char(output2.charAt(sx)); 3532 3533 setAttribute(0); 3534 3535 last_time = time; 3536 n_putchar = 0; 3537 n_putchars = 0; 3538 n_linefeeds = 0; 3539 n_paint = 0; 3540 n_repaint = 0; 3541 3542 repaint(true); 3543 } 3545 3546 public int op_get_width() { 3547 return horizontally_scrollable? buf.totalCols(): buf.visibleCols(); 3548 } 3549 3550 public int op_get_column() { 3551 return st.cursor.col; 3552 } 3553 3554 public void op_soft_reset() { 3555 st.overstrike = true; 3556 top_margin = 0; bot_margin = 0; 3558 st.attr = 0; 3559 repaint(false); 3560 } 3561 3562 public void op_full_reset() { 3563 op_soft_reset(); 3564 op_cl(); reverse_video = false; 3566 repaint(false); 3567 } 3568 3569 public void op_set_mode(int mode) { 3570 switch (mode) { 3571 case 4: st.overstrike = false; 3573 break; 3574 case 2: case 12: case 20: break; 3579 } 3580 } 3581 3582 public void op_reset_mode(int mode) { 3583 switch (mode) { 3584 case 4: st.overstrike = true; 3586 break; 3587 case 2: case 12: case 20: break; 3592 } 3593 } 3594 public void op_status_report(int code) { 3595 switch (code) { 3596 case 5: 3597 reply((char)27 + "[0n"); break; 3599 case 6: 3600 reply((char)27 + "[" + (st.cursor.row - st.firstx) + ";" + st.cursor.col + "R"); break; 3604 } 3605 } 3606 } 3607 3608 private void putc_work(char c) { 3609 interp.processChar(c); 3610 possiblyHScroll(); 3611 screen.possiblyUpdateCaretText(); 3612 } 3613 3614 private void on_char(char c) { 3615 sendChar(c); 3616 } 3617 3618 private void sendChars(char c[], int offset, int count) { 3619 dte_end.sendChars(c, offset, count); 3620 } 3621 3622 private void sendChar(char c) { 3623 dte_end.sendChar(c); 3624 } 3625 3626 3629 private void adjust_scrollbar() { 3630 3631 3635 adjust_scrollbar_impl(); 3636 3637 3651 } 3652 3653 private void adjust_scrollbar_impl() { 3654 if (vscroll_bar != null) { 3655 int value = st.firstx; 3656 int extent = st.rows-1; 3657 int min = 0; 3658 int max; 3659 if (buf.nlines <= st.rows) 3660 max = st.rows - 1; 3661 else 3662 max = buf.nlines - 1; 3663 vscroll_bar.setValues(value, extent, min, max); 3664 } 3665 3666 if (hscroll_bar != null && horizontally_scrollable) { 3667 int value = st.firsty; 3668 int extent = buf.visibleCols()-1; 3669 int min = 0; 3670 int max; 3671 if (buf.totalCols() <= buf.visibleCols()) 3672 max = buf.visibleCols() - 1; 3673 else 3674 max = buf.totalCols() - 1; 3675 3676 3680 3681 hscroll_bar.setValues(value, extent, min, max); 3682 3683 3688 } 3689 } 3690 3691 3694 private Dimension calculateSize() { 3695 int dx = buf.visibleCols() * metrics.width + 3696 glyph_gutter_width + 3697 debug_gutter_width; 3698 int dy = st.rows * metrics.height; 3699 Dimension d = new Dimension(dx, dy); 3700 return d; 3701 } 3702 3703 3716 private void updateScreenSize() { 3717 3720 if (screen != null) { 3721 Dimension d = calculateSize(); 3722 sizeChanged(d.width, d.height); 3723 } 3724 } 3725 3726 3730 private int old_rows = -1; 3731 3732 3733 3741 3742 void sizeChanged(int newWidth, int newHeight) { 3743 3747 3748 int newcols = (newWidth - glyph_gutter_width - debug_gutter_width) / 3750 metrics.width; 3751 buf.setVisibleCols(newcols); 3752 3753 3754 if (old_rows == -1) { 3755 old_rows = st.rows; 3757 } 3758 3759 st.rows = newHeight/metrics.height; 3760 3761 if ( st.rows < 1 ) 3763 st.rows = 1; 3764 3765 3768 3769 int row_delta = st.rows - old_rows; old_rows = -1; 3771 3772 adjust_lines(row_delta); 3773 3774 limit_lines(); 3775 3776 3782 Dimension new_size = isSizeRounded()? 3783 calculateSize(): 3784 new Dimension(newWidth, newHeight); 3785 3786 3789 3790 if (false) { 3791 screen.setSize(new_size); 3796 3797 } else { 3798 screen.setPreferredSize(new_size); 3799 3800 invalidate(); 3802 if (getParent() != null) 3803 getParent().validate(); 3804 } 3805 3806 3807 updateTtySize(); 3811 } 3812 3813 3814 protected void possibly_repaint(boolean adjust_scrollbar) { 3815 if (!refresh_enabled) 3816 return; 3817 repaint(adjust_scrollbar); 3818 } 3819 3820 3823 protected void repaint(boolean adjust_scrollbar) { 3824 3825 3917 3918 n_repaint++; 3919 3920 if (adjust_scrollbar) 3921 adjust_scrollbar(); 3922 3923 3924 screen.repaint(20); 3927 3928 3929 3933 3938 } 3939 3940 3943 3944 3950 public void setReverseVideo(boolean reverse_video) { 3951 this.reverse_video = reverse_video; 3952 repaint(false); 3953 } 3954 3955 3958 public boolean isReverseVideo() { 3959 return reverse_video; 3960 } 3961 3962 private boolean reverse_video = false; 3963 3964 3967 public void setHighlightColor(Color color) { 3968 sel.setColor(color); 3969 repaint(false); 3970 } 3971 3972 3975 public Color getHighlightColor() { 3976 return sel.getColor(); 3977 } 3978 3979 3982 public void setHighlightXORColor(Color color) { 3983 sel.setXORColor(color); 3984 repaint(false); 3985 } 3986 3987 3990 public Color getHighlightXORColor() { 3991 return sel.getXORColor(); 3992 } 3993 3994 3995 3998 public void setActiveColor(Color color) { 3999 active_color = color; 4001 repaint(false); 4002 } 4003 4004 4007 public Color getActiveColor() { 4008 return active_color; 4011 } 4012 4013 private Color active_color = Color.lightGray; 4014 4015 4032 public void setAnchored(boolean anchored) { 4033 ckEventDispatchThread(); 4034 { 4036 if (anchored) { 4037 this.anchored = false; 4038 limit_lines(); 4039 this.anchored = true; 4040 } else { 4041 this.anchored = false; 4042 limit_lines(); 4043 repaint(false); } 4045 } 4046 } 4047 4048 4051 public boolean isAnchored() { 4052 return anchored; 4053 } 4054 4055 private boolean anchored = false; 4056 4057 4058 4063 public JComponent getCanvas() { 4064 return screen; 4065 } 4066 4067 4071 public JComponent getScreen() { 4072 return screen; 4073 } 4074 4075 4079 public Ops ops() { 4080 return ops; 4081 } 4082 4083 4087 public void setEmulation(String emulation) { 4088 Interp new_interp = InterpKit.forName(emulation, ops); 4089 if (new_interp == null) 4090 return; 4091 interp = new_interp; 4092 } 4093 4094 4098 public String getEmulation() { 4099 return getInterp().name(); 4100 } 4101 4102 4103 4110 public void setInterp(Interp interp) { 4111 this.interp = interp; 4112 } 4113 4114 4117 public Interp getInterp() { 4118 return interp; 4119 } 4120 4121 private Interp interp = new InterpDumb(ops); 4123 4124 4130 public void setHistorySize(int new_size) { 4131 history_size = new_size; 4132 limit_lines(); 4133 repaint(true); 4134 } 4135 4136 4139 public int getHistorySize() { 4140 return history_size; 4141 } 4142 private int history_size = 20; 4143 4144 4145 4146 4149 public void setGlyphGutterWidth(int pixels) { 4150 4151 glyph_gutter_width = pixels; 4152 4153 if (glyph_gutter_width > 30) 4155 glyph_gutter_width = 30; 4156 4157 updateScreenSize(); 4158 } 4159 private int glyph_gutter_width; 4160 4161 4168 public void setGlyphImage(int glyph_number, Image image) { 4169 if (glyph_number > 256) 4170 return; glyph_images[glyph_number] = image; 4172 } 4173 private Image glyph_images[] = new Image[256];; 4174 4175 4180 public Dimension getGlyphCellSize() { 4181 return new Dimension(glyph_gutter_width, metrics.height); 4182 } 4183 4184 4191 public void setCustomColor(int number, Color c) { 4192 custom_color[number] = c; 4193 } 4194 private final Color custom_color[] = new Color[8]; 4195 private final Color standard_color[] = new Color[8]; 4196 4197 4200 public int getCursorRow() { 4201 return st.cursor.row; 4202 } 4203 4204 4207 public int getCursorCol() { 4208 return cursor_line().cellToBuf(metrics, st.cursor.col); 4209 } 4210 4211 4216 public Coord getCursorCoord() { 4217 Line l = buf.lineAt(st.cursor.row); 4218 return new Coord(new BCoord(st.cursor.row, 4219 l.cellToBuf(metrics, st.cursor.col)), 4220 firsta); 4221 } 4222 4223 4229 public void goTo(Coord coord) { 4230 setCursorCoord(coord); 4231 } 4232 4233 4237 public void setCursorCoord(Coord coord) { 4238 Coord c = (Coord) coord.clone(); 4239 c.clip(st.rows, buf.visibleCols(), firsta); 4240 st.cursor = c.toBCoord(firsta); 4241 st.cursor.col = cursor_line().bufToCell(metrics, st.cursor.col); 4242 repaint(true); 4243 } 4244 4245 4251 public void setCursorVisible(boolean cursor_visible) { 4252 this.cursor_visible = cursor_visible; 4253 } 4254 4255 4258 public boolean isCursorVisible() { 4259 return cursor_visible; 4260 } 4261 4262 private boolean cursor_visible = true; 4263 4264 4265 4272 4273 public Coord backup(Coord c) { 4274 BCoord bRow = buf.backup(c.toBCoord(firsta)); 4275 if (bRow == null) 4276 return null; 4277 return new Coord(bRow, firsta); 4278 } 4279 4280 4287 public Coord advance(Coord c) { 4288 return new Coord(buf.advance(c.toBCoord(firsta)), firsta); 4289 } 4290 4291 4292 4297 public String getSelectedText() { 4298 return sel.getSelection(); 4299 } 4300 4301 4306 public Extent getSelectionExtent() { 4307 return sel.getExtent(); 4308 } 4309 4310 4313 public void setSelectionExtent(Extent extent) { 4314 extent.begin.clip(buf.nlines, buf.totalCols(), firsta); 4315 extent.end.clip(buf.nlines, buf.totalCols(), firsta); 4316 sel.setExtent(extent); 4317 repaint(false); 4318 } 4319 4320 4323 public void clearSelection() { 4324 sel.cancel( true ); 4325 repaint(false); 4326 } 4327 4328 4342 public void setAutoCopy(boolean auto_copy) { 4343 } 4345 4346 4351 public boolean isAutoCopy() { 4352 return true; 4353 } 4354 4355 4361 public void setRefreshEnabled(boolean refresh_enabled) { 4362 this.refresh_enabled = refresh_enabled; 4363 if (refresh_enabled) 4364 repaint(true); 4365 } 4366 public boolean isRefreshEnabled() { 4367 return refresh_enabled; 4368 } 4369 private boolean refresh_enabled = true; 4370 4371 4372 4376 public void setSelectionXOR(boolean selection_xor) { 4377 this.selection_xor = selection_xor; 4378 repaint(false); 4379 } 4380 4384 public boolean isSelectionXOR() { 4385 return selection_xor; 4386 } 4387 4388 boolean selection_xor = false; 4390 4391 4410 public void setTabSize(int tab_size) { 4411 this.tab_size = tab_size; 4412 } 4413 4414 4417 public int getTabSize() { 4418 return tab_size; 4419 } 4420 4421 private int tab_size = 8; 4422 4423 4428 public void setScrollOnInput(boolean scroll_on_input) { 4429 this.scroll_on_input = scroll_on_input; 4430 } 4431 4432 4435 public boolean isScrollOnInput() { 4436 return scroll_on_input; 4437 } 4438 4439 private boolean scroll_on_input = true; 4440 4441 4455 public void setScrollOnOutput(boolean scroll_on_output) { 4456 this.scroll_on_output = scroll_on_output; 4457 } 4458 4459 4462 public boolean isScrollOnOutput() { 4463 return scroll_on_output; 4464 } 4465 4466 private boolean scroll_on_output = true; 4467 4468 4469 4478 public void setTrackCursor(boolean track_cursor) { 4479 this.track_cursor = track_cursor; 4480 } 4481 4482 4485 public boolean isTrackCursor() { 4486 return track_cursor; 4487 } 4488 4489 private boolean track_cursor = true; 4490 4491 4492 4498 public void setHorizontallyScrollable(boolean horizontally_scrollable) { 4499 this.horizontally_scrollable = horizontally_scrollable; 4500 hscroll_wrapper.setVisible(horizontally_scrollable); 4502 } 4503 4504 4508 public boolean isHorizontallyScrollable() { 4509 return this.horizontally_scrollable; 4510 } 4511 4512 private boolean horizontally_scrollable = true; 4513 4514 4515 4521 public void setText(String text) { 4522 clearHistoryNoRefresh(); 4524 appendText(text, true); 4525 } 4526 4527 4534 public void appendText(String text, boolean repaint) { 4535 4536 if (text == null) 4537 return; 4538 4539 ckEventDispatchThread(); 4540 { 4542 for (int cx = 0; cx < text.length(); cx++) { 4543 putc_work(text.charAt(cx)); 4544 if (text.charAt(cx) == '\n') 4545 putc_work('\r'); 4546 } 4547 } 4548 if (repaint) 4549 repaint(true); 4550 } 4551 4552 4557 4558 public void pageUp(int n) { 4559 ckEventDispatchThread(); 4560 { 4562 st.firstx -= n * st.rows; 4563 if (st.firstx < 0) 4564 st.firstx = 0; 4565 } 4566 repaint(true); 4567 } 4568 4569 4574 4575 public void pageDown(int n) { 4576 ckEventDispatchThread(); 4577 { 4579 st.firstx += n * st.rows; 4580 4581 if (st.firstx + st.rows > buf.nlines) 4582 st.firstx = buf.nlines - st.rows; 4583 } 4584 repaint(true); 4585 } 4586 4587 4590 public void lineUp(int n) { 4591 ckEventDispatchThread(); 4592 { 4594 st.firstx -= n; 4595 if (st.firstx < 0) 4596 st.firstx = 0; 4597 } 4598 repaint(true); 4599 } 4600 4601 4604 public void lineDown(int n) { 4605 ckEventDispatchThread(); 4606 { 4608 st.firstx += n; 4609 if (st.firstx + st.rows > buf.nlines) 4610 st.firstx = buf.nlines - st.rows; 4611 } 4612 repaint(true); 4613 } 4614 4615 4618 public void pageLeft(int n) { 4619 columnLeft(n * buf.visibleCols()); 4620 } 4621 4622 4625 public void pageRight(int n) { 4626 columnRight(n * buf.visibleCols()); 4627 } 4628 4629 4632 public void columnRight(int n) { 4633 ckEventDispatchThread(); 4634 { 4636 st.firsty += n; 4637 if (st.firsty + buf.visibleCols() > buf.totalCols()) 4638 st.firsty = buf.totalCols() - buf.visibleCols(); 4639 } 4640 repaint(true); 4641 } 4642 4643 4646 public void columnLeft(int n) { 4647 ckEventDispatchThread(); 4648 { 4650 st.firsty -= n; 4651 if (st.firsty < 0) 4652 st.firsty = 0; 4653 } 4654 repaint(true); 4655 } 4656 4657 4660 public int charWidth(char c) { 4661 return metrics.wcwidth(c); 4662 } 4663 4664 4667 4668 4674 4675 public void setFont(Font new_font) { 4676 4677 Font font = new Font("Monospaced", new_font.getStyle(), 4679 new_font.getSize()); 4680 4681 super.setFont(font); 4684 4690 4691 metrics = new MyFontMetrics(this, font); 4693 4694 updateScreenSize(); 4695 } 4696 4697 4698 4704 public void requestFocus() { 4705 screen.requestFocus(); 4706 } 4707 4708 public boolean requestFocusInWindow() { 4709 return screen.requestFocusInWindow(); 4710 } 4711 4712 4717 public void setEnabled(boolean enabled) { 4718 4720 super.setEnabled(enabled); 4721 4722 hscroll_bar.setEnabled(enabled); 4723 vscroll_bar.setEnabled(enabled); 4724 screen.setEnabled(enabled); 4725 } 4726 4727 4728 4733 4803 4804 public AccessibleContext getAccessibleContext() { 4805 if (accessible_context == null) { 4806 accessible_context = new AccessibleTerm(); 4807 } 4808 return accessible_context; 4809 } 4810 private AccessibleContext accessible_context; 4811 4812 4817 protected class AccessibleTerm extends AccessibleJComponent { 4818 public AccessibleRole getAccessibleRole() { 4819 return AccessibleRole.PANEL; 4820 } 4821 public void setAccessibleName(String name) { 4822 screen.getAccessibleContext().setAccessibleName(name); 4823 } 4824 } 4825 4826 4832 public int CoordToPosition(Coord c) { 4833 BCoord b = c.toBCoord(firsta); 4834 int nchars = charsInPrehistory; 4835 for (int r = 0; r < b.row; r++) { 4836 Line l = buf.lineAt(r); 4837 nchars += l.length(); 4838 if (!l.isWrapped()) 4839 nchars += 1; 4840 } 4841 4842 nchars += c.col; 4843 4844 return nchars; 4845 } 4846 4847 4853 public Coord PositionToCoord(int position) { 4854 int nchars = charsInPrehistory; 4855 for (int r = 0; r < buf.nlines; r++) { 4856 Line l = buf.lineAt(r); 4857 nchars += l.length(); 4858 if (!l.isWrapped()) 4859 nchars += 1; 4860 if (nchars > position) { 4861 BCoord b = new BCoord(); 4862 b.row = r; 4863 b.col = buf.lineAt(r).length() + 1 - (nchars - position); 4864 return new Coord(b, firsta); 4865 } 4866 } 4867 return null; 4868 } 4869 4870 4876 4877 int getCharCount() { 4878 int nchars = charsInPrehistory; 4879 for (int r = 0; r < buf.nlines; r++) { 4880 Line l = buf.lineAt(r); 4881 nchars += l.length(); 4882 if (!l.isWrapped()) 4883 nchars += 1; 4884 } 4885 return nchars; 4886 } 4887 4888 4891 Rectangle getCharacterBounds(Coord c) { 4892 if (c == null) 4893 return null; 4894 BCoord b = c.toBCoord(firsta); 4895 4896 char ch = '\0'; 4897 try { 4898 Line l = buf.lineAt(b.row); 4899 ch = l.charArray()[b.col]; 4900 } catch(Exception x) { 4901 ; 4902 } 4903 4904 Point p1 = toPixel(b); 4905 Rectangle rect = new Rectangle(); 4906 rect.x = p1.x; 4907 rect.y = p1.y; 4908 rect.width = metrics.width * charWidth(ch); 4909 rect.height = metrics.height; 4910 return rect; 4911 } 4912 4913 Color backgroundColor(boolean reverse, int attr) { 4914 Color bg = null; 4915 if (reverse) { 4916 int fcx = Attr.foregroundColor(attr); 4917 if (fcx != 0 && fcx <= 8) { 4918 bg = standard_color[fcx-1]; 4919 } else if (fcx > 8) { 4920 bg = custom_color[fcx-9]; 4921 } else { 4922 bg = actual_foreground; 4923 } 4924 4925 } else { 4926 int bcx = Attr.backgroundColor(attr); 4927 if (bcx != 0 && bcx <= 8) { 4928 bg = standard_color[bcx-1]; 4929 } else if (bcx > 8) { 4930 bg = custom_color[bcx-9]; 4931 } 4932 } 4933 return bg; 4934 } 4935 4936 Color foregroundColor(boolean reverse, int attr) { 4937 Color fg = null; 4938 if (reverse) { 4939 int bcx = Attr.backgroundColor(attr); 4940 if (bcx != 0 && bcx <= 8) { 4941 fg = standard_color[bcx-1]; 4942 } else if (bcx > 8) { 4943 fg = custom_color[bcx-9]; 4944 } else { 4945 fg = actual_background; 4946 } 4947 4948 } else { 4949 int fcx = Attr.foregroundColor(attr); 4950 if (fcx != 0 && fcx <= 8) { 4951 fg = standard_color[fcx-1]; 4952 } else if (fcx > 8) { 4953 fg = custom_color[fcx-9]; 4954 } else { 4955 fg = actual_foreground; 4956 } 4957 } 4958 return fg; 4959 } 4960 4961 private static void ckEventDispatchThread() { 4962 4968 } 4969 4970 4972 private static void addMouseWheelHandler(JComponent comp, JScrollBar bar) { 4973 comp.addMouseWheelListener(new MouseWheelHandler (bar)); } 4975 4976 private static class MouseWheelHandler implements MouseWheelListener { 4977 4978 private JScrollBar scrollbar; 4979 4980 public MouseWheelHandler (JScrollBar scrollbar) { 4981 this.scrollbar = scrollbar; 4982 } 4983 4984 public void mouseWheelMoved(MouseWheelEvent e) { 4985 int totalScrollAmount = e.getUnitsToScroll() * scrollbar.getUnitIncrement(); 4986 scrollbar.setValue( scrollbar.getValue() + totalScrollAmount ); 4987 } 4988 4989 } 4990} 4991 | Popular Tags |