/*
 * $Source: $
 * $Revision: $
 * $Date: $
 * $State: $
 * $Author: $
 *
 *
 * $Log: $
 * Version 3.1	4/10/92 wade
 * Added print_getinfo()
 *
 * Version 4.1 6/22/93 edward
 * print_getinfo() plots a color icon if possible
 * icon in print_getinfo is now perfectly square
 *
 * Version 4.1 6/24/93 edward
 * Added global pdescent which is the font descent
 * Added the global extern gMac.  It's used to see if System 7 is being used
 * Added variable fontSize to print_cmd.  If the window being printed is a list window, print_cmd
 *  gets sets the font size to the one the user chose in the menu view dialog
 * Added variable resource in print_list and print_getinfo.  It stores the resource ID of the icon
 *  to be plotted.
 * Changed the method to calculate the iconRect in print_list and print_getinfo so that the icons are square
 * If possible, print_list and print_getinfo plot a color icon
 * Changed the method to calculate the where to place items in print_list so that enough room
 *  is left for the icon, no matter what the font size
 * Changed the method to calculate page_y to undo the position done by print_header and redo the
 *  position based on the font size in print_header
 *
 * Version 4.1b2 7/12/93 edward
 * Added support for binhex in print_getinfo
 *
 * Version 4.1b3 10/1/93 edward
 * Included node.h
 * Changed *_ITEM to node type in node.h
 * Added support for unknown types in print_getinfo and print_list
 *
 * Revision 4.2WWW 3/7/94 - edward
 * Replaced all references to list, text, and gif with NT_MENU, NT_ASCII, and NT_GIF
 * Included node.h
 *
 * Revision 4.2a2 5/25/94 - edward
 * Changed print_getinfo to print "Path: <path>" for files (nodes that have ascii of binary bit
 *  set), "URL: <URL>" for URL nodes, and "<path>" for all others
 *
 * Revision 4.2a3 6/8/94 - edward
 * Included StandardFile
 *
 * Revision 4.2a3 6/9/94 - edward
 * Replaced SysEqu.h with LowMem.h
 * Included Icons.h
 *
 * Revision 4.2a3 6/13/94 - edward
 * Replaced the icon drawing code in print_getinfo and print_list with a call to plot_ti_icon
 *  in utilMgr.c.  No use repeating the same code.
 *
 * Revision 4.2a3 6/17/94 - edward
 * Included stdlib.h and strings.h
 *
 * Revision 4.2a3 6/29/94 - edward
 * Included ctype.h
 *
 * Revision 4.2a4 7/5/94 - edward
 * Porting to MW C/C++ 68K.  The headers are only included if we're not using MW
 */

/*  Copyright (c) 1991 by the Massachusetts Institute of Technology,
 *	For copying and distribution information, see the file
 *	"mit-copyright.h".
 *
 * 	printMgr.c 
 *		Printer commands.
 *
 *	print_page_dlog
 *	print_cmd
 *	print_text
 *	print_list
 *  print_getinfo
 *  print_header
 *  need_page
 *
 */

// 7/5/94 edward - If we're compiling with MW all of these headers are precompiled in TIFast*
#ifndef __MWERKS__

#include <Types.h>
#include <Quickdraw.h>
#include <Windows.h>
#include <Fonts.h>
#include <TextEdit.h>
#include <Menus.h>
#include <String.h>
#include <Memory.h>
#include <Packages.h>
#include <files.h>
#include <Lists.h>
#include <LowMem.h>
#include <stdio.h>
#include <Time.h>
#include <Resources.h>
#include <ToolUtils.h>
#include <StandardFile.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include "pips.h"
#ifdef TE32K
#include "TE32K.h"
#endif
#include "documentRec.h"
#include "prototype.h"
#include "node.h"

#endif

#include <Printing.h>
#include <Icons.h>
#include "mit-copyright.h"

#define bDevCItoh 1
#define ICN				1229147683

