/* > C.PrintPsd */

/*****************************************************************************/
/***                                                                       ***/
/***                       PSD designer Versie 2                           ***/
/***                                                                       ***/
/***             (C) Copyright   : Concorde software 1989-1991             ***/
/***                                                                       ***/
/*****************************************************************************/

#ifndef __system_io
#define __system_io
#endif
#define FILEHANDLE int


#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <setjmp.h>
#include <signal.h>
#include <time.h>

#include "swis.h"
#include "Wimp.h"
#include "Wimpt.h"
#include "Werr.h"
#include "Win.h"
#include "Event.h"
#include "Msgs.h"
#include "Dbox.h"
#include "DboxQuery.h"
#include "Visdelay.h"
#include "os.h"
#include "bbc.h"
#include "sprite.h"
#include "drawfobj.h"
#include "font.h"
#include "colourtran.h"
#include "drawfdiag.h"

#include "Wimp-Funct.h"
#include "global.h"
#include "main.h"
#include "PsdWimp.h"
#include "PsdRedraw.h"
#include "Select.h"
#include "PsdDiv.h"
#include "PrintProj.h"
#include "DrawPsd.h"

#ifndef PRINT_FONT
#define PRINT_FONT         "Corpus.Medium"
#define PRINT_FONT_SIZE    12 * 16
#endif

/*************************** print_parameters ********************************
*                                                                            *
*  Description: Print de parameters van een psd onder elkaar (de komma zorgt *
*               voor de scheiding).                                          *
*                                                                            *
*  Parameters:  char *buffer1                Pointer naar de paramter buffer *
*               int *hoogte                  Pointer naar start hoogte       *
*                                                                            *
*  Returns:     void                                                         *
*                                                                            *
*  Other Info:  De parameters moeten door een komma gescheiden zijn.         *
*                                                                            * 
*****************************************************************************/

void print_parameters(char *buffer1,int *hoogte)
{
   char buffer2[256];

   if (strlen(buffer1) == 0)
      *hoogte = *hoogte - PRINT_LINE_SPACE;
   else
   {
      while (strlen(buffer1) > 0)
      {
         strcpy(buffer2,buffer1);
         buffer2[strcspn(buffer1,",")] = '\0';
         print_left(410,*hoogte,buffer2);
         *hoogte = *hoogte - PRINT_LINE_SPACE;
         if (strpbrk(buffer1,",") != NULL)
            strcpy(buffer2,(char *)(strpbrk(buffer1,",") + 1));
         else
            strcpy(buffer2,"");
         strcpy(buffer1,buffer2);
      }
   }
}

/***************************** draw_psd_title ********************************
*                                                                            *
*  Description: Tekend op het beeld de project title page                    *
*                                                                            *
*  Parameters:  void *pointer                Pointer naar psd                *
*               int *page                    Pointer naar pagina nummer      *
*                                                                            *
*  Returns:     BOOL                         Altijd TRUE                     *
*                                                                            *
*  Other Info:  Geen                                                         *
*                                                                            * 
*****************************************************************************/

