add more test (3)
[cmore.git] / cmore.c
1 /* depend: */
2 /* cflags: */
3 /* linker: cmd.o debug.o tui.o -lcurses */
4 /* winlnk: cmd.o debug.o tui.o -lpdcurses */
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9
10 #include "cmd.h"
11 #include "debug.h"
12 #include "tui.h"
13
14 /* static variables */
15 char *progname = NULL;
16 char *version = "0.1";
17
18 char *input = NULL;
19 char *command = NULL;
20 int second = 0;
21
22 void display (char **lines, int xmax, int ymax)
23 {
24 int stop = 0;
25
26 #ifdef __PDCURSES__
27 statusmsg ("Press 'q' or escape to quit");
28 #else
29 statusmsg ("Press 'q' or double-escape to quit");
30 #endif
31
32 int skip = 0;
33 while (!stop) {
34 clsbody ();
35 int i = 0;
36 int eol = 0;
37 for (i = 0; i < ymax - 1; i++) {
38 if (lines [skip + i] == NULL) {
39 break;
40 }
41 if (eol) {
42 bodymsg ("\n");
43 }
44 bodymsg (lines[skip + i]);
45 eol = (lines[skip + i][xmax - 1 ] == '\0');
46 }
47 if (lines [skip + i] != NULL) {
48 if (eol) {
49 bodymsg ("\n");
50 }
51 char *str = (char *) calloc (1, xmax + 1);
52 strcpy (str, lines[skip + i]);
53 if (str[xmax - 1] != '\0') {
54 VERBOSE (DEBUG, fprintf (stdout, "last line too long\n"));
55 strcpy (str + xmax - 3, ">>");
56 }
57 bodymsg (str);
58 free (str);
59 }
60
61 if (second > 0) {
62 DoExit ();
63 break;
64 }
65 int key = waitforkey ();
66 VERBOSE (DEBUG, fprintf (stdout, "key pressed: 0x%04x (%c)\n", key, (key >= ' ') && (key < 256) ? key : '.'));
67 switch (key) {
68 case KEY_ESC:
69 #ifndef __PDCURSES__
70 key = waitforkey ();
71 switch (key) {
72 case KEY_ESC:
73 DoExit ();
74 /* fallthrough */
75 case 'f':
76 case 'h':
77 stop = 1;
78 break;
79 }
80 break;
81 #endif
82 case 'q':
83 DoExit ();
84 stop = 1;
85 break;
86 case 'i':
87 case KEY_UP:
88 skip = (skip > 0) ? skip - 1 : skip;
89 break;
90 case 'k':
91 case KEY_DOWN:
92 skip = (lines[skip + 1] != NULL) ? skip + 1 : skip;
93 break;
94 #ifdef __PDCURSES__
95 case ALT_F:
96 case ALT_H:
97 stop = 1;
98 break;
99 #endif
100 }
101 }
102
103 rmstatus();
104 }
105
106 void process (void)
107 {
108 static char **lines = NULL;
109
110 int xmax, ymax;
111 WINDOW *wbody = bodywin ();
112 getmaxyx (wbody, ymax, xmax);
113
114 char *buffer = (char *)-1;
115 if (command) {
116 buffer = exec_cmd (command);
117 } else if (input) {
118 buffer = load_file (input);
119 } else if (!lines) {
120 buffer = read_stdin ();
121 }
122
123 if (buffer == NULL) {
124 cleanup ();
125 VERBOSE (ERROR, fprintf (stderr, "%s: %s\n", command ? "can't execute:" : input ? "can't load:" : "can't read", command ? command : input ? input : "stdin"));
126 exit (1);
127 }
128
129 if (!lines) {
130 lines = split_lines (buffer, xmax);
131 free (buffer);
132 }
133
134 if (lines) {
135 display (lines, xmax, ymax);
136 if (command || buffer) {
137 free_lines (lines);
138 lines = NULL;
139 }
140 }
141
142 if (second > 0) {
143 VERBOSE (DEBUG, fprintf (stdout, "sleeping for %d''\n", second));
144 sleep (second);
145 cleanup ();
146 exit (0);
147 }
148 }
149
150 menu SubMenu0[] =
151 {
152 { "Refresh", process, "Refresh action"},
153 { "Exit", DoExit, "Terminate program" },
154 { "", (FUNC)0, "" }
155 };
156
157 void sub0 (void)
158 {
159 domenu (SubMenu0);
160 }
161
162 menu SubMenu1[] =
163 {
164 { "About", DoExit, "About..." },
165 { "", (FUNC)0, "" }
166 };
167
168 void sub1 (void)
169 {
170 domenu (SubMenu1);
171 }
172
173 menu MainMenu[] =
174 {
175 { "File", sub0, "File menu" },
176 { "Help", sub1, "Help menu" },
177 { "", (FUNC)0, "" } /* always add this as the last item! */
178 };
179
180 /* help message */
181 int usage (int ret)
182 {
183 FILE *fd = ret ? stderr : stdout;
184 fprintf (fd, "usage: %s [-c command] [-f file] [-h] [-s sec] [-v]\n", progname);
185 fprintf (fd, " -c: command\n");
186 fprintf (fd, " -i: input file\n");
187 fprintf (fd, " -h: help message\n");
188 fprintf (fd, " -s: stoptime\n");
189 fprintf (fd, " -v: verbose level (%d)\n", verbose);
190
191 return ret;
192 }
193
194 /* main function */
195 int main (int argc, char *argv[])
196 {
197
198 /* get basename */
199 char *pt = progname = argv[0];
200 while (*pt) {
201 if ((*pt == '/') || (*pt == '\\')) {
202 progname = pt + 1;
203 }
204 pt++;
205 }
206
207 /* process argument */
208 while (argc-- > 1) {
209 char *arg = *(++argv);
210 if (arg[0] != '-') {
211 VERBOSE (ERROR, fprintf (stderr, "%s: invalid option -- %s\n", progname, arg));
212 return usage (1);
213 }
214 char c = arg[1];
215 switch (c) {
216 case 'c':
217 arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
218 if ((arg) && (command == NULL)) {
219 command = arg;
220 } else {
221 VERBOSE (ERROR, fprintf (stderr, "%s: error for command '%s'\n", progname, arg));
222 return usage (1);
223 }
224 break;
225 case 'f':
226 arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
227 if ((arg) && (input == NULL)) {
228 input = arg;
229 } else {
230 VERBOSE (ERROR, fprintf (stderr, "%s: error for file '%s'\n", progname, arg));
231 return usage (1);
232 }
233 break;
234 case 's':
235 arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
236 if (arg == NULL) {
237 VERBOSE (ERROR, fprintf (stderr, "%s: missing number of second\n", progname));
238 return usage (1);
239 }
240 second = atoi (arg);
241 break;
242 case 'v':
243 arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
244 if (arg == NULL) {
245 VERBOSE (ERROR, fprintf (stderr, "%s: missing verbose level\n", progname));
246 return usage (1);
247 }
248 verbose = atoi (arg);
249 break;
250 case 'h':
251 default:
252 return usage (c != 'h');
253 }
254 }
255
256 char titre[256] = {0};
257 sprintf (titre, "Application: %s", command ? command : input ? input : "stdin");
258
259 startmenu (MainMenu, titre, process);
260
261 return 0;
262 }
263
264 /* test: cmore.exe -c 2>&1 | grep error */
265 /* test: cmore.exe -c notAnExistingCommand 2>&1 | grep can\'t */
266 /* test: cmore.exe -f 2>&1 | grep error */
267 /* test: cmore.exe -f notAnExistingFile 2>&1 | grep can\'t */
268 /* test: cmore.exe -h | grep usage */
269 /* test: cmore.exe -Z 2>&1 | grep usage */
270 /* test: cmore.exe -v 2>&1 | grep missing */
271 /* test: cmore.exe -s 2>&1 | grep missing */
272 /* test: cmore.exe _ 2>&1 | grep invalid */
273 /* test: cat tui.c | cmore.exe -v 5 -s 2*/
274 /* test: (sleep 1; echo -n q) | cmore.exe -c 'ip addr' */
275 /* test: (sleep 1; echo -ne '\e\e') | cmore.exe -f tui.c */
276 /* test: (sleep 1; echo -n kkkkk; sleep 1; echo -n i; sleep 1; echo -n q) | cmore.exe -c 'ip addr' */
277 /* test: (sleep 1; echo -n q) | cmore.exe -c 'echo -n a; for i in $(seq 1 '$(( $COLUMNS*($LINES-4)-2 ))'); do echo -n .; done; echo -n z' -v 5 | grep -q 'last line too long' */
278 /* test: (sleep 1; echo -n q) | cmore.exe -c 'echo -n a; for i in $(seq 1 '$(( $COLUMNS*($LINES-4)-3 ))'); do echo -n .; done; echo -n z' -v 5 | grep -q 'last line too long'; test $? -eq 1 */
279
280 /* vim: set ts=4 sw=4 et: */