THPrint print_handle = NULL;

static TPPrPort pport;				/* Printer port */
static TPrStatus tstatus;			/* return value of PrPicFile */
static short num_lines = -1;		/* Number of lines so far */
static short pline_height;			/* Height of normal text */
static char p_from[40],p_date[40];	/* From & Date */
static char p_subject[60];			/* Subject */
static short page_num;				/* Page num */
static short page_y;				/* Y coord. on page */
static short pdescent;				/* edward 6/23/93 - font descent.  Needed for print_list */

extern WindowPtr	gListWindow;
extern WindowPtr	gTextWindow;
extern SysEnvRec	gMac;

#pragma segment Print

void print_page_dlog(void)
{
     if (print_handle == NULL) {
	  PrOpen();
	  print_handle = (THPrint) NewHandle(sizeof(TPrint));
	  PrintDefault(print_handle);
     }

     PrStlDialog (print_handle);
}

#pragma segment Print
void print_cmd(void)
{
	WindowPtr	window;
	FontInfo	finfo;
	Str255		fontSize;			/* edward 6/22/93 - font size */
	 
	window = FrontWindow();
	
	if (print_handle == NULL) {
		PrOpen();
		print_handle = (THPrint) NewHandle(sizeof(TPrint));
		PrintDefault(print_handle);
	}
	
	if (!PrJobDialog (print_handle)) {
		return;
	}
	if (PrError() != noErr)
		OpenAlertDialog(PRINT_ERROR,"Job Dialog");
		
	pport = PrOpenDoc(print_handle, nil, nil);
	if (PrError() != noErr)
		OpenAlertDialog(PRINT_ERROR,"PrOpenDoc");
		
	if (((((**print_handle).prStl.wDev) >> 8) & 0xFF) == bDevCItoh)
		TextFont(monaco);
	else
		TextFont(courier);
	
	/* edward 6/22/93 - if printing a list window use font size set in menu view */
	if (wind_type(window) == NT_MENU)
	{
		pref_get_string(FONT_SIZE_STR, fontSize);
		TextSize(atoi(fontSize));
	}
	else
		TextSize (12);
	GetFontInfo(&finfo);
	pline_height = finfo.ascent + finfo.descent + finfo.leading;
	pdescent = finfo.descent;			/* edward 6/23/93 */

	num_lines = -1;

	switch(wind_type(window)) {
		case NT_ASCII:	
	 		print_text(window);
			break;
		case NT_MENU:
	 		print_list(window); 
			break;
		case getinfo:
			print_getinfo(window);
			break;
		default:
			OpenAlertDialog(PRINT_ERROR,"Could not print the front most window.");
	}

	PrCloseDoc(pport);
	
	if ((**print_handle).prJob.bJDocLoop == bSpoolLoop && PrError() == noErr) {
		PrPicFile(print_handle,nil,nil,nil,&tstatus);
	}
	 
	if (PrError() != noErr)
	 	OpenAlertDialog(PRINT_ERROR,"PrPicFile");
}

