/**
 *
 * ChoX11: XLib replacement for RISC OS
 *
 * Misc. functionality
 *
 * Copyright 2003 by Peter Naulls
 * Written by Peter Naulls
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation. No representations are made about the suitability of this
 * software for any purpose.  It is provided "as is" without express or
 * implied warranty.
 *
 */


#define NeedFunctionPrototypes 1
#define NeedNestedPrototypes   1

#include <X11/Xlibint.h>

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


#define ECHECK(err) (errno == err)


extern	Bool		XkbLookupKeySym(
    Display *			dpy,
    KeyCode 			keycode,
    unsigned int 		modifiers,
    unsigned int *		modifiers_return,
    KeySym *			keysym_return
) {
  puts("XkbLookupKeySym (not implemented)");
  return False;
}



extern int _XError(
    Display*	dpy,
    xError*	rep
);


extern int _XIOError(
    Display*	dpy
);


extern void _XEatData(
    Display*		dpy,
    unsigned long	n
) {
  puts("_XEatData (not implemented)");
}


extern char *_XAllocScratch(
    Display*		dpy,
    unsigned long	nbytes
) {
  char *fake_return = malloc(nbytes);
  printf("_XAllocScratch: (not implemented) returning %p\n", fake_return);
  return fake_return;
}

extern char *_XAllocTemp(
    Display*		dpy,
    unsigned long	nbytes
);


extern void _XFreeTemp(
    Display*		dpy,
    char*		buf,
    unsigned long	nbytes
);


extern Visual *_XVIDtoVisual(
    Display*	dpy,
    VisualID	id
);


extern unsigned long _XSetLastRequestRead(
    Display*		dpy,
    xGenericReply*	rep
) {
  puts("_XSetLastRequestRead (not implemented)");
  return 0;
}


extern int _XGetHostname(
    char*	buf,
    int		maxlen
);



/*
 * _XScreenOfWindow - get the Screen of a given window
 */

Screen *_XScreenOfWindow (dpy, w)
    Display *dpy;
    Window w;
{
    register int i;
    Window root;
    int x, y;				/* dummy variables */
    unsigned int width, height, bw, depth;  /* dummy variables */

    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
		      &bw, &depth) == False) {
	return None;
    }
    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
	if (root == RootWindow (dpy, i)) {
	    return ScreenOfDisplay (dpy, i);
	}
    }
    return NULL;
}

extern Bool _XAsyncErrorHandler(
    Display*	dpy,
    xReply*	rep,
    char*	buf,
    int		len,
    XPointer	data
);


extern char *_XGetAsyncReply(
    Display*	dpy,
    char*	replbuf,
    xReply*	rep,
    char*	buf,
    int		len,
    int		extra,
    Bool	discard
);


extern void _XFlush(
    Display*	dpy
) {
  puts("_XFlush (not implemented)");
}


extern int _XEventsQueued(
    Display*	dpy,
    int 	mode
);


extern void _XReadEvents(
    Display*	dpy
);


extern int _XRead(
    Display*	dpy,
    char*	data,
    long	size
) {
  puts("_XRead (not implemented)");
  return 0;
}


extern void _XReadPad(
    Display*	dpy,
    char*	data,
    long	size
);


extern void _XSend(
    Display*		dpy,
    _Xconst char*	data,
    long		size
) {
  puts("_XSend (not implemented)");
}


extern Status _XReply(
    Display*	dpy,
    xReply*	rep,
    int		extra,
    Bool	discard
) {
  puts("_XReply (not implemented)");
  return 0;
}


extern void _XEnq(
    Display*	dpy,
    xEvent*	event
);


extern void _XDeq(
    Display*	dpy,
    _XQEvent*	prev,
    _XQEvent*	qelt
);



extern int (*XESetCreateGC(

    Display*		 display,
    int			 extension,
    int (*proc) (

	      Display*			 display,
	      GC			 gc,
	      XExtCodes*		 codes

	    )		

))(

    Display*, GC, XExtCodes*

) {
  puts("XESetCreateGC (not implemented)");
}


extern int (*XESetCopyGC(

    Display*		 display,
    int			 extension,
    int (*proc) (

	      Display*			 display,
              GC			 gc,
              XExtCodes*		 codes

            )		      

))(

    Display*, GC, XExtCodes*

) {
  puts("XESetCopyGC (not implemented)");
  return 0;
}

