다음을 통해 공유


콘솔 가상 터미널 시퀀스

가상 터미널 시퀀스는 출력 스트림에 쓸 때 커서 이동, 콘솔 색 및 기타 작업을 제어할 수 있는 제어 문자 시퀀스입니다. 출력 스트림 쿼리 정보 시퀀스에 대한 응답으로 입력 스트림에서 시퀀스를 수신하거나 적절한 모드가 설정된 경우 사용자 입력의 인코딩으로 시퀀스를 수신할 수도 있습니다.

GetConsoleModeSetConsoleMode 함수를 사용하여 이 동작을 구성할 수 있습니다. 가상 터미널 동작을 사용하도록 설정하는 권장 방법의 샘플은 이 문서의 끝부분에 포함되어 있습니다.

다음 시퀀스의 동작은 VT100 및 파생된 터미널 에뮬레이터 기술, 특히 xterm 터미널 에뮬레이터를 기반으로 합니다. 터미널 시퀀스에 대한 자세한 내용은 http://vt100.nethttp://invisible-island.net/xterm/ctlseqs/ctlseqs.html에서 찾을 수 있습니다.

출력 시퀀스

SetConsoleMode 함수를 사용하여 화면 버퍼 핸들에 ENABLE_VIRTUAL_TERMINAL_PROCESSING 플래그가 설정된 경우 출력 스트림에 기록될 때 콘솔 호스트에서 다음 터미널 시퀀스를 가로채게 됩니다. DISABLE_NEWLINE_AUTO_RETURN 플래그는 행의 마지막 열에 기록된 문자와 관련하여 다른 터미널 에뮬레이터의 커서 위치 지정 및 스크롤 동작을 에뮬레이트하는 데 유용할 수도 있습니다.

간단한 커서 위치 지정

다음 설명에서 ESC는 항상 16진수 값 0x1B입니다. 터미널 시퀀스에는 공백을 포함할 수 없습니다. 개별 터미널 시퀀스는 WriteFile 또는 WriteConsole에 대한 여러 순차 호출에서 문자 또는 바이트 위치에서 분할될 수 있지만 전체 시퀀스를 한 번의 호출에 포함하는 것이 가장 좋습니다. 이러한 시퀀스의 실제 사용 사례는 이 토픽의 끝부분에 있는 예제를 참조하세요.

다음 표에서는 ESC 문자 바로 다음에 단일 작업 명령이 오는 간단한 이스케이프 시퀀스에 대해 설명합니다. 이러한 시퀀스는 매개 변수를 사용하지 않고 즉시 적용됩니다.

이 표의 모든 명령은 일반적으로 SetConsoleCursorPosition 콘솔 API를 호출하여 커서를 배치합니다.

커서 이동은 버퍼의 현재 뷰포트로 제한됩니다. 스크롤(사용 가능한 경우)은 발생하지 않습니다.

Sequence 약식 동작
ESC M RI 역방향 인덱스 – \n의 역방향 작업을 수행하고 커서를 한 줄 위로 이동하고 기본 가로 위치를 지정하고 필요한 경우 버퍼를 스크롤합니다.*
ESC 7 DECSC 메모리에 커서 위치 저장**
ESC 8 DECSR 메모리에서 커서 위치 복원**

참고 항목

* 스크롤 여백이 설정된 경우 여백 내부의 RI는 여백의 내용만 스크롤하고 뷰포트를 변경하지 않은 상태로 둡니다. (스크롤 여백 참조)

**저장 명령을 처음 사용할 때까지 메모리에 저장된 값은 없습니다. 저장된 값에 액세스하는 유일한 방법은 복원 명령입니다.

커서 위치 지정