#pragma segment Print
void print_text(WindowPtr window)
{
	Str255	title;
	Str255	menu;
	time_t	seconds;
	Handle	text_handle;
	int		text_length;
	char	*start;
	char	*end;
	short	x;
	char	buf[512];
	char	*dp;
	Rect	page_rect;
	short	c_width;
	short	num_spaces;
	char	*orig_dp;
	char	*orig_sp;
	char	*tp;
	short	i;
	short	ctr;
	
     /* Figure out page headers */
     p_date[0] = '\0';
     p_from[0] = '\0';
     p_subject[0] = '\0';
     page_num = 0;
		
	 GetWTitle(window, title );
	 p2cstr(title);
	 strncpy(p_subject, title, sizeof(p_subject));
	 p_subject[sizeof(p_subject)-1] = '\0';				/* make sure there is an ending null char */
	 
	 GetWTitle(gListWindow, menu );
	 p2cstr(menu);
	 /* get rid of the # items, ie. "(n items)" from the menu title */
	 for (tp = &menu[strlen(menu) - 1]; *tp != '('; tp-- )
	 	;
	 if (*tp == '(')
	 	*tp = '\0';
	 strncpy(p_from, menu, sizeof(p_from));
	 p_from[sizeof(p_from)-1] = '\0';
	 if (strlen(menu) >= sizeof(p_from)-1) {
	 	ctr = 3;
	 	for(tp=&p_from[sizeof(p_from)-2];ctr>0;ctr--,tp--)
			*tp = '.';
	 }
	 
	 time(&seconds);
	 strncpy(p_date, ctime(&seconds), sizeof(p_date));
	 p_date[sizeof(p_date)-1] = '\0';
	 tp = strstr(p_date,"\n");
	 if ( tp != NULL )
	 	*tp = '\0';
		
	 PrOpenPage(pport, nil);
	 if (PrError() != noErr)
	 	OpenAlertDialog(PRINT_ERROR,"PrOpenPage");
	 print_header();
	 
	 text_handle = text_get_handle(window);
	 text_length = text_get_length(window);
	 HLock(text_handle);
	 
	 page_rect = (**print_handle).prInfo.rPage;
	 c_width = CharWidth('m');
	 
	 start = *text_handle;
	 end = start + text_length;
	 while( start < end ) {
	 	if (need_page()) {
			if (num_lines != -1) {
				PrClosePage(pport);
				if (PrError() != noErr)
	 				OpenAlertDialog(PRINT_ERROR,"PrClosePage");
			}
			PrOpenPage(pport,nil);
			if (PrError() != noErr)
	 			OpenAlertDialog(PRINT_ERROR,"PrOpenPage");
			print_header();
		}
		
		dp = buf;
		x = page_rect.left + 5;
		while( start < end && *start != CR) {
		 	if (*start == '\t') {
		    	num_spaces = 8 - ((dp - buf) % 8);
		    	for (i = 0; i < num_spaces; i++)
			 		*dp++ = ' ';
		    		start++;
	       	}
			else
		    	*dp++ = *start++;
			
			if (x + (dp - buf) * c_width > page_rect.right) {
		    	orig_dp = dp-1;
		    	orig_sp = start-1;
		    	while(dp > buf && !(isspace(*(dp - 1)))) {
		         	dp--;
			 		start--;
		    	}
				
	            if (dp == buf) {
		          dp = orig_dp;
			 	  start = orig_sp;
		    	}
				
		    	while(dp > buf && isspace(*(dp - 1)))
			 		dp--;
					
		    	while(start < end && (*start == ' ' || *start == '\t'))
			 		start++;
		    	break;
	       }
			
		}
		
		if (start < end && *start == CR )
			start++;
		
		MoveTo(x, page_y);
		DrawText(buf,0,dp-buf);
		page_y += pline_height;
		num_lines++;
	 }
	 
	 HUnlock(text_handle);
	 PrClosePage(pport);
}

#define print_label(a1,a2) { \
	page_y += pline_height; \
	TextFace(bold); \
	MoveTo(x, page_y); \
	DrawText(a1,0,a2); \
	TextFace(normal); \
}

#define print_info(b1,b2) { \
	MoveTo(t, page_y); \
	DrawText(b1,0,b2); \
	page_y += pline_height; \
}
/*
 *	print_getinfo print the contents in the getinfo window.
 *  This routine assumes we are printing only one page and that
 *  each line does not exceed the page width.  We may want to fix
 *  this in a future version.
 */
