#!/usr/bin/env perl # $Id$ # # Copyright 2009 Norbert Preining # This file is licensed under the GNU General Public License version 2 # or any later version. # use strict; $^W = 1; my $svnrev = '$Revision: 11925 $'; $svnrev =~ m/: ([0-9]+) /; $::menurevision = $1; our %vars; our $tlpdb; our $texlive_release; our $MENU_INSTALL = 0; our $MENU_ABORT = 1; our $MENU_QUIT = 2; our $MENU_ALREADYDONE = 3; my $return = $MENU_INSTALL; require Tk; require Tk::Dialog; require Tk::DialogBox; require Tk::PNG; require Tk::ROText; require Tk::ProgressBar; use utf8; no utf8; # # LAYOUT of the wizard # # /-----------------------------------------\ # | # | /------------ Frame $ftitle -------\ | # | | Lab $tit | | # | \----------------------------------/ | # | | # | /------------ Frame $fmain --------\ | # | | | | # | \----------------------------------/ | # | | # | /------------ Frame $fbuttons -----\ | # | | But $can <$spi> But $prv <$spii> But $nxt | | # | \----------------------------------/ | # | | # \-----------------------------------------/ # my $ftitle; my $tit; my $fmain; my $fbuttons; my $can; my $spi; my $prv; my $spii; my $nxt; my $img; if (defined($::opt_lang)) { $::lang = $::opt_lang; if ($::lang eq "zh") { # set language to simplified chinese $::lang = "zh-cn"; } } else { if ($^O =~ /^MSWin(32|64)$/i) { # trying to deduce automatically the country code my $foo = TeXLive::TLWinGoo::reg_country(); if ($foo) { $::lang = $foo; } else { debug("Didn't get any usuful code from reg_country: $foo...\n"); } } else { # we load POSIX and locale stuff require POSIX; import POSIX qw/locale_h/; # now we try to deduce $::lang my $loc = setlocale(&POSIX::LC_MESSAGES); my ($lang,$area,$codeset); if ($loc =~ m/^([^_.]*)(_([^.]*))?(\.([^@]*))?(@.*)?$/) { $lang = defined($1)?$1:""; $area = defined($3)?$3:""; if ($lang eq "zh") { if ($area =~ m/^(TW|HK)$/i) { $lang = "zh-tw"; } else { # fallback to zh-cn for anything else, that is # zh-cn, zh-sg, zh, and maybe something else $lang = "zh-cn"; } } } $::lang = $lang if ($lang); } } my $dest = "/usr/local/texlive/2008"; my $mw; ###################################################################### push @::info_hook, sub { update_status(join(" ",@_)); $mw->update; }; push @::warn_hook, sub { update_status(join(" ",@_)); $mw->update; }; push @::install_packages_hook, \&update_progressbar; push @::install_packages_hook, sub { $mw->update; $::sww->update; }; sub update_status { my ($p) = @_; $::progressw->insert("end", "$p"); $::progressw->see("end"); } sub update_progressbar { my ($n,$total) = @_; if (defined($n) && defined($total)) { $::progress->value(int($n*100/$total)); } } my %text = ( title => 'TeX Live 2008 Installation', basicinfo => 'Basic Information', custom => 'Further Customization', dirsetup => "Directory setup", options => 'Options', sysint => 'System Integration', change => 'Change', toggle => 'Toggle', install => 'Install TeX Live', finbut => 'Finish', quit => 'Quit', ok => 'Ok', cancel => 'Cancel', status => 'Status output', changevar => 'Change variable value', enterpath => 'Enter path for', hinthome => '(use ~ for %%%)', selectscheme => 'Select a scheme', selectstdcol => 'Select the collections to be installed', selectall => 'Select All', selectnone => 'Deselect All', selectlang => 'Select language support', selectdoc => 'Select language-specific documentation', createsym => 'create symlinks in standard directories', binto => 'binaries to', manto => 'manpages to', infoto => 'info to', selectsys => 'Select arch-os', outof => 'out of', collof => 'collections out of', diskreq => 'disk space required', yes => 'Yes', no => 'No', notwritable => '(default not writable - please change!)', changetexdir => '(please change TEXDIR first!)', nolangcol => '(no language collection selected!)', finished => 'See TEXDIR/index.html for links to documentation.\nThe TeX Live web site\n(http://tug.org/texlive/) contains any updates and corrections.\nTeX Live is a joint project of the TeX user groups around the world;\nplease consider supporting it by joining the group best for you. The\nlist of groups is available on the web at http://tug.org/usergroups.html.', finishedpath => 'Add TEXDIR/texmf/doc/man to MANPATH.\nAdd TEXDIR/texmf/doc/info to INFOPATH.\nMost importantly, add TEXDIR/bin/PLATFORM\nto your PATH for current and future sessions.', welcome => 'Welcome to TeX Live!', ); my %labels = ( binsys => 'Binary System(s)', scheme => 'Selected Scheme', stdcoll => 'Standard Collections', langcoll => 'Language Collections', texdir => 'TEXDIR (the main TeX directory)', localdir => 'TEXMFLOCAL (directory for site-wide local files)', sysvardir => 'TEXMFSYSVAR (directory for autogenerated data)', sysconfigdir => 'TEXMFSYSCONFIG (directory for local config)', texmfhome => 'TEXMFHOME (directory for user-specific files)', optletter => 'Use letter size instead of A4 by default', optfmt => 'Create all format files', optdoc => 'Install font/macro doc tree', optsrc => 'Install font/macro source tree', symlink => 'Create symlinks in system directories', ); if (($::lang ne "en") && ($::lang ne "C")) { if (! -r "$::installerdir/tlpkg/installer/lang/perltk-$::lang") { tlwarn ("\n Sorry, no translations available for $::lang; falling back to English. (If you'd like to help translate the installer's messages, please see http://tug.org/texlive/doc.html#install-tl-xlate for information.)\n\n"); } else { # merge the translated strings into the text string open(LANG, "<$::installerdir/tlpkg/installer/lang/perltk-$::lang"); my %trans; while () { chomp; next if m/^\s*#/; next if m/^\s*$/; my ($a,$b) = split(/:/,$_,2); $b =~ s/^\s*([^\s])/$1/; $b =~ s/\s*$//; if (!utf8::decode($b)) { warn("decoding string to utf8 didn't work:$b\n"); } $trans{"$a"} = "$b"; } close(LANG); foreach my $k (keys %text) { $text{$k} = $trans{"text.$k"} if defined($trans{"text.$k"}); } foreach my $k (keys %labels) { $labels{$k} = $trans{"label.$k"} if defined($trans{"label.$k"}); } } } sub unpack_buttons { $can->packForget; $spi->packForget; $prv->packForget; $spii->packForget; $nxt->packForget; } sub pack_buttons { if (member("cancel", @_)) { $can->pack(-side => "left"); $spi->pack(-side => "left"); } if (member("next", @_)) { $nxt->pack(-side => "right"); $spii->pack(-side => "right"); } if (member("prev", @_)) { $prv->pack(-side => "right"); } } sub run_menu { calc_depends(); $mw = Tk::MainWindow->new; $ftitle = $mw->Frame; $tit = $ftitle->Label(-text => "TeX Live 2008 Installation"); $tit->pack(-side => "top", -expand => 1, -fill => "both"); $fmain = $mw->Frame(); ## DEBUG: -relief => "ridge", -borderwidth => 2); $fbuttons = $mw->Frame; $can = $fbuttons->Button(-width => 10, -relief => "ridge"); $spi = $fbuttons->Label(-width => 6); $nxt = $fbuttons->Button(-width => 10, -relief => "ridge"); $spii= $fbuttons->Label(-width => 2); $prv = $fbuttons->Button(-width => 10, -relief => "ridge"); reset_start(); $ftitle->pack(-side => "top", -expand => 1, -fill => "both", -padx => "8m", -pady => "8m"); $fmain->pack(-side => "top", -expand => 1, -fill => "both", -padx => "8m", -pady => "8m"); $fbuttons->pack(-side => "bottom", -expand => 1, -fill => "both", -padx => "8m", -pady => "8m"); $mw->configure(-width => 600, -height => 400); $mw->packPropagate(0); Tk::MainLoop(); return($return); } sub reset_start { for ($fmain->children) { $_->destroy; } my $inf = $fmain->Label(-text => "Welcome to the installation of TeX Live 2008\nThis wizard will guide you through the installation."); $inf->pack(-padx => "3m", -pady => "3m"); $fmain->configure(-height => $fmain->reqheight, -width => $fmain->reqwidth); unpack_buttons(); $can->configure(-text => "Cancel", -command => sub { $mw->destroy; do_cleanup(); exit(1); }); $prv->configure(-text => "< Back", -command => \&run_menu); $nxt->configure(-text => "Next >", -command => \&ask_scheme); pack_buttons("cancel", "next"); } sub ask_scheme { for ($fmain->children) { $_->destroy; } my $af = $fmain->Frame; my $bf = $fmain->Frame; my $lab = $af->Label(-text => "Currently selected scheme:"); $lab->pack(-side => "left"); my $val = $af->Label(-textvar => \$vars{'selected_scheme'}); $val->pack(-side => "left", -padx => "3m"); my $but = $af->Button(-text => "Change", -command => \&change_scheme, -relief => "ridge", -width => 10); $but->pack(-side => "right"); my $inf = $bf->Label(-text => "A scheme defines what will be installed.\nThe predefined scheme-full installs all of TeX Live (recommended)."); $inf->pack(-padx => "3m", -pady => "3m"); $af->pack(-expand => 1, -fill => "both"); $bf->pack(-expand => 1, -fill => "both"); unpack_buttons(); $nxt->configure(-command => \&ask_path, -text => "Next >"); $prv->configure(-text => "< Back", -command => \&reset_start); pack_buttons("cancel", "prev", "next"); } sub ask_path { for ($fmain->children) { $_->destroy; } my $af = $fmain->Frame; my $bf = $fmain->Frame; $af->pack(-expand => 1, -fill => "both"); $bf->pack(-expand => 1, -fill => "both"); my $lab = $af->Label(-text => "Destination Folder:"); $lab->pack(-side => "left"); my $val = $af->Label(-textvar => \$dest); $val->pack(-side => "left", -padx => "3m"); my $but = $af->Button(-text => "Change", -command => \&change_path, -relief => "ridge", -width => 10); $but->pack(-side => "right"); my $inf = $bf->Label(-text => "The destination folder will contain the installation.\nIt is recommended to keep the year as last component."); $inf->pack(-padx => "3m", -pady => "3m"); unpack_buttons(); $nxt->configure(-command => \&ask_go); $prv->configure(-text => "< Back", -command => \&ask_scheme); pack_buttons("cancel", "prev", "next"); } sub ask_go { for ($fmain->children) { $_->destroy; } my $inf = $fmain->Label(-justify => "left", -text => "We are ready to install TeX Live 2008.\nThe following settings will be used.\nIf you want to change something please go back,\notherwise press the \"Install\" button.\n\nDestination folder: $dest\nSelected scheme: $vars{'selected_scheme'}"); $inf->pack(-padx => "3m"); unpack_buttons(); $nxt->configure(-command => \&installation_window, -text => "Install"); $prv->configure(-text => "< Back", -command => \&ask_path); pack_buttons("cancel", "prev", "next"); } sub change_path { my $val = $dest; my $sw = $mw->Toplevel(-title => "Changing TEXDIR"); $sw->transient($mw); $sw->grab(); $sw->Label(-text => $text{'enterpath'} . " TEXDIR: ")->pack(-padx => "2m", -pady => "2m"); my $entry = $sw->Entry(-textvariable => $val, -width => 60); $entry->pack(-padx => "2m", -pady => "2m"); my $f = $sw->Frame; my $okbutton = $f->Button(-text => $text{'ok'}, -relief => "ridge", -command => sub { $val = $entry->get; callback_change_texdir($val) ; $sw->destroy })->pack(-side => 'left', -padx => "2m", -pady => "2m"); my $cancelbutton = $f->Button(-text => $text{'cancel'}, -relief => "ridge", -command => sub { $sw->destroy })->pack(-side => 'right', -padx => "2m", -pady => "2m"); $f->pack(-expand => 'x'); # bindings $sw->bind('' => [ $okbutton, 'Invoke']); $sw->bind('' => [ $cancelbutton, 'Invoke']); } sub callback_change_texdir { my ($val) = @_; my $home = getenv('HOME'); if (win32()) { $home = getenv('USERPROFILE'); $home =~ s!\\!/!g; } $home ||= '~'; $val =~ s!\\!/!g; $vars{'TEXDIR'} = $val; $vars{'TEXDIR'} =~ s/^~/$home/; $vars{'TEXMFLOCAL'} =~ s/^~/$home/; $vars{'TEXMFSYSVAR'} =~ s/^~/$home/; $vars{'TEXMFSYSCONFIG'} =~ s/^~/$home/; # only if we set TEXDIR we set the others in parallel if ($vars{'TEXDIR'}=~/^(.*)\/$texlive_release$/) { $vars{'TEXMFLOCAL'}="$1/texmf-local"; $vars{'TEXMFSYSVAR'}="$1/$texlive_release/texmf-var"; $vars{'TEXMFSYSCONFIG'}="$1/$texlive_release/texmf-config"; } elsif ($vars{'TEXDIR'}=~/^(.*)$/) { $vars{'TEXMFLOCAL'}="$1/texmf-local"; $vars{'TEXMFSYSVAR'}="$1/texmf-var"; $vars{'TEXMFSYSCONFIG'}="$1/texmf-config"; } $vars{'TEXDIRW'}=$vars{'TEXDIR'}; $dest = $vars{'TEXDIR'}; } sub installation_window { # create a progress bar window $::sww = $mw->Toplevel(-title => "installation process", -width => 400); $::sww->transient($mw); $::sww->grab(); $::sww->Label(-text => "Installation process")->pack; $::progressw = $::sww->Scrolled("ROText", -scrollbars => "e", -height => 16); $::progressw->pack(-expand => 1, -fill => "both"); my $percent_done = 0; $::progress = $::sww->ProgressBar(-variable => \$percent_done, -width => 20, -length => 400, -from => 0, -to => 100, -blocks => 10, -colors => [ 0, '#0078b8' ]); $::progress->pack(-fill => "x"); my $f = $::sww->Frame; my $b = $f->Button(-text => $text{'cancel'}, -relief => "ridge", -command => sub { $::sww->destroy; $mw->destroy; do_cleanup(); exit(1); } )->pack(-pady => "2m"); $f->pack; # set the vars calc_depends(); $mw->Busy(-recurse => 1); do_installation(); $mw->Unbusy; $::sww->destroy; $return = $MENU_ALREADYDONE; my $t = $text{'finished'}; if (!win32()) { $t .= "\n\n$text{'finishedpath'}"; } $t .= "\n\n$text{'welcome'}"; $t =~ s/TEXDIR/$::vars{'TEXDIR'}/g; $t =~ s/PLATFORM/$::vars{'this_platform'}/g; $t =~ s/\\n/\n/g; for ($fmain->children) { $_->destroy; } $can->packForget; $prv->packForget; my $lab = $fmain->ROText(-height => 16); my $linechar = $lab->index("end"); $lab->markSet("finaltext", $linechar); $lab->markGravity("finaltext", "left"); $lab->insert("end", "\n$t"); $lab->see("end"); $lab->tagAdd("centered", $linechar, "end"); $lab->tagConfigure("centered", -justify => "center"); $lab->pack; $nxt->configure(-text => $text{'finbut'}, -command => sub { $mw->destroy; }); } sub change_scheme { my $sw = $mw->Toplevel(-title => $labels{'scheme'}); $sw->transient($mw); $sw->grab(); my @schemes; foreach my $pkg ($tlpdb->list_packages) { my $tlpobj = $tlpdb->{'tlps'}{$pkg}; if ($tlpobj->category eq "Scheme") { push @schemes, $pkg; $vars{"$pkg"}=($vars{'selected_scheme'} eq $pkg)? 1:0; } } @schemes=sort @schemes; my $selected = $vars{'selected_scheme'}; $sw->Label(-text => $text{'selectscheme'})->pack(-padx => "2m", -pady => "2m"); my $f2 = $sw->Frame; my $f2l = $f2->Frame; my $f2r = $f2->Frame; my $nrfh = $#schemes / 2; my $i = 0; foreach my $scheme (@schemes) { my $tlpobj = $tlpdb->get_package("$scheme"); if ($i < $nrfh) { $f2l->Radiobutton(-variable => \$selected, -value => $scheme, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } else { $f2r->Radiobutton(-variable => \$selected, -value => $scheme, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } $i++; } $f2l->pack(-side => 'left', -padx => "2m", -pady => "2m"); $f2r->pack(-side => 'right', -padx => "2m", -pady => "2m"); $f2->pack; my $f3 = $sw->Frame; my $okbutton = $f3->Button(-text => $text{'ok'}, -relief => "ridge", -command => sub { my $s = shift; print "s=$selected\n"; select_scheme($selected) ; $sw->destroy })->pack(-side => 'left', -padx => "2m", -pady => "2m"); my $cancelbutton = $f3->Button(-text => $text{'cancel'}, -relief => "ridge", -command => sub { $sw->destroy })->pack(-side => 'left', -padx => "2m", -pady => "2m"); $f3->pack(-expand => 'x'); $sw->bind('' => [ $okbutton, 'Invoke']); $sw->bind('' => [ $cancelbutton, 'Invoke']); } 1; __END__ ### Local Variables: ### perl-indent-level: 2 ### tab-width: 2 ### indent-tabs-mode: nil ### End: # vim:set tabstop=2 expandtab: #