/* ************************************ * void ScrollScreenBuffer(HANDLE h, INT x) * 功能 滚动屏幕 * 参数 HANDLE h, 控制台句柄; INT x, 行 **************************************/ void ScrollScreenBuffer(HANDLE h, INT x) { SMALL_RECT srctScrollRect, srctClipRect; CHAR_INFO chiFill; COORD coordDest; srctScrollRect.Left = 0; srctScrollRect.Top = 1; srctScrollRect.Right = csbiInfo.dwSize.X - x; srctScrollRect.Bottom = csbiInfo.dwSize.Y - x; // 目的 coordDest.X = 0; coordDest.Y = 0; // left unchanged. srctClipRect = srctScrollRect; // 设置填充的字符串和属性 chiFill.Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; chiFill.Char.AsciiChar = (char)' '; // 滚动一行 ScrollConsoleScreenBuffer( h, // 屏幕缓冲区句柄 &srctScrollRect, // scrolling rectangle &srctClipRect, // clipping rectangle coordDest, // 右上角目的cell &chiFill); // 填充的字符的颜色 }
co_rc_t console_widget_NT_t::op_bmove( const co_console_unit &Y, const co_console_unit &X, const co_console_unit &T, const co_console_unit &L, const co_console_unit &B, const co_console_unit &R) { SMALL_RECT r; COORD c; c.Y = Y; c.X = X; r.Top = T; r.Left = L; r.Bottom = B; r.Right = R; if(!ScrollConsoleScreenBuffer(buffer, &r, ®ion, c, &blank)) co_debug("ScrollConsoleScreenBuffer() error %d\n", GetLastError()); return CO_RC(OK); }
static void scroll_line (int dist, int direction) { /* The idea here is to implement a horizontal scroll in one line to implement delete and half of insert. */ SMALL_RECT scroll; COORD dest; CHAR_INFO fill; struct frame * f = PICK_FRAME (); scroll.Top = cursor_coords.Y; scroll.Bottom = cursor_coords.Y; if (direction == LEFT) { scroll.Left = cursor_coords.X + dist; scroll.Right = FRAME_COLS (f) - 1; } else { scroll.Left = cursor_coords.X; scroll.Right = FRAME_COLS (f) - dist - 1; } dest.X = cursor_coords.X; dest.Y = cursor_coords.Y; fill.Char.AsciiChar = 0x20; fill.Attributes = char_attr_normal; ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill); }
void ScrollScreenBuffer(HANDLE h, INT x) { SMALL_RECT srctScrollRect, srctClipRect; CHAR_INFO chiFill; COORD coordDest; srctScrollRect.Left = 0; srctScrollRect.Top = 1; srctScrollRect.Right = csbiInfo.dwSize.X - (SHORT)x; srctScrollRect.Bottom = csbiInfo.dwSize.Y - (SHORT)x; // The destination for the scroll rectangle is one row up. coordDest.X = 0; coordDest.Y = 0; // The clipping rectangle is the same as the scrolling rectangle. // The destination row is left unchanged. srctClipRect = srctScrollRect; // Set the fill character and attributes. chiFill.Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; chiFill.Char.AsciiChar = (char)' '; // Scroll up one line. ScrollConsoleScreenBuffer( h, // screen buffer handle &srctScrollRect, // scrolling rectangle &srctClipRect, // clipping rectangle coordDest, // top left destination cell &chiFill); // fill character and color }
BOOL Scroll5( IN HANDLE Handle ) { SMALL_RECT ScrollRectangle; CHAR_INFO Fill; COORD DestinationOrigin; CONSOLE_SCREEN_BUFFER_INFO ScreenInfo; if (!GetConsoleScreenBufferInfo(Handle,&ScreenInfo)) { DbgPrint("ERROR: GetConsoleScreenBufferInfo failed\n"); } ScrollRectangle = ScreenInfo.srWindow; Fill.Attributes = BACKGROUND_GREEN; Fill.Char.UnicodeChar = 'T'; DestinationOrigin.X = 0; DestinationOrigin.Y = -(ScreenInfo.srWindow.Bottom - ScreenInfo.srWindow.Top + 1); if (!ScrollConsoleScreenBuffer(Handle, &ScrollRectangle, NULL, DestinationOrigin, &Fill)) { DbgPrint("ScrollConsoleScreenBuffer failed\n"); return FALSE; } DbgPrint("scrolled entire screen\n"); DbgBreakPoint(); return TRUE; }
//------------------------------------------------------------------------------ void win_screen_buffer::delete_chars(int count) { if (count <= 0) return; CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(m_handle, &csbi); SMALL_RECT rect; rect.Left = csbi.dwCursorPosition.X + count; rect.Right = csbi.dwSize.X - 1; rect.Top = rect.Bottom = csbi.dwCursorPosition.Y; CHAR_INFO fill; fill.Char.AsciiChar = ' '; fill.Attributes = csbi.wAttributes; ScrollConsoleScreenBuffer(m_handle, &rect, NULL, csbi.dwCursorPosition, &fill); int chars_moved = rect.Right - rect.Left + 1; if (chars_moved < count) { COORD xy = csbi.dwCursorPosition; xy.X += chars_moved; count -= chars_moved; DWORD written; FillConsoleOutputCharacterW(m_handle, ' ', count, xy, &written); FillConsoleOutputAttribute(m_handle, csbi.wAttributes, count, xy, &written); } }
VALUE rb_ScrollConsoleScreenBuffer( VALUE self, VALUE hConsoleOutput, VALUE left1, VALUE top1, VALUE right1, VALUE bottom1, VALUE col, VALUE row, VALUE cChar, VALUE attr, VALUE left2, VALUE top2, VALUE right2, VALUE bottom2) { HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) ); CHAR_INFO fill; COORD origin; SMALL_RECT scroll, clip; scroll.Left = NUM2INT( left1 ); scroll.Right = NUM2INT( right1 ); scroll.Top = NUM2INT( top1 ); scroll.Bottom = NUM2INT( bottom1 ); clip.Left = NUM2INT( left2 ); clip.Right = NUM2INT( right2 ); clip.Top = NUM2INT( top2 ); clip.Bottom = NUM2INT( bottom2 ); #ifdef UNICODE fill.Char.UnicodeChar = NUM2CHR( cChar ); #else fill.Char.AsciiChar = NUM2CHR( cChar ); #endif fill.Attributes = NUM2INT(attr); origin.X = NUM2UINT( col ); origin.Y = NUM2UINT( row ); if ( ScrollConsoleScreenBuffer( handle, &scroll, &clip, origin, &fill ) ) return INT2FIX(1); return rb_getWin32Error(); }
unsigned int __stdcall Rain(void *param) { DWORD dwRead; SMALL_RECT srcScrollRect; char *bLengthOfRain, *bIsSpace, *buff; COORD coordLine0 = {0, 0}, coordLine2 = {0, 2}; CHAR_INFO char_info = {' ', FOREGROUND_GREEN|FOREGROUND_INTENSITY}; // 设置要移动的范围 // srcScrollRect.Top = coord.Y; srcScrollRect.Left = 0; srcScrollRect.Right = sColNum - 1; srcScrollRect.Bottom = sRowNum - 1; buff = (char *)malloc(sColNum); bIsSpace = (char *)malloc(sColNum); bLengthOfRain = (char *)malloc(sColNum); memset(bIsSpace, 0, sColNum); memset(bLengthOfRain, 0, sColNum); do { Sleep(50); /* if (bStart) coord.Y = 2; else coord.Y = 0; */ // 上面的if...else...简化如下 coord.Y = bStart << 1; coordDest.Y = coord.Y + 1; srcScrollRect.Top = coord.Y; // 移动一块字符, 并用 char_info 填充空出来的区域 ScrollConsoleScreenBuffer(hStdOut, &srcScrollRect, 0, coordDest, &char_info); // 输出一行字符 for (char index = 0; index != sColNum; ++index) { if (!bLengthOfRain[index]--) { bIsSpace[index] = GetRandom(0, 4); // 25% 概率出字符 bLengthOfRain[index] = GetRandom(10, 25); // 每列最短10, 最长25 } buff[index] = bIsSpace[index] ? ' ' : GetRandom(0x30, 0x7E); } WriteConsoleOutputCharacter(hStdOut, buff, sColNum, coord, NULL); if (bStart) // 读取第3行的内容并写到第1行 { ReadConsoleOutputCharacter(hStdOut, buff, sColNum, coordLine2, &dwRead); WriteConsoleOutputCharacter(hStdOut, buff, dwRead, coordLine0, NULL); } } while (!kbhit()); bRainExit = true; free(bLengthOfRain); free(bIsSpace); free(buff); // MessageBox(NULL, _T("t1 free success"), NULL, 0x40); return 0; }
void Screen::scroll (int destX, int destY, const SMALL_RECT& scrollRect, const SMALL_RECT *pClipRect) { CHAR_INFO fill; fill.Char.AsciiChar = ' '; fill.Attributes = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN; COORD dest; dest.X = destX; dest.Y = destY; if (ScrollConsoleScreenBuffer (mScreenBuf, &scrollRect, pClipRect, dest, &fill) != TRUE) throw AppException (WHERE, ERR_WINDOWS_FMT, "ScrollConsoleScreenBuffer", GetLastError ()); }
JNIEXPORT void JNICALL Java_com_yifanlu_Josh_Josh_SCROLLCONSOLESCREENBUFFER (JNIEnv *env, jclass jcls, jlong pointer, jint scrollLeft, jint scrollTop, jint scrollRight, jint scrollBottom, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom, jint toX, jint toY, jchar fillChar, jint fillAttribute) { HANDLE hConsole = pointerToHandle(pointer); SMALL_RECT scroll = {scrollLeft, scrollTop, scrollRight, scrollBottom}; SMALL_RECT clip = {clipLeft, clipTop, clipRight, clipBottom}; COORD to = {toX, toY}; CHAR_INFO fill; fill.Attributes = fillAttribute; fill.Char.UnicodeChar = (char)fillChar; ScrollConsoleScreenBuffer(hConsole, &scroll, clipLeft == -1 ? NULL : &clip, to, &fill); }
void Sys_ConScrollLine() { SMALL_RECT src; COORD dest; CHAR_INFO fill; src.Left = 0; src.Right = cbInfo.dwSize.X - 1; src.Top = 1; src.Bottom = cbInfo.dwSize.Y - 2; dest.X = 0; dest.Y = 0; fill.Attributes = TEXT_ATTRIB; fill.Char.AsciiChar = ' '; ScrollConsoleScreenBuffer(hcScreen, &src, NULL, dest, &fill); }
/* scroll down */ void ossscr(int top, int left, int bottom, int right, int blankcolor) { COORD newpos; SMALL_RECT pos; SMALL_RECT clip; CHAR_INFO fill; pos.Top = clip.Top = top; pos.Left = clip.Left = left; pos.Bottom = clip.Bottom = bottom; pos.Right = clip.Right = right; newpos.X = left; newpos.Y = top - 1; fill.Char.AsciiChar = ' '; fill.Attributes = blankcolor; ScrollConsoleScreenBuffer(G_out_bufhdl, &pos, &clip, newpos, &fill); }
//------------------------------------------------------------------------------ void win_screen_buffer::insert_chars(int count) { if (count <= 0) return; CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(m_handle, &csbi); SMALL_RECT rect; rect.Left = csbi.dwCursorPosition.X; rect.Right = csbi.dwSize.X; rect.Top = rect.Bottom = csbi.dwCursorPosition.Y; CHAR_INFO fill; fill.Char.AsciiChar = ' '; fill.Attributes = csbi.wAttributes; csbi.dwCursorPosition.X += count; ScrollConsoleScreenBuffer(m_handle, &rect, NULL, csbi.dwCursorPosition, &fill); }
co_rc_t console_widget_NT_t::op_scroll_down( const co_console_unit &T, const co_console_unit &B, const co_console_unit &L) { SMALL_RECT r; COORD c; r.Left = region.Left; r.Right = region.Right; r.Top = T; r.Bottom = B; c.X = 0; c.Y = r.Top + L; if (!ScrollConsoleScreenBuffer(buffer, &r, &r, c, &blank)) co_debug("ScrollConsoleScreenBuffer() error code: %d \n", GetLastError()); return CO_RC(OK); }
void InterpretEscSeq( void ) { int i; WORD attribut; CONSOLE_SCREEN_BUFFER_INFO Info; CONSOLE_CURSOR_INFO CursInfo; DWORD len, NumberOfCharsWritten; COORD Pos; SMALL_RECT Rect; CHAR_INFO CharInfo; if (prefix == '[') { if (prefix2 == '?' && (suffix == 'h' || suffix == 'l')) { if (es_argc == 1 && es_argv[0] == 25) { GetConsoleCursorInfo( hConOut, &CursInfo ); CursInfo.bVisible = (suffix == 'h'); SetConsoleCursorInfo( hConOut, &CursInfo ); return; } } // Ignore any other \e[? or \e[> sequences. if (prefix2 != 0) return; GetConsoleScreenBufferInfo( hConOut, &Info ); switch (suffix) { case 'm': if (es_argc == 0) es_argv[es_argc++] = 0; for (i = 0; i < es_argc; i++) { switch (es_argv[i]) { case 0: foreground = org_fg; background = org_bg; bold = (es_argc == 1) ? org_bold : 0; underline = (es_argc == 1) ? org_ul : 0; rvideo = 0; concealed = 0; break; case 1: bold = FOREGROUND_INTENSITY; break; case 5: /* blink */ case 4: underline = BACKGROUND_INTENSITY; break; case 7: rvideo = 1; break; case 8: concealed = 1; break; case 21: bold = 0; break; case 25: case 24: underline = 0; break; case 27: rvideo = 0; break; case 28: concealed = 0; break; } if (30 <= es_argv[i] && es_argv[i] <= 37) foreground = es_argv[i]-30; if (40 <= es_argv[i] && es_argv[i] <= 47) background = es_argv[i]-40; } if (concealed) { if (rvideo) { attribut = foregroundcolor[foreground] | backgroundcolor[foreground]; if (bold) attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; } else { attribut = foregroundcolor[background] | backgroundcolor[background]; if (underline) attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; } } else if (rvideo) { attribut = foregroundcolor[background] | backgroundcolor[foreground]; if (bold) attribut |= BACKGROUND_INTENSITY; if (underline) attribut |= FOREGROUND_INTENSITY; } else attribut = foregroundcolor[foreground] | backgroundcolor[background] | bold | underline; SetConsoleTextAttribute( hConOut, attribut ); return; case 'J': if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[J == ESC[0J if (es_argc != 1) return; switch (es_argv[0]) { case 0: // ESC[0J erase from cursor to end of display len = (Info.dwSize.Y - Info.dwCursorPosition.Y - 1) * Info.dwSize.X + Info.dwSize.X - Info.dwCursorPosition.X - 1; FillConsoleOutputCharacter( hConOut, ' ', len, Info.dwCursorPosition, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Info.dwCursorPosition, &NumberOfCharsWritten ); return; case 1: // ESC[1J erase from start to cursor. Pos.X = 0; Pos.Y = 0; len = Info.dwCursorPosition.Y * Info.dwSize.X + Info.dwCursorPosition.X + 1; FillConsoleOutputCharacter( hConOut, ' ', len, Pos, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos, &NumberOfCharsWritten ); return; case 2: // ESC[2J Clear screen and home cursor Pos.X = 0; Pos.Y = 0; len = Info.dwSize.X * Info.dwSize.Y; FillConsoleOutputCharacter( hConOut, ' ', len, Pos, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos, &NumberOfCharsWritten ); SetConsoleCursorPosition( hConOut, Pos ); return; default: return; } case 'K': if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[K == ESC[0K if (es_argc != 1) return; switch (es_argv[0]) { case 0: // ESC[0K Clear to end of line len = Info.srWindow.Right - Info.dwCursorPosition.X + 1; FillConsoleOutputCharacter( hConOut, ' ', len, Info.dwCursorPosition, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Info.dwCursorPosition, &NumberOfCharsWritten ); return; case 1: // ESC[1K Clear from start of line to cursor Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; FillConsoleOutputCharacter( hConOut, ' ', Info.dwCursorPosition.X + 1, Pos, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, Info.dwCursorPosition.X + 1, Pos, &NumberOfCharsWritten ); return; case 2: // ESC[2K Clear whole line. Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; FillConsoleOutputCharacter( hConOut, ' ', Info.dwSize.X, Pos, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, Info.dwSize.X, Pos, &NumberOfCharsWritten ); return; default: return; } case 'L': // ESC[#L Insert # blank lines. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L if (es_argc != 1) return; Rect.Left = 0; Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwSize.Y - 1; Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; CharInfo.Char.UnicodeChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); return; case 'M': // ESC[#M Delete # lines. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M if (es_argc != 1) return; if (es_argv[0] > Info.dwSize.Y - Info.dwCursorPosition.Y) es_argv[0] = Info.dwSize.Y - Info.dwCursorPosition.Y; Rect.Left = 0; Rect.Top = Info.dwCursorPosition.Y + es_argv[0]; Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwSize.Y - 1; Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; CharInfo.Char.UnicodeChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); return; case 'P': // ESC[#P Delete # characters. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[P == ESC[1P if (es_argc != 1) return; if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1) es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X; Rect.Left = Info.dwCursorPosition.X + es_argv[0]; Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwCursorPosition.Y; CharInfo.Char.UnicodeChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Info.dwCursorPosition, &CharInfo ); return; case '@': // ESC[#@ Insert # blank characters. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[@ == ESC[1@ if (es_argc != 1) return; if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1) es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X; Rect.Left = Info.dwCursorPosition.X; Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1 - es_argv[0]; Rect.Bottom = Info.dwCursorPosition.Y; Pos.X = Info.dwCursorPosition.X + es_argv[0]; Pos.Y = Info.dwCursorPosition.Y; CharInfo.Char.UnicodeChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); return; case 'A': // ESC[#A Moves cursor up # lines if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A if (es_argc != 1) return; Pos.Y = Info.dwCursorPosition.Y - es_argv[0]; if (Pos.Y < 0) Pos.Y = 0; Pos.X = Info.dwCursorPosition.X; SetConsoleCursorPosition( hConOut, Pos ); return; case 'B': // ESC[#B Moves cursor down # lines if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B if (es_argc != 1) return; Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; Pos.X = Info.dwCursorPosition.X; SetConsoleCursorPosition( hConOut, Pos ); return; case 'C': // ESC[#C Moves cursor forward # spaces if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[C == ESC[1C if (es_argc != 1) return; Pos.X = Info.dwCursorPosition.X + es_argv[0]; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition( hConOut, Pos ); return; case 'D': // ESC[#D Moves cursor back # spaces if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[D == ESC[1D if (es_argc != 1) return; Pos.X = Info.dwCursorPosition.X - es_argv[0]; if (Pos.X < 0) Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition( hConOut, Pos ); return; case 'E': // ESC[#E Moves cursor down # lines, column 1. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E if (es_argc != 1) return; Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; Pos.X = 0; SetConsoleCursorPosition( hConOut, Pos ); return; case 'F': // ESC[#F Moves cursor up # lines, column 1. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F if (es_argc != 1) return; Pos.Y = Info.dwCursorPosition.Y - es_argv[0]; if (Pos.Y < 0) Pos.Y = 0; Pos.X = 0; SetConsoleCursorPosition( hConOut, Pos ); return; case 'G': // ESC[#G Moves cursor column # in current row. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[G == ESC[1G if (es_argc != 1) return; Pos.X = es_argv[0] - 1; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; if (Pos.X < 0) Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition( hConOut, Pos ); return; case 'f': // ESC[#;#f case 'H': // ESC[#;#H Moves cursor to line #, column # if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[H == ESC[1;1H if (es_argc == 1) es_argv[es_argc++] = 1; // ESC[#H == ESC[#;1H if (es_argc > 2) return; Pos.X = es_argv[1] - 1; if (Pos.X < 0) Pos.X = 0; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; Pos.Y = es_argv[0] - 1; if (Pos.Y < 0) Pos.Y = 0; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; SetConsoleCursorPosition( hConOut, Pos ); return; case 's': // ESC[s Saves cursor position for recall later if (es_argc != 0) return; SavePos = Info.dwCursorPosition; return; case 'u': // ESC[u Return to saved cursor position if (es_argc != 0) return; SetConsoleCursorPosition( hConOut, SavePos ); return; case 'n': // ESC[#n Device status report if (es_argc != 1) return; // ESC[n == ESC[0n -> ignored switch (es_argv[0]) { case 5: // ESC[5n Report status SendSequence( L"\33[0n" ); // "OK" return; case 6: // ESC[6n Report cursor position { TCHAR buf[32]; wsprintf( buf, L"\33[%d;%dR", Info.dwCursorPosition.Y + 1, Info.dwCursorPosition.X + 1 ); SendSequence( buf ); } return; default: return; } case 't': // ESC[#t Window manipulation if (es_argc != 1) return; if (es_argv[0] == 21) // ESC[21t Report xterm window's title { TCHAR buf[MAX_PATH*2]; DWORD len = GetConsoleTitle( buf+3, lenof(buf)-3-2 ); // Too bad if it's too big or fails. buf[0] = ESC; buf[1] = ']'; buf[2] = 'l'; buf[3+len] = ESC; buf[3+len+1] = '\\'; buf[3+len+2] = '\0'; SendSequence( buf ); } return; default: return; } } else // (prefix == ']') { // Ignore any \e]? or \e]> sequences. if (prefix2 != 0) return; if (es_argc == 1 && es_argv[0] == 0) // ESC]0;titleST { SetConsoleTitle( Pt_arg ); } } }
BOOL Scroll4( IN HANDLE Handle ) { CHAR_INFO CharBuffer[20][25]; SMALL_RECT WriteRegion; COORD BufferSize; COORD BufferCoord; CHAR TextAttr; CHAR BackgroundAttr; int i,j; CHAR Char; SMALL_RECT ScrollRectangle,ClipRectangle; CHAR_INFO Fill; COORD DestinationOrigin; BackgroundAttr = BACKGROUND_BLUE; TextAttr = FOREGROUND_WHITE; for (i=0;i<20;i++) { for (Char='a',j=0;j<25;j++) { CharBuffer[i][j].Attributes = BackgroundAttr | TextAttr; CharBuffer[i][j].Char.AsciiChar = Char; Char++; if (Char > 'z') Char = 'a'; } } // // write square to screen // BufferSize.X = 25; BufferSize.Y = 20; BufferCoord.X = 0; BufferCoord.Y = 0; WriteRegion.Left = 5; WriteRegion.Right = 15; WriteRegion.Top = 5; WriteRegion.Bottom = 15; if (!WriteConsoleOutput(Handle, (PCHAR_INFO)CharBuffer, BufferSize, BufferCoord, &WriteRegion )) { DbgPrint("WriteConsoleOutput failed\n"); return FALSE; } if (WriteRegion.Left != 5 || WriteRegion.Right != 15 || WriteRegion.Top != 5 || WriteRegion.Bottom != 15) { DbgPrint("test 1: regions don't match\n"); DbgPrint("WriteRegion is %ld\n",&WriteRegion); } DbgPrint("wrote rectangle to 5,5\n"); DbgBreakPoint(); ScrollRectangle.Left = 5; ScrollRectangle.Right = 15; ScrollRectangle.Top = 5; ScrollRectangle.Bottom = 15; ClipRectangle.Left = 9; ClipRectangle.Right = 25; ClipRectangle.Top = 9; ClipRectangle.Bottom = 25; Fill.Attributes = BACKGROUND_GREEN; Fill.Char.UnicodeChar = 'T'; DestinationOrigin.X = 20; DestinationOrigin.Y = 20; if (!ScrollConsoleScreenBuffer(Handle, &ScrollRectangle, &ClipRectangle, DestinationOrigin, &Fill)) { DbgPrint("ScrollConsoleScreenBuffer failed\n"); return FALSE; } DbgPrint("scrolled region (5,15)(5,15) to (20,20) with clip (9,9)(25,25)\n"); DbgBreakPoint(); return TRUE; }
void InterpretEscSeq( void ) { int i; WORD attribut; CONSOLE_SCREEN_BUFFER_INFO Info; CONSOLE_CURSOR_INFO CursInfo; DWORD len, NumberOfCharsWritten; COORD Pos; SMALL_RECT Rect; CHAR_INFO CharInfo; if (prefix == '[') { if (prefix2 == '?' && (suffix == 'h' || suffix == 'l')) { if (es_argc == 1 && es_argv[0] == 25) { GetConsoleCursorInfo( hConOut, &CursInfo ); CursInfo.bVisible = (suffix == 'h'); SetConsoleCursorInfo( hConOut, &CursInfo ); return; } } // Ignore any other \e[? or \e[> sequences. if (prefix2 != 0) return; GetConsoleScreenBufferInfo( hConOut, &Info ); switch (suffix) { case 'm': if (es_argc == 0) es_argv[es_argc++] = 0; for (i = 0; i < es_argc; i++) { if (30 <= es_argv[i] && es_argv[i] <= 37) grm.foreground = es_argv[i] - 30; else if (40 <= es_argv[i] && es_argv[i] <= 47) grm.background = es_argv[i] - 40; else switch (es_argv[i]) { case 0: case 39: case 49: { TCHAR def[4]; int a; *def = '7'; def[1] = '\0'; GetEnvironmentVariable( (LPCTSTR)L"ANSICON_DEF", def, lenof(def) ); a = wcstol( (const wchar_t*)def, NULL, 16 ); grm.reverse = FALSE; if (a < 0) { grm.reverse = TRUE; a = -a; } if (es_argv[i] != 49) grm.foreground = attr2ansi[a & 7]; if (es_argv[i] != 39) grm.background = attr2ansi[(a >> 4) & 7]; if (es_argv[i] == 0) { if (es_argc == 1) { grm.bold = a & FOREGROUND_INTENSITY; grm.underline = a & BACKGROUND_INTENSITY; } else { grm.bold = 0; grm.underline = 0; } grm.rvideo = 0; grm.concealed = 0; } } break; case 1: grm.bold = FOREGROUND_INTENSITY; break; case 5: // blink case 4: grm.underline = BACKGROUND_INTENSITY; break; case 7: grm.rvideo = 1; break; case 8: grm.concealed = 1; break; case 21: // oops, this actually turns on double underline case 22: grm.bold = 0; break; case 25: case 24: grm.underline = 0; break; case 27: grm.rvideo = 0; break; case 28: grm.concealed = 0; break; } } if (grm.concealed) { if (grm.rvideo) { attribut = foregroundcolor[grm.foreground] | backgroundcolor[grm.foreground]; if (grm.bold) attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; } else { attribut = foregroundcolor[grm.background] | backgroundcolor[grm.background]; if (grm.underline) attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; } } else if (grm.rvideo) { attribut = foregroundcolor[grm.background] | backgroundcolor[grm.foreground]; if (grm.bold) attribut |= BACKGROUND_INTENSITY; if (grm.underline) attribut |= FOREGROUND_INTENSITY; } else attribut = foregroundcolor[grm.foreground] | grm.bold | backgroundcolor[grm.background] | grm.underline; if (grm.reverse) attribut = ((attribut >> 4) & 15) | ((attribut & 15) << 4); SetConsoleTextAttribute( hConOut, attribut ); return; case 'J': if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[J == ESC[0J if (es_argc != 1) return; switch (es_argv[0]) { case 0: // ESC[0J erase from cursor to end of display len = (Info.dwSize.Y - Info.dwCursorPosition.Y - 1) * Info.dwSize.X + Info.dwSize.X - Info.dwCursorPosition.X - 1; FillConsoleOutputCharacter( hConOut, ' ', len, Info.dwCursorPosition, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Info.dwCursorPosition, &NumberOfCharsWritten ); return; case 1: // ESC[1J erase from start to cursor. Pos.X = 0; Pos.Y = 0; len = Info.dwCursorPosition.Y * Info.dwSize.X + Info.dwCursorPosition.X + 1; FillConsoleOutputCharacter( hConOut, ' ', len, Pos, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos, &NumberOfCharsWritten ); return; case 2: // ESC[2J Clear screen and home cursor Pos.X = 0; Pos.Y = 0; len = Info.dwSize.X * Info.dwSize.Y; FillConsoleOutputCharacter( hConOut, ' ', len, Pos, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos, &NumberOfCharsWritten ); SetConsoleCursorPosition( hConOut, Pos ); return; default: return; } case 'K': if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[K == ESC[0K if (es_argc != 1) return; switch (es_argv[0]) { case 0: // ESC[0K Clear to end of line len = Info.srWindow.Right - Info.dwCursorPosition.X + 1; FillConsoleOutputCharacter( hConOut, ' ', len, Info.dwCursorPosition, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Info.dwCursorPosition, &NumberOfCharsWritten ); return; case 1: // ESC[1K Clear from start of line to cursor Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; FillConsoleOutputCharacter( hConOut, ' ', Info.dwCursorPosition.X + 1, Pos, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, Info.dwCursorPosition.X + 1, Pos, &NumberOfCharsWritten ); return; case 2: // ESC[2K Clear whole line. Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; FillConsoleOutputCharacter( hConOut, ' ', Info.dwSize.X, Pos, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, Info.dwSize.X, Pos, &NumberOfCharsWritten ); return; default: return; } case 'X': // ESC[#X Erase # characters. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[X == ESC[1X if (es_argc != 1) return; FillConsoleOutputCharacter( hConOut, ' ', es_argv[0], Info.dwCursorPosition, &NumberOfCharsWritten ); FillConsoleOutputAttribute( hConOut, Info.wAttributes, es_argv[0], Info.dwCursorPosition, &NumberOfCharsWritten ); return; case 'L': // ESC[#L Insert # blank lines. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L if (es_argc != 1) return; Rect.Left = 0; Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwSize.Y - 1; Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; CharInfo.Char.UnicodeChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); return; case 'M': // ESC[#M Delete # lines. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M if (es_argc != 1) return; if (es_argv[0] > Info.dwSize.Y - Info.dwCursorPosition.Y) es_argv[0] = Info.dwSize.Y - Info.dwCursorPosition.Y; Rect.Left = 0; Rect.Top = Info.dwCursorPosition.Y + es_argv[0]; Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwSize.Y - 1; Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; CharInfo.Char.UnicodeChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); return; case 'P': // ESC[#P Delete # characters. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[P == ESC[1P if (es_argc != 1) return; if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1) es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X; Rect.Left = Info.dwCursorPosition.X + es_argv[0]; Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwCursorPosition.Y; CharInfo.Char.UnicodeChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Info.dwCursorPosition, &CharInfo ); return; case '@': // ESC[#@ Insert # blank characters. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[@ == ESC[1@ if (es_argc != 1) return; if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1) es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X; Rect.Left = Info.dwCursorPosition.X; Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1 - es_argv[0]; Rect.Bottom = Info.dwCursorPosition.Y; Pos.X = Info.dwCursorPosition.X + es_argv[0]; Pos.Y = Info.dwCursorPosition.Y; CharInfo.Char.UnicodeChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); return; case 'k': // ESC[#k case 'A': // ESC[#A Moves cursor up # lines if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A if (es_argc != 1) return; Pos.Y = Info.dwCursorPosition.Y - es_argv[0]; if (Pos.Y < 0) Pos.Y = 0; Pos.X = Info.dwCursorPosition.X; SetConsoleCursorPosition( hConOut, Pos ); return; case 'e': // ESC[#e case 'B': // ESC[#B Moves cursor down # lines if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B if (es_argc != 1) return; Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; Pos.X = Info.dwCursorPosition.X; SetConsoleCursorPosition( hConOut, Pos ); return; case 'a': // ESC[#a case 'C': // ESC[#C Moves cursor forward # spaces if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[C == ESC[1C if (es_argc != 1) return; Pos.X = Info.dwCursorPosition.X + es_argv[0]; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition( hConOut, Pos ); return; case 'j': // ESC[#j case 'D': // ESC[#D Moves cursor back # spaces if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[D == ESC[1D if (es_argc != 1) return; Pos.X = Info.dwCursorPosition.X - es_argv[0]; if (Pos.X < 0) Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition( hConOut, Pos ); return; case 'E': // ESC[#E Moves cursor down # lines, column 1. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E if (es_argc != 1) return; Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; Pos.X = 0; SetConsoleCursorPosition( hConOut, Pos ); return; case 'F': // ESC[#F Moves cursor up # lines, column 1. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F if (es_argc != 1) return; Pos.Y = Info.dwCursorPosition.Y - es_argv[0]; if (Pos.Y < 0) Pos.Y = 0; Pos.X = 0; SetConsoleCursorPosition( hConOut, Pos ); return; case '`': // ESC[#` case 'G': // ESC[#G Moves cursor column # in current row. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[G == ESC[1G if (es_argc != 1) return; Pos.X = es_argv[0] - 1; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; if (Pos.X < 0) Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition( hConOut, Pos ); return; case 'd': // ESC[#d Moves cursor row #, current column. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[d == ESC[1d if (es_argc != 1) return; Pos.Y = es_argv[0] - 1; if (Pos.Y < 0) Pos.Y = 0; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; SetConsoleCursorPosition( hConOut, Pos ); return; case 'f': // ESC[#;#f case 'H': // ESC[#;#H Moves cursor to line #, column # if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[H == ESC[1;1H if (es_argc == 1) es_argv[es_argc++] = 1; // ESC[#H == ESC[#;1H if (es_argc > 2) return; Pos.X = es_argv[1] - 1; if (Pos.X < 0) Pos.X = 0; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; Pos.Y = es_argv[0] - 1; if (Pos.Y < 0) Pos.Y = 0; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; SetConsoleCursorPosition( hConOut, Pos ); return; case 's': // ESC[s Saves cursor position for recall later if (es_argc != 0) return; SavePos = Info.dwCursorPosition; return; case 'u': // ESC[u Return to saved cursor position if (es_argc != 0) return; SetConsoleCursorPosition( hConOut, SavePos ); return; case 'n': // ESC[#n Device status report if (es_argc != 1) return; // ESC[n == ESC[0n -> ignored switch (es_argv[0]) { case 5: // ESC[5n Report status SendSequence( (LPTSTR)L"\33[0n" ); // "OK" return; case 6: // ESC[6n Report cursor position { TCHAR buf[32]; wsprintf( buf, (LPTSTR)L"\33[%d;%dR", Info.dwCursorPosition.Y + 1, Info.dwCursorPosition.X + 1 ); SendSequence( buf ); } return; default: return; } case 't': // ESC[#t Window manipulation if (es_argc != 1) return; if (es_argv[0] == 21) // ESC[21t Report xterm window's title { TCHAR buf[MAX_PATH*2]; DWORD len = GetConsoleTitle( buf+3, lenof(buf)-3-2 ); // Too bad if it's too big or fails. buf[0] = ESC; buf[1] = ']'; buf[2] = 'l'; buf[3+len] = ESC; buf[3+len+1] = '\\'; buf[3+len+2] = '\0'; SendSequence( buf ); } return; default: return; } } else // (prefix == ']') { // Ignore any \e]? or \e]> sequences. if (prefix2 != 0)
void MessageEditor::delete_work() { //str_pos和cursor_pos不变 int tmp_post_end_pos; DWORD cCharsWritten; if (line_str_pos[current_line_num] == line[current_line_num].size()) //最后一行行尾后一格 return; character_count--; wch = line[current_line_num][line_str_pos[current_line_num]]; int deleted_ch_width; if (!isascii(wch)) deleted_ch_width = 2; else deleted_ch_width = 1; //在该行删去当前光标位置的字符,并将后面的字符向前移动 if (line_str_pos[current_line_num] == line[current_line_num].size() - 1) { //当前位置在行尾 tmp_post_end_pos = line_cursor_pos[current_line_num]; FillConsoleOutputCharacter(stdout_handle, (TCHAR)' ', deleted_ch_width, input_cursor_pos, &cCharsWritten); } else { SMALL_RECT scroll_rect; scroll_rect.Bottom = scroll_rect.Top = input_cursor_pos.Y; scroll_rect.Left = line_cursor_pos[current_line_num] + deleted_ch_width; wch = line[current_line_num].back(); if (!isascii(wch)) scroll_rect.Right = line_end_pos[current_line_num] + 1; else scroll_rect.Right = line_end_pos[current_line_num]; tmp_post_end_pos = scroll_rect.Right + 1 - deleted_ch_width; ScrollConsoleScreenBuffer(stdout_handle, &scroll_rect, NULL, input_cursor_pos, &blank_char); } line[current_line_num].erase(line_str_pos[current_line_num], 1); //将后面的行依次往前移动(每次操作某行时,从后一行提取若干字符,并将后一行左移) int operating_line_num = current_line_num; while (operating_line_num < line_str_pos.size()) { if (operating_line_num == line_str_pos.size() - 1) { //最后一行,只需设置line_end_pos if (line[operating_line_num].empty()) //最后一行被删成空行 line_end_pos[operating_line_num] = -1; else { wch = line[operating_line_num].back(); if (!isascii(wch)) line_end_pos[operating_line_num] = tmp_post_end_pos - 2; else line_end_pos[operating_line_num] = tmp_post_end_pos - 1; } } else { COORD end_pos = { tmp_post_end_pos, input_cursor_pos.Y + (operating_line_num - current_line_num) }; int deleted_chars_width = 0; int tmp_char_width; int tmp_line_count = line_str_pos.size(); while (tmp_post_end_pos <= RIGHT) { //从下一行借取若干字接在此行最后 if (line[operating_line_num + 1].empty()) { //下一行已经被取空,将下一行删去 line_str_pos.pop_back(); line_cursor_pos.pop_back(); line_end_pos.pop_back(); break; } else { //否则取出一个字,接在该行后 wch = line[operating_line_num + 1].front(); if (!isascii(wch)) tmp_char_width = 2; else tmp_char_width = 1; tmp_post_end_pos += tmp_char_width; if (tmp_post_end_pos > RIGHT + 1) { //太长,此步操作取消 tmp_post_end_pos -= tmp_char_width; break; } deleted_chars_width += tmp_char_width; line[operating_line_num + 1].erase(0, 1); line[operating_line_num].push_back(wch); FillConsoleOutputCharacter(stdout_handle, wch, tmp_char_width, end_pos, &cCharsWritten); end_pos.X += tmp_char_width; } } //设置line_end_pos wch = line[operating_line_num].back(); if (!isascii(wch)) line_end_pos[operating_line_num] = tmp_post_end_pos - 2; else line_end_pos[operating_line_num] = tmp_post_end_pos - 1; if (deleted_chars_width == 0) { //未从下一行取走字符 if ((operating_line_num == current_line_num) && //光标所在的行 (line_cursor_pos[current_line_num] > line_end_pos[current_line_num]) && //光标位置上已不存在字符 (current_line_num + 1 < line_str_pos.size())) { //下一行存在,光标应移动到下一行 line_str_pos[current_line_num] = 0; line_cursor_pos[current_line_num] = LEFT; current_line_num++; line_str_pos[current_line_num] = 0; line_cursor_pos[current_line_num] = LEFT; input_cursor_pos.X = LEFT; input_cursor_pos.Y++; } break; //无需对后面的行再进行操作 } else { //取出了下一行的字符,因此将下一行的内容左移 if (operating_line_num + 1 < tmp_line_count) { //如果下一行还存在 end_pos.Y++; end_pos.X = LEFT; if (line[operating_line_num + 1].empty()) //下一行为空 FillConsoleOutputCharacter(stdout_handle, (TCHAR)' ', deleted_chars_width, end_pos, &cCharsWritten); else { SMALL_RECT scroll_rect; scroll_rect.Bottom = scroll_rect.Top = end_pos.Y; scroll_rect.Left = LEFT + deleted_chars_width; wch = line[operating_line_num + 1].back(); if (!isascii(wch)) scroll_rect.Right = line_end_pos[operating_line_num + 1] + 1; else scroll_rect.Right = line_end_pos[operating_line_num + 1]; tmp_post_end_pos = scroll_rect.Right + 1 - deleted_chars_width; ScrollConsoleScreenBuffer(stdout_handle, &scroll_rect, NULL, end_pos, &blank_char); } } } } operating_line_num++; } //对齐虚拟光标位置 for (int i = current_line_num + 1; i < line_str_pos.size(); i++) { line_str_pos[i] = 0; line_cursor_pos[i] = 0; } make_align(); refresh_character_count(); SetConsoleCursorPosition(stdout_handle, input_cursor_pos); }
/* Insert n lines at vpos. if n is negative delete -n lines. */ static void w32con_ins_del_lines (int vpos, int n) { int i, nb; SMALL_RECT scroll; COORD dest; CHAR_INFO fill; struct frame * f = PICK_FRAME (); if (n < 0) { scroll.Top = vpos - n; scroll.Bottom = FRAME_LINES (f); dest.Y = vpos; } else { scroll.Top = vpos; scroll.Bottom = FRAME_LINES (f) - n; dest.Y = vpos + n; } scroll.Left = 0; scroll.Right = FRAME_COLS (f); dest.X = 0; fill.Char.AsciiChar = 0x20; fill.Attributes = char_attr_normal; ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill); /* Here we have to deal with a w32 console flake: If the scroll region looks like abc and we scroll c to a and fill with d we get cbd... if we scroll block c one line at a time to a, we get cdd... Emacs expects cdd consistently... So we have to deal with that here... (this also occurs scrolling the same way in the other direction. */ if (n > 0) { if (scroll.Bottom < dest.Y) { for (i = scroll.Bottom; i < dest.Y; i++) { w32con_move_cursor (i, 0); w32con_clear_end_of_line (FRAME_COLS (f)); } } } else { nb = dest.Y + (scroll.Bottom - scroll.Top) + 1; if (nb < scroll.Top) { for (i = nb; i < scroll.Top; i++) { w32con_move_cursor (i, 0); w32con_clear_end_of_line (FRAME_COLS (f)); } } } cursor_coords.X = 0; cursor_coords.Y = vpos; }
void MessageEditor::insert_work(wchar_t input) { //如果输入Ascii字符,新浪微博、人人将其处理为半个“字”,输入“aa”算作输入了一个字,此处为符合作业要求也将其视作一个“字” if (character_count >= 140) return; wch = input; character_count++; int tmp_post_end_pos; DWORD cCharsWritten; int insert_ch_width; if (!isascii(wch)) insert_ch_width = 2; else insert_ch_width = 1; bool move_right = true; if ((line_str_pos[current_line_num] == 0) && (current_line_num > 0)) { //试图在上一行末尾插入该字 wch = line[current_line_num - 1].back(); if (!isascii(wch)) tmp_post_end_pos = line_end_pos[current_line_num - 1] + 2 + insert_ch_width; else tmp_post_end_pos = line_end_pos[current_line_num - 1] + 1 + insert_ch_width; if (tmp_post_end_pos <= RIGHT + 1) { //能插入,则跳过后面步骤,在上一行末尾插入完后直接前往END COORD new_pos = { tmp_post_end_pos - insert_ch_width, input_cursor_pos.Y - 1 }; line[current_line_num - 1].push_back(input); line_end_pos[current_line_num - 1] = tmp_post_end_pos - insert_ch_width; FillConsoleOutputCharacter(stdout_handle, input, insert_ch_width, new_pos, &cCharsWritten); move_right = false; goto END; } } //先在该行插入该字 if (line[current_line_num].empty()) tmp_post_end_pos = LEFT + insert_ch_width; else { wch = line[current_line_num].back(); if (!isascii(wch)) tmp_post_end_pos = line_end_pos[current_line_num] + 2 + insert_ch_width; else tmp_post_end_pos = line_end_pos[current_line_num] + 1 + insert_ch_width; } line[current_line_num].insert(line_str_pos[current_line_num], 1, input); int overflow_chars_count, overflow_chars_width; line_overflow(current_line_num, tmp_post_end_pos, overflow_chars_count, overflow_chars_width); //重绘当前行 int operating_line_num; if (line_cursor_pos[current_line_num] >= tmp_post_end_pos) { //原来光标所在位置也被顶到下一行 FillConsoleOutputCharacter(stdout_handle, (TCHAR)' ', RIGHT + 1 - input_cursor_pos.X, input_cursor_pos, &cCharsWritten); line_cursor_pos[current_line_num] = LEFT; line_str_pos[current_line_num] = 0; current_line_num++; line_cursor_pos[current_line_num] = LEFT; line_str_pos[current_line_num] = 0; input_cursor_pos.X = LEFT; input_cursor_pos.Y++; operating_line_num = current_line_num; } else { COORD new_pos = { input_cursor_pos.X + insert_ch_width, input_cursor_pos.Y }; SMALL_RECT scroll_rect; scroll_rect.Bottom = scroll_rect.Top = input_cursor_pos.Y; scroll_rect.Left = line_cursor_pos[current_line_num]; scroll_rect.Right = tmp_post_end_pos - 1 - insert_ch_width; if (scroll_rect.Left <= scroll_rect.Right) //如果在行尾后一格插入,则无需移动 ScrollConsoleScreenBuffer(stdout_handle, &scroll_rect, NULL, new_pos, &blank_char); FillConsoleOutputCharacter(stdout_handle, input, insert_ch_width, input_cursor_pos, &cCharsWritten); operating_line_num = current_line_num + 1; } //将后面的行依次向后移动 while (operating_line_num < line_str_pos.size()) { if (overflow_chars_width == 0) break; wch = line[operating_line_num].back(); if (!isascii(wch)) tmp_post_end_pos = line_end_pos[operating_line_num] + 2 + overflow_chars_width; else tmp_post_end_pos = line_end_pos[operating_line_num] + 1 + overflow_chars_width; int tmp_overflow_chars_count, tmp_overflow_chars_width; line_overflow(operating_line_num, tmp_post_end_pos, tmp_overflow_chars_count, tmp_overflow_chars_width); //重绘当前行 COORD new_pos = { LEFT + overflow_chars_width, input_cursor_pos.Y + (operating_line_num - current_line_num) }; SMALL_RECT scroll_rect; scroll_rect.Bottom = scroll_rect.Top = new_pos.Y; scroll_rect.Left = LEFT; scroll_rect.Right = tmp_post_end_pos - 1 - overflow_chars_width; if (scroll_rect.Left <= scroll_rect.Right) //如果在行尾后一格插入,则无需移动 ScrollConsoleScreenBuffer(stdout_handle, &scroll_rect, NULL, new_pos, &blank_char); new_pos.X = tmp_post_end_pos; FillConsoleOutputCharacter(stdout_handle, (TCHAR)' ', RIGHT + 1 - new_pos.X, new_pos, &cCharsWritten); new_pos.X = LEFT; int processing_ch_width; for (int i = 0; i < overflow_chars_count; i++) { wch = line[operating_line_num][i]; if (!isascii(wch)) processing_ch_width = 2; else processing_ch_width = 1; FillConsoleOutputCharacter(stdout_handle, wch, processing_ch_width, new_pos, &cCharsWritten); new_pos.X += processing_ch_width; } overflow_chars_count = tmp_overflow_chars_count; overflow_chars_width = tmp_overflow_chars_width; operating_line_num++; } END: //对齐虚拟光标位置 for (int i = current_line_num + 1; i < line_str_pos.size(); i++) { line_str_pos[i] = 0; line_cursor_pos[i] = 0; } make_align(); if (move_right) right_work(); refresh_character_count(); SetConsoleCursorPosition(stdout_handle, input_cursor_pos); }
BOOL consoleScrollVert ( PSCREEN pScreen, ROW Top, COLUMN Left, ROW Bottom, COLUMN Right, INT Rows ) /*++ Routine Description: Scrolls Arguments: pScreen - Supplies pointer to screen data Top - Supplies top row Left - Supplies left column Bottom - Supplies bottom row Right - Supplies right column Rows - Number of rows to scroll Return Value: TRUE if scrolled FALSE otherwise --*/ { PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen; SMALL_RECT Rect; COORD Coord; CHAR_INFO CharInfo; BOOLEAN Ok; PLINE_INFO LineInfo; ROW R; if ( Rows ) { EnterCriticalSection( &(ScreenData->CriticalSection) ); // // If there is something to flush, we flush it now // if ( ScreenData->FirstRow <= ScreenData->LastRow ) { consoleShowScreen( pScreen ); } // // Scroll // Coord.X = (SHORT)Left; Coord.Y = (SHORT)Top; Rect.Left = (SHORT)Left; Rect.Top = (SHORT)Top; Rect.Right = (SHORT)Right; Rect.Bottom = (SHORT)Bottom; if ( Rows > 0 ) { Rect.Top += Rows; } else { Rect.Bottom += Rows; Coord.Y -= Rows; } CharInfo.Char.AsciiChar = ' '; CharInfo.Attributes = ScreenData->AttributeNew; Ok = ScrollConsoleScreenBuffer( ScreenData->ScreenHandle, &Rect, NULL, Coord, &CharInfo ); // // Mark all the lines in our buffer as containing garbage // LineInfo = ScreenData->LineInfo + Top; R = Bottom - Top + 1; while ( R-- ) { LineInfo->Garbage = TRUE; LineInfo++; } LeaveCriticalSection( &(ScreenData->CriticalSection) ); } return Ok; }
//------------------------------------------------------------------------------ static void simulate_sigwinch(COORD expected_cursor_pos) { // In the land of POSIX a terminal would raise a SIGWINCH signal when it is // resized. See rl_sigwinch_handler() in readline/signal.c. extern int _rl_vis_botlin; extern int _rl_last_v_pos; CONSOLE_SCREEN_BUFFER_INFO csbi; rl_voidfunc_t* redisplay_func_cache; int base_y; int bottom_line; HANDLE handle; bottom_line = _rl_vis_botlin - 1; handle = GetStdHandle(STD_OUTPUT_HANDLE); // Cache redisplay function. Need original as it handles redraw correctly. redisplay_func_cache = rl_redisplay_function; rl_redisplay_function = rl_redisplay; // Cursor may be out of sync with where Readline expects the cursor to be. // Put it back where it was, clamping if necessary. GetConsoleScreenBufferInfo(handle, &csbi); if (expected_cursor_pos.X >= csbi.dwSize.X) { expected_cursor_pos.X = csbi.dwSize.X - 1; } if (expected_cursor_pos.Y >= csbi.dwSize.Y) { expected_cursor_pos.Y = csbi.dwSize.Y - 1; } SetConsoleCursorPosition(handle, expected_cursor_pos); // Let Readline handle the buffer resize. RL_SETSTATE(RL_STATE_SIGHANDLER); rl_resize_terminal(); RL_UNSETSTATE(RL_STATE_SIGHANDLER); rl_redisplay_function = redisplay_func_cache; // Now some redraw edge cases need to be handled. GetConsoleScreenBufferInfo(handle, &csbi); base_y = csbi.dwCursorPosition.Y - _rl_last_v_pos; if (bottom_line > _rl_vis_botlin) { // Readline SIGWINCH handling assumes that at most one line needs to // be cleared which is not the case when resizing from small to large // widths. CHAR_INFO fill; SMALL_RECT rect; COORD coord; rect.Left = 0; rect.Right = csbi.dwSize.X; rect.Top = base_y + _rl_vis_botlin + 1; rect.Bottom = base_y + bottom_line; fill.Char.AsciiChar = ' '; fill.Attributes = csbi.wAttributes; coord.X = rect.Right + 1; coord.Y = rect.Top; ScrollConsoleScreenBuffer(handle, &rect, NULL, coord, &fill); } else { // Readline never writes to the last column as it wraps the cursor. The // last column will have noise when making the width smaller. Clear it. CHAR_INFO fill; SMALL_RECT rect; COORD coord; rect.Left = rect.Right = csbi.dwSize.X - 1; rect.Top = base_y; rect.Bottom = base_y + _rl_vis_botlin; fill.Char.AsciiChar = ' '; fill.Attributes = csbi.wAttributes; coord.X = rect.Right + 1; coord.Y = rect.Top; ScrollConsoleScreenBuffer(handle, &rect, NULL, coord, &fill); } }
/* move howmany lines starting at from to to */ static void ntconio_scroll(int from, int to, int n) { SMALL_RECT sRect; COORD dest; CHAR_INFO fill; int scroll_pause; scflush(); if (to == from) return; #if OPT_PRETTIER_SCROLL if (ABS(from - to) > 1) { ntconio_scroll(from, (from < to) ? to - 1 : to + 1, n); if (from < to) from = to - 1; else from = to + 1; } #endif #ifdef UNICODE fill.Char.UnicodeChar = ' '; #else fill.Char.AsciiChar = ' '; #endif fill.Attributes = currentAttribute; sRect.Left = 0; sRect.Top = (SHORT) from; sRect.Right = (SHORT) (csbi.dwMaximumWindowSize.X - 1); sRect.Bottom = (SHORT) (from + n - 1); dest.X = 0; dest.Y = (SHORT) to; ScrollConsoleScreenBuffer(hConsoleOutput, &sRect, NULL, dest, &fill); if ((scroll_pause = global_g_val(GVAL_SCROLLPAUSE)) > 0) { /* * If the user has cheap video HW (1 MB or less) and * there's a busy background app (say, dev studio), then * the console version of vile can exhibit serious repaint * problems when the display is rapidly scrolled. By * inserting a user-defined sleep after the scroll, the * video HW has a chance to properly paint before the * next scroll operation. */ Sleep(scroll_pause); } #if !OPT_PRETTIER_SCROLL if (ABS(from - to) > n) { DWORD cnt; COORD coordCursor; coordCursor.X = 0; if (to > from) { coordCursor.Y = (SHORT) (from + n); cnt = to - from - n; } else { coordCursor.Y = (SHORT) (to + n); cnt = from - to - n; } cnt *= csbi.dwMaximumWindowSize.X; erase_at(coordCursor, cnt); } #endif }
int Execute(HANDLE hPlugin,const char *CmdStr,bool HideOutput, bool Silent,bool ShowTitle, int MWaitForExternalProgram, bool SeparateWindow) { STARTUPINFO si; PROCESS_INFORMATION pi; int ExitCode, CreateProcessCode; memset(&si,0,sizeof(si)); si.cb=sizeof(si); HANDLE hChildStdoutRd,hChildStdoutWr; HANDLE StdInput=GetStdHandle(STD_INPUT_HANDLE); HANDLE StdOutput=GetStdHandle(STD_OUTPUT_HANDLE); HANDLE StdError=GetStdHandle(STD_ERROR_HANDLE); HANDLE hScreen=NULL; CONSOLE_SCREEN_BUFFER_INFO csbi; if (HideOutput) { SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 32768)) { SetStdHandle(STD_OUTPUT_HANDLE,hChildStdoutWr); SetStdHandle(STD_ERROR_HANDLE,hChildStdoutWr); if (Silent) { hScreen=Far::SaveScreen (0,0,-1,0); Far::Text (2,0,7,MWaitForExternalProgram); } else { hScreen=Far::SaveScreen(); FarMessage msg; msg.AddLine (""); msg.AddLine (MWaitForExternalProgram); msg.Show(); } } else HideOutput=false; } else { GetConsoleScreenBufferInfo(StdOutput,&csbi); char Blank[1024]; FillMemory (Blank, csbi.dwSize.X, ' '); Blank [csbi.dwSize.X] = '\0'; for (int Y=0;Y<csbi.dwSize.Y;Y++) Far::Text (0, Y, 7, Blank); Far::FlushText(); COORD C; C.X=0; C.Y=csbi.dwCursorPosition.Y; SetConsoleCursorPosition(StdOutput,C); } DWORD ConsoleMode; GetConsoleMode(StdInput,&ConsoleMode); SetConsoleMode(StdInput,ENABLE_PROCESSED_INPUT|ENABLE_LINE_INPUT| ENABLE_ECHO_INPUT|ENABLE_MOUSE_INPUT); char ExpandedCmd[260]; ExpandEnvironmentStrings(CmdStr,ExpandedCmd,sizeof(ExpandedCmd)); char SaveTitle[512]; GetConsoleTitle(SaveTitle,sizeof(SaveTitle)); if (ShowTitle) SetConsoleTitle(ExpandedCmd); CreateProcessCode=CreateProcess(NULL,ExpandedCmd,NULL,NULL,HideOutput,0,NULL,NULL,&si,&pi); if (HideOutput) { SetStdHandle(STD_OUTPUT_HANDLE,StdOutput); SetStdHandle(STD_ERROR_HANDLE,StdError); CloseHandle(hChildStdoutWr); } if (CreateProcessCode) { if (SeparateWindow) ExitCode = 0; else { if (HideOutput) { WaitForSingleObject(pi.hProcess,1000); char PipeBuf[32768]; DWORD Read; while (ReadFile(hChildStdoutRd,PipeBuf,sizeof(PipeBuf),&Read,NULL)) ; CloseHandle(hChildStdoutRd); } WaitForSingleObject(pi.hProcess,INFINITE); GetExitCodeProcess(pi.hProcess,(LPDWORD)&ExitCode); } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } else if (HideOutput) CloseHandle (hChildStdoutRd); SetConsoleTitle(SaveTitle); SetConsoleMode(StdInput,ConsoleMode); if (!HideOutput) { SMALL_RECT src; COORD dest; CHAR_INFO fill; src.Left=0; src.Top=2; src.Right=csbi.dwSize.X; src.Bottom=csbi.dwSize.Y; dest.X=dest.Y=0; fill.Char.AsciiChar=' '; fill.Attributes=7; ScrollConsoleScreenBuffer(StdOutput,&src,NULL,dest,&fill); FarCtrl (hPlugin).SetUserScreen(); } if (hScreen) { Far::RestoreScreen (NULL); Far::RestoreScreen (hScreen); } if (!CreateProcessCode) return -1; else return ExitCode; }
HANDLE WINAPI OpenW(const struct OpenInfo *Info) { const int CUR_DIR_SIZE = 100000; char* filename = 0; switch( Info->OpenFrom ) { case OPEN_COMMANDLINE: { OpenCommandLineInfo* cinfo = (OpenCommandLineInfo*)Info->Data; const wchar_t* cmdline = cinfo->CommandLine; if( !cmdline ) return INVALID_HANDLE_VALUE; while( *cmdline && *cmdline <= ' ' ) cmdline++; if( *cmdline ) filename = w2a( cmdline ); else return 0; break; } case OPEN_PLUGINSMENU: { FarGetPluginPanelItem pinfo; PluginPanelItem* pitem = (PluginPanelItem*)malloc(CUR_DIR_SIZE); ZeroMemory(&pinfo, sizeof(pinfo)); ZeroMemory(pitem, CUR_DIR_SIZE); pinfo.StructSize = sizeof(pinfo); pinfo.Size = CUR_DIR_SIZE; pinfo.Item = pitem; if(InfoW.PanelControl( PANEL_ACTIVE, FCTL_GETCURRENTPANELITEM, 0, &pinfo )) { filename = w2a( pinfo.Item->FileName ); free(pitem); } else { free(pitem); return 0; } break; } default: return 0; } if( !filename ) return 0; wchar_t comspec[MAX_PATH * 2]; if( !GetEnvironmentVariableW( L"COMSPEC", comspec, sizeofa( comspec ) ) ) lstrcpyW( comspec, L"cmd.exe" ); char pipename[100]; wsprintf( pipename, "\\\\.\\pipe\\FarCall%ul", GetCurrentProcessId() ); char* batchstr = (char*)malloc( 10000 ); wsprintf( batchstr, batch, filename, ModuleName, pipename ); // obtaining temp file name wchar_t tmp[MAX_PATH * 10]; GetTempPathW( sizeofa( tmp ), tmp ); GetTempFileNameW( tmp, L"", 0, tmp ); DeleteFileW( tmp ); lstrcatW( tmp, L".bat" ); HANDLE file = CreateFileW( tmp, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0 ); if( !file || file == INVALID_HANDLE_VALUE ) { DeleteFileW( tmp ); free( filename ); free( batchstr ); return INVALID_HANDLE_VALUE; } DWORD written; WriteFile( file, batchstr, lstrlen( batchstr ), &written, 0 ); CloseHandle( file ); wchar_t cmd[MAX_PATH * 10] = L"\""; lstrcatW( lstrcatW( lstrcatW( lstrcatW( cmd, comspec ), L"\" /c \"" ), tmp ), L"\""); STARTUPINFOW sinfo; ZeroMemory( &sinfo, sizeof( sinfo ) ); sinfo.cb = sizeof( sinfo ); PROCESS_INFORMATION pinfo; Handle np( CreateNamedPipe( pipename, PIPE_ACCESS_DUPLEX, PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 100, 100, 0, 0 ) ); connected = false; DWORD id; Handle thread( CreateThread( 0, 0, ListenEnv, np, 0, &id ) ); while( !connected ) Sleep( 100 ); CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &csbi ); #ifndef LIGHTGRAY #define LIGHTGRAY 7 #endif wchar_t Blank[1024]; FSFW.sprintf(Blank,L"%*s",csbi.dwSize.X,L""); FarColor fc = {FCF_NONE, LIGHTGRAY, 0, 0}; for (int Y=0;Y<csbi.dwSize.Y;Y++) InfoW.Text(0,Y,&fc,Blank); InfoW.Text(0,0,0,NULL); COORD C; C.X=0; C.Y=csbi.dwCursorPosition.Y; SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), C ); wchar_t* curr_dir = (wchar_t*)malloc(CUR_DIR_SIZE); FSFW.GetCurrentDirectory(CUR_DIR_SIZE, curr_dir); if( np && CreateProcessW( NULL, cmd, 0, 0, TRUE, 0, 0, curr_dir[0] ? curr_dir : 0, &sinfo, &pinfo ) ) { HANDLE ar[] = {pinfo.hProcess, np}; WaitForMultipleObjects( 2, ar, TRUE, INFINITE ); CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); SMALL_RECT src; COORD dest; CHAR_INFO fill; src.Left=0; src.Top=2; src.Right=csbi.dwSize.X; src.Bottom=csbi.dwSize.Y; dest.X=dest.Y=0; fill.Char.AsciiChar=' '; fill.Attributes=7; ScrollConsoleScreenBuffer( GetStdHandle( STD_OUTPUT_HANDLE ), &src, NULL, dest, &fill); InfoW.AdvControl(0, ACTL_REDRAWALL, 0, 0); } else Handle onp( CreateFile( pipename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 ) ); free( filename ); free( batchstr ); free( curr_dir ); DeleteFileW( tmp ); return 0; }
static void InterpretEscSeq(void) { int i; WORD attribut; CONSOLE_SCREEN_BUFFER_INFO Info; DWORD NumberOfCharsWritten; COORD Pos; SMALL_RECT Rect; CHAR_INFO CharInfo; if (prefix != '[') return; GetConsoleScreenBufferInfo(hConOut, &Info); switch (suffix) { case 'm': if (es_argc == 0) es_argv[es_argc++] = 0; for (i = 0; i < es_argc; i++) { switch (es_argv[i]) { case 0: foreground = FOREGROUND_WHITE; background = BACKGROUND_BLACK; bold = 0; underline = 0; rvideo = 0; concealed = 0; break; case 1: bold = 1; break; case 21: bold = 0; break; case 4: underline = 1; break; case 24: underline = 0; break; case 7: rvideo = 1; break; case 27: rvideo = 0; break; case 8: concealed = 1; break; case 28: concealed = 0; break; } if ((30 <= es_argv[i]) && (es_argv[i] <= 37)) foreground = (WORD)(es_argv[i] - 30); if ((40 <= es_argv[i]) && (es_argv[i] <= 47)) background = (WORD)(es_argv[i] - 40); } if (rvideo) attribut = foregroundcolor[background] | backgroundcolor[foreground]; else attribut = foregroundcolor[foreground] | backgroundcolor[background]; if (bold) attribut |= FOREGROUND_INTENSITY; if (underline) attribut |= BACKGROUND_INTENSITY; SetConsoleTextAttribute(hConOut, attribut); return; case 'J': if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[J == ESC[0J if (es_argc != 1) return; switch (es_argv[0]) { case 0: // ESC[0J erase from cursor to end of display FillConsoleOutputCharacter(hConOut, ' ', (Info.dwSize.Y - Info.dwCursorPosition.Y - 1) * Info.dwSize.X + Info.dwSize.X - Info.dwCursorPosition.X - 1, Info.dwCursorPosition, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, (Info.dwSize.Y - Info.dwCursorPosition.Y - 1) * Info.dwSize.X + Info.dwSize.X - Info.dwCursorPosition.X - 1, Info.dwCursorPosition, &NumberOfCharsWritten); return; case 1: // ESC[1J erase from start to cursor. Pos.X = 0; Pos.Y = 0; FillConsoleOutputCharacter(hConOut, ' ', Info.dwCursorPosition.Y * Info.dwSize.X + Info.dwCursorPosition.X + 1, Pos, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, Info.dwCursorPosition.Y * Info.dwSize.X + Info.dwCursorPosition.X + 1, Pos, &NumberOfCharsWritten); return; case 2: // ESC[2J Clear screen and home cursor Pos.X = 0; Pos.Y = 0; FillConsoleOutputCharacter(hConOut, ' ', Info.dwSize.X * Info.dwSize.Y, Pos, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, Info.dwSize.X * Info.dwSize.Y, Pos, &NumberOfCharsWritten); SetConsoleCursorPosition(hConOut, Pos); return; default: return; } case 'K': if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[K == ESC[0K if (es_argc != 1) return; switch (es_argv[0]) { case 0: // ESC[0K Clear to end of line FillConsoleOutputCharacter(hConOut, ' ', Info.srWindow.Right - Info.dwCursorPosition.X + 1, Info.dwCursorPosition, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, Info.srWindow.Right - Info.dwCursorPosition.X + 1, Info.dwCursorPosition, &NumberOfCharsWritten); return; case 1: // ESC[1K Clear from start of line to cursor Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; FillConsoleOutputCharacter(hConOut, ' ', Info.dwCursorPosition.X + 1, Pos, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, Info.dwCursorPosition.X + 1, Pos, &NumberOfCharsWritten); return; case 2: // ESC[2K Clear whole line. Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; FillConsoleOutputCharacter(hConOut, ' ', Info.dwSize.X, Pos, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, Info.dwSize.X, Pos, &NumberOfCharsWritten); return; default: return; } case 'L': // ESC[#L Insert # blank lines. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L if (es_argc != 1) return; Rect.Left = 0; Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwSize.Y - 1; Pos.X = 0; Pos.Y = (SHORT)(Info.dwCursorPosition.Y + es_argv[0]); CharInfo.Char.AsciiChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer(hConOut, &Rect, NULL, Pos, &CharInfo); Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; FillConsoleOutputCharacter(hConOut, ' ', Info.dwSize.X * es_argv[0], Pos, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, Info.dwSize.X * es_argv[0], Pos, &NumberOfCharsWritten); return; case 'M': // ESC[#M Delete # line. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M if (es_argc != 1) return; if (es_argv[0] > Info.dwSize.Y - Info.dwCursorPosition.Y) es_argv[0] = Info.dwSize.Y - Info.dwCursorPosition.Y; Rect.Left = 0; Rect.Top = (SHORT)(Info.dwCursorPosition.Y + es_argv[0]); Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwSize.Y - 1; Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; CharInfo.Char.AsciiChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer(hConOut, &Rect, NULL, Pos, &CharInfo); Pos.Y = (SHORT)(Info.dwSize.Y - es_argv[0]); FillConsoleOutputCharacter(hConOut, ' ', Info.dwSize.X * es_argv[0], Pos, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, Info.dwSize.X * es_argv[0], Pos, &NumberOfCharsWritten); return; case 'P': // ESC[#P Delete # characters. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[P == ESC[1P if (es_argc != 1) return; if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1) es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X; Rect.Left = (SHORT)(Info.dwCursorPosition.X + es_argv[0]); Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1; Rect.Bottom = Info.dwCursorPosition.Y; CharInfo.Char.AsciiChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer(hConOut, &Rect, NULL, Info.dwCursorPosition, &CharInfo); Pos.X = (SHORT)(Info.dwSize.X - es_argv[0]); Pos.Y = Info.dwCursorPosition.Y; FillConsoleOutputCharacter(hConOut, ' ', es_argv[0], Pos, &NumberOfCharsWritten); return; case '@': // ESC[#@ Insert # blank characters. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[@ == ESC[1@ if (es_argc != 1) return; if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1) es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X; Rect.Left = Info.dwCursorPosition.X; Rect.Top = Info.dwCursorPosition.Y; Rect.Right = Info.dwSize.X - 1 - es_argv[0]; Rect.Bottom = Info.dwCursorPosition.Y; Pos.X = Info.dwCursorPosition.X + es_argv[0]; Pos.Y = Info.dwCursorPosition.Y; CharInfo.Char.AsciiChar = ' '; CharInfo.Attributes = Info.wAttributes; ScrollConsoleScreenBuffer(hConOut, &Rect, NULL, Pos, &CharInfo); FillConsoleOutputCharacter(hConOut, ' ', es_argv[0], Info.dwCursorPosition, &NumberOfCharsWritten); FillConsoleOutputAttribute(hConOut, Info.wAttributes, es_argv[0], Info.dwCursorPosition, &NumberOfCharsWritten); return; case 'A': // ESC[#A Moves cursor up # lines if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A if (es_argc != 1) return; Pos.X = Info.dwCursorPosition.X; Pos.Y = Info.dwCursorPosition.Y - es_argv[0]; if (Pos.Y < 0) Pos.Y = 0; SetConsoleCursorPosition(hConOut, Pos); return; case 'B': // ESC[#B Moves cursor down # lines if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B if (es_argc != 1) return; Pos.X = Info.dwCursorPosition.X; Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; SetConsoleCursorPosition(hConOut, Pos); return; case 'C': // ESC[#C Moves cursor forward # spaces if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[C == ESC[1C if (es_argc != 1) return; Pos.X = Info.dwCursorPosition.X + es_argv[0]; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition(hConOut, Pos); return; case 'D': // ESC[#D Moves cursor back # spaces if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[D == ESC[1D if (es_argc != 1) return; Pos.X = Info.dwCursorPosition.X - es_argv[0]; if (Pos.X < 0) Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition(hConOut, Pos); return; case 'E': // ESC[#E Moves cursor down # lines, column 1. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E if (es_argc != 1) return; Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; SetConsoleCursorPosition(hConOut, Pos); return; case 'F': // ESC[#F Moves cursor up # lines, column 1. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F if (es_argc != 1) return; Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y - es_argv[0]; if (Pos.Y < 0) Pos.Y = 0; SetConsoleCursorPosition(hConOut, Pos); return; case 'G': // ESC[#G Moves cursor column # in current row. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[G == ESC[1G if (es_argc != 1) return; Pos.X = es_argv[0] - 1; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; if (Pos.X < 0) Pos.X = 0; Pos.Y = Info.dwCursorPosition.Y; SetConsoleCursorPosition(hConOut, Pos); return; case 'f': case 'H': // ESC[#;#H or ESC[#;#f Moves cursor to line #, column # if (es_argc == 0) { es_argv[es_argc++] = 1; // ESC[G == ESC[1;1G es_argv[es_argc++] = 1; } if (es_argc == 1) { es_argv[es_argc++] = 1; // ESC[nG == ESC[n;1G } if (es_argc > 2) return; Pos.X = es_argv[1] - 1; if (Pos.X < 0) Pos.X = 0; if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; Pos.Y = es_argv[0] - 1; if (Pos.Y < 0) Pos.Y = 0; if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; SetConsoleCursorPosition(hConOut, Pos); return; case 's': // ESC[s Saves cursor position for recall later if (es_argc != 0) return; SavePos.X = Info.dwCursorPosition.X; SavePos.Y = Info.dwCursorPosition.Y; return; case 'u': // ESC[u Return to saved cursor position if (es_argc != 0) return; SetConsoleCursorPosition(hConOut, SavePos); return; } }