X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fxmatrix.c;h=1433527cadb98934f88187983c9180b880c0af45;hb=c28aecf9fc41e3a03494bacf7279745425e2fa18;hp=1a6bebf158c8b857a436e5298e4e20abd6d1ad41;hpb=8eb2873d7054e705c4e83f22d18c40946a9e2529;p=xscreensaver diff --git a/hacks/xmatrix.c b/hacks/xmatrix.c index 1a6bebf1..1433527c 100644 --- a/hacks/xmatrix.c +++ b/hacks/xmatrix.c @@ -42,11 +42,11 @@ */ #include "screenhack.h" +#include "xpm-pixmap.h" #include #include -#ifdef HAVE_XPM -# include +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) # include "images/matrix0.xpm" # include "images/matrix1.xpm" # include "images/matrix2.xpm" @@ -111,6 +111,8 @@ static unsigned char char_map[256] = { 176,177,178,195,180,181,182,183,184,185,186,187,188,189,190,191 /* 240 */ }; +#define CURSOR_GLYPH 97 + typedef enum { TRACE0, TRACE1, TRACE2, KNOCK0, KNOCK1, KNOCK2, KNOCK3, KNOCK4, KNOCK5, KNOCK6, KNOCK7, @@ -124,8 +126,10 @@ typedef struct { int grid_width, grid_height; int char_width, char_height; m_cell *cells; + m_cell *cursor; m_feeder *feeders; int nspinners; + Bool knock_knock_p; Bool small_p; Bool insert_top_p, insert_bottom_p; m_mode mode; @@ -144,47 +148,21 @@ typedef struct { static void load_images_1 (m_state *state, int which) { -#ifdef HAVE_XPM +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) if (!get_boolean_resource ("mono", "Boolean") && state->xgwa.depth > 1) { - - - XpmAttributes xpmattrs; - int result; - xpmattrs.valuemask = 0; - -# ifdef XpmCloseness - xpmattrs.valuemask |= XpmCloseness; - xpmattrs.closeness = 40000; -# endif -# ifdef XpmVisual - xpmattrs.valuemask |= XpmVisual; - xpmattrs.visual = state->xgwa.visual; -# endif -# ifdef XpmDepth - xpmattrs.valuemask |= XpmDepth; - xpmattrs.depth = state->xgwa.depth; -# endif -# ifdef XpmColormap - xpmattrs.valuemask |= XpmColormap; - xpmattrs.colormap = state->xgwa.colormap; -# endif - - result = XpmCreatePixmapFromData (state->dpy, state->window, - (which == 0 ? (state->small_p ? matrix0b_xpm : matrix0_xpm) : - which == 1 ? (state->small_p ? matrix1b_xpm : matrix1_xpm) : - (state->small_p ? matrix2b_xpm : matrix2_xpm)), - &state->images[which], 0 /* mask */, - &xpmattrs); - if (!state->images || (result != XpmSuccess && result != XpmColorError)) - state->images[which] = 0; - - state->image_width = xpmattrs.width; - state->image_height = xpmattrs.height; + char **bits = + (which == 0 ? (state->small_p ? matrix0b_xpm : matrix0_xpm) : + which == 1 ? (state->small_p ? matrix1b_xpm : matrix1_xpm) : + (state->small_p ? matrix2b_xpm : matrix2_xpm)); + + state->images[which] = + xpm_data_to_pixmap (state->dpy, state->window, bits, + &state->image_width, &state->image_height, 0); } else -#endif /* !HAVE_XPM */ +#endif /* !HAVE_XPM && !HAVE_GDK_PIXBUF */ { unsigned long fg, bg; state->image_width = (state->small_p ? matrix0b_width :matrix0_width); @@ -357,6 +335,7 @@ init_matrix (Display *dpy, Window window) state->cells = (m_cell *) calloc (sizeof(m_cell), state->grid_width * state->grid_height); + state->cursor = NULL; state->feeders = (m_feeder *) calloc (sizeof(m_feeder), state->grid_width); state->density = get_integer_resource ("density", "Integer"); @@ -392,6 +371,8 @@ init_matrix (Display *dpy, Window window) if (insert) free (insert); + state->knock_knock_p = get_boolean_resource ("knockKnock", "KnockKnock"); + mode = get_string_resource ("mode", "Mode"); if (mode && !strcasecmp(mode, "trace")) state->mode = TRACE0; @@ -526,6 +507,97 @@ feed_matrix (m_state *state) } } + +static void +redraw_cells (m_state *state, Bool active) +{ + int x, y; + int count = 0; + + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + m_cell *cell = &state->cells[state->grid_width * y + x]; + + if (cell->glyph) + count++; + + if (state->mode == TRACE2 && active) + { + int xx = x % strlen(state->tracing); + Bool dead_p = state->tracing[xx] > 0; + + if (y == 0 && x == xx) + cell->glyph = (dead_p + ? state->glyph_map[state->tracing[xx]-'0'] + 1 + : 0); + else if (y == 0) + cell->glyph = 0; + else + cell->glyph = (dead_p ? 0 : + (state->glyph_map[(random()%state->nglyphs)] + + 1)); + + cell->changed = 1; + } + + if (!cell->changed) + continue; + + if (cell->glyph == 0 && cell != state->cursor) + XFillRectangle (state->dpy, state->window, state->erase_gc, + x * state->char_width, + y * state->char_height, + state->char_width, + state->char_height); + else + { + int g = (cell == state->cursor ? CURSOR_GLYPH : cell->glyph); + int cx = (g - 1) % CHAR_COLS; + int cy = (g - 1) / CHAR_COLS; + int map = ((cell->glow > 0 || cell->spinner) ? GLOW_MAP : + (cell->glow < 0) ? FADE_MAP : + PLAIN_MAP); + + XCopyArea (state->dpy, state->images[map], + state->window, state->draw_gc, + cx * state->char_width, + cy * state->char_height, + state->char_width, + state->char_height, + x * state->char_width, + y * state->char_height); + } + + cell->changed = 0; + + if (cell->glow > 0) + { + cell->glow--; + cell->changed = 1; + } + else if (cell->glow < 0) + { + cell->glow++; + if (cell->glow == 0) + cell->glyph = 0; + cell->changed = 1; + } + + if (cell->spinner && active) + { + cell->glyph = (state->glyph_map[(random()%state->nglyphs)] + 1); + cell->changed = 1; + } + } + + if (state->cursor) + { + state->cursor->changed = 1; + } +} + + static int densitizer (m_state *state) { @@ -554,19 +626,29 @@ hack_text (m_state *state) int i; int x = 0; const char *s; + Bool typing_delay = False; + Bool transmit_delay = False; + Bool visible_cursor = False; switch (state->mode) { - case TRACE0: s = "Call trans opt: received.\n" - "2-19-98 13:24:18 REC:Log>_"; break; - case TRACE1: s = "Trace program: running_"; break; - + case TRACE0: if (state->grid_width >= 52) + s = "Call trans opt: received. 2-19-98 13:24:18 REC:Log>"; + else + s = "Call trans opt: received.\n2-19-98 13:24:18 REC:Log>"; + transmit_delay = True; + visible_cursor = True; + break; + case TRACE1: s = "Trace program: running"; + transmit_delay = True; + visible_cursor = True; + break; case KNOCK0: s = "Wake up, Neo..."; break; case KNOCK1: s = ""; break; - case KNOCK2: s = "The Matrix has you..."; break; + case KNOCK2: s = "The Matrix has you..."; typing_delay = True; break; case KNOCK3: s = ""; break; - case KNOCK4: s = "Follow the white rabbit..."; break; + case KNOCK4: s = "Follow the white rabbit."; typing_delay = True; break; case KNOCK5: s = ""; break; - case KNOCK6: s = "Knock knock, Neo."; break; + case KNOCK6: s = "Knock, knock, Neo."; break; case KNOCK7: s = ""; break; default: abort(); break; @@ -606,11 +688,31 @@ hack_text (m_state *state) cell->glyph = char_map[(unsigned char) *s] + 1; if (*s == ' ' || *s == '\t') cell->glyph = 0; cell->changed = 1; + if (visible_cursor) + { + m_cell *next = &state->cells[i + 1]; + next->changed = 1; + state->cursor = next; + } i++; } x++; } s++; + if (typing_delay || transmit_delay) + { + redraw_cells (state, False); + XSync (state->dpy, False); + screenhack_handle_events (state->dpy); + if (typing_delay) + { + usleep (50000); + if (typing_delay && 0 == random() % 3) + usleep (0xFFFFFF & ((random() % 250000) + 1)); + } + else + usleep (20000); + } } } @@ -672,7 +774,7 @@ roll_state (m_state *state) break; case MATRIX: - if (! (random() % 5000)) + if (state->knock_knock_p && (! (random() % 5000))) { state->mode = KNOCK0; flip_images (state); @@ -689,9 +791,38 @@ roll_state (m_state *state) if (delay) { - XSync (state->dpy, False); - sleep (delay); + if (state->cursor) + { + int blink_delay = 333000; + int tot_delay = 0; + m_cell *cursor = state->cursor; + while (tot_delay < delay * 1000000) + { + if (state->cursor) + { + usleep (blink_delay * 2); + tot_delay += (2 * blink_delay); + state->cursor = NULL; + } + else + { + usleep (blink_delay); + tot_delay += blink_delay; + state->cursor = cursor; + } + cursor->changed = 1; + redraw_cells (state, False); + XSync (state->dpy, False); + screenhack_handle_events (state->dpy); + } + } + else + { + XSync (state->dpy, False); + sleep (delay); + } } + state->cursor = NULL; } @@ -770,88 +901,9 @@ hack_matrix (m_state *state) static void draw_matrix (m_state *state) { - int x, y; - int count = 0; - feed_matrix (state); hack_matrix (state); - - for (y = 0; y < state->grid_height; y++) - for (x = 0; x < state->grid_width; x++) - { - m_cell *cell = &state->cells[state->grid_width * y + x]; - - if (cell->glyph) - count++; - - if (state->mode == TRACE2) - { - int xx = x % strlen(state->tracing); - Bool dead_p = state->tracing[xx] > 0; - - if (y == 0 && x == xx) - cell->glyph = (dead_p - ? state->glyph_map[state->tracing[xx]-'0'] + 1 - : 0); - else if (y == 0) - cell->glyph = 0; - else - cell->glyph = (dead_p ? 0 : - (state->glyph_map[(random()%state->nglyphs)] - + 1)); - - cell->changed = 1; - } - - if (!cell->changed) - continue; - - if (cell->glyph == 0) - XFillRectangle (state->dpy, state->window, state->erase_gc, - x * state->char_width, - y * state->char_height, - state->char_width, - state->char_height); - else - { - int cx = (cell->glyph - 1) % CHAR_COLS; - int cy = (cell->glyph - 1) / CHAR_COLS; - int map = ((cell->glow > 0 || cell->spinner) ? GLOW_MAP : - (cell->glow == 0) ? PLAIN_MAP : - GLOW_MAP); - - XCopyArea (state->dpy, state->images[map], - state->window, state->draw_gc, - cx * state->char_width, - cy * state->char_height, - state->char_width, - state->char_height, - x * state->char_width, - y * state->char_height); - } - - cell->changed = 0; - - if (cell->glow > 0) - { - cell->glow--; - cell->changed = 1; - } - else if (cell->glow < 0) - { - cell->glow++; - if (cell->glow == 0) - cell->glyph = 0; - cell->changed = 1; - } - - if (cell->spinner) - { - cell->glyph = (state->glyph_map[(random()%state->nglyphs)] + 1); - cell->changed = 1; - } - } - + redraw_cells (state, True); roll_state (state); #if 0 @@ -880,7 +932,7 @@ char *progclass = "XMatrix"; char *defaults [] = { ".background: black", - ".foreground: green", + ".foreground: #00AA00", "*small: ", "*delay: 10000", "*insert: both", @@ -888,6 +940,7 @@ char *defaults [] = { "*tracePhone: (212) 555-0690", "*spinners: 5", "*density: 75", + "*knockKnock: False", 0 }; @@ -904,6 +957,7 @@ XrmOptionDescRec options [] = { { "-dna", ".mode", XrmoptionNoArg, "DNA" }, { "-binary", ".mode", XrmoptionNoArg, "binary" }, { "-hexadecimal", ".mode", XrmoptionNoArg, "hexadecimal"}, + { "-knock-knock", ".knockKnock", XrmoptionNoArg, "True" }, { 0, 0, 0, 0 } };