在尝试使用ncurses进行一些工作时,我已经到了需要使用宽字符、框绘制以及其他内容的地步,而且我正处于一种每个平铺控件都很有用的情况下。
但是,当尝试使用以下代码时,我遇到了麻烦:
#define _XOPEN_SOURCE_EXTENDED
#include <locale.h>
#include <curses.h>
#include <stdlib.h>
#include <time.h>
#define ESC 27
int main() {
setlocale(LC_CTYPE, "");
initscr();
keypad(initscr(),1);
curs_set(9);
nonl();
cchar_t special;
setcchar(&special, L"æ", 0, COLOR_PAIR(0), NULL);
cchar_t speshul;
setcchar(&speshul, L"朝", 0, COLOR_PAIR(0), NULL);
int c=0;
do {
clear();
mvadd_wch(3,6, &special);
mvadd_wch(4,6,&speshul);
refresh();
} while ((ESC!=(c=getch())));
endwin();
}
编辑:
更新了代码以使用
setcchar
;结果令人沮丧:?
只有一个问号
special
应该在哪里,而speshul
不应该在哪里。两个角色都没有按预期出现。
问题在哪里,我该如何解决?
编辑:一些额外的信息回应皮特:
预期的结果是打印字符“æ”,并在其下面,朝。我在Mac OS X上使用Terminal.app;我正在编译它Xcode。
最佳答案
你的代码中还有很多其他的“问题”,其中一些可能与你的宽字符问题有关:
initscr();
keypad(initscr(),1);
避免无缘无故地呼叫两次
initscr()
。要么将第一个调用的结果存储在一个WINDOW
指针中,要么简单地使用内置的stdscr
同时避免使用数值常量来表示bool
值,最好使用命名常量TRUE
和FALSE
语义是完全不同的。所以使用:
WINDOW *screen = initscr();
keypad(screen, TRUE);
或
initscr();
keypad(stdscr, TRUE);
curs_set(9);
9
不是curs_set()
的有效参数。在手册中:“curs_set例程将光标状态设置为invisible、normal或very visible,可见性分别为0、1或2”setcchar(&special, L"æ", 0, COLOR_PAIR(0), NULL);
setcchar()
的第四个参数是short color_pair
它需要一个颜色对编号,而不是它的属性掩码(它应该应用于chtype
)。我同意,这是一个很糟糕的记录使用COLOR_PAIR()
仅适用于对0对于任意对,例如pair4
,使用:setcchar(&special, L"æ", WA_NORMAL, 4, NULL);
也可以使用
WA_NORMAL
而不是0
。不要依赖常量值,使用命名的值!while ((ESC!=(c=getch())))
您还应该测试
ERR
返回不要假设c
将始终包含有效的字符代码:while ((c=getch()) != ERR && c != ESC)
此外,如果您真的想使用
ESC
作为角色来打破循环,您应该阅读关于ESCDELAY
的内容默认情况下,在用户按下ESC键和该键可供程序使用之间需要一整秒钟的时间简单地说,原因是ESC还用于启动转义序列,因此在确定ESC是单独按键之前,光标必须等待查看它是否后跟其他控制字符所以你不能避免一个延迟,但是你可以把它减少到一个不易察觉的时间,比如说100毫秒。这必须在初始化诅咒之前设置!setenv("ESCDELAY", 100, FALSE);
在宽字符世界中使用
getch()
时要小心对于一个简单的“循环到ESC”这是可以的,但当您想真正解析用户输入时,请用get_wch()
替换它。最后,不需要将locale设置为
"en_US.UTF-8"
,因为这将覆盖用户的locale如果您的终端被设置为UTF-8
以外的字符编码,或者您的语言不是en_US
,该怎么办?只需将程序设置为使用用户环境中设置的任何语言环境:setlocale(LC_ALL, "");
这与完全不设置语言环境非常不同,因为默认情况下,语言C假定语言环境是
C
,即仅7位ASCII字符诅咒就是荣耀。