/* $XConsortium: amigaInit.c,v 5.24 91/08/23 16:14:53 keith Exp $ */
/*-
 * amigaInit.c --
 *	Initialization functions for screen/keyboard/mouse, etc.
 *
 * Copyright (c) 1987 by the Regents of the University of California
 *
 * 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.  The University of California
 * makes no representations about the suitability of this
 * software for any purpose.  It is provided "as is" without
 * express or implied warranty.
 *
 *
 */

/************************************************************
Copyright 1994 by Eduardo Horvath
Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.

                    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 no-
tice  appear  in all copies and that both that copyright no-
tice and this permission notice appear in  supporting  docu-
mentation,  and  that the names of Sun or MIT not be used in
advertising or publicity pertaining to distribution  of  the
software  without specific prior written permission. Sun and
M.I.T. make no representations about the suitability of this
software for any purpose. It is provided "as is" without any
express or implied warranty.

SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
ABLE  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.

********************************************************/

#ifndef	lint
static char sccsid[] = "%W %G Copyright 1987 Sun Micro";
#endif

#include    "amiga.h"
#include    <servermd.h>
#include    "dixstruct.h"
#include    "dix.h"
#include    "opaque.h"
#include    "mipointer.h"

extern int amigaMouseProc();
extern int amigaKbdProc();
extern Bool amigaBW2Probe(), amigaBW2Create();
extern Bool amigaCProbe(), amigaCCreate();
extern void ProcessInputEvents();

extern void SetInputCheck();
extern char *strncpy();
extern GCPtr CreateScratchGC();

#define	XDEVICE	"XDEVICE"
#define	PARENT	"WINDOW_GFX"

static int autoRepeatHandlersInstalled;	/* FALSE each time InitOutput called */

static Bool amigaDevsProbed = FALSE;
unsigned long amigaGeneration = 0;
int amigaScreenIndex;
Bool FlipPixels = FALSE;

extern int displayDepth;

/*-
 *-----------------------------------------------------------------------
 * SigIOHandler --
 *	Signal handler for SIGIO - input is available.
 *
 * Results:
 *	amigaSigIO is set - ProcessInputEvents() will be called soon.
 *
 * Side Effects:
 *	None
 *
 *-----------------------------------------------------------------------
 */
/*ARGSUSED*/
static void
SigIOHandler(sig, code, scp)
    int		code;
    int		sig;
    struct sigcontext *scp;
{
    amigaEnqueueEvents ();
}

amigaFbDataRec amigaFbData[] = {
    amigaCProbe,  	"/dev/notused",	    amigaCCreate,
};

#define DEV_START   0
#define DEV_END	    0

/*
 * NUMSCREENS is the number of supported frame buffers (i.e. the number of
 * structures in amigaFbData which have an actual probeProc).
 */
#define NUMSCREENS (sizeof(amigaFbData)/sizeof(amigaFbData[0]))
#define NUMDEVICES  2

fbFd amigaFbs[NUMDEVICES];

/*-
 *-----------------------------------------------------------------------
 * amigaNonBlockConsoleOff --
 *	Turn non-blocking mode on the console off, so you don't get logged
 *	out when the server exits.
 *
 * Results:
 *	None.
 *
 * Side Effects:
 *	None.
 *
 *-----------------------------------------------------------------------
 */
/*ARGSUSED*/
amigaNonBlockConsoleOff(arg)
    char	*arg;
{
    register int i;

    i = fcntl(2, F_GETFL, 0);
    if (i >= 0)
	(void) fcntl(2, F_SETFL, i & ~FNDELAY);
}

/*-
 *-----------------------------------------------------------------------
 * InitOutput --
 *	Initialize screenInfo for all actually accessible framebuffers.
 *	The
 *
 * Results:
 *	screenInfo init proc field set
 *
 * Side Effects:
 *	None
 *
 *-----------------------------------------------------------------------
 */

void InitOutput(pScreenInfo, argc, argv)
    ScreenInfo 	  *pScreenInfo;
    int     	  argc;
    char    	  **argv;
{
    int     	  i, n, dev;
    int		  nonBlockConsole = 0;
    static int	  setup_on_exit = 0;
    int		  devStart = DEV_START;
    extern Bool	  RunFromSmartParent;

    if (!monitorResolution)
	monitorResolution = 90;
    if (RunFromSmartParent)
	nonBlockConsole = 1;
    for (i = 1; i < argc; i++) {
	if (!strcmp(argv[i],"-debug"))
	    nonBlockConsole = 0;
/*	else if (!strcmp(argv[i],"-mono"))
	    devStart = 0; */
    }
    /*
     *	Writes to /dev/console can block - causing an
     *	excess of error messages to hang the server in
     *	deadlock.  So.......
     */
    if (nonBlockConsole) {
	if (!setup_on_exit) {
	    if (atexit(amigaNonBlockConsoleOff))
		ErrorF("InitOutput: can't register NBIO exit handler\n");
	    setup_on_exit = 1;
	}
	i = fcntl(2, F_GETFL, 0);
	if (i >= 0)
	    i = fcntl(2, F_SETFL, i | FNDELAY);
	if (i < 0) {
	    perror("fcntl");
	    ErrorF("InitOutput: can't put stderr in non-block mode\n");
	}
    }
    pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
    pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
    pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
    pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;

    pScreenInfo->numPixmapFormats = 1;
    pScreenInfo->formats[0].depth = 1;
    pScreenInfo->formats[0].bitsPerPixel = 1;
    pScreenInfo->formats[0].scanlinePad = BITMAP_SCANLINE_PAD;

    if (displayDepth != 1)
    {
        pScreenInfo->numPixmapFormats++;
	pScreenInfo->formats [1].depth = displayDepth;
	pScreenInfo->formats [1].bitsPerPixel = displayDepth > 4 ? 8 : 4;
	pScreenInfo->formats [1].scanlinePad = BITMAP_SCANLINE_PAD;
    }

    autoRepeatHandlersInstalled = FALSE;

    if (!amigaDevsProbed)
    {
	n = 0;
	for (i = NUMSCREENS, dev = devStart; --i >= DEV_END; dev++) {
	    if ((*amigaFbData[dev].probeProc)(pScreenInfo, n, dev, argc, argv))
		n++;
	    else
		amigaFbData[dev].createProc = NULL;
	}
	amigaDevsProbed = TRUE;
	if (n == 0)
	    return;
    }

    for (i = NUMSCREENS, dev = devStart; --i >= DEV_END; dev++) {
	if (amigaFbData[dev].createProc)
	    (*amigaFbData[dev].createProc)(pScreenInfo, argc, argv);
    }
    amigaInitCursor();
    signal(SIGWINCH, SIG_IGN);
}

