/* monoify.c - convert text and attributes to BBS text string
 */

#include <stdio.h>
#include <string.h>
#include "mstring.h"
#include "vt100.h"


/* Put a BBS attribute sequence into "b" (max length "l") which changes
 * from attributes "*c" to "d". The contents of "*c" are changed to "d" on
 * success.
 *
 * Note that this function is little more than a modified copy of the
 * vt100_ansify_attr() function in the VT100 library.
 */
void ansi_monoify_attr(unsigned short *c, unsigned short d, char *b, int l)
{
	unsigned short attr_on, attr_off;	/* changing attributes */
	int fg, bg, dfg, dbg;		 /* foreground, background, desired fg&bg */
	unsigned short attr, dattr;	 /* attributes, desired attributes */
	static char buf[8];		 /* internal buffer */
	static char *c_fg = "KRGYBMCW";	 /* foreground colour codes */
	static char *c_bg = "krgybmcw";	 /* background colour codes */

	if ((!c) || (!b) || (l < 5))
		return;

	*b = 0;

	if (*c == d)
		return;			    /* nothing to change */

	attr = *c;
	fg = (attr & VT_FOREGROUND_MASK) >> VT_FOREGROUND_SHIFT;
	bg = (attr & VT_BACKGROUND_MASK) >> VT_BACKGROUND_SHIFT;
	attr ^= (attr & (VT_FOREGROUND_MASK | VT_BACKGROUND_MASK));

	dattr = d;
	dfg = (dattr & VT_FOREGROUND_MASK) >> VT_FOREGROUND_SHIFT;
	dbg = (dattr & VT_BACKGROUND_MASK) >> VT_BACKGROUND_SHIFT;
	dattr ^= (dattr & (VT_FOREGROUND_MASK | VT_BACKGROUND_MASK));

	if (dattr != attr) {		    /* need to change some attributes */
		if (dattr == 0) {	    /* turn all attributes off */
			if (mstrncat(b, "\035a", &l))
				return;
			(*c) ^= attr;
		} else {		    /* here comes the klarty bit */

			do {
				attr = *c;
				attr ^=
				    (attr &
				     (VT_FOREGROUND_MASK |
				      VT_BACKGROUND_MASK));

				attr_on = dattr - (dattr & attr);	/* turn these ON */
				attr_off = attr - (dattr & attr);	/* turn these OFF */

				if (attr_off &
				    (VT_ATTR_BOLD | VT_ATTR_FAINT)) {
					if (mstrncat(b, "\035b", &l))
						return;
					(*c) ^= attr & VT_ATTR_BOLD;
					(*c) ^= attr & VT_ATTR_FAINT;
					(*c) ^= attr & VT_ATTR_STANDOUT;
					(*c) ^= attr & VT_ATTR_REVERSE;
					continue;	/* restart loop as have changed multiple things */
				}

				if (attr_off & VT_ATTR_STANDOUT) {
					if (mstrncat(b, "\035s", &l))
						return;
					(*c) ^= attr & VT_ATTR_STANDOUT;
				}

				if (attr_off & VT_ATTR_UNDERLINE) {
					if (mstrncat(b, "\035u", &l))
						return;
					(*c) ^= attr & VT_ATTR_UNDERLINE;
				}

				if (attr_off & VT_ATTR_BLINK) {
					if (mstrncat(b, "\035f", &l))
						return;
					(*c) ^= attr & VT_ATTR_BLINK;
				}

				if (attr_off & VT_ATTR_REVERSE) {
					if (mstrncat(b, "\035r", &l))
						return;
					(*c) ^= attr & VT_ATTR_REVERSE;
				}

				if (attr_on & VT_ATTR_BOLD) {
					if (mstrncat(b, "\035B", &l))
						return;
					(*c) |= VT_ATTR_BOLD;
				}

				if (attr_on & VT_ATTR_FAINT) {
					if (mstrncat(b, "\035B", &l))
						return;
					(*c) |= VT_ATTR_FAINT;
				}

				if (attr_on & VT_ATTR_STANDOUT) {
					if (mstrncat(b, "\035S", &l))
						return;
					(*c) |= VT_ATTR_STANDOUT;
				}

				if (attr_on & VT_ATTR_UNDERLINE) {
					if (mstrncat(b, "\035U", &l))
						return;
					(*c) |= VT_ATTR_UNDERLINE;
				}

				if (attr_on & VT_ATTR_BLINK) {
					if (mstrncat(b, "\035F", &l))
						return;
					(*c) |= VT_ATTR_BLINK;
				}

				if (attr_on & VT_ATTR_REVERSE) {
					if (mstrncat(b, "\035R", &l))
						return;
					(*c) |= VT_ATTR_REVERSE;
				}
			} while (attr_on | attr_off);
		}
	}

	if (dfg != fg) {		    /* need to change foreground colour */
		sprintf(buf, "\035C%c", c_fg[dfg]);
		if (mstrncat(b, buf, &l))
			return;
		attr = *c;
		attr ^= (attr & VT_FOREGROUND_MASK);
		attr |= (dfg << VT_FOREGROUND_SHIFT);
		(*c) = attr;
	}

	if (dbg != bg) {		    /* need to change background colour */
		sprintf(buf, "\035C%c", c_bg[dbg]);
		if (mstrncat(b, buf, &l))
			return;
		attr = *c;
		attr ^= (attr & VT_BACKGROUND_MASK);
		attr |= (dbg << VT_BACKGROUND_SHIFT);
		(*c) = attr;
	}

}


/* Combine the text starting at "t" and the attributes starting at "a", which
 * are both "n" items long, into one string (stored in "s", max length "l")
 * of BBS-attributed colour text.
 *
 * Returns the number of items converted (bytes and shorts), NOT the length
 * of the resultant string. A negative return value indicates an error.
 *
 * The output string is always null terminated.
 *
 * Note that this function is little more than a modified copy of the
 * vt100_ansify() function in the VT100 library.
 */
int ansi_monoify(char *s, unsigned char *t, unsigned short *a, int l,
		 int n)
{
	unsigned short attr;
	char buf[64];
	int i;

	if ((!s) || (!t) || (!a))
		return (-1);
	if ((l < 1) || (n < 1))
		return (0);

	attr = VT_COLOUR_WHITE << VT_FOREGROUND_SHIFT;
	s[0] = 0;			    /* null-terminate output buffer before starting */

	for (i = 0; i < n; i++) {
		ansi_monoify_attr(&attr, a[i], buf, 64);
		if ((strlen(s) + strlen(buf) + 1) >= l)
			return (i);	    /* no room */
		strcat(s, buf);		    /* add escape sequences */
		buf[0] = t[i];
		buf[1] = 0;
		strcat(s, buf);		    /* add character from text */
	}

	return (n);
}

/* EOF */
