Sequências de terminais virtuais do console

As sequências de terminais virtuais são sequências de caracteres de controle que podem controlar o movimento do cursor, a cor do console e outras operações quando gravadas no fluxo de saída. As sequências também poderão ser recebidas no fluxo de entrada em resposta a uma sequência de informações de consulta do fluxo de saída ou como uma codificação de entrada do usuário quando o modo apropriado for definido.

Você pode usar as funções GetConsoleMode e SetConsoleMode para configurar esse comportamento. Um exemplo da maneira sugerida de habilitar comportamentos de terminal virtual está incluído no final deste documento.

O comportamento das sequências a seguir baseia-se nas tecnologias de emulador de terminal VT100 e derivadas, mais especificamente no emulador de terminal xterm. Mais informações sobre as sequências de terminais podem ser encontradas em http://vt100.net e em http://invisible-island.net/xterm/ctlseqs/ctlseqs.html.

Sequências de saída

As sequências de terminal a seguir serão interceptadas pelo host do console quando gravadas no fluxo de saída, se o sinalizador ENABLE_VIRTUAL_TERMINAL_PROCESSING estiver definido no identificador de buffer de tela usando a função SetConsoleMode. Observe que o sinalizador DISABLE_NEWLINE_AUTO_RETURN também pode ser útil para emular o posicionamento do cursor e o comportamento de rolagem de outros emuladores de terminal em relação aos caracteres escritos na coluna final em qualquer linha.

Posicionamento simples do cursor

Em todas as descrições a seguir, ESC sempre é o valor hexadecimal 0x1B. Não há espaços a serem incluídos nas sequências de terminais. Sequências de terminal individuais podem ser divididas, em qualquer posição de caractere ou byte, em várias chamadas sequenciais para WriteFile ou WriteConsole, mas é recomendada a inclusão de toda a sequência em uma chamada. Para obter um exemplo de como essas sequências são usadas na prática, confira o exemplo no final deste tópico.

A tabela a seguir descreve as sequências de escape simples com um só comando de ação diretamente após o caractere ESC. Essas sequências não têm parâmetros e entram em vigor imediatamente.

Todos os comandos nessa tabela geralmente são equivalentes a chamar a API de console SetConsoleCursorPosition para posicionar o cursor.

O movimento do cursor será limitado pelo visor atual no buffer. A rolagem (se disponível) não ocorrerá.

Sequência Abreviação Comportamental
ESC M RI Índice reverso – Executa a operação reversa de \n, move o cursor uma linha para cima, mantém a posição horizontal e rola o buffer, se necessário*
ESC 7 DECSC Salva a posição do cursor na memória**
ESC 8 DECSR Restaura a posição do cursor da memória**

Observação

* Se houver margens de rolagem definidas, o RI dentro das margens rolará apenas o conteúdo delas e deixará o visor inalterado. (Confira Margens de rolagem)

**Não haverá nenhum valor salvo na memória até o primeiro uso do comando save. A única maneira de acessar o valor salvo é com o comando restore.

Posicionamento do cursor

