#include <stdio.h>
#include <utils.h>
#include <pmp/pmp.h>
#include "banner.h"

/***============================================================***/

typedef	unsigned char letter;

#define BAN_MAX_EXPANSION	4

#define BAN_MV_PREFIX	0xee
#define width(w)	w
#define move(x,y)	BAN_MV_PREFIX,x,y
#define draw(x,y)	x,y
#define done	0xff

/***============================================================***/

static letter p_space[]=	{ 	width(8),			done };
static letter p_bang[]=	{ 	width(5),
				draw(1,0),draw(0,6),draw(0,0),
		move(0,8),	draw(0,9), 			done };
static letter p_dquote[]=	{ 	width(4),
				draw(0,3),
		move(2,0),	draw(2,3),			done };
static letter p_sharp[]=	{ 	width(9),
		move(2,0),	draw(2,8),
		move(4,0),	draw(4,8),
		move(0,2),	draw(6,2),
		move(0,6),	draw(6,6),			done };
static letter p_dollar[]=	{	width(9),
		move(2,0),	draw(2,8),
		move(4,8),	draw(4,0),
		move(6,1),	draw(1,1),draw(0,2),draw(0,3),draw(1,4),
				draw(5,4),draw(6,5),draw(6,6),draw(5,7),
				draw(0,7),			done };
static letter p_percent[]= 	{	width(9),
		move(6,1),	draw(0,7),
		move(1,0),	draw(2,1),draw(1,2),draw(0,1),draw(1,0),
		move(5,6),	draw(6,7),draw(5,8),draw(4,7),draw(5,6),
								done };
static letter p_amp[]=		{ 	width(9),
		move(5,5),	draw(5,7),draw(4,8),draw(1,8),draw(0,7),
				draw(0,5),draw(3,2),draw(3,1),draw(2,0),
				draw(1,0),draw(0,1),draw(0,2),draw(6,8),
								done };
static letter p_squote[]=	{	width(5),
		move(0,3),	draw(2,1),draw(2,0),draw(1,0),draw(1,1),
								done };
static letter p_oparen[]=	{	width(5),
		move(2,0),	draw(0,2),draw(0,6),draw(2,8),	done };
static letter p_cparen[]=	{	width(5),
				draw(2,2),draw(2,6),draw(0,8),	done };
static letter p_star[]=	{	width(9),
		move(0,2),	draw(3,4),draw(0,6),
		move(6,2),	draw(3,4),draw(6,6),
		move(3,1),	draw(3,7),			done};
static letter p_plus[]=	{	width(9),
		move(3,1),	draw(3,7),
		move(0,4),	draw(6,4),			done};
static letter p_comma[]=	{	width(5),
		move(0,10),	draw(2,8),draw(2,7),draw(1,7),draw(1,9),
								done};
static letter p_minus[]=	{	width(9),
		move(0,4),	draw(6,4),			done};
static letter p_period[]=	{	width(5),
		move(0,8),	draw(1,8),draw(1,9),draw(0,9),draw(0,8),
								done};
static letter p_slash[]=	{	width(8),
		move(0,8),	draw(5,0),			done};

static letter p_0[]=	{		width(9),
		move(0,2),	draw(2,0),draw(4,0),draw(6,2),draw(6,6),
				draw(4,8),draw(2,8),draw(0,6),draw(0,2),
		move(1,6),	draw(5,2),			done};
static letter p_1[]=	{		width(7),
		move(0,2),	draw(2,0),draw(2,8),
		move(0,8),	draw(4,8),			done};
static letter p_2[]=	{		width(9),
		move(0,1),	draw(1,0),draw(5,0),draw(6,1),draw(6,3),
				draw(5,4),draw(1,4),draw(0,5),draw(0,7),
				draw(0,8),draw(6,8),		done};
static letter p_3[]=	{		width(9),
		move(0,1),	draw(1,0),draw(5,0),draw(6,1),draw(6,3),
				draw(5,4),draw(3,4),draw(5,4),draw(6,5),
				draw(6,7),draw(5,8),draw(1,8),draw(0,7),
								done};
