/*
 *  hap -- a mail notification program
 * 
 *  copyright 1995 by Eric Fischer, etaoin@uchicago.edu
 * 
 *  copies of hap may be redistributed under the terms of the
 *  GNU public license, copies of which are available from
 *  the Free Software Foundation, 59 Temple Place, Boston, MA
 *  02111 USA.
 *
 */

/*************************************************************

   READ HEADERS FROM FILES; FORMAT THEM FOR NOTIFICATIONS

**************************************************************/

#include "hap.h"

/* initialize all the fields in a hlist at the start of
   a function.  Assumes that they don't point to anything
   yet, obviously, or we'd be leaking memory all over
   the place.
*/

void
inithlist (it)
	hlist *it;
{
	it->from = 0;
	it->to = 0;
	it->subject = 0;
	it->startpoint = 0;
	it->endpoint = 0;
	it->msgnumstr = 0;
	it->msgnumint = 0;
	it->postmark = 0;
}

/* much like inithlist, but this time they might actually
   point to something.  And of course, we must have already
   done inithlist() earlier or we might have uninitialized
   pointers pointing to things we definitely don't want
   to be free()ing
*/

void
clearheaders (headers)
	hlist *headers;
{
	if (headers->from) free (headers->from), headers->from = 0;
	if (headers->to) free (headers->to), headers->to = 0;
	if (headers->subject) free (headers->subject), headers->subject = 0;
	if (headers->msgnumstr) free(headers->msgnumstr),headers->msgnumstr=0;
	if (headers->postmark) free (headers->postmark),headers->postmark=0;
}

/* add num spaces to a malloc string.  quicker than calling
   addtostr over and over again.  probably belongs in string.c
*/

void
addnspaces (str, num)
	char **str;
	int num;
{
	char *temp;
	int i;

	if (num <= 0) return;

	temp = xmalloc ((num + 1) * sizeof (char));
	for (i = 0; i < num; i++) {
		temp[i] = ' ';
	}
	temp[num] = 0;

	addstr (str, temp);
	free (temp);
}

/* dumpheaders both adds a readable version of the headers to *str
   and frees the headers themselves.
*/

void
dumpheaders (str, headers)
	char **str;
	hlist *headers;
{
	/* if we don't have anything to say, don't bother saying
	   it.  This will happen when we just hit the first postmark
	   of a file and it's busily trying to output the previous
	   ones, which there aren't any of.
	*/

	if (headers->from == 0
	&&  headers->postmark == 0) return;

	{
		int maxwid = screenwid() - 1;

		char *msgnum = 0;
		char *from = 0;
		char *to = 0;
		char *subject = 0;

		/* if there's a string for a message number,
		   pad it to align with a 4-digit number
		*/

		if (headers->msgnumstr) {
			int l = strlen (headers->msgnumstr);

			while (l < 4) {
				addstr (&msgnum, " ");
				l++;
			}

			addstr (&msgnum, headers->msgnumstr);
		} else {
			addstr (&msgnum, itoa (headers->msgnumint));
		}

		addstr (&msgnum, " ");

		/* we already verified above that at least one of
		   headers->from and headers->postmark exists
		*/

		if (headers->from) {
			if (preferaddr) {
				addstr (&from, canonaddr (JUSTADDR,
							  headers->from));
			} else {
				addstr (&from, canonaddr (JUSTNAME, 
							  headers->from));
			}
		} else {
			addstr (&from, headers->postmark);
		}

		if (headers->subject) {
			addstr (&from, " -- ");
			addstr (&subject, headers->subject);
		} else {
			addstr (&subject, "");
		}

		addstr (&subject, "  ");
		addstr (&subject, 
		    ftoa ((headers->endpoint - headers->startpoint)/1024.0));
		addstr (&subject, "k");

		if (headers->to) {
			addstr (&to, "   to ");

			if (preferaddr) {
				addstr (&to, canonaddr (JUSTADDR, 
							headers->to));
			} else {
				addstr (&to, canonaddr (JUSTNAME, 
							headers->to));
			}
		} else {
			addstr (&to, "");
		}

		if (terse || (
		    strlen (msgnum) + strlen (from) + strlen (subject) +
		    strlen (to) <= maxwid)) {
			/* hooray! it all fits! 
			   (or we're terse and we don't care) 
			*/

			int pad = strlen (msgnum) + strlen (from) +
			          strlen (subject) + strlen (to);

			addstr (str, msgnum);
			addstr (str, from);
			addstr (str, subject);

			if (pad < maxwid) {
				if (*to) addnspaces (str, maxwid - pad);
			}

			addstr (str, to);
			addstr (str, "\n");
		} else if (strlen (msgnum) + strlen (from) + 
		           strlen (to) <= maxwid) {

			/* ok -- can we get the sender and the
			   recipients on a line?
			*/

			int pad = strlen (msgnum) + strlen (from) +
			          strlen (to);

			addstr (str, msgnum);
			addstr (str, from);

			if (pad < maxwid) {
				if (*to) addnspaces (str, maxwid - pad);
			}

			addstr (str, to);
			addstr (str, "\n     ");
			addstr (str, truncstr (subject, maxwid - 5));
			addstr (str, "\n");
		} else if (strlen (msgnum) + strlen (from) + strlen (subject)
		           <= maxwid) {

			/* how about the sender and the subject? */

			addstr (str, msgnum);
			addstr (str, from);
			addstr (str, subject);

			if (*to) {
				char *chopto = truncstr (to, maxwid - 6);

				addstr (str, "\n");
				if (maxwid - strlen (chopto) > 0) 
				    addnspaces (str, maxwid - strlen (chopto));

				addstr (str, chopto);
			}

			addstr (str, "\n");
		} else {
			/* ok, we give up... */

			addstr (str, msgnum);
			addstr (str, truncstr(from, maxwid - strlen (msgnum)));

			addstr (str, "\n     ");
			addstr (str, truncstr (subject, maxwid - 5));
			
			if (*to) {
				char *chopto = truncstr (to, maxwid - 6);

				addstr (str, "\n");
				if (maxwid - strlen (chopto) > 0) 
				    addnspaces (str, maxwid - strlen (chopto));

				addstr (str, chopto);
			}

			addstr (str, "\n");
		}

		free (msgnum);
		free (from);
		free (to);
		free (subject);

		clearheaders (headers);
	}
}

/* slurp in headers from a file.  handles continuation lines properly,
   and to and cc are lumped together
*/

void
readheaders (list, f)
	hlist *list;
	FILE *f;
{
	char *s;
	char **which = 0;

	while ((s = fgetl (f))) {
		if (*s == '\n') break;
		stripcr (s);

		if (!isspace (*s)) which = 0;
		if (cstarts (s, "from:")) which = &(list->from);
		if (cstarts (s, "subject:")) which = &(list->subject);

		/* to and cc are both lumped together as
		   just generic recipients
		*/

		if (cstarts (s, "to:")
		||  cstarts (s, "cc:")) {
			which = &(list->to);

			if (list->to) {
				addstr (which, ", ");
			}
		}

		if (isspace (*s)) {
			while (isspace (*s)) s++;
		} else {
			while ((*s != ':') && (*s)) s++;
			while (*s == ':') s++;
			while (isspace (*s)) s++;
		}

		if (which) {
			if (*which) {
				addstr (which, " ");
			}
			addstr (which, s);
		}
	}
}

/* wow, an exciting one.  if quote exists, add it to msg and
   throw the original away.
*/

void
dumpquote (msg, quote)
	char **msg;
	char **quote;
{
	if (*quote) {
		addstr (msg, *quote);

		free (*quote);
		*quote = 0;
	}
}
