/*
** File: hey_format.c
** Desc: Reading & formatting functions for 'hey'
** Auth: Cian Synnott <pooka@redbrick.dcu.ie>
** Date: Sun Nov 15 19:56:51 GMT 1998
*/

#include <stdarg.h>
#include <string.h>
#include <stdio.h>

#include "hey_format.h"
#include "config.h"
#include "aux.h"

#ifdef HAVE_LIBREADLINE
/* <bobb> readline includes */
#include <readline/readline.h>
#include <readline/history.h>
#endif

#define LINESIZE 128		/* Should be plenty */

/* Buffer to keep things in */
dyn_page *hey_page = NULL;

/* Read user input into hey_page, also allocates it & suchlike */ 
void hey_user_input(void) {
	/* <bobb> return from readline is char *,  not good, but hey ! */
#ifdef HAVE_LIBREADLINE
	char *line;
#else
	char line[LINESIZE];
#endif
	char *ptr; 
	int  len;
	
	/* Allocate hey_page, passing hey_wrap as the word wrapping width */
	if (!(hey_page = dyn_pageAlloc(hey_wrap))) 
		printerr_exit ("Woah. Error allocating hey_page.\n");

	/* Read from standard input until end of file, store in hey_page, 
	** cleaning up any dodgy whitespace */
 	/*  <bobb> just use readline instead    */
#ifdef HAVE_LIBREADLINE
	while ((line=readline(NULL))){
#else
 	while (fgets(line, LINESIZE, stdin)) {
#endif
      		len = strlen(line);

		/* Remove newlines from strings that don't consist merely of
		** them ... */

		/* <bobb> Readline is _supposed_ to do this itself  */
#ifndef HAVE_LIBREADLINE
		if (len > 1)
			if (line[len - 1] == '\n') line[len -1] = 0;
#endif

		/* Clean up whitespace */
		for (ptr = line; *ptr; ptr++) 
			switch (*ptr) {
				case '\t':
				case '\f':
				case '\r':
				case '\n':
					*ptr = ' ';
			}
			
		/* Append line to page */
		dyn_pageAppend(hey_page, line);
	
	}
	
	/* And that's that ... */
	return;

}

/* Prototype for strprint(); see below ... */
char *strprint(char *, int, char *, ...);

/* Formats the lines present in hey_page into the 'hey' to be sent. */
void hey_format_input(void) {
	dyn_page *new_format;
	char line[LINESIZE];
	char *ptr;
	int offset, topwidth;
	int width = strlen(hey_title) + 2;

	/* Calculate the width of the hey .. It's either the strlen (hey_title) 
	** + 2 (spaces on either side), or the longest string in hey_page
	** Then add 4 for the space on either side of the message & 
	** the side border chars */
	if(!(ptr = dyn_pageRead(hey_page))) return;

	do {
		if (strlen(ptr) > width) width = strlen(ptr);
	} while ((ptr = dyn_pageRead(NULL)));
	
	width += 4;
	
	/* Set up the offset to print before each line (thus centering it ...) */
	offset = ((80 - width) / 2);

	/* Allocate the new page, with no wrapping width */
	if (!(new_format = dyn_pageAlloc(0))) 
		printerr_exit("Woah. Error allocating formatted page.\n");

	/* Print top line into it */
	if (!strlen(hey_title)) 
		strprint(line, LINESIZE, "%xc%c%xc%c", 
				' ', offset, B_TOPLFT, B_TOP, width - 2, B_TOPRHT);
	else {
		/* The total number of 'top' border chars we'll have to print is the
		** the width minus two chars for the corners, two chars for the spaces 
		** either side of the title, and the length of the title itself */
		topwidth = width - 4 - strlen(hey_title);
		strprint(line, LINESIZE, "%xc%c%xc %s %xc%c", 
				' ', offset, B_TOPLFT, 
				B_TOP, topwidth / 2, 
				hey_title,
				B_TOP, topwidth - (topwidth / 2), 
				B_TOPRHT);
	}

	dyn_pageAppend(new_format, line);
	
	/* Print all the other lines into it */
	if(!(ptr = dyn_pageRead(hey_page))) return;

	do {
		/* Format the line & append to new page */
		strprint(line, LINESIZE, 
				"%xc%c %s%xc%c", ' ', offset, B_LFT, ptr, 
				' ', width - 3 - strlen(ptr), B_RHT);
		dyn_pageAppend(new_format, line);

	} while ((ptr = dyn_pageRead(NULL)));

	strprint(line, LINESIZE, "%xc%c%xc%c", 
             ' ', offset, B_BOTLFT, B_BOT, width - 2, B_BOTRHT);
	dyn_pageAppend(new_format, line);

	/* Free the old hey_page, and point at the new formatted one */
	dyn_pageFree(hey_page);
	hey_page = new_format;

	return;
}

/* A little like a stripped-down version of snprintf. Accepts only string and
** character arguments, and only one modifier - x, meaning that the argument
** after the string or char will be the number of times to repeat it. */
char *strprint(char *str, int size, char *fmt, ...) {
	char *str_p, *fmt_p, *str_arg, char_arg;
	va_list args;
	int multiple;

	/* Clear the string and setup the va_* macros */
	memset(str, 0, size);
	va_start(args, fmt);

	str_p = str;
	fmt_p = fmt;

	/* Cycle through the format string */
	while (*fmt_p && (str_p - str) < size) {
		if (*fmt_p == '%') {	
			multiple = 1; 
			char_arg = 0; 
			str_arg  = 0;

			fmt_p++;
			switch (*fmt_p) {
				case 'c': 
					char_arg = va_arg(args, char);
					break;
				
				case 's': 
					str_arg = va_arg(args, char *); 
					break;
			
				case 'x': 
					fmt_p++; 
					if (*fmt_p == 'c') char_arg = va_arg(args, char); 
					if (*fmt_p == 's') str_arg  = va_arg(args, char *);
					multiple = va_arg(args, int);
					break;
				
				default:
					return NULL;
			}
			fmt_p++; 

			/* Concat the char or string arg onto the end of str 'multiple' 
			** times */
			while (multiple && (str_p - str) < size) {	
				if (str_arg) {
					strncat(str, str_arg, size - strlen(str));
					str_p += strlen(str_arg);
				} else if (char_arg) {
					*str_p = char_arg;
					str_p++;
				}
				multiple--;
			}
		} else {
			*str_p = *fmt_p;
			str_p++, fmt_p++;
		}

	}

	/* Set the last character to 0 if necessary */
	if ((str_p - str) >= size) str[size - 1] = 0;
					
	/* Finish & return */
	va_end(args);
	return str;
}
