启用宽字符支持导致ncurses菜单显示异常的解决求助
问题:ncursesw宽字符模式下菜单显示截断,需同时支持宽字符输入与正常菜单显示
背景
开发带基础TUI的Ada程序,因ncursesada绑定无法使用,采用C语言接口调用ncurses。为实现法语输入功能,添加ncursesw宽字符支持:
- 在
initscr前调用setlocale(LC_ALL, "") - 定义
NCURSES_WIDECHAR为1 - 使用指定的编译/链接参数
目前宽字符输入功能正常,但菜单显示被截断。排查setlocale配置、参考ncurses Unicode相关文档后问题仍未解决;移除宽字符相关设置后,菜单显示恢复正常。需求是同时支持宽字符输入与正常菜单显示,未找到合适的C替代库,C++因Ada接口问题无法使用,特此求助。
编译/链接参数
- 编译器参数:
-I/usr/include/ncursesw -D_DEFAULT_SOURCE -D_XOPEN_SOURCE_EXTENDED=600 - 链接器参数:
-Wl,-Bsymbolic-functions -lncursesw -ltinfo
最小复现代码
编译命令
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 (); }
内容的提问来源于stack exchange,提问作者Akutchi
相关产品推荐
相关产品推荐

