/* XtDrawContext - Drawing context using the Xt Library.

   Copyright (C) 1995 Free Software Foundation, Inc.

   Written by:  Adam Fedor <fedor@boulder.colorado.edu>
   Date: Nov 1995
   
   This file is part of the GNU Objective C User Interface Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.
   
   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */

#include "XtDrawContext.h"
#include "XtDrawObject.h"
#include "XtGStateOps.h"
#include "xttools.h"
#include "cgt.h"
#include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSData.h>
#include <Foundation/NSValue.h>
#include <Foundation/NSString.h>
#include <objects/Stack.h>
#include <objc/hashtable.h>

#include "XtDrawPrivate.h"

static NSMutableDictionary *globalfontdir;
static NSMutableArray *fontid;

const char * dpsclientXtDrawContextWraps();

static const float *
ctxt_obj2matrix(NSData *obj)
{
  return (float *)[obj bytes];
}

static NSMutableData *
ctxt_matrix2obj(const float *m)
{
  return [NSMutableData dataWithBytes:(void *)m length: 6*sizeof(float)];
}

/* Motif compatability functions */
void 
PSgsaveview( void *aView )
{
  [(XtDrawContext *)currentContext gsaveWithView: aView];
}

void 
PSgstateview( void *aView )
{
  [(XtDrawContext *)currentContext gstateWithView: aView];
}

void 
PSgstateobject( int gst, void **gstateobj )
{
  if (gstateobj)
    *gstateobj = [(XtDrawContext *)currentContext gstateObject: gst];
}

void 
PSxwcontext(XWContext *xwcontext)
{
  if (xwcontext)
    *xwcontext = [(XtDrawContext *)currentContext XWContext];
}

/* Extra routines */
void 
PSwindowdeviceview( int num, void *aView)
{
  [(XtDrawContext *)currentContext DPSwindowdeviceview: num : aView];
}

void 
PSaddwindow(Widget window, float x, float y, float w, float h,
	    int type, int *num)
{
  [(XtDrawContext *)currentContext addwindow: window : x : y : w : h 
            : type : num];
}

@interface XtDrawContext (Private)
- (void) _checkFontDir;
- (void) _findXFont: (font_t *)font;
@end

@implementation XtDrawContext 

+ alloc
{
  return [self allocWithZone: globalZone];
}

- _initVars
{
  int		screen;
  Visual	*visual;
  
  alloc_mode = alloc_local;
  localZone = NSCreateZone(vm_page_size, vm_page_size, YES);

  /* Dummy function to force loading of categories */
  dpsclientXtDrawContextWraps();

  /* Initialize lists and stacks */
  opstack = [[Stack allocWithZone: [self zone]] init];
  gstack = [[Stack allocWithZone: [self zone]] init];
  glist  = [[NSMutableArray allocWithZone: [self zone]] initWithCapacity: 32];
  
  /* gstate index of 0 indicates no gstate, thus we put a dummy object at 0.
     Then create a default gstate */
  [glist addObject: [CTXT_OBJ_ALLOC(NSObject) init]];
  gstate = [CTXT_OBJ_ALLOC(XtGState) initWithDrawContext: self];
  [glist addObject: gstate];

  /* Get the visual information */
  /* FIXME: Need a better way to choose the best visual */
  screen = DefaultScreen(xwctxt.display);
  visual = DefaultVisual(xwctxt.display, screen);
  if (!XMatchVisualInfo(xwctxt.display,
			screen,
			DefaultDepth(xwctxt.display, screen),
			visual->class,
			&xwctxt.vinfo))
    {
      INVOKE_ERROR_VAL(DPSconfigurationerror, 
		       @"Problem getting visual information", 0);
    }

  /* Create/Use the standard colormap */
  xtDefaultColormap([self XWContext]);

  return self;
}

- initContext: (const char *)hostName : (const char *)serverName
	: (DPSTextProc)textProc : (DPSErrorProc)errorProc
	timeout: (int)timeout 
{
  char *display_name;

  [super initContext: hostName : serverName : textProc : errorProc
   timeout: timeout];

  display_name = NULL;
  if (hostName)
    {
      OBJC_MALLOC(display_name, char, strlen(hostName)+10);
      sprintf(display_name, "%s:0.0", hostName);
    }
  xwctxt.display = XOpenDisplay(display_name);
  OBJC_FREE(display_name);
  /* FIXME: should we abort if we can't open the display? */
  if (!xwctxt.display)
    {
      INVOKE_ERROR_VAL(DPSconfigurationerror, @"Unable to open display", 0);
    }

  [self _initVars];
  dpsctxt.type = dps_xtServer;
  return self;
}

/* Compatible init methods. This method is for use with applications
   that use their own widget set but still want a DrawContext to draw
   in a view (aka Motif). Here we assume the display was already
   opened and initialized. */
- initWithDisplay: (Display *)XDisplay
{
  [super init];
  xwctxt.display = XDisplay;
  [self _initVars];
  
  /* Another widget set will handle these, so we shouldn't */
  dontHandleEvents = YES;
  dontHandleWidgets = YES;
  return self;
}

- (void) dealloc
{
  [opstack release];
  [gstack release];
  [glist release];
  [localfontdir release];
  NSDestroyZone(localZone);
  [super dealloc];
}

- (XWContext) XWContext
{
  xwctxt.gstate  = gstate;
  xwctxt.ctxt    = [self contextId];
  return &xwctxt;
}

- (XtGState *) gstateObject: (int)gst
{
  return [glist objectAtIndex:gst];
}

- (void) gsaveWithView: (View *)view
{
  [gstack pushObject: gstate];
  gstate = [gstate copyWithView: view];
}

- (void) gstateWithView: (View *)view
{
  [gstack pushObject: gstate];
  gstate = [gstate copyWithView: view];
  [glist addObject: gstate];
  [self DPSsendint: [glist indexOfObject: gstate]];
}