static letter p_4[]=	{		width(9),
		move(5,8),	draw(5,0),draw(0,5),draw(0,6),draw(6,6),
								done};
static letter p_5[]=	{		width(9),
		move(6,0),	draw(0,0),draw(0,3),draw(1,4),draw(5,4),
				draw(6,5),draw(6,7),draw(5,8),draw(1,8),
				draw(0,7),			done};
static letter p_6[]=	{		width(9),
		move(5,0),	draw(2,0),draw(0,2),draw(0,7),draw(1,8),
				draw(5,8),draw(6,7),draw(6,5),draw(5,4),
				draw(1,4),			done};
static letter p_7[]=	{		width(9),
		move(0,1),	draw(0,0),draw(6,0),draw(6,1),draw(1,6),
				draw(1,8),
		move(1,4),	draw(5,4),			done};
static letter p_8[]=	{		width(9),
		move(1,0),	draw(5,0),draw(6,1),draw(6,3),draw(5,4),
				draw(6,5),draw(6,7),draw(5,8),draw(1,8),
				draw(0,7),draw(0,5),draw(1,4),draw(0,3),
				draw(0,1),draw(1,0),
		move(2,4),	draw(5,4),			done};
static letter p_9[]=	{		width(9),
		move(5,4),	draw(1,4),draw(0,3),draw(0,1),draw(1,0),
				draw(5,0),draw(6,1),draw(6,7),draw(5,8),
				draw(1,8),			done};
static letter p_colon[]=	{	width(4),
		move(0,4),	draw(1,4),draw(1,3),draw(0,3),draw(0,4),
		move(0,7),	draw(1,7),draw(1,6),draw(0,6),draw(0,7),
								done};
static letter p_semi[]=	{	width(5),
		move(1,5),	draw(2,5),draw(2,4),draw(1,4),draw(1,5),
		move(1,9),	draw(1,7),draw(2,7),draw(2,8),draw(0,10),
								done};
static letter p_less[]=	{	width(7),
		move(4,0),	draw(0,4),draw(4,8),		done};
static letter p_equal[]=	{	width(9),
		move(0,3),	draw(6,3),
		move(0,5),	draw(6,5),			done};
static letter p_greater[]=	{	width(7),
				draw(4,4),draw(0,8),		done};
static letter p_question[]=	{	width(9),
		move(0,1),	draw(1,0),draw(5,0),draw(6,1),draw(6,3),
				draw(5,4),draw(3,4),draw(2,5),draw(2,6),
		move(2,8),	draw(2,9),			done};
static letter p_atsign[]=	{	width(9),
		move(6,7),	draw(5,8),draw(2,8),draw(0,6),draw(0,2),
				draw(2,0),draw(5,0),draw(6,1),draw(6,5),
				draw(5,6),draw(4,5),draw(4,2),draw(3,2),
				draw(2,3),draw(2,5),draw(3,6),draw(4,5),
								done};
static letter p_A[]=	{		width(9),
		move(0,8),	draw(0,3),draw(3,0),draw(6,3),draw(6,8),
		move(1,5),	draw(6,5),			done};
static letter p_B[]=	{		width(9),
		move(0,8),	draw(0,0),draw(5,0),draw(6,1),draw(6,3),
				draw(5,4),draw(1,4),draw(5,4),draw(6,5),
				draw(6,7),draw(5,8),draw(1,8),	done};
static letter p_C[]=	{		width(9),
		move(6,1),	draw(5,0),draw(1,0),draw(0,1),draw(0,7),
				draw(1,8),draw(5,8),draw(6,7),	done};
static letter p_D[]=	{		width(9),
		move(0,8),	draw(0,0),draw(4,0),draw(6,2),draw(6,6),
				draw(4,8),draw(1,8),		done};
static letter p_E[]=	{		width(9),
		move(6,0),	draw(0,0),draw(0,8),draw(6,8),
		move(0,4),	draw(4,4),			done};
static letter p_F[]=	{		width(9),
		move(6,0),	draw(0,0),draw(0,8),
		move(0,4),	draw(4,4),			done};
