/* PostScript output routines and print dialog */

#include "graph_primi.h"
#include "objects.h"
#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/List.h>
#include <Xm/PushB.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/RowColumn.h>
#include <Xm/TextF.h>
#include <Xm/DialogS.h>
#include <Xm/ToggleB.h>
#include "busy.h"

extern int media;     /* SCREEN or POSTSCRIPT, defined in graph_primi.c */
extern int mapWidth, mapHeight;
extern double mapWidthcm, mapHeightcm;
extern LOCATION map_origin;
extern long map_scale;
extern Widget toplevel;


FILE *ps;

int originalWidth, originalHeight;
long originalScale;
double originalWidthcm, originalHeightcm;
LOCATION originalorigin;
Widget shell, printfile;
static int orientation = 1;   /* default: landscape */
static char printfilename[128] = "map.ps";


#define FROM  0
#define VIA1  1
#define VIA2  2
#define VIA3  3
#define DEST  4

/* current route to be drawn */

extern OBJECT *currentroute[];
extern int drawroutenumpoints;
extern LOCATION drawroutepoints[100];



/* prototypes */

void psheader(int landscape);
void pstrailer();
void coord_drawgrid (int printlabels);


/* callback routines for buttons */

/* orientation */

void printorientCB (Widget w, XtPointer client_data, XmToggleButtonCallbackStruct *cbs)
{
  orientation = (int) client_data;
}


