1 /*
2 TERMatrix 0.2
3 Copyright 2006 Flavio Chierichetti
4 Licence GPL 2
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <time.h>
11 #include <unistd.h>
12 #include <signal.h>
13 #include <fcntl.h>
14 #include <termios.h>
15 #include <sys/time.h>
16 #include <sys/ioctl.h>
17
18 #define TERMINAL_DEVICE "/dev/tty"
19
20 #define min(x, y) ((x) < (y) ? (x) : (y))
21
22 #define termCursorOff() printf("\x1b[?25l");
23 #define termMoveTo(r, c) printf("\x1b[%d;%dH", r + 1, c + 1)
24 #define termSetAttr(fore, back, attr) printf("\x1b[%d;%d;%dm", attr, fore + 30, back + 40)
25 #define termPutChar(c) printf("%c", c)
26 #define termErase() printf("\x1b[2J")
27 #define termReset() printf("\x1b%c", 'c')
28
29 typedef struct s {
30 int start, end, n, speed, counter;
31 char last;
32 struct s *next;
33 } seq;
34
35 enum { usecDelay = 8000, speedMin = 3 , speedMax = 8 , darkProb = 75 , newSeqProb = 20 , letterChangeProb = 25 };
36
37 enum { black = 0, red, green, yellow, blue, magenta, cyan, white };
38 enum { normalAttr = 1 , boldAttr = 22 };
39
40 void initTerm(int signum);
41 void initSigActions();
42 void print(int signum);
43 void end(int signum);
44
45 char *V = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz<>()[]{}.,:;!@#$%^&*-_=+|?/`~'\"\\";
46 int Length, R, C;
47 seq **S;
48
49 char *quotes[] = {
50 "Wake up, Neo.",
51 "There is no spoon.",
52 "Follow the white rabbit.",
53 "What is the matrix?",
54 "Welcome to the real world.",
55 "Don't think you are. Know you are.",
56 "It is inevitable.",
57 "Only human.",
58 "Deja vu...",
59 NULL
60 };
61
main()62 int main() {
63 initTerm(0);
64
65 srand(time(NULL) % RAND_MAX);
66
67 Length = strlen(V);
68
69 initSigActions();
70
71 while (1)
72 pause();
73
74 return 0;
75 }
76
initTerm(int signum)77 void initTerm(int signum) {
78 int fd;
79 struct winsize ws;
80 int i;
81
82 if ( (fd = open(TERMINAL_DEVICE, O_RDWR)) == -1 )
83 exit(1);
84
85 if ( ioctl(fd, TIOCGWINSZ, &ws) != 0 )
86 exit(1);
87
88 close(fd);
89
90 R = ws.ws_row;
91 C = ws.ws_col;
92
93 /* If this function is called more than once, there would be a little memory leak here */
94
95 S = (seq**) calloc (C, sizeof(seq*));
96
97 for ( i = 0 ; i < C ; i++ )
98 S[i] = NULL;
99
100 termCursorOff();
101 termSetAttr(green, black, normalAttr);
102 termErase();
103 }
104
initSigActions()105 void initSigActions() {
106 struct sigaction sigintAction, sigalrmAction, sigwinchAction;
107 struct itimerval timer;
108
109 sigfillset(&sigwinchAction.sa_mask);
110 sigwinchAction.sa_flags = 0;
111 sigwinchAction.sa_handler = initTerm;
112 sigaction(SIGWINCH, &sigwinchAction, NULL);
113
114 sigfillset(&sigalrmAction.sa_mask);
115 sigalrmAction.sa_flags = 0;
116 sigalrmAction.sa_handler = print;
117 sigaction(SIGALRM, &sigalrmAction, NULL);
118
119 sigfillset(&sigintAction.sa_mask);
120 sigintAction.sa_flags = 0;
121 sigintAction.sa_handler = end;
122 sigaction(SIGINT, &sigintAction, NULL);
123
124 timer.it_interval.tv_sec = timer.it_value.tv_sec = 0;
125 timer.it_interval.tv_usec = timer.it_value.tv_usec = usecDelay;
126 setitimer(ITIMER_REAL, &timer, NULL);
127 }
128
print(int signum)129 void print(int signum) {
130 int c, r;
131
132 for ( c = 0 ; c < C ; c++ )
133 if ( S[c] ) {
134 S[c]->counter = (S[c]->counter + 1) % S[c]->speed;
135 if ( S[c]->counter == 0 ) {
136 for ( r = S[c]->start ; r < min(R, S[c]->end) ; r++ )
137 if ( rand() % 100 < letterChangeProb || r == S[c]->end - 1 ) {
138 if ( rand() % 100 < darkProb )
139 termSetAttr(green, black, boldAttr);
140 else
141 termSetAttr(green, black, normalAttr);
142
143 termMoveTo(r, c);
144 termPutChar(V[rand() % Length]);
145 }
146
147 if ( S[c]->end == R )
148 S[c]->end++;
149
150 if ( S[c]->n == 0 ) {
151 termMoveTo(S[c]->start, c);
152 termPutChar(' ');
153
154 S[c]->start++;
155 }
156
157 if ( S[c]->end < R ) {
158 S[c]->last = V[rand() % Length];
159
160 termSetAttr(white, black, normalAttr);
161 termMoveTo(S[c]->end, c);
162 termPutChar(S[c]->last);
163
164 S[c]->end++;
165 }
166
167 if ( S[c]->n > 0 )
168 S[c]->n--;
169
170 if ( S[c]->start == S[c]->end ) {
171 free(S[c]);
172 S[c] = NULL;
173 }
174 }
175 } else
176 if ( rand() % 100 < newSeqProb ) {
177 S[c] = (seq*) malloc ( sizeof(seq) );
178
179 S[c]->start = 0;
180 S[c]->end = 0;
181 S[c]->speed = rand() % (speedMax - speedMin + 1) + speedMin;
182 S[c]->counter = 0;
183 S[c]->n = rand() % R + 1;
184
185 S[c]->last = 0;
186 }
187
188 fflush(stdout);
189 }
190
end(int signum)191 void end(int signum) {
192 int i;
193
194 termReset();
195
196 for ( i = 0 ; quotes[i] != NULL ; i++ );
197 i = rand() % i;
198
199 printf("%s\n", quotes[i]);
200
201 exit(0);
202 }
203