/*-
 *-----------------------------------------------------------------------
 * InitInput --
 *	Initialize all supported input devices...what else is there
 *	besides pointer and keyboard?
 *
 * Results:
 *	None.
 *
 * Side Effects:
 *	Two DeviceRec's are allocated and registered as the system pointer
 *	and keyboard devices.
 *
 *-----------------------------------------------------------------------
 */
/*ARGSUSED*/
void InitInput(argc, argv)
    int     	  argc;
    char    	  **argv;
{
    DevicePtr p, k;
    static int  zero = 0;
    
    p = AddInputDevice(amigaMouseProc, TRUE);
    k = AddInputDevice(amigaKbdProc, TRUE);
    if (!p || !k)
	FatalError("failed to create input devices in InitInput");

    SetTimeSinceLastInputEvent();
    RegisterPointerDevice(p);
    RegisterKeyboardDevice(k);
    miRegisterPointerDevice(screenInfo.screens[0], p);
    if (!mieqInit (k, p))
	return;
    signal(SIGIO, SigIOHandler);
}


static Bool
amigaCloseScreen (i, pScreen)
    int		i;
    ScreenPtr	pScreen;
{
    SetupScreen(pScreen);
    Bool    ret;

    signal (SIGIO, SIG_IGN);
    amigaDisableCursor (pScreen);
    pScreen->CloseScreen = pPrivate->CloseScreen;
    ret = (*pScreen->CloseScreen) (i, pScreen);
    (void) (*pScreen->SaveScreen) (pScreen, SCREEN_SAVER_OFF);
    xfree ((pointer) pPrivate);
    return ret;
}

Bool
amigaSaveScreen (pScreen, on)
    ScreenPtr	pScreen;
    int		on;
{
    SetupScreen(pScreen);
    int		state;

    if (on == SCREEN_SAVER_FORCER)
	SetTimeSinceLastInputEvent();
    else
    {
	if (pPrivate->SaveScreen)
	    (*pPrivate->SaveScreen)(pScreen, on);
	else {
#if 0
	    if (on == SCREEN_SAVER_ON)
		(void) ioctl(amigaFbs[pScreen->myNum].fd, VIOCDISPLAY, 0);
	    else
		(void) ioctl(amigaFbs[pScreen->myNum].fd, VIOCREMOVE, 0);
#endif
	}
    }
    return( TRUE );
}

/*-
 *-----------------------------------------------------------------------
 * amigaScreenInit --
 *	Things which must be done for all types of frame buffers...
 *	Should be called last of all.
 *
 * Results:
 *	TRUE if successful, else FALSE
 *
 * Side Effects:
 *	Both a BlockHandler and a WakeupHandler are installed for the
 *	first screen.  Together, these handlers implement autorepeat
 *	keystrokes on the Sun.
 *
 *-----------------------------------------------------------------------
 */

Bool
amigaScreenAllocate (pScreen)
    ScreenPtr	pScreen;
{
    amigaScreenPtr    pPrivate;

    if (amigaGeneration != serverGeneration)
    {
	amigaScreenIndex = AllocateScreenPrivateIndex();
	if (amigaScreenIndex < 0)
	    return FALSE;
	amigaGeneration = serverGeneration;
    }
    pPrivate = (amigaScreenPtr) xalloc (sizeof (amigaScreenRec));
    if (!pPrivate)
	return FALSE;
    bzero(pPrivate, sizeof(amigaScreenRec));

    pScreen->devPrivates[amigaScreenIndex].ptr = (pointer) pPrivate;
    return TRUE;
}

Bool
amigaScreenInit (pScreen)
    ScreenPtr	pScreen;
{
    SetupScreen(pScreen);
    extern void   amigaBlockHandler();
    extern void   amigaWakeupHandler();
    static ScreenPtr autoRepeatScreen;
    extern miPointerScreenFuncRec   amigaPointerScreenFuncs;

    pPrivate->installedMap = 0;
    pPrivate->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = amigaCloseScreen;
    pScreen->SaveScreen = amigaSaveScreen;

    /*
     *	Block/Unblock handlers
     */
    if (autoRepeatHandlersInstalled == FALSE) {
	autoRepeatScreen = pScreen;
	autoRepeatHandlersInstalled = TRUE;
    }

    if (pScreen == autoRepeatScreen) {
        pScreen->BlockHandler = amigaBlockHandler;
        pScreen->WakeupHandler = amigaWakeupHandler;
    }
    if (!amigaCursorInitialize (pScreen))
	miDCInitialize (pScreen, &amigaPointerScreenFuncs);

    amigaInitCursor ();

    return TRUE;
}
