#!/usr/bin/perl
# proc_files_lin.pl
# Processes files on Linux boxes for the Collective.
# Windows-OS processing is required before the files are moved to the Linux
# PC (see proc_files_win.pl). This app only handles the Linux processing.
# The app consists of a GUI (using tk) and processing functions (using perl).
# Various functions use private $statusFlag variables for error tracking; they
# return a positive number on success and 0 on failure.
# Note: Functions have multiple returns. When a significant error is encountered,
# a function displays an error message and then returns at that point. This makes the
# code simpler, but when reading the code keep in mind that errors can cause early
# returns from functions.
# For development on Windows instead of Linux, comment out ###Linux lines and
# uncomment ###Windows lines. Warning: ProcessProject() makes several system
# calls to Linux and will not work properly under Windows.
# Version History:
# 4 Nov. 02:
# Moved the call to ChangeOwnAndMode() to occur after RunGlimpse() (instead of
# before CreatePlatDir(), so that files and directories created during processing
# are all changed.
# Contents
# PART 1: The Premilinaries
# PART 1.1: Modules
# PART 1.2: Global Variables
# PART 2: The GUI
# PART 2.1: Widgets (Windows, Boxes, and their Contents)
# Input Window
# Output Window
# Help Window
# PART 2.2: The Main Loop
# PART 2.3: GUI-Management Functions
# OpenHelpWin()
# OpenOutWin()
# ShowError()
# ShowQuery()
# ScanWkgDir()
# CheckStartDirState()
# LookForSubDirs()
# AdjustPlatState()
# AdjustProjState()
# PART 3: Input Error Checking Functions
# CheckForErrors()
# CheckStartDir()
# CheckDirContents()
# CheckSrcDir()
# CheckDocDir()
# CheckPlatDir()
# CheckProjDir()
# CheckOwnGrp()
# CheckProjTitle()
# PART 4: File Processing Functions
# ProcessProject()
# CreatePlatDir()
# CreateProjDir()
# MoveFiles()
# RunLxr()
# RunGlimpse()
# ChangeOwnAndMode()
# PART 5: Help Data
# GetHelpContents()
# PART 1: The Premilinaries
# PART 1.1: Modules
use strict; # Catches errors during code.
use File::Find; # For file operations.
use File::Path; # For rmtree().
use Tk; # For the GUI.
use Tk::DialogBox; # Dialog boxes for the GUI.
use Tk::Font; # Font objects for the GUI.
# PART 1.2: Global Variables
# Global input variables. These hold the user input and important values
# derived from or pertaining to the input.
my $dirSep = "/"; # Directory separator. ###Linux
#my $dirSep = "\\"; # Directory separator. ###Windows
my $baseDir = "/inetpub/www"; # Base path. ###Linux
###TODO: Someday allow for the other Linux box, /var/www/.
#my $baseDir = "C:\\Astell-THQ"; # Base path. ###Windows
my $wkgDir = $baseDir . $dirSep . "wkg"; # Working directory (where dirs from Windows get dumped).
my $refDir = $baseDir . $dirSep . "reference"; # Path to reference dir.
my $destDir; # Full destination path (refDir, platDir, projDir).
my $startDir = "???"; # Starting project dir (dir to be processed).
my $startDirFlag = 1; # Flags whether (1, default) a dir from $wkgDir or (2) a user-input dir is to be used.
my $startDirState = 1; # Tracks whether or not to reset input dir items.
my $procDir = "???"; # = $wkgDir . $dirSep . $startDir OR = $userDir
my $userDir = ""; # For user to enter a project dir.
my $platDir = "???"; # Platform or category dir for project.
my $projDir = "???"; # Destination project dir.
my @foundDirs = (); # Dirs found in $wkgDir; possible project dirs.
my $numDirs = 0; # Number of dirs found in $wkgDir.
my $haveSrcFlag = 0; # Flags whether or not project has a src subdir.
my $haveDocFlag = 0; # Flags whether or not project has a doc subdir.
my $haveWarnFlag = 0; # Flags whether or not project displays a restricted usage warning.
my $overOld = 0; # Overwrite dest dir flag.
my $platDirValue = "none"; # Holds platform radiobutton values.
my $userPlatDir = ""; # Holds user-input platform dir.
my $projDirFlag = -1; # Flags which "project" dir is to be used in the reference dir.
my $userProjDir = ""; # Holds user-input project dir.
my $projOwner = "astell"; # Holds owner name for the files.
my $projGroup = "inetadmin"; # Holds group name for the files.
my $projOwnGrp = ""; # = $projOwner . ":" . $projGroup.
my $projTitle = "???"; # Project title string (used on HTML pages, can't have spaces).
my $useLxrFlag = 1; # Flags whether or not source code is to be crossed referenced by lxr.
my $useGlimpseFlag = 1; # Flags whether or not source code is to be crossed referenced by lxr.
# Predeclared variables (widget references) so that code can use them before they are defined.
my $inWin;
my $inTitleFr;
my $rescanBtn;
my $inBody;
my $inDirFr;
my $dirList;
my $userDirEn;
my $inPlatFr;
my( $platGbc, $platGba, $platGcn, $platPsx, $platPs2, $platXbox, $platPc, $platCpp, $platOther );
my $userPlatEn;
my( $projDefault, $projOther );
my $userProjEn;
my $projTitleEn;
my $showOutWinBn;
my $outWin;
my $outTitleFr;
my $outBody;
my $helpWin;
my $helpTitleFr;
my $helpBody;
# Other global variables.
my $temp; # Used to refer to widgets when permanent reference is not needed.
my $tempStr = ""; # Temporary string.
my $width; # Used in sizing windows.
my $height; # Used in sizing windows.
my $widthEntry; # Width of an entry box.
my @msgItem; # Holds text-and-tag entries for error and query messages.
my $text; # Holds the text to insert into a Text widget.
my $tag; # Holds the tag for the text being inserted into a Text widget.
my $scanFlag = 0; # Flags whether or $wkgDir has been scanned for projects.
# PART 2: The GUI
# App can display these windows:
# Input window (the Main Window) on left; is called up initially.
# Output window (a Top Level) on right; is called up initially.
# Help window (a Top Level) on right; user can call up.
# and these dialog boxes (Tk::DialogBox):
# Error box; pops up when bad input is detected.
# Query box; pops up to check that user actually wants to do some odd set of specifications.
# Canvases are used to create visual spacers (highlightthickness is set to 0
# to turn off "border" outside canvas).
# $_toplevel_->protocol() is used to prevent inadvertent destruction of top level windows
# that are not the main window (e.g., the user clicks the X, which destroys
# the window. The protocol causes the window to be withdrawn instead. Cannot use:
# $_toplevel_->bind( "", sub { $outWin->withdraw; } );
# as bind() detects the event but does not prevent it (so the window is
# destroyed despite your best intentions.
# PART 2.1: Widgets (Windows, Boxes, and their Contents)
# Input Window
# Create the main window (the Input Window).
$inWin = new MainWindow;
$inWin->title( "Linux File Processing: Input" );
$inWin->configure( -background => "#EEEEEE" );
$inWin->focusFollowsMouse();
# When app loads, checks that processing will occur using Linux.
$inWin->bind( "", sub
{
if ( $^O eq "MSWin32" )
{
# return; ###Windows - Uncomment this line (to abort the WIn32 check) when developing on Windows
@msgItem = ( @msgItem, "ERROR: Wrong operating system!\n12b" );
@msgItem = ( @msgItem,
"Processing must occur on a Linux box, but your OS says it is $^O.\n\n" .
"The program will shut down.\n10n" );
ShowError();
exit;
} elsif ( $^O ne "linux" )
{
@msgItem = ( @msgItem, "WARNING: Wrong operating system?\n12b" );
@msgItem = ( @msgItem,
"This program was written for Linux, but your OS says it is $^O.\n\n" .
"If your OS is some form of Unix, things may work OK, but who knows?\n10n" );
ShowError();
}
} );
# Ctrl-W closes the app (defined in main window but affects all windows).
# 'all' forces all widgets to recognize event, else widgets with focus
# would ignore this.
$inWin->bind( 'all', "", sub
{
$temp = $inWin->focusCurrent();
if ( $temp->toplevel() == $inWin->toplevel() )
{
exit; # Ctrl-W was pressed in Input window; exit app.
} elsif ( $temp->toplevel() == $outWin->toplevel() )
{
$outWin->withdraw; # Ctrl-W was pressed in Output window; withdraw that window.
} elsif ( $temp->toplevel() == $helpWin->toplevel() )
{
$helpWin->withdraw; # Ctrl-W was pressed in Help window; withdraw that window.
} else
{
return; # Ctrl-W was pressed elsewhere (dialog box?); ignore.
}
} );
# Adjust window per screen resolution.
$width = int( .5 * .9 * $inWin->screenwidth() );
$height = int( .8 * $inWin->screenheight() );
$inWin->geometry( $width . "x" . $height . "+20+15" );
# Base width of entry widgets on screen size.
if ( $inWin->screenwidth() < 800 )
{
$widthEntry = 30;
} elsif ( $inWin->screenwidth() < 1000 )
{
$widthEntry = 40;
} else
{
$widthEntry = 60;
}
# Fonts
my $helv8n = $inWin->Font(
-family => "helvetica",
-size => 8,
-weight => "normal" );
my $helv8b = $inWin->Font(
-family => "helvetica",
-size => 8,
-weight => "bold" );
my $helv10n = $inWin->Font(
-family => "helvetica",
-size => 10,
-weight => "normal" );
my $helv10b = $inWin->Font(
-family => "helvetica",
-size => 10,
-weight => "bold" );
my $helv10i = $inWin->Font(
-family => "helvetica",
-size => 10,
-slant => "italic",
-weight => "normal" );
my $helv12n = $inWin->Font(
-family => "helvetica",
-size => 12,
-weight => "normal" );
my $helv12b = $inWin->Font(
-family => "helvetica",
-size => 12,
-weight => "bold" );
my $helv16b = $inWin->Font(
-family => "helvetica",
-size => 16,
-weight => "bold" );
my $cour10n = $inWin->Font(
-family => "courier",
-size => 10,
-weight => "normal" );
my $cour10b = $inWin->Font(
-family => "courier",
-size => 10,
-weight => "bold" );
# Overall Title
$inWin->Label(
-anchor => 'w',
-background => "#BBBBBB",
-font => "$helv16b",
-text => "Linux File Processing for the Collective" )
->pack(
-fill => 'x',
-side => 'top' );
# Input Title Frame
$inTitleFr = $inWin->Frame( -background => "#EEEEEE" )
->pack(
-fill => 'x',
-pady => 2,
-side => 'top' );
# Input Title
$inTitleFr->Label(
-anchor => 'w',
-background => "#EEEEEE",
-font => "$helv12b",
-text => "Input" )
->pack( -side => 'left' );
# Help Button
$inTitleFr->Button(
-activebackground => "#F7DF8F",
-background => "#CCBB99",
-command => \&OpenHelpWin,
-font => "$helv8b",
-text => "Help" )
->pack(
-padx => 10,
-side => 'right' );
# Visual Separator
$inWin->Canvas(
-background => "#888888",
-height => 2,
-highlightthickness => 0,
-takefocus => 0 )
->pack(
-fill => 'x',
-pady => 2,
-side => 'top' );
# Input Area
$inBody = $inWin->Scrolled( "Text",
-background => "#EEEEEE",
-cursor => 'left_ptr',
-font => "$helv10n",
-relief => 'flat',
-scrollbars => 'osoe',
-wrap => 'word' )
->pack(
-expand => 1,
-fill => 'both',
-side => 'top' );
$inBody->tagConfigure( '8n', -font => "$helv8n" );
$inBody->tagConfigure( '8b', -font => "$helv8b" );
$inBody->tagConfigure( '10n', -font => "$helv10n" );
$inBody->tagConfigure( '10b', -font => "$helv10b" );
$inBody->tagConfigure( '10i', -font => "$helv10i" );
$inBody->tagConfigure( '12n', -font => "$helv12n" );
$inBody->tagConfigure( '12b', -font => "$helv12b" );
# Input Directory
$inBody->insert( 'end', "Directory to Be Processed:\n", '10b' );
$inDirFr = $inBody->Frame( -background => "#EEEEEE" )
->pack(
-fill => 'x',
-pady => 2,
-side => 'top' );
$inBody->windowCreate( 'end', -window => $inDirFr );
# Use a Dir in $wkgDir Radiobutton
$temp = $inDirFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'nw',
-background => "#EEEEEE",
-command => sub
{
ScanWkgDir() if ( not $scanFlag );
$rescanBtn->configure( -state => 'normal' ) if ( $rescanBtn->cget( -state ) eq "disabled" );
CheckStartDirState();
},
-font => "$helv10n",
-justify => 'left',
-text => "Choose a directory in $wkgDir:",
-selectcolor => "#FFFF00",
-variable => \$startDirFlag,
-value => "1" )
->grid(
-column => 0,
-row => 0,
-sticky => 'ne' );
# Directory Listing
$dirList = $inDirFr->Listbox(
-background => "#FFFFFF",
-font => "$helv10b",
-height => 0,
-relief => 'flat',
-selectbackground => "#F7DF8F",
-selectforeground => "#000000",
-selectmode => "single" )
->grid(
-column => 1,
-row => 0,
-sticky => 'ne' );
$dirList->insert( 'end', @foundDirs );
$dirList->bind( "", sub
{
return unless ( $startDirFlag );
if ( $numDirs == 0 )
{
@msgItem = ( @msgItem, "ERROR: No directories!\n12b" );
@msgItem = ( @msgItem,
"No directories were found in $wkgDir.\n10n" );
ShowError();
return;
}
$startDir = $dirList->get( $dirList->curselection() );
$procDir = $wkgDir . $dirSep . $startDir;
CheckStartDir( $procDir );
$projDir = $startDir if ( $projDirFlag == 1 );
LookForSubDirs();
} );
# Rescan Button
$rescanBtn = $inDirFr->Button(
-activebackground => "#F7DF8F",
-anchor => 'nw',
-background => "#CCBB99",
-command => \&ScanWkgDir,
-font => "$helv8b",
-text => "Rescan" )
->grid(
-column => 2,
-row => 0,
-sticky => 'ne' );
$rescanBtn->bind( "", sub
{
if ( not $scanFlag )
{
if ( -d $wkgDir )
{
ScanWkgDir();
} else
{
$startDirFlag = 0;
$rescanBtn->configure( -state => 'disabled' );
$userDirEn->configure( -background => "#FFFFFF", -state => 'normal' );
$dirList->configure( -background => "#EEEEEE", -takefocus => '0' );
}
}
} );
$inBody->insert( 'end', "\n" );
# Use a User-Input Dir Radiobutton
$temp = $inBody->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'e',
-background => "#EEEEEE",
-command => sub
{
CheckStartDirState();
$rescanBtn->configure( -state => 'disabled' ) if ( $rescanBtn->cget( -state ) eq "normal" );
$userDir = "???";
},
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Enter the full path to a directory: ",
-variable => \$startDirFlag,
-value => "0" );
$inBody->windowCreate( 'end', -window => $temp );
# User-Input Dir Entry
$userDirEn = $inBody->Entry(
-background => "#EEEEEE",
-font => "$helv10n",
-state => 'disabled',
-textvariable => \$userDir,
-width => 40 );
$inBody->windowCreate( 'end', -window => $userDirEn );
$userDirEn->bind( "", sub
{
return if ( $userDirEn->cget( -state ) eq 'disabled' );
$userDirEn->selectionRange( 0, 'end' );
} );
$userDirEn->bind( "", sub
{
return if ( $userDirEn->cget( -state ) eq 'disabled' );
$userDir =~ s/\s/_/g;
$userDir =~ s/\\/\//g; # Make sure dir uses / separators. ###Linux
#$userDir =~ s/\//\\/g; # Make sure dir uses Windows \ separators. ###Windows
$userDir = "???" if ( $userDir eq "" );
chop $userDir while ( rindex( $userDir, $dirSep ) == (length( $userDir ) - 1) );
$procDir = $userDir;
if ( index( "$userDir", $dirSep ) != -1 )
{
$startDir = $projDir = substr( "$userDir", (rindex( "$userDir", "$dirSep" ) + 1) );
} else
{
$startDir = $projDir = $userDir;
}
LookForSubDirs();
} );
$inBody->insert( 'end', "\n" );
# Directory Processing Options
$inBody->insert( 'end', "\n", '10n' );
$inBody->insert( 'end', "Processing Options for ", '10b' );
$temp = $inBody->Label(
-anchor => 'w',
-background => "#EEEEEE",
-foreground => "#FF0000",
-font => "$helv10b",
-textvariable => \$procDir );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', ":" );
$inBody->insert( 'end', "\n" );
# Src Subdir Checkbutton
$temp = $inBody->Checkbutton(
-activebackground => "#F7DF8F",
-anchor => 'e',
-background => "#EEEEEE",
-font => "$helv10b",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Project's source code is in a src subdirectory",
-variable => \$haveSrcFlag );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
# Doc Subdir Checkbutton
$temp = $inBody->Checkbutton(
-activebackground => "#F7DF8F",
-anchor => 'e',
-background => "#EEEEEE",
-font => "$helv10b",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Project has a doc subdirectory",
-variable => \$haveDocFlag );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
# Warning Checkbutton
$temp = $inBody->Checkbutton(
-activebackground => "#F7DF8F",
-anchor => 'e',
-background => "#EEEEEE",
-font => "$helv10b",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Project needs restricted usage warning",
-variable => \$haveWarnFlag );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
# Destination Directory
$tempStr = $refDir . $dirSep. "" . $dirSep . "";
$inBody->insert( 'end', "Move ", '10b' );
$temp = $inBody->Label(
-anchor => 'w',
-background => "#EEEEEE",
-foreground => "#FF0000",
-font => "$helv10b",
-textvariable => \$procDir );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', " to $tempStr:\n", '10b' );
# Overwrite Checkbutton
$inBody->insert( 'end', " ", '10b' );
$temp = $inBody->Checkbutton(
-activebackground => "#F7DF8F",
-anchor => 'e',
-background => "#EEEEEE",
-font => "$helv10b",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Overwrite if it already exists",
-variable => \$overOld );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
# Destination "Platform" Directory
$inBody->insert( 'end', " : Platform Directory: ", '10b' );
$temp = $inBody->Label(
-anchor => 'w',
-background => "#EEEEEE",
-foreground => "#FF0000",
-font => "$helv10b",
-textvariable => \$platDir );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
# Platform Frame and Radiobuttons
$inBody->insert( 'end', " " );
$inPlatFr = $inBody->Frame( -background => "#EEEEEE" )
->pack(
-fill => 'x',
-pady => 2,
-side => 'top' );
$inBody->windowCreate( 'end', -window => $inPlatFr );
$platGbc = $inPlatFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustPlatState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Game Boy Color (gbc)",
-variable => \$platDirValue,
-value => "gbc" )
->grid(
-column => 1,
-row => 1,
-sticky => 'nw' );
$platGba = $inPlatFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustPlatState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Game Boy Advance (gba)",
-variable => \$platDirValue,
-value => "gba" )
->grid(
-column => 1,
-row => 2,
-sticky => 'nw' );
$platGcn = $inPlatFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustPlatState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "GameCube (gcn)",
-variable => \$platDirValue,
-value => "gcn" )
->grid(
-column => 1,
-row => 3,
-sticky => 'nw' );
$platPsx = $inPlatFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustPlatState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "PlayStation (psx)",
-variable => \$platDirValue,
-value => "psx" )
->grid(
-column => 1,
-row => 4,
-sticky => 'nw' );
$platPs2 = $inPlatFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustPlatState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "PlayStation2 (ps2)",
-variable => \$platDirValue,
-value => "ps2" )
->grid(
-column => 2,
-row => 1,
-sticky => 'nw' );
$platXbox = $inPlatFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustPlatState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Xbox (xbox)",
-variable => \$platDirValue,
-value => "xbox" )
->grid(
-column => 2,
-row => 2,
-sticky => 'nw' );
$platPc = $inPlatFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustPlatState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "PC/Windows Game (pc)",
-variable => \$platDirValue,
-value => "pc" )
->grid(
-column => 2,
-row => 3,
-sticky => 'nw' );
$platCpp = $inPlatFr->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustPlatState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "C/C++ Tool or Library (cpp)",
-variable => \$platDirValue,
-value => "cpp" )
->grid(
-column => 2,
-row => 4,
-sticky => 'nw' );
$inBody->insert( 'end', "\n" );
# User-Input Platform Radiobutton
$inBody->insert( 'end', " " );
$platOther = $inBody->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => sub
{
AdjustPlatState();
$userPlatDir = "???";
},
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Other: ",
-variable => \$platDirValue,
-value => "user" );
$inBody->windowCreate( 'end', -window => $platOther );
# User-Input Platform Entry
$userPlatEn = $inBody->Entry(
-background => "#EEEEEE",
-font => "$helv10n",
-state => 'disabled',
-textvariable => \$userPlatDir,
-width => 30 );
$inBody->windowCreate( 'end', -window => $userPlatEn );
$userPlatEn->bind( "", sub
{
return if ( $userPlatEn->cget( -state ) eq 'disabled' );
$userPlatEn->selectionRange( 0, 'end' );
} );
$userPlatEn->bind( "", sub
{
return if ( $userPlatEn->cget( -state ) eq 'disabled' );
$userPlatDir =~ s/\s/_/g;
$platDir = $userPlatDir;
} );
$inBody->insert( 'end', "\n" );
# Destination "Project" Directory
$inBody->insert( 'end', " : Project Directory: ", '10b' );
$temp = $inBody->Label(
-anchor => 'w',
-background => "#EEEEEE",
-foreground => "#FF0000",
-font => "$helv10b",
-textvariable => \$projDir );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
$inBody->insert( 'end', " " );
$projDefault = $inBody->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => \&AdjustProjState,
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-textvariable => \$startDir,
-variable => \$projDirFlag,
-value => "1" );
$inBody->windowCreate( 'end', -window => $projDefault );
$inBody->insert( 'end', " " );
$projOther = $inBody->Radiobutton(
-activebackground => "#F7DF8F",
-anchor => 'w',
-background => "#EEEEEE",
-command => sub
{
AdjustProjState();
$userProjDir = "???";
$projDir = "???";
},
-font => "$helv10n",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Other: ",
-variable => \$projDirFlag,
-value => "0" );
$inBody->windowCreate( 'end', -window => $projOther );
# User-Input Project Entry
$userProjEn = $inBody->Entry(
-background => "#EEEEEE",
-font => "$helv10n",
-state => 'disabled',
-textvariable => \$userProjDir,
-width => 30 );
$inBody->windowCreate( 'end', -window => $userProjEn );
$userProjEn->bind( "", sub
{
return if ( $userProjEn->cget( -state ) eq 'disabled' );
$userProjEn->selectionRange( 0, 'end' );
} );
$userProjEn->bind( "", sub
{
return if ( $userProjEn->cget( -state ) eq 'disabled' );
$userProjDir =~ s/\s/_/g;
$projDir = $userProjDir;
} );
$inBody->insert( 'end', "\n" );
$inBody->insert( 'end', "\n", '10n' );
# Owner and Group for the Files
$inBody->insert( 'end', " Files' owner: ", '10b' );
$temp = $inBody->Entry(
-background => "#FFFFFF",
-font => "$helv10n",
-state => 'normal',
-textvariable => \$projOwner,
-width => 20 );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', " Files' group: ", '10b' );
$temp = $inBody->Entry(
-background => "#FFFFFF",
-font => "$helv10n",
-state => 'normal',
-textvariable => \$projGroup,
-width => 20 );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n", '10n' );
# Project Title
$inBody->insert( 'end', "\n", '10n' );
$inBody->insert( 'end', "Project Title for Web Pages (no spaces!): ", '10b' );
$projTitleEn = $inBody->Entry(
-background => "#FFFFFF",
-font => "$helv10n",
-textvariable => \$projTitle,
-width => 30 );
$inBody->windowCreate( 'end', -window => $projTitleEn );
$projTitleEn->bind( "", sub
{
$projTitleEn->selectionRange( 0, 'end' );
} );
$projTitleEn->bind( "", sub
{
return if ( $projTitleEn->cget( -state ) eq 'disabled' );
$projTitle =~ s/\s/_/g;
} );
$inBody->insert( 'end', "\n" );
$inBody->insert( 'end', "Example: SomeGame(AGB)\n", '8n' );
# lxr Options
$temp = $inBody->Checkbutton(
-activebackground => "#F7DF8F",
-anchor => 'e',
-background => "#EEEEEE",
-font => "$helv10b",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Use lxr to link up the project",
-variable => \$useLxrFlag );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
# glimpse Options
$temp = $inBody->Checkbutton(
-activebackground => "#F7DF8F",
-anchor => 'e',
-background => "#EEEEEE",
-font => "$helv10b",
-justify => 'left',
-selectcolor => "#FFFF00",
-text => "Use glimpse to index the project (can be any code)",
-variable => \$useGlimpseFlag );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
# Process Project Button
$temp = $inBody->Button(
-activebackground => "#F7DF8F",
-background => "#CCBB99",
-command => sub
{
my $statusFlag = 1;
$outBody->configure( -state => 'normal' );
$statusFlag = CheckForErrors();
ProcessProject() if ( $statusFlag );
$outBody->configure( -state => 'disabled' );
},
-font => "$helv8b",
-text => "Process the Project" );
$inBody->windowCreate( 'end', -window => $temp );
# Adds space between buttons
$inBody->insert( 'end', " " );
# Quit Button
$temp = $inBody->Button(
-activebackground => "#F7DF8F",
-background => "#CCBB99",
-command => sub { exit; },
-font => "$helv8b",
-text => "Quit" );
$inBody->windowCreate( 'end', -window => $temp );
$inBody->insert( 'end', "\n" );
# Output Window Button
$inBody->insert( 'end', "\n", '8n' );
$showOutWinBn = $inBody->Button(
-activebackground => "#F7DF8F",
-background => "#CCBB99",
-disabledforeground => "#EEEEEE",
-command => \&OpenOutWin,
-font => "$helv8b",
-text => "Show Ouput Window" )
->pack(
-padx => 10,
-side => 'top' );
$inBody->windowCreate( 'end', -window => $showOutWinBn );
$inBody->insert( 'end', "\n" );
# Affects static elements but not inserted interactive widgets.
$inBody->configure( -state => 'disabled' ); # Disables user mucking with non-interactive widgets.
# Output Window
$outWin = $inWin->Toplevel();
$outWin->title( "Linux File Processing: Output" );
$outWin->configure( -background => "#DDDDDD" );
# Prevent inadvertent destruction of the window (withdraw it instead).
$outWin->protocol( 'WM_DELETE_WINDOW', sub
{
$outWin->withdraw;
} );
# Adjust window per screen resolution.
$outWin->geometry( $width . "x" . $height . "+" . ( 27 + $width ) . "+15" );
# Output Title Frame
$outTitleFr = $outWin->Frame( -background => "#DDDDDD" )
->pack(
-fill => 'x',
-pady => 2,
-side => 'top' );
# Output Title
$outTitleFr->Label(
-anchor => 'w',
-background => "#DDDDDD",
-font => "$helv12b",
-text => "Output" )
->pack( -side => 'left' );
# Clear Output Button
$outTitleFr->Button(
-activebackground => "#F7DF8F",
-background => "#CCBB99",
-font => "$helv8b",
-command => sub
{
$outBody->configure( -state => 'normal' );
$outBody->delete( "1.0", 'end' );
$outBody->configure( -state => 'disabled' );
},
-text => "Clear" )
->pack(
-padx => 10,
-side => 'right' );
# Visual Separator
$outWin->Canvas(
-background => "#888888",
-height => 2,
-highlightthickness => 0,
-takefocus => 0 )
->pack(
-fill => 'x',
-pady => 2,
-side => 'top' );
# Output Area
$outBody = $outWin->Scrolled( "Text",
-background => "#DDDDDD",
-cursor => 'left_ptr',
-font => "$helv10n",
-relief => 'flat',
-scrollbars => 'osoe',
-wrap => 'word' )
->pack(
-expand => 1,
-fill => 'both',
-side => 'top' );
$outBody->tagConfigure( '10n', -font => "$helv10n" );
$outBody->tagConfigure( '10b', -font => "$helv10b" );
$outBody->tagConfigure( '12n', -font => "$helv12n" );
$outBody->tagConfigure( '12b', -font => "$helv12b" );
$outBody->tagConfigure( 'c10n', -font => "$cour10n" );
$outBody->tagConfigure( 'c10b', -font => "$cour10b" );
# Screen size warning
if ( $inWin->screenwidth() < 800 )
{
$outBody->insert( 'end', "Screen Size\n", '12b' );
$outBody->insert( 'end', "WARNING: ", '10b' );
$outBody->insert( 'end', "Screen size is small! " .
"You may have problems using this program at this resolution.\n", '10n' );
}
# Initial Message
$outBody->insert( 'end', "Output messages will appear here.\n" );
# User cannot change output contents.
$outBody->configure( -state => 'disabled' );
# Binding to toggle Show Output Window button (in Input Window) on and off.
# Binding is mapped to a specific widget in $outWin rather than $outWin itself
# (as otherwise the binding is triggered as each child in $outWin is mapped
# and unmapped).
$outBody->bind( "