/* gglue.c - Graphics glue routines */

/************************************************************************/
/*	Copyright (C) 1986-1993 Phar Lap Software, Inc.			*/
/*	Unpublished - rights reserved under the Copyright Laws of the	*/
/*	United States.  Use, duplication, or disclosure by the 		*/
/*	Government is subject to restrictions as set forth in 		*/
/*	subparagraph (c)(1)(ii) of the Rights in Technical Data and 	*/
/*	Computer Software clause at 252.227-7013.			*/
/*	Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138	*/
/************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pharlap.h>
#include "gserver.h"

/*
 * Include the Microsoft graphics library definition file.  Before we do
 * this, we will undefine the keywords '__far' and '__huge' so that we will
 * be able to compile the function prototypes with all 32-bit compilers.
 *
 * Also, for MetaWare High C/C++, define '__cdecl' so all the prototypes
 * in graph.h work.
 */
#undef __far
#undef __huge
#define __far
#define __huge
#ifdef __HIGHC__
#define __cdecl
#endif
#ifndef _MSC_VER
#define _MSC_VER 700	/* so __far and __huge don't get defined again */
#endif
#include "graph.h"

/*
 * Global data used by the glue code
 */
int _gopenf = 0;	/* Graphics server is open (initialized) flag */
int _gregf = 0;		/* "_gclose" has been registered with "exit" flag */

char def_dname[] = "gserver.drv";	/* Default name of the graphics
					   server */
REALPTR _server_func;	/* Real mode FAR address of the graphics server */
			/* function entry point */


GBPTR _gbuffp;		/* Pointer to the protected mode graphics */
			/* commands buffer */
USHORT _rbuffseg;	/* Real mode segment addr of real mode */
			/* graphics commands buffer */
REALPTR _rbuffp;	/* Real mode FAR ptr to the real mode */
			/* graphics commands buffer */

int _gbuff_flag;	/* Buffered mode flag - TRUE = buffered, FALSE =
			   unbuffered */

REALPTR protpsp;	/* protected mode PSP */


/*
 * Prototypes for functions in this file
 */
static int _gopen(char *fnp);
#ifdef __WATCOMC__
void _gclose(void);
#else
void __cdecl _gclose(void);
#endif
static GBPTR _galloc(unsigned nbytes);
static void _gflush();

/*
 * Prototypes for functions in prot.asm
 * Force C stack-based calling conventions for these.
 */
#ifdef __cplusplus
extern "C" {
#endif
void __STKCALL realexit();
int __STKCALL realload(char *filenamep, REALPTR *server_funcp);
#ifdef __cplusplus
}
#endif

/*

_gopen - Open (initialize) the real mode graphics server

	fnp	pointer to name of .EXE file containing real mode graphics
		server program

Returns:
	0	if success
	<>0	if error
*/
static int _gopen(char *fnp)
{
	int rc;			/* Return code */
	USHORT largest;		/* largest number of page available */

	/* Make a quick return if the server is already open */
	if(_gopenf)
		return 0;

	/* Allocate real mode graphics commands buffer */
	/* If error terminate program */
	rc = _dx_real_alloc(GBUFF_SIZE / 16, &_rbuffseg, &largest);
	if (rc != 0)
	{
		printf("Can't allocate real mode commands buffer: \
DOS error = %d\n", rc);
		exit(rc);
	}
	RP_SET(_rbuffp, 0, _rbuffseg);

	/* Allocate protected mode graphics commands buffer */
	/* If error terminate program */
	_gbuffp = malloc(GBUFF_SIZE);
	if (_gbuffp == NULL)
	{
		printf("Can't allocate protected mode commands buffer\n");
		exit(1);
	}

        /* Load and initialize the real mode graphics server */
        /* If there was a load error terminate the program */
        rc = realload(fnp, &_server_func);
        if(rc)
        {
                printf("Error loading real mode graphics server: %s: ", fnp);
                switch(rc)
                {
                case 2:
                        printf("file not found\n");
                        break;
                case 5:
                        printf("access denied\n");
                        break;
                case 8:
                        printf("insufficient memory\n");
                        break;
                case 10:
                        printf("invalid environment segment\n");
                        break;
                case 11:
                        printf("invalid file format\n");
                        break;
                default:
                        printf("error code=%d\n", rc);
                        break;
                }
                exit(rc);
        }

	/* Mark the protected mode graphics commands buffer empty. */
	*(GBSPTR)_gbuffp = sizeof(short);

	/* Start the graphics server in buffered mode. */
	_gbuff_flag = 0;

	/* Turn on the open flag */
	_gopenf = 1;

	/* Register _gclose to be called at exit time */
	if(!_gregf)
	{
		_gregf = 1;
		atexit(_gclose);
	}

	/* Return success */

	return 0;
}


/*

_gclose - Close the graphics driver

	1).  Any existing commands in the graphics commands buffer
	     are executed.

	2).  The server is told to exit and it
	     does any necessary clean-up operations.

*/

