/*
 * DATlib   Copyright (c) 1995-1996 Marcus Meissner &
 *          Friedrich-Alexander Universitaet Erlangen-Nuernberg (FAU), IMMD4
 *          All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Marcus Meissner
 *    at the Friedrich-Alexander Universitaet Erlangen-Nuernberg (FAU), IMMD4
 *
 * 4. The name of the University or the author may not be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND THE AUTHOR ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR THE AUTHOR BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <stdio.h>

#define MAXX	10
#define MAXY	20

#define MIDX	(MAXX/2)
#define MIDY	(MAXY/2)

#include "_7seg.h"

void
init_ixbm(struct ixbm *xb,int width,int height) {
	width = (width+7)&~7;
	xb->width	= width;
	xb->height	= height;
	xb->bits	= (unsigned char*)malloc((width*height)/8);
	memset(xb->bits,'\0',(width*height)/8);
	return;
}

void
drawpixel(struct ixbm *xb,int x,int y,int f) {
	int	bitnr,byte,bit;

	if (x>=xb->width ||  y>=xb->height || x<0 || y<0)
		return;
	bitnr=xb->width*y+x;
	byte= bitnr>>3;
	bit = (bitnr&7)^7;
	xb->bits[byte] = (xb->bits[byte] & ~(1<<bit))| (f<<bit);
}

void
drawline(struct ixbm *xb,int x1,int y1,int x2,int y2,int f) {
	int	dx,dy,i;
	float	Dx,Dy;

	if (x1<0 || y1<0 || y2<0 || x2<0)
		return;
	if (x1>=xb->width || x2>=xb->width || y1>=xb->height || y2>=xb->height)
		return;
	dx=x2-x1;
	dy=y2-y1;
	if (!dy) {
		if (x2<x1) {i=x1;x1=x2;x2=i;}
		for (i=x1;i<x2;i++)
			drawpixel(xb,i,y1,f);
		return;
	}
	if (!dx) {
		if (y2<y1) {i=y1;y1=y2;y2=i;}
		for (i=y1;i<y2;i++)
			drawpixel(xb,x1,i,f);
		return;
	}
	fprintf(stderr,"schraege linien not supported yet :)\n");
}

void
disp7seg(struct ixbm* xb,int *px,int *py,int mask) {
	int		x=*px,y=*py;
	int		f;

	/*  ----1----         
	 * |         |
	 * |         |
	 * |         |
	 * |         |
	 * 2         4
	 * |         |
	 * |         |
	 * |         |
	 * |         |
	 *  ----8---- 
	 * |         |
	 * |         |
	 * |         |
	 * |         |
	 * 16       32
	 * |         |
	 * |         |
	 * |         |
	 * |         |
	 *  ----64--- 
	 */
	
	
#define	MASK(x)	if (mask&x) f=1;else f=0;
	MASK(1);
		drawline(xb,x+1 ,y   ,x+MAXX-1 ,y  ,f);
	MASK(2);
		drawline(xb,x   ,y+1 ,x   ,y+MIDY-1 ,f);
	MASK(4);
		drawline(xb,x+MAXX,y+1 ,x+MAXX,y+MIDY-1 ,f);
	MASK(8);
		drawline(xb,x+1 ,y+MIDY,x+MAXX-1 ,y+MIDY,f);
	MASK(16);
		drawline(xb,x   ,y+MIDY+1,x   ,y+MAXY-1,f);
	MASK(32);
		drawline(xb,x+MAXX,y+11,x+MAXX,y+MAXY-1,f);
	MASK(64);
		drawline(xb,x+1 ,y+MAXY,x+MAXX-1 ,y+MAXY,f);
	*px+=MAXX+2;
}

