+static void drain_matrix (m_state *);
+
+static void
+handle_events (m_state *state)
+{
+ XSync (state->dpy, False);
+ while (XPending (state->dpy))
+ {
+ XEvent event;
+ XNextEvent (state->dpy, &event);
+
+ if (event.xany.type == ConfigureNotify)
+ {
+ int ow = state->grid_width;
+ int oh = state->grid_height;
+ XGetWindowAttributes (state->dpy, state->window, &state->xgwa);
+ state->grid_width = state->xgwa.width / state->char_width;
+ state->grid_height = state->xgwa.height / state->char_height;
+ state->grid_width++;
+ state->grid_height++;
+ if (state->grid_width < 5) state->grid_width = 5;
+ if (state->grid_height < 5) state->grid_height = 5;
+
+ if (ow != state->grid_width ||
+ oh != state->grid_height)
+ {
+ m_cell *ncells = (m_cell *)
+ calloc (sizeof(m_cell),
+ state->grid_width * state->grid_height);
+ m_feeder *nfeeders = (m_feeder *)
+ calloc (sizeof(m_feeder), state->grid_width);
+ int x, y, i;
+
+ /* fprintf(stderr, "resize: %d x %d ==> %d x %d\n",
+ ow, oh, state->grid_width, state->grid_height); */
+
+ for (y = 0; y < oh; y++)
+ for (x = 0; x < ow; x++)
+ if (x < ow && x < state->grid_width &&
+ y < oh && y < state->grid_height)
+ ncells[y * state->grid_width + x] =
+ state->cells[y * ow + x];
+ free (state->cells);
+ state->cells = ncells;
+
+ x = (ow < state->grid_width ? ow : state->grid_width);
+ for (i = 0; i < x; i++)
+ nfeeders[i] = state->feeders[i];
+ free (state->feeders);
+ state->feeders = nfeeders;
+ }
+ }
+ else if (event.xany.type == KeyPress)
+ {
+ KeySym keysym;
+ char c = 0;
+ XLookupString (&event.xkey, &c, 1, &keysym, 0);
+ if (c == '0')
+ {
+ drain_matrix (state);
+ return;
+ }
+ else if (c == '+' || c == '=' || c == '>' || c == '.')
+ {
+ state->density += 10;
+ if (state->density > 100)
+ state->density = 100;
+ else
+ return;
+ }
+ else if (c == '-' || c == '_' || c == '<' || c == ',')
+ {
+ state->density -= 10;
+ if (state->density < 0)
+ state->density = 0;
+ else
+ return;
+ }
+ }
+
+ screenhack_handle_event (state->dpy, &event);
+ }
+}
+
+
+static void
+matrix_usleep (m_state *state, unsigned long delay)
+{
+ if (!delay) return;
+
+ if (state->cursor)
+ {
+ int blink_delay = 333000;
+ int tot_delay = 0;
+ m_cell *cursor = state->cursor;
+ while (tot_delay < delay)
+ {
+ 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);
+ handle_events (state);
+ }
+ }
+ else
+ {
+ XSync (state->dpy, False);
+ handle_events (state);
+ usleep (delay);
+ }
+}
+
+
+static void
+hack_text_1 (m_state *state,
+ int *xP, int *yP,
+ const char *s,
+ Bool typing_delay,
+ Bool transmit_delay,
+ Bool long_delay,
+ Bool visible_cursor,
+ Bool scroll_p)
+{
+ int x = *xP;
+ int y = *yP;
+ int i = state->grid_width * y + x;
+ Bool glow_p = False;
+
+ if (y >= state->grid_height-1) return;
+
+ while (*s)
+ {
+ m_cell *cell;
+ Bool done_p = s[1] == '\000';
+
+ long_delay = done_p;
+
+ if (*s == '\n')
+ {
+ x = 0;
+ y++;
+ i = state->grid_width * y + x;
+
+ if (scroll_p)
+ {
+ int xx, yy;
+ for (yy = 0; yy < state->grid_height-1; yy++)
+ for (xx = 0; xx < state->grid_width; xx++)
+ {
+ int ii = yy * state->grid_width + xx;
+ int jj = (yy+1) * state->grid_width + xx;
+ state->cells[ii] = state->cells[jj];
+ state->cells[ii].changed = 1;
+ }
+ /* clear bottom row */
+ for (xx = 0; xx < state->grid_width; xx++)
+ {
+ int ii = yy * state->grid_width + xx;
+ state->cells[ii].glyph = 0;
+ state->cells[ii].changed = 1;
+ }
+ y--; /* move it back */
+ i = state->grid_width * y + x;
+ }
+
+ if (y >= state->grid_height) return;
+
+ cell = &state->cells[i];
+ if (visible_cursor)
+ {
+ cell->changed = 1;
+ state->cursor = cell;
+ }
+ }
+ else if (*s == '\010')
+ ;
+ else if (*s == '\002')
+ glow_p = True;
+ else
+ {
+ cell = &state->cells[i];
+ if (x < state->grid_width-1)
+ {
+ cell->glyph = char_map[(unsigned char) *s] + 1;
+ if (*s == ' ' || *s == '\t') cell->glyph = 0;
+ cell->changed = 1;
+ cell->glow = (glow_p ? 8 : 0);
+ if (visible_cursor)
+ {
+ m_cell *next = &state->cells[i + 1];
+ next->changed = 1;
+ state->cursor = next;
+ }
+ i++;
+ }
+ x++;
+ }
+ s++;
+ if (typing_delay || transmit_delay || long_delay)
+ {
+ redraw_cells (state, False);
+ XSync (state->dpy, False);
+ handle_events (state);
+ if (typing_delay)
+ {
+ usleep (50000);
+ if (typing_delay && 0 == random() % 3)
+ usleep (0xFFFFFF & ((random() % 250000) + 1));
+ }
+ else
+ if (long_delay)
+ matrix_usleep (state, 1000000);
+ else
+ usleep (20000);
+ }
+ }
+
+ *xP = x;
+ *yP = y;
+}
+
+