#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include "substdio.h"
#include "subfd.h"
#include "getln.h"
#include "mess822.h"
#include "strerr.h"
#include "exit.h"
#include "leapsecs.h"
#include "caltime.h"
#include "tai.h"

#define FATAL "822print: fatal: "

void nomem()
{
  strerr_die2x(111,FATAL,"out of memory");
}

void putspaces(len)
int len;
{
  while (len-- > 0) substdio_put(subfdout," ",1);
}

void putformat(buf,len)
char *buf;
unsigned int len;
{
  while (len > 1) {
    switch(*buf++) {
      case '_':
        substdio_put(subfdout,"_\010",2);
	break;
      case '+':
        substdio_put(subfdout,buf,1);
        substdio_put(subfdout,"\010",1);
	break;
    }
    substdio_put(subfdout,buf++,1);
    len -= 2;
  }
}

void format(out,buf,len,pre,style1,style2)
stralloc *out;
char *buf;
int len;
char *pre;
char *style1;
char *style2;
{
  char ch;
  char ch2;

  if (!stralloc_copys(out,pre)) nomem();

  while (len--) {
    ch = *buf++;
    if (ch == '\n') ch = 0;
    if (ch == '\t') ch = ' ';
    if ((ch >= 32) && (ch <= 126)) {
      if (!stralloc_append(out,style1)) nomem();
      if (!stralloc_append(out,&ch)) nomem();
      continue;
    }

    if (!stralloc_cats(out,style2)) nomem();
    if (!stralloc_append(out,"\\")) nomem();
    ch2 = '0' + (ch >> 6);
    if (!stralloc_cats(out,style2)) nomem();
    if (!stralloc_append(out,&ch2)) nomem();
    ch2 = '0' + (7 & (ch >> 3));
    if (!stralloc_cats(out,style2)) nomem();
    if (!stralloc_append(out,&ch2)) nomem();
    ch2 = '0' + (7 & ch);
    if (!stralloc_cats(out,style2)) nomem();
    if (!stralloc_append(out,&ch2)) nomem();
  }
}

stralloc leftline = {0};
stralloc rightline = {0};
stralloc tmp = {0};

void doleft()
{
  int len;
  int pos;
  int i;

  len = leftline.len / 2;
  pos = 0;
  while (len > 73) {
    i = byte_rchr(leftline.s + pos,73 * 2,' ') / 2; /*XXX*/
    if (!i) i = 73;
    putformat(leftline.s + pos,i * 2);
    substdio_puts(subfdout,"\n");
    len -= i;
    pos += 2 * i;
  }
  putformat(leftline.s + pos,len * 2);
  substdio_puts(subfdout,"\n");
}

void doleftright()
{
  int leftxlen;
  int leftxpos;
  int rightxlen;
  int rightxpos;
  int i;
  int j;

  rightxlen = rightline.len / 2;
  leftxlen = leftline.len / 2;

  leftxpos = 0;
  rightxpos = 0;

  while (leftxlen + rightxlen > 76) {
    i = 50;
    if (i > leftxlen) i = leftxlen;
    j = 50;
    if (j > rightxlen) j = rightxlen;
    if (i + j > 76) j = 76 - i;

    putformat(leftline.s + leftxpos,i * 2);
    putspaces(78 - i - j);
    putformat(rightline.s + rightxpos,j * 2);
    substdio_put(subfdout,"\n",1);
    leftxlen -= i;
    leftxpos += 2 * i;
    rightxlen -= j;
    rightxpos += 2 * j;
  }

  putformat(leftline.s + leftxpos,leftxlen * 2);
  putspaces(78 - leftxlen - rightxlen);
  putformat(rightline.s + rightxpos,rightxlen * 2);
  substdio_put(subfdout,"\n",1);
}

void putvalue(a,pre)
stralloc *a;
char *pre;
{
  int j;

  j = a->len;
  if (j && (a->s[j - 1] == '\n')) --j;
  format(&rightline,a->s,j,"","_","=");
  format(&leftline,"",0,pre,"=","_");

  doleftright();
}

