#!/usr/bin/perl -w
require 5.006;
## I tossed this together just to test the tellSize method.
## If you don't have the required Tk stuff it may not work
## too well for you. -Ken
use strict;
$|++;
our $VERSION = '1.0';
use Getopt::Long qw(GetOptions);
use Cwd;
use File::Basename; 
use GDS2;
use Tk;
use Tk::WaitBox; 
use Tk::HList; 
use Tk::ProgressBar;
use Tk::Scale;

$\="\n";
## subs used
sub printUsage(;$);
sub printVersion();
sub getHomeDir($);
sub dumpGds($;$);

our $BGCOLOR='#99ccff';
our $BGCOLOR2='#ffff00';
our $BGCOLOR3='#ffffcc';
our $FGCOLOR='#000000';
our $FileImg;
our $TextFileImg;
our $FoldImg;
our $G_percentDone=0;
our $G_ECHO=1,
our $ActFoldImg;
our $MW;

my $gui=0;
## process command line...
GetOptions(
           'gui!'       => \$gui,
           'help'       => \&printUsage,
           'version'    => \&printVersion,
          ) || printUsage();
          
my $fileNameIn = '';
$fileNameIn = shift if ($#ARGV >= 0);
printUsage() if ($#ARGV >= 0);

if (! $gui)
{
    ## take care of things we need from user that were not 
    ## supplied on command line
    if ($fileNameIn eq '')
    {
        my $notDone = 9; #limit for how many times we will ask
        while ($notDone)
        {
            printf("GDS2 file to read: ");
            $fileNameIn = <STDIN>;
            chomp $fileNameIn;
            $notDone = 0 if ($fileNameIn ne '');
        }
        printUsage() if ($fileNameIn eq '');
    }
    dumpGds($fileNameIn); 
}
else
{
    my @packList1 = (-side => 'left',  -padx => 0, -pady => 3, -fill => 'x');
    my @packList2 = (-side => 'left',  -padx => 3, -pady => 2, -fill => 'x');
    my @packList3 = (-side => 'top',   -padx => 0, -pady => 3, -fill => 'x');
    my @packList4 = (-side => 'right', -padx => 3, -pady => 3, -fill => 'x');

    #### create the MainWindow (MW)
    $MW = MainWindow -> new(
        -background => $BGCOLOR,
        -foreground => $FGCOLOR, 
    );
    $MW -> title('gds2dump'); 
    $MW -> iconname('gds2dump'); 
    $MW -> minsize(1, 1); 

    ###### start top menu bar #####
    my $wMenu = $MW -> Frame(
        -relief => 'raised', 
        -background => $BGCOLOR,
        -borderwidth => 2,
    );
    $wMenu -> pack(-fill => 'x');

    ##### options menu #####
    my $optionsMenu = $wMenu -> Menubutton(
        -activebackground => $BGCOLOR2,
        -background       => $BGCOLOR,
        -text             => 'Options', 
        -underline        => 0
    );

    $optionsMenu -> separator(
        -background       => $BGCOLOR,
    );

    $optionsMenu -> radiobutton(
        -activebackground => $BGCOLOR, 
        -variable         => \$G_ECHO,
        -label            => 'Echo to terminal',
        -value            => 1,
    );

    $optionsMenu -> radiobutton(
        -activebackground => $BGCOLOR, 
        -variable         => \$G_ECHO,
        -label            => 'do not echo to terminal',
        -value            => 0,
    );

    ### quit
    $optionsMenu -> command(
        -activebackground => 'Red',
        -background       => $BGCOLOR,
        -label            => 'Exit',
        -command          => sub { $MW -> destroy; exit(1); },
    );
    $optionsMenu -> pack(-side=>'left');

    ##### Help menu #####
    my $textArea;
    my $helpMenu = $wMenu -> Menubutton(
        -text             => 'Help', 
        -activebackground => $BGCOLOR2,
        -background       => $BGCOLOR,
        -underline        => 0
    );
    $helpMenu -> command(
        -activebackground => $BGCOLOR2,
        -background       => $BGCOLOR,
        -label            => 'Program Version',
        -command          => sub {
            $textArea -> delete('0.0', 'end');
            $textArea -> insert('end', "gds2dump $VERSION\n");
            $textArea -> insert('end', "Using Perl $]\n");
        },
    );
    $helpMenu -> separator(
        -background       => $BGCOLOR,
    );
    $helpMenu -> command(
        -activebackground => $BGCOLOR2,
        -background       => $BGCOLOR,
        -label            => 'Print help in text window',
        -command          => sub { \&printUsage($textArea); },
        -activebackground => 'purple',
    );
    $helpMenu -> pack(-side=>'right');
    #### end top menu bar #####################################

    ##### Create file selection areas #### 
    ## Create Frame for left side 
    my $mwLeft = $MW -> Frame(
        -relief      => 'raised', 
        -background  => $BGCOLOR,
        -borderwidth => 2,
    );
    $mwLeft -> pack(@packList1); 

    $FileImg     = $mwLeft -> Pixmap(-file => Tk->findINC('file.xpm'));
    $TextFileImg = $mwLeft -> Pixmap(-file => Tk->findINC('textfile.xpm'));
    $FoldImg     = $mwLeft -> Pixmap(-file => Tk->findINC('folder.xpm'));
    $ActFoldImg  = $mwLeft -> Pixmap(-file => Tk->findINC('act_folder.xpm'));

    #### directory entry
    my $directoryLabel = $mwLeft -> Label( 
        -background  => $BGCOLOR,
        -text        => 'PWD:', 
        -font        => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*", 
        -anchor      => 'w', 
    ); 
    $directoryLabel -> pack(@packList3); 

    my $G_DIRECTORY = ''; 
    my $entryDirectory = $mwLeft -> Entry( 
        -background     => '#cccccc', 
        -font           => "-*-courier-medium-r-normal--*-140-*-*-*-*-*-*", 
        -foreground     => $FGCOLOR, 
        -relief         => 'sunken', 
        -state          => 'disabled', 
        -textvariable   => \$G_DIRECTORY, 
        -width          => 20, 
    ); 
    $entryDirectory -> pack(@packList3); 
    my $localDir = cwd(); 
    $G_DIRECTORY=basename($localDir); 

    #### spacer label 
    my $spacerLabel_1 = $mwLeft -> Label( 
        -background => $BGCOLOR,
        -text       => '    ', 
        -font       => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*", 
        -anchor     => 'w', 
    ); 
    $spacerLabel_1 -> pack(@packList3);; 

    #### graphics file entry 
    my $graphicsFileLabel = $mwLeft -> Label( 
        -text       => 'Gds2 File: ', 
        -font       => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*", 
        -background => $BGCOLOR, 
        -anchor     => 'w', 
    ); 
    $graphicsFileLabel -> pack(@packList3); 

    ##### Create graphics text display area  ##### 
    my $G_GDS2FILE = $fileNameIn;
    my $entryGraphicsFile = $mwLeft -> Entry( 
        -background     => '#cccccc', 
        -font           => "-*-courier-medium-r-normal--*-140-*-*-*-*-*-*", 
        -foreground     => $FGCOLOR, 
        -relief         => 'sunken', 
        -state          => 'disabled', 
        -textvariable   => \$G_GDS2FILE, 
        -width          => 22, 
    ); 
    $entryGraphicsFile -> pack(@packList3); 
    ##$entryGraphicsFile -> focus; 

    #### spacer label 
    my $spacerLabel_2 = $mwLeft -> Label( 
        -background => $BGCOLOR,
        -text       => '    ', 
        -font       => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*", 
        -anchor     => 'w', 
    ); 
    $spacerLabel_2 -> pack(@packList3);; 

    #### gds2 label 
    my $graphicsFileLabel_1 = $mwLeft -> Label( 
        -text       => " Select Gds2 File:  'double click'", 
        -font       => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*", 
        -background => $BGCOLOR, 
        -anchor     => 'w', 
    ); 
    $graphicsFileLabel_1 -> pack(@packList3);; 

    ### -- graphics file listing -- ##
    my $graphicsFileList;
    $graphicsFileList = $mwLeft -> Scrolled(
        'HList',
        -scrollbars   => 'sw',
        -itemtype     => 'imagetext',
        -separator    => '/',
        -selectmode   => 'single',
        -indent       => 25,

        -background     => $BGCOLOR, 
        -bd             => '2', 
        -font           => "-*-courier-medium-r-normal--*-140-*-*-*-*-*-*", 
        -foreground     => $FGCOLOR, 
        -height         => 16, 
        -relief         => 'sunken', 
        -width          => 25, 

        -command      => sub {
            my $localDir = cwd(); 
            my $name=setFileName($_[0]); 
            $G_GDS2FILE=$name; 
            $G_DIRECTORY=basename($localDir); 
            chomp $G_GDS2FILE; 
            my $rootName = $G_GDS2FILE;
            $rootName =~ s|\.\w*||;
            if ($_[0] eq '.')
            {
                my $waitBox = $graphicsFileList -> WaitBox; 
                $waitBox -> configure( 
                    -txt1       => "Please wait while I list items", 
                    -txt2       => "Thank you", 
                    -font       => "-*-times-bold-r-normal--*-120-*-*-*-*-*-*", 
                    -foreground => $FGCOLOR, 
                    -background => $BGCOLOR, 
                ); 
                $waitBox -> Show; 

                $graphicsFileList -> delete('entry', $_[0]);
                $graphicsFileList -> add(
                    '.',
                    -text  => $localDir, 
                    -image => $ActFoldImg,
                );
                my $displayName=basename($localDir);
                showGdsFiles('.', $displayName, $graphicsFileList);

                $waitBox -> unShow; 
            }
            chdir $localDir;
        },
    );
    $graphicsFileList -> grid(qw/-sticky nsew/);

    $localDir = cwd();
    $graphicsFileList -> add(
        '.',
        -text  => $localDir, 
        -image => $FoldImg,
    );

    $graphicsFileList -> pack(@packList3);
    ### -- end Graphics listing -- ##

    #### text areaa 
    $textArea = $MW -> Text( 
        -bd             => '2', 
        -font           => '-*-courier-medium-r-normal--*-140-*-*-*-*-*-*', 
        -height         => 25, 
        -relief         => 'sunken', 
        -setgrid        => 'true', 
        -width          => 93, 
        -wrap           => 'word', 
        -background     => $BGCOLOR3, 
        -foreground     => $FGCOLOR, 
    ); 

    my $progress = $MW -> ProgressBar(
        -anchor => 'w',
        -width => 20,
        -length => 200,
        -from => 0,
        -to => 98,
        -troughcolor => '#000000',
        -blocks => 20,
        -colors => [0 => 'red',14 => 'orange',28 => 'yellow',42 => 'green',56 => 'blue',70 => 'purple',84 => 'violet'],
        -resolution => 5,
        -variable => \$G_percentDone,
    );
    $progress -> pack();

    #### text scrollbar...attached to MW 
    my $textScroll = $MW -> Scrollbar( 
        -command    => [$textArea => 'yview'], 
        -background => $BGCOLOR, 
    ); 
    $textArea -> configure( 
        -yscrollcommand => ['set', $textScroll], 
    ); 

    #### scrollbar goes on the left side 
    $textScroll -> pack( 
        -side => 'left', 
        -fill => 'y', 
    ); 
    #### display 
    $textArea -> pack( 
        -expand => 'yes', 
        -fill => 'both', 
    ); 

    #### Create Frame for bottom 
    my $mwBottom = $MW -> Frame(
        -relief      => 'raised', 
        -background  => $BGCOLOR,
        -borderwidth => 2,
    );  
    $mwBottom -> pack(@packList1); 

    #### Create 'Dump' Button widget ###### 
    my $dumpButton  = $mwBottom -> Button( 
        -font             => '-*-times-bold-r-normal--*-140-*-*-*-*-*-*', 
        -text             => 'Dump', 
        -height           => 1, 
        -width            => 8, 
        -command          => sub { \&dumpGds($fileNameIn,$textArea); }, 
        -background       => $BGCOLOR,
        -activebackground => $BGCOLOR2, 
    ); 
    $dumpButton -> pack(@packList2);

    #### Create 'Clear' Button widget ###### 
    my $clearButton  = $mwBottom -> Button( 
        -font             => '-*-times-bold-r-normal--*-140-*-*-*-*-*-*', 
        -text             => ' Clear ', 
        -height           => 1, 
        -width            => 8, 
        -command          => sub { \&clear($textArea); }, 
        -background       => $BGCOLOR,
        -activebackground => $BGCOLOR2, 
    ); 
    $clearButton -> pack(@packList2); 

    $progress -> value($G_percentDone);
    my $fileSize = (stat $fileNameIn)[5];

    MainLoop();
}

## subroutines...
################################################################################ 
sub dumpGds($;$)
{
    my $fileNameIn = shift;
    my $widget = shift;

    my $fileSize = (stat $fileNameIn)[7];
    my $gds2FileIn = new GDS2(-fileName => $fileNameIn);
    if (defined $widget)
    {
        $G_percentDone = 0;
        $MW -> update;
    }

    while ($gds2FileIn -> readGds2Record) 
    {
        my $printString = $gds2FileIn -> returnRecordAsString;
        print $printString if ($G_ECHO);
        if (defined $widget)
        {
            $widget -> insert('end',"$printString\n");
            $widget -> update;
        }
        $G_percentDone = int($gds2FileIn -> tellSize * 100 / $fileSize);
    }
}

################################################################################ 
sub setFileName($)
{ 
    my $file = $_[0]; 
    my $returnString=''; 
 
    $file =~ s|\./||; ## for now...
    chomp $file;
    if (-f $file)
    { 
        $returnString=$file; 
    } 
    return $returnString; 
}

################################################################################ 
sub showGdsFiles 
{
    my($entryPath, $text, $widget) = @_;

    opendir(DIR, $entryPath);
    my(@dirent_1) = grep ! /^\.\.?$/, sort(readdir DIR);
    closedir DIR;
    my(@dirent_2) = grep ! /~$/, @dirent_1;
    my(@dirent) = grep ! /\.swp$/, @dirent_2;

    if ($entryPath ne '.')
    {
        $widget -> add(
            $entryPath,
            -text  => $text, 
            -image => $ActFoldImg,
        );
    }
    my $file;
    my $cnt=0;
    while ($file = shift @dirent) 
    {
        my $filePath = "$entryPath/$file";
        if (! -d $filePath) 
        {
            if ( ($file =~ /\.gds[2i]*$/i) or ($file =~ /\.sf$/i) )
            {
                $cnt++;
                my $size = -s $filePath;
                if (-T $file)
                {
                    $widget -> add(
                        $filePath,  
                        -text  => $file, 
                        -image => $TextFileImg, 
                        -data  => $size,
                    );
                }
                else
                {
                    $widget -> add(
                        $filePath,  
                        -text  => $file, 
                        -image => $FileImg, 
                        -data  => $size,
                    );
                }
            }
        }
    }
    if (! $cnt)
    {
        print "In order to be seen, graphics files must end in \".gds\", \".gds2\", \".gdsii\", \".sf\" ";
    }
} # end showGdsFiles
################################################################################ 


################################################################################ 
sub clear($;$)
{
    my $widget = shift;

    $widget -> delete('0.0', 'end'); 
    $G_percentDone = 0;
    $widget -> update;
}

################################################################################ 
sub printVersion()
{
    print $main::VERSION;
    exit 0;
}

################################################################################ 
sub printUsage(;$)
{
    my $widget = shift;
    my $printMethodFront = 'printf("'; 
    my $printMethodBack = '\n");'; 
    if (defined $widget) 
    {
        $widget -> delete('0.0', 'end'); 
        $widget -> yview('end'); 
        $widget -> insert('end', "Calling help ....\n"); 
        $widget -> update;
        $printMethodFront = "\$widget -> insert(\'end\', \""; 
        $printMethodBack = '\n"); $widget -> update;'; 
    }
    eval $printMethodFront." ".$printMethodBack; 
    eval $printMethodFront."  gds2dump rev $main::VERSION".$printMethodBack; 
    eval $printMethodFront."    ".$printMethodBack; 
    eval $printMethodFront."Usage:".$printMethodBack; 
    eval $printMethodFront."  gds2dump [options] gds_file_to_read ".$printMethodBack; 
    eval $printMethodFront."      ".$printMethodBack; 
    eval $printMethodFront."Synopsis:".$printMethodBack; 
    eval $printMethodFront."  Dumps GDS2 file out in an ascii format that preserves the data contained ".$printMethodBack; 
    eval $printMethodFront."  therein.".$printMethodBack; 
    eval $printMethodFront."  ".$printMethodBack; 
    eval $printMethodFront."Options:".$printMethodBack; 
    eval $printMethodFront."  -gui".$printMethodBack; 
    eval $printMethodFront."    run in GUI mode".$printMethodBack; 
    eval $printMethodFront."    ".$printMethodBack; 
    eval $printMethodFront."  -help".$printMethodBack; 
    eval $printMethodFront."    print help and exit".$printMethodBack; 
    eval $printMethodFront."    ".$printMethodBack; 
    eval $printMethodFront."  -version".$printMethodBack; 
    eval $printMethodFront."    print version and exit".$printMethodBack; 
    eval $printMethodFront."  ".$printMethodBack; 
    eval $printMethodFront."Example:".$printMethodBack; 
    eval $printMethodFront."  gds2dump test.gds > test.dumpgds".$printMethodBack; 
    eval $printMethodFront." ".$printMethodBack; 
    exit 1 if (! defined $widget);
}
################################################################################

__END__

