/*
 * (c) Copyright IBM Corp. 2005 All Rights Reserved
 *
 * Physical Memory Information Module
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/**
 * @file outpust.c
 *
 * @brief Basic PostScript file writing function.
 *
 * This part provides the source for the writing of the graphical
 * data in PostScript format.
 *
 * @author International Business Machines
 * @author Paul Movall <movall@us.ibm.com>
 *
 * @version Current Version: 1.0
 *
 * @date Current Date: 1/2005
 *
 * @version 0.1, 11/2003: File created by Paul Movall <movall@us.ibm.com>
 * @version 1.0, 01/2005: Miscellaneous cleanup for publish
 *
 */

#include <stdio.h>
#include "td.h"

#define MAX_COMMAND_LEN 16
#define RM 1.0
#define LM 1.0
#define TM 1.0
#define BM 1.0
#define SEGMENT_MASK 0xF0000000
#define STACK_SEGMENT 0x70000000

struct font_info_struct {
	int size;
	int font_size;
	int delta;
};
struct font_info_struct font_x[] = {
	{ size: 6, font_size: 18, delta: 3 },	/* 18 */
	{ size: 5, font_size: 14, delta: 3 },	/* 14 */
	{ size: 4, font_size: 12, delta: 2 },	/* 12 */
	{ size: 3, font_size: 10, delta: 2 },	/* 10 */
	{ size: 3, font_size: 8, delta: 2 },	/*  8 */
	{ size: 3, font_size: 6, delta: 2 },	/*  6 */
};
#define FONT_18PT_INDEX 0
#define FONT_14PT_INDEX 1
#define FONT_12PT_INDEX 2
#define FONT_10PT_INDEX 3
#define FONT_8PT_INDEX 4
#define FONT_6PT_INDEX 5
#define MAX_TASKS_18PT 32
#define MAX_TASKS_14PT 40
#define MAX_TASKS_12PT 48
#define MAX_TASKS_10PT 56
#define MAX_TASKS_8PT 66
#define MAX_TASKS_6PT 78


