From http://www.jwz.org/xscreensaver/xscreensaver-5.39.tar.gz
[xscreensaver] / hacks / flag.c
index 41311f4a92a26bb30d38167765aab2e4f6bda9c3..f12c0bc28d389af1cbf07212888e55045b357786 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 4 -*-
  * flag --- a waving flag
  */
-#if !defined( lint ) && !defined( SABER )
+#if 0
 static const char sccsid[] = "@(#)flag.c       4.02 97/04/01 xlockmore";
 #endif
 
@@ -32,25 +32,32 @@ static const char sccsid[] = "@(#)flag.c    4.02 97/04/01 xlockmore";
  * 01-May-96: written.
  */
 
+#ifdef HAVE_COCOA
+# define DEF_FONT "Monaco 15"
+#else
+# define DEF_FONT "fixed"
+#endif
+
 #ifdef STANDALONE
-# define PROGCLASS                                     "Flag"
-# define HACK_INIT                                     init_flag
-# define HACK_DRAW                                     draw_flag
-# define flag_opts                                     xlockmore_opts
-# define DEFAULTS      "*delay:                50000   \n"                     \
-                                       "*cycles:               1000    \n"                     \
-                                       "*size:                 -7      \n"                     \
-                                       "*ncolors:              200     \n"
+# define DEFAULTS      "*delay:                50000   \n"             \
+                                       "*cycles:               1000    \n"             \
+                                       "*size:                 -7      \n"             \
+                                       "*ncolors:              200     \n"             \
+                                       "*bitmap:                               \n"             \
+                                       "*font:         " DEF_FONT      "\n"    \
+                                       "*text:                                 \n" \
+                                       "*fpsSolid:             true    \n" \
+                                   "*lowrez:       true    \n" \
+
 # define BRIGHT_COLORS
 # define UNIFORM_COLORS
-# define DEF_FONT                                      "-*-helvetica-bold-r-*-240-*"
-# define DEF_BITMAP                                    ""
-# define DEF_TEXT                                      ""
+# define release_flag 0
+# define reshape_flag 0
+# define flag_handle_event 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 
-#include "xpm-pixmap.h"
-
-#include "images/bob.xbm"
+#include "ximage-loader.h"
+#include "images/gen/bob_png.h"
 
 #else  /* !STANDALONE */
 # include "xlock.h"                                    /* from the xlockmore distribution */
@@ -71,7 +78,7 @@ static XrmOptionDescRec opts[] =
 
 #endif /* STANDALONE */
 
