/*
 * $Id: amiga.trm,v 3.26 92/03/24 22:34:45 woo Exp Locker: woo $
 */

/* GNUPLOT - amiga.trm */
/*
 * Copyright (C) 1991, 1992
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted, 
 * provided that the above copyright notice appear in all copies and 
 * that both that copyright notice and this permission notice appear 
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the modified code.  Modifications are to be distributed 
 * as patches to released version.
 *  
 * This software  is provided "as is" without express or implied warranty.
 * 
 * This file is included by ../term.c.
 *
 * This terminal driver supports:
 *   Amiga Custom Screen
 *
 * AUTHORS
 *   Carsten Steger
 * 
 *   Pat R. Empleo      Slightly modified for Aztec C v5.2a (beta); sort of
 *   08/27/91           supports overscan; for large WB 2.0 virtual screens,
 *                      we limit the plot size so we don't have to scroll
 *                      around (not fun).
 *
 *   Carsten Steger     Modified to support Kickstart 2.0.
 *   09/11/91           Opens a text overscan screen when used with WB 2.0.
 *                      Discerns between NTSC and PAL Amigas when used with
 *                      WB 1.3 and lower.
 *
 *   Pat R. Empleo      Defined some 2.0 stuff in order to get Aztec C to
 *   09/20/91           work with Carsten's new code (see above).  When
 *                      KS/WB 2.0 support gets implemented in Aztec C, this
 *                      kludge will get deleted! 
 *                      (Aztec C release 5.2 beta)
 *
 * send your comments or suggestions to (info-gnuplot@ames.arc.nasa.gov).
 * 
 */

#ifdef AMIGA_AC_5
#include <intuition/intuitionbase.h>
#include <intuition/screens.h>
#include <graphics/text.h>
#include <graphics/gfxbase.h>
#else
/* You will have to use the Kickstart 2.0 header files for this to compile */
#include <exec/types.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/exec.h>
#include <proto/diskfont.h>
#endif

extern char *getenv(),*strchr();

#define AMIGA_XMAX 640
#define AMIGA_YMAX 512

#define AMIGA_VCHAR (12)
#define AMIGA_HCHAR (8)
#define AMIGA_VTIC (AMIGA_YMAX/80)
#define AMIGA_HTIC (AMIGA_XMAX/80)
/* The origin is in the upper left hand corner, so we have to translate */
/* and flip the coordinates: */
#define AMIGA_VTF(y) (AMIGA_ymax-1-(y))


struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *DiskfontBase;
static struct TextAttr AMIGA_Font = {
  "topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT
};
static struct TextFont *AMIGA_TextFont;
static struct NewScreen AMIGA_NewScreen = {
  0,0,AMIGA_XMAX,AMIGA_YMAX,4,15,0,HIRES|LACE,
  CUSTOMSCREEN|SCREENBEHIND|SCREENQUIET,NULL,NULL,NULL,NULL
};
static struct Screen *AMIGA_Screen;
static UWORD AMIGA_Colors [] = {
  0x000,0xfff,0xbbb,0x0f0,0xf00,0x00f,0x3ca,0xf0f,
  0x94d,0x0ff,0x82f,0xff0,0x0af,0xc5e,0xfa2,0xf44
};
static int AMIGA_slinetype;
static enum JUSTIFY AMIGA_justify = LEFT;
static unsigned int AMIGA_ymax,AMIGA_xmax; 
static WORD AMIGA_cwd,AMIGA_cht,AMIGA_bsl,AMIGA_vadj;
static struct TagItem AMIGA_ScrTagList[] = {
  {SA_Overscan,OSCAN_TEXT},{TAG_DONE,0}
};


AMIGA_reset()
{
  if (AMIGA_TextFont != NULL) CloseFont(AMIGA_TextFont);
  if (DiskfontBase != NULL) CloseLibrary(DiskfontBase);
  if (AMIGA_Screen != NULL) CloseScreen(AMIGA_Screen);
  if (IntuitionBase != NULL) CloseLibrary(IntuitionBase);
  if (GfxBase != NULL) CloseLibrary(GfxBase);
  AMIGA_TextFont = NULL;
  DiskfontBase = NULL;
  AMIGA_Screen = NULL;
  IntuitionBase = NULL;
  GfxBase = NULL;
}


