/*********************************************/
/*                                           */
/*	  Editor for all bitmaps				*/
/*                                           */
/*	  PC-VGA version from :				*/
/*                                           */
/*		Herve SOULARD, Paris, 1990		*/
/*                                           */
/*********************************************/

#include <stdio.h>
#include <malloc.h>
#include <graph.h>

#define	X_OFF	100
#define	Y_OFF	100

#define	X_SIZE	10
#define	Y_SIZE	10

#define	WIDTH		16
#define	HEIGHT	16

#define	MAXPGM	23

struct videoconfig config;
int sizePgm;

char *pgms[MAXPGM];
char *bitmap[MAXPGM];
char *name[MAXPGM];


void makePgm(char bitmap[],char pgms[])
{
	char *ptr,c;
	int i,j;
	unsigned r1,r2,r3,r4;
	unsigned *uptr;
	
	ptr = pgms;
	uptr = (unsigned *)pgms;
	
	if (ptr == NULL) {
		printf ("Erreur allocation (pgms)\n");
		exit(1);
	}	

	*ptr = WIDTH;
	*(ptr+2) = HEIGHT;
	*(ptr+1) = *(ptr+3) = 0;

	for (i=0; i < HEIGHT;i++) {
		r1 = r2 = r3 = r4 = 0;
		for (j=0; j < WIDTH; j++) {
			c = bitmap[(i*WIDTH)+j];
			if (c & 0x01)
				r1 |= (1 << ((WIDTH-1)-j));
			if (c & 0x02)
				r2 |= (1 << ((WIDTH-1)-j));
			if (c & 0x04)
				r3 |= (1 << ((WIDTH-1)-j));
			if (c & 0x08)
				r4 |= (1 << ((WIDTH-1)-j));
		}
		/*
			For compatibility with _putimage from Microsoft
			
		*(uptr+2+(i*4)) = r1;
		*(uptr+2+(i*4)+1) = r2;
		*(uptr+2+(i*4)+2) = r3;
		*(uptr+2+(i*4)+3) = r4;
		*/

		/*	Using my own _putimage (drawPgm)
		*/
		*(uptr+2+i) = r1;
		*(uptr+2+i+16) = r2;
		*(uptr+2+i+32) = r3;
		*(uptr+2+i+48) = r4;
	}
	for (i=4; i< sizePgm; i+=2) {
		c = *(ptr+i);
		*(ptr+i) = *(ptr+i+1);
		*(ptr+i+1) = c;
	}
}


void makePgms()
{
	int i;
	
	for (i = 0; i < MAXPGM;i++) {
		pgms[i] = (char *)malloc(sizePgm);
		makePgm(bitmap[i],pgms[i]);
	}
}

void drawBitmap(int num)
{
	char c;
	int i,j;
	int x,y;
	char *ptrBitmap;

	
	ptrBitmap = bitmap[num];
	makePgm(ptrBitmap,pgms[num]);
	
	drawPgm(num * 3,8,pgms[num],_GPSET);

	_settextposition(3,0);
	_outtext("                                                                               ");
	_settextposition(3,1 + (num * 3));
	_outtext("^");
	
	_settextposition(5,50);
	_outtext("                    ");
	_settextposition(5,50);
	_outtext(name[num]);
	
	for (i=0; i < HEIGHT;i++) {
		y = (i*(Y_SIZE+2)) + Y_OFF;
		for (j=0; j < WIDTH; j++) {
			c = ptrBitmap[(i*WIDTH)+j];
			_setcolor(c);
			x = (j*(X_SIZE+2)) + X_OFF;
			_rectangle(_GFILLINTERIOR, x, y, x + X_SIZE, y + Y_SIZE);
		}
	}
}


void drawColor()
{
	int i;
	int y;
	
	for (i=0;i<16;i++) {
		_setcolor(i);
		y = Y_OFF + (i*2*Y_SIZE);
		_rectangle(_GFILLINTERIOR, 450, y + 5,
			450 + 2 * X_SIZE, y + 2 * Y_SIZE);
	}
}

