From http://www.jwz.org/xscreensaver/xscreensaver-5.27.tar.gz
[xscreensaver] / hacks / glx / fliptext.c
index d76be1354e09e21068cf3c3cfd45ef6fefc0626f..798c1c685ae0f5f6d6f2fc5ad818729d56f6f07e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * fliptext, Copyright (c) 2005-2006 Jamie Zawinski <jwz@jwz.org>
+ * fliptext, Copyright (c) 2005-2014 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 # include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#include <ctype.h>
-#include <sys/stat.h>
-
-#ifndef HAVE_COCOA
-# include <X11/Intrinsic.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_UNAME
-# include <sys/utsname.h>
-#endif /* HAVE_UNAME */
-
-
 /* Utopia 800 needs 64 512x512 textures (4096x4096 bitmap).
    Utopia 720 needs 16 512x512 textures (2048x2048 bitmap).
    Utopia 480 needs 16 512x512 textures (2048x2048 bitmap).
@@ -43,6 +27,7 @@
 #define DEFAULTS "*delay:        10000      \n" \
                 "*showFPS:      False      \n" \
                 "*wireframe:    False      \n" \
+                "*usePty:       False      \n" \
                 "*font:       " DEF_FONT  "\n" \
                 ".foreground: " DEF_COLOR "\n" \
 
 
 #include "xlockmore.h"
 #include "texfont.h"
+#include "textclient.h"
 
 #ifdef USE_GL /* whole file */
 
+/* Should be in <GL/glext.h> */
+# ifndef  GL_TEXTURE_MAX_ANISOTROPY_EXT
+#  define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE
+# endif
+# ifndef  GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
+#  define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+# endif
+
+
 #define DEF_PROGRAM    "xscreensaver-text --cols 0"  /* don't wrap */
 #define DEF_LINES      "8"
 #define DEF_FONT_SIZE  "20"
 #define DEF_COLUMNS    "80"
-#define DEF_ALIGN      "random"
+#define DEF_ALIGNMENT  "random"
 #define DEF_SPEED       "1.0"
 #define TAB_WIDTH        8
 
@@ -96,11 +91,7 @@ typedef struct {
   GLXContext *glx_context;
 
   texture_font_data *texfont;
-
-  FILE *pipe;
-  XtInputId pipe_id;
-  XtIntervalId pipe_timer;
-  Time subproc_relaunch_delay;
+  text_data *tc;
 
   char *buf;
   int buf_size;
@@ -155,7 +146,7 @@ static argtype vars[] = {
   {&max_lines,      "lines",     "Integer",    DEF_LINES,     t_Int},
   {&font_size,      "fontSize",  "Float",      DEF_FONT_SIZE, t_Float},
   {&target_columns, "columns",   "Integer",    DEF_COLUMNS,   t_Int},
-  {&alignment_str,  "alignment", "Alignment",  DEF_ALIGN,     t_String},
+  {&alignment_str,  "alignment", "Alignment",  DEF_ALIGNMENT, t_String},
   {&speed,         "speed",     "Speed",      DEF_SPEED,     t_Float},
 };
 
@@ -224,106 +215,6 @@ strip (char *s, Bool leading, Bool trailing)
 }
 
 
