/***********************************************************
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and 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, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/
/* $XConsortium: scrinit.c,v 1.57 88/10/02 15:08:27 rws Exp $ */

#include "X.h"
#include "Xproto.h"	/* for xColorItem */
#include "Xmd.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "resource.h"
#include "colormap.h"
#include "cursor.h"
#include "..\common\ibmmouse.h"
#include "../../mi/mistruct.h"
#include "dix.h"
#include <dos.h>
#include <string.h>
#include "../../mi/mipointer.h"
#include "validate.h"
#include "ega.h"

#include "servermd.h"
#include "funcs.h"
#include "egafuncs.h"
#include "mxfuncs.h"

extern int monitorResolution;
int egaGeneration;
int egaGCPrivateIndex;
/* int egaScrPrivateIndex; */

static int egaIsOpen = 0;

static VisualRec visual = {
/* vid  class       bpRGB cmpE nplan rMask gMask bMask oRed oGreen oBlue */
   0,   StaticGray, 1,    2,   1,    0,    0,    0,    0,   0,     0
};

static VisualID VID;

static DepthRec depth = {
/* depth	numVid		vids */
    1,		1,		&VID
};

#ifdef BACKING_STORE
miBSFuncRec egaBSfuncs = {
	mxSaveAreas,
	mxRestoreAreas,
	mxSetClipmaskRgn,
	mxGetImagePixmap,
	mxGetSpansPixmap,
};
#endif

#ifdef ERGO
const __segment	vga_base;
#endif
int vga_width;
u_char	vga_curpage;
u_char	vga_page_shift;
char	vga_hires;

