/*->c.g3dec */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>


#include "h.os"
#include "h.wimp"
#include "h.bbc"
#include "h.flex"

#include "h.Drawlevel0"


#include "h.fsx"
#include "h.wos"
#include "h.strdef"
#include "h.pic"
#include "h.buffer"

#include "h.code"

#include "h.g3dec"



#define EOL_CODE     -1
#define INVALID_CODE -2


       int g3bit_number;
       int g3code_byte;
static int color;
static int column_limit;
static int row_limit;
static int row_number;
static int column_number;
static int g3bitrev;

       int   g3finished;
       getfn g3getbyte;



/* return -1 when image finished */

static int new_row(void)
{
 if(column_number)
 {
  writenewrow();
  color=WHITE;
  if(++row_number>=row_limit) return (-1);
  column_number=0;
  return(0);
 }
 else 
  return(0);
}



int g3i_newrow(void)
{
 if(column_number)
 {
  color=WHITE;
  if(++row_number>=row_limit) return (-1);
  column_number=0;
  return(0);
 }
 else 
  return(0);
}



static void g3i_checkrow(codestr * cx)
{
 int runlength;

 if(column_number<column_limit)
 {
  runlength=column_limit-column_number;

  if(color==WHITE || !cx->run) cx->runs[cx->run++]=runlength;
  else                         cx->runs[cx->run-1]+=runlength;
 }
}



static char bitrev[256]=
{
0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,240,8,136,72,200,40,168,104,232,24,152,88,216,56,184,120,248,4,132,68,196,36,164,100,228,20,148,84,212,52,180,116,244,12,140,76,204,44,172,108,236,28,156,92,220,60,188,124,252,2,130,66,194,34,162,98,226,18,146,82,210,50,178,114,242,10,138,74,202,42,170,106,234,26,154,90,218,58,186,122,250,6,134,70,198,38,166,102,230,22,150,86,214,54,182,118,246,14,142,78,206,46,174,110,238,30,158,94,222,62,190,126,254,1,129,65,193,33,161,97,225,17,145,81,209,49,177,113,241,9,137,73,201,41,169,105,233,25,153,89,217,57,185,121,249,5,133,69,197,37,165,101,229,21,149,85,213,53,181,117,245,13,141,77,205,45,173,109,237,29,157,93,221,61,189,125,253,3,131,67,195,35,163,99,227,19,147,83,211,51,179,115,243,11,139,75,203,43,171,107,235,27,155,91,219,59,187,123,251,7,135,71,199,39,167,103,231,23,151,87,215,55,183,119,247,15,143,79,207,47,175,111,239,31,159,95,223,63,191,127,255
};





os_error * g3bitep;
buffer   * g3bitbuf;


int g3bit_refill(void)
{
 g3bitep=g3getbyte(g3bitbuf,&g3code_byte);

 if(g3code_byte==EOF)
 {
  g3code_byte=0;
  g3finished=1;
 }
 else
 if(g3bitrev) g3code_byte=bitrev[g3code_byte];

 g3bit_number=128;

 return(g3code_byte & g3bit_number);
}



#define next_bit() ((g3bit_number>>=1)?(g3code_byte & g3bit_number):g3bit_refill())



