/*
 * $Id: atarivdi.trm,v 1.1 1995/06/14 12:22:17 drd Exp $
 *
 */

/* GNUPLOT - atari.trm */
/*
 * Copyright (C) 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:
 *   Atari Screens working with the normal VDI
 *     (this should include TT and big screens)
 *
 * AUTHORS
 *  Alexander Lehmann
 *  HE Koechling
 *
 * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
 *
 * ATARI-related comments please to alexlehm@iti.informatik.th-darmstadt.de
 *
 */

#ifndef GOT_DRIVER_H
#include "driver.h"
#endif

#ifdef TERM_REGISTER
register_term(vdi)
#endif           

#ifdef TERM_PROTO

/* function-prototypes */
TERM_PUBLIC void VDI_options(void);
TERM_PUBLIC void VDI_init(void);
TERM_PUBLIC void VDI_reset(void);
TERM_PUBLIC void VDI_graphics(void);
TERM_PUBLIC void VDI_text(void);
TERM_PUBLIC void VDI_move(unsigned int x, unsigned int y);
TERM_PUBLIC void VDI_vector(unsigned int x, unsigned int y);
TERM_PUBLIC void VDI_linetype(int lt);
TERM_PUBLIC int VDI_text_angle(int ta);
TERM_PUBLIC void VDI_put_text(unsigned int x, unsigned int y, char *str);
TERM_PUBLIC int VDI_justify_text(enum JUSTIFY mode);
TERM_PUBLIC void VDI_point(unsigned int x, unsigned int y, int number);

/* default to hi-res */
#define VDI_XMAX 640
#define VDI_YMAX 400
#define VDI_VCHAR 16
#define VDI_HCHAR 8
#define VDI_HTIC (VDI_XMAX/100)
#define VDI_VTIC VDI_HTIC

#define GOT_VDI_PROTO
#endif /* TERM_PROTO */

#ifndef TERM_PROTO_ONLY
#ifdef TERM_BODY

#ifdef __PUREC__
/* why did they have to change these names ??? */
#include <aes.h>
#include <vdi.h>
#include <tos.h>
#else /* !__PUREC__ i.e. __GNUC__, maybe others */
#include <aesbind.h>
#include <vdibind.h>
#include <osbind.h>
#endif

#define VDI_yc(y) (VDI_maxycoord-(y))
#define VDI_LINETYPES_MAX	11
static int VDI_linetypes[VDI_LINETYPES_MAX] = {
        0xffff, 0x1111,
        0xffff, 0x5555, 0x3333, 0x7777,
        0x3f3f, 0x0f0f, 0x5f5f, 0xe4e4, 0x55f5};
static int VDI_lt;
static int vdi_vdi_handle=-1;
static int VDI_maxycoord;
static int VDI_rotation;
static int VDI_numcolors;
static int pxy[128];            /* Maximum of 64 pixels per v_pline */
static int pxy_index;
static int VDI_colors[16];
static int VDI_savecolors[16][3];
static int VDI_numpalette;
#define VDI_c_height_default 6 /* well, well ...               */
static int VDI_c_height = VDI_c_height_default;

static void vdi_flush_line(void);

TERM_PUBLIC void VDI_options( )
{
#define VDIHEXERROR "palette values 3 hex digits, please"
#define VDIHEIGHTERROR "expecting a character height"
    char opt[4];
    int i;
    char *tok_end;

    term_options[0]='\0';
    VDI_c_height=VDI_c_height_default;

    for( i=0 ; i<17 ; i++ ) {
        if(END_OF_COMMAND) break;
        if (token[c_token].length>3) {
            VDI_numpalette=0;
            VDI_c_height=VDI_c_height_default;
            term_options[0]='\0';
            int_error(VDIHEXERROR, c_token);
        }

        capture( opt, c_token, c_token, 6 );
        if (!i) {
            VDI_c_height = strtoul( opt, &tok_end, 10 );
            if( *tok_end!='\0' ) {
                VDI_numpalette=0;
                VDI_c_height=VDI_c_height_default;
                term_options[0]='\0';
                int_error(VDIHEIGHTERROR, c_token);
            }
            if( VDI_c_height>999 )
                VDI_c_height=999;  /* avoid opt length overflow */
            sprintf( opt, "%d ", VDI_c_height );
        }
        else {
            VDI_colors[i-1]=strtoul( opt, &tok_end, 16 );
            if( *tok_end!='\0' ) {
                VDI_numpalette=0;
                VDI_c_height=VDI_c_height_default;
                term_options[0]='\0';
                int_error(VDIHEXERROR, c_token);
            }

            sprintf( opt, "%03X ", VDI_colors[i-1] );
        }
        strcat( term_options, opt );
        c_token++;
    }
    VDI_numpalette=(i==0 ? 0 : i-1);
}