- (Region)viewclipRegion
{
  return viewclip;
}

- (void) setViewclipRegion: (Region)region;
{
  if (viewclip)
    XDestroyRegion(viewclip);
  viewclip = region;
}

@end

@implementation XtDrawContext (ColorOps)

- (void)DPScolorimage 
{
}

- (void)DPScurrentblackgeneration 
{
}

- (void)DPScurrentcmykcolor: (float *)c : (float *)m : (float *)y : (float *)k 
{
  [gstate DPScurrentcmykcolor:c :m :y :k];
}

- (void)DPScurrentcolorscreen 
{
}

- (void)DPScurrentcolortransfer 
{
}

- (void)DPScurrentundercolorremoval 
{
}

- (void)DPSsetblackgeneration 
{
}

- (void)DPSsetcmykcolor: (float)c : (float)m : (float)y : (float)k 
{
  [gstate DPSsetcmykcolor:c :m :y :k];
}

- (void)DPSsetcolorscreen 
{
}

- (void)DPSsetcolortransfer 
{
}

- (void)DPSsetundercolorremoval 
{
}

@end

@implementation XtDrawContext (ControlOps)

- (void)DPSeq 
{
}

- (void)DPSexit 
{
}

- (void)DPSfalse 
{
}

- (void)DPSfor 
{
}

- (void)DPSforall 
{
}

- (void)DPSge 
{
}

- (void)DPSgt 
{
}

- (void)DPSif 
{
}

- (void)DPSifelse 
{
}

- (void)DPSle 
{
}

- (void)DPSloop 
{
}

- (void)DPSlt 
{
}

- (void)DPSne 
{
}

- (void)DPSnot 
{
}

- (void)DPSor 
{
}

- (void)DPSrepeat 
{
}

- (void)DPSstop 
{
}

- (void)DPSstopped 
{
}

- (void)DPStrue 
{
}

@end

@implementation XtDrawContext (CtxOps)

- (void)DPScondition 
{
}

- (void)DPScurrentcontext: (int *)cid 
{
  CHECK_NULL_OUTPUT(cid);
  *cid = [self contextId];
}

- (void)DPScurrentobjectformat: (int *)code 
{
}

- (void)DPSdefineusername: (int)i : (const char *)username 
{
}

- (void)DPSdefineuserobject 
{
}

- (void)DPSdetach 
{
}

- (void)DPSexecuserobject: (int)index 
{
}

- (void)DPSfork 
{
}

- (void)DPSjoin 
{
}

- (void)DPSlock 
{
}

- (void)DPSmonitor 
{
}

- (void)DPSnotify 
{
}

- (void)DPSsetobjectformat: (int)code 
{
}

- (void)DPSsetvmthreshold: (int)i 
{
}

- (void)DPSundefineuserobject: (int)index 
{
}

- (void)DPSuserobject 
{
}

- (void)DPSwait 
{
}

- (void)DPSyield 
{
}

@end

@implementation XtDrawContext (DataOps)

- (void)DPSaload 
{
  int i, count;
  NSMutableArray *array;

  ctxt_pop(array, opstack);
  [self _check_typecheck:array class: [NSMutableArray class]];
  count = [array count];
  for (i=0; i < count; i++)
    [opstack pushObject: [array objectAtIndex:i]];
  [opstack pushObject: array];
}

- (void)DPSanchorsearch: (int *)truth 
{
}

- (void)DPSarray: (int)len 
{
  int i;
  NSMutableArray *array;

  array = [CTXT_OBJ_ALLOC(NSMutableArray) initWithCapacity: len];
  for (i=0; i < len; i++)
    [array addObject: [CTXT_OBJ_ALLOC(NSObject) init]];
  [opstack pushObject: array];
}

- (void)DPSastore 
{
  int i, count;
  NSMutableArray *array;

  ctxt_pop(array, opstack);
  [self _check_typecheck:array class: [NSMutableArray class]];
  count = [array count];
  for (i=0; i < count; i++)
    {
      NSObject *obj;
      ctxt_pop(obj, opstack);
      [self _check_invalidaccess: obj zone: [array zone]];
      [array replaceObjectAtIndex: count - i - 1 withObject: obj];
    }
  [opstack pushObject: array];
}

- (void)DPSbegin 
{
}

- (void)DPSclear 
{
  int count;
  count = [opstack count];
  while (count--)
    [opstack popObject];
}

- (void)DPScleartomark 
{
  int count;
  count = [opstack count];
  while (count--)
    {
      NSObject *obj = [opstack popObject];
      if ([obj isKindOfClass:[XtDrawObject class]]
	  && [(XtDrawObject *)obj drawType] == ctxt_mark)
	return;
    }
}

- (void)DPScopy: (int)n 
{
}

- (void)DPScount: (int *)n 
{
  CHECK_NULL_OUTPUT(n);
  *n = [opstack count];
}

- (void)DPScounttomark: (int *)n 
{
}

- (void)DPScvi 
{
}

- (void)DPScvlit 
{
}

- (void)DPScvn 
{
}

- (void)DPScvr 
{
}

- (void)DPScvrs 
{
}

- (void)DPScvs 
{
}

- (void)DPScvx 
{
}

- (void)DPSdef 
{
}

- (void)DPSdict: (int)len 
{
}

- (void)DPSdictstack 
{
}

- (void)DPSdup 
{
}

- (void)DPSend 
{
}

- (void)DPSexch 
{
}

- (void)DPSexecstack 
{
}

- (void)DPSexecuteonly 
{
}

- (void)DPSget 
{
}

- (void)DPSgetinterval 
{
}

- (void)DPSindex: (int)i 
{
}

- (void)DPSknown: (int *)b 
{
}

- (void)DPSlength: (int *)len 
{
}

- (void)DPSload 
{
}

- (void)DPSmark 
{
}

