/*
 *   MediaMVP Server Widget Library
 *
 *   (C) 2004 Dave Kelly
 *
 *   $Id: label.c,v 1.7 2004/08/30 08:55:24 ravelox Exp $
 *   $Date: 2004/08/30 08:55:24 $
 *
 *   Window handling
 *
 */

#include "mvpwindow.h"

#if 0
#define DEBUG(xxx...) fprintf(stderr,xxx)
#else
#define DEBUG(xxx,...)
#endif

static void label_set_font(window_t *label, font_t *font);
static font_t *label_get_font(window_t *label);
static void label_set_fgcol(window_t *label, uint32_t rgb);
static void label_set_bgcol(window_t *label, uint32_t rgb);
static uint32_t label_get_fgcol(window_t *label);
static uint32_t label_get_bgcol(window_t *label);

static attrib_fns_t label_fns = {
	0,
	NULL,
	NULL,
	NULL,
	label_set_font,
	label_set_fgcol,
	label_set_bgcol,
	NULL,
	NULL,
	NULL,
	label_get_font,
	label_get_fgcol,
	label_get_bgcol
};

typedef struct  {
	char *text;
	uint32_t fgcol;
	uint32_t bgcol;
	font_t *font;
	char align;
	char valign;
} label_t;

static void     label_print(window_t *label, int x, int y, int maxx,  char *text);
static void     label_printchar(window_t *label, int x, int y, glyph_t *glyph);
static void		delete_label_data(window_t *label);

extern glyph_t nbsp;

static int label_calc_x(window_t *label, char *text)
{
	label_t *data;
	int x = 0;
	int label_width, text_width;

	if(window_get_type(label) != WINDOW_LABEL) {
		return x;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return x;
	}

	label_width = window_get_width(label);
	text_width = font_get_textwidth(data->font, text);

	switch(data->align) {
		case LABEL_ALIGN_CENTRE:
			x = (label_width / 2) - (text_width / 2);
			break;
		case LABEL_ALIGN_RIGHT:
			x = label_width - text_width - window_get_xoffset(label);
			break;
		case LABEL_ALIGN_LEFT:
		default:
			x = window_get_xoffset(label);
			break;
	}

	if(x < 0) {
		x = 0;
	}

	return x;
}

static void draw_label(window_t *label)
{
	label_t *data;
	int height;
	int x,y;
	char *label_text, *ptr, *current_line;
	int num_lines = 1;

	if(window_get_type(label) != WINDOW_LABEL) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

	if(! data->text ) {
		return;
	}

	/* Count the number of lines */
	ptr = strchr(data->text, '\n');
	while(ptr++) {
		num_lines++;
		ptr = strchr(ptr, '\n');
	}

	window_clear(label, data->bgcol);
	
	height = window_get_height(label);

	switch(data->valign) {
		case LABEL_VALIGN_BOTTOM:
			y = height - (num_lines * font_get_height(data->font));
			break;
		case LABEL_VALIGN_MIDDLE:
			y = (height / 2) - ( num_lines * font_get_height(data->font) / 2) ;
			break;
		case LABEL_VALIGN_TOP:
		default:
			y = 0;
			break;
	}

	if(y < 0) {
		y = 0;
	}

	label_text = strdup(data->text);
	current_line = label_text;
	while(num_lines > 0) {
		ptr = strchr(current_line, '\n');
		if(ptr) *(ptr++)='\0';
		x = label_calc_x(label, current_line);
		label_print(label, x, y, window_get_width(label), current_line);
		num_lines--;
		current_line = ptr;
		y += font_get_height(data->font);

		if(y >= window_get_height(label) - window_get_yoffset(label)) {
			break;
		}
	}
	free(label_text);
}

window_t *new_label(window_t *parent, int x, int y, int width, int height, char *text)
{
	window_t *label;
	label_t *data;

	label = new_window(parent, WINDOW_LABEL, x, y, width, height);
	window_set_attrib_fns(label, &label_fns);
	data = (label_t *)malloc(sizeof(label_t));

	data->text = (char *)strdup(text);
	data->fgcol = 0xFFFFFF;
	data->bgcol = 0x000000;
	data->font = font_read(default_font);
	data->align = 0;
	data->valign = 0;

	window_set_name(label,  text);
	window_set_data(label, data);
	window_set_draw_func(label, draw_label);
	window_set_delete_func(label, delete_label_data);

	window_set_xoffset(label, 1);
	window_set_yoffset(label, 1);

	window_mark_dirty(label);

	return label;
}