static letter p_G[]=	{		width(9),
		move(6,1),	draw(5,0),draw(1,0),draw(0,1),draw(0,7),
				draw(1,8),draw(5,8),draw(6,7),draw(6,4),
				draw(3,4),			done};
static letter p_H[]=	{		width(9),
				draw(0,8),
		move(6,0),	draw(6,8),
		move(0,4),	draw(6,4),			done};
static letter p_I[]=	{		width(7),
				draw(4,0),draw(2,0),draw(2,8),draw(0,8),
				draw(4,8),			done};
static letter p_J[]=	{		width(9),
		move(5,0),	draw(5,7),draw(4,8),draw(1,8),draw(0,7),
				draw(0,6),			done};
static letter p_K[]=	{		width(9),
				draw(0,8),draw(0,5),draw(5,0),
		move(2,4),	draw(6,8),			done};
static letter p_L[]=	{		width(9),
				draw(0,8),draw(6,8),		done};
static letter p_M[]=	{		width(11),
		move(0,8),	draw(0,1),draw(1,0),draw(4,3),draw(4,6),
				draw(4,3),draw(7,0),draw(8,1),draw(8,8),
								done};
static letter p_N[]=	{		width(9),
		move(0,8),	draw(0,0),draw(6,8),draw(6,0),	done};
static letter p_O[]=	{		width(9),
		move(1,0),	draw(5,0),draw(6,1),draw(6,7),draw(5,8),
				draw(1,8),draw(0,7),draw(0,1),draw(1,0),
								done};
static letter p_P[]=	{		width(9),
		move(0,8),	draw(0,0),draw(5,0),draw(6,1),draw(6,3),
				draw(5,4),draw(1,4),		done};
static letter p_Q[]=	{		width(9),
		move(0,2),	draw(0,6),draw(2,8),draw(4,8),draw(6,6),
				draw(6,2),draw(4,0),draw(2,0),draw(0,2),
		move(4,6),	draw(6,8),			done};
static letter p_R[]=	{		width(9),
		move(0,8),	draw(0,0),draw(5,0),draw(6,1),draw(6,3),
				draw(5,4),draw(1,4),draw(3,4),draw(6,8),
								done};
static letter p_S[]=	{		width(9),
		move(0,7),	draw(1,8),draw(4,8),draw(6,6),draw(6,4),
				draw(5,3),draw(1,3),draw(0,2),draw(2,0),
				draw(5,0),draw(6,1),		done};
static letter p_T[]=	{		width(9),
				draw(6,0),draw(3,0),draw(3,8),	done};
static letter p_U[]=	{		width(9),
				draw(0,7),draw(1,8),draw(5,8),draw(6,7),
				draw(6,0),			done};
static letter p_V[]=	{		width(9),
				draw(0,4),draw(3,8),draw(6,4),draw(6,0),
								done};
static letter p_W[]=	{		width(11),
				draw(0,6),draw(2,8),draw(4,6),draw(4,3),
				draw(4,6),draw(6,8),draw(8,6),draw(8,0),
								done};
static letter p_X[]=	{		width(9),
				draw(0,1),draw(6,7),draw(6,8),
		move(0,8),	draw(0,7),draw(6,1),draw(6,0),	done};
static letter p_Y[]=	{		width(9),
				draw(0,3),draw(3,5),draw(3,8),draw(3,5),
				draw(6,3),draw(6,0),		done};
static letter p_Z[]=	{		width(9),
				draw(6,0),draw(6,1),draw(0,7),draw(0,8),
				draw(6,8),			done};
static letter p_obracket[]=	{	width(6),
		move(3,0),	draw(0,0),draw(0,8),draw(3,8),	done};
static letter p_bkslash[]=	{	width(8),
				draw(5,8),	done};
static letter p_cbracket[]=	{	width(6),
				draw(3,0),draw(3,8),draw(0,8),	done};
static letter p_caret[]=	{	width(9),
		move(0,3),	draw(3,0),draw(6,3),		done};
