summaryrefslogtreecommitdiff
path: root/app/xlockmore/modes/matrix.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 11:09:41 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 11:09:41 +0000
commit95c2d1cbda23a41cdf6e63520c7f0b825e63dd5b (patch)
tree06d3ffa4312e568c4157f69fe1bddaddec9bc497 /app/xlockmore/modes/matrix.c
parent3928433848e2d6a9356f3d438a14b32a4f87f660 (diff)
Importing xlockmore 5.22
Diffstat (limited to 'app/xlockmore/modes/matrix.c')
-rw-r--r--app/xlockmore/modes/matrix.c783
1 files changed, 783 insertions, 0 deletions
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 <X11/Intrinsic.h>
+#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 <X11/Intrinsic.h>
+#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 <speed> pixels,
+ * then fill only the top <speed> 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 <speed> 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 */