다음 표에는 CSI(Control Sequence Introducer) 형식 시퀀스가 나열되어 있습니다. 모든 CSI 시퀀스는 ESC(0x1B)와 [(왼쪽 대괄호, 0x5B)로 시작하고 각 작업에 대한 자세한 정보를 지정하는 가변 길이의 매개 변수를 포함할 수 있습니다. 이를 약식으로 표현하면 <n>이 됩니다. 아래의 각 표는 기능에 따라 그룹화되었으며 각 표의 아래에 제공된 메모는 그룹의 작동 방식을 설명합니다.

별도의 언급이 없으면 모든 매개 변수에 다음 규칙이 적용됩니다.

  • <n>은 이동할 거리를 나타내며 선택적 매개 변수입니다.
  • <n>이 생략되거나 0이면 1로 처리됩니다.
  • <n>은 32,767(최대 short 값)보다 클 수 없습니다.
  • <n>은 음수일 수 없습니다.

이 섹션의 모든 명령은 일반적으로 SetConsoleCursorPosition 콘솔 API를 호출합니다.

커서 이동은 버퍼의 현재 뷰포트로 제한됩니다. 스크롤(사용 가능한 경우)은 발생하지 않습니다.

Sequence 코드 설명 동작
ESC [ <n> A CUU 커서 위로 커서를 위로 <n>만큼 이동
ESC [ <n> B CUD 커서 아래로 커서를 아래로 <n>만큼 이동
ESC [ <n> C CUF 커서 앞으로 커서를 앞(오른쪽)으로 <n>만큼 이동
ESC [ <n> D CUB 커서 뒤로 커서를 뒤(왼쪽)으로 <n>만큼 이동
ESC [ <n> E CNL 커서 다음 줄 커서를 현재 위치에서 아래로 <n>줄 이동
ESC [ <n> F CPL 커서 이전 줄 커서를 현재 위치에서 위로 <n>줄 이동
ESC [ <n> G 커서 가로 절대값 커서가 현재 줄에서 가로 방향 <n>번째 위치로 이동
ESC [ <n> d VPA 세로 줄 위치 절대값 커서가 현재 열에서 세로 방향 <n>번째 위치로 이동
ESC [ <y> ; <x> H CUP 커서 위치 *커서가 x>로 <이동; <뷰포트 내의 y> 좌표입니다. 여기서 <x>는 y선의 <열입니다.>
ESC [ <y> ; <x> f HVP 가로 세로 위치 *커서가 x>로 <이동; <뷰포트 내의 y> 좌표입니다. 여기서 <x>는 y선의 <열입니다.>
ESC [ s ANSISYSSC 커서 저장 – Ansi.sys 에뮬레이션 **매개 변수가 없으므로 DECSC와 같은 저장 커서 작업을 수행합니다.
ESC [ u ANSISYSRC 커서 복원 – Ansi.sys 에뮬레이션 **매개 변수가 없으므로 DECRC와 같은 복원 커서 작업을 수행합니다.

참고 항목

*<x> 및 <y> 매개 변수는 위의 n>과 동일한 제한 사항이 있습니다<. <x> 및 <y>를 생략하면 1;1로 설정됩니다.

**ANSI.sys 기록 설명서는 편의/호환성을 위해 찾을 https://msdn.microsoft.com/library/cc722862.aspx 수 있으며 구현됩니다.

커서 표시 유형

다음 명령은 커서의 표시 유형 및 깜박임 상태를 제어합니다. DECTCEM 시퀀스는 일반적으로 SetConsoleCursorInfo 콘솔 API를 호출하여 커서 표시 유형을 전환합니다.

Sequence 코드 설명 동작
ESC [ ? 12 h ATT160 텍스트 커서 깜박임 사용 커서 깜박임 시작
ESC [ ? 12 l ATT160 텍스트 커서 깜박임 사용 안함 커서 깜박임 중지
ESC [ ? 25 h DECTCEM 텍스트 커서 모드 표시 사용 커서 표시
ESC [ ? 25 l DECTCEM 텍스트 커서 모드 숨김 사용 커서 숨김

사용 시퀀스는 소문자 H(h)로 끝나고 사용 안 함 시퀀스는 소문자 L(l)로 끝납니다.

커서 셰이프

다음 명령은 커서 셰이프를 제어하고 사용자 지정할 수 있도록 합니다.

Sequence 코드 설명 동작
ESC [ 0 SP q DECSCUSR 사용자 셰이프 사용자가 구성한 기본 커서 셰이프
ESC [ 1 SP q DECSCUSR 깜박이는 블록 블록 커서 모양 깜박임
ESC [ 2 SP q DECSCUSR 안정 블록 고정 블록 커서 모양
ESC [ 3 SP q DECSCUSR 깜박이는 밑줄 깜박이는 밑줄 커서 모양
ESC [ 4 SP q DECSCUSR 꾸준한 밑줄 꾸준한 밑줄 커서 모양
ESC [ 5 SP q DECSCUSR 깜박이는 막대 깜박이는 막대 커서 모양
ESC [ 6 SP q DECSCUSR 안정 막대 고정 막대 커서 모양

참고 항목

SP 은 중간 위치의 리터럴 공백 문자(0x20)이고, 그 뒤에 q 최종 위치에서 (0x71)가 옵니다.

뷰포트 위치 지정

이 섹션의 모든 명령은 일반적으로 ScrollConsoleScreenBuffer 콘솔 API를 호출하여 콘솔 버퍼의 내용을 이동합니다.

주의 명령 이름 때문에 오해하면 안 됩니다. 스크롤은 뷰포트가 이동하는 방향이 아니라 작업 중에 텍스트가 이동하는 방향을 말합니다.

Sequence 코드 설명 동작
ESC [ <n> S SU 위로 스크롤 텍스트를 위로 <n>만큼 스크롤합니다. 아래로 이동이라고도 하며, 화면 아래쪽에 새 줄이 채워집니다.
ESC [ <n> T SD 아래로 스크롤 아래로 <n>만큼 스크롤합니다. 위로 이동이라고도 하며, 화면 위쪽에 새 줄이 채워집니다.

커서가 있는 줄부터 텍스트가 이동합니다. 커서가 뷰포트의 중간 행에 있는 경우 위로 스크롤하면 뷰포트의 아래쪽 절반이 이동하고 맨 아래에 빈 줄이 삽입됩니다. 아래로 스크롤하면 뷰포트 행의 위쪽 절반이 이동하고 맨 위에 새 줄이 삽입됩니다.

또한 위로 스크롤 및 아래로 스크롤은 스크롤 여백의 영향을 받습니다. 위로 스크롤 및 아래로 스크롤은 스크롤 여백 밖에 있는 줄에는 영향을 주지 않습니다.

<n>의 기본값은 1이며 원한다면 이 값을 생략할 수 있습니다.

텍스트 수정

이 섹션의 모든 명령은 일반적으로 FillConsoleOutputCharacter, FillConsoleOutputAttributeScrollConsoleScreenBuffer 콘솔 API를 호출하여 텍스트 버퍼 내용을 수정합니다.

Sequence 코드 설명 동작
ESC [ <n> @ ICH 문자 삽입 현재 커서 위치에 공백을 <n>개 삽입하고, 모든 기존 텍스트를 오른쪽으로 이동합니다. 화면 오른쪽으로 빠져나가는 텍스트는 제거됩니다.
ESC [ <n> P DCH 문제 삭제 현재 커서 위치에서 <n>개 문자를 삭제하고, 화면 오른쪽 가장자리의 공백 문자를 안쪽으로 이동합니다.
ESC [ <n> X ECH 문자 지우기 문자를 공백 문자로 덮어쓰는 방식으로 현재 커서 위치에서 <n>개 문자를 지웁니다.
ESC [ <n> L IL 선 삽입 커서 위치의 버퍼에 <n>개 줄을 삽입합니다. 커서가 있는 줄과 그 아래 줄은 아래로 이동됩니다.
ESC [ <n> M DL 줄 삭제 커서가 있는 행부터 시작하여 버퍼에서 <n>개 줄을 삭제합니다.

참고 항목

IL 및 DL의 경우 스크롤 여백의 줄만 영향을 받습니다(스크롤 여백 참조). 여백을 설정하지 않으면 기본 여백 테두리는 현재 뷰포트입니다. 여백 아래로 이동되는 줄은 삭제됩니다. 줄이 삭제되면 여백 아래쪽에 빈 줄이 삽입됩니다. 뷰포트 밖에 있는 줄은 영향을 받지 않습니다.

각 시퀀스에서 <n>을 생략할 경우 기본값은 0입니다.

다음 명령에서 매개 변수 <n>의 유효한 값은 3입니다.

  • 0은 현재 커서 위치(포함)에서 줄/디스플레이 끝까지 지웁니다.
  • 1은 줄/디스플레이의 시작부터 현재 커서 위치(포함)까지 지웁니다.
  • 2는 전체 줄/디스플레이를 지웁니다.
Sequence 코드 설명 동작
ESC [ <n> J ED 디스플레이에서 지우기 <n>에서 지정한 현재 뷰포트/화면의 모든 텍스트를 공백 문자로 바꿉니다.
ESC [ <nK> EL 줄에서 지우기 <n>에서 지정한 커서가 있는 줄의 모든 텍스트를 공백 문자로 바꿉니다.

텍스트 서식 지정

이 섹션의 모든 명령은 일반적으로 SetConsoleTextAttribute 콘솔 API를 호출하여 향후 콘솔 출력 텍스트 버퍼에 대한 모든 쓰기의 서식을 조정합니다.

이 명령은 아래의 <n> 위치에 세미콜론으로 구분된 0~16개의 매개 변수를 사용할 수 있다는 점에서 특별합니다.

매개 변수를 지정하지 않으면 단일 0 매개 변수와 동일하게 처리됩니다.

Sequence 코드 설명 동작
ESC [ <n> m SGR 그래픽 변환 설정 <n>에 지정된 대로 화면 및 텍스트의 서식을 설정합니다.

다음 표의 값을 <n>에 사용하여 다른 서식 지정 모드를 표현할 수 있습니다.

서식 지정 모드는 왼쪽에서 오른쪽으로 적용됩니다. 서로 경쟁하는 서식 지정 옵션을 적용하면 맨 오른쪽 옵션이 우선적으로 적용됩니다.

색을 지정하는 옵션의 경우 SetConsoleScreenBufferInfoEx API를 사용하여 수정할 수 있는 콘솔 색 테이블에 정의된 대로 색이 사용됩니다. 테이블의 "파란색" 위치에 빨간색 RGB 음영을 표시하도록 테이블을 수정하면 변경 전까지 Foreground Blue를 호출할 때마다 빨간색이 표시됩니다.

설명 동작
0 기본값 모든 특성을 수정 전의 기본 상태로 되돌리기
1 굵게/밝게 전경색에 밝기/강도 플래그 적용
22 굵지 않음/밝지 않음 전경색에서 밝기/강도 플래그 제거
4 밑줄 밑줄 추가
24 밑줄 없음 밑줄 제거
7 부정 전경색과 배경색 바꾸기
27 양수(음수 불가능) 전경/배경으로 기본으로 되돌리기
30 전경 검은색 전경에 굵지 않은/밝지 않은 검은색 적용
31 전경 빨강 전경에 굵지 않은/밝지 않은 빨강 적용
32 전경 녹색 전경에 굵지 않은/밝지 않은 녹색 적용
33 전경 노랑 전경에 굵지 않은/밝지 않은 노랑 적용
34 전경 파랑 전경에 굵지 않은/밝지 않은 파랑 적용
35 전경 자홍 전경에 굵지 않은/밝지 않은 자홍 적용
36 전경 녹청 전경에 굵지 않은/밝지 않은 녹청 적용
37 전경 흰색 전경에 굵지 않은/밝지 않은 흰색 적용
38 전경 확장 전경에 확장된 색 값 적용(아래 세부 정보 참조)
39 전경 기본값 전경 기본값 부분만 적용(0 참조)
40 배경 검은색 배경에 굵지 않은/밝지 않은 검은색 적용
41 배경 빨강 배경에 굵지 않은/밝지 않은 빨강 적용
42 배경 녹색 배경에 굵지 않은/밝지 않은 녹색 적용
43 배경 노랑 배경에 굵지 않은/밝지 않은 노랑 적용
44 배경 파랑 배경에 굵지 않은/밝지 않은 파랑 적용
45 배경 자홍 배경에 굵지 않은/밝지 않은 자홍 적용
46 배경 녹청 배경에 굵지 않은/밝지 않은 녹청 적용
47 배경 흰색 배경에 굵지 않은/밝지 않은 흰색 적용
48 배경 확장 배경에 확장된 색 값 적용(아래 세부 정보 참조)
49 배경 기본값 배경 기본값 부분만 적용(0 참조)
90 밝은 전경 검은색 전경에 굵은/밝은 검은색 적용
91 밝은 전경 빨강 전경에 굵은/밝은 빨강 적용
92 밝은 전경 녹색 전경에 굵은/밝은 녹색 적용
93 밝은 전경 노랑 전경에 굵은/밝은 노랑 적용
94 밝은 전경 파랑 전경에 굵은/밝은 파랑 적용
95 밝은 전경 자홍 전경에 굵은/밝은 자홍 적용
96 밝은 전경 녹청 전경에 굵은/밝은 녹청 적용
97 밝은 전경 흰색 전경에 굵은/밝은 흰색 적용
100 밝은 배경 검은색 배경에 굵은/밝은 검은색 적용
101 밝은 배경 빨강 배경에 굵은/밝은 빨강 적용
102 밝은 배경 녹색 배경에 굵은/밝은 녹색 적용
103 밝은 배경 노랑 배경에 굵은/밝은 노랑 적용
104 밝은 배경 파랑 배경에 굵은/밝은 파랑 적용
105 밝은 배경 자홍 배경에 굵은/밝은 자홍 적용
106 밝은 배경 녹청 배경에 굵은/밝은 녹청 적용
107 밝은 배경 흰색 배경에 굵은/밝은 흰색 적용

확장된 색

일부 가상 터미널 에뮬레이터는 Windows 콘솔에서 제공하는 16색보다 많은 색상표를 지원합니다. 이처럼 확장된 색의 경우 Windows 콘솔은 기존 16 색상표에서 가장 가까운 색을 선택하여 표시합니다. 위의 일반적인 SGR 값과 달리, 확장된 값은 아래 표에 따라 첫 번째 표시기 뒤에 추가 매개 변수를 사용합니다.

SGR 하위 시퀀스 설명
38 ; 2 ; <r> ; <g> ; <b> 전경색을 r, g, <b 매개 변수에 <지정된 RGB> 값으로 설정*><>
48 ; 2 ; <r> ; <g> ; <b> r, g>, <<b> 매개 변수에 지정된 RGB 값으로>< 배경색 설정*
38 ; 5 ; <s> 88 또는 256 색 표에서 전경색을 <인> 덱스로 설정*
48 ; 5 ; <s> 88 또는 256 색 표에서 배경색 <을 인> 덱스로 설정*

*비교를 위해 내부적으로 기본 88 및 256 색상표는 xterm 터미널 에뮬레이터를 기반으로 합니다. 지금은 비교/반올림 테이블을 수정할 수 없습니다.

화면색

다음 명령을 사용하여 애플리케이션에서 화면 색상표 값을 RGB 값으로 설정할 수 있습니다.

RGB 값은 0~ff 사이의 16진수 값이어야 하고 슬래시 문자(예: rgb:1/24/86)로 구분되어야 합니다.

이 시퀀스는 OSC "운영 체제 명령" 시퀀스이며 나열된 다른 많은 시퀀스와 같은 CSI가 아니고 "\x1b["가 아닌 "\x1b]"로 시작합니다. OSC 시퀀스는 ()로 표시되고 전송되는 문자열 종결자로 종료됩니다ESC \0x1B 0x5C.<ST> BEL(0x7)을 종결자로 대신 사용할 수 있지만, 더 긴 형식을 사용하는 것이 좋습니다.

Sequence 설명 동작
ESC ] 4 ; <i> ; rgb : <r> / <g> / <b><ST> 화면색 수정 화면 색상표 인덱스 <i>를 <r>, <g>, <b>에 지정된 RGB 값으로 설정

모드 변경

입력 모드를 제어하는 시퀀스가 있습니다. 입력 모드에는 커서 키 모드와 키패드 키 모드의 두 가지 종류가 있습니다. 커서 키 모드는 화살표 키뿐 아니라 Home 및 End 키로 내보내는 시퀀스를 제어하는 반면, 키패드 키 모드는 주로 숫자 키패드의 키와 기능 키로 내보내는 시퀀스를 제어합니다.

이러한 각 모드는 간단한 부울 설정입니다. 커서 키 모드는 표준(기본값) 또는 애플리케이션이며, 키패드 키 모드는 숫자(기본값) 또는 애플리케이션입니다.

이러한 모드에서 내보내는 시퀀스에 대한 내용은 커서 키 및 숫자 키패드/기능 키 섹션을 참조하세요.

Sequence 코드 설명 동작
ESC = DECKPAM 키패드 애플리케이션 모드 사용 키패드 키는 애플리케이션 모드 시퀀스를 내보냅니다.
ESC > DECKPNM 키패드 숫자 모드 사용 키패드 키는 숫자 모드 시퀀스를 내보냅니다.
ESC [ ? 1 h DECCKM 커서 키 애플리케이션 모드 사용 키패드 키는 애플리케이션 모드 시퀀스를 내보냅니다.
ESC [ ? 1 l DECCKM 커서 키 애플리케이션 모드 사용 안 함(표준 모드 사용) 키패드 키는 숫자 모드 시퀀스를 내보냅니다.

상태 쿼리

이 섹션의 모든 명령은 일반적으로 Get* 콘솔 API를 호출하여 현재 콘솔 버퍼 상태에 대한 상태 정보를 검색하는 것과 같습니다.

참고 항목

이러한 쿼리는 ENABLE_VIRTUAL_TERMINAL_PROCESSING 설정된 동안 출력 스트림에서 인식된 직후 콘솔 입력 스트림으로 응답을 내보낸다. ENABLE_VIRTUAL_TERMINAL_INPUT 플래그는 쿼리를 만드는 애플리케이션이 항상 회신을 수신하려고 하는 것으로 가정하므로 쿼리 명령에는 적용되지 않습니다.

Sequence 코드 설명 동작
ESC [ 6 n DECXCPR 커서 위치 보고 커서 위치를 다음과 같이 내보낸다: ESC [ <r> ; <c> R Where <r> = 커서 행 및 <c> = 커서 열
ESC [ 0 c DA 디바이스 특성 터미널 ID를 보고합니다. "\x1b[?1; "옵션 없는 VT101"을 나타내는 0c"입니다.

Windows 콘솔에서는 일반적으로 탭 너비가 8자일 것으로 예상하지만 특정 시퀀스를 활용하는 *nix 애플리케이션은 탭이 콘솔 창 내에 있는 위치를 조작하여 애플리케이션의 커서 이동을 최적화할 수 있습니다.

애플리케이션에서 다음 시퀀스를 사용하여 콘솔 창 내에서 탭 정지 위치를 설정하고, 제거하고, 탭 정지 위치 간에 탐색할 수 있습니다.

Sequence 코드 설명 동작
ESC H HTS 가로 탭 설정 커서가 있는 현재 열에서 탭 정지를 설정합니다.
ESC [ <n> I CHT 커서 가로(앞으로) 탭 탭 정지가 있는 (같은 행의) 다음 열로 커서를 이동합니다. 탭 정지가 더 이상 없으면 행의 마지막 열로 이동합니다. 커서가 마지막 열에 있으면 다음 행의 첫 번째 열로 이동합니다.
ESC [ <n> Z CBT 커서 뒤로 탭 탭 정지가 있는 (같은 행의) 이전 열로 커서를 이동합니다. 탭 정지가 더 이상 없으면 커서를 첫 번째 열로 이동합니다. 커서가 첫 번째 열에 있으면 커서를 이동하지 않습니다.
ESC [ 0 g TBC 탭 지우기(현재 열) 현재 열의 탭 정지를 지웁니다(있는 경우). 탭 정지가 없으면 아무 작업도 수행하지 않습니다.
ESC [ 3 g TBC 탭 지우기(모든 열) 현재 설정된 탭 정지를 모두 지웁니다.
  • CHT 및 CBT에서 <n>은 커서를 지정된 방향으로 이동하는 횟수를 나타내는 선택적 매개 변수입니다(기본값=1).
  • HTS를 통해 설정된 탭 정지가 없으면 CHT 및 CBT는 창의 첫 번째 열과 마지막 열을 두 개의 탭 정지로 간주합니다.
  • 또한 HTS를 사용하여 탭 정지를 설정하면 콘솔이 CHT와 동일한 방식으로 TAB(0x09, '\t') 문자의 출력에서 다음 탭 정지로 이동합니다.

문자 세트 지정

다음 시퀀스를 사용하여 프로그램에서 활성 문자 세트 매핑을 변경할 수 있습니다. 이를 통해 프로그램에서는 7비트 ASCII 문자를 내보내고, 터미널 화면 자체에 다른 문자 모양으로 표시할 수 있습니다. 현재 지원되는 두 가지 문자 세트는 ASCII(기본값) 및 DEC 특수 그래픽 문자 세트입니다. DEC 특수 그래픽 문자 세트로 표시되는 모든 문자 목록은 http://vt100.net/docs/vt220-rm/table2-4.html을 참조하세요.

Sequence 설명 동작
ESC ( 0 문자 세트 지정 – DEC 선 그리기 DEC 선 그리기 모드 사용
ESC ( B 문자 세트 지정 – US ASCII ASCII 모드 사용(기본값)

DEC 선 그리기 모드는 콘솔 애플리케이션에서 테두리를 그리는 데 사용됩니다. 다음 표에서는 어떤 ASCII 문자가 어떤 선 그리기 문자에 매핑되는지 보여줍니다.

16진수 ASCII DEC 선 그리기
0x6a j
0x6b k
0x6c l
0x6d
0x6e n
0x71 q
0x74 t
0x75 u
0x76 v
0x77 w
0x78 x

스크롤 여백

다음 시퀀스를 사용하면 프로그램에서 스크롤 작업의 영향을 받는 화면의 "스크롤 영역"을 구성할 수 있습니다. 화면이 '\n' 또는 RI와 같이 스크롤될 때 조정되는 행의 하위 집합입니다. 이러한 여백은 줄 삽입(IL) 및 줄 삭제(DL), 위로 스크롤(SU) 및 아래로 스크롤(SD)에 의해 수정된 행에도 영향을 줍니다.

스크롤 여백은 애플리케이션의 맨 위에 제목 표시줄을 배치하거나 맨 아래에 상태 표시줄을 배치하는 경우처럼 화면의 일부는 나머지 부분이 채워질 때 스크롤되지 않도록 만들고 싶을 경우 특히 유용하게 사용할 수 있습니다.

DECSTBM의 경우 스크롤 영역(포함)의 위쪽 줄과 아래쪽 줄을 나타내는 행을 지정하는 데 사용되는 두 가지 선택적 매개 변수 <t> 및 <b>가 있습니다. 매개 변수를 생략하면 <t>는 기본적으로 1로 설정되고 <b>는 기본적으로 현재 뷰포트 높이로 설정됩니다.

스크롤 여백은 버퍼 단위이므로 대체 버퍼와 주 버퍼가 별도의 스크롤 여백 설정을 유지합니다(따라서 대체 버퍼의 전체 화면 애플리케이션이 주 버퍼의 여백을 포이즌하지 않음).

Sequence 코드 설명 동작
ESC [ <t> ; <b> r DECSTBM 스크롤 영역 설정 뷰포트의 VT 스크롤 여백을 설정합니다.

창 제목

다음 명령을 사용하면 애플리케이션에서 콘솔 창의 제목을 지정된 <문자열> 매개 변수로 설정할 수 있습니다. 문자열은 255자 미만이어야 합니다. 지정된 문자열로 SetConsoleTitle을 호출할 때와 동일합니다.

이러한 시퀀스는 OSC "운영 체제 명령" 시퀀스이며 나열된 다른 많은 시퀀스와 같은 CSI가 아니고 "\x1b["가 아닌 "\x1b]"로 시작됩니다. OSC 시퀀스는 ()로 표시되고 전송되는 문자열 종결자로 종료됩니다ESC \0x1B 0x5C.<ST> BEL(0x7)을 종결자로 대신 사용할 수 있지만, 더 긴 형식을 사용하는 것이 좋습니다.

Sequence 설명 동작
ESC ] 0 ; <문자열><세인트> 창 제목 설정 콘솔 창의 제목을 <문자열>로 설정합니다.
ESC ] 2 ; <문자열><세인트> 창 제목 설정 콘솔 창의 제목을 <문자열>로 설정합니다.

여기서 종료되는 문자는 "Bell" 문자 '\x07'입니다.

대체 화면 버퍼

*Nix 스타일 애플리케이션은 종종 대체 화면 버퍼를 활용하므로 버퍼를 시작한 애플리케이션에 영향을 주지 않고 버퍼의 전체 콘텐츠를 수정할 수 있습니다. 대체 버퍼는 스크롤백 영역 없이 정확하게 창 크기와 일치합니다.

이 동작에 대한 예제는 bash에서 vim을 시작하는 경우를 생각해 보세요. Vim은 전체 화면을 사용하여 파일을 편집합니다. 그 후 bash로 돌아가면 원래 버퍼가 변경되지 않은 상태로 유지됩니다.

Sequence 설명 동작
ESC [ ? 1 0 4 9 h 대체 화면 버퍼 사용 새 대체 화면 버퍼로 전환합니다.
ESC [ ? 1 0 4 9 l 주 화면 버퍼 사용 주 버퍼로 전환합니다.

창 너비

다음 시퀀스를 사용하여 콘솔 창의 너비를 제어할 수 있습니다. SetConsoleScreenBufferInfoEx 콘솔 API를 호출하여 창 너비를 설정하는 방법과 거의 동일합니다.

Sequence 코드 설명 동작
ESC [ ? 3 h DECCOLM 열 수를 132로 설정 콘솔 너비를 열 132개로 설정합니다.
ESC [ ? 3 l DECCOLM 열 수를 80으로 설정 콘솔 너비를 열 80개로 설정합니다.

소프트 초기화

다음 시퀀스를 사용하여 특정 속성을 기본값으로 초기화할 수 있습니다. 다음 속성은 아래와 같은 기본값으로 초기화됩니다. 이러한 속성을 제어하는 시퀀스도 나열되어 있습니다.

  • 커서 표시 유형: visible (DECTEM)
  • 숫자 키패드: 숫자 모드(DECNKM)
  • 커서 키 모드: 기본 모드(DECCKM)
  • 위쪽 및 아래쪽 여백: 위쪽=1, 아래쪽=콘솔 높이(DECSTBM)
  • 문자 집합: US ASCII
  • 그래픽 변환: 기본/해제(SGR)
  • 커서 상태 저장: 홈 위치(0,0)(DECSC)
Sequence 코드 설명 동작
ESC [ ! p DECSTR 소프트 초기화 특정 터미널 설정을 기본값으로 초기화

입력 시퀀스

SetConsoleMode 플래그를 사용하여 입력 버퍼 핸들에 ENABLE_VIRTUAL_TERMINAL_INPUT 플래그가 설정된 경우 입력 스트림의 콘솔 호스트에서 다음 터미널 시퀀스를 내보냅니다.

지정된 입력 키에 대해 내보낼 시퀀스를 제어하는 두 가지 내부 모드로 커서 키 모드와 키패드 키 모드가 있습니다. 관련 내용은 모드 변경 섹션에 설명되어 있습니다.

커서 키

표준 모드 애플리케이션 모드
위쪽 화살표 ESC [ A ESC O A
아래쪽 화살표 ESC [ B ESC O B
오른쪽 화살표 ESC [ C ESC O C
왼쪽 화살표 ESC [ D ESC O D
ESC [ H ESC O H
종료 ESC [ F ESC O F

또한 이러한 키 중 하나를 사용하여 Ctrl 키를 누르면 커서 키 모드에 관계 없이 다음 시퀀스가 대신 내보내집니다.

모든 모드
Ctrl + 위쪽 화살표 ESC [ 1 ; 5 A
Ctrl + 아래쪽 화살표 ESC [ 1 ; 5 B
Ctrl + 오른쪽 화살표 ESC [ 1 ; 5 C
Ctrl + 왼쪽 화살표 ESC [ 1 ; 5 D

숫자 패드 및 기능 키

Sequence
백스페이스 0x7f (DEL)
일시 중지 0x1a (SUB)
Esc 0x1b (ESC)
삽입 ESC [ 2 ~
삭제 ESC [ 3 ~
Page Up ESC [ 5 ~
Page Down ESC [ 6 ~
F1 ESC O P
F2 ESC O Q
F3 ESC O R
F4 ESC O S
F5 ESC [ 1 5 ~
F6 ESC [ 1 7 ~
F7 ESC [ 1 8 ~
F8 ESC [ 1 9 ~
F9 ESC [ 2 0 ~
F10 ESC [ 2 1 ~
F11 ESC [ 2 3 ~
F12 ESC [ 2 4 ~

한정자

Alt는 시퀀스에 이스케이프 접두사를 추가하여 처리됩니다. 여기서 c>는 운영 체제에서 전달하는 문자인 ESC <c><입니다. Alt+Ctrl은 운영 체제에서 <c> 키를 애플리케이션으로 릴레이할 적절한 제어 문자로 미리 이동한다는 점을 제외하고 동일한 방식으로 처리됩니다.

Ctrl은 일반적으로 시스템에서 받은 그대로 전달됩니다. 일반적으로 제어 문자 예약 공간(0x0-0x1f)으로 이동되는 단일 문자입니다. 예를 들어 Ctrl+@(0x40)는 NUL(0x00),Ctrl+[(0x5b)는 ESC(0x1b) 등이 됩니다. 다음 표에 따라 몇 가지 Ctrl 키 조합이 특별히 처리됩니다.

Sequence
Ctrl+스페이스바 0x00 (NUL)
Ctrl + 위쪽 화살표 ESC [ 1 ; 5 A
Ctrl + 아래쪽 화살표 ESC [ 1 ; 5 B
Ctrl + 오른쪽 화살표 ESC [ 1 ; 5 C
Ctrl + 왼쪽 화살표 ESC [ 1 ; 5 D

참고 항목

왼쪽 Ctrl + 오른쪽 Alt는 AltGr로 처리됩니다. 둘 다 함께 표시되면 둘 다 제거되고 시스템에서 제공하는 문자의 유니코드 값이 대상으로 전달됩니다. 시스템은 현재 시스템 입력 설정에 따라 AltGr 값을 미리 변환합니다.

샘플

SGR 터미널 시퀀스 예제

다음 코드에서는 여러 가지 텍스트 서식 지정 예제를 제공합니다.

#include <stdio.h>
#include <wchar.h>
#include <windows.h>

int main()
{
    // Set output mode to handle virtual terminal sequences
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        return GetLastError();
    }

    DWORD dwMode = 0;
    if (!GetConsoleMode(hOut, &dwMode))
    {
        return GetLastError();
    }

    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    if (!SetConsoleMode(hOut, dwMode))
    {
        return GetLastError();
    }

    // Try some Set Graphics Rendition (SGR) terminal escape sequences
    wprintf(L"\x1b[31mThis text has a red foreground using SGR.31.\r\n");
    wprintf(L"\x1b[1mThis text has a bright (bold) red foreground using SGR.1 to affect the previous color setting.\r\n");
    wprintf(L"\x1b[mThis text has returned to default colors using SGR.0 implicitly.\r\n");
    wprintf(L"\x1b[34;46mThis text shows the foreground and background change at the same time.\r\n");
    wprintf(L"\x1b[0mThis text has returned to default colors using SGR.0 explicitly.\r\n");
    wprintf(L"\x1b[31;32;33;34;35;36;101;102;103;104;105;106;107mThis text attempts to apply many colors in the same command. Note the colors are applied from left to right so only the right-most option of foreground cyan (SGR.36) and background bright white (SGR.107) is effective.\r\n");
    wprintf(L"\x1b[39mThis text has restored the foreground color only.\r\n");
    wprintf(L"\x1b[49mThis text has restored the background color only.\r\n");

    return 0;
}

참고 항목

이전 예제에서 문자열 '\x1b[31m'은 n이 31인 ESC [ <n> m<> 의 구현입니다.

다음 그림은 이전 코드 예제의 출력을 보여줍니다.

output of the console using the sgr command

가상 터미널 처리 사용 예제

다음 코드는 애플리케이션에 가상 터미널 처리를 사용하도록 설정하는 권장 방법의 예를 제공합니다. 이 샘플의 목적은 다음을 보여주는 것입니다.

  1. 기존 모드는 항상 GetConsoleMode를 통해 검색하여 분석한 후 SetConsoleMode로 설정되어야 합니다.

  2. SetConsoleMode가 반환되고 GetLastError가 ERROR_INVALID_PARAMETER 반환 0 하는지 여부를 확인하는 것은 하위 수준 시스템에서 실행할 때 확인하는 현재 메커니즘입니다. 비트 필드에서 최신 콘솔 모드 플래그 중 하나를 사용하여 ERROR_INVALID_PARAMETER 수신하는 애플리케이션은 정상적으로 동작을 저하시키고 다시 시도해야 합니다.

#include <stdio.h>
#include <wchar.h>
#include <windows.h>

int main()
{
    // Set output mode to handle virtual terminal sequences
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        return false;
    }
    HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
    if (hIn == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    DWORD dwOriginalOutMode = 0;
    DWORD dwOriginalInMode = 0;
    if (!GetConsoleMode(hOut, &dwOriginalOutMode))
    {
        return false;
    }
    if (!GetConsoleMode(hIn, &dwOriginalInMode))
    {
        return false;
    }

    DWORD dwRequestedOutModes = ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
    DWORD dwRequestedInModes = ENABLE_VIRTUAL_TERMINAL_INPUT;

    DWORD dwOutMode = dwOriginalOutMode | dwRequestedOutModes;
    if (!SetConsoleMode(hOut, dwOutMode))
    {
        // we failed to set both modes, try to step down mode gracefully.
        dwRequestedOutModes = ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        dwOutMode = dwOriginalOutMode | dwRequestedOutModes;
        if (!SetConsoleMode(hOut, dwOutMode))
        {
            // Failed to set any VT mode, can't do anything here.
            return -1;
        }
    }

    DWORD dwInMode = dwOriginalInMode | dwRequestedInModes;
    if (!SetConsoleMode(hIn, dwInMode))
    {
        // Failed to set VT input mode, can't do anything here.
        return -1;
    }

    return 0;
}

1주년 업데이트 기능 선택 예제

다음은 Windows 10 1주년 업데이트에 추가된 기능을 중심으로 다양한 이스케이프 시퀀스를 사용하여 버퍼를 조작하는 보다 강력한 코드를 보여주는 예제입니다.

이 예제에서는 대체 화면 버퍼를 사용하여 탭 정지를 조작하고, 스크롤 여백을 설정하고, 문자 세트를 변경합니다.

// System headers
#include <windows.h>

// Standard library C-style
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>

#define ESC "\x1b"
#define CSI "\x1b["

bool EnableVTMode()
{
    // Set output mode to handle virtual terminal sequences
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    DWORD dwMode = 0;
    if (!GetConsoleMode(hOut, &dwMode))
    {
        return false;
    }

    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    if (!SetConsoleMode(hOut, dwMode))
    {
        return false;
    }
    return true;
}

void PrintVerticalBorder()
{
    printf(ESC "(0"); // Enter Line drawing mode
    printf(CSI "104;93m"); // bright yellow on bright blue
    printf("x"); // in line drawing mode, \x78 -> \u2502 "Vertical Bar"
    printf(CSI "0m"); // restore color
    printf(ESC "(B"); // exit line drawing mode
}

void PrintHorizontalBorder(COORD const Size, bool fIsTop)
{
    printf(ESC "(0"); // Enter Line drawing mode
    printf(CSI "104;93m"); // Make the border bright yellow on bright blue
    printf(fIsTop ? "l" : "m"); // print left corner 

    for (int i = 1; i < Size.X - 1; i++)
        printf("q"); // in line drawing mode, \x71 -> \u2500 "HORIZONTAL SCAN LINE-5"

    printf(fIsTop ? "k" : "j"); // print right corner
    printf(CSI "0m");
    printf(ESC "(B"); // exit line drawing mode
}

void PrintStatusLine(const char* const pszMessage, COORD const Size)
{
    printf(CSI "%d;1H", Size.Y);
    printf(CSI "K"); // clear the line
    printf(pszMessage);
}

int __cdecl wmain(int argc, WCHAR* argv[])
{
    argc; // unused
    argv; // unused
    //First, enable VT mode
    bool fSuccess = EnableVTMode();
    if (!fSuccess)
    {
        printf("Unable to enter VT processing mode. Quitting.\n");
        return -1;
    }
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        printf("Couldn't get the console handle. Quitting.\n");
        return -1;
    }

    CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo;
    GetConsoleScreenBufferInfo(hOut, &ScreenBufferInfo);
    COORD Size;
    Size.X = ScreenBufferInfo.srWindow.Right - ScreenBufferInfo.srWindow.Left + 1;
    Size.Y = ScreenBufferInfo.srWindow.Bottom - ScreenBufferInfo.srWindow.Top + 1;

    // Enter the alternate buffer
    printf(CSI "?1049h");

    // Clear screen, tab stops, set, stop at columns 16, 32
    printf(CSI "1;1H");
    printf(CSI "2J"); // Clear screen

    int iNumTabStops = 4; // (0, 20, 40, width)
    printf(CSI "3g"); // clear all tab stops
    printf(CSI "1;20H"); // Move to column 20
    printf(ESC "H"); // set a tab stop

    printf(CSI "1;40H"); // Move to column 40
    printf(ESC "H"); // set a tab stop

    // Set scrolling margins to 3, h-2
    printf(CSI "3;%dr", Size.Y - 2);
    int iNumLines = Size.Y - 4;

    printf(CSI "1;1H");
    printf(CSI "102;30m");
    printf("Windows 10 Anniversary Update - VT Example");
    printf(CSI "0m");

    // Print a top border - Yellow
    printf(CSI "2;1H");
    PrintHorizontalBorder(Size, true);

    // // Print a bottom border
    printf(CSI "%d;1H", Size.Y - 1);
    PrintHorizontalBorder(Size, false);

    wchar_t wch;

    // draw columns
    printf(CSI "3;1H");
    int line = 0;
    for (line = 0; line < iNumLines * iNumTabStops; line++)
    {
        PrintVerticalBorder();
        if (line + 1 != iNumLines * iNumTabStops) // don't advance to next line if this is the last line
            printf("\t"); // advance to next tab stop

    }

    PrintStatusLine("Press any key to see text printed between tab stops.", Size);
    wch = _getwch();

    // Fill columns with output
    printf(CSI "3;1H");
    for (line = 0; line < iNumLines; line++)
    {
        int tab = 0;
        for (tab = 0; tab < iNumTabStops - 1; tab++)
        {
            PrintVerticalBorder();
            printf("line=%d", line);
            printf("\t"); // advance to next tab stop
        }
        PrintVerticalBorder();// print border at right side
        if (line + 1 != iNumLines)
            printf("\t"); // advance to next tab stop, (on the next line)
    }

    PrintStatusLine("Press any key to demonstrate scroll margins", Size);
    wch = _getwch();

    printf(CSI "3;1H");
    for (line = 0; line < iNumLines * 2; line++)
    {
        printf(CSI "K"); // clear the line
        int tab = 0;
        for (tab = 0; tab < iNumTabStops - 1; tab++)
        {
            PrintVerticalBorder();
            printf("line=%d", line);
            printf("\t"); // advance to next tab stop
        }
        PrintVerticalBorder(); // print border at right side
        if (line + 1 != iNumLines * 2)
        {
            printf("\n"); //Advance to next line. If we're at the bottom of the margins, the text will scroll.
            printf("\r"); //return to first col in buffer
        }
    }

    PrintStatusLine("Press any key to exit", Size);
    wch = _getwch();

    // Exit the alternate buffer
    printf(CSI "?1049l");

}