static letter p_underbar[]=	{	width(8),
		move(0,9),	draw(8,9),			done};
static letter p_bkquote[]=	{	width(5),
		move(2,3),	draw(0,1),draw(0,0),draw(1,0),draw(1,1),
								done};
static letter p_a[]=	{		width(8),
		move(1,3),	draw(4,3),draw(5,4),draw(5,8),draw(5,7),
				draw(4,8),draw(1,8),draw(0,7),draw(0,6),
				draw(1,5),draw(4,5),		done};
static letter p_b[]=	{		width(8),
				draw(0,8),draw(0,7),draw(1,8),draw(4,8),
				draw(5,7),draw(5,5),draw(4,4),draw(1,4),
								done};
static letter p_c[]=	{		width(8),
		move(5,4),	draw(4,3),draw(1,3),draw(0,4),draw(0,7),
				draw(1,8),draw(4,8),draw(5,7),	done};
static letter p_d[]=	{		width(8),
		move(5,0),	draw(5,8),draw(5,7),draw(4,8),draw(1,8),
				draw(0,7),draw(0,5),draw(1,4),draw(4,4),
								done};
static letter p_e[]=	{		width(8),
		move(5,7),	draw(4,8),draw(1,8),draw(0,7),draw(0,4),
				draw(1,3),draw(4,3),draw(5,4),draw(5,5),
				draw(1,5),			done};
static letter p_f[]=	{		width(6),
		move(4,1),	draw(3,0),draw(2,0),draw(1,1),draw(1,8),
		move(0,4),	draw(3,4),			done};
static letter p_g[]=	{		width(8),
		move(0,9),	draw(1,10),draw(4,10),draw(5,9),draw(5,3),
				draw(1,3),draw(0,4),draw(0,6),draw(1,7),
				draw(4,7),			done};
static letter p_h[]=	{		width(8),
				draw(0,8),draw(0,4),draw(1,3),draw(4,3),
				draw(5,4),draw(5,8),		done};
static letter p_i[]=	{		width(5),
		move(0,3),	draw(1,3),draw(1,8),draw(0,8),draw(2,8),
		move(1,1),	draw(1,1),			done};
static letter p_j[]=	{		width(6),
		move(0,9),	draw(1,10),draw(2,10),draw(3,9),draw(3,3),
		move(3,1),	draw(3,1),			done};
static letter p_k[]=	{		width(8),
				draw(0,8),draw(0,7),draw(5,2),draw(3,4),
				draw(5,8),			done};
static letter p_l[]=	{		width(4),
				draw(1,0),draw(1,8),draw(0,8),draw(2,8),
								done};
static letter p_m[]=	{		width(9),
		move(0,3),	draw(0,8),draw(0,4),draw(1,3),draw(3,5),
				draw(3,7),draw(3,5),draw(5,3),draw(6,4),
				draw(6,8),			done};
static letter p_n[]=	{		width(8),
		move(0,3),	draw(0,8),draw(0,5),draw(2,3),draw(4,3),
				draw(5,4),draw(5,8),		done};
static letter p_o[]=	{		width(8),
		move(0,4),	draw(1,3),draw(4,3),draw(5,4),draw(5,7),
				draw(4,8),draw(1,8),draw(0,7),draw(0,4),
								done};
static letter p_p[]=	{		width(8),
		move(0,10),	draw(0,3),draw(4,3),draw(5,4),draw(5,6),
				draw(4,7),draw(1,7),		done};
static letter p_q[]=	{		width(8),
		move(6,9),	draw(5,10),draw(5,3),draw(1,3),draw(0,4),
				draw(0,6),draw(1,7),draw(4,7),	done};
static letter p_r[]=	{		width(7),
		move(0,3),	draw(0,8),draw(0,5),draw(2,3),draw(4,3),
				draw(5,4),			done};
static letter p_s[]=	{		width(8),
		move(0,7),	draw(1,8),draw(4,8),draw(5,7),draw(5,6),
				draw(4,5),draw(1,5),draw(0,4),draw(1,3),
				draw(4,3),draw(5,4),		done};
