#!/usr/bin/perl 
#
# Copyright (C) 2001-2002 by MandrakeSoft
#                            DUPONT Sebastien
#                            Damien Chaumette <dchaumette@mandrakesoft.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# drakfont Future Overview
#         - Fonts import:
#                 pfb ( Adobe Type 1 binary )
#                 pfa ( Adobe Type 1 ASCII )
#                 ttf ( True-Type  )
#                 pcf.gz
#                 Speedo
#                 and Bitmap (PCF, BDF, and SNF)
#         - Features
#                 - Install fonts from any directory
#                 - Get windows fonts on any vfat partitions
#                 - Get fonts on any partitions.
#                 - UN-installation of any fonts (even if not installed through drakfont)
#         - Support
#               - Xfs
#               - ghostscript & printer
#               - Staroffice & printer
#               - abiword
#		- netscape
#               - Koffice, Gnumeric, ... studying
#               - all fonts supported by printer
#               - anti-aliases by RENDER in Xfree86 .... 
# 				supported by KDE.
# 				will be supported by gnome 1.2.
# Visual Interface:
#         Window interface:
#           - Fontselectiondialog widget
#           - Command buttons under Fontselectiondialog (like the actual frontend).
#         Commands buttons:
#           - import from windows partition.
#                 import from all fat32 partitions and look for winnt/windows/font
#                 and import all (delete doubles) but don't import if they already exist.
#           - import from directory
#                 look to see if each font exists and do not delete the original.
#                 (replace all, no, none)
#                 expert options:
#                         specify the directory, and look to see if it exists before
#                         if it exists ask: (replace all, no, none)
#           - uninstall with list per font type
#         Expert additional switch
#           - option support:   ghostscript, Staroffice, etc...
#                 check-button. (by default all check)
#           - Printer Application Fonts Support...
#                 check-button. (by default all check)
#
# TODO:
#     - abiword, Koffice, Gnumeric, ...  
#     - Speedo  and Bitmap (PCF, BDF, and SNF)
#     - option strong: strong verification with ttmkfdir -c ?
#                
# REQUIRE:
#     - font-tools.*.mdk.i586.rpm
#
# USING:
#    -  pfm2afm:   by Ken Borgendale: Convert a Windows .pfm  file to a .afm (Adobe Font Metrics)
#    -  type1inst: by James Macnicol: type1inst generates files fonts.dir fonts.scale & Fontmap.
#    -  ttf2pt1:   by Andrew Weeks, Frank Siegert, Thomas Henlich, Sergey Babkin  convert ttf font files to afm and pfb fonts
#
#
# directory to install fonts /usr/X11R6/lib/X11/fonts/
# -->> /usr/X11R6/lib/X11/fonts/drakfont

use strict;
use diagnostics;

use lib qw(/usr/lib/libDrakX);

use standalone;    #- warning, standalone must be loaded very first, for 'explanations'

use ugtk2 qw(:helpers :wrappers :create);
use common;

require_root_capability();

#   global variables needed by each functions
my $xlsfonts = 0;
my $windows  = 0;
my $strong;
my $replace;
my $so      = 1;
my $gs      = 1;
my $abi     = 1;
my $printer = 1;
my $mode    = -1;
my @application;
my @install;
my @uninstall;
my $interactive;
my $pbar;
my $pbar1;
my $pbar2;
my $pbar3;
my $font_box;
my $central_widget;
my $model;
my $list;
my $list_all_font_path;
my $left_list;
my $right_list;
my $left_model;
my $right_model;

foreach (@ARGV) {
    /--list|-l/            and $list_all_font_path = 1, $mode = -1;
    /--xls_fonts/          and $xlsfonts           = 1, $mode = -1;
    /--windows_import|-wi/ and $windows            = 1, $mode = -1;
    /--strong|-s/          and $strong             = 1, $mode = -1;
    /--replace|-r/         and $replace            = 1, $mode = -1;
    /--application/        and $mode               = 0, next;
    $mode == 0 and push @application, $_;
    /--install/ and $mode = 1, next;
    $mode == 1 and push @install, $_;
    /--uninstall/ and $mode = 2, next;
    $mode == 2 and push @uninstall, $_;
}

