vtv-viewer.c - vtv-tools - virtual terminal video tools
(HTM) git clone git://bitreich.org/vtv-tools git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/vtv-tools
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
(DIR) README
(DIR) LICENSE
---
vtv-viewer.c (2513B)
---
1 // Copyright 2023 Troels Henriksen <athas@sigkill.dk>
2 //
3 // See LICENSE file for licensing information.
4
5 #include <assert.h>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/ioctl.h>
11 #include <termios.h>
12 #include <unistd.h>
13 #include <errno.h>
14
15 #include "vtv.h"
16
17 struct termios orig_termios;
18
19 void cooked_mode() {
20 tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
21 printf("\033[?25h");
22 }
23
24 void raw_mode() {
25 printf("\033[?25l");
26
27 tcgetattr(STDIN_FILENO, &orig_termios);
28 atexit(cooked_mode);
29
30 struct termios raw = orig_termios;
31 raw.c_iflag &= ~(IXON);
32 raw.c_lflag &= ~(ECHO | ICANON);
33 raw.c_cc[VMIN] = 1;
34 raw.c_cc[VTIME] = 0;
35 tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
36 }
37
38 void move(int x, int y) { printf("\033[%d;%dH", y, x); }
39 void home() { printf("\033[;H"); }
40 void clear_screen() { printf("\033[2J"); }
41 void clear_line() { printf("\033[2K"); }
42 void def() { printf("\033[0m"); }
43
44 struct {
45 int frame;
46 int lines_per_frame;
47 struct vtv* vtv;
48 } state;
49
50 void show_status() {
51 printf("Frame (h/l): %5d Framesize (j/k): %5d\n",
52 state.frame, state.lines_per_frame);
53 }
54
55 void show_frame() {
56 vtv_show_frame(state.vtv, stdout, state.frame, state.lines_per_frame,
57 "\033[0m MISSING LINE");
58 }
59
60 int view(struct vtv* vtv) {
61 raw_mode();
62
63 state.frame = 0;
64 state.lines_per_frame = 25;
65 state.vtv = vtv;
66
67 while (1) {
68 home();
69 def();
70 clear_screen();
71 show_frame();
72 move(0, state.lines_per_frame+1);
73 def();
74 // It is intentional that the status is at the bottom, as VTV
75 // files may assume that they are drawn from line 0.
76 show_status();
77 switch(getchar()) {
78 case 'q':
79 return 0;
80 case 'h':
81 if (state.frame != 0) { state.frame--; }
82 break;
83 case 'l':
84 state.frame = (state.frame+1);
85 break;
86 case 'j':
87 if (state.lines_per_frame != 0) {state.lines_per_frame--; }
88 break;
89 case 'k':
90 state.lines_per_frame++;
91 break;
92 }
93 }
94 }
95
96 int main(int argc, char** argv) {
97 if (argc != 2) {
98 fprintf(stderr, "Usage: %s FILE\n", argv[0]);
99 return 1;
100 }
101
102 FILE* f = fopen(argv[1], "r");
103 if (f == NULL) {
104 fprintf(stderr, "%s: cannot open %s: %s\n",
105 argv[0], argv[1], strerror(errno));
106 }
107
108 struct vtv *vtv = vtv_read(f);
109
110 if (vtv == NULL) {
111 fprintf(stderr, "%s: failed to read from %s: %s\n",
112 argv[0], argv[1], strerror(errno));
113 }
114
115 int ret = view(vtv);
116 vtv_free(vtv);
117 return ret;
118 }
119