/* gserver.c - Graphics server code */

/************************************************************************/
/*	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	*/
/************************************************************************/

/*
 * This is real mode code which must be compiled in large model.  We
 * have to be compiled in large model so that all pointers are FAR
 * pointers.  We need to use FAR pointers throughout because when the
 * protected mode program calls us to execute graphics commands, the
 * buffer it passes commands in is a FAR buffer.
 */

#include <stdio.h>
#include <stdlib.h>

#include "graph.h"		/* from MSC 7.0 include directory */
#include "gserver.h"


/*

main - Main routine for the real mode graphics server

*/

main()

{
	/* Print out a message on the screen telling that we were loaded
	   okay */

	flushall();
	printf("Real mode graphics server has initialized.\n");
	flushall();

	/* Return to protected mode */

	protret();
}


/*

gserver - Graphics server
	This is the routine that gets called from protected mode
	whenever there are graphics commands to be executed.  We execute
	all the commands in the buffer and then return.

	Use __cdecl to force stack-based calling conventions, because this
	routine is called from an ASM routine that passes the argument
	on the stack.
*/

void __cdecl gserver(bp)

char *bp;		/* Pointer to the graphics commands buffer
			   passed in by the protected mode code */

{

	char *ebp;		/* End of buffer pointer */
	unsigned int len;	/* Length of the current command */
	struct _wxycoord wxy;	/* wxy co-ordinates */
	struct xycoord xy;	/* X-Y co-ordinates */
	struct rccoord rc;	/* Row-column co-ordinates */
	struct videoconfig vc;	/* Video configuration */

	/* The first short in the graphics commands buffer gives the number
	   of bytes used for graphics commands in the buffer.  From this
	   count, calculate "ebp" which point to the first byte after the
	   last command in the buffer. */

	ebp = bp + SHORT0;
	bp += sizeof(short);

	/* Loop through the buffer and execute each graphics command. */

	while(bp < ebp)
	{

		/* Decode the current graphics command */

		switch(*bp++)
		{

			/* Command executors */

			case op_arc:
				*SHORT16P = _arc(SHORT0, SHORT2, SHORT4,
				            SHORT6, SHORT8, SHORT10, SHORT12,
				            SHORT14);
				len = sizeof(short) * 9;
				break;

			case op_arc_w:
				*SHORT16P = _arc_w(DOUBL0, DOUBL8, DOUBL16,
				            DOUBL24, DOUBL32, DOUBL40,
				            DOUBL48, DOUBL56);
				len = sizeof(double) * 8 + sizeof(short);
				break;

			case op_arc_wxy:
				*SHORT64P = _arc_wxy((struct _wxycoord *)DOUBL0P
						, (struct _wxycoord *)DOUBL16P,
				           	(struct _wxycoord *)DOUBL32P,
						(struct _wxycoord *)DOUBL48P);
				len = sizeof(struct _wxycoord) * 4 
					+ sizeof(short);
				break;

			case op_clearscreen:
				_clearscreen(SHORT0);
				len = sizeof(short);
				break;

			case op_displaycursor:
				*SHORT2P = _displaycursor(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_ellipse:
				*SHORT10P = _ellipse(SHORT0, SHORT2, SHORT4,
				            SHORT6, SHORT8);
				len = sizeof(short) * 6;
				break;

			case op_ellipse_w:
				*SHORT34P = _ellipse_w(SHORT0, DOUBL2, DOUBL10,
				            DOUBL18, DOUBL26);
				len = sizeof(double) * 4 + sizeof(short) * 2;
				break;

			case op_ellipse_wxy:
				*SHORT34P = _ellipse_wxy(SHORT0,
						(struct _wxycoord *)DOUBL2P, 
						(struct _wxycoord *)DOUBL18P);
				len = sizeof(struct _wxycoord) * 2
					 + sizeof(short) * 2;
				break;

			case op_floodfill:
				*SHORT6P = _floodfill(SHORT0, SHORT2, SHORT4);
				len = sizeof(short) * 4;
				break;

			case op_floodfill_w:
				*SHORT18P = _floodfill_w(DOUBL0, DOUBL8,
					    SHORT16);
				len = sizeof(double) * 2 + sizeof(short);
				break;

			case op_getactivepage:
				*SHORT0P = _getactivepage();
				len = sizeof(short);
				break;

			case op_getarcinfo:
				*SHORT12P = _getarcinfo(
					   (struct xycoord *)SHORT0P,
					   (struct xycoord *)SHORT4P,
				           (struct xycoord *) SHORT8P);
				len = sizeof(struct xycoord) * 3 + sizeof(short);
				break;

			case op_getbkcolor:
				*LONG0P = _getbkcolor();
				len = sizeof(long);
				break;

			case op_getcolor:
				*SHORT0P = _getcolor();
				len = sizeof(short);
				break;

			case op_getcurrentposition:
				xy = _getcurrentposition();
				*SHORT0P = xy.xcoord;
				*SHORT2P = xy.ycoord;
				len = sizeof(short) * 2;
				break;

			case op_getcurrentposition_w:
				wxy = _getcurrentposition_w();
				*DOUBL0P = wxy.wx;
				*DOUBL8P = wxy.wy;
				len = sizeof(struct _wxycoord);
				break;

			case op_getfillmask:
				*SHORT8P = _getfillmask(bp) != NULL;
				len = sizeof(short) + 8;
				break;

			case op_getfontinfo:
				*SHORT8P = _getfontinfo((struct _fontinfo *)bp);
				len = sizeof(short) + 8;
				break;

			case op_getgtextextent:
				len = strlen(bp);
				*(short *)(bp + len + 1) = _getgtextextent(bp);
				len += 3;
				break;

			case op_getgtextvector:
				xy = _getgtextvector();
				*SHORT0P = xy.xcoord;
				*SHORT2P = xy.ycoord;
				len = sizeof(short) * 2;
				break;

			case op_getlinestyle:
				*SHORT0P = _getlinestyle();
				len = sizeof(short);
				break;

			case op_getphyscoord:
				xy = _getphyscoord(SHORT0, SHORT2);
				*SHORT4P = xy.xcoord;
				*SHORT6P = xy.ycoord;
				len = sizeof(short) * 4;
				break;

			case op_getpixel:
				*SHORT4P = _getpixel(SHORT0, SHORT2);
				len = sizeof(short) * 3;
				break;

			case op_getpixel_w:
				*SHORT16P = _getpixel_w(DOUBL0, DOUBL8);
				len = sizeof(double) * 2 + sizeof(short);
				break;

			case op_gettextcolor:
				*SHORT0P = _gettextcolor();
				len = sizeof(short);
				break;

			case op_gettextcursor:
				*SHORT0P = _gettextcursor();
				len = sizeof(short);
				break;

			case op_gettextposition:
				rc = _gettextposition();
				*SHORT0P = rc.row;
				*SHORT2P = rc.col;
				len = sizeof(short) * 2;
				break;

			case op_gettextwindow:
				_gettextwindow(SHORT0P, SHORT2P, 
						SHORT4P, SHORT6P);
				len = sizeof(short) * 4;
				break;

			case op_getvideoconfig:
				_getvideoconfig(&vc);
				*SHORT0P = vc.numxpixels;
				*SHORT2P = vc.numypixels;
				*SHORT4P = vc.numtextcols;
				*SHORT6P = vc.numtextrows;
				*SHORT8P = vc.numcolors;
				*SHORT10P = vc.bitsperpixel;
				*SHORT12P = vc.numvideopages;
				*SHORT14P = vc.mode;
				*SHORT16P = vc.adapter;
				*SHORT18P = vc.monitor;
				*SHORT20P = vc.memory;
				len = sizeof(short) * 11;
				break;

			case op_getviewcoord:
				xy = _getviewcoord(SHORT0, SHORT2);
				*SHORT4P = xy.xcoord;
				*SHORT6P = xy.ycoord;
				len = sizeof(short) * 4;
				break;

			case op_getviewcoord_w:
				xy = _getviewcoord_w(DOUBL0, DOUBL8);
				*SHORT16P = xy.xcoord;
				*SHORT18P = xy.ycoord;
				len = sizeof(short) * 2 + sizeof(double) * 2;
				break;

			case op_getviewcoord_wxy:
				xy = _getviewcoord_wxy((struct _wxycoord *)DOUBL0P);
				*SHORT16P = xy.xcoord;
				*SHORT18P = xy.ycoord;
				len = sizeof(short) * 2 + sizeof(double) * 2;
				break;

			case op_getvisualpage:
				*SHORT0P = _getvisualpage();
				len = sizeof(short);
				break;

			case op_getwindowcoord:
				wxy = _getwindowcoord(SHORT0, SHORT2);
				*DOUBL4P = wxy.wx;
				*DOUBL12P = wxy.wy;
				len = sizeof(short) * 2 + sizeof(double) * 2;
				break;

			case op_getwritemode:
				*SHORT0P = _getwritemode();
				len = sizeof(short);
				break;

			case op_grstatus:
				*SHORT0P = _grstatus();
				len = sizeof(short);
				break;

			case op_imagesize:
				*LONG8P = _imagesize(SHORT0, SHORT2, SHORT4,
				          SHORT6);
				len = sizeof(short) * 4 + sizeof(long);
				break;

			case op_imagesize_w:
				*LONG32P = _imagesize_w(DOUBL0, DOUBL8, DOUBL16,
				          DOUBL24);
				len = sizeof(double) * 4 + sizeof(long);
				break;

			case op_imagesize_wxy:
				*LONG32P = _imagesize_wxy(
						(struct _wxycoord *) DOUBL0P,
						(struct _wxycoord *) DOUBL16P);
				len = sizeof(struct _wxycoord) * 2
					 + sizeof(long);
				break;

/*
			case op_inchar:
				*SHORT0P = _inchar();
				len = sizeof(short);
				break;
*/

			case op_lineto:
				*SHORT4P = _lineto(SHORT0, SHORT2);
				len = sizeof(short) * 3;
				break;

			case op_lineto_w:
				*SHORT16P = _lineto_w(DOUBL0, DOUBL8);
				len = sizeof(double) * 2 + sizeof(short);
				break;

			case op_moveto:
				xy = _moveto(SHORT0, SHORT2);
				*SHORT4P = xy.xcoord;
				*SHORT6P = xy.ycoord;
				len = sizeof(short) * 4;
				break;

			case op_moveto_w:
				wxy = _moveto_w(DOUBL0, DOUBL8);
				*DOUBL16P = wxy.wx;
				*DOUBL24P = wxy.wy;
				len = sizeof(double) * 4;
				break;

			case op_outgtext:
				_outgtext(bp);
				len = strlen(bp) + 1;
				break;

			case op_outmem:
				_outmem((const char *)bp, (short)bp + strlen(bp));
				len = strlen(bp) + 1 + sizeof(short);
				break;

			case op_outtext:
				_outtext(bp);
				len = strlen(bp) + 1;
				break;

			case op_pie:
				*SHORT18P = _pie(SHORT0, SHORT2, SHORT4,
				            SHORT6, SHORT8, SHORT10, SHORT12,
				            SHORT14, SHORT16);
				len = sizeof(short) * 10;
				break;

			case op_pie_w:
				*SHORT66P = _pie_w(SHORT0, DOUBL2, DOUBL10,
				            DOUBL18, DOUBL26, DOUBL34, DOUBL42,
				            DOUBL50, DOUBL58);
				len = sizeof(short) * 2 + sizeof(double) * 8;
				break;

			case op_pie_wxy:
				*SHORT66P = _pie_wxy(SHORT0,
					   (struct _wxycoord *) DOUBL2P, 
					   (struct _wxycoord *) DOUBL18P,
				           (struct _wxycoord *) DOUBL34P, 
					   (struct _wxycoord *) DOUBL50P);
				len = sizeof(short) * 2 + 
					sizeof(struct _wxycoord) * 4;
				break;

			case op_rectangle:
				*SHORT10P = _rectangle(SHORT0, SHORT2, SHORT4,
				            SHORT6, SHORT8);
				len = sizeof(short) * 6;
				break;

			case op_rectangle_w:
				*SHORT34P = _rectangle_w(SHORT0, DOUBL2, 
						DOUBL10, DOUBL18, DOUBL26);
				len = sizeof(short) + sizeof(double) * 4;
				break;

			case op_rectangle_wxy:
				*SHORT34P = _rectangle_wxy(SHORT0, 
						(struct _wxycoord *) DOUBL2P, 
						(struct _wxycoord *) DOUBL18P);
				len = sizeof(short) + 
					sizeof(struct _wxycoord) * 2;
				break;

			case op_registerfonts:
				len = strlen(bp);
				*(short *)(bp + len + 1) = _registerfonts(bp);
				len += 3;
				break;

			case op_remapallpalette:
				*SHORT4P = _remapallpalette(LONG6P);
				len = *LONG0P + sizeof(long) + sizeof(short);
				break;

			case op_remappalette:
				*LONG6P = _remappalette(SHORT0, LONG2);
				len = sizeof(short) + sizeof(long) * 2;
				break;

			case op_scrolltextwindow:
				_scrolltextwindow(SHORT0);
				len = sizeof(short);
				break;

			case op_selectpalette:
				*SHORT2P = _selectpalette(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_setactivepage:
				*SHORT2P = _setactivepage(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_setbkcolor:
				*LONG4P = _setbkcolor(LONG0);
				len = sizeof(long) * 2;
				break;

			case op_setcliprgn:
				_setcliprgn(SHORT0, SHORT2, SHORT4, SHORT6);
				len = sizeof(short) * 4;
				break;

			case op_setcolor:
				*SHORT2P = _setcolor(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_setfillmask:
				_setfillmask(bp);
				len = 8;
				break;

			case op_setfont:
				len = strlen(bp);
				*(short *)(bp + len + 1) = _setfont(bp);
				len += 3;
				break;

			case op_setgtextvector:
				xy = _setgtextvector(SHORT0, SHORT2);
				*SHORT4P = xy.xcoord;
				*SHORT6P = xy.ycoord;
				len = sizeof(short) * 4;
				break;

			case op_setnullmask:
				_setfillmask(NULL);
				len = 0;
				break;

			case op_setlinestyle:
				_setlinestyle(SHORT0);
				len = sizeof(short);
				break;

			case op_setlogorg:
				xy = _setlogorg(SHORT0, SHORT2);
				*SHORT4P = xy.xcoord;
				*SHORT6P = xy.ycoord;
				len = sizeof(short) * 4;
				break;

			case op_setpixel:
				*SHORT4P = _setpixel(SHORT0, SHORT2);
				len = sizeof(short) * 3;
				break;

			case op_setpixel_w:
				*SHORT16P = _setpixel_w(DOUBL0, DOUBL8);
				len = sizeof(short) + sizeof(double) * 2;
				break;

			case op_settextcolor:
				*SHORT2P = _settextcolor(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_settextcursor:
				*SHORT2P = _settextcursor(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_settextposition:
				rc = _settextposition(SHORT0, SHORT2);
				*SHORT4P = rc.row;
				*SHORT6P = rc.col;
				len = sizeof(short) * 4;
				break;

			case op_settextrows:
				*SHORT2P = _settextrows(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_settextwindow:
				_settextwindow(SHORT0, SHORT2, SHORT4, SHORT6);
				len = sizeof(short) * 4;
				break;

			case op_setvideomode:
				*SHORT2P = _setvideomode(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_setvideomoderows:
				*SHORT4P = _setvideomoderows(SHORT0, SHORT2);
				len = sizeof(short) * 2;
				break;

			case op_setviewport:
				_setviewport(SHORT0, SHORT2, SHORT4, SHORT6);
				len = sizeof(short) * 4;
				break;

			case op_setvisualpage:
				*SHORT2P = _setvisualpage(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_setwindow:
				*SHORT34P = _setwindow(SHORT0, DOUBL2, 
						DOUBL10, DOUBL18, DOUBL26);
				len = sizeof(short) + sizeof(double) * 4;
				break;

			case op_setwritemode:
				*SHORT2P = _setwritemode(SHORT0);
				len = sizeof(short) * 2;
				break;

			case op_unregisterfonts:
				_unregisterfonts();
				len = 0;
				break;

			case op_wrapon:
				*SHORT2P = _wrapon(SHORT0);
				len = sizeof(short) * 2;
				break;

			default:
				printf("Bad graphics command: %d\n",
					*(bp-1));
				return;

		}

		/* Increment the buffer pointer to the next command. */

		bp += len;

	}

	/* Return back to the protected mode caller. */

	return;

}