AMIGA_init()
{
  static char fontname[80],*gnufont,*search;
  static int fsize;
  static char *test_str =
    " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
  static WORD test_len,test_pxl;


#ifdef AMIGA_LC_5_1
  /* Install exit trap in case of abnormal termination (see below). */
  int AMIGA_exit();
  if (!onexit(&AMIGA_exit)) {
    fprintf(stderr,"Couldn't set exit trap\n");
    exit(20);
  }
#endif
  GfxBase = OpenLibrary("graphics.library",0);
  if (GfxBase == NULL) {
    fprintf(stderr,"No Graphics-Library\n");
    AMIGA_reset();
    exit(20);
  }
  IntuitionBase = OpenLibrary("intuition.library",0);
  if (IntuitionBase == NULL) {
    fprintf(stderr,"No Intuition-Library\n");
    AMIGA_reset();
    exit(20);
  }
  if (IntuitionBase->LibNode.lib_Version <= 34) {
    /* We compute the vertical resolution for those poor NTSC-souls   :-)   */
    if (GfxBase->DisplayFlags & PAL) AMIGA_ymax = 512;
    else AMIGA_ymax = 400;
    AMIGA_xmax = 640;
    AMIGA_NewScreen.Width = AMIGA_xmax;
    AMIGA_NewScreen.Height = AMIGA_ymax;
    AMIGA_Screen = OpenScreen(&AMIGA_NewScreen);
    if (AMIGA_Screen == NULL) {
      fprintf(stderr,"No Screen\n");
      AMIGA_reset();
      exit(20);
    }
  } else {
    /* Kickstart 2.0 support */
    AMIGA_NewScreen.Width = STDSCREENWIDTH;
    AMIGA_NewScreen.Height = STDSCREENHEIGHT;
    AMIGA_Screen = OpenScreenTagList(&AMIGA_NewScreen,AMIGA_ScrTagList);
    if (AMIGA_Screen == NULL) {
      fprintf(stderr,"No Screen\n");
      AMIGA_reset();
      exit(20);
    }
    AMIGA_xmax = AMIGA_Screen->Width;
    AMIGA_ymax = AMIGA_Screen->Height;
  }
  term_tbl[term].xmax = AMIGA_xmax;
  term_tbl[term].ymax = AMIGA_ymax;
  gnufont = getenv("GNUFONT");
  if (gnufont != NULL ) {
    search = strchr(gnufont,'/');
    if (search != NULL) {
      *search++ = '\0';
      strncpy(fontname,gnufont,74);
      strcat(fontname,".font");
      sscanf(search,"%d",&fsize);
      /* Avoid opening "diskfont.library" if a built-in font is desired */
      if ((strcmp("topaz.font",fontname) == 0) &&
        ((fsize == TOPAZ_EIGHTY) || (fsize == TOPAZ_SIXTY))) {
        AMIGA_Font.ta_Name = fontname;
        AMIGA_Font.ta_YSize = fsize;
        AMIGA_Font.ta_Style = FS_NORMAL;
        AMIGA_Font.ta_Flags = FPF_ROMFONT;
        AMIGA_TextFont = OpenFont(&AMIGA_Font);
        if (AMIGA_TextFont != NULL) 
          SetFont(&AMIGA_Screen->RastPort,AMIGA_TextFont);
      } else {
        DiskfontBase = OpenLibrary("diskfont.library",0);
        if (DiskfontBase != NULL) {
          AMIGA_Font.ta_Name = fontname;
          AMIGA_Font.ta_YSize = fsize;
          AMIGA_Font.ta_Style = FS_NORMAL;
          AMIGA_Font.ta_Flags = FPF_ROMFONT|FPF_DISKFONT;
          AMIGA_TextFont = OpenDiskFont(&AMIGA_Font);
          if (AMIGA_TextFont != NULL)
            SetFont(&AMIGA_Screen->RastPort,AMIGA_TextFont);
        }
      }
    }
  }
  /* Width of characters: This works better for proportional fonts than */
  /* AMIGA_Screen->RastPort.TxWidth + AMIGA_Screen->RastPort.TxSpacing */
  test_len = strlen(test_str);
  test_pxl = TextLength(&AMIGA_Screen->RastPort,test_str,test_len);
  AMIGA_cwd = test_pxl / test_len;
  AMIGA_cht = AMIGA_Screen->RastPort.TxHeight; /* Height of characters */
  AMIGA_bsl = AMIGA_Screen->RastPort.TxBaseline; /* Reference line */
  /* Amount by which characters have to be shifted upwards to be */
  /* vertically justified: */
  AMIGA_vadj = AMIGA_bsl / 2;
  term_tbl[term].v_char = AMIGA_cht + 4; /* So lines won't be too close */
  term_tbl[term].h_char = AMIGA_cwd;
  LoadRGB4(&AMIGA_Screen->ViewPort,AMIGA_Colors,16);
  RemakeDisplay();
  AMIGA_slinetype = 1;
  SetAPen(&AMIGA_Screen->RastPort,AMIGA_slinetype);
  SetDrMd(&AMIGA_Screen->RastPort,JAM1);
}