TERM_PUBLIC void VDI_init( )
{
    int work_in[11];
    int work_out[57];
    int i;
    int hchar, wchar, dummy;
    int rgb[3];
    int num_save;
    char *colors,*tok_end;

    if( VDI_numpalette==0 && (colors=getenv("GNUCOLORS")) && *colors ) {
        for( i=0 ; i<17 ; i++ ) {
            if (!i) {
                VDI_c_height = strtoul( colors, &tok_end, 10 );
                 if( colors==tok_end ) {
                    i=0;
                    VDI_c_height=VDI_c_height_default;
                    break;
                }
           }
            else {
                if( *colors=='\0' ) break;
                VDI_colors[i]=strtoul( colors, &tok_end, 16 );
                if( colors==tok_end || (unsigned)VDI_colors[i]>0xfff ) {
                    i=0;
                    break;
                }
            }
            colors=tok_end;

            while( *colors==' ' ) colors++;
        }
        VDI_numpalette=(i==0 ? 0 : i-1);
    }

    vdi_vdi_handle=graf_handle( &wchar, &hchar, &dummy, &dummy );
    if( !vdi_vdi_handle )
        int_error("Fatal error opening virtual workstation", NO_CARET);

    for( i=0 ; i<10 ; work_in[i++]=1 );
        work_in[10]=2;                  /* use raster coordinates */
    v_opnvwk( work_in, &vdi_vdi_handle, work_out );
    if( !vdi_vdi_handle )
        int_error("Fatal error opening virtual workstation", NO_CARET);

    vst_height(vdi_vdi_handle, VDI_c_height, &dummy, &dummy, &wchar, &hchar);

    vs_clip( vdi_vdi_handle, 0, work_in ); /* turn clipping off */

    term->xmax=work_out[0]+1;
    term->ymax=work_out[1]+1;
    term->h_char=wchar;
    term->v_char=hchar;    /* hchar stands for height this time */
    term->h_tic=(work_out[0]+1)/100;
    term->v_tic=term->h_tic;

    VDI_maxycoord=work_out[1];
    VDI_numcolors=work_out[13];
    pxy_index=0;

    for( i=0 ; i<VDI_numpalette ; i++ ) {
        vq_color( vdi_vdi_handle, i, 1, VDI_savecolors[i] );

        rgb[0]=1000*(VDI_colors[i]>>8);
        rgb[0]/=15;
        rgb[1]=1000*((VDI_colors[i]>>4)&15);
        rgb[1]/=15;
        rgb[2]=1000*(VDI_colors[i]&15);
        rgb[2]/=15;
        vs_color(vdi_vdi_handle, i, rgb );
    }
#ifdef __PUREC__
/* currently the PureC version runs as .prg and the GCC version runs as .ttp.
   Let's hope that we soon figure out which way is the best */
    v_hide_c(vdi_vdi_handle);
#endif
}

TERM_PUBLIC void VDI_reset( )
{
    int i;

    if( vdi_vdi_handle!=-1 ) {
        for( i=0 ; i<VDI_numpalette ; i++ ) {
            vs_color(vdi_vdi_handle, i, VDI_savecolors[i] );
        }
#ifdef __PUREC__
/* see above */
	v_show_c(vdi_vdi_handle, 0);
#endif
        v_clsvwk( vdi_vdi_handle );
        vdi_vdi_handle=-1;
    }
}

TERM_PUBLIC void VDI_graphics( )
{
    int pxy[8];
    MFDB mfdb;

    fflush( stdout );
    fflush( stderr );
    Cconws( "\033f" ); /* turn cursor off */
/*  apparently v_clrwk doesn't work with overscan. We'll blit the screen clear.
    v_clrwk( vdi_vdi_handle );
*/
    mfdb.fd_addr=NULL; /* NULL means actual screen. So we don't need size etc. */

    pxy[0]=pxy[4]=0;
    pxy[1]=pxy[5]=0;
    pxy[2]=pxy[6]=term->xmax-1;
    pxy[3]=pxy[7]=term->ymax-1;

    vro_cpyfm( vdi_vdi_handle, ALL_WHITE /*0*/, pxy, &mfdb, &mfdb );

    pxy_index=0;
}

TERM_PUBLIC void VDI_text( )
{
    vdi_flush_line( );
    Cnecin();		/* wait for any char --> enable screen dump */
    Cconws( "\033e" );  /* turn cursor on again */
}

TERM_PUBLIC void VDI_move( unsigned int x, unsigned int y )
{
    vdi_flush_line( );

    pxy_index=1;
    pxy[0]=x;
    pxy[1]=VDI_yc(y);
}

