#include <stdio.h>
#include <malloc.h>
#include <dos.h>
#include "Xos.h"
#include "misc.h"
#include "X.h"
#include "input.h"
#include "opaque.h"
#include <signal.h>
#include "msdos.h"
#include <stdarg.h>

#define XDMCP

typedef unsigned long u_long;

extern char *display;

extern u_long near defaultScreenSaverTime;	/* for parsing command line */
extern u_long near defaultScreenSaverInterval;
extern int near defaultScreenSaverBlanking;
extern int near defaultBackingStore;
extern Bool near disableBackingStore;
extern Bool near disableSaveUnders;
extern int near defaultColorVisualClass;
extern u_long near ScreenSaverTime;		/* for forcing reset */
extern Bool near permitOldBugs;
extern int near monitorResolution;
int near debug = 0;

void ddxUseMsg();

Bool _near Must_have_memory = FALSE;

/* Force connections to close on SIGHUP from init */

AutoResetServer ()
{
    dispatchException |= DE_RESET;
    isItTimeToYield = TRUE;
}

/* Force connections to close and then exit on SIGTERM, SIGINT */

void
GiveUp()
{
    dispatchException |= DE_TERMINATE;
    isItTimeToYield = TRUE;
}

void
Error(str)
    char *str;
{
    perror(str);
}

u_long
GetTimeInMillis()
{
    u_long value;

    _disable();
    value = clock();
    _enable();
    return value;
}

void UseMsg()
{
    ErrorF("use: X [:<display>] [option]\n");
    ErrorF("-a #                   mouse acceleration (pixels)\n");
#ifdef notdef
    ErrorF("-auth string           select authorization file\n");	
#endif
    ErrorF("bc                     enable bug compatibility\n");
#ifdef notdef
    ErrorF("-bs                    disable any backing store support\n");
#endif
    ErrorF("-c                     turns off key-click\n");
    ErrorF("c #                    key-click volume (0-100)\n");
#ifdef notdef
    ErrorF("-cc int                default color visual class\n");
#endif
    ErrorF("-co string             color database file\n");
    ErrorF("-dpi int               screen resolution in dots per inch\n");
    ErrorF("-f #                   bell base (0-100)\n");
    ErrorF("-fc string             cursor font\n");
    ErrorF("-fn string             default font name\n");
    ErrorF("-fp string             default font path\n");
    ErrorF("-help                  prints message with these options\n");
    ErrorF("-I                     ignore all remaining arguments\n");
#ifdef notdef
    ErrorF("-logo                  enable logo in screen saver\n");
    ErrorF("nologo                 disable logo in screen saver\n");
    ErrorF("-p #                   screen-saver pattern duration (seconds)\n");
#endif
    ErrorF("-r                     turns off auto-repeat\n");
    ErrorF("r                      turns on auto-repeat \n");
    ErrorF("-s #                   screen-saver timeout (seconds)\n");
#ifdef notdef
    ErrorF("-su                    disable any save under support\n");
#endif
    ErrorF("-t #                   mouse threshold (pixels)\n");
    ErrorF("-to #                  connection time out\n");
    ErrorF("v                      video blanking for screen-saver\n");
    ErrorF("-v                     screen-saver without video blanking\n");
#ifdef notdef
    ErrorF("-wm                    WhenMapped default backing-store\n");
    ErrorF("-x string              loads named extension at init time \n");
#endif
    ErrorF("-debug		   turn on debugging\n");
#ifdef XDMCP
    XdmcpUseMsg();
#endif
    ddxUseMsg();
}

/*
 * This function parses the command line. Handles device-independent fields
 * and allows ddx to handle additional fields.  It is not allowed to modify
 * argc or any of the strings pointed to by argv.
 */
void
ProcessCommandLine ( argc, argv )
int	argc;
char	*argv[];