static void label_set_font(window_t *label, font_t *font)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

    data->font = font;
	window_mark_dirty(label);
}

static font_t *label_get_font(window_t *label)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return NULL;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return NULL;
	}

    return data->font;
}

static void label_set_fgcol(window_t *label, uint32_t rgb)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

    data->fgcol = rgb;
	window_mark_dirty(label);
}

void label_set_bgcol(window_t *label, uint32_t rgb)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

    data->bgcol = rgb;
	window_mark_dirty(label);
}

static uint32_t label_get_fgcol(window_t *label)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return 0;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return 0;
	}

	return data->fgcol;
}

static uint32_t label_get_bgcol(window_t *label)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return 0;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return 0;
	}

	return data->bgcol;
}

static void label_print(window_t *label, int x, int y, int maxwidth, char *text)
{
	label_t *data;
    glyph_t  *glyph;
    int   tabwidth = ( (maxwidth - x )  ) / 6;
    int width  = 0;

	if(! label) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

    /* Check to see if a font is defined */
    if(! data->font) {
        Dprintf(ERROR, "No font defined for label\n");
        return;
    }

    while ( *text ) {
        switch ( *text ) {
        case '\t':        /* Do some nasty stuff to calculate tab stops,
                             only really works for a full display */
            glyph_set_height(&nbsp, font_get_height(data->font));
            while ( x + 1 < ( ( x / tabwidth ) + 1 ) * tabwidth && x < maxwidth ) {
                label_printchar(label,x,y, &nbsp);
                x++;
            }
            break;
			/*
        case '\n':
            Dprintf(DEBUG, "label_print(cr)\n");
            glyph_set_height(&nbsp, font_get_height(data->font));
            width = glyph_get_width(&nbsp);
            y += font_get_height(data->font);
			x = label_calc_x(label);
            if ( y >= window_get_height(label) - window_get_yoffset(label)) {
                return;
            }
            break;
			*/
        default:
            if(font_is_defined(data->font, *(unsigned char *)text)) {
                glyph = font_get_glyph(data->font, *(unsigned char *)text);
                width = glyph_get_width(glyph);
                if ( x + width < maxwidth &&
                     ( y < window_get_height(label) - window_get_yoffset(label)) ) {
                    label_printchar(label,x,y,glyph);
                    x += width;
                }
            }
            break;
        }
        text++;
    }
}

static void label_printchar(window_t *label,int x, int y, glyph_t *glyph)
{
	label_t *data;
    int *bitmap;
    int i,j, mask;
    int width, height;

	if(! label) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

    bitmap = glyph_get_bitmap(glyph);

    width = glyph_get_width(glyph);
    height = glyph_get_height(glyph);

    for(j = 0 ; j < height; j++) {
        for ( i = 0; i < width; i++ ) {
            mask = 1 << i;
            if ( bitmap && (bitmap[j] & mask ) ) {
                surface_set_pixel(window_get_contents(label),x + (width - i),y,data->fgcol);
            } else {
                surface_set_pixel(window_get_contents(label),x + (width - i),y,data->bgcol);
            }
        }
        y++;
    }
}

void label_set_align(window_t *label, int align)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

	data->align = align;

	window_mark_dirty(label);
}

void label_set_valign(window_t *label, int valign)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

	data->valign = valign;
	window_mark_dirty(label);

	return;
}


char label_get_align(window_t *label)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return 0;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return 0;
	}

	return data->align;
}

char label_get_valign(window_t *label)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return 0;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return 0;
	}

	return data->valign;
}

static void delete_label_data(window_t *label)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

	free(data->text);
	free(data);

	window_set_data(label, NULL);
}

void label_set_text(window_t *label, char *text)
{
	label_t *data;

	if(window_get_type(label) != WINDOW_LABEL) {
		return;
	}

	if(! (data = (label_t *)window_get_data(label)) ) {
		return;
	}

	free(data->text);
	data->text = (char *)strdup(text);
    
    window_mark_dirty(label);

}

/*
 * Local Variables:
 *  indent-tabs-mode:nil
 *  require-final-newline:t
 *  c-basic-offset: 4
 * End:
 */
