summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBradford Hovinen (Gdict maintainer) <hovinen@src.gnome.org>2000-07-31 20:06:12 +0000
committerBradford Hovinen (Gdict maintainer) <hovinen@src.gnome.org>2000-07-31 20:06:12 +0000
commit2830dc67b34fcc777cfcf774dc13cdf3a277dbe3 (patch)
tree3690ce4b6bcbe27e001015e954d73d56f6ccd0d4
parent7bd66b87444ecc4dafcdf2d6954d28cd70794945 (diff)
downloadgnome-control-center-2830dc67b34fcc777cfcf774dc13cdf3a277dbe3.tar.gz
Added new screensaver properties capplet
-rw-r--r--capplets/screensaver/ChangeLog488
-rw-r--r--capplets/screensaver/XScreenSaver_ad.h952
-rw-r--r--capplets/screensaver/checked-disabled.xpm22
-rw-r--r--capplets/screensaver/checked.xpm22
-rw-r--r--capplets/screensaver/daemon.c77
-rw-r--r--capplets/screensaver/daemon.h34
-rw-r--r--capplets/screensaver/expr.c259
-rw-r--r--capplets/screensaver/expr.h36
-rw-r--r--capplets/screensaver/main.c248
-rw-r--r--capplets/screensaver/no-hack.pngbin0 -> 2250 bytes
-rw-r--r--capplets/screensaver/pref-file.c538
-rw-r--r--capplets/screensaver/pref-file.h33
-rw-r--r--capplets/screensaver/preferences.c288
-rw-r--r--capplets/screensaver/preferences.h110
-rw-r--r--capplets/screensaver/prefs-widget.c1635
-rw-r--r--capplets/screensaver/prefs-widget.h128
-rw-r--r--capplets/screensaver/preview.c322
-rw-r--r--capplets/screensaver/preview.h39
-rw-r--r--capplets/screensaver/rc-parse.c601
-rw-r--r--capplets/screensaver/rc-parse.h48
-rw-r--r--capplets/screensaver/resources.c138
-rw-r--r--capplets/screensaver/resources.h37
-rw-r--r--capplets/screensaver/screensaver-prefs-dialog.c953
-rw-r--r--capplets/screensaver/screensaver-prefs-dialog.h72
-rw-r--r--capplets/screensaver/screensaver-properties.desktop44
-rw-r--r--capplets/screensaver/selection-dialog.c239
-rw-r--r--capplets/screensaver/selection-dialog.h61
-rw-r--r--capplets/screensaver/unchecked-disabled.xpm22
-rw-r--r--capplets/screensaver/unchecked.xpm22
29 files changed, 7468 insertions, 0 deletions
diff --git a/capplets/screensaver/ChangeLog b/capplets/screensaver/ChangeLog
new file mode 100644
index 000000000..d35774939
--- /dev/null
+++ b/capplets/screensaver/ChangeLog
@@ -0,0 +1,488 @@
+2000-07-31 Bradford Hovinen <hovinen@helixcode.com>
+
+ * all: Removed ENABLE_{LIBGLADE|CAPPLET|PREVIEW} ifdefs
+
+2000-07-26 Bradford Hovinen <hovinen@helixcode.com>
+
+ * src/rc-parse.c (command_exists): Use gnome_is_program_in_path,
+ return stat results if program is a full path
+
+2000-07-20 Bradford Hovinen <hovinen@helixcode.com>
+
+ * src/prefs-widget.c: Include check button xpms
+ (set_pixmap): Use gdk_pixbuf_new_from_xpm_data
+
+ * src/Makefile.am (screensaver_properties_capplet_SOURCES): Put
+ headers in sources list
+ (pixmap_DATA): Don't install xpms
+ (EXTRA_DIST): Add check button xpms
+
+2000-06-25 Bradford Hovinen <hovinen@udel.edu>
+
+ * src/prefs-widget.c (screensaver_remove_cb): Select next row, not
+ next saver in list
+
+ * src/selection-dialog.c (place_screensaver_list): Don't crash if
+ node is null
+
+ * src/rc-parse.c (parse_screensaver_list): Code cleanup
+
+ * src/selection-dialog.c (place_screensaver_list): Code cleanup
+
+ * src/preferences.c (screensaver_remove): Return pointer to new head
+ of list, take pointer to start of screensaver list,
+ use g_list_remove_link
+
+ * src/prefs-widget.c (screensaver_remove_cb): Get new head pointer
+ and assign to screensaver list entry, assign widget->selected_saver
+ (screensaver_prefs_ok_cb): Set text in clist
+
+ * src/main.c (demo_cb): Save a copy of prefs_widget->screensavers
+ in prefs before saving preferences
+
+2000-06-24 Bradford Hovinen <hovinen@udel.edu>
+
+ * src/screensaver-prefs-dialog.c (read_boolean): Set toggle button
+ correctly
+
+ * src/expr.c (int_parse_factor): Handle G_TOKEN_IDENTIFIER
+
+ * src/screensaver-prefs-dialog.c (read_command_line): Use GScanner
+ (arg_is_set): Rewrite for sentance parser
+
+ * src/expr.c (int_parse_factor): Use g_scanner_error
+ (parse_sentance):
+ (int_parse_sentance):
+ (int_parse_unary):
+ (int_parse_atom): Implement
+
+2000-06-23 Bradford Hovinen <hovinen@udel.edu>
+
+ * src/prefs-widget.c (prefs_widget_init): Tweak table attach
+ policies for screensaver selection page
+
+ * src/main.c (setup_capplet_widget): Set window policy
+
+ * src/preview.c (strip_arg):
+ (setup_path):
+ (add_window_arg):
+ (show_screensaver): Compile only if ENABLE_PREVIEW set
+
+ * src/prefs-widget.c (prefs_widget_init): Use table for
+ positioning basic controls
+
+ * src/main.c (main): Start xscreensaver only if screensaver is not
+ disabled
+ (try_cb):
+ (revert_cb):
+ (ok_cb):
+ (cancel_cb): Start and stop xscreensaver based on whether
+ screensaver is disabled
+
+ * src/screensaver-prefs-dialog.c (get_basic_screensaver_widget):
+ Add visual combo box, set border width to 5
+ (screensaver_prefs_dialog_new): Don't set container border width
+ for frame
+ (store_cli): Save visual
+
+ * src/prefs-widget.c (prefs_widget_init): Set frame border width
+ after adding scrolled window
+
+ * src/preferences.c (preferences_load): Make default selection
+ mode 3
+
+ * src/preferences.h: Add SM_DISABLE_SCREENSAVER and SM_BLANK_SCREEN
+
+ * src/prefs-widget.c (prefs_widget_init): Use table for power
+ management
+ (prefs_widget_init): Add disable screensaver and black screen only
+ controls
+
+ * src/main.c (setup_capplet_widget): Don't call
+ prefs_widget_set_screensavers
+
+ * src/prefs-widget.c (prefs_widget_get_prefs): Call
+ prefs_widget_set_screensavers
+ (prefs_widget_set_screensavers): Clear clist
+
+ * src/preview.c: gdk-pixbuf should be mandatory
+ (show_screensaver): Don't fork off second process
+ (show_screensaver_timeout): Implement
+ (close_preview): Clear preview_pid, cancel timeout
+ (show_preview): Set timeout id
+ Declare preview_window, preview_pid, and timeout_id only if
+ preview is enabled
+
+ * src/prefs-widget.c (prefs_widget_init): Make viewport
+ declaration depend on whether ENABLE_PREVIEW is declared
+
+2000-06-22 Bradford Hovinen <hovinen@udel.edu>
+
+ * src/preview.c: Removed demo_pid and demo_window
+ (print_args): Disabled compilation
+
+ * src/screensaver-prefs-dialog.c (get_argument_data):
+ (get_screensaver_widget):
+ (arg_mapping_exists): Use SSPROP_DATADIR
+
+ * src/preview.c (show_screensaver): Use SSPROP_DATADIR
+
+ * src/prefs-widget.c (set_pixmap): Use SSPROP_DATADIR
+
+ * configure.in (SSPROP_DATADIR): Define
+
+ * src/prefs-widget.c (prefs_widget_init): Autosort screensaver list on
+ column 1
+ (select_saver_cb):
+ (deselect_saver_cb):
+ (create_list_item): Use gtk_clist_{get|set}_row_data
+ (set_pixmap): Accept row
+ (set_toggle_buttons_sensitive): Use gtk_clist_get_row_data
+ (set_screensavers_enabled): Don't call set_pixmap
+ (set_all_pixmaps): Rename from set_toggle_buttons_sensitive
+ (one_screensaver_cb):
+ (random_cb): Don't call set_all_pixmaps
+ (toggle_saver): Accept row
+ (demo_next_cb):
+ (demo_prev_cb): Use gtk_clist_find_row_with_data to get row
+ (select_row): Implement
+ (create_list_item): Return row
+ (prefs_widget_init): Don't create viewport
+ (prefs_widget_set_screensavers): Find enabled screensaver
+ manually, freeze and thaw screensaver list
+
+ * src/main.c (setup_capplet_widget): Don't sort
+
+ * src/prefs-widget.c (deselect_saver_cb):
+ (toggle_saver): Implement
+ (set_pixmap): Create pixmaps here, use GdkPixbuf
+ (prefs_widget_store_prefs): Store selection mode
+ (set_pixmap):
+ (set_toggle_buttons_sensitive): Pass selection mode
+ (prefs_widget_set_screensavers):
+ (demo_next_cb):
+ (demo_prev_cb):
+ (screensaver_remove_cb):
+ (one_screensaver_cb):
+ (add_select_cb): Call gtk_clist_moveto after selecting widget
+
+ * src/preferences.h (struct _Screensaver ): Remove widgets
+
+ * src/prefs-widget.c (prefs_widget_class_init): Set up pixmaps for
+ screensaver list
+ (prefs_widget_init): Construct clist for screensaver_list, connect
+ signal for selecting rows
+ (create_list_item):
+ (add_select_cb):
+ (prefs_widget_set_screensavers):
+ (select_saver_cb):
+ (set_toggle_buttons_sensitive):
+ (set_screensavers_enabled):
+ (choose_from_selected_cb):
+ (demo_next_cb):
+ (demo_prev_cb): Rewrite for clist
+ (demo_next_cb):
+ (demo_prev_cb): Don't stop preview
+ (screensaver_toggle_cb): Remove
+ (prefs_widget_init): Remove disabled code
+
+ * src/preferences.c (get_selection_mode): Remove
+ (preferences_load):
+ (preferences_save): Use gnome_config to store selection mode
+ (preferences_destroy):
+ (screensaver_destroy): Don't act if object is NULL
+ (preferences_load):
+ (preferences_save):
+ (screensaver_add):
+ (screensaver_remove):
+ (screensaver_get_desc): Add assertions
+
+ * src/prefs-widget.c (choose_from_selected_cb): Check off active
+ screensaver when moving from one screensaver only mode to choose
+ from selected mode
+
+ * configure.in: Eliminate option to use xscreensaver command to
+ start demo (made mandatory)
+
+ * src/preview.c (show_screensaver): Lower priority on preview
+ (show_demo): Don't close preview when showing demo
+ Eliminate version of show_demo that calls screensaver directly
+
+ * src/prefs-widget.c (prefs_widget_init): Make priority range from -20
+ to 0
+
+2000-06-21 Bradford Hovinen <hovinen@udel.edu>
+
+ * src/pref-file.c (get_line): Don't subtract off len, don't use len-2
+ when doing line number increase test
+
+ * src/prefs-widget.c (prefs_widget_init): Change "selected" to
+ "checked off"
+
+ * src/main.c (setup_capplet_widget): Set screensavers after showing
+ the widget
+
+ * src/prefs-widget.c (demo_next_cb):
+ (demo_prev_cb): Kill off the preview
+ (set_screensavers_enabled): Implement
+ (random_cb): Enable all screensavers
+ (one_screensaver_cb): Disable all screensavers, then select the
+ first one if none selected
+ (prefs_widget_set_screensavers): Select enabled item when in one
+ screensaver only mode
+
+ * src/screensaver-prefs-dialog.c (screensaver_prefs_dialog_init): Add
+ help button
+ (help_cb): Implement
+
+ * src/prefs-widget.c (prefs_demo_cb): Implement
+
+ * src/screensaver-prefs-dialog.c (get_basic_screensaver_widget):
+ Remove message to choose a screensaver from the list, set padding
+ to 5 pixels
+ (arg_mapping_exists): Return FALSE if name is NULL
+ (screensaver_prefs_dialog_init): Add demo button
+ (screensaver_prefs_dialog_new): Connect demo button signal
+ (store_cli):
+ (demo_cb): Implement
+ (screensaver_prefs_dialog_class_init): Add signal demo
+
+ * src/preferences.c (screensaver_get_desc): Set screensaver
+ description to default value if it cannot be found
+
+ * src/selection-dialog.c (selection_dialog_ok_cb): Use g_strdup for
+ name, set name and command_line only when selected node is valid
+
+ * src/preferences.c (screensaver_add): Implement
+
+ * src/prefs-widget.c (screensaver_add_cb): Use SelectionDialog
+ (create_list_item): Implement
+ (add_select_cb): Select the item just created
+
+ * src/selection-dialog.c (selection_dialog_get_type):
+ (selection_dialog_init):
+ (selection_dialog_class_init):
+ (selection_dialog_new):
+ (select_program_cb):
+ (selection_dialog_ok_cb):
+ (selection_dialog_cancel_cb):
+ (append_list_item): Implement
+
+ * src/prefs-widget.c (prefs_widget_set_screensavers): Make item a
+ member of the saver
+
+ * src/preferences.c (screensaver_destroy): Don't remove link from
+ list; assume that's already done
+ (screensaver_remove): Don't destroy screensaver
+
+ * src/prefs-widget.c (prefs_widget_store_prefs): Use
+ gtk_spin_button_get_value_as_{float|int}
+ (make_screensaver_selection_dialog):
+ (add_cancel_cb):
+ (add_select_cb): Implement
+
+ * src/preferences.c (store_prefs_in_db):
+ (read_prefs_from_db): Remove password timeout
+
+ * src/rc-parse.c (write_minutes): Accept gdouble
+ (parse_minutes_resource): Return gdouble
+
+ * src/preferences.h (struct _Preferences ): Make timeouts doubles
+
+ * src/prefs-widget.c (prefs_widget_set_screensavers): Use member
+ label_widget rather than auto label
+ (prefs_widget_init): Remove controls dealing with password
+ timeout, make lock timeout in minutes
+
+ * src/preferences.c (screensaver_remove): Implement
+
+ * src/prefs-widget.c (prefs_widget_init): Add demo previous button
+ (demo_prev_cb): Implement
+
+ * src/rc-parse.c (parse_screensaver_list): Use our own procedure to
+ append the item to the end of the list
+
+ * src/prefs-widget.c (demo_next_cb):
+ (settings_cb): Check if a screensaver is selected before proceeding
+ (demo_next_cb): Implement
+
+ * src/rc-parse.c (parse_screensaver_list): Set saver->link
+
+ * src/prefs-widget.c (prefs_widget_init): Make remove button a member
+ of the structure
+ (select_saver_cb): Sensitive remove_button
+ (prefs_widget_init): Add demo next button
+
+ * src/preview.c (find_xscreensaver_window): Fixed up the code to
+ trap errors better
+
+2000-06-20 Bradford Hovinen <hovinen@udel.edu>
+
+ * src/screensaver-prefs-dialog.c (screensaver_prefs_dialog_init): Add
+ code to support name entry
+ (screensaver_prefs_dialog_new): Set name entry to label, add
+ preferences widget only if it exists, make basic_widget an element
+ of the structure
+ (screensaver_prop_ok_cb): Set label from name entry, free old
+ command line and label, use g_strdup when getting text from entries
+ (add_screensaver_selector): Implement
+ (get_basic_screensaver_widget): Use a different label if the
+ screensaver is not yet defined
+
+ * src/prefs-widget.c (set_standby_time_sensitive):
+ (set_suspend_time_sensitive):
+ (set_power_controls_sensitive): Implement
+ (set_power_down_time_sensitive): Disable only the control, not the
+ labels
+ (power_management_toggled_cb): Use set_power_controls_sensitive
+ (prefs_widget_get_prefs): Code cleanup
+
+ * src/daemon.c (setup_dpms): Use standby and suspend times, add
+ prefs->timeout, sanitize values before sending to xset, return if
+ power management disabled
+
+ * src/preferences.c (preferences_load):
+ (preferences_save): Load/save standby and suspend times
+
+ * src/prefs-widget.c (prefs_widget_init): Remove extraneous code, add
+ support for all dpms timings
+ (prefs_widget_store_prefs):
+ (prefs_widget_get_prefs): Read/store standby and suspend times
+
+ * src/daemon.c (setup_dpms): Don't call the command to enable dpms,
+ use unsigned formats, multiply times by 60
+
+ * src/main.c (state_changed_cb):
+ (try_cb):
+ (revert_cb):
+ (ok_cb): Call setup_dpms
+
+ * src/rc-parse.c (get_settings_name):
+ (get_label): Use g_strdup rather than strdup
+
+ * src/pref-file.c (preferences_save_to_file):
+ (write_entry): Use g_file_test rather than stat
+
+ * src/main.c (main): Set up to start xscreensaver on startup
+
+ * src/rc-parse.c (get_settings_name): Use g_basename
+ (command_exists): Use g_file_test rather than stat
+ (parse_boolean_resource): Use g_strncasecmp
+
+ * src/pref-file.c (init_file_name): Use g_concat_dir_and_file and
+ g_get_home_dir
+
+ * src/daemon.c (start_xscreensaver):
+ (stop_xscreensaver):
+ (restart_xscreensaver):
+ (setup_dpms): Use gnome_execute_shell rather than system
+
+ * src/main.c (cancel_cb):
+ (ok_cb):
+ (revert_cb):
+ (try_cb): Don't restart xscreensaver
+
+ * src/prefs-widget.c (prefs_widget_get_prefs): Don't divide minute
+ values by 60 before displaying
+ (prefs_widget_store_prefs): Don't multiply minute values by 60
+ before storing
+
+ * src/pref-file.c (preferences_save_to_file): Use g_warning rather
+ than sprintf and perror
+ (parse_config_file): Use g_warning directly rather than
+ g_strdup_printf
+
+ * src/preferences.h (struct _Preferences ): Change be_verbose to
+ verbose
+
+ * src/preferences.c (preferences_get_screensaver_list): Remove
+ (preferences_load): Call read_prefs_from_db
+ (preferences_save): Call store_prefs_in_db
+ (read_prefs_from_db):
+ (store_prefs_in_db): Implement
+
+ * src/rc-parse.c (format_command):
+ (stab_to):
+ (string_columns):
+ (format_hack): Move to rc-parse.c
+ (write_screensaver_list): Implement; copy from pref-file.c,
+ preferences_save_to_file
+ (write_screensaver_list): Fixed memory leak with output from
+ format_hack
+
+ * src/pref-file.c (preferences_save_to_file): Remove code to write out
+ programs resource string
+
+ * src/preferences.c (preferences_destroy): Remove check on prefs->shell
+
+ * src/prefs-widget.c (prefs_widget_init): Remove lock_vts widget
+
+2000-06-19 Bradford Hovinen <hovinen@udel.edu>
+
+ * src/prefs-widget.c (prefs_widget_init): Create GtkText
+ prefs->description rather than prefs->description_label; put
+ inside a scrolled window
+ (select_saver_cb): Fill GtkText with description
+ (set_description_text): Implement
+
+ * src/preview.c (show_demo): Make xscreensaver_window automatic
+
+ * src/prefs-widget.c (prefs_widget_class_init): New signal:
+ activate-demo
+ (demo_cb): Emit activate-demo signal
+
+ * src/main.c (setup_capplet_widget): Connect activate-demo signal
+
+ * src/preview.c (find_xscreensaver_window): Use free rather than
+ g_free for data allocated by Xlib
+ (show_demo): Free allocated event structure
+
+ * src/pref-file.c: Use g_strstrip rather than strip
+ (transform_line): Add default action to copy escaped character over
+
+ * src/rc-parse.c (command_exists): Check for string termination when
+ looking for the first whitespace
+
+ * src/resources.c (get_resource): Use g_strconcat rather than strcpy
+ and strcat
+
+ * src/rc-parse.c (parse_screensaver): Use g_strdup rather than malloc
+ and strncpy
+
+ * src/screensaver-prefs-dialog.c (arg_mapping_exists): Implement
+ (screensaver_prefs_dialog_new): Check if glade definition exists
+ before trying to load data
+
+ * src/pref-file.c (transform_line): Terminate loop when i > len
+ (strip): Code cleanup
+ (init_file_name):
+ (init_file_tmp_name): Use g_strconcat rather than legacy functions
+
+ * src/prefs-widget.c (prefs_widget_init): Add line to set data type
+ for fade_ticks_widget to integer
+
+2000-06-18 Bradford Hovinen <hovinen@udel.edu>
+
+ * src/pref-file.c (place_preferences): Delete
+ (preferences_load_from_file): Return gboolean rather than int
+ (preferences_save_to_file): Use g_tree_traverse on config_db
+ (write_preference_cb): Implement
+ (preferences_save_to_file): Store programs resource in config_db
+ after building it
+ (transform_line): Added support for backslash escape
+
+ * src/resources.c (preferences_load_from_xrdb): Update to use
+ config_db
+ (get_string_resource): Rename to get_resource
+
+ * src/pref-file.c (preferences_load_from_file): Use GTree for
+ config_db rather than GHashTable
+
+ * src/prefs-widget.c (prefs_widget_init): Put preview above
+ description
+
+ * src/preferences.h (struct _Preferences ): Add config_db
+
+ * src/screensaver-prefs-dialog.c (screensaver_prefs_dialog_new): Set
+ dialog title to label + " properties"
+
diff --git a/capplets/screensaver/XScreenSaver_ad.h b/capplets/screensaver/XScreenSaver_ad.h
new file mode 100644
index 000000000..667edf900
--- /dev/null
+++ b/capplets/screensaver/XScreenSaver_ad.h
@@ -0,0 +1,952 @@
+"#error Do not run app-defaults files through xrdb!",
+"#error That does not do what you might expect.",
+"#error Put this file in /usr/lib/X11/app-defaults/XScreenSaver instead.",
+"*timeout: 10",
+"*cycle: 10",
+"*lockTimeout: 0",
+"*passwdTimeout: 30",
+"*nice: 10",
+"*lock: False",
+"*lockVTs: True",
+"*verbose: False",
+"*timestamp: False",
+"*fade: True",
+"*unfade: False",
+"*fadeSeconds: 3",
+"*fadeTicks: 20",
+"*splash: True",
+"*splashDuration: 5",
+"*visualID: default",
+"*captureStderr: True",
+"*overlayTextForeground: #FFFF00",
+"*overlayTextBackground: #000000",
+"*overlayStderr: True",
+"*font: *-medium-r-*-140-*-m-*",
+"*sgiSaverExtension: True",
+"*mitSaverExtension: False",
+"*xidleExtension: True",
+"*procInterrupts: True",
+"*demoCommand: xscreensaver-demo",
+"*prefsCommand: xscreensaver-demo -prefs",
+"*helpURL: http://www.jwz.org/xscreensaver/man.html",
+"*loadURL: netscape -remote 'openURL(%s)' || netscape '%s'",
+"*manualCommand: xterm +sb -fg black -bg gray75 -T '%s manual' \
+ -e /bin/sh -c 'man \"%s\" || read foo'",
+"*dateFormat: %d-%b-%y (%a); %I:%M %p",
+"*installColormap: True",
+"*programs: \
+ \"Qix (solid)\" qix -root -solid -delay 0 -segments 100 \\n\
+ \"Qix (transparent)\" qix -root -count 4 -solid -transparent \\n\
+ \"Qix (linear)\" qix -root -count 5 -solid -transparent \
+ -linear -segments 250 -size 100 \\n\
+- mono: \"Qix (xor)\" qix -root -linear -count 5 -size 200 \
+ -spread 30 -segments 75 -solid -xor \\n\
+ \
+ \"Attraction (balls)\" attraction -root -mode balls \\n\
+ \"Attraction (lines)\" attraction -root -mode lines -points 3 \
+ -segments 200 \\n\
+- \"Attraction (poly)\" attraction -root -mode polygons \\n\
+ \"Attraction (splines)\" attraction -root -mode splines -segments \
+ 300 \\n\
+ \"Attraction (orbital)\" attraction -root -mode lines -radius 300 \
+ -orbit -vmult 0.5 \\n\
+ \
+ pyro -root \\n\
+ rocks -root \\n\
+ helix -root \\n\
+ pedal -root \\n\
+ rorschach -root -offset 7 \\n\
+ hopalong -root \\n\
+ greynetic -root \\n\
+ xroger -root \\n\
+ imsmap -root \\n\
+ slidescreen -root \\n\
+ decayscreen -root \\n\
+ jigsaw -root \\n\
+ blitspin -root -grab \\n\
+ slip -root \\n\
+ distort -root \\n\
+ spotlight -root \\n\
+ \"Ripples (oily)\" ripples -root -oily -light 2 \\n\
+ \"Ripples (stir)\" ripples -root -oily -light 2 -stir \\n\
+ \"Ripples (desktop)\" ripples -root -water -light 6 \\n\
+ hypercube -root \\n\
+ halo -root \\n\
+ maze -root \\n\
+ noseguy -root \\n\
+ flame -root \\n\
+ lmorph -root \\n\
+ deco -root \\n\
+ moire -root \\n\
+ moire2 -root \\n\
+ lightning -root \\n\
+ strange -root \\n\
+ spiral -root \\n\
+ laser -root \\n\
+ grav -root \\n\
+ \"Grav (trails)\" grav -root -trail -decay \\n\
+ drift -root \\n\
+ ifs -root \\n\
+ julia -root \\n\
+ penrose -root \\n\
+ sierpinski -root \\n\
+ braid -root \\n\
+ galaxy -root \\n\
+ bouboule -root \\n\
+ swirl -root \\n\
+ flag -root \\n\
+ sphere -root \\n\
+ forest -root \\n\
+ lisa -root \\n\
+ lissie -root \\n\
+ goop -root -max-velocity 0.5 -elasticity \
+ 0.9 \\n\
+ starfish -root \\n\
+ \"Starfish (blob)\" starfish -root -blob \\n\
+ munch -root \\n\
+ fadeplot -root \\n\
+ coral -root -delay 0 \\n\
+ mountain -root \\n\
+ triangle -root -delay 1 \\n\
+ worm -root \\n\
+ rotor -root \\n\
+ ant -root \\n\
+ demon -root \\n\
+ loop -root \\n\
+ vines -root \\n\
+ kaleidescope -root \\n\
+ xjack -root \\n\
+ xlyap -root -randomize \\n\
+ cynosure -root \\n\
+ flow -root \\n\
+ epicycle -root \\n\
+ interference -root \\n\
+ truchet -root -randomize \\n\
+ bsod -root \\n\
+ crystal -root \\n\
+ discrete -root \\n\
+ kumppa -root \\n\
+ rd-bomb -root \\n\
+ \"RD-Bomb (mobile)\" rd-bomb -root -speed 1 -size 0.1 \\n\
+ sonar -root \\n\
+ t3d -root \\n\
+ penetrate -root \\n\
+ deluxe -root \\n\
+ compass -root \\n\
+ squiral -root \\n\
+ xflame -root \\n\
+ wander -root \\n\
+ \"Wander (spots)\" wander -root -advance 0 -size 10 -circles \
+ True -length 10000 -reset 100000 \\n\
+ critical -root \\n\
+ phosphor -root \\n\
+ xmatrix -root \\n\
+ petri -root -size 2 -count 20 \\n\
+ \"Petri 2\" petri -root -minlifespeed 0.02 \
+ -maxlifespeed 0.03 -minlifespan 1 \
+ -maxlifespan 1 -instantdeathchan 0 \
+ -minorchan 0 -anychan 0.3 \\n\
+ shadebobs -root \\n\
+ ccurve -root \\n\
+ blaster -root \\n\
+ bumps -root \\n\
+ xteevee -root \\n\
+ xspirograph -root \\n\
+ color: bubbles -root \\n\
+ default-n: webcollage -root \\n\
+ default-n: \"WebCollage (whacked)\" \
+ webcollage -root -filter \
+ 'vidwhacker -stdin -stdout' \\n\
+- default-n: vidwhacker -root \\n\
+ \
+ GL: gears -root \\n\
+ GL: superquadrics -root \\n\
+ GL: morph3d -root \\n\
+ GL: cage -root \\n\
+ GL: moebius -root \\n\
+ GL: stairs -root \\n\
+ GL: pipes -root \\n\
+ GL: sproingies -root \\n\
+ GL: rubik -root \\n\
+ GL: atlantis -root \\n\
+ GL: lament -root \\n\
+ GL: bubble3d -root \\n\
+ GL: glplanet -root \\n\
+ GL: pulsar -root \\n\
+- GL: \"Pulsar (textures)\" \
+ pulsar -root -texture -mipmap \
+ -texture_quality -light -fog \\n\
+ GL: extrusion -root \\n\
+ GL: sierpinski3d -root \\n\
+ GL: starwars -root \\n\
+ \
+- xdaliclock -root -builtin3 -cycle \\n\
+- default-n: xearth -nofork -nostars -ncolors 50 \
+ -night 3 -wait 0 -timewarp 400.0 -pos \
+ sunrel/38/-30 \\n\
+- ssystem -fullscreen :32 \\n\
+- xmountains -b -M -Z 0 -r 1 \\n\
+- \"XMountains (top)\" xmountains -b -M -Z 0 -r 1 -m \\n\
+- xaos -root -autopilot -incoloring -1 \
+ -nogui -outcoloring -1 \\n\
+- xfishtank -d -s \\n\
+- xsnow \\n\
+- goban -root \\n\
+- electricsheep \\n",
+"XScreenSaver.pointerPollTime: 5",
+"XScreenSaver.initialDelay: 0",
+"XScreenSaver.windowCreationTimeout: 30",
+"XScreenSaver.bourneShell: /bin/sh",
+"*Dialog.headingFont: *-times-bold-r-*-*-*-180-*-*-*-iso8859-1",
+"*Dialog.bodyFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
+"*Dialog.labelFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
+"*Dialog.buttonFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
+"*Dialog.dateFont: *-courier-medium-r-*-*-*-80-*-*-*-iso8859-1",
+"*Dialog.foreground: #000000",
+"*Dialog.background: #BFBFBF",
+"*Dialog.Button.foreground: #000000",
+"*Dialog.Button.background: #D0D0D0",
+"*Dialog.text.foreground: #000000",
+"*Dialog.text.background: #FFFFFF",
+"*Dialog.logo.foreground: #FF0000",
+"*Dialog.logo.background: #FFFFFF",
+"*Dialog.topShadowColor: #E7E7E7",
+"*Dialog.bottomShadowColor: #737373",
+"*Dialog.logo.width: 200",
+"*Dialog.logo.height: 200",
+"*Dialog.internalBorderWidth: 30",
+"*Dialog.borderWidth: 1",
+"*Dialog.shadowThickness: 4",
+"*passwd.heading.label: XScreenSaver %s",
+"*passwd.body.label: This display is locked.",
+"*passwd.user.label: User:",
+"*passwd.passwd.label: Password:",
+"*passwd.passwdFont: *-courier-medium-r-*-*-*-140-*-*-*-iso8859-1",
+"*passwd.thermometer.width: 8",
+"*splash.heading.label: XScreenSaver %s",
+"*splash.body.label: Copyright © 1991-1999 by",
+"*splash.body2.label: Jamie Zawinski <jwz@jwz.org>",
+"*splash.demo.label: Demo",
+"*splash.prefs.label: Prefs",
+"*splash.help.label: Help",
+"*fontList: *-helvetica-medium-r-*-*-*-120-*-*-*-iso8859-1",
+"*demoDialog*label1.fontList: *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1",
+"*cmdText.fontList: *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1",
+"*label0.fontList: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
+"XScreenSaver*doc.fontList: *-helvetica-medium-r-*-*-*-100-*-*-*-iso8859-1",
+"*foreground: #000000",
+"*background: #C0C0C0",
+"*XmTextField.foreground: #000000",
+"*XmTextField.background: #FFFFFF",
+"*list.foreground: #000000",
+"*list.background: #FFFFFF",
+"*ApplicationShell.title: XScreenSaver",
+"*warning.title: XScreenSaver",
+"*warning_popup.title: XScreenSaver",
+"*allowShellResize: True",
+"*autoUnmanage: False",
+"*menubar*file.labelString: File",
+"*menubar*file.mnemonic: F",
+"*file.blank.labelString: Blank Screen Now",
+"*file.blank.mnemonic: B",
+"*file.lock.labelString: Lock Screen Now",
+"*file.lock.mnemonic: L",
+"*file.kill.labelString: Kill Daemon",
+"*file.kill.mnemonic: K",
+"*file.restart.labelString: Restart Daemon",
+"*file.restart.mnemonic: R",
+"*file.exit.labelString: Exit",
+"*file.exit.mnemonic: E",
+"*menubar*edit.labelString: Edit",
+"*menubar*edit.mnemonic: E",
+"*edit.cut.labelString: Cut",
+"*edit.cut.mnemonic: u",
+"*edit.copy.labelString: Copy",
+"*edit.copy.mnemonic: C",
+"*edit.paste.labelString: Paste",
+"*edit.paste.mnemonic: P",
+"*menubar*help.labelString: Help",
+"*menubar*help.mnemonic: H",
+"*help.about.labelString: About...",
+"*help.about.mnemonic: A",
+"*help.docMenu.labelString: Documentation...",
+"*help.docMenu.mnemonic: D",
+"*demoTab.marginWidth: 10",
+"*optionsTab.marginWidth: 10",
+"*XmScrolledWindow.topOffset: 10",
+"*XmScrolledWindow.leftOffset: 10",
+"*demoTab.topOffset: 4",
+"*form1.bottomOffset: 10",
+"*form3.leftOffset: 10",
+"*form3.rightOffset: 10",
+"*frame.topOffset: 10",
+"*frame.bottomOffset: 10",
+"*enabled.topOffset: 10",
+"*visLabel.topOffset: 10",
+"*combo.topOffset: 10",
+"*form4.bottomOffset: 4",
+"*hr.bottomOffset: 4",
+"*XmComboBox.marginWidth: 0",
+"*XmComboBox.marginHeight: 0",
+"*demo.marginWidth: 30",
+"*demo.marginHeight: 4",
+"*man.marginWidth: 10",
+"*man.marginHeight: 4",
+"*down.leftOffset: 40",
+"*down.marginWidth: 4",
+"*down.marginHeight: 4",
+"*up.marginWidth: 4",
+"*up.marginHeight: 4",
+"*frame.traversalOn: False",
+"*list.automaticSelection: True",
+"*list.visibleItemCount: 20",
+"*doc.columns: 60",
+"*combo.columns: 11",
+"*demoTab.labelString: Graphics Demos",
+"*optionsTab.labelString: Screensaver Options",
+"*down.labelString: \\\\/ ",
+"*up.labelString: /\\\\ ",
+"*frameLabel.labelString: ",
+"*cmdLabel.labelString: Command Line:",
+"*cmdLabel.alignment: ALIGNMENT_BEGINNING",
+"*enabled.labelString: Enabled",
+"*visLabel.labelString: Visual:",
+"*visLabel.alignment: ALIGNMENT_END",
+"*visLabel.leftOffset: 20",
+"*demo.labelString: Demo",
+"*man.labelString: Documentation...",
+"*done.labelString: Quit",
+"*preferencesLabel.labelString: XScreenSaver Parameters",
+"*timeoutLabel.labelString: Saver Timeout",
+"*cycleLabel.labelString: Cycle Timeout",
+"*fadeSecondsLabel.labelString: Fade Duration",
+"*fadeTicksLabel.labelString: Fade Ticks",
+"*lockLabel.labelString: Lock Timeout",
+"*passwdLabel.labelString: Password Timeout",
+"*preferencesForm*XmTextField.columns: 8",
+"*verboseToggle.labelString: Verbose",
+"*cmapToggle.labelString: Install Colormap",
+"*fadeToggle.labelString: Fade Colormap",
+"*unfadeToggle.labelString: Unfade Colormap",
+"*lockToggle.labelString: Require Password",
+"*OK.marginWidth: 30",
+"*OK.marginHeight: 4",
+"*OK.leftOffset: 10",
+"*OK.bottomOffset: 10",
+"*Cancel.marginWidth: 30",
+"*Cancel.marginHeight: 4",
+"*Cancel.rightOffset: 10",
+"*Cancel.bottomOffset: 10",
+"*hacks.documentation.isInstalled: True",
+"*hacks.qix.documentation: \
+This is the swiss army chainsaw of qix programs. It bounces a series \
+of line segments around the screen, and uses variations on this basic \
+motion pattern to produce all sorts of different presentations: line \
+segments, filled polygons, overlapping translucent areas... Written \
+by Jamie Zawinski.",
+"*hacks.attraction.documentation: \
+Like qix, this uses a simple simple motion model to generate many \
+different display modes. The control points attract each other up to \
+a certain distance, and then begin to repel each other. The \
+attraction/repulsion is proportional to the distance between any two \
+particles, similar to the strong and weak nuclear forces. \
+ \\n\\n\
+One of the most interesting ways to watch this hack is simply as \
+bouncing balls, because their motions and interactions with each \
+other are so odd. Sometimes two balls will get into a tight orbit \
+around each other, to be interrupted later by a third, or by the edge \
+of the screen. It looks quite chaotic. \
+ \\n\\n\
+Written by Jamie Zawinski, based on Lisp code by John Pezaris.",
+"*hacks.pyro.documentation: \
+Pyro draws exploding fireworks. Blah blah blah. Written by Jamie \
+Zawinski.",
+"*hacks.helix.documentation: \
+This repeatedly generates spirally string-art-ish patterns. Written \
+by Jamie Zawinski.",
+"*hacks.pedal.documentation: \
+This is sort of a combination spirograph/string-art. It generates a \
+large, complex polygon, and lets the X server do the bulk of the work \
+by giving it an even/odd winding rule. Written by Dale Moore, based \
+on some ancient PDP-11 code.",
+"*hacks.rorschach.documentation: \
+This generates random inkblot patterns. The algorithm is deceptively \
+simple for how well it works; it merely walks a dot around the screen \
+randomly, and then reflects the image horizontally, vertically, or \
+both. Any deep-seated neurotic tendencies which this program reveals \
+are your own problem. Written by Jamie Zawinski.",
+"*hacks.hopalong.documentation: \
+This draws lacy fractal patterns, based on iteration in the imaginary \
+plane, from a 1986 Scientific American article. Mostly written by \
+Patrick Naughton.",
+"*hacks.greynetic.documentation: \
+This draws random colored and stippled rectangles. Written by Jamie \
+Zawinski.",
+"*hacks.xroger.documentation: \
+The XScreenSaver logo. Don't you hate it? So do I. Would you like \
+to design a new logo for XScreenSaver? If so, send jwz your \
+submissions.",
+"*hacks.imsmap.name: IMSmap",
+"*hacks.imsmap.documentation: \
+This generates random cloud-like patterns. It looks quite different \
+in monochrome and color. The basic idea is to take four points on \
+the edge of the image, and assign each a random ``elevation''. Then \
+find the point between them, and give it a value which is the average \
+of the other four, plus some small random offset. Then coloration is \
+done based on elevation. \
+ \\n\\n\
+The color selection is done by binding the elevation to either hue, \
+saturation, or brightness, and assigning random values to the others. \
+The ``brightness'' mode tends to yield cloudlike patterns, and the \
+others tend to generate images that look like heat-maps or CAT-scans. \
+Written by Juergen Nickelsen and Jamie Zawinski.",
+"*hacks.slidescreen.name: SlideScreen",
+"*hacks.slidescreen.documentation: \
+This grabs an image of whatever is on your screen, divides it into a \
+grid, and then randomly shuffles the squares around as if it was one \
+of those annoying ``16-puzzle'' games, where there is a grid of \
+squares, one of which is missing. I hate trying to solve those \
+puzzles, but watching one permute itself is more amusing. Written by \
+Jamie Zawinski.",
+"*hacks.decayscreen.name: DecayScreen",
+"*hacks.decayscreen.documentation: \
+This grabs an image of whatever is on your screen, and makes it melt. \
+You've no doubt seen this effect before, but no screensaver would \
+really be complete without it. It works best if there's something \
+colorful visible. Warning, if the effect continues after the screen \
+saver is off, seek medical attention. Written by David Wald and \
+Vivek Khera. \
+ \\n\\n\
+A number of these screenhacks have the ability to take an image of \
+your desktop and manipulate it in some way. On SGI systems, these \
+programs are able to (at random) pull their source image from the \
+system's video input instead! This works nicely if you leave some \
+some random television station plugged in.",
+"*hacks.jigsaw.documentation: \
+This grabs a screen image, carves it up into a jigsaw puzzle, \
+shuffles it, and then solves the puzzle. This works especially well \
+when you feed it an external video signal instead of letting it grab \
+the screen image (actually, I guess this is generally true...) When \
+it is grabbing a video image, it is sometimes pretty hard to guess \
+what the image is going to look like once the puzzle is solved. \
+Written by Jamie Zawinski.",
+"*hacks.blitspin.name: BlitSpin",
+"*hacks.blitspin.documentation: \
+The ``blitspin'' hack repeatedly rotates a bitmap by 90 degrees by \
+using logical operations: the bitmap is divided into quadrants, and \
+the quadrants are shifted clockwise. Then the same thing is done \
+again with progressively smaller quadrants, except that all \
+sub-quadrants of a given size are rotated in parallel. Written by \
+Jamie Zawinski based on some cool SmallTalk code seen in in Byte \
+Magazine in 1981. \
+ \\n\\n\
+As you watch it, the image appears to dissolve into static and then \
+reconstitute itself, but rotated. You can provide the image to use, \
+as an XBM or XPM file, or tell it to grab a screen image and rotate \
+that.",
+"*hacks.slip.documentation: \
+This program throws some random bits on the screen, then sucks them \
+through a jet engine and spews them out the other side. To avoid \
+turning the image completely to mush, every now and then it will and \
+then it interjects some splashes of color into the scene, or go into \
+a spin cycle, or stretch the image like taffy, or (this is my \
+addition) grab an image of your current desktop to chew on. \
+Originally written by Scott Draves; whacked on by Jamie Zawinski.",
+"*hacks.distort.documentation: \
+This hack grabs an image of the screen, and then lets a transparent \
+lens wander around the screen, magnifying whatever is underneath. \
+Written by Jonas Munsin.",
+"*hacks.spotlight.documentation: \
+Draws a spotlight scanning across a black screen, illumnating the \
+underlying desktop when it passes. Written by Rick Schultz.",
+"*hacks.hypercube.documentation: \
+This displays 2D projections of the sequence of 3D objects which are \
+the projections of the 4D analog to the cube: as a square is composed \
+of four lines, each touching two others; and a cube is composed of \
+six squares, each touching four others; a hypercube is composed of \
+eight cubes, each touching six others. To make it easier to \
+visualize the rotation, it uses a different color for the edges of \
+each face. Don't think about it too long, or your brain will melt. \
+Written by Joe Keane, Fritz Mueller, and Jamie Zawinski.",
+"*hacks.halo.documentation: \
+This draws trippy psychedelic circular patterns that hurt to look at. \
+It can also animate the control-points, but that takes a lot of CPU \
+and bandwidth. Written by Jamie Zawinski.",
+"*hacks.maze.documentation: \
+This is the ancient X maze demo, modified to work with xscreensaver. \
+It generates a random maze, then solves it with visual feedback. \
+Originally by Jim Randell; modified by a cast of thousands.",
+"*hacks.noseguy.documentation: \
+A little man with a big nose wanders around your screen saying \
+things. The things which he says can come from a file, or from an \
+external program like `zippy' or `fortune'. This was extracted from \
+`xnlock' by Dan Heller. Colorized by Jamie Zawinski.",
+"*hacks.flame.documentation: \
+Another iterative fractal generator. Written by Scott Draves.",
+"*hacks.lmorph.name: LMorph",
+"*hacks.lmorph.documentation: \
+This generates random spline-ish line drawings and morphs between \
+them. Written by Sverre H. Huseby and Glenn T. Lines.",
+"*hacks.deco.documentation: \
+This one subdivides and colors rectangles randomly. It looks kind of \
+like Brady-Bunch-era rec-room wall paneling. (Raven says: ``this \
+screensaver is ugly enough to peel paint.'') Written by Jamie \
+Zawinski, inspired by Java code by Michael Bayne.",
+"*hacks.moire.documentation: \
+This one draws cool circular interference patterns. Most of the \
+circles you see aren't explicitly rendered, but show up as a result \
+of interactions between the other pixels that were drawn. Written by \
+Jamie Zawinski, inspired by Java code by Michael Bayne. As he \
+pointed out, the beauty of this one is that the heart of the display \
+algorithm can be expressed with just a pair of loops and a handful of \
+arithmetic, giving it a high ``display hack metric''.",
+"*hacks.moire2.documentation: \
+Another example of the fun you can have with moire \
+interference patterns; this hack generates fields of concentric \
+circles or ovals, and combines the planes with various operations. \
+The planes are moving independently of one another, causing the \
+interference lines to ``spray.'' Written by Jamie Zawinski.",
+"*hacks.lightning.documentation: \
+This one draws crackling fractal lightning bolts. It's simple, \
+direct, and to the point. If only it had sound... Written by Keith \
+Romberg.",
+"*hacks.strange.documentation: \
+This draws strange attractors: it's a colorful, \
+unpredictably-animating field of dots that swoops and twists around. \
+The motion is very nice. Written by Massimino Pascal.",
+"*hacks.spiral.documentation: \
+Moving circular patterns, by Peter Schmitzberger. Moving circular \
+patterns means moire; interference patterns, of course.",
+"*hacks.laser.documentation: \
+Moving radiating lines, that look vaguely like scanning laser beams. \
+Written by Pascal Pensa. (Frankie say: relax.)",
+"*hacks.grav.documentation: \
+This program draws a simple orbital simulation. If you turn on \
+trails, it looks kind of like a cloud-chamber photograph. Written \
+by Greg Bowering.",
+"*hacks.drift.documentation: \
+How could one possibly describe this except as ``drifting recursive \
+fractal cosmic flames?'' Another fine hack from the Scott Draves \
+collection of fine hacks.",
+"*hacks.ifs.name: IFS",
+"*hacks.ifs.documentation: \
+This one draws spinning, colliding iterated-function-system images. \
+Written by Massimino Pascal.",
+"*hacks.julia.documentation: \
+This one draws spinning, animating (are you detecting a pattern here \
+yet?) explorations of the Julia set. You've probably seen static \
+images of this fractal form before, but it's a lot of fun to watch in \
+motion as well. One interesting thing is that there is a small \
+swinging dot passing in front of the image, which indicates the \
+control point from which the rest of the image was generated. \
+Written by Sean McCullough.",
+"*hacks.penrose.documentation: \
+Draws quasiperiodic tilings; think of the implications on modern \
+formica technology. Written by Timo Korvola. \
+ \\n\\n\
+In April 1997, Sir Roger Penrose, a British math professor who has \
+worked with Stephen Hawking on such topics as relativity, black \
+holes, and whether time has a beginning, filed a \
+copyright-infringement lawsuit against the Kimberly-Clark \
+Corporation, which Penrose said copied a pattern he created (a \
+pattern demonstrating that ``a nonrepeating pattern could exist in \
+nature'') for its Kleenex quilted toilet paper. Penrose said he \
+doesn't like litigation but, ``When it comes to the population of \
+Great Britain being invited by a multinational to wipe their bottoms \
+on what appears to be the work of a Knight of the Realm, then a last \
+stand must be taken.'' \
+ \\n\\n\
+As reported by News of the Weird #491, 4-jul-1997.",
+"*hacks.sierpinski.documentation: \
+This draws the two-dimensional variant of the recursive Sierpinski \
+triangle fractal. Written by Desmond Daignault.",
+"*hacks.braid.documentation: \
+Draws random color-cycling inter-braided concentric circles. Written \
+by John Neil.",
+"*hacks.galaxy.documentation: \
+This draws spinning galaxies, which then collide and scatter their \
+stars to the, uh, four winds or something. Originally an Amiga \
+program by Uli Siegmund.",
+"*hacks.bouboule.documentation: \
+This draws what looks like a spinning, deforming baloon with \
+varying-sized spots painted on its invisible surface. Written by \
+Jeremie Petit.",
+"*hacks.swirl.documentation: \
+More flowing, swirly patterns. This version is by M. Dobie and R. \
+Taylor, but you might have seen a Mac program similar to this called \
+FlowFazer. There is also a cool Java applet of a similar concept",
+"*hacks.flag.documentation: \
+This draws a waving colored flag, that undulates its way around the \
+screen. The trick is the flag can contain arbitrary text and images. \
+By default, it displays either the current system name and OS \
+type, or a picture of ``Bob,'' but you can replace the text or the \
+image with a command-line option. Written by Charles Vidal and Jamie \
+Zawinski.",
+"*hacks.sphere.documentation: \
+Another of the classic screenhacks of the distant past, this one \
+draws shaded spheres in multiple colors. This hack traces its \
+lineage back to Tom Duff in 1982.",
+"*hacks.forest.documentation: \
+This draws fractal trees. Written by Peter Baumung. Everybody loves \
+fractals, right?",
+"*hacks.lisa.documentation: \
+This draws Lisajous loops, by Caleb Cullen. Remember that device \
+they had the Phantom Zone prisoners in during their trial in \
+Superman? I think that was one of these.",
+"*hacks.lissie.documentation: \
+Another Lissajous figure. This one draws the progress of circular \
+shapes along a path. Written by Alexander Jolk.",
+"*hacks.goop.documentation: \
+This draws set of animating, transparent, amoeba-like blobs. The \
+blobs change shape as they wander around the screen, and they are \
+translucent, so you can see the lower blobs through the higher ones, \
+and when one passes over another, their colors merge. Written by \
+Jamie Zawinski. I got the idea for this from a cool mouse pad I \
+have, which achieves the same kind of effect in real life by having \
+several layers plastic with colored oil between them. Written by \
+Jamie Zawinski.",
+"*hacks.starfish.documentation: \
+This generates a sequence of undulating, throbbing, star-like \
+patterns which pulsate, rotate, and turn inside out. Another display \
+mode uses these shapes to lay down a field of colors, which are then \
+cycled. The motion is very organic. Written by Jamie Zawinski.",
+"*hacks.munch.documentation: \\n\
+ DATAI 2 \\n\
+ ADDB 1,2 \\n\
+ ROTC 2,-22 \\n\
+ XOR 1,2 \\n\
+ JRST .-4 \\n\
+ \\n\
+As reported by HAKMEM, in 1962, Jackson Wright wrote the above PDP-1 \
+code. That code still lives on in this screenhack, some 35 years \
+later. The number of lines of enclosing code has increased \
+substantially, however. This version is by Tim Showalter.",
+"*hacks.fadeplot.name: FadePlot",
+"*hacks.fadeplot.documentation: \
+Draws what looks like a waving ribbon following a sinusoidal path. \
+Written by Bas van Gaalen and Charles Vidal.",
+"*hacks.coral.documentation: \
+Simulates coral growth, albeit somewhat slowly. This image doesn't \
+really do it justice. Written by Frederick Roeber.",
+"*hacks.mountain.documentation: \
+Generates random 3d plots that look vaguely mountainous. Written by \
+Pascal Pensa.",
+"*hacks.triangle.documentation: \
+Generates random mountain ranges using iterative subdivision of \
+triangles. Written by Tobias Gloth.",
+"*hacks.worm.documentation: \
+An ancient xlock hack that draws multicolored worms that crawl around \
+the screen. Written by Brad Taylor, Dave Lemke, Boris Putanec, and \
+Henrik Theiling.",
+"*hacks.rotor.documentation: \
+Another ancient xlock demo, this one by Tom Lawrence. It draws a \
+line segment moving along a complex spiraling curve. I tweaked this \
+to generate curvier lines, but still frames of it don't look like \
+much.",
+"*hacks.ant.documentation: \
+A cellular automaton that is really a two-dimensional Turing machine: \
+as the heads (``ants'') walk along the screen, they change pixel \
+values in their path. Then, as they pass over changed pixels, their \
+behavior is influenced. Written by David Bagley.",
+"*hacks.demon.documentation: \
+A cellular automaton that starts with a random field, and organizes \
+it into stripes and spirals. Written by David Bagley.",
+"*hacks.loop.documentation: \
+This one produces loop-shaped colonies that spawn, age, and \
+eventually die. Written by David Bagley.",
+"*hacks.vines.documentation: \
+This one generates a continuous sequence of small, curvy geometric \
+patterns. It scatters them around your screen until it fills up, \
+then it clears the screen and starts over. Written by Tracy Camp and \
+David Hansen.",
+"*hacks.kaleidescope.documentation: \
+Another clone of an ancient meme, consisting largely of frenetic \
+rotational motion of colored lines. This one is by Ron Tapia. The \
+motion is nice, but I think it needs more solids, or perhaps just \
+brighter colors. More variations in the rotational speed might help, \
+too.",
+"*hacks.xjack.documentation: \
+This program behaves schizophrenically and makes a lot of typos. \
+Written by Jamie Zawinski. If you haven't seen Stanley Kubrick's \
+masterpiece, ``The Shining,'' you won't get it. Those who have \
+describe this hack as ``inspired.''",
+"*hacks.xlyap.documentation: \
+This generates pretty fractal pictures by doing funky math involving \
+the ``Lyapunov exponent.'' It has a cool interactive mode, too. \
+Written by Ron Record.",
+"*hacks.cynosure.documentation: \
+A hack similar to `greynetic', but less frenetic. The first \
+implementation was by Stephen Linhart; then Ozymandias G. Desiderata \
+wrote a Java applet clone. That clone was discovered by Jamie \
+Zawinski, and ported to C for inclusion here.",
+"*hacks.flow.documentation: \
+Another series of strange attractors: a flowing series of points, \
+making strange rotational shapes. Written by Jeff Butterworth.",
+"*hacks.epicycle.documentation: \
+This program draws the path traced out by a point on the edge of a \
+circle. That circle rotates around a point on the rim of another \
+circle, and so on, several times. These were the basis for the \
+pre-heliocentric model of planetary motion. Written by James \
+Youngman.",
+"*hacks.interference.documentation: \
+Another color-field hack, this one works by computing decaying \
+sinusoidal waves, and allowing them to interfere with each other as \
+their origins move. Written by Hannu Mallat.",
+"*hacks.truchet.documentation: \
+This draws line- and arc-based Truchet patterns that tile the screen. \
+Written by Adrian Likins.",
+"*hacks.bsod.name: BSOD",
+"*hacks.bsod.documentation: \
+BSOD stands for ``Blue Screen of Death.'' The finest in personal \
+computer emulation, this hack simulates popular screen savers from a \
+number of less robust operating systems. Written by Jamie Zawinski.",
+"*hacks.crystal.documentation: \
+Moving polygons, similar to a kaleidescope (more like a kaleidescope \
+than the hack called `kaleid,' actually.) This one by Jouk Jansen.",
+"*hacks.discrete.documentation: \
+More ``discrete map'' systems, including new variants of Hopalong and \
+Julia, and a few others. Written by Tim Auckland.",
+"*hacks.kumppa.documentation: \
+Spiraling, spinning, and very, very fast splashes of color rush \
+toward the screen. Written by Teemu Suutari.",
+"*hacks.rd-bomb.name: RD-Bomb",
+"*hacks.rd-bomb.documentation: \
+Another variation of the `Bomb' program by Scott Draves. This draws \
+a grid of growing square-like shapes that, once they overtake each \
+other, react in unpredictable ways. ``RD'' stands for \
+reaction-diffusion.",
+"*hacks.sonar.documentation: \
+This program draws a simulation of a sonar screen. Written by \
+default, it displays a random assortment of ``bogies'' on the screen, \
+but if compiled properly, it can ping (pun intended) your local \
+network, and actually plot the proximity of the other hosts on your \
+network to you. It would be easy to make it monitor other sources of \
+data, too. (Processes? Active network connections? CPU usage per \
+user?) Written by Stephen Martin.",
+"*hacks.t3d.name: T3D",
+"*hacks.t3d.documentation: \
+This draws a working analog clock composed of floating, throbbing \
+bubbles. Written by Bernd Paysan.",
+"*hacks.penetrate.documentation: \
+This hack simulates the classic arcade game Missile Command. Written \
+by Adam Miller.",
+"*hacks.deluxe.documentation: \
+This draws a pulsing sequence of stars, circles, and lines. It would \
+look better if it was faster, but as far as I can tell, there is no \
+way to make this be both: fast, and flicker-free. Yet another reason \
+X sucks. Written by Jamie Zawinski.",
+"*hacks.compass.documentation: \
+This draws a compass, with all elements spinning about randomly, for \
+that ``lost and nauseous'' feeling. Written by Jamie Zawinski.",
+"*hacks.squiral.documentation: \
+Draws a set of interacting, square-spiral-producing automata. The \
+spirals grow outward until they hit something, then they go around \
+it. Written by Jeff Epler.",
+"*hacks.xflame.documentation: \
+Draws a simulation of pulsing fire. It can also take an arbitrary \
+image and set it on fire too. Written by Carsten Haitzler, hacked on \
+by many others.",
+"*hacks.wander.documentation: \
+Draws a colorful random-walk, in various forms. Written by Rick \
+Campbell.",
+"*hacks.critical.documentation: \
+Draws a system of self-organizing lines. It starts out as random \
+squiggles, but after a few iterations, order begins to appear. \
+Written by Martin Pool.",
+"*hacks.phosphor.documentation: \
+Draws a simulation of an old terminal, with large pixels and \
+long-sustain phosphor. It can run any program as a source of the text \
+it displays. Written by Jamie Zawinski.",
+"*hacks.xmatrix.documentation: \
+A rendition of the text scrolls seen in the movie ``The Matrix.'' \
+Written by Jamie Zawinski.",
+"*hacks.petri.documentation: \
+This simulates colonies of mold growing in a petri dish. Growing \
+colored circles overlap and leave spiral interference in their wake. \
+Written by Dan Bornstein.",
+"*hacks.shadebobs.name: ShadeBobs",
+"*hacks.shadebobs.documentation: \
+This draws smoothly-shaded oscilating oval patterns, that look \
+something like vapor trails or neon tubes. Written by Shane Smit.",
+"*hacks.ccurve.name: C Curve",
+"*hacks.ccurve.documentation: \
+Generates self-similar linear fractals, including the classic ``C \
+Curve.'' Written by Rick Campbell.",
+"*hacks.blaster.documentation: \
+Draws a simulation of flying space-combat robots (cleverly disguised \
+as colored circles) doing battle in front of a moving star field. \
+Written by Jonathan Lin.",
+"*hacks.bumps.documentation: \
+A bit like `Spotlight', except that instead of merely exposing part \
+of your desktop, it creates a bump map from it. Basically, it \
+3D-izes a roaming section of your desktop, based on color intensity. \
+Written by Shane Smit.",
+"*hacks.xteevee.name: XTeeVee",
+"*hacks.xteevee.documentation: \
+XTeeVee simulates various television problems, including static, \
+loss of vertical hold, and a test pattern. By Greg Knauss.",
+"*hacks.xspirograph.name: XSpiroGraph",
+"*hacks.xspirograph.documentation: \
+Simulates that pen-in-nested-plastic-gears toy from your childhood. \
+By Rohit Singh.",
+"*hacks.webcollage.name: WebCollage",
+"*hacks.webcollage.documentation: \
+This program makes collages out of random images pulled off of the \
+World Wide Web. It finds these images by doing random web searches, \
+and then extracting images from the returned pages. It can also be \
+set up to filter the images through the `VidWhacker' program, above, \
+which looks really great. \
+ \\n\\n\
+(Note that most of the images it finds are text, and not pictures. \
+This is because most of the web is pictures of text. Which is pretty \
+sad.) Written by Jamie Zawinski.",
+"*hacks.vidwhacker.name: VidWhacker",
+"*hacks.vidwhacker.documentation: \
+This is actually just a shell script that grabs a frame of video from \
+the system's video input, and then uses some PBM filters (chosen at \
+random) to manipulate and recombine the video frame in various ways \
+(edge detection, subtracting the image from a rotated version of \
+itself, etc.) Then it displays that image for a few seconds, and \
+does it again. This works really well if you just feed broadcast \
+television into it. \
+ \\n\\n\
+Currently, the three lines of the script that actually grab the \
+source picture are SGI specific, but it should be trivial to adapt it \
+to work on other systems that can grab video (please send me the \
+changes if you do this...)",
+"*hacks.rocks.documentation: \
+This draws an animation of flight through an asteroid field, with \
+changes in rotation and direction. It can also display 3D \
+separations for red/blue glasses! Mostly written by Jamie Zawinski.",
+"*hacks.bubbles.documentation: \
+This simulates the kind of bubble formation that happens when water \
+boils:small bubbles appear, and as they get closer to each other, \
+they combine to form larger bubbles, which eventually pop. Written \
+by James Macnicol.",
+"*hacks.gears.documentation: \
+This draws a set of turning, interlocking gears, rotating in three \
+dimensions. Another GL hack, by Danny Sung, Brian Paul, and Ed \
+Mackey.",
+"*hacks.superquadrics.documentation: \
+Ed Mackey reports that he wrote the first version of this program in \
+BASIC on a Commodore 64 in 1987, as a 320x200 black and white \
+wireframe. Now it is GL and has specular reflections.",
+"*hacks.morph3d.name: Morph3D",
+"*hacks.morph3d.documentation: \
+Another 3d shape-changing GL hack, by Marcelo Vianna. It has the \
+same shiny-plastic feel as Superquadrics, as many computer-generated \
+objects do...",
+"*hacks.cage.documentation: \
+This draws Escher's ``Impossible Cage,'' a 3d analog of a moebius \
+strip, and rotates it in three dimensions. Written by Marcelo \
+Vianna.",
+"*hacks.moebius.documentation: \
+Another M. C. Escher hack by Marcelo Vianna, this one draws \
+``Moebius Strip II,'' a GL image of ants walking along the surface of \
+a moebius strip.",
+"*hacks.stairs.documentation: \
+by Marcelo Vianna's third Escher GL hack, this one draws an \
+``infinite'' staircase.",
+"*hacks.pipes.documentation: \
+If you've ever been in the same room with a Windows NT machine, \
+you've probably seen this GL hack. This version is by Marcelo \
+Vianna.",
+"*hacks.sproingies.documentation: \
+Q-Bert meets Marble Madness! Written by Ed Mackey.",
+"*hacks.rubik.documentation: \
+Draws a Rubik's Cube that rotates in three dimensions and repeatedly \
+shuffles and solves itself. Another fine GL hack by Marcelo Vianna.",
+"*hacks.atlantis.documentation: \
+This is xfishtank writ large: a GL animation of a number of sharks, \
+dolphins, and whales. The swimming motions are great. Originally \
+written by Mark Kilgard.",
+"*hacks.lament.documentation: \
+Animates a simulation of Lemarchand's Box, repeatedly solving itself. \
+Requires OpenGL, and a machine with fast hardware support for texture \
+maps. Warning: occasionally opens doors. Written by Jamie Zawinski.",
+"*hacks.bubble3d.name: Bubble3D",
+"*hacks.bubble3d.documentation: \
+Draws a stream of rising, undulating 3D bubbles, rising toward the \
+top of the screen, with nice specular reflections. Written by Richard \
+Jones.",
+"*hacks.glplanet.name: GLPlanet",
+"*hacks.glplanet.documentation: \
+Draws a planet bouncing around in space. Written by David Konerding. \
+The built-in image is a map of the earth (extracted from `xearth'), \
+but you can wrap any texture around the sphere, e.g., the planetary \
+textures that come with `ssystem'.",
+"*hacks.pulsar.documentation: \
+Draws some intersecting planes, making use of alpha blending, fog, \
+textures, and mipmaps, plus a ``frames per second'' meter so that you \
+can tell how fast your graphics card is... Requires OpenGL. Written \
+by David Konerding.",
+"*hacks.extrusion.documentation: \
+Draws various rotating extruded shapes that twist around, lengthen, \
+and turn inside out. Created by David Konerding from the samples \
+that come with the GL Extrusion library by Linas Vepstas.",
+"*hacks.sierpinski3d.name: Sierpinski3D",
+"*hacks.sierpinski3d.documentation: \
+This draws the three-dimensional variant of the recursive Sierpinski \
+triangle fractal, using GL. Written by Tim Robinson and Jamie Zawinski.",
+"*hacks.ripples.documentation: \
+This draws rippling interference patterns like splashing water. \
+With the -water option, it manipulates your desktop image to look \
+like something is dripping into it. Written by Tom Hammersley.",
+"*hacks.xdaliclock.name: XDaliClock",
+"*hacks.xdaliclock.documentation: \
+XDaliClock draws a large digital clock, the numbers of which change by \
+``melting'' into their new shapes. Written by Jamie Zawinski. This \
+is not included with the XScreenSaver package, but if you don't have \
+it already, you can find it at <http://www.jwz.org/xdaliclock/>.",
+"*hacks.xearth.documentation: \
+XEarth draws an image of the Earth, as seen from your favorite vantage \
+point in space, correctly shaded for the current position of the Sun. \
+Written by Kirk Johnson. This is not included with the XScreenSaver \
+package, but if you don't have it already, you can find it at \
+<http://www.cs.colorado.edu/~tuna/xearth/>.",
+"*hacks.ssystem.name: SSystem",
+"*hacks.ssystem.documentation: \
+SSystem is a GL Solar System simulator. It simulates flybys of Sun, \
+the nine planets and a few major satellites, with four camera modes. \
+Written by Raul Alonso. This is not included with the XScreenSaver \
+package, but if you don't have it already, you can find it at \
+<http://www1.las.es/~amil/ssystem/>.",
+"*hacks.xmountains.documentation: \
+XMountains generates realistic-looking fractal terrains of snow-capped \
+mountains near water, with either a top view or a side view. \
+Written by Stephen Booth. This is not included with the XScreenSaver \
+package, but if you don't have it already, you can find it at \
+<http://www.epcc.ed.ac.uk/~spb/xmountains/>. \
+ \\n\\n\
+Be sure to compile it with -DVROOT or it won't work right when launched \
+by the xscreensaver daemon.",
+"*hacks.xaos.name: XaoS",
+"*hacks.xaos.documentation: \
+XaoS generates fast fly-through animations of the Mandelbrot and other \
+fractal sets. Written by Thomas Marsh and Jan Hubicka. This is not \
+included with the XScreenSaver package, but if you don't have it \
+already, you can find it at <http://limax.paru.cas.cz/~hubicka/XaoS/>.",
+"*hacks.xfishtank.name: XFishTank",
+"*hacks.xfishtank.documentation: \
+Fish! This is not included with the XScreenSaver package, but if you \
+don't have it already, you can find it at \
+<http://metalab.unc.edu/pub/Linux/X11/demos/>.",
+"*hacks.xsnow.documentation: \
+Draws falling snow and the occasional tiny Santa. By Rick Jansen. \
+You can find it at <http://zoutmijn.bpa.nl/rick/Xsnow/>.",
+"*hacks.goban.documentation: \
+Replays historical games of go (aka wei-chi and baduk) on the screen. \
+By Scott Draves. You can find it at <http://www.draves.org/goban/>.",
+"*hacks.electricsheep.name: ElectricSheep",
+"*hacks.electricsheep.documentation: \
+ElectricSheep is an xscreensaver module that displays mpeg video of \
+an animated fractal flame. In the background, it contributes render \
+cycles to the next animation. Periodically it uploades completed \
+frames to the server, where they are compressed for distribution to \
+all clients. \
+ \\n\\n\
+This program is recommended only if you have a high bandwidth \
+connection to the Internet. \
+ \\n\\n\
+By Scott Draves. You can find it at <http://www.electricsheep.org/>. \
+See that web site for configuration information.",
diff --git a/capplets/screensaver/checked-disabled.xpm b/capplets/screensaver/checked-disabled.xpm
new file mode 100644
index 000000000..a0ac44b2d
--- /dev/null
+++ b/capplets/screensaver/checked-disabled.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * checked_disabled_xpm[] = {
+"16 16 3 2",
+" g None",
+". g #000000",
+"+ g #D9D9D9",
+" ",
+" ",
+" . . . . . . . . . . . . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + . + . ",
+" . + + + + + + + . . + . ",
+" . + + + + + + . . . + . ",
+" . + . + + + . . . + + . ",
+" . + . . + . . . + + + . ",
+" . + . . . . . + + + + . ",
+" . + + . . . + + + + + . ",
+" . + + + . + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . . . . . . . . . . . . ",
+" ",
+" "};
diff --git a/capplets/screensaver/checked.xpm b/capplets/screensaver/checked.xpm
new file mode 100644
index 000000000..d5010b24a
--- /dev/null
+++ b/capplets/screensaver/checked.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * checked_xpm[] = {
+"16 16 3 2",
+" g None",
+". g #000000",
+"+ g #FFFFFF",
+" ",
+" ",
+" . . . . . . . . . . . . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + . + . ",
+" . + + + + + + + . . + . ",
+" . + + + + + + . . . + . ",
+" . + . + + + . . . + + . ",
+" . + . . + . . . + + + . ",
+" . + . . . . . + + + + . ",
+" . + + . . . + + + + + . ",
+" . + + + . + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . . . . . . . . . . . . ",
+" ",
+" "};
diff --git a/capplets/screensaver/daemon.c b/capplets/screensaver/daemon.c
new file mode 100644
index 000000000..7555216be
--- /dev/null
+++ b/capplets/screensaver/daemon.c
@@ -0,0 +1,77 @@
+/* -*- mode: c; style: linux -*- */
+
+/* daemon.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen (hovinen@helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <gnome.h>
+
+#include "daemon.h"
+
+void
+start_xscreensaver (void)
+{
+ gnome_execute_shell (".", "xscreensaver -no-splash &");
+}
+
+void
+stop_xscreensaver (void)
+{
+ gnome_execute_shell (".", "xscreensaver-command -exit");
+}
+
+void
+restart_xscreensaver (void)
+{
+ gnome_execute_shell (".", "xscreensaver-command -restart &");
+}
+
+void
+setup_dpms (Preferences *prefs)
+{
+ char *command_line;
+ guint standby_time, suspend_time, power_down_time;
+
+ if (!prefs->power_management) return;
+
+ standby_time = prefs->standby_time ?
+ (prefs->timeout + prefs->standby_time) * 60 : 0;
+ suspend_time = prefs->suspend_time ?
+ (prefs->timeout + prefs->suspend_time) * 60 : 0;
+ power_down_time = prefs->power_down_time ?
+ (prefs->timeout + prefs->power_down_time) * 60 : 0;
+
+ /* Sanitize values */
+ if (standby_time > suspend_time) standby_time = 0;
+ if (standby_time > power_down_time) standby_time = 0;
+ if (suspend_time > power_down_time) suspend_time = 0;
+
+ command_line = g_strdup_printf ("xset dpms %u %u %u",
+ standby_time,
+ suspend_time,
+ power_down_time);
+ gnome_execute_shell (".", command_line);
+ g_free (command_line);
+}
diff --git a/capplets/screensaver/daemon.h b/capplets/screensaver/daemon.h
new file mode 100644
index 000000000..2b95b4003
--- /dev/null
+++ b/capplets/screensaver/daemon.h
@@ -0,0 +1,34 @@
+/* -*- mode: c; style: linux -*- */
+
+/* daemon.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen (hovinen@helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __DAEMON_H
+#define __DAEMON_H
+
+#include "preferences.h"
+
+void start_xscreensaver (void);
+void stop_xscreensaver (void);
+void restart_xscreensaver (void);
+void setup_dpms (Preferences *prefs);
+
+#endif /* __DAEMON_H */
diff --git a/capplets/screensaver/expr.c b/capplets/screensaver/expr.c
new file mode 100644
index 000000000..45046a803
--- /dev/null
+++ b/capplets/screensaver/expr.c
@@ -0,0 +1,259 @@
+/* -*- mode: c; style: linux -*- */
+
+/* expr.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen (hovinen@helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "expr.h"
+
+static gdouble int_parse_sentence (GScanner *scanner);
+static gdouble int_parse_unary (GScanner *scanner);
+static gdouble int_parse_atom (GScanner *scanner);
+static gdouble int_parse_expr (GScanner *scanner, gboolean expr,
+ gboolean neg);
+static gdouble int_parse_term (GScanner *scanner, gboolean expr,
+ gboolean inv);
+static gdouble int_parse_factor (GScanner *scanner, gboolean expr);
+
+gboolean
+parse_sentence (gchar *sentence, GScanner *scanner)
+{
+ g_scanner_input_text (scanner, sentence, strlen (sentence));
+ g_scanner_get_next_token (scanner);
+ return int_parse_sentence (scanner) != 0.0;
+}
+
+gdouble
+parse_expr (gchar *expr, gdouble var)
+{
+ static GScannerConfig config;
+ GScanner *scanner;
+ gchar *var_string;
+ gfloat ret;
+
+ config.cset_skip_characters = " \t\n";
+ config.cset_identifier_first = "abcdefghijklmnopqrstuvwxyz";
+ config.cset_identifier_nth = "abcdefghijklmnopqrstuvwxyz_";
+ config.scan_symbols = TRUE;
+ config.scan_identifier = TRUE;
+
+ scanner = g_scanner_new (&config);
+ g_scanner_input_text (scanner, expr, strlen (expr));
+ g_scanner_get_next_token (scanner);
+ g_scanner_set_scope (scanner, 0);
+ var_string = g_strdup_printf ("%f", var);
+ g_scanner_scope_add_symbol (scanner, 0, "var", var_string);
+
+ ret = int_parse_expr (scanner, TRUE, FALSE);
+
+ g_free (var_string);
+ g_scanner_destroy (scanner);
+ return ret;
+}
+
+static gdouble
+int_parse_sentence (GScanner *scanner)
+{
+ GTokenType token_type;
+ GTokenValue value;
+ gdouble left;
+
+ left = int_parse_unary (scanner);
+
+ token_type = g_scanner_cur_token (scanner);
+ value = g_scanner_cur_value (scanner);
+
+ if ((token_type == G_TOKEN_CHAR && value.v_char == '&') ||
+ (token_type == G_TOKEN_SYMBOL && value.v_symbol == SYMBOL_AND))
+ {
+ g_scanner_get_next_token (scanner);
+ return (int_parse_sentence (scanner) != 0.0 &&
+ left != 0.0) ? 1.0 : 0.0;
+ }
+ else if ((token_type == G_TOKEN_CHAR && value.v_char == '|') ||
+ (token_type == G_TOKEN_SYMBOL &&
+ value.v_symbol == SYMBOL_OR))
+ {
+ g_scanner_get_next_token (scanner);
+ return (int_parse_sentence (scanner) != 0.0 ||
+ left != 0.0) ? 1.0 : 0.0;
+ }
+
+ return left;
+}
+
+static gdouble
+int_parse_unary (GScanner *scanner)
+{
+ GTokenType token_type;
+ GTokenValue value;
+
+ token_type = g_scanner_cur_token (scanner);
+ value = g_scanner_cur_value (scanner);
+
+ if ((token_type == G_TOKEN_CHAR && value.v_char == '!') ||
+ (token_type == G_TOKEN_SYMBOL && value.v_symbol == SYMBOL_NOT))
+ {
+ g_scanner_get_next_token (scanner);
+ return (int_parse_unary (scanner) != 0.0) ? 0.0 : 1.0;
+ } else {
+ return (int_parse_atom (scanner) != 0.0) ? 1.0 : 0.0;
+ }
+}
+
+static gdouble
+int_parse_atom (GScanner *scanner)
+{
+ GTokenType token_type;
+ GTokenValue value;
+ gdouble left;
+
+ left = int_parse_expr (scanner, FALSE, FALSE);
+
+ token_type = g_scanner_cur_token (scanner);
+
+ if (token_type == G_TOKEN_CHAR) {
+ value = g_scanner_cur_value (scanner);
+ if (value.v_char == '=') {
+ g_scanner_get_next_token (scanner);
+ return (int_parse_expr (scanner, FALSE, FALSE)
+ == left) ? 1.0 : 0.0;
+ }
+ else if (value.v_char == '<') {
+ g_scanner_get_next_token (scanner);
+ return (int_parse_expr (scanner, FALSE, FALSE)
+ > left) ? 1.0 : 0.0;
+ }
+ else if (value.v_char == '>') {
+ g_scanner_get_next_token (scanner);
+ return (int_parse_expr (scanner, FALSE, FALSE)
+ < left) ? 1.0 : 0.0;
+ }
+ }
+
+ return left;
+}
+
+static gdouble
+int_parse_expr (GScanner *scanner, gboolean expr, gboolean neg)
+{
+ GTokenType token_type;
+ GTokenValue value;
+ gdouble left;
+ gdouble ret;
+
+ left = int_parse_term (scanner, expr, FALSE);
+
+ token_type = g_scanner_cur_token (scanner);
+
+ if (token_type == G_TOKEN_CHAR) {
+ value = g_scanner_cur_value (scanner);
+ if (value.v_char == '+') {
+ g_scanner_get_next_token (scanner);
+ return left + int_parse_expr (scanner, expr, FALSE);
+ }
+ else if (value.v_char == '-') {
+ g_scanner_get_next_token (scanner);
+ ret = int_parse_expr (scanner, expr, TRUE);
+ if (neg)
+ return left + ret;
+ else
+ return left - ret;
+ }
+ }
+
+ return left;
+}
+
+static gdouble
+int_parse_term (GScanner *scanner, gboolean expr, gboolean inv)
+{
+ GTokenType token_type;
+ GTokenValue value;
+ gdouble left;
+ gdouble ret;
+
+ left = int_parse_factor (scanner, expr);
+
+ token_type = g_scanner_cur_token (scanner);
+
+ if (token_type == G_TOKEN_CHAR) {
+ value = g_scanner_cur_value (scanner);
+ if (token_type == '*') {
+ g_scanner_get_next_token (scanner);
+ return left * int_parse_term (scanner, expr, FALSE);
+ }
+ else if (token_type == '/') {
+ g_scanner_get_next_token (scanner);
+ ret = int_parse_term (scanner, expr, TRUE);
+ if (inv)
+ return left * ret;
+ else
+ return left / ret;
+ }
+ }
+
+ return left;
+}
+
+static gdouble
+int_parse_factor (GScanner *scanner, gboolean expr)
+{
+ GTokenType token_type;
+ GTokenValue value;
+ gdouble ret;
+
+ token_type = g_scanner_cur_token (scanner);
+ value = g_scanner_cur_value (scanner);
+ g_scanner_get_next_token (scanner);
+
+ if (token_type == G_TOKEN_CHAR && value.v_char == '(') {
+ if (expr)
+ ret = int_parse_expr (scanner, TRUE, FALSE);
+ else
+ ret = int_parse_sentence (scanner);
+
+ g_scanner_get_next_token (scanner);
+ return ret;
+ }
+ else if (token_type == G_TOKEN_INT) {
+ return value.v_int;
+ }
+ else if (token_type == G_TOKEN_FLOAT) {
+ return value.v_float;
+ }
+ else if (token_type == G_TOKEN_SYMBOL) {
+ if (value.v_symbol == (gpointer) 1)
+ return (gint) value.v_symbol;
+ else
+ return g_strtod (value.v_symbol, NULL);
+ }
+ else if (token_type == G_TOKEN_IDENTIFIER) {
+ return 0.0;
+ } else {
+ g_scanner_error (scanner, "Parse error in expression");
+ }
+
+ return 0;
+}
diff --git a/capplets/screensaver/expr.h b/capplets/screensaver/expr.h
new file mode 100644
index 000000000..b634c76ec
--- /dev/null
+++ b/capplets/screensaver/expr.h
@@ -0,0 +1,36 @@
+/* -*- mode: c; style: linux -*- */
+
+/* expr.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen (hovinen@helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __EXPR_H
+#define __EXPR_H
+
+#include <glib.h>
+
+#define SYMBOL_AND ((gpointer) -1)
+#define SYMBOL_OR ((gpointer) -2)
+#define SYMBOL_NOT ((gpointer) -3)
+
+gboolean parse_sentence (gchar *sentence, GScanner *scanner);
+gdouble parse_expr (gchar *expr, gdouble var);
+
+#endif /* __EXPR_H */
diff --git a/capplets/screensaver/main.c b/capplets/screensaver/main.c
new file mode 100644
index 000000000..a0d47fb4b
--- /dev/null
+++ b/capplets/screensaver/main.c
@@ -0,0 +1,248 @@
+/* -*- mode: c; style: linux -*- */
+
+/* main.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen (hovinen@helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <gnome.h>
+#include <libgnomeui/gnome-window-icon.h>
+
+#include <glade/glade.h>
+
+#include <capplet-widget.h>
+
+#include "preferences.h"
+#include "prefs-widget.h"
+#include "preview.h"
+#include "daemon.h"
+#include "resources.h"
+
+static Preferences *prefs;
+static Preferences *old_prefs;
+static PrefsWidget *prefs_widget;
+
+static CappletWidget *capplet;
+
+static void
+state_changed_cb (GtkWidget *widget)
+{
+ if (!prefs->frozen)
+ capplet_widget_state_changed (capplet, TRUE);
+}
+
+static void
+try_cb (GtkWidget *widget)
+{
+ gboolean old_sm;
+
+ old_sm = prefs->selection_mode;
+
+ prefs_widget_store_prefs (prefs_widget, prefs);
+ preferences_save (prefs);
+ setup_dpms (prefs);
+
+ if (old_sm == SM_DISABLE_SCREENSAVER &&
+ prefs->selection_mode != SM_DISABLE_SCREENSAVER)
+ start_xscreensaver ();
+ else if (old_sm != SM_DISABLE_SCREENSAVER &&
+ prefs->selection_mode == SM_DISABLE_SCREENSAVER)
+ stop_xscreensaver ();
+}
+
+static void
+revert_cb (GtkWidget *widget)
+{
+ gboolean old_sm;
+
+ old_sm = old_prefs->selection_mode;
+
+ preferences_save (old_prefs);
+ preferences_destroy (prefs);
+ prefs = preferences_new ();
+ preferences_load (prefs);
+
+ prefs->frozen = TRUE;
+ prefs_widget_get_prefs (prefs_widget, prefs);
+ prefs->frozen = FALSE;
+
+ setup_dpms (old_prefs);
+
+ if (old_sm == SM_DISABLE_SCREENSAVER &&
+ prefs->selection_mode != SM_DISABLE_SCREENSAVER)
+ start_xscreensaver ();
+ else if (old_sm != SM_DISABLE_SCREENSAVER &&
+ prefs->selection_mode == SM_DISABLE_SCREENSAVER)
+ stop_xscreensaver ();
+}
+
+static void
+ok_cb (GtkWidget *widget)
+{
+ gboolean old_sm;
+
+ old_sm = prefs->selection_mode;
+
+ close_preview ();
+
+ prefs_widget_store_prefs (prefs_widget, prefs);
+ preferences_save (prefs);
+ setup_dpms (prefs);
+
+ if (old_sm == SM_DISABLE_SCREENSAVER &&
+ prefs->selection_mode != SM_DISABLE_SCREENSAVER)
+ start_xscreensaver ();
+ else if (old_sm != SM_DISABLE_SCREENSAVER &&
+ prefs->selection_mode == SM_DISABLE_SCREENSAVER)
+ stop_xscreensaver ();
+}
+
+static void
+cancel_cb (GtkWidget *widget)
+{
+ gboolean old_sm;
+
+ old_sm = old_prefs->selection_mode;
+
+ close_preview ();
+
+ preferences_save (old_prefs);
+ setup_dpms (old_prefs);
+
+ if (old_sm == SM_DISABLE_SCREENSAVER &&
+ prefs->selection_mode != SM_DISABLE_SCREENSAVER)
+ start_xscreensaver ();
+ else if (old_sm != SM_DISABLE_SCREENSAVER &&
+ prefs->selection_mode == SM_DISABLE_SCREENSAVER)
+ stop_xscreensaver ();
+}
+
+static void
+demo_cb (GtkWidget *widget)
+{
+ prefs->screensavers = prefs_widget->screensavers;
+ preferences_save (prefs);
+}
+
+static void
+setup_capplet_widget (void)
+{
+ capplet = CAPPLET_WIDGET (capplet_widget_new ());
+
+ gtk_signal_connect (GTK_OBJECT (capplet), "try",
+ GTK_SIGNAL_FUNC (try_cb), NULL);
+ gtk_signal_connect (GTK_OBJECT (capplet), "revert",
+ GTK_SIGNAL_FUNC (revert_cb), NULL);
+ gtk_signal_connect (GTK_OBJECT (capplet), "ok",
+ GTK_SIGNAL_FUNC (ok_cb), NULL);
+ gtk_signal_connect (GTK_OBJECT (capplet), "cancel",
+ GTK_SIGNAL_FUNC (cancel_cb), NULL);
+
+ prefs->frozen = TRUE;
+
+ prefs_widget = PREFS_WIDGET (prefs_widget_new ());
+
+ gtk_container_add (GTK_CONTAINER (capplet), GTK_WIDGET (prefs_widget));
+
+ set_preview_window (PREFS_WIDGET (prefs_widget)->preview_window);
+
+ prefs_widget_get_prefs (prefs_widget, prefs);
+
+ gtk_signal_connect (GTK_OBJECT (prefs_widget), "pref-changed",
+ GTK_SIGNAL_FUNC (state_changed_cb), NULL);
+ gtk_signal_connect (GTK_OBJECT (prefs_widget), "activate-demo",
+ GTK_SIGNAL_FUNC (demo_cb), NULL);
+
+ gtk_widget_show_all (GTK_WIDGET (capplet));
+
+ prefs->frozen = FALSE;
+}
+
+int
+main (int argc, char **argv)
+{
+ GnomeClient *client;
+ GnomeClientFlags flags;
+ gint token, res;
+ gchar *restart_args[3];
+
+ bindtextdomain (PACKAGE, GNOMELOCALEDIR);
+ textdomain (PACKAGE);
+
+ glade_gnome_init ();
+
+ res = gnome_capplet_init ("screensaver-properties",
+ VERSION, argc, argv, NULL,
+ 0, NULL);
+
+ if (res < 0) {
+ g_error ("Could not initialize the capplet.");
+ }
+
+ client = gnome_master_client ();
+ flags = gnome_client_get_flags (client);
+
+ if (flags & GNOME_CLIENT_IS_CONNECTED) {
+ token = gnome_startup_acquire_token
+ ("GNOME_SCREENSAVER_PROPERTIES",
+ gnome_client_get_id (client));
+
+ if (token) {
+ gnome_client_set_priority (client, 20);
+ gnome_client_set_restart_style (client,
+ GNOME_RESTART_ANYWAY);
+ restart_args[0] = argv[0];
+ restart_args[1] = "--init-session-settings";
+ restart_args[2] = NULL;
+ gnome_client_set_restart_command (client, 2,
+ restart_args);
+ } else {
+ gnome_client_set_restart_style (client,
+ GNOME_RESTART_NEVER);
+ }
+ } else {
+ token = 1;
+ }
+
+ gnome_window_icon_set_default_from_file
+ (GNOME_ICONDIR"/gnome-ccscreensaver.png");
+
+ init_resource_database (argc, argv);
+ prefs = preferences_new (); preferences_load (prefs);
+
+ if (token) {
+ if (prefs->selection_mode != SM_DISABLE_SCREENSAVER)
+ start_xscreensaver ();
+ setup_dpms (prefs);
+ }
+
+ if (!res) {
+ old_prefs = preferences_new (); preferences_load (old_prefs);
+ setup_capplet_widget ();
+
+ capplet_gtk_main ();
+ }
+
+ return 0;
+}
diff --git a/capplets/screensaver/no-hack.png b/capplets/screensaver/no-hack.png
new file mode 100644
index 000000000..affb745f0
--- /dev/null
+++ b/capplets/screensaver/no-hack.png
Binary files differ
diff --git a/capplets/screensaver/pref-file.c b/capplets/screensaver/pref-file.c
new file mode 100644
index 000000000..991f4e0bd
--- /dev/null
+++ b/capplets/screensaver/pref-file.c
@@ -0,0 +1,538 @@
+/* -*- mode: c; style: linux -*- */
+
+/* pref-file.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ * Parts written by Jamie Zawinski <jwz@jwz.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+#include <gnome.h>
+
+#include "pref-file.h"
+#include "rc-parse.h"
+
+#define START_BUF_SIZE 1024
+#define MIN_FREE_BUF 128
+
+/* From xscreensaver 3.24 driver/prefs.c line 80 ... */
+
+static char *
+chase_symlinks (const char *file)
+{
+# ifdef HAVE_REALPATH
+ char buf[2048], *msg;
+
+ if (file) {
+ if (realpath (file, buf))
+ return g_strdup (buf);
+
+ msg = g_strdup_printf ("realpath: %s", g_strerror (errno));
+ g_warning (msg);
+ }
+# endif /* HAVE_REALPATH */
+
+ return 0;
+}
+
+static const char *
+init_file_name (void)
+{
+ static char *file = 0;
+
+ if (!file)
+ file = g_concat_dir_and_file (g_get_home_dir (),
+ ".xscreensaver");
+
+ if (file && *file)
+ return file;
+ else
+ return NULL;
+}
+
+static const char *
+init_file_tmp_name (void)
+{
+ static char *file = 0;
+ if (!file)
+ {
+ const char *name = init_file_name();
+ const char *suffix = ".tmp";
+
+ char *n2 = chase_symlinks (name);
+ if (n2) name = n2;
+
+ if (!name || !*name)
+ file = "";
+ else
+ file = g_strconcat (name, suffix, NULL);
+
+ if (n2) g_free (n2);
+ }
+
+ if (file && *file)
+ return file;
+ else
+ return 0;
+}
+
+/* From xscreensaver 3.24 driver/prefs.c line 211 ... */
+
+static char *
+get_line (FILE *file, int *line_no)
+{
+ char *buf, *start;
+ int buf_size = START_BUF_SIZE, free_buf = START_BUF_SIZE;
+ int len, l;
+
+ buf = start = g_new (char, buf_size);
+
+ (*line_no)++;
+
+ if (!fgets (start, buf_size, file)) {
+ g_free (start);
+ return NULL;
+ }
+
+ len = strlen (start);
+
+ while (buf[len-1] != '\n' || buf[len-2] == '\\') {
+ free_buf -= len;
+ buf += len;
+
+ if (free_buf < MIN_FREE_BUF) {
+ free_buf += buf_size;
+ buf_size *= 2;
+ l = buf - start;
+ start = g_renew (char, start, buf_size);
+ buf = start + l;
+ }
+
+ if (buf[-2] == '\\') (*line_no)++;
+
+ if (!fgets (buf, free_buf - 1, file))
+ return start;
+
+ len = strlen (buf);
+ }
+
+ return start;
+}
+
+static char *
+transform_line (char *line)
+{
+ char *line1;
+ int i, i1 = 0, len;
+
+ len = strlen (line);
+ line1 = g_new (char, len + 1);
+
+ for (i = 0; i <= len; i++) {
+ if (line[i] != '\\') {
+ line1[i1++] = line[i];
+ } else {
+ i++;
+ switch (line[i]) {
+ case 'n':
+ line1[i1++] = '\n';
+ break;
+ case 'r':
+ line1[i1++] = '\r';
+ break;
+ case 't':
+ line1[i1++] = '\t';
+ break;
+ case '\\':
+ line1[i1++] = '\\';
+ break;
+ case '\n':
+ break;
+ default:
+ line1[i1++] = line[i];
+ break;
+ }
+ }
+ }
+
+ return line1;
+}
+
+/* Adapted from xscreensaver 3.24 driver/prefs.c line 257 ... */
+
+static GTree *
+parse_config_file (const char *file_name)
+{
+ struct stat st;
+ FILE *in;
+ char *buf;
+ GTree *config_db;
+ gint line_no;
+ char *line, *key, *value;
+
+ if (!g_file_test (file_name, G_FILE_TEST_ISFILE))
+ return NULL;
+
+ in = fopen (file_name, "r");
+
+ if (!in) {
+ g_warning ("error reading \"%s\": %s",
+ file_name, g_strerror (errno));
+ return NULL;
+ }
+
+ if (fstat (fileno(in), &st) != 0) {
+ g_warning ("couldn't re-stat \"%s\": %s",
+ file_name, g_strerror (errno));
+ return NULL;
+ }
+
+ config_db = g_tree_new ((GCompareFunc) strcmp);
+ line_no = 0;
+
+ while ((buf = get_line (in, &line_no))) {
+ line = transform_line (buf); g_free (buf);
+ key = g_strstrip (line);
+
+ if (*key == '#' || *key == '!' || *key == ';' ||
+ *key == '\n' || *key == 0)
+ continue;
+
+ value = strchr (key, ':');
+
+ if (!value) {
+ g_warning("%s:%d: unparsable line: %s\n",
+ file_name, line_no, key);
+ continue;
+ } else {
+ *value++ = 0;
+ value = g_strstrip (value);
+ }
+
+ g_tree_insert (config_db, g_strdup (key), g_strdup (value));
+ }
+
+ fclose (in);
+
+ return config_db;
+}
+
+gboolean
+preferences_load_from_file (Preferences *prefs)
+{
+ prefs->config_db = parse_config_file (init_file_name ());
+
+ if (!prefs->config_db)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/* Writing
+ */
+
+/* From xscreensaver 3.24 driver/prefs.c line 168 ... */
+
+static const char * const pref_names[] = {
+ "timeout",
+ "cycle",
+ "lock",
+ "lockVTs",
+ "lockTimeout",
+ "passwdTimeout",
+ "visualID",
+ "installColormap",
+ "verbose",
+ "timestamp",
+ "splashDuration",
+ "demoCommand",
+ "prefsCommand",
+ "helpURL",
+ "loadURL",
+ "nice",
+ "fade",
+ "unfade",
+ "fadeSeconds",
+ "fadeTicks",
+ "captureStderr",
+ "font",
+ "",
+ "programs",
+ "",
+ "pointerPollTime",
+ "windowCreationTimeout",
+ "initialDelay",
+ "sgiSaverExtension",
+ "mitSaverExtension",
+ "xidleExtension",
+ "procInterrupts",
+ "overlayStderr",
+ 0
+};
+
+/* From xscreensaver 3.24 driver/prefs.c line 397 ... */
+
+static int
+tab_to (FILE *out, int from, int to)
+{
+ int tab_width = 8;
+ int to_mod = (to / tab_width) * tab_width;
+
+ while (from < to_mod) {
+ fprintf(out, "\t");
+ from = (((from / tab_width) + 1) * tab_width);
+ }
+
+ while (from < to) {
+ fprintf(out, " ");
+ from++;
+ }
+
+ return from;
+}
+
+/* From xscreensaver 3.24 driver/prefs.c line 453 ... */
+
+static void
+write_entry (FILE *out, const char *key, const char *value)
+{
+ char *v = g_strdup(value ? value : "");
+ char *v2 = v;
+ char *nl = 0;
+ int col;
+ gboolean programs_p = (!strcmp(key, "programs"));
+ int tab = (programs_p ? 32 : 16);
+ gboolean first = TRUE;
+
+ fprintf (out, "%s:", key);
+ col = strlen(key) + 1;
+
+ while (1) {
+ if (!programs_p)
+ v2 = g_strstrip(v2);
+ nl = strchr(v2, '\n');
+ if (nl)
+ *nl = 0;
+
+ if (first && programs_p) {
+ col = tab_to (out, col, 77);
+ fprintf (out, " \\\n");
+ col = 0;
+ }
+
+ if (first)
+ first = FALSE;
+ else {
+ col = tab_to (out, col, 75);
+ fprintf (out, " \\n\\\n");
+ col = 0;
+ }
+
+ if (!programs_p)
+ col = tab_to (out, col, tab);
+
+ if (programs_p &&
+ string_columns(v2, strlen (v2), col) + col > 75)
+ {
+ int L = strlen (v2);
+ int start = 0;
+ int end = start;
+ while (start < L) {
+ while (v2[end] == ' ' || v2[end] == '\t')
+ end++;
+ while (v2[end] != ' ' && v2[end] != '\t' &&
+ v2[end] != '\n' && v2[end] != 0)
+ end++;
+ if (string_columns (v2 + start,
+ (end - start), col) >= 74)
+ {
+ col = tab_to (out, col, 75);
+ fprintf(out, " \\\n");
+ col = tab_to (out, 0, tab + 2);
+ while (v2[start] == ' ' ||
+ v2[start] == '\t')
+ start++;
+ }
+
+ col = string_columns (v2 + start,
+ (end - start), col);
+ while (start < end)
+ fputc(v2[start++], out);
+ }
+ } else {
+ fprintf (out, "%s", v2);
+ col += string_columns(v2, strlen (v2), col);
+ }
+
+ if (nl)
+ v2 = nl + 1;
+ else
+ break;
+ }
+
+ fprintf(out, "\n");
+ g_free(v);
+}
+
+static int
+write_preference_cb (gchar *key, gchar *value, FILE *out)
+{
+ write_entry (out, key, value);
+ return FALSE;
+}
+
+/* Adapted from xscreensaver 3.24 driver/prefs.c line 537 ... */
+
+gint
+preferences_save_to_file (Preferences *prefs)
+{
+ int status = -1;
+ const char *name = init_file_name();
+ const char *tmp_name = init_file_tmp_name();
+ char *n2 = chase_symlinks (name);
+ struct stat st;
+
+ FILE *out;
+
+ if (!name) goto END;
+
+ if (n2) name = n2;
+
+ if (prefs->verbose)
+ g_message ("writing \"%s\".\n", name);
+
+ unlink (tmp_name);
+ out = fopen(tmp_name, "w");
+ if (!out)
+ {
+ g_warning ("error writing \"%s\": %s", name,
+ g_strerror (errno));
+ goto END;
+ }
+
+ /* Give the new .xscreensaver file the same permissions as the old one;
+ except ensure that it is readable and writable by owner, and not
+ executable. Extra hack: if we're running as root, make the file
+ be world-readable (so that the daemon, running as "nobody", will
+ still be able to read it.)
+ */
+ if (g_file_test (name, G_FILE_TEST_ISFILE)) {
+ mode_t mode = st.st_mode;
+ mode |= S_IRUSR | S_IWUSR; /* read/write by user */
+ mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); /* executable by none */
+
+ if (getuid() == (uid_t) 0) /* read by group/other */
+ mode |= S_IRGRP | S_IROTH;
+
+ if (fchmod (fileno(out), mode) != 0)
+ {
+ g_warning ("error fchmodding \"%s\" to 0%o: %s",
+ tmp_name, (guint) mode, g_strerror (errno));
+ goto END;
+ }
+ }
+
+ {
+ struct passwd *pw = getpwuid (getuid ());
+ char *whoami = (pw && pw->pw_name && *pw->pw_name
+ ? pw->pw_name
+ : "<unknown>");
+ time_t now = time ((time_t *) 0);
+ char *timestr = (char *) ctime (&now);
+ char *nl = (char *) strchr (timestr, '\n');
+ if (nl) *nl = 0;
+ fprintf (out,
+ "# %s Preferences File\n"
+ "# Written by %s %s for %s on %s.\n"
+ "# http://www.jwz.org/xscreensaver/\n"
+ "\n",
+ "XScreenSaver", "xscreensaver", "3.24", whoami, timestr);
+ }
+
+ g_tree_traverse (prefs->config_db,
+ (GTraverseFunc) write_preference_cb,
+ G_IN_ORDER, out);
+
+ fprintf(out, "\n");
+
+ if (fclose(out) == 0)
+ {
+ time_t write_date = 0;
+
+ if (stat (tmp_name, &st) == 0)
+ {
+ write_date = st.st_mtime;
+ }
+ else
+ {
+ g_warning ("couldn't stat \"%s\": %s",
+ tmp_name, g_strerror (errno));
+ unlink (tmp_name);
+ goto END;
+ }
+
+ if (rename (tmp_name, name) != 0) {
+ g_warning ("error renaming \"%s\" to \"%s\": %s",
+ tmp_name, name, g_strerror (errno));
+ unlink (tmp_name);
+ goto END;
+ } else {
+ prefs->init_file_date = write_date;
+
+ /* Since the .xscreensaver file is used for
+ * IPC, let's try and make sure that the bits
+ * actually land on the disk right away.
+ */
+ sync ();
+
+ status = 0; /* wrote and renamed successfully! */
+ }
+ }
+
+ else
+ {
+ g_warning ("error closing \"%s\": %s",
+ name, g_strerror (errno));
+ unlink (tmp_name);
+ goto END;
+ }
+
+ END:
+ if (n2) g_free (n2);
+ return status;
+}
diff --git a/capplets/screensaver/pref-file.h b/capplets/screensaver/pref-file.h
new file mode 100644
index 000000000..6f9676c97
--- /dev/null
+++ b/capplets/screensaver/pref-file.h
@@ -0,0 +1,33 @@
+/* -*- mode: c; style: linux -*- */
+
+/* pref-file.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ * Parts written by Jamie Zawinski <jwz@jwz.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __PREF_FILE_H
+#define __PREF_FILE_H
+
+#include "preferences.h"
+
+gboolean preferences_load_from_file (Preferences *prefs);
+gint preferences_save_to_file (Preferences *prefs);
+
+#endif /* __PREF_FILE_H */
diff --git a/capplets/screensaver/preferences.c b/capplets/screensaver/preferences.c
new file mode 100644
index 000000000..b4afe03e4
--- /dev/null
+++ b/capplets/screensaver/preferences.c
@@ -0,0 +1,288 @@
+/* -*- mode: c; style: linux -*- */
+
+/* preferences.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include <gnome.h>
+
+#include "preferences.h"
+#include "preview.h"
+#include "pref-file.h"
+#include "resources.h"
+#include "rc-parse.h"
+
+static void
+remove_entry (GTree *config_db, gchar *entry)
+{
+ gchar *value_str;
+
+ value_str = g_tree_lookup (config_db, "verbose");
+ g_tree_remove (config_db, "verbose");
+ if (value_str) g_free (value_str);
+}
+
+static void
+read_prefs_from_db (Preferences *prefs)
+{
+ gchar *value;
+
+ value = g_tree_lookup (prefs->config_db, "verbose");
+ if (value) prefs->verbose = parse_boolean_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "lock");
+ if (value) prefs->lock = parse_boolean_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "fade");
+ if (value) prefs->fade = parse_boolean_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "unfade");
+ if (value) prefs->unfade = parse_boolean_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "fadeSeconds");
+ if (value) prefs->fade_seconds = parse_seconds_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "fadeTicks");
+ if (value) prefs->fade_ticks = parse_integer_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "installColormap");
+ if (value) prefs->install_colormap = parse_boolean_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "nice");
+ if (value) prefs->nice = parse_integer_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "timeout");
+ if (value) prefs->timeout = parse_minutes_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "lockTimeout");
+ if (value) prefs->lock_timeout = parse_minutes_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "cycle");
+ if (value) prefs->cycle = parse_minutes_resource (value);
+
+ value = g_tree_lookup (prefs->config_db, "programs");
+ if (value) prefs->screensavers = parse_screensaver_list (value);
+}
+
+static void
+store_prefs_in_db (Preferences *prefs)
+{
+ remove_entry (prefs->config_db, "verbose");
+ g_tree_insert (prefs->config_db, "verbose",
+ write_boolean (prefs->verbose));
+
+ remove_entry (prefs->config_db, "lock");
+ g_tree_insert (prefs->config_db, "lock",
+ write_boolean (prefs->lock));
+
+ remove_entry (prefs->config_db, "fade");
+ g_tree_insert (prefs->config_db, "fade",
+ write_boolean (prefs->fade));
+
+ remove_entry (prefs->config_db, "unfade");
+ g_tree_insert (prefs->config_db, "unfade",
+ write_boolean (prefs->unfade));
+
+ remove_entry (prefs->config_db, "fadeSeconds");
+ g_tree_insert (prefs->config_db, "fadeSeconds",
+ write_seconds (prefs->fade_seconds));
+
+ remove_entry (prefs->config_db, "fadeTicks");
+ g_tree_insert (prefs->config_db, "fadeTicks",
+ write_integer (prefs->fade_ticks));
+
+ remove_entry (prefs->config_db, "installColormap");
+ g_tree_insert (prefs->config_db, "installColormap",
+ write_boolean (prefs->install_colormap));
+
+ remove_entry (prefs->config_db, "nice");
+ g_tree_insert (prefs->config_db, "nice",
+ write_integer (prefs->nice));
+
+ remove_entry (prefs->config_db, "timeout");
+ g_tree_insert (prefs->config_db, "timeout",
+ write_minutes (prefs->timeout));
+
+ remove_entry (prefs->config_db, "lockTimeout");
+ g_tree_insert (prefs->config_db, "lockTimeout",
+ write_minutes (prefs->lock_timeout));
+
+ remove_entry (prefs->config_db, "cycle");
+ g_tree_insert (prefs->config_db, "cycle",
+ write_minutes (prefs->cycle));
+
+ remove_entry (prefs->config_db, "programs");
+ g_tree_insert (prefs->config_db, "programs",
+ write_screensaver_list (prefs->screensavers));
+}
+
+Preferences *
+preferences_new (void)
+{
+ Preferences *prefs;
+
+ prefs = g_new0 (Preferences, 1);
+
+ return prefs;
+}
+
+void
+preferences_destroy (Preferences *prefs)
+{
+ GList *node;
+
+ if (!prefs) return;
+
+ /* Destroy screensavers */
+ if (prefs->screensavers) {
+ for (node = prefs->screensavers; node; node = node->next)
+ screensaver_destroy (SCREENSAVER (node->data));
+
+ g_list_free (prefs->screensavers);
+ }
+
+ if (prefs->programs_list) g_free (prefs->programs_list);
+ g_free (prefs);
+}
+
+void
+preferences_load (Preferences *prefs)
+{
+ g_return_if_fail (prefs != NULL);
+
+ if (!preferences_load_from_file (prefs))
+ preferences_load_from_xrdb (prefs);
+
+ read_prefs_from_db (prefs);
+
+ prefs->selection_mode =
+ gnome_config_get_int ("/Screensaver/Default/selection_mode=3");
+ prefs->power_management =
+ gnome_config_get_bool ("/Screensaver/Default/use_dpms=FALSE");
+ prefs->standby_time =
+ gnome_config_get_int ("/Screensaver/Default/standby_time=0");
+ prefs->suspend_time =
+ gnome_config_get_int ("/Screensaver/Default/suspend_time=0");
+ prefs->power_down_time =
+ gnome_config_get_int ("/Screensaver/Default/shutdown_time=20");
+}
+
+void
+preferences_save (Preferences *prefs)
+{
+ g_return_if_fail (prefs != NULL);
+ g_return_if_fail (prefs->config_db != NULL);
+
+ store_prefs_in_db (prefs);
+
+ preferences_save_to_file (prefs);
+
+ gnome_config_set_int ("/Screensaver/Default/selection_mode",
+ prefs->selection_mode);
+ gnome_config_set_bool ("/Screensaver/Default/use_dpms",
+ prefs->power_management);
+ gnome_config_set_int ("/Screensaver/Default/standby_time",
+ prefs->standby_time);
+ gnome_config_set_int ("/Screensaver/Default/suspend_time",
+ prefs->suspend_time);
+ gnome_config_set_int ("/Screensaver/Default/shutdown_time",
+ prefs->power_down_time);
+ gnome_config_sync ();
+}
+
+Screensaver *
+screensaver_new (void)
+{
+ Screensaver *saver;
+
+ saver = g_new0 (Screensaver, 1);
+ saver->name = NULL;
+ saver->enabled = TRUE;
+
+ return saver;
+}
+
+void
+screensaver_destroy (Screensaver *saver)
+{
+ if (!saver) return;
+
+ if (saver->visual) g_free (saver->visual);
+ if (saver->name) g_free (saver->name);
+ if (saver->command_line) g_free (saver->command_line);
+ if (saver->label) g_free (saver->label);
+ if (saver->description) g_free (saver->description);
+
+ g_free (saver);
+}
+
+GList *
+screensaver_add (Screensaver *saver, GList *screensavers)
+{
+ GList *list, *node;
+
+ g_return_val_if_fail (saver != NULL, NULL);
+
+ list = g_list_append (screensavers, saver);
+ saver->link = g_list_find (list, saver);
+
+ for (node = list; node != saver->link; node = node->next)
+ saver->id++;
+
+ return list;
+}
+
+GList *
+screensaver_remove (Screensaver *saver, GList *screensavers)
+{
+ GList *node;
+
+ g_return_val_if_fail (saver != NULL, NULL);
+ g_return_val_if_fail (saver->link != NULL, NULL);
+ g_return_val_if_fail (saver == saver->link->data, NULL);
+
+ for (node = saver->link->next; node; node = node->next)
+ SCREENSAVER (node->data)->id--;
+
+ return g_list_remove_link (screensavers, saver->link);
+}
+
+char *
+screensaver_get_desc (Screensaver *saver)
+{
+ g_return_val_if_fail (saver != NULL, NULL);
+
+ if (!saver->description)
+ screensaver_get_desc_from_xrdb (saver);
+
+ if (!saver->description)
+ saver->description = g_strdup (_("Custom screensaver. No description available"));
+
+ return saver->description;
+}
diff --git a/capplets/screensaver/preferences.h b/capplets/screensaver/preferences.h
new file mode 100644
index 000000000..2426beff3
--- /dev/null
+++ b/capplets/screensaver/preferences.h
@@ -0,0 +1,110 @@
+/* -*- mode: c; style: linux -*- */
+
+/* preferences.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __PREFERENCES_H
+#define __PREFERENCES_H
+
+#include <sys/time.h>
+#include <gtk/gtk.h>
+
+enum _SelectionMode {
+ SM_DISABLE_SCREENSAVER,
+ SM_BLANK_SCREEN,
+ SM_ONE_SCREENSAVER_ONLY,
+ SM_CHOOSE_FROM_LIST,
+ SM_CHOOSE_RANDOMLY
+};
+
+typedef enum _SelectionMode SelectionMode;
+
+#define SCREENSAVER(obj) ((Screensaver *) obj)
+
+typedef struct _Screensaver Screensaver;
+
+struct _Screensaver
+{
+ guint id;
+ gchar *name;
+ gchar *label;
+ gchar *description;
+ gchar *command_line;
+ gchar *visual;
+ gboolean enabled;
+ GList *link;
+};
+
+struct _Preferences
+{
+ time_t init_file_date;
+
+ gboolean verbose;
+ gboolean lock;
+
+ gboolean fade;
+ gboolean unfade;
+ time_t fade_seconds;
+ guint fade_ticks;
+
+ gboolean install_colormap;
+
+ gint nice;
+
+ gdouble timeout;
+ gdouble lock_timeout;
+ gdouble cycle;
+
+ gchar *programs_list; /* Programs resource, in JWZ's format */
+
+ SelectionMode selection_mode;
+
+ GList *screensavers;
+
+ gboolean frozen; /* TRUE if we shouldn't reflect
+ * preference changes in capplet */
+ GTree *config_db; /* key-value database of config options */
+
+ /* Settings that are not stored in .xscreensaver ... */
+
+ gboolean power_management;
+ time_t standby_time;
+ time_t suspend_time;
+ time_t power_down_time;
+};
+
+typedef struct _Preferences Preferences;
+
+Preferences *preferences_new (void);
+void preferences_destroy (Preferences *prefs);
+
+void preferences_load (Preferences *prefs);
+void preferences_save (Preferences *prefs);
+
+Screensaver *screensaver_new (void);
+void screensaver_destroy (Screensaver *saver);
+
+GList *screensaver_add (Screensaver *saver, GList *screensavers);
+GList *screensaver_remove (Screensaver *saver, GList *screensavers);
+
+char *screensaver_get_desc (Screensaver *saver);
+
+#endif /* __PREFERENCES_H */
diff --git a/capplets/screensaver/prefs-widget.c b/capplets/screensaver/prefs-widget.c
new file mode 100644
index 000000000..49d44a79f
--- /dev/null
+++ b/capplets/screensaver/prefs-widget.c
@@ -0,0 +1,1635 @@
+/* -*- mode: c; style: linux -*- */
+
+/* prefs-widget.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <gdk/gdkprivate.h>
+#include <capplet-widget.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "prefs-widget.h"
+#include "preview.h"
+#include "screensaver-prefs-dialog.h"
+#include "selection-dialog.h"
+#include "rc-parse.h"
+
+#include "checked.xpm"
+#include "unchecked.xpm"
+#include "checked-disabled.xpm"
+#include "unchecked-disabled.xpm"
+
+enum {
+ STATE_CHANGED_SIGNAL,
+ ACTIVATE_DEMO_SIGNAL,
+ LAST_SIGNAL
+};
+
+static gint prefs_widget_signals[LAST_SIGNAL] = { 0 };
+
+static void prefs_widget_init (PrefsWidget *prefs);
+static void prefs_widget_class_init (PrefsWidgetClass *class);
+
+static void set_lock_controls_sensitive (PrefsWidget *prefs, gboolean s);
+static void set_fade_scales_sensitive (PrefsWidget *prefs, gboolean s);
+static void set_fade_controls_sensitive (PrefsWidget *prefs, gboolean s);
+static void set_standby_time_sensitive (PrefsWidget *prefs, gboolean s);
+static void set_suspend_time_sensitive (PrefsWidget *prefs, gboolean s);
+static void set_power_down_time_sensitive (PrefsWidget *prefs, gboolean s);
+static void set_power_controls_sensitive (PrefsWidget *prefs, gboolean s);
+
+static void set_all_pixmaps (PrefsWidget *prefs,
+ SelectionMode mode);
+
+static void disable_screensaver_cb (GtkToggleButton *button,
+ PrefsWidget *widget);
+static void blank_screen_selected_cb (GtkToggleButton *button,
+ PrefsWidget *widget);
+static void one_screensaver_cb (GtkToggleButton *button,
+ PrefsWidget *widget);
+static void choose_from_selected_cb (GtkToggleButton *button,
+ PrefsWidget *widget);
+static void random_cb (GtkToggleButton *button,
+ PrefsWidget *widget);
+
+static void select_saver_cb (GtkCList *list,
+ gint row, gint column,
+ GdkEventButton *event,
+ PrefsWidget *widget);
+static void deselect_saver_cb (GtkCList *list,
+ gint row, gint column,
+ GdkEventButton *event,
+ PrefsWidget *widget);
+static void settings_cb (GtkWidget *button,
+ PrefsWidget *widget);
+static void screensaver_add_cb (GtkWidget *button,
+ PrefsWidget *widget);
+static void screensaver_remove_cb (GtkWidget *button,
+ PrefsWidget *widget);
+static void demo_cb (GtkWidget *button,
+ PrefsWidget *widget);
+static void demo_next_cb (GtkWidget *button,
+ PrefsWidget *widget);
+static void demo_prev_cb (GtkWidget *button,
+ PrefsWidget *widget);
+
+static void require_password_changed_cb (GtkCheckButton *button,
+ PrefsWidget *widget);
+static void lock_timeout_changed_cb (GtkCheckButton *button,
+ PrefsWidget *widget);
+static void power_management_toggled_cb (GtkCheckButton *button,
+ PrefsWidget *widget);
+static void standby_monitor_toggled_cb (GtkCheckButton *button,
+ PrefsWidget *widget);
+static void suspend_monitor_toggled_cb (GtkCheckButton *button,
+ PrefsWidget *widget);
+static void shut_down_monitor_toggled_cb (GtkCheckButton *button,
+ PrefsWidget *widget);
+
+static void install_cmap_changed_cb (GtkCheckButton *button,
+ PrefsWidget *widget);
+static void fade_unfade_changed_cb (GtkCheckButton *button,
+ PrefsWidget *widget);
+
+static void state_changed_cb (GtkWidget *widget,
+ PrefsWidget *prefs);
+
+static void screensaver_prefs_ok_cb (ScreensaverPrefsDialog *dialog,
+ PrefsWidget *widget);
+
+static void prefs_demo_cb (GtkWidget *widget,
+ PrefsWidget *prefs_widget);
+
+static void add_select_cb (GtkWidget *widget,
+ Screensaver *saver,
+ PrefsWidget *prefs_widget);
+
+static gint create_list_item (Screensaver *saver,
+ SelectionMode mode,
+ PrefsWidget *prefs_widget);
+
+static void set_description_text (PrefsWidget *widget,
+ gchar *description);
+
+static void set_screensavers_enabled (PrefsWidget *widget,
+ gboolean s);
+static void set_pixmap (GtkCList *clist,
+ Screensaver *saver, gint row,
+ SelectionMode mode);
+static void toggle_saver (PrefsWidget *widget, gint row,
+ Screensaver *saver);
+static void select_row (GtkCList *clist, gint row);
+
+guint
+prefs_widget_get_type (void)
+{
+ static guint prefs_widget_type = 0;
+
+ if (!prefs_widget_type) {
+ GtkTypeInfo prefs_widget_info = {
+ "PrefsWidget",
+ sizeof (PrefsWidget),
+ sizeof (PrefsWidgetClass),
+ (GtkClassInitFunc) prefs_widget_class_init,
+ (GtkObjectInitFunc) prefs_widget_init,
+ (GtkArgSetFunc) NULL,
+ (GtkArgGetFunc) NULL
+ };
+
+ prefs_widget_type =
+ gtk_type_unique (gtk_notebook_get_type (),
+ &prefs_widget_info);
+ }
+
+ return prefs_widget_type;
+}
+
+static void
+prefs_widget_init (PrefsWidget *prefs)
+{
+ GtkWidget *table, *frame, *vbox, *vbox1, *hbox, *label;
+ GtkWidget *hbuttonbox, *scrolled_window, *button;
+ GtkObject *adjustment;
+ GSList *no_screensavers_group = NULL;
+ GtkWidget *viewport;
+
+ table = gtk_table_new (2, 2, FALSE);
+ gtk_container_add (GTK_CONTAINER (prefs), table);
+ gtk_container_set_border_width (GTK_CONTAINER (table), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 10);
+
+ frame = gtk_frame_new (_("Selection"));
+ gtk_table_attach (GTK_TABLE (table), frame, 0, 1, 0, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+
+ vbox1 = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), vbox1, FALSE, FALSE, 0);
+
+ prefs->disable_screensaver_widget =
+ gtk_radio_button_new_with_label
+ (no_screensavers_group, _("Disable screensaver"));
+ no_screensavers_group =
+ gtk_radio_button_group
+ (GTK_RADIO_BUTTON (prefs->disable_screensaver_widget));
+ gtk_box_pack_start (GTK_BOX (vbox1),
+ prefs->disable_screensaver_widget,
+ FALSE, FALSE, 0);
+
+ prefs->blank_screen_widget =
+ gtk_radio_button_new_with_label
+ (no_screensavers_group, _("Black screen only"));
+ no_screensavers_group =
+ gtk_radio_button_group
+ (GTK_RADIO_BUTTON (prefs->blank_screen_widget));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->blank_screen_widget,
+ FALSE, FALSE, 0);
+
+ prefs->one_screensaver_widget =
+ gtk_radio_button_new_with_label
+ (no_screensavers_group, _("One screensaver all the time"));
+ no_screensavers_group =
+ gtk_radio_button_group
+ (GTK_RADIO_BUTTON (prefs->one_screensaver_widget));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->one_screensaver_widget,
+ FALSE, FALSE, 0);
+
+ prefs->choose_from_list_widget =
+ gtk_radio_button_new_with_label
+ (no_screensavers_group,
+ _("Choose randomly from those checked off"));
+ no_screensavers_group =
+ gtk_radio_button_group
+ (GTK_RADIO_BUTTON (prefs->choose_from_list_widget));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->choose_from_list_widget,
+ FALSE, FALSE, 0);
+
+ prefs->choose_randomly_widget =
+ gtk_radio_button_new_with_label
+ (no_screensavers_group,
+ _("Choose randomly among all screensavers"));
+ no_screensavers_group =
+ gtk_radio_button_group
+ (GTK_RADIO_BUTTON (prefs->choose_randomly_widget));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->choose_randomly_widget,
+ FALSE, FALSE, 0);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+
+ prefs->screensaver_list = gtk_clist_new (2);
+ gtk_clist_column_titles_hide (GTK_CLIST (prefs->screensaver_list));
+ gtk_clist_set_column_width (GTK_CLIST (prefs->screensaver_list),
+ 0, 16);
+ gtk_clist_set_sort_column (GTK_CLIST (prefs->screensaver_list), 1);
+ gtk_clist_set_auto_sort (GTK_CLIST (prefs->screensaver_list), TRUE);
+ gtk_clist_set_selection_mode (GTK_CLIST (prefs->screensaver_list),
+ GTK_SELECTION_SINGLE);
+ gtk_container_add (GTK_CONTAINER (scrolled_window),
+ prefs->screensaver_list);
+
+ hbuttonbox = gtk_hbutton_box_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), hbuttonbox, FALSE, FALSE, 0);
+
+ button = gtk_button_new_with_label (_("Add..."));
+ gtk_container_add (GTK_CONTAINER (hbuttonbox), button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ screensaver_add_cb, prefs);
+
+ prefs->remove_button = gtk_button_new_with_label (_("Remove"));
+ gtk_container_add (GTK_CONTAINER (hbuttonbox), prefs->remove_button);
+ gtk_signal_connect (GTK_OBJECT (prefs->remove_button), "clicked",
+ screensaver_remove_cb, prefs);
+ gtk_widget_set_sensitive (prefs->remove_button, FALSE);
+
+ prefs->settings_button = gtk_button_new_with_label (_("Edit..."));
+ gtk_container_add (GTK_CONTAINER (hbuttonbox), prefs->settings_button);
+ gtk_widget_set_sensitive (prefs->settings_button, FALSE);
+
+ hbuttonbox = gtk_hbutton_box_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), hbuttonbox, FALSE, FALSE, 0);
+
+ prefs->demo_button = gtk_button_new_with_label (_("Demo"));
+ gtk_container_add (GTK_CONTAINER (hbuttonbox), prefs->demo_button);
+ gtk_widget_set_sensitive (prefs->demo_button, FALSE);
+
+ button = gtk_button_new_with_label (_("Demo Next"));
+ gtk_container_add (GTK_CONTAINER (hbuttonbox), button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ demo_next_cb, prefs);
+
+ button = gtk_button_new_with_label (_("Demo Previous"));
+ gtk_container_add (GTK_CONTAINER (hbuttonbox), button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ demo_prev_cb, prefs);
+
+ frame = gtk_frame_new (_("Preview"));
+ gtk_table_attach (GTK_TABLE (table), frame, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (frame), scrolled_window);
+ gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 5);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+
+ viewport = gtk_viewport_new (NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), viewport);
+
+ prefs->preview_window = gtk_drawing_area_new ();
+ gtk_container_add (GTK_CONTAINER (viewport), prefs->preview_window);
+ gtk_widget_set_usize (prefs->preview_window, 300, 250);
+
+ frame = gtk_frame_new (_("Description"));
+
+ gtk_table_attach (GTK_TABLE (table), frame, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+ gtk_container_add (GTK_CONTAINER (frame), scrolled_window);
+ gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 5);
+
+ prefs->description = gtk_text_new (NULL, NULL);
+ gtk_text_set_word_wrap (GTK_TEXT (prefs->description), TRUE);
+ gtk_container_add (GTK_CONTAINER (scrolled_window),
+ prefs->description);
+
+ gtk_widget_show_all (table);
+ label = gtk_label_new (_("Screensaver Selection"));
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (prefs),
+ gtk_notebook_get_nth_page
+ (GTK_NOTEBOOK (prefs), 0), label);
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (prefs), vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+
+ frame = gtk_frame_new (_("Basic"));
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+
+ vbox1 = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (frame), vbox1);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5);
+
+ table = gtk_table_new (2, 3, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+ gtk_box_pack_start (GTK_BOX (vbox1), table, FALSE, FALSE, 0);
+
+ label = gtk_label_new (_("Start screensaver after"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_table_attach (GTK_TABLE (table), label,
+ 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
+
+ adjustment = gtk_adjustment_new (1, 0, 1000, 1, 10, 10);
+ prefs->timeout_widget =
+ gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 1, 0);
+ gtk_table_attach (GTK_TABLE (table), prefs->timeout_widget,
+ 1, 2, 0, 1, 0, 0, 0, 0);
+
+ label = gtk_label_new (_("minutes"));
+ gtk_table_attach (GTK_TABLE (table), label,
+ 2, 3, 0, 1, 0, 0, 0, 0);
+
+ label = gtk_label_new (_("Switch screensavers every"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_table_attach (GTK_TABLE (table), label,
+ 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+
+ adjustment = gtk_adjustment_new (1, 0, 6000, 1, 10, 10);
+ prefs->cycle_length_widget =
+ gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 1, 0);
+ gtk_table_attach (GTK_TABLE (table), prefs->cycle_length_widget,
+ 1, 2, 1, 2, 0, 0, 0, 0);
+
+ label = gtk_label_new (_("minutes"));
+ gtk_table_attach (GTK_TABLE (table), label,
+ 2, 3, 1, 2, 0, 0, 0, 0);
+
+ frame = gtk_frame_new (_("Security"));
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+
+ vbox1 = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (frame), vbox1);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5);
+
+ prefs->lock_widget =
+ gtk_check_button_new_with_label
+ (_("Require password to unlock"));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->lock_widget,
+ TRUE, TRUE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 5);
+ gtk_box_pack_start (GTK_BOX (vbox1), hbox, TRUE, TRUE, 0);
+
+ prefs->enable_timeout_widget =
+ gtk_check_button_new_with_label
+ (_("Only after the screensaver has run for"));
+ gtk_box_pack_start (GTK_BOX (hbox), prefs->enable_timeout_widget,
+ FALSE, FALSE, 0);
+
+ adjustment = gtk_adjustment_new (1, 0, 1000, 1, 10, 10);
+ prefs->time_to_lock_widget =
+ gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 1, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), prefs->time_to_lock_widget,
+ FALSE, TRUE, 0);
+
+ prefs->lock_timeout_seconds_label = gtk_label_new (_("minutes"));
+ gtk_box_pack_start (GTK_BOX (hbox), prefs->lock_timeout_seconds_label,
+ FALSE, FALSE, 0);
+ gtk_label_set_justify (GTK_LABEL (prefs->lock_timeout_seconds_label),
+ GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (prefs->lock_timeout_seconds_label),
+ 0, 0.5);
+
+ frame = gtk_frame_new (_("Power Management"));
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+
+ vbox1 = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (frame), vbox1);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5);
+
+ prefs->pwr_manage_enable =
+ gtk_check_button_new_with_label (_("Enable power management"));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->pwr_manage_enable,
+ FALSE, FALSE, 0);
+
+ table = gtk_table_new (3, 3, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+ gtk_box_pack_start (GTK_BOX (vbox1), table, TRUE, TRUE, 0);
+
+ prefs->standby_monitor_toggle =
+ gtk_check_button_new_with_label
+ (_("Go to standby mode after"));
+ gtk_table_attach (GTK_TABLE (table), prefs->standby_monitor_toggle,
+ 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
+
+ adjustment = gtk_adjustment_new (1, 0, 10000, 1, 10, 10);
+ prefs->standby_time_widget =
+ gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 1, 0);
+ gtk_table_attach (GTK_TABLE (table), prefs->standby_time_widget,
+ 1, 2, 0, 1, 0, 0, 0, 0);
+
+ prefs->standby_monitor_label2 =
+ gtk_label_new (_("minutes"));
+ gtk_table_attach (GTK_TABLE (table), prefs->standby_monitor_label2,
+ 2, 3, 0, 1, 0, 0, 0, 0);
+
+ prefs->suspend_monitor_toggle =
+ gtk_check_button_new_with_label
+ (_("Go to suspend mode after"));
+ gtk_table_attach (GTK_TABLE (table), prefs->suspend_monitor_toggle,
+ 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+
+ adjustment = gtk_adjustment_new (1, 0, 10000, 1, 10, 10);
+ prefs->suspend_time_widget =
+ gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 1, 0);
+ gtk_table_attach (GTK_TABLE (table), prefs->suspend_time_widget,
+ 1, 2, 1, 2, 0, 0, 0, 0);
+
+ prefs->suspend_monitor_label2 =
+ gtk_label_new (_("minutes"));
+ gtk_table_attach (GTK_TABLE (table), prefs->suspend_monitor_label2,
+ 2, 3, 1, 2, 0, 0, 0, 0);
+
+ prefs->shut_down_monitor_toggle =
+ gtk_check_button_new_with_label
+ (_("Shut down monitor after"));
+ gtk_table_attach (GTK_TABLE (table), prefs->shut_down_monitor_toggle,
+ 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
+
+ adjustment = gtk_adjustment_new (1, 0, 10000, 1, 10, 10);
+ prefs->shut_down_time_widget =
+ gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 1, 0);
+ gtk_table_attach (GTK_TABLE (table), prefs->shut_down_time_widget,
+ 1, 2, 2, 3, 0, 0, 0, 0);
+
+ prefs->shut_down_monitor_label2 =
+ gtk_label_new (_("minutes"));
+ gtk_table_attach (GTK_TABLE (table), prefs->shut_down_monitor_label2,
+ 2, 3, 2, 3, 0, 0, 0, 0);
+
+ gtk_widget_show_all (vbox);
+
+ label = gtk_label_new (_("General Properties"));
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (prefs),
+ gtk_notebook_get_nth_page
+ (GTK_NOTEBOOK (prefs), 1), label);
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (prefs), vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+
+ table = gtk_table_new (3, 3, FALSE);
+ gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (table), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+
+ label = gtk_label_new (_("Priority"));
+ gtk_table_attach (GTK_TABLE (table), label, 0, 3, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+ label = gtk_label_new (_("Low"));
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
+ gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
+
+ label = gtk_label_new (_("High"));
+ gtk_table_attach (GTK_TABLE (table), label, 2, 3, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+ adjustment = gtk_adjustment_new (0, -20, 0, 0, 0, 0);
+ gtk_signal_connect (adjustment, "value-changed", state_changed_cb,
+ prefs);
+ prefs->nice_widget =
+ gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+ gtk_table_attach (GTK_TABLE (table), prefs->nice_widget, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_scale_set_draw_value (GTK_SCALE (prefs->nice_widget), FALSE);
+
+ prefs->verbose_widget =
+ gtk_check_button_new_with_label (_("Be verbose"));
+ gtk_box_pack_start (GTK_BOX (vbox), prefs->verbose_widget,
+ FALSE, FALSE, 0);
+
+ prefs->effects_frame = gtk_frame_new (_("Effects"));
+ gtk_box_pack_start (GTK_BOX (vbox), prefs->effects_frame,
+ FALSE, TRUE, 0);
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (prefs->effects_frame), vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+
+ vbox1 = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), vbox1, FALSE, TRUE, 0);
+
+ prefs->install_cmap_widget =
+ gtk_check_button_new_with_label (_("Install colormap"));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->install_cmap_widget,
+ FALSE, FALSE, 0);
+
+ prefs->fade_widget =
+ gtk_check_button_new_with_label
+ (_("Fade to black when activating screensaver"));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->fade_widget,
+ FALSE, FALSE, 0);
+
+ prefs->unfade_widget =
+ gtk_check_button_new_with_label
+ (_("Fade desktop back when deactivating screensaver"));
+ gtk_box_pack_start (GTK_BOX (vbox1), prefs->unfade_widget,
+ FALSE, FALSE, 0);
+
+ table = gtk_table_new (4, 3, FALSE);
+ gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+
+ prefs->fade_duration_label = gtk_label_new (_("Fade Duration"));
+ gtk_table_attach (GTK_TABLE (table),
+ prefs->fade_duration_label, 0, 3, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (prefs->fade_duration_label),
+ GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (prefs->fade_duration_label), 0, 0.5);
+
+ adjustment = gtk_adjustment_new (100, 0, 256, 0, 0, 0);
+ gtk_signal_connect (adjustment, "value-changed", state_changed_cb,
+ prefs);
+ prefs->fade_ticks_widget =
+ gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+ gtk_table_attach (GTK_TABLE (table),
+ prefs->fade_ticks_widget, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_scale_set_draw_value (GTK_SCALE (prefs->fade_ticks_widget), FALSE);
+
+ prefs->fade_ticks_label = gtk_label_new (_("Fade Smoothness"));
+ gtk_table_attach (GTK_TABLE (table),
+ prefs->fade_ticks_label, 0, 3, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (prefs->fade_ticks_label),
+ GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (prefs->fade_ticks_label), 0, 0);
+
+ adjustment = gtk_adjustment_new (3, 0, 10, 0, 0, 0);
+ prefs->fade_duration_widget =
+ gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+ gtk_signal_connect (adjustment, "value-changed", state_changed_cb,
+ prefs);
+ gtk_table_attach (GTK_TABLE (table),
+ prefs->fade_duration_widget, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_scale_set_draw_value (GTK_SCALE (prefs->fade_duration_widget),
+ FALSE);
+
+ prefs->fade_duration_high_label = gtk_label_new (_("Long"));
+ gtk_table_attach (GTK_TABLE (table),
+ prefs->fade_duration_high_label, 2, 3, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (prefs->fade_duration_high_label),
+ GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (prefs->fade_duration_high_label),
+ 0, 0.5);
+
+ prefs->fade_ticks_high_label = gtk_label_new (_("Smooth"));
+ gtk_table_attach (GTK_TABLE (table),
+ prefs->fade_ticks_high_label, 2, 3, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (prefs->fade_ticks_high_label),
+ GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (prefs->fade_ticks_high_label),
+ 0, 0.5);
+
+ prefs->fade_duration_low_label = gtk_label_new (_("Short"));
+ gtk_table_attach (GTK_TABLE (table),
+ prefs->fade_duration_low_label, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (prefs->fade_duration_low_label),
+ GTK_JUSTIFY_RIGHT);
+ gtk_misc_set_alignment (GTK_MISC (prefs->fade_duration_low_label),
+ 1, 0.5);
+
+ prefs->fade_ticks_low_label = gtk_label_new (_("Jerky"));
+ gtk_table_attach (GTK_TABLE (table),
+ prefs->fade_ticks_low_label, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (prefs->fade_ticks_low_label),
+ GTK_JUSTIFY_RIGHT);
+ gtk_misc_set_alignment (GTK_MISC (prefs->fade_ticks_low_label),
+ 1, 0.5);
+
+ gtk_widget_show_all (vbox);
+ label = gtk_label_new (_("Advanced Properties"));
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (prefs),
+ gtk_notebook_get_nth_page
+ (GTK_NOTEBOOK (prefs), 2), label);
+
+ gtk_signal_connect (GTK_OBJECT (prefs->disable_screensaver_widget),
+ "toggled",
+ GTK_SIGNAL_FUNC (disable_screensaver_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->blank_screen_widget),
+ "toggled",
+ GTK_SIGNAL_FUNC (blank_screen_selected_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->one_screensaver_widget),
+ "toggled",
+ GTK_SIGNAL_FUNC (one_screensaver_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->choose_from_list_widget),
+ "toggled",
+ GTK_SIGNAL_FUNC (choose_from_selected_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->choose_randomly_widget),
+ "toggled",
+ GTK_SIGNAL_FUNC (random_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->screensaver_list),
+ "select-row", GTK_SIGNAL_FUNC (select_saver_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->screensaver_list),
+ "unselect-row",
+ GTK_SIGNAL_FUNC (deselect_saver_cb), prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->demo_button), "clicked",
+ GTK_SIGNAL_FUNC (demo_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->settings_button), "clicked",
+ GTK_SIGNAL_FUNC (settings_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->timeout_widget), "changed",
+ GTK_SIGNAL_FUNC (state_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->cycle_length_widget), "changed",
+ GTK_SIGNAL_FUNC (state_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->lock_widget), "toggled",
+ GTK_SIGNAL_FUNC (require_password_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->enable_timeout_widget),
+ "toggled",
+ GTK_SIGNAL_FUNC (lock_timeout_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->time_to_lock_widget), "changed",
+ GTK_SIGNAL_FUNC (state_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->pwr_manage_enable), "toggled",
+ GTK_SIGNAL_FUNC (power_management_toggled_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->standby_monitor_toggle),
+ "toggled",
+ GTK_SIGNAL_FUNC (standby_monitor_toggled_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->suspend_monitor_toggle),
+ "toggled",
+ GTK_SIGNAL_FUNC (suspend_monitor_toggled_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->shut_down_monitor_toggle),
+ "toggled",
+ GTK_SIGNAL_FUNC (shut_down_monitor_toggled_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->standby_time_widget),
+ "changed",
+ GTK_SIGNAL_FUNC (state_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->suspend_time_widget),
+ "changed",
+ GTK_SIGNAL_FUNC (state_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->shut_down_time_widget),
+ "changed",
+ GTK_SIGNAL_FUNC (state_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->verbose_widget), "toggled",
+ GTK_SIGNAL_FUNC (state_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->install_cmap_widget), "toggled",
+ GTK_SIGNAL_FUNC (install_cmap_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->fade_widget), "toggled",
+ GTK_SIGNAL_FUNC (fade_unfade_changed_cb),
+ prefs);
+ gtk_signal_connect (GTK_OBJECT (prefs->unfade_widget), "toggled",
+ GTK_SIGNAL_FUNC (fade_unfade_changed_cb),
+ prefs);
+}
+
+static void
+prefs_widget_class_init (PrefsWidgetClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass *) class;
+
+ prefs_widget_signals[STATE_CHANGED_SIGNAL] =
+ gtk_signal_new ("pref-changed", GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (PrefsWidgetClass,
+ state_changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ prefs_widget_signals[ACTIVATE_DEMO_SIGNAL] =
+ gtk_signal_new ("activate-demo", GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (PrefsWidgetClass,
+ activate_demo),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, prefs_widget_signals,
+ LAST_SIGNAL);
+
+ class->state_changed = NULL;
+}
+
+GtkWidget *
+prefs_widget_new (void)
+{
+ return gtk_type_new (prefs_widget_get_type ());
+}
+
+void
+prefs_widget_store_prefs (PrefsWidget *prefs_widget, Preferences *prefs)
+{
+ GtkAdjustment *adjustment;
+
+ prefs->timeout = gtk_spin_button_get_value_as_float
+ (GTK_SPIN_BUTTON (prefs_widget->timeout_widget));
+
+ prefs->cycle = gtk_spin_button_get_value_as_float
+ (GTK_SPIN_BUTTON (prefs_widget->cycle_length_widget));
+
+ prefs->lock = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->lock_widget));
+
+ prefs->lock_timeout = gtk_spin_button_get_value_as_float
+ (GTK_SPIN_BUTTON (prefs_widget->time_to_lock_widget));
+
+ prefs->lock_timeout = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->enable_timeout_widget));
+
+ prefs->power_management = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->pwr_manage_enable));
+
+ prefs->standby_time = gtk_spin_button_get_value_as_int
+ (GTK_SPIN_BUTTON (prefs_widget->standby_time_widget));
+
+ prefs->suspend_time = gtk_spin_button_get_value_as_int
+ (GTK_SPIN_BUTTON (prefs_widget->suspend_time_widget));
+
+ prefs->power_down_time = gtk_spin_button_get_value_as_int
+ (GTK_SPIN_BUTTON (prefs_widget->shut_down_time_widget));
+
+ prefs->lock = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->lock_widget));
+
+ adjustment = gtk_range_get_adjustment
+ (GTK_RANGE (prefs_widget->nice_widget));
+ prefs->nice = -adjustment->value;
+
+ prefs->verbose = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->verbose_widget));
+
+ prefs->install_colormap = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->install_cmap_widget));
+
+ prefs->fade = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->fade_widget));
+
+ prefs->unfade = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->unfade_widget));
+
+ adjustment = gtk_range_get_adjustment
+ (GTK_RANGE (prefs_widget->fade_duration_widget));
+ prefs->fade_seconds = adjustment->value;
+
+ adjustment = gtk_range_get_adjustment
+ (GTK_RANGE (prefs_widget->fade_ticks_widget));
+ prefs->fade_ticks = adjustment->value;
+
+ prefs->screensavers = prefs_widget->screensavers;
+ prefs->selection_mode = prefs_widget->selection_mode;
+}
+
+void
+prefs_widget_get_prefs (PrefsWidget *prefs_widget, Preferences *prefs)
+{
+ GtkWidget *widget = NULL;
+ GtkAdjustment *adjustment;
+ GdkVisual *visual;
+
+ prefs_widget->selection_mode = prefs->selection_mode;
+
+ switch (prefs->selection_mode) {
+ case SM_DISABLE_SCREENSAVER:
+ widget = prefs_widget->disable_screensaver_widget;
+ break;
+ case SM_BLANK_SCREEN:
+ widget = prefs_widget->blank_screen_widget;
+ break;
+ case SM_ONE_SCREENSAVER_ONLY:
+ widget = prefs_widget->one_screensaver_widget;
+ break;
+ case SM_CHOOSE_FROM_LIST:
+ widget = prefs_widget->choose_from_list_widget;
+ break;
+ case SM_CHOOSE_RANDOMLY:
+ widget = prefs_widget->choose_randomly_widget;
+ break;
+ }
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+
+ gtk_spin_button_set_value
+ (GTK_SPIN_BUTTON (prefs_widget->timeout_widget),
+ prefs->timeout);
+
+ gtk_spin_button_set_value
+ (GTK_SPIN_BUTTON (prefs_widget->cycle_length_widget),
+ prefs->cycle);
+
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->lock_widget), prefs->lock);
+
+ gtk_widget_set_sensitive (prefs_widget->time_to_lock_widget, TRUE);
+ gtk_spin_button_set_value
+ (GTK_SPIN_BUTTON (prefs_widget->time_to_lock_widget),
+ prefs->lock_timeout);
+
+ gtk_widget_set_sensitive (prefs_widget->time_to_lock_widget,
+ (gboolean) prefs->lock_timeout);
+
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->enable_timeout_widget),
+ (gboolean) prefs->lock_timeout);
+
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->pwr_manage_enable),
+ prefs->power_management);
+
+ gtk_spin_button_set_value
+ (GTK_SPIN_BUTTON (prefs_widget->standby_time_widget),
+ prefs->standby_time);
+
+ set_standby_time_sensitive (prefs_widget,
+ (gboolean) prefs->standby_time);
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->standby_monitor_toggle),
+ (gboolean) prefs->standby_time);
+
+ gtk_spin_button_set_value
+ (GTK_SPIN_BUTTON (prefs_widget->suspend_time_widget),
+ prefs->suspend_time);
+
+ set_suspend_time_sensitive (prefs_widget,
+ (gboolean) prefs->suspend_time);
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->suspend_monitor_toggle),
+ (gboolean) prefs->suspend_time);
+
+ gtk_spin_button_set_value
+ (GTK_SPIN_BUTTON (prefs_widget->shut_down_time_widget),
+ prefs->power_down_time);
+
+ set_power_down_time_sensitive (prefs_widget,
+ (gboolean) prefs->power_down_time);
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->shut_down_monitor_toggle),
+ (gboolean) prefs->power_down_time);
+
+ set_lock_controls_sensitive (prefs_widget, prefs->lock);
+
+ adjustment = gtk_range_get_adjustment
+ (GTK_RANGE (prefs_widget->nice_widget));
+ gtk_adjustment_set_value (adjustment, -prefs->nice);
+
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->verbose_widget),
+ prefs->verbose);
+
+ visual = gdk_visual_get_system ();
+
+ if (visual->type == GDK_VISUAL_GRAYSCALE ||
+ visual->type == GDK_VISUAL_PSEUDO_COLOR)
+ {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->install_cmap_widget),
+ prefs->install_colormap);
+
+ if (prefs->install_colormap) {
+ set_fade_controls_sensitive (prefs_widget, TRUE);
+
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->fade_widget),
+ prefs->fade);
+
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON
+ (prefs_widget->unfade_widget),
+ prefs->unfade);
+
+ if (prefs->fade || prefs->unfade) {
+ set_fade_scales_sensitive (prefs_widget, TRUE);
+
+ adjustment =
+ gtk_range_get_adjustment
+ (GTK_RANGE (prefs_widget->
+ fade_duration_widget));
+ gtk_adjustment_set_value
+ (adjustment, prefs->fade_seconds);
+
+ adjustment =
+ gtk_range_get_adjustment
+ (GTK_RANGE (prefs_widget->
+ fade_ticks_widget));
+ gtk_adjustment_set_value
+ (adjustment,
+ prefs->fade_ticks);
+ } else {
+ set_fade_scales_sensitive
+ (prefs_widget, FALSE);
+ }
+ } else {
+ set_fade_controls_sensitive (prefs_widget, FALSE);
+ }
+ } else {
+ gtk_widget_set_sensitive
+ (prefs_widget->install_cmap_widget, FALSE);
+
+ set_fade_controls_sensitive (prefs_widget, FALSE);
+ }
+
+ prefs_widget_set_screensavers (prefs_widget,
+ prefs->screensavers,
+ prefs->selection_mode);
+}
+
+void
+prefs_widget_set_screensavers (PrefsWidget *prefs,
+ GList *screensavers,
+ SelectionMode mode)
+{
+ GList *node;
+ gint row;
+ GtkCList *clist;
+ Screensaver *saver;
+
+ prefs->screensavers = screensavers;
+
+ clist = GTK_CLIST (prefs->screensaver_list);
+
+ gtk_clist_freeze (clist);
+
+ gtk_clist_clear (clist);
+ for (node = screensavers; node; node = node->next)
+ create_list_item (SCREENSAVER (node->data), mode, prefs);
+
+ gtk_clist_thaw (clist);
+
+ if (mode == SM_ONE_SCREENSAVER_ONLY) {
+ for (row = 0; row < clist->rows; row++) {
+ saver = gtk_clist_get_row_data (clist, row);
+ if (saver->enabled) break;
+ }
+
+ select_row (clist, row);
+ }
+}
+
+static void
+set_fade_scales_sensitive (PrefsWidget *prefs_widget, gboolean s)
+{
+ gtk_widget_set_sensitive (prefs_widget->fade_duration_label, s);
+ gtk_widget_set_sensitive (prefs_widget->fade_duration_low_label, s);
+ gtk_widget_set_sensitive (prefs_widget->fade_duration_high_label, s);
+ gtk_widget_set_sensitive (prefs_widget->fade_duration_widget, s);
+ gtk_widget_set_sensitive (prefs_widget->fade_ticks_label, s);
+ gtk_widget_set_sensitive (prefs_widget->fade_ticks_low_label, s);
+ gtk_widget_set_sensitive (prefs_widget->fade_ticks_high_label, s);
+ gtk_widget_set_sensitive (prefs_widget->fade_ticks_widget, s);
+}
+
+static void
+set_fade_controls_sensitive (PrefsWidget *prefs_widget, gboolean s)
+{
+ gtk_widget_set_sensitive (prefs_widget->fade_widget, s);
+ gtk_widget_set_sensitive (prefs_widget->unfade_widget, s);
+
+ set_fade_scales_sensitive (prefs_widget, s);
+}
+
+static void
+set_lock_controls_sensitive (PrefsWidget *prefs, gboolean s)
+{
+ gtk_widget_set_sensitive (prefs->enable_timeout_widget, s);
+
+ if (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs->enable_timeout_widget)))
+ gtk_widget_set_sensitive (prefs->time_to_lock_widget, s);
+
+ gtk_widget_set_sensitive (prefs->lock_timeout_seconds_label, s);
+}
+
+static void
+set_standby_time_sensitive (PrefsWidget *prefs_widget, gboolean s)
+{
+ gtk_widget_set_sensitive (prefs_widget->standby_time_widget, s);
+}
+
+static void
+set_suspend_time_sensitive (PrefsWidget *prefs_widget, gboolean s)
+{
+ gtk_widget_set_sensitive (prefs_widget->suspend_time_widget, s);
+}
+
+static void
+set_power_down_time_sensitive (PrefsWidget *prefs_widget, gboolean s)
+{
+ gtk_widget_set_sensitive (prefs_widget->shut_down_time_widget, s);
+}
+
+static void
+set_power_controls_sensitive (PrefsWidget *prefs_widget, gboolean s)
+{
+ gboolean value;
+
+ value = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->standby_monitor_toggle));
+ set_standby_time_sensitive (prefs_widget, s & value);
+ value = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->suspend_monitor_toggle));
+ set_suspend_time_sensitive (prefs_widget, s & value);
+ value = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (prefs_widget->shut_down_monitor_toggle));
+ set_power_down_time_sensitive (prefs_widget, s & value);
+
+ gtk_widget_set_sensitive (prefs_widget->standby_monitor_toggle, s);
+ gtk_widget_set_sensitive (prefs_widget->standby_monitor_label2, s);
+ gtk_widget_set_sensitive (prefs_widget->suspend_monitor_toggle, s);
+ gtk_widget_set_sensitive (prefs_widget->suspend_monitor_label2, s);
+ gtk_widget_set_sensitive (prefs_widget->shut_down_monitor_toggle, s);
+ gtk_widget_set_sensitive (prefs_widget->shut_down_monitor_label2, s);
+}
+
+static void
+set_all_pixmaps (PrefsWidget *prefs, SelectionMode mode)
+{
+ GtkCList *list;
+ Screensaver *saver;
+ gint i;
+
+ list = GTK_CLIST (prefs->screensaver_list);
+
+ for (i = 0; i < list->rows; i++) {
+ saver = gtk_clist_get_row_data (list, i);
+ set_pixmap (list, saver, i, mode);
+ }
+}
+
+static void
+demo_cb (GtkWidget *button, PrefsWidget *widget)
+{
+ if (!widget->selected_saver) return;
+
+ gtk_signal_emit (GTK_OBJECT (widget),
+ prefs_widget_signals[ACTIVATE_DEMO_SIGNAL]);
+ show_demo (widget->selected_saver);
+}
+
+static void
+demo_next_cb (GtkWidget *button, PrefsWidget *widget)
+{
+ gint row;
+
+ if (GTK_CLIST (widget->screensaver_list)->rows == 0) return;
+
+ if (widget->selected_saver) {
+ row = gtk_clist_find_row_from_data
+ (GTK_CLIST (widget->screensaver_list),
+ widget->selected_saver) + 1;
+ if (row >= GTK_CLIST (widget->screensaver_list)->rows)
+ row = 0;
+ } else {
+ row = 0;
+ }
+
+ select_row (GTK_CLIST (widget->screensaver_list), row);
+
+ gtk_signal_emit (GTK_OBJECT (widget),
+ prefs_widget_signals[ACTIVATE_DEMO_SIGNAL]);
+ show_demo (widget->selected_saver);
+}
+
+static void
+demo_prev_cb (GtkWidget *button, PrefsWidget *widget)
+{
+ gint row;
+
+ if (GTK_CLIST (widget->screensaver_list)->rows == 0) return;
+
+ if (widget->selected_saver) {
+ row = gtk_clist_find_row_from_data
+ (GTK_CLIST (widget->screensaver_list),
+ widget->selected_saver) - 1;
+ if (row < 0)
+ row = GTK_CLIST (widget->screensaver_list)->rows - 1;
+ } else {
+ row = GTK_CLIST (widget->screensaver_list)->rows - 1;
+ }
+
+ select_row (GTK_CLIST (widget->screensaver_list), row);
+
+ gtk_signal_emit (GTK_OBJECT (widget),
+ prefs_widget_signals[ACTIVATE_DEMO_SIGNAL]);
+ show_demo (widget->selected_saver);
+}
+
+static void
+screensaver_add_cb (GtkWidget *button, PrefsWidget *widget)
+{
+ GtkWidget *dialog;
+
+ dialog = selection_dialog_new (widget);
+
+ gtk_signal_connect (GTK_OBJECT (dialog), "ok-clicked",
+ GTK_SIGNAL_FUNC (add_select_cb), widget);
+}
+
+static void
+screensaver_remove_cb (GtkWidget *button, PrefsWidget *widget)
+{
+ GtkCList *clist;
+ Screensaver *rm;
+ gint row;
+
+ if (!widget->selected_saver) return;
+
+ rm = widget->selected_saver;
+ clist = GTK_CLIST (widget->screensaver_list);
+
+ row = gtk_clist_find_row_from_data (clist, widget->selected_saver);
+ gtk_clist_remove (GTK_CLIST (widget->screensaver_list), row);
+
+ /* Find another screensaver to select */
+ if (clist->rows == 0) {
+ widget->selected_saver = NULL;
+ gtk_widget_set_sensitive (widget->demo_button, FALSE);
+ gtk_widget_set_sensitive (widget->remove_button, FALSE);
+ gtk_widget_set_sensitive (widget->settings_button, FALSE);
+ } else {
+ if (row >= clist->rows)
+ row = clist->rows - 1;
+ widget->selected_saver =
+ gtk_clist_get_row_data (clist, row);
+ select_row (clist, row);
+ }
+
+ widget->screensavers = screensaver_remove (rm, widget->screensavers);
+ screensaver_destroy (rm);
+
+ state_changed_cb (button, widget);
+}
+
+static void
+settings_cb (GtkWidget *button, PrefsWidget *widget)
+{
+ GtkWidget *dialog;
+
+ if (!widget->selected_saver) return;
+
+ dialog = screensaver_prefs_dialog_new (widget->selected_saver);
+ gtk_signal_connect (GTK_OBJECT (dialog), "ok-clicked",
+ GTK_SIGNAL_FUNC (screensaver_prefs_ok_cb),
+ widget);
+ gtk_signal_connect (GTK_OBJECT (dialog), "demo",
+ GTK_SIGNAL_FUNC (prefs_demo_cb),
+ widget);
+ gtk_widget_show_all (dialog);
+}
+
+static void
+disable_screensaver_cb (GtkToggleButton *button, PrefsWidget *widget)
+{
+ if (gtk_toggle_button_get_active (button)) {
+ widget->selection_mode = SM_DISABLE_SCREENSAVER;
+ set_screensavers_enabled (widget, FALSE);
+ }
+
+ state_changed_cb (GTK_WIDGET (widget), widget);
+}
+
+static void
+blank_screen_selected_cb (GtkToggleButton *button, PrefsWidget *widget)
+{
+ if (gtk_toggle_button_get_active (button)) {
+ widget->selection_mode = SM_BLANK_SCREEN;
+ set_screensavers_enabled (widget, FALSE);
+ }
+
+ state_changed_cb (GTK_WIDGET (widget), widget);
+}
+
+static void
+one_screensaver_cb (GtkToggleButton *button, PrefsWidget *widget)
+{
+ if (gtk_toggle_button_get_active (button)) {
+ widget->selection_mode = SM_ONE_SCREENSAVER_ONLY;
+ set_screensavers_enabled (widget, FALSE);
+
+ if (!widget->selected_saver && widget->screensavers) {
+ widget->selected_saver =
+ SCREENSAVER
+ (widget->screensavers->data);
+ select_row (GTK_CLIST (widget->screensaver_list), 0);
+ } else {
+ widget->selected_saver->enabled = TRUE;
+ }
+ }
+
+ state_changed_cb (GTK_WIDGET (widget), widget);
+}
+
+static void
+choose_from_selected_cb (GtkToggleButton *button, PrefsWidget *widget)
+{
+ if (gtk_toggle_button_get_active (button)) {
+ widget->selection_mode = SM_CHOOSE_FROM_LIST;
+ set_all_pixmaps (widget, SM_CHOOSE_FROM_LIST);
+ }
+
+ state_changed_cb (GTK_WIDGET (widget), widget);
+}
+
+static void
+random_cb (GtkToggleButton *button, PrefsWidget *widget)
+{
+ if (gtk_toggle_button_get_active (button)) {
+ widget->selection_mode = SM_CHOOSE_RANDOMLY;
+ set_screensavers_enabled (widget, TRUE);
+ }
+
+ state_changed_cb (GTK_WIDGET (widget), widget);
+}
+
+static void
+select_saver_cb (GtkCList *list, gint row, gint column,
+ GdkEventButton *event, PrefsWidget *widget)
+{
+ Screensaver *saver;
+
+ saver = gtk_clist_get_row_data (list, row);
+
+ if (widget->selection_mode == SM_ONE_SCREENSAVER_ONLY) {
+ if (widget->selected_saver)
+ widget->selected_saver->enabled = FALSE;
+ saver->enabled = TRUE;
+ state_changed_cb (GTK_WIDGET (widget), widget);
+ }
+
+ widget->selected_saver = saver;
+
+ set_description_text (widget, screensaver_get_desc (saver));
+
+ show_preview (saver);
+
+ gtk_widget_set_sensitive (widget->demo_button, TRUE);
+ gtk_widget_set_sensitive (widget->remove_button, TRUE);
+ gtk_widget_set_sensitive (widget->settings_button, TRUE);
+
+ if (column == 0 && widget->selection_mode == SM_CHOOSE_FROM_LIST)
+ toggle_saver (widget, row, saver);
+}
+
+static void
+deselect_saver_cb (GtkCList *list, gint row, gint column,
+ GdkEventButton *event, PrefsWidget *widget)
+{
+ Screensaver *saver;
+ int r, c;
+
+ if (column == 0 && widget->selection_mode == SM_CHOOSE_FROM_LIST) {
+ gtk_clist_get_selection_info (list, event->x, event->y,
+ &r, &c);
+ if (r == row) {
+ saver = gtk_clist_get_row_data (list, row);
+ toggle_saver (widget, row, saver);
+ }
+ }
+}
+
+static void
+require_password_changed_cb (GtkCheckButton *button, PrefsWidget *widget)
+{
+ gboolean state;
+
+ state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ set_lock_controls_sensitive (widget, state);
+
+ state_changed_cb (GTK_WIDGET (button), widget);
+}
+
+static void
+lock_timeout_changed_cb (GtkCheckButton *button, PrefsWidget *widget)
+{
+ gboolean lock_timeout_enabled;
+
+ lock_timeout_enabled =
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_widget_set_sensitive (widget->time_to_lock_widget,
+ lock_timeout_enabled);
+
+ state_changed_cb (GTK_WIDGET (button), widget);
+}
+
+static void
+install_cmap_changed_cb (GtkCheckButton *button, PrefsWidget *widget)
+{
+ gboolean state;
+
+ state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ set_fade_controls_sensitive (widget, state);
+
+ state_changed_cb (GTK_WIDGET (button), widget);
+}
+
+static void
+fade_unfade_changed_cb (GtkCheckButton *button, PrefsWidget *widget)
+{
+ gboolean fade, unfade;
+
+ fade = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (widget->fade_widget));
+ unfade = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (widget->unfade_widget));
+
+ set_fade_scales_sensitive (widget, fade || unfade);
+
+ state_changed_cb (GTK_WIDGET (button), widget);
+}
+
+static void
+power_management_toggled_cb (GtkCheckButton *button, PrefsWidget *widget)
+{
+ gboolean s;
+
+ s = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ set_power_controls_sensitive (widget, s);
+
+ state_changed_cb (GTK_WIDGET (button), widget);
+}
+
+static void
+standby_monitor_toggled_cb (GtkCheckButton *button, PrefsWidget *widget)
+{
+ gboolean s;
+
+ s = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ set_standby_time_sensitive (widget, s);
+
+ state_changed_cb (GTK_WIDGET (button), widget);
+}
+
+static void
+suspend_monitor_toggled_cb (GtkCheckButton *button, PrefsWidget *widget)
+{
+ gboolean s;
+
+ s = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ set_suspend_time_sensitive (widget, s);
+
+ state_changed_cb (GTK_WIDGET (button), widget);
+}
+
+static void
+shut_down_monitor_toggled_cb (GtkCheckButton *button, PrefsWidget *widget)
+{
+ gboolean s;
+
+ s = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ set_power_down_time_sensitive (widget, s);
+
+ state_changed_cb (GTK_WIDGET (button), widget);
+}
+
+static void
+state_changed_cb (GtkWidget *widget, PrefsWidget *prefs)
+{
+ gtk_signal_emit (GTK_OBJECT (prefs),
+ prefs_widget_signals[STATE_CHANGED_SIGNAL]);
+}
+
+static void
+prefs_demo_cb (GtkWidget *widget, PrefsWidget *prefs_widget)
+{
+ gtk_signal_emit (GTK_OBJECT (prefs_widget),
+ prefs_widget_signals[ACTIVATE_DEMO_SIGNAL]);
+}
+
+static void
+add_select_cb (GtkWidget *widget, Screensaver *saver,
+ PrefsWidget *prefs_widget)
+{
+ gint row;
+
+ prefs_widget->screensavers =
+ screensaver_add (saver, prefs_widget->screensavers);
+
+ row = create_list_item (saver, prefs_widget->selection_mode,
+ prefs_widget);
+ select_row (GTK_CLIST (prefs_widget->screensaver_list), row);
+
+ prefs_widget->selected_saver = saver;
+
+ settings_cb (widget, prefs_widget);
+}
+
+static void
+screensaver_prefs_ok_cb (ScreensaverPrefsDialog *dialog,
+ PrefsWidget *widget)
+{
+ gint row;
+
+ if (dialog->saver == widget->selected_saver) {
+ show_preview (dialog->saver);
+ }
+
+ row = gtk_clist_find_row_from_data
+ (GTK_CLIST (widget->screensaver_list), dialog->saver);
+ gtk_clist_set_text (GTK_CLIST (widget->screensaver_list),
+ row, 1, dialog->saver->label);
+ gtk_clist_sort (GTK_CLIST (widget->screensaver_list));
+
+ row = gtk_clist_find_row_from_data
+ (GTK_CLIST (widget->screensaver_list), dialog->saver);
+ gtk_clist_moveto (GTK_CLIST (widget->screensaver_list),
+ row, 0, 0.5, 0);
+ state_changed_cb (GTK_WIDGET (widget), widget);
+}
+
+static void
+set_description_text (PrefsWidget *widget, gchar *description)
+{
+ guint length;
+
+ length = strlen (description);
+
+ gtk_text_freeze (GTK_TEXT (widget->description));
+ gtk_text_set_point (GTK_TEXT (widget->description), 0);
+ length = gtk_text_get_length (GTK_TEXT (widget->description));
+ gtk_text_forward_delete (GTK_TEXT (widget->description), length);
+ gtk_text_insert (GTK_TEXT (widget->description),
+ NULL, NULL, NULL, description, strlen (description));
+ gtk_text_set_point (GTK_TEXT (widget->description), 0);
+ gtk_text_thaw (GTK_TEXT (widget->description));
+}
+
+static gint
+create_list_item (Screensaver *saver, SelectionMode mode,
+ PrefsWidget *prefs_widget)
+{
+ char *text[2];
+ gint row;
+
+ text[0] = NULL; text[1] = saver->label;
+ row = gtk_clist_prepend (GTK_CLIST (prefs_widget->screensaver_list),
+ text);
+ gtk_clist_set_row_data (GTK_CLIST (prefs_widget->screensaver_list),
+ row, saver);
+ set_pixmap (GTK_CLIST (prefs_widget->screensaver_list), saver,
+ row, mode);
+
+ return row;
+}
+
+static void
+set_screensavers_enabled (PrefsWidget *widget, gboolean s)
+{
+ GList *node;
+
+ for (node = widget->screensavers; node; node = node->next)
+ SCREENSAVER (node->data)->enabled = s;
+
+ set_all_pixmaps (widget, widget->selection_mode);
+}
+
+static void
+set_pixmap (GtkCList *clist, Screensaver *saver, gint row, SelectionMode mode)
+{
+ GdkPixbuf *pixbuf;
+ GdkPixmap *pixmap;
+ GdkBitmap *bitmap;
+ static GdkPixmap *checked_pixmap = NULL, *unchecked_pixmap = NULL;
+ static GdkPixmap *checked_disabled_pixmap = NULL;
+ static GdkPixmap *unchecked_disabled_pixmap = NULL;
+ static GdkBitmap *checked_bitmap = NULL, *unchecked_bitmap = NULL;
+ static GdkBitmap *checked_disabled_bitmap = NULL;
+ static GdkBitmap *unchecked_disabled_bitmap = NULL;
+
+ if (mode == SM_CHOOSE_FROM_LIST && saver->enabled) {
+ if (!checked_pixmap) {
+ pixbuf = gdk_pixbuf_new_from_xpm_data (checked_xpm);
+ gdk_pixbuf_render_pixmap_and_mask
+ (pixbuf, &checked_pixmap,
+ &checked_bitmap, 1);
+ gdk_pixbuf_unref (pixbuf);
+ gdk_pixmap_ref (checked_pixmap);
+ gdk_bitmap_ref (checked_bitmap);
+ }
+ pixmap = checked_pixmap;
+ bitmap = checked_bitmap;
+ }
+ else if (mode == SM_CHOOSE_FROM_LIST && !saver->enabled) {
+ if (!unchecked_pixmap) {
+ pixbuf = gdk_pixbuf_new_from_xpm_data (unchecked_xpm);
+ gdk_pixbuf_render_pixmap_and_mask
+ (pixbuf, &unchecked_pixmap,
+ &unchecked_bitmap, 1);
+ gdk_pixbuf_unref (pixbuf);
+ gdk_pixmap_ref (unchecked_pixmap);
+ gdk_bitmap_ref (unchecked_bitmap);
+ }
+ pixmap = unchecked_pixmap;
+ bitmap = unchecked_bitmap;
+ }
+ else if (mode == SM_CHOOSE_RANDOMLY) {
+ if (!checked_disabled_pixmap) {
+ pixbuf = gdk_pixbuf_new_from_xpm_data
+ (checked_disabled_xpm);
+ gdk_pixbuf_render_pixmap_and_mask
+ (pixbuf, &checked_disabled_pixmap,
+ &checked_disabled_bitmap, 1);
+ gdk_pixbuf_unref (pixbuf);
+ gdk_pixmap_ref (checked_disabled_pixmap);
+ gdk_bitmap_ref (checked_disabled_bitmap);
+ }
+ pixmap = checked_disabled_pixmap;
+ bitmap = checked_disabled_bitmap;
+ } else {
+ if (!unchecked_disabled_pixmap) {
+ pixbuf = gdk_pixbuf_new_from_xpm_data
+ (unchecked_disabled_xpm);
+ gdk_pixbuf_render_pixmap_and_mask
+ (pixbuf, &unchecked_disabled_pixmap,
+ &unchecked_disabled_bitmap, 1);
+ gdk_pixbuf_unref (pixbuf);
+ gdk_pixmap_ref (unchecked_disabled_pixmap);
+ gdk_bitmap_ref (unchecked_disabled_bitmap);
+ }
+ pixmap = unchecked_disabled_pixmap;
+ bitmap = unchecked_disabled_bitmap;
+ }
+
+ gtk_clist_set_pixmap (clist, row, 0, pixmap, bitmap);
+}
+
+static void
+toggle_saver (PrefsWidget *widget, gint row, Screensaver *saver)
+{
+ saver->enabled = !saver->enabled;
+
+ set_pixmap (GTK_CLIST (widget->screensaver_list),
+ saver, row, SM_CHOOSE_FROM_LIST);
+
+ state_changed_cb (GTK_WIDGET (widget), widget);
+}
+
+static void
+select_row (GtkCList *clist, gint row)
+{
+ gtk_clist_select_row (clist, row, 1);
+ if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_FULL)
+ gtk_clist_moveto (clist, row, 0, 0.5, 0);
+}
diff --git a/capplets/screensaver/prefs-widget.h b/capplets/screensaver/prefs-widget.h
new file mode 100644
index 000000000..f81a96d67
--- /dev/null
+++ b/capplets/screensaver/prefs-widget.h
@@ -0,0 +1,128 @@
+/* -*- mode: c; style: linux -*- */
+
+/* prefs-widget.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __PREFS_WIDGET_H
+#define __PREFS_WIDGET_H
+
+#include <gtk/gtk.h>
+
+#include "preferences.h"
+
+#define PREFS_WIDGET(obj) GTK_CHECK_CAST (obj, prefs_widget_get_type (), PrefsWidget)
+#define PREFS_WIDGET_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, prefs_widget_get_type (), PrefsWidgetClass)
+#define IS_PREFS_WIDGET(obj) GTK_CHECK_TYPE (obj, prefs_widget_get_type ())
+
+typedef struct _PrefsWidget PrefsWidget;
+typedef struct _PrefsWidgetClass PrefsWidgetClass;
+
+struct _PrefsWidget
+{
+ GtkNotebook notebook;
+
+ GtkWidget *disable_screensaver_widget;
+ GtkWidget *blank_screen_widget;
+ GtkWidget *one_screensaver_widget;
+ GtkWidget *choose_from_list_widget;
+ GtkWidget *choose_randomly_widget;
+
+ GtkWidget *screensaver_list;
+
+ GtkWidget *demo_button;
+ GtkWidget *remove_button;
+ GtkWidget *settings_button;
+
+ GtkWidget *preview_window;
+ GtkWidget *description;
+
+ GtkObject *timeout_widget_adj;
+ GtkWidget *timeout_widget;
+ GtkObject *cycle_length_widget_adj;
+ GtkWidget *cycle_length_widget;
+
+ GtkWidget *lock_widget;
+ GtkWidget *enable_timeout_widget;
+ GtkObject *time_to_lock_widget_adj;
+ GtkWidget *time_to_lock_widget;
+ GtkWidget *lock_timeout_seconds_label;
+ GtkWidget *lock_vts_widget;
+ GtkWidget *pwr_manage_enable;
+
+ GtkWidget *standby_monitor_toggle;
+ GtkObject *standby_time_widget_adj;
+ GtkWidget *standby_time_widget;
+ GtkWidget *standby_monitor_label2;
+
+ GtkWidget *suspend_monitor_toggle;
+ GtkObject *suspend_time_widget_adj;
+ GtkWidget *suspend_time_widget;
+ GtkWidget *suspend_monitor_label2;
+
+ GtkWidget *shut_down_monitor_toggle;
+ GtkObject *shut_down_time_widget_adj;
+ GtkWidget *shut_down_time_widget;
+ GtkWidget *shut_down_monitor_label2;
+
+ GtkWidget *nice_widget;
+ GtkWidget *verbose_widget;
+
+ GtkWidget *effects_frame;
+ GtkWidget *install_cmap_widget;
+ GtkWidget *fade_widget;
+ GtkWidget *unfade_widget;
+ GtkWidget *fade_duration_label;
+ GtkWidget *fade_ticks_widget;
+ GtkWidget *fade_ticks_label;
+ GtkWidget *fade_duration_widget;
+ GtkWidget *fade_duration_high_label;
+ GtkWidget *fade_ticks_high_label;
+ GtkWidget *fade_duration_low_label;
+ GtkWidget *fade_ticks_low_label;
+
+ GList *screensavers;
+ Screensaver *selected_saver;
+
+ /* Cached preferences */
+ SelectionMode selection_mode;
+};
+
+struct _PrefsWidgetClass
+{
+ GtkNotebookClass notebook_class;
+
+ void (*state_changed) (PrefsWidget *widget);
+ void (*activate_demo) (PrefsWidget *widget);
+};
+
+guint prefs_widget_get_type (void);
+
+GtkWidget *prefs_widget_new (void);
+
+void prefs_widget_get_prefs (PrefsWidget *prefs_widget,
+ Preferences *prefs);
+void prefs_widget_store_prefs (PrefsWidget *prefs_widget,
+ Preferences *prefs);
+void prefs_widget_set_screensavers (PrefsWidget *prefs_widget,
+ GList *screensavers,
+ SelectionMode mode);
+
+#endif /* __PREFS_WIDGET_H */
diff --git a/capplets/screensaver/preview.c b/capplets/screensaver/preview.c
new file mode 100644
index 000000000..039679743
--- /dev/null
+++ b/capplets/screensaver/preview.c
@@ -0,0 +1,322 @@
+/* -*- mode: c; style: linux -*- */
+
+/* preview.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gnome.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include <X11/Xatom.h>
+
+#include "preview.h"
+
+static GtkWidget *preview_window;
+static pid_t preview_pid;
+static int timeout_id;
+
+#if 0
+
+/* DEBUG FUNCTION */
+static void
+print_args (char **args)
+{
+ int i;
+
+ printf ("Command line:\n");
+ for (i = 0; args[i]; i++) {
+ printf ("%s ", args[i]);
+ }
+ printf ("\n");
+}
+
+#endif
+
+void
+set_preview_window (GtkWidget *widget)
+{
+ preview_window = widget;
+}
+
+static char **
+strip_arg (char **args, char *arg)
+{
+ int i, j, arg_len;
+
+ arg_len = strlen (arg);
+
+ for (i = 0; args[i]; i++) {
+ if (!strncmp (args[i], arg, arg_len)) {
+ for (j = i; args[j]; j++)
+ args[j] = args[j + 1];
+ i--;
+ }
+ }
+
+ return args;
+}
+
+static void
+setup_path (void)
+{
+ char *path, *newpath;
+
+ path = getenv ("PATH");
+ newpath = g_strconcat (path, ":/usr/X11R6/lib/xscreensaver", NULL);
+ setenv ("PATH", newpath, TRUE);
+}
+
+/* Warning: memory leaks, please do not use except in a separate
+ * process
+ */
+
+static char **
+add_window_arg (char **args, GdkWindow *window)
+{
+ int i;
+ char *x_window_id;
+
+ for (i = 0; args[i]; i++);
+
+ x_window_id =
+ g_strdup_printf ("0x%x",
+ (guint) GDK_WINDOW_XWINDOW (window));
+
+ args = g_renew (char *, args, i + 4);
+ args[i] = "-window";
+ args[i + 1] = "-window-id";
+ args[i + 2] = x_window_id;
+ args[i + 3] = NULL;
+
+ return args;
+}
+
+/* show_screensaver
+ *
+ * Given a GdkWindow in which to render and a particular screensaver,
+ * fork off a process and start the screensaver.
+ */
+
+static void
+show_screensaver (GdkWindow *window, Screensaver *saver, pid_t *pid)
+{
+ char **args;
+
+ *pid = fork ();
+
+ if (*pid == (pid_t) -1) {
+ perror ("fork");
+ abort ();
+ }
+ else if (*pid == 0) {
+ nice (20); /* Very low priority */
+
+ args = g_strsplit (saver->command_line, " ", -1);
+ args = strip_arg (args, "-root");
+ args = add_window_arg (args, window);
+
+ setup_path ();
+
+ if (execvp (args[0], args) == -1) {
+ perror ("execv");
+ abort ();
+ }
+
+ exit (1);
+ }
+}
+
+static gint
+show_screensaver_timeout (void)
+{
+ GdkPixbuf *pixbuf;
+ int ret;
+
+ ret = waitpid (preview_pid, NULL, WNOHANG);
+
+ if (ret == -1) {
+ g_error ("waitpid: %s", g_strerror (errno));
+ }
+ else if (ret > 0) {
+ pixbuf = gdk_pixbuf_new_from_file
+ (GNOME_ICONDIR "/no-hack.png");
+ gdk_pixbuf_render_to_drawable
+ (pixbuf, (GdkDrawable *) preview_window->window,
+ preview_window->style->fg_gc[0], 0, 0, 0, 0,
+ 300, 250, GDK_RGB_DITHER_NONE, 0, 0);
+ }
+
+ timeout_id = 0;
+
+ return FALSE;
+}
+
+void
+show_preview (Screensaver *saver)
+{
+ /* Note: kill this next line for a very interesting effect ... */
+ close_preview ();
+ if (!saver->command_line) return;
+ show_screensaver (preview_window->window, saver, &preview_pid);
+ timeout_id =
+ gtk_timeout_add (500, (GtkFunction)
+ show_screensaver_timeout, NULL);
+}
+
+void
+close_preview (void)
+{
+ if (timeout_id) {
+ gtk_timeout_remove (timeout_id);
+ timeout_id = 0;
+ }
+
+ if (preview_pid) {
+ kill (preview_pid, SIGTERM);
+ preview_pid = 0;
+ }
+}
+
+/* Ick... */
+
+static GdkWindow *
+gdk_window_new_from_xwindow (Window xwindow)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *window_priv;
+
+ window_priv = g_new0 (GdkWindowPrivate, 1);
+ window = (GdkWindow *) window_priv;
+ window_priv->xdisplay = gdk_display;
+ window_priv->xwindow = xwindow;
+ window_priv->destroyed = FALSE;
+
+ return window;
+}
+
+static GdkWindow *
+find_xscreensaver_window (Display *dpy)
+{
+ static Atom XA_SCREENSAVER;
+ GdkAtom actual_type;
+ gint actual_format;
+ Window root, parent, *children;
+ Window root_ret;
+ GdkWindow *ret;
+ gint number_children, i;
+ unsigned long nitems, bytes_after;
+ gboolean found;
+ unsigned char *data;
+ gint x_error;
+
+ if (!XA_SCREENSAVER)
+ XA_SCREENSAVER =
+ XInternAtom (dpy, "_SCREENSAVER_VERSION", FALSE);
+
+ gdk_error_trap_push ();
+
+ root = GDK_ROOT_WINDOW ();
+
+ XQueryTree (dpy, DefaultRootWindow (dpy),
+ &root_ret, &parent, &children, &number_children);
+
+ if (root_ret != root) abort ();
+ if (parent) abort ();
+ if (!children || !number_children) return NULL;
+
+ for (i = 0; i < number_children; i++) {
+ found = XGetWindowProperty (dpy, children[i],
+ XA_SCREENSAVER,
+ 0, 0, FALSE, XA_STRING,
+ &actual_type,
+ &actual_format, &nitems,
+ &bytes_after, &data);
+ free (data);
+
+ if (actual_type != None) {
+ ret = gdk_window_new_from_xwindow (children[i]);
+ free (children);
+ return ret;
+ }
+ }
+
+ free (children);
+
+ gdk_flush ();
+ x_error = gdk_error_trap_pop ();
+
+ if (x_error && x_error != BadWindow)
+ g_error ("X error");
+
+ return NULL;
+}
+
+void
+show_demo (Screensaver *saver)
+{
+ static GdkAtom demo_atom, xscreensaver_atom;
+ GdkWindow *xscreensaver_window;
+ GdkEventClient *event;
+
+ if (!demo_atom)
+ demo_atom = gdk_atom_intern ("DEMO", FALSE);
+
+ if (!xscreensaver_atom)
+ xscreensaver_atom = gdk_atom_intern ("SCREENSAVER", FALSE);
+
+ xscreensaver_window = find_xscreensaver_window (gdk_display);
+
+ if (!xscreensaver_window)
+ g_error ("Could not find XScreensaver window");
+
+ event = g_new0 (GdkEventClient, 1);
+ event->type = GDK_CLIENT_EVENT;
+ event->window = xscreensaver_window;
+ event->message_type = xscreensaver_atom;
+ event->data_format = 32;
+ event->data.l[0] = demo_atom;
+ event->data.l[1] = 300; /* XA_DEMO protocol version number */
+ event->data.l[2] = saver->id + 1;
+
+ gdk_event_send_client_message
+ ((GdkEvent *) event, GDK_WINDOW_XWINDOW (xscreensaver_window));
+
+ gdk_flush ();
+ g_free (xscreensaver_window);
+ g_free (event);
+}
+
+void
+close_demo (void)
+{
+}
diff --git a/capplets/screensaver/preview.h b/capplets/screensaver/preview.h
new file mode 100644
index 000000000..5380f6475
--- /dev/null
+++ b/capplets/screensaver/preview.h
@@ -0,0 +1,39 @@
+/* -*- mode: c; style: linux -*- */
+
+/* preview.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __PREVIEW_H
+#define __PREVIEW_H
+
+#include <gtk/gtk.h>
+
+#include "preferences.h"
+
+void set_preview_window (GtkWidget *widget);
+
+void show_preview (Screensaver *saver);
+void close_preview (void);
+
+void show_demo (Screensaver *saver);
+void close_demo (void);
+
+#endif /* __PREVIEW_H */
diff --git a/capplets/screensaver/rc-parse.c b/capplets/screensaver/rc-parse.c
new file mode 100644
index 000000000..633562e11
--- /dev/null
+++ b/capplets/screensaver/rc-parse.c
@@ -0,0 +1,601 @@
+/* -*- mode: c; style: linux -*- */
+
+/* rc-parse.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ * Parts written by Jamie Zawinski <jwz@jwz.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <glib.h>
+#include <gnome.h>
+
+#include "rc-parse.h"
+#include "preferences.h"
+#include "resources.h"
+
+/* Adapted from xscreensaver 3.24 utils/resources.c line 57 ... */
+
+gboolean
+parse_boolean_resource (char *res)
+{
+ if (!g_strncasecmp (res, "on", 2) ||
+ !g_strncasecmp (res, "true", 4) ||
+ !g_strncasecmp (res, "yes", 3))
+ return TRUE;
+
+ if (!g_strncasecmp (res, "off", 3) ||
+ !g_strncasecmp (res, "false", 5) ||
+ !g_strncasecmp (res, "no", 2))
+ return FALSE;
+
+ g_warning ("invalid boolean value: %s", res);
+ return FALSE;
+}
+
+int
+parse_integer_resource (char *res)
+{
+ int val;
+ char c;
+
+ while (*res && *res <= ' ') res++; /* skip whitespace */
+
+ if (res[0] == '0' && (res[1] == 'x' || res[1] == 'X')) {
+ if (sscanf (res + 2, "%x %c", &val, &c) == 1)
+ return val;
+ } else {
+ if (sscanf (res, "%d %c", &val, &c) == 1)
+ return val;
+ }
+
+ g_warning ("invalid integer value: %s", res);
+
+ return 0;
+}
+
+double
+parse_float_resource (char *res)
+{
+ double val;
+ char c;
+
+ if (sscanf (res, " %lf %c", &val, &c) == 1)
+ return val;
+
+ g_warning ("invalid float value: %s", res);
+
+ return 0.0;
+}
+
+static int
+parse_time (const char *string, gboolean seconds_default_p, gboolean silent_p)
+{
+ unsigned int h, m, s;
+ char c;
+
+ if (3 == sscanf (string, " %u : %2u : %2u %c", &h, &m, &s, &c))
+ ;
+ else if (2 == sscanf (string, " : %2u : %2u %c", &m, &s, &c) ||
+ 2 == sscanf (string, " %u : %2u %c", &m, &s, &c))
+ h = 0;
+ else if (1 == sscanf (string, " : %2u %c", &s, &c))
+ h = m = 0;
+ else if (1 == sscanf (string, " %u %c",
+ (seconds_default_p ? &s : &m), &c))
+ {
+ h = 0;
+ if (seconds_default_p) m = 0;
+ else s = 0;
+ } else {
+ if (! silent_p)
+ g_warning ("invalid time interval specification \"%s\".\n",
+ string);
+ return -1;
+ }
+ if (s >= 60 && (h != 0 || m != 0)) {
+ if (! silent_p)
+ g_warning ("seconds > 59 in \"%s\".\n", string);
+ return -1;
+ }
+ if (m >= 60 && h > 0) {
+ if (! silent_p)
+ g_warning ("minutes > 59 in \"%s\".\n", string);
+ return -1;
+ }
+
+ return ((h * 60 * 60) + (m * 60) + s);
+}
+
+guint
+parse_time_resource (char *res, gboolean sec_p)
+{
+ int val;
+
+ val = parse_time (res, sec_p, FALSE);
+
+ return (val < 0 ? 0 : val);
+}
+
+guint
+parse_seconds_resource (char *res)
+{
+ return parse_time_resource (res, TRUE);
+}
+
+gdouble
+parse_minutes_resource (char *res)
+{
+ return (gdouble) parse_time_resource (res, FALSE) / 60.0;
+}
+
+/*****************************************************************************/
+/* Parsing the screensaver resource */
+/*****************************************************************************/
+
+/* Adapted from xscreensaver 3.24 driver/demo-Gtk.c line 944 ... */
+
+static char *
+get_settings_name (const char *command_line)
+{
+ char *s = g_strdup (command_line);
+ char *s2;
+
+ for (s2 = s; *s2; s2++) /* truncate at first whitespace */
+ if (isspace (*s2)) {
+ *s2 = 0;
+ break;
+ }
+
+ s2 = g_basename (s);
+
+ if (strlen (s2) > 50) /* Truncate after 50 characters */
+ s2[50] = '\0';
+
+ return s2;
+}
+
+static char *
+get_label (char *name)
+{
+ char *s, *label;
+
+ label = screensaver_get_label_from_xrdb (name);
+ if (label) return label;
+
+ label = g_strdup (name);
+
+ for (s = label; *s; s++) /* if it has any capitals, return it */
+ if (*s >= 'A' && *s <= 'Z')
+ return s;
+
+ if (label[0] >= 'a' && label[0] <= 'z') /* else cap it */
+ label[0] -= 'a'-'A';
+ if (label[0] == 'X' && label[1] >= 'a' && label[1] <= 'z')
+ label[1] -= 'a'-'A';
+
+ return label;
+}
+
+/* WARNING: Looking at the following code is likely to cause seizures ... */
+
+static gchar *
+strip_whitespace (const gchar *line)
+{
+ gchar *line2, *s;
+
+ s = line2 = g_new0 (char, strlen (line));
+
+ while (*line) {
+ if (!isspace (*line))
+ *line2++ = *line++;
+ else if (*++line && !isspace (*line))
+ *line2++ = ' ';
+ }
+
+ return s;
+}
+
+/* command_exists
+ *
+ * Given a command line, determines if the command may be executed
+ */
+
+static gboolean
+command_exists (char *command)
+{
+ char *program, *fullpath;
+ static char **path_dirs;
+ int i;
+ gboolean ret;
+
+ program = g_strdup (command);
+
+ /* Truncate at first whitespace */
+ for (i = 0; program[i] && !isspace (program[i]); i++);
+ program[i] = '\0';
+
+ /* If this is a complete path, then just stat it */
+ if (strchr (program, '/')) {
+ if (g_file_test (program, G_FILE_TEST_ISFILE))
+ ret = TRUE;
+ else
+ ret = FALSE;
+
+ g_free (program);
+
+ return ret;
+ }
+
+ /* Check the /usr/X11R6/lib/xscreensaver/ directory */
+ fullpath = g_concat_dir_and_file ("/usr/X11R6/lib/xscreensaver",
+ program);
+ if (g_file_test (fullpath, G_FILE_TEST_ISFILE)) {
+ g_free (program);
+ g_free (fullpath);
+ return TRUE;
+ }
+ g_free (fullpath);
+
+ fullpath = gnome_is_program_in_path (program);
+ if (fullpath)
+ ret = TRUE;
+ else
+ ret = FALSE;
+
+ if (fullpath) g_free (fullpath);
+ g_free (program);
+
+ return ret;
+}
+
+/* Adapted from xscreensaver 3.24 driver/prefs.c line 900 ...
+ *
+ * Parsing the programs resource.
+ */
+
+static Screensaver *
+parse_screensaver (const char *line)
+{
+ Screensaver *h;
+ const char *s;
+
+ h = screensaver_new ();
+
+ while (isspace(*line)) line++; /* skip whitespace */
+ if (*line == '-') { /* handle "-" */
+ h->enabled = FALSE;
+ line++;
+ while (isspace(*line)) line++; /* skip whitespace */
+ }
+
+ s = line; /* handle "visual:" */
+ while (*line && *line != ':' && *line != '"' && !isspace(*line))
+ line++;
+
+ if (*line != ':')
+ line = s;
+ else {
+ h->visual = g_strndup (s, line - s);
+ if (*line == ':') line++; /* skip ":" */
+ while (isspace(*line)) line++; /* skip whitespace */
+ }
+
+ if (*line == '"') { /* handle "name" */
+ line++;
+ s = line;
+ while (*line && *line != '"') line++;
+ h->label = g_strndup (s, line - s);
+ if (*line == '"') line++; /* skip "\"" */
+ while (isspace(*line)) line++; /* skip whitespace */
+ }
+
+ h->command_line = strip_whitespace (line);
+ if (!command_exists (h->command_line)) {
+ screensaver_destroy (h);
+ return NULL;
+ }
+
+ h->name = get_settings_name (h->command_line);
+ if (!h->label) h->label = get_label (h->name);
+
+ return h;
+}
+
+/* Adapted from xscreensaver 3.24 driver/prefs.c line 1076 ... */
+
+GList *
+parse_screensaver_list (char *list)
+{
+ int start = 0;
+ int end = 0;
+ int size = 0;
+ int count = 0;
+
+ int number_enabled = 0;
+ int total = 0;
+
+ GList *list_head = NULL, *list_tail = NULL;
+ Screensaver *saver;
+
+ size = strlen (list);
+
+ /* Iterate over the lines in `d' (the string with newlines)
+ and make new strings to stuff into the `screenhacks' array.
+ */
+
+ while (start < size) {
+ /* skip forward over whitespace. */
+ while (list[start] == ' ' ||
+ list[start] == '\t' ||
+ list[start] == '\n')
+ start++;
+
+ /* skip forward to newline or end of string. */
+ end = start;
+ while (list[end] != 0 && list[end] != '\n')
+ end++;
+
+ /* null terminate. */
+ list[end] = 0;
+
+ saver = parse_screensaver (list + start);
+ if (saver) {
+ saver->id = count++;
+ if (saver->enabled) number_enabled++;
+ total++;
+ list_tail = g_list_append (list_tail, saver);
+ if (!list_head) list_head = list_tail;
+ list_tail = g_list_last (list_tail);
+ saver->link = list_tail;
+ }
+
+ start = end + 1;
+ }
+
+ return list_head;
+}
+
+gchar *
+write_boolean (gboolean value)
+{
+ return value ? g_strdup ("True") : g_strdup ("False");
+}
+
+gchar *
+write_integer (gint value)
+{
+ return g_strdup_printf ("%d", value);
+}
+
+gchar *
+write_float (gfloat value)
+{
+ return g_strdup_printf ("%f", value);
+}
+
+gchar *
+write_time (time_t value)
+{
+ return g_strdup_printf ("%u:%02u:%02u",
+ (guint) value / 60 / 60,
+ (guint) (value / 60) % 60,
+ (guint) value % 60);
+}
+
+gchar *
+write_seconds (gint value)
+{
+ return write_time ((time_t) value);
+}
+
+gchar *
+write_minutes (gdouble value)
+{
+ return write_time ((time_t) (value * 60.0));
+}
+
+
+/* From xscreensaver 3.24 driver/prefs.c line 963 ... */
+
+static char *
+format_command (const char *cmd, gboolean wrap_p)
+{
+ int tab = 30;
+ int col = tab;
+ char *cmd2 = g_new0 (char, 2 * (strlen (cmd) + 1));
+ const char *in = cmd;
+ char *out = cmd2;
+
+ while (*in) {
+ /* shrink all whitespace to one space, for the benefit
+ * of the "demo" mode display. We only do this when
+ * we can easily tell that the whitespace is not
+ * significant (no shell metachars).
+ */
+ switch (*in) {
+ case '\'': case '"': case '`': case '\\':
+ /* Metachars are scary. Copy the rest of the
+ * line unchanged. */
+ while (*in)
+ *out++ = *in++, col++;
+ break;
+
+ case ' ': case '\t':
+ /* Squeeze all other whitespace down to one space. */
+ while (*in == ' ' || *in == '\t')
+ in++;
+ *out++ = ' ', col++;
+ break;
+
+ default:
+ /* Copy other chars unchanged. */
+ *out++ = *in++, col++;
+ break;
+ }
+ }
+
+ *out = 0;
+
+ /* Strip trailing whitespace */
+ while (out > cmd2 && isspace (out[-1]))
+ *(--out) = 0;
+
+ return cmd2;
+}
+
+/* From xscreensaver 3.24 driver/prefs.c line 415 ... */
+
+static char *
+stab_to (char *out, int from, int to)
+{
+ int tab_width = 8;
+ int to_mod = (to / tab_width) * tab_width;
+
+ while (from < to_mod) {
+ *out++ = '\t';
+ from = (((from / tab_width) + 1) * tab_width);
+ }
+
+ while (from < to) {
+ *out++ = ' ';
+ from++;
+ }
+
+ return out;
+}
+
+int
+string_columns (const char *string, int length, int start)
+{
+ int tab_width = 8;
+ int col = start;
+ const char *end = string + length;
+
+ while (string < end) {
+ if (*string == '\n')
+ col = 0;
+ else if (*string == '\t')
+ col = (((col / tab_width) + 1) * tab_width);
+ else
+ col++;
+ string++;
+ }
+
+ return col;
+}
+
+/* From xscreensaver 3.24 driver/prefs.c line 1009 ... */
+
+static char *
+format_hack (Screensaver *saver, gboolean wrap_p)
+{
+ int tab = 32;
+ int size = (2 * (strlen(saver->command_line) +
+ (saver->visual ? strlen(saver->visual) : 0) +
+ (saver->name ? strlen(saver->name) : 0) +
+ tab));
+ char *h2 = g_new (char, size);
+ char *out = h2;
+ char *s;
+ int col = 0;
+
+ if (!saver->enabled) *out++ = '-'; /* write disabled flag */
+
+ if (saver->visual && *saver->visual) { /* write visual name */
+ if (saver->enabled) *out++ = ' ';
+ *out++ = ' ';
+ strcpy (out, saver->visual);
+ out += strlen (saver->visual);
+ *out++ = ':';
+ *out++ = ' ';
+ }
+
+ *out = 0;
+ col = string_columns (h2, strlen (h2), 0);
+
+ if (saver->label && *saver->label) { /* write pretty name */
+ int L = (strlen (saver->label) + 2);
+ if (L + col < tab)
+ out = stab_to (out, col, tab - L - 2);
+ else
+ *out++ = ' ';
+ *out++ = '"';
+ strcpy (out, saver->label);
+ out += strlen (saver->label);
+ *out++ = '"';
+ *out = 0;
+
+ col = string_columns (h2, strlen (h2), 0);
+ if (wrap_p && col >= tab) {
+ out = stab_to (out, col, 77);
+ *out += strlen(out);
+ }
+ else
+ *out++ = ' ';
+
+ if (out >= h2+size) abort();
+ }
+
+ *out = 0;
+ col = string_columns (h2, strlen (h2), 0);
+ out = stab_to (out, col, tab); /* indent */
+
+ if (out >= h2+size) abort();
+ s = format_command (saver->command_line, wrap_p);
+ strcpy (out, s);
+ out += strlen (s);
+ g_free (s);
+ *out = 0;
+
+ return h2;
+}
+
+gchar *
+write_screensaver_list (GList *screensavers)
+{
+ GList *node;
+ Screensaver *saver;
+ GString *hack_string;
+ gchar *str;
+
+ hack_string = g_string_new (NULL);
+ node = screensavers;
+
+ while (node) {
+ saver = SCREENSAVER (node->data);
+ str = format_hack (saver, TRUE);
+ g_string_append (hack_string, str);
+ g_string_append (hack_string, "\n");
+ node = node->next;
+ g_free (str);
+ }
+
+ str = hack_string->str;
+ g_string_free (hack_string, FALSE);
+ return str;
+}
diff --git a/capplets/screensaver/rc-parse.h b/capplets/screensaver/rc-parse.h
new file mode 100644
index 000000000..f9244ceb7
--- /dev/null
+++ b/capplets/screensaver/rc-parse.h
@@ -0,0 +1,48 @@
+/* -*- mode: c; style: linux -*- */
+
+/* rc-parse.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __RC_PARSE_H
+#define __RC_PARSE_H
+
+#include <glib.h>
+
+gboolean parse_boolean_resource (char *res);
+int parse_integer_resource (char *res);
+double parse_float_resource (char *res);
+guint parse_time_resource (char *res, gboolean sec);
+guint parse_seconds_resource (char *res);
+gdouble parse_minutes_resource (char *res);
+GList *parse_screensaver_list (char *list);
+
+gchar *write_boolean (gboolean value);
+gchar *write_integer (gint value);
+gchar *write_float (gfloat value);
+gchar *write_time (time_t value);
+gchar *write_seconds (gint value);
+gchar *write_minutes (gdouble value);
+gchar *write_screensaver_list (GList *screensavers);
+
+/* Internal; used by pref-file.c and rc-parse.c only */
+int string_columns (const char *string, int length, int start);
+
+#endif /* __RC_PARSE_H */
diff --git a/capplets/screensaver/resources.c b/capplets/screensaver/resources.c
new file mode 100644
index 000000000..483e7f156
--- /dev/null
+++ b/capplets/screensaver/resources.c
@@ -0,0 +1,138 @@
+/* -*- mode: c; style: linux -*- */
+
+/* resources.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ * Parts written by Jamie Zawinski <jwz@jwz.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+#include <gdk/gdkprivate.h>
+
+#include "resources.h"
+#include "rc-parse.h"
+
+static char *defaults[] = {
+#include "XScreenSaver_ad.h"
+ 0
+};
+
+static XrmDatabase db;
+
+void
+init_resource_database (int argc, char **argv)
+{
+ XtAppContext app;
+ Widget toplevel_shell;
+ Display *dpy;
+
+ /* From xscreensaver 3.24 display/demo-Gtk.c line 1908 ... */
+
+ XtToolkitInitialize ();
+ app = XtCreateApplicationContext ();
+ dpy = gdk_display;
+ XtAppSetFallbackResources (app, defaults);
+ XtDisplayInitialize (app, dpy, "xscreensaver", "XScreenSaver",
+ 0, 0, &argc, argv);
+ toplevel_shell = XtAppCreateShell ("xscreensaver", "XScreenSaver",
+ applicationShellWidgetClass,
+ dpy, 0, 0);
+
+ dpy = XtDisplay (toplevel_shell);
+ db = XtDatabase (dpy);
+}
+
+/* From xscreensaver 3.24 utils/resource.c line 34 ... */
+
+static char *
+get_resource (char *res_name, char *res_class)
+{
+ XrmValue value;
+ char *type, *value_str = NULL, *full_name, *full_class;
+
+ full_name = g_strconcat ("xscreensaver.", res_name, NULL);
+ full_class = g_strconcat ("XScreenSaver.", res_class, NULL);
+
+ if (XrmGetResource (db, full_name, full_class, &type, &value))
+ value_str = g_strndup (value.addr, value.size);
+
+ g_free (full_name);
+ g_free (full_class);
+
+ return value_str;
+}
+
+static gchar *rc_names[][2] = {
+ { "verbose", "Boolean" },
+ { "lock", "Boolean" },
+ { "lockVTs", "Boolean" },
+ { "fade", "Boolean" },
+ { "unfade", "Boolean" },
+ { "fadeSeconds", "Time" },
+ { "fadeTicks", "Integer" },
+ { "installColormap", "Boolean" },
+ { "nice", "Nice" },
+ { "timeout", "Time" },
+ { "lockTimeout", "Time" },
+ { "cycle", "Time" },
+ { "passwdTimeout", "Time" },
+ { "xidleExtension", "Boolean" },
+ { "mitSaverExtension", "Boolean" },
+ { "sgiSaverExtension", "Boolean" },
+ { "procInterrupts", "Boolean" },
+ { "bourneShell", "BourneShell" },
+ { "programs", "Programs" },
+ { NULL, NULL }
+};
+
+void
+preferences_load_from_xrdb (Preferences *prefs)
+{
+ int i;
+
+ prefs->config_db = g_tree_new ((GCompareFunc) strcmp);
+
+ for (i = 0; rc_names[i][0]; i++)
+ g_tree_insert (prefs->config_db, rc_names[i][0],
+ get_resource (rc_names[i][0], rc_names[i][1]));
+}
+
+void
+screensaver_get_desc_from_xrdb (Screensaver *saver)
+{
+ gchar *s;
+
+ s = g_strconcat ("hacks.", saver->name, ".documentation", NULL);
+ saver->description = get_resource (s, s);
+ g_free (s);
+}
+
+gchar *
+screensaver_get_label_from_xrdb (gchar *name)
+{
+ gchar *s;
+
+ s = g_strdup_printf ("hacks.%s.name", name);
+ return get_resource (s, s);
+}
diff --git a/capplets/screensaver/resources.h b/capplets/screensaver/resources.h
new file mode 100644
index 000000000..e301d44a2
--- /dev/null
+++ b/capplets/screensaver/resources.h
@@ -0,0 +1,37 @@
+/* -*- mode: c; style: linux -*- */
+
+/* resources.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ * Parts written by Jamie Zawinski <jwz@jwz.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __RESOURCES_H
+#define __RESOURCES_H
+
+#include "preferences.h"
+
+void init_resource_database (int argc, char **argv);
+
+void preferences_load_from_xrdb (Preferences *prefs);
+void screensaver_get_desc_from_xrdb (Screensaver *saver);
+
+gchar *screensaver_get_label_from_xrdb (gchar *name);
+
+#endif /* __RESOURCES_H */
diff --git a/capplets/screensaver/screensaver-prefs-dialog.c b/capplets/screensaver/screensaver-prefs-dialog.c
new file mode 100644
index 000000000..d48233703
--- /dev/null
+++ b/capplets/screensaver/screensaver-prefs-dialog.c
@@ -0,0 +1,953 @@
+/* -*- mode: c; style: linux -*- */
+
+/* screensaver-prefs-dialog.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gnome.h>
+#include <parser.h>
+#include <sys/stat.h>
+
+#include <glade/glade.h>
+
+#include "screensaver-prefs-dialog.h"
+#include "preferences.h"
+#include "expr.h"
+#include "preview.h"
+
+struct _cli_argument_t
+{
+ char *argument;
+ char *value;
+};
+
+typedef struct _cli_argument_t cli_argument_t;
+
+enum {
+ OK_CLICKED_SIGNAL,
+ DEMO_SIGNAL,
+ LAST_SIGNAL
+};
+
+static gint screensaver_prefs_dialog_signals[LAST_SIGNAL] = { 0 };
+
+static void screensaver_prefs_dialog_init (ScreensaverPrefsDialog *dialog);
+static void screensaver_prefs_dialog_class_init (ScreensaverPrefsDialogClass *dialog);
+
+static void set_widgets_sensitive (GladeXML *prop_data,
+ gchar *widgets_str,
+ gboolean s);
+
+static void activate_option_cb (GtkWidget *widget);
+static void toggle_check_cb (GtkWidget *widget,
+ xmlNodePtr node);
+
+static gchar *write_boolean (xmlNodePtr arg_def,
+ GladeXML *prop_data);
+static gchar *write_number (xmlNodePtr arg_def,
+ GladeXML *prop_data);
+static gchar *write_select (xmlNodePtr arg_def,
+ GladeXML *prop_data);
+static gchar *write_command_line (gchar *name,
+ xmlNodePtr arg_def,
+ GladeXML *prop_data);
+
+static GScanner *read_command_line (char *command_line);
+static xmlNodePtr get_argument_data (Screensaver *saver);
+static GladeXML *get_screensaver_widget (Screensaver *saver,
+ xmlNodePtr argument_data);
+
+static gint arg_is_set (xmlNodePtr argument_data,
+ GScanner *cli_db);
+static void read_boolean (GladeXML *widget_data,
+ xmlNodePtr argument_data,
+ GScanner *cli_db);
+static void read_number (GladeXML *widget_data,
+ xmlNodePtr argument_data,
+ GScanner *cli_db);
+static void read_select (GladeXML *widget_data,
+ xmlNodePtr argument_data,
+ GScanner *cli_db);
+static void place_screensaver_properties (ScreensaverPrefsDialog *dialog);
+
+static gboolean arg_mapping_exists (Screensaver *saver);
+
+static void store_cli (ScreensaverPrefsDialog *dialog);
+
+static GtkWidget *get_basic_screensaver_widget (ScreensaverPrefsDialog *dialog,
+ Screensaver *saver);
+
+static void demo_cb (GtkWidget *widget,
+ ScreensaverPrefsDialog *dialog);
+static void help_cb (GtkWidget *widget,
+ ScreensaverPrefsDialog *dialog);
+static void screensaver_prop_ok_cb (GtkWidget *widget,
+ ScreensaverPrefsDialog *dialog);
+static void screensaver_prop_cancel_cb (GtkWidget *widget,
+ ScreensaverPrefsDialog *dialog);
+
+guint
+screensaver_prefs_dialog_get_type (void)
+{
+ static guint screensaver_prefs_dialog_type = 0;
+
+ if (!screensaver_prefs_dialog_type) {
+ GtkTypeInfo screensaver_prefs_dialog_info = {
+ "ScreensaverPrefsDialog",
+ sizeof (ScreensaverPrefsDialog),
+ sizeof (ScreensaverPrefsDialogClass),
+ (GtkClassInitFunc) screensaver_prefs_dialog_class_init,
+ (GtkObjectInitFunc) screensaver_prefs_dialog_init,
+ (GtkArgSetFunc) NULL,
+ (GtkArgGetFunc) NULL
+ };
+
+ screensaver_prefs_dialog_type =
+ gtk_type_unique (gnome_dialog_get_type (),
+ &screensaver_prefs_dialog_info);
+ }
+
+ return screensaver_prefs_dialog_type;
+}
+
+static void
+screensaver_prefs_dialog_init (ScreensaverPrefsDialog *dialog)
+{
+ GtkWidget *global_vbox, *vbox, *hbox, *frame, *label;
+
+ gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, FALSE);
+
+ global_vbox = GNOME_DIALOG (dialog)->vbox;
+
+ hbox = gtk_hbox_new (FALSE, 5);
+ gtk_box_pack_start (GTK_BOX (global_vbox), hbox, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+
+ label = gtk_label_new (_("Name:"));
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
+
+ dialog->name_entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), dialog->name_entry, TRUE, TRUE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 10);
+ gtk_box_pack_start (GTK_BOX (global_vbox), hbox, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+
+ dialog->settings_dialog_frame = gtk_frame_new (_("Settings"));
+ gtk_box_pack_start (GTK_BOX (hbox), dialog->settings_dialog_frame,
+ TRUE, TRUE, 0);
+
+ vbox = gtk_vbox_new (FALSE, 10);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+ frame = gtk_frame_new (_("Description"));
+ gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
+
+ dialog->description = gtk_label_new (_("label1"));
+ gtk_container_add (GTK_CONTAINER (frame), dialog->description);
+ gtk_label_set_justify (GTK_LABEL (dialog->description),
+ GTK_JUSTIFY_LEFT);
+ gtk_label_set_line_wrap (GTK_LABEL (dialog->description), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (dialog->description), 0, 0);
+ gtk_misc_set_padding (GTK_MISC (dialog->description), 5, 5);
+
+ gnome_dialog_append_button (GNOME_DIALOG (dialog),
+ _("Demo"));
+ gnome_dialog_append_button (GNOME_DIALOG (dialog),
+ GNOME_STOCK_BUTTON_HELP);
+ gnome_dialog_append_button (GNOME_DIALOG (dialog),
+ GNOME_STOCK_BUTTON_OK);
+ gnome_dialog_append_button (GNOME_DIALOG (dialog),
+ GNOME_STOCK_BUTTON_CANCEL);
+
+ gtk_widget_show_all (global_vbox);
+}
+
+static void
+screensaver_prefs_dialog_class_init (ScreensaverPrefsDialogClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass *) class;
+
+ screensaver_prefs_dialog_signals[OK_CLICKED_SIGNAL] =
+ gtk_signal_new ("ok-clicked", GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET
+ (ScreensaverPrefsDialogClass, ok_clicked),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ screensaver_prefs_dialog_signals[DEMO_SIGNAL] =
+ gtk_signal_new ("demo", GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET
+ (ScreensaverPrefsDialogClass, demo),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class,
+ screensaver_prefs_dialog_signals,
+ LAST_SIGNAL);
+
+ class->ok_clicked = NULL;
+}
+
+GtkWidget *
+screensaver_prefs_dialog_new (Screensaver *saver)
+{
+ GtkWidget *widget;
+ ScreensaverPrefsDialog *dialog;
+ char *title;
+
+ widget = gtk_type_new (screensaver_prefs_dialog_get_type ());
+ dialog = SCREENSAVER_PREFS_DIALOG (widget);
+
+ dialog->saver = saver;
+
+ title = g_strconcat (saver->label, " properties", NULL);
+ gtk_entry_set_text (GTK_ENTRY (dialog->name_entry),
+ saver->label);
+
+ if (arg_mapping_exists (saver)) {
+ dialog->cli_args_db =
+ read_command_line (saver->command_line);
+ dialog->argument_data = get_argument_data (saver);
+ dialog->prefs_widget_data =
+ get_screensaver_widget (saver,
+ dialog->argument_data);
+ } else {
+ dialog->basic_widget =
+ get_basic_screensaver_widget (dialog, saver);
+ }
+
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ gnome_dialog_button_connect (GNOME_DIALOG (dialog), 0,
+ demo_cb, dialog);
+ gnome_dialog_button_connect (GNOME_DIALOG (dialog), 1,
+ help_cb, dialog);
+ gnome_dialog_button_connect (GNOME_DIALOG (dialog), 2,
+ screensaver_prop_ok_cb, dialog);
+ gnome_dialog_button_connect (GNOME_DIALOG (dialog), 3,
+ screensaver_prop_cancel_cb, dialog);
+
+ if (dialog->basic_widget)
+ gtk_container_add (GTK_CONTAINER
+ (dialog->settings_dialog_frame),
+ dialog->basic_widget);
+ else if (dialog->prefs_widget_data)
+ gtk_container_add (GTK_CONTAINER
+ (dialog->settings_dialog_frame),
+ glade_xml_get_widget
+ (dialog->prefs_widget_data,
+ "widget"));
+
+ gtk_label_set_text (GTK_LABEL (dialog->description),
+ screensaver_get_desc (saver));
+
+ if (dialog->argument_data)
+ place_screensaver_properties (dialog);
+
+ return widget;
+}
+
+/*****************************************************************************/
+/* Enabling/disabling widgets based on options selected */
+/*****************************************************************************/
+
+/* set_widgets_sensitive
+ *
+ * Given a string of comma-separated widget names, finds the widgets
+ * in the given Glade XML definition and enables or disables them,
+ * based on the value of s
+ */
+
+static void
+set_widgets_sensitive (GladeXML *prop_data, gchar *widgets_str, gboolean s)
+{
+ char **widgets;
+ int i;
+ GtkWidget *widget;
+
+ if (!widgets_str) return;
+
+ widgets = g_strsplit (widgets_str, ",", -1);
+
+ for (i = 0; widgets[i]; i++) {
+ widget = glade_xml_get_widget (prop_data, widgets[i]);
+ if (widget) gtk_widget_set_sensitive (widget, s);
+ }
+
+ g_strfreev (widgets);
+}
+
+/* activate_option_cb
+ *
+ * Callback invoked when an option on an option menu is selected. The
+ * callback scans the xml node corresponding with that option to see
+ * what widgets are enabled by selecting that option and uses
+ * set_widgets_sensitive to enable them. Iterates through all other
+ * XML nodes and disables those widgets enabled by other nodes.
+ */
+
+static void
+activate_option_cb (GtkWidget *widget)
+{
+ GladeXML *prop_data;
+ xmlNodePtr argument_data, option_def, node;
+
+ prop_data = gtk_object_get_data (GTK_OBJECT (widget),
+ "prop_data");
+ argument_data = gtk_object_get_data (GTK_OBJECT (widget),
+ "argument_data");
+ option_def = gtk_object_get_data (GTK_OBJECT (widget),
+ "option_def");
+
+ node = argument_data->childs;
+
+ while (node) {
+ if (node != option_def)
+ set_widgets_sensitive (prop_data,
+ xmlGetProp (node, "enable"),
+ FALSE);
+ node = node->next;
+ }
+
+ set_widgets_sensitive (prop_data,
+ xmlGetProp (option_def, "enable"), TRUE);
+}
+
+/* toggle_check_cb
+ *
+ * Callback invoked when a check button is toggled. Works in a manner
+ * analagous to select_option_cb and deselect_option_cb above.
+ */
+
+static void
+toggle_check_cb (GtkWidget *widget, xmlNodePtr node)
+{
+ GladeXML *prop_data;
+ gboolean set;
+
+ prop_data = gtk_object_get_data (GTK_OBJECT (widget),
+ "prop_data");
+ set = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+ set_widgets_sensitive (prop_data,
+ xmlGetProp (node, "enable"),
+ set);
+}
+
+/*****************************************************************************/
+/* Writing out command lines */
+/*****************************************************************************/
+
+static gchar *
+write_boolean (xmlNodePtr argument_data, GladeXML *prop_data)
+{
+ char *widget_name;
+ GtkWidget *widget;
+
+ widget_name = g_strconcat (xmlGetProp (argument_data, "id"),
+ "_widget", NULL);
+ widget = glade_xml_get_widget (prop_data, widget_name);
+ g_free (widget_name);
+
+ if (!widget || !GTK_WIDGET_IS_SENSITIVE (widget)) return NULL;
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+ return xmlGetProp (argument_data, "arg-set");
+ else
+ return NULL;
+}
+
+static gchar *
+write_number (xmlNodePtr argument_data, GladeXML *prop_data)
+{
+ char *widget_name;
+ GtkWidget *widget;
+ GtkAdjustment *adjustment = NULL;
+ gfloat value = 0.0;
+ gchar *to_cli_expr;
+
+ widget_name = g_strconcat (xmlGetProp (argument_data, "id"),
+ "_widget", NULL);
+ widget = glade_xml_get_widget (prop_data, widget_name);
+ g_free (widget_name);
+
+ if (!widget || !GTK_WIDGET_IS_SENSITIVE (widget)) return NULL;
+
+ if (GTK_IS_RANGE (widget))
+ adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
+ else if (GTK_IS_SPIN_BUTTON (widget))
+ adjustment = gtk_spin_button_get_adjustment
+ (GTK_SPIN_BUTTON (widget));
+ if (adjustment)
+ value = adjustment->value;
+
+ to_cli_expr = xmlGetProp (argument_data, "to-cli-conv");
+ if (to_cli_expr)
+ value = parse_expr (to_cli_expr, value);
+
+ return g_strdup_printf (xmlGetProp (argument_data, "arg"), (int) value);
+}
+
+/* Note to readers: *please* ignore the following function, for the
+ * sake of your own mental health and my reputation as a sane
+ * coder. Just accept that it returns a string containing the CLI
+ * arguments corresponding with the selected option of an option
+ * menu. *sigh* I really must ask someone if there's a better way to
+ * do this...
+ */
+
+static gchar *
+write_select (xmlNodePtr argument_data, GladeXML *prop_data)
+{
+ xmlNodePtr node;
+ int i = 0;
+ GtkWidget *widget, *menu, *active;
+ char *widget_name;
+ GList *menu_item;
+
+ node = argument_data->childs;
+ widget_name = g_strconcat (xmlGetProp (argument_data, "id"),
+ "_widget", NULL);
+ widget = glade_xml_get_widget (prop_data, widget_name);
+ if (!widget || !GTK_WIDGET_IS_SENSITIVE (widget)) return NULL;
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (widget));
+ menu_item = GTK_MENU_SHELL (menu)->children;
+ active = gtk_menu_get_active (GTK_MENU (menu));
+
+ while (node && menu_item) {
+ if (active == menu_item->data &&
+ !xmlGetProp (node, "no-output"))
+ return xmlGetProp (node, "arg-set");
+
+ node = node->next; menu_item = menu_item->next; i++;
+ }
+
+ return NULL;
+}
+
+/* write_command_line
+ *
+ * Scan through XML nodes in the argument definition file and write
+ * out the parameter corresponding to each node in turn.
+ */
+
+static gchar *
+write_command_line (gchar *name, xmlNodePtr argument_data, GladeXML *prop_data)
+{
+ GString *line;
+ xmlNodePtr node;
+ gchar *arg, *ret;
+
+ line = g_string_new (name);
+ node = argument_data->childs;
+
+ for (node = argument_data->childs; node; node = node->next) {
+ if (xmlGetProp (node, "no-output"))
+ continue;
+
+ if (!strcmp (node->name, "boolean"))
+ arg = write_boolean (node, prop_data);
+ else if (!strcmp (node->name, "number"))
+ arg = write_number (node, prop_data);
+ else if (!strcmp (node->name, "select"))
+ arg = write_select (node, prop_data);
+ else if (!strcmp (node->name, "command"))
+ arg = xmlGetProp (node, "arg");
+ else
+ arg = NULL;
+
+ if (arg) {
+ g_string_append (line, " ");
+ g_string_append (line, arg);
+ }
+ }
+
+ ret = line->str;
+ g_string_free (line, FALSE);
+ return ret;
+}
+
+/*****************************************************************************/
+/* Reading the command line */
+/*****************************************************************************/
+
+static GScanner *
+read_command_line (char *command_line)
+{
+ char **args;
+ int i;
+ GScanner *cli_db;
+ static GScannerConfig config;
+ char *arg, *value;
+
+ config.cset_skip_characters = " \t\n";
+ config.cset_identifier_first = "abcdefghijklmnopqrstuvwxyz";
+ config.cset_identifier_nth = "abcdefghijklmnopqrstuvwxyz_";
+ config.scan_symbols = TRUE;
+ config.scan_identifier = TRUE;
+
+ cli_db = g_scanner_new (&config);
+ g_scanner_set_scope (cli_db, 0);
+
+ args = g_strsplit (command_line, " ", -1);
+
+ g_scanner_scope_add_symbol (cli_db, 0, "and", SYMBOL_AND);
+ g_scanner_scope_add_symbol (cli_db, 0, "or", SYMBOL_OR);
+ g_scanner_scope_add_symbol (cli_db, 0, "not", SYMBOL_NOT);
+
+ for (i = 0; args[i]; i++) {
+ if (args[i][0] == '-') {
+ arg = g_strdup (args[i] + 1);
+
+ if (args[i + 1] && args[i + 1][0] != '-') {
+ value = g_strdup (args[i + 1]);
+ i++;
+ } else {
+ value = (char *) 1;
+ }
+
+ g_scanner_scope_add_symbol (cli_db, 0, arg, value);
+ }
+ }
+
+ g_strfreev (args);
+
+ return cli_db;
+}
+
+/*****************************************************************************/
+/* Getting the argument definition data */
+/*****************************************************************************/
+
+static xmlNodePtr
+get_argument_data (Screensaver *saver)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root_node, node;
+ gchar *name;
+
+ doc = xmlParseFile (SSPROP_DATADIR "/hacks.xml");
+ root_node = xmlDocGetRootElement (doc);
+ g_assert (root_node != NULL);
+ node = root_node->childs;
+
+ while (node) {
+ name = xmlGetProp (node, "name");
+ if (!strcmp (name, saver->name)) break;
+ node = node->next;
+ }
+
+ return node;
+}
+
+/*****************************************************************************/
+/* Creating the dialog proper */
+/*****************************************************************************/
+
+static GladeXML *
+get_screensaver_widget (Screensaver *saver,
+ xmlNodePtr argument_data)
+{
+ GladeXML *screensaver_prop_data;
+ gchar *file_name;
+
+ file_name = g_strconcat (SSPROP_DATADIR "/",
+ saver->name, "-settings.glade", NULL);
+ screensaver_prop_data = glade_xml_new (file_name, "widget");
+ g_free (file_name);
+
+ return screensaver_prop_data;
+}
+
+/*****************************************************************************/
+/* Setting dialog properties from the CLI */
+/*****************************************************************************/
+
+/* arg_is_set
+ *
+ * Determines if an argument or set of arguments specified by the
+ * argument definition entry is set on a command line. Returns -1 if
+ * the argument is definitely not set, 0 if it may be, and 1 if it
+ * definitely is.
+ */
+
+static gint
+arg_is_set (xmlNodePtr argument_data, GScanner *cli_db)
+{
+ char *test;
+
+ test = xmlGetProp (argument_data, "test");
+
+ if (test) {
+ return parse_sentence (test, cli_db) ? 1 : -1;
+ } else {
+ return 0;
+ }
+}
+
+static void
+read_boolean (GladeXML *widget_data, xmlNodePtr argument_data,
+ GScanner *cli_db)
+{
+ char *widget_name;
+ GtkWidget *widget;
+ gint found;
+
+ found = arg_is_set (argument_data, cli_db);
+
+ widget_name = g_strconcat (xmlGetProp (argument_data, "id"),
+ "_widget", NULL);
+ widget = glade_xml_get_widget (widget_data, widget_name);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
+ found >= 0);
+
+ gtk_object_set_data (GTK_OBJECT (widget), "prop_data",
+ widget_data);
+ gtk_signal_connect (GTK_OBJECT (widget), "toggled",
+ GTK_SIGNAL_FUNC (toggle_check_cb),
+ argument_data);
+
+ if (found >= 0) {
+ set_widgets_sensitive (widget_data,
+ xmlGetProp (argument_data, "enable"),
+ TRUE);
+ } else {
+ set_widgets_sensitive (widget_data,
+ xmlGetProp (argument_data, "enable"),
+ FALSE);
+ }
+}
+
+static void
+read_number (GladeXML *widget_data, xmlNodePtr argument_data,
+ GScanner *cli_db)
+{
+ char *arg;
+ char *arg_line;
+ char **args;
+ char *widget_name;
+ char *from_cli_conv;
+ GtkWidget *widget;
+ GtkAdjustment *adjustment;
+ gfloat value;
+
+ arg_line = xmlGetProp (argument_data, "arg");
+ args = g_strsplit (arg_line, " ", -1);
+
+ arg = g_scanner_scope_lookup_symbol (cli_db, 0, args[0] + 1);
+ if (!arg) return;
+
+ widget_name = g_strconcat (xmlGetProp (argument_data, "id"),
+ "_widget", NULL);
+ widget = glade_xml_get_widget (widget_data, widget_name);
+
+ from_cli_conv = xmlGetProp (argument_data, "from-cli-conv");
+
+ if (from_cli_conv)
+ value = parse_expr (from_cli_conv, atof (arg));
+ else
+ value = atof (arg);
+
+ if (GTK_IS_RANGE (widget)) {
+ adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
+ gtk_adjustment_set_value (adjustment, value);
+ }
+ else if (GTK_IS_SPIN_BUTTON (widget)) {
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
+ }
+
+ g_strfreev (args);
+}
+
+static void
+read_select (GladeXML *widget_data, xmlNodePtr argument_data,
+ GScanner *cli_db)
+{
+ xmlNodePtr node;
+ gchar *widget_name;
+ GtkWidget *widget, *menu;
+ GList *menu_item_node;
+ gint found, max_found = -1;
+ int set_idx = 0, i = 0;
+
+ widget_name = g_strconcat (xmlGetProp (argument_data, "id"),
+ "_widget", NULL);
+ widget = glade_xml_get_widget (widget_data, widget_name);
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (widget));
+
+ node = argument_data->childs;
+
+ /* Get the index of the selected option */
+
+ while (node) {
+ found = arg_is_set (node, cli_db);
+
+ if (found > max_found) {
+ set_idx = i;
+ max_found = found;
+ }
+
+ node = node->next; i++;
+ }
+
+ /* Enable widgets enabled by selected option and disable
+ * widgets enabled by other options; connect select and
+ * deselect signals to do the same when an option is selected
+ */
+
+ menu_item_node = GTK_MENU_SHELL (menu)->children;
+ node = argument_data->childs; i = 0;
+
+ while (node) {
+ if (i == set_idx) {
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU (widget), i);
+ set_widgets_sensitive (widget_data,
+ xmlGetProp (node, "enable"),
+ TRUE);
+ } else {
+ set_widgets_sensitive (widget_data,
+ xmlGetProp (node, "enable"),
+ FALSE);
+ }
+
+ gtk_object_set_data (GTK_OBJECT (menu_item_node->data),
+ "prop_data", widget_data);
+ gtk_object_set_data (GTK_OBJECT (menu_item_node->data),
+ "option_def", node);
+ gtk_object_set_data (GTK_OBJECT (menu_item_node->data),
+ "argument_data", argument_data);
+
+ gtk_signal_connect (GTK_OBJECT (menu_item_node->data),
+ "activate",
+ GTK_SIGNAL_FUNC (activate_option_cb),
+ NULL);
+
+ node = node->next; menu_item_node = menu_item_node->next; i++;
+ }
+}
+
+static void
+place_screensaver_properties (ScreensaverPrefsDialog *dialog)
+{
+ xmlNodePtr node;
+
+ node = dialog->argument_data->childs;
+
+ while (node) {
+ if (!strcmp (node->name, "boolean"))
+ read_boolean (dialog->prefs_widget_data, node,
+ dialog->cli_args_db);
+ else if (!strcmp (node->name, "number"))
+ read_number (dialog->prefs_widget_data, node,
+ dialog->cli_args_db);
+ else if (!strcmp (node->name, "select"))
+ read_select (dialog->prefs_widget_data, node,
+ dialog->cli_args_db);
+
+ node = node->next;
+ }
+}
+
+static gboolean
+arg_mapping_exists (Screensaver *saver)
+{
+ struct stat buf;
+ char *filename;
+ gboolean ret;
+
+ if (!saver->name) return FALSE;
+
+ filename = g_strconcat (SSPROP_DATADIR "/",
+ saver->name, "-settings.glade", NULL);
+
+ if (stat (filename, &buf))
+ ret = FALSE;
+ else
+ ret = TRUE;
+
+ g_free (filename);
+ return ret;
+}
+
+static void
+store_cli (ScreensaverPrefsDialog *dialog)
+{
+ char *str;
+
+ g_free (dialog->saver->command_line);
+
+ if (dialog->prefs_widget_data) {
+ dialog->saver->command_line =
+ write_command_line (dialog->saver->name,
+ dialog->argument_data,
+ dialog->prefs_widget_data);
+ } else {
+ dialog->saver->command_line =
+ g_strdup (gtk_entry_get_text
+ (GTK_ENTRY (dialog->cli_entry)));
+ str = gtk_entry_get_text
+ (GTK_ENTRY (GTK_COMBO
+ (dialog->visual_combo)->entry));
+ if (!strcmp (str, "Any")) {
+ dialog->saver->visual = NULL;
+ } else {
+ dialog->saver->visual = g_strdup (str);
+ g_strdown (dialog->saver->visual);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* Fallback when Glade definition not found */
+/*****************************************************************************/
+
+static GtkWidget *
+get_basic_screensaver_widget (ScreensaverPrefsDialog *dialog,
+ Screensaver *saver)
+{
+ GtkWidget *vbox, *label;
+ GList *node;
+
+ vbox = gtk_vbox_new (FALSE, 10);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+
+ if (saver->name) {
+ label = gtk_label_new (_("Cannot find the data to configure this screensaver. Please edit the command line below."));
+ } else {
+ label = gtk_label_new (_("Please enter a command line below."));
+ }
+
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 5);
+ dialog->cli_entry = gtk_entry_new ();
+
+ if (saver->command_line) {
+ gtk_entry_set_text (GTK_ENTRY (dialog->cli_entry),
+ saver->command_line);
+ }
+
+ gtk_box_pack_start (GTK_BOX (vbox), dialog->cli_entry,
+ TRUE, FALSE, 5);
+
+ label = gtk_label_new (_("Visual:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 5);
+
+ dialog->visual_combo = gtk_combo_new ();
+
+ node = g_list_alloc ();
+ node->data = "Any";
+ g_list_append (node, "Best");
+ g_list_append (node, "Default");
+ g_list_append (node, "Default-N");
+ g_list_append (node, "GL");
+ g_list_append (node, "TrueColor");
+ g_list_append (node, "PseudoColor");
+ g_list_append (node, "StaticGray");
+ g_list_append (node, "GrayScale");
+ g_list_append (node, "DirectColor");
+ g_list_append (node, "Color");
+ g_list_append (node, "Gray");
+ g_list_append (node, "Mono");
+
+ gtk_combo_set_popdown_strings (GTK_COMBO (dialog->visual_combo), node);
+ if (saver->visual)
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO
+ (dialog->visual_combo)->entry),
+ saver->visual);
+ else
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO
+ (dialog->visual_combo)->entry),
+ "Any");
+
+ gtk_box_pack_start (GTK_BOX (vbox), dialog->visual_combo,
+ TRUE, FALSE, 5);
+ return vbox;
+}
+
+/*****************************************************************************/
+/* Global dialog callbacks */
+/*****************************************************************************/
+
+static void
+demo_cb (GtkWidget *widget, ScreensaverPrefsDialog *dialog)
+{
+ store_cli (dialog);
+ gtk_signal_emit (GTK_OBJECT (dialog),
+ screensaver_prefs_dialog_signals[DEMO_SIGNAL]);
+ show_demo (dialog->saver);
+}
+
+static void
+help_cb (GtkWidget *widget, ScreensaverPrefsDialog *dialog)
+{
+ GnomeHelpMenuEntry entry;
+ gchar *url;
+
+ if (!dialog->saver->name) return;
+
+ if (dialog->prefs_widget_data) {
+ entry.name = "screensaver-properties-capplet";
+ entry.path = g_strconcat (dialog->saver->name, ".html", NULL);
+
+ if (entry.path) {
+ gnome_help_display (NULL, &entry);
+ g_free (entry.path);
+ }
+ } else {
+ url = g_strconcat ("man:", dialog->saver->name, NULL);
+ gnome_url_show (url);
+ g_free (url);
+ }
+}
+
+static void
+screensaver_prop_ok_cb (GtkWidget *widget, ScreensaverPrefsDialog *dialog)
+{
+ store_cli (dialog);
+
+ g_free (dialog->saver->label);
+ dialog->saver->label =
+ g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->name_entry)));
+
+ gtk_signal_emit (GTK_OBJECT (dialog),
+ screensaver_prefs_dialog_signals[OK_CLICKED_SIGNAL]);
+
+ gnome_dialog_close (GNOME_DIALOG (dialog));
+}
+
+static void
+screensaver_prop_cancel_cb (GtkWidget *widget, ScreensaverPrefsDialog *dialog)
+{
+ gnome_dialog_close (GNOME_DIALOG (dialog));
+}
diff --git a/capplets/screensaver/screensaver-prefs-dialog.h b/capplets/screensaver/screensaver-prefs-dialog.h
new file mode 100644
index 000000000..d06ebf9f9
--- /dev/null
+++ b/capplets/screensaver/screensaver-prefs-dialog.h
@@ -0,0 +1,72 @@
+/* -*- mode: c; style: linux -*- */
+
+/* screensaver-prefs-dialog.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __SCREENSAVER_PREFS_DIALOG_H
+#define __SCREENSAVER_PREFS_DIALOG_H
+
+#include <gnome.h>
+#include <tree.h>
+#include <glade/glade.h>
+
+#include "preferences.h"
+#include "prefs-widget.h"
+
+#define SCREENSAVER_PREFS_DIALOG(obj) GTK_CHECK_CAST (obj, screensaver_prefs_dialog_get_type (), ScreensaverPrefsDialog)
+#define SCREENSAVER_PREFS_DIALOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, screensaver_prefs_dialog_get_type (), ScreensaverPrefsDialogClass)
+#define IS_SCREENSAVER_PREFS_DIALOG(obj) GTK_CHECK_TYPE (obj, screensaver_prefs_dialog_get_type ())
+
+typedef struct _ScreensaverPrefsDialog ScreensaverPrefsDialog;
+typedef struct _ScreensaverPrefsDialogClass ScreensaverPrefsDialogClass;
+
+struct _ScreensaverPrefsDialog
+{
+ GnomeDialog gnome_dialog;
+
+ Screensaver *saver;
+ PrefsWidget *global_prefs_widget;
+ GladeXML *prefs_widget_data;
+ xmlNodePtr argument_data;
+ GScanner *cli_args_db;
+
+ GtkWidget *settings_dialog_frame;
+ GtkWidget *description;
+
+ GtkWidget *cli_entry;
+ GtkWidget *visual_combo;
+ GtkWidget *name_entry;
+ GtkWidget *basic_widget;
+};
+
+struct _ScreensaverPrefsDialogClass
+{
+ GnomeDialogClass gnome_dialog_class;
+
+ void (*ok_clicked) (ScreensaverPrefsDialog *);
+ void (*demo) (ScreensaverPrefsDialog *);
+};
+
+guint screensaver_prefs_dialog_get_type (void);
+
+GtkWidget *screensaver_prefs_dialog_new (Screensaver *saver);
+
+#endif /* __SCREENSAVER_PREFS_DIALOG_H */
diff --git a/capplets/screensaver/screensaver-properties.desktop b/capplets/screensaver/screensaver-properties.desktop
new file mode 100644
index 000000000..4f43a73f0
--- /dev/null
+++ b/capplets/screensaver/screensaver-properties.desktop
@@ -0,0 +1,44 @@
+[Desktop Entry]
+Name=Screensaver
+Name[da]=Pauseskærm
+Name[ca]=Protector de pantalla
+Name[de]=Bildschirmschoner
+Name[es]=Propiedades Salvapantallas
+Name[et]=Ekraanisäästja
+Name[fi]=Ruudunsäästäjä
+Name[fr]=Propriétés Économiseur d'écran
+Name[hu]=Képernyõvédõ
+Name[it]=Salvaschermo
+Name[ja]=¥¹¥¯¥ê¡¼¥ó¥»¡¼¥Ð¡¼
+Name[ko]=È­¸é º¸È£±â
+Name[no]=Skjermsparer
+Name[pl]=Wygaszacz ekranu
+Name[pt]=Propriedades da protecção de ecrã
+Name[pt_BR]=Propriedades da proteção de tela
+Name[ru]=èÒÁÎÉÔÅÌØ ÜËÒÁÎÁ
+Name[sv]=Skärmsläckare
+Name[uk]=úÂÅÒ¦ÇÁÞ ÅËÒÁÎÁ
+Name[wa]=Spårgneu di waitroûle
+Comment=Configure the settings of the screensaver.
+Comment[da]=Indstil pauseskærmen
+Comment[ca]=Configurar el protector de pantalla.
+Comment[de]=Bildschirmschoner einrichten
+Comment[es]=Configurar el salvapantalla
+Comment[et]=Ekraanisäästja häälestus
+Comment[fi]=Aseta ruudunsäästäjän asetukset.
+Comment[fr]=Configurer l'économiseur d'écran
+Comment[hu]=Képernyõvédõ beállítások
+Comment[it]=Impostazioni del salvaschermo
+Comment[ja]=¥¹¥¯¥ê¡¼¥ó¥»¡¼¥Ð¡¼¤ÎÀßÄê
+Comment[ko]=È­¸é º¸È£±â ¼³Á¤
+Comment[no]=Endre innstillingene for skjermspareren
+Comment[pl]=Konfiguracja wygaszacza ekranu
+Comment[pt]=Configura as opções da protecção de ecrã.
+Comment[ru]=îÁÓÔÒÏÊËÁ ÈÒÁÎÉÔÅÌÑ ÜËÒÁÎÁ.
+Comment[sv]=Ändra inställningar för skärmsläckare
+Comment[uk]=îÁÌÁÇÏÄÖÅÎÎÑ ÚÂÅÒ¦ÇÁÞÁ ÅËÒÁÎÁ
+Comment[wa]=Apontiaedje do spårgneu di waitroûle
+Exec=screensaver-properties-capplet
+Icon=gnome-ccscreensaver.png
+Terminal=0
+Type=Application
diff --git a/capplets/screensaver/selection-dialog.c b/capplets/screensaver/selection-dialog.c
new file mode 100644
index 000000000..0979c92ee
--- /dev/null
+++ b/capplets/screensaver/selection-dialog.c
@@ -0,0 +1,239 @@
+/* -*- mode: c; style: linux -*- */
+
+/* selection-dialog.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ * Parts written by Jamie Zawinski <jwz@jwz.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <ctype.h>
+
+#include <gnome.h>
+#include <parser.h>
+
+#include "selection-dialog.h"
+#include "preferences.h"
+
+enum {
+ OK_CLICKED_SIGNAL,
+ LAST_SIGNAL
+};
+
+static xmlDocPtr screensaver_doc;
+
+static gint selection_dialog_signals[LAST_SIGNAL] = { 0 };
+
+static void selection_dialog_init (SelectionDialog *dialog);
+static void selection_dialog_class_init (SelectionDialogClass *dialog);
+
+static void place_screensaver_list (SelectionDialog *dialog);
+
+static void select_program_cb (GtkListItem *item,
+ SelectionDialog *dialog);
+static void selection_dialog_ok_cb (GtkWidget *widget,
+ SelectionDialog *dialog);
+static void selection_dialog_cancel_cb (GtkWidget *widget,
+ SelectionDialog *dialog);
+
+guint
+selection_dialog_get_type (void)
+{
+ static guint selection_dialog_type = 0;
+
+ if (!selection_dialog_type) {
+ GtkTypeInfo selection_dialog_info = {
+ "SelectionDialog",
+ sizeof (SelectionDialog),
+ sizeof (SelectionDialogClass),
+ (GtkClassInitFunc) selection_dialog_class_init,
+ (GtkObjectInitFunc) selection_dialog_init,
+ (GtkArgSetFunc) NULL,
+ (GtkArgGetFunc) NULL
+ };
+
+ selection_dialog_type =
+ gtk_type_unique (gnome_dialog_get_type (),
+ &selection_dialog_info);
+ }
+
+ return selection_dialog_type;
+}
+
+static void
+selection_dialog_init (SelectionDialog *dialog)
+{
+ GtkWidget *label, *scrolled_window, *viewport;
+ GtkBox *vbox;
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Add a new screensaver"));
+
+ gnome_dialog_append_button (GNOME_DIALOG (dialog),
+ GNOME_STOCK_BUTTON_OK);
+ gnome_dialog_append_button (GNOME_DIALOG (dialog),
+ GNOME_STOCK_BUTTON_CANCEL);
+
+ vbox = GTK_BOX (GNOME_DIALOG (dialog)->vbox);
+
+ label = gtk_label_new (_("Select the screensaver to run from the list below:"));
+ gtk_box_pack_start (vbox, label, FALSE, TRUE, 0);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+ gtk_box_pack_start (vbox, scrolled_window, TRUE, TRUE, 0);
+
+ viewport = gtk_viewport_new (NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), viewport);
+
+ dialog->program_list = GTK_LIST (gtk_list_new ());
+ gtk_list_set_selection_mode (GTK_LIST (dialog->program_list),
+ GTK_SELECTION_SINGLE);
+ gtk_container_add (GTK_CONTAINER (viewport),
+ GTK_WIDGET (dialog->program_list));
+
+ gnome_dialog_button_connect (GNOME_DIALOG (dialog), 0,
+ GTK_SIGNAL_FUNC (selection_dialog_ok_cb),
+ dialog);
+ gnome_dialog_button_connect (GNOME_DIALOG (dialog), 1,
+ GTK_SIGNAL_FUNC
+ (selection_dialog_cancel_cb),
+ dialog);
+
+ gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
+}
+
+static void
+selection_dialog_class_init (SelectionDialogClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass *) class;
+
+ selection_dialog_signals[OK_CLICKED_SIGNAL] =
+ gtk_signal_new ("ok-clicked", GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (SelectionDialogClass,
+ ok_clicked),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
+
+ gtk_object_class_add_signals (object_class,
+ selection_dialog_signals,
+ LAST_SIGNAL);
+
+ class->ok_clicked = NULL;
+}
+
+GtkWidget *
+selection_dialog_new (PrefsWidget *prefs_widget)
+{
+ GtkWidget *widget;
+
+ widget = gtk_type_new (selection_dialog_get_type ());
+
+ if (!screensaver_doc)
+ screensaver_doc = xmlParseFile (SSPROP_DATADIR "/hacks.xml");
+
+ place_screensaver_list (SELECTION_DIALOG (widget));
+
+ gtk_widget_show (widget);
+
+ return widget;
+}
+
+static void
+place_screensaver_list (SelectionDialog *dialog)
+{
+ GtkWidget *item;
+ GList *item_list_head = NULL, *item_list_tail = NULL;
+ xmlNodePtr node;
+ gchar *label;
+
+ node = xmlDocGetRootElement (screensaver_doc);
+
+ if (node) {
+ node = node->childs;
+
+ while (node) {
+ label = xmlGetProp (node, "name");
+ label[0] = toupper (label[0]);
+ item = gtk_list_item_new_with_label (label);
+ gtk_widget_show (item);
+ gtk_object_set_data (GTK_OBJECT (item), "node", node);
+ gtk_signal_connect (GTK_OBJECT (item), "select",
+ GTK_SIGNAL_FUNC
+ (select_program_cb),
+ dialog);
+
+ item_list_tail = g_list_append (item_list_tail, item);
+ if (!item_list_head) item_list_head = item_list_tail;
+ item_list_tail = g_list_last (item_list_tail);
+ node = node->next;
+ }
+ }
+
+ item = gtk_list_item_new_with_label ("Custom");
+ gtk_widget_show (item);
+ gtk_signal_connect (GTK_OBJECT (item), "select",
+ GTK_SIGNAL_FUNC (select_program_cb), dialog);
+
+ item_list_tail = g_list_append (item_list_tail, item);
+ if (!item_list_head) item_list_head = item_list_tail;
+ gtk_list_append_items (dialog->program_list, item_list_head);
+
+ gtk_list_select_item (dialog->program_list, 0);
+}
+
+static void
+select_program_cb (GtkListItem *item, SelectionDialog *dialog)
+{
+ dialog->selected_program_item = item;
+ dialog->selected_program_node =
+ gtk_object_get_data (GTK_OBJECT (item), "node");
+}
+
+static void
+selection_dialog_ok_cb (GtkWidget *widget, SelectionDialog *dialog)
+{
+ Screensaver *saver;
+
+ saver = screensaver_new ();
+ saver->label = g_strdup (_("New screensaver"));
+
+ if (dialog->selected_program_node) {
+ saver->name =
+ g_strdup (xmlGetProp (dialog->selected_program_node,
+ "name"));
+ saver->command_line = g_strconcat (saver->name, " -root", NULL);
+ }
+
+ gtk_signal_emit (GTK_OBJECT (dialog),
+ selection_dialog_signals[OK_CLICKED_SIGNAL], saver);
+ gnome_dialog_close (GNOME_DIALOG (dialog));
+}
+
+static void
+selection_dialog_cancel_cb (GtkWidget *widget, SelectionDialog *dialog)
+{
+ gnome_dialog_close (GNOME_DIALOG (dialog));
+}
diff --git a/capplets/screensaver/selection-dialog.h b/capplets/screensaver/selection-dialog.h
new file mode 100644
index 000000000..ebf22f35d
--- /dev/null
+++ b/capplets/screensaver/selection-dialog.h
@@ -0,0 +1,61 @@
+/* -*- mode: c; style: linux -*- */
+
+/* selection-dialog.h
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Written by Bradford Hovinen <hovinen@helixcode.com>
+ * Parts written by Jamie Zawinski <jwz@jwz.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __SELECTION_DIALOG_H
+#define __SELECTION_DIALOG_H
+
+#include <gnome.h>
+#include <tree.h>
+
+#include "prefs-widget.h"
+
+#define SELECTION_DIALOG(obj) GTK_CHECK_CAST (obj, selection_dialog_get_type (), SelectionDialog)
+#define SELECTION_DIALOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, selection_dialog_get_type (), SelectionDialogClass)
+#define IS_SELECTION_DIALOG(obj) GTK_CHECK_TYPE (obj, selection_dialog_get_type ())
+
+typedef struct _SelectionDialog SelectionDialog;
+typedef struct _SelectionDialogClass SelectionDialogClass;
+
+struct _SelectionDialog
+{
+ GnomeDialog gnome_dialog;
+
+ GtkList *program_list;
+
+ GtkListItem *selected_program_item;
+ xmlNodePtr selected_program_node;
+};
+
+struct _SelectionDialogClass
+{
+ GnomeDialogClass gnome_dialog_class;
+
+ void (*ok_clicked) (SelectionDialog *, Screensaver *);
+};
+
+guint selection_dialog_get_type (void);
+
+GtkWidget *selection_dialog_new (PrefsWidget *prefs_widget);
+
+#endif /* __SELECTION_DIALOG_H */
diff --git a/capplets/screensaver/unchecked-disabled.xpm b/capplets/screensaver/unchecked-disabled.xpm
new file mode 100644
index 000000000..c2c39b7d9
--- /dev/null
+++ b/capplets/screensaver/unchecked-disabled.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * unchecked_disabled_xpm[] = {
+"16 16 3 2",
+" g None",
+". g #000000",
+"+ g #D9D9D9",
+" ",
+" ",
+" . . . . . . . . . . . . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . . . . . . . . . . . . ",
+" ",
+" "};
diff --git a/capplets/screensaver/unchecked.xpm b/capplets/screensaver/unchecked.xpm
new file mode 100644
index 000000000..0056cd963
--- /dev/null
+++ b/capplets/screensaver/unchecked.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * unchecked_xpm[] = {
+"16 16 3 2",
+" g None",
+". g #000000",
+"+ g #FFFFFF",
+" ",
+" ",
+" . . . . . . . . . . . . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . + + + + + + + + + + . ",
+" . . . . . . . . . . . . ",
+" ",
+" "};