static int	letter2nr[128]={
0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0,	/* control chars */

/* */0,
/*!*/0,
0,0, 0,0,0,
/*'*/0,
0,0,0,0,0,
/*-*/8|256,
0,
0,
0,
/*0*/0,
/*1*/0,
/*2*/0,
/*3*/0,
/*4*/0,
/*5*/0,
/*6*/0,
/*7*/0,
/*8*/0,
/*9*/0,
0,0,0,0,
/*?*/0,
0,			/* @ */
/*A*/	16|8|256|1024|262144|524288,
/*B*/	1|2|4|8|256|16|1024|64|512,
/*C*/	1|128|2|16|64|512,
/*D*/	1|2|4|256|16|1024|64|512,
/*E*/	1|2|128|8|16|64|512,
/*F*/	1|128|2|16|8,
/*G*/	1|2|16|64|512|1024|256,
/*H*/	2|2048|8|256|16|1024,
/*I*/	1|128|4|32|64|512,
/*J*/	1|128|2048|1024|512|64|16,
/*K*/	2|8|16|8192|16384,
/*L*/	2|16|64|512,
/*M*/	16|2|1|4|128|2048|1024,
/*N*/	16|2|4096|8192|2048|1024,
/*O*/	2|16|1|128|2048|1024|64|512,
/*P*/	1|128|2|2048|8|256|16,
/*Q*/	1|128|2|16|64|512|2048|1024, /*FIXME*/
/*R*/	1|128|2|2048|8|256|16|8192,
/*S*/	1|128|2|8|256|1024|512|64,
/*T*/	1|128|4|32,
/*U*/	2|16|64|512|1024|2048,
/*V*/	2|131072|65536|2048,
/*W*/	2|16|32|64|512|1024|2048,
/*X*/	4096|8192|16384|32768,
/*Y*/	2|8|256|2048|32,
/*Z*/	1|128|32768|16384|64|512,
0,0,0,0,0,0,
/*A*/	16|8|256|1024|262144|524288,
/*B*/	1|2|4|8|256|16|1024|64|512,
/*C*/	1|128|2|16|64|512,
/*D*/	1|2|4|256|16|1024|64|512,
/*E*/	1|2|128|8|16|64|512,
/*F*/	1|128|2|16|8,
/*G*/	1|2|16|64|512|1024|256,
/*H*/	2|2048|8|256|16|1024,
/*I*/	1|128|4|32|64|512,
/*J*/	1|128|2048|1024|512|64|16,
/*K*/	2|8|16|8192|16384,
/*L*/	2|16|64|512,
/*M*/	16|2|1|4|128|2048|1024,
/*N*/	16|2|4096|8192|2048|1024,
/*O*/	2|16|1|128|2048|1024|64|512,
/*P*/	1|128|2|2048|8|256|16,
/*Q*/	1|128|2|16|64|512|2048|1024, /*FIXME*/
/*R*/	1|128|2|2048|8|256|16|8192,
/*S*/	1|128|2|8|256|1024|512|64,
/*T*/	1|128|4|32,
/*U*/	2|16|64|512|1024|2048,
/*V*/	2|131072|65536|2048,
/*W*/	2|16|32|64|512|1024|2048,
/*X*/	4096|8192|16384|32768,
/*Y*/	32|4096|16384,
/*Z*/	1|128|32768|16384|64|512,
0,0,0,0,0
};