BOOL draw_psd_title(void *pointer,int *page)
{
   struct psd *psd_pointer;
   char buffer1[256];
   char buffer2[256];
   char buffer3[256];
   int  hoogte;
   time_t datum1;
   time_t datum2;
   time_t datum3;

   psd_pointer = pointer;
   bbc_move(0,1790);
   bbc_draw(1280,1790);
   sprintf(buffer1,"%s %s",psd_pointer->psd_name,psd_page_to_string(
           &psd_pointer->psd_page_number));
   print_left(0,1820,buffer1);
   sprintf(buffer1,"Page : %d",*page);
   print_right(1279,1820,buffer1);

   hoogte = 1550;
   sprintf(buffer1,"PSD name             : %s",psd_pointer->psd_name);
   print_left(0,hoogte,buffer1);
   hoogte = hoogte - PRINT_LINE_SPACE;
   sprintf(buffer1,"PSD index            : %s",psd_page_to_string(
           &psd_pointer->psd_page_number));
   print_left(0,hoogte,buffer1);
   hoogte = hoogte - PRINT_LINE_SPACE;
   switch(psd_pointer->psd_type)
   {
      case TYPE_PROCEDURE :
         print_left(0,hoogte,"PSD type             : Procedure");
         break;
      case TYPE_FUNCTION  :
         print_left(0,hoogte,"PSD type             : Function");
         break;
   }
   hoogte = hoogte - PRINT_LINE_SPACE;
   print_left(0,hoogte,"Value parameters     :");
   strcpy(buffer1,psd_pointer->psd_value_par);
   print_parameters(buffer1,&hoogte);
   print_left(0,hoogte,"Reference parameters :");
   strcpy(buffer1,psd_pointer->psd_reference_par);
   print_parameters(buffer1,&hoogte);
   if (psd_pointer->psd_type == TYPE_FUNCTION)
   {
      print_left(0,hoogte,"Return variable      :");
      strcpy(buffer1,psd_pointer->psd_return_var);
      print_parameters(buffer1,&hoogte);
   }
/***************************************************************************
   hoogte = 1000;
   print_centre(0,1280,hoogte,"PSD description");
   hoogte = hoogte - 2 * PRINT_LINE_SPACE;
   print_left(100,hoogte,psd_pointer->psd_description1);
   hoogte = hoogte - PRINT_LINE_SPACE;
   print_left(100,hoogte,psd_pointer->psd_description2);
   hoogte = hoogte - PRINT_LINE_SPACE;
   print_left(100,hoogte,psd_pointer->psd_description3);
   hoogte = hoogte - PRINT_LINE_SPACE;
   print_left(100,hoogte,psd_pointer->psd_description4);
   hoogte = hoogte - PRINT_LINE_SPACE;
   print_left(100,hoogte,psd_pointer->psd_description5);
***************************************************************************/
   hoogte = 150;
   datum1 = (time_t)psd_pointer->psd_start_date;
   datum2 = (time_t)psd_pointer->psd_last_change;
   time(&datum3);
   if (default_date == PREFERENCE_UK) {
      strftime(buffer1,80,"Start date  : %A %d %B %Y",localtime(&datum1));
      strftime(buffer2,80,"Last change : %A %d %B %Y",localtime(&datum2));
      strftime(buffer3,80,"Printed at  : %A %d %B %Y",localtime(&datum3));
   }
   if (default_date == PREFERENCE_USA) {
      strftime(buffer1,80,"Start date  : %B %A %d %Y",localtime(&datum1));
      strftime(buffer2,80,"Last change : %B %A %d %Y",localtime(&datum2));
      strftime(buffer3,80,"Printed at  : %B %A %d %Y",localtime(&datum3));
   }
   print_left(0,hoogte,buffer1);
   hoogte = hoogte - PRINT_LINE_SPACE;
   print_left(0,hoogte,buffer2);
   hoogte = hoogte - PRINT_LINE_SPACE;
   print_left(0,hoogte,buffer3);
   return(TRUE);
}

/************************ print_psd_title_page *******************************
*                                                                            *
*  Description: Print van een psd de titel pagina. Op deze pagina staan de   *
*               gegevens van het psd (input par, output par enz.)            *
*                                                                            *
*  Parameters:  struct psd *psd_pointer      Te printen psd titel pagina     *
*               int *page                    Pagina nummer                   *
*                                                                            *
*  Returns:     BOOL                         TRUE / FALSE                    *
*                                                                            *
*  Other Info:  Er kunnen error meldingen gegeven worden als bv. printer     *
*               driver niet ingeladen is of als x vergroting te groot is.    *
*                                                                            * 
*****************************************************************************/

BOOL print_psd_title_page(struct psd *psd_pointer,int *page)
{
   BOOL flag;

   flag = print_page(draw_psd_title,psd_pointer,page);
   if (flag == TRUE)
      *page = *page + 1;
   return(flag);
}