void setCursor(xC,yC,bitmap)
int xC,yC;
char bitmap[];
{
	char *ptr,c;
	int x,y;

	c = bitmap[(yC*WIDTH)+xC];
	_setcolor(15 - c);
	y = (yC*(Y_SIZE+2)) + Y_OFF;
	x = (xC*(X_SIZE+2)) + X_OFF;
	_rectangle(_GBORDER, x, y, x + X_SIZE, y + Y_SIZE);
}


void unsetCursor(xC,yC,bitmap)
int xC,yC;
char bitmap[];
{
	char *ptr,c;
	int x,y;

	c = bitmap[(yC*WIDTH)+xC];
	_setcolor(c);
	y = (yC*(Y_SIZE+2)) + Y_OFF;
	x = (xC*(X_SIZE+2)) + X_OFF;
	_rectangle(_GBORDER, x, y, x + X_SIZE, y + Y_SIZE);
}

void setColor(xC,yC,bitmap)
int xC,yC;
char bitmap[];
{
	char c;
	int aux;

	c = bitmap[(yC*WIDTH)+xC];
	_setcolor(c);
	aux = Y_OFF + (c*2*Y_SIZE);
	_rectangle(_GFILLINTERIOR, 480, aux + 5, 480+ 2*X_SIZE, aux + 2*Y_SIZE);
}


void unsetColor(xC,yC,bitmap)
int xC,yC;
char bitmap[];
{
	char c;
	int aux;

	c = bitmap[(yC*WIDTH)+xC];
	_setcolor(0);
	aux = Y_OFF + (c*2*Y_SIZE);
	_rectangle(_GFILLINTERIOR, 480, aux + 5, 480+ 2*X_SIZE, aux + 2*Y_SIZE);
}

void load()
{
	FILE *map;
	int i,j,k;
	char buf[300];
	int *ptr;
	char *aux;
	int color[WIDTH];
	
	strcpy(buf,"bitmaps.dat");
	map = fopen(buf,"r");
	if (map == 0) {
		printf("Erreur d'ouverture du fichier\n");
	}
	else {
		for (i = 0;i < MAXPGM;i++) {
			fgets(buf,300,map);
			bitmap[i] = (char *)malloc(HEIGHT * WIDTH);
			name[i] = (char *)malloc(80);
			sscanf(buf,"%s",name[i]);
			for (j = 0;j < HEIGHT;j++) {
				ptr = color;
				fgets(buf,300,map);
				sscanf(buf,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
					    ptr++,ptr++,ptr++,ptr++,ptr++,ptr++,ptr++,ptr++,ptr++,
						 ptr++,ptr++,ptr++,ptr++,ptr++,ptr++,ptr);
				for (k = 0; k < WIDTH;k++)
					bitmap[i][(j*WIDTH)+k] = (char)color[k];
			}
			fgets(buf,300,map);

		}
		fclose(map);
	}
}

void save()
{
	FILE *map;
	char filename[20];
	int i,j,k;
	
	strcpy(filename,"bitmaps.dat");
	map = fopen(filename,"w");
	if (map == 0) {
		printf("Erreur d'ouverture du fichier\n");
	}
	else {
		for (i = 0;i < MAXPGM;i++) {
			fprintf(map,"%s %2d\n",name[i],i);
			for (j = 0;j < HEIGHT;j++) {
				fprintf(map,"\t");
				for (k = 0;k < WIDTH;k++) 
					fprintf(map,"%2d ",bitmap[i][(j*WIDTH)+k]);
				fprintf(map,"\n");
			}
			fprintf(map,"\t\n");
		}
		fclose(map);
	}
}


