http://ftp.x.org/contrib/applications/xscreensaver-2.24.tar.gz
[xscreensaver] / driver / demo.c
index a0ae2dab66c1b2d0b09f4c833d4f75822724cb15..10a177efbf258d2939d9b3dc400e21428f489c0c 100644 (file)
@@ -1,5 +1,5 @@
 /* demo.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-1997 Jamie Zawinski <jwz@netscape.com>
+ * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@netscape.com>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 
 #include <X11/Intrinsic.h>
 
+/* We don't actually use any widget internals, but these are included
+   so that gdb will have debug info for the widgets... */
+#include <X11/IntrinsicP.h>
+#include <X11/ShellP.h>
+
 #ifdef HAVE_MOTIF
 # include <Xm/Xm.h>
 # include <Xm/Text.h>
@@ -35,6 +40,7 @@
 # include <X11/Xaw/Viewport.h>
 # include <X11/Xaw/Dialog.h>
 # include <X11/Xaw/Scrollbar.h>
+# include <X11/Xaw/Text.h>
 #endif /* HAVE_ATHENA */
 
 #include "xscreensaver.h"
@@ -99,7 +105,13 @@ get_text_string (Widget text_widget)
   return XmTextGetString (text_widget);
 #else  /* HAVE_ATHENA */
   char *string = 0;
-  XtVaGetValues (text_widget, XtNvalue, &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 */
 }
@@ -199,7 +211,6 @@ destroy_screenhack_dialogs (saver_info *si)
     XInstallColormap (si->dpy, ssi->cmap);
 }
 
-#ifdef HAVE_MOTIF
 
 static void
 text_cb (Widget text_widget, XtPointer client_data, XtPointer call_data)
@@ -210,7 +221,24 @@ text_cb (Widget text_widget, XtPointer client_data, XtPointer call_data)
   demo_mode_hack (si, line);
 }
 
-#endif /* HAVE_MOTIF */
+
+#ifdef HAVE_ATHENA
+/* Bend over backwards to make hitting Return in the text field do the
+   right thing. 
+   */
+extern saver_info *global_si_kludge;
+static void text_enter (Widget w, XEvent *event, String *av, Cardinal *ac)
+{
+  text_cb (w, global_si_kludge, 0);
+}
+
+static XtActionsRec actions[] = {{"done",      text_enter}
+                               };
+static char translations[] = ("<Key>Return:    done()\n"
+                             "<Key>Linefeed:   done()\n"
+                             "Ctrl<Key>M:      done()\n"
+                             "Ctrl<Key>J:      done()\n");
+#endif /* HAVE_ATHENA */
 
 
 static void
@@ -220,7 +248,12 @@ select_cb (Widget button, XtPointer client_data, XtPointer call_data)
 
 #ifdef HAVE_ATHENA
   XawListReturnStruct *item = (XawListReturnStruct*)call_data;
+  XtVaSetValues(text_line, XtNstring, item->string, 0);
+
   demo_mode_hack (si, item->string);
+  if (item->list_index >= 0)
+    si->default_screen->current_hack = item->list_index;
+
 #else  /* HAVE_MOTIF */
   XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
   char *string = 0;
@@ -228,7 +261,11 @@ select_cb (Widget button, XtPointer client_data, XtPointer call_data)
     XmStringGetLtoR (lcb->item, XmSTRING_DEFAULT_CHARSET, &string);
   set_text_string (text_line, (string ? string : ""));
   if (lcb->reason == XmCR_DEFAULT_ACTION && string)
-    demo_mode_hack (si, string);
+    {
+      demo_mode_hack (si, string);
+      if (lcb->item_position > 0)
+       si->default_screen->current_hack = lcb->item_position - 1;
+    }
   if (string)
     XtFree (string);
 #endif /* HAVE_MOTIF */
@@ -341,7 +378,7 @@ next_cb (Widget button, XtPointer client_data, XtPointer call_data)
   int cnt;
   XawListReturnStruct *current = XawListShowCurrent(demo_list);
   if (current->list_index == XAW_LIST_NONE)
