/*
 * FSM gdos bindings
 * this file has some relationship to a file supplied by Atari
 * but it changed quite a bit (among other things it appears to work).
 * v_shtext survived verbatim from the original.
 */

#include "common.h"
#ifndef _COMPILER_H
# include <compiler.h>
#endif
#include <types.h>

/* FSMBIND functions
 * ======================================================================
 */

#ifdef __DEF_ALL__

#define L_v_getbit
#define L_vqt_fext
#define L_v_ftext
#define L_v_killou
#define L_v_getout
#define L_vst_scra
#define L_vst_erro
#define L_v_shtext
#define L_vst_arbp
#define L_vqt_adva
#define L_vqt_devi
#define L_v_saveca
#define L_v_loadca
#define L_v_flushc
#define L_vst_sets
#define L_vst_skew
#define L_vqt_get_
#define L_vqt_cach

#endif /* __DEF_ALL__ */

#ifdef L_v_getbit

/* ---------------------------------------------------------------------------
 * Retrieve placement information for FSM generated characters
 * Information is placed in infoarray of 52 ints.
 * Borrow a soothsayer from DRI or Atari to find its meaning.
 *
 * This is a temporary bindings since one genius decided
 * that some entries in infoarray will represent real numbers.
 * You may fully expect that that this representation of reals is
 * absolutely different from what your compiler is using.
 * Count your lucky stars if at least sizeof(double) == 2 * sizeof(int).
 * Or maybe sizeof(double) is supposed to be sizeof(float)?
 */
void
v_getbitmap_info(int handle, int ch, int infoarray[52])
{
    short *ptr = _intin;

    *ptr++ = ch;
    *(int **)ptr = &infoarray[0];

    __vdi__(VDI_CONTRL_ENCODE(239, 0, 3, 0), handle);

#ifndef __MSHORT__
    /* Repack returned information from an array of shorts into an
       array of ints */
    { /* dummy block to contain new declarations */
	short *s_ptr = (short *)(&infoarray[0]) + 52;
	short *bot   = (short *)(&infoarray[0]) +  4;
	int   *i_ptr = (&infoarray[0]) + 52;

	do {
	    s_ptr -= 2;		      /* copy y-offset */
	    *(--i_ptr) = *(int *)s_ptr;
	    *(--i_ptr) = 0;
	
	    s_ptr -= 2;		      /* copy x-offset */
	    *(--i_ptr) = *(int *)s_ptr;
	    *(--i_ptr) = 0;
	    
	    *(--i_ptr) = *(--s_ptr);  /* bitmap height */
	    *(--i_ptr) = *(--s_ptr);  /* bitmap width  */
	} while (s_ptr > bot);

	*(--i_ptr) = *(--s_ptr);      /* remainder y-advance */
	*(--i_ptr) = *(--s_ptr);      /* y-advance */
	*(--i_ptr) = *(--s_ptr);      /* remainder x-advance */
	*i_ptr     = *s_ptr;          /* x-advance */
    }
#endif /* __MSHORT__ */
}

#endif /* L_v_getbit */

#ifdef L_vqt_fext

/* ---------------------------------------------------------------------------
 * Inquire text extent, accounting for FSM text placement
 */
void
vqt_f_extent(int handle, const char *str, int extent[8])
{
    unsigned char ch;
    short *ptr;
    int   *ept, *end;
    
    ptr = _intin;
    while ( ch = *str++)
	*ptr++ = ch;
    *ptr = 0;    
    __vdi__(VDI_CONTRL_ENCODE(240, 0, (int)(ptr - _intin), 0), handle);
    
    ptr = _ptsout;
    ept = extent;
    end = ept + 8;
    do {
	*ept++ = *ptr++;
    } while (ept < end);
}

#endif /* L_vqt_fext */


#ifdef L_v_ftext

/* ---------------------------------------------------------------------------
 * Draw FSM text (accounts for fractional advances in rotated text)
 */
void
v_ftext(int handle, int x, int y, const char *str)
{
    unsigned char   ch;
    short *ptr = _intin;
    
    _ptsin[0] = x;
    _ptsin[1] = y;
    while ( ch  = (unsigned const char) *str++)
	*ptr++ = ch;
    *ptr = 0;
    
    __vdi__(VDI_CONTRL_ENCODE(241, 1, (int)(ptr - _intin), 0), handle);
}

