/* #ident "@(#)g3.c	3.1 95/08/30 Copyright (c) Gert Doering" */

#include "config.h"

#include <stdlib.h>
#include <stdio.h>

#include <glib.h>

#include "g3.h"

struct g3code t_white[66] = {
{ 0,   0, 0x0ac,  8 },
{ 0,   1, 0x038,  6 },
{ 0,   2, 0x00e,  4 },
{ 0,   3, 0x001,  4 },
{ 0,   4, 0x00d,  4 },
{ 0,   5, 0x003,  4 },
{ 0,   6, 0x007,  4 },
{ 0,   7, 0x00f,  4 },
{ 0,   8, 0x019,  5 },
{ 0,   9, 0x005,  5 },
{ 0,  10, 0x01c,  5 },
{ 0,  11, 0x002,  5 },
{ 0,  12, 0x004,  6 },
{ 0,  13, 0x030,  6 },
{ 0,  14, 0x00b,  6 },
{ 0,  15, 0x02b,  6 },
{ 0,  16, 0x015,  6 },
{ 0,  17, 0x035,  6 },
{ 0,  18, 0x072,  7 },
{ 0,  19, 0x018,  7 },
{ 0,  20, 0x008,  7 },
{ 0,  21, 0x074,  7 },
{ 0,  22, 0x060,  7 },
{ 0,  23, 0x010,  7 },
{ 0,  24, 0x00a,  7 },
{ 0,  25, 0x06a,  7 },
{ 0,  26, 0x064,  7 },
{ 0,  27, 0x012,  7 },
{ 0,  28, 0x00c,  7 },
{ 0,  29, 0x040,  8 },
{ 0,  30, 0x0c0,  8 },
{ 0,  31, 0x058,  8 },
{ 0,  32, 0x0d8,  8 },
{ 0,  33, 0x048,  8 },
{ 0,  34, 0x0c8,  8 },
{ 0,  35, 0x028,  8 },
{ 0,  36, 0x0a8,  8 },
{ 0,  37, 0x068,  8 },
{ 0,  38, 0x0e8,  8 },
{ 0,  39, 0x014,  8 },
{ 0,  40, 0x094,  8 },
{ 0,  41, 0x054,  8 },
{ 0,  42, 0x0d4,  8 },
{ 0,  43, 0x034,  8 },
{ 0,  44, 0x0b4,  8 },
{ 0,  45, 0x020,  8 },
{ 0,  46, 0x0a0,  8 },
{ 0,  47, 0x050,  8 },
{ 0,  48, 0x0d0,  8 },
{ 0,  49, 0x04a,  8 },
{ 0,  50, 0x0ca,  8 },
{ 0,  51, 0x02a,  8 },
{ 0,  52, 0x0aa,  8 },
{ 0,  53, 0x024,  8 },
{ 0,  54, 0x0a4,  8 },
{ 0,  55, 0x01a,  8 },
{ 0,  56, 0x09a,  8 },
{ 0,  57, 0x05a,  8 },
{ 0,  58, 0x0da,  8 },
{ 0,  59, 0x052,  8 },
{ 0,  60, 0x0d2,  8 },
{ 0,  61, 0x04c,  8 },
{ 0,  62, 0x0cc,  8 },
{ 0,  63, 0x02c,  8 },
{ 0, -1, 0, 11 },		/* 11 0-bits == EOL, special handling */
{ 0, -1, 0, 0 }};		/* end of table */