TERM_PUBLIC void VDI_vector( unsigned int x, unsigned int y )
{
    pxy[2*pxy_index]=x;
    pxy[2*pxy_index+1]=VDI_yc(y);
    pxy_index++;

    if( pxy_index==64 ) {   /* we're all full */
        vdi_flush_line( );
    }
}

TERM_PUBLIC void VDI_linetype( int lt )
{
    vdi_flush_line( );

    VDI_lt=lt;
}

TERM_PUBLIC void VDI_put_text( unsigned int x, unsigned int y, char *str )
{
    int vchar=term->v_char;
    int dummy;

    if( !strlen(str) ) return;

    if( x<0 ) x=0;
    if( y<0 ) y=0;

    /* align text left and to middle of char height */
    vst_alignment( vdi_vdi_handle, 0, 5, &dummy, &dummy );
    vst_rotation( vdi_vdi_handle, (VDI_rotation ? 900 : 0) );
    if( VDI_rotation ) 
        v_gtext( vdi_vdi_handle, x-vchar/2+1, VDI_yc(y)-1, str );
    else
        v_gtext( vdi_vdi_handle, x+1, VDI_yc(y)-vchar/2+1, str );
}

TERM_PUBLIC int VDI_text_angle( int ang )
{
    VDI_rotation=ang;

    return TRUE;
}

TERM_PUBLIC int VDI_justify_text( enum JUSTIFY mode )
{
    return FALSE;
}

TERM_PUBLIC void VDI_point(unsigned int x, unsigned int y, int number )
{
    int old_linetype;

    if( VDI_numcolors==2 ) {
        line_and_point( x, y, number ); /* monochrome */
    } else {
	/* we map colors that exceed our limit to dotted lines, but we can't do
	   that with the markers (sortof a generalized line_and_point) */
	old_linetype=VDI_lt;
	if( VDI_lt>VDI_numcolors-2 )
	    VDI_linetype(VDI_lt%(VDI_numcolors-2)); /* same color, but no dots */
        do_point( x, y, number );
	VDI_linetype(old_linetype);
    }
}

static void vdi_flush_line( )
{
    int line_type;
    int color_index;
    int i;

    if( pxy_index>=2 ) {
        if( VDI_numcolors==2 ) { /* Monochrome */
            color_index=1;
            line_type=VDI_lt;
            if (line_type >= 0)
                line_type %= (VDI_LINETYPES_MAX - 2);
        } else { /* Color */
            if (VDI_lt<0) {
                color_index=1;
                line_type= VDI_lt;
            }
            else {
            	color_index=2+VDI_lt%(VDI_numcolors-2);
            	line_type=(VDI_lt/(VDI_numcolors-2)) % (VDI_LINETYPES_MAX - 2);
            }
        }

        vswr_mode( vdi_vdi_handle, MD_TRANS);
        vsl_color( vdi_vdi_handle, color_index );

        vsl_type( vdi_vdi_handle, 7 );
        vsl_udsty( vdi_vdi_handle, VDI_linetypes[line_type + 2] );

        v_pline( vdi_vdi_handle, pxy_index, pxy );
    }

    if( pxy_index>=1 ) {
        pxy[0]=pxy[2*(pxy_index-1)];
        pxy[1]=pxy[2*(pxy_index-1)+1];
        pxy_index=1;
    }
}

#endif /* TERM_BODY */

#ifdef TERM_TABLE

TERM_TABLE_START(vdi_driver)	
	"vdi", "Atari VDI-Terminal",
	VDI_XMAX, VDI_YMAX, VDI_VCHAR, VDI_HCHAR, 
	VDI_VTIC, VDI_HTIC, VDI_options, VDI_init, VDI_reset, 
	VDI_text, null_scale, VDI_graphics, VDI_move, VDI_vector, 
	VDI_linetype, VDI_put_text, VDI_text_angle, 
	VDI_justify_text, VDI_point, do_arrow, set_font_null,
	0, TERM_CAN_MULTIPLOT, 0, 0
TERM_TABLE_END(vdi_driver)

#undef LAST_TERM
#define LAST_TERM vdi_driver

#endif /* TERM_TABLE */

#endif /* TERM_PROTO_ONLY */

#ifdef TERM_HELP
START_HELP(vdi)
"1 atari ST (via VDI)",
"?set terminal vdi",
"?vdi",
" This terminal is the same as the `atari` terminal, except for the fact that",
" it sends output to the screen via the VDI and not into AES-Windows.",
"",
" The `vdi` terminal has the same options as the `atari` terminal."
END_HELP(vdi)
#endif /* TERM_HELP */