void putfields(a)
stralloc *a;
{
  int j;
  int i;

  for (j = i = 0;j < a->len;++j)
    if (a->s[j] == '\n') {
      format(&leftline,a->s + i,j - i,"","=","_");
      doleft();
      i = j + 1;
    }
}

void putaddr(a,pre,post,style)
stralloc *a;
char *pre;
char *post;
char *style;
{
  int i;
  int j;
  int comment;
  char *addr;

  comment = 0;
  for (j = i = 0;j < a->len;++j)
    if (!a->s[j]) {
      if (a->s[i] == '(') {
	if (comment) {
	  format(&leftline,a->s + comment,str_len(a->s + comment),pre,"_","=");
	  doleft();
	}
	comment = i + 1;
      }
      else if (a->s[i] == '+') {
	addr = a->s + i + 1;
	/* XXX: replace addr with nickname? */
	if (comment)
          format(&leftline,a->s + comment,str_len(a->s + comment),pre,"_","=");
	else
          format(&leftline,"",0,pre,"=","_");
	format(&rightline,addr,str_len(addr),post,style,"_");
	doleftright();
	comment = 0;
      }
      i = j + 1;
    }

  if (comment) {
    format(&leftline,a->s + comment,str_len(a->s + comment),pre,"_","=");
    doleft();
  }
}

void putdate(text,t)
stralloc *text;
mess822_time *t;
{
  struct tai sec;
  unsigned char secpack[TAI_PACK];
  time_t secunix;
  struct tm *tm;
  struct caltime local;
  int j;

  j = text->len;
  if (j && (text->s[j - 1] == '\n')) --j;
  format(&leftline,text->s,j,"=D=a=t=e=:","=","_");
  if (!t->known) {
    doleft();
    return;
  }

  caltime_tai(&t->ct,&sec);
  tai_pack(secpack,&sec);
  secunix = secpack[0] - 64;
  secunix = (secunix << 8) + secpack[1];
  secunix = (secunix << 8) + secpack[2];
  secunix = (secunix << 8) + secpack[3];
  secunix = (secunix << 8) + secpack[4];
  secunix = (secunix << 8) + secpack[5];
  secunix = (secunix << 8) + secpack[6];
  secunix = (secunix << 8) + secpack[7];
  secunix -= 10;

  tm = localtime(&secunix);
  local.offset = 0;
  local.date.year = tm->tm_year + 1900;
  local.date.month = tm->tm_mon + 1;
  local.date.day = tm->tm_mday;
  local.hour = tm->tm_hour;
  local.minute = tm->tm_min;
  local.second = tm->tm_sec;

  if (!stralloc_ready(&tmp,caltime_fmt((char *) 0,&local))) nomem();
  tmp.len = caltime_fmt(tmp.s,&local) - 6;

  format(&rightline,tmp.s,tmp.len,"","_","=");
  doleftright();
}

stralloc returnpath = {0};
stralloc envelope = {0};
stralloc threading = {0};
stralloc mid = {0};
stralloc refs = {0};

stralloc subject = {0};

stralloc dates = {0};
mess822_time date;

stralloc to = {0};
stralloc cc = {0};
stralloc bcc = {0};
stralloc nrudt = {0};

stralloc from = {0};
stralloc sender = {0};
stralloc replyto = {0};
stralloc mailreplyto = {0};
stralloc followupto = {0};

stralloc misc = {0};

