Каков рекомендуемый способ реализации прокрутки текста в ncurses? - PullRequest
7 голосов
/ 02 августа 2011

Я пытаюсь реализовать приложение ncurses с прокруткой текста, как меньше.Каков рекомендуемый способ сделать это?

Вот что я знаю:

  1. Вы можете использовать scroll для перемещения текстового буфера вверх или вниз на 1 строку.Тем не менее, в итоге вы получите одну пустую строку вверху, если прокрутите вниз, или внизу, если прокрутите вверх, которую вам придется перекрашивать самостоятельно.
  2. Ncurses делает для вас перенос слов, чтопортит мою математику, когда мне нужно определить, какую строку мне нужно перекрасить на шаге 1.

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

Ответы [ 3 ]

2 голосов
/ 10 августа 2012

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

#include <ncurses.h>
#include <stdlib.h>

#define MAXLEN 128

typedef struct Line {
    char contents[MAXLEN];
    struct Line *prev, *next;
} Line;

Line *head, *curr;

int nr_lines;
int curr_line;

int term_rows, term_cols;

void load(const char *filename);
void draw(Line *l);

int main(int argc, char **argv)
{
    if (argc == 1)
    {
        fputs("less: No file to open\n", stderr);
        return 1;
    }

    initscr();
    noecho();
    keypad(stdscr, TRUE);   // for KEY_UP, KEY_DOWN
    getmaxyx(stdscr, term_rows, term_cols);
    addstr("Reading text...\n");

    load(argv[1]);

    curr = head;
    curr_line = 0;
    draw(curr);

    int ch;
    while ((ch = getch()) != EOF && ch != 'q')
    {
        if (ch == KEY_UP && curr->prev != NULL)
        {
            curr_line--;
            curr = curr->prev;
        }
        else if (ch == KEY_DOWN && curr->next != NULL
            && curr_line + term_rows < nr_lines)
        {
            curr_line++;
            curr = curr->next;
        }
        draw(curr);
    }

    endwin();
    return 0;
}

void load(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    Line *lp;

    head = malloc(sizeof(Line));
    head->prev = head->next = NULL;
    curr = head;

    while (fgets(curr->contents, MAXLEN, fp))
    {
        lp = malloc(sizeof(Line));
        lp->prev = curr;
        curr->next = lp;
        curr = lp;
        nr_lines++;
    }
    curr->next = NULL;
}

void draw(Line *l)
{
    int i;
    clear();
    for (i = 0; i < term_rows && l != NULL; i++, l = l->next)
        addstr(l->contents);
}

Я не уверен, как это будет обрабатывать строки длиннее 128 символов, но это другая проблема с другим решением.

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

2 голосов
/ 15 февраля 2018

Ответ зависит от того, сколько текста у вас есть, и как вы используете данные на экране.Но обычно функция pad является предпочтительным способом отображения прокручиваемого текста.Это не только функция ncurses , но и поддерживается большинством реализаций curses (т. Е. Что-либо после конца 1980-х).

A pad походит на окно, но его размер не ограничен текущим размером экрана.Вместо этого данные отображаются через представление, положение которого в pad может быть легко изменено.

В ncurses-examples есть две примеры программ, которые имеют отношение: view.c отображает файл, записывая его содержимое в окно, в то время как padview.c использует панель, на которой рисуется весь файл, и использует функции панели для перемещения представления по мере необходимости вверх/ вниз и влево / вправо.

В этих программах функция show_all выполняет фактическое рисование и составляет примерно треть от длины padview.c (35 строк) по сравнениюэквивалент view.c (94 строки).

Дополнительная литература: обсуждение view в качестве примера для сравнения библиотек ncurses и slang.

1 голос
/ 28 сентября 2011

ncurses знает только о текущем экране. Когда экран прокручивается, ncurses не отслеживает текст, который покидает экран. Ваш терминал может иметь буфер обратной прокрутки, но он не зависит от ncurses, а у curses нет видимости в буфер обратной прокрутки терминала.

Я ожидаю, что вам нужно будет отслеживать ваше текущее местоположение в файле, если вам нужно прокрутить.

Я не думал, что ncurses сделал перенос слов, как вы делаете перенос слов?

...