foreach my $i (@application) {
    if ($i =~ /so/i) {
        if ($gs != 2) { $gs = 0 }
        $so = 2;
    }
    if ($i =~ /gs/i) {
        if ($so != 2) { $so = 0 }
        $gs = 2;
    }
}

# PATH and binary full path
#my $xfs_conffile = '/etc/fonts/fonts.conf';
my $drakfont_dir = '/usr/X11R6/lib/X11/fonts/drakfont';
my $ttf2pt1      = '/usr/sbin/ttf2pt1';
my $pfm2afm      = '/usr/sbin/pfm2afm';
my $type1inst    = '/usr/sbin/type1inst';
my $chkfontpath  = '/usr/sbin/chkfontpath';
# mkttfdir only knows about iso-8859-1, using ttmkfdir -u instead -- pablo
my $ttmkfdir     = '/usr/sbin/ttmkfdir';
my $fccache      = '/usr/bin/fc-cache';

my @font_list;                 # list of fonts to install
my @installed_fonts;           # list of installed fonts
my @installed_fonts_path;      # list of path included in xfs
my @installed_fonts_full_path; # full path list of fonts to uninstall

sub list_fontpath() {
    foreach (grep { /\d+:\s/ } `$chkfontpath -l`) {
        chomp;
        s/\d+:\s//gi;
        s/:\w*$//gi;
        push @installed_fonts_path, $_;
    }
}

sub chk_empty_xfs_path() {
    foreach my $tmp_path (@installed_fonts_path) {
        if (every { /^fonts/ || /^type/ } all($tmp_path)) {
            system("$chkfontpath -r $tmp_path ")
              or print "PERL::system command failed during chkfontpath\n";
        }
    }
}

sub search_installed_fonts() {
    list_fontpath();
    interactive_progress($pbar, 0.1, N("Search installed fonts"));
    push @installed_fonts, all($_) foreach @installed_fonts_path;
    interactive_progress($pbar, 0.1, N("Unselect fonts installed"));
}

sub search_installed_fonts_full_path() {
    list_fontpath();
    foreach my $i (@installed_fonts_path) {
        foreach my $j (all($i)) {
            push @installed_fonts_full_path, "$i/$j";
        }
    }
}

sub search_windows_font() {
    foreach my $fstab_line (grep { /vfat|smbfs|ntfs/ } cat_('/etc/mtab')) {
        my $win_dir = (split('\s', $fstab_line))[1];
        my @list_fonts_win   = all("$win_dir/windows/fonts");
        my @list_fonts_winnt = all("$win_dir/winnt/fonts");
        my $nb_dir           = @list_fonts_win + @list_fonts_winnt;
        foreach ([ \@list_fonts_win, "windows" ],
                 [ \@list_fonts_winnt, "winnt" ]) {
            foreach my $i (@{ $_->[0] }) {
                if ($interactive) {
                    if ($nb_dir) {
                        progress($pbar, 0.25 / $nb_dir, N("parse all fonts"));
                    } else {
                        display_error(N("no fonts found"));
                        return 0;
                    }
                }
                !$replace && any { /$i/ } @installed_fonts and next;
                any { /$i$/ } @font_list or push @font_list, "$win_dir/$_->[1]/fonts/$i";
            }
        }
        $interactive && $nb_dir and progress($pbar, 1, N("done"));
    }
    if (!@font_list) {
        print "drakfont:: could not find any font in /win*/fonts \n";
        $interactive
          and display_error(
            N("could not find any font in your mounted partitions"));
        return 0;
    }
    1;
}

sub is_a_font($) {
    my ($file) = @_;
    any { $file =~ /\Q.$_\E$/i } qw(ttf pfa pfb pcf pcf.gz pfm gsf); 
}

# Optimisation de cette etape indispensable
sub search_dir_font() {
    foreach my $fn (@install) {
        my @font_list_tmp;
        my $dir;
        if (!(-e $fn)) { print "$fn :: no such file or directory \n" }
        else {
            if (-d $fn) {
                $dir = $fn;
                foreach my $i (all($fn)) {
                    if (is_a_font($i)) {
                        push @font_list_tmp, $i;
                        foreach my $i (@font_list_tmp) {
                            !$replace && any { /$i/ } @installed_fonts and next;
                            any { /$i/ } @font_list or push @font_list, "$fn/$i";
                        }
                    }
                }
            }
            elsif (is_a_font($fn)) {
		!$replace && any { /$fn/ } @installed_fonts and next;
		!any { /$fn/ } @installed_fonts and push @font_list, $fn;
	    }
        }
        interactive_progress($pbar, 0.50 / @install, N("Reselect correct fonts"));
    }
    interactive_progress($pbar, 1, N("done"));
    !@font_list && $interactive and display_error(N("could not find any font.\n"));
}

