ncurses菜单边框错位的解决方法

How to solve ncurses menu border misalignment

我正在使用以下简单的 ncurses 代码创建菜单:

#include <menu.h>
#include <stdlib.h>

ITEM   **it;
MENU   *me;
WINDOW *win;

void quit(void)
{
  int i;

  unpost_menu(me);
  free_menu(me);

  for(i=0; i<=4; i++)
  {
    free_item(it[i]);
  }

  free(it);
  delwin(win);
 
  endwin();
}

int main(void)
{
  int ch;

  initscr();
  atexit(quit);
  clear();
  noecho();
  curs_set(0);
  cbreak();
  nl();
  keypad(stdscr, TRUE);
  start_color();

  init_pair(1, COLOR_WHITE, COLOR_BLUE);
  init_pair(2, COLOR_BLUE, COLOR_YELLOW);

  bkgd(COLOR_PAIR(1));

  it = (ITEM **)calloc(5, sizeof(ITEM *));
  it[0] = new_item("M1", "Menueeintrag 1");
  it[1] = new_item("M2", "Menueeintrag 2");
  it[2] = new_item("M3", "Menueeintrag 3");
  it[3] = new_item("Ende", "Programm beenden");
  it[4] = 0;
  me = new_menu(it);

  win = newwin(8, 30, 5, 5);
  set_menu_win (me, win);
  set_menu_sub (me, derwin(win, 4, 28, 3, 2));
  box(win, 0, 0);  
  mvwaddstr(win, 1, 2, "***** Testmenü *****");
  set_menu_fore(me, COLOR_PAIR(1)|A_REVERSE);
  set_menu_back(me, COLOR_PAIR(1));
  wbkgd(win, COLOR_PAIR(2));

  post_menu(me);        

  mvaddstr(14, 3, "Programm mittels Menü oder F1-Funktionstaste beenden");

  refresh();
  wrefresh(win);
 
  while((ch=getch()) != KEY_F(1))
  {
    switch(ch)
    {
      case KEY_DOWN:
        menu_driver(me, REQ_DOWN_ITEM);
        break;
      case KEY_UP:
        menu_driver(me, REQ_UP_ITEM);
        break;
      case 0xA: /* Return- bzw. Enter-Taste -> ASCII-Code */
        if(item_index(current_item(me)) == 3)
          exit(0);      
    }

    wrefresh(win);
  }   

  return (0);  
}

但是在我放置文本的位置总是出现奇怪的错位。您可以在查看菜单边框以及与帮助文本相同高度的终端右边框时看到它。

生成的程序的屏幕截图

“Testmenü”上的变音符号说明了这个故事:它可能被编码为 UTF-8,它使用两个字节:

252: 252 0374 0xfc text "4" utf8 34

如果 locale 设置是(例如)en_US,那么这会告诉 ncurses 终端不使用 UTF-8,它会假定该字符串实际上是 ISO-8859-1。在这种情况下,它将将该字符的两个字节计为屏幕上的单独单元格。

同时,终端可能正在使用UTF-8编码(并显示如屏幕截图所示的字符)。但是如果语言环境设置与终端不对应,你会看到类似这样的奇怪东西。