#ifdef __WATCOMC__
void _gclose(void)
#else
void __cdecl _gclose(void)
#endif
{

	/* Switch on the current state of the open flag.  This switch
	   is required in case we are re-entered due to an abnormal error
	   exit from "_gflush" or "realexit". */

	switch(_gopenf)
	{

	/* First flush any commands in the graphics commands buffer */
	case 1:
		++_gopenf;
		_gflush();

	/* Then tell the real mode code to exit */
	case 2:
		++_gopenf;
		realexit(protpsp);
		
	/* Then turn off the open flag */
	default:
		_gopenf = 0;
		break;
		
	}

	/* free the buffers */
	_dx_real_free(_rbuffseg);
	free(_gbuffp);

	/* Return */
	return;

}


/*

_gbuffmode - Set video buffering mode

This routine is called to change the buffering mode for the graphics commands
buffer.  The routine takes a single argument which is the new mode. A
value of zero means unbuffered and a value of one means buffered.  The
routine returns as a function result the old mode.

*/

int _gbuffmode(int newmode)

{

	int oldmode;		/* Old buffering mode */

	if(!_gopenf)
		_gopen(def_dname);
	oldmode = _gbuff_flag;
	_gbuff_flag = newmode;
	if(!newmode)
		_gflush();

	return oldmode;

}


/* 

_galloc - Allocate space in the graphics commands buffer

This routine is used by the glue routines to allocate space
in the graphics commands buffer.  The caller passes in the number
of bytes that it needs in the graphics commands buffer to hold
a command.  If this number of bytes are available, then the
routine returns immediately with a pointer
into the buffer where the command can be placed.  If the
space is not available, then the real mode server is called to
empty out the buffer in order to make room for the new command.
When the server is all done, this routine returns with a 
pointer to the empty graphics commands buffer.

*/

static GBPTR _galloc(unsigned nbytes)
{

	register GBPTR bp;		/* Buffer pointer */
	GBPTR rp;			/* Returned pointer */

	/* If the server is not open, then open to the default server */

	if(!_gopenf)
		_gopen(def_dname);

	/* If the graphics commands buffer does not have enough room for
	   the number of bytes requested by the caller, then flush the buffer
	   by executing all of the commands in it in order to make room. */

	bp = _gbuffp;
	if(SHORT0 + nbytes > GBUFF_SIZE)
		_gflush();

	/* Calculate the return pointer for the caller */

	rp = bp + SHORT0;

	/* Increment the used byte count that is located in the first 2
	   bytes of the buffer */

	*SHORT0P += nbytes;

	/* Return */

	return rp;
}

/*

_gflush - Flush the graphics commands buffer

This routine is called to flush the graphics commands buffer.  If
the buffer is not empty, then this routine calls the real mode
server to execute all of the commands in the buffer.  The buffer
is then marked as empty.

*/

static void _gflush()

{

	register GBPTR bp;		/* Buffer pointer */
	RMC_BLK rm_regs = {0};		/* Real mode register values for call*/

	/* If the server is not open, then return */
	if(!_gopenf)
		return;

	/* If the prot mode commands buffer is not empty, then (1) copy the 
	   buffer to the real mode commands buffer, (2) call the real mode
	   server to execute the graphics commands in the buffer, and (3)
	   copy the real mode buffer back again to get anything returned
	   by the call. */
	bp = _gbuffp;
	if(SHORT0 > sizeof(short))
	{
		WriteRealMem(_rbuffp, _gbuffp, GBUFF_SIZE);
		_dx_call_real(_server_func, &rm_regs, 2, _rbuffp);
		ReadRealMem(_gbuffp, _rbuffp, GBUFF_SIZE);
	}

	/* Empty out the buffer by setting the use count at the front
	   of the buffer to the size of the use count. */
	*SHORT0P = sizeof(short);

}

/*
_arc - _arc glue routine 
*/
short  __cdecl _arc(short x1, short y1, short x2, short y2,
               short x3, short y3, short x4, short y4)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 9 + 1);
	*bp++ = op_arc;
	*SHORT0P = x1;
	*SHORT2P = y1;
	*SHORT4P = x2;
	*SHORT6P = y2;
	*SHORT8P = x3;
	*SHORT10P = y3;
	*SHORT12P = x4;
	*SHORT14P = y4;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT16;
	}
	return 1;
}

/*
_arc_w - _arc_w glue routine 
*/
short  __cdecl _arc_w(double x1, double y1, double x2, double y2,
               double x3, double y3, double x4, double y4)
{

	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(double) * 8 + sizeof(short) + 1);
	*bp++ = op_arc_w;
	*DOUBL0P = x1;
	*DOUBL8P = y1;
	*DOUBL16P = x2;
	*DOUBL24P = y2;
	*DOUBL32P = x3;
	*DOUBL40P = y3;
	*DOUBL48P = x4;
	*DOUBL56P = y4;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT64;
	}
	return 1;
}

/*
_arc_wxy - _arc_wxy glue routine 
*/
short  __cdecl _arc_wxy(const struct _wxycoord *pwxy1, const struct _wxycoord *pwxy2,
		const struct _wxycoord *pwxy3, const struct _wxycoord *pwxy4)
{

	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(struct _wxycoord) * 4 + sizeof(short) + 1);
	*bp++ = op_arc_wxy;
	*DOUBL0P = pwxy1->wx;
	*DOUBL8P = pwxy1->wy;
	*DOUBL16P = pwxy2->wx;
	*DOUBL24P = pwxy2->wy;
	*DOUBL32P = pwxy3->wx;
	*DOUBL40P = pwxy3->wy;
	*DOUBL48P = pwxy4->wx;
	*DOUBL56P = pwxy4->wy;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT64;
	}
	return 1;
}

