9

私は、lessのようにテキストをスクロールするncursesアプリを実装しようとしています。これを行うための推奨される方法は何ですか?

これが私が知っていることです:

  1. を使用scrollして、テキストバッファを1行上または下に移動できます。ただし、下にスクロールすると上部に1行、上にスクロールすると下部に1行の空白行が表示され、自分で再描画する必要があります。
  2. Ncursesはワードラップを実行します。これは、手順1で再描画する必要がある行を決定する必要がある場合に、計算を台無しにします。

自分でワードラップを再実装して、すべてのポストラップされた行の配列を保持できると思いますが、これは一般的な問題のように思われるので、より良い方法があるかもしれません。

4

3 に答える 3

2

私はまだ ncurses の経験が浅いので、すべてのライブラリ関数を知っているわけではありませんが、テキスト行の二重にリンクされたリストを保持することはうまくいく可能性があります。以下は、less のプリミティブなクローンです。

#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 つに分割できます。

于 2012-08-10T10:56:08.407 に答える
1

ncurses は、現在の画面についてのみ認識します。画面がスクロールされると、ncurses は画面から出たテキストを追跡しません。端末にはスクロール バック バッファがあるかもしれませんが、それは ncurses とは無関係であり、curses は端末のスクロール バック バッファを認識​​できません。

スクロールする必要がある場合は、ファイル内の現在の場所を追跡する必要があると思います。

ncurses がワード ラップを行うとは思いませんでした。どのようにワード ラップを行っていますか?

于 2011-09-27T21:59:03.587 に答える