/*
 *  Copyright (C) 1995, 1996  Karl-Johan Johnsson.
 */

#include "global.h"
#include "xface.h"

#if !HAVE_COMPFACE

Pixmap do_xface(char **headers, int n, long *width, long *height)
{
    return None;
}

#else

#include "util.h"
#include <stdlib.h>
#include <compface.h>

#define FACE_SIZE	48

static int fill_buf(char **headers, int n, char *buf, int size)
{
    int		 pos = 0;
    char	*c;

    c = *headers++ + 7; /* Skip 'X-Face:' */
    n--;

    do {
	int	h_len = strlen(c);

	if (h_len + pos >= size)
	    return False;

	while (h_len-- > 0)
	    buf[pos++] = *c++;
	buf[pos] = '\0';
    } while (n-- > 0 && (c = *headers++) && IS_SPACE(*c));

    return True;
}

static int hex_digit(int ch)
{
    if (ch >= '0' && ch <= '9')
	return ch - '0';
    if (ch >= 'A' && ch <= 'F')
	return ch - 'A' + 10;
    if (ch >= 'a' && ch <= 'f')
	return ch - 'a' + 10;

    return -1;
}

static int parse_buf(const char *buf, unsigned char *image)
{
    int		i, j, k;

    for (i = 0 ; i < FACE_SIZE ; i++)
	for (j = 0 ; j < FACE_SIZE / 16 ; j++) {
	    int		d1, d2, d3, d4;
	    unsigned	val, mask;

	    while (IS_SPACE(*buf) || *buf == '\n' || *buf == ',')
		buf++;

	    if (*buf++ != '0' || (*buf++ != 'x' && *buf != 'X'))
		return False;

	    if ((d1 = hex_digit(*buf++)) < 0 ||
		(d2 = hex_digit(*buf++)) < 0 ||
		(d3 = hex_digit(*buf++)) < 0 ||
		(d4 = hex_digit(*buf++)) < 0)
		return False;

	    val = (d1 << 12) | (d2 << 8) | (d3 << 4) | d4;
	    for (mask = 0x8000 ; mask != 0 ; mask >>= 1)
		*image++ = (val & mask) ? 0 : 0xff;
	}

    return True;
}

static Pixmap conv_xface(char **headers, int n)
{
    char		buf[4000];
    unsigned char	image[FACE_SIZE * FACE_SIZE];

    if (!fill_buf(headers, n, buf, sizeof buf - 2))
	return None;
    if (uncompface(buf) < 0)
	return None;
    if (!parse_buf(buf, image))
	return None;

    return put_grey_image(image, FACE_SIZE, FACE_SIZE);
}

Pixmap do_xface(char **headers, int n, long *width, long *height)
{

    while (n > 0 && case_lstrncmp(*headers, "x-face:", 7) != 0) {
	headers++;
	n--;
    }

    if (n <= 0)
	return 0;
    else {
	*width  = FACE_SIZE;
	*height = FACE_SIZE;

	return conv_xface(headers, n);
    }
}

#endif

