/* $Id: build.c,v 1.1.1.1 90/11/28 17:01:40 altenhof Exp $ */

/*
 * Copyright (C) 1990 by Digital Equipment Corporation.
 * 
 * Author: Michael P. Altenhofen, CEC Karlsruhe e-mail:
 * Altenhofen@kampus.enet.dec.com
 * 
 * This file ist part of Shared X
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation without fee is hereby granted, but only for non-profit  use
 * and distribution,  and provided  that the copyright notice and this notice
 * is preserved on all copies.
 * 
 * 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.
 */
#include "XmuXlibint.h"
#define NEED_EVENTS
#include <X11/Xproto.h>
#include <X11/Xatom.h>

#define FontShiftSize  5
#define TextEltHeader  2

void
CheckPolyText (dpy, req)
  Display *dpy;
  xPolyTextReq *req;
{
  register unsigned char *pBuf, *pEnd;
  register int itemSize;

  pBuf = (unsigned char *) &req[1];
  pEnd = ((unsigned char *) req) + (req->length << 2);

  if (req->reqType == X_PolyText8)
    itemSize = 1;
  else
    itemSize = 2;

  while (pEnd - pBuf > TextEltHeader) {
    if (*pBuf == FontChange) {
      Font fid;

      fid = ((XID) * (pBuf + 4))
	| ((XID) * (pBuf + 3)) << 8
	| ((XID) * (pBuf + 2)) << 16
	| ((XID) * (pBuf + 1)) << 24;

      fid = XmuXMapID (dpy, fid, FromClient);
      pBuf[1] = (fid & 0xff000000) >> 24;
      pBuf[2] = (fid & 0x00ff0000) >> 16;
      pBuf[3] = (fid & 0x0000ff00) >> 8;
      pBuf[4] = fid & 0x000000ff;
      pBuf += FontShiftSize;
    }
    else
      pBuf = pBuf + TextEltHeader + (*pBuf) * itemSize;
  }
}

#undef FontShiftSize
#undef TextEltHeader

void
CheckProperty (dpy, type, property, units, from_where)
  Display *dpy;
  Atom type;			/* the property type */
  char *property;		/* the data */
  int units;			/* the number of data units */
  int from_where;		/* if we must map: is it an ID from the
				 * server or from the client */
{				/* we only check "long" (4 byte)
				 * properties and assume that unsigned
				 * longs are 4 bytes long */
  register unsigned long *pbuf = (unsigned long *) property;
  register int i;

  /*
   * as you can see by the switch statement: this procedure is
   * restricted to predefined atoms and does the mapping in a hardcoded
   * way.  We can't solve this problem in a generic way but there exists
   * a "probabilistic solution": use the structure of X's resource ID's;
   * a (valid) ID has at least one of it's 13 high bits set (hope that
   * the protocol won't change that !), so a property value with one of
   * these bits set will "probably" be an ID :
   *
   *  for( i = 0 ; i < units ; i++ , pbuf++ )
   *     if( *pbuf & 0xfff80000 )
   *	   *pbuf = MapID(dpy, *pbuf, from_where);
   *
   * maybe we use it next time
   */

  switch (type) {
  case XA_BITMAP:
  case XA_COLORMAP:
  case XA_CURSOR:
  case XA_DRAWABLE:
  case XA_FONT:
  case XA_PIXMAP:
  case XA_VISUALID:
  case XA_WINDOW:
  case XA_WM_TRANSIENT_FOR:
    /* these properties should be of size 1 */
    *pbuf = XmuXMapID (dpy, *pbuf, from_where);
    break;

  case XA_RGB_COLOR_MAP:
  case XA_RGB_BEST_MAP:
  case XA_RGB_BLUE_MAP:
  case XA_RGB_DEFAULT_MAP:
  case XA_RGB_GRAY_MAP:
  case XA_RGB_GREEN_MAP:
  case XA_RGB_RED_MAP:
    /* we have to rely on ../X11/server/dix/BuiltInAtoms */
    *pbuf = XmuXMapID (dpy, *pbuf, from_where);
    break;

  case XA_WM_HINTS:
    /* according to ../X11/server/dix/BuiltInAtoms .. */
    /* unit 4 contains the icon-pixmap ID ... */
    pbuf[3] = XmuXMapID (dpy, pbuf[3], from_where);
    /* unit 5 the icon-window ID ... */
    pbuf[4] = XmuXMapID (dpy, pbuf[4], from_where);
    /* and unit 6 the icon-mask bitmap ID */
    pbuf[5] = XmuXMapID (dpy, pbuf[5], from_where);
    break;

  default:
    break;
  }
}

