X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fmemscroller.c;h=f18e5a0e3a91d0c74414c7bbed5c62924ecedcc1;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hp=f4d68ca5852472baff43550540d21a3db7442f50;hpb=bc7b7a8eb122206d239ec0e693676bcce31be1aa;p=xscreensaver diff --git a/hacks/memscroller.c b/hacks/memscroller.c index f4d68ca5..f18e5a0e 100644 --- a/hacks/memscroller.c +++ b/hacks/memscroller.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2002, 2004 Jamie Zawinski +/* xscreensaver, Copyright (c) 2002-2015 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 @@ -12,11 +12,14 @@ */ #include "screenhack.h" +#include "xshm.h" #include -#include -#ifdef HAVE_XSHM_EXTENSION -#include "xshm.h" +#undef countof +#define countof(x) (sizeof(x)/sizeof(*(x))) + +#ifndef HAVE_MOBILE +# define READ_FILES #endif typedef struct { @@ -26,6 +29,7 @@ typedef struct { int rez; int speed; int scroll_tick; + unsigned int value; unsigned char *data; int count_zero; } scroller; @@ -35,7 +39,7 @@ typedef struct { Window window; XWindowAttributes xgwa; GC draw_gc, erase_gc, text_gc; - XFontStruct *font; + XFontStruct *fonts[6]; int border; enum { SEED_RAM, SEED_RANDOM, SEED_FILE } seed_mode; @@ -47,16 +51,18 @@ typedef struct { int nscrollers; scroller *scrollers; -# ifdef HAVE_XSHM_EXTENSION - Bool shm_p; XShmSegmentInfo shm_info; -# endif + + int delay; } state; -state * -init_memscroller (Display *dpy, Window window) +static void reshape_memscroller (state *st); + + +static void * +memscroller_init (Display *dpy, Window window) { int i; XGCValues gcv; @@ -64,8 +70,9 @@ init_memscroller (Display *dpy, Window window) char *s; st->dpy = dpy; st->window = window; + st->delay = get_integer_resource (dpy, "delay", "Integer"); + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); - XSelectInput(st->dpy, st->window, ExposureMask); /* Fill up the colormap with random colors. We don't actually use these explicitly, but in 8-bit mode, @@ -73,57 +80,64 @@ init_memscroller (Display *dpy, Window window) { int ncolors = 255; XColor colors[256]; - make_random_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, + make_random_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, colors, &ncolors, True, True, 0, False); } - st->border = get_integer_resource ("borderSize", "BorderSize"); + st->border = get_integer_resource (dpy, "borderSize", "BorderSize"); { - char *fontname = get_string_resource ("font", "Font"); - st->font = XLoadQueryFont (dpy, fontname); - - if (!st->font) + int i; + int nfonts = countof (st->fonts); + for (i = nfonts-1; i >= 0; i--) { - static const char *fonts[] = { - "-*-courier-medium-r-*-*-*-1400-*-*-p-*-*-*", - "-*-courier-medium-r-*-*-*-600-*-*-p-*-*-*", - "-*-utopia-*-r-*-*-*-1400-*-*-p-*-*-*", - "-*-utopia-*-r-*-*-*-600-*-*-p-*-*-*", - "-*-utopia-*-r-*-*-*-240-*-*-p-*-*-*", - "-*-helvetica-*-r-*-*-*-240-*-*-p-*-*-*", - "-*-*-*-r-*-*-*-240-*-*-m-*-*-*", - "fixed", 0 }; - i = 0; - while (fonts[i]) + char *fontname; + char res[20]; + sprintf (res, "font%d", i+1); + fontname = get_string_resource (dpy, res, "Font"); + /* Each resource can be a comma-separated list of font names. + We use the first one that exists. */ + if (fontname && *fontname) { - st->font = XLoadQueryFont (dpy, fonts[i]); - if (st->font) break; - i++; - } - if (st->font) - fprintf (stderr, "%s: couldn't load font \"%s\", using \"%s\"\n", - progname, fontname, fonts[i]); - else - { - fprintf(stderr, "%s: couldn't load any font\n", progname); - exit(-1); + char *f2 = strdup(fontname); + char *f, *token = f2; + while ((f = strtok(token, ",")) && !st->fonts[i]) + { + token = 0; + while (*f == ' ' || *f == '\t') f++; + st->fonts[i] = XLoadQueryFont (dpy, f); + } + free (f2); + if (!st->fonts[i] && i < nfonts-1) + { + fprintf (stderr, "%s: unable to load font: \"%s\"\n", + progname, fontname); + st->fonts[i] = st->fonts[i+1]; + } } } + + if (!st->fonts[0]) + st->fonts[0] = XLoadQueryFont (dpy, "fixed"); + + if (!st->fonts[0]) + { + fprintf (stderr, "%s: unable to load any fonts!", progname); + exit (1); + } } gcv.line_width = st->border; - gcv.background = get_pixel_resource("background", "Background", - st->dpy, st->xgwa.colormap); - gcv.foreground = get_pixel_resource("textColor", "Foreground", - st->dpy, st->xgwa.colormap); - gcv.font = st->font->fid; + gcv.background = get_pixel_resource(st->dpy, st->xgwa.colormap, + "background", "Background"); + gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, + "textColor", "Foreground"); st->text_gc = XCreateGC (st->dpy, st->window, - GCForeground|GCBackground|GCFont, &gcv); + GCForeground|GCBackground, &gcv); - gcv.foreground = get_pixel_resource("foreground", "Foreground", - st->dpy, st->xgwa.colormap); + gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); st->draw_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground|GCLineWidth, &gcv); @@ -132,7 +146,7 @@ init_memscroller (Display *dpy, Window window) GCForeground|GCBackground, &gcv); - s = get_string_resource ("drawMode", "DrawMode"); + s = get_string_resource (dpy, "drawMode", "DrawMode"); if (!s || !*s || !strcasecmp (s, "color")) st->draw_mode = DRAW_COLOR; else if (!strcasecmp (s, "mono")) @@ -147,7 +161,9 @@ init_memscroller (Display *dpy, Window window) s = 0; - st->filename = get_string_resource ("filename", "Filename"); +# ifdef READ_FILES + st->filename = get_string_resource (dpy, "filename", "Filename"); +# endif if (!st->filename || !*st->filename || @@ -155,12 +171,16 @@ init_memscroller (Display *dpy, Window window) !strcasecmp (st->filename, "(mem)") || !strcasecmp (st->filename, "(memory)")) st->seed_mode = SEED_RAM; +# ifdef READ_FILES else if (st->filename && (!strcasecmp (st->filename, "(rand)") || !strcasecmp (st->filename, "(random)"))) st->seed_mode = SEED_RANDOM; else st->seed_mode = SEED_FILE; +# else + st->seed_mode = SEED_RANDOM; +# endif st->nscrollers = 3; st->scrollers = (scroller *) calloc (st->nscrollers, sizeof(scroller)); @@ -173,29 +193,12 @@ init_memscroller (Display *dpy, Window window) sc->which = i; sc->speed = i+1; - sc->image = 0; -# ifdef HAVE_XSHM_EXTENSION - st->shm_p = get_boolean_resource ("useSHM", "Boolean"); - if (st->shm_p) - { - sc->image = create_xshm_image (st->dpy, st->xgwa.visual, - st->xgwa.depth, - ZPixmap, 0, &st->shm_info, - 1, max_height); - if (! sc->image) - st->shm_p = False; - } -# endif /* HAVE_XSHM_EXTENSION */ + sc->image = create_xshm_image (st->dpy, st->xgwa.visual, + st->xgwa.depth, + ZPixmap, &st->shm_info, + 1, max_height); if (!sc->image) - sc->image = XCreateImage (st->dpy, st->xgwa.visual, st->xgwa.depth, - ZPixmap, 0, 0, 1, max_height, 8, 0); - - if (sc->image && !sc->image->data) - sc->image->data = (char *) - malloc (sc->image->bytes_per_line * sc->image->height + 1); - - if (!sc->image || !sc->image->data) { fprintf (stderr, "%s: out of memory (allocating 1x%d image)\n", progname, sc->image->height); @@ -203,6 +206,7 @@ init_memscroller (Display *dpy, Window window) } } + reshape_memscroller (st); return st; } @@ -253,6 +257,7 @@ reshape_memscroller (state *st) +# ifdef READ_FILES static void open_file (state *st) { @@ -271,6 +276,19 @@ open_file (state *st) exit (1); } } +#endif + + +/* "The brk and sbrk functions are historical curiosities left over + from earlier days before the advent of virtual memory management." + -- sbrk(2) man page on BSD systems, as of 1995 or so. + */ +#ifdef HAVE_SBRK +# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) /* gcc >= 4.2 */ + /* Don't print "warning: 'sbrk' is deprecated". */ +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif static unsigned int @@ -279,13 +297,28 @@ more_bits (state *st, scroller *sc) static unsigned char *lomem = 0; static unsigned char *himem = 0; unsigned char r, g, b; - unsigned int v; - /* Pack bytes as RGBR so that we don't have to worry about actually - figuring out the color channel order. + /* vv: Each incoming byte rolls through all 4 bytes of this (it is sc->value) + This is the number displayed at the top. + pv: the pixel color value. incoming bytes land in R,G,B, or maybe just G. + */ + unsigned int vv, pv; + + unsigned int rmsk = st->scrollers[0].image->red_mask; + unsigned int gmsk = st->scrollers[0].image->green_mask; + unsigned int bmsk = st->scrollers[0].image->blue_mask; + unsigned int amsk = ~(rmsk | gmsk | bmsk); + + vv = sc->value; + + /* Pack RGB into a pixel according to the XImage component masks; + set the remaining bits to 1 for the benefit of HAVE_JWXYZ alpha. */ # undef PACK -# define PACK(r,g,b) ((r) | ((g) << 8) | ((b) << 16) | ((r) << 24)) +# define PACK() ((((r << 24) | (r << 16) | (r << 8) | r) & rmsk) | \ + (((g << 24) | (g << 16) | (g << 8) | g) & gmsk) | \ + (((b << 24) | (b << 16) | (b << 8) | b) & bmsk) | \ + amsk) switch (st->seed_mode) { @@ -304,11 +337,24 @@ more_bits (state *st, scroller *sc) himem = ((unsigned char *) sbrk(0)) - (2 * sizeof(void *)); # endif - /* I don't understand what's going on there, but on MacOS X, - we're getting insane values for lomem and himem. Is there - more than one heap? */ - if ((unsigned long) himem - (unsigned long) lomem > 0x0FFFFFFF) + if (!lomem || !himem) + { + /* bad craziness! give up! */ + st->seed_mode = SEED_RANDOM; + return 0; + } + + /* I don't understand what's going on there, but on MacOS X, we're + getting insane values for lomem and himem (both Xlib and HAVE_JWXYZ). + Does malloc() draw from more than one heap? */ + if ((unsigned long) himem - (unsigned long) lomem > 0x0FFFFFFF) { +# if 0 + fprintf (stderr, "%s: wonky: 0x%08x - 0x%08x = 0x%08x\n", progname, + (unsigned int) himem, (unsigned int) lomem, + (unsigned int) himem - (unsigned int) lomem); +# endif himem = lomem + 0xFFFF; + } if (lomem >= himem) abort(); @@ -322,21 +368,23 @@ more_bits (state *st, scroller *sc) r = *sc->data++; g = *sc->data++; b = *sc->data++; + vv = (vv << 24) | (r << 16) | (g << 8) | b; break; case DRAW_MONO: r = 0; g = *sc->data++; b = 0; + vv = (vv << 8) | g; break; default: abort(); } - v = PACK(r,g,b); + pv = PACK(); /* avoid having many seconds of blackness: truncate zeros at 24K. */ - if (v == 0) + if (vv == 0) sc->count_zero++; else sc->count_zero = 0; @@ -346,25 +394,26 @@ more_bits (state *st, scroller *sc) break; case SEED_RANDOM: - v = random(); + vv = random(); switch (st->draw_mode) { case DRAW_COLOR: - r = (v >> 16) & 0xFF; - g = (v >> 8) & 0xFF; - b = (v ) & 0xFF; + r = (vv >> 16) & 0xFF; + g = (vv >> 8) & 0xFF; + b = (vv ) & 0xFF; break; case DRAW_MONO: r = 0; - g = v & 0xFF; + g = vv & 0xFF; b = 0; break; default: abort(); } - v = PACK(r,g,b); + pv = PACK(); break; +# ifdef READ_FILES case SEED_FILE: { int i; @@ -394,64 +443,81 @@ more_bits (state *st, scroller *sc) GETC(r); GETC(g); GETC(b); + vv = (vv << 24) | (r << 16) | (g << 8) | b; break; case DRAW_MONO: r = 0; GETC(g); b = 0; + vv = (vv << 8) | g; break; default: abort(); } # undef GETC - v = PACK(r,g,b); + pv = PACK(); } break; +# endif /* READ_FILES */ default: abort(); } # undef PACK - return v; + + sc->value = vv; + return pv; } static void -draw_string (state *st, unsigned int n) +draw_string (state *st) { char buf[40]; int direction, ascent, descent; - XCharStruct overall; - int x, y, w, h; int bot = st->scrollers[0].rect.y; const char *fmt = "%08X"; + int i; - sprintf (buf, fmt, 0); - XTextExtents (st->font, buf, strlen(buf), - &direction, &ascent, &descent, &overall); - sprintf (buf, "%08X", n); + /* Draw the first font that fits. + */ + for (i = 0; i < countof (st->fonts); i++) + { + XCharStruct overall; + int x, y, w, h; + + if (! st->fonts[i]) continue; - w = overall.width; - h = st->font->ascent + st->font->descent + 1; - x = (st->xgwa.width - w) / 2; - y = (bot - h) / 2; + sprintf (buf, fmt, 0); + XTextExtents (st->fonts[i], buf, strlen(buf), + &direction, &ascent, &descent, &overall); + sprintf (buf, "%08X", st->scrollers[0].value); - if (y + h + 10 > bot) return; + w = overall.width; + h = ascent + descent + 1; + x = (st->xgwa.width - w) / 2; + y = (bot - h) / 2; - XFillRectangle (st->dpy, st->window, st->erase_gc, - x-w, y, w*3, h); - XDrawString (st->dpy, st->window, st->text_gc, - x, y + st->font->ascent, buf, strlen(buf)); + if (y + h + 10 <= bot && x > -10) + { + XSetFont (st->dpy, st->text_gc, st->fonts[i]->fid); + XFillRectangle (st->dpy, st->window, st->erase_gc, + x-w, y, w*3, h); + XDrawString (st->dpy, st->window, st->text_gc, + x, y + ascent, buf, strlen(buf)); + break; + } + } } -static void -draw_memscroller (state *st) +static unsigned long +memscroller_draw (Display *dpy, Window window, void *closure) { + state *st = (state *) closure; int i; - - draw_string (st, *((unsigned int *) st->scrollers[0].image->data)); + draw_string (st); for (i = 0; i < st->nscrollers; i++) { @@ -483,62 +549,73 @@ draw_memscroller (state *st) for (j = 0; j < sc->speed; j++) { -# ifdef HAVE_XSHM_EXTENSION - if (st->shm_p) - XShmPutImage (st->dpy, st->window, st->draw_gc, sc->image, + put_xshm_image (st->dpy, st->window, st->draw_gc, sc->image, 0, 0, sc->rect.x + sc->rect.width - sc->image->width - j, sc->rect.y, sc->rect.width, sc->rect.height, - False); - else -# endif /* HAVE_XSHM_EXTENSION */ - XPutImage (st->dpy, st->window, st->draw_gc, sc->image, - 0, 0, - sc->rect.x + sc->rect.width - sc->image->width - j, - sc->rect.y, - sc->rect.width, sc->rect.height); + &st->shm_info); } } + + return st->delay; } + static void -handle_events (state *st) +memscroller_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) { - XSync (st->dpy, False); - while (XPending (st->dpy)) - { - XEvent event; - XNextEvent (st->dpy, &event); - if (event.xany.type == ConfigureNotify || - event.xany.type == Expose) - { - XClearWindow (st->dpy, st->window); - reshape_memscroller (st); - } + state *st = (state *) closure; + XClearWindow (st->dpy, st->window); + reshape_memscroller (st); +} - screenhack_handle_event (st->dpy, &event); - } +static Bool +memscroller_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; } - -char *progclass = "MemScroller"; +static void +memscroller_free (Display *dpy, Window window, void *closure) +{ +} + -char *defaults [] = { +static const char *memscroller_defaults [] = { ".background: black", "*drawMode: color", + "*fpsSolid: true", + "*fpsTop: true", "*filename: (RAM)", ".textColor: #00FF00", ".foreground: #00FF00", "*borderSize: 2", - ".font: -*-courier-medium-r-*-*-*-1400-*-*-m-*-*-*", + +#if defined(HAVE_COCOA) || defined(HAVE_ANDROID) + ".font1: OCR A Std 192, Lucida Console 192, Monaco 192", + ".font2: OCR A Std 144, Lucida Console 144, Monaco 144", + ".font3: OCR A Std 128, Lucida Console 128, Monaco 128", + ".font4: OCR A Std 96, Lucida Console 96, Monaco 96", + ".font5: OCR A Std 48, Lucida Console 48, Monaco 48", + ".font6: OCR A Std 24, Lucida Console 24, Monaco 24", +#else /* real X11 */ + ".font1: -*-courier-bold-r-*-*-*-1440-*-*-m-*-*-*", + ".font2: -*-courier-bold-r-*-*-*-960-*-*-m-*-*-*", + ".font3: -*-courier-bold-r-*-*-*-480-*-*-m-*-*-*", + ".font4: -*-courier-bold-r-*-*-*-320-*-*-m-*-*-*", + ".font5: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*", + ".font6: fixed", +#endif /* real X11 */ + "*delay: 10000", "*offset: 0", 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec memscroller_options [] = { { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-font", ".font", XrmoptionSepArg, 0 }, { "-filename", ".filename", XrmoptionSepArg, 0 }, @@ -549,18 +626,4 @@ XrmOptionDescRec options [] = { { 0, 0, 0, 0 } }; - -void -screenhack (Display *dpy, Window window) -{ - state *st = init_memscroller (dpy, window); - int delay = get_integer_resource ("delay", "Integer"); - reshape_memscroller (st); - while (1) - { - draw_memscroller (st); - XSync (dpy, False); - handle_events (st); - if (delay) usleep (delay); - } -} +XSCREENSAVER_MODULE ("MemScroller", memscroller)