AMIGA_text()
{
  char c;

  c = getc(stdin); /* This is extremely ugly... Yuk !!!!   >:-(   */
  ungetc(c,stdin); /* Maybe someone else will find a better solution */
  ScreenToBack(AMIGA_Screen);
}


AMIGA_graphics()
{
  SetRast(&AMIGA_Screen->RastPort,0);
  SetAPen(&AMIGA_Screen->RastPort,AMIGA_slinetype);
  ScreenToFront(AMIGA_Screen);
}


AMIGA_move(x,y)
unsigned int x,y;
{
  if ((x>=AMIGA_xmax) || (y>=AMIGA_ymax)) return;
  Move(&AMIGA_Screen->RastPort,x,AMIGA_VTF(y));
}


AMIGA_vector(x,y)
unsigned int x,y;
{
  if ((x>=AMIGA_xmax) || (y>=AMIGA_ymax)) return;
  Draw(&AMIGA_Screen->RastPort,x,AMIGA_VTF(y));
}


AMIGA_linetype(linetype)
int linetype;
{
  if (linetype >= 13) linetype %= 13;
  AMIGA_slinetype = linetype+3;
  SetAPen(&AMIGA_Screen->RastPort,AMIGA_slinetype);
}


AMIGA_put_text(x,y,str)
unsigned int x,y;
char *str;
{
  LONG len,tx_len;
  WORD xmin,xmax,ymin,ymax;

  len = strlen(str);
  tx_len = TextLength(&AMIGA_Screen->RastPort,str,len);
  switch (AMIGA_justify) {
    case LEFT:
      xmin = x;
      xmax = x + tx_len;
      break;
    case CENTRE:
      xmin = x - tx_len / 2;
      xmax = x + tx_len - tx_len / 2; /* aviod roundoff errors ! */
      break;
    case RIGHT:
      xmin = x - tx_len;
      xmax = x;
      break;
  }
  ymin = AMIGA_VTF(y) - AMIGA_vadj;
  ymax = ymin + AMIGA_cht;
  /* Check if character-string lies completely within the screen: */
  if ((xmax >= AMIGA_xmax) || (ymin < 0) || (ymax >= AMIGA_ymax)) return;
  Move(&AMIGA_Screen->RastPort,xmin,ymin+AMIGA_bsl);
  Text(&AMIGA_Screen->RastPort,str,len);
}


int AMIGA_justify_text(mode)
enum JUSTIFY mode;
{
  AMIGA_justify = mode;
  return TRUE;
}


/* This function is mainly included if the program terminates abnormally */
/* and the screen and libraries are still open. It closes down all opened */
/* libraries and screens. This happens e.g. when loading "bivariat.demo" */
/* and the stack is smaller than 70000 bytes. */
#ifdef AMIGA_LC_5_1
int AMIGA_exit(rc)
int rc;
{
  AMIGA_reset();
  return rc;
}
#endif
