/* Merged parser stuff for keyboard plugin
 */

%{

/* for keyboard plugin */
static void keyb_mod(int wich, int keynum, int dummy);
static void dump_keytable_part(FILE *f, unsigned char *map, int size);
void dump_keytable(FILE *f, struct keytable_entry *kt);

%}
	/* no special bison declaration for keyboard plugin so far */
%%

keyboard_modval:  DGRAVE { keyb_mod(0, DEAD_GRAVE, 0); }
		| DACUTE { keyb_mod(0, DEAD_ACUTE, 0); }
		| DCIRCUM { keyb_mod(0, DEAD_CIRCUMFLEX, 0); }
		| DTILDE { keyb_mod(0, DEAD_TILDE, 0); }
		| DBREVE { keyb_mod(0, DEAD_BREVE, 0); }
		| DABOVED { keyb_mod(0, DEAD_ABOVEDOT, 0); }
		| DDIARES { keyb_mod(0, DEAD_DIAERESIS, 0); }
		| DABOVER { keyb_mod(0, DEAD_ABOVERING, 0); }
		| DDACUTE { keyb_mod(0, DEAD_DOUBLEACUTE, 0); }
		| DCEDILLA { keyb_mod(0, DEAD_CEDILLA, 0); }
		| DIOTA { keyb_mod(0,DEAD_IOTA, 0); }
		| DOGONEK { keyb_mod(0,DEAD_OGONEK, 0); }
		| DCARON { keyb_mod(0,DEAD_CARON, 0); }
		;
%%

/* for keyboard plugin */

static void keyb_mod(int wich, int keynum, int dummy)
{
  static unsigned char *table = 0;
  static int count = 0;
  static int in_altmap = 0;

  switch (wich) {
    case ' ': {
      in_altmap = 0;
      switch (keynum & 0x300) {
        case 0: table = config.keytable->key_map;
        	count=config.keytable->sizemap;
        	break;
        case 0x100: table = config.keytable->shift_map;
        	count=config.keytable->sizemap;
        	break;
        case 0x200: table = config.keytable->alt_map;
        	count=config.keytable->sizemap;
        	in_altmap = 1;
        	break;
        case 0x300: table = config.keytable->num_table;
        	count=config.keytable->sizepad;
        	break;
      }
      break;
    }
    case 'S': table = config.keytable->shift_map;
    	count=config.keytable->sizemap;
	in_altmap = 0;
    	break;
    case 'A': table = config.keytable->alt_map;
    	count=config.keytable->sizemap;
    	in_altmap = 1;
    	break;
    case 'N': table = config.keytable->num_table;
    	count=config.keytable->sizepad;
	in_altmap = 0;
    	break;
  }

  keynum &= 0xff;
  if (wich) {
    if (keynum >= count) return;
    table += keynum;
    count -= keynum;
    return;
  }
  if (count > 0) {
    *table++ = keynum;
    if (in_altmap && keynum)
      config.keytable->flags |= KT_USES_ALTMAP;
    count--;
  }
}


static void dump_keytable_part(FILE *f, unsigned char *map, int size)
{
  int i, in_string=0, is_deadkey;
  unsigned char c, *cc, comma=' ', buf[16];
  static unsigned char dead_key_list[] = {FULL_DEADKEY_LIST, 0};
  static char *dead_key_names[] = {
    "dgrave", "dacute", "dcircum", "dtilde", "dbreve", "daboved", "ddiares",
    "dabover", "ddacute", "dcedilla", "diota", "dogonek", "dcaron"
  };

  size--;
  for (i=0; i<=size; i++) {
    c = map[i];
    if (!(i & 15)) fprintf(f,"    ");
    is_deadkey = c ? (int)strchr(dead_key_list, c) : 0;
    if (!is_deadkey && isprint(c) && !strchr("\\\"\'`", c)) {
      if (in_string) fputc(c,f);
      else {
        fprintf(f, "%c\"%c", comma, c);
        in_string = 1;
      }
    }
    else {
      if (is_deadkey) cc = dead_key_names[is_deadkey - (int)(&dead_key_list)];
      else {
        sprintf(buf, "%d", c);
        cc = buf;
      }
      if (!in_string) fprintf(f, "%c%s", comma, cc);
      else {
        fprintf(f, "\",%s", cc);
        in_string = 0;
      }
    }
    if ((i & 15) == 15) {
      if (in_string) fputc('"', f);
      if (i < size) fputc(',', f);
      fputc('\n', f);
      in_string = 0;
      comma = ' ';
    }
    else comma = ',';
  }
  if (in_string) fputc('"', f);
  fputc('\n', f);
}

void dump_keytable(FILE *f, struct keytable_entry *kt)
{
    fprintf(f, "keytable %s {\n", kt->name);
    fprintf(f, "  0=\n");
    dump_keytable_part(f, kt->key_map, kt->sizemap);
    fprintf(f, "  shift 0=\n");
    dump_keytable_part(f, kt->shift_map, kt->sizemap);
    fprintf(f, "  alt 0=\n");
    dump_keytable_part(f, kt->alt_map, kt->sizemap);
    fprintf(f, "  numpad 0=\n");
    dump_keytable_part(f, kt->num_table, kt->sizepad-1);
    fprintf(f, "}\n\n\n");
}