sub search_dir_font_uninstall {
    my ($fn)  = @_;
    print "Fonts to uninstal: " . $_ . "\n" foreach uniq(@font_list, -d $fn ? (grep { is_a_font($_) } all($fn)) : if_(is_a_font($fn), $fn));
}

sub search_dir_font_uninstall_gi() {
    @font_list = @uninstall;
    interactive_progress($pbar, 1, N("Search for fonts in installed list"));
}

sub print_list() {
    print "Font(s) to Install:\n\n";
    print "$_\n" foreach @font_list;
}

sub dir_created() {
    -e $drakfont_dir or mkdir_p($drakfont_dir);
    -e $drakfont_dir . "/Type1"     or mkdir_p($drakfont_dir . "/Type1");
    -e $drakfont_dir . "/ttf"       or mkdir_p($drakfont_dir . "/ttf");
    -e $drakfont_dir . "/tmp"       or mkdir_p($drakfont_dir . "/tmp");
    -e $drakfont_dir . "/tmp/ttf"   or mkdir_p($drakfont_dir . "/tmp/ttf");
    -e $drakfont_dir . "/tmp/Type1" or mkdir_p($drakfont_dir . "/tmp/Type1");
    -e $drakfont_dir . "/tmp/tmp"   or mkdir_p($drakfont_dir . "/tmp/tmp");
}


sub convert_fonts {
    my ($fonts, $converter, $font_type, $o_generate_pfb) = @_;
    $o_generate_pfb = $o_generate_pfb ? "-b" : "";
    foreach my $fontname (@$fonts) {
        system("cd $drakfont_dir/tmp/tmp && $converter $o_generate_pfb $fontname");
        interactive_progress($pbar2, 0.50 / @$fonts, N("%s fonts conversion", $font_type));
    }
}

sub convert_ttf_fonts {
    my ($fonts, $o_generate_pfb) = @_;
    convert_fonts($fonts, $ttf2pt1, "TTF", $o_generate_pfb);
}


sub move_fonts {
    my ($src_dir, $dest_dir, @extensions) = @_;
    my @fonts = map { s!.*/!!; $_ } map { glob("$src_dir/*.$_") } @extensions;
    system("cd $src_dir && mv @fonts $dest_dir") if @fonts;
}

sub put_font_dir_real {
    my ($subdir, $command, $progress, $title) = @_;
    system("cd $drakfont_dir/$subdir && $fccache && $command");
    interactive_progress($pbar2, $progress, $title);
    return "$chkfontpath -a $drakfont_dir/$subdir";
}

