summaryrefslogtreecommitdiffstats
path: root/hacks/xsublim.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/xsublim.c')
-rw-r--r--hacks/xsublim.c799
1 files changed, 799 insertions, 0 deletions
diff --git a/hacks/xsublim.c b/hacks/xsublim.c
new file mode 100644
index 0000000..719de50
--- /dev/null
+++ b/hacks/xsublim.c
@@ -0,0 +1,799 @@
+/****************************************************************************
+ * *
+ * xsublim -- Submit. Conform. Obey. *
+ * *
+ * Copyright (c) 1999 - 2000 Greg Knauss (greg@eod.com) *
+ * *
+ * Thanks to Jamie Zawinski, whose suggestions and advice made what was a *
+ * boring little program into a less boring (and a _lot_ less little) *
+ * program. *
+ * *
+ * Permission to use, copy, modify, distribute, and sell this software and *
+ * its documentation for any purpose is hereby granted without fee, provided *
+ * that the above copyright notice appear in all copies and that both that *
+ * copyright notice and this permission notice appear in supporting *
+ * documentation. No representations are made about the suitability of this *
+ * software for any purpose. It is provided "as is" without express or *
+ * implied warranty. *
+ * *
+ * Stare into the subliminal for as long as you can... *
+ * *
+ *****************************************************************************/
+
+
+/* Warnings *******************************************************************
+
+ Please don't end this process with a SIGKILL. If it's got the X server
+ grabbed when you do, you'll never get it back and it won't be my fault.
+*/
+
+
+/* Arguments ******************************************************************
+
+ -font font Font to use
+ -file filename New-line delimited phrase file
+ -program executable New-line delimited phrase-producing executable
+ -delayShow ms Microsecs for display of each word
+ -delayWord ms Microsecs for blank between words
+ -delayPhraseMin ms Microsecs for min blank between phrases
+ -delayPhraseMax ms Microsecs for max blank between phrases
+ -random Show phrases in random order (Default)
+ -no-random Show phrases in listed order
+ -screensaver Wait for an active screensaver (Default)
+ -no-screensaver Draw over active windows
+ -outline Draw a contrasting outline around words (Default)
+ -no-outline Draw words without an outline
+ -center Draw words in the center of the screen (Default)
+ -no-center Draw words randomly around the screen
+*/
+
+
+/* Changelog ******************************************************************
+
+ 1.1.1 20000407 Added -program
+ 1.1.0 19991221 Added -file
+ 1.0.1 19990716 Assume that XGetImage()/XDestroyImage() don't leak,
+ which they apparently don't. I have no idea how I
+ convinced myself that they did. Huh. (greg@eod.com)
+ 1.0.0 19990716 Initial release
+*/
+
+
+/* Defines *******************************************************************/
+#define XSUBLIM_NAME "XSublim"
+#define XSUBLIM_TEXT_COUNT 1000
+#define XSUBLIM_TEXT_LENGTH 128
+#define XSUBLIM_TEXT_OUTLINE 1
+#define XSUBLIM_PROGRAM_SIZE 1024*10
+#define XSUBLIM_ARG_DELAYSHOW "delayShow"
+#define XSUBLIM_ARG_DELAYWORD "delayWord"
+#define XSUBLIM_ARG_DELAYPHRASEMIN "delayPhraseMin"
+#define XSUBLIM_ARG_DELAYPHRASEMAX "delayPhraseMax"
+#define XSUBLIM_ARG_RANDOM "random"
+#define XSUBLIM_ARG_FILE "file"
+#define XSUBLIM_ARG_PROGRAM "program"
+#define XSUBLIM_ARG_SCREENSAVER "screensaver"
+#define XSUBLIM_ARG_OUTLINE "outline"
+#define XSUBLIM_ARG_CENTER "center"
+#define XSUBLIM_ARG_FONT "font"
+#define XSUBLIM_ARG_PHRASES "phrases"
+#ifndef TRUE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+
+/* Includes ******************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <X11/Intrinsic.h>
+#include <X11/IntrinsicP.h>
+#include <X11/CoreP.h>
+#include <X11/Shell.h>
+#include <X11/StringDefs.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Xproto.h>
+#if defined(__sgi)
+#include <X11/SGIScheme.h>
+#endif
+
+#include "usleep.h"
+#include "yarandom.h"
+#include "resources.h"
+#include "font-retry.h"
+#include "vroot.h"
+
+
+/* Globals *******************************************************************/
+char* progname;
+char* progclass = XSUBLIM_NAME;
+
+# ifdef __GNUC__
+ __extension__ /* don't warn about "string length is greater than the
+ length ISO C89 compilers are required to support"
+ in the following string constant... */
+# endif
+
+static char* defaults[] =
+{
+ ".background: #000000",
+ ".foreground: #FFFFFF",
+ "*" XSUBLIM_ARG_PHRASES ":"
+ "Submit.\\n"
+ "Conform.\\n"
+ "Obey.\\n"
+ "OBEY. OBEY. OBEY.\\n"
+ "Consume.\\n"
+ "Be silent.\\n"
+ "Fear.\\n"
+ "Waste.\\n"
+ "Money.\\n"
+ "Watch TV.\\n"
+ "Hate yourself.\\n"
+ "Buy needlessly.\\n"
+ "Despair quietly.\\n"
+ "God hates you.\\n"
+ "You are being watched.\\n"
+ "You will be punished.\\n"
+ "You serve no purpose.\\n"
+ "Your contributions are ignored.\\n"
+ "They are laughing at you.\\n"
+ "They lied to you.\\n"
+ "They read your mail.\\n"
+ "They know.\\n"
+ "Surrender.\\n"
+ "You will fail.\\n"
+ "Never question.\\n"
+ "You are a prisoner.\\n"
+ "You are helpless.\\n"
+ "You are diseased.\\n"
+ "Fear the unknown.\\n"
+ "Happiness follows obedience.\\n"
+ "Ignorance is strength.\\n"
+ "War is peace.\\n"
+ "Freedom is slavery.\\n"
+ "Abandon all hope.\\n"
+ "You will be assimilated.\\n"
+ "Resistance is futile.\\n"
+ "Resistance is useless.\\n"
+ "Life is pain.\\n"
+ "No escape.\\n"
+ "What's that smell?\\n"
+ "All praise the company.\\n"
+ "Fnord.\\n",
+ "*" XSUBLIM_ARG_FONT ": -*-utopia-*-r-*-*-*-600-*-*-p-*-*-*",
+ "*" XSUBLIM_ARG_DELAYSHOW ": 40000",
+ "*" XSUBLIM_ARG_DELAYWORD ": 100000",
+ "*" XSUBLIM_ARG_DELAYPHRASEMIN ": 5000000",
+ "*" XSUBLIM_ARG_DELAYPHRASEMAX ": 20000000",
+ "*" XSUBLIM_ARG_RANDOM ": true",
+ "*" XSUBLIM_ARG_SCREENSAVER ": true",
+ "*" XSUBLIM_ARG_OUTLINE": true",
+ "*" XSUBLIM_ARG_CENTER": true",
+ NULL
+};
+
+static XrmOptionDescRec options[] =
+{
+ {"-" XSUBLIM_ARG_FONT, "." XSUBLIM_ARG_FONT,
+ XrmoptionSepArg,0},
+ {"-" XSUBLIM_ARG_DELAYSHOW, "." XSUBLIM_ARG_DELAYSHOW,
+ XrmoptionSepArg,0},
+ {"-" XSUBLIM_ARG_DELAYWORD, "." XSUBLIM_ARG_DELAYWORD,
+ XrmoptionSepArg,0},
+ {"-" XSUBLIM_ARG_DELAYPHRASEMIN,"." XSUBLIM_ARG_DELAYPHRASEMIN,
+ XrmoptionSepArg,0},
+ {"-" XSUBLIM_ARG_DELAYPHRASEMAX,"." XSUBLIM_ARG_DELAYPHRASEMAX,
+ XrmoptionSepArg,0},
+ {"-" XSUBLIM_ARG_RANDOM, "." XSUBLIM_ARG_RANDOM,
+ XrmoptionNoArg,"true"},
+ {"-no-" XSUBLIM_ARG_RANDOM, "." XSUBLIM_ARG_RANDOM,
+ XrmoptionNoArg,"false"},
+ {"-" XSUBLIM_ARG_FILE, "." XSUBLIM_ARG_FILE,
+ XrmoptionSepArg,0 },
+#if !defined(VMS)
+ {"-" XSUBLIM_ARG_PROGRAM, "." XSUBLIM_ARG_PROGRAM,
+ XrmoptionSepArg,0 },
+#endif
+ {"-" XSUBLIM_ARG_SCREENSAVER, "." XSUBLIM_ARG_SCREENSAVER,
+ XrmoptionNoArg,"true"},
+ {"-no-" XSUBLIM_ARG_SCREENSAVER,"." XSUBLIM_ARG_SCREENSAVER,
+ XrmoptionNoArg,"false"},
+ {"-" XSUBLIM_ARG_OUTLINE, "." XSUBLIM_ARG_OUTLINE,
+ XrmoptionNoArg,"true"},
+ {"-no-" XSUBLIM_ARG_OUTLINE, "." XSUBLIM_ARG_OUTLINE,
+ XrmoptionNoArg,"false"},
+ {"-" XSUBLIM_ARG_CENTER, "." XSUBLIM_ARG_CENTER,
+ XrmoptionNoArg,"true"},
+ {"-no-" XSUBLIM_ARG_CENTER, "." XSUBLIM_ARG_CENTER,
+ XrmoptionNoArg,"false"},
+ {NULL, NULL,
+ 0, 0 }
+};
+static int Xsublim_Sig_Last;
+
+
+/* Functions *****************************************************************/
+
+/* Defer signals to protect the server grab ================================ */
+static void xsublim_Sig_Catch(int sig_Number)
+{
+ /* BSD needs this reset each time, and it shouldn't hurt anything
+ else */
+ signal(sig_Number,xsublim_Sig_Catch);
+ Xsublim_Sig_Last = sig_Number;
+}
+
+/* This was all basically swiped from driver/remote.c and util/vroot.h */
+static Window xsublim_Ss_GetWindow(Display* ss_Display)
+{
+ Screen *s = DefaultScreenOfDisplay (ss_Display);
+ Window root = XRootWindowOfScreen (s);
+ Window vroot = VirtualRootWindowOfScreen (s);
+ if (root == vroot)
+ return 0;
+ else
+ return vroot;
+}
+
+/* Main ==================================================================== */
+static XErrorHandler Xsublim_Sh_Handler = NULL;
+static int Xsublim_Sh_Status = 0;
+
+static int xsublim_Sh_Handler(Display* handle_Display,
+ XErrorEvent* handle_Error)
+{
+ if (handle_Error->error_code == BadMatch)
+ {
+ Xsublim_Sh_Status = BadMatch;
+ return 0;
+ }
+ if (Xsublim_Sh_Handler == NULL)
+ {
+ fprintf(stderr,"%s: ",progname);
+ abort();
+ }
+ return (*Xsublim_Sh_Handler)(handle_Display,handle_Error);
+}
+
+
+int main(int argc,char* argv[])
+{
+ XtAppContext app;
+ int sig_Number;
+ int sig_Signal[] =
+ {
+ SIGHUP,
+ SIGINT,
+ SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+#if defined(SIGIOT)
+ SIGIOT,
+#endif
+ SIGABRT,
+#if defined(SIGEMT)
+ SIGEMT,
+#endif
+ SIGFPE,
+ SIGBUS,
+ SIGSEGV,
+#if defined(SIGSYS)
+ SIGSYS,
+#endif
+ SIGTERM,
+#if defined(SIGXCPU)
+ SIGXCPU,
+#endif
+#if defined(SIGXFSZ)
+ SIGXFSZ,
+#endif
+#if defined(SIGDANGER)
+ SIGDANGER,
+#endif
+ -1
+ };
+ Widget app_App;
+ Display* dpy;
+ Window win_Root;
+ XWindowAttributes attr_Win;
+ XGCValues gc_ValFore;
+ XGCValues gc_ValBack;
+ GC gc_GcFore;
+ GC gc_GcBack;
+ XFontStruct* font_Font;
+ char* font_List[] =
+ {
+ "-*-character-*-r-*-*-*-600-*-*-p-*-*-*",
+ "-*-helvetica-*-r-*-*-*-600-*-*-p-*-*-*",
+ "-*-lucida-*-r-*-*-*-600-*-*-p-*-*-*",
+ "-*-*-*-r-*-sans-*-600-*-*-p-*-*-*",
+ "-*-*-*-r-*-*-*-600-*-*-m-*-*-*",
+ "-*-helvetica-*-r-*-*-*-240-*-*-p-*-*-*",
+ "-*-lucida-*-r-*-*-*-240-*-*-p-*-*-*",
+ "-*-*-*-r-*-sans-*-240-*-*-p-*-*-*",
+ "-*-*-*-r-*-*-*-240-*-*-m-*-*-*",
+ "fixed",
+ NULL
+ };
+ int font_Index;
+ int text_Length;
+ int text_X;
+ int text_Y;
+ int text_Width;
+ int text_Height;
+ char* text_List[XSUBLIM_TEXT_COUNT];
+ int text_Used[XSUBLIM_TEXT_COUNT];
+ char text_Text[XSUBLIM_TEXT_LENGTH+1];
+ char* text_Phrase;
+ char* text_Word;
+ int text_Index;
+ int text_Item;
+ int text_Count;
+ struct
+ {
+ int outline_X;
+ int outline_Y;
+ } text_Outline[] =
+ {
+ { -1,-1 },
+ { 1,-1 },
+ { -1, 1 },
+ { 1, 1 },
+ { 0, 0 }
+ };
+ int text_OutlineIndex;
+ XImage* image_Image = NULL;
+ int image_X = 0;
+ int image_Y = 0;
+ int image_Width = 0;
+ int image_Height = 0;
+ int arg_Count;
+ int arg_FlagCenter;
+ int arg_FlagOutline;
+ int arg_FlagScreensaver;
+ int arg_FlagRandom;
+ int arg_DelayShow;
+ int arg_DelayWord;
+ int arg_DelayPhraseMin;
+ int arg_DelayPhraseMax;
+ char* arg_Text;
+ char* arg_Source;
+
+ /* Set-up ---------------------------------------------------------- */
+
+ /* Catch signals */
+ Xsublim_Sig_Last = -1;
+ for (sig_Number = 0;sig_Signal[sig_Number] != -1;sig_Number++)
+ {
+ signal(sig_Number,xsublim_Sig_Catch);
+ }
+
+ /* Randomize -- only need to do this here because this program
+ doesn't use the `screenhack.h' or `lockmore.h' APIs. */
+# undef ya_rand_init
+ ya_rand_init (0);
+
+ /* Handle all the X nonsense */
+#if defined(__sgi)
+ SgiUseSchemes("none");
+#endif
+ for (arg_Count = 0;options[arg_Count].option != NULL;arg_Count++)
+ {
+ ;
+ }
+ app_App = XtAppInitialize(&app,progclass,options,arg_Count,&argc,argv,
+ defaults,0,0);
+
+ /* jwz */
+ if (argc > 1)
+ {
+ int x = 18;
+ int end = 78;
+ int i;
+ int count = (sizeof(options)/sizeof(*options))-1;
+ fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
+ fprintf (stderr, "Options include: ");
+ for (i = 0; i < count; i++)
+ {
+ char *sw = options [i].option;
+ Bool argp = (options [i].argKind == XrmoptionSepArg);
+ int size = strlen (sw) + (argp ? 6 : 0) + 2;
+ if (x + size >= end)
+ {
+ fprintf (stderr, "\n\t\t ");
+ x = 18;
+ }
+ x += size;
+ fprintf (stderr, "%s", sw);
+ if (argp) fprintf (stderr, " <arg>");
+ if (i != count-1) fprintf (stderr, ", ");
+ }
+ fprintf (stderr, ".\n");
+ exit (-1);
+ }
+
+ dpy = XtDisplay(app_App);
+ XtGetApplicationNameAndClass(dpy,&progname,&progclass);
+ win_Root = RootWindowOfScreen(XtScreen(app_App));
+ XtDestroyWidget(app_App);
+
+ /* Get the arguments */
+ arg_FlagCenter = get_boolean_resource(dpy, XSUBLIM_ARG_CENTER,"Boolean");
+ arg_FlagOutline = get_boolean_resource(dpy, XSUBLIM_ARG_OUTLINE,"Boolean");
+ arg_FlagScreensaver = get_boolean_resource(dpy, XSUBLIM_ARG_SCREENSAVER,
+ "Boolean");
+ arg_FlagRandom = get_boolean_resource(dpy, XSUBLIM_ARG_RANDOM,"Boolean");
+ arg_DelayShow = get_integer_resource(dpy, XSUBLIM_ARG_DELAYSHOW,"Integer");
+ arg_DelayWord = get_integer_resource(dpy, XSUBLIM_ARG_DELAYWORD,"Integer");
+ arg_DelayPhraseMin = get_integer_resource(dpy, XSUBLIM_ARG_DELAYPHRASEMIN,
+ "Integer");
+ arg_DelayPhraseMax = get_integer_resource(dpy, XSUBLIM_ARG_DELAYPHRASEMAX,
+ "Integer");
+ if (arg_DelayPhraseMax < arg_DelayPhraseMin)
+ {
+ arg_DelayPhraseMax = arg_DelayPhraseMin;
+ }
+
+ /* Get the phrases */
+ text_Index = 0;
+ text_Item = 0;
+ text_Count = 0;
+ memset(text_Used,0,sizeof(text_Used));
+ arg_Source = get_string_resource(dpy, XSUBLIM_ARG_FILE,"Filename");
+ if (arg_Source != NULL)
+ {
+ FILE* file_Fs;
+ struct stat file_Stat;
+
+ file_Fs = fopen(arg_Source,"rb");
+ if (file_Fs == NULL)
+ {
+ fprintf(stderr,"%s: Could not open '%s'\n",progname,
+ arg_Source);
+ exit(-1);
+ }
+ if (fstat(fileno(file_Fs),&file_Stat) != 0)
+ {
+ fprintf(stderr,"%s: Could not stat '%s'\n",progname,
+ arg_Source);
+ exit(-1);
+ }
+ arg_Text = calloc(1,file_Stat.st_size+1);
+ if (arg_Text != NULL)
+ {
+ if (fread(arg_Text,file_Stat.st_size,1,file_Fs) != 1)
+ {
+ fprintf(stderr,"%s: Could not read '%s'\n",
+ progname,arg_Source);
+ exit(-1);
+ }
+ }
+ fclose(file_Fs);
+ }
+ else
+ {
+ arg_Source = get_string_resource(dpy, XSUBLIM_ARG_PROGRAM,
+ "Executable");
+ if (arg_Source != NULL)
+ {
+ char* exe_Command = calloc(1,strlen(arg_Source)+10);
+ FILE* exe_Fs;
+
+ if (exe_Command == NULL)
+ {
+ fprintf(stderr,
+ "%s: Could not allocate space for '%s'\n",
+ progname,arg_Source);
+ exit(-1);
+ }
+ sprintf(exe_Command,"( %s ) 2>&1",arg_Source);
+
+ exe_Fs = popen(exe_Command,"r");
+ if (exe_Fs == NULL)
+ {
+ fprintf(stderr,"%s: Could not run '%s'\n",
+ progname,arg_Source);
+ exit(-1);
+ }
+ arg_Text = calloc(1,XSUBLIM_PROGRAM_SIZE);
+ if (arg_Text != NULL)
+ {
+ if (fread(arg_Text,1,XSUBLIM_PROGRAM_SIZE,
+ exe_Fs) <= 0)
+ {
+ fprintf(stderr,
+ "%s: Could not read output of '%s'\n",
+ progname,arg_Source);
+ exit(-1);
+ }
+ if (
+ strstr(arg_Text,": not found") ||
+ strstr(arg_Text,": Not found") ||
+ strstr(arg_Text,": command not found") ||
+ strstr(arg_Text,": Command not found"))
+ {
+ fprintf(stderr,
+ "%s: Could not find '%s'\n",
+ progname,arg_Source);
+ exit(-1);
+ }
+ }
+ fclose(exe_Fs);
+ }
+ else
+ {
+ arg_Text =
+ get_string_resource(dpy, XSUBLIM_ARG_PHRASES,"Phrases");
+ if (arg_Text != NULL)
+ {
+ arg_Text = strdup(arg_Text);
+ }
+ }
+ }
+ if (arg_Text != NULL)
+ {
+ while (((text_Phrase = strtok(arg_Text,"\n")) != NULL) &&
+ (text_Count < XSUBLIM_TEXT_COUNT))
+ {
+ arg_Text = NULL;
+ text_List[text_Count] = text_Phrase;
+ text_Count++;
+ }
+ text_List[text_Count] = NULL;
+ }
+ if (text_Count == 0)
+ {
+ fprintf(stderr,"%s: No text to display\n",progname);
+ exit(-1);
+ }
+
+ /* Load the font */
+ font_Font = load_font_retry(dpy,
+ get_string_resource(dpy, XSUBLIM_ARG_FONT,"Font"));
+ font_Index = 0;
+ while ((font_Font == NULL) && (font_List[font_Index] != NULL))
+ {
+ font_Font = load_font_retry(dpy,font_List[font_Index]);
+ font_Index++;
+ }
+ if (font_Font == NULL)
+ {
+ fprintf(stderr,"%s: Couldn't load a font\n",progname);
+ exit(-1);
+ }
+
+ /* Create the GCs */
+ XGetWindowAttributes(dpy,win_Root,&attr_Win);
+ gc_ValFore.font = font_Font->fid;
+ gc_ValFore.foreground = get_pixel_resource(dpy,
+ attr_Win.colormap,
+ "foreground","Foreground");
+ gc_ValFore.background = get_pixel_resource(dpy,
+ attr_Win.colormap,
+ "background","Background");
+ gc_ValFore.subwindow_mode = IncludeInferiors;
+ gc_GcFore = XCreateGC(dpy,win_Root,
+ (GCFont|GCForeground|GCBackground|GCSubwindowMode),&gc_ValFore);
+ gc_ValBack.font = font_Font->fid;
+ gc_ValBack.foreground = get_pixel_resource(dpy,
+ attr_Win.colormap,
+ "background","Background");
+ gc_ValBack.background = get_pixel_resource(dpy,
+ attr_Win.colormap,
+ "foreground","Foreground");
+ gc_ValBack.subwindow_mode = IncludeInferiors;
+ gc_GcBack = XCreateGC(dpy,win_Root,
+ (GCFont|GCForeground|GCBackground|GCSubwindowMode),&gc_ValBack);
+
+ /* Loop ------------------------------------------------------------ */
+ while (Xsublim_Sig_Last == -1)
+ {
+ /* Once-per-phrase stuff ----------------------------------- */
+
+ /* If we're waiting for a screensaver... */
+ if (arg_FlagScreensaver != FALSE)
+ {
+ /* Find the screensaver's window */
+ win_Root = xsublim_Ss_GetWindow(dpy);
+ if (win_Root == 0)
+ {
+ usleep(30000000);
+ continue;
+ }
+ }
+
+ /* Pick the next phrase */
+ if (arg_FlagRandom != FALSE)
+ {
+ text_Item = random()%text_Count;
+ text_Index = 0;
+ }
+ while (text_Used[text_Item] != FALSE)
+ {
+ text_Index++;
+ text_Item++;
+ if (text_Index == text_Count)
+ {
+ text_Index = 0;
+ memset(text_Used,0,sizeof(text_Used));
+ }
+ if (text_List[text_Item] == NULL)
+ {
+ text_Item = 0;
+ }
+ }
+ text_Used[text_Item] = TRUE;
+ strncpy(text_Text,text_List[text_Item],
+ XSUBLIM_TEXT_LENGTH);
+ text_Phrase = text_Text;
+
+ /* Run through the phrase */
+ while (((text_Word = strtok(text_Phrase," \t")) != NULL) &&
+ (Xsublim_Sig_Last == -1))
+ {
+ text_Phrase = NULL;
+
+ /* Once-per-word stuff ----------------------------- */
+
+ /* Find the text's position */
+ XGetWindowAttributes(dpy,win_Root,&attr_Win);
+ text_Length = strlen(text_Word);
+ text_Width = XTextWidth(font_Font,text_Word,
+ text_Length)+XSUBLIM_TEXT_OUTLINE*2;
+ text_Height = font_Font->ascent+font_Font->descent+1+
+ XSUBLIM_TEXT_OUTLINE*2;
+ if (arg_FlagCenter == FALSE)
+ {
+ text_X = random()%(attr_Win.width-text_Width);
+ text_Y = random()%(attr_Win.height-
+ text_Height);
+ }
+ else
+ {
+ text_X = (attr_Win.width/2)-(text_Width/2);
+ text_Y = (attr_Win.height/2)-(text_Height/2);
+ }
+
+ /* Find the image's position (and pad it out slightly,
+ otherwise bits of letter get left behind -- are
+ there boundry issues I don't know about?) */
+ image_X = text_X-16;
+ image_Y = text_Y;
+ image_Width = text_Width+32;
+ image_Height = text_Height;
+ if (image_X < 0)
+ {
+ image_X = 0;
+ }
+ if (image_Y < 0)
+ {
+ image_Y = 0;
+ }
+ if (image_X+image_Width > attr_Win.width)
+ {
+ image_Width = attr_Win.width-image_X;
+ }
+ if (image_Y+image_Height > attr_Win.height)
+ {
+ image_Height = attr_Win.height-image_Y;
+ }
+
+ /* Influence people for our own ends --------------- */
+
+ /* Grab the server -- we can't let anybody draw over
+ us */
+ XSync(dpy,FALSE);
+ XGrabServer(dpy);
+ XSync(dpy,FALSE);
+
+ /* Set up an error handler that ignores BadMatches --
+ since the screensaver can take its window away at
+ any time, any call that uses it might choke */
+ Xsublim_Sh_Status = 0;
+ Xsublim_Sh_Handler =
+ XSetErrorHandler(xsublim_Sh_Handler);
+
+ /* Save the current background */
+ image_Image = XGetImage(dpy,win_Root,image_X,
+ image_Y,image_Width,image_Height,~0L,ZPixmap);
+
+ /* If we've successfully saved the background... */
+ if (image_Image != NULL)
+ {
+ if (Xsublim_Sh_Status == 0)
+ {
+ /* Draw the outline */
+ if (arg_FlagOutline != FALSE)
+ {
+ for (text_OutlineIndex = 0;
+ text_Outline[
+ text_OutlineIndex].outline_X
+ != 0;text_OutlineIndex++)
+ {
+ /* Y'know, eight
+ character tabs and
+ descriptive variable
+ names become
+ annoying at some
+ point... */
+ XDrawString(
+ dpy,
+ win_Root,gc_GcBack,
+ text_X+text_Outline[
+ text_OutlineIndex].
+ outline_X*
+ XSUBLIM_TEXT_OUTLINE,
+ text_Y+
+ (font_Font->ascent)+
+ text_Outline[
+ text_OutlineIndex].
+ outline_Y*
+ XSUBLIM_TEXT_OUTLINE,
+ text_Word,
+ text_Length);
+ }
+ }
+
+ /* Draw the word */
+ XDrawString(dpy,win_Root,
+ gc_GcFore,text_X,
+ text_Y+(font_Font->ascent),text_Word,
+ text_Length);
+ }
+ if (Xsublim_Sh_Status == 0)
+ {
+ /* Wait a bit */
+ XSync(dpy,FALSE);
+ if (Xsublim_Sig_Last == -1)
+ {
+ usleep(arg_DelayShow);
+ }
+
+ /* Restore the background */
+ XPutImage(dpy,win_Root,
+ gc_GcFore,image_Image,0,0,image_X,
+ image_Y,image_Width,image_Height);
+ }
+
+ /* Free the image */
+ XDestroyImage(image_Image);
+ }
+
+ /* Restore the error handler, ungrab the server */
+ XSync(dpy,FALSE);
+ XSetErrorHandler(Xsublim_Sh_Handler);
+ XUngrabServer(dpy);
+ XSync(dpy,FALSE);
+
+ /* Pause between words */
+ if (Xsublim_Sig_Last == -1)
+ {
+ usleep(arg_DelayWord);
+ }
+ }
+
+ /* Pause between phrases */
+ if (Xsublim_Sig_Last == -1)
+ {
+ usleep(random()%(arg_DelayPhraseMax-
+ arg_DelayPhraseMin+1)+arg_DelayPhraseMin);
+ }
+ }
+
+ /* Exit ------------------------------------------------------------ */
+ for (sig_Number = 0;sig_Signal[sig_Number] != -1;sig_Number++)
+ {
+ signal(sig_Number,SIG_DFL);
+ }
+ kill(getpid(),Xsublim_Sig_Last);
+
+ return 0;
+}