X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fphosphor.c;h=1238048976d0e3dd6c8eebb1fa36e52f464acdf9;hb=aa75c7476aeaa84cf3abc192b376a8b03c325213;hp=63df6dfeb1388ee71c5dd96402e46b896a535780;hpb=4ade52359b6eba3621566dac79793a33aa4c915f;p=xscreensaver diff --git a/hacks/phosphor.c b/hacks/phosphor.c index 63df6dfe..12380489 100644 --- a/hacks/phosphor.c +++ b/hacks/phosphor.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1999-2013 Jamie Zawinski +/* xscreensaver, Copyright (c) 1999-2014 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -17,12 +17,13 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ -#ifndef HAVE_COCOA +#ifndef HAVE_JWXYZ # include #endif #include "screenhack.h" #include "textclient.h" +#include "utf8wc.h" #define FUZZY_BORDER @@ -73,9 +74,12 @@ typedef struct { int scale; int ticks; int mode; + int escstate; int csiparam[NPAR]; int curparam; + int unicruds; char unicrud[7]; + p_char **chars; p_cell *cells; XGCValues gcv; @@ -139,6 +143,11 @@ static void char_to_pixmap (p_state *state, p_char *pc, int c); static void clear (p_state *); static void set_cursor (p_state *, Bool on); +static unsigned short scale_color_channel (unsigned short ch1, unsigned short ch2) +{ + return (ch1 * 100 + ch2 * 156) >> 8; +} + static void * phosphor_init (Display *dpy, Window window) { @@ -211,7 +220,7 @@ phosphor_init (Display *dpy, Window window) state->gcs = (GC *) calloc (sizeof(GC), state->ticks + 1); { - int ncolors = MAX (0, state->ticks - 3); + int ncolors = MAX (1, state->ticks - 3); XColor *colors = (XColor *) calloc (ncolors, sizeof(XColor)); int h1, h2; double s1, s2, v1, v2; @@ -220,22 +229,29 @@ phosphor_init (Display *dpy, Window window) "foreground", "Foreground"); unsigned long bg = get_pixel_resource (state->dpy, state->xgwa.colormap, "background", "Background"); - unsigned long flare = get_pixel_resource (state->dpy,state->xgwa.colormap, - "flareForeground", "Foreground"); - unsigned long fade = get_pixel_resource (state->dpy,state->xgwa.colormap, - "fadeForeground", "Foreground"); + unsigned long flare = fg; - XColor start, end; + XColor fg_color, bg_color; - start.pixel = fade; - XQueryColor (state->dpy, state->xgwa.colormap, &start); + fg_color.pixel = fg; + XQueryColor (state->dpy, state->xgwa.colormap, &fg_color); - end.pixel = bg; - XQueryColor (state->dpy, state->xgwa.colormap, &end); + bg_color.pixel = bg; + XQueryColor (state->dpy, state->xgwa.colormap, &bg_color); /* Now allocate a ramp of colors from the main color to the background. */ - rgb_to_hsv (start.red, start.green, start.blue, &h1, &s1, &v1); - rgb_to_hsv (end.red, end.green, end.blue, &h2, &s2, &v2); + rgb_to_hsv (scale_color_channel(fg_color.red, bg_color.red), + scale_color_channel(fg_color.green, bg_color.green), + scale_color_channel(fg_color.blue, bg_color.blue), + &h1, &s1, &v1); + rgb_to_hsv (bg_color.red, bg_color.green, bg_color.blue, &h2, &s2, &v2); + + /* Avoid rainbow effects when fading to black/grey/white. */ + if (s2 < 0.003) + h2 = h1; + if (s1 < 0.003) + h1 = h2; + make_color_ramp (state->xgwa.screen, state->xgwa.visual, state->xgwa.colormap, h1, s1, v1, @@ -246,6 +262,21 @@ phosphor_init (Display *dpy, Window window) /* Adjust to the number of colors we actually got. */ state->ticks = ncolors + STATE_MAX; + /* If the foreground is brighter than the background, the flare is white. + * Otherwise, the flare is left at the foreground color (i.e. no flare). */ + rgb_to_hsv (fg_color.red, fg_color.green, fg_color.blue, &h1, &s1, &v1); + if (v2 <= v1) + { + XColor white; + /* WhitePixel is only for the default visual, which can be overridden + * on the command line. */ + white.red = 0xffff; + white.green = 0xffff; + white.blue = 0xffff; + if (XAllocColor(state->dpy, state->xgwa.colormap, &white)) + flare = white.pixel; + } + /* Now, GCs all around. */ state->gcv.font = (font ? font->fid : 0); @@ -296,7 +327,8 @@ phosphor_init (Display *dpy, Window window) state->xgwa.width, state->xgwa.height, state->grid_width - 1, - state->grid_height - 1); + state->grid_height - 1, + 0); return state; } @@ -394,7 +426,7 @@ capture_font_bits (p_state *state) GCCapStyle | GCLineWidth), &state->gcv); -#ifdef HAVE_COCOA +#ifdef HAVE_JWXYZ jwxyz_XSetAntiAliasing (state->dpy, state->gc0, False); jwxyz_XSetAntiAliasing (state->dpy, state->gc1, False); #endif @@ -700,6 +732,8 @@ scroll (p_state *state) static void print_char (p_state *state, int c) { + int cols = state->grid_width; + int rows = state->grid_height; p_cell *cell = &state->cells[state->grid_width * state->cursor_y + state->cursor_x]; @@ -717,7 +751,11 @@ print_char (p_state *state, int c) CRLF line endings instead of bare LF, so that's no good. */ { - int i, start, end; + int i; + int start, end; + + /* Mostly duplicated in apple2-main.c */ + switch (state->escstate) { case 0: @@ -732,20 +770,23 @@ print_char (p_state *state, int c) state->cursor_x--; break; case 9: /* HT */ - if (state->cursor_x < state->grid_width - 8) + if (state->cursor_x < cols - 8) { state->cursor_x = (state->cursor_x & ~7) + 8; } else { state->cursor_x = 0; - if (state->cursor_y < state->grid_height - 1) + if (state->cursor_y < rows - 1) state->cursor_y++; else scroll (state); } break; case 10: /* LF */ +# ifndef HAVE_FORKPTY + state->cursor_x = 0; /* No ptys on iPhone; assume CRLF. */ +# endif case 11: /* VT */ case 12: /* FF */ if(state->last_c == 13) @@ -754,14 +795,14 @@ print_char (p_state *state, int c) cell->p_char = state->chars[state->bk]; cell->changed = True; } - if (state->cursor_y < state->grid_height - 1) + if (state->cursor_y < rows - 1) state->cursor_y++; else scroll (state); break; case 13: /* CR */ state->cursor_x = 0; - cell = &state->cells[state->grid_width * state->cursor_y]; + cell = &state->cells[cols * state->cursor_y]; if((cell->p_char == NULL) || (cell->p_char->name == CURSOR_INDEX)) state->bk = ' '; else @@ -769,8 +810,7 @@ print_char (p_state *state, int c) break; case 14: /* SO */ case 15: /* SI */ - /* Dummy case - I don't want to load several fonts for - the maybe two programs world-wide that use that */ + /* Dummy case - there is one and only one font. */ break; case 24: /* CAN */ case 26: /* SUB */ @@ -790,6 +830,49 @@ print_char (p_state *state, int c) state->curparam = 0; break; default: + + /* states 102-106 are for UTF-8 decoding */ + + if ((c & 0xE0) == 0xC0) { /* 110xxxxx: 11 bits, 2 bytes */ + state->unicruds = 1; + state->unicrud[0] = c; + state->escstate = 102; + break; + } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx: 16 bits, 3 bytes */ + state->unicruds = 1; + state->unicrud[0] = c; + state->escstate = 103; + break; + } else if ((c & 0xF8) == 0xF0) { /* 11110xxx: 21 bits, 4 bytes */ + state->unicruds = 1; + state->unicrud[0] = c; + state->escstate = 104; + break; + } else if ((c & 0xFC) == 0xF8) { /* 111110xx: 26 bits, 5 bytes */ + state->unicruds = 1; + state->unicrud[0] = c; + state->escstate = 105; + break; + } else if ((c & 0xFE) == 0xFC) { /* 1111110x: 31 bits, 6 bytes */ + state->unicruds = 1; + state->unicrud[0] = c; + state->escstate = 106; + break; + } + + PRINT: + + /* If the cursor is in column 39 and we print a character, then + that character shows up in column 39, and the cursor is no + longer visible on the screen (it's in "column 40".) If + another character is printed, then that character shows up in + column 0, and the cursor moves to column 1. + + This is empirically what xterm and gnome-terminal do, so that + must be the right thing. (In xterm, the cursor vanishes, + whereas; in gnome-terminal, the cursor overprints the + character in col 39.) + */ cell->state = FLARE; cell->p_char = state->chars[c]; cell->changed = True; @@ -798,10 +881,10 @@ print_char (p_state *state, int c) if (c != ' ' && cell->p_char->blank_p) cell->p_char = state->chars[CURSOR_INDEX]; - if (state->cursor_x >= state->grid_width - 1) + if (state->cursor_x >= cols - 1 /*####*/) { state->cursor_x = 0; - if (state->cursor_y >= state->grid_height - 1) + if (state->cursor_y >= rows - 1) scroll (state); else state->cursor_y++; @@ -821,7 +904,7 @@ print_char (p_state *state, int c) state->escstate = 0; break; case 'D': /* Linefeed */ - if (state->cursor_y < state->grid_height - 1) + if (state->cursor_y < rows - 1) state->cursor_y++; else scroll (state); @@ -852,10 +935,14 @@ print_char (p_state *state, int c) state->csiparam[i] = 0; state->curparam = 0; break; - case '%': /* Select charset */ - /* No, I don't support UTF-8, since the phosphor font - isn't even Unicode anyway. We must still catch the - last byte, though. */ + case '%': /* Select charset */ + /* @: Select default (ISO 646 / ISO 8859-1) + G: Select UTF-8 + 8: Select UTF-8 (obsolete) + + We can just ignore this and always process UTF-8, I think? + We must still catch the last byte, though. + */ case '(': case ')': /* I don't support different fonts either - see above @@ -896,15 +983,15 @@ print_char (p_state *state, int c) case '@': for (i = 0; i < state->csiparam[0]; i++) { - if(++state->cursor_x > state->grid_width) + if(++state->cursor_x > cols) { state->cursor_x = 0; - if (state->cursor_y < state->grid_height - 1) + if (state->cursor_y < rows - 1) state->cursor_y++; else scroll (state); } - cell = &state->cells[state->grid_width * state->cursor_y + state->cursor_x]; + cell = &state->cells[cols * state->cursor_y + state->cursor_x]; if (cell->state == FLARE || cell->state == NORMAL) { cell->state = FADE; @@ -928,16 +1015,16 @@ print_char (p_state *state, int c) case 'B': if (state->csiparam[0] == 0) state->csiparam[0] = 1; - if ((state->cursor_y += state->csiparam[0]) >= state->grid_height - 1) - state->cursor_y = state->grid_height - 1; + if ((state->cursor_y += state->csiparam[0]) >= rows - 1 /*####*/) + state->cursor_y = rows - 1; state->escstate = 0; break; case 'a': case 'C': if (state->csiparam[0] == 0) state->csiparam[0] = 1; - if ((state->cursor_x += state->csiparam[0]) >= state->grid_width - 1) - state->cursor_x = state->grid_width - 1; + if ((state->cursor_x += state->csiparam[0]) >= cols - 1 /*####*/) + state->cursor_x = cols - 1; state->escstate = 0; break; case 'D': @@ -948,22 +1035,22 @@ print_char (p_state *state, int c) state->escstate = 0; break; case 'd': - if ((state->cursor_y = (state->csiparam[0] - 1)) >= state->grid_height - 1) - state->cursor_y = state->grid_height - 1; + if ((state->cursor_y = (state->csiparam[0] - 1)) >= rows - 1 /*####*/) + state->cursor_y = rows - 1; state->escstate = 0; break; case '`': case 'G': - if ((state->cursor_x = (state->csiparam[0] - 1)) >= state->grid_width - 1) - state->cursor_x = state->grid_width - 1; + if ((state->cursor_x = (state->csiparam[0] - 1)) >= cols - 1 /*####*/) + state->cursor_x = cols - 1; state->escstate = 0; break; case 'f': case 'H': - if ((state->cursor_y = (state->csiparam[0] - 1)) >= state->grid_height - 1) - state->cursor_y = state->grid_height - 1; - if ((state->cursor_x = (state->csiparam[1] - 1)) >= state->grid_width - 1) - state->cursor_x = state->grid_width - 1; + if ((state->cursor_y = (state->csiparam[0] - 1)) >= rows - 1 /*####*/) + state->cursor_y = rows - 1; + if ((state->cursor_x = (state->csiparam[1] - 1)) >= cols - 1 /*####*/) + state->cursor_x = cols - 1; if(state->cursor_y < 0) state->cursor_y = 0; if(state->cursor_x < 0) @@ -972,11 +1059,11 @@ print_char (p_state *state, int c) break; case 'J': start = 0; - end = state->grid_height * state->grid_width; + end = rows * cols; if (state->csiparam[0] == 0) - start = state->grid_width * state->cursor_y + state->cursor_x; + start = cols * state->cursor_y + state->cursor_x; if (state->csiparam[0] == 1) - end = state->grid_width * state->cursor_y + state->cursor_x; + end = cols * state->cursor_y + state->cursor_x; for (i = start; i < end; i++) { cell = &state->cells[i]; @@ -991,7 +1078,7 @@ print_char (p_state *state, int c) break; case 'K': start = 0; - end = state->grid_width; + end = cols; if (state->csiparam[0] == 0) start = state->cursor_x; if (state->csiparam[1] == 1) @@ -1007,6 +1094,9 @@ print_char (p_state *state, int c) } state->escstate = 0; break; + case 'm': /* Set attributes unimplemented (bold, blink, rev) */ + state->escstate = 0; + break; case 's': /* Save position */ state->saved_x = state->cursor_x; state->saved_y = state->cursor_y; @@ -1046,6 +1136,39 @@ print_char (p_state *state, int c) case 3: state->escstate = 0; break; + + case 102: + case 103: + case 104: + case 105: + case 106: + { + int total = state->escstate - 100; /* see what I did there */ + if (state->unicruds < total) { + /* Buffer more bytes of the UTF-8 sequence */ + state->unicrud[state->unicruds++] = c; + } + + if (state->unicruds >= total) { + /* Done! Convert it to Latin1 and print that. */ + char *s; + state->unicrud[state->unicruds] = 0; + s = utf8_to_latin1 ((const char *) state->unicrud, False); + state->unicruds = 0; + state->escstate = 0; + if (s) { + c = (unsigned char) s[0]; + free (s); + goto PRINT; + } else { + c = 0; + } + } + } + break; + + default: + abort(); } set_cursor (state, True); } @@ -1061,7 +1184,7 @@ print_char (p_state *state, int c) else { state->cursor_x = 0; - if (state->cursor_y == state->grid_height - 1) + if (state->cursor_y == rows - 1) scroll (state); else state->cursor_y++; @@ -1073,6 +1196,8 @@ print_char (p_state *state, int c) } else { + /* #### This should do UTF-8 decoding */ + cell->state = FLARE; cell->p_char = state->chars[c]; cell->changed = True; @@ -1081,10 +1206,10 @@ print_char (p_state *state, int c) if (c != ' ' && cell->p_char->blank_p) cell->p_char = state->chars[CURSOR_INDEX]; - if (state->cursor_x >= state->grid_width - 1) + if (state->cursor_x >= cols - 1) { state->cursor_x = 0; - if (state->cursor_y >= state->grid_height - 1) + if (state->cursor_y >= rows - 1) scroll (state); else state->cursor_y++; @@ -1182,7 +1307,8 @@ phosphor_reshape (Display *dpy, Window window, void *closure, textclient_reshape (state->tc, w, h, state->grid_width - 1, - state->grid_height - 1); + state->grid_height - 1, + 0); } @@ -1218,8 +1344,6 @@ static const char *phosphor_defaults [] = { ".background: Black", ".foreground: #00FF00", "*fpsSolid: true", - "*fadeForeground: #006400", - "*flareForeground: #FFFFFF", #if defined(BUILTIN_FONT) "*font: (builtin)", #elif defined(HAVE_COCOA)