static letter p_t[]=	{		width(5),
		move(1,1),	draw(1,7),draw(2,8),draw(3,7),
		move(0,3),	draw(2,3),			done};
static letter p_u[]=	{		width(8),
		move(0,3),	draw(0,7),draw(1,8),draw(4,8),draw(5,7),
				draw(5,3),draw(5,8),		done};
static letter p_v[]=	{		width(8),
		move(0,3),	draw(0,6),draw(2,8),draw(3,8),draw(5,6),
				draw(5,3),			done};
static letter p_w[]=	{		width(9),
		move(0,3),	draw(0,7),draw(1,8),draw(3,6),draw(3,4),
				draw(3,6),draw(5,8),draw(6,7),draw(6,3),
								done};
static letter p_x[]=	{		width(8),
		move(0,3),	draw(5,8),
		move(0,8),	draw(5,3),			done};
static letter p_y[]=	{		width(8),
		move(0,3),	draw(0,6),draw(1,7),draw(4,7),draw(5,6),
				draw(5,3),draw(5,9),draw(4,10),draw(1,10),
				draw(0,9),			done};
static letter p_z[]=	{		width(8),
		move(0,3),	draw(5,3),draw(0,8),draw(5,8),	done};
static letter p_obrace[]=	{	width(5),
		move(2,0),	draw(1,1),draw(1,3),draw(0,4),draw(1,5),
				draw(1,7),draw(2,8),		done};
static letter p_bar[]=		{	width(3),
				draw(0,3),
		move(0,5),	draw(0,8),			done};
static letter p_cbrace[]=	{	width(5),
				draw(1,1),draw(1,3),draw(2,4),draw(1,5),
				draw(1,7),draw(0,8),		done};
static letter p_tilde[]=	{	width(7),
		move(0,1),	draw(1,0),draw(2,0),draw(3,1),draw(4,1),
				draw(5,0),			done};

static letter *ascii['~'-' '+1]= {
	p_space,	p_bang,		p_dquote,	p_sharp,
	p_dollar,	p_percent,	p_amp,		p_squote,
	p_oparen,	p_cparen,	p_star,		p_plus,
	p_comma,	p_minus,	p_period,	p_slash,
	p_0,		p_1,		p_2,		p_3,
	p_4,		p_5,		p_6,		p_7,
	p_8,		p_9,		p_colon,	p_semi,
	p_less,		p_equal,	p_greater,	p_question,
	p_atsign,	p_A,		p_B,		p_C,
	p_D,		p_E,		p_F,		p_G,
	p_H,		p_I,		p_J,		p_K,
	p_L,		p_M,		p_N,		p_O,
	p_P,		p_Q,		p_R,		p_S,
	p_T,		p_U,		p_V,		p_W,
	p_X,		p_Y,		p_Z,		p_obracket,
	p_bkslash,	p_cbracket,	p_caret,	p_underbar,
	p_bkquote,	p_a,		p_b,		p_c,
	p_d,		p_e,		p_f,		p_g,
	p_h,		p_i,		p_j,		p_k,
	p_l,		p_m,		p_n,		p_o,
	p_p,		p_q,		p_r,		p_s,
	p_t,		p_u,		p_v,		p_w,
	p_x,		p_y,		p_z,		p_obrace,
	p_bar,		p_cbrace,	p_tilde};

/***============================================================***/

	int ban_debug;
static	int ban_size=		2;

static int
_ban_scale(x,y)
register1 int *x,*y;
{
    D_ENTRY2(ban_debug,"_ban_scale(0x%x,0x%x)\n",x,y);
    *x= ((*x)*BAN_MAX_EXPANSION*BAN_X_ASPECT*ban_size)/BAN_MAX_SIZE;
    *y= ((*y)*BAN_MAX_EXPANSION*BAN_Y_ASPECT*ban_size)/BAN_MAX_SIZE;
    RETURN(TRUE);
}

static int 	ban_width=	0;
static xform	ban_transform=	_ban_scale;

/***============================================================***/

