X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fnoseguy.c;h=c5cc9c08d491e5ff7639e4d3a61493533be68780;hb=aa75c7476aeaa84cf3abc192b376a8b03c325213;hp=cae0397f740cfeac227d1233d42e9d8bae75a702;hpb=5f1f12f2a37da634000f96d18d59cc73a8814ef7;p=xscreensaver diff --git a/hacks/noseguy.c b/hacks/noseguy.c index cae0397f..c5cc9c08 100644 --- a/hacks/noseguy.c +++ b/hacks/noseguy.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-2014 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 @@ -16,16 +16,14 @@ #include "screenhack.h" #include "xpm-pixmap.h" -#include +#include "textclient.h" +#include "xft.h" -#ifdef HAVE_COCOA +#ifdef HAVE_JWXYZ # define HAVE_XPM #endif -extern FILE *popen (const char *, const char *); -extern int pclose (FILE *); - -#define font_height(font) (font->ascent + font->descent) +#define font_height(font) (font->ascent + font->descent) struct state { @@ -33,15 +31,17 @@ struct state { Window window; int Width, Height; GC fg_gc, bg_gc, text_fg_gc, text_bg_gc; - char *words; int x, y; - XFontStruct *font; + + XftFont *xftfont; + XftColor xftcolor; + XftDraw *xftdraw; unsigned long interval; Pixmap left1, left2, right1, right2; Pixmap left_front, right_front, front, down; - char *program, *orig_program; + text_data *tc; int state; /* indicates states: walking or getting passwd */ int first_time; @@ -60,10 +60,11 @@ struct state { int x, y, width, height; } s_rect; - char word_buf[BUFSIZ]; + char words[10240]; + int lines; }; -static char *get_words (struct state *); +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 *); @@ -110,7 +111,7 @@ init_images (struct state *st) images[i++] = &st->left_front; images[i++] = &st->right_front; images[i++] = &st->front; - images[i++] = &st->down; + images[i] = &st->down; #if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) @@ -122,7 +123,7 @@ init_images (struct state *st) bits[i++] = nose_f2_xpm; bits[i++] = nose_f3_xpm; bits[i++] = nose_f1_xpm; - bits[i++] = nose_f4_xpm; + bits[i] = nose_f4_xpm; for (i = 0; i < sizeof (images) / sizeof(*images); i++) { @@ -326,18 +327,12 @@ think (struct state *st) if (random() & 1) walk(st, FRONT); if (random() & 1) - { - st->words = get_words(st); return 1; - } return 0; } -#define MAXLINES 25 - -#undef BUFSIZ -#define BUFSIZ ((MAXLINES + 1) * 100) - +#define MAXLINES 10 +#define LINELEN 256 static void talk (struct state *st, int force_erase) @@ -348,8 +343,7 @@ talk (struct state *st, int force_erase) total = 0; register char *p, *p2; - char buf[BUFSIZ], - args[MAXLINES][256]; + char args[MAXLINES][LINELEN]; /* clear what we've written */ if (st->talking || force_erase) @@ -371,18 +365,30 @@ talk (struct state *st, int force_erase) } return; } + p = st->words; + /* If there is actually no words, just return */ + if (!*p) + { + st->talking = 0; + return; + } st->talking = 1; walk(st, FRONT); - p = strcpy(buf, st->words); for (p2 = p; *p2; p2++) if (*p2 == '\t') *p2 = ' '; if (!(p2 = strchr(p, '\n')) || !p2[1]) { + XGlyphInfo extents; + total = strlen (st->words); - strcpy (args[0], st->words); - width = XTextWidth(st->font, st->words, total); + 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 @@ -390,12 +396,20 @@ talk (struct state *st, int force_erase) for (height = 0; p; height++) { int w; + XGlyphInfo extents; *p2 = 0; - if ((w = XTextWidth(st->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!"); */ @@ -412,7 +426,7 @@ talk (struct state *st, int force_erase) * new box by 15 pixels on the sides (30 total) top and bottom. */ st->s_rect.width = width + 30; - st->s_rect.height = height * font_height(st->font) + 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) @@ -435,21 +449,26 @@ talk (struct state *st, int force_erase) st->s_rect.x + 7, st->s_rect.y + 7, st->s_rect.width - 15, st->s_rect.height - 15); st->X = 15; - st->Y = 15 + font_height(st->font); + 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++) { int L = strlen(args[Z]); - if (args[Z][L-1] == '\r' || args[Z][L-1] == '\n') + /* 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; - XDrawString(st->dpy, st->window, st->text_fg_gc, st->s_rect.x + st->X, st->s_rect.y + st->Y, - args[Z], L); - st->Y += font_height(st->font); + 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); } 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 @@ -485,74 +504,31 @@ look (struct state *st) static void -init_words (struct state *st) +fill_words (struct state *st) { - st->program = get_string_resource (st->dpy, "program", "Program"); + char *p = st->words + strlen(st->words); + char *c; + int lines = 0; + int max = MAXLINES; - if (st->program) /* get stderr on stdout, so it shows up on the window */ + for (c = st->words; c < p; c++) + if (*c == '\n') + lines++; + + while (p < st->words + sizeof(st->words) - 1 && + lines < max) { - st->orig_program = st->program; - st->program = (char *) malloc (strlen (st->program) + 10); - strcpy (st->program, "( "); - strcat (st->program, st->orig_program); - strcat (st->program, " ) 2>&1"); + int c = textclient_getc (st->tc); + if (c == '\n') + lines++; + if (c > 0) + *p++ = (char) c; + else + break; } + *p = 0; - st->words = get_words(st); -} - -static char * -get_words (struct state *st) -{ - FILE *pp; - register char *p = st->word_buf; - - st->word_buf[0] = '\0'; - - if ((pp = popen(st->program, "r"))) - { - while (fgets(p, sizeof(st->word_buf) - strlen(st->word_buf), pp)) - { - if (strlen(st->word_buf) + 1 < sizeof(st->word_buf)) - p = st->word_buf + strlen(st->word_buf); - else - break; - } - (void) pclose(pp); - if (! st->word_buf[0]) - sprintf (st->word_buf, "\"%s\" produced no output!", st->orig_program); - else if (!st->first_time && - (strstr (st->word_buf, ": not found") || - strstr (st->word_buf, ": Not found") || - strstr (st->word_buf, ": command not found") || - strstr (st->word_buf, ": Command not found"))) - switch (random () % 20) - { - case 1: strcat (st->word_buf, "( Get with the st->program, bub. )\n"); - break; - case 2: strcat (st->word_buf, - "( I blow my nose at you, you silly person! ) \n"); break; - case 3: strcat (st->word_buf, - "\nThe resource you want to\nset is `noseguy.program'\n"); - break; - case 4: - strcat(st->word_buf,"\nHelp!! Help!!\nAAAAAAGGGGHHH!! \n\n"); break; - case 5: strcpy (st->word_buf, "You have new mail.\n"); break; - case 6: - strcat(st->word_buf,"( Hello? Are you paying attention? )\n");break; - case 7: - strcat (st->word_buf, "sh: what kind of fool do you take me for? \n"); - break; - } - st->first_time = 0; - p = st->word_buf; - } - else - { - perror(st->program); - } - - return p; + st->lines = lines; } @@ -562,9 +538,10 @@ static const char *noseguy_defaults [] = { ".foreground: #CCCCCC", "*textForeground: black", "*textBackground: #CCCCCC", - "*fpsSolid: true", - "*program: xscreensaver-text --cols 40 | head -n15", - ".font: -*-new century schoolbook-*-r-*-*-*-180-*-*-*-*-*-*", + "*fpsSolid: true", + "*program: xscreensaver-text", + "*usePty: False", + ".font: -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*", 0 }; @@ -596,16 +573,26 @@ noseguy_init (Display *d, Window w) st->Height = xgwa.height + 2; cmap = xgwa.colormap; - init_words(st); + 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); - if (!fontname || !*fontname) - fprintf (stderr, "%s: no font specified.\n", progname); - st->font = XLoadQueryFont(st->dpy, fontname); - if (!st->font) { - fprintf (stderr, "%s: could not load font %s.\n", progname, fontname); - exit(1); - } + 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"); @@ -617,26 +604,25 @@ noseguy_init (Display *d, Window w) if (! get_string_resource (st->dpy, "textBackground", "Background")) text_bg = fg; - gcvalues.font = st->font->fid; gcvalues.foreground = fg; gcvalues.background = bg; st->fg_gc = XCreateGC (st->dpy, st->window, - GCForeground|GCBackground|GCFont, + GCForeground|GCBackground, &gcvalues); gcvalues.foreground = bg; gcvalues.background = fg; st->bg_gc = XCreateGC (st->dpy, st->window, - GCForeground|GCBackground|GCFont, + GCForeground|GCBackground, &gcvalues); gcvalues.foreground = text_fg; gcvalues.background = text_bg; st->text_fg_gc = XCreateGC (st->dpy, st->window, - GCForeground|GCBackground|GCFont, + GCForeground|GCBackground, &gcvalues); gcvalues.foreground = text_bg; gcvalues.background = text_fg; st->text_bg_gc = XCreateGC (st->dpy, st->window, - GCForeground|GCBackground|GCFont, + GCForeground|GCBackground, &gcvalues); st->x = st->Width / 2; st->y = st->Height / 2; @@ -650,6 +636,7 @@ static unsigned long noseguy_draw (Display *dpy, Window window, void *closure) { struct state *st = (struct state *) closure; + fill_words(st); st->next_fn(st); return (st->interval * 1000); } @@ -658,6 +645,9 @@ 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 @@ -669,6 +659,9 @@ noseguy_event (Display *dpy, Window window, void *closure, XEvent *event) 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)