#include "libpdftex.h"

#define ENC_BUF_SIZE    1024

static FILE *enc_file;

#define ENC_OPEN()      texpsheaderbopenin(enc_file)
#define ENC_GETCHAR()   xgetc(enc_file)
#define ENC_CLOSE()     xfclose(enc_file, filename)
#define ENC_EOF()       feof(enc_file)

enc_entry *enc_ptr = 0, *enc_tab = 0;
static enc_max = 256;

int add_enc(char *s)
{
    enc_entry *e;
    if (enc_tab == 0) {
        enc_tab = XTALLOC(enc_max, enc_entry);
        enc_ptr = enc_tab;
    }
    for (e = enc_tab; e < enc_ptr; e++)
        if (strcmp(s, e->name) == 0)
            return e - enc_tab;
    enc_ptr->name = xstrdup(s);
    enc_ptr->obj_num = 0;
    enc_ptr++;
    if (enc_ptr - enc_tab == enc_max) {
        enc_tab = XRETALLOC(enc_tab, enc_max + 256, enc_entry);
        enc_ptr = enc_tab + enc_max;
        enc_max += 256;
    }
    return enc_ptr - enc_tab - 1;
}

void write_enc(enc_entry *e)
{
    char enc_line[ENC_BUF_SIZE], buf[ENC_BUF_SIZE], *p, *q, *r;
    int c, i, names_count;
    boolean is_notdef;
    filename = e->name;
    packfilename(maketexstring(filename), getnullstr(), getnullstr());
    if (!ENC_OPEN()) {
        WARN("cannot open encoding file for reading");
        return;
    }
    TEX_PRINTF("<%s" AND e->name);
    is_notdef = false;
    for (;;) {
        p = enc_line;
        do {
            c = ENC_GETCHAR();
            APPEND_CHAR_TO_BUF(c, p, enc_line, ENC_BUF_SIZE);
        } while (c != 10);
        APPEND_EOL(p, enc_line, ENC_BUF_SIZE);
        if (p - enc_line > 1 && *enc_line == '/')
            break; /* we suppose this line to contain the name of encoding vector */
        if (ENC_EOF())
            FAIL("unexpected end of file");
    }
    pdfnewdict(0, 0);
    e->obj_num = objptr;
    names_count = 0;
    for (i = 0; i < MAX_CHAR_NUM; e->glyph_names[i++] = notdef);
    PDF_PRINTF("/Type /Encoding\n/Differences [");
    for (;;) {
        p = enc_line;
        do {
            c = ENC_GETCHAR();
            APPEND_CHAR_TO_BUF(c, p, enc_line, ENC_BUF_SIZE);
        } while (c != 10);
        APPEND_EOL(p, enc_line, ENC_BUF_SIZE);
        if (p - enc_line <= 1 || *enc_line == '%')
            continue;
        if (!strncmp(enc_line, "] def", strlen("] def")))
            goto done; /* we suppose this to be the last line of encoding vector */
        else if (ENC_EOF())
            FAIL("unexpected end of file");
        r = enc_line;
        do {
            if (*r == '%')
                break;
            READ_FIELD(r, q, buf);
            if (!strcmp(buf + 1, notdef)) /* skip the slash */ {
                if (!is_notdef) {
                    PDF_PRINTF(" %i/%s" AND names_count AND buf + 1);
                    is_notdef = true;
                }
            }
            else {
                if (is_notdef || (names_count == 0)) {
                    PDF_PRINTF(" %i" AND names_count);
                    is_notdef = false;
                }
                PDF_PRINTF("/%s" AND buf + 1);
                e->glyph_names[names_count] = xstrdup(buf + 1);
            }
            if (names_count++ >= MAX_CHAR_NUM)
                FAIL("encoding vector contains more than %i names" AND
                     MAX_CHAR_NUM);
        } while (*r != 10);
    }
done:
    PDF_PRINTF("]\n>> endobj\n");
    ENC_CLOSE();
    TEX_PRINTF(">");
}

int enc_objnum(int i)
{
    if (enc_tab[i].obj_num == 0)
        write_enc(enc_tab + i);
    return enc_tab[i].obj_num;
}

void enc_free()
{
    enc_entry *e;
    int k;
    for (e = enc_tab; e < enc_ptr; e++) {
        XFREE(e->name);
        for (k = 0; k < MAX_CHAR_NUM; k++)
            XFREE(e->glyph_names[k]);
    }
    XFREE(enc_tab);
}
