/*
 *  Copyright (C) Samuel Thibault <samuel.thibault@ens-lyon.org>
 *
 * This program is free software ; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation ; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY ; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the program ; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <assert.h>

#ifndef TEST
/* Print byte from its binary encoding */
#define P(b7,b6,b5,b4,b3,b2,b1,b0) \
	printf("%c", b0*1+b1*2+b2*4+b3*8+b4*16+b5*32+b6*64+b7*128)
#define _P(a) P(a)

/* Print big-endian double byte from its binary encoding */
#define P2(b15,b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0) \
	P(b15,b14,b13,b12,b11,b10,b9,b8); \
	P(b7,b6,b5,b4,b3,b2,b1,b0)
#define _P2(a) P2(a)

/* Print space */
#define DO_SPC() \
	P(0,0,0,0,0,0,0,0)
/* Print double-byte space */
#define DO_SPC2() \
	P2(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)


/* Print dots according to DESSIN */
#define _DO_DOTS(__x, __y) do { \
	int x = (__x), y = (__y);\
	_P(DESSIN); \
} while(0)
#define DO_DOTS(n,m) \
	_DO_DOTS( \
		!!(i&(1<<(n-1))), \
		!!(i&(1<<(m-1)))  \
			)

/* Print double-byte dots according to DESSIN1 */
#define _DO_DOTS1(__x,__y) do { \
	int x = (__x), y = (__y); \
	_P2(DESSIN1); \
} while(0)
#define DO_DOTS1(n,m) \
	_DO_DOTS1( \
		!!(i&(1<<(n-1))), \
		!!(i&(1<<(m-1))) \
		)

/* Print double-byte dots according to DESSIN2 */
#define _DO_DOTS2(__x,__y) do { \
	int x = (__x), y = (__y); \
	_P2(DESSIN2); \
} while(0)
#define DO_DOTS2(n,m) \
	_DO_DOTS2( \
		!!(i&(1<<(n-1))), \
		!!(i&(1<<(m-1))) \
		)


#else
#define HASH '#'
#define TOP \
	printf("/"); \
	for (j = 0; j < w; j++) \
		printf("-"); \
	printf("\\\n");
#define BOTTOM \
	printf("\\"); \
	for (j = 0; j < w; j++) \
		printf("-"); \
	printf("/\n");

#define LINEHEAD \
	if (i == 0) { TOP; continue; } \
	if (i == 1) n++; \
	if (i == 2) { assert(n == h); BOTTOM; break; } \

#define P(b7,b6,b5,b4,b3,b2,b1,b0) \
	LINEHEAD; \
	printf("|"); \
	if (w >= 1) printf("%c", b7 ? HASH : ' '); \
	if (w >= 2) printf("%c", b6 ? HASH : ' '); \
	if (w >= 3) printf("%c", b5 ? HASH : ' '); \
	if (w >= 4) printf("%c", b4 ? HASH : ' '); \
	if (w >= 5) printf("%c", b3 ? HASH : ' '); \
	if (w >= 6) printf("%c", b2 ? HASH : ' '); \
	if (w >= 7) printf("%c", b1 ? HASH : ' '); \
	if (w >= 8) printf("%c", b0 ? HASH : ' '); \
	printf("|\n");
#define _P(a) P(a)

#define P2(b15,b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0) \
	LINEHEAD; \
	printf("|"); \
	if (w >= 1) printf("%c",b15 ? HASH : ' '); \
	if (w >= 2) printf("%c",b14 ? HASH : ' '); \
	if (w >= 3) printf("%c",b13 ? HASH : ' '); \
	if (w >= 4) printf("%c",b12 ? HASH : ' '); \
	if (w >= 5) printf("%c",b11 ? HASH : ' '); \
	if (w >= 6) printf("%c",b10 ? HASH : ' '); \
	if (w >= 7) printf("%c", b9 ? HASH : ' '); \
	if (w >= 8) printf("%c", b8 ? HASH : ' '); \
	if (w >= 9) printf("%c", b7 ? HASH : ' '); \
	if (w >= 10) printf("%c", b6 ? HASH : ' '); \
	if (w >= 11) printf("%c", b5 ? HASH : ' '); \
	if (w >= 12) printf("%c", b4 ? HASH : ' '); \
	if (w >= 13) printf("%c", b3 ? HASH : ' '); \
	if (w >= 14) printf("%c", b2 ? HASH : ' '); \
	if (w >= 15) printf("%c", b1 ? HASH : ' '); \
	if (w >= 16) printf("%c", b0 ? HASH : ' '); \
	printf("|\n");
#define _P2(a) P2(a)

/* Print space */
#define DO_SPC() \
	P(0,0,0,0,0,0,0,0)
/* Print double-byte space */
#define DO_SPC2() \
	P2(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)

#define DO_DOTS(__x,__y) \
	_P(DESSIN);

#define DO_DOTS1(__x,__y) \
	_P2(DESSIN1);

#define DO_DOTS2(__x,__y) \
	_P2(DESSIN2);

#endif