- (void)DPSmatrix 
{
}

- (void)DPSmaxlength: (int *)len 
{
}

- (void)DPSnoaccess 
{
}

- (void)DPSnull 
{
}

- (void)DPSpackedarray 
{
}

- (void)DPSpop 
{
}

- (void)DPSput 
{
}

- (void)DPSputinterval 
{
}

- (void)DPSrcheck: (int *)b 
{
}

- (void)DPSreadonly 
{
}

- (void)DPSroll: (int)n : (int)j 
{
}

- (void)DPSscheck: (int *)b 
{
}

- (void)DPSsearch: (int *)b 
{
}

- (void)DPSshareddict 
{
}

- (void)DPSstatusdict 
{
}

- (void)DPSstore 
{
}

- (void)DPSstring: (int)len 
{
}

- (void)DPSstringwidth: (const char *)s : (float *)xp : (float *)yp 
{
}

- (void)DPSsystemdict 
{
}

- (void)DPSuserdict 
{
}

- (void)DPSwcheck: (int *)b 
{
}

- (void)DPSwhere: (int *)b 
{
}

- (void)DPSxcheck: (int *)b 
{
}

@end

@implementation XtDrawContext (FontOps)

/* Takes a font name stored in font.name and tries to find the X11 font
   information for that font. If the the font name does not begin with a
   '-', then it is assumed to be a standard PostScript name that should
   be converted to the X11 font name format. */
- (void) _findXFont: (font_t *)font
{
  int i, len;
  char   buf[1024];

  /* Try to convert the font name into a X11 font name */
  if (font->name[0] != '-')
    {
      char *s;
      len = strlen(font->name);
      font->internal_name = copy_string_buffer(font->name);
      for (i=0; i < len; i++)
	font->internal_name[i] = tolower(font->internal_name[i]);
      if (font->weight == 0)
	font->weight = "medium";
      if (font->slant == 0)
	font->slant  = 'r';
      if (font->size == 0)
	font->size   = 120;
      s = strchr(font->internal_name, '-');
      if (s)
	{
	  switch(*s) 
	    {
	    case 'b': font->weight = "bold"; break;
	    case 'd': font->weight = "demibold"; break;
	    case 'o': font->slant  = 'o'; break;
	    case 'i': font->slant  = 'i'; break;
	    default:
	    }
	}
      sprintf(buf, "-*-%s-%s-%c-*-%d-*", font->internal_name,
	      font->weight, font->slant, (int)font->size);
      free(font->internal_name);
      font->internal_name = NULL;
    }
  else
    strcpy(buf, font->name);

  font->info = XLoadQueryFont(xwctxt.display, buf);
  if (font->info)
    {
      font->internal_name = copy_string_buffer(buf);
      font->id   = font->info->fid;
    }
}

- (void) _checkFontDir
{
  if (alloc_mode == alloc_local)
    {
      if (localfontdir == nil)
	localfontdir = [CTXT_OBJ_ALLOC(NSMutableDictionary) init];
    }
  else
    {
      if (globalfontdir == nil)
	globalfontdir = [CTXT_OBJ_ALLOC(NSMutableDictionary) init];
    }
  if (fontid == nil)
    fontid = [NSMutableArray arrayWithCapacity:32];
}

- (void)DPSFontDirectory 
{
}

- (void)DPSISOLatin1Encoding 
{
}

- (void)DPSSharedFontDirectory 
{
}

- (void)DPSStandardEncoding 
{
}

- (void)DPScachestatus: (int *)bsize : (int *)bmax : (int *)msize 
{
}

- (void)DPScurrentcacheparams 
{
}

- (void)DPScurrentfont 
{
  int ident;
  [self _checkFontDir];
  ident = [fontid indexOfObject: fontobj];
  [opstack pushObject: [NSNumber numberWithLong: ident]];
}

- (void)DPSdefinefont 
{
  [self DPSdefineresource: "Font"];
}

- (void)DPSfindfont: (const char *)name 
{
  [self DPSfindresource: name : "Font"];
}

- (void)DPSmakefont 
{
}

- (void)DPSscalefont: (float)size 
{
  id obj;
  int ident;
  font_t font;

  ctxt_pop(obj, opstack);
  [self _check_typecheck:obj class: [NSNumber class]];
  ident = [obj longValue];
  [self _check_invalidfont: ident];

  obj = [fontid objectAtIndex:ident];
  [obj getValue:&font];
  font.size = size * 10;

  /* Try to find a X font that matches this size */
  [self _findXFont: &font];
  if (font.internal_name != NULL)
    {
      obj = [NSValue value: &font withObjCType: @encode(font_t)];
      ident = [fontid count];
      [fontid addObject: obj];
    }
  [opstack pushObject: [NSNumber numberWithLong: ident]];
}

- (void)DPSselectfont: (const char *)name : (float)scale 
{
}

- (void)DPSsetcachedevice: (float)wx : (float)wy : (float)llx : (float)lly : (float)urx : (float)ury 
{
}

- (void)DPSsetcachelimit: (float)n 
{
}

- (void)DPSsetcacheparams 
{
}

- (void)DPSsetcharwidth: (float)wx : (float)wy 
{
}

- (void)DPSsetfont: (int)f 
{
  font_t font;
  [self _check_invalidfont: f];
  fontobj = [fontid objectAtIndex: f];
  [fontobj getValue:&font];
  [gstate setFont: font.id];
}

- (void)DPSundefinefont: (const char *)name 
{
}

@end

@implementation XtDrawContext (GStateOps)

- (void)DPSconcat: (const float *)m 
{
  [gstate DPSconcat: m];
}

- (void)DPScurrentdash 
{
}

- (void)DPScurrentflat: (float *)flatness 
{
}

- (void)DPScurrentgray: (float *)gray 
{
  CHECK_NULL_OUTPUT(gray);
  [gstate DPScurrentgray: gray];
}

