ncurses волнуется при записи широкого символа в определенных местах экрана - PullRequest
0 голосов
/ 21 февраля 2019

Я пишу приложение, используя ncurses, и хочу использовать в нем символы рисования прямоугольников, в частности u / 2550 и u / 2551 (на данный момент).У меня есть для настройки петель, чтобы рисовать столбцы с двух сторон терминала, исходя из размера экрана, который я определяю в другом месте.

По любой причине, когда дело доходит до рисования любых символов Юникода по горизонтали (здесь, внизу экрана,но он делает это в любой строке), он перейдет от печати символов в порядке к печати мусора 'P's.Это немного сложно объяснить, поэтому у меня есть несколько фотографий, показывающих, что происходит, когда я рисую 6 символов, а затем 7 или более символов.

With 6 characters

With 7 characters

Часть кода, ответственная за рисование этих символов, как таковая, обратите внимание, что последний цикл for - это то, что рисует эти символы, и итератор должен идти дальше, чем просто7, но он делает это здесь и в любом другом месте.

void drawBorder(){ //draw the border graphics
                attron(COLOR_PAIR(3));
        for(int i = 1; i < screenSizeY - 1; i++){ //draw left side
                mvaddwstr(i, 0, L"║");
        }
        for(int i = 1; i < screenSizeY - 1; i++){ //draw right side
                mvaddwstr(i, screenSizeX - 1, L"\u2551");
        }
        for(int i = 0; i < 7; i++){ //draw bottom
                mvaddwstr(screenSizeY - 1, i, L"\u2550");
        }
                attroff(COLOR_PAIR(3));
}

Я связываюсь с пакетом ncursesw и у меня правильно настроен языковой стандарт.Другие символы, нарисованные вертикальными линиями, работают нормально, но это не так.Я использую C ++, скомпилированный с g ++, работающий на Linux в терминальной сессии Alacritty.

Это не имеет ничего общего с функциями рисования блоков или определенными возможностями терминала, все широкие символы отлично поддерживаются терминалом,и работать в других частях терминала.Это произойдет в зависимости от того, сколько из них я нарисовал подряд, а также для других символов ящика.

1 Ответ

0 голосов
/ 26 февраля 2019

OP отправил более полный пример, который показывает проблему:

#include <ncurses.h>
#include <string>
#include <iostream>

using namespace std;

int main(){

    initscr();
    setlocale(LC_ALL, "");
    raw();
    keypad(stdscr, TRUE);
    noecho();

    for(int i = 0; i < 10; i++){
        mvaddwstr(0, i, L"\u2550");
    }
    for(int i = 0; i < 6; i++){
        mvaddwstr(1, i, L"\u2550");
    }
    refresh();
    getch();
    endwin();

    return 0;

}

Проблема в том, что библиотека инициализируется с другим языковым стандартом, чем используется в вызовах mvaddwstr.Страница руководства сообщает

Библиотека использует локаль, которую инициализировала вызывающая программа.Обычно это делается с помощью setlocale:

setlocale(LC_ALL, "");

Если языковой стандарт не инициализирован, библиотека предполагает, что символы могут быть напечатаныкак в ISO-8859-1 , для работы с некоторыми устаревшими программами.Вы должны инициализировать локаль и не полагаться на конкретные данные библиотеки, если локаль не была настроена.

Поскольку вызов setlocale происходит после initscr, а не ранее, ncurses предполагает, что данные соответствуют ISO-8859-1, и сталкивается с неожиданным сценарием.В других местах, таких как addwstr, ncurses проверяет, являются ли данные действительными wchar_t, но в них используется текущий языковой стандарт.В этом случае это далеко от функций, которые, как он знает, должны обрабатываться таким образом (это рендеринг данных, которые уже были обработаны).Сравнение в библиотеке, которое позволяет обрабатывать это с использованием возможности repeat_char, может быть улучшено, но фактическая ошибка в примере программы.

...