向某些屏幕位置写入宽字符时,ncurses 会崩溃
ncurses freaks out when writing wide character to certain screen locations
我正在使用 ncurses 编写应用程序并希望在其中使用方框绘图字符,特别是 u/2550 和 u/2551(截至目前)。我有循环设置,根据我在其他地方确定的屏幕尺寸,在终端的两侧绘制条形图。
无论出于何种原因,当涉及到水平绘制任何 unicode 字符时(此处位于屏幕底部,但它在任何行上都这样做),它会从正常打印字符变成打印垃圾“P”。这有点难以解释,所以我有一些图片显示当我绘制 6 个字符然后绘制 7 个或更多字符时会发生什么。
负责绘制这些字符的代码部分是这样的,请注意最后一个 for 循环是绘制这些字符的部分,迭代器应该比 7 更远,但它在这里和任何地方都这样做否则。
void drawBorder(){ //draw the border graphics
attron(COLOR_PAIR(3));
for(int i = 1; i < screenSizeY - 1; i++){ //draw left side
mvaddwstr(i, 0, L"║");
}
for(int i = 1; i < screenSizeY - 1; i++){ //draw right side
mvaddwstr(i, screenSizeX - 1, L"\u2551");
}
for(int i = 0; i < 7; i++){ //draw bottom
mvaddwstr(screenSizeY - 1, i, L"\u2550");
}
attroff(COLOR_PAIR(3));
}
我正在链接到 ncursesw 包并正确设置了语言环境。其他用竖线画的字符也能正常工作,但这里不行。我在 Alacritty 终端会话中使用用 g++ 编译的 C++,运行 on Linux。
这与画框功能或特定终端功能无关,终端完美支持所有宽字符,并在终端的其他部分工作。这将根据我在一行中绘制的这些字符的数量而发生,其他方框字符也会发生这种情况。
OP发了一个更完整的例子,说明了问题所在:
#include <ncurses.h>
#include <string>
#include <iostream>
using namespace std;
int main(){
initscr();
setlocale(LC_ALL, "");
raw();
keypad(stdscr, TRUE);
noecho();
for(int i = 0; i < 10; i++){
mvaddwstr(0, i, L"\u2550");
}
for(int i = 0; i < 6; i++){
mvaddwstr(1, i, L"\u2550");
}
refresh();
getch();
endwin();
return 0;
}
问题是库初始化时使用的语言环境与 mvaddwstr
调用中使用的语言环境不同。 manual page 表示
The library uses the locale which the calling program has initialized.
That is normally done with setlocale
:
setlocale(LC_ALL, "");
If the locale is not initialized, the library assumes that characters
are printable as in ISO-8859-1, to work with certain legacy programs.
You should initialize the locale and not rely on specific details of
the library when the locale has not been setup.
因为调用setlocale
是在initscr
之后,而不是之前,ncurses假设数据是 ISO-8859-1,并遇到了意想不到的情况。在其他地方,例如 addwstr
,ncurses 检查数据是否有效 wchar_t
,但在那些地方,它使用的是 current 语言环境。在这种情况下,它远离它知道必须以这种方式处理的功能(它正在渲染已经处理过的数据)。允许使用 repeat_char
功能处理的库中的比较可以改进,但实际错误在示例程序中。
我正在使用 ncurses 编写应用程序并希望在其中使用方框绘图字符,特别是 u/2550 和 u/2551(截至目前)。我有循环设置,根据我在其他地方确定的屏幕尺寸,在终端的两侧绘制条形图。
无论出于何种原因,当涉及到水平绘制任何 unicode 字符时(此处位于屏幕底部,但它在任何行上都这样做),它会从正常打印字符变成打印垃圾“P”。这有点难以解释,所以我有一些图片显示当我绘制 6 个字符然后绘制 7 个或更多字符时会发生什么。
负责绘制这些字符的代码部分是这样的,请注意最后一个 for 循环是绘制这些字符的部分,迭代器应该比 7 更远,但它在这里和任何地方都这样做否则。
void drawBorder(){ //draw the border graphics
attron(COLOR_PAIR(3));
for(int i = 1; i < screenSizeY - 1; i++){ //draw left side
mvaddwstr(i, 0, L"║");
}
for(int i = 1; i < screenSizeY - 1; i++){ //draw right side
mvaddwstr(i, screenSizeX - 1, L"\u2551");
}
for(int i = 0; i < 7; i++){ //draw bottom
mvaddwstr(screenSizeY - 1, i, L"\u2550");
}
attroff(COLOR_PAIR(3));
}
我正在链接到 ncursesw 包并正确设置了语言环境。其他用竖线画的字符也能正常工作,但这里不行。我在 Alacritty 终端会话中使用用 g++ 编译的 C++,运行 on Linux。
这与画框功能或特定终端功能无关,终端完美支持所有宽字符,并在终端的其他部分工作。这将根据我在一行中绘制的这些字符的数量而发生,其他方框字符也会发生这种情况。
OP发了一个更完整的例子,说明了问题所在:
#include <ncurses.h>
#include <string>
#include <iostream>
using namespace std;
int main(){
initscr();
setlocale(LC_ALL, "");
raw();
keypad(stdscr, TRUE);
noecho();
for(int i = 0; i < 10; i++){
mvaddwstr(0, i, L"\u2550");
}
for(int i = 0; i < 6; i++){
mvaddwstr(1, i, L"\u2550");
}
refresh();
getch();
endwin();
return 0;
}
问题是库初始化时使用的语言环境与 mvaddwstr
调用中使用的语言环境不同。 manual page 表示
The library uses the locale which the calling program has initialized. That is normally done with
setlocale
:
setlocale(LC_ALL, "");
If the locale is not initialized, the library assumes that characters are printable as in ISO-8859-1, to work with certain legacy programs. You should initialize the locale and not rely on specific details of the library when the locale has not been setup.
因为调用setlocale
是在initscr
之后,而不是之前,ncurses假设数据是 ISO-8859-1,并遇到了意想不到的情况。在其他地方,例如 addwstr
,ncurses 检查数据是否有效 wchar_t
,但在那些地方,它使用的是 current 语言环境。在这种情况下,它远离它知道必须以这种方式处理的功能(它正在渲染已经处理过的数据)。允许使用 repeat_char
功能处理的库中的比较可以改进,但实际错误在示例程序中。