/* See LICENSE file for copyright and license details. */ #include #include #include #include void freefilebuf(char **buffer, ssize_t cnt) { if (!buffer || !cnt) return; while (cnt) free(buffer[--cnt]); free(buffer); } int readfile(FILE *fp, char ***buffer, ssize_t *count, int ncols) { char **buf, **tmp; char *line; int ret; size_t chunks, sz; ssize_t cnt, len, cuts, clen; #define CHUNKS 128 if (!fp) return -1; buf = malloc(sizeof(char *) * CHUNKS); if (buf == NULL) { perror(NULL); return -1; } ret = 0; cnt = 0; chunks = CHUNKS; for (cnt = 0; ; cnt++) { if (cnt == chunks-5) { chunks += CHUNKS; tmp = realloc(buf, chunks * sizeof(char *)); if (tmp == NULL) { ret = -1; break; } buf = tmp; } line = NULL; sz = 0; if ((len = getdelim(&line, &sz, '\n', fp)) == -1) { if (ferror(fp)) ret = -1; break; } line[--len] = '\0'; /* remove the newline */ if (len > ncols) { char *p; cuts = 0; clen = len; p = line; while ((clen > 0) && (ret != -1)) { buf[cnt+cuts] = strndup(p, (clen > ncols) ? ncols - 1 : clen); p += ncols - 1; clen -= ncols - 1; cuts++; if (cnt+cuts == chunks-5) { chunks += CHUNKS; tmp = realloc(buf, chunks * sizeof(char *)); if (tmp == NULL) { ret = -1; break; } buf = tmp; } } cnt += (cuts - 1); free(line); if (ret == -1) break; } else { buf[cnt] = line; } } if (ret == -1) { perror(NULL); freefilebuf(buf, cnt); } else { *buffer = buf; *count = cnt; } free(line); return ret; } void displayfile(FILE *fp, long fpos, int r, int c, int y, int x) { WINDOW *win; char **lbuf; int i, ch, inc, loc; ssize_t n, ctop, start; if (fseek(fp, fpos, SEEK_SET) == -1) { perror(NULL); return; } if ((readfile(fp, &lbuf, &n, c) == -1) || (n <= r)) { freefilebuf(lbuf, n); return; } inc = 0; ctop = start = n - r; win = newwin(r, c, y, x); idlok(win, TRUE); scrollok(win, TRUE); wsetscrreg(win, 0, r-1); for (i = 0; i < r && i < n; i++) mvwaddnstr(win, i, 0, lbuf[ctop+i], c); wrefresh(win); while ((ch = getch()) != 'q') { if (n <=r) continue; switch (ch) { case 'f': if (ctop + r >= n) break; ctop += r; if (ctop > n - r) ctop = (n - r); break; case 'b': if (ctop == 0) break; ctop -= r; if (ctop < 0) ctop = 0; break; case 'j': if (ctop + r >= n) break; inc = 1; ctop++; break; case 'k': if (ctop == 0) break; inc = -1; ctop--; break; default: break; } if (start != ctop) { if (inc) { loc = (inc < 0) ? 0 : r - 1; wscrl(win, inc); mvwaddnstr(win, loc, 0, lbuf[ctop+loc], c); wrefresh(win); inc = 0; } else if (start != ctop) { wclear(win); for (i = 0; i < r; i++) mvwaddnstr(win, i, 0, lbuf[ctop+i], c); wrefresh(win); } start = ctop; } } freefilebuf(lbuf, n); delwin(win); }