-ModeSpecOpt flag_opts = {
+ENTRYPOINT ModeSpecOpt flag_opts = {
 #ifdef STANDALONE
   2, opts, 0, NULL, NULL
 #else  /* !STANDALONE */
@@ -79,9 +86,6 @@ ModeSpecOpt flag_opts = {
 #endif /* STANDALONE */
 };
 
-#include <string.h>
-#include <X11/Xutil.h>
-
 #define MINSIZE 1
 #define MAXSCALE 8
 #define MINSCALE 2
@@ -103,6 +107,7 @@ typedef struct {
        int         timer;
        int         initialized;
        int         stab[ANGLES];
+    Bool               dbufp;
        Pixmap      cache;
        int         width, height;
        int         pointsize;
@@ -165,6 +170,11 @@ affiche(ModeInfo * mi)
                                XSetForeground(display, MI_GC(mi),
                                               MI_PIXEL(mi, (y + x + fp->sidx + fp->startcolor) % MI_NPIXELS(mi)));
 
+            if (fp->cache == MI_WINDOW(mi)) {  /* not double-buffering */
+              xp += fp->x_flag;
+              yp += fp->y_flag;
+            }
+
                        if (fp->pointsize <= 1)
                                XDrawPoint(display, fp->cache, MI_GC(mi), xp, yp);
                        else if (fp->pointsize < 6)
@@ -183,8 +193,12 @@ make_flag_bits(ModeInfo *mi)
 {
   Display *dpy = MI_DISPLAY(mi);
   flagstruct *fp = &flags[MI_SCREEN(mi)];
-  char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
-  char *text = get_string_resource ("text", "Text");
+  char *bitmap_name = get_string_resource (dpy, "bitmap", "Bitmap");
+  char *text = get_string_resource (dpy, "text", "Text");
+
+#ifdef HAVE_JWXYZ
+  bitmap_name = 0;  /* #### always use default */
+#endif
 
   /* If neither a bitmap nor text are specified, randomly select either
         the builtin bitmap or builtin text. */
@@ -210,8 +224,8 @@ make_flag_bits(ModeInfo *mi)
       int width = 0;
       int height = 0;
 
-      bitmap = xpm_file_to_pixmap (dpy, MI_WINDOW (mi), bitmap_name,
-                                   &width, &height, 0);
+      bitmap = file_to_pixmap (dpy, MI_WINDOW (mi), bitmap_name,
+                               &width, &height, 0);
          if (bitmap)
                {
                  fp->image = XGetImage(dpy, bitmap, 0, 0, width, height, ~0L,
@@ -222,7 +236,7 @@ make_flag_bits(ModeInfo *mi)
   else if (text && *text)
        {
          char *text2;
-         char *fn = get_string_resource ("font", "Font");
+         char *fn = get_string_resource (dpy, "font", "Font");
          char *def_fn = "fixed";
          char *line, *token;
          int width, height;
@@ -253,13 +267,42 @@ make_flag_bits(ModeInfo *mi)
                                                                         strlen(uts.sysname) +
                                                                         strlen(uts.version) +
                                                                         strlen(uts.release) + 10);
-# ifdef _AIX
+# if defined(_AIX)
                          sprintf(text, "%s\n%s %s.%s",
                                          uts.nodename, uts.sysname, uts.version, uts.release);
-# else  /* !_AIX */
+#  elif defined(__APPLE__) && !defined(USE_IPHONE)  /* MacOS X + XDarwin */
+              {
+                const char *file = 
+                  "/System/Library/CoreServices/SystemVersion.plist";
+                FILE *f = fopen (file, "r");
+                char *pbv = 0, *pn = 0, *puvv = 0;
+                if (f) {
+                  char *s, buf[255];
+
+                  while (fgets (buf, sizeof(buf)-1, f)) {
+#                   define GRAB(S,V)                                   \
+                    if (strstr(buf, S)) {                                      \
+                      fgets (buf, sizeof(buf)-1, f);                   \
+                      if ((s = strchr (buf, '>'))) V = strdup(s+1);    \
+                      if ((s = strchr (V, '<'))) *s = 0;                       \
+                    }
+                    GRAB ("ProductName", pn)
+                    GRAB ("ProductBuildVersion", pbv)
+                    GRAB ("ProductUserVisibleVersion", puvv)
+#                   undef GRAB
+                  }
+                }
+                if (pbv)
+                  sprintf (text, "%s\n%s\n%s", 
+                           uts.nodename, pn, puvv /*, uts.machine*/);
+                else
+                  sprintf(text, "%s\n%s %s",
+                          uts.nodename, uts.sysname, uts.release);
+              }
+# else
                          sprintf(text, "%s\n%s %s",
                                          uts.nodename, uts.sysname, uts.release);
-# endif /* !_AIX */
+# endif /* special system types */
                        }
 #else  /* !HAVE_UNAME */
 # ifdef VMS
@@ -278,13 +321,7 @@ make_flag_bits(ModeInfo *mi)
          text2 = strdup(text);
 
          if (!fn) fn = def_fn;
-      font = XLoadQueryFont (dpy, fn);
-      if (! font)
-               {
-                 fprintf(stderr, "%s: unable to load font %s; using %s\n",
-                                 progname, fn, def_fn);
-                 font = XLoadQueryFont (dpy, def_fn);
-               }
+      font = load_font_retry (dpy, fn);
 
          memset(&overall, 0, sizeof(overall));
          token = text;
@@ -341,15 +378,30 @@ make_flag_bits(ModeInfo *mi)
          fp->image = XGetImage(dpy, bitmap, 0, 0, width, height, 1L, XYPixmap);
          XFreePixmap(dpy, bitmap);
        }
-  else
+
+
+  if (! fp->image)
        {
-      char *bits = (char *) malloc (sizeof(bob_bits));
-      memcpy (bits, bob_bits, sizeof(bob_bits));
+      XImage *im = image_data_to_ximage (dpy, MI_VISUAL(mi),
+                                       bob_png, sizeof(bob_png));
+      int x, y;
+
          fp->image = XCreateImage (dpy, MI_VISUAL(mi), 1, XYBitmap, 0,
-                                                               bits, bob_width, bob_height,
-                                                               8, 0);
-         fp->image->byte_order = LSBFirst;
-         fp->image->bitmap_bit_order = LSBFirst;
+                                                               0, im->width, im->height, 8, 0);
+      fp->image->data = malloc (fp->image->bytes_per_line * fp->image->height);
+
+      /* Convert deep image to 1 bit */
+      for (y = 0; y < im->height; y++)
+        {
+          for (x = 0; x < im->width; x++)
+            {
+              unsigned long p = XGetPixel (im, x, im->height-y-1);
+              if (! (p & 0xFF000000)) p = ~0;  /* alpha -> white */
+              p = (p >> 16) & 0xFF;            /* red */
+              XPutPixel (fp->image, x, y, p > 0x7F ? 0 : 1);
+            }
+        }
+      XDestroyImage (im);
        }
 
   if (bitmap_name)
@@ -382,21 +434,18 @@ make_flag_bits(ModeInfo *mi)
 #endif /* !STANDALONE */
 
 
-void
+ENTRYPOINT void
 init_flag(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
        int         size = MI_SIZE(mi);
        flagstruct *fp;
 
-       if (flags == NULL) {
-               if ((flags = (flagstruct *) calloc(MI_NUM_SCREENS(mi),
-                                              sizeof (flagstruct))) == NULL)
-                       return;
-       }
+       MI_INIT (mi, flags);
        fp = &flags[MI_SCREEN(mi)];
 
        make_flag_bits(mi);
+    if (!fp->image) abort();
 
        fp->width = MI_WIN_WIDTH(mi);
        fp->height = MI_WIN_HEIGHT(mi);
@@ -415,9 +464,17 @@ init_flag(ModeInfo * mi)
        fp->sidx = fp->x_flag = fp->y_flag = 0;
 
        if (!fp->initialized) {
+      fp->dbufp = True;
+# ifdef HAVE_JWXYZ             /* Don't second-guess Quartz's double-buffering */
+      fp->dbufp = False;
+#endif
                fp->initialized = True;
-               if (!(fp->cache = XCreatePixmap(display, MI_WINDOW(mi),
-               MAXW(fp), MAXH(fp), MI_WIN_DEPTH(mi))))
+               if (!fp->dbufp)
+          fp->cache = MI_WINDOW(mi);  /* not double-buffering */
+        else
+          if (!(fp->cache = XCreatePixmap(display, MI_WINDOW(mi),
+                                          MAXW(fp), MAXH(fp),
+                                          MI_WIN_DEPTH(mi))))
 #ifdef STANDALONE
                  exit(-1);
 #else   /* !STANDALONE */
@@ -448,66 +505,61 @@ init_flag(ModeInfo * mi)
        XClearWindow(display, MI_WINDOW(mi));
 }
 
-void release_flag(ModeInfo * mi);
-
-
-void
+ENTRYPOINT void
 draw_flag(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
        Window      window = MI_WINDOW(mi);
        flagstruct *fp = &flags[MI_SCREEN(mi)];
 
-       if (fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) {
+    if (!fp->image) abort();
+    if (fp->cache == window) {  /* not double-buffering */
+      XClearWindow (display, window);
+    } else if (fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) {
                fp->size = MININITSIZE;
                /* fp->pointsize = MINPOINTSIZE; */
-               XCopyArea(display, fp->cache, window, MI_GC(mi),
-                         0, 0, MINW(fp), MINH(fp), fp->x_flag, fp->y_flag);
+        XCopyArea(display, fp->cache, window, MI_GC(mi),
+                  0, 0, MINW(fp), MINH(fp), fp->x_flag, fp->y_flag);
        } else {
                if ((fp->size + fp->inctaille) > MAXSCALE)
                        fp->inctaille = -fp->inctaille;
                if ((fp->size + fp->inctaille) < MINSCALE)
                        fp->inctaille = -fp->inctaille;
                fp->size += fp->inctaille;
-               XCopyArea(display, fp->cache, window, MI_GC(mi),
-                         0, 0, MAXW(fp), MAXH(fp), fp->x_flag, fp->y_flag);
+        XCopyArea(display, fp->cache, window, MI_GC(mi),
+                  0, 0, MAXW(fp), MAXH(fp), fp->x_flag, fp->y_flag);
        }
        XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
        XFillRectangle(display, fp->cache, MI_GC(mi),
                       0, 0, MAXW(fp), MAXH(fp));
-       XFlush(display);
        affiche(mi);
        fp->sidx += 2;
        fp->sidx %= (ANGLES * MI_NPIXELS(mi));
-       XFlush(display);
        fp->timer++;
        if ((MI_CYCLES(mi) > 0) && (fp->timer >= MI_CYCLES(mi)))
-      {
-        release_flag(mi);
                init_flag(mi);
-      }
 }
 
-void
-release_flag(ModeInfo * mi)
+ENTRYPOINT void
+free_flag(ModeInfo * mi)
 {
-       if (flags != NULL) {
-               int         screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                 {
-                       if (flags[screen].cache)
-                               XFreePixmap(MI_DISPLAY(mi), flags[screen].cache);
-                       if (flags[screen].image)
-                         XDestroyImage(flags[screen].image);
-                 }
-               (void) free((void *) flags);
-               flags = NULL;
-       }
+       int         screen = MI_SCREEN(mi);
+
+       if (flags == NULL)
+               return;
+
+       if (flags[screen].cache && flags[screen].dbufp)
+               XFreePixmap(MI_DISPLAY(mi), flags[screen].cache);
+       if (flags[screen].image)
+         XDestroyImage(flags[screen].image);
 }
 
-void
+#ifndef STANDALONE
+ENTRYPOINT void
 refresh_flag(ModeInfo * mi)
 {
        /* Do nothing, it will refresh by itself */
 }
+#endif
+
+XSCREENSAVER_MODULE ("Flag", flag)