784 lines
30 KiB
C
784 lines
30 KiB
C
|
/* -*- 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 */
|