
#ifndef __PROTO_H__
#define __PROTO_H__

#include "config.h"
#include "vncproto.h"
#include "vncserv.h"

typedef struct zrle_state zrle_state;

typedef enum {
  VNCSERVSTATE_IDLE,
  VNCSERVSTATE_WAITING_FOR_PROTOCOL_VERSION,
  VNCSERVSTATE_WAITING_FOR_AUTH,
  VNCSERVSTATE_WAITING_FOR_CLIENT_INIT,
  VNCSERVSTATE_READY,
  VNCSERVSTATE_SENDING_UPDATE, // In the middle of sending a FramebufferUpdate
  VNCSERVSTATE_SENDING_TEXT, // In the middle of sending a ServerCutText
} vncservstate;

typedef struct {
  unsigned int hextile:1;
  unsigned int copy:1;
  unsigned int hextiledithering:1;
  unsigned int desktopsize:1;
  unsigned int cursor:1;
  unsigned int xcursor:1;
  unsigned int zrle:1;
  unsigned int zlib:1;
} supported_encodings;

struct vncserv_s {
  // configuration for this server instance
  server_config_t config;
  // the framebuffer we're serving
  servscreen screen;
  // current palette; matches OS palette for <= 8bpp OS mode, else standard 256 colour palette for >16bpp OS mode
  unsigned int pal8bpp[256];
  // colour translation table for 555 -> pal8bpp
  void *pixtrans;
  // pixel format being used by the client
  PIXEL_FORMAT clientformat;
  // io
  vncservio io;
  void *meta;
  // encodings supported by client
  supported_encodings encodings;
  // True if we've received a pointer update from the client
  // (sending the shape data too early upsets RealVNC - although I'm not sure
  // whether that's because the client hadn't sent a pointer update yet, or
  // whether it's because it's expecting something else like the initial screen
  // update)
  bool pointer_active;
  // state machine state
  vncservstate state;
  // zlib, zrle encoders
  zrle_state *zrle;
  zrle_state *zlib;
};

static inline int vncserv_write(vncserv *serv, const void *buffer, int bytes)
{
  return serv->io.write(serv, buffer, bytes, serv->meta);
}

static inline int vncserv_get_tx_space(vncserv *serv)
{
  return serv->io.get_tx_space(serv, serv->meta);
}

#endif
