/*  filo -- manipulate a `rolodex'-like database
 *  Copyright (C) 1994 David Deaven, Jennifer Corkill
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: directory.c,v 1.4 1996/04/17 16:28:27 deaven Exp $
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "dmd/memory.h"
#include "filo.h"

typedef struct {
	char *name;
	char *familyname;
	char *address;
	char *tel;
	char *fax;
	char *email;
	char *account;
} DirEntry;

static DirEntry **Directory = NULL;
static int ndir = 0;

static int dcmp(const void *a, const void *b)
{
	int r;
	DirEntry *da = *((DirEntry **) a), *db = *((DirEntry **) b);
	r = strcmp(da->familyname, db->familyname);
	if(r == 0) r = strcmp(da->name, db->name);
	return r;
}

void AddDirectory(char *record)
{
	char *s;
	DirEntry *d = mymalloc(sizeof(DirEntry));

	d->address = NULL;
	d->tel = scan_keyword(record, "tel");
	d->fax = scan_keyword(record, "fax");
	d->account = scan_keyword(record, "account");
	d->email = scan_keyword(record, "email");
	if(d->email == NULL)
	{
	  /* we can scan for an address contained in <> (angle brackets)
	   * if no explicit address has been given.
	   */
	  char *l, *r;
	  if((l = strchr(record, '<')) != NULL &&
	     (r = strchr(l, '>')) != NULL) 
	  {
	    for(s = l; s < r; ++s) if(!isprint(*s)) break;
	    if(s >= r)
	    {
	      *r = '\0';
	      d->email = mystrdup(l + 1);
	      *r = '>';
	    }
	  }
	}


	d->name = scan_address(record);
	for(s = d->name; *s != '\0' && *s != '\n'; ++s);
	if(*s != '\0')
	{
	  *s = '\0';
	  d->address = s + 1;
	}
	for(s = d->name + strlen(d->name) - 1; !isspace(*s) && *s != '\0'; --s);

	d->familyname = s + 1;
	*s = '\0';

	Directory = myrealloc(Directory, (ndir + 1) * sizeof(DirEntry *));
	Directory[ndir++] = d;
}

static void paddress(FILE *f, char *s, char *newline, int *row)
{
	int cr = 0;
	while(*s != '\0')
	{
	  if(*s == '\n')
	  {
	    cr = 1;
	  }
	  else
	  {
	    if(cr) { fprintf(f, "%s", newline); cr = 0; ++(*row); }
	    fputc(*s, f);
	  }
	  ++s;
	}
}

static void p_ascii(FILE *f, DirEntry *d)
{
	int row = 0;
	fprintf(f, "%s, %s\n\t", d->familyname, d->name);
	paddress(f, d->address, ", ", &row);
	fprintf(f, "\n");
	if(d->tel != NULL)
	  fprintf(f, "\ttel: %s\n", d->tel);
	if(d->email != NULL)
	  fprintf(f, "\temail: %s\n", d->email);
}

static void p_tex(FILE *f, DirEntry *d)
{
	int row = 0;
	fprintf(f, "{\\obeylines\n");
	fprintf(f, "{\\bf %s}, %s\n", d->familyname, d->name);
	fprintf(f, "{\\sl ");
	paddress(f, d->address, ", ", &row);
	fprintf(f, "}\n");
	if(d->tel != NULL)
	  fprintf(f, "tel: %s\n", d->tel);
	if(d->email != NULL)
	  fprintf(f, "email: {\\tt %s}\n", d->email);
	fprintf(f, "}\n\\smallskip\n");
}


static void PrintPSDirectory(FILE *f)
{
	int i, col, row, page = 0;
	int maxrow = 66, maxcol = 3;
	double margin, height, width, dx, dy;
	DirEntry *d;

	margin = (1.0 * 72.0);
	height = (11.0 * 72.0) - 2.0 * margin;
	width  = (8.5 * 72.0) - 2.0 * margin;
	dx = width / maxcol;
	dy = height / maxrow;

	col = maxcol; /* force new page */
	row = maxrow;

	for(i=0; i<ndir; ++i)
	{
	  if(row >= maxrow)
	  {
	    row = 0;
	    if(++col >= maxcol)
	    {
	      col = 0;
	      ++page;
	      if(i > 0) fprintf(f, "showpage end\n");
	      fprintf(f, "%%%%Page: %d %d\n", page, page);
	      fprintf(f, "filoDict begin\n");
	    }
	  }
	  fprintf(f, "%.2f %.2f moveto\n",
	    margin + col * dx, height + margin - row * dy);

	  d = Directory[i];
	  fps_string(f, d->name);
	  fputc(' ', f);
	  fps_string(f, d->familyname);
	  ++row;
	  fprintf(f, " DirectoryEntry\n");
	  fprintf(f, "(");
	  paddress(f, d->address, ") Address\n(", &row);
	  fprintf(f, ") Address\n"); ++row;
	  if(d->tel != NULL) {
	    fprintf(f, "(%s) Telephone\n", d->tel);
	    ++row;
	  }
	  if(d->email != NULL) {
	    fprintf(f, "(%s) Email\n", d->email);
	    ++row;
	  }
	}
	fprintf(f, "%%%%Pages: %d\nshowpage end\n%%%%EOF", page);
}

void PrintDirectory(FILE *f, enum directory_style style)
{
	int i;
	qsort(Directory, ndir, sizeof(DirEntry *), dcmp);

	if(style == POSTSCRIPT_STYLE) PrintPSDirectory(f);
	else
	{
	  for(i=0; i<ndir; ++i)
	  {
	    switch(style) {
	      case ASCII_STYLE:
		p_ascii(f, Directory[i]); break;
	      case TEX_STYLE:
		p_tex(f, Directory[i]); break;
	      default:
		fprintf(stderr, "internal error: bad style (%d)\n", style);
		exit(1);
	    }
	  }
	}


}