sub put_font_dir() {
    -e "/usr/share/ghostscript" or do { $gs = 0; print "ghostscript is not installed on your system...\n" };
    if (@font_list) {
        dir_created();
        foreach my $i (@font_list) {
            cp_af($i, $drakfont_dir . "/tmp/tmp");
            interactive_progress($pbar1, 1 / @font_list, N("Fonts copy"));
        }
        interactive_progress($pbar1, 0.01, N("done"));
        interactive_progress($pbar2, 0.10, N("True Type fonts installation"));
        foreach my $font (glob("$drakfont_dir/tmp/tmp/*.TTF")) {
            my $newfont = $font;
            $newfont =~ s/\.TTF$/.ttf/;
            rename($font, $newfont);
        }
        system('cd ' . $drakfont_dir . '/tmp/tmp  && cp *.ttf ../../ttf; chmod 644 ../../ttf/*ttf');
        interactive_progress($pbar2, 0.20, N("please wait during ttmkfdir..."));
        my $update_chkfontpath = put_font_dir_real("ttf", "$ttmkfdir -u > fonts.dir", 0.10, N("True Type install done"));

        if ($gs) {
            convert_ttf_fonts([ glob("$drakfont_dir/tmp/tmp/*.ttf") ], 1);
            move_fonts("$drakfont_dir/tmp/tmp", "../Type1", qw(afm gsf pfb pfm));
            system("cd $drakfont_dir/tmp/Type1 && $type1inst");
            interactive_progress($pbar2, 0.1, N("type1inst building"));
            if ($so) {
                -e "$drakfont_dir/tmp/Type1/Fontmap" 
                  and system("cd $drakfont_dir/tmp/Type1 && cat Fontmap >> `rpm -ql ghostscript | grep Fontmap.GS` ");
                move_fonts("$drakfont_dir/tmp/Type1", "../../Type1", qw(afm gsf pfb pfm));
            } else {
                system("cd $drakfont_dir/tmp/Type1 && cat Fontmap >> `rpm -ql ghostscript | grep Fontmap.GS` ");
                move_fonts("$drakfont_dir/tmp/Type1", "../../Type1", qw(afm gsf pfb pfm));
            }
            $update_chkfontpath .= "; " . put_font_dir_real("Type1", $type1inst, 0.05, N("Ghostscript referencing"));
        } elsif ($so) {
            convert_ttf_fonts([ glob("$drakfont_dir/tmp/tmp/*.ttf") ]);
            convert_fonts([ glob("$drakfont_dir/tmp/tmp/*.pfm") ], $pfm2afm, "PFM");
            move_fonts("$drakfont_dir/tmp/tmp", "../Type1", qw(afm));
            move_fonts("$drakfont_dir/tmp/Type1", "../../Type1", qw(afm));
            $update_chkfontpath .= put_font_dir_real("Type1", $type1inst, 0.14, N("type1inst building"));
        }

        interactive_progress($pbar2, 1, N("done"));
        interactive_progress($pbar3, 0.25, N("Suppress Temporary Files"));
        rm_rf("$drakfont_dir/tmp/");
        print "\n\nretarting xfs......\n";
        interactive_progress($pbar3, 0.5, N("Restart XFS"));
        system($update_chkfontpath);
        system('/etc/rc.d/init.d/xfs restart');
        system('xset fp rehash');
        interactive_progress($pbar3, 0.30, N("done"));
    }
}

sub remove_gs_fonts() {
    my @Fontmap_new;

    if (all("$drakfont_dir/remove")) {
        system(" cd $drakfont_dir/remove && $type1inst");
        my @Fontmap_out = cat_("$drakfont_dir/remove/Fontmap");
        my $FontmapGS   = `rpm -ql ghostscript | grep Fontmap.GS`;
        chomp($FontmapGS);
        my @FontmapGS_list = cat_($FontmapGS);
        foreach my $font_gs (@FontmapGS_list) {
            my @tmp_list = split(' ', $font_gs);
            any { /$tmp_list[0]/ } @Fontmap_out or push @Fontmap_new, $font_gs;
        }
        print $_ foreach @Fontmap_new;
        output($FontmapGS, @Fontmap_new);
    }

}

sub remove_fonts() {
    my @list_dir;
    -e $drakfont_dir . "/remove" or mkdir_p($drakfont_dir . "/remove");
    interactive_progress($pbar, 1, N("done"));
    
    foreach my $i (@font_list) {
        local $_ = $i;
        if (/.pfb$/ || /.gsf$/ || /.pfm$/ || /.pfa$/) {
            system("mv $_ $drakfont_dir/remove ");
        } else {
	    if (/.ttf$/) {
		rm_rf($_);
		# rebuild of the fonts.dir and fc-cache files
       		system("cd `dirname $_` && $fccache && $ttmkfdir -u > fonts.dir");
	    } else { rm_rf($i) }
        }
        $i =~ s!/\w*\.\w*!!gi;
        any { $i } @list_dir or push @list_dir, $i;
        interactive_progress($pbar1, 1 / @font_list, N("Suppress Fonts Files"));
    }
    interactive_progress($pbar1, 0.01, N("done"));
    -e "/usr/share/ghostscript" and remove_gs_fonts();
    foreach my $i (@list_dir) {
        if (listlength all($i) < 3) {
            system("chkfontpath -r $i") or print "PERL::system command failed during chkfontpath\n";
        } else {
            system("cd $i && type1inst") or print "PERL::system command failed during cd or type1inst\n";
        }
        interactive_progress($pbar2, 1 / @list_dir, N("Suppress Fonts Files"));
    }
    interactive_progress($pbar2, 0.01, N("xfs restart"));
    system("/etc/rc.d/init.d/xfs restart");
    system('xset fp rehash');
    -e "/usr/share/ghostscript" and rm_rf("$drakfont_dir/remove");
    interactive_progress($pbar2, 0.01, N("done"));
}