#endif /* L_v_ftext */


#ifdef L_v_killou
/* ---------------------------------------------------------------------------
 * Release memory associated with outline component generated by v_getoutline()
 */
void
v_killoutline(int handle, void *component)
{
    *(void **)&_intin[0] =  component;
    __vdi__(VDI_CONTRL_ENCODE(242, 0, 2, 0), handle);
}
#endif /* L_v_killou */


#ifdef L_v_getout
/* ---------------------------------------------------------------------------
 * Generate an outline for character ch, and return the address of the outline.
 */
void
v_getoutline(int handle, int ch, void **component)
{
    _intin[0] = ch;
    *(void ***)&_intin[1] = component;
    __vdi__(VDI_CONTRL_ENCODE(243, 0, 3, 0), handle);
}

#endif /* L_v_getout */


#ifdef L_vst_scra
/* ---------------------------------------------------------------------------
 * Set scratch buffer allocation mode.
 * This buffes is used when creating special effects on fonts.
 * mode=0: (default) account for FSM fonts when allocating scratch buffers
 * mode=1: account only for BM fonts;  no special effects for outlines
 * mode=2: allocate no scratch buffer; no special effects at all
 */
void
vst_scratch(int handle, int mode)
{
    _intin[0] = mode;
    __vdi__(VDI_CONTRL_ENCODE(244, 0, 1, 0), handle);
}

#endif /* L_vst_scra */


#ifdef L_vst_erro

/* ---------------------------------------------------------------------------
 * Set FSM error mode.
 * mode=1: (default) errors go to screen.
 * mode=0: errors reported in error variable `errorvar'.
 */
void
vst_error(int handle, int mode, int *errorvar)
{
    _intin[0] = mode;
    *(int **)&_intin[1] = errorvar;
    __vdi__(VDI_CONTRL_ENCODE(245, 0, 3, 0), handle);
}

#endif /* L_vst_erro */


#ifdef L_v_shtext

/* ----------------------------------------------------------------------
 * v_gtext with shadow.
 * Text color should be set to `color' before calling.
 * This is not technically an FSM binding,
 * but this module is a convenient place for it.
 */
void
v_shtext( int wsid, 
	  int x,
	  int y,
	  const char * text,
	  int color,
	  int xshadow,
	  int yshadow )
{
    __EXTERN void v_ftext __PROTO((int, int, int, const char *));
    __EXTERN int vst_color __PROTO((int, int));

    if( xshadow || yshadow )
    {
	v_ftext( wsid, x+xshadow*2, y+yshadow*2, text );
	(void) vst_color( wsid, 0 );
	v_ftext( wsid, x+xshadow, y+yshadow, text );
	(void) vst_color( wsid, color );
    }
    v_ftext( wsid, x, y, text );
}
#endif /* L_v_shtext */


#ifdef L_vst_arbp

/* ----------------------------------------------------------------------
 * Set character cell height to arbitrary value.
 * Height is given in printer points (more or less) and it does not
 * have to be listed in extend.sys.
 * Only for FSM outline fonts.
 */
int
vst_arbpt( int handle,
	   int point,
	   int *wchar,
	   int *hchar,
	   int *wcell,
	   int *hcell )
{
    short	*outp = &_ptsout[0];

    _intin[0] = point;
    __vdi__(VDI_CONTRL_ENCODE(246, 0, 1, 0), handle);
    *wchar = *outp++;
    *hchar = *outp++;
    *wcell = *outp++;
    *hcell = *outp;

    return _intout[0];
}
#endif /* L_vst_arbp */

#ifdef L_vqt_adva

/* ----------------------------------------------------------------------
 * Inquire FSM text advance placement vector.
 * Remainders xrem and yrem are modulo 16384 (2^14, 1 << 14)
 */
void
vqt_advance( int handle, int ch, int *xadv, int *yadv, int *xrem, int *yrem)
{
    short	*outp = &_ptsout[0];

    _intin[0] = ch;
    __vdi__(VDI_CONTRL_ENCODE(247, 0, 1, 0), handle);
    *xadv = *outp++;
    *yadv = *outp++;
    *xrem = *outp++;
    *yrem = *outp;
}
#endif /* L_vqt_adva */