/*
_clearscreen - _clearscreen glue routine
*/
void  __cdecl _clearscreen(short area)
{
	register GBPTR bp;

	bp = _galloc(sizeof(short) + 1);
	*bp++ = op_clearscreen;
	*SHORT0P = area;
	if(!_gbuff_flag)
		_gflush();
	return;
}

/*
_displaycursor - _displaycursor glue routine 
*/
short  __cdecl _displaycursor(short n)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_displaycursor;
	*SHORT0P = n;
	_gflush();
	return SHORT2;
}


/*
_ellipse - _ellipse glue routine 
*/
short  __cdecl _ellipse(short c, short x1, short y1, short x2, short y2)
{

	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 6 + 1);
	*bp++ = op_ellipse;
	*SHORT0P = c;
	*SHORT2P = x1;
	*SHORT4P = y1;
	*SHORT6P = x2;
	*SHORT8P = y2;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT10;
	}
	return 1;
}

/*
_ellipse_w - _ellipse_w glue routine 
*/
short  __cdecl _ellipse_w(short c, double x1, double y1, double x2, double y2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(double) * 4 + sizeof(short) * 2 + 1);
	*bp++ = op_ellipse_w;
	*SHORT0P = c;
	*DOUBL2P = x1;
	*DOUBL10P = y1;
	*DOUBL18P = x2;
	*DOUBL26P = y2;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT34;
	}
	return 1;
}

/*
_ellipse_wxy - _ellipse_wxy glue routine 
*/
short  __cdecl _ellipse_wxy(short c, const struct _wxycoord *pwxy1, 
				const struct _wxycoord *pwxy2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(struct _wxycoord) * 2 + sizeof(short) * 2 + 1);
	*bp++ = op_ellipse_wxy;
	*SHORT0P = c;
	*DOUBL2P = pwxy1->wx;
	*DOUBL10P = pwxy1->wy;
	*DOUBL18P = pwxy2->wx;
	*DOUBL26P = pwxy2->wy;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT34;
	}
	return 1;
}

/*
_floodfill - _floodfill glue routine 
*/
short  __cdecl _floodfill(short x, short y, short b)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_floodfill;
	*SHORT0P = x;
	*SHORT2P = y;
	*SHORT4P = b;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT6;
	}
	return 1;
}

/*
_floodfill_w - _floodfill_w glue routine 
*/
short  __cdecl _floodfill_w(double x, double y, short b)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(double) * 2 + sizeof(short) + 1);
	*bp++ = op_floodfill;
	*DOUBL0P = x;
	*DOUBL8P = y;
	*SHORT16P = b;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT18;
	}
	return 1;
}


/*
_fmoveto - Fast _moveto glue routine (buffered)
*/
void _fmoveto(short x, short y)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_moveto;
	*SHORT0P = x;
	*SHORT2P = y;
	if(!_gbuff_flag)
		_gflush();
	return;
}

/*
_getactivepage - _getactivepage glue routine 
*/
short  __cdecl _getactivepage(void)
{

	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) + 1);
	*bp++ = op_getactivepage;
	_gflush();
	return SHORT0;
}

/*
_getarcinfo - _getarcinfo glue routine 
*/
short  __cdecl _getarcinfo(struct _xycoord *start, struct _xycoord *end,
		struct _xycoord *fill)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(struct _xycoord) * 3 + sizeof(short) + 1);
	*bp++ = op_getarcinfo;
	*SHORT0P = start->xcoord;
	*SHORT2P = start->ycoord;
	*SHORT4P = end->xcoord;
	*SHORT6P = end->ycoord;
	*SHORT8P = fill->xcoord;
	*SHORT10P = fill->ycoord;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT12;
	}
	return 1;
}


/*
_getbkcolor - _getbkcolor glue routine 
*/
long  __cdecl _getbkcolor(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(long) + 1);
	*bp++ = op_getbkcolor;
	_gflush();
	return LONG0;
}

/*
_getcolor - _getcolor glue routine 
*/
short  __cdecl _getcolor(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 1 + 1);
	*bp++ = op_getcolor;
	_gflush();
	return SHORT0;
}

/*
_getcurrentposition - _getcurrentposition glue routine 
*/
struct _xycoord  __cdecl _getcurrentposition(void)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_getcurrentposition;
	_gflush();
	xy.xcoord = SHORT0;
	xy.ycoord = SHORT2;
	return xy;
}

/*
_getcurrentposition_w - _getcurrentposition_w glue routine 
*/
struct _wxycoord  __cdecl _getcurrentposition_w(void)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _wxycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_getcurrentposition_w;
	_gflush();
	xy.wx = DOUBL0;
	xy.wy = DOUBL8;
	return xy;
}

/*
_getfillmask - _getfillmask glue routine 
*/
unsigned char * __cdecl _getfillmask(register unsigned char *mp)
{
	register GBPTR bp;		/* Buffer pointer */
	int i;				/* Loop counter */

	bp = _galloc(sizeof(short) + 8 + 1);
	*bp++ = op_getfillmask;
	_gflush();
	if(!SHORT8)
		return NULL;
	for(i = 0; i < 8; ++i)
		*mp++ = *bp++;
	return mp - 8;
}