/* FIXME: I don't think this does the same thing as the PS operator of the
   same name.  Does it change the current gstate? */
- (void)DPScurrentgstate: (int)gst 
{
}

- (void)DPScurrenthalftone 
{
}

- (void)DPScurrenthalftonephase: (float *)x : (float *)y 
{
}

- (void)DPScurrenthsbcolor: (float *)h : (float *)s : (float *)b 
{
  CHECK_NULL_OUTPUT(h);
  CHECK_NULL_OUTPUT(s);
  CHECK_NULL_OUTPUT(b);
  [gstate DPScurrenthsbcolor:h :s :b];
}

- (void)DPScurrentlinecap: (int *)linecap 
{
  [gstate DPScurrentlinecap: linecap];
}

- (void)DPScurrentlinejoin: (int *)linejoin 
{
  [gstate DPScurrentlinejoin: linejoin];
}

- (void)DPScurrentlinewidth: (float *)width 
{
  [gstate DPScurrentlinewidth: width];
}

- (void)DPScurrentmatrix 
{
  NSMutableData *obj;

  ctxt_pop(obj, opstack);
  [self _check_typecheck:obj class: [NSMutableData class]];
  [gstate DPScurrentmatrix: [obj mutableBytes]];
  [opstack pushObject:obj];
}

- (void)DPScurrentmiterlimit: (float *)limit 
{
}

- (void)DPScurrentpoint: (float *)x : (float *)y 
{
  CHECK_NULL_OUTPUT(x);
  CHECK_NULL_OUTPUT(y);
  [gstate DPScurrentpoint:x :y];
}

- (void)DPScurrentrgbcolor: (float *)r : (float *)g : (float *)b 
{
  CHECK_NULL_OUTPUT(r);
  CHECK_NULL_OUTPUT(g);
  CHECK_NULL_OUTPUT(b);
  [gstate DPScurrentrgbcolor:r :g :b];
}

- (void)DPScurrentscreen 
{
}

- (void)DPScurrentstrokeadjust: (int *)b 
{
}

- (void)DPScurrenttransfer 
{
}

- (void)DPSdefaultmatrix 
{
}

- (void)DPSgrestore 
{
  [gstate flushRectIfNeeded:NULL];
  [gstate release];
  ctxt_pop(gstate, gstack);
  [gstate retain];
}

- (void)DPSgrestoreall 
{
}

- (void)DPSgsave 
{
  [gstack pushObject: gstate];
  gstate = [gstate copy];
}

- (void)DPSgstate 
{
  [gstack pushObject: gstate];
  gstate = [gstate copy];
  [glist addObject: gstate];
  [self DPSsendint: [glist indexOfObject: gstate]];
}

- (void)DPSinitgraphics 
{
  [gstate DPSinitgraphics];
}

- (void)DPSinitmatrix 
{
  [gstate DPSinitmatrix];
}

- (void)DPSrotate: (float)angle 
{
  [gstate DPSrotate: angle];
}

- (void)DPSscale: (float)x : (float)y 
{
  [gstate DPSscale:x :y];
}

- (void)DPSsetdash: (const float *)pat : (int)size : (float)offset 
{
}

- (void)DPSsetflat: (float)flatness 
{
}

- (void)DPSsetgray: (float)gray 
{
  [gstate DPSsetgray: gray];
}

- (void)DPSsetgstate: (int)gst 
{
  if (gst < 0 || gst >= [glist count])
    INVOKE_ERROR(DPSinvalidparam, @"Gstate not defined for given index");
  gstate = [glist objectAtIndex: gst];
}

- (void)DPSsethalftone 
{
}

- (void)DPSsethalftonephase: (float)x : (float)y 
{
}

- (void)DPSsethsbcolor: (float)h : (float)s : (float)b 
{
  [gstate DPSsethsbcolor:h :s :b];
}

- (void)DPSsetlinecap: (int)linecap 
{
  [gstate DPSsetlinecap: linecap];
}

- (void)DPSsetlinejoin: (int)linejoin 
{
  [gstate DPSsetlinejoin: linejoin];
}

- (void)DPSsetlinewidth: (float)width 
{
  [gstate DPSsetlinewidth: width];
}

- (void)DPSsetmatrix 
{
  NSMutableData *obj;

  ctxt_pop(obj, opstack);

  [self _check_typecheck:obj class: [NSMutableData class]];
  [gstate DPSsetmatrix: ctxt_obj2matrix(obj)];
}

- (void)DPSsetmiterlimit: (float)limit 
{
}

- (void)DPSsetrgbcolor: (float)r : (float)g : (float)b 
{
  [gstate DPSsetrgbcolor:r :g :b];
}

- (void)DPSsetscreen 
{
}

- (void)DPSsetstrokeadjust: (int)b 
{
}

- (void)DPSsettransfer 
{
}

- (void)DPStranslate: (float)x : (float)y 
{
  [gstate DPStranslate:x :y];
}

@end

@implementation XtDrawContext (IOOps)

- (void)DPSequals 
{
}

- (void)DPSequalsequals 
{
}

- (void)DPSbytesavailable: (int *)n 
{
}

- (void)DPSclosefile 
{
}

- (void)DPScurrentfile 
{
}

- (void)DPSdeletefile: (const char *)filename 
{
}

- (void)DPSecho: (int)b 
{
}

- (void)DPSfile: (const char *)name : (const char *)access 
{
}

- (void)DPSfilenameforall 
{
}

- (void)DPSfileposition: (int *)pos 
{
}

- (void)DPSflush 
{
}

- (void)DPSflushfile 
{
}

- (void)DPSprint 
{
}

- (void)DPSprintobject: (int)tag 
{
}

- (void)DPSpstack 
{
}

- (void)DPSread: (int *)b 
{
}

- (void)DPSreadhexstring: (int *)b 
{
}

- (void)DPSreadline: (int *)b 
{
}

