#include <u.h>
#include <libc.h>
#include <bio.h>
#include "dict.h"

/*
* American Heritage Dictionary (encrypted)
*/

static Rune intab[256] = {
       [0x82] L'é',
       [0x85] L'à',
       [0x89] L'ë',
       [0x8a] L'è',
       [0xa4] L'ñ',
       [0xf8] L'°',
       [0xf9] L'·',
};

static char     tag[64];

enum{
       Run, Openper, Openat, Closeat
};

void
ahdprintentry(Entry e, int cmd)
{
       static int inited;
       long addr;
       char *p, *t = tag;
       int obreaklen;
       int c, state = Run;

       if(!inited){
               for(c=0; c<256; c++)
                       if(intab[c] == 0)
                               intab[c] = c;
               inited = 1;
       }
       obreaklen = breaklen;
       breaklen = 80;
       addr = e.doff;
       for(p=e.start; p<e.end; p++){
               c = intab[(*p ^ (addr++>>1))&0xff];
               switch(state){
               case Run:
                       if(c == '%'){
                               t = tag;
                               state = Openper;
                               break;
                       }
               Putchar:
                       if(c == '\n')
                               outnl(0);
                       else if(c < Runeself)
                               outchar(c);
                       else
                               outrune(c);
                       break;

               case Openper:
                       if(c == '@')
                               state = Openat;
                       else{
                               outchar('%');
                               state = Run;
                               goto Putchar;
                       }
                       break;

               case Openat:
                       if(c == '@')
                               state = Closeat;
                       else if(t < &tag[sizeof tag-1])
                               *t++ = c;
                       break;

               case Closeat:
                       if(c == '%'){
                               *t = 0;
                               switch(cmd){
                               case 'h':
                                       if(strcmp("EH", tag) == 0)
                                               goto out;
                                       break;
                               case 'r':
                                       outprint("%%@%s@%%", tag);
                                       break;
                               }
                               state = Run;
                       }else{
                               if(t < &tag[sizeof tag-1])
                                       *t++ = '@';
                               if(t < &tag[sizeof tag-1])
                                       *t++ = c;
                               state = Openat;
                       }
                       break;
               }
       }
out:
       outnl(0);
       breaklen = obreaklen;
}

long
ahdnextoff(long fromoff)
{
       static char *patterns[] = { "%@NL@%", "%@2@%", 0 };
       int c, k = 0, state = 0;
       char *pat = patterns[0];
       long defoff = -1;

       if(Bseek(bdict, fromoff, 0) < 0)
               return -1;
       while((c = Bgetc(bdict)) >= 0){
               c ^= (fromoff++>>1)&0xff;
               if(c != pat[state]){
                       state = 0;
                       continue;
               }
               if(pat[++state])
                       continue;
               if(pat = patterns[++k]){        /* assign = */
                       state = 0;
                       defoff = fromoff-6;
                       continue;
               }
               return fromoff-5;
       }
       return defoff;
}

void
ahdprintkey(void)
{
       Bprint(bout, "No pronunciations.\n");
}