extern int (*XESetFlushGC(

    Display*		 display,
    int			 extension,
    int (*proc) (

	      Display*			 display,
              GC			 gc,
              XExtCodes*		 codes

            )		      

))(

    Display*, GC, XExtCodes*

) {
  puts("XESetFlushGC (not implemented)");
}

extern int (*XESetFreeGC(

    Display*		 display,
    int			 extension,
    int (*proc) (

	      Display*			 display,
              GC			 gc,
              XExtCodes*		 codes

            )		     

))(

    Display*, GC, XExtCodes*

) {
  puts("XESetFreeGC (not implemented)");
}

extern int (*XESetCreateFont(

    Display*		 display,
    int			 extension,
    int (*proc) (

	      Display*			 display,
              XFontStruct*		 fs,
              XExtCodes*		 codes

            )		     

))(

    Display*, XFontStruct*, XExtCodes*

) {
  puts("XESetCreateFont (not implemented)");
}

extern int (*XESetFreeFont(

    Display*		 display,
    int			 extension,
    int (*proc) (

	      Display*			 display,
              XFontStruct*		 fs,
              XExtCodes*		 codes

            )		    

))(

    Display*, XFontStruct*, XExtCodes*

) {
  puts("XESetFreeFont (not implemented)");
  return 0;
}


extern int (*XESetCloseDisplay(
    Display*		display,
    int			extension,
    int (*proc) (
	      Display*			display,
              XExtCodes*		codes
            )
))(
    Display*, XExtCodes*
) {
  puts("XESetCloseDisplay (not implemented)");
};


extern int (*XESetError(

    Display*		 display,
    int			 extension,
    int (*proc) (

	      Display*			 display,
              xError*			 err,
              XExtCodes*		 codes,
              int*			 ret_code

            )    

))(

    Display*, xError*, XExtCodes*, int*

) {
 puts("XESetError (not implemented)");
}

extern char* (*XESetErrorString(

    Display*		 display,
    int			 extension,
    char* (*proc) (

	        Display*		 display,
                int			 code,
                XExtCodes*		 codes,
                char*			 buffer,
                int			 nbytes

              )

))(

    Display*, int, XExtCodes*, char*, int

) {
 puts("XESetErrorString (not implemented)");
}

extern void (*XESetPrintErrorValues (

    Display*		 display,
    int			 extension,
    void (*proc)(

	      Display*			 display,
	      XErrorEvent*		 ev,
	      void*			 fp

	     )		 

))(

    Display*, XErrorEvent*, void*

);

extern Bool (*XESetWireToEvent(

    Display*		 display,
    int			 event_number,
    Bool (*proc) (

	       Display*			 display,
               XEvent*			 re,
               xEvent*			 event

             )		    

))(

    Display*, XEvent*, xEvent*

) {
  puts("XESetWireToEvent (not implemented)");
  return NULL;
}

extern Status (*XESetEventToWire(

    Display*		 display,
    int			 event_number,
    Status (*proc) (

	      Display*			 display,
              XEvent*			 re,
              xEvent*			 event

            )		    

))(

    Display*, XEvent*, xEvent*

) {
  puts("XESetEventToWire (not implemented)");
  return 0;
}

extern Bool (*XESetWireToError(

    Display*		 display,
    int			 error_number,
    Bool (*proc) (

	       Display*			 display,
	       XErrorEvent*		 he,
	       xError*			 we

            )		    

))(

    Display*, XErrorEvent*, xError*

);

extern void (*XESetBeforeFlush(

    Display*		 display,
    int			 error_number,
    void (*proc) (

	       Display*			 display,
	       XExtCodes*		 codes,
	       _Xconst char*		 data,
	       long			 len

            )		   

))(

    Display*, XExtCodes*, _Xconst char*, long

);


extern Status _XRegisterInternalConnection(

    Display*			 dpy,
    int				 fd,
    _XInternalConnectionProc	 callback,
    XPointer			 call_data

);

extern void _XUnregisterInternalConnection(

    Display*			 dpy,
    int				 fd

);


extern int _XTextHeight(

    XFontStruct*	 font_struct,
    _Xconst char*	 string,
    int			 count

);

extern int _XTextHeight16(

    XFontStruct*	 font_struct,
    _Xconst XChar2b*	 string,
    int			 count

);



/*
 * _XDefaultIOError - Default fatal system error reporting routine.  Called 
 * when an X internal system error is encountered.
 */