- (void)DPSreadstring: (int *)b 
{
}

- (void)DPSrenamefile: (const char *)old : (const char *)new 
{
}

- (void)DPSresetfile 
{
}

- (void)DPSsetfileposition: (int)pos 
{
}

- (void)DPSstack 
{
}

- (void)DPSstatus: (int *)b 
{
}

- (void)DPStoken: (int *)b 
{
}

- (void)DPSwrite 
{
}

- (void)DPSwritehexstring 
{
}

- (void)DPSwriteobject: (int)tag 
{
}

- (void)DPSwritestring 
{
}

@end

@implementation XtDrawContext (MathOps)

- (void)DPSabs 
{
}

- (void)DPSadd 
{
}

- (void)DPSand 
{
}

- (void)DPSatan 
{
}

- (void)DPSbitshift: (int)shift 
{
}

- (void)DPSceiling 
{
}

- (void)DPScos 
{
}

- (void)DPSdiv 
{
}

- (void)DPSexp 
{
}

- (void)DPSfloor 
{
}

- (void)DPSidiv 
{
}

- (void)DPSln 
{
}

- (void)DPSlog 
{
}

- (void)DPSmod 
{
}

- (void)DPSmul 
{
}

- (void)DPSneg 
{
}

- (void)DPSround 
{
}

- (void)DPSsin 
{
}

- (void)DPSsqrt 
{
}

- (void)DPSsub 
{
}

- (void)DPStruncate 
{
}

- (void)DPSxor 
{
}

@end

@implementation XtDrawContext (MatrixOps)

- (void)DPSconcatmatrix
{
  NSMutableData *obj1, *obj2, *obj3;
  cgt_t cgt1, cgt2;

  ctxt_pop(obj3, opstack);
  [self _check_typecheck:obj3 class: [NSMutableData class]];
  ctxt_pop(obj2, opstack);
  [self _check_typecheck:obj2 class: [NSMutableData class]];
  ctxt_pop(obj1, opstack);
  [self _check_typecheck:obj1 class: [NSMutableData class]];
  cgt1 = matrixToCgt(ctxt_obj2matrix(obj1));
  cgt2 = matrixToCgt(ctxt_obj2matrix(obj2));
  cgt1 = concatCGT(cgt1, cgt2);
  obj3 = ctxt_matrix2obj(cgtToMatrix(cgt1));

  [opstack pushObject:obj3];
}

- (void)DPSdtransform: (float)x1 : (float)y1 : (float *)x2 : (float *)y2 
{
  NSMutableData *obj;
  NSPoint point;
  cgt_t cgt;

  ctxt_pop(obj, opstack);
  if (![obj isKindOfClass: [NSMutableData class]])
    {
      [opstack pushObject: obj];
      [self DPScurrentmatrix];
      ctxt_pop(obj, opstack);
    }
  cgt = matrixToCgt(ctxt_obj2matrix(obj));
  cgt.tx = 0; cgt.ty = 0;
  point.x = x1; point.y = y1;
  point = applyCGT(point, cgt);
  *x2 = point.x;
  *y2 = point.y;
}

- (void)DPSidentmatrix 
{
  NSMutableData *obj;

  ctxt_pop(obj, opstack);
  [self _check_typecheck:obj class: [NSMutableData class]];
  obj = ctxt_matrix2obj(cgtToMatrix(composeCGT(NULL, 0, NULL)));
  [opstack pushObject: obj];
}

- (void)DPSidtransform: (float)x1 : (float)y1 : (float *)x2 : (float *)y2 
{
  NSMutableData *obj;
  NSPoint point;
  cgt_t cgt;

  ctxt_pop(obj, opstack);
  if (![obj isKindOfClass: [NSMutableData class]])
    {
      [opstack pushObject: obj];
      [self DPScurrentmatrix];
      ctxt_pop(obj, opstack);
    }
  cgt = invertCGT(matrixToCgt(ctxt_obj2matrix(obj)));
  cgt.tx = 0; cgt.ty = 0;
  point.x = x1; point.y = y1;
  point = applyCGT(point, cgt);
  *x2 = point.x;
  *y2 = point.y;
}

- (void)DPSinvertmatrix 
{
  NSMutableData *obj, *obj2;
  cgt_t cgt;

  ctxt_pop(obj, opstack);
  [self _check_typecheck:obj class: [NSMutableData class]];
  ctxt_pop(obj2, opstack);
  [self _check_typecheck:obj2 class: [NSMutableData class]];
  cgt = matrixToCgt(ctxt_obj2matrix(obj));
  cgt = invertCGT(cgt);
  obj = ctxt_matrix2obj(cgtToMatrix(cgt));
  [opstack pushObject: obj];
}

- (void)DPSitransform: (float)x1 : (float)y1 : (float *)x2 : (float *)y2 
{
  NSMutableData *obj;
  NSPoint point;
  cgt_t cgt;

  ctxt_pop(obj, opstack);
  if (![obj isKindOfClass: [NSMutableData class]])
    {
      [opstack pushObject: obj];
      [self DPScurrentmatrix];
      ctxt_pop(obj, opstack);
    }
  cgt = invertCGT(matrixToCgt(ctxt_obj2matrix(obj)));
  cgt.tx = 0; cgt.ty = 0;
  point.x = x1; point.y = y1;
  point = applyCGT(point, cgt);
  *x2 = point.x;
  *y2 = point.y;
}

- (void)DPStransform: (float)x1 : (float)y1 : (float *)x2 : (float *)y2 
{
  NSMutableData *obj;
  NSPoint point;
  cgt_t cgt;

  ctxt_pop(obj, opstack);
  if (![obj isKindOfClass: [NSMutableData class]])
    {
      [opstack pushObject: obj];
      [self DPScurrentmatrix];
      ctxt_pop(obj, opstack);
    }
  cgt = matrixToCgt(ctxt_obj2matrix(obj));
  cgt.tx = 0; cgt.ty = 0;
  point.x = x1; point.y = y1;
  point = applyCGT(point, cgt);
  *x2 = point.x;
  *y2 = point.y;
}