/*
_getfontinfo - _getfontinfo glue routine 
*/
short   __cdecl _getfontinfo(struct _fontinfo *fontbuffer)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(struct _fontinfo) + sizeof(short) + 1);
	*bp++ = op_getfontinfo;
	_gflush();
	fontbuffer->type = ((struct _fontinfo *) bp)->type;
	fontbuffer->ascent = ((struct _fontinfo *) (bp + 2))->ascent;
	fontbuffer->pixwidth = ((struct _fontinfo *) (bp + 4))->pixwidth;
	fontbuffer->pixheight = ((struct _fontinfo *) (bp + 6))->pixheight;
	fontbuffer->avgwidth = ((struct _fontinfo *) (bp + 8))->avgwidth;
	strcpy(fontbuffer->filename , ((struct _fontinfo *)(bp + 10))->filename);
	strcpy(fontbuffer->facename , ((struct _fontinfo *)bp)->facename);
	return SHORT124;
}

/*
_getgtextextent - _getgtextextent glue routine 
*/
short   __cdecl _getgtextextent(const char *text)
{
	register GBPTR bp;	/* Buffer pointer */
	int n;			/* String length */
	int cc;			/* Cycle count */
	int i;			/* Buffer copy count */
	int ret;		/* return value */

	ret = 0;
	n = strlen(text);
	while(n)
	{
		cc = n;
		if(cc > GBUFF_SIZE - 4)
			cc = GBUFF_SIZE - 4;
		bp = _galloc(cc + 4);
		*bp++ = op_getgtextextent;
		for(i = 0; i < cc; ++i)
			*(bp+i) = *(text+i);
		*(bp + cc) = 0;
		n -= cc;
		_gflush();
		ret += *(short *)(bp + cc + 1);
	}
	return ret;
}

/*
_getgtextvector - _getgtextvector glue routine 
*/
struct _xycoord   __cdecl _getgtextvector(void)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_getgtextvector;
	_gflush();
	xy.xcoord = SHORT0;
	xy.ycoord = SHORT2;
	return xy;
}

/*
_getlinestyle - _getlinestyle glue routine 
*/
unsigned short   __cdecl _getlinestyle(void)
{

	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 1 + 1);
	*bp++ = op_getlinestyle;
	_gflush();
	return (unsigned short)SHORT0;

}

/*
_getphyscoord - _getphyscoord glue routine 
*/
struct _xycoord   __cdecl _getphyscoord(short x, short y)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_getphyscoord;
	*SHORT0P = x;
	*SHORT2P = y;
	_gflush();
	xy.xcoord = SHORT4;
	xy.ycoord = SHORT6;
	return xy;
}

/*
_getpixel - _getpixel glue routine
*/
short   __cdecl _getpixel(short x, short y)
{
	register GBPTR bp;

	bp = _galloc(sizeof(short) * 3 + 1);
	*bp++ = op_getpixel;
	*SHORT0P = x;
	*SHORT2P = y;
	_gflush();
	return SHORT4;
}

/*
_getpixel_w - _getpixel_w glue routine
*/
short   __cdecl _getpixel_w(double wx, double wy)
{
	register GBPTR bp;

	bp = _galloc(sizeof(double) * 2 + sizeof(short) + 1);
	*bp++ = op_getpixel_w;
	*DOUBL0P = wx;
	*DOUBL8P = wy;
	_gflush();
	return SHORT16;
}

/*
_gettextcolor - _gettextcolor glue routine 
*/
short   __cdecl _gettextcolor(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 1 + 1);
	*bp++ = op_gettextcolor;
	_gflush();
	return SHORT0;
}

/*
_gettextcursor - _gettextcursor glue routine 
*/
short   __cdecl _gettextcursor(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 1 + 1);
	*bp++ = op_gettextcursor;
	_gflush();
	return SHORT0;
}

/*
_gettextposition - _gettextposition glue routine 
*/
struct _rccoord   __cdecl _gettextposition(void)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _rccoord rc;		/* Row/column structure */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_gettextposition;
	_gflush();
	rc.row = SHORT0;
	rc.col = SHORT2;
	return rc;
}

/*
_getvideoconfig - _getvideoconfig glue routine 
*/
struct _videoconfig * __cdecl _getvideoconfig(struct _videoconfig *p)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 11 + 1);
	*bp++ = op_getvideoconfig;
	_gflush();
	p->numxpixels = SHORT0;
	p->numypixels = SHORT2;
	p->numtextcols = SHORT4;
	p->numtextrows = SHORT6;
	p->numcolors = SHORT8;
	p->bitsperpixel = SHORT10;
	p->numvideopages = SHORT12;
	p->mode = SHORT14;
	p->adapter = SHORT16;
	p->monitor = SHORT18;
	p->memory = SHORT20;
	return p;
}

/*
_gettextwindow - _gettextwindow glue routine
*/
void   __cdecl _gettextwindow(short *r1, short *c1, short *r2, short *c2)
{
	register GBPTR bp;

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_gettextwindow;
	if(!_gbuff_flag)
		_gflush();
	*r1 = SHORT0;
	*c1 = SHORT2;
	*r2 = SHORT4;
	*c2 = SHORT6;
	

	return;
}