sub license_msg() {
    print N("Before installing any fonts, be sure that you have the right to use and install them on your system.\n\n-You can install the fonts the normal way. In rare cases, bogus fonts may hang up your X Server.") . "\n";
}

sub backend_mod() {
    $xlsfonts and system("xlsfonts");
    $list_all_font_path and system($chkfontpath);

    if ($windows) {
        license_msg();
        print "\nWindows fonts Installation........\n";
        search_installed_fonts();
        if (search_windows_font()) {
            print_list();
            put_font_dir();
        }
        print "\nThe End...........................\n";
    }

    if (@install) {
        license_msg();
        print "\nInstall Specifics Fonts...........\n";
        search_installed_fonts();
        search_dir_font();
        print "Font to install: " . $_ . "\n" foreach @font_list;
        put_font_dir();
        print "\nThe End...........................\n";
    }

    if (@uninstall) {
        print "\nUninstall Specifics Fonts.........\n";
        search_installed_fonts_full_path();
        if ($interactive) { search_dir_font_uninstall_gi() }
        else { search_dir_font_uninstall() foreach @uninstall }
        remove_fonts();
        print "\nThe End............................\n";
    }
}

sub create_fontsel() {
    my $font_sel;
    gtkpack($font_box, $font_sel = Gtk2::FontSelection->new,);
    $central_widget = \$font_sel;
}

sub display_error {
    my ($message) = @_;
    my $error_box;
    $$central_widget->destroy;
    gtkpack($font_box,
            $error_box = gtkpack_(Gtk2::VBox->new(0, 0), 
                                  1, Gtk2::Label->new($message), 
                                  0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'spread'),
                                            gtksignal_connect(Gtk2::Button->new(N("OK")),
                                                              clicked => sub { $$central_widget->destroy; create_fontsel() }
                                                             ),
                                           ),
                                 )
           );
    $central_widget = \$error_box;
}

sub interactive_mode() {
    my $font_sel;
    $interactive = 1;
    my $window1 = ugtk2->new('drakfont');
    $window1->{rwindow}->signal_connect(delete_event => sub { ugtk2->exit(0) });
    unless ($::isEmbedded) {
        $window1->{rwindow}->set_position('center');
        $window1->{rwindow}->set_title(N("Import Fonts"));
    }
    
    my $button = {};
    my $disable = sub { my ($b) = @_; $button->{$_}->set_sensitive($_ ne $b) foreach keys %$button };

    gtkadd($window1->{window},
	   gtkpack_(Gtk2::VBox->new(0, 2), 
                 if_(!$::isEmbedded, 0, gtkcreate_img("drakfont.620x57")), 
                 1, gtkpack_(Gtk2::HBox->new(0, 2), 
                             1, gtkpack_(Gtk2::VBox->new(0, 2), 
                                         1, gtkpack($font_box = Gtk2::VBox->new(0, 5), $font_sel = Gtk2::FontSelection->new,),
                                         0, gtkpack_(Gtk2::HBox->new(0, 2),
                                                     0, gtkadd(gtkset_layout(Gtk2::VButtonBox->new, 'end'),
                                                               gtksignal_connect($button->{windows} = Gtk2::Button->new(N("Get Windows Fonts")),
                                                                                 clicked => sub {
                                                                                     $disable->('windows');
                                                                                     $$central_widget->destroy;
                                                                                     $windows = 1;
                                                                                     appli_choice();
                                                                                 }),
                                                               gtksignal_connect($button->{uninstall} = Gtk2::Button->new(N("Uninstall Fonts")),
                                                                                 clicked => sub {
                                                                                     $disable->('uninstall');
                                                                                     $$central_widget->destroy;
                                                                                     uninstall();
                                                                                 }),
                                                              ), 
                                                     0, gtkadd(gtkset_layout(Gtk2::VButtonBox->new, 'end'),
                                                               gtksignal_connect($button->{adv_option} = Gtk2::Button->new(N("Advanced Options")),
                                                                                 clicked => sub {
                                                                                     $disable->('adv_option');
                                                                                     $$central_widget->destroy;
                                                                                     $windows = 0;
                                                                                     advanced_install();
                                                                                 }),
                                                               gtksignal_connect($button->{font_list} = Gtk2::Button->new(N("Font List")),
                                                                                 clicked => sub {
                                                                                     $disable->('font_list');
                                                                                     $$central_widget->destroy;
                                                                                     create_fontsel();
                                                                                 }),
                                                              ), 
                                                     1, Gtk2::HBox->new(0, 2), 
                                                     0, gtkadd(gtkset_layout(Gtk2::VButtonBox->new, 'end'),
                                                               gtksignal_connect(Gtk2::Button->new(N("About")), clicked => \&help),
                                                               gtksignal_connect(Gtk2::Button->new(N("Close")), clicked => sub { Gtk2->main_quit }),
                                                              ),
                                                    ),
                                        ),
                            ),
                ),
          );

    $central_widget = \$font_sel;
    $disable->('font_list');
    $window1->{rwindow}->show_all;
    $window1->{rwindow}->realize;
    $window1->main;
    ugtk2->exit(0);
}