@end

@implementation XtDrawContext (MiscOps)

- (void)DPSbanddevice 
{
}

- (void)DPSframedevice 
{
}

- (void)DPSnulldevice 
{
}

- (void)DPSrenderbands 
{
}

@end

@implementation XtDrawContext (Opstack)

- (void)DPSgetboolean: (int *)it 
{
  NSNumber *number;
  CHECK_NULL_OUTPUT(it);
  ctxt_pop(number, opstack);
  [self _check_typecheck: number class: [NSNumber class]];
  *it = [number boolValue];
}

- (void)DPSgetchararray: (int)size : (char *)s 
{
  NSMutableData *data;
  CHECK_NULL_OUTPUT(s);
  ctxt_pop(data, opstack);
  [self _check_typecheck: data class: [NSMutableData class]];
  memcpy(s, [data bytes], size*sizeof(char));
}

- (void)DPSgetfloat: (float *)it 
{
  NSNumber *number;
  CHECK_NULL_OUTPUT(it);
  ctxt_pop(number, opstack);
  [self _check_typecheck: number class: [NSNumber class]];
  *it = [number floatValue];
}

- (void)DPSgetfloatarray: (int)size : (float *)a 
{
  NSMutableData *data;
  CHECK_NULL_OUTPUT(a);
  ctxt_pop(data, opstack);
  [self _check_typecheck: data class: [NSMutableData class]];
  memcpy(a, [data bytes], size*sizeof(float));
}

- (void)DPSgetint: (int *)it 
{
  NSNumber *number;
  CHECK_NULL_OUTPUT(it);
  ctxt_pop(number, opstack);
  [self _check_typecheck: number class:[NSNumber class]];
  *it = [number intValue];
}

- (void)DPSgetintarray: (int)size : (int *)a 
{
  NSMutableData *data;
  CHECK_NULL_OUTPUT(a);
  ctxt_pop(data, opstack);
  [self _check_typecheck: data class: [NSMutableData class]];
  memcpy(a, [data bytes], size*sizeof(int));
}

- (void)DPSgetstring: (char *)s 
{
  NSString *str;
  CHECK_NULL_OUTPUT(s);
  ctxt_pop(str, opstack);
  [self _check_typecheck: str class: [NSString class]];
  strcpy(s, [str cString]);
}

- (void)DPSsendboolean: (int)it 
{
  [opstack pushObject: [NSNumber numberWithBool: it]];
}

- (void)DPSsendchararray: (const char *)s : (int)size 
{
  NSMutableData *data;
  data = [NSMutableData dataWithBytes: s length: size*sizeof(char)];
  [opstack pushObject: data];
}

- (void)DPSsendfloat: (float)it 
{
  [opstack pushObject: [NSNumber numberWithFloat: it]];
}

- (void)DPSsendfloatarray: (const float *)a : (int)size 
{
  NSMutableData *data;
  data = [NSMutableData dataWithBytes: a length: size*sizeof(float)];
  [opstack pushObject: data];
}

- (void)DPSsendint: (int)it 
{
  [opstack pushObject: [NSNumber numberWithInt: it]];
}

- (void)DPSsendintarray: (const int *)a : (int)size 
{
  NSMutableData *data;
  data = [NSMutableData dataWithBytes: a length: size*sizeof(int)];
  [opstack pushObject: data];
}

- (void)DPSsendstring: (const char *)s 
{
  [opstack pushObject: [NSString stringWithCString: s]];
}

@end

@implementation XtDrawContext (PaintOps)

- (void)DPSashow: (float)x : (float)y : (const char *)s 
{
  [gstate DPSashow: x : y : s];
}

- (void)DPSawidthshow: (float)cx : (float)cy : (int)c : (float)ax : (float)ay : (const char *)s 
{
  [gstate DPSawidthshow: cx : cy : c : ax : ay : s];
}

- (void)DPScopypage 
{
}

- (void)DPSeofill 
{
  [gstate DPSeofill];
}

- (void)DPSerasepage 
{
}

- (void)DPSfill 
{
  [gstate DPSfill];
}

- (void)DPSimage 
{
}

- (void)DPSimagemask 
{
}

- (void)DPSkshow: (const char *)s 
{
}

- (void)DPSrectfill: (float)x : (float)y : (float)w : (float)h 
{
  [gstate DPSrectfill:x :y :w :h];
}

- (void)DPSrectstroke: (float)x : (float)y : (float)w : (float)h 
{
  [gstate DPSrectstroke:x :y :w :h];
}

- (void)DPSshow: (const char *)s 
{
}

- (void)DPSshowpage 
{
}

- (void)DPSstroke 
{
  [gstate DPSstroke];
}

- (void)DPSstrokepath 
{
  [gstate DPSstrokepath];
}

- (void)DPSueofill: (const char *)nums : (int)n : (const char *)op : (int)l 
{
}

- (void)DPSufill: (const char *)nums : (int)n : (const char *)ops : (int)l 
{
}

- (void)DPSustroke: (const char *)nums   : (int)n : (const char *)ops : (int)l 
{
}

- (void)DPSustrokepath: (const char *)nums : (int)n : (const char *)ops : (int)l 
{
}

- (void)DPSwidthshow: (float)x : (float)y : (int)c : (const char *)s 
{
  [gstate DPSwidthshow: x : y : c : s];
}

- (void)DPSxshow: (const char *)s : (const float *)numarray : (int)size 
{
  [gstate DPSxshow: s : numarray : size];
}

- (void)DPSxyshow: (const char *)s : (const float *)numarray : (int)size 
{
  [gstate DPSxyshow: s : numarray : size];
}