void printCB (Widget w, XtPointer client_data, XmPushButtonCallbackStruct *cbs)
{
  XmString temp;
  Widget   warning;
  Arg      args[10];
  char     *tempstr;
  int      printroute = ((int) client_data) == 2, i;
  LOCATION topleft, botright, a, b;
  double   heightNM, widthNM, scalehor, scalever; 
  int      x1, y1, x2, y2;


  XtUnmapWidget (shell);


  if (client_data)
    {
      /* read filename from dialog box */

      XtVaGetValues (printfile,
		     XmNvalue, &tempstr,
		     NULL);
      
      strcpy (printfilename, tempstr);
      
      media = POSTSCRIPT;
      
      if (ps = fopen (printfilename, "w"))
	{
	  originalWidth = mapWidth;
	  originalHeight = mapHeight;
	  originalWidthcm = mapWidthcm;
	  originalHeightcm = mapHeightcm;
	  originalScale = map_scale;
	  originalorigin = map_origin;
	  
	  /* if route is to be printed, find out best orientation and scale */
	  
	  if (printroute)
	    {
	      /* check if there is no detailed route set up yet */
	      
	      if (drawroutenumpoints == 0)
		{
		  if (currentroute[FROM])
		    drawroutepoints[drawroutenumpoints++] = currentroute[FROM]->location;
		  if (currentroute[VIA1])
		    drawroutepoints[drawroutenumpoints++] = currentroute[VIA1]->location;
		  if (currentroute[VIA2])
		    drawroutepoints[drawroutenumpoints++] = currentroute[VIA2]->location;
		  if (currentroute[VIA3])
		    drawroutepoints[drawroutenumpoints++] = currentroute[VIA3]->location;
		  if (currentroute[DEST])
		    drawroutepoints[drawroutenumpoints++] = currentroute[DEST]->location;
		}
	      
	      /* check if we have enough waypoints (min. 2 needed) */
	      
	      if (drawroutenumpoints >= 2)
		{
		  /* find extension of area to be printed */
		  
		  topleft  = drawroutepoints[0];
		  botright = drawroutepoints[0];
		  
		  for (i=1; i<drawroutenumpoints; i++)
		    {
		      if (drawroutepoints[i].longitude < topleft.longitude)
			topleft.longitude = drawroutepoints[i].longitude;
		      if (drawroutepoints[i].latitude < topleft.latitude)
			topleft.latitude = drawroutepoints[i].latitude;
		      if (drawroutepoints[i].longitude > botright.longitude)
			botright.longitude = drawroutepoints[i].longitude;
		      if (drawroutepoints[i].latitude > botright.latitude)
			botright.latitude = drawroutepoints[i].latitude;
		    }
		  
		  /* calc width and height of map in NM */
		  
		  a.longitude = b.longitude = topleft.longitude;
		  a.latitude = topleft.latitude;
		  b.latitude = botright.latitude;
		  heightNM = distance (a, b);
		  
		  b.longitude = botright.longitude;
		  b.latitude  = topleft.latitude;
		  widthNM = distance (a, b);
		  
		  /* suggest either landscape (1) or portrait (0) */
		  
		  orientation = (widthNM > heightNM) ? 1 : 0;
		  
		  
		  /* now we need to find a scale that makes everything fit: */
		  
		  if (orientation)     /* landscape */
		    {
		      scalehor = widthNM * 185200 / 24.7;
		      scalever = heightNM * 185200 / 17.6;
		    }
		  else
		    {
		      scalehor = widthNM * 185200 / 17.6;
		      scalever = heightNM * 185200 / 24.7;
		    }
		  
		  map_scale = (long) ((scalehor > scalever) ? scalehor : scalever);
		  map_scale = (long) (map_scale * 1.1);
		  
		  /* last but not least: choose map origin so that everything will fit */
		  
		  map_origin.longitude = (long) ((topleft.longitude + botright.longitude) / 2);
		  map_origin.latitude  = (long) ((topleft.latitude  + botright.latitude)  / 2);
		  
		  
		}
	    }
	  
	  /* from here, it dowsn't matter any more whether we are drawing a
	     simple map or one that contains a route */
	 	  
	  psheader(orientation);
	  
	  map_initcoord();
	  
	  fprintf (ps, "0.2 setlinewidth\n");
	  fprintf (ps, "[] 0 setdash\n");
	  coord_drawgrid (1);         /* draw coordinate grid */
	  
	  drawvisibleobjects (0);   /* objects other than CTRs... */
	  drawvisibleobjects (1);   /* and CTRs */

	  
	  /* draw route lines if required */
	  
	  if (printroute && (drawroutenumpoints >= 2))
	    {
	      gp_setlinestyle (1, SOLID);
	      gp_setcolor (BLACK);
	      
	      internal2window (drawroutepoints[0], &x1, &y1);
	      
	      for (i=1; i<drawroutenumpoints; i++)
		{
		  internal2window (drawroutepoints[i], &x2, &y2);
		  gp_drawline (x1, y1, x2, y2);
		  
		  x1 = x2;   y1 = y2;
		}
	    }
	  
	  pstrailer();
	  
	  map_initcoord();
	  
	  fclose (ps);
	}
      else
	{
	  temp = XmStringCreateSimple ("Could not print to specified file!");
	  
	  i = 0;
	  XtSetArg (args[i], XmNtitle,   "Warning!");     i++;
	  warning = (Widget) XmCreateInformationDialog (toplevel, "warning", args, i);
	  
	  XtVaSetValues (warning, 
			 XmNmessageString, temp,
			 NULL);
	  XtUnmanageChild ((Widget) XmMessageBoxGetChild (warning, XmDIALOG_HELP_BUTTON));
	  
	  XtManageChild (warning);
	  
	  XmStringFree (tempstr);
	}
      
      media = SCREEN;
      
    }

}



/* user interface */

