-
Notifications
You must be signed in to change notification settings - Fork 5
/
cfastread.c
137 lines (118 loc) · 3.78 KB
/
cfastread.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#define WPM 400
// should be 1/2 the size of the longest string
// don't want to read in the whole thing first.
// if the string is longer than 2x the offset,
// too bad.
#define OFFSET 20
#define BUFSIZE 1024
#define COLOR "\x1b[0m"
// "\x1b[37;1m"
#define CENTERCOLOR "\x1b[31;1m"
#define RESETCOLOR "\x1b[0m"
// number of spaces to prepend to string on output
int spaces(int stringsize, int offset) {
// offset marks where the middle character should go.
// so # of spaces is offset - stringsize/2
// or 0 of negative
int result = offset - (stringsize/2);
return (result > 0) ? result : 0;
}
int buffer_spans(char *buffer, size_t size, char *delims) {
int i = 0;
int len_delims = strlen(delims);
// for each delimiter (marking separation character)
// check if the last character in the buffer matches.
// If it does, we don't need to save the last token
for (i = 0; i < len_delims; i++) {
if (buffer[size-1] == delims[i]) {
return 0;
}
}
return 1;
}
void printstring(char *string) {
int n_spaces;
int middle = (strlen(string)/2);
n_spaces = spaces(strlen(string), OFFSET);
printf("%*s", n_spaces,"");
printf(COLOR "%.*s", middle, string);
printf(CENTERCOLOR "%.*s", 1, string+middle);
printf(COLOR "%s" RESETCOLOR, string+middle+1);
}
int main(int argc, char *argv[]) {
struct stat st_buf;
int status, save_last, has_punct;
FILE *f;
char *delims = ";\n \"";
char buffer[BUFSIZE],*p;
// for strings that span the buffer boundary
char *savedstring = NULL;
char *frankenstring = NULL;
char *last;
// check file
if (argc == 2) {
status = stat(argv[1], &st_buf);
if (status != 0 || (!S_ISREG(st_buf.st_mode))) {
fprintf(stderr, "Error or file not found: %s\n", argv[1]);
return 1;
}
f = fopen(argv[1], "r");
} else {
f = stdin;
}
// open the file
if (f == NULL) {
fprintf(stderr, "Error opening file: %s\n", argv[1]);
return 1;
}
while(fgets(buffer, BUFSIZE, f) != NULL) {
save_last = buffer_spans(buffer, BUFSIZE, delims);
p=strtok(buffer, delims);
// fgets keeps newlines, but the tokenizer splits them
// so p can be NULL if fgets only has a newline.
if (p == NULL) {
usleep(4*(60.0/WPM) * 1000 * 1000);
continue;
}
if (savedstring && (savedstring != NULL)) {
if (frankenstring && (frankenstring != NULL)) {
free(frankenstring);
frankenstring = NULL;
}
frankenstring = malloc(sizeof(char) * (strlen(p)+strlen(savedstring)) + 1);
strncat(frankenstring, savedstring, strlen(savedstring));
strncat(frankenstring, p, strlen(p));
p = frankenstring;
}
do {
if (save_last == 1) {
last = p;
}
printstring(p);
// I actually don't know why these don't work if both are
// puts or printf or they are swapped... shrug.
printf("\x1b[0K");
puts("\x1b[1A");
// delay twice as long for punctuation
has_punct = (ispunct(p[strlen(p)-1]) == 0) ? 1 : 2;
usleep(has_punct*(60.0/WPM) * 1000 * 1000);
} while ((p = strtok(NULL, delims)));
// clean up
if (save_last == 1) {
if (savedstring && (savedstring != NULL)) {
free(savedstring);
savedstring = NULL;
} else {
savedstring = strdup(last);
}
}
}
fclose(f);
printf("\n");
}