我目前正在尝试使用基本的 TUI 创建一个 ada 程序(这将在稍后相关)。 为此,我使用 ncurses,更具体地说,我与 C 交互,因为 ada 绑定 ncursesada 对我不起作用 [1]。
我想做的是一个基本的 ncurses 菜单。这是一个简单的菜单,包含三个选项,其中两个选项允许用户输入一个句子,然后我在主程序中使用该句子。由于我的输入句子是法语,我搜索了如何添加对宽字符的支持,并偶然发现了this post,这使我在配置文件中添加了一些编译器/链接器标志。就我而言,他们是:
编译器:-I/usr/include/ncursesw -D_DEFAULT_SOURCE -D_XOPEN_SOURCE_EXTENDED=600
链接器:-Wl,-Bsymbolic-functions -lncursesw -ltinfo
另外,我在
setlocale (LC_ALL, "")
之前添加了 initsrc
,并将相关宏 NCURSES_WIDECHAR
重新定义为 1,我知道我应该这样做。
有了这一切,我现在可以毫无问题地获得宽字符,但是,我的主菜单现在被破坏了。事实上,它不是显示完整选项,而是看起来有点被删减。
在寻找解决方案时,我告诉自己也许问题出在 setlocale 函数上;这似乎不是问题。我还查看了这篇文章,其中描述了与 unicode 相关的 ncurses 的八个问题。我应该擅长八点[2]。在最后的努力中,我尝试删除编译器和链接器标志,并在适用的情况下从 wint_t(*) 回滚到 char(*)。令我惊讶的是,这解决了问题。 所以现在我陷入了僵局。我想使用 ncursesw 来访问宽字符,但如果我这样做,我的菜单似乎会损坏。我能做什么来解决这个问题? 我考虑过使用 ncurses 的替代品,但是:
快速搜索后,我在 C 中没有找到任何其他内容
[1] 使用alire命令安装,但是编译时,它抱怨一些libraires不存在。
[2] 也许不是第四点,它说“非常非常小心,不要使用实际上没有宽字符函数的库版本。”,但我没有找到如何使用带有 ncursesw 的菜单(我尝试导入
但它似乎没有做任何事情)。
这样,我获得了
这个菜单gcc ncurses_external.c -I/usr/include/ncursesw -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -o main -lmenu -Wl,-Bsymbolic-functions -lncursesw -ltinfo
ncurses_external.h
#include <ncurses.h>
#include <menu.h>
#define INVISIBLE 0
#define VISIBLE 1
#define ENTER_CODE 10
#define SENTENCE 0
#define FILE_STR 1
char* Choices[] = {
"Traduire (FR->NO)",
"Traduire (NO->FR)",
"Quitter"
};
int InitScr_Wrp ();
void Refresh_Wrp ();
void Colored_Line (char Line[], short Color, int y);
int Menu (int y);
wint_t* Get (int type, int y);
// the wint_t errors (underlined in an IDE) are IDE's specific error. Program
// compile.
int main (int argc, char *argv[]);
void EndScr_Wrp ();
// private in regards to Ada
ITEM** Allocate_List (int N, char* choices[]);
void Free (int N, ITEM** List, MENU* menu);
ncurses_external.c
#include "ncurses_external.h"
#include <ncursesw/ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#define NCURSES_WIDECHAR 1
int InitScr_Wrp () {
setlocale (LC_ALL, "");
initscr ();
if (has_colors () == FALSE) {
endwin ();
return -1;
}
curs_set (INVISIBLE);
cbreak ();
noecho ();
start_color ();
keypad (stdscr, TRUE);
return 0;
}
void Refresh_Wrp () {
refresh ();
}
void Colored_Line (char Line[], short Color, int y) {
init_pair (y, Color, COLOR_BLACK);
attron (COLOR_PAIR (y));
mvwprintw (stdscr, y - 1, 0, "%s", Line);
attroff (COLOR_PAIR (y));
}
ITEM** Allocate_List (int N, char* choices[]) {
ITEM** List;
List = (ITEM**)calloc (N + 1, sizeof (ITEM*));
for (int i = 0; i < N; ++i) {
List[i] = new_item (choices[i], "");
}
return List;
}
void Free (int N, ITEM** List, MENU* menu) {
unpost_menu (menu);
free_menu (menu);
for (int i = 0; i < N; i++) {
free_item (List[i]);
}
}
int Menu (int y) {
ITEM** Item_List;
WINDOW* menu_win;
MENU* Option_Menu;
menu_win = newwin (16, 50, y, 0);
keypad (menu_win, TRUE);
int N = sizeof (Choices) / sizeof (Choices[0]);
Item_List = Allocate_List (N, Choices);
Option_Menu = new_menu (Item_List);
set_menu_win (Option_Menu, menu_win);
set_menu_sub (Option_Menu, menu_win);
post_menu (Option_Menu);
wrefresh (menu_win);
int character;
int Choosen_Option = 0;
menu_driver (Option_Menu, REQ_FIRST_ITEM);
do {
character = wgetch (menu_win);
switch (character) {
case KEY_UP:
Choosen_Option = Choosen_Option > 0 ? Choosen_Option - 1 : 0;
menu_driver (Option_Menu, REQ_UP_ITEM);
break;
case KEY_DOWN:
Choosen_Option = Choosen_Option < N ? Choosen_Option + 1 : N;
menu_driver (Option_Menu, REQ_DOWN_ITEM);
break;
}
} while (character != ENTER_CODE);
Free (N, Item_List, Option_Menu);
wclear (menu_win);
wrefresh (menu_win);
delwin (menu_win);
return Choosen_Option;
}
wint_t* Get (int type, int y) {
if (type == SENTENCE) {
mvwprintw (stdscr, y, 0, "Entrer une phrase à traduire :");
}
else {
mvwprintw (stdscr, y, 0, "Entrer un fichier à décoder :");
}
mvwprintw (stdscr, y + 1, 0, "> ");
wrefresh (stdscr);
curs_set (VISIBLE);
echo ();
wint_t* response = NULL;
size_t N = 0;
size_t curr_end_size = 255;
size_t Block = 16;
response = (wint_t*)realloc (NULL, sizeof (*response) * curr_end_size);
if (!response) return response;
wint_t character;
do {
get_wch (&character);
response[N] = character;
N++;
if (N == curr_end_size) {
curr_end_size += Block;
response = (wint_t*)realloc (response, sizeof (*response) * curr_end_size);
if (!response) return response;
}
} while (character != ENTER_CODE);
return response;
}
void EndScr_Wrp () {
endwin ();
}
int main (int argc, char *argv[]) {
int y1 = 10;
int option;
InitScr_Wrp ();
option = Menu (y1);
switch (option) {
case (SENTENCE):
Get (SENTENCE, y1);
break;
case (FILE_STR):
Get (FILE_STR, y1);
break;
}
EndScr_Wrp ();
}
-lmenuw
而不是
-lmenu
。