- (void)DPSyshow: (const char *)s : (const float *)numarray : (int)size 
{
  [gstate DPSyshow: s : numarray : size];
}

@end

@implementation XtDrawContext (PathOps)

- (void)DPSarc: (float)x : (float)y : (float)r : (float)angle1 : (float)angle2 
{
  [gstate DPSarc: x : y : r : angle1 : angle2];
}

- (void)DPSarcn: (float)x : (float)y : (float)r : (float)angle1 : (float)angle2 
{
  [gstate DPSarc: x : y : r : angle1 : angle2];
}

- (void)DPSarct: (float)x1 : (float)y1 : (float)x2 : (float)y2 : (float)r 
{
  [gstate DPSarc: x1 : y1 : x2 : y2 : r];
}

- (void)DPSarcto: (float)x1 : (float)y1 : (float)x2 : (float)y2 : (float)r : (float *)xt1 : (float *)yt1 : (float *)xt2 : (float *)yt2 
{
  [gstate DPSarcto: x1 : y1 : x2 : y2 : r : xt1 : yt1 : xt2 : yt2];
}

- (void)DPScharpath: (const char *)s : (int)b 
{
}

- (void)DPSclip 
{
  [gstate DPSclip];
}

- (void)DPSclippath 
{
  [gstate DPSclippath];
}

- (void)DPSclosepath 
{
  [gstate DPSclosepath];
}

- (void)DPScurveto: (float)x1 : (float)y1 : (float)x2 : (float)y2 : (float)x3 : (float)y3 
{
  [gstate DPScurveto: x1 : y1 : x2 : y2 : x3 : y3];
}

- (void)DPSeoclip 
{
  [gstate DPSeoclip];
}

- (void)DPSeoviewclip 
{
  [gstate DPSeoviewclip];
}

- (void)DPSflattenpath 
{
  [gstate DPSflattenpath];
}

- (void)DPSinitclip 
{
  [gstate DPSinitclip];
}

- (void)DPSinitviewclip 
{
  [gstate DPSinitviewclip];
}

- (void)DPSlineto: (float)x : (float)y 
{
  [gstate DPSlineto: x : y];
}

- (void)DPSmoveto: (float)x : (float)y 
{
  [gstate DPSmoveto: x : y];
}

- (void)DPSnewpath 
{
  [gstate DPSnewpath];
}

- (void)DPSpathbbox: (float *)llx : (float *)lly : (float *)urx : (float *)ury 
{
  [gstate DPSpathbbox: llx : lly : urx : ury];
}

- (void)DPSpathforall 
{
  [gstate DPSpathforall];
}

- (void)DPSrcurveto: (float)x1 : (float)y1 : (float)x2 : (float)y2 : (float)x3 : (float)y3 
{
  [gstate DPSrcurveto: x1 : y1 : x2 : y2 : x3 : y3];
}

- (void)DPSrectclip: (float)x : (float)y : (float)w : (float)h 
{
  [gstate DPSrectclip: x : y : w : h];
}

- (void)DPSrectviewclip: (float)x : (float)y : (float)w : (float)h 
{
  [gstate DPSrectviewclip: x : y : w : h];
}

- (void)DPSreversepath 
{
  [gstate DPSreversepath];
}

- (void)DPSrlineto: (float)x : (float)y 
{
  [gstate DPSrlineto: x : y];
}

- (void)DPSrmoveto: (float)x : (float)y 
{
  [gstate DPSrmoveto: x : y];
}

- (void)DPSsetbbox: (float)llx : (float)lly : (float)urx : (float)ury 
{
  [gstate DPSsetbbox: llx : lly : urx : ury];
}

- (void)DPSsetucacheparams 
{
}

- (void)DPSuappend: (const char *)nums : (int)n : (const char *)ops : (int)l 
{
}

- (void)DPSucache 
{
}

- (void)DPSucachestatus 
{
}

- (void)DPSupath: (int)b 
{
}

- (void)DPSviewclip 
{
  [gstate DPSviewclip];
}

- (void)DPSviewclippath 
{
}

@end

@implementation XtDrawContext (SysOps)

- (void)DPSbind 
{
}

- (void)DPScountdictstack: (int *)n 
{
}

- (void)DPScountexecstack: (int *)n 
{
}

- (void)DPScurrentdict 
{
}

- (void)DPScurrentpacking: (int *)b 
{
}

- (void)DPScurrentshared: (int *)b 
{
}

- (void)DPSdeviceinfo 
{
}

- (void)DPSerrordict 
{
}

- (void)DPSexec 
{
}

- (void)DPSprompt 
{
}

- (void)DPSquit 
{
}

- (void)DPSrand 
{
}

- (void)DPSrealtime: (int *)i 
{
}

- (void)DPSrestore 
{
}

- (void)DPSrrand 
{
}

- (void)DPSrun: (const char *)filename 
{
}

- (void)DPSsave 
{
}

- (void)DPSsetpacking: (int)b 
{
}

- (void)DPSsetshared: (int)b 
{
}

- (void)DPSsrand 
{
}

- (void)DPSstart 
{
}

- (void)DPStype 
{
}

- (void)DPSundef: (const char *)name 
{
}

- (void)DPSusertime: (int *)milliseconds 
{
}

- (void)DPSversion: (int)bufsize : (char *)buf
{
}

- (void)DPSvmreclaim: (int)code 
{
}

- (void)DPSvmstatus: (int *)level : (int *)used : (int *)maximum 
{
}

@end

@implementation XtDrawContext (WinOps)

- (void)DPSineofill: (float)x : (float)y : (int *)b 
{
}

- (void)DPSinfill: (float)x : (float)y : (int *)b 
{
}

- (void)DPSinstroke: (float)x : (float)y : (int *)b 
{
}

- (void)DPSinueofill: (float)x : (float)y : (const char *)nums : (int)n : (const char *)ops : (int)l : (int *)b 
{
}