void
BuildWindowChanges (dpy, mask, changes)
  Display *dpy;
  Mask mask;
  XWindowChanges *changes;

{
  register unsigned long *pbuf = (unsigned long *) changes;

  XmuXdebug (debug_requests, "Mask : %lx\n", mask);
  if (mask & CWX) {
    XmuXdebug (debug_requests, "WCh x : %d ", *pbuf);
    pbuf++;
  }
  if (mask & CWY) {
    XmuXdebug (debug_requests, "WCh y : %d ", *pbuf);
    pbuf++;
  }
  if (mask & CWWidth) {
    XmuXdebug (debug_requests, "WCh width  : %d ", *pbuf);
    pbuf++;
  }
  if (mask & CWHeight) {
    XmuXdebug (debug_requests, "WCh height : %d ", *pbuf);
    pbuf++;
  }
  if (mask & CWBorderWidth) {
    XmuXdebug (debug_requests, "WCh b_width : %d ", *pbuf);
    pbuf++;
  }
  if (mask & CWSibling) {
    /* sibling is a window ID --> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "WCh sibling: 0x%lx ", *pbuf);
    pbuf++;
  }
  if (mask & CWStackMode) {
    XmuXdebug (debug_requests, "WCh stack mode : %d ", *pbuf);
    pbuf++;
  }
  XmuXdebug (debug_requests, "\n");
}

void
CheckGCValues (dpy, valuemask, values, gid, window, new)
  Display *dpy;
  Mask valuemask;
  XGCValues *values;
  GContext gid;			/* MAPPED ID !!! */
  Window window;		/* MAPPED ID !!! */
  Bool new;			/* do we call CheckGCValues from
				 * ProcCreateGC? */
{
  register unsigned long *pbuf = (unsigned long *) values, GCflags = 0L;
  XGCValues gcval;

  XmuXdebug (debug_requests, "Mask : %lx\n", valuemask);
  if (valuemask & GCFunction) {
    XmuXdebug (debug_requests, "GC function :%u ", *pbuf);
    if (*pbuf != GXcopy) {
      gcval.function = *pbuf;
      GCflags |= GCFunction;
    }
    pbuf++;
  }
  if (valuemask & GCPlaneMask) {
    XmuXdebug (debug_requests, "GC plane mask :%lx ", *pbuf);
    if (*pbuf != AllPlanes) {
      gcval.plane_mask = *pbuf;
      GCflags |= GCPlaneMask;
    }
    pbuf++;
  }
  if (valuemask & GCForeground) {
    gcval.foreground = *pbuf;	/* store the unmapped value */
    XmuXdebug (debug_requests, "GC \"foreground\" :%u ",
	       *pbuf);
    GCflags |= GCForeground;
    pbuf++;
  }
  else

    /*
     * new GC's may be used with their default color values; make sure
     * that they are inserted in the list
     */
  if (new) {
    GCflags |= GCForeground;
    gcval.foreground = 0L;	/* the default */
  }
  if (valuemask & GCBackground) {
    gcval.background = *pbuf;	/* store the unmapped value */
    XmuXdebug (debug_requests, "GC \"background\" :%u ",
	       *pbuf);
    GCflags |= GCBackground;
    pbuf++;
  }
  else

    /*
     * new GC's may be used with their default color values; make sure
     * that they are inserted in the list
     */
  if (new) {
    GCflags |= GCBackground;
    gcval.background = 1L;	/* the default */
  }

  if (valuemask & GCLineWidth) {
    XmuXdebug (debug_requests, "GC line width :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCLineStyle) {
    XmuXdebug (debug_requests, "GC line style :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCCapStyle) {
    XmuXdebug (debug_requests, "GC cap style :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCJoinStyle) {
    XmuXdebug (debug_requests, "GC join style :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCFillStyle) {
    XmuXdebug (debug_requests, "GC fill style :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCFillRule) {

    XmuXdebug (debug_requests, "GC fill rule :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCTile) {
    /* tile is a pixmap ID -> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "GC tile pixmap :0x%lx ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCStipple) {
    /* stipple is a pixmap ID -> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "GC stipple pixmap :0x%lx ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCTileStipXOrigin) {
    XmuXdebug (debug_requests, "GC ts x orig :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCTileStipYOrigin) {
    XmuXdebug (debug_requests, "GC ts y orig :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCFont) {
    /* font is an font ID -> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "GC font :0x%lx ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCSubwindowMode) {
    XmuXdebug (debug_requests, "GC subwindow mode :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCGraphicsExposures) {
    XmuXdebug (debug_requests, "GC gr exposures :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCClipXOrigin) {
    XmuXdebug (debug_requests, "GC clip x orig :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCClipYOrigin) {
    XmuXdebug (debug_requests, "GC clip y orig :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCClipMask) {
    /* clip mask is an pixmap ID -> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "GC clip mask :0x%lx ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCDashOffset) {
    XmuXdebug (debug_requests, "GC dash offset :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCDashList) {
    XmuXdebug (debug_requests, "GC dashes :%s ", *pbuf);
    pbuf++;
  }
  if (valuemask & GCArcMode) {
    XmuXdebug (debug_requests, "GC arc mode :%u ", *pbuf);
    pbuf++;
  }
  /* XXX -- Add && XmuXMoreThanOneColormap( dpy ) later !! */
  if (GCflags)
    XmuXUpdateGCPixels (dpy, gid, GCflags, &gcval);

  XmuXdebug (debug_requests, "\n");
}

void
CheckWindowAttributes (dpy, win, valuemask, attr)
  Display *dpy;
  Window win;
  Mask valuemask;
  XSetWindowAttributes *attr;
{
  register unsigned long *pbuf = (unsigned long *) attr;

  XmuXdebug (debug_requests, "value mask : %lx\n", valuemask);
  if (valuemask & CWBackPixmap) {
    /* background pixmap is a pixmap ID -> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "WA bg pixmap :0x%lx ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWBackPixel) {
    /* pixel values must be mapped */
    *pbuf = XmuXMapPixel (dpy, win, *pbuf);
    XmuXdebug (debug_requests, "WA bg pixel :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWBorderPixmap) {
    /* border pixmap is a pixmap ID -> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "WA border pixmap :0x%lx ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWBorderPixel) {
    /* pixel values must be mapped */
    *pbuf = XmuXMapPixel (dpy, win, *pbuf);
    XmuXdebug (debug_requests, "WA border pixel :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWBitGravity) {
    XmuXdebug (debug_requests, "WA bit gravity :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWWinGravity) {
    XmuXdebug (debug_requests, "WA window gravity :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWBackingStore) {
    XmuXdebug (debug_requests, "WA backing store :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWBackingPlanes) {
    XmuXdebug (debug_requests, "WA backing planes :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWBackingPixel) {
    XmuXdebug (debug_requests, "WA backing pixel :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWOverrideRedirect) {
    XmuXdebug (debug_requests, "WA override red :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWSaveUnder) {
    /* don't want to care about save unders */
    *pbuf = (unsigned long) False;
    XmuXdebug (debug_requests, "WA save under :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWEventMask) {
    PrintMask (win, *pbuf, debug_requests, False);
    pbuf++;
  }
  if (valuemask & CWDontPropagate) {
    XmuXdebug (debug_requests, "WA don't prop mask :%u ", *pbuf);
    pbuf++;
  }
  if (valuemask & CWColormap) {
    /* colormap is a color map ID -> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "WA colormap :0x%lx ", *pbuf);
    XmuXSetWindowCmap (dpy, win, *pbuf);
    pbuf++;
  }
  if (valuemask & CWCursor) {
    /* cursor is a cursor ID -> map it */
    *pbuf = XmuXMapID (dpy, *pbuf, FromClient);
    XmuXdebug (debug_requests, "WA cursor :0x%lx ", *pbuf);
    pbuf++;
  }
  XmuXdebug (debug_requests, "\n");
}

int
CheckWire (dpy, ev)
  Display *dpy;
  xEvent *ev;
{
  switch (ev->u.u.type & 0177) {

  case KeyPress:
  case KeyRelease:
  case ButtonPress:
  case ButtonRelease:
  case MotionNotify:
    ev->u.keyButtonPointer.root =
      XmuXMapID (dpy, ev->u.keyButtonPointer.root, FromClient);
    ev->u.keyButtonPointer.event =
      XmuXMapID (dpy, ev->u.keyButtonPointer.event, FromClient);
    ev->u.keyButtonPointer.child =
      XmuXMapID (dpy, ev->u.keyButtonPointer.child, FromClient);
    break;

  case EnterNotify:
  case LeaveNotify:
    ev->u.enterLeave.root =
      XmuXMapID (dpy, ev->u.enterLeave.root, FromClient);
    ev->u.enterLeave.event =
      XmuXMapID (dpy, ev->u.enterLeave.event, FromClient);
    ev->u.enterLeave.child =
      XmuXMapID (dpy, ev->u.enterLeave.child, FromClient);
    break;

  case FocusIn:
  case FocusOut:
    ev->u.focus.window = XmuXMapID (dpy, ev->u.focus.window,
				    FromClient);
    break;

  case KeymapNotify:
    break;

  case Expose:
    ev->u.expose.window = XmuXMapID (dpy, ev->u.expose.window,
				     FromClient);
    break;

  case GraphicsExpose:
    ev->u.graphicsExposure.drawable =
      XmuXMapID (dpy, ev->u.graphicsExposure.drawable, FromClient);
    break;

  case NoExpose:
    ev->u.noExposure.drawable =
      XmuXMapID (dpy, ev->u.noExposure.drawable, FromClient);
    break;

  case VisibilityNotify:
    ev->u.visibility.window =
      XmuXMapID (dpy, ev->u.visibility.window, FromClient);
    break;

  case CreateNotify:
    ev->u.createNotify.window =
      XmuXMapID (dpy, ev->u.createNotify.window, FromClient);
    ev->u.createNotify.parent =
      XmuXMapID (dpy, ev->u.createNotify.parent, FromClient);
    break;

  case DestroyNotify:
    ev->u.destroyNotify.window =
      XmuXMapID (dpy, ev->u.destroyNotify.window, FromClient);
    ev->u.destroyNotify.event =
      XmuXMapID (dpy, ev->u.destroyNotify.event, FromClient);
    break;

  case UnmapNotify:
    ev->u.unmapNotify.window =
      XmuXMapID (dpy, ev->u.unmapNotify.window, FromClient);
    ev->u.unmapNotify.event =
      XmuXMapID (dpy, ev->u.unmapNotify.event, FromClient);
    break;

  case MapNotify:
    ev->u.mapNotify.window =
      XmuXMapID (dpy, ev->u.mapNotify.window, FromClient);
    ev->u.mapNotify.event =
      XmuXMapID (dpy, ev->u.mapNotify.event, FromClient);
    break;

  case MapRequest:
    ev->u.mapRequest.window =
      XmuXMapID (dpy, ev->u.mapRequest.window, FromClient);
    ev->u.mapRequest.parent =
      XmuXMapID (dpy, ev->u.mapRequest.parent, FromClient);
    break;

  case ReparentNotify:
    ev->u.reparent.window =
      XmuXMapID (dpy, ev->u.reparent.window, FromClient);
    ev->u.reparent.event =
      XmuXMapID (dpy, ev->u.reparent.event, FromClient);
    ev->u.reparent.parent =
      XmuXMapID (dpy, ev->u.reparent.parent, FromClient);
    break;

  case ConfigureNotify:
    ev->u.configureNotify.window =
      XmuXMapID (dpy, ev->u.configureNotify.window, FromClient);
    ev->u.configureNotify.event =
      XmuXMapID (dpy, ev->u.configureNotify.event, FromClient);
    ev->u.configureNotify.aboveSibling =
      XmuXMapID (dpy, ev->u.configureNotify.aboveSibling,
		 FromClient);
    break;

  case ConfigureRequest:
    ev->u.configureRequest.window =
      XmuXMapID (dpy, ev->u.configureRequest.window, FromClient);
    ev->u.configureRequest.parent =
      XmuXMapID (dpy, ev->u.configureRequest.parent, FromClient);
    ev->u.configureRequest.sibling =
      XmuXMapID (dpy, ev->u.configureRequest.sibling,
		 FromClient);
    break;

  case GravityNotify:
    ev->u.gravity.window =
      XmuXMapID (dpy, ev->u.gravity.window, FromClient);
    ev->u.gravity.event =
      XmuXMapID (dpy, ev->u.gravity.event, FromClient);
    break;

  case ResizeRequest:
    ev->u.resizeRequest.window =
      XmuXMapID (dpy, ev->u.resizeRequest.window, FromClient);
    break;

  case CirculateNotify:
    ev->u.circulate.window =
      XmuXMapID (dpy, ev->u.circulate.window, FromClient);
    ev->u.circulate.event =
      XmuXMapID (dpy, ev->u.circulate.event, FromClient);
    break;

  case CirculateRequest:
    ev->u.circulate.window =
      XmuXMapID (dpy, ev->u.circulate.window, FromClient);
    ev->u.circulate.event =
      XmuXMapID (dpy, ev->u.circulate.event, FromClient);
    break;

  case PropertyNotify:
    ev->u.property.window =
      XmuXMapID (dpy, ev->u.property.window, FromClient);
    ev->u.property.atom =
      XmuXMapID (dpy, ev->u.property.atom, FromClient);
    break;

  case SelectionClear:
    ev->u.selectionClear.window =
      XmuXMapID (dpy, ev->u.selectionClear.window, FromClient);
    ev->u.selectionClear.atom =
      XmuXMapID (dpy, ev->u.selectionClear.atom, FromClient);
    break;

  case SelectionRequest:
    ev->u.selectionRequest.owner =
      XmuXMapID (dpy, ev->u.selectionRequest.owner, FromClient);
    ev->u.selectionRequest.selection =
      XmuXMapID (dpy, ev->u.selectionRequest.selection, FromClient);
    ev->u.selectionRequest.target =
      XmuXMapID (dpy, ev->u.selectionRequest.target, FromClient);
    ev->u.selectionRequest.property =
      XmuXMapID (dpy, ev->u.selectionRequest.property, FromClient);
    break;

  case SelectionNotify:
    ev->u.selectionNotify.requestor =
      XmuXMapID (dpy, ev->u.selectionNotify.requestor, FromClient);
    ev->u.selectionNotify.selection =
      XmuXMapID (dpy, ev->u.selectionNotify.selection, FromClient);
    ev->u.selectionNotify.target =
      XmuXMapID (dpy, ev->u.selectionNotify.target, FromClient);
    ev->u.selectionNotify.property =
      XmuXMapID (dpy, ev->u.selectionNotify.property, FromClient);
    break;

  case ColormapNotify:
    ev->u.colormap.window =
      XmuXMapID (dpy, ev->u.colormap.window, FromClient);
    ev->u.colormap.colormap =
      XmuXMapID (dpy, ev->u.colormap.colormap, FromClient);
    break;

  case ClientMessage:
    ev->u.clientMessage.window =
      XmuXMapID (dpy, ev->u.clientMessage.window, FromClient);
    switch (ev->u.u.detail) {
    case 8:
      ev->u.clientMessage.u.b.type =
	XmuXMapID (dpy, ev->u.clientMessage.u.b.type, FromClient);
      break;
    case 16:
      ev->u.clientMessage.u.s.type =
	XmuXMapID (dpy, ev->u.clientMessage.u.s.type, FromClient);
      break;
    case 32:
      ev->u.clientMessage.u.l.type =
	XmuXMapID (dpy, ev->u.clientMessage.u.l.type, FromClient);
      break;
    }
    break;

  case MappingNotify:
    break;

  default:
    return (False);

  }
  return (True);
}