#ifdef L_vqt_devi

/* ----------------------------------------------------------------------
 * Inquire device status information.
 * 
 * Watch out!  Name is returned as a COUNTED string in 8+3 format,
 * without separator, all in an upper case.  Missing character
 * positions are filled with blanks.
 * (At least this was the case for some versions of FSMGDOS.
 * Who knows what will happen next.  This is NOT documented.
 * Check before you jump!)
 */
void
vqt_devinfo( int handle, int device, int *isdev, char *drivername )
{
    short	*ioutp, *end;

    _intin[0] = device;
    __vdi__(VDI_CONTRL_ENCODE(248, 0, 1, 0), handle);
    if (0 != (*isdev = _ptsout[0])) {
	ioutp = _intout;
	end  = ioutp + _contrl[4];
	do {
	    *drivername++ = (char) *ioutp++;
	} while (ioutp < end);
    }
    *drivername = '\0';
}
#endif /* L_vqt_devi */

#ifdef L_v_saveca

/* ----------------------------------------------------------------------
 * Save FSM cache to disk.
 */
int
v_savecache( int handle, char *filename )
{
    short       *inptr = _intin;

    while (*inptr++ = *filename++)
	;	/* nothing */
    __vdi__(VDI_CONTRL_ENCODE(249, 0, (int)(inptr - _intin), 0), handle);

    return _intout[0];
}
#endif /* L_v_saveca */

#ifdef L_v_loadca

/* ----------------------------------------------------------------------
 * Load/merge FSM cache from disk.
 */
int
v_loadcache( int handle, char *filename, int mode )
{
    short *inptr = _intin;

    *inptr++ = mode;
    while (*inptr++ = *filename++)
	;	/* nothing */
    __vdi__(VDI_CONTRL_ENCODE(250, 0, (int)(inptr - _intin), 0), handle);

    return _intout[0];
}
#endif /* L_v_loadca */

#ifdef L_v_flushc

/* ----------------------------------------------------------------------
 * Flush FSM cache.
 */
int
v_flushcache( int handle )
{
    __vdi__(VDI_CONTRL_ENCODE(251, 0, 0, 0), handle);

    return _intout[0];
}
#endif /* L_v_flushc */

#ifdef L_vst_sets

/* ----------------------------------------------------------------------
 * Set character cell width (set size) to arbitrary value.
 * Width is given in printer points (more or less).
 * Only for FSM outline fonts.
 * Effects are cancelled by calls to vst_point, vst_arbpt or vst_height.
 */
int
vst_setsize( int handle,
	     int point,
	     int *wchar,
	     int *hchar,
	     int *wcell,
	     int *hcell )
{
    short *outp = &_ptsout[0];
    
    _intin[0] = point;
    __vdi__(VDI_CONTRL_ENCODE(252, 0, 1, 0), handle);

    *wchar = *outp++;
    *hchar = *outp++;
    *wcell = *outp++;
    *hcell = *outp;

    return _intout[0];
}
#endif /* L_vst_sets */

#ifdef L_vst_skew

/* ----------------------------------------------------------------------
 * Set FSM skew.
 * Skew in tenths of degrees.  Valid values between -900 and 900.
 */
int
vst_skew( int handle, int skew )
{
    _intin[0] = skew;
    __vdi__(VDI_CONTRL_ENCODE(253, 0, 1, 0), handle);

    return _intout[0];
}
#endif /* L_vst_skew */

#ifdef L_vqt_get_

/* ----------------------------------------------------------------------
 * Get FSM GASCII tables.
 */
void
vqt_get_tables( int handle, void **gascii, void **style )
{
    __vdi__(VDI_CONTRL_ENCODE(254, 0, 0, 0), handle);
    *gascii = *(void **)&_intout[0];
    *style =  *(void **)&_intout[2];
}
#endif /* L_vqt_get_ */

#ifdef L_vqt_cach

/* ----------------------------------------------------------------------
 * Get FSM cashe size
 */
void
vqt_cachesize( int handle, int which_cache, size_t *size )
{
    _intin[0] = which_cache;
    __vdi__(VDI_CONTRL_ENCODE(255, 0, 1, 0), handle);
    *size = *(size_t *)&_intout[0];
}
#endif /* L_vqt_cach */

/* -eof- */
