#!/usr/bin/perl
#  makeumap.in version 0.8
#  yutex package - Unicode Editor for the X Window System (and Linux) 
#
#  Author: gsinai@iname.com (Gaspar Sinai)
#  Copyright (C) 1997  Gaspar Sinai
#
#  yutex version 0.8 Copyright (C) 5th November 1997, Tokyo Japan  Gaspar Sinai
#
#  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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#---
#!/usr/local/bin/perl
# createMap.pl
# Gaspar Sinai <gsinai@gol.com>
# this one should create a map between unicode and the current decoding.
# The map may start and end early - late.

$shiftNum = 0;
if ($#ARGV >= 0 && $ARGV[0] eq "-high")
{
	$shiftNum = 1;
	shift;
}

#
# We can specify the column number for the local code
# The unicode will always be the last column.
#
if ($#ARGV != 1 && $#ARGV != 2 && $#ARGV != 3)
{
	print STDERR  "usage: $0 [-shift] file-name map-name [native#] [unicode#]\n";
	print STDERR  "       native# is the column of the native code. (0)\n";
	print STDERR  "       unicode#  is the column of the unicode code. (last row)\n";
	exit (1);
}

$inputFile=$ARGV[0];
$outputFile=$ARGV[1] . "." . "umap";
$alias=$ARGV[1];
$column=0;
$column=$ARGV[2] if ($#ARGV >= 2);
$unicodeColumn=-1;
$unicodeColumn=$ARGV[3] if ($#ARGV ==3);

die "error: can not open $inputFile" unless (open (IN, "< $inputFile"));
die "error: can not open $outputFile" unless (open (OUT, "> $outputFile"));

$localMinL = 2**8-1;
$localMaxL = 0;
$localMinR = 2**8-1;
$localMaxR = 0;

$uniMinL = 2**8-1;
$uniMaxL = 0;
$uniMinR = 2**8-1;
$uniMaxR = 0;

%hexMap = 
(
	"0",0, "1",1,  "2",2, "3",3, "4",4, "5",5, "6",6, "7",7, "8",8, "9",9,
	"a",10, "b", 11, "c",12, "d",13, "e",14, "f",15, 
	"A",10, "B", 11, "C",12, "D",13, "E",14, "F",15, 
);
#
# I arrange everything in rows and colomns to save space
#
while (<IN>)
{
	chop;
	s/#.*$//o;
	split;
	next if ($#_ < 1);
	$localCode = $_[$column];
	if ($unicodeColumn==-1)
	{
		$uniCode = $_[$#_];
	}
	else
	{
		if ($#_ < $unicodeColumn)
		{
			printf (STDERR "error: file has only %d + 1 colums.\n",
				$#_);
			exit (1);
		}
		$uniCode = $_[$unicodeColumn];
	}

	($leftLocal, $rightLocal) = &getLR ($localCode);
	if ($shiftNum==1)
	{
		$leftLocal += 128;
		$rightLocal += 128;
	}
	($leftUni, $rightUni) = &getLR ($uniCode);


	$localMinL = $leftLocal if ($leftLocal < $localMinL);
	$localMinR = $rightLocal if ($rightLocal < $localMinR);

	$localMaxL = $leftLocal if ($leftLocal > $localMaxL);
	$localMaxR = $rightLocal if ($rightLocal > $localMaxR);

	$bigMapLU[$leftLocal * 256 + $rightLocal] = $leftUni*256 + $rightUni;

	$uniMinL = $leftUni if ($leftUni < $uniMinL);
	$uniMinR = $rightUni if ($rightUni < $uniMinR);

	$uniMaxL = $leftUni if ($leftUni > $uniMaxL);
	$uniMaxR = $rightUni if ($rightUni > $uniMaxR);

	$bigMapUL[$leftUni * 256 + $rightUni] = $leftLocal*256 + $rightLocal;
}

close (IN);

@mapLU = &mapIt ($localMinL, $localMaxL, $localMinR, $localMaxR, @bigMapLU);
@mapUL = &mapIt ($uniMinL, $uniMaxL, $uniMinR, $uniMaxR, @bigMapUL);

$mapUL = join (' ', @mapUL);
$mapLU = join (' ', @mapLU);

&fatal unless print OUT <<EDO;
/*
 * <<<<<<<<<<< DO NOT EDIT >>>>>>>>>>>>
 * This file is automatically generated.
 * The map was generated from $inputFile
 *
 */

static char umap_name[]="$alias";

/* Decoding local code into unicode. Array Boundaries */
static unsigned short decode_high_min=$localMinL;
static unsigned short decode_high_max=$localMaxL;
static unsigned short decode_low_min=$localMinR;
static unsigned short decode_low_max=$localMaxR;

static unsigned short decode_matrix[]=$mapLU;

/* Encoding unicode. Array Boundaries */
static unsigned short encode_high_min=$uniMinL;
static unsigned short encode_high_max=$uniMaxL;
static unsigned short encode_low_min=$uniMinR;
static unsigned short encode_low_max=$uniMaxR;

static unsigned short encode_matrix[]=$mapUL;

EDO
exit (0);

#
# get the left and the right portion 
#
sub
getLR
{
	local ($number) = $_[0];

	$_ = $_[0];

	if (/^0x([0-9a-zA-Z]+)/)
	{
		$number=0;
		$_=$1;
		while (/([0-9a-zA-Z])(.*)/)
		{
			die "internal error $1" if (!defined ($hexMap{$1}));
			$number = $number * 16 + $hexMap{$1};
			$_ = $2;
		}
	}
	
	local ($left, $right) = (int($number/256),  $number%256);
	return ($left,  $right); 
}

#
# Produce a usable ascii output for the c program.
#
sub
mapIt
{
	local ($minL, $maxL, $minR, $maxR, @array) = @_;
	local ($count) = 0;
	local ($i, $j, $value, $position);
	local ($charsPerRow) = $maxL - $minL + 1;
	local (@retVle);

	$position =0;

	@retVle = "{";

	for ($i = $minL; $i <= $maxL; $i++)
	{
		for ($j = $minR; $j <= $maxR; $j++)
		{
			$value =  $array[($i << 8) + $j];
			$value=0 if (!defined ($value));
			push (@retVle, "\n")  if ($position % 8 ==0);
			if ($value>-10 && $value<10)
			{
				push (@retVle, sprintf ("%d,", $value));
			}
			else
			{
				push (@retVle, sprintf ("0x%x,", $value));
			}
			$position++;
		}
	}
	push (@retVle, "}");
	return (@retVle);
}

#
# Fatal error handler
#
sub
fatal
{
	close (OUT);
	unlink ($outputFile);
	exit (1);
}
