将矩形打印到终端

Print rectangles to terminal

我正在尝试为 Linux 编写一个看起来像 MS-DOS EDIT 的文本编辑器。

但是,我被卡住了,因为我不知道如何在编辑器屏幕和对话框周围绘制细矩形。我知道 Linux dialog 命令可以做类似的事情:

如何在屏幕周围绘制矩形(最好没有 curses)?

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃These are box-drawing characters.      ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│They live in the U+2500-U+257F range of│
│Unicode characters.                    │
└───────────────────────────────────────┘

░▒▓▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜▓▒░
░▒▓▌ The shadows are block elements, ▐▓▒░
░▒▓▌ Unicode U+2580-U+259F.          ▐▓▒░
░▒▓▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟▓▒░

曾几何时,box-drawing characters and block elements and were common in CP-437. Modern terminals likely expect UTF-8. (They don't work very well in web browsers... see here 如果上面的文字看起来很奇怪。)

还有ANSI escapes设置终端显示文本的背景色、前景色等属性。不过,我无法在 Stack Overflow 上很好地展示它。

您所描述的是使用存在于各种扩展字符集中的 box drawing characters。可用字符至少取决于平台和终端仿真。

鉴于您的问题带有 Linux 标记,最简单的方法是使用 ncurses 库。为什么您不想使用它而不得不重新发明那个轮子?

如果你能期待至少 VT100 仿真(合理)那么你可以使用基本的线条画,但更高级别有更多字符。

它有点旧,但请查看此处的 window 示例代码:

您可能还想查看 Xterm 转义字符(扩展 VT100 集):

ncurses 库是做你想做的事的好方法,尽管你说你想要替代品。您可以将 Unicode 方框绘图字符用作宽字符。它们包括 MS-DOS 代码页 437 中的所有字符。

现代发行版应该设置为默认支持 UTF-8,所以这应该可行。 (我建议将源文件保存为带有字节顺序标记的UTF-8。)

#define _XOPEN_SOURCE 700

#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>

int main(void)
{
  setlocale( LC_ALL, "" );
  fputws( L"╒╩╤╣\n", stdout );

  return EXIT_SUCCESS;
}

没有 curses,您可以检查环境变量 LINESCOLS 来获取终端的尺寸。在 Linux 控制台上打印颜色等的控制字符在 console_codes(4) man 页面中(并且是 VT102 控制代码的变体,它是 VT100 的超集,超集ANSI 标准终端)。如果您想从 gnome_terminal 等程序中调用它,也请查看其文档,但它可能会实现 xterm 的扩展,它是 VT102 的扩展等。一个非常有用的是表单feed character '\L' 将清除屏幕并让您重绘它。您也可以使用 terminfo 或 termcap 来获得更抽象和通用的界面,但实际上,除了 VT100 和 ANSI 颜色的扩展之外,没有人会再使用任何东西。

确保您的终端字体包含您要使用的画线字符! DejaVu Sans Mono 是一种出色的等宽字体,尤其是它对 Unicode 的覆盖。此外,您可以使用 locale 命令检查您的区域设置是否正确;您看到的语言环境名称应该以 .utf8UTF-8.

之类的结尾

您正在寻找 box-drawing characters。这是完整的 table.

假设你的系统安装了 Unicode 字体,大多数现代发行版都安装了,你可以像这样将它们打印到你的终端:

#include <wchar.h>
#include <locale.h>
...
    setlocale(LC_ALL,"en_US.UTF-8");
    wprintf(L"\u250C\u2500\u2510\n");    // ┏━┓
    wprintf(L"\u2502 \u2502\n");         // │   │
    wprintf(L"\u2514\u2500\u2518\n");    // └━─┘