#!/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 $application;
my $install;
my $uninstall;
my $so      = 1;
my $gs      = 1;
my $abi     = 1;
my $printer = 1;
my $mode    = -1;
my @application;
my @install;
my @uninstall;
my $interactive;
my $text;
my $vscrollbar;
my $check4;
my $check1;
my $check2;
my $check3;
my $pbar;
my $pbar1;
my $pbar2;
my $pbar3;
my $font_box;
my $central_widget;
my $label1;
my $label2;
my $label3;
my $label4;
my $list_path;
my $path_list;
my $current_path;
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 $ghostscript;

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 @fontsdir_to_install;       # list of fonts to uninstall
my @fontsdir_to_uninstall;     # path to remove in xfs font file
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 (!(any { if_(!(/^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|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;
                grep { /$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;
                            grep { /$i/ } @font_list or push @font_list, "$fn/$i";
                        }
                    }
                }
            }
            elsif (is_a_font($fn)) {
		!$replace && any { /$fn/ } @installed_fonts and next;
		!grep { /$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)  = @_;
    my @font_list_tmp;
    if (-d $fn) {
        @font_list_tmp = map { if_(is_a_font($_), $_) } all($fn);
    } else {
        push @font_list_tmp, $fn if is_a_font($fn);
    }
    @font_list = uniq(@font_list, @installed_fonts_full_path);
    print "Fonts to uninstal: " . $_ . "\n" foreach @font_list;
}

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 / @$fontname, N("%s fonts conversion", $font_type));
    }
}

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



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"));
        glob("$drakfont_dir/tmp/tmp/*.TTF") 
          and system('cd ' . $drakfont_dir . '/tmp/tmp ; for foo in *.TTF; do mv $foo `basename $foo .TTF`.ttf; done');
        system('cd ' . $drakfont_dir . '/tmp/tmp  && cp *.ttf ../../ttf');
        interactive_progress($pbar2, 0.20, N("please wait during ttmkfdir..."));

        my $ttfdir = $drakfont_dir . "/ttf";
        system("cd $ttfdir && $fccache && $ttmkfdir -u > fonts.dir");
        interactive_progress($pbar2, 0.10, N("True Type install done"));
        my $update_chkfontpath = "$chkfontpath -a $drakfont_dir/ttf";

        if ($so && $gs) {
            my @glob_drak = glob("$drakfont_dir/tmp/tmp/*.ttf");
            convert_ttf_fonts(\@glob_drak, 1);
            system("cd $drakfont_dir/tmp/tmp && mv *.gsf *.pfb *.pfm *.afm ../Type1");
            system("cd $drakfont_dir/tmp/Type1 && $type1inst");
            interactive_progress($pbar2, 0.10, N("type1inst building"));
            -e "$drakfont_dir/tmp/Type1/Fontmap" 
              and system("cd $drakfont_dir/tmp/Type1 && cat Fontmap >> `rpm -ql ghostscript | grep Fontmap.GS` ");
            system("cd $drakfont_dir/tmp/Type1 && mv *.pfm *.gsf *.afm *.pfb ../../Type1 ");
            my $type1dir = $drakfont_dir . "/Type1";
            system("cd $type1dir && $fccache && $type1inst");
            interactive_progress($pbar2, 0.05, N("Ghostscript referencing"));
            $update_chkfontpath .= "; $chkfontpath -a $drakfont_dir/Type1";
        }

        if (!$so && $gs) {
            convert_ttf_fonts([ glob("$/drakfont_dir/tmp/tmp/*.ttf") ], 1);
            system("cd $drakfont_dir/tmp/tmp && mv *.gsf *.pfb *.pfm ../Type1");
            system("cd $drakfont_dir/tmp/Type1 && $type1inst");
            interactive_progress($pbar2, 0.1, N("type1inst building"));
            system("cd $drakfont_dir/tmp/Type1 && cat Fontmap >> `rpm -ql ghostscript | grep Fontmap.GS` ");
            system("cd $drakfont_dir/tmp/Type1 && mv *.pfm *.afm *.gsf *.pfb ../../Type1 ");
            my $type1dir = $drakfont_dir . "/Type1";
            system("cd $type1dir && $fccache && $type1inst");
            interactive_progress($pbar2, 0.05, N("Ghostscript referencing"));
            $update_chkfontpath .= "; $chkfontpath -a $drakfont_dir/Type1";
        }

        if ($so && !$gs) {
            convert_ttf_fonts([ glob("$drakfont_dir/tmp/tmp/*.ttf") ]);
            convert_fonts([ glob("$drakfont_dir/tmp/tmp/*.pfm") ], $pfm2afm, "PFM");
            system("cd $drakfont_dir/tmp/tmp && mv  *.afm ../Type1");
            system("cd $drakfont_dir/tmp/Type1 && mv *.afm ../../Type1 ");
            my $type1dir = $drakfont_dir . "/Type1";
            system("cd $type1dir && $fccache && $type1inst");
            interactive_progress($pbar2, 0.14, N("type1inst building"));
            $update_chkfontpath .= "; $chkfontpath -a $drakfont_dir/Type1";
        }

        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);
            grep { /$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;
        grep { $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 = new Gtk2::FontSelection,);
    $central_widget = \$font_sel;
}

