#include "config.h"
#include "webmacros.h"

#define PRINTF_BUF_SIZE  256

#define MAX_CHAR_NUM    256

#define TEX_PRINTF(S) do {                                 \
    sprintf(printf_buf, S);                                \
    print(maketexstring(printf_buf));                      \
    flushstring();                                         \
    xfflush(stdout);                                       \
} while (0)

#define PDF_PRINTF(S) do {                                 \
    sprintf(printf_buf,  S);                               \
    flush_printf_buf();                                    \
} while (0)

#define AND ,

#define FAIL(S) do {                                      \
    fprintf(stderr, "\n! Error: %s", program_invocation_name);  \
    if (filename)                                         \
        fprintf(stderr, " (file %s)", filename);          \
    fprintf(stderr, ":\n");                               \
    fprintf(stderr, S);                                   \
    fprintf(stderr, "\n");                                \
    exit(-1);                                             \
} while (0)

#define WARN(S) do {                                      \
    fprintf(stderr, "\n! Warning: %s", program_invocation_name);\
    if (filename)                                         \
        fprintf(stderr, " (file %s)", filename);          \
    fprintf(stderr, ":\n");                               \
    fprintf(stderr, S);                                   \
    fprintf(stderr, "\n");                                \
} while (0)

#define CHECK_BUF(size, buf_size)                         \
    if ((size) >= buf_size - 2)                           \
        FAIL("buffer overflow [%i bytes]" AND buf_size)

#define APPEND_CHAR_TO_BUF(c, p, buf, buf_size) do {       \
    if (c == 9)                                            \
        c = 32;                                            \
    if (c == 13 || c == EOF)                               \
        c = 10;                                            \
    if (c != ' ' || (p > buf && p[-1] != 32)) {            \
        CHECK_BUF(p - buf, buf_size);                      \
        *p++ = c;                                          \
    }                                                      \
} while (0)

#define APPEND_EOL(p, buf, buf_size) do {                  \
    if (p - buf > 1 && p[-1] != 10) {                      \
        CHECK_BUF(p - buf, buf_size);                      \
        *p++ = 10;                                         \
    }                                                      \
    if (p - buf > 2 && p[-2] == 32) {                      \
        p[-2] = 10;                                        \
        p--;                                               \
    }                                                      \
    *p = 0;                                                \
} while (0)

#define READ_FIELD(r, q, buf) do {                         \
    for (q = buf; *r != 32 && *r != 10; *q++ = *r++);      \
    *q = 0;                                                \
    if (*r == 32)                                          \
        r++;                                               \
} while (0)

#define XFREE(p)        if (!p) free(p)

#define ASCENT_CODE         0
#define CAPHEIGHT_CODE      1
#define DESCENT_CODE        2
#define FONTNAME_CODE       3
#define ITALIC_ANGLE_CODE   4
#define STEMV_CODE          5
#define XHEIGHT_CODE        6
#define FONTBBOX1_CODE      7
#define FONTBBOX2_CODE      8
#define FONTBBOX3_CODE      9
#define FONTBBOX4_CODE      10
#define MAX_KEY_CODE        (FONTBBOX1_CODE + 1)
#define FONT_KEYS_NUM       (FONTBBOX4_CODE + 1)

#define F_INCLUDED  0x01
#define F_SUBSETTED 0x02
#define F_TRUETYPE  0x04
#define F_BASEFONT  0x08
#define F_NOPARSING 0x10

#define is_included()   (fm_cur->font_type & F_INCLUDED)
#define is_subsetted()  (fm_cur->font_type & F_SUBSETTED)
#define is_truetype()   (fm_cur->font_type & F_TRUETYPE)
#define is_basefont()   (fm_cur->font_type & F_BASEFONT)
#define is_noparsing()  (fm_cur->font_type & F_NOPARSING)
#define is_reencoded()  (fm_cur->encoding >= 0)

typedef struct {
    char *pdfname;
    char *t1name;
    union {
      integer i;
      char *s;
    } value;
    boolean valid;
} key_entry;

typedef struct {
    integer obj_num;
    char *name;
    char *glyph_names[MAX_CHAR_NUM];
} enc_entry;

typedef struct {
    char *tex_name;           /* TFM file name */
    char *base_name;          /* PostScript name */
    integer flags;            /* font flags */
    char *ff_name;            /* font file name */
    char *prefix;             /* prefix for subsetted font */
    int encoding;             /* index to table of encoding vectors */
    int font_type;            /* font type */
    integer extend;
    integer slant;
} fm_entry;

extern char *builtin_glyph_names[];
extern enc_entry *enc_ptr, *enc_tab;
extern char *filename;
extern fm_entry *fm_cur, *fm_ptr, *fm_tab;
extern char **cur_glyph_names;
extern char *mapfiles;
extern boolean font_file_not_found;
extern key_entry font_keys[];
extern char notdef[];
extern char printf_buf[PRINTF_BUF_SIZE];
extern integer t1_length1, t1_length2, t1_length3;
extern internalfontnumber tex_font;
extern integer ttf_length;

extern int xfflush(FILE *);
extern size_t xfwrite(void *, size_t, size_t, FILE *);
extern int xgetc(FILE *);
extern int xputc(int, FILE *);
extern char *makecstring(integer);
extern boolean str_eq_cstr(strnumber, char *);
extern strnumber maketexstring(char *);
extern void flush_printf_buf();
extern integer myatodim(char **);
extern integer myatol(char **);
extern void readconfig();
extern void fm_read_info();
extern integer fmlookup(internalfontnumber);
extern boolean sharedsrc(internalfontnumber,internalfontnumber);
extern void fm_free();
extern int add_enc(char *);
extern int enc_objnum(int);
extern void enc_free();
extern void writettf();
extern void writet1();
extern void img_free();
extern void libpdffinish();
