我试图编写一个基本程序,以使用 curs 和 non-spacing character 在C语言中打印ā(带上划线的a)。我已将语言环境设置为en_US.UTF-8,并且能够使用该语言环境打印国际语言字符。此代码仅打印不带上划线的。我也与ncurses得到类似的结果。要在屏幕上显示ā,我还需要做什么?
def _if(v, cond, yes, no = nil)
if cond.call(v)
yes.call(v)
else
no&.call(v)
end
end
cond = lambda { |v| v > 2 }
yes = lambda { |v| v + 1 }
no = lambda { |v| 0 }
_if(1, cond, yes, no)
_if(3, cond, yes, no)
_if(1, cond, yes)
答案 0 :(得分:0)
curses调用需要指向数据的指针,而不仅仅是指针。
可以为宽字符传递以null终止的数组,但是cchar_t
数据的指针需要一些修复。
以下是该程序的修复程序:
> diff -u foo.c.orig foo.c
--- foo.c.orig 2020-05-21 19:50:48.000000000 -0400
+++ foo.c 2020-05-21 19:51:46.799849136 -0400
@@ -3,7 +3,7 @@
#include <wchar.h>
#include <assert.h>
-int main() {
+int main(void) {
setlocale(LC_ALL, "");
initscr();
int s = 0x41; // represents 'a'
@@ -12,11 +12,11 @@
assert(wcwidth(ns) == 0);
wchar_t wstr[] = { s, ns, L'\0'};
- cchar_t *cc;
- int x = setcchar(cc, wstr, 0x00, 0, NULL);
+ cchar_t cc;
+ int x = setcchar(&cc, wstr, 0x00, 0, NULL);
assert(x == 0);
- add_wch(cc);
+ add_wch(&cc);
refresh();
getch();
在xterm上产生带有横线的“ A”:
(对于价值而言, 0x61
为“ a”,而 0x41
为“ A”)。
答案 1 :(得分:0)
除了声明cc
外,您的代码基本上是正确的。不过,建议您隐藏光标;我认为这可以防止您在以下字符位置看到错误绘制的横条。
我修改了您的代码,如下所示:
#include <curses.h>
#include <locale.h>
#include <wchar.h>
#include <assert.h>
int main() {
setlocale(LC_ALL, "");
initscr();
int s = 0x41; // represents 'A'
int ns = 0x0305; // represents COMBINING OVERLINE (a non-spacing character)
assert(wcwidth(ns) == 0);
wchar_t wstr[] = { s, ns, L'\0'};
cchar_t cc; /* Changed *cc to cc */
int x = setcchar(&cc, wstr, 0x00, 0, NULL); /* Changed cc to &cc */
assert(x == 0);
set_curs(0); /* Added to hide the cursor */
add_wch(&cc); /* Changed cc to &cc */
refresh();
getch();
endwin();
return 0;
}
我在kubuntu系统上进行了测试,因为这很方便。生成的程序在xterm(具有丑陋的字体)上可以完美运行,但在konsole上则不能。在konsole上,它在下一个字符位置渲染了横线,这显然是一个渲染错误,因为如果有一个,则横线会出现在下一个字符的顶部。将konsole的字体更改为Liberation Mono后,测试程序运行完美。
渲染错误将不容易被发现,因为它很难复制,尽管从我的实验来看,当字体为DejaVu Sans Mono时,它似乎可以可靠地显示出来。奇怪的是,我的系统设置为使用DejaVu Sans Mono中的非间距字符作为其他字体(如Ubuntu Mono)的替代,当这些字符用作替代时,间距似乎是正确的。但是,Unicode渲染非常复杂,以至于我实际上无法证明替代字符确实来自配置的字体,并且渲染错误似乎来来往往。它可能取决于字体缓存,尽管我也不能证明。
如果我还有更多要做的事情,我将提交错误报告,并且如果我有动力明天再对此进行研究,我可能会发现一些东西。同时,其他人可以提供的任何信息无疑将是有用的。至少应包括操作系统和控制台仿真器,具有准确的版本号,并尝试使用的字体列表以及它们是否成功的指示。
顺便说一下,没有必要使用ncurses来查看此错误。在您的shell中进行测试就足够了:
printf '\u0041\u0305\u000a'
就足够了。我觉得测试很有趣
printf '\u0041\u0305\u0321\u000a'
也是。
我在以下系统上进行过测试:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic
$ konsole --version
konsole 17.12.3
$ # Fonts showing bug
$ otfinfo -v /usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf
Version 2.37
$ # Fonts not showing bug
$ otfinfo -v /usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf
Version 1.07.4
答案 2 :(得分:-2)
这里有多个问题。首先,将setcchar
的结果存储在未初始化的指针cc
的随机存储器中。每当函数使用指针进行输出时,都需要传递要存储结果的对象的地址,而不是未初始化的指针变量。输出必须是足够长的数组,以存储输入中的字符数。我不确定null终止约定是什么,所以为了安全起见,我会使用
cchar_t cc[3];
int x = setcchar(cc, wstr, 0x00, 0, NULL);
然后,add_wch
函数仅需要添加一个字符,并根据它是空格还是非间距字符来替换或追加。因此,您需要为每个字符调用一次。