- (void)DPSinufill: (float)x : (float)y : (const char *)nums : (int)n : (const char *)ops : (int)l : (int *)b 
{
}

- (void)DPSinustroke: (float)x : (float)y : (const char *)nums : (int)n  : (const char *)ops : (int)l : (int *)b 
{
}

- (void)DPSwtranslation: (float *)x : (float *)y 
{
}

@end

@implementation XtDrawContext (L2Ops)

- (void)DPSleftbracket 
{
}

- (void)DPSrightbracket 
{
}

- (void)DPSleftleft 
{
}

- (void)DPSrightright 
{
}

- (void)DPScshow: (const char *)s 
{
}

- (void)DPScurrentcolor 
{
}

- (void)DPScurrentcolorrendering 
{
}

- (void)DPScurrentcolorspace 
{
}

- (void)DPScurrentdevparams: (const char *)dev 
{
}

- (void)DPScurrentglobal: (int *)b 
{
}

- (void)DPScurrentoverprint: (int *)b 
{
}

- (void)DPScurrentpagedevice 
{
}

- (void)DPScurrentsystemparams 
{
}

- (void)DPScurrentuserparams 
{
}

- (void)DPSdefineresource: (const char *)category 
{
  id obj;
  NSString *key;
  NSMutableDictionary *local;
  NSMutableDictionary *global;

  ctxt_pop(obj, opstack);
  [self _check_typecheck: obj class: [NSNumber class]];
  ctxt_pop(key, opstack);
  [self _check_typecheck: key class:  [NSString class]];
  if (strcmp(category, "Font") == 0)
    {
      [self _checkFontDir];
      local = localfontdir;
      global = globalfontdir;
    }
  else
    {
      INVOKE_ERROR(DPSundefined, [NSString stringWithCString: category]);
    }

  if (alloc_mode == alloc_local)
    {
      [local setObject: obj forKey: key];
    }
  else
    {
      [local removeObjectForKey: key];
      [global setObject: obj forKey: key];
    }
  [opstack pushObject: obj];
}

- (void)DPSexecform 
{
}

- (void)DPSfilter 
{
}

- (void)DPSfindencoding: (const char *)key 
{
}

- (void)DPSfindresource: (const char *)key : (const char *)category 
{
  id obj;
  NSMutableDictionary *local;
  NSMutableDictionary *global;

  if (strcmp(category, "Font") == 0)
    {
      [self _checkFontDir];
      local = localfontdir;
      global = globalfontdir;
    }
  else
    {
      NSString *str = [NSString stringWithFormat: 
		       @"Could not find key %s", key];
      INVOKE_ERROR(DPSundefined, str);
    }

  obj = nil;
  if (alloc_mode != alloc_global)
    obj = [local objectForKey: [NSString stringWithCString:key]];
  if (obj == nil)
    obj = [global objectForKey: [NSString stringWithCString:key]];

  if (obj == nil)
    {
      if (strcmp(category, "Font") == 0)
	{
	  int ident;
	  font_t font;
	  font.name = copy_string_buffer(key);
	  [self _findXFont: &font];
	  if (font.internal_name != NULL)
	    {
	      ident = [fontid count];
	      obj = [NSValue value: &font withObjCType: @encode(font_t)];
	      [fontid addObject: obj];
	      obj = [NSNumber numberWithLong: ident];
	    }
	}
      if (obj == nil)
	{
	  NSString *str = [NSString stringWithFormat: 
			   @"Could not find resource %s", key];
	  INVOKE_ERROR(DPSundefinedresource, str);
	}
    }

  [opstack pushObject: obj];
}

- (void)DPSgcheck: (int *)b 
{
}

- (void)DPSglobaldict 
{
}

- (void)DPSGlobalFontDirectory 
{
}

- (void)DPSglyphshow: (const char *)name 
{
}

- (void)DPSlanguagelevel: (int *)n 
{
}

- (void)DPSmakepattern 
{
}

- (void)DPSproduct 
{
}

- (void)DPSresourceforall: (const char *)category 
{
}

- (void)DPSresourcestatus: (const char *)key : (const char *)category : (int *)b 
{
}

- (void)DPSrevision: (int *)n 
{
}

- (void)DPSrootfont 
{
}

- (void)DPSserialnumber: (int *)n 
{
}

- (void)DPSsetcolor 
{
}

- (void)DPSsetcolorrendering 
{
}

- (void)DPSsetcolorspace 
{
}

- (void)DPSsetdevparams 
{
}

- (void)DPSsetglobal: (int)b 
{
}

- (void)DPSsetoverprint: (int)b 
{
}

- (void)DPSsetpagedevice 
{
}

- (void)DPSsetpattern: (int)patternDict 
{
}

- (void)DPSsetsystemparams 
{
}

- (void)DPSsetuserparams 
{
}

- (void)DPSstartjob: (int)b : (const char *)password 
{
}

- (void)DPSundefineresource: (const char *)key : (const char *)category 
{
}

@end

@implementation XtDrawContext (PrivateError)

- (void) _check_invalidaccess: object zone: (NSZone *)need_zone
{
  NSZone *zone = [object zone];
  if (zone != globalZone && zone != need_zone)
    INVOKE_ERROR(DPSinvalidaccess, @"Allocating object from incorrect zone");
}

- (void) _check_invalidfont: (long)ident
{
  if (ident >= [fontid count])
    INVOKE_ERROR(DPSinvalidfont, @"Cannot find indicated font");
}

- (void) _check_stackunderflow: (Stack *)stack
{
  if ([stack count] == 0)
    INVOKE_ERROR(DPSstackunderflow, @"Attempt to pop from empty stack");
}

- (void) _check_typecheck: object class: (Class)kind
{
  if (![object isKindOf:[kind class]])
    INVOKE_ERROR(DPStypecheck, @"Invalid object");
}

@end