void print_dialog()
{
  Widget form, rowcol, label, orientlabel, outputlabel, landscape, portrait,
         cancelbutton, printbutton, printroutebutton;
  XmString tempstr, landstr, portstr;

  shell = XtVaCreateManagedWidget ("printdialog", xmDialogShellWidgetClass, toplevel,
				   XmNtitle,             "ICAO Print Map",
				   XmNdeleteResponse,    XmDESTROY,
				   XmNallowShellResize,  True,
				   XmNmappedWhenManaged, False,
				   NULL);
 
  form = XtVaCreateManagedWidget ("printform", xmFormWidgetClass, shell, 
				  NULL);

  tempstr = XmStringCreateSimple ("Choose Print Options:");
  label = XtVaCreateManagedWidget ("printlabel", xmLabelWidgetClass, form,
				   XmNlabelString,      tempstr,
				   XmNtopAttachment,    XmATTACH_FORM,
				   XmNleftAttachment,   XmATTACH_FORM,
				   XmNrightAttachment,  XmATTACH_FORM,
				   NULL);
  XmStringFree (tempstr);

  tempstr = XmStringCreateSimple ("Orientation:");
  orientlabel = XtVaCreateManagedWidget ("orientlabel", xmLabelWidgetClass, form,
					 XmNlabelString,      tempstr,
					 XmNtopAttachment,    XmATTACH_WIDGET,
					 XmNtopWidget,        label,
					 XmNtopOffset,        10,
					 XmNleftAttachment,   XmATTACH_FORM,
					 XmNleftOffset,       10,
					 NULL);
  XmStringFree (tempstr);

  rowcol = XtVaCreateManagedWidget ("printorientation", xmRowColumnWidgetClass, form,
				    XmNradioBehavior,    True,
				    XmNorientation,      XmVERTICAL,
				    XmNnumColumns,       2,
				    XmNtopAttachment,    XmATTACH_WIDGET,
				    XmNtopWidget,        label,
				    XmNtopOffset,        4,
				    XmNleftAttachment,   XmATTACH_WIDGET,
				    XmNleftWidget,       orientlabel,
				    XmNleftOffset,       10,
				    NULL);


  landstr = XmStringCreateSimple ("Landscape");
  landscape = XtVaCreateManagedWidget ("scaleswitch", xmToggleButtonWidgetClass, 
				       rowcol,
				       XmNset,         (orientation ? True : False),
				       XmNlabelString, landstr,
				       NULL);
  XmStringFree (landstr);
  XtAddCallback (landscape, XmNvalueChangedCallback, (XtCallbackProc) printorientCB,
		 (XtPointer) 1);
 
  portstr = XmStringCreateSimple ("Portrait");
  portrait = XtVaCreateManagedWidget ("scaleswitch", xmToggleButtonWidgetClass, 
				      rowcol,
				      XmNset,         (!orientation ? True : False),
				      XmNlabelString, portstr,
				      NULL);
  
  XmStringFree (portstr);
  XtAddCallback (portrait, XmNvalueChangedCallback, (XtCallbackProc) printorientCB,
		 (XtPointer) 0);



  tempstr = XmStringCreateSimple ("Output to:");
  outputlabel = XtVaCreateManagedWidget ("outputlabel", xmLabelWidgetClass, form,
					 XmNlabelString,      tempstr,
					 XmNtopAttachment,    XmATTACH_WIDGET,
					 XmNtopWidget,        orientlabel,
					 XmNtopOffset,        11,
					 XmNleftAttachment,   XmATTACH_OPPOSITE_WIDGET,
					 XmNleftWidget,       orientlabel,
					 NULL);
  XmStringFree (tempstr);


  printfile = XtVaCreateManagedWidget ("printfile", xmTextFieldWidgetClass, form,
				       XmNtopAttachment,    XmATTACH_WIDGET,
				       XmNtopWidget,        orientlabel,
				       XmNtopOffset,        5,
				       XmNleftAttachment,   XmATTACH_OPPOSITE_WIDGET,
				       XmNleftWidget,       rowcol,
				       XmNleftOffset,       5,
				       XmNvalue,            printfilename,
				       NULL);

  /* push buttons */

  tempstr = XmStringCreateSimple ("Cancel");
  cancelbutton = XtVaCreateManagedWidget ("cancel", xmPushButtonWidgetClass, form,
					  XmNlabelString,      tempstr,
					  XmNtopAttachment,    XmATTACH_WIDGET,
					  XmNtopWidget,        printfile,
					  XmNtopOffset,        10,
					  XmNleftAttachment,   XmATTACH_FORM,
					  XmNleftOffset,       10,
					  NULL);
  XmStringFree (tempstr);
  XtAddCallback (cancelbutton, XmNactivateCallback, (XtCallbackProc) printCB, 
		 (XtPointer) 0L);


  tempstr = XmStringCreateSimple ("Print Map");
  printbutton = XtVaCreateManagedWidget ("cancel", xmPushButtonWidgetClass, form,
					  XmNlabelString,      tempstr,
					  XmNtopAttachment,    XmATTACH_WIDGET,
					  XmNtopWidget,        printfile,
					  XmNtopOffset,        10,
					  XmNleftAttachment,   XmATTACH_WIDGET,
					  XmNleftWidget,       cancelbutton,
					  XmNleftOffset,       10,
					  NULL);
  XmStringFree (tempstr);
  XtAddCallback (printbutton, XmNactivateCallback, (XtCallbackProc) printCB, 
		 (XtPointer) 1L);

  

  tempstr = XmStringCreateSimple ("Print Route");
  printroutebutton = XtVaCreateManagedWidget ("cancel", xmPushButtonWidgetClass, form,
					      XmNlabelString,      tempstr,
					      XmNtopAttachment,    XmATTACH_WIDGET,
					      XmNtopWidget,        printfile,
					      XmNtopOffset,        10,
					      XmNleftAttachment,   XmATTACH_WIDGET,
					      XmNleftWidget,       printbutton,
					      XmNleftOffset,       10,
					      XmNbottomAttachment, XmATTACH_FORM,
					      XmNbottomOffset,     10,
					      NULL);
  XmStringFree (tempstr);
  XtAddCallback (printroutebutton, XmNactivateCallback, (XtCallbackProc) printCB, 
		 (XtPointer) 2L);

  
  XtMapWidget (shell);

}