/*
_getviewcoord - _getviewcoord glue routine 
*/

struct _xycoord   __cdecl _getviewcoord(short x, short y)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_getviewcoord;
	*SHORT0P = x;
	*SHORT2P = y;
	_gflush();
	xy.xcoord = SHORT4;
	xy.ycoord = SHORT6;
	return xy;
}

/*
_getviewcoord_w - _getviewcoord_w glue routine 
*/
struct _xycoord   __cdecl _getviewcoord_w(double wx, double wy)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 2 + sizeof(double) * 2 + 1);
	*bp++ = op_getviewcoord_w;
	*DOUBL0P = wx;
	*DOUBL8P = wy;
	_gflush();
	xy.xcoord = SHORT16;
	xy.ycoord = SHORT18;
	return xy;
}

/*
_getviewcoord_wxy - _getviewcoord_wxy glue routine 
*/
struct _xycoord   __cdecl _getviewcoord_wxy(const struct _wxycoord *pwxy1)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 2 + sizeof(double) * 2 + 1);
	*bp++ = op_getviewcoord_wxy;
	*DOUBL0P = pwxy1->wx;
	*DOUBL8P = pwxy1->wy;
	_gflush();
	xy.xcoord = SHORT16;
	xy.ycoord = SHORT18;
	return xy;
}

/*
_getvisualpage - _getvisualpage glue routine 
*/
short   __cdecl _getvisualpage(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 1 + 1);
	*bp++ = op_getvisualpage;
	_gflush();
	return SHORT0;
}

/*
_getwindowcoord - _getwindowcoord glue routine 
*/

struct _wxycoord  __cdecl _getwindowcoord(short x, short y)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _wxycoord wxy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_getwindowcoord;
	*SHORT0P = x;
	*SHORT2P = y;
	_gflush();
	wxy.wx = DOUBL4;
	wxy.wy = DOUBL12;
	return wxy;
}

/*
_getwritemode - _getwritemode glue routine 
*/
short   __cdecl _getwritemode(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 1 + 1);
	*bp++ = op_getwritemode;
	_gflush();
	return SHORT0;
}

/*
_grstatus - _grstatus glue routine 
*/
short   __cdecl _grstatus(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) + 1);
	*bp++ = op_grstatus;
	_gflush();
	return SHORT0;
}

/*
_imagesize - _imagesize glue routine 
*/
long   __cdecl _imagesize(short x1, short y1, short x2, short y2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 4 + sizeof(long) + 1);
	*bp++ = op_imagesize;
	*SHORT0P = x1;
	*SHORT2P = y1;
	*SHORT4P = x2;
	*SHORT6P = y2;
	_gflush();
	return LONG8;
}

/*
_imagesize_w - _imagesize_w glue routine 
*/
long   __cdecl _imagesize_w(double x1, double y1, double x2, double y2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(double) * 4 + sizeof(long) + 1);
	*bp++ = op_imagesize_w;
	*DOUBL0P = x1;
	*DOUBL8P = y1;
	*DOUBL16P = x2;
	*DOUBL24P = y2;
	_gflush();
	return LONG32;
}

/*
_imagesize_wxy - _imagesize_wxy glue routine 
*/
long   __cdecl _imagesize_wxy(const struct _wxycoord *pwxy1 ,
				const struct _wxycoord *pwxy2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(double) * 4 + sizeof(long) + 1);
	*bp++ = op_imagesize_wxy;
	*DOUBL0P = pwxy1->wx;
	*DOUBL8P = pwxy1->wy;
	*DOUBL16P = pwxy2->wx;
	*DOUBL24P = pwxy2->wy;
	_gflush();
	return LONG32;
}

/*
_inchar - _inchar glue routine
*/

short   __cdecl _inchar(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) + 1);
	*bp++ = op_inchar;
	_gflush();
	return SHORT0;
}


/*
_lineto - _lineto glue routine
*/
short   __cdecl _lineto(short x, short y)
{
	register GBPTR bp;

	bp = _galloc(sizeof(short) * 3 + 1);
	*bp++ = op_lineto;
	*SHORT0P = x;
	*SHORT2P = y;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT4;
	}
	return 1;
}

/*
_lineto_w - _lineto_w glue routine
*/
short   __cdecl _lineto_w(double x, double y)
{
	register GBPTR bp;

	bp = _galloc(sizeof(double) * 2 + sizeof(short) + 1);
	*bp++ = op_lineto_w;
	*DOUBL0P = x;
	*DOUBL8P = y;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT16;
	}
	return 1;
}

/*
_moveto - _moveto glue routine
*/
struct _xycoord   __cdecl _moveto(short x, short y)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord ppnt;		/* Previous point */

	bp = _galloc(sizeof(short) * 3 + 1);
	*bp++ = op_moveto;
	*SHORT0P = x;
	*SHORT2P = y;
	_gflush();
	ppnt.xcoord= SHORT4;
	ppnt.ycoord = SHORT6;
	return ppnt;
}

/*
_moveto_w - _moveto_w glue routine
*/
struct _wxycoord   __cdecl _moveto_w(double wx, double wy)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _wxycoord ppnt;		/* Previous point */

	bp = _galloc(sizeof(double) * 3 + 1);
	*bp++ = op_moveto_w;
	*DOUBL0P = wx;
	*DOUBL8P = wy;
	_gflush();
	ppnt.wx= DOUBL16;
	ppnt.wy= DOUBL24;
	return ppnt;
}

