/*
 * -- $Header: /cec/src/nestor/servers/R3/shXlib/XFont.c,v 1.1.1.1 90/04/23 09:57:20 spanachi Exp $
 */

#include "copyright.h"

/* $XConsortium: XFont.c,v 11.26 88/09/06 16:05:50 jim Exp $ */
/* Copyright    Massachusetts Institute of Technology    1986	*/

/* -- MULTIPLEX Extension -- */

#define NEED_REPLIES
#include "Xlibint.h"

/* additional includes -- */
#include "resources.h"
#include "utils.h"
#include "map.h"

XFontStruct *_XQueryFont();

XFontStruct *XLoadQueryFont(calling_dpy, name)
   /* -- must rename or else macro GetReq will fail -- */
   register Display *calling_dpy;
   char *name;
{
    XFontStruct *font_result, *def_result ;
    register long nbytes;
    Font fid;
    xOpenFontReq *req;

    /* -- additional vars -- */
    register Display *dpy ;
    register int      i , ok ;

    /* -- Flush the queue to keep buffers aligned -- */
    XmuXFlushDefault( calling_dpy ) ;

    /* 
     * -- XLoadQueryFont creates a new resource; 
     * -- we loop here to detect an error
     */
    ok = True ;
    for( i = 0 ; 
	 ( dpy = XmuXGetDisplay( calling_dpy , i ) ) != NULL && ok ; i++ )
    {
	LockDisplay(dpy);
	GetReq(OpenFont, req);
	nbytes = req->nbytes  = name ? strlen(name) : 0;
	req->fid = fid = XAllocID(dpy);
	req->length += (nbytes+3)>>2;
	Data (dpy, name, nbytes);
	dpy->request--;
	font_result = (_XQueryFont(dpy, fid));
	dpy->request++;
	if (!font_result) 
	{
	    /* if _XQueryFont returned NULL, then the OpenFont request got
	       a BadName error.  This means that the following QueryFont
	       request is guaranteed to get a BadFont error, since the id
	       passed to QueryFont wasn't really a valid font id.  To read
	       and discard this second error, we call _XReply again. */
	    xReply reply;
	    (void) _XReply (dpy, &reply, 0, xFalse);
	    ok = False ;
	}
	else
	    /* 
	     * -- On success : store the new resource if it necessary 
	     */
	    if( XmuXStoreResources( dpy ) )
		XmuXInsertFontInfo( dpy , fid , name ) ;
	if( dpy == calling_dpy )
	    def_result = font_result ;
	UnlockDisplay(dpy);
	SyncHandle();
    }
    
    return(  ok ? def_result : ( XFontStruct * ) NULL ) ;
}

XFreeFont(dpy, fs)
    register Display *dpy;
    XFontStruct *fs;
{ 
    register xResourceReq *req;
    register _XExtension *ext = dpy->ext_procs;

    LockDisplay(dpy);
    while (ext) {		/* call out to any extensions interested */
	if (ext->free_Font != NULL) (*ext->free_Font)(dpy, fs, &ext->codes);
	ext = ext->next;
	}    
    GetResReq (CloseFont, fs->fid, req);
    _XFreeExtData(fs->ext_data);
    if (fs->per_char)
       Xfree ((char *) fs->per_char);
    if (fs->properties)
       Xfree ((char *) fs->properties);
    ext = dpy->ext_procs;
    /* 
     * -- remove the resource info 
     */
    if( XmuXStoreResources( dpy ) )
	XmuXRemoveFontInfo( dpy , fs->fid ) ;
    Xfree ((char *) fs);
    UnlockDisplay(dpy);
    SyncHandle();
}


XFontStruct *_XQueryFont (dpy, fid)	/* Internal-only entry point */
    register Display *dpy;
    Font fid;