#pragma segment Print
void print_getinfo(WindowPtr window)
{
	Str255		title;
	time_t		seconds;
	short		x;
	short		t;
	Rect		page_rect;
	char		*tp, *sp;
	NODE_INFO 	**select_node;
	Handle		tempH = NULL;
	Rect		iconRect;
	Str255		temp_string;
	short 		save_font,save_size;
	GrafPtr 	gp;
	Str255		link;								/* edward 5/25/94 - URL for URL nodes */
	unsigned char *type;
	
     /* Figure out page headers */
     p_date[0] = NULL;
     p_from[0] = NULL;
     p_subject[0] = NULL;
     page_num = 0;
		
	 GetWTitle(window, title );
	 p2cstr(title);
	 strncpy(p_subject, title, sizeof(p_subject));
	 p_subject[sizeof(p_subject)-1] = '\0';				/* make sure there is an ending null char */
	 	 
	 time(&seconds);
	 strncpy(p_date, ctime(&seconds), sizeof(p_date));
	 p_date[sizeof(p_date)-1] = '\0';
	 tp = strstr(p_date,"\n");
	 if ( tp != NULL )
	 	*tp = '\0';
		
	 PrOpenPage(pport, nil);
	 if (PrError() != noErr)
	 	OpenAlertDialog(PRINT_ERROR,"PrOpenPage");
	 print_header();
	 
	 GetPort(&gp);
     save_font = gp->txFont;
     save_size = gp->txSize;
     if (((((**print_handle).prStl.wDev) >> 8) & 0xFF) == bDevCItoh)
	 	TextFont(geneva);
     else
	 	TextFont(helvetica);
     TextSize(10);

	 page_rect = (**print_handle).prInfo.rPage;
	 x = page_rect.left + 30;						/* left margin for drawing label */
	 t = page_rect.left + 150;						/* left margin for drawing text */

	 select_node = (NODE_INFO **)GetWRefCon(window);
	  HLock((Handle)select_node);
	 
	 MoveTo(t, page_y);
	 DrawText((**select_node).title,0,strlen((**select_node).title));
				
	iconRect.top = page_y - pline_height + 3;
	iconRect.bottom = page_y + 3;	/* add 3 pixels, it looks better */
	iconRect.left = 30;				/* offset two pixels from border */
	iconRect.right = iconRect.left + (iconRect.bottom - iconRect.top);

	/* TechInfo 4.2a3 edward - Replaced icon drawing code with this call so that the */
	/* same chunk of code is used throughout TI.  Makes it easier to add new icons */
	plot_ti_icon(*((**select_node).type), &iconRect);
	
	/*  print_label takes two arguments, label name and label length */
	/*  print_info takes two arguments, text name, text length */
	page_y += pline_height;
	print_label("ID:", 3);
	print_info((**select_node).node_id, strlen((**select_node).node_id)); 
	
	print_label("Short Source:",13);
	print_info((**select_node).source, strlen((**select_node).source)); 
	
	type = (**select_node).type;

	if (type[0] != NT_TECHINFO && type[0] != NT_CSO_LIST)
	{
		print_label("Long Source:",12);
		print_info((**select_node).source_long, strlen((**select_node).source_long)); 
		
		print_label("Contact:",8);
		/* print each token on a seperate line */
		strcpy(temp_string,(**select_node).source_name);
		for(sp=temp_string,tp=temp_string; *sp != NULL; sp++) {
			if (*sp == CR || *sp == ',') {
				*sp = NULL;
				print_info(tp,strlen(tp));
				tp = sp + 1;
			}
		}
		/* print last token in list */
		print_info(tp,strlen(tp));
		
		print_label("Email:", 6);
		/* print each token on a seperate line */
		strcpy(temp_string,(**select_node).source_email);
		for(sp=temp_string,tp=temp_string; *sp != NULL; sp++) {
			if (*sp == CR || *sp == ',') {
				*sp = NULL;
				print_info(tp,strlen(tp));
				tp = sp + 1;
			}
		}
		/* print last token in list */
		print_info(tp,strlen(tp));
		
		print_label("Phone:",6);
		/* print each token on a seperate line */
		strcpy(temp_string,(**select_node).source_phone);
		for(sp=temp_string,tp=temp_string; *sp != NULL; sp++) {
			if (*sp == CR || *sp == ',') {
				*sp = NULL;
				print_info(tp,strlen(tp));
				tp = sp + 1;
			}
		}
		/* print last token in list */
		print_info(tp,strlen(tp));
	}
	
	if ( type[0] == NT_URL )
	{
		print_label("URL:", 4);
		semicolon2colon((**select_node).path, link);
		print_info(link, strlen(link));
	}
	else if (type[1] == ascii || type[1] == binary)
	{
		print_label("Path:", 5);
		print_info((**select_node).path, strlen((**select_node).path)); 
	}
	else if (type[0] != NT_TECHINFO && type[0] != NT_CSO_LIST)
	{
		print_label("", 0);			/* provide proper spacing */
		print_info((**select_node).path, strlen((**select_node).path)); 
	}
	else
	{
		print_label("", 0);			/* provide proper spacing */
		print_info("", 0); 
	}
	
	print_label("Keywords:",9);
	/* print each token on a seperate line */
	strcpy(temp_string,(**select_node).source_topic);
	for(sp=temp_string,tp=temp_string; *sp != NULL; sp++) {
		if (*sp == CR || *sp == ',') {
			*sp = NULL;
			print_info(tp,strlen(tp));
			tp = sp + 1;
		}
	}
	/* print last keyword in list */
	print_info(tp,strlen(tp));

	HUnlock((Handle)select_node);
	PrClosePage(pport);
	
	TextFont(save_font);
    TextSize(save_size);
    TextFace(normal);
}


