我可以确定终端是否解释C1控制代码?

时间:2010-09-24 13:58:44

标签: unix ncurses gnu-screen vt100 termcap

ISO / IEC 2022定义the C0 and C1 control codes。 C0集是ASCII,ISO-8859-1和UTF-8中0x000x1f之间熟悉的代码(例如 ESC CR LF )。

某些VT100终端仿真器(例如screen(1),PuTTY)也支持C1集。这些是0x800x9f之间的值(例如,0x84将光标向下移动一行)。

我正在显示用户提供的输入。我不希望用户输入能够改变终端状态(例如移动光标)。我目前正在过滤出C0集中的字符代码;但是,如果终端将它们解释为控制代码,我想有条件地过滤出C1集。

有没有办法从termcap等数据库中获取此信息?

4 个答案:

答案 0 :(得分:2)

我能想到的唯一方法就是使用C1请求并测试返回值:

$ echo `echo -en "\x9bc"`
^[[?1;2c
$ echo `echo -e "\x9b5n"`
^[[0n
$ echo `echo -e "\x9b6n"`
^[[39;1R
$ echo `echo -e "\x9b0x" `
^[[2;1;1;112;112;1;0x

以上是:

CSI c      Primary DA; request Device Attributes
CSI 5 n    DSR; Device Status Report
CSI 6 n    CPR; Cursor Position Report
CSI 0 x    DECREQTPARM; Request Terminal Parameters

ESR维护的terminfo / termcap(link)在用户字符串7和9中有几个请求(user7 / u7,user9 / u9):

# INTERPRETATION OF USER CAPABILITIES
#
# The System V Release 4 and XPG4 terminfo format defines ten string
# capabilities for use by applications, ....   In this file, we use
# certain of these capabilities to describe functions which are not covered
# by terminfo.  The mapping is as follows:
#
#       u9      terminal enquire string (equiv. to ANSI/ECMA-48 DA)
#       u8      terminal answerback description
#       u7      cursor position request (equiv. to VT100/ANSI/ECMA-48 DSR 6)
#       u6      cursor position report (equiv. to ANSI/ECMA-48 CPR)
#
# The terminal enquire string  should elicit an answerback response
# from the terminal.  Common values for  will be ^E (on older ASCII
# terminals) or \E[c (on newer VT100/ANSI/ECMA-48-compatible terminals).
#
# The cursor position request () string should elicit a cursor position
# report.  A typical value (for VT100 terminals) is \E[6n.
#
# The terminal answerback description (u8) must consist of an expected
# answerback string.  The string may contain the following scanf(3)-like
# escapes:
#
#       %c      Accept any character
#       %[...]  Accept any number of characters in the given set
#
# The cursor position report () string must contain two scanf(3)-style
# %d format elements.  The first of these must correspond to the Y coordinate
# and the second to the %d.  If the string contains the sequence %i, it is
# taken as an instruction to decrement each value after reading it (this is
# the inverse sense from the cup string).  The typical CPR value is
# \E[%i%d;%dR (on VT100/ANSI/ECMA-48-compatible terminals).
#
# These capabilities are used by tac(1m), the terminfo action checker
# (distributed with ncurses 5.0).

示例:

$ echo `tput u7`
^[[39;1R
$ echo `tput u9`
^[[?1;2c

当然,如果您只想防止显示损坏,可以使用less方法,让用户在显示/不显示控制字符之间切换(less中的-r和-R选项)。此外,如果您知道输出字符集,则ISO-8859字符集会为控制代码保留C1范围(因此它们在该范围内没有可打印的字符)。

答案 1 :(得分:1)

实际上,PuTTY似乎不支持C1控件。

测试此功能的常用方法是使用vttest,它提供用于分别更改输入和输出的菜单项,以使用8位控件。 PuTTY未对每个菜单条目进行完整性检查,如果禁用该检查,结果将确认PuTTY不遵守这些控件。

答案 2 :(得分:0)

100%自动完成它充其量是挑战。许多(如果不是大多数)Unix接口都是智能的(xterms和诸如此类),但实际上你并不知道是否连接到ASR33或运行MSDOS的PC。

enter image description here

如果没有回复,您可以尝试一些终端询问转义序列并超时。但是,您可能不得不退回并可能询问用户他们正在使用哪种终端。

答案 3 :(得分:-1)

我认为没有一种简单的方法可以查询终端是否支持它们。您可以尝试令人讨厌的hacky变通方法(比如打印它们然后查询光标位置)但我真的不建议沿着这些方向做任何事情。

我认为您可以无条件地过滤掉这些C1代码。无论如何,Unicode声明U + 0080 .. U + 009F范围作为控制字符,我认为你不应该将它们用于任何不同的东西。

(注意:您使用示例TimingGPU.cuh将光标向下移动。实际上0x84编码的是终端使用的编码,例如U+0084用于UTF-8。)