From 95c2d1cbda23a41cdf6e63520c7f0b825e63dd5b Mon Sep 17 00:00:00 2001 From: Matthieu Herrb Date: Sun, 26 Nov 2006 11:09:41 +0000 Subject: Importing xlockmore 5.22 --- app/xlockmore/modes/matrix.c | 783 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 783 insertions(+) create mode 100644 app/xlockmore/modes/matrix.c (limited to 'app/xlockmore/modes/matrix.c') diff --git a/app/xlockmore/modes/matrix.c b/app/xlockmore/modes/matrix.c new file mode 100644 index 000000000..7e4bfab78 --- /dev/null +++ b/app/xlockmore/modes/matrix.c @@ -0,0 +1,783 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* matrix --- screensaver inspired by the 1999 sci-fi flick "The Matrix" */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)matrix.c 5.00 2000/11/01 xlockmore"; +#endif + +/* Matrix-style screensaver + * + * Author: Erik O'Shaughnessy (eriko@xenolab.com) 20 Apr 1999 + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 23-Jul-1999: Unleashed on an unsuspecting world + * 29-Jun-1999: More hacking by Jeremy Buhler (jbuhler@cs.washington.edu) + * - fix memory-related bugs found by xlock maintainer + * - properly reinitialize screen with new size when init() + * is called multiple times + * - reinstate multiple final characters (suggested by + * Joan Touzet) + * - reduce delay to 1 ms (provisionally) + * - decouple pixmap height from screen height, to permit + * less memory use and shorter, more frequent updates + * (for smoother scrolling on slow boxes, but nothing + * will help if the machine is busy. Also restores + * broken display on very small windows). + * - nevertheless, certain display parameters such as the + * interval between column speed updates should depend on + * the screen height -- enforce this at runtime. + * - fix column spacing to use entire window + * - remove redundant size fields from matrix_t and column_t + * structures -- rely on character size and window size + * instead. + * - consistently use PICK_MATRIX() instead of passing + * mp as a parameter whenever the active screen is + * implicitly required. + * 27-Jun-1999: Overhauled by Jeremy Buhler (jbuhler@cs.washington.edu) + * - use screen-to-screen copies as much as possible + * - get by with a single pixmap per column instead of two + * - try to optimize draw_matrix() and new_column() as much + * as humanly possible + * - fixed double-freeing in release_matrix() + * - increased delay to 10 ms to prevent hyperfast scrolling + * - minor cleanups; removed unused or duplicate code/data + * 26-Jun-1999: Tweaks by Jeremy Buhler (jbuhler@cs.washington.edu) + * - Use larger Katakana font with numbers + * - tweak character colors + * - change string and gap distributions for lower screen density + * - Matrix strings end with a fixed character + * - fix scrolling artifacts due to gaps between two column + * pixmaps + * - minor code cleanups to allow future parameterization + * of speed, density + * 09-Jun-1999: Tweaks by Joan Touzet to look more like the original film's + * effects + * 22-Apr-1999: Initial version + */ + +#ifdef VMS +#include "vms_x_fix.h" + +/*- + * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock. + * otherwise caddr_t is not defined correctly + */ + +#include +#endif + +#ifdef STANDALONE +#define MODE_matrix +#define PROGCLASS "Matrix" +#define HACK_INIT init_matrix +#define HACK_DRAW draw_matrix +#define matrix_opts xlockmore_opts +#define DEFAULTS "*delay: 1000\n" +#include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +#include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +ModeSpecOpt matrix_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct matrix_description = +{"matrix", "init_matrix", "draw_matrix", "release_matrix", + "refresh_matrix", "change_matrix", (char *) NULL, &matrix_opts, + 1000, 1, 1, 1, 64, 1.0, "", + "Shows the Matrix", 0, NULL}; +#endif + +#ifdef MODE_matrix +#ifndef VMS +#ifndef WIN32 +#include +#endif /* WIN32 */ +#endif + +/* + * state associated with a single column of the waterfall display + */ +typedef struct { + int yPtr; /* current offset relative to pixmap origin */ + Pixmap pixmap; + + int strLen; /* remaining length of current string */ + int gapLen; /* remaining length of current gap */ + Bool endChar; /* is the next char an ending char? */ + + int speed; /* pixels downward per update */ + int nextSpeedUpdate; /* time until next change in speed */ + +} column_t; + + +/* + * Matrix display parameters associated with a particular X screen + */ +typedef struct { + column_t *columns; /* columns of the Matrix display */ + int num_cols; /* number of columns of Matrix data + * (depends on screen width) */ + + int charsPerPixmap; /* height of column pixmaps in characters + * (depends on screen height) */ + + int pixmapHeight; /* height of column pixmaps in pixels + * (depends on screen height) */ + + int speedUpdateInterval; /* number of characters or spaces that + * must be written to column pixmap before + * the column speed is changed + * (depends on screen height) */ + + Pixmap kana[2]; /* pixmap containing katakana + * [0] is fg on bg + * [1] is bold on bg */ + + Pixel fg; /* foreground */ + Pixel bg; /* background */ + Pixel bold; /* standout foreground color */ +} matrix_t; + + +/* These Katakana font bitmaps were taken from the file 12x24rk.bdf + * distributed with XFree86 3.3.3. The numbers were taken from the file + * 10x20.bdf, since the 12x24rk numbers were rather large compared to + * the other characters. + */ +#define katakana_cell_width 12 +#define katakana_cell_height 24 +#define katakana_num_cells 65 + +#define katakana_width 780 +#define katakana_height 24 + +static const unsigned char katakana_bits[] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff, + 0xff,0xfc,0xff,0xff,0xff,0xef,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xff,0xff, + 0x7f,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xef,0x9f,0xff,0xff,0x9f,0xff,0xfd,0xef,0xff,0xf9,0xcf,0xff, + 0xff,0x7f,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xfe,0xfb,0xfc, + 0xfc,0x9f,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xfc,0xff,0x3f,0xf8,0xcf,0xff,0xe7,0xff,0xff,0xfe,0xff,0xff,0xff,0x03,0x3c, + 0xc7,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0x9f,0xff,0xff, + 0xbf,0xff,0xf9,0xcf,0xff,0xf9,0xcf,0xff,0xff,0x73,0x3e,0xff,0x7b,0xfc,0xfe, + 0xfb,0xfc,0xfd,0xff,0xdc,0x9c,0x03,0xfc,0xfc,0x9f,0xff,0xff,0xff,0xff,0xf9, + 0x7f,0xfe,0xfb,0xff,0xff,0xdf,0xff,0xff,0xf9,0xff,0x7f,0xf0,0x9f,0xff,0xef, + 0xff,0xff,0xfe,0xff,0x9f,0x9f,0x07,0x7c,0xcf,0x9f,0xff,0xff,0xff,0x9f,0xdf, + 0xff,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x01,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1f,0xf8,0xcf,0x9f,0xff,0xff,0x3f,0xff,0xf9,0xdf,0xff,0xf9,0xcf, + 0x9f,0xdf,0x67,0x7e,0xff,0x03,0xf8,0xfc,0xfb,0xf9,0xcd,0x0f,0xdc,0x9d,0x07, + 0xff,0xfc,0xbf,0xff,0xff,0x1b,0xfc,0xf9,0xff,0x7c,0xf2,0xf9,0xdf,0x80,0xff, + 0xff,0xf9,0xff,0xff,0xc3,0x9f,0xff,0xcf,0xff,0xfe,0xfe,0xff,0x3f,0x80,0xff, + 0x7f,0xcf,0x93,0xbf,0xff,0xff,0x1f,0x80,0xf9,0x0f,0x9f,0xff,0xf9,0x0f,0xff, + 0xf0,0xff,0x3e,0xc0,0x0f,0x3f,0xc0,0x0f,0xff,0xf0,0x01,0xf8,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x05,0xf8,0xcf,0x9d,0xbd, + 0xc3,0x3f,0xff,0xf9,0xdf,0xff,0xdd,0xef,0x3f,0x80,0x67,0x7e,0xfe,0x87,0xfd, + 0xfc,0xf3,0xfd,0xc1,0x03,0x9f,0x9d,0xff,0xff,0xfc,0xbf,0xff,0xff,0x03,0xf8, + 0xef,0xff,0xfc,0xf4,0xf3,0x1f,0x80,0xcf,0xff,0xf9,0x3f,0xf8,0x8f,0x9f,0xff, + 0xcf,0x03,0xfc,0xfe,0xff,0x3f,0x80,0xff,0x7f,0xcf,0x87,0x3f,0xff,0xfb,0x3d, + 0x80,0xfb,0x0f,0x0f,0xff,0xf8,0x67,0x7e,0xe6,0x7f,0x3e,0xff,0x67,0xfe,0xcf, + 0x67,0x7e,0xe6,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xc1,0xf9,0xe7,0x01,0x38,0xc0,0x3f,0xff,0x81,0xdf,0xff,0x80, + 0xef,0x3f,0x80,0x67,0xfe,0xfe,0xff,0xfd,0xfc,0xf7,0xfd,0xc0,0xa1,0xbf,0x99, + 0xff,0xff,0xfc,0xbf,0xff,0xff,0xc7,0xfd,0xe1,0xff,0xfc,0xe4,0xfb,0x3f,0xcf, + 0xcf,0xdf,0x01,0x01,0xf0,0x9f,0xdf,0xff,0xcf,0x03,0xff,0x0c,0x7f,0xfe,0x9f, + 0xff,0x7f,0xcf,0x97,0x3f,0xff,0x03,0xbc,0xcf,0xf3,0x0f,0x67,0x7e,0xf8,0xf3, + 0x3c,0xcf,0x3f,0x3e,0xff,0xf3,0xfe,0xcf,0xf3,0x3c,0xcf,0xff,0xfc,0xff,0x7f, + 0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfb,0xfc,0xe7,0x03, + 0x3c,0xf8,0x3f,0xdf,0x80,0x1f,0xfc,0x80,0x67,0xf0,0xdf,0x67,0xfe,0x7f,0xff, + 0xfc,0xbc,0xe7,0xfc,0xce,0xbf,0x3f,0x99,0xff,0xff,0xfc,0xbf,0x3f,0xc0,0xff, + 0xdd,0xe0,0xff,0xfe,0xee,0xfb,0xff,0xcf,0x87,0x1f,0x00,0x81,0xf1,0xff,0xdf, + 0xff,0xcf,0xdf,0xff,0x00,0x01,0xfe,0x9f,0xff,0x7f,0xcf,0x97,0x3f,0xff,0x03, + 0xbc,0xcf,0xf7,0x0f,0x67,0x3e,0xf9,0xf3,0x3c,0xcf,0x1f,0x3e,0xff,0xf3,0xff, + 0xe7,0xf3,0x3c,0xcf,0xff,0xfc,0xc0,0x7f,0xfe,0xf9,0xff,0xff,0xfb,0xef,0xff, + 0xff,0xff,0xbf,0xfc,0x5f,0xfe,0xf3,0xfb,0xfc,0xf9,0x3d,0x10,0x98,0x05,0xfc, + 0xde,0x07,0xf0,0xdf,0x67,0xd8,0x3f,0xff,0xfe,0x00,0xe7,0x7c,0xee,0xbf,0x3f, + 0x99,0x04,0xf0,0xfc,0x3d,0x38,0xe0,0xff,0x1c,0xe4,0x7f,0xfe,0xce,0xfb,0xfc, + 0xcf,0xa7,0x1f,0xf8,0xf9,0x39,0xfe,0xcf,0x7f,0xee,0xdf,0xff,0xa0,0x03,0xfe, + 0x9f,0x0c,0x78,0xcf,0x97,0x3f,0x7f,0xf3,0xbc,0xcf,0xe7,0x0b,0xf3,0xfc,0xf9, + 0xff,0xfc,0xcf,0x4f,0x3e,0xff,0xf3,0xff,0xe7,0xf3,0x3c,0xcf,0xff,0x3c,0xc0, + 0xff,0xfe,0xf9,0xff,0xff,0xf3,0xcf,0xff,0xff,0xff,0xbc,0xcd,0x1f,0xfe,0xf3, + 0xfb,0xfc,0xf9,0x01,0x10,0x99,0x81,0x7f,0xce,0x07,0xff,0xdf,0x01,0x90,0xbf, + 0xff,0x6e,0x80,0xe7,0x7c,0xe6,0xbf,0x3f,0x99,0x01,0xf0,0xf0,0x01,0xf0,0xff, + 0xff,0x3c,0xf3,0x7f,0x7e,0xce,0x7b,0xfc,0xcf,0x37,0xff,0xf9,0xff,0x7c,0xf8, + 0xcf,0xff,0xec,0xdf,0x1f,0x9c,0x7f,0xfe,0x9f,0x01,0x78,0xcf,0x97,0x3f,0x3f, + 0xf3,0xbc,0xcf,0xe7,0x0b,0xf3,0xfc,0xf9,0xff,0xfc,0xe7,0x67,0x3e,0xf1,0x13, + 0xff,0xf3,0x67,0x3e,0xcf,0x03,0x3c,0xce,0x7f,0xbe,0xe9,0xff,0xff,0xf3,0xcf, + 0xfe,0xff,0x03,0x3c,0xc9,0x1f,0xff,0xf9,0xfb,0xfc,0xf9,0x01,0xff,0x99,0x9b, + 0x7f,0xef,0x33,0xff,0xdf,0x01,0x3e,0x9f,0x7f,0x0e,0xdc,0xe7,0x3e,0xe6,0x3f, + 0x38,0xdb,0xb9,0xff,0xe0,0x81,0xff,0xff,0xe7,0xfe,0xf3,0x7f,0x7f,0xde,0x1b, + 0xff,0xcf,0x73,0x7f,0xf1,0xff,0xfc,0xf0,0x6f,0xff,0xe0,0xdf,0x1f,0xdc,0x7f, + 0xfe,0x9f,0xf1,0x79,0xcf,0x97,0x3f,0xbf,0xf3,0xbc,0xcf,0xe7,0x09,0xf3,0xfc, + 0xf9,0x7f,0xfe,0xf1,0x73,0x3e,0xe6,0x63,0xfe,0xf3,0x0f,0x7f,0xc6,0x03,0xfc, + 0xef,0x3f,0x3f,0xe0,0xff,0xff,0xf3,0x0f,0xfc,0xff,0x07,0x7c,0xcb,0x9f,0xff, + 0xf9,0xfb,0xfc,0xf9,0x3f,0xff,0x9d,0x9f,0x3f,0xef,0x3b,0xff,0xdf,0x67,0x7e, + 0xde,0x7f,0x9f,0xcc,0xff,0xbe,0xf4,0x05,0xf8,0xcf,0xbf,0xff,0xc4,0x9f,0xff, + 0xff,0x4f,0xfe,0xf9,0x3f,0x7f,0x9e,0x83,0xff,0xcf,0x7b,0x7e,0xe9,0x7f,0xfe, + 0xe3,0x6f,0xff,0xf1,0x1f,0x98,0xdd,0x7f,0xfe,0x9f,0xff,0x79,0xcf,0x97,0x37, + 0x9f,0xf3,0xbc,0xcf,0xff,0x0d,0xf3,0xfc,0xf9,0x1f,0xff,0xe7,0x73,0xfe,0xcf, + 0xf3,0xfc,0xf9,0x67,0xfe,0xc8,0xff,0xfc,0xe1,0x3f,0x3f,0xe0,0x03,0x3e,0xc0, + 0x0f,0xfc,0xe7,0xff,0x7c,0xcb,0x9f,0xff,0xf8,0xfb,0xfc,0xf9,0x3f,0xff,0x9d, + 0x9f,0xbf,0xe7,0x39,0xff,0xdf,0x67,0x7e,0xce,0x3f,0xff,0xec,0x7f,0x9e,0xf0, + 0x81,0xff,0xcf,0xbf,0xff,0xcc,0x9f,0xff,0xff,0x4f,0xff,0xf1,0x3f,0x7f,0x9f, + 0xc3,0xff,0xe7,0xf9,0x7e,0xc9,0x7b,0xfe,0xc7,0x67,0xfe,0xf3,0x04,0xf8,0xcd, + 0x7f,0x3e,0x80,0xff,0x7c,0xcf,0x97,0x33,0xdf,0xf3,0xbc,0xcf,0xff,0x0c,0xf3, + 0xfc,0xf9,0xcf,0xff,0xcf,0x03,0xfc,0xcf,0xf3,0xfc,0xf9,0xf3,0xfc,0xcf,0x7f, + 0xfe,0xf1,0x1f,0x3f,0xef,0x03,0x3e,0xc0,0xc1,0x7c,0xe0,0xff,0x7c,0xca,0x9f, + 0x7f,0xfa,0xfb,0xfc,0xf9,0x1f,0xff,0x9d,0x9f,0x90,0xf7,0x3d,0xff,0xdf,0x67, + 0xfe,0xef,0xbf,0xff,0xe4,0x7f,0xdf,0xf1,0x99,0xff,0xcf,0xbf,0xff,0xdc,0x9f, + 0xff,0xff,0x1f,0xff,0xe0,0xbf,0x7f,0xbf,0xfb,0xff,0xe7,0xfd,0x3c,0xd9,0x73, + 0xff,0xcf,0xe7,0xfe,0xe7,0xc1,0xff,0xed,0x7f,0x7e,0xc0,0xff,0x7c,0xcf,0x97, + 0x3b,0xcf,0xf3,0xfc,0xcf,0xff,0x0e,0x67,0xfe,0xf9,0xe7,0x3f,0xcf,0x7f,0xfe, + 0xcf,0xf3,0xfc,0xfc,0xf3,0xfc,0xcf,0x7f,0xfe,0xf9,0x0f,0x3f,0xef,0x9f,0xff, + 0xf1,0xc3,0x7e,0xe0,0xff,0xfc,0xee,0x9f,0x3f,0xfb,0xfb,0xfe,0xf9,0x5f,0xff, + 0x9d,0x0f,0xd0,0xf7,0x3d,0xff,0xcf,0x67,0xfe,0xe7,0x1f,0xfe,0xf4,0x3f,0xff, + 0xf3,0x9f,0xff,0xef,0x9f,0xff,0xfc,0x9f,0xff,0xff,0x1f,0x7f,0xc0,0x9f,0x3f, + 0xbf,0xfb,0xff,0xf7,0xff,0x3d,0x99,0x27,0xff,0xff,0xe7,0xfc,0xe3,0xd9,0xff, + 0xe5,0x7f,0xff,0xdf,0x7f,0x7e,0xcf,0x97,0x39,0xef,0xf3,0xfc,0xef,0x7f,0x0e, + 0x67,0xfe,0xf9,0xf3,0x3f,0xcf,0x7f,0x3e,0xcf,0xf3,0xfc,0xfc,0xf3,0x7c,0xcf, + 0x7f,0xfe,0xf9,0x0f,0x3f,0xef,0x9f,0xff,0xf1,0x5f,0xfe,0xe7,0x07,0xfc,0xef, + 0x9f,0x9f,0xfb,0x7b,0xfe,0xf9,0x4f,0xff,0x9c,0x00,0xff,0xf3,0xbf,0xff,0xcf, + 0x67,0xfe,0xf7,0x5f,0xfe,0xf0,0xbf,0xff,0xf1,0x9f,0xff,0xe7,0x9f,0xff,0xfc, + 0x9f,0xff,0xff,0x1f,0x3e,0x88,0xdf,0x3f,0xbf,0xfb,0xff,0xf3,0xff,0xb9,0x99, + 0x8f,0xff,0xff,0xf7,0xfc,0xcb,0xdf,0xff,0xf1,0x7f,0xff,0xdf,0x7f,0x7e,0xef, + 0x97,0x3d,0xe7,0xf3,0xfc,0xe7,0x7f,0x0f,0x0f,0xff,0xf9,0xf3,0x7f,0xe6,0x7f, + 0x7e,0xe6,0x67,0x7e,0xfe,0x67,0x7e,0xe6,0x3f,0xff,0xfd,0x27,0x3f,0xe7,0x9f, + 0xff,0xf0,0x5f,0xff,0xe7,0x07,0xfe,0xe7,0xdf,0xdf,0xfb,0x7f,0xfe,0xb9,0x6f, + 0xff,0xdc,0xa1,0xff,0xfb,0xbf,0xff,0xcf,0x67,0xfe,0xf3,0xcf,0xfc,0xfc,0x9f, + 0xff,0xf5,0x9f,0xff,0xf7,0xdf,0xff,0xfc,0xdf,0xff,0xff,0xdf,0x1e,0x99,0xcf, + 0xbf,0xbf,0xfb,0xff,0xfb,0xff,0x99,0xb9,0x9f,0x3f,0xfe,0xf3,0xf9,0xd9,0xdf, + 0xff,0xf9,0x7f,0xff,0xdf,0x3f,0xff,0xe7,0x97,0x3c,0xf7,0xf3,0xfc,0xe7,0x3f, + 0x0f,0x9f,0x3f,0xc0,0x03,0xfc,0xf0,0x7f,0xfe,0xf0,0x0f,0x7f,0xfe,0x0f,0xff, + 0xf0,0x3f,0xff,0xfd,0x37,0xff,0xf7,0x9f,0xff,0xf2,0xdf,0xff,0xe7,0xff,0xfe, + 0xf7,0xcf,0xff,0xfb,0x3f,0xcf,0x00,0x67,0xff,0xde,0xbf,0xff,0xf9,0x9f,0x1f, + 0xc0,0x67,0xff,0xf9,0xef,0xfd,0xfc,0xdf,0xff,0xfc,0xdf,0xff,0xf3,0xcf,0xff, + 0xfc,0xdf,0xdf,0x00,0xcf,0x8c,0x39,0xef,0xbf,0xbf,0xfb,0xff,0xf9,0xff,0xc3, + 0xb9,0x3f,0x3f,0xf8,0x33,0xf8,0x9d,0xdf,0xff,0xf9,0x7c,0xff,0xdf,0xbf,0xff, + 0xe7,0x93,0x3e,0xf3,0x03,0xfc,0xf7,0x9f,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9f,0xff,0xfd,0x3f,0xff,0xf3, + 0x9f,0x7f,0xf2,0xdf,0xff,0xe7,0xff,0xfe,0xf3,0xef,0xff,0xfb,0x3f,0x1f,0x00, + 0x77,0x7f,0xda,0xbf,0xff,0xfc,0xdf,0x3f,0xc0,0x7f,0xbf,0xfc,0xe7,0xf9,0xfc, + 0xcf,0xff,0xfe,0xcf,0xff,0xf9,0xef,0xff,0xfc,0xcf,0x1f,0x00,0xef,0xfd,0x39, + 0xe7,0x9f,0x3f,0xfb,0xff,0xfd,0xff,0x43,0xb8,0x3f,0xff,0xf1,0x01,0xf8,0xfc, + 0xdf,0xff,0xfb,0x01,0xf0,0xdf,0x9f,0xff,0xe7,0x13,0x3e,0xf9,0x03,0xfc,0xf3, + 0x8f,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x9f,0xff,0xfc,0x3f,0xff,0xfb,0x9f,0x7f,0xf3,0x9f,0xff,0xe7,0xff, + 0xfe,0xfb,0xe7,0xff,0xfb,0x9f,0x1f,0xff,0x53,0x7f,0xc3,0xbf,0xff,0xfc,0xcf, + 0xff,0xff,0x3f,0x3f,0xfc,0xf3,0xf9,0xfc,0xef,0x7f,0xfe,0xef,0xff,0xf9,0xe7, + 0xff,0xfc,0xef,0x1f,0xff,0xe7,0xf9,0xf9,0xf7,0xdf,0x3f,0xfb,0xff,0xfc,0xff, + 0xf3,0xf8,0x7f,0xfe,0xe3,0xc1,0xf3,0xfe,0xdf,0xff,0xfb,0x01,0x10,0x80,0xdf, + 0xff,0xf7,0x1b,0x3e,0xfd,0xf3,0xff,0xfb,0xcb,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0xff,0xfe,0x3f,0xff, + 0xf9,0x9f,0x3f,0xf3,0x9f,0xff,0xe7,0xff,0xfe,0xf9,0xf7,0xff,0xfb,0x9f,0xff, + 0xff,0x19,0x3f,0xe7,0xbf,0x7f,0xfe,0xef,0xff,0xff,0xbf,0x3f,0xfe,0xf9,0xfb, + 0x01,0xe7,0x3f,0xff,0xe7,0xff,0xfc,0xf3,0xff,0xfc,0xe7,0xff,0xff,0xf3,0xf3, + 0xf9,0xf3,0xcf,0xff,0xf3,0xf9,0xfe,0xff,0xff,0xf8,0x7f,0xfe,0xc7,0xf9,0x73, + 0xfe,0x1f,0xf0,0xfb,0xff,0x1f,0x80,0xcf,0xff,0xf3,0x19,0x3f,0xfc,0xf3,0xff, + 0xf9,0xe3,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xe7,0x7f,0xfe,0x3f,0xff,0xfd,0x03,0xb8,0xf1,0x9f,0x1f,0xc0, + 0x03,0xfc,0xfc,0xf3,0xff,0xfb,0xcf,0xff,0xff,0x19,0x9f,0xe7,0xbf,0x3f,0xff, + 0xe7,0xff,0xff,0x9f,0x7f,0xfe,0xf9,0xff,0x01,0xf7,0x1f,0xff,0xf3,0x7f,0xfe, + 0xf3,0xff,0xfc,0xf3,0xff,0xff,0xf9,0xf3,0xf9,0xfb,0xef,0xff,0x03,0x78,0xfe, + 0xff,0xff,0xf9,0xff,0xff,0xcf,0xff,0x33,0xff,0x1f,0xf0,0xfb,0xff,0xff,0xff, + 0xe7,0xff,0xf8,0x1d,0x3f,0xfe,0xff,0xff,0xfd,0xe3,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0x7f,0xff,0x3f, + 0xff,0xfc,0x03,0xf8,0xfb,0x9f,0x1f,0x80,0x07,0x7c,0xfc,0xfb,0xff,0xfb,0xe7, + 0xff,0xff,0x3c,0x9f,0xff,0xbf,0x9f,0xff,0xf7,0xff,0xff,0xcf,0xff,0xff,0xff, + 0xff,0xff,0xff,0x9f,0xff,0xf3,0x3f,0xff,0xf9,0xff,0xfc,0xff,0xff,0xff,0xf9, + 0xff,0xf9,0xf9,0xff,0xff,0x07,0x38,0xff,0xff,0xff,0xfd,0xff,0xff,0xdf,0xff, + 0x33,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xf3,0xff,0xfc,0xbd,0x7f,0xff,0xff, + 0xff,0xfc,0xf3,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f +}; + +#define PIXMAP_WIDTH katakana_cell_width + +#define PICK_MATRIX(mi) (&matrix[MI_SCREEN(mi)]) +#define MATRIX_RANDOM(min, max) (NRAND((max) - (min)) + (min)) + +/************************************************************************* + * CONFIGURABLE DISPLAY OPTIONS + *************************************************************************/ + +/* Defining RANDOMIZE_COLUMNS causes each column pixmap to be regenerated + * after scrolling off the screen rather than just repeating + * infinitely. This is a better effect but uses more CPU and will + * cause update hesitations (especially on multi-headed machines or + * slower hardware). However, it can be done in relatively little memory + * because the pixmaps can be kept short and regenerated frequently. + * + * Undefining RANDOMIZE_COLUMNS will cause the pixmaps to be generated only + * once, which should save a lot of horsepower for whatever else your machine + * might be doing. However, the tradeoff is that the pixmaps are longer + * to avoid a really boring display. + */ +#define RANDOMIZE_COLUMNS + +/* + * Speed at which columns move, in pixels per screen update. + * Must be <= katakana_cell_height; interesting values range + * from one (crawl) to about fifteen (zoom!). + * (Note: the distribution of speeds implemented in new_column() + * is slightly biased against very slow scrolling.) + */ +#define MATRIX_SPEED MATRIX_RANDOM(1, 8) + +/* + * Number of characters in each generated string + * (Note: this is not limited by the pixmap size!) + */ +#define MATRIX_STRLEN MATRIX_RANDOM(15, 20) + +/* + * Number of character-heights in each generated gap + * (Note: this is not limited by the pixmap size!) + */ +#define MATRIX_GAPLEN MATRIX_RANDOM(2, 6) + +/* colors used for Matrix characters */ +#define BRIGHTGREEN (28 * MI_NPIXELS(mi) / 64) +#define GREEN (26 * MI_NPIXELS(mi) / 64) + +/*************************************************************************/ + +/* + * state of the Matrix + */ +static matrix_t *matrix = (matrix_t *) NULL; + + +/* NAME: new_column + * + * FUNCTION: clears and generates a pixmap of "matrix" data + */ + +static void new_column(const ModeInfo *mi, column_t *c) +{ + matrix_t *mp = PICK_MATRIX(mi); + int currChar; + + /* + * clear the pixmap to get rid of previous data or initialize + */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), mp->bg); + XFillRectangle(MI_DISPLAY(mi), (Drawable) c->pixmap, MI_GC(mi), + 0, 0, PIXMAP_WIDTH, mp->pixmapHeight); + + /* + * Write characters into the column pixmap, starting at the + * bottom and moving upwards. Decrement the string length, gap length, + * and next-speed-update timers for the column and reinitialize them + * if necessary. + */ + for (currChar = mp->charsPerPixmap - 1; currChar >= 0; currChar--) { + if (c->nextSpeedUpdate-- == 0) { + c->speed = MATRIX_SPEED; + c->nextSpeedUpdate = mp->speedUpdateInterval; + + /* tweak to prevent really slow columns from remaining slow */ + if (c->speed <= 2) + c->nextSpeedUpdate /= 2; + } + + if (c->gapLen > 0) { + c->gapLen--; + continue; + } else if (c->strLen == 0) { + /* + * generate a gap of random length in the string, followed + * by a random number of characters. Set the endChar flag + * to indicate the end of a new string. + */ + c->gapLen = MATRIX_GAPLEN; + c->strLen = MATRIX_STRLEN; + c->endChar = True; + } else { + Pixmap src; + int kOffset; + + if (c->endChar) { + src = mp->kana[1]; /* a bold, non-numeric character */ + kOffset = MATRIX_RANDOM(10, katakana_num_cells); + c->endChar = False; + } else { /* inside a string - kana or number */ + src = mp->kana[0]; + kOffset = MATRIX_RANDOM(0, katakana_num_cells); + } + + XCopyArea(MI_DISPLAY(mi), (Drawable) src, + (Drawable) c->pixmap, MI_GC(mi), + kOffset * katakana_cell_width, 0, + katakana_cell_width, katakana_cell_height, + 0, currChar * katakana_cell_height); + + c->strLen--; + } + } +} + +/* NAME: free_matrix + * + * FUNCTION: delete the data associated with a single screen. Be careful + * not to do spurious free()s of nonexistent data, and to nullify all + * freed pointers that might be reused past the end of this call. + */ +static void +free_matrix(Display *display, matrix_t *mp) +{ + if (mp->columns != NULL) { + int c; + + for (c = 0; c < mp->num_cols; c++) { + if (mp->columns[c].pixmap) + XFreePixmap(display, mp->columns[c].pixmap); + } + + free(mp->columns); + mp->columns = (column_t *) NULL; + } + + if (mp->kana[0]) { + XFreePixmap(display, mp->kana[0]); + mp->kana[0] = None; + } + + if (mp->kana[1]) { + XFreePixmap(display, mp->kana[1]); + mp->kana[1] = None; + } +} + +/* NAME: setup_matrix() + * + * FUNCTION: Initialize the Matrix state for the current screen. + * Based on the width and height of the display, + * allocate and initialize column data structures. + */ + +static void setup_matrix(const ModeInfo *mi) +{ + matrix_t *mp = PICK_MATRIX(mi); + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int c; + + /* screen may have changed size/depth/who-knows-what */ + free_matrix(display, mp); + + if (MI_NPIXELS(mi) > 2) { + mp->fg = MI_PIXEL(mi, GREEN); + mp->bold = MI_PIXEL(mi, BRIGHTGREEN); + } else + mp->fg = mp->bold = MI_WHITE_PIXEL(mi); + + mp->bg = MI_BLACK_PIXEL(mi); + + if ((mp->kana[0] = XCreatePixmapFromBitmapData(display, window, + (char *) katakana_bits, katakana_width, katakana_height, + mp->bg, mp->fg, MI_DEPTH(mi))) == None) { + free_matrix(display, mp); + return; + } + + if ((mp->kana[1] = XCreatePixmapFromBitmapData(display, window, + (char *) katakana_bits, katakana_width, katakana_height, + mp->bg, mp->bold, MI_DEPTH(mi))) == None) { + free_matrix(display, mp); + return; + } + + /* + * Using the width of the kana font, determine how many + * columns can fit across the current screen (with a little + * padding). + */ + mp->num_cols = (int) (MI_WIDTH(mi) / (1.3 * katakana_cell_width)); + + if ((mp->columns = (column_t *) calloc(mp->num_cols, + sizeof(column_t))) == NULL) { + free_matrix(display, mp); + return; + } + + /* + * If we're randomizing columns, keep the column pixmap height small + * to save memory and minimize time for each column update. Otherwise, + * make the height large to maximize variety without updating the pixmaps. + */ +#ifdef RANDOMIZE_COLUMNS + mp->charsPerPixmap = MI_HEIGHT(mi) / (4 * katakana_cell_height); +#else + mp->charsPerPixmap = MI_HEIGHT(mi) / katakana_cell_height; +#endif + + if (!mp->charsPerPixmap) /* sanity check for tiny windows */ + mp->charsPerPixmap = 1; + + mp->pixmapHeight = mp->charsPerPixmap * katakana_cell_height; + + for (c = 0; c < mp->num_cols; c++) + if ((mp->columns[c].pixmap = XCreatePixmap(display, window, + PIXMAP_WIDTH, mp->pixmapHeight, MI_DEPTH(mi))) == None) { + free_matrix(display, mp); + return; + } + + /* Change the speed of a column after it's covered half the screen */ + mp->speedUpdateInterval = MI_HEIGHT(mi) / (2 * katakana_cell_height); + + /* initialize the column data */ + for (c = 0; c < mp->num_cols; c++) { + column_t *column = &(mp->columns[c]); + + column->yPtr = mp->pixmapHeight; + + column->nextSpeedUpdate = 0; /* will generate new speed */ + column->strLen = 0; /* will generate new string */ + + new_column(mi, column); + } +} + + + +/* NAME: init_matrix + * + * FUNCTION: allocate space for global matrix array + * initialize colors + * initialize dimensions + * allocate a pair of pixmaps containing character set + * (0 is green on black, 1 is bold on black) + * create columns of "matrix" data + */ + +void init_matrix(ModeInfo *mi) +{ + if (matrix == NULL) { + if ((matrix = (matrix_t *) calloc(MI_NUM_SCREENS(mi), + sizeof(matrix_t))) == NULL) + return; + } + + /* don't want any exposure events from XCopyArea */ + XSetGraphicsExposures(MI_DISPLAY(mi), MI_GC(mi), False); + + MI_CLEARWINDOW(mi); + setup_matrix(mi); +} + + +/* NAME: draw_matrix + * + * FUNCTION: update the matrix waterfall display + */ +void draw_matrix(ModeInfo *mi) +{ + double xDistance; + int i; + matrix_t *mp; + + if (matrix == NULL) + return; + mp = PICK_MATRIX(mi); + if (mp->columns == NULL) + return; + + MI_IS_DRAWN(mi) = True; + xDistance = (double) MI_WIDTH(mi) / (double) mp->num_cols; + + /* + * THEORY OF OPERATION + * + * Screen-to-screen blits occur within the video RAM and are usually + * hardware-accelerated, while pixmap-to-screen blits require DMA + * between main memory and vRAM. To make updates as fast as possible, + * we scroll down the screen contents in each column by pixels, + * then fill only the top rows of the column with pixmap data. + * + * There are two tricky bits to this scheme. First, we must keep a + * pointer (yPtr) to the pixmap contents which should be used to + * fill in the top rows of each column. yPtr is decremented on each + * call to draw_matrix(); when it reaches zero, the column's pixmap + * may be redrawn to generate new characters for the column. + * + * Second, the scroll increment corresponding to need not be a + * multiple of the pixmap height. We must special-case the handling of the + * last decrement that makes yPtr <= 0 to ensure that the last few pixels + * of the old data AND the first few pixels of the new data are both drawn. + * It turns out to be quite reasonable to do the pixmap update inline, + * between drawing the last few old pixels and the first few new pixels. + * Hence, we can achieve smooth scrolling with only one pixmap per column. + */ + + for (i = 0; i < mp->num_cols; i++) { + column_t *c = &(mp->columns[i]); + int xOffset = (int) (i * xDistance); + int yDelta = c->speed; + + /* screen-screen blit takes care of most of the column */ + XCopyArea(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_WINDOW(mi), MI_GC(mi), + xOffset, 0, + PIXMAP_WIDTH, MI_HEIGHT(mi) - yDelta, + xOffset, yDelta); + + c->yPtr -= yDelta; + + if (c->yPtr <= 0) /* we're about to finish the current pixmap */ + { + /* exhaust the pixels in the current pixmap */ + XCopyArea(MI_DISPLAY(mi), (Drawable) c->pixmap, + MI_WINDOW(mi), MI_GC(mi), + 0, 0, + PIXMAP_WIDTH, yDelta + c->yPtr, + xOffset, -(c->yPtr)); + +#ifdef RANDOMIZE_COLUMNS + /* regenerate the column pixmap with new text */ + new_column(mi, c); +#else + /* speed is normally updated in new_column(), which isn't called, + * so take this opportunity to update the column speed. + */ + c->speed = MATRIX_SPEED; +#endif + + /* fill in the remainder of the column from the new pixmap */ + XCopyArea(MI_DISPLAY(mi), (Drawable) c->pixmap, + MI_WINDOW(mi), MI_GC(mi), + 0, mp->pixmapHeight + c->yPtr, + PIXMAP_WIDTH, -(c->yPtr), + xOffset, 0); + + c->yPtr += mp->pixmapHeight; + } + else + { + /* fill in the remainder of the column from the pixmap */ + XCopyArea(MI_DISPLAY(mi), (Drawable) c->pixmap, + MI_WINDOW(mi), MI_GC(mi), + 0, c->yPtr, + PIXMAP_WIDTH, yDelta, + xOffset, 0); + } + } +} + + +/* NAME: release_matrix + * + * FUNCTION: frees all allocated resources + */ + +void release_matrix(ModeInfo *mi) +{ + + /* If the matrix exists, free all data associated with all screens. + * free_matrix() does no harm if given nonexistent screens. + */ + if (matrix != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_matrix(MI_DISPLAY(mi), &matrix[screen]); + free(matrix); + matrix = (matrix_t *) NULL; + } +} + + +/* NAME: refresh_matrix + * + * FUNCTION: refresh the screen + */ + +void refresh_matrix(ModeInfo *mi) +{ + int c; + matrix_t *mp; + + if (matrix == NULL) + return; + mp = PICK_MATRIX(mi); + if (mp->columns == NULL) + return; + + /* We simply clear the whole window and restart the scrolling operation. + * In principle, it is possible to restore at least some of the + * column pixmap data to the screen, but it's not worth the trouble. + */ + MI_CLEARWINDOW(mi); + + for (c = 0; c < mp->num_cols; c++) + mp->columns[c].yPtr = mp->pixmapHeight; +} + + +/* NAME: change_matrix + * + * FUNCTION: resets column offsets and speeds and generates new pixmaps + */ + +void change_matrix(ModeInfo *mi) +{ + int c; + matrix_t *mp; + + if (matrix == NULL) + return; + mp = PICK_MATRIX(mi); + if (mp->columns == NULL) + return; + + MI_CLEARWINDOW(mi); + + for (c = 0; c < mp->num_cols; c++) { + column_t *column = &(mp->columns[c]); + + column->yPtr = mp->pixmapHeight; + + column->nextSpeedUpdate = 0; /* will generate new speed */ + column->strLen = 0; /* will generate new string */ + + new_column(mi, column); + } +} + +#endif /* MODE_matrix */ -- cgit v1.2.3