#include "vncviewer.h"
static int CapsIndex(CapsContainer *pcaps, CARD32 code);
CapsContainer *
CapsNewContainer(void)
{
  CapsContainer *pcaps;
  pcaps = malloc(sizeof(CapsContainer));
  if (pcaps != NULL) {
    pcaps->known_count = 0;
    pcaps->enabled_count = 0;
  }
  return pcaps;
}
void
CapsDeleteContainer(CapsContainer *pcaps)
{
  int i;
  for (i = 0; i < pcaps->known_count; i++) {
    if (pcaps->descriptions[i] != NULL)
      free(pcaps->descriptions[i]);
  }
  free(pcaps);
}
void
CapsAdd(CapsContainer *pcaps,
        CARD32 code, char *vendor, char *name, char *desc)
{
  
  rfbCapabilityInfo capinfo;
  capinfo.code = code;
  memcpy(capinfo.vendorSignature, vendor, sz_rfbCapabilityInfoVendor);
  memcpy(capinfo.nameSignature, name, sz_rfbCapabilityInfoName);
  CapsAddInfo(pcaps, &capinfo, desc);
}
void
CapsAddInfo(CapsContainer *pcaps,
            rfbCapabilityInfo *capinfo, char *desc)
{
  int i;
  char *desc_copy;
  i = CapsIndex(pcaps, capinfo->code);
  if (i == -1) {
    if (pcaps->known_count >= TIGHTVNC_MAX_CAPS) {
      return;                   
    }
    i = pcaps->known_count++;
    pcaps->known_list[i] = capinfo->code;
    pcaps->descriptions[i] = NULL;
  }
  pcaps->known_info[i] = *capinfo;
  pcaps->enable_flags[i] = (char)False;
  if (pcaps->descriptions[i] != NULL) {
    free(pcaps->descriptions[i]);
  }
  desc_copy = NULL;
  if (desc != NULL) {
    desc_copy = strdup(desc);
  }
  pcaps->descriptions[i] = desc_copy;
}
static int
CapsIndex(CapsContainer *pcaps, CARD32 code)
{
  int i;
  for (i = 0; i < pcaps->known_count; i++) {
    if (pcaps->known_list[i] == code)
      return i;
  }
  return -1;
}
Bool
CapsIsKnown(CapsContainer *pcaps, CARD32 code)
{
  return (CapsIndex(pcaps, code) != -1);
}
Bool
CapsGetInfo(CapsContainer *pcaps, CARD32 code, rfbCapabilityInfo *capinfo)
{
  int i;
  i = CapsIndex(pcaps, code);
  if (i != -1) {
    *capinfo = pcaps->known_info[i];
    return True;
  }
  return False;
}
char *
CapsGetDescription(CapsContainer *pcaps, CARD32 code)
{
  int i;
  i = CapsIndex(pcaps, code);
  if (i != -1) {
    return pcaps->descriptions[i];
  }
  return NULL;
}
Bool
CapsEnable(CapsContainer *pcaps, rfbCapabilityInfo *capinfo)
{
  int i;
  rfbCapabilityInfo *known;
  i = CapsIndex(pcaps, capinfo->code);
  if (i == -1)
    return False;
  known = &pcaps->known_info[i];
  if ( memcmp(known->vendorSignature, capinfo->vendorSignature,
              sz_rfbCapabilityInfoVendor) != 0 ||
       memcmp(known->nameSignature, capinfo->nameSignature,
              sz_rfbCapabilityInfoName) != 0 ) {
    pcaps->enable_flags[i] = (char)False;
    return False;
  }
  
  if (pcaps->enabled_count >= TIGHTVNC_MAX_CAPS) {
    pcaps->enable_flags[i] = (char)False;
    return False;
  }
  pcaps->enable_flags[i] = (char)True;
  pcaps->enabled_list[pcaps->enabled_count++] = capinfo->code;
  return True;
}
Bool
CapsIsEnabled(CapsContainer *pcaps, CARD32 code)
{
  int i;
  i = CapsIndex(pcaps, code);
  if (i != -1) {
    return (pcaps->enable_flags[i] != (char)False);
  }
  return False;
}
int CapsNumEnabled(CapsContainer *pcaps)
{
  return pcaps->enabled_count;
}
CARD32
CapsGetByOrder(CapsContainer *pcaps, int idx)
{
  return (idx < pcaps->enabled_count) ? pcaps->enabled_list[idx] : 0;
}