void psheader(int landscape)
{
  fprintf (ps, "%% ICAO map output\n\n");
  fprintf (ps, "40 40 translate\n");
  fprintf (ps, "0.5 0.5 scale\n");

  if (landscape)
    {
      mapWidth = 1400;
      mapHeight = 1000;
      mapWidthcm = 24.7;
      mapHeightcm = 17.6;

      fprintf (ps, "270 rotate\n");
      fprintf (ps, "-1400 1000 translate\n");
      fprintf (ps, "1 -1 scale\n");
    }
  else
    {
      mapWidth = 1000;
      mapHeight = 1400;
      mapWidthcm = 17.6;
      mapHeightcm = 24.7;

      fprintf (ps, "0 1400 translate\n");
      fprintf (ps, "1 -1 scale\n");
    }


  fprintf (ps, "newpath\n");
  fprintf (ps, "0 0 moveto\n");
  fprintf (ps, "0 %d lineto\n", mapHeight);
  fprintf (ps, "%d %d lineto\n", mapWidth, mapHeight);
  fprintf (ps, "%d 0 lineto\n", mapWidth);
  fprintf (ps, "0 0 lineto\n");
  fprintf (ps, "closepath\n");
  fprintf (ps, "stroke\n");

  fprintf (ps, "newpath\n");
  fprintf (ps, "0 0 moveto\n");
  fprintf (ps, "0 %d lineto\n", mapHeight);
  fprintf (ps, "%d %d lineto\n", mapWidth, mapHeight);
  fprintf (ps, "%d 0 lineto\n", mapWidth);
  fprintf (ps, "0 0 lineto\n");
  fprintf (ps, "closepath\n");
  fprintf (ps, "clip\n");
}


void pstrailer()
{
  mapWidth = originalWidth;
  mapHeight = originalHeight;
  mapWidthcm = originalWidthcm;
  mapHeightcm = originalHeightcm;
  map_scale = originalScale;
  map_origin = originalorigin;

  fprintf (ps, "showpage\n");
  fprintf (ps, "quit\n");
}





void button_print()
{
  media = POSTSCRIPT;

  if (ps = fopen ("map.ps", "w"))
    {
      originalWidth = mapWidth;
      originalHeight = mapHeight;
      originalWidthcm = mapWidthcm;
      originalHeightcm = mapHeightcm;
      originalScale = map_scale;

      map_initcoord();

      psheader(1);

      fprintf (ps, "0.2 setlinewidth\n");
      fprintf (ps, "[] 0 setdash\n");
      coord_drawgrid (0);         /* draw coordinate grid */

      drawvisibleobjects (0);   /* objects other than CTRs... */
      drawvisibleobjects (1);   /* and CTRs */

      pstrailer();
     
      map_initcoord();

      fclose (ps);
    }
  media = SCREEN;
}



