From 2830dc67b34fcc777cfcf774dc13cdf3a277dbe3 Mon Sep 17 00:00:00 2001 From: "Bradford Hovinen (Gdict maintainer)" Date: Mon, 31 Jul 2000 20:06:12 +0000 Subject: [PATCH] Added new screensaver properties capplet --- capplets/screensaver/ChangeLog | 488 +++++ capplets/screensaver/XScreenSaver_ad.h | 952 ++++++++++ capplets/screensaver/checked-disabled.xpm | 22 + capplets/screensaver/checked.xpm | 22 + capplets/screensaver/daemon.c | 77 + capplets/screensaver/daemon.h | 34 + capplets/screensaver/expr.c | 259 +++ capplets/screensaver/expr.h | 36 + capplets/screensaver/main.c | 248 +++ capplets/screensaver/no-hack.png | Bin 0 -> 2250 bytes capplets/screensaver/pref-file.c | 538 ++++++ capplets/screensaver/pref-file.h | 33 + capplets/screensaver/preferences.c | 288 +++ capplets/screensaver/preferences.h | 110 ++ capplets/screensaver/prefs-widget.c | 1635 +++++++++++++++++ capplets/screensaver/prefs-widget.h | 128 ++ capplets/screensaver/preview.c | 322 ++++ capplets/screensaver/preview.h | 39 + capplets/screensaver/rc-parse.c | 601 ++++++ capplets/screensaver/rc-parse.h | 48 + capplets/screensaver/resources.c | 138 ++ capplets/screensaver/resources.h | 37 + .../screensaver/screensaver-prefs-dialog.c | 953 ++++++++++ .../screensaver/screensaver-prefs-dialog.h | 72 + .../screensaver-properties.desktop | 44 + capplets/screensaver/selection-dialog.c | 239 +++ capplets/screensaver/selection-dialog.h | 61 + capplets/screensaver/unchecked-disabled.xpm | 22 + capplets/screensaver/unchecked.xpm | 22 + 29 files changed, 7468 insertions(+) create mode 100644 capplets/screensaver/ChangeLog create mode 100644 capplets/screensaver/XScreenSaver_ad.h create mode 100644 capplets/screensaver/checked-disabled.xpm create mode 100644 capplets/screensaver/checked.xpm create mode 100644 capplets/screensaver/daemon.c create mode 100644 capplets/screensaver/daemon.h create mode 100644 capplets/screensaver/expr.c create mode 100644 capplets/screensaver/expr.h create mode 100644 capplets/screensaver/main.c create mode 100644 capplets/screensaver/no-hack.png create mode 100644 capplets/screensaver/pref-file.c create mode 100644 capplets/screensaver/pref-file.h create mode 100644 capplets/screensaver/preferences.c create mode 100644 capplets/screensaver/preferences.h create mode 100644 capplets/screensaver/prefs-widget.c create mode 100644 capplets/screensaver/prefs-widget.h create mode 100644 capplets/screensaver/preview.c create mode 100644 capplets/screensaver/preview.h create mode 100644 capplets/screensaver/rc-parse.c create mode 100644 capplets/screensaver/rc-parse.h create mode 100644 capplets/screensaver/resources.c create mode 100644 capplets/screensaver/resources.h create mode 100644 capplets/screensaver/screensaver-prefs-dialog.c create mode 100644 capplets/screensaver/screensaver-prefs-dialog.h create mode 100644 capplets/screensaver/screensaver-properties.desktop create mode 100644 capplets/screensaver/selection-dialog.c create mode 100644 capplets/screensaver/selection-dialog.h create mode 100644 capplets/screensaver/unchecked-disabled.xpm create mode 100644 capplets/screensaver/unchecked.xpm 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 + + * all: Removed ENABLE_{LIBGLADE|CAPPLET|PREVIEW} ifdefs + +2000-07-26 Bradford Hovinen + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 ", +"*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 .", +"*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 \ +.", +"*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 \ +.", +"*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 \ +. \ + \\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 .", +"*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 \ +.", +"*hacks.xsnow.documentation: \ +Draws falling snow and the occasional tiny Santa. By Rick Jansen. \ +You can find it at .", +"*hacks.goban.documentation: \ +Replays historical games of go (aka wei-chi and baduk) on the screen. \ +By Scott Draves. You can find it at .", +"*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 . \ +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 +#endif + +#include +#include + +#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 +#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 + +#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 +#endif + +#include +#include +#include + +#include + +#include + +#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 0000000000000000000000000000000000000000..affb745f0864743523bc9f591ee1047719ae3bbb GIT binary patch literal 2250 zcmeHJYgp2U9;VC0a!TelX^I|m%eAGb)9@Ca(lo=%QA>1Q(9>gTDVYYD613E`S!qYh z($rcqG!#-3FDM+TBVKZ@00|MP44L6yMIQv^cG%~A-nV`D-QG{{^S&S6-}Qe*hFb3Y zawiA`vJ5*G90LMvIbhm1&9|C*4FqU5jqMqSBMyT=9hDZkv`Kx;B94N8GlST`cH0qRw}U|D31Pv9PZT@=rp37T@msG&2T-58U;2l9%OxoH zRTX&q-qkAs_sY8F+j#v~#!gBC1zqa;94A;Z^1_-}PsD8THHJYz2I=)(oM7{`y(R9} zNA8(Bg_rEwcf{PrspN0?&zk5Xtyy{jwg**Nj>+y3-)X3K7zzA{C||)dFB1qgu&xw( zj~Ku+liTCuYa0rM0?#CaeE=7Zlmf)32^(2_d5kN~MEcjbxKL~}TZFCSt0`jM{NpND@60^T% zG)HqaYL6!7$sj%ty^WJc8LbqY*K#PMBD7_?3iUd%y=rjPJ$J(p7k14o}J2rvJsNUeqwehs_kNbcAR{L1dzeyRF#mst4p@t|tevn*w`+Q$g992*_=m2@_(-5iJ z*FMmQY?_qC;&5iCzGJaiV=n;9MCObbh>JWP=+~S#f^7LW)*xT&%kJ6S-Kj_aG>W#W zK8tvxQ3ZOK86SD{eUT1K>tk${MFXtkO+RHEV%^PzzoZGz_Bldl0(8GuKcn!%ty)uj z1a_6B=)~+}lPK?TFAA@f_5FdhtV)BQ9M1sS`E&Hf(x5XviOlkK{SaqE2)QNQ$qyJl z2RM*ExgoW)#D^A%`t(vo6PoDZv+~+{w%#@qi1vK52k;WNqF=JzIYTzL*BO)+x+QuI zGYoj)kgAq;#C@RPqdHo$b=;ZY*Sv0#o_8!tE^U;}8}>Y$_Yh_qcn38GR7gWI$MgLGlwEqO2*&aCMJeSv(L>H%B6SCo=N6p%BmQf|U=JP(|JlOGfLjC3OtheRggeO65 T + * Parts written by Jamie Zawinski + * + * 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 + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 + : ""); + 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 + * Parts written by Jamie Zawinski + * + * 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 + * + * 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 +#include +#include +#include + +#include + +#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 + * + * 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 +#include + +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 + * + * 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 +#include +#include + +#include + +#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 + * + * 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 + +#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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 + * + * 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 + +#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 + * Parts written by Jamie Zawinski + * + * 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 +#include +#include +#include + +#include +#include + +#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 + * + * 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 + +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 + * Parts written by Jamie Zawinski + * + * 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 +#include +#include + +#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 + * Parts written by Jamie Zawinski + * + * 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 + * + * 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 +#include +#include + +#include + +#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 + * + * 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 +#include +#include + +#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 + * Parts written by Jamie Zawinski + * + * 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 + +#include +#include + +#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 + * Parts written by Jamie Zawinski + * + * 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 +#include + +#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", +" ", +" ", +" . . . . . . . . . . . . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . + + + + + + + + + + . ", +" . . . . . . . . . . . . ", +" ", +" "};