1 /* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
11 * Wendy, let me explain something to you. Whenever you come in here and
12 * interrupt me, you're BREAKING my CONCENTRATION. You're DISTRACTING me!
13 * And it will then take me time to get back to where I was. You understand?
14 * Now, we're going to make a new rule. When you come in here and you hear
15 * me typing, or whether you DON'T hear me typing, or whatever the FUCK you
16 * hear me doing; when I'm in here, it means that I am working, THAT means
17 * don't come in! Now, do you think you can handle that?
21 #include "screenhack.h"
23 char *progclass = "XJack";
26 ".background: #FFF0B4",
27 ".foreground: #000000",
28 "XJack.font: -*-courier-medium-r-*-*-*-240-*-*-m-*-*-*",
33 XrmOptionDescRec options [] = {
34 { "-delay", ".delay", XrmoptionSepArg, 0 },
35 { "-font", ".font", XrmoptionSepArg, 0 },
40 screenhack (Display *dpy, Window window)
42 static const char *source = "All work and no play makes Jack a dull boy. ";
43 /* If you're here because you're thinking about making the above string be
44 customizable, then you don't get the joke. You loser. */
45 const char *s = source;
46 int columns, rows; /* characters */
47 int left, right; /* characters */
48 int char_width, line_height; /* pixels */
49 int x, y; /* characters */
51 int hspace = 15; /* pixels */
52 int vspace = 15; /* pixels */
53 Bool break_para = True;
58 XWindowAttributes xgwa;
61 int delay = get_integer_resource ("delay", "Integer");
62 char *fontname = get_string_resource ("font", "Font");
63 XFontStruct *font = XLoadQueryFont (dpy, fontname);
66 font = XLoadQueryFont (dpy, "-*-*-medium-r-*-*-*-240-*-*-m-*-*-*");
68 font = XLoadQueryFont (dpy, "-*-courier-medium-r-*-*-*-180-*-*-m-*-*-*");
70 font = XLoadQueryFont (dpy, "-*-*-*-r-*-*-*-240-*-*-m-*-*-*");
73 fprintf(stderr, "no big fixed-width font like \"%s\"\n", fontname);
77 XGetWindowAttributes (dpy, window, &xgwa);
80 gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy,
82 gcv.background = get_pixel_resource ("background", "Background", dpy,
84 gc = XCreateGC (dpy, window, (GCFont | GCForeground | GCBackground), &gcv);
86 char_width = (font->per_char
87 ? font->per_char['n'-font->min_char_or_byte2].rbearing
88 : font->min_bounds.rbearing);
89 line_height = font->ascent + font->descent + 1;
91 columns = (xgwa.width - hspace - hspace) / char_width;
92 rows = (xgwa.height - vspace - vspace) / line_height;
94 left = 0xFF & (random() % ((columns / 2)+1));
95 right = left + (0xFF & (random() % (columns - left - 10)+10));
103 for (s2 = s; *s2 && *s2 != ' '; s2++)
108 (x + word_length) >= right))
116 if (mode == 1 || mode == 2)
118 /* 1 = left margin goes southwest; 2 = southeast */
119 left += (mode == 1 ? 1 : -1);
120 if (left >= right - 10)
122 if ((right < (columns - 10)) && (random() & 1))
123 right += (0xFF & (random() % (columns - right)));
133 else if (mode == 3 || mode == 4)
135 /* 3 = right margin goes southeast; 4 = southwest */
136 right += (mode == 3 ? 1 : -1);
137 if (right >= columns)
142 else if (right <= left + 10)
146 if (y >= rows) /* bottom of page */
148 /* scroll by 1-5 lines */
149 int lines = (random() % 5 ? 0 : (0xFF & (random() % 5))) + 1;
153 /* but sometimes scroll by a whole page */
154 if (0 == (random() % 100))
160 int inc = line_height / 7;
161 int pix_delay = delay / 1000;
162 if (inc <= 0) inc = 1;
163 for (i = 0; i < line_height; i += inc)
167 XCopyArea (dpy, window, window, gc,
169 xgwa.width, xgwa.height - inc,
172 if (pix_delay) usleep (pix_delay);
177 /* See? It's OK. He saw it on the television. */
178 XClearArea (dpy, window,
179 0, xgwa.height - vspace - line_height,
180 xgwa.width, line_height + vspace + vspace,
184 XGetWindowAttributes (dpy, window, &xgwa);
185 columns = (xgwa.width - hspace - hspace) / char_width;
186 rows = (xgwa.height - vspace - vspace) / line_height;
187 if (y > rows) y = rows-1;
188 if (x > columns) x = columns-2;
190 if (delay) usleep (delay);
201 int xshift = 0, yshift = 0;
202 if (0 == random() % 50)
204 xshift = random() % ((char_width / 3) + 1); /* mis-strike */
205 yshift = random() % ((line_height / 6) + 1);
206 if (0 == (random() % 3))
214 if (0 == (random() % 250)) /* introduce adjascent-key typo */
216 static const char * const typo[] = {
217 "asqw", "ASQW", "bgvhn", "cxdfv", "dserfcx", "ewsdrf",
218 "Jhuikmn", "kjiol,m", "lkop;.,", "mnjk,", "nbhjm", "oiklp09",
219 "pol;(-0", "redft54", "sawedxz", "uyhji87", "wqase32",
220 "yuhgt67", ".,l;/", 0 };
222 while (typo[i] && typo[i][0] != c)
225 c = typo[i][0xFF & ((random() % strlen(typo[i]+1)) + 1)];
229 if (c >= 'a' && c <= 'z' && (caps || 0 == (random() % 350)))
232 if (c == 'O' && random() & 1)
237 XDrawString (dpy, window, gc,
238 (x * char_width) + hspace + xshift,
239 (y * line_height) + vspace + font->ascent + yshift,
241 if (xshift == 0 && yshift == 0 && (0 == (random() & 3000)))
250 if ((tolower(c) != tolower(*s))
251 ? (0 == (random() % 10)) /* backup to correct */
252 : (0 == (random() % 400))) /* fail to advance */
257 if (delay) usleep (0xFFFF & (delay + (random() % (delay * 10))));
264 if (0 == random() % 200)
266 if (random() & 1 && s != source)
267 s--; /* duplicate character */
269 s++; /* skip character */
275 caps = (0 == random() % 40); /* capitalize sentence */
277 if (0 == (random() % 10) || /* randomly break paragraph */
279 ((0 == (random() % 10)) || sentences > 20)))
285 if (random() & 1) /* mode=0 50% of the time */
288 mode = (0xFF & (random() % 5));
290 if (0 == (random() % 2)) /* re-pick margins */
292 left = 0xFF & (random() % (columns / 3));
293 right = columns - (0xFF & (random() % (columns / 3)));
295 if (0 == random() % 3) /* sometimes be wide */
296 right = left + ((right - left) / 2);
299 if (right - left <= 10) /* introduce sanity */
305 if (right - left > 50) /* if wide, shrink and move */
307 left += (0xFF & (random() % ((columns - 50) + 1)));
308 right = left + (0xFF & ((random() % 40) + 10));
318 left -= (right - columns);
328 if (0 == random() % 3)
329 usleep(0xFFFFFF & ((random() % (delay * 5)) + 1));
332 usleep(0xFFFFFF & ((random() % (delay * 15)) + 1));
336 (0 == (random() % 1000)) &&
340 int n = random() & 3;
342 for (i = 0; i < n; i++)
344 /* See also http://catalog.com/hopkins/unix-haters/login.html */
346 "NFS server overlook not responding, still trying...";
347 const char *n2 = "NFS server overlook ok.";
350 XDrawString (dpy, window, gc,
351 (x * char_width) + hspace,
352 (y * line_height) + vspace + font->ascent,
355 if (x >= columns) x = 0, y++;
362 XDrawString (dpy, window, gc,
363 (x * char_width) + hspace,
364 (y * line_height) + vspace + font->ascent,
367 if (x >= columns) x = 0, y++;
375 screenhack_handle_events (dpy);