-\f
-/* Subprocess.
-   (This bit mostly cribbed from phosphor.c)
- */
-
-static void drain_input (fliptext_configuration *sc);
-
-static void
-subproc_cb (XtPointer closure, int *source, XtInputId *id)
-{
-  fliptext_configuration *sc = (fliptext_configuration *) closure;
-  drain_input (sc);
-}
-
-
-static void
-launch_text_generator (fliptext_configuration *sc)
-{
-  XtAppContext app = XtDisplayToApplicationContext (sc->dpy);
-  char *oprogram = get_string_resource (sc->dpy, "program", "Program");
-  char *program = (char *) malloc (strlen (oprogram) + 10);
-  strcpy (program, "( ");
-  strcat (program, oprogram);
-  strcat (program, " ) 2>&1");
-
-  if ((sc->pipe = popen (program, "r")))
-    {
-      sc->pipe_id =
-        XtAppAddInput (app, fileno (sc->pipe),
-                       (XtPointer) (XtInputReadMask | XtInputExceptMask),
-                       subproc_cb, (XtPointer) sc);
-    }
-  else
-    {
-      perror (program);
-    }
-}
-
-
-static void
-relaunch_generator_timer (XtPointer closure, XtIntervalId *id)
-{
-  fliptext_configuration *sc = (fliptext_configuration *) closure;
-  if (!sc->pipe_timer) abort();
-  sc->pipe_timer = 0;
-  launch_text_generator (sc);
-}
-
-
-/* When the subprocess has generated some output, this reads as much as it
-   can into sc->buf at sc->buf_tail.
- */
-static void
-drain_input (fliptext_configuration *sc)
-{
-  XtAppContext app = XtDisplayToApplicationContext (sc->dpy);
-  if (sc->buf_tail < sc->buf_size - 2)
-    {
-      int target = sc->buf_size - sc->buf_tail - 2;
-      int n = (sc->pipe
-               ? read (fileno (sc->pipe),
-                       (void *) (sc->buf + sc->buf_tail),
-                       target)
-               : 0);
-      if (n > 0)
-        {
-          sc->buf_tail += n;
-          sc->buf[sc->buf_tail] = 0;
-        }
-      else
-        {
-          if (sc->pipe)
-            {
-              XtRemoveInput (sc->pipe_id);
-              sc->pipe_id = 0;
-              pclose (sc->pipe);
-              sc->pipe = 0;
-            }
-
-          /* If the process didn't print a terminating newline, add one. */
-          if (sc->buf_tail > 1 &&
-              sc->buf[sc->buf_tail-1] != '\n')
-            {
-              sc->buf[sc->buf_tail++] = '\n';
-              sc->buf[sc->buf_tail] = 0;
-            }
-
-          /* Then add one more, just for giggles. */
-          sc->buf[sc->buf_tail++] = '\n';
-          sc->buf[sc->buf_tail] = 0;
-
-          /* Set up a timer to re-launch the subproc in a bit. */
-          sc->pipe_timer = XtAppAddTimeOut (app, sc->subproc_relaunch_delay,
-                                            relaunch_generator_timer,
-                                            (XtPointer) sc);
-        }
-    }
-}
-
-
 static int
 char_width (fliptext_configuration *sc, char c)
 {
@@ -345,8 +236,23 @@ get_one_line (fliptext_configuration *sc)
   int wrap_pix = sc->font_wrap_pixels;
   int col = 0;
   int col_pix = 0;
-
   char *s = sc->buf;
+  int target = sc->buf_size - sc->buf_tail - 2;
+
+  /* Fill as much as we can into sc->buf, but stop at newline.
+   */
+  while (target > 0)
+    {
+      int c = textclient_getc (sc->tc);
+      if (c <= 0)
+        break;
+      sc->buf[sc->buf_tail++] = (char) c;
+      sc->buf[sc->buf_tail] = 0;
+      target--;
+      if (c == '\r' || c == '\n')
+        break;
+    }
+
   while (!result)
     {
       int cw;
@@ -905,6 +811,7 @@ init_fliptext (ModeInfo *mi)
 
   if ((sc->glx_context = init_GL(mi)) != NULL) {
     reshape_fliptext (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+    clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */
   }
 
   program = get_string_resource (mi->dpy, "program", "Program");
@@ -925,15 +832,20 @@ init_fliptext (ModeInfo *mi)
       glEnable (GL_ALPHA_TEST);
       glEnable (GL_TEXTURE_2D);
 
-# ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
       /* "Anistropic filtering helps for quadrilateral-angled textures.
          A sharper image is accomplished by interpolating and filtering
          multiple samples from one or more mipmaps to better approximate
          very distorted textures.  This is the next level of filtering
          after trilinear filtering." */
-      glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
-      clear_gl_error();
-# endif
+      if (strstr ((char *) glGetString(GL_EXTENSIONS),
+                  "GL_EXT_texture_filter_anisotropic"))
+      {
+        GLfloat anisotropic = 0.0;
+        glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic);
+        if (anisotropic >= 1.0)
+          glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 
+                           anisotropic);
+      }
     }
   
   /* The default font is (by fiat) "18 points".
@@ -958,8 +870,6 @@ init_fliptext (ModeInfo *mi)
   sc->buf_size = target_columns * max_lines;
   sc->buf = (char *) calloc (1, sc->buf_size);
 
-  sc->subproc_relaunch_delay = 2 * 1000;   /* 2 seconds */
-
   alignment_random_p = False;
   if (!alignment_str || !*alignment_str ||
       !strcasecmp(alignment_str, "left"))
@@ -980,7 +890,7 @@ init_fliptext (ModeInfo *mi)
       exit (1);
     }
 
-  launch_text_generator (sc);
+  sc->tc = textclient_open (sc->dpy);
 
   if (max_lines < 1) max_lines = 1;
   min_lines = max_lines * 0.66;
@@ -1021,6 +931,7 @@ draw_fliptext (ModeInfo *mi)
   mi->polygon_count = 0;
 
   glPushMatrix();
+  glRotatef(current_device_rotation(), 0, 0, 1);
   {
     GLfloat s = 3.0 / (sc->top_margin - sc->bottom_margin);
     glScalef(s, s, s);
@@ -1081,12 +992,8 @@ release_fliptext (ModeInfo *mi)
     int screen;
     for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
       fliptext_configuration *sc = &scs[screen];
-      if (sc->pipe_id)
-        XtRemoveInput (sc->pipe_id);
-      if (sc->pipe)
-        pclose (sc->pipe);
-      if (sc->pipe_timer)
-        XtRemoveTimeOut (sc->pipe_timer);
+      if (sc->tc)
+        textclient_close (sc->tc);
 
       /* #### there's more to free here */
     }