-/* xscreensaver, Copyright (c) 1992, 1996, 1997, 1998, 2005
- * Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-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 "screenhack.h"
#include "xpm-pixmap.h"
-#include <stdio.h>
-
-extern FILE *popen (const char *, const char *);
-extern int pclose (FILE *);
-
-#define font_height(font) (font->ascent + font->descent)
-#define FONT_NAME "-*-times-*-*-*-*-18-*-*-*-*-*-*-*"
-
-static Display *dpy;
-static Window window;
-static int Width, Height;
-static GC fg_gc, bg_gc, text_fg_gc, text_bg_gc;
-static char *words;
-static char *get_words (void);
-static int x, y;
-static XFontStruct *font;
-static void walk (int dir);
-static void talk (int erase);
-static void talk_1 (void);
-static int think (void);
-static unsigned long interval;
-static unsigned long look (void);
-static Pixmap left1, left2, right1, right2;
-static Pixmap left_front, right_front, front, down;
-
-static char *program, *orig_program, *filename, *text;
-
-#define FROM_ARGV 1
-#define FROM_PROGRAM 2
-#define FROM_FILE 3
-#define FROM_RESRC 4
+#include "textclient.h"
+#include "xft.h"
-#define IS_MOVING 1
-#define GET_PASSWD 2
-static int state; /* indicates states: walking or getting passwd */
+#ifdef HAVE_JWXYZ
+# define HAVE_XPM
+#endif
+
+#define font_height(font) (font->ascent + font->descent)
+
+
+struct state {
+ Display *dpy;
+ Window window;
+ int Width, Height;
+ GC fg_gc, bg_gc, text_fg_gc, text_bg_gc;
+ int x, y;
+
+ XftFont *xftfont;
+ XftColor xftcolor;
+ XftDraw *xftdraw;
+
+ unsigned long interval;
+ Pixmap left1, left2, right1, right2;
+ Pixmap left_front, right_front, front, down;
+
+ text_data *tc;
+
+ int state; /* indicates states: walking or getting passwd */
+ int first_time;
+
+ void (*next_fn) (struct state *);
-static void (*next_fn) (void);
+ int move_length, move_dir;
+
+ int walk_lastdir;
+ int walk_up;
+ Pixmap walk_frame;
+
+ int X, Y, talking;
+
+ struct {
+ int x, y, width, height;
+ } s_rect;
+
+ char words[10240];
+ int lines;
+};
+
+static void fill_words (struct state *);
+static void walk (struct state *, int dir);
+static void talk (struct state *, int erase);
+static void talk_1 (struct state *);
+static int think (struct state *);
+static unsigned long look (struct state *);
+
+#define IS_MOVING 1
#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
# include "images/noseguy/nose-f1.xpm"
#endif
static void
-init_images (void)
+init_images (struct state *st)
{
- static Pixmap *images[] = {
- &left1, &left2, &right1, &right2,
- &left_front, &right_front, &front, &down
- };
- int i;
+ Pixmap *images[8];
#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
+ char **bits[8];
+#else
+ unsigned char *bits[8];
+#endif
+
+ int i = 0;
+ images[i++] = &st->left1;
+ images[i++] = &st->left2;
+ images[i++] = &st->right1;
+ images[i++] = &st->right2;
+ images[i++] = &st->left_front;
+ images[i++] = &st->right_front;
+ images[i++] = &st->front;
+ images[i] = &st->down;
- static char **bits[] = {
- nose_l1_xpm, nose_l2_xpm, nose_r1_xpm, nose_r2_xpm,
- nose_f2_xpm, nose_f3_xpm, nose_f1_xpm, nose_f4_xpm
- };
+#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
+ i = 0;
+ bits[i++] = nose_l1_xpm;
+ bits[i++] = nose_l2_xpm;
+ bits[i++] = nose_r1_xpm;
+ bits[i++] = nose_r2_xpm;
+ bits[i++] = nose_f2_xpm;
+ bits[i++] = nose_f3_xpm;
+ bits[i++] = nose_f1_xpm;
+ bits[i] = nose_f4_xpm;
for (i = 0; i < sizeof (images) / sizeof(*images); i++)
{
- Pixmap pixmap = xpm_data_to_pixmap (dpy, window, bits[i],
+ Pixmap pixmap = xpm_data_to_pixmap (st->dpy, st->window, bits[i],
0, 0, 0);
if (!pixmap)
{
*images[i] = pixmap;
}
#else
- static unsigned char *bits[] = {
- nose_l1_bits, nose_l2_bits, nose_r1_bits, nose_r2_bits,
- nose_f2_bits, nose_f3_bits, nose_f1_bits, nose_f4_bits
- };
+ i = 0;
+ bits[i++] = nose_l1_bits;
+ bits[i++] = nose_l2_bits;
+ bits[i++] = nose_r1_bits;
+ bits[i++] = nose_r2_bits;
+ bits[i++] = nose_f2_bits;
+ bits[i++] = nose_f3_bits;
+ bits[i++] = nose_f1_bits;
+ bits[i++] = nose_f4_bits;
for (i = 0; i < sizeof (images) / sizeof(*images); i++)
if (!(*images[i] =
- XCreatePixmapFromBitmapData(dpy, window,
+ XCreatePixmapFromBitmapData(st->dpy, st->window,
(char *) bits[i], 64, 64, 1, 0, 1)))
{
fprintf (stderr, "%s: Can't load nose images\n", progname);
#define Y_INCR 2
static void
-move (void)
+move (struct state *st)
{
- static int length,
- dir;
-
- if (!length)
+ if (!st->move_length)
{
register int tries = 0;
- dir = 0;
- if ((random() & 1) && think())
+ st->move_dir = 0;
+ if ((random() & 1) && think(st))
{
- talk(0); /* sets timeout to itself */
+ talk(st, 0); /* sets timeout to itself */
return;
}
- if (!(random() % 3) && (interval = look()))
+ if (!(random() % 3) && (st->interval = look(st)))
{
- next_fn = move;
+ st->next_fn = move;
return;
}
- interval = 20 + random() % 100;
+ st->interval = 20 + random() % 100;
do
{
if (!tries)
- length = Width / 100 + random() % 90, tries = 8;
+ st->move_length = st->Width / 100 + random() % 90, tries = 8;
else
tries--;
+ /* There maybe the case that we won't be able to exit from
+ this routine (especially when the geometry is too small)!!
+
+ Ensure that we can exit from this routine.
+ */
+#if 1
+ if (!tries && (st->move_length <= 1)) {
+ st->move_length = 1;
+ break;
+ }
+#endif
switch (random() % 8)
{
case 0:
- if (x - X_INCR * length >= 5)
- dir = LEFT;
+ if (st->x - X_INCR * st->move_length >= 5)
+ st->move_dir = LEFT;
break;
case 1:
- if (x + X_INCR * length <= Width - 70)
- dir = RIGHT;
+ if (st->x + X_INCR * st->move_length <= st->Width - 70)
+ st->move_dir = RIGHT;
break;
case 2:
- if (y - (Y_INCR * length) >= 5)
- dir = UP, interval = 40;
+ if (st->y - (Y_INCR * st->move_length) >= 5)
+ st->move_dir = UP, st->interval = 40;
break;
case 3:
- if (y + Y_INCR * length <= Height - 70)
- dir = DOWN, interval = 20;
+ if (st->y + Y_INCR * st->move_length <= st->Height - 70)
+ st->move_dir = DOWN, st->interval = 20;
break;
case 4:
- if (x - X_INCR * length >= 5 && y - (Y_INCR * length) >= 5)
- dir = (LEFT | UP);
+ if (st->x - X_INCR * st->move_length >= 5 && st->y - (Y_INCR * st->move_length) >= 5)
+ st->move_dir = (LEFT | UP);
break;
case 5:
- if (x + X_INCR * length <= Width - 70 &&
- y - Y_INCR * length >= 5)
- dir = (RIGHT | UP);
+ if (st->x + X_INCR * st->move_length <= st->Width - 70 &&
+ st->y - Y_INCR * st->move_length >= 5)
+ st->move_dir = (RIGHT | UP);
break;
case 6:
- if (x - X_INCR * length >= 5 &&
- y + Y_INCR * length <= Height - 70)
- dir = (LEFT | DOWN);
+ if (st->x - X_INCR * st->move_length >= 5 &&
+ st->y + Y_INCR * st->move_length <= st->Height - 70)
+ st->move_dir = (LEFT | DOWN);
break;
case 7:
- if (x + X_INCR * length <= Width - 70 &&
- y + Y_INCR * length <= Height - 70)
- dir = (RIGHT | DOWN);
+ if (st->x + X_INCR * st->move_length <= st->Width - 70 &&
+ st->y + Y_INCR * st->move_length <= st->Height - 70)
+ st->move_dir = (RIGHT | DOWN);
break;
default:
/* No Defaults */
break;
}
- } while (!dir);
+ } while (!st->move_dir);
}
- walk(dir);
- --length;
- next_fn = move;
+ if (st->move_dir)
+ walk(st, st->move_dir);
+ --st->move_length;
+ st->next_fn = move;
}
#ifdef HAVE_XPM
#endif
static void
-walk(int dir)
+walk (struct state *st, int dir)
{
register int incr = 0;
- static int lastdir;
- static int up = 1;
- static Pixmap frame;
if (dir & (LEFT | RIGHT))
- { /* left/right movement (mabye up/down too) */
- up = -up; /* bouncing effect (even if hit a wall) */
+ { /* left/right movement (mabye up/st->down too) */
+ st->walk_up = -st->walk_up; /* bouncing effect (even if hit a wall) */
if (dir & LEFT)
{
incr = X_INCR;
- frame = (up < 0) ? left1 : left2;
+ st->walk_frame = (st->walk_up < 0) ? st->left1 : st->left2;
}
else
{
incr = -X_INCR;
- frame = (up < 0) ? right1 : right2;
+ st->walk_frame = (st->walk_up < 0) ? st->right1 : st->right2;
}
- if ((lastdir == FRONT || lastdir == DOWN) && dir & UP)
+ if ((st->walk_lastdir == FRONT || st->walk_lastdir == DOWN) && dir & UP)
{
/*
* workaround silly bug that leaves screen dust when guy is
- * facing forward or down and moves up-left/right.
+ * facing forward or st->down and moves up-left/right.
*/
- COPY(dpy, frame, window, fg_gc, 0, 0, 64, 64, x, y);
- XFlush(dpy);
+ COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y);
}
/* note that maybe neither UP nor DOWN is set! */
- if (dir & UP && y > Y_INCR)
- y -= Y_INCR;
- else if (dir & DOWN && y < Height - 64)
- y += Y_INCR;
+ if (dir & UP && st->y > Y_INCR)
+ st->y -= Y_INCR;
+ else if (dir & DOWN && st->y < st->Height - 64)
+ st->y += Y_INCR;
}
- /* Explicit up/down movement only (no left/right) */
+ /* Explicit up/st->down movement only (no left/right) */
else if (dir == UP)
- COPY(dpy, front, window, fg_gc, 0, 0, 64, 64, x, y -= Y_INCR);
+ COPY(st->dpy, st->front, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y -= Y_INCR);
else if (dir == DOWN)
- COPY(dpy, down, window, fg_gc, 0, 0, 64, 64, x, y += Y_INCR);
- else if (dir == FRONT && frame != front)
+ COPY(st->dpy, st->down, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y += Y_INCR);
+ else if (dir == FRONT && st->walk_frame != st->front)
{
- if (up > 0)
- up = -up;
- if (lastdir & LEFT)
- frame = left_front;
- else if (lastdir & RIGHT)
- frame = right_front;
+ if (st->walk_up > 0)
+ st->walk_up = -st->walk_up;
+ if (st->walk_lastdir & LEFT)
+ st->walk_frame = st->left_front;
+ else if (st->walk_lastdir & RIGHT)
+ st->walk_frame = st->right_front;
else
- frame = front;
- COPY(dpy, frame, window, fg_gc, 0, 0, 64, 64, x, y);
+ st->walk_frame = st->front;
+ COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y);
}
if (dir & LEFT)
while (--incr >= 0)
{
- COPY(dpy, frame, window, fg_gc, 0, 0, 64, 64, --x, y + up);
- XFlush(dpy);
+ COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, --st->x, st->y + st->walk_up);
}
else if (dir & RIGHT)
while (++incr <= 0)
{
- COPY(dpy, frame, window, fg_gc, 0, 0, 64, 64, ++x, y + up);
- XFlush(dpy);
+ COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, ++st->x, st->y + st->walk_up);
}
- lastdir = dir;
+ st->walk_lastdir = dir;
}
static int
-think (void)
+think (struct state *st)
{
if (random() & 1)
- walk(FRONT);
+ walk(st, FRONT);
if (random() & 1)
- {
- words = get_words();
return 1;
- }
return 0;
}
-#define MAXLINES 25
-
-#undef BUFSIZ
-#define BUFSIZ ((MAXLINES + 1) * 100)
-
+#define MAXLINES 10
+#define LINELEN 256
static void
-talk(int force_erase)
+talk (struct state *st, int force_erase)
{
int width = 0,
height,
Z,
total = 0;
- static int X,
- Y,
- talking;
- static struct
- {
- int x,
- y,
- width,
- height;
- } s_rect;
register char *p,
*p2;
- char buf[BUFSIZ],
- args[MAXLINES][256];
+ char args[MAXLINES][LINELEN];
/* clear what we've written */
- if (talking || force_erase)
+ if (st->talking || force_erase)
{
- if (!talking)
+ if (!st->talking)
return;
- XFillRectangle(dpy, window, bg_gc, s_rect.x - 5, s_rect.y - 5,
- s_rect.width + 10, s_rect.height + 10);
- talking = 0;
+ XFillRectangle(st->dpy, st->window, st->bg_gc, st->s_rect.x - 5, st->s_rect.y - 5,
+ st->s_rect.width + 10, st->s_rect.height + 10);
+ st->talking = 0;
if (!force_erase)
- next_fn = move;
- interval = 0;
+ st->next_fn = move;
+ st->interval = 0;
{
- /* might as well check the window for size changes now... */
+ /* might as well check the st->window for size changes now... */
XWindowAttributes xgwa;
- XGetWindowAttributes (dpy, window, &xgwa);
- Width = xgwa.width + 2;
- Height = xgwa.height + 2;
+ XGetWindowAttributes (st->dpy, st->window, &xgwa);
+ st->Width = xgwa.width + 2;
+ st->Height = xgwa.height + 2;
}
return;
}
- talking = 1;
- walk(FRONT);
- p = strcpy(buf, words);
+ p = st->words;
+ /* If there is actually no words, just return */
+ if (!*p)
+ {
+ st->talking = 0;
+ return;
+ }
+ st->talking = 1;
+ walk(st, FRONT);
for (p2 = p; *p2; p2++)
if (*p2 == '\t') *p2 = ' ';
if (!(p2 = strchr(p, '\n')) || !p2[1])
{
- total = strlen (words);
- strcpy (args[0], words);
- width = XTextWidth(font, words, total);
+ XGlyphInfo extents;
+
+ total = strlen (st->words);
+ strncpy (args[0], st->words, LINELEN);
+ args[0][LINELEN - 1] = 0;
+ XftTextExtentsUtf8 (st->dpy, st->xftfont,
+ (FcChar8 *) st->words, total,
+ &extents);
+ width = extents.xOff;
height = 0;
}
else
for (height = 0; p; height++)
{
int w;
+ XGlyphInfo extents;
*p2 = 0;
- if ((w = XTextWidth(font, p, p2 - p)) > width)
- width = w;
+
+ XftTextExtentsUtf8 (st->dpy, st->xftfont,
+ (FcChar8 *) p, p2 - p,
+ &extents);
+ w = extents.xOff;
+ if (w > width)
+ width = w;
+
total += p2 - p; /* total chars; count to determine reading
* time */
- (void) strcpy(args[height], p);
+ (void) strncpy(args[height], p, LINELEN);
+ args[height][LINELEN - 1] = 0;
if (height == MAXLINES - 1)
{
/* puts("Message too long!"); */
* Figure out the height and width in pixels (height, width) extend the
* new box by 15 pixels on the sides (30 total) top and bottom.
*/
- s_rect.width = width + 30;
- s_rect.height = height * font_height(font) + 30;
- if (x - s_rect.width - 10 < 5)
- s_rect.x = 5;
- else if ((s_rect.x = x + 32 - (s_rect.width + 15) / 2)
- + s_rect.width + 15 > Width - 5)
- s_rect.x = Width - 15 - s_rect.width;
- if (y - s_rect.height - 10 < 5)
- s_rect.y = y + 64 + 5;
+ st->s_rect.width = width + 30;
+ st->s_rect.height = height * font_height(st->xftfont) + 30;
+ if (st->x - st->s_rect.width - 10 < 5)
+ st->s_rect.x = 5;
+ else if ((st->s_rect.x = st->x + 32 - (st->s_rect.width + 15) / 2)
+ + st->s_rect.width + 15 > st->Width - 5)
+ st->s_rect.x = st->Width - 15 - st->s_rect.width;
+ if (st->y - st->s_rect.height - 10 < 5)
+ st->s_rect.y = st->y + 64 + 5;
else
- s_rect.y = y - 5 - s_rect.height;
+ st->s_rect.y = st->y - 5 - st->s_rect.height;
- XFillRectangle(dpy, window, text_bg_gc,
- s_rect.x, s_rect.y, s_rect.width, s_rect.height);
+ XFillRectangle(st->dpy, st->window, st->text_bg_gc,
+ st->s_rect.x, st->s_rect.y, st->s_rect.width, st->s_rect.height);
/* make a box that's 5 pixels thick. Then add a thin box inside it */
- XSetLineAttributes(dpy, text_fg_gc, 5, 0, 0, 0);
- XDrawRectangle(dpy, window, text_fg_gc,
- s_rect.x, s_rect.y, s_rect.width - 1, s_rect.height - 1);
- XSetLineAttributes(dpy, text_fg_gc, 0, 0, 0, 0);
- XDrawRectangle(dpy, window, text_fg_gc,
- s_rect.x + 7, s_rect.y + 7, s_rect.width - 15, s_rect.height - 15);
+ XSetLineAttributes(st->dpy, st->text_fg_gc, 5, 0, 0, 0);
+ XDrawRectangle(st->dpy, st->window, st->text_fg_gc,
+ st->s_rect.x, st->s_rect.y, st->s_rect.width - 1, st->s_rect.height - 1);
+ XSetLineAttributes(st->dpy, st->text_fg_gc, 0, 0, 0, 0);
+ XDrawRectangle(st->dpy, st->window, st->text_fg_gc,
+ st->s_rect.x + 7, st->s_rect.y + 7, st->s_rect.width - 15, st->s_rect.height - 15);
- X = 15;
- Y = 15 + font_height(font);
+ st->X = 15;
+ st->Y = 15 + font_height(st->xftfont);
/* now print each string in reverse order (start at bottom of box) */
for (Z = 0; Z < height; Z++)
{
- XDrawString(dpy, window, text_fg_gc, s_rect.x + X, s_rect.y + Y,
- args[Z], strlen(args[Z]));
- Y += font_height(font);
+ int L = strlen(args[Z]);
+ /* If there are continuous new lines, L can be 0 */
+ if (L && (args[Z][L-1] == '\r' || args[Z][L-1] == '\n'))
+ args[Z][--L] = 0;
+ XftDrawStringUtf8 (st->xftdraw, &st->xftcolor, st->xftfont,
+ st->s_rect.x + st->X, st->s_rect.y + st->Y,
+ (FcChar8 *) args[Z], L);
+
+ st->Y += font_height(st->xftfont);
}
- interval = (total / 15) * 1000;
- if (interval < 2000) interval = 2000;
- next_fn = talk_1;
+ st->interval = (total / 15) * 1000;
+ if (st->interval < 2000) st->interval = 2000;
+ st->next_fn = talk_1;
+ *st->words = 0;
+ st->lines = 0;
}
-static void talk_1 (void)
+static void
+talk_1 (struct state *st)
{
- talk(0);
+ talk(st, 0);
}
static unsigned long
-look (void)
+look (struct state *st)
{
if (random() % 3)
{
- COPY(dpy, (random() & 1) ? down : front, window, fg_gc,
- 0, 0, 64, 64, x, y);
+ COPY(st->dpy, (random() & 1) ? st->down : st->front, st->window, st->fg_gc,
+ 0, 0, 64, 64, st->x, st->y);
return 1000L;
}
if (!(random() % 5))
return 0;
if (random() % 3)
{
- COPY(dpy, (random() & 1) ? left_front : right_front,
- window, fg_gc, 0, 0, 64, 64, x, y);
+ COPY(st->dpy, (random() & 1) ? st->left_front : st->right_front,
+ st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y);
return 1000L;
}
if (!(random() % 5))
return 0;
- COPY(dpy, (random() & 1) ? left1 : right1, window, fg_gc,
- 0, 0, 64, 64, x, y);
+ COPY(st->dpy, (random() & 1) ? st->left1 : st->right1, st->window, st->fg_gc,
+ 0, 0, 64, 64, st->x, st->y);
return 1000L;
}
static void
-init_words (void)
+fill_words (struct state *st)
{
- program = get_string_resource ("program", "Program");
- filename = get_string_resource ("filename", "Filename");
- text = get_string_resource ("text", "Text");
+ char *p = st->words + strlen(st->words);
+ char *c;
+ int lines = 0;
+ int max = MAXLINES;
+
+ for (c = st->words; c < p; c++)
+ if (*c == '\n')
+ lines++;
- if (program) /* get stderr on stdout, so it shows up on the window */
+ while (p < st->words + sizeof(st->words) - 1 &&
+ lines < max)
{
- orig_program = program;
- program = (char *) malloc (strlen (program) + 10);
- strcpy (program, "( ");
- strcat (program, orig_program);
- strcat (program, " ) 2>&1");
+ int c = textclient_getc (st->tc);
+ if (c == '\n')
+ lines++;
+ if (c > 0)
+ *p++ = (char) c;
+ else
+ break;
}
+ *p = 0;
- words = get_words();
-}
-
-static int first_time = 1;
-
-static char *
-get_words (void)
-{
- FILE *pp;
- static char buf[BUFSIZ];
- register char *p = buf;
-
- buf[0] = '\0';
-
- if ((pp = popen(program, "r")))
- {
- while (fgets(p, sizeof(buf) - strlen(buf), pp))
- {
- if (strlen(buf) + 1 < sizeof(buf))
- p = buf + strlen(buf);
- else
- break;
- }
- (void) pclose(pp);
- if (! buf[0])
- sprintf (buf, "\"%s\" produced no output!", orig_program);
- else if (!first_time &&
- (strstr (buf, ": not found") ||
- strstr (buf, ": Not found") ||
- strstr (buf, ": command not found") ||
- strstr (buf, ": Command not found")))
- switch (random () % 20)
- {
- case 1: strcat (buf, "( Get with the program, bub. )\n");
- break;
- case 2: strcat (buf,
- "( I blow my nose at you, you silly person! ) \n"); break;
- case 3: strcat (buf,
- "\nThe resource you want to\nset is `noseguy.program'\n");
- break;
- case 4:
- strcat(buf,"\nHelp!! Help!!\nAAAAAAGGGGHHH!! \n\n"); break;
- case 5: strcpy (buf, "You have new mail.\n"); break;
- case 6:
- strcat(buf,"( Hello? Are you paying attention? )\n");break;
- case 7:
- strcat (buf, "sh: what kind of fool do you take me for? \n");
- break;
- }
- first_time = 0;
- p = buf;
- }
- else
- {
- perror(program);
- }
-
- return p;
+ st->lines = lines;
}
\f
-char *progclass = "Noseguy";
-
-char *defaults [] = {
- ".background: black",
- ".foreground: gray80",
- "*program: xscreensaver-text --cols 40 | head -15",
- "noseguy.font: -*-new century schoolbook-*-r-*-*-*-180-*-*-*-*-*-*",
+static const char *noseguy_defaults [] = {
+ ".background: black",
+ ".foreground: #CCCCCC",
+ "*textForeground: black",
+ "*textBackground: #CCCCCC",
+ "*fpsSolid: true",
+ "*program: xscreensaver-text",
+ "*usePty: False",
+ ".font: -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*",
0
};
-XrmOptionDescRec options [] = {
- { "-mode", ".mode", XrmoptionSepArg, 0 },
+static XrmOptionDescRec noseguy_options [] = {
{ "-program", ".program", XrmoptionSepArg, 0 },
- { "-text", ".text", XrmoptionSepArg, 0 },
- { "-filename", ".filename", XrmoptionSepArg, 0 },
{ "-font", ".font", XrmoptionSepArg, 0 },
{ "-text-foreground", ".textForeground", XrmoptionSepArg, 0 },
{ "-text-background", ".textBackground", XrmoptionSepArg, 0 },
};
-static void
+static void *
noseguy_init (Display *d, Window w)
{
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
unsigned long fg, bg, text_fg, text_bg;
XWindowAttributes xgwa;
Colormap cmap;
- char *fontname = get_string_resource ("font", "Font");
- char **list;
- int foo, i;
+ char *fontname;
XGCValues gcvalues;
- dpy = d;
- window = w;
- XGetWindowAttributes (dpy, window, &xgwa);
- Width = xgwa.width + 2;
- Height = xgwa.height + 2;
+ st->dpy = d;
+ st->window = w;
+ st->first_time = 1;
+
+ fontname = get_string_resource (st->dpy, "font", "Font");
+ XGetWindowAttributes (st->dpy, st->window, &xgwa);
+ st->Width = xgwa.width + 2;
+ st->Height = xgwa.height + 2;
cmap = xgwa.colormap;
- init_words();
- init_images();
-
- if (!fontname || !(font = XLoadQueryFont(dpy, fontname)))
- {
- list = XListFonts(dpy, FONT_NAME, 32767, &foo);
- for (i = 0; i < foo; i++)
- if ((font = XLoadQueryFont(dpy, list[i])))
- break;
- if (!font)
- {
- fprintf (stderr, "%s: Can't find a large font.", progname);
- exit (1);
- }
- XFreeFontNames(list);
- }
-
- fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
- bg = get_pixel_resource ("background", "Background", dpy, cmap);
- text_fg = get_pixel_resource ("textForeground", "Foreground", dpy, cmap);
- text_bg = get_pixel_resource ("textBackground", "Background", dpy, cmap);
+ st->tc = textclient_open (st->dpy);
+ {
+ int w = 40;
+ int h = 15;
+ textclient_reshape (st->tc, w, h, w, h,
+ /* Passing MAXLINES isn't actually necessary */
+ 0);
+ }
+
+ init_images(st);
+
+ st->xftfont = XftFontOpenXlfd (st->dpy, screen_number (xgwa.screen),
+ fontname);
+ XftColorAllocName (st->dpy, xgwa.visual, xgwa.colormap,
+ get_string_resource (st->dpy,
+ "textForeground", "Foreground"),
+ &st->xftcolor);
+ st->xftdraw = XftDrawCreate (st->dpy, st->window, xgwa.visual,
+ xgwa.colormap);
+
+
+ fg = get_pixel_resource (st->dpy, cmap, "foreground", "Foreground");
+ bg = get_pixel_resource (st->dpy, cmap, "background", "Background");
+ text_fg = get_pixel_resource (st->dpy, cmap, "textForeground", "Foreground");
+ text_bg = get_pixel_resource (st->dpy, cmap, "textBackground", "Background");
/* notice when unspecified */
- if (! get_string_resource ("textForeground", "Foreground"))
+ if (! get_string_resource (st->dpy, "textForeground", "Foreground"))
text_fg = bg;
- if (! get_string_resource ("textBackground", "Background"))
+ if (! get_string_resource (st->dpy, "textBackground", "Background"))
text_bg = fg;
- gcvalues.font = font->fid;
- gcvalues.graphics_exposures = False;
gcvalues.foreground = fg;
gcvalues.background = bg;
- fg_gc = XCreateGC (dpy, window,
- GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+ st->fg_gc = XCreateGC (st->dpy, st->window,
+ GCForeground|GCBackground,
&gcvalues);
gcvalues.foreground = bg;
gcvalues.background = fg;
- bg_gc = XCreateGC (dpy, window,
- GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+ st->bg_gc = XCreateGC (st->dpy, st->window,
+ GCForeground|GCBackground,
&gcvalues);
gcvalues.foreground = text_fg;
gcvalues.background = text_bg;
- text_fg_gc = XCreateGC (dpy, window,
- GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+ st->text_fg_gc = XCreateGC (st->dpy, st->window,
+ GCForeground|GCBackground,
&gcvalues);
gcvalues.foreground = text_bg;
gcvalues.background = text_fg;
- text_bg_gc = XCreateGC (dpy, window,
- GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+ st->text_bg_gc = XCreateGC (st->dpy, st->window,
+ GCForeground|GCBackground,
&gcvalues);
- x = Width / 2;
- y = Height / 2;
- state = IS_MOVING;
+ st->x = st->Width / 2;
+ st->y = st->Height / 2;
+ st->state = IS_MOVING;
+ st->next_fn = move;
+ st->walk_up = 1;
+ return st;
}
-void
-screenhack (Display *d, Window w)
+static unsigned long
+noseguy_draw (Display *dpy, Window window, void *closure)
{
- noseguy_init (d, w);
- next_fn = move;
- while (1)
- {
- next_fn();
- XSync (dpy, False);
- screenhack_handle_events (dpy);
- usleep (interval * 1000);
- }
+ struct state *st = (struct state *) closure;
+ fill_words(st);
+ st->next_fn(st);
+ return (st->interval * 1000);
+}
+
+static void
+noseguy_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+ struct state *st = (struct state *) closure;
+ st->Width = w + 2;
+ st->Height = h + 2;
+}
+
+static Bool
+noseguy_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ return False;
+}
+
+static void
+noseguy_free (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ textclient_close (st->tc);
+ free (st);
}
+XSCREENSAVER_MODULE ("NoseGuy", noseguy)