_ban_putptrn(ptrn)
register1 letter 	*ptrn;
{
	  int	x=       0;
	  int	y=       0;
register2 int	last_x=  0;
register3 int	last_y=	 0;
register4 int	chwidth;

    D_ENTRY1(ban_debug,"_ban_putptrn(0x%x)\n",ptrn);
    chwidth= *ptrn++;
    x=0;
    y=0;
    (*ban_transform)(&x,&y);
    p_mv_relative(x-last_x,y-last_y);
    while (*ptrn!=done) {
	if (*ptrn==BAN_MV_PREFIX) {
	    ptrn++;
	    x= (*ptrn++);
	    y= (*ptrn++);
	    (*ban_transform)(&x,&y);
	    p_mv_relative(x-last_x,y-last_y);
	}
	else {
	    x= (*ptrn++);
	    y= (*ptrn++);
	    (*ban_transform)(&x,&y);
	    if ((x==last_x)&&(y==last_y))
		y+=1;
	    p_vec_relative(x-last_x,y-last_y);
	}
	last_x= x;
	last_y= y;
    }
    if (ban_width)	x= ban_width;
    else		x= chwidth;
    y= 0;
    (*ban_transform)(&x,&y);
    p_mv_relative(x-last_x,y-last_y);
    RETURN(x);
}

/***============================================================***/

ban_set_size(size)
register1 int size;
{
    D_ENTRY1(ban_debug,"ban_set_size(%d)\n",size);
    if ((size<BAN_MIN_SIZE)||(size>BAN_MAX_SIZE)) 
	RETURN(FALSE);
    ban_size= size;
    size= (size*BAN_MAX_EXPANSION*BAN_Y_ASPECT)/BAN_MAX_SIZE;
    if		(size<1)			size= 1;
    else if 	(size>P_VECTOR_MAX_WIDTH)	size= P_VECTOR_MAX_WIDTH;
    p_vec_set_width(size);
    p_vec_set_ends(P_VECTOR_ROUND_ENDS);
    RETURN(TRUE);
}

/***============================================================***/

xform 
ban_set_transform(new)
register1 xform new;
{
register2 xform old;

    D_ENTRY1(ban_debug,"ban_set_transform(0x%x)\n",new);
    old= ban_transform;
    if (new)	ban_transform= new;
    else 	ban_transform= _ban_scale;
    RETURN(old);
}

/***============================================================***/

ban_putc(ch)
register1 char ch;
{
    D_ENTRY1(ban_debug,"ban_putc(%c)\n",ch);
    _ban_putptrn(ascii[ch-' ']);
    RETURN(TRUE);
}

/***============================================================***/

ban_putstr(str)
register1 char	*str;
{
    D_ENTRY1(ban_debug,"ban_putstr(%s)\n",str);
    while (*str) {
	_ban_putptrn(ascii[(*str++)-' ']);
    }
    RETURN(TRUE);
}

/***============================================================***/

ban_chwidth(ch)
register1 char ch;
{
int	top_row= 0;
int	chwidth;

    D_ENTRY1(ban_debug,"ban_chwidth(%c)\n",ch);
    if (ban_width)	chwidth= ban_width;
    else	    	chwidth= ascii[ch-' '][0];
    (*ban_transform)(&top_row,&chwidth);
    RETURN(chwidth);
}

/***============================================================***/

ban_strwidth(str)
register1 char *str;
{
int	top_row= 0;
int	chwidth;

    D_ENTRY1(ban_debug,"ban_chwidth(%s)\n",str);
    if (ban_width) {
	chwidth= ban_width*strlen(str);
    }
    else {
	chwidth= 0;
	while (*str) {
	    chwidth+= ascii[(*str++)-' '][0];
	}
    }
    (*ban_transform)(&top_row,&chwidth);
    RETURN(chwidth);
}

/***============================================================***/

ban_height()
{
int x= BAN_X_ASPECT;
int y= BAN_Y_ASPECT;

    D_ENTRY(ban_debug,"ban_height()\n");
    (*ban_transform)(&x,&y);
    RETURN(y);
}
