终端窗口大小和 termcap
程序员文章站
2022-07-01 09:17:42
...
多数 UNIX 系统都提供了一种跟踪当前终端窗口大小的方法。在窗口大小发生变化时,内核就会通知前台进程组。内核为每个终端和伪终端都维护了一个如下的 winsize 结构。
此结构的规则如下:
1、用 ioctl 函数(见终端I/O函数 ioctl一节)的 TIOCGWINSZ 命令可以取此结构的当前值。
2、用 ioctl 的 TIOCSWINSZ 命令可以将此结构的新值存储到内核中。如果此新值与存储在内核中的当前值不同,则将向前台进程组发送 SIGWINCH 信号(默认会被忽略)。
3、除了存储此结构的当前值以及在此值改变时产生一个信号以外,内核对该结构不进行任何其他操作。对结构中的值进行解释是应用程序的工作。
提供这种功能的目的是,当窗口大小发生变化时应用程序能得到通知(如 vi 编辑器)。应用程序接收到此信号后,可以获取窗口大小的新值,然后重绘屏幕。
下面这个程序会打印当前窗口大小,然后休眠。之后每次窗口大小改变时,程序就捕捉 SIGWINCH 信号,然后打印新的窗口大小。
termcap 的意思是终端能力(terminal capability),它涉及文本文件 /etc/termcap 和一套读此文件的例程,主要是为了支持 vi 编辑器而开发的。termcap 文件包含了对各种终端的说明:终端支持哪些功能(如行数、列数、是否支持退格)、如何使终端执行某些操作(如清屏、移动光标到指定位置)等。把这些信息从编译过的程序中取出来并把它们放在易于编辑的文本文件中,这样就使得 vi 编辑器能在很多不同的终端上运行。最后,将支持 termcap 文件的例程从 vi 编辑器中抽取出来,放在一个单独的 curses 库中。为使这套库可供要进行屏幕处理的任何程序使用,还增加了很多功能。
不过 termcap 这种技术并不是很完善。因为当越来越多的终端被加到数据文件中时,为找到一个特定的终端,可能需要花费很长的时间扫描此数据文件。另外,该数据文件还用两个字符的名字来标识不同的终端属性。因此出现了 terminfo 以及与其相关的 curses 库。在 terminfo 中,终端说明基本上都是文本说明的编译版本,在运行时易于被快速定位。
但不论是 termcap 还是 terminfo,它们本身都只提供在各种终端上执行典型操作(如清屏、移动光标等)的方法,而不处理如更改终端模式、更改终端特殊字符、处理窗口大小等问题。不过 curses 库能提供某种具体细节方面的帮助。它提供了很多函数,用来设置原始模式、设置 cbreak 模式、打开和关闭回显等。注意,curses 库是为基于字符的哑终端设计的,它们如今大部分已被基于像素的图像终端所代替。
struct winsize{ unsigned short ws_row; // rows, in characters unsigned short ws_col; // columns, in characters unsigned short ws_xpixel; // horizontal size, pixels (unused) unsigned short ws_ypixel; // vertical size, pixels (unused) };
此结构的规则如下:
1、用 ioctl 函数(见终端I/O函数 ioctl一节)的 TIOCGWINSZ 命令可以取此结构的当前值。
2、用 ioctl 的 TIOCSWINSZ 命令可以将此结构的新值存储到内核中。如果此新值与存储在内核中的当前值不同,则将向前台进程组发送 SIGWINCH 信号(默认会被忽略)。
3、除了存储此结构的当前值以及在此值改变时产生一个信号以外,内核对该结构不进行任何其他操作。对结构中的值进行解释是应用程序的工作。
提供这种功能的目的是,当窗口大小发生变化时应用程序能得到通知(如 vi 编辑器)。应用程序接收到此信号后,可以获取窗口大小的新值,然后重绘屏幕。
下面这个程序会打印当前窗口大小,然后休眠。之后每次窗口大小改变时,程序就捕捉 SIGWINCH 信号,然后打印新的窗口大小。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #ifndef TIOCGWINSZ #include <sys/ioctl.h> #endif static void pr_winsize(int fd){ struct winsize size; if(ioctl(fd, TIOCGWINSZ, (char *)&size) < 0){ printf("TIOCGWINSZ error\n"); exit(1); } printf("%d rows, %d columns\n", size.ws_row, size.ws_col); } static void sig_winch(int signo){ printf("SIGWINCH received\n"); pr_winsize(STDIN_FILENO); } int main(void){ if(isatty(STDIN_FILENO) == 0) exit(1); if(signal(SIGWINCH, sig_winch) == SIG_ERR){ printf("signal error\n"); exit(1); } pr_winsize(STDIN_FILENO); // print initial size for(;;) // and sleep forever pause(); }
termcap 的意思是终端能力(terminal capability),它涉及文本文件 /etc/termcap 和一套读此文件的例程,主要是为了支持 vi 编辑器而开发的。termcap 文件包含了对各种终端的说明:终端支持哪些功能(如行数、列数、是否支持退格)、如何使终端执行某些操作(如清屏、移动光标到指定位置)等。把这些信息从编译过的程序中取出来并把它们放在易于编辑的文本文件中,这样就使得 vi 编辑器能在很多不同的终端上运行。最后,将支持 termcap 文件的例程从 vi 编辑器中抽取出来,放在一个单独的 curses 库中。为使这套库可供要进行屏幕处理的任何程序使用,还增加了很多功能。
不过 termcap 这种技术并不是很完善。因为当越来越多的终端被加到数据文件中时,为找到一个特定的终端,可能需要花费很长的时间扫描此数据文件。另外,该数据文件还用两个字符的名字来标识不同的终端属性。因此出现了 terminfo 以及与其相关的 curses 库。在 terminfo 中,终端说明基本上都是文本说明的编译版本,在运行时易于被快速定位。
但不论是 termcap 还是 terminfo,它们本身都只提供在各种终端上执行典型操作(如清屏、移动光标等)的方法,而不处理如更改终端模式、更改终端特殊字符、处理窗口大小等问题。不过 curses 库能提供某种具体细节方面的帮助。它提供了很多函数,用来设置原始模式、设置 cbreak 模式、打开和关闭回显等。注意,curses 库是为基于字符的哑终端设计的,它们如今大部分已被基于像素的图像终端所代替。
上一篇: Python TIPs
下一篇:
jstl最常用的标签之
推荐阅读
-
vBulletin HACK----显示话题大小和打开新窗口于论坛索引页
-
修改wicket modal窗口的大小和位置 wicketAjaxApache.netHTML
-
检测窗口大小显示和隐藏内容
-
终端窗口大小和 termcap
-
vBulletin HACK----显示话题大小和打开新窗口于论坛索引页_php基础
-
vBulletin HACK----显示话题大小和打开新窗口于论坛索引页_PHP教程
-
vBulletin HACK----显示话题大小和打开新窗口于论坛索引页
-
Vim设置默认字体、窗口大小和配色方案
-
bulletin vBulletin HACK----显示话题大小和打开新窗口于论坛索引页
-
浏览器窗口加载和大小改变事件示例_javascript技巧