########################################################################### ## ## YardBox.pm ## Copyright (C) 2000, 2001, 2002, 2003 by Jonathan Rosenbaum ## ## ## This program is free software; you may 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. ## ############################################################################## package BootRoot::YardBox; use vars qw(@ISA @EXPORT %EXPORT_TAGS); use Exporter; @ISA = qw(Exporter); @EXPORT = qw(yard ars filesystem_size file_system); use strict; use BootRoot::BootRoot; use BootRoot::Yard; use BootRoot::Error; use BootRoot::lsMode; use File::Basename; my $item_factory; my $true = 1; my $false = 0; #my $error; my ($continue_button,$close_button,$save_button); my($check,$dep,$space,$create,$create_expect_uml,$test); my($filename,$filesystem_size,$kernel,$template_dir,$template,$tmp,$mnt); my ($text, $changed_text, $changed_text_from_template); my $save_as; my ($replacements_window, $filesystem_window, $path_window, $tutorial, $shortcut, $uml_exclusively); my ($search_window, $question_window, $offset); my $Shortcuts; my @entry; my $file_dialog; my $search_text; #my $filesystem_type = "ext2"; #my $inode_size = 8192; my $lib_bool = 1; my $bin_bool = 1; my $mod_bool = 1; my $ars; sub ars { $ars = $_[0]; $filename = $ars->{filename}; $filesystem_size = $ars->{filesystem_size}; $kernel = $ars->{kernel}; $template_dir = $ars->{template_dir}; $template = $ars->{template}; $tmp = $ars->{tmp}; $mnt = $ars->{mnt}; $changed_text = "$template_dir$template" if defined $template; } # Freshmeat comes here so the rest of the program needs # to be warned when the template is coming from here. my @menu_items = ( { path => '/File', type => '' }, { path => '/File/file_tearoff', type => '' }, { path => '/File/_New Template', accelerator => 'N', callback => \&saved, action => 103 }, { path => '/File/file_separator', type => '' }, { path => '/File/_Save', accelerator => 'S', callback => \&saved, action => 100 }, { path => '/File/Save _As ...', accelerator => 'A', callback => \&saved, action => 101 }, { path => '/File/file_separator', type => '' }, { path => '/File/Close', accelerator => 'W', callback => sub { destroy $main::yard_window; }}, { path => '/_Edit', type => '' }, { path => '/Edit/edit_tearoff', type => '' }, { path => '/Edit/Settings/' }, { path => '/Edit/Settings/edit_tearoff', type => '' }, { path => '/Edit/Settings/Path', callback => \&path }, { path => '/Edit/Settings/Stripping/' }, ## { path => '/Edit/Settings/edit_separator', ## type => '' }, ## { path => '/Edit/Settings/Replacements', ## action => "4", ## type => '' }, ## { path => '/Edit/Settings/Modules', ## action => "5", ## type => '' }, { path => '/Edit/Settings/Stripping/edit_tearoff', type => '' }, { path => '/Edit/Settings/Stripping/Libraries', action => "1", type => '' }, { path => '/Edit/Settings/Stripping/settings/' }, { path => '/Edit/Settings/Stripping/settings/strip-all', action => "10", type => '', callback => \&strip_all }, { path => '/Edit/Settings/Stripping/settings/strip-debug', action => '11', type => '', callback => \&strip_debug }, { path => '/Edit/Settings/Stripping/Binaries', action => "2", type => '' }, { path => '/Edit/Settings/Stripping/Modules', action => '3', type => '' }, { path => '/Edit/Settings/settings_separator', type => '' }, { path => '/Edit/Settings/NSS Config', action => "60", type => '', callback => \&nss_pam }, { path => '/Edit/Settings/PAM Config', action => '61', type => '', callback => \&nss_pam }, { path => '/Edit/Stages/' }, { path => '/Edit/Stages/one-by-one', action => 13, type => '', callback => \&stages_one_by_one }, { path => '/Edit/Stages/continuous', action => 14, type => '', callback => \&stages_continuous }, { path => '/Edit/Stages/user defined', action => 15, type => '', callback => \&stages_user_defined }, { path => '/Edit/File System', callback => \&file_system }, { path => '/Edit/Replacements', callback => \&Replacements }, { path => '/Edit/edit_separator', type => '' }, { path => '/Edit/_Search in Page', accelerator => 'S', callback => \&search }, { path => '/_Create', type => '' }, { path => '/Create/create_tearoff', type => '' }, { path => '/Create/Replacements/' }, { path => '/Create/Replacements/replacement_tearoff', type => '' }, { path => '/Create/Replacements/fstab', action => 16, type => '', callback => \&check_stage }, ## { path => '/Create/Replacements/rc', ## action => 17, ## type => '', ## callback => \&check_stage }, ## { path => '/Create/Replacements/fstab directory name', ## action => 18, ## type => '', ## callback => \&check_stage }, { path => '/_Tests', type => '<Branch>' }, { path => '/Tests/tests_tearoff', type => '<Tearoff>' }, { path => '/Tests/fstab', action => 30, type => '<CheckItem>', callback => \&tests }, { path => '/Tests/inittab', action => 31, type => '<CheckItem>', callback => \&tests }, { path => '/Tests/scripts', action => 32, type => '<CheckItem>', callback => \&tests }, { path => '/Tests/links', action => 33, type => '<CheckItem>', callback => \&tests }, { path => '/Tests/passwd', action => 34, type => '<CheckItem>', callback => \&tests }, { path => '/Tests/pam', action => 35, type => '<CheckItem>', callback => \&tests }, { path => '/Tests/nss', action => 36, type => '<CheckItem>', callback => \&tests }, { path => '/_Help', type => '<LastBranch>' }, { path => '/Help/help_tearoff', type => '<Tearoff>' }, { path => '/_Help/Tutorial', callback => \&tutorial }, { path => '/_Help/Shortcuts', callback => \&shortcut } ); ###### # YARD ###### sub yard { my $error; # Error handling in Yard will take some strategy if (!-d $kernel && -f $kernel) { $error = kernel_version_check($kernel); # Yard: kernel,kernel version # Becomes $ENV{'RELEASE'} return if $error && $error eq "ERROR"; } open(CONTENTS, "<$changed_text") or ($error = error("$changed_text: $!")); return "ERROR"if $error && $error eq "ERROR"; my @template = <CONTENTS>; close(CONTENTS); $changed_text_from_template = join("",@template); yard_box(); } # end sub yard ############### # File System # ############### my %uml_expect; # What to do if file_system is never called, # Receives values when ARS is opened from BootRoot. sub filesystem_size { if ( $> == 0 ) { $uml_expect{uml_exclusively} = 0 if !$uml_expect{uml_exclusively}; $uml_expect{preserve_ownership} = 1 if !$uml_expect{preserve_ownership}; $ars->{uml_exclusively} = $uml_expect{uml_exclusively}; ars2($ars); $ars->{preserve_ownership} = $uml_expect{preserve_ownership}; ars2($ars); } else { # When the user opens the filesystem box it is # assumed that he wants to take over setting the # check boxes, however, if he closes it, the defaults # come back to play for uml_exclusively if the size is # changed, but only if it is greater than 8192. if ( !$uml_exclusively ) { if ( $filesystem_size > 8192 ) { $uml_expect{uml_exclusively} = 1; } else { $uml_expect{uml_exclusively} = 0; } } else { if ( $filesystem_size > 8192 ) { $uml_expect{uml_exclusively} = 1 if !$uml_expect{uml_exclusively}; } else { $uml_expect{uml_exclusively} = 0 if !$uml_expect{uml_exclusively}; } } $ars->{uml_exclusively} = $uml_expect{uml_exclusively}; ars2($ars); $uml_expect{preserve_ownership} = 0 if !$uml_expect{preserve_ownership}; $ars->{preserve_ownership} = $uml_expect{preserve_ownership}; ars2($ars); } } # end sub fileystem_size # This allows the user to choose a different filesystem besides ext2. # The space_check inode percentage formula can be altered. Default 2%. sub file_system { if (not defined $filesystem_window) { $filesystem_window = Gtk::Window->new("toplevel"); $filesystem_window->signal_connect("destroy", \&destroy_window, \$filesystem_window); $filesystem_window->signal_connect("delete_event", \&destroy_window, \$filesystem_window); $filesystem_window->signal_connect("key_press_event", sub { my $event = pop @_; if ($event->{'keyval'}) { if ($event->{'keyval'} == 65307) { $filesystem_window->destroy; undef $offset; } } }, ); $filesystem_window->set_policy( $true, $true, $false ); $filesystem_window->set_default_size( 300, 90 ); $filesystem_window->set_title( "Filesystem Box" ); $filesystem_window->border_width(1); my $main_vbox = Gtk::VBox->new( $false, 0 ); $filesystem_window->add( $main_vbox ); $main_vbox->show(); #my $table_filesystem = Gtk::Table->new( 3, 3, $true ); my $table_filesystem = Gtk::Table->new( 3, 2, $false ); ##$main_vbox->pack_start( $table_filesystem, $true, $true, 0 ); $main_vbox->pack_start( $table_filesystem, $true, $false, 0 ); $table_filesystem->show(); #_______________________________________ # Editor and execute options label("Filesystem Command: ",0,1,0,1,$table_filesystem); my $fs1 = entry(1,3,0,1,2,$table_filesystem); $fs1->set_text($main::makefs); $table_filesystem->set_row_spacing( 0, 2); #_______________________________________ # UML Exclusively # # root = not selected # normal user = forced selected if $fs_size > 8192 otherwise # not selected. # $uml_exclusively = new Gtk::CheckButton("UML Exclusively"); $uml_exclusively->active($uml_expect{uml_exclusively}); $uml_exclusively->signal_connect("button_press_event", sub { if ( $uml_exclusively->get_active() == 1 ) { $uml_expect{uml_exclusively} = 0; } else { $uml_expect{uml_exclusively} = 1; } # for Yard.pm $ars->{uml_exclusively} = $uml_expect{uml_exclusively}; ars2($ars); }); $uml_exclusively->signal_connect("key_press_event", sub { if ( $uml_exclusively->get_active() == 1 ) { $uml_expect{uml_exclusively} = 1; } else { $uml_expect{uml_exclusively} = 0; } # for Yard.pm $ars->{uml_exclusively} = $uml_expect{uml_exclusively}; ars2($ars); }); $table_filesystem->attach($uml_exclusively,0,1,1,2,['expand'], ['fill','shrink'],0,0); $uml_exclusively->show; #_______________________________________ # Preserve Ownership # # root = selected # normal user = not selected # my $preserve_ownership = new Gtk::CheckButton("Preserve Ownership"); #$uml_exclusively->signal_connect("clicked", \&which_stage, "check"); $table_filesystem->attach($preserve_ownership,2,3,1,2,['expand'], ['fill','shrink'],0,0); $preserve_ownership->active($uml_expect{preserve_ownership}); $preserve_ownership->signal_connect("button_press_event", sub { if ( $preserve_ownership->get_active() == 1 ) { $uml_expect{preserve_ownership} = 0; } else { $uml_expect{preserve_ownership} = 1; } $ars->{preserve_ownership} = $uml_expect{preserve_ownership}; ars2($ars); }); $preserve_ownership->show; #_______________________________________ # Submit button my $submit_b = button(0,1,2,3,"Submit",$table_filesystem); $submit_b->can_default(1); $submit_b->grab_default; # It actually works o.k. with $fs1 (which doesn't belong here). $fs1->signal_connect("key_press_event", sub { my $event = pop @_; if ($event->{'keyval'} == 65293) { $submit_b->clicked(); } }); $submit_b->signal_connect( "clicked", sub { if ($entry[2]) { # Check to see if it actually exists # unless UML Exclusively is used, then # supported fs types can be used even if they # don't exist on the host system. my $executable = (split(/\s+/,$entry[2]))[0]; if ( $uml_expect{uml_exclusively} == 0 ) { if (!find_file_in_path(basename($executable))) { if ( $executable ne "genext2fs" ) { error_window ("gBootRoot: ERROR: Enter a valid command"); return; } } if ($executable =~ m,/,) { if (! -e $executable) { error_window("gBootRoot: ERROR: " . "Enter a valid path for the command."); return; } } } # usinng uml_exlusively else { my %uml_helper_fs_types = qw(mke2fs 1 mkcramfs 1 genromfs 1 mkfs.minix 1 mkminix 1 mkreiserfs 1 mkfs.jffs 1 mkfs.jffs2 1); if ( !$uml_helper_fs_types{$executable} ) { error_window("ROOT_FS_HELPER ERROR: " . "These are supported " . "make fs commands:\n\nmke2fs mkcramfs" . " genromfs mkfs.minix mkminix mkreiserfs" . " mkfs.jffs mkfs.jffs2"); return; } } $main::makefs = $entry[2]; info(0,"Filesystem Command is $entry[2]\n"); } } ); #_______________________________________ # Close button my $close_b = button(2,3,2,3,"Close",$table_filesystem); $close_b->signal_connect("clicked", sub { $filesystem_window->destroy() if $filesystem_window; } ); } if (!visible $filesystem_window) { $filesystem_window->show(); } } # end sub file_system ########### # OBJCOPY # ########### # There is a subtle, but important difference between set_active and # active which makes the next magic possible. set_active is like actually # pressing the button. It's a lot easier to work with checkbuttons than # with radio buttons, because there is no easy way to establish a group. # The use of hide() and show() can really create some magic. my $lib_strip_all; my $lib_strip_debug; my $strip_bool = 1; sub strip_all { $lib_strip_debug->active(0); $strip_bool = 1; # print"$strip_bool\n"; } sub strip_debug { $lib_strip_all->active(0); $strip_bool = 0; # print "$strip_bool\n"; } ########## # STAGES # ########## my $stages_bool = "one-by-one"; my $one_by_one; my $continuous; my $user_defined; sub stages_one_by_one { $continuous->active(0); $user_defined->active(0); $stages_bool = "one-by-one"; # print "$stages_bool\n"; } sub stages_continuous { $one_by_one->active(0); $user_defined->active(0); $stages_bool = "continuous"; # print "$stages_bool\n"; } sub stages_user_defined { $one_by_one->active(0); $continuous->active(0); $stages_bool = "user-defined"; # print "$stages_bool\n"; } my $continue = { check => 0, dep => 0, space => 0, copy => 0, create => 0, test => 0, }; my @check_boxes; # Makes main checkbuttons act like radiobuttons # Applies to both one_by_one & continuous, # otherwise just normal click capabilities (expert mode). sub which_stage { my($widget,$name) = @_; my ($thing,$name_cmp); @check_boxes = ($check, $dep, $space, $create, $create_expect_uml, $test); if ($stages_bool eq "one-by-one" or $stages_bool eq "continuous") { foreach $thing (@check_boxes) { if ($thing ne $widget) { $thing->hide(); $thing->active($false); $thing->show(); } } # Finally we just reset %continue to reflect the button pressed. # Either the user can back up when doing one-by-one or it # automatically starts again if the text has been modified. # 0 0 0 0 0 # 1 0 0 0 0 # 1 1 0 0 0 # 1 1 1 0 0 # 1 1 1 1 0 # 1 1 1 1 1 # 0 everything if ($name eq "check") { foreach $name_cmp (%$continue) { $continue->{$name_cmp} = 0; } } # 1 0 0 0 0 elsif ($name eq "dep") { foreach $name_cmp (%$continue) { if ($name_cmp ne "check") { $continue->{$name_cmp} = 0; } } } elsif ($name eq "space") { foreach $name_cmp (%$continue) { if ($name_cmp ne "check" && $name_cmp ne "dep") { $continue->{$name_cmp} = 0; } } } elsif ($name eq "create") { foreach $name_cmp (%$continue) { if ($name_cmp ne "check" && $name_cmp ne "dep" && $name_cmp ne "space") { $continue->{$name_cmp} = 0; } } } elsif ($name eq "create_expect_uml") { foreach $name_cmp (%$continue) { if ($name_cmp ne "check" && $name_cmp ne "dep" && $name_cmp ne "space" && $name_cmp ne "create") { $continue->{$name_cmp} = 0; } } } elsif ($name eq "test") { foreach $name_cmp (%$continue) { if ($name_cmp ne "check" && $name_cmp ne "dep" && $name_cmp ne "space" && $name_cmp ne "create" && $name_cmp ne "create_expect_uml") { $continue->{$name_cmp} = 0; } } } # for (keys %$continue) { print $_, "=>", $continue->{$_}, "\n"; } } # end if one-by-one or continuous } sub continue { my $thing; # This has to go sequentially, but backwards is o.k. if ($stages_bool eq "one-by-one" || $stages_bool eq "continuous") { if ( $continue->{check} == 0 ) { check(); foreach $thing (@check_boxes) { $thing->hide(); $thing->active($false); $thing->show(); } $dep->hide(); $dep->active($true); $dep->show(); $continue->{check} = 1; return if $stages_bool eq "one-by-one"; } if ( $continue->{dep} == 0 ) { links_deps(); foreach $thing (@check_boxes) { $thing->hide(); $thing->active($false); $thing->show(); } $space->hide(); $space->active($true); $space->show(); $continue->{dep} = 1; return if $stages_bool eq "one-by-one"; } if ( $continue->{space} == 0 ) { space_left(); foreach $thing (@check_boxes) { $thing->hide(); $thing->active($false); $thing->show(); } $create->hide(); $create->active($true); $create->show(); $continue->{space} = 1; return if $stages_bool eq "one-by-one"; } if ( $continue->{copy} == 0 ) { create(); foreach $thing (@check_boxes) { $thing->hide(); $thing->active($false); $thing->show(); } $create_expect_uml->hide(); $create_expect_uml->active($true); $create_expect_uml->show(); $continue->{copy} = 1; return if $stages_bool eq "one-by-one"; } if ( $continue->{create} == 0 ) { create_uml(); foreach $thing (@check_boxes) { $thing->hide(); $thing->active($false); $thing->show(); } $test->hide(); $test->active($true); $test->show(); $continue->{create} = 1; return if $stages_bool eq "one-by-one"; } if ( $continue->{test} == 0 ) { test(); foreach $thing (@check_boxes) { $thing->hide(); $thing->active($false); $thing->show(); } $continue->{test} = 1; return if $stages_bool eq "one-by-one"; } } elsif ($stages_bool eq "user-defined") { if ($check->get_active()) { check(); $check->hide(); $check->active($false); $check->show(); } if ($dep->get_active()) { links_deps(); $dep->hide(); $dep->active($false); $dep->show(); } if ($space->get_active()) { space_left(); $space->hide(); $space->active($false); $space->show(); } if ($create->get_active()) { create(); $create->hide(); $create->active($false); $create->show(); } if ($create_expect_uml->get_active()) { create_uml(); $create_expect_uml->hide(); $create_expect_uml->active($false); $create_expect_uml->show(); } if ($test->get_active()) { test(); $test->hide(); $test->active($false); $test->show(); } } } # end sub continue sub check { my $error = read_contents_file( "$template_dir$template", $tmp, $filesystem_size, \%uml_expect ); return if $error && $error eq "ERROR"; } ############ # NSS PAM # ############ my %nss_pam = ( 60 => { conf_nss => 1, }, 61 => { conf_pam => 1, }, ); sub nss_pam { my ($widget,$action) = @_; my @label = keys( % { $nss_pam{$action} } ); # off if ($nss_pam{$action}{$label[0]} == 1) { $nss_pam{$action}{$label[0]} = 0; } # on else { $nss_pam{$action}{$label[0]} = 1; } } sub links_deps { my $error = extra_links($changed_text, \%nss_pam); return if $error && $error eq "ERROR"; $error = hard_links(); return if $error && $error eq "ERROR"; $error = library_dependencies("$template_dir$template"); return if $error && $error eq "ERROR"; } sub space_left { $lib_bool = "" if $lib_bool eq 0; $bin_bool = "" if $bin_bool eq 0; $mod_bool = "" if $mod_bool eq 0; my $error = space_check($filesystem_size, $lib_bool, $bin_bool, $mod_bool, $strip_bool, $tmp); return if $error && $error eq "ERROR"; } # This is the copy stage sub create { $lib_bool = "" if $lib_bool eq 0; $bin_bool = "" if $bin_bool eq 0; $mod_bool = "" if $mod_bool eq 0; # my $error = create_filesystem($filename,$filesystem_size,$filesystem_type, # $inode_size,$tmp,$lib_bool,$bin_bool, # $mod_bool,$strip_bool); my $error = create_filesystem($filename,$filesystem_size,$tmp,$lib_bool, $bin_bool,$mod_bool,$strip_bool, \%uml_expect); return if $error && $error eq "ERROR"; } sub create_uml { create_expect_uml($filesystem_size, $tmp, $filename); } ######### # TESTS # ######### my %tests = ( 30 => { test_fstab => 1, }, 31 => { test_inittab => 1, }, 32 => { test_scripts => 1, }, 33 => { test_links => 1, }, 34 => { test_passwd => 1, }, 35 => { test_pam => 1, }, 36 => { test_nss => 1, }, ); sub tests { my ($widget,$action) = @_; my @label = keys( % { $tests{$action} } ); # off if ($tests{$action}{$label[0]} == 1) { $tests{$action}{$label[0]} = 0; } # on else { $tests{$action}{$label[0]} = 1; } ## print "$label[0]", $tests{$action}{$label[0]} , "\n"; } sub test { # Need to know whether genext2fs is being used my $fs_type = (split(/\s/,$main::makefs))[0]; # unecessary logic ## if ( $fs_type ne "genext2fs" ) { ## $tests{30}{test_fstab} = 0; ## $tests{31}{test_inittab} = 0; ## $tests{32}{test_scripts} = 0; ## } my $error = which_tests(\%tests); return if $error && $error eq "ERROR"; } ######################### # CHECK STAGE VARIABLES # ######################### my %checks = ( 16 => { fstab => 0, }, ## 18 => { ## fstab_directory_name => 0, ## }, ## 17 => { ## rc => 0, ## } ); # try show hide & use variables sub check_stage { my ($widget,$action) = @_; my @label = keys( %{ $checks{$action} } ); # off if ($checks{$action}{$label[0]} == 1) { $checks{$action}{$label[0]} = 0; ## if ($label[0] eq "fstab") { ## $item_factory->delete_item ## ('/Create/Replacements/fstab directory name'); ## } } # on else { $checks{$action}{$label[0]} = 1; # Fancy, but not quite what I want ## if ($label[0] eq "fstab") { ## $item_factory->delete_item ## ('/Create/Replacements/fstab directory name'); ## $item_factory->create_item ## (['/Create/Replacements/fstab directory name', ## undef, undef, <Item>]); ## } } # print "$label[0]", $checks{$action}{$label[0]} , "\n"; if ($label[0] eq "fstab") { if ($checks{$action}{$label[0]} == 1) { create_fstab("$main::global_yard/Replacements/etc/fstab.new"); } } } ########### # YARDBOX # ########### # cut little booleans for Gtk::CheckMenuItem my $replacement_bool = 1; my $module_bool = 1; my $start_length; sub yard_box { $main::yard_window = new Gtk::Window "toplevel"; $main::yard_window->signal_connect("destroy", \&destroy_window, \$main::yard_window); $main::yard_window->signal_connect("delete_event",\&destroy_window, \$main::yard_window); $main::yard_window->signal_connect("destroy", sub { $search_window->destroy if $search_window; } ); $main::yard_window->signal_connect("delete_event", sub { $search_window->destroy if $search_window; }); # Probably not such a good idea, but interesting to try ## $main::yard_window->signal_connect("key_press_event", sub { ## my $event = pop @_; ## if ($event->{'keyval'}) { ## if ($event->{'keyval'} == 65307) { ## $main::yard_window->destroy; ## } ## } ## }, ## ); $main::yard_window->set_usize( 525, 450 ); $main::yard_window->set_policy( $true, $true, $false ); $main::yard_window->set_title( "Yard Box - $template" ); $main::yard_window->border_width(0); my $main_vbox = new Gtk::VBox( $false, 0 ); $main::yard_window->add( $main_vbox ); $main_vbox->show(); my $vbox = new Gtk::VBox( $false, 0 ); $vbox->border_width( 0 ); $main_vbox->pack_start( $vbox, $false, $true, 0 ); $vbox->show(); #_______________________________________ # Item::Factory my $menubar = yard_menu($main::yard_window); $vbox->pack_start( $menubar, $false, $true, 0 ); $menubar->show(); $vbox = new Gtk::VBox( $false, 10 ); $vbox->border_width( 10 ); $main_vbox->pack_start( $vbox, $true, $true, 0 ); $vbox->show(); my $table = new Gtk::Table( 2, 2, $false ); $table->set_row_spacing( 0, 2 ); $table->set_col_spacing( 0, 2 ); $vbox->pack_start( $table, $true, $true, 0 ); $table->show( ); # This is necessary because the symbols are dependent on %ars for now. ##filesystem_size(); #_______________________________________ # Manipulate Gtk::ItemFactory - # The trick here is to use the real path. # GUIDE TO VARIABLES AND THEIR VALUES # # objcopy <RadioItem> # ------------------- # $strip_bool strip-all (default) # strip-debug # # stages <RadioItem> # ------------------ # one-by-one (default) # $stages_bool continuous # user-defined # # stripping <CheckItem> # --------------------- # on off # -- --- # $lib_bool 1 (default) 0 # $bin_bool 1 (default) 0 # $mod_bool 1 (default) 0 # # Checking Settings <CheckItem> # ----------------------------- # $replacement_bool 1 (default) 0 # $module_bool 1 (default) 0 # # Check Stage Variables HOH = %checks # ----------------------------------- # 16 fstab 1 0 (default) ## These next two were removed, because there isn't any ## script to make rc, and I can't remember what the # fstab directory name entry was for. :*? # 17 rc 1 0 (default # 18 'fstab directory name' if fstab == 0 # # Tests <CheckItem> HOH = %tests # -------------------------------- # 30 test_fstab 1 (default) 0 # 31 test_inittab 1 (default) 0 # 32 test_scripts 1 (default) 0 # 33 test_links 1 (default) 0 # 34 test_passwd 1 (default) 0 # 35 test_pam 1 (default) 0 # 36 test_nss 1 (default) 0 # # NSS PAM Conf <CheckItem> HOH = %nss_pam # ----------------------------------------- # 60 conf_nss 1 (default) 0 # 61 conf_nss 1 (default) 0 # Stages $one_by_one = $item_factory->get_item('/Edit/Stages/one-by-one'); $continuous = $item_factory->get_item('/Edit/Stages/continuous'); $user_defined = $item_factory->get_item('/Edit/Stages/user defined'); if ( $stages_bool eq "one-by-one" ) { $continuous->active(0); $user_defined->active(0); } elsif ( $stages_bool eq "continuous" ) { $one_by_one->active(0); $user_defined->active(0); } elsif ( $stages_bool eq "user-defined" ) { $one_by_one->active(0); $continuous->active(0); } # Stripping # Libraries my $lib_strip = $item_factory->get_item ('/Edit/Settings/Stripping/Libraries'); $lib_strip->signal_connect( "activate", sub { # off if ($lib_bool eq "") { $lib_bool = 0; } if ($lib_bool == 1) { $lib_bool--; } # on else { $lib_bool++; } #print "$lib_bool\n"; } ); $lib_bool == 1 ? $lib_strip->active($true) : $lib_strip->active($false); # objcopy parameters for Libraries $lib_strip_all = $item_factory->get_item ('/Edit/Settings/Stripping/settings/strip-all'); $lib_strip_debug = $item_factory->get_item ('/Edit/Settings/Stripping/settings/strip-debug'); $strip_bool == 1 ? $lib_strip_debug->active($false) : $lib_strip_all->active($false); # Binaries my $bin_strip = $item_factory->get_item ('/Edit/Settings/Stripping/Binaries'); $bin_strip->active($true); $bin_strip->signal_connect( "activate", sub { if ($bin_bool eq "") { $bin_bool = 0; } # off if ($bin_bool == 1) { $bin_bool--; } # on else { $bin_bool++; } #print "$bin_bool\n"; } ); $bin_bool == 1 ? $bin_strip->active($true) : $bin_strip->active($false); # Modules my $mod_strip = $item_factory->get_item ('/Edit/Settings/Stripping/Modules'); $mod_strip->active($true); $mod_strip->signal_connect( "activate", sub { # off if ($mod_bool eq "") { $mod_bool = 0; } if ($mod_bool == 1) { $mod_bool--; } # on else { $mod_bool++; } #print "$mod_bool\n"; } ); $mod_bool == 1 ? $mod_strip->active($true) : $mod_strip->active($false); # Checking - Replacements and/or Modules? # Replacements ## my $replacement_check = $item_factory->get_item ## ('/Edit/Settings/Replacements'); ## $replacement_check->active($true); ## $replacement_check->signal_connect( "activate", ## sub { # off ## if ($replacement_bool == 1) { ## $replacement_bool--; ## } # on ## else { ## $replacement_bool++; ## } ## print "$replacement_bool\n"; ## } ## ); # Modules ## my $modules_check = $item_factory->get_item('/Edit/Settings/Modules'); ## $modules_check->active($true); ## $modules_check->signal_connect( "activate", ## sub { # off ## if ($module_bool == 1) { ## $module_bool--; ## } # on ## else { ## $module_bool++; ## } ## print "$module_bool\n"; ## } ## ); # Tests my $test_fstab = $item_factory->get_item('/Tests/fstab'); $tests{30}{test_fstab} == 1 ? $test_fstab->active(1) : $test_fstab->active(0); my $test_inittab = $item_factory->get_item('/Tests/inittab'); $tests{31}{test_inittab} == 1 ? $test_inittab->active(1) : $test_inittab->active(0); my $test_scripts = $item_factory->get_item('/Tests/scripts'); $tests{32}{test_scripts} == 1 ? $test_scripts->active(1) : $test_scripts->active(0); my $test_links = $item_factory->get_item('/Tests/links'); $tests{33}{test_links} == 1 ? $test_links->active(1) : $test_links->active(0); my $test_passwd = $item_factory->get_item('/Tests/passwd'); $tests{34}{test_passwd} == 1 ? $test_passwd->active(1) : $test_passwd->active(0); my $test_pam = $item_factory->get_item('/Tests/pam'); $tests{35}{test_pam} == 1 ? $test_pam->active(1) : $test_pam->active(0); my $test_nss = $item_factory->get_item('/Tests/nss'); $tests{36}{test_nss} == 1 ? $test_nss->active(1) : $test_nss->active(0); # PAM NSS Conf my $conf_nss = $item_factory->get_item('/Edit/Settings/NSS Config'); $nss_pam{60}{conf_nss} == 1 ? $conf_nss->active(1) : $conf_nss->active(0); my $conf_pam = $item_factory->get_item('/Edit/Settings/PAM Config'); $nss_pam{61}{conf_pam} == 1 ? $conf_pam->active(1) : $conf_pam->active(0); #_______________________________________ # Create the GtkText widget $text = new Gtk::Text( undef, undef ); $text->set_editable($true); #$text->signal_connect("activate", sub { $text->signal_connect("changed", sub { my $new_length = $text->get_length(); $changed_text_from_template = $text->get_chars(0,$new_length); } ); $table->attach( $text, 0, 1, 0, 1, [ 'expand', 'shrink', 'fill' ], [ 'expand', 'shrink', 'fill' ], 0, 0 ); $text->grab_focus(); $text->show(); $text->freeze(); $text->insert( undef, undef, undef, $changed_text_from_template); $text->thaw(); $start_length = $text->get_length(); # Add a vertical scrollbar to the GtkText widget my $vscrollbar = new Gtk::VScrollbar( $text->vadj ); $table->attach( $vscrollbar, 1, 2, 0, 1, 'fill', [ 'expand', 'shrink', 'fill' ], 0, 0 ); $vscrollbar->show(); #_______________________________________ # Separator my $separator = new Gtk::HSeparator(); $main_vbox->pack_start( $separator, $false, $true, 0 ); $separator->show(); #_______________________________________ # Check stage boxes # check | links & deps | space | create | test $vbox = new Gtk::HBox( $false, 0 ); $vbox->border_width( 0 ); $main_vbox->pack_start( $vbox, $false, $true, 0 ); $vbox->show(); $check = new Gtk::CheckButton("Check"); $check->signal_connect("clicked", \&which_stage, "check"); $vbox->pack_start( $check, $true, $true, 10 ); show $check; $dep = new Gtk::CheckButton("Links & Deps"); $dep->signal_connect("clicked", \&which_stage, "dep"); $vbox->pack_start( $dep, $true, $true, 0 ); show $dep; $space = new Gtk::CheckButton("Space Left"); $space->signal_connect("clicked", \&which_stage, "space"); $vbox->pack_start( $space, $true, $true, 0 ); show $space; $create = new Gtk::CheckButton("Copy"); $create->signal_connect("clicked", \&which_stage, "create"); $vbox->pack_start( $create, $true, $true, 0 ); show $create; $create_expect_uml = new Gtk::CheckButton("Create"); $create_expect_uml->signal_connect("clicked", \&which_stage, "create"); $vbox->pack_start( $create_expect_uml, $true, $true, 0 ); show $create_expect_uml; $test = new Gtk::CheckButton("Test"); $test->signal_connect("clicked", \&which_stage, "test"); $vbox->pack_start( $test, $true, $true, 0 ); show $test; # sets up default radiobutton behavior which_stage("check","check"); $check->active($true); #_______________________________________ # Separator $separator = new Gtk::HSeparator(); $main_vbox->pack_start( $separator, $false, $true, 0 ); $separator->show(); #_______________________________________ # Continue - Close - Save Buttons $vbox = new Gtk::HBox( $false, 10 ); $vbox->border_width( 10 ); $main_vbox->pack_start( $vbox, $false, $true, 0 ); $vbox->show(); $continue_button = new Gtk::Button( "Continue" ); $continue_button->signal_connect( 'clicked', \&continue); $vbox->pack_start( $continue_button, $true, $true, 0 ); $continue_button->show(); $close_button = new Gtk::Button( "Close" ); $close_button->signal_connect( 'clicked', sub { destroy $main::yard_window; } ); $vbox->pack_start( $close_button, $true, $true, 0 ); $close_button->show(); $save_button = new Gtk::Button( "Save" ); # This sub can be used by all the saved buttons $save_button->signal_connect( 'clicked', \&saved, 102); $vbox->pack_start( $save_button, $true, $true, 0 ); $save_button->show(); # chrooted tests not wanted for non-root user if ( $> != 0 ) { $item_factory->delete_item('/Tests/fstab'); $item_factory->delete_item('/Tests/inittab'); $item_factory->delete_item('/Tests/scripts'); } show $main::yard_window; } # end sub yard_box sub saved { my ($widget,$whoami) = @_; my $error; $text->activate(); # It's not necessary to use lsMode, but it's a cool program by MJD. if ($whoami == 100 || $whoami == 102 ) { if ( file_mode("$template_dir$template") =~ /l/ ) { error_window("gBootRoot: ERROR: " . "$template_dir$template is not " . "writable.\nUse [ File->Save As ] or " . "[Alt-A] with the yard suffix."); } elsif ( file_mode("$template_dir$template") !~ /w/ ) { error_window("gBootRoot: ERROR: " . "$template_dir$template is not " . "writable.\nUse [ File->Save As ] or " . "[Alt-A] with the yard suffix."); } else { # Here's where we get to undef Yard variable and start over at # check my $new = "$template_dir$template" . ".new"; open(NEW,">$new") or ($error = error("Can't create $new")); return if $error && $error eq "ERROR"; print NEW $changed_text_from_template; close(NEW); rename($new, "$template_dir$template") or ($error = error("Can't rename $new to " . "$template_dir$template")); return if $error && $error eq "ERROR"; } } elsif ($whoami == 101 || $whoami == 103) { save_as($whoami); } } # end sub saved # rindex and index makes things easy # This can be added to other widgets. sub search { if (not defined $search_window) { $search_window = Gtk::Window->new("toplevel"); $search_window->set_transient_for($main::yard_window); $search_window->signal_connect("destroy", \&destroy_window, \$search_window); $search_window->signal_connect("delete_event", \&destroy_window, \$search_window); $search_window->signal_connect("key_press_event", sub { my $event = pop @_; if ($event->{'keyval'}) { if ($event->{'keyval'} == 65307) { $search_window->destroy; undef $offset; } } }, ); $search_window->set_policy( $true, $true, $false ); $search_window->set_title( "gBootRoot: Search" ); $search_window->border_width(1); $search_window->set_position('mouse'); my $main_vbox = Gtk::VBox->new( $false, 0 ); $search_window->add( $main_vbox ); $main_vbox->show(); my $table_search = Gtk::Table->new( 4, 3, $true ); $main_vbox->pack_start( $table_search, $true, $true, 0 ); $table_search->show(); #_______________________________________ # Search keywords label("Search:",0,1,0,1,$table_search); my $search1 = entry(1,3,0,1,0,$table_search); $search1->signal_connect("changed", sub { $search_text = $search1->get_text(); }); $search1->set_text($search_text) if defined $search_text; $search1->select_region(0,length($search1->get_text)); #_______________________________________ # Case Sensitive my $case_sensitive = new Gtk::CheckButton("Case Sensitive"); $table_search->attach($case_sensitive,1,2,1,2, ['shrink','fill','expand'],['fill','shrink'],0,0); $case_sensitive->show(); #_______________________________________ # Search Backwards my $search_backwards = new Gtk::CheckButton("Search Backwards"); $table_search->attach($search_backwards,2,3,1,2, ['shrink','fill','expand'],['fill','shrink'],0,0); $search_backwards->show(); #_______________________________________ # Separator my $separator = new Gtk::HSeparator(); $table_search->attach($separator,0,3,2,3, ['shrink','fill','expand'],['fill','shrink'],0,0); $separator->show(); #_______________________________________ # Search button my ($keywords, $old_keywords, $before_offset); my ($tmp_ct, $tmp_k); my $submit_b = button(0,1,3,4,"Search",$table_search); $search1->signal_connect("key_press_event", sub { my $event = pop @_; if ($event->{'keyval'} == 65293) { $submit_b->clicked(); } }); $submit_b->can_default(1); $search_window->set_default($submit_b); $submit_b->grab_default; $submit_b->signal_connect( "clicked", sub { my $keywords = $search1->get_text(); $before_offset = $offset if $offset != -1; if ($old_keywords ne $keywords) { undef $before_offset; } # rindex if ($search_backwards->active) { if (!$offset) { if(!$case_sensitive->active) { if (!$tmp_ct && !$tmp_k) { ($tmp_ct = $changed_text_from_template) =~ tr/A-Z/a-z/; ($tmp_k = $keywords) =~ tr/A-Z/a-z/; } if ($tmp_k && $tmp_k ne $keywords) { ($tmp_k = $keywords) =~ tr/A-Z/a-z/; } if ($tmp_ct && $tmp_ct ne $changed_text_from_template) { ($tmp_ct = $changed_text_from_template) =~ tr/A-Z/a-z/; } $offset = rindex($tmp_ct, $tmp_k); } else { $offset = rindex($changed_text_from_template, $keywords); } if ($offset != -1) { my $length = length($keywords); $text->set_position($offset); $text->get_chars($offset, $length); $length = $length + $offset; $text->select_region($offset, $length); } # Here is an initial search and nothing is found if (!$before_offset && $offset == -1) { error_window("Search string \'$keywords\' not found."); undef $offset; undef $before_offset; return; } } else { $offset = $offset - 1; if(!$case_sensitive->active) { if (!$tmp_ct && !$tmp_k) { ($tmp_ct = $changed_text_from_template) =~ tr/A-Z/a-z/; ($tmp_k = $keywords) =~ tr/A-Z/a-z/; } if ($tmp_k && $tmp_k ne $keywords) { ($tmp_k = $keywords) =~ tr/A-Z/a-z/; } if ($tmp_ct && $tmp_ct ne $changed_text_from_template) { ($tmp_ct = $changed_text_from_template) =~ tr/A-Z/a-z/; } $offset = rindex($tmp_ct, $tmp_k, $offset); } else { $offset = rindex($changed_text_from_template, $keywords, $offset); } if ($offset != -1) { my $length = length($keywords); $text->set_position($offset); $text->get_chars($offset, $length); $length = $length + $offset; $text->select_region($offset,$length); } else { $offset = ""; my $tmp_offset; if (!$case_sensitive->active) { $tmp_offset = rindex($tmp_ct, $tmp_k); } else { $tmp_offset = rindex($changed_text_from_template, $keywords); } question_window("Beginning of document reached; " . "continue from end?", $search_window, $submit_b, -1); } } } # index else { if (!$offset) { if(!$case_sensitive->active) { if (!$tmp_ct && !$tmp_k) { ($tmp_ct = $changed_text_from_template) =~ tr/A-Z/a-z/; ($tmp_k = $keywords) =~ tr/A-Z/a-z/; } if ($tmp_k && $tmp_k ne $keywords) { ($tmp_k = $keywords) =~ tr/A-Z/a-z/; } if ($tmp_ct && $tmp_ct ne $changed_text_from_template) { ($tmp_ct = $changed_text_from_template) =~ tr/A-Z/a-z/; } $offset = index($tmp_ct, $tmp_k); } else { $offset = index($changed_text_from_template, $keywords); } if ($offset != -1) { my $length = length($keywords); $text->set_position($offset); $text->get_chars($offset, $length); $length = $length + $offset; $text->select_region($offset, $length); } # Here is an initial search and nothing is found if (!$before_offset && $offset == -1) { error_window("Search string \'$keywords\' not found."); undef $offset; undef $before_offset; return; } } else { $offset = $offset + 1; if(!$case_sensitive->active) { if (!$tmp_ct && !$tmp_k) { ($tmp_ct = $changed_text_from_template) =~ tr/A-Z/a-z/; ($tmp_k = $keywords) =~ tr/A-Z/a-z/; } if ($tmp_k && $tmp_k ne $keywords) { ($tmp_k = $keywords) =~ tr/A-Z/a-z/; } if ($tmp_ct && $tmp_ct ne $changed_text_from_template) { ($tmp_ct = $changed_text_from_template) =~ tr/A-Z/a-z/; } $offset = index($tmp_ct, $tmp_k, $offset); } else { $offset = index($changed_text_from_template, $keywords, $offset); } if ($offset != -1) { my $length = length($keywords); $text->set_position($offset); $text->get_chars($offset, $length); $length = $length + $offset; $text->select_region($offset,$length); } elsif (!$before_offset && $offset == -1) { # Here is a continued search and nothing is found # We want the question_window to come up first # Then pop this error box. question_window("End of document reached;" . " continue from beginning?", $search_window,$submit_b, length($changed_text_from_template)); $before_offset = -100; } # The previous elsif continues. elsif ($before_offset && $before_offset == -100) { error_window("Search string \'$keywords\' not" . " found."); undef $offset; undef $before_offset; return; } else { question_window("End of document reached;" . " continue from beginning?", $search_window,$submit_b, length($changed_text_from_template)); } } } $old_keywords = $keywords; } ); #_______________________________________ # Cancel button my $close_b = button(2,3,3,4,"Cancel",$table_search); $close_b->signal_connect("clicked", sub { undef $offset; $search_window->destroy() if $search_window; } ); } if (!visible $search_window) { $search_window->show(); } } # end sub search # Just a universal dialog box with OK and Cancel sub question_window { my ($output,$widget, $widget_button, $tmp_offset) = @_; my ($ok_button, $c_button); if (not defined $question_window) { $question_window = new Gtk::Dialog; $question_window->set_modal($true); $question_window->set_transient_for($widget); $question_window->signal_connect("destroy", \&destroy_window, \$question_window); $question_window->signal_connect("delete_event", \&destroy_window, \$question_window); $question_window->signal_connect("key_press_event", sub { my $event = pop @_; if ($event->{'keyval'}) { if ($event->{'keyval'} == 65307) { $offset = $tmp_offset; $question_window->destroy } elsif ($event->{'keyval'} == 65293) { $widget_button->clicked; $question_window->destroy; } } }); $question_window->set_title("gBootRoot Question?"); $question_window->border_width(15); my $label = new Gtk::Label($output); #$label->set_justify("left") if $_[1]; $question_window->vbox->pack_start( $label, $true, $true, 15 ); $label->show(); # OK button #---------------------------------------- $ok_button = new Gtk::Button("OK"); $ok_button->signal_connect("clicked", sub { $widget_button->clicked; $question_window->destroy; }); $ok_button->can_default(1); $question_window->action_area->pack_start($ok_button, $false, $false,0); $ok_button->grab_default; $ok_button->show; # Cancel button #---------------------------------------- $c_button = new Gtk::Button("Cancel"); $c_button->signal_connect("clicked", sub { $offset = $tmp_offset; $question_window->destroy if $question_window; }); $question_window->action_area->pack_start($c_button, $false, $false,0); $c_button->show; } if (!visible $question_window) { $question_window->show; } return ($ok_button,$c_button); } # end sub question_window sub yard_menu { my ($window) = @_; my $accel_group = new Gtk::AccelGroup(); $item_factory = new Gtk::ItemFactory( 'Gtk::MenuBar', '<main>', $accel_group ); $accel_group->attach($window); $item_factory->create_items(@menu_items); ##$item_factory->delete_item('/File/Checkbox'); ##$item_factory->create_item(['/File/Checkbox', undef, undef, <Item>]); return ( $item_factory->get_widget( '<main>' ) ); } # This will just be a simple dialog, and doubles as New Template as # well as Save As my $write_over; sub save_as { # Will just use a dialog box. my ($whoami) = @_; my $error; if (not defined $save_as) { $save_as = Gtk::Dialog->new(); $save_as->signal_connect("destroy", \&destroy_window, \$save_as); $save_as->signal_connect("delete_event", \&destroy_window, \$save_as); $save_as->signal_connect("key_press_event", sub { my $event = pop @_; if ($event->{'keyval'}) { if ($event->{'keyval'} == 65307) { $save_as->destroy; } } }, ); $whoami == 101 ? $save_as->set_title("Save As") : $save_as->set_title("New Template"); $save_as->border_width(12); $save_as->set_position('center'); my $new_template; my $entry = Gtk::Entry->new(); $entry->set_editable( $true ); if ( $whoami == 101 ) { $entry->set_text($template) if $template; } $entry->signal_connect( "changed", sub { $new_template = $entry->get_text(); }); $save_as->vbox->pack_start( $entry, $false, $false, 0); $entry->show(); my $label = Gtk::Label->new(); $label->set_justify( 'left' ); #$label->set_pattern("_________") if defined $pattern; $save_as->vbox->pack_start( $label, $false, $false, 2 ); $label->show(); my $button = Gtk::Button->new("OK"); my $new_template_tmp = "nothing"; my $event_count = 0; $button->signal_connect("clicked", sub { # Here's where we get to undef Yard variable and start over at # check my $new = "$template_dir$new_template" if $new_template; if ( $whoami == 101 ) { if (!$new_template) { if ( file_mode("$template_dir$template") =~ /l/ ) { error_window("gBootRoot: ERROR: " . "$template_dir$template is not " . "writable.\nUse [ File->Save As ] or " . "[Alt-S] with the yard suffix."); $save_as->destroy; return; } elsif ( file_mode("$template_dir$template") !~ /w/ ) { error_window("gBootRoot: ERROR: " . "$template_dir$template is not " . "writable.\nUse [ File->Save As ] or " . "[Alt-S] with the yard suffix."); $save_as->destroy; return; } } } # $whoami == 101 # An open template should just be saved not saved_as. if (!$new_template) { error_window("gBootRoot: ERROR: $template already exists, " . "use Save instead."); $save_as->destroy; return; } # An existing file shouldn't be written over unless the user wants # this to happen. if (!-f $new) { open(NEW,">$new") or ($error = error("Can't create $new")); return if $error && $error eq "ERROR"; if ( $whoami == 101 ) { print NEW $changed_text_from_template; } elsif ( $whoami == 103 ) { my $text_length = $text->get_length(); $text->set_point($text_length); $text->backward_delete($text->get_length()); print NEW ""; } close(NEW); $template = $new_template; opendir(DIR,$template_dir) if -d $template_dir; my @templates = grep { m,\.yard$, } readdir(DIR) if $template_dir; closedir(DIR); $main::combo->set_popdown_strings( @templates ) if @templates; $main::combo->entry->set_text($new_template); $main::yard_window->set_title( "Yard Box - $template" ); $save_as->destroy; } else { if ( file_mode("$new") =~ /l/ ) { error_window("gBootRoot: ERROR: " . "$new is not " . "writable.\nUse [ File->Save As ] or " . "[Alt-S] with the yard suffix."); $save_as->destroy; return; } elsif ( file_mode("$new") !~ /w/ ) { error_window("gBootRoot: ERROR: " . "$new is not " . "writable.\nUse [ File->Save As ] or " . "[Alt-S] with the yard suffix."); $save_as->destroy; return; } if ( $whoami == 101 ) { $label->set_text("$new_template already exists, " . "do\nyou want to write over it, " . "or\nsave $template with a different name?"); } elsif ( $whoami == 103 ) { $label->set_text("$new_template already exists, " . "do\nyou want to write over it?"); } $event_count++; my $event = pop(@_); if ($new_template eq $new_template_tmp) { if ($event_count >= 2 && $event && $event eq "clicked") { open(NEW,">$new") or ($error = error("Can't create $new")); return if $error && $error eq "ERROR"; if ( $whoami == 101 ) { print NEW $changed_text_from_template; } elsif ( $whoami == 103 ) { my $text_length = $text->get_length(); $text->set_point($text_length); $text->backward_delete($text->get_length()); print NEW ""; } close(NEW); $template = $new_template; opendir(DIR,$template_dir) if -d $template_dir; my @templates = grep { m,\.yard$, } readdir(DIR) if $template_dir; closedir(DIR); $main::combo->set_popdown_strings( @templates ) if @templates; $main::combo->entry->set_text($new_template); $main::yard_window->set_title( "Yard Box - $template" ); $event_count = 0; $save_as->destroy; } } $new_template_tmp = $new_template; } }, "clicked"); $button->can_default(1); $save_as->action_area->pack_start($button, $false, $false,0); $button->grab_default; $button->show; $button = Gtk::Button->new("Cancel"); $button->signal_connect("clicked", sub { destroy $save_as} ); $save_as->action_area->pack_start($button, $false, $false,0); $button->show; } if (!visible $save_as) { show $save_as; } else { destroy $save_as; #save_as($error,$count) if $error == 0; } } # end sub save_as sub tutorial { if (not defined $tutorial) { $tutorial = Gtk::Dialog->new(); $tutorial->signal_connect("destroy", \&destroy_window, \$tutorial); $tutorial->signal_connect("delete_event", \&destroy_window, \$tutorial); $tutorial->set_title("Tutorial"); $tutorial->border_width(12); $tutorial->set_position('center'); my $label = Gtk::Label-> new("Tutorial is in /usr/share/doc/gbootroot/html/index.html."); $label->set_justify( 'left' ); # $label->set_pattern("_________"); $tutorial->vbox->pack_start( $label, $false, $false, 2 ); $label->show(); my $button = Gtk::Button->new("OK"); $button->signal_connect("clicked", sub { $tutorial->destroy; }); $button->can_default(1); $tutorial->action_area->pack_start($button, $false, $false,0); $button->grab_default; $button->show; } if (!visible $tutorial) { $tutorial->show(); } else { $tutorial->destroy(); } } # end sub tutorial sub shortcut { if (not defined $shortcut) { $shortcut = Gtk::Dialog->new(); $shortcut->signal_connect("destroy", \&destroy_window, \$shortcut); $shortcut->signal_connect("delete_event", \&destroy_window, \$shortcut); $shortcut->set_title("Shortcuts"); $shortcut->border_width(12); $shortcut->set_position('center'); my $label = Gtk::Label->new($Shortcuts); $label->set_justify( 'left' ); # $label->set_pattern("_________"); $shortcut->vbox->pack_start( $label, $false, $false, 2 ); $label->show(); my $button = Gtk::Button->new("OK"); $button->signal_connect("clicked", sub { $shortcut->destroy; }); $button->can_default(1); $shortcut->action_area->pack_start($button, $false, $false,0); $button->grab_default; $button->show; } if (!visible $shortcut) { $shortcut->show(); } else { $shortcut->destroy(); } } $Shortcuts = << "SHORTCUTS"; Motion Shortcuts Ctrl-A Beginning of line Ctrl-E End of line Ctrl-N Next Line Ctrl-P Previous Line Ctrl-B Backward one character Ctrl-F Forward one character Alt-B Backward one word Alt-F Forward one word Ctrl-Home Beginning of buffer Ctrl-End End of buffer Editing Shortcuts Ctrl-H Delete Backward Character (Backspace) Ctrl-D Delete Forward Character (Delete) Ctrl-W Delete Backward Word Alt-D Delete Forward Word Ctrl-K Delete to end of line Ctrl-U Delete line Selection Shortcuts Ctrl-X Cut to clipboard Ctrl-C Copy to clipboard Ctrl-V Paste from clipboard Searching Shortcuts Alt-S Search Template File Shortcuts Alt-N New Template Ctrl-S Save File Alt-A Save As File Yard Box Shortcuts Alt-W Close Esc Close SHORTCUTS sub path { if (not defined $path_window) { $path_window = Gtk::Window->new("toplevel"); $path_window->signal_connect("destroy", \&destroy_window, \$path_window); $path_window->signal_connect("delete_event", \&destroy_window, \$path_window); $path_window->set_policy( $true, $true, $false ); $path_window->set_title( "Path Box" ); $path_window->set_usize( 450, "" ); $path_window->border_width(1); my $main_vbox = Gtk::VBox->new( $false, 0 ); $path_window->add( $main_vbox ); $main_vbox->show(); my $table_path = Gtk::Table->new( 2, 3, $true ); $main_vbox->pack_start( $table_path, $true, $true, 0 ); $table_path->show(); #_______________________________________ # Editor and execute options label("Extra Path(s):",0,1,0,1,$table_path); my $path11 = entry(1,3,0,1,3,$table_path); #$fs1->set_text(":"); $table_path->set_row_spacing( 0, 2); #_______________________________________ # Submit button my $submit_b = button(0,1,1,2,"Submit",$table_path); $submit_b->signal_connect( "clicked", sub { if ($entry[3]) { my @pathlist = split(':', $ENV{'PATH'}); @main::additional_dirs = split(/:|\s+|,/,$entry[3]); my @additional_dirs; # Check to see if this path doesn't already exist. foreach my $alt_path ( @main::additional_dirs ) { my $add_path = grep(/$alt_path/,$ENV{'PATH'}); if ($add_path == 0) { push(@additional_dirs, $alt_path); } } info(0, "Search path is now:\n", join(" ", @additional_dirs), " ", join(" ", @pathlist), "\n"); } } ); #_______________________________________ # Close button my $close_b = button(2,3,1,2,"Close",$table_path); $close_b->signal_connect("clicked", sub { $path_window->destroy() if $path_window; } ); } if (!visible $path_window) { $path_window->show(); } else { $path_window->destroy; } } sub Replacements { if (not defined $replacements_window) { $replacements_window = Gtk::Window->new("toplevel"); $replacements_window->signal_connect("destroy", \&destroy_window, \$replacements_window); $replacements_window->signal_connect("delete_event", \&destroy_window, \$replacements_window); $replacements_window->set_policy( $true, $true, $false ); $replacements_window->set_default_size( 525, 90 ); $replacements_window->set_title( "Replacements Box" ); $replacements_window->border_width(1); my $main_vbox = Gtk::VBox->new( $false, 0 ); $replacements_window->add( $main_vbox ); $main_vbox->show(); #my $table_replacements = Gtk::Table->new( 3, 3, $true ); my $table_replacements = Gtk::Table->new( 5, 3, $false ); #$main_vbox->pack_start( $table_replacements, $true, $true, 0 ); $main_vbox->pack_start( $table_replacements, $true, $false, 0 ); $table_replacements->show(); #_______________________________________ # Editor and execute options label("Editor:",0,1,0,1,$table_replacements); my $repl1 = entry(1,5,0,1,0,$table_replacements); $repl1->set_text($main::editor); #my $tooltips = Gtk::Tooltips->new(); # $tooltips->set_tip( $repl1, # "Choose an editory with " . # "its executable option switch.", # "" ); #_______________________________________ # Replacement file label("Replacement:",0,1,1,2,$table_replacements); my $repl2 = entry(1,4,1,2,1,$table_replacements); button_fileselect(4,5,1,2,"Selection",$repl2,"Selection",0, $table_replacements, "$main::global_yard/Replacements/"); $repl2->set_text("$main::global_yard/Replacements/") if -e "$main::global_yard/Replacements/"; $table_replacements->set_row_spacing( 1, 3); #_______________________________________ # Submit button my $submit_b = button(0,2,2,3,"Submit",$table_replacements); $submit_b->can_default($true); $submit_b->grab_default(); $submit_b->signal_connect( "clicked", sub { if ($entry[0] && $entry[1]) { # Check to see if it actually exists my $executable = (split(/\s+/,$entry[0]))[0]; if (!find_file_in_path(basename($executable))) { error_window("gBootRoot: ERROR: Enter a valid editor."); return; } if ($executable =~ m,/,) { if (! -e $executable) { error_window("gBootRoot: ERROR: " . "Enter a valid path for the editor."); return; } } my $pid; unless ($pid = fork) { unless (fork) { if ($pid == 0) { sys("$entry[0] $entry[1]"); Gtk->_exit($pid); } } } waitpid($pid,0); } } ); #_______________________________________ # Close button my $close_b = button(3,5,2,3,"Close",$table_replacements); $close_b->signal_connect("clicked", sub { $replacements_window->destroy() if $replacements_window; } ); } if (!visible $replacements_window) { $replacements_window->show(); } } # Just label_advanced sub label { my($text) = @_; my $label = Gtk::Label->new( $text ); $label->set_justify( "fill" ); $_[5]->attach($label,$_[1],$_[2],$_[3],$_[4], ['expand'],['fill','shrink'],0,0); $label->show(); } # Just entry_advanced sub entry { my $numa = $_[4]; my $entry = Gtk::Entry->new(); $entry->set_editable( $true ); $entry->signal_connect( "changed", sub { $entry[$numa] = $entry->get_text(); # if ($numa == 4) { # $ars->{filename} = $entry[$numa]; # ars($ars); # } } ); $entry->set_usize(100,20); $_[5]->attach($entry,$_[0],$_[1],$_[2],$_[3], ['shrink','fill','expand'],['fill','shrink'],0,0); show $entry; return $entry; } sub button { # cretzu should like this my ($left_attach,$right_attach,$top_attach, $bottom_attach,$text,$widget) = @_; my $button = Gtk::Button->new($text); $widget->attach($button,$left_attach,$right_attach, $top_attach,$bottom_attach, ['shrink','fill','expand'],['fill','shrink'],2,2); show $button; return $button; } sub button_fileselect { # cretzu should like this # $order does matter because it fills in $container[$order]. my ($left_attach,$right_attach,$top_attach,$bottom_attach,$text,$ent, $name,$order,$widget,$device) = @_; my $button = Gtk::Button->new($text); $widget->attach($button,$left_attach,$right_attach, $top_attach,$bottom_attach, ['shrink','fill','expand'],['fill','shrink'],2,2); $button->signal_connect( "clicked",\&fileselect,$ent,$name,$order,$device); $button->show(); } # end sub button_fileselect sub fileselect { my ($widget,$ent,$name,$order,$device) = @_; if (not defined $file_dialog) { # Create a new file selection widget $file_dialog = Gtk::FileSelection->new( "$name" ); $file_dialog->signal_connect( "destroy", \&destroy_window, \$file_dialog); $file_dialog->signal_connect( "delete_event", \&destroy_window, \$file_dialog); # Connect the ok_button to file_ok_sel function $file_dialog->ok_button->signal_connect( "clicked", \&file_ok_sel, $file_dialog,$ent,$order); # Connect the cancel_button to destroy the widget $file_dialog->cancel_button->signal_connect( "clicked", sub { destroy $file_dialog } ); $file_dialog->set_filename( $device ) if defined $device; $file_dialog->set_position('mouse'); } if (!visible $file_dialog) { show $file_dialog; } else { destroy $file_dialog; } } # end sub fileselect sub file_ok_sel { my( $widget, $file_selection,$entry,$order) = @_; my $file = $file_selection->get_filename(); $entry->set_text($file); destroy $file_dialog; } ###### Replacement Stuff 1;