/*
 *  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
 *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
 *
 *  This 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 software 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 software; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 *  USA.
 */

#ifdef LIBVNCSERVER_HAVE_LIBZ

/*
 * zlib.c - handle zlib encoding.
 *
 * This file shouldn't be compiled directly.  It is included multiple times by
 * rfbproto.c, each time with a different definition of the macro BPP.  For
 * each value of BPP, this file defines a function which handles an zlib
 * encoded rectangle with BPP bits per pixel.
 */

#define HandleZlibBPP CONCAT2E(HandleZlib,BPP)
#define CARDBPP CONCAT3E(uint,BPP,_t)

static rfbBool
HandleZlibBPP (rfbClient* client, int rx, int ry, int rw, int rh)
{
  rfbZlibHeader hdr;
  int remaining;
  int inflateResult;
  int toRead;

  /* First make sure we have a large enough raw buffer to hold the
   * decompressed data.  In practice, with a fixed BPP, fixed frame
   * buffer size and the first update containing the entire frame
   * buffer, this buffer allocation should only happen once, on the
   * first update.
   */
  if ( client->raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) {

    if ( client->raw_buffer != NULL ) {

      free( client->raw_buffer );

    }

    client->raw_buffer_size = (( rw * rh ) * ( BPP / 8 ));
    client->raw_buffer = (char*) malloc( client->raw_buffer_size );

  }

  if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader))
    return FALSE;

  remaining = rfbClientSwap32IfLE(hdr.nBytes);

  /* Need to initialize the decompressor state. */
  client->decompStream.next_in   = ( Bytef * )client->buffer;
  client->decompStream.avail_in  = 0;
  client->decompStream.next_out  = ( Bytef * )client->raw_buffer;
  client->decompStream.avail_out = client->raw_buffer_size;
  client->decompStream.data_type = Z_BINARY;

  /* Initialize the decompression stream structures on the first invocation. */
  if ( client->decompStreamInited == FALSE ) {

    inflateResult = inflateInit( &client->decompStream );

    if ( inflateResult != Z_OK ) {
      rfbClientLog(
              "inflateInit returned error: %d, msg: %s\n",
              inflateResult,
              client->decompStream.msg);
      return FALSE;
    }

    client->decompStreamInited = TRUE;

  }

  inflateResult = Z_OK;

  /* Process buffer full of data until no more to process, or
   * some type of inflater error, or Z_STREAM_END.
   */
  while (( remaining > 0 ) &&
         ( inflateResult == Z_OK )) {
  
    if ( remaining > RFB_BUFFER_SIZE ) {
      toRead = RFB_BUFFER_SIZE;
    }
    else {
      toRead = remaining;
    }

    /* Fill the buffer, obtaining data from the server. */
    if (!ReadFromRFBServer(client, client->buffer,toRead))
      return FALSE;

    client->decompStream.next_in  = ( Bytef * )client->buffer;
    client->decompStream.avail_in = toRead;

    /* Need to uncompress buffer full. */
    inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH );

    /* We never supply a dictionary for compression. */
    if ( inflateResult == Z_NEED_DICT ) {
      rfbClientLog("zlib inflate needs a dictionary!\n");
      return FALSE;
    }
    if ( inflateResult < 0 ) {
      rfbClientLog(
              "zlib inflate returned error: %d, msg: %s\n",
              inflateResult,
              client->decompStream.msg);
      return FALSE;
    }

    /* Result buffer allocated to be at least large enough.  We should
     * never run out of space!
     */
    if (( client->decompStream.avail_in > 0 ) &&
        ( client->decompStream.avail_out <= 0 )) {
      rfbClientLog("zlib inflate ran out of space!\n");
      return FALSE;
    }

    remaining -= toRead;

  } /* while ( remaining > 0 ) */

  if ( inflateResult == Z_OK ) {

    /* Put the uncompressed contents of the update on the screen. */
    CopyRectangle(client, (uint8_t *)client->raw_buffer, rx, ry, rw, rh);
  }
  else {

    rfbClientLog(
            "zlib inflate returned error: %d, msg: %s\n",
            inflateResult,
            client->decompStream.msg);
    return FALSE;

  }

  return TRUE;
}

#undef CARDBPP

#endif
