Initial revision
authorStephen Adams <edu/mit/csail/zurich/adams>
Wed, 2 Aug 1995 21:28:26 +0000 (21:28 +0000)
committerStephen Adams <edu/mit/csail/zurich/adams>
Wed, 2 Aug 1995 21:28:26 +0000 (21:28 +0000)
46 files changed:
v7/src/swat/Makefile [new file with mode: 0644]
v7/src/swat/c/MITScheme.c [new file with mode: 0644]
v7/src/swat/c/Makefile [new file with mode: 0644]
v7/src/swat/c/scxl.c [new file with mode: 0644]
v7/src/swat/c/tk-c-mit.c [new file with mode: 0644]
v7/src/swat/c/tk-c.c [new file with mode: 0644]
v7/src/swat/c/tk3.2-custom/Makefile [new file with mode: 0644]
v7/src/swat/c/tk3.2-custom/library/emacs.tcl [new file with mode: 0644]
v7/src/swat/c/tk3.2-custom/tcl/Makefile [new file with mode: 0644]
v7/src/swat/c/tk3.2-custom/tcl/tclUnix.h [new file with mode: 0644]
v7/src/swat/c/tk3.2-custom/tkEvent.c [new file with mode: 0644]
v7/src/swat/c/tk3.2-custom/tkWindow.c [new file with mode: 0644]
v7/src/swat/c/uitk-prims.c [new file with mode: 0644]
v7/src/swat/c/widget-c-mit.c [new file with mode: 0644]
v7/src/swat/c/widget-c.c [new file with mode: 0644]
v7/src/swat/scheme/baseobj.scm [new file with mode: 0644]
v7/src/swat/scheme/canvas.scm [new file with mode: 0644]
v7/src/swat/scheme/control-floating-errors.scm [new file with mode: 0644]
v7/src/swat/scheme/generics.scm [new file with mode: 0644]
v7/src/swat/scheme/geometry.scm [new file with mode: 0644]
v7/src/swat/scheme/load.scm [new file with mode: 0644]
v7/src/swat/scheme/menu.scm [new file with mode: 0644]
v7/src/swat/scheme/mit-xhooks.scm [new file with mode: 0644]
v7/src/swat/scheme/mit-xlib.scm [new file with mode: 0644]
v7/src/swat/scheme/other/btest.scm [new file with mode: 0644]
v7/src/swat/scheme/other/doodle.scm [new file with mode: 0644]
v7/src/swat/scheme/other/exports.scm [new file with mode: 0644]
v7/src/swat/scheme/other/plotter.scm [new file with mode: 0644]
v7/src/swat/scheme/other/pole-zero.scm [new file with mode: 0644]
v7/src/swat/scheme/other/rtest.scm [new file with mode: 0644]
v7/src/swat/scheme/other/test-load.scm [new file with mode: 0644]
v7/src/swat/scheme/other/test.scm [new file with mode: 0644]
v7/src/swat/scheme/other/unhash-testing.scm [new file with mode: 0644]
v7/src/swat/scheme/scc-macros.scm [new file with mode: 0644]
v7/src/swat/scheme/simple.scm [new file with mode: 0644]
v7/src/swat/scheme/structures.scm [new file with mode: 0644]
v7/src/swat/scheme/structures2.scm [new file with mode: 0644]
v7/src/swat/scheme/swat.cbf [new file with mode: 0644]
v7/src/swat/scheme/swat.sf [new file with mode: 0644]
v7/src/swat/scheme/text.scm [new file with mode: 0644]
v7/src/swat/scheme/tk-mit.scm [new file with mode: 0644]
v7/src/swat/scheme/uitk-macros.scm [new file with mode: 0644]
v7/src/swat/scheme/uitk.scm [new file with mode: 0644]
v7/src/swat/scheme/widget-mit.scm [new file with mode: 0644]
v7/src/swat/scheme/widget.scm [new file with mode: 0644]
v7/src/swat/scheme/xlibCONSTANTS.scm [new file with mode: 0644]

diff --git a/v7/src/swat/Makefile b/v7/src/swat/Makefile
new file mode 100644 (file)
index 0000000..81581e9
--- /dev/null
@@ -0,0 +1,56 @@
+##
+## $Id: Makefile,v 1.1 1995/08/02 21:19:38 adams Exp $
+##
+## 
+##
+
+#_______________________________________________________________________
+#
+# Installation configuration
+#
+# Where the installed version of SWAT lives
+
+INSTALL_DIR=/scheme/8.0/700/lib/swat
+
+# SWAT's own copies of tcl and tk.  These definitions are passed down to
+# the compilation of Tk and Tcl and become hard paths in the tcl.sl
+# and tk.sl libraries.  DO NOT point these to source directories: the
+# installation cleans them out.
+
+TCL_LIBRARY = $(INSTALL_DIR)/tcl_lib
+TK_LIBRARY = $(INSTALL_DIR)/tk_lib
+
+#_______________________________________________________________________
+
+C_LIBRARIES = c/scxl.sl c/tk.sl c/tcl.sl c/uitk.sl
+
+all:
+       echo "No all target."
+       echo "Only make install"
+       exit 1
+
+install: scheme/compiled
+       (cd c; make TCL_LIBRARY=$(TCL_LIBRARY) TK_LIBRARY=$(TK_LIBRARY) all)
+       # Remove dynload separatly first: will fail if SWAT is in use.
+       rm -rf $(INSTALL_DIR)/dynload
+       rm -rf $(INSTALL_DIR) $(TCL_LIBRARY) $(TK_LIBRARY)
+       mkdir  $(INSTALL_DIR) $(INSTALL_DIR)/dynload \
+               $(TCL_LIBRARY) $(TK_LIBRARY)
+       cp $(C_LIBRARIES) $(INSTALL_DIR)/dynload
+       (cd c/tk3.2/library;     cp *.tcl tclIndex prolog.ps  $(TK_LIBRARY))
+       (cd c/tk3.2/tcl/library; cp *.tcl tclIndex  $(TCL_LIBRARY))
+       (cd scheme; cp load.scm *.com *.bci $(INSTALL_DIR))
+       echo "Installation complete"
+
+
+#$(C_LIBRARIES):
+
+
+scheme/compiled:
+       echo "Build Scheme subsystem  with scheme compiler"
+       exit 1
+       (cd scheme; \
+        echo '(load "swat.sf") (load "swat.cbf")' | $(SCHEME) -compiler \
+       )
+
+clean:
\ No newline at end of file
diff --git a/v7/src/swat/c/MITScheme.c b/v7/src/swat/c/MITScheme.c
new file mode 100644 (file)
index 0000000..0311d5a
--- /dev/null
@@ -0,0 +1,9 @@
+#include "scheme.h"
+#include "prims.h"
+
+extern char *EXFUN (dload_initialize_file, (void));
+
+char *
+  DEFUN_VOID (dload_initialize_file)
+{ return "#NoMITSchemePrimitives";
+}
diff --git a/v7/src/swat/c/Makefile b/v7/src/swat/c/Makefile
new file mode 100644 (file)
index 0000000..8302e9a
--- /dev/null
@@ -0,0 +1,147 @@
+##
+## $Id: Makefile,v 1.1 1995/08/02 21:21:00 adams Exp $
+##
+## WARNING: This makefile is designed to be used only from the master
+## makefile in the parent directory.
+
+#_______________________________________________________________________
+#
+# How this makefile works.
+#
+# This makefile builds four libraries.  Two are based directly on
+# Tk/Tcl.  The other two are an interface between Scheme, X and
+# Tk/Tcl.
+#
+# The build process works by customizing an off-the-shelf version of tk
+# (currently version 3.2).  The SWAT versions of some of the files are
+# copied over the off-the-shelf version.  The customized version is
+# compiled to produce the libtk.a and libtcl.a libraries.  These
+# libraries are not acutally used but they ensure that all the targets
+# that we are interested in are up to date.  Then we construct our own
+# libraries (tk.sl and tcl.sl).
+#
+# The other libraries are more straight-forward.
+#_______________________________________________________________________
+
+# The location of the customized files.  The directory structure matches
+# that of tk3.2 and is sparsely populated with customized files:
+
+CUSTOM = tk3.2-custom
+
+# Important: select a microcode source directory with the correct scheme
+# object representation:
+
+SCHEME_INCLUDE_DIRS =  -I/scheme/8.0/src/microcode
+
+TK =        tk3.2
+TCL =       $(TK)/tcl
+
+#UITK_INCLUDE_DIRS = -I $(UITK) -I $(UITK_C) -I $(TK) -I $(TCL) $(SCHEME_INCLUDE_DIRS)
+UITK_INCLUDE_DIRS = -I $(TK) -I $(TCL) $(SCHEME_INCLUDE_DIRS)
+CFLAGS = -DMIT_SCHEME -O  -Ae -D_HPUX -I/usr/include/X11R5 +z
+
+XLIB           = -L /usr/lib/X11R5 -lX11
+
+# These library paths are overruled by the master makefile.
+
+#TK_LIBRARY    = /scheme/8.0/700/swat/c/tk3.2/library
+#TCL_LIBRARY   = /scheme/8.0/700/swat/c/tk3.2/tcl/library
+TK_LIBRARY     = Built_incorrectly__TK_LIBRARY__not_specified
+TCL_LIBRARY    = Built_incorrectly__TCL_LIBRARY__not_specified
+
+TCL_GENERIC_OBJS = \
+       $(TCL)/regexp.o     $(TCL)/tclAssem.o   $(TCL)/tclBasic.o \
+       $(TCL)/tclCkalloc.o $(TCL)/tclCmdAH.o   $(TCL)/tclCmdIL.o \
+       $(TCL)/tclCmdMZ.o   $(TCL)/tclExpr.o    $(TCL)/tclGet.o \
+       $(TCL)/tclHash.o    $(TCL)/tclHistory.o $(TCL)/tclParse.o \
+       $(TCL)/tclProc.o    $(TCL)/tclUtil.o    $(TCL)/tclVar.o
+
+TCL_UNIX_OBJS = \
+        $(TCL)/panic.o $(TCL)/tclEnv.o $(TCL)/tclGlob.o $(TCL)/tclUnixAZ.o \
+       $(TCL)/tclUnixStr.o $(TCL)/tclUnixUtil.o 
+
+TCL_OBJS = $(TCL_GENERIC_OBJS) $(TCL_UNIX_OBJS) MITScheme.o
+
+TK_WIDGOBJS = \
+       $(TK)/tkButton.o $(TK)/tkEntry.o    $(TK)/tkFrame.o $(TK)/tkListbox.o \
+       $(TK)/tkMenu.o $(TK)/tkMenubutton.o $(TK)/tkMessage.o $(TK)/tkScale.o \
+       $(TK)/tkScrollbar.o
+
+TK_CANVOBJS = \
+       $(TK)/tkCanvas.o   $(TK)/tkCanvArc.o  $(TK)/tkCanvBmap.o \
+       $(TK)/tkCanvLine.o $(TK)/tkCanvPoly.o $(TK)/tkCanvPs.o \
+       $(TK)/tkCanvText.o $(TK)/tkCanvWind.o $(TK)/tkRectOval.o $(TK)/tkTrig.o
+
+TK_TEXTOBJS = $(TK)/tkText.o $(TK)/tkTextBTree.o $(TK)/tkTextDisp.o \
+       $(TK)/tkTextIndex.o $(TK)/tkTextTag.o
+
+TK_OBJS = \
+       $(TK)/tk3d.o     $(TK)/tkArgv.o  $(TK)/tkAtom.o  $(TK)/tkBind.o \
+       $(TK)/tkBitmap.o $(TK)/tkCmds.o  $(TK)/tkColor.o $(TK)/tkConfig.o \
+       $(TK)/tkCursor.o $(TK)/tkError.o $(TK)/tkEvent.o $(TK)/tkFocus.o \
+       $(TK)/tkFont.o   $(TK)/tkGet.o   $(TK)/tkGC.o    $(TK)/tkGeometry.o \
+       $(TK)/tkGrab.o   $(TK)/tkOption.o $(TK)/tkPack.o $(TK)/tkPlace.o \
+       $(TK)/tkPreserve.o $(TK)/tkSelect.o $(TK)/tkSend.o $(TK)/tkWindow.o \
+       $(TK)/tkWm.o $(TK_WIDGOBJS) $(TK_CANVOBJS) $(TK_TEXTOBJS) MITScheme.o
+
+UITK_OBJS = tk-c.o tk-c-mit.o widget-c.o widget-c-mit.o uitk-prims.o
+SCXL_OBJS = scxl.o
+
+# Contents of custom directory structure:
+
+CUSTOM_SRC = \
+       $(CUSTOM)/Makefile $(CUSTOM)/tkCanvArc.c $(CUSTOM)/tkMenu.c \
+       $(CUSTOM)/tkEvent.c $(CUSTOM)/tkWindow.c \
+       $(CUSTOM)/tcl/Makefile $(CUSTOM)/tcl/tclUnix.h \
+       $(CUSTOM)/library/emacs.tcl
+
+all:  scxl.sl tcl.sl tk.sl uitk.sl
+
+scxl.sl: $(SCXL_OBJS)
+       rm -f scxl.sl
+       ld -b -o scxl.sl  $(SCXL_OBJS) $(XLIB) -lc
+
+tcl.sl: $(TCL)/libtcl.a MITScheme.o
+       rm -f tcl.sl
+       ld -b -o tcl.sl  $(TCL_OBJS) -lc
+
+tk.sl: $(TK)/libtk.a MITScheme.o
+       rm -f tk.sl
+       ld -b -o tk.sl  $(TK_OBJS) $(XLIB) -lm -lc
+
+uitk.sl: $(UITK_OBJS)
+       rm -f uitk.sl
+       ld -b -o uitk.sl  $(UITK_OBJS) -lm -lc
+
+scxl.o MITScheme.o uitk-prims.o:
+       $(CC) $(CFLAGS) $(SCHEME_INCLUDE_DIRS) -c $*.c
+
+MITScheme.o: MITScheme.c
+scxl.o: scxl.c
+uitk-prims.o: uitk-prims.c
+
+widget-c.o widget-c-mit.o tk-c-mit.o: $(TK)/tkInt.h $(TK)/default.h
+       $(CC) $(CFLAGS) $(UITK_INCLUDE_DIRS) -c $*.c
+
+tk-c.o: tk-c.c $(TK)/tkInt.h $(TK)/default.h
+       $(CC) $(CFLAGS) $(UITK_INCLUDE_DIRS) TK_LIBRARY=$(TK_LIBRARY) \
+               TCL_LIBRARY=$(TCL_LIBRARY) -c $*.c
+widegt-c.o: widget-c.c
+widget-c-mit.o: widget-c-mit.c
+tk-c-mit.o: tk-c-mit.c
+
+#$(TCL_OBJS) $(TK_OBJS): customization
+$(TCL)/libtcl.a $(TK)/libtk.a: customization
+
+customization: $(CUSTOM_SRC)
+       (cd $(TCL); ./config)
+       # overwrite standard code with customized files
+       cp -f -R tk3.2-custom/* tk3.2
+       rm -f $(TK)/libtk.a $(TCL)/libtcl.a
+       (cd tk3.2; \
+        make -f Makefile TCL_LIBRARY=$(TCL_LIBRARY) TK_LIBRARY=$(TK_LIBRARY) \
+                 libtk.a tcl/libtcl.a \
+       )
+       date > customization
+
+
diff --git a/v7/src/swat/c/scxl.c b/v7/src/swat/c/scxl.c
new file mode 100644 (file)
index 0000000..647d684
--- /dev/null
@@ -0,0 +1,1011 @@
+/* X11 support similar to that in Joel Bartlett's Scheme-To-C xlib (scxl) */
+
+#include "scheme.h"
+#include "prims.h"
+#include "ux.h"
+#include "uxselect.h"
+
+/* Changed 7/95 by Nick in an attempt to fix problem Hal was having with SWAT over PPP (i.e. slow connections) */
+/* commented out 'cause x11.h includes em all
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include "ansidecl.h" */
+
+#include "x11.h"
+
+extern void EXFUN (block_signals, (void));
+extern void EXFUN (unblock_signals, (void));
+
+/* end nick's changes - but see below for more */
+
+
+/* Operations */
+
+DEFINE_PRIMITIVE ("%XAllocNamedColor", Prim_scxl_allocated_named_color,
+                 5, 5, 0)
+{ /* (%XAllocNamedColor display colormap color-string
+                        return-alloc return-exact)
+  */
+  PRIMITIVE_HEADER(5);
+  CHECK_ARG(4, STRING_P);
+  CHECK_ARG(5, STRING_P);
+  if (STRING_LENGTH(ARG_REF(4)) < sizeof (XColor))
+    error_bad_range_arg(4);
+  if (STRING_LENGTH(ARG_REF(5)) < sizeof (XColor))
+    error_bad_range_arg(5);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) XAllocNamedColor((Display *) arg_integer(1),
+                             (Colormap) arg_integer(2),
+                             STRING_ARG(3),
+                             (XColor *) STRING_ARG(4),
+                             (XColor *) STRING_ARG(5))));
+}
+
+DEFINE_PRIMITIVE ("%XChangeWindowAttributes", Prim_scxl_change_wind_attr,
+                 4, 4, 0)
+{ /* (%XChangeWindowAttributes display window mask attributes) */
+  /* ATTRIBUTES is a string */
+  PRIMITIVE_HEADER(4);
+  CHECK_ARG(4, STRING_P);
+  if (STRING_LENGTH(ARG_REF(4)) < sizeof (XSetWindowAttributes))
+    error_bad_range_arg(4);
+  XChangeWindowAttributes((Display *) arg_integer(1),
+                         (Window) arg_integer(2),
+                         (unsigned long) arg_integer(3),
+                         (XSetWindowAttributes *) STRING_ARG(4));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XCheckMaskEvent", Prim_scxl_check_mask_event, 3, 3, 0)
+{ /* (%XCheckMaskEvent display event-mask return-event) */
+  PRIMITIVE_HEADER (3);
+  CHECK_ARG(3, STRING_P);
+  if (STRING_LENGTH(ARG_REF(3)) < sizeof(XEvent))
+    error_bad_range_arg(3);
+  PRIMITIVE_RETURN (BOOLEAN_TO_OBJECT
+                   (XCheckMaskEvent ((Display *) arg_integer(1),
+                                     (long) arg_integer(2),
+                                     (XEvent *) STRING_ARG(3))));
+}
+
+DEFINE_PRIMITIVE ("%XClearArea", Prim_scxl_clear_area, 7, 7, 0)
+{ /* (%XClearArea display window x y width height) */
+  PRIMITIVE_HEADER (7);
+  XClearArea ((Display *) arg_integer(1),
+             (Drawable) arg_integer(2),
+             (int) arg_integer(3),
+             (int) arg_integer(4),
+             (unsigned int) arg_integer(5),
+             (unsigned int) arg_integer(6),
+             (Bool) BOOLEAN_ARG(7));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XClearWindow", Prim_scxl_clear_window, 2, 2, 0)
+{ /* (%XClearWindow display window) */
+  PRIMITIVE_HEADER (2);
+  XClearWindow ((Display *) arg_integer(1),
+               (Drawable) arg_integer(2));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XCloseDisplay", Prim_scxl_close, 1, 1, 0)
+{ /* (%XCloseDisplay display) */
+  PRIMITIVE_HEADER (1);
+  XCloseDisplay((Display *) arg_integer(1));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XConnectionNumber", Prim_scxl_connection_number, 1, 1, 0)
+{ /* (%XConnectionNumber display) */
+  PRIMITIVE_HEADER (1);
+  PRIMITIVE_RETURN (long_to_integer
+                   (XConnectionNumber((Display *) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%XCreateGC", Prim_scxl_create_gc, 4, 4, 0)
+{ /* (%XCreateGC display window mask values) */
+  PRIMITIVE_HEADER(4);
+  CHECK_ARG(4, STRING_P);
+  if (STRING_LENGTH(ARG_REF(4)) < sizeof(XGCValues))
+    error_bad_range_arg(4);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) XCreateGC((Display *) arg_integer(1),
+                      (Drawable) arg_integer(2),
+                      (unsigned long) arg_integer(3),
+                      (XGCValues *) STRING_ARG(4))));
+}
+
+DEFINE_PRIMITIVE ("%XCreateRegion", Prim_scxl_create_region, 0, 0, 0)
+{ /* (%XCreateRegion) */
+  Region Result;
+  PRIMITIVE_HEADER(0);
+  Result = XCreateRegion();
+  PRIMITIVE_RETURN (long_to_integer ((long) Result));
+}
+
+DEFINE_PRIMITIVE ("%XCreateSimpleWindow", Prim_scxl_create_simple_window,
+                 9, 9, 0)
+{ /* (%XCreateSimpleWindow display parent-window x y width height
+                           border-width border-color background-color)
+  */
+  PRIMITIVE_HEADER(9);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) XCreateSimpleWindow
+      ((Display *) arg_integer(1),
+       (Window) arg_integer(2),
+       (int) arg_integer(3),
+       (int) arg_integer(4),
+       (unsigned int) arg_integer(5),
+       (unsigned int) arg_integer(6),
+       (unsigned int) arg_integer(7),
+       (unsigned long) arg_integer(8),
+       (unsigned long) arg_integer(9))));
+}
+
+DEFINE_PRIMITIVE ("%XDecodeButtonEvent", prim_scxl_decode_button, 2, 2, 0)
+{ /* (%XDecodeButtonEvent event vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XButtonEvent *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XButtonEvent))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 15)
+   error_bad_range_arg(2);
+  Input = (XButtonEvent *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->type));   /* 0 */
+  *Next++ = long_to_integer ((long) (Input->serial)); /* 1 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->send_event);     /* 2 */
+  *Next++ = long_to_integer ((long) (Input->display)); /* 3 */
+  *Next++ = long_to_integer ((long) (Input->window)); /* 4 */
+  *Next++ = long_to_integer ((long) (Input->root));   /* 5 */
+  *Next++ = long_to_integer ((long) (Input->subwindow)); /* 6 */
+  *Next++ = long_to_integer ((long) (Input->time));   /* 7 */
+  *Next++ = long_to_integer ((long) (Input->x));      /* 8 */
+  *Next++ = long_to_integer ((long) (Input->y));      /* 9 */
+  *Next++ = long_to_integer ((long) (Input->x_root)); /* 10 */
+  *Next++ = long_to_integer ((long) (Input->y_root)); /* 11 */
+  *Next++ = long_to_integer ((long) (Input->state));  /* 12 */
+  *Next++ = long_to_integer ((long) (Input->button));  /* 13 */
+  *Next = BOOLEAN_TO_OBJECT(Input->same_screen);      /* 14 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+  
+DEFINE_PRIMITIVE ("%XDecodeConfigureEvent",
+                 prim_scxl_decode_config, 2, 2, 0)
+{ /* (%XDecodeConfigureEvent event vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XConfigureEvent *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XConfigureEvent))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 13)
+   error_bad_range_arg(2);
+  Input = (XConfigureEvent *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->type));   /* 0 */
+  *Next++ = long_to_integer ((long) (Input->serial)); /* 1 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->send_event);     /* 2 */
+  *Next++ = long_to_integer ((long) (Input->display)); /* 3 */
+  *Next++ = long_to_integer ((long) (Input->event));  /* 4 */
+  *Next++ = long_to_integer ((long) (Input->window)); /* 5 */
+  *Next++ = long_to_integer ((long) (Input->x));      /* 6 */
+  *Next++ = long_to_integer ((long) (Input->y));      /* 7 */
+  *Next++ = long_to_integer ((long) (Input->width));  /* 8 */
+  *Next++ = long_to_integer ((long) (Input->height)); /* 9 */
+  *Next++ = long_to_integer ((long) (Input->border_width)); /* 10 */
+  *Next++ = long_to_integer ((long) (Input->above));  /* 11 */
+  *Next = BOOLEAN_TO_OBJECT(Input->override_redirect); /* 12 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+  
+DEFINE_PRIMITIVE ("%XDecodeCrossingEvent", prim_scxl_decode_crossing, 2, 2, 0)
+{ /* (%XDecodeCrossingEvent event vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XCrossingEvent *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XCrossingEvent))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 17)
+   error_bad_range_arg(2);
+  Input = (XCrossingEvent *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->type));   /* 0 */
+  *Next++ = long_to_integer ((long) (Input->serial)); /* 1 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->send_event);     /* 2 */
+  *Next++ = long_to_integer ((long) (Input->display)); /* 3 */
+  *Next++ = long_to_integer ((long) (Input->window)); /* 4 */
+  *Next++ = long_to_integer ((long) (Input->root));   /* 5 */
+  *Next++ = long_to_integer ((long) (Input->subwindow)); /* 6 */
+  *Next++ = long_to_integer ((long) (Input->time));   /* 7 */
+  *Next++ = long_to_integer ((long) (Input->x));      /* 8 */
+  *Next++ = long_to_integer ((long) (Input->y));      /* 9 */
+  *Next++ = long_to_integer ((long) (Input->x_root)); /* 10 */
+  *Next++ = long_to_integer ((long) (Input->y_root)); /* 11 */
+  *Next++ = long_to_integer ((long) (Input->mode));   /* 12 */
+  *Next++ = long_to_integer ((long) (Input->detail)); /* 13 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->same_screen);    /* 14 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->focus);         /* 15 */
+  *Next = long_to_integer ((long) (Input->state));    /* 16 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+  
+DEFINE_PRIMITIVE ("%XDecodeExposeEvent", prim_scxl_decode_expose, 2, 2, 0)
+{ /* (%XDecodeExposeEvent event vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XExposeEvent *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XExposeEvent))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 10)
+   error_bad_range_arg(2);
+  Input = (XExposeEvent *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->type));   /* 0 */
+  *Next++ = long_to_integer ((long) (Input->serial)); /* 1 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->send_event);     /* 2 */
+  *Next++ = long_to_integer ((long) (Input->display)); /* 3 */
+  *Next++ = long_to_integer ((long) (Input->window)); /* 4 */
+  *Next++ = long_to_integer ((long) (Input->x));      /* 5 */
+  *Next++ = long_to_integer ((long) (Input->y));      /* 6 */
+  *Next++ = long_to_integer ((long) (Input->width));  /* 7 */
+  *Next++ = long_to_integer ((long) (Input->height)); /* 8 */
+  *Next = long_to_integer ((long) (Input->count));    /* 9 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDecodeKeyEvent", prim_scxl_decode_key, 2, 2, 0)
+{ /* (%XDecodeKeyEvent event vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XKeyEvent *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XKeyEvent))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 15)
+   error_bad_range_arg(2);
+  Input = (XKeyEvent *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->type));   /* 0 */
+  *Next++ = long_to_integer ((long) (Input->serial)); /* 1 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->send_event);     /* 2 */
+  *Next++ = long_to_integer ((long) (Input->display)); /* 3 */
+  *Next++ = long_to_integer ((long) (Input->window)); /* 4 */
+  *Next++ = long_to_integer ((long) (Input->root));   /* 5 */
+  *Next++ = long_to_integer ((long) (Input->subwindow)); /* 6 */
+  *Next++ = long_to_integer ((long) (Input->time));   /* 7 */
+  *Next++ = long_to_integer ((long) (Input->x));      /* 8 */
+  *Next++ = long_to_integer ((long) (Input->y));      /* 9 */
+  *Next++ = long_to_integer ((long) (Input->x_root)); /* 10 */
+  *Next++ = long_to_integer ((long) (Input->y_root)); /* 11 */
+  *Next++ = long_to_integer ((long) (Input->state));  /* 12 */
+  *Next++ = long_to_integer ((long) (Input->keycode)); /* 13 */
+  *Next = BOOLEAN_TO_OBJECT(Input->same_screen);      /* 14 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDecodeMotionEvent", prim_scxl_decode_motion, 2, 2, 0)
+{ /* (%XDecodeMotionEvent event vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XMotionEvent *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XMotionEvent))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 15)
+   error_bad_range_arg(2);
+  Input = (XMotionEvent *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->type));   /* 0 */
+  *Next++ = long_to_integer ((long) (Input->serial)); /* 1 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->send_event);     /* 2 */
+  *Next++ = long_to_integer ((long) (Input->display)); /* 3 */
+  *Next++ = long_to_integer ((long) (Input->window)); /* 4 */
+  *Next++ = long_to_integer ((long) (Input->root));   /* 5 */
+  *Next++ = long_to_integer ((long) (Input->subwindow)); /* 6 */
+  *Next++ = long_to_integer ((long) (Input->time));   /* 7 */
+  *Next++ = long_to_integer ((long) (Input->x));      /* 8 */
+  *Next++ = long_to_integer ((long) (Input->y));      /* 9 */
+  *Next++ = long_to_integer ((long) (Input->x_root)); /* 10 */
+  *Next++ = long_to_integer ((long) (Input->y_root)); /* 11 */
+  *Next++ = long_to_integer ((long) (Input->state));  /* 12 */
+  *Next++ = long_to_integer ((long) (Input->is_hint)); /* 13 */
+  *Next = BOOLEAN_TO_OBJECT(Input->same_screen);      /* 14 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+  
+DEFINE_PRIMITIVE ("%XDecodeUnknownEvent", Prim_scxl_decode_unknown, 2, 2, 0)
+{ /* (%XDecodeUnknownEvent event vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XAnyEvent *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XAnyEvent))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 5)
+   error_bad_range_arg(2);
+  Input = (XAnyEvent *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->type));   /* 0 */
+  *Next++ = long_to_integer ((long) (Input->serial)); /* 1 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->send_event);     /* 2 */
+  *Next++ = long_to_integer ((long) (Input->display)); /* 3 */
+  *Next = long_to_integer ((long) (Input->window));   /* 4 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDecodeWindowAttributes", Prim_scxl_decode_wind_attr, 2, 2, 0)
+{ /* (%XDecodeWindowAttributes attributes vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XWindowAttributes *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XWindowAttributes))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 23)
+   error_bad_range_arg(2);
+  Input = (XWindowAttributes *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->x));      /* 0 */
+  *Next++ = long_to_integer ((long) (Input->y));      /* 1 */
+  *Next++ = long_to_integer ((long) (Input->width));  /* 2 */
+  *Next++ = long_to_integer ((long) (Input->height)); /* 3 */
+  *Next++ = long_to_integer ((long) (Input->border_width)); /* 4 */
+  *Next++ = long_to_integer ((long) (Input->depth));  /* 5 */
+  *Next++ = long_to_integer ((long) (Input->visual)); /* 6 */
+  *Next++ = long_to_integer ((long) (Input->root));   /* 7 */
+  *Next++ = long_to_integer ((long) (Input->class));  /* 8 */
+  *Next++ = long_to_integer ((long) (Input->bit_gravity)); /* 9 */
+  *Next++ = long_to_integer ((long) (Input->win_gravity)); /* 10 */
+  *Next++ = long_to_integer ((long) (Input->backing_store)); /* 11 */
+  *Next++ = long_to_integer ((long) (Input->backing_planes)); /* 12 */
+  *Next++ = long_to_integer ((long) (Input->backing_pixel)); /* 13 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->save_under);     /* 14 */
+  *Next++ = long_to_integer ((long) (Input->colormap));        /* 15 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->map_installed);  /* 16 */
+  *Next++ = long_to_integer ((long) (Input->map_state)); /* 17 */
+  *Next++ = long_to_integer ((long) (Input->all_event_masks)); /* 18 */
+  *Next++ = long_to_integer ((long) (Input->your_event_mask)); /* 19 */
+  *Next++ = long_to_integer ((long) (Input->do_not_propagate_mask)); /* 20 */
+  *Next++ = BOOLEAN_TO_OBJECT(Input->override_redirect); /* 21 */
+  *Next = long_to_integer ((long) (Input->screen));   /* 22 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDecodeXColor", Prim_scxl_decode_xcolor, 2, 2, 0)
+{ /* (%XDecodeXColor xcolor vector) */
+  SCHEME_OBJECT Result = ARG_REF(2);
+  SCHEME_OBJECT *Next;
+  XColor *Input;
+
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(1, STRING_P);
+  if (STRING_LENGTH(ARG_REF(1)) != sizeof(XColor))
+    error_bad_range_arg(1);
+  CHECK_ARG(2, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 5)
+   error_bad_range_arg(2);
+  Input = (XColor *) STRING_ARG(1);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = long_to_integer ((long) (Input->pixel));  /* 0 */
+  *Next++ = long_to_integer ((long) (Input->red));    /* 1 */
+  *Next++ = long_to_integer ((long) (Input->green));  /* 2 */
+  *Next++ = long_to_integer ((long) (Input->blue));   /* 3 */
+  *Next = long_to_integer ((long) (Input->flags));    /* 4 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDefaultColormap", Prim_scxl_default_colormap, 2, 2, 0)
+{ /* (%XDefaultColormap display screen) */
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) XDefaultColormap((Display *) arg_integer(1),
+                             arg_integer(2))));
+}
+
+DEFINE_PRIMITIVE ("%XDefaultRootWindow", Prim_scxl_default_root_window,
+                 1, 1, 0)
+{ /* (%XDefaultRootWindow display) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) XDefaultRootWindow ((Display *) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%XDefaultScreen", Prim_scxl_default_screen, 1, 1, 0)
+{ /* (%XDefaultScreen display) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) XDefaultScreen((Display *) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%XDestroyRegion", Prim_scxl_destroy_region, 1, 1, 0)
+{ /* (%XDestroyRegion region) */
+  PRIMITIVE_HEADER (1);
+  XDestroyRegion ((Region) arg_integer(1));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDestroyWindow", Prim_scxl_destroy_window, 2, 2, 0)
+{ /* (%XDestroyWindow display window) */
+  PRIMITIVE_HEADER (2);
+  XDestroyWindow((Display *) arg_integer(1),
+                (Window) arg_integer(2));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDrawArc", Prim_scxl_draw_arc, 9, 9, 0)
+{ /* (%XDrawArc display window context
+                      x y width height angle1 angle2) */
+  PRIMITIVE_HEADER (9);
+  XDrawArc((Display *) arg_integer(1),
+          (Drawable) arg_integer(2),
+          (GC) arg_integer(3),
+          (int) arg_integer(4),
+          (int) arg_integer(5),
+          (unsigned int) arg_integer(6),
+          (unsigned int) arg_integer(7),
+          (unsigned int) arg_integer(8),
+          (unsigned int) arg_integer(9));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDrawLine", Prim_scxl_draw_line, 7, 7, 0)
+{ /* (%XDrawLine display window context x1 y1 x2 y2) */
+  PRIMITIVE_HEADER (7);
+  XDrawLine((Display *) arg_integer(1),
+           (Drawable) arg_integer(2),
+           (GC) arg_integer(3),
+           (int) arg_integer(4),
+           (int) arg_integer(5),
+           (int) arg_integer(6),
+           (int) arg_integer(7));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XDrawRectangle", Prim_scxl_draw_rectangle, 7, 7, 0)
+{ /* (%XDrawRectangle display window context x y width height) */
+  PRIMITIVE_HEADER (7);
+  XDrawRectangle((Display *) arg_integer(1),
+                (Drawable) arg_integer(2),
+                (GC) arg_integer(3),
+                (int) arg_integer(4),
+                (int) arg_integer(5),
+                (unsigned int) arg_integer(6),
+                (unsigned int) arg_integer(7));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XFillArc", Prim_scxl_fill_arc, 9, 9, 0)
+{ /* (%XFillArc display window context
+                      x y width height angle1 angle2) */
+  PRIMITIVE_HEADER (9);
+  XFillArc((Display *) arg_integer(1),
+          (Drawable) arg_integer(2),
+          (GC) arg_integer(3),
+          (int) arg_integer(4),
+          (int) arg_integer(5),
+          (unsigned int) arg_integer(6),
+          (unsigned int) arg_integer(7),
+          (unsigned int) arg_integer(8),
+          (unsigned int) arg_integer(9));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XFillRectangle", Prim_scxl_fill_rectangle, 7, 7, 0)
+{ /* (%XFillRectangle display window context x y width height) */
+  PRIMITIVE_HEADER (7);
+  XFillRectangle((Display *) arg_integer(1),
+                (Drawable) arg_integer(2),
+                (GC) arg_integer(3),
+                (int) arg_integer(4),
+                (int) arg_integer(5),
+                (unsigned int) arg_integer(6),
+                (unsigned int) arg_integer(7));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XFlush", Prim_scxl_flush, 1, 1, 0)
+{ /* (%XFlush display) */
+  PRIMITIVE_HEADER (1);
+  XFlush((Display *) arg_integer(1));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XFreeColormap", Prim_scxl_free_colormap, 2, 2, 0)
+{ /* (%XFreeColormap display colormap) */
+  PRIMITIVE_HEADER(2);
+  XFreeColormap((Display *) arg_integer(1), (Colormap) arg_integer(2));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XFreeGC", Prim_scxl_free_gc, 2, 2, 0)
+{ /* (%XFreeGC display graphic-context) */
+  PRIMITIVE_HEADER(2);
+  XFreeGC((Display *) arg_integer(1), (GC) arg_integer(2));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XGetDefault", Prim_scxl_get_default, 3, 3, 0)
+{ /* (%XGetDefault display program option) */
+  PRIMITIVE_HEADER(3);
+  PRIMITIVE_RETURN
+    (char_pointer_to_string
+     ((unsigned char *) XGetDefault((Display *) arg_integer(1),
+                                   STRING_ARG(2),
+                                   STRING_ARG(3))));
+}
+
+DEFINE_PRIMITIVE ("%XGetWindowAttributes", Prim_scxl_get_wind_attr, 3, 3, 0)
+{ /* (%XGetWindowAttributes display window attributes-to-fill) */
+  PRIMITIVE_HEADER(3);
+  CHECK_ARG(3, STRING_P);
+  if (STRING_LENGTH(ARG_REF(3)) < sizeof(XWindowAttributes))
+    error_bad_range_arg(3);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long)
+      XGetWindowAttributes((Display *) arg_integer(1),
+                          (Window) arg_integer(2),
+                          (XWindowAttributes *) STRING_ARG(3))));
+}
+
+DEFINE_PRIMITIVE ("%XIntersectRegion", Prim_scxl_intersect_reg, 3, 3, 0)
+{ /* (%XIntersectRegion source1 source2 dest) */
+  PRIMITIVE_HEADER (3);
+  XIntersectRegion((Region) arg_integer(1),
+                  (Region) arg_integer(2),
+                  (Region) arg_integer(3));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XLoadFont", Prim_scxl_load_font, 2, 2, 0)
+{ /* (%XLoadFont display name-string) */
+  PRIMITIVE_HEADER (2);
+  PRIMITIVE_RETURN
+    (long_to_integer ((long) XLoadFont((Display *) arg_integer(1),
+                                      STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%XMapWindow", Prim_scxl_map_window, 2, 2, 0)
+{ /* (%XMapWindow display window) */
+  PRIMITIVE_HEADER(2);
+  XMapWindow((Display *) arg_integer(1),
+            (Window) arg_integer(2));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XNextEvent", Prim_scxl_next_event, 2, 2, 0)
+{ /* (%XNextEvent display returned-event) */
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(2, STRING_P);
+  if (STRING_LENGTH(ARG_REF(2)) < sizeof(XEvent))
+    error_bad_range_arg(2);
+  XNextEvent((Display *) arg_integer(1),
+            (XEvent *) STRING_ARG(2));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+     
+DEFINE_PRIMITIVE ("%XOpenDisplay", Prim_scxl_open_display, 1, 1, 0)
+{ /* (%XOpenDisplay string) */
+  PRIMITIVE_HEADER (1);
+  {
+    /* Changed 7/95 by Nick in an attempt to fix problem Hal was having with SWAT over PPP (i.e. slow connections) */
+    Display * display;
+    block_signals ();
+    display = XOpenDisplay(STRING_ARG(1));
+    unblock_signals ();
+    PRIMITIVE_RETURN (long_to_integer((long) display));
+  }
+}
+
+DEFINE_PRIMITIVE ("%XPending", Prim_scxl_pending, 1, 1, 0)
+{ /* (%XPending display) */
+  PRIMITIVE_HEADER (1);
+  PRIMITIVE_RETURN
+    (long_to_integer(XPending ((Display *) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%XPutBackEvent", Prim_scxl_put_back_event, 2, 2, 0)
+{ /* (%XPutBackEvent display event) */
+  PRIMITIVE_HEADER (2);
+  CHECK_ARG(2, STRING_P);
+  if (STRING_LENGTH(ARG_REF(2)) < sizeof(XEvent))
+    error_bad_range_arg(2);
+  XPutBackEvent ((Display *) arg_integer(1),
+                (XEvent *) STRING_ARG(2));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XQueryPointer", Prim_scxl_query_pointer, 3, 3, 0)
+{ /* (%XQueryPointer display window result-vector) */
+  SCHEME_OBJECT Result = ARG_REF(3);
+  SCHEME_OBJECT *Next;
+  Window Root=0, Child=0;
+  int Root_X=0, Root_Y=0, Win_X=0, Win_Y=0;
+  unsigned int Keys_Buttons=0;
+  Bool result_status;
+
+  PRIMITIVE_HEADER (3);
+  CHECK_ARG(3, VECTOR_P);
+  if (VECTOR_LENGTH(Result) < 8) error_bad_range_arg(3);
+  result_status = XQueryPointer((Display *) arg_integer(1),
+                               (Window) arg_integer(2),
+                               &Root, &Child, &Root_X, &Root_Y,
+                               &Win_X, &Win_Y, &Keys_Buttons);
+  Next = VECTOR_LOC(Result, 0);
+  *Next++ = BOOLEAN_TO_OBJECT(result_status);        /* 0 */
+  *Next++ = long_to_integer ((long) Root);           /* 1 */
+  *Next++ = long_to_integer ((long) Child);          /* 2 */
+  *Next++ = long_to_integer ((long) Root_X);         /* 3 */
+  *Next++ = long_to_integer ((long) Root_Y);         /* 4 */
+  *Next++ = long_to_integer ((long) Win_X);          /* 5 */
+  *Next++ = long_to_integer ((long) Win_Y);          /* 6 */
+  *Next++ = long_to_integer ((long) Keys_Buttons);    /* 7 */
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XQueryTree", Prim_query_tree, 2, 2, 0)
+{ /* (%XQueryTree display window)
+     returns a vector of #(root parent . kids)
+  */
+  SCHEME_OBJECT Kid_Return;
+  Window Root, Parent, *Kids;
+  unsigned int NKids, i;
+
+  PRIMITIVE_HEADER (2);
+  if (XQueryTree((Display *) arg_integer(1), (Window) arg_integer(2),
+                &Root, &Parent, &Kids, &NKids)==0)
+  { error_external_return();
+  }
+  Kid_Return = allocate_marked_vector(TC_VECTOR, NKids+2, true);
+  VECTOR_SET(Kid_Return, 0, long_to_integer((long) Root));
+  VECTOR_SET(Kid_Return, 1, long_to_integer((long) Parent));
+  for (i=0; i < NKids; i++)
+    VECTOR_SET(Kid_Return, i+2, long_to_integer((long) Kids[i]));
+  XFree(Kids);
+  PRIMITIVE_RETURN (Kid_Return);
+}
+
+DEFINE_PRIMITIVE ("%XScreenCount", Prim_scxl_screencount, 1, 1, 0)
+{ /* (%XScreenCount display) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   (XScreenCount((Display *) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%XSetForeground", Prim_scxl_set_foreground, 3, 3, 0)
+{ /* (%XSetForeground display context pixel) */
+  PRIMITIVE_HEADER(3);
+  XSetForeground((Display *) arg_integer(1),
+                (GC) arg_integer(2),
+                arg_integer(3));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+
+DEFINE_PRIMITIVE ("%XSetFunction", Prim_scxl_set_function, 3, 3, 0)
+{ /* (%XSetFunction display context function_number) */
+  PRIMITIVE_HEADER(3);
+  XSetFunction((Display *) arg_integer(1),
+                (GC) arg_integer(2),
+                arg_integer(3));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+
+DEFINE_PRIMITIVE ("%XSetRegion", Prim_scxl_set_region, 3, 3, 0)
+{ /* (%XSetForeground display gc region) */
+  PRIMITIVE_HEADER(3);
+  XSetRegion((Display *) arg_integer(1),
+            (GC) arg_integer(2),
+            (Region) arg_integer(3));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XStoreName", Prim_scxl_store_name, 3, 3, 0)
+{ /* (%XStoreName display window title-string */
+  PRIMITIVE_HEADER (3);
+  XStoreName((Display *) arg_integer(1),
+            (Window) arg_integer(2),
+            STRING_ARG(3));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XSubtractRegion", Prim_scxl_subtract_reg, 3, 3, 0)
+{ /* (%XSubtractRegion source1 source2 dest) */
+  PRIMITIVE_HEADER (3);
+  XSubtractRegion((Region) arg_integer(1),
+                 (Region) arg_integer(2),
+                 (Region) arg_integer(3));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XTranslateCoordinates", Prim_scxl_translate_coords,
+                 6, 6, 0)
+{ /* (%XTranslateCoordinates display old-window new-window x y vector)
+  */
+  int X, Y;
+  Window W;
+  SCHEME_OBJECT Vect;
+  Boolean status;
+  PRIMITIVE_HEADER (6);
+  Vect = VECTOR_ARG(6);
+  if (VECTOR_LENGTH(Vect) < 4) error_bad_range_arg(6);
+  status = XTranslateCoordinates((Display *) arg_integer(1),
+                                (Window) arg_integer(2),
+                                (Window) arg_integer(3),
+                                (int) arg_integer(4),
+                                (int) arg_integer(5),
+                                &X, &Y, &W);
+  VECTOR_SET(Vect, 0, BOOLEAN_TO_OBJECT(status));
+  VECTOR_SET(Vect, 1, long_to_integer((long) X));
+  VECTOR_SET(Vect, 2, long_to_integer((long) Y));
+  VECTOR_SET(Vect, 3, long_to_integer((long) W));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XUnionRegion", Prim_scxl_union_reg, 3, 3, 0)
+{ /* (%XUnionRegion source1 source2 dest) */
+  PRIMITIVE_HEADER (3);
+  XUnionRegion((Region) arg_integer(1),
+              (Region) arg_integer(2),
+              (Region) arg_integer(3));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XUnionRectSpecsWithRegion!", Prim_scxl_union_rectspecs, 6, 6, 0)
+{ /* (%XUnionRectSpecsWithRegion! x y width height inregion outregion) */
+  XRectangle Rect;
+  PRIMITIVE_HEADER (6);
+  Rect.x = arg_integer(1);
+  Rect.y = arg_integer(2);
+  Rect.width = arg_integer(3);
+  Rect.height = arg_integer(4);
+  XUnionRectWithRegion(&Rect,
+                      (Region) (arg_integer (5)),
+                      (Region) (arg_integer (6)));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%XUnloadFont", Prim_scxl_unload_font, 2, 2, 0)
+{ /* (%XUnloadFont display font) */
+  PRIMITIVE_HEADER(2);
+  XUnloadFont((Display *) arg_integer(1), (Font) arg_integer(2));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+/* Data structure constructors.  These are represented as strings to */
+/* circumvent  garbage collection */
+
+DEFINE_PRIMITIVE ("%XMake-Color", Prim_scxl_make_color, 0, 0, 0)
+{ /* (%XMake-Color) */
+  PRIMITIVE_HEADER (0);
+  PRIMITIVE_RETURN(allocate_string(sizeof(XColor)));
+}
+
+DEFINE_PRIMITIVE ("%XMake-Event", Prim_scxl_make_event, 0, 0, 0)
+{ /* (%XMake-Event) */
+  PRIMITIVE_HEADER (0);
+  PRIMITIVE_RETURN(allocate_string(sizeof(XEvent)));
+}
+
+DEFINE_PRIMITIVE ("%XMake-GCValues", Prim_scxl_make_gc_values, 0, 0, 0)
+{ /* (%XMake-GCValues) */
+  PRIMITIVE_HEADER (0);
+  PRIMITIVE_RETURN(allocate_string(sizeof(XGCValues)));
+}
+
+DEFINE_PRIMITIVE ("%XMake-GetWindowAttributes", Prim_scxl_make_get_wind_attr,
+                 0, 0, 0)
+{ /* (%XMake-GetWindowAttributes) */
+  PRIMITIVE_HEADER (0);
+  PRIMITIVE_RETURN(allocate_string(sizeof(XWindowAttributes)));
+}
+
+DEFINE_PRIMITIVE ("%XMake-SetWindowAttributes", Prim_scxl_make_set_wind_attr,
+                 0, 0, 0)
+{ /* (%XMake-SetWindowAttributes) */
+  PRIMITIVE_HEADER (0);
+  PRIMITIVE_RETURN(allocate_string(sizeof(XSetWindowAttributes)));
+}
+
+/* Mutators */
+
+#define Mutator(StructType, Field, FieldType, Converter)       \
+{                                                              \
+  PRIMITIVE_HEADER(2);                                         \
+  CHECK_ARG(1, STRING_P);                                      \
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(StructType))          \
+    error_bad_range_arg(1);                                    \
+  ((StructType *) (STRING_ARG(1)))->Field =                    \
+    ((FieldType) Converter(2));                                        \
+  PRIMITIVE_RETURN (UNSPECIFIC);                               \
+}
+
+DEFINE_PRIMITIVE ("%XSetWindowAttributes-Event_Mask!",
+                 Prim_scxl_XSetWindowAttributes_Event_Mask_bang,
+                 2, 2, 0)
+  Mutator(XSetWindowAttributes, event_mask, long, arg_integer)
+
+static int
+DEFUN (x_io_error_handler, (display),
+       Display * display)
+{
+  fprintf (stderr, "\nX IO Error on display 0x%x\n", display);
+  error_external_return ();
+}
+
+void DEFUN (Scheme_x_error_handler, (display, error_event),
+           Display * display AND
+           XErrorEvent * error_event)
+{
+  char buffer [2048];
+  XGetErrorText (display, (error_event -> error_code),
+                buffer, (sizeof (buffer)));
+  fprintf (stderr, "\nX Error: %s\n", buffer);
+  fprintf (stderr, "         Request code: %d\n",
+          (error_event -> request_code));
+  fprintf (stderr, "         Error serial: 0x%x\n",
+          (error_event -> serial));
+  fprintf (stderr, "         Display: %d (0x%x)\n",
+          error_event->display, error_event->display);
+  fprintf (stderr, "         Resource ID: %d (0x%x)\n",
+          error_event->resourceid, error_event->resourceid);
+  fprintf (stderr, "         Minor code: %d (0x%x)\n",
+          error_event->minor_code, error_event->minor_code);
+  fflush (stderr);
+}
+
+static int
+DEFUN (Scheme_low_x_error_handler, (display, error_event),
+       Display * display AND
+       XErrorEvent * error_event)
+{ Scheme_x_error_handler(display, error_event);
+  error_external_return ();
+}
+
+DEFINE_PRIMITIVE("%XInitSCXL!", Prim_scxl_init, 0, 0, 0)
+{ extern int _XDefaultError();
+  PRIMITIVE_HEADER (0);
+  XSetErrorHandler (Scheme_low_x_error_handler);
+  XSetIOErrorHandler (x_io_error_handler);
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE("%XSync", Prim_scxl_sync, 2, 2, 0)
+{ PRIMITIVE_HEADER (2);
+  XSync((Display *) arg_integer(1), BOOLEAN_ARG(2));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE("%XSynchronize", Prim_scxl_synchronize, 2, 2, 0)
+{ PRIMITIVE_HEADER (2);
+  XSynchronize((Display *) arg_integer(1), BOOLEAN_ARG(2));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+SCHEME_OBJECT Debug_State_Flag;
+
+DEFINE_PRIMITIVE("%SetDebugState!", Prim_scxl_state, 1, 1, 0)
+{ PRIMITIVE_HEADER(1);
+  Debug_State_Flag = ARG_REF(1);
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+extern char *EXFUN (dload_initialize_file, (void));
+
+char *
+  DEFUN_VOID (dload_initialize_file)
+{ declare_primitive("%XAllocNamedColor", Prim_scxl_allocated_named_color,
+                 5, 5, 0);
+  declare_primitive("%XChangeWindowAttributes", Prim_scxl_change_wind_attr,
+                 4, 4, 0);
+  declare_primitive("%XCheckMaskEvent", Prim_scxl_check_mask_event, 3, 3, 0);
+  declare_primitive("%XClearArea", Prim_scxl_clear_area, 7, 7, 0);
+  declare_primitive("%XClearWindow", Prim_scxl_clear_window, 2, 2, 0);
+  declare_primitive("%XCloseDisplay", Prim_scxl_close, 1, 1, 0);
+  declare_primitive("%XConnectionNumber", Prim_scxl_connection_number, 1, 1, 0);
+  declare_primitive("%XCreateGC", Prim_scxl_create_gc, 4, 4, 0);
+  declare_primitive("%XCreateRegion", Prim_scxl_create_region, 0, 0, 0);
+  declare_primitive("%XCreateSimpleWindow", Prim_scxl_create_simple_window,
+                 9, 9, 0);
+  declare_primitive("%XDecodeButtonEvent", prim_scxl_decode_button, 2, 2, 0);
+  declare_primitive("%XDecodeConfigureEvent",
+                 prim_scxl_decode_config, 2, 2, 0);
+  declare_primitive("%XDecodeCrossingEvent", prim_scxl_decode_crossing, 2, 2, 0);
+  declare_primitive("%XDecodeExposeEvent", prim_scxl_decode_expose, 2, 2, 0);
+  declare_primitive("%XDecodeKeyEvent", prim_scxl_decode_key, 2, 2, 0);
+  declare_primitive("%XDecodeMotionEvent", prim_scxl_decode_motion, 2, 2, 0);
+  declare_primitive("%XDecodeUnknownEvent", Prim_scxl_decode_unknown, 2, 2, 0);
+  declare_primitive("%XDecodeWindowAttributes", Prim_scxl_decode_wind_attr, 2, 2, 0);
+  declare_primitive("%XDecodeXColor", Prim_scxl_decode_xcolor, 2, 2, 0);
+  declare_primitive("%XDefaultColormap", Prim_scxl_default_colormap, 2, 2, 0);
+  declare_primitive("%XDefaultRootWindow", Prim_scxl_default_root_window,
+                 1, 1, 0);
+  declare_primitive("%XDefaultScreen", Prim_scxl_default_screen, 1, 1, 0);
+  declare_primitive("%XDestroyRegion", Prim_scxl_destroy_region, 1, 1, 0);
+  declare_primitive("%XDestroyWindow", Prim_scxl_destroy_window, 2, 2, 0);
+  declare_primitive("%XDrawArc", Prim_scxl_draw_arc, 9, 9, 0);
+  declare_primitive("%XDrawLine", Prim_scxl_draw_line, 7, 7, 0);
+  declare_primitive("%XDrawRectangle", Prim_scxl_draw_rectangle, 7, 7, 0);
+  declare_primitive("%XFillArc", Prim_scxl_fill_arc, 9, 9, 0);
+  declare_primitive("%XFillRectangle", Prim_scxl_fill_rectangle, 7, 7, 0);
+  declare_primitive("%XFlush", Prim_scxl_flush, 1, 1, 0);
+  declare_primitive("%XFreeColormap", Prim_scxl_free_colormap, 2, 2, 0);
+  declare_primitive("%XFreeGC", Prim_scxl_free_gc, 2, 2, 0);
+  declare_primitive("%XGetDefault", Prim_scxl_get_default, 3, 3, 0);
+  declare_primitive("%XGetWindowAttributes", Prim_scxl_get_wind_attr, 3, 3, 0);
+  declare_primitive("%XIntersectRegion", Prim_scxl_intersect_reg, 3, 3, 0);
+  declare_primitive("%XLoadFont", Prim_scxl_load_font, 2, 2, 0);
+  declare_primitive("%XMapWindow", Prim_scxl_map_window, 2, 2, 0);
+  declare_primitive("%XNextEvent", Prim_scxl_next_event, 2, 2, 0);
+  declare_primitive("%XOpenDisplay", Prim_scxl_open_display, 1, 1, 0);
+  declare_primitive("%XPending", Prim_scxl_pending, 1, 1, 0);
+  declare_primitive("%XPutBackEvent", Prim_scxl_put_back_event, 2, 2, 0);
+  declare_primitive("%XQueryPointer", Prim_scxl_query_pointer, 3, 3, 0);
+  declare_primitive("%XQueryTree", Prim_query_tree, 2, 2, 0);
+  declare_primitive("%XScreenCount", Prim_scxl_screencount, 1, 1, 0);
+  declare_primitive("%XSetForeground", Prim_scxl_set_foreground, 3, 3, 0);
+  declare_primitive("%XSetFunction", Prim_scxl_set_function, 3, 3, 0);
+  declare_primitive("%XSetRegion", Prim_scxl_set_region, 3, 3, 0);
+  declare_primitive("%XStoreName", Prim_scxl_store_name, 3, 3, 0);
+  declare_primitive("%XSubtractRegion", Prim_scxl_subtract_reg, 3, 3, 0);
+  declare_primitive("%XTranslateCoordinates", Prim_scxl_translate_coords,
+                 6, 6, 0);
+  declare_primitive("%XUnionRegion", Prim_scxl_union_reg, 3, 3, 0);
+  declare_primitive("%XUnionRectSpecsWithRegion!", Prim_scxl_union_rectspecs, 6, 6, 0);
+  declare_primitive("%XUnloadFont", Prim_scxl_unload_font, 2, 2, 0);
+  declare_primitive("%XMake-Color", Prim_scxl_make_color, 0, 0, 0);
+  declare_primitive("%XMake-Event", Prim_scxl_make_event, 0, 0, 0);
+  declare_primitive("%XMake-GCValues", Prim_scxl_make_gc_values, 0, 0, 0);
+  declare_primitive("%XMake-GetWindowAttributes", Prim_scxl_make_get_wind_attr,
+                 0, 0, 0);
+  declare_primitive("%XMake-SetWindowAttributes", Prim_scxl_make_set_wind_attr,
+                 0, 0, 0);
+  declare_primitive("%XSetWindowAttributes-Event_Mask!",
+                 Prim_scxl_XSetWindowAttributes_Event_Mask_bang,
+                 2, 2, 0);
+  declare_primitive("%XInitSCXL!", Prim_scxl_init, 0, 0, 0);
+  declare_primitive("%XSync", Prim_scxl_sync, 2, 2, 0);
+  declare_primitive("%XSynchronize", Prim_scxl_synchronize, 2, 2, 0);
+  declare_primitive("%SetDebugState!", Prim_scxl_state, 1, 1, 0);
+  return "#SCXL";
+}
diff --git a/v7/src/swat/c/tk-c-mit.c b/v7/src/swat/c/tk-c-mit.c
new file mode 100644 (file)
index 0000000..ebc9fd9
--- /dev/null
@@ -0,0 +1,410 @@
+/* -*- C -*-
+/* Uses tk-c.c - Support routines for Tk Widgets called from Scheme */
+/* $Id: tk-c-mit.c,v 1.1 1995/08/02 21:21:00 adams Exp $ */
+
+#include "scheme.h"
+#include "prims.h"
+#include "ansidecl.h"
+#include "X11/Xlib.h"
+#include "tk.h"
+#include "tkInt.h"             /* For TkWindow */
+
+DEFINE_PRIMITIVE ("%tclGlobalEval", Prim_tcl_eval, 2, 2, 0)
+{ /* (%tclGlobalEval TK-main-window string) */
+  Tcl_Interp *tclInterp;
+
+  PRIMITIVE_HEADER(2);
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tcl_GlobalEval(tclInterp, STRING_ARG(2)) != TCL_OK)
+  { fprintf(stderr, "%tclGlobalEval: error '%s'\n",
+           tclInterp->result);
+    error_external_return();
+  }
+  PRIMITIVE_RETURN (char_pointer_to_string
+                   ((unsigned char *) tclInterp->result));
+}
+
+long TKEvent = true;
+DEFINE_PRIMITIVE ("%tkCompletelyHandlesEvent?",
+                 Prim_tk_completely_handles_event, 1, 1, 0)
+{ /* (%tkCompletelyHandlesEvent? event) */
+  XEvent *Event;
+
+  PRIMITIVE_HEADER (1);
+
+  /*  We return 0 if there is a bad argument rather than generating  */
+  /* and error.  This avoids the need to put a                       */
+  /*  dynamic wind around calls to this primitive.                   */
+  /*  Error checking is                                              */
+  /*  done at the next level up, in tk-completely-handles-event?     */
+
+  if (!STRING_P(ARG_REF(1))) PRIMITIVE_RETURN(LONG_TO_UNSIGNED_FIXNUM(0));
+  if (STRING_LENGTH(ARG_REF(1)) < sizeof(XEvent)) 
+           PRIMITIVE_RETURN(LONG_TO_UNSIGNED_FIXNUM(0));
+
+
+  Event = (XEvent *) STRING_ARG(1);
+  TKEvent = true;
+  Tk_HandleEvent(Event);
+  PRIMITIVE_RETURN (BOOLEAN_TO_OBJECT(TKEvent));
+}
+
+void OurTopLevelGeometryProc(ClientData CallBackHash, XEvent *Event)
+{ /* Based on the code for PackStructureProc in tkPack.c.  That code */
+  /* handles four kinds of events: ConfigureNotify, DestroyNotify,   */
+  /* MapNotify, and UnmapNotify.  Here, we consider only the         */
+  /* ConfigureNotify case and reflect it back into Scheme.           */
+
+  if (Event->type == ConfigureNotify)
+  { 
+#include <string.h>
+    extern void
+      AddSchemeCallBack(int argc, char **argv, long *countv);
+    char *argv[2], CallBackNumber[50],
+         EventChars[1+sizeof(XConfigureEvent)];
+    long Counts[2];
+
+    XConfigureEvent *E = (XConfigureEvent *) Event;
+    Counts[0] = sprintf(CallBackNumber, "%d", (long) CallBackHash);
+    argv[0] = CallBackNumber;
+    Counts[1] = sizeof(XConfigureEvent);
+    argv[1] = (char *) E;
+    AddSchemeCallBack(2, argv, Counts);
+  }
+}
+
+DEFINE_PRIMITIVE ("%tkCreateTopLevelWindow", Prim_tk_create_tl_window,
+                 3, 3, 0)
+{ /* (%tkCreateTopLevelWindow MainWindow Name CallBackHash) */
+  Tk_Window Result;
+  Tcl_Interp *tclInterp;
+  
+  PRIMITIVE_HEADER (3);
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  Result =
+    Tk_CreateWindow(tclInterp, (Tk_Window) arg_integer(1),
+                   STRING_ARG(2), "");
+  if (Result == NULL)
+  { fprintf(stderr, "%tkCreateTopLevelWindow: error '%s'\n",
+           tclInterp->result);
+    error_external_return();
+  }
+  Tk_SetWindowBackground(Result,
+                        BlackPixelOfScreen(Tk_Screen(Result)));
+  Tk_CreateEventHandler(Result,
+                       StructureNotifyMask,
+                       OurTopLevelGeometryProc,
+                       (ClientData) arg_integer(3));
+  PRIMITIVE_RETURN (long_to_integer((long) Result));
+}
+\f
+char *TK_CallBack_List;
+long NChars_In_TK_Callbacks = 0;
+
+DEFINE_PRIMITIVE ("%tkDoEvents", Prim_tk_do_events, 0, 0, 0)
+{ /* (%tkDoEvents) */
+  extern void DoTkEvents ();
+  PRIMITIVE_HEADER (0);
+  DoTkEvents();
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkDrainCallBacks", Prim_tk_drain, 2, 2, 0)
+{ /* (%tkDrainCallBacks nchar string)                                */
+  /* Returns the number of characters available in the call back     */
+  /* string if there is NOT enough room in the string to hold all of */
+  /* the characters.  Otherwise, the characters are written into     */
+  /* STRING, C variable is cleared, space freed and the primitive    */
+  /* returns #F.                                                     */
+
+  long NCharsInString;
+  unsigned char *StringSpace;
+
+  PRIMITIVE_HEADER (2);
+  NCharsInString = arg_integer(1);
+  StringSpace = (unsigned char *) STRING_ARG(2);
+  if ((NChars_In_TK_Callbacks != 0) &&
+      (NCharsInString >= NChars_In_TK_Callbacks))
+  { fast unsigned char * scan_result = StringSpace;
+    fast unsigned char * end_result = (scan_result + NChars_In_TK_Callbacks);
+    fast unsigned char * data = (unsigned char *) TK_CallBack_List;
+    while (scan_result < end_result)
+      (*scan_result++) = (*data++);
+    SET_STRING_LENGTH (ARG_REF(2), NChars_In_TK_Callbacks);
+    /* free(TK_CallBack_List); */
+    /* TK_CallBack_List = NULL; */
+    NChars_In_TK_Callbacks = 0;
+    PRIMITIVE_RETURN (SHARP_F);
+  }
+  else
+  { PRIMITIVE_RETURN(long_to_integer(NChars_In_TK_Callbacks));
+  }
+}
+
+void OurEventHandler(ClientData ignored_data, XEvent *ignored_event)
+{ TKEvent = false;
+}
+
+DEFINE_PRIMITIVE ("%tkGenerateSchemeEvent",
+                 Prim_tk_generate_scheme_event, 2, 2, 0)
+{ /* (%tkGenerateSchemeEvent mask TkWindow) */
+  PRIMITIVE_HEADER (2);
+  if (arg_integer(1) == 0)
+    Tk_DeleteEventHandler((Tk_Window) arg_integer(2),
+                         arg_integer(1),
+                         OurEventHandler,
+                         (ClientData) 0);
+  else Tk_CreateEventHandler((Tk_Window) arg_integer(2),
+                            arg_integer(1),
+                            OurEventHandler,
+                            (ClientData) 0);
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkInit", Prim_tk_init, 2, 2, 0)
+{ /* (%tkInit display name) */
+  extern long /*Tk_Window*/ InitTkApplication (long /*Display*/ *display,
+                                              char *Name);
+  PRIMITIVE_HEADER (2);
+  PRIMITIVE_RETURN((long_to_integer
+                   ((long) InitTkApplication
+                    ((long /*Display*/ *) arg_integer(1),
+                     STRING_ARG(2)))));
+}
+
+typedef int (*cmdProc) (ClientData clientData, Tcl_Interp *interp,
+                       int argc, char **argv);
+
+#define NTKCommands 14
+cmdProc TkCommandTable[] =
+{ Tk_AfterCmd, Tk_BindCmd, Tk_DestroyCmd, Tk_FocusCmd, Tk_GrabCmd,
+  Tk_OptionCmd, Tk_PackCmd, Tk_PlaceCmd, Tk_SelectionCmd,
+  Tk_TkCmd, Tk_TkwaitCmd, Tk_UpdateCmd, Tk_WinfoCmd, Tk_WmCmd
+};
+
+DEFINE_PRIMITIVE ("%tkInvokeCommand", Prim_tk_invoke, 2, LEXPR, 0)
+{ /* (%tkInvokeCommand commandnumber tkmainwindow . argstrings) */
+#include "tkInt.h"
+  long WhichCommand, NArgsToPass, i, Result;
+  char **Argv;
+  SCHEME_OBJECT SchemeResult;
+  Tcl_Interp *tclInterp;
+
+  PRIMITIVE_HEADER(LEXPR);
+  WhichCommand = arg_integer(1);
+  tclInterp = (((TkWindow *) arg_integer(2))->mainPtr)->interp;
+  if (WhichCommand > NTKCommands) error_bad_range_arg(1);
+  NArgsToPass = LEXPR_N_ARGUMENTS() - 1;
+  Argv = (char **) malloc((sizeof (char *)) * NArgsToPass);
+  Argv[0] = "<InvokedFromScheme>";
+  for (i=1; i < NArgsToPass; i++) Argv[i] = STRING_ARG(i+2);
+  Result = (TkCommandTable[WhichCommand])((ClientData) arg_integer(2),
+                                         tclInterp,
+                                         NArgsToPass,
+                                         Argv);
+  free(Argv);
+  if (Result != TCL_OK)
+  { fprintf(stderr, "tkInvokeCommand error: %s\n", tclInterp->result);
+    error_external_return();
+  }
+  
+  SchemeResult = (char_pointer_to_string
+                 ((unsigned char *) tclInterp->result));
+  Tcl_ResetResult(tclInterp);
+  PRIMITIVE_RETURN(SchemeResult);
+}
+
+DEFINE_PRIMITIVE ("%tkKillApplication", Prim_tk_kill_app, 1, 1, 0)
+{ /* (%tkKillApplication TKMainWindow) */
+  Tk_Window TKWin;
+  Tcl_Interp *Interp;
+  
+  PRIMITIVE_HEADER (1);
+  TKWin = (Tk_Window) arg_integer(1);
+  Interp = (((TkWindow *) TKWin)->mainPtr)->interp;
+  Tk_DestroyWindow(TKWin);
+  Tcl_DeleteInterp(Interp);
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+void Our_Geometry_Manager(ClientData clientData, Tk_Window tkwin)
+{ extern void AddSchemeCallBack(int argc, char **argv, long *countv);
+  char *argv[1], CallBackNumber[50];
+  long counts[1];
+
+  counts[0] = sprintf(CallBackNumber, "%d", (long) clientData);
+  argv[0] = CallBackNumber;
+  AddSchemeCallBack(1, argv, counts);
+}
+
+DEFINE_PRIMITIVE ("%tkManageGeometry", Prim_tk_manage_geom, 2, 2, 0)
+{ /* (%tkManageGeometry tkwin object-hash) */
+  PRIMITIVE_HEADER (2);
+  if (ARG_REF(2) == SHARP_F)
+    Tk_ManageGeometry((Tk_Window) arg_integer(1), NULL, 0);
+  else Tk_ManageGeometry((Tk_Window) arg_integer(1),
+                        Our_Geometry_Manager,
+                        (ClientData) arg_integer(2));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkMapWidget", Prim_tk_map_widget, 6, 6, 0)
+{ extern char * tk_map_widget (long /*Button*/ *button,
+                              long /*Tk_Window*/ tkMainWindow,
+                              char *name,
+                              long /*Window*/ xwindow,
+                              int x, int y);
+  PRIMITIVE_HEADER(6);
+  PRIMITIVE_RETURN(char_pointer_to_string
+                  ((unsigned char *)
+                   tk_map_widget((long /*Button*/ *) arg_integer(1),
+                                 (long /*Tk_Window*/) arg_integer(2),
+                                 STRING_ARG(3),
+                                 (long /*Window*/) arg_integer(4),
+                                 arg_integer(5),
+                                 arg_integer(6))));
+
+}
+
+DEFINE_PRIMITIVE ("%tkMapWindow", Prim_tk_map_window, 1, 1, 0)
+{ /* (%tkMapWindow TkWindow) returns X Window ID */
+  Tk_Window tkwin;
+
+  PRIMITIVE_HEADER(1);
+  tkwin = (Tk_Window) arg_integer(1);
+  Tk_MapWindow(tkwin);
+  PRIMITIVE_RETURN(long_to_integer((long) Tk_WindowId(tkwin)));
+}
+
+DEFINE_PRIMITIVE ("%tkMoveWindow", Prim_tk_move, 3, 3, 0)
+{ /* (%tkMoveWindow tkwin x y) */
+  PRIMITIVE_HEADER (3);
+  Tk_MoveWindow((Tk_Window) arg_integer(1),
+               (int) arg_integer(2),
+               (int) arg_integer(3));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkMoveResizeWindow", Prim_tk_move_resize, 5, 5, 0)
+{ /* (%tkMoveResizeWindow tkwin x y width height) */
+  PRIMITIVE_HEADER (5);
+  Tk_MoveResizeWindow((Tk_Window) arg_integer(1),
+                     (int) arg_integer(2), (int) arg_integer(3),
+                     (unsigned int) arg_integer(4),
+                     (unsigned int) arg_integer(5));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkNextWakeup", Prim_tk_next_wakeup, 0, 0, 0)
+{ /* (%tkNextWakeup) */
+  /* If the call back list isn't empty, wake up right away. */
+  extern long tk_GetIntervalToNextEvent();
+  long Result =
+    (NChars_In_TK_Callbacks != 0) ? 0 : tk_GetIntervalToNextEvent();
+  
+  if (Result == -1)
+    PRIMITIVE_RETURN(SHARP_F);
+  else PRIMITIVE_RETURN(long_to_integer(Result));
+}
+
+DEFINE_PRIMITIVE ("%tkResizeWindow", Prim_tk_resize, 3, 3, 0)
+{ /* (%tkResizeWindow tkwin width height) */
+  PRIMITIVE_HEADER (3);
+  Tk_ResizeWindow((Tk_Window) arg_integer(1),
+               (int) arg_integer(2),
+               (int) arg_integer(3));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkUnmapWindow", Prim_tk_unmap_window, 1, 1, 0)
+{ /* (%tkUnmapWindow tk-win) */
+  PRIMITIVE_HEADER (1);
+  Tk_UnmapWindow((Tk_Window) arg_integer(1));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkWinReqHeight", Prim_tk_win_req_height, 1, 1, 0)
+{ /* (%tkwinReqHeight tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   ((long) Tk_ReqHeight (arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinReqWidth", Prim_tk_win_req_width, 1, 1, 0)
+{ /* (%tkwinReqWidth tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   ((long) Tk_ReqWidth (arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWidget.tkwin", Prim_tk_widget_get_tkwin, 1, 1, 0)
+{ extern long /*Tk_Window*/ tk_tkwin_widget (long /*button*/ *button);
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN(long_to_integer
+                  ((long) tk_tkwin_widget
+                   ((long /*Button*/ *) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinDisplay", Prim_tk_win_display, 1, 1, 0)
+{ /* (%tkwinDisplay tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   ((long) Tk_Display ((Tk_Window) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinIsMapped?", Prim_tk_win_is_mapped, 1, 1, 0)
+{ /* (%tkwinismapped? tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (BOOLEAN_TO_OBJECT
+                   (Tk_IsMapped ((Tk_Window) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinHeight", Prim_tk_win_height, 1, 1, 0)
+{ /* (%tkwinHeight tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   ((long) Tk_Height ((Tk_Window) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinWidth", Prim_tk_win_width, 1, 1, 0)
+{ /* (%tkwinWidth tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   ((long) Tk_Width ((Tk_Window) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinWindow", Prim_tk_win_window, 1, 1, 0)
+{ /* (%tkwinWindow tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   ((long) Tk_WindowId ((Tk_Window) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinX", Prim_tk_win_x, 1, 1, 0)
+{ /* (%tkwinx tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   ((long) Tk_X ((Tk_Window) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinY", Prim_tk_win_y, 1, 1, 0)
+{ /* (%tkwiny tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (long_to_integer
+                   ((long) Tk_Y ((Tk_Window) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinName", Prim_tk_win_name, 1, 1, 0)
+{ /* (%tkwinname tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (char_pointer_to_string
+                   ((unsigned char *) Tk_Name ((Tk_Window) arg_integer(1))));
+}
+
+DEFINE_PRIMITIVE ("%tkWinPathName", Prim_tk_win_pathname, 1, 1, 0)
+{ /* (%tkwinpathname tk-win) */
+  PRIMITIVE_HEADER(1);
+  PRIMITIVE_RETURN (char_pointer_to_string
+                   ((unsigned char *) Tk_PathName ((Tk_Window) arg_integer(1))));
+}
+
diff --git a/v7/src/swat/c/tk-c.c b/v7/src/swat/c/tk-c.c
new file mode 100644 (file)
index 0000000..af982d3
--- /dev/null
@@ -0,0 +1,308 @@
+/* -*- C -*-
+/* tk-c.c - Support routines for Tk Widgets called from Scheme */
+/* $Id: tk-c.c,v 1.1 1995/08/02 21:21:00 adams Exp $ */
+
+/**********************************************************************
+ This file contains the C code shared between MIT CScheme and DEC
+ Scheme-To-C for interfacing to general TK things.   There are similar
+ files for particular widgets, named things like "button-c.c".  The
+ Scheme implementation specific interface files for this are tk-sc.sc,
+ tk-c-mit.c, and tk-mit.scm.
+**********************************************************************/
+
+#include "tk.h"
+#include  <tcl/tclInt.h>
+#include  <tclHash.h>
+
+/* structure for passing callbacks to the TK Shell */
+
+typedef        struct {
+    char       *name;  /* Name of command       */
+    Tcl_CmdProc *proc;  /* Pointer to procedure  */
+    ClientData  data;   /* Client data           */
+} TKCallbacks, *TKCallbackPtr;
+
+/* shell procedure declaration */
+
+static void    TKShell
+(
+ Tk_Window,         /* Application main window */
+ char *,           /* Name of shell window    */
+ char *,           /* Class name              */
+ TKCallbackPtr     /* Array of callbacks      */
+);
+\f
+/* This procedure is registered with TCL under the name
+   "SchemeCallBack".  TK widgets are given command lines of the form
+   "-command SchemeCallBack n" where "n" is the object ID of the
+   Scheme call back procedure.  Thus, when TK actually calls this
+   procedure, it will pass as argv[1] the Scheme object ID (as a
+   string), followed by any TK-supplied arguments.
+
+   This procedure side-effects the C global variable TK_CallBack_List
+   (in file tk-c-mit.c).  The value of this variable is tested in
+   %tkOwnsEvent? to generate callbacks int Scheme.
+
+   Tk_SchemeCallBack COPIES all of the arguments passed in, since I
+   haven't the vaguest idea how TK handles garbage collection.
+*/
+
+static int NDigits(unsigned long N)
+{ register Ans = 1;
+  while (N > 9)
+  { Ans += 1;
+    N = N/10;
+  }
+  return Ans;
+}
+
+#define TK_CALLBACK_CHUNK_SIZE 256
+static long Size_Of_TK_Callbacks = 0;
+
+void Allocate_TK_Callback(long NChars)
+{ /* Size_Of_TK_Callbacks will always be a multiple of              */
+  /* TK_CALLBACK_CHUNK_SIZE.  It is the total number of bytes       */
+  /* available, and includes space for the terminating null.        */
+  /* NChars_In_TK_Callbacks, however, is the number of useful bytes */
+  /* and does NOT include the terminating null byte.  NChars is the */
+  /* number of bytes to be added to the current contents.           */
+
+  extern char *TK_CallBack_List;
+  extern long NChars_In_TK_Callbacks;
+
+  Size_Of_TK_Callbacks = 
+    (((NChars_In_TK_Callbacks+NChars)/TK_CALLBACK_CHUNK_SIZE)+1) *
+      TK_CALLBACK_CHUNK_SIZE;
+  if (NChars_In_TK_Callbacks == 0)
+    TK_CallBack_List = malloc(Size_Of_TK_Callbacks);
+  else
+    TK_CallBack_List =
+      (char *) realloc(TK_CallBack_List, Size_Of_TK_Callbacks);
+  return;
+}
+    
+extern void AddSchemeCallBack(int argc, char **argv, long *countv)
+{ /* argc is the number of arguments to be transmitted.  They start at */
+  /* argv[0].  This isn't the usual C convention, but it is more       */
+  /* sensible.                                                         */
+  extern char *TK_CallBack_List;
+  extern long NChars_In_TK_Callbacks;
+  register long ThisEntryLength = 0;
+  register long i;
+  register char **This;
+  register long *Count;
+  char *NextEntry;
+  long NChars_To_Add;
+
+  /* First, calculate how much space we need */
+  for (i=0, Count=countv; i < argc; i++)
+  { register long N = *Count++;
+    ThisEntryLength += N + 2 + NDigits(N); /* 2 for < > */
+  }
+  NChars_To_Add =
+    ThisEntryLength + 2 + NDigits(ThisEntryLength); /* 2 more for < > */
+  if ((NChars_In_TK_Callbacks+NChars_To_Add+1) > Size_Of_TK_Callbacks)
+    Allocate_TK_Callback(NChars_To_Add);
+  NextEntry = &(TK_CallBack_List[NChars_In_TK_Callbacks]);
+  NChars_In_TK_Callbacks += NChars_To_Add;
+  /* And start putting in the information */
+  NextEntry += sprintf(NextEntry, "<%d>", ThisEntryLength);
+  for (i=0, This=argv, Count=countv; i < argc; i++, This++, Count++)
+  { NextEntry += sprintf(NextEntry, "<%d>", *Count);
+    memcpy(NextEntry, *This, *Count);
+    NextEntry += *Count;
+  }
+  if (NextEntry != TK_CallBack_List+(NChars_In_TK_Callbacks))
+    fprintf(stderr, "Tk_SchemeCallback %d %s\n",
+           NChars_In_TK_Callbacks, TK_CallBack_List);
+  *NextEntry = '\0';           /* Null terminate the string */
+  return;
+}
+
+int
+Tk_TkError(ClientData clientData,
+          Tcl_Interp *interp,
+          int argc,
+          char **argv)
+{ if (argc==2)
+  { fprintf(stderr, "TCL Error: %s\n", argv[1]);
+    fputs(Tcl_GetVar(interp, "errorInfo", 0), stderr);
+  }
+  else
+    fprintf(stderr, "TCL Error with argc=%d!\n", argc);
+  error_external_return();
+}
+
+int
+Tk_SchemeCallBack(clientData, interp, argc, argv)
+    ClientData clientData;     /* Main window associated with
+                                * interpreter. NOT USED. */
+    Tcl_Interp *interp;                /* Current interpreter. NOT USED. */
+    int argc;                  /* Number of arguments. */
+    char **argv;               /* Argument strings. */
+{ /* As usual, argv[0] is *NOT* used for anything! */
+  long *Counts = (long *) malloc(argc*sizeof(long));
+  register long i, *Count;
+  register char **This;
+
+  if (Counts == NULL)
+  { fprintf(stderr, "Out of space in Tk_SchemeCallBack\n");
+    exit (1);
+  }
+  for (i=1, This=argv+1, Count=Counts+1; i < argc; i++)
+    *Count++ = strlen(*This++);
+  AddSchemeCallBack(argc-1, argv+1, Counts+1);
+  /* Deliberately not changing interp->result, 'cause the TCL manual */
+  /* says we don't have to if we don't want to.                      */
+  return TCL_OK;
+}
+\f
+/*
+ * External Interface Routines
+ */
+
+int Scheme_TK_X_error_handler(ClientData D, XErrorEvent *E)
+{ extern void Scheme_x_error_handler(Display *Disp, XErrorEvent *Event);
+
+  fprintf(stderr, "Our Handler for %d 0x%x\n", D, E);
+  Scheme_x_error_handler((Display *) D, E);
+  return 0;
+}
+
+extern Tk_Window
+InitTkApplication(Display *Disp, char *Name)
+{ Tk_Window Result;
+  extern Tk_Window
+    Tk_CreateMainWindow_from_display(Tcl_Interp *interp,
+                                    Display *display,
+                                    char *baseName);
+  Tcl_Interp *tclInterp = Tcl_CreateInterp();
+/*
+  static char initTCLCmd[] =
+    "source /scheme/users/jmiller/uitk/tk/tcl/library/init.tcl;";
+  static char initTKCmd[] =
+    "source /scheme/users/jmiller/uitk/tk/library/tk.tcl";
+  static char initEmacsCmd[] =
+    "source /scheme/users/jmiller/uitk/tk/library/emacs.tcl";
+*/
+
+  static char initTCLCmd[] =   "source [info library]/init.tcl;";
+  static char initTKCmd[] =    "source $tk_library/tk.tcl";
+  static char initEmacsCmd[] = "source $tk_library/emacs.tcl";
+    
+  Result = Tk_CreateMainWindow_from_display(tclInterp, Disp, Name);
+  if (Result == (Tk_Window) NULL)
+    fprintf(stderr,
+           "Error from Tk_CreateMainWindow: %s\n"
+           , tclInterp->result);
+  if (Tcl_Eval(tclInterp, initTCLCmd, 0, (char **) NULL) != TCL_OK)
+  { char * msg = Tcl_GetVar(tclInterp, "errorInfo", TCL_GLOBAL_ONLY);
+    if (msg == NULL) msg = tclInterp->result;
+    fprintf(stderr, "%s\n", msg);
+    return (Tk_Window) NULL;
+  }
+  /* This must be read for EVERY new main window, since it     */
+  /* establishes bindings and so forth that use "." implicitly */
+  if (Tcl_Eval(tclInterp, initTKCmd, 0, (char **) NULL) != TCL_OK)
+  { char * msg = Tcl_GetVar(tclInterp, "errorInfo", TCL_GLOBAL_ONLY);
+    if (msg == NULL) msg = tclInterp->result;
+    fprintf(stderr, "%s\n", msg);
+    return (Tk_Window) NULL;
+  }
+  if (Tcl_Eval(tclInterp, initEmacsCmd, 0, (char **) NULL) != TCL_OK)
+  { char * msg = Tcl_GetVar(tclInterp, "errorInfo", TCL_GLOBAL_ONLY);
+    if (msg == NULL) msg = tclInterp->result;
+    fprintf(stderr, "%s\n", msg);
+    return (Tk_Window) NULL;
+  }
+  Tcl_CreateCommand(tclInterp,
+                   "SchemeCallBack",
+                   Tk_SchemeCallBack,
+                   (ClientData) 0 /* not used */,
+                   (void (*)()) NULL); /* Delete Procedure */
+  Tcl_CreateCommand(tclInterp,
+                   "tkerror",
+                   Tk_TkError,
+                   (ClientData) 0 /* not used */,
+                   (void (*) ()) NULL); /* Delete Procedure */
+  Tk_CreateErrorHandler(Disp, -1, -1, -1,
+                       Scheme_TK_X_error_handler, (ClientData) Disp);
+  return Result;
+}
+\f
+/*
+ * Process all pending Tk events, then return
+ */
+
+void
+DoTkEvents ()
+{ while (Tk_DoOneEvent (TK_DONT_WAIT|TK_TIMER_EVENTS|TK_IDLE_EVENTS) > 0)
+  { /* fprintf(stderr, "Did TK Event"); */ }
+}
+
+/*  Access the Client Data for a command.  For widget commands,
+ *  this is a pointer to the widget data structure.
+ */
+
+ClientData
+GetCmdClientData (Tcl_Interp *interp, char *cmd)
+
+{
+    Tcl_HashEntry   *hPtr;
+
+    hPtr = Tcl_FindHashEntry (&((Interp *)interp)->commandTable, cmd);
+    return ((Command *) Tcl_GetHashValue (hPtr))->clientData;
+}
+
+/*  Window structure routines.
+ *  These are Macros, so need a functional interface for Scheme
+ */
+
+Display *
+tk_display (Tk_Window tkwin)
+
+{
+    return Tk_Display (tkwin);
+}
+
+Window
+tk_windowid (Tk_Window tkwin)
+
+{
+    return Tk_WindowId (tkwin);
+}
+
+int
+tk_width (Tk_Window tkwin)
+
+{
+    return Tk_Width (tkwin);
+}
+
+int
+tk_height (Tk_Window tkwin)
+
+{
+    return Tk_Height (tkwin);
+}
+
+void
+tk_set_width (Tk_Window tkwin, long W)
+{ Tk_Width(tkwin) = W;
+}
+
+void
+tk_set_height (Tk_Window tkwin, long H)
+{ Tk_Height(tkwin) = H;
+}
+
+/*****************************************************************/
+/* The following procedures OUGHT to be here, but they require   */
+/* internal data structure from tkButton.c to work               */
+/*                                                               */
+/* void                                                          */
+/* tk_map_widget (Button *button, Tk_Window tkMainWindow,        */
+/*                char *name, Window xwindow, int x, int y)      */
+/* Tk_Window                                                     */
+/* tk_tkwin_widget (Button *button)                              */
+/*****************************************************************/
diff --git a/v7/src/swat/c/tk3.2-custom/Makefile b/v7/src/swat/c/tk3.2-custom/Makefile
new file mode 100644 (file)
index 0000000..6c85585
--- /dev/null
@@ -0,0 +1,150 @@
+#
+# This is a simplified Makefile for use in Tk distributions.  Before using
+# it to compile Tk, you may wish to reset some of the following variables:
+#
+# TCL_DIR -            Name of directory holding tcl.h and tcl.a.
+# XLIB -               If your Xlib library isn't in the standard place,
+#                      you can replace "-lX11" with the name of the file
+#                      containing your library archive.
+# INSTALL_DIR -                Full path name of top-level directory where
+#                      information is installed.
+# TK_LIBRARY -         Full path name of directory to contain scripts
+#                      and other library files used by Tk.  This value
+#                      is available to applications as the variable
+#                      $tk_library.  If the environment variable
+#                      TK_LIBRARY is defined by a user, it will override
+#                      the value specified in this Makefile.
+# LIB_DIR -            Directory in which to install the archive libtcl.a
+# BIN_DIR -            Directory in which to install executables such as wish.
+# INCLUDE_DIR -                Directory in which to install header files.
+# MANx_DIR -           Directories in which to install manual entries.
+# RANLIB -             If you're using a System-V-based UNIX that doesn't
+#                      have ranlib, change this definition to "echo" or
+#                      something else harmless.
+# SHELL -              Some versions of make (e.g. SGI's) use this variable
+#                      to determine which shell to use for executing
+#                      commands.
+#
+
+TCL_DIR                = tcl
+XLIB           = -lX11
+INSTALL_DIR    = /usr/local
+LIB_DIR                = $(INSTALL_DIR)/lib
+TK_LIBRARY     = $(INSTALL_DIR)/lib/tk
+BIN_DIR                = $(INSTALL_DIR)/bin
+INCLUDE_DIR    = $(INSTALL_DIR)/include
+MAN1_DIR       = $(INSTALL_DIR)/man/man1
+MAN3_DIR       = $(INSTALL_DIR)/man/man3
+MANN_DIR       = $(INSTALL_DIR)/man/mann
+RANLIB         = ranlib
+SHELL          = /bin/sh
+
+# ANSI-C procedure prototypes are turned on by default if supported
+# by the compiler.  To turn them off, uncomment the following line:
+
+# NP =         -DNO_PROTOTYPE
+
+# To compile under OpenWindows, uncomment the following line:
+
+# OW =         -I/usr/openwin/include -L/usr/openwin/lib
+CC             = cc
+CFLAGS         = -I. -I$(TCL_DIR) -O -DTK_LIBRARY=\"${TK_LIBRARY}\" +z \
+       ${NP} ${OW}
+
+LIBS = libtk.a $(TCL_DIR)/libtcl.a
+
+WIDGOBJS = tkButton.o tkEntry.o tkFrame.o tkListbox.o \
+       tkMenu.o tkMenubutton.o tkMessage.o tkScale.o \
+       tkScrollbar.o
+
+CANVOBJS = tkCanvas.o tkCanvArc.o tkCanvBmap.o tkCanvLine.o \
+       tkCanvPoly.o tkCanvPs.o tkCanvText.o tkCanvWind.o \
+       tkRectOval.o tkTrig.o
+
+TEXTOBJS = tkText.o tkTextBTree.o tkTextDisp.o tkTextIndex.o tkTextTag.o
+
+OBJS = tk3d.o tkArgv.o tkAtom.o tkBind.o tkBitmap.o tkCmds.o \
+       tkColor.o tkConfig.o tkCursor.o tkError.o tkEvent.o \
+       tkFocus.o tkFont.o tkGet.o tkGC.o tkGeometry.o tkGrab.o \
+        tkOption.o tkPack.o tkPlace.o tkPreserve.o tkSelect.o \
+        tkSend.o tkWindow.o tkWm.o $(WIDGOBJS) \
+       $(CANVOBJS) $(TEXTOBJS)
+
+WIDGSRCS = tkButton.c tkEntry.c tkFrame.c tkListbox.c \
+       tkMenu.c tkMenubutton.c tkMessage.c tkScale.c \
+       tkScrollbar.c tkText.c tkTextBTree.c tkTextDisp.c \
+       tkTextIndex.c
+
+CANVSRCS = tkCanvas.c tkCanvArc.c tkCanvBmap.c tkCanvLine.c \
+       tkCanvPoly.c tkCanvPs.c tkCanvText.c tkCanvWind.c \
+       tkRectOval.c tkTrig.c
+
+TEXTSRCS = tkText.c tkTextBTree.c tkTextDisp.c tkTextIndex.c tkTextTag.c
+
+SRCS = tk3d.c tkArgv.c tkAtom.c tkBind.c tkBitmap.c tkCmds.c \
+       tkColor.c tkConfig.c tkCursor.c tkError.c tkEvent.c \
+       tkFocus.c tkFont.c tkGet.c tkGC.c tkGeometry.c tkGrab.c \
+        tkOption.c tkPack.c tkPlace.c tkPreserve.c tkSelect.c \
+        tkSend.c tkWindow.c tkWm.c $(WIDGSRCS) \
+       $(CANVSRCS) $(TEXTSRCS)
+
+all: libtk.a wish
+
+wish: main.o $(LIBS)
+       $(CC) $(CFLAGS) main.o $(LIBS) $(XLIB) -lm -o wish
+
+libtk.a: $(OBJS)
+       rm -f libtk.a
+       ar cr libtk.a $(OBJS)
+       $(RANLIB) libtk.a
+
+$(TCL_DIR)/libtcl.a:
+       cd $(TCL_DIR); $(MAKE) $(MFLAGS) TCL_LIBRARY=$(TCL_LIBRARY) libtcl.a
+
+install: libtk.a wish $(TCL_DIR)/libtcl.a
+       -if [ ! -d $(LIB_DIR) ] ; then mkdir -p $(LIB_DIR); fi
+       -if [ ! -d $(INCLUDE_DIR) ] ; then mkdir -p $(INCLUDE_DIR); fi
+       -if [ ! -d $(TK_LIBRARY) ] ; then mkdir -p $(TK_LIBRARY); fi
+       -if [ ! -d $(BIN_DIR) ] ; then mkdir -p $(BIN_DIR); fi
+       -if [ ! -d $(MAN1_DIR) ] ; then mkdir -p $(MAN1_DIR); fi
+       -if [ ! -d $(MAN3_DIR) ] ; then mkdir -p $(MAN3_DIR); fi
+       -if [ ! -d $(MANN_DIR) ] ; then mkdir -p $(MANN_DIR); fi
+       rm -rf $(TK_LIBRARY)/*
+       cp -r library/*.tcl library/tclIndex library/demos $(TK_LIBRARY)
+       cp library/prolog.ps $(TK_LIBRARY)
+       rm -f $(LIB_DIR)/libtk.a
+       cp libtk.a $(LIB_DIR)
+       $(RANLIB) $(LIB_DIR)/libtk.a
+       rm -f $(BIN_DIR)/wish
+       cp wish $(BIN_DIR)
+       rm -f $(INCLUDE_DIR)/tk.h
+       cp tk.h $(INCLUDE_DIR)
+       cd doc; for i in *.1; \
+           do \
+           rm -f $(MAN1_DIR)/$$i; \
+           sed -e '/man\.macros/r man.macros' -e '/man\.macros/d' \
+                   $$i > $(MAN1_DIR)/$$i; \
+           done; cd ..
+       cd doc; for i in *.3; \
+           do \
+           rm -f $(MAN3_DIR)/$$i; \
+           sed -e '/man\.macros/r man.macros' -e '/man\.macros/d' \
+                   $$i > $(MAN3_DIR)/$$i; \
+           done; cd ..
+       cd doc; for i in *.n; \
+           do \
+           rm -f $(MANN_DIR)/$$i; \
+           sed -e '/man\.macros/r man.macros' -e '/man\.macros/d' \
+                   $$i > $(MANN_DIR)/$$i; \
+           done; cd ..
+       cd $(TCL_DIR); $(MAKE) $(MFLAGS) INSTALL_DIR=$(INSTALL_DIR) install
+
+clean:
+       rm -f $(OBJS) main.o libtk.a wish
+       cd $(TCL_DIR); $(MAKE) $(MFLAGS) clean
+
+$(OBJS): tk.h tkInt.h tkConfig.h
+$(WIDGOBJS): default.h
+$(CANVOBJS): default.h tkCanvas.h
+$(TEXTOBJS): default.h tkText.h
+main.o: tk.h tkInt.h
diff --git a/v7/src/swat/c/tk3.2-custom/library/emacs.tcl b/v7/src/swat/c/tk3.2-custom/library/emacs.tcl
new file mode 100644 (file)
index 0000000..68cb662
--- /dev/null
@@ -0,0 +1,203 @@
+#-----------------------------------------------------------------------------
+#  Emacs-like bindings for Tk text widgets
+#
+#      Andrew C. Payne
+#      payne@crl.dec.com
+#
+#-----------------------------------------------------------------------------
+
+set tk_priv(cutbuffer) ""
+
+#-----------------------------------------------------------------------------
+# Keyboard bindings, model after emacs
+#-----------------------------------------------------------------------------
+
+proc emacs-text-move {w where} {
+       global tk_priv
+
+       $w mark set insert $where
+       $w yview -pickplace insert
+       if {$tk_priv(selectMode) == "select"} {
+               $w tag remove sel 0.0 end
+               $w tag add sel anchor insert
+       }
+}
+
+proc emacs-twiddle {w} {
+       set c [$w get insert-1c]
+       $w delete insert-1c
+       $w insert insert-1c $c
+}
+
+proc emacs-move-page {w dir} {
+       global tk_priv
+
+        set height [lindex [$w configure -height] 4]
+        $w mark set insert "insert $dir $height lines"
+        $w yview -pickplace insert
+       if {$tk_priv(selectMode) == "select"} {
+               $w tag remove sel 0.0 end
+               $w tag add sel anchor insert
+       }
+}
+
+#
+#  If there is a current selection, delete it.  Else, backspace one character
+#
+proc emacs-backspace {w} {
+       if {[catch {$w delete sel.first sel.last}]} {
+               tk_textBackspace $w
+       }
+       $w yview -pickplace insert      
+}
+
+bind Text <Any-KeyPress> {
+       if {%k == 140} {
+               set tk_priv(selectMode) {}
+               catch {set tk_priv(cutbuffer) [%W get sel.first sel.last]}
+               catch {%W delete sel.first sel.last}
+       }
+       if {"%A" != ""} {
+               %W insert insert %A
+       }
+       %W yview -pickplace insert
+}
+
+# By default, all the control and meta keys are disabled
+bind Text <Control-Key> {
+    %W yview -pickplace insert
+}
+bind Text <Meta-Key> {
+    %W yview -pickplace insert
+}
+bind Text <Control-Meta-Key> {
+    %W yview -pickplace insert
+}
+bind Text <Escape> {
+    %W yview -pickplace insert
+}
+
+set tk_last_deleted ""
+bind Text <Control-k>  {
+       global tk_last_deleted
+       set tk_last_deleted [%W get insert {insert lineend}]
+        %W delete insert {insert lineend}
+}
+bind Text <Control-y>   {
+       global tk_last_deleted
+       %W insert insert $tk_last_deleted
+        %W yview -pickplace insert
+}
+bind Text <Up>                 {emacs-text-move %W insert-1l}
+bind Text <Down>       {emacs-text-move %W insert+1l}
+bind Text <Left>       {emacs-text-move %W insert-1c}
+bind Text <Right>      {emacs-text-move %W insert+1c}
+
+bind Text <Control-a>  {emacs-text-move %W {insert linestart}}
+bind Text <Control-b>  {emacs-text-move %W insert-1c}
+bind Text <Control-d>  {%W delete insert insert+1c}
+bind Text <Control-e>  {emacs-text-move %W {insert lineend}}
+bind Text <Control-f>  {emacs-text-move %W insert+1c}
+bind Text <Control-h>  {emacs-backspace %W}
+bind Text <Control-n>  {emacs-text-move %W insert+1l}
+bind Text <Control-o>  {%W insert insert "\n"; emacs-text-move %W insert-1c}
+bind Text <Control-p>  {emacs-text-move %W insert-1l}
+bind Text <Control-t>  {emacs-twiddle %W}
+bind Text <Control-v>  {emacs-move-page %W +}
+
+bind Text <Prior>      {emacs-move-page %W -}
+bind Text <Next>       {emacs-move-page %W +}
+bind Text <Delete>     {emacs-backspace %W}
+
+bind Text <Insert> {
+        %W insert insert $tk_priv(cutbuffer)
+        %W yview -pickplace insert
+}
+
+bind Text <Select> {
+       %W tag remove sel 0.0 end
+       if {$tk_priv(selectMode) == "select"} {
+               set tk_priv(selectMode) {}
+       } {
+               %W mark set anchor insert
+               set tk_priv(selectMode) select
+       }
+}
+
+
+#-----------------------------------------------------------------------------
+#  Mouse bindings
+#-----------------------------------------------------------------------------
+
+bind Text <1> {
+       set tk_priv(selectMode) char
+       %W mark set insert @%x,%y
+       %W mark set anchor insert
+       if {[lindex [%W config -state] 4] == "normal"} {focus %W}
+       %W tag remove sel 0.0 end
+}
+
+#
+#  Button 2 is used to paste the current X selection, just like many X
+#  applications.  This is the default Motif binding.
+#
+bind Text <2> {
+       catch { 
+               %W insert insert [selection get]
+               %W yview -pickplace insert
+       }
+}
+
+bind Text <B2-Motion> {}
+
+#
+#  Use button 3 as a drag for window text (just like the old Tk button 2
+#  binding.
+#
+bind Text <3>          {%W scan mark %y}
+bind Text <B3-Motion>  {%W scan dragto %y}
+
+
+#-----------------------------------------------------------------------------
+#  Emacs-like bindings for Tk entry widgets
+#-----------------------------------------------------------------------------
+
+# By default, all the control and meta keys are disabled
+bind Entry <Control-Key> {
+    tk_entrySeeCaret %W
+}
+bind Entry <Meta-Key> {
+    tk_entrySeeCaret %W
+}
+bind Entry <Control-Meta-Key> {
+    tk_entrySeeCaret %W
+}
+bind Entry <Escape> {
+    tk_entrySeeCaret %W
+}
+
+# need to repeat these because they've just been overwritten
+bind Entry <Control-h> {tk_entryBackspace %W; tk_entrySeeCaret %W}
+bind Entry <Control-u> {%W delete 0 end}
+bind Entry <Control-v> {%W insert insert [selection get]; tk_entrySeeCaret %W}
+bind Entry <Control-w> {tk_entryBackword %W; tk_entrySeeCaret %W}
+
+# Some Emacs bindings
+bind Entry <Control-a> {%W icursor 0; tk_entrySeeCaret %W}
+bind Entry <Control-e> {%W icursor end; tk_entrySeeCaret %W}
+bind Entry <Control-k> {%W delete insert end}
+bind Entry <Control-d> {%W delete insert}
+
+set entry_cursor_index ""
+bind Entry <Control-f> {
+    global entry_cursor_index
+    set entry_cursor_index [expr {[%W index insert] + 1}]
+    %W icursor $entry_cursor_index
+}
+bind Entry <Control-b> {
+    global entry_cursor_index
+    set entry_cursor_index [expr {[%W index insert] - 1}]
+    %W icursor $entry_cursor_index
+}
+
diff --git a/v7/src/swat/c/tk3.2-custom/tcl/Makefile b/v7/src/swat/c/tk3.2-custom/tcl/Makefile
new file mode 100644 (file)
index 0000000..eb3ea33
--- /dev/null
@@ -0,0 +1,128 @@
+#
+# This Makefile is for use when distributing Tcl to the outside world.
+# It is normally set up by running the "config" script.  Before modifying
+# this file by hand, you should read through the "config" script to see
+# what it does.
+#
+# Some changes you may wish to make here:
+#
+# 1. To compile for non-UNIX systems (so that only the non-UNIX-specific
+# commands are available), change the OBJS line below so it doesn't
+# include ${UNIX_OBJS}.  Also, add the switch "-DTCL_GENERIC_ONLY" to
+# CFLAGS.  Lastly, you'll have to provide your own replacement for the
+# "panic" procedure (see panic.c for what the current one does).
+
+# 2. ANSI-C procedure prototypes are turned on by default if supported
+# by the compiler.  To turn them off, uncomment the following line:
+
+# NP =         -DNO_PROTOTYPE
+
+# 3. If you want to put Tcl-related information in non-standard places,
+# change the following definitions below to reflect where you want
+# things (all must be specified as full rooted path names):
+#
+#    INSTALL_DIR       Top-level directory in which to install;  contains
+#                      each of the other directories below.
+#    TCL_LIBRARY       Directory in which to install the library of Tcl
+#                      scripts.  Note: if the TCL_LIBRARY environment
+#                      variable is specified at run-time then Tcl looks
+#                      there rather than in the place specified here.
+#    LIB_DIR           Directory in which to install the archive libtcl.a
+#    INCLUDE_DIR       Directory in which to install include files.
+#    MAN3_DIR          Directory in which to install manual entries for
+#                      library procedures such as Tcl_Eval.
+#    MANN_DIR          Directory in which to install manual entries for
+#                      miscellaneous things such as the Tcl overview
+#                      manual entry.
+#    RANLIB            If you're using a System-V-based UNIX that doesn't
+#                      have ranlib, change this definition to "echo" or
+#                      something else harmless.
+#    SHELL             Some versions of make (e.g. SGI's) use this variable
+#                      to determine which shell to use for executing
+#                      commands.
+
+INSTALL_DIR =  /usr/local
+TCL_LIBRARY =  $(INSTALL_DIR)/lib/tcl
+LIB_DIR =      $(INSTALL_DIR)/lib
+INCLUDE_DIR =  $(INSTALL_DIR)/include
+MAN3_DIR =     $(INSTALL_DIR)/man/man3
+MANN_DIR =     $(INSTALL_DIR)/man/mann
+RANLIB =       ranlib
+SHELL =                /bin/sh
+
+CC =           cc
+CFLAGS =       -O -I. -DTCL_LIBRARY=\"${TCL_LIBRARY}\" ${NP} +z
+
+GENERIC_OBJS = regexp.o tclAssem.o tclBasic.o tclCkalloc.o \
+       tclCmdAH.o tclCmdIL.o tclCmdMZ.o tclExpr.o tclGet.o \
+       tclHash.o tclHistory.o tclParse.o tclProc.o tclUtil.o \
+       tclVar.o
+
+UNIX_OBJS = panic.o tclEnv.o tclGlob.o tclUnixAZ.o tclUnixStr.o \
+       tclUnixUtil.o 
+
+COMPAT_OBJS =
+
+OBJS = ${GENERIC_OBJS} ${UNIX_OBJS} ${COMPAT_OBJS}
+
+all: libtcl.a
+
+libtcl.a: ${OBJS}
+       rm -f libtcl.a
+       ar cr libtcl.a ${OBJS}
+       $(RANLIB) libtcl.a
+
+install: libtcl.a
+       -if [ ! -d $(LIB_DIR) ] ; then mkdir -p $(LIB_DIR); fi
+       -if [ ! -d $(TCL_LIBRARY) ] ; then mkdir -p $(TCL_LIBRARY); fi
+       -if [ ! -d $(INCLUDE_DIR) ] ; then mkdir -p $(INCLUDE_DIR); fi
+       -if [ ! -d $(MAN3_DIR) ] ; then mkdir -p $(MAN3_DIR); fi
+       -if [ ! -d $(MANN_DIR) ] ; then mkdir -p $(MANN_DIR); fi
+       rm -rf $(TCL_LIBRARY)/*
+       for i in library/*.tcl library/tclIndex; \
+           do \
+           cp $$i $(TCL_LIBRARY);  \
+           done
+       rm -f $(LIB_DIR)/libtcl.a
+       cp libtcl.a $(LIB_DIR)
+       $(RANLIB) $(LIB_DIR)/libtcl.a
+       rm -f $(INCLUDE_DIR)/tcl.h $(INCLUDE_DIR)/tclHash.h
+       cp tcl.h $(INCLUDE_DIR)
+       cp tclHash.h $(INCLUDE_DIR)
+       cd doc; for i in *.3; \
+           do \
+           rm -f $(MAN3_DIR)/$$i; \
+           sed -e '/man\.macros/r man.macros' -e '/man\.macros/d' \
+                   $$i > $(MAN3_DIR)/$$i; \
+           done; cd ..
+       cd doc; for i in *.n; \
+           do \
+           rm -f $(MANN_DIR)/$$i; \
+           sed -e '/man\.macros/r man.macros' -e '/man\.macros/d' \
+                   $$i > $(MANN_DIR)/$$i; \
+           done; cd ..
+
+tclTest: tclTest.o libtcl.a
+       ${CC} ${CFLAGS} tclTest.o libtcl.a -o tclTest
+
+test: tclTest
+       ( echo cd tests ; echo source all ) | ./tclTest
+
+configured:
+       @echo "The configuration script \"./config\" hasn't been run"
+       @echo "successfully yet.  Please run it as described in the "
+       @echo "README file, then run make again."
+       exit 1
+
+clean:
+       rm -f ${OBJS} libtcl.a tclTest.o tclTest
+
+# The following target is used during configuration to compile
+# a test program to see if certain facilities are available on
+# the system.
+
+configtest:
+       ${CC} ${CFLAGS} test.c
+
+${OBJS}: tcl.h tclHash.h tclInt.h configured
+${UNIX_OBJS}: tclUnix.h
diff --git a/v7/src/swat/c/tk3.2-custom/tcl/tclUnix.h b/v7/src/swat/c/tk3.2-custom/tcl/tclUnix.h
new file mode 100644 (file)
index 0000000..1c6ad4c
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * tclUnix.h --
+ *
+ *     This file reads in UNIX-related header files and sets up
+ *     UNIX-related macros for Tcl's UNIX core.  It should be the
+ *     only file that contains #ifdefs to handle different flavors
+ *     of UNIX.  This file sets up the union of all UNIX-related
+ *     things needed by any of the Tcl core files.  This file
+ *     depends on configuration #defines in tclConfig.h
+ *
+ *     The material in this file was originally contributed by
+ *     Karl Lehenbauer, Mark Diekhans and Peter da Silva.
+ *
+ * Copyright 1991 Regents of the University of California
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that this copyright
+ * notice appears in all copies.  The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ *
+ * $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/swat/c/tk3.2-custom/tcl/tclUnix.h,v 1.1 1995/08/02 21:24:59 adams Exp $ SPRITE (Berkeley)
+ */
+
+#ifndef _TCLUNIX
+#define _TCLUNIX
+
+/*
+ * The following #defines are used to distinguish between different
+ * UNIX systems.  These #defines are normally set by the "config" script
+ * based on information it gets by looking in the include and library
+ * areas.  The defaults below are for BSD-based systems like SunOS
+ * or Ultrix.
+ *
+ * TCL_GETTOD -                        1 means there exists a library procedure
+ *                             "gettimeofday" (e.g. BSD systems).  0 means
+ *                             have to use "times" instead.
+ * TCL_GETWD -                 1 means there exists a library procedure
+ *                             "getwd" (e.g. BSD systems).  0 means
+ *                             have to use "getcwd" instead.
+ * TCL_SYS_ERRLIST -           1 means that the array sys_errlist is
+ *                             defined as part of the C library.
+ * TCL_SYS_TIME_H -            1 means there exists an include file
+ *                             <sys/time.h> (e.g. BSD derivatives).
+ * TCL_SYS_WAIT_H -            1 means there exists an include file
+ *                             <sys/wait.h> that defines constants related
+ *                             to the results of "wait".
+ * TCL_UNION_WAIT -            1 means that the "wait" system call returns
+ *                             a structure of type "union wait" (e.g. BSD
+ *                             systems).  0 means "wait" returns an int
+ *                             (e.g. System V and POSIX).
+ * TCL_PID_T -                 1 means that <sys/types> defines the type
+ *                             pid_t.  0 means that it doesn't.
+ * TCL_UID_T -                 1 means that <sys/types> defines the type
+ *                             uid_t.  0 means that it doesn't.
+ */
+
+#define TCL_GETTOD 1
+#define TCL_GETWD 1
+#define TCL_SYS_ERRLIST 1
+#define TCL_SYS_TIME_H 1
+#define TCL_SYS_WAIT_H 1
+#define TCL_UNION_WAIT 0
+#define TCL_PID_T 1
+#define TCL_UID_T 1
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#if TCL_SYS_TIME_H
+#   include <sys/time.h>
+#else
+#   include <time.h>
+#endif
+#if TCL_SYS_WAIT_H
+#   include <sys/wait.h>
+#endif
+
+/*
+ * Not all systems declare the errno variable in errno.h. so this
+ * file does it explicitly.  The list of system error messages also
+ * isn't generally declared in a header file anywhere.
+ */
+
+extern int errno;
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+/*
+ * The type of the status returned by wait varies from UNIX system
+ * to UNIX system.  The macro below defines it:
+ */
+
+#if TCL_UNION_WAIT
+#   define WAIT_STATUS_TYPE union wait
+#else
+#   define WAIT_STATUS_TYPE int
+#endif
+
+/*
+ * Supply definitions for macros to query wait status, if not already
+ * defined in header files above.
+ */
+
+#ifndef WIFEXITED
+#   define WIFEXITED(stat)  (((*((int *) &(stat))) & 0xff) == 0)
+#endif
+
+#ifndef WEXITSTATUS
+#   define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff)
+#endif
+
+#ifndef WIFSIGNALED
+#   define WIFSIGNALED(stat) (((*((int *) &(stat)))) && ((*((int *) &(stat))) == ((*((int *) &(stat))) & 0x00ff)))
+#endif
+
+#ifndef WTERMSIG
+#   define WTERMSIG(stat)    ((*((int *) &(stat))) & 0x7f)
+#endif
+
+#ifndef WIFSTOPPED
+#   define WIFSTOPPED(stat)  (((*((int *) &(stat))) & 0xff) == 0177)
+#endif
+
+#ifndef WSTOPSIG
+#   define WSTOPSIG(stat)    (((*((int *) &(stat))) >> 8) & 0xff)
+#endif
+
+/*
+ * Supply macros for seek offsets, if they're not already provided by
+ * an include file.
+ */
+
+#ifndef SEEK_SET
+#   define SEEK_SET 0
+#endif
+
+#ifndef SEEK_CUR
+#   define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#   define SEEK_END 2
+#endif
+
+/*
+ * The stuff below is needed by the "time" command.  If this
+ * system has no gettimeofday call, then must use times and the
+ * CLK_TCK #define (from sys/param.h) to compute elapsed time.
+ * Unfortunately, some systems only have HZ and no CLK_TCK, and
+ * some might not even have HZ.
+ */
+
+#if ! TCL_GETTOD
+#   include <sys/times.h>
+#   include <sys/param.h>
+#   ifndef CLK_TCK
+#       ifdef HZ
+#           define CLK_TCK HZ
+#       else
+#           define CLK_TCK 60
+#       endif
+#   endif
+#endif
+
+/*
+ * Define access mode constants if they aren't already defined.
+ */
+
+#ifndef F_OK
+#    define F_OK 00
+#endif
+#ifndef X_OK
+#    define X_OK 01
+#endif
+#ifndef W_OK
+#    define W_OK 02
+#endif
+#ifndef R_OK
+#    define R_OK 04
+#endif
+
+/*
+ * On systems without symbolic links (i.e. S_IFLNK isn't defined)
+ * define "lstat" to use "stat" instead.
+ */
+
+#ifndef S_IFLNK
+#   define lstat stat
+#endif
+
+/*
+ * Define macros to query file type bits, if they're not already
+ * defined.
+ */
+
+#ifndef S_ISREG
+#   ifdef S_IFREG
+#       define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#   else
+#       define S_ISREG(m) 0
+#   endif
+# endif
+#ifndef S_ISDIR
+#   ifdef S_IFDIR
+#       define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#   else
+#       define S_ISDIR(m) 0
+#   endif
+# endif
+#ifndef S_ISCHR
+#   ifdef S_IFCHR
+#       define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#   else
+#       define S_ISCHR(m) 0
+#   endif
+# endif
+#ifndef S_ISBLK
+#   ifdef S_IFBLK
+#       define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#   else
+#       define S_ISBLK(m) 0
+#   endif
+# endif
+#ifndef S_ISFIFO
+#   ifdef S_IFIFO
+#       define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#   else
+#       define S_ISFIFO(m) 0
+#   endif
+# endif
+#ifndef S_ISLNK
+#   ifdef S_IFLNK
+#       define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#   else
+#       define S_ISLNK(m) 0
+#   endif
+# endif
+#ifndef S_ISSOCK
+#   ifdef S_IFSOCK
+#       define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#   else
+#       define S_ISSOCK(m) 0
+#   endif
+# endif
+
+/*
+ * Make sure that MAXPATHLEN is defined.
+ */
+
+#ifndef MAXPATHLEN
+#   ifdef PATH_MAX
+#       define MAXPATHLEN PATH_MAX
+#   else
+#       define MAXPATHLEN 2048
+#   endif
+#endif
+
+/*
+ * Define pid_t and uid_t if they're not already defined.
+ */
+
+#if ! TCL_PID_T
+#   define pid_t int
+#endif
+#if ! TCL_UID_T
+#   define uid_t int
+#endif
+
+/*
+ * Variables provided by the C library:
+ */
+
+#if defined(_sgi) || defined(__sgi)
+#define environ _environ
+#endif
+extern char **environ;
+
+/*
+ * Library procedures used by Tcl but not declared in a header file:
+ */
+
+#ifndef _CRAY
+extern int     access     _ANSI_ARGS_((CONST char *path, int mode));
+extern int     chdir      _ANSI_ARGS_((CONST char *path));
+extern int     close      _ANSI_ARGS_((int fd));
+extern int     dup2       _ANSI_ARGS_((int src, int dst));
+extern void    endpwent   _ANSI_ARGS_((void));
+extern int     execvp     _ANSI_ARGS_((CONST char *name, char **argv));
+extern void    _exit      _ANSI_ARGS_((int status));
+extern pid_t   fork       _ANSI_ARGS_((void));
+extern uid_t   geteuid    _ANSI_ARGS_((void));
+extern pid_t   getpid     _ANSI_ARGS_((void));
+extern char *  getcwd     _ANSI_ARGS_((char *buffer, int size));
+extern char *  getwd      _ANSI_ARGS_((char *buffer));
+extern int     kill       _ANSI_ARGS_((pid_t pid, int sig));
+extern long    lseek      _ANSI_ARGS_((int fd, int offset, int whence));
+extern char *  mktemp     _ANSI_ARGS_((char *template));
+#if !(defined(sparc) || defined(_IBMR2))
+extern int     open       _ANSI_ARGS_((CONST char *path, int flags, ...));
+#endif
+extern int     pipe       _ANSI_ARGS_((int *fdPtr));
+extern int     read       _ANSI_ARGS_((int fd, char *buf, int numBytes));
+extern int     readlink   _ANSI_ARGS_((CONST char *path, char *buf, int size));
+extern int     unlink     _ANSI_ARGS_((CONST char *path));
+extern int     write      _ANSI_ARGS_((int fd, char *buf, int numBytes));
+#endif /* _CRAY */
+
+#endif /* _TCLUNIX */
diff --git a/v7/src/swat/c/tk3.2-custom/tkEvent.c b/v7/src/swat/c/tk3.2-custom/tkEvent.c
new file mode 100644 (file)
index 0000000..4c324bc
--- /dev/null
@@ -0,0 +1,1675 @@
+/* 
+ * tkEvent.c --
+ *
+ *     This file provides basic event-managing facilities,
+ *     whereby procedure callbacks may be attached to
+ *     certain events.
+ *
+ * Copyright 1990-1992 Regents of the University of California.
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies.  The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ */
+
+/* ADDED tk_GetIntervalToNextEvent */
+
+#ifndef lint
+static char rcsid[] = "$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/swat/c/tk3.2-custom/tkEvent.c,v 1.1 1995/08/02 21:23:26 adams Exp $ SPRITE (Berkeley)";
+#endif
+
+#include "tkConfig.h"
+#include "tkInt.h"
+#include <errno.h>
+#include <signal.h>
+
+/*
+ * For each timer callback that's pending, there is one record
+ * of the following type, chained together in a list sorted by
+ * time (earliest event first).
+ */
+
+typedef struct TimerEvent {
+    struct timeval time;       /* When timer is to fire. */
+    void (*proc)  _ANSI_ARGS_((ClientData clientData));
+                               /* Procedure to call. */
+    ClientData clientData;     /* Argument to pass to proc. */
+    Tk_TimerToken token;       /* Identifies event so it can be
+                                * deleted. */
+    struct TimerEvent *nextPtr;        /* Next event in queue, or NULL for
+                                * end of queue. */
+} TimerEvent;
+
+static TimerEvent *timerQueue; /* First event in queue. */
+
+/*
+ * The information below is used to provide read, write, and
+ * exception masks to select during calls to Tk_DoOneEvent.
+ */
+
+static int readCount;          /* Number of files for which we */
+static int writeCount;         /* care about each event type. */
+static int exceptCount;
+#define MASK_SIZE ((OPEN_MAX+(8*sizeof(int))-1)/(8*sizeof(int)))
+static int masks[3*MASK_SIZE]; /* Integer array containing official
+                                * copies of the three sets of
+                                * masks. */
+static int ready[3*MASK_SIZE]; /* Temporary copy of masks, passed
+                                * to select and modified by kernel
+                                * to indicate which files are
+                                * actually ready. */
+static int *readPtr;           /* Pointers to the portions of */
+static int *writePtr;          /* *readyPtr for reading, writing, */
+static int *exceptPtr;         /* and excepting.  Will be NULL if
+                                * corresponding count (e.g. readCount
+                                * is zero. */
+static int numFds = 0;         /* Number of valid bits in mask
+                                * arrays (this value is passed
+                                * to select). */
+
+/*
+ * For each file registered in a call to Tk_CreateFileHandler,
+ * and for each display that's currently active, there is one
+ * record of the following type.  All of these records are
+ * chained together into a single list.
+ */
+
+typedef struct FileEvent {
+    int fd;                    /* Descriptor number for this file. */
+    int *readPtr;              /* Pointer to word in ready array
+                                * for this file's read mask bit. */
+    int *writePtr;             /* Same for write mask bit. */
+    int *exceptPtr;            /* Same for except mask bit. */
+    int mask;                  /* Value to AND with mask word to
+                                * select just this file's bit. */
+    void (*proc)  _ANSI_ARGS_((ClientData clientData, int mask));
+                               /* Procedure to call.  NULL means
+                                * this is a display. */
+    ClientData clientData;     /* Argument to pass to proc.  For
+                                * displays, this is a (Display *). */
+    struct FileEvent *nextPtr; /* Next in list of all files we
+                                * care about (NULL for end of
+                                * list). */
+} FileEvent;
+
+static FileEvent *fileList;    /* List of all file events. */
+
+/*
+ * There is one of the following structures for each of the
+ * handlers declared in a call to Tk_DoWhenIdle.  All of the
+ * currently-active handlers are linked together into a list.
+ */
+
+typedef struct IdleHandler {
+    void (*proc)  _ANSI_ARGS_((ClientData clientData));
+                               /* Procedure to call. */
+    ClientData clientData;     /* Value to pass to proc. */
+    int generation;            /* Used to distinguish older handlers from
+                                * recently-created ones. */
+    struct IdleHandler *nextPtr;/* Next in list of active handlers. */
+} IdleHandler;
+
+static IdleHandler *idleList = NULL;
+                               /* First in list of all idle handlers. */
+static IdleHandler *lastIdlePtr = NULL;
+                               /* Last in list (or NULL for empty list). */
+static int idleGeneration = 0; /* Used to fill in the "generation" fields
+                                * of IdleHandler structures.  Increments
+                                * each time Tk_DoOneEvent starts calling
+                                * idle handlers, so that all old handlers
+                                * can be called without calling any of the
+                                * new ones created by old ones. */
+
+/*
+ * There's a potential problem if a handler is deleted while it's
+ * current (i.e. its procedure is executing), since Tk_HandleEvent
+ * will need to read the handler's "nextPtr" field when the procedure
+ * returns.  To handle this problem, structures of the type below
+ * indicate the next handler to be processed for any (recursively
+ * nested) dispatches in progress.  The nextHandler fields get
+ * updated if the handlers pointed to are deleted.  Tk_HandleEvent
+ * also needs to know if the entire window gets deleted;  the winPtr
+ * field is set to zero if that particular window gets deleted.
+ */
+
+typedef struct InProgress {
+    XEvent *eventPtr;           /* Event currently being handled. */
+    TkWindow *winPtr;           /* Window for event.  Gets set to None if
+                                 * window is deleted while event is being
+                                 * handled. */
+    TkEventHandler *nextHandler; /* Next handler in search. */
+    struct InProgress *nextPtr;         /* Next higher nested search. */
+} InProgress;
+
+static InProgress *pendingPtr = NULL;
+                               /* Topmost search in progress, or
+                                * NULL if none. */
+
+/*
+ * For each call to Tk_CreateGenericHandler, an instance of the following
+ * structure will be created.  All of the active handlers are linked into a
+ * list.
+ */
+
+typedef struct GenericHandler {
+    Tk_GenericProc *proc;      /* Procedure to dispatch on all X events. */
+    ClientData clientData;     /* Client data to pass to procedure. */
+    int deleteFlag;            /* Flag to set when this handler is deleted. */
+    struct GenericHandler *nextPtr;
+                               /* Next handler in list of all generic
+                                * handlers, or NULL for end of list. */
+} GenericHandler;
+
+static GenericHandler *genericList = NULL;
+                               /* First handler in the list, or NULL. */
+static GenericHandler *lastGenericPtr = NULL;
+                               /* Last handler in list. */
+
+/*
+ * There's a potential problem if Tk_HandleEvent is entered recursively.
+ * A handler cannot be deleted physically until we have returned from
+ * calling it.  Otherwise, we're looking at unallocated memory in advancing to
+ * its `next' entry.  We deal with the problem by using the `delete flag' and
+ * deleting handlers only when it's known that there's no handler active.
+ *
+ * The following variable has a non-zero value when a handler is active.
+ */
+
+static int genericHandlersActive = 0;
+
+/*
+ * Array of event masks corresponding to each X event:
+ */
+
+static unsigned long eventMasks[] = {
+    0,
+    0,
+    KeyPressMask,                      /* KeyPress */
+    KeyReleaseMask,                    /* KeyRelease */
+    ButtonPressMask,                   /* ButtonPress */
+    ButtonReleaseMask,                 /* ButtonRelease */
+    PointerMotionMask|PointerMotionHintMask|ButtonMotionMask
+           |Button1MotionMask|Button2MotionMask|Button3MotionMask
+           |Button4MotionMask|Button5MotionMask,
+                                       /* MotionNotify */
+    EnterWindowMask,                   /* EnterNotify */
+    LeaveWindowMask,                   /* LeaveNotify */
+    FocusChangeMask,                   /* FocusIn */
+    FocusChangeMask,                   /* FocusOut */
+    KeymapStateMask,                   /* KeymapNotify */
+    ExposureMask,                      /* Expose */
+    ExposureMask,                      /* GraphicsExpose */
+    ExposureMask,                      /* NoExpose */
+    VisibilityChangeMask,              /* VisibilityNotify */
+    SubstructureNotifyMask,            /* CreateNotify */
+    StructureNotifyMask,               /* DestroyNotify */
+    StructureNotifyMask,               /* UnmapNotify */
+    StructureNotifyMask,               /* MapNotify */
+    SubstructureRedirectMask,          /* MapRequest */
+    StructureNotifyMask,               /* ReparentNotify */
+    StructureNotifyMask,               /* ConfigureNotify */
+    SubstructureRedirectMask,          /* ConfigureRequest */
+    StructureNotifyMask,               /* GravityNotify */
+    ResizeRedirectMask,                        /* ResizeRequest */
+    StructureNotifyMask,               /* CirculateNotify */
+    SubstructureRedirectMask,          /* CirculateRequest */
+    PropertyChangeMask,                        /* PropertyNotify */
+    0,                                 /* SelectionClear */
+    0,                                 /* SelectionRequest */
+    0,                                 /* SelectionNotify */
+    ColormapChangeMask,                        /* ColormapNotify */
+    0,                                 /* ClientMessage */
+    0,                                 /* Mapping Notify */
+};
+
+/*
+ * If someone has called Tk_RestrictEvents, the information below
+ * keeps track of it.
+ */
+
+static Bool (*restrictProc)  _ANSI_ARGS_((Display *display, XEvent *eventPtr,
+    char *arg));               /* Procedure to call.  NULL means no
+                                * restrictProc is currently in effect. */
+static char *restrictArg;      /* Argument to pass to restrictProc. */
+
+/*
+ * The following array keeps track of the last TK_NEVENTS X events, for
+ * memory dump analysis.  The tracing is only done if tkEventDebug is set
+ * to 1.
+ */
+
+#define TK_NEVENTS 32
+static XEvent eventTrace[TK_NEVENTS];
+static int traceIndex = 0;
+int tkEventDebug = 0;
+\f
+long tk_GetIntervalToNextEvent()
+/* Returns next time event in milliseconds (from now) */
+{ struct timeval curTime, timeout, *timeoutPtr;
+
+  if (idleList != NULL) return 0; /* Ready NOW */
+  if (timerQueue == NULL) return -1;
+  (void) gettimeofday(&curTime, (struct timezone *) NULL);
+  if ((timerQueue->time.tv_sec < curTime.tv_sec)
+      || ((timerQueue->time.tv_sec == curTime.tv_sec)
+         &&  (timerQueue->time.tv_usec < curTime.tv_usec)))
+    return 0;                  /* Already expired, so do it NOW */
+  return (((curTime.tv_sec - timerQueue->time.tv_sec) * 1000) +
+         (((curTime.tv_usec - timerQueue->time.tv_usec) + 500) /
+          1000));
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateEventHandler --
+ *
+ *     Arrange for a given procedure to be invoked whenever
+ *     events from a given class occur in a given window.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     From now on, whenever an event of the type given by
+ *     mask occurs for token and is processed by Tk_HandleEvent,
+ *     proc will be called.  See the manual entry for details
+ *     of the calling sequence and return value for proc.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CreateEventHandler(token, mask, proc, clientData)
+    Tk_Window token;           /* Token for window in which to
+                                * create handler. */
+    unsigned long mask;                /* Events for which proc should
+                                * be called. */
+    Tk_EventProc *proc;                /* Procedure to call for each
+                                * selected event */
+    ClientData clientData;     /* Arbitrary data to pass to proc. */
+{
+    register TkEventHandler *handlerPtr;
+    register TkWindow *winPtr = (TkWindow *) token;
+    int found;
+
+    /*
+     * Skim through the list of existing handlers to (a) compute the
+     * overall event mask for the window (so we can pass this new
+     * value to the X system) and (b) see if there's already a handler
+     * declared with the same callback and clientData (if so, just
+     * change the mask).  If no existing handler matches, then create
+     * a new handler.
+     */
+
+    found = 0;
+    if (winPtr->handlerList == NULL) {
+       handlerPtr = (TkEventHandler *) ckalloc(
+               (unsigned) sizeof(TkEventHandler));
+       winPtr->handlerList = handlerPtr;
+       goto initHandler;
+    } else {
+       for (handlerPtr = winPtr->handlerList; ;
+               handlerPtr = handlerPtr->nextPtr) {
+           if ((handlerPtr->proc == proc)
+                   && (handlerPtr->clientData == clientData)) {
+               handlerPtr->mask = mask;
+               found = 1;
+           }
+           if (handlerPtr->nextPtr == NULL) {
+               break;
+           }
+       }
+    }
+
+    /*
+     * Create a new handler if no matching old handler was found.
+     */
+
+    if (!found) {
+       handlerPtr->nextPtr = (TkEventHandler *)
+               ckalloc(sizeof(TkEventHandler));
+       handlerPtr = handlerPtr->nextPtr;
+       initHandler:
+       handlerPtr->mask = mask;
+       handlerPtr->proc = proc;
+       handlerPtr->clientData = clientData;
+       handlerPtr->nextPtr = NULL;
+    }
+
+    /*
+     * No need to call XSelectInput:  Tk always selects on all events
+     * for all windows (needed to support bindings on classes and "all").
+     */
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteEventHandler --
+ *
+ *     Delete a previously-created handler.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     If there existed a handler as described by the
+ *     parameters, the handler is deleted so that proc
+ *     will not be invoked again.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DeleteEventHandler(token, mask, proc, clientData)
+    Tk_Window token;           /* Same as corresponding arguments passed */
+    unsigned long mask;                /* previously to Tk_CreateEventHandler. */
+    Tk_EventProc *proc;
+    ClientData clientData;
+{
+    register TkEventHandler *handlerPtr;
+    register InProgress *ipPtr;
+    TkEventHandler *prevPtr;
+    register TkWindow *winPtr = (TkWindow *) token;
+
+    /*
+     * Find the event handler to be deleted, or return
+     * immediately if it doesn't exist.
+     */
+
+    for (handlerPtr = winPtr->handlerList, prevPtr = NULL; ;
+           prevPtr = handlerPtr, handlerPtr = handlerPtr->nextPtr) {
+       if (handlerPtr == NULL) {
+           return;
+       }
+       if ((handlerPtr->mask == mask) && (handlerPtr->proc == proc)
+               && (handlerPtr->clientData == clientData)) {
+           break;
+       }
+    }
+
+    /*
+     * If Tk_HandleEvent is about to process this handler, tell it to
+     * process the next one instead.
+     */
+
+    for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+       if (ipPtr->nextHandler == handlerPtr) {
+           ipPtr->nextHandler = handlerPtr->nextPtr;
+       }
+    }
+
+    /*
+     * Free resources associated with the handler.
+     */
+
+    if (prevPtr == NULL) {
+       winPtr->handlerList = handlerPtr->nextPtr;
+    } else {
+       prevPtr->nextPtr = handlerPtr->nextPtr;
+    }
+    ckfree((char *) handlerPtr);
+
+
+    /*
+     * No need to call XSelectInput:  Tk always selects on all events
+     * for all windows (needed to support bindings on classes and "all").
+     */
+}
+\f
+/*--------------------------------------------------------------
+ *
+ * Tk_CreateGenericHandler --
+ *
+ *     Register a procedure to be called on each X event, regardless
+ *     of display or window.  Generic handlers are useful for capturing
+ *     events that aren't associated with windows, or events for windows
+ *     not managed by Tk.
+ *
+ * Results:
+ *     None.
+ *
+ * Side Effects:
+ *     From now on, whenever an X event is given to Tk_HandleEvent,
+ *     invoke proc, giving it clientData and the event as arguments.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CreateGenericHandler(proc, clientData)
+     Tk_GenericProc *proc;     /* Procedure to call on every event. */
+     ClientData clientData;    /* One-word value to pass to proc. */
+{
+    GenericHandler *handlerPtr;
+    
+    handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler));
+    
+    handlerPtr->proc = proc;
+    handlerPtr->clientData = clientData;
+    handlerPtr->deleteFlag = 0;
+    handlerPtr->nextPtr = NULL;
+    if (genericList == NULL) {
+       genericList = handlerPtr;
+    } else {
+       lastGenericPtr->nextPtr = handlerPtr;
+    }
+    lastGenericPtr = handlerPtr;
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteGenericHandler --
+ *
+ *     Delete a previously-created generic handler.
+ *
+ * Results:
+ *     None.
+ *
+ * Side Effects:
+ *     If there existed a handler as described by the parameters,
+ *     that handler is logically deleted so that proc will not be
+ *     invoked again.  The physical deletion happens in the event
+ *     loop in Tk_HandleEvent.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DeleteGenericHandler(proc, clientData)
+     Tk_GenericProc *proc;
+     ClientData clientData;
+{
+    GenericHandler * handler;
+    
+    for (handler = genericList; handler; handler = handler->nextPtr) {
+       if ((handler->proc == proc) && (handler->clientData == clientData)) {
+           handler->deleteFlag = 1;
+       }
+    }
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_HandleEvent --
+ *
+ *     Given an event, invoke all the handlers that have
+ *     been registered for the event.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Depends on the handlers.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_HandleEvent(eventPtr)
+    XEvent *eventPtr;          /* Event to dispatch. */
+{
+    register TkEventHandler *handlerPtr;
+    register GenericHandler *genericPtr;
+    register GenericHandler *genPrevPtr;
+    TkWindow *winPtr;
+    register unsigned long mask;
+    InProgress ip;
+    Window handlerWindow;
+
+    /*
+     * First off, look for a special trigger event left around by the
+     * grab module.  If it's found, call the grab module and discard
+     * the event.
+     */
+
+    if ((eventPtr->xany.type == -1) && (eventPtr->xany.window == None)) {
+       TkGrabTriggerProc(eventPtr);
+       return;
+    }
+
+    /* 
+     * Next, invoke all the generic event handlers (those that are
+     * invoked for all events).  If a generic event handler reports that
+     * an event is fully processed, go no further.
+     */
+
+    for (genPrevPtr = NULL, genericPtr = genericList;  genericPtr != NULL; ) {
+       if (genericPtr->deleteFlag) {
+           if (!genericHandlersActive) {
+               GenericHandler *tmpPtr;
+
+               /*
+                * This handler needs to be deleted and there are no
+                * calls pending through the handler, so now is a safe
+                * time to delete it.
+                */
+
+               tmpPtr = genericPtr->nextPtr;
+               if (genPrevPtr == NULL) {
+                   genericList = tmpPtr;
+               } else {
+                   genPrevPtr->nextPtr = tmpPtr;
+               }
+               (void) ckfree((char *) genericPtr);
+               genericPtr = tmpPtr;
+               continue;
+           }
+       } else {
+           int done;
+
+           genericHandlersActive++;
+           done = (*genericPtr->proc)(genericPtr->clientData, eventPtr);
+           genericHandlersActive--;
+           if (done) {
+               return;
+           }
+       }
+       genPrevPtr = genericPtr;
+       genericPtr = genPrevPtr->nextPtr;
+    }
+
+    /*
+     * If the event is a MappingNotify event, find its display and
+     * refresh the keyboard mapping information for the display.
+     * After that there's nothing else to do with the event, so just
+     * quit.
+     */
+
+    if (eventPtr->type == MappingNotify) {
+       TkDisplay *dispPtr;
+
+       for (dispPtr = tkDisplayList; dispPtr != NULL;
+               dispPtr = dispPtr->nextPtr) {
+           if (dispPtr->display != eventPtr->xmapping.display) {
+               continue;
+           }
+           XRefreshKeyboardMapping(&eventPtr->xmapping);
+           dispPtr->bindInfoStale = 1;
+           break;
+       }
+       return;
+    }
+
+    /*
+     * Events selected by StructureNotify look the same as those
+     * selected by SubstructureNotify;  the only difference is
+     * whether the "event" and "window" fields are the same.
+     * Check it out and convert StructureNotify to
+     * SubstructureNotify if necessary.
+     */
+
+    handlerWindow = eventPtr->xany.window;
+    mask = eventMasks[eventPtr->xany.type];
+    if (mask == StructureNotifyMask) {
+       if (eventPtr->xmap.event != eventPtr->xmap.window) {
+           mask = SubstructureNotifyMask;
+           handlerWindow = eventPtr->xmap.event;
+       }
+    }
+    if (XFindContext(eventPtr->xany.display, handlerWindow,
+           tkWindowContext, (caddr_t *) &winPtr) != 0) {
+
+       /*
+        * There isn't a TkWindow structure for this window.
+        * However, if the event is a PropertyNotify event then call
+        * the selection manager (it deals beneath-the-table with
+        * certain properties).
+        */
+
+       if (eventPtr->type == PropertyNotify) {
+           TkSelPropProc(eventPtr);
+       }
+       return;
+    }
+
+    /*
+     * Call focus-related code to look at FocusIn, FocusOut, Enter,
+     * and Leave events;  depending on its return value, ignore the
+     * event.
+     */
+
+    if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask))
+           && !TkFocusFilterEvent(winPtr, eventPtr)) {
+       return;
+    }
+
+    /*
+     * Redirect KeyPress and KeyRelease events to the focus window,
+     * or ignore them entirely if there is no focus window.  Map the
+     * x and y coordinates to make sense in the context of the focus
+     * window, if possible (make both -1 if the map-from and map-to
+     * windows don't share the same screen).
+     */
+
+    if (mask & (KeyPressMask|KeyReleaseMask)) {
+       TkWindow *focusPtr;
+       int winX, winY, focusX, focusY;
+
+       winPtr->dispPtr->lastEventTime = eventPtr->xkey.time;
+       if (winPtr->mainPtr->focusPtr == NULL) {
+           return;
+       }
+       focusPtr = winPtr->mainPtr->focusPtr;
+       if ((focusPtr->display != winPtr->display)
+               || (focusPtr->screenNum != winPtr->screenNum)) {
+           eventPtr->xkey.x = -1;
+           eventPtr->xkey.y = -1;
+       } else {
+           Tk_GetRootCoords((Tk_Window) winPtr, &winX, &winY);
+           Tk_GetRootCoords((Tk_Window) focusPtr, &focusX, &focusY);
+           eventPtr->xkey.x -= focusX - winX;
+           eventPtr->xkey.y -= focusY - winY;
+       }
+       eventPtr->xkey.window = focusPtr->window;
+       winPtr = focusPtr;
+    }
+
+    /*
+     * Call a grab-related procedure to do special processing on
+     * pointer events.
+     */
+
+    if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask
+           |EnterWindowMask|LeaveWindowMask)) {
+       if (mask & (ButtonPressMask|ButtonReleaseMask)) {
+           winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time;
+       } else if (mask & PointerMotionMask) {
+           winPtr->dispPtr->lastEventTime = eventPtr->xmotion.time;
+       } else {
+           winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time;
+       }
+       if (TkPointerEvent(eventPtr, winPtr) == 0) {
+           return;
+       }
+    }
+
+    /*
+     * For events where it hasn't already been done, update the current
+     * time in the display.
+     */
+
+    if (eventPtr->type == PropertyNotify) {
+       winPtr->dispPtr->lastEventTime = eventPtr->xproperty.time;
+    }
+
+    /*
+     * There's a potential interaction here with Tk_DeleteEventHandler.
+     * Read the documentation for pendingPtr.
+     */
+
+    ip.eventPtr = eventPtr;
+    ip.winPtr = winPtr;
+    ip.nextHandler = NULL;
+    ip.nextPtr = pendingPtr;
+    pendingPtr = &ip;
+    if (mask == 0) {
+       if ((eventPtr->type == SelectionClear)
+               || (eventPtr->type == SelectionRequest)
+               || (eventPtr->type == SelectionNotify)) {
+           TkSelEventProc((Tk_Window) winPtr, eventPtr);
+       } else if ((eventPtr->type == ClientMessage)
+               && (eventPtr->xclient.message_type ==
+                   Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS"))) {
+           TkWmProtocolEventProc(winPtr, eventPtr);
+       }
+    } else {
+       for (handlerPtr = winPtr->handlerList; handlerPtr != NULL; ) {
+           if ((handlerPtr->mask & mask) != 0) {
+               ip.nextHandler = handlerPtr->nextPtr;
+               (*(handlerPtr->proc))(handlerPtr->clientData, eventPtr);
+               handlerPtr = ip.nextHandler;
+           } else {
+               handlerPtr = handlerPtr->nextPtr;
+           }
+       }
+
+       /*
+        * Pass the event to the "bind" command mechanism.  But, don't
+        * do this for SubstructureNotify events.  The "bind" command
+        * doesn't support them anyway, and it's easier to filter out
+        * these events here than in the lower-level procedures.
+        */
+
+       if ((ip.winPtr != None) && (mask != SubstructureNotifyMask)) {
+           TkBindEventProc(winPtr, eventPtr);
+       }
+    }
+    pendingPtr = ip.nextPtr;
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateFileHandler --
+ *
+ *     Arrange for a given procedure to be invoked whenever
+ *     a given file becomes readable or writable.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     From now on, whenever the I/O channel given by fd becomes
+ *     ready in the way indicated by mask, proc will be invoked.
+ *     See the manual entry for details on the calling sequence
+ *     to proc.  If fd is already registered then the old mask
+ *     and proc and clientData values will be replaced with
+ *     new ones.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CreateFileHandler(fd, mask, proc, clientData)
+    int fd;                    /* Integer identifier for stream. */
+    int mask;                  /* OR'ed combination of TK_READABLE,
+                                * TK_WRITABLE, and TK_EXCEPTION:
+                                * indicates conditions under which
+                                * proc should be called. */
+    Tk_FileProc *proc;         /* Procedure to call for each
+                                * selected event.  NULL means that
+                                * this is a display, and that
+                                * clientData is the (Display *)
+                                * for it, and that events should
+                                * be handled automatically. */
+    ClientData clientData;     /* Arbitrary data to pass to proc. */
+{
+    register FileEvent *filePtr;
+    int index;
+
+    if (fd >= OPEN_MAX) {
+       panic("Tk_CreatefileHandler can't handle file id %d", fd);
+    }
+
+    /*
+     * Make sure the file isn't already registered.  Create a
+     * new record in the normal case where there's no existing
+     * record.
+     */
+
+    for (filePtr = fileList; filePtr != NULL;
+           filePtr = filePtr->nextPtr) {
+       if (filePtr->fd == fd) {
+           break;
+       }
+    }
+    index = fd/(8*sizeof(int));
+    if (filePtr == NULL) {
+       filePtr = (FileEvent *) ckalloc(sizeof(FileEvent));
+       filePtr->fd = fd;
+       filePtr->readPtr = &ready[index];
+       filePtr->writePtr = &ready[index+MASK_SIZE];
+       filePtr->exceptPtr = &ready[index+2*MASK_SIZE];
+       filePtr->mask = 1 << (fd%(8*sizeof(int)));
+       filePtr->nextPtr = fileList;
+       fileList = filePtr;
+    } else {
+       if (masks[index] & filePtr->mask) {
+           readCount--;
+           *filePtr->readPtr &= ~filePtr->mask;
+           masks[index] &= ~filePtr->mask;
+       }
+       if (masks[index+MASK_SIZE] & filePtr->mask) {
+           writeCount--;
+           *filePtr->writePtr &= ~filePtr->mask;
+           masks[index+MASK_SIZE] &= ~filePtr->mask;
+       }
+       if (masks[index+2*MASK_SIZE] & filePtr->mask) {
+           exceptCount--;
+           *filePtr->exceptPtr &= ~filePtr->mask;
+           masks[index+2*MASK_SIZE] &= ~filePtr->mask;
+       }
+    }
+
+    /*
+     * The remainder of the initialization below is done
+     * regardless of whether or not this is a new record
+     * or a modification of an old one.
+     */
+
+    if (mask & TK_READABLE) {
+       masks[index] |= filePtr->mask;
+       readCount++;
+    }
+    readPtr = (readCount == 0) ? (int *) NULL : &ready[0];
+
+    if (mask & TK_WRITABLE) {
+       masks[index+MASK_SIZE] |= filePtr->mask;
+       writeCount++;
+    }
+    writePtr = (writeCount == 0) ? (int *) NULL : &ready[MASK_SIZE];
+
+    if (mask & TK_EXCEPTION) {
+       masks[index+2*MASK_SIZE] |= filePtr->mask;
+       exceptCount++;
+    }
+    exceptPtr = (exceptCount == 0) ? (int *) NULL : &ready[2*MASK_SIZE];
+
+    filePtr->proc = proc;
+    filePtr->clientData = clientData;
+
+    if (numFds <= fd) {
+       numFds = fd+1;
+    }
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteFileHandler --
+ *
+ *     Cancel a previously-arranged callback arrangement for
+ *     a file.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     If a callback was previously registered on fd, remove it.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DeleteFileHandler(fd)
+    int fd;                    /* Stream id for which to remove
+                                * callback procedure. */
+{
+    register FileEvent *filePtr;
+    FileEvent *prevPtr;
+    int index;
+
+    /*
+     * Find the entry for the given file (and return if there
+     * isn't one).
+     */
+
+    for (prevPtr = NULL, filePtr = fileList; ;
+           prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+       if (filePtr == NULL) {
+           return;
+       }
+       if (filePtr->fd == fd) {
+           break;
+       }
+    }
+
+    /*
+     * Clean up information in the callback record.
+     */
+
+    index = filePtr->fd/(8*sizeof(int));
+    if (masks[index] & filePtr->mask) {
+       readCount--;
+       *filePtr->readPtr &= ~filePtr->mask;
+       masks[index] &= ~filePtr->mask;
+    }
+    if (masks[index+MASK_SIZE] & filePtr->mask) {
+       writeCount--;
+       *filePtr->writePtr &= ~filePtr->mask;
+       masks[index+MASK_SIZE] &= ~filePtr->mask;
+    }
+    if (masks[index+2*MASK_SIZE] & filePtr->mask) {
+       exceptCount--;
+       *filePtr->exceptPtr &= ~filePtr->mask;
+       masks[index+2*MASK_SIZE] &= ~filePtr->mask;
+    }
+    if (prevPtr == NULL) {
+       fileList = filePtr->nextPtr;
+    } else {
+       prevPtr->nextPtr = filePtr->nextPtr;
+    }
+    ckfree((char *) filePtr);
+
+    /*
+     * Recompute numFds.
+     */
+
+    numFds = 0;
+    for (filePtr = fileList; filePtr != NULL;
+           filePtr = filePtr->nextPtr) {
+       if (numFds <= filePtr->fd) {
+           numFds = filePtr->fd+1;
+       }
+    }
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateTimerHandler --
+ *
+ *     Arrange for a given procedure to be invoked at a particular
+ *     time in the future.
+ *
+ * Results:
+ *     The return value is a token for the timer event, which
+ *     may be used to delete the event before it fires.
+ *
+ * Side effects:
+ *     When milliseconds have elapsed, proc will be invoked
+ *     exactly once.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_TimerToken
+Tk_CreateTimerHandler(milliseconds, proc, clientData)
+    int milliseconds;          /* How many milliseconds to wait
+                                * before invoking proc. */
+    Tk_TimerProc *proc;                /* Procedure to invoke. */
+    ClientData clientData;     /* Arbitrary data to pass to proc. */
+{
+    register TimerEvent *timerPtr, *tPtr2, *prevPtr;
+    static int id = 0;
+
+    timerPtr = (TimerEvent *) ckalloc(sizeof(TimerEvent));
+
+    /*
+     * Compute when the event should fire.
+     */
+
+    (void) gettimeofday(&timerPtr->time, (struct timezone *) NULL);
+    timerPtr->time.tv_sec += milliseconds/1000;
+    timerPtr->time.tv_usec += (milliseconds%1000)*1000;
+    if (timerPtr->time.tv_usec > 1000000) {
+       timerPtr->time.tv_usec -= 1000000;
+       timerPtr->time.tv_sec += 1;
+    }
+
+    /*
+     * Fill in other fields for the event.
+     */
+
+    timerPtr->proc = proc;
+    timerPtr->clientData = clientData;
+    id++;
+    timerPtr->token = (Tk_TimerToken) id;
+
+    /*
+     * Add the event to the queue in the correct position
+     * (ordered by event firing time).
+     */
+
+    for (tPtr2 = timerQueue, prevPtr = NULL; tPtr2 != NULL;
+           prevPtr = tPtr2, tPtr2 = tPtr2->nextPtr) {
+       if ((tPtr2->time.tv_sec > timerPtr->time.tv_sec)
+               || ((tPtr2->time.tv_sec == timerPtr->time.tv_sec)
+               && (tPtr2->time.tv_usec > timerPtr->time.tv_usec))) {
+           break;
+       }
+    }
+    if (prevPtr == NULL) {
+       timerPtr->nextPtr = timerQueue;
+       timerQueue = timerPtr;
+    } else {
+       timerPtr->nextPtr = prevPtr->nextPtr;
+       prevPtr->nextPtr = timerPtr;
+    }
+    return timerPtr->token;
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteTimerHandler --
+ *
+ *     Delete a previously-registered timer handler.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Destroy the timer callback identified by TimerToken,
+ *     so that its associated procedure will not be called.
+ *     If the callback has already fired, or if the given
+ *     token doesn't exist, then nothing happens.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DeleteTimerHandler(token)
+    Tk_TimerToken token;       /* Result previously returned by
+                                * Tk_DeleteTimerHandler. */
+{
+    register TimerEvent *timerPtr, *prevPtr;
+
+    for (timerPtr = timerQueue, prevPtr = NULL; timerPtr != NULL;
+           prevPtr = timerPtr, timerPtr = timerPtr->nextPtr) {
+       if (timerPtr->token != token) {
+           continue;
+       }
+       if (prevPtr == NULL) {
+           timerQueue = timerPtr->nextPtr;
+       } else {
+           prevPtr->nextPtr = timerPtr->nextPtr;
+       }
+       ckfree((char *) timerPtr);
+       return;
+    }
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DoWhenIdle --
+ *
+ *     Arrange for proc to be invoked the next time the
+ *     system is idle (i.e., just before the next time
+ *     that Tk_DoOneEvent would have to wait for something
+ *     to happen).
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Proc will eventually be called, with clientData
+ *     as argument.  See the manual entry for details.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DoWhenIdle(proc, clientData)
+    Tk_IdleProc *proc;         /* Procedure to invoke. */
+    ClientData clientData;     /* Arbitrary value to pass to proc. */
+{
+    register IdleHandler *idlePtr;
+
+    idlePtr = (IdleHandler *) ckalloc(sizeof(IdleHandler));
+    idlePtr->proc = proc;
+    idlePtr->clientData = clientData;
+    idlePtr->generation = idleGeneration;
+    idlePtr->nextPtr = NULL;
+    if (lastIdlePtr == NULL) {
+       idleList = idlePtr;
+    } else {
+       lastIdlePtr->nextPtr = idlePtr;
+    }
+    lastIdlePtr = idlePtr;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CancelIdleCall --
+ *
+ *     If there are any when-idle calls requested to a given procedure
+ *     with given clientData, cancel all of them.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     If the proc/clientData combination were on the when-idle list,
+ *     they are removed so that they will never be called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CancelIdleCall(proc, clientData)
+    Tk_IdleProc *proc;         /* Procedure that was previously registered. */
+    ClientData clientData;     /* Arbitrary value to pass to proc. */
+{
+    register IdleHandler *idlePtr, *prevPtr;
+    IdleHandler *nextPtr;
+
+    for (prevPtr = NULL, idlePtr = idleList; idlePtr != NULL;
+           prevPtr = idlePtr, idlePtr = idlePtr->nextPtr) {
+       while ((idlePtr->proc == proc)
+               && (idlePtr->clientData == clientData)) {
+           nextPtr = idlePtr->nextPtr;
+           ckfree((char *) idlePtr);
+           idlePtr = nextPtr;
+           if (prevPtr == NULL) {
+               idleList = idlePtr;
+           } else {
+               prevPtr->nextPtr = idlePtr;
+           }
+           if (idlePtr == NULL) {
+               lastIdlePtr = prevPtr;
+               return;
+           }
+       }
+    }
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DoOneEvent --
+ *
+ *     Process a single event of some sort.  If there's no
+ *     work to do, wait for an event to occur, then process
+ *     it.
+ *
+ * Results:
+ *     The return value is 1 if the procedure actually found
+ *     an event to process.  If no event was found then 0 is
+ *     returned.
+ *
+ * Side effects:
+ *     May delay execution of process while waiting for an
+ *     X event, X error, file-ready event, or timer event.
+ *     The handling of the event could cause additional
+ *     side effects.  Collapses sequences of mouse-motion
+ *     events for the same window into a single event by
+ *     delaying motion event processing.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_DoOneEvent(flags)
+    int flags;                 /* Miscellaneous flag values:  may be any
+                                * combination of TK_DONT_WAIT, TK_X_EVENTS,
+                                * TK_FILE_EVENTS, TK_TIMER_EVENTS, and
+                                * TK_IDLE_EVENTS. */
+{
+    register FileEvent *filePtr;
+    struct timeval curTime, timeout, *timeoutPtr;
+    int numFound;
+    static XEvent delayedMotionEvent;  /* Used to hold motion events that
+                                        * are being saved until later. */
+    static int eventDelayed = 0;       /* Non-zero means there is an event
+                                        * in delayedMotionEvent. */
+
+    if ((flags & TK_ALL_EVENTS) == 0) {
+       flags |= TK_ALL_EVENTS;
+    }
+
+    /*
+     * Phase One: see if there's already something ready
+     * (either a file or a display) that was left over
+     * from before (i.e don't do a select, just check the
+     * bits from the last select).
+     */
+
+    checkFiles:
+    for (filePtr = fileList; filePtr != NULL;
+           filePtr = filePtr->nextPtr) {
+       int mask;
+
+       /*
+        * Displays:  flush output, check for queued events,
+        * and read events from the server if display is ready.
+        * If there are any events, process one and then
+        * return.
+        */
+
+       if ((filePtr->proc == NULL) && (flags & TK_X_EVENTS)) {
+           Display *display = (Display *) filePtr->clientData;
+           XEvent event;
+
+           XFlush(display);
+           if ((*filePtr->readPtr) & filePtr->mask) {
+               *filePtr->readPtr &= ~filePtr->mask;
+               if (XEventsQueued(display, QueuedAfterReading) == 0) {
+
+                   /*
+                    * Things are very tricky if there aren't any events
+                    * readable at this point (after all, there was
+                    * supposedly data available on the connection).
+                    * A couple of things could have occurred:
+                    * 
+                    * One possibility is that there were only error events
+                    * in the input from the server.  If this happens,
+                    * we should return (we don't want to go to sleep
+                    * in XNextEvent below, since this would block out
+                    * other sources of input to the process).
+                    *
+                    * Another possibility is that our connection to the
+                    * server has been closed.  This will not necessarily
+                    * be detected in XEventsQueued (!!), so if we just
+                    * return then there will be an infinite loop.  To
+                    * detect such an error, generate a NoOp protocol
+                    * request to exercise the connection to the server,
+                    * then return.  However, must disable SIGPIPE while
+                    * sending the event, or else the process will die
+                    * from the signal and won't invoke the X error
+                    * function to print a nice message.
+                    */
+
+                   void (*oldHandler)();
+
+                   oldHandler = (void (*)()) signal(SIGPIPE, SIG_IGN);
+                   XNoOp(display);
+                   XFlush(display);
+                   (void) signal(SIGPIPE, oldHandler);
+                   return 1;
+               }
+               if (restrictProc != NULL) {
+                   if (!XCheckIfEvent(display, &event, restrictProc,
+                           restrictArg)) {
+                       return 1;
+                   }
+               } else {
+                   XNextEvent(display, &event);
+               }
+           } else {
+               if (QLength(display) == 0) {
+                   continue;
+               }
+               if (restrictProc != NULL) {
+                   if (!XCheckIfEvent(display, &event, restrictProc,
+                           restrictArg)) {
+                       continue;
+                   }
+               } else {
+                   XNextEvent(display, &event);
+               }
+           }
+
+           /*
+            * Got an event.  Deal with mouse-motion-collapsing and
+            * event-delaying here.  If there's already an event delayed,
+            * then process that event if it's incompatible with the new
+            * event (new event not mouse motion, or window changed, or
+            * state changed).  If the new event is mouse motion, then
+            * don't process it now;  delay it until later in the hopes
+            * that it can be merged with other mouse motion events
+            * immediately following.
+            */
+
+           if (tkEventDebug) {
+               eventTrace[traceIndex] = event;
+               traceIndex = (traceIndex+1) % TK_NEVENTS;
+           }
+
+           if (eventDelayed) {
+               if (((event.type != MotionNotify)
+                           && (event.type != GraphicsExpose)
+                           && (event.type != NoExpose)
+                           && (event.type != Expose))
+                       || (event.xmotion.display
+                           != delayedMotionEvent.xmotion.display)
+                       || (event.xmotion.window
+                           != delayedMotionEvent.xmotion.window)) {
+                   XEvent copy;
+
+                   /*
+                    * Must copy the event out of delayedMotionEvent before
+                    * processing it, in order to allow recursive calls to
+                    * Tk_DoOneEvent as part of the handler.
+                    */
+
+                   copy = delayedMotionEvent;
+                   eventDelayed = 0;
+                   Tk_HandleEvent(&copy);
+               }
+           }
+           if (event.type == MotionNotify) {
+               delayedMotionEvent = event;
+               eventDelayed = 1;
+           } else {
+               Tk_HandleEvent(&event);
+           }
+           return 1;
+       }
+
+       /*
+        * Not a display:  if the file is ready, call the
+        * appropriate handler.
+        */
+
+       if (((*filePtr->readPtr | *filePtr->writePtr
+               | *filePtr->exceptPtr) & filePtr->mask) == 0) {
+           continue;
+       }
+       if (!(flags & TK_FILE_EVENTS)) {
+           continue;
+       }
+       mask = 0;
+       if (*filePtr->readPtr & filePtr->mask) {
+           mask |= TK_READABLE;
+           *filePtr->readPtr &= ~filePtr->mask;
+       }
+       if (*filePtr->writePtr & filePtr->mask) {
+           mask |= TK_WRITABLE;
+           *filePtr->writePtr &= ~filePtr->mask;
+       }
+       if (*filePtr->exceptPtr & filePtr->mask) {
+           mask |= TK_EXCEPTION;
+           *filePtr->exceptPtr &= ~filePtr->mask;
+       }
+       (*filePtr->proc)(filePtr->clientData, mask);
+       return 1;
+    }
+
+    /*
+     * Phase Two: get the current time and see if any timer
+     * events are ready to fire.  If so, fire one and return.
+     */
+
+    checkTime:
+    if ((timerQueue != NULL) && (flags & TK_TIMER_EVENTS)) {
+       register TimerEvent *timerPtr = timerQueue;
+
+       (void) gettimeofday(&curTime, (struct timezone *) NULL);
+       if ((timerPtr->time.tv_sec < curTime.tv_sec)
+               || ((timerPtr->time.tv_sec == curTime.tv_sec)
+               &&  (timerPtr->time.tv_usec < curTime.tv_usec))) {
+           timerQueue = timerPtr->nextPtr;
+           (*timerPtr->proc)(timerPtr->clientData);
+           ckfree((char *) timerPtr);
+           return 1;
+       }
+    }
+
+
+    /*
+     * Phase Three: if there is a delayed motion event, process it
+     * now, before any DoWhenIdle handlers.  Better to process before
+     * idle handlers than after, because the goal of idle handlers is
+     * to delay until after all pending events have been processed.
+     * Must free up delayedMotionEvent *before* calling Tk_HandleEvent,
+     * so that the event handler can call Tk_DoOneEvent recursively
+     * without infinite looping.
+     */
+
+    if ((eventDelayed) && (flags & TK_X_EVENTS)) {
+       XEvent copy;
+
+       copy = delayedMotionEvent;
+       eventDelayed = 0;
+       Tk_HandleEvent(&copy);
+       return 1;
+    }
+
+    /*
+     * Phase Four: if there are DoWhenIdle requests pending (or
+     * if we're not allowed to block), then do a select with an
+     * instantaneous timeout.  If a ready file is found, then go
+     * back to process it.
+     */
+
+    if (((idleList != NULL) && (flags & TK_IDLE_EVENTS))
+           || (flags & TK_DONT_WAIT)) {
+       if (flags & (TK_X_EVENTS|TK_FILE_EVENTS)) {
+           memcpy((VOID *) ready, (VOID *) masks, 3*MASK_SIZE*sizeof(int));
+           timeout.tv_sec = timeout.tv_usec = 0;
+           do {
+               numFound = select(numFds, (SELECT_MASK *) readPtr,
+                       (SELECT_MASK *) writePtr, (SELECT_MASK *) exceptPtr,
+                   &timeout);
+           } while ((numFound == -1) && (errno == EINTR));
+           if (numFound > 0) {
+               goto checkFiles;
+           }
+       }
+    }
+
+    /*
+     * Phase Five:  process all pending DoWhenIdle requests.
+     */
+
+    if ((idleList != NULL) && (flags & TK_IDLE_EVENTS)) {
+       register IdleHandler *idlePtr;
+       int oldGeneration;
+
+       oldGeneration = idleList->generation;
+       idleGeneration++;
+
+       /*
+        * The code below is trickier than it may look, for the following
+        * reasons:
+        *
+        * 1. New handlers can get added to the list while the current
+        *    one is being processed.  If new ones get added, we don't
+        *    want to process them during this pass through the list (want
+        *    to check for other work to do first).  This is implemented
+        *    using the generation number in the handler:  new handlers
+        *    will have a different generation than any of the ones currently
+        *    on the list.
+        * 2. The handler can call Tk_DoOneEvent, so we have to remove
+        *    the hander from the list before calling it. Otherwise an
+        *    infinite loop could result.
+        * 3. Tk_CancelIdleCall can be called to remove an element from
+        *    the list while a handler is executing, so the list could
+        *    change structure during the call.
+        */
+
+       for (idlePtr = idleList;
+               ((idlePtr != NULL) && (idlePtr->generation == oldGeneration));
+               idlePtr = idleList) {
+         /* fprintf(stderr, "Phase5A"); Here is where it is looping */
+         idleList = idlePtr->nextPtr;
+           if (idleList == NULL) {
+               lastIdlePtr = NULL;
+           }
+           (*idlePtr->proc)(idlePtr->clientData);
+           ckfree((char *) idlePtr);
+       }
+       return 1;
+    }
+
+    /*
+     * Phase Six: do a select to wait for either one of the
+     * files to become ready or for the first timer event to
+     * fire.  Then go back to process the event.
+     */
+
+    if ((flags & TK_DONT_WAIT)
+           || !(flags & (TK_TIMER_EVENTS|TK_FILE_EVENTS|TK_X_EVENTS))) {
+       return 0;
+    }
+    if ((timerQueue == NULL) || !(flags & TK_TIMER_EVENTS)) {
+       timeoutPtr = NULL;
+    } else {
+       timeoutPtr = &timeout;
+       timeout.tv_sec = timerQueue->time.tv_sec - curTime.tv_sec;
+       timeout.tv_usec = timerQueue->time.tv_usec - curTime.tv_usec;
+       if (timeout.tv_usec < 0) {
+           timeout.tv_sec -= 1;
+           timeout.tv_usec += 1000000;
+       }
+    }
+    memcpy((VOID *) ready, (VOID *) masks, 3*MASK_SIZE*sizeof(int));
+    do {
+       numFound = select(numFds, (SELECT_MASK *) readPtr,
+               (SELECT_MASK *) writePtr, (SELECT_MASK *) exceptPtr,
+               timeoutPtr);
+    } while ((numFound == -1) && (errno == EINTR));
+    if (numFound == 0) {
+       goto checkTime;
+    }
+    goto checkFiles;
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_MainLoop --
+ *
+ *     Call Tk_DoOneEvent over and over again in an infinite
+ *     loop as long as there exist any main windows.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Arbitrary;  depends on handlers for events.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_MainLoop()
+{
+    while (tk_NumMainWindows > 0) {
+       Tk_DoOneEvent(0);
+    }
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Sleep --
+ *
+ *     Delay execution for the specified number of milliseconds.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Time passes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_Sleep(ms)
+    int ms;                    /* Number of milliseconds to sleep. */
+{
+    static struct timeval delay;
+
+    delay.tv_sec = ms/1000;
+    delay.tv_usec = (ms%1000)*1000;
+    (void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0,
+           (SELECT_MASK *) 0, &delay);
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_RestrictEvents --
+ *
+ *     This procedure is used to globally restrict the set of events
+ *     that will be dispatched.  The restriction is done by filtering
+ *     all incoming X events through a procedure that determines
+ *     whether they are to be processed immediately or deferred.
+ *
+ * Results:
+ *     The return value is the previous restriction procedure in effect,
+ *     if there was one, or NULL if there wasn't.
+ *
+ * Side effects:
+ *     From now on, proc will be called to determine whether to process
+ *     or defer each incoming X event.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_RestrictProc *
+Tk_RestrictEvents(proc, arg, prevArgPtr)
+    Tk_RestrictProc *proc;     /* X "if" procedure to call for each
+                                * incoming event.  See "XIfEvent" doc.
+                                * for details. */
+    char *arg;                 /* Arbitrary argument to pass to proc. */
+    char **prevArgPtr;         /* Place to store information about previous
+                                * argument. */
+{
+    Bool (*prev)  _ANSI_ARGS_((Display *display, XEvent *eventPtr, char *arg));
+
+    prev = restrictProc;
+    *prevArgPtr = restrictArg;
+    restrictProc = proc;
+    restrictArg = arg;
+    return prev;
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * TkEventDeadWindow --
+ *
+ *     This procedure is invoked when it is determined that
+ *     a window is dead.  It cleans up event-related information
+ *     about the window.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Various things get cleaned up and recycled.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkEventDeadWindow(winPtr)
+    TkWindow *winPtr;          /* Information about the window
+                                * that is being deleted. */
+{
+    register TkEventHandler *handlerPtr;
+    register InProgress *ipPtr;
+
+    /*
+     * While deleting all the handlers, be careful to check for
+     * Tk_HandleEvent being about to process one of the deleted
+     * handlers.  If it is, tell it to quit (all of the handlers
+     * are being deleted).
+     */
+
+    while (winPtr->handlerList != NULL) {
+       handlerPtr = winPtr->handlerList;
+       winPtr->handlerList = handlerPtr->nextPtr;
+       for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+           if (ipPtr->nextHandler == handlerPtr) {
+               ipPtr->nextHandler = NULL;
+           }
+           if (ipPtr->winPtr == winPtr) {
+               ipPtr->winPtr = None;
+           }
+       }
+       ckfree((char *) handlerPtr);
+    }
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCurrentTime --
+ *
+ *     Try to deduce the current time.  "Current time" means the time
+ *     of the event that led to the current code being executed, which
+ *     means the time in the most recently-nested invocation of
+ *     Tk_HandleEvent.
+ *
+ * Results:
+ *     The return value is the time from the current event, or
+ *     CurrentTime if there is no current event or if the current
+ *     event contains no time.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Time
+TkCurrentTime(dispPtr)
+    TkDisplay *dispPtr;                /* Display for which the time is desired. */
+{
+    register XEvent *eventPtr;
+
+    if (pendingPtr == NULL) {
+       return dispPtr->lastEventTime;
+    }
+    eventPtr = pendingPtr->eventPtr;
+    switch (eventPtr->type) {
+       case ButtonPress:
+       case ButtonRelease:
+           return eventPtr->xbutton.time;
+       case KeyPress:
+       case KeyRelease:
+           return eventPtr->xkey.time;
+       case MotionNotify:
+           return eventPtr->xmotion.time;
+       case EnterNotify:
+       case LeaveNotify:
+           return eventPtr->xcrossing.time;
+       case PropertyNotify:
+           return eventPtr->xproperty.time;
+    }
+    return dispPtr->lastEventTime;
+}
diff --git a/v7/src/swat/c/tk3.2-custom/tkWindow.c b/v7/src/swat/c/tk3.2-custom/tkWindow.c
new file mode 100644 (file)
index 0000000..3d2470b
--- /dev/null
@@ -0,0 +1,1802 @@
+/**************************
+  Changes on April 1, 1993 to support Scheme UITK:
+  1) Added Tk_CreateMainWindow_from_display.
+  2) Renamed GetScreen to GetScreenByName.  Added GetScreenByDisplay.
+  3) Rewrote Tk_CreateMainWindow into Tk_CreateMainWindow_from_data,
+     which takes both a lookup procedure for finding a Screen and the
+     data necessary for the lookup.  Rewrite Tk_CreateMainWindow in
+     terms of this.
+  4) Changed the signature of CreateTopLevelWindow to accept a lookup
+     procedure and data.
+  5) Made NameWindow public for reparenting widgets when mapped by UITK
+  6) Added external entry point Tk_DestroyDisplayByNumber.
+**************************/
+
+/* 
+ * tkWindow.c --
+ *
+ *     This file provides basic window-manipulation procedures,
+ *     which are equivalent to procedures in Xlib (and even
+ *     invoke them) but also maintain the local Tk_Window
+ *     structure.
+ *
+ * Copyright 1989-1992 Regents of the University of California.
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies.  The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/swat/c/tk3.2-custom/tkWindow.c,v 1.1 1995/08/02 21:23:26 adams Exp $ SPRITE (Berkeley)";
+#endif
+
+#include "tkConfig.h"
+#include "tkInt.h"
+
+/*
+ * Count of number of main windows currently open in this process.
+ */
+
+int tk_NumMainWindows;
+
+/*
+ * List of all displays currently in use.
+ */
+
+TkDisplay *tkDisplayList = NULL;
+
+/*
+ * Have statics in this module been initialized?
+ */
+
+static initialized = 0;
+
+/*
+ * Context information used to map from X window id's to
+ * TkWindow structures (during event handling, for example):
+ */
+
+XContext tkWindowContext;
+
+/*
+ * The variables below hold several uid's that are used in many places
+ * in the toolkit.
+ */
+
+Tk_Uid tkDisabledUid = NULL;
+Tk_Uid tkActiveUid = NULL;
+Tk_Uid tkNormalUid = NULL;
+
+/*
+ * Default values for "changes" and "atts" fields of TkWindows.  Note
+ * that Tk always requests all events for all windows, except StructureNotify
+ * events on internal windows:  these events are generated internally.
+ */
+
+static XWindowChanges defChanges = {
+    0, 0, 1, 1, 0, 0, Above
+};
+#define ALL_EVENTS_MASK \
+    KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
+    EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
+    VisibilityChangeMask|SubstructureNotifyMask| \
+    FocusChangeMask|PropertyChangeMask|ColormapChangeMask
+static XSetWindowAttributes defAtts= {
+    None,                      /* background_pixmap */
+    0,                         /* background_pixel */
+    CopyFromParent,            /* border_pixmap */
+    0,                         /* border_pixel */
+    ForgetGravity,             /* bit_gravity */
+    NorthWestGravity,          /* win_gravity */
+    NotUseful,                 /* backing_store */
+    ~0,                                /* backing_planes */
+    0,                         /* backing_pixel */
+    False,                     /* save_under */
+    ALL_EVENTS_MASK,           /* event_mask */
+    0,                         /* do_not_propagate_mask */
+    False,                     /* override_redirect */
+    CopyFromParent,            /* colormap */
+    None                       /* cursor */
+};
+
+/*
+ * The following structure defines all of the commands supported by
+ * Tk, and the C procedures that execute them.
+ */
+
+typedef struct {
+    char *name;                        /* Name of command. */
+    int (*cmdProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
+           int argc, char **argv));
+                               /* Command procedure. */
+} TkCmd;
+
+TkCmd commands[] = {
+    /*
+     * Commands that are part of the intrinsics:
+     */
+
+    {"after",          Tk_AfterCmd},
+    {"bind",           Tk_BindCmd},
+    {"destroy",                Tk_DestroyCmd},
+    {"focus",          Tk_FocusCmd},
+    {"grab",           Tk_GrabCmd},
+    {"option",         Tk_OptionCmd},
+    {"pack",           Tk_PackCmd},
+    {"place",          Tk_PlaceCmd},
+    {"selection",      Tk_SelectionCmd},
+    {"tk",             Tk_TkCmd},
+    {"tkwait",         Tk_TkwaitCmd},
+    {"update",         Tk_UpdateCmd},
+    {"winfo",          Tk_WinfoCmd},
+    {"wm",             Tk_WmCmd},
+
+    /*
+     * Widget-creation commands.
+     */
+    {"button",         Tk_ButtonCmd},
+    {"canvas",         Tk_CanvasCmd},
+    {"checkbutton",    Tk_ButtonCmd},
+    {"entry",          Tk_EntryCmd},
+    {"frame",          Tk_FrameCmd},
+    {"label",          Tk_ButtonCmd},
+    {"listbox",                Tk_ListboxCmd},
+    {"menu",           Tk_MenuCmd},
+    {"menubutton",     Tk_MenubuttonCmd},
+    {"message",                Tk_MessageCmd},
+    {"radiobutton",    Tk_ButtonCmd},
+    {"scale",          Tk_ScaleCmd},
+    {"scrollbar",      Tk_ScrollbarCmd},
+    {"text",           Tk_TextCmd},
+    {"toplevel",       Tk_FrameCmd},
+    {(char *) NULL,    (int (*)()) NULL}
+};
+
+/*
+ * Forward declarations to procedures defined later in this file:
+ */
+
+static Tk_Window       CreateTopLevelWindow
+  _ANSI_ARGS_((Tcl_Interp *interp,
+              Tk_Window parent,
+              char *name,
+              TkDisplay *LookupProcedure(Tcl_Interp *interp,
+                                         char *data,
+                                         int *screenPtr),
+              char *data));
+static void            DoConfigureNotify _ANSI_ARGS_((TkWindow *winPtr));
+static TkDisplay *     GetScreenByName _ANSI_ARGS_((Tcl_Interp *interp,
+                                                    char *screenName,
+                                                    int *screenPtr));
+static TkDisplay *     GetScreenByDisplay _ANSI_ARGS_((Tcl_Interp *interp,
+                                                       char /*Display*/ *disp,
+                                                       int *screenPtr));
+extern int             NameWindow _ANSI_ARGS_((Tcl_Interp *interp,
+                           TkWindow *winPtr, TkWindow *parentPtr,
+                           char *name));
+static TkWindow        *       NewWindow _ANSI_ARGS_((TkDisplay *dispPtr,
+                           int screenNum, TkWindow *parentPtr));
+
+extern void             Tk_DestroyDisplayByNumber _ANSI_ARGS_ ((Display *disp));
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateTopLevelWindow --
+ *
+ *     Make a new window that will be at top-level (its parent will
+ *     be the root window of a screen).
+ *
+ * Results:
+ *     The return value is a token for the new window, or NULL if
+ *     an error prevented the new window from being created.  If
+ *     NULL is returned, an error message will be left in
+ *     interp->result.
+ *
+ * Side effects:
+ *     A new window structure is allocated locally.  An X
+ *     window is NOT initially created, but will be created
+ *     the first time the window is mapped.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tk_Window
+CreateTopLevelWindow(interp, parent, name, LookupProcedure, data)
+    Tcl_Interp *interp;                /* Interpreter to use for error reporting. */
+    Tk_Window parent;          /* Token for logical parent of new window
+                                * (used for naming, options, etc.).  May
+                                * be NULL. */
+    char *name;                        /* Name for new window;  if parent is
+                                * non-NULL, must be unique among parent's
+                                * children. */
+    TkDisplay *(*LookupProcedure) _ANSI_ARGS_ ((Tcl_Interp *interp, char *data, int *screenPtr));
+                               /* Lookup a display structure, either */
+                               /* by name or by display connection */
+    char *data;                        /* Data supplied to LookupProcedure: */
+                               /* either a screen name or a display */
+                               /* connection */
+{
+    register TkWindow *winPtr;
+    register TkDisplay *dispPtr;
+    int screenId;
+
+    if (!initialized) {
+       initialized = 1;
+       tkWindowContext = XUniqueContext();
+       tkActiveUid = Tk_GetUid("active");
+       tkDisabledUid = Tk_GetUid("disabled");
+       tkNormalUid = Tk_GetUid("normal");
+    }
+
+    if ((LookupProcedure==GetScreenByName) && (parent != NULL) &&
+       (data != NULL) && (data[0] == '\0'))
+    { dispPtr = ((TkWindow *) parent)->dispPtr;
+      screenId = Tk_ScreenNumber(parent);
+    }
+    else
+    { dispPtr = LookupProcedure(interp, data, &screenId);
+      if (dispPtr == NULL) return (Tk_Window) NULL;
+    }
+
+    winPtr = NewWindow(dispPtr, screenId, (TkWindow *) parent);
+
+    /*
+     * Internal windows don't normally ask for StructureNotify events,
+     * since we can generate them internally.  However, for top-level
+     * windows we need to as for the events because the window could
+     * be manipulated externally.
+     */
+
+    winPtr->atts.event_mask |= StructureNotifyMask;
+
+    /*
+     * (Need to set the TK_TOP_LEVEL flag immediately here;  otherwise
+     * Tk_DestroyWindow will core dump if it is called before the flag
+     * has been set.)
+     */
+
+    winPtr->flags |= TK_TOP_LEVEL;
+    if (parent != NULL) {
+       if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) {
+           Tk_DestroyWindow((Tk_Window) winPtr);
+           return (Tk_Window) NULL;
+       }
+    }
+    TkWmNewWindow(winPtr);
+    return (Tk_Window) winPtr;
+}
+\f
+TkDisplay * MakeTkDisplay(display, NameLength, screenName)
+     Display *display;
+     int NameLength;
+     char* screenName;
+{
+  register TkDisplay *dispPtr = (TkDisplay *) ckalloc(sizeof(TkDisplay));
+  register long i;
+
+  dispPtr->display = display;
+  dispPtr->nextPtr = tkDisplayList;
+  dispPtr->name = (char *) ckalloc((unsigned) (NameLength+1));
+  dispPtr->lastEventTime = CurrentTime;
+  strncpy(dispPtr->name, screenName, NameLength);
+  dispPtr->focusTopLevelPtr = NULL;
+  dispPtr->focussedOnEnter = 0;
+  dispPtr->name[NameLength] = '\0';
+  dispPtr->bindInfoStale = 1;
+  dispPtr->errorPtr = NULL;
+  dispPtr->deleteCount = 0;
+  dispPtr->commWindow = NULL;
+  dispPtr->selectionOwner = NULL;
+  dispPtr->selectionSerial = 0;
+  dispPtr->multipleAtom = None;
+  dispPtr->atomInit = 0;
+  dispPtr->cursorFont = None;
+  dispPtr->grabWinPtr = NULL;
+  dispPtr->eventualGrabWinPtr = NULL;
+  dispPtr->buttonWinPtr = NULL;
+  dispPtr->serverWinPtr = NULL;
+  dispPtr->firstGrabEventPtr = NULL;
+  dispPtr->lastGrabEventPtr = NULL;
+  dispPtr->grabFlags = 0;
+  dispPtr->colorModels =
+    (Tk_ColorModel *) ckalloc((unsigned)
+                             (ScreenCount(display)*
+                              sizeof(Tk_ColorModel)));
+  for (i = ScreenCount(display)-1; i >= 0; i--) {
+    if (DisplayPlanes(display, i) <= 4) {
+      dispPtr->colorModels[i] = TK_MONO;
+    } else {
+      dispPtr->colorModels[i] = TK_COLOR;
+    }
+  }
+  tkDisplayList = dispPtr;
+  Tk_CreateFileHandler(ConnectionNumber(display),
+                      TK_READABLE, (void (*)()) NULL,
+                      (ClientData) display);
+  return dispPtr;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetScreenByName --
+ *
+ *     Given a string name for a display-plus-screen, find the
+ *     TkDisplay structure for the display and return the screen
+ *     number too.
+ *
+ * Results:
+ *     The return value is a pointer to information about the display,
+ *     or NULL if the display couldn't be opened.  In this case, an
+ *     error message is left in interp->result.  The location at
+ *     *screenPtr is overwritten with the screen number parsed from
+ *     screenName.
+ *
+ * Side effects:
+ *     A new connection is opened to the display if there is no
+ *     connection already.  A new TkDisplay data structure is also
+ *     setup, if necessary.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkDisplay *
+GetScreenByName(interp, screenName, screenPtr)
+    Tcl_Interp *interp;                /* Place to leave error message. */
+    char *screenName;          /* Name for screen.  NULL or empty means
+                                * use DISPLAY envariable. */
+    int *screenPtr;            /* Where to store screen number. */
+{
+    register TkDisplay *dispPtr;
+    char *p;
+    int length, screenId, i;
+
+    /*
+     * Separate the screen number from the rest of the display
+     * name.  ScreenName is assumed to have the syntax
+     * <display>.<screen> with the dot and the screen being
+     * optional.
+     */
+
+    if ((screenName == NULL) || (screenName[0] == '\0')) {
+       screenName = getenv("DISPLAY");
+       if (screenName == NULL) {
+           interp->result =
+                   "no display name and no $DISPLAY environment variable";
+           return (TkDisplay *) NULL;
+       }
+    }
+    length = strlen(screenName);
+    screenId = 0;
+    p = screenName+length-1;
+    while (isdigit(*p) && (p != screenName)) {
+       p--;
+    }
+    if ((*p == '.') && (p[1] != '\0')) {
+       length = p - screenName;
+       screenId = strtoul(p+1, (char **) NULL, 10);
+    }
+
+    /*
+     * See if we already have a connection to this display.  If not,
+     * then open a new connection.
+     */
+
+    for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr)
+    { if (dispPtr == NULL)
+      { Display *display;
+       /* block and unblock added by Hal  -- 7/22/95 in an attempt to fix a problem
+           with making this work over PPP (i.e. slow) connections */
+        block_signals ();
+       display = XOpenDisplay(screenName);
+        unblock_signals ();
+       if (display == NULL)
+       { Tcl_AppendResult(interp, "couldn't connect to display \"",
+                          screenName, "\"", (char *) NULL);
+         return (TkDisplay *) NULL;
+       }
+       dispPtr = MakeTkDisplay(display, length, screenName);
+       break;
+      }
+      if ((strncmp(dispPtr->name, screenName, length) == 0)
+         && (dispPtr->name[length] == '\0'))
+      {
+       break;
+      }
+    }
+    if (screenId >= ScreenCount(dispPtr->display)) {
+       sprintf(interp->result, "bad screen number \"%d\"", screenId);
+       return (TkDisplay *) NULL;
+    }
+    *screenPtr = screenId;
+    return dispPtr;
+}
+
+static TkDisplay *GetScreenByDisplay(interp, disp, screenPtr)
+     Tcl_Interp *interp;
+     char *disp;
+     int *screenPtr;
+/* GetScreenByDisplay assumes screen 0! */
+{ Display *Disp = (Display *) disp;
+  register TkDisplay *dispPtr;
+
+  for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr)
+  { if (dispPtr == NULL)
+    { dispPtr = MakeTkDisplay(Disp, 0, "");
+      break;
+    }
+    if (Disp==(dispPtr->display)) break;
+  }
+  *screenPtr = 0;
+  return dispPtr;
+}
+
+void Tk_DestroyDisplayByNumber(Disp)
+     Display *Disp;
+/* Tk_DestroyDisplayByNumber assumes screen 0! */
+{ register TkDisplay *dispPtr, *Prev=(TkDisplay *) NULL;
+
+  for (dispPtr = tkDisplayList; dispPtr != NULL;
+       Prev=dispPtr, dispPtr = dispPtr->nextPtr)
+  { if (Disp==(dispPtr->display))
+    { if (Prev==(TkDisplay *) NULL)
+       tkDisplayList = dispPtr->nextPtr;
+      else Prev->nextPtr = dispPtr->nextPtr;
+      ckfree(dispPtr->name);
+      ckfree(dispPtr->colorModels);
+      ckfree(dispPtr);
+      Tk_DeleteFileHandler(ConnectionNumber(Disp));
+      return;
+    }
+  }
+  return;
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * NewWindow --
+ *
+ *     This procedure creates and initializes a TkWindow structure.
+ *
+ * Results:
+ *     The return value is a pointer to the new window.
+ *
+ * Side effects:
+ *     A new window structure is allocated and all its fields are
+ *     initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkWindow *
+NewWindow(dispPtr, screenNum, parentPtr)
+    TkDisplay *dispPtr;                /* Display associated with new window. */
+    int screenNum;             /* Index of screen for new window. */
+    TkWindow *parentPtr;       /* Parent from which this window should
+                                * inherit visual inforamtion.  NULL means
+                                * use screen defaults instead of
+                                * inheriting. */
+{
+    register TkWindow *winPtr;
+
+    winPtr = (TkWindow *) ckalloc(sizeof(TkWindow));
+    winPtr->display = dispPtr->display;
+    winPtr->dispPtr = dispPtr;
+    winPtr->screenNum = screenNum;
+    if (parentPtr != NULL) {
+       winPtr->visual = parentPtr->visual;
+       winPtr->depth = parentPtr->depth;
+    } else {
+       winPtr->visual = DefaultVisual(dispPtr->display, screenNum);
+       winPtr->depth = DefaultDepth(dispPtr->display, screenNum);
+    }
+    winPtr->window = None;
+    winPtr->childList = NULL;
+    winPtr->parentPtr = NULL;
+    winPtr->nextPtr = NULL;
+    winPtr->mainPtr = NULL;
+    winPtr->pathName = NULL;
+    winPtr->nameUid = NULL;
+    winPtr->classUid = NULL;
+    winPtr->changes = defChanges;
+    winPtr->dirtyChanges = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
+    winPtr->atts = defAtts;
+    if (parentPtr != NULL) {
+       winPtr->atts.colormap = parentPtr->atts.colormap;
+    } else {
+       winPtr->atts.colormap = DefaultColormap(dispPtr->display, screenNum);
+    }
+    winPtr->dirtyAtts = CWEventMask|CWColormap;
+    winPtr->flags = 0;
+    winPtr->handlerList = NULL;
+    winPtr->focusProc = NULL;
+    winPtr->focusData = NULL;
+    winPtr->optionLevel = -1;
+    winPtr->selHandlerList = NULL;
+    winPtr->selClearProc = NULL;
+    winPtr->selClearData = NULL;
+    winPtr->geomProc = NULL;
+    winPtr->geomData = NULL;
+    winPtr->reqWidth = winPtr->reqHeight = 0;
+    winPtr->internalBorderWidth = 0;
+    winPtr->wmInfoPtr = NULL;
+
+    return winPtr;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * NameWindow --
+ *
+ *     This procedure is invoked to give a window a name and insert
+ *     the window into the hierarchy associated with a particular
+ *     application.
+ *
+ * Results:
+ *     A standard Tcl return value.
+ *
+ * Side effects:
+ *      See above.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+NameWindow(interp, winPtr, parentPtr, name)
+    Tcl_Interp *interp;                /* Interpreter to use for error reporting. */
+    register TkWindow *winPtr; /* Window that is to be named and inserted. */
+    TkWindow *parentPtr;       /* Pointer to logical parent for winPtr
+                                * (used for naming, options, etc.). */
+    char *name;                        /* Name for winPtr;   must be unique among
+                                * parentPtr's children. */
+{
+#define FIXED_SIZE 200
+    char staticSpace[FIXED_SIZE];
+    char *pathName;
+    int new;
+    Tcl_HashEntry *hPtr;
+    int length1, length2;
+
+    /*
+     * Setup all the stuff except name right away, then do the name stuff
+     * last.  This is so that if the name stuff fails, everything else
+     * will be properly initialized (needed to destroy the window cleanly
+     * after the naming failure).
+     */
+    winPtr->parentPtr = parentPtr;
+    winPtr->nextPtr = parentPtr->childList;
+    parentPtr->childList = winPtr;
+    winPtr->mainPtr = parentPtr->mainPtr;
+    winPtr->nameUid = Tk_GetUid(name);
+
+    /*
+     * Don't permit names that start with an upper-case letter:  this
+     * will just cause confusion with class names in the option database.
+     */
+
+    if (isupper(name[0])) {
+       Tcl_AppendResult(interp,
+               "window name starts with an upper-case letter: \"",
+               name, "\"", (char *) NULL);
+       return TCL_ERROR;
+    }
+
+    /*
+     * To permit names of arbitrary length, must be prepared to malloc
+     * a buffer to hold the new path name.  To run fast in the common
+     * case where names are short, use a fixed-size buffer on the
+     * stack.
+     */
+
+    length1 = strlen(parentPtr->pathName);
+    length2 = strlen(name);
+    if ((length1+length2+2) <= FIXED_SIZE) {
+       pathName = staticSpace;
+    } else {
+       pathName = (char *) ckalloc((unsigned) (length1+length2+2));
+    }
+    if (length1 == 1) {
+       pathName[0] = '.';
+       strcpy(pathName+1, name);
+    } else {
+       strcpy(pathName, parentPtr->pathName);
+       pathName[length1] = '.';
+       strcpy(pathName+length1+1, name);
+    }
+    hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new);
+    if (pathName != staticSpace) {
+       ckfree(pathName);
+    }
+    if (!new) {
+       Tcl_AppendResult(interp, "window name \"", name,
+               "\" already exists in parent", (char *) NULL);
+       return TCL_ERROR;
+    }
+    Tcl_SetHashValue(hPtr, winPtr);
+    winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
+    return TCL_OK;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CreateMainWindow --
+ *
+ *     Make a new main window.  A main window is a special kind of
+ *     top-level window used as the outermost window in an
+ *     application.
+ *
+ * Results:
+ *     The return value is a token for the new window, or NULL if
+ *     an error prevented the new window from being created.  If
+ *     NULL is returned, an error message will be left in
+ *     interp->result.
+ *
+ * Side effects:
+ *     A new window structure is allocated locally;  "interp" is
+ *     associated with the window and registered for "send" commands
+ *     under "baseName".  BaseName may be extended with an instance
+ *     number in the form "#2" if necessary to make it globally
+ *     unique.  Tk-related commands are bound into interp.  An X
+ *     window is NOT initially created, but will be created the
+ *     first time the window is mapped.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_CreateMainWindow_from_data(interp, baseName, LookupProcedure, data)
+    Tcl_Interp *interp;                /* Interpreter to use for error reporting. */
+    char *baseName;            /* Base name for application;  usually of the
+                                * form "prog instance". */
+    TkDisplay *(*LookupProcedure) _ANSI_ARGS_ ((Tcl_Interp *interp, char *data, int *screenPtr));
+                               /* Lookup a display structure, either */
+                               /* by name or by display connection */
+    char *data;                        /* Data supplied to LookupProcedure */
+{
+    Tk_Window tkwin;
+    int result, dummy;
+    Tcl_HashEntry *hPtr;
+    register TkMainInfo *mainPtr;
+    register TkWindow *winPtr;
+    register TkCmd *cmdPtr;
+    char *libDir;
+
+    /*
+     * Create the basic TkWindow structure.
+     */
+
+    tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,
+                                LookupProcedure, data);
+    if (tkwin == NULL) {
+       return NULL;
+    }
+
+    /*
+     * Create the TkMainInfo structure for this application, and set
+     * up name-related information for the new window.
+     */
+
+    winPtr = (TkWindow *) tkwin;
+    mainPtr = (TkMainInfo *) ckalloc(sizeof(TkMainInfo));
+    mainPtr->winPtr = winPtr;
+    mainPtr->interp = interp;
+    Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);
+    mainPtr->bindingTable = Tk_CreateBindingTable(interp);
+    mainPtr->focusPtr = winPtr;
+    mainPtr->focusDefaultPtr = NULL;
+    mainPtr->optionRootPtr = NULL;
+    winPtr->mainPtr = mainPtr;
+    hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);
+    Tcl_SetHashValue(hPtr, winPtr);
+    winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr);
+
+    /*
+     * Register the interpreter for "send" purposes.  If baseName isn't
+     * already unique, find a unique suffix to add to it to make it
+     * unique.  Change the window's name to contain the suffix.
+     */
+
+    result = Tk_RegisterInterp(interp, baseName, tkwin);
+    if (result == TCL_OK) {
+       winPtr->nameUid = Tk_GetUid(baseName);
+    } else {
+       char newName[110];
+       int i;
+
+       for (i = 2; ; i++) {
+           sprintf(newName, "%.100s #%d", baseName, i);
+           Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
+           result = Tk_RegisterInterp(interp, newName, tkwin);
+           if (result == TCL_OK) {
+               break;
+           }
+           if (i >= 100) {
+               Tcl_SetResult(interp,
+                       "couldn't generate unique name to register application",
+                       TCL_STATIC);
+               Tk_DestroyWindow(tkwin);
+           }
+       }
+       winPtr->nameUid = Tk_GetUid(newName);
+    }
+
+    /*
+     * Bind in Tk's commands.
+     */
+
+    for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
+       Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,
+               (ClientData) tkwin, (void (*)()) NULL);
+    }
+
+    /*
+     * Set variables for the intepreter.
+     */
+
+    libDir = getenv("TK_LIBRARY");
+    if (libDir == NULL) {
+       libDir = TK_LIBRARY;
+    }
+    Tcl_SetVar(interp, "tk_library", libDir, TCL_GLOBAL_ONLY);
+    Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY);
+    Tcl_SetVar(interp, "tkVersion", TK_VERSION, TCL_GLOBAL_ONLY);
+
+    tk_NumMainWindows++;
+    return tkwin;
+}
+
+Tk_Window
+  Tk_CreateMainWindow(interp, screenName, baseName)
+    Tcl_Interp *interp;                /* Interpreter to use for error reporting. */
+    char *screenName;          /* Name of screen on which to create
+                                * window.  Empty or NULL string means
+                                * use DISPLAY environment variable. */
+    char *baseName;            /* Base name for application;  usually of the
+                                * form "prog instance". */
+{ return Tk_CreateMainWindow_from_data(interp, baseName,
+                                      GetScreenByName, screenName);
+}
+
+Tk_Window
+Tk_CreateMainWindow_from_display(interp, display, baseName)
+    Tcl_Interp *interp;                /* Interpreter to use for error reporting. */
+    Display *display;          /* X Display connection */
+    char *baseName;            /* Base name for application;  usually of the
+                                * form "prog instance". */
+{ return Tk_CreateMainWindow_from_data(interp, baseName,
+                                      GetScreenByDisplay,
+                                      (char *) display);
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateWindow --
+ *
+ *     Create a new internal or top-level window as a child of an
+ *     existing window.
+ *
+ * Results:
+ *     The return value is a token for the new window.  This
+ *     is not the same as X's token for the window.  If an error
+ *     occurred in creating the window (e.g. no such display or
+ *     screen), then an error message is left in interp->result and
+ *     NULL is returned.
+ *
+ * Side effects:
+ *     A new window structure is allocated locally.  An X
+ *     window is not initially created, but will be created
+ *     the first time the window is mapped.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_CreateWindow(interp, parent, name, screenName)
+    Tcl_Interp *interp;                /* Interpreter to use for error reporting.
+                                * Interp->result is assumed to be
+                                * initialized by the caller. */
+    Tk_Window parent;          /* Token for parent of new window. */
+    char *name;                        /* Name for new window.  Must be unique
+                                * among parent's children. */
+    char *screenName;          /* If NULL, new window will be internal on
+                                * same screen as its parent.  If non-NULL,
+                                * gives name of screen on which to create
+                                * new window;  window will be a top-level
+                                * window. */
+{
+    TkWindow *parentPtr = (TkWindow *) parent;
+    TkWindow *winPtr;
+
+    if (screenName == NULL)
+    { winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum,
+                        parentPtr);
+      if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK)
+      { Tk_DestroyWindow((Tk_Window) winPtr);
+       return NULL;
+      }
+      else
+      { return (Tk_Window) winPtr;
+      }
+    }
+    else
+    { return CreateTopLevelWindow(interp, parent, name,
+                                 GetScreenByName, screenName);
+    }
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CreateWindowFromPath --
+ *
+ *     This procedure is similar to Tk_CreateInternalWindow except
+ *     that it uses a path name to create the window, rather than
+ *     a parent and a child name.
+ *
+ * Results:
+ *     The return value is a token for the new window.  This
+ *     is not the same as X's token for the window.  If an error
+ *     occurred in creating the window (e.g. no such display or
+ *     screen), then an error message is left in interp->result and
+ *     NULL is returned.
+ *
+ * Side effects:
+ *     A new window structure is allocated locally.  An X
+ *     window is not initially created, but will be created
+ *     the first time the window is mapped.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName)
+    Tcl_Interp *interp;                /* Interpreter to use for error reporting.
+                                * Interp->result is assumed to be
+                                * initialized by the caller. */
+    Tk_Window tkwin;           /* Token for any window in application
+                                * that is to contain new window. */
+    char *pathName;            /* Path name for new window within the
+                                * application of tkwin.  The parent of
+                                * this window must already exist, but
+                                * the window itself must not exist. */
+    char *screenName;          /* If NULL, new window will be on same
+                                * screen as its parent.  If non-NULL,
+                                * gives name of screen on which to create
+                                * new window;  window will be a top-level
+                                * window. */
+{
+#define FIXED_SPACE 5
+    char fixedSpace[FIXED_SPACE+1];
+    char *p;
+    Tk_Window parent;
+    int numChars;
+
+    /*
+     * Strip the parent's name out of pathName (it's everything up
+     * to the last dot).  There are two tricky parts: (a) must
+     * copy the parent's name somewhere else to avoid modifying
+     * the pathName string (for large names, space for the copy
+     * will have to be malloc'ed);  (b) must special-case the
+     * situation where the parent is ".".
+     */
+
+    p = strrchr(pathName, '.');
+    if (p == NULL) {
+       Tcl_AppendResult(interp, "bad window path name \"", pathName,
+               "\"", (char *) NULL);
+       return NULL;
+    }
+    numChars = p-pathName;
+    if (numChars > FIXED_SPACE) {
+       p = (char *) ckalloc((unsigned) (numChars+1));
+    } else {
+       p = fixedSpace;
+    }
+    if (numChars == 0) {
+       *p = '.';
+       p[1] = '\0';
+    } else {
+       strncpy(p, pathName, numChars);
+       p[numChars] = '\0';
+    }
+
+    /*
+     * Find the parent window.
+     */
+
+    parent = Tk_NameToWindow(interp, p, tkwin);
+    if (p != fixedSpace) {
+       ckfree(p);
+    }
+    if (parent == NULL) {
+       return NULL;
+    }
+
+    /*
+     * Create the window.
+     */
+
+    if (screenName == NULL) {
+       TkWindow *parentPtr = (TkWindow *) parent;
+       TkWindow *winPtr;
+
+       winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum,
+                          parentPtr);
+       if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)
+               != TCL_OK) {
+           Tk_DestroyWindow((Tk_Window) winPtr);
+           return NULL;
+       } else
+       { return (Tk_Window) winPtr;
+       }
+    } else {
+       return CreateTopLevelWindow(interp, parent, pathName+numChars+1,
+                                   GetScreenByName, screenName);
+    }
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DestroyWindow --
+ *
+ *     Destroy an existing window.  After this call, the caller
+ *     should never again use the token.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The window is deleted, along with all of its children.
+ *     Relevant callback procedures are invoked.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DestroyWindow(tkwin)
+    Tk_Window tkwin;           /* Window to destroy. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+    XEvent event;
+
+    if (winPtr->flags & TK_ALREADY_DEAD) {
+       /*
+        * An destroy event binding caused the window to be destroyed
+        * again.  Ignore the request.
+        */
+
+       return;
+    }
+
+    /*
+     * Recursively destroy children.  The TK_RECURSIVE_DESTROY
+     * flags means that the child's window needn't be explicitly
+     * destroyed (the destroy of the parent already did it), nor
+     * does it need to be removed from its parent's child list,
+     * since the parent is being destroyed too.
+     */
+
+    while (winPtr->childList != NULL) {
+       winPtr->childList->flags |= TK_RECURSIVE_DESTROY;
+       Tk_DestroyWindow((Tk_Window) winPtr->childList);
+    }
+
+    /*
+     * Generate a DestroyNotify event.  In order for the DestroyNotify
+     * event to be processed correctly, need to make sure the window
+     * exists.  This is a bit of a kludge, and may be unnecessarily
+     * expensive, but without it no event handlers will get called for
+     * windows that don't exist yet.
+     */
+
+    if (winPtr->window == None) {
+       Tk_MakeWindowExist(tkwin);
+    }
+    winPtr->flags |= TK_ALREADY_DEAD;
+    event.type = DestroyNotify;
+    event.xdestroywindow.serial =
+           LastKnownRequestProcessed(winPtr->display);
+    event.xdestroywindow.send_event = False;
+    event.xdestroywindow.display = winPtr->display;
+    event.xdestroywindow.event = winPtr->window;
+    event.xdestroywindow.window = winPtr->window;
+    Tk_HandleEvent(&event);
+
+    /*
+     * Cleanup the data structures associated with this window.
+     * No need to destroy windows during recursive destroys, since
+     * that will happen automatically when the parent window is
+     * destroyed (not true for top-level windows:  must destroy
+     * them explicitly).
+     */
+
+    if (winPtr->window != None) {
+       if (!(winPtr->flags & TK_RECURSIVE_DESTROY)
+               || (winPtr->flags & TK_TOP_LEVEL)) {
+           XDestroyWindow(winPtr->display, winPtr->window);
+       }
+       XDeleteContext(winPtr->display, winPtr->window, tkWindowContext);
+       winPtr->window = None;
+    }
+    if (winPtr->parentPtr != NULL) {
+       if (winPtr->parentPtr->childList == winPtr) {
+           winPtr->parentPtr->childList = winPtr->nextPtr;
+       } else {
+           register TkWindow *winPtr2;
+    
+           for (winPtr2 = winPtr->parentPtr->childList; ;
+                   winPtr2 = winPtr2->nextPtr) {
+               if (winPtr2 == NULL) {
+                   panic("Tk_DestroyWindow couldn't find child in parent (deleted twice?)");
+                   break;
+               }
+               if (winPtr2->nextPtr == winPtr) {
+                   winPtr2->nextPtr = winPtr->nextPtr;
+                   break;
+               }
+           }
+       }
+    }
+    TkEventDeadWindow(winPtr);
+    TkFocusDeadWindow(winPtr);
+    TkOptionDeadWindow(winPtr);
+    TkSelDeadWindow(winPtr);
+    if (winPtr->flags & TK_TOP_LEVEL) {
+       TkWmDeadWindow(winPtr);
+    }
+    TkGrabDeadWindow(winPtr);
+    if (winPtr->mainPtr != NULL) {
+       Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,
+               (ClientData) winPtr->pathName);
+       if (winPtr->pathName != NULL) {
+           Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable,
+                   winPtr->pathName));
+       }
+       if (winPtr->mainPtr->winPtr == winPtr) {
+           register TkCmd *cmdPtr;
+
+           /*
+            * Deleting a main window.  Delete the TkMainInfo structure too
+            * and replace all of Tk's commands with dummy commands that
+            * return errors.  Also delete the "send" command to unregister
+            * the interpreter.
+            */
+
+           for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
+               Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name,
+                       TkDeadAppCmd, (ClientData) NULL, (void (*)()) NULL);
+           }
+           Tcl_CreateCommand(winPtr->mainPtr->interp, "send",
+                   TkDeadAppCmd, (ClientData) NULL, (void (*)()) NULL);
+           Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);
+           Tk_DeleteBindingTable(winPtr->mainPtr->bindingTable);
+           ckfree((char *) winPtr->mainPtr);
+           tk_NumMainWindows--;
+       }
+    }
+    ckfree((char *) winPtr);
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_MapWindow --
+ *
+ *     Map a window within its parent.  This may require the
+ *     window and/or its parents to actually be created.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The given window will be mapped.  Windows may also
+ *     be created.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_MapWindow(tkwin)
+    Tk_Window tkwin;           /* Token for window to map. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+    XEvent event;
+
+    if (winPtr->flags & TK_MAPPED) {
+       return;
+    }
+    if (winPtr->window == None) {
+       Tk_MakeWindowExist(tkwin);
+    }
+    if (winPtr->flags & TK_TOP_LEVEL) {
+       /*
+        * Lots of special processing has to be done for top-level
+        * windows.  Let tkWm.c handle everything itself.
+        */
+
+       TkWmMapWindow(winPtr);
+       return;
+    }
+    winPtr->flags |= TK_MAPPED;
+    XMapWindow(winPtr->display, winPtr->window);
+    event.type = MapNotify;
+    event.xmap.serial = LastKnownRequestProcessed(winPtr->display);
+    event.xmap.send_event = False;
+    event.xmap.display = winPtr->display;
+    event.xmap.event = winPtr->window;
+    event.xmap.window = winPtr->window;
+    event.xmap.override_redirect = winPtr->atts.override_redirect;
+    Tk_HandleEvent(&event);
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_MakeWindowExist --
+ *
+ *     Ensure that a particular window actually exists.  This
+ *     procedure shouldn't normally need to be invoked from
+ *     outside the Tk package, but may be needed if someone
+ *     wants to manipulate a window before mapping it.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     When the procedure returns, the X window associated with
+ *     tkwin is guaranteed to exist.  This may require the
+ *     window's ancestors to be created also.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_MakeWindowExist(tkwin)
+    Tk_Window tkwin;           /* Token for window. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+    Window parent;
+
+    if (winPtr->window != None) {
+       return;
+    }
+
+    if (winPtr->flags & TK_TOP_LEVEL) {
+       parent = XRootWindow(winPtr->display, winPtr->screenNum);
+    } else {
+       if (winPtr->parentPtr->window == None) {
+           Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
+       }
+       parent = winPtr->parentPtr->window;
+    }
+
+    winPtr->window = XCreateWindow(winPtr->display, parent,
+           winPtr->changes.x, winPtr->changes.y,
+           winPtr->changes.width, winPtr->changes.height,
+           winPtr->changes.border_width, winPtr->depth,
+           InputOutput, winPtr->visual, winPtr->dirtyAtts,
+           &winPtr->atts);
+    XSaveContext(winPtr->display, winPtr->window, tkWindowContext,
+           (caddr_t) winPtr);
+    winPtr->dirtyAtts = 0;
+    winPtr->dirtyChanges &= ~(CWX|CWY|CWWidth|CWHeight|CWBorderWidth);
+    if (winPtr->dirtyChanges != 0) {
+       XConfigureWindow(winPtr->display, winPtr->window,
+               winPtr->dirtyChanges, &winPtr->changes);
+       winPtr->dirtyChanges = 0;
+    }
+
+    /*
+     * Issue a ConfigureNotify event if there were deferred configuration
+     * changes.
+     */
+
+    if (winPtr->flags & TK_NEED_CONFIG_NOTIFY) {
+       winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
+       DoConfigureNotify(winPtr);
+    }
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_UnmapWindow, etc. --
+ *
+ *     There are several procedures under here, each of which
+ *     mirrors an existing X procedure.  In addition to performing
+ *     the functions of the corresponding procedure, each
+ *     procedure also updates the local window structure and
+ *     synthesizes an X event (if the window's structure is being
+ *     managed internally).
+ *
+ * Results:
+ *     See the manual entries.
+ *
+ * Side effects:
+ *     See the manual entries.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_UnmapWindow(tkwin)
+    Tk_Window tkwin;           /* Token for window to unmap. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    if (!(winPtr->flags & TK_MAPPED)) {
+       return;
+    }
+    winPtr->flags &= ~TK_MAPPED;
+    XUnmapWindow(winPtr->display, winPtr->window);
+    if (!(winPtr->flags & TK_TOP_LEVEL)) {
+       XEvent event;
+
+       event.type = UnmapNotify;
+       event.xunmap.serial = LastKnownRequestProcessed(winPtr->display);
+       event.xunmap.send_event = False;
+       event.xunmap.display = winPtr->display;
+       event.xunmap.event = winPtr->window;
+       event.xunmap.window = winPtr->window;
+       event.xunmap.from_configure = False;
+       Tk_HandleEvent(&event);
+    }
+}
+
+void
+Tk_ConfigureWindow(tkwin, valueMask, valuePtr)
+    Tk_Window tkwin;           /* Window to re-configure. */
+    unsigned int valueMask;    /* Mask indicating which parts of
+                                * *valuePtr are to be used. */
+    XWindowChanges *valuePtr;  /* New values. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    if (valueMask & CWX) {
+       winPtr->changes.x = valuePtr->x;
+    }
+    if (valueMask & CWY) {
+       winPtr->changes.y = valuePtr->y;
+    }
+    if (valueMask & CWWidth) {
+       winPtr->changes.width = valuePtr->width;
+    }
+    if (valueMask & CWHeight) {
+       winPtr->changes.height = valuePtr->height;
+    }
+    if (valueMask & CWBorderWidth) {
+       winPtr->changes.border_width = valuePtr->border_width;
+    }
+    if (valueMask & CWSibling) {
+       winPtr->changes.sibling = valuePtr->sibling;
+    }
+    if (valueMask & CWStackMode) {
+       winPtr->changes.stack_mode = valuePtr->stack_mode;
+    }
+
+    if (winPtr->window != None) {
+       XConfigureWindow(winPtr->display, winPtr->window,
+               valueMask, valuePtr);
+       if (!(winPtr->flags & TK_TOP_LEVEL)) {
+           DoConfigureNotify(winPtr);
+       }
+    } else {
+       winPtr->dirtyChanges |= valueMask;
+       winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+    }
+}
+
+void
+Tk_MoveWindow(tkwin, x, y)
+    Tk_Window tkwin;           /* Window to move. */
+    int x, y;                  /* New location for window (within
+                                * parent). */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->changes.x = x;
+    winPtr->changes.y = y;
+    if (winPtr->window != None) {
+       XMoveWindow(winPtr->display, winPtr->window, x, y);
+       if (!(winPtr->flags & TK_TOP_LEVEL)) {
+           DoConfigureNotify(winPtr);
+       }
+    } else {
+       winPtr->dirtyChanges |= CWX|CWY;
+       winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+    }
+}
+
+void
+Tk_ResizeWindow(tkwin, width, height)
+    Tk_Window tkwin;           /* Window to resize. */
+    unsigned int width, height;        /* New dimensions for window. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->changes.width = width;
+    winPtr->changes.height = height;
+    if (winPtr->window != None) {
+       XResizeWindow(winPtr->display, winPtr->window, width, height);
+       if (!(winPtr->flags & TK_TOP_LEVEL)) {
+           DoConfigureNotify(winPtr);
+       }
+    } else {
+       winPtr->dirtyChanges |= CWWidth|CWHeight;
+       winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+    }
+}
+
+void
+Tk_MoveResizeWindow(tkwin, x, y, width, height)
+    Tk_Window tkwin;           /* Window to move and resize. */
+    int x, y;                  /* New location for window (within
+                                * parent). */
+    unsigned int width, height;        /* New dimensions for window. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->changes.x = x;
+    winPtr->changes.y = y;
+    winPtr->changes.width = width;
+    winPtr->changes.height = height;
+    if (winPtr->window != None) {
+       XMoveResizeWindow(winPtr->display, winPtr->window,
+               x, y, width, height);
+       if (!(winPtr->flags & TK_TOP_LEVEL)) {
+           DoConfigureNotify(winPtr);
+       }
+    } else {
+       winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;
+       winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+    }
+}
+
+void
+Tk_SetWindowBorderWidth(tkwin, width)
+    Tk_Window tkwin;           /* Window to modify. */
+    int width;                 /* New border width for window. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->changes.border_width = width;
+    if (winPtr->window != None) {
+       XSetWindowBorderWidth(winPtr->display, winPtr->window, width);
+       if (!(winPtr->flags & TK_TOP_LEVEL)) {
+           DoConfigureNotify(winPtr);
+       }
+    } else {
+       winPtr->dirtyChanges |= CWBorderWidth;
+       winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+    }
+}
+
+void
+Tk_ChangeWindowAttributes(tkwin, valueMask, attsPtr)
+    Tk_Window tkwin;           /* Window to manipulate. */
+    unsigned long valueMask;   /* OR'ed combination of bits,
+                                * indicating which fields of
+                                * *attsPtr are to be used. */
+    register XSetWindowAttributes *attsPtr;
+                               /* New values for some attributes. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    if (valueMask & CWBackPixmap) {
+       winPtr->atts.background_pixmap = attsPtr->background_pixmap;
+    }
+    if (valueMask & CWBackPixel) {
+       winPtr->atts.background_pixel = attsPtr->background_pixel;
+    }
+    if (valueMask & CWBorderPixmap) {
+       winPtr->atts.border_pixmap = attsPtr->border_pixmap;
+    }
+    if (valueMask & CWBorderPixel) {
+       winPtr->atts.border_pixel = attsPtr->border_pixel;
+    }
+    if (valueMask & CWBitGravity) {
+       winPtr->atts.bit_gravity = attsPtr->bit_gravity;
+    }
+    if (valueMask & CWWinGravity) {
+       winPtr->atts.win_gravity = attsPtr->win_gravity;
+    }
+    if (valueMask & CWBackingStore) {
+       winPtr->atts.backing_store = attsPtr->backing_store;
+    }
+    if (valueMask & CWBackingPlanes) {
+       winPtr->atts.backing_planes = attsPtr->backing_planes;
+    }
+    if (valueMask & CWBackingPixel) {
+       winPtr->atts.backing_pixel = attsPtr->backing_pixel;
+    }
+    if (valueMask & CWOverrideRedirect) {
+       winPtr->atts.override_redirect = attsPtr->override_redirect;
+    }
+    if (valueMask & CWSaveUnder) {
+       winPtr->atts.save_under = attsPtr->save_under;
+    }
+    if (valueMask & CWEventMask) {
+       winPtr->atts.event_mask = attsPtr->event_mask;
+    }
+    if (valueMask & CWDontPropagate) {
+       winPtr->atts.do_not_propagate_mask
+               = attsPtr->do_not_propagate_mask;
+    }
+    if (valueMask & CWColormap) {
+       winPtr->atts.colormap = attsPtr->colormap;
+    }
+    if (valueMask & CWCursor) {
+       winPtr->atts.cursor = attsPtr->cursor;
+    }
+
+    if (winPtr->window != None) {
+       XChangeWindowAttributes(winPtr->display, winPtr->window,
+               valueMask, attsPtr);
+    } else {
+       winPtr->dirtyAtts |= valueMask;
+    }
+}
+
+void
+Tk_SetWindowBackground(tkwin, pixel)
+    Tk_Window tkwin;           /* Window to manipulate. */
+    unsigned long pixel;       /* Pixel value to use for
+                                * window's background. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->atts.background_pixel = pixel;
+
+    if (winPtr->window != None) {
+       XSetWindowBackground(winPtr->display, winPtr->window, pixel);
+    } else {
+       winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixmap)
+               | CWBackPixel;
+    }
+}
+
+void
+Tk_SetWindowBackgroundPixmap(tkwin, pixmap)
+    Tk_Window tkwin;           /* Window to manipulate. */
+    Pixmap pixmap;             /* Pixmap to use for window's
+                                * background. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->atts.background_pixmap = pixmap;
+
+    if (winPtr->window != None) {
+       XSetWindowBackgroundPixmap(winPtr->display,
+               winPtr->window, pixmap);
+    } else {
+       winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixel)
+               | CWBackPixmap;
+    }
+}
+
+void
+Tk_SetWindowBorder(tkwin, pixel)
+    Tk_Window tkwin;           /* Window to manipulate. */
+    unsigned long pixel;       /* Pixel value to use for
+                                * window's border. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->atts.border_pixel = pixel;
+
+    if (winPtr->window != None) {
+       XSetWindowBorder(winPtr->display, winPtr->window, pixel);
+    } else {
+       winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixmap)
+               | CWBorderPixel;
+    }
+}
+
+void
+Tk_SetWindowBorderPixmap(tkwin, pixmap)
+    Tk_Window tkwin;           /* Window to manipulate. */
+    Pixmap pixmap;             /* Pixmap to use for window's
+                                * border. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->atts.border_pixmap = pixmap;
+
+    if (winPtr->window != None) {
+       XSetWindowBorderPixmap(winPtr->display,
+               winPtr->window, pixmap);
+    } else {
+       winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixel)
+               | CWBorderPixmap;
+    }
+}
+
+void
+Tk_DefineCursor(tkwin, cursor)
+    Tk_Window tkwin;           /* Window to manipulate. */
+    Cursor cursor;             /* Cursor to use for window (may be None). */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->atts.cursor = cursor;
+
+    if (winPtr->window != None) {
+       XDefineCursor(winPtr->display, winPtr->window, cursor);
+    } else {
+       winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
+    }
+}
+
+void
+Tk_UndefineCursor(tkwin)
+    Tk_Window tkwin;           /* Window to manipulate. */
+{
+    Tk_DefineCursor(tkwin, None);
+}
+
+void
+Tk_SetWindowColormap(tkwin, colormap)
+    Tk_Window tkwin;           /* Window to manipulate. */
+    Colormap colormap;         /* Colormap to use for window. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->atts.colormap = colormap;
+
+    if (winPtr->window != None) {
+       XSetWindowColormap(winPtr->display, winPtr->window, colormap);
+    } else {
+       winPtr->dirtyAtts |= CWColormap;
+    }
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetWindowVisual --
+ *
+ *     This procedure is called to specify a visual to be used
+ *     for a Tk window when it is created.  This procedure, if
+ *     called at all, must be called before the X window is created
+ *     (i.e. before Tk_MakeWindowExist is called).
+ *
+ * Results:
+ *     The return value is 1 if successful, or 0 if the X window has
+ *     been already created.
+ *
+ * Side effects:
+ *     The information given is stored for when the window is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_SetWindowVisual(tkwin, visual, depth, colormap)
+    Tk_Window tkwin;           /* Window to manipulate. */
+    Visual *visual;            /* New visual for window. */
+    unsigned int depth;                /* New depth for window. */
+    Colormap colormap;         /* An appropriate colormap for the visual. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    if( winPtr->window != None ){
+       /* Too late! */
+       return 0;
+    }
+
+    winPtr->visual = visual;
+    winPtr->depth = depth;
+    winPtr->atts.colormap = colormap;
+
+    /*
+     * The following code is needed to make sure that the window doesn't
+     * inherit the parent's border pixmap, which would result in a BadMatch
+     * error.
+     */
+
+    if (!(winPtr->dirtyAtts & CWBorderPixmap)) {
+       winPtr->dirtyAtts |= CWBorderPixel;
+    }
+    return 1;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * DoConfigureNotify --
+ *
+ *     Generate a ConfigureNotify event describing the current
+ *     configuration of a window.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     An event is generated and processed by Tk_HandleEvent.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DoConfigureNotify(winPtr)
+    register TkWindow *winPtr;         /* Window whose configuration
+                                        * was just changed. */
+{
+    XEvent event;
+
+    event.type = ConfigureNotify;
+    event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
+    event.xconfigure.send_event = False;
+    event.xconfigure.display = winPtr->display;
+    event.xconfigure.event = winPtr->window;
+    event.xconfigure.window = winPtr->window;
+    event.xconfigure.x = winPtr->changes.x;
+    event.xconfigure.y = winPtr->changes.y;
+    event.xconfigure.width = winPtr->changes.width;
+    event.xconfigure.height = winPtr->changes.height;
+    event.xconfigure.border_width = winPtr->changes.border_width;
+    if (winPtr->changes.stack_mode == Above) {
+       event.xconfigure.above = winPtr->changes.sibling;
+    } else {
+       event.xconfigure.above = None;
+    }
+    event.xconfigure.override_redirect = winPtr->atts.override_redirect;
+    Tk_HandleEvent(&event);
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetClass --
+ *
+ *     This procedure is used to give a window a class.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     A new class is stored for tkwin, replacing any existing
+ *     class for it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetClass(tkwin, className)
+    Tk_Window tkwin;           /* Token for window to assign class. */
+    char *className;           /* New class for tkwin. */
+{
+    register TkWindow *winPtr = (TkWindow *) tkwin;
+
+    winPtr->classUid = Tk_GetUid(className);
+    if (winPtr->flags & TK_TOP_LEVEL) {
+       TkWmSetClass(winPtr);
+    }
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_NameToWindow --
+ *
+ *     Given a string name for a window, this procedure
+ *     returns the token for the window, if there exists a
+ *     window corresponding to the given name.
+ *
+ * Results:
+ *     The return result is either a token for the window corresponding
+ *     to "name", or else NULL to indicate that there is no such
+ *     window.  In this case, an error message is left in interp->result.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_NameToWindow(interp, pathName, tkwin)
+    Tcl_Interp *interp;                /* Where to report errors. */
+    char *pathName;            /* Path name of window. */
+    Tk_Window tkwin;           /* Token for window:  name is assumed to
+                                * belong to the same main window as tkwin. */
+{
+    Tcl_HashEntry *hPtr;
+
+    hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
+           pathName);
+    if (hPtr == NULL) {
+       Tcl_AppendResult(interp, "bad window path name \"",
+               pathName, "\"", (char *) NULL);
+       return NULL;
+    }
+    return (Tk_Window) Tcl_GetHashValue(hPtr);
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DisplayName --
+ *
+ *     Return the textual name of a window's display.
+ *
+ * Results:
+ *     The return value is the string name of the display associated
+ *     with tkwin.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tk_DisplayName(tkwin)
+    Tk_Window tkwin;           /* Window whose display name is desired. */
+{
+    return ((TkWindow *) tkwin)->dispPtr->name;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetColorModel --
+ *
+ *     This procedure changes the current color model for a window
+ *     (actually, for the window's screen).
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The color model for tkwin's screen is set to "model".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetColorModel(tkwin, model)
+    Tk_Window tkwin;           /* Token for window;  this selects a screen
+                                * whose color model is to be modified. */
+    Tk_ColorModel model;       /* New model for tkwin's screen. */
+{
+    TkWindow *winPtr = (TkWindow *) tkwin;
+    winPtr->dispPtr->colorModels[winPtr->screenNum] = model;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetColorModel --
+ *
+ *     This procedure returns the current color model for a window
+ *     (actually, for the window's screen).
+ *
+ * Results:
+ *     A color model.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_ColorModel
+Tk_GetColorModel(tkwin)
+    Tk_Window tkwin;           /* Token for window;  this selects a screen
+                                * whose color model is returned. */
+{
+    TkWindow *winPtr = (TkWindow *) tkwin;
+    return winPtr->dispPtr->colorModels[winPtr->screenNum];
+
+}
diff --git a/v7/src/swat/c/uitk-prims.c b/v7/src/swat/c/uitk-prims.c
new file mode 100644 (file)
index 0000000..fd4cc55
--- /dev/null
@@ -0,0 +1,106 @@
+#include "scheme.h"
+#include "prims.h"
+
+#define External_Primitive(fn_name)            \
+   extern SCHEME_OBJECT EXFUN (fn_name, (void))
+
+External_Primitive(Prim_tcl_eval);
+External_Primitive(Prim_tk_completely_handles_event);
+External_Primitive(Prim_tk_create_tl_window);
+External_Primitive(Prim_tk_do_events);
+External_Primitive(Prim_tk_drain);
+External_Primitive(Prim_tk_generate_scheme_event);
+External_Primitive(Prim_tk_init);
+External_Primitive(Prim_tk_invoke);
+External_Primitive(Prim_tk_kill_app);
+External_Primitive(Prim_tk_manage_geom);
+External_Primitive(Prim_tk_map_widget);
+External_Primitive(Prim_tk_map_window);
+External_Primitive(Prim_tk_move);
+External_Primitive(Prim_tk_move_resize);
+External_Primitive(Prim_tk_next_wakeup);
+External_Primitive(Prim_tk_resize);
+External_Primitive(Prim_tk_unmap_window);
+External_Primitive(Prim_tk_win_req_height);
+External_Primitive(Prim_tk_win_req_width);
+External_Primitive(Prim_tk_widget_get_tkwin);
+External_Primitive(Prim_tk_win_display);
+External_Primitive(Prim_tk_win_is_mapped);
+External_Primitive(Prim_tk_win_height);
+External_Primitive(Prim_tk_win_width);
+External_Primitive(Prim_tk_win_window);
+External_Primitive(Prim_tk_win_x);
+External_Primitive(Prim_tk_win_y);
+External_Primitive(Prim_tk_win_name);
+External_Primitive(Prim_tk_win_pathname);
+External_Primitive(Prim_tk_delete_display);
+External_Primitive(Prim_tk_destroy_widget);
+External_Primitive(Prim_tk_make_button);
+External_Primitive(Prim_tk_make_canvas);
+External_Primitive(Prim_tk_make_check_button);
+External_Primitive(Prim_tk_make_entry);
+External_Primitive(Prim_tk_make_label);
+External_Primitive(Prim_tk_make_listbox);
+External_Primitive(Prim_tk_make_menu);
+External_Primitive(Prim_tk_make_menu_button);
+External_Primitive(Prim_tk_make_message);
+External_Primitive(Prim_tk_make_radio_button);
+External_Primitive(Prim_tk_make_scale);
+External_Primitive(Prim_tk_make_scrollbar);
+External_Primitive(Prim_tk_make_text);
+
+extern char *EXFUN (dload_initialize_file, (void));
+
+char *
+  DEFUN_VOID (dload_initialize_file)
+{ /* Primitives in tk-c-mit.c */
+  declare_primitive ("%tclGlobalEval", Prim_tcl_eval, 2, 2, 0);
+  declare_primitive ("%tkCompletelyHandlesEvent?",
+                    Prim_tk_completely_handles_event, 1, 1, 0);
+  declare_primitive ("%tkCreateTopLevelWindow",
+                    Prim_tk_create_tl_window, 3, 3, 0);
+  declare_primitive ("%tkDoEvents", Prim_tk_do_events, 0, 0, 0);
+  declare_primitive ("%tkDrainCallBacks", Prim_tk_drain, 2, 2, 0);
+  declare_primitive ("%tkGenerateSchemeEvent",
+                    Prim_tk_generate_scheme_event, 2, 2, 0);
+  declare_primitive ("%tkInit", Prim_tk_init, 2, 2, 0);
+  declare_primitive ("%tkInvokeCommand", Prim_tk_invoke, 2, LEXPR, 0);
+  declare_primitive ("%tkKillApplication", Prim_tk_kill_app, 1, 1, 0);
+  declare_primitive ("%tkManageGeometry", Prim_tk_manage_geom, 2, 2, 0);
+  declare_primitive ("%tkMapWidget", Prim_tk_map_widget, 6, 6, 0);
+  declare_primitive ("%tkMapWindow", Prim_tk_map_window, 1, 1, 0);
+  declare_primitive ("%tkMoveWindow", Prim_tk_move, 3, 3, 0);
+  declare_primitive ("%tkMoveResizeWindow", Prim_tk_move_resize, 5, 5, 0);
+  declare_primitive ("%tkNextWakeup", Prim_tk_next_wakeup, 0, 0, 0);
+  declare_primitive ("%tkResizeWindow", Prim_tk_resize, 3, 3, 0);
+  declare_primitive ("%tkUnmapWindow", Prim_tk_unmap_window, 1, 1, 0);
+  declare_primitive ("%tkWinReqHeight", Prim_tk_win_req_height, 1, 1, 0);
+  declare_primitive ("%tkWinReqWidth", Prim_tk_win_req_width, 1, 1, 0);
+  declare_primitive ("%tkWidget.tkwin", Prim_tk_widget_get_tkwin, 1, 1, 0);
+  declare_primitive ("%tkWinDisplay", Prim_tk_win_display, 1, 1, 0);
+  declare_primitive ("%tkWinIsMapped?", Prim_tk_win_is_mapped, 1, 1, 0);
+  declare_primitive ("%tkWinHeight", Prim_tk_win_height, 1, 1, 0);
+  declare_primitive ("%tkWinWidth", Prim_tk_win_width, 1, 1, 0);
+  declare_primitive ("%tkWinWindow", Prim_tk_win_window, 1, 1, 0);
+  declare_primitive ("%tkWinX", Prim_tk_win_x, 1, 1, 0);
+  declare_primitive ("%tkWinY", Prim_tk_win_y, 1, 1, 0);
+  declare_primitive ("%tkWinName", Prim_tk_win_name, 1, 1, 0);
+  declare_primitive ("%tkWinPathName", Prim_tk_win_pathname, 1, 1, 0);
+  /* Primitive in widget-c-mit.c */
+  declare_primitive ("%tkDeleteDisplay", Prim_tk_delete_display, 1, 1, 0);
+  declare_primitive ("%tkDestroyWidget", Prim_tk_destroy_widget, 1, 1, 0);
+  declare_primitive ("%tkMakeButton", Prim_tk_make_button, 2, 2, 0);
+  declare_primitive ("%tkMakeCanvas", Prim_tk_make_canvas, 2, 2, 0);
+  declare_primitive ("%tkMakeCheckButton", Prim_tk_make_check_button, 2, 2, 0);
+  declare_primitive ("%tkMakeEntry", Prim_tk_make_entry, 2, 2, 0);
+  declare_primitive ("%tkMakeLabel", Prim_tk_make_label, 2, 2, 0);
+  declare_primitive ("%tkMakeListbox", Prim_tk_make_listbox, 2, 2, 0);
+  declare_primitive ("%tkMakeMenu", Prim_tk_make_menu, 2, 2, 0);
+  declare_primitive ("%tkMakeMenuButton", Prim_tk_make_menu_button, 2, 2, 0);
+  declare_primitive ("%tkMakeMessage", Prim_tk_make_message, 2, 2, 0);
+  declare_primitive ("%tkMakeRadioButton", Prim_tk_make_radio_button, 2, 2, 0);
+  declare_primitive ("%tkMakeScale", Prim_tk_make_scale, 2, 2, 0);
+  declare_primitive ("%tkMakeScrollBar", Prim_tk_make_scrollbar, 2, 2, 0);
+  declare_primitive ("%tkMakeText", Prim_tk_make_text, 2, 2, 0);
+  return "#UITK";
+}
diff --git a/v7/src/swat/c/widget-c-mit.c b/v7/src/swat/c/widget-c-mit.c
new file mode 100644 (file)
index 0000000..5a73d82
--- /dev/null
@@ -0,0 +1,171 @@
+/* Cover routines to make MIT Scheme primitives out of the procedures */
+/* in button-c.c. */
+
+#include "scheme.h"
+#include "prims.h"
+#include "ansidecl.h"
+#include "X11/Xlib.h"
+
+DEFINE_PRIMITIVE ("%tkDeleteDisplay", Prim_tk_delete_display, 1, 1, 0)
+{ /* (%tkDeleteDisplay XDisplayNumber) */
+  extern void tk_delete_display (Display *disp);
+  PRIMITIVE_HEADER(1);
+  tk_delete_display((Display *) arg_integer(1));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkDestroyWidget", Prim_tk_destroy_widget, 1, 1, 0)
+{ /* (%tkDestroyWidget tk-handle ) */
+  extern void tk_destroy_widget(long /*Button **/ button);
+  PRIMITIVE_HEADER(1);
+  tk_destroy_widget((long /*Button **/) arg_integer(1));
+  PRIMITIVE_RETURN(UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("%tkMakeButton", Prim_tk_make_button, 2, 2, 0)
+{ /* (%tkMakeButton ParentTKWindow name-string)
+  */
+  extern int *MakeButton(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeButton((long /*Tk_Window*/) arg_integer(1),
+                       STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%tkMakeCanvas", Prim_tk_make_canvas, 2, 2, 0)
+{ /* (%tkMakeCanvas ParentTKWindow name-string)
+  */
+  extern int *MakeCanvas(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeCanvas((long /*Tk_Window*/) arg_integer(1),
+                       STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%tkMakeCheckButton", Prim_tk_make_check_button, 2, 2, 0)
+{ /* (%tkMakeCheckButton ParentTKWindow name-string)
+  */
+  extern int *MakeCheckButton(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeCheckButton((long /*Tk_Window*/) arg_integer(1),
+                            STRING_ARG(2))));
+  
+}
+
+DEFINE_PRIMITIVE ("%tkMakeEntry", Prim_tk_make_entry, 2, 2, 0)
+{ /* (%tkMakeEntry ParentTKWindow name-string)
+  */
+  extern int *MakeEntry(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeEntry((long /*Tk_Window*/) arg_integer(1),
+                      STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%tkMakeLabel", Prim_tk_make_label, 2, 2, 0)
+{ /* (%tkMakeLabel ParentTKWindow name-string)
+  */
+  extern int *MakeLabel(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeLabel((long /*Tk_Window*/) arg_integer(1),
+                      STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%tkMakeListbox", Prim_tk_make_listbox, 2, 2, 0)
+{ /* (%tkMakeListbox ParentTKWindow name-string)
+  */
+  extern int *MakeListbox(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeListbox((long /*Tk_Window*/) arg_integer(1),
+                        STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%tkMakeMenu", Prim_tk_make_menu, 2, 2, 0)
+{ /* (%tkMakeMenu ParentTKWindow name-string)
+  */
+  extern int *MakeMenu(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeMenu((long /*Tk_Window*/) arg_integer(1),
+                      STRING_ARG(2))));
+
+}
+
+DEFINE_PRIMITIVE ("%tkMakeMenuButton", Prim_tk_make_menu_button, 2, 2, 0)
+{ /* (%tkMakeMenuButton ParentTKWindow name-string)
+  */
+  extern int *MakeMenuButton(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeMenuButton((long /*Tk_Window*/) arg_integer(1),
+                           STRING_ARG(2))));
+
+}
+
+DEFINE_PRIMITIVE ("%tkMakeMessage", Prim_tk_make_message, 2, 2, 0)
+{ /* (%tkMakeMessage ParentTKWindow name-string)
+  */
+  extern int *MakeMessage(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeMessage((long /*Tk_Window*/) arg_integer(1),
+                        STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%tkMakeRadioButton", Prim_tk_make_radio_button, 2, 2, 0)
+{ /* (%tkMakeRadioButton ParentTKWindow name-string)
+  */
+  extern int *MakeRadioButton(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeRadioButton((long /*Tk_Window*/) arg_integer(1),
+                            STRING_ARG(2))));
+  
+}
+
+DEFINE_PRIMITIVE ("%tkMakeScale", Prim_tk_make_scale, 2, 2, 0)
+{ /* (%tkMakeScale ParentTKWindow name-string)
+  */
+  extern int *MakeScale(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeScale((long /*Tk_Window*/) arg_integer(1),
+                      STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%tkMakeScrollBar", Prim_tk_make_scrollbar, 2, 2, 0)
+{ /* (%tkMakeScrollBar ParentTKWindow name-string)
+  */
+  extern int *MakeScrollBar(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeScrollBar((long /*Tk_Window*/) arg_integer(1),
+                          STRING_ARG(2))));
+}
+
+DEFINE_PRIMITIVE ("%tkMakeText", Prim_tk_make_text, 2, 2, 0)
+{ /* (%tkMakeText ParentTKWindow name-string)
+  */
+  extern int *MakeText(long /*Tk_Window*/ parent_window, char *name);
+  PRIMITIVE_HEADER(2);
+  PRIMITIVE_RETURN
+    (long_to_integer
+     ((long) MakeText((long /*Tk_Window*/) arg_integer(1),
+                     STRING_ARG(2))));
+
+}
diff --git a/v7/src/swat/c/widget-c.c b/v7/src/swat/c/widget-c.c
new file mode 100644 (file)
index 0000000..e4ac8d8
--- /dev/null
@@ -0,0 +1,279 @@
+#include <stdio.h>
+#include "tk.h"
+#include "default.h"
+#include "tkInt.h"
+
+typedef struct
+{ Tk_Window tkwin;
+  Display *display;
+  Tcl_Interp *interp;
+} All_Widgets;
+
+
+int *
+MakeButton(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "button";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_ButtonCmd ((ClientData) tkMainWindow,
+                   tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeCanvas(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "canvas";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_CanvasCmd ((ClientData) tkMainWindow,
+                   tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeCheckButton(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "checkbutton";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_ButtonCmd ((ClientData) tkMainWindow,
+                   tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeEntry(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "entry";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_EntryCmd ((ClientData) tkMainWindow,
+                  tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeLabel(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "label";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_ButtonCmd ((ClientData) tkMainWindow,
+                  tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeListbox(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "listbox";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_ListboxCmd ((ClientData) tkMainWindow,
+                    tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeMenu(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "menu";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_MenuCmd ((ClientData) tkMainWindow,
+                  tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeMenuButton(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "menubutton";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_MenubuttonCmd ((ClientData) tkMainWindow,
+                       tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeMessage(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "message";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_MessageCmd ((ClientData) tkMainWindow,
+                    tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeRadioButton(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "radiobutton";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_ButtonCmd ((ClientData) tkMainWindow,
+                   tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeScale(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "scale";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_ScaleCmd ((ClientData) tkMainWindow,
+                   tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeScrollBar(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "scrollbar";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_ScrollbarCmd ((ClientData) tkMainWindow,
+                      tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+int *
+MakeText(Tk_Window tkMainWindow, char *name)
+{ char      *argv [2];
+  Tcl_Interp *tclInterp;
+
+  argv [0] = "text";
+  argv [1] = name;
+  tclInterp = (((TkWindow *) arg_integer(1))->mainPtr)->interp;
+  if (Tk_TextCmd ((ClientData) tkMainWindow,
+                 tclInterp, 2, argv) != TCL_OK)
+  { fprintf (stderr, tclInterp->result);
+    exit (1);
+  }
+  return (int *) GetCmdClientData (tclInterp, name);
+}
+
+/* These ought to be in tk-c.c but need internal data structures to work */
+
+char *
+tk_map_widget (All_Widgets *Widget, Tk_Window tkMainWindow, char *name,
+              Window xwindow, int x, int y)
+/* This better work for all TK widgets or there's trouble */
+/* "name" is the name originally given to this widget. */
+{ TkWindow *win;
+
+  win = ((TkWindow *) (Widget->tkwin));
+  if ((xwindow != (Window) NULL) &&
+      (((win->parentPtr)->window) != xwindow))
+  { extern int         NameWindow _ANSI_ARGS_((Tcl_Interp *interp,
+                                               TkWindow *winPtr,
+                                               TkWindow *parentPtr,
+                                               char *name));
+    char *argv [3];
+    Tcl_Interp *tclInterp = (((TkWindow *) tkMainWindow)->mainPtr)->interp;
+    Tk_Window InternalWindow =
+      Tk_CreateWindow(tclInterp, tkMainWindow, name, (char *) NULL);
+
+    ((TkWindow *) InternalWindow)->window = xwindow;
+    if (((win->parentPtr)->window) != (Window) NULL)
+      fprintf(stderr, "tk_map_widget: changing parent window!\n");
+    NameWindow(tclInterp, (TkWindow *) win,
+              (TkWindow *) InternalWindow, name);
+    argv[0] = "rename";
+    argv[1] = name;
+    argv[2] = Tk_PathName((Tk_Window) win);
+    if (Tcl_RenameCmd((ClientData) 0, tclInterp, 3, argv) != TCL_OK)
+    { fprintf(stderr, "Failed. %s\n", tclInterp->result);
+    }
+  }
+  Tk_MoveWindow ((Tk_Window) win, x, y);
+  if (xwindow == (Window) NULL) Tk_UnmapWindow((Tk_Window) win);
+  else Tk_MapWindow ((Tk_Window) win);
+  return Tk_PathName((Tk_Window) win);
+}
+
+Tk_Window
+tk_tkwin_widget (All_Widgets *Widget)
+/* This better work for all TK widgets or there's trouble */
+{
+    return Widget->tkwin;
+}
+
+void
+tk_destroy_widget (All_Widgets *Widget)
+{ /* This better work for all TK widgets or there's trouble */
+  Tk_DestroyWindow(Widget->tkwin);
+  return;
+}
+
+void
+  tk_delete_display (Display *disp)
+{ Tk_DestroyDisplayByNumber(disp);
+  return;
+}
diff --git a/v7/src/swat/scheme/baseobj.scm b/v7/src/swat/scheme/baseobj.scm
new file mode 100644 (file)
index 0000000..7b8907a
--- /dev/null
@@ -0,0 +1,647 @@
+;;;;; -*- Scheme -*-
+;;;;; Basic objects for the Scheme User Interface Tool Kit
+;;;; MIT Scheme Version derived from Scheme-To-C version 1.2
+
+;;;; $Id: baseobj.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
+
+;;;; Application objects
+
+(define (application->TKMainWindow obj) (Application%.TKMainWindow obj))
+(define (application->Display obj) (Application%.Xdisplay obj))
+
+(define (valid-color-for-application? app color-string)
+  ((string->color (application->display app)) color-string))
+
+(define (valid-color? color-string)
+  ;; For default application
+  ((string->color (application->display *the-default-application*))
+   color-string))
+
+(define (make-top-level-geometry-callback kid)
+  ;; Is the TK-TOP-LEVEL-WINDOW required any more? --Jim
+  (let ((my-screen-area #f))
+    (lambda (configure-event)
+      (Decode-Configure-Event
+       Configure-Event
+       (lambda (type serial send_event display event window x y width
+                    height border-width above override-redirect)
+        type serial send_event display event window x y
+        border-width above override-redirect ; Not used
+        (let ((new-area (make-UITKRectangle
+                                       ; (make-point x y)
+                         (make-point 0 0)
+                         (make-size width height))))
+          (if (not (screen-area= new-area my-screen-area))
+              (begin
+                (%XClearWindow display window)
+                (assign-screen-area! kid #F)
+                (assign-screen-area! kid new-area)))
+          (set! my-screen-area new-area))
+        'DONE)))))
+
+(define (valid-child? object)
+  (or (interactor%? object)
+      (box%? object)
+      (arraybox%? object)
+      (shape%? object)
+      (tkwidget%? object)))
+
+(define (application-add-child! application to-be-managed . child-name)
+  ;; Name is an optional string that overrides the application's
+  ;; name for providing a title to the child window
+  (if (not (valid-child? to-be-managed))
+      (error "APPLICATION-ADD-CHILD!: Bad UIObj" to-be-managed))
+  (one-parent-only! to-be-managed application)
+  (let ((really-adding? #F)
+       (new-entry (cons to-be-managed 'TK-Top-Level-Window)))
+    (update-locked-list!
+     (Application%.%child-windows application)
+     (lambda (kids)
+       (if (assq to-be-managed kids)
+          kids
+          (begin
+            (set! really-adding? #T)
+            (cons new-entry kids)))))
+    (if really-adding?
+       (let ((Xdisplay (Application%.Xdisplay application))
+             (context (Application%.context application))
+             (top-level-geometry-callback
+              (make-top-level-geometry-callback to-be-managed))
+             (TKMainW
+              (application->TKMainWindow application))
+             (TKW (make-ToolKitWindow application #F #F)))
+         (let* ((drawing-surface (make-DrawingSurface TKW #F))
+                (tlwindow
+                 (tk-create-top-level-window
+                  TKMainW
+                  (hash top-level-geometry-callback *our-hash-table*))))
+           (set-cdr! new-entry tlwindow)
+           (set-ToolKitWindow.TK-Window! TKW tlwindow)
+           (set-ToolKitWindow.Top-Level-Geometry-Callback!
+            TKW top-level-geometry-callback)
+           (set-context! to-be-managed context)
+           (assign-drawing-surface! to-be-managed drawing-surface)
+           (let ((desired-size (get-desired-size to-be-managed))
+                 (window-name (tkwin.pathname tlwindow)))
+             (tk-invoke-command
+              'WM TKMainW
+              (list "title" window-name
+                    (if (and (pair? child-name)
+                             (string? (car child-name)))
+                        (car child-name)
+                        (Application%.application-name application))))
+             (let ((tlwindow-width
+                    (number->string (or (size.width desired-size) 0)))
+                   (tlwindow-height
+                    (number->string (or (size.height desired-size) 0))))
+
+               #|
+               (tk-invoke-command
+                'WM TKMainW
+                (list "minsize" window-name "1" "1"))
+               |#
+
+               (tk-invoke-command
+                'WM TKMainW
+                (list "minsize" window-name tlwindow-width tlwindow-height))
+               ;;X signals errors if we don't do this, but I'm damned if I know why
+               (tk-invoke-command
+                'WM TKMainW
+                (list "geometry" window-name
+                      (string-append tlwindow-width "x" tlwindow-height)))
+               )
+             (let ((kill-me
+                    (lambda ()
+                      (application-remove-destroyed-child! application to-be-managed)
+                      )))
+               (tk-invoke-command
+                'BIND TKMainW
+                (list window-name "<Destroy>"
+                      (string-append
+                       "SchemeCallBack "
+                       (number->string (hash kill-me *our-hash-table*)))))
+               (UIObj-protect-from-gc! to-be-managed kill-me))
+             ;; Events start being generated and handled in
+             ;; the other thread as soon as we map this
+             ;; window!  We must map the window before doing
+             ;; the MAKE-UITKWINDOW below, because TK
+             ;; doesn't create the X window until the widget
+             ;; is mapped.
+             (our-with-thread-mutex-locked
+              'add-child-locks-out-others
+              *event-processing-mutex*
+              (lambda ()
+                (tk-map-window tlwindow)
+                (let ((UITKWindow
+                       (make-uitkwindow
+                        Xdisplay
+                        (wrap-window Xdisplay
+                                     (tkwin.window tlwindow)))))
+                  (set-DrawingSurface.UITKWindow!
+                   drawing-surface UITKWindow)
+                  (assign-drawing-surface!
+                   to-be-managed drawing-surface))
+                ;; UITKWindow changed and some objects will
+                ;; need that rather than just the TK top
+                ;; level window.
+                (assign-screen-area!
+                 to-be-managed
+                 (make-UITKRectangle (make-point 0 0)
+                                     (tkwin->size tlwindow)))
+                ))))
+         #|
+         ;;let window resize when kid requests resize
+         ;;but this means that size is determined by kid -- not WM
+         ;;do we want both kinds of windows??
+         (on-geometry-change!
+          to-be-managed 'APPLICATION
+          (lambda (old-screen-area new-screen-area)
+            old-screen-area            ;not used
+            (if (eq? new-screen-area #T) ;instigated by child
+                (let* ((desired-size (get-desired-size to-be-managed))
+                       (tlwindow-width
+                        (number->string (or (size.width desired-size) 0)))
+                       (tlwindow-height
+                        (number->string (or (size.height desired-size) 0)))
+                       (window-name
+                        (tkwin.pathname
+                         (ToolkitWindow.TK-window
+                          (DrawingSurface.ToolkitWindow
+                           (drawing-surface to-be-managed))))))
+                  (tk-invoke-command
+                   'WM TKMainW
+                   (list "minsize" window-name tlwindow-width tlwindow-height))
+                  (tk-invoke-command
+                   'WM TKMainW
+                   (list "geometry" window-name
+                         (string-append tlwindow-width "x" tlwindow-height)))))))
+
+         |#
+
+         (on-death! to-be-managed 'APPLICATION
+                    (lambda ()
+                      (application-remove-child! application to-be-managed)))))
+    'ADDED))
+;;; More methods for Applications below
+  \f
+;;; More methods for Applications objects
+
+(define (application-remove-child! Application to-be-unmanaged)
+  ;; This is called by the generic REMOVE-CHILD! procedure.
+  (let ((entry (with-locked-list
+               (application%.%child-windows application)
+               (lambda (kids) (assq to-be-unmanaged kids)))))
+    (if (not entry)
+       'NOT-A-CHILD
+       (let ((tlwindow (cdr entry)))
+         ;; Just kill the TK Top Level window.  This will cause us to get a
+         ;; <Destroy> back from TK, which we process with
+         ;; Application-Remove-Destroyed-Child!, below.
+         (tk-invoke-command 'DESTROY
+                            (Application->TKMainWindow Application)
+                            (list (tkwin.pathname tlwindow)))
+         'REMOVED))))
+
+(define (application-remove-destroyed-child! Application to-be-unmanaged)
+  (if (not (valid-child? to-be-unmanaged))
+      (error "APPLICATION-REMOVE-DESTROYED-CHILD!: Bad UIObj" to-be-unmanaged))
+  (if (let ((OK? #T))
+       (update-locked-list! (Application%.%child-windows Application)
+                            (lambda (kids)
+                              (if (assq to-be-unmanaged kids)
+                                  (del-assq! to-be-unmanaged kids)
+                                  (begin (set! OK? #F)
+                                         kids))))
+       OK?)
+      (begin
+       (assign-drawing-surface! to-be-unmanaged 'RETRACTED)
+       (forget! Application to-be-unmanaged)
+       'REMOVED)
+      'NOT-A-CHILD))
+
+(define (make-destroy-<application>-related-objects disp registration mainwindow)
+  ;; This code should not have lexical reference to the
+  ;; Application, since it will run only after the Application
+  ;; has vanished.
+  (lambda ()
+    (destroy-registration registration)
+    (destroy-associated-tk-widgets (->xdisplay disp))
+    (destroy-all-sensitive-surfaces-from-display disp)
+    (tk-kill-application mainwindow)
+    'done))
+
+(define (application-maker application-name dsp TKmain context children code)
+  ;; Can't be nested in MAKE-APPLICATION because it would lexically
+  ;; capture the list of kids!
+  (make-application%
+   (make-UIObjInternals application-add-child!
+                       application-remove-child!
+                       UIObj-set-context!
+                       'invalid-application-1  ; UIObj-assign-screen-area!
+                       'invalid-application-2  ; UIObj-assign-drawing-surface!
+                       'invalid-application-3  ; UIObj-point-within?
+                       'invalid-application-4  ; UIObj-rectangle-overlaps?
+                       'invalid-application-5  ; UIObj-handle-event
+                       'invalid-application-6  ; UIObj-get-desired-size
+                       'invalid-application-7  ; UIObj-assigned-screen-area
+                       'invalid-application-8  ; UIObj-used-screen-area
+                       'invalid-application-9  ; UIObj-set-assigned-screen-area!
+                       'invalid-application-10 ; UIObj-set-used-screen-area!
+                       'invalid-application-11); UIObj-assign-glue!
+   children
+   code
+   application-name
+   dsp
+   TKMain
+   context))
+
+(define (make-application application-name . kids)
+  (let* ((dsp (open-display))
+        (context (create-default-context application-name dsp))
+        (me 'later)
+        (event-string (%XMake-Event)))
+    (define (service-display-connection)
+      ;; This code is run asynchronously when data arrives from
+      ;; the display connection
+      (define (process-event event)
+       (for-each
+        (lambda (kid) (handle-event kid event))
+        (with-locked-list (Application%.%child-windows me)
+                          (lambda (kids)
+                            (let loop ((rest kids)
+                                       (handled-by '()))
+                              (cond ((null? rest) (reverse handled-by))
+                                    ((event-within? (caar rest) event)
+                                     (loop (cdr rest)
+                                           (cons (caar rest) handled-by)))
+                                    (else (loop (cdr rest) handled-by))))))))
+      (let loop ((nextevent (get-x-event dsp event-string)))
+       (if nextevent
+           (begin
+             (set! EVENT-COUNTER (+ 1 EVENT-COUNTER))
+            
+             (our-with-thread-mutex-locked
+              'process-event *event-processing-mutex*
+              (lambda ()
+                (if (not (tk-completely-handles-event? nextevent))
+                    (process-event (XEvent-><Event> nextevent)))))
+             
+             (do-tk-callbacks)
+
+             (loop (get-x-event dsp event-string)))
+           'done))
+      )
+    (define (idle-work)
+                                       ; Not actually used by MIT version
+      (debug-print 'idle-work 'never called!!!!)
+      (flush-queued-output dsp)
+      (tk-doevents))
+    (let ((TKMainWindow (tk-init dsp)))
+      (set! me (application-maker application-name dsp TKMainWindow
+                                 context (make-locked-list)
+                                 service-display-connection))
+      (add-widget-list-for-display-number! (->xdisplay dsp))
+      (for-each (lambda (kid) (add-child! me kid)) kids)
+      (when-unreferenced
+       me
+       (make-destroy-<application>-related-objects
+       dsp
+       (fork-to-wait-on dsp service-display-connection idle-work)
+       TKMainWindow))
+      me))
+  )
+\f
+;;;; Interactive Geometry handlers ... low level version
+
+(define (interactor-add-child! interact to-be-managed)
+  (define (find-handler event-type handlers)
+    ;; Returns a list of all handlers for this event-type
+    (let loop ((rest handlers))
+      (cond ((null? rest) '())
+           ((eq? event-type (caar rest))
+            (cons (cadr (car rest)) (loop (cdr rest))))
+           (else (loop (cdr rest))))))
+
+  (if (not (valid-child? to-be-managed))
+      (error "INTERACTOR-ADD-CHILD!: Bad UIObj" to-be-managed))
+  (let ((sensitive-surfaces (Interactor%.sensitive-surface-map interact)))
+    (if (not (assq to-be-managed sensitive-surfaces))
+       (let* ((ss (create-sensitive-surface to-be-managed
+                                            (Interactor%.handlers interact)))
+              (entry `(,to-be-managed ,ss)))
+         (set-Interactor%.sensitive-surface-map! interact
+                                                 (cons entry sensitive-surfaces))
+         (on-event! to-be-managed interact
+                    (lambda (event)
+                      (let* ((handlers (Interactor%.handlers interact))
+                             (applicable-handlers
+                              (find-handler (event.type event) handlers)))
+                        (cond ((not (null? applicable-handlers))
+                               (for-each (lambda (handler) (handler event))
+                                         applicable-handlers))
+                              ((assq #T handlers)
+                               => (lambda (entry) ((cadr entry) event)))
+                              (else #F)))
+                      (event! interact event)))
+         (on-geometry-change! to-be-managed interact
+                              (lambda (old-screen-area new-screen-area)
+                                (if (and (not old-screen-area)
+                                         (not new-screen-area))
+                                    ;; When a drawing surface is set.
+                                    (set! ss
+                                          (change-sensitive-surface!
+                                           ss
+                                           to-be-managed))
+                                    (set-car! (cdr entry) ss))))))))
+
+(define (interactor-remove-child! interact was-managed)
+  (if (not (valid-child? was-managed))
+      (error "INTERACTOR-REMOVE-CHILD!: Bad UIObj" to-be-managed))
+  (forget! was-managed interact)
+  (let ((ss (assq was-managed (Interactor%.sensitive-surface-map interact))))
+    (if ss (destroy-sensitive-surface was-managed (cadr ss)))))
+
+;; Interactor Maker
+(define (interactor-maker alist-of-handlers)
+  (make-Interactor%
+   (make-UIObjInternals interactor-add-child!
+                       interactor-remove-child!
+                       UIObj-set-context! ; Defaults
+                       UIObj-assign-screen-area!
+                       UIObj-assign-drawing-surface!
+                       UIObj-point-within?
+                       UIObj-rectangle-overlaps?
+                       UIObj-handle-event
+                       UIObj-get-desired-size
+                       UIObj-assigned-screen-area
+                       UIObj-used-screen-area
+                       UIObj-set-assigned-screen-area!
+                       UIObj-set-used-screen-area!
+                       'invalid)
+   alist-of-handlers))
+
+(define (make-interactor objects alist-of-handlers)
+  ;; Constructor for interactors
+  (let ((me (interactor-maker alist-of-handlers)))
+    (for-each (lambda (object) (add-child! me object)) objects)
+    me)
+  )
+\f
+;;;; Higher level interactors
+
+(define (handle-exposure object receiver)
+  ;; Receiver will be called with the exposed rectangle
+  (make-interactor
+   (list object)
+   `((EXPOSURE
+      ,(lambda (event)
+        (receiver
+         (Make-UITKRectangle (Event.Offset Event)
+                             (Make-Size (Event.Width Event)
+                                        (Event.Height Event))))))))
+  'OK)
+
+(define (handle-button-grab object which-buttons receiver)
+  ;; Receiver is called with the buttons that were actually down and a
+  ;; "while-grabbed" procedure which is expected to be tail-called by
+  ;; receiver, specifying how to handle subsequent motion events and
+  ;; motion termination.
+  (make-interactor
+   (list object)
+   `((BUTTON-PRESS
+      ,(lambda (event)
+        (decode-button-event
+         (Event.OS-Event event)
+         (lambda (type serial sent? display window root
+                       subwindow time x y RootX RootY state
+                       button SameScreen?)
+           type serial sent? display window root
+           subwindow time x y RootX RootY state
+           button SameScreen?
+           (if (or (= which-buttons ANYBUTTON)
+                   (memv button which-buttons))
+               (let* ((should-be-result (list 'foo))
+                      (result
+                       (receiver event
+                                 (lambda (on-motion at-end)
+                                   (mouse-drag (drawing-surface object)
+                                               on-motion)
+                                   (at-end)
+                                   should-be-result))))
+                 (if (eq? result should-be-result)
+                     'OK
+                     (error "HANDLE-BUTTON-GRAB: Must tail call"))))))))
+     (POINTER-MOTION ,(lambda (e) e 'IGNORE))
+     (BUTTON-RELEASE ,(lambda (e) e 'IGNORE)))))
+\f
+;;;; Support code for interaction managers:
+;;;; Maps from DrawingSurface to Interactor to event masks
+
+;; The global map ds->(<interactor>->eventmasks)
+(define *all-sensitive-surfaces* '())
+
+;; A Surface-Sensitivity specifies for a given drawing surface the
+;; total event-generation mask for that surface and a list of
+;; Sensitivity data structures. The mask here is the inclusive-OR of
+;; all the masks in the Sensitivity data structures.
+
+;; A Sensitivity maps a single handler to the list of event types it
+;; is intended to handle.  For GC reasons, it only weakly holds the
+;; handler itself, since these are included in the global
+;; *all-sensitive-surfaces* list.
+
+(define find-sensitivity
+  ;; (find-sensitivity <interactor> list-of-sensitivities) =>
+  ;;  sensitivity or #F
+  ;; Or, in layman's terms, given a list of handler/description pairs
+  ;; and a specific handler, find the description of that handler.
+  (make-lookup
+   (lambda (obj) (weak-car (Sensitivity.%weak-<interactor> obj)))))
+
+(define find-ss
+  ;; (find-ss drawing-surface list-of-Surface-Sensitivity)
+  ;; returns a specific Surface-Sensitivity or #F
+  (make-lookup
+   (lambda (x) (weak-car (Surface-Sensitivity.Weak-Surface x)))))
+
+(define (record-surface-sensitivity! surface interactor mask)
+  (define (record-<interactor>-sensitivity! ss)
+    (let* ((sensitivities (surface-sensitivity.sensitivities ss))
+          (entry (find-sensitivity interactor sensitivities)))
+      (if entry
+         (set-sensitivity.masks! entry (cons mask (sensitivity.masks entry)))
+         (set-surface-sensitivity.sensitivities! ss
+           `(,(make-sensitivity (weak-cons interactor '()) (list mask))
+             ,@sensitivities))))
+    ;; Now tell the window system to set the event generation for this
+    ;; particular drawing surface
+    (reset-sensitivity! ss))
+  (let ((sensitivity-of-surface
+        (or (find-ss surface *all-sensitive-surfaces*)
+            (let ((new-entry
+                   (make-surface-sensitivity (weak-cons surface 'ignore)
+                                             NoEventMask '())))
+              (set! *all-sensitive-surfaces*
+                    (cons new-entry *all-sensitive-surfaces*))
+              new-entry))))
+    (record-<interactor>-sensitivity! sensitivity-of-surface)))
+
+(define delete-<interactor>!
+  (let ((del-sensitivity!
+        (del-op! (lambda (obj)
+                   (weak-car (sensitivity.%weak-<interactor> obj)))))
+       (del-ss! (del-op! surface-sensitivity.sensitivities)))
+    (lambda (surface interactor)
+      (let ((ss (find-ss surface *all-sensitive-surfaces*)))
+       (if ss
+           (let ((new (del-sensitivity!
+                       interactor
+                       (surface-sensitivity.sensitivities ss))))
+             (if (null? new)
+                 (set! *all-sensitive-surfaces*
+                       (del-ss! surface *all-sensitive-surfaces*))
+                 (begin
+                   (set-surface-sensitivity.sensitivities! ss new)
+                   ;; Now tell the window system to set the event
+                   ;; generation for this particular drawing surface
+                   (reset-sensitivity! ss)))))))))
+
+;;;; Continued ...
+\f
+;;;; Support code for interactive geometry managers, continued
+
+;;; When a surface is asked to generate events, we ask the toolkit to
+;;; generate events if it is a toolkit window.  Otherwise, we ask the
+;;; window system directly.  WE DO NOT DO BOTH.
+;;;
+;;; This lets people create windows from Scheme which don't have
+;;; related toolkit windows, even though we haven't done that yet.
+
+(define (reset-sensitivity! surface-sensitivity)
+  ;; This tells the window system to actually update the event
+  ;; generation mask for a given drawing surface.
+  ;; NOTE: Whoever calls this is responsible for guaranteeing that the
+  ;;       surface (which is weakly held) still exists.
+  (let ((original (surface-sensitivity.mask surface-sensitivity)))
+    (let loop ((s 0)
+              (rest (surface-sensitivity.sensitivities
+                     surface-sensitivity)))
+      (if (null? rest)
+         (begin
+           (set-surface-sensitivity.mask! surface-sensitivity s)
+           (if (not (= s original))
+               (let ((Surface
+                      (weak-car
+                       (surface-sensitivity.Weak-Surface
+                        surface-sensitivity))))
+                 (if Surface
+                     (let ((TKWindow (DrawingSurface.ToolKitWindow Surface))
+                           (UITKWindow (DrawingSurface.UITKWindow Surface)))
+                       (if TKWindow
+                           (tk-generate-Scheme-event
+                            s
+                            (ToolKitWindow.TK-Window TKWindow))
+                           (Generate-Events! UITKWindow s)))))))
+         (loop (apply bit-or s (sensitivity.masks (car rest)))
+               (cdr rest))))))
+
+(define (create-sensitive-surface UIObject handlers)
+  ;; Given an object, return the Sensitive-Surface that will generate
+  ;; these events.
+  (let ((surface (Drawing-Surface UIObject)))
+    (if (DrawingSurface? surface)
+       (begin
+         (record-surface-sensitivity! surface UIObject
+           (if (null? handlers)
+               0
+               (apply bit-or (map handler->sensitivity handlers))))
+         (make-sensitive-surface surface handlers))
+       (make-sensitive-surface #F handlers))))
+
+(define (change-sensitive-surface! sensitive-surface UIObject)
+  ;; If the drawing surface for an object changes, remove the old
+  ;; record of handlers for that object (recorded on the old drawing
+  ;; surface) and enter a new record on the current drawing surface.
+  (let ((surface (Drawing-Surface UIObject))
+       (old-surface
+        (sensitive-surface.DrawingSurface sensitive-surface)))
+    (if (eq? surface old-surface)
+       sensitive-surface
+       (begin
+         (if (DrawingSurface? old-surface)
+             (destroy-sensitive-surface UIObject sensitive-surface))
+         (create-sensitive-surface
+          UIObject (sensitive-surface.handlers sensitive-surface))))))
+
+(define (destroy-sensitive-surface interactor sensitive-surface)
+  (let ((surface
+        (sensitive-surface.DrawingSurface sensitive-surface)))
+    (delete-<interactor>! surface interactor)))
+
+(define (destroy-all-sensitive-surfaces-from-display display)
+  (set! *all-sensitive-surfaces*
+       ((list-deletor!
+         (lambda (surface-sensitivity)
+           (let ((surface
+                  (weak-car (surface-sensitivity.Weak-Surface
+                             surface-sensitivity))))
+             (or (not surface)
+                 (eq? display
+                      (Application->display
+                       (ToolKitWindow.Application
+                        (drawingsurface.ToolKitWindow surface))))))))
+        *all-sensitive-surfaces*)))
+\f
+;;;; Support for simplified user interface building.  We provide a
+;;;; default application, and a procedure for adding new children to
+;;;; it.
+
+(define *the-default-application*
+  (make-application "SWAT"))
+
+;;; (Swat-Open obj1 ['-title "title1"] obj2 ['-title "title2"] ...)
+;;; adds obj1, obj2, ... to the default application with the window
+;;; titled by the string specified with the -title option.
+;;; If no title option is specified, the window title will be the
+;;; title of the application
+
+(define (swat-open . objects-and-title-options)
+  (apply swat-open-in-application
+        *the-default-application*
+        objects-and-title-options))
+
+;;; (SWAT-OPEN-IN-APPLICATION app obj1 ['-title "title1"] obj2 ['-title "title2"] ...)
+;;; is like swat-open, except for the speficifed application.
+
+(define (swat-open-in-application app . objects-and-title-options)
+  (let loop ((more-to-show objects-and-title-options))
+    (if (null? more-to-show)
+       'OK
+       (let ((next-obj (car more-to-show))
+             (after-next (if (null? (cdr more-to-show))
+                             #F
+                             (cadr more-to-show))))
+         ;;look for -title following the object to show
+         (if (eq? after-next '-title)
+             (let ((specified-title
+                    (if (null? (cddr more-to-show))
+                        (error
+                         "-title option given and no title specified -- SWAT-OPEN"
+                         objects-and-title-options)
+                        (caddr more-to-show))))
+               ;;if -title is there, next thing must be a string
+               (if (string? specified-title)
+                   (add-child! app
+                               next-obj
+                               specified-title)
+                   (error "specified title is not a string -- SWAT-OPEN"
+                          specified-title))
+               (loop (cdddr more-to-show)))
+             ;;no -title specified -- use default naming
+             (begin (add-child! app next-obj)
+                    (loop (cdr more-to-show))))))))
+
+(define (swat-close . objs)
+  (for-each (lambda (obj) (remove-child! *the-default-application* obj))
+           objs)
+  'closed)
\ No newline at end of file
diff --git a/v7/src/swat/scheme/canvas.scm b/v7/src/swat/scheme/canvas.scm
new file mode 100644 (file)
index 0000000..5d7c2c6
--- /dev/null
@@ -0,0 +1,281 @@
+;;; -*- Scheme -*-
+
+;;; Canvases can be scrollable: we can create them with two scrollbars,
+;;; one on the right and one on the bottom.
+
+(define (make-scrollable-canvas . options)
+  (let ((canvas (apply make-canvas options))
+       (vscroll (make-scrollbar '(-orient vert)))
+       (hscroll (make-scrollbar '(-orient horiz))))
+    (let ((v-command
+          (lambda ()
+            (ask-widget
+             vscroll
+             `(configure -command
+                         ,(string-append (tk-widget->pathname canvas) " yview")))))
+         (h-command
+          (lambda ()
+            (ask-widget
+             hscroll
+             `(configure -command
+                         ,(string-append (tk-widget->pathname canvas) " xview")))))
+         (c-command
+          (lambda ()
+            (maybe-defer
+             vscroll
+             (lambda ()
+               (ask-widget
+                canvas
+                `(configure
+                   -xscroll
+                  ,(string-append (tk-widget->pathname hscroll) " set")
+                   -yscroll
+                  ,(string-append (tk-widget->pathname vscroll) " set"))))))))
+      (defer canvas v-command)
+      (defer canvas h-command)
+      (defer hscroll c-command)
+      (make-vbox (make-hbox canvas vscroll) hscroll))))
+
+(define (scrollable-canvas-canvas scrollable-canvas)
+  (let ((top-row (car (box-children scrollable-canvas))))
+    (car (box-children top-row))))
+
+(define (scrollable-canvas-vscroll scrollable-canvas)
+  (let ((top-row (car (box-children scrollable-canvas))))
+    (cadr (box-children top-row))))
+
+(define (scrollable-canvas-hscroll scrollable-canvas)
+  (cadr (box-children scrollable-canvas)))
+
+
+;;; Canvas has special protect-from-gc! procedures
+
+(define (canvas-protect-from-gc! canvas stuff)
+  (let ((crud (crud-that-I-dont-want-to-gc-away canvas)))
+    (set-cdr! crud (cons stuff (cdr crud))))
+  'done)
+
+(define (canvas-unprotect-from-gc! canvas stuff)
+  (let ((crud (crud-that-I-dont-want-to-gc-away canvas)))  
+    (set-cdr! crud (delq! stuff (cdr crud))))
+  'done)  
+
+(define (canvas-flush-protect-list! canvas)
+  (let ((crud (crud-that-I-dont-want-to-gc-away canvas)))  
+    (set-cdr! crud '()))
+  'done)  
+
+
+;;; CanvasItem structure
+
+(define (make-canvas-item name canvas)
+  (if (not (TKWidget%.handle canvas))
+      (error "You must OPEN the canvas before you can make an item on it"))
+  (let ((item (make-canvasitem canvasitem-ask-widget
+                              canvasitem-add-event-handler!
+                              'invalid
+                              name
+                              canvas
+                              '())))
+    (canvas-protect-from-gc! canvas item)
+    item))
+
+(define (canvasitem-add-event-handler! item event handler substitutions)
+  (let ((canvas (CanvasItem.canvas item))
+       (handler (proc-with-transformed-args handler substitutions)))
+    (set-canvasitem.%binding-callbacks!
+     item
+     (cons handler (canvasitem.%binding-callbacks item)))
+    (ask-widget canvas
+               `(bind
+                 ,(CanvasItem.name item)
+                 ,event
+                 ("SchemeCallBack" ,(hash handler *our-hash-table*)
+                                   ,@substitutions)))))
+
+;;; The following assumes that the commands which explicitly mention
+;;; canvas items mention them only as their second argument. This is
+;;; true for most of the commands (e.g., itemconfigure, move, raise);
+;;; but select, for example, is an exception. Do we care about those,
+;;; anyway?  Same is true for the <CanvasItemGroup> version.
+
+(define (canvasitem-ask-widget me arg-list)
+  (let* ((name   (CanvasItem.name  me))
+        (canvas (CanvasItem.canvas me))
+        (command (car arg-list))
+        (new-arg-list (cons (if (eq? command 'configure)
+                                'itemconfigure
+                                command)
+                            (cons name (cdr arg-list)))))
+    (let ((result (ask-widget canvas new-arg-list)))
+      (if (eq? command 'delete)
+         (canvas-unprotect-from-gc! canvas me))
+      result)))
+
+
+;;; CanvasItemGroup structure, for grouping (tagging) canvas items together.
+
+(define (make-canvas-item-group canvas list-of-canvas-items)
+  (let ((tag (tk-gen-name "CanvasItemGroup")))
+    (for-each (lambda (item)
+               (if (eq? canvas (CanvasItem.canvas item))
+                   (ask-widget item `(configure -tags ,tag))
+                   (error "MAKE-CANVAS-ITEM-GROUP: not a canvas item on canvas"
+                          canvas item)))
+             list-of-canvas-items)
+    (let ((CanvasItemGroup (make-CanvasItemGroup CanvasItemGroup-ask-widget
+                                                CanvasItemGroup-add-event-handler!
+                                                'invalid
+                                                tag
+                                                canvas
+                                                '())))
+      (canvas-protect-from-gc! canvas CanvasItemGroup)
+      CanvasItemGroup)))
+
+
+(define (add-to-canvas-item-group tag new-item)
+  (if (eq? (CanvasItem.canvas new-item)
+          (CanvasItemGroup.canvas tag))
+      (ask-widget new-item `(configure -tags ,(CanvasItemGroup.tag tag)))
+      (error "ADD-TO-CANVAS-ITEM-GROUP: not a canvas item on canvas"
+            canvas new-item)))
+
+(define (merge-canvas-item-groups canvas destructive? . tags)
+  (let ((new-tag (tk-gen-name "CanvasItemGroup")))
+    (for-each
+     (lambda (tag)
+       (cond ((eq? (CanvasItemGroup.canvas tag) canvas)
+             (let ((tk-tag (CanvasItemGroup.tag tag)))
+               (ask-widget canvas `(addtag ,new-tag withtag ,tk-tag))
+               ;; If destructive? is true, the old tags are
+               ;; destroyed. Otherwise, they are kept. The old tags
+               ;; take precedence in case of conflicting event handlers. 
+               (if destructive?
+                   (begin
+                     (ask-widget canvas `(dtag ,tk-tag))
+                     (canvas-unprotect-from-gc! canvas tag)))))
+            (else
+             (error "MERGE-CANVAS-ITEM-GROUPS: not a canvas tag on canvas"
+                    canvas tag))))
+     tags)
+    (let ((CanvasItemGroup (make-CanvasItemGroup CanvasItemGroup-ask-widget
+                                    CanvasItemGroup-add-event-handler!
+                                    'invalid
+                                    new-tag
+                                    canvas
+                                    '())))
+      (canvas-protect-from-gc! canvas CanvasItemGroup)
+      CanvasItemGroup)))
+
+(define (CanvasItemGroup-add-event-handler! tag event handler substitutions)
+  ;; to handle tagged canvas items
+  (let ((canvas (CanvasItemGroup.canvas tag))
+       (handler (proc-with-transformed-args handler substitutions)))
+    (set-CanvasItemGroup.%binding-callbacks!
+     tag
+     (cons handler (CanvasItemGroup.%binding-callbacks tag)))
+    (ask-widget canvas
+               `(bind
+                 ,(CanvasItemGroup.tag tag)
+                 ,event
+                 ("SchemeCallBack" ,(hash handler *our-hash-table*)
+                                   ,@substitutions)))))
+
+(define (CanvasItemGroup-ask-widget tag arg-list)
+  ;; to handle tagged canvas items
+  (let* ((tag-name (CanvasItemGroup.tag    tag))
+        (canvas   (CanvasItemGroup.canvas tag))
+        (command  (car arg-list))
+        (new-arg-list (cons (if (eq? command 'configure)
+                                'itemconfigure
+                                command)
+                            (cons tag-name (cdr arg-list)))))
+    (let ((result (ask-widget canvas new-arg-list)))
+      (if (eq? command 'delete)
+         (canvas-unprotect-from-gc! canvas tag))
+      result)))
+
+
+;;; This is how the user creates canvas items, e.g.
+;;; (define george (make-arc-on-canvas c 200 200 250 250))
+
+(define (make-arc-on-canvas canvas x1 y1 x2 y2 . options)
+  (let ((configure-options (if (null? options) '() (car options))))
+    (make-canvas-item
+     (ask-widget canvas `(create arc ,x1 ,y1 ,x2 ,y2 ,@configure-options))
+     canvas)))
+
+(define (make-bitmap-on-canvas canvas bitmap-filename-string x y . options)
+  (if (not (file-exists? bitmap-filename-string))
+      (error "MAKE-BITMAP-ON-CANVAS: Bad file name" bitmap-filename-string))
+  (let ((configure-options (if (null? options) '() (car options))))
+    (make-canvas-item
+     (ask-widget canvas
+                `(create bitmap ,x ,y
+                         -bitmap ,(string-append "@" bitmap-filename-string)
+                         ,@configure-options))
+     canvas)))
+    
+(define (make-line-on-canvas canvas x1 y1 x2 y2 . opt-args)
+  (let loop ((opt-args opt-args) (xy-list '()) (configure-options '()))
+    (if (null? opt-args)
+       (if (odd? (length xy-list))
+           (error "MAKE-LINE:  Missing a y coordinate"
+                  (append (list x1 y1 x2 y2) xy-list))
+           (make-canvas-item
+            (ask-widget canvas `(create line ,x1 ,y1 ,x2 ,y2 ,@xy-list
+                                        ,@configure-options))
+            canvas))
+       (let ((next-arg (car opt-args)))
+         (if (list? next-arg)
+             (loop (cdr opt-args) xy-list next-arg)
+             (loop (cdr opt-args)
+                   (append xy-list (list next-arg))
+                   configure-options))))))
+
+(define (make-oval-on-canvas canvas x1 y1 x2 y2 . options)
+  (let ((configure-options (if (null? options) '() (car options))))
+    (make-canvas-item
+     (ask-widget canvas `(create oval ,x1 ,y1 ,x2 ,y2 ,@configure-options))
+     canvas)))
+
+(define (make-polygon-on-canvas canvas x1 y1 x2 y2 x3 y3 . opt-args)
+  (let loop ((opt-args opt-args) (xy-list '()) (configure-options '()))
+    (if (null? opt-args)
+       (if (odd? (length xy-list))
+           (error "MAKE-POLYGON:  Missing a y coordinate"
+                  (append (list x1 y1 x2 y2 x3 y3) xy-list))
+           (make-canvas-item
+            (ask-widget canvas `(create polygon ,x1 ,y1 ,x2 ,y2 ,x3 ,y3
+                                        ,@xy-list ,@configure-options))
+            canvas))
+       (let ((next-arg (car opt-args)))
+         (if (list? next-arg)
+             (loop (cdr opt-args) xy-list next-arg)
+             (loop (cdr opt-args)
+                   (append xy-list (list next-arg))
+                   configure-options))))))
+
+(define (make-rectangle-on-canvas canvas x1 y1 x2 y2 . options)
+  (let ((configure-options (if (null? options) '() (car options))))
+    (make-canvas-item
+     (ask-widget canvas `(create rectangle ,x1 ,y1 ,x2 ,y2 ,@configure-options))
+     canvas)))
+
+(define (make-text-on-canvas canvas x y . options)
+  (let ((configure-options (if (null? options) '() (car options))))
+    (make-canvas-item
+     (ask-widget canvas `(create text ,x ,y ,@configure-options))
+     canvas)))
+
+(define (make-widget-on-canvas canvas widget x y . options)
+  (let ((configure-options (if (null? options) '() (car options))))
+    (add-child! canvas widget)
+    (make-canvas-item
+     (ask-widget
+      canvas
+      `(create window ,x ,y
+              -window ,(lambda () (tk-widget->pathname widget))
+              ,@configure-options))
+     canvas)))
+
diff --git a/v7/src/swat/scheme/control-floating-errors.scm b/v7/src/swat/scheme/control-floating-errors.scm
new file mode 100644 (file)
index 0000000..a4cdc4b
--- /dev/null
@@ -0,0 +1,74 @@
+;;; -*-Scheme-*-
+
+#|
+       (set-floating-error-mask! <fixnum>)
+
+       sets the floating-point enables to the bottom 5 bits of fixnum.
+       returns a fixnum with the old floating-point enables in the bottom 5 bits.
+
+       Warning: This does not check the argument type.
+
+       Flags:  V       valid operation         16
+               Z       zero divide              8
+               O       overflow                 4
+               U       underflow                2
+               I       inexact                  1
+
+       This version is long because it compiles under both 7.4 and 8.0
+|#
+
+(declare (usual-integrations))
+
+(define-macro (deflap name . lap)
+  `(define ,name
+     (scode-eval
+      ',((access lap->code (->environment '(compiler top-level)))
+        name
+        lap)
+      system-global-environment)))
+
+(define set-floating-error-mask!
+  (let ()
+    (deflap set-floating-error-mask/8.0!
+      (entry-point set-floating-error-mask/8.0!)
+      (scheme-object CONSTANT-0 #F)
+      (scheme-object CONSTANT-1 0)
+      (external-label () #x202 (@pcr set-floating-error-mask/8.0!))
+
+      (LABEL set-floating-error-mask/8.0!)
+                                       ; arg = 2, cont = 19
+      (fstws () 0 (offset 0 0 21))     ; flags to free
+      (ldw () (offset 0 0 21) 6)       ; flags to reg 6
+      (copy () 6 7)                    ; copy flags to 7
+      (dep () 2 31 5 7)                        ; arg merged with flags in 7
+      (stw () 7 (offset 0 0 21))       ; new flags to free
+      (dep () 6 31 5 2)                        ; flags merged with arg in 2
+      (fldws () (offset 0 0 21) 0)     ; store flags
+      (bv (n) 0 19)                    ; return
+      )
+
+    (deflap set-floating-error-mask/7.4!
+      (entry-point set-floating-error-mask/7.4!)
+      (scheme-object CONSTANT-0 #F)
+      (scheme-object CONSTANT-1 0)
+      (external-label () #x202 (@pcr set-floating-error-mask/7.4!))
+
+      (LABEL set-floating-error-mask/7.4!)
+
+      (fstws () 0 (offset 0 0 21))     ; flags to free
+      (ldw () (offset 0 0 #x16) 2)     ; arg to reg 2
+      (ldw () (offset 0 0 21) 6)       ; flags to reg 6
+      (copy () 6 7)                    ; copy flags to 7
+      (dep () 2 31 5 7)                        ; arg merged with flags in 7
+      (stw () 7 (offset 0 0 21))       ; new flags to free
+      (dep () 6 31 5 2)                        ; flags merged with arg in 2
+      (fldws () (offset 0 0 21) 0)     ; store flags
+      (ldo () (offset 4 0 #x16) #x16)  ; pop arg
+      (ldwm () (offset 4 0 #x16) 6)    ; pop ret add
+      (dep () 5 5 6 6)                 ; remove tag
+      (bv (n) 0 6)                     ; return
+      )
+
+    (if (object-type? 0 0)             ; untagged fixnums?
+       set-floating-error-mask/8.0!
+       set-floating-error-mask/7.4!)))
\ No newline at end of file
diff --git a/v7/src/swat/scheme/generics.scm b/v7/src/swat/scheme/generics.scm
new file mode 100644 (file)
index 0000000..ef4f2c4
--- /dev/null
@@ -0,0 +1,214 @@
+;;; -*- Scheme -*-
+
+(define-integrable (uiobjinternals uiobj)
+  (vector-ref uiobj uiobjinternals-index))  
+
+;;; Generic operations:
+;;;   ADD-CHILD!, REMOVE-CHILD!, SET-CONTEXT!, ASSIGN-SCREEN-AREA!,
+;;;   ASSIGN-DRAWING-SURFACE!, HANDLE-EVENT,
+;;;   GET-DESIRED-SIZE, GET-DESIRED-SIZE, EVENT-WITHIN?
+
+(define (add-child! object child . others)
+  (if (null? others)
+      ((UIObjInternals.Add-Child!-Procedure (uiobjinternals object))
+       object
+       child)
+      (apply 
+       (UIObjInternals.Add-Child!-Procedure (uiobjinternals object))
+       object child others)))
+
+(define (REMOVE-CHILD! Object Child)
+  ((UIObjInternals.Remove-Child!-Procedure (uiobjinternals object))
+   Object
+   child))
+
+(define (SET-CONTEXT! Object Context)
+  ((UIObjInternals.Set-Context!-Procedure (uiobjinternals object))
+   Object Context))
+
+(define (ASSIGN-SCREEN-AREA! Object Screen-area)
+  ((UIObjInternals.Assign-Screen-Area!-Procedure (uiobjinternals object))
+   Object Screen-Area))
+
+(define (weak-delq! item items)
+  ;; Cleans out #F entries in the list as it goes
+  (let loop ((previous #F)
+            (items* items))
+    (cond ((weak-pair? items*)
+          (if (or (null? (weak-car items*))
+                  (eq? (weak-car items*) item))
+              (begin
+                (if previous
+                    (weak-set-cdr! previous (weak-cdr items*))
+                    (set! items (weak-cdr items*)))
+                (loop previous (weak-cdr items*)))
+              (loop items* (weak-cdr items*))))
+         ((null? items*) items)
+         (else
+          (error:wrong-type-argument items "weak pair" 'weak-delq!)))))
+
+(define (ASSIGN-DRAWING-SURFACE! Object Surface)
+  (let ((old (drawing-surface object)))
+    ((UIObjInternals.Assign-Drawing-Surface!-Procedure (uiobjinternals object))
+     Object Surface)
+    (if (eq? Surface 'RETRACTED)
+       (begin
+         (set-assigned-screen-area! Object #F)
+         (set-used-screen-area! Object #F)))
+    (if (not (eq? old Surface))
+       (begin
+         (if (DrawingSurface? old)
+             (set-DrawingSurface.Weak-List-of-Widgets!
+              old
+              (weak-delq! object (DrawingSurface.Weak-List-of-Widgets old))))
+         (if (DrawingSurface? Surface)
+             (set-DrawingSurface.Weak-List-of-Widgets!
+              Surface (weak-cons object
+                                 (DrawingSurface.Weak-List-of-Widgets
+                                  Surface))))))
+    'OK))
+
+(define (POINT-WITHIN? Object Point)
+  ((UIObjInternals.Point-Within?-Procedure (uiobjinternals object))
+   Object Point))
+
+(define (RECTANGLE-OVERLAPS? Object Point Width Height)
+  ((UIObjInternals.Rectangle-Overlaps?-Procedure (uiobjinternals object))
+   Object Point Width Height))
+
+(define (HANDLE-EVENT Object Event)
+  ((UIObjInternals.Handle-Event-Procedure (uiobjinternals object))
+   Object Event))
+
+(define (GET-DESIRED-SIZE Object)
+  ((UIObjInternals.Get-Desired-Size-Procedure (uiobjinternals object))
+   Object))
+
+(define (ASSIGNED-SCREEN-AREA Object)
+  ((UIObjInternals.ASSIGNED-SCREEN-AREA-Procedure (uiobjinternals object))
+   Object))
+
+(define (USED-SCREEN-AREA Object)
+  ((UIObjInternals.Used-SCREEN-AREA-Procedure (uiobjinternals object))
+   Object))
+
+(define (SET-ASSIGNED-SCREEN-AREA! Object Screen-area)
+  ((UIObjInternals.Set-ASSIGNED-SCREEN-AREA!-Procedure (uiobjinternals object))
+   Object Screen-area))
+
+(define (SET-USED-SCREEN-AREA! Object Screen-area)
+  ((UIObjInternals.Set-Used-SCREEN-AREA!-Procedure (uiobjinternals object))
+   Object Screen-Area))
+
+(define (ASSIGN-GLUE! Object)
+  ((UIObjInternals.Assign-Glue!-Procedure (uiobjinternals object))
+   Object))
+
+
+(define (%geometry-alerts UIObj)
+  (UIObjInternals.%geometry-alerts (UIObjInternals UIObj)))
+
+(define (set-%geometry-alerts! UIObj new-value)
+  (set-UIObjInternals.%geometry-alerts! (UIObjInternals UIObj)
+                                       new-value))
+
+(define (%event-alerts UIObj)
+  (UIObjInternals.%event-alerts (UIObjInternals UIObj)))
+
+(define (set-%event-alerts! UIObj new-value)
+  (set-UIObjInternals.%event-alerts! (UIObjInternals UIObj)
+                                    new-value))
+
+(define (%context-alerts UIObj)
+  (UIObjInternals.%context-alerts (UIObjInternals UIObj)))
+
+(define (set-%context-alerts! UIObj new-value)
+  (set-UIObjInternals.%context-alerts! (UIObjInternals UIObj)
+                                      new-value))
+
+(define (%death-alerts UIObj)
+  (UIObjInternals.%death-alerts (UIObjInternals UIObj)))
+
+(define (set-%death-alerts! UIObj new-value)
+  (set-UIObjInternals.%death-alerts! (UIObjInternals UIObj)
+                                    new-value))
+
+(define (clip-region UIObj)
+  (UIObjInternals.clip-region (UIObjInternals UIObj)))
+
+(define (set-clip-region! UIObj new-value)
+  (set-UIObjInternals.clip-region! (UIObjInternals UIObj)
+                                  new-value))
+
+(define (drawing-surface UIObj)
+  (UIObjInternals.drawing-surface (UIObjInternals UIObj)))
+
+(define (set-drawing-surface! UIObj new-value)
+  (set-UIObjInternals.drawing-surface! (UIObjInternals UIObj)
+                                      new-value))
+
+(define (%desired-size UIObj)
+  (UIObjInternals.%desired-size (UIObjInternals UIObj)))
+
+(define (set-%desired-size! UIObj new-value)
+  (set-UIObjInternals.%desired-size! (UIObjInternals UIObj)
+                                    new-value))
+
+(define (%vglue UIObj)
+  (UIObjInternals.%vglue (UIObjInternals UIObj)))
+
+(define (set-%vglue! UIObj new-value)
+  (set-UIObjInternals.%vglue! (UIObjInternals UIObj) new-value))
+
+(define (%hglue UIObj)
+  (UIObjInternals.%hglue (UIObjInternals UIObj)))
+
+(define (set-%hglue! UIObj new-value)
+  (set-UIObjInternals.%hglue! (UIObjInternals UIObj) new-value))
+
+(define (crud-that-I-dont-want-to-gc-away UIObj)
+  (UIObjInternals.crud-that-I-dont-want-to-gc-away (UIObjInternals UIObj)))
+
+(define (set-crud-that-I-dont-want-to-gc-away! UIObj new-value)
+  (set-UIObjInternals.crud-that-I-dont-want-to-gc-away!
+   (UIObjInternals UIObj) new-value))
+
+
+;;; procedures that are generic over CanvasItem, CanvasItemGroup, MenuItem,
+;;; TextTag, and TKWidget
+
+(define (valid-non-widget? obj)
+  (or (CanvasItem? obj)
+      (CanvasItemGroup? obj)
+      (MenuItem? obj)
+      (TextTag? obj)))
+
+(define (ASK-WIDGET Object Command)
+  (cond ((TkWidget%? Object)
+        ((TKwidget%.ask-widget-procedure Object) Object Command))
+       ((valid-non-widget? Object)
+        ((vector-ref object ask-widget-procedure-index) object command))
+       (else (error "ASK-WIDGET: Not a valid Tk widget" Object))))
+
+(define (ADD-EVENT-HANDLER! Object Event-type Handler . Substitutions)
+  (cond ((TkWidget%? Object)
+        ((TKwidget%.add-event-handler!-procedure Object)
+         Object Event-type Handler substitutions))
+       ((valid-non-widget? Object)
+        ((vector-ref object add-event-handler!-procedure-index)
+         Object Event-type Handler substitutions))
+       (else (error "ADD-EVENT-HANDLER!: Can't add an event handler to" Object))))
+
+;;; set-callback! is also generic over active variables
+
+(define (SET-CALLBACK! Object Callback)
+  (cond ((TkWidget%? Object)
+        ((TKWidget%.set-callback!-procedure Object) Object Callback))
+       ((TK-variable? Object)
+        (set-active-variable-callback! Object Callback))
+       ((valid-non-widget? Object)
+        ((vector-ref object set-callback!-procedure-index) Object Callback))
+       (else (error "SET-CALLBACK!: Can't set a callback for" Object))))
+
+
+
diff --git a/v7/src/swat/scheme/geometry.scm b/v7/src/swat/scheme/geometry.scm
new file mode 100644 (file)
index 0000000..720b7c9
--- /dev/null
@@ -0,0 +1,934 @@
+;;;;; -*- Scheme -*-
+;;;;;
+;;;;; $Id: geometry.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
+;;;;; derived from geometry.sc,v 1.1 1993/02/16 14:04:09 jmiller Exp $
+
+;; The box makers - one for horizontal, one for vertical
+
+(define (make-hbox . kids)
+  (make-box h-size h-arrange h-get-hglue h-get-vglue kids))
+
+(define (make-vbox  . kids)
+  (make-box v-size v-arrange v-get-hglue v-get-vglue kids))
+
+;; user-level accessor
+(define (box-children box)
+  (cond ((box%? box)
+        (box%.kids box))
+       ((arraybox%? box)
+        (arraybox%.kids-lists box))
+       (else (error "not a box -- BOX-CHILDREN" box))))
+
+;; Vertical sizer
+
+(define (v-size kids)
+  (make-size
+   (apply max (cons 0
+                   (map (lambda (kid)
+                          (Size.Width (get-desired-size kid)))
+                        kids)))
+   (apply + (map (lambda (kid)
+                  (Size.Height (get-desired-size kid)))
+                kids))))
+
+;; Horizontal sizer
+
+(define (h-size kids)
+  (make-size
+   (apply + (map (lambda (kid)
+                    (Size.Width (get-desired-size kid)))
+                kids))
+   (apply max (cons 0
+                   (map (lambda (kid)
+                          (Size.Height (get-desired-size kid)))
+                        kids)))))
+
+;; Vertical arranger
+
+(define (v-arrange kids my-screen-area)
+  (let* ((my-height (UITKRectangle.Height my-screen-area))
+        (full-width (UITKRectangle.Width my-screen-area))
+        (my-offset (UITKRectangle.Offset my-screen-area))
+        (Y (point.Y my-offset))
+        (vglues (map %vglue kids)))
+    (conquer-space
+     my-height
+     vglues
+     (lambda (positions-vector)
+       (let loop ((n 0) (rest kids))
+        (if (null? rest)
+            #F
+            (let* ((kid (car rest))
+                   (kid-y-offset (vector-ref positions-vector n))
+                   (height (- (vector-ref positions-vector (+ n 1)) 
+                              kid-y-offset))
+                   (desired-size (get-desired-size kid))
+                   (desired-width (Size.Width Desired-Size))
+                   (hglue (%hglue kid))
+                   (width (cond ((or (fil-glue? hglue)
+                                     (fill-glue? hglue))
+                                 full-width)
+                                ((rigid-glue? hglue) desired-width)
+                                ;;((percent-glue? hglue)
+                                ;;(max desired-width
+                                ;;(inexact->exact
+                                ;;(ceiling (* .01 (glue.value hglue) height)))))
+                                (else (error "Unknown glue class"
+                                             (glue.class hglue)))))
+                   (X (+ (Point.X my-offset)
+                         (ceiling
+                          (/ (- (UITKRectangle.Width my-screen-area) width)
+                             2)))))
+              (assign-screen-area!
+               kid
+               (make-UITKRectangle (make-point X (+ Y kid-y-offset))
+                                   (make-size width height)))
+              (loop (+ n 1) (cdr rest)))))))))
+
+
+;; Horizontal arranger
+
+(define (h-arrange kids my-screen-area)
+  (let* ((my-width (UITKRectangle.Width my-screen-area))
+        (full-height (UITKRectangle.Height my-screen-area))
+        (my-offset (UITKRectangle.Offset my-screen-area))
+        (X (point.X my-offset))
+        (hglues (map %hglue kids)))
+    (conquer-space
+     my-width
+     hglues
+     (lambda (positions-vector)
+       (let loop ((n 0) (rest kids))
+        (if (null? rest)
+            #F
+            (let* ((kid (car rest))
+                   (kid-x-offset (vector-ref positions-vector n))
+                   (width (- (vector-ref positions-vector (+ n 1)) 
+                             kid-x-offset))
+                   (desired-size (get-desired-size kid))
+                   (desired-height (Size.Height Desired-Size))
+                   (vglue (%vglue kid))
+                   (height (cond ((or (fil-glue? vglue)
+                                      (fill-glue? vglue))
+                                  full-height)
+                                 ((rigid-glue? vglue) desired-height)
+                                 ;;((percent-glue? vglue)
+                                 ;;(max desired-height 
+                                 ;;(inexact->exact
+                                 ;;(ceiling (* .01 (glue.value vglue) width)))))
+                                 (else (error "Unknown glue class"
+                                              (glue.class vglue)))))
+                   (Y (+ (Point.Y my-offset)
+                         (ceiling
+                          (/ (- (UITKRectangle.Height my-screen-area) height)
+                             2)))))
+              (assign-screen-area!
+               kid
+               (make-UITKRectangle (make-point (+ X kid-x-offset) Y)
+                                   (make-size width height)))
+              (loop (+ n 1) (cdr rest)))))))))
+
+
+;;; Calculate hglue and vglue for hboxes...
+
+(define (h-get-hglue kids)
+  (series-compose-glues (map %hglue kids)))
+
+(define (h-get-vglue kids)
+  (parallel-compose-glues (map %vglue kids)))
+
+;;; ... and vboxes.
+
+(define (v-get-hglue kids)
+  (parallel-compose-glues (map %hglue kids)))
+
+(define (v-get-vglue kids)
+  (series-compose-glues (map %vglue kids)))
+
+
+;; Generic arranger
+
+(define (retract-area objects)
+  (for-each (lambda (obj) (assign-screen-area! obj #F))
+           objects))
+
+(define (box-add-child! me kid)
+  (if (not (valid-child? kid))
+      (error "BOX-ADD-CHILD!: Bad UIObj" kid))
+  (one-parent-only! kid me)
+  (set-Box%.kids! me (append (Box%.kids me) (list kid)))
+  (on-geometry-change!
+   kid 'BOX
+   (lambda (old-screen-area new-screen-area)
+     old-screen-area                   ; Not used
+     (if (eq? new-screen-area #T)      ; Instigated by child, not manager
+        (box:rearrange me))))
+  (on-death! kid 'BOX (lambda () (box-remove-child! me kid)))
+  (assign-drawing-surface! kid (drawing-surface me))
+  (box:rearrange me))
+
+(define (box-remove-child! me kid)
+  (if (not (valid-child? kid))
+      (error "BOX-REMOVE-CHILD!: Bad UIObj" kid))
+  (set-Box%.kids! me (delq! kid (Box%.kids me)))
+  (forget! kid 'BOX)
+  (assign-drawing-surface! kid 'RETRACTED)
+  (box:rearrange me))
+
+(define (box-assign-drawing-surface! me surface)
+  (check-drawing-surface! me surface)
+  (for-each (lambda (kid)
+             (if (eq? surface 'RETRACTED)
+                 (forget! kid 'BOX))
+             (assign-drawing-surface! kid surface))
+           (Box%.kids me))
+  (if (DrawingSurface? surface)
+      (set-%desired-size! me ((Box%.sizer me) (Box%.kids me))))
+  (if (eq? Surface 'RETRACTED)
+      (death! me)
+      (geometry-change! me #F #F))
+  'OK)
+
+(define (box-assign-screen-area! me screen-area)
+  (cond ((vector? screen-area)
+        (set-assigned-screen-area! me screen-area)
+        (let ((old (used-screen-area me)))
+          (if (not (screen-area= old screen-area))
+              (begin
+                (set-used-screen-area! me screen-area)
+                (box:rearrange me)
+                (geometry-change! me old screen-area))))
+        screen-area)
+       ((not screen-area)
+        (set-assigned-screen-area! me screen-area)
+        (let ((old (used-screen-area me)))
+          (if (not (screen-area= old screen-area))
+              (begin
+                (set-used-screen-area! me screen-area)
+                (retract-area (Box%.kids me))
+                (geometry-change! me old screen-area))))
+        screen-area)
+       (else
+        (error "BOX-ASSIGN-SCREEN-AREA!: Bad screen-area" screen-area))))
+
+(define (box-assign-glue! me)
+  (let ((kids (Box%.kids me)))
+    (for-each assign-glue! kids)
+    (set-%hglue! me ((Box%.get-hglue me) kids)) 
+    (set-%vglue! me ((Box%.get-vglue me) kids))))
+
+;; Box Maker
+(define (box-maker size-proc screen-area-proc get-hglue get-vglue)
+  (make-Box%
+   (make-UIObjInternals box-add-child!
+                       'invalid
+                       UIObj-set-context!
+                       box-assign-screen-area!
+                       box-assign-drawing-surface!
+                       UIObj-point-within?
+                       UIObj-rectangle-overlaps?
+                       UIObj-handle-event
+                       UIObj-get-desired-size
+                       UIObj-assigned-screen-area
+                       UIObj-used-screen-area
+                       UIObj-set-assigned-screen-area!
+                       UIObj-set-used-screen-area!
+                       box-assign-glue!)
+   size-proc
+   screen-area-proc
+   get-hglue
+   get-vglue))
+
+(define (box:rearrange me)
+  (let ((screen-area (used-screen-area me))
+       (arrange (Box%.arranger me))
+       (size (Box%.sizer me))
+       (kids (Box%.kids me)))
+    (if screen-area
+       (let ((new-size (size kids)))
+         (set-%desired-size! me new-size)
+         (if (size= new-size (UITKRectangle.Size screen-area))
+             (begin (assign-glue! me)
+                    (arrange kids screen-area))
+             (begin
+               (set-%desired-size! me new-size)
+               (geometry-change! me screen-area #T)
+               (if (eq? screen-area (used-screen-area me))
+                   (begin (assign-glue! me)
+                          (arrange kids screen-area)))))))))
+                   
+(define (box:event-propagator box)
+  (lambda (event)
+    (for-each (lambda (kid)
+               (if (event-within? kid event)
+                   (handle-event kid event)))
+             (Box%.kids box))))
+  
+
+(define (make-box size-proc screen-area-proc get-hglue get-vglue children)
+  (let ((me (box-maker size-proc screen-area-proc get-hglue get-vglue)))
+    (on-event! me 'BOX
+              (box:event-propagator me))
+    (for-each (lambda (kid) (add-child! me kid)) children)
+    me))
+
+;;; Glue Mechanism snarfed from Halstead
+
+;;; Glue abstraction, captures a minimum size (horizontal or vertical,
+;;; depending on usage) below which the object really ought not to shrink.
+;;; Also specifies a stretchability value (glue-value) and a stretchability
+;;; class (glue-class).  Space is divided between two series-composed
+;;; glues as follows:
+;;;
+;;; 1. If the total is less than the sum of the glues' minimum sizes
+;;;    then divide the space in proportion to the minimum sizes (everybody
+;;;    has to give up the same percentage of their minimum size).
+;;;
+;;; 2. Else, if both glues have the same glue-class, then divide the excess
+;;;    of available space (over the sum of their minimum sizes)
+;;;    in proportion to their glue-values.
+;;;
+;;; 3. If the glue-classes differ, then the glue with the smaller glue-class
+;;;    gets its minimum size, and the glue with the larger glue-class gets
+;;;    all the rest (thus glue of a given glue-class is "infinitely" more
+;;;    stretchable than any glue from a lower glue-class -- this is useful
+;;;    for filling out to a boundary without stretching the item before the
+;;;    fill).
+
+;;; Conventional glue classes:
+
+(define *rigid-glue-class* -1) ; for things that really don't want to stretch
+(define *percent-glue-class* 0)        ; for proportionally allocating space
+(define *fill-glue-class* 1)   ; for things intended to be infinitely stretchable
+(define *fil-glue-class* 2)    ; even stretchier!
+
+(define (make-rigid-glue minsize value)
+  (make-glue minsize *rigid-glue-class* value))
+
+(define (make-percent-glue minsize percent)
+  (make-glue minsize *percent-glue-class* percent))
+
+(define (make-fill-glue minsize value)
+  (make-glue minsize *fill-glue-class* value))
+
+(define (make-fil-glue minsize value)
+  (make-glue minsize *fil-glue-class* value))
+
+(define (rigid-glue? glue)
+  (= (glue.class glue) *rigid-glue-class*))
+
+(define (percent-glue? glue)
+  (= (glue.class glue) *percent-glue-class*))
+
+(define (fill-glue? glue)
+  (= (glue.class glue) *fill-glue-class*))
+
+(define (fil-glue? glue)
+  (= (glue.class glue) *fil-glue-class*))
+
+(define *fil-glue* (make-fil-glue 0 1))
+(define *rigid-glue* (make-rigid-glue 0 1))
+   
+
+;;; Compose two glues laid end-to-end -- sum their minimum sizes
+;;;   and their glue values (which implies that if the glue-classes
+;;;   differ, then the resulting glue-class and glue-value are those
+;;;   of the input glue with the larger glue-class).
+
+(define (series-compose-glue g1 g2)
+  (let ((c1 (glue.class g1))
+       (c2 (glue.class g2)))
+    (if (< c2 c1)
+       (series-compose-glue g2 g1)
+       (make-glue (+ (glue.minsize g1) (glue.minsize g2))
+                  c2
+                  (if (= c1 c2)
+                      (+ (glue.value g1) (glue.value g2))
+                      (glue.value g2))))))
+
+;;; Compose two glues laid in parallel -- use the max of their
+;;;   minimum sizes and the min of their stretchabilities (which
+;;;   implies using the stretchability of the glue with the smaller
+;;;   glue-class, or the smaller glue-value if the glue-classes are
+;;;   equal).
+
+(define (parallel-compose-glue g1 g2)
+  (let ((c1 (glue.class g1))
+       (c2 (glue.class g2)))
+    (if (< c2 c1)
+       (parallel-compose-glue g2 g1)
+       (make-glue (max (glue.minsize g1) (glue.minsize g2))
+                  c1
+                  (if (= c1 c2)
+                      (min (glue.value g1) (glue.value g2))
+                      (glue.value g1))))))
+
+;;; Support > 2 glues as arguments
+
+(define (compose-glues fcn list-of-glues)
+  ;; If there's no glue at all, make it be fil glue.
+  (if (null? list-of-glues)
+      *fil-glue*
+      (let loop ((cumulative-glue (car list-of-glues))
+                (rest (cdr list-of-glues)))
+       (if (null? rest)
+           cumulative-glue
+           (let ((next-glue (car rest)))
+             (loop (fcn cumulative-glue next-glue)
+                   (cdr rest)))))))
+
+(define (series-compose-glues list-of-glues)
+  (compose-glues series-compose-glue list-of-glues))
+
+(define (parallel-compose-glues list-of-glues)
+  (compose-glues parallel-compose-glue list-of-glues))
+
+
+;;; Choose the less restrictive (in terms of minimum size) of two
+;;;   glues.  This procedure is used for implementing the "orbox" combiner:
+
+(define (choose-minimum-glue list-of-glues)
+  (define (min-glue g1 g2)
+    (let ((min1 (glue.minsize g1))
+         (min2 (glue.minsize g2)))
+      (cond ((< min1 min2) g1)
+           ((> min1 min2) g2)
+           (else g1))))        ; arbitrary choice
+  (let ((g1 (car list-of-glues)))
+    (let loop ((list-of-glues list-of-glues) (g g1))
+      (if (null? (cdr list-of-glues))
+         (min-glue g (car list-of-glues))
+         (let* ((next-glue (car list-of-glues)))
+           (loop (cdr list-of-glues) (min-glue g next-glue)))))))
+
+(define (choose-maximum-glue list-of-glues)
+  (define (max-glue g1 g2)
+    (let ((max1 (glue.minsize g1))
+         (max2 (glue.minsize g2)))
+      (cond ((< max1 max2) g2)
+           ((> max1 max2) g1)
+           (else g1))))        ; arbitrary choice
+  (let ((g1 (car list-of-glues)))
+    (let loop ((list-of-glues list-of-glues) (g g1))
+      (if (null? list-of-glues)
+         g
+         (let* ((next-glue (car list-of-glues)))
+           (loop (cdr list-of-glues) (max-glue g next-glue)))))))
+
+#|
+;;; Magnify the minsize and stretchability of a glue by a factor:
+
+(define (magnify-glue g factor)
+  (make-glue (* factor (glue.minsize g))
+            (glue.class g)
+            (* factor (glue.value g))))
+
+;;; Decide whether the given glue fits happily into the given space:
+
+(define (glue-fits-space? g space)
+  (<= (glue.minsize g) space))
+|#
+
+;;; Divide a given amount of space between two glues, according to the
+;;;   rules given above.  Returns the amounts of space allocated to the
+;;;   two glues to the continuation k.
+
+(define (divide-space space g1 g2 k)
+  (let ((m1 (glue.minsize g1))
+       (m2 (glue.minsize g2)))
+    (let ((msum (+ m1 m2)))
+      (if (and (<= space msum) (> msum 0))
+         (let ((x1 (inexact->exact
+                    (floor
+                     (quotient (+ (* 2 m1 space) msum)
+                               (* 2 msum)))))) ; round off space allocation
+           (k x1 (- space x1)))
+         (let ((c1 (glue.class g1))
+               (c2 (glue.class g2)))
+           (cond ((< c1 c2) (k m1 (- space m1)))
+                 ((> c1 c2) (k (- space m2) m2))
+                 (else (let ((v1 (glue.value g1))
+                             (v2 (glue.value g2)))
+                         (let ((vsum (+ v1 v2)))
+                           (let ((x1 (+ m1
+                                        (inexact->exact
+                                         (floor
+                                          (quotient
+                                           (+ (* 2 v1 (- space msum))
+                                              vsum)
+                                           (* 2 vsum)))))))
+                             (k x1 (- space x1))))))))))))
+
+
+;;; Given a space (width or height), a list of glues (assuming the
+;;; order of glues provided is left to right), and a receiver, divides
+;;; the space between the glues according to their properties.
+;;; Receiver is applied to the resulting vector of positions which are
+;;; offsets into the space. 
+
+(define (conquer-space space list-of-glues receiver)
+  (let* ((num-glues (length list-of-glues))
+        (glues (list->vector list-of-glues))
+        (cum-glues (compute-cumulative-glues list-of-glues))
+        (positions-vector (make-vector (+ num-glues 1))))
+    (let loop ((s space) (n (- num-glues 1)))
+      (vector-set! positions-vector (+ n 1) s)
+      (if (> n 0)
+         (divide-space
+          s (vector-ref cum-glues (- n 1)) (vector-ref glues n)
+          (lambda (s1 s2)
+            s2                         ; ignore
+            (loop s1 (- n 1))))))
+    (vector-set! positions-vector 0 0)
+    (receiver positions-vector)))
+        
+
+;;; Given a list of glues, returns a vector of cumulative glues --
+;;; glues obtained by series composition of g1, g1&g2, (g1&g2)&g3, and
+;;; so on.  For example,
+;;;
+;;;  (compute-cumulative-glues (list g1 g2 g3)) is equivalent to:
+;;; 
+;;;      (let* ((g12 (series-compose-glue g1 g2))
+;;;             (g123 (series-compose-glue g12 g3)))    
+;;;       `#(,g1 ,g12 ,g123))
+
+(define (compute-cumulative-glues list-of-glues)
+  ;; If there's no glue at all, make it be fil glue.
+  (if (null? list-of-glues)
+      *fil-glue*
+      (let* ((num-glues (length list-of-glues))
+            (cum-glues (make-vector num-glues))
+            (g1 (car list-of-glues)))
+       (vector-set! cum-glues 0 g1)
+       (let loop ((n 1) (old-glue g1) (glues (cdr list-of-glues)))
+         (if (= n num-glues)
+             cum-glues
+             (let* ((g (car glues))
+                    (new-glue (series-compose-glue old-glue g)))
+               (vector-set! cum-glues n new-glue)
+               (loop (+ n 1) new-glue (cdr glues))))))))
+
+
+;;; A space is basically a "piece of glue." It is of class fil, so it
+;;; is very stretchable (more so than anything else). It can be used
+;;; to fill in spaces between widgets in a box.
+;;; This would probably be better off if implemented as a shape
+;;; instead of a canvas, but for now (till shapes are working
+;;; right)... 
+
+(define (make-space . options)
+  (let* ((configure-options (if options (car options) '()))
+        (space (make-canvas `(-width 0 -height 0 ,@configure-options))))
+    (set-%hglue! space *fil-glue*)
+    (set-%vglue! space *fil-glue*)
+    space))
+
+
+
+;;; Build a tabular array of boxes.  Each argument is a list of kids that
+;;;   are to be arranged left-to-right, in hbox fashion.  These rows of boxes
+;;;   are in turn stacked vertically, in vbox fashion; however, the sizes of
+;;;   the boxes in different rows interact so that columns, as well as rows,
+;;;   of boxes are kept aligned.  Thus (array-box '(A B C) '(D E F) '(G H J))
+;;;   will generate the following arrangement of kids A-J:
+;;;
+;;;            A   B   C
+;;;
+;;;            D   E   F
+;;;
+;;;            G   H   J
+;;;
+;;;   regardless of the individual sizes of the component boxes.  Instead of
+;;;   boxes, the following symbols may also appear as elements of an argument:
+;;;
+;;;      skip -- indicates the corresponding cell is to be left empty.
+;;;      left -- indicates the box to the left spans into this cell as well.
+;;;      up -- indicates the box above spans into this cell as well.
+;;;
+;;;   If the argument lists are not all of the same length, they are considered
+;;;   to be padded out at the end with as many occurrences of the symbol "left"
+;;;   as needed to make their lengths all equal.
+
+(define (kids-lists->complete-kids-lists kids-lists)
+  (let ((num-cols (apply max (map length kids-lists))))
+    (define (kids-list->complete-kids-list kids-list)
+      (let loop ((col 0) (complete-kids-list '()) (rest-kids kids-list))
+       (if (= col num-cols)
+           complete-kids-list
+           (let* ((next-kid
+                   (if (null? rest-kids)
+                       'left
+                       (car rest-kids)))
+                  (rest-kids
+                   (if (null? rest-kids)
+                       '()
+                       (cdr rest-kids)))
+                  (next-complete-list
+                   (append complete-kids-list (list next-kid))))
+             (loop (+ col 1) next-complete-list rest-kids)))))
+    
+    (let loop ((complete-kids-lists '()) (rest-kids-lists kids-lists))
+      (if (null? rest-kids-lists)
+         complete-kids-lists
+         (let ((next-list (car rest-kids-lists)))
+           (loop (append complete-kids-lists
+                         (list (kids-list->complete-kids-list next-list)))
+                 (cdr rest-kids-lists)))))))
+
+
+(define (row-lists->col-lists kids-lists)
+  (let ((kids-lists (kids-lists->complete-kids-lists kids-lists)))
+    (let loop ((col 0) (col-lists '()))
+      (if (= col (apply max (map length kids-lists)))
+         col-lists
+         (let ((col-list
+                (let loop ((row 0) (col-list '()))
+                  (if (= row (length kids-lists))
+                      col-list
+                      (loop (+ row 1)
+                            (cons (list-ref (list-ref kids-lists row) col)
+                                  col-list))))))
+           (loop (+ col 1) (cons col-list col-lists)))))))
+
+(define (array-size kids-lists)
+  (let ((col-lists (row-lists->col-lists kids-lists)))
+    (make-size
+     (apply +
+           (map (lambda (col-list)
+                  (apply max
+                         (map (lambda (kid)
+                                (if (symbol? kid)
+                                    0
+                                    (size.width (get-desired-size kid))))
+                              col-list)))
+                col-lists))
+     (apply +
+           (map (lambda (row-list)
+                  (apply max
+                         (map (lambda (kid)
+                                (if (symbol? kid)
+                                    0
+                                    (size.height (get-desired-size kid))))
+                              row-list)))
+                kids-lists)))))
+
+(define (array-arrange kids-lists my-screen-area)
+  (let* ((my-width (UITKRectangle.Width my-screen-area))
+        (my-height (UITKRectangle.Height my-screen-area))
+        (my-offset (UITKRectangle.Offset my-screen-area))
+        (X (point.X my-offset))
+        (Y (point.Y my-offset))
+        (kids-lists (kids-lists->complete-kids-lists kids-lists))
+        )
+
+    (define (kids-lists->kids-array kids-lists)
+      (let loop ((kids-lists kids-lists) (kids-array-list '()))
+       (if (null? kids-lists)
+           (list->vector kids-array-list)
+           (loop (cdr kids-lists)
+                 (append kids-array-list
+                         (list (list->vector (car kids-lists))))))))
+
+    (let* ((kids-array (kids-lists->kids-array kids-lists))
+          (num-rows (vector-length kids-array))
+          (num-cols (vector-length (vector-ref kids-array 0))))
+
+      (define (aref array row col)
+       (vector-ref (vector-ref array row) col))
+
+      (define (aset! array row col value)
+       (vector-set! (vector-ref array row) col value))
+
+      (define (kids-column-hglue col)
+       (define (get-hglue kid)
+         (if (symbol? kid)
+             *fil-glue*
+             (%hglue kid)))
+       (let* ((kid1 (aref kids-array 0 col))
+              (g1 (get-hglue kid1)))
+         (let loop ((row 1) (g g1))
+           (if (< row num-rows)
+               (let* ((next-kid (aref kids-array row col))
+                      (next-glue (get-hglue next-kid)))
+                 (loop (+ row 1) (parallel-compose-glue g next-glue)))
+               g))))
+
+      (define (kids-row-vglue row)
+       (define (get-vglue kid)
+         (if (symbol? kid)
+             *fil-glue*
+             (%vglue kid)))
+       (let* ((kid1 (aref kids-array row 0))
+              (g1 (get-vglue kid1)))
+         (let loop ((col 1) (g g1))
+           (if (< col num-cols)
+               (let* ((next-kid (aref kids-array row col))
+                      (next-glue (get-vglue next-kid)))
+                 (loop (+ col 1) (parallel-compose-glue g next-glue)))
+               g))))
+
+      (define (enumerate-interval from to)
+       (if (> from to)
+           '()
+           (cons from (enumerate-interval (+ from 1) to))))
+
+      (define (instantiate-kids h-positions-vector v-positions-vector)
+       (let loop-rows ((row 0))
+         (if (= row num-rows)
+             'done
+             (let loop-cols ((col 0))
+               (if (= col num-cols)
+                   (loop-rows (+ row 1))
+                   (let ((kid (aref kids-array row col)))
+                     (if (symbol? kid)
+                         (cond ((eq? kid 'skip)
+                                (loop-cols (+ col 1)))
+                               ((or (eq? kid 'left) (eq? kid 'up))
+                                ;; wasn't to the right or below a
+                                ;; valid child, so it's either been
+                                ;; taken care of already, or needs to
+                                ;; be 'skip.
+                                (aset! kids-array row col 'skip)
+                                (loop-cols (+ col 1)))
+                               (else
+                                (error
+                                 "Illegal symbol in array box:"
+                                 "Must be 'skip, 'left, or 'up." kid)))
+                         (let* ((kid-x-offset
+                                 (vector-ref h-positions-vector col))
+                                (kid-y-offset
+                                 (vector-ref v-positions-vector row))
+                                (width (- (vector-ref h-positions-vector
+                                                      (+ col 1))
+                                          kid-x-offset))
+                                (height (- (vector-ref v-positions-vector
+                                                       (+ row 1))
+                                           kid-y-offset)))
+
+                           (let expand-h-loop ((col+ 1) (wid width))
+                             (let ((new-col (+ col+ col)))
+                               (if (= new-col num-cols)
+                                   (set! width wid)
+                                   (let ((next-h-kid (aref kids-array row new-col)))
+                                     (if (symbol? next-h-kid)
+                                         (cond
+                                          ((eq? next-h-kid 'left)
+                                           (let* ((x-offset
+                                                   (vector-ref h-positions-vector
+                                                               new-col))
+                                                  (new-wid
+                                                   (+ wid
+                                                      (- (vector-ref
+                                                                h-positions-vector
+                                                                (+ new-col 1))
+                                                         x-offset))))
+                                             (aset! kids-array row new-col 'skip)
+                                             (expand-h-loop (+ col+ 1) new-wid)))
+                                          ((eq? next-h-kid 'skip)
+                                           (set! width wid))
+                                          ((eq? next-h-kid 'up)
+                                           (set! width wid))
+                                          (else
+                                           (error "Illegal symbol in array box:"
+                                                  "Must be 'skip, 'left, or 'up."
+                                                  next-h-kid)))
+                                         (set! width wid))))))
+                     
+                           (let expand-v-loop ((row+ 1) (ht height))
+                             (let ((new-row (+ row+ row)))
+                               (if (= new-row num-rows)
+                                   (set! height ht)
+                                   (let ((next-v-kid (aref kids-array new-row col)))
+                                     (if (symbol? next-v-kid)
+                                         (cond
+                                          ((eq? next-v-kid 'up)
+                                           (let* ((y-offset
+                                                   (vector-ref v-positions-vector
+                                                               new-row))
+                                                  (new-ht
+                                                   (+ ht (- (vector-ref
+                                                               v-positions-vector
+                                                               (+ new-row 1))
+                                                            y-offset))))
+                                             (aset! kids-array new-row col 'skip)
+                                             (expand-v-loop (+ row+ 1) new-ht)))
+                                          ((eq? next-v-kid 'skip)
+                                           (set! height ht))
+                                          ((eq? next-v-kid 'left)
+                                           (set! height ht))
+                                          (else
+                                           (error "Illegal symbol in array box:"
+                                                  "Must be 'skip, 'left, or 'up."
+                                                  next-v-kid)))
+                                         (set! height ht))))))
+                     
+                           (assign-screen-area!
+                            kid
+                            (make-UITKRectangle (make-point (+ X kid-x-offset)
+                                                            (+ Y kid-y-offset))
+                                                (make-size width height)))
+                           (loop-cols (+ col 1))))))))))
+
+      (let ((cols-hglues (map kids-column-hglue (enumerate-interval 0 (- num-cols 1))))
+           (rows-vglues (map kids-row-vglue (enumerate-interval 0 (- num-rows 1)))))
+       (conquer-space
+        my-width
+        cols-hglues
+        (lambda (h-positions-vector)
+          (conquer-space
+           my-height
+           rows-vglues
+           (lambda (v-positions-vector)
+             (instantiate-kids h-positions-vector v-positions-vector))))))
+      )))
+
+(define (array-get-hglue kids-lists)
+  ;; or minimum?
+  (choose-maximum-glue
+   (map (lambda (kids-list)
+         (series-compose-glues
+          (map (lambda (kid)
+                 (if (symbol? kid)
+                     *rigid-glue*
+                     (%hglue kid)))
+               kids-list)))
+       kids-lists)))
+
+(define (array-get-vglue kids-lists)
+  (choose-maximum-glue
+   (map (lambda (kids-list)
+         (series-compose-glues
+          (map (lambda (kid)
+                 (if (symbol? kid)
+                     *rigid-glue*
+                     (%vglue kid)))
+               kids-list)))
+       (row-lists->col-lists kids-lists))))
+
+
+(define (find-real-array-box-children kids-lists)
+  (let loop-lists ((kids-lists kids-lists)
+                  (valid-kids-list '()))
+    (if (null? kids-lists)
+       valid-kids-list
+       (let loop-list ((kids-list (car kids-lists))
+                       (valid-kids '()))
+         (if (null? kids-list)
+             (loop-lists (cdr kids-lists)
+                         (append valid-kids-list valid-kids))
+             (let ((kid (car kids-list)))
+               (if (symbol? kid)
+                   (loop-list (cdr kids-list) valid-kids)
+                   (loop-list (cdr kids-list)
+                              (append valid-kids (list kid))))))))))
+
+(define (array:rearrange me)
+  (let ((screen-area (used-screen-area me))
+       (kids-lists (ArrayBox%.kids-lists me)))
+    (if screen-area
+       (let ((new-size (array-size kids-lists)))
+         (set-%desired-size! me new-size)
+         (if (size= new-size (UITKRectangle.Size screen-area))
+             (begin (assign-glue! me)
+                    (array-arrange kids-lists screen-area))
+             (begin
+               (set-%desired-size! me new-size)
+               (geometry-change! me screen-area #T)
+               (if (eq? screen-area (used-screen-area me))
+                   (begin (assign-glue! me)
+                          (array-arrange kids-lists screen-area)))))))))
+
+(define (array-box-add-child! me kid)
+  (if (not (valid-child? kid))
+      (error "ARRAY-BOX-ADD-CHILD!: Bad UIObj" kid))
+  (one-parent-only! kid me)
+  (set-ArrayBox%.kids! me (append (ArrayBox%.kids me) (list kid)))
+  (on-geometry-change!
+   kid 'ARRAY-BOX
+   (lambda (old-screen-area new-screen-area)
+     old-screen-area                   ; Not used
+     (if (eq? new-screen-area #T)      ; Instigated by child, not manager
+        (array:rearrange me))))
+  (on-death! kid 'ARRAY-BOX            ; Die horribly ....
+            (lambda ()
+              (assign-drawing-surface! me 'RETRACTED)))
+  (assign-drawing-surface! kid (drawing-surface me))
+  (array:rearrange me))
+
+(define (array-box-assign-drawing-surface! me surface)
+  (check-drawing-surface! me surface)
+  (for-each (lambda (kid)
+             (if (eq? surface 'RETRACTED)
+                 (forget! kid 'ARRAY-BOX))
+             (assign-drawing-surface! kid surface))
+           (ArrayBox%.kids me))
+  (if (DrawingSurface? surface)
+      (set-%desired-size! me (array-size (ArrayBox%.kids-lists me))))
+  (if (eq? surface 'RETRACTED)
+      (death! me)
+      (geometry-change! me #F #F))
+  'OK)
+
+(define (array-box-assign-screen-area! me screen-area)
+  (cond ((vector? screen-area)
+        (set-assigned-screen-area! me screen-area)
+        (let ((old (used-screen-area me)))
+          (if (not (screen-area= old screen-area))
+              (begin
+                (set-used-screen-area! me screen-area)
+                (array:rearrange me)
+                (geometry-change! me old screen-area))))
+        screen-area)
+       ((not screen-area)
+        (set-assigned-screen-area! me screen-area)
+        (let ((old (used-screen-area me)))
+          (if (not (screen-area= old screen-area))
+              (begin
+                (set-used-screen-area! me screen-area)
+                (retract-area (ArrayBox%.kids me))
+                (geometry-change! me old screen-area))))
+        screen-area)
+       (else
+        (error "ARRAY-BOX-ASSIGN-SCREEN-AREA!: Bad screen-area" screen-area))))
+
+(define (array-box-assign-glue! me)
+  (let ((kids-lists (ArrayBox%.kids-lists me)))
+    (for-each assign-glue! (ArrayBox%.kids me))
+    (set-%hglue! me (array-get-hglue kids-lists)) 
+    (set-%vglue! me (array-get-vglue kids-lists))))
+
+;; Box Maker
+(define (array-box-maker kids-lists)
+  (make-ArrayBox%
+   (make-UIObjInternals 'invalid-arraybox-1 ; array-box-add-child!
+                       'invalid-arraybox-2 ; array-box-remove-child!
+                       UIObj-set-context!
+                       array-box-assign-screen-area!
+                       array-box-assign-drawing-surface!
+                       UIObj-point-within?
+                       UIObj-rectangle-overlaps?
+                       UIObj-handle-event
+                       UIObj-get-desired-size
+                       UIObj-assigned-screen-area
+                       UIObj-used-screen-area
+                       UIObj-set-assigned-screen-area!
+                       UIObj-set-used-screen-area!
+                       array-box-assign-glue!)
+   kids-lists))
+
+(define (array-box-propagator box)
+  (lambda (event)
+    (for-each (lambda (kid)
+               (if (event-within? kid event)
+                   (handle-event kid event)))
+             (array-box%.kids box))))
+             
+(define (make-array-box . kids-lists)
+  (let ((kids (find-real-array-box-children kids-lists)))
+    (let ((me (array-box-maker kids-lists)))
+      (on-event! me 'ARRAY-BOX
+                (array-box-propagator me))
+      (for-each (lambda (kid) (array-box-add-child! me kid))
+               kids)
+      me)))
diff --git a/v7/src/swat/scheme/load.scm b/v7/src/swat/scheme/load.scm
new file mode 100644 (file)
index 0000000..f7a3979
--- /dev/null
@@ -0,0 +1,1057 @@
+#|
+(with-working-directory-pathname
+    (directory-pathname (current-load-pathname))
+  (lambda ()
+    ;; Dynamically load the microcode.  Order important.
+    (load "dynload/scxl")
+    (load "dynload/tcl")
+    (load "dynload/tk")
+    (load "dynload/uitk")
+
+    ((access with-directory-rewriting-rule
+            (->environment '(RUNTIME COMPILER-INFO)))
+     (working-directory-pathname)
+     (pathname-as-directory "lib/swat")
+     (lambda ()
+       (package/system-loader "swat" '() 'QUERY)))
+    (add-system! (make-system "SWAT" 1 0 '()))))
+|#
+
+
+
+(let ((swat-env
+       (in-package system-global-environment
+        (let ()
+          (the-environment)))))
+
+  (package/add-child!  (find-package '())  'SWAT  swat-env)
+
+  (for-each (lambda (export)
+             (local-assignment swat-env export 'UNASSIGNED)
+             (environment-link-name
+              (package/environment (find-package '()))
+              swat-env
+              export))
+    ;; All of SWAT's exported names.  This list need pruning
+    '(*-alert-structure-size-*
+      *-alert.function-*
+      *-alert.reason-*
+      *-canvasitem-structure-size-*
+      *-canvasitem.add-event-handler!-procedure-*
+      *-canvasitem.ask-widget-procedure-*
+      *-canvasitem.canvas-*
+      *-canvasitem.name-*
+      *-canvasitem.set-callback!-procedure-*
+      *-canvasitemgroup-structure-size-*
+      *-canvasitemgroup.add-event-handler!-procedure-*
+      *-canvasitemgroup.ask-widget-procedure-*
+      *-canvasitemgroup.canvas-*
+      *-canvasitemgroup.set-callback!-procedure-*
+      *-canvasitemgroup.tag-*
+      *-context-structure-size-*
+      *-context.activebackground-*
+      *-context.activeforeground-*
+      *-context.anchor-*
+      *-context.background-*
+      *-context.border-*
+      *-context.borderwidth-*
+      *-context.foreground-*
+      *-context.relief-*
+      *-drawingsurface-structure-size-*
+      *-drawingsurface.toolkitwindow-*
+      *-drawingsurface.uitkwindow-*
+      *-drawingsurface.weak-list-of-widgets-*
+      *-event-structure-size-*
+      *-event.height-*
+      *-event.offset-*
+      *-event.os-event-*
+      *-event.point-or-rectangle?-*
+      *-event.type-*
+      *-event.width-*
+      *-event.window-*
+      *-glue-structure-size-*
+      *-glue.class-*
+      *-glue.minsize-*
+      *-glue.value-*
+      *-locked-list-structure-size-*
+      *-menuitem-structure-size-*
+      *-menuitem.add-event-handler!-procedure-*
+      *-menuitem.ask-widget-procedure-*
+      *-menuitem.index-*
+      *-menuitem.menurecord-*
+      *-menuitem.set-callback!-procedure-*
+      *-menurecord-structure-size-*
+      *-menurecord.items-*
+      *-menurecord.menu-*
+      *-point-structure-size-*
+      *-point.x-*
+      *-point.y-*
+      *-queue-structure-size-*
+      *-scxl-wrapper-structure-size-*
+      *-scxl-wrapper.other-stuff-*
+      *-scxl-wrapper.strong-dependents-*
+      *-scxl-wrapper.type-*
+      *-scxl-wrapper.wrapped-object-*
+      *-sensitive-surface-structure-size-*
+      *-sensitive-surface.drawingsurface-*
+      *-sensitive-surface.handlers-*
+      *-sensitivity-structure-size-*
+      *-sensitivity.masks-*
+      *-size-structure-size-*
+      *-size.height-*
+      *-size.width-*
+      *-surface-sensitivity-structure-size-*
+      *-surface-sensitivity.mask-*
+      *-surface-sensitivity.sensitivities-*
+      *-surface-sensitivity.weak-surface-*
+      *-texttag-structure-size-*
+      *-texttag.add-event-handler!-procedure-*
+      *-texttag.ask-widget-procedure-*
+      *-texttag.callbacks-*
+      *-texttag.name-*
+      *-texttag.set-callback!-procedure-*
+      *-texttag.text-*
+      *-tk-variable-structure-size-*
+      *-tk-variable.application-*
+      *-tk-variable.callback-*
+      *-tk-variable.tk-name-*
+      *-toolkitwindow-structure-size-*
+      *-toolkitwindow.application-*
+      *-toolkitwindow.tk-window-*
+      *-toolkitwindow.top-level-geometry-callback-*
+      *-uiobjinternals-structure-size-*
+      *-uiobjinternals.add-child!-procedure-*
+      *-uiobjinternals.already-have-a-parent?-*
+      *-uiobjinternals.assign-drawing-surface!-procedure-*
+      *-uiobjinternals.assign-glue!-procedure-*
+      *-uiobjinternals.assign-screen-area!-procedure-*
+      *-uiobjinternals.assigned-screen-area-*
+      *-uiobjinternals.assigned-screen-area-procedure-*
+      *-uiobjinternals.clip-region-*
+      *-uiobjinternals.crud-that-i-dont-want-to-gc-away-*
+      *-uiobjinternals.drawing-surface-*
+      *-uiobjinternals.get-desired-size-procedure-*
+      *-uiobjinternals.handle-event-procedure-*
+      *-uiobjinternals.point-within?-procedure-*
+      *-uiobjinternals.rectangle-overlaps?-procedure-*
+      *-uiobjinternals.remove-child!-procedure-*
+      *-uiobjinternals.set-assigned-screen-area!-procedure-*
+      *-uiobjinternals.set-context!-procedure-*
+      *-uiobjinternals.set-used-screen-area!-procedure-*
+      *-uiobjinternals.used-screen-area-*
+      *-uiobjinternals.used-screen-area-procedure-*
+      *-uitkrectangle-structure-size-*
+      *-uitkrectangle.offset-*
+      *-uitkrectangle.size-*
+      *-uitkwindow-structure-size-*
+      *-uitkwindow.xdisplay-*
+      *-uitkwindow.xwindow-*
+      *all-menus*
+      *all-sensitive-surfaces*
+      *event-processing-mutex*
+      *fil-glue*
+      *fil-glue-class*
+      *fill-glue-class*
+      *our-hash-table*
+      *percent-glue-class*
+      *rigid-glue*
+      *rigid-glue-class*
+      *synchronizing?*
+      *the-default-application*
+      *uitk-interval*
+      *uitk:gc-has-occurred?*
+      *xclosedisplaycallbacks*
+      ->widget
+      ->xcolormap
+      ->xdisplay
+      ->xgc
+      ->xpixel
+      ->xregion
+      ->xwindow
+      active-variable-value
+      add-child!
+      add-event-handler!
+      add-event-handler!-procedure-index
+      add-sub-menu
+      add-to-agenda!
+      add-to-canvas-item-group
+      add-to-menu
+      add-to-protection-list!
+      add-vectors
+      add-widget-list-for-display-number!
+      after-delay
+      after-last-space
+      alert.function
+      alert.reason
+      alert/pp
+      alert?
+      allow-free-trace?
+      application->display
+      application->tkmainwindow
+      application-add-child!
+      application-maker
+      application-remove-child!
+      application-remove-destroyed-child!
+      array-arrange
+      array-box-add-child!
+      array-box-assign-drawing-surface!
+      array-box-assign-glue!
+      array-box-assign-screen-area!
+      array-box-maker
+      array-box-propagator
+      array-get-hglue
+      array-get-vglue
+      array-size
+      array:rearrange
+      ask-widget
+      ask-widget-procedure-index
+      assign-drawing-surface!
+      assign-geometry!
+      assign-glue!
+      assign-location!
+      assign-screen-area!
+      assigned-screen-area
+      atomic-read-and-clear-cell!
+      bit-or
+      box-add-child!
+      box-assign-drawing-surface!
+      box-assign-glue!
+      box-assign-screen-area!
+      box-children
+      box-maker
+      box-remove-child!
+      box:event-propagator
+      box:rearrange
+      button-stretch
+      canvas-flush-protect-list!
+      canvas-protect-from-gc!
+      canvas-stretch
+      canvas-unprotect-from-gc!
+      canvasitem-add-event-handler!
+      canvasitem-ask-widget
+      canvasitem.add-event-handler!-procedure
+      canvasitem.ask-widget-procedure
+      canvasitem.canvas
+      canvasitem.name
+      canvasitem.set-callback!-procedure
+      canvasitem/pp
+      canvasitem?
+      canvasitemgroup-add-event-handler!
+      canvasitemgroup-ask-widget
+      canvasitemgroup.add-event-handler!-procedure
+      canvasitemgroup.ask-widget-procedure
+      canvasitemgroup.canvas
+      canvasitemgroup.set-callback!-procedure
+      canvasitemgroup.tag
+      canvasitemgroup/pp
+      canvasitemgroup?
+      change-sensitive-surface!
+      check-drawing-surface!
+      checkbutton-variable-on?
+      choose-maximum-glue
+      choose-minimum-glue
+      clean-lost-celled-objects
+      clean-lost-protected-objects
+      cleanup-vanished-objects-for-display
+      clear-counters!
+      cleararea
+      clip-region
+      close-lost-displays-daemon
+      color?
+      colormap/colormap
+      colormap/pixel-list
+      compose-glues
+      compute-cumulative-glues
+      conquer-space
+      context-change!
+      context.activebackground
+      context.activeforeground
+      context.anchor
+      context.background
+      context.border
+      context.borderwidth
+      context.foreground
+      context.relief
+      context/pp
+      context?
+      copy-free-traces
+      copy-rectangle
+      copyxregion
+      create-default-context
+      create-sensitive-surface
+      crud-that-i-dont-want-to-gc-away
+      current-size
+      current-time
+      death!
+      debug-print
+      debug-surface
+      debugging-port
+      decode-button-event
+      decode-configure-event
+      decode-crossing-event
+      decode-expose-event
+      decode-key-event
+      decode-motion-event
+      decode-unknown-event
+      decode-window-attributes
+      defer
+      ;;del-assq!
+      ;;del-assv!
+      ;;del-op!
+      delete-<interactor>!
+      delete-menuitem!
+      ;;dequeue!
+      destroy-all-sensitive-surfaces-from-display
+      destroy-associated-tk-widgets
+      destroy-registration
+      destroy-sensitive-surface
+      display->tk-widgets
+      display-protection-list
+      display/colormap-list
+      display/default-root-window
+      display/display
+      display/font-list
+      display/gc-list
+      display/screen/default-color-map
+      display/window-list
+      divide-space
+      do-tk-callbacks
+      do-tk-callbacks-from-string
+      drawarc
+      drawing-surface
+      drawingsurface.application
+      drawingsurface.toolkitwindow
+      drawingsurface.uitkwindow
+      drawingsurface.weak-list-of-widgets
+      drawingsurface/pp
+      drawingsurface?
+      drawline
+      drawrectangle
+      empty-agenda?
+      empty-queue?
+      empty-segments?
+      ;;enqueue!
+      ensure-graphics-context
+      entry-height-stretch
+      event!
+      event-counter
+      event-within?
+      event.height
+      event.offset
+      event.os-event
+      event.point-or-rectangle?
+      event.type
+      event.width
+      event.window
+      event/pp
+      event?
+      fil-glue?
+      fill-glue?
+      fillarc
+      fillrectangle
+      finalize-uitk-objects
+      finalize-uitk-objects-later
+      find-in-protection-list
+      find-menu-record
+      find-real-array-box-children
+      find-sensitivity
+      find-ss
+      find-tk-protection-list
+      find-tk-protection-list-from-number
+      first-segment
+      flush-display-hook
+      flush-queued-output
+      forget!
+      forget-context-change!
+      forget-death-notification!
+      forget-event!
+      forget-geometry-change!
+      fork-to-wait-on
+      gc/gc
+      gc/region
+      generate-events!
+      generate-graphics-context!
+      geometry-change!
+      get-desired-size
+      get-interval-to-next-delayed-event
+      get-interval-to-tk-wakeup
+      get-tk-widget-orientation
+      get-uitkwindow
+      get-window-attributes
+      get-x-event
+      getdefaultvalue
+      glue.class
+      glue.minsize
+      glue.value
+      glue/pp
+      glue?
+      h-arrange
+      h-get-hglue
+      h-get-vglue
+      h-size
+      handle-button-grab
+      handle-event
+      handle-exposure
+      handler->sensitivity
+      idle-queue
+      ignore-repl
+      init-alert
+      init-canvasitem
+      init-canvasitemgroup
+      init-context
+      init-drawingsurface
+      init-event
+      init-glue
+      init-locked-list
+      init-menuitem
+      init-menurecord
+      init-point
+      init-queue
+      init-scxl-wrapper
+      init-sensitive-surface
+      init-sensitivity
+      init-size
+      init-surface-sensitivity
+      init-texttag
+      init-tk-variable
+      init-toolkitwindow
+      init-uiobjinternals
+      init-uitkrectangle
+      init-uitkwindow
+      initial-thread-state
+      initialize-mit-widgets!
+      initialize-scxl!
+      initialize-uitk!
+      initialize-widgets!
+      insert-new-time!
+      interactor-add-child!
+      interactor-maker
+      interactor-remove-child!
+      intersectxregions
+      is-type-wrapped-object
+      kick-uitk-thread
+      kids-lists->complete-kids-lists
+      locked-list/pp
+      locked-list?
+      loop-counter
+      loop-trace
+      make-active-variable
+      make-add-alert!
+      make-agenda
+      make-alert
+      make-alert!
+      make-application
+      make-arc-on-canvas
+      make-arg-transformers
+      make-array-box
+      make-bitmap-on-canvas
+      make-box
+      make-button
+      make-canvas
+      make-canvas-item
+      make-canvas-item-group
+      make-canvasitem
+      make-canvasitemgroup
+      make-checkbutton
+      make-colored-graphics-context
+      make-context
+      make-del-op!
+      make-destroy-<application>-related-objects
+      make-drawingsurface
+      make-drop-rubber-rectangle-surface
+      make-enqueueable-thunk
+      make-entry
+      make-event
+      make-fil-glue
+      make-fill-glue
+      make-filled-circle
+      make-filled-oval
+      make-filled-rectangle
+      make-free-trace
+      make-glue
+      make-hbox
+      make-interactor
+      make-label
+      make-line
+      make-line-on-canvas
+      make-listbox
+      make-locked-list
+      make-lookup
+      make-menu
+      make-menubutton
+      make-menuitem
+      make-menurecord
+      make-message
+      make-oval
+      make-oval-on-canvas
+      make-percent-glue
+      make-point
+      make-point-event
+      make-polygon-on-canvas
+      make-protection-list
+      ;;make-queue
+      make-radiobutton
+      make-rect
+      make-rectangle-event
+      make-rectangle-on-canvas
+      make-remove-alert!
+      make-rigid-glue
+      make-scale
+      make-scaling-line
+      make-scaling-oval
+      make-scaling-rect
+      make-scrollable-canvas
+      make-scrollable-text
+      make-scrollbar
+      make-scxl-wrapper
+      make-self-painting-circle
+      make-self-painting-rectangle
+      make-self-painting-unfilled-rectangle
+      make-sensitive-surface
+      make-sensitivity
+      make-shape
+      make-shape-surface
+      make-simple-graphics-context
+      make-size
+      make-space
+      make-surface-sensitivity
+      make-text
+      make-text-on-canvas
+      make-text-tag
+      make-texttag
+      make-time-segment
+      make-tk-variable
+      make-tk-widget
+      make-toolkitwindow
+      make-top-level-geometry-callback
+      make-uiobjinternals
+      make-uitk-thread
+      make-uitkrectangle
+      make-uitkwindow
+      make-unfilled-circle
+      make-unfilled-oval
+      make-unfilled-rectangle
+      make-unknown-event
+      make-vbox
+      ;;make-weak-del-op!
+      ;;make-weak-lookup
+      make-widget-on-canvas
+      makexregion
+      maybe-defer
+      menuitem-ask-widget
+      menuitem-set-callback!
+      menuitem.add-event-handler!-procedure
+      menuitem.ask-widget-procedure
+      menuitem.index
+      menuitem.menu
+      menuitem.menurecord
+      menuitem.set-callback!-procedure
+      menuitem/pp
+      menuitem?
+      menurecord.items
+      menurecord.menu
+      menurecord/pp
+      menurecord?
+      merge-canvas-item-groups
+      more-counter
+      more-work-to-do
+      mouse-drag
+      on-context-change!
+      on-death!
+      on-event!
+      on-geometry-change!
+      one-parent-only!
+      open-display
+      our-with-thread-mutex-locked
+      parallel-compose-glue
+      parallel-compose-glues
+      percent-glue?
+      pixel/pixel
+      point-event-within?
+      point-event?
+      point-in-rectangle?
+      point-within?
+      point.x
+      point.y
+      point/pp
+      point=
+      point?
+      proc-with-transformed-args
+      protection-list-all-elements
+      protection-list-referenced-elements
+      queue/pp
+      ;;queue?
+      read-and-empty-agenda!
+      read-and-empty-queue!
+      read-queue-trace
+      record-free-pointer
+      record-surface-sensitivity!
+      rectangle->xregion
+      rectangle-event-within?
+      rectangle-event?
+      rectangle-overlaps-rectangle?
+      rectangle-overlaps?
+      rectangle=
+      region-protection-list
+      region/region
+      remember-on-canvas!
+      remove-child!
+      remove-from-protection-list!
+      remove-from-registry
+      reset-sensitivity!
+      rest-segments
+      restart-uitk
+      retract-area
+      rigid-glue?
+      row-lists->col-lists
+      run-queue-trace
+      screen-area=
+      scrollable-canvas-canvas
+      scrollable-canvas-hscroll
+      scrollable-canvas-vscroll
+      scrollable-text-text
+      scrollable-text-vscroll
+      scxl-destroy!
+      scxl-destroyed?
+      scxl-display?
+      scxl-install-xclosedisplay-callback
+      scxl-unwrap
+      scxl-wrap
+      scxl-wrapped?
+      scxl-wrapper.other-stuff
+      scxl-wrapper.strong-dependents
+      scxl-wrapper.type
+      scxl-wrapper.wrapped-object
+      scxl-wrapper/pp
+      scxl-wrapper?
+      search-protection-list
+      segment-queue
+      segment-time
+      segments
+      self-paint!
+      sensitive-surface.drawingsurface
+      sensitive-surface.handlers
+      sensitive-surface/pp
+      sensitive-surface?
+      sensitivity.masks
+      sensitivity/pp
+      sensitivity?
+      series-compose-glue
+      series-compose-glues
+      set-active-variable!
+      set-active-variable-callback!
+      set-alert.function!
+      set-alert.reason!
+      set-assigned-screen-area!
+      set-callback!
+      set-callback!-procedure-index
+      set-canvasitem.add-event-handler!-procedure!
+      set-canvasitem.ask-widget-procedure!
+      set-canvasitem.canvas!
+      set-canvasitem.name!
+      set-canvasitem.set-callback!-procedure!
+      set-canvasitemgroup.add-event-handler!-procedure!
+      set-canvasitemgroup.ask-widget-procedure!
+      set-canvasitemgroup.canvas!
+      set-canvasitemgroup.set-callback!-procedure!
+      set-canvasitemgroup.tag!
+      set-clip-region!
+      set-context!
+      set-context.activebackground!
+      set-context.activeforeground!
+      set-context.anchor!
+      set-context.background!
+      set-context.border!
+      set-context.borderwidth!
+      set-context.foreground!
+      set-context.relief!
+      set-crud-that-i-dont-want-to-gc-away!
+      set-drawing-surface!
+      set-drawingsurface.toolkitwindow!
+      set-drawingsurface.uitkwindow!
+      set-drawingsurface.weak-list-of-widgets!
+      set-event.height!
+      set-event.offset!
+      set-event.os-event!
+      set-event.point-or-rectangle?!
+      set-event.type!
+      set-event.width!
+      set-event.window!
+      set-floating-error-mask!
+      set-gc/region!
+      set-glue.class!
+      set-glue.minsize!
+      set-glue.value!
+      set-menuitem.add-event-handler!-procedure!
+      set-menuitem.ask-widget-procedure!
+      set-menuitem.index!
+      set-menuitem.menurecord!
+      set-menuitem.set-callback!-procedure!
+      set-menurecord.items!
+      set-menurecord.menu!
+      set-point.x!
+      set-point.y!
+      set-scxl-wrapper.other-stuff!
+      set-scxl-wrapper.strong-dependents!
+      set-scxl-wrapper.type!
+      set-scxl-wrapper.wrapped-object!
+      set-segments!
+      set-sensitive-surface.drawingsurface!
+      set-sensitive-surface.handlers!
+      set-sensitivity.masks!
+      set-size.height!
+      set-size.width!
+      set-surface-sensitivity.mask!
+      set-surface-sensitivity.sensitivities!
+      set-surface-sensitivity.weak-surface!
+      set-texttag.add-event-handler!-procedure!
+      set-texttag.ask-widget-procedure!
+      set-texttag.callbacks!
+      set-texttag.name!
+      set-texttag.set-callback!-procedure!
+      set-texttag.text!
+      set-tk-variable.application!
+      set-tk-variable.callback!
+      set-tk-variable.tk-name!
+      set-toolkitwindow.application!
+      set-toolkitwindow.tk-window!
+      set-toolkitwindow.top-level-geometry-callback!
+      set-uiobjinternals.add-child!-procedure!
+      set-uiobjinternals.already-have-a-parent?!
+      set-uiobjinternals.assign-drawing-surface!-procedure!
+      set-uiobjinternals.assign-glue!-procedure!
+      set-uiobjinternals.assign-screen-area!-procedure!
+      set-uiobjinternals.assigned-screen-area!
+      set-uiobjinternals.assigned-screen-area-procedure!
+      set-uiobjinternals.clip-region!
+      set-uiobjinternals.crud-that-i-dont-want-to-gc-away!
+      set-uiobjinternals.drawing-surface!
+      set-uiobjinternals.get-desired-size-procedure!
+      set-uiobjinternals.handle-event-procedure!
+      set-uiobjinternals.point-within?-procedure!
+      set-uiobjinternals.rectangle-overlaps?-procedure!
+      set-uiobjinternals.remove-child!-procedure!
+      set-uiobjinternals.set-assigned-screen-area!-procedure!
+      set-uiobjinternals.set-context!-procedure!
+      set-uiobjinternals.set-used-screen-area!-procedure!
+      set-uiobjinternals.used-screen-area!
+      set-uiobjinternals.used-screen-area-procedure!
+      set-uitkrectangle.offset!
+      set-uitkrectangle.size!
+      set-uitkwindow.xdisplay!
+      set-uitkwindow.xwindow!
+      set-used-screen-area!
+      setclipxregion
+      shape-assign-glue!
+      shape-assign-screen-area!
+      shape-copy
+      shape-draw
+      shape-draw-function
+      shape-erase-maybe
+      shape-maker
+      shape-point-within?
+      shape-rectangle-overlaps?
+      shape-set-color!
+      shape-set-erase-function!
+      shape-set-gc-function!
+      show-counters
+      shut-down-event-server
+      size.height
+      size.width
+      size/pp
+      size=
+      size?
+      string->color
+      stringify-for-tk
+      sub-vectors
+      subtractxregions
+      surface-sensitivity.mask
+      surface-sensitivity.sensitivities
+      surface-sensitivity.weak-surface
+      surface-sensitivity/pp
+      surface-sensitivity?
+      suspend-counter
+      swat-close
+      swat-open
+      swat-open-in-application
+      swat:number->string
+      tcl-global-eval
+      text-flush-protect-list!
+      text-protect-from-gc!
+      text-unprotect-from-gc!
+      texttag-add-event-handler!
+      texttag-ask-widget
+      texttag.add-event-handler!-procedure
+      texttag.ask-widget-procedure
+      texttag.callbacks
+      texttag.name
+      texttag.set-callback!-procedure
+      texttag.text
+      texttag/pp
+      texttag?
+      the-agenda
+      thread-start
+      tk-completely-handles-event?
+      tk-create-top-level-window
+      tk-delete-display
+      tk-doevents
+      tk-gen-name
+      tk-generate-scheme-event
+      tk-has-requested-new-size
+      tk-init
+      tk-invoke-command
+      tk-kill-application
+      tk-make-button
+      tk-make-canvas
+      tk-make-checkbutton
+      tk-make-entry
+      tk-make-label
+      tk-make-listbox
+      tk-make-menu
+      tk-make-menubutton
+      tk-make-message
+      tk-make-radiobutton
+      tk-make-scale
+      tk-make-scrollbar
+      tk-make-text
+      tk-manage-geometry
+      tk-map-window
+      tk-move-resize-widget
+      tk-op
+      tk-unmap-window
+      tk-variable.application
+      tk-variable.callback
+      tk-variable.tk-name
+      tk-variable/pp
+      tk-variable?
+      tk-widget->pathname
+      tk-widget-destroy
+      tk-widget.tkwin
+      tkwidget-add-child!
+      tkwidget-add-event-handler!
+      tkwidget-ask-widget
+      tkwidget-assign-drawing-surface!
+      tkwidget-assign-glue!
+      tkwidget-assign-screen-area!
+      tkwidget-assigned-screen-area
+      tkwidget-get-desired-size
+      tkwidget-maker
+      tkwidget-set-assigned-screen-area!
+      tkwidget-set-callback!
+      tkwidget-set-used-screen-area!
+      tkwidget-used-screen-area
+      tkwin->requested-size
+      tkwin->size
+      tkwin.display
+      tkwin.height
+      tkwin.ismapped?
+      tkwin.name
+      tkwin.pathname
+      tkwin.req-height
+      tkwin.req-width
+      tkwin.width
+      tkwin.window
+      tkwin.x
+      tkwin.y
+      toolkitwindow.application
+      toolkitwindow.tk-window
+      toolkitwindow.top-level-geometry-callback
+      toolkitwindow/pp
+      toolkitwindow?
+      translate-rectangle
+      type-check-wrapped-object
+      uiobj-assign-drawing-surface!
+      uiobj-assign-screen-area!
+      uiobj-assigned-screen-area
+      uiobj-get-desired-size
+      uiobj-handle-event
+      uiobj-point-within?
+      uiobj-protect-from-gc!
+      uiobj-rectangle-overlaps?
+      uiobj-set-assigned-screen-area!
+      uiobj-set-context!
+      uiobj-set-used-screen-area!
+      uiobj-unprotect-from-gc!
+      uiobj-used-screen-area
+      uiobjinternals
+      uiobjinternals-index
+      uiobjinternals.add-child!-procedure
+      uiobjinternals.already-have-a-parent?
+      uiobjinternals.assign-drawing-surface!-procedure
+      uiobjinternals.assign-glue!-procedure
+      uiobjinternals.assign-screen-area!-procedure
+      uiobjinternals.assigned-screen-area
+      uiobjinternals.assigned-screen-area-procedure
+      uiobjinternals.clip-region
+      uiobjinternals.crud-that-i-dont-want-to-gc-away
+      uiobjinternals.drawing-surface
+      uiobjinternals.get-desired-size-procedure
+      uiobjinternals.handle-event-procedure
+      uiobjinternals.point-within?-procedure
+      uiobjinternals.rectangle-overlaps?-procedure
+      uiobjinternals.remove-child!-procedure
+      uiobjinternals.set-assigned-screen-area!-procedure
+      uiobjinternals.set-context!-procedure
+      uiobjinternals.set-used-screen-area!-procedure
+      uiobjinternals.used-screen-area
+      uiobjinternals.used-screen-area-procedure
+      uiobjinternals/pp
+      uiobjinternals?
+      uitk-protection-list
+      uitk-queue
+      uitk-thread
+      uitk-thread-main-loop
+      uitk-timer
+      uitkrectangle.height
+      uitkrectangle.offset
+      uitkrectangle.size
+      uitkrectangle.width
+      uitkrectangle/pp
+      uitkrectangle?
+      uitkwindow.xdisplay
+      uitkwindow.xwindow
+      uitkwindow/pp
+      uitkwindow?
+      unionxregions
+      unwrap-display
+      update-locked-list!
+      used-screen-area
+      v-arrange
+      v-get-hglue
+      v-get-vglue
+      v-size
+      valid-child?
+      valid-color-for-application?
+      valid-color?
+      valid-non-widget?
+      ;;weak-delq!
+      when-idle!
+      when-unreferenced
+      widget->screen-area
+      widget->size
+      widget/widget
+      window/window
+      with-clipping!
+      with-locked-list
+      with-uitk-thread-errors-captured
+      wrap-colormap
+      wrap-display
+      wrap-graphics-context
+      wrap-pixel
+      wrap-region
+      wrap-tk-widget
+      wrap-window
+      wrap-with-scxl-destroy!
+      xallocnamedcolor
+      xchangewindowattributes
+      xcheckmaskevent!?
+      xcleararea
+      xclearwindow
+      xclosedisplay
+      xclosedisplaybynumber
+      xcolor.pixel
+      xconnectionnumber
+      xcopy-event
+      xcreategc
+      xcreateregion
+      xcreatesimplewindow
+      xdecodebuttonevent
+      xdecodeconfigureevent
+      xdecodecrossingevent
+      xdecodeexposeevent
+      xdecodekeyevent
+      xdecodemotionevent
+      xdecodeunknownevent
+      xdecodewindowattributes
+      xdecodexcolor
+      xdefaultcolormap
+      xdefaultrootwindow
+      xdefaultscreen
+      xdestroyregion
+      xdestroywindow
+      xdrawarc
+      xdrawline
+      xdrawrectangle
+      xevent-><event>
+      xevent-type
+      xfillarc
+      xfillrectangle
+      xflush
+      xfreecolormap
+      xfreegc
+      xgetdefault
+      xgetwindowattributes
+      xintersectregion!
+      xloadfont
+      xmake-color
+      xmake-event
+      xmake-gcvalues
+      xmake-setwindowattributes
+      xmapwindow
+      xnextevent
+      xnextevent!
+      xopendisplay
+      xpending
+      xputbackevent
+      xquerypointer
+      xquerytree
+      xscreencount
+      xsetforeground
+      xsetfunction
+      xsetregion
+      xsetwindowattributes-event_mask!
+      xstorename
+      xsubtractregion!
+      xtranslatecoordinates
+      xunionrectspecswithregion!
+      xunionregion!
+      xunloadfont)))
+
+
+(with-working-directory-pathname
+    (directory-pathname (current-load-pathname))
+  (lambda ()
+
+    (in-package (->environment '(SWAT))
+      ;; These get overriden when TK is loaded
+      (define (tk-doevents) 'tk-doevents)
+      (define (tk-init dsp) 'tk-init))
+
+    ;; Dynamically load the microcode.  Order important.
+    (load "dynload/scxl")
+    (load "dynload/tcl")
+    (load "dynload/tk")
+    (load "dynload/uitk")
+   
+    ;; And now the Scheme level
+    ;;(load "scc-macros")
+    ;;(load "uitk-macros")
+      
+    ((access with-directory-rewriting-rule
+            (->environment '(RUNTIME COMPILER-INFO)))
+     (working-directory-pathname)
+     (pathname-as-directory "lib/swat")
+     (lambda ()
+       (let ((load
+             (lambda (file)
+               (load file '(SWAT)))))
+        (load "control-floating-errors")
+        (load "structures")
+        (load "structures2")
+        (load "generics")
+        (load "uitk")
+        (load "xlibCONSTANTS")
+        (load "mit-xlib")
+        (load "tk-mit")
+        (load "mit-xhooks")
+        (load "widget-mit")
+        (load "baseobj")
+        (load "widget")
+        (load "geometry")
+        (load "simple")
+        (load "canvas")
+        (load "menu")
+        (load "text")
+        ;;(load "rtest")
+        ;;(load "btest")
+        )))))
diff --git a/v7/src/swat/scheme/menu.scm b/v7/src/swat/scheme/menu.scm
new file mode 100644 (file)
index 0000000..ee07267
--- /dev/null
@@ -0,0 +1,104 @@
+;;; -*- Scheme -*-
+
+;;; <MenuItem> class
+
+(define *all-menus* '())
+
+(define (MenuItem.Menu item)
+  (MenuRecord.Menu (MenuItem.MenuRecord item)))
+
+(define (find-menu-record menu)
+  (let loop ((prev #F)
+            (rest *all-menus*))
+    (cond ((null? rest)
+          (error "Find-Menu-Record: Can't find record" menu))
+         ((null? (weak-car rest))
+          (if prev
+              (weak-set-cdr! prev (weak-cdr rest))
+              (set! *all-menus* (weak-cdr rest)))
+          (loop prev (weak-cdr rest)))
+         ((eq? (MenuRecord.Menu (weak-car rest)) menu)
+          (weak-car rest))
+         (else (loop rest (weak-cdr rest))))))
+
+(define (add-sub-menu menu sub-menu . options)
+  (set-TKWidget%.do-not-gc-protect! sub-menu #T)
+  (UIObj-protect-from-gc! sub-menu menu) ; Keep daddy alive ...
+  ;; Above must happen *before* add-child!, since the menu may already
+  ;; have a drawing surface and then the sub-menu would get it
+  ;; immediately and the protection wouldn't be removed.  Get it?
+  (add-child! menu sub-menu)
+  (apply add-to-menu menu 'cascade
+        '-menu (lambda () (tk-widget->pathname sub-menu))
+        options))
+
+(define (menuitem-set-callback! me proc)
+  (if (not (MenuItem.Index me))
+      (error "SET-CALLBACK!: menu item deleted!" me))
+  (set-MenuItem.%callback! me proc)
+  (ask-widget (MenuItem.Menu me)
+             `(entryconfigure
+               ,(MenuItem.Index me)
+               -command
+               ,(string-append "SchemeCallBack "
+                               (number->string
+                                (hash proc *our-hash-table*))))))
+
+(define (delete-menuitem! item)
+  (let ((menu-record (MenuItem.MenuRecord item))
+       (index (MenuItem.Index item)))
+    (let loop ((rest (MenuRecord.Items menu-record))
+              (count 0)
+              (prev #F))
+      (cond ((null? rest)
+            (ask-widget (MenuRecord.Menu menu-record)
+                        `(delete ,(MenuItem.index item)))
+            (set-MenuItem.index! item #F)
+            'DONE)
+           ((eq? (car rest) item)
+            (if (not (= count Index))
+                (error "Delete-MenuItem!: Inconsistent count"
+                       count index me))
+            
+            (if prev
+                (set-cdr! prev (cdr rest))
+                (set-MenuRecord.Items! menu-record (cdr rest)))
+            (loop (cdr rest) (+ count 1) prev))
+           ((= count index)
+            (error "Delete-MenuItem!: Missing item" count index me))
+           (else
+            (if (> count index)
+                (Set-MenuItem.Index! (car rest) (- count 1)))
+            (loop (cdr rest) (+ count 1) rest))))))
+
+(define (menuitem-ask-widget me command)
+  ;; For example:
+  ;; (Ask-Widget me `(configure -label "George"))
+  ;; becomes
+  ;; (Ask-Widget menu `(entryconfigure index -label "George"))
+  (if (or (eq? (car command) 'configure)
+         (string=? (car command) "configure"))
+      (ask-widget (MenuItem.Menu me)
+                 `(entryconfigure ,(MenuItem.Index me)
+                                  ,@(cdr command)))
+      (error "MenuItem-Ask-Widget: must be configure command"
+            me command)))
+
+(define (add-to-menu menu which-kind . options)
+  ;; Which-Kind should be 'CHECKBUTTON, 'COMMAND,
+  ;; 'RADIOBUTTON, or 'SEPARATOR.  Cascades are made using
+  ;; Add-Sub-Menu, above
+  (let ((menu-record (find-menu-record menu)))
+    (let ((items (MenuRecord.Items Menu-Record)))
+      (let ((new-item
+            (make-menuitem menuitem-ask-widget
+                           'invalid
+                           menuitem-set-callback!
+                           menu-record
+                           '()
+                           (length items))))
+       (ask-widget menu `(add ,which-kind ,@options))
+       (set-MenuRecord.Items! Menu-Record
+                              (append! items (list new-item)))
+       new-item))))
+
diff --git a/v7/src/swat/scheme/mit-xhooks.scm b/v7/src/swat/scheme/mit-xhooks.scm
new file mode 100644 (file)
index 0000000..390d265
--- /dev/null
@@ -0,0 +1,922 @@
+;;; -*- Scheme -*-
+
+#| ******************************
+
+MIT-XHOOKS defines the level of the system that handles event
+processing, and the manipulation of UITK objects just above the X
+level (defined in MIT-XLIB).  This layer will differ between
+MIT-Scheme and Scheme-to-C
+
+This file tries to include all the functions that actually call X so
+that the other parts of the system can be rebuilt on a different
+substrate. 
+
+  ****************************** |#
+
+#|
+Not used?
+
+(define (with-window display title desired-size context receiver)
+  ;; Call RECEIVER with UITKwindow and actual size
+  (let* ((window (create-top-level-x-window
+                 display title desired-size context)))
+    (XMapWindow display window)
+    (report-window-size display window receiver)))
+
+(define (report-window-size display window receiver)
+  (get-window-attributes display window
+   (lambda (x y width height . others)
+     others
+     (receiver (make-uitkwindow display window)
+              (make-size width height)
+              x
+              y))))
+
+
+(define (create-top-level-x-window display title desired-size context)
+  (let ((window
+        (XCreateSimpleWindow
+         display
+         (XDefaultRootWindow display)  ; Parent is root window
+         0                             ; X
+         0                             ; Y
+         (size.width desired-size)     ; Width
+         (size.height desired-size)    ; Height
+         (context.BorderWidth context)
+         (context.Border context)
+         (context.Background context))))
+    (XStoreName display window title)
+    window))
+
+
+(define (destroy-window w)
+  (let ((Xwindow (UITKWindow.XWindow w)))
+    (XDestroyWindow (UITKWindow.XDisplay w) Xwindow)))
+
+
+
+
+
+|#
+
+\f
+;;;;UITK main loop
+
+#| In general, the system will have two threads running -- the
+ordinary REP and the UITK thread, which processes events for the
+widgets.
+
+When an event is signalled, it is placed (at interrupt level) on a
+queue, which is processed at user level by the UITK thread main loop
+|#
+
+;;;UITK thread will wake up at at least this interval, since it needs
+;;;to clean up objects labelld for destruction by the GC, even if
+;;;there are no events to process.
+
+(define *UITK-INTERVAL* (* 30 1000))   ; 30 seconds, in milliseconds
+
+(define uitk-queue 'later)             ;code that processes events
+(define idle-queue 'later)             ;not used in MIT version
+(define the-agenda 'later)             ;processing scheduled by AFTER-DELAY
+(define uitk-thread 'later)
+(define more-work-to-do #F)
+(define uitk-timer #F)
+
+#| #############################################################
+This is some debugging stuff for probing the space usage.
+|# 
+
+
+(DEFINE LOOP-COUNTER 0)
+(DEFINE EVENT-COUNTER 0)
+(DEFINE MORE-COUNTER 0)
+(DEFINE SUSPEND-COUNTER 0)
+(DEFINE LOOP-TRACE)
+(DEFINE READ-QUEUE-TRACE)
+(DEFINE RUN-QUEUE-TRACE)
+(define ALLOW-FREE-TRACE? #T)
+
+(define (clear-counters!)
+  (SET! LOOP-COUNTER 0)
+  (SET! EVENT-COUNTER 0)
+  (SET! MORE-COUNTER 0)
+  (SET! SUSPEND-COUNTER 0)
+  0)
+
+(define ignore-repl #F)
+
+(define (show-counters)
+  (pp
+   `(events: , event-counter loop: ,loop-counter more: ,more-counter suspend: ,suspend-counter)))
+
+(define (make-free-trace n)
+  (cons 0 (make-vector n #f)))
+
+(define (copy-free-traces)
+  (fluid-let ((allow-free-trace? #f))
+    (vector (cons (car loop-trace) (vector-copy (cdr loop-trace)))
+           (cons (car read-queue-trace) (vector-copy (cdr read-queue-trace)))
+           (cons (car run-queue-trace) (vector-copy (cdr run-queue-trace))))))
+
+(define (record-free-pointer trace)
+  (if allow-free-trace?
+      (let-syntax ((ucode-primitive
+                   (macro arguments
+                     (apply make-primitive-procedure arguments))))
+       (vector-set! (cdr trace)
+                    (car trace)
+                    ((ucode-primitive primitive-get-free 1) 26))
+       (set-car! trace
+                 (if (fix:= (fix:+ (car trace) 1) (vector-length (cdr trace)))
+                     0
+                     (fix:+ (car trace) 1))))))
+
+#| #############################################
+end of debugging stuff
+
+|#
+
+
+(define (make-uitk-thread)
+  (set! uitk-thread
+       (create-thread (create-thread-continuation) thread-start))
+  (kick-uitk-thread))
+
+(define initial-thread-state 'later)
+
+(define (thread-start)
+  (call-with-current-continuation
+   (lambda (start-up)
+     (set! initial-thread-state start-up)
+     (uitk-thread-main-loop))))
+
+(define (restart-uitk)
+  (restart-thread uitk-thread #T (lambda () (initial-thread-state 'go))))
+
+(let-syntax ((last-reference
+             (macro (variable)
+               `(let ((foo ,variable))
+                  (set! ,variable #F)
+                  foo))))
+
+  (define (uitk-thread-main-loop)
+    (define (flush-all-displays)
+      (for-each flush-queued-output
+               (protection-list-referenced-elements
+                display-protection-list)))
+    (define (run thunk) (thunk))
+    (SET! LOOP-COUNTER 0)
+    (SET! EVENT-COUNTER 0)
+    (SET! MORE-COUNTER 0)
+    (SET! SUSPEND-COUNTER 0)
+    (let process-loop ()
+      (SET! LOOP-COUNTER (+ 1 LOOP-COUNTER))
+      (block-thread-events)
+      (set! more-work-to-do #F)
+      ;; Read out the event/idle/delayed thunks
+      (let ((events (read-and-empty-queue! uitk-queue))
+           (idle (read-and-empty-queue! idle-queue))
+           (delayed (read-and-empty-agenda! the-agenda))
+           )
+       (unblock-thread-events)
+       ;;process the thinks that were read, and clear the variables so
+       ;; the thunks can GC away after they are run.
+       (for-each run (last-reference events))
+       (for-each run (last-reference idle))
+       (for-each run (last-reference delayed))
+       ;; Allow tk to do its pending events (includes handling callbacks)
+       (tk-doevents)
+       ;;check if a GC has occurred (the GC daemon sets the flag) and
+       ;;finalize the GC'd objects.
+       (if (with-absolutely-no-interrupts
+            (lambda ()
+              (let ((result *UITK:GC-HAS-OCCURRED?*))
+                (set! *UITK:GC-HAS-OCCURRED?* #F)
+                result)))
+           (begin                      ; Clean up after GC
+             (finalize-uitk-objects)
+             (close-lost-displays-daemon)))
+       (let ((more? (begin (block-thread-events) more-work-to-do)))
+         ;; MORE? is #T if work arrived while we were handling the
+         ;; previously grabbed event/idle thunks
+         (flush-all-displays)
+         (IF (OR MORE? IGNORE-REPL)
+             (begin
+               (unblock-thread-events)
+               (SET! MORE-COUNTER (+ 1 MORE-COUNTER))
+               (process-loop))         ; Don't give up CPU yet
+             (begin
+               (let ((tk-wake-up (get-interval-to-tk-wakeup))
+                     (delayed-wake-up (get-interval-to-next-delayed-event)))
+                 ;;get time to wake up to for next TK event or
+                 ;;delayed event
+                 (let ((wake-up (if tk-wake-up
+                                    (if delayed-wake-up
+                                        (min tk-wake-up delayed-wake-up)
+                                        tk-wake-up)
+                                    delayed-wake-up)))
+                   ;;flush the current timer event if there is one
+                   ;;and register the next actual time to wake up
+                   (if uitk-timer (deregister-timer-event uitk-timer))
+                   (set! uitk-timer
+                         (register-timer-event (if wake-up
+                                                   (min wake-up *UITK-INTERVAL*)
+                                                   *UITK-INTERVAL*)
+                                               (lambda () (set! uitk-timer #F))))))
+               ;;now go to sleep. The timer event, or an X event,
+               ;;will wake us up.  We suspend with events still
+               ;;blocked to avoid an interrupt hole, whereby an
+               ;;event is delivered but doesn't wake us up.
+               ;;Suspending atomically unblocks events in the right
+               ;;way to prevent this.
+               (suspend-current-thread)
+               (SET! SUSPEND-COUNTER (+ SUSPEND-COUNTER 1))
+               ;;(allow-thread-event-delivery)
+               (unblock-thread-events)
+               (process-loop))))))
+    ))
+
+(define (with-uitk-thread-errors-captured thunk)
+  (define newline-string "
+")
+  (call-with-current-continuation
+   (lambda (exit-continuation)
+     (fluid-let
+        ((standard-error-handler
+          (lambda (error-condition)
+            (fluid-let ((standard-error-handler standard-error-handler))
+              (newline)
+              (newline)
+              (display
+               (string-append
+                ";Error in UITK thread:" newline-string
+                ";" (condition/report-string error-condition)
+                newline-string
+                ";To debug, type (debug (unhash "
+                (number->string
+                 (hash (condition/continuation error-condition)))
+                "))"))
+              (newline)
+              (newline)
+              (exit-continuation 'punt-o-rama)))))
+       (thunk)))))
+
+;;;This forces the UITK thread to wake up
+(define kick-uitk-thread
+  (let ((*uitk-thread-kicked?* #F))
+    (lambda ()
+      (if (not *uitk-thread-kicked?*)
+         (begin
+           (set! *uitk-thread-kicked?* #T)
+           (when-idle!
+            ;; When-Idle! will make the thread awaken
+            (lambda ()
+              (set! *uitk-thread-kicked?* #F))))))))
+
+;;; Redefine hook found in mit-xlib.  Running the UITK loop will flush
+;;; all displays.
+(define flush-display-hook kick-uitk-thread)
+
+(define (when-idle! thunk)
+  (signal-thread-event
+   uitk-thread
+   (lambda ()
+     ;; Interrupt level
+     (set! more-work-to-do #T)
+     (enqueue! idle-queue thunk))))
+
+\f
+;;; Registering events for processing
+
+#| For each display connection, we have a permanently
+   registered request to process input from a particular file.
+   FORK-TO-WAIT-ON creates such a registration.  When events come in
+   on the display connection, the CHILD-WORK-CODE is enqueued for
+   user-level execution.  If the CHILD-WORK-CODE has been GCed away,
+   then code to deregister the handler is executed.
+|#
+
+(define fork-to-wait-on
+  (let ()
+    ;; This group of procedures can NOT be lexically nested inside of
+    ;; fork-to-wait-on because we want the link from the enqueued
+    ;; thunk to child-work-code to be a weak pointer.  
+    ;; Thus child-work-code should not be lexically visible to
+    ;; these procedures.  If we had a strong pointer, then the
+    ;; registry would point to the child work code and hence to the
+    ;; application, so applications could never be GCd.
+    (define (try-to-run weak)
+      (lambda ()
+       (let ((code (weak-car weak))
+             (wcdr (weak-cdr weak)))
+         (if (and code (not (scxl-destroyed? (weak-car wcdr))))
+             (begin
+               ;; Reinstall interrupt handler, then run user code
+               (register-input-thread-event
+                (XConnectionNumber (weak-car wcdr))
+                uitk-thread (weak-cdr wcdr))
+               (code))))))
+    (define (call-if-still-there weak)
+      ;; WEAK is a weak-list:
+      ;;   (desired-code-thunk display #F)
+      ;; In normal use, desired-code-thunk is #F iff the application
+      ;; has vanished.  This code creates a procedure to run at
+      ;; interrupt level, replaces the #F with the handler, and
+      ;; returns the handler to the caller.
+      (let ((result
+            (lambda ()
+              ;; Interrupt level
+              (let ((code (weak-car weak)))
+                (if code
+                    (begin
+                      (set! more-work-to-do #T)
+                      (enqueue! uitk-queue (try-to-run weak))
+                      'done
+                      ))))))
+       (weak-set-cdr! (weak-cdr weak) result)
+       result))
+    (lambda (display child-work-code child-idle-code)
+      child-idle-code                  ; Not used by MIT Scheme
+      (let ((file (XConnectionNumber display))
+           (weak (weak-cons child-work-code (weak-cons display #F))))
+       (without-interrupts
+        (lambda ()
+          (register-input-thread-event
+           file uitk-thread (call-if-still-there weak))))))))
+
+(define (destroy-registration registration)
+  (deregister-input-thread-event registration)
+  'OK)
+
+(define remove-from-registry
+  ;; This is called with a file descriptor when the file is closed to
+  ;; remove any registered requests for activity on the file.
+  (in-package (->environment '(runtime thread))
+    (lambda (descriptor)
+      (let loop ((dentry input-registrations))
+       (cond ((null? dentry) 'NOT-FOUND)
+             ((eq? descriptor (dentry/descriptor dentry))
+              (without-interrupts
+               (lambda ()
+                 (remove-from-select-registry! input-registry descriptor)
+                 (let ((prev (dentry/prev dentry))
+                       (next (dentry/next dentry)))
+                   (if prev
+                       (set-dentry/next! prev next)
+                       (set! input-registrations next))
+                   (if next
+                       (set-dentry/prev! next prev)))))
+              'REMOVED)
+             (else (loop (dentry/next dentry))))))))
+
+(define (shut-down-event-server display-number)
+  (remove-from-registry (%XConnectionNumber display-number)))
+\f
+
+;;;Delayed events
+
+;;; Schedule an action to be done later in the UITK thread
+;;; Implementation uses agendas from the 6.001 book
+
+
+(define (after-delay delay action-thunk)       ; delay in secs
+  (let ((now (real-time-clock)))
+    (signal-thread-event
+     uitk-thread
+     (lambda ()
+       ;; Interrupt level
+       (set! more-work-to-do #T)
+       (add-to-agenda! (+ (* delay 1000) now)  ; in msecs
+                      action-thunk
+                      the-agenda)))))
+
+(define (make-agenda)
+  (list '*agenda*))
+
+(define (segments agenda) (cdr agenda))
+(define (first-segment agenda) (car (segments agenda)))
+(define (rest-segments agenda) (cdr (segments agenda)))
+(define (set-segments! agenda segments) (set-cdr! agenda segments))
+(define (empty-segments? agenda)
+  (null? (segments agenda)))
+
+(define (add-to-agenda! time action agenda)
+  (define (add-to-segments! segments)
+    (if (= (segment-time (car segments)) time)
+       (enqueue! (segment-queue (car segments))
+                 action)
+       (let ((rest (cdr segments)))
+         (if (or (null? rest)
+                 (> (segment-time (car rest)) time))
+             (insert-new-time! time action agenda)
+             (add-to-segments! rest)))))
+  (without-interrupts
+   (lambda ()
+     (let ((segs (segments agenda)))
+       (if (null? segs)
+          (insert-new-time! time action agenda)
+          (add-to-segments! segs))))))
+
+
+(define (insert-new-time! time action agenda)
+  (let ((segs (segments agenda))
+       (q (make-queue)))
+    (enqueue! q action)
+    (let ((new-segment (make-time-segment time q)))
+      (if (null? segs)
+         (set-segments! agenda (list new-segment))
+         (set-cdr! segs
+                   (cons new-segment (cdr segs)))))))
+
+(define (read-and-empty-agenda! agenda)
+  (let ((now (real-time-clock)))
+    (define (find-all-events-up-to-now events)
+      (if (empty-segments? agenda)
+         events
+         (let ((current-segment (first-segment agenda)))
+           (if (> (segment-time current-segment) now)
+               events
+               (let ((q (segment-queue current-segment)))
+                 (if (empty-queue? q)
+                     (begin (set-segments! agenda (rest-segments agenda))
+                            (find-all-events-up-to-now events))
+                     (find-all-events-up-to-now
+                      (append events (list (dequeue! q))))))))))
+    (without-interrupts
+     (lambda ()
+       (find-all-events-up-to-now '())))))
+
+(define (empty-agenda? agenda)
+  (without-interrupts
+   (lambda ()
+     (or (empty-segments? agenda)
+        (and (empty-queue? (segment-queue (first-segment agenda)))
+             (null? (rest-segments agenda)))))))
+
+(define (make-time-segment time queue)
+  (cons time queue))
+
+(define (segment-time s) (car s))
+(define (segment-queue s) (cdr s))
+
+(define (current-time agenda)
+  (without-interrupts
+   (lambda ()
+     (and (not (null? (segments agenda)))
+         (segment-time (first-segment agenda))))))
+
+(define (get-interval-to-next-delayed-event)
+  (let ((agenda-time (current-time the-agenda)))
+    (and agenda-time
+        (- agenda-time (real-time-clock)))))
+
+;;; make-enqueueable-thunk is unused.  Part of an alternate
+;;; implementation, where the thunk doesn't hold on to the
+;;; application, so that the application can GC away even if there are
+;;; events scheduled. 
+
+(define make-enqueueable-thunk
+  (let ()
+    (define (try-to-run weak)    
+      (lambda ()
+       (let ((code (weak-car weak)))
+         (if code
+         (debug-print code)
+         (debug-print 'vanished))
+         (if code (code)))))
+    (lambda (thunk)
+      (try-to-run (weak-cons thunk 'IGNORED)))))
+
+\f
+;;;; UITK objects.  We almost never work with bare X objects.
+
+
+
+;;;convert an Xevent (string) to a UITK event structure.  This defines
+;;;the dispatch only.  The actual make-event procedures for the
+;;;various event types are defined in UITK.scm 
+
+(define XEvent-><Event>
+  (let ((X-Event-Converters
+        (make-vector LASTEVENT
+                     (lambda (event)
+                       (decode-unknown-event event
+                         (lambda (type serial sent? display window)
+                           type serial sent? display
+                           (make-unknown-event 'UNUSUAL event window)))))))
+
+    (define (key name)
+      (lambda (e)
+       (decode-key-event e
+          (lambda (type serial sent? display window root subwindow
+                       time x y RootX RootY state keycode SameScreen?)
+           type serial sent? display root subwindow
+           time RootX RootY state keycode SameScreen?
+           (make-point-event name e window (Make-Point X Y))))))
+    (vector-set! X-Event-Converters KeyPress (key 'KEY-PRESS))
+    (vector-set! X-Event-Converters KeyRelease (key 'KEY-RELEASE))
+
+    (define (button name)
+      (lambda (e)
+       (decode-button-event e
+          (lambda (type serial sent? display window root subwindow
+                       time x y RootX RootY state button SameScreen?)
+           type serial sent? display root subwindow
+           time RootX RootY state button SameScreen?
+           (make-point-event name e window (Make-Point X Y))))))
+    (vector-set! X-Event-Converters ButtonPress (button 'BUTTON-PRESS))
+    (vector-set! X-Event-Converters ButtonRelease (button 'BUTTON-RELEASE))
+
+    (define (motion name)
+      (lambda (e)
+       (decode-motion-event e
+        (lambda (type serial sent? display window root subwindow
+                 time x y RootX RootY state IsHint SameScreen?)
+          type serial sent? display window root
+          subwindow time RootX RootY state IsHint SameScreen?
+          (make-point-event name e window (Make-Point X Y))))))
+    (vector-set! X-Event-Converters MotionNotify (motion 'POINTER-MOTION))
+
+    (define (crossing name)
+      (lambda (e)
+       (decode-crossing-event
+        e
+        (lambda (type serial sent? display window root subwindow
+                      time x y RootX RootY mode detail SameScreen?
+                      Focus? state)
+          type serial sent? display root subwindow
+          time RootX RootY mode detail SameScreen? Focus? state
+          (make-point-event name e window (Make-Point X Y))))))
+    (vector-set! X-Event-Converters EnterNotify (crossing 'ENTER))
+    (vector-set! X-Event-Converters LeaveNotify (crossing 'LEAVE))
+
+    ; (vector-set! X-Event-Converters ConfigureNotify ...)
+    ; (vector-set! X-Event-Converters FocusIn ...)
+    ; (vector-set! X-Event-Converters FocusOut ...)
+    ; (vector-set! X-Event-Converters KeymapNotify ...)
+
+    (define (expose-fn type-name)
+      (lambda (e)
+       (decode-expose-event
+        e
+        (lambda (type serial sent? display
+                      window x y width height count)
+          type serial sent? display count width height
+          (make-rectangle-event
+                         type-name e window (Make-Point x y)
+                         width height)))))
+    (vector-set! X-Event-Converters Expose (expose-fn 'EXPOSURE))
+
+    ; (vector-set! X-Event-Converters GraphicsExpose ...)
+    ; (vector-set! X-Event-Converters NoExpose ...)
+    ; (vector-set! X-Event-Converters VisibilityNotify ...)
+    ; (vector-set! X-Event-Converters CreateNotify ...)
+    ; (vector-set! X-Event-Converters DestroyNotify ...)
+    ; (vector-set! X-Event-Converters UnmapNotify ...)
+    ; (vector-set! X-Event-Converters MapNotify ...)
+    ; (vector-set! X-Event-Converters MapRequest ...)
+    ; (vector-set! X-Event-Converters ReparentNotify ...)
+    ; (vector-set! X-Event-Converters ConfigureNotify ...)
+    ; (vector-set! X-Event-Converters ConfigureRequest ...)
+    ; (vector-set! X-Event-Converters GravityNotify ...)
+    ; (vector-set! X-Event-Converters ResizeRequest ...)
+    ; (vector-set! X-Event-Converters CirculateNotify ...)
+    ; (vector-set! X-Event-Converters CirculateRequest ...)
+    ; (vector-set! X-Event-Converters PropertyNotify ...)
+    ; (vector-set! X-Event-Converters SelectionClear ...)
+    ; (vector-set! X-Event-Converters SelectionRequest ...)
+    ; (vector-set! X-Event-Converters SelectionNotify ...)
+    ; (vector-set! X-Event-Converters ColormapNotify ...)
+    ; (vector-set! X-Event-Converters ClientMessage ...)
+    ; (vector-set! X-Event-Converters MappingNotify ...)
+    (lambda (XEvent)
+      ((vector-ref X-Event-Converters (xevent-type XEvent))
+       XEvent))))
+
+;;This places the XEvent in the given string.  It uses the side effect
+;;to avoid allocating a new string and generating garbage in the inner
+;;event processing loop
+
+(define (get-x-event display event-string)
+  (if (zero? (XPending display))
+      #F
+      (XNextEvent! display event-string)))
+
+
+\f
+;;; open a display and return the  numeric hook
+
+(define (open-display)
+  (let ((xdisplay (XOpenDisplay "")))
+    (if (or (and (number? xdisplay) (zero? xdisplay))
+           (and (pair? xdisplay) (number? (cdr xdisplay))
+                (zero? (cdr xdisplay))))
+       (error 'OPEN-DISPLAY "Could not open display")
+       xdisplay)))
+
+(define (string->color display)
+  (lambda (string)
+    (let ((result
+          (XAllocNamedColor display
+                            (XDefaultColormap display
+                                              (XDefaultScreen display))
+                            string)))
+      ;; Result is (Status ScreenColor ExactColor)
+      (if (zero? (car result))
+         #F                            ; Error status
+         (list-ref result 1)))))
+
+
+#| Fonts don't work yet
+(define (string->font display)
+  (lambda (string)
+    (XLoadFont display string)))
+|#
+
+\f
+;;;; Event-sensitive windows.  
+
+(define (Generate-Events! UITKWindow mask)
+  (let ((attributes (XMake-SetWindowAttributes))
+       (window (UITKWindow.XWindow UITKWindow))
+       (display (UITKWindow.XDisplay UITKWindow)))
+    (XSetWindowAttributes-Event_Mask! attributes mask)
+    (XChangeWindowAttributes display window CWEventMask attributes))
+    (let ((result (XGetWindowAttributes display window)))
+      (if (= (list-ref result 0) 0)
+         (error 'GENERATE-EVENTS!
+                "XGetWindowAttributes failed ~A" result)
+         (list-ref result 1))))
+
+
+(define (handler->sensitivity handler)
+  (case (car handler)
+    ((#T) NoEventMask)
+    ((KEY-PRESS) KeyPressMask)
+    ((KEY-RELEASE) KeyReleaseMask)
+    ((BUTTON-PRESS) ButtonPressMask)
+    ((BUTTON-RELEASE) ButtonReleaseMask)
+    ((ENTER) EnterWindowMask)
+    ((CONFIGURE-NOTIFY) StructureNotifyMask)
+    ((LEAVE) LeaveWindowMask)
+    ((POINTER-MOTION) PointerMotionMask)
+     ; (bit-or PointerMotionMask PointerMotionHintMask)
+    ((BUTTON-1-MOTION) Button1MotionMask)
+    ((BUTTON-2-MOTION) Button2MotionMask)
+    ((BUTTON-3-MOTION) Button3MotionMask)
+    ((BUTTON-4-MOTION) Button4MotionMask)
+    ((BUTTON-5-MOTION) Button5MotionMask)
+    ((BUTTON-MOTION) ButtonMotionMask)
+     ; (bit-or ButtonMotionMask PointerMotionHintMask)
+    ((KEYMAP-STATE) KeyMapStateMask)
+    ((EXPOSURE) ExposureMask)
+    ((VISIBITY-CHANGE) VisibilityChangeMask)
+    ((STRUCTURE-NOTIFY) StructureNotifyMask)
+    ;; I don't understand ResizeRedirect or substructure stuff
+    ((FOCUS-CHANGE) FocusChangeMask)
+    ((PROPERTY) PropertyChangeMask)
+    ;; Ignoring colormap and owner grab
+    (else (error 'HANDLER->SENSITIVITY "Unknown event type ~A" (car handler)))
+    ))
+
+(define (bit-or . integers)
+  (bit-string->unsigned-integer
+   (reduce bit-string-or (unsigned-integer->bit-string 32 0)
+          (map (lambda (n) (unsigned-integer->bit-string 32 n))
+               integers))))
+\f
+;;;; UITK level "X" calls.  
+
+#| In UITK, we almost never work with bare X objects.  Rather there
+are two levels of embedding.  The first is the "wrapper" which is used
+for garbage collection (see MIT-Xlib).  This wrapped object is then
+embedded in a UITK structure that bundles together associated
+information.  (For example, a UITKWindow holds both an X window and
+its associated X display.)  Thus, a user-level procedure such as
+Drawline, operates on UITK windows.  It is defined in terms of a lower
+level XDrawline (which operates on wrapped windows) which in tern is
+defined in terms of the X primitive %XDrawline. |#
+
+
+;;;; Graphics contexts
+
+(define (make-simple-graphics-context uitkwindow)
+  (let ((dpy (UITKWindow.XDisplay uitkwindow))
+       (win (UITKWindow.XWindow uitkwindow)))
+    (XCreateGC dpy win 0 (xmake-gcvalues))))
+
+(define (make-colored-graphics-context uitkwindow color-string)
+  (let ((gc (make-simple-graphics-context uitkwindow))
+       (dpy (UITKWindow.XDisplay uitkwindow)))
+    (let ((color ((string->color dpy) color-string)))
+      (if (color? color)
+         (begin
+           (XSetForeground dpy gc color)
+           gc)
+         (error 'make-colored-graphics-context
+                "Can't convert color name to value ~A"
+                color-string)))))
+
+(define (DrawArc uitkwindow gc X Y Width Height angle1 angle2)
+  (XDrawArc (UITKWindow.XDisplay uitkwindow)
+           (UITKWindow.XWindow uitkwindow)
+           gc x y width height angle1 angle2))
+
+(define (DrawLine uitkwindow gc X1 Y1 X2 Y2)
+  (XDrawLine (UITKWindow.XDisplay uitkwindow)
+                 (UITKWindow.XWindow uitkwindow)
+                 gc x1 y1 x2 y2))
+
+(define (DrawRectangle uitkwindow gc X Y Width Height)
+  (XDrawRectangle (UITKWindow.XDisplay uitkwindow)
+                 (UITKWindow.XWindow uitkwindow)
+                 gc x y width height))
+
+
+(define (FillRectangle uitkwindow gc X Y Width Height)
+  (XFillRectangle (UITKWindow.XDisplay uitkwindow)
+                 (UITKWindow.XWindow uitkwindow)
+                 gc x y width height))
+
+(define (FillArc uitkwindow gc X Y Width Height angle1 angle2)
+  (XFillArc (UITKWindow.XDisplay uitkwindow)
+           (UITKWindow.XWindow uitkwindow)
+           gc x y width height angle1 angle2))
+
+(define (ClearArea uitkwindow X Y width height exposures?)
+  (XClearArea (UITKWindow.XDisplay uitkwindow)
+             (UITKWindow.XWindow uitkwindow)
+             x y width height exposures?))
+
+(define (flush-queued-output display)
+  (xflush display))
+
+(define (GetDefaultValue display application-name variable)
+  (XGetDefault display application-name variable))
+
+(define (Decode-Button-Event event receiver)
+  (let ((vect (make-vector 15)))
+    (XDecodeButtonEvent event vect)
+    (apply receiver (vector->list vect))))
+
+(define (Decode-Configure-Event event receiver)
+  (let ((vect (make-vector 13)))
+    (XDecodeConfigureEvent event vect)
+    (apply receiver (vector->list vect))))
+
+(define (Decode-Crossing-Event event receiver)
+  (let ((vect (make-vector 17)))
+    (XDecodeCrossingEvent event vect)
+    (apply receiver (vector->list vect))))
+
+(define (Decode-Expose-Event event receiver)
+  (let ((vect (make-vector 10)))
+    (XDecodeExposeEvent event vect)
+    (apply receiver (vector->list vect))))
+
+(define (Decode-Key-Event event receiver)
+  (let ((vect (make-vector 15)))
+    (XDecodeKeyEvent event vect)
+    (apply receiver (vector->list vect))))
+
+(define (Decode-Motion-Event event receiver)
+  (let ((vect (make-vector 15)))
+    (XDecodeMotionEvent event vect)
+    (apply receiver (vector->list vect))))
+
+(define (Decode-Unknown-Event event receiver)
+  (let ((vect (make-vector 5)))
+    (XDecodeUnknownEvent event vect)
+    (apply receiver (vector->list vect))))
+
+(define (XEvent-Type xevent)
+  (Decode-Unknown-Event xevent
+    (lambda (type . others)
+      others                           ; Ignored
+      type)))
+
+(define (Decode-Window-Attributes attributes receiver)
+  (let ((vect (make-vector 23)))
+    (XDecodeWindowAttributes attributes vect)
+    (apply receiver (vector->list vect))))
+
+(define (Get-Window-Attributes display window receiver)
+  (let ((attributes (list-ref (XGetWindowAttributes display window) 1)))
+    (Decode-Window-Attributes attributes receiver)))
+
+(define (Rectangle->XRegion rectangle)
+  (MakeXRegion (Point.X (UITKRectangle.Offset rectangle))
+              (Point.Y (UITKRectangle.Offset rectangle))
+              (UITKRectangle.Width rectangle)
+              (UITKRectangle.Height rectangle)))
+
+(define (MakeXRegion x y width height)
+  (let ((region (XCreateRegion)))
+    (XUnionRectSpecsWithRegion! x y width height region region)
+    region))
+
+(define (IntersectXRegions x-region-1 x-region-2)
+  (let ((region (XCreateRegion)))
+    (XIntersectRegion! x-region-1 x-region-2 region)
+    region))
+
+(define (UnionXRegions x-region-1 x-region-2)
+  (let ((region (XCreateRegion)))
+    (XUnionRegion! x-region-1 x-region-2 region)
+    region))
+
+(define (CopyXRegion region)
+  (UnionXRegions (XCreateRegion) region))
+
+(define (SubtractXRegions x-region-1 x-region-2)
+  (let ((region (XCreateRegion)))
+    (XSubtractRegion! x-region-1 x-region-2 region)
+    region))
+
+(define (SetClipXRegion window graphics-context XRegion)
+  (XSetRegion (UITKWindow.XDisplay window)
+             graphics-context
+             XRegion))
+\f
+;;;process a mouse drag.
+;;;keep reading motion events and process them 
+;;;stop when there is a button release
+
+;;;This procedure is included here because of the X calls.  
+
+(define (mouse-drag surface on-motion)
+  ;; *** Maybe this should take an "other events handler" ***
+  (let* ((UITKWindow (DrawingSurface.UITKWindow surface))
+        (xdisplay (uitkwindow.xdisplay UITKWindow)))
+    (without-interrupts
+     (lambda ()
+       (let loop ()
+        (let* ((x-event (XNextEvent xdisplay))) ;**blocks?
+          (Decode-Unknown-Event
+           x-event
+           (lambda (type serial sent? display window)
+             serial sent? display window
+             (cond ((eq? type MotionNotify)
+                    (decode-motion-event x-event
+                     (lambda (type serial sent? display window root subwindow
+                              time x y RootX RootY state IsHint SameScreen?)
+                       type serial sent? display window root subwindow
+                       time RootX RootY state IsHint SameScreen?
+                       (on-motion (make-point x y))))
+                    (loop))
+                   ((eq? type ButtonRelease) 'endloop)
+                   (else (loop)))))))))))
+\f
+;;; GC of UITK objects
+;;; this uses the protrction list mechanism implemented in MIT-Xlib
+
+(define uitk-protection-list 'later)
+
+(define (when-unreferenced obj thunk)
+  (add-to-protection-list! uitk-protection-list obj thunk))
+
+(define (finalize-uitk-objects)
+  (clean-lost-protected-objects uitk-protection-list
+                               (lambda (thunk) (thunk))))
+
+(define (finalize-uitk-objects-later)
+  (set! *UITK:GC-HAS-OCCURRED?* #T)
+  ;; (when-idle! finalize-uitk-objects)
+  ;; Handled in the main UITK thread loop.  Also calls the scxl daemon
+  ;; there.
+  )
+
+;;; In generating hash numbers for callbacks, etc., we use a private
+;;; hash table, separate from the system one.
+
+(define *our-hash-table* 'later)
+(define *UITK:GC-HAS-OCCURRED?* #F)
+
+#|
+
+Shutting down the event server may be necessary in UITK even though
+the event server is shut down as soon as the UITK application is
+destroyed, because the applcation and display may vanish on the same
+GC.
+
+We must explicitly destroy the tk-widgets for this display (since Xlib
+doesn't know about them). The TK widgets must be destroyed BEFORE the
+display is closed.
+
+|#
+
+(define (initialize-uitk!)
+  (set! uitk-protection-list (make-protection-list))
+  ;; THIS SHOULD BE PUT BACK WHEN remove-gc-daemon! GETS WRITTEN
+  ;; (remove-gc-daemon! close-lost-displays-daemon)
+  (add-gc-daemon! finalize-uitk-objects-later)
+  (set! uitk-queue (make-queue))
+  (set! idle-queue (make-queue))
+  (set! the-agenda (make-agenda))
+  (make-uitk-thread)
+  (SCXL-Install-XCloseDisplay-Callback shut-down-event-server)
+  (set! *our-hash-table* (hash-table/make 4001))
+  )
+
+(initialize-uitk!)
diff --git a/v7/src/swat/scheme/mit-xlib.scm b/v7/src/swat/scheme/mit-xlib.scm
new file mode 100644 (file)
index 0000000..fa042be
--- /dev/null
@@ -0,0 +1,1097 @@
+;;; -*- Scheme -*-
+
+#| This file defines the SCXL library for interfacing with X.  It is
+similar to Joel Bartlett's Scheme-to-C X library, except that it also
+provides support for cleaning up X objects when the corresponding
+Scheme objects are garbage collected.  The low-level primitives (e.g.
+%XDrawline, %XPending) are Scheme entries to the corresponding X
+library rooutines.  Microcode support for these is defined in the file
+scxl.c.  Users should almost never call these routines directly, but
+instead use the SCXL level routines (e.g., XDrawline, XPending), which
+operate on Scheme objects rather than bare addresses.
+
+We are writing this library for use in UITK (called from mit-xhooks).
+We have tried to organize it so that it can be used as a general X
+library, but this has not been really tested. |#
+
+;;;; Hooks that the library calls -- these should be redefined by
+;;;; systems that use the library
+
+#| FLUSH-DISPLAY-HOOK is called at the end of every SCXL command that
+might require a display flush.  In this file, it is defined as a
+no-op.  The UITK library redefines it to wake the thread responsible
+for handling this stuff. |#
+
+(define (flush-display-hook)
+  '(when not under UITK this does nothing)
+  '(replaced by mit-xhooks))
+
+#| *XCLOSEDISPLAYCALLBACKS* is a list of thunks that should be run
+before a display is closed.  |#
+
+\f
+#| SCXL Primitives operate on Scheme objects that are "wrapped around"
+cells containing the bare numbers that represent X server objects, via
+a call to SCXL-WRAP.  This permits us to perform finalization of X
+objects when the Scheme representatives are garbage-collected using
+the protection list mechanism described below. We use cells containing
+the numbers, rather than the numbers themselves, to permit these "bare
+objects" to be shared (e.g., in protection lists) and mutated (e.g.,
+marked as destroyed).
+
+One exception to the wrapping convention is that X events are
+represented at the lowest level as Scheme strings, and so we needn't
+worry about their garbage collection.  These low-level events (called
+OS-events in UITK) are components in higher-level UITK event structures.
+
+We maintain a list of strong dependents for these objects to represent
+facts like "if you are holding on to this graphics context, then you
+must also hold on to its display."  This prevents the GC from
+prematurely releasing displays (and other objects).
+
+|#
+
+;;;; SCXL Wrapping and Unwrapping
+
+;;; create a wrapped object and (optionally) place it on a protection
+;;; list for GC finalization.  The wrapped object may also have
+;;; additional stuff associated with it (for example, a display will
+;;; contain information used to clean up its windows and fonts)
+;;; The "bare object" kept on the protection list is held in a cell to
+;;; allow for mutation (in particular, to mark things as being destroyed).
+
+(define (SCXL-WRAP protection-list type object strong-dependents . rest)
+  (let* ((cell (make-cell object))
+        (result (make-scxl-wrapper type cell strong-dependents rest)))
+    (if protection-list
+       (add-to-protection-list! protection-list result cell))
+    result))
+
+(define (SCXL-WRAPPED? obj) (scxl-wrapper? obj))
+
+(define (type-check-wrapped-object type object)
+  (if (SCXL-DESTROYED? object)
+      (error "attempt to reference destroyed object" object)
+      (if (and (SCXL-WRAPPED? object)
+              (eq? (scxl-wrapper.type object) type))
+         'OK
+         (error "wrong type wrapped-object" type object))))
+
+(define (is-type-wrapped-object type)
+  (lambda (object)
+    (if (SCXL-DESTROYED? object)
+       (error "attempt to reference destroyed object" object)
+       (and (SCXL-WRAPPED? object)
+            (eq? (scxl-wrapper.type object) type)))))
+
+;;;  (SCXL-UNWRAP
+;;;     (SCXL-WRAP protection-list type object dependents data1 data2 ...)
+;;;        (lambda (object . data-values) ....))
+
+(define (SCXL-UNWRAP wrapped receiver)
+  ;; Note: this doesn't return the strong dependents
+  (apply receiver (cell-contents (scxl-wrapper.wrapped-object wrapped))
+                 (scxl-wrapper.other-stuff wrapped)))
+
+#| A destroyed object is the Scheme representitive of an X object that
+has been destroyed.  It is generally an error to attempt to use a
+destroyed object any SCXL primitive that has the effect of destroying
+a resource on the server will call SCXL-DESTROY! on the corresponding
+Scheme representative |#
+
+(define (SCXL-DESTROY! obj)
+  (if (scxl-destroyed? obj)
+      'done
+      (begin
+       (set-cell-contents! (scxl-wrapper.wrapped-object obj) #F)
+       (set-scxl-wrapper.other-stuff!
+        obj
+        (make-list (length (scxl-wrapper.other-stuff obj))
+                   #F))
+       (set-scxl-wrapper.strong-dependents! obj '()))))
+
+(define (SCXL-DESTROYED? obj)
+  (and (scxl-wrapped? obj)
+       (eq? (cell-contents (scxl-wrapper.wrapped-object obj)) #F)))
+
+#| wrap-with-SCXL-DESTROY! runs some core procedure on a wrapped
+object and then destroys the object.  The procedure will not be run if
+the object is already destroyed.  The procedure may also have
+arguments other than the object to be destroyed.  Nargs is the number
+of args to the core procedure.  Arg-num is the number of the arg that
+is the object to be destroyed. |#
+
+(define (wrap-with-SCXL-DESTROY! nargs arg-num core)
+  ;; (declare (integrable core))
+  (cond ((= nargs 1)
+        (lambda (arg)
+          arg-num                      ; Not used
+          (if (not (SCXL-WRAPPED? arg))
+              (error "not a wrapped object: wrap-with-SCXL-DESTROY" arg))
+          (if (not (SCXL-DESTROYED? arg))
+              (begin
+                (core arg)
+                (SCXL-DESTROY! arg))
+              #T)))
+       ((= nargs 2)
+        (lambda (arg1 arg2)
+          (define interesting-arg (if (= arg-num 0) arg1 arg2))
+          (if (not (SCXL-WRAPPED? interesting-arg))
+              (error "not a wrapped object: wrap-with-SCXL-DESTROY" interesting-arg))
+          (if (not (SCXL-DESTROYED? interesting-arg))
+              (begin (core arg1 arg2)
+                     (SCXL-DESTROY! interestring-arg))
+              #T)))
+       ((= nargs 3)
+        (lambda (arg1 arg2 arg3)
+          (define interesting-arg
+            (cond ((= arg-num 0) arg1)
+                  ((= arg-num 1) arg2)
+                  (else arg3)))
+          (if (not (SCXL-WRAPPED? interesting-arg))
+              (error "not a wrapped object: wrap-with-SCXL-DESTROY" interesting-arg))
+          (if (not (SCXL-DESTROYED? interesting-arg))
+              (begin (core arg1 arg2 arg3)
+                     (SCXL-DESTROY! interestring-arg))
+              #T)))
+       (else
+        (lambda args
+          (define interesting-arg
+            (list-ref args arg-num))
+          (if (not (SCXL-WRAPPED? interesting-arg))
+              (error "not a wrapped object: wrap-with-SCXL-DESTROY" interesting-arg))
+          (if (not (SCXL-DESTROYED? interesting-arg))
+              (begin (apply core args)
+                     (SCXL-DESTROY! interestring-arg))
+              #T)))))
+\f
+;;;; Protection lists
+
+#| A protection list is a list of weak pairs (scheme-object . microcode-object) 
+the list is scanned at GC time so the system can finalize the
+microcode objects whose associated Scheme objects have been GC'd away |#
+
+(define (make-protection-list)
+  (list 'PROTECTION-LIST))
+
+(define (add-to-protection-list! list scheme-object microcode-object)
+  (with-absolutely-no-interrupts
+   (lambda ()
+     (set-cdr! list
+              (cons (weak-cons scheme-object microcode-object)
+                    (cdr list))))))
+
+(define (remove-from-protection-list! list scheme-object)
+  (with-absolutely-no-interrupts
+   (lambda ()
+     (let loop ((associations (cdr list)) (previous list))
+       (if (not (null? associations))
+          (if (eq? scheme-object (weak-pair/car? (car associations)))
+              (set-cdr! previous (cdr associations))
+              (loop (cdr associations) associations)))))))
+
+(define (clean-lost-protected-objects list cleaner)
+  (let ((to-be-cleaned
+        (with-absolutely-no-interrupts
+         (lambda ()
+           (let loop ((result '())
+                      (associations (cdr list))
+                      (previous list))
+             (if (null? associations)
+                 result
+                 (if (weak-pair/car? (car associations))
+                     (loop result (cdr associations) associations)
+                     (let ((next (cdr associations)))
+                       (set-cdr! previous next)
+                       ;; Re-use associations so we don't CONS
+                       (set-car! associations (weak-cdr (car associations)))
+                       (set-cdr! associations result)
+                       (loop associations next previous)))))))))
+    (for-each cleaner to-be-cleaned)))
+
+;;; In general, the microcode objects in SCXL are held in cells.
+;;; clean-lost-celled-objects clears the cell and runs the cleaner on the
+;;; object in the cell.
+
+(define (clean-lost-celled-objects protection-list fn)
+  (clean-lost-protected-objects
+   protection-list
+   (lambda (cell)
+     (let ((obj (atomic-read-and-clear-cell! cell)))
+       (if obj (fn obj))))))
+
+(define (atomic-read-and-clear-cell! cell)
+  (with-absolutely-no-interrupts
+   (lambda ()
+     (let ((result (cell-contents cell)))
+       (set-cell-contents! cell #F)
+       result))))
+
+(define (search-protection-list list predicate)
+  (with-absolutely-no-interrupts
+   (lambda ()
+     (let loop ((associations (cdr list)))
+       (and (not (null? associations))
+           (let ((scheme-object (weak-car (car associations))))
+             (if (and scheme-object (predicate scheme-object))
+                 scheme-object
+                 (loop (cdr associations)))))))))
+
+(define (find-in-protection-list list scheme-element)
+  ;; Returns the pair whose weak-car is scheme-element
+  (with-absolutely-no-interrupts
+   (lambda ()
+     (let loop ((associations (cdr list)))
+       (and (not (null? associations))
+           (let ((scheme-object (weak-car (car associations))))
+             (if (and scheme-object (eq? scheme-element scheme-object))
+                 (car associations)
+                 (loop (cdr associations)))))))))
+
+(define (protection-list-referenced-elements list)
+  ;; Returns a list of the Scheme-visible objects which are still
+  ;; referenced
+  (with-absolutely-no-interrupts
+   (lambda ()
+     (let loop ((associations (cdr list)))
+       (cond ((null? associations)
+             '())
+            ((weak-pair/car? (car associations))
+             (cons (weak-car (car associations))
+                   (loop (cdr associations))))
+            (else
+             (loop (cdr associations))))))))
+
+(define (protection-list-all-elements
+        list dereference-ucode-object-fn)
+  ;; Returns a mixed list: returns the Scheme-visible object if it 
+  ;; is still referenced.  Otherwise returns the associated microcode
+  ;; reference.
+  (with-absolutely-no-interrupts
+   (lambda ()
+     (let loop ((associations (cdr list)))
+       (cond ((null? associations)
+             '())
+            ((weak-pair/car? (car associations))
+             (cons (weak-car (car associations))
+                   (loop (cdr associations))))
+            (else
+             (cons (dereference-ucode-object-fn
+                    (weak-cdr (car associations)))
+                   (loop (cdr associations)))))))))
+
+;;; Protection lists for SCXL objects
+
+(define display-protection-list 'INITIALIZED-LATER)
+(define region-protection-list 'INITIALIZED-LATER)
+
+\f
+;;;; Standard wrapping procedures
+
+;;; A display is wrapped along with protection lists for its windows,
+;;; fonts, etc.  We need to keep track of these because when the
+;;; display is closed, these objects will be destroyed, soe need to
+;;; mark the Scheme representitives as destroyed.
+
+(define (wrap-display xdisplay)
+  (define (find-default-colormaps wrapped-display)
+    (let ((nscreens (%XScreenCount xdisplay)))
+      (let ((vect (make-vector (+ nscreens 1) #F)))
+       (do ((this-screen 0 (+ this-screen 1)))
+           ((= this-screen nscreens) vect)
+         (vector-set! vect this-screen
+                      (wrap-colormap
+                       wrapped-display
+                       (%XDefaultColormap xdisplay this-screen)))))))
+  (let ((me
+        (SCXL-WRAP display-protection-list
+                   'scxl-display
+                   xdisplay
+                   '()                 ; No strong dependents
+                   (make-protection-list) ; Windows
+                   (make-protection-list) ; Fonts (not used now)
+                   (make-protection-list) ; Colormaps
+                   (make-protection-list) ; GCs
+                   #F                  ; Later ...
+                   #F)))               ; Later ...
+    (let ((stuff (scxl-wrapper.other-stuff me)))
+      (set-cdr! (list-tail stuff 3)
+               (list
+                (wrap-window me (%XDefaultRootWindow xdisplay))
+                (Find-Default-Colormaps me))))
+    me))
+
+(define (scxl-display? object)
+  (and (SCXL-WRAPPED? object)
+       (eq? (scxl-wrapper.type object) 'scxl-display)))
+
+(define (unwrap-display dsp receiver)
+  ;; Anyone who uses this must know the order of the protection lists
+  ;; within a display object!
+  (type-check-wrapped-object 'scxl-display dsp)
+  (SCXL-UNWRAP dsp receiver))
+
+(define (display/display user-visible-display)
+  (type-check-wrapped-object 'scxl-display user-visible-display)
+  (SCXL-UNWRAP user-visible-display
+              (lambda (display window-list font-list colormap-list gc-list
+                               default-root-window default-colormaps)
+                window-list font-list colormap-list gc-list
+                default-root-window default-colormaps ; Not used
+                display)))
+
+(define (display/window-list user-visible-display)
+  (type-check-wrapped-object 'scxl-display user-visible-display)
+  (SCXL-UNWRAP user-visible-display
+              (lambda (display window-list font-list colormap-list gc-list
+                               default-root-window default-colormaps)
+                display font-list colormap-list gc-list
+                default-root-window default-colormaps ; Not used
+                window-list)))
+
+(define (display/font-list user-visible-display)
+  (type-check-wrapped-object 'scxl-display user-visible-display)
+  (error "display/font-list: Fonts aren't implemented yet."))
+
+(define (display/colormap-list user-visible-display)
+  (type-check-wrapped-object 'scxl-display user-visible-display)
+  (SCXL-UNWRAP user-visible-display
+              (lambda (display window-list font-list colormap-list gc-list
+                               default-root-window default-colormaps)
+                display window-list font-list gc-list
+                default-root-window default-colormaps ; Not used
+                colormap-list)))
+
+(define (display/gc-list user-visible-display)
+  (type-check-wrapped-object 'scxl-display user-visible-display)
+  (SCXL-UNWRAP user-visible-display
+              (lambda (display window-list font-list colormap-list gc-list
+                               default-root-window default-colormaps)
+                display window-list font-list colormap-list
+                default-root-window default-colormaps ; Not used
+                gc-list)))
+
+(define (display/screen/default-color-map user-visible-display)
+  (type-check-wrapped-object 'scxl-display user-visible-display)
+  (SCXL-UNWRAP user-visible-display
+              (lambda (display window-list font-list colormap-list gc-list
+                               default-root-window default-colormaps)
+                display window-list font-list colormap-list gc-list
+                default-root-window    ; Not used
+                default-colormaps)))
+
+(define (display/default-root-window user-visible-display)
+  (type-check-wrapped-object 'scxl-display user-visible-display)
+  (SCXL-UNWRAP user-visible-display
+              (lambda (display window-list font-list colormap-list gc-list
+                               default-root-window default-colormaps)
+                display window-list font-list colormap-list gc-list
+                default-colormaps ; Not used
+                default-root-window)))
+
+;;; alternate name
+;;; in general, these ->names are used to extract the bare X pointers
+;;; from the SCXL objects
+(define ->xdisplay display/display)
+
+;;; notice that windows, fonts, etc. are wrapped with a protection
+;;; list for their associated displays.  We are not making a separate
+;;; protection list for windows, because we aren't keeping track of
+;;; the window hierarchy pointers that X maintains.  Therefore we
+;;; cannot safely destroy a window just because its Scheme
+;;; representitive disappears.  On the other other hand, when the
+;;; display is closed, all the wondows go away, so we destroy their
+;;; Scheme represeatitives.
+
+(define (wrap-window display window)
+  (SCXL-WRAP (display/window-list display)
+            'scxl-window
+            window
+            display))                  ; Strong dependent
+
+(define (window/window user-visible-window)
+  (type-check-wrapped-object 'scxl-window user-visible-window)
+  (SCXL-UNWRAP user-visible-window (lambda (window) window)))
+
+(define ->xwindow window/window)
+
+#| Fonts aren't implemented yet.  They have to be protected both on
+   the display and the graphics context to correctly reflect the
+   pointers maintained by X.
+
+(define (wrap-font display font)
+  (SCXL-WRAP (display/font-list display) 'scxl-font
+            font
+            display))                  ; Strong dependent
+
+(define font? (is-type-wrapped-object 'scxl-font))
+
+(define (font/font font)
+  (type-check-wrapped-object 'scxl-font font)
+  (SCXL-UNWRAP font (lambda (font) font)))
+
+(define ->xfont font/font)
+
+|#
+
+;;; NOTE: GCs maintain a lot of state in C.  Their Scheme shadows
+;;; should have strong dependencies on these things, like the XRegion,
+;;; Foreground and Background Pixel, font, etc.
+
+(define (wrap-graphics-context display gc)
+  (SCXL-WRAP (display/gc-list display)
+            'scxl-graphics-context
+            GC
+            display                    ; Strong dependent
+            (make-cell #F)))           ; No region
+
+(define (gc/gc gc)
+  (type-check-wrapped-object 'scxl-graphics-context gc)
+  (SCXL-UNWRAP gc (lambda (gc region-cell) region-cell gc)))
+
+(define (gc/region gc)
+  (type-check-wrapped-object 'scxl-graphics-context gc)
+  ;; Note gc/region returns a wrapped object
+  (cell-contents (SCXL-UNWRAP gc
+                             (lambda (gc region-cell)
+                               gc      ; Unused
+                               region-cell))))
+
+(define (set-gc/region! gc region)
+  (type-check-wrapped-object 'scxl-graphics-context gc)
+  (set-cell-contents!
+   (SCXL-UNWRAP gc
+               (lambda (gc region-cell)
+                 gc                    ; Unused
+                 region-cell))
+   region)
+  'MUNGED)
+
+(define (->xgc user-visible-gc)
+  (type-check-wrapped-object 'scxl-graphics-context user-visible-gc)
+  (cond ((SCXL-WRAPPED? user-visible-gc)
+        (gc/gc user-visible-gc))
+       ((number? user-visible-gc) user-visible-gc)
+       (else (error "->XGc: not a gc" user-visible-gc))))
+
+(define (wrap-colormap display colormap)
+  (SCXL-WRAP (display/colormap-list display)
+            'scxl-colormap
+            colormap
+            display                    ; Strong dependent
+            (make-protection-list)))   ; Pixel list
+
+(define (colormap/colormap colormap)
+  (type-check-wrapped-object 'scxl-colormap colormap)
+  (SCXL-UNWRAP colormap
+              (lambda (colormap pixels)
+                pixels                 ; Not used
+                colormap)))
+
+(define (colormap/pixel-list colormap)
+  (type-check-wrapped-object 'scxl-colormap colormap)
+  (SCXL-UNWRAP colormap
+              (lambda (colormap pixels)
+                colormap               ; Not used
+                pixels)))
+
+(define ->xcolormap colormap/colormap)
+
+(define (wrap-pixel display colormap pixel)
+  (SCXL-WRAP (colormap/pixel-list colormap)
+            'scxl-color
+            pixel
+            (list display colormap)))  ; Strong dependents
+
+(define color? (is-type-wrapped-object 'scxl-color))
+
+(define (pixel/pixel pixel)
+  (type-check-wrapped-object 'scxl-color pixel)
+  (SCXL-UNWRAP pixel (lambda (pixel) pixel)))
+
+(define ->xpixel pixel/pixel)
+
+(define (wrap-region region)
+  (SCXL-WRAP region-protection-list
+            'scxl-region
+            region
+            #F))                       ; No strong dependents
+
+(define (region/region region)
+  (type-check-wrapped-object 'scxl-region region)
+  (SCXL-UNWRAP region (lambda (region) region)))
+
+(define ->xregion region/region)
+\f
+#|  *****************************
+Debugging kludge
+This will print a whole lot of crap.  Break glass in case of emergency only.
+
+(define D_EVAL                 0)
+(define D_HEX_INPUT            1)
+(define D_FILE_LOAD            2)
+(define D_RELOC                        3)
+(define D_INTERN               4)
+(define D_CONT                 5)
+(define D_PRIMITIVE            6)
+(define D_LOOKUP               7)
+(define D_DEFINE               8)
+(define D_GC                   9)
+(define D_UPGRADE              10)
+(define D_DUMP                 11)
+(define D_TRACE_ON_ERROR       12)
+(define D_PER_FILE             13)
+(define D_BIGNUM               14)
+(define D_FLUIDS               15)
+
+(define *spew-crap-out?* #T)
+
+
+(define check-space
+  (let ((get-status (make-primitive-procedure 'gc-space-status))
+       (set-debug-flags! (make-primitive-procedure 'set-debug-flags!)))
+    (lambda ()
+      (let* ((status (get-status))
+            (free (vector-ref status 5))
+            (top (vector-ref status 6))
+            (space (- top free)))
+       (write-line `(space ,space))
+       (if (< space 2800000)
+           (if *spew-crap-out?*
+               (with-absolutely-no-interrupts
+                (lambda ()
+                  (debug-print 'space-low!)
+                  (set-debug-flags! D_EVAL #T)
+                  (set! *spew-crap-out?* #F)
+                  'OK))
+               (begin
+                 (debug-print 'end 'print)
+                 (set-debug-flags! D_EVAL #F)
+                 'OK)))))))
+
+*****************************************|#
+
+
+#| Finalization of SCXL objects.  In UITK, this is scheduled to be
+done by the UITK thread.  Other systems may schedule it to be done
+differently, or done immediately.  If this is scheduled in the GC, the
+assumptions about (not) interrupt locking the protection lists may be
+incorrect.  WATCH OUT!
+
+Note that this daemon has to call the lowest level % primitives rather
+than the wrapped version for lost objects in the cases where the
+wrappers have been lost and we have only the X pointers remianing.
+|#
+
+(define (close-lost-displays-daemon)
+  ;; Step one: clean up any displays that have GCed away
+  (clean-lost-celled-objects display-protection-list XCloseDisplayByNumber)
+  ;; Step two: clean up any regions that have GCed away
+  (clean-lost-celled-objects region-protection-list %XDestroyRegion)
+  ;; Step three: run through all displays that we DO have
+  ;; handles on, and release fonts/colomaps/gcs that we do
+  ;; NOT have handles on.
+  ;; *NOTE*: We do >>not<< close windows that we've lost handles on,
+  ;; because X maintains gazillions of pointers to them that we aren't
+  ;; tracking.
+  (for-each
+   cleanup-vanished-objects-for-display
+   (protection-list-referenced-elements display-protection-list)))
+
+(define (cleanup-vanished-objects-for-display display)
+  (if (not (SCXL-DESTROYED? display))
+      (unwrap-display
+       display
+       (lambda (display-number windows fonts colormaps gcs
+                              default-root-window default-colormaps)
+        windows fonts default-root-window default-colormaps ; Don't GC these!
+        (clean-lost-celled-objects
+         colormaps
+         (lambda (colormap-number)
+           (%XFreeColorMap display-number colormap-number)))
+        #| ****************************************
+        By rights, we should release unused colors from all
+        of the allocated color maps *and* the default color
+        map of each screen.  However, this would require us
+        to keep track of the foreground and background
+        color in graphics contexts since X keeps these
+        pointers for us.
+         When we fix this, it should use the protection list iterators
+        (if colormaps
+            (do ((associations (cdr colormaps) (cdr associations)))
+                ((null? associations))
+              (let* ((colormap (weak-car (car associations)))
+                     (pixels (colormap/pixel-list colormap)))
+                (if (not (null? pixels))
+                    (clean-lost-celled-objects
+                     pixels
+                     (lambda (pixel)
+                       (%XFreeColor display-number **doens't work
+                                    (->colormap colormap)
+                                    (-> pixel pixel))))))))
+        ******************************************** |#
+        (clean-lost-celled-objects
+         gcs
+         (lambda (gc-number) (%XFreeGC display-number gc-number)))))))
+
+
+\f
+;;;; Primitives written in C
+
+(define-primitives                     ; X Operations
+  (%XAllocNamedColor 5)
+  (%XChangeWindowAttributes 4)
+  (%XCheckMaskEvent 3)
+  (%XClearArea 7)
+  (%XClearWindow 2)
+  (%XCloseDisplay 1)
+  (%XConnectionNumber 1)
+  (%XCreateGC 4)
+  (%XCreateRegion 0)
+  (%XCreateSimpleWindow 9)
+  (%XDecodeButtonEvent 2)
+  (%XDecodeConfigureEvent 2)
+  (%XDecodeCrossingEvent 2)
+  (%XDecodeExposeEvent 2)
+  (%XDecodeKeyEvent 2)
+  (%XDecodeMotionEvent 2)
+  (%XDecodeUnknownEvent 2)
+  (%XDecodeWindowAttributes 2)
+  (%XDecodeXColor 2)
+  (%XDefaultColormap 2)
+  (%XDefaultRootWindow 1)
+  (%XDefaultScreen 1)
+  (%XDestroyRegion 1)
+  (%XDestroyWindow 2)
+  (%XDrawArc 9)
+  (%XDrawLine 7)
+  (%XDrawRectangle 7)
+  (%XFillArc 9)
+  (%XFillRectangle 7)
+  (%XFlush 1)
+  (%XFreeColormap 2)
+  (%XFreeGC 2)
+  (%XGetDefault 3)
+  (%XGetWindowAttributes 3)
+  (%XInitSCXL! 0)
+  (%XIntersectRegion 3)
+  (%XLoadFont 2)
+  (%XMapWindow 2)
+  (%XNextEvent 2)
+  (%XOpenDisplay 1)
+  (%XPending 1)
+  (%XPutBackEvent 2)
+  (%XQueryPointer 3)
+  (%XQueryTree 2)
+  (%XScreenCount 1)
+  (%XSetForeground 3)
+  (%XSetFunction 3)
+  (%XSetRegion 3)
+  (%XStoreName 3)
+  (%XSubtractRegion 3)
+  (%XSync 2)
+  (%XSynchronize 2)
+  (%XTranslateCoordinates 6)
+  (%XUnionRegion 3)
+  (%XUnionRectSpecsWithRegion! 6)
+  (%XUnloadFont 2))
+
+(define-primitives                     ; X Data Structure constructors
+  (%XMake-Color 0)
+  (%XMake-Event 0)
+  (%XMake-GCValues 0)
+  (%XMake-GetWindowAttributes 0)
+  (%XMake-SetWindowAttributes 0)
+  (%XMake-Window 0)                    ; Hold a window identifier
+  (%XMake-XY 0))                       ; Hold an X/Y value
+
+(define-primitives                     ; X data structure mutators
+  (%XSetWindowAttributes-Event_Mask! 2))
+\f
+(define (XColor.Pixel xcolor)
+  (let ((components (make-vector 5)))
+    ;; Returns #(pixel, red, green, blue, flags)
+    (XDecodeXColor xcolor components)
+    (vector-ref components 0)))
+
+;;;; SCXL-level calls to the X primitives
+
+(define (XAllocNamedColor display colormap color-string)
+  ;; Returns list: (Status Color-Allocated Exact-Color)
+  ;; where color-allocated and exact-color are each the cons of a
+  ;; wrapped pixel and a string that is the direct coding of the X
+  ;; color structure.
+  (let ((allocated (%XMake-Color))
+       (exact (%XMake-Color)))
+    (let ((result
+          (%XAllocNamedColor (->XDisplay display)
+                             (->XColormap colormap)
+                             color-string
+                             allocated
+                             exact)))
+      (list result
+           (wrap-pixel display colormap (XColor.Pixel allocated))
+           (wrap-pixel display colormap (XColor.Pixel exact))))))
+
+(define (XChangeWindowAttributes display window mask attributes)
+  (%XChangeWindowAttributes (->XDisplay display)
+                           (->XWindow window)
+                           mask
+                           attributes)
+  (flush-display-hook))
+
+(define (XCheckMaskEvent!? display event-mask returned-event)
+  (%XCheckMaskEvent (->XDisplay display)
+                   event-mask
+                   returned-event))
+
+(define (XClearArea display window x y width height exposures?)
+  (%XClearArea (->XDisplay display)
+              (->XWindow window)
+              x y width height exposures?)
+  (flush-display-hook))
+
+(define (XClearWindow display window)
+  (%XClearWindow (->XDisplay display)
+                (->XWindow window))
+  (flush-display-hook))
+
+#| XCloseDisplay closes the display and destroys the Scheme shadows of
+the associated server objects, and closes tk objects (which aren't
+automatically closed by X).  In UITK, XCloseDisplay is NEVER called.  The
+lower-level XCloseDisplayByNumber is called from the GC.  Anyone who
+writes programs that call XCloseDisplay needs to think carefully about the
+dependencies (on both the Scheme and C side) of objects and processes
+involved in calling destroy operations.  Tread carefully here. |#
+
+(define XCloseDisplay
+  (wrap-with-SCXL-DESTROY!
+   1 0
+   (lambda (dsp)
+     (define (kill-protected-objects protection-list)
+       (for-each SCXL-DESTROY!
+                (protection-list-referenced-elements protection-list)))
+     ;;SCXL-destroy the Scheme representitives of the X objects associated
+     ;;to the display (which are killed by X when the
+     ;;display is closed).
+     (unwrap-display
+      dsp
+      (lambda (xdisplay windows fonts colormaps gcs
+                       defaultwindow defaultcolormaps)
+       defaultwindow defaultcolormaps  ; Should be, but aren't, used
+       (for-each kill-protected-objects (list windows fonts colormaps gcs))
+       ;;do someting about the default window and colormap
+       (XCloseDisplayByNumber xdisplay))))))
+
+#| *********************************************
+
+XCloseDisplayByNumber is scheduled to be called by the gc-daemon when
+all references to the Scheme display have been lost.
+
+Closing the display will close the (C) windows, GC's, fonts, etc.  But
+we do NOT need to destroy their Scheme-side reflections, because we
+have arranged for these to point to the display.  Therefore, they
+cannot be around if the Scheme display object has been lost.
+
+*XclosedisplayCallBacks is a list of thinks that should be called when
+a display is closed.  In UITK, for example, we need to 
+shut down the even server for the display.
+
+  ************************************************ |#
+
+(define *XCloseDisplayCallBacks* '())
+
+(define (XCloseDisplayByNumber display-number)
+  (for-each (lambda (proc) (proc display-number))
+           *XCloseDisplayCallBacks*)
+  (%XCloseDisplay display-number))
+
+(define (SCXL-Install-XCloseDisplay-Callback proc)
+  (set! *XCloseDisplayCallbacks*
+       (cons proc *XCloseDisplayCallBacks*)))
+
+(define (XConnectionNumber display)
+  (%XConnectionNumber (->XDisplay display)))
+
+(define (XCreateGC display window mask gcvalues)
+  (wrap-graphics-context display
+                        (%XCreateGC (->XDisplay display)
+                                    (->XWindow window)
+                                    mask
+                                    gcvalues)))
+
+(define (XCreateRegion)
+  (wrap-region (%XCreateRegion)))
+
+(define (XCreateSimpleWindow
+        display parent x y width height
+        border-width border-pixel background-pixel)
+  (wrap-window display 
+              (%XCreateSimpleWindow (->XDisplay display)
+                                    (->XWindow parent)
+                                    x y width height border-width
+                                    (->XPixel border-pixel)
+                                    (->XPixel background-pixel))))
+  
+(define (XDecodeButtonEvent event vect)
+  (%XDecodeButtonEvent event vect))
+
+(define (XDecodeConfigureEvent event vect)
+  (%XDecodeConfigureEvent event vect))
+
+(define (XDecodeCrossingEvent event vect)
+  (%XDecodeCrossingEvent event vect))
+
+(define (XDecodeExposeEvent event vect)
+  (%XDecodeExposeEvent event vect))
+
+(define (XDecodeKeyEvent event vect)
+  (%XDecodeKeyEvent event vect))
+
+(define (XDecodeMotionEvent event vect)
+  (%XDecodeMotionEvent event vect))
+
+(define (XDecodeUnknownEvent event vect)
+  (%XDecodeUnknownEvent event vect))
+
+(define (XDecodeWindowAttributes attributes vect)
+  (%XDecodeWindowAttributes attributes vect))
+
+(define (XDecodeXColor XColor vect)
+  (%XDecodeXColor xcolor vect))
+
+(define (XDefaultColormap display screen)
+  (vector-ref (display/screen/default-color-map display) screen))
+
+(define (XDefaultRootWindow display)
+  (display/default-root-window display))
+
+;;; Screens are not wrapped -- they are just integers, because there
+;;; is no real resource that is being allocated here.
+
+(define (XDefaultScreen display)
+  (%XDefaultScreen (->XDisplay display)))
+
+(define XDestroyRegion
+  (wrap-with-SCXL-DESTROY! 1 0
+    (lambda (region)
+      (%XDestroyRegion (->XRegion region)))))
+
+(define XDestroyWindow
+  (wrap-with-SCXL-DESTROY! 2 1
+    (lambda (display window)
+      (%XDestroyWindow (->XDisplay display) (->XWindow window)))))
+
+(define (XDrawArc display window graphics-context
+                 x y width height angle1 angle2)
+  (%XDrawArc (->XDisplay display)
+            (->XWindow window)
+            (->XGC graphics-context)
+            x y width height angle1 angle2)
+  (flush-display-hook))
+
+(define (XDrawLine display window graphics-context x1 y1 x2 y2)
+  (%XDrawLine (->XDisplay display)
+             (->XWindow window)
+             (->XGC graphics-context)
+             x1 y1 x2 y2)
+  (flush-display-hook))
+
+(define (XDrawRectangle display window graphics-context x y width height)
+  (%XDrawRectangle (->XDisplay display)
+                  (->XWindow window)
+                  (->XGC graphics-context)
+                  x y width height)
+  (flush-display-hook))
+
+(define (XFillArc display window graphics-context
+                 x y width height angle1 angle2)
+  (%XFillArc (->XDisplay display)
+            (->XWindow window)
+            (->XGC graphics-context)
+            x y width height angle1 angle2)
+  (flush-display-hook))
+
+(define (XFillRectangle display window graphics-context x y width height)
+  (%XFillRectangle (->XDisplay display)
+                  (->XWindow window)
+                  (->XGC graphics-context)
+                  x y width height)
+  (flush-display-hook))
+
+(define (XFlush display)
+  (%XFlush (->XDisplay display)))
+
+;;; When we free a colormap, we have to destroy the Scheme
+;;; representitives of the pixels allocated in it.
+
+(define XFreeColormap
+  (wrap-with-SCXL-DESTROY! 2 1
+    (lambda (display colormap)
+      (%XFreeColormap (->XDisplay display) (->XColormap colormap))
+      (if (SCXL-WRAPPED? font)
+         (for-each SCXL-DESTROY!
+                   (protection-list-referenced-elements
+                    (colormap/pixel-list colormap)))))))
+
+(define XFreeGC
+  (wrap-with-SCXL-DESTROY! 2 1
+   (lambda (display gc)
+     (%XFreeGC (->XDisplay display) (->XGC gc)))))
+
+;;; XGetDefault returns a bare X pointer.  Anyone who calls it needs to know
+;;; what is expected and wrap it at the next level up.
+
+(define (XGetDefault display program option)
+  (%XGetDefault (->XDisplay display) program option))
+
+(define (XGetWindowAttributes display window)
+  ;; Returns a list of (Status Attributes)
+  (let ((attributes (%XMake-GetWindowAttributes)))
+    (list (%XGetWindowAttributes (->XDisplay display)
+                                (->XWindow window)
+                                attributes)
+         attributes)))
+
+(define (XIntersectRegion! source-1 source-2 dest)
+  (%XIntersectRegion
+   (->XRegion source-1)
+   (->XRegion source-2)
+   (->XRegion dest)))
+
+(define (XLoadFont display name)
+  (wrap-font display
+            (%XLoadFont (->Xdisplay display) name)))
+
+(define (XMapWindow display window)
+  (%XMapWindow (->XDisplay display) (->XWindow window))
+  (flush-display-hook))
+
+(define (XNextEvent display)
+  (let ((event (%XMake-Event)))
+    (%XNextEvent (->XDisplay display) event)
+    event))
+
+;;;This is a version that doesn't build up garbage
+(define (XNextEvent! display event-string)
+  (%XNextEvent (->XDisplay display) event-string)
+  event-string)
+
+;;;This is a flag that forces the X server into synchronous mode.  It is
+;;;useful for debugging, but slows things down alot.
+
+(define *Synchronizing?* #f)
+
+(define (XOpenDisplay string)
+  (wrap-display
+   (let ((result (%XOpenDisplay string)))
+     (%XSynchronize result *Synchronizing?*)
+     result)))
+
+(define (XPending display)
+  (%XPending (->XDisplay display)))
+
+(define (XPutBackEvent display event)
+  (%XPutBackEvent (->XDisplay display) event))
+
+(define (XQueryTree display window)
+  (%XQueryTree (->XDisplay display)
+              (->XWindow window)))
+
+(define (XQueryPointer display window)
+  (let ((result (make-vector 8)))
+    (%XQueryPointer (->XDisplay display)
+                   (->XWindow window)
+                   result)
+    result))
+
+(define (XScreenCount display)
+  (%XScreenCount (->XDisplay display)))
+
+(define (XSetForeground display graphics-context pixel-value)
+  (%XSetForeground (->XDisplay display)
+                  (->XGC graphics-context)
+                  (->XPixel pixel-value))
+  (flush-display-hook))
+
+
+(define (XSetFunction display graphics-context function-number)
+  (%XSetFunction (->XDisplay display)
+                (->XGC graphics-context)
+                function-number))
+
+(define (XSetRegion display graphics-context region)
+  (%XSetRegion (->XDisplay display)
+              (->XGC graphics-context)
+              (->XRegion region))
+  (if (SCXL-WRAPPED? graphics-context)
+      (set-gc/region! graphics-context region)))
+
+(define (XStoreName display window title)
+  (%XStoreName (->XDisplay display)
+              (->XWindow window)
+              title))
+
+(define (XSubtractRegion! source-1 source-2 dest)
+  (%XSubtractRegion
+   (->XRegion source-1)
+   (->XRegion source-2)
+   (->XRegion dest)))
+
+(define (XTranslateCoordinates display from-window to-window x y)
+  ;; Returns a vector (Status X Y Child-Window)
+  (let ((return-vector (make-vector 4)))
+    (%XTranslateCoordinates (->XDisplay display)
+                           (->XWindow from-window)
+                           (->XWindow to-window)
+                           x y return-vector)
+    return-vector))
+
+(define (XUnionRegion! source-1 source-2 dest)
+  (%XUnionRegion
+   (->XRegion source-1)
+   (->XRegion source-2)
+   (->XRegion dest)))
+
+(define (XUnionRectSpecsWithRegion! x y width height in-region out-region)
+  (%XUnionRectSpecsWithRegion! x y width height
+                              (->XRegion in-region)
+                              (->XRegion out-region)))
+
+(define XUnloadFont
+  (wrap-with-SCXL-DESTROY! 2 1
+    (lambda (display font)
+      (%XUnloadFont (->XDisplay display) (->XFont font)))))
+
+;;;; Constructors
+
+(define (XMake-Color) (%XMake-Color))
+(define (XMake-Event) (%XMake-Event))
+(define (XMake-GCValues) (%XMake-GCValues))
+(define (XMake-SetWindowAttributes) (%XMake-SetWindowAttributes))
+
+;;;; Mutators
+
+(define (XSetWindowAttributes-Event_Mask! object value)
+  (%XSetWindowAttributes-Event_Mask! object value))
+
+;;;; Auxilliary
+
+(define (XCopy-Event event)
+  (string-copy event))
+\f
+(define (initialize-scxl!)
+  (%XInitSCXL!)
+  (set! display-protection-list (make-protection-list))
+  (set! region-protection-list (make-protection-list))
+  ;; Warning: UITK (in mit-xhooks.scm) knows that
+  ;; close-lost-displays-daemon is *the* daemon associated with scxl.
+  ;; It arranges to run it in another thread and removes it from the
+  ;; gc-daemon list.
+  ;;
+  ;; THIS SHOULD BE PUT BACK!
+  ;; (add-gc-daemon! close-lost-displays-daemon)
+  )
+
+(initialize-scxl!)
+
diff --git a/v7/src/swat/scheme/other/btest.scm b/v7/src/swat/scheme/other/btest.scm
new file mode 100644 (file)
index 0000000..ac41efb
--- /dev/null
@@ -0,0 +1,960 @@
+;;; -*- Scheme -*-
+
+;; Test direct to TCL
+
+(define (do* args)
+  (tcl-global-eval *the-default-application* (car args) (cdr args)))
+
+(define (many arg-list) (for-each do* arg-list))
+
+;; Test the Button widget
+
+(define but1)
+(define (btest1)
+  (set! but1 (make-button '(-text "Hello Jim"
+                           -foreground blue -activeforeground black
+                           -background yellow -activebackground orange)))
+  (set-callback! but1
+                (lambda ()
+                  (display "Ouch!")
+                  (newline)))
+  (swat-open but1 '-title "Test Scheme Application"))
+
+(define v1)
+(define v2)
+(define v3)
+(define h1)
+(define h2)
+(define h3)
+(define leftframe)
+(define rightframe)
+(define frame)
+(define (btest2)
+  (set! v1 (make-button '(-text "Hello Jim"
+                         -foreground blue
+                         -activeforeground "hot pink")))
+  (set! v2 (make-button '(-text "Goodbye and Good Luck")))
+  (set! v3 (make-button '(-text "Jane")))
+  
+  (set! leftframe (make-vbox v1 v2 v3))
+  
+  (set! h1 (make-button '(-text "Button 1")))
+  (set! h2 (make-button '(-text "Button 2")))
+  (set! h3 (make-button '(-text "Button 3")))
+  
+  (set! rightframe (make-hbox h1 h2 h3))
+  
+  (set! frame (make-hbox leftframe rightframe))
+  
+  (set-callback! v1 (lambda ()
+                     (display "First button in Vbox")
+                     (newline)))
+  (set-callback! h1
+                (lambda ()
+                  (display "First button in Hbox")
+                  (newline)))
+  (swat-open frame '-title "Test Scheme Application"))
+
+
+(define but3)
+(define (btest3)
+  (set! but3 (make-button '(-text "hello there" -background yellow)))
+  (set-callback!
+   but3
+   (lambda ()
+     (after-delay 2
+                 (lambda ()
+                   (ask-widget but3 '(configure -background red))))
+     (after-delay 4
+                 (lambda ()
+                   (ask-widget but3 '(configure -background yellow))))))
+  (swat-open but3 '-title "btest3"))
+
+(define (show-window-attributes uitkwindow)
+  (let ((attributes (list-ref (XGetWindowAttributes
+                              (uitkwindow.xdisplay uitkwindow)
+                              (uitkwindow.xwindow uitkwindow)) 1)))
+    (Decode-Window-Attributes attributes
+      (lambda (x y width height border_width depth visual root class
+              bit_gravity win_gravity backing_store backing_planes
+              backing_pixel save_under colormap map_installed
+              map_state all_event_masks your_event_mask
+              do_not_propogate_mask override_redirect screen)
+       depth visual root class bit_gravity win_gravity backing_store
+       backing_planes backing_pixel save_under colormap map_installed
+       map_state override_redirect screen
+       (write-line (list 'x x 'y y 'width width
+                         'height height 'b-width border_width))
+       (write-line (list 'all (number->string all_event_masks 16)
+                         'event (number->string your_event_mask 16)
+                         'do-not-prop do_not_propogate_mask))))))
+
+(define scale1)
+(define (stest1)
+  (set! scale1 (make-scale '(-from 0 -to 99
+                            -foreground blue -activeforeground red
+                            -background yellow -length 500 -orient horiz)))
+#|  (set-callback! scale1
+                (lambda (value)
+                  (display (list "Ouch!" value))
+                  (newline)))
+|#
+  (swat-open scale1 '-title "Scale Test Scheme Application"))
+
+(define scale2)
+(define (stest2)
+  (set! scale2 (make-scale '(-from 0 -to 99 -length 500 -orient horiz
+                            -foreground blue -activeforeground red
+                            -background yellow)))
+  (set-callback! scale2 (lambda (value) 'ignore))
+  (swat-open scale2 '-title "Scale Test Scheme Application"))
+
+(define e)
+(define (etest1)
+  (set! e (make-entry '(-width 30 -relief sunken
+                       -foreground blue -background yellow)))
+  (swat-open e '-title "Entry Test"))
+
+(define sb)
+(define (sbtest1)
+  (set! sb (make-scrollbar '(-width 20 -orient vertical -relief sunken
+                            -foreground blue -background yellow)))
+  (swat-open sb '-title "Scrollbar Test"))
+
+(define (sbtest2)
+  (let* ((scroll (make-scrollbar '(-width 30 -orient horizontal -relief sunken
+                                  -foreground blue -background yellow)))
+        (entry (make-entry '(-width 45)))
+        (me (make-vbox entry scroll)))
+    (swat-open me '-title "Scrollbar Test")
+    me))
+
+(define (suicide-button)
+  (let ((sbut (make-button '(-text "Kill Me"))))
+    (set-callback! sbut
+                  (lambda ()
+                    (swat-close sbut)))
+  (swat-open sbut)))
+
+
+;;;scheduling the update for when-idle makes things a littel better, but not much.
+;;;GC still interferes
+
+(define (sbtest3)
+  ;; A "better" version is in sbtest4
+  (let ((app (make-application "Play")))
+    (let ((hscroll (make-scrollbar '(-width 20 -orient horizontal)))
+         (vscroll (make-scrollbar '(-width 20 -orient vertical)))
+         (big (make-rect 500 600 "blue"))
+         (small (make-oval 30 40 "yellow"))
+         (scrolly 0)
+         (scrollx 0)
+         (x 0)
+         (y 0))
+      (define (update-vert)
+       (if (not (= y scrolly))
+           (begin (set! y scrolly)
+                  (shape-draw big)
+                  (assign-location! small (make-point x y))
+                  (shape-draw small)
+                  (ask-widget vscroll `(set 600 40 ,y ,(+ y 40))))))
+      (define (update-horiz)
+       (if (not (= x scrollx))
+           (begin (set! x scrollx)
+                  (shape-draw big)
+                  (assign-location! small (make-point x y))
+                  (shape-draw small)
+                  (ask-widget hscroll `(set 500 30 ,x ,(+ x 30))))))
+
+      (ask-widget vscroll '(set 600 40 0 40))
+      (ask-widget hscroll '(set 500 30 0 30))
+      (let ((hb (make-hbox big vscroll)))
+       (let ((vb (make-vbox hb hscroll)))
+         (add-child! app vb)
+         ))
+
+      (set-callback! vscroll
+                    (lambda (value)
+                      (let* ((n (string->number value))
+                             ;;keep small bar totally on screen
+                             (n (max 0 n))
+                             (n (min 560 n)))
+                        (set! scrolly n)
+                        (when-idle! update-vert))))
+      (set-callback! hscroll
+                    (lambda (value)
+                      (let* ((n (string->number value))
+                             ;;keep small bar totally on screen
+                             (n (max 0 n))
+                             (n (min 470 n)))
+                        (set! scrollx n)
+                        (when-idle! update-horiz))))
+      (on-geometry-change!
+       big
+       'ignore
+       (lambda (old-screen-area new-screen-area)
+        (assign-geometry! small
+                          (drawing-surface big)
+                          (if new-screen-area
+                              (copy-rectangle new-screen-area)
+                              new-screen-area))
+        (shape-draw big)
+        (shape-draw small)))
+      (handle-exposure big (lambda (rect)
+                            (shape-draw big (rectangle->xregion rect))
+                            (shape-draw small)))
+      (when-idle! (lambda () (shape-draw small)))
+      `((app ,app)
+       (hscroll ,hscroll)
+       (vscroll ,vscroll)
+       (big ,big)
+       (small ,small)))))
+
+(define (compress-deferred-processing on-callback at-idle)
+  (let ((scheduled? #F))
+    (lambda args
+      (if (not scheduled?)
+         (begin
+           (when-idle!
+            (lambda ()
+              (set! scheduled? #F)
+              (at-idle)))
+           (set! scheduled? #T)))
+      (apply on-callback args))))
+
+(define (sbtest4)
+  (let ((app (make-application "Play")))
+    (let ((hscroll (make-scrollbar '(-width 20 -orient horizontal)))
+         (vscroll (make-scrollbar '(-width 20 -orient vertical)))
+         (big (make-rect 500 600 "blue"))
+         (small (make-oval 30 40 "yellow"))
+         (scrolly 0)
+         (scrollx 0)
+         (x 0)
+         (y 0))
+
+      (define (update-vert)
+       (if (not (= y scrolly))
+           (begin (set! y scrolly)
+                  (shape-draw big)
+                  (assign-location! small (make-point x y))
+                  (shape-draw small)
+                  (ask-widget vscroll `(set 600 40 ,y ,(+ y 40))))))
+
+      (define (update-horiz)
+       (if (not (= x scrollx))
+           (begin (set! x scrollx)
+                  (shape-draw big)
+                  (assign-location! small (make-point x y))
+                  (shape-draw small)
+                  (ask-widget hscroll `(set 500 30 ,x ,(+ x 30))))))
+
+      (ask-widget vscroll '(set 600 40 0 40))
+      (ask-widget hscroll '(set 500 30 0 30))
+      (add-child! app (make-vbox (make-hbox big vscroll)
+                                hscroll))
+      (set-callback! vscroll
+       (compress-deferred-processing
+        (lambda (value)
+          (let* ((n (string->number value))
+                 ;;keep small bar totally on screen
+                 (n (max 0 n))
+                 (n (min 560 n)))
+            (set! scrolly n)))
+        update-vert))
+
+      (set-callback! hscroll
+       (compress-deferred-processing
+        (lambda (value)
+          (let* ((n (string->number value))
+                 ;;keep small bar totally on screen
+                 (n (max 0 n))
+                 (n (min 470 n)))
+            (set! scrollx n)))
+        update-horiz))
+
+      (on-geometry-change!
+       big
+       'ignore
+       (lambda (old-screen-area new-screen-area)
+        (assign-geometry! small
+                          (drawing-surface big)
+                          (if new-screen-area
+                              (copy-rectangle new-screen-area)
+                              new-screen-area))
+        (shape-draw big)
+        (shape-draw small)))
+
+      (handle-exposure big (lambda (rect)
+                            (shape-draw big (rectangle->xregion rect))
+                            (shape-draw small)))
+
+      (when-idle! (lambda () (shape-draw small)))
+      `((app ,app)
+       (hscroll ,hscroll)
+       (vscroll ,vscroll)
+       (big ,big)
+       (small ,small)))))
+
+;;; canvas tests
+(define (canvas-test)
+  (let ((c (make-canvas '(-width 400 -height 300 -background "light gray"))))
+    (swat-open c)
+    (let ((george
+           (make-arc-on-canvas c 200 200 250 250
+                               `(-fill pink -outline black
+                                 -width 2 -start 0 -extent 300)))
+          (message (make-text-on-canvas c 100 100 '(-text "Hello there")))
+          (last-x #F)
+          (last-y #F)
+          (start 0))
+      (add-event-handler! george "<Enter>"
+       (lambda () (ask-widget george '(configure -fill yellow))))
+      (add-event-handler! george "<Leave>"
+       (lambda () (ask-widget george '(configure -fill pink))))
+      (add-event-handler! george "<ButtonPress-1>"
+       (lambda (x y)
+         (ask-widget message
+          `(configure -text "OUCH!"
+                      -font "-Adobe-Helvetica-Bold-R-Normal--*-240-*"))
+         (set! start (modulo (+ start 30) 360))
+         (ask-widget george `(configure -start ,start))
+         (set! last-x x)
+         (set! last-y y))
+       "%x" "%y")
+      (add-event-handler! george "<ButtonRelease-1>"
+       (lambda ()
+         (ask-widget message
+          '(configure -text "Hello there"
+                      -font "-Adobe-Helvetica-Bold-R-Normal--*-120-*"))))
+      (add-event-handler! george "<Button1-Motion>"
+       (lambda (x y)
+         (ask-widget george `(move ,(- x last-x) ,(- y last-y)))
+         (set! last-x x)
+         (set! last-y y))
+       "%x" "%y")
+      )))
+
+
+(define (doodle-test)
+  (let ((c (make-canvas '(-width 400 -height 300
+                          -background "light gray")))                           
+       (last-x 0)
+       (last-y 0))
+    (add-event-handler! c
+                       "<ButtonPress-1>"
+                       (lambda (x y)
+                         (ask-widget c `(delete all))
+                         (set! last-x x)
+                         (set! last-y y))
+                       "%x" "%y")
+    (add-event-handler! c
+                       "<B1-Motion>"
+                       (lambda (x y)
+                         (let ((line (make-line-on-canvas c last-x last-y x y)))
+                           (ask-widget line '(configure -width 1))
+                           (set! last-x x)
+                           (set! last-y y)))
+                       "%x" "%y")
+    (swat-open c '-title "Canvas Drawing")))
+
+
+(define (ctest)
+  (let ((a (make-application "Canvas Items: IQ Test")))
+    (let ((c (make-canvas '(-width 400 -height 300))))
+      (ask-widget c '(configure -background "light gray"))
+      (add-child! a c)
+      
+      (let* ((r1 (make-rectangle-on-canvas c  20  20  60  60))
+            (r2 (make-rectangle-on-canvas c  40  40  80  80))
+            (r3 (make-rectangle-on-canvas c  60  60 100 100))
+
+            (m1 (make-text-on-canvas      c 300  20 '(-text "CANVAS EVENTS:")))
+            (m2 (make-text-on-canvas      c 300  40 '(-text "B1: east")))
+            (m3 (make-text-on-canvas      c 300  60 '(-text "B3: west")))
+            (m4 (make-text-on-canvas      c 300  80 '(-text "B2,B1: south")))
+            (m5 (make-text-on-canvas      c 300 100 '(-text "B2,B3: north")))
+            (m6 (make-text-on-canvas      c 300 140 '(-text "TAG EVENTS:")))
+            (m7 (make-text-on-canvas      c 300 160 '(-text "B1: red")))
+            (m8 (make-text-on-canvas      c 300 180 '(-text "B2: green")))
+            (m9 (make-text-on-canvas      c 300 200 '(-text "B3: blue")))
+
+            (t1 (make-canvas-item-group          c (list r1 r2 r3)))
+            (t2 (make-canvas-item-group          c (list m2 m3 m4 m5 m7 m8 m9)))
+            )
+       (ask-widget r1 '(configure -fill red))
+       (ask-widget r2 '(configure -fill green))
+       (ask-widget r3 '(configure -fill blue))
+       (ask-widget t2 '(configure -anchor n -fill maroon))
+
+
+       (add-event-handler! c
+                           "<ButtonPress-1>"
+                           (lambda ()
+                             (ask-widget t1 `(move 10 0))))
+       (add-event-handler! c
+                           "<ButtonPress-3>"
+                           (lambda ()
+                             (ask-widget t1 `(move -10 0))))
+       (add-event-handler! c
+                           "<ButtonPress-2><ButtonPress-1>"
+                           (lambda ()
+                             (ask-widget t1 `(move 0 10))))
+       (add-event-handler! c
+                           "<ButtonPress-2><ButtonPress-3>"
+                           (lambda ()
+                             (ask-widget t1 `(move 0 -10))))
+
+       (add-event-handler! t1
+                           "<ButtonPress-1>"
+                           (lambda ()
+                             (ask-widget r1 `(move 10 10))))
+       (add-event-handler! t1
+                           "<ButtonPress-2>"
+                           (lambda ()
+                             (ask-widget r2 `(move 10 10))))
+       (add-event-handler! t1
+                           "<ButtonPress-3>"
+                           (lambda ()
+                             (ask-widget r3 `(move 10 10))))
+
+       (add-event-handler! r1
+                           "<Enter>"
+                           (lambda ()
+                             (ask-widget r1 `(raise))))
+       (add-event-handler! r2
+                           "<Enter>"
+                           (lambda ()
+                             (ask-widget r2 `(raise))))
+       (add-event-handler! r3
+                           "<Enter>"
+                           (lambda ()
+                             (ask-widget r3 `(raise))))
+       
+       (add-event-handler! t2
+                           "<Enter>"
+                           (lambda ()
+                             (ask-widget t2 `(configure -fill violetred))))
+       (add-event-handler! t2
+                           "<Leave>"
+                           (lambda ()
+                             (ask-widget t2 `(configure -fill maroon))))
+
+       c))))
+
+(define (ctest1)
+  (let* ((app (make-application "Canvas Widget"))
+        (canvas (make-canvas '(-width 300 -height 300)))
+        (button1 (make-button '(-text "Toggle background color")))
+        (vbox (make-vbox canvas button1)))
+    (ask-widget canvas '(configure -background yellow))
+    (ask-widget button1 '(configure -background cyan
+                                   -activebackground "light blue"))
+    (add-child! app vbox)
+    (set-callback!
+     button1
+     (lambda ()
+       (let* ((button2 (make-button '(-text "Yellow")))
+             (button3 (make-button '(-text "Red"))))
+        (ask-widget button2 '(configure -background "light blue"
+                                        -activebackground cyan))
+        (ask-widget button3 '(configure -background "light blue"
+                                        -activebackground cyan))
+        (let* ((cb2 (make-widget-on-canvas canvas button2 200 250))
+               (cb3 (make-widget-on-canvas canvas button3 250 250))
+               (both (make-canvas-item-group canvas (list cb2 cb3))))
+          (set-callback! button2
+                         (lambda ()
+                           (ask-widget canvas '(configure -background yellow))
+                           (ask-widget both '(delete))))
+          (set-callback! button3
+                         (lambda ()
+                           (ask-widget canvas '(configure -background red))
+                           (ask-widget both '(delete))))))))
+    (list app vbox)))
+
+
+(define (menu-test)
+  ;; No menu button
+  (let ((application (make-application "Menu Test")))
+    (define start-button (make-button '(-text "Go!")))
+    (define main (make-menu))
+    (define sub (make-menu))
+    (define button-1 (add-to-menu main 'command '-background "blue" '-label "Close"))
+    (define button-2 (add-to-menu main 'command '-background "yellow" '-label "Two"))
+    (define button-3 (add-sub-menu main sub '-background "blue" '-label "More..."))
+    (define sub-1 (add-to-menu sub 'command '-background "blue" '-label "A"))
+    (define sub-2 (add-to-menu sub 'command '-background "blue" '-label "B"))
+    (define sub-3 (add-to-menu sub 'command '-background "blue" '-label "C"))
+    (define sub-4 (add-to-menu sub 'command '-background "blue" '-label "D"))
+    (ask-widget start-button
+               '(configure -background yellow
+                           -font
+                           "-adobe-helvetica-bold-r-normal--34-240-100-100-p-182-iso8859-1"))
+    (add-child! application start-button)
+    (add-child! start-button main)
+    (set-callback! button-1 (lambda () (ask-widget main '(unpost))))
+    (set-callback! button-2 (lambda () (write-line 'Two)))
+    (set-callback! button-3 (lambda () (write-line 'Three)))
+    (set-callback! sub-1 (lambda () (write-line 'A)))
+    (set-callback! sub-2 (lambda () (write-line 'B)))
+    (set-callback! sub-3 (lambda () (write-line 'C)))
+    (set-callback! sub-4 (lambda () (write-line 'D)))
+    (set-callback! start-button (lambda () (ask-widget main '(post 10 20))))
+    (lambda ()
+      (list application start-button main sub
+           button-1 button-2 button-3
+           sub-1 sub-2 sub-3 sub-4))))
+
+(define (menu-test2)
+  (let ((application (make-application "Menu Test")))
+    (define main (make-menu))
+    (define start-button (make-menubutton main '(-text "Go!")))
+    (define sub (make-menu))
+    (define button-1 (add-to-menu main 'command '-background "blue" '-label "Close"))
+    (define button-2 (add-to-menu main 'command '-background "yellow" '-label "Two"))
+    (define button-3 (add-sub-menu main sub '-background "blue" '-label "More..."))
+    (define sub-1 (add-to-menu sub 'command '-background "blue" '-label "A"))
+    (define sub-2 (add-to-menu sub 'command '-background "blue" '-label "B"))
+    (define sub-3 (add-to-menu sub 'command '-background "blue" '-label "C"))
+    (define sub-4 (add-to-menu sub 'command '-background "blue" '-label "D"))
+    (add-child! application start-button)
+    (set-callback! button-1 (lambda () (ask-widget main '(unpost))))
+    (set-callback! button-2 (lambda () (write-line 'Two)))
+    (set-callback! button-3 (lambda () (write-line 'Three)))
+    (set-callback! sub-1 (lambda () (write-line 'A)))
+    (set-callback! sub-2 (lambda () (write-line 'B)))
+    (set-callback! sub-3 (lambda () (write-line 'C)))
+    (set-callback! sub-4 (lambda () (write-line 'D)))
+    (lambda ()
+      (list application start-button main sub
+           button-1 button-2 button-3
+           sub-1 sub-2 sub-3 sub-4))))
+
+(define (menu-test3)
+  (let ((application (make-application "Menu Test")))
+    (define main (make-menu))
+    (define start-button (make-menubutton main '(-text "Go!")))
+    (define button-1 (add-to-menu main 'command '-background "blue" '-label "Close"))
+    (define button-2 (add-to-menu main 'command '-background "yellow" '-label "Two"))
+    (add-child! application start-button)
+    (set-callback! button-1 (lambda () (ask-widget main '(unpost))))
+    (set-callback! button-2 (lambda () (write-line 'Two)))
+    (lambda ()
+      (list application start-button main 
+           button-1 button-2))))
+
+
+(define (mac)
+  (let* ((a (make-application "Microslop Word"))
+        (t (make-text))
+        (sb (make-scrollbar '(-width 20 -orient vertical)))
+        (file-menu (make-menu))
+        (file-mb (make-menubutton file-menu '(-text "File")))
+        (save-menu (make-menu))
+        (edit-menu (make-menu))
+        (edit-mb (make-menubutton edit-menu '(-text "Edit")))
+        (tools-menu (make-menu))
+        (tools-mb (make-menubutton tools-menu '(-text "Tools")))
+        )
+
+    (for-each (lambda (m)
+               (ask-widget m '(configure -background white
+                                         -activebackground red)))
+             (list file-menu save-menu edit-menu tools-menu
+                   file-mb edit-mb tools-mb))
+    (for-each (lambda (b)
+               (ask-widget b '(configure -relief raised)))
+             (list file-mb edit-mb tools-mb))
+
+    (ask-widget t '(configure -background white -wrap word -width 40))
+    (ask-widget sb '(configure -background red))
+    (ask-widget sb '(set 1000 400 0 400))
+
+    (set-callback!
+     sb
+     (lambda (value)
+       (let* ((n (string->number value)))
+        (when-idle!
+         (lambda () (ask-widget sb `(set 1000 400 ,n ,(+ n 400))))))))
+
+    (let ((me (make-vbox (make-hbox file-mb edit-mb tools-mb)
+                        (make-hbox t sb))))
+      (add-child! a me)
+
+      (add-to-menu file-menu 'command '-label "Open")
+      (add-to-menu file-menu 'command '-label "Close")
+      (add-sub-menu file-menu save-menu '-label "Save...")
+      (add-to-menu save-menu 'command '-label "There is no salvation")
+      (add-to-menu save-menu 'command '-label "Jesus saves")
+      (add-to-menu file-menu 'command '-label "Exit")
+
+      (let ((paste-button (add-to-menu edit-menu 'command '-label "Paste"))
+           (cut-button (add-to-menu edit-menu 'command '-label "Cut"))
+           (deleted-text #F))
+       (set-callback! cut-button
+                      (lambda ()
+                        (set! deleted-text
+                              (ask-widget t '(get sel.first sel.last)))
+                        (ask-widget t '(delete sel.first sel.last))))
+       (set-callback! paste-button
+                      (lambda ()
+                        (if deleted-text
+                            (ask-widget t `(insert insert ,deleted-text))))))
+
+      (add-to-menu edit-menu 'command '-label "Staple")
+      (add-to-menu edit-menu 'command '-label "Mutilate")
+
+      (add-to-menu tools-menu 'command '-label "Hammer")
+      (add-to-menu tools-menu 'command '-label "Saw")
+
+      me)))
+
+(define all-tags '())
+(define all-demos '())
+(define (browser)
+  (let* ((a (make-application "Demo Browser"))
+        (t (make-text))
+        (sb (make-scrollbar '(-width 20 -orient vertical)))
+        (m (make-menu))
+        (mb (make-menubutton m '(-text "Widgets"))))
+
+    (define (switch-to-widget-demos list-of-demos)
+      (for-each (lambda (tag) (ask-widget tag '(delete))) all-tags)
+      (set! all-tags '())
+      (ask-widget t '(delete "1.0" end))
+      (for-each
+       (lambda (demo-thunk-name)
+        (ask-widget t `(insert insert ,demo-thunk-name))
+        (ask-widget t '(insert insert " "))
+        (let ((tag (make-text-tag t "insert linestart" "insert-1c")))
+          ;; gc protect
+          (set! all-tags (cons tag all-tags))
+          (add-event-handler!
+           tag "<Enter>"
+           (lambda () (ask-widget tag '(configure -foreground violetred))))
+          (add-event-handler!
+           tag "<Leave>"
+           (lambda () (ask-widget tag '(configure -foreground blue))))
+          (add-event-handler!
+           tag
+           "<Button-1>"
+           (lambda ()
+             (ask-widget tag '(configure -underline 1))
+             (let ((demo-thunk
+                    (ask-widget
+                     t
+                     `(get ,(string-append (TextTag.name tag) ".first")
+                           ,(string-append (TextTag.name tag) ".last")))))
+               ;; gc protect
+               (set! all-demos (cons ((eval (string->symbol demo-thunk) 
+                                            user-initial-environment))
+                                     all-demos))
+               ))))
+        (ask-widget t '(insert insert "\n")))
+       list-of-demos))
+
+    (ask-widget t `(configure -width 20 -height 10
+                             -background "white" -foreground blue))
+    (for-each (lambda (x)
+               (ask-widget x '(configure -background blue -foreground white
+                                         -activebackground white
+                                         -activeforeground blue)))
+             (list m mb))
+    #|
+    (set-callback! sb
+                  (lambda (n)
+                    (ask-widget t `(yview -pickplace ,n))))
+
+    |#
+
+    (let ((me (make-vbox mb (make-hbox t sb))))
+      (add-child! a me)
+
+      (ask-widget t `(configure -yscrollcommand
+                               ,(string-append (tk-widget->pathname sb) " set")))
+      (ask-widget sb `(configure
+                      -command
+                      ,(string-append
+                        (tk-widget->pathname t)
+                        " yview -pickplace")))
+
+      (let* ((picture-button   (add-to-menu m 'command '-label "Picture"))
+            (button-button    (add-to-menu m 'command '-label "Button"))
+            (scale-button     (add-to-menu m 'command '-label "Scale"))
+            (entry-button     (add-to-menu m 'command '-label "Entry"))
+            (scrollbar-button (add-to-menu m 'command '-label "Scrollbar"))
+            (canvas-button    (add-to-menu m 'command '-label "Canvas"))
+            (menu-button      (add-to-menu m 'command '-label "Menu"))
+            (text-button      (add-to-menu m 'command '-label "Text Widget"))
+            (animation-button (add-to-menu m 'command '-label "Animation")))
+
+       (set-callback! picture-button
+                      (lambda () (switch-to-widget-demos
+                                  (list "test1" "test1a" "test2" "test3"))))
+       (set-callback! button-button
+                      (lambda () (switch-to-widget-demos
+                                  (list "btest1" "btest2" "btest3"))))
+       (set-callback! scale-button
+                      (lambda () (switch-to-widget-demos (list "stest1" "stest2"))))
+       (set-callback! entry-button
+                      (lambda () (switch-to-widget-demos (list "etest1"))))
+       (set-callback! scrollbar-button
+                      (lambda () (switch-to-widget-demos
+                                  (list "sbtest1" "sbtest2" "sbtest3"))))
+       (set-callback! canvas-button
+                      (lambda () (switch-to-widget-demos
+                                  (list "canvas-test" "doodle-test"
+                                        "ctest" "ctest1"))))
+       (set-callback! menu-button
+                      (lambda () (switch-to-widget-demos
+                                  (list "menu-test" "menu-test2"))))
+       (set-callback! text-button
+                      (lambda () (switch-to-widget-demos (list "mac" "browser"))))
+       (set-callback! animation-button
+                      (lambda () (switch-to-widget-demos
+                                  (list "btest3" "animation" "biff" "melt"
+                                        "balls"))))
+       
+       me))))
+
+
+(define app4)
+(define c4)
+(define but4)
+(define (animation)
+  (set! app4 (make-application "Animation"))
+  (set! c4 (make-canvas '(-background white -width 200 -height 200)))
+  (set! but4 (make-button '(-text "START" -background maroon -foreground white
+                           -activebackground "hot pink")))
+  (add-child! app4 c4)
+  (make-widget-on-canvas c4 but4 25 185)
+  (set-callback!
+   but4
+   (lambda ()             
+     (let ((rect (make-rectangle-on-canvas c4 10 10 40 40)))
+       (ask-widget rect '(configure -fill red))
+       (let loop ((position 10))
+        (if (> position 200)
+            (ask-widget rect '(delete))
+            (begin (ask-widget rect '(move 1 1))
+                   (after-delay .05 (lambda () (loop (1+ position))))))))))
+  c4)
+
+
+(define app5)
+(define c5)
+(define (biff)
+  (set! app5 (make-application "biff"))
+  (set! c5 (make-canvas '(-background black -width 70 -height 70)))
+  (add-child! app5 c5)
+  (let* ((file1 "/usr/local/lib/tk/demos/bitmaps/flagdown")
+        (file2 "/usr/local/lib/tk/demos/bitmaps/flagup")
+        (current-bitmap-filename file1)
+        (current-bknd "black")
+        (current-fgnd "cyan"))
+    (define (toggle-bitmap)
+      (let ((old-bknd current-bknd)
+           (old-fgnd current-fgnd))
+       (set! current-bknd old-fgnd)
+       (set! current-fgnd old-bknd))
+      (if (equal? current-bitmap-filename file1)
+         (set! current-bitmap-filename file2)
+         (set! current-bitmap-filename file1)))
+    (define (make-flag)
+      (let ((flag (make-bitmap-on-canvas c5 current-bitmap-filename 35 35)))
+       (ask-widget flag `(configure -background ,current-bknd
+                                    -foreground ,current-fgnd))
+       flag))
+
+    (let ((flag (make-flag)))
+      (define (toggle)
+       (ask-widget flag '(delete))
+       (toggle-bitmap)
+       (ask-widget c5 `(configure -background ,current-bknd))
+       (set! flag (make-flag)))
+      (after-delay
+       1
+       (lambda ()
+        (let loop ((count 0))
+          (if (> count 10)
+              'done
+              (after-delay 1
+                           (lambda ()
+                             (toggle)
+                             (loop (1+ count))))))))
+      (add-event-handler! c5 "<Any-ButtonPress>" toggle))))
+
+
+(define app6)
+(define c6)
+(define but6)
+(define (melt)
+  (define (generate-vertical-line x)
+    (let* ((length (random 30))
+          (start (- (random 30) 30))
+          (end (+ start length))
+          (line (make-line-on-canvas c6 x start x end)))
+      (ask-widget line `(configure -fill white))
+      line))
+  
+  (set! app6 (make-application "Mind Melt"))
+  (set! c6 (make-canvas '(-background black -width 200 -height 200)))
+  (set! but6 (make-button '(-text "MELT"
+                           -background black -foreground red
+                           -activebackground black -activeforeground red)))
+  (let ((me (make-vbox c6 but6)))
+    (add-child! app6 me)
+    (set-callback!
+     but6
+     (lambda ()
+       (let* ((lines (let loop ((x 0) (lines '()))
+                      (if (> x 200)
+                          lines
+                          (loop (+ x 2) (cons (generate-vertical-line x) lines)))))
+             (tag (make-canvas-item-group c6 lines)))
+        (let loop ((position 0))
+          (if (> position 230)
+              (ask-widget tag '(delete))
+              (after-delay .000005
+                           (lambda ()
+                             (for-each (lambda (line)
+                                         (ask-widget line `(move 0 ,(random 10))))
+                                       lines)
+                             (loop (1+ position)))))))))
+    me))
+
+
+(define (balls)
+  (define canvas-width 300)
+  (define canvas-height 300)
+  (define min-ball-size 1)
+  (define max-ball-size 30)
+  (define min-delta 1)
+  (define max-delta 8)
+  (define a (/ (- min-delta max-delta) (- max-ball-size min-ball-size)))
+  (define b (- min-delta (* a max-ball-size)))
+  (define (pick-random-color)
+    (define list-of-colors
+      '("green" "yellow" "red" "blue" "hot pink" "orange" "cyan"
+       "maroon" "skyblue" "firebrick" "aquamarine" "violet"
+       "violetred" "navyblue" "darkslateblue" "pink"))
+    (list-ref list-of-colors (random (length list-of-colors))))
+
+  (define (pick-true-or-false)
+    (list-ref '(#T #F) (random 2)))
+
+  (define (make-ball canvas diameter startx starty)
+    (let* ((radius (round->exact (/ diameter 2)))
+          (centerx (+ startx radius))
+          (centery (+ starty radius))
+          (the-ball
+           (make-oval-on-canvas canvas startx starty
+                                (+ startx diameter)
+                                (+ starty diameter)))
+          (increasing-x? (pick-true-or-false))
+          (increasing-y? (pick-true-or-false))
+          (speed-factor (round->exact (+ (* a diameter) b))))
+      (lambda (m)
+       (case m
+         ((the-ball) the-ball)
+         ((centerx) centerx)
+         ((centery) centery)
+         ((set-centerx!) (lambda (x) (set! centerx x)))
+         ((set-centery!) (lambda (y) (set! centery y)))
+         ((+x?) increasing-x?)
+         ((+y?) increasing-y?)
+         ((set+x?!) (lambda (boolean) (set! increasing-x? boolean)))
+         ((set+y?!) (lambda (boolean) (set! increasing-y? boolean)))
+         ((diameter) diameter)
+         ((speed-factor) speed-factor)))))
+
+  (define (generate-ball canvas)
+    (let* ((diameter (+ min-ball-size (random (- max-ball-size min-ball-size))))
+          (startx (min (random canvas-width) (- canvas-width diameter)))
+          (starty (min (random canvas-height) (- canvas-height diameter)))
+          (ball (make-ball canvas diameter startx starty)))
+      (ask-widget (ball 'the-ball) `(configure -fill ,(pick-random-color)))
+      ball))
+
+  (define (generate-move ball)
+    (let* ((centerx (ball 'centerx))
+          (centery (ball 'centery))
+          (diameter (ball 'diameter))
+          (radius (round->exact (/ diameter 2)))
+          (startx (- centerx radius))
+          (endx (+ centerx radius))
+          (starty (- centery radius))
+          (endy (+ centery radius))
+          (dx-sign (cond ((<= startx 0)
+                          ((ball 'set+x?!) #T)
+                          1)
+                         ((>= endx canvas-width)
+                          ((ball 'set+x?!) #F)
+                          -1)
+                         ((ball '+x?) 1)
+                         (else -1)))
+          (dy-sign (cond ((<= starty 0)
+                          ((ball 'set+y?!) #T)
+                          1)
+                         ((>= endy canvas-height)
+                          ((ball 'set+y?!) #F)
+                          -1)
+                         ((ball '+y?) 1)
+                         (else -1)))
+          (dx (* dx-sign (max 1 (random (ball 'speed-factor)))))
+          (dy (* dy-sign (max 1 (random (ball 'speed-factor))))))
+      ((ball 'set-centerx!) (+ centerx dx))
+      ((ball 'set-centery!) (+ centery dy))
+      `(move ,dx ,dy)))
+  
+  (let ((app7 (make-application "Bouncing Balls"))
+       (c7 (make-canvas `(-background black -width ,canvas-width
+                                      -height ,canvas-height))))
+    (add-child! app7 c7)
+  
+    (let ((balls
+          (let loop ((num 0) (balls '()))
+            (if (> num (+ 10 (random 10)))
+                balls
+                (loop (1+ num) (cons (generate-ball c7) balls))))))
+      (let ((go
+            (lambda ()
+              (let loop ()
+                (for-each
+                 (lambda (ball)
+                   (ask-widget (ball 'the-ball) (generate-move ball)))
+                 balls)
+                (after-delay 0.0005 loop)))))
+       (after-delay 1 go)
+       (list app7 c7 balls go)))))
+
+
+(define (canvas-sb-test)
+  (let ((sc (make-scrollable-canvas
+            '(-width 500 -height 500
+              -scrollregion (0 0 1000 1000)))))
+    (swat-open sc)
+    (ask-widget (scrollable-canvas-hscroll sc)
+               `(configure -foreground "yellow"))
+    (ask-widget (scrollable-canvas-vscroll sc)
+               `(configure -foreground "yellow"))
+    (make-rectangle-on-canvas (scrollable-canvas-canvas sc)
+                             100 100 400 400
+                             '(-fill red))
+    sc))
+
+
+
+(define (text-sb-test)
+  (let ((st (make-scrollable-text)))
+    (swat-open st)
+    (ask-widget (scrollable-text-vscroll st)
+               '(configure -foreground red))
+    st))
+    
+
+
+
+
+
diff --git a/v7/src/swat/scheme/other/doodle.scm b/v7/src/swat/scheme/other/doodle.scm
new file mode 100644 (file)
index 0000000..852518a
--- /dev/null
@@ -0,0 +1,103 @@
+;;; -*- Scheme -*-
+
+(declare (usual-integrations))
+
+;;;; This is a very simple application written in Scheme, withous any
+;;;; TK wigets.  It is a surface on which you cna sketch a path with
+;;;; the mouse.
+
+;;;Some geometric shape drawers:
+;;;This might be generally useful -- it saves the higher level from
+;;;worrying about the graphics context.
+
+;;;this doesn't handle clipping.  should we create a line-drawer with a
+;;;specified clip region??
+
+(define (geometry-drawer-for-shape shape color drawproc)
+  ;;also set line style, thickness, etc.
+  (let* ((window #F)
+        (gc #F))
+    (lambda args
+      ;;need to init the window and GC and keep it up to date if the
+      ;;window changes
+      ;;is there some way to used cached info for the shape to speed
+      ;;up these tests?
+      (if (not (used-screen-area shape))
+         (error "attempt to draw on background with no screen area"
+                shape))
+      (if (not (eq? window (get-uitkwindow shape)))
+         (begin (set! window (get-uitkwindow shape))
+                (set! gc (make-colored-graphics-context window color))))
+      (apply drawproc (cons window (cons gc args))))))
+
+(define (line-drawer-for-shape shape color)
+  (geometry-drawer-for-shape
+   shape color
+   (lambda (window gc p1 p2)
+     (drawline window gc 
+              (point.X p1) (point.Y p1)
+              (point.X p2) (point.Y p2)))))
+
+(define (arc-drawer-for-shape shape color)
+  (geometry-drawer-for-shape
+   shape color
+   (lambda (window gc p w h a1 a2)
+     (drawarc window gc (point.X p) (point.Y p) w h a1 a2))))
+
+(define (rectangle-drawer-for-shape shape color)
+  (geometry-drawer-for-shape
+   shape color
+   (lambda (window gc p w h)
+     (drawrectangle window gc (point.X p) (point.Y p) w h))))
+
+
+
+(define (setup-doodle)
+  (let ((d (make-doodle-surface 400 400 "light gray")))
+    (add-child! (make-application "doodle") d)
+    d))
+
+(define (make-doodle-surface width height background-color)
+  (let* ((line-color "black")
+        (background (make-rect width height background-color))
+        (draw-line (line-drawer-for-shape background line-color))
+        (path '()))
+    (define (collect-points first-event while-grabbed)
+      (shape-draw background)          ;clear and erase path
+      (set! path (list (event.offset first-event)))
+      (while-grabbed
+       (lambda (point)
+        (if (point-within? background point)
+            (begin (draw-line (car path) point)
+                   (set! path (cons point path)))))
+       (lambda () 'done)))             ;nothing to do at end of grab
+    (define (draw-path)
+      (if (not (null? path))
+         (let loop ((path path))
+           (if (null? (cdr path))
+               'done
+               (begin (draw-line (car path) (cadr path))
+                      (loop (cdr path)))))))
+    (handle-exposure
+     background
+     (lambda (exposed-rectangle)
+       (shape-draw background (rectangle->XRegion exposed-rectangle))
+       ;;should clip to exposed rectangle.  What's a nice way to do this?
+       (draw-path)))
+    (handle-button-grab
+     background ANYBUTTON
+     (lambda (e while-grabbed)
+       (collect-points e while-grabbed)))
+    (on-geometry-change!
+     background
+     'ignore
+     (lambda (old-screen-area new-screen-area)
+       old-screen-area
+       (if (UITKRectangle? new-screen-area)
+          (shape-draw background))))
+    background))
+
+
+
+
+
diff --git a/v7/src/swat/scheme/other/exports.scm b/v7/src/swat/scheme/other/exports.scm
new file mode 100644 (file)
index 0000000..9076409
--- /dev/null
@@ -0,0 +1,17 @@
+;; Make export list
+
+(define (make-export-list candidates)
+  ;; Call this on the names in the SWAT load environmnet to discover the
+  ;; useful names.
+  (define xlib-names (map second (read-file "xlibCONSTANTS.scm")))
+
+  (define (xlib-name? n) (memq n xlib-names))
+  (define (internal-name? n)
+    (let ((s (symbol-name n)))
+      (or (string-find-next-char s #\%))))
+
+  (sort (list-transform-negative candidates
+         (lambda (name)
+           (or (internal-name? name)
+               (xlib-name? name))))
+       symbol<?))
diff --git a/v7/src/swat/scheme/other/plotter.scm b/v7/src/swat/scheme/other/plotter.scm
new file mode 100644 (file)
index 0000000..4172c7d
--- /dev/null
@@ -0,0 +1,1183 @@
+;;; -*- Scheme -*-
+
+(declare (usual-integrations))
+
+;;;; Plotting Package for Scheme Widget Application Toolkit
+
+;;; Working from the Scheme Prompt
+
+;;;(PLOTTER) 
+;;;  Creates a new plotter.
+;;; 
+;;;     Example: (define p (plotter))
+;;;
+;;;(PLOT plotter . options)
+;;;  The options list sequentially describes one or more curves to be
+;;;  plotted, in the following manner: 
+;;;
+;;;    (PLOT plotter
+;;;          <function1> '<option> <value> '<option> <value> ... ;first curve 
+;;;          <function2> '<option> <value> ...                   ;second curve
+;;;          ...
+;;;          ...)
+;;;  Returns a single curve if only one function is specified, and a
+;;;  list of curves if more than one function is supplied.
+;;;
+;;;     Example: (define c0 (plot p sin 'xmin -10 'xmax 5))
+;;;              (define c1&2 (plot p cos 'pt-style 0 tan 'pt-style 5))
+;;;
+;;;  The first parameter to PLOT after plotter must always be a
+;;;  function. Curve-specific options affect only the function they
+;;;  follow, and thus can and should be repeated.  Any instance of a
+;;;  global option after the first will be ignored. 
+;;;
+;;;  Global options and arguments: 
+;;;    'XMIN:  The minimum value of x to be displayed on the plot.
+;;;            The default is 0. 
+;;;    'XMAX:  The maximum value of x to be displayed on the plot.
+;;;            The default is 1. 
+;;;    'YMIN:  The minimum value of y to be displayed on the plot.
+;;;            If not specified, the plot will be automatically scaled.
+;;;    'YMAX:  The maximum value of y to be displayed on the plot.
+;;;            If not specified, the plot will be automatically scaled.
+;;;    'AXIS-X:  The value of x at which the y-axis will be drawn.
+;;;              The default is 0. 
+;;;    'AXIS-Y:  The value of y at which the x-axis will be drawn.
+;;;              The default is 0. 
+;;;    'XTICKS:  A list of pairs describing ticks on the x axis.  The
+;;;              car of each pair is the value of x at which to make
+;;;              the tick.  The cdr is a string to be displayed as a
+;;;              label.  The procedure MAKE-VALS can be used to return
+;;;              a list of values for labels at regular intervals. If
+;;;              not specified, only the extreme values will be labeled. 
+;;;    'YTICKS:  A list of pairs describing ticks on the y axis.  Same
+;;;              format as XTICKS.  If not specified, only the extreme
+;;;              values will be labeled. 
+;;;
+;;;  Curve-specific options and arguments
+;;;    'NUM-PTS:  The number of points to be calculated for the curve.
+;;;               The default is one for every 10 pixels.
+;;;    'PT-STYLE:  A number representing the style in which the curve
+;;;                will be drawn: 
+;;;                  0  --  lines to the x-axis
+;;;                  1  --  large unfilled circles
+;;;                  2  --  large unfilled squares
+;;;                  3  --  x's
+;;;                  4  --  +'s
+;;;                  5  --  small filled circles
+;;;                  6  --  small filled squares
+;;;                  7  --  dots
+;;;                  10  --  large unfilled circles with lines to the x-axis
+;;;                  20  --  large unfilled squares with lines to the x-axis
+;;;                  30  --  x's with lines to the x-axis
+;;;                  40  --  +'s with lines to the x-axis
+;;;                  50  --  small filled circles with lines to the x-axis
+;;;                  60  --  small filled squares with lines to the x-axis
+;;;                  100  --  lines between successive points
+;;;                The default for the first curve is 0, and for all
+;;;                others 100. 
+;;;    'COLOR:  The color of the curve, as a string or color-value.
+;;;             The default for the first curve is black, and for all
+;;;             others gray. 
+;;;    'SHOW-VALS:  A list of values of x at which to label the
+;;;                 corresponding value of y.  The procedure
+;;;                 MAKE-VALS can be used to return a list of values
+;;;                 at regular intervals.  The default is null.
+;;;
+;;;
+;;;(SET-PLOTTER-PARAMS plotter '<option> <value> ... '<option> <value>)
+;;;  Options are the same as global options in PLOT.  This does
+;;;  basically the same thing as PLOT, but no *new* curve is drawn.
+;;;  Parameters are reset and all the existing (non-cleared) curves
+;;;  are redrawn.  Thus, an alternative way to write the example above
+;;;  is: 
+;;;
+;;;     Example: (set-plotter-params p 'xmin -10 'xmax 5)
+;;;              (define c0 (plot p sin))
+;;;
+;;;(RESET-PLOTTER-PARAMS plotter)
+;;;  Resets plotter's parameters to default params (the ones you see
+;;;  when the plotter first comes up).
+;;;
+;;;
+;;;(MAKE-VALS min max spacing . centered?)
+;;;  Returns a list of pairs that can be used for 'XTICKS 'YTICKS, or
+;;;  'SHOW-VALS. If centered? is #t, the ticks will be centered about
+;;;  0, with a tick at 0.  Otherwise, the ticks will begin at the min
+;;;  value. 
+;;; 
+;;;     Example: (define c0 (plot p sin 'xmin -5 'xmax 5
+;;;                                     'xticks (make-vals -5 5 1)))
+;;;
+;;;(CHANGE-COLOR curve color)
+;;;  Changes the color of the given curve and replots the curve.
+;;;  Replots the curve if it's not cleared.
+;;;
+;;;(CHANGE-PT-STYLE curve pt-style)
+;;;  Changes the point style of the given curve and replots the curve.
+;;;  Replots the curve if it's not cleared.
+;;;
+;;;(CHANGE-NUM-PTS curve num-pts)
+;;;  Changes the number of points calculated for the given curve and
+;;;  replots the curve. Replots the curve if it's not cleared.
+;;;
+;;;
+;;;(CLEAR-CURVE curve)
+;;;  Clears the given curve from the screen without deleting the curve
+;;;  from the plotter.
+;;;
+;;;(PLOT-CURVE curve)
+;;;  Replots the curve that has been cleared.
+;;;
+;;;(DELETE-CURVE curve)
+;;;  Deletes the given curve from the plotter.
+;;;
+;;;(ADD-SHOW-VALS curve show-vals)
+;;;  Add show-vals to a curve.
+;;;
+;;;(CLEAR-SHOW-VALS curve)
+;;;  Clears all the curve's show vals, w/o deleting them from the curve.
+;;;
+;;;(DRAW-SHOW-VALS curve)
+;;;  Redraws the cleared show-vals.
+;;;
+;;;(DELETE-SHOW-VALS curve)
+;;;  Clears the curve's show-vals and deletes them from a curve.
+;;;
+;;;
+;;;(ADD-XTICKS plotter xticks)
+;;;  Adds the specified xticks.
+;;;
+;;;(ADD-YTICKS plotter yticks)
+;;;  Adds the specified yticks.
+;;;
+;;;(CLEAR-TICKS plotter)
+;;;  Clears ticks from the axes of the plotter, without deleting them
+;;;  from the plotter.
+;;;
+;;;(DRAW-TICKS plotter)
+;;;  Redraws the cleared ticks.
+;;;
+;;;(DELETE-TICKS plotter)
+;;;  Clears ticks from the axes of the plotter and deletes them from
+;;;  the plotter.
+;;;
+;;;
+;;;(CLEAR-PLOTTER plotter)
+;;;  Clears all plotter's curves and ticks.
+;;;
+;;;(REPLOT plotter)
+;;;  Redraws all plotter's curves and ticks (including the cleared ones).
+;;;
+;;;(RESET-PLOTTER plotter)
+;;;  Deletes all plotter's curves and ticks.
+
+
+\f
+;;;-------------------
+;;; Interface Monster
+;;;-------------------
+
+;;; Customizable Variables
+
+(define button-background-color "yellow")
+(define button-active-background-color "red")
+(define button-active-foreground-color "white")
+(define canvas-background-color "white")
+(define canvas-width 500)
+(define canvas-height 300)
+(define canvas-border-size 15)
+(define font "-Adobe-Helvetica-Bold-R-Normal--*-100-*")
+
+(define tick-precision 2)
+(define vals-precision 2)
+
+(define curve-max-num-pts 200)
+
+(define plotter-default-num-pts 50)
+(define plotter-default-pt-style 100)
+(define plotter-default-curve-color "black")
+(define plotter-default-xmin -5)
+(define plotter-default-xmax 5)
+(define plotter-default-ymin -1)
+(define plotter-default-ymax 1)
+(define plotter-default-axis-x 0)
+(define plotter-default-axis-y 0)
+(define plotter-default-xticks '())
+(define plotter-default-yticks '())
+
+\f
+(define (plotter)
+  (let* ((plot-app (make-application "Plotter"))
+        (plotter
+         (make-plot-canvas canvas-width canvas-height canvas-background-color))
+        (plot-canvas (plotter 'the-canvas))
+        (func-button (make-button '(-text "Function")))
+        (func-box #f)
+        (options-menu (make-menu))
+        (options-button (make-menubutton options-menu '(-text "Options")))
+        (precision (add-to-menu options-menu 'command '-label "Precision"))
+        (prec-box #f)
+        (range (add-to-menu options-menu 'command '-label "Range"))
+        (range-box #f)
+        (plot-button (make-button '(-text "Plot")))
+        (reset-button (make-button '(-text "Reset")))
+        (button-box (make-hbox func-button options-button plot-button reset-button))
+        (interface (make-vbox plot-canvas button-box)))
+
+      (for-each (lambda (button)
+                 (ask-widget
+                  button
+                  `(configure -background ,button-background-color
+                              -activebackground ,button-active-background-color
+                              -activeforeground ,button-active-foreground-color)))
+               (list func-button options-button plot-button reset-button))
+    
+      (for-each (lambda (button)
+                 (ask-widget
+                  button
+                  `(configure -background ,button-background-color
+                              -activebackground ,button-background-color)))
+               (list range precision))
+    
+      (add-event-handler! plot-canvas "<Configure>" (plotter 'handle-resize))
+
+      (set-callback!
+       func-button
+       (lambda ()
+        (if (not func-box)
+            (let ((new-func-box (make-func-box plot-app plotter)))
+              (on-death! new-func-box 'func-dead (lambda () (set! func-box #f)))
+              (set! func-box new-func-box)))))
+
+      (set-callback!
+       precision
+       (lambda ()
+        (if (not prec-box)
+            (let ((new-prec-box (make-prec-box plot-app plotter)))
+              (on-death! new-prec-box 'prec-dead (lambda () (set! prec-box #f)))
+              (set! prec-box new-prec-box)))))
+
+      (set-callback!
+       range
+       (lambda ()
+        (if (not range-box)
+            (let ((new-range-box (make-range-box plot-app plotter)))
+              (on-death! new-range-box 'range-dead (lambda () (set! range-box #f)))
+              (set! range-box new-range-box)))))
+
+      (set-callback! plot-button (lambda () (plotter 'plot-current-func)))
+      (set-callback! reset-button (lambda () (plotter 'clear-curves)))
+
+      (on-death! interface 'interface-dead 
+                (lambda ()
+                  (if func-box  (remove-child! plot-app func-box))
+                  (if range-box (remove-child! plot-app range-box))
+                  (if prec-box  (remove-child! plot-app prec-box))))
+      
+      (swat-open-in-application plot-app interface)
+      plotter))
+
+(define (make-func-box plot-app plotter)
+  (let* ((func-entry (make-entry `(-width 40 -background ,canvas-background-color)))
+        (func-ok-button
+         (make-button
+          `(-text "Ok" -background ,button-background-color
+            -activebackground ,button-active-background-color
+            -activeforeground ,button-active-foreground-color)))
+        (func-box (make-hbox func-entry func-ok-button)))
+    (define (function-callback)
+      (let ((exp (ask-widget func-entry '(get))))
+       (if (not (string-null? exp))
+           ;; Of course, this could get an error while evaling; maybe
+           ;; need something more clever.
+           (let ((proc (eval (with-input-from-string exp read)
+                             user-initial-environment)))
+             (if (not (procedure? proc))
+                 (error "Not a procedure" proc)
+                 ((plotter 'set-function) proc))))))
+    (add-event-handler! func-entry "<KeyPress> <Return>" function-callback)
+    (set-callback! func-ok-button function-callback)
+    (swat-open-in-application plot-app func-box '-title "Enter a function of x")
+    func-box))
+
+(define (make-prec-box plot-app plotter)
+  (let* ((prec-scale
+         (make-scale `(-from 0 -to ,curve-max-num-pts -orient horizontal
+                       -length ,(inexact->exact (* 1.5 curve-max-num-pts))
+                       -background ,canvas-background-color
+                       -sliderforeground ,button-background-color
+                       -activeforeground ,button-active-background-color)))
+        (prec-redraw
+         (make-button `(-text "Redraw Curves" -background ,button-background-color
+                        -activebackground ,button-active-background-color
+                        -activeforeground ,button-active-foreground-color)))
+        (prec-box (make-vbox prec-scale prec-redraw)))
+    (ask-widget prec-scale `(set ,(plotter 'default-num-pts)))
+    (add-event-handler!
+     prec-scale
+     "<ButtonRelease-1>"
+     (lambda ()
+       ((plotter 'set-default-num-pts)
+       (string->number (ask-widget prec-scale '(get))))))
+    (set-callback! prec-redraw (lambda () (plotter 'plot-curves)))
+    (swat-open-in-application plot-app prec-box '-title "Number of points:")
+    prec-box))
+
+(define (make-range-box plot-app plotter)
+  (let* ((range-ok-button
+         (make-button `(-text "Ok" -background ,button-background-color
+                        -activebackground ,button-active-background-color
+                        -activeforeground ,button-active-foreground-color)))
+        (xmin-text (make-active-variable plot-app))
+        (xmax-text (make-active-variable plot-app))
+        (ymin-text (make-active-variable plot-app))
+        (ymax-text (make-active-variable plot-app))
+        (xmin-entry (make-entry `(-textvariable ,xmin-text)))
+        (xmax-entry (make-entry `(-textvariable ,xmax-text)))
+        (ymin-entry (make-entry `(-textvariable ,ymin-text)))
+        (ymax-entry (make-entry `(-textvariable ,ymax-text)))
+        (x-label (make-label '(-text "Values of x:")))
+        (xmin-label (make-label '(-text "From")))
+        (xmax-label (make-label '(-text "To")))
+        (y-label (make-label '(-text "Values of y:")))
+        (ymin-label (make-label '(-text "From")))
+        (ymax-label (make-label '(-text "To")))
+        (x-box
+         (make-vbox x-label
+                    (make-hbox xmin-label xmin-entry xmax-label xmax-entry)))
+        (y-box
+         (make-vbox y-label
+                    (make-hbox ymin-label ymin-entry ymax-label ymax-entry)))
+        (range-box (make-hbox (make-vbox x-box y-box) range-ok-button)))
+    (for-each (lambda (label)
+               (ask-widget label `(configure -background ,canvas-background-color)))
+             (list x-label xmin-label xmax-label y-label ymin-label ymax-label))
+    (for-each (lambda (entry)
+               ;; background color?
+               (ask-widget entry `(configure -width 5)))
+             (list xmin-entry xmax-entry ymin-entry ymax-entry))
+    (set-callback!
+     range-ok-button
+     (lambda ()
+       (let ((xmin (plotter 'xmin))
+            (xmax (plotter 'xmax))
+            (ymin (plotter 'ymin))
+            (ymax (plotter 'ymax))
+            (new-xmin (string->number (ask-widget xmin-entry '(get))))
+            (new-xmax (string->number (ask-widget xmax-entry '(get))))
+            (new-ymin (string->number (ask-widget ymin-entry '(get))))
+            (new-ymax (string->number (ask-widget ymax-entry '(get)))))
+        (if (not (and (eqv? xmin new-xmin)
+                      (eqv? xmax new-xmax)
+                      (eqv? ymin new-ymin)
+                      (eqv? ymax new-ymax)))
+            (begin
+              ((plotter 'set-xmin) new-xmin)
+              ((plotter 'set-xmax) new-xmax)
+              ((plotter 'set-ymin) new-ymin)
+              ((plotter 'set-ymax) new-ymax)
+              (plotter 'clear)
+              (draw-axes plotter)
+              (plotter 'plot-curves))))))
+    (swat-open-in-application plot-app range-box '-title "Range")
+    (set-active-variable! xmin-text (plotter 'xmin))
+    (set-active-variable! xmax-text (plotter 'xmax))
+    (set-active-variable! ymin-text (plotter 'ymin))
+    (set-active-variable! ymax-text (plotter 'ymax))
+    range-box))
+
+\f
+;;;-------------
+;;; The Plotter
+;;;-------------
+
+(define (make-plot-canvas hsize vsize bgrnd-color)
+  (let ((default-num-pts plotter-default-num-pts)
+       (default-pt-style plotter-default-pt-style)
+       (default-color plotter-default-curve-color)
+       (xmin plotter-default-xmin)
+       (xmax plotter-default-xmax)
+       (ymin plotter-default-ymin)
+       (ymax plotter-default-ymax)
+       (yaxis.xval plotter-default-axis-x)
+       (xaxis.yval plotter-default-axis-y)
+       (xticks plotter-default-xticks)
+       (yticks plotter-default-yticks)
+       (current-func #f)
+       (current-func-curve #f)
+       (curve-list '())
+       (resize-flag #f))
+    (let* ((the-canvas (make-canvas `(-width ,hsize -height ,vsize
+                                     -background ,bgrnd-color)))
+          (axes-tag (make-canvas-item-group the-canvas '()))
+          (ticks-tag (make-canvas-item-group the-canvas '())))
+      (define (plotter messg)
+       (case messg
+         ((hsize) hsize)
+         ((vsize) vsize)
+         ((the-canvas) the-canvas)
+         ((curve-list) curve-list)
+         ((default-num-pts) default-num-pts)
+         ((set-default-num-pts)
+          (lambda (new-num-pts) (set! default-num-pts new-num-pts)))
+         ((default-pt-style) default-pt-style)
+         ((set-default-pt-style)
+          (lambda (new-pt-style) (set! default-pt-style new-pt-style)))
+         ((default-color) default-color)
+         ((set-default-color)
+          (lambda (new-color) (set! default-color new-color)))
+         ((function) current-func)
+         ((set-function)
+          (lambda (func)
+            (set! current-func-curve #f)
+            (set! current-func func)))
+         ((xmin) xmin)
+         ((set-xmin) (lambda (new-xmin) (set! xmin new-xmin)))
+         ((xmax) xmax)
+         ((set-xmax) (lambda (new-xmax) (set! xmax new-xmax)))
+         ((ymin) ymin)
+         ((set-ymin) (lambda (new-ymin) (set! ymin new-ymin)))
+         ((ymax) ymax)
+         ((set-ymax) (lambda (new-ymax) (set! ymax new-ymax)))
+         ((xaxis.yval) xaxis.yval)
+         ((yaxis.xval) yaxis.xval)
+         ((xaxis.y)
+          (let ((y-range (- ymax ymin)))
+            (if (= y-range 0)
+                (error "ymin and ymax are the same--MAKE-PLOT-CANVAS" ymin)
+                (+ (* (exact->inexact (/ (- (* canvas-border-size 2) vsize)
+                                         y-range))
+                      (- xaxis.yval ymin))
+                   vsize
+                   (- canvas-border-size)))))
+         ((yaxis.x)
+          (let ((x-range (- xmax xmin)))
+            (if (= x-range 0)
+                (error "xmin and xmax are the same--MAKE-PLOT-CANVAS" xmin)
+                (+ (* (exact->inexact (/ (- hsize (* canvas-border-size 2))
+                                         (- xmax xmin)))
+                      (- yaxis.xval xmin))
+                   canvas-border-size))))
+         ((xticks) xticks)
+         ((set-xticks) (lambda (new-xticks) (set! xticks new-xticks)))
+         ((yticks) yticks)
+         ((set-yticks) (lambda (new-yticks) (set! yticks new-yticks)))
+         ((axes-tag) axes-tag)
+         ((ticks-tag) ticks-tag)
+         ((set-params)
+          (lambda (new-xmin new-xmax new-ymin new-ymax
+                            new-yaxis.xval new-xaxis.yval new-xticks new-yticks)
+            (set! xmin new-xmin)
+            (set! xmax new-xmax)
+            (set! ymin new-ymin)
+            (set! ymax new-ymax)
+            (set! yaxis.xval new-yaxis.xval)
+            (set! xaxis.yval new-xaxis.yval)
+            (set! xticks new-xticks)
+            (set! yticks new-yticks)
+            'set))
+         ((x:val->pix) (x:val->pix xmin xmax hsize))
+         ((y:val->pix) (y:val->pix ymin ymax vsize))
+         ((add-curve)
+          (lambda (curve) (set! curve-list (append curve-list (list curve)))))
+         ((plot-current-func)
+          (if (and current-func (not current-func-curve))
+              (let ((new-curve
+                     (make-curve plotter current-func default-pt-style
+                                 default-num-pts default-color #f)))
+                (set! current-func-curve new-curve)
+                (set! curve-list (cons new-curve curve-list))
+                (new-curve 'plot))))
+         ((plot-curves)
+          (for-each (lambda (curve)
+                      (if (not (curve 'cleared?))
+                          (curve 'plot)))
+                    curve-list)
+          'plotted)
+         ((clear)
+          (ask-widget the-canvas '(delete all))
+          'cleared)
+         ((clear-curves)
+          (for-each (lambda (curve) (curve 'clear)) curve-list)
+          'cleared)
+         ((delete-curve)
+          (lambda (curve)
+            (curve 'clear)
+            (set! curve-list (delq curve curve-list))
+            'deleted))
+         ((delete-curves)
+          (for-each (lambda (curve) (curve 'clear)) curve-list)
+          (set! curve-list #f)
+          'deleted)
+         ((clear-axes)
+          (ask-widget axes-tag '(delete))
+          'cleared)
+         ((clear-ticks)
+          (ask-widget ticks-tag '(delete))
+          'cleared)
+         ((delete-ticks)
+          (set! xticks '())
+          (set! yticks '())
+          (ask-widget ticks-tag '(delete))
+          'deleted)
+         ((handle-resize)
+          (lambda ()
+            ;; For some reason, the "<Configure>" event gets generated
+            ;; twice per window resize -- so skip one of them.
+            (if (not resize-flag)
+                (set! resize-flag #t)
+                (begin
+                  (set! resize-flag #f)
+                  (ask-widget the-canvas '(delete all))
+                  (let ((old-width hsize)
+                        (width (UITKRectangle.width
+                                (assigned-screen-area the-canvas)))
+                        (height (UITKRectangle.height
+                                 (assigned-screen-area the-canvas))))
+                    (set! hsize width)
+                    (set! vsize height)
+                    (set! default-num-pts (round (* default-num-pts
+                                                    (/ width old-width))))
+                    (draw-axes plotter)
+                    (for-each
+                     (lambda (curve)
+                       (curve-scale-num-pts!
+                        curve (exact->inexact (/ width old-width)))
+                       (if (not (curve 'cleared?))
+                           (begin (curve 'clear)
+                                  (curve 'plot))))
+                     curve-list))))))
+         (else (error "Bad message--PLOTTER" messg))))
+      plotter)))
+\f
+(define ((x:val->pix xmin xmax hsize) x)
+  (+ (* (exact->inexact
+        (/ (- hsize (* canvas-border-size 2))
+           (- xmax xmin)))
+       (- x xmin))
+     canvas-border-size))
+
+(define ((y:val->pix ymin ymax vsize) y)
+  (+ (* (exact->inexact
+        (/ (- (* canvas-border-size 2) vsize)
+           (- ymax ymin)))
+       (- y ymin))
+     vsize
+     (- canvas-border-size)))
+
+(define (draw-xticks plotter)
+  (let ((xticks (plotter 'xticks)))
+    (if xticks
+       (let ((plot-canvas (plotter 'the-canvas))
+             (x:val->pix (plotter 'x:val->pix))
+             (xmin (plotter 'xmin))
+             (xmax (plotter 'xmax))
+             (xaxis.y (plotter 'xaxis.y))
+             (ticks-tag (plotter 'ticks-tag))
+             (factor (expt 10 tick-precision)))
+         (for-each
+          (lambda (tick)
+            (if (> xmax tick xmin)
+                (let ((val (x:val->pix tick))
+                      (tag (swat:number->string
+                            (/ (truncate (* factor tick)) factor))))
+                  (add-to-canvas-item-group
+                   ticks-tag
+                   (make-line-on-canvas plot-canvas
+                                        val (- xaxis.y 4)
+                                        val (+ xaxis.y 4)))
+                  (add-to-canvas-item-group
+                   ticks-tag
+                   (make-text-on-canvas plot-canvas
+                                        val (- xaxis.y 9)
+                                        `(-text ,tag -font ,font))))))
+          xticks))))
+  'drawn)
+
+(define (draw-yticks plotter)
+  (let ((yticks (plotter 'yticks)))
+    (if yticks
+       (let ((plot-canvas (plotter 'the-canvas))
+             (y:val->pix (plotter 'y:val->pix))
+             (ymin (plotter 'ymin))
+             (ymax (plotter 'ymax))
+             (yaxis.x (plotter 'yaxis.x))
+             (ticks-tag (plotter 'ticks-tag))
+             (factor (expt 10 tick-precision)))
+         (for-each
+          (lambda (tick)
+            (if (> ymax tick ymin)
+                (let ((val (y:val->pix tick))
+                      (tag (swat:number->string
+                            (/ (truncate (* factor tick)) factor))))
+                  (add-to-canvas-item-group
+                   ticks-tag
+                   (make-line-on-canvas plot-canvas
+                                        (- yaxis.x 4) val
+                                        (+ yaxis.x 4) val))
+                  (add-to-canvas-item-group
+                   ticks-tag
+                   (make-text-on-canvas plot-canvas
+                                        (+ yaxis.x 6) val
+                                        `(-text ,tag -anchor w
+                                                -font ,font))))))
+          yticks))))
+  'drawn)
+
+(define (draw-axes plotter)
+  (let* ((plot-canvas (plotter 'the-canvas))
+        (hsize (plotter 'hsize))
+        (vsize (plotter 'vsize))
+        (xmin  (plotter 'xmin))
+        (xmax  (plotter 'xmax))
+        (ymin  (plotter 'ymin))
+        (ymax  (plotter 'ymax))
+        (xaxis.yval (plotter 'xaxis.yval))
+        (yaxis.xval (plotter 'yaxis.xval))
+        (xaxis.y (plotter 'xaxis.y))
+        (yaxis.x (plotter 'yaxis.x))
+        (axes-tag (plotter 'axes-tag))
+        (trim 3)
+        (x-.x trim)
+        (x+.x (- hsize trim))
+        (y-.y trim)
+        (y+.y (- vsize trim)))
+    (if (>= ymax xaxis.yval ymin)
+       (begin
+         (add-to-canvas-item-group
+          axes-tag
+          (make-line-on-canvas plot-canvas x+.x xaxis.y x-.x xaxis.y '(-arrow both)))
+         (draw-xticks plotter)
+         (make-text-on-canvas plot-canvas
+                              (- hsize trim) (- xaxis.y trim)
+                              `(-text ,(swat:number->string xmax) -anchor se)) ;
+         (make-text-on-canvas plot-canvas
+                              trim (- xaxis.y trim)
+                              `(-text ,(swat:number->string xmin) -anchor sw))))
+    (if (>= xmax yaxis.xval xmin)
+       (begin
+         (add-to-canvas-item-group
+          axes-tag
+          (make-line-on-canvas plot-canvas yaxis.x y+.y yaxis.x y-.y '(-arrow both)))
+         (draw-yticks plotter)
+         (let ((factor (expt 10 tick-precision)))
+           (make-text-on-canvas plot-canvas
+                                (+ yaxis.x 8) trim
+                                `(-text ,(swat:number->string
+                                          (/ (round (* ymax factor)) factor))
+                                        -anchor nw))
+           (make-text-on-canvas plot-canvas
+                                (+ yaxis.x 8) vsize
+                                `(-text ,(swat:number->string
+                                          (/ (round (* ymin factor)) factor))
+                                        -anchor sw)))))
+    'done))
+\f
+;;;--------
+;;; Curves
+;;;--------
+
+(define (make-curve plotter function pt-style num-pts color show-vals)
+  (let* ((plot-canvas (plotter 'the-canvas))
+        (curve-tag (make-canvas-item-group plot-canvas '()))
+        (outline-tag (make-canvas-item-group plot-canvas '()))
+        (vals-tag (make-canvas-item-group plot-canvas '()))
+        (cleared? #f))
+    (lambda (messg)
+      (case messg
+       ((plotter) plotter)
+       ((num-pts) num-pts)
+       ((set-num-pts) (lambda (new-num-pts) (set! num-pts new-num-pts)))
+       ((show-vals) show-vals)
+       ((set-show-vals) (lambda (new-vals) (set! show-vals new-vals)))
+       ((cleared?) cleared?)
+       ((change-pt-style)
+        (lambda (new-pt-style)
+          (cond ((pt-style? new-pt-style)
+                 (set! pt-style new-pt-style))
+                (else (write-line "Not a style--MAKE-CURVE") pt-style))))
+       ((change-color)
+        (lambda (new-color)
+          (set! color new-color)
+          (if (not cleared?)
+              (begin
+                (ask-widget curve-tag `(configure -fill ,color))
+                (ask-widget outline-tag `(configure -outline ,color))
+                (ask-widget vals-tag `(configure -fill ,color))))))
+       ((get-extreme-vals)
+        (lambda (min max)
+          (get-extreme-vals function min max num-pts)))
+       ((plot)
+        (graph function plotter curve-tag outline-tag pt-style num-pts color)
+        (if show-vals
+            (graph-vals function plotter show-vals vals-tag color))
+        (set! cleared? #f)
+        'plotted)
+       ((draw-vals)
+        (if show-vals
+            (graph-vals function plotter show-vals vals-tag color))
+        'drawn)
+       ((clear-vals)
+        (ask-widget vals-tag '(delete))
+        'cleared)
+       ((delete-vals)
+        (ask-widget vals-tag '(delete))
+        (set! show-vals #f)
+        'removed)
+       ((clear)
+        (ask-widget curve-tag '(delete))
+        (ask-widget outline-tag '(delete))
+        (ask-widget vals-tag '(delete))
+        (set! cleared? #t)
+        'cleared)
+       (else (error "Bad message--MAKE-CURVE" messg))))))
+
+(define (get-extreme-vals function min max num-pts)
+  (let* ((factor (expt 10 vals-precision))
+        (first-val (function min))
+        (min-val first-val)
+        (max-val first-val)
+        (step (exact->inexact (/ (- max min) num-pts))))
+    (define (calculate x)
+      (let ((val (function x)))
+       (cond ((> x max)
+              (list (/ (round (* min-val factor)) factor)
+                    (/ (round (* max-val factor)) factor)))
+             ((< val min-val) (set! min-val val)
+                              (calculate (+ x step)))
+             ((> val max-val) (set! max-val val)
+                              (calculate (+ x step)))
+             (else (calculate (+ x step))))))
+    (calculate (+ min step))))
+
+(define (pt-style? val)
+  (memv val '(0 1 2 3 4 5 6 7 10 20 30 40 50 60 100)))
+
+(define (curve-scale-num-pts! curve factor)
+  ((curve 'set-num-pts) (round (* (curve 'num-pts) factor))))
+
+(define (maybe-replot-curve curve)
+  (if (not (curve 'cleared?))
+      (begin (curve 'clear)
+            (curve'plot))))
+\f
+(define (graph function plotter curve-tag outline-tag pt-style num-pts color)
+  (let ((plot-canvas (plotter 'the-canvas))
+       (xmin (plotter 'xmin))
+       (xmax (plotter 'xmax))
+       (xaxis.yval (plotter 'xaxis.yval))
+       (x:val->pix (plotter 'x:val->pix))
+       (y:val->pix (plotter 'y:val->pix)))
+    (let ((xaxis.y (y:val->pix xaxis.yval)))
+
+      (define (draw-0 x y)
+         (add-to-canvas-item-group
+          curve-tag (make-line-on-canvas plot-canvas x xaxis.y x y)))
+      (define (draw-1 x y)
+       (add-to-canvas-item-group
+        outline-tag
+        (make-oval-on-canvas plot-canvas (- x 3) (- y 3) (+ x 3) (+ y 3))))
+      (define (draw-2 x y)
+       (add-to-canvas-item-group
+        outline-tag 
+        (make-rectangle-on-canvas plot-canvas (- x 3) (- y 3) (+ x 3) (+ y 3))))
+      (define (draw-3 x y)
+       (add-to-canvas-item-group
+        curve-tag 
+        (make-line-on-canvas plot-canvas (- x 2) (- y 2) (+ x 3) (+ y 3)))
+       (add-to-canvas-item-group
+        curve-tag
+        (make-line-on-canvas plot-canvas (+ x 2) (- y 2) (- x 2) (+ y 2))))
+      (define (draw-4 x y)
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas x (- y 2) x (+ y 3)))
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas (- x 2) y (+ x 3) y)))
+      (define (draw-5 x y)
+       (let ((seg (make-oval-on-canvas plot-canvas
+                                       (- x 2) (- y 2) (+ x 2) (+ y 2))))
+         (add-to-canvas-item-group curve-tag seg)
+         (add-to-canvas-item-group outline-tag seg)))
+      (define (draw-6 x y)
+       (let ((seg (make-rectangle-on-canvas plot-canvas
+                                            (- x 2) (- y 2) (+ x 2) (+ y 2))))
+         (add-to-canvas-item-group curve-tag seg)
+         (add-to-canvas-item-group outline-tag seg)))
+      (define (draw-7 x y)
+       (add-to-canvas-item-group
+        curve-tag (make-text-on-canvas plot-canvas x (- y 2) '(-text "."))))
+      (define (draw-10 x y)
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas x xaxis.y x (+ y 3)))
+       (add-to-canvas-item-group
+        outline-tag (make-oval-on-canvas
+                     plot-canvas (- x 3) (- y 3) (+ x 3) (+ y 3))))
+      (define (draw-20 x y)
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas x xaxis.y x (+ y 2)))
+       (add-to-canvas-item-group
+        outline-tag
+        (make-rectangle-on-canvas plot-canvas
+                                  (- x 3) (- y 3) (+ x 3) (+ y 3))))
+      (define (draw-30 x y)
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas
+                                        (- x 2) (- y 2) (+ x 3) (+ y 3)))
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas
+                                        (+ x 2) (- y 2) (- x 2) (+ y 2)))
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas x xaxis.y x y)))
+      (define (draw-40 x y)
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas x (- y 2) x xaxis.y))
+       (add-to-canvas-item-group
+        curve-tag (make-line-on-canvas plot-canvas (- x 2) y (+ x 3) y)))
+      (define (draw-50 x y)
+       (let ((seg1 (make-oval-on-canvas plot-canvas
+                                        (- x 2) (- y 2) (+ x 2) (+ y 2)))
+             (seg2 (make-line-on-canvas plot-canvas x xaxis.y x (+ y 2))))
+         (add-to-canvas-item-group outline-tag seg1)
+         (add-to-canvas-item-group curve-tag seg1)
+         (add-to-canvas-item-group curve-tag seg2)))
+      (define (draw-60 x y)
+       (let ((seg1 (make-rectangle-on-canvas plot-canvas
+                                             (- x 2) (- y 2) (+ x 2) (+ y 2)))
+             (seg2 (make-line-on-canvas plot-canvas x xaxis.y x (+ y 2))))
+         (add-to-canvas-item-group outline-tag seg1)
+         (add-to-canvas-item-group curve-tag seg1)
+         (add-to-canvas-item-group curve-tag seg2)))
+
+      (define (draw-dispatch pt-style)
+       (cond ((= pt-style 0) draw-0)
+             ((= pt-style 1) draw-1)
+             ((= pt-style 2) draw-2)
+             ((= pt-style 3) draw-3)
+             ((= pt-style 4) draw-4)
+             ((= pt-style 5) draw-5)
+             ((= pt-style 6) draw-6)
+             ((= pt-style 7) draw-7)
+             ((= pt-style 10) draw-10)
+             ((= pt-style 20) draw-20)
+             ((= pt-style 30) draw-30)
+             ((= pt-style 40) draw-40)
+             ((= pt-style 50) draw-50)
+             ((= pt-style 60) draw-60)))
+
+      (let* ((draw (draw-dispatch pt-style))
+            (xstep (exact->inexact (/ (- xmax xmin) num-pts))))
+       (define (calc-100 last-x last-y x y)
+         (if (not (> x xmax))
+             (let ((segment
+                    (make-line-on-canvas plot-canvas
+                                         (x:val->pix last-x)
+                                         (y:val->pix last-y)
+                                         (x:val->pix x)
+                                         (y:val->pix y))))
+               (add-to-canvas-item-group curve-tag segment)
+               (calc-100 x y (+ x xstep) (function (+ x xstep))))))
+       (define (calculate x y)
+         (if (not (> x xmax))
+             (begin (draw (x:val->pix x) (y:val->pix y))
+                    (calculate (+ x xstep) (function (+ x xstep))))))
+
+       (if (= pt-style 100)
+           (calc-100 xmin (function xmin) (+ xmin xstep) (function (+ xmin xstep)))
+           (calculate xmin (function xmin)))
+       (ask-widget curve-tag `(configure -fill ,color))
+       (ask-widget outline-tag `(configure -outline ,color))))))
+
+(define (graph-vals function plotter show-vals vals-tag color)
+  (let ((factor (expt 10 vals-precision))
+       (x:val->pix (plotter 'x:val->pix))
+       (y:val->pix (plotter 'y:val->pix))
+       (plot-canvas (plotter 'the-canvas)))
+    (let marker ((show-vals show-vals))
+      (if (not (null? show-vals))
+         (let* ((x-val (car show-vals))
+                (x (x:val->pix x-val))
+                (y-val (function x-val))
+                (y (y:val->pix y-val))
+                (pos-y? (>= y-val (plotter 'xaxis.yval))))
+           (add-to-canvas-item-group
+            vals-tag
+            (make-text-on-canvas
+             plot-canvas x (if pos-y? (- y 3) (+ y 6))
+             `(-text ,(swat:number->string (/ (round (* y-val factor)) factor))
+               -anchor ,(if pos-y? 's 'n))))
+           (add-to-canvas-item-group
+            vals-tag
+            (make-text-on-canvas plot-canvas x y '(-text "|")))
+           (marker (cdr show-vals)))))
+    (ask-widget vals-tag `(configure -fill ,color))))
+
+\f
+;;;-------------------------
+;;; Scheme-prompt Interface
+;;;-------------------------
+
+(define (plot plotter . spec-list)
+  (define (package-curves arg-list)
+    (let package-loop ((result (list (car arg-list)))
+                      (rest (cdr arg-list)))
+      (cond ((null? rest) (list (reverse result)))
+           ((procedure? (car rest))
+            (cons (reverse result) (package-curves rest)))
+           (else (package-loop (cons (car rest) result) (cdr rest))))))
+  (if (not (null? spec-list))
+      (let* ((curve-desc-list (package-curves spec-list))
+            (old-xmin (plotter 'xmin))
+            (old-xmax (plotter 'xmax))
+            (old-ymin (plotter 'ymin))
+            (old-ymax (plotter 'ymax))
+            (old-axis-y (plotter 'xaxis.yval))
+            (old-axis-x (plotter 'yaxis.xval))
+            (old-xticks (plotter 'xticks))
+            (old-yticks (plotter 'yticks))
+            (xmin~ #f) (axis-x~ #f) (num-pts~ #f)
+            (xmax~ #f) (axis-y~ #f) (pt-style~ #f) 
+            (ymin~ #f) (xticks~ #f) (color~ #f)
+            (ymax~ #f) (yticks~ #f) (show-vals~ #f)
+            (default-num-pts  (plotter 'default-num-pts))
+            (default-pt-style (plotter 'default-pt-style))
+            (default-color    (plotter 'default-color))
+            (curve-list '()))
+
+       (define (process-next-curve curve-desc)
+         (let ((f (car curve-desc))
+               (curve-options (cdr curve-desc)))
+           (let curve-loop ((curve-options curve-options))
+             (if (not (null? curve-options))
+                 (let ((option-name (car curve-options)))
+                   (cond ((not (symbol? option-name))
+                          (error "Bad option--PLOT" option-name))
+                         ((null? (cdr curve-options))
+                          (error "PLOT: No value specified for option"
+                                 option-name))
+                         (else
+                          (let ((option-value (cadr curve-options)))
+                            (process-option option-name option-value)
+                            (curve-loop (cddr curve-options))))))))
+           (make-curve plotter
+                       f
+                       (or pt-style~ default-pt-style)
+                       (or num-pts~ default-num-pts)
+                       (or color~ default-color)
+                       show-vals~)))
+
+       (define (process-option name value)
+         (case name
+           ;; global options
+           ((xmin) (if (not xmin~) (set! xmin~ value)))
+           ((xmax) (if (not xmax~) (set! xmax~ value)))
+           ((ymin) (if (not ymin~) (set! ymin~ value)))
+           ((ymax) (if (not ymax~) (set! ymax~ value)))
+           ((axis-x) (if (not axis-x~) (set! axis-x~ value)))
+           ((axis-y) (if (not axis-y~) (set! axis-y~ value)))
+           ((xticks) (if (not xticks~) (set! xticks~ value)))
+           ((yticks) (if (not yticks~) (set! xticks~ value)))
+           ;; curve-specific options
+           ((num-pts) (set! num-pts~ value))
+           ((pt-style) (set! pt-style~ value))
+           ((color) (set! color~ value))
+           ((show-vals) (set! show-vals~ value))
+           (else (error "Illegal option--PLOT" name))))
+
+       (define (reset-options!)
+         (set! num-pts~ #f)
+         (set! pt-style~ #f)
+         (set! color~ #f)
+         (set! show-vals~ #f))
+
+         (let process-loop ((curve-desc-list (reverse curve-desc-list)))
+           (if (not (null? curve-desc-list))
+               (let ((new-curve (process-next-curve (car curve-desc-list))))
+                 ((plotter 'add-curve) new-curve)
+                 (set! curve-list (cons new-curve curve-list))
+                 (reset-options!)
+                 (process-loop (cdr curve-desc-list)))))
+       
+         (let* ((xmin (or xmin~ old-xmin))
+                (xmax (or xmax~ old-xmax))
+                (get-extremes
+                 (lambda (xmin xmax)
+                   (map (lambda (curve) ((curve 'get-extreme-vals) xmin xmax))
+                        curve-list)))
+                (extremes #f)
+                (ymin
+                 (or ymin~
+                     (min
+                      old-ymin
+                      (let ((xtremes (get-extremes xmin xmax)))
+                        (set! extremes xtremes)
+                        (apply min (cons 0 (map (lambda (e) (car e)) xtremes)))))))
+                (ymax
+                 (or ymax~
+                     (max
+                      old-ymax
+                      (let ((xtremes
+                             (if extremes extremes (get-extremes xmin xmax))))
+                        (apply max (cons 0 (map (lambda (e) (cadr e)) xtremes)))))))
+                (axis-y (or axis-y~ old-axis-y))
+                (axis-x (or axis-x~ old-axis-x)))
+
+           (if (and (= xmin old-xmin)
+                    (= xmax old-xmax)
+                    (= ymin old-ymin)
+                    (= ymax old-ymax)
+                    (= axis-x old-axis-x)
+                    (= axis-y old-axis-y)
+                    (equal? xticks~ old-xticks)
+                    (equal? yticks~ old-yticks))
+               ;; only plot the new curves
+               (for-each (lambda (new-curve) (new-curve 'plot))
+                         curve-list)
+               ;; if a global param changed, replot everything
+               (begin
+                 ((plotter 'set-params)
+                  xmin xmax ymin ymax axis-x axis-y xticks~ yticks~)
+                 (plotter 'clear)
+                 (draw-axes plotter)
+                 (plotter 'plot-curves)))
+           
+           ;; return the curve if there's only one, list of curves if more.
+           (and (pair? curve-list)
+                (if (= (length curve-list) 1)
+                    (car curve-list)
+                    curve-list))))))
+
+(define (set-plotter-params plotter . spec-list)
+  (let ((xmin (plotter 'xmin))
+       (xmax (plotter 'xmax))
+       (ymin (plotter 'ymin))
+       (ymax (plotter 'ymax))
+       (axis-x (plotter 'yaxis.xval))
+       (axis-y (plotter 'xaxis.yval))
+       (xticks (plotter 'xticks))
+       (yticks (plotter 'yticks)))
+    (define (process-option name value)
+      (case name
+       ;; global options
+       ((xmin) (set! xmin value))
+       ((xmax) (set! xmax value))
+       ((ymin) (set! ymin value))
+       ((ymax) (set! ymax value))
+       ((axis-x) (set! axis-x value))
+       ((axis-y) (set! axis-y value))
+       ((xticks) (set! xticks value))
+       ((yticks) (set! xticks value))
+       (else (error "Illegal option--SET-PLOTTER-PARAMS" name))))
+    (let process-loop ((options spec-list))
+      (if (not (null? options))
+         (let ((option-name (car options)))
+           (cond ((not (symbol? option-name))
+                  (error "Bad option--PLOT" option-name))
+                 ((null? (cdr options))
+                  (error "SET-PLOTTER-PARAMS: No value specified for option"
+                         option-name))
+                 (else
+                  (let ((option-value (cadr options)))
+                    (process-option option-name option-value)
+                    (process-loop (cddr options))))))))
+    ((plotter 'set-params) xmin xmax ymin ymax axis-x axis-y xticks yticks)
+    (plotter 'clear)
+    (draw-axes plotter)
+    (plotter 'plot-curves)))
+
+(define (reset-plotter-params plotter)
+  (apply set-plotter-params
+        (list 'xmin plotter-default-xmin
+              'xmax plotter-default-xmax
+              'ymin plotter-default-ymin
+              'ymax plotter-default-ymax
+              'axis-x plotter-default-axis-x
+              'axis-y plotter-default-axis-y
+              'xticks plotter-default-xticks
+              'yticks plotter-default-yticks)))
+
+\f
+(define (make-vals min max spacing . center?)
+  (let ((min (if center? (* spacing (round (/ min spacing))) min)))
+    (define (tick-maker val)
+      (if (> val max)
+         '()
+         (cons val (tick-maker (+ val spacing)))))
+    (tick-maker min)))
+
+
+(define (change-color curve color)
+  ((curve 'change-color) color))
+  
+(define (change-pt-style curve pt-style)
+  ((curve 'change-pt-style) pt-style)
+  (maybe-replot-curve curve))
+
+(define (change-num-pts curve num-pts)
+  ((curve 'set-num-pts) num-pts)
+  (maybe-replot-curve curve))
+
+(define (clear-curve curve)
+  (curve 'clear))
+
+(define (plot-curve curve)
+  (if (curve 'cleared?)
+      (curve 'plot)))
+
+(define (delete-curve curve)
+  (((curve 'plotter) 'delete-curve) curve))
+
+(define (add-show-vals curve show-vals)
+  (curve 'clear-vals)
+  ((curve 'set-show-vals)
+   (append (curve 'show-vals) show-vals))
+  (curve 'draw-vals))
+
+(define (clear-show-vals curve)
+  (curve 'clear-vals))
+
+(define (draw-show-vals curve)
+  (curve 'draw-vals))
+
+(define (delete-show-vals curve)
+  (curve 'delete-vals))
+
+                        
+(define (add-xticks plotter xticks)
+  ((plotter 'set-xticks)
+   (append (plotter 'xticks) xticks))
+  (plotter 'clear-axes)
+  (draw-axes plotter))
+
+(define (add-yticks plotter yticks)
+  ((plotter 'set-yticks)
+   (append (plotter 'xticks) yticks))
+  (plotter 'clear-axes)
+  (draw-axes plotter))
+
+(define (clear-ticks plotter)
+  (plotter 'clear-ticks))
+
+(define (draw-ticks plotter)
+  (draw-xticks plotter)
+  (draw-yticks plotter))
+
+(define (delete-ticks plotter)
+  (plotter 'delete-ticks))
+
+(define (clear-plotter plotter)
+  (plotter 'clear-curves)
+  (plotter 'clear-ticks))
+
+(define (replot plotter)
+  (draw-ticks plotter)
+  (for-each plot-curve (plotter 'curve-list))
+  'replotted)
+
+(define (reset-plotter plotter)
+  (plotter 'delete-curves)
+  (plotter 'delete-ticks)
+  (plotter 'clear)
+  (draw-axes plotter)
+  'reset)
+  
diff --git a/v7/src/swat/scheme/other/pole-zero.scm b/v7/src/swat/scheme/other/pole-zero.scm
new file mode 100644 (file)
index 0000000..708f548
--- /dev/null
@@ -0,0 +1,495 @@
+;;; -*- Scheme -*-
+
+(declare (usual-integrations))
+
+;;;Demo of DT frequency response by frobbing poles and zeros
+
+(define half-window-size 200)
+(define zero-size 5)
+(define pole-size 4)
+(define trim 10)
+(define zero-color "violetred")
+(define pole-color "blue")
+(define canvas-color "white")
+(define text-font "CourR12")
+
+
+(define symbol-font
+  "-adobe-symbol-medium-r-normal--14-100-100-100-p-85-adobe-fontspecific")
+
+(define tracking-coords? #F)
+(define time-to-update-plot? #F)
+(define LOCATION 'later)       ; active variable
+(define all-zeros '())         ; alist of zeros(objects)/coords
+(define all-poles '())         ; alist of poles(objects)/coords
+
+(define number-of-points 100)
+(define max-w  3.14159)
+
+;;hack to print numbers to three decimals
+(define (unsigned->string n)
+  (let* ((int-part (floor n))
+        (frac-part (- n int-part))
+        (dec (floor->exact (* frac-part 1000)))
+        (string-dec (number->string dec))
+        (padded-string-dec
+         (cond ((< dec 10) (string-append "00" string-dec))
+               ((< dec 100) (string-append "0" string-dec))
+               (else string-dec))))
+    (string-append (number->string (floor->exact int-part))
+                  "."
+                  padded-string-dec)))
+
+(define (our-cx->string z)
+  (let* ((r (real-part z))
+        (i (imag-part z))
+        (rs (unsigned->string (abs r)))
+        (is (unsigned->string (abs i)))
+        (signed-r
+         (if (< r 0)
+             (string-append "-" rs)
+             rs))
+        (signed-i
+         (if (< i 0)
+             (string-append "-" is)
+             (string-append "+" is))))
+    (string-append signed-r signed-i "j")))
+
+(define (our-real->string r)
+  (let* ((rs (unsigned->string (abs r)))
+        (signed-r
+         (if (< r 0)
+             (string-append "-" rs)
+             rs)))
+    signed-r))
+
+
+(define (z->canvas-coords z)
+  (let ((x (real-part z))
+       (y (imag-part z)))
+    (list 
+     (round->exact
+      (+ (* x (- half-window-size (* 2 trim)))
+        half-window-size))
+     (round->exact
+      (+ (* y (- (* 2 trim) half-window-size))
+        half-window-size)))))
+
+(define (canvas-coords->z xy)
+  (let ((x (exact->inexact (car xy)))
+       (y (exact->inexact (cadr xy))))
+    (let ((real (/ (- x half-window-size)
+                  (- half-window-size (* 2 trim))))
+         (imag (/ (- y half-window-size)
+                  (- (* 2 trim) half-window-size))))
+      (+ real (* imag +i)))))
+
+;;; Pole/Zero Movement
+(define (move-with-conjugate-pair pole-zero obj1 obj2)
+  (let ((last-x 'later)
+       (last-y 'later))
+    (define (keep-track-of-coords x y)
+      (set! last-x x)
+      (set! last-y y)
+      (if tracking-coords?
+         (let ((z (canvas-coords->z (list last-x last-y))))
+           (set-active-variable! LOCATION (our-cx->string z)))))
+    (define (store-coords)
+      (let* ((zero-entry (assq obj1 all-zeros))
+            (obj1-entry
+             (if zero-entry zero-entry (assq obj1 all-poles)))
+            (obj2-entry
+             (if zero-entry
+                 (assq obj2 all-zeros)
+                 (assq obj2 all-poles)))
+            (z (canvas-coords->z (list last-x last-y))))
+       (set-cdr! obj1-entry z)
+       (set-cdr! obj2-entry (conjugate z))))
+    (add-event-handler!
+     obj1
+     "<ButtonPress-1>"
+     (lambda (x y)
+       (set! time-to-update-plot? #F)
+       (keep-track-of-coords x y))
+     "%x" "%y")
+    (add-event-handler!
+     obj1
+     "<ButtonRelease-1>"
+     (lambda ()
+       (store-coords)
+       (maybe-update-plot (pole-zero 'graph-canvas))
+       ))
+    (add-event-handler!
+     obj1
+     "<B1-Motion>"
+     (lambda (x y)
+       (ask-widget obj1 `(move ,(- x last-x) ,(- y last-y)))
+       (ask-widget obj2 `(move ,(- x last-x) ,(- last-y y)))
+       (keep-track-of-coords x y))
+     "%x" "%y")))
+
+(define (move-by-itself pole-zero obj)
+  (let ((last-x 'later))
+    (define (keep-track-of-coords x)
+      (set! last-x x)
+      (let ((z (canvas-coords->z (list last-x half-window-size))))
+       (if tracking-coords?
+           (set-active-variable! LOCATION (our-real->string z)))))
+    (define (store-coords)
+      (let ((entry
+            (let ((zero (assq obj all-zeros)))
+              (if zero zero (assq obj all-poles))))
+           (z (real-part (canvas-coords->z (list last-x 0)))))
+       (set-cdr! entry z)))
+    (add-event-handler!
+     obj
+     "<ButtonPress-1>"
+     (lambda (x)
+       (set! time-to-update-plot? #F)
+       (keep-track-of-coords x))
+     "%x")
+    (add-event-handler!
+     obj
+     "<ButtonRelease-1>"
+     (lambda ()
+       (store-coords)
+       (maybe-update-plot (pole-zero 'graph-canvas))
+       ))
+    (add-event-handler!
+     obj
+     "<B1-Motion>"
+     (lambda (x)
+       (ask-widget obj `(move ,(- x last-x) 0))
+       (keep-track-of-coords x))
+     "%x")))
+
+
+;;; This isn't quite right.  Time-to-update-plot? might be set to #F
+;;; and then back to #T inside the 2 sec interval, so the update will
+;;; come too soon.
+(define (maybe-update-plot graph-canvas)
+  (set! time-to-update-plot? #T)
+  (after-delay
+   2
+   (lambda ()
+     (if time-to-update-plot?
+        (plot-pole-zero graph-canvas)))))
+
+
+;;; Zeros
+(define (make-zero canvas xy)
+  (let ((x (car xy))
+       (y (cadr xy)))
+    (let ((zero
+          (make-oval-on-canvas canvas
+                               (- x zero-size) (- y zero-size)
+                               (+ x zero-size) (+ y zero-size))))
+      (set! all-zeros (cons (cons zero (canvas-coords->z xy))
+                           all-zeros))
+      (ask-widget zero `(configure -outline ,zero-color -fill ,canvas-color -width 2))
+      zero)))
+
+(define (make-single-zero pole-zero x)
+  (let ((canvas (pole-zero 'diagram-canvas)))
+    (let ((z (make-zero canvas (list x half-window-size))))
+      (move-by-itself pole-zero z)
+      z)))
+
+(define (make-zero-pair pole-zero x y)
+  (let ((canvas (pole-zero 'diagram-canvas)))
+    (let ((zero (canvas-coords->z (list x y))))
+      (let ((other-pos
+            (z->canvas-coords (conjugate zero))))
+       (let ((z1 (make-zero canvas (list x y)))
+             (z2 (make-zero canvas other-pos)))
+         (move-with-conjugate-pair pole-zero z1 z2)
+         (move-with-conjugate-pair pole-zero z2 z1))))))
+
+
+;;; Poles
+(define (make-pole canvas xy)
+  (let ((x (car xy))
+       (y (cadr xy)))
+    (let* ((line1
+           (make-line-on-canvas canvas
+                                (- x pole-size) (- y pole-size)
+                                (+ x pole-size) (+ y pole-size)))
+          (line2 
+           (make-line-on-canvas canvas
+                                (- x pole-size) (+ y pole-size)
+                                (+ x pole-size) (- y pole-size)))
+          (pole (make-canvas-item-group canvas (list line1 line2))))
+      (set! all-poles (cons (cons pole (canvas-coords->z xy))
+                           all-poles))
+      (ask-widget pole `(configure -fill ,pole-color -width 2))
+      pole)))
+
+(define (make-single-pole pole-zero x)
+  (let ((canvas (pole-zero 'diagram-canvas)))
+    (let ((p (make-pole canvas (list x half-window-size))))
+      (move-by-itself pole-zero p)
+      p)))
+
+(define (make-pole-pair pole-zero x y)
+  (let ((canvas (pole-zero 'diagram-canvas)))
+    (let ((pole (canvas-coords->z (list x y))))
+      (let ((other-pos
+            (z->canvas-coords (conjugate pole))))
+       (let ((p1 (make-pole canvas (list x y)))
+             (p2 (make-pole canvas other-pos)))
+         (move-with-conjugate-pair pole-zero p1 p2)
+         (move-with-conjugate-pair pole-zero p2 p1))))))
+
+;;; Button that switches from one label to another
+
+(define (make-switch color to-switch)
+  ;;to-switch is list ((text command) (text command))
+  (let ((n (length to-switch))
+       (button (make-button))
+       (state #F))
+    (define (switch-to-state i)
+      (set! state i)
+      ((cadr (list-ref to-switch i)))
+      (ask-widget button `(configure -text ,(car (list-ref to-switch i)))))
+    (ask-widget button `(configure -background ,color))
+    (switch-to-state 0)
+    (set-callback! button
+                  (lambda ()
+                    (switch-to-state (modulo (+ state 1) n))))
+    button))
+
+;;; Demo
+(define (make-pole-zero)
+  (set! all-zeros '())
+  (set! all-poles '())
+  (let ((diagram-canvas (make-canvas `(-width ,(* 2 half-window-size)
+                                      -height ,(* 2 half-window-size))))
+       (graph-canvas #F)
+       (pz 'later)
+       (shape-size 'later)
+       (single-maker 'later)
+       (pair-maker 'later))
+    
+    (define (switch-to-zeros)
+      (set! shape-size zero-size)
+      (set! single-maker make-single-zero)
+      (set! pair-maker make-zero-pair))
+
+    (define (switch-to-poles)
+      (set! shape-size pole-size)
+      (set! single-maker make-single-pole)
+      (set! pair-maker make-pole-pair))
+
+    (let* ((maker-button (make-switch "yellow"
+                                     `(("Zeros" ,switch-to-zeros)
+                                       ("Poles" ,switch-to-poles))))
+          (clear-button (make-button '(-text "Clear")))
+          (show-coords? (make-active-variable))
+          (coords-button
+           (make-checkbutton `(-text "Show Coords?" -variable ,show-coords?)))
+          (coords-display (make-label))
+          (plot-button (make-button '(-text "Plot"))))
+
+      (set! LOCATION (make-active-variable))
+      (ask-widget coords-display `(configure -width 13 -background ,canvas-color
+                                            -relief sunken -textvariable ,LOCATION
+                                            -font ,text-font))
+      (for-each (lambda (b)
+                 (ask-widget b `(configure -background "yellow" -font ,text-font)))
+               (list maker-button clear-button  coords-button plot-button))
+      (ask-widget diagram-canvas `(configure -background ,canvas-color))
+      (on-death! diagram-canvas 'little-brother-canvas
+                (lambda () (if graph-canvas (swat-close graph-canvas))))
+      
+      (set-callback!
+       clear-button
+       (lambda ()
+        (for-each (lambda (entry) (ask-widget (car entry) '(delete)))
+                  all-zeros)
+        (for-each (lambda (entry) (ask-widget (car entry) '(delete)))
+                  all-poles)
+        (set-active-variable! LOCATION "")
+        (cond (graph-canvas
+               (ask-widget graph-canvas '(delete all))
+               (draw-axes graph-canvas)))
+        (set! all-zeros '())
+        (set! all-poles '())))
+
+      (set-callback!
+       coords-button
+       (lambda ()
+        (if (checkbutton-variable-on? show-coords?)
+            (set! tracking-coords? #T)
+            (begin
+              (set-active-variable! LOCATION "")
+              (set! tracking-coords? #F)))))
+      (set-callback!
+       plot-button
+       (lambda ()
+        (cond ((not graph-canvas)
+               (set! graph-canvas
+                     (make-canvas `(-width ,(* 2 half-window-size)
+                                    -height ,(* 2 half-window-size))))
+               (ask-widget graph-canvas `(configure -background ,canvas-color))
+               (swat-open graph-canvas '-title "Magnitude of Frequency Response")
+               (on-death! graph-canvas 'big-brother-canvas
+                          (lambda () (set! graph-canvas #F)))))
+        (plot-pole-zero graph-canvas)))
+      (add-event-handler!
+       diagram-canvas
+       "<Double-ButtonPress-1>"
+       (lambda (x y)
+        (set! time-to-update-plot? #F)
+        (if (< (abs (- y half-window-size)) shape-size)
+            (single-maker pz x)
+            (pair-maker pz x y)))
+       "%x" "%y")
+
+      (let ((me (make-vbox diagram-canvas
+                          (make-hbox maker-button clear-button coords-button
+                                     coords-display plot-button))))
+       (swat-open me '-title "Pole-Zero Diagram")
+       (let ((x-axis (make-line-on-canvas
+                      diagram-canvas
+                      trim half-window-size
+                      (- (* 2 half-window-size) trim) half-window-size))
+             (y-axis (make-line-on-canvas
+                      diagram-canvas
+                      half-window-size trim
+                      half-window-size (- (* 2 half-window-size) trim)))
+             (unit-circle (make-oval-on-canvas
+                           diagram-canvas
+                           (* 2 trim) (* 2 trim)
+                           (* 2 (- half-window-size trim))
+                           (* 2 (- half-window-size trim)))))
+         (ask-widget x-axis '(configure -arrow last))
+         (ask-widget y-axis '(configure -arrow first))
+         (ask-widget unit-circle '(configure -outline "gray")))
+
+       (set! pz
+             (lambda (message)
+                     (case message
+                       ((graph-canvas) graph-canvas)
+                       ((diagram-canvas) diagram-canvas)
+                       ((add-zero)
+                        (lambda (z)
+                          (let ((xy (z->canvas-coords z)))
+                            (if (= (imag-part z) 0)
+                                (make-single-zero pz (car xy))
+                                (make-zero-pair pz (car xy) (cadr xy))))))
+                       ((add-pole)
+                        (lambda (p)
+                          (let ((xy (z->canvas-coords p)))
+                            (if (= (imag-part p) 0)
+                                (make-single-pole pz (car xy))
+                                (make-pole-pair pz (car xy) (cadr xy))))))
+                       (else "Unknown message -- MAKE-POLE-ZERO" message))))
+       pz))))
+       
+
+(define (add-butterworth-poles pole-zero-diagram n)
+  (define pi (* (atan 1 1) 4))
+  (define (make-index-list n start)
+    (if (> start n)
+       '()
+       (cons start (make-index-list n (+ start 1)))))
+  (let ((index-list (make-index-list n (+ (ceiling->exact (/ n 2)) 1)))
+       (w (exp (/ (* 2 +i pi) (* 2 n)))))
+    (for-each (lambda (pole)
+               ((pole-zero-diagram 'add-pole) pole))
+             (map (lambda (s)
+                    (let ((t 1))
+                      (/ (+ 1 (* (/ t 2) s))
+                         (- 1 (* (/ t 2) s)))))
+                  (map (lambda (k) (expt w (- k .5)))
+                       index-list)))
+    (let loop ((z 1))
+      (if (> z n)
+         'done
+         (begin ((pole-zero-diagram 'add-zero) -1)
+                (loop (1+ z)))))
+    (plot-pole-zero (pole-zero-diagram 'graph-canvas))))
+         
+
+(define (plot-pole-zero graph-canvas)
+  (cond (graph-canvas
+        (ask-widget graph-canvas '(delete all))
+        (draw-axes graph-canvas)
+        (plot-magnitude graph-canvas))))
+      
+(define (plot-magnitude graph-canvas)
+  (let ((zero-locations (map cdr all-zeros))
+       (pole-locations (map cdr all-poles)))
+    (let ((fcn
+          (lambda (x)
+            (let ((jw (exp (* x +i))))
+              (let ((numer
+                     (apply * (map (lambda (z) (magnitude (- jw z)))
+                                   zero-locations)))
+                    (denom
+                     (apply * (map (lambda (z) (magnitude (- jw z)))
+                                   pole-locations))))
+                (if (< denom 1.e-10)
+                    1.e5
+                    (/ numer denom)))))))
+      (plot-graph-on-canvas
+       graph-canvas
+       (let loop ((index 0) (points '()))
+        (if (> index number-of-points)
+            points
+            (let ((w (* index (/ max-w number-of-points))))
+              (loop (+ index 1)
+                    (cons (cons w (fcn w)) points)))))))))
+
+(define (plot-graph-on-canvas canvas graph)
+  (let* ((maxval (apply max (map cdr graph)))
+        (canvas-points
+         (map (lambda (graph-point)
+                (magnitude-coords->canvas-coords graph-point maxval))
+              graph)))
+    (let loop ((rest-points (cdr canvas-points))
+              (this-point (car canvas-points)))
+      (if (null? rest-points)
+         'done
+         (let ((next-point (car rest-points)))
+           (make-line-on-canvas canvas
+                                (car this-point)
+                                (cdr this-point)
+                                (car next-point)
+                                (cdr next-point))
+           (loop (cdr rest-points)
+                 (car rest-points)))))
+    (let ((maxval-display
+          (make-text-on-canvas
+           canvas (* 3 trim) (* 2 trim) `(-text ,(our-real->string maxval)))))
+      (ask-widget maxval-display
+                 `(configure -anchor sw -font ,symbol-font)))))
+
+
+(define (magnitude-coords->canvas-coords xy max-mag)
+  (let ((x (car xy))
+       (y (cdr xy)))
+    (cons (round->exact (+ (* x (/ (- (* 2 half-window-size) (* 4 trim)) max-w))
+                          (* 2 trim)))
+         (round->exact (+ (* y (/ (- (* 4 trim) (* 2 half-window-size)) max-mag))
+                          (* 2 (- half-window-size trim)))))))
+
+         
+(define (draw-axes graph-canvas)
+  (let ((x-axis (make-line-on-canvas
+                graph-canvas
+                trim (* 2 (- half-window-size trim))
+                (- (* 2 half-window-size) trim)
+                (* 2 (- half-window-size trim))))
+       (y-axis (make-line-on-canvas
+                graph-canvas
+                (* 2 trim) trim
+                (* 2 trim) (- (* 2 half-window-size) trim)))
+       (pi (make-text-on-canvas
+            graph-canvas
+            (* 2 (- half-window-size trim)) (- (* 2 half-window-size) trim)
+            '(-text "p"))))
+    (ask-widget x-axis '(configure -arrow last))
+    (ask-widget y-axis '(configure -arrow first))
+    (ask-widget pi `(configure -anchor e -font ,symbol-font))))
+
diff --git a/v7/src/swat/scheme/other/rtest.scm b/v7/src/swat/scheme/other/rtest.scm
new file mode 100644 (file)
index 0000000..076b6fe
--- /dev/null
@@ -0,0 +1,175 @@
+;;; -*- Scheme -*-
+
+;; to make this possible to debug
+
+; (set! *unparser-list-breadth-limit* 10)
+; (set! *unparser-list-depth-limit* 10)
+
+
+;; GC stress test
+
+(define (a)
+  (gc-flip)
+  (gc-flip)
+  (kick-uitk-thread)
+  (gc-flip)
+  (gc-flip)
+  (kick-uitk-thread))
+
+(define (foo test n)
+  (if (> n 0)
+      (begin
+       (test)
+       (foo test (- n 1)))))
+
+(define (foo2 test n)
+  (if (> n 0)
+      (begin
+       (display n)
+       (test)
+       (gc-flip)
+       (foo2 test (- n 1)))))
+
+
+;; Support for GC debugging
+
+(define gctr (make-primitive-procedure 'gc-trace-references))
+(define refs (make-vector 40))
+
+(define (go obj)
+  (gctr obj refs)
+  (gc-flip)
+  (write-line (list (vector-ref refs 0) (map object-type (vector->list refs)))))
+
+(define (get n) (vector-ref refs n))
+
+
+;; Test the Rectangle widget
+
+;; (define application (make-application "Test Scheme Application"))
+
+(define (make-picture)
+  (define v1 (make-self-painting-rectangle 50 30 "yellow"))
+  (define v2 (make-self-painting-rectangle 100 10 "blue"))
+  (define v3 (make-self-painting-rectangle 10 100 "orange"))
+  
+  (define topframe (make-vbox v1 v2 v3))
+  
+  (define h1 (make-self-painting-rectangle 10 10 "white"))
+  (define h2 (make-self-painting-rectangle 20 20 "gold"))
+  (define h3 (make-self-painting-rectangle 30 30 "green"))
+  
+  (define bottomframe (make-hbox h1 h2 h3))
+  
+  (make-hbox topframe bottomframe))
+
+(define (make-bad-picture)
+  (define v1 (make-rect 50 30 "yellow"))
+  (define v2 (make-rect 100 10 "blue"))
+  (define v3 (make-rect 10 100 "orange"))
+  
+  (define topframe (make-vbox v1 v2 v3))
+  
+  (define h1 (make-rect 10 10 "white"))
+  (define h2 (make-rect 20 20 "gold"))
+  (define h3 (make-rect 30 30 "green"))
+  (set! green h3)
+  
+  (define bottomframe (make-hbox h1 h2 h3))
+  
+  (make-hbox topframe bottomframe))
+
+(define (simple-picture)
+ (swat-open (make-self-painting-rectangle 50 30 "yellow")))
+
+(define (test0)
+  (simple-picture)
+  3)
+
+(define (test1)
+  (swat-open (make-picture))
+  3)
+
+(define (test1a)
+  (swat-open (make-picture))
+  (swat-open (make-picture))
+  3)
+
+(define app2)
+(define (test2)
+  (set! app2  (make-application "Test2-2 "))
+  (add-child! app2 (make-picture))
+  (swat-open (make-picture))
+  (swat-open (make-picture))
+  (swat-open (make-picture))
+  (swat-open (make-picture))
+  (swat-open (make-picture))
+  (swat-open (make-picture))
+  (add-child! app2 (make-picture))
+  (add-child! app2 (make-picture))
+  (add-child! app2 (make-picture))
+  (add-child! app2 (make-picture))
+  3)
+
+(define (make-switch color to-switch)
+  ;;to-switch is list ((text command) (text command))
+  (let ((n (length to-switch))
+       (button (make-button))
+       (state #F))
+    (define (switch-to-state i)
+      (set! state i)
+      ((cadr (list-ref to-switch i)))
+      (ask-widget button `(configure -text ,(car (list-ref to-switch i)))))
+    (ask-widget button `(configure -background ,color))
+    (switch-to-state 0)
+    (set-callback! button
+                  (lambda ()
+                    (switch-to-state (modulo (+ state 1) n))))
+    button))
+
+(define debug-test3)
+(define (test3)
+  (let* ((surface (make-shape-surface 600 600 "white" "red"))
+        (button1 (make-button '(-text "PANIC!")))
+        (button2 (make-button '(-text "SET COLOR")))
+        (button3 (make-switch
+                  "yellow"
+                  `(("Ovals" ,(lambda () (surface 'ovals)))
+                    ("Rectangles" ,(lambda () (surface 'rectangles))))))
+        (button4 (make-switch
+                  "yellow"
+                  `(("Outlined" ,(lambda () (surface 'outlined)))
+                    ("Filled" ,(lambda () (surface 'filled))))))
+        (e (make-entry '(-width 10))))
+    (define (handle-bad-color)
+      (ask-widget button2 '(configure -background red))
+      (ask-widget button2 '(flash))
+      (ask-widget button2 '(flash))
+      (ask-widget e `(delete 0 end))
+      (ask-widget e `(insert 0 red))
+      ((surface 'set-color!) "red"))
+    (define (change-color)
+      (let ((new-color (ask-widget e '(get))))
+       (if (valid-color? new-color)
+           (begin ((surface 'set-color!) new-color)
+                  (ask-widget button2
+                              `(configure -background ,new-color)))
+           (handle-bad-color))))
+    (set! debug-test3 (lambda () #f))
+    (ask-widget button1 '(configure
+                         -background green -activebackground red
+                         -font "-adobe-helvetica-bold-r-normal--34-240-100-100-p-182-iso8859-1"))
+    (ask-widget button2 '(configure -background red -activebackground white))
+    (ask-widget e '(configure -background white -foreground black -relief sunken))
+    (ask-widget e '(insert 0 red))
+    (set-callback! button1 (lambda () (surface 'clear)))
+    (set-callback! button2 change-color)
+    (let ((me (make-vbox (surface 'the-surface)
+                        (make-hbox button1 e
+                                   button2 button3 button4))))
+      (swat-open me '-title "Featureless Drawing Program")
+      me)))
+
+
+
+
diff --git a/v7/src/swat/scheme/other/test-load.scm b/v7/src/swat/scheme/other/test-load.scm
new file mode 100644 (file)
index 0000000..5a1f01f
--- /dev/null
@@ -0,0 +1,34 @@
+; These get overriden when TK is loaded
+(define (tk-doevents) 'tk-doevents)
+(define (tk-init dsp) 'tk-init)
+
+(with-working-directory-pathname
+ "/scheme/8.0/700/swat2/scheme"
+ (lambda ()
+   ; Dynamically load the microcode
+   (load "../c/scxl")
+   (load "../c/uitk")
+   
+   ; And now the Scheme level
+   ;;(load "scc-macros")
+   ;;(load "uitk-macros")
+   (load "control-floating-errors")
+   (load "structures")
+   (load "structures2")
+   (load "generics")
+   (load "uitk")
+   (load "xlibCONSTANTS")
+   (load "mit-xlib")
+   (load "tk-mit")
+   (load "mit-xhooks")
+   (load "widget-mit")
+   (load "baseobj")
+   (load "widget")
+   (load "geometry")
+   (load "simple")
+   (load "canvas")
+   (load "menu")
+   (load "text")
+   ;;(load "rtest")
+   ;;(load "btest")
+   ))
diff --git a/v7/src/swat/scheme/other/test.scm b/v7/src/swat/scheme/other/test.scm
new file mode 100644 (file)
index 0000000..f950e50
--- /dev/null
@@ -0,0 +1,40 @@
+  (define b1 (make-button '(-text "button1")))
+  (define b2 (make-button '(-text "button2")))
+  (define b3 (make-button '(-text "button3")))
+  (define b4 (make-button '(-text "button4")))
+  (define b5 (make-button '(-text "button5")))
+  (define b6 (make-button '(-text "very very long button6")))
+  (define b7 (make-button '(-text "b7")))
+  (define b8 (make-button '(-text "b8")))
+  (define b9 (make-button '(-text "b9")))
+  (define s (make-space))
+
+  (define a (make-application "test"))
+  (define ab (make-array-box (list b1 'left b3)
+                            (list 'up 'up b6)
+                            (list b7 b8 b9)))
+  (add-child! a ab)
+
+(define (test2)
+  (define c (make-canvas '(-width 300 -height 300 -background white)))
+  (define b1 (make-button '(-text "button1" -background red)))
+  (define b2 (make-button '(-text "button2" -background red)))
+  (define b3 (make-button '(-text "button3" -background red)))
+  (define s1 (make-space '(-background red)))
+  (define s2 (make-space '(-background red)))
+  (define hb (make-hbox s1 b1 b2 s2 b3))
+  (define vb (make-vbox c hb))
+  (define a (make-application "test"))
+  (add-child! a vb)
+  a)
+
+#|
+(define c (make-canvas '(-width 200 -height 200)))
+(define b1 (make-button '(-text "button1")))
+(define b2 (make-button '(-text "button2")))
+(define box1 (make-hbox b1 b2))
+(define box2 (make-vbox c box1))
+(define a (make-application "test"))
+(add-child! a box2)
+
+|#
\ No newline at end of file
diff --git a/v7/src/swat/scheme/other/unhash-testing.scm b/v7/src/swat/scheme/other/unhash-testing.scm
new file mode 100644 (file)
index 0000000..108519e
--- /dev/null
@@ -0,0 +1,127 @@
+;;; -*- Scheme -*-
+
+(declare (usual-integrations)
+        (integrate-external "/scheme/700/runtime/hash"))
+
+(using-syntax syntax-table/system-internal
+  (define foo-1 'invalid-rehash)
+  (define foo-2 'invalid-bucket)
+  (define foo-3 'unhash-table)
+  (define (foo)
+    (set! foo-1 3)
+    (set! foo-2 3)
+    (set! foo-3 3))
+
+(define *do-validation?* #T)
+
+  (define (count-unhash-table uht)
+    (let ((count 0))
+      (do ((i 0 (+ i 1)))
+         ((= i (vector-length uht)) count)
+       (set! count (+ count (length (cdr (vector-ref uht i))))))))
+
+  (define (valid-bucket-contents? table when y full?)
+    (define (valid? x)
+      (and (list? x)
+          (or (null? x)
+              (and (pair? x)
+                   (weak-pair? (car x))
+                   (let ((hash-number (weak-cdr (car x))))
+                     (and (number? hash-number)
+                          (or (not full?)
+                              (not (weak-car (car x)))
+                              (= hash-number (hash (weak-car (car x)) table))
+                              (let ((table (car (cons table #f)))
+                                    (x (car (cons x #f)))
+                                    (y (car (cons y #f)))
+                                    (forty-two (car (cons 42 #f))))
+                                (write-line
+                                 (list "invalid rehash" when table hash-number (car x)))
+                                (table)
+                                (list table x y forty-two)))))
+                   (valid? (cdr x))))))
+    (or (valid? y)
+       (begin 
+         (write-line (list "Invalid unhash bucket" table when))
+         (+ 2 foo-2))))
+
+  (define (validate table when full?)
+    (if *Do-Validation?*
+       (fluid-let ((*Do-Validation?* #F))
+         (let ((uht (hash-table/unhash-table table)))
+           (for-each
+            (lambda (bucket)
+              (valid-bucket-contents? table when (cdr bucket) full?))
+            (vector->list uht))))
+       'OK))
+
+  (define (show-unhash-table uht)
+    (for-each
+     (lambda (x) (if (not (number? x))
+                    (begin
+                      (write-line (list "show-unhash-table: not a number" x))
+                      (+ 3 foo-3)))
+            (display x)
+            (display #\space))
+     (reduce append '()
+            (map (lambda (bucket)
+                   (map weak-cdr (cdr bucket)))
+                 (vector->list uht))))
+    (newline))
+
+  (define (our-rehash-all-gc-daemon)
+    (let loop ((l all-hash-tables)
+              (n (weak-cdr all-hash-tables)))
+      (cond ((null? n)
+            (weak-set-cdr! l n))
+           ((not (weak-pair/car? n))
+            (loop l (weak-cdr n)))
+           (else
+            (weak-set-cdr! l n)
+            (let* ((table (weak-car n)))
+              (validate table 'before #F)
+              ; (write-line (list 'before (count-unhash-table uht)))
+              (hash-table/rehash table)
+              (validate table 'after #T)
+              ; (write-line (list 'after (count-unhash-table uht)))
+              ; (show-unhash-table uht)
+              (loop n (weak-cdr n)))))))
+
+  (delq! rehash-all-gc-daemon
+        (access gc-daemons (->environment '(runtime gc-daemons))))
+  (add-gc-daemon! our-rehash-all-gc-daemon)
+
+  (let ((old-hash object-hash))
+    (set! object-hash
+         (lambda (object #!optional table insert?)
+           (let ((table
+                  (if (default-object? table)
+                      default-hash-table
+                      (begin
+                        (if (not (hash-table? table))
+                            (error:wrong-type-argument table
+                                                       "object-hash table"
+                                                       'OBJECT-HASH))
+                        table)))
+                 (insert? (or (default-object? insert?) insert?)))
+             (let ((result (old-hash object table insert?)))
+               (validate table 'hash #F)
+               result)))))
+
+  (let ((old-unhash object-unhash))
+    (set! object-unhash
+         (lambda (number #!optional table)
+           (let ((table
+                  (if (default-object? table)
+                      default-hash-table
+                      (begin
+                        (if (not (hash-table? table))
+                            (error:wrong-type-argument table
+                                                       "object-hash table"
+                                                       'OBJECT-UNHASH))
+                        table))))
+             (let ((result (old-unhash number table)))
+               (validate table 'unhash #T)
+               result)))))
+             
+)
diff --git a/v7/src/swat/scheme/scc-macros.scm b/v7/src/swat/scheme/scc-macros.scm
new file mode 100644 (file)
index 0000000..f6a7303
--- /dev/null
@@ -0,0 +1,22 @@
+;;;; -*-Scheme-*-
+;;; $Id: scc-macros.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
+
+(syntax-table-define system-global-syntax-table
+    'DEFINE-CONSTANT
+  (macro (name value) `(DEFINE-INTEGRABLE ,name ,value)))
+
+(syntax-table-define system-global-syntax-table
+    'DEFINE-IN-LINE
+  (macro (arg-list . body)
+    `(DEFINE-INTEGRABLE ,arg-list . ,body)))
+
+(syntax-table-define system-global-syntax-table
+    'SCC-DEFINE-SYNTAX
+  (macro (name-and-arglist . body)
+    (let ((name (car name-and-arglist))
+         (arglist (cdr name-and-arglist)))
+      `(SYNTAX-TABLE-DEFINE SYSTEM-GLOBAL-SYNTAX-TABLE
+          ',name
+        (MACRO ,arglist ,@body)))))
+
+(define-integrable *running-in-mit-scheme* #T)
diff --git a/v7/src/swat/scheme/simple.scm b/v7/src/swat/scheme/simple.scm
new file mode 100644 (file)
index 0000000..83fef9d
--- /dev/null
@@ -0,0 +1,884 @@
+;;;;; -*- Scheme -*-
+;;;;; Simple objects for UITK
+;;;; derived from simple.sc,v 1.1 1993/02/16 14:04:09 jmiller Exp $
+
+;;;; Simplest drawing object
+
+;;;This is meant to be the external interface.  We need to implement these 
+;;;in some standard way.
+
+
+(define (with-clipping! shape user-fn Clip-to-XRegion)
+  (let ((screen-area (Used-Screen-Area shape))
+       (window (Get-UITKWindow shape))
+       (gc (Shape%.graphics-context shape)))
+    (if (and window screen-area)
+       (let ((clip (rectangle->xregion screen-area)))
+         (define (intersect! xregion)
+           (if xregion
+               (XIntersectRegion! xregion clip clip)))
+         (if (not (null? Clip-to-XRegion))
+             (intersect! (car Clip-to-XRegion)))
+         (intersect! (clip-region shape))
+         (SetClipXRegion window gc clip)
+         (user-fn window gc (UITKRectangle.Offset screen-area))
+         (XDestroyRegion clip)))))
+
+(define (shape-draw shape . Clip-to-XRegion)
+  (ensure-graphics-context shape)
+  (with-clipping! shape (Shape%.x-draw shape) Clip-to-XRegion))
+
+(define (shape-erase-maybe shape . Clip-to-XRegion)
+  (ensure-graphics-context shape)
+  (let ((e (Shape%.x-erase shape)))
+    (and e
+        (begin (with-clipping! shape e Clip-to-XRegion)
+               #T))))
+
+(define (shape-copy shape)
+  (let ((new (make-shape
+             (Shape%.x-draw shape)
+             (Shape%.calculate-used-screen-area shape)
+             (shape%.point-within? shape)
+             (Shape%.rectangle-overlaps? shape)
+             (%desired-size shape)
+             (Shape%.color shape))))
+    (set-clip-region! new (clip-region shape))
+    (assign-geometry! new
+                     (drawing-surface shape)
+                     (copy-rectangle (used-screen-area shape)))
+    new))
+
+(define (shape-set-color! shape color)
+  (set-Shape%.color! shape color)
+  (set-Shape%.graphics-context! shape false))
+
+(define (shape-draw-function shape)
+  (Shape%.x-draw shape))
+    
+(define (shape-set-gc-function! shape function-number)
+  (set-Shape%.gc-function! shape function-number)
+  (set-Shape%.graphics-context! shape false))
+
+(define (shape-set-erase-function! shape fcn)
+  (set-Shape%.x-erase! shape fcn))
+
+(define (shape-point-within? Shape Offset)
+  (if (not (vector? Offset))
+      (error "SHAPE-POINT-WITHIN?: Bad offset" Offset))
+  (let ((screen-area (used-screen-area shape)))
+    (and screen-area
+        ((Shape%.point-within? shape)
+         (UITKRectangle.Offset screen-area)
+         Offset))))
+
+(define (shape-rectangle-overlaps? Shape Offset W H)
+  (if (not (vector? Offset))
+      (error "SHAPE-RECTANGLE-OVERLAPS?: Bad offset" Offset))
+  (if (not (number? W))
+      (error "SHAPE-RECTANGLE-OVERLAPS?: Bad width" W))
+  (if (not (number? H))
+      (error "SHAPE-RECTANGLE-OVERLAPS?: Bad height" H))
+  (let ((screen-area (used-screen-area shape)))
+    (and screen-area
+        ((Shape%.rectangle-overlaps? shape)
+         (UITKRectangle.Offset screen-area)
+         offset w h))))
+
+(define (generate-graphics-context! shape)
+  ;; (define-primitives (set-debug-flags! 2))
+  (let ((window (Get-UITKWindow shape)))
+    (if window
+       (begin
+         (set-Shape%.graphics-context!
+          shape
+          (make-colored-graphics-context window (Shape%.color shape)))
+         (let ((Xdisplay (UITKWindow.XDisplay
+                          (DrawingSurface.UITKWindow
+                           (Drawing-Surface shape)))))
+           (XSetFunction Xdisplay
+                         (Shape%.graphics-context shape)
+                         (Shape%.gc-function shape)))
+         'OK)
+       #F)))
+
+(define (ensure-graphics-context shape)
+  (if (not (Shape%.graphics-context shape))
+      (let ((gc (generate-graphics-context! shape)))
+       (or gc
+           (begin (debug-print 'error)
+                  (error "cannot make graphics context"))))))
+
+(define (shape-assign-screen-area! shape screen-area)
+  (cond ((vector? screen-area)
+        (let ((old (used-screen-area shape))
+              (used ((Shape%.calculate-used-screen-area shape)
+                     screen-area)))    ; Calculate bounding box, etc.
+          (set-used-screen-area! shape used)
+          (set-assigned-screen-area! shape screen-area)
+          (geometry-change! shape old used)
+          used))
+       ((not screen-area)
+        ;; Screen-Area is #F to retract the area.
+        ;; Just inform any objects interested and don't draw
+        ;; anything.
+        (let ((old (used-screen-area shape)))
+          (if old
+              (begin
+                (set-used-screen-area! shape #F)
+                (set-assigned-screen-area! shape #F)
+                (geometry-change! shape old #F)
+                #F))))
+       (error "SHAPE-ASSIGN-SCREEN-AREA!: Bad screen-area" screen-area)))
+
+;; Use default ASSIGN-DRAWING-SURFACE!
+
+(define (shape-assign-glue! me)
+  ;; infinitely stretchable
+  (let* ((size (get-desired-size me))
+        (my-width (size.width size))
+        (my-height (size.height size)))
+    (set-%hglue! me (make-fill-glue my-width 1))
+    (set-%vglue! me (make-fill-glue my-height 1))))
+  
+;; Shape Maker
+(define (shape-maker x-drawing-routine calculate-used-screen-area
+                    point-within? rectangle-overlaps? color-string)
+  (make-Shape%
+   (make-UIObjInternals 'invalid
+                       'invalid
+                       UIObj-set-context! ; Defaults
+                       shape-assign-screen-area!
+                       UIObj-assign-drawing-surface!
+                       shape-point-within?
+                       shape-rectangle-overlaps?
+                       UIObj-handle-event
+                       UIObj-get-desired-size
+                       UIObj-assigned-screen-area
+                       UIObj-used-screen-area
+                       UIObj-set-assigned-screen-area!
+                       UIObj-set-used-screen-area!
+                       shape-assign-glue!)
+   x-drawing-routine
+   calculate-used-screen-area
+   color-string
+   point-within?
+   rectangle-overlaps?
+   GXCOPY))
+
+(define (make-shape x-drawing-routine calculate-used-screen-area
+                   point-within? rectangle-overlaps?
+                   desired-size color-string)
+  (let ((me (shape-maker x-drawing-routine
+                        calculate-used-screen-area
+                        point-within?
+                        rectangle-overlaps?
+                        color-string)))
+    (set-%desired-size! me desired-size)
+    me))
+\f
+(define (make-rect width height color-string . filled?)
+  ;;defaults to filled
+  (let* ((width (round->exact width))
+        (height (round->exact height))
+        (Width-1 (- width 1))
+        (Height-1 (- height 1))
+        (Xdraw (if (or (null? filled?) (car filled?))
+                   (lambda (uitkw gc x y)
+                     (FillRectangle uitkw gc x y width height))
+                   (lambda (uitkw gc x y)
+                     ;;!!@%$^$^$$#@#@#!! X!!
+                     (DrawRectangle uitkw gc x y Width-1 Height-1)))))
+    (make-shape
+     (lambda (UITKWindow graphics-context offset) ; Draw
+       (XDraw UITKWindow graphics-context
+             (Point.X offset) (Point.Y offset)))
+     (lambda (assigned-screen-area)    ; Calculate-Used-Screen-Area
+       (make-UITKRectangle (UITKRectangle.offset assigned-screen-area)
+                          (make-size width height)))
+     (lambda (My-Offset Offset)                ; Point within?
+       (point-in-rectangle? Offset My-Offset Width Height))
+     (lambda (My-Offset Offset W H)    ; Rectangle overlaps?
+       (rectangle-overlaps-rectangle?
+       My-Offset Width Height Offset W H))
+     (make-size width height)          ; Desired-Size
+     color-string)))
+
+(define (make-scaling-rect color-string . filled?)
+  ;;defaults to filled
+  (let* ((Width #F)
+        (Height #F)
+        (Width-1 #F)
+        (Height-1 #F)
+        (Xdraw (if (or (null? filled?) (car filled?))
+                   (lambda (uitkw gc x y)
+                     (FillRectangle uitkw gc x y width height))
+                   (lambda (uitkw gc x y)
+                     ;;!!@%$^$^$$#@#@#!! X!!
+                     (DrawRectangle uitkw gc x y Width-1 Height-1)))))
+    (make-shape
+     (lambda (UITKWindow graphics-context offset) ; Draw
+       (XDraw UITKWindow graphics-context
+             (Point.X offset) (Point.Y offset)))
+     (lambda (assigned-screen-area)    ; Calculate-Used-Screen-Area
+       (set! height (UITKRectangle.Height assigned-screen-area))
+       (set! width (UITKRectangle.Width assigned-screen-area))
+       (set! height-1 (- height 1))
+       (set! width-1 (- width 1))
+       assigned-screen-area)
+     (lambda (My-Offset Offset)                ; Point within?
+       (point-in-rectangle? Offset My-Offset Width Height))
+     (lambda (My-Offset Offset W H)    ; Rectangle overlaps?
+       (rectangle-overlaps-rectangle?
+       My-Offset Width Height Offset W H))
+     (make-size width height)          ; Desired-Size
+     color-string)))
+
+(define (make-filled-rectangle width height color-string)
+  (make-rect width height color-string #T))
+
+(define (make-unfilled-rectangle width height color-string)
+  (make-rect width height color-string #F))
+
+(define (make-oval width height color-string . filled?)
+  (let* ((width (round->exact width))
+        (height (round->exact height))
+        (Width-1 (- width 1))
+        (Height-1 (- height 1))
+        (angle (* 360 64))             ; X uses degrees/64
+        (Xdraw (if (or (null? filled?) (car filled?))
+                   (lambda (uitkw gc x y)
+                     (FillArc uitkw gc x y width height 0 angle))
+                   (lambda (uitkw gc x y)
+                     (DrawArc uitkw gc x y width-1 height-1 0 angle))))
+        (a (/ width 2.0))
+        (b (/ height 2.0))
+        (center (make-point a b)))
+    (make-shape
+     (lambda (UITKWindow graphics-context offset) ; Draw
+       (Xdraw UITKWindow graphics-context
+             (Point.X offset) (Point.Y offset)))
+     (lambda (assigned-screen-area)    ; Calculate-Used-Screen-Area
+       (make-UITKRectangle (UITKRectangle.Offset assigned-screen-area)
+                          (make-size width height)))
+     (lambda (My-Offset Offset)                ; Point within?
+       (and (point-in-rectangle? Offset My-Offset width height)
+           (let* ((dv (sub-vectors (add-vectors my-offset center) offset))
+                  (dx/a (/ (point.x dv) a))
+                  (dy/b (/ (point.y dv) b)))
+             (< (+ (* dx/a dx/a) (* dy/b dy/b)) 1.0))))
+     (lambda (My-Offset Offset W H)    ; Rectangle overlaps?
+       (rectangle-overlaps-rectangle?
+       My-Offset diameter diameter Offset W H))
+     (make-size width height)          ; Desired-Size
+     color-string)))
+
+(define (make-scaling-oval color-string . filled?)
+  (let ((width #F)
+       (height #F)
+       (width-1 #F)
+       (height-1 #F)
+       (a #F)
+       (b #F)
+       (center #F))
+    (let* ((angle (* 360 64))          ; X uses degrees/64
+          (Xdraw (if (or (null? filled?) (car filled?))
+                     (lambda (uitkw gc x y)
+                       (FillArc uitkw gc x y width height 0 angle))
+                     (lambda (uitkw gc x y)
+                       (DrawArc uitkw gc x y width-1 height-1 0 angle)))))
+      (make-shape
+       (lambda (UITKWindow graphics-context offset) ; Draw
+        (Xdraw UITKWindow graphics-context
+               (Point.X offset) (Point.Y offset)))
+       (lambda (assigned-screen-area)  ; Calculate-Used-Screen-Area
+        (set! width (UITKRectangle.Width assigned-screen-area))
+        (set! height (UITKRectangle.Height assigned-screen-area))
+        (set! width-1 (- width 1))
+        (set! height-1 (- height 1))
+        (set! a (/ width 2.0))
+        (set! b (/ height 2.0))
+        (set! center (make-point a b))
+        assigned-screen-area)
+       (lambda (My-Offset Offset)      ; Point within?
+        (and (point-in-rectangle? Offset My-Offset width height)
+             (let* ((dv (sub-vectors (add-vectors my-offset center) offset))
+                    (dx/a (/ (point.x dv) a))
+                    (dy/b (/ (point.y dv) b)))
+               (< (+ (* dx/a dx/a) (* dy/b dy/b)) 1.0))))
+       (lambda (My-Offset Offset W H)  ; Rectangle overlaps?
+        (rectangle-overlaps-rectangle?
+         My-Offset width height Offset W H))
+       (make-size width height)                ; Desired-Size
+       color-string))))
+
+(define (make-filled-oval width height color-string)
+  (make-oval width height color-string #T))
+
+(define (make-unfilled-oval width height color-string)
+  (make-oval width height color-string #F))
+
+(define (make-filled-circle radius color-string)
+  (make-filled-oval (* radius 2) (* radius 2) color-string))
+
+(define (make-unfilled-circle radius color-string)
+  (make-unfilled-oval (* radius 2) (* radius 2) color-string))
+
+;;;not right?  do lines need to be oriented (from to)
+
+(define (make-line width height color-string . filled?)
+  filled?                              ;ignore
+  (let ((width (round->exact width))
+       (height (round->exact height)))
+    (make-shape
+     (lambda (UITKWindow graphics-context offset) ; Draw
+       (DrawLine UITKWindow graphics-context
+             (Point.X offset) (Point.Y offset)
+             (+ width (Point.X offset)) (+ height (Point.Y offset))))
+     (lambda (assigned-screen-area)    ; Calculate-Used-Screen-Area
+       (make-UITKRectangle (UITKRectangle.offset assigned-screen-area)
+                          (make-size width height)))
+     (lambda (My-Offset Offset)                ; Point within?!!FIX
+       (point-in-rectangle? Offset My-Offset Width Height))
+     (lambda (My-Offset Offset W H)    ; Rectangle overlaps?!!FIX
+       (rectangle-overlaps-rectangle?
+       My-Offset Width Height Offset W H))
+     (make-size width height)          ; Desired-Size
+     color-string)))
+
+
+;;;*******Still not right for rubber-banding (I think)
+
+(define (make-scaling-line color-string . filled?)
+  filled?                              ;ignore
+  (let ((width #F)
+       (height #F))
+    (make-shape
+     (lambda (UITKWindow graphics-context offset) ; Draw
+       (DrawLine UITKWindow graphics-context
+                (Point.X offset) (Point.Y offset)
+                (+ width (Point.X offset)) (+ height (Point.Y offset))))
+     (lambda (assigned-screen-area)    ; Calculate-Used-Screen-Area
+       (set! height (UITKRectangle.Height assigned-screen-area))
+       (set! width (UITKRectangle.Width assigned-screen-area))
+       assigned-screen-area)
+    (lambda (My-Offset Offset)         ; Point within?!!FIX
+      (point-in-rectangle? Offset My-Offset Width Height))
+    (lambda (My-Offset Offset W H)     ; Rectangle overlaps?!!FIX
+      (rectangle-overlaps-rectangle?
+       My-Offset Width Height Offset W H))
+    (make-size width height)           ; Desired-Size
+    color-string)))
+
+
+
+#|
+;;; points is a list of points.  The offset of a path is the upper left-most
+;;; corner of the bounding box of the path.  Make-path comes born with
+;;; a used screen area
+(define (make-path points color)
+  (if (null? points)
+      (error "no points in path -- MAKE-PATH"))
+  (let* ((xcors (map point.x points))
+        (ycors (map point.y points))
+        (xmin (apply min xcors))
+        (xmax (apply max xcors))
+        (ymin (apply min ycors))
+        (ymax (apply max ycors))
+        (width (- xmax xmin))
+        (height (- ymax ymin))
+        ;;adjust points so relative to upper-left
+        (xpoints (map (lambda (x) (- x xmin)) xcors))
+        (ypoints (map (lambda (y) (- y ymin)) ycors))
+        (shape
+         (make-shape
+          (lambda (UITKWindow graphics-context offset)
+            (let* ((ox (point.x offset))
+                   (oy (point.y offset))
+                   (xs (map (lambda (x) (+ x ox)) xpoints))
+                   (ys (map (lambda (y) (+ y oy)) ypoints)))
+            (let loop ((fx (car xs))
+                       (fy (car ys))
+                       (restx (cdr xs))
+                       (resty (cdr ys)))
+              (if (null? restx)
+                  'done
+                  (begin (DrawLine UITKWindow graphics-context
+                                   fx fy (car restx) (car resty))
+                         (loop (car restx) (car resty)
+                               (cdr restx) (cdr resty)))))))
+          (lambda (assigned-screen-area)
+            ??????)
+          (lambda (point) ())
+          (lambda (rect) ())
+          desired-size
+          color)))
+    set up the used screen-area???
+    shape))
+
+FOO do just a line first
+    
+
+or maybe just do draw path and draw line given some shape for which to
+use the uitkwindow.
+
+
+|#
+
+
+(define (self-paint! shape)
+  (handle-exposure shape
+   (lambda (exposed-rectangle)
+     (shape-draw shape (Rectangle->XRegion exposed-rectangle))))
+  (on-geometry-change! shape 'REASON
+   (lambda (old-screen-area new-screen-area)
+     old-screen-area new-screen-area           ; Not used
+     (if new-screen-area (shape-draw shape))))
+  'done)
+
+(define (make-self-painting-rectangle width height color)
+  (let ((me (make-rect width height color)))
+    (self-paint! me)
+    me))
+
+(define (make-self-painting-unfilled-rectangle width height color)
+  (let ((me (make-unfilled-rectangle width height color)))
+    (self-paint! me)
+    me))
+
+(define (make-self-painting-circle radius color)
+  (let ((me (make-circle radius color)))
+    (self-paint! me)
+    me))
+
+
+;;; This is a surface that generates rectangles or ovals when you click on it.
+;;; Shapes grow with rubber banding.
+;;; After a shape is generated, it can be moved around.
+;;; You can choose either solid or outline mode for moving the shapes.
+;;;This is a little ugly, because I want to make sure that
+;;;make-rect is never called with negative width or height.
+
+(define (make-shape-surface width height background-color new-shape-color)
+  (let ((rubber-from #F)
+       (move-offset #F)                ;offset of moving shape relative to mouse
+       (shadow-shape #F)
+       (fill-shadow-shapes? #F)
+       (shape-maker make-rect)
+       (rubber-shape-maker make-scaling-rect)
+       (shapes-and-areas '())
+       (shape->maker-map '())
+       (outer-rectangle (make-rect width height background-color)))
+
+    (define (shape->shape-and-area shape)
+      (cons shape (used-screen-area shape)))
+    (define (shape-and-area->shape s-and-a) (car s-and-a))
+    (define (shape-and-area->area s-and-a) (cdr s-and-a))
+    (define (set-shape-and-area-area! s-and-a area)
+      (let ((shape (shape-and-area->shape s-and-a)))
+       (assign-screen-area! shape area)
+       (set-cdr! s-and-a (used-screen-area shape))))
+
+    (define (process-click-on-shape shape-and-area e while-grabbed)
+      (let ((shape (shape-and-area->shape shape-and-area))
+           (area (shape-and-area->area shape-and-area)))
+       (set! move-offset
+             (sub-vectors (Event.Offset e)
+                          (UITKRectangle.offset area)))
+      ;;;put shape at top
+       (set! shapes-and-areas
+             (append (delq! shape-and-area shapes-and-areas)
+                     (list shape-and-area)))
+       (shape-draw shape)
+       (set! shadow-shape (shape->moving-shape shape))
+       (shape-erase shape)             ;because shadow draws in XOR
+       (shape-draw shadow-shape)
+       (while-grabbed
+        (lambda (point)                ; Motion procedure
+          (if (point-within? outer-rectangle point)
+              (begin
+                (shape-erase shadow-shape)
+                (assign-location! shadow-shape
+                                  (sub-vectors point move-offset))
+                (shape-draw shadow-shape))))
+        (lambda ()                     ;finalization procedure
+          (set-shape-and-area-area! shape-and-area
+                                    (used-screen-area shadow-shape))
+          (shape-erase shadow-shape)
+          (shape-draw shape)))))
+
+    (define (process-click-on-background e while-grabbed)
+      (set! rubber-from (Event.Offset e))
+      (set! shadow-shape (make-rubber-shape))
+      (shape-draw shadow-shape)
+      (while-grabbed
+       (lambda (point)                 ; Motion procedure
+        (if (point-within? outer-rectangle point)
+            (grow-shadow-shape point)))
+       instantiate-shadow-shape))      ;finalization procedure
+
+    (define (instantiate-shadow-shape)
+      (let ((new-shape (screen-area->shape
+                       shape-maker
+                       (used-screen-area shadow-shape)
+                       new-shape-color
+                       #T)))           ;always fill
+       (shape-erase shadow-shape)
+       (shape-draw new-shape)
+       (set! shapes-and-areas
+             (append shapes-and-areas
+                     (list (shape->shape-and-area new-shape))))
+       ;;remember proc that shape was made with
+       (set! shape->maker-map
+             (cons (cons new-shape shape-maker)
+                   shape->maker-map))))
+
+    (define (shape->moving-shape shape)
+      (let ((entry (assq shape shape->maker-map)))
+       (if (null? entry)
+           (error "shape not in shape->maker-map" shape))
+       (let ((moving-shape
+              (screen-area->shape (cdr entry)
+                                  (used-screen-area shape)
+                                  background-color
+                                  fill-shadow-shapes?)))
+         (set-xor-draw! moving-shape)
+         moving-shape)))
+
+    (define (screen-area->shape maker screen-area color fill?)
+      (let ((new-shape (maker (UITKRectangle.Width screen-area)
+                             (UITKRectangle.Height screen-area)
+                             color
+                             fill?)))
+       (set-clip-region! new-shape
+                         (rectangle->XRegion 
+                          (used-screen-area outer-rectangle)))
+       (assign-geometry! new-shape
+                         (drawing-surface outer-rectangle)
+                         (copy-rectangle screen-area))
+       new-shape))
+
+    (define (make-rubber-shape)
+      (let ((new-shape
+            (rubber-shape-maker new-shape-color fill-shadow-shapes?)))
+       (set-clip-region! new-shape
+                         (rectangle->XRegion 
+                          (used-screen-area outer-rectangle)))
+       (set-shape-geometry! new-shape rubber-from rubber-from)
+       (set-xor-draw! new-shape)
+       new-shape))
+
+    (define (set-shape-geometry! shape from to)
+      (let ((x1 (point.x from))
+           (y1 (point.y from))
+           (x2 (point.x to))
+           (y2 (point.y to)))
+       (let* ((dx (- x2 x1))
+              (dy (- y2 y1))
+              (x-left (if (>= dx 0) x1 x2))
+              (y-top (if (>= dy 0) y1 y2)))
+         (assign-geometry! shape
+                           (drawing-surface outer-rectangle)
+                           (make-UITKRectangle (make-point x-left y-top)
+                                               (make-size (abs dx) (abs dy))))
+         'DONE)))
+
+    (define (grow-shadow-shape to)
+      (shape-erase shadow-shape)
+      (set-shape-geometry! shadow-shape rubber-from to)
+      (shape-draw shadow-shape))
+
+    (define (find-shape-under-event event)
+      (let loop ((more-shapes (reverse shapes-and-areas)))
+       (cond ((null? more-shapes) #F)
+             ((event-within?
+               (shape-and-area->shape (car more-shapes)) event)
+              (car more-shapes))
+             (else (loop (cdr more-shapes))))))
+
+    (define (shape-erase shape)
+      (or (shape-erase-maybe shape)
+         (redraw-surface-except
+          shape
+          (rectangle->Xregion (used-screen-area shape)))))
+
+    (define (set-xor-draw! shape)
+      (shape-set-gc-function! shape GXXOR)
+      (shape-set-erase-function! shape (shape-draw-function shape))
+      (shape-set-color! shape background-color))
+
+    (define (redraw-surface-except shape clip-region)
+         (shape-draw outer-rectangle clip-region)
+         (for-each
+          (lambda (shape) (shape-draw shape clip-region))
+          (map shape-and-area->shape
+               (list-transform-negative shapes-and-areas
+                 (lambda (shape-and-area)
+                   (eq? shape (shape-and-area->shape shape-and-area)))))))
+
+    (define (redraw-surface clip-region)
+      (shape-draw outer-rectangle clip-region)
+      (for-each (lambda (shape) (shape-draw shape clip-region))
+               (map shape-and-area->shape shapes-and-areas)))
+
+    (handle-exposure outer-rectangle
+                    (lambda (exposed-rectangle)
+                      (redraw-surface (Rectangle->XRegion exposed-rectangle))))
+
+    (handle-button-grab
+     outer-rectangle ANYBUTTON
+     (lambda (e while-grabbed)         ; When the button goes down
+       (let ((shape (find-shape-under-event e)))
+        (cond (shape (process-click-on-shape shape e while-grabbed))
+              ((event-within? outer-rectangle e)
+               (process-click-on-background e while-grabbed))       
+              (else
+               (while-grabbed
+                (lambda (point) point 'OK) ; Nothing to do
+                (lambda () 'OK)))))))
+
+    (on-geometry-change!
+     outer-rectangle 'ignore
+     (lambda (old-screen-area new-screen-area)
+       (if (not (screen-area= old-screen-area new-screen-area))
+          (if (UITKRectangle? new-screen-area)
+              (let ((Clip (rectangle->XRegion new-screen-area)))
+                (for-each
+                 (lambda (shape-and-area)
+                   (let ((shape (shape-and-area->shape shape-and-area))
+                         (area  (shape-and-area->area shape-and-area)))
+                     (set-clip-region! shape clip)
+                     (set-shape-and-area-area!
+                      shape-and-area
+                      (make-UITKRectangle
+                       (UITKRectangle.offset area)
+                       (UITKRectangle.Size new-screen-area)))))
+                 shapes-and-areas)
+                (redraw-surface clip))
+              (for-each (lambda (shape-and-area)
+                          (let ((shape
+                                 (shape-and-area->shape shape-and-area)))
+                            (set-clip-region! shape #F)
+                            (assign-screen-area! shape #F)))
+                        shapes-and-areas)))))
+    (lambda (message)
+      (case message
+       ((the-surface) outer-rectangle)
+       ((set-color!)
+        (lambda (string)
+          (set! new-shape-color string)))
+       ((rectangles)
+        (set! rubber-shape-maker make-scaling-rect)
+        (set! shape-maker make-rect))
+       ((ovals)
+        (set! rubber-shape-maker make-scaling-oval)
+        (set! shape-maker make-oval))
+       ((lines)
+        (set! rubber-shape-maker make-scaling-line)
+        (set! shape-maker make-line))
+       ((outlined) (set! fill-shadow-shapes? #F))
+       ((filled) (set! fill-shadow-shapes? #T))
+       ((clear)
+        (begin (set! shapes-and-areas '())
+               (set! shape->maker-map '())
+               (redraw-surface
+                (rectangle->XRegion
+                 (used-screen-area outer-rectangle)))))
+       (else (error "unknown message"))))))
+
+
+
+
+;;;;******This isn't working.  I don't understand how to manage the 
+;;;;event queue
+
+(define debug-surface)
+
+(define (make-drop-rubber-rectangle-surface app width height color shape-color)
+  (let ((rubber-from #F)               ; X,Y of click relative to dragging shape
+       (rubber-to #F)
+       (active-shape #F)
+       (shadow-shape #F)
+       (fill-rubber-shapes? #F)
+       (shape-maker make-rect)
+       (shadow-shape-maker make-scaling-rect)
+       (shapes '())
+       (outer-rectangle (make-rect width height color)))
+    (set! debug-surface (lambda () 'foo))
+    (define (pick-random-shape)
+      (let ((l (length shapes)))
+       (list-ref shapes (random l))))
+    (define (drop)
+      (if (not (null? shapes))
+         (let* ((s (pick-random-shape)))
+             (redraw-surface-except s (rectangle->Xregion (used-screen-area s)))
+             (let* ((p (UITKRectangle.offset (used-screen-area s)))
+                  (x (point.x p))
+                  (y (point.y p)))
+               (if (> y (+ (point.y (UITKRectangle.offset
+                                     (used-screen-area outer-rectangle)))
+                         height))
+                   (begin (set! shapes (delq! s shapes))
+                        'OK)
+                   (begin (assign-location! s (make-point x (+ y 5)))
+                          (shape-draw s))))
+             (when-idle! app drop))))
+    (define (find-shape event)
+      (let loop ((more-shapes (reverse shapes)))
+       (cond ((null? more-shapes) #F)
+             ((event-within? (car more-shapes) event)
+              (let ((this (car more-shapes)))
+                (set! shapes (append (delq! this shapes) (list this)))
+                this))
+             (else (loop (cdr more-shapes))))))
+    (define (process-click-on-active-shape e while-grabbed)
+      (let ((Click (Event.Offset e))
+           (screen-area (used-screen-area active-shape)))
+       (set! rubber-from (sub-vectors Click
+                                      (UITKRectangle.offset screen-area)))
+       ;;bring active shape to top
+       (shape-draw active-shape)
+       (while-grabbed
+        (lambda (point)                ; Motion procedure ...
+          (if (point-within? outer-rectangle point) ; maybe
+              (move-active-shape (sub-vectors point rubber-from))))
+        (lambda () (set! active-shape #F)) ;finalize
+        )))
+    (define (process-click-on-background e while-grabbed)
+      (let ((Click (Event.Offset e)))
+       (initialize-rubber-rectangle Click)
+       (while-grabbed
+        (lambda (point)                ; Motion procedure ...
+          (if (point-within? outer-rectangle point) ; maybe
+              (grow-rubber-rectangle point)))
+        instantiate-rubber-rectangle))) ;finalize
+
+    (define (instantiate-rubber-rectangle)
+      (let* ((used (used-screen-area shadow-shape))
+            (new-shape (shape-maker (UITKRectangle.Width used)
+                                    (UITKRectangle.Height used)
+                                    new-shape-color)))
+       (shape-erase shadow-shape)
+       (set! shadow-shape #F)
+       (set-clip-region! new-shape
+                         (rectangle->XRegion 
+                          (used-screen-area outer-rectangle)))
+       (set-shape-geometry! new-shape)
+       (shape-draw new-shape)
+       (set! shapes (append shapes (list new-shape)))
+       (when-idle! app drop)))
+
+    (define (initialize-rubber-rectangle Click)
+      (set! rubber-from Click)
+      (make-rubber-rectangle Click))
+       
+    (define (make-rubber-rectangle to)
+      (set! rubber-to to)
+      (set! shadow-shape (shadow-shape-maker "white" fill-rubber-shapes?))
+      (set-clip-region! shadow-shape
+                       (rectangle->XRegion 
+                        (used-screen-area outer-rectangle)))
+      (set-shape-geometry! shadow-shape)
+      (shape-set-gc-function! shadow-shape GXXOR)
+      (shape-set-erase-function! shadow-shape
+                                (shape-draw-function shadow-shape))
+      (shape-draw shadow-shape))
+
+    (define (set-shape-geometry! shape)
+      (let ((x1 (point.x rubber-from))
+           (y1 (point.y rubber-from))
+           (x2 (point.x rubber-to))
+           (y2 (point.y rubber-to)))
+       (let* ((dx (- x2 x1))
+              (dy (- y2 y1))
+              (x-left (if (>= dx 0) x1 x2))
+              (y-top (if (>= dy 0) y1 y2)))
+         (assign-geometry! shape
+                           (drawing-surface outer-rectangle)
+                           (make-UITKRectangle (make-point x-left y-top)
+                                               (make-size (abs dx) (abs dy))))
+         'DONE)))
+
+    (define (grow-rubber-rectangle point)
+      (set! rubber-to point)
+      (shape-erase shadow-shape)       ; Can't fail!
+      (set-shape-geometry! shadow-shape)
+      (shape-draw shadow-shape))
+
+    (define (redraw-surface-except shape clip-region)
+      (shape-draw outer-rectangle clip-region)
+      (for-each (lambda (shape) (shape-draw shape clip-region))
+               (delq shape shapes)))
+    (define (redraw-surface clip-region)
+      (shape-draw outer-rectangle clip-region)
+      (for-each (lambda (shape) (shape-draw shape clip-region))
+               shapes))
+    (define (move-active-shape to-point)
+      (let ((screen-area (used-screen-area active-shape)))
+       (redraw-surface-except active-shape
+                              (rectangle->XRegion screen-area))
+       (assign-location! active-shape to-point)
+       (shape-draw active-shape)))
+
+    (handle-exposure outer-rectangle
+                    (lambda (exposed-rectangle)
+                      (redraw-surface (Rectangle->XRegion exposed-rectangle))))
+
+    (handle-button-grab
+     outer-rectangle ANYBUTTON
+     (lambda (e while-grabbed)         ; When the button goes down
+       (set! active-shape (find-shape e))
+       (cond (active-shape (process-click-on-active-shape e while-grabbed))
+            ((event-within? outer-rectangle e)
+             (process-click-on-background e while-grabbed))         
+            (else
+             (while-grabbed
+              (lambda (point) point 'OK) ; Nothing to do
+              (lambda () (set! active-shape #F)))))))
+
+    (on-geometry-change!
+     outer-rectangle 'ignore
+     (lambda (old-screen-area new-screen-area)
+       old-screen-area
+       (let ((ds (drawing-surface outer-rectangle)))
+        (if (UITKRectangle? new-screen-area)
+            (let ((Clip (rectangle->XRegion new-screen-area)))
+              (for-each
+               (lambda (shape)
+                 (set-clip-region! shape clip)
+                 (assign-geometry! shape ds new-screen-area))
+               shapes)
+              (redraw-surface clip))
+            (for-each (lambda (shape)
+                        (set-clip-region! shape #F)
+                        (assign-screen-area! shape #F))
+                      shapes)))))
+    (when-idle! app drop)
+    (lambda (message)
+      (case message
+       ((the-surface) outer-rectangle)
+       ((set-color!)
+        (lambda (new-shape-color-name)
+          (let* ((dsp (UITKWindow.XDisplay
+                       (DrawingSurface.UITKWindow
+                        (Drawing-Surface outer-rectangle))))
+                 (color ((string->color dsp) new-shape-color-name)))
+            (if color
+                (begin
+                  (set! new-shape-color new-color-name)
+                  'OK)
+                #F))))
+       ((rectangles)
+        (set! shadow-shape-maker make-scaling-rect)
+        (set! shape-maker make-rect))
+       ((ovals)
+        (set! shadow-shape-maker make-scaling-oval)
+        (set! shape-maker make-oval))
+       ((outlined) (set! fill-rubber-shapes? #F))
+       ((filled) (set! fill-rubber-shapes? #T))
+       ((clear)
+        (begin (set! shapes '())
+               (redraw-surface
+                (rectangle->XRegion
+                 (used-screen-area outer-rectangle)))))
+       (else (error "unknown message"))))))
diff --git a/v7/src/swat/scheme/structures.scm b/v7/src/swat/scheme/structures.scm
new file mode 100644 (file)
index 0000000..bfb8618
--- /dev/null
@@ -0,0 +1,128 @@
+;;;;; -*- Scheme -*-
+;;;;;
+;;;;; derived from uitk.scm at MIT on April 24, 1993
+;;;;; $Id: structures.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
+
+;;;; Commonly used structure definitions.  They are here so that the
+;;;; macro versions can be loaded to improve performance.
+
+(scc-define-structure UITKWindow
+  xdisplay                             ; X display connection
+  xwindow)                             ; X window ID
+
+(scc-define-structure ToolKitWindow    ; For TK or whatever
+  Application                          ; For GC protection of TK Widgets
+  Top-Level-Geometry-Callback          ; From TK to us (for GC, too)
+  TK-Window)                           ; *Un*wrapped!
+
+(scc-define-structure DrawingSurface
+  ToolKitWindow
+  UITKWindow
+  (Weak-List-of-Widgets '()))          ; Ones that use this surface
+
+(scc-define-structure Point X Y)
+
+(scc-define-structure UITKRectangle Offset Size)
+
+(scc-define-structure Size Width Height)
+
+(scc-define-structure context
+  activebackground activeforeground anchor background
+  border borderwidth
+  ;; cursor
+  ;; font
+  foreground relief)
+
+(scc-define-structure alert reason function)
+
+(scc-define-structure queue
+  (%head #F)
+  (%tail #F))
+
+(scc-define-structure locked-list
+  (%mutex (make-thread-mutex))
+  (%data '()))
+
+(scc-define-structure surface-sensitivity
+  Weak-Surface
+  Mask
+  Sensitivities)
+
+(scc-define-structure sensitivity
+  %weak-<interactor>
+  Masks)
+
+(scc-define-structure sensitive-surface
+  DrawingSurface
+  Handlers) 
+
+(scc-define-structure TK-variable
+  application                
+  tk-name
+  callback     ;on writes
+  )
+
+(scc-define-structure scxl-wrapper
+  type
+  wrapped-object
+  strong-dependents
+  other-stuff)
+
+
+(scc-define-structure Event
+  Point-or-rectangle?
+  Type
+  OS-Event
+  Window
+  Offset
+  Width
+  Height)
+
+(scc-define-structure Glue
+  minsize
+  class
+  value)
+
+;;; Applications, interactors, boxes, shapes, tkwidgets
+;;; all share these internals.  These slots will be the first thing in
+;;; the structure.
+
+(scc-define-structure UIObjInternals
+  Add-Child!-procedure
+  Remove-Child!-procedure
+  Set-Context!-procedure
+  Assign-Screen-Area!-procedure
+  Assign-Drawing-Surface!-procedure
+  Point-Within?-procedure
+  Rectangle-Overlaps?-procedure
+  Handle-Event-procedure
+  Get-Desired-Size-procedure
+  Assigned-Screen-Area-procedure
+  Used-Screen-Area-procedure
+  Set-Assigned-Screen-Area!-procedure
+  Set-Used-Screen-Area!-procedure
+  Assign-Glue!-procedure
+  (%geometry-alerts '())
+  (%event-alerts '())
+  (%context-alerts '())
+  (%death-alerts '())
+  (Assigned-Screen-Area #F)
+  (Used-Screen-Area #F)
+  (clip-region #F)
+  (drawing-surface 'UNASSIGNED)
+  (%desired-size #F)
+  (%vglue #F)          ; for boxes, shapes
+  (%hglue #F)          ; and tkwidgets only
+  ;; Hal says:
+  ;; "Success has many parents, but a UIObj has only one"
+  (already-have-a-parent? #F)
+  ;; Second '() is a special list for canvas and text items, that
+  ;; might need to be un-gc-protected all at once.
+  (crud-that-I-dont-want-to-gc-away (cons '() '()))
+  )
+
+;;;Generic procedures on objects that have UIObj internals
+
+(define-integrable uiobjinternals-index 1)
+
+
diff --git a/v7/src/swat/scheme/structures2.scm b/v7/src/swat/scheme/structures2.scm
new file mode 100644 (file)
index 0000000..d02d5cf
--- /dev/null
@@ -0,0 +1,118 @@
+;;; -*- Scheme -*-
+
+;;; More structures.  With all this macro expansion, the compiler runs
+;;; out of space if they are all in one file.
+
+(scc-define-structure Application%
+  UIObjInternals
+  %child-windows       ; Locked list of all children
+  %%%code%%%           ; Asynchronous code to be
+                        ; executed when data arrives
+                        ; from the display connection
+  application-name
+  Xdisplay             ; A SCXL-wrapped display
+  TKMainWindow
+  context)
+
+(scc-define-structure Interactor%
+  UIObjInternals
+  handlers
+  ;; Map from children of the interactor -- things it manages --
+  ;; to Sensitive-Surface data structures.  These are implemented
+  ;; at the end of the file and maintain the correspondence
+  ;; between drawing surfaces, event generation masks, and
+  ;; <interactor> objects.
+  (sensitive-surface-map '()))
+
+(scc-define-structure Shape%
+  UIObjInternals
+  x-draw
+  calculate-used-screen-area
+  color
+  point-within?
+  rectangle-overlaps?
+  (x-erase #F)
+  gc-function
+  (graphics-context #F))
+
+(scc-define-structure Box%
+  UIObjInternals
+  sizer
+  arranger
+  get-hglue
+  get-vglue
+  (kids '()))
+
+(scc-define-structure ArrayBox%
+  UIObjInternals
+  kids-lists
+  (kids '()))
+
+(scc-define-structure TKWidget%
+  UIObjInternals
+  Ask-Widget-procedure
+  Add-Event-Handler!-procedure
+  Set-Callback!-procedure
+  (deferred-ask-widget-commands '())
+  (how-to-make-me 'later)
+  ;; Parent-Window -- stored as assigned screen area
+  (Set-Glue!-procedure 'later)
+  (%c-callback 'later)
+  (%binding-callbacks '())
+  (%scheme-geometry-manager 'later)
+  (%scheme-callback-hash 'later)
+  (%callback #F)
+  (%callback-command #F)
+  (%children '())
+  (handle #F)
+  (do-screen-area? 'later)
+  ;; The following is weird.  TK does finalization of some TK objects
+  ;; (sub-menus bit us ...) and we can *not* destroy these on our own.
+  ;; We simply reflect the ownership (via add-child!) to prevent them
+  ;; from being GCed away if the TK parent exists.  And the child
+  ;; better hold on to the parent, too.
+  (do-not-gc-protect #F))
+
+(scc-define-structure CanvasItem
+  Ask-Widget-procedure
+  Add-Event-Handler!-procedure
+  Set-Callback!-procedure
+  Name
+  Canvas
+  %binding-callbacks)
+
+(scc-define-structure CanvasItemGroup
+  Ask-Widget-procedure
+  Add-Event-Handler!-procedure
+  Set-Callback!-procedure
+  Tag
+  Canvas
+  %binding-callbacks)
+
+(scc-define-structure MenuRecord Menu Items)
+
+(scc-define-structure MenuItem
+  ask-widget-procedure
+  Add-event-handler!-procedure
+  Set-callback!-procedure
+  MenuRecord
+  %callback
+  index)
+
+(scc-define-structure TextTag
+  ask-widget-procedure
+  Add-event-handler!-procedure
+  Set-callback!-procedure
+  Name
+  Text
+  Callbacks)
+
+;;; procedures that are generic over CanvasItem, CanvasTag, MenuItem,
+;;; TextTag, and TKWidget
+
+(define-integrable ask-widget-procedure-index 1)
+(define-integrable add-event-handler!-procedure-index 2)
+(define-integrable set-callback!-procedure-index 3)
+
+
+
diff --git a/v7/src/swat/scheme/swat.cbf b/v7/src/swat/scheme/swat.cbf
new file mode 100644 (file)
index 0000000..63c4631
--- /dev/null
@@ -0,0 +1,45 @@
+;;; -*-Scheme-*-
+
+;;(define (cf-conditionally filename)
+;;  (sf-conditionally filename)
+;;  (if (not (file-processed? filename "bin" "com"))
+;;      (compile-bin-file filename)))
+;;
+;;
+;;(fluid-let ((sf/default-syntax-table syntax-table/system-internal)
+;;         (sf/default-declarations (cons '(usual-integrations)
+;;                                        sf/default-declarations)))
+;;  (cf-conditionally "scc-macros")
+;;  (load "scc-macros")
+;;  (cf-conditionally "uitk-macros")
+;;  (load "uitk-macros")
+;;  (cf-conditionally "control-floating-errors")
+;;  (cf-conditionally "structures")
+;;  (cf-conditionally "structures2")
+;;  (cf-conditionally "generics")
+;;  (cf-conditionally "widget-mit")
+;;  (cf-conditionally "tk-mit")
+;;  (cf-conditionally "uitk")
+;;  (cf-conditionally "xlibCONSTANTS")
+;;  (cf-conditionally "mit-xlib")
+;;  (cf-conditionally "mit-xhooks")
+;;  (cf-conditionally "baseobj")
+;;  (cf-conditionally "widget")
+;;  (cf-conditionally "geometry")
+;;  (cf-conditionally "simple")
+;;  (cf-conditionally "canvas")
+;;  (cf-conditionally "menu")
+;;  (cf-conditionally "text")
+;;
+;;  )
+;;
+
+
+
+(compile-directory ".")
+
+;; For `make install':
+
+(with-output-to-file "compiled"
+  (lambda ()
+    (write "Scheme compiled")))
\ No newline at end of file
diff --git a/v7/src/swat/scheme/swat.sf b/v7/src/swat/scheme/swat.sf
new file mode 100644 (file)
index 0000000..97c8edb
--- /dev/null
@@ -0,0 +1,38 @@
+
+(fluid-let ((sf/default-syntax-table syntax-table/system-internal)
+           (sf/default-declarations
+            `((usual-integrations) ,@sf/default-declarations)))
+
+  (sf-conditionally "scc-macros")
+  (load "scc-macros")
+  (sf-conditionally "uitk-macros")
+  (load "uitk-macros")
+  (sf-conditionally "structures")
+  (sf-conditionally "structures2")
+  (sf-conditionally "xlibCONSTANTS")
+
+  (fluid-let ((sf/default-declarations
+              `((integrate-external "structures")
+                (integrate-external "structures2")
+                (integrate-external "xlibCONSTANTS")
+                ,@sf/default-declarations)))
+    (sf-conditionally "control-floating-errors")
+    (sf-conditionally "generics")
+    (sf-conditionally "widget-mit")
+    (sf-conditionally "tk-mit")
+    (sf-conditionally "uitk")
+    (sf-conditionally "mit-xlib")
+    (sf-conditionally "mit-xhooks")
+    (sf-conditionally "baseobj")
+    (sf-conditionally "widget")
+    (sf-conditionally "geometry")
+    (sf-conditionally "simple")
+    (sf-conditionally "canvas")
+    (sf-conditionally "menu")
+    (sf-conditionally "text")
+    ))
+
+;;(load-option 'CREF)
+;;(cref/generate-constructors "swat")
+;;(sf "swat.con")
+;;(sf "swat.ldr")
\ No newline at end of file
diff --git a/v7/src/swat/scheme/text.scm b/v7/src/swat/scheme/text.scm
new file mode 100644 (file)
index 0000000..11ad25a
--- /dev/null
@@ -0,0 +1,110 @@
+;;; -*- Scheme -*-
+
+;;; Scrollable text widgets (only vertical scrollbar makes sense,
+;;; since text can't be extended horizontally without changing the
+;;; size of the top level window).
+
+#|
+(define (make-scrollable-text . options)
+  (let ((text (apply make-text options))
+       (vscroll (make-scrollbar '(-orient vert))))
+    (let ((sb-command
+          (lambda ()
+            (ask-widget
+             vscroll
+             `(configure -command
+                         ,(string-append (tk-widget->pathname text)
+                                         " yview")))))
+         (c-command
+          (lambda ()
+            (ask-widget
+             text
+             `(configure -yscrollcommand
+                         ,(string-append (tk-widget->pathname vscroll) " set"))))))
+      (defer text sb-command)
+      (defer vscroll c-command)
+      (make-hbox text vscroll))))
+|#
+
+(define (make-scrollable-text . options)
+  (let ((text (apply make-text options))
+       (vscroll (make-scrollbar '(-orient vert))))
+    (let ((c-command
+          (lambda ()
+            (ask-widget
+             text
+             `(configure -yscrollcommand
+                         ,(string-append (tk-widget->pathname vscroll) " set"))))))
+      (defer vscroll c-command)
+      (set-callback!
+       vscroll
+       (lambda (n)
+        (let ((n (string->number n)))
+          (ask-widget text `(yview -pickplace ,n)))))
+      (make-hbox text vscroll))))
+
+(define (scrollable-text-text scrollable-text)
+  (car (box-children scrollable text)))
+
+(define (scrollable-text-vscroll scrollable-text)
+  (cadr (box-children scrollable-text)))
+
+
+
+;;; Text has special protect-from-gc! procedures
+
+(define (text-protect-from-gc! text stuff)
+  (let ((crud (crud-that-I-dont-want-to-gc-away text)))
+    (set-cdr! crud (cons stuff (cdr crud))))
+  'done)
+
+(define (text-unprotect-from-gc! text stuff)
+  (let ((crud (crud-that-I-dont-want-to-gc-away text)))  
+    (set-cdr! crud (delq! stuff (cdr crud))))
+  'done)  
+
+(define (text-flush-protect-list! text)
+  (let ((crud (crud-that-I-dont-want-to-gc-away text)))  
+    (set-cdr! crud '()))
+  'done)  
+
+
+
+;;; TextTags
+
+(define (make-text-tag text index1 . index2)
+  (let ((name (tk-gen-name "texttag")))
+    (ask-widget text `(tag add ,name ,index1 ,@index2))
+    (let ((texttag (make-texttag texttag-ask-widget
+                                texttag-add-event-handler!
+                                'invalid
+                                name
+                                text
+                                '())))
+      (text-protect-from-gc! text texttag)
+      texttag)))
+
+(define (texttag-add-event-handler! tag event handler substitutions)
+  (let ((text (TextTag.text tag))
+       (handler (proc-with-transformed-args handler substitutions)))
+    (set-texttag.callbacks! tag
+                           (cons handler (texttag.callbacks tag)))
+    (ask-widget text
+               `(tag bind
+                 ,(TextTag.name tag)
+                 ,event
+                 ("SchemeCallBack" ,(object-hash handler *our-hash-table*)
+                                   ,@substitutions)))))
+
+(define (texttag-ask-widget tag arg-list)
+  (let* ((tag-name (TextTag.name tag))
+        (text     (TextTag.text tag))
+        (command  (car arg-list))
+        (new-arg-list (cons "tag"
+                            (cons command
+                                  (cons tag-name (cdr arg-list))))))
+    (let ((result (ask-widget text new-arg-list)))
+      (if (eq? command 'delete)
+         (text-unprotect-from-gc! text tag))
+      result)))
+
diff --git a/v7/src/swat/scheme/tk-mit.scm b/v7/src/swat/scheme/tk-mit.scm
new file mode 100644 (file)
index 0000000..046f53e
--- /dev/null
@@ -0,0 +1,379 @@
+; -*- Scheme -*-
+;;;;; C external interfaces to Tk procedures not associated with
+;;;;; a particular widget.
+;;;; $Id: tk-mit.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
+
+;;;; This is the lowest level Scheme interface to general TK/TCL data
+;;;; structures.  Primitives are defined in tk-mit.c and tk.c
+
+(define-primitives
+  (%tclGlobalEval 2)
+  (%tkCompletelyHandlesEvent? 1)
+  (%tkCreateTopLevelWindow 3)
+  (%tkDoEvents 0)
+  (%tkDrainCallBacks 2)
+  (%tkGenerateSchemeEvent 2)
+  (%tkInit 2)
+  (%tkInvokeCommand -1)
+  (%tkKillApplication 1)
+  (%tkManageGeometry 2)
+  (%tkMapWindow 1)
+  (%tkMoveResizeWindow 5)
+  (%tkMoveWindow 3)
+  (%tkNextWakeup 0)
+  (%tkResizeWindow 3)
+  (%tkUnmapWindow 1)
+  (%tkWidget.tkwin 1)
+  (%tkWinDisplay 1)
+  (%tkWinReqHeight 1)
+  (%tkWinReqWidth 1)
+  (%tkWinHeight 1)
+  (%tkWinIsMapped? 1)
+  (%tkWinName 1)
+  (%tkWinPathName 1)
+  (%tkWinWidth 1)
+  (%tkWinWindow 1)
+  (%tkWinX 1)
+  (%tkWinY 1)
+)
+
+;;;; Support code
+
+(define tk-gen-name
+  (let ((count 0))
+    (lambda (name)
+      (set! count (+ 1 count))
+      (string-append name (number->string count)))))
+\f
+;;;; Entry points in alphabetical order
+
+(define (get-interval-to-tk-wakeup)
+  (%tkNextWakeup))
+
+
+;;; A not-so-precise number->string that is faster and more than
+;;; sufficient for our purposes. 
+
+(define (swat:number->string x)
+
+  (define (digits x n tail)
+    (define (next* ch x*)
+      (cons ch (digits x* (fix:- n 1) tail)))
+    (define-integrable (next ch delta)
+      (next* ch (flo:* (flo:- x delta) 10.0)))
+    (cond ((< n 0)  tail)
+         ((flo:< x 1.e-10)  tail)
+         ((flo:< x 1.0) (next #\0 0.0))
+         ((flo:< x 2.0) (next #\1 1.0))
+         ((flo:< x 3.0) (next #\2 2.0))
+         ((flo:< x 4.0) (next #\3 3.0))
+         ((flo:< x 5.0) (next #\4 4.0))
+         ((flo:< x 6.0) (next #\5 5.0))
+         ((flo:< x 7.0) (next #\6 6.0))
+         ((flo:< x 8.0) (next #\7 7.0))
+         ((flo:< x 9.0) (next #\8 8.0))
+         (else          (next #\9 9.0))))
+       
+  (define (format-exponent e)
+    (define (format-integer n tail)
+      (define (+digit k) (cons (ascii->char (fix:+ k 48)) tail))
+      (if (fix:< n 10)
+         (+digit n)
+         (let ((front (fix:quotient n 10))
+               (back  (fix:remainder n 10)))
+           (format-integer front (+digit back)))))
+    (cond ((fix:= e 0) '())
+         ((fix:< e 0)
+          (cons* #\e #\- (format-integer (fix:- 0 e) '())))
+         (else
+          (cons* #\e (format-integer e '())))))
+
+  (define (scale x e)
+    (cond ((flo:< x 1.0e-30) '(#\0 #\. #\0))
+         ((flo:< x 1.0)     (scale (flo:* x 1000.0) (- e 3)))
+         ((flo:< x 10.0)
+          (let* ((tail  (format-exponent e))
+                 (ds (digits x 8 tail)))
+            (if (eq? (cdr ds) tail)
+                (cons* (car ds) #\. #\0 (cdr ds))
+                (cons* (car ds) #\. (cdr ds)))))
+         (else          (scale (flo:* x 0.1) (+ e 1)))))
+
+  (if (flo:flonum? x)
+      (list->string
+       (if (flo:< x 0.0)
+          (cons #\- (scale (flo:- 0.0 x) 0))
+          (scale x 0)))
+      (number->string x 10)))
+
+
+#|
+;;; This is a kludge to prevent tk from thinking that .7 is a name and
+;;; not a number.  
+(define (number->tk-string n)
+  (let ((abs-n (abs n)))
+    (if (< abs-n 1)
+       (let ((s (swat:number->string abs-n)))
+         (if (< n 0)
+             (string-append "-0" s)
+             (string-append "0" s)))
+       (swat:number->string n))))
+|#
+
+(define (stringify-for-tk arg)
+  (define (->string arg)
+    (cond ((string? arg) arg)
+         ((number? arg)
+          ;;(number->tk-string arg)
+          (swat:number->string arg)
+          )
+         ((symbol? arg) (symbol->string arg))
+         ((TK-variable? arg) (TK-variable.tk-name arg))
+         ((pair? arg) (apply string-append (map stringify-for-tk arg)))
+         ((procedure? arg) (->string (arg)))
+         (else (error "tcl-global-eval: Unknown argument type"
+                      arg))))
+  (string-append "{" (->string arg) "} "))
+
+(define (tk-op thunk)
+  (let ((result (thunk)))
+    (kick-uitk-thread)
+    result))
+   
+(define (tcl-global-eval application command-name args)
+  (tk-op
+   (lambda ()
+     (%tclGlobalEval
+      (application->TKMainWindow application)
+      (apply string-append
+            (map stringify-for-tk (cons command-name args)))))))
+
+;;;turn off all floating errors around TK processing
+;;;Note that we don't need a dynamic wind because
+;;;%tkCompletelyHandlesEvent? always completes.  If the argument is
+;;;bad it returns a 0.
+
+(define (tk-completely-handles-event? os-event)
+  (let ((old-mask (set-floating-error-mask! 0)))
+    (let ((result (%tkCompletelyHandlesEvent? os-event)))
+      (set-floating-error-mask! old-mask)
+      (if (eq? result 0)
+         (error "bad argument to tk-completely-handles-event?" os-event)
+         result))))
+
+(define (tk-create-top-level-window main-window callbackhash)
+  (tk-op
+   (lambda ()
+     (%tkCreateTopLevelWindow main-window
+                             (tk-gen-name "top-level-window")
+                             callbackhash))))
+
+(define (tk-doevents)
+  ;; Turn off floating errors
+  (let ((old-mask (set-floating-error-mask! 0)))
+    ;; Do all pending Tk events, which should only be do-when-idles
+    (%tkDoEvents)
+    (set-floating-error-mask! old-mask))
+  (do-tk-callbacks))
+
+(define (tk-generate-Scheme-event event-mask unwrapped-tk-window)
+  ;; Cause TK to signal us that Scheme wants to know about these kinds
+  ;; of events on this window.
+  (%tkGenerateSchemeEvent event-mask unwrapped-tk-window))
+
+(define (tk-init xdisplay)
+  ;; Set up an initial environment with a Tcl interpreter
+  (tk-op
+   (lambda ()
+     (%tkInit (->xdisplay xdisplay)
+             (tk-gen-name
+              (string-append "main-window-for-display-"
+                             (number->string (->xdisplay xdisplay))))))))
+
+(define (tk-invoke-command command-name main-window arg-strings)
+  (define commands
+    `((After . 0)
+      (Bind . 1)
+      (Destroy . 2)
+      (Focus . 3)
+      (Grab . 4)
+      (Option . 5)
+      (Pack . 6)
+      (Place . 7)
+      (Selection . 8)
+      (Tk . 9)
+      (Tkwait . 10)
+      (Update . 11)
+      (Winfo . 12)
+      (Wm . 13)))
+  (tk-op 
+   (lambda ()
+     (apply %tkInvokeCommand (cdr (assq command-name commands))
+           main-window
+           arg-strings))))
+
+(define (tk-kill-application main-window)
+  ;; main-window is an integer, not wrapped
+  (%tkKillApplication main-window))
+
+(define (tk-manage-geometry widget manager-procedure)
+  ;; Arrange for manager-procedure to be called with no arguments
+  ;; whenever TK requests geometry operations on widget.
+  (tk-op
+   (lambda ()
+     (%tkManageGeometry (tk-widget.tkwin widget)
+                       (and manager-procedure
+                            (hash manager-procedure
+                                  *our-hash-table*))))))
+
+(define (tk-map-window tkwin)
+  (tk-op (lambda () (%tkmapwindow tkwin))))
+
+(define (tk-move-resize-widget widget screen-area)
+  (tk-op
+   (lambda ()
+     (%tkMoveResizeWindow (tk-widget.tkwin widget)
+                         (Point.X (UITKRectangle.Offset screen-area))
+                         (Point.Y (UITKRectangle.Offset screen-area))
+                         (UITKRectangle.Width screen-area)
+                         (UITKRectangle.Height screen-area)))))
+
+(define (TK-Unmap-Window tkwin)
+  (tk-op (lambda () (%tkUnmapWindow tkwin))))
+
+(define (tk-widget.tkwin widget)
+  (%tkWidget.tkwin (->widget widget)))
+
+(define (tkwin.display tkwin)
+  (%tkWinDisplay tkwin))
+
+(define (tkwin.req-height tkwin)
+  (%tkWinReqHeight tkwin))
+
+(define (tkwin.req-width tkwin)
+  (%tkWinReqWidth tkwin))
+
+(define (tkwin.height tkwin)
+  (%tkWinHeight tkwin))
+
+(define (tkwin.IsMapped? tkwin)
+  (%tkWinIsMapped? tkwin))
+
+(define (tkwin.width tkwin)
+  (%tkWinWidth tkwin))
+
+(define (tkwin.window tkwin)
+  ;; Deliberately don't do a wrap-window. Instead, allow a higher
+  ;; level to do it, since the server maintains the window hierarchy
+  ;; and effectively keeps pointers for us.
+  (%tkWinWindow tkwin))
+
+(define (tkwin.name tkwin)
+  (%tkWinName tkwin))
+
+(define (tkwin.pathname tkwin)
+  (%tkWinPathName tkwin))
+
+(define (tkwin.x tkwin)
+  (%tkWinX tkwin))
+
+(define (tkwin.y tkwin)
+  (%tkWinY tkwin))
+\f
+;;;; TK Callback handling
+
+(define (do-tk-callbacks-from-string string)
+  ;; The string has the following format:
+  ;;  <char. count>
+  ;;    <nchars>chars
+  ;;    <nchars>chars
+  ;;  ...
+  ;;  where <char. count> is the number of characters in the object ID
+  ;;  and its associated string arguments.  The "<" and ">" are NOT
+  ;;  meta-characters; they are used for separating the entries and
+  ;;  error detection.
+  (define (split-string-by-number string receiver)
+    ;; Expects a character count in angle brackets.  Calls receiver
+    ;; with the counted string and the rest, or #F/#F if the string is
+    ;; empty.
+    (cond
+     ((string-null? string) (receiver #F #F))
+     ((not (char=? (string-ref string 0) #\<))
+      (error "Split-String-By-Number: Badly formed entry"
+            string))
+     (else
+      (let ((break-at (string-find-next-char string #\>)))
+       (if (not break-at)
+           (error "Split-String-By-Number: entry not terminated"
+                  string)
+           (let ((count (string->number (substring string 1 break-at)))
+                 (after-count (+ break-at 1))
+                 (slength (string-length string)))
+             (cond
+              ((not count)
+               (error "Split-String-By-Number: non-numeric count" string))
+              ((> (+ after-count count) slength)
+               (error "Split-String-By-Number: count too big" string))
+              (else
+               (let ((end (+ after-count count)))
+                 (receiver (substring string after-count end)
+                           (substring string end slength)))))))))))
+  (define (parse-entry string receiver)
+    ;; Entry starts with a character count in angle brackets
+    ;; Receiver is called with an object, a vector of strings, and the
+    ;; remaining string.
+    (split-string-by-number string
+     (lambda (entry after-entry)
+       (let loop ((rest entry)
+                 (strings '()))
+        (split-string-by-number rest
+         (lambda (this-string rest-of-strings)
+           (if this-string
+               (loop rest-of-strings
+                     (cons this-string strings))
+               (let ((all-strings (reverse strings)))
+                 (if (null? all-strings)
+                     (error "Parse-Entry: no entries" string))
+                 (let* ((Object-Name (car all-strings))
+                        (Object-ID (string->number object-name)))
+                   (if (not object-id)
+                       (error "Parse-Entry: non-number object ID"
+                              string object-name))
+                   ;; Note that the object associated with object-id
+                   ;; may have been GCed away!
+                   (receiver (object-unhash object-id *our-hash-table*)
+                             (cdr all-strings)
+                             after-entry))))))))))
+  (if string
+      (let callback-loop ((string string))
+       (if (string-null? string)
+           'done
+           (parse-entry string
+                        (lambda (callback list-of-string-args rest-of-string)
+                          ;; "callback" will be #F if it GC'ed away
+                          (if callback
+                              (our-with-thread-mutex-locked
+                               'do-tk-callback
+                               *event-processing-mutex*
+                               (lambda ()
+                                 (apply callback list-of-string-args))))
+                          (callback-loop rest-of-string))))))
+  'OK)
+
+(define *event-processing-mutex* (make-thread-mutex))
+
+(define do-tk-callbacks
+  (let ((nchars 0)
+       (string (make-string 0)))
+    (lambda ()
+      (let ((nchars-ready (%tkDrainCallBacks nchars string)))
+       (if nchars-ready
+           (if
+            (positive? nchars-ready)
+            (begin
+              (set! nchars nchars-ready)
+              (set! string (make-string nchars-ready))
+              (do-tk-callbacks))
+            'OK)
+           (do-tk-callbacks-from-string string))))))
+
diff --git a/v7/src/swat/scheme/uitk-macros.scm b/v7/src/swat/scheme/uitk-macros.scm
new file mode 100644 (file)
index 0000000..43af32c
--- /dev/null
@@ -0,0 +1,142 @@
+;;;; -*-Scheme-*-
+;;; $Id: uitk-macros.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
+;;; derived from macros.sc,v 1.1 1993/02/16 14:04:09 jmiller Exp $
+;;; Primitive X toolkit for Scheme->C.
+;;; RHH, September, 1989.
+;;; Macro definitions.
+
+;;; Stolen on January 17, 1993 by Jim Miller for use with UITK
+;;; Updated on June 27, 1993 by a bunch of us to use records instead
+;;; of vectors.
+
+;;;; SCC-DEFINE-STRUCTURE
+
+;;;; Components can be:
+;;;;   a symbol (name of structure component)
+;;;;   a pair (name and default value)
+;;;; Produces (in-lined)
+;;;;   predicate procedure: (<name>? object)
+;;;;   accessor procedures: (<name>.<component> object)
+;;;;   mutator procedures: (SET-<name>.<component>! object new-value)
+;;;;   internal constants: *-<name>.<component>-*
+;;;;   internal contant: *-<name>.STRUCTURE-SIZE-*
+;;;;   (re-)initialization procedure: (INIT-<name> object comp1 ...)
+;;;;   creator procedure: (MAKE-<name> comp1 ...)
+
+;;;; Note: The MAKE- and INIT- procedures have required arguments
+;;;;       for all components that do not have default values.
+
+;;;; Example:
+;;;; (scc-define-structure dot x y (color 'black))
+;;;; (define a-dot (make-dot 3 4))
+;;;; (set-dot.color! a-dot 'green)
+;;;; (list (dot.x a-dot) (dot.color a-dot)) -> (3 green)
+
+(scc-define-syntax (scc-define-structure name . components)
+  (define (symbol-format . args)
+    (string->symbol
+     (apply string-append
+           (map (lambda (object)
+                  (cond ((string? object) object)
+                        ((symbol? object) (symbol->string object))
+                        (else (error
+                               'SYMBOL-FORMAT
+                               "Neither symbol nor string ~A"
+                               object))))
+                args))))
+  (let ((size-name (symbol-format "*-" name '-STRUCTURE-SIZE "-*"))
+       (self-varname (lambda (fn-name)
+                       (symbol-format 'SELF "/" name "/" fn-name)))
+       (predicate-name (symbol-format name "?")))
+
+    (define (component-name component)
+      (if (pair? component) (car component) component))
+
+    (define (accessor-name component)
+      (symbol-format name "." (component-name component)))
+
+    (define (set-symbol component)
+      (symbol-format 'SET "-" name "." (component-name component) "!"))
+
+    (define (gen-accessors components counter)
+      (if (null? components)
+         `((DEFINE-CONSTANT ,size-name ,counter))
+         (let ((cname (component-name (car components))))
+           (let ((offset-name (symbol-format "*-" name "." cname "-*"))
+                 (self (self-varname cname)))
+             `((DEFINE-CONSTANT ,offset-name ,counter)
+               (DEFINE-IN-LINE (,(accessor-name cname) ,self)
+                 (IF (,predicate-name ,self)
+                     (VECTOR-REF ,self ,offset-name)
+                     (ERROR ',(accessor-name cname)
+                            "Object not correct type ~A" ,self)))
+               (DEFINE-IN-LINE (,(set-symbol cname) ,self NEW-VALUE)
+                 (IF (,predicate-name ,self)
+                     (BEGIN
+                       (VECTOR-SET! ,self ,offset-name NEW-VALUE)
+                       'MODIFIED!)
+                     (ERROR ',(set-symbol cname)
+                            "Object not correct type ~A" ,self)))
+               ,@(if *running-in-mit-scheme*
+                     '()
+                     `((DEFINE (,(accessor-name cname) ,self)
+                         (IF (,predicate-name ,self)
+                             (VECTOR-REF ,self ,offset-name)
+                             (ERROR ',(accessor-name cname)
+                                    "Object not correct type ~A" ,self)))
+                       (DEFINE (,(set-symbol cname) ,self NEW-VALUE)
+                         (IF (,predicate-name ,self)
+                             (BEGIN
+                               (VECTOR-SET! ,self ,offset-name NEW-VALUE)
+                               'MODIFIED!)
+                             (ERROR ',(set-symbol cname)
+                                    "Object not correct type ~A" ,self)))))
+               ,@(gen-accessors (cdr components) (+ counter 1)))))))
+
+    (define (make-bvl components)
+      (cond ((null? components) '())
+           ((pair? (car components)) (make-bvl (cdr components)))
+           (else (cons (car components) (make-bvl (cdr components))))))
+
+    (define (gen-structure-initialization self-name components)
+      (if (null? components)
+         '()
+         `((,(set-symbol (car components))
+            ,self-name
+            ,@(if (pair? (car components))
+                  (cdar components)
+                  (list (car components))))
+           ,@(gen-structure-initialization self-name (cdr components)))))
+
+    (let ((init-name (symbol-format 'INIT "-" name))
+         (init-self-name (self-varname 'INIT))
+         (init-bvl (make-bvl components))
+         (accessors (gen-accessors components 1))
+         (tag (symbol-format "#[" name "]")))
+      `(begin
+        (if ,*running-in-mit-scheme*
+            (ADD-UNPARSER-SPECIAL-OBJECT!
+             ',tag
+             (lambda (obj)
+               (display "#[scc-object ")
+               (display ',name)
+               (display " ")
+               (display (hash obj))
+               (display "]"))))
+        ,@accessors
+        (DEFINE (,(symbol-format name '/pp) OBJ)
+          (IF (NUMBER? OBJ) (SET! OBJ (UNHASH OBJ)))
+          (FOR-EACH (LAMBDA (FIELD-NAME ACCESSOR)
+                      (PP (LIST FIELD-NAME (ACCESSOR OBJ))))
+                    ',(map component-name components)
+                    (LIST ,@(map accessor-name components))))
+        (DEFINE (,predicate-name OBJ)
+          (AND (VECTOR? OBJ)
+               (= (VECTOR-LENGTH OBJ) ,size-name)
+               (EQ? (VECTOR-REF OBJ 0) ',tag)))
+        (DEFINE (,init-name ,init-self-name ,@init-bvl)
+          (VECTOR-SET! ,init-self-name 0 ',tag)
+          ,@(gen-structure-initialization init-self-name components)
+          ,init-self-name)
+        (DEFINE (,(symbol-format 'MAKE "-" name) ,@init-bvl)
+          (,init-name (make-vector ,size-name) ,@init-bvl))))))
diff --git a/v7/src/swat/scheme/uitk.scm b/v7/src/swat/scheme/uitk.scm
new file mode 100644 (file)
index 0000000..0718354
--- /dev/null
@@ -0,0 +1,565 @@
+;;;;; -*- scheme -*-
+;;;;;
+;;;;; derived from uitk.sc,v 1.2 1993/02/25 14:13:22 jmiller exp $
+;;;;; $id: uitk.scm,v 1.11 1993/02/26 15:10:23 jmiller exp jmiller $
+
+(define debugging-port #f)
+
+(define (debug-print . args)
+  (let ((port (or debugging-port (current-output-port)))
+       (string (with-output-to-string
+                 (lambda ()
+                   (display (cons 'debugging (cons (current-thread) args)))))))
+    (without-interrupts
+     (lambda () (display string port) (newline port)))))
+
+;;;; notes
+
+;;;; message flows define relationships.  normally, an operation that
+;;;; changes state on an object will use one of these relationships to
+;;;; alert other objects of the change.  this permits an external
+;;;; constraint satisfaction system to propagate changes through the
+;;;; system.  here are the flows currently
+;;;; assumed:
+;;;;     (1) geometry.  all object can report a desired size which
+;;;;         includes stretch, shrink, and minimum size.  this is a
+;;;;         pure query and does not establish a relationship.  the
+;;;;         relationship commences with a call to either
+;;;;         assign-screen-area! or assign-geometry!.  these
+;;;;         specify an area to be used and alert any object
+;;;;         monitoring for geometry changes.
+;;;;     (2) events.  an object may have children to whom it reports
+;;;;         events.  event directors take an event and a list of
+;;;;         children and propagate the event to the correct child
+;;;;         or take a default action.  this is a one-way interaction
+;;;;         (i.e. children don't know about parents).
+;;;;     (3) contexts.
+
+;;;; i'd like to use tiny clos as a means for handling the private
+;;;; slot in UIObj.  this allows the common operations to be as fast
+;;;; as possible (i.e. not using generic dispatch) while still
+;;;; permitting extensibility.  for the moment, however, i'm using
+;;;; simple structures and type-specific operations.
+
+;;;; when assign-screen-area! is called with #f instead of a screen
+;;;; area it means that it has had its area retracted.  this happens
+;;;; when the geometric parent is told to remove it as a child.  if it
+;;;; has been using the parent's window, it better clean up -- this
+;;;; may mean reparenting its own window to the root, i guess.
+\f
+(define (sub-vectors point-1 point-2)
+  (make-point
+   (- (point.x point-1) (point.x point-2))
+   (- (point.y point-1) (point.y point-2))))
+
+(define (add-vectors point-1 point-2)
+  (make-point
+   (+ (point.x point-1) (point.x point-2))
+   (+ (point.y point-1) (point.y point-2))))
+
+(define (point= point1 point2)
+  (or (eq? point1 point2)
+      (and
+       (= (point.x point1) (point.x point2))
+       (= (point.y point1) (point.y point2)))))
+
+(define (size= size1 size2)
+  (or (eq? size1 size2)
+      (and
+       (= (size.width size1) (size.width size2))
+       (= (size.height size1) (size.height size2)))))
+
+(define (copy-rectangle rect)
+  (vector-copy rect))
+
+(define (UITKRectangle.Width rect)
+  (size.width (UITKRectangle.Size rect)))
+
+(define (UITKRectangle.Height rect)
+  (size.height (UITKRectangle.Size rect)))
+
+(define (rectangle= rect1 rect2)
+  (or (eq? rect1 rect2)
+      (and (point= (UITKRectangle.offset rect1) (UITKRectangle.offset rect2))
+          (size= (UITKRectangle.Size rect1) (UITKRectangle.Size rect2)))))
+
+(define (screen-area= sa1 sa2)
+  (or (and sa1 sa2 (rectangle= sa1 sa2))
+      (and (not sa1) (not sa2))))
+
+(define (translate-rectangle rect point)
+  (and rect
+       (make-UITKRectangle point (UITKRectangle.Size rect))))
+
+\f
+;;;; event objects
+
+(define (make-point-event type os-event window offset)
+  (make-event 'point type os-event window offset 'invalid 'invalid))
+
+(define (make-rectangle-event type os-event window offset width height)
+  (make-event 'rectangle type os-event window offset width height))
+
+(define (make-unknown-event type os-event window)
+  (make-event 'unknown type os-event window 'invalid 'invalid 'invalid))
+
+(define (point-event? obj)
+  (and (event? obj)
+       (eq? (event.point-or-rectangle? obj) 'point)))
+
+(define (rectangle-event? obj)
+  (and (event? obj)
+       (eq? (event.point-or-rectangle? obj) 'rectangle)))
+
+\f
+;;;; General support procedures
+
+(define (make-lookup key-fn)
+  (lambda (object list)
+    (let loop ((list list))
+      (cond ((null? list) #F)
+           ((eq? object (key-fn (car list))) (car list))
+           (else (loop (cdr list)))))))
+
+(define (make-del-op! test?)
+  (lambda (op)
+    (lambda (key op-list)
+      (define (loop previous current)
+       (cond ((null? current) op-list)
+             ((test? (op (car current)) key)
+              (set-cdr! previous (cdr current))
+              op-list)
+             (else (loop current (cdr current)))))
+      (cond ((null? op-list) '())
+           ((test? (op (car op-list)) key)
+            (cdr op-list))
+           (else (loop op-list (cdr op-list)))))))
+
+(define del-op! (make-del-op! eq?))
+
+(define del-assq! (del-op! car))
+(define del-assv! ((make-del-op! eqv?) car))
+
+(define (make-weak-lookup key-fn)
+  (lambda (object list)
+    (let loop ((list list))
+      (cond ((null? list) #F)
+           ((eq? object (key-fn (weak-car list))) (weak-car list))
+           (else (loop (weak-cdr list)))))))
+
+(define (make-weak-del-op! test?)
+  (lambda (op)
+    (lambda (key op-list)
+      (define (loop previous current)
+       (cond ((null? current) op-list)
+             ((test? (op (weak-car current)) key)
+              (weak-set-cdr! previous (weak-cdr current))
+              op-list)
+             (else (loop current (weak-cdr current)))))
+      (cond ((null? op-list) '())
+           ((test? (op (weak-car op-list)) key)
+            (weak-cdr op-list))
+           (else (loop op-list (weak-cdr op-list)))))))
+\f
+;;;; UI Objects
+
+(define (one-parent-only! child object)
+  (let ((child-guts (uiobjinternals child)))
+    (if (UIObjInternals.already-have-a-parent? child-guts)
+       (error
+        "ADD-CHILD!: Hal says 'success has many parents, but a UIObj has only one'"
+        object child)
+       (set-UIObjInternals.already-have-a-parent?! child-guts #T))))
+
+(define (get-UITKWindow obj)
+  (let ((surface (drawing-surface obj)))
+    (and (DrawingSurface? surface)
+        (DrawingSurface.UITKWindow surface))))
+
+(define (DrawingSurface.Application ds)
+  (ToolKitWindow.Application (DrawingSurface.ToolKitWindow ds)))
+
+
+;;; The alerts are stored as alists with the key being, typically, the
+;;; reason the alert was added.  This allows the alert to be removed
+;;; if/when the reason is retracted.  The alert function is called
+;;; with the reason as its argument.
+
+(define make-add-alert!
+  (let ((find-alert (make-lookup alert.reason)))
+    (lambda (accessor mutator!)
+      (lambda (object key alert-fn)
+       (let* ((previous (accessor object))
+              (old-value (find-alert key previous)))
+         (if old-value
+             (begin
+               ;;(set-alert.function! old-value alert)
+               ;; (bkpt "gottcha in make-add-alert!")
+               (debug-print 'gottcha!))
+             (mutator! object `(,(make-alert key alert-fn) ,@previous)))
+         'added)))))
+
+(define make-remove-alert!
+  (let ((del-alert! (del-op! alert.reason)))
+    (lambda (accessor mutator!)
+      (lambda (object key)
+       (mutator! object (del-alert! key (accessor object)))
+       'removed))))
+
+(define (make-alert! arity accessor)
+  ;; Arity is the arity expected of the alert function.  Some alerts
+  ;; pass additional information -- geometry, for example, passes both
+  ;; the previous screen-area and the new screen-area.  The alert
+  ;; function can generally be assumed to have lexical access to both
+  ;; the reason for the alert (specified when the alert is created)
+  ;; and the object that generated the alert.
+  (case arity
+    ((0) (lambda (object)
+          (for-each (lambda (alert) ((alert.function alert)))
+                    (accessor object))))
+    ((1) (lambda (object arg)
+          (for-each (lambda (alert) ((alert.function alert) arg))
+                    (accessor object))))
+    ((2) (lambda (object arg1 arg2)
+          (for-each (lambda (alert) ((alert.function alert) arg1 arg2))
+                    (accessor object))))
+    (else (lambda (object . args)
+            (for-each (lambda (alert) (apply (alert.function alert) args))
+                      (accessor object))))))
+\f
+;;; Geometry alerts:
+;;;  Initiated when ASSIGN-SCREEN-AREA! is acted on by an object, by
+;;;  calling
+;;;    (GEOMETRY-CHANGE! object
+;;;                      old-used-screen-area new-used-screen-area)
+;;;  An alert is added by calling
+;;;    (ON-GEOMETRY-CHANGE! object reason 
+;;;       (lambda (old new) ...))
+;;;  The new-used-screen-area may be #T indicating that an object is
+;;;  requesting a new area, or it may be #F or an actual area
+;;;  indicating that it has been given (via ASSIGN-SCREEN-AREA!) a
+;;;  specific area to use.
+(define on-geometry-change!
+  (make-add-alert! %geometry-alerts set-%geometry-alerts!))
+(define forget-geometry-change!
+  (make-remove-alert! %geometry-alerts set-%geometry-alerts!))
+(define geometry-change! (make-alert! 2 %geometry-alerts))
+
+;;; Event alerts:
+;;;  Initiated when HANDLE-EVENT is acted on by an object, by calling
+;;;    (EVENT! object event)
+;;;  An alert is added by calling
+;;;    (ON-EVENT! object reason 
+;;;      (lambda (event) ...))
+(define on-event!
+  (make-add-alert! %event-alerts set-%event-alerts!))
+(define forget-event!
+  (make-remove-alert! %event-alerts set-%event-alerts!))
+(define event! (make-alert! 1 %event-alerts))
+
+;;; Context alerts:
+;;;  Initiated when SET-CONTEXT! is acted on by an object, by calling
+;;;    (CONTEXT-CHANGE! object new-context)
+;;;  An alert is added by calling
+;;;    (ON-CONTEXT-CHANGE! object reason 
+;;;       (lambda (new-context) ...))
+;;; NOTE: This protocol is not well worked out.
+(define on-context-change!
+  (make-add-alert! %context-alerts set-%context-alerts!))
+(define forget-context-change!
+  (make-remove-alert! %context-alerts set-%context-alerts!))
+(define context-change! (make-alert! 1 %context-alerts))
+
+;;; Death alerts:
+;;;  Initiated when an object has decided it is dead by calling
+;;;    (DEATH! object)
+;;;  An alert is added by calling
+;;;    (ON-DEATH! object reason (lambda () ...))
+(define on-death!
+  (make-add-alert! %death-alerts set-%death-alerts!))
+(define forget-death-notification!
+  (make-remove-alert! %death-alerts set-%death-alerts!))
+(define death! (make-alert! 0 %death-alerts))
+
+(define (forget! reporter reason)
+  (forget-geometry-change! reporter reason)
+  (forget-event! reporter reason)
+  (forget-death-notification! reporter reason)
+  (forget-context-change! reporter reason))
+\f
+;;;; Queues for communication between interrupt level and user level
+
+(define (empty-queue? queue)
+  (without-interrupts
+   (lambda ()
+     (not (queue.%head queue)))))
+
+(define (enqueue! queue value)
+  (let ((element (list value)))
+    (without-interrupts
+     (lambda ()
+       (if (queue.%head queue)
+          (set-cdr! (queue.%tail queue) element)
+          (set-queue.%head! queue element))
+       (set-queue.%tail! queue element)))))
+
+(define (dequeue! queue)
+  ;; Not safe to use if the queue is empty!
+  (without-interrupts
+   (lambda ()
+     (let* ((head (queue.%head queue))
+           (next (cdr head)))
+       (if (null? next)
+          (begin
+            (set-queue.%head! queue #F)
+            (set-queue.%tail! queue #F))
+          (set-queue.%head! queue next))
+       (car head)))))
+
+(define (read-and-empty-queue! queue)
+  ;; Returns a list of items, and leaves the queue empty
+  (let ((quick-result
+        (without-interrupts
+         (lambda ()
+           (let ((result (queue.%head queue)))
+             (set-queue.%head! queue #F)
+             (set-queue.%tail! queue #F)
+             result)))))
+    (or quick-result '())))
+\f
+
+(define (update-locked-list! locked-list receiver)
+  ;; Receiver gets the contents and returns a replacement
+  (our-with-thread-mutex-locked
+   'update-locked-list!
+   (locked-list.%mutex locked-list)
+    (lambda ()
+      (set-locked-list.%data!
+       locked-list
+       (receiver (locked-list.%data locked-list)))
+      ))
+  'DONE)
+
+(define (with-locked-list locked-list receiver)
+  ;; Receiver gets the contents
+  (our-with-thread-mutex-locked
+   'with-locked-list
+   (locked-list.%mutex locked-list)
+    (lambda ()
+      (receiver (locked-list.%data locked-list))
+      )))
+
+(define (our-with-thread-mutex-locked reason mutex thunk)
+  reason
+  (with-thread-mutex-locked mutex thunk))
+\f
+
+;;; The default for these is just to do information propagation
+;;; through the alert mechanism.
+
+(define (UIObj-set-context! UIObj Context)
+  (if (vector? Context)
+      (context-change! UIObj Context)
+      (error "UIOBJ-SET-CONTEXT!: Bad context" Context)))
+
+(define (UIObj-assign-screen-area! UIObj Screen-Area)
+  (if (or (UITKRectangle? Screen-Area)
+         (eq? #F Screen-Area))
+      (begin
+       (set-assigned-screen-area! UIObj Screen-Area)
+       (let ((old (used-screen-area UIObj)))
+         (set-used-screen-area! UIObj screen-area)
+         (geometry-change! UIObj old screen-area))
+       screen-area)
+      (error "UIOBJ-ASSIGN-SCREEN-AREA!: Bad screen area" Screen-Area)))
+
+(define (assign-location! object point)
+  ;; There may be a better way to do this by making it part of the
+  ;; geometry protocol.
+  (assign-screen-area! object
+    (translate-rectangle (used-screen-area object) point)))
+
+(define (UIObj-assign-drawing-surface! UIObj Surface)
+  (check-drawing-surface! UIObj Surface)
+  (geometry-change! UIObj #F #F)
+  'OK)
+
+(define (check-drawing-surface! UIObj Surface)
+  ;; Surface should be one of 'UNASSIGNED, 'RETRACTED, or a
+  ;; DrawingSurface
+  ;; This is used by internal routines that want to do the default
+  ;; operation (UIObj-assign-drawing-surface!) but don't want to
+  ;; announce the geometry change yet.
+  (let ((old (Drawing-Surface UIObj)))
+    (cond ((eq? old Surface) 'UNCHANGED)
+         ((or (eq? Surface 'RETRACTED)
+              (eq? old 'UNASSIGNED))
+          (set-drawing-surface! UIObj  Surface)
+          'CHANGED)
+         (else
+          (error "UIOBJ-ASSIGN-DRAWING-SURFACE!: Can't change surface"
+                 UIObj old surface)))))
+
+(define (assign-geometry! UIObj Surface Rectangle)
+  (assign-drawing-surface! UIObj surface)
+  (assign-screen-area! UIObj rectangle))
+\f
+(define (point-in-rectangle? point rect-offset width height)
+  (let ((rect-x (Point.X rect-offset))
+       (rect-y (Point.Y rect-offset))
+       (x (Point.X point))
+       (y (Point.Y point)))
+    (and (<= rect-x X)
+        (< X (+ rect-x Width))
+        (<= rect-Y Y)
+        (< Y (+ rect-Y Height)))))
+
+(define (rectangle-overlaps-rectangle? p w h p2 w2 h2)
+  (define (rectangles-overlap? LowEdge LowDelta HighEdge)
+    (<= HighEdge (+ LowEdge LowDelta)))
+  (let ((x (Point.X p))
+       (y (Point.Y p))
+       (x2 (Point.X p2))
+       (y2 (Point.Y p2)))
+    (and (if (< X X2)
+            (rectangles-overlap? X W X2)
+            (rectangles-overlap? X2 W2 X))
+        (if (< Y Y2)
+            (rectangles-overlap? Y H Y2)
+            (Rectangles-Overlap? Y2 H2 Y)))))
+
+(define (uiobj-point-within? UIObj Point)
+  (if (vector? Point)
+      (let ((screen-area (Used-Screen-Area UIObj)))
+       (and screen-area
+            (let ((Offset (UITKRectangle.Offset screen-area))
+                  (Height (UITKRectangle.Height screen-area))
+                  (Width (UITKRectangle.Width screen-area)))
+              (point-in-rectangle? Point Offset Width Height))))
+      (error "UIOBJ-POINT-WITHIN?: Bad point" point)))
+
+(define (UIObj-rectangle-overlaps? UIObj P1 W1 H1)
+  (if (not (vector? P1))
+      (error "UIOBJ-RECTANGLE-OVERLAPS?: Bad point" P1))
+  (if (not (number? W1))
+      (error "UIOBJ-RECTANGLE-OVERLAPS?: Bad width" W1))
+  (if (not (number? H1))
+      (error "UIOBJ-RECTANGLE-OVERLAPS?: Bad height" H1))
+  (let ((screen-area (Used-Screen-Area UIObj)))
+    (and
+     screen-area
+     (let ((P2 (UITKRectangle.Offset screen-area))
+          (H2 (UITKRectangle.Height screen-area))
+          (W2 (UITKRectangle.Width screen-area)))
+       (rectangle-overlaps-rectangle? p1 w1 h1 p2 w2 h2)))))
+
+
+(define (event-within? UIObj Event)
+  (cond ((point-event? event)
+        (point-event-within? UIObj event))
+       ((rectangle-event? event)
+        (rectangle-event-within? UIObj event))
+       (else (error "EVENT-WITHIN?: Bad event" event))))
+
+(define (point-event-within? UIObj Event)
+  (let ((window (Get-UITKWindow UIObj)))
+    (and window
+        (= (->XWindow (UITKWindow.xwindow window))
+           (Event.Window Event))
+        (point-within? UIObj (event.Offset event)))))
+
+(define (rectangle-event-within? UIObj Event)
+  (let ((window (Get-UITKWindow UIObj)))
+    (and window
+        (= (->XWindow (UITKWindow.xwindow window))
+           (Event.Window Event))
+        (Rectangle-Overlaps? UIObj
+                             (event.Offset event)
+                             (event.Width event)
+                             (event.Height event)))))
+\f
+(define (UIObj-handle-event UIObj Event)
+  (if (event? event)
+      (if (event-within? UIObj event)
+         (event! UIObj event))
+      (error "UIOBJ-HANDLE-EVENT: Bad event" event)))
+
+(define (UIObj-get-desired-size object)
+  (define (->size datum)
+    (or datum (make-size 0 0)))
+  (->size (%desired-size object)))
+
+
+;;; Default assigned-screen-area and used-screen-area (accessors and
+;;; mutators) simply look in or modify the appropriate slots in the
+;;; structure.  
+(define (UIObj-assigned-screen-area UIObj)
+  (UIObjInternals.assigned-screen-area (UIObjInternals UIObj)))
+
+(define (UIObj-set-assigned-screen-area! UIObj Screen-area)
+  (set-UIObjInternals.assigned-screen-area! (UIObjInternals UIObj)
+                                           Screen-Area))
+
+(define (UIObj-used-screen-area UIObj)
+  (UIObjInternals.used-screen-area (UIObjInternals UIObj)))
+
+(define (UIObj-set-used-screen-area! UIObj Screen-Area)
+  (set-UIObjInternals.used-screen-area! (UIObjInternals UIObj)
+                                       Screen-Area))
+
+(define (UIObj-protect-from-gc! UIObj stuff)
+  (let ((crud (crud-that-I-dont-want-to-gc-away UIObj)))
+    (set-car! crud (cons stuff (car crud))))
+  'done)
+
+(define (UIObj-unprotect-from-gc! UIObj stuff)
+  (let ((crud (crud-that-I-dont-want-to-gc-away UIObj)))  
+    (set-car! crud (delq! stuff (car crud))))
+  'done)
+
+
+\f
+;;;; Context procedures
+
+(define (create-default-context name display)
+  ;; Looks in appropriate customization locations to create a default
+  ;; context for the application specified by NAME
+  (define (convert converter predicate)
+    (lambda (default)
+      (define (get-default)
+       (cond ((procedure? default) (default))
+             ((string? default) (converter default))
+             (else default)))
+      (lambda (string)
+       (if (and (string? string) (not (zero? (string-length string))))
+           (let ((result (converter string)))
+             (if (predicate result)
+                 result
+                 (get-default)))
+           (get-default)))))
+  ;;;**** this doesn't make sense to me.  What are the predicates testing, really?
+  ;;; changed XLoadFont to return a wrapped object,so string->font will also
+
+  (let ((->symbol (convert string->symbol symbol?))
+       (->number (convert string->number number?))
+       (->color  (convert (string->color display) color?))
+       ;; (->font   (convert (string->font display) font?))
+       ;; (->cursor (convert string->cursor cursor?))
+       )
+    (apply make-context
+          (map (lambda (entry)
+                 (let ((converter (car entry))
+                       (string (cadr entry)))
+                   ;;;;********beware: getdefaultvalue is returning an unwrapped object!!
+                   ;;;; fix this to add the wrappers
+                   (converter (GetDefaultValue display name string))))
+               `((,(->color "White") "ActiveBackground")
+                 (,(->color "Black") "ActiveForeground")
+                 (,(->symbol 'nw) "Anchor")
+                 (,(->color "Black") "Background")
+                 (,(->color "White") "Border")
+                 (,(->number 0) "BorderWidth")
+                 ;; (,(->cursor "Block") "Cursor")
+                 ;; (,(->font #F) "Font")
+                 (,(->color "White") "Foreground")
+                 (,(->symbol 'raised) "Relief"))))))
diff --git a/v7/src/swat/scheme/widget-mit.scm b/v7/src/swat/scheme/widget-mit.scm
new file mode 100644 (file)
index 0000000..a6f29c2
--- /dev/null
@@ -0,0 +1,178 @@
+; -*- Scheme -*-
+;;;;; Tk interface code for a button
+;;; $Id: widget-mit.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
+
+;;; Lowest-level makers for various kinds of TK widgets.  These call C
+;;; primitives in widget-c-mit.c, and are called by the higher-level
+;;; widget object makers in widget.scm
+
+
+(define-primitives
+  (%tkDeleteDisplay 1)
+  (%tkDestroyWidget 1)  
+  (%tkMakeButton 2)
+  (%tkMakeCanvas 2)
+  (%tkMakeCheckbutton 2)
+  (%tkMakeEntry 2)
+  (%tkMakeLabel 2)
+  (%tkMakeListbox 2)
+  (%tkMakeMenu 2)
+  (%tkMakeMenubutton 2)
+  (%tkMakeMessage 2)
+  (%tkMakeRadiobutton 2)
+  (%tkMakeScale 2)
+  (%tkMakeScrollBar 2)
+  (%tkMakeText 2)
+  )
+
+#| Widgets hold strong pointers to the display and the application.
+Therefore, when we GC away the display or applcation, we can assume
+that there are no pointers to the widgets still around.  However, the
+C end may need to be closed |#
+
+;;; display->tk-widgets is a map that associates to each display a
+;;; protection list of the tk-widgets for the display
+(define display->tk-widgets 'INITIALIZED-LATER)
+
+(define (add-widget-list-for-display-number! display-number)
+  (set! display->tk-widgets
+       (cons (cons display-number (make-protection-list))
+             display->tk-widgets)))
+
+(define (find-tk-protection-list display)
+  (find-tk-protection-list-from-number (->xdisplay display)))
+
+(define (find-tk-protection-list-from-number number)
+  (let ((list (assv number display->tk-widgets)))
+    (if (null? list)
+       #F
+       (cdr list))))
+
+;;; The item on the protection list is a cell containing the widget
+;;; pointer.  This permits us to mark the cell when the C object is
+;;; destroyed so we don't try to destroy it twice.
+
+(define (Wrap-TK-widget surface name maker)
+  (let ((ToolKitParent (DrawingSurface.ToolKitWindow surface)))
+    ;; Note that the DrawingSurface's UITKWindow may not yet exist.
+    (let ((parent-tk-window (ToolKitWindow.TK-window ToolKitParent))
+         (application (ToolKitWindow.Application ToolKitParent)))
+      (let ((display (Application->Display application)))
+       (let ((new-window-name
+              (string-append
+               (tkwin.pathname parent-tk-window) "." name)))
+         (let ((wrapped-object #F))
+           (define (kill-me)
+             ;; Called when the object is destroyed
+             (SCXL-DESTROY! wrapped-object))
+           (set! wrapped-object
+                 (SCXL-WRAP
+                  (or (find-tk-protection-list display)
+                      (error "No tk-protection-list for this display" display))
+                  'tk-widget
+                  (tk-op
+                   (lambda ()
+                     (maker parent-tk-window new-window-name)))
+                  (list display surface kill-me) ;strong dependents
+                  ))
+           (tk-invoke-command
+            'BIND (Application->TKMainWindow application)
+            (list new-window-name "<Destroy>"
+                  (string-append "SchemeCallBack "
+                                 (number->string
+                                  (hash kill-me *our-hash-table*)))))
+           wrapped-object))))))
+
+(define (widget/widget widget)
+  (type-check-wrapped-object 'tk-widget widget)
+  (SCXL-UNWRAP widget (lambda (w) w)))
+
+(define ->widget widget/widget)
+
+(define (%tk-really-destroy-widget handle)
+  ;; Given a lowest-level TK handle or #F
+  (if handle (tk-op (lambda() (%TkDestroyWidget handle))))
+  'destroyed)
+
+(define tk-widget-destroy
+  ;; This will actually close the TK widget only if the wrapper isn't
+  ;; already marked destroyed.  But that should be OK -- we shouldn't
+  ;; be able to find a wrapper that's destroyed if the contents
+  ;; haven't been closed.
+  (wrap-with-SCXL-DESTROY! 1 0
+   (lambda (scxl-wrapped-widget)
+     (tk-op (lambda ()
+             (%tkDestroyWidget (->widget scxl-wrapped-widget)))))))
+
+(define (tk-delete-display disp)
+  (tk-op (lambda () (%tkDeleteDisplay (->Xdisplay disp)))))
+
+(define (tk-make-button drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeButton parent-tk-window real-name))))
+
+(define (tk-make-canvas drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeCanvas parent-tk-window real-name))))
+
+(define (tk-make-checkbutton drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeCheckButton parent-tk-window real-name))))
+
+(define (tk-make-entry drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeEntry parent-tk-window real-name))))
+
+(define (tk-make-label drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeLabel parent-tk-window real-name))))
+
+(define (tk-make-listbox drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeListbox parent-tk-window real-name))))
+
+(define (tk-make-menu drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeMenu parent-tk-window real-name))))
+
+(define (tk-make-menubutton drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeMenuButton parent-tk-window real-name))))
+
+(define (tk-make-message drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeMessage parent-tk-window real-name))))
+
+(define (tk-make-radiobutton drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeRadioButton parent-tk-window real-name))))
+
+(define (tk-make-scale drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeScale parent-tk-window real-name))))
+
+(define (tk-make-scrollbar drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeScrollBar parent-tk-window real-name))))
+
+(define (tk-make-text drawing-surface name)
+  (Wrap-TK-widget drawing-surface name
+                 (lambda (parent-tk-window real-name)
+                   (%tkMakeText parent-tk-window real-name))))
+
+(define (initialize-mit-widgets!)
+    (set! display->tk-widgets '()))
+
+(initialize-mit-widgets!)
diff --git a/v7/src/swat/scheme/widget.scm b/v7/src/swat/scheme/widget.scm
new file mode 100644 (file)
index 0000000..1837739
--- /dev/null
@@ -0,0 +1,726 @@
+;;;;; -*- Scheme -*-
+;;;;; $Id: widget.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
+;;;;; derived from button.sc,v 1.2 1993/02/26 00:49:36 jmiller Exp $
+
+;;;;;;;;;;  Widget Definitions
+
+(define tk-widget->pathname
+  (let ((->handle (lambda (widget)
+                   (if (not (tkwidget%? widget))
+                       (pp `(tkh 2 ,widget)))
+                   (TKWidget%.handle widget))))
+    (lambda (tk-widget)
+      (tkwin.pathname (tk-widget.tkwin (->handle tk-widget))))))
+
+(define (tkwin->size tkwindow)
+  (make-size (tkwin.width tkwindow) (tkwin.height tkwindow)))
+
+#| display->tk-widgets maps a display-number to a protection list,
+   which is a list of weak-pairs.  Each pair is <WRAPPED-OBJ or #F .
+   cell with (handle or #F)> #F on the left means that the Scheme
+   object has been lost.  #F on the right means that the TK widget has
+   been closed.  In UITK, both the wrapped object and the TK object
+   should be destroyed when the Scheme reference is lost.  However,
+   when we close a display the TK objects may still be around.  The
+   Scheme objects should not be around if we close the display from
+   GC, but (brave) users may wish to close displays explicitly.  |#
+
+(define (destroy-associated-tk-widgets display-number)
+  (let ((tk-widgets (find-tk-protection-list-from-number display-number)))
+    (if tk-widgets
+       (begin
+         ;;canonical Lisp bug #27: we need to do the set! here
+         (set! display->tk-widgets
+               (del-assv! display-number display->tk-widgets))
+         (for-each
+          (lambda (entry)
+            ;; An entry is either the left side of the pair described
+            ;; above, or the (former) contents of the cell on the
+            ;; right.
+            (if (SCXL-WRAPPED? entry)
+                (tk-widget-destroy entry)
+                (%tk-really-destroy-widget entry)))
+          (protection-list-all-elements tk-widgets
+                                        atomic-read-and-clear-cell!)))))
+  (%tkDeleteDisplay display-number)    ; Make TK forget the display exists
+  'done)
+
+(define (TKWidget-assign-drawing-surface! me Surface)
+  (let ((old (Drawing-Surface me))
+       (kids (TKWidget%.%children me)))
+    (cond
+     ;; Three kinds of Surface: 'RETRACTED, 'UNASSIGNED, or DrawingSurface?
+     ;; The default is 'UNASSIGNED and this is NOT a legal value to
+     ;; assign later!
+     ((and (eq? Surface 'UNASSIGNED)
+          (eq? old 'UNASSIGNED))
+      'nothing-to-do)
+     ((eq? Surface 'RETRACTED)
+      (set-drawing-surface! me 'RETRACTED)
+      (if (DrawingSurface? old)
+         (tk-widget-destroy (TKWidget%.handle me)))
+      (if (not (eq? old 'RETRACTED)) (death! me)))
+     ((not (DrawingSurface? Surface))
+      (error "TKWIDGET-ASSIGN-DRAWING-SURFACE!: Bad surface" Surface))
+     ;; All of the kids need to receive a drawing surface now.  It
+     ;; should be on the same application and XDisplay as me, but
+     ;; should use my own XWindow for the parent, and my TK Window as
+     ;; the TK Parent window.  Drawing surfaces are assigned TWICE:
+     ;; first with a valid ToolKitWindow, and then with both a
+     ;; ToolKitWindow and a UITKWindow (see baseobj.scm).  We mimic
+     ;; that here.
+     ((eq? old 'UNASSIGNED)
+      ;; Create the widget drawing surface is first assigned
+      (set-drawing-surface! me Surface)
+      (let ((wrapped-tk-widget ((TKWidget%.how-to-make-me me) Surface))
+           (application (DrawingSurface.Application Surface)))
+#|     
+       (define (kill-me)
+         (debug-print '<destroy> 'call 'back me)
+         (set-drawing-surface! me 'RETRACTED)
+         (death! me))
+       (UIObj-Protect-From-GC! me kill-me)
+       (tk-invoke-command
+        'BIND (Application->TKMainWindow application)
+        (list (tk-widget->pathname me) "<Destroy>"
+              (string-append "+SchemeCallBack "
+                             (number->string
+                              (hash kill-me *our-hash-table*)))))
+|#
+       (set-TKWidget%.handle! me wrapped-tk-widget)
+       (if (TKWidget%.do-not-gc-protect me)
+           (remove-from-protection-list!
+            (find-tk-protection-list-from-number
+             (->xdisplay
+              (Application->Display Application)))
+            wrapped-tk-widget)))
+      (let ((kid-surface (make-DrawingSurface
+                         (make-ToolKitWindow
+                          (DrawingSurface.Application Surface)
+                          #F
+                          (tk-widget.tkwin (TKWidget%.handle me)))
+                         #F)))
+       (for-each (lambda (kid) (ASSIGN-DRAWING-SURFACE! kid kid-surface))
+                 kids))
+      (for-each (lambda (thunk) (thunk))
+               (reverse
+                (TKWidget%.deferred-ask-widget-commands me)))
+      (set-TKWidget%.deferred-ask-widget-commands! me '())
+      (geometry-change! me #F #F))
+     ((eq? old Surface)
+      ;; 2nd pass now modifies that drawing surface to reflect a
+      ;; possibly updated UITK window
+      (if (not (null? kids))
+         (let ((new (drawing-surface (car kids))))
+           (set-DrawingSurface.UITKWindow!
+            new
+            (make-UITKWindow
+             (UITKWindow.XDisplay (DrawingSurface.UITKWindow Surface))
+             (tkwin.window (tk-widget.tkwin (TKWidget%.handle me)))))
+           (for-each (lambda (kid) (ASSIGN-DRAWING-SURFACE! kid new))
+                     kids)))
+      (geometry-change! me #F #F))
+     (else
+      (error "TKWIDGET-ASSIGN-DRAWING-SURFACE!: Can't change surface"
+            old Surface))))
+  'OK)
+
+(define (TKWidget-add-child! me kid)
+  (one-parent-only! kid me)
+  (let ((current-kids (TKWidget%.%children me)))
+    (if (not (null? current-kids))
+       (assign-drawing-surface! kid (drawing-surface (car current-kids)))
+       (let ((Surface (drawing-surface me)))
+         (if (not (DrawingSurface? Surface))
+             (assign-drawing-surface! kid Surface)
+             (let* ((parent-tkwin (tk-widget.tkwin (TKWidget%.handle me)))
+                    (kid-surface
+                     (make-DrawingSurface
+                      (make-ToolKitWindow
+                       (DrawingSurface.Application Surface)
+                       #F              ; Top-level geometry callback
+                       parent-tkwin)
+                      (make-UITKWindow
+                       (UITKWindow.XDisplay (DrawingSurface.UITKWindow Surface))
+                       (tkwin.window parent-tkwin)))))
+               (assign-drawing-surface! kid kid-surface)))))
+    (set-TKWidget%.%children! me (cons kid current-kids))))
+  
+(define (TKWidget-assign-screen-area! me screen-area)
+  (cond ((vector? screen-area)
+        (if (TKWidget%.do-screen-area? me)
+            (let ((tk-handle (TKWidget%.handle me)))
+              (if (not (assigned-screen-area me))
+                  (begin
+                    (tk-map-window (tk-widget.tkwin tk-handle))
+                    (tk-manage-geometry tk-handle
+                                        (TKWidget%.%scheme-geometry-manager me))))
+              (tk-move-resize-widget tk-handle screen-area)))
+        (geometry-change! me screen-area screen-area)
+        screen-area)
+       ((not Screen-Area)
+        (if (TKWidget%.do-screen-area? me)
+            (let ((tk-handle (TKWidget%.handle me)))
+              (TK-Unmap-Window (tk-widget.tkwin tk-handle))
+              (tk-manage-geometry tk-handle #F)))
+        (geometry-change! me screen-area screen-area)
+        screen-area)
+       (else
+        (error "TKWIDGET-ASSIGN-SCREEN-AREA!: Bad screen-area" screen-area))))
+
+(define (widget->screen-area widget)
+  (let ((tkwin (tk-widget.tkwin (TKWidget%.handle widget))))
+    (and (tkwin.ismapped? tkwin)
+        (make-UITKRectangle
+         (make-point (tkwin.x tkwin) (tkwin.y tkwin))
+         (make-size (tkwin.width tkwin)
+                    (tkwin.height tkwin))))))
+
+(define (TKWidget-assigned-screen-area me)
+  (widget->screen-area me))
+(define (TKWidget-used-screen-area me)
+  (widget->screen-area me))
+
+(define (TKWidget-set-assigned-screen-area! me anything)
+  (if (and (eq? (drawing-surface me) 'RETRACTED)
+          (eq? anything #F))
+      'OK
+      (error "You can't set the screen area for a TK Widget" me anything)))
+(define (TkWidget-set-used-screen-area! me anything)
+  (if (and (eq? (drawing-surface me) 'RETRACTED)
+          (eq? anything #F))
+      'OK
+      (error "You can't set the screen area for a TK Widget" me anything)))
+
+(define (TKWidget-get-desired-size object)
+  (widget->size object tkwin->requested-size))
+
+(define (TKWidget-assign-glue! me)
+  (let* ((size (get-desired-size me))
+        (my-width (size.Width size))
+        (my-height (size.Height size)))
+    ((TKWidget%.set-glue!-procedure me) me my-width my-height)))
+
+(define (maybe-defer me command)
+  (if (not (tkwidget%? me))
+      (pp `(tkh 3 ,me)))
+  (if (TKWidget%.handle me)
+      (command)
+      (defer me command)))
+
+(define (defer me command)
+  (set-TKWidget%.deferred-ask-widget-commands!
+   me
+   (cons command (TKWidget%.deferred-ask-widget-commands me)))
+  #F)
+  
+(define (TKWidget-add-event-handler! object event handler substitutions)
+  ;;for example
+  ;; (add-event-handler! obj "<ButtonPress>"
+  ;;     (lambda (path button) ....)
+  ;;     "%W" "%b")
+  ;; see TK manual (bind) for what these %frobs mean
+  ;;hang this on the widget to GC protect it
+  (let ((handler (proc-with-transformed-args handler substitutions)))
+    (set-TKWidget%.%binding-callbacks!
+     object
+     (cons handler (TKWidget%.%binding-callbacks object)))
+    (let ((command
+          (lambda ()
+            (tk-invoke-command
+             'bind
+             (application->TKMainWindow
+              (DrawingSurface.Application
+               (Drawing-Surface object)))
+             (list
+              (tk-widget->pathname object)
+              event
+              ;; "event" should be a string because TCL is
+              ;; case sensitive, (e.g. <ButtonPress>)
+              (apply
+               string-append
+               "SchemeCallBack "
+               (number->string (hash handler *our-hash-table*))
+               (map (lambda (s)
+                      (string-append " " s))
+                    substitutions)))))))
+      (maybe-defer object command))))
+
+(define (TKWidget-ask-widget me arg-list)
+  ;; If the widget doesn't have a drawing surface yet, then the TK
+  ;; object hasn't been created and we can't actually execute the
+  ;; command.
+  (let ((command
+        (lambda ()
+          (if (not (tkwidget%? me))
+              (pp `(tkh 1 ,me)))
+          (if (SCXL-DESTROYED? (tkwidget%.handle me))
+              'punt
+              (tcl-global-eval
+               (ToolKitWindow.Application
+                (DrawingSurface.ToolKitWindow (drawing-surface me)))
+               (tk-widget->pathname me)
+               arg-list)))))
+    (maybe-defer me command)))
+
+
+(define (current-size widget)
+  (widget->size widget tkwin->size))
+
+(define (widget->size widget ->size)
+  (let ((h (TKWidget%.handle widget)))
+    (if h
+       (->size (tk-widget.tkwin h))
+       (error "widget->size: widget not instantiated" widget))))
+
+(define (tk-has-requested-new-size object)
+  (let ((old-size (current-size object))
+       (new-size (get-desired-size object)))
+    (if (and (= (size.height old-size) (size.height new-size))
+            (= (size.width old-size) (size.width new-size)))
+       'OK
+       (geometry-change! object (used-screen-area object) #T))))
+
+;; method to attach callback to the widget
+(define (TKWidget-set-callback! me proc)
+  (set-TKWidget%.%callback! me proc)
+  (if (TKWidget%.%callback-command me)
+      ((TKWidget%.%callback-command me) me (TKWidget%.%scheme-callback-hash me))
+      (error "SET-CALLBACK!: not allowed" me proc)))
+
+;; TKWidget Maker
+(define (TKWidget-maker)
+  (make-tkwidget%
+   (make-UIObjInternals TKWidget-add-child!
+                       'invalid        ; Remove-Child!-procedure
+                       UIObj-set-context!
+                       TKWidget-assign-screen-area!
+                       TKWidget-assign-drawing-surface!
+                       UIObj-point-within?
+                       UIObj-rectangle-overlaps?
+                       UIObj-handle-event
+                       TKWidget-get-desired-size
+                       TKWidget-assigned-screen-area
+                       TKWidget-used-screen-area
+                       TKWidget-set-assigned-screen-area!
+                       TKWidget-set-used-screen-area!
+                       TKWidget-assign-glue!)
+   TKWidget-ask-widget
+   TKWidget-add-event-handler!
+   TKWidget-set-callback!))
+
+(define (tkwin->requested-size tkwindow)
+  (make-size (tkwin.req-width tkwindow)
+            (tkwin.req-height tkwindow)))
+
+(define (make-TK-widget type widget-maker callback-command do-screen-area? set-glue!)
+  ;; The Main widget-maker
+  (lambda args
+    (let ((me (TKWidget-maker)))
+      (let ((geometry-callback
+            (lambda () (tk-has-requested-new-size me)))
+           (the-real-callback
+            (lambda args
+              (apply (TKWidget%.%callback me) args))))
+       (let ((%scheme-callback-hash
+              (hash the-real-callback *our-hash-table*)))
+         (set-TKWidget%.%c-callback! me the-real-callback)
+         (set-TKWidget%.%scheme-geometry-manager! me geometry-callback)
+         (set-TKWidget%.%scheme-callback-hash! me %scheme-callback-hash)
+         (set-TKWidget%.%callback-command! me callback-command)
+         (set-TKWidget%.how-to-make-me!
+          me
+          (lambda (parent-drawing-surface)
+            (apply widget-maker parent-drawing-surface (tk-gen-name type) args)))
+         (set-TKWidget%.do-screen-area?! me do-screen-area?)
+         (set-TKWidget%.set-glue!-procedure! me set-glue!)
+         me))))
+  )
+
+(define (make-arg-transformers argspecs)
+  (let ((id (lambda (x) x)))
+    (map (lambda (spec)
+          (if (member spec
+                      '("%b" "%c" "%h" "%k" "%t" "%w" "%x" "%y" "%X" "%Y"))
+              string->number
+              id))
+        argspecs)))
+
+(define (proc-with-transformed-args proc argspecs)
+  (let ((transformers
+        (make-arg-transformers argspecs)))
+    (lambda args
+      (apply proc (map (lambda (t a) (t a))
+                      transformers args)))))
+
+\f
+
+(define button-stretch 2)
+(define canvas-stretch 20)
+(define entry-height-stretch 1)
+
+(define make-button
+  (let ((maker (make-tk-widget
+               "button" tk-make-button
+               (lambda (button scheme-callback-hash-number)
+                 (ask-widget
+                  button
+                  `(configure -command
+                              ,(string-append
+                                "SchemeCallBack "
+                                (number->string
+                                 scheme-callback-hash-number)))))
+               #T
+               (lambda (button button-width button-height)
+                 (set-%hglue! button (make-fill-glue button-width button-stretch))
+                 (set-%vglue! button (make-fill-glue button-height button-stretch))
+                 ))))
+    (lambda options            ;but don't use -callback!
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+      (let ((button (maker)))
+       (ask-widget button `(configure ,@configure-options))
+       button)))))
+
+(define remember-on-canvas!
+  (let ((fix! (lambda (widget value)
+               (set-TKWidget%.%binding-callbacks! widget value)))
+       (fetch (lambda (widget) (TKWidget%.%binding-callbacks widget))))
+    (lambda (canvas thing-to-remember)
+      (fix! canvas (cons thing-to-remember (fetch canvas))))))
+
+(define make-canvas
+  (let ((maker (make-tk-widget
+               "canvas" tk-make-canvas #F #T
+               (lambda (canvas canvas-width canvas-height)
+                 (set-%hglue! canvas (make-fill-glue canvas-width canvas-stretch))
+                 (set-%vglue! canvas (make-fill-glue canvas-height canvas-stretch))))))
+    (lambda options            
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((canvas (maker)))
+         (ask-widget canvas `(configure ,@configure-options))
+         canvas)))))
+    
+(define make-checkbutton
+  (let ((maker (make-tk-widget
+               "checkbutton" tk-make-checkbutton
+               (lambda (checkbutton scheme-callback-hash-number)
+                 (ask-widget
+                  checkbutton
+                  `(configure -command
+                              ,(string-append
+                                "SchemeCallBack "
+                                (number->string
+                                 scheme-callback-hash-number)))))
+               #T
+               (lambda (checkbutton cb-width cb-height)
+                 (set-%hglue! checkbutton (make-fill-glue cb-width button-stretch))
+                 (set-%vglue! checkbutton (make-fill-glue cb-height button-stretch))))))
+    (lambda options            
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((checkbutton (maker)))
+         (ask-widget checkbutton `(configure ,@configure-options))
+         checkbutton)))))
+
+(define make-entry
+  (let ((maker
+        (make-tk-widget
+         "entry"
+         tk-make-entry
+         (lambda (entry scheme-callback-hash-number)
+           (ask-widget
+            entry
+            `(configure -Scrollcommand
+                        ,(string-append "SchemeCallBack "
+                                        (number->string
+                                         scheme-callback-hash-number)))))
+         #T
+         (lambda (entry entry-width entry-height)
+           (set-%hglue! entry (make-fill-glue entry-width button-stretch))
+           (set-%vglue! entry (make-fill-glue entry-height entry-height-stretch))))))
+    (lambda options            
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((entry (maker)))
+         (ask-widget entry `(configure ,@configure-options))
+         entry)))))
+
+(define make-label
+  (let ((maker (make-tk-widget
+               "label" tk-make-label 
+               #F                      ; No callbacks allowed
+               #T                      ; Normal screen-area handling
+               (lambda (label label-width label-height)
+                 (set-%hglue! label (make-fill-glue label-width button-stretch))
+                 (set-%vglue! label (make-fill-glue label-height button-stretch))))))
+    (lambda options            
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((label (maker)))
+         (ask-widget label `(configure ,@configure-options))
+         label)))))
+
+(define make-listbox
+  (let ((maker (make-tk-widget
+               "listbox" tk-make-listbox
+               #F                      ; No callbacks allowed
+               #T                      ; Normal screen-area handling
+               (lambda (listbox listbox-width listbox-height)
+                 (set-%hglue! listbox (make-fill-glue listbox-width button-stretch))
+                 (set-%vglue! listbox (make-fill-glue listbox-height button-stretch))))))
+    (lambda options            
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((listbox (maker)))
+         (ask-widget listbox `(configure ,@configure-options))
+         listbox)))))
+
+(define make-menu
+  (let ((maker (make-tk-widget
+               "menu" tk-make-menu
+               #F                      ; No callbacks allowed
+               #F                      ; No screen area assignment code
+               (lambda (menu menu-width menu-height)
+                 (set-%hglue! menu (make-fill-glue menu-width button-stretch))
+                 (set-%vglue! text (make-fill-glue menu-height button-stretch))))))
+    (lambda options
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let* ((menu (maker))
+              (mr (make-menurecord menu '())))
+         (set! *all-menus* (weak-cons mr *all-menus*))
+         (uiobj-protect-from-gc! menu mr)
+         (ask-widget menu `(configure ,@configure-options))
+         menu)))))
+
+(define make-menubutton
+  (let ((maker (make-tk-widget
+               "menubutton"
+               tk-make-menubutton
+               #F                      ; No callbacks allowed
+               #T                      ; Normal screen-area handling
+               (lambda (menubutton mb-width mb-height)
+                 (set-%hglue! menubutton (make-fill-glue mb-width button-stretch))
+                 (set-%vglue! menubutton (make-fill-glue mb-height button-stretch))))))
+    (lambda (menu . options)           ; options can't include -menu
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((menubutton (maker)))
+         (add-child! menubutton menu)
+         (ask-widget menubutton `(configure ,@configure-options))
+         (ask-widget menubutton
+                     `(configure -menu
+                                 ,(lambda () (tk-widget->pathname menu))))
+         menubutton)))))
+
+(define make-message
+  (let ((maker (make-tk-widget
+               "message" tk-make-message
+               #F                      ; No callbacks allowed
+               #T                      ; Normal screen-area handling
+               (lambda (message message-width message-height)
+                 (set-%hglue! message (make-fill-glue message-width button-stretch))
+                 (set-%vglue! message (make-fill-glue message-height button-stretch))))))
+    (lambda options            
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((message (maker)))
+         (ask-widget message `(configure ,@configure-options))
+         message)))))
+
+(define make-radiobutton
+  (let ((maker (make-tk-widget
+               "radiobutton" tk-make-radiobutton
+               (lambda (radiobutton scheme-callback-hash-number)
+                 (ask-widget
+                  radiobutton
+                  `(configure -command
+                              ,(string-append
+                                "SchemeCallBack "
+                                (number->string
+                                 scheme-callback-hash-number)))))
+               #T
+               (lambda (radiobutton rb-width rb-height)
+                 (set-%hglue! radiobutton (make-fill-glue rb-width button-stretch))
+                 (set-%vglue! radiobutton (make-fill-glue rb-height button-stretch))))))
+    (lambda options            
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((radiobutton (maker)))
+         (ask-widget radiobutton `(configure ,@configure-options))
+         radiobutton)))))
+
+(define (after-last-space string)
+  (let ((index (string-find-previous-char string #\Space)))
+    (if index
+       (substring string (+ index 1) (string-length string))
+       (error "String does not contain a space" string))))
+
+(define (get-tk-widget-orientation tk-widget)
+  ;; returns 'v or 'h.
+  (string->symbol
+   (string-downcase
+    (substring
+     (after-last-space
+      (ask-widget tk-widget '(configure -orient)))
+     0
+     1))))
+
+(define make-scale
+  (let ((maker
+        (make-tk-widget
+         "scale"
+         tk-make-scale
+         (lambda (scale scheme-callback-hash-number)
+           (ask-widget scale
+                       `(configure -command
+                                   ,(string-append
+                                     "SchemeCallBack "
+                                     (number->string
+                                      scheme-callback-hash-number)))))
+         #T
+         (lambda (scale scale-width scale-height)
+           (let ((orientation (get-tk-widget-orientation scale)))
+             (cond ((eq? orientation 'v)
+                    (set-%hglue! scale (make-rigid-glue scale-width 1))
+                    (set-%vglue! scale (make-fill-glue scale-height button-stretch)))
+                   ((eq? orientation 'h)
+                    (set-%hglue! scale (make-fill-glue scale-width button-stretch))
+                    (set-%vglue! scale (make-rigid-glue scale-height 1)))
+                   (else (error "Bad orientation: Must be 'h or 'v" orientation))))))))
+    (lambda options
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((scale (maker)))
+         (ask-widget scale `(configure ,@configure-options))
+         scale)))))
+
+(define make-scrollbar
+  (let ((maker
+        (make-tk-widget
+         "scrollbar"
+         tk-make-scrollbar
+         (lambda (scrollbar scheme-callback-hash-number)
+           (ask-widget
+            scrollbar
+            `(configure -command
+                        ,(string-append "SchemeCallBack "
+                                        (number->string
+                                         scheme-callback-hash-number)))))
+         #T
+         (lambda (scrollbar scrollbar-width scrollbar-height)
+           (let ((orientation (get-tk-widget-orientation scrollbar)))
+             (cond ((eq? orientation 'v)
+                    (set-%hglue! scrollbar (make-rigid-glue scrollbar-width 1))
+                    (set-%vglue! scrollbar (make-fil-glue scrollbar-height 1)))
+                   ((eq? orientation 'h)
+                    (set-%hglue! scrollbar (make-fil-glue scrollbar-width 1))
+                    (set-%vglue! scrollbar (make-rigid-glue scrollbar-height 1)))
+                   (else (error "Bad orientation: must be 'h or 'v" orientation))))))))
+    (lambda options
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((scrollbar (maker)))
+         (ask-widget scrollbar `(configure ,@configure-options))
+         scrollbar)))))
+
+(define make-text
+  (let ((maker (make-tk-widget
+               "text"
+               tk-make-text
+               #F      ; No callbacks allowed
+               #T      ; Normal screen-area handling
+               (lambda (text text-width text-height)
+                 (set-%hglue! text (make-fill-glue text-width canvas-stretch))
+                 (set-%vglue! text (make-fill-glue text-height canvas-stretch))))))
+    (lambda options            
+      (let ((configure-options
+            (if (null? options)
+                '()
+                (car options))))
+       (let ((text (maker)))
+         (ask-widget text `(configure ,@configure-options))
+         text)))))
+\f
+;;; TK has "active variables"
+
+;;; Ask-widget should be changed so that TK-variables get replaced by
+;;; their names [WHAT DOES THIS MEAN?? -- Hal]
+
+(define (make-active-variable . application)
+  (let ((application (if (null? application)
+                        *the-default-application*
+                        (car application))))
+    (let* ((tk-name (tk-gen-name "variable"))
+          (variable (make-TK-variable application tk-name #F)))
+      (UIObj-protect-from-gc! application variable)
+      variable)))
+
+(define (active-variable-value var)
+  (tcl-global-eval
+   (TK-variable.application var)
+   "expr"
+   (list (string-append "$" (TK-variable.tk-name var)))))
+
+(define (set-active-variable! var value)
+  (tcl-global-eval
+   (TK-variable.application var)
+   "set"
+   (list (TK-variable.tk-name var) value)))
+
+(define (set-active-variable-callback! var thunk)
+  (let ((app (TK-variable.application var))
+       (name (TK-variable.tk-name var))
+       (cb (TK-variable.callback var)))
+    (if cb
+       (tcl-global-eval
+        app "trace"
+        (list "vdelete" name "w" `("SchemeCallBack"
+                                   ,(object-hash cb *our-hash-table*)))))
+    (let ((the-callback
+          (lambda (arg1 arg2 arg3)     ;tcl generates these
+            arg1 arg2 arg3             ;but we'll ignore them
+            (thunk)))) 
+      (tcl-global-eval
+       app "trace"
+       (list "variable" name "w"
+            `("SchemeCallBack"
+              ,(object-hash the-callback *our-hash-table*))
+            ))
+      (set-TK-variable.callback! var the-callback))))
+
+(define (checkbutton-variable-on? var)
+  (equal? (active-variable-value var) "1"))
+
+\f
+(define (initialize-widgets!)
+  (SCXL-Install-XCloseDisplay-Callback
+   destroy-associated-tk-widgets))
+
+(initialize-widgets!)
diff --git a/v7/src/swat/scheme/xlibCONSTANTS.scm b/v7/src/swat/scheme/xlibCONSTANTS.scm
new file mode 100644 (file)
index 0000000..8493dc0
--- /dev/null
@@ -0,0 +1,889 @@
+(define-constant X_PROTOCOL 11)
+(define-constant X_PROTOCOL_REVISION 0)
+(define-constant NONE 0)
+(define-constant PARENTRELATIVE 1)
+(define-constant COPYFROMPARENT 0)
+(define-constant POINTERWINDOW 0)
+(define-constant INPUTFOCUS 1)
+(define-constant POINTERROOT 1)
+(define-constant ANYPROPERTYTYPE 0)
+(define-constant ANYKEY 0)
+(define-constant ANYBUTTON 0)
+(define-constant ALLTEMPORARY 0)
+(define-constant CURRENTTIME 0)
+(define-constant NOSYMBOL 0)
+(define-constant NOEVENTMASK 0)
+(define-constant KEYPRESSMASK 1)
+(define-constant KEYRELEASEMASK 2)
+(define-constant BUTTONPRESSMASK 4)
+(define-constant BUTTONRELEASEMASK 8)
+(define-constant ENTERWINDOWMASK 16)
+(define-constant LEAVEWINDOWMASK 32)
+(define-constant POINTERMOTIONMASK 64)
+(define-constant POINTERMOTIONHINTMASK 128)
+(define-constant BUTTON1MOTIONMASK 256)
+(define-constant BUTTON2MOTIONMASK 512)
+(define-constant BUTTON3MOTIONMASK 1024)
+(define-constant BUTTON4MOTIONMASK 2048)
+(define-constant BUTTON5MOTIONMASK 4096)
+(define-constant BUTTONMOTIONMASK 8192)
+(define-constant KEYMAPSTATEMASK 16384)
+(define-constant EXPOSUREMASK 32768)
+(define-constant VISIBILITYCHANGEMASK 65536)
+(define-constant STRUCTURENOTIFYMASK 131072)
+(define-constant RESIZEREDIRECTMASK 262144)
+(define-constant SUBSTRUCTURENOTIFYMASK 524288)
+(define-constant SUBSTRUCTUREREDIRECTMASK 1048576)
+(define-constant FOCUSCHANGEMASK 2097152)
+(define-constant PROPERTYCHANGEMASK 4194304)
+(define-constant COLORMAPCHANGEMASK 8388608)
+(define-constant OWNERGRABBUTTONMASK 16777216)
+(define-constant KEYPRESS 2)
+(define-constant KEYRELEASE 3)
+(define-constant BUTTONPRESS 4)
+(define-constant BUTTONRELEASE 5)
+(define-constant MOTIONNOTIFY 6)
+(define-constant ENTERNOTIFY 7)
+(define-constant LEAVENOTIFY 8)
+(define-constant FOCUSIN 9)
+(define-constant FOCUSOUT 10)
+(define-constant KEYMAPNOTIFY 11)
+(define-constant EXPOSE 12)
+(define-constant GRAPHICSEXPOSE 13)
+(define-constant NOEXPOSE 14)
+(define-constant VISIBILITYNOTIFY 15)
+(define-constant CREATENOTIFY 16)
+(define-constant DESTROYNOTIFY 17)
+(define-constant UNMAPNOTIFY 18)
+(define-constant MAPNOTIFY 19)
+(define-constant MAPREQUEST 20)
+(define-constant REPARENTNOTIFY 21)
+(define-constant CONFIGURENOTIFY 22)
+(define-constant CONFIGUREREQUEST 23)
+(define-constant GRAVITYNOTIFY 24)
+(define-constant RESIZEREQUEST 25)
+(define-constant CIRCULATENOTIFY 26)
+(define-constant CIRCULATEREQUEST 27)
+(define-constant PROPERTYNOTIFY 28)
+(define-constant SELECTIONCLEAR 29)
+(define-constant SELECTIONREQUEST 30)
+(define-constant SELECTIONNOTIFY 31)
+(define-constant COLORMAPNOTIFY 32)
+(define-constant CLIENTMESSAGE 33)
+(define-constant MAPPINGNOTIFY 34)
+(define-constant LASTEVENT 35)
+(define-constant SHIFTMASK 1)
+(define-constant LOCKMASK 2)
+(define-constant CONTROLMASK 4)
+(define-constant MOD1MASK 8)
+(define-constant MOD2MASK 16)
+(define-constant MOD3MASK 32)
+(define-constant MOD4MASK 64)
+(define-constant MOD5MASK 128)
+(define-constant SHIFTMAPINDEX 0)
+(define-constant LOCKMAPINDEX 1)
+(define-constant CONTROLMAPINDEX 2)
+(define-constant MOD1MAPINDEX 3)
+(define-constant MOD2MAPINDEX 4)
+(define-constant MOD3MAPINDEX 5)
+(define-constant MOD4MAPINDEX 6)
+(define-constant MOD5MAPINDEX 7)
+(define-constant BUTTON1MASK 256)
+(define-constant BUTTON2MASK 512)
+(define-constant BUTTON3MASK 1024)
+(define-constant BUTTON4MASK 2048)
+(define-constant BUTTON5MASK 4096)
+(define-constant ANYMODIFIER 32768)
+(define-constant BUTTON1 1)
+(define-constant BUTTON2 2)
+(define-constant BUTTON3 3)
+(define-constant BUTTON4 4)
+(define-constant BUTTON5 5)
+(define-constant NOTIFYNORMAL 0)
+(define-constant NOTIFYGRAB 1)
+(define-constant NOTIFYUNGRAB 2)
+(define-constant NOTIFYWHILEGRABBED 3)
+(define-constant NOTIFYHINT 1)
+(define-constant NOTIFYANCESTOR 0)
+(define-constant NOTIFYVIRTUAL 1)
+(define-constant NOTIFYINFERIOR 2)
+(define-constant NOTIFYNONLINEAR 3)
+(define-constant NOTIFYNONLINEARVIRTUAL 4)
+(define-constant NOTIFYPOINTER 5)
+(define-constant NOTIFYPOINTERROOT 6)
+(define-constant NOTIFYDETAILNONE 7)
+(define-constant VISIBILITYUNOBSCURED 0)
+(define-constant VISIBILITYPARTIALLYOBSCURED 1)
+(define-constant VISIBILITYFULLYOBSCURED 2)
+(define-constant PLACEONTOP 0)
+(define-constant PLACEONBOTTOM 1)
+(define-constant FAMILYINTERNET 0)
+(define-constant FAMILYDECNET 1)
+(define-constant FAMILYCHAOS 2)
+(define-constant PROPERTYNEWVALUE 0)
+(define-constant PROPERTYDELETE 1)
+(define-constant COLORMAPUNINSTALLED 0)
+(define-constant COLORMAPINSTALLED 1)
+(define-constant GRABMODESYNC 0)
+(define-constant GRABMODEASYNC 1)
+(define-constant GRABSUCCESS 0)
+(define-constant ALREADYGRABBED 1)
+(define-constant GRABINVALIDTIME 2)
+(define-constant GRABNOTVIEWABLE 3)
+(define-constant GRABFROZEN 4)
+(define-constant ASYNCPOINTER 0)
+(define-constant SYNCPOINTER 1)
+(define-constant REPLAYPOINTER 2)
+(define-constant ASYNCKEYBOARD 3)
+(define-constant SYNCKEYBOARD 4)
+(define-constant REPLAYKEYBOARD 5)
+(define-constant ASYNCBOTH 6)
+(define-constant SYNCBOTH 7)
+(define-constant REVERTTONONE 0)
+(define-constant REVERTTOPOINTERROOT 1)
+(define-constant REVERTTOPARENT 2)
+(define-constant SUCCESS 0)
+(define-constant BADREQUEST 1)
+(define-constant BADVALUE 2)
+(define-constant BADWINDOW 3)
+(define-constant BADPIXMAP 4)
+(define-constant BADATOM 5)
+(define-constant BADCURSOR 6)
+(define-constant BADFONT 7)
+(define-constant BADMATCH 8)
+(define-constant BADDRAWABLE 9)
+(define-constant BADACCESS 10)
+(define-constant BADALLOC 11)
+(define-constant BADCOLOR 12)
+(define-constant BADGC 13)
+(define-constant BADIDCHOICE 14)
+(define-constant BADNAME 15)
+(define-constant BADLENGTH 16)
+(define-constant BADIMPLEMENTATION 17)
+(define-constant FIRSTEXTENSIONERROR 128)
+(define-constant LASTEXTENSIONERROR 255)
+(define-constant INPUTOUTPUT 1)
+(define-constant INPUTONLY 2)
+(define-constant CWBACKPIXMAP 1)
+(define-constant CWBACKPIXEL 2)
+(define-constant CWBORDERPIXMAP 4)
+(define-constant CWBORDERPIXEL 8)
+(define-constant CWBITGRAVITY 16)
+(define-constant CWWINGRAVITY 32)
+(define-constant CWBACKINGSTORE 64)
+(define-constant CWBACKINGPLANES 128)
+(define-constant CWBACKINGPIXEL 256)
+(define-constant CWOVERRIDEREDIRECT 512)
+(define-constant CWSAVEUNDER 1024)
+(define-constant CWEVENTMASK 2048)
+(define-constant CWDONTPROPAGATE 4096)
+(define-constant CWCOLORMAP 8192)
+(define-constant CWCURSOR 16384)
+(define-constant CWX 1)
+(define-constant CWY 2)
+(define-constant CWWIDTH 4)
+(define-constant CWHEIGHT 8)
+(define-constant CWBORDERWIDTH 16)
+(define-constant CWSIBLING 32)
+(define-constant CWSTACKMODE 64)
+(define-constant FORGETGRAVITY 0)
+(define-constant NORTHWESTGRAVITY 1)
+(define-constant NORTHGRAVITY 2)
+(define-constant NORTHEASTGRAVITY 3)
+(define-constant WESTGRAVITY 4)
+(define-constant CENTERGRAVITY 5)
+(define-constant EASTGRAVITY 6)
+(define-constant SOUTHWESTGRAVITY 7)
+(define-constant SOUTHGRAVITY 8)
+(define-constant SOUTHEASTGRAVITY 9)
+(define-constant STATICGRAVITY 10)
+(define-constant UNMAPGRAVITY 0)
+(define-constant NOTUSEFUL 0)
+(define-constant WHENMAPPED 1)
+(define-constant ALWAYS 2)
+(define-constant ISUNMAPPED 0)
+(define-constant ISUNVIEWABLE 1)
+(define-constant ISVIEWABLE 2)
+(define-constant SETMODEINSERT 0)
+(define-constant SETMODEDELETE 1)
+(define-constant DESTROYALL 0)
+(define-constant RETAINPERMANENT 1)
+(define-constant RETAINTEMPORARY 2)
+(define-constant ABOVE 0)
+(define-constant BELOW 1)
+(define-constant TOPIF 2)
+(define-constant BOTTOMIF 3)
+(define-constant OPPOSITE 4)
+(define-constant RAISELOWEST 0)
+(define-constant LOWERHIGHEST 1)
+(define-constant PROPMODEREPLACE 0)
+(define-constant PROPMODEPREPEND 1)
+(define-constant PROPMODEAPPEND 2)
+(define-constant GXCLEAR 0)
+(define-constant GXAND 1)
+(define-constant GXANDREVERSE 2)
+(define-constant GXCOPY 3)
+(define-constant GXANDINVERTED 4)
+(define-constant GXNOOP 5)
+(define-constant GXXOR 6)
+(define-constant GXOR 7)
+(define-constant GXNOR 8)
+(define-constant GXEQUIV 9)
+(define-constant GXINVERT 10)
+(define-constant GXORREVERSE 11)
+(define-constant GXCOPYINVERTED 12)
+(define-constant GXORINVERTED 13)
+(define-constant GXNAND 14)
+(define-constant GXSET 15)
+(define-constant LINESOLID 0)
+(define-constant LINEONOFFDASH 1)
+(define-constant LINEDOUBLEDASH 2)
+(define-constant CAPNOTLAST 0)
+(define-constant CAPBUTT 1)
+(define-constant CAPROUND 2)
+(define-constant CAPPROJECTING 3)
+(define-constant JOINMITER 0)
+(define-constant JOINROUND 1)
+(define-constant JOINBEVEL 2)
+(define-constant FILLSOLID 0)
+(define-constant FILLTILED 1)
+(define-constant FILLSTIPPLED 2)
+(define-constant FILLOPAQUESTIPPLED 3)
+(define-constant EVENODDRULE 0)
+(define-constant WINDINGRULE 1)
+(define-constant CLIPBYCHILDREN 0)
+(define-constant INCLUDEINFERIORS 1)
+(define-constant UNSORTED 0)
+(define-constant YSORTED 1)
+(define-constant YXSORTED 2)
+(define-constant YXBANDED 3)
+(define-constant COORDMODEORIGIN 0)
+(define-constant COORDMODEPREVIOUS 1)
+(define-constant COMPLEX 0)
+(define-constant NONCONVEX 1)
+(define-constant CONVEX 2)
+(define-constant ARCCHORD 0)
+(define-constant ARCPIESLICE 1)
+(define-constant GCFUNCTION 1)
+(define-constant GCPLANEMASK 2)
+(define-constant GCFOREGROUND 4)
+(define-constant GCBACKGROUND 8)
+(define-constant GCLINEWIDTH 16)
+(define-constant GCLINESTYLE 32)
+(define-constant GCCAPSTYLE 64)
+(define-constant GCJOINSTYLE 128)
+(define-constant GCFILLSTYLE 256)
+(define-constant GCFILLRULE 512)
+(define-constant GCTILE 1024)
+(define-constant GCSTIPPLE 2048)
+(define-constant GCTILESTIPXORIGIN 4096)
+(define-constant GCTILESTIPYORIGIN 8192)
+(define-constant GCFONT 16384)
+(define-constant GCSUBWINDOWMODE 32768)
+(define-constant GCGRAPHICSEXPOSURES 65536)
+(define-constant GCCLIPXORIGIN 131072)
+(define-constant GCCLIPYORIGIN 262144)
+(define-constant GCCLIPMASK 524288)
+(define-constant GCDASHOFFSET 1048576)
+(define-constant GCDASHLIST 2097152)
+(define-constant GCARCMODE 4194304)
+(define-constant GCLASTBIT 22)
+(define-constant FONTLEFTTORIGHT 0)
+(define-constant FONTRIGHTTOLEFT 1)
+(define-constant FONTCHANGE 255)
+(define-constant XYBITMAP 0)
+(define-constant XYPIXMAP 1)
+(define-constant ZPIXMAP 2)
+(define-constant ALLOCNONE 0)
+(define-constant ALLOCALL 1)
+(define-constant DORED 1)
+(define-constant DOGREEN 2)
+(define-constant DOBLUE 4)
+(define-constant CURSORSHAPE 0)
+(define-constant TILESHAPE 1)
+(define-constant STIPPLESHAPE 2)
+(define-constant AUTOREPEATMODEOFF 0)
+(define-constant AUTOREPEATMODEON 1)
+(define-constant AUTOREPEATMODEDEFAULT 2)
+(define-constant LEDMODEOFF 0)
+(define-constant LEDMODEON 1)
+(define-constant KBKEYCLICKPERCENT 1)
+(define-constant KBBELLPERCENT 2)
+(define-constant KBBELLPITCH 4)
+(define-constant KBBELLDURATION 8)
+(define-constant KBLED 16)
+(define-constant KBLEDMODE 32)
+(define-constant KBKEY 64)
+(define-constant KBAUTOREPEATMODE 128)
+(define-constant MAPPINGSUCCESS 0)
+(define-constant MAPPINGBUSY 1)
+(define-constant MAPPINGFAILED 2)
+(define-constant MAPPINGMODIFIER 0)
+(define-constant MAPPINGKEYBOARD 1)
+(define-constant MAPPINGPOINTER 2)
+(define-constant DONTPREFERBLANKING 0)
+(define-constant PREFERBLANKING 1)
+(define-constant DEFAULTBLANKING 2)
+(define-constant DISABLESCREENSAVER 0)
+(define-constant DISABLESCREENINTERVAL 0)
+(define-constant DONTALLOWEXPOSURES 0)
+(define-constant ALLOWEXPOSURES 1)
+(define-constant DEFAULTEXPOSURES 2)
+(define-constant SCREENSAVERRESET 0)
+(define-constant SCREENSAVERACTIVE 1)
+(define-constant HOSTINSERT 0)
+(define-constant HOSTDELETE 1)
+(define-constant ENABLEACCESS 1)
+(define-constant DISABLEACCESS 0)
+(define-constant STATICGRAY 0)
+(define-constant GRAYSCALE 1)
+(define-constant STATICCOLOR 2)
+(define-constant PSEUDOCOLOR 3)
+(define-constant TRUECOLOR 4)
+(define-constant DIRECTCOLOR 5)
+(define-constant LSBFIRST 0)
+(define-constant MSBFIRST 1)
+(define-constant XA_PRIMARY 1)
+(define-constant XA_SECONDARY 2)
+(define-constant XA_ARC 3)
+(define-constant XA_ATOM 4)
+(define-constant XA_BITMAP 5)
+(define-constant XA_CARDINAL 6)
+(define-constant XA_COLORMAP 7)
+(define-constant XA_CURSOR 8)
+(define-constant XA_CUT_BUFFER0 9)
+(define-constant XA_CUT_BUFFER1 10)
+(define-constant XA_CUT_BUFFER2 11)
+(define-constant XA_CUT_BUFFER3 12)
+(define-constant XA_CUT_BUFFER4 13)
+(define-constant XA_CUT_BUFFER5 14)
+(define-constant XA_CUT_BUFFER6 15)
+(define-constant XA_CUT_BUFFER7 16)
+(define-constant XA_DRAWABLE 17)
+(define-constant XA_FONT 18)
+(define-constant XA_INTEGER 19)
+(define-constant XA_PIXMAP 20)
+(define-constant XA_POINT 21)
+(define-constant XA_RECTANGLE 22)
+(define-constant XA_RESOURCE_MANAGER 23)
+(define-constant XA_RGB_COLOR_MAP 24)
+(define-constant XA_RGB_BEST_MAP 25)
+(define-constant XA_RGB_BLUE_MAP 26)
+(define-constant XA_RGB_DEFAULT_MAP 27)
+(define-constant XA_RGB_GRAY_MAP 28)
+(define-constant XA_RGB_GREEN_MAP 29)
+(define-constant XA_RGB_RED_MAP 30)
+(define-constant XA_STRING 31)
+(define-constant XA_VISUALID 32)
+(define-constant XA_WINDOW 33)
+(define-constant XA_WM_COMMAND 34)
+(define-constant XA_WM_HINTS 35)
+(define-constant XA_WM_CLIENT_MACHINE 36)
+(define-constant XA_WM_ICON_NAME 37)
+(define-constant XA_WM_ICON_SIZE 38)
+(define-constant XA_WM_NAME 39)
+(define-constant XA_WM_NORMAL_HINTS 40)
+(define-constant XA_WM_SIZE_HINTS 41)
+(define-constant XA_WM_ZOOM_HINTS 42)
+(define-constant XA_MIN_SPACE 43)
+(define-constant XA_NORM_SPACE 44)
+(define-constant XA_MAX_SPACE 45)
+(define-constant XA_END_SPACE 46)
+(define-constant XA_SUPERSCRIPT_X 47)
+(define-constant XA_SUPERSCRIPT_Y 48)
+(define-constant XA_SUBSCRIPT_X 49)
+(define-constant XA_SUBSCRIPT_Y 50)
+(define-constant XA_UNDERLINE_POSITION 51)
+(define-constant XA_UNDERLINE_THICKNESS 52)
+(define-constant XA_STRIKEOUT_ASCENT 53)
+(define-constant XA_STRIKEOUT_DESCENT 54)
+(define-constant XA_ITALIC_ANGLE 55)
+(define-constant XA_X_HEIGHT 56)
+(define-constant XA_QUAD_WIDTH 57)
+(define-constant XA_WEIGHT 58)
+(define-constant XA_POINT_SIZE 59)
+(define-constant XA_RESOLUTION 60)
+(define-constant XA_COPYRIGHT 61)
+(define-constant XA_NOTICE 62)
+(define-constant XA_FONT_NAME 63)
+(define-constant XA_FAMILY_NAME 64)
+(define-constant XA_FULL_NAME 65)
+(define-constant XA_CAP_HEIGHT 66)
+(define-constant XA_WM_CLASS 67)
+(define-constant XA_WM_TRANSIENT_FOR 68)
+(define-constant XA_LAST_PREDEFINED 68)
+(define-constant QUEUEDALREADY 0)
+(define-constant QUEUEDAFTERREADING 1)
+(define-constant QUEUEDAFTERFLUSH 2)
+(define-constant ALLPLANES -1)
+(define-constant NULL 0)
+(define-constant NULLQUARK 0)
+(define-constant NULLSTRING 0)
+(define-constant XRMBINDTIGHTLY 0)
+(define-constant XRMBINDLOOSELY 1)
+(define-constant XRMOPTIONNOARG 0)
+(define-constant XRMOPTIONISARG 1)
+(define-constant XRMOPTIONSTICKYARG 2)
+(define-constant XRMOPTIONSEPARG 3)
+(define-constant XRMOPTIONRESARG 4)
+(define-constant XRMOPTIONSKIPARG 5)
+(define-constant XRMOPTIONSKIPLINE 6)
+(define-constant NOVALUE 0)
+(define-constant XVALUE 1)
+(define-constant YVALUE 2)
+(define-constant WIDTHVALUE 4)
+(define-constant HEIGHTVALUE 8)
+(define-constant ALLVALUES 15)
+(define-constant XNEGATIVE 16)
+(define-constant YNEGATIVE 32)
+(define-constant USPOSITION 1)
+(define-constant USSIZE 2)
+(define-constant PPOSITION 4)
+(define-constant PSIZE 8)
+(define-constant PMINSIZE 16)
+(define-constant PMAXSIZE 32)
+(define-constant PRESIZEINC 64)
+(define-constant PASPECT 128)
+(define-constant PALLHINTS 252)
+(define-constant INPUTHINT 1)
+(define-constant STATEHINT 2)
+(define-constant ICONPIXMAPHINT 4)
+(define-constant ICONWINDOWHINT 8)
+(define-constant ICONPOSITIONHINT 16)
+(define-constant ICONMASKHINT 32)
+(define-constant WINDOWGROUPHINT 64)
+(define-constant ALLHINTS 127)
+(define-constant DONTCARESTATE 0)
+(define-constant NORMALSTATE 1)
+(define-constant ZOOMSTATE 2)
+(define-constant ICONICSTATE 3)
+(define-constant INACTIVESTATE 4)
+(define-constant RECTANGLEOUT 0)
+(define-constant RECTANGLEIN 1)
+(define-constant RECTANGLEPART 2)
+(define-constant VISUALNOMASK 0)
+(define-constant VISUALIDMASK 1)
+(define-constant VISUALSCREENMASK 2)
+(define-constant VISUALDEPTHMASK 4)
+(define-constant VISUALCLASSMASK 8)
+(define-constant VISUALREDMASKMASK 16)
+(define-constant VISUALGREENMASKMASK 32)
+(define-constant VISUALBLUEMASKMASK 64)
+(define-constant VISUALCOLORMAPSIZEMASK 128)
+(define-constant VISUALBITSPERRGBMASK 256)
+(define-constant VISUALALLMASK 511)
+(define-constant BITMAPSUCCESS 0)
+(define-constant BITMAPOPENFAILED 1)
+(define-constant BITMAPFILEINVALID 2)
+(define-constant BITMAPNOMEMORY 3)
+(define-constant XCSUCCESS 0)
+(define-constant XCNOMEM 1)
+(define-constant XCNOENT 2)
+(define-constant XK_BACKSPACE 65288)
+(define-constant XK_TAB 65289)
+(define-constant XK_LINEFEED 65290)
+(define-constant XK_CLEAR 65291)
+(define-constant XK_RETURN 65293)
+(define-constant XK_PAUSE 65299)
+(define-constant XK_ESCAPE 65307)
+(define-constant XK_DELETE 65535)
+(define-constant XK_MULTI_KEY 65312)
+(define-constant XK_KANJI 65313)
+(define-constant XK_HOME 65360)
+(define-constant XK_LEFT 65361)
+(define-constant XK_UP 65362)
+(define-constant XK_RIGHT 65363)
+(define-constant XK_DOWN 65364)
+(define-constant XK_PRIOR 65365)
+(define-constant XK_NEXT 65366)
+(define-constant XK_END 65367)
+(define-constant XK_BEGIN 65368)
+(define-constant XK_SELECT 65376)
+(define-constant XK_PRINT 65377)
+(define-constant XK_EXECUTE 65378)
+(define-constant XK_INSERT 65379)
+(define-constant XK_UNDO 65381)
+(define-constant XK_REDO 65382)
+(define-constant XK_MENU 65383)
+(define-constant XK_FIND 65384)
+(define-constant XK_CANCEL 65385)
+(define-constant XK_HELP 65386)
+(define-constant XK_BREAK 65387)
+(define-constant XK_MODE_SWITCH 65406)
+(define-constant XK_SCRIPT_SWITCH 65406)
+(define-constant XK_NUM_LOCK 65407)
+(define-constant XK_KP_SPACE 65408)
+(define-constant XK_KP_TAB 65417)
+(define-constant XK_KP_ENTER 65421)
+(define-constant XK_KP_F1 65425)
+(define-constant XK_KP_F2 65426)
+(define-constant XK_KP_F3 65427)
+(define-constant XK_KP_F4 65428)
+(define-constant XK_KP_EQUAL 65469)
+(define-constant XK_KP_MULTIPLY 65450)
+(define-constant XK_KP_ADD 65451)
+(define-constant XK_KP_SEPARATOR 65452)
+(define-constant XK_KP_SUBTRACT 65453)
+(define-constant XK_KP_DECIMAL 65454)
+(define-constant XK_KP_DIVIDE 65455)
+(define-constant XK_KP_0 65456)
+(define-constant XK_KP_1 65457)
+(define-constant XK_KP_2 65458)
+(define-constant XK_KP_3 65459)
+(define-constant XK_KP_4 65460)
+(define-constant XK_KP_5 65461)
+(define-constant XK_KP_6 65462)
+(define-constant XK_KP_7 65463)
+(define-constant XK_KP_8 65464)
+(define-constant XK_KP_9 65465)
+(define-constant XK_F1 65470)
+(define-constant XK_F2 65471)
+(define-constant XK_F3 65472)
+(define-constant XK_F4 65473)
+(define-constant XK_F5 65474)
+(define-constant XK_F6 65475)
+(define-constant XK_F7 65476)
+(define-constant XK_F8 65477)
+(define-constant XK_F9 65478)
+(define-constant XK_F10 65479)
+(define-constant XK_F11 65480)
+(define-constant XK_L1 65480)
+(define-constant XK_F12 65481)
+(define-constant XK_L2 65481)
+(define-constant XK_F13 65482)
+(define-constant XK_L3 65482)
+(define-constant XK_F14 65483)
+(define-constant XK_L4 65483)
+(define-constant XK_F15 65484)
+(define-constant XK_L5 65484)
+(define-constant XK_F16 65485)
+(define-constant XK_L6 65485)
+(define-constant XK_F17 65486)
+(define-constant XK_L7 65486)
+(define-constant XK_F18 65487)
+(define-constant XK_L8 65487)
+(define-constant XK_F19 65488)
+(define-constant XK_L9 65488)
+(define-constant XK_F20 65489)
+(define-constant XK_L10 65489)
+(define-constant XK_F21 65490)
+(define-constant XK_R1 65490)
+(define-constant XK_F22 65491)
+(define-constant XK_R2 65491)
+(define-constant XK_F23 65492)
+(define-constant XK_R3 65492)
+(define-constant XK_F24 65493)
+(define-constant XK_R4 65493)
+(define-constant XK_F25 65494)
+(define-constant XK_R5 65494)
+(define-constant XK_F26 65495)
+(define-constant XK_R6 65495)
+(define-constant XK_F27 65496)
+(define-constant XK_R7 65496)
+(define-constant XK_F28 65497)
+(define-constant XK_R8 65497)
+(define-constant XK_F29 65498)
+(define-constant XK_R9 65498)
+(define-constant XK_F30 65499)
+(define-constant XK_R10 65499)
+(define-constant XK_F31 65500)
+(define-constant XK_R11 65500)
+(define-constant XK_F32 65501)
+(define-constant XK_R12 65501)
+(define-constant XK_R13 65502)
+(define-constant XK_F33 65502)
+(define-constant XK_F34 65503)
+(define-constant XK_R14 65503)
+(define-constant XK_F35 65504)
+(define-constant XK_R15 65504)
+(define-constant XK_SHIFT_L 65505)
+(define-constant XK_SHIFT_R 65506)
+(define-constant XK_CONTROL_L 65507)
+(define-constant XK_CONTROL_R 65508)
+(define-constant XK_CAPS_LOCK 65509)
+(define-constant XK_SHIFT_LOCK 65510)
+(define-constant XK_META_L 65511)
+(define-constant XK_META_R 65512)
+(define-constant XK_ALT_L 65513)
+(define-constant XK_ALT_R 65514)
+(define-constant XK_SUPER_L 65515)
+(define-constant XK_SUPER_R 65516)
+(define-constant XK_HYPER_L 65517)
+(define-constant XK_HYPER_R 65518)
+(define-constant XK_SPACE 32)
+(define-constant XK_EXCLAM 33)
+(define-constant XK_QUOTEDBL 34)
+(define-constant XK_NUMBERSIGN 35)
+(define-constant XK_DOLLAR 36)
+(define-constant XK_PERCENT 37)
+(define-constant XK_AMPERSAND 38)
+(define-constant XK_QUOTERIGHT 39)
+(define-constant XK_PARENLEFT 40)
+(define-constant XK_PARENRIGHT 41)
+(define-constant XK_ASTERISK 42)
+(define-constant XK_PLUS 43)
+(define-constant XK_COMMA 44)
+(define-constant XK_MINUS 45)
+(define-constant XK_PERIOD 46)
+(define-constant XK_SLASH 47)
+(define-constant XK_0 48)
+(define-constant XK_1 49)
+(define-constant XK_2 50)
+(define-constant XK_3 51)
+(define-constant XK_4 52)
+(define-constant XK_5 53)
+(define-constant XK_6 54)
+(define-constant XK_7 55)
+(define-constant XK_8 56)
+(define-constant XK_9 57)
+(define-constant XK_COLON 58)
+(define-constant XK_SEMICOLON 59)
+(define-constant XK_LESS 60)
+(define-constant XK_EQUAL 61)
+(define-constant XK_GREATER 62)
+(define-constant XK_QUESTION 63)
+(define-constant XK_AT 64)
+(define-constant XK_A 65)
+(define-constant XK_B 66)
+(define-constant XK_C 67)
+(define-constant XK_D 68)
+(define-constant XK_E 69)
+(define-constant XK_F 70)
+(define-constant XK_G 71)
+(define-constant XK_H 72)
+(define-constant XK_I 73)
+(define-constant XK_J 74)
+(define-constant XK_K 75)
+(define-constant XK_L 76)
+(define-constant XK_M 77)
+(define-constant XK_N 78)
+(define-constant XK_O 79)
+(define-constant XK_P 80)
+(define-constant XK_Q 81)
+(define-constant XK_R 82)
+(define-constant XK_S 83)
+(define-constant XK_T 84)
+(define-constant XK_U 85)
+(define-constant XK_V 86)
+(define-constant XK_W 87)
+(define-constant XK_X 88)
+(define-constant XK_Y 89)
+(define-constant XK_Z 90)
+(define-constant XK_BRACKETLEFT 91)
+(define-constant XK_BACKSLASH 92)
+(define-constant XK_BRACKETRIGHT 93)
+(define-constant XK_ASCIICIRCUM 94)
+(define-constant XK_UNDERSCORE 95)
+(define-constant XK_QUOTELEFT 96)
+(define-constant XK_LCA 97)
+(define-constant XK_LCB 98)
+(define-constant XK_LCC 99)
+(define-constant XK_LCD 100)
+(define-constant XK_LCE 101)
+(define-constant XK_LCF 102)
+(define-constant XK_LCG 103)
+(define-constant XK_LCH 104)
+(define-constant XK_LCI 105)
+(define-constant XK_LCJ 106)
+(define-constant XK_LCK 107)
+(define-constant XK_LCL 108)
+(define-constant XK_LCM 109)
+(define-constant XK_LCN 110)
+(define-constant XK_LCO 111)
+(define-constant XK_LCP 112)
+(define-constant XK_LCQ 113)
+(define-constant XK_LCR 114)
+(define-constant XK_LCS 115)
+(define-constant XK_LCT 116)
+(define-constant XK_LCU 117)
+(define-constant XK_LCV 118)
+(define-constant XK_LCW 119)
+(define-constant XK_LCX 120)
+(define-constant XK_LCY 121)
+(define-constant XK_LCZ 122)
+(define-constant XK_BRACELEFT 123)
+(define-constant XK_BAR 124)
+(define-constant XK_BRACERIGHT 125)
+(define-constant XK_ASCIITILDE 126)
+(define-constant XK_NOBREAKSPACE 160)
+(define-constant XK_EXCLAMDOWN 161)
+(define-constant XK_CENT 162)
+(define-constant XK_STERLING 163)
+(define-constant XK_CURRENCY 164)
+(define-constant XK_YEN 165)
+(define-constant XK_BROKENBAR 166)
+(define-constant XK_SECTION 167)
+(define-constant XK_DIAERESIS 168)
+(define-constant XK_COPYRIGHT 169)
+(define-constant XK_ORDFEMININE 170)
+(define-constant XK_GUILLEMOTLEFT 171)
+(define-constant XK_NOTSIGN 172)
+(define-constant XK_HYPHEN 173)
+(define-constant XK_REGISTERED 174)
+(define-constant XK_MACRON 175)
+(define-constant XK_DEGREE 176)
+(define-constant XK_PLUSMINUS 177)
+(define-constant XK_TWOSUPERIOR 178)
+(define-constant XK_THREESUPERIOR 179)
+(define-constant XK_ACUTE 180)
+(define-constant XK_MU 181)
+(define-constant XK_PARAGRAPH 182)
+(define-constant XK_PERIODCENTERED 183)
+(define-constant XK_CEDILLA 184)
+(define-constant XK_ONESUPERIOR 185)
+(define-constant XK_MASCULINE 186)
+(define-constant XK_GUILLEMOTRIGHT 187)
+(define-constant XK_ONEQUARTER 188)
+(define-constant XK_ONEHALF 189)
+(define-constant XK_THREEQUARTERS 190)
+(define-constant XK_QUESTIONDOWN 191)
+(define-constant XK_AGRAVE 192)
+(define-constant XK_AACUTE 193)
+(define-constant XK_ACIRCUMFLEX 194)
+(define-constant XK_ATILDE 195)
+(define-constant XK_ADIAERESIS 196)
+(define-constant XK_ARING 197)
+(define-constant XK_AE 198)
+(define-constant XK_CCEDILLA 199)
+(define-constant XK_EGRAVE 200)
+(define-constant XK_EACUTE 201)
+(define-constant XK_ECIRCUMFLEX 202)
+(define-constant XK_EDIAERESIS 203)
+(define-constant XK_IGRAVE 204)
+(define-constant XK_IACUTE 205)
+(define-constant XK_ICIRCUMFLEX 206)
+(define-constant XK_IDIAERESIS 207)
+(define-constant XK_ETH 208)
+(define-constant XK_NTILDE 209)
+(define-constant XK_OGRAVE 210)
+(define-constant XK_OACUTE 211)
+(define-constant XK_OCIRCUMFLEX 212)
+(define-constant XK_OTILDE 213)
+(define-constant XK_ODIAERESIS 214)
+(define-constant XK_MULTIPLY 215)
+(define-constant XK_OOBLIQUE 216)
+(define-constant XK_UGRAVE 217)
+(define-constant XK_UACUTE 218)
+(define-constant XK_UCIRCUMFLEX 219)
+(define-constant XK_UDIAERESIS 220)
+(define-constant XK_YACUTE 221)
+(define-constant XK_THORN 222)
+(define-constant XK_SSHARP 223)
+(define-constant XK_LCAGRAVE 224)
+(define-constant XK_LCAACUTE 225)
+(define-constant XK_LCACIRCUMFLEX 226)
+(define-constant XK_LCATILDE 227)
+(define-constant XK_LCADIAERESIS 228)
+(define-constant XK_LCARING 229)
+(define-constant XK_LCAE 230)
+(define-constant XK_LCCCEDILLA 231)
+(define-constant XK_LCEGRAVE 232)
+(define-constant XK_LCEACUTE 233)
+(define-constant XK_LCECIRCUMFLEX 234)
+(define-constant XK_LCEDIAERESIS 235)
+(define-constant XK_LCIGRAVE 236)
+(define-constant XK_LCIACUTE 237)
+(define-constant XK_LCICIRCUMFLEX 238)
+(define-constant XK_LCIDIAERESIS 239)
+(define-constant XK_LCETH 240)
+(define-constant XK_LCNTILDE 241)
+(define-constant XK_LCOGRAVE 242)
+(define-constant XK_LCOACUTE 243)
+(define-constant XK_LCOCIRCUMFLEX 244)
+(define-constant XK_LCOTILDE 245)
+(define-constant XK_LCODIAERESIS 246)
+(define-constant XK_DIVISION 247)
+(define-constant XK_OSLASH 248)
+(define-constant XK_LCUGRAVE 249)
+(define-constant XK_LCUACUTE 250)
+(define-constant XK_LCUCIRCUMFLEX 251)
+(define-constant XK_LCUDIAERESIS 252)
+(define-constant XK_LCYACUTE 253)
+(define-constant XK_LCTHORN 254)
+(define-constant XK_YDIAERESIS 255)
+(define-constant DXK_RING_ACCENT 268500656)
+(define-constant DXK_CIRCUMFLEX_ACCENT 268500574)
+(define-constant DXK_CEDILLA_ACCENT 268500524)
+(define-constant DXK_ACUTE_ACCENT 268500519)
+(define-constant DXK_GRAVE_ACCENT 268500576)
+(define-constant DXK_TILDE 268500606)
+(define-constant DXK_DIAERESIS 268500514)
+(define-constant DXK_REMOVE 268500736)
+(define-constant XC_NUM_GLYPHS 154)
+(define-constant XC_X_CURSOR 0)
+(define-constant XC_ARROW 2)
+(define-constant XC_BASED_ARROW_DOWN 4)
+(define-constant XC_BASED_ARROW_UP 6)
+(define-constant XC_BOAT 8)
+(define-constant XC_BOGOSITY 10)
+(define-constant XC_BOTTOM_LEFT_CORNER 12)
+(define-constant XC_BOTTOM_RIGHT_CORNER 14)
+(define-constant XC_BOTTOM_SIDE 16)
+(define-constant XC_BOTTOM_TEE 18)
+(define-constant XC_BOX_SPIRAL 20)
+(define-constant XC_CENTER_PTR 22)
+(define-constant XC_CIRCLE 24)
+(define-constant XC_CLOCK 26)
+(define-constant XC_COFFEE_MUG 28)
+(define-constant XC_CROSS 30)
+(define-constant XC_CROSS_REVERSE 32)
+(define-constant XC_CROSSHAIR 34)
+(define-constant XC_DIAMOND_CROSS 36)
+(define-constant XC_DOT 38)
+(define-constant XC_DOTBOX 40)
+(define-constant XC_DOUBLE_ARROW 42)
+(define-constant XC_DRAFT_LARGE 44)
+(define-constant XC_DRAFT_SMALL 46)
+(define-constant XC_DRAPED_BOX 48)
+(define-constant XC_EXCHANGE 50)
+(define-constant XC_FLEUR 52)
+(define-constant XC_GOBBLER 54)
+(define-constant XC_GUMBY 56)
+(define-constant XC_HAND1 58)
+(define-constant XC_HAND2 60)
+(define-constant XC_HEART 62)
+(define-constant XC_ICON 64)
+(define-constant XC_IRON_CROSS 66)
+(define-constant XC_LEFT_PTR 68)
+(define-constant XC_LEFT_SIDE 70)
+(define-constant XC_LEFT_TEE 72)
+(define-constant XC_LEFTBUTTON 74)
+(define-constant XC_LL_ANGLE 76)
+(define-constant XC_LR_ANGLE 78)
+(define-constant XC_MAN 80)
+(define-constant XC_MIDDLEBUTTON 82)
+(define-constant XC_MOUSE 84)
+(define-constant XC_PENCIL 86)
+(define-constant XC_PIRATE 88)
+(define-constant XC_PLUS 90)
+(define-constant XC_QUESTION_ARROW 92)
+(define-constant XC_RIGHT_PTR 94)
+(define-constant XC_RIGHT_SIDE 96)
+(define-constant XC_RIGHT_TEE 98)
+(define-constant XC_RIGHTBUTTON 100)
+(define-constant XC_RTL_LOGO 102)
+(define-constant XC_SAILBOAT 104)
+(define-constant XC_SB_DOWN_ARROW 106)
+(define-constant XC_SB_H_DOUBLE_ARROW 108)
+(define-constant XC_SB_LEFT_ARROW 110)
+(define-constant XC_SB_RIGHT_ARROW 112)
+(define-constant XC_SB_UP_ARROW 114)
+(define-constant XC_SB_V_DOUBLE_ARROW 116)
+(define-constant XC_SHUTTLE 118)
+(define-constant XC_SIZING 120)
+(define-constant XC_SPIDER 122)
+(define-constant XC_SPRAYCAN 124)
+(define-constant XC_STAR 126)
+(define-constant XC_TARGET 128)
+(define-constant XC_TCROSS 130)
+(define-constant XC_TOP_LEFT_ARROW 132)
+(define-constant XC_TOP_LEFT_CORNER 134)
+(define-constant XC_TOP_RIGHT_CORNER 136)
+(define-constant XC_TOP_SIDE 138)
+(define-constant XC_TOP_TEE 140)
+(define-constant XC_TREK 142)
+(define-constant XC_UL_ANGLE 144)
+(define-constant XC_UMBRELLA 146)
+(define-constant XC_UR_ANGLE 148)
+(define-constant XC_WATCH 150)
+(define-constant XC_XTERM 152)