$list_all_font_path || $xlsfonts || $windows || @install || @uninstall ? backend_mod() : interactive_mode();

sub text_view {
    my ($text) = @_;
    my $box;
    gtkpack($font_box,
            $box = gtkpack_(Gtk2::VBox->new(0,10), 
                            1, gtkpack(Gtk2::HBox->new(0,0), 
                                       create_scrolled_window(gtktext_insert(Gtk2::TextView->new, [ [ $text ] ]))
                                      ), 
                            0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'spread'),
                                      gtksignal_connect(Gtk2::Button->new(N("OK")), 
                                                        clicked => sub { $$central_widget->destroy }),
                                     ),
                           )
           );
    $central_widget = \$box;
    $font_box->show_all;
}

sub help() {
    ugtk2::create_dialog(N("Help"), formatAlaTeX(N("Copyright (C) 2001-2002 by MandrakeSoft 


       DUPONT Sebastien (original version)

       CHAUMETTE Damien <dchaumette\@mandrakesoft.com>

       VIGNAUD Thierry <tvignaud\@mandrakesoft.com>")

. "\n\n\n" . N("This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.


 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.


 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.")

. "\n\n\n" . N("Thanks:

    -  pfm2afm:   
	 by Ken Borgendale:
	    Convert a Windows .pfm  file to a .afm (Adobe Font Metrics)

    -  type1inst:
	 by James Macnicol: 
	    type1inst generates files fonts.dir fonts.scale & Fontmap.

    -  ttf2pt1:   
	  by Andrew Weeks, Frank Siegert, Thomas Henlich, Sergey Babkin  
             Convert ttf font files to afm and pfb fonts
")));
}

sub appli_choice() {
    my $choice_box;
    my %checks;
    gtkpack($font_box,
            $choice_box = gtkpack__(Gtk2::VBox->new, 
                                    N("Choose the applications that will support the fonts:"),
                                    Gtk2::WrappedLabel->new(N("Before installing any fonts, be sure that you have the right to use and install them on your system.\n\n-You can install the fonts the normal way. In rare cases, bogus fonts may hang up your X Server.")),
                                    (map {
                                        gtkpack_(Gtk2::HBox->new, 
                                                 0, $_->[0], 
                                                 1, Gtk2::HBox->new, 
                                                 0, $checks{$_->[1]} = Gtk2::CheckButton->new,
                                                ), 
                                            } ([ N("Ghostscript"), "11" ],
                                               [ N("StarOffice"), "22" ],
                                               [ N("Abiword"), "33" ],
                                               [ N("Generic Printers"), "44" ],
                                              ), 
                                    ),
                                    gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'spread'),
                                           gtksignal_connect(Gtk2::Button->new(N("OK")),
                                                             clicked => sub {
                                                                 $$central_widget->destroy;
                                                                 import_status();
                                                             }),
                                           gtksignal_connect(Gtk2::Button->new(N("Cancel")),
                                                             clicked => sub {
                                                                 @install = ();
                                                                 $$central_widget->destroy;
                                                                 create_fontsel();
                                                             }),
                                          ),
                                   ),
           );
    foreach ([ $checks{11}, \$gs ], [ $checks{22}, \$so ], [ $checks{33}, \$abi ], [ $checks{44}, \$printer ]) {
        my $ref = $_->[1];
        gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1 });
    }
    $central_widget = \$choice_box;
}

my $select_font_msg;

sub font_choice() {
    my $file_dialog;
    $select_font_msg = N("Select the font file or directory and click on 'Add'");
    $file_dialog = gtksignal_connect(Gtk2::FileSelection->new(N("File Selection")), destroy => sub { $file_dialog->destroy });
    $file_dialog->ok_button->signal_connect(clicked => \&file_ok_sel, $file_dialog);
    $file_dialog->ok_button->set_label(N("Add"));
    $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy });
    $file_dialog->cancel_button->set_label(N("Close"));
    $file_dialog->show;
}