{
    int i, skip;

    defaultKeyboardControl.autoRepeat = TRUE;

    for ( i = 1; i < argc; i++ )
    {
	/* call ddx first, so it can peek/override if it wants */
        if(skip = ddxProcessArgument(argc, argv, i))
	{
	    i += (skip - 1);
	}
	else if(argv[i][0] ==  ':')  
	{
	    /* initialize display */
	    display = argv[i];
	    display++;
	}
	else if ( strcmp( argv[i], "-a") == 0)
	{
	    if(++i < argc)
	        defaultPointerControl.num = atoi(argv[i]);
	    else
		UseMsg();
	}
#ifdef later
	else if ( strcmp( argv[i], "-auth") == 0)
	{
	    if(++i < argc)
	        InitAuthorization (argv[i]);
	    else
		UseMsg();
	}
#endif
	else if ( strcmp( argv[i], "bc") == 0)
	    permitOldBugs = TRUE;
#ifdef notdef
	else if ( strcmp( argv[i], "-bs") == 0)
	    disableBackingStore = TRUE;
#endif
	else if ( strcmp( argv[i], "c") == 0)
	{
	    if(++i < argc)
	        defaultKeyboardControl.click = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-c") == 0)
	{
	    defaultKeyboardControl.click = 0;
	}
#ifdef notdef
	else if ( strcmp( argv[i], "-cc") == 0)
	{
	    if(++i < argc)
	        defaultColorVisualClass = atoi(argv[i]);
	    else
		UseMsg();
	}
#endif
	else if ( strcmp( argv[i], "-co") == 0)
	{
	    if(++i < argc)
	        rgbPath = argv[i];
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-dpi") == 0)
	{
	    if(++i < argc)
	        monitorResolution = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-f") == 0)
	{
	    if(++i < argc)
	        defaultKeyboardControl.bell = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-fc") == 0)
	{
	    if(++i < argc)
	        defaultCursorFont = argv[i];
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-fn") == 0)
	{
	    if(++i < argc)
	        defaultTextFont = argv[i];
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-fp") == 0)
	{
	    if(++i < argc)
	        defaultFontPath = argv[i];
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-help") == 0)
	{
	    UseMsg();
	    exit(0);
	}
#ifdef notdef
	else if ( strcmp( argv[i], "-logo") == 0)
	{
	    logoScreenSaver = 1;
	}
	else if ( strcmp( argv[i], "nologo") == 0)
	{
	    logoScreenSaver = 0;
	}
	else if ( strcmp( argv[i], "-p") == 0)
	{
	    if(++i < argc)
	        defaultScreenSaverInterval = ((long)atoi(argv[i])) *
					     MILLI_PER_MIN;
	    else
		UseMsg();
	}
#endif
	else if ( strcmp( argv[i], "r") == 0)
	    defaultKeyboardControl.autoRepeat = TRUE;
	else if ( strcmp( argv[i], "-r") == 0)
	    defaultKeyboardControl.autoRepeat = FALSE;
	else if ( strcmp( argv[i], "-s") == 0)
	{
	    if(++i < argc)
	        defaultScreenSaverTime = ((long)atoi(argv[i])) * MILLI_PER_MIN;
	    else
		UseMsg();
	}
#ifdef notdef
	else if ( strcmp( argv[i], "-su") == 0)
	    disableSaveUnders = TRUE;
#endif
	else if ( strcmp( argv[i], "-t") == 0)
	{
	    if(++i < argc)
	        defaultPointerControl.threshold = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-to") == 0)
	{
	    if(++i < argc)
		TimeOutValue = ((long)atoi(argv[i])) * MILLI_PER_SECOND;
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "v") == 0)
	    defaultScreenSaverBlanking = PreferBlanking;
	else if ( strcmp( argv[i], "-v") == 0)
	    defaultScreenSaverBlanking = DontPreferBlanking;
#ifdef notdef
	else if ( strcmp( argv[i], "-wm") == 0)
	    defaultBackingStore = WhenMapped;
#endif
	else if (strcmp(argv[i], "-debug") == 0)
	    debug = TRUE;
	else if ( strcmp( argv[i], "-I") == 0)
	{
	    /* ignore all remaining arguments */
	    break;
	}
#ifdef XDMCP
	else if ((skip = XdmcpOptions(argc, argv, i)) != i)
	{
	    i = skip - 1;
	}
#endif
 	else
 	{
	    UseMsg();
	    exit (1);
        }
    }
}

/* XALLOC -- X's internal memory allocator.  Why does it return unsigned
 * int * instead of the more common char *?  Well, if you read K&R you'll
 * see they say that alloc must return a pointer "suitable for conversion"
 * to whatever type you really want.  In a full-blown generic allocator
 * there's no way to solve the alignment problems without potentially
 * wasting lots of space.  But we have a more limited problem. We know
 * we're only ever returning pointers to structures which will have to
 * be long word aligned.  So we are making a stronger guarantee.  It might
 * have made sense to make Xalloc return char * to conform with people's
 * expectations of malloc, but this makes lint happier.
 */

void * 
Xalloc (amount)
    unsigned int amount;
{
    void *ptr;
	
    if(!amount)
	return (void *)NULL;
    /* aligned extra on word boundary */
    amount = (amount + 1) & ~1;
    if (ptr = malloc(amount))
	return ptr;
if (debug)
printf("Xalloc(%x) called with %u by %x:%x\n", (short)((long)Xalloc >> 16),
		amount, (&amount)[-1], (&amount)[-2]);
    if (Must_have_memory)
	FatalError("Out of memory");
    return (void *)NULL;
}

/*****************
 * Xcalloc
 *****************/

void *
Xcalloc (amount)
    unsigned int   amount;
{
    void *ret;

    ret = Xalloc (amount);
    if (ret)
	bzero ((char *) ret, (int) amount);
    return ret;
}

/*****************
 * Xrealloc
 *****************/

void *
Xrealloc (ptr, amount)
    void *ptr;
    unsigned int amount;
{

    if (FP_SEG(ptr) == (short)((long)&amount >> 16))
	printf("HELP! realloc data seg\n");
    if (!amount)
    {
	if (ptr)
	    free(ptr);
	return (void *)NULL;
    }
    if (ptr)
        ptr = realloc(ptr, amount);
    else
	ptr = malloc(amount);
    if (ptr)
        return ptr;
#ifdef notdef
printf("Xrealloc(%x) called with %u by %x:%x\n", (short)((long)Xrealloc >> 16),
amount, ((int *)&ptr)[-1], ((int *)&ptr)[-2]);
#endif
    if (Must_have_memory)
	FatalError("Out of memory");
    return (void *)NULL;
}
                    
/*****************
 *  Xfree
 *    calls free 
 *****************/    

void
Xfree(ptr)
void *ptr;
{
#ifdef notdef
    if (FP_SEG(ptr) == (short)((long)&ptr >> 16))
	printf("Xfree (%x) dseg called by %x:%x\n",
	(short)((long)Xfree >> 16), ((int *)&ptr)[-1], ((int *)&ptr)[-2]);
#endif
    if (ptr)
	free(ptr); 
}

void
FatalError(f,)
    char *f;
{
    va_list args;

    AbortDDX();
    va_start(args, f);
    fprintf(stderr, "\nFatal server bug!\n");
    vfprintf(stderr, f, args);
    fprintf(stderr, "\n");
#ifdef notdef
    if (debug)
	    stack_dump(0);
#endif
    exit(1);
}

/*VARARGS1*/
void
ErrorF(f,)
    char *f;
{
    va_list args;

    va_start(args, f);
    vfprintf(stderr, f, args);
}

#ifdef notdef
struct frame {
	struct frame near *bp;
	int ip;
	int cs;
};

void
stack_dump(bp)
struct frame near *bp;
{
	struct frame near *oldbp;
	int near *args;
	unsigned int i;

	if (!bp)
		bp = (struct frame *)&bp - 1;
	printf("top of stack: %x\n", (short)bp);
	oldbp = bp->bp;
	while (bp < oldbp) {
		printf("called by %x:%x", bp->cs, bp->ip);
		args = (int near *)(bp + 1);
		i = (int near *)oldbp - args;
		if (i > 8)
			i = 8;
		if (i) {
			printf(" with ");
			while (i--)
				printf("%x, ", *args++);
		}
		printf("\n");
		bp = oldbp;
		oldbp = bp->bp;
	}
	printf("bottom of stack: %x\n", (short)bp);
}
#endif
