content: package com.termux.terminal;
  
  import java.io.UnsupportedEncodingException;
  
  public class TerminalTest extends TerminalTestCase {
  
  	public void testCursorPositioning() throws Exception {
  		withTerminalSized(10, 10).placeCursorAndAssert(1, 2).placeCursorAndAssert(3, 5).placeCursorAndAssert(2, 2).enterString("A")
  				.assertCursorAt(2, 3);
  	}
  
  	public void testScreen() throws UnsupportedEncodingException {
  		withTerminalSized(3, 3);
  		assertLinesAre("   ", "   ", "   ");
  
  		assertEquals("", mTerminal.getScreen().getTranscriptText());
  		enterString("hi").assertLinesAre("hi ", "   ", "   ");
  		assertEquals("hi", mTerminal.getScreen().getTranscriptText());
  		enterString("\r\nu");
  		assertEquals("hi\nu", mTerminal.getScreen().getTranscriptText());
  		mTerminal.reset();
  		assertEquals("hi\nu", mTerminal.getScreen().getTranscriptText());
  
  		withTerminalSized(3, 3).enterString("hello");
  		assertEquals("hello", mTerminal.getScreen().getTranscriptText());
  		enterString("\r\nworld");
  		assertEquals("hello\nworld", mTerminal.getScreen().getTranscriptText());
  	}
  
  	public void testScrollDownInAltBuffer() {
  		withTerminalSized(3, 3).enterString("\033[?1049h");
  		enterString("\033[38;5;111m1\r\n");
  		enterString("\033[38;5;112m2\r\n");
  		enterString("\033[38;5;113m3\r\n");
  		enterString("\033[38;5;114m4\r\n");
  		enterString("\033[38;5;115m5");
  		assertLinesAre("3  ", "4  ", "5  ");
  		assertForegroundColorAt(0, 0, 113);
  		assertForegroundColorAt(1, 0, 114);
  		assertForegroundColorAt(2, 0, 115);
  	}
  
  	public void testMouseClick() throws Exception {
  		withTerminalSized(10, 10);
  		assertFalse(mTerminal.isMouseTrackingActive());
  		enterString("\033[?1000h");
  		assertTrue(mTerminal.isMouseTrackingActive());
  		enterString("\033[?1000l");
  		assertFalse(mTerminal.isMouseTrackingActive());
  		enterString("\033[?1000h");
  		assertTrue(mTerminal.isMouseTrackingActive());
  
  		enterString("\033[?1006h");
  		mTerminal.sendMouseEvent(TerminalEmulator.MOUSE_LEFT_BUTTON, 3, 4, true);
  		assertEquals("\033[<0;3;4M", mOutput.getOutputAndClear());
  		mTerminal.sendMouseEvent(TerminalEmulator.MOUSE_LEFT_BUTTON, 3, 4, false);
  		assertEquals("\033[<0;3;4m", mOutput.getOutputAndClear());
  
  		// When the client says that a click is outside (which could happen when pixels are outside
  		// the terminal area, see https://github.com/termux/termux-app/issues/501) the terminal
  		// sends a click at the edge.
  		mTerminal.sendMouseEvent(TerminalEmulator.MOUSE_LEFT_BUTTON, 0, 0, true);
  		assertEquals("\033[<0;1;1M", mOutput.getOutputAndClear());
  		mTerminal.sendMouseEvent(TerminalEmulator.MOUSE_LEFT_BUTTON, 11, 11, false);
  		assertEquals("\033[<0;10;10m", mOutput.getOutputAndClear());
  	}
  
  	public void testNormalization() throws UnsupportedEncodingException {
  		// int lowerCaseN = 0x006E;
  		// int combiningTilde = 0x0303;
  		// int combined = 0x00F1;
  		withTerminalSized(3, 3).assertLinesAre("   ", "   ", "   ");
  		enterString("\u006E\u0303");
  		assertEquals(1, WcWidth.width("\u006E\u0303".toCharArray(), 0));
  		// assertEquals("\u00F1  ", new String(mTerminal.getScreen().getLine(0)));
  		assertLinesAre("\u006E\u0303  ", "   ", "   ");
  	}
  
  	/** On "\e[18t" xterm replies with "\e[8;${HEIGHT};${WIDTH}t" */
  	public void testReportTerminalSize() throws Exception {
  		withTerminalSized(5, 5);
  		assertEnteringStringGivesResponse("\033[18t", "\033[8;5;5t");
  		for (int width = 3; width < 12; width++) {
  			for (int height = 3; height < 12; height++) {
  				mTerminal.resize(width, height);
  				assertEnteringStringGivesResponse("\033[18t", "\033[8;" + height + ";" + width + "t");
  			}
  		}
  	}
  
  	/** Device Status Report (DSR) and Report Cursor Position (CPR). */
  	public void testDeviceStatusReport() throws Exception {
  		withTerminalSized(5, 5);
  		assertEnteringStringGivesResponse("\033[5n", "\033[0n");
  
  		assertEnteringStringGivesResponse("\033[6n", "\033[1;1R");
  		enterString("AB");
  		assertEnteringStringGivesResponse("\033[6n", "\033[1;3R");
  		enterString("\r\n");
  		assertEnteringStringGivesResponse("\033[6n", "\033[2;1R");
  	}
  
  	/** Test the cursor shape changes using DECSCUSR. */
  	public void testSetCursorStyle() throws Exception {
  		withTerminalSized(5, 5);
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_BLOCK, mTerminal.getCursorStyle());
  		enterString("\033[3 q");
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_UNDERLINE, mTerminal.getCursorStyle());
  		enterString("\033[5 q");
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_BAR, mTerminal.getCursorStyle());
  		enterString("\033[0 q");
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_BLOCK, mTerminal.getCursorStyle());
  		enterString("\033[6 q");
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_BAR, mTerminal.getCursorStyle());
  		enterString("\033[4 q");
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_UNDERLINE, mTerminal.getCursorStyle());
  		enterString("\033[1 q");
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_BLOCK, mTerminal.getCursorStyle());
  		enterString("\033[4 q");
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_UNDERLINE, mTerminal.getCursorStyle());
  		enterString("\033[2 q");
  		assertEquals(TerminalEmulator.TERMINAL_CURSOR_STYLE_BLOCK, mTerminal.getCursorStyle());
  	}
  
  	public void testPaste() {
  		withTerminalSized(5, 5);
  		mTerminal.paste("hi");
  		assertEquals("hi", mOutput.getOutputAndClear());
  
  		enterString("\033[?2004h");
  		mTerminal.paste("hi");
  		assertEquals("\033[200~" + "hi" + "\033[201~", mOutput.getOutputAndClear());
  
  		enterString("\033[?2004l");
  		mTerminal.paste("hi");
  		assertEquals("hi", mOutput.getOutputAndClear());
  	}
  
  	public void testSelectGraphics() {
  		withTerminalSized(5, 5);
  		enterString("\033[31m");
  		assertEquals(mTerminal.mForeColor, 1);
  		enterString("\033[32m");
  		assertEquals(mTerminal.mForeColor, 2);
  		enterString("\033[43m");
  		assertEquals(2, mTerminal.mForeColor);
  		assertEquals(3, mTerminal.mBackColor);
  
  		// SGR 0 should reset both foreground and background color.
  		enterString("\033[0m");
  		assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, mTerminal.mForeColor);
  		assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, mTerminal.mBackColor);
  
  		// Test CSI resetting to default if sequence starts with ; or has sequential ;;
          // Check TerminalEmulator.parseArg()
          enterString("\033[31m\033[m");
          assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, mTerminal.mForeColor);
          enterString("\033[31m\033[;m");
          assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, mTerminal.mForeColor);
          enterString("\033[31m\033[0m");
          assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, mTerminal.mForeColor);
          enterString("\033[31m\033[0;m");
          assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, mTerminal.mForeColor);
          enterString("\033[31;;m");
          assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, mTerminal.mForeColor);
  
  		// 256 colors:
  		enterString("\033[38;5;119m");
  		assertEquals(119, mTerminal.mForeColor);
  		assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, mTerminal.mBackColor);
  		enterString("\033[48;5;129m");
  		assertEquals(119, mTerminal.mForeColor);
  		assertEquals(129, mTerminal.mBackColor);
  
  		// Invalid parameter:
  		enterString("\033[48;8;129m");
  		assertEquals(119, mTerminal.mForeColor);
  		assertEquals(129, mTerminal.mBackColor);
  
  		// Multiple parameters at once:
  		enterString("\033[38;5;178;48;5;179;m");
  		assertEquals(178, mTerminal.mForeColor);
  		assertEquals(179, mTerminal.mBackColor);
  
  		// 24 bit colors:
  		enterString(("\033[0m")); // Reset fg and bg colors.
  		enterString("\033[38;2;255;127;2m");
  		int expectedForeground = 0xff000000 | (255 << 16) | (127 << 8) | 2;
  		assertEquals(expectedForeground, mTerminal.mForeColor);
  		assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, mTerminal.mBackColor);
  		enterString("\033[48;2;1;2;254m");
  		int expectedBackground = 0xff000000 | (1 << 16) | (2 << 8) | 254;
  		assertEquals(expectedForeground, mTerminal.mForeColor);
  		assertEquals(expectedBackground, mTerminal.mBackColor);
  
  		// 24 bit colors, set fg and bg at once:
  		enterString(("\033[0m")); // Reset fg and bg colors.
  		assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, mTerminal.mForeColor);
  		assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, mTerminal.mBackColor);
  		enterString("\033[38;2;255;127;2;48;2;1;2;254m");
  		assertEquals(expectedForeground, mTerminal.mForeColor);
  		assertEquals(expectedBackground, mTerminal.mBackColor);
  
  		// 24 bit colors, invalid input:
  		enterString("\033[38;2;300;127;2;48;2;1;300;254m");
  		assertEquals(expectedForeground, mTerminal.mForeColor);
  		assertEquals(expectedBackground, mTerminal.mBackColor);
  	}
  
  	public void testBackgroundColorErase() {
  		final int rows = 3;
  		final int cols = 3;
  		withTerminalSized(cols, rows);
  		for (int r = 0; r < rows; r++) {
  			for (int c = 0; c < cols; c++) {
  				long style = getStyleAt(r, c);
  				assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.decodeForeColor(style));
  				assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, TextStyle.decodeBackColor(style));
  			}
  		}
  		// Foreground color to 119:
  		enterString("\033[38;5;119m");
  		// Background color to 129:
  		enterString("\033[48;5;129m");
  		// Clear with ED, Erase in Display:
  		enterString("\033[2J");
  		for (int r = 0; r < rows; r++) {
  			for (int c = 0; c < cols; c++) {
  				long style = getStyleAt(r, c);
  				assertEquals(119, TextStyle.decodeForeColor(style));
  				assertEquals(129, TextStyle.decodeBackColor(style));
  			}
  		}
  		// Background color to 139:
  		enterString("\033[48;5;139m");
  		// Insert two blank lines.
  		enterString("\033[2L");
  		for (int r = 0; r < rows; r++) {
  			for (int c = 0; c < cols; c++) {
  				long style = getStyleAt(r, c);
  				assertEquals((r == 0 || r == 1) ? 139 : 129, TextStyle.decodeBackColor(style));
  			}
  		}
  
  		withTerminalSized(cols, rows);
  		// Background color to 129:
  		enterString("\033[48;5;129m");
  		// Erase two characters, filling them with background color:
  		enterString("\033[2X");
  		assertEquals(129, TextStyle.decodeBackColor(getStyleAt(0, 0)));
  		assertEquals(129, TextStyle.decodeBackColor(getStyleAt(0, 1)));
  		assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, TextStyle.decodeBackColor(getStyleAt(0, 2)));
  	}
  
  	public void testParseColor() {
  		assertEquals(0xFF0000FA, TerminalColors.parse("#0000FA"));
  		assertEquals(0xFF000000, TerminalColors.parse("#000000"));
  		assertEquals(0xFF000000, TerminalColors.parse("#000"));
  		assertEquals(0xFF000000, TerminalColors.parse("#000000000"));
  		assertEquals(0xFF53186f, TerminalColors.parse("#53186f"));
  
  		assertEquals(0xFFFF00FF, TerminalColors.parse("rgb:F/0/F"));
  		assertEquals(0xFF0000FA, TerminalColors.parse("rgb:00/00/FA"));
  		assertEquals(0xFF53186f, TerminalColors.parse("rgb:53/18/6f"));
  
  		assertEquals(0, TerminalColors.parse("invalid_0000FA"));
  		assertEquals(0, TerminalColors.parse("#3456"));
  	}
  
  	/** The ncurses library still uses this. */
  	public void testLineDrawing() {
  		// 016 - shift out / G1. 017 - shift in / G0. "ESC ) 0" - use line drawing for G1
  		withTerminalSized(4, 2).enterString("q\033)0q\016q\017q").assertLinesAre("qq─q", "    ");
  		// "\0337", saving cursor should save G0, G1 and invoked charset and "ESC 8" should restore.
  		withTerminalSized(4, 2).enterString("\033)0\016qqq\0337\017\0338q").assertLinesAre("────", "    ");
  	}
  
  	public void testSoftTerminalReset() {
  		// See http://vt100.net/docs/vt510-rm/DECSTR and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=650304
  		// "\033[?7l" is DECRST to disable wrap-around, and DECSTR ("\033[!p") should reset it.
  		withTerminalSized(3, 3).enterString("\033[?7lABCD").assertLinesAre("ABD", "   ", "   ");
  		enterString("\033[!pEF").assertLinesAre("ABE", "F  ", "   ");
  	}
  
  	public void testBel() {
  		withTerminalSized(3, 3);
  		assertEquals(0, mOutput.bellsRung);
  		enterString("\07");
  		assertEquals(1, mOutput.bellsRung);
  		enterString("hello\07");
  		assertEquals(2, mOutput.bellsRung);
  		enterString("\07hello");
  		assertEquals(3, mOutput.bellsRung);
  		enterString("hello\07world");
  		assertEquals(4, mOutput.bellsRung);
  	}
  
  	public void testAutomargins() throws UnsupportedEncodingException {
  		withTerminalSized(3, 3).enterString("abc").assertLinesAre("abc", "   ", "   ").assertCursorAt(0, 2);
  		enterString("d").assertLinesAre("abc", "d  ", "   ").assertCursorAt(1, 1);
  
  		withTerminalSized(3, 3).enterString("abc\r ").assertLinesAre(" bc", "   ", "   ").assertCursorAt(0, 1);
  	}
  
  	public void testTab() {
  		withTerminalSized(11, 2).enterString("01234567890\r\tXX").assertLinesAre("01234567XX0", "           ");
  		withTerminalSized(11, 2).enterString("01234567890\033[44m\r\tXX").assertLinesAre("01234567XX0", "           ");
  	}
  
  }
  