在ncurses中实现文本滚动的推荐方法是什么?

时间:2011-08-02 13:31:47

标签: c ncurses curses

我正在尝试使用文本滚动来实现一个ncurses应用程序。建议的方法是什么?

以下是我所知道的:

  1. 您可以使用scroll将文本缓冲区向上或向下移动1行。但是,如果向下滚动,最后会在顶部显示一个空白行;如果向上滚动,则最后会在底部显示空白行,您必须自己重新绘制。
  2. Ncurses为你做了一个文字包装,当我必须确定我必须在第一步中重新绘制哪一行时,这会弄乱我的数学。
  3. 我想我可以自己重新实现自动换行并保留所有后置换行的数组,但这似乎是一个常见的问题,所以可能有更好的方法。

3 个答案:

答案 0 :(得分:2)

我对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个字符的行,但对于不同的解决方案,这是一个不同的问题。

对于自动换行,如果您不需要保留原始文本格式,则可以在从文件中读取长行时将其分成两行。

答案 1 :(得分:2)

答案取决于您拥有多少文本,以及您对屏幕上的数据进行了哪些其他用途。但通常pad功能是显示可滚动文本的首选方式。这不仅是 ncurses 功能,而且受到大多数curses实现的支持(即20世纪80年代后期以后的任何事情)。

pad 就像一个窗口,但其大小不限于当前屏幕大小。相反,数据通过视图显示,其中 pad 中的位置可以轻松更改。

ncurses-examples中有两个相关的示例程序:view.c通过将其内容写入窗口来显示文件,而padview.c使用填充整个文件的填充程序,并使用打击垫功能根据需要,向上/向下和向左/向右移动视图。

在这些程序中,show_all函数执行实际绘图,与view.c(35行)的等效项相比,padview.c(35行)约为三分之一(94行)

进一步阅读:讨论view作为比较ncurses和俚语库的例子。

答案 2 :(得分:1)

ncurses只知道当前的屏幕。当屏幕滚动时,ncurses不会跟踪离开屏幕的任何文本。您的终端可能有一个回滚缓冲区,但它独立于ncurses,并且curses无法看到终端的回滚缓冲区。

如果您需要滚动,我希望您需要跟踪文件中的当前位置。

我不认为ncurses会用自动换行包装你怎么做的?