+ /**
+ * Return the proper primary Device Attributes string.
+ *
+ * @return string to send to remote side that is appropriate for the
+ * this.type
+ */
+ private String deviceTypeResponse() {
+ switch (type) {
+ case VT100:
+ // "I am a VT100 with advanced video option" (often VT102)
+ return "\033[?1;2c";
+
+ case VT102:
+ // "I am a VT102"
+ return "\033[?6c";
+
+ case VT220:
+ case XTERM:
+ // "I am a VT220" - 7 bit version, with sixel and Jexer image
+ // support.
+ if (!s8c1t) {
+ return "\033[?62;1;6;9;4;22;444c";
+ }
+ // "I am a VT220" - 8 bit version, with sixel and Jexer image
+ // support.
+ return "\u009b?62;1;6;9;4;22;444c";
+ default:
+ throw new IllegalArgumentException("Invalid device type: " + type);
+ }
+ }
+
+ /**
+ * Return the proper TERM environment variable for this device type.
+ *
+ * @param deviceType DeviceType.VT100, DeviceType, XTERM, etc.
+ * @return "vt100", "xterm", etc.
+ */
+ public static String deviceTypeTerm(final DeviceType deviceType) {
+ switch (deviceType) {
+ case VT100:
+ return "vt100";
+
+ case VT102:
+ return "vt102";
+
+ case VT220:
+ return "vt220";
+
+ case XTERM:
+ return "xterm";
+
+ default:
+ throw new IllegalArgumentException("Invalid device type: "
+ + deviceType);
+ }
+ }
+
+ /**
+ * Return the proper LANG for this device type. Only XTERM devices know
+ * about UTF-8, the others are defined by their standard to be either
+ * 7-bit or 8-bit characters only.
+ *
+ * @param deviceType DeviceType.VT100, DeviceType, XTERM, etc.
+ * @param baseLang a base language without UTF-8 flag such as "C" or
+ * "en_US"
+ * @return "en_US", "en_US.UTF-8", etc.
+ */
+ public static String deviceTypeLang(final DeviceType deviceType,
+ final String baseLang) {
+
+ switch (deviceType) {
+
+ case VT100:
+ case VT102:
+ case VT220:
+ return baseLang;
+
+ case XTERM:
+ return baseLang + ".UTF-8";
+
+ default:
+ throw new IllegalArgumentException("Invalid device type: "
+ + deviceType);
+ }
+ }
+
+ /**
+ * Write a string directly to the remote side.
+ *
+ * @param str string to send
+ */
+ public void writeRemote(final String str) {
+ if (stopReaderThread) {
+ // Reader hit EOF, bail out now.
+ close();
+ return;
+ }
+
+ // System.err.printf("writeRemote() '%s'\n", str);
+
+ switch (type) {
+ case VT100:
+ case VT102:
+ case VT220:
+ if (outputStream == null) {
+ return;
+ }
+ try {
+ outputStream.flush();
+ for (int i = 0; i < str.length(); i++) {
+ outputStream.write(str.charAt(i));
+ }
+ outputStream.flush();
+ } catch (IOException e) {
+ // Assume EOF
+ close();
+ }
+ break;
+ case XTERM:
+ if (output == null) {
+ return;
+ }
+ try {
+ output.flush();
+ output.write(str);
+ output.flush();
+ } catch (IOException e) {
+ // Assume EOF
+ close();
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid device type: " + type);
+ }
+ }
+
+ /**
+ * Close the input and output streams and stop the reader thread. Note
+ * that it is safe to call this multiple times.
+ */
+ public final void close() {
+
+ // Tell the reader thread to stop looking at input. It will close
+ // the input streams.
+ if (stopReaderThread == false) {
+ stopReaderThread = true;
+ }
+
+ // Now close the output stream.
+ switch (type) {
+ case VT100:
+ case VT102:
+ case VT220:
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ // SQUASH
+ }
+ outputStream = null;
+ }
+ break;
+ case XTERM:
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ // SQUASH
+ }
+ outputStream = null;
+ }
+ if (output != null) {
+ try {
+ output.close();
+ } catch (IOException e) {
+ // SQUASH
+ }
+ output = null;
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid device type: " +
+ type);
+ }
+ }
+
+ /**
+ * See if the reader thread is still running.
+ *
+ * @return if true, we are still connected to / reading from the remote
+ * side
+ */
+ public final boolean isReading() {
+ return (!stopReaderThread);
+ }
+
+ /**
+ * Obtain a new blank display line for an external user
+ * (e.g. TTerminalWindow).
+ *
+ * @return new blank line
+ */
+ public final DisplayLine getBlankDisplayLine() {
+ return new DisplayLine(currentState.attr);
+ }
+
+ /**
+ * Get the scrollback buffer.
+ *
+ * @return the scrollback buffer
+ */
+ public final List<DisplayLine> getScrollbackBuffer() {
+ return scrollback;
+ }
+
+ /**
+ * Get the display buffer.
+ *
+ * @return the display buffer
+ */
+ public final List<DisplayLine> getDisplayBuffer() {
+ return display;
+ }
+
+ /**
+ * Get the visible display + scrollback buffer, offset by a specified
+ * number of rows from the bottom.
+ *
+ * @param visibleHeight the total height of the display to show
+ * @param scrollBottom the number of rows from the bottom to scroll back
+ * @return a copy of the display + scrollback buffers
+ */
+ public final List<DisplayLine> getVisibleDisplay(final int visibleHeight,
+ final int scrollBottom) {
+
+ assert (visibleHeight >= 0);
+ assert (scrollBottom >= 0);
+
+ int visibleBottom = scrollback.size() + display.size() - scrollBottom;
+
+ List<DisplayLine> preceedingBlankLines = new ArrayList<DisplayLine>();
+ int visibleTop = visibleBottom - visibleHeight;
+ if (visibleTop < 0) {
+ for (int i = visibleTop; i < 0; i++) {
+ preceedingBlankLines.add(getBlankDisplayLine());
+ }
+ visibleTop = 0;
+ }
+ assert (visibleTop >= 0);
+
+ List<DisplayLine> displayLines = new ArrayList<DisplayLine>();
+ displayLines.addAll(scrollback);
+ displayLines.addAll(display);
+
+ List<DisplayLine> visibleLines = new ArrayList<DisplayLine>();
+ visibleLines.addAll(preceedingBlankLines);
+ visibleLines.addAll(displayLines.subList(visibleTop, visibleBottom));
+
+ // Fill in the blank lines on bottom
+ int bottomBlankLines = visibleHeight - visibleLines.size();
+ assert (bottomBlankLines >= 0);
+ for (int i = 0; i < bottomBlankLines; i++) {
+ visibleLines.add(getBlankDisplayLine());
+ }
+
+ return copyBuffer(visibleLines);
+ }
+
+ /**
+ * Copy a display buffer.
+ *
+ * @param buffer the buffer to copy
+ * @return a deep copy of the buffer's data
+ */
+ private List<DisplayLine> copyBuffer(final List<DisplayLine> buffer) {
+ ArrayList<DisplayLine> result = new ArrayList<DisplayLine>(buffer.size());
+ for (DisplayLine line: buffer) {
+ result.add(new DisplayLine(line));
+ }
+ return result;
+ }
+
+ /**
+ * Get the display width.
+ *
+ * @return the width (usually 80 or 132)
+ */
+ public final int getWidth() {
+ return width;
+ }
+
+ /**
+ * Set the display width.
+ *
+ * @param width the new width
+ */
+ public final synchronized void setWidth(final int width) {
+ this.width = width;
+ rightMargin = width - 1;
+ if (currentState.cursorX >= width) {
+ currentState.cursorX = width - 1;
+ }
+ if (savedState.cursorX >= width) {
+ savedState.cursorX = width - 1;
+ }
+ }
+
+ /**
+ * Get the display height.
+ *
+ * @return the height (usually 24)
+ */
+ public final int getHeight() {
+ return height;
+ }
+
+ /**
+ * Set the display height.
+ *
+ * @param height the new height
+ */
+ public final synchronized void setHeight(final int height) {
+ int delta = height - this.height;
+ this.height = height;
+ scrollRegionBottom += delta;
+ if ((scrollRegionBottom < 0) || (scrollRegionTop > height - 1)) {
+ scrollRegionBottom = height - 1;
+ }
+ if (scrollRegionTop >= scrollRegionBottom) {
+ scrollRegionTop = 0;
+ }
+ if (currentState.cursorY >= height) {
+ currentState.cursorY = height - 1;
+ }
+ if (savedState.cursorY >= height) {
+ savedState.cursorY = height - 1;
+ }
+ while (display.size() < height) {
+ DisplayLine line = new DisplayLine(currentState.attr);
+ line.setReverseColor(reverseVideo);
+ display.add(line);
+ }
+ while (display.size() > height) {
+ appendScrollbackLine(display.remove(0));
+ }
+ }
+
+ /**
+ * Get the maximum number of lines in the scrollback buffer.
+ *
+ * @return the maximum number of lines in the scrollback buffer
+ */
+ public int getScrollbackMax() {
+ return scrollbackMax;
+ }
+
+ /**
+ * Set the maximum number of lines for the scrollback buffer.
+ *
+ * @param scrollbackMax the maximum number of lines for the scrollback
+ * buffer
+ */
+ public final void setScrollbackMax(final int scrollbackMax) {
+ this.scrollbackMax = scrollbackMax;
+ }
+
+ /**
+ * Get visible cursor flag.
+ *
+ * @return if true, the cursor is visible
+ */
+ public final boolean isCursorVisible() {
+ return cursorVisible;
+ }
+
+ /**
+ * Get the screen title as set by the xterm OSC sequence. Lots of
+ * applications send a screenTitle regardless of whether it is an xterm
+ * client or not.
+ *
+ * @return screen title
+ */
+ public final String getScreenTitle() {
+ return screenTitle;
+ }
+
+ /**
+ * Get 132 columns value.
+ *
+ * @return if true, the terminal is in 132 column mode
+ */
+ public final boolean isColumns132() {
+ return columns132;
+ }
+
+ /**
+ * Clear the CSI parameters and flags.
+ */
+ private void toGround() {
+ csiParams.clear();
+ collectBuffer.setLength(0);
+ scanState = ScanState.GROUND;
+ }
+
+ /**
+ * Reset the tab stops list.
+ */
+ private void resetTabStops() {
+ tabStops.clear();
+ for (int i = 0; (i * 8) <= rightMargin; i++) {
+ tabStops.add(Integer.valueOf(i * 8));
+ }
+ }
+
+ /**
+ * Reset the 88- or 256-colors.
+ */
+ private void resetColors() {
+ colors88 = new ArrayList<Integer>(256);
+ for (int i = 0; i < 256; i++) {
+ colors88.add(0);
+ }
+
+ // Set default system colors. These match DOS colors.
+ colors88.set(0, 0x00000000);
+ colors88.set(1, 0x00a80000);
+ colors88.set(2, 0x0000a800);
+ colors88.set(3, 0x00a85400);
+ colors88.set(4, 0x000000a8);
+ colors88.set(5, 0x00a800a8);
+ colors88.set(6, 0x0000a8a8);
+ colors88.set(7, 0x00a8a8a8);
+
+ colors88.set(8, 0x00545454);
+ colors88.set(9, 0x00fc5454);
+ colors88.set(10, 0x0054fc54);
+ colors88.set(11, 0x00fcfc54);
+ colors88.set(12, 0x005454fc);
+ colors88.set(13, 0x00fc54fc);
+ colors88.set(14, 0x0054fcfc);
+ colors88.set(15, 0x00fcfcfc);
+
+ // These match xterm's default colors from 256colres.h.
+ colors88.set(16, 0x000000);
+ colors88.set(17, 0x00005f);
+ colors88.set(18, 0x000087);
+ colors88.set(19, 0x0000af);
+ colors88.set(20, 0x0000d7);
+ colors88.set(21, 0x0000ff);
+ colors88.set(22, 0x005f00);
+ colors88.set(23, 0x005f5f);
+ colors88.set(24, 0x005f87);
+ colors88.set(25, 0x005faf);
+ colors88.set(26, 0x005fd7);
+ colors88.set(27, 0x005fff);
+ colors88.set(28, 0x008700);
+ colors88.set(29, 0x00875f);
+ colors88.set(30, 0x008787);
+ colors88.set(31, 0x0087af);
+ colors88.set(32, 0x0087d7);
+ colors88.set(33, 0x0087ff);
+ colors88.set(34, 0x00af00);
+ colors88.set(35, 0x00af5f);
+ colors88.set(36, 0x00af87);
+ colors88.set(37, 0x00afaf);
+ colors88.set(38, 0x00afd7);
+ colors88.set(39, 0x00afff);
+ colors88.set(40, 0x00d700);
+ colors88.set(41, 0x00d75f);
+ colors88.set(42, 0x00d787);
+ colors88.set(43, 0x00d7af);
+ colors88.set(44, 0x00d7d7);
+ colors88.set(45, 0x00d7ff);
+ colors88.set(46, 0x00ff00);
+ colors88.set(47, 0x00ff5f);
+ colors88.set(48, 0x00ff87);
+ colors88.set(49, 0x00ffaf);
+ colors88.set(50, 0x00ffd7);
+ colors88.set(51, 0x00ffff);
+ colors88.set(52, 0x5f0000);
+ colors88.set(53, 0x5f005f);
+ colors88.set(54, 0x5f0087);
+ colors88.set(55, 0x5f00af);
+ colors88.set(56, 0x5f00d7);
+ colors88.set(57, 0x5f00ff);
+ colors88.set(58, 0x5f5f00);
+ colors88.set(59, 0x5f5f5f);
+ colors88.set(60, 0x5f5f87);
+ colors88.set(61, 0x5f5faf);
+ colors88.set(62, 0x5f5fd7);
+ colors88.set(63, 0x5f5fff);
+ colors88.set(64, 0x5f8700);
+ colors88.set(65, 0x5f875f);
+ colors88.set(66, 0x5f8787);
+ colors88.set(67, 0x5f87af);
+ colors88.set(68, 0x5f87d7);
+ colors88.set(69, 0x5f87ff);
+ colors88.set(70, 0x5faf00);
+ colors88.set(71, 0x5faf5f);
+ colors88.set(72, 0x5faf87);
+ colors88.set(73, 0x5fafaf);
+ colors88.set(74, 0x5fafd7);
+ colors88.set(75, 0x5fafff);
+ colors88.set(76, 0x5fd700);
+ colors88.set(77, 0x5fd75f);
+ colors88.set(78, 0x5fd787);
+ colors88.set(79, 0x5fd7af);
+ colors88.set(80, 0x5fd7d7);
+ colors88.set(81, 0x5fd7ff);
+ colors88.set(82, 0x5fff00);
+ colors88.set(83, 0x5fff5f);
+ colors88.set(84, 0x5fff87);
+ colors88.set(85, 0x5fffaf);
+ colors88.set(86, 0x5fffd7);
+ colors88.set(87, 0x5fffff);
+ colors88.set(88, 0x870000);
+ colors88.set(89, 0x87005f);
+ colors88.set(90, 0x870087);
+ colors88.set(91, 0x8700af);
+ colors88.set(92, 0x8700d7);
+ colors88.set(93, 0x8700ff);
+ colors88.set(94, 0x875f00);
+ colors88.set(95, 0x875f5f);
+ colors88.set(96, 0x875f87);
+ colors88.set(97, 0x875faf);
+ colors88.set(98, 0x875fd7);
+ colors88.set(99, 0x875fff);
+ colors88.set(100, 0x878700);
+ colors88.set(101, 0x87875f);
+ colors88.set(102, 0x878787);
+ colors88.set(103, 0x8787af);
+ colors88.set(104, 0x8787d7);
+ colors88.set(105, 0x8787ff);
+ colors88.set(106, 0x87af00);
+ colors88.set(107, 0x87af5f);
+ colors88.set(108, 0x87af87);
+ colors88.set(109, 0x87afaf);
+ colors88.set(110, 0x87afd7);
+ colors88.set(111, 0x87afff);
+ colors88.set(112, 0x87d700);
+ colors88.set(113, 0x87d75f);
+ colors88.set(114, 0x87d787);
+ colors88.set(115, 0x87d7af);
+ colors88.set(116, 0x87d7d7);
+ colors88.set(117, 0x87d7ff);
+ colors88.set(118, 0x87ff00);
+ colors88.set(119, 0x87ff5f);
+ colors88.set(120, 0x87ff87);
+ colors88.set(121, 0x87ffaf);
+ colors88.set(122, 0x87ffd7);
+ colors88.set(123, 0x87ffff);
+ colors88.set(124, 0xaf0000);
+ colors88.set(125, 0xaf005f);
+ colors88.set(126, 0xaf0087);
+ colors88.set(127, 0xaf00af);
+ colors88.set(128, 0xaf00d7);
+ colors88.set(129, 0xaf00ff);
+ colors88.set(130, 0xaf5f00);
+ colors88.set(131, 0xaf5f5f);
+ colors88.set(132, 0xaf5f87);
+ colors88.set(133, 0xaf5faf);
+ colors88.set(134, 0xaf5fd7);
+ colors88.set(135, 0xaf5fff);
+ colors88.set(136, 0xaf8700);
+ colors88.set(137, 0xaf875f);
+ colors88.set(138, 0xaf8787);
+ colors88.set(139, 0xaf87af);
+ colors88.set(140, 0xaf87d7);
+ colors88.set(141, 0xaf87ff);
+ colors88.set(142, 0xafaf00);
+ colors88.set(143, 0xafaf5f);
+ colors88.set(144, 0xafaf87);
+ colors88.set(145, 0xafafaf);
+ colors88.set(146, 0xafafd7);
+ colors88.set(147, 0xafafff);
+ colors88.set(148, 0xafd700);
+ colors88.set(149, 0xafd75f);
+ colors88.set(150, 0xafd787);
+ colors88.set(151, 0xafd7af);
+ colors88.set(152, 0xafd7d7);
+ colors88.set(153, 0xafd7ff);
+ colors88.set(154, 0xafff00);
+ colors88.set(155, 0xafff5f);
+ colors88.set(156, 0xafff87);
+ colors88.set(157, 0xafffaf);
+ colors88.set(158, 0xafffd7);
+ colors88.set(159, 0xafffff);
+ colors88.set(160, 0xd70000);
+ colors88.set(161, 0xd7005f);
+ colors88.set(162, 0xd70087);
+ colors88.set(163, 0xd700af);
+ colors88.set(164, 0xd700d7);
+ colors88.set(165, 0xd700ff);
+ colors88.set(166, 0xd75f00);
+ colors88.set(167, 0xd75f5f);
+ colors88.set(168, 0xd75f87);
+ colors88.set(169, 0xd75faf);
+ colors88.set(170, 0xd75fd7);
+ colors88.set(171, 0xd75fff);
+ colors88.set(172, 0xd78700);
+ colors88.set(173, 0xd7875f);
+ colors88.set(174, 0xd78787);
+ colors88.set(175, 0xd787af);
+ colors88.set(176, 0xd787d7);
+ colors88.set(177, 0xd787ff);
+ colors88.set(178, 0xd7af00);
+ colors88.set(179, 0xd7af5f);
+ colors88.set(180, 0xd7af87);
+ colors88.set(181, 0xd7afaf);
+ colors88.set(182, 0xd7afd7);
+ colors88.set(183, 0xd7afff);
+ colors88.set(184, 0xd7d700);
+ colors88.set(185, 0xd7d75f);
+ colors88.set(186, 0xd7d787);
+ colors88.set(187, 0xd7d7af);
+ colors88.set(188, 0xd7d7d7);
+ colors88.set(189, 0xd7d7ff);
+ colors88.set(190, 0xd7ff00);
+ colors88.set(191, 0xd7ff5f);
+ colors88.set(192, 0xd7ff87);
+ colors88.set(193, 0xd7ffaf);
+ colors88.set(194, 0xd7ffd7);
+ colors88.set(195, 0xd7ffff);
+ colors88.set(196, 0xff0000);
+ colors88.set(197, 0xff005f);
+ colors88.set(198, 0xff0087);
+ colors88.set(199, 0xff00af);
+ colors88.set(200, 0xff00d7);
+ colors88.set(201, 0xff00ff);
+ colors88.set(202, 0xff5f00);
+ colors88.set(203, 0xff5f5f);
+ colors88.set(204, 0xff5f87);
+ colors88.set(205, 0xff5faf);
+ colors88.set(206, 0xff5fd7);
+ colors88.set(207, 0xff5fff);
+ colors88.set(208, 0xff8700);
+ colors88.set(209, 0xff875f);
+ colors88.set(210, 0xff8787);
+ colors88.set(211, 0xff87af);
+ colors88.set(212, 0xff87d7);
+ colors88.set(213, 0xff87ff);
+ colors88.set(214, 0xffaf00);
+ colors88.set(215, 0xffaf5f);
+ colors88.set(216, 0xffaf87);
+ colors88.set(217, 0xffafaf);
+ colors88.set(218, 0xffafd7);
+ colors88.set(219, 0xffafff);
+ colors88.set(220, 0xffd700);
+ colors88.set(221, 0xffd75f);
+ colors88.set(222, 0xffd787);
+ colors88.set(223, 0xffd7af);
+ colors88.set(224, 0xffd7d7);
+ colors88.set(225, 0xffd7ff);
+ colors88.set(226, 0xffff00);
+ colors88.set(227, 0xffff5f);
+ colors88.set(228, 0xffff87);
+ colors88.set(229, 0xffffaf);
+ colors88.set(230, 0xffffd7);
+ colors88.set(231, 0xffffff);
+ colors88.set(232, 0x080808);
+ colors88.set(233, 0x121212);
+ colors88.set(234, 0x1c1c1c);
+ colors88.set(235, 0x262626);
+ colors88.set(236, 0x303030);
+ colors88.set(237, 0x3a3a3a);
+ colors88.set(238, 0x444444);
+ colors88.set(239, 0x4e4e4e);
+ colors88.set(240, 0x585858);
+ colors88.set(241, 0x626262);
+ colors88.set(242, 0x6c6c6c);
+ colors88.set(243, 0x767676);
+ colors88.set(244, 0x808080);
+ colors88.set(245, 0x8a8a8a);
+ colors88.set(246, 0x949494);
+ colors88.set(247, 0x9e9e9e);
+ colors88.set(248, 0xa8a8a8);
+ colors88.set(249, 0xb2b2b2);
+ colors88.set(250, 0xbcbcbc);
+ colors88.set(251, 0xc6c6c6);
+ colors88.set(252, 0xd0d0d0);
+ colors88.set(253, 0xdadada);
+ colors88.set(254, 0xe4e4e4);
+ colors88.set(255, 0xeeeeee);
+
+ }
+
+ /**
+ * Get the RGB value of one of the indexed colors.
+ *
+ * @param index the color index
+ * @return the RGB value
+ */
+ private int get88Color(final int index) {
+ // System.err.print("get88Color: " + index);
+ if ((index < 0) || (index > colors88.size())) {
+ // System.err.println(" -- UNKNOWN");
+ return 0;
+ }
+ // System.err.printf(" %08x\n", colors88.get(index));
+ return colors88.get(index);
+ }
+
+ /**
+ * Set one of the indexed colors to a color specification.
+ *
+ * @param index the color index
+ * @param spec the specification, typically something like "rgb:aa/bb/cc"
+ */
+ private void set88Color(final int index, final String spec) {
+ // System.err.println("set88Color: " + index + " '" + spec + "'");
+
+ if ((index < 0) || (index > colors88.size())) {
+ return;
+ }
+ if (spec.startsWith("rgb:")) {
+ String [] rgbTokens = spec.substring(4).split("/");
+ if (rgbTokens.length == 3) {
+ try {
+ int rgb = (Integer.parseInt(rgbTokens[0], 16) << 16);
+ rgb |= Integer.parseInt(rgbTokens[1], 16) << 8;
+ rgb |= Integer.parseInt(rgbTokens[2], 16);
+ // System.err.printf(" set to %08x\n", rgb);
+ colors88.set(index, rgb);
+ } catch (NumberFormatException e) {
+ // SQUASH
+ }
+ }
+ return;
+ }
+
+ if (spec.toLowerCase().equals("black")) {
+ colors88.set(index, 0x00000000);
+ } else if (spec.toLowerCase().equals("red")) {
+ colors88.set(index, 0x00a80000);
+ } else if (spec.toLowerCase().equals("green")) {
+ colors88.set(index, 0x0000a800);
+ } else if (spec.toLowerCase().equals("yellow")) {
+ colors88.set(index, 0x00a85400);
+ } else if (spec.toLowerCase().equals("blue")) {
+ colors88.set(index, 0x000000a8);
+ } else if (spec.toLowerCase().equals("magenta")) {
+ colors88.set(index, 0x00a800a8);
+ } else if (spec.toLowerCase().equals("cyan")) {
+ colors88.set(index, 0x0000a8a8);
+ } else if (spec.toLowerCase().equals("white")) {
+ colors88.set(index, 0x00a8a8a8);
+ }
+
+ }
+
+ /**
+ * Reset the emulation state.
+ */
+ private void reset() {
+
+ currentState = new SaveableState();
+ savedState = new SaveableState();
+ scanState = ScanState.GROUND;
+ if (displayListener != null) {
+ width = displayListener.getDisplayWidth();
+ height = displayListener.getDisplayHeight();
+ } else {
+ width = 80;
+ height = 24;
+ }