-    XawListHighlight(demo_list,1);
+    XawListHighlight(demo_list, 0);
   else
     {
       XtVaGetValues(demo_list,
@@ -356,6 +393,7 @@ next_cb (Widget button, XtPointer client_data, XtPointer call_data)
 
   ensure_selected_item_visible (demo_list);
   current = XawListShowCurrent(demo_list);
+  XtVaSetValues(text_line, XtNstring, current->string, 0);
   demo_mode_hack (si, current->string);
 
 #else  /* HAVE_MOTIF */
@@ -363,18 +401,19 @@ next_cb (Widget button, XtPointer client_data, XtPointer call_data)
   int *pos_list;
   int pos_count;
   if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
-    XmListSelectPos (demo_list, 1, True);
+    {
+      XmListDeselectAllItems(demo_list);       /* LessTif lossage */
+      XmListSelectPos (demo_list, 1, 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);
+      int pos = pos_list[0] + 1;
+      if (pos > si->prefs.screenhacks_count)
+       pos = 1;
+      XmListDeselectAllItems(demo_list);       /* LessTif lossage */
+      XmListSelectPos (demo_list, pos, True);
     }
+  XtFree ((char *) pos_list);
   ensure_selected_item_visible (demo_list);
   demo_mode_hack (si, get_text_string (text_line));
 
@@ -390,10 +429,10 @@ prev_cb (Widget button, XtPointer client_data, XtPointer call_data)
 #ifdef HAVE_ATHENA
   XawListReturnStruct *current=XawListShowCurrent(demo_list);
   if (current->list_index == XAW_LIST_NONE)
-    XawListHighlight(demo_list,1);
+    XawListHighlight(demo_list, 0);
   else
     {
-      if (current->list_index>=1)
+      if (current->list_index >= 1)
        {
          current->list_index--;
          XawListHighlight(demo_list, current->list_index);
@@ -402,6 +441,7 @@ prev_cb (Widget button, XtPointer client_data, XtPointer call_data)
 
   ensure_selected_item_visible (demo_list);
   current = XawListShowCurrent(demo_list);
+  XtVaSetValues(text_line, XtNstring, current->string, 0);
   demo_mode_hack (si, current->string);
 
 #else  /* HAVE_MOTIF */
@@ -409,9 +449,13 @@ prev_cb (Widget button, XtPointer client_data, XtPointer call_data)
   int *pos_list;
   int pos_count;
   if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
-    XmListSelectPos (demo_list, 0, True);
+    {
+      XmListDeselectAllItems(demo_list);       /* LessTif lossage */
+      XmListSelectPos (demo_list, 0, True);
+    }
   else
     {
+      XmListDeselectAllItems(demo_list);       /* LessTif lossage */
       XmListSelectPos (demo_list, pos_list [0] - 1, True);
       XtFree ((char *) pos_list);
     }
@@ -451,6 +495,7 @@ restart_cb (Widget button, XtPointer client_data, XtPointer call_data)
   demo_mode_restart_process (si);
 }
 
+
 void
 pop_up_dialog_box (Widget dialog, Widget form, int where)
 {
@@ -481,13 +526,12 @@ pop_up_dialog_box (Widget dialog, Widget form, int where)
   XtSetArg (av [ac], XtNheight, &h); ac++;
   XtGetValues (form, av, ac);
 
-#ifdef DEBUG
+  /* for debugging -- don't ask */
   if (where >= 69)
     {
       where -= 69;
       sw = (sw * 7) / 12;
     }
-#endif
 
   switch (where)
     {
@@ -530,7 +574,7 @@ pop_up_dialog_box (Widget dialog, Widget form, int where)
 }
 
 
-static void
+void
 make_screenhack_dialog (saver_info *si)
 {
   saver_screen_info *ssi = si->default_screen;
@@ -568,28 +612,116 @@ make_screenhack_dialog (saver_info *si)
                 select_cb, (XtPointer) si);
   XtAddCallback (text_line, XmNactivateCallback, text_cb, (XtPointer) si);
 
-  for (; *hacks; hacks++)
+  if (hacks)
+    for (; *hacks; hacks++)
+      {
+       XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
+       XmListAddItem (demo_list, xmstr, 0);
+       XmStringFree (xmstr);
+      }
+
+  /* Cause the most-recently-run hack to be selected in the list.
+     Do some voodoo to make it be roughly centered in the list (really,
+     just make it not be within +/- 5 of the top/bottom if possible.)
+   */
+  if (ssi->current_hack > 0)
     {
-      XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
-      XmListAddItem (demo_list, xmstr, 0);
-      XmStringFree (xmstr);
+      int i = ssi->current_hack+1;
+      int top = i + 5;
+      int bot = i - 5;
+      if (bot < 1) bot = 1;
+      if (top > si->prefs.screenhacks_count)
+       top = si->prefs.screenhacks_count;
+
+      XmListDeselectAllItems(demo_list);       /* LessTif lossage */
+      XmListSelectPos (demo_list, bot, False);
+      ensure_selected_item_visible (demo_list);
+
+      XmListDeselectAllItems(demo_list);       /* LessTif lossage */
+      XmListSelectPos (demo_list, top, False);
+      ensure_selected_item_visible (demo_list);
+
+      XmListDeselectAllItems(demo_list);       /* LessTif lossage */
+      XmListSelectPos (demo_list, i, False);
+      ensure_selected_item_visible (demo_list);
     }
 
 #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, si->prefs.screenhacks_count,
                 0);
   XtAddCallback (demo_list, XtNcallback, select_cb, si);
+  if (ssi->current_hack > 0)
+  XawListHighlight(demo_list, ssi->current_hack);
+
+  /* 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);
+    printf("%d %d %d %d\n", x, y, w, h);
+    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 */
 
+  monitor_power_on (si);
   pop_up_dialog_box(demo_dialog, demo_form,
-#ifdef DEBUG
+                   /* for debugging -- don't ask */
                    (si->prefs.debug_p ? 69 : 0) +
-#endif
                    0);
+
+#ifdef HAVE_ATHENA
+  /* For Athena, have to do this after the dialog is managed. */
+  ensure_selected_item_visible (demo_list);
+#endif /* HAVE_ATHENA */
 }
 
 \f
@@ -703,21 +835,20 @@ res_done_cb (Widget button, XtPointer client_data, XtPointer call_data)
   p->unfade_p = res.unfade;
   p->lock_p = res.lock_p;
 
-#ifdef DEBUG
   if (p->debug_p && p->verbose_p)
     fprintf (stderr, "%s: parameters changed:\n\
        timeout: %d\n\tcycle:   %d\n\tlock:    %d\n\tpasswd:  %d\n\
        fade:    %d\n\tfade:    %d\n\tverbose: %d\n\tinstall: %d\n\
        fade:    %d\n\tunfade:  %d\n\tlock:    %d\n",
-            progname, p->timeout, p->cycle, p->lock_timeout,
-# ifdef NO_LOCKING
+            blurb(), p->timeout, p->cycle, p->lock_timeout,
+#ifdef NO_LOCKING
             0,
-# else
+#else
             p->passwd_timeout,
-# endif
+#endif
             p->fade_seconds, p->fade_ticks, p->verbose_p, p->install_cmap_p,
             p->fade_p, p->unfade_p, p->lock_p);
-#endif /* DEBUG */
+
 
 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
   if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
@@ -733,7 +864,7 @@ res_done_cb (Widget button, XtPointer client_data, XtPointer call_data)
          if (p->verbose_p)
            fprintf (stderr,
                   "%s: configuring server for saver timeout of %d seconds.\n",
-                    progname, server_timeout);
+                    blurb(), server_timeout);
          /* Leave all other parameters the same. */
          XSetScreenSaver (si->dpy, server_timeout, server_interval,
                           prefer_blank, allow_exp);
@@ -870,10 +1001,10 @@ pop_resources_dialog (saver_info *si)
   set_toggle_button_state (unfade_toggle, res.unfade);
   set_toggle_button_state (lock_toggle, res.lock_p);
 
+  monitor_power_on (si);
   pop_up_dialog_box (resources_dialog, resources_form,
-#ifdef DEBUG
+                    /* for debugging -- don't ask */
                     (si->prefs.debug_p ? 69 : 0) +
-#endif
                     1);
 }
 
@@ -886,7 +1017,7 @@ demo_mode (saver_info *si)
 {
   saver_preferences *p = &si->prefs;
   si->dbox_up_p = True;
-  initialize_screensaver_window (si);
+  monitor_power_on (si);
   raise_window (si, True, False, False);
   make_screenhack_dialog (si);
   while (si->demo_mode_p)
@@ -911,7 +1042,7 @@ demo_mode (saver_info *si)
 #ifdef DEBUG_TIMERS
              if (p->verbose_p)
                printf ("%s: starting notice_events_timer for 0x%X (%lu)\n",
-                       progname,
+                       blurb(),
                        (unsigned int) event.xcreatewindow.window,
                        p->notice_events_timeout);
 #endif /* DEBUG_TIMERS */