/* make-up codes white */
struct g3code m_white[28] = {
{ 0,  64, 0x01b,  5 },
{ 0, 128, 0x009,  5 },
{ 0, 192, 0x03a,  6 },
{ 0, 256, 0x076,  7 },
{ 0, 320, 0x06c,  8 },
{ 0, 384, 0x0ec,  8 },
{ 0, 448, 0x026,  8 },
{ 0, 512, 0x0a6,  8 },
{ 0, 576, 0x016,  8 },
{ 0, 640, 0x0e6,  8 },
{ 0, 704, 0x066,  9 },
{ 0, 768, 0x166,  9 },
{ 0, 832, 0x096,  9 },
{ 0, 896, 0x196,  9 },
{ 0, 960, 0x056,  9 },
{ 0,1024, 0x156,  9 },
{ 0,1088, 0x0d6,  9 },
{ 0,1152, 0x1d6,  9 },
{ 0,1216, 0x036,  9 },
{ 0,1280, 0x136,  9 },
{ 0,1344, 0x0b6,  9 },
{ 0,1408, 0x1b6,  9 },
{ 0,1472, 0x032,  9 },
{ 0,1536, 0x132,  9 },
{ 0,1600, 0x0b2,  9 },
{ 0,1664, 0x006,  6 },
{ 0,1728, 0x1b2,  9 },
{ 0,  -1, 0, 0} };


struct g3code t_black[66] = {
{ 0,   0, 0x3b0, 10 },
{ 0,   1, 0x002,  3 },
{ 0,   2, 0x003,  2 },
{ 0,   3, 0x001,  2 },
{ 0,   4, 0x006,  3 },
{ 0,   5, 0x00c,  4 },
{ 0,   6, 0x004,  4 },
{ 0,   7, 0x018,  5 },
{ 0,   8, 0x028,  6 },
{ 0,   9, 0x008,  6 },
{ 0,  10, 0x010,  7 },
{ 0,  11, 0x050,  7 },
{ 0,  12, 0x070,  7 },
{ 0,  13, 0x020,  8 },
{ 0,  14, 0x0e0,  8 },
{ 0,  15, 0x030,  9 },
{ 0,  16, 0x3a0, 10 },
{ 0,  17, 0x060, 10 },
{ 0,  18, 0x040, 10 },
{ 0,  19, 0x730, 11 },
{ 0,  20, 0x0b0, 11 },
{ 0,  21, 0x1b0, 11 },
{ 0,  22, 0x760, 11 },
{ 0,  23, 0x0a0, 11 },
{ 0,  24, 0x740, 11 },
{ 0,  25, 0x0c0, 11 },
{ 0,  26, 0x530, 12 },
{ 0,  27, 0xd30, 12 },
{ 0,  28, 0x330, 12 },
{ 0,  29, 0xb30, 12 },
{ 0,  30, 0x160, 12 },
{ 0,  31, 0x960, 12 },
{ 0,  32, 0x560, 12 },
{ 0,  33, 0xd60, 12 },
{ 0,  34, 0x4b0, 12 },
{ 0,  35, 0xcb0, 12 },
{ 0,  36, 0x2b0, 12 },
{ 0,  37, 0xab0, 12 },
{ 0,  38, 0x6b0, 12 },
{ 0,  39, 0xeb0, 12 },
{ 0,  40, 0x360, 12 },
{ 0,  41, 0xb60, 12 },
{ 0,  42, 0x5b0, 12 },
{ 0,  43, 0xdb0, 12 },
{ 0,  44, 0x2a0, 12 },
{ 0,  45, 0xaa0, 12 },
{ 0,  46, 0x6a0, 12 },
{ 0,  47, 0xea0, 12 },
{ 0,  48, 0x260, 12 },
{ 0,  49, 0xa60, 12 },
{ 0,  50, 0x4a0, 12 },
{ 0,  51, 0xca0, 12 },
{ 0,  52, 0x240, 12 },
{ 0,  53, 0xec0, 12 },
{ 0,  54, 0x1c0, 12 },
{ 0,  55, 0xe40, 12 },
{ 0,  56, 0x140, 12 },
{ 0,  57, 0x1a0, 12 },
{ 0,  58, 0x9a0, 12 },
{ 0,  59, 0xd40, 12 },
{ 0,  60, 0x340, 12 },
{ 0,  61, 0x5a0, 12 },
{ 0,  62, 0x660, 12 },
{ 0,  63, 0xe60, 12 },
{ 0,  -1, 0x000, 11 },
{ 0,  -1, 0, 0 } };

