/*
- * fliptext, Copyright (c) 2005-2007 Jamie Zawinski <jwz@jwz.org>
+ * fliptext, Copyright (c) 2005-2015 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).
- Utopia 400 needs 4 512x512 textures (1024x1024 bitmap).
- Utopia 180 needs 1 512x512 texture.
- Times 240 needs 1 512x512 texture.
- */
-#define DEF_FONT "-*-utopia-bold-r-normal-*-*-720-*-*-*-*-iso8859-1"
+#define DEF_FONT "-*-utopia-bold-r-normal-*-*-720-*-*-*-*-*-*"
#define DEF_COLOR "#00CCFF"
#define DEFAULTS "*delay: 10000 \n" \
"*showFPS: False \n" \
"*wireframe: False \n" \
+ "*usePty: False \n" \
+ "*texFontCacheSize: 60 \n" \
"*font: " DEF_FONT "\n" \
".foreground: " DEF_COLOR "\n" \
+ "*program: xscreensaver-text --cols 0" /* don't wrap */
# define refresh_fliptext 0
+# define release_fliptext 0
# define fliptext_handle_event 0
#undef countof
#define countof(x) (sizeof((x))/sizeof((*x)))
#include "xlockmore.h"
#include "texfont.h"
+#include "textclient.h"
#ifdef USE_GL /* whole file */
# 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
GLXContext *glx_context;
texture_font_data *texfont;
+ text_data *tc;
- FILE *pipe;
- XtInputId pipe_id;
- XtIntervalId pipe_timer;
- Time subproc_relaunch_delay;
+ int alignment;
char *buf;
int buf_size;
static fliptext_configuration *scs = NULL;
-static char *program;
static int max_lines, min_lines;
static float font_size;
static int target_columns;
static char *alignment_str;
-static int alignment, alignment_random_p;
+static int alignment_random_p;
static GLfloat speed;
static XrmOptionDescRec opts[] = {
- {"-program", ".program", XrmoptionSepArg, 0 },
{"-lines", ".lines", XrmoptionSepArg, 0 },
{"-size", ".fontSize", XrmoptionSepArg, 0 },
{"-columns", ".columns", XrmoptionSepArg, 0 },
};
static argtype vars[] = {
- {&program, "program", "Program", DEF_PROGRAM, t_String},
{&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},
};
}
-\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)
{
+ XCharStruct e;
char s[2];
s[0] = c;
s[1] = 0;
- return texture_string_width (sc->texfont, s, 0);
+ texture_string_metrics (sc->texfont, s, &e, 0, 0);
+ return e.width;
}
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;
{
char *t = result;
char *ut = untabify (t);
- strip (ut, (alignment == 0), 1); /* if centering, strip
- leading whitespace too */
+ strip (ut, (sc->alignment == 0), 1); /* if centering, strip
+ leading whitespace too */
result = ut;
free (t);
}
static line *
make_line (fliptext_configuration *sc, Bool skip_blanks_p)
{
+ XCharStruct e;
line *ln;
char *s;
ln = (line *) calloc (1, sizeof(*ln));
ln->text = s;
ln->state = NEW;
- ln->width = sc->font_scale * texture_string_width (sc->texfont, s, 0);
+ texture_string_metrics (sc->texfont, s, &e, 0, 0);
+ ln->width = sc->font_scale * e.width;
ln->height = sc->font_scale * sc->line_height;
memcpy (ln->color, sc->color, sizeof(ln->color));
glRotatef (line->cth, 0, 1, 0);
- if (alignment == 1)
+ if (sc->alignment == 1)
glTranslatef (-line->width, 0, 0);
- else if (alignment == 0)
+ else if (sc->alignment == 0)
glTranslatef (-line->width/2, 0, 0);
glScalef (sc->font_scale, sc->font_scale, sc->font_scale);
glColor3f (0.4, 0.4, 0.4);
while (*s)
{
+ XCharStruct e;
*c = *s++;
- w = texture_string_width (sc->texfont, c, &h);
+ texture_string_metrics (sc->texfont, c, &e, 0, 0);
+ w = e.width;
+ h = e.ascent + e.descent;
glBegin (GL_LINE_LOOP);
glVertex3f (0, 0, 0);
glVertex3f (w, 0, 0);
maxh = maxy - miny;
if (alignment_random_p)
- alignment = (random() % 3) - 1;
+ sc->alignment = (random() % 3) - 1;
- if (alignment == -1) maxx -= maxw;
- else if (alignment == 1) minx += maxw;
- else minx += maxw/2, maxx -= maxw/2;
+ if (sc->alignment == -1) maxx -= maxw;
+ else if (sc->alignment == 1) minx += maxw;
+ else minx += maxw/2, maxx -= maxw/2;
miny += maxh/2;
maxy -= maxh/2;
}
+static void free_fliptext (ModeInfo *mi);
+
+
ENTRYPOINT void
init_fliptext (ModeInfo *mi)
{
fliptext_configuration *sc;
- if (!scs) {
- scs = (fliptext_configuration *)
- calloc (MI_NUM_SCREENS(mi), sizeof (fliptext_configuration));
- if (!scs) {
- fprintf(stderr, "%s: out of memory\n", progname);
- exit(1);
- }
-
- sc = &scs[MI_SCREEN(mi)];
- sc->lines = (line **) calloc (max_lines+1, sizeof(char *));
- }
+ MI_INIT(mi, scs, free_fliptext);
sc = &scs[MI_SCREEN(mi)];
+ sc->lines = (line **) calloc (max_lines+1, sizeof(char *));
+
sc->dpy = MI_DISPLAY(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");
-
{
- int cw, lh;
+ XCharStruct e;
+ int cw, lh, ascent, descent;
sc->texfont = load_texture_font (MI_DISPLAY(mi), "font");
check_gl_error ("loading font");
- cw = texture_string_width (sc->texfont, "n", &lh);
+ texture_string_metrics (sc->texfont, "n", &e, &ascent, &descent);
+ cw = e.width;
+ lh = ascent + descent;
sc->char_width = cw;
sc->line_height = lh;
}
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"))
- alignment = -1;
+ sc->alignment = -1;
else if (!strcasecmp(alignment_str, "center") ||
!strcasecmp(alignment_str, "middle"))
- alignment = 0;
+ sc->alignment = 0;
else if (!strcasecmp(alignment_str, "right"))
- alignment = 1;
+ sc->alignment = 1;
else if (!strcasecmp(alignment_str, "random"))
- alignment = -1, alignment_random_p = True;
+ sc->alignment = -1, alignment_random_p = True;
else
{
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;
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);
glXSwapBuffers(dpy, window);
}
-ENTRYPOINT void
-release_fliptext (ModeInfo *mi)
+static void
+free_fliptext (ModeInfo *mi)
{
- if (scs) {
- 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);
-
- /* #### there's more to free here */
- }
- free (scs);
- scs = 0;
- }
- FreeAllGL(mi);
+ fliptext_configuration *sc = &scs[MI_SCREEN(mi)];
+ if (sc->tc)
+ textclient_close (sc->tc);
+ free(sc->lines);
+
+ /* #### there's more to free here */
}
XSCREENSAVER_MODULE ("FlipText", fliptext)