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