1 package de.mud.telnet.display;
2 /* "In case you would like to use the packages as libraries please
3 * apply the GNU Library General Public License as documented in the
4 * file COPYING.LIB." (from Telnet/Documentation/index.html)
7 * CharDisplay -- a simple character display
9 * $Id: CharDisplay.java,v 1.27 1998/03/18 12:43:33 leo Exp $
10 * $timestamp: Thu Jul 24 15:19:18 1997 by Matthias L. Jugel :$
12 * This file is part of "The Java Telnet Applet".
14 * This is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
19 * "The Java Telnet Applet" is distributed in the hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this software; see the file COPYING. If not, write to the
26 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 * Boston, MA 02111-1307, USA.
30 import java.awt.Graphics;
31 import java.awt.Panel;
32 import java.awt.Color;
33 import java.awt.Dimension;
35 import java.awt.FontMetrics;
36 import java.awt.Point;
37 import java.awt.Insets;
38 import java.awt.Event;
39 import java.awt.TextArea;
40 import java.awt.Label;
41 import java.awt.Frame;
42 import java.awt.Scrollbar;
43 import java.awt.Rectangle;
46 * A simple character display.
47 * @version $Id: CharDisplay.java,v 1.27 1998/03/18 12:43:33 leo Exp $
48 * @author Matthias L. Jugel, Marcus Meißner
50 public class CharDisplay extends Panel
53 * If you need the runtime version, just ask this variable.
55 public String version = "$Revision: 1.27 $ $Date: 1998/03/18 12:43:33 $";
57 * Enable debug messages. This is final static to prevent unused
58 * code to be compiled.
60 public final static int debug = 0;
62 private Dimension size; /* rows and columns */
63 private Insets insets; /* size of the border */
64 private boolean raised; /* indicator if the border is raised */
66 private char charArray[][]; /* contains the characters */
67 private int charAttributes[][]; /* contains character attrs */
68 private int bufSize, maxBufSize; /* buffer sizes */
70 private int windowBase; /* where the start displaying */
71 private int screenBase; /* the actual screen start */
72 private int topMargin; /* top scroll margon */
73 private int bottomMargin; /* bottom scroll margon */
74 private Scrollbar scrollBar; /* the scroll bar */
75 private String scrBarPos; /* the scroll bar position */
77 private Font normalFont; /* normal font */
78 private FontMetrics fm; /* current font metrics */
79 private int charWidth; /* current width of a char */
80 private int charHeight; /* current height of a char */
81 private int charDescent; /* base line descent */
82 private int resizeStrategy; /* current resizing strategy */
84 private int cursorX, cursorY; /* current cursor position */
85 private Point selectBegin, selectEnd; /* selection coordinates */
86 private TextArea selection;
87 private Frame selectFrame;
89 private de.mud.telnet.display.SoftFont sf = new de.mud.telnet.display.SoftFont();
91 private boolean screenLocked = false; /* screen needs to be locked */
92 /* because of paint requests */
93 /* during other operations */
94 private boolean update[];
96 private Color color[] = { Color.black.brighter(),
98 Color.green.brighter(),
99 Color.yellow.brighter(),
100 Color.blue.brighter(),
101 Color.magenta.brighter(),
102 Color.cyan.brighter(),
103 Color.white.brighter(),
105 private final static int COLOR_FG_STD = 7;
106 private final static int COLOR_BG_STD = 0;
107 private final static int COLOR = 0x7f8;
108 private final static int COLOR_FG = 0x78;
109 private final static int COLOR_BG = 0x780;
112 * Scroll up when inserting a line.
114 public final static boolean SCROLL_UP = false;
116 * Scroll down when inserting a line.
118 public final static boolean SCROLL_DOWN = true;
121 * Do nothing when the container is resized.
123 public final static int RESIZE_NONE = 0;
125 * Resize the width and height of the characterscreen.
127 public final static int RESIZE_SCREEN = 1;
129 * Resize the font to the new screensize.
131 public final static int RESIZE_FONT = 2;
134 * Make character normal.
136 public final static int NORMAL = 0x00;
138 * Make character bold.
140 public final static int BOLD = 0x01;
142 * Underline character.
144 public final static int UNDERLINE = 0x02;
148 public final static int INVERT = 0x04;
150 private void InitializeCharDisplay(int width, int height,
151 String fontname, int fsize)
153 System.err.println("CharDisplay: screen size: ["+width+","+height+"]");
154 normalFont = new Font(fontname, Font.BOLD, fsize);
156 fm = getFontMetrics(normalFont);
159 charWidth = fm.charWidth('@');
160 charHeight = fm.getHeight();
161 charDescent = fm.getDescent();
164 resizeStrategy = RESIZE_FONT;
165 size = new Dimension(width, height);
166 charArray = new char[size.height][size.width];
167 charAttributes = new int[size.height][size.width];
168 bufSize = size.height;
169 maxBufSize = 2 * size.height;
174 bottomMargin = size.height - 1;
176 update = new boolean[size.height + 1];
177 for(int i = 1; i <= size.height; i++) update[i] = true;
179 selectBegin = new Point(0,0);
180 selectEnd = new Point(0,0);
186 * Create a character display with size 80x24 and Font "Courier", size 12.
190 InitializeCharDisplay(80, 24, "Courier", 12);
194 * Create a character display with specific size, Font is "Courier", size 12.
196 public CharDisplay(int width, int height)
198 InitializeCharDisplay(width, height, "Courier", 12);
202 * Create a character display with 80x24 and specific font and font size.
204 public CharDisplay(String fname, int fsize)
206 InitializeCharDisplay(80, 24, fname, fsize);
210 * Create a character display with specific size, font and font size.
212 public CharDisplay(int width, int height, String fname, int fsize)
214 InitializeCharDisplay(width, height, fname, fsize);
218 * Put a character on the screen with normal font and outline.
219 * The character previously on that position will be overwritten.
220 * You need to call redraw() to update the screen.
221 * @param c x-coordinate (column)
222 * @param l y-coordinate (line)
223 * @param ch the character to show on the screen
228 public void putChar(int c, int l, char ch)
230 putChar(c, l, ch, NORMAL);
234 * Put a character on the screen with specific font and outline.
235 * The character previously on that position will be overwritten.
236 * You need to call redraw() to update the screen.
237 * @param c x-coordinate (column)
238 * @param l y-coordinate (line)
239 * @param ch the character to show on the screen
240 * @param attributes the character attributes
250 public void putChar(int c, int l, char ch, int attributes)
252 c = checkBounds(c, 0, size.width - 1);
253 l = checkBounds(l, 0, size.height - 1);
254 charArray[screenBase + l][c] = ch;
255 charAttributes[screenBase + l][c] = attributes;
260 * Get the character at the specified position.
261 * @param c x-coordinate (column)
262 * @param l y-coordinate (line)
265 public char getChar(int c, int l)
267 c = checkBounds(c, 0, size.width - 1);
268 l = checkBounds(l, 0, size.height - 1);
269 return charArray[l][c];
273 * Get the attributes for the specified position.
274 * @param c x-coordinate (column)
275 * @param l y-coordinate (line)
278 public int getAttributes(int c, int l)
280 c = checkBounds(c, 0, size.width - 1);
281 l = checkBounds(l, 0, size.height - 1);
282 return charAttributes[l][c];
286 * Insert a character at a specific position on the screen.
287 * All character right to from this position will be moved one to the right.
288 * You need to call redraw() to update the screen.
289 * @param c x-coordinate (column)
290 * @param l y-coordinate (line)
291 * @param ch the character to insert
292 * @param attributes the character attributes
301 public void insertChar(int c, int l, char ch, int attributes)
303 c = checkBounds(c, 0, size.width - 1);
304 l = checkBounds(l, 0, size.height - 1);
305 System.arraycopy(charArray[screenBase + l], c,
306 charArray[screenBase + l], c + 1, size.width - c - 1);
307 System.arraycopy(charAttributes[screenBase + l], c,
308 charAttributes[screenBase + l], c + 1, size.width - c - 1);
309 putChar(c, l, ch, attributes);
313 * Delete a character at a given position on the screen.
314 * All characters right to the position will be moved one to the left.
315 * You need to call redraw() to update the screen.
316 * @param c x-coordinate (column)
317 * @param l y-coordinate (line)
322 public void deleteChar(int c, int l)
324 c = checkBounds(c, 0, size.width - 1);
325 l = checkBounds(l, 0, size.height - 1);
326 if(c < size.width - 1)
328 System.arraycopy(charArray[screenBase + l], c + 1,
329 charArray[screenBase + l], c, size.width - c - 1);
330 System.arraycopy(charAttributes[screenBase + l], c + 1,
331 charAttributes[screenBase + l], c, size.width - c - 1);
333 putChar(size.width - 1, l, (char)0);
337 * Put a String at a specific position. Any characters previously on that
338 * position will be overwritten. You need to call redraw() for screen update.
339 * @param c x-coordinate (column)
340 * @param l y-coordinate (line)
341 * @param s the string to be shown on the screen
351 public void putString(int c, int l, String s)
353 putString(c, l, s, NORMAL);
357 * Put a String at a specific position giving all characters the same
358 * attributes. Any characters previously on that position will be
359 * overwritten. You need to call redraw() to update the screen.
360 * @param c x-coordinate (column)
361 * @param l y-coordinate (line)
362 * @param s the string to be shown on the screen
363 * @param attributes character attributes
373 public void putString(int c, int l, String s, int attributes)
375 for(int i = 0; i < s.length() && c + i < size.width; i++)
376 putChar(c + i, l, s.charAt(i), attributes);
380 * Insert a blank line at a specific position.
381 * The current line and all previous lines are scrolled one line up. The
382 * top line is lost. You need to call redraw() to update the screen.
383 * @param l the y-coordinate to insert the line
387 public void insertLine(int l)
389 insertLine(l, 1, SCROLL_UP);
393 * Insert blank lines at a specific position.
394 * You need to call redraw() to update the screen
395 * @param l the y-coordinate to insert the line
396 * @param n amount of lines to be inserted
400 public void insertLine(int l, int n)
402 insertLine(l, n, SCROLL_UP);
406 * Insert a blank line at a specific position. Scroll text according to
408 * You need to call redraw() to update the screen
409 * @param l the y-coordinate to insert the line
410 * @param scrollDown scroll down
416 public void insertLine(int l, boolean scrollDown)
418 insertLine(l, 1, scrollDown);
422 * Insert blank lines at a specific position.
423 * The current line and all previous lines are scrolled one line up. The
424 * top line is lost. You need to call redraw() to update the screen.
425 * @param l the y-coordinate to insert the line
426 * @param n number of lines to be inserted
427 * @param scrollDown scroll down
433 public synchronized void insertLine(int l, int n, boolean scrollDown)
437 l = checkBounds(l, 0, size.height - 1);
439 char cbuf[][] = null;
442 int oldBase = screenBase;
443 int top = (l < topMargin ?
444 0 : (l > bottomMargin ?
445 (bottomMargin + 1 < size.height ?
446 bottomMargin + 1 : size.height - 1) : topMargin));
447 int bottom = (l > bottomMargin ?
448 size.height - 1 : (l < topMargin ?
450 topMargin - 1 : 0) : bottomMargin));
454 if(n > (bottom - top)) n = (bottom - top);
455 cbuf = new char[bottom - l - (n - 1)][size.width];
456 abuf = new int[bottom - l - (n - 1)][size.width];
458 System.arraycopy(charArray, oldBase + l, cbuf, 0, bottom - l - (n - 1));
459 System.arraycopy(charAttributes, oldBase + l,
460 abuf, 0, bottom - l - (n - 1));
461 System.arraycopy(cbuf, 0, charArray, oldBase + l + n,
462 bottom - l - (n - 1));
463 System.arraycopy(abuf, 0, charAttributes, oldBase + l + n,
464 bottom - l - (n - 1));
466 abuf = charAttributes;
468 if(n > (bottom - top) + 1) n = (bottom - top) + 1;
469 if(bufSize < maxBufSize) {
470 if(bufSize + n > maxBufSize) {
471 offset = n - (maxBufSize - bufSize);
472 bufSize = maxBufSize;
473 screenBase = maxBufSize - size.height - 1;
474 windowBase = screenBase;
480 cbuf = new char[bufSize][size.width];
481 abuf = new int[bufSize][size.width];
485 abuf = charAttributes;
488 * copy anything from the top of the buffer (+offset) to the new top
489 * up to the screenBase.
493 System.arraycopy(charArray, offset,
496 System.arraycopy(charAttributes, offset,
501 * copy anything from the top of the screen (screenBase) up to the
502 * topMargin to the new screen
506 System.arraycopy(charArray, oldBase,
509 System.arraycopy(charAttributes, oldBase,
514 * copy anything from the topMargin up to the amount of lines inserted
515 * to the gap left over between scrollback buffer and screenBase
518 System.arraycopy(charArray, oldBase + top,
519 cbuf, oldBase - offset,
521 System.arraycopy(charAttributes, oldBase + top,
522 abuf, oldBase - offset,
526 * copy anything from topMargin + n up to the line linserted to the
529 System.arraycopy(charArray, oldBase + top + n,
530 cbuf, screenBase + top,
532 System.arraycopy(charAttributes, oldBase + top + n,
533 abuf, screenBase + top,
536 * copy the all lines next to the inserted to the new buffer
538 if(l < size.height - 1)
540 System.arraycopy(charArray, oldBase + l + 1,
541 cbuf, screenBase + l + 1,
542 (size.height - 1) - l);
543 System.arraycopy(charAttributes, oldBase + l + 1,
544 abuf, screenBase + l + 1,
545 (size.height - 1) - l);
547 } catch(ArrayIndexOutOfBoundsException e) {
548 System.err.println("*** Error while scrolling up:");
549 System.err.println("--- BEGIN STACKTRACE ---");
551 System.err.println("--- END STACKTRACE ---");
552 System.err.println("bufSize="+bufSize+", maxBufSize="+maxBufSize);
553 System.err.println("top="+top+", bottom="+bottom);
554 System.err.println("n="+n+", l="+l);
555 System.err.println("screenBase="+screenBase+", windowBase="+windowBase);
556 System.err.println("oldBase="+oldBase);
557 System.err.println("size.width="+size.width+", size.height="+size.height);
558 System.err.println("abuf.length="+abuf.length+", cbuf.length="+cbuf.length);
559 System.err.println("*** done dumping debug information");
562 for(int i = 0; i < n; i++)
564 cbuf[(screenBase + l) + (scrollDown ? i : -i) ] = new char[size.width];
565 abuf[(screenBase + l) + (scrollDown ? i : -i) ] = new int[size.width];
569 charAttributes = abuf;
572 markLine(l, bottom - l + 1);
574 markLine(top, l - top + 1);
576 if(scrollBar != null)
577 scrollBar.setValues(windowBase, size.height, 0, bufSize);
579 screenLocked = false;
583 * Delete a line at a specific position. Subsequent lines will be scrolled
584 * up to fill the space and a blank line is inserted at the end of the
586 * @param l the y-coordinate to insert the line
589 public void deleteLine(int l)
591 l = checkBounds(l, 0, size.height - 1);
593 int bottom = (l>bottomMargin?size.height-1:
594 (l<topMargin?topMargin:bottomMargin+1));
595 System.arraycopy(charArray, screenBase + l + 1,
596 charArray, screenBase + l, bottom - l -1 );
597 System.arraycopy(charAttributes, screenBase + l + 1,
598 charAttributes, screenBase + l, bottom - l -1);
599 charArray[screenBase + bottom - 1] = new char[size.width];
600 charAttributes[screenBase + bottom - 1] = new int[size.width];
601 markLine(l, bottom - l);
606 * Delete a rectangular portion of the screen.
607 * You need to call redraw() to update the screen.
608 * @param c x-coordinate (column)
609 * @param l y-coordinate (row)
610 * @param w with of the area in characters
611 * @param h height of the area in characters
616 public void deleteArea(int c, int l, int w, int h)
618 c = checkBounds(c, 0, size.width - 1);
619 l = checkBounds(l, 0, size.height - 1);
621 char cbuf[] = new char[w];
622 int abuf[] = new int[w];
624 for(int i = 0; i < h && l + i < size.height; i++)
626 System.arraycopy(cbuf, 0, charArray[screenBase + l + i], c, w);
627 System.arraycopy(abuf, 0, charAttributes[screenBase + l + i], c, w);
633 * Puts the cursor at the specified position.
637 public void setCursorPos(int c, int l)
639 c = checkBounds(c, 0, size.width - 1);
640 l = checkBounds(l, 0, size.height - 1);
641 markLine(cursorY, 1);
642 cursorX = (c < size.width ? c : size.width);
643 cursorY = (l < size.height ? l : size.height);
648 * Get the current cursor position.
649 * @see java.awt.Dimension
651 public Dimension getCursorPos()
653 return new Dimension(cursorX, cursorY);
657 * Set the top scroll margin for the screen. If the current bottom margin
658 * is smaller it will become the top margin and the line will become the
660 * @param l line that is the margin
662 public void setTopMargin(int l)
666 topMargin = bottomMargin;
671 if(topMargin < 0) topMargin = 0;
672 if(bottomMargin > size.height - 1) bottomMargin = size.height - 1;
676 * Get the top scroll margin.
678 public int getTopMargin()
684 * Set the bottom scroll margin for the screen. If the current top margin
685 * is bigger it will become the bottom margin and the line will become the
687 * @param l line that is the margin
689 public void setBottomMargin(int l)
693 bottomMargin = topMargin;
698 if(topMargin < 0) topMargin = 0;
699 if(bottomMargin > size.height - 1) bottomMargin = size.height - 1;
703 * Get the bottom scroll margin.
705 public int getBottomMargin()
711 * Set scrollback buffer size.
712 * @param amount new size of the buffer
714 public void setBufferSize(int amount)
718 if(amount < size.height) amount = size.height;
719 if(amount < maxBufSize)
721 char cbuf[][] = new char[amount][size.width];
722 int abuf[][] = new int[amount][size.width];
723 System.arraycopy(charArray, bufSize - amount, cbuf, 0, amount);
724 System.arraycopy(charAttributes, bufSize - amount, abuf, 0, amount);
726 charAttributes = abuf;
730 screenLocked = false;
736 * Retrieve current scrollback buffer size.
737 * @see #setBufferSize
739 public int getBufferSize()
745 * Retrieve maximum buffer Size.
746 * @see #getBufferSize
748 public int getMaxBufferSize()
754 * Set the current window base. This allows to view the scrollback buffer.
755 * @param line the line where the screen window starts
759 public void setWindowBase(int line)
761 if(line > screenBase) line = screenBase;
762 else if(line < 0) line = 0;
768 * Get the current window base.
771 public int getWindowBase()
777 * Change the size of the screen. This will include adjustment of the
779 * @param columns width of the screen
780 * @param columns height of the screen
782 public void setWindowSize(int width, int height)
788 if(width < 1 || height < 1) return;
792 super.update(getGraphics());
794 if(height > maxBufSize)
803 cbuf = new char[bufSize][width];
804 abuf = new int[bufSize][width];
806 for(int i = 0; i < bsize && i < bufSize; i++)
808 System.arraycopy(charArray[i], 0, cbuf[i], 0,
809 width < size.width ? width : size.width);
810 System.arraycopy(charAttributes[i], 0, abuf[i], 0,
811 width < size.width ? width : size.width);
814 charAttributes = abuf;
815 size = new Dimension(width, height);
817 bottomMargin = height - 1;
818 update = new boolean[height + 1];
819 for(int i = 0; i <= height; i++) update[i] = true;
820 screenLocked = false;
824 * Set the strategy when window is resized.
825 * RESIZE_FONT is default.
826 * @param strategy the strategy
829 * @see #RESIZE_SCREEN
831 public void setResizeStrategy(int strategy)
833 resizeStrategy = strategy;
837 * Get amount of rows on the screen.
839 public int getRows() { return size.height; }
842 * Get amount of columns on the screen.
844 public int getColumns() { return size.width; }
847 * Set the border thickness and the border type.
848 * @param thickness border thickness in pixels, zero means no border
849 * @param raised a boolean indicating a raised or embossed border
851 public void setBorder(int thickness, boolean raised)
853 if(thickness == 0) insets = null;
854 else insets = new Insets(thickness+1, thickness+1,
855 thickness+1, thickness+1);
856 this.raised = raised;
860 * Set the scrollbar position. valid values are "East" or "West".
861 * @param position the position of the scrollbar
863 public void setScrollbar(String position)
865 add(scrollBar = new Scrollbar());
866 scrollBar.setValues(windowBase, size.height, 0, bufSize - size.height);
867 scrBarPos = position;
871 * Mark lines to be updated with redraw().
872 * @param l starting line
873 * @param n amount of lines to be updated
876 public void markLine(int l, int n)
878 l = checkBounds(l, 0, size.height - 1);
879 for(int i = 0; i < n && l + i < size.height; i++)
880 update[l + i + 1] = true;
884 * Redraw marked lines.
894 * Update the display. to reduce flashing we have overridden this method.
896 public void update(Graphics g)
902 * Paint the current screen. All painting is done here. Only lines that have
903 * changed will be redrawn!
905 public synchronized void paint(Graphics g)
907 if(screenLocked) return;
908 int xoffset = (super.size().width - size.width * charWidth -
909 (scrollBar != null ? 15 : 0)) / 2;
910 int yoffset = (super.size().height - size.height * charHeight) / 2;
912 Color fg = color[COLOR_FG_STD];
913 Color bg = color[COLOR_BG_STD];
915 if(scrollBar != null && scrBarPos.equals("West")) xoffset += 15;
917 g.setFont(normalFont);
919 for(int l = 0; l < size.height; l++)
921 if(update[0] && !update[l + 1]) continue;
922 update[l + 1] = false;
923 for(int c = 0; c < size.width; c++)
926 int currAttr = charAttributes[windowBase + l][c];
928 fg = color[COLOR_FG_STD];
929 bg = color[COLOR_BG_STD];
930 if ((currAttr & COLOR_FG) != 0) {
931 fg = color[((currAttr & COLOR_FG) >> 3)-1];
933 if ((currAttr & COLOR_BG) != 0) {
934 bg = color[((currAttr & COLOR_BG) >> 7)-1];
937 if((currAttr & BOLD) != 0) {
938 if(fg.equals(Color.black))
940 else fg = fg.darker();
942 if((currAttr & INVERT) != 0) { Color swapc = bg; bg=fg;fg=swapc; }
944 if (sf.inSoftFont(charArray[windowBase + l][c])) {
946 g.fillRect(c * charWidth + xoffset, l * charHeight + yoffset,
947 charWidth, charHeight);
949 sf.drawChar(g,charArray[windowBase + l][c],xoffset+c*charWidth,
950 l*charHeight+yoffset, charWidth, charHeight);
954 // determine the maximum of characters we can print in one go
955 while(c + addr < size.width &&
956 charAttributes[windowBase + l][c + addr] == currAttr &&
957 !sf.inSoftFont(charArray[windowBase + l ][c+addr])
959 if(charArray[windowBase + l][c + addr] < ' ')
960 charArray[windowBase + l][c + addr] = ' ';
964 // clear the part of the screen we want to change (fill rectangle)
966 g.fillRect(c * charWidth + xoffset, l * charHeight + yoffset,
967 addr * charWidth, charHeight);
971 // draw the characters
972 g.drawChars(charArray[windowBase + l], c, addr,
973 c * charWidth + xoffset,
974 (l+1) * charHeight - charDescent + yoffset);
976 if((currAttr & UNDERLINE) != 0)
977 g.drawLine(c * charWidth + 1 + xoffset,
978 (l+1) * charHeight - charDescent / 2 + yoffset,
979 c * charWidth + addr * charWidth + xoffset,
980 (l+1) * charHeight - charDescent / 2 + yoffset);
987 if(screenBase + cursorY >= windowBase &&
988 screenBase + cursorY < windowBase + size.height)
990 g.setColor(color[COLOR_FG_STD]);
991 g.setXORMode(color[COLOR_BG_STD]);
992 g.fillRect( cursorX * charWidth + xoffset,
993 (cursorY + screenBase - windowBase) * charHeight + yoffset,
994 charWidth, charHeight);
998 if(windowBase <= selectBegin.y || windowBase <= selectEnd.y) {
999 int beginLine = selectBegin.y - windowBase;
1000 int endLine = selectEnd.y - selectBegin.y;
1002 endLine += beginLine;
1005 if(endLine > size.height) endLine = size.height - beginLine;
1007 g.setXORMode(color[COLOR_BG_STD]);
1008 g.fillRect(selectBegin.x * charWidth + xoffset,
1009 beginLine * charHeight + yoffset,
1010 (endLine == 0 ? (selectEnd.x - selectBegin.x) :
1011 (size.width - selectBegin.x))
1015 g.fillRect(0 + xoffset,
1016 (beginLine + 1) * charHeight + yoffset,
1017 size.width * charWidth,
1018 (endLine - 1) * charHeight);
1020 g.fillRect(0 + xoffset,
1021 (beginLine + endLine) * charHeight + yoffset,
1022 selectEnd.x * charWidth,
1027 if(insets != null) {
1028 g.setColor(getBackground());
1029 xoffset--; yoffset--;
1030 for(int i = insets.top - 1; i >= 0; i--)
1031 g.draw3DRect(xoffset - i, yoffset - i,
1032 charWidth * size.width + 1 + i * 2,
1033 charHeight * size.height + 1 + i * 2,
1040 private int checkBounds(int value, int lower, int upper)
1042 if(value < lower) return lower;
1043 if(value > upper) return upper;
1048 * Reshape character display according to resize strategy.
1049 * @see #setResizeStrategy
1051 public void reshape(int x, int y, int w, int h)
1054 System.err.println("CharDisplay: reshape("+x+","+y+","+w+","+h+")");
1056 int xborder = 0, yborder = 0;
1058 if(insets != null) {
1059 w -= (xborder = insets.left + insets.right);
1060 h -= (yborder = insets.top + insets.bottom);
1062 if(scrollBar != null) { w -= 15;}
1064 Font tmpFont = normalFont;
1065 String fontName = normalFont.getName();
1066 fm = getFontMetrics(normalFont);
1069 charWidth = fm.charWidth('@');
1070 charHeight = fm.getHeight();
1073 switch(resizeStrategy)
1076 setWindowSize(w / charWidth, size.height = h / charHeight);
1079 int height = h / size.height;
1080 int width = w / size.width;
1082 fm = getFontMetrics(normalFont = new Font(fontName, Font.PLAIN,
1085 // adapt current font size (from small up to best fit)
1086 if(fm.getHeight() < height || fm.charWidth('@') < width)
1088 fm = getFontMetrics(normalFont = new Font(fontName, Font.PLAIN,
1090 } while(fm.getHeight() < height ||
1091 fm.charWidth('@') < width);
1093 // now check if we got a font that is too large
1094 if(fm.getHeight() > height || fm.charWidth('@') > width)
1096 fm = getFontMetrics(normalFont = new Font(fontName, Font.PLAIN,
1098 } while(charHeight > 1 &&
1099 (fm.getHeight() > height ||
1100 fm.charWidth('@') > width));
1104 System.err.println("CharDisplay: error during resize, resetting");
1105 normalFont = tmpFont;
1106 System.err.println("CharDisplay: disabling font/screen resize");
1107 resizeStrategy = RESIZE_NONE;
1110 setFont(normalFont);
1111 fm = getFontMetrics(normalFont);
1112 charWidth = fm.charWidth('@');
1113 charHeight = fm.getHeight();
1114 charDescent = fm.getDescent();
1122 System.err.println("CharDisplay: charWidth="+charWidth+", "+
1123 "charHeight="+charHeight+", "+
1124 "charDescent="+charDescent);
1125 System.err.println("CharDisplay: "+normalFont+", "+fm);
1128 w + xborder + (scrollBar != null ? 15 : 0),
1131 if(scrollBar != null) {
1132 int xoffset = (super.size().width - size.width * charWidth - 15) / 2;
1133 int yoffset = (super.size().height - size.height * charHeight) / 2;
1134 if(scrBarPos.equals("West"))
1135 scrollBar.reshape(xoffset - (xborder / 2), yoffset - yborder / 2,
1136 15, size.height * charHeight + yborder);
1138 scrollBar.reshape(xoffset + (xborder / 2) + size.width * charWidth,
1139 yoffset - yborder / 2, 15,
1140 size.height * charHeight + yborder);
1145 * Return the real size in points of the character display.
1146 * @return Dimension the dimension of the display
1147 * @see java.awt.Dimension
1149 public Dimension size()
1151 int xborder = 0, yborder = 0;
1152 if(insets != null) {
1153 xborder = insets.left + insets.right;
1154 yborder = insets.top + insets.bottom;
1156 if(scrollBar != null) xborder += 15;
1158 return new Dimension(size.width * charWidth + xborder,
1159 size.height * charHeight + yborder);
1163 * Return the preferred Size of the character display.
1164 * This turns out to be the actual size.
1165 * @return Dimension dimension of the display
1168 public Dimension preferredSize()
1174 * The insets of the character display define the border.
1175 * @return Insets border thickness in pixels
1177 public Insets insets()
1179 return insets == null ? super.insets() : insets;
1183 * Handle mouse events for copy & paste
1184 * @param evt the event that occured
1185 * @return boolean true if action was taken
1186 * @see java.awt.Event
1188 public boolean handleEvent(Event evt)
1190 // handle scrollbar events
1191 if(evt != null && evt.target == scrollBar && evt.arg != null) {
1192 int val = ((Integer)evt.arg).intValue();
1197 if(evt.id == Event.MOUSE_DOWN || evt.id == Event.MOUSE_UP ||
1198 evt.id == Event.MOUSE_DRAG) {
1199 int xoffset = (super.size().width - size.width * charWidth) / 2;
1200 int yoffset = (super.size().height - size.height * charHeight) / 2;
1202 case Event.MOUSE_DOWN:
1203 selectBegin.x = (evt.x - xoffset) / charWidth;
1204 selectBegin.y = (evt.y - yoffset) / charHeight + windowBase;
1205 selectEnd.x = selectBegin.x;
1206 selectEnd.y = selectBegin.y;
1207 if(selectFrame != null) selectFrame.hide();
1209 case Event.MOUSE_UP:
1210 case Event.MOUSE_DRAG:
1211 int x = (evt.x - xoffset) / charWidth;
1212 int y = (evt.y - yoffset) / charHeight + windowBase;
1213 int oldx = selectEnd.x, oldy = selectEnd.y;
1215 if((x < selectBegin.x && y < selectBegin.y) &&
1216 (x < selectEnd.x && y < selectEnd.y)) {
1224 if(evt.id == Event.MOUSE_UP) {
1225 if(selectBegin.x == selectEnd.x &&
1226 selectBegin.y == selectEnd.y) {
1231 // fix end.x and end.y, they can get over the border
1232 if (selectEnd.x < 0) selectEnd.x = 0;
1233 if (selectEnd.y < 0) selectEnd.y = 0;
1234 if (selectEnd.y >= charArray.length) {
1235 selectEnd.y = charArray.length-1;
1237 if (selectEnd.x >= charArray[0].length) {
1238 selectEnd.x = charArray[0].length-1;
1240 for(int l = selectBegin.y; l <= selectEnd.y; l++)
1241 if(l == selectBegin.y)
1242 tmp = (new String(charArray[l])).substring(selectBegin.x) + "\n";
1243 else if(l == selectEnd.y)
1244 tmp += (new String(charArray[l])).substring(0, selectEnd.x);
1245 else tmp += new String(charArray[l]) + "\n";
1246 if(selectFrame == null) {
1248 String s=(String) ((StringSelection)this.getToolkit().
1249 getSystemClipboard().
1251 getTransferData(DataFlavor.stringFlavor);
1252 System.out.println(s);
1255 selectFrame = new Frame("Pasteboard");
1256 selection = new TextArea();
1257 selection.setFont(normalFont);
1258 selectFrame.add("Center", selection);
1259 selectFrame.add("South", new Label("Click on the terminal window"+
1263 selection.setText(tmp);
1264 //selectFrame.show();
1265 selection.selectAll();
1268 if(oldx != x || oldy != y) repaint();