summaryrefslogtreecommitdiffstats
path: root/perl-install/standalone/harddrake2
Commit message (Expand)AuthorAgeFilesLines
* simplify now that alternatives are an array and not an array refThierry Vignaud2007-09-121-2/+2
* display an identifier for generic SCSI devicesThierry Vignaud2007-09-041-0/+1
* bump yearThierry Vignaud2007-09-041-1/+1
* display the PCI domain tooThierry Vignaud2007-08-081-1/+2
* re-sync after the big svn lossPascal Rigaux2007-04-251-81/+60
* uploading the hw status to hcl.mandriva.com is now done in mccThierry Vignaud2006-02-151-42/+0
* - use drakfirstboot wizard instead of mdkonlineDaouda Lo2005-10-191-2/+2
* do not merge AGP section into BRIDGES one (translation is availlable for quit...Thierry Vignaud2005-10-181-2/+0
* Club integration for proprietary drivers: offer to subscribe to Mandriva ClubThierry Vignaud2005-10-181-1/+40
* space cleaning (thx perl_checko)Thierry Vignaud2005-09-161-1/+2
* show the main window very early. thus:Thierry Vignaud2005-09-151-6/+18
* (simple_read_rpmsrate) only install HW packages of weigh 4 or 5Thierry Vignaud2005-08-181-6/+6
* do not offer to configure driver of keyboards and mice (#17254)Thierry Vignaud2005-08-041-3/+2
* do not draw a border around the main window while embeddedThierry Vignaud2005-07-191-0/+1
* really reap zombie children; side-effect: we can now run a secondThierry Vignaud2005-07-191-1/+3
* let's work with "perl -w"Thierry Vignaud2005-07-191-2/+2
* fix undefined function after pixel cleanups (#16472)Thierry Vignaud2005-06-171-0/+1
* make perl_checker happyPascal Rigaux2005-06-031-1/+1
* (simple_read_rpmsrate) add support for HW_CAT keyword that enable to matchThierry Vignaud2005-05-191-0/+2
* - clean embedding stuffThierry Vignaud2005-05-121-12/+8
* embedding cleanups resulting in reusing main window icon in sub dialogsThierry Vignaud2005-05-021-5/+5
* mandrakesoft.com -> mandriva.comPablo Saratxaga2005-04-231-1/+1
* perl_checker cleanupsThierry Vignaud2005-04-151-2/+2
* do not try to install packages that are not availlable (#15106)Thierry Vignaud2005-03-311-1/+1
* do no try to install too generic hw packages (#15101)Thierry Vignaud2005-03-311-1/+1
* - disable imm/ppa probe during install since it causes some rubbish to be pri...Pascal Rigaux2005-03-291-1/+4
* help perl_checkerThierry Vignaud2005-03-221-1/+1
* install packages needed for hw supportThierry Vignaud2005-03-221-1/+32
* (upload) remove uneeded stringThierry Vignaud2005-03-101-1/+1
* enable to upload the hardware listThierry Vignaud2005-03-101-0/+41
* fix the various transient on {rwindow} (or even {window} ?) not working anymo...Pascal Rigaux2005-01-221-4/+4
* fix crash on opening help windowsThierry Vignaud2005-01-141-3/+3
* display the menubar and the banner when embeddedThierry Vignaud2005-01-121-17/+7
* add hint for translatorThierry Vignaud2004-11-291-1/+3
* fixed typoPablo Saratxaga2004-11-261-1/+1
* kill a stock iconThierry Vignaud2004-11-221-1/+1
* add some ";", remove some ";", as told by perl_checkerPascal Rigaux2004-11-181-8/+8
* display more informationThierry Vignaud2004-11-021-0/+9
* - don't trigger help system when mandrake-doc-common is not installedDaouda Lo2004-10-191-2/+6
* - don't hardcode distro name (usefull for oem to change the distroDaouda Lo2004-10-191-2/+4
* cleanup thanks to perl_checkerPascal Rigaux2004-10-141-2/+3
* better looking for alternative driversThierry Vignaud2004-09-061-1/+1
* enable harddrake2 to properly adapt to theme changes and the likeThierry Vignaud2004-09-011-1/+1
* aspell's typo fixesThierry Vignaud2004-08-231-3/+3
* perl_checker compliancePascal Rigaux2004-08-111-6/+6
* s/Mandrake/MandrakelinuxFunda Wang2004-08-081-1/+1
* several typos fixFunda Wang2004-08-011-4/+4
* typo fixThierry Vignaud2004-07-011-1/+1
* revert ugly code printing "This program cannot be run in console mode",Pascal Rigaux2004-07-011-10/+1
* Some standalone tools don't compile when run from consoleRafael Garcia-Suarez2004-06-241-1/+10
a> 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
package install_steps_gtk;

use diagnostics;
use strict;
use vars qw(@ISA);

@ISA = qw(install_steps_interactive interactive_gtk);

#-######################################################################################
#- misc imports
#-######################################################################################
use common qw(:common :file :functional :system);
use partition_table qw(:types);
use my_gtk qw(:helpers :wrappers);
use Gtk;
#use Gtk::XmHTML;
use devices;
use fsedit;
use modules;
use pkgs;
use install_steps;
use install_steps_interactive;
use interactive_gtk;
use install_any;
use diskdrake;
use log;
use help;
use lang;

#-#####################################################################################
#-INTERN CONSTANT
#-#####################################################################################
my $w_help;
my $itemsNB = 1;
my (@background1, @background2);

my @themes_vga16 = qw(blue blackwhite savane);
my @themes = qw(DarkMarble marble3d blueHeart);

my @circle_head = (
    "19 17 4 1"
);

my @circle_body = (
" c None",
"+ c #FFFFFF",
"        =====      ",
"      =========    ",
"     =+++=======   ",
"    =++==========  ",
"   ==+============ ",
"   +++============ ",
"  ================o",
"  ================o",
"  ================o",
"  ===============oo",
"  ===============oo",
"   =============oo ",
"   ============ooo ",
"    o=========ooo  ",
"     oo=====oooo   ",
"      ooooooooo    ",
"        ooooo      ",
);

#-my @questionmark_head = (
#-"39 97 6 1",
#-" 	c None",
#-".	c #000000",
#-"+	c #FFFFFF",
#-"o	c #AAAAAA",
#-);
#-my @questionmark_body = (
#-("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO") x 10,
#-"OOOOOOOOOOOOO.......OOOOOOOOOOOOOOOOOOO",
#-"OOOOOOOOOOOO..OOOOOOO.OOOOOOOOOOOOOOOOO",
#-"OOOOOOOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOOO",
#-"OOOOOOOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOOO",
#-"OOOOOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
#-"OOOOOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
#-"OOOOOOO..OOOOOOOOOOOOOOOOOOXOOOOOOOOOOO",
#-"OOOOOOO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
#-"OOOOOO.OOOOOOOOOOOOOOOOOOOOOXOOOOOOOOOO",
#-"OOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
#-"OOOOO.OOOOOOOOOOOOOOOOOOOOOOOXOOOOOOOOO",
#-"OOOO..OOOOOOOOOOOOOOOOOOOOOOOOXOOOOOOOO",
#-"OOOO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
#-"OOOO.OOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOOO",
#-"OOO..OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
#-"OOO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOO",
#-"OO..OOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOO",
#-"OOO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOO",
#-"OO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOO",
#-"OO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOO",
#-"O..OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOO",
#-"OO.OOOOOOOOOOOoo+++++ooOOOOOOOOOOXOOOOO",
#-"O.OOOOOOOOOOo+++o+++++++oOOOOOOOOOXOOOO",
#-"O.OOOOOOOOO+++OOOOo+++++++OOOOOOOOXOOOO",
#-"O.OOOOOOOOo++oOOOOOo++++++oOOOOOOOXOOOO",
#-"O.OOOOOOOo+++oOOOOOO+++++++OOOOOOOXOOOO",
#-"..OOOOOOOo++++OOOOOOo++++++oOOOOOOXOOOO",
#-"O.OOOOOOO+++++oOOOOOo+++++++OOOOOOXOOOO",
#-".OOOOOOOO++++++OOOOOo+++++++OOOOOOOXOOO",
#-".OOOOOOOO++++++OOOOOo+++++++OOOOOOXOOOO",
#-".OOOOOOOOo++++oOOOOOo++++++oOOOOOOOXOOO",
#-".OOOOOOOOOo++oOOOOOOo++++++oOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOOOO+++++++OOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOOOO++++++OOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOOOo+++++oOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOOO+++++OOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOOo+++oOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOO+++oOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOo++OOOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOO++OOOOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOO+oOOOOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOO+OOOOOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOO+OOOOOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOoOOOOOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOO",
#-"O.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOO",
#-"OOOOOOOOOOOOOOOOoooOOOOOOOOOOOOOOOOXOOO",
#-".OOOOOOOOOOOOOO+++++OOOOOOOOOOOOOOXOOOO",
#-"O.OOOOOOOOOOOO++++++oOOOOOOOOOOOOOXXOOO",
#-"O.OOOOOOOOOOOo+++++++OOOOOOOOOOOOOXOOOO",
#-"O.OOOOOOOOOOOo+++++++OOOOOOOOOOOOOXOOOO",
#-"O.OOOOOOOOOOOo+++++++OOOOOOOOOOOOOXOOOO",
#-"OOOOOOOOOOOOOO++++++oOOOOOOOOOOOOOXOOOO",
#-"O.OOOOOOOOOOOOO+++++OOOOOOOOOOOOOXXOOOO",
#-"OO.OOOOOOOOOOOOOoooOOOOOOOOOOOOOOOXOOOO",
#-"OO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOO",
#-"OO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXOOOOO",
#-"OOO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOO",
#-"OOO.OOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOO",
#-"OOOO.OOOOOOOOOOOOOOOOOOOOOOOOOOXXOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOOO",
#-"OOOOO.OOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXOOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOOOO",
#-"OOOOOO.OOOOOOOOOOOOOOOOOOOOOOXXOOOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXOOOOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOXXOOOOOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOXXXOOOOOOOOOOO",
#-"OOOOOOOOOOOOOOOOOOOOOOOOOXOOOOOOOOOOOOO",
#-"OOOOOOOOOOOOXOOOOOOOOOOXXXOOOOOOOOOOOOO",
#-"OOOOOOOOOOOOOOXOOOOOOXXXOOOOOOOOOOOOOOO",
#-"OOOOOOOOOOOOOOOXXXXXXXOOOOOOOOOOOOOOOOO",
#-("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO") x 10);

my    @red_circle = (@circle_head, "= c #FF0000", "o c #AA5500", @circle_body);
my @orange_circle = (@circle_head, "= c #FFAA00", "o c #AA5500", @circle_body);
my  @green_circle = (@circle_head, "= c #00FF00", "o c #00AA00", @circle_body);

#-######################################################################################
#- In/Out Steps Functions
#-######################################################################################
sub new($$) {
    my ($type, $o) = @_;

    my $old = $SIG{__DIE__};
    $SIG{__DIE__} = sub { $_[0] !~ /my_gtk\.pm/ and goto $old };

    $ENV{DISPLAY} = $o->{display} || ":0";
    unless ($::testing) {
	$my_gtk::force_focus = $ENV{DISPLAY} eq ":0";

	my $f = "/tmp/Xconf";
	createXconf($f, @{$o->{mouse}}{"XMOUSETYPE", "device"}, $o->{wacom});

	if ($ENV{DISPLAY} eq ":0") {
	    my $launchX = sub {
		my $ok = 1;
		local $SIG{CHLD} = sub { $ok = 0 if waitpid(-1, c::WNOHANG()) > 0 };
		unless (fork) {
		    exec $_[0], "-dpms","-s" ,"240", "-allowMouseOpenFail", "-xf86config", $f or exit 1;
		}
		foreach (1..60) {
		    sleep 1;
		    log::l("Server died"), return 0 if !$ok;
		    return 1 if c::Xtest($ENV{DISPLAY});
		}
		log::l("Timeout!!");
		0;
	    };
	    my @servers = qw(FBDev VGA16); #-)
	    if (arch() eq "alpha") {
		require Xconfigurator;
		my $card = Xconfigurator::cardConfigurationAuto();
		add2hash($card, Xconfigurator::cardName2card($card->{type})) if $card && $card->{type};
		@servers = $card->{server} || "TGA";
		#-@servers = qw(SVGA 3DLabs TGA) 
	    }
	    @servers = qw(Mach64) if arch() =~ /^sparc/;
	    @servers = qw(PPCDummy) if arch() eq "ppc";

	    foreach (@servers) {
		log::l("Trying with server $_");
		my $dir = "/usr/X11R6/bin";
		unless (-x "$dir/XF86_$_") {
		    unlink $_ foreach glob_("$dir/XF86_*");
		    local *F; open F, ">$dir/XF86_$_" or die "failed to write server: $!";
		    local $/ = \ (16 * 1024);
		    my $f = install_any::getFile("$dir/XF86_$_") or next;
		    syswrite F, $_ foreach <$f>;
		    chmod 0755, "$dir/XF86_$_";
		}
		if (/FB/) {
		    !$o->{vga16} && listlength(cat_("/proc/fb")) or next;

		    $o->{allowFB} = &$launchX("XF86_$_") #- keep in mind FB is used.
		      and goto OK;
		} else {
		    $o->{vga16} = 1 if /VGA16/;
		    &$launchX("XF86_$_") and goto OK;
		}
	    }
	    return undef;
	}
    }
  OK: @themes = @themes_vga16 if $o->{simple_themes} || $o->{vga16};

    init_sizes();
    install_theme($o);
    create_logo_window($o);

    $my_gtk::force_center = [ $::rootwidth - $::windowwidth, $::logoheight, $::windowwidth, $::windowheight ];

    (bless {}, ref $type || $type)->SUPER::new($o);
}

sub enteringStep {
    my ($o, $step) = @_;

    print _("Entering step `%s'\n", $o->{steps}{$step}{text});
    $o->SUPER::enteringStep($step);
    create_steps_window($o);
    create_help_window($o);
}
sub leavingStep {
    my ($o, $step) = @_;
    $o->SUPER::leavingStep($step);
}



#-######################################################################################
#- Steps Functions
#-######################################################################################
sub selectLanguage {
    my ($o) = @_;
    $o->SUPER::selectLanguage;
    Gtk->set_locale;
    install_theme($o);
}

#------------------------------------------------------------------------------
sub doPartitionDisks($$) {
    my ($o, $hds, $raid) = @_;

    if ($::beginner && fsedit::is_one_big_fat($hds)) {
	#- wizard
	my $min_linux = 600 << 11;
	my $max_linux = 1500 << 11;
	my $min_freewin = 300 << 11;

	my ($part) = fsedit::get_fstab(@{$o->{hds}});
	my $w = $o->wait_message(_("Resizing"), _("Computing fat filesystem bounds"));
	my $resize_fat = eval { resize_fat::main->new($part->{device}, devices::make($part->{device})) };
	$@ and goto diskdrake;
	my $min_win = $resize_fat->min_size;
	if (!$@ && $part->{size} > $min_linux + $min_freewin + $min_win && $o->ask_okcancel('',
_("WARNING!

DrakX now needs to resize your Windows partition. Be careful: this operation is
dangerous. If you have not already done so, you should first exit the
installation, run scandisk under Windows (and optionally run defrag), then
restart the installation. You should also backup your data.
When sure, press Ok."))) {
	    my $hd = $hds->[0];
	    my $oldsize = $part->{size};
	    $hd->{isDirty} = $hd->{needKernelReread} = 1;
	    $part->{size} -= min($max_linux, $part->{size} - $min_win);
	    $hd->adjustEnd($part);
	    partition_table::adjust_local_extended($hd, $part);
	    partition_table::adjust_main_extended($hd);

	    local *log::l = sub { $w->set(join(' ', @_)) };
	    eval { $resize_fat->resize($part->{size}) };
	    if ($@) {
		$part->{size} = $oldsize;
		$o->ask_warn('', _("Automatic resizing failed"));
	    } else {
		$part->{isFormatted} = 1;
		eval { fsedit::auto_allocate($hds, $o->{partitions}) };
		if (!$@) {
		    partition_table::write($hd) unless $::testing;
		    return;
		}
	    }
	}
    }

  diskdrake:
    while (1) {
	diskdrake::main($hds, $raid, interactive_gtk->new, $o->{partitions});
	if (!grep { isSwap($_) } fsedit::get_fstab(@{$o->{hds}})) {
	    if ($::beginner) {
		$o->ask_warn('', _("You must have a swap partition"));
	    } elsif (!$::expert) {
		$o->ask_okcancel('', _("You don't have a swap partition\n\nContinue anyway?")) and last;
	    } else { last }
	} else { last }
    }
}

#------------------------------------------------------------------------------
sub chooseSizeToInstall {
    my ($o, $packages, $min_size, $max_size) = @_;
    my ($min, $max) = map { pkgs::correctSize($_ / sqr(1024)) } $min_size, $max_size;
    log::l("choosing size to install between $min and $max (really between $min_size and $max_size)");
    my $w = my_gtk->new('');
    my $adj = create_adjustment($max, $min, $max);
    my $spin = gtkset_usize(new Gtk::SpinButton($adj, 0, 0), 100, 0);

    gtkadd($w->{window},
	  gtkpack(new Gtk::VBox(0,20),
_("Now that you've selected desired groups, please choose 
how many packages you want, ranging from minimal to full 
installation of each selected groups.") .
		  ($::expert ? "\n" . _("You will be able to choose more precisely in next step") : ''),
		 create_packtable({ col_spacings => 10 },
				  [ _("Choose the size you want to install"), $spin, _("MB"), ],
				  [ undef, new Gtk::HScrollbar($adj) ],
			       ),
		 create_okcancel($w)
		)
	 );
    $spin->signal_connect(activate => sub { $w->{retval} = 1; Gtk->main_quit });
    $spin->grab_focus();
    $w->main and pkgs::invCorrectSize($spin->get_value_as_int) * sqr(1024);
}
sub choosePackagesTree {
    my ($o, $packages, $compss) = @_;

    my ($curr, $info_widget, $w_size, $go, $idle);
    my (%wtree, %ptree);

    my $w = my_gtk->new('');
    my $details = new Gtk::VBox(0,0);
    my $tree = Gtk::CTree->new(2, 0);
    $tree->set_selection_mode('browse');
    $tree->set_column_auto_resize($_, 1) foreach 0..1;

    gtkadd($w->{window}, 
	   gtkpack_(new Gtk::VBox(0,5),
		    0, _("Choose the packages you want to install"),
		    1, gtkpack(new Gtk::HBox(0,0),
			       createScrolledWindow($tree),
			       gtkadd(gtkset_usize(new Gtk::Frame(_("Info")), 150, 0),
				      createScrolledWindow($info_widget = new Gtk::Text),
				     )),
		    0, gtkpack__(new Gtk::HBox(0,0), $w_size = new Gtk::Label('')),
		    0, gtkpack(new Gtk::HBox(0,10),
			       $go = gtksignal_connect(new Gtk::Button(_("Install")), "clicked" => sub { $w->{retval} = 1; Gtk->main_quit }),
			      )
    ));
    $w->{window}->set_usize(map { $_ - 2 * $my_gtk::border - 4 } $::windowwidth, $::windowheight);
    $go->grab_focus;
    $w->show;

    $tree->freeze;
    my $dir = $::testing && $ENV{SHARE_PATH} || "/usr/share";
    my $pix_base     = [ Gtk::Gdk::Pixmap->create_from_xpm($w->{window}->window, $w->{window}->style->bg('normal'), "$dir/rpm-base.xpm") ];
    my $pix_selected = [ Gtk::Gdk::Pixmap->create_from_xpm($w->{window}->window, $w->{window}->style->bg('normal'), "$dir/rpm-selected.xpm") ];
    my $pix_unselect = [ Gtk::Gdk::Pixmap->create_from_xpm_d($w->{window}->window, undef, "1 1 1 1", " c None", " ") ];

    my $parent; $parent = sub {
	if (my $w = $wtree{$_[0]}) { return $w }
	my $s; foreach (split '/', $_[0]) {
	    $wtree{"$s/$_"} ||= 
	      $tree->insert_node($s ? $parent->($s) : undef, undef, [$_], 5, (undef) x 4, 0, 0);
	    $s = "$s/$_";
	}
	$wtree{$s};
    };
    my $add_node = sub {
	my ($leaf, $root) = @_;
	my $node = $tree->insert_node($parent->($root), undef, [$leaf], 5, (undef) x 4, 1, 0);
	my $p = $packages->[0]{$leaf} or return;
	my $pix = pkgs::packageFlagBase($p) ? $pix_base : pkgs::packageFlagSelected($p) ? $pix_selected : $pix_unselect;
	$tree->node_set_pixmap($node, 1, $pix->[0], $pix->[1]);
	push @{$ptree{$leaf}}, $node;
    };
    
    my ($root, $leaf);
    foreach (sort keys %{$packages->[0]}) {
	$add_node->($_, 'all');
    }
    foreach (sort @$compss) {
	($root, $leaf) = m|(.*)/(.+)|o or ($root, $leaf) = ('', $_);
	$add_node->($leaf, $root);
    }
    $tree->thaw;

    my $display_info = sub {
	my $p = $packages->[0]{$curr} or return gtktext_insert($info_widget, '');
	pkgs::extractHeaders($o->{prefix}, [$p]);
	$p->{header} or die;

	my $ind = $o->{compssListLevels}{$o->{install_class}};
	my $imp = translate($pkgs::compssListDesc{pkgs::packageFlagBase($p) ? 100 : round_down($p->{values}[$ind], 10)});

	gtktext_insert($info_widget, $@ ? _("Bad package") :
		       _("Version: %s\n", pkgs::packageVersion($p) . '-' . pkgs::packageRelease($p)) .
		       _("Size: %d KB\n", pkgs::packageSize($p) / 1024) .
		       ($imp && _("Importance: %s\n", $imp)) . "\n" .
		       formatLines(c::headerGetEntry($p->{header}, 'description')));
	c::headerFree(delete $p->{header});
	0;
    };

    $tree->signal_connect(tree_select_row => sub {
	Gtk->timeout_remove($idle) if $idle;

	if ($_[1]->row->is_leaf) {
	    ($curr) = $tree->node_get_pixtext($_[1], 0);
	    $idle = Gtk->timeout_add(100, $display_info);
	} else {
	    $curr = $_[1];
	}
    });
    my $update_size = sub {
	my $size = 0;
	foreach (values %{$packages->[0]}) {
	    $size += pkgs::packageSize($_) - ($_->{installedCumulSize} || 0) if pkgs::packageFlagSelected($_); #- on upgrade, installed packages will be removed.
	}
	$w_size->set(_("Total size: %d / %d MB", 
		       pkgs::correctSize($size / sqr(1024)),
		       install_any::getAvailableSpace($o) / sqr(1024)));

    };
    my $toggle = sub {
	if (ref $curr) {
	    $tree->toggle_expansion($curr);
	} else {
	    my $p = $packages->[0]{$curr} or return;
	    pkgs::togglePackageSelection($packages, $p, my $l = {});
	    if (my @l = grep { $l->{$_} } keys %$l) {
		@l > 1 and $o->ask_okcancel('', [ _("The following packages are going to be install/removed"), join(", ", sort @l) ], 1) || return;
		pkgs::togglePackageSelection($packages, $p);
		foreach (@l) {
		    my $p = $packages->[0]{$_};
		    my $pix = pkgs::packageFlagSelected($p) ? $pix_selected : $pix_unselect;
		    $tree->node_set_pixmap($_, 1, $pix->[0], $pix->[1]) foreach @{$ptree{$_}};
		}
		&$update_size;
	    } else {
		$o->ask_warn('', _("This is a mandatory package, it can't unselected"));
	    }
	}
    };
    $tree->signal_connect(button_press_event => sub { &$toggle if $_[1]{type} =~ /^2/ });
    $tree->signal_connect(key_press_event => sub {
        my ($w, $e) = @_;
	my $c = chr $e->{keyval};
	&$toggle if $e->{keyval} >= 0x100 ? $c eq "\r" || $c eq "\x8d" : $c eq ' ';
	1;
    });
    &$update_size;
    $w->main;
}

#------------------------------------------------------------------------------
sub installPackages {
    my ($o, $packages) = @_;

    my ($current_total_size, $last_size, $nb, $total_size, $start_time, $last_dtime, $trans_progress_total);

    my $w = my_gtk->new(_("Installing"), grab => 1);
    $w->{window}->set_usize($::windowwidth * 0.8, $::windowheight * 0.5);
    my $text = new Gtk::Label;
    my ($msg, $msg_time_remaining, $msg_time_total) = map { new Gtk::Label($_) } '', (_("Estimating")) x 2;
    my ($progress, $progress_total) = map { new Gtk::ProgressBar } (1..2);
    gtkadd($w->{window}, gtkadd(new Gtk::EventBox,
				gtkpack(new Gtk::VBox(0,10),
			       _("Please wait, "), $msg, $progress,
			       create_packtable({},
						[_("Time remaining "), $msg_time_remaining],
						[_("Total time "), $msg_time_total],
						),
			       $text,
			       $progress_total,
			      )));
    $msg->set(_("Preparing installation"));
    $w->sync;

    my $old = \&pkgs::installCallback;
    local *pkgs::installCallback = sub {
	my $m = shift;
	if ($m =~ /^Starting installation/) {
	    $nb = $_[0];
	    $total_size = $_[1]; $current_total_size = 0;
	    $start_time = time();
	    $msg->set(_("%d packages", $nb) . _(", %U MB", pkgs::correctSize($total_size / sqr(1024))));
	    $w->flush;
	} elsif ($m =~ /^Starting installing package/) {
	    $progress->update(0);
	    my $name = $_[0];
	    $msg->set(_("Installing package %s", $name));
	    $current_total_size += $last_size;
	    $last_size = c::headerGetEntry($o->{packages}[0]{$name}{header}, 'size');
	    $text->set((split /\n/, c::headerGetEntry($o->{packages}[0]{$name}{header}, 'summary'))[0] || '');
	    $w->flush;
	} elsif ($m =~ /^Progressing installing package/) {
	    $progress->update($_[2] ? $_[1] / $_[2] : 0);

	    my $dtime = time() - $start_time;
	    my $ratio = $total_size ? ($_[1] + $current_total_size) / $total_size : 0;
	    my $total_time = $ratio ? $dtime / $ratio : time();

	    $progress_total->update($ratio);
	    if ($dtime != $last_dtime && $current_total_size > 2 * 1024 * 1024) {
		$msg_time_total->set(formatTime(10 * round($total_time / 10)));
		$msg_time_remaining->set(formatTime(10 * round(max($total_time - $dtime, 0) / 10)));
		$last_dtime = $dtime;
	    }
	    $w->flush;
	} else { unshift @_, $m; goto $old }
    };
    catch_cdie { $o->install_steps::installPackages($packages); }
      sub {
	  if ($@ =~ /^error ordering package list: (.*)/) {
	      $o->ask_yesorno('', [
_("There was an error ordering packages:"), $1, _("Go on anyway?") ], 1) and return 1;
	      ${$_[0]} = "already displayed";
	  }
	  0;
      };
    $w->destroy;
}

#------------------------------------------------------------------------------
sub load_rc($) {
    if (my ($f) = grep { -r $_ } map { "$_/$_[0].rc" } ("share", "/usr/share", dirname(__FILE__))) {
	Gtk::Rc->parse($f);
	foreach (cat_($f)) {
	    if (/style\s+"background"/ .. /^\s*$/) {
		@background1 = map { $_ * 256 * 256 } split ',', $1 if /NORMAL.*\{(.*)\}/;
		@background2 = map { $_ * 256 * 256 } split ',', $1 if /PRELIGHT.*\{(.*)\}/;
	    }
	}
    }
}

sub install_theme {
    my ($o, $theme) = @_;    
    $o->{theme} = $theme || $o->{theme} || $themes[0];

    gtkset_mousecursor(68);

    load_rc($_) foreach "themes-$o->{theme}", "install", "themes";

    if (my ($font, $font2) = lang::get_x_fontset($o->{lang})) {
	$font2 ||= $font;
	Gtk::Rc->parse_string(qq(
style "default-font" 
{
   fontset = "$font"
}
style "steps"
{
   fontset = "$font2"
}
widget "*" style "default-font"
widget "*Steps*" style "steps"

));
   }
    gtkset_background(@background1);# unless $::testing;

    create_logo_window($o);
    create_help_window($o);
}

#------------------------------------------------------------------------------
sub create_big_help {
    my $w = my_gtk->new('', grab => 1, force_position => [ $::stepswidth, $::logoheight ]);
    $w->{rwindow}->set_usize($::logowidth, $::rootheight - $::logoheight);
    gtkadd($w->{window},
	   gtkpack_(new Gtk::VBox(0,0),
		    1, createScrolledWindow(gtktext_insert(new Gtk::Text, 
							   formatAlaTeX(translate($help::steps{$::o->{step}})))),
		    0, gtksignal_connect(new Gtk::Button(_("Ok")), "clicked" => sub { Gtk->main_quit }),
		   ));
    $w->main;
}

#------------------------------------------------------------------------------
sub create_help_window {
    my ($o) = @_;

#    $o->{help_window}->destroy if $o->{help_window};

    my $w;
    if ($w = $o->{help_window}) {
	$_->destroy foreach $w->{window}->children;
    } else {
	$w = bless {}, 'my_gtk';
	$w->{rwindow} = $w->{window} = new Gtk::Window;
	$w->{rwindow}->set_uposition($::rootwidth - $::helpwidth, $::rootheight - $::helpheight);
	$w->{rwindow}->set_usize($::helpwidth, $::helpheight);
	$w->sync;
    }

#-    my $b = new Gtk::Button;
#-    $b->signal_connect(clicked => sub {
#-	  my $w = my_gtk->new('', grab => 1, force_position => [ $stepswidth, $logoheight ]);
#-	  $w->{rwindow}->set_usize($logowidth, $height - $logoheight);
#-	  gtkadd($w->{window},
#-		 gtkpack_(new Gtk::VBox(0,0),
#-			  1, createScrolledWindow(gtktext_insert(new Gtk::Text, 
#-								 formatAlaTeX(translate($help::steps_long{$o->{step}})))),
#-			  0, gtksignal_connect(new Gtk::Button(_("Ok")), "clicked" => sub { Gtk->main_quit }),
#-			  ));
#-	  $w->main;
#-    });
#-    my @l = (@questionmark_head,
#-	       join('', "X c #", map { sprintf "%02X", $_ / 256 } @background1),
#-	       join('', "O c #", map { sprintf "%02X", $_ / 256 } @background2),
#-	       @questionmark_body);
#-    my @pixmap = Gtk::Gdk::Pixmap->create_from_xpm_d($w->{window}->window, undef, @l);
#-    gtkadd($b, new Gtk::Pixmap(@pixmap));

#    Gtk::XmHTML->init;
    gtkadd($w->{window},
	   gtkpack_(new Gtk::HBox(0,-2),
#-		    0, $b,
#-		    1, createScrolledWindow($w_help = new Gtk::XmHTML)));
		    1, createScrolledWindow($w_help = new Gtk::Text)));
#-    $w_help->source($o->{step} ? translate($o->{steps}{$o->{step}}{help}) : '');
    gtktext_insert($w_help, $o->{step} ? formatAlaTeX(translate($help::steps{$o->{step}})) : '');

    $w->show;
    $o->{help_window} = $w;
}

sub set_help { 
    shift;
    gtktext_insert($w_help, 
		   formatAlaTeX(join "\n", 
				map { translate($help::steps{$_}) } @_));
    1;
}

#------------------------------------------------------------------------------
sub create_steps_window {
    my ($o) = @_;

    $o->{steps_window}->destroy if $o->{steps_window};
    my %reachableSteps if 0;
    %reachableSteps = ();

    my $w = bless {}, 'my_gtk';
    $w->{rwindow} = $w->{window} = new Gtk::Window;
    $w->{rwindow}->set_uposition(0, 0);
    $w->{rwindow}->set_usize($::stepswidth, $::stepsheight);
    $w->{rwindow}->set_name("Steps");
    $w->{rwindow}->set_events('button_press_mask');
    $w->{rwindow}->signal_connect(button_press_event => sub {
	$::setstep or return;
        my $Y = $_[1]{'y'};
	map_each {
	    my (undef, $y, undef, $height) = @{$::b->allocation};
	    $y <= $Y && $Y < $y + $height and die "setstep $::a\n";
	} %reachableSteps;
    });
    $w->show;

    gtkadd($w->{window},
	   gtkpack_(new Gtk::VBox(0,0),
		    (map {; 1, $_ } map {
			my $step = $o->{steps}{$_};
			my $circle =
			  $step->{done}    && \@green_circle  ||
			  $step->{entered} && \@orange_circle ||
			  \@red_circle;
			my @pixmap = Gtk::Gdk::Pixmap->create_from_xpm_d($w->{window}->window, undef, @$circle);

			my $w = new Gtk::Label(translate($step->{text}));

			$w->set_name("Steps" . ($step->{reachable} && "Reachable"));
			my $b = new Gtk::HBox(0,5);
			gtkpack_($b, 0, new Gtk::Pixmap(@pixmap), 0, $w);

			$reachableSteps{$_} = $b if $step->{reachable};
			$b;
		    } grep {
			local $_ = $o->{steps}{$_}{hidden};
			/^$/ or $o->{installClass} and /beginner/ && !$::beginner || /!expert/ && $::expert
		    } @{$o->{orderedSteps}}),
		    0, gtkpack(new Gtk::HBox(0,0), map {
			my $t = $_;
			my $w = new Gtk::Button('');
			$w->set_name($t);
			$w->set_usize(0, 7);
			gtksignal_connect($w, clicked => sub { 
			    $::setstep or return; #- just as setstep s
			    install_theme($o, $t); die "theme_changed\n" 
			});
		    } @themes)));
    $w->show;
    $o->{steps_window} = $w;
}

#------------------------------------------------------------------------------
sub create_logo_window() {
    my ($o) = @_;
    gtkdestroy($o->{logo_window});
    my $w = bless {}, 'my_gtk';
    $w->{rwindow} = $w->{window} = new Gtk::Window;
    $w->{rwindow}->set_uposition($::stepswidth, 0);
    $w->{rwindow}->set_usize($::logowidth, $::logoheight);
    $w->{rwindow}->set_name("logo");
    $w->show;
    my $file = "logo-mandrake.xpm";
    -r $file or $file = "/usr/share/$file";
    if (-r $file) {
	my $ww = $w->{window};
	my @logo = Gtk::Gdk::Pixmap->create_from_xpm($ww->window, $ww->style->bg('normal'), $file);
	gtkadd($ww, new Gtk::Pixmap(@logo));
    }
    $o->{logo_window} = $w;
}

sub init_sizes() {
    ($::rootheight,  $::rootwidth)    = (480, 640);
    ($::rootheight,  $::rootwidth)    = my_gtk::gtkroot()->get_size;
    ($::rootheight,  $::rootwidth)    = (min(600, $::rootheight), min(800, $::rootwidth));
    ($::stepswidth,  $::stepsheight)  = (140, $::rootheight);
    ($::logowidth,   $::logoheight)   = ($::rootwidth - $::stepswidth, 40);                                 
    ($::helpwidth,   $::helpheight)   = ($::rootwidth - $::stepswidth, 100);                                
    ($::windowwidth, $::windowheight) = ($::rootwidth - $::stepswidth, $::rootheight - $::helpheight - $::logoheight);
}

#------------------------------------------------------------------------------
sub createXconf($$$) {
    my ($file, $mouse_type, $mouse_dev, $wacom_dev) = @_;

    my $wacom;
    if ($wacom_dev) {
	$wacom_dev = devices::make($wacom_dev);
	$wacom = <<END;
Section "Module"
   Load "xf86Wacom.so"
EndSection

Section "XInput"
    SubSection "WacomStylus"
        Port "$wacom_dev"
        AlwaysCore
    EndSubSection
    SubSection "WacomCursor"
        Port "$wacom_dev"
        AlwaysCore
    EndSubSection
    SubSection "WacomEraser"
        Port "$wacom_dev"
        AlwaysCore
    EndSubSection
EndSection
END
    }

    local *F;
    open F, ">$file" or die "can't create X configuration file $file";
    print F <<END;
Section "Files"
   FontPath   "/usr/X11R6/lib/X11/fonts:unscaled"
EndSection

Section "Keyboard"
   Protocol    "Standard"
   AutoRepeat  0 0

   LeftAlt         Meta
   RightAlt        Meta
   ScrollLock      Compose
   RightCtl        Control
END

    if (arch() =~ /^sparc/) {
	print F <<END;
   XkbRules    "sun"
   XkbModel    "sun"
   XkbLayout   "us"
   XkbCompat   "compat/complete"
   XkbTypes    "types/complete"
   XkbKeycodes "sun(type5)"
   XkbGeometry "sun(type5)"
   XkbSymbols  "sun/us(sun5)"
END
    } else {
	print F "    XkbDisable\n";
    }

    print F <<END;
EndSection

Section "Pointer"
   Protocol    "$mouse_type"
   Device      "/dev/$mouse_dev"
   Emulate3Buttons
   Emulate3Timeout    50
EndSection

$wacom

Section "Monitor"
   Identifier  "My Monitor"
   VendorName  "Unknown"
   ModelName   "Unknown"
   HorizSync   31.5-35.5
   VertRefresh 50-70
   Modeline "640x480"     25.175 640  664  760  800   480  491  493  525
   Modeline "640x480"     28.3   640  664  760  800   480  491  493  525
   ModeLine "800x600"     36     800  824  896 1024   600  601  603  625
EndSection


Section "Device"
   Identifier "Generic VGA"
   VendorName "Unknown"
   BoardName "Unknown"
   Chipset "generic"
EndSection

Section "Device"
   Identifier "svga"
   VendorName "Unknown"
   BoardName "Unknown"
EndSection

Section "Screen"
    Driver      "vga16"
    Device      "Generic VGA"
    Monitor     "My Monitor"
    Subsection "Display"
        Modes       "640x480"
        ViewPort    0 0
    EndSubsection
EndSection

Section "Screen"
    Driver      "fbdev"
    Device      "Generic VGA"
    Monitor     "My Monitor"
    Subsection "Display"
        Depth       16
        Modes       "default"
        ViewPort    0 0
    EndSubsection
EndSection

Section "Screen"
    Driver "svga"
    Device      "svga"
    Monitor     "My Monitor"
    Subsection "Display"
        Depth       16
        Modes       "800x600" "640x480"
        ViewPort    0 0
    EndSubsection
EndSection

Section "Screen"
    Driver      "accel"
    Device      "svga"
    Monitor     "My Monitor"
    Subsection "Display"
        Depth       16
        Modes       "800x600" "640x480"
        ViewPort    0 0
    EndSubsection
EndSection
END

}
#-   ModeLine "640x480"     28     640  672  768  800   480  490  492  525
#-######################################################################################
#- Wonderful perl :(
#-######################################################################################
1; #