#pragma segment Print
void print_list(WindowPtr window)
{
	Str255	title;
	Str255	menu;
	time_t	seconds;
	short	x;
	Rect	page_rect;
	short	list_begin;
	short	list_bottom;
	Str255	list_buffer;
	char	*tp;
	int		rc;
	Handle	tempH = NULL;
	Rect	iconRect;
	char	type[2];
	short	ctr;
	Str255	temp;
	short	indent_level;
	Str255	ident_string;

	/* Figure out page headers */
	p_date[0] = '\0';
	p_from[0] = '\0';
	p_subject[0] = '\0';
	page_num = 0;
	
	/* there is no subject - leave this null */

	GetWTitle(window, menu );
	p2cstr(menu);
	/* get rid of the # items, ie. "(n items)" from the menu title */
	for (tp = &menu[strlen(menu) - 1]; *tp != '('; tp-- )
		;
	if (*tp == '(')
		*tp = '\0';
	strncpy(p_from, menu, sizeof(p_from));
	p_from[sizeof(p_from)-1] = '\0';
	if (strlen(menu) >= sizeof(p_from)-1)
	{
		ctr = 3;
		for(tp=&p_from[sizeof(p_from)-2];ctr>0;ctr--,tp--)
			*tp = '.';
	}
	
	time(&seconds);
	strncpy(p_date, ctime(&seconds), sizeof(p_date));
	p_date[sizeof(p_date)-1] = '\0';
	tp = strstr(p_date,"\n");
	if ( tp != NULL )
		*tp = '\0';
		
	PrOpenPage(pport, nil);
	if (PrError() != noErr)
		OpenAlertDialog(PRINT_ERROR,"PrOpenPage");
	print_header();

	page_rect = (**print_handle).prInfo.rPage;

	/* edward 6/24/93 - pline_height-1 is width of icon, 5 is left margin of icon, 5 is right */
	x = page_rect.left + (pline_height - 1) + 5 + 5;	/* left margin for drawing text */

	/* edward 6/23/93 - The -15 is because 15 is added aribitrarily at the end of print_header.  */
	/* This seems to assume that the text is going to be 12 pt, so I'm subtracting the assumption */
	page_y = page_y - 15 + pline_height;
	
	list_bottom = list_end() - 1;		
	list_begin = 0;

	for(;list_begin <= list_bottom; list_begin++) {
		if (need_page()) {
			if (num_lines != -1) {
				PrClosePage(pport);
			}
			PrOpenPage(pport,nil);
			print_header();
			/* edward 6/23/93 - The -15 is because 15 is added aribitrarily at the end of print_header.  */
			/* This seems to assume that the text is going to be 12 pt, so I'm subtracting the assumption */
			page_y = page_y - 15 + pline_height;
		}
		
		list_get_buffer(list_buffer,list_begin); 
		rc = get_field(list_buffer,TITLE,title);

		if (rc) {
			/* create the proper ident levels */
			rc = get_field(list_buffer,LEVEL,ident_string);
			indent_level = atoi(ident_string);
			*temp = '\0';
			for(ctr=1;ctr < indent_level;ctr++)
				strcat(temp,"  ");
				
			if ( *temp != '\0' ) {
				if (strlen(temp) + strlen(title) < sizeof(title)) {
					strcat(temp,title);
					strcpy(title,temp);
				}
			}
		}
	
		if (rc) {
			MoveTo(x, page_y);
			DrawText(title,0,strlen(title));
			
			rc = get_field(list_buffer,TYPE,type);
			if ( rc ) {
	
				iconRect.top = page_y - (pline_height - 1) + pdescent;
				iconRect.bottom = iconRect.top + (pline_height - 1);
				iconRect.left = 5 + (indent_level - 1) * StringWidth("\p  ");
				iconRect.right = iconRect.left + (iconRect.bottom - iconRect.top);
				
				/* TechInfo 4.2a3 edward - Replaced icon drawing code with this call so that the */
				/* same chunk of code is used throughout TI.  Makes it easier to add new icons */
				plot_ti_icon(*type, &iconRect);
			}
			
			page_y += pline_height;
			num_lines++;
		}
			
	 }
	 
	 PrClosePage(pport);
}

