summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiep Kroonenberg <siepo@cybercomm.nl>2011-03-23 17:48:43 +0000
committerSiep Kroonenberg <siepo@cybercomm.nl>2011-03-23 17:48:43 +0000
commitaf239484eb8ca0c0bec8804f054f7e482b9d6fe6 (patch)
tree74e4b1c2a606563741bbbecefb1d10fce82bf4a0
parent161cc5508f7aa14ffe0713f3d3e4979b551ca6c4 (diff)
Experimental installer with in-place and revised portable options
git-svn-id: svn://tug.org/texlive/trunk@21811 c570f23f-e606-0410-a88d-b1316a301751
-rwxr-xr-xMaster/install-tl-new2186
-rwxr-xr-xMaster/install-tl-new.bat64
-rw-r--r--Master/tlpkg/installer/install-menu-perltk-new.pl1054
-rwxr-xr-xMaster/tlpkg/installer/install-menu-text-new.pl1070
4 files changed, 4374 insertions, 0 deletions
diff --git a/Master/install-tl-new b/Master/install-tl-new
new file mode 100755
index 00000000000..db75ffbfc35
--- /dev/null
+++ b/Master/install-tl-new
@@ -0,0 +1,2186 @@
+#!/usr/bin/env perl
+# $Id: install-tl 21776 2011-03-21 01:47:19Z reinhardk $
+#
+# Copyright 2007, 2008, 2009, 2010 Reinhard Kotucha, Norbert Preining,
+# Karl Berry.
+#
+# This file is licensed under the GNU General Public License version 2
+# or any later version.
+#
+# Be careful when changing wording: Every normal informational message
+# output here must be recognized by the long grep in tl-update-tlnet.
+#
+# TODO:
+# - with -gui pop up a transient window showing:
+# testing for compressed archive packages ...
+# testing for uncompressed live system ...
+# testing for network access ...
+# loading tlpdb, this can take some time ...
+# (that, and maybe some others can be done with the waitVariableX
+# thingy as described in the Perl/Tk book in the chapter that can be
+# found on the net) (Werner 28.10.08)
+
+my $svnrev = '$Revision: 21776 $';
+$svnrev =~ m/: ([0-9]+) /;
+$::installerrevision = $1;
+
+# taken from 00texlive.config: release, $tlpdb->config_release;
+our $texlive_release;
+
+BEGIN {
+ $^W = 1;
+ my $Master;
+ my $me = $0;
+ $me =~ s!\\!/!g if $^O =~ /^MSWin(32|64)$/i;
+ if ($me =~ m!/!) {
+ ($Master = $me) =~ s!(.*)/[^/]*$!$1!;
+ } else {
+ $Master = ".";
+ }
+ $::installerdir = $Master;
+
+ # All platforms: add the installer modules
+ unshift (@INC, "$::installerdir/tlpkg");
+}
+
+use Cwd 'abs_path';
+use Getopt::Long qw(:config no_autoabbrev);
+use Pod::Usage;
+
+use TeXLive::TLUtils qw(platform platform_desc
+ which getenv win32 unix info log debug tlwarn ddebug tldie
+ get_system_tmpdir member process_logging_options rmtree
+ mkdirhier make_var_skeleton make_local_skeleton install_package copy
+ install_packages dirname setup_programs native_slashify forward_slashify);
+#use TeXLive::TLMedia;
+use TeXLive::TLPOBJ;
+use TeXLive::TLPDB;
+use TeXLive::TLConfig;
+use TeXLive::TLDownload;
+
+if (win32) {
+ require TeXLive::TLWinGoo;
+ TeXLive::TLWinGoo->import( qw(
+ &win_version
+ &is_vista
+ &admin
+ &non_admin
+ &reg_country
+ &expand_string
+ &global_tmpdir
+ &get_system_path
+ &get_user_path
+ &setenv_reg
+ &unsetenv_reg
+ &adjust_reg_path_for_texlive
+ &register_extension
+ &unregister_extension
+ &register_file_type
+ &unregister_file_type
+ &broadcast_env
+ &update_assocs
+ &add_desktop_shortcut
+ &add_menu_shortcut
+ &remove_desktop_shortcut
+ &remove_menu_shortcut
+ &create_uninstaller
+ ));
+}
+
+use strict;
+
+# global list of lines that get logged (see TLUtils.pm::_logit).
+@::LOGLINES = ();
+
+# global list of warnings
+@::WARNLINES = ();
+
+# we play around with the environment, place to keep original
+my %origenv = ();
+
+# $install{$packagename} == 1 if it should be installed
+my %install;
+
+# the different modules have to assign a code blob to this global variable
+# which starts the installation.
+# Example: In install-menu-text.pl there is
+# $::run_menu = \&run_menu_text;
+#
+$::run_menu = sub { die "no UI defined." ; };
+
+# the default scheme to be installed
+my $default_scheme='scheme-full';
+
+# some arrays where the lists of collections to be installed are saved
+# our for menus
+our @collections_std;
+our @collections_lang;
+our @collections_lang_doc;
+# The global variable %vars is an associative list which contains all
+# variables and their values which can be changed by the user.
+# needs to be our since TeXLive::TLUtils uses it
+#
+# The following values are taken from the remote tlpdb using the
+# $tlpdb->option_XXXXX
+# settings (i.e., taken from tlpkg/tlpsrc/00texlive.installation.tlpsrc
+#
+# 'option_path' => 0,
+# 'option_sys_bin' => '/usr/local/bin',
+# 'option_sys_man' => '/usr/local/man',
+# 'option_sys_info' => '/usr/local/info',
+# 'option_doc' => 1,
+# 'option_src' => 1,
+# 'option_fmt' => 0,
+# 'option_letter' => 0,
+our %vars=( # 'n_' means 'number of'.
+ 'this_platform' => '',
+ 'n_systems_available' => 0,
+ 'n_systems_selected' => 0,
+ 'n_collections_selected' => 0,
+ 'n_collections_available' => 0,
+ 'total_size' => 0,
+ 'src_splitting_supported' => 1,
+ 'doc_splitting_supported' => 1,
+ 'selected_scheme' => $default_scheme,
+ 'in_place' => 0,
+ 'portable' => 0,
+ );
+
+# option handling
+my $opt_in_place = 0;
+my $opt_gui = (win32() ? "wizard" : "text");
+my $opt_help = 0;
+my $opt_location = "";
+my $opt_no_gui = 0;
+my $opt_nonadmin = 0;
+my $opt_portable = 0;
+my $opt_print_arch = 0;
+my $opt_profileseed = "";
+my $opt_profile = "";
+my $opt_scheme = "";
+my $opt_custom_bin;
+my $opt_version = 0;
+my $opt_force_arch;
+my $opt_persistent_downloads = 1;
+my $opt_allow_ftp = 0;
+
+# show all options even those not relevant for that arch
+$::opt_all_options = 0;
+
+# default language for GUI installer
+$::lang = "en";
+
+# use the fancy directory selector for TEXDIR
+$::alternative_selector = 0;
+
+# do not debug translations by default
+$::debug_translation = 0;
+
+#
+# some strings to describe the different meanings of option_file_assoc
+$::fileassocdesc[0] = "None";
+$::fileassocdesc[1] = "Only new";
+$::fileassocdesc[2] = "All";
+
+# if we find a file installation.profile we ask the user whether we should
+# continue with the installation
+# note, we are in the installer directory.
+if (-r "installation.profile") {
+ print "ABORTED INSTALLATION FOUND: installation.profile\n";
+ print "Do you want to continue with the exact same settings as before (y/N): ";
+ my $answer = <STDIN>;
+ if ($answer =~ m/^y(es)?$/i) {
+ $opt_profile = "installation.profile";
+ }
+}
+
+
+# first process verbosity/quiet options
+process_logging_options();
+# now the others
+GetOptions(
+ "custom-bin=s" => \$opt_custom_bin,
+ "fancyselector" => \$::alternative_selector,
+ "in-place" => \$opt_in_place,
+ "gui:s" => \$opt_gui,
+ "lang=s" => \$::opt_lang,
+ "location|url|repository|repo=s" => \$opt_location,
+ "no-cls", # $::opt_no_cls in install-menu-text-pl
+ "no-gui" => \$opt_no_gui,
+ "non-admin" => \$opt_nonadmin,
+ "portable" => \$opt_portable,
+ "print-platform|print-arch" => \$opt_print_arch,
+ "force-platform|force-arch=s" => \$opt_force_arch,
+ "debug-translation" => \$::debug_translation,
+ "profile-seed=s" => \$opt_profileseed,
+ "profile=s" => \$opt_profile,
+ "scheme=s" => \$opt_scheme,
+ "all-options" => \$::opt_all_options,
+ "persistent-downloads!" => \$opt_persistent_downloads,
+ "version" => \$opt_version,
+ "help|?" => \$opt_help) or pod2usage(1);
+
+if ($opt_gui eq "") {
+ # the --gui option was given with an empty argument, set it to perltk
+ $opt_gui = "perltk";
+}
+if ($opt_gui eq "expert") {
+ $opt_gui = "perltk";
+}
+
+if (win32()) {
+ pod2usage(-exitstatus => 0,
+ -verbose => 2,
+ -noperldoc => 1,
+ -output => \*STDOUT) if $opt_help;
+} else {
+ pod2usage(-exitstatus => 0, -verbose => 2, -file => $0) if $opt_help;
+}
+
+if ($opt_version) {
+ print "install-tl (TeX Live Cross Platform Installer)",
+ " revision $::installerrevision\n";
+ if (open (REL_TL, "$::installerdir/release-texlive.txt")) {
+ # print first and last lines, which have the TL version info.
+ my @rel_tl = <REL_TL>;
+ print $rel_tl[0];
+ print $rel_tl[$#rel_tl];
+ close (REL_TL);
+ }
+ if ($::opt_verbosity > 0) {
+ print "Revision of modules:";
+ print "\nTLConfig: " . TeXLive::TLConfig->module_revision();
+ print "\nTLUtils: " . TeXLive::TLUtils->module_revision();
+ print "\nTLPOBJ: " . TeXLive::TLPOBJ->module_revision();
+ print "\nTLPDB: " . TeXLive::TLPDB->module_revision();
+ print "\nTLWinGoo: " . TeXLive::TLWinGoo->module_revision() if win32();
+ print "\n";
+ }
+ exit 0;
+}
+
+die "Options custom-bin and in-place are incompatible."
+ if ($opt_in_place and $opt_custom_bin);
+
+die "Options profile and in-place are incompatible."
+ if ($opt_in_place and $opt_profile);
+
+die "Options profile-seed and in-place are incompatible."
+ if ($opt_in_place and $opt_profileseed);
+
+if ($#ARGV >= 0) {
+ # we still have arguments left, should only be gui, otherwise die
+ if ($ARGV[0] =~ m/^gui$/i) {
+ $opt_gui = "perltk";
+ } else {
+ die "$0: Extra arguments `@ARGV'; try --help if you need it.\n";
+ }
+}
+
+
+if (defined($::opt_lang)) {
+ $::lang = $::opt_lang;
+}
+
+if ($opt_profile) { # for now, not allowed if in_place
+ if (-r $opt_profile) {
+ info("Automated TeX Live installation using profile: $opt_profile\n");
+ } else {
+ $opt_profile = "";
+ info("Profile $opt_profile not readable, continuing in interactive mode.\n");
+ }
+}
+
+if ($opt_nonadmin and win32()) {
+ non_admin();
+}
+
+
+# the TLPDB instances we will use. $tlpdb is for the one from the installation
+# media, while $localtlpdb is for the new installation
+# $tlpdb must be our because it is used in install-menu-text.pl
+our $tlpdb;
+my $localtlpdb;
+my $location;
+
+# $finished == 1 if the menu call already did the installation
+my $finished = 0;
+@::info_hook = ();
+
+my $system_tmpdir=get_system_tmpdir();
+my $media;
+our @media_available;
+
+# special uses of install-tl:
+if ($opt_print_arch) {
+ print platform()."\n";
+ exit 0;
+}
+
+
+# continuing with normal install
+
+# check as soon as possible for GUI functionality to give people a chance
+# to interrupt.
+if (($opt_gui ne "text") && !$opt_no_gui && ($opt_profile eq "")) {
+ # try to load Tk.pm, but don't die if it doesn't work
+ eval { require Tk; };
+ if ($@) {
+ # that didn't work out, so warn the user and continue with text mode
+ tlwarn("Cannot load Tk, maybe something is missing and\n");
+ tlwarn("maybe http://tug.org/texlive/distro.html#perltk can help.\n");
+ tlwarn("Error message from loading Tk:\n");
+ tlwarn(" $@\n");
+ tlwarn("Continuing in text mode...\n");
+ $opt_gui = "text";
+ }
+ eval { my $foo = Tk::MainWindow->new; $foo->destroy; };
+ if ($@) {
+ tlwarn("perl/Tk unusable, cannot create main windows.\n");
+ if (platform() eq "universal-darwin") {
+ tlwarn("That could be because X11 is not installed or started.\n");
+ }
+ tlwarn("Error message from creating MainWindow:\n");
+ tlwarn(" $@\n");
+ tlwarn("Continuing in text mode...\n");
+ $opt_gui = "text";
+ }
+ if ($opt_gui eq "text") {
+ # we switched from GUI to non-GUI mode, tell the user and wait a bit
+ tlwarn("\nSwitching to text mode installer, if you want to cancel, do it now.\n");
+ tlwarn("Waiting for 3 second\n");
+ sleep(3);
+ }
+}
+
+#
+if (defined($opt_force_arch)) {
+ tlwarn("Overriding platform to $opt_force_arch\n");
+ $::_platform_ = $opt_force_arch;
+}
+
+# initialize the correct platform
+platform();
+$vars{'this_platform'} = $::_platform_;
+
+# we do not support cygwin < 1.7, so check for that
+if (!$opt_custom_bin && (platform() eq "i386-cygwin")) {
+ chomp( my $un = `uname -r`);
+ if ($un =~ m/^(\d+)\.(\d+)\./) {
+ if ($1 < 2 && $2 < 7) {
+ tldie("\nSorry, the TL binaries require at least cygwin 1.7.\n");
+ }
+ }
+}
+
+if (!setup_programs ("$::installerdir/tlpkg/installer", "$::_platform_")) {
+ tldie("$0: Goodbye.\n");
+}
+
+# determine where we will find the distribution to install from.
+#
+$location = $opt_location;
+$location || ($location = "$::installerdir");
+if ($location =~ m!^(ctan$|(http|ftp)://)!i) {
+ $location =~ s,/(tlpkg|archive)?/*$,,; # remove any trailing tlpkg or /
+ if ($location =~ m/^ctan$/i) {
+ $location = TeXLive::TLUtils::give_ctan_mirror();
+ } elsif ($location =~ m/^$TeXLiveServerURL/) {
+ my $mirrorbase = TeXLive::TLUtils::give_ctan_mirror_base();
+ $location =~ s,^($TeXLiveServerURL|ctan$),$mirrorbase,;
+ }
+ $TeXLiveURL = $location;
+ $media = 'NET';
+ @media_available = qw/NET/;
+} else {
+ # remove leading file:/+ part
+ $location =~ s!^file://*!/!i;
+ $location = abs_path($location);
+ # remove trailing \ or / (e.g. root of dvd drive on w32)
+ $location =~ s,[\\\/]$,,;
+ if (-d "$location/$Archive") {
+ push @media_available, 'local_compressed';
+ }
+
+ if (-d "$location/texmf/web2c") {
+ push @media_available, 'local_uncompressed';
+ }
+
+ if (member('local_compressed', @media_available)) {
+ $media = 'local_compressed';
+ # for in_place option we want local_uncompressed media
+ $media = 'local_uncompressed' if $opt_in_place &&
+ member('local_uncompressed', @media_available);
+ } elsif (member('local_uncompressed', @media_available)) {
+ $media = 'local_uncompressed';
+ } else {
+ if ($opt_location) {
+ # user gave a --location but nothing can be found there, so die
+ die "$0: cannot find installation source at $opt_location.\n";
+ }
+ # no --location given, but NET installation
+ $TeXLiveURL = $location = TeXLive::TLUtils::give_ctan_mirror();
+ $media = 'NET';
+ }
+}
+info("Installing TeX Live $TeXLive::TLConfig::ReleaseYear from: $location\n");
+
+info("Platform: ", platform(), " => \'", platform_desc(platform), "\'\n");
+if ($opt_custom_bin) {
+ if (-d $opt_custom_bin && (-r "$opt_custom_bin/kpsewhich"
+ || -r "$opt_custom_bin/kpsewhich.exe")) {
+ info("Platform overridden, binaries taken from $opt_custom_bin\n"
+ . "and will be installed into .../bin/custom.\n");
+ } else {
+ tldie("$opt_custom_bin: Argument to -custom-bin must be a directory "
+ . "with TeX Live binaries.\n");
+ }
+}
+if ($media eq "local_uncompressed") {
+ info("Distribution: live (uncompressed)\n");
+} elsif ($media eq "local_compressed") {
+ info("Distribution: inst (compressed)\n");
+} elsif ($media eq "NET") {
+ info("Distribution: net (downloading)\n");
+ info("Using URL: $TeXLiveURL\n");
+ TeXLive::TLUtils::setup_persistent_downloads() if $opt_persistent_downloads;
+} else {
+ info("Distribution: $media\n");
+}
+info("Directory for temporary files: $system_tmpdir\n");
+
+if ($opt_in_place and ($media ne "local_uncompressed")) {
+ print "TeX Live not local or not decompressed; 'in_place' option not applicable\n";
+ $opt_in_place = 0;
+} elsif ($opt_in_place and (!TeXLive::TLUtils::texdir_check($::installerdir))) {
+ print "Installer dir not writable; 'in_place' option not applicable\n";
+ $opt_in_place = 0;
+}
+$vars{'in_place'} = $opt_in_place;
+$opt_scheme = "" if $opt_in_place;
+$vars{'portable'} = $opt_portable;
+
+load_tlpdb();
+
+log("Installer revision: $::installerrevision\n");
+log("Database revision: " . $tlpdb->config_revision . "\n");
+
+# correctly set the splitting support
+# for local_uncompressed we always support splitting
+if (($media eq "NET") || ($media eq "local_compressed")) {
+ $vars{'src_splitting_supported'} = $tlpdb->config_src_container;
+ $vars{'doc_splitting_supported'} = $tlpdb->config_doc_container;
+}
+$texlive_release = $tlpdb->config_release;
+if ($media eq "local_uncompressed") {
+ # existing installation may not have 00texlive.config metapackage
+ # so use TLConfig to establish what release we have
+ $texlive_release ||= $TeXLive::TLConfig::ReleaseYear;
+}
+
+# if the release from the remote TLPDB does not agree with the
+# TLConfig::ReleaseYear in the first 4 places break out here.
+# Why only the first four places: some optional network distributions
+# might use
+# release/2009-foobar
+if ($media eq "NET"
+ && $texlive_release !~ m/^$TeXLive::TLConfig::ReleaseYear/) {
+ die <<END_MISMATCH;
+$0: The TeX Live versions of the local installation
+and the repository being accessed are not compatible:
+ local: $TeXLive::TLConfig::ReleaseYear
+ repository: $texlive_release
+Perhaps you need to use a different CTAN mirror?
+END_MISMATCH
+}
+
+set_platforms_supported();
+set_texlive_default_dirs();
+set_install_platform();
+initialize_collections();
+
+# initialize the scheme from the command line value, if given.
+if ($opt_scheme) {
+ # add the scheme- prefix if they didn't give it.
+ $opt_scheme = "scheme-$opt_scheme" if $opt_scheme !~ /^scheme-/;
+ my $scheme = $tlpdb->get_package($opt_scheme);
+ if (defined($scheme)) {
+ select_scheme($opt_scheme); # select it
+ } else {
+ tlwarn("Scheme $opt_scheme not defined, ignoring it.\n");
+ }
+}
+
+
+if ($opt_profile eq "") {
+ if ($opt_profileseed) {
+ read_profile("$opt_profileseed");
+ }
+ # do the normal interactive installation.
+ #
+ # here we could load different menu systems. Currently several things
+ # are "our" so that the menu implementation can use it. The $tlpdb, the
+ # %var, and all the @collection*
+ # install-menu-*.pl have to assign a code ref to $::run_menu which is
+ # run, and should change ONLY stuff in %vars
+ # The allowed keys in %vars should be specified somewhere ...
+ # the menu implementation should return
+ # MENU_INSTALL do the installation
+ # MENU_ABORT abort every action immediately, no cleanup
+ # MENU_QUIT try to quit and clean up mess
+ our $MENU_INSTALL = 0;
+ our $MENU_ABORT = 1;
+ our $MENU_QUIT = 2;
+ our $MENU_ALREADYDONE = 3;
+ $opt_gui = "text" if ($opt_no_gui);
+ # finally do check for additional screens in the $opt_gui setting:
+ # format:
+ # --gui <plugin>:<a1>,<a2>,...
+ # which will passed to run_menu (<a1>, <a2>, ...)
+ #
+ my @runargs;
+ if ($opt_gui =~ m/^([^:]*):(.*)$/) {
+ $opt_gui = $1;
+ @runargs = split ",", $2;
+ }
+ if (-r "$::installerdir/tlpkg/installer/install-menu-${opt_gui}-new.pl") {
+ require("installer/install-menu-${opt_gui}-new.pl");
+ } else {
+ tlwarn("UI plugin $opt_gui not found,\n");
+ tlwarn("Using text mode installer.\n");
+ require("installer/install-menu-text-new.pl");
+ }
+
+ # before we start the installation we check for the existence of
+ # a previous installation, and in case we ship inform the UI
+ {
+ my $tlmgrwhich = which("tlmgr");
+ if ($tlmgrwhich) {
+ my $dn = dirname($tlmgrwhich);
+ $dn = abs_path("$dn/../..");
+ # The "make Karl happy" case, check that we are not running install-tl
+ # from the same tree where tlmgr is hanging around
+ my $install_tl_root = abs_path($::installerdir);
+ my $tlpdboldpath = "$dn/$TeXLive::TLConfig::InfraLocation/$TeXLive::TLConfig::DatabaseName";
+ if (-r $tlpdboldpath && $dn ne $install_tl_root) {
+ debug ("found old installation in $dn\n");
+ push @runargs, "-old-installation-found=$dn";
+ }
+ }
+ }
+
+ my $ret = &{$::run_menu}(@runargs);
+ if ($ret == $MENU_QUIT) {
+ do_cleanup();
+ flushlog();
+ exit(1);
+ }
+ if ($ret == $MENU_ABORT) {
+ # omit do_cleanup().
+ flushlog();
+ exit(2);
+ }
+ if ($ret == $MENU_ALREADYDONE) {
+ debug("run_menu has already done the work ... cleaning up.\n");
+ $finished = 1;
+ }
+ if (!$finished && ($ret != $MENU_INSTALL)) {
+ tlwarn("Unknown return value of run_menu: $ret\n");
+ exit(3);
+ }
+} else {
+ read_profile($opt_profile);
+}
+
+my $varsdump;
+foreach my $key (sort keys %vars) {
+ $varsdump.=" $key: \"" . $vars{$key} . "\"\n";
+}
+
+log("Settings:\n" . $varsdump);
+
+if (!$finished) {
+ # do the actual installation
+ # win32: first, remove trailing slash from texdir[w]
+ # in case it is the root of a drive
+ $vars{'TEXDIR'} =~ s![/\\]$!!;
+ #$vars{'TEXDIRW'} = $vars{'TEXDIR'}; # no longer used
+ sanitise_options();
+ info("Installing to: $vars{TEXDIR}\n");
+ do_installation();
+}
+
+do_cleanup();
+
+exit(0);
+
+
+###################################################################
+#
+# FROM HERE ON ONLY SUBROUTINES
+# NO VARIABLE DECLARATIONS
+#
+###################################################################
+
+sub do_installation {
+ install_warnlines_hook();
+ if (win32()) {
+ non_admin() if !$vars{'option_w32_multi_user'};
+ }
+ if ($vars{'n_collections_selected'} <= 0) {
+ tlwarn("Nothing selected, nothing to install, exiting!\n");
+ exit 1;
+ }
+ # do the actual installation
+ my $h;
+ prepare_installation();
+ if (!$vars{'in_place'}) {
+ calc_depends();
+ save_options_into_tlpdb();
+ do_install_packages();
+ if ($opt_custom_bin) {
+ $vars{'this_platform'} = "custom";
+ my $TEXDIR="$vars{'TEXDIR'}";
+ mkdirhier("$TEXDIR/bin/custom");
+ for my $f (<$opt_custom_bin/*>) {
+ copy($f, "$TEXDIR/bin/custom");
+ }
+ }
+ }
+ # now we save every scheme that is fully covered by the stuff we have
+ # installed to the $localtlpdb
+ foreach my $s ($tlpdb->schemes) {
+ my $stlp = $tlpdb->get_package($s);
+ die ("That cannot happen, $s not defined in tlpdb") unless defined($stlp);
+ my $incit = 1;
+ foreach my $d ($stlp->depends) {
+ if (!defined($localtlpdb->get_package($d))) {
+ $incit = 0;
+ last;
+ }
+ }
+ if ($incit) {
+ $localtlpdb->add_tlpobj($stlp);
+ }
+ }
+ $localtlpdb->save unless $vars{'in_place'};
+ do_postinst_stuff();
+ if (win32() || $vars{'portable'}) {
+ print welcome();
+ } else {
+ print welcome_paths();
+ }
+ print warnings_summary();
+}
+
+# do_postinst_stuff has to fix up the texmf tree and install some missing
+# files. The things to do are taken from the install-live.sh installer
+# of former times, and should be critically checked.
+sub do_postinst_stuff {
+ my $TEXDIR="$vars{'TEXDIR'}";
+ my $TEXMFSYSVAR="$vars{'TEXMFSYSVAR'}";
+ my $TEXMFSYSCONFIG="$vars{'TEXMFSYSCONFIG'}";
+ my $TEXMFVAR="$vars{'TEXMFVAR'}";
+ my $TEXMFCONFIG="$vars{'TEXMFCONFIG'}";
+ my $TEXMFLOCAL="$vars{'TEXMFLOCAL'}";
+ my $tmv;
+
+ do_texmf_cnf();
+
+ #
+ # clean up useless files in texmf-dist/tlpkg as this is only
+ # created by the relocatable packages
+ if (-d "$TEXDIR/$TeXLive::TLConfig::RelocTree/tlpkg") {
+ rmtree("$TEXDIR/TeXLive::TLConfig::RelocTree/tlpkg");
+ }
+
+ #
+ # create package backup directory for tlmgr autobackup to work
+ mkdirhier("$TEXDIR/$TeXLive::TLConfig::PackageBackupDir");
+
+ # final program execution
+ # we have to do several things:
+ # - clean the environment from spurious TEXMF related variables
+ # - add the bin dir to the PATH
+ # - select perl interpreter and set the correct perllib
+ # - run the programs
+
+ # Step 1: Clean the environment.
+ %origenv = %ENV;
+ my @TMFVARS0=qw(VARTEXFONTS
+ TEXMF SYSTEXMF VARTEXFONTS
+ TEXMFDBS WEB2C TEXINPUTS TEXFORMATS MFBASES MPMEMS TEXPOOL MFPOOL MPPOOL
+ PSHEADERS TEXFONTMAPS TEXPSHEADERS TEXCONFIG TEXMFCNF
+ TEXMFMAIN TEXMFDIST TEXMFLOCAL TEXMFSYSVAR TEXMFSYSCONFIG
+ TEXMFVAR TEXMFCONFIG TEXMFHOME TEXMFCACHE);
+
+ if (defined($ENV{'TEXMFCNF'})) {
+ print "WARNING: environment variable TEXMFCNF is set.
+You should know what you are doing.
+We will remove that for the post install actions, but all further
+operations might be disturbed.\n\n";
+ }
+ foreach $tmv (@TMFVARS0) {
+ delete $ENV{$tmv} if (defined($ENV{$tmv}));
+ }
+
+ # Step 2: Setup the PATH, switch to the new Perl
+
+ my $pathsep=(win32)? ';' : ':';
+ my $plat_bindir="$TEXDIR/bin/$vars{'this_platform'}";
+ my $perl_bindir="$TEXDIR/tlpkg/tlperl/bin";
+ my $perl_libdir="$TEXDIR/tlpkg/tlperl/lib";
+
+## This won't do any good;
+## have to remove other tex directories in calling batchfile
+# if (win32) {
+# debug("Removing other TeXs from path\n");
+# my @newpt = ();
+# foreach my $d (split (';', $ENV{'PATH'})) {
+# push @newpt, $d unless TeXLive::TLWinGoo::is_a_texdir($d);
+# }
+# $ENV{'PATH'} = join($pathsep, @newpt);
+# debug("Path after removals(s):\n $ENV{'PATH'}\n");
+# }
+
+ debug("Prepending $plat_bindir to PATH\n");
+
+ $ENV{'PATH'}="$plat_bindir" . "$pathsep" . "$ENV{'PATH'}";
+
+ if (win32) {
+ debug("Prepending $perl_bindir to PATH\n");
+ $ENV{'PATH'}="$perl_bindir" . "$pathsep" . "$ENV{'PATH'}";
+ $ENV{'PATH'} =~ s!/!\\!g;
+ }
+
+ debug("\nNew PATH is now:\n");
+ foreach my $dir (split $pathsep, $ENV{'PATH'}) {
+ debug(" $dir\n");
+ }
+ debug("\n");
+
+ if (win32) {
+ $ENV{'PERL5LIB'}="$perl_libdir";
+ }
+
+ #
+ # post install actions
+ #
+
+ # in case we are running from local_uncompressed
+ # we use the tlpdb from the local_uncompressed, otherwise
+ # the one we have locally created, for all the further actions
+ my $usedtlpdb = $vars{'in_place'} ? $tlpdb : $localtlpdb;
+
+
+ if (win32()) {
+ debug "Actual environment:\n".`set`."\n\n";
+ debug 'Effective TEXMFCNF: '.`kpsewhich -expand-path=\$TEXMFCNF`."\n";
+ }
+
+ if (win32() and !$vars{'portable'} and !$vars{'in_place'}) {
+ create_uninstaller($vars{'TEXDIR'}, $vars{'TEXDIR'},
+ $vars{'TEXMFSYSVAR'}, $vars{'TEXMFSYSCONFIG'});
+ # TODO: custom uninstaller for in_place
+ # (re-)initialize batchfile for uninstalling shortcuts
+ }
+
+ # Step 4: run the programs
+
+ if (!$vars{'in_place'}) {
+ info("running mktexlsr $TEXDIR/texmf-dist $TEXDIR/texmf\n");
+ system('mktexlsr', "$TEXDIR/texmf-dist", "$TEXDIR/texmf");
+ }
+
+ # we have to generate the various config file. That could be done with
+ # texconfig generate * but Win32 does not have texconfig. But we have
+ # $localtlpdb and this is simple code, so do it directly, i.e., duplicate
+ # the code from the various generate-*.pl scripts
+
+ info("writing fmtutil.cnf data to $TEXMFSYSVAR/web2c/fmtutil.cnf\n");
+ TeXLive::TLUtils::create_fmtutil($usedtlpdb,
+ "$TEXMFSYSVAR/web2c/fmtutil.cnf",
+ "$TEXMFLOCAL/web2c/fmtutil-local.cnf");
+
+ mkdirhier "$vars{'TEXMFSYSCONFIG'}/web2c";
+ info("writing updmap.cfg to $TEXMFSYSCONFIG/web2c/updmap.cfg\n");
+ TeXLive::TLUtils::create_updmap ($usedtlpdb,
+ "$TEXMFSYSCONFIG/web2c/updmap.cfg",
+ "$TEXMFLOCAL/web2c/updmap-local.cfg");
+
+ info("writing language.dat data to $TEXMFSYSVAR/tex/generic/config/language.dat\n");
+ TeXLive::TLUtils::create_language_dat($usedtlpdb,
+ "$TEXMFSYSVAR/tex/generic/config/language.dat",
+ "$TEXMFLOCAL/tex/generic/config/language-local.dat");
+
+ info("writing language.def data to $TEXMFSYSVAR/tex/generic/config/language.def\n");
+ TeXLive::TLUtils::create_language_def($usedtlpdb,
+ "$TEXMFSYSVAR/tex/generic/config/language.def",
+ "$TEXMFLOCAL/tex/generic/config/language-local.def");
+
+ info("writing language.dat.lua data to $TEXMFSYSVAR/tex/generic/config/language.dat.lua\n");
+ TeXLive::TLUtils::create_language_lua($usedtlpdb,
+ "$TEXMFSYSVAR/tex/generic/config/language.dat.lua",
+ "$TEXMFLOCAL/tex/generic/config/language-local.dat.lua");
+
+ info("running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG\n");
+ system("mktexlsr", $TEXMFSYSVAR, $TEXMFSYSCONFIG);
+
+ info("running updmap-sys...");
+ # system('updmap-sys', '--nohash');
+ log(`updmap-sys --nohash 2>&1`);
+ info("done\n");
+
+ # now work through the options if specified at all
+
+ # letter instead of a4
+ if ($vars{'option_letter'}) {
+ # set paper size, but do not execute any post actions, in this case
+ # it would be:
+ # - mktexlsr
+ # - fmtutil-sys -all
+ info("setting default paper size to letter\n");
+ log(`tlmgr --no-execute-actions paper letter 2>&1`);
+ }
+
+ # now rerun mktexlsr for updmap-sys and tlmgr paper letter updates.
+ info("re-running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG\n");
+ system("mktexlsr", $TEXMFSYSVAR, $TEXMFSYSCONFIG);
+
+ # luatex/context
+ # we only call luatools --generate once at installation time, the
+ # rest must be managed by the user, Taco email 2010-05-26
+ #
+ # disabled since we are not multi user capable, email taco 2010-06-08
+ #if (exists($install{"context"}) && $install{"context"} == 1) {
+ # info("making ConTeXt MkIV cache with luatools --generate, be patient...");
+ # chomp (my $tmv = `kpsewhich -expand-braces="$vars{TEXMFVAR}"`);
+ # log("\n TEXMFVAR=$vars{TEXMFVAR}, expanded to $tmv for mkdirhier\n");
+ # mkdirhier ($tmv); # don't be asked about making the dir
+ # log(`luatools --generate 2>&1`);
+ # info("done\n");
+ #}
+
+ # all formats option
+ if ($vars{'option_fmt'}) {
+ info("pre-generating all format files (fmtutil-sys --all), be patient...");
+ log(`fmtutil-sys --all 2>&1`);
+ info("done\n");
+ }
+
+ #
+ # do path adjustments: On Windows add/remove to PATH etc,
+ # on Unix set symlinks
+ # for portable, this option should be unset
+ # it should not be necessary to test separately for portable
+ do_path_adjustments() if $vars{'option_path'};
+
+ # now do the system integration:
+ # on unix this means setting up symlinks
+ # on w32 this means adding to path, settting registry values
+ # on both, we run the postaction directives of the tlpdb
+ # no need to test for portable or in_place:
+ # the menus (or profile?) should have set the required options
+ do_tlpdb_postactions();
+}
+
+
+sub do_tlpdb_postactions {
+ info ("running package specific postactions\n");
+ # Run the post installation code in the postaction tlpsrc entries
+ # For now the option_desktop_integrations maps to both desktop
+ # and menu entries, but we can split that later
+ # option settings already reflect portable- and in_place options.
+ my $usedtlpdb = $vars{'in_place'} ? $tlpdb : $localtlpdb;
+ foreach my $package ($usedtlpdb->list_packages) {
+ &TeXLive::TLUtils::do_postaction("install",
+ $usedtlpdb->get_package($package),
+ $vars{'option_file_assocs'},
+ $vars{'option_desktop_integration'},
+ $vars{'option_desktop_integration'},
+ $vars{'option_post_code'});
+ }
+ info ("finished with package specific postactions\n");
+}
+
+sub do_path_adjustments {
+ info ("running path adjustment actions\n");
+ if (win32()) {
+ TeXLive::TLUtils::w32_add_to_path($vars{'TEXDIR'}.'/bin/win32',
+ $vars{'option_w32_multi_user'});
+ broadcast_env();
+ } else {
+ TeXLive::TLUtils::add_symlinks($vars{'TEXDIR'}, $vars{'this_platform'},
+ $vars{'option_sys_bin'}, $vars{'option_sys_man'},
+ $vars{'option_sys_info'});
+ }
+ info ("finished with path adjustment actions\n");
+}
+
+
+# we have to adjust the texmf.cnf file to the paths set in the configuration!
+sub do_texmf_cnf {
+ open(TMF,"<$vars{'TEXDIR'}/texmf/web2c/texmf.cnf")
+ or die "$vars{'TEXDIR'}/texmf/web2c/texmf.cnf not found: $!";
+ my @texmfcnflines = <TMF>;
+ close(TMF);
+
+ my @changedtmf = (); # install to disk: write only changed items
+
+ my $yyyy = $TeXLive::TLConfig::ReleaseYear;
+ my $rewritetmflua = 0; # need a new texmfcnf.lua?
+
+ # we have to find TEXMFLOCAL TEXMFSYSVAR and TEXMFHOME
+ foreach my $line (@texmfcnflines) {
+ if ($line =~ m/^TEXMFLOCAL/) {
+ # by default TEXMFLOCAL = TEXDIR/../texmf-local, if this is the case
+ # we don't have to write a new setting.
+ my $deftmlocal = dirname($vars{'TEXDIR'});
+ $deftmlocal .= "/texmf-local";
+ if ("$vars{'TEXMFLOCAL'}" ne "$deftmlocal") {
+ push @changedtmf, "TEXMFLOCAL = $vars{'TEXMFLOCAL'}\n";
+ }
+ } elsif ($line =~ m/^TEXMFSYSVAR/) {
+ if ("$vars{'TEXMFSYSVAR'}" ne "$vars{'TEXDIR'}/texmf-var") {
+ push @changedtmf, "TEXMFSYSVAR = $vars{'TEXMFSYSVAR'}\n";
+ }
+ } elsif ($line =~ m/^TEXMFSYSCONFIG/) {
+ if ("$vars{'TEXMFSYSCONFIG'}" ne "$vars{'TEXDIR'}/texmf-config") {
+ push @changedtmf, "TEXMFSYSCONFIG = $vars{'TEXMFSYSCONFIG'}\n";
+ }
+ } elsif ($line =~ m/^TEXMFVAR/) {
+ if ($vars{"TEXMFVAR"} ne "~/.texlive$yyyy/texmf-var") {
+ push @changedtmf, "TEXMFVAR = $vars{'TEXMFVAR'}\n";
+ $rewritetmflua = 1; # TEXMFVAR change -> new texmfcnf.lua
+ }
+ } elsif ($line =~ m/^TEXMFCONFIG/) {
+ if ("$vars{'TEXMFCONFIG'}" ne "~/.texlive$yyyy/texmf-config") {
+ push @changedtmf, "TEXMFCONFIG = $vars{'TEXMFCONFIG'}\n";
+ }
+ } elsif ($line =~ m/^TEXMFHOME/) {
+ if ("$vars{'TEXMFHOME'}" ne "~/texmf") {
+ push @changedtmf, "TEXMFHOME = $vars{'TEXMFHOME'}\n";
+ }
+ } elsif ($line =~ m/^OSFONTDIR/) {
+ if (win32()) {
+ push @changedtmf, "OSFONTDIR = \$SystemRoot/fonts//\n";
+ }
+ }
+ }
+
+ if ($vars{'portable'}) {
+ push @changedtmf, "ASYMPTOTE_HOME = \$TEXMFCONFIG/asymptote\n";
+ }
+
+ my ($TMF, $TMFLUA);
+ # we want to write only changes to texmf.cnf
+ # even for in_place installation
+ $TMF = ">$vars{'TEXDIR'}/texmf.cnf";
+ open(TMF, $TMF) || die "open($TMF) failed: $!";
+ print TMF <<EOF;
+% (Public domain.)
+% This texmf.cnf file should contain only your personal changes from the
+% original texmf.cnf (for example, as chosen in the installer).
+%
+% That is, if you need to make changes to texmf.cnf, put your custom
+% settings in this file, which is .../texlive/YYYY/texmf.cnf, rather than
+% the distributed file (which is .../texlive/YYYY/texmf/web2c/texmf.cnf).
+% And include *only* your changed values, not a copy of the whole thing!
+%
+EOF
+ foreach (@changedtmf) {
+ # avoid absolute paths for TEXDIR, use $SELFAUTOPARENT instead
+ s/^(TEXMF\w+\s*=\s*)\Q$vars{'TEXDIR'}\E/$1\$SELFAUTOPARENT/;
+ print TMF;
+ }
+ #
+ # save the setting of shell_escape to the generated system texmf.cnf
+ # default in texmf/web2c/texmf.cnf is
+ # shell_escape = p
+ # so we write that only if the user *deselected* this option
+ if (!$vars{"option_write18_restricted"}) {
+ print TMF <<EOF;
+
+% Disable system commands via \\write18{...}. See texmf/web2c/texmf.cnf.
+shell_escape = 0
+EOF
+;
+ }
+ close(TMF) || warn "close($TMF) failed: $!";
+
+ if ($rewritetmflua) {
+ $TMFLUA = ">$vars{'TEXDIR'}/texmfcnf.lua";
+ open(TMFLUA, $TMFLUA) || die "open($TMFLUA) failed: $!";
+
+ print TMFLUA <<EOF;
+-- (Public domain.)
+-- This texmfcnf.lua file should exist only if you have personal changes
+-- from the distributed file; for example, if TEXMFVAR was changed in
+-- the installer.
+--
+return { TEXMFCACHE = '$vars{"TEXMFVAR"}' }
+EOF
+
+ close(TMFLUA) || warn "close($TMFLUA) failed: $!";
+ }
+}
+
+
+sub dump_vars {
+ my $filename=shift;
+ my $fh;
+ if (ref($filename)) {
+ $fh = $filename;
+ } else {
+ open VARS, ">$filename";
+ $fh = \*VARS;
+ }
+ foreach my $key (keys %vars) {
+ print $fh "$key $vars{$key}\n";
+ }
+ close VARS if (!ref($filename));
+ debug("\n%vars dumped to '$filename'.\n");
+}
+
+
+# Determine which platforms are supported.
+sub set_platforms_supported {
+ my @binaries = $tlpdb->available_architectures;
+ for my $binary (@binaries) {
+ unless (defined $vars{"binary_$binary"}) {
+ $vars{"binary_$binary"}=0;
+ }
+ }
+ for my $key (keys %vars) {
+ ++$vars{'n_systems_available'} if ($key=~/^binary/);
+ }
+}
+
+# Environment variables and default values on UNIX:
+# TEXLIVE_INSTALL_PREFIX /usr/local/texlive => $tex_prefix
+# TEXLIVE_INSTALL_TEXDIR $tex_prefix/2010 => $TEXDIR
+# TEXLIVE_INSTALL_TEXMFSYSVAR $TEXDIR/texmf-var
+# TEXLIVE_INSTALL_TEXMFSYSCONFIG $TEXDIR/texmf-config
+# TEXLIVE_INSTALL_TEXMFLOCAL $tex_prefix/texmf-local
+# TEXLIVE_INSTALL_TEXMFVAR ~/.texlive2010/texmf-var
+# TEXLIVE_INSTALL_TEXMFCONFIG ~/.texlive2010/texmf-config
+# TEXLIVE_INSTALL_TEXMFHOME '$HOME/texmf'
+
+sub set_texlive_default_dirs {
+ my $tex_prefix = $vars{'in_place'} ? $::installerdir :
+ getenv('TEXLIVE_INSTALL_PREFIX');
+ if (win32) {
+ $tex_prefix ||= getenv('SystemDrive') . '/texlive';
+ # we use SystemDrive because ProgramFiles requires admin rights
+ # we don't use USERPROFILE here because that will be copied back and
+ # forth on roaming profiles
+ } else {
+ $tex_prefix ||= '/usr/local/texlive';
+ }
+ # for portable and in_place installation we want everything in one directory
+ $vars{'TEXDIR'} = ($vars{'portable'} || $vars{'in_place'})
+ ? $tex_prefix : "$tex_prefix/$texlive_release";
+
+ my $texmfsysvar = getenv('TEXLIVE_INSTALL_TEXMFSYSVAR');
+ $texmfsysvar ||= $vars{'TEXDIR'} . '/texmf-var';
+ $vars{'TEXMFSYSVAR'} = $texmfsysvar;
+
+ my $texmfsysconfig = getenv('TEXLIVE_INSTALL_TEXMFSYSCONFIG');
+ $texmfsysconfig ||= $vars{'TEXDIR'} . '/texmf-config';
+ $vars{'TEXMFSYSCONFIG'}=$texmfsysconfig;
+
+ my $texmflocal = getenv('TEXLIVE_INSTALL_TEXMFLOCAL');
+ $texmflocal ||= "$tex_prefix/texmf-local";
+ $vars{'TEXMFLOCAL'} = $texmflocal;
+
+ $vars{'TEXDIR'} = $vars{'in_place'}
+ ? abs_path($::installerdir) : $vars{'TEXDIR'};
+
+ my $texmfhome = getenv('TEXLIVE_INSTALL_TEXMFHOME');
+ $texmfhome ||= "~";
+ $vars{'TEXMFHOME'}="$texmfhome/texmf";
+
+ # use the $texmfhome value just computed for these.
+ my $yyyy = $TeXLive::TLConfig::ReleaseYear;
+ my $texmfvar = getenv('TEXLIVE_INSTALL_TEXMFVAR');
+ $texmfvar ||= "$texmfhome/.texlive$yyyy/texmf-var";
+ $vars{'TEXMFVAR'} = $texmfvar;
+
+ my $texmfconfig = getenv('TEXLIVE_INSTALL_TEXMFCONFIG');
+ $texmfconfig ||= "$texmfhome/.texlive$yyyy/texmf-config";
+ $vars{'TEXMFCONFIG'} = $texmfconfig;
+
+ # for portable installation we want everything in one directory
+ if ($vars{'portable'}) {
+ $vars{'TEXMFHOME'} = "\$TEXMFLOCAL";
+ $vars{'TEXMFVAR'} = "\$TEXMFSYSVAR";
+ $vars{'TEXMFCONFIG'} = "\$TEXMFSYSCONFIG";
+ }
+}
+
+sub calc_depends {
+ # we have to reset the install hash EVERY TIME otherwise everything will
+ # always be installed since the default is scheme-full which selects
+ # all packages and never deselects it
+ %install=();
+ my $p;
+ my $a;
+
+ # initialize the %install hash with what should be installed
+
+ if ($vars{'selected_scheme'} ne "scheme-custom") {
+ # First look for packages in the selected scheme.
+ my $scheme=$tlpdb->get_package($vars{'selected_scheme'});
+ if (!defined($scheme)) {
+ if ($vars{'selected_scheme'}) {
+ # something is written in the selected scheme but not defined, that
+ # is strange, so warn and die
+ die ("Scheme $vars{'selected_scheme'} not defined, vars:\n");
+ dump_vars(\*STDOUT);
+ }
+ } else {
+ for my $scheme_content ($scheme->depends) {
+ $install{"$scheme_content"}=1 unless ($scheme_content=~/^collection-/);
+ }
+ }
+ }
+
+ # Now look for collections in the %vars hash. These are not
+ # necessarily the collections required by a scheme. The final
+ # decision is made in the collections/languages menu.
+ foreach my $key (keys %vars) {
+ if ($key=~/^collection-/) {
+ $install{$key} = 1 if $vars{$key};
+ }
+ }
+
+ # compute the list of archs to be installed
+ my @archs;
+ foreach (keys %vars) {
+ if (m/^binary_(.*)$/ ) {
+ if ($vars{$_}) { push @archs, $1; }
+ }
+ }
+
+ #
+ # work through the addon settings in the %vars hash
+ #if ($vars{'addon_editor'}) {
+ # $install{"texworks"} = 1;
+ #}
+
+ # if programs for arch=win32 are installed we also have to install
+ # tlperl.win32 which provides the "hidden" perl that will be used
+ # to run all the perl scripts.
+ # Furthermore we install tlgs.win32 and tlpsv.win32, too
+ if (grep(/^win32$/,@archs)) {
+ $install{"tlperl.win32"} = 1;
+ $install{"tlgs.win32"} = 1;
+ $install{"tlpsv.win32"} = 1;
+ }
+
+ # loop over all the packages until it is getting stable
+ my $changed = 1;
+ while ($changed) {
+ # set $changed to 0
+ $changed = 0;
+
+ # collect the already selected packages
+ my @pre_selected = keys %install;
+ debug("initial number of installations: $#pre_selected\n");
+
+ # loop over all the pre_selected and add them
+ foreach $p (@pre_selected) {
+ ddebug("pre_selected $p\n");
+ my $pkg = $tlpdb->get_package($p);
+ if (!defined($pkg)) {
+ tlwarn("$p is mentioned somewhere but not available, disabling it.\n");
+ $install{$p} = 0;
+ next;
+ }
+ foreach my $p_dep ($tlpdb->get_package($p)->depends) {
+ if ($p_dep =~ m/^(.*)\.ARCH$/) {
+ my $foo = "$1";
+ foreach $a (@archs) {
+ $install{"$foo.$a"} = 1 if defined($tlpdb->get_package("$foo.$a"));
+ }
+ } elsif ($p_dep =~ m/^(.*)\.win32$/) {
+ # a win32 package should *only* be installed if we are installing
+ # the win32 arch
+ if (grep(/^win32$/,@archs)) {
+ $install{$p_dep} = 1;
+ }
+ } else {
+ $install{$p_dep} = 1;
+ }
+ }
+ }
+
+ # check for newly selected packages
+ my @post_selected = keys %install;
+ debug("number of post installations: $#post_selected\n");
+
+ # set repeat condition
+ if ($#pre_selected != $#post_selected) {
+ $changed = 1;
+ }
+ }
+
+ # now do the size computation
+ my $size = 0;
+ foreach $p (keys %install) {
+ my $tlpobj = $tlpdb->get_package($p);
+ if (not(defined($tlpobj))) {
+ tlwarn("$p should be installed but "
+ . "is not in texlive.tlpdb; disabling.\n");
+ $install{$p} = 0;
+ next;
+ }
+ $size+=$tlpobj->docsize if $vars{'option_doc'};
+ $size+=$tlpobj->srcsize if $vars{'option_src'};
+ $size+=$tlpobj->runsize;
+ foreach $a (@archs) {
+ $size += $tlpobj->binsize->{$a} if defined($tlpobj->binsize->{$a});
+ }
+ }
+ $vars{'total_size'} =
+ sprintf "%d", ($size * $TeXLive::TLConfig::BlockSize)/1024**2;
+}
+
+sub load_tlpdb {
+ my $master = $location;
+ info("Loading $master/$TeXLive::TLConfig::InfraLocation/$TeXLive::TLConfig::DatabaseName\n");
+ $tlpdb = TeXLive::TLPDB->new(root => $master);
+ if (!defined($tlpdb)) {
+ my $do_die = 1;
+ # if that failed, and:
+ # - we are installing from the network
+ # - the location string does not contain "tlnet"
+ # then we simply add "/systems/texlive/tlnet" in case someone just
+ # gave an arbitrary CTAN mirror address without the full path
+ if ($media eq "NET" && $location !~ m/tlnet/) {
+ tlwarn("First attempt for net installation failed;\n");
+ tlwarn(" repository url does not contain \"tlnet\",\n");
+ tlwarn(" retrying with \"/systems/texlive/tlnet\" appended.\n");
+ $location .= "/systems/texlive/tlnet";
+ $master = $location;
+ #
+ # since we change location, we reset the error count of the
+ # download object
+ $::tldownload_server->enable if defined($::tldownload_server);
+ #
+ $tlpdb = TeXLive::TLPDB->new(root => $master);
+ if (!defined($tlpdb)) {
+ tlwarn("Oh well, adding tlnet did not help.\n");
+ tlwarn(<<END_EXPLICIT_MIRROR);
+
+You may want to try specifying an explicit or different CTAN mirror;
+see the information and examples for the -repository option at
+http://tug.org/texlive/doc/install-tl.html
+(or in the output of install-tl --help).
+
+END_EXPLICIT_MIRROR
+ } else {
+ # hurray, that worked out
+ info("Loading $master/$TeXLive::TLConfig::InfraLocation/$TeXLive::TLConfig::DatabaseName\n");
+ $do_die = 0;
+ }
+ }
+ die "$0: Could not load TeX Live Database from $master, goodbye.\n"
+ if $do_die;
+ }
+ # set the defaults to what is specified in the tlpdb
+ $vars{'option_doc'} = $tlpdb->option("install_docfiles");
+ $vars{'option_src'} = $tlpdb->option("install_srcfiles");
+ $vars{'option_fmt'} = $tlpdb->option("create_formats");
+ $vars{'option_autobackup'} = $tlpdb->option("autobackup");
+ $vars{'option_backupdir'} = $tlpdb->option("backupdir");
+ $vars{'option_letter'} = defined($tlpdb->option("paper"))
+ && ($tlpdb->option("paper") eq "letter" ? 1 : 0);
+ $vars{'option_desktop_integration'} = $tlpdb->option("desktop_integration");
+ $vars{'option_desktop_integration'} = 1 if win32();
+ $vars{'option_path'} = $tlpdb->option("path");
+ $vars{'option_path'} = 0 if !defined($vars{'option_path'});
+ $vars{'option_path'} = 1 if win32();
+ $vars{'option_w32_multi_user'} = $tlpdb->option("w32_multi_user");
+ # we have to make sure that this option is set to 0 in case
+ # that a non-admin is running the installations program
+ $vars{'option_w32_multi_user'} = 0 if (win32() && !admin());
+ $vars{'option_file_assocs'} = $tlpdb->option("file_assocs");
+ $vars{'option_post_code'} = $tlpdb->option("post_code");
+ $vars{'option_sys_bin'} = $tlpdb->option("sys_bin");
+ $vars{'option_sys_man'} = $tlpdb->option("sys_man");
+ $vars{'option_sys_info'} = $tlpdb->option("sys_info");
+ $vars{'option_write18_restricted'} = $tlpdb->option("write18_restricted");
+ # this option is not stored in tlpdb if an existing installation is used
+ $vars{'option_write18_restricted'} ||= 1;
+
+ # check that the default scheme is actually present, otherwise switch to
+ # scheme-minimal
+ if (!defined($tlpdb->get_package($default_scheme))) {
+ if (!defined($tlpdb->get_package("scheme-minimal"))) {
+ die("Aborting, cannot find either $default_scheme or scheme_minimal");
+ }
+ $default_scheme = "scheme-minimal";
+ $vars{'selected_scheme'} = $default_scheme;
+ }
+}
+
+sub initialize_collections {
+ foreach my $pkg ($tlpdb->list_packages) {
+ my $tlpobj = $tlpdb->{'tlps'}{$pkg};
+ if ($tlpobj->category eq "Collection") {
+ $vars{"$pkg"}=0;
+ ++$vars{'n_collections_available'};
+ if ($pkg=~/collection-lang/) {
+ push @collections_lang, $pkg;
+ } elsif ($pkg=~/documentation/) {
+ if ($pkg=~/documentation-base/) {
+ push @collections_std, $pkg;
+ } else {
+ push @collections_lang_doc, $pkg;
+ }
+ } else {
+ push @collections_std, $pkg;
+ }
+ }
+ }
+ my $scheme_tlpobj = $tlpdb->get_package($default_scheme);
+ if (defined ($scheme_tlpobj)) {
+ $vars{'n_collections_selected'}=0;
+ foreach my $dependent ($scheme_tlpobj->depends) {
+ if ($dependent=~/^(collection-.*)/) {
+ $vars{"$1"}=1;
+ ++$vars{'n_collections_selected'};
+ }
+ }
+ }
+ if ($vars{"binary_win32"}) {
+ $vars{"collection-wintools"} = 1;
+ ++$vars{'n_collections_selected'};
+ }
+}
+
+sub set_install_platform {
+ my $detected_platform=platform;
+ if ($opt_custom_bin) {
+ $detected_platform = "custom";
+ }
+ my $warn_nobin;
+ my $warn_nobin_x86_64_linux;
+ my $nowarn="";
+ my $wp='***'; # warning prefix
+
+ $warn_nobin="\n$wp WARNING: No binaries for your platform found. ";
+ $warn_nobin_x86_64_linux="$warn_nobin" .
+ "$wp No binaries for x86_64-linux found, using i386-linux instead.\n";
+
+ my $ret = $warn_nobin;
+ if (defined $vars{"binary_$detected_platform"}) {
+ $vars{"binary_$detected_platform"}=1;
+ $vars{'inst_platform'}=$detected_platform;
+ $ret = $nowarn;
+ } elsif ($detected_platform eq 'x86_64-linux') {
+ $vars{'binary_i386-linux'}=1;
+ $vars{'inst_platform'}='i386-linux';
+ $ret = $warn_nobin_x86_64_linux;
+ } else {
+ if ($opt_custom_bin) {
+ $ret = "$wp Using custom binaries from $opt_custom_bin.\n";
+ } else {
+ $ret = $warn_nobin;
+ }
+ }
+ foreach my $key (keys %vars) {
+ if ($key=~/^binary.*/) {
+ ++$vars{'n_systems_selected'} if $vars{$key}==1;
+ }
+ }
+ return($ret);
+}
+
+sub create_profile {
+ my $profilepath = shift;
+ # The file "TLprofile" is created at the beginning of the
+ # installation process and contains information about the current
+ # setup. The purpose is to allow non-interactive installations.
+ my $fh;
+ if (ref($profilepath)) {
+ $fh = $profilepath;
+ } else {
+ open PROFILE, ">$profilepath";
+ $fh = \*PROFILE;
+ }
+ my $tim = gmtime(time);
+ print $fh "# texlive.profile written on $tim UTC\n";
+ print $fh "# It will NOT be updated and reflects only the\n";
+ print $fh "# installation profile at installation time.\n";
+ print $fh "selected_scheme $vars{selected_scheme}\n";
+ foreach my $key (sort keys %vars) {
+ print $fh "$key $vars{$key}\n"
+ if $key=~/^collection/ and $vars{$key}==1;
+ print $fh "$key $vars{$key}\n" if $key =~ /^option_/;
+ print $fh "$key $vars{$key}\n" if (($key =~ /^binary_/) && $vars{$key});
+ print $fh "$key $vars{$key}\n" if $key =~ /^TEXDIR/;
+ print $fh "$key $vars{$key}\n" if $key =~ /^TEXMFSYSVAR/;
+ print $fh "$key $vars{$key}\n" if $key =~ /^TEXMFSYSCONFIG/;
+ print $fh "$key $vars{$key}\n" if $key =~ /^TEXMFVAR/;
+ print $fh "$key $vars{$key}\n" if $key =~ /^TEXMFCONFIG/;
+ print $fh "$key $vars{$key}\n" if $key =~ /^TEXMFLOCAL/;
+ print $fh "$key $vars{$key}\n" if $key =~ /^TEXMFHOME/;
+ print $fh "$key $vars{$key}\n" if $key =~ /^in_place/;
+ print $fh "$key $vars{$key}\n" if $key =~ /^portable/;
+ }
+ if (!ref($profilepath)) {
+ close PROFILE;
+ }
+}
+
+sub read_profile {
+ my $profilepath = shift;
+ open PROFILE, "<$profilepath"
+ or die "$0: Cannot open profile $profilepath for reading.\n";
+ my %pro;
+ while (<PROFILE>) {
+ chomp;
+ next if m/^[[:space:]]*$/; # skip empty lines
+ next if m/^[[:space:]]*#/; # skip comment lines
+ my ($k,$v) = split (" ", $_, 2); # value might have spaces
+ $pro{$k} = $v;
+ }
+ foreach (keys %vars) {
+ # clear out collections from var
+ if (m/^collection-/) { $vars{$_} = 0; }
+ if (defined($pro{$_})) { $vars{$_} = $pro{$_}; }
+ }
+ # if a profile contains *only* the selected_scheme setting without
+ # any collection, we assume that exactely that scheme should be installed
+ my $coldefined = 0;
+ foreach my $k (keys %pro) {
+ if ($k =~ m/^collection-/) {
+ $coldefined = 1;
+ last;
+ }
+ }
+ # if at least one collection has been defined return here
+ return if $coldefined;
+ # since no collections have been defined in the profile, we
+ # set those to be installed on which the scheme depends
+ my $scheme=$tlpdb->get_package($vars{'selected_scheme'});
+ if (!defined($scheme)) {
+ dump_vars(\*STDOUT);
+ die ("Scheme $vars{selected_scheme} not defined.\n");
+ }
+ for my $scheme_content ($scheme->depends) {
+ $vars{"$scheme_content"}=1 if ($scheme_content=~/^collection-/);
+ }
+}
+
+# helper subroutine to do sanity check of options before installation
+sub sanitise_options {
+ # portable option overrides any system integration options
+ $vars{'option_path'} &&= !$vars{'portable'};
+ $vars{'option_file_assocs'} &&= !$vars{'portable'};
+ $vars{'option_desktop_integration'} &&= !$vars{'portable'};
+}
+
+sub prepare_installation {
+ make_var_skeleton "$vars{'TEXMFSYSVAR'}";
+ make_local_skeleton "$vars{'TEXMFLOCAL'}";
+ mkdirhier "$vars{'TEXMFSYSCONFIG'}";
+
+ if ($vars{'in_place'}) {
+ $localtlpdb = $tlpdb;
+ } else {
+ $localtlpdb=new TeXLive::TLPDB;
+ $localtlpdb->root("$vars{'TEXDIR'}");
+ }
+}
+
+
+sub do_install_packages {
+ my @what;
+ foreach my $package (sort keys %install) {
+ push @what, $package if ($install{$package} == 1);
+ }
+ my $media0 = $media;
+ $media0 = 'CD' if $media eq 'local_compressed';
+ $media0 = 'DVD' if $media eq 'local_uncompressed';
+ if (!install_packages($tlpdb,$media0,$localtlpdb,\@what,
+ $vars{'option_src'},$vars{'option_doc'})) {
+ my $profile_name = "installation.profile";
+ create_profile($profile_name);
+ tlwarn("Installation failed.\n");
+ tlwarn("Rerunning the installer will try to restart the installation.\n");
+ tlwarn("Or you can restart by running the installer with:\n");
+ if (win32()) {
+ tlwarn(" install-tl.bat --profile $profile_name [EXTRA-ARGS]\n");
+ } else {
+ tlwarn(" install-tl --profile $profile_name [EXTRA-ARGS]\n");
+ }
+ flushlog();
+ exit(1);
+ }
+}
+
+# for later complete removal we want to save some options and values
+# into the local tlpdb:
+# - should links be set, and if yes, the destination (bin,man,info)
+sub save_options_into_tlpdb {
+ $localtlpdb->option ("location", $location);
+ $localtlpdb->option ("autobackup", $vars{'option_autobackup'});
+ $localtlpdb->option ("backupdir", $vars{'option_backupdir'});
+ $localtlpdb->option ("create_formats", $vars{'option_fmt'} ? "1" : "0");
+ $localtlpdb->option ("desktop_integration", $vars{'option_desktop_integration'} ? "1" : "0");
+ $localtlpdb->option ("file_assocs", $vars{'option_file_assocs'});
+ $localtlpdb->option ("post_code", $vars{'option_post_code'} ? "1" : "0");
+ $localtlpdb->option ("sys_bin", $vars{'option_sys_bin'});
+ $localtlpdb->option ("sys_info", $vars{'option_sys_info'});
+ $localtlpdb->option ("sys_man", $vars{'option_sys_man'});
+ $localtlpdb->option ("install_docfiles", $vars{'option_doc'} ? "1" : "0");
+ $localtlpdb->option ("install_srcfiles", $vars{'option_src'} ? "1" : "0");
+ $localtlpdb->option ("w32_multi_user", $vars{'option_w32_multi_user'} ? "1" : "0");
+ my @archs;
+ foreach (keys %vars) {
+ if (m/^binary_(.*)$/ ) {
+ if ($vars{$_}) { push @archs, $1; }
+ }
+ }
+ if ($opt_custom_bin) {
+ push @archs, "custom";
+ }
+
+ # only if we forced the platform we do save this option into the tlpdb
+ if (defined($opt_force_arch)) {
+ $localtlpdb->setting ("platform", $::_platform_);
+ }
+ $localtlpdb->setting("available_architectures", @archs);
+ $localtlpdb->save() unless $vars{'in_place'};
+}
+
+# this seems not to be used anymore
+
+#sub import_settings_from_old_tlpdb {
+# my $dn = shift;
+# my $tlpdboldpath = "$dn/$TeXLive::TLConfig::InfraLocation/$TeXLive::TLConfig::DatabaseName";
+# my $previoustlpdb;
+# if (-r $tlpdboldpath) {
+# # we found an old installation, so read that one in and save
+# # the list installed collections into an array.
+# info ("Trying to load old TeX Live Database,\n");
+# $previoustlpdb = TeXLive::TLPDB->new(root => $dn);
+# if ($previoustlpdb) {
+# info ("Importing settings from old installation in $dn\n");
+# } else {
+# tlwarn ("Cannot load old TLPDB, continuing with normal installation.\n");
+# return;
+# }
+# } else {
+# return;
+# }
+# # first import the collections
+# # since the scheme is not the final word we select scheme-custom here
+# # and then set the single collections by hand
+# $vars{'selected_scheme'} = "scheme-custom";
+# $vars{'n_collections_selected'} = 0;
+# # remove the selection of all collections
+# foreach my $entry (keys %vars) {
+# if ($entry=~/^(collection-.*)/) {
+# $vars{"$1"}=0;
+# }
+# }
+# for my $c ($previoustlpdb->collections) {
+# my $tlpobj = $tlpdb->get_package($c);
+# if ($tlpobj) {
+# $vars{$c} = 1;
+# ++$vars{'n_collections_selected'};
+# }
+# }
+# # now take over the path
+# my $oldroot = $previoustlpdb->root;
+# my $newroot = abs_path("$oldroot/..") . "/$texlive_release";
+# $vars{'TEXDIR'} = $newroot;
+# $vars{'TEXMFSYSVAR'} = "$newroot/texmf-var";
+# $vars{'TEXMFSYSCONFIG'} = "$newroot/texmf-config";
+# # only TEXMFLOCAL is treated differently, we use what is found by kpsewhich
+# # in 2008 and onward this is defined as
+# # TEXMFLOCAL = $SELFAUTOPARENT/../texmf-local
+# # so kpsewhich -var-value=TEXMFLOCAL returns
+# # ..../2008/../texmf-local
+# # TODO TODO TODO
+# chomp (my $tml = `kpsewhich -var-value=TEXMFLOCAL`);
+# $tml = abs_path($tml);
+# $vars{'TEXMFLOCAL'} = $tml;
+# #
+# # now for the settings
+# # set the defaults to what is specified in the tlpdb
+# $vars{'option_doc'} =
+# $previoustlpdb->option_pkg("00texlive.installation",
+# "install_docfiles");
+# $vars{'option_src'} =
+# $previoustlpdb->option_pkg("00texlive.installation",
+# "install_srcfiles");
+# $vars{'option_fmt'} =
+# $previoustlpdb->option_pkg("00texlive.installation",
+# "create_formats");
+# $vars{'option_desktop_integration'} = 1 if win32();
+# $vars{'option_path'} =
+# $previoustlpdb->option_pkg("00texlive.installation",
+# "path");
+# $vars{'option_path'} = 0 if !defined($vars{'option_path'});
+# $vars{'option_path'} = 1 if win32();
+# $vars{'option_sys_bin'} =
+# $previoustlpdb->option_pkg("00texlive.installation",
+# "sys_bin");
+# $vars{'option_sys_man'} =
+# $previoustlpdb->option_pkg("00texlive.installation",
+# "sys_man");
+# $vars{'sys_info'} =
+# $previoustlpdb->option_pkg("00texlive.installation",
+# "sys_info");
+# #
+# # import the set of selected architectures
+# my @aar = $previoustlpdb->setting_pkg("00texlive.installation",
+# "available_architectures");
+# if (@aar) {
+# for my $b ($tlpdb->available_architectures) {
+# $vars{"binary_$b"} = member( $b, @aar );
+# }
+# $vars{'n_systems_available'} = 0;
+# for my $key (keys %vars) {
+# ++$vars{'n_systems_available'} if ($key=~/^binary/);
+# }
+# }
+#}
+
+# do everything to select a scheme
+#
+sub select_scheme {
+ my $s = shift;
+ # set the selected scheme to $s
+ $vars{'selected_scheme'} = $s;
+ # if we are working on scheme-custom simply return
+ return if ($s eq "scheme-custom");
+ # remove the selection of all collections
+ foreach my $entry (keys %vars) {
+ if ($entry=~/^(collection-.*)/) {
+ $vars{"$1"}=0;
+ }
+ }
+ # select the collections belonging to the scheme
+ my $scheme_tlpobj = $tlpdb->get_package($s);
+ if (defined ($scheme_tlpobj)) {
+ $vars{'n_collections_selected'}=0;
+ foreach my $dependent ($scheme_tlpobj->depends) {
+ if ($dependent=~/^(collection-.*)/) {
+ $vars{"$1"}=1;
+ ++$vars{'n_collections_selected'};
+ }
+ }
+ }
+ # we have first set all collection-* keys to zero and than
+ # set to 1 only those which are required by the scheme
+ # since now scheme asks for collection-wintools we set its vars value
+ # to 1 in case we are installing win32 binaries
+ if ($vars{"binary_win32"}) {
+ $vars{"collection-wintools"} = 1;
+ ++$vars{'n_collections_selected'};
+ }
+ # for good measure, update the deps
+ calc_depends();
+}
+
+sub update_numbers {
+ $vars{'n_collections_available'}=0;
+ $vars{'n_collections_selected'} = 0;
+ $vars{'n_systems_available'} = 0;
+ $vars{'n_systems_selected'} = 0;
+ foreach my $key (keys %vars) {
+ if ($key =~ /^binary/) {
+ ++$vars{'n_systems_available'};
+ ++$vars{'n_systems_selected'} if $vars{$key} == 1;
+ }
+ if ($key =~ /^collection-/) {
+ ++$vars{'n_collections_available'};
+ ++$vars{'n_collections_selected'} if $vars{$key} == 1;
+ }
+ }
+}
+
+sub flushlog {
+ my $fh;
+ if (open(LOG,">install-tl.log")) {
+ printf "Writing log file to current working directory.\n";
+ $fh = \*LOG;
+ } else {
+ $fh = \*STDERR;
+ printf "Not creating a log file but flushing messages to stderr.\n";
+ }
+
+ foreach my $l (@::LOGLINES) {
+ print $fh $l;
+ }
+}
+
+sub check_on_lang_collection_installed {
+ # we check that at least one lang collection is installed:
+ foreach my $c (@collections_lang) {
+ return 1 if $vars{"$c"};
+ }
+ if ($vars{"selected_scheme"} eq "scheme-context") {
+ # context
+ return 1;
+ }
+ return 0;
+}
+
+sub do_cleanup {
+ # now open the log file and write out the log lines
+ # try to open a log file
+ # the user could have given the -logfile option in which case all the
+ # stuff is already dumped to it and $::LOGFILE defined. So do not
+ # redefine it
+ if (!defined($::LOGFILE)) {
+ if (open(LOGF,">$vars{'TEXDIR'}/install-tl.log")) {
+ $::LOGFILE = \*LOGF;
+ foreach my $line(@::LOGLINES) {
+ print $::LOGFILE "$line";
+ }
+ } else {
+ tlwarn("$0: Cannot create log file $vars{'TEXDIR'}/install-tl.log: $!\n"
+ . "Not writing out log lines.\n");
+ }
+ }
+
+ # remove temporary files from TEXDIR/temp
+ if (($media eq "local_compressed") or ($media eq "NET")) {
+ debug("Remove temporary downloaded containers...\n");
+ rmtree("$vars{'TEXDIR'}/temp") if (-d "$vars{'TEXDIR'}/temp");
+ }
+
+ # write the profile out
+ if ($vars{'in_place'}) {
+ create_profile("$vars{'TEXDIR'}/texlive.profile");
+ debug("Profile written to $vars{'TEXDIR'}/texlive.profile\n");
+ } else {
+ create_profile("$vars{'TEXDIR'}/$InfraLocation/texlive.profile");
+ debug("Profile written to $vars{'TEXDIR'}/$InfraLocation/texlive.profile\n");
+ }
+ # Close log file if present
+ close($::LOGFILE) if (defined($::LOGFILE));
+ if (defined($::LOGFILENAME) and (-e $::LOGFILENAME)) {
+ print "Logfile: $::LOGFILENAME\n";
+ } elsif (-e "$vars{'TEXDIR'}/install-tl.log") {
+ print "Logfile: $vars{'TEXDIR'}/install-tl.log\n";
+ } else {
+ print "No logfile\n";
+ }
+}
+
+
+# Return the basic welcome message.
+
+sub welcome {
+ my $welcome = <<"EOF";
+
+ See
+ $::vars{'TEXDIR'}/index.html
+ for links to documentation. The TeX Live web site (http://tug.org/texlive/)
+ contains updates and corrections.
+
+ TeX Live is a joint project of the TeX user groups around the world;
+ please consider supporting it by joining the group best for you. The
+ list of groups is available on the web at http://tug.org/usergroups.html.
+
+ Welcome to TeX Live!
+EOF
+ return $welcome;
+}
+
+
+# The same welcome message as above but with hints about C<PATH>,
+# C<MANPATH>, and C<INFOPATH>.
+
+sub welcome_paths {
+ my $welcome = welcome ();
+
+ # ugly, remove welcome msg; better than repeating the whole text, though.
+ $welcome =~ s/\n Welcome to TeX Live!\n//;
+
+ $welcome .= <<"EOF";
+
+ Add $::vars{'TEXDIR'}/texmf/doc/man to MANPATH, if not dynamically determined.
+ Add $::vars{'TEXDIR'}/texmf/doc/info to INFOPATH.
+EOF
+
+ if ($::vars{'in_place'} and !win32()) {
+ $welcome .= <<"EOF";
+ Set TEXMFCNF to $::vars{'TEXMFSYSVAR'}/web2c.
+EOF
+ }
+
+ $welcome .= <<"EOF";
+
+ Most importantly, add $::vars{'TEXDIR'}/bin/$::vars{'this_platform'}
+ to your PATH for current and future sessions.
+EOF
+
+ unless ($ENV{"TEXLIVE_INSTALL_ENV_NOCHECK"}) {
+ # check for tex-related envvars.
+ my $texenvs = "";
+ for my $evar (sort keys %origenv) {
+ next if $evar =~ /^(_
+ |.*PWD
+ |GENDOCS_TEMPLATE_DIR|PATH|SHELLOPTS
+ )$/x; # don't worry about these
+ if ("$evar $origenv{$evar}" =~ /tex/i) { # check both key and value
+ $texenvs .= " $evar=$origenv{$evar}\n";
+ }
+ }
+ if ($texenvs) {
+ $welcome .= <<"EOF";
+
+ ----------------------------------------------------------------------
+ The following environment variables contain the string "tex"
+ (case-independent). If you're doing anything but adding personal
+ directories to the system paths, they may well cause trouble with
+ some parts of running TeX. If you encounter problems, try unsetting
+ them. Please ignore any spurious matches that are unrelated to TeX.
+
+$texenvs ----------------------------------------------------------------------
+EOF
+ }
+ }
+
+ $welcome .= <<"EOF";
+
+ Welcome to TeX Live!
+EOF
+
+ return $welcome;
+}
+
+
+#
+# remember the warnings issued
+sub install_warnlines_hook {
+ push @::warn_hook, sub { push @::WARNLINES, @_; };
+}
+
+#
+# a summary of warnings if there were any
+sub warnings_summary {
+ return '' unless @::WARNLINES;
+ my $summary = <<EOF;
+
+ There were some warnings during the installation process.
+ Here is a summary of warning messages:
+EOF
+ $summary .= ' ' . join(' ', @::WARNLINES) . "\n";
+ return $summary;
+}
+
+
+#
+# some helper fucntion
+sub select_collections {
+ my $varref = shift;
+ foreach (@_) {
+ $varref->{$_} = 1;
+ }
+}
+
+sub deselect_collections {
+ my $varref = shift;
+ foreach (@_) {
+ $varref->{$_} = 0;
+ }
+}
+
+
+__END__
+
+=head1 NAME
+
+install-tl - TeX Live cross-platform installer
+
+=head1 SYNOPSIS
+
+install-tl [I<option>]...
+
+install-tl.bat [I<option>]...
+
+=head1 DESCRIPTION
+
+This installer creates a runnable TeX Live installation from various
+media, including over the network. The installer works across all
+platforms supported by TeX Live. For information on initially
+downloading the TeX Live, see L<http://tug.org/texlive/acquire.html>.
+
+The basic idea of TeX Live installation is to choose one of the
+top-level I<schemes>, each of which is defined as a different set of
+I<collections> and I<packages>, where a collection is a set of packages,
+and a package is what contains actual files.
+
+Within the installer, you can choose a scheme, and further customize the
+set of collections to install, but not the set of the packages. To do
+that, use C<tlmgr> (reference below) after the initial installation is
+completely.
+
+The default is C<scheme-full>, to install everything, and this is highly
+recommended.
+
+=head1 REFERENCES
+
+Post-installation configuration, package updates, and much more, are
+handled through B<tlmgr>(1), the TeX Live Manager
+(L<http://tug.org/texlive/tlmgr.html>).
+
+The most up-to-date version of this documentation is on the Internet at
+L<http://tug.org/texlive/doc/install-tl.html>.
+
+For the full documentation of TeX Live, see
+L<http://tug.org/texlive/doc>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-gui> [[=]I<module>]
+
+If no I<module> is given starts the C<perltk> (see below) GUI installer.
+
+If I<module> is given loads the given installer module. Currently the
+following modules are supported:
+
+=over 8
+
+=item C<text>
+
+The text mode user interface which is the default on Unix systems, and
+can be forced with by giving C<text> as I<module>, or with the C<-no-gui>
+switch.
+
+=item C<wizard>
+
+The wizard mode user interface asking only a few questions before installing
+all of TeX Live. This is the default on Windows systems.
+
+=item C<perltk>
+
+The all-in-one GUI installer.
+It can also be selected by giving the C<-gui> option without any I<module>.
+
+=back
+
+The C<perltk> and C<wizard> modules, and thus also when calling with a
+simple C<-gui> (without I<module>) requires
+the Perl/Tk module (L<http://tug.org/texlive/distro.html#perltk>); if
+Perl/Tk is not available, installation continues in text mode.
+
+
+=item B<-no-gui>
+
+Use the text mode installer (default except on Windows).
+
+=item B<-lang> I<llcode>
+
+(only for GUI installer) If possible, start the installer translated into
+the language specified by the 2-letter (ISO 639-1) language code (with
+the exception for selecting simplified or traditional Chinese).
+Currently supported
+languages: English (en, default), Czech (cs), German (de), French (fr),
+Italian (it), Dutch (nl), Polish (pl), Russian (ru), Slovak (sk),
+Slovenian (sl), Serbian (sr), Vietnamese (vi), simplified Chinese
+(zh-cn), and traditional Chinese (zh-tw).
+
+=item B<-repository> I<url|path>
+
+Specify the package repository to be used as the source of the
+installation, either a local directory via C</path/to/directory> or a
+C<file:/> url, or a network location via a C<http://> or C<ftp://> url.
+(No other protocols are supported.)
+
+The default is to pick a mirror automatically, using
+L<http://mirror.ctan.org/systems/texlive/tlnet>; the chosen mirror is
+used for the entire download. You can use the special argument C<ctan>
+as an abbreviation for this. See L<http://ctan.org> for more about CTAN
+and its mirrors.
+
+If the repository is on the network, trailing C</> characters and/or
+trailing C</tlpkg> and C</archive> components are ignored. For example,
+you could choose a particular CTAN mirror with something like this:
+
+ -repository http://ctan.example.org/its/ctan/dir/systems/texlive/tlnet
+
+Of course a real hostname and its particular top-level CTAN path
+have to be specified. The list of CTAN mirrors is available at
+L<http://ctan.org/mirrors>.
+
+If the repository is local, the installation type (compressed or live) is
+automatically determined, by checking for the presence of a
+C<archive> directory relative to the root. Compressed is
+preferred if both are available, since it is faster. Here's an example
+of using a local directory:
+
+ -repository /local/TL/repository
+
+After installation is complete, you can use that installation as the
+repository for another installation. If you chose to install less than
+the full scheme containing all packages, the list of available schemes
+will be adjusted accordingly.
+
+For backward compatibility and convenience, C<--location> and C<--repo>
+are accepted as aliases for this option.
+
+=item B<-all-options>
+
+Normally options not regarding the current platform are not shown.
+Giving this cmd line option allows to configure settings in the
+final tlpdb that do not have any immediate effect.
+
+=item B<-custom-bin> I<path>
+
+If you have built your own binaries for your system (probably because
+your platform was not supported by TeX Live out of the box), this option
+allows you to give the I<path> to a directory where the binaries for the
+current system are present. The installation will continue as usual, but
+at the end all files from I<path> are copied over to C<bin/custom> in
+your installation folder and this directory will be added to the path
+for the post-install actions.
+
+=item B<-debug-translation>
+
+In GUI mode, this switch makes C<tlmgr> report any missing, or more
+likely untranslated, messages to standard error. Helpful for
+translators to see what remains to be done.
+
+=item B<--help>, B<-help>, B<-?>
+
+Display this help and exit.
+
+=item B<-logfile> I<file>
+
+Write both all messages (informational, debugging, warnings) to I<file>,
+in addition to standard output or standard error.
+
+If this option is not given, the installer will create a log file
+in the root of the writable installation tree,
+for example, C</usr/local/texlive/YYYY/install-tl.log> for the I<YYYY>
+release.
+
+=item B<-force-platform> I<platform>
+
+Instead of auto-detecting the current platform, use I<platform>.
+Binaries for this platform must be present and they must actually be
+runnable, or installation will fail. C<-force-arch> is a synonym.
+
+=item B<-no-cls>
+
+(only for text mode installer) do not clear the screen when entering
+a new menu (for debugging purposes).
+
+=item B<-non-admin>
+
+For Windows only: configure for the current user, not for all users.
+
+=item B<--persistent-downloads>
+
+=item B<--no-persistent-downloads>
+
+For net installs, activating this option makes the installer try to set up a
+persistent connection using the Net::LWP Perl module.
+This opens only one connection between your computer and the server
+per session and reuses it, instead of initiating a new download for
+each package.
+
+This option is turned on by default, and the installation program will
+fall back to using C<wget> if this is not possible. To disable usage of
+LWP and persistent connections, use C<--no-persistent-downloads>.
+
+=item B<-portable>
+
+Install for portable use. This option minimazes the impact on the host
+system making TeX Live self-contained in a single directory and
+usable from portable drives. See section B<PORTABLE USE> below.
+
+=item B<-print-platform>
+
+Print the TeX Live identifier for the detected platform
+(hardware/operating system) combination to standard output, and exit.
+C<-print-arch> is a synonym.
+
+=item B<-profile> I<profile>
+
+Load the I<profile> file for repeated installations on different systems.
+A I<profile> contains the values of all necessary variable for the
+installation. After normal installation has finished a profile for that
+exact installation is written into DEST/tlpkg/texlive.profile. That file
+can be used to do the exact same installation on a different computer.
+
+You can also hand-craft such a profile starting from a generated one
+by changing some values. Normally a profile has to contain the value 1 for
+each collection that should be installed, even if the scheme is specified.
+That follows from the logic of the installer that you first select a scheme
+and then can change the actual collections being installed.
+
+There is one exception to this: If the profile contains a variable for
+C<selected_scheme> and I<no> collection variable is defined in the
+profile, then the collections which the specified scheme requires are
+installed. Thus, a simple line C<selected_scheme scheme-medium>
+together with the definitions of the paths (C<TEXDIR>,
+C<TEXMFHOME>, C<TEXMFLOCAL>, C<TEXMFSYSCONFIG>, C<TEXMFSYSVAR>) suffices
+to install the medium scheme with all default options.
+
+=item B<-q>
+
+Omit normal informational messages.
+
+=item B<-scheme> I<scheme>
+
+Schemes are the highest level of package grouping in TeX Live; the
+default is to use the C<full> scheme, which includes everything. This
+option overrides that default. You can change the scheme again before
+the actual installation with the usual menu. The I<scheme> argument may
+optionally have a prefix C<scheme->. The list of supported scheme names
+depends on what your package repository provides; see the interactive
+menu list.
+
+=item B<-v>
+
+Include debugging messages; repeat for maximum debugging, as in C<-v
+-v>. (Further repeats are accepted but ignored.)
+
+=item B<--version>, B<-version>
+
+Output version information and exit.
+If C<-v> has been given the revisions of the used modules are reported, too.
+
+=back
+
+As usual, all options can be specified with either C<-> or C<-->, and
+arguments can be separated from their options by either a space or C<=>.
+
+=head1 PORTABLE USE
+
+The root directory of a TeX Live installation contains a shell script
+C<tl-portable> and a DOS batch file C<tl-portable.bat> which start up a
+new shell (command prompt), in which TeX Live can be run self-contained.
+
+When running these scripts from a non-writable medium, some preparation
+of the host system is done on the first run, in the host directory
+C<~/.tlportableYYYY>. Otherwise, the host system is not touched.
+
+=head1 AUTHORS AND COPYRIGHT
+
+This script and its documentation were written for the TeX Live
+distribution (L<http://tug.org/texlive>) and both are licensed under the
+GNU General Public License Version 2 or later.
+
+=cut
+
+### Local Variables:
+### perl-indent-level: 2
+### tab-width: 2
+### indent-tabs-mode: nil
+### End:
+# vim:set tabstop=2 expandtab: #
diff --git a/Master/install-tl-new.bat b/Master/install-tl-new.bat
new file mode 100755
index 00000000000..37541572781
--- /dev/null
+++ b/Master/install-tl-new.bat
@@ -0,0 +1,64 @@
+@echo off
+rem $Id: install-tl.bat 15942 2009-11-06 23:54:05Z trzeciak $
+rem Wrapper script to set up environment for installer
+rem
+rem Public domain.
+rem Originally written 2009 by Tomasz M. Trzeciak.
+
+rem First, check if this is DOS based system
+rem in DOS '^' is just a normal character
+if not ^x==x goto DOS
+
+rem Abort if we are running from UNC path
+if %~d0==\\ goto UNC
+
+rem Localize environment changes
+setlocal enableextensions
+
+rem Do we really need to cd to the batch location?
+cd /d %~dp0
+
+rem Break search path into dir list and rebuild w/o tex dirs
+call :rebuildpath ";" "%path:;=" "%"
+if "%path:~0,1%"==";" set path=%path:~1%
+
+rem Use TL Perl
+set path=%~dp0tlpkg\tlperl\bin;%path%
+set PERL5LIB=%~dp0tlpkg\tlperl\lib
+
+rem Start installer
+path
+perl "%~dpn0" %*
+pause
+goto :eof
+
+rem Subroutine to build search path without tex directories
+rem any dir containing pdftex.exe is considered a tex dir
+:rebuildpath ";" dir list ...
+shift
+rem The first argument (";") serves as a marker to reset the path
+if "%~0"==";" set path=
+rem Finish if no more arguments to process
+if [%1]==[] goto :eof
+rem Continue if tex dir
+if exist "%~1\pdftex.exe" goto :rebuildpath
+rem Add dir to path
+set path=%path%;%~1
+goto :rebuildpath
+
+rem About install-tl.bat.manifest:
+rem Vista assumes that a file with install in the name is
+rem an installer and therefore requires administrative privileges.
+rem The manifest file tells Vista otherwise.
+
+:UNC
+echo Cannot run from UNC path.
+echo Map network drive to a drive letter and rerun the installer.
+echo You can use pushd/popd commands for temporary mapping.
+pause
+exit /b 1
+
+:DOS
+echo DOS and Windows 9x systems are not supported. Sorry.
+echo Windows 2000 or newer is required.
+pause
diff --git a/Master/tlpkg/installer/install-menu-perltk-new.pl b/Master/tlpkg/installer/install-menu-perltk-new.pl
new file mode 100644
index 00000000000..6cb806fbb92
--- /dev/null
+++ b/Master/tlpkg/installer/install-menu-perltk-new.pl
@@ -0,0 +1,1054 @@
+#!/usr/bin/env perl
+# $Id: install-menu-perltk.pl 20268 2010-10-31 07:26:14Z preining $
+#
+# Copyright 2008, 2009, 2010 Norbert Preining
+# Copyright 2008 Reinhard Kotucha
+# This file is licensed under the GNU General Public License version 2
+# or any later version.
+#
+# TODO:
+# - make the fancy selector the default, at least on unix
+# - for w32 find out the necessary files for the fancy selector and move
+# them to the installer perl package
+
+use strict;
+$^W = 1;
+
+my $svnrev = '$Revision: 20268 $';
+$svnrev =~ m/: ([0-9]+) /;
+$::menurevision = $1;
+
+require Tk;
+require Tk::Dialog;
+require Tk::DialogBox;
+require Tk::PNG;
+require Tk::ROText;
+require Tk::ProgressBar;
+require Tk::BrowseEntry;
+
+if ($::alternative_selector) {
+ require Tk::DirTree;
+}
+
+use utf8;
+no utf8;
+
+our %vars;
+our $tlpdb;
+our @collections_std;
+our @collections_lang;
+our @collections_lang_doc;
+our $texlive_release;
+
+our $MENU_INSTALL = 0;
+our $MENU_ABORT = 1;
+our $MENU_QUIT = 2;
+our $MENU_ALREADYDONE = 3;
+
+my $return = $MENU_INSTALL;
+
+our $LANG;
+our %TRANS;
+require("TeXLive/trans.pl");
+
+$::fileassocdesc[0] = __("None");
+$::fileassocdesc[1] = __("Only new");
+$::fileassocdesc[2] = __("All");
+
+$::letterdesc[0] = __('A4');
+$::letterdesc[1] = __('letter');
+
+my $mw;
+my $subframe;
+my $mainwindow;
+my $bintextbutton;
+my $schemebutton;
+my $tmflocalbutton;
+my $tmfsysvarbutton;
+my $tmfsysconfigbutton;
+my $tmfhomebutton;
+my $pathbutton;
+my $deskintbutton;
+my $assocbutton;
+my $adminbutton;
+my $collectionstext;
+my $texmflocaltext;
+my $texmfsysvartext;
+my $texmfsysconfigtext;
+my $texmfhometext;
+my $texdirtext;
+my $langcoltext;
+my $optletterstate;
+my $optfmtstate;
+my $optsrcstate;
+my $optdocstate;
+my $portableyesno = ( $vars{'portable'} ? __("Yes") : __("No") );
+my $letteryesno = $::letterdesc[$vars{'option_letter'}];
+my $fmtyesno = ( $vars{'option_fmt'} ? __("Yes") : __("No") );
+my $srcyesno = ( $vars{'option_src'} ? __("Yes") : __("No") );
+my $deskintyesno = ( $vars{'option_desktop_integration'} ? __("Yes") : __("No") );
+my $pathadjyesno = ( $vars{'option_path'} ? __("Yes") : __("No") );
+my $fileassocyesno = $::fileassocdesc[$vars{'option_file_assocs'}];
+my $editoryesno = ( $vars{'collection-texworks'} ? __("Yes") : __("No") );
+my $adminallyesno = ( $vars{'option_w32_multi_user'} ? __("Yes") : __("No") );
+my $docyesno = ( $vars{'option_doc'} ? __("Yes") : __("No") );
+my $restrictedyesno = ( $vars{'option_write18_restricted'} ? __("Yes") : __("No") );
+
+$::run_menu = \&run_menu_perltk;
+
+
+####################################################################
+# From here on only function definitions
+# ##################################################################
+
+
+sub menu_abort {
+ $return = $MENU_ABORT;
+ $mainwindow->destroy;
+}
+
+sub setup_hooks_perltk {
+ @::info_hook = ();
+ push @::info_hook,
+ sub {
+ return unless defined $mainwindow;
+ update_status(join(" ",@_));
+ $mainwindow->update;
+ };
+ push @::warn_hook,
+ sub {
+ return unless defined $mainwindow ;
+ update_status(join(" ",@_));
+ $mainwindow->update;
+ };
+ @::install_packages_hook = ();
+ push @::install_packages_hook, \&update_progressbar;
+ push @::install_packages_hook,
+ sub {
+ return unless defined $mainwindow;
+ return unless defined $::sww;
+ $mainwindow->update;
+ $::sww->update;
+ };
+}
+
+sub update_status {
+ my ($p) = @_;
+ return unless defined $::progressw;
+ $::progressw->insert("end", "$p");
+ $::progressw->see("end");
+}
+sub update_progressbar {
+ my ($n,$total) = @_;
+ return unless defined $::progress;
+ if (defined($n) && defined($total)) {
+ $::progress->value(int($n*100/$total));
+ }
+}
+
+
+sub run_menu_perltk {
+ calc_depends();
+ $mainwindow = Tk::MainWindow->new;
+ $mainwindow->protocol('WM_DELETE_WINDOW' => \&menu_abort);
+ setup_hooks_perltk();
+
+ if (!win32()) {
+ require Tk::Pane;
+ $subframe = $mainwindow->Scrolled("Frame", -scrollbars => "oe");
+ } else {
+ $subframe = $mainwindow->Frame;
+ }
+ $mw = $subframe->Frame;
+
+ # image frame on the left
+ my $fl = $mw->Frame(-background => "#0078b8");
+ my $img = $fl->Photo(-format => 'png', -file => "$::installerdir/tlpkg/installer/texlive.png");
+ $fl->Label(-image => $img, -background => "#0078b8")->pack(-expand => 1, -fill => "y");
+ $fl->Label(-text => "v$::installerrevision/$::menurevision", -background => "#0078b8")->pack;
+
+ # data frame on the right
+ my $fr = $mw->Frame;
+ $fl->pack(-side => 'left', -expand => 1, -fill => "y");
+ $fr->pack(-side => 'right');
+
+
+ my $row = 1;
+ $fr->Label(-text => __("TeX Live %s Installation", $TeXLive::TLConfig::ReleaseYear))->grid(-row => $row, -column => 1, -columnspan => 3);
+
+ if (!$vars{'in_place'}) {
+
+ $row++;
+ $fr->Label(-text => "------- " . __("Basic Information") . " -------")->grid(-row => $row, -column => 1, -columnspan => 3);
+
+ # binary system line
+ if (!win32()) {
+ $row++;
+ $fr->Label(-text => __('Binary system(s)'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $bintextbutton = $fr->Label(-anchor => 'w');
+ $bintextbutton->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button(-text => __("Change"), -command => sub { menu_select_binsystems(); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+ }
+
+ $row++;
+
+ # scheme line
+ $fr->Label(-text => __('Selected scheme'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $schemebutton = $fr->Label(-anchor => 'w');
+ $schemebutton->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button(-text => __("Change"), -command => sub { menu_select_scheme(); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+
+ # further customization
+ $fr->Label(-text => "------- " . __("Further Customization") . " -------")->grid(-row => $row, -column => 1,-columnspan => 3);
+
+ $row++;
+ # standard collection line
+ $fr->Label(-text => __('Standard collections'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Button(-text => __("Change"), -command => sub { menu_select_standard_collections(); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ # lang collection line
+ $fr->Label(-text => __('Language collections'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $langcoltext = $fr->Label(-anchor => 'w')->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button( -text => __("Change"), -command => sub { menu_select_lang_collections(); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ $collectionstext = $fr->Label();
+ $collectionstext->grid(-row => $row, -column => 1, -columnspan => 3);
+ }
+
+ $row++;
+ # further customization
+ $fr->Label(-text => "------- " . __("Directory setup") . " -------")->grid(-row => $row, -column => 1, -columnspan => 3);
+
+ $row++;
+ $fr->Label(-text => __('Portable setup'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$portableyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button(-text => __("Toggle"), -command => sub { toggle_portable(); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ # texdir line
+ $fr->Label(-text => __('TEXDIR (the main TeX directory)'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $texdirtext = $fr->Label(-anchor => 'w')->grid(-row => $row, -column => 2, -padx => "2m");
+ if (!$vars{'in_place'}) {
+ if ($::alternative_selector) {
+ $fr->Button(-text => __("Change"), -command => sub { menu_edit_texdir("TEXDIR"); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+ } else {
+ $fr->Button(-text => __("Change"), -command => sub { menu_edit_vars_value("TEXDIR"); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+ }
+ }
+
+
+ $row++;
+ # texmflocal line
+ $fr->Label(-text => __('TEXMFLOCAL (directory for site-wide local files)'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $texmflocaltext = $fr->Label(-anchor => 'w')->grid(-row => $row, -column => 2, -padx => "2m");
+ $tmflocalbutton = $fr->Button(-text => __("Change"), -command => sub { menu_edit_vars_value("TEXMFLOCAL"); });
+ $tmflocalbutton -> grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ # texmfsysvar line
+ $fr->Label(-text => __('TEXMFSYSVAR (directory for autogenerated data)'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $texmfsysvartext = $fr->Label(-anchor => 'w')->grid(-row => $row, -column => 2, -padx => "2m");
+ $tmfsysvarbutton = $fr->Button(-text => __("Change"), -command => sub { menu_edit_vars_value("TEXMFSYSVAR"); });
+ $tmfsysvarbutton->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ # texmfsysconfig line
+ $fr->Label(-text => __('TEXMFSYSCONFIG (directory for local config)'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $texmfsysconfigtext = $fr->Label(-anchor => 'w')->grid(-row => $row, -column => 2, -padx => "2m");
+ $tmfsysconfigbutton = $fr->Button(-text => __("Change"), -command => sub { menu_edit_vars_value("TEXMFSYSCONFIG"); });
+ $tmfsysconfigbutton->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ # texmfhome line
+ $fr->Label(-text => __('TEXMFHOME (directory for user-specific files)'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $texmfhometext = $fr->Label(-anchor => 'w')->grid(-row => $row, -column => 2, -padx => "2m");
+ $tmfhomebutton = $fr->Button(-text => __("Change"), -command => sub { menu_edit_vars_value("TEXMFHOME"); });
+ $tmfhomebutton->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ if ($vars{'portable'}) {
+ for my $b ($tmflocalbutton, $tmfsysvarbutton, $tmfsysconfigbutton, $tmfhomebutton) {
+ $b->configure(-state => 'disabled')
+ }
+ }
+
+ $row++;
+ # Options
+ $fr->Label(-text => "------- " . __("Options") . " -------")->grid(-row => $row, -column => 1, -columnspan => 3);
+
+ $row++;
+ # optpaper
+ $fr->Label(-text => __('Default paper size'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$letteryesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'option_letter'}, \$letteryesno, \@::letterdesc); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ $fr->Label(-text => __('Allow execution of restricted list of programs via \write18'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$restrictedyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'option_write18_restricted'}, \$restrictedyesno); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ $fr->Label(-text => __('Create all format files'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$fmtyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'option_fmt'}, \$fmtyesno); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ if ($vars{'doc_splitting_supported'} and !$vars{'in_place'}) {
+ $row++;
+ $fr->Label(-text => __('Install font/macro doc tree'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$docyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'option_doc'}, \$docyesno); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+ }
+
+ if ($vars{'src_splitting_supported'} and !$vars{'in_place'}) {
+ $row++;
+ $fr->Label(-text => __('Install font/macro source tree'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$srcyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'option_src'}, \$srcyesno); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+ }
+
+ $row++;
+ $fr->Label(-text => (win32()) ? __('Adjust PATH setting in registry') :
+ __('Create symlinks in system directories'),
+ -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$pathadjyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ if (unix()) {
+ $pathbutton = $fr->Button(-text => __("Change"), -command => sub { menu_select_symlink(); });
+ } else {
+ $pathbutton = $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'option_path'}, \$pathadjyesno); });
+ }
+ $pathbutton->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ if ($::opt_all_options || win32()) {
+ $row++;
+ $fr->Label(-text => __('Add shortcuts to menu and desktop'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$deskintyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $deskintbutton = $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'option_desktop_integration'}, \$deskintyesno); });
+ $deskintbutton->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ $row++;
+ $fr->Label(-text => __('Change file associations'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$fileassocyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $assocbutton = $fr->Button(-text => __("Change"), -command => sub { menu_edit_file_assocs(); });
+ $assocbutton->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+
+ if ($::opt_all_options || admin()) {
+ $row++;
+ $fr->Label(-text => __('Installation for all users'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$adminallyesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ $adminbutton = $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'option_w32_multi_user'}, \$adminallyesno); });
+ $adminbutton->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+ }
+
+ $row++;
+ $fr->Label(-text => __('Install TeXworks front end'), -anchor => 'w')->grid(-row => $row, -column => 1, -sticky => 'w');
+ $fr->Label(-anchor => 'w', -textvariable => \$editoryesno)->grid(-row => $row, -column => 2, -padx => "2m");
+ if (!$vars{'in_place'}) {
+ $fr->Button(-text => __("Toggle"), -command => sub { toggle_and_set_opt_variable(\$vars{'collection-texworks'}, \$editoryesno); })->grid(-row => $row, -column => 3, -sticky => "ew", -padx => "2m");
+ }
+ }
+ if ($vars{'portable'}) {
+ for $b ($pathbutton, $deskintbutton, $assocbutton, $adminbutton) {
+ $b->configure(-state => 'disabled') if $b;
+ }
+ }
+
+ # install/cancel buttons
+ my $f3 = $fr->Frame;
+ $f3->Button(
+ -text => __("Install TeX Live"),
+ -command => sub { installation_window(); }
+ )->pack(-side => 'left', -padx => "2m", -pady => "2m")->focus();
+ my $quitbutton = $f3->Button(
+ -text => __("Quit"),
+ -command => \&menu_abort,
+ )->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $mw->bind('<Escape>', [ $quitbutton, 'Invoke' ]);
+ #my $wizardbutton = $f3->Button(
+ # -text => __("Wizard"),
+ # -command => sub {
+ # $mainwindow->destroy;
+ # require("installer/install-menu-wizard.pl");
+ # setup_hooks_wizard();
+ # $return = run_menu_wizard();
+ # })->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $row++;
+ $f3->grid(-row => $row, -column => 1, -columnspan => 3);
+ menu_update_texts();
+ $fr->gridColumnconfigure(2, -minsize => 300);
+ $mw->pack(-expand => 1, -fill => "both");
+ $mw->update;
+ my $rh = $mw->reqheight;
+ my $rw = $mw->reqwidth;
+ my $maxheight = $mainwindow->screenheight() - 20;
+ debug("Requested height: $rh, requested width: $rw, max height: $maxheight\n");
+ if ($rh > $maxheight) {
+ $rh = $maxheight;
+ $rw += 20; # for the scrollbar = =
+ }
+ $subframe->configure(-height => $rh, -width=>$rw);
+ $subframe->pack(-expand => 1, -fill => "both");
+ $mainwindow->configure(-height => $rh, -width=>$rw);
+ #$mw->pack(-expand => 1, -fill => "both");
+ Tk::MainLoop();
+ return($return);
+}
+
+sub installation_window {
+ # create a progress bar window
+ $::sww = $mainwindow->Toplevel(-title => __("Installation process"),
+ -width => 400);
+ $::sww->transient($mainwindow);
+ $::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 => __("Cancel"),
+ -command => sub { $::sww->destroy; $mainwindow->destroy;
+ do_cleanup(); exit(1); }
+ )->pack(-pady => "2m");
+ $b->focus();
+ $f->pack;
+ do_installation();
+ $return = $MENU_ALREADYDONE;
+ my $t = __("See %s/index.html for links to documentation.\nThe TeX Live web site (http://tug.org/texlive/) contains any updates and corrections. TeX Live is a joint project of the TeX user groups around the world; please consider supporting it by joining the group best for you. The list of groups is available on the web at http://tug.org/usergroups.html.", $::vars{'TEXDIR'});
+ if (!win32()) {
+ $t .= "\n\n" . __("Add %s/texmf/doc/man to MANPATH.\nAdd %s/texmf/doc/info to INFOPATH.\nMost importantly, add %s/bin/%s\nto your PATH for current and future sessions.", $::vars{'TEXDIR'}, $::vars{'TEXDIR'}, $::vars{'TEXDIR'}, $::vars{'this_platform'});
+ }
+ if (@::WARNLINES) {
+ $t .= "\n\n" . __("There were some warnings during the installation process.\nHere is the list of warning messages:") . "\n";
+ $t .= join('', @::WARNLINES);
+ $t =~ s/\n\z//;
+ }
+
+ $t .= "\n\n" . __("Welcome to TeX Live!");
+ #$t =~ s/\\n/\n/g;
+ $::progressw->insert("end", "\n");
+ my $linechar = $::progressw->index("end");
+ $::progressw->markSet("finaltext", $linechar);
+ $::progressw->markGravity("finaltext", "left");
+ $::progressw->insert("end", "\n$t");
+ $::progressw->see("end");
+ $::progressw->tagAdd("centered", $linechar, "end");
+ $::progressw->tagConfigure("centered", -justify => "center");
+ $b->configure(-text => __("Finish"),
+ -command => sub { $mainwindow->destroy; });
+}
+
+# this sub will not be called if $vars{'in_place'}
+sub menu_edit_texdir {
+ my $key = shift;
+ our $addyear = 1;
+ our $addtexlive = 1;
+ my $val = $vars{$key};
+ our $currsel;
+ our $entry;
+ sub update_label {
+ my $t = $currsel;
+ $t .= "/texlive" if ($addtexlive);
+ $t .= "/$texlive_release" if ($addyear);
+ $entry->configure(-text => "$t");
+ }
+ my $hint_var;
+ if ($key ne 'TEXMFHOME') {
+ $hint_var = win32() ? $ENV{'USERPROFILE'} : $ENV{'HOME'};
+ } else {
+ $hint_var = win32() ? '%USERPROFILE%' : '$HOME';
+ }
+ if ($val =~ m!^(.*)/texlive/$texlive_release$!) {
+ $currsel = "$1";
+ $addyear = 1;
+ $addtexlive = 1;
+ } elsif ($val =~ m!^(.*)/$texlive_release$!) {
+ $currsel = "$1";
+ $addyear = 1;
+ $addtexlive = 0;
+ } elsif ($val =~ m!^(.*)/texlive$!) {
+ $currsel = "$1";
+ $addyear = 0;
+ $addtexlive = 1;
+ } else {
+ $addyear = 0;
+ $addtexlive = 0;
+ $currsel = $val;
+ }
+ my $sw = $mainwindow->Toplevel(-title => __("Change variable value"));
+ $sw->transient($mainwindow);
+ $sw->grab();
+ $sw->Label(-text => __("Enter path for %s (use ~ for %s)", $key, $hint_var))->pack(-padx => "2m", -pady => "2m");
+ $entry = $sw->Entry(-width => 60)->pack(-padx => "2m", -pady => "2m");
+ my $f = $sw->Frame;
+ my $c1 = $f->Checkbutton(-text => 'Add "texlive"', -variable => \$addtexlive,
+ -command => \&update_label);
+ my $c2 = $f->Checkbutton(-text => "Add \"$texlive_release\"", -variable => \$addyear,
+ -command => \&update_label);
+ my $foo = $sw->Scrolled("DirTree", -scrollbars => "osoe",
+ -browsecmd => sub { my ($d) = @_; $currsel = $d; update_label(); },
+ -directory => "$currsel");
+ my $ff = $sw->Frame;
+ my $ok = $ff->Button(-text => __("Ok"), -command => sub { $val = $entry->get; callback_edit_directories($key,$val); $sw->destroy; });
+ my $cancel = $ff->Button(-text => __("Cancel"), -command => sub { $sw->destroy; });
+ update_label();
+ $c1->pack(-side => "left", -padx => "2m", -pady => "2m");
+ $c2->pack(-side => "right", -padx => "2m", -pady => "2m");
+ $f->pack;
+ $foo->pack(-fill => "both", -expand => 1);
+ $ok->pack(-side => 'left' , -padx => "2m", -pady => "2m");
+ $cancel->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $ff->pack;
+ # bindings
+ $sw->bind('<Return>' => [ $ok, 'Invoke']);
+ $sw->bind('<Escape>' => [ $cancel, 'Invoke']);
+}
+
+sub menu_edit_vars_value {
+ my $key = shift;
+ my $sw = $mainwindow->Toplevel(-title => __("Change variable value"));
+ $sw->transient($mainwindow);
+ $sw->grab();
+ my $val = $vars{$key};
+ my $hint_var;
+ if ($key ne 'TEXMFHOME') {
+ $hint_var = win32() ? $ENV{'USERPROFILE'} : $ENV{'HOME'};
+ } else {
+ $hint_var = win32() ? '%USERPROFILE%' : '$HOME';
+ }
+ $sw->Label(-text => __("Enter path for %s (use ~ for %s)", $key, $hint_var))->pack(-padx => "2m", -pady => "2m");
+ my $entry = $sw->Entry(-text => native_slashify($val), -width => 60);
+ $entry->pack(-padx => "2m", -pady => "2m")->focus();
+ my $f = $sw->Frame;
+ my $okbutton = $f->Button(-text => __("Ok"),
+ -command => sub { $val = forward_slashify($entry->get); callback_edit_directories($key,$val) ; $sw->destroy })->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ my $cancelbutton = $f->Button(-text => __("Cancel"),
+ -command => sub { $sw->destroy })->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $f->pack(-expand => 'x');
+ # bindings
+ $sw->bind('<Return>' => [ $okbutton, 'Invoke']);
+ $sw->bind('<Escape>' => [ $cancelbutton, 'Invoke']);
+}
+
+sub menu_edit_file_assocs {
+ my $sw = $mainwindow->Toplevel(-title => __('Change file associations'));
+ $sw->transient($mainwindow);
+ $sw->grab();
+ my $key = 'option_file_assocs';
+ my $var = $::fileassocdesc[$vars{$key}];
+ $sw->Label(-text => __("Change file associations"))->pack(-padx => "2m", -pady => "2m");
+ my $opt = $sw->BrowseEntry(-autolistwidth => 1,
+ -variable => \$var);
+ for my $i (0..2) {
+ $opt->insert("end", $::fileassocdesc[$i]);
+ }
+
+ $opt->pack(-padx => "2m", -pady => "2m")->focus();
+ my $f = $sw->Frame;
+ my $okbutton = $f->Button(-text => __("Ok"),
+ -command => sub {
+ my $idx;
+ if ($var eq $::fileassocdesc[0]) {
+ $idx = 0;
+ } elsif ($var eq $::fileassocdesc[1]) {
+ $idx = 1;
+ } elsif ($var eq $::fileassocdesc[2]) {
+ $idx = 2;
+ } else {
+ die "How that could happen!\n";
+ }
+ $vars{$key} = $idx;
+ $fileassocyesno = $::fileassocdesc[$idx];
+ $sw->destroy; })->pack(-side => "left", -padx => "2m", -pady => "2m");
+ my $cancelbutton = $f->Button(-text => __("Cancel"), -command => sub { $sw->destroy; })->pack(-side => "left", -padx => "2m", -pady => "2m");
+ $f->pack;
+ $sw->bind('<Return>', [ $okbutton, 'Invoke' ]);
+ $sw->bind('<Escape>', [ $cancelbutton, 'Invoke' ]);
+}
+
+
+sub menu_select_scheme {
+ my $sw = $mainwindow->Toplevel(-title => __('Selected scheme'));
+ $sw->transient($mainwindow);
+ $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;
+ push @schemes, "scheme-custom";
+ my $selected = $vars{'selected_scheme'};
+ $sw->Label(-text => __("Selected scheme"))->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 $desc;
+ if ($scheme ne "scheme-custom") {
+ my $tlpobj = $tlpdb->get_package("$scheme");
+ $desc = $tlpobj->shortdesc;
+ } else {
+ $desc = "custom selection of collections";
+ }
+ my $b;
+ if ($i < $nrfh) {
+ $b = $f2l->Radiobutton(-variable => \$selected, -value => $scheme,
+ -text => __($desc))->pack(-anchor => 'w');
+ } else {
+ $b = $f2r->Radiobutton(-variable => \$selected, -value => $scheme,
+ -text => __($desc))->pack(-anchor => 'w');
+ }
+ if ($selected eq $scheme) {
+ $b->focus();
+ }
+ $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 => __("Ok"),
+ -command => sub { callback_select_scheme($selected) ; $sw->destroy })->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ my $cancelbutton = $f3->Button(-text => __("Cancel"),
+ -command => sub { $sw->destroy })->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ $f3->pack(-expand => 'x');
+ $sw->bind('<Return>' => [ $okbutton, 'Invoke']);
+ $sw->bind('<Escape>' => [ $cancelbutton, 'Invoke']);
+}
+
+sub menu_select_standard_collections {
+ my $sw = $mainwindow->Toplevel(-title => __('Standard collections'));
+ $sw->transient($mainwindow);
+ $sw->grab();
+ my $fb = $sw->Frame;
+ my $fc = $sw->Frame;
+ my $fd = $sw->Frame;
+ my $f1 = $fb->Frame;
+ my $f2 = $fb->Frame;
+ my %lvars = %vars;
+ $sw->Label(-text => __("Select the collections to be installed"))->pack(-padx => "2m", -pady => "2m");
+ my $halfcol = $#collections_std / 2;
+ my $i = 0;
+ foreach my $coll (sort @collections_std) {
+ my $tlpobj = $tlpdb->get_package("$coll");
+ if ($i < $halfcol) {
+ $f1->Checkbutton(-variable => \$lvars{$coll}, -text => __($tlpobj->shortdesc))->pack(-anchor => 'w');
+ } else {
+ $f2->Checkbutton(-variable => \$lvars{$coll}, -text => __($tlpobj->shortdesc))->pack(-anchor => 'w');
+ }
+ $i++;
+ }
+ $f1->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ $f2->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $fb->pack(-padx => "2m", -pady => "2m");
+ $fc->pack();
+ $fc->Button(-text => __("Select All"),
+ -command => sub { select_collections(\%lvars, @collections_std) })->pack(-side => 'left', -padx => "2m", -pady => "2m")->focus();
+ $fc->Button(-text => __("Deselect All"),
+ -command => sub { deselect_collections(\%lvars, @collections_std) })->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $fd->pack(-expand => 'x', -padx => "2m", -pady => "2m");
+ my $okbutton = $fd->Button(-text => __("Ok"),
+ -command => sub {
+ # we call the update only if something has changed
+ my $changed = 0;
+ for my $k (keys %lvars) {
+ if ($vars{$k} ne $lvars{$k}) {
+ $changed = 1;
+ last;
+ }
+ }
+ if ($changed) {
+ %vars = %lvars;
+ callback_select_collection();
+ }
+ $sw->destroy;
+ })->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ my $cancelbutton = $fd->Button(-text => __("Cancel"),
+ -command => sub { $sw->destroy })->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $sw->bind('<Return>' => [ $okbutton, 'Invoke']);
+ $sw->bind('<Escape>' => [ $cancelbutton, 'Invoke']);
+}
+
+sub menu_select_lang_collections {
+ my $sw = $mainwindow->Toplevel(-title => __('Language collections'));
+ $sw->transient($mainwindow);
+ $sw->grab();
+ my $f1 = $sw->Frame;
+ $f1->pack;
+ my $f1lang = $f1->Labelframe(-text => __("Select language support"));
+ my $f1doc = $f1->Labelframe(-text => __("Select language-specific documentation"));
+ $f1lang->pack(-side => 'left', -padx => "2m", -pady => "2m", -ipadx => "2m", -ipady => "2m");
+ $f1doc->pack(-side => 'right', -padx => "2m", -pady => "2m", -ipadx => "2m", -ipady => "2m", -expand => 1, -fill => "y");
+ my $f1langT = $f1lang->Frame; $f1langT->pack;
+ my $f1langL = $f1lang->Frame; $f1langL->pack;
+ my $f1langLa = $f1langL->Frame; $f1langLa->pack(-side => 'left');
+ my $f1langLb = $f1langL->Frame; $f1langLb->pack(-side => 'right');
+ my $langh = $#collections_lang / 2;
+ my $i = 0;
+ my %lvars = %vars;
+ foreach my $coll (sort @collections_lang) {
+ my $tlpobj = $tlpdb->get_package("$coll");
+ if ($i < $langh) {
+ $f1langLa->Checkbutton(-variable => \$lvars{$coll}, -text => __($tlpobj->shortdesc))->pack(-anchor => 'w');
+ } else {
+ $f1langLb->Checkbutton(-variable => \$lvars{$coll}, -text => __($tlpobj->shortdesc))->pack(-anchor => 'w');
+ }
+ $i++;
+ }
+ my $f1langB = $f1lang->Frame;
+ $f1langB->pack(-expand => 'x');
+ $f1langB->Button(-text => __("Select All"),
+ -command => sub { select_collections(\%lvars, @collections_lang) })->pack(-side => 'left', -padx => "2m", -pady => "2m")->focus();
+ $f1langB->Button(-text => __("Deselect All"),
+ -command => sub { deselect_collections(\%lvars, @collections_lang) })->pack(-side => 'right', -padx => "2m", -pady => "2m");
+
+ my $f1docT = $f1doc->Frame; $f1docT->pack;
+ my $f1docL = $f1doc->Frame; $f1docL->pack;
+ my $f1docLa = $f1docL->Frame; $f1docLa->pack(-side => 'left');
+ my $f1docLb = $f1docL->Frame; $f1docLb->pack(-side => 'right');
+ my $doch = $#collections_lang_doc / 2;
+ $i = 0;
+ foreach my $coll (sort @collections_lang_doc) {
+ my $tlpobj = $tlpdb->get_package("$coll");
+ if ($i < $doch) {
+ $f1docLa->Checkbutton(-variable => \$lvars{$coll}, -text => __($tlpobj->shortdesc))->pack(-anchor => 'w');
+ } else {
+ $f1docLb->Checkbutton(-variable => \$lvars{$coll}, -text => __($tlpobj->shortdesc))->pack(-anchor => 'w');
+ }
+ $i++;
+ }
+ my $f1docB = $f1doc->Frame;
+ $f1docB->pack(-expand => 1, -side => "bottom");
+ $f1docB->Button(-text => __("Select All"),
+ -command => sub { select_collections(\%lvars, @collections_lang_doc) })->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ $f1docB->Button(-text => __("Deselect All"),
+ -command => sub { deselect_collections(\%lvars, @collections_lang_doc) })->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ my $f2 = $sw->Frame; $f2->pack(-expand => 'x');
+ my $okbutton = $f2->Button(-text => __("Ok"),
+ -command => sub {
+ # we call the update only if something has changed
+ my $changed = 0;
+ for my $k (keys %lvars) {
+ if ($vars{$k} ne $lvars{$k}) {
+ $changed = 1;
+ last;
+ }
+ }
+ if ($changed) {
+ %vars = %lvars;
+ callback_select_collection();
+ }
+ $sw->destroy;
+ })->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ my $cancelbutton = $f2->Button(-text => __("Cancel"),
+ -command => sub { $sw->destroy })->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $sw->bind('<Return>' => [ $okbutton, 'Invoke']);
+ $sw->bind('<Escape>' => [ $cancelbutton, 'Invoke']);
+}
+
+sub menu_select_symlink {
+ our ($lbin,$lman,$linfo);
+ our $osym = $vars{'option_path'};
+ our ($binlab,$binb,$manlab,$manb,$infolab,$infob);
+ sub set_unset_buttons {
+ $lbin = ($osym ? $vars{'option_sys_bin'} : '');
+ $linfo = ($osym ? $vars{'option_sys_info'} : '');
+ $lman = ($osym ? $vars{'option_sys_man'} : '');
+ if ($osym) {
+ $binb->configure (-state => 'normal');
+ $manb->configure (-state => 'normal');
+ $infob->configure(-state => 'normal');
+ } else {
+ $infob->configure(-state => 'disabled');
+ $manb->configure (-state => 'disabled');
+ $binb->configure (-state => 'disabled');
+ }
+ }
+ sub return_callback {
+ if ($osym) {
+ my $home = getenv('HOME');
+ $home = getenv('USERPROFILE') if (win32());
+ $home ||= '~';
+ $lbin =~ s/^~/$home/;
+ $linfo =~ s/^~/$home/;
+ $lman =~ s/^~/$home/;
+ $vars{'option_sys_bin'} = $lbin;
+ $vars{'option_sys_info'} = $linfo;
+ $vars{'option_sys_man'} = $lman;
+ }
+ $vars{'option_path'} = $osym;
+ toggle_and_set_opt_variable(\$vars{'option_path'}, \$pathadjyesno);
+ }
+ my $sw = $mainwindow->Toplevel(-title => __('Create symlinks in system directories'));
+ $sw->transient($mainwindow);
+ $sw->grab();
+ $sw->Checkbutton(-variable => \$osym,
+ -text => __("create symlinks in standard directories"),
+ -command => sub { set_unset_buttons(); } )->grid(-column => 1,
+ -row => 1,
+ -columnspan => 2,
+ -padx => "2m");
+ $binlab = $sw->Label(-text => __("binaries to"));
+ $binb = $sw->Entry(-textvariable => \$lbin);
+ $manlab = $sw->Label(-text => __("manpages to"));
+ $manb = $sw->Entry(-textvariable => \$lman);
+ $infolab = $sw->Label(-text => __("info to"));
+ $infob = $sw->Entry(-textvariable => \$linfo);
+ $binlab->grid(-row => 2, -column => 1, -sticky => "w", -padx => "2m");
+ $binb->grid(-row => 2, -column => 2, -sticky => "ew", -padx => "2m");
+ $manlab->grid(-row => 3, -column => 1, -sticky => "w", -padx => "2m");
+ $manb->grid(-row => 3, -column => 2, -sticky => "ew", -padx => "2m");
+ $infolab->grid(-row => 4, -column => 1, -sticky => "w", -padx => "2m");
+ $infob->grid(-row => 4, -column => 2, -sticky => "ew", -padx => "2m");
+ set_unset_buttons();
+ my $f2 = $sw->Frame; $f2->grid(-column => 1, -columnspan => 2, -row => 5);
+ my $okbutton = $f2->Button(-text => __("Ok"),
+ -command => sub { return_callback(); $sw->destroy })->pack(-side => 'left');
+ my $cancelbutton = $f2->Button(-text => __("Cancel"),
+ -command => sub { $sw->destroy })->pack(-side => 'right');
+ $sw->bind('<Return>' => [ $okbutton, 'Invoke']);
+ $sw->bind('<Escape>' => [ $cancelbutton, 'Invoke']);
+}
+
+sub menu_select_binsystems {
+ my $f2r;
+ my $f2;
+ my $sw = $mainwindow->Toplevel(-title => __('Binary system(s)'));
+ $sw->transient($mainwindow);
+ $sw->grab();
+ my @diskarchs = ();
+ foreach my $key (keys %vars) {
+ if ($key=~/binary_(.*)/) {
+ push @diskarchs, $1;
+ }
+ }
+ $sw->Label(-text => __("Select arch-os"))->pack(-padx => "2m", -pady => "2m");
+ $f2 = $sw->Frame;
+ my $f2l = $f2->Frame;
+ foreach my $sys (sort @diskarchs) {
+ $f2l->Checkbutton(-variable => \$vars{"binary_$sys"}, -text => platform_desc($sys))->pack(-anchor => 'w');
+ }
+ $f2l->pack(-side => 'left');
+ $f2->pack(-padx => "2m", -pady => "2m");
+ my $f3 = $sw->Frame;
+ my $okbutton = $f3->Button(-text => __("Ok"),
+ -command => sub { callback_select_systems() ; $sw->destroy })->pack(-side => 'left', -padx => "2m", -pady => "2m");
+ my $cancelbutton = $f3->Button(-text => __("Cancel"),
+ -command => sub { $sw->destroy })->pack(-side => 'right', -padx => "2m", -pady => "2m");
+ $f3->pack(-expand => 'x');
+ $sw->bind('<Return>' => [ $okbutton, 'Invoke']);
+ $sw->bind('<Escape>' => [ $cancelbutton, 'Invoke']);
+}
+
+
+sub menu_set_text {
+ my $w = shift;
+ my $t = shift;
+ # if in_place or portable not a complete interface
+ $w->configure(-text => $t, @_) if $w;
+}
+
+sub menu_set_schemebutton_text {
+ menu_set_text($schemebutton, "$vars{'selected_scheme'}");
+}
+
+sub menu_set_binbutton_text {
+ if (!win32()) {
+ menu_set_text($bintextbutton, __("%s out of %s", $vars{'n_systems_selected'}, $vars{'n_systems_available'}));
+ }
+}
+
+sub menu_set_collections_text {
+ menu_set_text($collectionstext, __("%s collections out of %s",
+ $vars{'n_collections_selected'}, $vars{'n_collections_available'})
+ . " (" . __("disk space required:") . " $vars{'total_size'} MB)");
+}
+
+sub menu_set_pathes_text {
+ if (check_on_lang_collection_installed()) {
+ # good
+ menu_set_text($langcoltext, "");
+ } else {
+ # bad
+ menu_set_text($langcoltext, __("(no language collection selected!)"), -foreground => "red");
+ }
+ if (TeXLive::TLUtils::texdir_check($vars{'TEXDIR'})) {
+ menu_set_text($texdirtext, native_slashify($vars{'TEXDIR'}), -foreground => "black");
+ } else {
+ menu_set_text($texdirtext, __("(default not writable - please change!)"), -foreground => "red");
+ }
+ menu_set_text($texmflocaltext, native_slashify($vars{'TEXMFLOCAL'}));
+ if ((-w $vars{'TEXMFSYSVAR'}) || (-w dirname($vars{'TEXMFSYSVAR'}))) {
+ menu_set_text($texmfsysvartext, native_slashify($vars{'TEXMFSYSVAR'}), -foreground => "black");
+ } elsif ("$vars{'TEXMFSYSVAR'}" =~ m;^$vars{'TEXDIR'};) {
+ if (TeXLive::TLUtils::texdir_check($vars{'TEXDIR'})) {
+ menu_set_text($texmfsysvartext, native_slashify($vars{'TEXMFSYSVAR'}), -foreground => "black");
+ } else {
+ menu_set_text($texmfsysvartext, __("(please change TEXDIR first!)"), -foreground => "red");
+ }
+ } else {
+ menu_set_text($texmfsysvartext, __("(default not writable - please change!)"));
+ }
+ if ((-w $vars{'TEXMFSYSCONFIG'}) || (-w dirname($vars{'TEXMFSYSCONFIG'}))) {
+ menu_set_text($texmfsysconfigtext, native_slashify($vars{'TEXMFSYSCONFIG'}), -foreground => "black");
+ } elsif ("$vars{'TEXMFSYSCONFIG'}" =~ m;^$vars{'TEXDIR'};) {
+ if (TeXLive::TLUtils::texdir_check($vars{'TEXDIR'})) {
+ menu_set_text($texmfsysconfigtext, native_slashify($vars{'TEXMFSYSCONFIG'}), -foreground => "black");
+ } else {
+ menu_set_text($texmfsysconfigtext, __("(please change TEXDIR first!)"), -foreground => "red");
+ }
+ } else {
+ menu_set_text($texmfsysconfigtext, __("(default not writable - please change!)"));
+ }
+ menu_set_text($texmfhometext, native_slashify($vars{'TEXMFHOME'}));
+}
+
+
+sub menu_update_texts {
+ menu_set_pathes_text;
+ menu_set_collections_text;
+ menu_set_binbutton_text;
+ menu_set_schemebutton_text;
+ $optletterstate = $::letterdesc[$vars{'option_letter'}];
+ $optfmtstate = ($vars{'option_fmt'} ? __("Yes") : __("No"));
+ $optsrcstate = ($vars{'option_src'} ? __("Yes") : __("No"));
+ $optdocstate = ($vars{'option_doc'} ? __("Yes") : __("No"));
+}
+
+sub callback_select_scheme {
+ my $s = shift;
+ select_scheme($s);
+ $editoryesno = ($vars{'collection-texworks'} ? __("Yes") : __("No"));
+ menu_update_texts();
+}
+
+sub callback_select_collection {
+ # special case for collection-texworks:
+ $editoryesno = ($vars{'collection-texworks'} ? __("Yes") : __("No"));
+ calc_depends();
+ select_scheme("scheme-custom");
+ update_numbers();
+ menu_update_texts();
+}
+
+sub callback_select_systems() {
+ if ($vars{"binary_win32"}) {
+ $vars{"collection-wintools"} = 1;
+ } else {
+ $vars{"collection-wintools"} = 0;
+ }
+ calc_depends();
+ update_numbers();
+ menu_update_texts();
+}
+
+sub callback_edit_directories {
+ my ($key,$val) = @_;
+ my $home = getenv('HOME');
+ if (win32()) {
+ $home = getenv('USERPROFILE');
+ $home =~ s!\\!/!g;
+ }
+ $home ||= '~';
+ $val =~ s!\\!/!g;
+ $vars{$key} = $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 ($key eq "TEXDIR") {
+ 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'}
+ }
+ menu_update_texts();
+}
+
+sub callback_edit_var() {
+ my ($key,$val) = @_;
+ $vars{$key} = $val;
+ menu_update_texts();
+}
+
+sub dump_vars_stdout {
+ foreach my $k (keys %vars) {
+ print "DEBUG: vars{$k} = $vars{$k}\n";
+ }
+}
+
+sub toggle_portable {
+ my $td = $vars{'TEXDIR'};
+ my $b;
+ if ($vars{'portable'}) {
+ $vars{'portable'} = 0;
+ $portableyesno = __('No');
+ # enable some buttons
+ for $b ($tmflocalbutton, $tmfsysvarbutton, $tmfsysconfigbutton, $tmfhomebutton) {
+ $b->configure(-state => 'normal');
+ }
+ for $b ($pathbutton, $deskintbutton, $assocbutton, $adminbutton) {
+ $b->configure(-state => 'normal') if $b;
+ }
+ } else {
+ $vars{'portable'} = 1;
+ $portableyesno = __('Yes');
+ # disable some buttons. These should get a name first.
+ for $b ($tmflocalbutton, $tmfsysvarbutton, $tmfsysconfigbutton, $tmfhomebutton) {
+ $b->configure(-state => 'disabled');
+ }
+ $vars{'option_path'} = 0;
+ $vars{'option_desktop_integration'} = 0;
+ $vars{'option_file_assocs'} = 0;
+ $vars{'option_w32_multi_user'} = 0;
+ $deskintyesno = __("No");
+ $pathadjyesno = __("No");
+ $fileassocyesno = __("None");
+ $adminallyesno = __("No");
+ for $b ($pathbutton, $deskintbutton, $assocbutton, $adminbutton) {
+ $b->configure(-state => 'disabled') if $b;
+ }
+ }
+ set_texlive_default_dirs(); # this sub tests for portable and in_place
+ menu_set_pathes_text();
+ # same for some options
+}
+
+sub toggle_and_set_opt_variable {
+ my ($varsref, $toggleref, $choicesref) = @_;
+ my ($no, $yes) = $choicesref ? @$choicesref : (__('No'), __('Yes'));
+ $$toggleref = ($$toggleref eq $yes) ? $no : $yes;
+ $$varsref = 0;
+ $$varsref = 1 if ($$toggleref eq $yes);
+ calc_depends();
+ menu_update_texts();
+}
+
+1;
+
+__END__
+
+### Local Variables:
+### perl-indent-level: 2
+### tab-width: 2
+### indent-tabs-mode: nil
+### End:
+# vim:set tabstop=2 expandtab: #
diff --git a/Master/tlpkg/installer/install-menu-text-new.pl b/Master/tlpkg/installer/install-menu-text-new.pl
new file mode 100755
index 00000000000..092226643ab
--- /dev/null
+++ b/Master/tlpkg/installer/install-menu-text-new.pl
@@ -0,0 +1,1070 @@
+#!/usr/bin/env perl
+# $Id: install-menu-text.pl 20268 2010-10-31 07:26:14Z preining $
+# install-menu-txt.pl
+#
+# Copyright 2007, 2008, 2009, 2010 Norbert Preining, Karl Berry
+# Copyright 2007, 2008 Reinhard Kotucha
+# This file is licensed under the GNU General Public License version 2
+# or any later version.
+#
+# This file implements the text based menu system for the TeX Live installer.
+
+use vars qw(@::end_install_hook $::opt_no_cls);
+
+our %vars;
+our $tlpdb;
+our @media_available;
+our $previoustlpdb;
+our @collections_std;
+our @collections_lang;
+our @collections_lang_doc;
+our $texlive_release;
+
+my $MENU_CONTINUE = -1;
+our $MENU_INSTALL = 0;
+our $MENU_ABORT = 1;
+our $MENU_QUIT = 2;
+
+
+my $RETURN = $MENU_CONTINUE;
+
+# issue welcome message on end of installation
+push @::end_install_hook,
+ sub { if (win32()) { print TeXLive::TLUtils::welcome(); }
+ else { print TeXLive::TLUtils::welcome_paths(); } };
+
+sub clear_screen {
+ return 0 if ($::opt_no_cls);
+ system (unix() ? 'clear' : 'cls');
+}
+
+sub string_to_list {
+ my $string=shift;
+ return split(//, $string);
+}
+
+sub button {
+ my $val=shift;
+ return ($val)? '[X]':'[ ]';
+}
+
+sub hbar {
+ return '=' x79, "\n";
+}
+
+sub toggle {
+ my $var=shift;
+ $vars{$var} = ($vars{$var} ? 0 : 1);
+}
+
+sub menu_head {
+ my $text = shift;
+ clear_screen;
+ print hbar(), "$text\n\n";
+}
+
+sub other_options {
+ my @options=@_;
+ my %opts=(
+ '-' => 'deselect all',
+ '+' => 'select all',
+ 'H' => 'help',
+ 'R' => 'return to main menu',
+ 'Q' => 'quit'
+ );
+
+ $opts{'I'}=$vars{'portable'} ? 'start portable installation' : 'start hd installation';
+
+ print "\nActions:";
+ if ($options[$#options] eq 'diskspace') {
+ pop @options;
+ calc_depends ();
+ print " (disk space required: $vars{'total_size'} MB)";
+ }
+ print "\n";
+
+ for my $option (@options) {
+ if (defined $opts{"$option"}) {
+ printf " <%s> %s\n", $option, $opts{$option};
+ } else {
+ die "other_options: $opts{$option} undefined.\n";
+ }
+ }
+}
+
+sub prompt {
+ my $prompt = shift;
+ print "\n$prompt: ";
+ my $answer = <STDIN>;
+ $answer = "q" if !defined($answer);
+ chomp($answer);
+ return "$answer";
+}
+
+# The menu loop. A menu is a function. Its return value is a
+# reference to another menu or to itself.
+sub run_menu_text {
+ my (@args) = @_;
+ # the text mode installer does not take interest in any argument
+ # but the -old-installation-found
+ while (@args) {
+ my $f = shift @args;
+ if ($f =~ m/^-old-installation-found=(.*)$/) {
+ my $dn = $1;
+ print "\nAn old installation of TeX Live has been found in $dn\n";
+ print "
+If you want the selection of collections and various options being taken
+over press `y', otherwise anything else.
+
+Import settings from previous TeX Live installation: (y/n): ";
+ chomp(my $yn = <STDIN>);
+ if ($yn =~ m/^y$/i) {
+ import_settings_from_old_tlpdb($dn);
+ }
+ }
+ }
+ my $menu=\&main_menu;
+ while ($RETURN == $MENU_CONTINUE) {
+ $menu=$menu->();
+ }
+ return($RETURN);
+}
+$::run_menu = \&run_menu_text;
+
+sub binary_menu {
+ my %command=(
+ 'self' => \&binary_menu,
+ 'R' => \&main_menu,
+ 'Q' => \&quit
+ );
+
+ my @binaries;
+ my @keys=string_to_list "abcdefghijklmopstuvwxyz";
+ my $index=0;
+ my %keyval;
+ my $selected_platform;
+
+ menu_head "Available platforms:";
+
+ foreach my $key (keys %vars) {
+ if ($key =~ /binary_(.*)/) {
+ push @binaries, $1;
+ }
+ }
+ @binaries=sort(@binaries);
+
+ foreach my $binary (@binaries) {
+ printf " %s %s %-16s %s\n", $keys[$index],
+ button($vars{"binary_$binary"}),
+ "$binary",
+ platform_desc($binary);
+ $keyval{"$keys[$index]"} = "binary_$binary";
+ ++$index;
+ }
+ other_options qw(- + R Q diskspace);
+
+ my $answer = prompt 'Enter letter(s) to select platforms';
+
+ my @keystrokes=string_to_list $answer;
+
+ foreach my $keystroke (@keystrokes) {
+ if ($keystroke eq '-') {
+ for my $binary (@binaries) {
+ $vars{"binary_$binary"}=0 if defined $vars{"binary_$binary"};
+ }
+ }
+ if ($keystroke eq '+') {
+ for my $binary (@binaries) {
+ $vars{"binary_$binary"}=1 if defined $vars{"binary_$binary"};
+ }
+ }
+ if (defined $keyval{$keystroke}) {
+ toggle "$keyval{$keystroke}";
+ } elsif (!defined $command{"\u$answer"}) {
+ print "Unknown command: $keystroke\n\n";
+ }
+ }
+ if ($vars{"binary_win32"}) {
+ $vars{"collection-wintools"} = 1;
+ } else {
+ $vars{"collection-wintools"} = 0;
+ }
+ if (defined $command{"\u$answer"}) {
+ return $command{"\u$answer"}->();
+ } else {
+ return $command{'self'}->();
+ }
+}
+
+
+sub scheme_menu {
+ my %command=(
+ 'self' => \&scheme_menu,
+ 'R' => \&main_menu,
+ 'Q' => \&quit
+ );
+
+ my @schemes;
+ my @keys=string_to_list "abcdefghijklmnopstuvwxyz";
+ my %keyval;
+ my $index=0;
+
+ menu_head 'Select scheme:';
+
+ foreach my $pkg ($tlpdb->schemes) {
+ push @schemes, $pkg;
+ $vars{"$pkg"}=($vars{'selected_scheme'} eq $pkg)? 1:0;
+ }
+ @schemes=sort @schemes;
+ push @schemes, "scheme-custom";
+
+ foreach my $scheme (@schemes) {
+ $keyval{$keys[$index]}="$scheme";
+ if ($scheme ne "scheme-custom") {
+ my $tlpobj = $tlpdb->get_package("$scheme");
+ printf " %s %s %s\n", $keys[$index], button($vars{"$scheme"}),
+ $tlpobj->shortdesc;
+ } else {
+ printf " %s %s custom selection of collections\n",
+ $keys[$index], button($vars{'selected_scheme'} eq "scheme-custom");
+ }
+ ++$index;
+ }
+
+ select_scheme($vars{'selected_scheme'});
+
+ if ($vars{"binary_win32"}) {
+ $vars{"collection-wintools"} = 1;
+ } else {
+ $vars{"collection-wintools"} = 0;
+ }
+
+ other_options qw(R Q diskspace);
+ my $answer = prompt 'Enter letter to select scheme';
+
+ if (defined $keyval{"$answer"}) {
+ $vars{'selected_scheme'}=$keyval{"$answer"};
+ select_scheme($vars{'selected_scheme'});
+ return $command{'self'}->();
+ }
+ if (defined $command{"\u$answer"}) {
+ return $command{"\u$answer"}->();
+ } else {
+ print "Unknown command: $answer\n\n";
+ return $command{'self'}->();
+ }
+}
+
+
+sub collection_menu {
+ my %command=(
+ 'self' => \&collection_menu,
+ 'R' => \&main_menu,
+ 'Q' => \&quit
+ );
+
+ my @collections;
+ my @keys=string_to_list "abcdefghijklmnopstuvwxyzABCDEFGHIJKLMNOPSTUVWXYZ";
+ my %keyval;
+ my $index=0;
+ my @coll_short_desc;
+ my @coll_long_desc;
+
+ menu_head 'Select collections:';
+
+ @collections=sort @collections_std;
+
+ foreach my $collection (@collections) {
+ next if ($collection eq 'collection-perl');
+ my $tlpobj = $tlpdb->get_package("$collection");
+ if (length $tlpobj->shortdesc>30) {
+ push @coll_long_desc, $collection;
+ } else {
+ push @coll_short_desc, $collection;
+ }
+ }
+ my $singlecolumn_index=@coll_short_desc-1;
+
+##<cols=2>
+ my $lines=@coll_short_desc/2;
+ ++$lines if (@coll_short_desc%2);
+ for (0..$lines-1) {
+ $index=$_;
+ my $collection=$coll_short_desc[$index];
+ my $tlpobj = $tlpdb->get_package("$collection");
+ $keyval{$keys[$index]}="$collection";
+ printf " %s %s %-33s", $keys[$index], button($vars{"$collection"}),
+ substr($tlpobj->shortdesc,0,33);
+ if (defined $coll_short_desc[$index+$lines]) {
+ my $collection=$coll_short_desc[$index+$lines];
+ my $tlpobj=$tlpdb->get_package("$collection");
+ $keyval{$keys[$index+$lines]}="$collection";
+ printf " %s %s %-32s\n", $keys[$index+$lines],
+ button($vars{"$collection"}), substr($tlpobj->shortdesc,0,32);
+ } else {
+ print "\n";
+ }
+ }
+##</cols=2>
+ $index=$singlecolumn_index;
+# print "\n$index\n\n";
+ foreach my $collection (@coll_long_desc) {
+ my $tlpobj=$tlpdb->get_package("$collection");
+ $keyval{$keys[$index+1]}="$collection";
+ printf " %s %s %s\n", $keys[$index+1], button($vars{"$collection"}),
+ $tlpobj->shortdesc;
+ ++$index;
+ }
+##</cols=1>
+
+ other_options qw(- + R Q diskspace);
+ my $answer = prompt 'Enter letter(s) to select collection(s)';
+
+ my @keystrokes=string_to_list $answer;
+
+ foreach my $keystroke (@keystrokes) {
+ if ($keystroke eq '-') {
+ for my $collection (@collections) {
+ $vars{"$collection"}=0 if defined $vars{"$collection"};
+ }
+ }
+ if ($keystroke eq '+') {
+ for my $collection (@collections) {
+ $vars{"$collection"}=1 if defined $vars{"$collection"};
+ }
+ }
+ if (defined $keyval{$keystroke}) {
+ toggle "$keyval{$keystroke}";
+ } elsif (!defined $command{"\u$answer"}) {
+ print "Unknown command: $keystroke\n\n";
+ }
+ }
+
+ if (defined $command{"\u$answer"}) {
+ # if we play around with collections we also select custom-scheme
+ # but we do not switch back to originally afterwards, too complicated
+ # to be done
+ select_scheme("scheme-custom");
+ return $command{"\u$answer"}->();
+ } else {
+ return $command{'self'}->();
+ }
+}
+
+sub language_menu {
+ my %command=(
+ 'self' => \&language_menu,
+ 'R' => \&main_menu,
+ 'Q' => \&quit
+ );
+
+ my @languages;
+ my @lang_docs;
+ my @lang_keys=string_to_list "abcdefghijklmnopstuvwxyz0123456789";
+ my @lang_doc_keys=string_to_list "ABCDEFGHIJKLMNOPSTUVWXYZ";
+ my %keyval;
+ my $lang_index=0;
+ my $lang_doc_index=0;
+ my $lines;
+
+ menu_head 'Language support:';
+
+ @languages=sort @collections_lang;
+ @lang_docs=sort @collections_lang_doc;
+
+ $lines=@languages/2;
+ ++$lines if (@languages%2);
+ for my $index (0..$lines-1) {
+ my $language=$languages[$index];
+ my $tlpobj = $tlpdb->get_package("$language");
+ $keyval{$lang_keys[$index]}="$language";
+ printf " %s %s %-33s", $lang_keys[$index], button($vars{"$language"}),
+ substr($tlpobj->shortdesc,0,33);
+ if (defined $languages[$index+$lines]) {
+ my $language=$languages[$index+$lines];
+ my $tlpobj = $tlpdb->get_package("$language");
+ $keyval{$lang_keys[$index+$lines]}="$language";
+ printf " %s %s %-32s\n", $lang_keys[$index+$lines],
+ button($vars{"$language"}), substr($tlpobj->shortdesc,0,32);
+ } else {
+ print "\n";
+ }
+ }
+
+ print "\nLanguage-specific documentation:\n\n";
+
+ $lines=@lang_docs/2;
+ ++$lines if (@lang_docs%2);
+ for my $index (0..$lines-1) {
+ my $lang_doc=$lang_docs[$index];
+ my $tlpobj = $tlpdb->get_package("$lang_doc");
+ $keyval{$lang_doc_keys[$index]}="$lang_doc";
+ printf " %s %s %-33s", $lang_doc_keys[$index], button($vars{"$lang_doc"}),
+ substr($tlpobj->shortdesc,0,33);
+ if (defined $lang_docs[$index+$lines]) {
+ my $lang_doc=$lang_docs[$index+$lines];
+ my $tlpobj = $tlpdb->get_package("$lang_doc");
+ $keyval{$lang_doc_keys[$index+$lines]}="$lang_doc";
+ printf " %s %s %-32s\n", $lang_doc_keys[$index+$lines],
+ button($vars{"$lang_doc"}), substr($tlpobj->shortdesc,0,32);
+ } else {
+ print "\n";
+ }
+ }
+
+ other_options qw (+ - R Q diskspace);
+ my $answer = prompt 'Enter letter(s) to select language(s)';
+
+ my @keystrokes=string_to_list $answer;
+
+ foreach my $keystroke (@keystrokes) {
+ if ($keystroke eq '-') {
+ for my $collection (@languages,@lang_docs) {
+ $vars{"$collection"}=0 if defined $vars{"$collection"};
+ }
+ }
+ if ($keystroke eq '+') {
+ for my $collection (@languages,@lang_docs) {
+ $vars{"$collection"}=1 if defined $vars{"$collection"};
+ }
+ }
+ if (defined $keyval{$keystroke}) {
+ toggle "$keyval{$keystroke}";
+ } elsif (!defined $command{"\u$answer"}) {
+ print "Unknown command: $keystroke\n\n";
+ }
+ }
+
+ if (defined $keyval{"$answer"}) {
+ return $command{'self'}->();
+ }
+ if (defined $command{"\u$answer"}) {
+ select_scheme("scheme-custom");
+ return $command{"\u$answer"}->();
+ } else {
+ return $command{'self'}->();
+ }
+}
+
+
+sub directories_menu
+{
+ my %command=(
+ 'self' => \&directories_menu,
+ 'R' => \&main_menu,
+ 'Q' => \&quit
+ );
+
+ my $maindir = 'TEXDIR';
+
+ menu_head "Directories setup:";
+ if (!TeXLive::TLUtils::texdir_check($vars{$maindir})) {
+ print "!! The default location as given below can't be written to.
+!! Either change the destination directory using <1> or create it
+!! outside this script.
+";
+ }
+ if (!$vars{'in_place'}) {
+ print <<"EOF";
+ <1> TEXDIR: $vars{'TEXDIR'}
+ support tree: $vars{'TEXDIR'}/texmf
+EOF
+ } else {
+ print <<"EOF";
+ TEXDIR: $vars{'TEXDIR'}
+ support tree: $vars{'TEXDIR'}/texmf
+EOF
+ }
+ if (!$vars{'portable'}) {
+ print <<"EOF";
+
+ <2> TEXMFLOCAL: $vars{'TEXMFLOCAL'}
+ <3> TEXMFSYSVAR: $vars{'TEXMFSYSVAR'}
+ <4> TEXMFSYSCONFIG: $vars{'TEXMFSYSCONFIG'}
+
+ <5> TEXMFVAR: $vars{'TEXMFVAR'}
+ <6> TEXMFCONFIG: $vars{'TEXMFCONFIG'}
+ <7> TEXMFHOME: $vars{'TEXMFHOME'}
+
+EOF
+
+ if (win32) {
+ print " Note: ~ will expand to %USERPROFILE%\n";
+ } else {
+ print " Note: ~ will expand to \$HOME (or to %USERPROFILE% on Windows)\n";
+ }
+ }
+
+ other_options qw(R Q);
+ my $answer = prompt 'Enter command';
+
+ if ("\u$answer" eq '1' and !$vars{'in_place'}) {
+ print "New value for $maindir [$vars{$maindir}]: ";
+ $answer = &input_dirname ();
+ $vars{$maindir} = $answer if $answer ne "";
+ if ($vars{$maindir}=~/^(.*)\/$texlive_release$/) {
+ $vars{'TEXMFLOCAL'}="$1/texmf-local";
+ $vars{'TEXMFSYSVAR'}="$1/$texlive_release/texmf-var";
+ $vars{'TEXMFSYSCONFIG'}="$1/$texlive_release/texmf-config";
+ } elsif ($vars{$maindir}=~/^(.*)$/) {
+ $vars{'TEXMFLOCAL'}="$1/texmf-local";
+ $vars{'TEXMFSYSVAR'}="$1/texmf-var";
+ $vars{'TEXMFSYSCONFIG'}="$1/texmf-config";
+ }
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq '2' and !$vars{'portable'}) {
+ print "New value for TEXMFLOCAL [$vars{'TEXMFLOCAL'}]: ";
+ $answer = &input_dirname ();
+ $vars{'TEXMFLOCAL'} = $answer if $answer ne "";
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq '3' and !$vars{'portable'}) {
+ print "New value for TEXMFSYSVAR [$vars{'TEXMFSYSVAR'}]: ";
+ $answer = &input_dirname ();
+ $vars{'TEXMFSYSVAR'} = $answer if $answer ne "";
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq '4' and !$vars{'portable'}) {
+ print "New value for TEXMFSYSCONFIG [$vars{'TEXMFSYSCONFIG'}]: ";
+ $answer = &input_dirname ();
+ $vars{'TEXMFSYSCONFIG'} = $answer if $answer ne "";
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq '5' and !$vars{'portable'}) {
+ print "New value for TEXMFVAR [$vars{'TEXMFVAR'}]: ";
+ $answer = &input_dirname ("noexpansion");
+ $vars{'TEXMFVAR'} = $answer if $answer ne "";
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq '6' and !$vars{'portable'}) {
+ print "New value for TEXMFCONFIG [$vars{'TEXMFCONFIG'}]: ";
+ $answer = &input_dirname ("noexpansion");
+ $vars{'TEXMFCONFIG'} = $answer if $answer ne "";
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq '7' and !$vars{'portable'}) {
+ print "New value for TEXMFHOME [$vars{'TEXMFHOME'}]: ";
+ $answer = &input_dirname ("noexpansion");
+ $vars{'TEXMFHOME'} = $answer if $answer ne "";
+ return $command{'self'};
+ }
+
+ if (defined $command{"\u$answer"}) {
+ return $command{"\u$answer"}->();
+ } else {
+ print "Unknown command: $answer\n\n";
+ return $command{'self'}->();
+ }
+}
+
+
+# Helper function to read a directory name and clean it up.
+# Unless NO_EXPANSION is true, convert to absolute path.
+#
+sub input_dirname
+{
+ my $noexpansion = shift;
+ chomp (my $answer = <STDIN>);
+ return "" if $answer eq "";
+
+ $answer =~ s!\\!/!g if win32(); # switch to forward slashes
+
+ if (!$noexpansion) {
+ my $home = getenv('HOME');
+ $home = getenv('USERPROFILE') if win32();
+ $home ||= '~';
+ $answer =~ s/^~/$home/; # $home expansion
+ }
+
+ if ($answer !~ m/^~/) {
+ # relative paths are unlikely to work in texmf.cnf, et al.,
+ # and don't have any apparent practical use. Convert to absolute.
+ if (! File::Spec->file_name_is_absolute($answer)) {
+ $answer = Cwd::abs_path($answer);
+ }
+ }
+ return $answer;
+}
+
+
+$vars{'page'}=0;
+
+sub html2text {
+ my $filename=shift;
+ my @text;
+ open IN, "$filename";
+ @all_lines=<IN>;
+ close IN;
+ chomp @all_lines;
+
+ my $itemcnt;
+ my $ordered_list=0;
+ my $h1_indent=25;
+ my $h2_indent=3;
+ my $h3_indent=6;
+
+ for (@all_lines) {
+ next if /DOCTYPE/;
+ next if /<!--/;
+ next if /<title/i;
+ next if /<\/?body/i;
+ next if /<\/?html/i;
+ next if /<\/?head/i;
+ next if /<\/?meta/i;
+ next if /^\s*$/; # ignore empty lines
+
+ s/<i>/"/gi; s/<\/i>/"/gi; # italics
+ s/<tt>/'/gi; s/<\/tt>/'/gi; # typewriter
+ s/<p>.*//gi; # paragraphs
+ s/<\/ul>.*//gi; # unsorted lists
+ s/<\/ol>.*//gi; # ordered lists
+ s/&mdash;/--/gi; # mdash
+ s/&lt;/</gi; s/&gt;/>/gi; # < and >
+ if (/<h1>(.*?)<\/h1>/i) {
+ push @text, " " x $h1_indent. "$1\n";
+ push @text, " " x $h1_indent. "=" x (length $1). "\n";
+ push @text, "\n";
+ } elsif (/<h2>(.*?)<\/h2>/i) {
+ push @text, "\n";
+ push @text, " " x $h2_indent. "$1\n";
+ push @text, " " x $h2_indent. "~" x (length $1). "\n";
+ push @text, "\n";
+ } elsif (/<h3>(.*?)<\/h3>/i) {
+ push @text, "\n";
+ push @text, " " x $h3_indent. "$1\n";
+ push @text, " " x $h3_indent. "-" x (length $1). "\n";
+ push @text, "\n";
+ } elsif (/<ol>/i) {
+ $ordered_list=1;
+ $itemcnt=1;
+ } elsif (/<ul>/i) {
+ $ordered_list=0;
+ } elsif (/^\s*<li>\s*(.*)/) {
+ if ($ordered_list) {
+ push @text, "\n";
+ push @text, " $itemcnt. $1\n";
+ ++$itemcnt;
+ } else {
+ push @text, "\n";
+ push @text, " * $1\n";
+ }
+ } else {
+ push @text, "$_\n";
+ }
+ }
+ return @text;
+}
+
+
+sub help_menu {
+ my %command=(
+ 'self' => \&help_menu,
+ 'R' => \&main_menu,
+ 'Q' => \&quit
+ );
+ my $installer_help="$installerdir/tlpkg/installer/install-tl.html";
+
+ clear_screen;
+
+ my @text=html2text "$installer_help";
+ my $lines=(@text);
+ my $overlap=3;
+ my $lps=32; # lines per screen - overlap
+ my $firstline=$vars{'page'}*$lps;
+ my $lastline=$firstline+$lps+$overlap;
+ my $line=0;
+# print "<<<$firstline>>> <<<$lastline>>>\n";
+ for (@text) {
+ print "$_" if ($line>=$firstline and $line<=$lastline);
+ ++$line;
+ }
+ print "\n", hbar,
+ " <T> top <N> next page <P> previous page <R> return"
+ . " <Q> quit --", $vars{'page'}+1, "--\n";
+
+ my $answer = prompt 'Enter command';
+
+ if ("\u$answer" eq 'T') {
+ $vars{'page'}=0;
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq 'N') {
+ $vars{'page'}+=1 unless $lastline>$lines;
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq 'P') {
+ $vars{'page'}-=1 if $vars{'page'}>=1;
+ return $command{'self'};
+
+ } elsif (defined $command{"\u$answer"}) {
+ return $command{"\u$answer"};
+
+ } else {
+ print "Unknown command: $answer\n\n";
+ return $command{'self'};
+ }
+}
+
+
+sub options_menu {
+ my $b_path=button($vars{'option_path'});
+ my $b_doc=button($vars{'option_doc'});
+ my $b_src=button($vars{'option_src'});
+ my $b_fmt=button($vars{'option_fmt'});
+ my $b_letter=button($vars{'option_letter'});
+ my $b_deskint=button($vars{'option_desktop_integration'});
+ my $b_admin=button($vars{'option_w32_multi_user'});
+ my $b_addoneditor=button($vars{'collection-texworks'});
+ my $b_restricted=button($vars{'option_write18_restricted'});
+
+ my $sys_bin=$vars{'option_sys_bin'};
+ my $sys_man=$vars{'option_sys_man'};
+ my $sys_info=$vars{'option_sys_info'};
+
+ my $t_sys_bin=($vars{'option_path'})? $vars{'option_sys_bin'}:'';
+ my $t_sys_man=($vars{'option_path'})? $vars{'option_sys_man'}:'';
+ my $t_sys_info=($vars{'option_path'})? $vars{'option_sys_info'}:'';
+
+ my %command=(
+ 'self' => \&options_menu,
+ 'R' => \&main_menu,
+ 'Q' => \&quit
+ );
+
+ clear_screen;
+ menu_head "Options setup:";
+
+ print <<"EOF";
+ <P> use letter size instead of A4 by default: $b_letter
+ <E> execution of restricted list of programs: $b_restricted
+ <F> create format files: $b_fmt
+EOF
+;
+ if ($vars{'doc_splitting_supported'} and !$vars{'in_place'}) {
+ print " <D> install font/macro doc tree: $b_doc\n";
+ }
+ if ($vars{'src_splitting_supported'} and !$vars{'in_place'}) {
+ print " <S> install font/macro source tree: $b_src\n";
+ }
+ if (!$vars{'portable'}) {
+ if (unix() || $::opt_all_options) {
+ print <<"EOF";
+ <L> create symlinks in standard directories: $b_path
+ binaries to: $t_sys_bin
+ manpages to: $t_sys_man
+ info to: $t_sys_info
+EOF
+;
+ } else {
+ print <<"EOF";
+ <L> adjust registry entry for path: $b_path
+EOF
+;
+ }
+ if (win32() || $::opt_all_options) {
+ print " <M> install menu items, shortcuts, etc: $b_deskint\n";
+ print " <N> update file associations: [$::fileassocdesc[$vars{'option_file_assocs'}]]\n";
+ if ($::opt_all_options || TeXLive::TLWinGoo::admin()) {
+ # if we are admin we allow normal user installation, too
+ print " <U> make installation available to all users: $b_admin\n";
+ }
+ }
+ }
+ if (win32() || $::opt_all_options) {
+ print " <W> install TeXworks front end: $b_addoneditor\n";
+ }
+ other_options qw(R Q diskspace);
+ my $answer = prompt 'Enter command';
+
+ # option_path
+
+ if (unix()) {
+ if (("\u$answer" eq 'L') and !$vars{'portable'}) {
+ my $home = getenv('HOME');
+ $home = getenv('USERPROFILE') if (win32());
+ $home ||= '~';
+ toggle 'option_path';
+ if ($vars{'option_path'}) {
+ print "New value for binary directory [$sys_bin]: ";
+ chomp($answer=<STDIN>);
+ $vars{'option_sys_bin'} = "$answer" if (length $answer);
+ $vars{'option_sys_bin'} =~ s@\\@/@g if (win32());
+ $vars{'option_sys_bin'} =~ s/^~/$home/;
+ if ($vars{'option_sys_bin'}=~/^(.*)\/bin$/) {
+ $vars{'option_sys_man'}="$1/man";
+ $vars{'option_sys_info'}="$1/info";
+ }
+ print "New value for man directory [$vars{'option_sys_man'}]: ";
+ chomp($answer=<STDIN>);
+ $vars{'option_sys_man'}="$answer" if (length $answer);
+ $vars{'option_sys_man'} =~ s@\\@/@g if (win32());
+ $vars{'option_sys_man'} =~ s/^~/$home/;
+
+ print "New value for info directory [$vars{'option_sys_info'}]: ";
+ chomp($answer=<STDIN>);
+ $vars{'option_sys_info'}="$answer" if (length $answer);
+ $vars{'option_sys_info'} =~ s@\\@/@g if (win32());
+ $vars{'option_sys_info'} =~ s/^~/$home/;
+ }
+ return $command{'self'};
+ }
+ } else {
+ if (("\u$answer" eq 'L') and !$vars{'portable'}) {
+ my $home = getenv('HOME');
+ $home = getenv('USERPROFILE') if (win32());
+ $home ||= '~';
+ toggle 'option_path';
+ return $command{'self'};
+ }
+ }
+
+ # option_desktop_integration, option_file_assocs
+
+ if (win32() || $::opt_all_options) {
+ if ("\u$answer" eq 'M' and !$vars{'portable'}) {
+ toggle 'option_desktop_integration';
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq 'N' and !$vars{'portable'}) {
+ print "New value for file_assocs:\n";
+ print " 0 -- don't tweak the file associations\n";
+ print " 1 -- only add new file associations, don't overwrite old ones\n";
+ print " 2 -- always create file associations to TeX Live programs\n";
+ print "New value for file_assocs [$vars{'option_file_assocs'}]: ";
+ chomp (my $a = <STDIN>);
+ if ($a eq "0" || $a eq "1" || $a eq "2") {
+ $vars{'option_file_assocs'} = $a;
+ }
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq 'U' and !$vars{'portable'}) {
+ toggle 'option_w32_multi_user';
+ return $command{'self'};
+ }
+ }
+
+ # other options
+
+ if ("\u$answer" eq 'P') {
+ toggle 'option_letter';
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq 'F') {
+ toggle 'option_fmt';
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq 'E') {
+ toggle 'option_write18_restricted';
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq 'S' and !$vars{'in_place'}) {
+ toggle 'option_src';
+ return $command{'self'};
+
+ } elsif ("\u$answer" eq 'D' and !$vars{'in_place'}) {
+ toggle 'option_doc';
+ return $command{'self'};
+
+ } elsif (defined $command{"\u$answer"}) {
+ return $command{"\u$answer"};
+
+ } elsif (("\u$answer" eq 'W') && ($::opt_all_options || win32()) &&
+ !$vars{'in_place'} ) {
+ toggle 'collection-texworks';
+ return $command{'self'};
+
+ } else {
+ print "Unknown or unsupported command: $answer\n\n";
+ return $command{'self'};
+ }
+}
+
+
+sub quit {
+ exit 0;
+ $RETURN = $MENU_QUIT;
+}
+
+sub do_install {
+ $RETURN = $MENU_INSTALL;
+}
+
+sub toggle_portable {
+ if ($vars{'portable'}) {
+ $vars{'portable'} = 0;
+ $vars{'option_desktop_integration'} = 0;
+ $vars{'option_path'} = 0;
+ $vars{'option_file_assocs'} = 0;
+ $vars{'option_w32_multi_user'} = 0;
+ } else {
+ $vars{'portable'} = 1;
+ $vars{'option_desktop_integration'} = 1;
+ $vars{'option_path'} = 1;
+ $vars{'option_file_assocs'} = 1;
+ $vars{'option_w32_multi_user'} = 1;
+ }
+ set_texlive_default_dirs(); # this sub tests for portable and in_place
+ main_menu;
+}
+
+sub main_menu {
+ my $this_platform=platform_desc($vars{'this_platform'});
+
+ my $b_path=button($vars{'option_path'});
+ my $b_doc=button($vars{'option_doc'});
+ my $b_src=button($vars{'option_src'});
+ my $b_fmt=button($vars{'option_fmt'});
+ my $b_letter=button($vars{'option_letter'});
+ my $b_deskint=button($vars{'option_desktop_integration'});
+ my $b_admin=button($vars{'option_w32_multi_user'});
+ my $b_addoneditor=button($vars{'collection-texworks'});
+ my $b_restricted=button($vars{'option_write18_restricted'});
+
+ my $warn_nobin;
+
+ $warn_nobin=set_install_platform;
+
+ my $maindir = 'TEXDIR';
+
+ $vars{'n_systems_selected'}=0;
+ $vars{'n_collections_selected'}=0;
+ foreach my $key (keys %vars) {
+ if ($key=~/^binary.*/) {
+ ++$vars{'n_systems_selected'} if $vars{$key}==1;
+ }
+ if ($key=~/^collection/) {
+ ++$vars{'n_collections_selected'} if $vars{$key}==1;
+ }
+ }
+ calc_depends();
+
+ my %command = (
+ 'self' => \&main_menu,
+ 'D' => \&directories_menu,
+ 'H' => \&help_menu,
+ 'I' => \&do_install,
+ 'O' => \&options_menu,
+ 'Q' => \&quit,
+ 'V' => \&toggle_portable,
+ );
+ if (!$vars{'in_place'}) {
+ $command{'B'} = \&binary_menu if unix();
+ $command{'C'} = \&collection_menu;
+ $command{'L'} = \&language_menu;
+ $command{'S'} = \&scheme_menu;
+ }
+
+ clear_screen;
+ print <<"EOF";
+======================> TeX Live installation procedure <=====================
+
+=======> Note: Letters/digits in <angle brackets> indicate menu items <=======
+=======> for commands or configurable options <=======
+
+ Detected platform: $this_platform
+ $warn_nobin
+EOF
+
+ if (!$vars{'in_place'}) {
+ print <<"EOF";
+ <B> platforms: $vars{'n_systems_selected'} out of $vars{'n_systems_available'}
+
+ <S> installation scheme ($vars{'selected_scheme'})
+ $vars{'n_collections_selected'} collections out of $vars{'n_collections_available'}, disk space required: $vars{'total_size'} MB
+
+ Customizing installation scheme:
+ <C> standard collections
+ <L> language collections
+EOF
+
+ if (!check_on_lang_collection_installed()) {
+ print " !! No language specific collection selected!\n";
+ print " !! If you only write American English documents that is fine!\n";
+ }
+ }
+ print <<"EOF";
+
+ <D> directories:
+ TEXDIR (the main TeX directory):
+EOF
+
+ if (TeXLive::TLUtils::texdir_check($vars{$maindir})) {
+ print " $vars{$maindir}\n";
+ } else {
+ print " !! default location: $vars{$maindir}\n";
+ print " !! is not writable, please select a different one!\n";
+ }
+ print <<"EOF";
+ TEXMFLOCAL (directory for site-wide local files):
+ $vars{'TEXMFLOCAL'}
+ TEXMFSYSVAR (directory for variable and automatically generated data):
+ $vars{'TEXMFSYSVAR'}
+ TEXMFSYSCONFIG (directory for local config):
+ $vars{'TEXMFSYSCONFIG'}
+ TEXMFVAR (personal directory for variable and automatically generated data):
+ $vars{'TEXMFVAR'}
+ TEXMFCONFIG (personal directory for local config):
+ $vars{'TEXMFCONFIG'}
+ TEXMFHOME (directory for user-specific files):
+ $vars{'TEXMFHOME'}
+
+EOF
+
+print <<"EOF";
+ <O> options:
+ $b_letter use letter size instead of A4 by default
+ $b_restricted allow execution of restricted list of programs via \\write18
+ $b_fmt create all format files
+EOF
+
+ if (!$vars{'in_place'}) {
+ if ($vars{'doc_splitting_supported'}) {
+ print " $b_doc install macro/font doc tree\n";
+ }
+ if ($vars{'src_splitting_supported'}) {
+ print " $b_src install macro/font source tree\n";
+ }
+ }
+ if (win32()) {
+ if (!$vars{'portable'}) {
+ print " $b_path adjust search path\n";
+ print " $b_deskint add menu items, shortcuts, etc.\n";
+ print " [$vars{'option_file_assocs'}] update file associations\n";
+ if (admin()) {
+ print " $b_admin make installation available to all users\n";
+ }
+ }
+ print " $b_addoneditor install TeXworks front end\n";
+ print " $b_path create symlinks to standard directories\n" unless
+ ($vars{'portable'} || win32());
+ }
+
+ if ($vars{'portable'}) {
+ print "\n <V> set up for regular hd installation\n";
+ } else {
+ print "\n <V> set up for portable installation\n";
+ }
+
+ other_options qw(I H Q);
+ my $answer = prompt 'Enter command';
+
+ if (defined $command{"\u$answer"}) {
+ return $command{"\u$answer"};
+ } else {
+ print "Unknown command: $answer\n\n";
+ return $command{'self'};
+ }
+}
+
+# needs a terminal 1 for require to succeed!
+1;
+
+__END__
+
+### Local Variables:
+### perl-indent-level: 2
+### tab-width: 2
+### indent-tabs-mode: nil
+### End:
+# vim:set tabstop=2 expandtab: #