curses 如何保留屏幕内容?

How curses preserves screen contents?

当您启动 (n)curses 程序时,它会从您的终端仿真器中移除滚动条,清除屏幕,滚动日志(历史记录)也会消失。退出程序时,屏幕内容重新出现,滚动条returns,滚动缓冲区returns。

ncurses是怎么做到的?我研究了所有 ANSI 转义码,我看不出有什么可以做这样的事情。这背后的技术是什么?

这项技术叫做The Alternate Screen Buffer。终端仿真器提供两种模式:主要模式和备用模式。备用屏幕缓冲区没有回滚,当您在这些缓冲区之间切换时,它们中的内容将被保留。要在它们之间切换,请使用 smcuprmcup ANSI 转义序列。它们的二进制形式是:

$ tput smcup|hexdump -C 
00000000  1b 5b 3f 31 30 34 39 68                           |.[?1049h|

$ tput rmcup|hexdump -C 
00000000  1b 5b 3f 31 30 34 39 6c                           |.[?1049l|

这在 xterm 常见问题解答中有详细讨论 Why doesn't the screen clear when running vi?

ncurses 不会这样做。这是由 终端 完成的,给出 终端描述 中提供的转义序列。

该行为来自 备用屏幕缓冲区,它是在 X10R4(1986 年底)中随 xterm 一起引入的。 xterm 维护两个缓冲区:

  • 普通屏幕缓冲区(您在 VT100 window 中看到的内容)包括回滚区域,以及
  • 备用屏幕缓冲区(不包括回滚区域)

xterm(以及使用此功能的程序,例如 rxvt)识别用于在两个缓冲区之间切换的转义序列。由于传统的 termcap 没有此功能,开发人员使用了 termcap 初始化序列 tite(对应于 terminfo smcuprmcup)。从技术上讲,名称指的是游标寻址模式,但没人关心(很多)。

可以通过在运行时删除 termcap tite 功能(来自 TERMCAP 环境变量)来抑制原始 xterm 的备用屏幕功能,但这种方法不起作用with terminfo,它使用文件。自 1997 年以来,xterm 实现了一组较新的转义序列,这些转义序列可以被 xterm 忽略。一些其他程序允许抑制该功能,但通常情况下,这些程序不允许。