int WritePostScriptPreface(FILE *fp, int num_lines, int max_sz, int landscape) {
	int font_index;
	int i;
	int rc;

	/* round off and up to nearest 100 */
	max_sz = max_sz / 100;
	max_sz++;
	max_sz = max_sz * 100;

	/* figure out what font size to use */
	if (num_lines < MAX_TASKS_18PT) {
		font_index = FONT_18PT_INDEX;
		rc = MAX_TASKS_18PT;
	} else {
		if (num_lines < MAX_TASKS_14PT) {
			font_index = FONT_14PT_INDEX;
			rc = MAX_TASKS_14PT;
		} else {
			if (num_lines < MAX_TASKS_12PT) {
				font_index = FONT_12PT_INDEX;
				rc = MAX_TASKS_12PT;
			} else {
				if (num_lines < MAX_TASKS_10PT) {
					font_index = FONT_10PT_INDEX;
					rc = MAX_TASKS_10PT;
				} else {
					if (num_lines < MAX_TASKS_8PT) {
						font_index = FONT_8PT_INDEX;
						rc = MAX_TASKS_8PT;
					} else {
						/* go with smallest */
						font_index = FONT_8PT_INDEX;
						rc = MAX_TASKS_8PT;
					}
				}
			}
		}
	}

	/* file is open for writing so output formulas */
	fprintf(fp, "%%!PS-Adobe-2.0\n\n");

	fprintf(fp, "%% Global definitions\n");
	i = MAX_COMMAND_LEN * font_x[font_index].size;
	fprintf(fp, "/tsksize %d def\n", i);
	fprintf(fp, "/ends %d def\n", max_sz);

	fprintf(fp, "\n%% Font definitions\n");
	fprintf(fp, "/FH %d def\n", font_x[font_index].font_size);
	fprintf(fp, "/FHdelta %d def\n", font_x[font_index].delta);
	fprintf(fp, "/H {\t%% fontheight H -\n");
	fprintf(fp, "\t/Helvetica findfont\n");
	fprintf(fp, "\texch scalefont setfont\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n%% Page definitions\n");
	fprintf(fp, "/S {moveto show} bind def\n");
	fprintf (fp, "/pagesetup {\n");
	if (landscape)
		fprintf(fp, "\t90 rotate 0 0 72 8.5 mul sub translate\n");
	fprintf(fp, "\t%f 72 mul %f 72 mul translate\n", LM, BM);
	fprintf(fp, "\tFH H\n\t0 0 moveto\n");
	fprintf(fp, "} bind def\n");

	if (landscape) {
		fprintf(fp,
			"/pw 72 11 mul %f 72 mul %f 72 mul add sub def\n",
			LM, RM);
		fprintf(fp,
			"/ph 72 8.5 mul %f 72 mul %f 72 mul add sub def\n",
			TM, BM);
/*		pgw = (11 - (LM + RM)) * 72;
		pgh = (8.5 - (TM + BM)) * 72; */
	} else {
		fprintf(fp,
			"/pw 72 8.5 mul %f 72 mul %f 72 mul add sub def\n",
			LM, RM);
		fprintf(fp,
			"/ph 72 11 mul %f 72 mul %f 72 mul add sub def\n",
			TM, BM);
/*		pgw = (8.5 -(LM + RM)) * 72;
		pgh = (11 - (BM + TM)) * 72; */
	}
	fprintf(fp, "\n%% Width of graph area\n");
	fprintf(fp, "/graphwidth pw tsksize sub def\n");
	fprintf(fp, "/xscale graphwidth ends div def\n");

	fprintf(fp, "\n%% Misc procedures\n");
	fprintf(fp, "/SP {showpage pagesetup } bind def\n");
	fprintf(fp,
		"/shadedbox {\t%%x1 y1 x2 y2 red green blue linewidth shadedbox -\n");
	fprintf(fp, "\t/borderwidth exch def\n");
	fprintf(fp, "\t/blue exch def\n");
	fprintf(fp, "\t/green exch def\n");
	fprintf(fp, "\t/red exch def\n");
	fprintf(fp, "\t/upperY exch def\n\t/upperX exch def\n");
	fprintf(fp, "\t/lowerY exch def\n\t/lowerX exch def\n\n");
	fprintf(fp, "\tgsave\n");
	fprintf(fp, "\t\tlowerX lowerY moveto\n\t\tlowerX upperY lineto\n");
	fprintf(fp, "\t\tupperX upperY lineto\n\t\tupperX lowerY lineto closepath\n");
	fprintf(fp, "\t\tred green blue setrgbcolor\n\t\tfill\n");
	fprintf(fp, "\t\t0 0 0 setrgbcolor\n");
	fprintf(fp, "\t\tlowerX lowerY moveto\n\t\tlowerX upperY lineto\n");
	fprintf(fp, "\t\tupperX upperY lineto\n\t\tupperX lowerY lineto closepath\n");
	fprintf(fp, "\t\tborderwidth setlinewidth stroke\n\tgrestore\n");
	fprintf(fp, "} bind def  %%shadedbox\n");

	fprintf(fp, "\n/printlegend {\t%% printlegend -\n");
	fprintf(fp, "\t(Max Axis: %d pages) 0 ph 23 add S\n", max_sz);
	fprintf(fp, "\t0 ph 5 add 5 ph 15 add 0 0 0 0 shadedbox\n");
	fprintf(fp, "\t(Stack) 7 ph 5 add S\n");
	fprintf(fp, "\t70 ph 5 add 75 ph 15 add 255 255 0 0 shadedbox\n");
	fprintf(fp, "\t(Data) 77 ph 5 add S\n");
	fprintf(fp, "\t130 ph 5 add 135 ph 15 add 0 0 255 0 shadedbox\n");
	fprintf(fp, "\t(Text) 137 ph 5 add S\n");
	fprintf(fp, "\t190 ph 5 add 195 ph 15 add 255 0 255 0 shadedbox\n");
	fprintf(fp, "\t(Heap) 197 ph 5 add S\n");
	fprintf(fp, "\t250 ph 5 add 255 ph 15 add 0 255 255 0 shadedbox\n");
	fprintf(fp, "\t(Lib BSS) 257 ph 5 add S\n");
	fprintf(fp, "\t335 ph 5 add 340 ph 15 add 255 0 0 0 shadedbox\n");
	fprintf(fp, "\t(Lib Data) 342 ph 5 add S\n");
	fprintf(fp, "\t420 ph 5 add 425 ph 15 add 0 255 0 0 shadedbox\n");
	fprintf(fp, "\t(Lib Text) 427 ph 5 add S\n");
	fprintf(fp, "} bind def %% printlegend\n");

	fprintf(fp, "\n%% Procs specifically for areas of the graph\n");
	fprintf(fp, "/taskname {\t%% (command) xloc yloc height taskname -\n");
	fprintf(fp, "\t/height exch def\n");
	fprintf(fp, "\t/yloc exch def\n");
	fprintf(fp, "\t/xloc exch def\n");
	fprintf(fp, "\txloc tsksize add 1 sub yloc xloc tsksize add yloc height add 0 0 0 1 shadedbox\n");
	fprintf(fp, "\tFH H\n");
	fprintf(fp, "\t%% get the height of the bounding box for characters\n");
	fprintf(fp, "\tgsave\n");
	fprintf(fp, "\t\t0 0 moveto\n");
	fprintf(fp, "\t\t(M) false charpath flattenpath pathbbox\n");
	fprintf(fp, "\t\texch pop exch sub 2 div /ychar exch def pop\n");
	fprintf(fp, "\tgrestore\n");
	fprintf(fp, "\txloc yloc ychar add S\n");
	fprintf(fp, "\tdrawscale\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/drawpgs {\t%% start_num_pages end_num_pages offset red green blue drawpgs -\n");
	fprintf(fp, "\t/blue exch def\n");
	fprintf(fp, "\t/green exch def\n");
	fprintf(fp, "\t/red exch def\n");
	fprintf(fp, "\t/offset exch def\n");
	fprintf(fp, "\t/endpgs exch def\n");
	fprintf(fp, "\t/startpgs exch def\n");
	fprintf(fp, "\t/xloc tsksize def\n");
	fprintf(fp, "\t/yloc ypos FH FHdelta add 4 div add def\n");
	fprintf(fp, "\txloc yloc translate\n");
	fprintf(fp, "\txscale 1 scale\n");
	fprintf(fp, "\tstartpgs FH offset mul endpgs FH offset 0.4 add mul red green blue 0 shadedbox\n");
	fprintf(fp, "\t1 xscale div 1 scale\n");
	fprintf(fp, "\txloc neg yloc neg translate\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/drawscalebar {\t%% x drawscalebar -\n");
	fprintf(fp, "\t/xpos exch def\n\n");
	fprintf(fp, "\n\t/xloc tsksize def\n");
	fprintf(fp, "\t/yloc ypos def\n");
	fprintf(fp, "\txloc yloc translate\n");
	fprintf(fp, "\txscale 1 scale\n");
	fprintf(fp, "\txpos 0 xpos FH FHdelta add 0 0 0 0 shadedbox\n");
	fprintf(fp, "\t1 xscale div 1 scale\n");
	fprintf(fp, "\txloc neg yloc neg translate\n");
	fprintf(fp, "} bind def %% drawscalebar\n");

	fprintf(fp, "\n/drawscale {\t%%drawscale -\n");
	for (i = 0; i < max_sz; i += 100) {
		fprintf(fp, "\t%d drawscalebar\n", i);

		/* for large max, skip some */
		if (max_sz > 1000) {
			i += 100;
		}
		if (max_sz > 2000) {
			i += 200;
		}
	}
	fprintf(fp, "\t%d drawscalebar\n", max_sz);
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/stacksz {\t%% start_num_pages end_num_pages offset stacksz\n");
	fprintf(fp, "\t%%set fill to black\n");
	fprintf(fp, "\t0 0 0 drawpgs\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/datasz {\t%% start_num_pages end_num_pages offset datasz\n");
	fprintf(fp, "\t%%set fill to yellow\n");
	fprintf(fp, "\t255 255 0 drawpgs\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/textsz {\t%% start_num_pages end_num_pages offset textsz\n");
	fprintf(fp, "\t%%set fill to blue\n");
	fprintf(fp, "\t0 0 255 drawpgs\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/heapsz {\t%% start_num_pages end_num_pages offset heapsz\n");
	fprintf(fp, "\t%%set fill to magenta\n");
	fprintf(fp, "\t255 0 255 drawpgs\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/lbsssz {\t%% start_num_pages end_num_pages offset lbsssz\n");
	fprintf(fp, "\t%%set fill cyan\n");
	fprintf(fp, "\t0 255 255 drawpgs\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/ldatasz {\t%% start_num_pages end_num_pages offset ldatasz\n");
	fprintf(fp, "\t%%set fill red\n");
	fprintf(fp, "\t255 0 0 drawpgs\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/ltextsz {\t%% start_num_pages end_num_pages offset ltextsz\n");
	fprintf(fp, "\t%%set fill green\n");
	fprintf(fp, "\t0 255 0 drawpgs\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/taskpgs {\t%% stack data text heap lbss ldata ltext offset taskpgs -\n");
	fprintf(fp, "\t/offset exch def\n");
	fprintf(fp, "\t/ltextpgs exch def\n");
	fprintf(fp, "\t/ldatapgs exch def\n");
	fprintf(fp, "\t/lbsspgs exch def\n");
	fprintf(fp, "\t/heappgs exch def\n");
	fprintf(fp, "\t/textpgs exch def\n");
	fprintf(fp, "\t/datapgs exch def\n");
	fprintf(fp, "\t/stackpgs exch def\n\n");
	fprintf(fp, "\t0 stackpgs offset stacksz\n");
	fprintf(fp, "\t/enddata stackpgs datapgs add def\n");
	fprintf(fp, "\tstackpgs enddata offset datasz\n");
	fprintf(fp, "\t/endtext enddata textpgs add def\n");
	fprintf(fp, "\tenddata endtext offset textsz\n");
	fprintf(fp, "\t/endheap endtext heappgs add def\n");
	fprintf(fp, "\tendtext endheap offset heapsz\n");
	fprintf(fp, "\t/endlbss endheap lbsspgs add def\n");
	fprintf(fp, "\tendheap endlbss offset lbsssz\n");
	fprintf(fp, "\t/endldata endlbss ldatapgs add def\n");
	fprintf(fp, "\tendlbss endldata offset ldatasz\n");
	fprintf(fp, "\t/endltext endldata ltextpgs add def\n");
	fprintf(fp, "\tendldata endltext offset ltextsz\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n/libpgs {\t%% lbss ldata ltext offset libpgs -\n");
	fprintf(fp, "\t/offset exch def\n");
	fprintf(fp, "\t/ltextpgs exch def\n");
	fprintf(fp, "\t/ldatapgs exch def\n");
	fprintf(fp, "\t/lbsspgs exch def\n");
	fprintf(fp, "\t/endlbss 0 lbsspgs add def\n");
	fprintf(fp, "\t0 endlbss offset lbsssz\n");
	fprintf(fp, "\t/endldata endlbss ldatapgs add def\n");
	fprintf(fp, "\tendlbss endldata offset ldatasz\n");
	fprintf(fp, "\t/endltext endldata ltextpgs add def\n");
	fprintf(fp, "\tendldata endltext offset ltextsz\n");
	fprintf(fp, "} bind def\n");

	fprintf(fp, "\n%%\n");
	fprintf(fp, "%% Start of actual task data\n");
	fprintf(fp, "%%\n\n");

	return(rc);
}

void WritePostScriptStartPage(FILE *fp, int landscape) {
	fprintf(fp, "pagesetup\n");
	fprintf(fp, "printlegend\n");
	fprintf(fp, "/ypos ph FH sub def\n\n");
}

void WritePostScriptEndPage(FILE *fp, int landscape) {
	fprintf(fp, "1 setlinewidth stroke\n");
	fprintf(fp, "showpage\n");
}

void WritePostScriptEpilog(FILE *fp, int num_lines, int max_sz, int landscape) {
}