/*
_outgtext - _outgtext glue routine 
*/
void   __cdecl _outgtext(const char *p)
{
	register GBPTR bp;	/* Buffer pointer */
	int n;			/* String length */
	int cc;			/* Cycle count */
	int i;			/* Buffer copy count */

	n = strlen(p);
	while(1)
	{
		cc = n;
		if(cc > GBUFF_SIZE - 2)
			cc = GBUFF_SIZE - 2;
		bp = _galloc(cc + 2);
		*bp++ = op_outgtext;
		for(i = 0; i < cc; ++i)
			*(bp+i) = *(p+i);
		*(bp + cc) = 0;
		n -= cc;
		if(n == 0)
			break;
		_gflush();
	}
}

/*
_outmem - _outmem glue routine 
*/
void   __cdecl _outmem(const char *p, short len)
{
	register GBPTR bp;	/* Buffer pointer */
	int cc;			/* Cycle count */
	int i;			/* Buffer copy count */

	while(1)
	{
		cc = len;
		if(cc > GBUFF_SIZE - 2)
			cc = GBUFF_SIZE - 2;
		bp = _galloc(cc + 2);
		*bp++ = op_outmem;
		for(i = 0; i < cc; ++i)
			*(bp+i) = *(p+i);
		*(bp + cc) = 0;
		len -= cc;
		if(len == 0)
			break;
		_gflush();
	}
}

/*
_outtext - _outtext glue routine 
*/
void   __cdecl _outtext(const char *p)
{
	register GBPTR bp;	/* Buffer pointer */
	int n;			/* String length */
	int cc;			/* Cycle count */
	int i;			/* Buffer copy count */

	n = strlen(p);
	while(1)
	{
		cc = n;
		if(cc > GBUFF_SIZE - 2)
			cc = GBUFF_SIZE - 2;
		bp = _galloc(cc + 2);
		*bp++ = op_outtext;
		for(i = 0; i < cc; ++i)
			*(bp+i) = *(p+i);
		*(bp + cc) = 0;
		n -= cc;
		if(n == 0)
			break;
	}
	_gflush();
	return;
}

/*
_pie - _pie glue routine 
*/
short   __cdecl _pie(short c, short x1, short y1, short x2, short y2,
               short x3, short y3, short x4, short y4)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 10 + 1);
	*bp++ = op_pie;
	*SHORT0P = c;
	*SHORT2P = x1;
	*SHORT4P = y1;
	*SHORT6P = x2;
	*SHORT8P = y2;
	*SHORT10P = x3;
	*SHORT12P = y3;
	*SHORT14P = x4;
	*SHORT16P = y4;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT18;
	}
	return 1;
}

/*
_pie_w - _pie_w glue routine 
*/
short   __cdecl _pie_w(short c, double x1, double y1, double x2, double y2,
               double x3, double y3, double x4, double y4)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + sizeof(double) * 8 + 1);
	*bp++ = op_pie_w;
	*SHORT0P = c;
	*DOUBL2P = x1;
	*DOUBL10P = y1;
	*DOUBL18P = x2;
	*DOUBL26P = y2;
	*DOUBL34P = x3;
	*DOUBL42P = y3;
	*DOUBL50P = x4;
	*DOUBL58P = y4;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT66;
	}
	return 1;
}

/*
_pie_wxy - _pie_wxy glue routine 
*/
short   __cdecl _pie_wxy(short c, const struct _wxycoord *pwxy1, 
	const struct _wxycoord *pwxy2, const struct _wxycoord *pwxy3, 
	const struct _wxycoord *pwxy4)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + sizeof(double) * 8 + 1);
	*bp++ = op_pie_wxy;
	*SHORT0P = c;
	*DOUBL2P = pwxy1->wx;
	*DOUBL10P = pwxy1->wy;
	*DOUBL18P = pwxy2->wx;
	*DOUBL26P = pwxy2->wy;
	*DOUBL34P = pwxy3->wx;
	*DOUBL42P = pwxy3->wy;
	*DOUBL50P = pwxy4->wx;
	*DOUBL58P = pwxy4->wy;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT66;
	}
	return 1;
}

/*
_rectangle - _rectangle glue routine 
*/
short   __cdecl _rectangle(short c, short x1, short y1, short x2, short y2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 6 + 1);
	*bp++ = op_rectangle;
	*SHORT0P = c;
	*SHORT2P = x1;
	*SHORT4P = y1;
	*SHORT6P = x2;
	*SHORT8P = y2;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT10;
	}
	return SHORT10;
}

/*
_rectangle_w - _rectangle_w glue routine 
*/
short   __cdecl _rectangle_w(short c, double x1, double y1, double x2, double y2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + sizeof(double) * 4 + 1);
	*bp++ = op_rectangle_w;
	*SHORT0P = c;
	*DOUBL2P = x1;
	*DOUBL10P = y1;
	*DOUBL18P = x2;
	*DOUBL26P = y2;
	if(!_gbuff_flag)
	{
		_gflush();
		return SHORT34;
	}
	return SHORT34;
}

