diff --git a/ChangeLog b/ChangeLog index 7cd585aa..4272404b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2019-06-19 Markus Gans + * Add a unit test for FTermLinux with a Linux console emulation + and a dedicated FSystem test instance + 2019-06-12 Markus Gans * Fixes problem with scroll bar view after first draw diff --git a/doc/vga.txt b/doc/vga.txt new file mode 100644 index 00000000..a1ae9e9a --- /dev/null +++ b/doc/vga.txt @@ -0,0 +1,516 @@ +3C0h: Attribute Controller: Address register +bit 0-4 Address of data register to write to port 3C0h or read from port 3C1h + (Reads only on VGA). + 5 If set screen output is enabled and the palette can not be modified, + if clear screen output is disabled and the palette can be modified. + + +Port 3C0h is special in that it is both address and data-write register. +Data reads happen from port 3C1h. An internal flip-flop remembers whether it +is currently acting as address or data register. +Accesses to the attribute controller must be separated by at least 250ns. +Reading port 3dAh will reset the flip-flop to address mode. + + +3C0h index 0-Fh (r/W): Attribute: Palette +bit 0 (EGA) Primary Blue + 1 (EGA) Primary Green + 2 (EGA) Primary Red + 3 (EGA) Secondary Blue + 4 (EGA) Secondary Green + 5 (EGA) Secondary Red + 0-5 (VGA) Index into the 256 color DAC table. + May be modified by 3C0h index 10h and 14h. + +3C0h index 10h (r/W): Attribute: Mode Control Register +bit 0 Graphics mode if set, Alphanumeric mode else. + 1 Monochrome mode if set, color mode else. + 2 9-bit wide characters if set. + The 9th bit of characters C0h-DFh will be the same as + the 8th bit. Otherwise it will be the background color. + 3 If set Attribute bit 7 is blinking, else high intensity. + 5 (VGA Only) If set the PEL panning register (3C0h index 13h) is + temporarily set to 0 from when the line compare causes a wrap around + until the next vertical retrace when the register is automatically + reloaded with the old value, else the PEL panning register ignores + line compares. + 6 (VGA Only) If set pixels are 8 bits wide. Used in 256 color modes. + 7 (VGA Only) If set bit 4-5 of the index into the DAC table are taken + from port 3C0h index 14h bit 0-1, else the bits in the palette + register are used. + +3C0h index 11h (r/W): Attribute: Overscan Color Register. +bit 0-5 Color of screen border. Color is defined as in the palette registers. +Note: The EGA requires the Overscan color to be 0 in high resolution modes. + +3C0h index 12h (r/W): Attribute: Color Plane Enable Register +bit 0 Bit plane 0 is enabled if set. + 1 Bit plane 1 is enabled if set. + 2 Bit plane 2 is enabled if set. + 3 Bit plane 3 is enabled if set. + 4-5 Video Status MUX. Diagnostics use only. + Two attribute bits appear on bits 4 and 5 of the Input + Status Register 1 (3dAh). + Value EGA VGA + 0 Red/Blue Bit 2/Bit 0 + 1 Blue'/Green Bit 5/Bit 4 + 2 Red'/Green' Bit 3/Bit 1 + 3 Bit 7/Bit 6 + +3C0h index 13h (r/W): Attribute: Horizontal PEL Panning Register +bit 0-3 Indicates number of pixels to shift the display left + Value 9bit textmode 256color mode Other modes + 0 1 0 0 + 1 2 n/a 1 + 2 3 1 2 + 3 4 n/a 3 + 4 5 2 4 + 5 6 n/a 5 + 6 7 3 6 + 7 8 n/a 7 + 8 0 n/a n/a + +3C0h index 14h (r/W): Attribute: Color Select Register (VGA Only) +bit 0-1 If 3C0h index 10h bit 7 is set these 2 bits are used as bits 4-5 of + the index into the DAC table. + 2-3 These 2 bits are used as bit 6-7 of the index into the DAC table + except in 256 color mode. +Note: this register does not affect 256 color modes. + +3C2h (R): Input Status #0 Register +bit 4 Status of the switch selected by the Miscellaneous Output + Register 3C2h bit 2-3. Switch high if set. + 5 (EGA Only) Pin 19 of the Feature Connector (FEAT0) is high if set + 6 (EGA Only) Pin 17 of the Feature Connector (FEAT1) is high if set + 7 (EGA Only ??) If set IRQ 2 has happened due to Vertical Retrace. + Should be cleared by IRQ 2 interrupt routine by clearing port 3d4h + index 11h bit 4. + +3C2h (W): Miscellaneous Output Register +bit 0 If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base + Address=3Bxh. + 1 Enable CPU Access to video memory if set + 2-3 Clock Select + 0: 14MHz(EGA) 25MHz(VGA) + 1: 16MHz(EGA) 28MHz(VGA) + 2: External(EGA) Reserved(VGA) + 4 (EGA Only) Disable internal video drivers if set + 5 When in Odd/Even modes Select High 64k bank if set + 6 Horizontal Sync Polarity. Negative if set + 7 Vertical Sync Polarity. Negative if set + Bit 6-7 indicates the number of lines on the display: + 0=200(EGA) Reserved(VGA) + 1= 400(VGA) + 2=350(EGA) 350(VGA) + 3= 480(VGA). +Note: Set to all zero on a hardware reset. +Note: On the VGA this register can be read from port 3CCh. + +3C3h (W): Video Subsystem Enable Register +bit 0 Enables the VGA display if set + +3C4h index 0 (r/W): Sequencer: Reset +bit 0 (EGA) Asynchronous Reset if clear + 0 (VGA) Synchronous Reset just as bit 1 + 1 Synchronous Reset if clear + +3C4h index 1 (r/W): Sequencer: Clocking Mode +bit 0 If set character clocks are 8 dots wide, else 9. + 1 (EGA Only) If set the CRTC uses 2/5 of the clock cycles, else 4/5. + 2 If set loads video serializers every other character + clock cycle, else every one. + 3 If set the Dot Clock is Master Clock/2, else same as + Master Clock (See 3C2h bit 2-3). (Doubles pixels). + 4 (VGA Only) If set loads video serializers every fourth character + clock cycle, else every one. + 5 (VGA Only) if set turns off screen and gives all memory cycles to the + CPU interface. + +3C4h index 2 (r/W): Sequencer: Map Mask Register +bit 0 Enable writes to plane 0 if set + 1 Enable writes to plane 1 if set + 2 Enable writes to plane 2 if set + 3 Enable writes to plane 3 if set + +3C4h index 3 (r/W): Sequencer: Character Map Select Register +bit 0-1 (EGA) Selects EGA Character Map (0..3) if bit 3 of the character + attribute is clear. + 2-3 (EGA) Selects EGA Character Map (0..3) if bit 3 of the character + attribute is set. + 0,1,4 (VGA) Selects VGA Character Map (0..7) if bit 3 of the character + attribute is clear. + 2,3,5 (VGA) Selects VGA Character Map (0..7) if bit 3 of the character + attribute is set. +Note: Character Maps are placed at: + Map no. (EGA/VGA) Map no. (VGA) + 0 0k 4 8k + 1 16k 5 24k + 2 32k 6 40k + 3 48k 7 56k + +3C4h index 4 (r/W): Sequencer: Memory Mode Register +bit 0 Set if in an alphanumeric mode, clear in graphics modes. + 1 Set if more than 64kbytes on the adapter. + 2 Enables Odd/Even addressing mode if set. Odd/Even mode places all odd + bytes in plane 1&3, and all even bytes in plane 0&2. + 3 (VGA Only) If set address bit 0-1 selects video memory planes + (256 color mode), rather than the Map Mask and Read Map Select + Registers. + +3C4h index 7 (R/W): Sequencer Horizontal Character Counter Reset Register. + (VGA Only) +Note: Undocumented by IBM. May not be available in all clones. + A write to this register will cause the Horizontal Character Counter + to be held reset (=0) until a write happens to any of the Sequencer + registers index 0..6. + The Vertical Line counter is clocked by a signal derived from the + Horizontal Display Enable (which does not occur if the Horizontal + Character Counter is held reset). + Thus a write to index 7 during Vertical Retrace can stop the display + timing and allow software to start the next frame reasonably + synchronous to an external event. + +3C6h (R/W): PEL Mask (VGA Only) +bit 0-7 This register is anded with the palette index sent for each dot. + Should be set to FFh. + +3C7h (R): DAC State Register (VGA Only) +bit 0-1 0 indicates the DAC is in Read Mode and 3 indicates write mode. + +3C7h (W): PEL Address Read Mode (VGA Only) +bit 0-7 The PEL data register (0..255) to be read from 3C9h. +Note: After reading the 3 bytes at 3C9h this register will increment, + pointing to the next data register. + +3C8h (R/W): PEL Address Write Mode (VGA Only) +bit 0-7 The PEL data register (0..255) to be written to 3C9h. +Note: After writing the 3 bytes at 3C9h this register will increment, pointing + to the next data register. + +3C9h (R/W): PEL Data Register (VGA Only) +bit 0-5 Color value +Note: Each read or write of this register will cycle through first the + registers for Red, Blue and Green, then increment the appropriate + address register, thus the entire palette can be loaded by writing 0 to + the PEL Address Write Mode register 3C8h and then writing all 768 bytes + of the palette to this register. + +3CAh (R): Feature Control Register (VGA Only) +Bit 3 Vertical Sync Select. If set Vertical Sync to the monitor is the + logical OR of the vertical sync and the vertical display enable. +Note: This register is written to port 3dAh and read from 3CAh. + +3CAh (W): Graphics 2 Position (EGA Only) +bit 0-1 Select which bit planes should be controlled by Graphics Controller + #2. Always set to 1. + +3CCh (R): Miscellaneous Output Register (VGA Only) +bit 0 If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base + Address=3Bxh. + 1 Enable CPU Access to video memory if set + 2-3 Clock Select. 0= 25MHz, 1= 28MHz, 2= Reserved + 5 When in Odd/Even modes Select High 64k bank if set + 6 Horizontal Sync Polarity. Negative if set + 7 Vertical Sync Polarity. Negative if set + Bit 6-7 indicates the number of lines on the display: + 0=Reserved, 1=400, 2=350, 3=480. +Note: This register is written to port 3C2h and read from port 3CCh. + +3CCh (W): Graphics 1 Position (EGA Only) +bit 0-1 Select which bit planes should be controlled by Graphics Controller + #1. Always set to 0. + +3CEh index 0 (r/W): Graphics: Set/Reset Register +bit 0 If in Write Mode 0 and bit 0 of 3CEh index 1 is set a write to + display memory will set all the bits in plane 0 of the byte to this + bit, if the corresponding bit is set in the Map Mask Register (3CEh + index 8). + 1 Same for plane 1 and bit 1 of 3CEh index 1. + 2 Same for plane 2 and bit 2 of 3CEh index 1. + 3 Same for plane 3 and bit 3 of 3CEh index 1. + +3CEh index 1 (r/W): Graphics: Enable Set/Reset Register +bit 0 If set enables Set/reset of plane 0 in Write Mode 0. + 1 Same for plane 1. + 2 Same for plane 2. + 3 Same for plane 3. + +3CEh index 2 (r/W): Graphics: Color Compare Register +bit 0-3 In Read Mode 1 each pixel at the address of the byte read is compared + to this color and the corresponding bit in the output set to 1 if + they match, 0 if not. The Color Don't Care Register (3CEh index 7) + can exclude bitplanes from the comparison. + +3CEh index 3 (r/W): Graphics: Data Rotate +bit 0-2 Number of positions to rotate data right before it is written to + display memory. Only active in Write Mode 0. + 3-4 In Write Mode 2 this field controls the relation between the data + written from the CPU, the data latched from the previous read and the + data written to display memory: + 0: CPU Data is written unmodified + 1: CPU data is ANDed with the latched data + 2: CPU data is ORed with the latch data. + 3: CPU data is XORed with the latched data. + +3CEh index 4 (r/W): Graphics: Read Map Select Register +bit 0-1 Number of the plane Read Mode 0 will read from. + +3CEh index 5 (r/W): Graphics: Mode Register +bit 0-1 Write Mode: Controls how data from the CPU is transformed before + being written to display memory: + 0: Mode 0 works as a Read-Modify-Write operation. + First a read access loads the data latches of the EGA/VGA with + the value in video memory at the addressed location. Then a + write access will provide the destination address and the CPU + data byte. The data written is modified by the function code in + the Data Rotate register (3CEh index 3) as a function of the CPU + data and the latches, then data is rotated as specified by the + same register. + 1: Mode 1 is used for video to video transfers. + A read access will load the data latches with the contents of + the addressed byte of video memory. A write access will write + the contents of the latches to the addressed byte. Thus a single + MOVSB instruction can copy all pixels in the source address byte + to the destination address. + 2: Mode 2 writes a color to all pixels in the addressed byte of + video memory. Bit 0 of the CPU data is written to plane 0 et + cetera. Individual bits can be enabled or disabled through the + Bit Mask register (3CEh index 8). + 3: (VGA Only) Mode 3 can be used to fill an area with a color and + pattern. The CPU data is rotated according to 3CEh index 3 bits + 0-2 and anded with the Bit Mask Register (3CEh index 8). For + each bit in the result the corresponding pixel is set to the + color in the Set/Reset Register (3CEh index 0 bits 0-3) if the + bit is set and to the contents of the processor latch if the bit + is clear. + 2 (EGA Only) Forces all outputs to a high impedance state if set. + 3 Read Mode + 0: Data is read from one of 4 bit planes depending on the Read Map + Select Register (3CEh index 4). + 1: Data returned is a comparison between the 8 pixels occupying the + read byte and the color in the Color Compare Register (3CEh + index 2). A bit is set if the color of the corresponding pixel + matches the register. + 4 Enables Odd/Even mode if set (See 3C4h index 4 bit 2). + 5 Enables CGA style 4 color pixels using even/odd bit pairs if set. + 6 (VGA Only) Enables 256 color mode if set. + +3CEh index 6 (r/W): Graphics: Miscellaneous Register +bit 0 Indicates Graphics Mode if set, Alphanumeric mode else. + 1 Enables Odd/Even mode if set. + 2-3 Memory Mapping: + 0: use A000h-BFFFh + 1: use A000h-AFFFh EGA/VGA Graphics modes + 2: use B000h-B7FFh Monochrome modes + 3: use B800h-BFFFh CGA modes + +3CEh index 7 (r/W): Graphics: Color Don't Care Register +bit 0 Ignore bit plane 0 in Read mode 1 if clear. + 1 Ignore bit plane 1 in Read mode 1 if clear. + 2 Ignore bit plane 2 in Read mode 1 if clear. + 3 Ignore bit plane 3 in Read mode 1 if clear. + +3CEh index 8 (r/W): Graphics: Bit Mask Register +bit 0-7 Each bit if set enables writing to the corresponding bit of a byte in + display memory. + +3d4h index 0 (r/W): CRTC: Horizontal Total Register +bit 0-7 (EGA) Horizontal Total Character Clocks-2 + 0-7 (VGA) Horizontal Total Character Clocks-5 + +3d4h index 1 (r/W): CRTC: Horizontal Display End Register +bit 0-7 Number of Character Clocks Displayed -1 + +3d4h index 2 (r/W): CRTC: Start Horizontal Blanking Register +bit 0-7 The count at which Horizontal Blanking starts + +3d4h index 3 (r/W): CRTC: End Horizontal Blanking Register +bit 0-4 Horizontal Blanking ends when the last 5 (6 for VGA) bits of the + character counter equals this field. + (VGA) The sixth bit is found in port 3d4h index 5 bit 7. + 5-6 Number of character clocks to delay start of display after Horizontal + Total has been reached. + 7 (VGA Only) Access to Vertical Retrace registers if set. If clear + reads to 3d4h index 10h and 11h access the Lightpen read back + registers ?? + +3d4h index 4 (r/W): CRTC: Start Horizontal Retrace Register +bit 0-7 Horizontal Retrace starts when the Character Counter reaches this + value. + +3d4h index 5 (r/W): CRTC: End Horizontal Retrace Register +bit 0-4 Horizontal Retrace ends when the last 5 bits of the character counter + equals this value. + 5-6 Number of character clocks to delay start of display after Horizontal + Retrace. + 7 (EGA) Provides Smooth Scrolling in Odd/Even mode. When set display + starts from an odd byte. + 7 (VGA) bit 5 of the End Horizontal Blanking count (See 3d4h index 3 + bit 0-4). + +3d4h index 6 (r/W): CRTC: Vertical Total Register +bit 0-7 Lower 8 bits of the Vertical Total. Bit 8 is found in 3d4h index 7 + bit 0. (VGA) Bit 9 is found in 3d4h index 7 bit 5. +Note: For the VGA this value is the number of scan lines in the display -2. + +3d4h index 7 (r/W): CRTC: Overflow Register +bit 0 Bit 8 of Vertical Total (3d4h index 6) + 1 Bit 8 of Vertical Display End (3d4h index 12h) + 2 Bit 8 of Vertical Retrace Start (3d4h index 10h) + 3 Bit 8 of Start Vertical Blanking (3d4h index 15h) + 4 Bit 8 of Line Compare Register (3d4h index 18h) + 5 (VGA) Bit 9 of Vertical Total (3d4h index 6) + 6 (VGA) Bit 9 of Vertical Display End (3d4h index 12h) + 7 (VGA) Bit 9 of Vertical Retrace Start (3d4h index 10h) + +3d4h index 8 (r/W): CRTC: Preset Row Scan Register +bit 0-4 Number of lines we have scrolled down in the first character row. + Provides Smooth Vertical Scrolling. + 5-6 (VGA Only) Number of bytes to skip at the start of scanline. Provides + Smooth Horizontal Scrolling together with the Horizontal Panning + Register (3C0h index 13h). + +3d4h index 9 (r/W): CRTC: Maximum Scan Line Register +bit 0-4 Number of scan lines in a character row -1. In graphics modes this is + the number of times (-1) the line is displayed before passing on to + the next line (0: normal, 1: double, 2: triple...). + This is independent of bit 7, except in CGA modes which seems to + require this field to be 1 and bit 7 to be set to work. + 5 (VGA) Bit 9 of Start Vertical Blanking + 6 (VGA) Bit 9 of Line Compare Register + 7 (VGA) Doubles each scan line if set. + I.e. displays 200 lines on a 400 display. + +3d4h index Ah (r/W): CRTC: Cursor Start Register +bit 0-4 First scanline of cursor within character. + 5 (VGA) Turns Cursor off if set + +3d4h index Bh (r/W): CRTC: Cursor End Register +bit 0-4 Last scanline of cursor within character + 5-6 Delay of cursor data in character clocks. + +3d4h index Ch (r/W): CRTC: Start Address High Register +bit 0-7 Upper 8 bits of the start address of the display buffer + +3d4h index Dh (r/W): CRTC: Start Address Low Register +bit 0-7 Lower 8 bits of the start address of the display buffer + +3d4h index Eh (r/W): CRTC: Cursor Location High Register +bit 0-7 Upper 8 bits of the address of the cursor + +3d4h index Fh (r/W): CRTC: Cursor Location Low Register +bit 0-7 Lower 8 bits of the address of the cursor + +3d4h index 10h (R): CRTC: Light Pen High Register (EGA Only) +bit 0-7 (EGA Only) Upper 8 bits of the address of the lightpen position. + +3d4h index 10h (r/W): CRTC: Vertical Retrace Start Register +bit 0-7 Lower 8 bits of Vertical Retrace Start. Vertical Retrace starts when + the line counter reaches this value. Bit 8 is found in 3d4h index 7 + bit 2. (VGA Only) Bit 9 is found in 3d4h index 7 bit 7. + +3d4h index 11h (R): CRTC: Light Pen Low Register (EGA Only) +bit 0-7 (EGA Only) Lower 8 bits of the address of the lightpen position. + +3d4h index 11h (r/W): CRTC: Vertical Retrace End Register +bit 0-3 Vertical Retrace ends when the last 4 bits of the line counter equals + this value. + 4 if clear Clears pending Vertical Interrupts. + 5 Vertical Interrupts (IRQ 2) disabled if set. Can usually be left + disabled, but some systems (including PS/2) require it to be enabled. + 6 (VGA Only) If set selects 5 refresh cycles per scanline rather + than 3. + 7 (VGA Only) Disables writing to registers 0-7 if set 3d4h index 7 + bit 4 is not affected by this bit. + +3d4h index 12h (r/W): CRTC: Vertical Display End Register +bit 0-7 Lower 8 bits of Vertical Display End. The display ends when the line + counter reaches this value. Bit 8 is found in 3d4h index 7 bit 1. + (VGA Only) Bit 9 is found in 3d4h index 7 bit 6. + +3d4h index 13h (r/W): CRTC: Offset register +bit 0-7 Number of bytes in a scanline / K. Where K is 2 for byte mode, 4 for + word mode and 8 for Double Word mode. + +3d4h index 14h (r/W): CRTC: Underline Location Register +bit 0-4 Position of underline within Character cell. + 5 (VGA Only) If set memory address is only changed every fourth + character clock. + 6 (VGA Only) Double Word mode addressing if set + +3d4h index 15h (r/W): CRTC: Start Vertical Blank Register +bit 0-7 Lower 8 bits of Vertical Blank Start. Vertical blanking starts when + the line counter reaches this value. Bit 8 is found in 3d4h index 7 + bit 3. + +3d4h index 16h (r/W): CRTC: End Vertical Blank Register +bit 0-4 (EGA) Vertical blanking stops when the lower 5 bits of the line + counter equals this field. + 0-6 (VGA) Vertical blanking stops when the lower 7 bits of the line + counter equals this field. + +3d4h index 17h (r/W): CRTC: Mode Control Register +bit 0 If clear use CGA compatible memory addressing system + by substituting character row scan counter bit 0 for address bit 13, + thus creating 2 banks for even and odd scan lines. + 1 If clear use Hercules compatible memory addressing system by + substituting character row scan counter bit 1 for address bit 14, + thus creating 4 banks. + 2 If set increase scan line counter only every second line. + 3 If set increase memory address counter only every other character + clock. + 4 (EGA Only) If set disable the EGA output drivers. This bit is used + for other purposes in some Super VGA chips. + 5 When in Word Mode bit 15 is rotated to bit 0 if this bit is set else + bit 13 is rotated into bit 0. + 6 If clear system is in word mode. Addresses are rotated 1 position up + bringing either bit 13 or 15 into bit 0. + 7 Clearing this bit will reset the display system until the bit is set + again. + +3d4h index 18h (r/W): CRTC: Line Compare Register +bit 0-7 Lower 8 bits of the Line Compare. When the Line counter reaches this + value, the display address wraps to 0. Provides Split Screen + facilities. Bit 8 is found in 3d4h index 7 bit 4. + (VGA Only) Bit 9 is found in 3d4h index 9 bit 6. + +3d4h index 22h (R): Memory Latch Register (VGA - Undoc) +bit 0-7 Reads the contents of the Graphics Controller Memory Data Latch for + the plane selected by 3C0h index 4 bit 0-1 (Read Map Select). +Note: This register is not documented by IBM and may not be available on all + clones. + +3d4h index 24h (R): Attribute Controller Toggle Register. (VGA - Undoc) +bit 0-4 Attribute Controller Index. + The current value of the Attribute Index Register. + 5 Palette Address Source. Same as 3C0h bit 5. + 7 If set next read or write to 3C0h will access the data register. +Note: This register is not documented by IBM and may not be available on all + clones. + +3d4h index 30h-3Fh (W): Clear Vertical Display Enable. (VGA - Undoc) +bit 0 Setting this bit will clear the Vertical Display Enable thus blanking + the display for the rest of the frame and giving the CPU total access + to display memory until the start of the next frame. +Note: This register is not documented by IBM and may not be available on all + clones. + +3dAh (R): Input Status #1 Register +bit 0 Either Vertical or Horizontal Retrace active if set + 1 (EGA Only) Light Pen has triggered if set + 2 (EGA Only) Light Pen switch is open if set + 3 Vertical Retrace in progress if set + 4-5 (EGA Only) Shows two of the 6 color outputs, depending on 3C0h index + 12h bit 4-5: + Attr: Bit 4-5: Out bit 4 Out bit 5 + 0 Blue Red + 1 I Blue Green + 2 I Red I Green + +3dAh (W): Feature Control Register +bit 0 (EGA Only) Output to pin 21 of the Feature Connector. + 1 (EGA Only) Output to pin 20 of the Feature Connector. + 3 (VGA Only) Vertical Sync Select. If set Vertical Sync to the monitor + is the logical OR of the vertical sync and the vertical display + enable. +Note: On the VGA this register can be read from port 3CAh. diff --git a/src/fterm.cpp b/src/fterm.cpp index daebdc49..5db43829 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -316,12 +316,6 @@ bool FTerm::setOldFont() else if ( isLinuxTerm() ) { retval = linux->loadOldFont(fc::character); - - if ( retval ) - { - data->supportShadowCharacter (linux->hasShadowCharacter()); - data->supportHalfBlockCharacter (linux->hasHalfBlockCharacter()); - } } #endif // defined(__linux__) @@ -916,8 +910,6 @@ void FTerm::initScreenSettings() // Important: Do not use setNewFont() or setVGAFont() after // the console character mapping has been initialized linux->initCharMap (fc::character); - data->supportShadowCharacter (linux->hasShadowCharacter()); - data->supportHalfBlockCharacter (linux->hasHalfBlockCharacter()); #elif defined(__FreeBSD__) || defined(__DragonFly__) freebsd->initCharMap (fc::character); #endif diff --git a/src/ftermlinux.cpp b/src/ftermlinux.cpp index 0fff2872..bc2062c0 100644 --- a/src/ftermlinux.cpp +++ b/src/ftermlinux.cpp @@ -40,8 +40,6 @@ namespace finalcut bool FTermLinux::new_font; bool FTermLinux::vga_font; - bool FTermLinux::shadow_character = true; - bool FTermLinux::half_block_character = true; bool FTermLinux::has_saved_palette = false; FTermData* FTermLinux::fterm_data = nullptr; @@ -158,6 +156,8 @@ void FTermLinux::init() term_detection = FTerm::getFTermDetection(); screen_unicode_map.entries = nullptr; screen_font.data = nullptr; + fterm_data->supportShadowCharacter (true); + fterm_data->supportHalfBlockCharacter (true); if ( FTerm::openConsole() == 0 ) { @@ -279,7 +279,10 @@ bool FTermLinux::loadVGAFont() vga_font = false; if ( vga_font ) - shadow_character = half_block_character = true; + { + fterm_data->supportShadowCharacter (true); + fterm_data->supportHalfBlockCharacter (true); + } return vga_font; } @@ -316,7 +319,10 @@ bool FTermLinux::loadNewFont() new_font = false; if ( vga_font ) - shadow_character = half_block_character = true; + { + fterm_data->supportShadowCharacter (true); + fterm_data->supportHalfBlockCharacter (true); + } return new_font; } @@ -1221,7 +1227,7 @@ inline void FTermLinux::initSpecialCharacter() || FTerm::charEncode(c2, fc::PC) == FTerm::charEncode(c2, fc::ASCII) || FTerm::charEncode(c3, fc::PC) == FTerm::charEncode(c3, fc::ASCII) ) { - shadow_character = false; + fterm_data->supportShadowCharacter (false); } wchar_t c4 = fc::RightHalfBlock; @@ -1230,7 +1236,7 @@ inline void FTermLinux::initSpecialCharacter() if ( FTerm::charEncode(c4, fc::PC) == FTerm::charEncode(c4, fc::ASCII) || FTerm::charEncode(c5, fc::PC) == FTerm::charEncode(c5, fc::ASCII) ) { - half_block_character = false; + fterm_data->supportHalfBlockCharacter (false); } } diff --git a/src/include/final/ftermlinux.h b/src/include/final/ftermlinux.h index aab81be2..4b444074 100644 --- a/src/include/final/ftermlinux.h +++ b/src/include/final/ftermlinux.h @@ -94,8 +94,6 @@ class FTermLinux final // Inquiries static bool isLinuxConsole(); - static bool hasShadowCharacter(); - static bool hasHalfBlockCharacter(); static bool isVGAFontUsed(); static bool isNewFontUsed(); @@ -176,8 +174,6 @@ class FTermLinux final #if defined(__linux__) static bool vga_font; static bool new_font; - static bool shadow_character; - static bool half_block_character; static bool has_saved_palette; static FTermData* fterm_data; static FSystem* fsystem; @@ -203,14 +199,6 @@ inline const char* FTermLinux::getClassName() const inline int FTermLinux::getFramebufferBpp() { return framebuffer_bpp; } -//---------------------------------------------------------------------- -inline bool FTermLinux::hasShadowCharacter() -{ return shadow_character; } - -//---------------------------------------------------------------------- -inline bool FTermLinux::hasHalfBlockCharacter() -{ return half_block_character; } - //---------------------------------------------------------------------- inline bool FTermLinux::isVGAFontUsed() { return vga_font; } diff --git a/test/Makefile.am b/test/Makefile.am index 1cedd8b6..da1e79e9 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,6 +13,7 @@ noinst_PROGRAMS = \ ftermdata_test \ ftermdetection_test \ ftermcapquirks_test \ + ftermlinux_test \ foptimove_test \ foptiattr_test \ fcolorpair_test \ @@ -27,6 +28,7 @@ fkeyboard_test_SOURCES = fkeyboard-test.cpp ftermdata_test_SOURCES = ftermdata-test.cpp ftermdetection_test_SOURCES = ftermdetection-test.cpp ftermcapquirks_test_SOURCES = ftermcapquirks-test.cpp +ftermlinux_test_SOURCES = ftermlinux-test.cpp foptimove_test_SOURCES = foptimove-test.cpp foptiattr_test_SOURCES = foptiattr-test.cpp fcolorpair_test_SOURCES = fcolorpair-test.cpp @@ -41,6 +43,7 @@ TESTS = fobject_test \ ftermdata_test \ ftermdetection_test \ ftermcapquirks_test \ + ftermlinux_test \ foptimove_test \ foptiattr_test \ fcolorpair_test \ diff --git a/test/conemu.h b/test/conemu.h new file mode 100644 index 00000000..b106631e --- /dev/null +++ b/test/conemu.h @@ -0,0 +1,1103 @@ +/*********************************************************************** +* conemu.h - Emulator for various consoles and terminals * +* * +* This file is part of the Final Cut widget toolkit * +* * +* Copyright 2019 Markus Gans * +* * +* The Final Cut is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public License * +* as published by the Free Software Foundation; either version 3 of * +* the License, or (at your option) any later version. * +* * +* The Final Cut is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this program. If not, see * +* . * +***********************************************************************/ + +/* Standalone test class + * ═════════════════════ + * + * ▕▔▔▔▔▔▔▔▔▏ + * ▕ ConEmu ▏ + * ▕▁▁▁▁▁▁▁▁▏ + */ + +#ifndef CONEMU_H +#define CONEMU_H + +#include +#include + +#include + +namespace test +{ + +//---------------------------------------------------------------------- +// class ConEmu +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class ConEmu +{ + public: + // Enumeration + enum console + { + ansi, + xterm, + rxvt, + urxvt, + mlterm, + putty, + kde_konsole, + gnome_terminal, + newer_vte_terminal, + kterm, + tera_term, + cygwin, + mintty, + linux_con, + freebsd_con, + netbsd_con, + openbsd_con, + sun_con, + screen, + tmux + }; + + // Constructors + ConEmu() + { + // Map shared memory + void* ptr = mmap ( NULL + , sizeof(*shared_state) + , PROT_READ | PROT_WRITE + , MAP_SHARED | MAP_ANONYMOUS, -1 + , 0 ); + shared_state = static_cast(ptr); + *shared_state = false; + } + + // Disable copy constructor + ConEmu (const ConEmu&) = delete; + + // Destructor + ~ConEmu() + { + closeMasterPTY(); + closeSlavePTY(); + // Unmap shared memory + munmap (shared_state, sizeof(*shared_state)); + } + + // Disable assignment operator (=) + ConEmu& operator = (const ConEmu&) = delete; + + protected: + // Mutators + void enableConEmuDebug (bool); + + // Inquiries + bool isConEmuChildProcess (pid_t); + + // Methods + void printConEmuDebug(); + void closeConEmuStdStreams(); + pid_t forkConEmu(); + void startConEmuTerminal (console); + + private: + // Accessors + char* getAnswerback (console); + char* getDSR (console); + char* getDECID (console); + char* getDA (console); + char* getDA1 (console); + char* getSEC_DA (console); + + // Methods + bool openMasterPTY(); + bool openSlavePTY(); + void closeMasterPTY(); + void closeSlavePTY(); + void parseTerminalBuffer (std::size_t, console); + + // Data Members + int fd_stdin{fileno(stdin)}; + int fd_stdout{fileno(stdout)}; + int fd_stderr{fileno(stderr)}; + int fd_master{-1}; + int fd_slave{-1}; + bool debug{false}; + char buffer[2048]{}; + static bool* shared_state; + static char* colorname[]; +}; +#pragma pack(pop) + +// static class attributes +bool* ConEmu::shared_state = nullptr; + + +// private Data Member of ConEmu +//---------------------------------------------------------------------- +char* ConEmu::colorname[] = +{ + C_STR("0000/0000/0000"), // 0 + C_STR("bbbb/0000/0000"), // 1 + C_STR("0000/bbbb/0000"), // 2 + C_STR("bbbb/bbbb/0000"), // 3 + C_STR("0000/0000/bbbb"), // 4 + C_STR("bbbb/0000/bbbb"), // 5 + C_STR("0000/bbbb/bbbb"), // 6 + C_STR("bbbb/bbbb/bbbb"), // 7 + C_STR("5555/5555/5555"), // 8 + C_STR("ffff/5555/5555"), // 9 + C_STR("5555/ffff/5555"), // 10 + C_STR("ffff/ffff/5555"), // 11 + C_STR("5555/5555/ffff"), // 12 + C_STR("ffff/5555/ffff"), // 13 + C_STR("5555/ffff/ffff"), // 14 + C_STR("ffff/ffff/ffff"), // 15 + C_STR("0000/0000/0000"), // 16 + C_STR("0000/0000/5f5f"), // 17 + C_STR("0000/0000/8787"), // 18 + C_STR("0000/0000/afaf"), // 19 + C_STR("0000/0000/d7d7"), // 20 + C_STR("0000/0000/ffff"), // 21 + C_STR("0000/5f5f/0000"), // 22 + C_STR("0000/5f5f/5f5f"), // 23 + C_STR("0000/5f5f/8787"), // 24 + C_STR("0000/5f5f/afaf"), // 25 + C_STR("0000/5f5f/d7d7"), // 26 + C_STR("0000/5f5f/ffff"), // 27 + C_STR("0000/8787/0000"), // 28 + C_STR("0000/8787/5f5f"), // 29 + C_STR("0000/8787/8787"), // 30 + C_STR("0000/8787/afaf"), // 31 + C_STR("0000/8787/d7d7"), // 32 + C_STR("0000/8787/ffff"), // 33 + C_STR("0000/afaf/0000"), // 34 + C_STR("0000/afaf/5f5f"), // 35 + C_STR("0000/afaf/8787"), // 36 + C_STR("0000/afaf/afaf"), // 37 + C_STR("0000/afaf/d7d7"), // 38 + C_STR("0000/afaf/ffff"), // 39 + C_STR("0000/d7d7/0000"), // 40 + C_STR("0000/d7d7/5f5f"), // 41 + C_STR("0000/d7d7/8787"), // 42 + C_STR("0000/d7d7/afaf"), // 43 + C_STR("0000/d7d7/d7d7"), // 44 + C_STR("0000/d7d7/ffff"), // 45 + C_STR("0000/ffff/0000"), // 46 + C_STR("0000/ffff/5f5f"), // 47 + C_STR("0000/ffff/8787"), // 48 + C_STR("0000/ffff/afaf"), // 49 + C_STR("0000/ffff/d7d7"), // 50 + C_STR("0000/ffff/ffff"), // 51 + C_STR("5f5f/0000/0000"), // 52 + C_STR("5f5f/0000/5f5f"), // 53 + C_STR("5f5f/0000/8787"), // 54 + C_STR("5f5f/0000/afaf"), // 55 + C_STR("5f5f/0000/d7d7"), // 56 + C_STR("5f5f/0000/ffff"), // 57 + C_STR("5f5f/5f5f/0000"), // 58 + C_STR("5f5f/5f5f/5f5f"), // 59 + C_STR("5f5f/5f5f/8787"), // 60 + C_STR("5f5f/5f5f/afaf"), // 61 + C_STR("5f5f/5f5f/d7d7"), // 62 + C_STR("5f5f/5f5f/ffff"), // 63 + C_STR("5f5f/8787/0000"), // 64 + C_STR("5f5f/8787/5f5f"), // 65 + C_STR("5f5f/8787/8787"), // 66 + C_STR("5f5f/8787/afaf"), // 67 + C_STR("5f5f/8787/d7d7"), // 68 + C_STR("5f5f/8787/ffff"), // 69 + C_STR("5f5f/afaf/0000"), // 70 + C_STR("5f5f/afaf/5f5f"), // 71 + C_STR("5f5f/afaf/8787"), // 72 + C_STR("5f5f/afaf/afaf"), // 73 + C_STR("5f5f/afaf/d7d7"), // 74 + C_STR("5f5f/afaf/ffff"), // 75 + C_STR("5f5f/d7d7/0000"), // 76 + C_STR("5f5f/d7d7/5f5f"), // 77 + C_STR("5f5f/d7d7/8787"), // 78 + C_STR("5f5f/d7d7/afaf"), // 79 + C_STR("5f5f/d7d7/d7d7"), // 80 + C_STR("5f5f/d7d7/ffff"), // 81 + C_STR("5f5f/ffff/0000"), // 82 + C_STR("5f5f/ffff/5f5f"), // 83 + C_STR("5f5f/ffff/8787"), // 84 + C_STR("5f5f/ffff/afaf"), // 85 + C_STR("5f5f/ffff/d7d7"), // 86 + C_STR("5f5f/ffff/ffff"), // 87 + C_STR("8787/0000/0000"), // 88 + C_STR("8787/0000/5f5f"), // 89 + C_STR("8787/0000/8787"), // 90 + C_STR("8787/0000/afaf"), // 91 + C_STR("8787/0000/d7d7"), // 92 + C_STR("8787/0000/ffff"), // 93 + C_STR("8787/5f5f/0000"), // 94 + C_STR("8787/5f5f/5f5f"), // 95 + C_STR("8787/5f5f/8787"), // 96 + C_STR("8787/5f5f/afaf"), // 97 + C_STR("8787/5f5f/d7d7"), // 98 + C_STR("8787/5f5f/ffff"), // 99 + C_STR("8787/8787/0000"), // 100 + C_STR("8787/8787/5f5f"), // 101 + C_STR("8787/8787/8787"), // 102 + C_STR("8787/8787/afaf"), // 103 + C_STR("8787/8787/d7d7"), // 104 + C_STR("8787/8787/ffff"), // 105 + C_STR("8787/afaf/0000"), // 106 + C_STR("8787/afaf/5f5f"), // 107 + C_STR("8787/afaf/8787"), // 108 + C_STR("8787/afaf/afaf"), // 109 + C_STR("8787/afaf/d7d7"), // 110 + C_STR("8787/afaf/ffff"), // 111 + C_STR("8787/d7d7/0000"), // 112 + C_STR("8787/d7d7/5f5f"), // 113 + C_STR("8787/d7d7/8787"), // 114 + C_STR("8787/d7d7/afaf"), // 115 + C_STR("8787/d7d7/d7d7"), // 116 + C_STR("8787/d7d7/ffff"), // 117 + C_STR("8787/ffff/0000"), // 118 + C_STR("8787/ffff/5f5f"), // 119 + C_STR("8787/ffff/8787"), // 120 + C_STR("8787/ffff/afaf"), // 121 + C_STR("8787/ffff/d7d7"), // 122 + C_STR("8787/ffff/ffff"), // 123 + C_STR("afaf/0000/0000"), // 124 + C_STR("afaf/0000/5f5f"), // 125 + C_STR("afaf/0000/8787"), // 126 + C_STR("afaf/0000/afaf"), // 127 + C_STR("afaf/0000/d7d7"), // 128 + C_STR("afaf/0000/ffff"), // 129 + C_STR("afaf/5f5f/0000"), // 130 + C_STR("afaf/5f5f/5f5f"), // 131 + C_STR("afaf/5f5f/8787"), // 132 + C_STR("afaf/5f5f/afaf"), // 133 + C_STR("afaf/5f5f/d7d7"), // 134 + C_STR("afaf/5f5f/ffff"), // 135 + C_STR("afaf/8787/0000"), // 136 + C_STR("afaf/8787/5f5f"), // 137 + C_STR("afaf/8787/8787"), // 138 + C_STR("afaf/8787/afaf"), // 139 + C_STR("afaf/8787/d7d7"), // 140 + C_STR("afaf/8787/ffff"), // 141 + C_STR("afaf/afaf/0000"), // 142 + C_STR("afaf/afaf/5f5f"), // 143 + C_STR("afaf/afaf/8787"), // 144 + C_STR("afaf/afaf/afaf"), // 145 + C_STR("afaf/afaf/d7d7"), // 146 + C_STR("afaf/afaf/ffff"), // 147 + C_STR("afaf/d7d7/0000"), // 148 + C_STR("afaf/d7d7/5f5f"), // 149 + C_STR("afaf/d7d7/8787"), // 150 + C_STR("afaf/d7d7/afaf"), // 151 + C_STR("afaf/d7d7/d7d7"), // 152 + C_STR("afaf/d7d7/ffff"), // 153 + C_STR("afaf/ffff/0000"), // 154 + C_STR("afaf/ffff/5f5f"), // 155 + C_STR("afaf/ffff/8787"), // 156 + C_STR("afaf/ffff/afaf"), // 157 + C_STR("afaf/ffff/d7d7"), // 158 + C_STR("afaf/ffff/ffff"), // 159 + C_STR("d7d7/0000/0000"), // 160 + C_STR("d7d7/0000/5f5f"), // 161 + C_STR("d7d7/0000/8787"), // 162 + C_STR("d7d7/0000/afaf"), // 163 + C_STR("d7d7/0000/d7d7"), // 164 + C_STR("d7d7/0000/ffff"), // 165 + C_STR("d7d7/5f5f/0000"), // 166 + C_STR("d7d7/5f5f/5f5f"), // 167 + C_STR("d7d7/5f5f/8787"), // 168 + C_STR("d7d7/5f5f/afaf"), // 169 + C_STR("d7d7/5f5f/d7d7"), // 170 + C_STR("d7d7/5f5f/ffff"), // 171 + C_STR("d7d7/8787/0000"), // 172 + C_STR("d7d7/8787/5f5f"), // 173 + C_STR("d7d7/8787/8787"), // 174 + C_STR("d7d7/8787/afaf"), // 175 + C_STR("d7d7/8787/d7d7"), // 176 + C_STR("d7d7/8787/ffff"), // 177 + C_STR("d7d7/afaf/0000"), // 178 + C_STR("d7d7/afaf/5f5f"), // 179 + C_STR("d7d7/afaf/8787"), // 180 + C_STR("d7d7/afaf/afaf"), // 181 + C_STR("d7d7/afaf/d7d7"), // 182 + C_STR("d7d7/afaf/ffff"), // 183 + C_STR("d7d7/d7d7/0000"), // 184 + C_STR("d7d7/d7d7/5f5f"), // 185 + C_STR("d7d7/d7d7/8787"), // 186 + C_STR("d7d7/d7d7/afaf"), // 187 + C_STR("d7d7/d7d7/d7d7"), // 188 + C_STR("d7d7/d7d7/ffff"), // 189 + C_STR("d7d7/ffff/0000"), // 190 + C_STR("d7d7/ffff/5f5f"), // 191 + C_STR("d7d7/ffff/8787"), // 192 + C_STR("d7d7/ffff/afaf"), // 193 + C_STR("d7d7/ffff/d7d7"), // 194 + C_STR("d7d7/ffff/ffff"), // 195 + C_STR("ffff/0000/0000"), // 196 + C_STR("ffff/0000/5f5f"), // 197 + C_STR("ffff/0000/8787"), // 198 + C_STR("ffff/0000/afaf"), // 199 + C_STR("ffff/0000/d7d7"), // 200 + C_STR("ffff/0000/ffff"), // 201 + C_STR("ffff/5f5f/0000"), // 202 + C_STR("ffff/5f5f/5f5f"), // 203 + C_STR("ffff/5f5f/8787"), // 204 + C_STR("ffff/5f5f/afaf"), // 205 + C_STR("ffff/5f5f/d7d7"), // 206 + C_STR("ffff/5f5f/ffff"), // 207 + C_STR("ffff/8787/0000"), // 208 + C_STR("ffff/8787/5f5f"), // 209 + C_STR("ffff/8787/8787"), // 210 + C_STR("ffff/8787/afaf"), // 211 + C_STR("ffff/8787/d7d7"), // 212 + C_STR("ffff/8787/ffff"), // 213 + C_STR("ffff/afaf/0000"), // 214 + C_STR("ffff/afaf/5f5f"), // 215 + C_STR("ffff/afaf/8787"), // 216 + C_STR("ffff/afaf/afaf"), // 217 + C_STR("ffff/afaf/d7d7"), // 218 + C_STR("ffff/afaf/ffff"), // 219 + C_STR("ffff/d7d7/0000"), // 220 + C_STR("ffff/d7d7/5f5f"), // 221 + C_STR("ffff/d7d7/8787"), // 222 + C_STR("ffff/d7d7/afaf"), // 223 + C_STR("ffff/d7d7/d7d7"), // 224 + C_STR("ffff/d7d7/ffff"), // 225 + C_STR("ffff/ffff/0000"), // 226 + C_STR("ffff/ffff/5f5f"), // 227 + C_STR("ffff/ffff/8787"), // 228 + C_STR("ffff/ffff/afaf"), // 229 + C_STR("ffff/ffff/d7d7"), // 230 + C_STR("ffff/ffff/ffff"), // 231 + C_STR("0808/0808/0808"), // 232 + C_STR("1212/1212/1212"), // 233 + C_STR("1c1c/1c1c/1c1c"), // 234 + C_STR("2626/2626/2626"), // 235 + C_STR("3030/3030/3030"), // 236 + C_STR("3a3a/3a3a/3a3a"), // 237 + C_STR("4444/4444/4444"), // 238 + C_STR("4e4e/4e4e/4e4e"), // 239 + C_STR("5858/5858/5858"), // 240 + C_STR("6262/6262/6262"), // 241 + C_STR("6c6c/6c6c/6c6c"), // 242 + C_STR("7676/7676/7676"), // 243 + C_STR("8080/8080/8080"), // 244 + C_STR("8a8a/8a8a/8a8a"), // 245 + C_STR("9494/9494/9494"), // 246 + C_STR("9e9e/9e9e/9e9e"), // 247 + C_STR("a8a8/a8a8/a8a8"), // 248 + C_STR("b2b2/b2b2/b2b2"), // 249 + C_STR("bcbc/bcbc/bcbc"), // 250 + C_STR("c6c6/c6c6/c6c6"), // 251 + C_STR("d0d0/d0d0/d0d0"), // 252 + C_STR("dada/dada/dada"), // 253 + C_STR("e4e4/e4e4/e4e4"), // 254 + C_STR("eeee/eeee/eeee"), // 255 + 0 +}; + + +// ConEmu inline functions + +// protected methods of ConEmu +//---------------------------------------------------------------------- +inline void ConEmu::enableConEmuDebug (bool enable) +{ + debug = enable; +} + +//---------------------------------------------------------------------- +inline bool ConEmu::isConEmuChildProcess (pid_t pid) +{ + return bool( pid == 0 ); +} + +//---------------------------------------------------------------------- +inline void ConEmu::printConEmuDebug() +{ + // Printing terminal debug information for some escape sequences + + if ( ! debug ) + return; + + setenv ("DSR", "\\033[5n", 1); + setenv ("CURSOR_POS", "\\033[6n", 1); + setenv ("DECID", "\\033Z", 1); + setenv ("DA", "\\033[c", 1); + setenv ("DA1", "\\033[1c", 1); + setenv ("SEC_DA", "\\033[>c", 1); + setenv ("ANSWERBACK", "\\005", 1); + setenv ("TITLE", "\\033[21t", 1); + setenv ("COLOR16", "\\033]4;15;?\\a", 1); + setenv ("COLOR88", "\\033]4;87;?\\a", 1); + setenv ("COLOR256", "\\033]4;254;?\\a", 1); + + setenv ("GO_MIDDLE", "\\033[80D\\033[15C", 1); + setenv ("GO_RIGHT", "\\033[79D\\033[40C", 1); + + finalcut::FString line (69, '-'); + std::cout << std::endl << line << std::endl; + std::cout << "Probe Escape sequence Reply"; + std::cout << std::endl << line << std::endl; + + // Command line + constexpr char debug_command[] = "/bin/bash -c ' \ + for i in DSR CURSOR_POS DECID DA DA1 SEC_DA ANSWERBACK \ + TITLE COLOR16 COLOR88 COLOR256; \ + do \ + eval \"echo -en \\\"$i${GO_MIDDLE}\\\"; \ + echo -n \\\"\\${$i}\\\"; \ + echo -en \\\"${GO_RIGHT}\\${$i}\\\"\"; \ + sleep 0.5; \ + echo -e \"\\r\"; \ + done'"; + system(debug_command); +} + +//---------------------------------------------------------------------- +inline void ConEmu::closeConEmuStdStreams() +{ + close(fd_stdin); // stdin + close(fd_stdout); // stdout + close(fd_stderr); // stderr +} + +//---------------------------------------------------------------------- +inline pid_t ConEmu::forkConEmu() +{ + // Initialize buffer with '\0' + std::fill_n (buffer, sizeof(buffer), '\0'); + + if ( ! openMasterPTY() ) + return -1; + + if ( ! openSlavePTY() ) + return -1; + + pid_t pid = fork(); // Create a child process + + if ( pid < 0) // Fork failed + return -1; + + if ( isConEmuChildProcess(pid) ) // Child process + { + struct termios term_settings; + closeMasterPTY(); + + // Creates a session and makes the current process to the leader + setsid(); + +#ifdef TIOCSCTTY + // Set controlling tty + if ( ioctl(fd_slave, TIOCSCTTY, 0) == -1 ) + { + *shared_state = true; + return -1; + } +#endif + + // Get current terminal settings + if ( tcgetattr(fd_slave, &term_settings) == -1 ) + { + *shared_state = true; + return -1; + } + + // Set raw mode on the slave side of the PTY + cfmakeraw (&term_settings); + tcsetattr (fd_slave, TCSANOW, &term_settings); + +#ifdef TIOCSWINSZ + // Set slave tty window size + struct winsize size; + size.ws_row = 25; + size.ws_col = 80; + + if ( ioctl(fd_slave, TIOCSWINSZ, &size) == -1) + { + *shared_state = true; + return -1; + } +#endif + + closeConEmuStdStreams(); + + fd_stdin = dup(fd_slave); // PTY becomes stdin (0) + fd_stdout = dup(fd_slave); // PTY becomes stdout (1) + fd_stderr = dup(fd_slave); // PTY becomes stderr (2) + + closeSlavePTY(); + + // The child process is now ready for input + *shared_state = true; + } + else + { + constexpr int timeout = 150; // 1.5 seconds + int i = 0; + + // Wait until the child process is ready for input + while ( ! *shared_state && i < timeout ) + { + // Wait 10 ms (= 10,000,000 ns) + nanosleep ((const struct timespec[]){{0, 10000000L}}, NULL); + i++; + } + + *shared_state = false; + } + + return pid; +} + + + +//---------------------------------------------------------------------- +inline void ConEmu::startConEmuTerminal (console con) +{ + closeSlavePTY(); + + while ( 1 ) + { + fd_set ifds; + struct timeval tv; + ssize_t len; + + FD_ZERO(&ifds); + FD_SET(fd_stdin, &ifds); + FD_SET(fd_master, &ifds); + tv.tv_sec = 0; + tv.tv_usec = 750000; // 750 ms + + // Wait for data from stdin or the master side of PTY + if ( select(fd_master + 1, &ifds, 0, 0, &tv) < 0 ) + break; + + // Data on standard input + if ( FD_ISSET(fd_stdin, &ifds) ) + { + len = read (fd_stdin, buffer, sizeof(buffer)); + + if ( len > 0 && std::size_t(len) < sizeof(buffer) ) + { + buffer[len] = '\0'; + write (fd_master, buffer, len); // Send data to the master side + } + } + + // Data on the master side of PTY + if ( FD_ISSET(fd_master, &ifds) ) + { + len = read (fd_master, buffer, sizeof(buffer)); + + if ( len == -1 || std::size_t(len) >= sizeof(buffer) ) + break; + else if ( len > 0 ) + { + buffer[len] = '\0'; + parseTerminalBuffer (len, con); + } + } + } +} + + +// private methods of ConEmu +//---------------------------------------------------------------------- +inline char* ConEmu::getAnswerback (console con) +{ + static char* Answerback[] = + { + 0, // Ansi, + 0, // XTerm + 0, // Rxvt + 0, // Urxvt + 0, // mlterm - Multi Lingual TERMinal + C_STR("PuTTY"), // PuTTY + 0, // KDE Konsole + 0, // GNOME Terminal + 0, // VTE Terminal >= 0.53.0 + 0, // kterm, + 0, // Tera Term + 0, // Cygwin + 0, // Mintty + 0, // Linux console + 0, // FreeBSD console + 0, // NetBSD console + 0, // OpenBSD console + 0, // Sun console + 0, // screen + 0 // tmux + }; + + return Answerback[con]; +} + +//---------------------------------------------------------------------- +inline char* ConEmu::getDSR (console con) +{ + static char* DSR[] = + { + 0, // Ansi, + C_STR("\033[0n"), // XTerm + C_STR("\033[0n"), // Rxvt + C_STR("\033[0n"), // Urxvt + C_STR("\033[0n"), // mlterm - Multi Lingual TERMinal + C_STR("\033[0n"), // PuTTY + C_STR("\033[0n"), // KDE Konsole + C_STR("\033[0n"), // GNOME Terminal + C_STR("\033[0n"), // VTE Terminal >= 0.53.0 + C_STR("\033[0n"), // kterm, + C_STR("\033[0n"), // Tera Term + 0, // Cygwin + C_STR("\033[0n"), // Mintty + C_STR("\033[0n"), // Linux console + C_STR("\033[0n"), // FreeBSD console + C_STR("\033[0n"), // NetBSD console + C_STR("\033[0n"), // OpenBSD console + 0, // Sun console + C_STR("\033[0n"), // screen + C_STR("\033[0n") // tmux + }; + + return DSR[con]; +} + +//---------------------------------------------------------------------- +inline char* ConEmu::getDECID (console con) +{ + static char* DECID[] = + { + 0, // Ansi, + C_STR("\033[?63;1;2;6;4;6;9;15;22c"), // XTerm + C_STR("\033[?1;2c"), // Rxvt + C_STR("\033[?1;2c"), // Urxvt + C_STR("\033[?63;1;2;3;4;7;29c"), // mlterm - Multi Lingual TERMinal + C_STR("\033[?6c"), // PuTTY + C_STR("\033[?1;2c"), // KDE Konsole + C_STR("\033[?62;c"), // GNOME Terminal + C_STR("\033[?65;1;9c"), // VTE Terminal >= 0.53.0 + C_STR("\033[?1;2c"), // kterm, + C_STR("\033[?1;2c"), // Tera Term + 0, // Cygwin + C_STR("\033[?1;2;6;22c"), // Mintty + C_STR("\033[?6c"), // Linux console + 0, // FreeBSD console + 0, // NetBSD console + 0, // OpenBSD console + 0, // Sun console + C_STR("\033[?1;2c"), // screen + 0 // tmux + }; + + return DECID[con]; +} + +//---------------------------------------------------------------------- +inline char* ConEmu::getDA (console con) +{ + static char* DA[] = + { + 0, // Ansi, + C_STR("\033[?63;1;2;6;4;6;9;15;22c"), // XTerm + C_STR("\033[?1;2c"), // Rxvt + C_STR("\033[?1;2c"), // Urxvt + C_STR("\033[?63;1;2;3;4;7;29c"), // mlterm - Multi Lingual TERMinal + C_STR("\033[?6c"), // PuTTY + C_STR("\033[?1;2c"), // KDE Konsole + C_STR("\033[?62;c"), // GNOME Terminal + C_STR("\033[?65;1;9c"), // VTE Terminal >= 0.53.0 + C_STR("\033[?1;2c"), // kterm, + C_STR("\033[?1;2c"), // Tera Term + C_STR("\033[?6c"), // Cygwin + C_STR("\033[?1;2;6;22c"), // Mintty + C_STR("\033[?6c"), // Linux console + C_STR("\033[?1;2c"), // FreeBSD console + C_STR("\033[?62;6c"), // NetBSD console + C_STR("\033[?62;6c"), // OpenBSD console + 0, // Sun console + C_STR("\033[?1;2c"), // screen + C_STR("\033[?1;2c") // tmux + }; + + return DA[con]; +} + +//---------------------------------------------------------------------- +inline char* ConEmu::getDA1 (console con) +{ + static char* DA1[] = + { + 0, // Ansi, + 0, // XTerm + C_STR("\033[?1;2c"), // Rxvt + C_STR("\033[?1;2c"), // Urxvt + C_STR("\033[?63;1;2;3;4;7;29c"), // mlterm - Multi Lingual TERMinal + C_STR("\033[?6c"), // PuTTY + C_STR("\033[?1;2c"), // KDE Konsole + C_STR("\033[?62;c"), // GNOME Terminal + C_STR("\033[?65;1;9c"), // VTE Terminal >= 0.53.0 + 0, // kterm, + C_STR("\033[?1;2c"), // Tera Term + C_STR("\033[?6c"), // Cygwin + C_STR("\033[?1;2;6;22c"), // Mintty + 0, // Linux console + 0, // FreeBSD console + 0, // NetBSD console + 0, // OpenBSD console + 0, // Sun console + 0, // screen + 0 // tmux + }; + + return DA1[con]; +} + +//---------------------------------------------------------------------- +inline char* ConEmu::getSEC_DA (console con) +{ + static char* SEC_DA[] = + { + 0, // Ansi, + C_STR("\033[>19;312;0c"), // XTerm + C_STR("\033[>82;20710;0c"), // Rxvt + C_STR("\033[>85;95;0c"), // Urxvt + C_STR("\033[>24;279;0c"), // mlterm - Multi Lingual TERMinal + C_STR("\033[>0;136;0c"), // PuTTY + C_STR("\033[>0;115;0c"), // KDE Konsole + C_STR("\033[>1;5202;0c"), // GNOME Terminal + C_STR("\033[>65;5300;1c"), // VTE Terminal >= 0.53.0 + C_STR("\033[?1;2c"), // kterm, + C_STR("\033[>32;278;0c"), // Tera Term + C_STR("\033[>67;200502;0c"), // Cygwin + C_STR("\033[>77;20402;0c"), // Mintty + 0, // Linux console + 0, // FreeBSD console + 0, // NetBSD console + 0, // OpenBSD console + 0, // Sun console + C_STR("\033[>83;40201;0c"), // screen + C_STR("\033[>84;0;0c") // tmux + }; + + return SEC_DA[con]; +} + +//---------------------------------------------------------------------- +inline bool ConEmu::openMasterPTY() +{ + int result; + + // Open a pseudoterminal device + fd_master = posix_openpt(O_RDWR); + + if ( fd_master < 0 ) + return false; + + // Change the slave pseudoterminal access rights + result = grantpt(fd_master); + + if ( result != 0 ) + return false; + + // Unlock the pseudoterminal master/slave pair + result = unlockpt(fd_master); + + if ( result != 0 ) + return false; + + return true; +} + +//---------------------------------------------------------------------- +inline bool ConEmu::openSlavePTY() +{ + closeSlavePTY(); + + // Get PTY filename + const char* pty_name = ptsname(fd_master); + + if ( pty_name == 0 ) + return false; + + // Open the slave PTY + fd_slave = open(pty_name, O_RDWR); + + if ( fd_slave < 0 ) + return false; + + return true; +} + +//---------------------------------------------------------------------- +inline void ConEmu::closeMasterPTY() +{ + if ( fd_master <= 0 ) + return; + + close (fd_master); + fd_master = -1; +} + +//---------------------------------------------------------------------- +inline void ConEmu::closeSlavePTY() +{ + if ( fd_slave <= 0 ) + return; + + close (fd_slave); + fd_slave = -1; +} + +//---------------------------------------------------------------------- +inline void ConEmu::parseTerminalBuffer (std::size_t length, console con) +{ + for (std::size_t i = 0; i < length; i++) + { + if ( buffer[i] == ENQ[0] ) // Enquiry character + { + char* answer = getAnswerback(con); + + if ( answer ) + write(fd_master, answer, std::strlen(answer)); + } + else if ( i < length - 1 // Terminal ID (DECID) + && buffer[i] == '\033' + && buffer[i + 1] == 'Z' ) + { + char* DECID = getDECID(con); + + if ( DECID ) + write (fd_master, DECID, std::strlen(DECID)); + + i += 2; + } + else if ( i < length - 3 // Device status report (DSR) + && buffer[i] == '\033' + && buffer[i + 1] == '[' + && buffer[i + 2] == '5' + && buffer[i + 3] == 'n' ) + { + char* DSR = getDSR(con); + + if ( DSR ) + write (fd_master, DSR, std::strlen(DSR)); + + i += 4; + } + else if ( i < length - 3 // Report cursor position (CPR) + && buffer[i] == '\033' + && buffer[i + 1] == '[' + && buffer[i + 2] == '6' + && buffer[i + 3] == 'n' ) + { + write (fd_master, "\033[25;80R", 8); // row 25 ; column 80 + i += 4; + } + else if ( i < length - 2 // Device attributes (DA) + && buffer[i] == '\033' + && buffer[i + 1] == '[' + && buffer[i + 2] == 'c' ) + { + char* DA = getDA(con); + + if ( DA ) + write (fd_master, DA, std::strlen(DA)); + + i += 3; + } + else if ( i < length - 3 // Device attributes (DA1) + && buffer[i] == '\033' + && buffer[i + 1] == '[' + && buffer[i + 2] == '1' + && buffer[i + 3] == 'c' ) + { + char* DA1 = getDA1(con); + + if ( DA1 ) + write (fd_master, DA1, std::strlen(DA1)); + i += 4; + } + else if ( i < length - 3 // Secondary device attributes (SEC_DA) + && buffer[i] == '\033' + && buffer[i + 1] == '[' + && buffer[i + 2] == '>' + && buffer[i + 3] == 'c' ) + { + char* SEC_DA = getSEC_DA(con); + + if ( SEC_DA ) + write (fd_master, SEC_DA, std::strlen(SEC_DA)); + + i += 4; + } + else if ( i < length - 4 // Report xterm window's title + && buffer[i] == '\033' + && buffer[i + 1] == '[' + && buffer[i + 2] == '2' + && buffer[i + 3] == '1' + && buffer[i + 4] == 't' ) + { + if ( con == urxvt ) + write (fd_master, "\033]l", 3); + else if ( con == tera_term ) + write (fd_master, "\033]l\033\\", 5); + else if ( con == screen ) + write (fd_master, "\033]lbash\033\\", 9); + else if ( con != ansi + && con != rxvt + && con != mlterm + && con != kde_konsole + && con != kterm + && con != cygwin + && con != mintty + && con != linux_con + && con != freebsd_con + && con != netbsd_con + && con != openbsd_con + && con != sun_con + && con != tmux ) + write (fd_master, "\033]lTITLE\033\\", 10); + + i += 5; + } + else if ( i < length - 7 // Get xterm color name 0-9 + && buffer[i] == '\033' + && buffer[i + 1] == ']' + && buffer[i + 2] == '4' + && buffer[i + 3] == ';' + && buffer[i + 4] >= '0' && buffer[i + 4] <= '9' + && buffer[i + 5] == ';' + && buffer[i + 6] == '?' + && buffer[i + 7] == '\a' ) + { + if ( con != ansi + && con != rxvt + && con != kde_konsole + && con != kterm + && con != cygwin + && con != mintty + && con != linux_con + && con != freebsd_con + && con != netbsd_con + && con != openbsd_con + && con != sun_con + && con != screen + && con != tmux ) + { + int n = buffer[i + 4] - '0'; + write (fd_master, "\033]4;", 4); + write (fd_master, &buffer[i + 4], 1); + write (fd_master, ";rgb:", 5); + write (fd_master, colorname[n], 14); + write (fd_master, "\a", 1); + } + + i += 8; + } + else if ( i < length - 8 // Get xterm color name 0-9 + && buffer[i] == '\033' + && buffer[i + 1] == ']' + && buffer[i + 2] == '4' + && buffer[i + 3] == ';' + && buffer[i + 4] >= '0' && buffer[i + 4] <= '9' + && buffer[i + 5] >= '0' && buffer[i + 5] <= '9' + && buffer[i + 6] == ';' + && buffer[i + 7] == '?' + && buffer[i + 8] == '\a' ) + { + if ( con != ansi + && con != rxvt + && con != kde_konsole + && con != kterm + && con != cygwin + && con != mintty + && con != linux_con + && con != freebsd_con + && con != netbsd_con + && con != openbsd_con + && con != sun_con + && con != screen + && con != tmux ) + { + int n = (buffer[i + 4] - '0') * 10 + + (buffer[i + 5] - '0'); + write (fd_master, "\033]4;", 4); + write (fd_master, &buffer[i + 4], 1); + write (fd_master, &buffer[i + 5], 1); + write (fd_master, ";rgb:", 5); + write (fd_master, colorname[n], 14); + write (fd_master, "\a", 1); + } + + i += 9; + } + else if ( i < length - 9 // Get xterm color name 0-9 + && buffer[i] == '\033' + && buffer[i + 1] == ']' + && buffer[i + 2] == '4' + && buffer[i + 3] == ';' + && buffer[i + 4] >= '0' && buffer[i + 4] <= '9' + && buffer[i + 5] >= '0' && buffer[i + 5] <= '9' + && buffer[i + 6] >= '0' && buffer[i + 6] <= '9' + && buffer[i + 7] == ';' + && buffer[i + 8] == '?' + && buffer[i + 9] == '\a' ) + { + if ( con != ansi + && con != rxvt + && con != kde_konsole + && con != kterm + && con != cygwin + && con != mintty + && con != linux_con + && con != freebsd_con + && con != netbsd_con + && con != openbsd_con + && con != sun_con + && con != screen + && con != tmux ) + { + int n = (buffer[i + 4] - '0') * 100 + + (buffer[i + 5] - '0') * 10 + + (buffer[i + 6] - '0'); + + if ( n < 256 ) + { + write (fd_master, "\033]4;", 4); + write (fd_master, &buffer[i + 4], 1); + write (fd_master, &buffer[i + 5], 1); + write (fd_master, &buffer[i + 6], 1); + write (fd_master, ";rgb:", 5); + write (fd_master, colorname[n], 14); + write (fd_master, "\a", 1); + } + } + + i += 10; + } + else + { + write (fd_stdout, &buffer[i], 1); // Send data to stdout + } + } +} + +} // namespace test + +#endif // CONEMU_H diff --git a/test/fmouse-test.cpp b/test/fmouse-test.cpp index 6ac1d65b..b13f9231 100644 --- a/test/fmouse-test.cpp +++ b/test/fmouse-test.cpp @@ -3,7 +3,7 @@ * * * This file is part of the Final Cut widget toolkit * * * -* Copyright 2018 Markus Gans * +* Copyright 2018-2019 Markus Gans * * * * The Final Cut is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * @@ -30,6 +30,8 @@ #include +namespace test +{ //---------------------------------------------------------------------- // class FMouse_protected @@ -77,6 +79,8 @@ class FMouse_protected : public finalcut::FMouse }; #pragma pack(pop) +} // namespace test + //---------------------------------------------------------------------- // class finalcut::FMouseTest @@ -129,7 +133,7 @@ class FMouseTest : public CPPUNIT_NS::TestFixture //---------------------------------------------------------------------- void FMouseTest::classNameTest() { - FMouse_protected m; + test::FMouse_protected m; const char* const classname1 = m.getClassName(); CPPUNIT_ASSERT ( std::strcmp(classname1, "FMouse") == 0 ); @@ -159,7 +163,7 @@ void FMouseTest::classNameTest() //---------------------------------------------------------------------- void FMouseTest::noArgumentTest() { - FMouse_protected mouse; + test::FMouse_protected mouse; CPPUNIT_ASSERT ( mouse.getPos() == finalcut::FPoint(0, 0) ); CPPUNIT_ASSERT ( mouse.getNewMousePosition() == finalcut::FPoint(0, 0) ); CPPUNIT_ASSERT ( ! mouse.hasEvent() ); @@ -201,7 +205,7 @@ void FMouseTest::doubleClickTest() { using finalcut::operator -; - FMouse_protected mouse; + test::FMouse_protected mouse; CPPUNIT_ASSERT ( mouse.getDblclickInterval() == 500000 ); // 500 ms timeval tv = { 0, 0 }; CPPUNIT_ASSERT ( mouse.isDblclickTimeout(&tv) ); @@ -226,7 +230,7 @@ void FMouseTest::doubleClickTest() //---------------------------------------------------------------------- void FMouseTest::workspaceSizeTest() { - FMouse_protected mouse; + test::FMouse_protected mouse; CPPUNIT_ASSERT ( mouse.getMaxWidth() == 80 ); CPPUNIT_ASSERT ( mouse.getMaxHeight() == 25 ); diff --git a/test/fobject-test.cpp b/test/fobject-test.cpp index 71bebfb1..6dd61d9b 100644 --- a/test/fobject-test.cpp +++ b/test/fobject-test.cpp @@ -3,7 +3,7 @@ * * * This file is part of the Final Cut widget toolkit * * * -* Copyright 2018 Markus Gans * +* Copyright 2018-2019 Markus Gans * * * * The Final Cut is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * @@ -30,6 +30,8 @@ #include +namespace test +{ //---------------------------------------------------------------------- // class FObject_protected @@ -138,6 +140,8 @@ class FObject_userEvent : public finalcut::FObject }; #pragma pack(pop) +} // namespace test + //---------------------------------------------------------------------- // class FObjectTest @@ -219,7 +223,7 @@ void FObjectTest::noArgumentTest() CPPUNIT_ASSERT ( o1.isInstanceOf("FObject") ); CPPUNIT_ASSERT ( ! o1.isTimerInUpdating() ); - FObject_protected t; + test::FObject_protected t; auto ev = new finalcut::FEvent(finalcut::fc::None_Event); CPPUNIT_ASSERT ( ! t.event(ev) ); delete ev; @@ -294,7 +298,7 @@ void FObjectTest::childObjectTest() //---------------------------------------------------------------------- void FObjectTest::widgetObjectTest() { - FObject_protected o; + test::FObject_protected o; CPPUNIT_ASSERT ( ! o.isWidget() ); o.setWidgetProperty (true); CPPUNIT_ASSERT ( o.isWidget() ); @@ -451,8 +455,8 @@ void FObjectTest::timerTest() using finalcut::operator +=; using finalcut::operator <; - FObject_protected t1; - FObject_protected t2; + test::FObject_protected t1; + test::FObject_protected t2; int id1, id2; CPPUNIT_ASSERT ( t1.getTimerList()->empty() ); id1 = t1.addTimer(300); @@ -552,7 +556,7 @@ void FObjectTest::timerTest() //---------------------------------------------------------------------- void FObjectTest::performTimerActionTest() { - FObject_protected t1; + test::FObject_protected t1; uInt num_events = 0; uInt loop = 0; t1.addTimer(100); @@ -569,7 +573,7 @@ void FObjectTest::performTimerActionTest() CPPUNIT_ASSERT ( num_events == 9 ); CPPUNIT_ASSERT ( t1.count == 9 ); - FObject_timer t2; + test::FObject_timer t2; CPPUNIT_ASSERT ( t2.getValue() == 0 ); finalcut::FTimerEvent timer_ev (finalcut::fc::Timer_Event, 1); @@ -582,7 +586,7 @@ void FObjectTest::performTimerActionTest() //---------------------------------------------------------------------- void FObjectTest::userEventTest() { - FObject_userEvent user; + test::FObject_userEvent user; CPPUNIT_ASSERT ( user.getValue() == 0 ); int n = 9; diff --git a/test/ftermdetection-test.cpp b/test/ftermdetection-test.cpp index f3f664a6..7c6d52fc 100644 --- a/test/ftermdetection-test.cpp +++ b/test/ftermdetection-test.cpp @@ -31,272 +31,12 @@ #include #include +#include #include #define CPPUNIT_ASSERT_CSTRING(expected, actual) \ check_c_string (expected, actual, CPPUNIT_SOURCELINE()) -static char* colorname[] = -{ - C_STR("0000/0000/0000"), // 0 - C_STR("bbbb/0000/0000"), // 1 - C_STR("0000/bbbb/0000"), // 2 - C_STR("bbbb/bbbb/0000"), // 3 - C_STR("0000/0000/bbbb"), // 4 - C_STR("bbbb/0000/bbbb"), // 5 - C_STR("0000/bbbb/bbbb"), // 6 - C_STR("bbbb/bbbb/bbbb"), // 7 - C_STR("5555/5555/5555"), // 8 - C_STR("ffff/5555/5555"), // 9 - C_STR("5555/ffff/5555"), // 10 - C_STR("ffff/ffff/5555"), // 11 - C_STR("5555/5555/ffff"), // 12 - C_STR("ffff/5555/ffff"), // 13 - C_STR("5555/ffff/ffff"), // 14 - C_STR("ffff/ffff/ffff"), // 15 - C_STR("0000/0000/0000"), // 16 - C_STR("0000/0000/5f5f"), // 17 - C_STR("0000/0000/8787"), // 18 - C_STR("0000/0000/afaf"), // 19 - C_STR("0000/0000/d7d7"), // 20 - C_STR("0000/0000/ffff"), // 21 - C_STR("0000/5f5f/0000"), // 22 - C_STR("0000/5f5f/5f5f"), // 23 - C_STR("0000/5f5f/8787"), // 24 - C_STR("0000/5f5f/afaf"), // 25 - C_STR("0000/5f5f/d7d7"), // 26 - C_STR("0000/5f5f/ffff"), // 27 - C_STR("0000/8787/0000"), // 28 - C_STR("0000/8787/5f5f"), // 29 - C_STR("0000/8787/8787"), // 30 - C_STR("0000/8787/afaf"), // 31 - C_STR("0000/8787/d7d7"), // 32 - C_STR("0000/8787/ffff"), // 33 - C_STR("0000/afaf/0000"), // 34 - C_STR("0000/afaf/5f5f"), // 35 - C_STR("0000/afaf/8787"), // 36 - C_STR("0000/afaf/afaf"), // 37 - C_STR("0000/afaf/d7d7"), // 38 - C_STR("0000/afaf/ffff"), // 39 - C_STR("0000/d7d7/0000"), // 40 - C_STR("0000/d7d7/5f5f"), // 41 - C_STR("0000/d7d7/8787"), // 42 - C_STR("0000/d7d7/afaf"), // 43 - C_STR("0000/d7d7/d7d7"), // 44 - C_STR("0000/d7d7/ffff"), // 45 - C_STR("0000/ffff/0000"), // 46 - C_STR("0000/ffff/5f5f"), // 47 - C_STR("0000/ffff/8787"), // 48 - C_STR("0000/ffff/afaf"), // 49 - C_STR("0000/ffff/d7d7"), // 50 - C_STR("0000/ffff/ffff"), // 51 - C_STR("5f5f/0000/0000"), // 52 - C_STR("5f5f/0000/5f5f"), // 53 - C_STR("5f5f/0000/8787"), // 54 - C_STR("5f5f/0000/afaf"), // 55 - C_STR("5f5f/0000/d7d7"), // 56 - C_STR("5f5f/0000/ffff"), // 57 - C_STR("5f5f/5f5f/0000"), // 58 - C_STR("5f5f/5f5f/5f5f"), // 59 - C_STR("5f5f/5f5f/8787"), // 60 - C_STR("5f5f/5f5f/afaf"), // 61 - C_STR("5f5f/5f5f/d7d7"), // 62 - C_STR("5f5f/5f5f/ffff"), // 63 - C_STR("5f5f/8787/0000"), // 64 - C_STR("5f5f/8787/5f5f"), // 65 - C_STR("5f5f/8787/8787"), // 66 - C_STR("5f5f/8787/afaf"), // 67 - C_STR("5f5f/8787/d7d7"), // 68 - C_STR("5f5f/8787/ffff"), // 69 - C_STR("5f5f/afaf/0000"), // 70 - C_STR("5f5f/afaf/5f5f"), // 71 - C_STR("5f5f/afaf/8787"), // 72 - C_STR("5f5f/afaf/afaf"), // 73 - C_STR("5f5f/afaf/d7d7"), // 74 - C_STR("5f5f/afaf/ffff"), // 75 - C_STR("5f5f/d7d7/0000"), // 76 - C_STR("5f5f/d7d7/5f5f"), // 77 - C_STR("5f5f/d7d7/8787"), // 78 - C_STR("5f5f/d7d7/afaf"), // 79 - C_STR("5f5f/d7d7/d7d7"), // 80 - C_STR("5f5f/d7d7/ffff"), // 81 - C_STR("5f5f/ffff/0000"), // 82 - C_STR("5f5f/ffff/5f5f"), // 83 - C_STR("5f5f/ffff/8787"), // 84 - C_STR("5f5f/ffff/afaf"), // 85 - C_STR("5f5f/ffff/d7d7"), // 86 - C_STR("5f5f/ffff/ffff"), // 87 - C_STR("8787/0000/0000"), // 88 - C_STR("8787/0000/5f5f"), // 89 - C_STR("8787/0000/8787"), // 90 - C_STR("8787/0000/afaf"), // 91 - C_STR("8787/0000/d7d7"), // 92 - C_STR("8787/0000/ffff"), // 93 - C_STR("8787/5f5f/0000"), // 94 - C_STR("8787/5f5f/5f5f"), // 95 - C_STR("8787/5f5f/8787"), // 96 - C_STR("8787/5f5f/afaf"), // 97 - C_STR("8787/5f5f/d7d7"), // 98 - C_STR("8787/5f5f/ffff"), // 99 - C_STR("8787/8787/0000"), // 100 - C_STR("8787/8787/5f5f"), // 101 - C_STR("8787/8787/8787"), // 102 - C_STR("8787/8787/afaf"), // 103 - C_STR("8787/8787/d7d7"), // 104 - C_STR("8787/8787/ffff"), // 105 - C_STR("8787/afaf/0000"), // 106 - C_STR("8787/afaf/5f5f"), // 107 - C_STR("8787/afaf/8787"), // 108 - C_STR("8787/afaf/afaf"), // 109 - C_STR("8787/afaf/d7d7"), // 110 - C_STR("8787/afaf/ffff"), // 111 - C_STR("8787/d7d7/0000"), // 112 - C_STR("8787/d7d7/5f5f"), // 113 - C_STR("8787/d7d7/8787"), // 114 - C_STR("8787/d7d7/afaf"), // 115 - C_STR("8787/d7d7/d7d7"), // 116 - C_STR("8787/d7d7/ffff"), // 117 - C_STR("8787/ffff/0000"), // 118 - C_STR("8787/ffff/5f5f"), // 119 - C_STR("8787/ffff/8787"), // 120 - C_STR("8787/ffff/afaf"), // 121 - C_STR("8787/ffff/d7d7"), // 122 - C_STR("8787/ffff/ffff"), // 123 - C_STR("afaf/0000/0000"), // 124 - C_STR("afaf/0000/5f5f"), // 125 - C_STR("afaf/0000/8787"), // 126 - C_STR("afaf/0000/afaf"), // 127 - C_STR("afaf/0000/d7d7"), // 128 - C_STR("afaf/0000/ffff"), // 129 - C_STR("afaf/5f5f/0000"), // 130 - C_STR("afaf/5f5f/5f5f"), // 131 - C_STR("afaf/5f5f/8787"), // 132 - C_STR("afaf/5f5f/afaf"), // 133 - C_STR("afaf/5f5f/d7d7"), // 134 - C_STR("afaf/5f5f/ffff"), // 135 - C_STR("afaf/8787/0000"), // 136 - C_STR("afaf/8787/5f5f"), // 137 - C_STR("afaf/8787/8787"), // 138 - C_STR("afaf/8787/afaf"), // 139 - C_STR("afaf/8787/d7d7"), // 140 - C_STR("afaf/8787/ffff"), // 141 - C_STR("afaf/afaf/0000"), // 142 - C_STR("afaf/afaf/5f5f"), // 143 - C_STR("afaf/afaf/8787"), // 144 - C_STR("afaf/afaf/afaf"), // 145 - C_STR("afaf/afaf/d7d7"), // 146 - C_STR("afaf/afaf/ffff"), // 147 - C_STR("afaf/d7d7/0000"), // 148 - C_STR("afaf/d7d7/5f5f"), // 149 - C_STR("afaf/d7d7/8787"), // 150 - C_STR("afaf/d7d7/afaf"), // 151 - C_STR("afaf/d7d7/d7d7"), // 152 - C_STR("afaf/d7d7/ffff"), // 153 - C_STR("afaf/ffff/0000"), // 154 - C_STR("afaf/ffff/5f5f"), // 155 - C_STR("afaf/ffff/8787"), // 156 - C_STR("afaf/ffff/afaf"), // 157 - C_STR("afaf/ffff/d7d7"), // 158 - C_STR("afaf/ffff/ffff"), // 159 - C_STR("d7d7/0000/0000"), // 160 - C_STR("d7d7/0000/5f5f"), // 161 - C_STR("d7d7/0000/8787"), // 162 - C_STR("d7d7/0000/afaf"), // 163 - C_STR("d7d7/0000/d7d7"), // 164 - C_STR("d7d7/0000/ffff"), // 165 - C_STR("d7d7/5f5f/0000"), // 166 - C_STR("d7d7/5f5f/5f5f"), // 167 - C_STR("d7d7/5f5f/8787"), // 168 - C_STR("d7d7/5f5f/afaf"), // 169 - C_STR("d7d7/5f5f/d7d7"), // 170 - C_STR("d7d7/5f5f/ffff"), // 171 - C_STR("d7d7/8787/0000"), // 172 - C_STR("d7d7/8787/5f5f"), // 173 - C_STR("d7d7/8787/8787"), // 174 - C_STR("d7d7/8787/afaf"), // 175 - C_STR("d7d7/8787/d7d7"), // 176 - C_STR("d7d7/8787/ffff"), // 177 - C_STR("d7d7/afaf/0000"), // 178 - C_STR("d7d7/afaf/5f5f"), // 179 - C_STR("d7d7/afaf/8787"), // 180 - C_STR("d7d7/afaf/afaf"), // 181 - C_STR("d7d7/afaf/d7d7"), // 182 - C_STR("d7d7/afaf/ffff"), // 183 - C_STR("d7d7/d7d7/0000"), // 184 - C_STR("d7d7/d7d7/5f5f"), // 185 - C_STR("d7d7/d7d7/8787"), // 186 - C_STR("d7d7/d7d7/afaf"), // 187 - C_STR("d7d7/d7d7/d7d7"), // 188 - C_STR("d7d7/d7d7/ffff"), // 189 - C_STR("d7d7/ffff/0000"), // 190 - C_STR("d7d7/ffff/5f5f"), // 191 - C_STR("d7d7/ffff/8787"), // 192 - C_STR("d7d7/ffff/afaf"), // 193 - C_STR("d7d7/ffff/d7d7"), // 194 - C_STR("d7d7/ffff/ffff"), // 195 - C_STR("ffff/0000/0000"), // 196 - C_STR("ffff/0000/5f5f"), // 197 - C_STR("ffff/0000/8787"), // 198 - C_STR("ffff/0000/afaf"), // 199 - C_STR("ffff/0000/d7d7"), // 200 - C_STR("ffff/0000/ffff"), // 201 - C_STR("ffff/5f5f/0000"), // 202 - C_STR("ffff/5f5f/5f5f"), // 203 - C_STR("ffff/5f5f/8787"), // 204 - C_STR("ffff/5f5f/afaf"), // 205 - C_STR("ffff/5f5f/d7d7"), // 206 - C_STR("ffff/5f5f/ffff"), // 207 - C_STR("ffff/8787/0000"), // 208 - C_STR("ffff/8787/5f5f"), // 209 - C_STR("ffff/8787/8787"), // 210 - C_STR("ffff/8787/afaf"), // 211 - C_STR("ffff/8787/d7d7"), // 212 - C_STR("ffff/8787/ffff"), // 213 - C_STR("ffff/afaf/0000"), // 214 - C_STR("ffff/afaf/5f5f"), // 215 - C_STR("ffff/afaf/8787"), // 216 - C_STR("ffff/afaf/afaf"), // 217 - C_STR("ffff/afaf/d7d7"), // 218 - C_STR("ffff/afaf/ffff"), // 219 - C_STR("ffff/d7d7/0000"), // 220 - C_STR("ffff/d7d7/5f5f"), // 221 - C_STR("ffff/d7d7/8787"), // 222 - C_STR("ffff/d7d7/afaf"), // 223 - C_STR("ffff/d7d7/d7d7"), // 224 - C_STR("ffff/d7d7/ffff"), // 225 - C_STR("ffff/ffff/0000"), // 226 - C_STR("ffff/ffff/5f5f"), // 227 - C_STR("ffff/ffff/8787"), // 228 - C_STR("ffff/ffff/afaf"), // 229 - C_STR("ffff/ffff/d7d7"), // 230 - C_STR("ffff/ffff/ffff"), // 231 - C_STR("0808/0808/0808"), // 232 - C_STR("1212/1212/1212"), // 233 - C_STR("1c1c/1c1c/1c1c"), // 234 - C_STR("2626/2626/2626"), // 235 - C_STR("3030/3030/3030"), // 236 - C_STR("3a3a/3a3a/3a3a"), // 237 - C_STR("4444/4444/4444"), // 238 - C_STR("4e4e/4e4e/4e4e"), // 239 - C_STR("5858/5858/5858"), // 240 - C_STR("6262/6262/6262"), // 241 - C_STR("6c6c/6c6c/6c6c"), // 242 - C_STR("7676/7676/7676"), // 243 - C_STR("8080/8080/8080"), // 244 - C_STR("8a8a/8a8a/8a8a"), // 245 - C_STR("9494/9494/9494"), // 246 - C_STR("9e9e/9e9e/9e9e"), // 247 - C_STR("a8a8/a8a8/a8a8"), // 248 - C_STR("b2b2/b2b2/b2b2"), // 249 - C_STR("bcbc/bcbc/bcbc"), // 250 - C_STR("c6c6/c6c6/c6c6"), // 251 - C_STR("d0d0/d0d0/d0d0"), // 252 - C_STR("dada/dada/dada"), // 253 - C_STR("e4e4/e4e4/e4e4"), // 254 - C_STR("eeee/eeee/eeee"), // 255 - 0 -}; - //---------------------------------------------------------------------- void check_c_string ( const char* s1 , const char* s2 @@ -319,34 +59,9 @@ void check_c_string ( const char* s1 #pragma pack(push) #pragma pack(1) -class FTermDetectionTest : public CPPUNIT_NS::TestFixture +class FTermDetectionTest : public CPPUNIT_NS::TestFixture, test::ConEmu { public: - // Enumeration - enum console - { - ansi, - xterm, - rxvt, - urxvt, - mlterm, - putty, - kde_konsole, - gnome_terminal, - newer_vte_terminal, - kterm, - tera_term, - cygwin, - mintty, - linux_con, - freebsd_con, - netbsd_con, - openbsd_con, - sun_con, - screen, - tmux - }; - FTermDetectionTest(); ~FTermDetectionTest(); @@ -375,23 +90,6 @@ class FTermDetectionTest : public CPPUNIT_NS::TestFixture void ttytypeTest(); private: - char* getAnswerback (console); - char* getDSR (console); - char* getDECID (console); - char* getDA (console); - char* getDA1 (console); - char* getSEC_DA (console); - void debugOutput(); - bool openMasterPTY(); - bool openSlavePTY(); - void closeMasterPTY(); - void closeSlavePTY(); - void closeStandardStreams(); - pid_t forkProcess(); - bool isChildProcess (pid_t); - void terminalSimulation (console); - void parseTerminalBuffer (std::size_t, console); - // Adds code needed to register the test suite CPPUNIT_TEST_SUITE (FTermDetectionTest); @@ -421,44 +119,16 @@ class FTermDetectionTest : public CPPUNIT_NS::TestFixture // End of test suite definition CPPUNIT_TEST_SUITE_END(); - - // Data Members - int fd_stdin{fileno(stdin)}; - int fd_stdout{fileno(stdout)}; - int fd_stderr{fileno(stderr)}; - int fd_master{-1}; - int fd_slave{-1}; - bool debug{false}; - char buffer[2048]{}; - static bool* shared_state; - }; #pragma pack(pop) -// static class attributes -bool* FTermDetectionTest::shared_state = nullptr; - //---------------------------------------------------------------------- FTermDetectionTest::FTermDetectionTest() -{ - // Map shared memory - void* ptr = mmap ( NULL - , sizeof(*shared_state) - , PROT_READ | PROT_WRITE - , MAP_SHARED | MAP_ANONYMOUS, -1 - , 0 ); - shared_state = static_cast(ptr); - *shared_state = false; -} +{ } //---------------------------------------------------------------------- FTermDetectionTest::~FTermDetectionTest() -{ - closeMasterPTY(); - closeSlavePTY(); - // Unmap shared memory - munmap (shared_state, sizeof(*shared_state)); -} +{ } //---------------------------------------------------------------------- void FTermDetectionTest::classNameTest() @@ -476,9 +146,9 @@ void FTermDetectionTest::ansiTest() setenv ("TERM", "ansi", 1); data.setTermFileName(C_STR("ansi")); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "ansi", 1); unsetenv("TERMCAP"); @@ -523,14 +193,14 @@ void FTermDetectionTest::ansiTest() CPPUNIT_ASSERT ( ! detect.isAnsiTerminal() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (ansi); + // Start the terminal emulation + startConEmuTerminal (ConEmu::ansi); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -545,9 +215,9 @@ void FTermDetectionTest::xtermTest() data.setTermFileName(C_STR("xterm")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "xterm", 1); setenv ("XTERM_VERSION", "XTerm(312)", 1); @@ -584,14 +254,14 @@ void FTermDetectionTest::xtermTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( detect.hasSetCursorStyleSupport() ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (xterm); + // Start the terminal emulation + startConEmuTerminal (ConEmu::xterm); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -606,9 +276,9 @@ void FTermDetectionTest::rxvtTest() data.setTermFileName(C_STR("rxvt-cygwin-native")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "rxvt-cygwin-native", 1); setenv ("COLORTERM", "rxvt-xpm", 1); @@ -646,14 +316,14 @@ void FTermDetectionTest::rxvtTest() CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("rxvt-cygwin-native") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (rxvt); + // Start the terminal emulation + startConEmuTerminal (ConEmu::rxvt); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -668,9 +338,9 @@ void FTermDetectionTest::urxvtTest() data.setTermFileName(C_STR("rxvt-unicode-256color")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "rxvt-unicode-256color", 1); setenv ("COLORTERM", "rxvt-xpm", 1); @@ -707,14 +377,14 @@ void FTermDetectionTest::urxvtTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (urxvt); + // Start the terminal emulation + startConEmuTerminal (ConEmu::urxvt); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -729,9 +399,9 @@ void FTermDetectionTest::mltermTest() data.setTermFileName(C_STR("mlterm")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "mlterm", 1); setenv ("MLTERM", "3.8.4", 1); @@ -776,14 +446,14 @@ void FTermDetectionTest::mltermTest() CPPUNIT_ASSERT ( detect.canDisplay256Colors() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("xterm-256color") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (mlterm); + // Start the terminal emulation + startConEmuTerminal (ConEmu::mlterm); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -798,9 +468,9 @@ void FTermDetectionTest::puttyTest() data.setTermFileName(C_STR("xterm")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "xterm", 1); unsetenv("TERMCAP"); @@ -837,15 +507,15 @@ void FTermDetectionTest::puttyTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); - debug = true; - debugOutput(); - closeStandardStreams(); + enableConEmuDebug(true); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (putty); + // Start the terminal emulation + startConEmuTerminal (ConEmu::putty); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -860,9 +530,9 @@ void FTermDetectionTest::kdeKonsoleTest() data.setTermFileName(C_STR("xterm-256color")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "xterm-256color", 1); setenv ("COLORTERM", "truecolor", 1); @@ -899,14 +569,14 @@ void FTermDetectionTest::kdeKonsoleTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (kde_konsole); + // Start the terminal emulation + startConEmuTerminal (ConEmu::kde_konsole); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -921,9 +591,9 @@ void FTermDetectionTest::gnomeTerminalTest() data.setTermFileName(C_STR("xterm-256color")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "xterm-256color", 1); setenv ("COLORTERM", "truecolor", 1); @@ -961,14 +631,14 @@ void FTermDetectionTest::gnomeTerminalTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( detect.hasSetCursorStyleSupport() ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (gnome_terminal); + // Start the terminal emulation + startConEmuTerminal (ConEmu::gnome_terminal); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -983,9 +653,9 @@ void FTermDetectionTest::newerVteTerminalTest() data.setTermFileName(C_STR("xterm-256color")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "xterm-256color", 1); setenv ("COLORTERM", "truecolor", 1); @@ -1023,14 +693,14 @@ void FTermDetectionTest::newerVteTerminalTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( detect.hasSetCursorStyleSupport() ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (newer_vte_terminal); + // Start the terminal emulation + startConEmuTerminal (ConEmu::newer_vte_terminal); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1045,9 +715,9 @@ void FTermDetectionTest::ktermTest() data.setTermFileName(C_STR("kterm")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "kterm", 1); unsetenv("TERMCAP"); @@ -1092,14 +762,14 @@ void FTermDetectionTest::ktermTest() CPPUNIT_ASSERT ( ! detect.isKtermTerminal() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (kterm); + // Start the terminal emulation + startConEmuTerminal (ConEmu::kterm); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1114,9 +784,9 @@ void FTermDetectionTest::teraTermTest() data.setTermFileName(C_STR("xterm")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "xterm", 1); unsetenv("TERMCAP"); @@ -1154,14 +824,14 @@ void FTermDetectionTest::teraTermTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (tera_term); + // Start the terminal emulation + startConEmuTerminal (ConEmu::tera_term); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1176,9 +846,9 @@ void FTermDetectionTest::cygwinTest() data.setTermFileName(C_STR("cygwin")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "cygwin", 1); unsetenv("TERMCAP"); @@ -1216,14 +886,14 @@ void FTermDetectionTest::cygwinTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (cygwin); + // Start the terminal emulation + startConEmuTerminal (ConEmu::cygwin); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1238,9 +908,9 @@ void FTermDetectionTest::minttyTest() data.setTermFileName(C_STR("xterm-256color")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "xterm-256color", 1); unsetenv("TERMCAP"); @@ -1278,14 +948,14 @@ void FTermDetectionTest::minttyTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( detect.hasSetCursorStyleSupport() ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (mintty); + // Start the terminal emulation + startConEmuTerminal (ConEmu::mintty); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1300,9 +970,9 @@ void FTermDetectionTest::linuxTest() data.setTermFileName(C_STR("linux")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "linux", 1); unsetenv("TERMCAP"); @@ -1347,14 +1017,14 @@ void FTermDetectionTest::linuxTest() CPPUNIT_ASSERT ( ! detect.isLinuxTerm() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (linux_con); + // Start the terminal emulation + startConEmuTerminal (ConEmu::linux_con); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1369,9 +1039,9 @@ void FTermDetectionTest::freebsdTest() data.setTermFileName(C_STR("xterm")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "xterm", 1); unsetenv("TERMCAP"); @@ -1419,14 +1089,14 @@ void FTermDetectionTest::freebsdTest() CPPUNIT_ASSERT ( ! detect.isFreeBSDTerm() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (freebsd_con); + // Start the terminal emulation + startConEmuTerminal (ConEmu::freebsd_con); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1441,9 +1111,9 @@ void FTermDetectionTest::netbsdTest() data.setTermFileName(C_STR("wsvt25")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "wsvt25", 1); unsetenv("TERMCAP"); @@ -1489,14 +1159,14 @@ void FTermDetectionTest::netbsdTest() CPPUNIT_ASSERT ( ! detect.isFreeBSDTerm() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (netbsd_con); + // Start the terminal emulation + startConEmuTerminal (ConEmu::netbsd_con); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1511,9 +1181,9 @@ void FTermDetectionTest::openbsdTest() data.setTermFileName(C_STR("vt220")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "vt220", 1); unsetenv("TERMCAP"); @@ -1559,14 +1229,14 @@ void FTermDetectionTest::openbsdTest() CPPUNIT_ASSERT ( ! detect.isOpenBSDTerm() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (openbsd_con); + // Start the terminal emulation + startConEmuTerminal (ConEmu::openbsd_con); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1580,9 +1250,9 @@ void FTermDetectionTest::sunTest() finalcut::FTermDetection detect; data.setTermFileName(C_STR("sun-color")); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "sun-color", 1); unsetenv("TERMCAP"); @@ -1627,14 +1297,14 @@ void FTermDetectionTest::sunTest() CPPUNIT_ASSERT ( ! detect.isSunTerminal() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (sun_con); + // Start the terminal emulation + startConEmuTerminal (ConEmu::sun_con); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1649,9 +1319,9 @@ void FTermDetectionTest::screenTest() data.setTermFileName(C_STR("screen")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "screen", 1); setenv ("TERMCAP", "SC|screen|VT 100/ANSI X3.64 virtual terminal:...", 1); @@ -1695,14 +1365,14 @@ void FTermDetectionTest::screenTest() CPPUNIT_ASSERT ( detect.canDisplay256Colors() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("screen-256color") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (screen); + // Start the terminal emulation + startConEmuTerminal (ConEmu::screen); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1717,9 +1387,9 @@ void FTermDetectionTest::tmuxTest() data.setTermFileName(C_STR("screen")); detect.setTerminalDetection(true); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { setenv ("TERM", "screen", 1); setenv ("TMUX", "/tmp/tmux-1000/default,7844,0", 1); @@ -1764,14 +1434,14 @@ void FTermDetectionTest::tmuxTest() CPPUNIT_ASSERT ( detect.canDisplay256Colors() ); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("screen-256color") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { // Start the terminal simulation - terminalSimulation (tmux); + startConEmuTerminal (ConEmu::tmux); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1821,9 +1491,9 @@ void FTermDetectionTest::ttytypeTest() detect.setTerminalDetection(true); detect.setTtyTypeFileName(C_STR("new-root-dir/etc/ttytype")); - pid_t pid = forkProcess(); + pid_t pid = forkConEmu(); - if ( isChildProcess(pid) ) + if ( isConEmuChildProcess(pid) ) { unsetenv("TERM"); unsetenv("TERMCAP"); @@ -1851,14 +1521,14 @@ void FTermDetectionTest::ttytypeTest() detect.detect(); CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); - debugOutput(); - closeStandardStreams(); + printConEmuDebug(); + closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { - // Start the terminal simulation - terminalSimulation (ansi); + // Start the terminal emulation + startConEmuTerminal (ConEmu::ansi); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; @@ -1870,679 +1540,6 @@ void FTermDetectionTest::ttytypeTest() } -// private methods of FOptiMoveTest -//---------------------------------------------------------------------- -char* FTermDetectionTest::getAnswerback (console con) -{ - static char* Answerback[] = - { - 0, // Ansi, - 0, // XTerm - 0, // Rxvt - 0, // Urxvt - 0, // mlterm - Multi Lingual TERMinal - C_STR("PuTTY"), // PuTTY - 0, // KDE Konsole - 0, // GNOME Terminal - 0, // VTE Terminal >= 0.53.0 - 0, // kterm, - 0, // Tera Term - 0, // Cygwin - 0, // Mintty - 0, // Linux console - 0, // FreeBSD console - 0, // NetBSD console - 0, // OpenBSD console - 0, // Sun console - 0, // screen - 0 // tmux - }; - - return Answerback[con]; -} - -//---------------------------------------------------------------------- -char* FTermDetectionTest::getDSR (console con) -{ - static char* DSR[] = - { - 0, // Ansi, - C_STR("\033[0n"), // XTerm - C_STR("\033[0n"), // Rxvt - C_STR("\033[0n"), // Urxvt - C_STR("\033[0n"), // mlterm - Multi Lingual TERMinal - C_STR("\033[0n"), // PuTTY - C_STR("\033[0n"), // KDE Konsole - C_STR("\033[0n"), // GNOME Terminal - C_STR("\033[0n"), // VTE Terminal >= 0.53.0 - C_STR("\033[0n"), // kterm, - C_STR("\033[0n"), // Tera Term - 0, // Cygwin - C_STR("\033[0n"), // Mintty - C_STR("\033[0n"), // Linux console - C_STR("\033[0n"), // FreeBSD console - C_STR("\033[0n"), // NetBSD console - C_STR("\033[0n"), // OpenBSD console - 0, // Sun console - C_STR("\033[0n"), // screen - C_STR("\033[0n") // tmux - }; - - return DSR[con]; -} - -//---------------------------------------------------------------------- -char* FTermDetectionTest::getDECID (console con) -{ - static char* DECID[] = - { - 0, // Ansi, - C_STR("\033[?63;1;2;6;4;6;9;15;22c"), // XTerm - C_STR("\033[?1;2c"), // Rxvt - C_STR("\033[?1;2c"), // Urxvt - C_STR("\033[?63;1;2;3;4;7;29c"), // mlterm - Multi Lingual TERMinal - C_STR("\033[?6c"), // PuTTY - C_STR("\033[?1;2c"), // KDE Konsole - C_STR("\033[?62;c"), // GNOME Terminal - C_STR("\033[?65;1;9c"), // VTE Terminal >= 0.53.0 - C_STR("\033[?1;2c"), // kterm, - C_STR("\033[?1;2c"), // Tera Term - 0, // Cygwin - C_STR("\033[?1;2;6;22c"), // Mintty - C_STR("\033[?6c"), // Linux console - 0, // FreeBSD console - 0, // NetBSD console - 0, // OpenBSD console - 0, // Sun console - C_STR("\033[?1;2c"), // screen - 0 // tmux - }; - - return DECID[con]; -} - -//---------------------------------------------------------------------- -char* FTermDetectionTest::getDA (console con) -{ - static char* DA[] = - { - 0, // Ansi, - C_STR("\033[?63;1;2;6;4;6;9;15;22c"), // XTerm - C_STR("\033[?1;2c"), // Rxvt - C_STR("\033[?1;2c"), // Urxvt - C_STR("\033[?63;1;2;3;4;7;29c"), // mlterm - Multi Lingual TERMinal - C_STR("\033[?6c"), // PuTTY - C_STR("\033[?1;2c"), // KDE Konsole - C_STR("\033[?62;c"), // GNOME Terminal - C_STR("\033[?65;1;9c"), // VTE Terminal >= 0.53.0 - C_STR("\033[?1;2c"), // kterm, - C_STR("\033[?1;2c"), // Tera Term - C_STR("\033[?6c"), // Cygwin - C_STR("\033[?1;2;6;22c"), // Mintty - C_STR("\033[?6c"), // Linux console - C_STR("\033[?1;2c"), // FreeBSD console - C_STR("\033[?62;6c"), // NetBSD console - C_STR("\033[?62;6c"), // OpenBSD console - 0, // Sun console - C_STR("\033[?1;2c"), // screen - C_STR("\033[?1;2c") // tmux - }; - - return DA[con]; -} - -//---------------------------------------------------------------------- -char* FTermDetectionTest::getDA1 (console con) -{ - static char* DA1[] = - { - 0, // Ansi, - 0, // XTerm - C_STR("\033[?1;2c"), // Rxvt - C_STR("\033[?1;2c"), // Urxvt - C_STR("\033[?63;1;2;3;4;7;29c"), // mlterm - Multi Lingual TERMinal - C_STR("\033[?6c"), // PuTTY - C_STR("\033[?1;2c"), // KDE Konsole - C_STR("\033[?62;c"), // GNOME Terminal - C_STR("\033[?65;1;9c"), // VTE Terminal >= 0.53.0 - 0, // kterm, - C_STR("\033[?1;2c"), // Tera Term - C_STR("\033[?6c"), // Cygwin - C_STR("\033[?1;2;6;22c"), // Mintty - 0, // Linux console - 0, // FreeBSD console - 0, // NetBSD console - 0, // OpenBSD console - 0, // Sun console - 0, // screen - 0 // tmux - }; - - return DA1[con]; -} - -//---------------------------------------------------------------------- -char* FTermDetectionTest::getSEC_DA (console con) -{ - static char* SEC_DA[] = - { - 0, // Ansi, - C_STR("\033[>19;312;0c"), // XTerm - C_STR("\033[>82;20710;0c"), // Rxvt - C_STR("\033[>85;95;0c"), // Urxvt - C_STR("\033[>24;279;0c"), // mlterm - Multi Lingual TERMinal - C_STR("\033[>0;136;0c"), // PuTTY - C_STR("\033[>0;115;0c"), // KDE Konsole - C_STR("\033[>1;5202;0c"), // GNOME Terminal - C_STR("\033[>65;5300;1c"), // VTE Terminal >= 0.53.0 - C_STR("\033[?1;2c"), // kterm, - C_STR("\033[>32;278;0c"), // Tera Term - C_STR("\033[>67;200502;0c"), // Cygwin - C_STR("\033[>77;20402;0c"), // Mintty - 0, // Linux console - 0, // FreeBSD console - 0, // NetBSD console - 0, // OpenBSD console - 0, // Sun console - C_STR("\033[>83;40201;0c"), // screen - C_STR("\033[>84;0;0c") // tmux - }; - - return SEC_DA[con]; -} - -//---------------------------------------------------------------------- -void FTermDetectionTest::debugOutput() -{ - if ( ! debug ) - return; - - setenv ("DSR", "\\033[5n", 1); - setenv ("CURSOR_POS", "\\033[6n", 1); - setenv ("DECID", "\\033Z", 1); - setenv ("DA", "\\033[c", 1); - setenv ("DA1", "\\033[1c", 1); - setenv ("SEC_DA", "\\033[>c", 1); - setenv ("ANSWERBACK", "\\005", 1); - setenv ("TITLE", "\\033[21t", 1); - setenv ("COLOR16", "\\033]4;15;?\\a", 1); - setenv ("COLOR88", "\\033]4;87;?\\a", 1); - setenv ("COLOR256", "\\033]4;254;?\\a", 1); - - setenv ("GO_MIDDLE", "\\033[80D\\033[15C", 1); - setenv ("GO_RIGHT", "\\033[79D\\033[40C", 1); - - finalcut::FString line (69, '-'); - std::cout << std::endl << line << std::endl; - std::cout << "Probe Escape sequence Reply"; - std::cout << std::endl << line << std::endl; - - // Command line - constexpr char debug_command[] = "/bin/bash -c ' \ - for i in DSR CURSOR_POS DECID DA DA1 SEC_DA ANSWERBACK \ - TITLE COLOR16 COLOR88 COLOR256; \ - do \ - eval \"echo -en \\\"$i${GO_MIDDLE}\\\"; \ - echo -n \\\"\\${$i}\\\"; \ - echo -en \\\"${GO_RIGHT}\\${$i}\\\"\"; \ - sleep 0.5; \ - echo -e \"\\r\"; \ - done'"; - system(debug_command); -} - -//---------------------------------------------------------------------- -bool FTermDetectionTest::openMasterPTY() -{ - int result; - - // Open a pseudoterminal device - fd_master = posix_openpt(O_RDWR); - - if ( fd_master < 0 ) - return false; - - // Change the slave pseudoterminal access rights - result = grantpt(fd_master); - - if ( result != 0 ) - return false; - - // Unlock the pseudoterminal master/slave pair - result = unlockpt(fd_master); - - if ( result != 0 ) - return false; - - return true; -} - -//---------------------------------------------------------------------- -bool FTermDetectionTest::openSlavePTY() -{ - closeSlavePTY(); - - // Get PTY filename - const char* pty_name = ptsname(fd_master); - - if ( pty_name == 0 ) - return false; - - // Open the slave PTY - fd_slave = open(pty_name, O_RDWR); - - if ( fd_slave < 0 ) - return false; - - return true; -} - -//---------------------------------------------------------------------- -void FTermDetectionTest::closeMasterPTY() -{ - if ( fd_master <= 0 ) - return; - - close (fd_master); - fd_master = -1; -} - -//---------------------------------------------------------------------- -void FTermDetectionTest::closeSlavePTY() -{ - if ( fd_slave <= 0 ) - return; - - close (fd_slave); - fd_slave = -1; -} - -//---------------------------------------------------------------------- -void FTermDetectionTest::closeStandardStreams() -{ - close(fd_stdin); // stdin - close(fd_stdout); // stdout - close(fd_stderr); // stderr -} - -//---------------------------------------------------------------------- -pid_t FTermDetectionTest::forkProcess() -{ - // Initialize buffer with '\0' - std::fill_n (buffer, sizeof(buffer), '\0'); - - if ( ! openMasterPTY() ) - return -1; - - if ( ! openSlavePTY() ) - return -1; - - pid_t pid = fork(); // Create a child process - - if ( pid < 0) // Fork failed - return -1; - - if ( isChildProcess(pid) ) // Child process - { - struct termios term_settings; - closeMasterPTY(); - - // Creates a session and makes the current process to the leader - setsid(); - -#ifdef TIOCSCTTY - // Set controlling tty - if ( ioctl(fd_slave, TIOCSCTTY, 0) == -1 ) - { - *shared_state = true; - return -1; - } -#endif - - // Get current terminal settings - if ( tcgetattr(fd_slave, &term_settings) == -1 ) - { - *shared_state = true; - return -1; - } - - // Set raw mode on the slave side of the PTY - cfmakeraw (&term_settings); - tcsetattr (fd_slave, TCSANOW, &term_settings); - -#ifdef TIOCSWINSZ - // Set slave tty window size - struct winsize size; - size.ws_row = 25; - size.ws_col = 80; - - if ( ioctl(fd_slave, TIOCSWINSZ, &size) == -1) - { - *shared_state = true; - return -1; - } -#endif - - closeStandardStreams(); - - fd_stdin = dup(fd_slave); // PTY becomes stdin (0) - fd_stdout = dup(fd_slave); // PTY becomes stdout (1) - fd_stderr = dup(fd_slave); // PTY becomes stderr (2) - - closeSlavePTY(); - - // The child process is now ready for input - *shared_state = true; - } - else - { - constexpr int timeout = 150; // 1.5 seconds - int i = 0; - - // Wait until the child process is ready for input - while ( ! *shared_state && i < timeout ) - { - // Wait 10 ms (= 10,000,000 ns) - nanosleep ((const struct timespec[]){{0, 10000000L}}, NULL); - i++; - } - - *shared_state = false; - } - - return pid; -} - -//---------------------------------------------------------------------- -inline bool FTermDetectionTest::isChildProcess (pid_t pid) -{ - return bool( pid == 0 ); -} - -//---------------------------------------------------------------------- -void FTermDetectionTest::terminalSimulation (console con) -{ - closeSlavePTY(); - - while ( 1 ) - { - fd_set ifds; - struct timeval tv; - ssize_t len; - - FD_ZERO(&ifds); - FD_SET(fd_stdin, &ifds); - FD_SET(fd_master, &ifds); - tv.tv_sec = 0; - tv.tv_usec = 750000; // 750 ms - - // Wait for data from stdin or the master side of PTY - if ( select(fd_master + 1, &ifds, 0, 0, &tv) < 0 ) - break; - - // Data on standard input - if ( FD_ISSET(fd_stdin, &ifds) ) - { - len = read (fd_stdin, buffer, sizeof(buffer)); - - if ( len > 0 && std::size_t(len) < sizeof(buffer) ) - { - buffer[len] = '\0'; - write (fd_master, buffer, len); // Send data to the master side - } - } - - // Data on the master side of PTY - if ( FD_ISSET(fd_master, &ifds) ) - { - len = read (fd_master, buffer, sizeof(buffer)); - - if ( len == -1 || std::size_t(len) >= sizeof(buffer) ) - break; - else if ( len > 0 ) - { - buffer[len] = '\0'; - parseTerminalBuffer (len, con); - } - } - } -} - -//---------------------------------------------------------------------- -void FTermDetectionTest::parseTerminalBuffer (std::size_t length, console con) -{ - for (std::size_t i = 0; i < length; i++) - { - if ( buffer[i] == ENQ[0] ) // Enquiry character - { - char* answer = getAnswerback(con); - - if ( answer ) - write(fd_master, answer, std::strlen(answer)); - } - else if ( i < length - 1 // Terminal ID (DECID) - && buffer[i] == '\033' - && buffer[i + 1] == 'Z' ) - { - char* DECID = getDECID(con); - - if ( DECID ) - write (fd_master, DECID, std::strlen(DECID)); - - i += 2; - } - else if ( i < length - 3 // Device status report (DSR) - && buffer[i] == '\033' - && buffer[i + 1] == '[' - && buffer[i + 2] == '5' - && buffer[i + 3] == 'n' ) - { - char* DSR = getDSR(con); - - if ( DSR ) - write (fd_master, DSR, std::strlen(DSR)); - - i += 4; - } - else if ( i < length - 3 // Report cursor position (CPR) - && buffer[i] == '\033' - && buffer[i + 1] == '[' - && buffer[i + 2] == '6' - && buffer[i + 3] == 'n' ) - { - write (fd_master, "\033[25;80R", 8); // row 25 ; column 80 - i += 4; - } - else if ( i < length - 2 // Device attributes (DA) - && buffer[i] == '\033' - && buffer[i + 1] == '[' - && buffer[i + 2] == 'c' ) - { - char* DA = getDA(con); - - if ( DA ) - write (fd_master, DA, std::strlen(DA)); - - i += 3; - } - else if ( i < length - 3 // Device attributes (DA1) - && buffer[i] == '\033' - && buffer[i + 1] == '[' - && buffer[i + 2] == '1' - && buffer[i + 3] == 'c' ) - { - char* DA1 = getDA1(con); - - if ( DA1 ) - write (fd_master, DA1, std::strlen(DA1)); - i += 4; - } - else if ( i < length - 3 // Secondary device attributes (SEC_DA) - && buffer[i] == '\033' - && buffer[i + 1] == '[' - && buffer[i + 2] == '>' - && buffer[i + 3] == 'c' ) - { - char* SEC_DA = getSEC_DA(con); - - if ( SEC_DA ) - write (fd_master, SEC_DA, std::strlen(SEC_DA)); - - i += 4; - } - else if ( i < length - 4 // Report xterm window's title - && buffer[i] == '\033' - && buffer[i + 1] == '[' - && buffer[i + 2] == '2' - && buffer[i + 3] == '1' - && buffer[i + 4] == 't' ) - { - if ( con == urxvt ) - write (fd_master, "\033]l", 3); - else if ( con == tera_term ) - write (fd_master, "\033]l\033\\", 5); - else if ( con == screen ) - write (fd_master, "\033]lbash\033\\", 9); - else if ( con != ansi - && con != rxvt - && con != mlterm - && con != kde_konsole - && con != kterm - && con != cygwin - && con != mintty - && con != linux_con - && con != freebsd_con - && con != netbsd_con - && con != openbsd_con - && con != sun_con - && con != tmux ) - write (fd_master, "\033]lTITLE\033\\", 10); - - i += 5; - } - else if ( i < length - 7 // Get xterm color name 0-9 - && buffer[i] == '\033' - && buffer[i + 1] == ']' - && buffer[i + 2] == '4' - && buffer[i + 3] == ';' - && buffer[i + 4] >= '0' && buffer[i + 4] <= '9' - && buffer[i + 5] == ';' - && buffer[i + 6] == '?' - && buffer[i + 7] == '\a' ) - { - if ( con != ansi - && con != rxvt - && con != kde_konsole - && con != kterm - && con != cygwin - && con != mintty - && con != linux_con - && con != freebsd_con - && con != netbsd_con - && con != openbsd_con - && con != sun_con - && con != screen - && con != tmux ) - { - int n = buffer[i + 4] - '0'; - write (fd_master, "\033]4;", 4); - write (fd_master, &buffer[i + 4], 1); - write (fd_master, ";rgb:", 5); - write (fd_master, colorname[n], 14); - write (fd_master, "\a", 1); - } - - i += 8; - } - else if ( i < length - 8 // Get xterm color name 0-9 - && buffer[i] == '\033' - && buffer[i + 1] == ']' - && buffer[i + 2] == '4' - && buffer[i + 3] == ';' - && buffer[i + 4] >= '0' && buffer[i + 4] <= '9' - && buffer[i + 5] >= '0' && buffer[i + 5] <= '9' - && buffer[i + 6] == ';' - && buffer[i + 7] == '?' - && buffer[i + 8] == '\a' ) - { - if ( con != ansi - && con != rxvt - && con != kde_konsole - && con != kterm - && con != cygwin - && con != mintty - && con != linux_con - && con != freebsd_con - && con != netbsd_con - && con != openbsd_con - && con != sun_con - && con != screen - && con != tmux ) - { - int n = (buffer[i + 4] - '0') * 10 - + (buffer[i + 5] - '0'); - write (fd_master, "\033]4;", 4); - write (fd_master, &buffer[i + 4], 1); - write (fd_master, &buffer[i + 5], 1); - write (fd_master, ";rgb:", 5); - write (fd_master, colorname[n], 14); - write (fd_master, "\a", 1); - } - - i += 9; - } - else if ( i < length - 9 // Get xterm color name 0-9 - && buffer[i] == '\033' - && buffer[i + 1] == ']' - && buffer[i + 2] == '4' - && buffer[i + 3] == ';' - && buffer[i + 4] >= '0' && buffer[i + 4] <= '9' - && buffer[i + 5] >= '0' && buffer[i + 5] <= '9' - && buffer[i + 6] >= '0' && buffer[i + 6] <= '9' - && buffer[i + 7] == ';' - && buffer[i + 8] == '?' - && buffer[i + 9] == '\a' ) - { - if ( con != ansi - && con != rxvt - && con != kde_konsole - && con != kterm - && con != cygwin - && con != mintty - && con != linux_con - && con != freebsd_con - && con != netbsd_con - && con != openbsd_con - && con != sun_con - && con != screen - && con != tmux ) - { - int n = (buffer[i + 4] - '0') * 100 - + (buffer[i + 5] - '0') * 10 - + (buffer[i + 6] - '0'); - - if ( n < 256 ) - { - write (fd_master, "\033]4;", 4); - write (fd_master, &buffer[i + 4], 1); - write (fd_master, &buffer[i + 5], 1); - write (fd_master, &buffer[i + 6], 1); - write (fd_master, ";rgb:", 5); - write (fd_master, colorname[n], 14); - write (fd_master, "\a", 1); - } - } - - i += 10; - } - else - { - write (fd_stdout, &buffer[i], 1); // Send data to stdout - } - } -} - - // Put the test suite in the registry CPPUNIT_TEST_SUITE_REGISTRATION (FTermDetectionTest); diff --git a/test/ftermlinux-test.cpp b/test/ftermlinux-test.cpp new file mode 100644 index 00000000..b45461f6 --- /dev/null +++ b/test/ftermlinux-test.cpp @@ -0,0 +1,1525 @@ +/*********************************************************************** +* ftermlinux-test.cpp - FTermLinux unit tests * +* * +* This file is part of the Final Cut widget toolkit * +* * +* Copyright 2019 Markus Gans * +* * +* The Final Cut is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public License * +* as published by the Free Software Foundation; either version 3 of * +* the License, or (at your option) any later version. * +* * +* The Final Cut is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this program. If not, see * +* . * +***********************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) + #include +#endif + +#include +#include + +namespace test +{ + +//---------------------------------------------------------------------- +// class FSystemTest +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FSystemTest : public finalcut::FSystem +{ + // Typedefs and Enumerations + typedef struct + { + unsigned char shift : 1; + unsigned char alt_gr : 1; + unsigned char ctrl : 1; + unsigned char alt : 1; + unsigned char : 4; // padding bits + } shiftstate; + + typedef struct + { + unsigned char red; + unsigned char green; + unsigned char blue; + } rgb; + + typedef struct + { + rgb color[16]; + } ColorMap; + + enum ac_mode + { + index_mode, + data_mode + }; + + public: + // Constructor + FSystemTest(); + + // Destructor + virtual ~FSystemTest(); + + // Methods + virtual uChar inPortByte (uShort); + virtual void outPortByte (uChar, uShort); + virtual int isTTY (int); + virtual int ioctl (int, uLong, ...); + virtual int open (const char*, int, ...); + virtual int close (int); + virtual FILE* fopen (const char*, const char*); + virtual int fclose (FILE*); + + private: + // Methods + static void initVScreenInfo(); + static void initFScreenInfo(); + + // Data Members + static shiftstate shift_state; + static rgb terminal_color[16]; + static rgb defaultColor[16]; + static unimapdesc terminal_unicode_map; + static struct fb_var_screeninfo fb_terminal_info; + static struct fb_fix_screeninfo fb_terminal_fix_info; + static bool vga_port_access; + + ac_mode attribute_controller_mode = index_mode; + unsigned char ac_address_register[21] = \ + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x0c, 0x00, 0x0f, 0x08, 0x00 + }; + unsigned char ac_index = 0; + bool palette_addr_source_field = true; + unsigned char port_3cc = 0x67; // Miscellaneous output + unsigned char port_3da = 0; // Input status 1 + static uChar vga8x16[]; + static struct unipair unicode_cp437_pairs[]; +}; +#pragma pack(pop) + + +// private Data Member of FSystemTest +//---------------------------------------------------------------------- +uChar FSystemTest::vga8x16[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, // 1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, // 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, // 3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // 4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 6 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, // 9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, // 10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, // 11 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 12 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, // 13 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, // 14 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 15 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, // 16 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, // 17 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // 18 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, // 19 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, // 20 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, // 21 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, // 22 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, // 23 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 24 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, // 25 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 26 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 27 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 28 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 29 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, // 30 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // 31 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 32 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 33 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 34 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, // 35 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, // 36 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, // 37 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 38 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 39 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, // 40 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // 41 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 42 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 43 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, // 44 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 45 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 46 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, // 47 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, // 48 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, // 49 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, // 50 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 51 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, // 52 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 53 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 54 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, // 55 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 56 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, // 57 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // 58 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // 59 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, // 60 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 61 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, // 62 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 63 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, // 64 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 65 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, // 66 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, // 67 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, // 68 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, // 69 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, // 70 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, // 71 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 72 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 73 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, // 74 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, // 75 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, // 76 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 77 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 78 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 79 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, // 80 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, // 81 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, // 82 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 83 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 84 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 85 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, // 86 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00, // 87 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 88 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 89 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, // 90 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, // 91 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, // 92 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, // 93 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 94 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, // 95 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 96 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 97 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, // 98 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 99 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 100 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 101 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, // 102 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, // 103 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, // 104 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 105 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, // 106 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, // 107 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 108 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 109 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, // 110 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 111 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, // 112 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, // 113 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, // 114 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 115 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, // 116 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 117 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, // 118 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00, // 119 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, // 120 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, // 121 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, // 122 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, // 123 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 124 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, // 125 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 126 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, // 127 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, // 128 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 129 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 130 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 131 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 132 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 133 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 134 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, // 135 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 136 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 137 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 138 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 139 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 140 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 141 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 142 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 143 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, // 144 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, // 145 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, // 146 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 147 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 148 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 149 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 150 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 151 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, // 152 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 153 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 154 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 155 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, // 156 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 157 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00, // 158 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, // 159 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 160 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 161 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 162 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 163 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, // 164 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 165 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 166 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 167 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 168 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, // 169 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // 170 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00, // 171 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, // 172 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, // 173 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 174 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 175 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, // 176 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, // 177 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, // 178 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 179 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 180 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 181 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 182 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 183 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 184 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 185 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 186 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 187 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 188 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 189 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 190 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 191 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 192 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 193 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 194 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 195 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 196 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 197 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 198 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 199 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 200 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 201 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 202 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 203 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 204 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 205 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 206 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 207 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 208 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 209 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 210 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 211 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 212 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 213 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 214 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 215 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 216 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 217 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 218 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 219 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 220 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 221 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, // 222 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 223 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, // 224 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, // 225 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, // 226 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, // 227 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, // 228 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, // 229 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, // 230 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // 231 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, // 232 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, // 233 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, // 234 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, // 235 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 236 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, // 237 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, // 238 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 239 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, // 240 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, // 241 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, // 242 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, // 243 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 244 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, // 245 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // 246 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 247 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 248 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 249 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 250 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, // 251 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 252 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 253 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, // 254 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 255 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +struct unipair FSystemTest::unicode_cp437_pairs[] = +{ + // .----------- unicode + // | .---- fontpos + // | | + {0x0000, 0x00}, + {0x0020, 0x20}, + {0x0021, 0x21}, + {0x0022, 0x22}, + {0x0023, 0x23}, + {0x0024, 0x24}, + {0x0025, 0x25}, + {0x0026, 0x26}, + {0x0027, 0x27}, + {0x0028, 0x28}, + {0x0029, 0x29}, + {0x002a, 0x2a}, + {0x002b, 0x2b}, + {0x002c, 0x2c}, + {0x002d, 0x2d}, + {0x002e, 0x2e}, + {0x002f, 0x2f}, + {0x0030, 0x30}, + {0x0031, 0x31}, + {0x0032, 0x32}, + {0x0033, 0x33}, + {0x0034, 0x34}, + {0x0035, 0x35}, + {0x0036, 0x36}, + {0x0037, 0x37}, + {0x0038, 0x38}, + {0x0039, 0x39}, + {0x003a, 0x3a}, + {0x003b, 0x3b}, + {0x003c, 0x3c}, + {0x003d, 0x3d}, + {0x003e, 0x3e}, + {0x003f, 0x3f}, + {0x0040, 0x40}, + {0x0041, 0x41}, + {0x0042, 0x42}, + {0x0043, 0x43}, + {0x0044, 0x44}, + {0x0045, 0x45}, + {0x0046, 0x46}, + {0x0047, 0x47}, + {0x0048, 0x48}, + {0x0049, 0x49}, + {0x004a, 0x4a}, + {0x004b, 0x4b}, + {0x004c, 0x4c}, + {0x004d, 0x4d}, + {0x004e, 0x4e}, + {0x004f, 0x4f}, + {0x0050, 0x50}, + {0x0051, 0x51}, + {0x0052, 0x52}, + {0x0053, 0x53}, + {0x0054, 0x54}, + {0x0055, 0x55}, + {0x0056, 0x56}, + {0x0057, 0x57}, + {0x0058, 0x58}, + {0x0059, 0x59}, + {0x005a, 0x5a}, + {0x005b, 0x5b}, + {0x005c, 0x5c}, + {0x005d, 0x5d}, + {0x005e, 0x5e}, + {0x005f, 0x5f}, + {0x0060, 0x60}, + {0x0061, 0x61}, + {0x0062, 0x62}, + {0x0063, 0x63}, + {0x0064, 0x64}, + {0x0065, 0x65}, + {0x0066, 0x66}, + {0x0067, 0x67}, + {0x0068, 0x68}, + {0x0069, 0x69}, + {0x006a, 0x6a}, + {0x006b, 0x6b}, + {0x006c, 0x6c}, + {0x006d, 0x6d}, + {0x006e, 0x6e}, + {0x006f, 0x6f}, + {0x0070, 0x70}, + {0x0071, 0x71}, + {0x0072, 0x72}, + {0x0073, 0x73}, + {0x0074, 0x74}, + {0x0075, 0x75}, + {0x0076, 0x76}, + {0x0077, 0x77}, + {0x0078, 0x78}, + {0x0079, 0x79}, + {0x007a, 0x7a}, + {0x007b, 0x7b}, + {0x007c, 0x7c}, + {0x007d, 0x7d}, + {0x007e, 0x7e}, + {0x00a0, 0xff}, + {0x00a1, 0xad}, + {0x00a2, 0x9b}, + {0x00a3, 0x9c}, + {0x00a4, 0x0f}, + {0x00a5, 0x9d}, + {0x00a6, 0x7c}, + {0x00a7, 0x15}, + {0x00a8, 0x22}, + {0x00a9, 0x43}, + {0x00aa, 0xa6}, + {0x00ab, 0xae}, + {0x00ac, 0xaa}, + {0x00ad, 0x2d}, + {0x00ae, 0x52}, + {0x00b0, 0xf8}, + {0x00b1, 0xf1}, + {0x00b2, 0xfd}, + {0x00b4, 0x27}, + {0x00b5, 0xe6}, + {0x00b6, 0x14}, + {0x00b7, 0xfa}, + {0x00b8, 0x2c}, + {0x00ba, 0xa7}, + {0x00bb, 0xaf}, + {0x00bc, 0xac}, + {0x00bd, 0xab}, + {0x00bf, 0xa8}, + {0x00c0, 0x41}, + {0x00c1, 0x41}, + {0x00c2, 0x41}, + {0x00c3, 0x41}, + {0x00c4, 0x8e}, + {0x00c5, 0x8f}, + {0x00c6, 0x92}, + {0x00c7, 0x80}, + {0x00c8, 0x45}, + {0x00c9, 0x90}, + {0x00ca, 0x45}, + {0x00cb, 0x45}, + {0x00cc, 0x49}, + {0x00cd, 0x49}, + {0x00ce, 0x49}, + {0x00cf, 0x49}, + {0x00d0, 0x44}, + {0x00d1, 0xa5}, + {0x00d2, 0x4f}, + {0x00d3, 0x4f}, + {0x00d4, 0x4f}, + {0x00d5, 0x4f}, + {0x00d6, 0x99}, + {0x00d7, 0x78}, + {0x00d8, 0xe8}, + {0x00d9, 0x55}, + {0x00da, 0x55}, + {0x00db, 0x55}, + {0x00dc, 0x9a}, + {0x00dd, 0x59}, + {0x00df, 0xe1}, + {0x00e0, 0x85}, + {0x00e1, 0xa0}, + {0x00e2, 0x83}, + {0x00e3, 0x61}, + {0x00e4, 0x84}, + {0x00e5, 0x86}, + {0x00e6, 0x91}, + {0x00e7, 0x87}, + {0x00e8, 0x8a}, + {0x00e9, 0x82}, + {0x00ea, 0x88}, + {0x00eb, 0x89}, + {0x00ec, 0x8d}, + {0x00ed, 0xa1}, + {0x00ee, 0x8c}, + {0x00ef, 0x8b}, + {0x00f0, 0xeb}, + {0x00f1, 0xa4}, + {0x00f2, 0x95}, + {0x00f3, 0xa2}, + {0x00f4, 0x93}, + {0x00f5, 0x6f}, + {0x00f6, 0x94}, + {0x00f7, 0xf6}, + {0x00f8, 0xed}, + {0x00f9, 0x97}, + {0x00fa, 0xa3}, + {0x00fb, 0x96}, + {0x00fc, 0x81}, + {0x00fd, 0x79}, + {0x00ff, 0x98}, + {0x0192, 0x9f}, + {0x0393, 0xe2}, + {0x0398, 0xe9}, + {0x03a3, 0xe4}, + {0x03a6, 0xe8}, + {0x03a9, 0xea}, + {0x03b1, 0xe0}, + {0x03b2, 0xe1}, + {0x03b4, 0xeb}, + {0x03b5, 0xee}, + {0x03bc, 0xe6}, + {0x03c0, 0xe3}, + {0x03c3, 0xe5}, + {0x03c4, 0xe7}, + {0x03c6, 0xed}, + {0x2022, 0x07}, + {0x203c, 0x13}, + {0x207f, 0xfc}, + {0x20a7, 0x9e}, + {0x2126, 0xea}, + {0x212a, 0x4b}, + {0x212b, 0x8f}, + {0x2190, 0x1b}, + {0x2191, 0x18}, + {0x2192, 0x1a}, + {0x2193, 0x19}, + {0x2194, 0x1d}, + {0x2195, 0x12}, + {0x21a8, 0x17}, + {0x2208, 0xee}, + {0x2219, 0xf9}, + {0x221a, 0xfb}, + {0x221e, 0xec}, + {0x221f, 0x1c}, + {0x2229, 0xef}, + {0x2248, 0xf7}, + {0x2261, 0xf0}, + {0x2264, 0xf3}, + {0x2265, 0xf2}, + {0x2302, 0x7f}, + {0x2310, 0xa9}, + {0x2320, 0xf4}, + {0x2321, 0xf5}, + {0x23bd, 0x5f}, + {0x2500, 0xc4}, + {0x2502, 0xb3}, + {0x250c, 0xda}, + {0x2510, 0xbf}, + {0x2514, 0xc0}, + {0x2518, 0xd9}, + {0x251c, 0xc3}, + {0x2524, 0xb4}, + {0x252c, 0xc2}, + {0x2534, 0xc1}, + {0x253c, 0xc5}, + {0x2550, 0xcd}, + {0x2551, 0xba}, + {0x2552, 0xd5}, + {0x2553, 0xd6}, + {0x2554, 0xc9}, + {0x2555, 0xb8}, + {0x2556, 0xb7}, + {0x2557, 0xbb}, + {0x2558, 0xd4}, + {0x2559, 0xd3}, + {0x255a, 0xc8}, + {0x255b, 0xbe}, + {0x255c, 0xbd}, + {0x255d, 0xbc}, + {0x255e, 0xc6}, + {0x255f, 0xc7}, + {0x2560, 0xcc}, + {0x2561, 0xb5}, + {0x2562, 0xb6}, + {0x2563, 0xb9}, + {0x2564, 0xd1}, + {0x2565, 0xd2}, + {0x2566, 0xcb}, + {0x2567, 0xcf}, + {0x2568, 0xd0}, + {0x2569, 0xca}, + {0x256a, 0xd8}, + {0x256b, 0xd7}, + {0x256c, 0xce}, + {0x2580, 0xdf}, + {0x2584, 0xdc}, + {0x2588, 0xdb}, + {0x258c, 0xdd}, + {0x2590, 0xde}, + {0x2591, 0xb0}, + {0x2592, 0xb1}, + {0x2593, 0xb2}, + {0x25a0, 0xfe}, + {0x25ac, 0x16}, + {0x25b2, 0x1e}, + {0x25b6, 0x10}, + {0x25ba, 0x10}, + {0x25bc, 0x1f}, + {0x25c0, 0x11}, + {0x25c4, 0x11}, + {0x25c6, 0x04}, + {0x25cb, 0x09}, + {0x25d8, 0x08}, + {0x25d9, 0x0a}, + {0x263a, 0x01}, + {0x263b, 0x02}, + {0x263c, 0x0f}, + {0x2640, 0x0c}, + {0x2642, 0x0b}, + {0x2660, 0x06}, + {0x2663, 0x05}, + {0x2665, 0x03}, + {0x2666, 0x04}, + {0x266a, 0x0d}, + {0x266b, 0x0e}, + {0xf804, 0x5f}, + {0xfffd, 0xfe} +}; + +FSystemTest::rgb FSystemTest::terminal_color[16] { }; + +FSystemTest::rgb FSystemTest::defaultColor[16] +{ + {0x00, 0x00, 0x00}, {0xaa, 0x00, 0x00}, + {0x00, 0xaa, 0x00}, {0xaa, 0x55, 0x00}, + {0x00, 0x00, 0xaa}, {0xaa, 0x00, 0xaa}, + {0x00, 0xaa, 0xaa}, {0xaa, 0xaa, 0xaa}, + {0x55, 0x55, 0x55}, {0xff, 0x55, 0x55}, + {0x55, 0xff, 0x55}, {0xff, 0xff, 0x55}, + {0x55, 0x55, 0xff}, {0xff, 0x55, 0xff}, + {0x55, 0xff, 0xff}, {0xff, 0xff, 0xff} +}; + + +// static class attributes +//---------------------------------------------------------------------- +FSystemTest::shiftstate FSystemTest::shift_state; +unimapdesc FSystemTest::terminal_unicode_map; +struct fb_var_screeninfo FSystemTest::fb_terminal_info; +struct fb_fix_screeninfo FSystemTest::fb_terminal_fix_info; +bool FSystemTest::vga_port_access = false; + + +// constructors and destructor +//---------------------------------------------------------------------- +FSystemTest::FSystemTest() // constructor +{ + // fill bit field with 0 + memset (&shift_state, 0x00, sizeof(shift_state)); + memset (&terminal_unicode_map, 0x00, sizeof(terminal_unicode_map)); + + // init framebuffer + initVScreenInfo(); + initFScreenInfo(); +} + +//---------------------------------------------------------------------- +FSystemTest::~FSystemTest() // destructor +{ + if ( terminal_unicode_map.entries ) + delete[] terminal_unicode_map.entries; +} + + +// public methods of FSystemTest +//---------------------------------------------------------------------- +uChar FSystemTest::inPortByte (uShort port) +{ + std::cerr << "Call: im (port=" << port << ")\n"; + + switch ( port ) + { + case 0x3c1: + if ( attribute_controller_mode == data_mode ) + return ac_address_register[ac_index]; + break; + + case 0x3cc: + return port_3cc; + + case 0x3da: + attribute_controller_mode = index_mode; + return port_3da; + } + + return 0; +} + +//---------------------------------------------------------------------- +void FSystemTest::outPortByte (uChar value, uShort port) +{ + std::cerr << "Call: outb (value=" << value + << ", port=" << port << ")\n"; + + switch ( port ) + { + case 0x3c0: + if ( attribute_controller_mode == index_mode ) + { + ac_index = value & 0x1f; + palette_addr_source_field = bool(value & 0x20); + attribute_controller_mode = data_mode; + } + else + { + ac_address_register[ac_index] = value; + attribute_controller_mode = index_mode; + } + break; + + default: + return; + } +} + +//---------------------------------------------------------------------- +int FSystemTest::isTTY (int fd) +{ + std::cerr << "Call: isatty (fd=" << fd << ")\n"; + return 1; +} + +//---------------------------------------------------------------------- +int FSystemTest::ioctl (int fd, uLong request, ...) +{ + va_list args; + void* argp; + std::string req_string; + int ret_val = -1; + + va_start (args, request); + argp = va_arg (args, void*); + + switch ( request ) + { + case TIOCLINUX: + { + req_string = "TIOCLINUX"; + char* subcode = static_cast(argp); + unsigned char* state = reinterpret_cast(&shift_state); + + if ( *subcode == 6 ) + *subcode = static_cast(*state); + + ret_val = 0; + break; + } + + case KDFONTOP: + { + req_string = "KDFONTOP"; + struct console_font_op* fn = static_cast(argp); + fn->width = 8; + fn->height = 16; + fn->charcount = 256; + + if ( fn->data ) + memcpy (fn->data, &vga8x16, sizeof(vga8x16)); + + ret_val = 0; + break; + } + + case KDGKBTYPE: + { + req_string = "KDGKBTYPE"; + char* keyboard_type = static_cast(argp); + *keyboard_type = KB_101; + ret_val = 0; + break; + } + + case GIO_CMAP: + { + req_string = "GIO_CMAP"; + ColorMap* cmap = static_cast(argp); + // Set Default + if ( terminal_color[15].red == 0 + && terminal_color[15].green == 0 + && terminal_color[15].blue == 0 ) + { + for (size_t index = 0; index < 16; index++) + { + terminal_color[index].red = defaultColor[index].red; + terminal_color[index].green = defaultColor[index].green; + terminal_color[index].blue = defaultColor[index].blue; + } + } + + for (size_t index = 0; index < 16; index++) + { + cmap->color[index].red = terminal_color[index].red; + cmap->color[index].green = terminal_color[index].green; + cmap->color[index].blue = terminal_color[index].blue; + } + + ret_val = 0; + break; + } + + case PIO_CMAP: + { + req_string = "PIO_CMAP"; + ColorMap* cmap = static_cast(argp); + + for (size_t index = 0; index < 16; index++) + { + terminal_color[index].red = cmap->color[index].red; + terminal_color[index].green = cmap->color[index].green; + terminal_color[index].blue = cmap->color[index].blue; + } + + ret_val = 0; + break; + } + + case GIO_UNIMAP: + { + req_string = "GIO_UNIMAP"; + unimapdesc* umap = static_cast(argp); + size_t pairs = sizeof(unicode_cp437_pairs) / sizeof(unipair); + size_t pairs_size = pairs * sizeof(unipair); + + // Sets the default unicode map of the terminal on the first call + if ( terminal_unicode_map.entries == 0 ) + { + terminal_unicode_map.entry_ct = pairs; + terminal_unicode_map.entries = new unipair[pairs](); + memcpy (terminal_unicode_map.entries, &unicode_cp437_pairs, pairs_size); + } + + umap->entry_ct = terminal_unicode_map.entry_ct; + + if ( umap->entries && terminal_unicode_map.entries ) + { + memcpy (umap->entries, &terminal_unicode_map.entries, pairs_size); + ret_val = 0; + } + else + ret_val = -1; + + break; + } + + case PIO_UNIMAP: + { + req_string = "PIO_UNIMAP"; + unimapdesc* umap = static_cast(argp); + memcpy (&terminal_unicode_map, umap, sizeof(*umap)); + ret_val = 0; + break; + } + + case PIO_UNIMAPCLR: + req_string = "PIO_UNIMAPCLR"; + ret_val = 0; + break; + + case FBIOGET_VSCREENINFO: + { + req_string = "FBIOGET_VSCREENINFO"; + struct fb_var_screeninfo* fb_var \ + = static_cast(argp); + memcpy (fb_var, &fb_terminal_info, sizeof(fb_terminal_info)); + ret_val = 0; + break; + } + + case FBIOGET_FSCREENINFO: + { + req_string = "FBIOGET_FSCREENINFO"; + struct fb_fix_screeninfo* fb_fix + = static_cast(argp); + memcpy (fb_fix, &fb_terminal_fix_info, sizeof(fb_terminal_fix_info)); + ret_val = 0; + break; + } + + case KDENABIO: + { + req_string = "KDENABIO"; + vga_port_access = true; + ret_val = 0; + break; + } + + case KDDISABIO: + { + req_string = "KDDISABIO"; + vga_port_access = false; + ret_val = 0; + break; + } + + case TIOCGWINSZ: + { + req_string = "TIOCGWINSZ"; + struct winsize* win_size = static_cast(argp); + win_size->ws_col = 96; + win_size->ws_row = 36; + ret_val = 0; + break; + } + } + + va_end (args); + + std::cerr << "Call: ioctl (fd=" << fd + << ", request=" << req_string + << "(0x" << std::hex << request << ")" + << ", argp=" << argp << ")\n"; + return ret_val; +} + +//---------------------------------------------------------------------- +int FSystemTest::open (const char* pathname, int flags, ...) +{ + va_list args; + va_start (args, flags); + mode_t mode = static_cast(va_arg (args, int)); + va_end (args); + + std::cerr << "Call: open (pathname=\"" << pathname + << "\", flags=" << flags + << ", mode=" << mode << ")\n"; + + if ( std::strncmp(pathname, "/dev/fb0", 9) == 0 + || std::strncmp(pathname, "/dev/fb/0", 9) == 0 ) + return 99; // File descriptor + + return 0; +} + +//---------------------------------------------------------------------- +int FSystemTest::close (int fildes) +{ + std::cerr << "Call: close (fildes=" << fildes << ")\n"; + return 0; +} + +//---------------------------------------------------------------------- +FILE* FSystemTest::fopen (const char* path, const char* mode) +{ + std::cerr << "Call: fopen (path=" << path + << ", mode=" << mode << ")\n"; + return 0; +} + +//---------------------------------------------------------------------- +int FSystemTest::fclose (FILE* fp) +{ + std::cerr << "Call: fclose (fp=" << fp << ")\n"; + return 0; +} + +// private methods of FSystemTest +//---------------------------------------------------------------------- +void FSystemTest::initVScreenInfo() +{ + fb_terminal_info.xres = 800; + fb_terminal_info.yres = 600; + fb_terminal_info.xres_virtual = 1176; + fb_terminal_info.yres_virtual = 885; + fb_terminal_info.xoffset = 0; + fb_terminal_info.yoffset = 0; + fb_terminal_info.bits_per_pixel = 32; + fb_terminal_info.grayscale = 0; + fb_terminal_info.red.offset = 16; + fb_terminal_info.red.length = 8; + fb_terminal_info.red.msb_right = 0; + fb_terminal_info.green.offset = 8; + fb_terminal_info.green.length = 8, + fb_terminal_info.green.msb_right = 0; + fb_terminal_info.blue.offset = 0; + fb_terminal_info.blue.length = 8; + fb_terminal_info.blue.msb_right = 0; + fb_terminal_info.transp.offset = 0; + fb_terminal_info.blue.length = 0; + fb_terminal_info.blue.msb_right = 0; + fb_terminal_info.nonstd = 0; + fb_terminal_info.activate = 0; + fb_terminal_info.height = 0xffffffff; + fb_terminal_info.width = 0xffffffff; + fb_terminal_info.accel_flags = 0; + fb_terminal_info.pixclock = 0; + fb_terminal_info.left_margin = 0; + fb_terminal_info.right_margin = 0; + fb_terminal_info.upper_margin = 0; + fb_terminal_info.lower_margin = 0; + fb_terminal_info.hsync_len = 0; + fb_terminal_info.vsync_len = 0; + fb_terminal_info.sync = 0; + fb_terminal_info.vmode = 0; + fb_terminal_info.rotate = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) + fb_terminal_info.colorspace = 0; +#endif + fb_terminal_info.reserved[0] = 0; + fb_terminal_info.reserved[1] = 0; + fb_terminal_info.reserved[2] = 0; + fb_terminal_info.reserved[3] = 0; +} + +//---------------------------------------------------------------------- +void FSystemTest::initFScreenInfo() +{ + char id[16] { "VESA VGA" }; + std::strncpy (fb_terminal_fix_info.id, id, sizeof(id)); + fb_terminal_fix_info.smem_start = 0xf9000000; + fb_terminal_fix_info.smem_len = 0x00500000; + fb_terminal_fix_info.type = 0; + fb_terminal_fix_info.type_aux = 0; + fb_terminal_fix_info.visual = 2; + fb_terminal_fix_info.xpanstep = 0; + fb_terminal_fix_info.ypanstep = 0; + fb_terminal_fix_info.ywrapstep = 0; + fb_terminal_fix_info.line_length = 5120; + fb_terminal_fix_info.mmio_start = 0; + fb_terminal_fix_info.mmio_len = 0; + fb_terminal_fix_info.accel = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) + fb_terminal_fix_info.capabilities = 0; +#endif + fb_terminal_fix_info.reserved[0] = 0; + fb_terminal_fix_info.reserved[1] = 0; +} + +} // namespace test + + +//---------------------------------------------------------------------- +// class FTermLinuxTest +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FTermLinuxTest : public CPPUNIT_NS::TestFixture, test::ConEmu +{ + public: + FTermLinuxTest(); + + protected: + void classNameTest(); + void linuxConsoleTest(); + + private: + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE (FTermLinuxTest); + + // Add a methods to the test suite + CPPUNIT_TEST (classNameTest); + CPPUNIT_TEST (linuxConsoleTest); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); +}; +#pragma pack(pop) + +//---------------------------------------------------------------------- +FTermLinuxTest::FTermLinuxTest() +{ + +} + +//---------------------------------------------------------------------- +void FTermLinuxTest::classNameTest() +{ + const finalcut::FTermLinux p; + const char* const classname = p.getClassName(); + CPPUNIT_ASSERT ( std::strcmp(classname, "FTermLinux") == 0 ); +} + +//---------------------------------------------------------------------- +void FTermLinuxTest::linuxConsoleTest() +{ + finalcut::FTermData* data; + finalcut::FSystem* fsys; + fsys = new test::FSystemTest(); + finalcut::FTerm::setFSystem(fsys); + finalcut::FTermDetection* term_detection; + std::cout << "\n"; + data = finalcut::FTerm::getFTermData(); + + auto& encoding_list = data->getEncodingList(); + encoding_list["UTF-8"] = finalcut::fc::UTF8; + encoding_list["UTF8"] = finalcut::fc::UTF8; + encoding_list["VT100"] = finalcut::fc::VT100; + encoding_list["PC"] = finalcut::fc::PC; + encoding_list["ASCII"] = finalcut::fc::ASCII; + + data->setTermEncoding(finalcut::fc::PC); + + auto& character_map = data->getCharSubstitutionMap(); + character_map[finalcut::fc::BlackCircle] = L'*'; + character_map[finalcut::fc::Times] = L'x'; + character_map[L'ˣ'] = finalcut::fc::SuperscriptLatinSmallLetterN; + + data->setBaudrate(38400); + data->setTermType("linux"); + data->setTermFileName("/dev/tty2"); + +#if DEBUG + data->setFramebufferBpp(32); +#endif + + data->supportShadowCharacter (false); + data->supportHalfBlockCharacter (false); + data->supportCursorOptimisation (true); + data->setCursorHidden (true); + data->useAlternateScreen (false); + data->setASCIIConsole (true); + data->setVT100Console (false); + data->setUTF8Console (false); + data->setUTF8 (false); + data->setNewFont (false); + data->setVGAFont (false); + data->setMonochron (false); + data->setTermResized (false); + + term_detection = finalcut::FTerm::getFTermDetection(); + finalcut::FTermLinux linux; + + term_detection->setLinuxTerm(true); + + pid_t pid = forkConEmu(); + + if ( isConEmuChildProcess(pid) ) + { + setenv ("TERM", "linux", 1); + setenv ("COLUMNS", "90", 1); + setenv ("LINES", "30", 1); + unsetenv("TERMCAP"); + unsetenv("COLORTERM"); + unsetenv("COLORFGBG"); + unsetenv("VTE_VERSION"); + unsetenv("XTERM_VERSION"); + unsetenv("ROXTERM_ID"); + unsetenv("KONSOLE_DBUS_SESSION"); + unsetenv("KONSOLE_DCOP"); + unsetenv("TMUX"); + + term_detection->detect(); + linux.init(); + + CPPUNIT_ASSERT ( isatty(3) == 0 ); + CPPUNIT_ASSERT ( term_detection->isLinuxTerm() ); + CPPUNIT_ASSERT ( data->getTermGeometry().getWidth() == 96 ); + CPPUNIT_ASSERT ( data->getTermGeometry().getHeight() == 36 ); + CPPUNIT_ASSERT ( data->hasShadowCharacter() ); + CPPUNIT_ASSERT ( data->hasHalfBlockCharacter() ); + CPPUNIT_ASSERT ( linux.getFramebufferBpp() == 32 ); + + + // linux->setUTF8 (enable); + // linux->loadVGAFont() + // linux->loadNewFont() + // linux->loadOldFont(fc::character); + // linux->initCharMap (fc::character); + // linux->restoreCursorStyle(); + // linux->saveColorMap(); + // linux->resetColorMap(); + // linux->setPalette(index, r, g, b); + // linux->setBeep (Hz, ms); + // linux->resetBeep(); + // const char* cstyle = linux->setCursorStyle ( fc::underscore_cursor + // , data->isCursorHidden() ); + closeConEmuStdStreams(); + exit(EXIT_SUCCESS); + } + else // Parent + { + // Start the terminal emulation + startConEmuTerminal (ConEmu::linux_con); + + if ( waitpid(pid, 0, WUNTRACED) != pid ) + std::cerr << "waitpid error" << std::endl; + } + + linux.finish(); +} + + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION (FTermLinuxTest); + +// The general unit test main part +#include