/********************** bepaal_extra_verkleining *****************************
*                                                                            *
*  Description: Bepaal de extra verkleining als het psd met de opgegeven     *
*               verkleining niet op het papier pas. De vergrooting en        *
*               verkleining wordt zo aangepast zodat het psd wel pas.        *
*                                                                            *
*  Parameters:  struct psd *psd_pointer      Te printen psd                  *
*               int *vergroot                Opgegeven vergroting            *
*               int *verklein                Opgegeven verkleining           *
*                                                                            *
*  Returns:     BOOL                         TRUE -> was te groot            *
*                                                                            *
*  Other Info:                                                               *
*                                                                            * 
*****************************************************************************/

BOOL bepaal_extra_verkleining(struct psd *psd_pointer,int *vergroot,
                              int *verklein)
{
   BOOL flag = FALSE;

   if ((psd_pointer->psd_column[psd_pointer->psd_col_aantal] * *vergroot / 
       *verklein) > PRINT_RECHTER_KANTLIJN)
   {
      *vergroot = 200;
      *verklein = (psd_pointer->psd_column[psd_pointer->psd_col_aantal] * 
                   *vergroot) / PRINT_RECHTER_KANTLIJN;
      flag = TRUE;
   }
   return(flag);
}

/****************** bepaal_aantal_elementen_per_pagina ***********************
*                                                                            *
*  Description: Bepaal het aantal elementen dat met de opgegeven vergroting  *
*               op n pagina past.                                          *
*                                                                            *
*  Parameters:  int vergroot                 De opgegeven vergroting         *
*               int verklein                 De opgegeven verkleining        *
*                                                                            *
*  Returns:     int                          Het aantal psd-elementen        *
*                                                                            *
*  Other Info:                                                               *
*                                                                            * 
*****************************************************************************/

int bepaal_aantal_elementen_per_pagina(int vergroot,int verklein)
{
   int dummy;
   int page_top;
   int page_bottom;

   PrintPageSize(&dummy,&dummy,&dummy,&page_bottom,&dummy,&page_top);
   return((page_top - ConvertToPoint(PRINT_PSD_START_HOOGTE) - page_bottom) / 
          ConvertToPoint(ELEMENT_HOOGTE * vergroot / verklein) - 2);
}

/************************ bepaal_aantal_paginas ******************************
*                                                                            *
*  Description: Bepaal uit hoeveel pagina's een psd bestaat bij het printen  *
*               met een opgegeven vergroting en verkleining.                 *
*                                                                            *
*  Parameters:  struct psd *psd_pointer      Te bepalen psd                  *
*               int vergroot                 De opgegeven vergroting         *
*               int verklein                 De opgegeven verkleining        *
*               int psd_info                 Including psd info page         *
*                                                                            *
*  Returns:     int                          Het aantal pagina's             *
*                                                                            *
*  Other Info:  Deze routine wordt gebruikt bij het maken van een index. Het *
*               aantal pagina's is inclusief de titel pagina.                *
*                                                                            * 
*****************************************************************************/

int bepaal_aantal_paginas(struct psd *psd_pointer,int vergroot,int verklein,int psd_info)
{
   int  x0;
   int  y0;
   int  x1;
   int  y1;
   int  aantal_hoog;
   int  aantal_per_pagina;
   int  aantal_paginas;

   bepaal_extra_verkleining(psd_pointer,&vergroot,&verklein);

   select_all(psd_pointer);
   gen_psd(psd_pointer);
   get_select_bounding_box(psd_pointer,&x0,&y0,&x1,&y1);

   aantal_hoog = abs((y1 - y0) / ELEMENT_HOOGTE);
   aantal_per_pagina = bepaal_aantal_elementen_per_pagina(vergroot,verklein);
   aantal_paginas = aantal_hoog / aantal_per_pagina;

   if ((aantal_hoog % aantal_per_pagina) != NULL)
   {
      aantal_paginas += 1;      /* Tel titel pagina plus extra erbij op */
   }
   if (psd_info == TRUE)
   {
      aantal_paginas += 1;      /* Tel titel pagina erbij op            */
   }
   return(aantal_paginas);
}

