X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fstderr.c;h=0c999e2fcfd55cdef991c2712069e15b3243b902;hb=c6b273ef7292ba10943694df1656b05203d7b62f;hp=7d5fc1366c0f7e4fc54f59ddf9d430d4f2389d74;hpb=ccbc9f87eb59497b23bd0424ee1ed20ad7c7db54;p=xscreensaver diff --git a/driver/stderr.c b/driver/stderr.c index 7d5fc136..0c999e2f 100644 --- a/driver/stderr.c +++ b/driver/stderr.c @@ -1,4 +1,5 @@ -/* xscreensaver, Copyright (c) 1991-1995 Jamie Zawinski +/* stderr.c --- capturing stdout/stderr output onto the screensaver window. + * xscreensaver, Copyright (c) 1991-1998 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 @@ -12,111 +13,166 @@ /* stderr hackery - Why Unix Sucks, reason number 32767. */ -#if __STDC__ -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" #endif +#include + #include -#include #include +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_FCNTL +# include +#endif + #include #include "xscreensaver.h" +#include "resources.h" +#include "visual.h" -extern XtAppContext app; -extern Colormap cmap; -extern Window screensaver_window; +FILE *real_stderr = 0; +FILE *real_stdout = 0; -extern char *get_string_resource P((char *, char *)); -extern Bool get_boolean_resource P((char *, char *)); -extern unsigned int get_pixel_resource P((char *, char *, - Display *, Colormap)); -static char stderr_buffer [1024]; +/* It's ok for these to be global, since they refer to the one and only + stderr stream, not to a particular screen or window or visual. + */ +static char stderr_buffer [4096]; static char *stderr_tail = 0; static time_t stderr_last_read = 0; -static XtIntervalId stderr_popup_timer = 0; -FILE *real_stderr = 0; -FILE *real_stdout = 0; +static void make_stderr_overlay_window (saver_screen_info *); + + +void +reset_stderr (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + + if (si->prefs.debug_p) + fprintf ((real_stderr ? real_stderr : stderr), + "%s: resetting stderr\n", progname); + + ssi->stderr_text_x = 0; + ssi->stderr_text_y = 0; + + if (ssi->stderr_gc) + XFreeGC (si->dpy, ssi->stderr_gc); + ssi->stderr_gc = 0; -static int text_x = 0; -static int text_y = 0; + if (ssi->stderr_overlay_window) + XDestroyWindow(si->dpy, ssi->stderr_overlay_window); + ssi->stderr_overlay_window = 0; + + if (ssi->stderr_cmap) + XFreeColormap(si->dpy, ssi->stderr_cmap); + ssi->stderr_cmap = 0; +} void -reset_stderr () +clear_stderr (saver_screen_info *ssi) { - text_x = text_y = 0; + saver_info *si = ssi->global; + ssi->stderr_text_x = 0; + ssi->stderr_text_y = 0; + if (ssi->stderr_overlay_window) + XClearWindow (si->dpy, ssi->stderr_overlay_window); } + static void -print_stderr (string) - char *string; +print_stderr_1 (saver_screen_info *ssi, char *string) { + saver_info *si = ssi->global; + Display *dpy = si->dpy; + Screen *screen = ssi->screen; + Window window = (ssi->stderr_overlay_window ? + ssi->stderr_overlay_window : + ssi->screensaver_window); int h_border = 20; int v_border = 20; - static int line_height; - static XFontStruct *font = 0; - static GC gc = 0; char *head = string; char *tail; - /* In verbose mode, copy it to stderr as well. */ - if (verbose_p) - fprintf (real_stderr, "%s", string); + if (! ssi->stderr_font) + { + char *font_name = get_string_resource ("font", "Font"); + if (!font_name) font_name = "fixed"; + ssi->stderr_font = XLoadQueryFont (dpy, font_name); + if (! ssi->stderr_font) ssi->stderr_font = XLoadQueryFont (dpy, "fixed"); + ssi->stderr_line_height = (ssi->stderr_font->ascent + + ssi->stderr_font->descent); + } - if (! gc) + if (! ssi->stderr_gc) { XGCValues gcv; Pixel fg, bg; - char *font_name = get_string_resource ("font", "Font"); - if (!font_name) font_name = "fixed"; - font = XLoadQueryFont (dpy, font_name); - if (! font) font = XLoadQueryFont (dpy, "fixed"); - line_height = font->ascent + font->descent; - fg = get_pixel_resource ("textForeground", "Foreground", dpy, cmap); - bg = get_pixel_resource ("textBackground", "Background", dpy, cmap); - gcv.font = font->fid; + Colormap cmap = ssi->cmap; + + if (!ssi->stderr_overlay_window && + get_boolean_resource("overlayStderr", "Boolean")) + { + make_stderr_overlay_window (ssi); + if (ssi->stderr_overlay_window) + window = ssi->stderr_overlay_window; + if (ssi->stderr_cmap) + cmap = ssi->stderr_cmap; + } + + fg = get_pixel_resource ("overlayTextForeground","Foreground",dpy,cmap); + bg = get_pixel_resource ("overlayTextBackground","Background",dpy,cmap); + gcv.font = ssi->stderr_font->fid; gcv.foreground = fg; gcv.background = bg; - gc = XCreateGC (dpy, screensaver_window, - (GCFont | GCForeground | GCBackground), &gcv); + ssi->stderr_gc = XCreateGC (dpy, window, + (GCFont | GCForeground | GCBackground), + &gcv); } + + if (ssi->stderr_cmap) + XInstallColormap(si->dpy, ssi->stderr_cmap); + for (tail = string; *tail; tail++) { if (*tail == '\n' || *tail == '\r') { int maxy = HeightOfScreen (screen) - v_border - v_border; if (tail != head) - XDrawImageString (dpy, screensaver_window, gc, - text_x + h_border, - text_y + v_border + font->ascent, + XDrawImageString (dpy, window, ssi->stderr_gc, + ssi->stderr_text_x + h_border, + ssi->stderr_text_y + v_border + + ssi->stderr_font->ascent, head, tail - head); - text_x = 0; - text_y += line_height; + ssi->stderr_text_x = 0; + ssi->stderr_text_y += ssi->stderr_line_height; head = tail + 1; if (*tail == '\r' && *head == '\n') head++, tail++; - if (text_y > maxy - line_height) + if (ssi->stderr_text_y > maxy - ssi->stderr_line_height) { #if 0 - text_y = 0; + ssi->stderr_text_y = 0; #else - int offset = line_height * 5; - XCopyArea (dpy, screensaver_window, screensaver_window, gc, + int offset = ssi->stderr_line_height * 5; + XCopyArea (dpy, window, window, ssi->stderr_gc, 0, v_border + offset, WidthOfScreen (screen), (HeightOfScreen (screen) - v_border - v_border - offset), 0, v_border); - XClearArea (dpy, screensaver_window, + XClearArea (dpy, window, 0, HeightOfScreen (screen) - v_border - offset, WidthOfScreen (screen), offset, False); - text_y -= offset; + ssi->stderr_text_y -= offset; #endif } } @@ -125,21 +181,75 @@ print_stderr (string) { int direction, ascent, descent; XCharStruct overall; - XDrawImageString (dpy, screensaver_window, gc, - text_x + h_border, text_y + v_border + font->ascent, + XDrawImageString (dpy, window, ssi->stderr_gc, + ssi->stderr_text_x + h_border, + ssi->stderr_text_y + v_border + + ssi->stderr_font->ascent, head, tail - head); - XTextExtents (font, tail, tail - head, + XTextExtents (ssi->stderr_font, tail, tail - head, &direction, &ascent, &descent, &overall); - text_x += overall.width; + ssi->stderr_text_x += overall.width; } } +static void +make_stderr_overlay_window (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + unsigned long transparent_pixel = 0; + Visual *visual = get_overlay_visual (ssi->screen, &transparent_pixel); + if (visual) + { + int depth = visual_depth (ssi->screen, visual); + XSetWindowAttributes attrs; + unsigned long attrmask; + + if (si->prefs.debug_p) + fprintf(real_stderr, + "%s: using overlay visual 0x%0x for stderr text layer.\n", + progname, (int) XVisualIDFromVisual (visual)); + + ssi->stderr_cmap = XCreateColormap(si->dpy, + RootWindowOfScreen(ssi->screen), + visual, AllocNone); + + attrmask = (CWColormap | CWBackPixel | CWBackingPixel | CWBorderPixel | + CWBackingStore | CWSaveUnder); + attrs.colormap = ssi->stderr_cmap; + attrs.background_pixel = transparent_pixel; + attrs.backing_pixel = transparent_pixel; + attrs.border_pixel = transparent_pixel; + attrs.backing_store = NotUseful; + attrs.save_under = False; + + ssi->stderr_overlay_window = + XCreateWindow(si->dpy, ssi->screensaver_window, 0, 0, + WidthOfScreen(ssi->screen), HeightOfScreen(ssi->screen), + 0, depth, InputOutput, visual, attrmask, &attrs); + XMapRaised(si->dpy, ssi->stderr_overlay_window); + } +} + + +static void +print_stderr (saver_info *si, char *string) +{ + saver_preferences *p = &si->prefs; + int i; + + /* In verbose mode, copy it to stderr as well. */ + if (p->verbose_p) + fprintf (real_stderr, "%s", string); + + for (i = 0; i < si->nscreens; i++) + print_stderr_1 (&si->screens[i], string); +} + static void -stderr_popup_timer_fn (closure, id) - XtPointer closure; - XtIntervalId *id; +stderr_popup_timer_fn (XtPointer closure, XtIntervalId *id) { + saver_info *si = (saver_info *) closure; char *s = stderr_buffer; if (*s) { @@ -150,20 +260,18 @@ stderr_popup_timer_fn (closure, id) if (strlen (s) > max) strcpy (s + max, trailer); /* Now show the user. */ - print_stderr (s); + print_stderr (si, s); } stderr_tail = stderr_buffer; - stderr_popup_timer = 0; + si->stderr_popup_timer = 0; } static void -stderr_callback (closure, fd, id) - XtPointer closure; - int *fd; - XtIntervalId *id; +stderr_callback (XtPointer closure, int *fd, XtIntervalId *id) { + saver_info *si = (saver_info *) closure; char *s; int left; int size; @@ -212,16 +320,17 @@ stderr_callback (closure, fd, id) */ if (read_this_time > 0) { - if (stderr_popup_timer) - XtRemoveTimeOut (stderr_popup_timer); + if (si->stderr_popup_timer) + XtRemoveTimeOut (si->stderr_popup_timer); - stderr_popup_timer = - XtAppAddTimeOut (app, 1 * 1000, stderr_popup_timer_fn, 0); + si->stderr_popup_timer = + XtAppAddTimeOut (si->app, 1 * 1000, stderr_popup_timer_fn, + (XtPointer) si); } } void -initialize_stderr () +initialize_stderr (saver_info *si) { static Boolean done = False; int fds [2]; @@ -229,19 +338,21 @@ initialize_stderr () int new_stdout, new_stderr; int stdout_fd = 1; int stderr_fd = 2; - int flags; - Boolean stderr_dialog_p = get_boolean_resource ("captureStderr", "Boolean"); - Boolean stdout_dialog_p = get_boolean_resource ("captureStdout", "Boolean"); + int flags = 0; + Boolean stderr_dialog_p, stdout_dialog_p; + + if (done) return; + done = True; real_stderr = stderr; real_stdout = stdout; + stderr_dialog_p = get_boolean_resource ("captureStderr", "Boolean"); + stdout_dialog_p = get_boolean_resource ("captureStdout", "Boolean"); + if (!stderr_dialog_p && !stdout_dialog_p) return; - if (done) return; - done = True; - if (pipe (fds)) { perror ("error creating pipe:"); @@ -251,15 +362,15 @@ initialize_stderr () in = fds [0]; out = fds [1]; -# ifdef O_NONBLOCK - flags = O_NONBLOCK; -# else -# ifdef O_NDELAY - flags = O_NDELAY; +# ifdef HAVE_FCNTL + +# if defined(O_NONBLOCK) + flags = O_NONBLOCK; +# elif defined(O_NDELAY) + flags = O_NDELAY; # else - ERROR!! neither O_NONBLOCK nor O_NDELAY are defined. + ERROR!! neither O_NONBLOCK nor O_NDELAY are defined. # endif -# endif /* Set both sides of the pipe to nonblocking - this is so that our reads (in stderr_callback) will terminate, and so that @@ -276,6 +387,8 @@ initialize_stderr () return; } +# endif /* !HAVE_FCNTL */ + if (stderr_dialog_p) { FILE *new_stderr_file; @@ -324,5 +437,6 @@ initialize_stderr () } } - XtAppAddInput (app, in, (XtPointer) XtInputReadMask, stderr_callback, 0); + XtAppAddInput (si->app, in, (XtPointer) XtInputReadMask, stderr_callback, + (XtPointer) si); }