/*
 * Copyright (c) 1997 Hong Hunsoo of (KAIST)
 * The Korea Advanced Institute of Science and Technology
 * 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. Neither the name of the KAIST nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include <memory.h>

#include "common.h"
#include "defs.h"
#include "hangul.h"

#define PATT_LEN 2048
#define ORIGIN 24

char2byte out_char2b[256];
unsigned char patterns[48][PATT_LEN]; /* 48 sufficient? */
struct fontset *fen, *fko;
int	columns;
int	biased;
struct character *chars[256];

int	convert_string(char *str, int len);
int	convert_string2nd(char *str, int len);
void	final_output(void);
void	clean_patterns(void);
void	put_patterns(void);
int	shoot_over, shoot_under, total_height;
void	usage(const int);

void
usage(const int should_I_die)
{
	static char *msg="usage: hbanner [-en bdf.file.for.english] "
		"[-ko bdf.file.for.korean]\n\t\t[-size howmany.columns]\n"
		"\t\tHere \"-size 0\" means that the columns number"
		" is infinity(==2000)\n";
	fprintf(stderr, "%s", msg); 
	if (should_I_die)
		exit(should_I_die);
	return;
}

int
main(int argc, char *argv[])
{
	char	inbuf0[LINE], inbuf1[LINE];
	int	tmp0, tmp1, sized, koreaned, englished;
	char	*bdf_korean, *bdf_english;
	char	**app, *p;

	sized = koreaned = englished = 1;
        for (app = (argv + 1); *app != NULL; app++) {
                p = *app;
                if (strcmp(p, "-ko") == 0) {
                        bdf_korean = *++app;
			koreaned = 0;
		} else if (strcmp(p, "-en") == 0) {
                        bdf_english = *++app;
			englished = 0;
                } else if (strcmp(p, "-size") == 0) {
                        columns = atoi(*++app);
			sized = 0;
			if (columns < -1)
				usage(1);
			if (columns == 0)
				columns = 2000;
		}
	}
	if (sized) {
		get_winsize(&tmp0, &tmp1);
		columns = tmp1;
	}
	if (koreaned)
		bdf_korean = "johabshg16.bdf";
	if (englished)
		bdf_english = "courB18.bdf";

	usage(0);
	

	fprintf(stderr, "initialization starts\nPlease wait a minite\n");
	fen = initial(bdf_english);
	fko = initial(bdf_korean);
	fprintf(stderr, "initialization ends\n");

	tmp0 = fen->f_boundingbox.bb_height + fen->f_boundingbox.bb_offy;
	tmp1 = fko->f_boundingbox.bb_height + fko->f_boundingbox.bb_offy;
	shoot_over  = LARGER(tmp0, tmp1);

	tmp0 = -fen->f_boundingbox.bb_offy;
	tmp1 = -fko->f_boundingbox.bb_offy;
	shoot_under = LARGER(tmp0, tmp1);
	total_height = shoot_under + shoot_over;
	biased = ORIGIN - shoot_over;

	while (fgets(inbuf0, LINE, stdin)) {
		inbuf0[strlen(inbuf0)-1] = 0;
		convert_ks_to_johab(inbuf0, inbuf1, strlen(inbuf0));
		if (convert_string2nd(inbuf1, strlen(inbuf1)))
			final_output();

	}

	return 0;
}