static int decode_black_word()
{
  if (next_bit ()) /* 1... */
  {
    if (next_bit ()) /* 11 */ return (2);
    else /* 10 */ return (3);
  }
  else /* 0... */
  {
    if (next_bit ()) /* 01... */
    {
      if (next_bit ()) /* 011 */ return (4);
      else /* 010 */ return (1);
    }
    else /* 00... */
    {
      if (next_bit ()) /* 001... */
      {
        if (next_bit ()) /* 0011 */ return (5);
        else /* 0010 */ return (6);
      }
      else /* 000... */
      {
        if (next_bit ()) /* 0001... */
        {
          if (next_bit ()) /* 0001 1 */ return (7);
          else /* 0001 0... */
          {
            if (next_bit ()) /* 0001 01 */ return (8);
            else /* 0001 00 */ return (9);
          }
        }
        else /* 0000... */
        {
          if (next_bit ()) /* 0000 1... */
          {
            if (next_bit ()) /* 0000 11... */
            {
              if (next_bit ()) /* 0000 111 */ return (12);
              else /* 0000 110... */
              {
                if (next_bit ()) /* 0000 1101... */
                {
                  if (next_bit ()) /* 0000 1101 1... */
                  {
                    if (next_bit ()) /* 0000 1101 11 */ return (0);
                    else /* 0000 1101 10... */
                    {
                      if (next_bit ()) /* 0000 1101 101... */
                      {
                        if (next_bit ()) /* 0000 1101 1011 */ return (43);
                        else /* 0000 1101 1010 */ return (42);
                      }
                      else /* 0000 1101 100 */ return (21);
                    }
                  }
                  else /* 0000 1101 0... */
                  {
                    if (next_bit ()) /* 0000 1101 01... */
                    {
                      if (next_bit ()) /* 0000 1101 011... */
                      {
                        if (next_bit ()) /* 0000 1101 0111 */ return (39);
                        else /* 0000 1101 0110 */ return (38);
                      }
                      else /* 0000 1101 010... */
                      {
                        if (next_bit ()) /* 0000 1101 0101 */ return (37);
                        else /* 0000 1101 0100 */ return (36);
                      }
                    }
                    else /* 0000 1101 00... */
                    {
                      if (next_bit ()) /* 0000 1101 001... */
                      {
                        if (next_bit ()) /* 0000 1101 0011 */ return (35);
                        else /* 0000 1101 0010 */ return (34);
                      }
                      else /* 0000 1101 000 */ return (20);
                    }
                  }
                }
                else /* 0000 1100... */
                {
                  if (next_bit ()) /* 0000 1100 1... */
                  {
                    if (next_bit ()) /* 0000 1100 11... */
                    {
                      if (next_bit ()) /* 0000 1100 111 */ return (19);
                      else /* 0000 1100 110... */
                      {
                        if (next_bit ()) /* 0000 1100 1101 */ return (29);
                        else /* 0000 1100 1100 */ return (28);
                      }
                    }
                    else /* 0000 1100 10... */
                    {
                      if (next_bit ()) /* 0000 1100 101.. */
                      {
                        if (next_bit ()) /* 0000 1100 1011 */ return (27);
                        else /* 0000 1100 1010 */ return (26);
                      }
                      else /* 0000 1100 100... */
                      {
                        if (next_bit ()) /* 0000 1100 1001 */ return (192);
                        else /* 0000 1100 1000 */ return (128);
                      }
                    }
                  }
                  else /* 0000 1100 0 */ return (15);
                }
              }
            }
            else /* 0000 10... */
            {
              if (next_bit ()) /* 0000 101 */ return (11);
              else /* 0000 100 */ return (10);
            }
          }
          else /* 0000 0... */
          {
            if (next_bit ()) /* 0000 01... */
            {
              if (next_bit ()) /* 0000 011... */
              {
                if (next_bit ()) /* 0000 0111 */ return (14);
                else /* 0000 0110... */
                {
                  if (next_bit ()) /* 0000 0110 1... */
                  {
                    if (next_bit ()) /* 0000 0110 11... */
                    {
                      if (next_bit ()) /* 0000 0110 111 */ return (22);
                      else /* 0000 0110 110... */
                      {
                        if (next_bit ()) /* 0000 0110 1101 */ return (41);
                        else /* 0000 0110 1100 */ return (40);
                      }
                    }
                    else /* 0000 0110 10... */
                    {
                      if (next_bit ()) /* 0000 0110 101... */
                      {
                        if (next_bit ()) /* 0000 0110 1011 */ return (33);
                        else /* 0000 0110 1010 */ return (32);
                      }
                      else /* 0000 0110 100... */
                      {
                        if (next_bit ()) /* 0000 0110 1001 */ return (31);
                        else /* 0000 0110 1000 */ return (30);
                      }
                    }
                  }
                  else /* 0000 0110 0... */
                  {
                    if (next_bit ()) /* 0000 0110 01... */
                    {
                      if (next_bit ()) /* 0000 0110 011... */
                      {
                        if (next_bit ()) /* 0000 0110 0111 */ return (63);
                        else /* 0000 0110 0110 */ return (62);
                      }
                      else /* 0000 0110 010... */
                      {
                        if (next_bit ()) /* 0000 0110 0101 */ return (49);
                        else /* 0000 0110 0100 */ return (48);
                      }
                    }
                    else /* 0000 0110 00 */ return (17);
                  }
                }
              }
              else /* 0000 010... */
              {
                if (next_bit ()) /* 0000 0101... */
                {
                  if (next_bit ()) /* 0000 0101 1... */
                  {
                    if (next_bit ()) /* 0000 0101 11 */ return (16);
                    else /* 0000 0101 10... */
                    {
                      if (next_bit ()) /* 0000 0101 101... */
                      {
                        if (next_bit ()) /* 0000 0101 1011 */ return (256);
                        else /* 0000 0101 1010 */ return (61);
                      }
                      else /* 0000 0101 100... */
                      {
                        if (next_bit ()) /* 0000 0101 1001 */ return (58);
                        else /* 0000 0101 1000 */ return (57);
                      }
                    }
                  }
                  else /* 0000 0101 0... */
                  {
                    if (next_bit ()) /* 0000 0101 01... */
                    {
                      if (next_bit ()) /* 0000 0101 011... */
                      {
                        if (next_bit ()) /* 0000 0101 0111 */ return (47);
                        else /* 0000 0101 0110 */ return (46);
                      }
                      else /* 0000 0101 010... */
                      {
                        if (next_bit ()) /* 0000 0101 0101 */ return (45);
                        else /* 0000 0101 0100 */ return (44);
                      }
                    }
                    else /* 0000 0101 00... */
                    {
                      if (next_bit ()) /* 0000 0101 001... */
                      {
                        if (next_bit ()) /* 0000 0101 0011 */ return (51);
                        else /* 0000 0101 0010 */ return (50);
                      }
                      else /* 0000 0101 000 */ return (23);
                    }
                  }
                }
                else /* 0000 0100 */ return (13);
              }
            }
            else /* 0000 00... */
            {
              if (next_bit ()) /* 0000 001... */
              {
                if (next_bit ()) /* 0000 0011... */
                {
                  if (next_bit ()) /* 0000 0011 1... */
                  {
                    if (next_bit ()) /* 0000 0011 11 */ return (64);
                    else /* 0000 0011 10... */
                    {
                      if (next_bit ()) /* 0000 0011 101... */
                      {
                        if (next_bit ()) /* 0000 0011 1011... */
                        {
                          if (next_bit ()) /* 0000 0011 1011 1 */ return (1216);
                          else /* 0000 0011 1011 0 */ return (1152);
                        }
                        else /* 0000 0011 1010... */
                        {
                          if (next_bit ()) /* 0000 0011 1010 1 */ return (1088);
                          else /* 0000 0011 1010 0 */ return (1024);
                        }
                      }
                      else /* 0000 0011 100... */
                      {
                        if (next_bit ()) /* 0000 0011 1001... */
                        {
                          if (next_bit ()) /* 0000 0011 1001 1 */ return (960);
                          else /* 0000 0011 1001 0 */ return (896);
                        }
                        else /* 0000 0011 1000 */ return (54);
                      }
                    }
                  }
                  else /* 0000 0011 0... */
                  {
                    if (next_bit ()) /* 0000 0011 01... */
                    {
                      if (next_bit ()) /* 0000 0011 011... */
                      {
                        if (next_bit ()) /* 0000 0011 0111 */ return (53);
                        else /* 0000 0011 0110... */
                        {
                          if (next_bit ()) /* 0000 0011 0110 1 */ return (576);
                          else /* 0000 0011 0110 0 */ return (512);
                        }
                      }
                      else /* 0000 0011 010... */
                      {
                        if (next_bit ()) /* 0000 0011 0101 */ return (448);
                        else /* 0000 0011 0100 */ return (384);
                      }
                    }
                    else /* 0000 0011 00... */
                    {
                      if (next_bit ()) /* 0000 0011 001... */
                      {
                        if (next_bit ()) /* 0000 0011 0011 */ return (320);
                        else /* 0000 0011 0010... */
                        {
                          if (next_bit ()) /* 0000 0011 0010 1 */ return (1728);
                          else /* 0000 0011 0010 0 */ return (1664);
                        }
                      }
                      else /* 0000 0011 000 */ return (25);
                    }
                  }
                }
                else /* 0000 0010... */
                {
                  if (next_bit ()) /* 0000 0010 1... */
                  {
                    if (next_bit ()) /* 0000 0010 11... */
                    {
                      if (next_bit ()) /* 0000 0010 111 */ return (24);
                      else /* 0000 0010 110... */
                      {
                        if (next_bit ()) /* 0000 0010 1101... */
                        {
                          if (next_bit ()) /* 0000 0010 1101 1 */ return (1600);
                          else /* 0000 0010 1101 0 */ return (1536);
                        }
                        else /* 0000 0010 1100 */ return (60);
                      }
                    }
                    else /* 0000 0010 10... */
                    {
                      if (next_bit ()) /* 0000 0010 101... */
                      {
                        if (next_bit ()) /* 0000 0010 1011 */ return (59);
                        else /* 0000 0010 1010... */
                        {
                          if (next_bit ()) /* 0000 0010 1010 1 */ return (1472);
                          else /* 0000 0010 1010 0 */ return (1408);
                        }
                      }
                      else /* 0000 0010 100... */
                      {
                        if (next_bit ()) /* 0000 0010 1001... */
                        {
                          if (next_bit ()) /* 0000 0010 1001 1 */ return (1344);
                          else /* 0000 0010 1001 0 */ return (1280);
                        }
                        else /* 0000 0010 1000 */ return (56);
                      }
                    }
                  }
                  else /* 0000 0010 0... */
                  {
                    if (next_bit ()) /* 0000 0010 01... */
                    {
                      if (next_bit ()) /* 0000 0010 011... */
                      {
                        if (next_bit ()) /* 0000 0010 0111 */ return (55);
                        else /* 0000 0010 0110... */
                        {
                          if (next_bit ()) /* 0000 0010 0110 1 */ return (832);
                          else /* 0000 0010 0110 0 */ return (768);
                        }
                      }
                      else /* 0000 0010 010... */
                      {
                        if (next_bit ()) /* 0000 0010 0101... */
                        {
                          if (next_bit ()) /* 0000 0010 0101 1 */ return (704);
                          else /* 0000 0010 0101 0 */ return (640);
                        }
                        else /* 0000 0010 0100 */ return (52);
                      }
                    }
                    else /* 0000 0010 00 */ return (18);
                  }
                }
              }
              else /* 0000 000... */
              {
                if (next_bit ()) /* 0000 0001... */
                {
                  if (next_bit ()) /* 0000 0001 1... */
                  {
                    if (next_bit ()) /* 0000 0001 11... */
                    {
                      if (next_bit ()) /* 0000 0001 111... */
                      {
                        if (next_bit ()) /* 0000 0001 1111 */ return (2560);
                        else /* 0000 0001 1110 */ return (2496);
                      }
                      else /* 0000 0001 110... */
                      {
                        if (next_bit ()) /* 0000 0001 1101 */ return (2432);
                        else /* 0000 0001 1100 */ return (2368);
                      }
                    }
                    else /* 0000 0001 10... */
                    {
                      if (next_bit ()) /* 0000 0001 101 */ return (1920);
                      else /* 0000 0001 100 */ return (1856);
                    }
                  }
                  else /* 0000 0001 0... */
                  {
                    if (next_bit ()) /* 0000 0001 01... */
                    {
                      if (next_bit ()) /* 0000 0001 011... */
                      {
                        if (next_bit ()) /* 0000 0001 0111 */ return (2304);
                        else /* 0000 0001 0110 */ return (2240);
                      }
                      else /* 0000 0001 010... */
                      {
                        if (next_bit ()) /* 0000 0001 0101 */ return (2176);
                        else /* 0000 0001 0100 */ return (2112);
                      }
                    }
                    else /* 0000 0001 00... */
                    {
                      if (next_bit ()) /* 0000 0001 001... */
                      {
                        if (next_bit ()) /* 0000 0001 0011 */ return (2048);
                        else /* 0000 0001 0010 */ return (1984);
                      }
                      else /* 0000 0001 000 */ return (1792);
                    }
                  }
                }
                else /* 0000 0000... */
                {
                  if (next_bit ()) /* 0000 0000 1 */ return (INVALID_CODE);
                  else /* 0000 0000 0... */
                  {
                    if (next_bit ()) /* 0000 0000 01 */ return (INVALID_CODE);
                    else /* 0000 0000 00... */
                    {
                      if (next_bit ()) /* 0000 0000 001 */
                                                        return (INVALID_CODE);
                      else /* 0000 0000 000... */
                      {
                        if (next_bit ()) /* 0000 0000 0001 */ return (EOL_CODE);
                        else /* 0000 0000 0000 */ /* return (INVALID_CODE); */
                          /* normally this is an invalid code, but *if* we
                                assume the file has no errors, then we can
                                greatly simplify pad stripping with the
                                following... */
                          while(!g3bitep && !g3finished)
                                  if(next_bit()) return (EOL_CODE);
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

 return(INVALID_CODE);
}






/*
 *      return the length of the next run, assumed to be black
 */

os_error * decode_black_run(int * runlength)
{
 int        cumulative;
 int        code_value;

 g3bitep=NULL;
 cumulative=0;

 while(!g3finished)
 {
  code_value=decode_black_word();

  cumulative+=code_value;

  if(code_value<0)
  {
   *runlength=code_value;
   return(g3bitep);
  }
  if(code_value<64)
  {
   *runlength=cumulative;
   return(g3bitep);
  }
 }
 return(g3bitep);
}



static int decode_white_word ()
{
  if (next_bit ()) /* 1... */
  {
    if (next_bit ()) /* 11... */
    {
      if (next_bit ()) /* 111... */
      {
        if (next_bit ()) /* 1111 */ return (7);
        else /* 1110 */ return (6);
      }
      else /* 110... */
      {
        if (next_bit ()) /* 1101... */
        {
          if (next_bit ()) /* 1101 1 */ return (64);
          else /* 1101 0... */
          {
            if (next_bit ()) /* 1101 01 */ return (15);
            else /* 1101 00 */ return (14);
          }
        }
        else /* 1100 */ return (5);
      }
    }
    else /* 10... */
    {
      if (next_bit ()) /* 101... */
      {
        if (next_bit ()) /* 1011 */ return (4);
        else /* 1010... */
        {
          if (next_bit ()) /* 10101... */
          {
            if (next_bit ()) /* 101011 */ return (17);
            else /* 101010 */ return (16);
          }
          else /* 10100 */ return (9);
        }
      }
      else /* 100... */
      {
        if (next_bit ()) /* 1001... */
        {
          if (next_bit ()) /* 10011 */ return (8);
          else /* 10010 */ return (128);
        }
        else /* 1000 */ return (3);
      }
    }
  }
  else /* 0... */
  {
    if (next_bit ()) /* 01... */
    {
      if (next_bit ()) /* 011... */
      {
        if (next_bit ()) /* 0111 */ return (2);
        else /* 0110... */
        {
          if (next_bit ()) /* 01101... */
          {
            if (next_bit ()) /* 011011... */
            {
              if (next_bit ()) /* 0110111 */ return (256);
              else /* 0110110... */
              {
                if (next_bit ()) /* 01101101... */
                {
                  if (next_bit ()) /* 011011011 */ return (1408);
                  else /* 011011010 */ return (1344);
                }
                else /* 01101100... */
                {
                  if (next_bit ()) /* 011011001 */ return (1280);
                  else /* 011011000 */ return (1216);
                }
              }
            }
            else /* 011010... */
            {
              if (next_bit ()) /* 0110101... */
              {
                if (next_bit ()) /* 01101011... */
                {
                  if (next_bit ()) /* 011010111 */ return (1152);
                  else /* 011010110 */ return (1088);
                }
                else /* 01101010... */
                {
                  if (next_bit ()) /* 011010101 */ return (1024);
                  else /* 011010100 */ return (960);
                }
              }
              else /* 0110100... */
              {
                if (next_bit ()) /* 01101001... */
                {
                  if (next_bit ()) /* 011010011 */ return (896);
                  else /* 011010010 */ return (832);
                }
                else /* 01101000 */ return (576);
              }
            }
          }
          else /* 01100... */
          {
            if (next_bit ()) /* 011001... */
            {
              if (next_bit ()) /* 0110011... */
              {
                if (next_bit ()) /* 01100111 */ return (640);
                else /* 01100110 */
                {
                  if (next_bit ()) /* 011001101 */ return (768);
                  else /* 011001100 */ return (704);
                }
              }
              else /* 0110010 */
              {
                if (next_bit ()) /* 01100101 */ return (512);
                else /* 01100100 */ return (448);
              }
            }
            else /* 011000 */ return (1664);
          }
        }
      }
      else /* 010... */
      {
        if (next_bit ()) /* 0101... */
        {
          if (next_bit ()) /* 01011... */
          {
            if (next_bit ()) /* 010111 */ return (192);
            else /* 010110... */
            {
              if (next_bit ()) /* 0101101... */
              {
                if (next_bit ()) /* 01011011 */ return (58);
                else /* 01011010 */ return (57);
              }
              else /* 0101100... */
              {
                if (next_bit ()) /* 01011001 */ return (56);
                else /* 01011000 */ return (55);
              }
            }
          }
          else /* 01010... */
          {
            if (next_bit ()) /* 010101... */
            {
              if (next_bit ()) /* 0101011 */ return (25);
              else /* 0101010... */
              {
                if (next_bit ()) /* 01010101 */ return (52);
                else /* 01010100 */ return (51);
              }
            }
            else /* 010100... */
            {
              if (next_bit ()) /* 0101001... */
              {
                if (next_bit ()) /* 01010011 */ return (50);
                else /* 01010010 */ return (49);
              }
              else /* 0101000 */ return (24);
            }
          }
        }
        else /* 0100... */
        {
          if (next_bit ()) /* 01001... */
          {
            if (next_bit ()) /* 010011... */
            {
              if (next_bit ()) /* 0100111 */ return (18);
              else /* 0100110... */
              {
                if (next_bit ()) /* 01001101... */
                {
                  if (next_bit ()) /* 010011011 */ return (1728);
                  else /* 010011010 */ return (1600);
                }
                else /* 01001100... */
                {
                  if (next_bit ()) /* 010011001 */ return (1536);
                  else /* 010011000 */ return (1472);
                }
              }
            }
            else /* 010010... */
            {
              if (next_bit ()) /* 0100101... */
              {
                if (next_bit ()) /* 01001011 */ return (60);
                else /* 01001010 */ return (59);
              }
              else /* 0100100 */ return (27);
            }
          }
          else /* 01000 */ return (11);
        }
      }
    }
    else /* 00... */
    {
      if (next_bit ()) /* 001... */
      {
        if (next_bit ()) /* 0011... */
        {
          if (next_bit ()) /* 00111 */ return (10);
          else /* 00110... */
          {
            if (next_bit ()) /* 001101... */
            {
              if (next_bit ()) /* 0011011... */
              {
                if (next_bit ()) /* 00110111 */ return (384);
                else /* 00110110 */ return (320);
              }
              else /* 0011010... */
              {
                if (next_bit ()) /* 00110101 */ return (0);
                else /* 00110100 */ return (63);
              }
            }
            else /* 001100... */
            {
              if (next_bit ()) /* 0011001... */
              {
                if (next_bit ()) /* 00110011 */ return (62);
                else /* 00110010 */ return (61);
              }
              else /* 0011000 */ return (28);
            }
          }
        }
        else /* 0010... */
        {
          if (next_bit ()) /* 00101... */
          {
            if (next_bit ()) /* 001011... */
            {
              if (next_bit ()) /* 0010111 */ return (21);
              else /* 0010110... */
              {
                if (next_bit ()) /* 00101101 */ return (44);
                else /* 00101100 */ return (43);
              }
            }
            else /* 001010... */
            {
              if (next_bit ()) /* 0010101... */
              {
                if (next_bit ()) /* 00101011 */ return (42);
                else /* 00101010 */ return (41);
              }
              else /* 0010100... */
              {
                if (next_bit ()) /* 00101001 */ return (40);
                else /* 00101000 */ return (39);
              }
            }
          }
          else /* 00100... */
          {
            if (next_bit ()) /* 001001... */
            {
              if (next_bit ()) /* 0010011 */ return (26);
              else /* 0010010... */
              {
                if (next_bit ()) /* 00100101 */ return (54);
                else /* 00100100 */ return (53);
              }
            }
            else /* 001000 */ return (12);
          }
        }
      }
      else /* 000... */
      {
        if (next_bit ()) /* 0001... */
        {
          if (next_bit ()) /* 00011... */
          {
            if (next_bit ()) /* 000111 */ return (1);
            else /* 000110... */
            {
              if (next_bit ()) /* 0001101... */
              {
                if (next_bit ()) /* 00011011 */ return (32);
                else /* 00011010 */ return (31);
              }
              else /* 0001100 */ return (19);
            }
          }
          else /* 00010... */
          {
            if (next_bit ()) /* 000101... */
            {
              if (next_bit ()) /* 0001011... */
              {
                if (next_bit ()) /* 00010111 */ return (38);
                else /* 00010110 */ return (37);
              }
              else /* 0001010... */
              {
                if (next_bit ()) /* 00010101 */ return (36);
                else /* 00010100 */ return (35);
              }
            }
            else /* 000100... */
            {
              if (next_bit ()) /* 0001001... */
              {
                if (next_bit ()) /* 00010011 */ return (34);
                else /* 00010010 */ return (33);
              }
              else /* 0001000 */ return (20);
            }
          }
        }
        else /* 0000... */
        {
          if (next_bit ()) /* 00001... */
          {
            if (next_bit ()) /* 000011 */ return (13);
            else /* 000010... */
            {
              if (next_bit ()) /* 0000101... */
              {
                if (next_bit ()) /* 00001011 */ return (48);
                else /* 00001010 */ return (47);
              }
              else /* 0000100 */ return (23);
            }
          }
          else /* 00000... */
          {
            if (next_bit ()) /* 000001... */
            {
              if (next_bit ()) /* 0000011 */ return (22);
              else /* 0000010... */
              {
                if (next_bit ()) /* 00000101 */ return (46);
                else /* 00000100 */ return (45);
              }
            }
            else /* 000000... */
            {
              if (next_bit ()) /* 0000001... */
              {
                if (next_bit ()) /* 00000011 */ return (30);
                else /* 00000010 */ return (29);
              }
              else /* 0000 000... */
              {
                if (next_bit ()) /* 0000 0001... */
                {
                  if (next_bit ()) /* 0000 0001 1... */
                  {
                    if (next_bit ()) /* 0000 0001 11... */
                    {
                      if (next_bit ()) /* 0000 0001 111... */
                      {
                        if (next_bit ()) /* 0000 0001 1111 */ return (2560);
                        else /* 0000 0001 1110 */ return (2496);
                      }
                      else /* 0000 0001 110... */
                      {
                        if (next_bit ()) /* 0000 0001 1101 */ return (2432);
                        else /* 0000 0001 1100 */ return (2368);
                      }
                    }
                    else /* 0000 0001 10... */
                    {
                      if (next_bit ()) /* 0000 0001 101 */ return (1920);
                      else /* 0000 0001 100 */ return (1856);
                    }
                  }
                  else /* 0000 0001 0... */
                  {
                    if (next_bit ()) /* 0000 0001 01... */
                    {
                      if (next_bit ()) /* 0000 0001 011... */
                      {
                        if (next_bit ()) /* 0000 0001 0111 */ return (2304);
                        else /* 0000 0001 0110 */ return (2240);
                      }
                      else /* 0000 0001 010... */
                      {
                        if (next_bit ()) /* 0000 0001 0101 */ return (2176);
                        else /* 0000 0001 0100 */ return (2112);
                      }
                    }
                    else /* 0000 0001 00... */
                    {
                      if (next_bit ()) /* 0000 0001 001... */
                      {
                        if (next_bit ()) /* 0000 0001 0011 */ return (2048);
                        else /* 0000 0001 0010 */ return (1984);
                      }
                      else /* 0000 0001 000 */ return (1792);
                    }
                  }
                }
                else /* 0000 0000... */
                {
                  if (next_bit ()) /* 0000 0000 1 */ return (INVALID_CODE);
                  else /* 0000 0000 0... */
                  {
                    if (next_bit ()) /* 0000 0000 01 */ return (INVALID_CODE);
                    else /* 0000 0000 00... */
                    {
                      if (next_bit ()) /* 0000 0000 001 */
                                                        return (INVALID_CODE);
                      else /* 0000 0000 000... */
                      {
                        if (next_bit ()) /* 0000 0000 0001 */ return (EOL_CODE);
                        else /* 0000 0000 0000 */ /* return (INVALID_CODE); */
                          /* normally this is an invalid code, but *if* we
                                assume the file has no errors, then we can
                                greatly simplify pad stripping with the
                                following... */
                          while(!g3bitep && !g3finished) 
                                        if(next_bit()) return (EOL_CODE);
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

 return (INVALID_CODE);
}



/*
 *      return the length of the next run, assumed to be white 
 */

os_error * decode_white_run(int * runlength)
{
 int        cumulative;
 int        code_value;

 cumulative=0;
 g3bitep=NULL;

 while(!g3finished)
 {
  code_value=decode_white_word();

  cumulative+=code_value;

  if(code_value<0)
  {
   *runlength=code_value;
   return(g3bitep);
  }

  if(code_value<64)
  {
   *runlength=cumulative;
   return(g3bitep);
  }
 }
 return(g3bitep);
}







/* g3i_decode () successively invokes (*p_decode_next_byte) () for each byte
   of the encoded image, and calls (*p_decode_white) () or (*p_decode_black) ()
   as required to return the image contents on a run-by-run basis. */


#define DECBUFSIZE 0x10000

os_error * g3i_decode(int fh,int length,int xpix,int ypix,int bitrev)
{
 os_error * ep;
 int        runlength;
 buffer     xbitbuf;

 g3i_initialize(xpix,ypix,bf_get,bitrev);

 ep=bf_alloc(&xbitbuf,DECBUFSIZE,fh,length);

 g3bitbuf=&xbitbuf;

 if(row_number<row_limit)
 {
  while(!g3finished)
  {
   if(color==WHITE)
   {
    ep=decode_white_run(&runlength);
    if(runlength==-2)
    {

    }
    else
    if(runlength==-1)
    {
     if(new_row())
     { 
      break;
     }
    }
    else
    {
     column_number+=runlength;
     writewhiterun(runlength);
     color=BLACK;
    }
   }
   else
   {
    ep=decode_black_run(&runlength);
    if(runlength==-2)
    {

    }
    else
    if(runlength==-1)
    {
     if(new_row())
     {
      break;
     }
    }
    else
    {
     column_number+=runlength;
     writeblackrun(runlength);
     color=WHITE;
    }
   }
  }
 }

 bf_dealloc(&xbitbuf);

 return(ep);
}





/* special version for TIFF files with no EOL characters */
os_error * g3i_decode_T(int fh,int length,int xpix,int ypix,int bitrev)
{
 os_error * ep;
 int        runlength;
 buffer     xbitbuf;

 g3i_initialize(xpix,ypix,bf_get,bitrev);

 ep=bf_alloc(&xbitbuf,DECBUFSIZE,fh,length);

 g3bitbuf=&xbitbuf;


 if(row_number<row_limit)
 {
  while(!g3finished)
  {
   if(color==WHITE)
   {
    ep=decode_white_run(&runlength);
    if(runlength==-2)
    {
     break;
    }
    else
    if(runlength==-1)
    {
     if(new_row())
     {
      break;
     }
    }
    else
    {
     column_number+=runlength;
     writewhiterun(runlength);
     color=BLACK;
     if(column_number>=column_limit)
     {
      if(new_row()) 
      {
       break;
      }
      g3bit_number=0;
     }
    }
   }
   else
   {
    ep=decode_black_run(&runlength);
    if(runlength==-2)
    {
     break;
    }
    else
    if(runlength==-1)
    {
     if(new_row())
     {
      break;
     }
    }
    else
    {
     column_number+=runlength;
     writeblackrun(runlength);
     color=WHITE;
     if(column_number>=column_limit)
     {
      if(new_row())
      {
       break;
      }
      g3bit_number=0;
     }
    }
   }
  }
 }

 bf_dealloc(&xbitbuf);

 return(ep);
}


os_error * g3i_getline(codestr * cx,int * eof)
{
 os_error * err;
 int        runlength;

 err=NULL;

 g3bitbuf=cx->bf;
 cx->run=0;
 cx->line++;
 cx->good=1;

 *eof=(row_number>=row_limit) || (g3finished);
 if(!(*eof))
 {
  while(!g3finished)
  {
   if(color==WHITE)
   {
    err=decode_white_run(&runlength);
    if(runlength==-2)
    {

    }
    else
    if(runlength==-1)
    {
     g3i_checkrow(cx);
     g3i_newrow();
     break;
    }
    else
    {
     if(column_number<column_limit)
     {
      column_number+=runlength;
      if(column_number>column_limit)
      {
       runlength-=(column_number-column_limit);
       column_number=column_limit;
       cx->good=0;
      }
      cx->runs[cx->run++]=runlength;
     }
     color=BLACK;
    }
   }
   else
   {
    err=decode_black_run(&runlength);
    if(runlength==-2)
    {

    }
    else
    if(runlength==-1)
    {
     g3i_checkrow(cx);
     g3i_newrow();
     break;
    }
    else
    {
     if(column_number<column_limit)
     {
      column_number+=runlength;
      if(column_number>column_limit)
      {
       runlength-=(column_number-column_limit);
       column_number=column_limit;
       cx->good=0;
      }
      cx->runs[cx->run++]=runlength;
     }
     color=WHITE;
    }
   }
  }
 }

 return(err);
}



os_error * g3i_getlineT(codestr * cx,int * eof)
{
 os_error * err;
 int        runlength;

 err=NULL;

 g3bitbuf=cx->bf;
 cx->run=0;
 cx->line++;
 cx->good=1;

 *eof=(row_number>=row_limit) || (g3finished);
 if(!(*eof))
 {
  while(!g3finished)
  {
   if(color==WHITE)
   {
    err=decode_white_run(&runlength);
    if(runlength==-2)
    {

    }
    else
    if(runlength==-1)
    {
     g3i_newrow();
     break;
    }
    else
    {
     column_number+=runlength;
     if(column_number>column_limit)
     {
      runlength-=(column_number-column_limit);
      column_number=column_limit;
      cx->good=0;
     }

     cx->runs[cx->run++]=runlength;
     color=BLACK;
     if(column_number>=column_limit)
     {
      if(new_row()) 
      {
       break;
      }
      g3bit_number=0;
     }
    }
   }
   else
   {
    err=decode_black_run(&runlength);
    if(runlength==-2)
    {

    }
    else
    if(runlength==-1)
    {
     g3i_newrow();
     break;
    }
    else
    {
     column_number+=runlength;

     if(column_number>column_limit)
     {
      runlength-=(column_number-column_limit);
      column_number=column_limit;
      cx->good=0;
     }

     cx->runs[cx->run++]=runlength;
     color=WHITE;
     if(column_number>=column_limit)
     {
      if(new_row()) 
      {
       break;
      }
      g3bit_number=0;
     }
    }
   }
  }
 }

 return(err);
}





void g3i_initialize(int image_width,int image_length,getfn getf,int bitrev)
{
 color=WHITE;
 g3bit_number=0;
 column_limit=image_width;
 row_limit=image_length;
 row_number=0;
 column_number=0;
 g3finished=0;
 g3getbyte=getf;
 g3bitrev=bitrev;
}