int _XDefaultIOError(
	Display *dpy)
{
	if (ECHECK(EPIPE)) {
	    (void) fprintf (stderr,
	"X connection to %s broken (explicit kill or server shutdown).\r\n",
			    DisplayString (dpy));
	} else {
	    (void) fprintf (stderr, 
			"XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
#ifdef WIN32
			WSAGetLastError(), strerror(WSAGetLastError()),
#else
			errno, strerror (errno),
#endif
			DisplayString (dpy));
	    (void) fprintf (stderr, 
	 "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
			NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
			QLength(dpy));

	}
	exit(1);
        return(0); /* dummy - function should never return */
}


static int _XPrintDefaultError(
    Display *dpy,
    XErrorEvent *event,
    FILE *fp)
{
    char buffer[BUFSIZ];
    char mesg[BUFSIZ];
    char number[32];
    char *mtype = "XlibMessage";
    register _XExtension *ext = (_XExtension *)NULL;
    _XExtension *bext = (_XExtension *)NULL;
    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", 
	mesg, BUFSIZ);
    (void) fprintf(fp, mesg, event->request_code);
    if (event->request_code < 128) {
	sprintf(number, "%d", event->request_code);
	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
    } else {
	for (ext = dpy->ext_procs;
	     ext && (ext->codes.major_opcode != event->request_code);
	     ext = ext->next)
	  ;
	if (ext)
	    strcpy(buffer, ext->name);
	else
	    buffer[0] = '\0';
    }
    (void) fprintf(fp, " (%s)\n", buffer);
    if (event->request_code >= 128) {
	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
			      mesg, BUFSIZ);
	fputs("  ", fp);
	(void) fprintf(fp, mesg, event->minor_code);
	if (ext) {
	    sprintf(mesg, "%s.%d", ext->name, event->minor_code);
	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
	    (void) fprintf(fp, " (%s)", buffer);
	}
	fputs("\n", fp);
    }
    if (event->error_code >= 128) {
	/* kludge, try to find the extension that caused it */
	buffer[0] = '\0';
	for (ext = dpy->ext_procs; ext; ext = ext->next) {
	    if (ext->error_string) 
		(*ext->error_string)(dpy, event->error_code, &ext->codes,
				     buffer, BUFSIZ);
	    if (buffer[0]) {
		bext = ext;
		break;
	    }
	    if (ext->codes.first_error &&
		ext->codes.first_error < (int)event->error_code &&
		(!bext || ext->codes.first_error > bext->codes.first_error))
		bext = ext;
	}    
	if (bext)
	    sprintf(buffer, "%s.%d", bext->name,
		    event->error_code - bext->codes.first_error);
	else
	    strcpy(buffer, "Value");
	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
	if (mesg[0]) {
	    fputs("  ", fp);
	    (void) fprintf(fp, mesg, event->resourceid);
	    fputs("\n", fp);
	}
	/* let extensions try to print the values */
	for (ext = dpy->ext_procs; ext; ext = ext->next) {
	    if (ext->error_values)
		(*ext->error_values)(dpy, event, fp);
	}
    } else if ((event->error_code == BadWindow) ||
	       (event->error_code == BadPixmap) ||
	       (event->error_code == BadCursor) ||
	       (event->error_code == BadFont) ||
	       (event->error_code == BadDrawable) ||
	       (event->error_code == BadColor) ||
	       (event->error_code == BadGC) ||
	       (event->error_code == BadIDChoice) ||
	       (event->error_code == BadValue) ||
	       (event->error_code == BadAtom)) {
	if (event->error_code == BadValue)
	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
				  mesg, BUFSIZ);
	else if (event->error_code == BadAtom)
	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
				  mesg, BUFSIZ);
	else
	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
				  mesg, BUFSIZ);
	fputs("  ", fp);
	(void) fprintf(fp, mesg, event->resourceid);
	fputs("\n", fp);
    }
    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", 
			  mesg, BUFSIZ);
    fputs("  ", fp);
    (void) fprintf(fp, mesg, event->serial);
    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
			  mesg, BUFSIZ);
    fputs("\n  ", fp);
    (void) fprintf(fp, mesg, dpy->request);
    fputs("\n", fp);
    if (event->error_code == BadImplementation) return 0;
    return 1;
}

int _XDefaultError(
	Display *dpy,
	XErrorEvent *event)
{
    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
    exit(1);
    /*NOTREACHED*/
}