/*
_rectangle_wxy - _rectangle_wxy glue routine 
*/
short   __cdecl _rectangle_wxy(short c, const struct _wxycoord *pwxy1, 
				const struct _wxycoord *pwxy2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + sizeof(double) * 4 + 1);
	*bp++ = op_rectangle_wxy;
	*SHORT0P = c;
	*DOUBL2P = pwxy1->wx;
	*DOUBL10P = pwxy1->wy;
	*DOUBL18P = pwxy2->wx;
	*DOUBL26P = pwxy2->wy;
	_gflush();
	return SHORT34;
}

/*
_registerfonts - _registerfonts glue routine 
*/
short   __cdecl _registerfonts(const char *pathname)
{
	register GBPTR bp;	/* Buffer pointer */
	int n;			/* String length */
	int cc;			/* Cycle count */
	int i;			/* Buffer copy count */
	int ret;		/* return value */

	ret = 0;
	n = strlen(pathname);
	while(n)
	{
		cc = n;
		if(cc > GBUFF_SIZE - 4)
			cc = GBUFF_SIZE - 4;
		bp = _galloc(cc + 4);
		*bp++ = op_registerfonts;
		for(i = 0; i < cc; ++i)
			*(bp+i) = *(pathname+i);
		*(bp + cc) = 0;
		n -= cc;
		_gflush();
		ret += *(short *)(bp + cc + 1);
	}
	return ret;
}

/*
_remapallpalette - _rempallpalette glue routine 
*/
short  __cdecl _remapallpalette(const long *p)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _videoconfig vc;
	int size;

//
// Figure out how big the array is
//
	_getvideoconfig(&vc);
	if (vc.numcolors == 256)
		size = 256 * sizeof(long);
	else if (vc.numcolors == 64)
		size = 64 * sizeof(long);
	else
		size = 16 * sizeof(long);

	bp = _galloc(size + sizeof(long) + sizeof(short) + 1);
	*bp++ = op_remapallpalette;
	*LONG0P = size;
	memcpy(LONG6P, p, size);
	if(!_gbuff_flag)
	{
		_gflush();
		return *SHORT4P;
	}
	return 0;
}

/*
_remappalette - _remappalette glue routine 
*/
long   __cdecl _remappalette(short p, long c)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) + sizeof(long) + 1);
	*bp++ = op_remappalette;
	*SHORT0P = p;
	*LONG2P = c;
	_gflush();
	return LONG6;
}

/*
_scrolltextwindow - Fast _scrolltextwindow glue routine (buffered)
*/
void   __cdecl _scrolltextwindow(short lines)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) + 1);
	*bp++ = op_scrolltextwindow;
	*SHORT0P = lines;
	if(!_gbuff_flag)
		_gflush();
	return;
}

/*
_selectpalette - _selectpalette glue routine 
*/
short   __cdecl _selectpalette(short n)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_selectpalette;
	*SHORT0P = n;
	_gflush();
	return SHORT2;
}

/*
_setactivepage - _setactivepage glue routine 
*/
short   __cdecl _setactivepage(short n)
{

	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_setactivepage;
	*SHORT0P = n;
	_gflush();
	return SHORT2;
}

/*
_setbkcolor - _setbkcolor glue routine 
*/
long   __cdecl _setbkcolor(long c)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(long) * 2 + 1);
	*bp++ = op_setbkcolor;
	*LONG0P = c;
	_gflush();
	return LONG4;
}

/*
_setcliprgn - _setcliprgn glue routine 
*/
void   __cdecl _setcliprgn(short x1, short y1, short x2, short y2)
{

	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_setcliprgn;
	*SHORT0P = x1;
	*SHORT2P = y1;
	*SHORT4P = x2;
	*SHORT6P = y2;
	if(!_gbuff_flag)
		_gflush();
	return;
}

/*
_setcolor - _setcolor glue routine 
*/
short   __cdecl _setcolor(short c)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_setcolor;
	*SHORT0P = c;
	_gflush();
	return SHORT2;
}

/*
_setfillmask - _setfillmask glue routine 
*/
void   __cdecl _setfillmask(const unsigned char *p)
{
	register GBPTR bp;		/* Buffer pointer */
	int i;

	if(p == NULL)
	{
		bp = _galloc(1);
		*bp++ = op_setnullmask;
	}
	else
	{
		bp = _galloc(8 + 1);
		*bp++ = op_setfillmask;
		for(i = 0; i < 8; ++i)
			*(bp+i) = *(p+i);
	}
	if(!_gbuff_flag)
		_gflush();
	return;
}

/*
_setfont - _setfont glue routine 
*/
short   __cdecl _setfont(const char *option)
{
	register GBPTR bp;	/* Buffer pointer */
	int n;			/* String length */
	int cc;			/* Cycle count */
	int i;			/* Buffer copy count */
	int ret;		/* return value */

	ret = 0;
	n = strlen(option);
	while(n)
	{
		cc = n;
		if(cc > GBUFF_SIZE - 4)
			cc = GBUFF_SIZE - 4;
		bp = _galloc(cc + 4);
		*bp++ = op_setfont;
		for(i = 0; i < cc; ++i)
			*(bp+i) = *(option+i);
		*(bp + cc) = 0;
		n -= cc;
		_gflush();
		ret += *(short *)(bp + cc + 1);
	}
	return ret;
}

