/*{{{  #includes*/
#include <ctype.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>

#include <local/bool.h>

#define PUTRC
#include "../h/rcformat.h"

#define SET_C

#include "keybind.h"
/*}}}  */

/*{{{  types*/
typedef struct charset
 { char *name;
   int  no;
   Set set;
   struct charset *next;
 } charset;
/*}}}  */
/*{{{  variables*/
private int set_used;
private charset *sets=0;
/*}}}  */

/*{{{  poke_char*/
private void poke_char(int x,Set setcode)
{ setcode[x>>3] |= (1<<(x & 7));
}
/*}}}  */
/*{{{  init_sets*/
public bool init_sets(void)
{ charset *x;
  int i;

  sets=0;
  /*{{{  digit*/
  x=(charset*)calloc(1,sizeof(charset));
  if (!x)
   { error_po();
     fprintf(stderr,M_NOMEMORY);
     return(TRUE);
   }
  x->name="digit";
  x->no=DIGIT;
  for (i=0;i<256;i++)
    if (isdigit(i)) poke_char(i,x->set);
  x->next=sets;
  sets=x;
  /*}}}  */
  /*{{{  alpha*/
  x=(charset*)calloc(1,sizeof(charset));
  if (!x)
   { error_po();
     fprintf(stderr,M_NOMEMORY);
     return(TRUE);
   }
  x->name="alpha";
  x->no=ALPHA;
  for (i=0;i<256;i++)
    if (isalpha(i)) poke_char(i,x->set);
  x->next=sets;
  sets=x;
  /*}}}  */
  /*{{{  upper*/
  x=(charset*)calloc(1,sizeof(charset));
  if (!x)
   { error_po();
     fprintf(stderr,M_NOMEMORY);
     return(TRUE);
   }
  x->name="upper";
  x->no=UPPER;
  for (i=0;i<256;i++)
    if (isalpha(i) && isupper(i)) poke_char(i,x->set);
  x->next=sets;
  sets=x;
  /*}}}  */
  /*{{{  lower*/
  x=(charset*)calloc(1,sizeof(charset));
  if (!x)
   { error_po();
     fprintf(stderr,M_NOMEMORY);
     return(TRUE);
   }
  x->name="lower";
  x->no=LOWER;
  for (i=0;i<256;i++)
    if (isalpha(i) && islower(i)) poke_char(i,x->set);
  x->next=sets;
  sets=x;
  /*}}}  */

  return(FALSE);
}
/*}}}  */
/*{{{  parse_set*/
public bool parse_set(void)
{ charset *x=(charset*)calloc(1,sizeof(charset));
  int i;
  tokens token;

  /*{{{  no space?*/
  if (!x)
   { error_po();
     fprintf(stderr,M_NOMEMORY);
     return(TRUE);
   }
  /*}}}  */
  /*{{{  name expected*/
  if (get_token(FALSE)!=NAME)
   { error_po();
     fprintf(stderr,M_SNAME);
     return(TRUE);
   }
  x->name=malloc(strlen(tk_string)+1);
  if (!x->name)
   { error_po();
     fprintf(stderr,M_NOMEMORY);
     return(TRUE);
   }
  strcpy(x->name,tk_string);
  /*}}}  */
  if (verbose) fprintf(stderr,F_SETDEC,tk_string,set_used);
  if (begin_parse()) return(TRUE);
  for (i=0;i<sizeof(Set);i++) x->set[i]='\0';
  while ((token=get_token(FALSE))!=END)
   { if (token==NAME)
      /*{{{  get the char*/
      { charset *y=sets;

        /*{{{  look in list*/
        while (y)
         if (!strcmp(tk_string,y->name))
          /*{{{  or the codes*/
          { int i;

            for (i=0;i<sizeof(Set);i++) x->set[i] |= y->set[i];
            break;
          }
          /*}}}  */
         else
           y=y->next;
        /*}}}  */
        if (
           /*{{{  not found and maybe a ctrl-string*/
           !y && strlen(tk_string)==3
              && tk_string[0]=='C'
              && tk_string[1]=='-'
              && tk_string[2]!='\0'
              && tk_string[3]=='\0'
           /*}}}  */
        )
         /*{{{  ctrl-char*/
           poke_char(ctrl_c[tk_string[2]],x->set);
         /*}}}  */
        else if (!y)
         /*{{{  show error*/
         { error_po();
           fprintf(stderr,M_NOSETCHAR);
           return(TRUE);
         }
         /*}}}  */
      }
      /*}}}  */
     else if (token==MACRO && strlen(tk_string)==1)
      /*{{{  single char*/
        poke_char((int)(tk_string[0]),x->set);
      /*}}}  */
     else
      /*{{{  show error*/
      { error_po();
        fprintf(stderr,M_NOSETCHAR);
        return(TRUE);
      }
      /*}}}  */
   }
  x->no=set_used;
  x->next=sets;
  sets=x;
  set_used++;

  return(FALSE);
}
/*}}}  */
/*{{{  get_set*/
public int get_set(void)
{ charset *x=sets;

  /*{{{  name?*/
  if (get_token(FALSE)!=NAME)
   { error_po();
     fprintf(stderr,M_SNAME);
     return(UNDEFINED_SET);
   }
  /*}}}  */
  /*{{{  look in list and return no*/
  while (x)
     if (!strcmp(tk_string,x->name))
        return(x->no);
     else
        x=x->next;
  /*}}}  */
  error_po();
  fprintf(stderr,M_SETMISS);
  return(UNDEFINED_SET);
}
/*}}}  */
/*{{{  parse_set_macro*/
public TOKEN *parse_set_macro(TOKEN* buff)
{ *buff++=M_SET_COPY;
  if ((*buff++=get_set())<0)
   { error_po();fprintf(stderr,M_SNAME);return(0); }
  if ((*buff++=get_set())==UNDEFINED_SET)
   { error_po();fprintf(stderr,M_SNAME);return(0); }
  return(buff);
}
/*}}}  */
/*{{{  writesets*/
public bool writesets(FILE *rc)
{
  charset *x=sets;

  if (!set_used) return(FALSE);
  if (verbose) fprintf(stderr,F_SETUSE,set_used);
  rc_put_c(RC_CHARSET,rc);
  rc_put_w(set_used*sizeof(Set),rc);
  /*{{{  write all sets*/
  while (set_used--)
  { int i;

    for (i=0;i<sizeof(Set);i++) rc_put_c(x->set[i],rc);
    x=x->next;
  }
  /*}}}  */

  return(FALSE);
}
/*}}}  */