sub file_ok_sel {
    my ($_widget, $file_selection) = @_;
    my $file_name = $file_selection->get_filename;
    if ($file_name =~ /\Q$select_font_msg/) {
        create_dialog(N("Error"), N("You've not selected any font"));
    } else {
        print "-- @install\n";
        if (!member($file_name, @install)) {
            push @install, $file_name;
            $model->append_set(undef, [ 0 => $file_name ]);
        }
    }
}

sub list_remove() { #- TODO : multi-selection
    my ($treeStore, $iter) = $list->get_selection->get_selected;
    return unless $iter;
    my $to_remove = $treeStore->get($iter, 0);
    my ($index) = map_index { if_($_ eq $to_remove, $::i) } @install;
    splice @install, $index, 1;
    $treeStore->remove($iter);
}

sub advanced_install() {
    my $adv_box;
    $model = Gtk2::TreeStore->new("Glib::String");
    $list = Gtk2::TreeView->new_with_model($model);
    $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0));
    $list->set_headers_visible(0);
    $list->get_selection->set_mode('browse');
    $list->set_rules_hint(1);

    gtkpack($font_box,
            $adv_box = gtkpack_(Gtk2::VBox->new(0, 10), 
                                1, gtkpack_(Gtk2::HBox->new(0, 4), 1, create_scrolled_window($list),), 
                                0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'spread'),
                                          gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => \&font_choice),
                                          gtksignal_connect(Gtk2::Button->new(N("Remove Selected")), clicked => \&list_remove),
                                          gtksignal_connect(Gtk2::Button->new(N("Install List")), 
                                                            clicked => sub {
                                                                if (@install) {
                                                                    $$central_widget->destroy;
                                                                    appli_choice();
                                                                }
                                                            })
                                         )
                               )
           );
    $central_widget = \$adv_box;
    $adv_box->show_all;
}

sub list_to_remove() {
    #my @files_path = grep(!/fonts/, all($current_path)); garbage ?
    gtkflush();
    my ($tree, @tux) = $left_list->get_selection->get_selected_rows; #- get tree & paths
    push @uninstall, map { $tree->get($tree->get_iter($_), 0) } @tux;
    #push @uninstall, $current_path . "/" . $files_path[$_] foreach @number_to_remove; garbage ?
    $$central_widget->destroy;
    show_list_to_remove();
}

sub show_list_to_remove() {
    my $show_box;
    my $model = Gtk2::TreeStore->new("Glib::String");
    my $list = Gtk2::TreeView->new_with_model($model);
    $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0));
    $list->set_headers_visible(0);
    $list->get_selection->set_mode('browse');
    $list->set_rules_hint(1);

    $model->append_set(undef, [ 0 => $_ ]) foreach @uninstall;

    gtkpack($font_box,
            $show_box = gtkpack_(Gtk2::VBox->new(0, 10), 
                                 1, gtkpack_(Gtk2::HBox->new(0, 4), 1, create_scrolled_window($list)), 
                                 0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'spread'),
                                           gtksignal_connect(Gtk2::Button->new(N("click here if you are sure.")),
                                                             clicked => sub {
                                                                 $$central_widget->destroy;
                                                                 import_status_uninstall();
                                                             }),
                                           gtksignal_connect(Gtk2::Button->new(N("here if no.")),
                                                             clicked =>
                                                             sub { $$central_widget->destroy; create_fontsel() }
                                                            ),
                                          ),
                                )
           );
    $central_widget = \$show_box;
    $show_box->show_all;
}