/*
_setgtextvector - _setgtextvector glue routine 
*/
struct _xycoord   __cdecl _setgtextvector(short x, short y)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_setgtextvector;
	*SHORT0P = x;
	*SHORT2P = y;
	_gflush();
	xy.xcoord = SHORT4;
	xy.ycoord = SHORT6;
	return xy;
}

/*
_setlinestyle - _setlinestyle glue routine 
*/
void   __cdecl _setlinestyle(unsigned short m)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) + 1);
	*bp++ = op_setlinestyle;
	*SHORT0P = m;
	if(!_gbuff_flag)
		_gflush();
	return;
}

/*
_setlogorg - _setlogorg glue routine 
*/
struct _xycoord   __cdecl _setlogorg(short x, short y)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _xycoord xy;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_setlogorg;
	*SHORT0P = x;
	*SHORT2P = y;
	_gflush();
	xy.xcoord = SHORT4;
	xy.ycoord = SHORT6;
	return xy;
}

/*
_setpixel - _setpixel glue routine 
*/
short   __cdecl _setpixel(short x, short y)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 3 + 1);
	*bp++ = op_setpixel;
	*SHORT0P = x;
	*SHORT2P = y;
	_gflush();
	return SHORT4;
}

/*
_setpixel_w - _setpixel_w glue routine 
*/
short   __cdecl _setpixel_w(double x, double y)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) + sizeof(double) + 1);
	*bp++ = op_setpixel_w;
	*DOUBL0P = x;
	*DOUBL8P = y;
	_gflush();
	return SHORT16;
}

/*
_settextcolor - _settextcolor glue routine 
*/
short   __cdecl _settextcolor(short c)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_settextcolor;
	*SHORT0P = c;
	return SHORT2;
}

/*
_settextcursor - _settextcursor glue routine 
*/
short   __cdecl _settextcursor(short c)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_settextcursor;
	*SHORT0P = c;
	_gflush();
	return SHORT2;
}

/*
_settextposition - _settextposition glue routine 
*/
struct _rccoord   __cdecl _settextposition(short r, short c)
{
	register GBPTR bp;		/* Buffer pointer */
	struct _rccoord rc;		/* X-Y return value */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_settextposition;
	*SHORT0P = r;
	*SHORT2P = c;
	_gflush();
	rc.row = SHORT4;
	rc.col = SHORT6;
	return rc;
}

/*
_settextrows - _settextrows glue routine 
*/
short   __cdecl _settextrows(short c)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_settextrows;
	*SHORT0P = c;
	_gflush();
	return SHORT2;
}

/*
_settextwindow - _settextwindow glue routine 
*/
void   __cdecl _settextwindow(short r1, short c1, short r2, short c2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_settextwindow;
	*SHORT0P = r1;
	*SHORT2P = c1;
	*SHORT4P = r2;
	*SHORT6P = c2;
	if(!_gbuff_flag)
		_gflush();
	return;

}

/*
_setvideomode - _setvideomode glue routine
*/
short   __cdecl _setvideomode(short mode)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_setvideomode;
	*SHORT0P = mode;
	_gflush();
	return SHORT2;
}

/*
_setvideomoderows - _setvideomoderows glue routine 
*/
short   __cdecl _setvideomoderows(short mode, short rows)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_setvideomoderows;
	*SHORT0P = mode;
	*SHORT2P = rows;
	_gflush();
	return SHORT4;
}

/*
_setviewport - _setviewport glue routine 
*/
void   __cdecl _setviewport(short x1, short y1, short x2, short y2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 4 + 1);
	*bp++ = op_setviewport;
	*SHORT0P = x1;
	*SHORT2P = y1;
	*SHORT4P = x2;
	*SHORT6P = y2;
	if(!_gbuff_flag)
		_gflush();
	return;
}

/*
_setvisualpage - _setvisualpage glue routine 
*/
short   __cdecl _setvisualpage(short n)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_setvisualpage;
	*SHORT0P = n;
	_gflush();
	return SHORT2;
}

/*
_setwindow - _setwindow glue routine 
*/
short   __cdecl _setwindow(short c, double x1, double y1, double x2, double y2)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + sizeof(double) * 4 + 1);
	*bp++ = op_setwindow;
	*SHORT0P = c;
	*DOUBL2P = x1;
	*DOUBL10P = y1;
	*DOUBL18P = x2;
	*DOUBL26P = y2;
	_gflush();
	return SHORT34;
}

/*
_setwritemode - _setwritemode glue routine 
*/
short   __cdecl _setwritemode(short n)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_setwritemode;
	*SHORT0P = n;
	_gflush();
	return SHORT2;
}

/*
_unregisterfonts - _unregisterfonts glue routine 
*/
void  __cdecl _unregisterfonts(void)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(1);
	*bp++ = op_unregisterfonts;
	_gflush();
	return;
}

/*
_wrapon - _wrapon glue routine 
*/
short  __cdecl _wrapon(short n)
{
	register GBPTR bp;		/* Buffer pointer */

	bp = _galloc(sizeof(short) * 2 + 1);
	*bp++ = op_wrapon;
	*SHORT0P = n;
	_gflush();
	return SHORT2;
}
