#!/usr/bin/perl

#
# Anson Schall
# txttopuz.pl v1.2
#
# A simple tool to create Across Lite formatted crossword puzzle
# files from the King Features text format. Across Lite will not
# open files created by txttopuz.pl because they are missing the
# proper checksums. Most third-party programs such as Black Ink,
# however, can read them.
#
#
# Changelog
#
# v1.2
# - Fixed a bug causing the clue list to be incorrect.
#
# v1.1
# - Added latin1 encoding to fix problems with non-ASCII characters
#   in clue list.
# - Rewrote regex code for clarity.
#
# v1.0
# - Initial release.
#

use encoding 'latin1';

# Determine the input and output filenames

if($#ARGV !~ /^[01]$/) {
    die("usage: txttopuz yyyymmdd.txt [output.puz]\n");
}
$fileIn = @ARGV[0];
if(defined($ARGV[1])) {
    $fileOut = $ARGV[1];
} else {
    $fileOut = $fileIn;
    $fileOut =~ s/\.txt$//;
    $fileOut .= ".puz";
}


# Open the file and read into memory

open fp, $fileIn or die("failed to open $fileIn for reading\n");
$file = "";
while(<fp>) {
    s/\r/\n/g;    # change line endings
    $file .= $_;
}
close fp;


# Filter garbage out of input
# and split into sections

$file =~ s/^[^A-Z#]*//;      # unneeded crap at start of file
$file =~ s/\|\s*$//gm;       # trailing `|'s at ends of most lines
$file =~ s/\n\s*$//gms;      # get rid of empty lines

($grid, $across, $down) = split /\n{/s, $file;
$grid =~ s/ //g;                                # fix up the solution grid
$grid =~ s/#/./g;                               # "
s/^(\d)\./00$1/gm foreach (($across, $down));   # prepare for sort
s/^(\d\d)\./0$1/gm foreach (($across, $down));  # "
s/^(\d\d\d)\./$1/gm foreach (($across, $down)); # "
$across =~ s/^(\d+)/$1A/gm;                     # "
$down =~ s/^(\d+)/$1D/gm;                       # "

@solution = split /\n/s, $grid;
@clues = sort(split /\n/s, $across . "\n" . $down);
s/^[^ ]+ //g foreach (@clues);  # remove the clue number and direction
s/  +/ /g foreach (@clues);     # clean up sloppy spacing in clues


# Setting the proper date requires a
# filename formatted like yyyymmdd.txt

@months = qw/ winkWinkNudgeNudgeSayNoMore January February March April May June July August September October November December /;
if ($fileIn =~ /(\d\d\d\d)(\d\d)(\d\d)/) {
    $year = $1;
    $month = $months[$2];
    $date = $3;
    $date =~ s/^0//;  # remove leading zero from date
    $title = "$month $date, $year";
} else {
    $title = "Unknown date";
}
$author = "Thomas Joseph";
$copyright = "$year King Features Syndicate";


# Creating the actual binary output now

open fp, ">$fileOut";
print fp "\x00" x 2;
print fp "ACROSS&DOWN";             # file magic
print fp "\x00" x 31;
print fp chr(length($solution[0])); # width
print fp chr($#solution + 1);       # height
print fp chr($#clues + 1);          # number of clues
print fp "\x00" x 5;
print fp foreach @solution;         # solution grid
s/[A-Z]/-/g and print fp foreach @solution;           # progress grid
print fp "$title\x00$author\x00\xa9 $copyright\x00";  # puzzle title, copyright, etc
print fp and print fp "\x00" foreach (@clues);        # clues
print fp "\x00";                    # EOF
close fp;
