+
+#elif defined(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 */
+}
+
+
+#ifdef HAVE_ATHENA
+static void
+set_hack_list (Widget demo_list, saver_preferences *p)
+{
+ char **strings = (char **) calloc (sizeof (char *), p->screenhacks_count);
+ int i;
+ for (i = 0; i < p->screenhacks_count; i++)
+ strings[i] = format_hack (p->screenhacks[i], False);
+ XtVaSetValues (demo_list,
+ XtNlist, strings,
+ XtNnumberStrings, p->screenhacks_count,
+ 0);
+# if 0
+ for (i = 0; i < p->screenhacks_count; i++)
+ {
+ free (strings[i]);
+ strings[i] = (char *) 0xDEADBEEF;
+ }
+ free (strings);
+# endif
+}
+#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
+text_cb (WIDGET text_widget, POINTER client_data, POINTER call_data)
+{
+ saver_preferences *p = (saver_preferences *) client_data;
+ char *new_text = get_text_string (text_widget);
+ Display *dpy = widget_display (text_widget);
+ Bool save = TRUE;
+
+ int hack_number = -1; /* 0-based */
+
+#ifdef HAVE_ATHENA
+ XawListReturnStruct *current = XawListShowCurrent(demo_list);
+ hack_number = current->list_index;
+#elif defined(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_ATHENA */
+
+ ensure_selected_item_visible (demo_list);
+
+ if (hack_number < 0 || hack_number >= p->screenhacks_count)
+ {
+ set_text_string (text_widget, "");
+ XBell (XtDisplay (text_widget), 0);
+ }
+ else
+ {
+ screenhack *new_hack = parse_screenhack (new_text);
+ if (p->screenhacks [hack_number])
+ free_screenhack (p->screenhacks [hack_number]);
+ p->screenhacks [hack_number] = new_hack;
+
+#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);
+
+#elif defined(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);
+ set_hack_list (demo_list, p);
+ XawViewportSetCoordinates (vp, vp_x, vp_y);
+ XawListHighlight (demo_list, hack_number);
+ }
+
+#endif /* HAVE_ATHENA */
+
+ if (save)
+ 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... */