{
    register XFontStruct *fs;
    register long nbytes;
    xQueryFontReply reply;
    register xResourceReq *req;
    register _XExtension *ext;

    GetResReq(QueryFont, fid, req);
    if (!_XReply (dpy, (xReply *) &reply,
       ((SIZEOF(xQueryFontReply) - SIZEOF(xReply)) >> 2), xFalse))
	   return (NULL);
    fs = (XFontStruct *) Xmalloc (sizeof (XFontStruct));
    fs->ext_data 		= NULL;
    fs->fid 			= fid;
    fs->direction 		= reply.drawDirection;
    fs->min_char_or_byte2	= reply.minCharOrByte2;
    fs->max_char_or_byte2 	= reply.maxCharOrByte2;
    fs->min_byte1 		= reply.minByte1;
    fs->max_byte1 		= reply.maxByte1;
    fs->default_char 		= reply.defaultChar;
    fs->all_chars_exist 	= reply.allCharsExist;
    fs->ascent 			= cvtINT16toInt (reply.fontAscent);
    fs->descent 		= cvtINT16toInt (reply.fontDescent);
    
#ifdef MUSTCOPY
    {
	xCharInfo *xcip;

	xcip = (xCharInfo *) &reply.minBounds;
	fs->min_bounds.lbearing = xcip->leftSideBearing;
	fs->min_bounds.rbearing = xcip->rightSideBearing;
	fs->min_bounds.width = xcip->characterWidth;
	fs->min_bounds.ascent = xcip->ascent;
	fs->min_bounds.descent = xcip->descent;
	fs->min_bounds.attributes = xcip->attributes;

	xcip = (xCharInfo *) &reply.maxBounds;
	fs->max_bounds.lbearing = xcip->leftSideBearing;
	fs->max_bounds.rbearing = xcip->rightSideBearing;
	fs->max_bounds.width = xcip->characterWidth;
	fs->max_bounds.ascent = xcip->ascent;
	fs->max_bounds.descent = xcip->descent;
	fs->max_bounds.attributes = xcip->attributes;
    }
#else
    /* XXX the next two statements won't work if short isn't 16 bits */
    fs->min_bounds = * (XCharStruct *) &reply.minBounds;
    fs->max_bounds = * (XCharStruct *) &reply.maxBounds;
#endif /* MUSTCOPY */

    fs->n_properties = reply.nFontProps;
    /* 
     * if no properties defined for the font, then it is bad
     * font, but shouldn't try to read nothing.
     */
    fs->properties = NULL;
    if (fs->n_properties > 0) {
	    nbytes = reply.nFontProps * sizeof(XFontProp);
	    fs->properties = (XFontProp *) Xmalloc (nbytes);
	    nbytes = reply.nFontProps * SIZEOF(xFontProp);
	    _XRead32 (dpy, (char *)fs->properties, nbytes);
    }
    /*
     * If no characters in font, then it is a bad font, but
     * shouldn't try to read nothing.
     */
    /* have to unpack charinfos on some machines (CRAY) */
    fs->per_char = NULL;
    if (reply.nCharInfos > 0){
	    nbytes = reply.nCharInfos * sizeof(XCharStruct);
	    fs->per_char = (XCharStruct *) Xmalloc (nbytes);
	    nbytes = reply.nCharInfos * SIZEOF(xCharInfo);
	    _XRead16 (dpy, (char *)fs->per_char, nbytes);
    }

    ext = dpy->ext_procs;
    while (ext) {		/* call out to any extensions interested */
	if (ext->create_Font != NULL) 
		(*ext->create_Font)(dpy, fs, &ext->codes);
	ext = ext->next;
	}    
    return (fs);
}


XFontStruct *XQueryFont (dpy, fid)
    register Display *dpy;
    Font fid;
{
    XFontStruct *font_result;

    LockDisplay(dpy);
    font_result = _XQueryFont(dpy, fid );
    UnlockDisplay(dpy);
    SyncHandle();
    return font_result;
}

   
   

