Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <curses.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <time.h>
- #include <unistd.h>
- #define MAX_LINE 128
- #define MIN(a, b) ({ \
- __auto_type _a = (a); \
- __auto_type _b = (b); \
- _a < _b ? _a : _b; \
- })
- struct line {
- char text[MAX_LINE];
- };
- struct buffer {
- struct line *lines;
- int nlines;
- };
- struct buffer buf;
- int width, height;
- int v_scroll;
- int read_file(struct buffer *buf, const char *file)
- {
- int fd;
- char b[1024];
- const char *p;
- struct line *lines, *newlines;
- int nlines;
- int idx;
- ssize_t r;
- if ((fd = open(file, O_RDONLY)) < 0)
- return -1;
- lines = malloc(sizeof(*lines) * 8);
- if (lines == NULL) {
- close(fd);
- return -1;
- }
- nlines = 0;
- idx = 0;
- while ((r = read(fd, b, sizeof(b))) > 0) {
- p = b;
- do {
- if (*p == '\n') {
- lines[nlines].text[idx] = '\0';
- nlines++;
- newlines = realloc(lines, sizeof(*lines) * (nlines + 1));
- if (newlines == NULL)
- goto end;
- lines = newlines;
- idx = 0;
- } else {
- if (idx + 1 == MAX_LINE)
- continue; /* cut off lines that are too long */
- lines[nlines].text[idx++] = *p;
- }
- p++;
- } while(--r);
- }
- end:
- close(fd);
- lines[nlines].text[idx] = '\0';
- buf->lines = lines;
- buf->nlines = nlines + 1;
- return 0;
- }
- void draw_lines(WINDOW *win, int y, struct line *lines, int nlines, int from, int to)
- {
- int begy, begx;
- int maxy, maxx;
- getbegyx(win, begy, begx);
- getmaxyx(win, maxy, maxx);
- maxx -= begx;
- maxy -= begy;
- if (from < 0)
- from = 0;
- if (to < 0 || to >= nlines)
- to = nlines - 1;
- if (maxy - y < to - from)
- to = maxy - y + from;
- wattr_set(win, 0, 0, NULL);
- for (; from <= to; from++, y++)
- mvwaddstr(win, y, 0, lines[from].text);
- }
- void handle_char(int c)
- {
- switch (c) {
- case 'j':
- if (v_scroll == buf.nlines - height)
- break;
- scrl(1);
- v_scroll++;
- draw_lines(stdscr, height - 1, buf.lines, buf.nlines, v_scroll + height, v_scroll + height);
- break;
- case 'k':
- if (v_scroll == 0)
- break;
- scrl(-1);
- v_scroll--;
- draw_lines(stdscr, 0, buf.lines, buf.nlines, v_scroll, v_scroll);
- break;
- case 'g':
- erase();
- draw_lines(stdscr, 0, buf.lines, buf.nlines, -1, -1);
- break;
- case 'G':
- erase();
- draw_lines(stdscr, 0, buf.lines, buf.nlines, buf.nlines - height, -1);
- break;
- }
- }
- void do_refresh(void)
- {
- refresh();
- }
- int main(int argc, char **argv)
- {
- if (argc < 2) {
- fprintf(stderr, "usage: %s <file name>\n", argv[0]);
- return -1;
- }
- initscr();
- noecho();
- raw();
- curs_set(0);
- start_color();
- keypad(stdscr, true);
- scrollok(stdscr, true);
- /* reserve the last line for the status bar */
- setscrreg(0, LINES - 2);
- refresh();
- if (read_file(&buf, argv[1]) < 0) {
- endwin();
- fprintf(stderr, "error reading file '%s'\n", argv[1]);
- return -1;
- }
- width = MIN(COLS, MAX_LINE);
- height = MIN(LINES - 1, buf.nlines);
- v_scroll = 0;
- /* Draw initial content */
- draw_lines(stdscr, 0, buf.lines, buf.nlines, -1, -1);
- const time_t start = time(NULL);
- /* Main loop */
- while (1) {
- /* Draw status bar */
- attr_set(A_REVERSE, 0, NULL);
- mvprintw(LINES - 1, 0, "%4d (%3d%%)", v_scroll + 1, 100 * v_scroll / (buf.nlines - height));
- hline(' ', COLS - getcurx(stdscr));
- do_refresh();
- int c = 0;
- if (rand() % 2 == 0)
- c = 'j';
- else
- c = 'k';
- handle_char(c);
- /* Run for 30 seconds */
- if (time(NULL) - start == 30)
- break;
- }
- endwin();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement