1 /* 2 * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". 3 * 4 * (c) Matthias L. Jugel, Marcus Mei�ner 1996-2005. All Rights Reserved. 5 * 6 * Please visit http://javatelnet.org/ for updates and contact. 7 * 8 * --LICENSE NOTICE-- 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * as published by the Free Software Foundation; either version 2 12 * of the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 * --LICENSE NOTICE-- 23 * 24 */ 25 26 package de.mud.terminal; 27 28 import java.util.Arrays; 29 30 /** 31 * Implementation of a Video Display Unit (VDU) buffer. This class contains all methods to 32 * manipulate the buffer that stores characters and their attributes as well as the regions 33 * displayed. 34 * 35 * @version $Id: VDUBuffer.java 503 2005-10-24 07:34:13Z marcus $ 36 */ 37 public class VDUBuffer { 38 39 /** The current version id tag */ 40 public final static String ID = "$Id: VDUBuffer.java 503 2005-10-24 07:34:13Z marcus $"; 41 42 /** Enable debug messages. */ 43 public final static int debug = 0; 44 45 public int height, width; /* rows and columns */ 46 public boolean[] update; /* contains the lines that need update */ 47 public char[][] charArray; /* contains the characters */ 48 public int[][] charAttributes; /* contains character attrs */ 49 public int bufSize; 50 public int maxBufSize; /* buffer sizes */ 51 public int screenBase; /* the actual screen start */ 52 public int windowBase; /* where the start displaying */ 53 public int scrollMarker; /* marks the last line inserted */ 54 55 private int topMargin; /* top scroll margin */ 56 private int bottomMargin; /* bottom scroll margin */ 57 58 // cursor variables 59 protected boolean showcursor = true; 60 protected int cursorX, cursorY; 61 62 /** Scroll up when inserting a line. */ 63 public final static boolean SCROLL_UP = false; 64 /** Scroll down when inserting a line. */ 65 public final static boolean SCROLL_DOWN = true; 66 67 /* 68 * Attributes bit-field usage: 69 * 70 * 8421 8421 8421 8421 8421 8421 8421 8421 |||| |||| |||| |||| |||| |||| |||| |||`- Bold |||| |||| 71 * |||| |||| |||| |||| |||| ||`-- Underline |||| |||| |||| |||| |||| |||| |||| |`--- Invert |||| 72 * |||| |||| |||| |||| |||| |||| `---- Low |||| |||| |||| |||| |||| |||| |||`------ Invisible |||| 73 * |||| |||| |||| ||`+-++++-+++------- Foreground Color |||| |||| |`++-++++-++------------------ 74 * Background Color |||| |||| `----------------------------- Fullwidth character 75 * `+++-++++------------------------------- Reserved for future use 76 */ 77 78 /** Make character normal. */ 79 public final static int NORMAL = 0x00; 80 /** Make character bold. */ 81 public final static int BOLD = 0x01; 82 /** Underline character. */ 83 public final static int UNDERLINE = 0x02; 84 /** Invert character. */ 85 public final static int INVERT = 0x04; 86 /** Lower intensity character. */ 87 public final static int LOW = 0x08; 88 /** Invisible character. */ 89 public final static int INVISIBLE = 0x10; 90 /** Unicode full-width character (CJK, et al.) */ 91 public final static int FULLWIDTH = 0x8000000; 92 93 /** how much to left shift the foreground color */ 94 public final static int COLOR_FG_SHIFT = 5; 95 /** how much to left shift the background color */ 96 public final static int COLOR_BG_SHIFT = 14; 97 /** color mask */ 98 public final static int COLOR = 0x7fffe0; /* 0000 0000 0111 1111 1111 1111 1110 0000 */ 99 /** foreground color mask */ 100 public final static int COLOR_FG = 0x3fe0; /* 0000 0000 0000 0000 0011 1111 1110 0000 */ 101 /** background color mask */ 102 public final static int COLOR_BG = 0x7fc000; /* 0000 0000 0111 1111 1100 0000 0000 0000 */ 103 104 /** 105 * Create a new video display buffer with the passed width and height in characters. 106 * 107 * @param width 108 * the length of the character lines 109 * @param height 110 * the amount of lines on the screen 111 */ VDUBuffer(int width, int height)112 public VDUBuffer(int width, int height) { 113 // set the display screen size 114 setScreenSize(width, height, false); 115 } 116 117 /** 118 * Create a standard video display buffer with 80 columns and 24 lines. 119 */ VDUBuffer()120 public VDUBuffer() { 121 this(80, 24); 122 } 123 124 /** 125 * Put a character on the screen with normal font and outline. The character previously on that 126 * position will be overwritten. You need to call redraw() to update the screen. 127 * 128 * @param c 129 * x-coordinate (column) 130 * @param l 131 * y-coordinate (line) 132 * @param ch 133 * the character to show on the screen 134 * @see #insertChar 135 * @see #deleteChar 136 * @see #redraw 137 */ putChar(int c, int l, char ch)138 public void putChar(int c, int l, char ch) { 139 putChar(c, l, ch, NORMAL); 140 } 141 142 /** 143 * Put a character on the screen with specific font and outline. The character previously on that 144 * position will be overwritten. You need to call redraw() to update the screen. 145 * 146 * @param c 147 * x-coordinate (column) 148 * @param l 149 * y-coordinate (line) 150 * @param ch 151 * the character to show on the screen 152 * @param attributes 153 * the character attributes 154 * @see #BOLD 155 * @see #UNDERLINE 156 * @see #INVERT 157 * @see #INVISIBLE 158 * @see #NORMAL 159 * @see #LOW 160 * @see #insertChar 161 * @see #deleteChar 162 * @see #redraw 163 */ 164 putChar(int c, int l, char ch, int attributes)165 public void putChar(int c, int l, char ch, int attributes) { 166 charArray[screenBase + l][c] = ch; 167 charAttributes[screenBase + l][c] = attributes; 168 if (l < height) { 169 update[l + 1] = true; 170 } 171 } 172 173 /** 174 * Get the character at the specified position. 175 * 176 * @param c 177 * x-coordinate (column) 178 * @param l 179 * y-coordinate (line) 180 * @see #putChar 181 */ getChar(int c, int l)182 public char getChar(int c, int l) { 183 return charArray[screenBase + l][c]; 184 } 185 186 /** 187 * Get the attributes for the specified position. 188 * 189 * @param c 190 * x-coordinate (column) 191 * @param l 192 * y-coordinate (line) 193 * @see #putChar 194 */ getAttributes(int c, int l)195 public int getAttributes(int c, int l) { 196 return charAttributes[screenBase + l][c]; 197 } 198 199 /** 200 * Insert a character at a specific position on the screen. All character right to from this 201 * position will be moved one to the right. You need to call redraw() to update the screen. 202 * 203 * @param c 204 * x-coordinate (column) 205 * @param l 206 * y-coordinate (line) 207 * @param ch 208 * the character to insert 209 * @param attributes 210 * the character attributes 211 * @see #BOLD 212 * @see #UNDERLINE 213 * @see #INVERT 214 * @see #INVISIBLE 215 * @see #NORMAL 216 * @see #LOW 217 * @see #putChar 218 * @see #deleteChar 219 * @see #redraw 220 */ insertChar(int c, int l, char ch, int attributes)221 public void insertChar(int c, int l, char ch, int attributes) { 222 System.arraycopy(charArray[screenBase + l], c, charArray[screenBase + l], c + 1, width - c - 1); 223 System.arraycopy(charAttributes[screenBase + l], c, charAttributes[screenBase + l], c + 1, 224 width - c - 1); 225 putChar(c, l, ch, attributes); 226 } 227 228 /** 229 * Delete a character at a given position on the screen. All characters right to the position will 230 * be moved one to the left. You need to call redraw() to update the screen. 231 * 232 * @param c 233 * x-coordinate (column) 234 * @param l 235 * y-coordinate (line) 236 * @see #putChar 237 * @see #insertChar 238 * @see #redraw 239 */ deleteChar(int c, int l)240 public void deleteChar(int c, int l) { 241 if (c < width - 1) { 242 System.arraycopy(charArray[screenBase + l], c + 1, charArray[screenBase + l], c, width - c 243 - 1); 244 System.arraycopy(charAttributes[screenBase + l], c + 1, charAttributes[screenBase + l], c, 245 width - c - 1); 246 } 247 putChar(width - 1, l, (char) 0); 248 } 249 250 /** 251 * Put a String at a specific position. Any characters previously on that position will be 252 * overwritten. You need to call redraw() for screen update. 253 * 254 * @param c 255 * x-coordinate (column) 256 * @param l 257 * y-coordinate (line) 258 * @param s 259 * the string to be shown on the screen 260 * @see #BOLD 261 * @see #UNDERLINE 262 * @see #INVERT 263 * @see #INVISIBLE 264 * @see #NORMAL 265 * @see #LOW 266 * @see #putChar 267 * @see #insertLine 268 * @see #deleteLine 269 * @see #redraw 270 */ putString(int c, int l, String s)271 public void putString(int c, int l, String s) { 272 putString(c, l, s, NORMAL); 273 } 274 275 /** 276 * Put a String at a specific position giving all characters the same attributes. Any characters 277 * previously on that position will be overwritten. You need to call redraw() to update the 278 * screen. 279 * 280 * @param c 281 * x-coordinate (column) 282 * @param l 283 * y-coordinate (line) 284 * @param s 285 * the string to be shown on the screen 286 * @param attributes 287 * character attributes 288 * @see #BOLD 289 * @see #UNDERLINE 290 * @see #INVERT 291 * @see #INVISIBLE 292 * @see #NORMAL 293 * @see #LOW 294 * @see #putChar 295 * @see #insertLine 296 * @see #deleteLine 297 * @see #redraw 298 */ putString(int c, int l, String s, int attributes)299 public void putString(int c, int l, String s, int attributes) { 300 for (int i = 0; i < s.length() && c + i < width; i++) { 301 putChar(c + i, l, s.charAt(i), attributes); 302 } 303 } 304 305 /** 306 * Insert a blank line at a specific position. The current line and all previous lines are 307 * scrolled one line up. The top line is lost. You need to call redraw() to update the screen. 308 * 309 * @param l 310 * the y-coordinate to insert the line 311 * @see #deleteLine 312 * @see #redraw 313 */ insertLine(int l)314 public void insertLine(int l) { 315 insertLine(l, 1, SCROLL_UP); 316 } 317 318 /** 319 * Insert blank lines at a specific position. You need to call redraw() to update the screen 320 * 321 * @param l 322 * the y-coordinate to insert the line 323 * @param n 324 * amount of lines to be inserted 325 * @see #deleteLine 326 * @see #redraw 327 */ insertLine(int l, int n)328 public void insertLine(int l, int n) { 329 insertLine(l, n, SCROLL_UP); 330 } 331 332 /** 333 * Insert a blank line at a specific position. Scroll text according to the argument. You need to 334 * call redraw() to update the screen 335 * 336 * @param l 337 * the y-coordinate to insert the line 338 * @param scrollDown 339 * scroll down 340 * @see #deleteLine 341 * @see #SCROLL_UP 342 * @see #SCROLL_DOWN 343 * @see #redraw 344 */ insertLine(int l, boolean scrollDown)345 public void insertLine(int l, boolean scrollDown) { 346 insertLine(l, 1, scrollDown); 347 } 348 349 /** 350 * Insert blank lines at a specific position. The current line and all previous lines are scrolled 351 * one line up. The top line is lost. You need to call redraw() to update the screen. 352 * 353 * @param l 354 * the y-coordinate to insert the line 355 * @param n 356 * number of lines to be inserted 357 * @param scrollDown 358 * scroll down 359 * @see #deleteLine 360 * @see #SCROLL_UP 361 * @see #SCROLL_DOWN 362 * @see #redraw 363 */ insertLine(int l, int n, boolean scrollDown)364 public synchronized void insertLine(int l, int n, boolean scrollDown) { 365 char cbuf[][] = null; 366 int abuf[][] = null; 367 int offset = 0; 368 int oldBase = screenBase; 369 370 int newScreenBase = screenBase; 371 int newWindowBase = windowBase; 372 int newBufSize = bufSize; 373 374 if (l > bottomMargin) { 375 return; 376 } 377 int top = 378 (l < topMargin ? 0 : (l > bottomMargin ? (bottomMargin + 1 < height ? bottomMargin + 1 379 : height - 1) : topMargin)); 380 int bottom = 381 (l > bottomMargin ? height - 1 : (l < topMargin ? (topMargin > 0 ? topMargin - 1 : 0) 382 : bottomMargin)); 383 384 // System.out.println("l is "+l+", top is "+top+", bottom is "+bottom+", bottomargin is "+bottomMargin+", topMargin is "+topMargin); 385 386 if (scrollDown) { 387 if (n > (bottom - top)) { 388 n = (bottom - top); 389 } 390 int size = bottom - l - (n - 1); 391 if (size < 0) { 392 size = 0; 393 } 394 cbuf = new char[size][]; 395 abuf = new int[size][]; 396 397 System.arraycopy(charArray, oldBase + l, cbuf, 0, bottom - l - (n - 1)); 398 System.arraycopy(charAttributes, oldBase + l, abuf, 0, bottom - l - (n - 1)); 399 System.arraycopy(cbuf, 0, charArray, oldBase + l + n, bottom - l - (n - 1)); 400 System.arraycopy(abuf, 0, charAttributes, oldBase + l + n, bottom - l - (n - 1)); 401 cbuf = charArray; 402 abuf = charAttributes; 403 } else { 404 try { 405 if (n > (bottom - top) + 1) { 406 n = (bottom - top) + 1; 407 } 408 if (bufSize < maxBufSize) { 409 if (bufSize + n > maxBufSize) { 410 offset = n - (maxBufSize - bufSize); 411 scrollMarker += offset; 412 newBufSize = maxBufSize; 413 newScreenBase = maxBufSize - height - 1; 414 newWindowBase = screenBase; 415 } else { 416 scrollMarker += n; 417 newScreenBase += n; 418 newWindowBase += n; 419 newBufSize += n; 420 } 421 422 cbuf = new char[newBufSize][]; 423 abuf = new int[newBufSize][]; 424 } else { 425 offset = n; 426 cbuf = charArray; 427 abuf = charAttributes; 428 } 429 // copy anything from the top of the buffer (+offset) to the new top 430 // up to the screenBase. 431 if (oldBase > 0) { 432 System.arraycopy(charArray, offset, cbuf, 0, oldBase - offset); 433 System.arraycopy(charAttributes, offset, abuf, 0, oldBase - offset); 434 } 435 // copy anything from the top of the screen (screenBase) up to the 436 // topMargin to the new screen 437 if (top > 0) { 438 System.arraycopy(charArray, oldBase, cbuf, newScreenBase, top); 439 System.arraycopy(charAttributes, oldBase, abuf, newScreenBase, top); 440 } 441 // copy anything from the topMargin up to the amount of lines inserted 442 // to the gap left over between scrollback buffer and screenBase 443 if (oldBase >= 0) { 444 System.arraycopy(charArray, oldBase + top, cbuf, oldBase - offset, n); 445 System.arraycopy(charAttributes, oldBase + top, abuf, oldBase - offset, n); 446 } 447 // copy anything from topMargin + n up to the line linserted to the 448 // topMargin 449 System 450 .arraycopy(charArray, oldBase + top + n, cbuf, newScreenBase + top, l - top - (n - 1)); 451 System.arraycopy(charAttributes, oldBase + top + n, abuf, newScreenBase + top, l - top 452 - (n - 1)); 453 // 454 // copy the all lines next to the inserted to the new buffer 455 if (l < height - 1) { 456 System.arraycopy(charArray, oldBase + l + 1, cbuf, newScreenBase + l + 1, (height - 1) 457 - l); 458 System.arraycopy(charAttributes, oldBase + l + 1, abuf, newScreenBase + l + 1, 459 (height - 1) - l); 460 } 461 } catch (ArrayIndexOutOfBoundsException e) { 462 // this should not happen anymore, but I will leave the code 463 // here in case something happens anyway. That code above is 464 // so complex I always have a hard time understanding what 465 // I did, even though there are comments 466 System.err.println("*** Error while scrolling up:"); 467 System.err.println("--- BEGIN STACK TRACE ---"); 468 e.printStackTrace(); 469 System.err.println("--- END STACK TRACE ---"); 470 System.err.println("bufSize=" + bufSize + ", maxBufSize=" + maxBufSize); 471 System.err.println("top=" + top + ", bottom=" + bottom); 472 System.err.println("n=" + n + ", l=" + l); 473 System.err.println("screenBase=" + screenBase + ", windowBase=" + windowBase); 474 System.err.println("newScreenBase=" + newScreenBase + ", newWindowBase=" + newWindowBase); 475 System.err.println("oldBase=" + oldBase); 476 System.err.println("size.width=" + width + ", size.height=" + height); 477 System.err.println("abuf.length=" + abuf.length + ", cbuf.length=" + cbuf.length); 478 System.err.println("*** done dumping debug information"); 479 } 480 } 481 482 // this is a little helper to mark the scrolling 483 scrollMarker -= n; 484 485 for (int i = 0; i < n; i++) { 486 cbuf[(newScreenBase + l) + (scrollDown ? i : -i)] = new char[width]; 487 Arrays.fill(cbuf[(newScreenBase + l) + (scrollDown ? i : -i)], ' '); 488 abuf[(newScreenBase + l) + (scrollDown ? i : -i)] = new int[width]; 489 } 490 491 charArray = cbuf; 492 charAttributes = abuf; 493 screenBase = newScreenBase; 494 windowBase = newWindowBase; 495 bufSize = newBufSize; 496 497 if (scrollDown) { 498 markLine(l, bottom - l + 1); 499 } else { 500 markLine(top, l - top + 1); 501 } 502 503 display.updateScrollBar(); 504 } 505 506 /** 507 * Delete a line at a specific position. Subsequent lines will be scrolled up to fill the space 508 * and a blank line is inserted at the end of the screen. 509 * 510 * @param l 511 * the y-coordinate to insert the line 512 * @see #deleteLine 513 */ deleteLine(int l)514 public void deleteLine(int l) { 515 int bottom = (l > bottomMargin ? height - 1 : (l < topMargin ? topMargin : bottomMargin + 1)); 516 int numRows = bottom - l - 1; 517 518 char[] discardedChars = charArray[screenBase + l]; 519 int[] discardedAttributes = charAttributes[screenBase + l]; 520 521 if (numRows > 0) { 522 System.arraycopy(charArray, screenBase + l + 1, charArray, screenBase + l, numRows); 523 System.arraycopy(charAttributes, screenBase + l + 1, charAttributes, screenBase + l, numRows); 524 } 525 526 int newBottomRow = screenBase + bottom - 1; 527 charArray[newBottomRow] = discardedChars; 528 charAttributes[newBottomRow] = discardedAttributes; 529 Arrays.fill(charArray[newBottomRow], ' '); 530 Arrays.fill(charAttributes[newBottomRow], 0); 531 532 markLine(l, bottom - l); 533 } 534 535 /** 536 * Delete a rectangular portion of the screen. You need to call redraw() to update the screen. 537 * 538 * @param c 539 * x-coordinate (column) 540 * @param l 541 * y-coordinate (row) 542 * @param w 543 * with of the area in characters 544 * @param h 545 * height of the area in characters 546 * @param curAttr 547 * attribute to fill 548 * @see #deleteChar 549 * @see #deleteLine 550 * @see #redraw 551 */ deleteArea(int c, int l, int w, int h, int curAttr)552 public void deleteArea(int c, int l, int w, int h, int curAttr) { 553 int endColumn = c + w; 554 int targetRow = screenBase + l; 555 for (int i = 0; i < h && l + i < height; i++) { 556 Arrays.fill(charAttributes[targetRow], c, endColumn, curAttr); 557 Arrays.fill(charArray[targetRow], c, endColumn, ' '); 558 targetRow++; 559 } 560 markLine(l, h); 561 } 562 563 /** 564 * Delete a rectangular portion of the screen. You need to call redraw() to update the screen. 565 * 566 * @param c 567 * x-coordinate (column) 568 * @param l 569 * y-coordinate (row) 570 * @param w 571 * with of the area in characters 572 * @param h 573 * height of the area in characters 574 * @see #deleteChar 575 * @see #deleteLine 576 * @see #redraw 577 */ deleteArea(int c, int l, int w, int h)578 public void deleteArea(int c, int l, int w, int h) { 579 deleteArea(c, l, w, h, 0); 580 } 581 582 /** 583 * Sets whether the cursor is visible or not. 584 * 585 * @param doshow 586 */ showCursor(boolean doshow)587 public void showCursor(boolean doshow) { 588 showcursor = doshow; 589 } 590 591 /** 592 * Check whether the cursor is currently visible. 593 * 594 * @return visibility 595 */ isCursorVisible()596 public boolean isCursorVisible() { 597 return showcursor; 598 } 599 600 /** 601 * Puts the cursor at the specified position. 602 * 603 * @param c 604 * column 605 * @param l 606 * line 607 */ setCursorPosition(int c, int l)608 public void setCursorPosition(int c, int l) { 609 cursorX = c; 610 cursorY = l; 611 } 612 613 /** 614 * Get the current column of the cursor position. 615 */ getCursorColumn()616 public int getCursorColumn() { 617 return cursorX; 618 } 619 620 /** 621 * Get the current line of the cursor position. 622 */ getCursorRow()623 public int getCursorRow() { 624 return cursorY; 625 } 626 627 /** 628 * Set the current window base. This allows to view the scrollback buffer. 629 * 630 * @param line 631 * the line where the screen window starts 632 * @see #setBufferSize 633 * @see #getBufferSize 634 */ setWindowBase(int line)635 public void setWindowBase(int line) { 636 if (line > screenBase) { 637 line = screenBase; 638 } else if (line < 0) { 639 line = 0; 640 } 641 windowBase = line; 642 update[0] = true; 643 redraw(); 644 } 645 646 /** 647 * Get the current window base. 648 * 649 * @see #setWindowBase 650 */ getWindowBase()651 public int getWindowBase() { 652 return windowBase; 653 } 654 655 /** 656 * Set the scroll margins simultaneously. If they're out of bounds, trim them. 657 * 658 * @param l1 659 * line that is the top 660 * @param l2 661 * line that is the bottom 662 */ setMargins(int l1, int l2)663 public void setMargins(int l1, int l2) { 664 if (l1 > l2) { 665 return; 666 } 667 668 if (l1 < 0) { 669 l1 = 0; 670 } 671 if (l2 >= height) { 672 l2 = height - 1; 673 } 674 675 topMargin = l1; 676 bottomMargin = l2; 677 } 678 679 /** 680 * Set the top scroll margin for the screen. If the current bottom margin is smaller it will 681 * become the top margin and the line will become the bottom margin. 682 * 683 * @param l 684 * line that is the margin 685 */ setTopMargin(int l)686 public void setTopMargin(int l) { 687 if (l > bottomMargin) { 688 topMargin = bottomMargin; 689 bottomMargin = l; 690 } else { 691 topMargin = l; 692 } 693 if (topMargin < 0) { 694 topMargin = 0; 695 } 696 if (bottomMargin >= height) { 697 bottomMargin = height - 1; 698 } 699 } 700 701 /** 702 * Get the top scroll margin. 703 */ getTopMargin()704 public int getTopMargin() { 705 return topMargin; 706 } 707 708 /** 709 * Set the bottom scroll margin for the screen. If the current top margin is bigger it will become 710 * the bottom margin and the line will become the top margin. 711 * 712 * @param l 713 * line that is the margin 714 */ setBottomMargin(int l)715 public void setBottomMargin(int l) { 716 if (l < topMargin) { 717 bottomMargin = topMargin; 718 topMargin = l; 719 } else { 720 bottomMargin = l; 721 } 722 if (topMargin < 0) { 723 topMargin = 0; 724 } 725 if (bottomMargin >= height) { 726 bottomMargin = height - 1; 727 } 728 } 729 730 /** 731 * Get the bottom scroll margin. 732 */ getBottomMargin()733 public int getBottomMargin() { 734 return bottomMargin; 735 } 736 737 /** 738 * Set scrollback buffer size. 739 * 740 * @param amount 741 * new size of the buffer 742 */ setBufferSize(int amount)743 public void setBufferSize(int amount) { 744 if (amount < height) { 745 amount = height; 746 } 747 if (amount < maxBufSize) { 748 char cbuf[][] = new char[amount][width]; 749 int abuf[][] = new int[amount][width]; 750 int copyStart = bufSize - amount < 0 ? 0 : bufSize - amount; 751 int copyCount = bufSize - amount < 0 ? bufSize : amount; 752 if (charArray != null) { 753 System.arraycopy(charArray, copyStart, cbuf, 0, copyCount); 754 } 755 if (charAttributes != null) { 756 System.arraycopy(charAttributes, copyStart, abuf, 0, copyCount); 757 } 758 charArray = cbuf; 759 charAttributes = abuf; 760 bufSize = copyCount; 761 screenBase = bufSize - height; 762 windowBase = screenBase; 763 } 764 maxBufSize = amount; 765 766 update[0] = true; 767 redraw(); 768 } 769 770 /** 771 * Retrieve current scrollback buffer size. 772 * 773 * @see #setBufferSize 774 */ 775 public int getBufferSize() { 776 return bufSize; 777 } 778 779 /** 780 * Retrieve maximum buffer Size. 781 * 782 * @see #getBufferSize 783 */ 784 public int getMaxBufferSize() { 785 return maxBufSize; 786 } 787 788 /** 789 * Change the size of the screen. This will include adjustment of the scrollback buffer. 790 * 791 * @param w 792 * of the screen 793 * @param h 794 * of the screen 795 */ 796 @SuppressWarnings("unused") 797 public void setScreenSize(int w, int h, boolean broadcast) { 798 char cbuf[][]; 799 int abuf[][]; 800 int maxSize = bufSize; 801 802 if (w < 1 || h < 1) { 803 return; 804 } 805 806 if (debug > 0) { 807 System.err.println("VDU: screen size [" + w + "," + h + "]"); 808 } 809 810 if (h > maxBufSize) { 811 maxBufSize = h; 812 } 813 814 if (h > bufSize) { 815 bufSize = h; 816 screenBase = 0; 817 windowBase = 0; 818 } 819 820 if (windowBase + h >= bufSize) { 821 windowBase = bufSize - h; 822 } 823 824 if (screenBase + h >= bufSize) { 825 screenBase = bufSize - h; 826 } 827 828 cbuf = new char[bufSize][w]; 829 abuf = new int[bufSize][w]; 830 831 for (int i = 0; i < bufSize; i++) { 832 Arrays.fill(cbuf[i], ' '); 833 } 834 835 if (bufSize < maxSize) { 836 maxSize = bufSize; 837 } 838 839 int rowLength; 840 if (charArray != null && charAttributes != null) { 841 for (int i = 0; i < maxSize && charArray[i] != null; i++) { 842 rowLength = charArray[i].length; 843 System.arraycopy(charArray[i], 0, cbuf[i], 0, w < rowLength ? w : rowLength); 844 System.arraycopy(charAttributes[i], 0, abuf[i], 0, w < rowLength ? w : rowLength); 845 } 846 } 847 848 int C = getCursorColumn(); 849 if (C < 0) { 850 C = 0; 851 } else if (C >= width) { 852 C = width - 1; 853 } 854 855 int R = getCursorRow(); 856 if (R < 0) { 857 R = 0; 858 } else if (R >= height) { 859 R = height - 1; 860 } 861 862 setCursorPosition(C, R); 863 864 charArray = cbuf; 865 charAttributes = abuf; 866 width = w; 867 height = h; 868 topMargin = 0; 869 bottomMargin = h - 1; 870 update = new boolean[h + 1]; 871 update[0] = true; 872 /* 873 * FIXME: ??? if(resizeStrategy == RESIZE_FONT) setBounds(getBounds()); 874 */ 875 } 876 877 /** 878 * Get amount of rows on the screen. 879 */ getRows()880 public int getRows() { 881 return height; 882 } 883 884 /** 885 * Get amount of columns on the screen. 886 */ getColumns()887 public int getColumns() { 888 return width; 889 } 890 891 /** 892 * Mark lines to be updated with redraw(). 893 * 894 * @param l 895 * starting line 896 * @param n 897 * amount of lines to be updated 898 * @see #redraw 899 */ markLine(int l, int n)900 public void markLine(int l, int n) { 901 for (int i = 0; (i < n) && (l + i < height); i++) { 902 update[l + i + 1] = true; 903 } 904 } 905 906 // private static int checkBounds(int value, int lower, int upper) { 907 // if (value < lower) 908 // return lower; 909 // else if (value > upper) 910 // return upper; 911 // else 912 // return value; 913 // } 914 915 /** a generic display that should redraw on demand */ 916 protected VDUDisplay display; 917 setDisplay(VDUDisplay display)918 public void setDisplay(VDUDisplay display) { 919 this.display = display; 920 } 921 922 /** 923 * Trigger a redraw on the display. 924 */ redraw()925 protected void redraw() { 926 if (display != null) { 927 display.redraw(); 928 } 929 } 930 } 931