#pragma segment Print
Boolean need_page(void)
{
     return (num_lines < 0 || page_y > (**print_handle).prInfo.rPage.bottom - 10);
}

#pragma segment Print
void print_header(void)
{
	char page_txt[10];
	short center,flen,dlen,save_font,page_left,save_size;
	GrafPtr gp;
	Str255	appName;

	page_num++;

	GetPort(&gp);
	save_font = gp->txFont;
	save_size = gp->txSize;
	if (((((**print_handle).prStl.wDev) >> 8) & 0xFF) == bDevCItoh)
		TextFont(geneva);
	else
		TextFont(helvetica);
	TextSize(10);
	TextFace(bold);
     
	sprintf(page_txt, "Page %d", page_num);

	page_left = (**print_handle).prInfo.rPage.right - TextWidth(page_txt, 0, strlen(page_txt)) - 3;
	center = ((**print_handle).prInfo.rPage.left + (**print_handle).prInfo.rPage.right) / 2;

	flen = TextWidth(p_from, 0, strlen(p_from));
	dlen = TextWidth(p_date, 0, strlen(p_date));

	page_y = 0;
	MoveTo(3, page_y);
	LineTo((**print_handle).prInfo.rPage.right - 3, page_y);
     
	page_y = 11;
	MoveTo(3, page_y);
	drawstring(p_from);
	 
	pref_get_string(APPLICATION_NAME,appName);
	MoveTo(center - (TextWidth(appName, 0, strlen(appName)) / 2), page_y);
	c2pstr(appName);
	DrawString(appName);

	MoveTo((**print_handle).prInfo.rPage.right - 3 - dlen, page_y);
	drawstring(p_date);

	page_y += 16;     
	MoveTo(3, page_y);
	drawstring(p_subject);

	MoveTo(page_left, page_y);
	drawstring(page_txt);

	TextFont(save_font);
	TextSize(save_size);
	TextFace(normal);

	page_y += 5;
	MoveTo(3, page_y);
	LineTo((**print_handle).prInfo.rPage.right - 3, page_y);
     
	page_y += 15;
	num_lines = 0;
}