void
disp7letter(struct ixbm *xb,int *px,int *py,int letter) {
	int		x=*px,y=*py;
	int		i,f;
	unsigned long	mask;

	mask=letter2nr[letter];
	/*  ----1---- ---128---
	 * |\       /|\       /|
	 * | 4     5 | 2     / |
	 * |  0   2  |  6   4  2
	 * |   9 4   |   2 8   0
	 * 2    6    4    3    4
	 * |   2 \   |   6 1   8
	 * |  8   \  |  1   4  |
	 * | 8     \ | /     4 |
	 * |/       \|/       \|
	 *  ----8---- ---256---
	 * |\       /|\       /|
	 * | 2     / | \     / |
	 * |  7   /  |  8   6  1
	 * |   0 8   |   1 3   0
	 * 16   6   32    9    2
	 * |   7 1   |   5 2   4
	 * |  2   3  |  5   \  |
	 * | 3     1 | 6     \ |
	 * |/       \|/       \|
	 *  ----64--- ---512---
	 */
	
#define	MASK(x)	if (mask&x) f=1;else f=0;
	MASK(4096);
		drawline(xb,x+1	,y+1	,x+MIDX-1,y+MIDY-1,f);
	MASK(131072);
		drawline(xb,x+1	,y+MIDY+1,x+MIDX-1,y+MAXY-1,f);
	MASK(262144);
		drawline(xb,x+MIDX+1	,y+1	,x+MAXX-1,y+MIDY-1,f);
	MASK(8192);
		drawline(xb,x+MIDX+1	,y+MIDY+1,x+MAXX-1,y+MAXY-1,f);
	MASK(131072);
		drawline(xb,x+1	,y+MIDY+1,x+MIDX-1,y+MAXY-1,f);
	MASK(524288);
		drawline(xb,x+MIDX-1	,y+1,x+1,y+MIDY-1,f);
	MASK(16384);
		drawline(xb,x+MAXX-1	,y+1,x+MIDX+1,y+MIDY-1,f);
	MASK(32768);
		drawline(xb,x+MIDX-1	,y+MIDY+1,x+1,y+MAXY-1,f);
	MASK(65536);
		drawline(xb,x+MAXX-1	,y+MIDY+1,x+MIDX+1,y+MAXY-1,f);
	MASK(1);
		drawline(xb,x+1	,y	,x+MIDX-1,y,f);
	MASK(128);
		drawline(xb,x+1+MIDX	,y	,x+MAXX-1,y,f);
	MASK(2);
		drawline(xb,x		,y+1	,x	,y+MIDY-1,f);
	MASK(4);
		drawline(xb,x+MIDX	,y+1	,x+MIDX	,y+MIDY-1,f);
	MASK(2048);
		drawline(xb,x+MAXX	,y+1	,x+MAXX	,y+MIDY-1,f);
	MASK(8);
		drawline(xb,x+1	,y+MIDY	,x+MIDX-1,y+MIDY,f);
	MASK(256);
		drawline(xb,x+MIDX+1	,y+MIDY	,x+MAXX-1,y+MIDY,f);
	MASK(16);
		drawline(xb,x		,y+MIDY+1,x	,y+MAXY-1,f);
	MASK(32);
		drawline(xb,x+MIDX	,y+MIDY+1,x+MIDX,y+MAXY-1,f);
	MASK(1024);
		drawline(xb,x+MAXX	,y+MIDY+1,x+MAXX,y+MAXY-1,f);
	MASK(64);
		drawline(xb,x+1	,y+MAXY	,x+MIDX-1,y+MAXY,f);
	MASK(512);
		drawline(xb,x+MIDX+1	,y+MAXY	,x+MAXX-1,y+MAXY,f);
	*px+=MAXX+2;
}

void
disp7dp(struct ixbm *xb,int *x,int *y) {
	/*
	 *
	 *
	 *
	 *
	 *
	 *
	 * |
	 * |
	 *
	 *
	 * |
	 * |
	 *
	 *
	 *
	 *
	 *
	 *
	 *
	 *
	 *
	 */
	*x=(*x)+2;
	drawline(xb,*x,*y+6 ,*x,*y+8 ,1);
	drawline(xb,*x,*y+11,*x,*y+13,1);
	*x=(*x)+2;
}

static int nr2mask[10]={
	1|2|4|16|32|64,
	4|32,
	1|4|8|16|64,
	1|4|8|32|64,
	2|4|8|32,
	1|2|8|32|64,
	1|2|16|8|32|64,
	1|4|32,
	1|2|4|8|16|32|64,
	1|2|4|8|32|64,
};

void
disp7segnr(struct ixbm *xb,int *x,int *y,int nr,int res) {
	int	i;

	for (i=1;res--;i=i*10)
		/*EMPTY*/;
	for (;i=i/10;) {
		disp7seg(xb,x,y,nr2mask[(nr/i)%10]);
		*x+=2;
		nr=nr-((nr/i)%10)*i;
	}
}