Bool
egainit(iScreen, pScreen, argc, argv)
int iScreen;
ScreenPtr pScreen;
int argc;
char **argv;
{
    ColormapPtr pColormap;
    union REGS regs;
    int		mode = 1;
    int		i;

    iScreen = iScreen;

    while (argc > 0) {
	if (strcmp(*argv, "-mode") == 0) {
		argv++; argc--;
		if (!argc) {
			printf("bad -mode argument\n");
			break;
		}
		mode = atoi(*argv);
		if (mode <= 0) {
		    fprintf(stderr, "%s: invalid mode.\n", *argv);
		    return FALSE;
		}
	}
	argv++; argc--;
    }

    if (egaGeneration != serverGeneration)
    {
	egaGCPrivateIndex = AllocateGCPrivateIndex();
/*	egaScrPrivateIndex = AllocateScreenPrivateIndex(); */
	visual.vid = FakeClientID(0);
	VID = visual.vid;
	egaGeneration = serverGeneration;
    }
    if (!AllocateGCPrivate(pScreen, egaGCPrivateIndex, sizeof(egaPrivGC)))
	return FALSE;

    if (VGAOpen(mode)) {
	return FALSE;
    }
    vga_curpage = 0;
    SetPage();
    egaIsOpen++;

#ifdef ERGO
    /* Get a 64k window to screen memory */
    *(__segment *)&vga_base = get_real_window(0xa0000, 0x10000);
    if (&vga_base == 0) {
	printf("Can't get window, error %d\n", errno);
	(void)mxClose(0, 0);
	return FALSE;
    }
#endif
    if (!scr_height)
	scr_height = (bios[0x484] + 1) * *(u_short *)(&bios[0x485]);
    pScreen->height = scr_height;

    /* get crt size in pixels */
    regs.h.ah = 0xf;
    int386(0x10, &regs, &regs);

    if (!vga_width)
	vga_width = regs.h.ah;
    if (!scr_width)
	scr_width = (int)regs.h.ah * 8;
    pScreen->width = scr_width;
    vga_hires = mode >= 3;
    vga_hires += mode >= 4;
/*
printf("ega: mode=%d, columns=%d, height=%d\n", regs.h.al, regs.h.ah, pScreen->height);
*/

    if (monitorResolution) {
	pScreen->mmWidth = pScreen->width * 25 / monitorResolution;
	pScreen->mmHeight = pScreen->height * 25 / monitorResolution;
    } else {
	pScreen->mmWidth = 250;
	pScreen->mmHeight = 180;
    }

    pScreen->numDepths = 1;
    pScreen->allowedDepths = &depth;

    pScreen->rootDepth = 1;
    pScreen->rootVisual = VID;
    pScreen->defColormap = (Colormap) FakeClientID(0);
    pScreen->minInstalledCmaps = 1;
    pScreen->maxInstalledCmaps = 1;
    pScreen->whitePixel = 1;
    pScreen->blackPixel = 0;
#ifdef BACKING_STORE
    pScreen->backingStoreSupport = WhenMapped;
#else
    pScreen->backingStoreSupport = NotUseful;
#endif
    pScreen->saveUnderSupport = NotUseful;

    pScreen->numVisuals = 1;
    pScreen->visuals = &visual;

    pScreen->CreateWindow = mxCreateWindow;
    pScreen->DestroyWindow = mxDestroyWindow;
    pScreen->PositionWindow = mxPositionWindow;
    pScreen->RealizeWindow = mxMapWindow;
    pScreen->UnrealizeWindow = mxUnmapWindow;
    pScreen->ChangeWindowAttributes = mxChangeWindowAttributes;
    pScreen->ValidateTree = miValidateTree;
    pScreen->WindowExposures = miWindowExposures;

    pScreen->ClearToBackground = miClearToBackground;
    pScreen->PaintWindowBackground = mxPaintWindow;
    pScreen->PaintWindowBorder = mxPaintWindow;
    pScreen->CopyWindow = mxCopyWindow;

    pScreen->RealizeFont = mxRealizeFont;
    pScreen->UnrealizeFont = mxUnrealizeFont;
    pScreen->GetImage = mxGetImage;
    pScreen->GetSpans = mxGetSpans;
    pScreen->CreatePixmap = mxCreatePixmap;
    pScreen->DestroyPixmap = mxDestroyPixmap;

    pScreen->CreateColormap = mxCreateColormap;
    pScreen->DestroyColormap = mxDestroyColormap;
    pScreen->InstallColormap = mxInstallColormap;
    pScreen->UninstallColormap = mxUninstallColormap;
    pScreen->ListInstalledColormaps = mxListInstalledColormaps;
    pScreen->StoreColors = NoopDDA;
    pScreen->ResolveColor = mxResolveColor;

    pScreen->CreateGC = mxCreateGC;

    pScreen->RegionCreate = miRegionCreate;
    pScreen->RegionInit = miRegionInit;
    pScreen->RegionCopy = miRegionCopy;
    pScreen->RegionDestroy = miRegionDestroy;
    pScreen->RegionUninit = miRegionUninit;
    pScreen->Intersect = miIntersect;
    pScreen->Inverse = miInverse;
    pScreen->Union = miUnion;
    pScreen->Subtract = miSubtract;
    pScreen->RegionReset = miRegionReset;
    pScreen->TranslateRegion = miTranslateRegion;
    pScreen->RectIn = miRectIn;
    pScreen->PointInRegion = miPointInRegion;
    pScreen->RegionNotEmpty = miRegionNotEmpty;
    pScreen->RegionEmpty = miRegionEmpty;
    pScreen->RegionExtents = miRegionExtents;
    pScreen->RegionAppend = miRegionAppend;
    pScreen->RegionValidate = miRegionValidate;
    pScreen->BitmapToRegion = mfbPixmapToRegion;
    pScreen->RectsToRegion = miRectsToRegion;
    pScreen->SendGraphicsExpose = miSendGraphicsExpose;

    pScreen->CloseScreen = mxClose;
    pScreen->SaveScreen = mxSaveScreen;

    /*
     * Cursor functions
     */
    pScreen->PointerNonInterestBox = mousePointerNonInterestBox;
    pScreen->RealizeCursor = mouseRealizeCursor;
    pScreen->UnrealizeCursor = mouseUnrealizeCursor;
    pScreen->DisplayCursor = mouseDisplayCursor;
    pScreen->SetCursorPosition = mouseSetCursorPosition;
    pScreen->CursorLimits = mouseCursorLimits;
    pScreen->ConstrainCursor = mouseConstrainCursor;
    pScreen->RecolorCursor = mxRecolorCursor;

    pScreen->QueryBestSize = mxQueryBestSize;

#ifdef BACKING_STORE
    miInitializeBackingStore (pScreen, &egaBSfuncs);
#endif

    /* os layer stuff */
#ifdef notused
    pScreen->BlockHandler = mxBlockHandler;
    pScreen->WakeupHandler = mxWakeupHandler;
    pScreen->wakeupData = (pointer)0;
    pScreen->blockData = (pointer)0;
#endif
    if ((i = CreateColormap(pScreen->defColormap, pScreen, &visual,
	&pColormap, AllocNone, 0)) != Success ||
	    pColormap == NULL) {
		ErrorF("egainit: CreateColormap returned %d\n", i);
		return FALSE;
    }
    mxInstallColormap(pColormap);

    return TRUE;
}

/* Should this be a 8-bit array? */
int endtab[16] = 
	{
	0x0000,
	0x8000,
	0xC000,
	0xE000,
	0xF000,
	0xF800,
	0xFC00,
	0xFE00,
	0xFF00,
	0xFF80,
	0xFFC0,
	0xFFE0,
	0xFFF0,
	0xFFF8,
	0xFFFC,
	0xFFFE
	};

void
screen_abort()
{
	if (egaIsOpen)
		mxClose(0, (ScreenPtr)0);
}

/* The cursor is black and white.  Therefore we don't need to do much
 * work here.
 */
void
mxRecolorCursor( pScr, pCurs, displayed)
    ScreenPtr	pScr;
    CursorPtr	pCurs;
    Bool	displayed;
{
    pScr = pScr;
    pCurs = pCurs;
    displayed = displayed;
}

Bool
mxClose(index, pScreen)
int index;
ScreenPtr pScreen;
{

    index = index;

    if (egaIsOpen) {
	VGAClose();
	egaIsOpen = 0;
    }
#ifdef notdef
    if (((struct overlay *)&vga_base)->seg) {
printf("delete segment\n");
	i = delete_segment(((struct overlay *)&vga_base)->seg);
	if (i) {
		printf("error code %d\n", i);
	}
	((struct overlay *)&vga_base)->seg = 0;
    }
#endif
    if (pScreen == 0)
	return FALSE;
    pScreen->devPrivate = 0;
    return TRUE;
}