/****************************** print_psd ************************************
*                                                                            *
*  Description: Print een psd via de printer driver. Is er geen printer      *
*               driver ingeladen, of size is te groot, dan komt er een error *
*                                                                            *
*  Parameters:  struct psd *psd_pointer      Te printen psd                  *
*               int x_vergroot               vergroting van x                *
*               int x_verklein               verkleining van x               *
*               int y_vergroot               vergroting van y                *
*               int y_verklein               verkleining van y               *
*               int center                   centreren als 1, 0 niet         *
*               int info                     print info als 1, 0 dan niet    *
*               int *page                    Pagina nummer                   *
*                                                                            *
*  Returns:     BOOL                         TRUE / FALSE                    *
*                                                                            *
*  Other Info:  Er kunnen error meldingen gegeven worden als bv. printer     *
*               driver niet ingeladen is of als x vergroting te groot is.    *
*                                                                            * 
*****************************************************************************/

BOOL print_psd(struct psd *psd_pointer,int vergroot,int verklein,int center,int info,int *page)
{
   os_error *err;
   draw_error draw_err;
   char buffer1[255];
   int  dimentions[5];
   int  bounds[5];
   int  recbuf[5];
   int  pos[2];
   int  more;
   int  x0;
   int  y0;
   int  x1;
   int  y1;
   int  page_xsize;
   int  page_ysize;
   int  page_left;
   int  page_right;
   int  page_bottom;
   int  page_top;
   int  aantal_per_pagina;
   int  aantal_rijen;
   int  teller;
   int  stap;
   int  id;
   font font_handle;
   wimp_paletteword voorgrond;
   wimp_paletteword achtergrond;
   int  max;
   double zoom;
   draw_box box;
   draw_redrawstr redraw;

   if (check_printer_driver() == FALSE)
   {
      return(FALSE);
   }
   else
   {
      if (info == TRUE)
      {
         if (print_psd_title_page(psd_pointer,page) == FALSE)
         {
            return(FALSE);
         }
      }
      dimentions[0] = 0x10000;
      dimentions[1] = 0;
      dimentions[2] = 0;
      dimentions[3] = 0x10000;
      voorgrond.word  = 0x00000000;
      achtergrond.word = 0xffffff00;
      max = 8;

      bepaal_extra_verkleining(psd_pointer,&vergroot,&verklein);

      /** Haal pagina afmeting op                                        **/

      err = PrintPageSize(&page_xsize,&page_ysize,&page_left,&page_bottom,&page_right,&page_top);

      deselect_all(psd_pointer);
      set_modified(psd_pointer,TRUE);
      gen_psd(psd_pointer);
      draw_rebind_diag((draw_diag *)&psd_pointer->diagram);                
      draw_queryBox((draw_diag *)&psd_pointer->diagram,&box,FALSE);
      draw_shift_diag((draw_diag *)&psd_pointer->diagram,0,-box.y0);
      draw_queryBox((draw_diag *)&psd_pointer->diagram,&box,TRUE);
      set_modified(psd_pointer,TRUE);
      x0 = (box.x0 - 4) * vergroot / verklein;
      y0 = (box.y0 - 4) * vergroot / verklein;
      x1 = (box.x1 + 4) * vergroot / verklein;
      y1 = (box.y1 + 4) * vergroot / verklein;

      if (abs(y1 - y0) < ELEMENT_HOOGTE)
      {
         visdelay_end();
         warning(msgs_lookup("psdwarn48:Empty psd"));
         return(FALSE);
      }

      aantal_rijen = y1 / (ELEMENT_HOOGTE * vergroot / verklein);
      aantal_per_pagina = bepaal_aantal_elementen_per_pagina(vergroot,verklein);
      zoom   = (double)vergroot / (double)verklein;
      teller = 0;
      stap   = aantal_per_pagina * ELEMENT_HOOGTE * vergroot / verklein;
      do {
         /** Geeft eerst de informatie (rectangle) die nodig is voor het psd zelf **/


         bounds[0] = x0 - 4;
         bounds[1] = y1 - stap * (teller + 1);
         bounds[2] = x1 + 4;
         bounds[3] = y1 - stap * teller + 4;
         if (bounds[1] < 0)
         {
            bounds[1] = 0;
         }
         pos[0] = (center == 1) ? page_left + ((page_right - page_left) / 2) - (ConvertToPoint(x1 - x0) / 2) : page_left;
         pos[1] = page_top - ConvertToPoint(bounds[3] - bounds[1]) - ConvertToPoint(PRINT_PSD_START_HOOGTE);
         if ((err = PrintGiveRectangle(PRINT_PSD_ID,bounds,dimentions,pos)) != NULL)
         {
            print_error(SIGINT);
            return(FALSE);
         }

         /** Geef nu de informatie die nodig is om na 'drawpage' een paginanummer neer **/
         /** te kunnen zetten. Onder het pagina nummer wordt een lijn getrokken        **/
         /** Het pagina nummer en de psd-naam wordt binnen de grens 0,1780,1280,1900   **/
         /** getekend. Het psd wordt daaronder gezet (y <= 1750)                       **/

         bounds[0]  = 0;
         bounds[1]  = 1780;
         bounds[2]  = 1280;
         bounds[3]  = 1900;
         pos[1]     = page_top - ConvertToPoint(bounds[3] - bounds[1]);
         pos[0]     = page_left + (page_right - page_left) / 2 - (ConvertToPoint(bounds[2] - bounds[0])) / 2;
         if ((err = PrintGiveRectangle(PRINT_PAGE_NUMBER_ID,bounds,dimentions,pos)) != NULL)
         {
            print_error(SIGINT);
            return(FALSE);
         }

         /** Alle informatie die nodig is, is gegeven. Begin nu met drawpage           **/

         if ((err = PrintDrawPage(1,1,recbuf,&id,&more)) != NULL)
         {
            print_error(SIGINT);
            return(FALSE);
         }
         while (more != 0 )
         {
            err = os_swi6(ColourTrans_SetGCOL,0xffffff00,0,0,0x80,0,0);
            err = os_swi6(ColourTrans_SetGCOL,0x00000000,0,0,0x00,0,0);

            bbc_clg();
            switch ( id )
            {
               case PRINT_PAGE_NUMBER_ID :
                  bbc_move(0,1790);
                  bbc_draw(1280,1790);
                  wimpt_noerr(font_find(PRINT_FONT,PRINT_FONT_SIZE,PRINT_FONT_SIZE,0,0,&font_handle));
                  wimpt_noerr(colourtran_setfontcolours(&font_handle,&achtergrond,&voorgrond,&max));
                  sprintf(buffer1,"%s %s",psd_pointer->psd_name,psd_page_to_string(&psd_pointer->psd_page_number));
                  print_left(0,1820,buffer1);
                  sprintf(buffer1,"Page : %d",*page);
                  print_right(1279,1820,buffer1);
                  wimpt_noerr(font_lose(font_handle));
                  break;
               case PRINT_PSD_ID :
                  redraw.reserved = 0;
                  redraw.box.x0 = x0 - 4;
                  redraw.box.y0 = y0 - 4;
                  redraw.box.x1 = x1 + 4;
                  redraw.box.y1 = y1 + 4;
                  redraw.scx    = x0;
                  redraw.scy    = y1;
                  redraw.g.x0   = redraw.box.x0;
                  redraw.g.y0   = redraw.box.y0;
                  redraw.g.x1   = redraw.box.x1;
                  redraw.g.y1   = redraw.box.y1;

                  draw_render_diag((draw_diag *)&psd_pointer->diagram,&redraw,zoom,&draw_err);

#ifdef DEMO
                  print_demo(bounds);
#endif
                  break;
            }
            if ((err = PrintGetRectangle(recbuf,&id,&more)) != NULL)
            {
               print_error(SIGINT);
               return(FALSE);
            }
         }
         teller = teller + 1;
         *page = *page + 1;
      } while (teller * aantal_per_pagina < aantal_rijen);

      if (psd_pointer->psd_window_handle != NULL)
      {
         set_modified(psd_pointer,TRUE);
         wimp_force_redraw_window_easy(psd_pointer->psd_window_handle);
      }
   }
   return( TRUE );
}