As tabelas a seguir abrangem sequências do tipo CSI (Introdutor de Sequência de Controle). Todas as sequências do CSI começam com ESC (0x1B), são seguidas por [ (colchete esquerdo, 0x5B) e podem conter parâmetros de comprimento variável para especificar mais informações para cada operação. Isso será representado pela abreviação <n>. Cada tabela abaixo é agrupada por funcionalidade com observações abaixo de cada tabela explicando como o grupo funciona.

As seguintes regras se aplicam a todos os parâmetros, a menos que indicado de outra forma:

  • <n> representa a distância a ser movida e é um parâmetro opcional
  • Se <n> for omitido ou for igual a 0, ele será tratado como 1
  • <n> não pode ser maior que 32.767 (valor curto máximo)
  • <n> não pode ser negativo

Todos os comandos nessa seção geralmente são equivalentes a chamar a API de console SetConsoleCursorPosition.

O movimento do cursor será limitado pelo visor atual no buffer. A rolagem (se disponível) não ocorrerá.

Sequência Código Descrição Comportamento
ESC [ <n> A CUU O cursor sobe O cursor sobe <n> linhas
ESC [ <n> B CUD O cursor desce O cursor desce <n> linhas
ESC [ <n> C CUF O cursor avança O cursor avança (direita) <n> colunas
ESC [ <n> D CUB O cursor volta O cursor volta (esquerda) <n> colunas
ESC [ <n> E CNL Cursor para a próxima linha O cursor desce <n> linhas da posição atual
ESC [ <n> F CPL Cursor para a linha anterior Cursor sobe <n> linhas da posição atual
ESC [ <n> G CHA Cursor horizontal absoluto O cursor move-se para a <n>ª posição horizontalmente na linha atual
ESC [ <n> d VPA Posição de linha vertical absoluta O cursor move-se para a <n>ª posição verticalmente na coluna atual
ESC [ <y> ; <x> H CUP Posição do cursor *O cursor move-se para a coordenada <x>; <y> dentro do visor, em que <x> é a coluna da linha <y>
ESC [ <y> ; <x> f HVP Posição vertical horizontal *O cursor move-se para a coordenada <x>; <y> dentro do visor, em que <x> é a coluna da linha <y>
ESC [ s ANSISYSSC Salvar o cursor – Emulação de Ansi.sys **Sem parâmetros, execute uma operação para salvar o cursor, como DECSC
ESC [ u ANSISYSRC Restaurar o cursor – Emulação de Ansi.sys **Sem parâmetros, execute uma operação para restaurar o cursor, como DECRC

Observação

Os parâmetros <x> e <y> têm as mesmas limitações que o <n> acima. Se <x> e <y> forem omitidos, eles serão definidos como 1;1.

**A documentação histórica do ANSI.sys pode ser encontrada em https://msdn.microsoft.com/library/cc722862.aspx e é implementada para fins de conveniência/compatibilidade.

Visibilidade do cursor

Os comandos a seguir controlam a visibilidade do cursor e o estado de intermitência. As sequências de DECTCEM geralmente são equivalentes a chamar a API de console SetConsoleCursorInfo para alternar a visibilidade do cursor.

Sequência Código Descrição Comportamento
ESC [ ? 12 h ATT160 Habilitar intermitência do cursor de texto Iniciar a intermitência do cursor
ESC [ ? 12 l ATT160 Desabilitar intermitência do cursor de texto Parar a intermitência do cursor
ESC [ ? 25 h DECTCEM Habilitar o modo de exibição do cursor de texto Exibir o cursor
ESC [ ? 25 l DECTCEM Habilitar o modo oculto do cursor de texto Ocultar o cursor

Dica

As sequências de habilitação terminam com um caractere H minúsculo (h) e as sequências de desabilitação terminam com um caractere L minúsculo (l).

Forma do cursor

Os comandos a seguir controlam e permitem a personalização da forma do cursor.

Sequência Código Descrição Comportamento
ESC [ 0 SP q DECSCUSR Forma do usuário Forma de cursor padrão configurada pelo usuário
ESC [ 1 SP q DECSCUSR Bloco intermitente Forma de cursor do bloco intermitente
ESC [ 2 SP q DECSCUSR Bloco constante Forma de cursor do bloco constante
ESC [ 3 SP q DECSCUSR Sublinhado intermitente Forma de cursor do sublinhado intermitente
ESC [ 4 SP q DECSCUSR Sublinhado constante Forma de cursor do sublinhado constante
ESC [ 5 SP q DECSCUSR Barra piscando Forma de cursor da barra intermitente
ESC [ 6 SP q DECSCUSR Barra constante Forma de cursor da barra constante

Observação

SP é um caractere espacial literal (0x20) na posição intermediária e é seguido por q (0x71) na posição final.

Posicionamento do visor

Todos os comandos nesta seção geralmente são equivalentes a chamar a API de console ScrollConsoleScreenBuffer para mover o conteúdo do buffer do console.

Cuidado Os nomes de comando são enganosos. Rolar refere-se a qual direção o texto move durante a operação e não a qual maneira o visor parece se mover.

Sequência Código Descrição Comportamento
ESC [ <n> S SU Rolar para cima Rolar o texto para cima por <n>. Também conhecido como panorâmica para baixo, novas linhas são preenchidas na parte inferior da tela
ESC [ <n> T SD Rolar para baixo Role para baixo por <n>. Também conhecido como panorâmica para cima, novas linhas são preenchidas na parte superior da tela

O texto é movido começando com a linha em que o cursor está. Se o cursor estiver na linha intermediária do visor, a rolagem para cima moverá a metade inferior do visor e inserirá as linhas em branco na parte inferior. A rolagem para baixo moveria a metade superior das linhas do visor e inseriria novas linhas na parte superior.

Também é importante observar que a rolagem para cima e para baixo também são afetadas pelas margens de rolagem. Rolar para cima e para baixo não afetará nenhuma linha fora das margens de rolagem.

O valor padrão para <n> é 1. e o valor pode ser opcionalmente omitido.

Modificação de dados

Todos os comandos nesta seção geralmente são equivalentes a chamar as APIs de console FillConsoleOutputCharacter, FillConsoleOutputAttribute e ScrollConsoleScreenBuffer para modificar o conteúdo do buffer de texto.

Sequência Código Descrição Comportamento
ESC [ <n> @ ICH Inserir caractere Insira <n> espaços na posição atual do cursor, deslocando todo o texto existente para a direita. O texto que sai da tela à direita é removido.
ESC [ <n> P DCH Excluir caractere Exclua <n> caracteres na posição atual do cursor, alternando em caracteres de espaço da borda direita da tela.
ESC [ <n> X ECH Apagar caractere Apague <n> caracteres da posição atual do cursor, substituindo-os por um caractere de espaço.
ESC [ <n> L IL Inserir linha Insere <n> linhas no buffer na posição do cursor. A linha em que o cursor está e as linhas abaixo dele serão deslocadas para baixo.
ESC [ <n> M DL Excluir linha Exclui <n> linhas do buffer, começando com a linha em que o cursor está.

Observação

Para IL e DL, somente as linhas nas margens de rolagem (confira Margens de rolagem) são afetadas. Se nenhuma margem for definida, as bordas de margem padrão serão o visor atual. Se as linhas forem deslocadas para baixo das margens, elas serão descartadas. Quando as linhas são excluídas, as linhas em branco são inseridas na parte inferior das margens e as linhas fora do visor nunca são afetadas.

Para cada uma das sequências, o valor padrão de <n> se ele for omitido será 0.

Para os seguintes comandos, o parâmetro <n> tem três valores válidos:

  • 0 apaga da posição atual do cursor (inclusive) até o fim da linha/tela
  • 1 apaga do início da linha/tela até e inclusive a posição atual do cursor
  • 2 apaga toda a linha/tela
Sequência Código Descrição Comportamento
ESC [ <n> J ED Apagar na tela Substitua todo o texto no visor/tela atual especificado em <n> por caracteres de espaço
ESC [ <n> K EL Apagar na linha Substitua todo o texto na linha com o cursor especificado em <n> por caracteres de espaço

Formatação de texto

Todos os comandos nesta seção geralmente são equivalentes a chamar as APIs de console SetConsoleTextAttribute para ajustar a formatação de todas as gravações futuras para o buffer de texto de saída do console.

Esse comando é especial, pois a posição <n> abaixo pode aceitar entre 0 e 16 parâmetros separados por ponto e vírgula.

Quando nenhum parâmetro for especificado, ele será tratado como um parâmetro 0.

Sequência Código Descrição Comportamento
ESC [ <n> m SGR Definir a representação de gráficos Definir o formato da tela e do texto conforme especificado por <n>

A tabela de valores a seguir pode ser usada em <n> para representar modos de formatação diferentes.

Os modos de formatação são aplicados da esquerda para a direita. A aplicação das opções de formatação concorrentes fará com que a opção mais à direita tenha precedência.

Para opções que especificam cores, as cores serão usadas conforme definido na tabela de cores do console que pode ser modificada usando a API SetConsoleScreenBufferInfoEx. Se a tabela for modificada para fazer com que a posição "azul" na tabela exiba um sombreamento de RGB vermelho, todas as chamadas para o Primeiro plano azul exibirão a cor vermelha até que ela seja alterada.

Valor Descrição Comportamento
0 Default Retorna todos os atributos para o estado padrão antes da modificação
1 Negrito/brilhante Aplica o sinalizador de brilho/intensidade à cor de primeiro plano
22 Sem negrito/brilhante Remove o sinalizador de brilho/intensidade da cor de primeiro plano
4 Sublinhado Adiciona o sublinhado
24 Sem sublinhado Remove o sublinhado
7 Negativo Altera as cores do primeiro plano e da tela de fundo
27 Positivo (sem negativo) Retorna o primeiro plano/tela de fundo para normal
30 Primeiro plano preto Aplica o preto sem negrito/brilhante no primeiro plano
31 Primeiro plano vermelho Aplica o vermelho sem negrito/brilhante no primeiro plano
32 Primeiro plano verde Aplica o verde sem negrito/brilhante no primeiro plano
33 Primeiro plano amarelo Aplica o amarelo sem negrito/brilhante no primeiro plano
34 Primeiro plano azul Aplica o azul sem negrito/brilhante no primeiro plano
35 Primeiro plano magenta Aplica o magenta sem negrito/brilhante no primeiro plano
36 Primeiro plano ciano Aplica o ciano sem negrito/brilhante no primeiro plano
37 Primeiro plano branco Aplica o branco sem negrito/brilhante no primeiro plano
38 Primeiro plano estendido Aplica o valor de cor estendida no primeiro plano (veja os detalhes abaixo)
39 Padrão de primeiro plano Aplica-se somente aos padrões do primeiro plano (veja 0)
40 Tela de fundo preta Aplica o preto sem negrito/brilhante na tela de fundo
41 Tela de fundo vermelha Aplica o vermelho sem negrito/brilhante na tela de fundo
42 Tela de fundo verde Aplica o verde sem negrito/brilhante na tela de fundo
43 Tela de fundo amarela Aplica o amarelo sem negrito/brilhante na tela de fundo
44 Tela de fundo azul Aplica o azul sem negrito/brilhante na tela de fundo
45 Tela de fundo magenta Aplica o magenta sem negrito/brilhante na tela de fundo
46 Tela de fundo ciano Aplica o ciano sem negrito/brilhante na tela de fundo
47 Tela de fundo branca Aplica o branco sem negrito/brilhante na tela de fundo
48 Tela de fundo estendida Aplica o valor de cor estendida na tela de fundo (veja os detalhes abaixo)
49 Padrão da tela de fundo Aplica-se somente aos padrões da tela de fundo (veja 0)
90 Primeiro plano preto brilhante Aplica o preto em negrito/brilhante no primeiro plano
91 Primeiro plano vermelho brilhante Aplica o vermelho em negrito/brilhante no primeiro plano
92 Primeiro plano em verde brilhante Aplica o verde em negrito/brilhante no primeiro plano
93 Primeiro plano amarelo brilhante Aplica o amarelo em negrito/brilhante no primeiro plano
94 Primeiro plano azul brilhante Aplica o azul em negrito/brilhante no primeiro plano
95 Primeiro plano magenta brilhante Aplica o magenta em negrito/brilhante no primeiro plano
96 Primeiro plano ciano brilhante Aplica o ciano em negrito/brilhante no primeiro plano
97 Primeiro plano branco brilhante Aplica o branco em negrito/brilhante no primeiro plano
100 Tela de fundo preta brilhante Aplica o preto em negrito/brilhante na tela de fundo
101 Tela de fundo vermelha brilhante Aplica o vermelho em negrito/brilhante na tela de fundo
102 Tela de fundo verde brilhante Aplica o verde em negrito/brilhante na tela de fundo
103 Tela de fundo amarela brilhante Aplica o amarelo em negrito/brilhante na tela de fundo
104 Tela de fundo azul brilhante Aplica o azul em negrito/brilhante na tela de fundo
105 Tela de fundo magenta brilhante Aplica o magenta em negrito/brilhante na tela de fundo
106 Tela de fundo ciano brilhante Aplica o ciano em negrito/brilhante na tela de fundo
107 Tela de fundo branca brilhante Aplica o branco em negrito/brilhante na tela de fundo

Cores estendidas

Alguns emuladores de terminal virtual dão suporte a uma paleta de cores maior do que as 16 cores fornecidas pelo Console do Windows. Para essas cores estendidas, o Console do Windows escolherá a cor apropriada mais próxima da tabela de 16 cores existente para a tela. Diferentemente dos valores de SGR típicos acima, os valores estendidos consumirão parâmetros adicionais após o indicador inicial de acordo com a tabela a seguir.

Subsequência de SGR Descrição
38 ; 2 ; <r> ; <g> ; <b> Define a cor de primeiro plano como o valor de RGB especificado nos parâmetros <r>, <g>, <b>*
48 ; 2 ; <r> ; <g> ; <b> Define a cor da tela de fundo como o valor de RGB especificado nos parâmetros <r>, <g>, <b>*
38 ; 5 ; <s> Define a cor de primeiro plano como o índice <s> na tabela de cores 88 ou 256*
48 ; 5 ; <s> Define a cor da tela de fundo como o índice <s> na tabela de cores 88 ou 256

*As paletas de cores 88 e 256 mantidas internamente para comparação são baseadas no emulador de terminal xterm. As tabelas de comparação/arredondamento não podem ser modificadas neste momento.

Cores da tela

O comando a seguir permite que o aplicativo defina os valores da paleta cores da tela para qualquer valor de RGB.

Os valores de RGB devem ser valores hexadecimais entre 0 e ff, separados pelo caractere de barra invertida (por exemplo, rgb:1/24/86).

Observe que essa sequência é uma sequência do OSC ("Comando do sistema operacional"), e não de um CSI como muitas das outras sequências listadas e, como tal, ela começa com “\x1b]”, não “\x1b[”. Como sequências de OSC, elas são encerradas com um terminador de cadeia de caracteres representado como <ST> e transmitido com ESC \ (0x1B 0x5C). Em vez disso, BEL (0x7) pode ser usado como o terminador, mas a forma mais longa é preferencial.

Sequência Descrição Comportamento
ESC ] 4 ; <i> ; rgb : <r> / <g> / <b><ST> Modificar cores da tela Define o índice da paleta de cores da tela <i> para os valores de RGB especificados em <r>, <g>, <b>

Alterações no modo

Essas são as sequências que controlam os modos de entrada. Há dois conjuntos diferentes de modos de entrada, o Modo de Teclas do Cursor e o Modo de Teclas do Teclado. O Modo de Teclas do Cursor controla as sequências emitidas pelas teclas de direção, bem como as teclas Home e End, enquanto o Modo de Teclas do Teclado controla as sequências emitidas principalmente pelas teclas no teclado numérico, bem como as teclas de função.

Cada um desses modos são configurações boolianas simples – o Modo de Teclas do Cursor é Normal (padrão) ou Aplicativo e o Modo de Teclas do Teclado é Numérico (padrão) ou Aplicativo.

Confira as seções Teclas do cursor e Chaves de função e do teclado numérico para obter as sequências emitidas nesses modos.

Sequência Código Descrição Comportamento
ESC = DECKPAM Habilitar o modo de aplicativo do teclado As teclas do teclado emitirão as sequências do Modo de Aplicativo.
ESC > DECKPNM Habilitar o modo numérico do teclado As teclas do teclado emitirão as sequências do Modo Numérico.
ESC [ ? 1 h DECCKM Habilitar o modo de aplicativo das teclas de cursor As teclas do teclado emitirão as sequências do Modo de Aplicativo.
ESC [ ? 1 l DECCKM Desabilitar o modo de aplicativo das teclas de cursor (usar o modo normal) As teclas do teclado emitirão as sequências do Modo Numérico.

Estado de consulta

Todos os comandos nesta seção geralmente são equivalentes a chamar as APIs de console Get* para recuperar informações de status sobre o estado atual do buffer do console.

Observação

Essas consultas emitirão as respostas para o fluxo de entrada do console imediatamente depois de serem reconhecidas no fluxo de saída, enquanto ENABLE_VIRTUAL_TERMINAL_PROCESSING é definido. O sinalizador ENABLE_VIRTUAL_TERMINAL_INPUT não se aplica a comandos de consulta, pois supõe-se que um aplicativo que faz a consulta sempre desejará receber a resposta.

Sequência Código Descrição Comportamento
ESC [ 6 n DECXCPR Relatar a posição do cursor ESC ESC [ <r> ; <c>, em que <r> é a linha do cursor e <c> é a coluna do cursor
ESC [ 0 c DA Atributos do dispositivo Relatar a identidade do terminal. Emitirá “\x1b[?1;0c”, indicando "VT101 sem opções".

Tabulações

Embora o console do Windows tradicionalmente espere que as tabulações tenham apenas oito caracteres de largura, os aplicativos nix* que usam determinadas sequências podem manipular onde as paradas de tabulação estão dentro das janelas do console para otimizar o movimento do cursor pelo aplicativo.

As sequências a seguir permitem que um aplicativo defina os locais de parada de tabulação na janela do console, remova-os e navegue entre eles.

Sequência Código Descrição Comportamento
ESC H HTS Definir a tabulação horizontal Define uma parada de tabulação na coluna atual em que o cursor está.
ESC [ <n> I CHT Tabulação horizontal do cursor (para frente) Avance o cursor para a próxima coluna (na mesma linha) com uma parada de tabulação. Se não houver mais paradas de tabulação, ele será movido para a última coluna da linha. Se o cursor estiver na última coluna, ele será movido para a primeira coluna da próxima linha.
ESC [ <n> Z CBT Tabulação de regressão do cursor Mova o cursor para a coluna anterior (na mesma linha) com uma parada de tabulação. Se não houver mais paradas de tabulação, o cursor será movido para a primeira coluna. Se o cursor estiver na primeira coluna, não mova o cursor.
ESC [ 0 g TBC Limpar tabulação (coluna atual) Limpa a parada de tabulação na coluna atual, se houver uma. Caso contrário, não faz nada.
ESC [ 3 g TBC Limpar tabulação (todas as colunas) Limpa todas as paradas de tabulação definidas no momento.
  • Para o CHT e o CBT, <n> é um parâmetro opcional que (padrão = 1) indica quantas vezes o cursor deve avançar na direção especificada.
  • Se não houver nenhuma parada de tabulação definida por meio de HTS, o CHT e o CBT tratarão a primeira e a última coluna da janela como as duas únicas paradas de tabulação.
  • Usar o HTS para definir uma parada de tabulação também fará com que o console navegue até a próxima parada de tabulação na saída de um caractere de TAB (0x09, ‘\t’), da mesma maneira que o CHT.

Designar o conjunto de caracteres

As sequências a seguir permitem que um programa altere o mapeamento de um conjunto de caracteres ativo. Isso permite que um programa emita caracteres ASCII de 7 bits, mas que eles sejam exibidos como outros glifos na própria tela do terminal. Atualmente, os dois conjuntos de caracteres com suporte são ASCII (padrão) e o DEC Special Graphics Character Set. Confira http://vt100.net/docs/vt220-rm/table2-4.html para obter uma lista de todos os caracteres representados pelo DEC Special Graphics Character Set.

Sequência Descrição Comportamento
ESC ( 0 Designar o conjunto de caracteres – Desenho de linha do DEC Habilita o modo de desenho de linha do DEC
ESC ( B Designar o conjunto de caracteres – US ASCII Habilita o modo ASCII (padrão)

Notavelmente, o modo de Desenho de Linha do DEC é usado para desenhar bordas em aplicativos de console. A tabela a seguir mostra qual caractere ASCII é mapeado para qual caractere de desenho de linha.

Hex ASCII Desenho de linha do DEC
0x6a j
0x6b k
0x6c l
0x6d m
0x6e n
0x71 q
0x74 t
0x75 u
0x76 v
0x77 w
0x78 x

Margens de rolagem

As sequências a seguir permitem que um programa configure a "região de rolagem" da tela que é afetada pelas operações de rolagem. Esse é um subconjunto das linhas que são ajustadas quando a tela rolar, por exemplo, em um ‘\n’ ou RI. Essas margens também afetam as linhas modificadas por Inserir Linha (IL) e Excluir Linha (DL), Rolar para Cima (SU) e Rolar para Baixo (SD).

As margens de rolagem podem ser especialmente úteis para ter uma parte da tela que não rola quando o restante da tela é preenchido, como ter uma barra de título na parte superior ou uma barra de status na parte inferior do seu aplicativo.

Para DECSTBM, há dois parâmetros opcionais, <t> e <b>, que são usados para especificar as linhas que representam as linhas superior e inferior da região de rolagem, inclusive. Se os parâmetros forem omitidos, o padrão de <t> será 1 e o padrão de <b> será a altura atual do visor.

As margens de rolagem são por buffer, portanto, é importante que o Buffer Alternado e o Buffer Principal mantenham configurações de margens de rolagem separadas (de modo que um aplicativo de tela inteira no buffer alternado não contaminará as margens do buffer principal).

Sequência Código Descrição Comportamento
ESC [ <t> ; <b> r DECSTBM Definir a região de rolagem Define as margens de rolagem de VT do visor.

Título da janela

Os comandos a seguir permitem que o aplicativo defina o título da janela do console para determinado parâmetro <string>. A cadeia de caracteres precisa ter menos de 255 caracteres para ser aceita. Isso é equivalente a chamar o SetConsoleTitle com a cadeia de caracteres fornecida.

Observe que essas sequências são sequências do OSC ("Comando do sistema operacional"), e não de um CSI como muitas das outras sequências listadas e, como tal, elas começam com “\x1b]”, não “\x1b[”. Como sequências de OSC, elas são encerradas com um terminador de cadeia de caracteres representado como <ST> e transmitido com ESC \ (0x1B 0x5C). Em vez disso, BEL (0x7) pode ser usado como o terminador, mas a forma mais longa é preferencial.

Sequência Descrição Comportamento
ESC ] 0 ; <cadeia de caracteres><ST> Window_Title Define o título da janela do console como <string>.
ESC ] 2 ; <cadeia de caracteres><ST> Window_Title Define o título da janela do console como <string>.

O caractere de encerramento aqui é o caractere “Sino”, ‘\x07’

Buffer de tela alternativo

*Os aplicativos de estilo Nix geralmente utilizam um buffer de tela alternativo, para que eles possam modificar todo o conteúdo do buffer, sem afetar o aplicativo que os iniciou. O buffer alternativo tem exatamente as mesmas dimensões da janela, sem nenhuma região retorno de rolagem.

Para obter um exemplo desse comportamento, considere quando o VIM é iniciado no Bash. O VIM usa toda a tela para editar o arquivo, e retornar ao Bash deixa o buffer original inalterado.

Sequência Descrição Comportamento
ESC [ ? 1 0 4 9 h Usar o buffer de tela alternativo Alterna para um novo buffer de tela alternativo.
ESC [ ? 1 0 4 9 l Usar o buffer de tela principal Alterna para o buffer principal.

Largura da janela

As sequências a seguir podem ser usadas para controlar a largura da janela do console. Elas são aproximadamente equivalentes à chamada da API de console SetConsoleScreenBufferInfoEx para definir a largura da janela.

Sequência Código Descrição Comportamento
ESC [ ? 3 h DECCOLM Definir número de colunas como 132 Define a largura do console como 132 colunas de largura.
ESC [ ? 3 l DECCOLM Definir número de colunas como 80 Define a largura do console como 80 colunas de largura.

Redefinição reversível

A sequência a seguir pode ser usada para redefinir determinadas propriedades para os valores padrão. As seguintes propriedades são redefinidas para os seguintes valores padrão (as sequências que controlam essas propriedades também são listadas):

  • Visibilidade do cursor: visível (DECTEM)
  • Teclado numérico: Modo numérico (DECNKM)
  • Modo de teclas de cursor: Modo normal (DECCKM)
  • Margens superior e inferior: superior = 1, inferior = altura do console (DECSTBM)
  • Conjunto de caracteres: ASCII dos EUA
  • Representação gráfica: padrão/desativada (SGR)
  • Salvar estado do cursor: posição inicial (0,0) (DECSC)
Sequência Código Descrição Comportamento
ESC [ ! p DECSTR Redefinição reversível Redefina determinadas configurações de terminal para os padrões.

Sequências de entrada

As sequências de terminal a seguir serão emitidas pelo host do console no fluxo de entrada se o sinalizador ENABLE_VIRTUAL_TERMINAL_INPUT estiver definido no identificador do buffer de entrada usando o sinalizador SetConsoleMode.

Há dois modos internos que controlam quais sequências são emitidas para as chaves de entrada determinadas, o Modo de Teclas do Cursor e o Modo de Teclas do Teclado. Eles são descritos na seção Alterações do modo.

Teclas do cursor

Chave Modo normal Modo de aplicativo
Seta para cima ESC [ A ESC O A
Seta para Baixo ESC [ B ESC O B
Seta para a Direita ESC [ C ESC O C
Seta para a Esquerda ESC [ D ESC O D
Página Inicial ESC [ H ESC O H
Fim ESC [ F ESC O F

Além disso, se Ctrl for pressionado com qualquer uma dessas teclas, as seguintes sequências serão emitidas, independentemente do Modo de Teclas do Cursor:

Chave Qualquer modo
Ctrl + Seta para cima ESC [ 1 ; 5 A
Ctrl + Seta para baixo ESC [ 1 ; 5 B
Ctrl + Seta para a direita ESC [ 1 ; 5 C
Ctrl + Seta para a esquerda ESC [ 1 ; 5 D

Teclas de função e teclado numérico

Chave Sequência
Backspace 0x7f (DEL)
Pausar 0x1a (SUB)
Escape 0x1b (ESC)
Insert ESC [ 2 ~
Excluir 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 ~

Modificadores

Alt é tratado prefixando a sequência com um escape: ESC <c> onde <c> é o caractere passado pelo sistema operacional. Alt + Ctrl é tratado da mesma forma, exceto pelo fato que o sistema operacional terá deslocado previamente a tecla <c> para o caractere de controle apropriado que será retransmitido para o aplicativo.

O Ctrl geralmente é passado exatamente como ele é recebido do sistema. Normalmente, há um caractere deslocado para baixo no espaço reservado do caractere de controle (0x0-0x1f). Por exemplo, Ctrl+@ (0x40) torna-se NULO (0x00), Ctrl+[ (0x5b) torna-se ESC (0x1b), etc. Algumas combinações de teclas Ctrl são tratadas de modo especial de acordo com a tabela a seguir:

Chave Sequência
Ctrl+Espaço 0x00 (NUL)
Ctrl + Seta para cima ESC [ 1 ; 5 A
Ctrl + Seta para baixo ESC [ 1 ; 5 B
Ctrl + Seta para a direita ESC [ 1 ; 5 C
Ctrl + Seta para a esquerda ESC [ 1 ; 5 D

Observação

Ctrl à esquerda + Alt à direita é tratado como AltGr. Quando ambos estiverem juntos, eles serão removidos e o valor Unicode do caractere apresentado pelo sistema será passado para o destino. O sistema converterá previamente os valores de AltGr de acordo com as configurações de entrada do sistema atual.

Exemplos

Exemplo de sequências de terminais de SGR

O código a seguir fornece vários exemplos de formatação de texto.

#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;
}

Observação

No exemplo anterior, a cadeia de caracteres '\x1b[31m' é a implementação de ESC [ <n> m com <n> igual a 31.

O gráfico a seguir mostra a saída do exemplo de código anterior.

output of the console using the sgr command

Exemplo de habilitação do processamento de terminal virtual

O código a seguir fornece um exemplo da maneira recomendada para habilitar o processamento de terminal virtual para um aplicativo. A intenção do exemplo é demonstrar:

  1. O modo existente sempre deve ser recuperado por meio do GetConsoleMode e analisado antes de ser definido com SetConsoleMode.

  2. Verificar se SetConsoleMode retornar 0 e se GetLastError retornar ERROR_INVALID_PARAMETER é o mecanismo atual para determinar quando executar um sistema de nível inferior. Um aplicativo que recebe ERROR_INVALID_PARAMETER com um dos novos sinalizadores de modo de console no campo de bits deve degradar o comportamento normalmente e tentar de novo.

#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;
}

Exemplo de recursos selecionados de atualização de aniversário

O exemplo a seguir destina-se a ser um exemplo mais robusto de código usando uma variedade de sequências de escape para manipular o buffer, com ênfase nos recursos adicionados na Atualização de Aniversário do Windows 10.

Este exemplo usa o buffer de tela alternativo, manipulando paradas de tabulação, definindo margens de rolagem e alterando o conjunto de caracteres.

// 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");

}