/*
- * starwars, Copyright (c) 1998-2001 Jamie Zawinski <jwz@jwz.org> and
+ * starwars, Copyright (c) 1998-2001, 2004 Jamie Zawinski <jwz@jwz.org> and
* Claudio Matsuoka <claudio@helllabs.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
#define HACK_RESHAPE reshape_sws
#define sws_opts xlockmore_opts
-#define DEF_PROGRAM ZIPPY_PROGRAM
+#define DEF_PROGRAM "(default)"
#define DEF_LINES "125"
#define DEF_STEPS "35"
#define DEF_SPIN "0.03"
#ifdef USE_GL /* whole file */
+#include <ctype.h>
#include <GL/glu.h>
+#include <sys/stat.h>
#include "glutstroke.h"
#include "glut_roman.h"
#define GLUT_FONT (&glutStrokeRoman)
+#ifdef HAVE_UNAME
+# include <sys/utsname.h>
+#endif /* HAVE_UNAME */
+
typedef struct {
GLXContext *glx_context;
static int alignment;
static XrmOptionDescRec opts[] = {
- {"-program", ".starwars.program", XrmoptionSepArg, (caddr_t) 0 },
- {"-lines", ".starwars.lines", XrmoptionSepArg, (caddr_t) 0 },
- {"-steps", ".starwars.steps", XrmoptionSepArg, (caddr_t) 0 },
- {"-spin", ".starwars.spin", XrmoptionSepArg, (caddr_t) 0 },
- {"-size", ".starwars.fontSize", XrmoptionSepArg, (caddr_t) 0 },
- {"-columns", ".starwars.columns", XrmoptionSepArg, (caddr_t) 0 },
- {"-smooth", ".starwars.smooth", XrmoptionNoArg, (caddr_t) "True" },
- {"-no-smooth", ".starwars.smooth", XrmoptionNoArg, (caddr_t) "False" },
- {"-thick", ".starwars.thick", XrmoptionNoArg, (caddr_t) "True" },
- {"-no-thick", ".starwars.thick", XrmoptionNoArg, (caddr_t) "False" },
- {"-fade", ".starwars.fade", XrmoptionNoArg, (caddr_t) "True" },
- {"-no-fade", ".starwars.fade", XrmoptionNoArg, (caddr_t) "False" },
- {"-wrap", ".starwars.lineWrap", XrmoptionNoArg, (caddr_t) "True" },
- {"-no-wrap", ".starwars.lineWrap", XrmoptionNoArg, (caddr_t) "False" },
- {"-nowrap", ".starwars.lineWrap", XrmoptionNoArg, (caddr_t) "False" },
- {"-left", ".starwars.alignment",XrmoptionNoArg, (caddr_t) "Left" },
- {"-right", ".starwars.alignment",XrmoptionNoArg, (caddr_t) "Right" },
- {"-center", ".starwars.alignment",XrmoptionNoArg, (caddr_t) "Center" },
+ {"-program", ".starwars.program", XrmoptionSepArg, 0 },
+ {"-lines", ".starwars.lines", XrmoptionSepArg, 0 },
+ {"-steps", ".starwars.steps", XrmoptionSepArg, 0 },
+ {"-spin", ".starwars.spin", XrmoptionSepArg, 0 },
+ {"-size", ".starwars.fontSize", XrmoptionSepArg, 0 },
+ {"-columns", ".starwars.columns", XrmoptionSepArg, 0 },
+ {"-smooth", ".starwars.smooth", XrmoptionNoArg, "True" },
+ {"-no-smooth", ".starwars.smooth", XrmoptionNoArg, "False" },
+ {"-thick", ".starwars.thick", XrmoptionNoArg, "True" },
+ {"-no-thick", ".starwars.thick", XrmoptionNoArg, "False" },
+ {"-fade", ".starwars.fade", XrmoptionNoArg, "True" },
+ {"-no-fade", ".starwars.fade", XrmoptionNoArg, "False" },
+ {"-wrap", ".starwars.lineWrap", XrmoptionNoArg, "True" },
+ {"-no-wrap", ".starwars.lineWrap", XrmoptionNoArg, "False" },
+ {"-nowrap", ".starwars.lineWrap", XrmoptionNoArg, "False" },
+ {"-left", ".starwars.alignment",XrmoptionNoArg, "Left" },
+ {"-right", ".starwars.alignment",XrmoptionNoArg, "Right" },
+ {"-center", ".starwars.alignment",XrmoptionNoArg, "Center" },
};
static argtype vars[] = {
- {(caddr_t *) &program, "program", "Program", DEF_PROGRAM, t_String},
- {(caddr_t *) &max_lines, "lines", "Integer", DEF_LINES, t_Int},
- {(caddr_t *) &scroll_steps, "steps", "Integer", DEF_STEPS, t_Int},
- {(caddr_t *) &star_spin, "spin", "Float", DEF_SPIN, t_Float},
- {(caddr_t *) &font_size, "fontSize","Float", DEF_STEPS, t_Float},
- {(caddr_t *) &target_columns, "columns", "Integer", DEF_COLUMNS, t_Int},
- {(caddr_t *) &wrap_p, "lineWrap","Boolean", DEF_COLUMNS, t_Bool},
- {(caddr_t *) &alignment_str, "alignment","Alignment",DEF_ALIGN, t_String},
- {(caddr_t *) &smooth_p, "smooth", "Boolean", DEF_SMOOTH, t_Bool},
- {(caddr_t *) &thick_p, "thick", "Boolean", DEF_THICK, t_Bool},
- {(caddr_t *) &fade_p, "fade", "Boolean", DEF_FADE, t_Bool},
+ {&program, "program", "Program", DEF_PROGRAM, t_String},
+ {&max_lines, "lines", "Integer", DEF_LINES, t_Int},
+ {&scroll_steps, "steps", "Integer", DEF_STEPS, t_Int},
+ {&star_spin, "spin", "Float", DEF_SPIN, t_Float},
+ {&font_size, "fontSize", "Float", DEF_STEPS, t_Float},
+ {&target_columns, "columns", "Integer", DEF_COLUMNS, t_Int},
+ {&wrap_p, "lineWrap", "Boolean", DEF_COLUMNS, t_Bool},
+ {&alignment_str, "alignment", "Alignment", DEF_ALIGN, t_String},
+ {&smooth_p, "smooth", "Boolean", DEF_SMOOTH, t_Bool},
+ {&thick_p, "thick", "Boolean", DEF_THICK, t_Bool},
+ {&fade_p, "fade", "Boolean", DEF_FADE, t_Bool},
};
ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
}
+/* The GLUT font only has ASCII characters in them, so do what we can to
+ convert Latin1 characters to the nearest ASCII equivalent...
+ */
+static void
+latin1_to_ascii (char *s)
+{
+ unsigned char *us = (unsigned char *) s;
+ const unsigned char ascii[95] = {
+ '!', 'C', '#', '#', 'Y', '|', 'S', '_', 'C', '?', '<', '=', '-', 'R', '_',
+ '?', '?', '2', '3', '\'','u', 'P', '.', ',', '1', 'o', '>', '?', '?', '?',
+ '?', 'A', 'A', 'A', 'A', 'A', 'A', 'E', 'C', 'E', 'E', 'E', 'E', 'I', 'I',
+ 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'x', '0', 'U', 'U', 'U', 'U',
+ 'Y', 'p', 'S', 'a', 'a', 'a', 'a', 'a', 'a', 'e', 'c', 'e', 'e', 'e', 'e',
+ 'i', 'i', 'i', 'i', 'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', 'o', 'u', 'u',
+ 'u', 'u', 'y', 'p', 'y' };
+ while (*us)
+ {
+ if (*us >= 161)
+ *us = ascii[*us - 161];
+ else if (*us > 127)
+ *us = '?';
+ us++;
+ }
+}
+
\f
/* Subprocess.
(This bit mostly cribbed from phosphor.c)
launch_text_generator (sws_configuration *sc)
{
char *oprogram = get_string_resource ("program", "Program");
- char *program = (char *) malloc (strlen (oprogram) + 10);
+ char *program;
+
+ if (!strcasecmp(oprogram, "(default)"))
+ {
+ oprogram = FORTUNE_PROGRAM;
+
+#if defined(__linux__) && defined(HAVE_UNAME)
+ {
+ static int done_once = 0;
+ if (!done_once)
+ {
+ struct utsname uts;
+ struct stat st;
+ done_once = 1;
+ if (uname (&uts) == 0)
+ {
+ static char cmd[200];
+ char *s;
+ /* strip version at the first non-digit-dash-dot, to
+ lose any "SMP" crap at the end. */
+ for (s = uts.release; *s; s++)
+ if (!isdigit(*s) && *s != '.' && *s != '-')
+ *s = 0;
+ sprintf (cmd, "cat /usr/src/linux-%s/README", uts.release);
+ if (!stat (cmd+4, &st))
+ oprogram = cmd;
+ else
+ {
+ /* kernel source not installed? try X... */
+ strcpy (cmd, "cat /usr/X11R6/lib/X11/doc/README");
+ if (!stat (cmd+4, &st))
+ oprogram = cmd;
+ }
+ }
+ }
+ }
+#endif /* __linux__ && HAVE_UNAME */
+#ifdef __APPLE__ /* MacOS X + XDarwin */
+ {
+ static int done_once = 0;
+ if (!done_once)
+ {
+ struct stat st;
+ static char *cmd = "cat /usr/X11R6/README";
+ if (!stat (cmd+4, &st))
+ oprogram = cmd;
+ }
+ }
+#endif /* __APPLE__ */
+ }
+
+ program = (char *) malloc (strlen (oprogram) + 10);
strcpy (program, "( ");
strcat (program, oprogram);
strcat (program, " ) 2>&1");
return;
}
- if (*s == '\n' || col > sc->columns)
+ if (*s == '\r' || *s == '\n' || col > sc->columns)
{
int L = s - sc->buf;
- if (*s == '\n')
- *s++ = 0;
+ if (*s == '\r' || *s == '\n')
+ {
+ if (*s == '\r' && s[1] == '\n') /* swallow CRLF too */
+ *s++ = 0;
+
+ *s++ = 0;
+ }
else
{
/* We wrapped -- try to back up to the previous word boundary. */
sc->lines[sc->total_lines] = (char *) malloc (L+1);
memcpy (sc->lines[sc->total_lines], sc->buf, L);
sc->lines[sc->total_lines][L] = 0;
+ latin1_to_ascii (sc->lines[sc->total_lines]);
{
char *t = sc->lines[sc->total_lines];
if (sc->buf_tail > (s - sc->buf))
{
int i = sc->buf_tail - (s - sc->buf);
- memcpy (sc->buf, s, i);
+ memmove (sc->buf, s, i);
sc->buf_tail = i;
sc->buf[sc->buf_tail] = 0;
}
#endif /* DEBUG */
+/* Construct stars (number of stars is dependent on size of screen) */
+static void
+init_stars (ModeInfo *mi, int width, int height)
+{
+ sws_configuration *sc = &scs[MI_SCREEN(mi)];
+ int i, j;
+ int nstars = width * height / 320;
+ int max_size = 3;
+ GLfloat inc = 0.5;
+ int steps = max_size / inc;
+
+ glDeleteLists (sc->star_list, 1);
+ sc->star_list = glGenLists (1);
+ glNewList (sc->star_list, GL_COMPILE);
+
+ glEnable(GL_POINT_SMOOTH);
+
+ for (j = 1; j <= steps; j++)
+ {
+ glPointSize(inc * j);
+ glBegin (GL_POINTS);
+ for (i = 0; i < nstars / steps; i++)
+ {
+ glColor3f (0.6 + frand(0.3),
+ 0.6 + frand(0.3),
+ 0.6 + frand(0.3));
+ glVertex2f (2 * width * (0.5 - frand(1.0)),
+ 2 * height * (0.5 - frand(1.0)));
+ }
+ glEnd ();
+ }
+ glEndList ();
+}
+
+
/* Window management, etc
*/
void
}
- /* Construct stars (number of stars is dependent on size of screen) */
- {
- int i;
- int nstars = width * height / 320;
- glDeleteLists (sc->star_list, 1);
- sc->star_list = glGenLists (1);
- glNewList (sc->star_list, GL_COMPILE);
- glBegin (GL_POINTS);
- for (i = 0; i < nstars; i++)
- {
- GLfloat c = 0.6 + 0.3 * random() / RAND_MAX;
- glColor3f (c, c, c);
- glVertex3f (2 * width * (0.5 - 1.0 * random() / RAND_MAX),
- 2 * height * (0.5 - 1.0 * random() / RAND_MAX),
- 0.0);
- }
- glEnd ();
- glEndList ();
- }
-
-
/* Compute the height in pixels of the line at the bottom of the screen. */
{
GLdouble mm[17], pm[17];
if ((sc->glx_context = init_GL(mi)) != NULL) {
gl_init(mi);
reshape_sws (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+ init_stars (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
}
-
font_height = GLUT_FONT->top - GLUT_FONT->bottom;
sc->font_scale = 1.0 / glutStrokeWidth (GLUT_FONT, 'z'); /* 'n' seems
too wide */
sc->subproc_relaunch_delay = 2 * 1000;
sc->total_lines = max_lines-1;
- launch_text_generator (sc);
if (random() & 1)
star_spin = -star_spin;
progname, alignment_str);
exit (1);
}
+
+ launch_text_generator (sc);
+
+ /* one more reshape, after line_height has been computed */
+ reshape_sws (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
}
}
if (alignment >= 0)
- xoff = 1.0 - (glutStrokeLength(GLUT_FONT, line) * sc->font_scale);
+ xoff = 1.0 - (glutStrokeLength(GLUT_FONT,
+ (unsigned char *) line)
+ * sc->font_scale);
if (alignment == 0)
xoff /= 2;