sub display_error {
    my ($message) = @_;
    my $error_box;
    $$central_widget->destroy();
    gtkpack($font_box,
	    $error_box = gtkpack_(new Gtk2::VBox(0, 0), 1,
				  new Gtk2::Label($message), 0,
				  gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'),
					 gtksignal_connect(new Gtk2::Button(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 ($adv_opt_button, $font_button);
    gtkadd($window1->{window},
	   gtkpack_(new Gtk2::VBox(0, 2), if_(!$::isEmbedded, 0, gtkcreate_img("drakfont.620x57")), 1,
		    gtkpack_(new Gtk2::HBox(0, 2), 1,
			     gtkpack_(new Gtk2::VBox(0, 2), 1,
				      gtkpack($font_box = new Gtk2::VBox(0, 5), $font_sel = new Gtk2::FontSelection,), 1,
				      gtkpack_(new Gtk2::HBox(0, 2), 0,
					       gtkadd(gtkset_layout(new Gtk2::VButtonBox, 'end'),
						      gtksignal_connect(new Gtk2::Button(N("Get Windows Fonts")),
									clicked => sub {
									    $$central_widget->destroy();
									    $windows = 1;
									    appli_choice();
									}),
						      gtksignal_connect(new Gtk2::Button(N("Uninstall Fonts")),
									clicked => sub {
									    $$central_widget->destroy();
									    uninstall();
									}),
						     ), 0,
					       gtkadd(gtkset_layout(new Gtk2::VButtonBox, 'end'),
						      gtksignal_connect($adv_opt_button = new Gtk2::Button(N("Advanced Options")),
									clicked => sub {
                                                 $font_button->set_sensitive(1);
                                                 $adv_opt_button->set_sensitive(0);
									    $$central_widget->destroy();
									    $windows = 0;
									    advanced_install();
									}),
						      gtksignal_connect($font_button = new Gtk2::Button(N("Font List")),
									clicked => sub {
                                                 $font_button->set_sensitive(0);
                                                 $adv_opt_button->set_sensitive(1);
									    $$central_widget->destroy();
									    create_fontsel();
									}),
						     ), 1,
					       new Gtk2::HBox(0, 2), 0,
					       gtkadd(gtkset_layout(new Gtk2::VButtonBox, 'end'),
						      gtksignal_connect(new Gtk2::Button(N("About")), clicked => \&help),
						      gtksignal_connect(new Gtk2::Button(N("Close")), clicked => sub { Gtk2->main_quit() }),
						     ),
					      ),
				     ),
			    ),
		   ),
	  );
    $central_widget = \$font_sel;
    $font_button->set_sensitive(0);
    $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_(new Gtk2::VBox(0,10), 1,
			    gtkpack_(new Gtk2::HBox(0,0), 1,
				     create_scrolled_window(gtktext_insert(new Gtk2::TextView, [ [ $text ] ]))
				    ), 0, 
			    gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'),
				   gtksignal_connect(new Gtk2::Button(N("OK")), 
						     clicked => sub { $$central_widget->destroy() }),
				  ),
			   )
	   );
    $central_widget = \$box;
    $font_box->show_all();
}

sub help() {
    ugtk2::create_dialog(N("Help"), N("
 Copyright (C) 2001-2002 by MandrakeSoft 
     DUPONT Sebastien (original version)
     CHAUMETTE Damien <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.

 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 $text = new Gtk2::TextView;
    gtkpack($font_box,
	    $choice_box = gtkpack_(new Gtk2::HBox(0, 10), 0,
				   new Gtk2::VBox(0, 10), 0,
				   new Gtk2::VBox(0, 10), 1,
				   gtkpack_(new Gtk2::VBox(0, 10), 1,
					    gtkpack_(new Gtk2::VBox(0, 10), 1,
						     gtkpack(new Gtk2::HBox(0, 10), 
							     new Gtk2::HBox(0, 10),
							     N("Choose the applications that will support the fonts:"),
							     new Gtk2::HBox(0, 10),
							    ), 0,
						     new Gtk2::HBox(0, 10), 0, 
						     gtkpack_(new Gtk2::HBox(0, 10), 0,
							      N("Ghostscript"), 1,
							      new Gtk2::HBox(0, 10), 0,
							      my $check11 = new Gtk2::CheckButton(),
							     ), 0,
						     gtkpack_(new Gtk2::HBox(0, 10), 0,
							      N("StarOffice"), 1,
							      new Gtk2::HBox(0, 10), 0,
							      my $check22 = new Gtk2::CheckButton(),
							     ), 0,
						     gtkpack_(new Gtk2::HBox(0, 10), 0,
							      N("Abiword"), 1,
							      new Gtk2::HBox(0, 10), 0,
							      my $check33 = new Gtk2::CheckButton(),
							     ), 0,
						     gtkpack_(new Gtk2::HBox(0, 10), 0,
							      N("Generic Printers"), 1,
							      new Gtk2::HBox(0, 10), 0,
							      my $check44 = new Gtk2::CheckButton(),
							     ),
						    ), 0,
					    gtkpack_(new Gtk2::HBox(0, 10), 1,
						     gtktext_insert(gtkset_editable($text, 0),
								    [ [ 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.") ] ]
								   ), 0,
						     new Gtk2::VBox(0, 10),
						    ), 0,
					    gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'),
						   gtksignal_connect(new Gtk2::Button(N("OK")),
								     clicked => sub {
									 $$central_widget->destroy();
									 import_status();
								     }),
						   gtksignal_connect(new Gtk2::Button(N("Cancel")),
								     clicked => sub {
									 @install = ();
									 $$central_widget->destroy();
									 create_fontsel();
								     }),
						  ),
					   ), 0,
				   new Gtk2::VBox(0, 10), 0,
				   new Gtk2::VBox(0, 10),
				  ),
	   );
    foreach ([ $check11, \$gs ], [ $check22, \$so ], [ $check33, \$abi ], [ $check44, \$printer ]) {
        my $ref = $_->[1];
        gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1 });
    }
    $central_widget = \$choice_box;
    $font_box->show_all();
}

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(new Gtk2::FileSelection(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->set_filename($select_font_msg);
    $file_dialog->show();
}

sub file_ok_sel {
    my ($_widget, $file_selection) = @_;
    my $file_name = $file_selection->get_filename();
    if ($file_name =~ /$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;
    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(Gtk2::GType->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_(new Gtk2::VBox(0, 10), 1,
				gtkpack_(new Gtk2::HBox(0, 4), 1, create_scrolled_window($list),), 0,
				gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'),
				       gtksignal_connect(new Gtk2::Button(N("Add")), clicked => sub { font_choice() }),
				       gtksignal_connect(new Gtk2::Button(N("Remove Selected")), clicked => \&list_remove),
				       gtksignal_connect(new Gtk2::Button(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(Gtk2::GType->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_(new Gtk2::VBox(0, 10), 1,
				 gtkpack_(new Gtk2::HBox(0, 4), 1, create_scrolled_window($list)), 0,
				 gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'),
					gtksignal_connect(new Gtk2::Button(N("click here if you are sure.")),
							  clicked => sub {
							      $$central_widget->destroy();
							      import_status_uninstall();
							  }),
					gtksignal_connect(new Gtk2::Button(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(Gtk2::GType->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(Gtk2::GType->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_(new Gtk2::VBox(0, 10), 1,
				   gtkpack_(new Gtk2::HBox(0, 4), 1,
					    create_scrolled_window($left_list), #1,
					    #create_scrolled_window($right_list)
					   ), 0,
				   gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'),
					  gtksignal_connect(new Gtk2::Button(N("Unselected All")),
							    clicked => sub { $left_list->get_selection->unselect_all() }
							   ),
					  gtksignal_connect(new Gtk2::Button(N("Selected All")),
							    clicked => sub { $left_list->get_selection->select_all() }
							   ),
					  gtksignal_connect(new Gtk2::Button(N("Remove List")), clicked => sub { list_to_remove() }),
					 ),
				  )
	   );
    $central_widget = \$uninst_box;
    $uninst_box->show_all();
}

sub import_status() {
    my $table;
    $pbar  = new Gtk2::ProgressBar;
    $pbar1 = new Gtk2::ProgressBar;
    $pbar2 = new Gtk2::ProgressBar;
    $pbar3 = new Gtk2::ProgressBar;
    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  = new Gtk2::ProgressBar;
    $pbar1 = new Gtk2::ProgressBar;
    $pbar2 = new Gtk2::ProgressBar;
    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();
    gtkflush();
    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(@_);
}