mess822_header h = MESS822_HEADER;
mess822_action a[] = {
  { "date", 0, 0, &dates, 0, &date }
, { "subject", 0, 0, &subject, 0, 0 }
, { "to", 0, 0, 0, &to, 0 }
, { "cc", 0, 0, 0, &cc, 0 }
, { "bcc", 0, 0, 0, &bcc, 0 }
, { "apparently-to", 0, 0, 0, &bcc, 0 }
, { "notice-requested-upon-delivery-to", 0, 0, 0, &nrudt, 0 }
, { "from", 0, 0, 0, &from, 0 }
, { "sender", 0, 0, 0, &sender, 0 }
, { "reply-to", 0, 0, 0, &replyto, 0 }
, { "mail-reply-to", 0, 0, 0, &mailreplyto, 0 }
, { "mail-followup-to", 0, 0, 0, &followupto, 0 }
, { "message-id", 0, 0, 0, &mid, 0 }
, { "references", 0, 0, 0, &refs, 0 }
, { "in-reply-to", 0, &threading, 0, 0, 0 }
, { "return-path", 0, 0, 0, &returnpath, 0 }
, { "received", 0, &envelope, 0, 0, 0 }
, { "delivered-to", 0, &envelope, 0, 0, 0 }
, { "errors-to", 0, &envelope, 0, 0, 0 }
, { "resent-sender", 0, &envelope, 0, 0, 0 }
, { "resent-from", 0, &envelope, 0, 0, 0 }
, { "resent-reply-to", 0, &envelope, 0, 0, 0 }
, { "resent-to", 0, &envelope, 0, 0, 0 }
, { "resent-cc", 0, &envelope, 0, 0, 0 }
, { "resent-bcc", 0, &envelope, 0, 0, 0 }
, { "resent-date", 0, &envelope, 0, 0, 0 }
, { "resent-message-id", 0, &envelope, 0, 0, 0 }
, { 0, 0, &misc, 0, 0, 0 }
} ;

void finishheader()
{
  if (!mess822_end(&h)) nomem();

  putvalue(&subject,"=S=u=b=j=e=c=t=:");
  putaddr(&from,"=F=r=o=m=:= ","","+");

  putdate(&dates,&date);

  putaddr(&returnpath,"=R=e=t=u=r=n=-=P=a=t=h=:= ","=r=e=t=u=r=n= ","+");
  putfields(&envelope);
  putfields(&threading);
  putaddr(&refs,"=R=e=f=:= ","","_");
  putaddr(&mid,"=M=e=s=s=a=g=e=-=I=D=:= ","","_");

  substdio_puts(subfdout,"------------------------------------------------------------------------------\n");

  putaddr(&to,"=T=o=:= ","","+");
  putaddr(&cc,"=C=c=:= ","","+");
  putaddr(&bcc,"=B=c=c=:= ","","+");
  putaddr(&nrudt,"=N=o=t=i=c=e=-=R=e=q=u=e=s=t=e=d=-=U=p=o=n=-=D=e=l=i=v=e=r=y=-=T=o=:= ","","+");

  substdio_puts(subfdout,"------------------------------------------------------------------------------\n");

  putaddr(&sender,"=S=e=n=d=e=r=:= ","=s=e=n=d=e=r= ","+");
  putaddr(&replyto,"=R=e=p=l=y=-=T=o=:= ","=r=e=p=l=y= =t=o= ","+");
  putaddr(&mailreplyto,"=M=a=i=l=-=R=e=p=l=y=-=T=o=:= ","=r=e=p=l=y= =t=o= ","+");
  putaddr(&followupto,"=M=a=i=l=-=F=o=l=l=o=w=u=p=-=T=o=:= ","=f=o=l=l=o=w= =u=p= =t=o= ","+");

  putfields(&misc);
}

stralloc line = {0};
int match;

void main()
{
  int i;
  int flagheader = 1;

  if (leapsecs_init() == -1)
    strerr_die2sys(111,FATAL,"unable to init leapsecs: ");

  if (!mess822_begin(&h,a)) nomem();
  for (;;) {
    if (getln(subfdin,&line,&match,'\n') == -1)
      strerr_die2sys(111,FATAL,"unable to read input: ");
    if (flagheader)
      if (!mess822_ok(&line)) {
        finishheader();
	flagheader = 0;
      }
    if (!flagheader)
      substdio_put(subfdout,line.s,line.len);
    else
      if (!mess822_line(&h,&line)) nomem();
    if (!match) break;
  }
  if (flagheader)
    finishheader();

  substdio_flush(subfdout);
  _exit(0);
}


syntax highlighted by Code2HTML, v. 0.9.1