void
final_output(void)
{
	unsigned int accum;
	struct character *cp, **cpp;
	char    *p;
	int     i, j, printed, rel;
	int     height, offset, offset1;
	int     start, end;
	unsigned int bits;
	struct bbox *bp, *fbp;


	offset = 0;
	clean_patterns();

	accum = 0;
	printed = 0;
	cpp = chars;
	if (cpp[0])
		offset = - cpp[0]->c_bbox.bb_offx; /* XXX */
	else
		return;

	while ((cp = *cpp)) {
		fbp = &(cp->c_fontset->f_boundingbox);
		height = fbp->bb_height;
		bp = &cp->c_bbox;

		if (offset + bp->bb_offx + bp->bb_width > columns) {
			printed = accum;
			put_patterns();
			clean_patterns();
			offset = - fbp->bb_offx;
		}

		start = bp->bb_offx - fbp->bb_offx;
		end   = bp->bb_offx - fbp->bb_offx + bp->bb_width;

		rel = ORIGIN - (fbp->bb_offy + fbp->bb_height);
		offset1 = offset + fbp->bb_offx; /* XXX */
		for (i=0; i < height; i++) {
			bits = cp->c_rows[i];
			p = &patterns[rel+i][offset1];
			for (j= start; j < end; j++)
				if (step_mask[j] & bits)
					p[j] = 'X';
		}
		offset += cp->c_dwidth[0];
		cpp++;
		accum++;
	}
	if (accum != printed)
		put_patterns();
	return;
}

void
put_patterns(void)
{
	int     i, j, indx;
	char    *p;

	indx = 0;
	for (j=0; j < 10; j++)
		for (i=biased; i < (biased + total_height); i++)
			if (patterns[i][j] != '.') {
				indx = j;
				j = 100; /* to break double */
				break;
			}

	for (i= biased; i < (biased + total_height); i++) {
		p = &patterns[i][columns+30];
		while (*--p == '.')
			*p = 0;
		printf("%s\n", &patterns[i][indx]);
	}
	return;
}

void
clean_patterns(void)
{
	int     i;

	for (i=0; i< 48;i++)
		memset(patterns[i], '.', PATT_LEN);
	return;
}


int
convert_string(char *str, int len)
{
	int     n, i, ret;
	char   *p;
	unsigned short *shp;
	struct character **charpp;

	charpp = &chars[0];
	ret = 0;
	while (len > 0) {
		if (*str & 0x80) {
			for (p = str; len > 0 && *p & 0x80; p += 2, len -= 2)
				/* void */ ;
			n = convert_johab_to_display(str, out_char2b, p - str);
			shp = (unsigned short *) out_char2b;
			for (i=0; i < n; i++)
				*charpp++ = bsearch4char(fko, shp[i]);
		} else {
			for (p = str; len > 0 && !(*p & 0x80); p++, len--)
				/* void */ ;
			n = p-str;
			for (i=0; i < n; i++)
				*charpp++ = bsearch4char(fen, str[i]);
		}
		str = p;
		ret = 1;
	}
	*charpp++ = NULL;
	return ret;
}

int
convert_string2nd(char *str, int len)
{
	int     n, i, ret;
	char   *p, *lastp, backup;
	unsigned short *shp;
	struct character **charpp;

	charpp = &chars[0];
	ret = 0;
	while (len > 0) {
		if (*str & 0x80) {
			for (p = str; len > 0 && *p & 0x80; p += 2, len -= 2)
				/* void */ ;
			n = convert_johab_to_display(str, out_char2b, p - str);
			shp = (unsigned short *) out_char2b;
			for (i=0; i < n; i++)
				*charpp++ = bsearch4char(fko, shp[i]);
		} else {
			for (p = str; len > 0 && !(*p & 0x80); p++, len--)
				/* void */ ;
			lastp = p;
			backup = p[0];
			*lastp = 0;
			for (p = str; p < lastp;) {
				if (p[0] != '\\') {
					*charpp++ = bsearch4char(fen, p[0]);
					p++;
				} else if (p[1] == 0) {
					*charpp++ = bsearch4char(fen, '\\');
					p++;
				} else if (!isalnum(p[1])) {
					*charpp++ = bsearch4char(fen, p[1]);
					p += 2;
				} else {
					if (isdigit(p[1])) /* maybe hangul */
						p=get_hancode(fko,&p[1],charpp);
					else
						p=get_engcode(fen,&p[1],charpp);
					if (charpp[0]) /* found no code */
						charpp++;
				}
			}
			*lastp = backup;
		}
		str = p;
		ret = 1;
	}
	*charpp++ = NULL;
	return ret;
}