sub uninstall() { #- TODO : add item to right list with gtksignal_connect
    my $uninst_box;
    @install              = ();
    @installed_fonts_path = ();
    list_fontpath();
    chk_empty_xfs_path();
    
    #- left part
    $left_model = Gtk2::TreeStore->new("Glib::String");
    $left_list = Gtk2::TreeView->new_with_model($left_model);
    $left_list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0));
    $left_list->set_headers_visible(0);
    $left_list->set_rules_hint(1);
    $left_list->get_selection->set_mode('multiple');

    $left_model->append_set(undef, [ 0 => $_ ]) foreach @installed_fonts_path;

    #- right part
    $right_model = Gtk2::TreeStore->new("Glib::String");;
    $right_list = Gtk2::TreeView->new_with_model($right_model);
    $right_list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0));
    $right_list->set_headers_visible(0);
    $right_list->get_selection->set_mode('multiple');
    $right_list->set_rules_hint(1);

    gtkpack($font_box,
            $uninst_box = gtkpack_(Gtk2::VBox->new(0, 10), 
                                   1, gtkpack_(Gtk2::HBox->new(0, 4), 
                                               1, create_scrolled_window($left_list),
                                               #1, create_scrolled_window($right_list)
                                              ), 
                                   0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'spread'),
                                             gtksignal_connect(Gtk2::Button->new(N("Unselected All")),
                                                               clicked => sub { $left_list->get_selection->unselect_all }
                                                              ),
                                             gtksignal_connect(Gtk2::Button->new(N("Selected All")),
                                                               clicked => sub { $left_list->get_selection->select_all }
                                                              ),
                                             gtksignal_connect(Gtk2::Button->new(N("Remove List")), clicked => sub { list_to_remove() }),
                                            ),
                                  )
           );
    $central_widget = \$uninst_box;
    $uninst_box->show_all;
}

sub import_status() {
    my $table;
    $pbar  = Gtk2::ProgressBar->new;
    $pbar1 = Gtk2::ProgressBar->new;
    $pbar2 = Gtk2::ProgressBar->new;
    $pbar3 = Gtk2::ProgressBar->new;
    gtkpack(
        $font_box,
        $table = create_packtable({ col_spacings => 10, row_spacings => 50 },
				  [ "", "" ],
				  [ N("Initial tests"), $pbar, $pbar->set_text(' ') ],
				  [ N("Copy fonts on your system"), $pbar1, $pbar1->set_text(' ') ],
				  [ N("Install & convert Fonts"), $pbar2, $pbar2->set_text(' ') ],
				  [ N("Post Install"), $pbar3, $pbar3->set_text(' ') ],
				 ),
	   );
    $central_widget = \$table;
    $font_box->show_all;
    gtkflush();
    backend_mod();
}

sub import_status_uninstall() {
    my $table;
    $pbar  = Gtk2::ProgressBar->new;
    $pbar1 = Gtk2::ProgressBar->new;
    $pbar2 = Gtk2::ProgressBar->new;
    gtkpack(
        $font_box,
        $table = create_packtable({ col_spacings => 10, row_spacings => 50 },
				  [ "", "" ],
				  [ "", "" ],
				  [ N("Initial tests"), $pbar, $pbar->set_text(' ') ],
				  [ N("Remove fonts on your system"), $pbar1, $pbar1->set_text(' ') ],
				  [ N("Post Uninstall"), $pbar2, $pbar2->set_text(' ') ],
				 ),
	   );
    $central_widget = \$table;
    $font_box->show_all;
    backend_mod();
}

sub progress {
    my ($progressbar, $incr, $label_text) = @_;
    $progressbar->set_fraction(min(1, $progressbar->get_fraction + $incr));
    $progressbar->set_text($label_text);
    gtkflush();
}

sub interactive_progress {
    $interactive and progress(@_);
}