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