struct g3code m_black[28] = {
{ 0,  64, 0x3c0, 10 },
{ 0, 128, 0x130, 12 },
{ 0, 192, 0x930, 12 },
{ 0, 256, 0xda0, 12 },
{ 0, 320, 0xcc0, 12 },
{ 0, 384, 0x2c0, 12 },
{ 0, 448, 0xac0, 12 },
{ 0, 512, 0x6c0, 13 },
{ 0, 576,0x16c0, 13 },
{ 0, 640, 0xa40, 13 },
{ 0, 704,0x1a40, 13 },
{ 0, 768, 0x640, 13 },
{ 0, 832,0x1640, 13 },
{ 0, 896, 0x9c0, 13 },
{ 0, 960,0x19c0, 13 },
{ 0,1024, 0x5c0, 13 },
{ 0,1088,0x15c0, 13 },
{ 0,1152, 0xdc0, 13 },
{ 0,1216,0x1dc0, 13 },
{ 0,1280, 0x940, 13 },
{ 0,1344,0x1940, 13 },
{ 0,1408, 0x540, 13 },
{ 0,1472,0x1540, 13 },
{ 0,1536, 0xb40, 13 },
{ 0,1600,0x1b40, 13 },
{ 0,1664, 0x4c0, 13 },
{ 0,1728,0x14c0, 13 },
{ 0,  -1, 0, 0 } };

void tree_add_node( struct g3_tree *p, struct g3code * g3c,
		        int bit_code, int bit_length )
{
int i;

    if ( bit_length <= FBITS )		/* leaf (multiple bits) */
    {
	g3c->nr_bits = bit_length;	/* leaf tag */

	if ( bit_length == FBITS )	/* full width */
	{
	    p->nextb[ bit_code ] = (struct g3_tree *) g3c;
	}
	else				/* fill bits */
	  for ( i=0; i< ( 1 << (FBITS-bit_length)); i++ )
	  {
	    p->nextb[ bit_code + ( i << bit_length ) ] = (struct g3_tree *) g3c;
	  }
    }
    else				/* node */
    {
    struct g3_tree *p2;

	p2 = p->nextb[ bit_code & BITM ];
	if ( p2 == 0 )			/* no sub-node exists */
	{
	    p2 = p->nextb[ bit_code & BITM ] =
		( struct g3_tree * ) calloc( 1, sizeof( struct g3_tree ));
	    if ( p2 == NULL ) { perror( "malloc 3" ); exit(11); }
	    p2->nr_bits = 0;		/* node tag */

	}
	if ( p2->nr_bits != 0 )
	{
	    g_printerr ("internal table setup error\n" ); exit(6);
	}
	tree_add_node( p2, g3c, bit_code >> FBITS, bit_length - FBITS );
    }
}

void build_tree (struct g3_tree ** p, struct g3code * c )
{
    if ( *p == NULL )
    {
	(*p) = (struct g3_tree *) calloc( 1, sizeof(struct g3_tree) );
	if ( *p == NULL ) { perror( "malloc(1)" ); exit(10); }

	(*p)->nr_bits=0;
    }

    while ( c->bit_length != 0 )
    {
	tree_add_node( *p, c, c->bit_code, c->bit_length );
	c++;
    }
}

void init_byte_tab (int reverse, int byte_tab[] )
{
int i;
    if ( reverse ) for ( i=0; i<256; i++ ) byte_tab[i] = i;
    else
      for ( i=0; i<256; i++ )
	     byte_tab[i] = ( ((i & 0x01) << 7) | ((i & 0x02) << 5) |
			     ((i & 0x04) << 3) | ((i & 0x08) << 1) |
			     ((i & 0x10) >> 1) | ((i & 0x20) >> 3) |
			     ((i & 0x40) >> 5) | ((i & 0x80) >> 7) );
}