main()
{
	int fin = 0;
	char keyhit;
	int num = 0;
	int x = 0;
	int y = 0;
	int color = 15;
	int aux;
	
	_setvideomode(_MAXRESMODE);
	_getvideoconfig(&config);
	sizePgm = (unsigned int)_imagesize(0,0,WIDTH-1,HEIGHT-1);

	load();
	makePgms();
	
	for (aux=0;aux < MAXPGM; aux++)
		drawPgm(aux * 3,8,pgms[aux],_GPSET);

	drawBitmap(num);

	drawColor();
	
	_setcolor(color);
	aux = Y_OFF + (color*2*Y_SIZE);
	_rectangle(_GFILLINTERIOR, 420, aux + 5, 420+ 2*X_SIZE, aux + 2*Y_SIZE);

	while (!fin) {
		setCursor(x,y,bitmap[num]);
		if (kbhit()) {
			keyhit = getch();
			if (keyhit == 0 || keyhit == 0xE0)
				keyhit = getch();
			switch (keyhit) {
				case 32 :
					unsetColor(x,y,bitmap[num]);
					bitmap[num][(y*16)+x] = color;
					drawBitmap(num);
					setColor(x,y,bitmap[num]);
					break;
				case 75 :
					unsetCursor(x,y,bitmap[num]);
					unsetColor(x,y,bitmap[num]);
					if (--x < 0)
						x = WIDTH-1;
					setCursor(x,y,bitmap[num]);
					setColor(x,y,bitmap[num]);
					break;
				case 72 :
					unsetCursor(x,y,bitmap[num]);
					unsetColor(x,y,bitmap[num]);
					if (--y < 0)
						y = HEIGHT-1;
					setCursor(x,y,bitmap[num]);
					setColor(x,y,bitmap[num]);
					break;
				case 80 :
					unsetCursor(x,y,bitmap[num]);
					unsetColor(x,y,bitmap[num]);
					if (++y > HEIGHT-1)
						y = 0;
					setCursor(x,y,bitmap[num]);
					setColor(x,y,bitmap[num]);
					break;
				case 77 :
					unsetCursor(x,y,bitmap[num]);
					unsetColor(x,y,bitmap[num]);
					if (++x > WIDTH-1)
						x = 0;
					setCursor(x,y,bitmap[num]);
					setColor(x,y,bitmap[num]);
					break;
				case 73 :
					unsetCursor(x,y,bitmap[num]);
					unsetColor(x,y,bitmap[num]);
					x = y = 0;
					if (++num > MAXPGM-1)
						num = 0;
					drawBitmap(num);
					setCursor(x,y,bitmap[num]);
					setColor(x,y,bitmap[num]);
					break;
				case 81 :
					unsetCursor(x,y,bitmap[num]);
					unsetColor(x,y,bitmap[num]);
					x = y = 0;
					if (--num < 0)
						num = MAXPGM-1;
					drawBitmap(num);
					setCursor(x,y,bitmap[num]);
					setColor(x,y,bitmap[num]);
					break;
				case 'S' :
				case 's' :
					save();
					break;
				case '+' :
					_setcolor(0);
					aux = Y_OFF + (color*2*Y_SIZE);
					_rectangle(_GFILLINTERIOR, 420, aux + 5, 
						      420+ 2*X_SIZE, aux + 2*Y_SIZE);
					if (++color > 15)
						color = 0;
					_setcolor(color);
					aux = Y_OFF + (color*2*Y_SIZE);
					_rectangle(_GFILLINTERIOR, 420, aux + 5, 
						      420+ 2*X_SIZE, aux + 2*Y_SIZE);

					break;
				case '-' :
					_setcolor(0);
					aux = Y_OFF + (color*2*Y_SIZE);
					_rectangle(_GFILLINTERIOR, 420, aux + 5, 
						      420+ 2*X_SIZE, aux + 2*Y_SIZE);
					if (--color < 0)
						color = 15;
					_setcolor(color);
					aux = Y_OFF + (color*2*Y_SIZE);
					_rectangle(_GFILLINTERIOR, 420, aux + 5, 
						      420+ 2*X_SIZE, aux + 2*Y_SIZE);
					break;
				case 27 :
					fin = 1;
					break;
			}
		}
		unsetCursor(x,y,bitmap[num]);
	}
	
	_setvideomode(_DEFAULTMODE);
	exit(0);
}

