X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fdemo.c;h=e92e9617a1da6c111758a8e2dd2a1fbdeeab86d3;hb=c31d10b6605cd8dc1a7b61fef4256f06198767e5;hp=339162221423731b156b943052c68619829e5fba;hpb=65740e2a8dea3d6309ae6e8914a0fb79e993ada8;p=xscreensaver diff --git a/driver/demo.c b/driver/demo.c old mode 100755 new mode 100644 index 33916222..e92e9617 --- a/driver/demo.c +++ b/driver/demo.c @@ -1,4 +1,5 @@ -/* xscreensaver, Copyright (c) 1993 Jamie Zawinski +/* demo.c --- implements the interactive demo-mode and options dialogs. + * xscreensaver, Copyright (c) 1993-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 @@ -9,35 +10,101 @@ * implied warranty. */ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_ATHENA_KLUDGE /* don't ask */ +# undef HAVE_MOTIF +# define HAVE_ATHENA 1 +#endif -#if !__STDC__ -# define _NO_PROTO +#include + +#ifdef HAVE_UNISTD_H +# include #endif -#include -#include -#include -#include +#ifndef VMS +# include /* for getpwuid() */ +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + +#ifdef HAVE_UNAME +# include /* for uname() */ +#endif /* HAVE_UNAME */ -#include "xscreensaver.h" #include -extern Time timeout, cycle, lock_timeout; -#ifndef NO_LOCKING -extern Time passwd_timeout; -#endif -extern int fade_seconds, fade_ticks; -extern Bool verbose_p, install_cmap_p, fade_p, unfade_p; -extern Bool lock_p, locking_disabled_p; +#include +#include + +/* We don't actually use any widget internals, but these are included + so that gdb will have debug info for the widgets... */ +#include +#include + +#ifdef HAVE_MOTIF +# include +# include +# include +# include +# include +# include +# include + +#else /* HAVE_ATHENA */ + /* Athena demo code contributed by Jon A. Christopher */ + /* Copyright 1997, with the same permissions as above. */ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif /* HAVE_ATHENA */ + +#include "version.h" +#include "prefs.h" +#include "resources.h" /* for parse_time() */ +#include "visual.h" /* for has_writable_cells() */ +#include "remote.h" /* for xscreensaver_command() */ + +#include +#include +#include + + +char *progname = 0; +char *progclass = "XScreenSaver"; +XrmDatabase db; + +typedef struct { + saver_preferences *a, *b; +} prefs_pair; + + +char *blurb (void) { return progname; } + +static void run_hack (Display *dpy, int n); -static void demo_mode_hack P((char *)); -static void demo_mode_done P((void)); +#ifdef HAVE_ATHENA +static saver_preferences *global_prefs_kludge = 0; /* I hate C so much... */ +#endif /* HAVE_ATHENA */ -static void focus_fuckus P((Widget dialog)); -static void text_cb P((Widget button, XtPointer, XtPointer)); +static char *short_version = 0; -extern void demo_mode_restart_process (); +Atom XA_VROOT; +Atom XA_SCREENSAVER, XA_SCREENSAVER_RESPONSE, XA_SCREENSAVER_VERSION; +Atom XA_SCREENSAVER_TIME, XA_SCREENSAVER_ID, XA_SELECT, XA_DEMO, XA_RESTART; + +extern void create_demo_dialog (Widget, Visual *, Colormap); +extern void create_preferences_dialog (Widget, Visual *, Colormap); extern Widget demo_dialog; extern Widget label1; @@ -46,275 +113,610 @@ extern Widget demo_form; extern Widget demo_list; extern Widget next, prev, done, restart, edit; -extern Widget resources_dialog; -extern Widget resources_form; -extern Widget res_done, res_cancel; -extern Widget timeout_text, cycle_text, fade_text, ticks_text; -extern Widget lock_time_text, passwd_time_text; -extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle, +extern Widget preferences_dialog; +extern Widget preferences_form; +extern Widget prefs_done, prefs_cancel; +extern Widget timeout_text, cycle_text, fade_text, fade_ticks_text; +extern Widget lock_timeout_text, passwd_timeout_text; +extern Widget verbose_toggle, install_cmap_toggle, fade_toggle, unfade_toggle, lock_toggle; -extern create_demo_dialog (); -extern create_resources_dialog (); -static void -focus_fuckus (dialog) - Widget dialog; +#ifdef HAVE_MOTIF + +# define set_toggle_button_state(toggle,state) \ + XmToggleButtonSetState ((toggle), (state), True) +# define set_text_string(text_widget,string) \ + XmTextSetString ((text_widget), (string)) +# define add_button_callback(button,cb,arg) \ + XtAddCallback ((button), XmNactivateCallback, (cb), (arg)) +# define add_toggle_callback(button,cb,arg) \ + XtAddCallback ((button), XmNvalueChangedCallback, (cb), (arg)) +# define add_text_callback add_toggle_callback + +#else /* HAVE_ATHENA */ + +# define set_toggle_button_state(toggle,state) \ + XtVaSetValues((toggle), XtNstate, (state), 0) +# define set_text_string(text_widget,string) \ + XtVaSetValues ((text_widget), XtNvalue, (string), 0) +# define add_button_callback(button,cb,arg) \ + XtAddCallback ((button), XtNcallback, (cb), (arg)) +# define add_toggle_callback add_button_callback +# define add_text_callback(b,c,a) ERROR! + +#endif /* HAVE_ATHENA */ + + +#define disable_widget(widget) \ + XtVaSetValues((widget), XtNsensitive, False, 0) + + +static char * +get_text_string (Widget text_widget) { - XSetInputFocus (XtDisplay (dialog), XtWindow (dialog), - RevertToParent, CurrentTime); +#ifdef HAVE_MOTIF + return XmTextGetString (text_widget); +#else /* HAVE_ATHENA */ + char *string = 0; + if (XtIsSubclass(text_widget, textWidgetClass)) + XtVaGetValues (text_widget, XtNstring, &string, 0); + else if (XtIsSubclass(text_widget, dialogWidgetClass)) + XtVaGetValues (text_widget, XtNvalue, &string, 0); + else + string = 0; + + return string; +#endif /* HAVE_ATHENA */ } +static char * +get_label_string (Widget label_widget) +{ +#ifdef HAVE_MOTIF + char *label = 0; + XmString xm_label = 0; + XtVaGetValues (label_widget, XmNlabelString, &xm_label, 0); + if (!xm_label) + return 0; + XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label); + return label; +#else /* HAVE_ATHENA */ + char *label = 0; + XtVaGetValues (label_widget, XtNlabel, &label, 0); + return (label ? strdup(label) : 0); +#endif /* HAVE_ATHENA */ +} + + static void -raise_screenhack_dialog () +set_label_string (Widget label_widget, char *string) { - XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog)); - if (resources_dialog) - XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog)); - focus_fuckus (resources_dialog ? resources_dialog : demo_dialog); +#ifdef HAVE_MOTIF + XmString xm_string = XmStringCreate (string, XmSTRING_DEFAULT_CHARSET); + XtVaSetValues (label_widget, XmNlabelString, xm_string, 0); + XmStringFree (xm_string); +#else /* HAVE_ATHENA */ + XtVaSetValues (label_widget, XtNlabel, string, 0); +#endif /* HAVE_ATHENA */ } + static void -destroy_screenhack_dialogs () +format_into_label (Widget label, const char *arg) { - if (demo_dialog) XtDestroyWidget (demo_dialog); - if (resources_dialog) XtDestroyWidget (resources_dialog); - demo_dialog = resources_dialog = 0; + char *text = get_label_string (label); + char *buf = (char *) malloc ((text ? strlen(text) : 0) + strlen(arg) + 100); + + if (!text || !strcmp (text, XtName (label))) + strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY"); + else + sprintf (buf, text, arg); + + set_label_string (label, buf); + free (buf); + XtFree (text); } + +/* Why this behavior isn't automatic in *either* toolkit, I'll never know. + */ static void -text_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +ensure_selected_item_visible (Widget list) { - char *line = XmTextGetString (button); - demo_mode_hack (line); +#ifdef HAVE_MOTIF + int *pos_list = 0; + int pos_count = 0; + if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0) + { + int top = -2; + int visible = 0; + XtVaGetValues (list, + XmNtopItemPosition, &top, + XmNvisibleItemCount, &visible, + 0); + if (pos_list[0] >= top + visible) + { + int pos = pos_list[0] - visible + 1; + if (pos < 0) pos = 0; + XmListSetPos (list, pos); + } + else if (pos_list[0] < top) + { + XmListSetPos (list, pos_list[0]); + } + } + if (pos_list) + XtFree ((char *) pos_list); + +#else /* HAVE_ATHENA */ +# ifdef HAVE_XawViewportSetCoordinates + + int margin = 16; /* should be line height or something. */ + int count = 0; + int pos; + Dimension list_h = 0, vp_h = 0; + Dimension top_margin = 4; /* I don't know where this value comes from */ + Position vp_x = 0, vp_y = 0, current_y; + double cratio; + Widget viewport = XtParent(demo_list); + Widget sb = (viewport ? XtNameToWidget(viewport, "*vertical") : 0); + float sb_top = 0, sb_size = 0; + XawListReturnStruct *current = XawListShowCurrent(demo_list); + if (!current || !sb) return; + + XtVaGetValues(demo_list, + XtNnumberStrings, &count, + XtNheight, &list_h, + 0); + if (count < 2 || list_h < 10) return; + + XtVaGetValues(viewport, XtNheight, &vp_h, XtNx, &vp_x, XtNy, &vp_y, 0); + if (vp_h < 10) return; + + XtVaGetValues(sb, XtNtopOfThumb, &sb_top, XtNshown, &sb_size, 0); + if (sb_size <= 0) return; + + pos = current->list_index; + cratio = ((double) pos) / ((double) count); + current_y = (cratio * list_h); + + if (cratio < sb_top || + cratio > sb_top + sb_size) + { + if (cratio < sb_top) + current_y -= (vp_h - margin - margin); + else + current_y -= margin; + + if ((long)current_y >= (long) list_h) + current_y = (Position) ((long)list_h - (long)vp_h); + + if ((long)current_y < (long)top_margin) + current_y = (Position)top_margin; + + XawViewportSetCoordinates (viewport, vp_x, current_y); + } +# endif /* HAVE_XawViewportSetCoordinates */ +#endif /* HAVE_ATHENA */ } +/* Callback for the text area: + - note the text the user has entered; + - change the corresponding element in `screenhacks'; + - write the .xscreensaver file; + - tell the xscreensaver daemon to run that hack. + */ static void -select_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +text_cb (Widget text_widget, XtPointer client_data, XtPointer call_data) { - char **hacks = (char **) client_data; - XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data; - XmTextSetString (text_line, hacks [lcb->item_position - 1]); - if (lcb->reason == XmCR_DEFAULT_ACTION) - text_cb (text_line, 0, 0); - focus_fuckus (demo_dialog); + Display *dpy = XtDisplay (text_widget); + saver_preferences *p = (saver_preferences *) client_data; + char *new_text = get_text_string (text_widget); + + int hack_number = -1; /* 0-based */ + +#ifdef HAVE_ATHENA + XawListReturnStruct *current = XawListShowCurrent(demo_list); + hack_number = current->list_index; +#else /* HAVE_MOTIF */ + int *pos_list = 0; + int pos_count = 0; + if (XmListGetSelectedPos (demo_list, &pos_list, &pos_count)) + hack_number = pos_list[0] - 1; + if (pos_list) + XtFree ((char *) pos_list); +#endif /* HAVE_MOTIF */ + + ensure_selected_item_visible (demo_list); + + if (hack_number < 0 || hack_number >= p->screenhacks_count) + { + set_text_string (text_widget, ""); + XBell (dpy, 0); + } + else + { +fprintf(stderr, "%d:\nold: %s\nnew: %s\n", + hack_number, p->screenhacks [hack_number], new_text); + + if (p->screenhacks [hack_number]) + free (p->screenhacks [hack_number]); + p->screenhacks [hack_number] = strdup (new_text); + +#ifdef HAVE_MOTIF + + XmListDeselectAllItems (demo_list); + { + XmString xmstr = XmStringCreate (new_text, XmSTRING_DEFAULT_CHARSET); + XmListReplaceItemsPos (demo_list, &xmstr, 1, hack_number+1); + XmStringFree (xmstr); + } + XmListSelectPos (demo_list, hack_number+1, True); + +#else /* HAVE_ATHENA */ + + { + Widget vp = XtParent(demo_list); + Widget sb = (vp ? XtNameToWidget(vp, "*vertical") : 0); + Dimension list_h = 0; + Position vp_x = 0, vp_y = 0; + float sb_top = 0; + + XawListUnhighlight (demo_list); + + XtVaGetValues (vp, XtNx, &vp_x, 0); + XtVaGetValues (sb, XtNtopOfThumb, &sb_top, 0); + XtVaGetValues (demo_list, XtNheight, &list_h, 0); + vp_y = (sb_top * list_h); + XtVaSetValues (demo_list, + XtNlist, p->screenhacks, + XtNnumberStrings, p->screenhacks_count, + 0); + XawViewportSetCoordinates (vp, vp_x, vp_y); + XawListHighlight (demo_list, hack_number); + } + +#endif /* HAVE_ATHENA */ + + write_init_file (p, short_version); + XSync (dpy, False); + usleep (500000); /* give the disk time to settle down */ + + run_hack (dpy, hack_number+1); + } } + +#ifdef HAVE_ATHENA +/* Bend over backwards to make hitting Return in the text field do the + right thing. + */ +static void text_enter (Widget w, XEvent *event, String *av, Cardinal *ac) +{ + text_cb (w, global_prefs_kludge, 0); /* I hate C so much... */ +} + +static XtActionsRec actions[] = {{"done", text_enter} + }; +static char translations[] = ("Return: done()\n" + "Linefeed: done()\n" + "CtrlM: done()\n" + "CtrlJ: done()\n"); +#endif /* HAVE_ATHENA */ + + +/* Callback for the Run Next button. + */ static void -next_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +next_cb (Widget button, XtPointer client_data, XtPointer call_data) { - int *pos_list; - int pos_count; +#ifdef HAVE_ATHENA + XawListReturnStruct *current = XawListShowCurrent(demo_list); + int cnt; + XtVaGetValues (demo_list, XtNnumberStrings, &cnt, 0); + if (current->list_index == XAW_LIST_NONE || + current->list_index + 1 >= cnt) + current->list_index = 0; + else + current->list_index++; + XawListHighlight(demo_list, current->list_index); + + ensure_selected_item_visible (demo_list); + current = XawListShowCurrent(demo_list); + XtVaSetValues(text_line, XtNstring, current->string, 0); + + run_hack (XtDisplay (button), current->list_index + 1); + +#else /* HAVE_MOTIF */ + + saver_preferences *p = (saver_preferences *) client_data; + int *pos_list = 0; + int pos_count = 0; + int pos; if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count)) - XmListSelectPos (demo_list, 1, True); + { + pos = 1; + XmListDeselectAllItems (demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, pos, True); + } else { - int pos = pos_list [0]; - XmListSelectPos (demo_list, pos + 1, True); - XtFree ((char *) pos_list); - if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count)) - abort (); - if (pos_list [0] == pos) - XmListSelectPos (demo_list, 1, True); - XtFree ((char *) pos_list); + pos = pos_list[0] + 1; + if (pos > p->screenhacks_count) + pos = 1; + XmListDeselectAllItems (demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, pos, True); } - text_cb (text_line, 0, 0); + + ensure_selected_item_visible (demo_list); + run_hack (XtDisplay (button), pos); + if (pos_list) + XtFree ((char *) pos_list); + +#endif /* HAVE_MOTIF */ } + +/* Callback for the Run Previous button. + */ static void -prev_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +prev_cb (Widget button, XtPointer client_data, XtPointer call_data) { - int *pos_list; - int pos_count; +#ifdef HAVE_ATHENA + XawListReturnStruct *current = XawListShowCurrent(demo_list); + int cnt; + XtVaGetValues (demo_list, XtNnumberStrings, &cnt, 0); + if (current->list_index == XAW_LIST_NONE || + current->list_index <= 0) + current->list_index = cnt-1; + else + current->list_index--; + XawListHighlight(demo_list, current->list_index); + + ensure_selected_item_visible (demo_list); + current = XawListShowCurrent(demo_list); + XtVaSetValues(text_line, XtNstring, current->string, 0); + + run_hack (XtDisplay (button), current->list_index + 1); + +#else /* HAVE_MOTIF */ + + saver_preferences *p = (saver_preferences *) client_data; + int *pos_list = 0; + int pos_count = 0; + int pos; if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count)) - XmListSelectPos (demo_list, 0, True); + { + pos = p->screenhacks_count; + XmListDeselectAllItems (demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, pos, True); + } else { - XmListSelectPos (demo_list, pos_list [0] - 1, True); - XtFree ((char *) pos_list); + pos = pos_list[0] - 1; + if (pos == 0) + pos = p->screenhacks_count; + XmListDeselectAllItems (demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, pos, True); } - text_cb (text_line, 0, 0); + + ensure_selected_item_visible (demo_list); + run_hack (XtDisplay (button), pos); + if (pos_list) + XtFree ((char *) pos_list); + +#endif /* HAVE_MOTIF */ +} + + +/* Callback run when a list element is double-clicked. + */ +static void +select_cb (Widget button, XtPointer client_data, XtPointer call_data) +{ +/* saver_preferences *p = (saver_preferences *) client_data; */ + +#ifdef HAVE_ATHENA + XawListReturnStruct *item = (XawListReturnStruct*)call_data; + XtVaSetValues(text_line, XtNstring, item->string, 0); + run_hack (XtDisplay (button), item->list_index + 1); + +#else /* HAVE_MOTIF */ + XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data; + char *string = 0; + if (lcb->item) + XmStringGetLtoR (lcb->item, XmSTRING_DEFAULT_CHARSET, &string); + set_text_string (text_line, (string ? string : "")); + + if (lcb->reason == XmCR_DEFAULT_ACTION && string) + run_hack (XtDisplay (button), lcb->item_position); + + if (string) + XtFree (string); +#endif /* HAVE_MOTIF */ } -static void pop_resources_dialog (); -static void make_resources_dialog (); +static void pop_preferences_dialog (prefs_pair *pair); +static void make_preferences_dialog (prefs_pair *pair, Widget parent); + +/* Callback for the Preferences button. + */ static void -edit_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +preferences_cb (Widget button, XtPointer client_data, XtPointer call_data) { - Widget parent = (Widget) client_data; - if (! resources_dialog) - make_resources_dialog (parent); - pop_resources_dialog (); + prefs_pair *pair = (prefs_pair *) client_data; + Widget parent = button; + + do { + parent = XtParent(parent); + } while (XtParent(parent)); + + if (! preferences_dialog) + make_preferences_dialog (pair, parent); + pop_preferences_dialog (pair); } +/* Callback for the Quit button. + */ static void -done_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +quit_cb (Widget button, XtPointer client_data, XtPointer call_data) { - demo_mode_done (); + /* Save here? Right now we don't need to, because we save every time + the text field is edited, or the Preferences OK button is pressed. + */ + exit (0); } +/* Callback for the (now unused) Restart button. + */ static void -restart_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +restart_cb (Widget button, XtPointer client_data, XtPointer call_data) { - demo_mode_restart_process (); + xscreensaver_command (XtDisplay (button), XA_RESTART, 0, False); } -void -pop_up_dialog_box (dialog, form, where) - Widget dialog, form; - int where; + +static void +pop_up_dialog_box (Widget dialog, Widget form) { - /* I'm sure this is the wrong way to pop up a dialog box, but I can't - figure out how else to do it. - - It's important that the screensaver dialogs not get decorated or - otherwise reparented by the window manager, because they need to be - children of the *real* root window, not the WM's virtual root, in - order for us to guarentee that they are visible above the screensaver - window itself. - */ - Arg av [100]; - int ac = 0; - Dimension sw, sh, x, y, w, h; +#ifdef HAVE_ATHENA + XtRealizeWidget (dialog); + XtPopup (dialog, XtGrabNone); +#else /* HAVE_MOTIF */ XtRealizeWidget (form); - sw = WidthOfScreen (XtScreen (dialog)); - sh = HeightOfScreen (XtScreen (dialog)); - ac = 0; - XtSetArg (av [ac], XmNwidth, &w); ac++; - XtSetArg (av [ac], XmNheight, &h); ac++; - XtGetValues (form, av, ac); - switch (where) - { - case 0: /* center it in the top-right quadrant */ - x = (sw/2 + w) / 2 + (sw/2) - w; - y = (sh/2 + h) / 2 - h; - break; - case 1: /* center it in the bottom-right quadrant */ - x = (sw/2 + w) / 2 + (sw/2) - w; - y = (sh/2 + h) / 2 + (sh/2) - h; - break; - case 2: /* center it on the screen */ - x = (sw + w) / 2 - w; - y = (sh + h) / 2 - h; - break; - default: - abort (); - } - if (x + w > sw) x = sw - w; - if (y + h > sh) y = sh - h; - ac = 0; - XtSetArg (av [ac], XmNx, x); ac++; - XtSetArg (av [ac], XmNy, y); ac++; - XtSetArg (av [ac], XtNoverrideRedirect, True); ac++; - XtSetArg (av [ac], XmNdefaultPosition, False); ac++; - /* I wonder whether this does anything useful? */ - /* XtSetArg (av [ac], XmNdialogStyle, XmDIALOG_SYSTEM_MODAL); ac++; */ - XtSetValues (dialog, av, ac); - XtSetValues (form, av, ac); XtManageChild (form); - - focus_fuckus (dialog); +#endif /* HAVE_MOTIF */ + XMapRaised (XtDisplay (dialog), XtWindow (dialog)); } static void -make_screenhack_dialog (parent, hacks) - Widget parent; - char **hacks; +make_demo_dialog (Widget toplevel_shell, prefs_pair *pair) { - char buf [255]; - Arg av[10]; - int ac; - char *label; - XmString xm_label = 0; - XmString new_xm_label; - - create_demo_dialog (parent); - ac = 0; - XtSetArg (av [ac], XmNlabelString, &xm_label); ac++; - XtGetValues (label1, av, ac); - XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label); - if (!strcmp (label, XtName (label1))) - strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY"); - else - sprintf (buf, label, screensaver_version); - new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET); - ac = 0; - XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++; - XtSetValues (label1, av, ac); - XmStringFree (new_xm_label); - XtFree (label); - - XtAddCallback (demo_list, XmNbrowseSelectionCallback, select_cb, - (XtPointer) hacks); - XtAddCallback (demo_list, XmNdefaultActionCallback, select_cb, - (XtPointer) hacks); - - XtAddCallback (text_line, XmNactivateCallback, text_cb, 0); - XtAddCallback (next, XmNactivateCallback, next_cb, 0); - XtAddCallback (prev, XmNactivateCallback, prev_cb, 0); - XtAddCallback (done, XmNactivateCallback, done_cb, 0); - XtAddCallback (restart, XmNactivateCallback, restart_cb, 0); - XtAddCallback (edit, XmNactivateCallback, edit_cb, (XtPointer) parent); - - for (; *hacks; hacks++) - { - XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET); - XmListAddItem (demo_list, xmstr, 0); - /* XmListSelectPos (widget, i, False); */ - XmStringFree (xmstr); - } - -#if 0 - /* Dialogs that have scroll-lists don't obey maxWidth! Fuck!! Hack it. */ - ac = 0; - XtSetArg (av [ac], XmNmaxWidth, &max_w); ac++; - XtGetValues (demo_dialog, av, ac); /* great, this SEGVs */ -#endif - - pop_up_dialog_box (demo_dialog, demo_form, 0); + saver_preferences *p = pair->a; + /* saver_preferences *p2 = pair->b; */ + + Widget parent = toplevel_shell; + char **hacks = p->screenhacks; + + create_demo_dialog (parent, + DefaultVisualOfScreen (XtScreen (parent)), + DefaultColormapOfScreen (XtScreen (parent))); + format_into_label (label1, short_version); + + add_button_callback (next, next_cb, (XtPointer) p); + add_button_callback (prev, prev_cb, (XtPointer) p); + add_button_callback (done, quit_cb, (XtPointer) p); + if (restart) + add_button_callback(restart,restart_cb, (XtPointer) p); + add_button_callback (edit, preferences_cb, (XtPointer) pair); + +#ifdef HAVE_MOTIF + XtAddCallback (demo_list, XmNbrowseSelectionCallback, + select_cb, (XtPointer) p); + XtAddCallback (demo_list, XmNdefaultActionCallback, + select_cb, (XtPointer) p); + XtAddCallback (text_line, XmNactivateCallback, text_cb, (XtPointer) p); + + if (hacks) + for (; *hacks; hacks++) + { + XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET); + XmListAddItem (demo_list, xmstr, 0); + XmStringFree (xmstr); + } + +#else /* HAVE_ATHENA */ + + /* Hook up the text line. */ + + XtAppAddActions(XtWidgetToApplicationContext(text_line), + actions, XtNumber(actions)); + XtOverrideTranslations(text_line, XtParseTranslationTable(translations)); + + + /* Must realize the widget before populating the list, or the dialog + will be as wide as the longest string. + */ + XtRealizeWidget (demo_dialog); + + XtVaSetValues (demo_list, + XtNlist, hacks, + XtNnumberStrings, p->screenhacks_count, + 0); + XtAddCallback (demo_list, XtNcallback, select_cb, p); + + /* Now that we've populated the list, make sure that the list is as + wide as the dialog itself. + */ + { + Widget viewport = XtParent(demo_list); + Widget subform = XtParent(viewport); + Widget box = XtNameToWidget(demo_dialog, "*box"); + Widget label1 = XtNameToWidget(demo_dialog, "*label1"); + Widget label2 = XtNameToWidget(demo_dialog, "*label2"); + Dimension x=0, y=0, w=0, h=0, bw=0, w2=0; + XtVaGetValues(subform, + XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0); + XtVaGetValues(box, XtNwidth, &w2, 0); + if (w2 != w) + XtResizeWidget(subform, w2, h, bw); + + /* Why isn't the viewport getting centered? */ + XtVaGetValues(viewport, + XtNx, &x, XtNy, &y, XtNheight, &h, XtNborderWidth, &bw, 0); + XtConfigureWidget(viewport, x, y, w2-x-x, h, bw); + + /* And the text line, too. */ + XtVaGetValues(text_line, + XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0); + XtVaGetValues(viewport, XtNwidth, &w2, 0); + if (w2 != w) + XtResizeWidget(text_line, w2, h, bw); + + /* And the labels too. */ + XtVaGetValues(label1, + XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0); + if (w2 != w) + XtResizeWidget(label1, w2, h, bw); + + XtVaGetValues(label2, + XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0); + if (w2 != w) + XtResizeWidget(label2, w2, h, bw); + + } + +#endif /* HAVE_ATHENA */ + + pop_up_dialog_box(demo_dialog, demo_form); + +#ifdef HAVE_ATHENA + /* For Athena, have to do this after the dialog is managed. */ + ensure_selected_item_visible (demo_list); +#endif /* HAVE_ATHENA */ } -/* the Screensaver Parameters dialog */ - -static struct resources { - int timeout, cycle, secs, ticks, lock_time, passwd_time; - int verb, cmap, fade, unfade, lock_p; -} res; - - -extern int parse_time (); +/* the Preferences dialog + */ +/* Helper for the text fields that contain time specifications: + this parses the text, and does error checking. + */ static void -hack_time_cb (dpy, line, store, sec_p) - Display *dpy; - char *line; - int *store; - Bool sec_p; +hack_time_text (Display *dpy, char *line, Time *store, Bool sec_p) { if (*line) { int value; value = parse_time (line, sec_p, True); + value *= 1000; /* Time measures in microseconds */ if (value < 0) /*XBell (dpy, 0)*/; else @@ -322,30 +724,36 @@ hack_time_cb (dpy, line, store, sec_p) } } + +/* Callback for text fields that hold a time that default to seconds, + when not fully spelled out. client_data is an Time* where the value goes. + */ static void -res_sec_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +prefs_sec_cb (Widget button, XtPointer client_data, XtPointer call_data) { - hack_time_cb (XtDisplay (button), XmTextGetString (button), - (int *) client_data, True); + hack_time_text (XtDisplay (button), get_text_string (button), + (Time *) client_data, True); } + +/* Callback for text fields that hold a time that default to minutes, + when not fully spelled out. client_data is an Time* where the value goes. + */ static void -res_min_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +prefs_min_cb (Widget button, XtPointer client_data, XtPointer call_data) { - hack_time_cb (XtDisplay (button), XmTextGetString (button), - (int *) client_data, False); + hack_time_text (XtDisplay (button), get_text_string (button), + (Time *) client_data, False); } + +/* Callback for text fields that hold an integer value. + client_data is an int* where the value goes. + */ static void -res_int_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +prefs_int_cb (Widget button, XtPointer client_data, XtPointer call_data) { - char *line = XmTextGetString (button); + char *line = get_text_string (button); int *store = (int *) client_data; unsigned int value; char c; @@ -357,106 +765,145 @@ res_int_cb (button, client_data, call_data) *store = value; } +/* Callback for toggle buttons. client_data is an Bool* where the value goes. + */ static void -res_bool_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +prefs_bool_cb (Widget button, XtPointer client_data, XtPointer call_data) { - int *store = (int *) client_data; + Bool *store = (Bool *) client_data; +#ifdef HAVE_MOTIF *store = ((XmToggleButtonCallbackStruct *) call_data)->set; +#else /* HAVE_ATHENA */ + Boolean state = FALSE; + XtVaGetValues (button, XtNstate, &state, 0); + *store = state; +#endif /* HAVE_ATHENA */ } + +/* Callback for the Cancel button on the Preferences dialog. + */ static void -res_cancel_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +prefs_cancel_cb (Widget button, XtPointer client_data, XtPointer call_data) { - XtDestroyWidget (resources_dialog); - resources_dialog = 0; - raise_screenhack_dialog (); + XtDestroyWidget (preferences_dialog); + preferences_dialog = 0; + XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog)); } +/* Callback for the OK button on the Preferences dialog. + */ static void -res_done_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +prefs_ok_cb (Widget button, XtPointer client_data, XtPointer call_data) { - res_cancel_cb (button, client_data, call_data); - - if (res.timeout < 10) res.timeout = 10; - if (res.cycle < 2) res.cycle = 2; - if (res.passwd_time < 2) res.passwd_time = 30; - - timeout = res.timeout * 1000; - cycle = res.cycle * 1000; - lock_timeout = res.lock_time * 1000; -#ifndef NO_LOCKING - passwd_timeout = res.passwd_time * 1000; -#endif - fade_seconds = res.secs; - fade_ticks = res.ticks; - verbose_p = res.verb; - install_cmap_p = res.cmap; - fade_p = res.fade; - unfade_p = res.unfade; - lock_p = res.lock_p; + prefs_pair *pair = (prefs_pair *) client_data; + saver_preferences *p = pair->a; + saver_preferences *p2 = pair->b; + + prefs_cancel_cb (button, 0, call_data); + +#ifdef HAVE_ATHENA + /* Athena doesn't let us put callbacks on these widgets, so run + all the callbacks by hand when OK is pressed. */ + prefs_min_cb (timeout_text, (XtPointer) &p2->timeout, 0); + prefs_min_cb (cycle_text, (XtPointer) &p2->cycle, 0); + prefs_sec_cb (fade_text, (XtPointer) &p2->fade_seconds, 0); + prefs_int_cb (fade_ticks_text, (XtPointer) &p2->fade_ticks, 0); + prefs_min_cb (lock_timeout_text, (XtPointer) &p2->lock_timeout, 0); + prefs_sec_cb (passwd_timeout_text, (XtPointer) &p2->passwd_timeout, 0); +#endif /* HAVE_ATHENA */ + + p->timeout = p2->timeout; + p->cycle = p2->cycle; + p->lock_timeout = p2->lock_timeout; + p->passwd_timeout = p2->passwd_timeout; + p->fade_seconds = p2->fade_seconds; + p->fade_ticks = p2->fade_ticks; + p->verbose_p = p2->verbose_p; + p->install_cmap_p = p2->install_cmap_p; + p->fade_p = p2->fade_p; + p->unfade_p = p2->unfade_p; + p->lock_p = p2->lock_p; + + write_init_file (p, short_version); } static void -make_resources_dialog (parent) - Widget parent; +make_preferences_dialog (prefs_pair *pair, Widget parent) { - Arg av[10]; - int ac; + saver_preferences *p = pair->a; + saver_preferences *p2 = pair->b; + + Screen *screen = XtScreen (parent); + Display *dpy = XtDisplay (parent); + + *p2 = *p; /* copy all slots of p into p2. */ - create_resources_dialog (parent); + create_preferences_dialog (parent, + DefaultVisualOfScreen (screen), + DefaultColormapOfScreen (screen)); - XtAddCallback (res_done, XmNactivateCallback, res_done_cb, 0); - XtAddCallback (res_cancel, XmNactivateCallback, res_cancel_cb, 0); + add_button_callback (prefs_done, prefs_ok_cb, (XtPointer) pair); + add_button_callback (prefs_cancel, prefs_cancel_cb, 0); #define CB(widget,type,slot) \ - XtAddCallback ((widget), XmNvalueChangedCallback, (type), \ - (XtPointer) (slot)) - CB (timeout_text, res_min_cb, &res.timeout); - CB (cycle_text, res_min_cb, &res.cycle); - CB (fade_text, res_sec_cb, &res.secs); - CB (ticks_text, res_int_cb, &res.ticks); - CB (lock_time_text, res_min_cb, &res.lock_time); - CB (passwd_time_text, res_sec_cb, &res.passwd_time); - CB (verbose_toggle, res_bool_cb, &res.verb); - CB (cmap_toggle, res_bool_cb, &res.cmap); - CB (fade_toggle, res_bool_cb, &res.fade); - CB (unfade_toggle, res_bool_cb, &res.unfade); - CB (lock_toggle, res_bool_cb, &res.lock_p); + add_text_callback ((widget), (type), (XtPointer) (slot)) +#define CBT(widget,type,slot) \ + add_toggle_callback ((widget), (type), (XtPointer) (slot)) + +#ifdef HAVE_MOTIF + /* When using Athena widgets, we can't set callbacks for these, + so in that case, we run them by hand when "OK" is pressed. */ + CB (timeout_text, prefs_min_cb, &p2->timeout); + CB (cycle_text, prefs_min_cb, &p2->cycle); + CB (fade_text, prefs_sec_cb, &p2->fade_seconds); + CB (fade_ticks_text, prefs_int_cb, &p2->fade_ticks); + CB (lock_timeout_text, prefs_min_cb, &p2->lock_timeout); + CB (passwd_timeout_text, prefs_sec_cb, &p2->passwd_timeout); +#endif /* HAVE_MOTIF */ + + CBT (verbose_toggle, prefs_bool_cb, &p2->verbose_p); + CBT (install_cmap_toggle, prefs_bool_cb, &p2->install_cmap_p); + CBT (fade_toggle, prefs_bool_cb, &p2->fade_p); + CBT (unfade_toggle, prefs_bool_cb, &p2->unfade_p); + CBT (lock_toggle, prefs_bool_cb, &p2->lock_p); #undef CB - ac = 0; - XtSetArg (av[ac], XmNsensitive, False); ac++; - - if (locking_disabled_p) - { - XtSetValues (passwd_time_text, av, ac); - XtSetValues (lock_time_text, av, ac); - XtSetValues (lock_toggle, av, ac); - } - if (CellsOfScreen (XtScreen (parent)) <= 2) - { - XtSetValues (fade_text, av, ac); - XtSetValues (ticks_text, av, ac); - XtSetValues (cmap_toggle, av, ac); - XtSetValues (fade_toggle, av, ac); - XtSetValues (unfade_toggle, av, ac); - } +#undef CBT + + { + Bool found_any_writable_cells = False; + int nscreens = ScreenCount(dpy); + int i; + for (i = 0; i < nscreens; i++) + { + Screen *s = ScreenOfDisplay (dpy, i); + if (has_writable_cells (s, DefaultVisualOfScreen (s))) + { + found_any_writable_cells = True; + break; + } + } + + if (! found_any_writable_cells) /* fading isn't possible */ + { + disable_widget (fade_text); + disable_widget (fade_ticks_text); + disable_widget (install_cmap_toggle); + disable_widget (fade_toggle); + disable_widget (unfade_toggle); + } + } } +/* Formats a `Time' into "H:MM:SS". (Time is microseconds.) + */ static void -fmt_time (buf, s, min_p) - char *buf; - unsigned int s; - int min_p; +format_time (char *buf, Time time) { + int s = time / 1000; unsigned int h = 0, m = 0; if (s >= 60) { @@ -468,134 +915,406 @@ fmt_time (buf, s, min_p) h += (m / 60); m %= 60; } -/* - if (min_p && h == 0 && s == 0) - sprintf (buf, "%u", m); - else if (!min_p && h == 0 && m == 0) - sprintf (buf, "%u", s); - else - if (h == 0) - sprintf (buf, "%u:%02u", m, s); - else -*/ - sprintf (buf, "%u:%02u:%02u", h, m, s); + sprintf (buf, "%u:%02u:%02u", h, m, s); } + static void -pop_resources_dialog () +pop_preferences_dialog (prefs_pair *pair) { - char buf [100]; + /* saver_preferences *p = pair->a; */ + saver_preferences *p2 = pair->b; + char s[100]; + + format_time (s, p2->timeout); set_text_string(timeout_text, s); + format_time (s, p2->cycle); set_text_string(cycle_text, s); + format_time (s, p2->lock_timeout); set_text_string(lock_timeout_text, s); + format_time (s, p2->passwd_timeout); set_text_string(passwd_timeout_text, s); + format_time (s, p2->fade_seconds); set_text_string(fade_text, s); + sprintf (s, "%u", p2->fade_ticks); set_text_string(fade_ticks_text, s); + + set_toggle_button_state (verbose_toggle, p2->verbose_p); + set_toggle_button_state (install_cmap_toggle, p2->install_cmap_p); + set_toggle_button_state (fade_toggle, p2->fade_p); + set_toggle_button_state (unfade_toggle, p2->unfade_p); + set_toggle_button_state (lock_toggle, p2->lock_p); + + pop_up_dialog_box (preferences_dialog, preferences_form); +} - res.timeout = timeout / 1000; - res.cycle = cycle / 1000; - res.lock_time = lock_timeout / 1000; -#ifndef NO_LOCKING - res.passwd_time = passwd_timeout / 1000; -#endif - res.secs = fade_seconds; - res.ticks = fade_ticks; - res.verb = verbose_p; - res.cmap = install_cmap_p; - res.fade = fade_p; - res.unfade = unfade_p; - res.lock_p = (lock_p && !locking_disabled_p); - - fmt_time (buf, res.timeout, 1); XmTextSetString (timeout_text, buf); - fmt_time (buf, res.cycle, 1); XmTextSetString (cycle_text, buf); - fmt_time (buf, res.lock_time, 1); XmTextSetString (lock_time_text, buf); - fmt_time (buf, res.passwd_time, 0); XmTextSetString (passwd_time_text, buf); - fmt_time (buf, res.secs, 0); XmTextSetString (fade_text, buf); - sprintf (buf, "%u", res.ticks); XmTextSetString (ticks_text, buf); - - XmToggleButtonSetState (verbose_toggle, res.verb, True); - XmToggleButtonSetState (cmap_toggle, res.cmap, True); - XmToggleButtonSetState (fade_toggle, res.fade, True); - XmToggleButtonSetState (unfade_toggle, res.unfade, True); - XmToggleButtonSetState (lock_toggle, res.lock_p, True); - - pop_up_dialog_box (resources_dialog, resources_form, 1); + +static void +run_hack (Display *dpy, int n) +{ + if (n <= 0) abort(); + xscreensaver_command (dpy, XA_DEMO, n, False); } - -/* The code on this page isn't actually Motif-specific */ -Bool dbox_up_p = False; -Bool demo_mode_p = False; +static void +warning_dialog_dismiss_cb (Widget button, XtPointer client_data, + XtPointer call_data) +{ + Widget shell = (Widget) client_data; + XtDestroyWidget (shell); +} -extern XtAppContext app; -extern Widget toplevel_shell; -extern Bool use_xidle; -extern Time notice_events_timeout; +static void +warning_dialog (Widget parent, const char *message) +{ + char *msg = strdup (message); + char *head; -extern char **screenhacks; -extern char *demo_hack; + Widget dialog = 0; + Widget label = 0; + Widget ok = 0; + int i = 0; -extern void notice_events_timer P((XtPointer closure, void *timer)); -extern Bool handle_clientmessage P((/*XEvent *, Bool*/)); +#ifdef HAVE_MOTIF -void -demo_mode () -{ - dbox_up_p = True; - initialize_screensaver_window (); - raise_window (True, False); - make_screenhack_dialog (toplevel_shell, screenhacks); - while (demo_mode_p) + Widget w; + Widget container; + XmString xmstr; + Arg av[10]; + int ac = 0; + + ac = 0; + dialog = XmCreateWarningDialog (parent, "versionWarning", av, ac); + + w = XmMessageBoxGetChild (dialog, XmDIALOG_MESSAGE_LABEL); + if (w) XtUnmanageChild (w); + w = XmMessageBoxGetChild (dialog, XmDIALOG_CANCEL_BUTTON); + if (w) XtUnmanageChild (w); + w = XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON); + if (w) XtUnmanageChild (w); + + ok = XmMessageBoxGetChild (dialog, XmDIALOG_OK_BUTTON); + + ac = 0; + XtSetArg (av[ac], XmNnumColumns, 1); ac++; + XtSetArg (av[ac], XmNorientation, XmVERTICAL); ac++; + XtSetArg (av[ac], XmNpacking, XmPACK_COLUMN); ac++; + XtSetArg (av[ac], XmNrowColumnType, XmWORK_AREA); ac++; + XtSetArg (av[ac], XmNspacing, 0); ac++; + container = XmCreateRowColumn (dialog, "container", av, ac); + +#else /* HAVE_ATHENA */ + + Widget form; + dialog = XtVaCreatePopupShell("warning_dialog", transientShellWidgetClass, + parent, 0); + form = XtVaCreateManagedWidget("warning_form", formWidgetClass, dialog, 0); + +#endif /* HAVE_ATHENA */ + + head = msg; + while (head) { - XEvent event; - XtAppNextEvent (app, &event); - switch (event.xany.type) - { - case 0: /* synthetic "timeout" event */ - break; + char name[20]; + char *s = strchr (head, '\n'); + if (s) *s = 0; + + sprintf (name, "label%d", i++); + +#ifdef HAVE_MOTIF + xmstr = XmStringCreate (head, XmSTRING_DEFAULT_CHARSET); + ac = 0; + XtSetArg (av[ac], XmNlabelString, xmstr); ac++; + label = XmCreateLabelGadget (container, name, av, ac); + XtManageChild (label); + XmStringFree (xmstr); +#else /* HAVE_ATHENA */ + + label = XtVaCreateManagedWidget (name, labelWidgetClass, + form, + XtNleft, XtChainLeft, + XtNright, XtChainRight, + XtNlabel, head, + (label ? XtNfromVert : XtNtop), + (label ? label : XtChainTop), + 0); + +#endif /* HAVE_ATHENA */ + + if (s) + head = s+1; + else + head = 0; + } - case ClientMessage: - handle_clientmessage (&event, False); - break; +#ifdef HAVE_MOTIF - case CreateNotify: -#ifdef HAVE_XIDLE - if (! use_xidle) -#endif - XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer, - (XtPointer) event.xcreatewindow.window); - break; - - case ButtonPress: - case ButtonRelease: - if (!XtWindowToWidget (dpy, event.xbutton.window)) - raise_screenhack_dialog (); - /* fall through */ - - default: - XtDispatchEvent (&event); - break; - } + XtManageChild (container); + XtRealizeWidget (dialog); + XtManageChild (dialog); + +#else /* HAVE_ATHENA */ + + ok = XtVaCreateManagedWidget ("ok", commandWidgetClass, form, + XtNleft, XtChainLeft, + XtNbottom, XtChainBottom, + XtNfromVert, label, + 0); + + XtRealizeWidget (dialog); + XtPopup (dialog, XtGrabNone); + +#endif /* HAVE_ATHENA */ + + add_button_callback (ok, warning_dialog_dismiss_cb, dialog); + + free (msg); +} + + + +/* The main demo-mode command loop. + */ + +#if 0 +static Bool +mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks, + XrmRepresentation *type, XrmValue *value, XPointer closure) +{ + int i; + for (i = 0; quarks[i]; i++) + { + if (bindings[i] == XrmBindTightly) + fprintf (stderr, (i == 0 ? "" : ".")); + else if (bindings[i] == XrmBindLoosely) + fprintf (stderr, "*"); + else + fprintf (stderr, " ??? "); + fprintf(stderr, "%s", XrmQuarkToString (quarks[i])); } - destroy_screenhack_dialogs (); - initialize_screensaver_window (); - unblank_screen (); + + fprintf (stderr, ": %s\n", (char *) value->addr); + + return False; } +#endif static void -demo_mode_hack (hack) - char *hack; +the_network_is_not_the_computer (Widget parent) { - if (! demo_mode_p) abort (); - kill_screenhack (); - if (! demo_hack) - blank_screen (); - demo_hack = hack; - spawn_screenhack (False); + Display *dpy = XtDisplay (parent); + char *rversion, *ruser, *rhost; + char *luser, *lhost; + char *msg = 0; + struct passwd *p = getpwuid (getuid ()); + const char *d = DisplayString (dpy); + +# if defined(HAVE_UNAME) + struct utsname uts; + if (uname (&uts) < 0) + lhost = ""; + else + lhost = uts.nodename; +# elif defined(VMS) + strcpy (lhost, getenv("SYS$NODE")); +# else /* !HAVE_UNAME && !VMS */ + strcat (lhost, ""); +# endif /* !HAVE_UNAME && !VMS */ + + if (p && p->pw_name) + luser = p->pw_name; + else + luser = "???"; + + server_xscreensaver_version (dpy, &rversion, &ruser, &rhost); + + /* Make a buffer that's big enough for a number of copies of all the + strings, plus some. */ + msg = (char *) malloc (10 * ((rversion ? strlen(rversion) : 0) + + (ruser ? strlen(ruser) : 0) + + (rhost ? strlen(rhost) : 0) + + strlen(lhost) + + strlen(luser) + + strlen(d) + + 30)); + *msg = 0; + + if (!rversion || !*rversion) + { + sprintf (msg, + "Warning:\n\n" + "xscreensaver doesn't seem to be running on display \"%s\".", + d); + } + else if (p && ruser && *ruser && !!strcmp (ruser, p->pw_name)) + { + /* Warn that the two processes are running as different users. + */ + sprintf(msg, + "Warning:\n\n" + "%s is running as user \"%s\" on host \"%s\".\n" + "But the xscreensaver managing display \"%s\"\n" + "is running as user \"%s\" on host \"%s\".\n" + "\n" + "Since they are different users, they won't be reading/writing\n" + "the same ~/.xscreensaver file, so %s isn't\n" + "going to work right.\n" + "\n" + "Either re-run %s as \"%s\", or re-run\n" + "xscreensaver as \"%s\".\n", + progname, luser, lhost, + d, + (ruser ? ruser : "???"), (rhost ? rhost : "???"), + progname, + progname, (ruser ? ruser : "???"), + luser); + } + else if (rhost && *rhost && !!strcmp (rhost, lhost)) + { + /* Warn that the two processes are running on different hosts. + */ + sprintf (msg, + "Warning:\n\n" + "%s is running as user \"%s\" on host \"%s\".\n" + "But the xscreensaver managing display \"%s\"\n" + "is running as user \"%s\" on host \"%s\".\n" + "\n" + "If those two machines don't share a file system (that is,\n" + "if they don't see the same ~%s/.xscreensaver file) then\n" + "%s won't work right.", + progname, luser, lhost, + d, + (ruser ? ruser : "???"), (rhost ? rhost : "???"), + luser, + progname); + } + else if (!!strcmp (rversion, short_version)) + { + /* Warn that the version numbers don't match. + */ + sprintf (msg, + "Warning:\n\n" + "This is %s version %s.\n" + "But the xscreensaver managing display \"%s\"\n" + "is version %s. This could cause problems.", + progname, short_version, + d, + rversion); + } + + + if (*msg) + warning_dialog (parent, msg); + + free (msg); } -static void -demo_mode_done () + +static char *defaults[] = { +#include "XScreenSaver_ad.h" + 0 +}; + +int +main (int argc, char **argv) { - kill_screenhack (); - if (demo_hack) - unblank_screen (); - demo_mode_p = False; - dbox_up_p = False; - demo_hack = 0; + XtAppContext app; + prefs_pair Pair, *pair; + saver_preferences P, P2, *p, *p2; + Bool prefs = False; + int i; + Display *dpy; + Widget toplevel_shell; + char *real_progname = argv[0]; + char *s; + + s = strrchr (real_progname, '/'); + if (s) real_progname = s+1; + + p = &P; + p2 = &P2; + pair = &Pair; + pair->a = p; + pair->b = p2; + memset (p, 0, sizeof (*p)); + memset (p2, 0, sizeof (*p2)); + + /* We must read exactly the same resources as xscreensaver. + That means we must have both the same progclass *and* progname, + at least as far as the resource database is concerned. So, + put "xscreensaver" in argv[0] while initializing Xt. + */ + argv[0] = "xscreensaver"; + + toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, &argc, argv, + defaults, 0, 0); + dpy = XtDisplay (toplevel_shell); + db = XtDatabase (dpy); + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + + for (i = 1; i < argc; i++) + { + char *s = argv[i]; + if (s[0] == '-' && s[1] == '-') + s++; + if (!strcmp (s, "-prefs")) + prefs = True; + else + { + fprintf (stderr, "usage: %s [ -display dpy-string ] [ -prefs ]\n", + real_progname); + exit (1); + } + } + + short_version = (char *) malloc (5); + memcpy (short_version, screensaver_id + 17, 4); + short_version [4] = 0; + + + /* Now that Xt has been initialized, we can set our `progname' variable + to something that makes more sense (like our "real" argv[0].) + */ + progname = real_progname; + + + p->db = db; + p->fading_possible_p = True; + load_init_file (p); + *p2 = *p; + +#ifdef HAVE_ATHENA + global_prefs_kludge = p; /* I hate C so much... */ +#endif /* HAVE_ATHENA */ + +#if 0 + { + XrmName name = { 0 }; + XrmClass class = { 0 }; + int count = 0; + XrmEnumerateDatabase (db, &name, &class, XrmEnumAllLevels, mapper, + (XtPointer) &count); + } +#endif + + + XA_VROOT = XInternAtom (dpy, "__SWM_VROOT", False); + XA_SCREENSAVER = XInternAtom (dpy, "SCREENSAVER", False); + XA_SCREENSAVER_VERSION = XInternAtom (dpy, "_SCREENSAVER_VERSION",False); + XA_SCREENSAVER_TIME = XInternAtom (dpy, "_SCREENSAVER_TIME", False); + XA_SCREENSAVER_ID = XInternAtom (dpy, "_SCREENSAVER_ID", False); + XA_SCREENSAVER_RESPONSE = XInternAtom (dpy, "_SCREENSAVER_RESPONSE", False); + XA_SELECT = XInternAtom (dpy, "SELECT", False); + XA_DEMO = XInternAtom (dpy, "DEMO", False); + XA_RESTART = XInternAtom (dpy, "RESTART", False); + + make_demo_dialog (toplevel_shell, pair); + + if (prefs) + { + make_preferences_dialog (pair, toplevel_shell); + pop_preferences_dialog (pair); + } + + the_network_is_not_the_computer (preferences_dialog + ? preferences_dialog + : demo_dialog); + + XtAppMainLoop(app); + exit (0); }