diff --git a/xi/makefile.nt b/xi/makefile.nt
new file mode 100755
index 000000000..ff130d7fc
--- /dev/null
+++ b/xi/makefile.nt
@@ -0,0 +1,120 @@
+##################################################################
+#
+# Makefile for XVT/NT 4.00 Examples
+# Compiler: Microsoft Visual C++ 1.0
+#
+##################################################################
+# Copyright 1989-1994 XVT Software Inc.
+
+!IFNDEF APP_DEBUG
+APP_DEBUG       = FALSE
+!ENDIF
+
+# File pathnames
+XVT_DIR         = C:\XVTDSC2\NT_X86\PTK
+XVT_INCDIR      = $(XVT_DIR)\include
+XVT_LIBDIR      = $(XVT_DIR)\lib
+XVT_BINDIR      = $(XVT_DIR)\bin
+
+XN_API_LIB       =$(XVT_LIBDIR)\xvtnmapi.lib
+XN_HBND_LIB      =$(XVT_LIBDIR)\xvtnmhb.lib
+XN_HIPC_LIB      =$(XVT_LIBDIR)\xvtnmhi.lib
+XN_HNAT_LIB      =$(XVT_LIBDIR)\xvtnmhn.lib
+
+XI_DIR = \XI
+XI_INCDIR = $(XI_DIR)\include
+
+##########################################################################
+#
+#     Compiler/library/linker flags
+#
+
+!include <ntwin32.mak>
+
+!IF "$(APP_DEBUG)" == "TRUE"
+C_FLAGS_DEBUG   = $(cdebug) -DDEBUG
+L_FLAGS_DEBUG   = $(ldebug)
+!ELSE
+C_FLAGS_DEBUG   =
+L_FLAGS_DEBUG   =
+!ENDIF
+
+C_FLAGS = -I. -I$(XVT_INCDIR) -I$(XI_INCDIR) -DSTRICT $(cflags) $(cvarsmt) $(C_FLAGS_DEBUG)
+
+L_FLAGS = $(ldebug) $(guiflags) $(L_FLAGS_DEBUG)
+
+L_LIBS  = $(XN_API_LIB) $(guilibsmt)
+L_HELP_LIBS = $(XN_HBND_LIB)
+# L_HELP_LIBS = $(XN_HIPC_LIB)
+# L_HELP_LIBS = $(XN_HNAT_LIB)
+
+#####################################################################
+#
+# Suffix rules
+#
+
+.SUFFIXES: .rc .url
+
+.c.obj:
+        $(CC) $(C_FLAGS) $*.c
+
+.url.rc:
+        $(XVT_BINDIR)\curl -r rcnt -s -I$(XVT_INCDIR) -DLIBDIR=$(XVT_LIBDIR) $*.url
+
+.url.res:
+        $(XVT_BINDIR)\curl -r rcnt -s -I$(XVT_INCDIR) -DLIBDIR=$(XVT_LIBDIR) $*.url
+    rc -r -fo $*.res $*.rc
+
+.rc.res:
+    rc -r -fo $*.res $*.rc
+
+XILIB = $(XI_DIR)\lib\mxin.lib
+
+OBJS = xilm.obj xilm2.obj xiutils.obj xitext.obj xistx.obj xitree.obj xiheap.obj xi.obj xi2.obj xicf.obj xidbg.obj
+
+SRC = ..
+
+
+###########################################################################
+#
+#     Targets
+#
+###########################################################################
+
+$(XILIB): $(OBJS)
+  del $(XILIB)
+  lib /OUT:$(XILIB) $(OBJS)
+
+xiutils.obj: $(SRC)\xiutils.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xitext.obj: $(SRC)\xitext.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xistx.obj: $(SRC)\xistx.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xilm.obj: $(SRC)\xilm.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xilm2.obj: $(SRC)\xilm2.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xitree.obj: $(SRC)\xitree.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xiheap.obj: $(SRC)\xiheap.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xi.obj: $(SRC)\xi.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xi2.obj: $(SRC)\xi2.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xicf.obj: $(SRC)\xicf.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
+xidbg.obj: $(SRC)\xidbg.c
+  cl $(C_FLAGS) $(SRC)\$*.c
+
diff --git a/xi/makefile.sch b/xi/makefile.sch
new file mode 100755
index 000000000..c22953041
--- /dev/null
+++ b/xi/makefile.sch
@@ -0,0 +1,76 @@
+#=========================================================================
+# Makefile for XI/CH source
+# Orca Software distributes these makefiles for convenience.  Having a
+# makefile for a particular platform does not imply that you have a
+# license to use the source code on that platform.  Before using the
+# source code on any given platform, make sure that you have purchased
+# the appropriate license.
+#
+
+#=========================== System Defines ==============================
+CC				= acc
+XVTDIR			= $(HOME)/xvtdsc2/ch_sparc_sunos/ptk
+XVTCHLIB		= $(XVTDIR)/lib/libxvtcui.a
+CCOPTS			=
+CURLOPTS		=
+XIDIR           = $(HOME)/xi
+
+# --------------------------- Sun SPARC ------------------------------
+CURLFLAGS		= -r furl -s
+XVTFLAGS		=
+LD_FLAGS		=
+LIBS			= $(XVTLIBS) /usr/5lib/libcurses.a
+
+#============================== Utilities ================================
+CURL			= $(XVTDIR)/bin/curl $(CURLFLAGS)
+INCLUDES		= -I$(XVTDIR)/include -I$(XIDIR)/include -I$(XIDIR)/src
+CFLAGS			= $(CCOPTS) $(XVTFLAGS) $(INCLUDES)
+XVTLIBS			= $(XVTCHLIB)
+
+#============================== Resources ================================
+.SUFFIXES: .url .frl
+
+.url.frl:
+  $(CURL) $(CURLOPTS) $(INCLUDES) $<
+
+XILIB = ../lib/libxisch.a
+SRC = $(XIDIR)/src
+OBJP = $(XIDIR)/src/sch
+
+$(XILIB): $(OBJP)/xiheap.o $(OBJP)/xitree.o $(OBJP)/xicf.o $(OBJP)/xitext.o $(OBJP)/xilm.o $(OBJP)/xilm2.o $(OBJP)/xistx.o $(OBJP)/xiutils.o $(OBJP)/xi.o $(OBJP)/xi2.o $(OBJP)/xidbg.o
+        ar rc $(XILIB) $(OBJP)/xiheap.o $(OBJP)/xitree.o $(OBJP)/xicf.o $(OBJP)/xitext.o $(OBJP)/xilm.o $(OBJP)/xilm2.o $(OBJP)/xistx.o $(OBJP)/xiutils.o $(OBJP)/xi.o $(OBJP)/xi2.o $(OBJP)/xidbg.o
+  ranlib $(XILIB)
+
+$(OBJP)/xiheap.o: $(SRC)/xiheap.c
+  $(CC) -c $(CFLAGS) $(SRC)/xiheap.c -o $(OBJP)/xiheap.o
+
+$(OBJP)/xitext.o: $(SRC)/xitext.c
+  $(CC) -c $(CFLAGS) $(SRC)/xitext.c -o $(OBJP)/xitext.o
+
+$(OBJP)/xilm.o: $(SRC)/xilm.c
+  $(CC) -c $(CFLAGS) $(SRC)/xilm.c -o $(OBJP)/xilm.o
+
+$(OBJP)/xilm2.o: $(SRC)/xilm2.c
+  $(CC) -c $(CFLAGS) $(SRC)/xilm2.c -o  $(OBJP)/xilm2.o
+
+$(OBJP)/xistx.o: $(SRC)/xistx.c
+  $(CC) -c $(CFLAGS) $(SRC)/xistx.c -o $(OBJP)/xistx.o
+
+$(OBJP)/xiutils.o: $(SRC)/xiutils.c
+  $(CC) -c $(CFLAGS) $(SRC)/xiutils.c -o $(OBJP)/xiutils.o
+
+$(OBJP)/xi.o: $(SRC)/xi.c
+  $(CC) -c $(CFLAGS) $(SRC)/xi.c -o $(OBJP)/xi.o
+
+$(OBJP)/xi2.o: $(SRC)/xi2.c
+  $(CC) -c $(CFLAGS) $(SRC)/xi2.c -o $(OBJP)/xi2.o
+
+$(OBJP)/xitree.o: $(SRC)/xitree.c
+  $(CC) -c $(CFLAGS) $(SRC)/xitree.c -o $(OBJP)/xitree.o
+
+$(OBJP)/xicf.o: $(SRC)/xicf.c
+  $(CC) -c $(CFLAGS) $(SRC)/xicf.c -o $(OBJP)/xicf.o
+
+$(OBJP)/xidbg.o: $(SRC)/xidbg.c
+  $(CC) -c $(CFLAGS) $(SRC)/xidbg.c -o $(OBJP)/xidbg.o
+
diff --git a/xi/makefile.sgi b/xi/makefile.sgi
new file mode 100755
index 000000000..49271f883
--- /dev/null
+++ b/xi/makefile.sgi
@@ -0,0 +1,186 @@
+#
+# Makefile for XI/X Motif source on SGI
+# Orca Software distributes these makefiles for convenience.  Having a 
+# makefile for a particular platform does not imply that you have a
+# license to use the source code on that platform.  Before using the
+# source code on any given platform, make sure that you have purchased
+# the appropriate license.
+
+
+XVTIDIR = $(XVT_DSC_DIR)/ptk/include
+XPOIDIR = $(ROOTP)/include
+
+# Xvt product and system macros.
+
+PRODUCT  = xvtxm
+SYSTEM   = sgi
+
+# Macros for system utilities.
+
+SHELL    = /bin/sh
+MAKE     = /bin/make
+CC       = /usr/bin/cc
+AR       = /usr/bin/ar
+ARFLAGS  = cr
+LD       = /usr/bin/cc
+LDFLAGS  = -O
+CD       = cd
+SED      = /bin/sed
+YACC     = /bin/yacc -vd
+CP       = /bin/cp
+LN       = /bin/ln -s
+MKDIR    = /bin/mkdir -p
+MV       = /bin/mv -f
+RM       = /bin/rm -f
+TOUCH    = /bin/touch
+
+UIL      = /usr/bin/X11/uil -I$(ROOTP)/include -o
+
+# Macro for 'makedepend' makefile utility.
+
+MKDEP    = /usr/bin/X11/makedepend
+
+# Miscellaneous macros.
+
+STAR     = *
+SHRSUFF  = UNDEFINED
+LSUFF    = .a
+RSUFF	 = .uid
+
+LIBUI    = $(PRODUCT)ui
+LIBTK    = $(PRODUCT)tk
+LIBHLP   = $(PRODUCT)help
+LIBHLPCS = $(PRODUCT)help_cs
+
+XVTBINP  = $(ROOTP)/bin
+XVTLIBP  = $(ROOTP)/lib
+
+XVTLIBS  = $(XVTLIBP)/lib$(LIBUI)$(LSUFF) $(XVTLIBP)/lib$(LIBHLP)$(LSUFF) $(XVTLIBP)/lib$(LIBTK)$(LSUFF)
+TKLDLIBS = -L$(XVTLIBP) -l$(LIBUI) -l$(LIBHLP) -l$(LIBTK)  -lMrm -lXm -lXt -lX11
+
+#
+# Copyright 1993, XVT Software Inc.
+#
+# Imakefile for 'xpoxm' archive.
+#
+# $RCSfile: makefile.sgi,v $
+# $Revision: 1.1.1.1 $ $Date: 1997-12-17 10:43:21 $
+#
+
+# Relative paths to build area root directory, source and objects files.
+
+ROOTP    = ..
+SRCP     = .
+OBJP	 = ./sgi
+
+# Macros for compiling C source.
+
+IDIRS    =  -I$(XPOIDIR) -I$(XVTIDIR)
+CFLAGS	 = -c -g -O -Wf,-XNd8400,-XNp12000 $(IDIRS)
+
+# Library root names.
+
+LIBXI   = ../lib/libxisgi.a
+
+TARGETS  = $(LIBXI)
+
+# Errscan command line for generating new 'xvt_perr.h'.
+
+ERRSCAN  = $(XVTDIR)/errscan -h $(ROOTP)/include/xvt_perr.h -o $(ROOTP)/doc/ERRCODES.TXT $(ROOTP)/include/xvt_msgs.h
+
+# Makefile targets...
+
+default: libtarget
+
+# Spreadsheat (gasp!) Custom Control
+
+XISRC = \
+    $(SRCP)/xi.c \
+    $(SRCP)/xi2.c \
+    $(SRCP)/xicf.c \
+    $(SRCP)/xidbg.c \
+    $(SRCP)/xiheap.c \
+    $(SRCP)/xilm.c \
+    $(SRCP)/xilm2.c \
+    $(SRCP)/xistx.c \
+    $(SRCP)/xitext.c \
+    $(SRCP)/xitree.c \
+    $(SRCP)/xiutils.c
+
+XIOBJ = \
+    $(OBJP)/xi.o \
+    $(OBJP)/xi2.o \
+    $(OBJP)/xicf.o \
+    $(OBJP)/xidbg.o \
+    $(OBJP)/xiheap.o \
+    $(OBJP)/xilm.o \
+    $(OBJP)/xilm2.o \
+    $(OBJP)/xistx.o \
+    $(OBJP)/xitext.o \
+    $(OBJP)/xitree.o \
+    $(OBJP)/xiutils.o
+
+$(OBJP)/xi.o: $(SRCP)/xi.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xi.o $(SRCP)/xi.c
+
+$(OBJP)/xi2.o: $(SRCP)/xi2.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xi2.o $(SRCP)/xi2.c
+
+$(OBJP)/xicf.o: $(SRCP)/xicf.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xicf.o $(SRCP)/xicf.c
+
+$(OBJP)/xidbg.o: $(SRCP)/xidbg.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xidbg.o $(SRCP)/xidbg.c
+
+$(OBJP)/xiheap.o: $(SRCP)/xiheap.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xiheap.o $(SRCP)/xiheap.c
+
+$(OBJP)/xilm.o: $(SRCP)/xilm.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xilm.o $(SRCP)/xilm.c
+
+$(OBJP)/xilm2.o: $(SRCP)/xilm2.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xilm2.o $(SRCP)/xilm2.c
+
+$(OBJP)/xistx.o: $(SRCP)/xistx.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xistx.o $(SRCP)/xistx.c
+
+$(OBJP)/xitext.o: $(SRCP)/xitext.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xitext.o $(SRCP)/xitext.c
+
+$(OBJP)/xitree.o: $(SRCP)/xitree.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xitree.o $(SRCP)/xitree.c
+
+$(OBJP)/xiutils.o: $(SRCP)/xiutils.c
+  $(CC) $(CFLAGS) -o $(OBJP)/xiutils.o $(SRCP)/xiutils.c
+
+$(LIBXI):  $(XIOBJ)
+  $(AR) $(ARFLAGS)  $(LIBXI) $?
+
+# Other Stuff
+
+xvt_perr:
+  @$(RM) $(ROOTP)/include/xvt_perr.h
+  @$(RM) $(ROOTP)/doc/ERRCODES.TXT
+  $(ERRSCAN) $(ROOTP)/src/$(STAR).c \
+  $(ROOTP)/help/common/$(STAR).c $(ROOTP)/help/compiler/$(STAR).c \
+  $(ROOTP)/help/engine/$(STAR).c $(ROOTP)/help/viewer/$(STAR).c
+
+all: $(TARGETS)
+
+libtarget:  $(TARGETS)
+
+depends:
+  @echo "making 'depends'..."
+  @$(MKDEP) -s "# DO NOT DELETE" -p$(OBJP)/ -- $(CFLAGS) -- $(XISRC)
+
+LIBS = $(XVTLIBP)/lib$(LIBXI)$(LSUFF)
+OBJS = $(XIOBJ)
+
+clean:
+  @echo "making 'clean'..."
+  @$(RM) $(LIBS) $(OBJS)
+
+bin:
+
+# DO NOT DELETE THIS LINE -- makedepend depends on it!
+
diff --git a/xi/makefile.sxm b/xi/makefile.sxm
new file mode 100755
index 000000000..46e96b158
--- /dev/null
+++ b/xi/makefile.sxm
@@ -0,0 +1,108 @@
+#
+# Makefile for XI/X Motif source on Sun Sparc
+# Orca Software distributes these makefiles for convenience.  Having a
+# makefile for a particular platform does not imply that you have a
+# license to use the source code on that platform.  Before using the
+# source code on any given platform, make sure that you have purchased
+# the appropriate license.
+
+# Macros for system utilities.
+
+SHELL    = /usr/bin/sh
+MAKE     = /usr/bin/make
+CC       = acc
+AR       = /usr/bin/ar
+ARFLAGS  = cru
+LD       = acc
+LDFLAGS  = -O
+CD       = cd
+SED      = /usr/bin/sed
+YACC     = /usr/lang/yacc -vd
+CP       = /usr/bin/cp
+LN       = /usr/bin/ln -s
+MKDIR    = /usr/bin/mkdir -p
+MV       = /usr/bin/mv -f
+RM       = /usr/bin/rm -f
+TOUCH    = /usr/bin/touch -f
+
+RANLIB   = /usr/bin/ranlib
+
+UIL      = $(MOTIFHOME)/bin/uil -I$(ROOTP)/include -o
+
+# Macro for 'makedepend' makefile utility.
+
+MKDEP    = $(OPENWINHOME)/bin/makedepend
+
+# Miscellaneous macros.
+
+STAR     = *
+SHRSUFF  = .so.4.0
+LSUFF    = .a
+RSUFF	 = .uid
+
+BTAG     = 
+LTAG     =
+LIBUI    = $(PRODUCT)ui$(LTAG)
+LIBTK    = $(PRODUCT)tk$(LTAG)
+LIBHLP   = $(PRODUCT)help$(LTAG)
+LIBHLPCS = $(PRODUCT)help_cs$(LTAG)
+
+XVTBINP  = $(ROOTP)/bin
+XVTLIBP  = $(ROOTP)/lib
+
+XVTLIBS  = $(XVTLIBP)/lib$(LIBUI)$(LSUFF) $(XVTLIBP)/lib$(LIBHLP)$(SHRSUFF) $(XVTLIBP)/lib$(LIBTK)$(SHRSUFF)
+TKLDLIBS = -L$(XVTLIBP) -l$(LIBUI) -l$(LIBHLP) -l$(LIBTK) -L$(MOTIFHOME)/lib -L$(OPENWINHOME)/lib -lMrm -lXm -lXt -lX11
+
+ROOTP   = ../../xvtdsc2/sun/ptk
+SRCP	= .
+OBJP	= ./sxm
+BINP	= $(OBJP)
+
+IDIRS   = -I$(ROOTP)/include -I../include -I/d3/include -I/d3/ericw/motif/include
+CFLAGS	= -c -O -DXTFUNCPROTO $(IDIRS) -temp=/usr/temp
+LDLIBS	= $(TKLDLIBS) -lm
+
+CURL    = $(XVTBINP)/curl$(BTAG) -r mtf11 -s -o
+HELPC   = $(XVTBINP)/helpc$(BTAG) -f xvt -I$(ROOTP)/include -o
+
+XILIB = ../lib/libxisxm.a
+SRC = .
+
+$(XILIB): $(OBJP)/xiheap.o $(OBJP)/xitree.o $(OBJP)/xicf.o $(OBJP)/xitext.o $(OBJP)/xistx.o $(OBJP)/xi.o $(OBJP)/xi2.o $(OBJP)/xitree.o $(OBJP)/xicf.o $(OBJP)/xidbg.o $(OBJP)/xilm.o $(OBJP)/xilm2.o $(OBJP)/xiutils.o
+        $(AR) $(ARFLAGS) $(XILIB) $(OBJP)/xiheap.o $(OBJP)/xitree.o $(OBJP)/xicf.o $(OBJP)/xitext.o $(OBJP)/xilm.o $(OBJP)/xilm2.o $(OBJP)/xistx.o $(OBJP)/xiutils.o $(OBJP)/xi.o $(OBJP)/xi2.o $(OBJP)/xitree.o $(OBJP)/xicf.o $(OBJP)/xidbg.o
+  ranlib $(XILIB) 
+
+$(OBJP)/xiheap.o: $(SRC)/xiheap.c
+  $(CC) -c $(CFLAGS) $(SRC)/xiheap.c -o $(OBJP)/xiheap.o
+
+$(OBJP)/xitext.o: $(SRC)/xitext.c
+  $(CC) -c $(CFLAGS) $(SRC)/xitext.c -o $(OBJP)/xitext.o
+
+$(OBJP)/xilm.o: $(SRC)/xilm.c
+  $(CC) -c $(CFLAGS) $(SRC)/xilm.c -o $(OBJP)/xilm.o
+
+$(OBJP)/xilm2.o: $(SRC)/xilm2.c
+  $(CC) -c $(CFLAGS) $(SRC)/xilm2.c -o $(OBJP)/xilm2.o
+
+$(OBJP)/xistx.o: $(SRC)/xistx.c
+  $(CC) -c $(CFLAGS) $(SRC)/xistx.c -o $(OBJP)/xistx.o
+
+$(OBJP)/xiutils.o: $(SRC)/xiutils.c
+  $(CC) -c $(CFLAGS) $(SRC)/xiutils.c -o $(OBJP)/xiutils.o
+
+$(OBJP)/xi.o: $(SRC)/xi.c
+  $(CC) -c $(CFLAGS) $(SRC)/xi.c -o $(OBJP)/xi.o
+
+$(OBJP)/xi2.o: $(SRC)/xi2.c
+  $(CC) -c $(CFLAGS) $(SRC)/xi2.c -o $(OBJP)/xi2.o
+
+$(OBJP)/xitree.o: $(SRC)/xitree.c
+  $(CC) -c $(CFLAGS) $(SRC)/xitree.c -o $(OBJP)/xitree.o
+
+$(OBJP)/xicf.o: $(SRC)/xicf.c
+  $(CC) -c $(CFLAGS) $(SRC)/xicf.c -o $(OBJP)/xicf.o
+
+$(OBJP)/xidbg.o: $(SRC)/xidbg.c
+  $(CC) -c $(CFLAGS) $(SRC)/xidbg.c -o $(OBJP)/xidbg.o
+
+
diff --git a/xi/makefile.wm b/xi/makefile.wm
new file mode 100755
index 000000000..611eb4aca
--- /dev/null
+++ b/xi/makefile.wm
@@ -0,0 +1,172 @@
+#################################################################
+#
+# Makefile for XI/Win source
+# Compiler: Microsoft Visual C++ version 1.0 or 1.5
+# Orca Software distributes these makefiles for convenience.  Having a
+# makefile for a particular platform does not imply that you have a 
+# license to use the source code on that platform.  Before using the
+# source code on any given platform, make sure that you have purchased
+# the appropriate license.
+#
+##################################################################
+# Copyright 1989-1994 XVT Software Inc.
+
+APP_MODEL       = LARGE
+APP_DEBUG       = FALSE
+
+# File pathnames
+XVT_DIR     = \xvtdsc2\win_x86\ptk
+XVT_INCDIR  = $(XVT_DIR)\include
+XVT_LIBDIR  = $(XVT_DIR)\lib
+XVT_BINDIR  = $(XVT_DIR)\bin
+XI_DIR = \xi
+XI_INCDIR = $(XI_DIR)\include
+XI_LIBDIR = $(XI_DIR)\lib
+LIB = $(XI_LIBDIR)\lmxiw.lib
+
+all: $(LIB)
+
+#
+# Compiler variables
+#
+#  Note: The debug variables are only enabled when APP_DEBUG is
+#        set to TRUE above.
+#  -Od: Turn off optimization
+#  -Zi: Compile for debugging 
+#  -c : Compile without linking
+#  -G2s: Compile for 286 instruction set.
+#  -W3: Turn on warning level 3.
+#  -Zp: Pack structure members.
+CC      = cl
+CDEBUG  = -Od -Zi
+CFLAGS  = -G2s -GA -GEs -W3 -Zp -DWSWIN
+
+#
+# Link variables
+#
+#  Note: The debug variables are only enabled when APP_DEBUG is
+#        set to TRUE above.
+# /CO : Add debugging information for Codeview.
+# /ALIGN: aligns segment on 16 byte boundaries.
+# /NOD: Don't search for default libraries.
+# /NOE: Prevent linker from searching extended dictionaries.
+#
+LINK    = link
+LDEBUG  = /CO
+LFLAGS  = /ALIGN:16/NOD/NOE
+
+#
+# Debug variables
+#
+# Do not modify these.
+!IF "$(APP_DEBUG)" == "TRUE"
+C_FLAGS_DEBUG   = $(CDEBUG) -DDEBUG
+L_FLAGS_DEBUG   = $(LDEBUG)
+!ELSE
+C_FLAGS_DEBUG   =
+L_FLAGS_DEBUG   =
+!ENDIF
+
+#
+# Memory Model variables
+#
+# Do not modify these.
+C_FLAGS_MODEL   = -AL
+C_LIBS          = llibcew libw oldnames
+XVT_LIBS_MODEL  = $(XVT_LIBDIR)\xvtwmapi.lib $(XVT_LIBDIR)\xvtwmhn.lib
+XI_LIB_MODEL = $(XI_LIBDIR)\lmxiw.lib
+
+##########################################################################
+#
+# Library Variables
+#
+C_FLAGS = $(C_FLAGS_DEBUG) $(CFLAGS) $(C_FLAGS_MODEL) \
+      -I. -I$(XVT_INCDIR) -DSTRICT
+
+L_FLAGS = $(L_FLAGS_DEBUG) $(LFLAGS)
+
+L_LIBS  = $(C_LIBS) $(XVT_LIBS_MODEL) $(XI_LIB_MODEL)
+
+L_DEFS  = $(XVT_LIBDIR)\xvtwapp.def
+
+
+#####################################################################
+#
+# Suffix rules
+#
+.c.obj:
+  $(CC) $(C_FLAGS) -Fo$* $?
+
+.url.rc:
+  $(XVT_BINDIR)\curl -r rcwin -s -I$(XVT_INCDIR) $*.url
+
+.url.res:
+  $(XVT_BINDIR)\curl -r rcwin -s -I$(XVT_INCDIR) $*.url
+  rc -r $*.rc
+
+.rc.res:
+  rc -r $*.rc
+
+.SUFFIXES: .rc .url
+
+.obj.exe:
+    echo $*.obj        > wiapp.tmp
+  echo $@           >> wiapp.tmp
+  echo nul          >> wiapp.tmp
+  echo $(L_LIBS)    >> wiapp.tmp
+  echo $(L_DEFS)    >> wiapp.tmp
+  $(LINK) $(L_FLAGS) @wiapp.tmp
+  del wiapp.tmp
+  rc -k -30 $*.res
+
+clean:
+  -del *.exe
+  -del *.obj
+  -del *.res
+  -del *.rc
+
+OBJS = xilm.obj xilm2.obj xiutils.obj xitext.obj xistx.obj xitree.obj xiheap.obj xi.obj xi2.obj xicf.obj xidbg.obj
+
+SRC = ..
+
+$(LIB): $(OBJS)
+  del $(LIB)
+  lib @<<
+$(LIB)&
+$(OBJS), nul
+<<NOKEEP
+
+xiutils.obj: $(SRC)\xiutils.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xitext.obj: $(SRC)\xitext.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xistx.obj: $(SRC)\xistx.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xilm.obj: $(SRC)\xilm.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xilm2.obj: $(SRC)\xilm2.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xitree.obj: $(SRC)\xitree.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xiheap.obj: $(SRC)\xiheap.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xi.obj: $(SRC)\xi.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xi2.obj: $(SRC)\xi2.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xicf.obj: $(SRC)\xicf.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+xidbg.obj: $(SRC)\xidbg.c
+  $(CC) -c $(C_FLAGS) $(SRC)\$*.c
+
+
diff --git a/xi/xi.c b/xi/xi.c
new file mode 100755
index 000000000..97b1b743d
--- /dev/null
+++ b/xi/xi.c
@@ -0,0 +1,3704 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+#define XI_INTERNAL
+#include "xi.h"
+#include "xitext.h"
+#include "xistx.h"
+#include "xilm.h"
+#include "xiutils.h"
+#include "xvtmenu.h"
+#include "xi_int.h"
+
+#if XIWS == MTFWS
+#include <X11/Intrinsic.h>
+#include <Xm/Xm.h>
+#endif
+
+#if XIWS == MTFWS
+#include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
+#endif
+
+#if XI_IS_CH
+#undef strcmp
+#define strcmp(a, b) strcmp(a, b)
+#endif
+
+#define MAXPIX 6000
+
+#define VRCT_TO_PRCT(rp) \
+  (rp)->left -= cur_delta_x; \
+  (rp)->right -= cur_delta_x; \
+  (rp)->top -= cur_delta_y; \
+  (rp)->bottom -= cur_delta_y;
+
+
+/* ERROR CODES 20000-20089 */
+
+/********************************* CONSTANTS *******************************/
+
+/********************************* DATA TYPES *******************************/
+
+/******************************* STATIC DATA ********************************/
+WINDOW xi_modal_win = NULL_WIN;
+
+BOOLEAN xi_false = FALSE;
+
+/******************************** FUNCTIONS *********************************/
+
+#ifndef NO_PRIMARY_SELECTION
+#if XIWS == MTFWS
+
+static XI_OBJ *rp_xi_obj = NULL;
+
+static void
+receive_primesel(Widget widget, XtPointer data, Atom *selection,
+Atom *type, XtPointer value, unsigned long *length, int *format)
+{
+  char *s;
+  WINDOW win;
+  char *p;
+
+  /* printf("receive_primesel: ENTERED, widget %d, selection %d, type %d\n",
+    widget, *selection, *type); */
+  /* printf("                           length %d, format %d\n",
+    *length, *format); */
+
+  /* check if request for primary selection was successful */
+  if (*selection != XA_PRIMARY || *type != XA_STRING || *format != 8)
+  {
+    /* printf("receive_primesel: get primary selection failed\n"); */
+    return;
+  }
+
+  /* allocate space and fill in text from selection value */
+  s = xvt_mem_alloc(*length + 1);
+  /* Assertion for out of memory? */
+  strncpy(s, (char *)value, *length);
+  s[*length] = '\0';
+  /* printf("receive_primesel: primary selection text = '%s'\n", s); */
+  XtFree((char *)value);                          /* this must be freed with XtFree */
+
+  /* xvt_dm_post_note("Text from Primary selection is '%s'", s); */
+  win = xi_get_window(rp_xi_obj);
+  rp_xi_obj = NULL;
+  for (p = s; *p != '\0'; ++p)
+  {
+    EVENT ev;
+
+    MEMCLEAR(ev);
+    ev.type = E_CHAR;
+    ev.v.chr.ch = (unsigned char)*p;
+    xi_event(win, &ev);
+    xvt_dwin_update(win);
+  }
+  xvt_mem_free(s);
+}
+
+
+static void
+get_primary_selection(XI_OBJ *itf, WINDOW win)
+{
+  Widget widget;
+
+  rp_xi_obj = itf;
+
+  /* printf("get_primary_selection: ENTERED, win %d\n", win); */
+
+  /* request PRIMARY selection */
+  widget = (Widget) xvt_vobj_get_attr(win, ATTR_X_WIDGET);
+  XtGetSelectionValue(widget, XA_PRIMARY, XA_STRING, receive_primesel, NULL,
+      XtLastTimestampProcessed(XtDisplay(widget)));
+
+  /* printf("get_primary_selection: returning\n"); */
+}
+#endif
+#endif
+
+BOOLEAN call_cb(XI_OBJ *itf, XI_EVENT *xiev)
+{
+  XI_ITF_DATA *itf_data;
+
+  itf_data = itf->v.itf;
+  itf_data->in_callback++;
+#if XI_IS_CH
+  CTOS_IS_CH;
+  xi_coalesce_invalidates(itf, TRUE);
+  CTOS_END;
+#endif
+  (*itf_data->xi_eh)((struct _xi_obj *)itf, xiev);
+#ifdef WINRUNNER
+  xir_record(itf, xiev);
+#endif
+  if (xi_is_itf(itf))
+  {
+#if XI_IS_CH
+    CTOS_IS_CH;
+    xi_coalesce_invalidates(itf, FALSE);
+    CTOS_END;
+#endif
+    itf_data->in_callback--;
+    if (itf_data->closing)
+    {
+      itf_data->closing = FALSE;
+      xi_close_window_internal(itf);
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+static long near
+event_to_longchar(EVENT *ep)
+{
+  long c = ep->v.chr.ch;
+
+  if (ep->v.chr.control)
+    c |= XI_MOD_CONTROL;
+  if (ep->v.chr.shift)
+    c |= XI_MOD_SHIFT;
+  return(c);
+}
+
+void xi_column_set_pixel_width( XI_OBJ * column, int width )
+{
+  int               i;
+  XI_LIST_DATA * list;
+  LM_DATA*          lm_data;
+
+  list = column->parent->v.list;
+  lm_data = (LM_DATA *)list->lm;
+  xvt_errmsg_sig_if(!(column->type == XIT_COLUMN), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20010", 20010,
+    "Non-column object sent to xi_column_set_pixel_width");
+  lm_column_set_pixel_width( list->lm, xi_obj_to_idx(column),
+      width );
+  if (list->sb_win && (! list->width))
+    xi_move_list_scroll_bar(column->parent);
+  i = xi_obj_to_idx(column);
+  if (i < lm_data->fixed_columns && list->hsb_win)
+    xi_move_list_hscroll_bar(column->parent);
+}
+
+void xi_set_column_width(XI_OBJ * column, int width)
+{
+  int width_in_chars;
+  if (xi_get_xil_pref((XI_OBJ*)column->itf))
+    width_in_chars = width;
+  else
+    width_in_chars = width / XI_FU_MULTIPLE;
+
+  xi_column_set_pixel_width( column, width_in_chars
+      * ((LM_DATA *)column->parent->v.list->lm)
+      ->pix_char_width );
+}
+
+static XI_OBJ *
+xi_get_default(XI_OBJ *obj)
+{
+  XI_OBJ * *objlist;
+  XI_OBJ *temp;
+  int n;
+
+  temp = obj->itf->v.itf->focus_obj;
+  if ( temp != NULL && temp->type == XIT_BTN )
+    return temp;
+
+  if (obj->type == XIT_BTN && obj->v.btn->dflt)
+    return(obj);
+
+  switch (obj->type)
+  {
+  case XIT_GROUP:
+  case XIT_CELL:
+  case XIT_ROW:
+    return(NULL);
+  default:
+    break;
+  }
+
+  /* search in child list */
+  objlist = xi_get_member_list(obj, &n);
+  for (; n > 0; n--, objlist++)
+  {
+    /* call recursively for generality in future versions */
+    if ((temp = xi_get_default(*objlist)) != NULL)
+      return(temp);
+  }
+  return(NULL);
+}
+
+void
+xi_hscroll_internal(XI_OBJ *xi_obj, int nbr_lines, int pos)
+{
+  XI_OBJ *itf, *focus;
+  LM lm = xi_obj->v.list->lm;
+
+  itf = xi_obj->parent;
+  focus = xi_get_focus(itf);
+  if (focus && focus->parent == xi_obj)
+  {
+    if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+    {
+      lm_hscroll(lm, nbr_lines, pos);
+    }
+    else
+    {
+      if (xi_move_focus(itf))
+  lm_hscroll(lm, nbr_lines, pos);
+    }
+  }
+  else
+    lm_hscroll(lm, nbr_lines, pos);
+}
+
+void
+xi_hscroll(XI_OBJ *xi_obj, int nbr_lines)
+{
+  xi_hscroll_internal(xi_obj, nbr_lines, 0);
+}
+
+static void
+control_event_hscroll(XI_OBJ *xi_obj, int nbr_lines, int pos)
+{
+  XI_LIST_DATA *list_data;
+  XI_OBJ *other_list;
+
+  list_data = xi_obj->v.list;
+  xi_hscroll_internal(xi_obj, nbr_lines, pos);
+  if (list_data->horz_sync_list &&
+      ! list_data->scrolling_in_progress)
+  {
+    list_data->scrolling_in_progress = TRUE;
+    other_list = xi_get_obj(xi_obj->itf,
+  list_data->horz_sync_list);
+    if (other_list)
+      xi_hscroll_internal(other_list, nbr_lines, pos);
+    list_data->scrolling_in_progress = FALSE;
+  }
+}
+
+static void
+control_event_scroll( XI_OBJ *xi_obj, int nbr_lines, int percent,
+          BOOLEAN same_cell )
+{
+  XI_LIST_DATA *list_data;
+  XI_OBJ *other_list;
+
+  list_data = xi_obj->v.list;
+  xi_scroll_internal( xi_obj, nbr_lines, percent, same_cell );
+  if (list_data->vert_sync_list &&
+    ! list_data->scrolling_in_progress)
+  {
+  list_data->scrolling_in_progress = TRUE;
+    other_list = xi_get_obj(xi_obj->itf,
+  list_data->vert_sync_list);
+    if (other_list)
+      xi_scroll_internal(other_list, nbr_lines, percent, same_cell );
+    list_data->scrolling_in_progress = FALSE;
+  }
+}
+
+static void
+control_event(XI_OBJ *itf, WINDOW win, EVENT *ep)
+{
+  XI_ITF_DATA *itf_data;
+  XI_OBJ *xi_obj;
+
+  itf_data = itf->v.itf;
+  win = itf_data->xvt_win;
+  if ((xi_obj = xi_get_obj(itf, ep->v.ctl.id)) != NULL)
+  {
+    switch (xi_obj->type)
+    {
+    case XIT_BTN:
+      {
+  XI_EVENT xiev;
+  MEMCLEAR(xiev);
+  xiev.type = XIE_BUTTON;
+  xiev.v.xi_obj = xi_obj;
+  call_cb(itf, &xiev);
+
+  if (xi_is_itf(itf) && xi_is_window(win)
+      && xi_get_focus(itf) != xi_obj)
+  {
+    WINDOW front_win = xvt_scr_get_focus_vobj();
+    if (win)
+    xvt_scr_set_focus_vobj(win);
+    xvt_vobj_raise(win);          
+    if (front_win != win && front_win)
+    xvt_scr_set_focus_vobj(front_win);
+    xvt_vobj_raise(front_win);          
+  }
+
+  break;
+      }
+    case XIT_LIST:
+      {
+  switch (ep->v.ctl.ci.v.scroll.what)
+  {
+  case SC_LINE_UP:
+    control_event_scroll(xi_obj, -1, 0, TRUE );
+    break;
+  case SC_LINE_DOWN:
+    control_event_scroll(xi_obj, 1, 0, TRUE );
+    break;
+  case SC_PAGE_UP:
+    control_event_scroll(xi_obj, XI_SCROLL_PGUP, 0, TRUE );
+    break;
+  case SC_PAGE_DOWN:
+    control_event_scroll(xi_obj, XI_SCROLL_PGDOWN, 0, TRUE );
+    break;
+  case SC_THUMB:
+    {
+      int percent = ep->v.ctl.ci.v.scroll.pos;
+    if (xvt_sbar_get_proportion(ep->v.ctl.ci.win, HVSCROLL)
+    + percent == 100)
+        control_event_scroll(xi_obj, XI_SCROLL_LAST, 0, TRUE );
+      else
+        control_event_scroll(xi_obj, XI_SCROLL_FIRST, percent, TRUE );
+      break;
+    }
+  }
+  break;
+      }
+    }
+  }
+  if (xi_is_itf(itf) &&
+      (xi_obj = xi_get_obj(itf, ep->v.ctl.id - HSCROLL_CID_CONST)) != NULL)
+  {
+    switch (xi_obj->type)
+    {
+    case XIT_LIST:
+      switch (ep->v.ctl.ci.v.scroll.what)
+      {
+      case SC_LINE_UP:
+  control_event_hscroll(xi_obj, -1, 0);
+  break;
+      case SC_LINE_DOWN:
+  control_event_hscroll(xi_obj, 1, 0);
+  break;
+      case SC_PAGE_UP:
+  control_event_hscroll(xi_obj, XI_SCROLL_PGUP, 0);
+  break;
+      case SC_PAGE_DOWN:
+  control_event_hscroll(xi_obj, XI_SCROLL_PGDOWN, 0);
+  break;
+      case SC_THUMB:
+  {
+    int prop;
+    int rng1, rng2;
+    int pos;
+
+    prop = xvt_sbar_get_proportion(ep->v.ctl.ci.win, HVSCROLL);
+    xvt_sbar_get_range(ep->v.ctl.ci.win, HVSCROLL, &rng1, &rng2);
+    pos = (rng2 - rng1 - prop) ?
+        (int)(ep->v.ctl.ci.v.scroll.pos * 100L / (rng2 - rng1 - prop)) : 0;
+    control_event_hscroll(xi_obj, XI_SCROLL_FIRST, pos);
+    break;
+  }
+      }
+      break;
+    }
+  }
+}
+
+void
+xi_set_trap_obj(XI_OBJ *xi_obj)
+{
+  XI_OBJ *itf;
+  XI_ITF_DATA *itf_data;
+
+  itf = xi_obj->itf;
+  itf_data = itf->v.itf;
+  itf_data->trap_obj = xi_obj;
+  itf_data->trap_explicit = TRUE;
+}
+
+static void
+destroy_controls(XI_OBJ *xi_obj)
+{
+  XI_OBJ * *objp;
+  int i;
+
+  switch (xi_obj->type)
+  {
+  case XIT_LIST:
+    lm_remove_all_rows( (LM_DATA *) xi_obj->v.list->lm, TRUE );
+    break;
+  }
+  objp = xi_obj->children;
+  for (i = xi_obj->nbr_children; i > 0; i--, objp++)
+    destroy_controls(*objp);
+}
+
+static void
+copy_to_clip(XI_OBJ *focus_obj)
+{
+  int b, e;
+  char *buff;
+
+  xi_get_sel(focus_obj, &b, &e);
+  if (b != e)
+  {
+    char *p;
+    long len;
+
+    len = e - b;
+    buff = xi_get_text(focus_obj, NULL, 0);
+    if (xvt_cb_open(TRUE))
+    {
+      if ((p = xvt_cb_alloc_data(len + 1)) != NULL)
+      {
+  gstrncpy(p, &buff[b], (int)len);
+  p[(int)len] = '\0';
+  xvt_cb_put_data(CB_TEXT, NULL, len, (PICTURE)NULL);
+  xvt_cb_free_data();
+      }
+      xvt_cb_close();
+    }
+  }
+}
+
+static void
+update_menus(void)
+{
+  BOOLEAN paste_enable;
+  BOOLEAN cut_or_copy_enable = FALSE;
+  XI_OBJ *itf;
+  XI_ITF_DATA *itfdata;
+  WINDOW win;
+
+  win = xvt_scr_get_focus_vobj();
+  if (win == NULL_WIN || ! xi_is_window(win))
+    return;
+  itf = xi_get_itf(win);
+  itfdata = itf->v.itf;
+  if (itfdata->menu_win != NULL_WIN)
+    win = itfdata->menu_win;
+  if (itfdata->edit_menu)
+  {
+    XI_OBJ *focus_obj;
+
+    paste_enable = xvt_cb_has_format(CB_TEXT, NULL);
+  xvt_menu_set_item_enabled(win, M_EDIT_PASTE, paste_enable);
+  focus_obj = xi_get_focus(itf);
+    if ((focus_obj && (focus_obj->type == XIT_CELL)) ||
+    (focus_obj && (focus_obj->type == XIT_FIELD)))
+      {
+  int s, e;
+
+  xi_get_sel(focus_obj, &s, &e);
+  if (s != e)
+    cut_or_copy_enable = TRUE;
+      }
+    if (paste_enable != itfdata->paste_enable)
+    {
+    xvt_menu_set_item_enabled(win, M_EDIT_PASTE, paste_enable);
+    itfdata->paste_enable = paste_enable;
+  }
+  if (cut_or_copy_enable != itfdata->cut_or_copy_enable)
+  {
+    xvt_menu_set_item_enabled(win, M_EDIT_CUT, cut_or_copy_enable);
+    xvt_menu_set_item_enabled(win, M_EDIT_COPY, cut_or_copy_enable);
+    xvt_menu_set_item_enabled(win, M_EDIT_CLEAR, cut_or_copy_enable);
+    itfdata->cut_or_copy_enable = cut_or_copy_enable;
+  }
+  }
+}
+
+static void
+do_edit_menu(XI_OBJ *itf, EVENT *ep)
+{
+  XI_OBJ *focus_obj;
+  unsigned long attrib = 0L;
+
+  focus_obj = xi_get_focus(itf);
+  if (focus_obj && focus_obj->type != XIT_ITF)
+  {
+    switch (focus_obj->type)
+    {
+    case XIT_FIELD:
+      attrib = xi_get_attrib(focus_obj);
+      break;
+    case XIT_CELL:
+      {
+  XI_OBJ *list, *column;
+  XI_OBJ * *members;
+  int col_nbr, nbr_members;
+
+  list = focus_obj->parent;
+  members = xi_get_member_list(list, &nbr_members);
+  col_nbr = focus_obj->v.cell.column;
+  column = members[col_nbr];
+  attrib = xi_get_attrib(column);
+  break;
+      }
+    }
+    if (attrib & XI_ATR_EDITMENU)
+    {
+      int b, e;
+
+      switch (ep->v.cmd.tag)
+      {
+      case M_EDIT_CUT:
+  copy_to_clip(focus_obj);
+  /* fall through */
+      case M_EDIT_CLEAR:
+  xi_get_sel(focus_obj, &b, &e);
+  if (b != e)
+  {
+    EVENT ev;
+
+    MEMCLEAR(ev);
+    ev.type = E_CHAR;
+    ev.v.chr.ch = K_DEL;
+    xi_event(xi_get_window(itf), &ev);
+  }
+  update_menus();
+  break;
+      case M_EDIT_COPY:
+  copy_to_clip(focus_obj);
+  update_menus();
+  break;
+      case M_EDIT_PASTE:
+  if (focus_obj->type == XIT_FIELD)
+    if (xi_get_txedit(focus_obj) != BAD_TXEDIT)
+      if (xi_get_pref(XI_PREF_MULTILINE_QUICK_PASTE))
+        break;
+  if (xvt_cb_open(FALSE))
+  {
+    char *p;
+    long size;
+
+    if ((p = xvt_cb_get_data(CB_TEXT, NULL, &size)) != NULL)
+    {
+      WINDOW win;
+
+      win = xi_get_window(itf);
+      itf->v.itf->pasting = TRUE;
+      while ( size-- > 0 )
+      {
+        EVENT ev;
+
+        MEMCLEAR(ev);
+        ev.type = E_CHAR;
+        ev.v.chr.ch = (unsigned char)*p++;
+        xi_event(win, &ev);
+        xvt_dwin_update(win);
+      }
+      itf->v.itf->pasting = FALSE;
+    }
+    xvt_cb_close();
+  }
+  update_menus();
+  break;
+      }
+    }
+  }
+}
+
+
+#define RALEN 32
+#define RCT_TOP 0
+#define RCT_LEFT 1
+#define RCT_BOTTOM 2
+#define RCT_RIGHT 3
+
+static BOOLEAN
+bound_rct(RCT *ra, int ra_len, RCT *rct, int which)
+{
+  int i;
+  BOOLEAN b;
+
+  switch (which)
+  {
+  case RCT_TOP:
+    {
+      for (i = 0; i < ra_len; ++i)
+      {
+  if (ra->bottom < rct->bottom && ra->bottom >= rct->top)
+    rct->top = ra->bottom;
+  ++ra;
+      }
+      break;
+    }
+  case RCT_LEFT:
+    {
+      for (i = 0; i < ra_len; ++i)
+      {
+  if (ra->right < rct->right && ra->right >= rct->left)
+    rct->left = ra->right;
+  ++ra;
+      }
+      break;
+    }
+  case RCT_BOTTOM:
+    {
+      for (i = 0; i < ra_len; ++i)
+      {
+  if (ra->top > rct->top && ra->top <= rct->bottom)
+    rct->bottom = ra->top;
+  ++ra;
+      }
+      break;
+    }
+  case RCT_RIGHT:
+    {
+      for (i = 0; i < ra_len; ++i)
+      {
+  if (ra->left > rct->left && ra->left <= rct->right)
+    rct->right = ra->left;
+  ++ra;
+      }
+      break;
+    }
+  }
+  b = (rct->top < rct->bottom && rct->left < rct->right);
+  return b;
+}
+
+
+static void
+draw_all_rects(XI_OBJ *itf)
+{
+  RCT ra[RALEN];
+  RCT rct;
+  int list_len, ra_len, i;
+  XI_OBJ * *child;
+  XI_ITF_DATA *itf_data;
+  int cur_delta_x, cur_delta_y;
+
+#if XIWS == XOLWS || XIWS == MTFWS
+  /* X GRAY SCALE HACK */
+  xi_set_xvt_back_color(itf->v.itf->xvt_win, COLOR_WHITE);
+  {
+    DRAW_CTOOLS ct;
+    WINDOW win = itf->v.itf->xvt_win;
+
+    xi_get_draw_ctools(win, &ct);
+    ct.opaque_text = FALSE;
+    xi_set_draw_ctools(win, &ct);
+    xi_draw_text(win, 0, 0, " ", -1);
+  }
+#endif
+
+  itf_data = itf->v.itf;
+  cur_delta_x = itf_data->delta_x;
+  cur_delta_y = itf_data->delta_y;
+
+  list_len = 0;
+  for (i = 0, child = itf->children; i < itf->nbr_children; ++i, ++child)
+  {
+    if ((*child)->type == XIT_LIST && (xi_get_attrib(*child) & XI_ATR_VISIBLE))
+    {
+      if (list_len < (RALEN - 1))
+      {
+  xi_get_rect((*child), &ra[list_len]);
+  ++list_len;
+      }
+    }
+  }
+  ra_len = list_len;
+  if (list_len)
+  {
+    int cnt;
+
+    for (cnt = 0; cnt < list_len; ++cnt)
+    {
+      RCT lr;
+
+      lr = ra[cnt];
+
+      /* do left rect */
+      rct.left = 0;
+      rct.top = 0;
+      rct.bottom = MAXPIX;
+      rct.right = lr.left;
+      if (bound_rct(ra, ra_len, &rct, RCT_LEFT))
+      {
+  VRCT_TO_PRCT(&rct);
+  xvt_dwin_draw_rect(itf_data->xvt_win, &rct);
+    }
+
+    /* do top rect */
+      rct.left = 0;
+      rct.top = 0;
+      rct.bottom = lr.top;
+      rct.right = MAXPIX;
+      if (bound_rct(ra, ra_len, &rct, RCT_TOP))
+    VRCT_TO_PRCT(&rct);
+    xvt_dwin_draw_rect(itf_data->xvt_win, &rct);
+
+      /* do right rect */
+      rct.left = lr.right;
+      rct.top = 0;
+      rct.bottom = MAXPIX;
+      rct.right = MAXPIX;
+      if (bound_rct(ra, ra_len, &rct, RCT_RIGHT))
+    VRCT_TO_PRCT(&rct);
+    xvt_dwin_draw_rect(itf_data->xvt_win, &rct);
+
+    /* do bottom rect */
+      rct.left = 0;
+      rct.top = lr.bottom;
+      rct.bottom = MAXPIX;
+      rct.right = MAXPIX;
+      if (bound_rct(ra, ra_len, &rct, RCT_BOTTOM))
+    VRCT_TO_PRCT(&rct);
+    xvt_dwin_draw_rect(itf_data->xvt_win, &rct);
+
+  }
+  }
+  else
+  {
+  rct.top = 0;
+  rct.left = 0;
+  rct.bottom = MAXPIX;
+  rct.right = MAXPIX;
+    xvt_dwin_draw_rect(itf_data->xvt_win, &rct);
+  }
+}
+
+
+static void
+draw_background(XI_OBJ *itf)
+{
+  XI_ITF_DATA *itf_data = itf->v.itf;
+  WINDOW win = itf_data->xvt_win;
+
+  if (itf_data->back_color)
+  {
+  DRAW_CTOOLS t;
+  CBRUSH cbrush;
+
+#if (XIWS == PMWS) && (XVT_OS != XVT_OS_CTOS)
+  CBRUSH hollow_cbrush;
+  RCT rct;
+
+  /* Bad bug with XVT/PM, needs this before can draw COLOR_LTGRAY */
+  xvt_app_get_default_ctools(&t);
+  xvt_dwin_set_draw_ctools(win, &t);
+  hollow_cbrush.color = COLOR_WHITE;
+  hollow_cbrush.pat = PAT_HOLLOW;
+  xvt_dwin_set_cbrush(win, &hollow_cbrush);
+  rct.top = 0;
+  rct.left = 0;
+  rct.bottom = 0;
+  rct.right = 0;
+  xvt_dwin_draw_rect(win, &rct);
+#endif
+#if XIWS == XOLWS || XIWS == MTFWS
+  /* X GRAY SCALE HACK */
+  xi_set_xvt_back_color(win, COLOR_WHITE);
+  {
+    DRAW_CTOOLS ct;
+
+    xi_get_draw_ctools(win, &ct);
+    ct.opaque_text = FALSE;
+    xi_set_draw_ctools(win, &ct);
+    xi_draw_text(win, 0, 0, " ", -1);
+  }
+#endif
+
+  xvt_app_get_default_ctools(&t);
+  xi_set_draw_ctools(win, &t);
+  xvt_dwin_set_cpen(win, &hollow_cpen);
+  cbrush.pat = PAT_SOLID;
+  cbrush.color = itf_data->back_color;
+#if XI_IS_CH
+  CTOS_IS_CH;
+  xi_fix_color(&cbrush.color);
+  CTOS_END;
+#endif
+  xvt_dwin_set_cbrush(win, &cbrush);
+  xvt_dwin_set_clip(win, NULL);
+  draw_all_rects(itf);
+  }
+}
+
+
+static void
+do_post_event(XI_OBJ *itf, EVENT *ep)
+{
+  XI_EVENT xiev;
+
+  if (xi_is_itf(itf))
+  {
+    /* send XVT event */
+    MEMCLEAR(xiev);
+    xiev.type = XIE_XVT_POST_EVENT;
+    xiev.v.xvte = *ep;
+    xiev.refused = FALSE;
+    call_cb(itf, &xiev);
+  }
+}
+
+/* ------------------------------------------------------------------------ */
+/* get_text_ctools                                                          */
+/* ------------------------------------------------------------------------ */
+static DRAW_CTOOLS * near
+get_text_ctools(XI_ITF_DATA *itf_data, DRAW_CTOOLS *ct, FONT_OBJ *font)
+{
+  xvt_app_get_default_ctools(ct);
+  ct->pen.color = ct->fore_color = COLOR_BLACK;
+  ct->opaque_text = FALSE;
+  if (itf_data->font)
+  *font = *itf_data->font;
+  else
+    *font = xi_sysfont;
+  return(ct);
+}
+
+/* ------------------------------------------------------------------------ */
+/* xi_draw_obj                                                              */
+/* ------------------------------------------------------------------------ */
+static void near
+xi_draw_obj(XI_OBJ *xi_obj)
+{
+  WINDOW win;
+  XI_ITF_DATA *itf_data;
+
+  itf_data = xi_obj->itf->v.itf;
+  win = itf_data->xvt_win;
+  switch (xi_obj->type)
+  {
+  case XIT_TEXT:
+  {
+    XI_TEXT_DATA *text;
+    DRAW_CTOOLS ct;
+    FONT_OBJ font;
+
+    text = xi_obj->v.text;
+    get_text_ctools(itf_data, &ct, &font);
+    ct.back_color = itf_data->back_color;
+    ct.fore_color = COLOR_BLACK;
+    if (text->fore_color)
+      ct.fore_color = text->fore_color;
+    if (text->back_color)
+      {
+      ct.opaque_text = TRUE;
+      ct.back_color = text->back_color;
+      }
+    xi_set_xvt_font(win, &font, TRUE);
+    if (text->font)
+      xi_set_xvt_font(win, text->font, FALSE);
+    xi_set_draw_ctools(win, &ct);
+    if ((text->attrib & XI_ATR_ENABLED))
+      xi_set_xvt_fore_color(win, ct.fore_color);
+    else
+      xi_set_xvt_fore_color( win,
+        (COLOR)xi_get_pref(XI_PREF_COLOR_DISABLED) );
+    xi_set_xvt_back_color(win, ct.back_color);
+    xi_draw_clipped_text(win, text->text, &text->rct, &text->rct,
+      text->attrib | XI_ATR_VCENTER, FALSE, 0, -1);
+    break;
+  }
+  case XIT_LINE:
+  {
+    XI_LINE_DATA *line;
+    PNT pnt1, pnt2;
+
+    line = xi_obj->v.line;
+    if (line->attrib & XI_ATR_VISIBLE)
+    {
+      pnt1 = line->pnt1;
+      pnt2 = line->pnt2;
+      if ((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK))
+      xi_draw_3d_line(win, pnt1, pnt2, line->well);
+      else
+      {
+      CPEN cpen;
+      cpen = black_cpen;
+      if (line->fore_color)
+        cpen.color = line->fore_color;
+      xi_set_cpen(win, &cpen);
+      if (line->back_color)
+        xi_set_xvt_back_color(win, line->back_color);
+      xi_move_to(win, pnt1);
+      xi_draw_line(win, pnt2);
+      }
+    }
+    break;
+  }
+  case XIT_RECT:
+  {
+    XI_RECT_DATA *rect;
+    RCT rct;
+
+    rect = xi_obj->v.rect;
+    if (rect->attrib & XI_ATR_VISIBLE)
+    {
+      rct = rect->rct;
+      if ((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK))
+      {
+      xi_draw_3d_rect(win, &rct, rect->well, 1,
+          rect->hilight_color, rect->back_color,
+          rect->shadow_color);
+      if (rect->ridge)
+      {
+        xi_inflate_rect(&rct, -1);
+        xi_draw_3d_rect(win, &rct, (BOOLEAN)(! rect->well), 1,
+          rect->hilight_color, rect->back_color,
+          rect->shadow_color);
+      }
+      }
+      else
+      {
+      CPEN cpen;
+      CBRUSH cbrush;
+
+      cpen = black_cpen;
+      if (rect->fore_color)
+        cpen.color = rect->fore_color;
+      xi_set_cpen(win, &cpen);
+      cbrush.pat = PAT_SOLID;
+      cbrush.color = COLOR_WHITE;
+      if (rect->back_color)
+        cbrush.color = rect->back_color;
+      xi_set_cbrush(win, &cbrush);
+      xi_draw_rect(win, &rct);
+      }
+    }
+    break;
+  }
+  default:
+  break;
+  }
+}
+
+/* ------------------------------------------------------------------------ */
+/* draw_field_button                                                        */
+/* ------------------------------------------------------------------------ */
+static void
+draw_field_button(XI_OBJ *xi_obj)
+{
+  XI_FIELD_DATA *fd;
+  unsigned long attrib;
+  STX_DATA *stxd;
+#if XI_IS_NOT_CH
+  int x, y;
+  RCT cr, r;
+#endif
+  WINDOW win;
+
+  attrib = xi_get_attrib(xi_obj);
+  if (! (attrib & XI_ATR_VISIBLE))
+    return;
+  fd = xi_obj->v.field;
+  stxd = (STX_DATA *)fd->stx;
+  win = xi_obj->itf->v.itf->xvt_win;
+  xi_set_draw_mode(win, M_COPY);
+  xi_set_clip(win, NULL);
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  r = fd->btn_rct;
+  r.top++;
+  r.left++;
+  r.bottom--;
+  r.right--;
+#if (XIWS == PMWS) && (XVT_OS != XVT_OS_CTOS)
+  {
+    CBRUSH hollow_cbrush;
+    RCT rct;
+    DRAW_CTOOLS t;
+
+    /* Bad bug with XVT/PM, needs this before can draw COLOR_LTGRAY */
+    xvt_app_get_default_ctools(&t);
+    xvt_dwin_set_draw_ctools(win, &t);
+    hollow_cbrush.color = COLOR_WHITE;
+    hollow_cbrush.pat = PAT_HOLLOW;
+    xvt_dwin_set_cbrush(win, &hollow_cbrush);
+    rct.top = 0;
+    rct.left = 0;
+    rct.bottom = 0;
+    rct.right = 0;
+    xvt_dwin_draw_rect(win, &rct);
+  }
+#endif
+  if ((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK))
+    xi_draw_3d_rect(win, &r, fd->down, 2, stxd->hilight_color,
+  stxd->attrib & XI_ATR_ENABLED ? stxd->back_color : stxd->disabled_back_color, stxd->shadow_color);
+  else
+  {
+    xi_set_cbrush(win, &white_cbrush);
+    xi_set_cpen(win, &hollow_cpen);
+    xi_draw_rect(win, &r);
+  }
+  x = r.left + 3;
+  y = r.top + 2;
+  cr = r;
+  cr.top += 2;
+  cr.left += 2;
+  cr.bottom -= 2;
+  cr.right -= 2;
+  xi_set_clip(win, &cr);
+#if XIWS == PMWS
+  /* Hack for OS2 - Icons are drawn differenty depending on whether
+  opaque_text is set or not in the DRAW_CTOOLS */
+  {
+    DRAW_CTOOLS ct;
+
+    xi_get_draw_ctools(win, &ct);
+    ct.opaque_text = TRUE;
+    ct.back_color = xi_get_pref(XI_PREF_COLOR_CTRL);
+  ct.fore_color = COLOR_BLACK;
+  xi_set_draw_ctools(win, &ct);
+  }
+#endif
+  {
+  int icon_rid;
+
+  icon_rid = fd->icon_rid;
+  if (icon_rid == 0)
+    icon_rid = (int) xi_get_pref( XI_PREF_COMBO_ICON );
+  if (fd->down)
+    xi_draw_icon( win, x, y + 1, icon_rid, COLOR_BLACK,
+      xi_get_pref(XI_PREF_COLOR_CTRL));
+  else
+      xi_draw_icon( win, x, y, icon_rid, COLOR_BLACK,
+        xi_get_pref(XI_PREF_COLOR_CTRL));
+  }
+  xi_set_clip(win, NULL);
+  xi_set_cpen(win, &black_cpen);
+  xi_set_cbrush(win, &hollow_cbrush);
+  xi_draw_rect(win, &fd->btn_rct);
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  NOREF(stxd);
+  {
+    CBRUSH black_cbrush;
+
+    black_cbrush = white_cbrush;
+    black_cbrush.color = COLOR_BLACK;
+    xi_set_clip(win, NULL);
+    xi_set_cpen(win, &hollow_cpen);
+    xi_set_cbrush(win, &black_cbrush);
+    xi_draw_rect(win, &fd->btn_rct);
+  }
+  CTOS_END;
+#endif
+}
+
+/* ------------------------------------------------------------------------ */
+/* field_event                                                              */
+/* ------------------------------------------------------------------------ */
+static void
+field_event(XI_OBJ *xi_obj, EVENT *ep)
+{
+  XI_FIELD_DATA *field_data;
+  RCT rct;
+#if XIWS == MACWS
+  RCT irct;
+  WINDOW win;
+#endif
+
+  field_data = xi_obj->v.field;
+  rct = field_data->btn_rct;
+#if XIWS == MACWS
+  irct = rct;
+  xi_inflate_rect(&irct, -1);
+  win = xi_obj->itf->v.itf->xvt_win;
+#endif
+  switch (ep->type)
+  {
+  case E_CHAR:
+    {
+      long button_key;
+      BOOLEAN shift, control;
+
+      button_key = xi_get_pref(XI_PREF_BUTTON_KEY);
+      shift = (BOOLEAN)((button_key & XI_MOD_SHIFT) != 0);
+      control = (BOOLEAN)((button_key & XI_MOD_CONTROL) != 0);
+      button_key &= 0xffffffL;
+      if (button_key == ep->v.chr.ch &&
+    shift == ep->v.chr.shift &&
+    control == ep->v.chr.control)
+      {
+  XI_EVENT xiev;
+  XI_OBJ *itf;
+
+  MEMCLEAR(xiev);
+  xiev.type = XIE_BUTTON;
+  xiev.v.xi_obj = xi_obj;
+  itf = xi_obj->itf;
+  call_cb(itf, &xiev);
+      }
+      break;
+    }
+  case E_UPDATE:
+    if (field_data->button)
+      draw_field_button(xi_obj);
+    break;
+  case E_MOUSE_DOWN:
+    {
+      unsigned long attrib;
+
+      attrib = stx_get_attrib(xi_obj->v.field->stx);
+      attrib &= (XI_ATR_ENABLED | XI_ATR_VISIBLE);
+      if (field_data->button &&
+    attrib == (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+      {
+  if (xvt_rect_has_point(&rct, ep->v.mouse.where))
+  {
+    field_data->down = TRUE;
+    field_data->down_in_btn = TRUE;
+#if XIWS == MACWS
+    xi_invalidate_rect(win, &irct);
+#else
+    draw_field_button(xi_obj);
+#endif
+    xi_set_trap_obj(xi_obj);
+    xi_trap_mouse(xi_obj->itf->v.itf->xvt_win);
+  }
+      }
+      break;
+    }
+  case E_MOUSE_MOVE:
+    if (field_data->button && field_data->down_in_btn)
+    {
+      if (xvt_rect_has_point(&rct, ep->v.mouse.where) && ! field_data->down)
+      {
+  field_data->down = TRUE;
+#if XIWS == MACWS
+  xi_invalidate_rect(win, &irct);
+#else
+  draw_field_button(xi_obj);
+#endif
+      }
+      if (! xvt_rect_has_point(&rct, ep->v.mouse.where) && field_data->down)
+      {
+  field_data->down = FALSE;
+#if XIWS == MACWS
+  xi_invalidate_rect(win, &irct);
+#else
+  draw_field_button(xi_obj);
+#endif
+      }
+    }
+    break;
+  case E_MOUSE_UP:
+    if (field_data->button && field_data->down_in_btn)
+    {
+      xi_release_mouse();
+      if (field_data->down)
+      {
+  field_data->down = FALSE;
+#if XIWS == MACWS
+  xi_invalidate_rect(win, &irct);
+#else
+  draw_field_button(xi_obj);
+#endif
+      }
+      field_data->down_in_btn = FALSE;
+      if (xvt_rect_has_point(&rct, ep->v.mouse.where))
+      {
+  if (xi_move_focus(xi_obj))
+  {
+    XI_EVENT xiev;
+    XI_OBJ *itf;
+
+    MEMCLEAR(xiev);
+    xiev.type = XIE_BUTTON;
+    xiev.v.xi_obj = xi_obj;
+    itf = xi_obj->itf;
+    call_cb(itf, &xiev);
+  }
+      }
+    }
+    break;
+  }
+}
+/* ------------------------------------------------------------------------ */
+/* form_event                                                               */
+/* ------------------------------------------------------------------------ */
+
+static BOOLEAN near
+form_event(XI_OBJ *xi_obj, EVENT *ep)
+{
+  BOOLEAN retval = FALSE;
+  XI_OBJ *focus_obj = xi_obj->itf->v.itf->focus_obj;
+
+  switch(ep->type)
+  {
+  case E_COMMAND:
+    /* TODO -- navigation */
+    break;
+  case E_CHAR:
+    {
+      long c = event_to_longchar(ep);
+      XI_OBJ *next_obj = NULL;
+
+      /* navigation character event */
+      if ( c == '\r' && xi_obj->itf->v.itf->tab_on_enter
+    && xi_obj->type != XIT_BTN )
+  c = xi_get_pref( XI_PREF_FORM_TAB_CHAR );
+      if ( c == xi_get_pref(XI_PREF_FORM_TAB_CHAR) || c == K_DOWN )
+      {
+  next_obj = xi_find_next_obj(focus_obj, XI_NEXT_FORM_TAB, c);
+      }
+      else
+  if (c == xi_get_pref(XI_PREF_FORM_BACKTAB_CHAR) ||
+      c == K_UP)
+  {
+    next_obj = focus_obj;
+    do {
+      next_obj = xi_find_next_obj(next_obj, XI_NEXT_FORM_BACKTAB, c);
+    } while (next_obj != NULL && next_obj != focus_obj &&
+        (next_obj->type == XIT_FORM || next_obj->type == XIT_CONTAINER));
+  }
+      if (next_obj != NULL)
+      {
+  xi_move_focus_internal(next_obj, TRUE, TRUE,
+      ((c == xi_get_pref(XI_PREF_FORM_TAB_CHAR)) || (c == K_DOWN)) ? 1 : 2);
+  retval = TRUE;
+      }
+      break;
+    }
+  default:
+    break;
+  }
+  return retval;
+}
+/* ------------------------------------------------------------------------ */
+/* invalidate_button_rect                                                   */
+/* ------------------------------------------------------------------------ */
+static void near
+invalidate_button_rect(XI_OBJ *xi_obj, XI_BTN_DATA *bd, RCT *rct)
+{
+  if ((bd->type == XIBT_BUTTON || bd->type == XIBT_BUTTON_CHECKBOX ||
+      bd->type == XIBT_RADIOBTN) && bd->drawable)
+  {
+    RCT r;
+    WINDOW win;
+
+    r = *rct;
+    xi_inflate_rect(&r, -4);
+    win = xi_get_window(xi_obj->itf);
+    xi_invalidate_rect(win, &r);
+    xvt_dwin_update(win);
+  }
+}
+
+/* ------------------------------------------------------------------------ */
+/* btn_event                                                                */
+/* ------------------------------------------------------------------------ */
+static BOOLEAN near
+btn_event(XI_OBJ *xi_obj, EVENT *ep)
+{
+  BOOLEAN enabled;
+  BOOLEAN visible;
+  BOOLEAN focus;
+  BOOLEAN dflt;
+  BOOLEAN send_to_form = TRUE;
+  BOOLEAN ret_val;
+  RCT rct;
+  unsigned long attrib;
+  XI_BTN_DATA *bd;
+
+  if (! (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS))
+  {
+    attrib = xi_get_attrib(xi_obj);
+    enabled = ((attrib & XI_ATR_ENABLED) != 0);
+    visible = ((attrib & XI_ATR_VISIBLE) != 0);
+    focus = (xi_get_focus(xi_obj->itf) == xi_obj);
+    bd = xi_obj->v.btn;
+    dflt = bd->dflt;
+    rct = bd->rct;
+    switch (ep->type)
+    {
+    case E_TIMER:
+      return FALSE;
+    case E_CHAR:
+      if (ep->v.chr.ch == ' ' && focus)
+      {
+  XI_EVENT xiev;
+  XI_OBJ *itf;
+
+  MEMCLEAR(xiev);
+  xiev.type = XIE_BUTTON;
+  xiev.v.xi_obj = xi_obj;
+  itf = xi_obj->itf;
+  call_cb(itf, &xiev);
+  if (! xi_is_itf(itf))
+    send_to_form = FALSE;
+      }
+      break;
+    case E_UPDATE:
+      xi_draw_button(xi_obj, &rct, bd->text, bd->down_icon_rid,
+    bd->up_icon_rid, bd->disabled_icon_rid, enabled,
+    visible, focus, bd->down, dflt, bd->checked, FALSE);
+      break;
+    case E_MOUSE_DBL:
+      if (! xi_get_pref(XI_PREF_DBL_PRESSES_BUTTON))
+  break;
+      /* else fall through */
+    case E_MOUSE_DOWN:
+      {
+  RCT     hit_rct;
+
+  if ((enabled == FALSE)||(visible == FALSE))
+    break;
+  hit_rct     = rct;
+  if (bd->packed == TRUE)
+    xi_inflate_rect(&hit_rct,
+        -((int)xi_get_pref(XI_PREF_CONTAINER_GRID_WIDTH)));
+  if (xvt_rect_has_point(&hit_rct, ep->v.mouse.where))
+  {
+    bd->down = TRUE;
+    bd->down_in_btn = TRUE;
+    xi_draw_button(xi_obj, &rct, bd->text, bd->down_icon_rid,
+        bd->up_icon_rid, bd->disabled_icon_rid, enabled,
+        visible, focus, bd->down, dflt, bd->checked, FALSE);
+    invalidate_button_rect(xi_obj, bd, &rct);
+    xi_set_trap_obj(xi_obj);
+    xi_trap_mouse(xi_get_window(xi_obj->itf));
+  }
+  break;
+      }
+    case E_MOUSE_MOVE:
+      if (bd->down_in_btn)
+      {
+  if (xvt_rect_has_point(&rct, ep->v.mouse.where) && ! bd->down)
+  {
+    bd->down = TRUE;
+    xi_draw_button(xi_obj, &rct, bd->text, bd->down_icon_rid,
+        bd->up_icon_rid, bd->disabled_icon_rid,
+        enabled, visible, focus, bd->down, dflt,
+        bd->checked, FALSE);
+    invalidate_button_rect(xi_obj, bd, &rct);
+  }
+  else if (! xvt_rect_has_point(&rct, ep->v.mouse.where) &&
+      bd->down)
+  {
+    bd->down = FALSE;
+    xi_draw_button(xi_obj, &rct, bd->text, bd->down_icon_rid,
+        bd->up_icon_rid, bd->disabled_icon_rid,
+        enabled, visible, focus, bd->down, dflt,
+        bd->checked, FALSE);
+    invalidate_button_rect(xi_obj, bd, &rct);
+  }
+      }
+      break;
+    case E_MOUSE_UP:
+      if (bd->down_in_btn)
+      {
+  bd->down_in_btn = FALSE;
+  if (bd->down)
+  {
+    bd->down = FALSE;
+    xi_draw_button(xi_obj, &rct, bd->text, bd->down_icon_rid,
+        bd->up_icon_rid, bd->disabled_icon_rid,
+        enabled, visible, focus, bd->down, dflt,
+        bd->checked, FALSE);
+    invalidate_button_rect(xi_obj, bd, &rct);
+  }
+  xi_release_mouse();
+  if (ep->type == E_MOUSE_UP &&
+      xvt_rect_has_point(&rct, ep->v.mouse.where))
+  {
+    XI_EVENT xiev;
+    XI_OBJ *itf;
+
+    MEMCLEAR(xiev);
+    xiev.type = XIE_BUTTON;
+    xiev.v.xi_obj = xi_obj;
+    itf = xi_obj->itf;
+    call_cb(itf, &xiev);
+    if (! xi_is_itf(itf))
+      send_to_form = FALSE;
+  }
+      }
+      break;
+    }
+  }
+  ret_val = TRUE;
+  if (send_to_form)
+    ret_val = form_event(xi_obj, ep);
+  return ret_val;
+}
+/* ------------------------------------------------------------------------ */
+/* draw_list_button                                                         */
+/* ------------------------------------------------------------------------ */
+#define P_OFFSET 3
+static void
+draw_list_button(WINDOW win, RCT *rct, BOOLEAN down)
+{
+#if XI_IS_NOT_CH
+  int x, y, plus_width, plus_height;
+  PNT p;
+  RCT r;
+  BOOLEAN x2;
+
+  CTOS_IS_PM;
+  r = *rct;
+  xi_set_cpen(win, &black_cpen);
+  xi_set_cbrush(win, &hollow_cbrush);
+  xi_draw_rect(win, &r);
+  r.top++;
+  r.left++;
+  r.bottom--;
+  r.right--;
+  if ((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK))
+    xi_draw_3d_rect(win, &r, down, 2, 0L, 0L, 0L);
+  else
+  {
+    xi_set_cbrush(win, &white_cbrush);
+    xi_draw_rect(win, &r);
+  }
+
+  p.h = rct->left;
+  p.v = rct->top - 1;
+  xi_set_cpen(win, &black_cpen);
+  xi_move_to(win, p);
+  p.h = rct->right;
+  xi_draw_line(win, p);
+
+  plus_width = r.right - r.left;
+  plus_height = plus_width + 4;
+  x = r.left + plus_width / 2;
+  y = r.top + plus_height / 2;
+  x2 = ! ((r.right + r.left) % 2);
+  if (x2)
+    x--;
+  y--;
+  xi_set_cpen(win, &black_cpen);
+
+  /*
+  draw vertical lines
+  */
+  p.h = x;
+  p.v = r.top + P_OFFSET + down;
+  xi_move_to(win, p);
+  p.v = r.top + plus_height - P_OFFSET + down;
+  xi_draw_line(win, p);
+  p.h = x + 1;
+  p.v = r.top + P_OFFSET + down;
+  xi_move_to(win, p);
+  p.v = r.top + plus_height - P_OFFSET + down;
+  xi_draw_line(win, p);
+
+  /*
+  draw horizontal lines
+  */
+  p.v = y + down;
+  p.h = r.left + P_OFFSET;
+  xi_move_to(win, p);
+  p.h = r.left + plus_width - P_OFFSET;
+  xi_draw_line(win, p);
+  p.v = y + down + 1;
+  p.h = r.left + P_OFFSET;
+  xi_move_to(win, p);
+  p.h = r.left + plus_width - P_OFFSET;
+  xi_draw_line(win, p);
+  CTOS_END;
+#endif
+  NOREF(rct);
+  NOREF(down);
+  NOREF(win);
+}
+
+/* ------------------------------------------------------------------------ */
+/* list_event                                                               */
+/* ------------------------------------------------------------------------ */
+static void
+list_event(XI_OBJ *xi_obj, EVENT *ep)
+{
+  XI_LIST_DATA *list_data;
+  RCT rct;
+  LM_DATA *lmp;
+
+  list_data = xi_obj->v.list;
+  lmp = (LM_DATA *)list_data->lm;
+  if (lmp->attrib & XI_ATR_VISIBLE)
+  {
+    rct = list_data->sbb_rct;
+    switch (ep->type)
+    {
+    case E_UPDATE:
+      if (list_data->scroll_bar_button)
+  draw_list_button(lmp->win, &rct, list_data->down);
+      break;
+    case E_MOUSE_DOWN:
+      if (list_data->scroll_bar_button)
+      {
+  if (xvt_rect_has_point(&rct, ep->v.mouse.where))
+  {
+    list_data->down = TRUE;
+    list_data->down_in_btn = TRUE;
+    draw_list_button(lmp->win, &rct, TRUE);
+    xi_set_trap_obj(xi_obj);
+    xi_trap_mouse(xi_obj->itf->v.itf->xvt_win);
+  }
+      }
+      break;
+    case E_MOUSE_MOVE:
+      if (list_data->scroll_bar_button && list_data->down_in_btn)
+      {
+  if (xvt_rect_has_point(&rct, ep->v.mouse.where) && ! list_data->down)
+  {
+    list_data->down = TRUE;
+    draw_list_button(lmp->win, &rct, TRUE);
+  }
+  if (! xvt_rect_has_point(&rct, ep->v.mouse.where) && list_data->down)
+  {
+    list_data->down = FALSE;
+    draw_list_button(lmp->win, &rct, FALSE);
+  }
+      }
+      break;
+    case E_MOUSE_UP:
+      if (list_data->scroll_bar_button && list_data->down_in_btn)
+      {
+  xi_release_mouse();
+  if (list_data->down)
+  {
+    list_data->down = FALSE;
+    draw_list_button(lmp->win, &rct, FALSE);
+  }
+  list_data->down_in_btn = FALSE;
+  if (xvt_rect_has_point(&rct, ep->v.mouse.where))
+  {
+    XI_EVENT xiev;
+    XI_OBJ *itf;
+
+    MEMCLEAR(xiev);
+    xiev.type = XIE_BUTTON;
+    xiev.v.xi_obj = xi_obj;
+    itf = xi_obj->itf;
+    call_cb(itf, &xiev);
+  }
+      }
+      break;
+    }
+  }
+}
+
+/* ------------------------------------------------------------------------ */
+/* itf_event                                                                */
+/* ------------------------------------------------------------------------ */
+static BOOLEAN near
+itf_event(XI_OBJ *xi_obj, EVENT *ep)
+{
+  BOOLEAN retval = FALSE;
+  XI_ITF_DATA *itf_data;
+  XI_OBJ *focus_obj;
+
+  itf_data = xi_obj->itf->v.itf;
+  focus_obj = itf_data->focus_obj;
+  switch(ep->type)
+  {
+  case E_COMMAND:
+    /* TODO -- navigation */
+    break;
+  case E_CHAR:
+    {
+      long c = event_to_longchar(ep);
+      XI_OBJ *next_obj = NULL;
+
+    xvt_errmsg_sig_if(!(focus_obj->itf == xi_obj), NULL_WIN,
+      SEV_FATAL, ERR_ASSERT_4, "20030", 20030,
+      "Internal focus error");   
+
+      /* navigation character event */
+      if (c == xi_get_pref(XI_PREF_ITF_TAB_CHAR))
+  next_obj = xi_find_next_obj(focus_obj, XI_NEXT_ITF_TAB, c);
+      else
+  if (c == xi_get_pref(XI_PREF_ITF_BACKTAB_CHAR))
+    next_obj = xi_find_next_obj(focus_obj, XI_NEXT_ITF_BACKTAB,
+        c);
+  else
+    if (c == xi_get_pref(XI_PREF_FORM_TAB_CHAR) &&
+        focus_obj->type == XIT_ITF)
+      next_obj = xi_search_itf(focus_obj, XI_SEARCH_FOR_FOCUSABLE,
+    0);
+      if (c == '\r')
+      {
+  XI_OBJ *dflt_obj;
+
+  dflt_obj = xi_get_default(xi_obj->itf);
+  if (dflt_obj && (xi_get_attrib(dflt_obj) & (XI_ATR_ENABLED
+      | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+  {
+    XI_EVENT xiev;
+    XI_OBJ *itf;
+
+    MEMCLEAR(xiev);
+    xiev.type = XIE_BUTTON;
+    xiev.v.xi_obj = dflt_obj;
+    itf = xi_obj->itf;
+    call_cb(itf, &xiev);
+    retval = TRUE;
+  }
+      }
+      if (next_obj != NULL)
+      {
+  xi_move_focus_internal(next_obj, TRUE, FALSE, 0);
+  retval = TRUE;
+      }
+      break;
+    }
+  default:
+    break;
+  }
+  return(retval);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* xi_send_event                                                            */
+/* ------------------------------------------------------------------------ */
+
+static int
+xi_send_event(XI_OBJ *xi_obj, EVENT *ep, BOOLEAN do_subtree)
+{
+  int n;
+  XI_OBJ * *objlist;
+  BOOLEAN send_to_parent = FALSE;
+  int retval = 0;
+
+  switch(xi_obj->type)
+  {
+  case XIT_RECT:
+  case XIT_TEXT:
+  case XIT_LINE:
+  if (ep->type == E_UPDATE)
+    xi_draw_obj(xi_obj);
+  break;
+  case XIT_FIELD:
+  field_event(xi_obj, ep);
+  retval = stx_event(xi_obj->v.field->stx, ep);
+  send_to_parent = !retval;
+
+    /* don't send any character events (for navigation to the parent if pasting */
+    if (ep->type == E_CHAR && xi_obj->itf->v.itf->pasting)
+      send_to_parent = FALSE;
+    break;
+  case XIT_CONTAINER:
+    send_to_parent = TRUE;
+    break;
+  case XIT_FORM:
+    send_to_parent = !form_event(xi_obj, ep);
+    break;
+  case XIT_BTN:
+    send_to_parent = !btn_event(xi_obj, ep);
+    break;
+  case XIT_LIST:
+  {
+    XI_OBJ *itf;
+
+    itf = xi_obj->itf;
+    if (xi_obj->itf->v.itf->update_obj)
+    {
+      lm_event(xi_obj->v.list->lm, ep);
+      send_to_parent = FALSE;
+      do_subtree = FALSE;
+    }
+    else
+    {
+      list_event(xi_obj, ep);
+      retval = lm_event(xi_obj->v.list->lm, ep);
+      send_to_parent = !retval;
+      /* Don't broadcast events to columns */
+      do_subtree = FALSE;
+    }
+    if (xi_is_itf(itf))
+      if (xi_obj->itf->v.itf->pasting)
+  send_to_parent = FALSE;
+    break;
+  }
+  case XIT_ITF:
+    itf_event(xi_obj, ep);
+    break;
+  case XIT_CELL:
+    /* Send events to list as there is no handler for individual cells */
+    send_to_parent = TRUE;
+    break;
+  case XIT_COLUMN:
+  default:
+    /* ignored */
+    break;
+  }
+    if (do_subtree && xi_obj->type != XIT_GROUP)
+    {
+      int retval;
+
+      /* loop over sub-objects */
+      objlist = xi_get_member_list(xi_obj, &n);
+      for (; n > 0; n--, objlist++)
+      {
+  retval = xi_send_event(*objlist, ep, do_subtree);
+  if (retval)
+  {
+    return retval;
+  }
+      }
+    }
+  if (send_to_parent)
+  {
+    retval = xi_send_event(xi_obj->parent, ep, FALSE);
+    return retval;
+  }
+  return retval;
+}
+
+void
+xi_event(WINDOW win, EVENT *ep)
+{
+  XI_OBJ *itf;
+  XI_EVENT xiev;
+  XI_ITF_DATA *itf_data;
+  BOOLEAN retval;
+  CURSOR new_cursor;
+
+  if (win == NULL_WIN)
+  win = xvt_scr_get_focus_vobj();
+  if (win == NULL_WIN || ((itf = xi_get_itf(win)) == NULL))
+    return;
+  itf_data = itf->v.itf;
+
+  /* send XVT event */
+  MEMCLEAR(xiev);
+  xiev.type = XIE_XVT_EVENT;
+  xiev.v.xvte = *ep;
+  xiev.refused = FALSE;
+  if (!call_cb(itf, &xiev))
+    return;
+  if (xiev.refused)
+    return;
+
+  *ep = xiev.v.xvte;
+
+  if (ep->type == E_MOUSE_UP)
+    xi_release_mouse();
+
+  if (! xi_eh(win, ep))
+    return;
+  if (ep->type == E_UPDATE)
+  xi_dequeue();
+
+#if (XIWS == PMWS) || (XIWS == MTFWS) || (XIWS == XOLWS) || (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS)
+#if (XIWS == MACWS)
+  if (xi_modal_win && ep->type == E_FOCUS && (! ep->v.active) && win == xi_modal_win)
+  {
+  xvt_scr_set_focus_vobj(xi_modal_win);
+  xvt_vobj_raise(xi_modal_win);          
+  }
+#else
+  if (xi_modal_win && ep->type == E_FOCUS && ep->v.active && win != xi_modal_win)
+  {
+  xvt_scr_set_focus_vobj(xi_modal_win);
+  xvt_vobj_raise(xi_modal_win);          
+  }
+#endif
+  if (xi_modal_win && win != xi_modal_win && xvt_vobj_get_parent(win) != xi_modal_win && ep->type != E_UPDATE && ep->type != E_TIMER)
+    return;
+#endif
+
+
+  MEMCLEAR(xiev);
+  switch (ep->type)
+  {
+  case E_TIMER:
+    {
+      xi_send_event(itf, ep, TRUE);
+      break;
+    }
+  case E_UPDATE:
+    {
+      if (itf_data->update_obj)
+      {
+  xi_send_event(itf_data->update_obj, ep, FALSE);
+  itf_data->update_obj = NULL;
+      }
+      else
+      {
+  itf->v.itf->half_baked = FALSE;
+  draw_background(itf);
+  xi_send_event(itf, ep, TRUE);
+      }
+      break;
+    }
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+    {
+      XI_OBJ *itf2;
+
+      itf2 = itf;
+      itf_data->mouse_is_down = TRUE;
+      xi_send_event(itf, ep, TRUE);
+      if (xi_is_itf(itf2))
+  if (! itf_data->trap_explicit)
+    itf_data->trap_obj = itf_data->focus_obj;
+      break;
+    }
+  case E_CHAR:
+#if XIWS == WINWS
+    if (ep->v.chr.ch == '\t' && ep->v.chr.shift)
+      /* ignore bogus shift-tab from XVT */
+      break;
+#endif
+#if XVT_OS != XVT_OS_CTOS
+#if XIWS == WMWS
+    /* TODO ep->v.chr.shift and ep->v.chr.control are not set properly for XVT/CH */
+    ep->v.chr.shift = FALSE;
+    ep->v.chr.control = FALSE;
+#endif
+#endif
+    if (ep->v.chr.ch == K_BTAB)
+      ep->v.chr.shift = FALSE;
+    if (itf_data->focus_obj != NULL)
+      xi_send_event(itf_data->focus_obj, ep, FALSE);
+    update_menus();
+    break;
+  case E_SIZE:
+    xi_send_event(itf, ep, TRUE);
+    break;
+  case E_MOUSE_UP:
+#ifndef NO_PRIMARY_SELECTION
+#if XIWS == MTFWS
+    if (ep->v.mouse.button == 2)
+      get_primary_selection(itf, win);
+#endif
+#endif
+    itf_data->mouse_is_down = FALSE;
+    if (itf_data->trap_obj != NULL)
+      xi_send_event(itf_data->trap_obj, ep, FALSE);
+    if (xi_is_itf(itf))
+    {
+      itf_data->trap_obj = NULL;
+      itf_data->trap_explicit = FALSE;
+      update_menus();
+    }
+    break;
+  case E_MOUSE_MOVE:
+    if (itf_data->trap_obj != NULL)
+      xi_send_event(itf_data->trap_obj, ep, FALSE);
+    else
+    {
+      if (! itf_data->mouse_is_down)
+      {
+  retval = xi_send_event(itf, ep, TRUE);
+  switch(retval)
+  {
+  case 0:
+    new_cursor = CURSOR_ARROW;
+    break;
+  case 1:
+    new_cursor = CURSOR_IBEAM;
+    break;
+  case 2:
+    new_cursor =
+        (CURSOR)xi_get_pref(XI_PREF_SIZE_CURSOR_RID);
+    break;
+  case 3:
+    new_cursor =
+        (CURSOR)xi_get_pref(XI_PREF_HAND_CURSOR_RID);
+    break;
+  case 4:
+    new_cursor = CURSOR_CROSS;
+    break;
+  case 5:
+    new_cursor = CURSOR_ARROW;
+    break;
+  case 6:
+    new_cursor =
+        (CURSOR)xi_get_pref(XI_PREF_VSIZE_CURSOR_RID);
+    break;
+  }
+  if (itf_data->cursor != new_cursor)
+  {
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    xvt_win_set_cursor(itf_data->xvt_win, new_cursor);
+    CTOS_END;
+#endif
+    itf_data->cursor = new_cursor;
+  }
+      }
+    }
+    break;
+  case E_COMMAND:
+    {
+      WINDOW win;
+
+      xiev.v.cmd.tag = ep->v.cmd.tag;
+      xiev.v.cmd.shift = ep->v.cmd.shift;
+      xiev.v.cmd.control = ep->v.cmd.control;
+      xiev.type = XIE_COMMAND;
+      win = itf_data->xvt_win;
+      call_cb(itf, &xiev);
+      if (xi_is_window(win))
+  if (itf_data->focus_obj != NULL)
+    xi_send_event(itf_data->focus_obj, ep, FALSE);
+    }
+    if (xi_is_itf(itf))
+      do_edit_menu(itf, ep);
+    break;
+  case E_ACTIVATE:
+    update_menus();
+    break;
+  case E_KILL_WINDOW:
+    {
+    XI_ITF_DATA *itf_data;
+      int i;
+    destroy_controls(itf);
+    xvt_tx_process_event(win, ep);
+      xiev.type = XIE_CLEANUP;
+      xiev.v.xi_obj = itf;
+      call_cb(itf, &xiev);
+      xi_remove_window_from_list(win);
+
+    itf_data = itf->v.itf;
+    for (i = 0; i < itf_data->nbr_font_ids; ++i)
+    xvt_font_destroy(itf_data->font_ids[i]);
+
+    /* free the whole interface tree */
+    xi_tree_free((char *)itf);
+      break;
+    }
+  case E_CLOSE:
+    xiev.type = XIE_CLOSE;
+    xiev.v.xi_obj = itf;
+    call_cb(itf, &xiev);
+    if (!xiev.refused)
+      xi_close_window_internal(itf);
+    break;
+  case E_QUIT:
+    if (ep->v.query)
+      xvt_app_allow_quit();
+    else
+      xi_terminate();
+    break;
+  case E_HSCROLL:
+  case E_VSCROLL:
+    /* handle E_HSCROLL, etc if list is using window scroll bars */
+    break;
+  case E_CONTROL:
+    control_event(itf, win, ep);
+    update_menus();
+    break;
+  }
+
+  if (ep->type == E_UPDATE)
+  {
+    /* send XVT event */
+    MEMCLEAR(xiev);
+    xiev.type = XIE_UPDATE;
+    xiev.v.xvte = *ep;
+    xiev.refused = FALSE;
+    call_cb(itf, &xiev);
+    xvt_dwin_set_clip(xi_get_window(itf), NULL);
+  }
+
+  do_post_event(itf, ep);
+}
+
+long
+xi_get_app_data(XI_OBJ *xi_obj)
+{
+  return(xi_obj->app_data);
+}
+
+long
+xi_get_app_data2(XI_OBJ *xi_obj)
+{
+  return(xi_obj->app_data2);
+}
+
+unsigned long xi_get_attrib(XI_OBJ *xi_obj)
+{
+  switch(xi_obj->type)
+  {
+  case XIT_COLUMN:
+    return (lm_get_attrib(xi_obj->parent->v.list->lm, LM_COLUMN,
+      xi_obj_to_idx(xi_obj), 0, FALSE));
+  case XIT_LIST:
+    return (lm_get_attrib(xi_obj->v.list->lm, LM_LIST, 0, 0, FALSE));
+  case XIT_ROW:
+    return (lm_get_attrib(xi_obj->parent->v.list->lm, LM_ROW,
+      xi_obj->v.row, 0, FALSE));
+  case XIT_CELL:
+    return (lm_get_attrib( xi_obj->parent->v.list->lm, LM_CELL,
+        xi_obj->v.cell.row, xi_obj->v.cell.column,
+        xi_obj->v.cell.is_vert_scrolled ));
+  case XIT_BTN:
+    return(xi_obj->v.btn->attrib);
+  case XIT_CONTAINER:
+    /*
+      pretend that containers have attributes, and that they are always
+      visible and enabled
+      */
+    return XI_ATR_ENABLED | XI_ATR_VISIBLE;
+  case XIT_FORM:
+    return(xi_obj->v.form->attrib);
+  case XIT_FIELD:
+    return(stx_get_attrib(xi_obj->v.field->stx));
+  case XIT_TEXT:
+    return(xi_obj->v.text->attrib);
+  case XIT_LINE:
+    return(xi_obj->v.line->attrib);
+  case XIT_RECT:
+    return(xi_obj->v.rect->attrib);
+  case XIT_GROUP:
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20018", 20018,
+    "Invalid object passed to xi_get_attrib");   
+  }
+  return 0L;
+}
+
+XI_OBJ *
+xi_get_focus(XI_OBJ *itf)
+{
+  WINDOW win;
+
+  if (itf != NULL)
+    return(itf->v.itf->focus_obj);
+  else if ((win = xvt_scr_get_focus_vobj()) == NULL_WIN)
+  return(NULL);
+  else if (xi_is_window(win))
+  {
+    XI_OBJ *itf;
+
+    itf = xi_get_itf(win);
+    return(itf->v.itf->focus_obj);
+  }
+  else
+    return(NULL);
+}
+
+long *
+xi_get_list_info(XI_OBJ *xi_obj, int *nbr_recs)
+{
+  xvt_errmsg_sig_if(!(xi_obj->type == XIT_LIST), NULL_WIN,
+    SEV_FATAL, ERR_ASSERT_4, "20020", 20020,
+    "Non-list object passed to xi_get_list_info");   
+  return lm_get_list_info(xi_obj->v.list->lm, nbr_recs);
+}
+
+XI_OBJ * *
+xi_get_member_list(XI_OBJ *xi_obj, int *nbr_members)
+{
+  int i;
+  XI_OBJ *obj;
+  XI_GROUP_DATA *groupdata;
+
+  if (xi_obj->type == XIT_GROUP)
+  {
+    groupdata = xi_obj->v.group;
+    if (groupdata->objlist != NULL)
+      xi_tree_free(groupdata->objlist);
+    groupdata->objlist =
+  (XI_OBJ * *)xi_tree_malloc(sizeof(XI_OBJ *) * groupdata->nbr_cids, xi_obj);
+    *nbr_members = 0;
+    for (i = 0; i < groupdata->nbr_cids; i++)
+    {
+      obj = xi_get_obj(xi_obj->itf, groupdata->cidlist[i]);
+      if (obj != NULL)
+      {
+  groupdata->objlist[*nbr_members] = obj;
+  (*nbr_members)++;
+      }
+    }
+    return(groupdata->objlist);
+  }
+  else
+    {
+      *nbr_members = xi_obj->nbr_children;
+      return(xi_obj->children);
+    }
+}
+
+/*
+xi_get_obj: retrieve an XI_OBJ from the interface tree given its cid.
+Although externally documented to work only on XIT_ITF,
+this will start searching at any point in the interface tree.
+
+xi_get_obj will ignore NULL objects so it can be used in the middle
+of creating an interface tree.
+*/
+XI_OBJ *
+xi_get_obj(XI_OBJ *obj, int cid)
+{
+  XI_OBJ * *objlist;
+  XI_OBJ *temp;
+  int n;
+
+  if (obj->cid == cid)
+  return(obj);
+  switch (obj->type)
+  {
+  case XIT_GROUP:
+  case XIT_CELL:
+  case XIT_ROW:
+  return(NULL);
+  default:
+  break;
+  }
+
+  /* search in child list */
+  objlist = xi_get_member_list(obj, &n);
+  for (; n > 0; n--, objlist++)
+  {
+  /* call recursively for generality in future versions */
+  if ((temp = xi_get_obj(*objlist, cid)) != NULL)
+    return(temp);
+  }
+  xvt_errmsg_sig_if(!(!(BOOLEAN)xi_get_pref(XI_PREF_ASSERT_ON_NULL_CID)),
+      NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"30207", 30207,
+      "xi_get_obj: Invalid cid");   
+  return(NULL);
+}
+
+RCT *
+xi_get_rect(XI_OBJ *xi_obj, RCT *rctp)
+{
+  return xi_get_rect_internal(xi_obj, rctp, NULL, NULL);
+}
+
+RCT *
+xi_get_rect_internal(XI_OBJ *xi_obj, RCT *rctp, RCT *old_win_rct, RCT *new_win_rct)
+{
+  XI_OBJ * *objp;
+  RCT rct;
+  int i, n;
+
+  switch(xi_obj->type)
+  {
+  case XIT_CONTAINER:
+    *rctp = xi_obj->v.container->rct;
+    break;
+  case XIT_BTN:
+    *rctp = xi_obj->v.btn->rct;
+    break;
+  case XIT_COLUMN:
+    lm_get_rect(xi_obj->parent->v.list->lm, LM_COLUMN,
+  xi_obj_to_idx(xi_obj), rctp);
+    break;
+  case XIT_ROW:
+    lm_get_rect(xi_obj->parent->v.list->lm, LM_ROW,
+  xi_obj->v.row, rctp);
+    break;
+  case XIT_LIST:
+    lm_get_rect(xi_obj->v.list->lm, LM_LIST, 0, rctp);
+    if (xi_obj->v.list->scroll_bar)
+    {
+      xi_get_sb_rect(xi_obj, &rct);
+      rctp->right = rct.right;
+    }
+    if (xi_obj->v.list->width)
+    {
+      xi_get_hsb_rect(xi_obj, &rct);
+      rctp->bottom = rct.bottom;
+    }
+    if (old_win_rct)
+    {
+      rctp->bottom = (int)((long)rctp->bottom * new_win_rct->bottom / old_win_rct->bottom);
+      rctp->right = (int)((long)rctp->right * new_win_rct->right / old_win_rct->right);
+    }
+    break;
+  case XIT_ITF:
+  case XIT_FORM:
+    {
+      BOOLEAN first_rect = TRUE;
+
+      objp = xi_obj->children;
+      n = xi_obj->nbr_children;
+      for (i = 0; i < n; objp++, i++)
+      {
+  if (xi_get_rect_internal(*objp, &rct, old_win_rct, new_win_rct) != NULL)
+  {
+    if (first_rect)
+    {
+      first_rect = FALSE;
+      *rctp = rct;
+    }
+    else
+      xi_get_enclosing_rect(rctp, &rct, rctp);
+  }
+      }
+      break;
+    }
+  case XIT_FIELD:
+  {
+    XI_FIELD_DATA *fd;
+
+    fd = xi_obj->v.field;
+    stx_get_rect(fd->stx, rctp);
+    if (fd->button)
+    {
+      if (fd->button_on_left)
+  rctp->left = fd->btn_rct.left;
+      else
+  rctp->right = fd->btn_rct.right;
+    }
+    break;
+  }
+  case XIT_TEXT:
+    *rctp = xi_obj->v.text->rct;
+    break;
+  case XIT_RECT:
+    *rctp = xi_obj->v.rect->rct;
+    break;
+  case XIT_LINE:
+    {
+      XI_LINE_DATA *line;
+
+      line = xi_obj->v.line;
+      rctp->top = min(line->pnt1.v, line->pnt2.v);
+      rctp->bottom = max(line->pnt1.v, line->pnt2.v);
+      rctp->left = min(line->pnt1.h, line->pnt2.h);
+      rctp->right = max(line->pnt1.h, line->pnt2.h);
+      break;
+    }
+  case XIT_GROUP:
+    /* bounding rect is undefined */
+    return(NULL);
+  case XIT_CELL:
+    {
+      XI_OBJ row;
+      XI_OBJ *col;
+      XI_OBJ * *members;
+      int nbr_members;
+      int row_nbr, col_nbr;
+      RCT row_rct, col_rct;
+
+      if (xi_obj->v.cell.is_vert_scrolled)
+  memset( (char *)rctp, 0, sizeof(*rctp) );
+      else
+      {
+  row_nbr = xi_obj->v.cell.row;
+  col_nbr = xi_obj->v.cell.column;
+      XI_MAKE_ROW(&row, xi_obj->parent, row_nbr);
+  xi_get_rect_internal(&row, &row_rct, old_win_rct, new_win_rct);
+  members = xi_get_member_list(xi_obj->parent, &nbr_members);
+  col = members[col_nbr];
+  xi_get_rect_internal(col, &col_rct, old_win_rct, new_win_rct);
+  xi_rect_intersect(rctp, &row_rct, &col_rct);
+      }
+      break;
+    }
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4,"20021", 20021,
+      "xi_get_rect: Invalid XI_OBJ_TYPE in tree");   
+  }
+  return(rctp);
+}
+
+void xi_get_sel(XI_OBJ *xi_obj, int *selstart, int *selstop)
+{
+  XI_OBJ *focus_obj;
+  BOOLEAN is_focus;
+
+  focus_obj = xi_get_focus(xi_obj->itf);
+  /* check if the passed object is the focus object */
+  if ( focus_obj == NULL )
+    is_focus = FALSE;              /* no focus */
+  else if ( focus_obj == xi_obj )
+    is_focus = TRUE;               /* object is the focus object */
+  else if ( focus_obj->type != XIT_CELL || xi_obj->type != XIT_CELL )
+    is_focus = FALSE;              /* objects are not both cells */
+  else /* both objects are temporary cell objects */
+    is_focus = ( xi_obj->v.cell.row == focus_obj->v.cell.row
+    && xi_obj->v.cell.column == focus_obj->v.cell.column
+    && !focus_obj->v.cell.is_vert_scrolled );
+  /* it's the focus if the row & column are */
+  /* the same */
+  if ( !is_focus )
+  {
+    /* selection is only valid for focus object */
+    *selstart = *selstop = 0;
+    return;
+  }
+  switch(xi_obj->type)
+  {
+  case XIT_CELL:
+    lm_get_sel(xi_obj->parent->v.list->lm, selstart, selstop);
+    break;
+  case XIT_FIELD:
+    stx_get_sel(xi_obj->v.field->stx, selstart, selstop);
+    break;
+  case XIT_COLUMN:
+  case XIT_ITF:
+  case XIT_LIST:
+  case XIT_ROW:
+  case XIT_BTN:
+  case XIT_FORM:
+  case XIT_GROUP:
+  case XIT_TEXT:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20022", 20022,
+    "Invalid object passed to xi_get_sel");   
+    break;
+  }
+}
+
+TXEDIT
+xi_get_txedit(XI_OBJ *xi_obj)
+{
+  return stx_get_txedit(xi_obj->v.field->stx);
+}
+
+char* xi_get_text(XI_OBJ *xi_obj, char *s, int len)
+{
+  static char buf[100];
+  char *b;
+
+  b = NULL;
+  switch(xi_obj->type)
+  {
+  case XIT_CELL:
+    b = lm_get_text(xi_obj->parent->v.list->lm, s, len,
+  xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled);
+    break;
+  case XIT_COLUMN:
+    b = lm_get_text( xi_obj->parent->v.list->lm, s, len,
+        LM_HEADING_TEXT, xi_obj_to_idx(xi_obj), FALSE );
+    break;
+  case XIT_ITF:
+    xvt_vobj_get_title(xi_obj->v.itf->xvt_win, buf, sizeof(buf));
+    b = buf;
+    break;
+  case XIT_ROW:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20023", 20023,
+    "xi_get_text not implemented for XIT_ROW");   
+  case XIT_BTN:
+    b = xi_obj->v.btn->text;
+    break;
+  case XIT_FIELD:
+    b = stx_get_text(xi_obj->v.field->stx, s, len);
+    break;
+  case XIT_TEXT:
+    {
+      XI_TEXT_DATA *text_data;
+
+      text_data = xi_obj->v.text;
+      b = text_data->text;
+    }
+    break;
+  case XIT_LIST:
+  case XIT_GROUP:
+  case XIT_FORM:
+    if (s)
+      *s = '\0';
+    break;
+  }
+  if (s && b)
+    tgstrncpy(s, b, len);
+  return b;
+}
+
+WINDOW
+xi_get_window(XI_OBJ *xi_obj)
+{
+  return(xi_obj->itf->v.itf->xvt_win);
+}
+
+/*-------------------------------------------------------------------------
+function:       xi_scroll_rec
+xi_obj:         list object to scroll.  Must be a list object.
+rec:            first record to go to
+color:          color of row
+attrib:         attribute of row
+-------------------------------------------------------------------------*/
+int
+xi_scroll_rec(XI_OBJ *xi_obj, long rec, COLOR color, unsigned long attrib, int row_height)
+{
+  LM_SCROLL_ARG arg;
+
+  xvt_errmsg_sig_if(!(xi_obj->type == XIT_LIST), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20024",
+    20024, "Invalidate object passed to xi_scroll_rec");   
+  xi_obj->v.list->done_initial_xi_scroll = TRUE;
+  MEMCLEAR(arg);
+  arg.lm = xi_obj->v.list->lm;
+  /*
+  arg.nbr_lines = 0;
+  arg.percent = 0;
+  arg.same_cell = 0;
+  */
+  arg.rec = rec;
+  arg.have_rec = TRUE;
+  arg.color = color;
+  arg.attrib = attrib;
+  arg.row_height = row_height;
+  arg.rec_at_top = TRUE;
+  return lm_scroll(&arg);
+}
+
+/*
+typedef struct _xi_scroll_record_arg
+{
+  XI_OBJ *xi_obj;
+  long record;
+  COLOR row_color;
+  unsigned long attrib;
+  int row_height;
+  BOOLEAN rec_at_top;
+} XI_SCROLL_RECORD_ARG;
+*/
+int
+xi_scroll_record(XI_SCROLL_RECORD_ARG *arg)
+{
+  LM_SCROLL_ARG lm_scroll_arg;
+  XI_OBJ *xi_obj = arg->xi_obj;
+
+  xi_obj->v.list->done_initial_xi_scroll = TRUE;
+  MEMCLEAR(lm_scroll_arg);
+  lm_scroll_arg.lm = xi_obj->v.list->lm;
+  /*
+  lm_scroll_arg.nbr_lines = 0;
+  lm_scroll_arg.percent = 0;
+  lm_scroll_arg.same_cell = 0;
+  */
+  lm_scroll_arg.rec = arg->record;
+  lm_scroll_arg.have_rec = TRUE;
+  lm_scroll_arg.color = arg->row_color;
+  lm_scroll_arg.attrib = arg->attrib;
+  lm_scroll_arg.row_height = arg->row_height;
+  lm_scroll_arg.rec_at_top = arg->rec_at_top;
+  return lm_scroll(&lm_scroll_arg);
+}
+
+/*-------------------------------------------------------------------------
+function:       xi_scroll_internal
+xi_obj:         list object to scroll.  Must be a list object.
+nbr_lines:      nbr of lines to scroll, may be positive or negative, may be set
+  to XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, or XI_SCROLL_PGDN
+percent:        passed with XI_SCROLL_FIRST event
+same_cell:      sometimes the focus goes back onto the same cell.  In other cases,
+  for instance, XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, and
+  XI_SCROLL_PGDN, we don't want to put the focus back on the same cell,
+  but instead, want to put the focus on the first or last fully visible
+  row.
+invalidate:     indicates whether to invalidate the list. This is only set to FALSE when xi_scroll_internal is
+  called when the interface is created.
+-------------------------------------------------------------------------*/
+int
+xi_scroll_internal(XI_OBJ *xi_obj, int nbr_lines, int percent,
+      BOOLEAN same_cell )
+{
+  LM_SCROLL_ARG arg;
+
+  xvt_errmsg_sig_if(!(xi_obj->type == XIT_LIST), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20037",
+    20037, "Invalidate object passed to xi_scroll_internal");   
+  xi_obj->v.list->done_initial_xi_scroll = TRUE;
+  MEMCLEAR(arg);
+  arg.lm = xi_obj->v.list->lm;
+  arg.nbr_lines = nbr_lines;
+  arg.percent = percent;
+  arg.same_cell = same_cell;
+  arg.rec_at_top = TRUE;
+  /*
+  arg.rec = 0;
+  arg.have_rec = FALSE;
+  arg.color = 0L;
+  arg.attrib = 0L;
+  arg.row_height = 0;
+  */
+  return lm_scroll(&arg);
+}
+
+BOOLEAN
+xi_delete_row(XI_OBJ *xi_obj)
+{
+  int row;
+  XI_OBJ *list_obj;
+  BOOLEAN rv;
+
+  xvt_errmsg_sig_if(!(xi_obj->type == XIT_ROW), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20025",
+    20025, "Invalidate object passed to xi_delete_row");   
+  list_obj = xi_obj->parent;
+  row = xi_obj->v.row;
+  rv = lm_delete_row(list_obj->v.list->lm, row);
+  return rv;
+}
+
+BOOLEAN
+xi_insert_row(XI_OBJ *list, int row)
+{
+  BOOLEAN rv;
+
+  xvt_errmsg_sig_if(!(list->type == XIT_LIST), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20026",
+    20026, "Invalidate object passed to xi_insert_row");   
+  rv = lm_insert_row(list->v.list->lm, row);
+  return rv;
+}
+
+int
+xi_scroll(XI_OBJ *xi_obj, int nbr_lines)
+{
+  return(xi_scroll_internal(xi_obj, nbr_lines, 0, (BOOLEAN)(nbr_lines < 1000)));
+}
+
+int
+xi_scroll_percent(XI_OBJ *xi_obj, int percent)
+{
+  return(xi_scroll_internal(xi_obj, XI_SCROLL_FIRST, percent, FALSE ));
+}
+
+void
+xi_set_app_data(XI_OBJ *xi_obj, long app_data)
+{
+  xi_obj->app_data = app_data;
+}
+
+void
+xi_set_app_data2(XI_OBJ *xi_obj, long app_data)
+{
+  xi_obj->app_data2 = app_data;
+}
+
+void
+xi_set_fore_color(XI_OBJ *xi_obj, COLOR color)
+{
+  RCT rct;
+
+  switch (xi_obj->type)
+  {
+  case XIT_ROW:
+    lm_set_color(xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row,
+    0, FALSE, color, FALSE);
+    break;
+  case XIT_CELL:
+  {
+    LM_DATA far *lmp = LMP(xi_obj->parent->v.list->lm);
+    int idx = xi_obj->v.cell.row;
+    int idx2 = xi_obj->v.cell.column;
+    BOOLEAN do_redraw = (lmp->cell_data[idx][idx2].color != color);
+
+    lm_set_color( xi_obj->parent->v.list->lm, LM_CELL, xi_obj->v.cell.row,
+      xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled, color,
+      FALSE);
+    if (do_redraw)
+    {
+  xi_get_rect(xi_obj, &rct);
+  xi_invalidate_rect(xi_get_window(xi_obj->itf), &rct);
+    }
+    break;
+  }
+  }
+}
+
+void
+xi_set_attrib(XI_OBJ *xi_obj, unsigned long attrib)
+{
+  int n;
+  XI_OBJ * *objlist;
+  unsigned long attrib_diff;
+  WINDOW win = xi_obj->itf->v.itf->xvt_win;
+
+  attrib_diff = xi_get_attrib(xi_obj) ^ attrib;
+  switch(xi_obj->type)
+  {
+  case XIT_BTN:
+    if (! (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS))
+    {
+      XI_BTN_DATA *bd;
+      RCT r;
+
+      bd = xi_obj->v.btn;
+      r = bd->rct;
+      if (bd->type == XIBT_TABBTN)
+  r.bottom += 2;
+      xi_invalidate_rect(win, &r);
+    }
+    else
+    {
+      if (attrib_diff & XI_ATR_VISIBLE)
+      {
+  WINDOW btn_win;
+
+  btn_win = xi_obj->v.btn->btnctl;
+  xvt_vobj_set_visible(btn_win, (BOOLEAN)((attrib & XI_ATR_VISIBLE)
+      != 0));
+  xi_invalidate_rect(win, &xi_obj->v.btn->rct);
+      }
+      if (attrib_diff & XI_ATR_ENABLED)
+  xvt_vobj_set_enabled(xi_obj->v.btn->btnctl,
+      (BOOLEAN)((attrib & XI_ATR_ENABLED) != 0));
+    }
+    xi_obj->v.btn->attrib = attrib;
+    break;
+  case XIT_FORM:
+    /* loop over sub-objects */
+    objlist = xi_get_member_list(xi_obj, &n);
+    for (; n > 0; n--, objlist++)
+      xi_set_attrib(*objlist, attrib);
+    break;
+  case XIT_FIELD:
+    {
+      RCT rct;
+      XI_FIELD_DATA *fd;
+
+      stx_set_attrib(xi_obj->v.field->stx, attrib);
+      fd = xi_obj->v.field;
+      rct = fd->rct;
+      if (fd->button)
+  if (! fd->button_on_left)
+    rct.right = fd->btn_rct.right;
+      xi_invalidate_rect(win, &rct);
+      break;
+    }
+  case XIT_GROUP:
+    /* it is not clear how to get the proper behaviour here */
+    break;
+  case XIT_LINE:
+    {
+      RCT rct;
+      XI_LINE_DATA *ld;
+
+      ld = xi_obj->v.line;
+      rct.top = min(ld->pnt1.v, ld->pnt2.v);
+      rct.bottom = max(ld->pnt1.v, ld->pnt2.v);
+      rct.left = min(ld->pnt1.h, ld->pnt2.h);
+      rct.right = max(ld->pnt1.h, ld->pnt2.h);
+      --rct.top;
+      rct.bottom += 3;
+      --rct.left;
+      rct.right += 3;
+      xi_obj->v.line->attrib = attrib;
+      xi_invalidate_rect(win, &rct);
+      break;
+    }
+  case XIT_RECT:
+    xi_obj->v.rect->attrib = attrib;
+    xi_invalidate_rect(win, &xi_obj->v.rect->rct);
+    break;
+  case XIT_TEXT:
+    xi_obj->v.text->attrib = attrib;
+    xi_invalidate_rect(win, &xi_obj->v.text->rct);
+    break;
+  case XIT_ITF:
+    /* it is not clear how to get the proper behaviour here */
+    break;
+  case XIT_COLUMN:
+    lm_set_attrib( xi_obj->parent->v.list->lm, LM_COLUMN,
+      xi_obj_to_idx(xi_obj), 0, FALSE, attrib, FALSE);
+    break;
+  case XIT_LIST:
+    {
+      XI_LIST_DATA *ld;
+
+      ld = xi_obj->v.list;
+      if (attrib & XI_ATR_VISIBLE && ! ld->done_initial_xi_scroll)
+      {
+  ld->done_initial_xi_scroll = TRUE;
+  xi_scroll_internal(xi_obj, XI_SCROLL_FIRST, ld->start_percent, FALSE );
+      }
+      lm_set_attrib(ld->lm, LM_LIST, 0, 0, FALSE, attrib, FALSE);
+      if (ld->sb_win)
+      {
+  xvt_vobj_set_visible(ld->sb_win, (BOOLEAN)((attrib & XI_ATR_VISIBLE) != 0));
+  xvt_vobj_set_enabled(ld->sb_win, (BOOLEAN)((attrib & XI_ATR_ENABLED) != 0));
+      }
+      if (ld->hsb_win)
+      {
+  xvt_vobj_set_visible(ld->hsb_win, (BOOLEAN)((attrib & XI_ATR_VISIBLE) != 0));
+  xvt_vobj_set_enabled(ld->hsb_win, (BOOLEAN)((attrib & XI_ATR_ENABLED) != 0));
+      }
+      break;
+    }
+  case XIT_ROW:
+    lm_set_attrib( xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row, 0, FALSE,
+      attrib, FALSE);
+    break;
+  case XIT_CELL:
+    lm_set_attrib( xi_obj->parent->v.list->lm, LM_CELL, xi_obj->v.cell.row,
+      xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled,
+      attrib, FALSE);
+    break;
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20027", 20027,
+    "Invalid object passed to xi_set_attrib");   
+  break;
+  }
+}
+
+void
+xi_set_bufsize(XI_OBJ *xi_obj, int size)
+{
+  XI_OBJ * *objp;
+  int i;
+
+  switch(xi_obj->type)
+  {
+  case XIT_FIELD:
+    stx_set_bufsize(xi_obj->v.field->stx, (short)size);
+    break;
+  case XIT_COLUMN:
+    lm_set_buf_size(xi_obj->parent->v.list->lm, LM_COLUMN,
+  xi_obj_to_idx(xi_obj), size);
+    break;
+  case XIT_LIST:
+  case XIT_FORM:
+    objp = xi_obj->children;
+    for (i = xi_obj->nbr_children; i > 0; i--, objp++)
+      xi_set_bufsize(*objp, size);
+    break;
+  }
+}
+
+void xi_set_sel(XI_OBJ *xi_obj, int selstart, int selstop)
+{
+  switch(xi_obj->type)
+  {
+  case XIT_CELL:
+    xi_set_focus(xi_obj);
+    lm_set_sel( xi_obj->parent->v.list->lm, xi_obj->v.cell.row,
+    xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled,
+    selstart, selstop);
+    break;
+  case XIT_FIELD:
+    xi_set_focus(xi_obj);
+    stx_set_sel(xi_obj->v.field->stx, selstart, selstop);
+    break;
+  case XIT_BTN:
+  case XIT_FORM:
+  case XIT_GROUP:
+  case XIT_TEXT:
+  case XIT_COLUMN:
+  case XIT_ITF:
+  case XIT_LIST:
+  case XIT_ROW:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20028", 20028,
+    "Invalid object passed to xi_set_sel");
+    break;
+  }
+}
+
+void
+xi_set_text(XI_OBJ *xi_obj, char *s)
+{
+  char *buf;
+  size_t buf_size = 256;
+  BOOLEAN ddd;
+
+  if ( xi_obj == xi_obj->itf->v.itf->focus_obj )
+    xi_obj->itf->v.itf->chg_flag = FALSE;
+  buf = xvt_mem_alloc(buf_size);
+  xi_get_text(xi_obj, buf, buf_size);
+  if (! strcmp(s, buf))
+  {
+    xvt_mem_free(buf);
+    return;
+  }
+  xvt_mem_free(buf);
+  ddd = ! (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS);
+  switch(xi_obj->type)
+  {
+  case XIT_BTN:
+    {
+      XI_BTN_DATA *btn;
+
+      btn = xi_obj->v.btn;
+      btn->text = (char *)xi_tree_realloc(btn->text, strlen(s) + 1);
+      strcpy(btn->text, s);
+      if (ddd)
+      {
+  if ((xi_get_attrib( xi_obj ) & XI_ATR_VISIBLE) != 0)
+    xi_invalidate_rect( xi_obj->itf->v.itf->xvt_win, &btn->rct);
+      }
+      else
+  xvt_vobj_set_title(btn->btnctl, s);
+      break;
+    }
+  case XIT_CELL:
+    lm_set_text( xi_obj->parent->v.list->lm, s, xi_obj->v.cell.row,
+    xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled );
+    break;
+  case XIT_COLUMN:
+    lm_set_text( xi_obj->parent->v.list->lm, s, LM_HEADING_TEXT,
+    xi_obj_to_idx(xi_obj), FALSE );
+    break;
+  case XIT_FIELD:
+    {
+      /*
+      RCT rct;
+*/
+
+      stx_set_text(xi_obj->v.field->stx, s);
+      /*
+      TODO change approach, simply draw text
+      xi_get_rect(xi_obj, &rct);
+      xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct);
+*/
+      break;
+    }
+  case XIT_ITF:
+    xvt_vobj_set_title(xi_obj->v.itf->xvt_win, s);
+    break;
+  case XIT_ROW:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20029", 20029,
+    "xi_set_text not implemented for XIT_ROW");   
+  case XIT_TEXT:
+    {
+      XI_TEXT_DATA *text_data;
+      RCT rct;
+
+      text_data = xi_obj->v.text;
+      text_data->text = (char *)xi_tree_realloc(text_data->text, strlen(s) + 1);
+      strcpy(text_data->text, s);
+      if ((xi_get_attrib( xi_obj ) & XI_ATR_VISIBLE) != 0)
+      {
+  xi_get_rect(xi_obj, &rct);
+  xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct);
+      }
+      break;
+    }
+  case XIT_GROUP:
+  case XIT_FORM:
+  case XIT_LIST:
+    break;
+  }
+}
+
+void
+xi_draw_button(XI_OBJ *xi_obj, RCT *rct, char *text,
+int down_icon_rid, int up_icon_rid, int disabled_icon_rid,
+BOOLEAN enabled, BOOLEAN visible, BOOLEAN focus, BOOLEAN down, BOOLEAN dflt,
+BOOLEAN checked, BOOLEAN box_only)
+{
+  XI_BTN_DATA *bd;
+  COLOR fore_color;
+  CPEN fore_cp;
+  WINDOW win;
+  XI_OBJ *itf;
+  XI_ITF_DATA *id;
+
+  if (! visible)
+    return;
+  itf = xi_obj->itf;
+  id = itf->v.itf;
+  if (id->half_baked)
+    return;
+  win = xi_get_window(itf);
+  xvt_dwin_set_clip( win, NULL );
+  bd = xi_obj->v.btn;
+  fore_color = COLOR_BLACK;
+  fore_cp = black_cpen;
+  if (bd->fore_color)
+  {
+    fore_cp.color = bd->fore_color;
+    fore_color = bd->fore_color;
+  }
+  switch (bd->type)
+  {
+  case XIBT_BUTTON:
+  case XIBT_BUTTON_CHECKBOX:
+  case XIBT_BUTTON_RADIOBTN:
+  {
+      int     grid_width;
+      RCT     r;
+
+      r       = *rct;
+      if (xi_obj->v.btn->packed == TRUE)
+      {
+  grid_width  = (int)xi_get_pref(XI_PREF_CONTAINER_GRID_WIDTH);
+  xi_inflate_rect(&r, -grid_width);
+      }
+      else
+      {
+  XI_BTN_TYPE bt;
+
+  bt = xi_obj->v.btn->type;
+  if (bt == XIBT_BUTTON || bt == XIBT_BUTTON_CHECKBOX ||
+      bt == XIBT_BUTTON_RADIOBTN)
+    xi_inflate_rect(&r, -3);
+      }
+      xi_set_draw_mode(win, M_COPY);
+#if (XIWS == PMWS) && (XVT_OS != XVT_OS_CTOS)
+      {
+  CBRUSH hollow_cbrush;
+  RCT rct;
+  DRAW_CTOOLS t;
+
+  /* Bad bug with XVT/PM, needs this before can draw COLOR_LTGRAY */
+  xvt_app_get_default_ctools(&t);
+  xvt_dwin_set_draw_ctools(win, &t);
+  hollow_cbrush.color = COLOR_WHITE;
+  hollow_cbrush.pat = PAT_HOLLOW;
+  xvt_dwin_set_cbrush(win, &hollow_cbrush);
+  rct.top = 0;
+  rct.left = 0;
+  rct.bottom = 0;
+  rct.right = 0;
+  xvt_dwin_draw_rect(win, &rct);
+      }
+#endif
+      xi_draw_3d_rect(win, &r, (BOOLEAN)(down || bd->checked), 2, 0L, 0L, 0L);
+      if (up_icon_rid)
+      {
+  int x, y;
+  RCT r2;
+
+  x = r.left + 2 + bd->icon_x;
+  y = r.top + 2 + bd->icon_y;
+  r2 = r;
+  xi_inflate_rect(&r2, -2);
+  xi_set_clip(win, &r2);
+  if (down)
+    xi_draw_icon(win, x, y + 1, down_icon_rid, COLOR_BLACK,
+      xi_get_pref(XI_PREF_COLOR_CTRL));
+  else
+  {
+    if (enabled || ! disabled_icon_rid)
+      xi_draw_icon(win, x, y, up_icon_rid, COLOR_BLACK,
+    xi_get_pref(XI_PREF_COLOR_CTRL));
+    else
+      xi_draw_icon(win, x, y, disabled_icon_rid, COLOR_BLACK,
+    xi_get_pref(XI_PREF_COLOR_CTRL));
+  }
+  xi_set_clip(win, NULL);
+      }
+      else
+      {
+  unsigned long attrib;
+  RCT       text_rect;
+  COLOR     color;
+  FONT_OBJ* fontp;
+
+  attrib = XI_ATR_VCENTER | XI_ATR_HCENTER | XI_ATR_VISIBLE;
+  if (enabled)
+    xi_set_xvt_fore_color(win, fore_color);
+  else
+    xi_set_xvt_fore_color( win,
+        (COLOR)xi_get_pref(XI_PREF_COLOR_DISABLED) );
+  text_rect = r;
+  if (down)
+    text_rect.top += 2;
+  fontp = xi_obj->itf->v.itf->font;
+  if (fontp)
+    xi_set_xvt_font(win, fontp, FALSE);
+  else
+    xi_set_xvt_font(win, &xi_sysfont, FALSE);
+  color = (COLOR)xi_get_pref(XI_PREF_COLOR_CTRL);
+  xi_set_xvt_back_color(win, color);
+  xi_draw_clipped_text(win, text, &text_rect, &text_rect, attrib, FALSE, 0, -1);
+      }
+      if ((focus) || (xi_obj->v.btn->packed))
+      {
+  int     width;
+  RCT     rct2;
+
+  width   = (xi_obj->v.btn->packed) ? grid_width : 2;
+  rct2 = r;
+  rct2.top -= width;
+  rct2.left -= width;
+  rct2.bottom += width;
+  rct2.right += width;
+  xi_set_cpen(win, &black_cpen);
+  xi_set_cbrush(win, &hollow_cbrush);
+  xi_draw_thick_rect(win, &rct2, width);
+      }
+      else
+      {
+  RCT rct2;
+  CPEN cpen;
+
+  rct2 = r;
+  rct2.top--;
+  rct2.left--;
+  rct2.bottom++;
+  rct2.right++;
+  xi_set_cpen(win, &black_cpen);
+  xi_set_cbrush(win, &hollow_cbrush);
+  xi_draw_rect(win, &rct2);
+  rct2.top--;
+  rct2.left--;
+  rct2.bottom++;
+  rct2.right++;
+  if (id->back_color)
+  {
+    cpen = black_cpen;
+    cpen.color = id->back_color;
+    xi_set_cpen(win, &cpen);
+    xi_draw_rect(win, &rct2);
+  }
+  if (dflt)
+  {
+    rct2.top--;
+    rct2.left--;
+    rct2.bottom++;
+    rct2.right++;
+    xi_set_cpen(win, &black_cpen);
+    xi_draw_rect(win, &rct2);
+  }
+      }
+      break;
+    }
+  case XIBT_RADIOBTN:
+    {
+      RCT rbrct, rct2;
+      unsigned long attrib;
+      RCT text_rect;
+      COLOR color;
+
+      rbrct = *rct;
+      rbrct.bottom -= 4;
+      rct2 = rbrct;
+      rct2.right = rct2.left + (rct2.bottom - rct2.top);
+      xi_set_draw_mode(win, M_COPY);
+#if (XIWS == PMWS) && (XVT_OS != XVT_OS_CTOS)
+      {
+  CBRUSH hollow_cbrush;
+  RCT rct;
+  DRAW_CTOOLS t;
+
+  /* Bad bug with XVT/PM, needs this before can draw COLOR_LTGRAY */
+  xvt_app_get_default_ctools(&t);
+  xvt_dwin_set_draw_ctools(win, &t);
+  hollow_cbrush.color = COLOR_WHITE;
+  hollow_cbrush.pat = PAT_HOLLOW;
+  xvt_dwin_set_cbrush(win, &hollow_cbrush);
+  rct.top = 0;
+  rct.left = 0;
+  rct.bottom = 0;
+  rct.right = 0;
+  xvt_dwin_draw_rect(win, &rct);
+      }
+#endif
+      xi_draw_3d_diamond(win, &rct2, checked, down, down ? 2 : 1,
+    down ? bd->fore_color : 0L);
+    if (checked)
+    {
+  RCT rct;
+
+  rct = rct2;
+  rct.top += 4;
+  rct.left += 4;
+  rct.bottom -= 4;
+  rct.right -= 4;
+  xi_draw_3d_diamond(win, &rct, FALSE, TRUE, rct.right - rct.left,
+    enabled ? bd->fore_color : xi_get_pref(XI_PREF_COLOR_DISABLED));
+      }
+      if (! box_only)
+      {
+  CPEN cpen;
+  FONT_OBJ *fontp;
+
+  attrib = XI_ATR_VCENTER | XI_ATR_VISIBLE;
+  if (enabled)
+    xi_set_xvt_fore_color(win, fore_color);
+  else
+    xi_set_xvt_fore_color( win,
+      (COLOR)xi_get_pref(XI_PREF_COLOR_DISABLED) );
+  text_rect = *rct;
+  text_rect.left = rct2.right + (rct2.right - rct2.left) / 2;
+  fontp = xi_obj->itf->v.itf->font;
+  if (fontp)
+    xi_set_xvt_font(win, fontp, FALSE);
+  else
+    xi_set_xvt_font(win, &xi_sysfont, FALSE);
+  color = (COLOR)xi_get_pref(XI_PREF_COLOR_CTRL);
+  xi_set_xvt_back_color(win, color);
+  xi_draw_clipped_text(win, text, &text_rect, &text_rect, attrib, FALSE, 0, -1);
+  if (focus)
+  {
+    cpen = black_cpen;
+    cpen.pat = PAT_RUBBER;
+    xi_set_cpen(win, &cpen);
+    xi_set_cbrush(win, &hollow_cbrush);
+    text_rect.left = rct2.right + (rct2.right - rct2.left) / 4;
+    xi_draw_rect(win, &text_rect);
+  }
+  else
+  {
+    if (id->back_color)
+    {
+      cpen = black_cpen;
+      cpen.color = id->back_color;
+      xi_set_cpen(win, &cpen);
+      xi_set_cbrush(win, &hollow_cbrush);
+      text_rect.left = rct2.right + (rct2.right - rct2.left) / 4;
+      xi_draw_rect(win, &text_rect);
+    }
+  }
+      }
+      break;
+    }
+  case XIBT_TABBTN:
+    {
+      RCT tbrct;
+      unsigned long attrib;
+      CPEN line_cpen;
+      PNT p;
+      COLOR color;
+      CPEN cpen;
+      int leading, ascent, descent, height, width, hdiff, vdiff;
+      RCT r;
+      char s[100];
+      FONT_OBJ *fontp;
+
+      tbrct = *rct;
+      height = tbrct.bottom - tbrct.top;
+      xi_set_draw_mode(win, M_COPY);
+      line_cpen = black_cpen;
+
+      /* Draw background color, one line at a time */
+      line_cpen.color = xi_get_pref( XI_PREF_COLOR_CTRL );
+      xi_set_cpen(win, &line_cpen);
+      for ( hdiff = 1, vdiff = height / 2; hdiff < height; hdiff++ )
+      {
+  p.h = tbrct.left + vdiff;
+  p.v = tbrct.top + hdiff;
+  xi_move_to( win, p );
+  p.h = tbrct.right - vdiff;
+  xi_draw_line( win, p );
+  if ( hdiff % 2 )
+    vdiff--;
+      }
+
+      /* Draw bottom line, adjust color if checked. */
+      if (checked)
+  line_cpen.color = xi_get_pref(XI_PREF_COLOR_CTRL);
+      else
+  line_cpen.color = xi_get_pref( XI_PREF_COLOR_LIGHT );
+      xi_set_cpen(win, &line_cpen);
+      p.h = tbrct.left + 1;
+      p.v = tbrct.bottom;
+      xi_move_to(win, p);
+      p.h = tbrct.right - 1;
+      xi_draw_line(win, p);
+
+      line_cpen.color = xi_get_pref(XI_PREF_COLOR_LIGHT);
+      xi_set_cpen(win, &line_cpen);
+
+      /* Draw left, slanted line */
+      p.h = tbrct.left;
+      p.v = tbrct.bottom;
+      xi_move_to(win, p);
+      p.h = tbrct.left + height / 2;
+      p.v = tbrct.top;
+      xi_draw_line(win, p);
+
+      /* Draw top line */
+      xi_move_to(win, p);
+      p.h = tbrct.right - height / 2;
+      p.v = tbrct.top;
+      xi_draw_line(win, p);
+
+      /* Draw right, slanted line */
+      line_cpen.color = xi_get_pref(XI_PREF_COLOR_DARK);
+      xi_set_cpen(win, &line_cpen);
+      p.v = tbrct.top + 1;
+      xi_move_to(win, p);
+      p.h = tbrct.right;
+      p.v = tbrct.bottom;
+      xi_draw_line(win, p);
+
+      /* Draw text */
+      attrib = XI_ATR_VCENTER | XI_ATR_VISIBLE | XI_ATR_HCENTER;
+      if (enabled)
+  xi_set_xvt_fore_color(win, fore_color);
+    else
+  xi_set_xvt_fore_color( win,
+    (COLOR)xi_get_pref(XI_PREF_COLOR_DISABLED) );
+    fontp = xi_obj->itf->v.itf->font;
+    if ( !fontp )
+  fontp = &xi_sysfont;
+      if ( checked )
+      {
+  XVT_FNTID font_id = xvt_font_create();
+  xvt_font_copy( font_id, *fontp, (unsigned long)XVT_FA_ALL );
+  xvt_font_set_style( font_id, XVT_FS_BOLD );
+  xvt_dwin_set_font( win, font_id );
+  xvt_font_destroy( font_id );
+    } else
+  xi_set_xvt_font(win, fontp, FALSE);
+    color = (COLOR)xi_get_pref(XI_PREF_COLOR_CTRL);
+    xi_set_xvt_back_color(win, color);
+    xi_draw_clipped_text(win, text, &tbrct, &tbrct, attrib, FALSE, 0, -1);
+
+    /* Draw focus line, or erase focus line */
+      if (focus)
+      {
+  cpen = black_cpen;
+  cpen.pat = PAT_RUBBER;
+      }
+      else
+      {
+  cpen = black_cpen;
+  cpen.color = xi_get_pref( XI_PREF_COLOR_CTRL );
+      }
+      xi_get_font_metrics(win, &leading, &ascent, &descent);
+      height = leading + ascent + descent;
+      gstrncpy(s, text, sizeof(s));
+      s[sizeof(s) - 1] = '\0';
+      width = xi_xvt_get_text_width(win, s, -1);
+      vdiff = (tbrct.bottom - tbrct.top - height) / 2 - 1;
+      hdiff = (tbrct.right - tbrct.left - width) / 2 - 2;
+      r = tbrct;
+      r.top += vdiff;
+#if XIWS != GRWS
+      r.top++;
+#endif
+      r.bottom -= vdiff;
+      r.left += hdiff;
+      r.right -= hdiff;
+      xi_set_cpen(win, &cpen);
+      xi_set_cbrush(win, &hollow_cbrush);
+      xi_draw_rect(win, &r);
+      break;
+    }
+  case XIBT_CHECKBOX:
+    {
+      RCT cbrct, rct2;
+      unsigned long attrib;
+      RCT text_rect;
+      COLOR color;
+
+      cbrct = *rct;
+      cbrct.bottom -= 4;
+      rct2 = cbrct;
+      rct2.right = rct2.left + (rct2.bottom - rct2.top);
+      xi_set_draw_mode(win, M_COPY);
+#if (XIWS == PMWS) && (XVT_OS != XVT_OS_CTOS)
+      {
+  CBRUSH hollow_cbrush;
+  RCT rct;
+  DRAW_CTOOLS t;
+
+  /* Bad bug with XVT/PM, needs this before can draw COLOR_LTGRAY */
+  xvt_app_get_default_ctools(&t);
+  xvt_dwin_set_draw_ctools(win, &t);
+  hollow_cbrush.color = COLOR_WHITE;
+  hollow_cbrush.pat = PAT_HOLLOW;
+  xvt_dwin_set_cbrush(win, &hollow_cbrush);
+  rct.top = 0;
+  rct.left = 0;
+  rct.bottom = 0;
+  rct.right = 0;
+  xvt_dwin_draw_rect(win, &rct);
+      }
+#endif
+      if (down)
+      {
+  xi_set_cpen(win, &fore_cp);
+  xi_set_cbrush(win, &hollow_cbrush);
+  xi_draw_thick_rect(win, &rct2, 2);
+      }
+    else
+  xi_draw_3d_rect(win, &rct2, down, 1, 0L, 0L, 0L);
+      if (! enabled)
+    fore_cp.color = xi_get_pref(XI_PREF_COLOR_DISABLED);
+    if (checked)
+      {
+  PNT pnt1, pnt2;
+
+  xi_set_cpen(win, &fore_cp);
+  pnt1.h = rct2.left + 2;
+  pnt1.v = rct2.bottom - 7;
+  xi_move_to(win, pnt1);
+  pnt2.h = pnt1.h;
+  pnt2.v = pnt1.v + 5;
+  xi_draw_line(win, pnt2);
+
+  pnt1.h++;
+  pnt1.v--;
+  xi_move_to(win, pnt1);
+  pnt2.h++;
+  xi_draw_line(win, pnt2);
+
+  pnt1.h++;
+  pnt1.v = rct2.bottom - 5;
+  pnt2 = pnt1;
+  pnt2.v += 2;
+
+  while (pnt1.v >= (rct2.top + 3) && pnt1.h <= (rct2.right - 4))
+  {
+    xi_move_to(win, pnt1);
+    xi_draw_line(win, pnt2);
+    pnt1.h++;
+    pnt1.v--;
+    pnt2.h++;
+    pnt2.v--;
+  }
+  pnt1.v++;
+  xi_move_to(win, pnt1);
+  xi_draw_line(win, pnt2);
+      }
+      if (! box_only)
+      {
+  FONT_OBJ *fontp;
+
+  attrib = XI_ATR_VCENTER | XI_ATR_VISIBLE;
+  if (enabled)
+    xi_set_xvt_fore_color(win, fore_color);
+  else
+    xi_set_xvt_fore_color( win,
+      (COLOR)xi_get_pref(XI_PREF_COLOR_DISABLED) );
+  text_rect = *rct;
+  text_rect.left = rct2.right + (rct2.right - rct2.left) / 2;
+  fontp = xi_obj->itf->v.itf->font;
+  if (fontp)
+    xi_set_xvt_font(win, fontp, FALSE);
+  else
+    xi_set_xvt_font(win, &xi_sysfont, FALSE);
+  color = (COLOR)xi_get_pref(XI_PREF_COLOR_CTRL);
+  xi_set_xvt_back_color(win, color);
+  xi_draw_clipped_text(win, text, &text_rect, &text_rect, attrib, FALSE, 0, -1);
+  if (focus)
+  {
+    CPEN cpen;
+
+    cpen = black_cpen;
+    cpen.pat = PAT_RUBBER;
+    xi_set_cpen(win, &cpen);
+    xi_set_cbrush(win, &hollow_cbrush);
+    text_rect.left = rct2.right + (rct2.right - rct2.left) / 4;
+    xi_draw_rect(win, &text_rect);
+  }
+      else
+  {
+    if (id->back_color)
+    {
+      CPEN cpen;
+
+      cpen = black_cpen;
+        cpen.color = id->back_color;
+        xi_set_cpen(win, &cpen);
+        xi_set_cbrush(win, &hollow_cbrush);
+        text_rect.left = rct2.right + (rct2.right - rct2.left) / 4;
+        xi_draw_rect(win, &text_rect);
+      }
+  }
+      }
+      break;
+    }
+  }
+}
+
+
+/* -------------------------------------------------------------------------*/
+/*  xi_set_fixed_columns                                                    */
+/* -------------------------------------------------------------------------*/
+
+void xi_set_fixed_columns( XI_OBJ* list, int new_fixed_count )
+{
+  xvt_errmsg_sig_if(!(list->type == XIT_LIST), NULL_WIN,
+    SEV_FATAL, ERR_ASSERT_4, "20031", 20031,
+    "Non-list object sent to xi_set_fixed_columns");   
+  lm_set_fixed_columns( list->v.list->lm, new_fixed_count );
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_get_fixed_columns                                                    */
+/* -------------------------------------------------------------------------*/
+int xi_get_fixed_columns( XI_OBJ* list )
+{
+  xvt_errmsg_sig_if(!( list->type == XIT_LIST), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20038", 20038,
+    "Non-list object sent to xi_get_fixed_columns");   
+  return lm_get_fixed_columns( list->v.list->lm );
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_get_handle                                                           */
+/* -------------------------------------------------------------------------*/
+long xi_get_handle( XI_OBJ* list, XI_OBJ* child )
+{
+  LM_DATA* lm_data;
+  if (list->type != XIT_LIST)
+  return -1L;
+  lm_data = (LM_DATA*)list->v.list->lm;
+  switch (child->type)
+  {
+  case XIT_ROW:
+  {
+    int row = child->v.row;
+    if ( row >= 0 && row < lm_data->nbr_realized_rows)
+  return lm_data->recs[row];
+    break;
+  }
+  case XIT_CELL:
+  {
+    int row;
+
+    if (child->v.cell.is_vert_scrolled)
+  return lm_data->focus_rec;
+    row = child->v.cell.row;
+    if ( row >= 0 && row < lm_data->nbr_realized_rows)
+  return lm_data->recs[row];
+    break;
+  }
+  }
+  return -1L;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_field_calc_height_font_id                                            */
+/* -------------------------------------------------------------------------*/
+int xi_field_calc_height_font_id( XVT_FNTID font )
+{
+  if (font == 0)
+  font = xi_sysfont;
+  return xi_get_fu_height_font( &font );
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_button_calc_height_font_id                                            */
+/* -------------------------------------------------------------------------*/
+int xi_button_calc_height_font_id( XVT_FNTID font )
+{
+  return xi_field_calc_height_font_id( font );
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_field_calc_width_font_id                                             */
+/* -------------------------------------------------------------------------*/
+int xi_field_calc_width_font_id( XVT_FNTID font, char* string )
+{
+  WINDOW win;
+  XI_RCT rct = {-1000,-1000,-900,-900};
+  int    result;
+
+  if (font == 0)
+  font = xi_sysfont;
+  win = xi_new_child_window(&rct, "", W_DOC, FALSE, FALSE, FALSE, FALSE,
+    FALSE, FALSE, NULL_WIN, 0L, 0, 0L, FALSE, FALSE, 0);
+  xvt_dwin_set_font(win, font);
+  result = xvt_dwin_get_text_width( win, string, -1 ) + 4;
+  xvt_vobj_destroy(win);
+  return result;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_list_def_get_rows                                                    */
+/* -------------------------------------------------------------------------*/
+int xi_list_def_get_rows( XI_OBJ_DEF* list_def )
+{
+  int pix_row_spacing, height, pix_row1_top, title_height;
+
+  if (list_def->v.list->one_row_list)
+  return 1;
+  lm_get_vertical_metrics( list_def, &pix_row1_top, &pix_row_spacing, &height,
+        &title_height );
+  return height / pix_row_spacing;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_list_def_get_height                                                  */
+/* -------------------------------------------------------------------------*/
+int xi_list_def_get_client_height( XI_OBJ_DEF* list_def, int rows )
+{
+  int pix_row_spacing, height, pix_row1_top, title_height;
+
+  lm_get_vertical_metrics( list_def, &pix_row1_top, &pix_row_spacing, &height,
+        &title_height );
+  return title_height + rows * pix_row_spacing + (BORDER_WIDTH - RULE_WIDTH_H);
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_list_def_get_height                                                  */
+/* -------------------------------------------------------------------------*/
+int xi_list_def_get_outer_height( XI_OBJ_DEF* list_def, int rows )
+{
+  int result;
+
+  result = xi_list_def_get_client_height( list_def, rows );
+  return result + (int)xi_get_pref( XI_PREF_SB_HEIGHT );
+}
+
+/* -------------------------------------------------------------------------*/
+/*  button_get_horz_padding                                                 */
+/* -------------------------------------------------------------------------*/
+static int button_get_horz_padding( int type, int height, BOOLEAN packed )
+{
+  switch (type)
+  {
+  case XIBT_BUTTON:
+  case XIBT_BUTTON_CHECKBOX:
+  case XIBT_BUTTON_RADIOBTN:
+    if (packed)
+  return (int)xi_get_pref(XI_PREF_CONTAINER_GRID_WIDTH) * 2;
+    return 6;
+  case XIBT_RADIOBTN:
+    return height + height / 2 - 6;
+  case XIBT_TABBTN:
+    return height + 4;
+  case XIBT_CHECKBOX:
+    return height + height / 2 - 6;
+  }
+  return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_button_calc_height                                                   */
+/* -------------------------------------------------------------------------*/
+int xi_button_calc_pixel_height( int height )
+{
+  return height + 6;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_button_calc_height                                                   */
+/* -------------------------------------------------------------------------*/
+int xi_button_calc_pixel_width( int width )
+{
+  return width + 6;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_button_def_get_width                                                 */
+/* -------------------------------------------------------------------------*/
+
+int xi_button_def_get_width( XI_OBJ_DEF* obj_def )
+{
+  FONT_OBJ*   font;
+  XI_RCT      rct = {-1000,-1000,-900,-900};
+  WINDOW      win;
+  int         width;
+  XI_BTN_DEF* button;
+
+  if ( obj_def->type != XIT_BTN)
+    return 0;
+  font = xi_def_get_font( obj_def );
+  win = xi_new_child_window(&rct, "", W_DOC, FALSE, FALSE, FALSE, FALSE,
+          FALSE, FALSE, NULL_WIN, 0L, 0, 0L, FALSE, FALSE, 0);
+  xvt_dwin_set_font(win, *font);
+  button = obj_def->v.btn;
+  width = xvt_dwin_get_text_width( win, button->text, -1 );
+  xvt_vobj_destroy( win );
+  width += button_get_horz_padding( button->type, xi_get_fu_height_font( font ),
+            FALSE );
+  return width;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_container_def_get_btn_width                                          */
+/* -------------------------------------------------------------------------*/
+
+int xi_container_def_get_btn_width( XI_OBJ_DEF* obj_def )
+{
+  int               i;
+  FONT_OBJ*         font;
+  XI_RCT            rct = {-1000,-1000,-900,-900};
+  WINDOW            win;
+  int               max_width;
+  XI_CONTAINER_DEF* container;
+  BOOLEAN           packed;
+
+  if ( obj_def->type != XIT_CONTAINER || obj_def->nbr_children <= 0)
+    return 0;
+  font = xi_def_get_font( obj_def );
+  max_width = 0;
+  win = xi_new_child_window(&rct, "", W_DOC, FALSE, FALSE, FALSE, FALSE,
+                  FALSE, FALSE, NULL_WIN, 0L, 0, 0L, FALSE, FALSE, 0);
+  xvt_dwin_set_font(win, *font);
+  for (i = 0; i < obj_def->nbr_children; ++i)
+  {
+    XI_BTN_DEF* button;
+    int         width;
+
+    button = obj_def->children[i]->v.btn;
+    width = xvt_dwin_get_text_width( win, button->text, -1 );
+    max_width = max( width, max_width );
+  }
+  xvt_vobj_destroy( win );
+  container = obj_def->v.container;
+  packed = ((container->orientation == XI_GRID_HORIZONTAL
+      || container->orientation == XI_GRID_VERTICAL)
+    && container->packed);
+  max_width += button_get_horz_padding( obj_def->children[0]->v.btn->type,
+          xi_get_fu_height_font( font ),
+          packed );
+  return max_width;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_container_def_get_width                                              */
+/* -------------------------------------------------------------------------*/
+
+int xi_container_def_get_width( XI_OBJ_DEF* obj_def )
+{
+  XI_CONTAINER_DEF* container;
+
+  container = obj_def->v.container;
+  switch (container->orientation)
+  {
+    case XI_STACK_HORIZONTAL:
+    {
+      int horz_spacing;
+
+      if (container->packed)
+  horz_spacing = 0;
+      else if ((horz_spacing = (int)xi_get_pref(XI_PREF_HORZ_PIXEL_SPACING))
+    == 0)
+      {
+  FONT_OBJ* font;
+  font = xi_def_get_font( obj_def );
+  horz_spacing = (short)((xi_get_pref(XI_PREF_HORZ_SPACING)
+        * xi_get_fu_width_font(font)) / XI_FU_MULTIPLE);
+      }
+      return xi_container_def_get_btn_width( obj_def ) * obj_def->nbr_children +
+      (obj_def->nbr_children - 1) * horz_spacing;
+    }
+    case XI_STACK_VERTICAL:
+      return xi_container_def_get_btn_width( obj_def );
+  }
+  return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+/*  xi_container_def_get_height                                             */
+/* -------------------------------------------------------------------------*/
+int xi_container_def_get_height( XI_OBJ_DEF* obj_def )
+{
+  XI_CONTAINER_DEF* container;
+  FONT_OBJ*         font;
+  int               height;
+  int               vert_spacing;
+  int               top_offset;
+ 
+  if (obj_def->nbr_children == 0)
+    return 0;
+  container = obj_def->v.container;
+  font = xi_def_get_font( obj_def );
+  height = xi_button_calc_height_font_id( *font );
+  if (container->orientation == XI_STACK_HORIZONTAL)
+    return height;
+  if (container->orientation != XI_STACK_VERTICAL)
+    return 0;
+  switch (obj_def->children[0]->v.btn->type)
+  {
+  case XIBT_BUTTON:
+  case XIBT_BUTTON_CHECKBOX:
+  case XIBT_BUTTON_RADIOBTN:
+  case XIBT_TABBTN:
+    if (container->packed)
+      vert_spacing = 0;
+    else if ((vert_spacing = (int)xi_get_pref( XI_PREF_VERT_PIXEL_SPACING))
+            == 0)
+      vert_spacing = (int)((xi_get_pref(XI_PREF_VERT_SPACING)
+          * height ) / XI_FU_MULTIPLE );
+      top_offset = vert_spacing / 2;
+      break;
+    case XIBT_CHECKBOX:
+    case XIBT_RADIOBTN:
+      vert_spacing    = 0;
+      top_offset = 0;
+      break;
+  }
+  return height * obj_def->nbr_children + vert_spacing
+  * (obj_def->nbr_children - 1) + top_offset;
+}
+ 
diff --git a/xi/xi.h b/xi/xi.h
new file mode 100755
index 000000000..b50dc837c
--- /dev/null
+++ b/xi/xi.h
@@ -0,0 +1,1365 @@
+/*******************************************************************************
+*  Copyright 1991, 1992, 1993, 1994, 1995 by ORCA Software, Inc.               *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#ifndef INCL_XI
+#define INCL_XI
+
+#define OLDXVT_H
+#ifndef XVT_INCL_XVT
+#include "xvt.h"
+#endif
+#ifndef GRWS
+#define GRWS 9999
+#endif
+
+#if (defined(XVT_PTK_VERSION_MAJOR) && XVT_PTK_VERSION_MAJOR >= 4)
+#define R4
+#endif
+
+#define R4FONT
+
+#ifndef TABLE_INCL
+#ifdef XI_INTERNAL
+typedef struct
+{
+  short font_dummy;
+} *FONT;
+#else
+typedef void FONT;
+#endif
+#endif
+typedef XVT_FNTID FONT_OBJ;
+
+
+#if XVTWS == NTWS
+#define XIWS WINWS
+#else
+#define XIWS XVTWS
+#endif
+
+#if (XIWS == MTFWS || XIWS == XOLWS)
+#define near
+#endif
+
+#ifndef XVT_OS_CTOS
+#define XVT_OS_CTOS 9999
+#endif
+
+#if XVT_OS != XVT_OS_CTOS
+#ifdef XVTENTRY
+#undef XVTENTRY
+#endif
+#define XVTENTRY
+#ifdef BTCENTRY
+#undef BTCENTRY
+#endif
+#define BTCENTRY
+#endif
+
+#define XI_VERSION "3.3"
+#define XI_VERSION_NBR 3.3
+
+#define XI_IS_CH (XIWS == WMWS) || (XVT_OS == XVT_OS_CTOS)
+#define XI_IS_NOT_CH (XIWS != WMWS) || (XVT_OS == XVT_OS_CTOS)
+#define XI_IS_PM (XIWS == PMWS) || (XVT_OS == XVT_OS_CTOS)
+
+#if XVT_OS == XVT_OS_CTOS
+#define CTOS_IS_CH if (npctos_env == CHSERVICE) {
+#define CTOS_IS_PM if (npctos_env == PMSERVICE) {
+#define CTOS_END }
+#else
+#define CTOS_IS_CH
+#define CTOS_IS_PM
+#define CTOS_END
+#endif
+
+#if XI_IS_PM
+#define gmemset memset
+#endif
+
+#define gmemset memset
+
+#if 0
+#if defined(M_I86MM) || defined(__MEDIUM__) 
+#define gmemset memset
+#define assert4(a,b,c,d)
+#endif
+#endif
+
+/******************************************************************
+Miscellaneous
+******************************************************************/
+#define MEMCLEAR(x) gmemset((char *)&(x), '\0', (size_t)sizeof(x))
+
+/* FORM UNITS */
+#define XI_FU_MULTIPLE 8
+
+/* character modifier constants */
+#define XI_MOD_SHIFT  0x10000000L
+#define XI_MOD_CONTROL  0x20000000L
+#define XI_MOD_ALT    0x40000000L   /* not yet supported */
+
+#define XI_PASSWORD_CHAR '#'
+
+#define XI_CURSOR_RESIZE 8001
+#define XI_CURSOR_HAND 8002
+#define XI_CURSOR_VRESIZE 8003
+
+#ifndef COMBO_ICON
+#define COMBO_ICON 1026
+#endif
+
+#define HSCROLL_CID_CONST 6000
+
+typedef enum _e_search_type
+{
+  XI_SEARCH_FOR_FOCUSABLE,
+  XI_SEARCH_FOR_FIELD,
+  XI_SEARCH_FOR_TAB_CID
+}
+XI_SEARCH_TYPE;
+
+typedef enum _e_next_type
+{
+  XI_NEXT_FORM_TAB,
+  XI_NEXT_FORM_BACKTAB,
+  XI_NEXT_ITF_TAB,
+  XI_NEXT_ITF_BACKTAB
+}
+XI_NEXT_TYPE;
+
+
+/******************************************************************
+These must go first
+******************************************************************/
+typedef long LM;
+typedef long STX;
+
+/**********************************
+* XI Manifest constants
+**********************************/
+#define XI_ATR_ENABLED    0x1L
+#define XI_ATR_EDITMENU   0x2L
+#define XI_ATR_AUTOSELECT 0x4L
+#define XI_ATR_AUTOSCROLL 0x8L
+#define XI_ATR_RJUST    0x10L
+#define XI_ATR_BORDER   0x20L
+#define XI_ATR_VISIBLE    0x40L
+#define XI_ATR_FOCUSBORDER  0x80L
+#define XI_ATR_READONLY   0x100L
+#define XI_ATR_NAVIGATE   0x200L
+#define XI_ATR_TABWRAP    0x400L
+#define XI_ATR_PASSWORD   0x800L
+#define XI_ATR_SELECTED   0x1000L
+#define XI_ATR_VCENTER    0x2000L
+#define XI_ATR_SELECTABLE 0x4000L
+#define XI_ATR_COL_SELECTABLE 0x8000L
+#define XI_ATR_HCENTER    0x10000L
+
+#define XI_MAX_EVENT    100
+#define XI_NULL_OBJ     ((XI_OBJ *)NULL)
+#define XI_SCROLL_PGUP    1001
+#define XI_SCROLL_PGDOWN  1002
+#define XI_SCROLL_FIRST   1003
+#define XI_SCROLL_LAST    1004
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern BOOLEAN xi_false;
+#ifdef __cplusplus
+}
+#endif
+
+/**********************************
+* XI Types
+**********************************/
+typedef PNT XI_PNT; /* XI form coordinates */
+typedef RCT XI_RCT;
+typedef struct
+{
+  short row;
+  short column;
+} XI_CELL_SPEC;
+
+typedef enum
+{
+  XIC_ENABLED,
+  XIC_BACK,
+  XIC_HILIGHT,
+  XIC_SHADOW,
+  XIC_ACTIVE,
+  XIC_DISABLED,
+  XIC_DISABLED_BACK,
+  XIC_WHITE_SPACE,
+  XIC_ACTIVE_BACK,
+  XIC_FORE
+}
+XI_COLOR_PART;
+
+/**********************************
+* XI Event callback
+**********************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if ! XVT_CC_PROTO
+  typedef void (* XVT_CALLCONV1 XI_EVENT_HANDLER)();
+#else
+#if (XIWS == XOLWS) || (XIWS == MTFWS) || (XIWS == PMWS)
+  typedef void (* XVT_CALLCONV1 XI_EVENT_HANDLER)(void *itf, void *xiev);
+#else
+  struct _xi_obj;
+  struct _xi_event;
+  typedef void (* XVT_CALLCONV1 XI_EVENT_HANDLER)(struct _xi_obj *itf, struct _xi_event *xiev);
+#endif
+#endif
+#define XI_CB XI_EVENT_HANDLER
+#ifdef __cplusplus
+} 
+// End of extern "C"
+#endif
+
+/* 
+typedef void (*XI_EVENT_HANDLER)(void *itf, void *xiev);
+*/
+/**********************************
+* XI Preferences enumeration
+**********************************/
+typedef enum
+{
+  XI_PREF_OVERLAP,
+  XI_PREF_FORM_TAB_CHAR,
+  XI_PREF_FORM_BACKTAB_CHAR,
+  XI_PREF_SCROLL_INC,
+  XI_PREF_3D_LOOK,
+  XI_PREF_USE_APP_DATA,
+  XI_PREF_AUTOSEL_ON_MOUSE,
+  XI_PREF_CELL_BTN_ICON_X,
+  XI_PREF_CELL_BTN_ICON_Y,
+  XI_PREF_COLUMN_OFFSET,
+  XI_PREF_SB_OFFSET,
+  XI_PREF_SB_WIDTH,
+  XI_PREF_SB_HEIGHT,
+  XI_PREF_SIZE_CURSOR_RID,
+  XI_PREF_HAND_CURSOR_RID,
+  XI_PREF_VSIZE_CURSOR_RID,
+  XI_PREF_COMBO_ICON,
+  XI_PREF_COLOR_LIGHT,
+  XI_PREF_COLOR_CTRL,
+  XI_PREF_COLOR_DARK,
+  XI_PREF_OPTIMIZE_CELL_REQUESTS,
+  XI_PREF_CARET_WIDTH,
+  XI_PREF_TRIPLE_CLICK_TIME,
+  XI_PREF_BUTTON_KEY,
+  XI_PREF_LIMIT_MIN_WIN_SIZE,
+  XI_PREF_DEFAULT_MAX_LINES_IN_CELL,
+  XI_PREF_UNUSED_PREFERENCE,
+  XI_PREF_NATIVE_CTRLS,
+  XI_PREF_ITF_TAB_CHAR,
+  XI_PREF_ITF_BACKTAB_CHAR,
+  XI_PREF_ITF_WS_RIGHT,       /* in form units */
+  XI_PREF_ITF_WS_BOTTOM,        /* in form units */
+  XI_PREF_VIR_SP_H,
+  XI_PREF_VIR_SP_V,
+  XI_PREF_DBL_PRESSES_BUTTON,
+  XI_PREF_CONTAINER_GRID_WIDTH,   /* in pixels */
+  XI_PREF_MULTILINE_QUICK_PASTE,
+  XI_PREF_COLOR_DISABLED,
+  XI_PREF_BUTTON_HEIGHT,
+  XI_PREF_BUTTON_PAD,
+  XI_PREF_HORZ_SPACING,
+  XI_PREF_VERT_SPACING,
+  XI_PREF_HORZ_PIXEL_SPACING,
+  XI_PREF_VERT_PIXEL_SPACING,
+  XI_PREF_ITF_MIN_TOP,        /* in pixels */
+  XI_PREF_ITF_MIN_LEFT,       /* in pixels */
+  XI_PREF_XIL,
+  XI_PREF_ASSERT_ON_NULL_CID, /* with xi_get_obj */
+  XI_PREF_LASTPREF          /* should always be last */
+}
+XI_PREF_TYPE;
+
+#define XI_NBR_PREFERENCES XI_PREF_LASTPREF
+
+/**********************************
+* XI Object definition structures
+**********************************/
+typedef enum _xi_btn_type
+{
+  XIBT_BUTTON,
+  XIBT_CHECKBOX,
+  XIBT_RADIOBTN,
+  XIBT_TABBTN,
+  XIBT_BUTTON_CHECKBOX,
+  XIBT_BUTTON_RADIOBTN
+}
+XI_BTN_TYPE;
+
+typedef enum _xi_obj_type
+{
+  XIT_BTN,
+  XIT_CONTAINER,
+  XIT_FORM,
+  XIT_FIELD,
+  XIT_GROUP,
+  XIT_LINE,
+  XIT_RECT,
+  XIT_TEXT,
+  XIT_CELL,
+  XIT_COLUMN,
+  XIT_ITF,
+  XIT_LIST,
+  XIT_ROW
+} 
+XI_OBJ_TYPE;
+
+typedef struct _xi_btn_def
+{
+  XI_BTN_TYPE type;
+  XI_RCT      xi_rct;
+  XI_RCT      pixel_rect;
+  unsigned long attrib;
+  char*       text;
+  int         tab_cid;
+  BOOLEAN     dflt;
+  int         down_icon_rid;
+  int         up_icon_rid;
+  int         disabled_icon_rid;
+  short       icon_x;
+  short       icon_y;
+  BOOLEAN     checked;
+  COLOR       fore_color;
+  BOOLEAN     drawable;
+} XI_BTN_DEF;
+
+typedef enum
+{
+  XI_STACK_HORIZONTAL,
+  XI_STACK_VERTICAL,
+  XI_GRID_HORIZONTAL,
+  XI_GRID_VERTICAL
+}
+XI_CONTAINER_ORIENTATION;
+
+typedef struct _xi_container_def
+{
+  XI_RCT   xi_rct;
+  XI_RCT   pixel_rect;
+  XI_CONTAINER_ORIENTATION orientation;
+  int      tab_cid;
+  short    btn_height; /* in form units */
+  short    btn_width;  /* in form units */
+  BOOLEAN  packed;   /* no space btwn btns, overlap 1 pixel in grid */
+} XI_CONTAINER_DEF;
+
+typedef struct _xi_field_def
+{
+  XI_PNT   pnt;     /* form units */
+  short    field_width;  /* form units */
+  XI_PNT   pixel_origin;
+  short    pixel_width;
+  short    pixel_button_distance;
+  XI_RCT   xi_rct;      /* if set, use text edit module */
+  unsigned long attrib;
+  int   tab_cid;
+  short text_size;
+  COLOR back_color;
+  COLOR enabled_color;  /* but inactive */
+  COLOR disabled_color;
+  COLOR disabled_back_color;
+  COLOR active_color;
+  COLOR active_back_color;
+  COLOR hilight_color;    /* for well and platform fields */
+  COLOR shadow_color;   /* for well and platform fields */
+  BOOLEAN button;
+  BOOLEAN button_on_left;
+  int icon_rid;
+  BOOLEAN well;
+  BOOLEAN platform;
+  BOOLEAN auto_tab;
+  FONT *font;
+  XVT_FNTID font_id;
+} XI_FIELD_DEF;
+
+typedef struct _xi_form_def
+{
+  int tab_cid;
+} XI_FORM_DEF;
+
+typedef struct _xi_group_def
+{
+  short nbr_cids;
+  int *cids;
+} XI_GROUP_DEF;
+
+typedef struct _xi_line_def
+{
+  XI_PNT  pnt1;
+  XI_PNT  pnt2;
+  XI_PNT  pixel_pnt1;
+  XI_PNT  pixel_pnt2;
+  COLOR   fore_color;
+  COLOR   back_color;  /* XVT/CH only */
+  BOOLEAN well;
+  unsigned long attrib;
+} XI_LINE_DEF;
+
+typedef struct _xi_rect_def
+{
+  XI_RCT xi_rct;
+  XI_RCT pixel_rect;
+  COLOR  fore_color;
+  COLOR  back_color;
+  COLOR  hilight_color;
+  COLOR  shadow_color;
+  BOOLEAN well; /* else platform */
+  BOOLEAN ridge;
+  unsigned long attrib;
+} XI_RECT_DEF;
+
+typedef struct _xi_text_def
+{
+  XI_RCT    xi_rct;
+  XI_RCT    pixel_rect;
+  unsigned long attrib;
+  char*     text;
+  FONT*     font;
+  XVT_FNTID font_id;
+  COLOR     fore_color;
+  COLOR     back_color;
+} XI_TEXT_DEF;
+
+typedef struct _xi_column_def
+{
+  unsigned long attrib;
+  short sort_number;
+  short width;       /* form units */
+  short pixel_width; /* alternate, pixel width */
+  short text_size;
+  char *heading_text;
+  BOOLEAN center_heading;
+  BOOLEAN heading_well;
+  BOOLEAN heading_platform;
+  BOOLEAN column_well;
+  BOOLEAN column_platform;
+  short position;
+  FONT *font;
+  XVT_FNTID font_id;
+  int icon_rid;
+  short icon_x;
+  short icon_y;
+  BOOLEAN size_rows;
+  BOOLEAN suppress_update_heading;
+  BOOLEAN suppress_update_cells;
+  BOOLEAN vertical_align_center;
+  BOOLEAN vertical_align_bottom;
+  BOOLEAN wrap_text;
+  BOOLEAN auto_tab;
+} XI_COLUMN_DEF;
+
+typedef struct _xi_itf_def
+{
+  XI_EVENT_HANDLER xi_eh;
+  RCT *rctp;
+  char *title;
+  BOOLEAN ctl_size;
+  BOOLEAN ctl_vscroll;
+  BOOLEAN ctl_hscroll;
+  BOOLEAN ctl_close;
+  BOOLEAN ctl_iconized;
+  BOOLEAN ctl_iconizable;
+  int menu_bar_rid;
+  WINDOW win;
+  WINDOW menu_win;
+  BOOLEAN size_win; /* automatically size window win */
+  BOOLEAN edit_menu;
+  COLOR back_color;
+  BOOLEAN automatic_back_color;
+  unsigned long attrib;
+  BOOLEAN virtual_itf;
+  BOOLEAN modal;
+  BOOLEAN size_font_to_win;
+  BOOLEAN tab_on_enter;
+  BOOLEAN use_whitespace;
+  int whitespace_right;
+  int whitespace_bottom;
+  FONT *font;
+  XVT_FNTID font_id;
+  BOOLEAN use_xil_win;
+} XI_ITF_DEF;
+
+typedef struct _xi_list_def
+{
+  XI_PNT xi_pnt;
+  short height;
+  short width;
+  XI_PNT  pixel_origin;
+  short   pixel_height;
+  short   pixel_width;
+  unsigned long attrib;
+  COLOR back_color;
+  COLOR enabled_color;  /* but inactive */
+  COLOR disabled_color;
+  COLOR disabled_back_color;
+  COLOR active_color;
+  COLOR active_back_color;
+  COLOR white_space_color;
+  COLOR rule_color;
+  BOOLEAN no_heading;
+  BOOLEAN one_row_list;
+  BOOLEAN scroll_bar;
+  BOOLEAN sizable_columns;
+  BOOLEAN movable_columns;
+  BOOLEAN scroll_bar_button;
+  short fixed_columns;
+  int tab_cid;
+  short min_cell_height;
+  short min_heading_height;
+  BOOLEAN no_horz_lines;
+  BOOLEAN no_vert_lines;
+  int start_percent;
+  int first_vis_column;
+  BOOLEAN drop_and_delete;
+  BOOLEAN select_cells;
+  BOOLEAN get_all_records;
+  BOOLEAN keep_all_records;
+  BOOLEAN resize_with_window;
+  FONT *font;
+  XVT_FNTID font_id;
+  int horz_sync_list;
+  int vert_sync_list;
+  BOOLEAN row_focus_border;
+  COLOR row_focus_border_color;
+  int max_lines_in_cell;
+  BOOLEAN single_select;
+  BOOLEAN retain_back_color_on_select;
+} XI_LIST_DEF;
+
+typedef struct _xi_obj_def
+{                  
+  XI_OBJ_TYPE type;
+  int cid;
+  struct _xi_obj_def *parent;
+  short nbr_children;
+  struct _xi_obj_def * *children;
+  long app_data;
+  long app_data2;
+  union
+    {
+    XI_BTN_DEF *btn;
+    XI_CONTAINER_DEF *container;
+    XI_FORM_DEF *form;
+    XI_FIELD_DEF *field;
+    XI_GROUP_DEF *group;
+    XI_LINE_DEF *line;
+    XI_RECT_DEF *rect;
+  XI_TEXT_DEF *text;
+  XI_COLUMN_DEF *column;
+  XI_ITF_DEF *itf;
+    XI_LIST_DEF *list;
+  } v;
+} XI_OBJ_DEF;
+
+/**********************************
+* XI Events
+**********************************/
+typedef enum _xi_event_type
+{
+  XIE_CHAR_FIELD,
+  XIE_DBL_FIELD,
+  XIE_CHG_FIELD,
+  XIE_OFF_FIELD,
+  XIE_ON_FIELD,
+  XIE_OFF_GROUP,
+  XIE_ON_GROUP,
+  XIE_OFF_FORM,
+  XIE_ON_FORM,
+  XIE_VIR_PAN,
+  XIE_XVT_EVENT,
+  XIE_XVT_POST_EVENT,
+  XIE_INIT,
+  XIE_BUTTON,
+  XIE_CHAR_CELL,
+  XIE_CLEANUP,
+  XIE_CLOSE,
+  XIE_COMMAND,
+  XIE_DBL_CELL,
+  XIE_GET_FIRST,
+  XIE_GET_LAST,
+  XIE_GET_NEXT,
+  XIE_GET_PERCENT,
+  XIE_GET_PREV,
+  XIE_CELL_REQUEST,
+  XIE_CHG_CELL,
+  XIE_OFF_CELL,
+  XIE_ON_CELL,
+  XIE_OFF_ROW,
+  XIE_ON_ROW,
+  XIE_OFF_COLUMN,
+  XIE_ON_COLUMN,
+  XIE_OFF_LIST,
+  XIE_ON_LIST,
+  XIE_REC_ALLOCATE,
+  XIE_REC_FREE,
+  XIE_ROW_SIZE,
+  XIE_SELECT,
+  XIE_UPDATE,
+  XIE_COL_DELETE,
+  XIE_COL_MOVE,
+  XIE_COL_SIZE,
+  XIE_POST_NAVIGATION
+}
+XI_EVENT_TYPE;
+
+struct _xi_obj;
+
+typedef struct _xi_event
+{
+  XI_EVENT_TYPE type;
+  BOOLEAN refused;
+  union
+    {
+    EVENT xvte;
+    struct _xi_obj *xi_obj;
+    struct xit_rec_request
+    {
+      struct _xi_obj *list;
+      long spec_rec;
+      long data_rec;
+      short percent;
+      unsigned long attrib;
+      COLOR color;
+      int row_height;
+      BOOLEAN has_focus;
+    } rec_request;
+    struct xit_rec_allocate
+    {
+      struct _xi_obj *list;
+      long record;
+    } rec_allocate;
+    struct xit_rec_free
+    {
+      struct _xi_obj *list;
+      long record;
+    } rec_free;
+    struct xit_get_percent
+    {
+      struct _xi_obj *list;
+      long record;
+      short percent;
+    } get_percent;
+  struct xit_select
+  {
+    struct _xi_obj *xi_obj;
+    BOOLEAN selected;
+    BOOLEAN dbl_click;
+    BOOLEAN shift;
+    BOOLEAN control;
+    int column;
+    long* records;
+  } select;
+  struct xit_cell_request
+  {
+    struct _xi_obj *list;
+    char *s;
+    short len;
+    long rec;
+    short col_nbr;
+    int icon_rid;
+    unsigned long attrib;
+    COLOR color;
+    COLOR back_color;
+    FONT *font;
+    XVT_FNTID font_id;
+    BOOLEAN button;
+    BOOLEAN button_on_left;
+    BOOLEAN button_on_focus;
+    int button_icon_rid;
+    long *records;
+  } cell_request;
+  struct xit_row_size
+    {
+      struct _xi_obj *xi_obj;
+      int new_row_height;
+    } row_size;
+    struct xit_cmd
+    {
+      int tag;
+      BOOLEAN shift;
+      BOOLEAN control;
+    } cmd;
+    struct xit_chr
+    {
+      struct _xi_obj *xi_obj;
+      int ch;
+      BOOLEAN shift;
+      BOOLEAN control;
+      BOOLEAN is_paste;
+    } chr;
+    struct xit_vir_pan
+    {
+      BOOLEAN before_pan;       /* else after */
+      int delta_x;
+      int delta_y;
+  } vir_pan;
+    struct xit_column
+    {
+      struct _xi_obj *list;
+      int   col_nbr;    /* column to move, size, delete */
+      int   new_col_nbr;
+      BOOLEAN in_fixed;
+      int   new_col_width;  /* form units */
+    int   new_col_pixel_width;  /* form units */
+  } column;
+    long user_data;
+  } v;
+} XI_EVENT;
+
+
+/***************************************************
+* XI Object Macros
+* Use these macros to fill in the appropriate
+* fields of an XI_OBJ struct for synthesizing
+* cells, rows, and columns.
+***************************************************/
+#define XI_MAKE_CELL(objp, listobj, row_nbr, column_nbr) \
+  memset((char *)objp, '\0', (size_t)sizeof(XI_OBJ)), \
+  ((objp)->itf = (listobj)->parent, \
+  (objp)->parent = listobj, \
+  (objp)->type = XIT_CELL, \
+  (objp)->v.cell.row = row_nbr, \
+  (objp)->v.cell.column = column_nbr, \
+  (objp)->nbr_children = 0)
+
+#define XI_MAKE_ROW(objp, listobj, row_nbr) \
+  memset((char *)objp, '\0', (size_t)sizeof(XI_OBJ)), \
+  ((objp)->itf = (listobj)->parent, \
+  (objp)->parent = listobj, \
+  (objp)->type = XIT_ROW, \
+  (objp)->v.row = row_nbr, \
+  (objp)->nbr_children = 0)
+
+/***************************************************
+* XI Object data
+*
+* NOTE: Applications cannot use or rely upon data
+* found in the XI_INTERNAL section of these structures
+* Applications should use the non-XI_INTERNAL fields
+* when referring to these objects.
+*
+* The cid field is unused for objects of type
+* XIT_CELL, XIT_ROW and XIT_COLUMN
+***************************************************/
+
+#ifdef __cplusplus
+struct _xi_column_data;
+struct _xi_itf_data;
+struct _xi_list_data;
+struct _xi_container_data;
+struct _xi_btn_data;
+struct _xi_field_data;
+struct _xi_form_data;
+struct _xi_group_data;
+struct _xi_line_data;
+struct _xi_rect_data;
+struct _xi_text_data;
+#define STRUCT
+#else
+#define STRUCT struct
+#endif
+
+typedef struct _xi_cell_data
+{
+  unsigned char row;
+  unsigned char column;
+  unsigned char is_vert_scrolled;
+} XI_CELL_DATA;
+
+typedef struct _xi_row_data
+{
+  short         row;
+  unsigned char is_vert_scrolled;
+} XI_ROW_DATA;
+
+typedef struct _xi_obj
+{
+  int cid;
+  struct _xi_obj *itf;
+  struct _xi_obj *parent;
+  XI_OBJ_TYPE type;
+  short nbr_children;
+  struct _xi_obj * *children;
+  long app_data;
+  long app_data2;
+  union
+    {
+    XI_CELL_DATA cell;
+    XI_ROW_DATA  row_data;
+    short        row;
+#ifdef XI_INTERNAL
+    STRUCT _xi_column_data *column;
+    STRUCT _xi_itf_data *itf;
+    STRUCT _xi_list_data *list;
+    STRUCT _xi_container_data *container;
+    STRUCT _xi_btn_data *btn;
+    STRUCT _xi_field_data *field;
+    STRUCT _xi_form_data *form;
+    STRUCT _xi_group_data *group;
+    STRUCT _xi_line_data *line;
+    STRUCT _xi_rect_data *rect;
+  STRUCT _xi_text_data *text;
+#else
+    /* so that union has room for a ptr */
+    char *dummy;
+#endif
+  } v;
+} XI_OBJ;
+
+#if ! XVT_CC_PROTO
+typedef void (* XVT_CALLCONV1 XI_EH_TYPE)();
+#else
+#if (XIWS == XOLWS)
+typedef void (* XVT_CALLCONV1 XI_EH_TYPE)();
+#else
+typedef void (* XVT_CALLCONV1 XI_EH_TYPE)(XI_OBJ *itf, struct _xi_event *xiev);
+#endif
+#endif
+
+#ifdef XI_INTERNAL
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_btn_data
+{
+  XI_BTN_TYPE type;
+  int tab_cid;
+  unsigned long attrib;
+  int down_icon_rid;
+  int up_icon_rid;
+  int disabled_icon_rid;
+  short icon_x;
+  short icon_y;
+  WINDOW btnctl;
+  RCT rct;      /* bounding rectangle in pixels */
+  XI_RCT xi_rct;    /* original bounding rect in form units */
+  char *text;
+  COLOR fore_color;
+  BOOLEAN drawable;
+  BOOLEAN checked;
+  BOOLEAN down;
+  BOOLEAN down_in_btn;
+  BOOLEAN dflt;
+  BOOLEAN packed;     /* no focus or default rect space */
+} XI_BTN_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_container_data
+{           /* copied from XI_CONTAINER_DEF */
+  XI_RCT  xi_rct;     /* original container rect in form units */
+  XI_CONTAINER_ORIENTATION  orientation;
+  int   tab_cid;
+  short btn_height;   /* original button height in form units */
+  short btn_width;    /* original button width in form units */
+  short nbr_buttons;  /* number of buttons used in calculations */
+  BOOLEAN packed;     /* no padding or focus rect space */
+  /* calculated */
+  RCT   rct;
+  short nbr_down;   /* number of buttons down in the container */
+  short nbr_across;   /* number of buttons across the container */
+  short pix_height;   /* button height in pixels */
+  short pix_width;    /* button width in pixels */
+  short step_down;    /* pixels from top edge to next top edge */
+  short step_across;  /* pixels from left edge to next left edge */
+} XI_CONTAINER_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_field_data
+{
+  STX    stx;
+  int    tab_cid;
+  XI_RCT xi_rct;
+  XI_PNT xi_pnt;
+  int    field_width;
+  RCT    rct;
+  BOOLEAN button;
+  BOOLEAN button_on_left;
+  int     icon_rid;
+  BOOLEAN down;
+  BOOLEAN down_in_btn;
+  RCT btn_rct;
+  BOOLEAN well;
+  BOOLEAN platform;
+  BOOLEAN font_set;
+} XI_FIELD_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_form_data
+{
+  XI_OBJ *focus_field;
+  unsigned long attrib;
+  int tab_cid;
+} XI_FORM_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_group_data
+{
+  short nbr_cids;
+  int *cidlist;
+  XI_OBJ * *objlist;
+} XI_GROUP_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_line_data
+{
+  PNT pnt1;
+  PNT pnt2;
+  XI_PNT xi_pnt1;
+  XI_PNT xi_pnt2;
+  COLOR fore_color;
+  COLOR back_color;
+  BOOLEAN well;
+  unsigned long attrib;
+} XI_LINE_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_rect_data
+{
+  RCT rct;
+  XI_RCT xi_rct;
+  COLOR fore_color;
+  COLOR back_color;
+  COLOR hilight_color;
+  COLOR shadow_color;
+  BOOLEAN well;
+  BOOLEAN ridge;
+  unsigned long attrib;
+} XI_RECT_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_text_data
+{
+  RCT rct;
+  XI_RCT xi_rct;
+  short text_size;
+  char *text;
+  unsigned long attrib;
+  FONT_OBJ *font;
+  COLOR fore_color;
+  COLOR back_color;
+} XI_TEXT_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_column_data
+{
+  short sort_number;
+} XI_COLUMN_DATA;
+
+/* XI INTERNAL USE ONLY */
+typedef struct _xi_itf_data
+{
+  unsigned short magic;
+  WINDOW xvt_win;
+  WINDOW menu_win;
+  XI_EVENT_HANDLER xi_eh;
+  XI_OBJ *focus_obj;
+  XI_OBJ *trap_obj;
+  BOOLEAN trap_explicit;
+  CURSOR cursor;
+  BOOLEAN half_baked;
+  BOOLEAN edit_menu;
+  BOOLEAN paste_enable;
+  BOOLEAN cut_or_copy_enable;
+  COLOR back_color;
+  BOOLEAN automatic_back_color;
+  BOOLEAN virtual_itf;
+  BOOLEAN modal;
+  BOOLEAN size_font_to_win;
+  BOOLEAN tab_on_enter;
+  RCT original_win_rct;
+  int original_font_size;
+  WINDOW prev_modal;
+  XI_PNT max_xi_pnt;
+  XI_PNT phys_xi_pnt;
+  XI_PNT win_xi_pnt;
+  int delta_x;
+  int delta_y;
+  int caret_x;
+  int caret_y;
+  int caret_height;
+  BOOLEAN caret_is_on;
+  BOOLEAN mouse_is_down;
+  BOOLEAN closing;
+  int in_callback;
+  XI_OBJ *update_obj;
+  FONT_OBJ *font;
+  int fu_width;
+  int fu_height;
+  int nbr_font_ids;
+  FONT_OBJ *font_ids;
+  BOOLEAN moving_focus;
+  BOOLEAN chg_flag;
+#if XIWS == WMWS
+  int coalescing;
+  BOOLEAN invalidated;
+  RCT inv_rct;
+#endif
+  BOOLEAN use_xil_win;
+  BOOLEAN pasting;
+} XI_ITF_DATA;
+
+/* XI INTERNAL USE ONLY */
+#define FOCUS_CELL_ARRAY_LEN 6
+typedef struct _xi_list_data
+{
+  XI_PNT  xi_pnt;
+  int     height;
+  int     tab_cid;
+  BOOLEAN scroll_bar;
+  BOOLEAN one_row_list;
+  short   sb_offset;
+  short   sb_width;
+  BOOLEAN movable_columns;
+  BOOLEAN scroll_bar_button;
+  short   width;
+  XI_OBJ* focus_cell;
+  XI_OBJ  focus_cell_array[FOCUS_CELL_ARRAY_LEN];
+  LM      lm;
+  WINDOW  sb_win;
+  WINDOW  hsb_win;
+  RCT     sbb_rct;
+  BOOLEAN down_in_btn;
+  BOOLEAN down;
+  int     start_percent;
+  XI_CELL_SPEC* cell_spec;
+  BOOLEAN have_sb_rct;
+  RCT     sb_rct;
+  BOOLEAN have_hsb_rct;
+  RCT     hsb_rct;
+  FONT_OBJ* font;
+  int       horz_sync_list;
+  int       vert_sync_list;
+  BOOLEAN   row_focus_border;
+  COLOR     row_focus_border_color;
+  int       max_lines_in_cell;
+  BOOLEAN   scrolling_in_progress;
+  BOOLEAN   done_initial_xi_scroll;
+  BOOLEAN   single_select;
+} XI_LIST_DATA;
+#endif    /* XI_INTERNAL */
+
+/**********************************
+* XI Metrics and preferences
+**********************************/
+typedef enum
+{
+  XI_SV_FU_HEIGHT,
+  XI_SV_FU_WIDTH,
+  XI_SV_ITF_BORDER,
+  XI_SV_SYSFONT_HEIGHT,
+  XI_SV_SYSFONT_ASCENT,
+  XI_SV_SYSFONT_DESCENT,
+  XI_SV_SYSFONT_LEADING,
+  XI_SV_LASTSV        /* should always be last */
+}
+XI_SV_TYPE;
+#define XI_NBR_SYSVALS XI_SV_LASTSV
+
+typedef struct _xi_eq
+{
+  XI_EVENT xiev;
+  XI_OBJ *itf;
+  struct _xi_eq *next;
+} XI_EQ;
+
+typedef struct _xi_window_list
+{
+  struct _xi_window_list *next;
+  WINDOW win;
+  XI_OBJ *itf;
+} XI_WINDOW_LIST;
+
+typedef struct _xi_scroll_record_arg
+{
+  XI_OBJ *xi_obj;
+  long record;
+  COLOR row_color;
+  unsigned long attrib;
+  int row_height;
+  BOOLEAN rec_at_top;
+} XI_SCROLL_RECORD_ARG;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_button_def XVT_CC_ARGS((XI_OBJ_DEF *parent,
+                                            int cid, XI_RCT *rct,
+                                            unsigned long attrib, char *text,
+                              int tab_cid));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_container_def XVT_CC_ARGS((XI_OBJ_DEF *itf,
+                                              int cid, XI_RCT* xi_rct,
+                                              XI_CONTAINER_ORIENTATION orientation,
+                                              int tab_cid));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_field_def XVT_CC_ARGS((XI_OBJ_DEF *form,
+                                          int cid, int v, int h,
+                                          int field_width,
+                                          unsigned long attrib, int tab_cid,
+                                          int text_size, COLOR enabled_color,
+                                          COLOR back_color,
+                            COLOR disabled_color,
+                                          COLOR disabled_back_color,
+                                          COLOR active_color));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_form_def XVT_CC_ARGS((XI_OBJ_DEF *itf, int cid,
+                                          int tab_cid));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_group_def XVT_CC_ARGS((XI_OBJ_DEF *object,
+                                          int cid, int nbr_cids,
+                                          int *cid_list));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_line_def XVT_CC_ARGS((XI_OBJ_DEF *itf, int cid,
+                                          XI_PNT *pnt1, XI_PNT *pnt2,
+                                          unsigned long attrib,
+                            COLOR fore_color, COLOR back_color,
+                                          BOOLEAN well));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_rect_def XVT_CC_ARGS((XI_OBJ_DEF* itf, int cid,
+                                          XI_RCT* rct, unsigned long attrib,
+                                          COLOR fore_color, COLOR back_color));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_text_def XVT_CC_ARGS((XI_OBJ_DEF* itf, int cid,
+                            XI_RCT* rct, unsigned long attrib,
+                            char* text));
+int         XVT_CALLCONV1 xi_button_calc_pixel_height XVT_CC_ARGS((
+                                                      int height ));
+int         XVT_CALLCONV1 xi_button_calc_pixel_width XVT_CC_ARGS(( int width ));
+int         XVT_CALLCONV1 xi_button_def_get_width XVT_CC_ARGS((
+                                                  XI_OBJ_DEF* obj_def ));
+void        XVT_CALLCONV1 xi_check XVT_CC_ARGS((XI_OBJ *xi_obj, BOOLEAN check));
+int         XVT_CALLCONV1 xi_container_def_get_btn_width XVT_CC_ARGS((
+                                                        XI_OBJ_DEF* obj_def ));
+int         XVT_CALLCONV1 xi_container_def_get_height XVT_CC_ARGS((
+                                                      XI_OBJ_DEF* obj_def ));
+int         XVT_CALLCONV1 xi_container_def_get_width XVT_CC_ARGS((
+                                                    XI_OBJ_DEF* obj_def ));
+void        XVT_CALLCONV1 xi_container_reorient XVT_CC_ARGS((XI_OBJ *cnt_obj,
+                                                XI_CONTAINER_DEF *cnt_def));
+int         XVT_CALLCONV1 xi_get_fixed_columns XVT_CC_ARGS( (XI_OBJ* xi_obj) );
+long        XVT_CALLCONV1 xi_get_handle XVT_CC_ARGS( (XI_OBJ* list,
+                                                      XI_OBJ* child_obj ) );
+TXEDIT      XVT_CALLCONV1 xi_get_txedit XVT_CC_ARGS((XI_OBJ *xi_obj));
+BOOLEAN     XVT_CALLCONV1 xi_is_checked XVT_CC_ARGS((XI_OBJ *xi_obj));
+void        XVT_CALLCONV1 xi_set_fixed_columns XVT_CC_ARGS( (XI_OBJ *xi_obj,
+                                              int fixed_columns) );
+void        XVT_CALLCONV1 xi_set_fore_color XVT_CC_ARGS((XI_OBJ *xi_obj,
+                                            COLOR color));
+void        XVT_CALLCONV1 xi_vir_pan XVT_CC_ARGS((XI_OBJ *xi_obj, int delta_x,
+                                                int delta_y));
+int         XVT_CALLCONV1 xi_button_calc_height_font_id XVT_CC_ARGS((
+                                                        XVT_FNTID font ));
+int         XVT_CALLCONV1 xi_field_calc_height_font_id XVT_CC_ARGS((
+                                                      XVT_FNTID font ));
+int         XVT_CALLCONV1 xi_field_calc_width_font_id XVT_CC_ARGS((
+                                                      XVT_FNTID font,
+                                                      char* string ));
+
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_column_def XVT_CC_ARGS((XI_OBJ_DEF *list,
+                                            int cid, unsigned long attrib,
+                                            int sort_number, int width,
+                              int text_size, char *heading_text));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_add_list_def XVT_CC_ARGS((XI_OBJ_DEF *itf, int cid,
+                            int v, int h, int height,
+                            unsigned long attrib,
+                            COLOR enabled_color, COLOR back_color,
+                            COLOR disabled_color,
+                            COLOR disabled_back_color,
+                            COLOR active_color, int tab_cid));
+BOOLEAN     XVT_CALLCONV1 xi_button_set_default XVT_CC_ARGS((XI_OBJ* xi_obj,
+                                        BOOLEAN set));
+void        XVT_CALLCONV1 xi_cell_request XVT_CC_ARGS((XI_OBJ *xi_obj));
+void        XVT_CALLCONV1 xi_clean_up XVT_CC_ARGS((void));
+XI_OBJ*     XVT_CALLCONV1 xi_create XVT_CC_ARGS((XI_OBJ *parent,
+                        XI_OBJ_DEF* xi_obj_def));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_create_itf_def XVT_CC_ARGS((int cid,
+                              XI_EVENT_HANDLER xi_eh, RCT *rctp,
+                              char *title, long app_data));
+void        XVT_CALLCONV1 xi_delete XVT_CC_ARGS((XI_OBJ *xi_obj));
+BOOLEAN     XVT_CALLCONV1 xi_delete_row XVT_CC_ARGS((XI_OBJ *xi_obj));
+void        XVT_CALLCONV1 xi_dequeue XVT_CC_ARGS((void));
+void        XVT_CALLCONV1 xi_event XVT_CC_ARGS((WINDOW win, EVENT *ep));
+void        XVT_CALLCONV1 xi_fu_to_pu XVT_CC_ARGS((XI_OBJ *itf, PNT *pnts,
+                          int nbr_pnts));
+long        XVT_CALLCONV1 xi_get_app_data XVT_CC_ARGS((XI_OBJ *xi_obj));
+long        XVT_CALLCONV1 xi_get_app_data2 XVT_CC_ARGS((XI_OBJ *xi_obj));
+unsigned long XVT_CALLCONV1 xi_get_attrib XVT_CC_ARGS((XI_OBJ *xi_obj));
+XI_CELL_SPEC* XVT_CALLCONV1 xi_get_cell_selection XVT_CC_ARGS((XI_OBJ *list,
+                                  int *nbr_cells));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_get_def XVT_CC_ARGS((XI_OBJ *obj));
+RCT*        XVT_CALLCONV1 xi_get_def_rect XVT_CC_ARGS((XI_OBJ_DEF *xi_obj_def,
+                            RCT *rctp));
+XI_OBJ*     XVT_CALLCONV1 xi_get_focus XVT_CC_ARGS((XI_OBJ *itf));
+XI_OBJ*     XVT_CALLCONV1 xi_get_itf XVT_CC_ARGS((WINDOW win));
+XI_OBJ_DEF* XVT_CALLCONV1 xi_get_list_def XVT_CC_ARGS((XI_OBJ *list));
+long*       XVT_CALLCONV1 xi_get_list_info XVT_CC_ARGS((XI_OBJ *list,
+                            int *nbr_recs));
+XI_OBJ**    XVT_CALLCONV1 xi_get_member_list XVT_CC_ARGS((XI_OBJ *xi_obj,
+                              int *nbr_members));
+long        XVT_CALLCONV1 xi_get_pref XVT_CC_ARGS((XI_PREF_TYPE preftype));
+XI_OBJ*     XVT_CALLCONV1 xi_get_obj XVT_CC_ARGS((XI_OBJ *itf, int cid));
+RCT*        XVT_CALLCONV1 xi_get_rect XVT_CC_ARGS((XI_OBJ *xi_obj, RCT *rctp));
+void        XVT_CALLCONV1 xi_get_sel XVT_CC_ARGS((XI_OBJ *xi_obj, int *selstart,
+                        int *selstop));
+int         XVT_CALLCONV1 xi_get_sysval XVT_CC_ARGS((XI_SV_TYPE valtype));
+char*       XVT_CALLCONV1 xi_get_text XVT_CC_ARGS((XI_OBJ *xi_obj, char *s,
+                          int len));
+WINDOW      XVT_CALLCONV1 xi_get_window XVT_CC_ARGS((XI_OBJ *xi_obj));
+int         XVT_CALLCONV1 xi_get_visible_rows XVT_CC_ARGS((XI_OBJ *xi_obj,
+                              int *first_vis, int *last_vis));
+void        XVT_CALLCONV1 xi_get_visible_columns XVT_CC_ARGS((XI_OBJ *xi_obj,
+                                int *first_vis,
+                                int *last_vis));
+void        XVT_CALLCONV1 xi_set_fixed_columns XVT_CC_ARGS(( XI_OBJ* xi_obj,
+                                int new_fixed_count ));
+XI_RCT*     XVT_CALLCONV1 xi_get_xi_rct XVT_CC_ARGS((XI_OBJ *itf,
+                          XI_RCT *xi_rct));
+void        XVT_CALLCONV1 xi_init XVT_CC_ARGS((void));
+BOOLEAN     XVT_CALLCONV1 xi_insert_row XVT_CC_ARGS((XI_OBJ *list, int row));
+BOOLEAN     XVT_CALLCONV1 xi_is_changed XVT_CC_ARGS((XI_OBJ* obj));
+BOOLEAN     XVT_CALLCONV1 xi_is_itf XVT_CC_ARGS((XI_OBJ *itf));
+BOOLEAN     XVT_CALLCONV1 xi_is_window XVT_CC_ARGS((WINDOW win));
+BOOLEAN     XVT_CALLCONV1 xi_is_focus_moving XVT_CC_ARGS((XI_OBJ *xi_obj));
+BOOLEAN     XVT_CALLCONV1 xi_is_auto_tab XVT_CC_ARGS((XI_OBJ *xi_obj));
+
+int         XVT_CALLCONV1 xi_list_def_get_client_height XVT_CC_ARGS((
+                                                        XI_OBJ_DEF* list_def,
+                                      int rows ));
+int         XVT_CALLCONV1 xi_list_def_get_client_width XVT_CC_ARGS((
+                                                      XI_OBJ_DEF* obj_def,
+                                                      int columns ));
+int         XVT_CALLCONV1 xi_list_def_get_outer_height XVT_CC_ARGS((
+                                                      XI_OBJ_DEF* list_def,
+                                                      int rows ));
+int         XVT_CALLCONV1 xi_list_def_get_outer_width XVT_CC_ARGS((
+                                                      XI_OBJ_DEF* obj_def,
+                                                      int columns ));
+int         XVT_CALLCONV1 xi_list_def_get_rows XVT_CC_ARGS((
+                                XI_OBJ_DEF* list_def ));
+
+void        XVT_CALLCONV1 xi_move_column XVT_CC_ARGS((XI_OBJ *column,
+                                        int position));
+BOOLEAN     XVT_CALLCONV1 xi_move_focus XVT_CC_ARGS((XI_OBJ *xi_obj));
+void        XVT_CALLCONV1 xi_move_to XVT_CC_ARGS((WINDOW win, PNT pnt));
+WINDOW      XVT_CALLCONV1 xi_new_child_window XVT_CC_ARGS((RCT *rctp,
+                                              char *title, WIN_TYPE t,
+                                              BOOLEAN ctl_size,
+                                              BOOLEAN ctl_vscroll,
+                                              BOOLEAN ctl_hscroll,
+                              BOOLEAN ctl_close,
+                              BOOLEAN ctl_iconized,
+                              BOOLEAN ctl_iconizable,
+                              WINDOW parent,
+                                long app_data, short reserve1,
+                              long reserve2, BOOLEAN visible,
+                              BOOLEAN enabled,
+                                              int menu_bar_rid));
+  void XVT_CALLCONV1 xi_pu_to_fu XVT_CC_ARGS((XI_OBJ *itf, PNT *pnts, int nbr_pnts));
+  int XVT_CALLCONV1 xi_scroll XVT_CC_ARGS((XI_OBJ *xi_obj, int nbr_lines));
+  int XVT_CALLCONV1 xi_scroll_rec XVT_CC_ARGS((XI_OBJ *xi_obj, long record, COLOR row_color, unsigned
+    long attrib, int row_height));
+  int XVT_CALLCONV1 xi_scroll_record XVT_CC_ARGS((XI_SCROLL_RECORD_ARG *arg));
+  int XVT_CALLCONV1 xi_scroll_percent XVT_CC_ARGS((XI_OBJ *xi_obj, int percent));
+  void XVT_CALLCONV1 xi_set_app_data XVT_CC_ARGS((XI_OBJ *xi_obj, long app_data));
+  void XVT_CALLCONV1 xi_set_app_data2 XVT_CC_ARGS((XI_OBJ *xi_obj, long app_data2));
+  void XVT_CALLCONV1 xi_set_attrib XVT_CC_ARGS((XI_OBJ *xi_obj, unsigned long attrib));
+  void XVT_CALLCONV1 xi_set_bufsize XVT_CC_ARGS((XI_OBJ *xi_obj, int size));
+  void XVT_CALLCONV1 xi_set_color XVT_CC_ARGS((XI_OBJ *xi_obj, XI_COLOR_PART part, COLOR color));
+  void XVT_CALLCONV1 xi_set_column_width XVT_CC_ARGS(( XI_OBJ *xi_obj,
+      int width));
+  void XVT_CALLCONV1 xi_column_set_pixel_width XVT_CC_ARGS(( XI_OBJ *xi_obj,
+    int width ));
+  void XVT_CALLCONV1 xi_set_focus XVT_CC_ARGS((XI_OBJ *xi_obj));
+  void XVT_CALLCONV1 xi_set_font_id XVT_CC_ARGS((XVT_FNTID font_id));
+  void XVT_CALLCONV1 xi_set_list_size XVT_CC_ARGS((XI_OBJ *xi_obj, int height, int width));
+  void XVT_CALLCONV1 xi_set_obj_font_id XVT_CC_ARGS((XI_OBJ *xi_obj, XVT_FNTID font_id));
+  void XVT_CALLCONV1 xi_set_icon XVT_CC_ARGS((XI_OBJ *xi_obj, int icon_rid, int down_icon_rid));
+  void XVT_CALLCONV1 xi_set_pref XVT_CC_ARGS((XI_PREF_TYPE preftype, long value));
+  void XVT_CALLCONV1 xi_set_sel XVT_CC_ARGS((XI_OBJ *xi_obj, int selstart, int selstop));
+  void XVT_CALLCONV1 xi_set_row_height XVT_CC_ARGS((XI_OBJ *xi_obj, int height));
+  void XVT_CALLCONV1 xi_set_text XVT_CC_ARGS((XI_OBJ *xi_obj, char *s));
+  void XVT_CALLCONV1 xi_event_debug XVT_CC_ARGS((char *tag, XI_EVENT *xiev, char *s, int len));
+
+  char * XVT_CALLCONV1 gstrncpy XVT_CC_ARGS((char *dst, char *src, int n));
+
+  /*
+XI consistant drawing functions - these functions perform identically
+on all platforms.  These functions also do virtual interface coordinate
+conversion.
+*/
+  void XVT_CALLCONV1 xi_get_font_metrics XVT_CC_ARGS((WINDOW win, int *leadingp, int *ascentp, int *descentp));
+  void XVT_CALLCONV1 xi_set_xvt_font XVT_CC_ARGS((WINDOW win, FONT_OBJ *font, BOOLEAN scale));
+  void XVT_CALLCONV1 xi_set_draw_ctools XVT_CC_ARGS((WINDOW win, DRAW_CTOOLS *ct));
+  void XVT_CALLCONV1 xi_scroll_rect XVT_CC_ARGS((WINDOW win, RCT *rctp, int dh, int dv));
+  void XVT_CALLCONV1 xi_set_draw_mode XVT_CC_ARGS((WINDOW win, DRAW_MODE mode));
+  void XVT_CALLCONV1 xi_set_cbrush XVT_CC_ARGS((WINDOW win, CBRUSH *cbrush));
+  void XVT_CALLCONV1 xi_set_cpen XVT_CC_ARGS((WINDOW win, CPEN *cpen));
+  void XVT_CALLCONV1 xi_draw_icon XVT_CC_ARGS((WINDOW win, int x, int y, int rid,
+      COLOR fore_color, COLOR back_color));
+  void XVT_CALLCONV1 xi_set_xvt_fore_color XVT_CC_ARGS((WINDOW win, COLOR color));
+  void XVT_CALLCONV1 xi_set_xvt_back_color XVT_CC_ARGS((WINDOW win, COLOR color));
+  DRAW_CTOOLS * XVT_CALLCONV1 xi_get_draw_ctools XVT_CC_ARGS((WINDOW win, DRAW_CTOOLS *ct));
+  int XVT_CALLCONV1 xi_xvt_get_text_width XVT_CC_ARGS((WINDOW win, char *string, int len));
+  void XVT_CALLCONV1 xi_set_clip XVT_CC_ARGS((WINDOW win, RCT *rctp));
+  void XVT_CALLCONV1 xi_draw_text XVT_CC_ARGS((WINDOW win, int x, int y, char *buf, int len));
+  void XVT_CALLCONV1 xi_caret_on XVT_CC_ARGS((WINDOW win, int x, int y, int height));
+  void XVT_CALLCONV1 xi_caret_off XVT_CC_ARGS((WINDOW win));
+  void XVT_CALLCONV1 xi_draw_3d_diamond XVT_CC_ARGS((WINDOW win, RCT *rctp, BOOLEAN well, BOOLEAN black,
+      int height, COLOR color));
+  void XVT_CALLCONV1 xi_draw_3d_line XVT_CC_ARGS((WINDOW win, PNT pnt1, PNT pnt2, BOOLEAN well));
+  void XVT_CALLCONV1 xi_draw_3d_rect XVT_CC_ARGS((WINDOW win, RCT *rctp, BOOLEAN well, int height, COLOR
+      color_light, COLOR color_ctrl, COLOR color_dark));
+  void XVT_CALLCONV1 xi_draw_diamond XVT_CC_ARGS((WINDOW win, RCT *rctp, BOOLEAN well, BOOLEAN black, BOOLEAN
+      fill,
+    COLOR color));
+  void XVT_CALLCONV1 xi_draw_rect XVT_CC_ARGS((WINDOW win, RCT *rctp));
+  void XVT_CALLCONV1 xi_draw_line XVT_CC_ARGS((WINDOW win, PNT pnt));
+  void XVT_CALLCONV1 xi_draw_text_attrib XVT_CC_ARGS((WINDOW win, int x, int y, char *s, int len, unsigned
+    long attrib));
+  void XVT_CALLCONV1 xi_draw_thick_rect XVT_CC_ARGS((WINDOW win, RCT *rctp, int width));
+  int XVT_CALLCONV1 xi_get_text_width XVT_CC_ARGS((WINDOW win, char *s, int len, unsigned long attrib));
+  void XVT_CALLCONV1 xi_invalidate_rect XVT_CC_ARGS((WINDOW win, RCT *rct));
+  BOOLEAN XVT_CALLCONV1 xi_needs_update XVT_CC_ARGS((WINDOW win, RCT *rct));
+  BOOLEAN XVT_CALLCONV1 xi_rect_intersect XVT_CC_ARGS((RCT *rctp, RCT *rctp1, RCT *rctp2));
+  void XVT_CALLCONV1 xi_trap_mouse XVT_CC_ARGS((WINDOW win));
+  void XVT_CALLCONV1 xi_release_mouse XVT_CC_ARGS((void));
+
+  /******************************************************************
+Tree module
+******************************************************************/
+#ifdef TREEDEBUG
+#define xi_tree_malloc(size, parent) \
+  xi_tree_malloc_d(size, parent, __LINE__, __FILE__)
+#define xi_tree_realloc(p, size) \
+  xi_tree_realloc_d(p, size, __LINE__, __FILE__)
+#endif
+#ifdef TREEDEBUG
+  void * XVT_CALLCONV1 xi_tree_malloc_d XVT_CC_ARGS((size_t size, void *parent, int line, char
+    *file));
+  void * XVT_CALLCONV1 xi_tree_realloc_d XVT_CC_ARGS((void *p, size_t size, int line, char *file));
+#else
+  void * XVT_CALLCONV1 xi_tree_malloc XVT_CC_ARGS((size_t size, void *parent));
+  void * XVT_CALLCONV1 xi_tree_realloc XVT_CC_ARGS((void *p, size_t size));
+#endif
+  void XVT_CALLCONV1 xi_tree_reparent XVT_CC_ARGS((void *p, void *parent));
+  void XVT_CALLCONV1 xi_tree_free XVT_CC_ARGS((void *p));
+  void * XVT_CALLCONV1 xi_tree_get_parent XVT_CC_ARGS((void *p));
+  void XVT_CALLCONV1 xi_tree_dbg XVT_CC_ARGS((char *title));
+  void XVT_CALLCONV1 xi_tree_check_sanity XVT_CC_ARGS((char *title));
+  void XVT_CALLCONV1 xi_tree_reg_error_fcn XVT_CC_ARGS((void (* fcn)(void)));
+
+#ifdef __cplusplus
+}
+// End of extern "C"
+#endif
+
+#endif   /* INCL_XI */
+
diff --git a/xi/xi2.c b/xi/xi2.c
new file mode 100755
index 000000000..e368cb1a3
--- /dev/null
+++ b/xi/xi2.c
@@ -0,0 +1,3502 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#define XVT_INCL_NATIVE
+
+#define XI_INTERNAL
+#include "xi.h"
+#include "xitext.h"
+#include "xistx.h"
+#include "xilm.h"
+#include "xiutils.h"
+#include "xvtmenu.h"
+#include "xi_int.h"
+
+#if XIWS == MTFWS
+#include <X11/Intrinsic.h>
+#include <Xm/Xm.h>
+#endif
+
+#if XI_IS_CH
+#undef strcmp
+#define strcmp(a, b) strcmp(a, b)
+#endif
+
+#if XVT_OS == XVT_OS_CTOS
+#define BORDER_WIDTH ((npctos_env == CHSERVICE) ? 8 : 2)
+#define EDIT_BORDER_WIDTH_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#define EDIT_BORDER_SPACE_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#else
+#if XIWS == WMWS
+#define BORDER_WIDTH 8
+#define EDIT_BORDER_WIDTH_Y 0
+#define EDIT_BORDER_SPACE_Y 0
+#else
+#define BORDER_WIDTH 2
+#define EDIT_BORDER_WIDTH_Y 1
+#define EDIT_BORDER_SPACE_Y 1
+#endif
+#endif
+
+/******************************* STATIC DATA ********************************/
+static XI_EQ *xi_eq;
+static BOOLEAN inited = FALSE;
+static XI_WINDOW_LIST *xi_window_list;
+static char *list_parent;
+extern WINDOW xi_modal_win;
+
+/******************************** FUNCTIONS *********************************/
+BOOLEAN xi_compare_objs( XI_OBJ* obj_one, XI_OBJ* obj_two )
+{
+  if (obj_one == obj_two)
+    return(TRUE);
+  if ( obj_two != NULL && obj_two->type == XIT_CELL
+      && obj_one != NULL && obj_one->type == XIT_CELL
+      && obj_two->parent == obj_one->parent )
+  {
+    XI_CELL_DATA* cell_one = &obj_one->v.cell;
+    XI_CELL_DATA* cell_two = &obj_two->v.cell;
+
+    return cell_one->row == cell_two->row
+          && cell_one->column == cell_two->column
+          && cell_one->is_vert_scrolled == cell_two->is_vert_scrolled;
+  }
+  return FALSE;
+}
+
+
+static XI_OBJ * get_non_focus_cell_obj(XI_LIST_DATA *list_data)
+{
+  int i;
+
+  for (i = 0; i < FOCUS_CELL_ARRAY_LEN; ++i)
+    if (list_data->focus_cell == &list_data->focus_cell_array[i])
+      break;
+  i = (i + 1) % FOCUS_CELL_ARRAY_LEN;
+  return &list_data->focus_cell_array[i];
+}
+
+XI_OBJ *
+xi_search_itf(XI_OBJ *xi_obj,
+XI_SEARCH_TYPE search_type, int parm1)
+{
+  XI_OBJ *obj;
+  XI_OBJ * *objp;
+  int i, column, tab_cid;
+  unsigned long attrib;
+  XI_OBJ *cell_obj;
+  XI_LIST_DATA *list_data;
+  LM lm;
+
+  switch (search_type)
+  {
+  case XI_SEARCH_FOR_FOCUSABLE:
+    switch (xi_obj->type)
+    {
+    case XIT_LIST:
+      lm = xi_obj->v.list->lm;
+      attrib = lm_get_attrib(lm, LM_LIST, 0, 0, FALSE);
+      if ((attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) !=
+          (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+        return NULL;
+      return(xi_obj);
+    case XIT_CELL:
+      return(xi_obj);
+    case XIT_COLUMN:
+      lm = xi_obj->parent->v.list->lm;
+      attrib = lm_get_attrib(lm, LM_LIST, 0, 0, FALSE);
+      if ((attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) !=
+          (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+        return NULL;
+      column = xi_obj_to_idx(xi_obj);
+      attrib = lm_get_attrib(lm, LM_COLUMN, column, 0, FALSE);
+      if ((attrib &
+          (XI_ATR_ENABLED | XI_ATR_SELECTABLE | XI_ATR_VISIBLE))
+          != (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+        return NULL;
+      else
+      {
+        list_data = xi_obj->parent->v.list;
+        cell_obj = get_non_focus_cell_obj(list_data);
+        cell_obj->v.cell.row = 0;
+        cell_obj->v.cell.column = (unsigned char)column;
+        return (cell_obj);
+      }
+    case XIT_FIELD:
+      attrib = stx_get_attrib(xi_obj->v.field->stx);
+      if ((attrib & XI_ATR_ENABLED) != 0 &&
+          (attrib & XI_ATR_VISIBLE) != 0)
+        return (xi_obj);
+      else
+        return NULL;
+    case XIT_BTN:
+#if XIWS == MACWS
+      return NULL;
+#else
+      {
+        unsigned long attrib;
+
+        attrib = xi_obj->v.btn->attrib;
+        if ((attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) ==
+            (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+          return xi_obj;
+        else
+          return NULL;
+      }
+#endif
+    case XIT_GROUP:
+      return NULL;
+    default:
+      break;
+    }
+    break;
+  case XI_SEARCH_FOR_TAB_CID:
+    switch (xi_obj->type)
+    {
+    case XIT_FIELD:
+      tab_cid = xi_obj->v.field->tab_cid;
+      break;
+    case XIT_BTN:
+      tab_cid = xi_obj->v.btn->tab_cid;
+      break;
+    case XIT_FORM:
+      tab_cid = xi_obj->v.form->tab_cid;
+      break;
+    case XIT_CONTAINER:
+      tab_cid = xi_obj->v.container->tab_cid;
+      break;
+    case XIT_LIST:
+      tab_cid = xi_obj->v.list->tab_cid;
+      break;
+    default:
+      tab_cid = -1;
+      break;
+    }
+    if (tab_cid == parm1)
+      return xi_obj;
+    break;
+  case XI_SEARCH_FOR_FIELD:
+    if (xi_obj->type == XIT_FIELD)
+      return xi_obj;
+    break;
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20002",
+      20002, "Internal XI error");   
+  }
+  /* search child list */
+  objp = xi_obj->children;
+  obj = NULL;
+  for (i = xi_obj->nbr_children; i > 0 && obj == NULL; i--, objp++)
+    obj = xi_search_itf(*objp, search_type, parm1);
+  return obj;
+}
+
+static void near
+xi_remove_from_parent_list(XI_OBJ *xi_obj)
+{
+  XI_OBJ *parent;
+  XI_OBJ * *list;
+  int n;
+  BOOLEAN copying_down = FALSE;
+
+  if ((parent = xi_obj->parent) == NULL)
+    return;
+  list = parent->children;
+  n = parent->nbr_children;
+  for (; n > 0; n--, list++)
+  {
+    if (copying_down)
+      list[-1] = *list;
+    if (*list == xi_obj)
+      copying_down = TRUE;
+  }
+  /* error if we did not find the child in the list */
+  xvt_errmsg_sig_if(!(copying_down), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20001",
+    20001, "XI: internal object deletion error");   
+  parent->nbr_children--;
+}
+
+/*
+  xi_find_next_obj: find the next control in the tabbing sequence.
+  The focus_obj parameter indicates the object that currently has
+  the focus.
+  The type of navigation is given by the tab_type parameter.
+*/
+XI_OBJ *
+xi_find_next_obj(XI_OBJ *focus_obj, XI_NEXT_TYPE tab_type, long c)
+{
+  XI_OBJ_TYPE type;
+  XI_OBJ *itf, *obj;
+  int tab_cid;
+
+  if (focus_obj == NULL || focus_obj->type == XIT_ITF)
+  {
+    /* find the first thing on the interface */
+    return(xi_search_itf(focus_obj->itf, XI_SEARCH_FOR_FOCUSABLE, 0));
+  }
+
+  type = focus_obj->type;
+  itf = focus_obj->itf;
+  switch (tab_type)
+  {
+  case XI_NEXT_FORM_TAB:
+  case XI_NEXT_ITF_TAB:
+    switch (tab_type)
+    {
+    case XI_NEXT_FORM_TAB:
+      if (type == XIT_FORM)
+        return(xi_search_itf(itf, XI_SEARCH_FOR_FIELD, 0));
+      obj = focus_obj;
+      break;
+    case XI_NEXT_ITF_TAB:
+      obj = focus_obj->parent;
+      if (obj->type == XIT_ITF)   /* No container, ignore it */
+        return NULL;
+      break;
+    }
+    while (TRUE)
+    {
+      switch (obj->type)
+      {
+      case XIT_FIELD:
+        tab_cid = obj->v.field->tab_cid;
+        break;
+      case XIT_BTN:
+        tab_cid = obj->v.btn->tab_cid;
+        break;
+      case XIT_FORM:
+        tab_cid = obj->v.form->tab_cid;
+        break;
+      case XIT_LIST:
+        tab_cid = obj->v.list->tab_cid;
+        break;
+      case XIT_CONTAINER:
+        tab_cid = obj->v.container->tab_cid;
+        break;
+      default:
+      xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4,"20003",
+        20003, "Internal error");   
+        break;
+      }
+      obj = xi_get_obj(itf, tab_cid);
+      if (obj == NULL || obj == focus_obj)
+        break;
+#if XIWS == MACWS
+      if (obj->type == XIT_BTN || obj->type == XIT_CONTAINER)
+        continue;
+#endif
+      if (
+          (xi_get_attrib(obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) !=
+          (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+        continue;
+      if (obj->type == XIT_LIST)
+      {
+        int i, nbr_members;
+        XI_OBJ * *members;
+        BOOLEAN have_column;
+
+        members = xi_get_member_list(obj, &nbr_members);
+        have_column = FALSE;
+        for (i = 0; i < nbr_members; ++i)
+        {
+          unsigned long attrib;
+
+          attrib = xi_get_attrib(members[i]);
+          if ((attrib & XI_ATR_ENABLED) &&
+              ! (attrib & XI_ATR_SELECTABLE))
+          {
+            have_column = TRUE;
+            break;
+          }
+        }
+        if (! have_column)
+          continue;
+      }
+
+      /*
+        If the tab key was pressed, and the focus is not on the first
+        enabled and visible radio button in the group, then skip to
+        a control that is not in the group.
+        */
+      {
+        XI_OBJ * *rb_obj, *parent;
+        int i;
+
+        if (c != K_DOWN &&
+            obj->type == XIT_BTN &&
+            obj->v.btn->type == XIBT_RADIOBTN &&
+            obj->parent->type == XIT_CONTAINER)
+        {
+          parent = obj->parent;
+          for (i = 0, rb_obj = parent->children; i < parent->nbr_children; ++i,
+              ++rb_obj)
+            if ((xi_get_attrib(*rb_obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+            == (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+              break;
+          if (*rb_obj != obj)
+            continue;
+        }
+      }
+
+      /*
+        If a meta-tab key was pressed, and the obj->type == XIT_FORM
+        then move the focus to the first field in the form
+        */
+      if (obj->type == XIT_FORM)
+      {
+        XI_OBJ * *field_obj;
+        int i;
+
+        for (i = 0, field_obj = obj->children; i < obj->nbr_children; ++i, ++field_obj)
+          if ((xi_get_attrib(*field_obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+            == (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+            break;
+        if (i == obj->nbr_children)
+          continue;
+        obj = *field_obj;
+      }
+
+      break;
+    }
+    return(obj);
+  case XI_NEXT_FORM_BACKTAB:
+  case XI_NEXT_ITF_BACKTAB:
+    switch (tab_type)
+    {
+    case XI_NEXT_FORM_BACKTAB:
+      if (type == XIT_FORM)
+        return(xi_search_itf(itf, XI_SEARCH_FOR_FIELD, 0));
+      obj = focus_obj;
+      break;
+    case XI_NEXT_ITF_BACKTAB:
+      obj = focus_obj->parent;
+      if (obj->type == XIT_ITF)   /* No container, ignore it */
+        return NULL;
+      break;
+    }
+    while (TRUE)
+    {
+      /*
+        xi_search_itf, searching for TAB CID finds the tab control id
+        just previous in the tabbing sequence, hence the break at the bottom of the loop.
+        */
+      obj = xi_search_itf(itf, XI_SEARCH_FOR_TAB_CID, obj->cid);
+      if (obj == NULL || obj == focus_obj)
+        break;
+#if XIWS == MACWS
+      if (obj->type == XIT_BTN || obj->type == XIT_CONTAINER)
+        continue;
+#endif
+      if (
+          (xi_get_attrib(obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) !=
+          (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+        continue;
+
+      if (obj->type == XIT_LIST)
+      {
+        int i, nbr_members;
+        XI_OBJ * *members;
+        BOOLEAN have_column;
+
+        members = xi_get_member_list(obj, &nbr_members);
+        have_column = FALSE;
+        for (i = 0; i < nbr_members; ++i)
+        {
+          unsigned long attrib;
+
+          attrib = xi_get_attrib(members[i]);
+          if ((attrib & XI_ATR_ENABLED) &&
+              ! (attrib & XI_ATR_SELECTABLE))
+          {
+            have_column = TRUE;
+            break;
+          }
+        }
+        if (! have_column)
+          continue;
+      }
+
+      /*
+        If a meta-tab key was pressed, and the obj->type == XIT_FORM
+        then move the focus to the first field in the form
+        */
+      if (obj->type == XIT_FORM)
+      {
+        XI_OBJ * *field_obj;
+        int i;
+
+        for (i = 0, field_obj = obj->children; i < obj->nbr_children; ++i, ++field_obj)
+          if ((xi_get_attrib(*field_obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+            == (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+            break;
+        if (i == obj->nbr_children)
+          continue;
+        obj = *field_obj;
+      }
+      break;
+    }
+    if (obj && c != K_UP &&
+        obj->type == XIT_BTN &&
+        obj->v.btn->type == XIBT_RADIOBTN &&
+        obj->parent->type == XIT_CONTAINER &&
+        obj->parent->children[0] != obj)
+    {
+      obj = obj->parent->children[0];
+      while (TRUE)
+      {
+        if ((xi_get_attrib(obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED
+            | XI_ATR_VISIBLE))
+          break;
+        obj = xi_search_itf(itf, XI_SEARCH_FOR_TAB_CID, obj->cid);
+      }
+    }
+    return(obj);
+  }
+  return NULL;
+}
+
+/*
+  xi_lowlevel_focus: inform a control that it is gaining or losing the focus.
+  A control may reset some internal state when this happens.
+  This is not refusable.
+*/
+static void near
+xi_lowlevel_focus(XI_OBJ *xi_obj, BOOLEAN set)
+{
+  XI_OBJ *itf;
+  WINDOW win;
+  BOOLEAN native_controls = (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS);
+
+  itf = xi_obj->itf;
+  win = itf->v.itf->xvt_win;
+  if (native_controls)
+  {
+    if (set && xi_obj->type != XIT_BTN)    /* should be set, not ! set */
+    if (xvt_scr_get_focus_vobj() == win)   /* should be ==, not != */
+      xvt_scr_set_focus_vobj(win);
+      xvt_vobj_raise(win);          
+  }
+  switch(xi_obj->type)
+  {
+  case XIT_CELL:
+    lm_focus_cb( xi_obj->parent->v.list->lm, xi_obj->v.cell.row,
+                xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled, set );
+    return;
+  case XIT_FIELD:
+    stx_focus_cb(xi_obj->v.field->stx, set);
+    break;
+  case XIT_BTN:
+    {
+      XI_BTN_DATA *bd;
+
+      bd = xi_obj->v.btn;
+      if (!native_controls)
+      {
+        BOOLEAN enabled, visible, focus;
+        unsigned long attrib;
+
+        if (itf->v.itf->back_color && ! bd->drawable)
+        {
+          attrib = xi_get_attrib(xi_obj);
+          enabled = ((attrib & XI_ATR_ENABLED) != 0);
+          visible = ((attrib & XI_ATR_VISIBLE) != 0);
+          focus = (xi_get_focus(xi_obj->itf) == xi_obj);
+          xi_draw_button(xi_obj, &bd->rct, bd->text, bd->down_icon_rid,
+              bd->up_icon_rid, bd->disabled_icon_rid, enabled,
+              visible, focus, bd->down, bd->dflt, bd->checked, FALSE);
+        }
+        else
+          xi_invalidate_rect(win, &bd->rct);
+      }
+      else
+      {
+        if (set)
+      xvt_scr_set_focus_vobj(bd->btnctl);
+    }
+      break;
+    }
+  default:
+    /* ignore */
+    break;
+  }
+}
+
+/*
+  is_group_member: given an object, determine if it is in a group.
+*/
+static BOOLEAN near
+is_group_member(XI_OBJ *obj, XI_OBJ *group)
+{
+  int *cidlist;
+  int i;
+
+  cidlist = group->v.group->cidlist;
+  for (i = group->v.group->nbr_cids; i > 0; i--, cidlist++)
+  {
+    if (*cidlist == obj->cid)
+      return(TRUE);
+  }
+  return(FALSE);
+}
+
+
+BOOLEAN
+xi_is_focus_moving(XI_OBJ *xi_obj)
+{
+  XI_OBJ *itf = xi_obj->itf;
+
+  return itf->v.itf->moving_focus;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* lm_list_is_about_to_lose_focus                                          */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN
+lm_list_is_about_to_lose_focus(LM_DATA *lmp)
+{
+  if (lm_list_has_focus(lmp) && lmp->txt_is_invisible &&
+      lmp->focus_rec)
+  {
+    int idx, focus_row, focus_column;
+    BOOLEAN v_scrolled;
+
+    for (idx = 0; idx < lmp->nbr_realized_rows; ++idx)
+      if (lmp->focus_rec == lmp->recs[idx])
+        return FALSE;
+    lm_allocate_rec_info(lmp, lmp->realized_rows_array_len + 1);
+    ++lmp->nbr_realized_rows;
+    idx = lmp->nbr_realized_rows - 1;
+    lmp->recs[idx] = lmp->focus_rec;
+    lmp->saved_focus_rec = lmp->focus_rec;
+    lmp->focus_rec = 0L;
+    lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+    focus_row = idx;
+    lm_set_focus_cell(lmp, focus_row, focus_column, TRUE );
+    lm_invalidate_rows_internal((LM)lmp, focus_row, focus_row, FALSE,
+                                focus_column, TRUE );
+    calculate_pix_offsets(lmp, FALSE );
+    calculate_visibles(lmp);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* lm_list_did_lose_focus                                                  */
+/* ----------------------------------------------------------------------- */
+static void
+lm_list_did_lose_focus(LM_DATA *lmp)
+{
+  LM_CB_DATA lm_cb_data;
+
+  lm_cb_data.lm = (LM)lmp;
+  lm_cb_data.cb_type = LM_CB_REC_FREE;
+  lm_cb_data.cid = lmp->cid;
+  lm_cb_data.win = lmp->win;
+  lm_cb_data.v.rec_free.record = lmp->saved_focus_rec;
+  (*lmp->lm_cb)(&lm_cb_data);
+  lm_allocate_rec_info(lmp, lmp->nbr_realized_rows - 1);
+  --lmp->nbr_realized_rows;
+  lmp->focus_rec = 0L;
+  lmp->txt_is_invisible = FALSE;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* lm_list_did_not_lose_focus                                              */
+/* ----------------------------------------------------------------------- */
+static void
+lm_list_did_not_lose_focus(LM_DATA *lmp)
+{
+  lm_allocate_rec_info(lmp, lmp->realized_rows_array_len - 1);
+  --lmp->nbr_realized_rows;
+  lmp->focus_rec = lmp->saved_focus_rec;
+}
+
+/* ----------------------------------------------------------------------- */
+/* send focus event                                                        */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN send_object_event( XI_OBJ* object, int event_type )
+{
+  XI_EVENT xiev;
+
+  MEMCLEAR(xiev);
+  xiev.type = event_type;
+  xiev.v.xi_obj = object;
+  call_cb(object->itf, &xiev);
+  return !xiev.refused;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* move_focus_off_groups                                                   */
+/* ----------------------------------------------------------------------- */
+
+static BOOLEAN move_group_focus( XI_OBJ* primary_obj, XI_OBJ* secondary_obj,
+                                int event_type )
+{
+  XI_OBJ** objp;
+  int      i;
+  BOOLEAN  moving_between_rows = FALSE;
+
+  if ( primary_obj == NULL )
+    return TRUE;
+  if (secondary_obj != NULL && secondary_obj->type == XIT_CELL)
+  {
+    if (primary_obj->type == XIT_CELL)
+      moving_between_rows = ( primary_obj->v.cell.row
+                              != secondary_obj->v.cell.row );
+    secondary_obj = secondary_obj->parent->children[
+                                  secondary_obj->v.cell.column ];
+  }
+  if (primary_obj->type == XIT_CELL)
+    primary_obj = primary_obj->parent->children[primary_obj->v.cell.column];
+  objp = primary_obj->itf->children;
+  for (i = primary_obj->itf->nbr_children; i > 0; i--, objp++)
+  {
+    XI_OBJ* obj;
+
+    obj = *objp;
+    if (obj->type == XIT_GROUP && is_group_member(primary_obj, obj) &&
+        ( secondary_obj == NULL || !is_group_member(secondary_obj, obj) ||
+          moving_between_rows ))
+      if (!send_object_event( obj, event_type ))
+        return FALSE;
+  }
+  return TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* move_off_column                                                         */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN move_off_column( XI_OBJ* old_focus, XI_OBJ* new_focus )
+{
+  if ( new_focus != NULL && new_focus->type == XIT_CELL
+      && old_focus->v.cell.column == new_focus->v.cell.column )
+    return TRUE;
+  old_focus = old_focus->parent->children[old_focus->v.cell.column];
+  return send_object_event( old_focus, XIE_OFF_COLUMN );
+}
+
+/* ----------------------------------------------------------------------- */
+/* move_off_row                                                            */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN move_row_focus( XI_OBJ* primary_obj, XI_OBJ* secondary_obj,
+                              int event_type )
+{
+  XI_OBJ row_obj;
+
+  /* move off of row */
+  if ( secondary_obj != NULL && secondary_obj->type == XIT_CELL
+      && primary_obj->v.cell.row == secondary_obj->v.cell.row
+      && primary_obj->parent == secondary_obj->parent )
+    return TRUE;
+  XI_MAKE_ROW(&row_obj, primary_obj->parent, primary_obj->v.cell.row);
+  row_obj.v.row_data.is_vert_scrolled = primary_obj->v.cell.is_vert_scrolled;
+  if (!send_object_event( &row_obj, event_type ))
+    return FALSE;
+  return TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* move_on_column                                                          */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN move_on_column( XI_OBJ* old_focus, XI_OBJ* new_focus )
+{
+  if ( old_focus != NULL && old_focus->type == XIT_CELL
+      && old_focus->parent == new_focus->parent
+      && old_focus->v.cell.column == new_focus->v.cell.column)
+    return TRUE;
+  new_focus = new_focus->parent->children[new_focus->v.cell.column];
+  return send_object_event( new_focus, XIE_ON_COLUMN );
+}
+
+/* ----------------------------------------------------------------------- */
+/* same_parents                                                            */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN same_parents( XI_OBJ* one, XI_OBJ* two )
+{
+  if (one != NULL && one->type != XIT_LIST && one->type != XIT_FORM)
+    one = one->parent;
+  if (two != NULL && two->type != XIT_LIST && two->type != XIT_FORM)
+    two = two->parent;
+  return one == two;
+}
+
+/* ----------------------------------------------------------------------- */
+/* remove_focus                                                            */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN remove_focus( XI_OBJ* old_focus, XI_OBJ* new_focus )
+{
+  /* move off old 1st-level object */
+  if (old_focus == NULL)
+    return TRUE;
+  switch (old_focus->type)
+  {
+    case XIT_CELL:
+      if ( !send_object_event( old_focus, XIE_OFF_CELL )
+          || !move_off_column( old_focus, new_focus )
+          || !move_group_focus( old_focus, new_focus, XIE_OFF_GROUP )
+          || !move_row_focus( old_focus, new_focus, XIE_OFF_ROW ) )
+        return FALSE;
+      if ( !same_parents( old_focus, new_focus ) )
+        return send_object_event( old_focus->parent, XIE_OFF_LIST );
+      break;
+    case XIT_LIST:
+      return ( move_group_focus( old_focus, new_focus, XIE_OFF_GROUP )
+              && (same_parents(old_focus, new_focus)
+                  || send_object_event( old_focus, XIE_OFF_LIST )) );
+    case XIT_FIELD:
+      if ( !send_object_event( old_focus, XIE_OFF_FIELD )
+          || !move_group_focus( old_focus, new_focus, XIE_OFF_GROUP ) )
+        return FALSE;
+      if ( old_focus->parent != new_focus->parent)
+        return send_object_event( old_focus->parent, XIE_OFF_FORM );
+      break;
+    default:
+      return move_group_focus( old_focus, new_focus, XIE_OFF_GROUP );
+  }
+  return TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* place_focus                                                             */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN place_focus (XI_OBJ* old_focus, XI_OBJ* new_focus)
+{
+  if (new_focus == NULL)
+    return TRUE;
+  switch (new_focus->type)
+  {
+    case XIT_CELL:
+      if ( !same_parents( old_focus, new_focus )
+          && !send_object_event( new_focus->parent, XIE_ON_LIST ))
+        return FALSE;
+      return ( move_row_focus( new_focus, old_focus, XIE_ON_ROW )
+              && move_group_focus( new_focus, old_focus, XIE_ON_GROUP )
+              && move_on_column( old_focus, new_focus )
+              && send_object_event( new_focus, XIE_ON_CELL ));
+    case XIT_LIST:
+      return (( same_parents(old_focus, new_focus)
+                || send_object_event( new_focus, XIE_ON_LIST ))
+              && move_group_focus( new_focus, old_focus, XIE_ON_GROUP )); 
+    case XIT_FIELD:
+      if ( (old_focus == NULL || new_focus->parent != old_focus->parent )
+          && !send_object_event( new_focus->parent, XIE_ON_FORM ))
+        return FALSE;
+      return ( move_group_focus( new_focus, old_focus, XIE_ON_GROUP )
+              && send_object_event( new_focus, XIE_ON_FIELD ));
+  }
+  return move_group_focus( new_focus, old_focus, XIE_ON_GROUP );
+}
+
+/* ----------------------------------------------------------------------- */
+/* find_cell_obj                                                           */
+/* ----------------------------------------------------------------------- */
+static XI_OBJ* find_cell_obj( XI_OBJ* new_focus )
+{
+  LM_DATA*      lmp;
+  XI_OBJ        tmp_obj;
+  XI_LIST_DATA* list_data;
+
+  list_data = new_focus->parent->v.list;
+  lmp = (LM_DATA *)list_data->lm;
+
+  tmp_obj = *new_focus;
+
+  new_focus = get_non_focus_cell_obj(tmp_obj.parent->v.list);
+  new_focus->v.cell.row = tmp_obj.v.cell.row;
+  new_focus->v.cell.column = tmp_obj.v.cell.column;
+  if (new_focus->v.cell.row >= (unsigned char)lmp->nbr_realized_rows)
+    return new_focus->itf;
+  return new_focus;
+}
+
+/* ----------------------------------------------------------------------- */
+/* move_focus_to_list                                                      */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN move_focus_to_list( XI_OBJ** focus_result )
+{
+  LM_DATA*      lmp;
+  int           col;
+  XI_OBJ*       new_focus;
+  XI_LIST_DATA* list_data;
+
+  new_focus = *focus_result;
+  list_data = new_focus->v.list;
+  lmp = (LM_DATA *)list_data->lm;
+  if (new_focus->nbr_children <= 0)
+    return FALSE;
+  if (lmp->sizing_row)
+    return FALSE;
+  if ( lmp->nbr_realized_rows == 0)
+  {
+    *focus_result = new_focus->itf;
+    return TRUE;
+  }
+  if ( lmp->single_select ) /* attempt to select row */
+    return TRUE;
+  new_focus = list_data->focus_cell;
+  /* if cell is selectable, disabled, etc, then find another cell */
+  col = new_focus->v.cell.column;
+  while (TRUE)
+  {
+    long attrib;
+
+    attrib = lmp->lm_column_data[col]->attrib;
+    if ((attrib & XI_ATR_ENABLED) && !(attrib & XI_ATR_SELECTABLE))
+    {
+      new_focus->v.cell.column = (unsigned char)col;
+      break;
+    }
+    col++;
+    if (col == lmp->nbr_columns)
+      col = 0;
+    if ((unsigned char)col == new_focus->v.cell.column)
+    {
+      *focus_result = new_focus->itf;
+      return TRUE;
+    }
+  }
+  if (new_focus->v.cell.row >= (unsigned char)lmp->nbr_realized_rows)
+  {
+    if (new_focus->type == XIT_CELL)
+    {
+      /* Last row had focus, but has been deleted.  Set focus to new
+        last row, if there is one */
+      if (lmp->nbr_realized_rows >= 1)
+        new_focus->v.cell.row = lmp->nbr_realized_rows - 1;
+      else
+        new_focus = xi_find_next_obj( new_focus->parent, XI_NEXT_FORM_TAB,
+                        XI_PREF_FORM_TAB_CHAR );
+    }
+    else
+      new_focus = new_focus->itf;
+  }
+  *focus_result = new_focus;
+  return TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* determine_focus_button                                                 */
+/* ----------------------------------------------------------------------- */
+static XI_OBJ* determine_focus_button( XI_OBJ* new_focus )
+{
+  int     i;
+  unsigned long attr = 0L;
+
+  xvt_errmsg_sig_if(!(new_focus->nbr_children), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20005",
+    20005, "Internal error");   
+  for (i = 0; i < new_focus->nbr_children; i++)
+  {
+    attr = xi_get_attrib(new_focus->children[i]);
+    if ((attr & XI_ATR_ENABLED) && (attr & XI_ATR_VISIBLE))
+      return new_focus->children[i];
+  }
+  return xi_find_next_obj(new_focus, XI_NEXT_FORM_TAB, XI_PREF_FORM_TAB_CHAR);
+}
+
+/* ----------------------------------------------------------------------- */
+/* determine_new_focus                                                     */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN determine_new_focus( XI_OBJ** new_focus )
+{
+  if (*new_focus == NULL)
+    return TRUE;
+  do {
+    switch ((*new_focus)->type)
+    {
+      case XIT_CELL:
+        *new_focus = find_cell_obj( *new_focus );
+        break;
+      case XIT_LIST:
+        return move_focus_to_list( new_focus );
+      case XIT_FORM:
+      {
+        XI_OBJ* focus_field = (*new_focus)->v.form->focus_field;
+        if (focus_field)
+          *new_focus = focus_field;
+        break;
+      }
+      case XIT_CONTAINER:
+        *new_focus = determine_focus_button( *new_focus );
+        break;
+    }
+  } while (*new_focus != NULL &&
+          ((*new_focus)->type == XIT_CONTAINER ||
+          (*new_focus)->type == XIT_FORM ||
+          (*new_focus)->type == XIT_LIST ));
+  if (*new_focus == NULL)
+    return FALSE;
+  return TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* move_focus_internal                                                     */
+/* ----------------------------------------------------------------------- */
+static void check_new_focus_enabled( XI_OBJ* xi_obj )
+{
+  if (xi_obj == NULL)
+    return;
+  switch (xi_obj->type)
+  {
+    case XIT_CELL:
+    {
+      BOOLEAN xi_obj_enabled;
+
+      xi_obj_enabled = ((xi_get_attrib(xi_obj->parent) & (XI_ATR_ENABLED |
+          XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE));
+    xvt_errmsg_sig_if(!(xi_obj_enabled), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20006", 20006,
+      "Attempting to move to disabled or invisible object");   
+      break;
+    }
+    case XIT_BTN:
+    case XIT_FIELD:
+    case XIT_LIST:
+    {
+      BOOLEAN xi_obj_enabled;
+
+      xi_obj_enabled = ((xi_get_attrib(xi_obj) & (XI_ATR_ENABLED |
+          XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE));
+    xvt_errmsg_sig_if(!(xi_obj_enabled), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20007", 20007,
+      "Attempting to move to disabled or invisible object");   
+      break;
+    }
+  }
+}
+
+/* ----------------------------------------------------------------------- */
+/* move_focus_internal                                                     */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN determine_alternate_focus( XI_OBJ* old_focus, XI_OBJ** new_focus,
+                                          BOOLEAN next_if_disabled,
+                                          int check_for_reenabled )
+{
+  XI_OBJ* xi_obj;
+
+  xi_obj = *new_focus;
+  /* if field for new focus has been disabled, proceed with next field */
+  if (xi_obj->type != XIT_CELL && xi_obj->type != XIT_ITF)
+  {
+    unsigned long attrib;
+
+    attrib = xi_get_attrib(xi_obj);
+    if (! (attrib & XI_ATR_ENABLED))
+    {
+      if (next_if_disabled)
+        xi_obj = xi_find_next_obj(xi_obj, XI_NEXT_FORM_TAB,
+                                  XI_PREF_FORM_TAB_CHAR);
+      else
+        return FALSE;
+    }
+  }
+
+  /* if next field used to be disabled, and is not enabled, move to it */
+  if (check_for_reenabled)
+  {
+    if (xi_obj->type == XIT_FIELD)
+    {
+      XI_OBJ *tmp_obj;
+
+      tmp_obj = xi_find_next_obj( old_focus,
+          check_for_reenabled == 1 ? XI_NEXT_FORM_TAB : XI_NEXT_FORM_BACKTAB,
+          check_for_reenabled == 1 ? xi_get_pref(XI_PREF_FORM_TAB_CHAR) :
+          xi_get_pref(XI_PREF_FORM_BACKTAB_CHAR));
+      if (tmp_obj)
+        xi_obj = tmp_obj;
+    }
+  }
+  *new_focus = xi_obj;
+  return TRUE;
+}
+/* ----------------------------------------------------------------------- */
+/* perform_move_focus                                                      */
+/* ----------------------------------------------------------------------- */
+static BOOLEAN perform_move_focus( XI_OBJ* old_focus, XI_OBJ* new_focus,
+                                  BOOLEAN make_callbacks,
+                                  BOOLEAN next_if_disabled,
+                                  int check_for_reenabled )
+{
+  BOOLEAN row_changed;
+
+  if (!determine_new_focus( &new_focus ))
+    return FALSE;
+  check_new_focus_enabled( new_focus );
+  /* remove focus */
+  if (make_callbacks && !remove_focus( old_focus, new_focus ))
+    return FALSE;
+  if (!determine_alternate_focus( old_focus, &new_focus, next_if_disabled,
+                                  check_for_reenabled ) )
+    return FALSE;
+  if (make_callbacks && !place_focus( old_focus, new_focus ))
+    return FALSE;
+    /* if list has focus, it's a single-select list */
+  if ( new_focus != NULL && new_focus->type == XIT_LIST )
+  {
+    unsigned long attrib;
+    XI_OBJ        row_obj;
+    XI_LIST_DATA* list_data = new_focus->v.list;
+    LM_DATA*      lmp = (LM_DATA*)list_data->lm;
+    int           row = list_data->focus_cell->v.cell.row;
+
+    /* See if the focus row is selected. */
+    if (row >= lmp->nbr_realized_rows)
+      row = lmp->nbr_realized_rows - 1;
+    XI_MAKE_ROW( &row_obj, new_focus, row );
+    attrib = xi_get_attrib(&row_obj);
+    /* If it isn't, see if any row is selected. */
+    if ((attrib & XI_ATR_SELECTED) == 0)
+    {
+      for (row = 0; row < lmp->nbr_realized_rows; row++)
+      {
+        XI_MAKE_ROW( &row_obj, new_focus, row );
+        attrib = xi_get_attrib(&row_obj);
+        if (attrib & XI_ATR_SELECTED)
+          break;
+      }
+    }
+    if (row < lmp->nbr_realized_rows)
+      /* Move the focus to the selected row. */
+      list_data->focus_cell->v.cell.row = row;
+    else
+    {
+      /* Select the first row in the list and make it the focus row. */
+      list_data->focus_cell->v.cell.row = 0;
+      XI_MAKE_ROW( &row_obj, new_focus, 0 );
+      if (make_callbacks)
+      {
+        XI_EVENT event;
+
+        MEMCLEAR(event);
+        event.type = XIE_SELECT;
+        event.v.select.xi_obj = &row_obj;
+        event.v.select.selected = TRUE;
+        event.v.select.dbl_click = FALSE;
+      event.v.select.records = &lmp->recs[0];
+      call_cb(new_focus->itf, &event);
+      if (event.refused)
+      return FALSE;
+    }
+/*
+    xi_set_attrib(&row_obj, attrib | XI_ATR_SELECTED );
+*/
+    }
+  }
+
+  /* if we get to here then it has happened */
+  {
+    XI_ITF_DATA* itf_data;
+
+    itf_data = new_focus->itf->v.itf;
+    itf_data->chg_flag = FALSE;
+    itf_data->focus_obj = new_focus;
+    if (itf_data->virtual_itf)
+      xi_make_obj_visible(new_focus);
+  }
+  if (new_focus->type == XIT_CELL)
+    new_focus->parent->v.list->focus_cell = new_focus;
+  if (new_focus->type == XIT_FIELD)
+    new_focus->parent->v.form->focus_field = new_focus;
+  if (old_focus != NULL)
+    xi_lowlevel_focus(old_focus, FALSE);
+  if (new_focus != NULL)
+    xi_lowlevel_focus(new_focus, TRUE);
+  row_changed = TRUE;
+  if (old_focus && new_focus &&
+    old_focus->type == XIT_CELL && new_focus->type == XIT_CELL &&
+    old_focus->parent == new_focus->parent &&
+    old_focus->v.cell.row == new_focus->v.cell.row)
+    row_changed = FALSE;
+  if (old_focus != NULL)
+  {
+    if ((old_focus->type == XIT_CELL) && row_changed && (old_focus->v.cell.is_vert_scrolled != TRUE))
+    {
+      LM lm;
+
+      lm = old_focus->parent->v.list->lm;
+      lm_redraw_row((LM_DATA *)lm, old_focus->v.cell.row, FALSE);
+    }
+  }
+  if (new_focus != NULL)
+  {
+    if ((new_focus->type == XIT_CELL) && row_changed)
+    {
+      LM lm;
+
+      lm = new_focus->parent->v.list->lm;
+      lm_redraw_row((LM_DATA *)lm, new_focus->v.cell.row, FALSE);
+      if ( ((LM_DATA *)lm)->txt != NULL )
+        txt_redraw(((LM_DATA *)lm)->txt, FALSE);
+    }
+  }
+  return TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* move_focus_internal                                                     */
+/* ----------------------------------------------------------------------- */
+/*
+  This function attempts to move the focus to the object indicated,
+  returning TRUE if successful, FALSE if refused.  This function will
+  set or remove the focus from any low-level editing modules as necessary.
+
+  If make_callbacks is TRUE, then XI callbacks will be issued to
+  determine whether the focus change should be allowed before proceeding.
+*/
+BOOLEAN
+xi_move_focus_internal(XI_OBJ *xi_obj, BOOLEAN make_callbacks,
+                BOOLEAN next_if_disabled, int check_for_reenabled)
+{
+  XI_OBJ*      focus_obj;
+  XI_ITF_DATA* itf_data;
+  LM_DATA*     lmp = NULL;
+  BOOLEAN      focus_was_on_invisible = FALSE;
+
+  itf_data = xi_obj->itf->v.itf;
+  focus_obj = itf_data->focus_obj;
+
+  if (xi_compare_objs( focus_obj, xi_obj ))
+    return(TRUE);
+  itf_data->moving_focus = TRUE;
+  if (focus_obj && focus_obj->type == XIT_CELL)
+  {
+    XI_OBJ *list_obj;
+
+    list_obj = focus_obj->parent;
+    lmp = (LM_DATA *)(list_obj->v.list->lm);
+    focus_was_on_invisible = lm_list_is_about_to_lose_focus(lmp);
+  }
+  if (!perform_move_focus( focus_obj, xi_obj, make_callbacks, next_if_disabled,
+                          check_for_reenabled ))
+  {
+    itf_data->moving_focus = FALSE;
+    if (focus_was_on_invisible)
+      lm_list_did_not_lose_focus(lmp);
+    return FALSE;
+  }
+  if (focus_was_on_invisible)
+    lm_list_did_lose_focus(lmp);
+  if (make_callbacks)
+  {
+    XI_EVENT event;
+
+    MEMCLEAR(event);
+    event.type = XIE_POST_NAVIGATION;
+    call_cb(xi_obj->itf, &event);
+  }
+  itf_data->moving_focus = FALSE;
+  return(TRUE);
+}
+
+static void near
+xi_set_interface_window(XI_OBJ *xi_obj)
+{
+  WINDOW win;
+#if XIWS != PMWS
+  WINDOW itf_win;
+  itf_win = xi_obj->itf->v.itf->xvt_win;
+#endif
+
+  win = xvt_scr_get_focus_vobj();
+  while (win != xi_obj->itf->v.itf->xvt_win)
+  {
+    if (win == NULL_WIN)
+      return;
+    win = xvt_vobj_get_parent(win);
+  }
+  /* TODO we have a problem here.  If we call xvt_R3_set_front_window here, then OS/2
+  quits generating E_CONTROL events.  If we don't call xvt_R3_set_front_window here,
+  then the vertical scroll bar retains the keyboard focus after scrolling.
+  */
+#if XIWS != PMWS
+  xvt_scr_set_focus_vobj(itf_win);
+  xvt_vobj_raise(itf_win);
+#endif
+}
+
+BOOLEAN
+xi_move_focus(XI_OBJ *xi_obj)
+{
+  XI_OBJ *list_obj;
+  LM_DATA* lmp = NULL;
+
+  if ( xi_obj->type == XIT_ITF || xi_obj->type == XIT_CELL
+      || (xi_get_attrib(xi_obj) & XI_ATR_VISIBLE))
+  {
+  if (xi_obj->type == XIT_CELL)
+  {
+    list_obj = xi_obj->parent;
+    lmp = (LM_DATA *)(list_obj->v.list->lm);
+    if (CELL_IS_SELECTABLE((LM)lmp, xi_obj->v.cell.row, xi_obj->v.cell.column))
+      return FALSE;
+    }
+    xi_set_interface_window(xi_obj);
+    return xi_move_focus_internal(xi_obj, TRUE, FALSE, 0);
+  }
+  return FALSE;
+}
+
+void
+xi_set_focus(XI_OBJ *xi_obj)
+{
+  XI_OBJ *list_obj;
+  LM_DATA* lmp = NULL;
+
+  if ( xi_obj->type == XIT_ITF || xi_obj->type == XIT_CELL
+      || (xi_get_attrib(xi_obj) & XI_ATR_VISIBLE))
+  {
+  if (xi_obj->type == XIT_CELL)
+  {
+    list_obj = xi_obj->parent;
+    lmp = (LM_DATA *)(list_obj->v.list->lm);
+    if (CELL_IS_SELECTABLE((LM)lmp, xi_obj->v.cell.row, xi_obj->v.cell.column))
+      return;
+    }
+    xi_set_interface_window(xi_obj);
+    xi_move_focus_internal(xi_obj, FALSE, FALSE, 0);
+  }
+}
+
+static void near
+xi_add_to_parent_list(XI_OBJ *obj, int position)
+{
+  XI_OBJ *parent;
+
+  if ((parent = obj->parent) == NULL)
+    return;
+  realloc_ptrs((void * * *)&parent->children,
+      parent->nbr_children, parent);
+  if (position == -1)
+    parent->children[parent->nbr_children] = obj;
+  else
+  {
+  int i;
+
+    for (i = parent->nbr_children; i > position; --i)
+      parent->children[i] = parent->children[i - 1];
+    parent->children[position] = obj;
+  }
+  parent->nbr_children++;
+}
+
+static void
+xi_stx_cb(STX_CB_DATA *stx_cb_data)
+{
+  XI_EVENT xiev;
+  BOOLEAN send_cb;
+  XI_OBJ *xi_obj;
+
+  xi_obj = xiev.v.xi_obj = (XI_OBJ *)stx_get_app_data(stx_cb_data->stx);
+  xiev.refused = FALSE;
+  switch(stx_cb_data->cb_type)
+  {
+  case STX_CB_CHAR:
+    /* generate an XIE_CHAR_FIELD */
+    xiev.type = XIE_CHAR_FIELD;
+    xiev.v.chr.xi_obj = xi_obj;
+  xiev.v.chr.ch = stx_cb_data->v.chr.ch;
+    xiev.v.chr.shift = stx_cb_data->v.chr.shift;
+    xiev.v.chr.control = stx_cb_data->v.chr.control;
+    xiev.v.chr.is_paste = stx_cb_data->v.chr.is_paste;
+    send_cb = TRUE;
+    break;
+  case STX_CB_CHANGE:
+    /* generate an XIE_CHG_FIELD */
+    xiev.type = XIE_CHG_FIELD;
+    send_cb = TRUE;
+    break;
+  case STX_CB_FOCUS:
+  stx_cb_data->v.refused = !xi_move_focus_internal(xi_obj, TRUE,
+        TRUE, 0);
+    send_cb = FALSE;
+    break;
+  case STX_CB_DBL:
+    xiev.type = XIE_DBL_FIELD;
+    send_cb = TRUE;
+    break;
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20008",
+    20008, "XI: unknown STX callback");   
+  }
+  if (send_cb)
+  call_cb(xi_obj->itf, &xiev);
+  if (stx_cb_data->cb_type == STX_CB_CHAR)
+  {
+    stx_cb_data->v.chr.ch = xiev.v.chr.ch;
+    stx_cb_data->v.chr.refused = xiev.refused;
+  }
+}
+
+static void
+xi_lm_cb(LM_CB_DATA *lm_cb_data)
+{
+  XI_EVENT xiev;
+  BOOLEAN send_cb = FALSE;
+  XI_OBJ *lm_obj;
+  XI_OBJ *next_obj;
+  XI_LIST_DATA *ldata;
+  LM_DATA *lmp;
+
+  MEMCLEAR(xiev);
+  lm_obj = (XI_OBJ *)lm_get_list_obj(lm_cb_data->lm);
+  lmp = (LM_DATA *)lm_obj->v.list->lm;
+  ldata = lm_obj->v.list;
+  xiev.v.xi_obj = ldata->focus_cell;
+
+  next_obj = get_non_focus_cell_obj(ldata);
+  switch(lm_cb_data->cb_type)
+  {
+  case LM_CB_CHAR:
+  /* generate an XIE_CHAR_CELL */
+  xiev.type = XIE_CHAR_CELL;
+  xiev.v.chr.xi_obj = ldata->focus_cell;
+  xiev.v.chr.ch = lm_cb_data->v.chr.ch;
+    xiev.v.chr.shift = lm_cb_data->v.chr.shift;
+    xiev.v.chr.control = lm_cb_data->v.chr.control;
+  xiev.v.chr.is_paste = lm_cb_data->v.chr.is_paste;
+    send_cb = TRUE;
+    break;
+  case LM_CB_CHANGE:
+  xiev.type = XIE_CHG_CELL;
+    send_cb = TRUE;
+    break;
+  case LM_CB_FOCUS:
+  case LM_CB_CELL_BTN:
+    {
+      BOOLEAN ref;
+      XI_OBJ *focus_obj;
+
+      focus_obj = xi_get_focus(lm_obj->itf);
+      next_obj->v.cell.row = (unsigned char)lm_cb_data->row;
+      next_obj->v.cell.column = (unsigned char)lm_cb_data->column;
+    next_obj->v.cell.is_vert_scrolled = FALSE;
+      ref = FALSE;
+
+      if (focus_obj && focus_obj->type == XIT_CELL && next_obj->type == XIT_CELL)
+      {
+        if (focus_obj->parent != next_obj->parent ||
+            focus_obj->v.cell.row != next_obj->v.cell.row ||
+            focus_obj->v.cell.column != next_obj->v.cell.column)
+      {
+          if (!xi_move_focus_internal(next_obj, TRUE, FALSE, 0))
+            if (lm_cb_data->cb_type == LM_CB_FOCUS)
+              ref = lm_cb_data->v.refused = TRUE;
+      }
+      }
+      else
+        if (!xi_move_focus_internal(next_obj, TRUE, FALSE, 0))
+          if (lm_cb_data->cb_type == LM_CB_FOCUS)
+            ref = lm_cb_data->v.refused = TRUE;
+      next_obj = get_non_focus_cell_obj(ldata);
+      next_obj->v.cell.row = (unsigned char)(lm_cb_data->row);
+    next_obj->v.cell.column = (unsigned char)(lm_cb_data->column);
+      send_cb = FALSE;
+      if ((! ref) && (lm_cb_data->cb_type == LM_CB_CELL_BTN))
+      {
+      xiev.type = XIE_BUTTON;
+        xiev.v.xi_obj = next_obj;
+        send_cb = TRUE;
+      }
+      break;
+    }
+  case LM_CB_DBL:
+    xiev.type = XIE_DBL_CELL;
+  send_cb = TRUE;
+    break;
+  case LM_CB_TEXT:
+  xiev.type = XIE_CELL_REQUEST;
+  xiev.v.cell_request.list = lm_obj;
+  xiev.v.cell_request.s = lm_cb_data->v.text.text;
+  xiev.v.cell_request.len = lm_cb_data->v.text.len;
+  xiev.v.cell_request.col_nbr = lm_cb_data->column;
+  xiev.v.cell_request.rec = lm_cb_data->rec;
+  xiev.v.cell_request.icon_rid = lm_cb_data->v.text.icon_rid;
+  xiev.v.cell_request.attrib = lm_cb_data->v.text.attrib;
+  xiev.v.cell_request.color = lm_cb_data->v.text.color;
+  xiev.v.cell_request.back_color = lm_cb_data->v.text.back_color;
+  xiev.v.cell_request.records = &lmp->recs[0];
+  send_cb = TRUE;
+  break;
+  case LM_CB_REC_ALLOCATE:
+  xiev.type = XIE_REC_ALLOCATE;
+  xiev.v.rec_allocate.list = lm_obj;
+  xiev.v.rec_allocate.record = lm_cb_data->v.rec_allocate.record;
+  send_cb = TRUE;
+  break;
+  case LM_CB_REC_FREE:
+  xiev.type = XIE_REC_FREE;
+  xiev.v.rec_free.list = lm_obj;
+  xiev.v.rec_free.record = lm_cb_data->v.rec_free.record;
+  send_cb = TRUE;
+  break;
+  case LM_CB_GET_FIRST:
+  case LM_CB_GET_NEXT:
+  case LM_CB_GET_PREV:
+  case LM_CB_GET_LAST:
+  switch (lm_cb_data->cb_type)
+  {
+  case LM_CB_GET_FIRST:
+    xiev.type = XIE_GET_FIRST;
+    break;
+  case LM_CB_GET_NEXT:
+    xiev.type = XIE_GET_NEXT;
+    break;
+  case LM_CB_GET_PREV:
+    xiev.type = XIE_GET_PREV;
+    break;
+  case LM_CB_GET_LAST:
+    xiev.type = XIE_GET_LAST;
+    break;
+  }
+  xiev.v.rec_request.list = lm_obj;
+  xiev.v.rec_request.spec_rec = lm_cb_data->v.rec_request.spec_rec;
+  xiev.v.rec_request.data_rec = lm_cb_data->v.rec_request.data_rec;
+  xiev.v.rec_request.percent = lm_cb_data->v.rec_request.percent;
+  xiev.v.rec_request.attrib = lm_cb_data->v.rec_request.attrib;
+  xiev.v.rec_request.color = lm_cb_data->v.rec_request.color;
+  send_cb = TRUE;
+  break;
+  case LM_CB_GET_PERCENT:
+  xiev.type = XIE_GET_PERCENT;
+  xiev.v.get_percent.list = lm_obj;
+  xiev.v.get_percent.record = lm_cb_data->v.get_percent.record;
+  send_cb = TRUE;
+  break;
+  case LM_CB_SELECT:
+  {
+    if (lm_cb_data->row == 255 && lm_cb_data->column == 255)
+    {
+      xiev.type = XIE_SELECT;
+      xiev.v.select.xi_obj = lm_obj;
+      xiev.v.select.selected = TRUE;
+      xiev.v.select.dbl_click = FALSE;
+      xiev.v.select.shift = lm_cb_data->v.select.shift;
+      xiev.v.select.control = lm_cb_data->v.select.control;
+      xiev.v.select.records = &lmp->recs[0];
+      xiev.v.select.column = 0;
+      send_cb = TRUE;
+    }
+    else if (lm_cb_data->row == 255)
+    {
+      xiev.type = XIE_SELECT;
+      xiev.v.select.xi_obj =
+        lm_obj->children[lm_cb_data->column];
+      xiev.v.select.selected = lm_cb_data->v.select.selected;
+      xiev.v.select.dbl_click = lm_cb_data->v.select.dbl_click;
+      xiev.v.select.shift = lm_cb_data->v.select.shift;
+      xiev.v.select.control = lm_cb_data->v.select.control;
+      xiev.v.select.column = lm_cb_data->column;
+      xiev.v.select.records = &lmp->recs[0];
+      send_cb = TRUE;
+    }
+    else
+    {
+      XI_OBJ row_obj;
+
+      XI_MAKE_ROW(&row_obj, lm_obj, lm_cb_data->row);
+      xiev.type = XIE_SELECT;
+      xiev.v.select.xi_obj = &row_obj;
+      xiev.v.select.selected = lm_cb_data->v.select.selected;
+      xiev.v.select.dbl_click = lm_cb_data->v.select.dbl_click;
+      xiev.v.select.shift = lm_cb_data->v.select.shift;
+      xiev.v.select.control = lm_cb_data->v.select.control;
+      xiev.v.select.column = lm_cb_data->column;
+      xiev.v.select.records = &lmp->recs[0];
+      send_cb = TRUE;
+    }
+    break;
+  }
+  case LM_CB_ROW_SIZE:
+  {
+    XI_OBJ row_obj;
+
+    XI_MAKE_ROW(&row_obj, lm_obj, lm_cb_data->row);
+    xiev.type = XIE_ROW_SIZE;
+    xiev.v.row_size.xi_obj = &row_obj;
+    xiev.v.row_size.new_row_height = lm_cb_data->v.row_size.new_row_height;
+    send_cb = TRUE;
+    break;
+  }
+  case LM_CB_COL_DELETE:
+  xiev.type                   = XIE_COL_DELETE;
+  xiev.v.column.list          = lm_obj;
+  xiev.v.column.col_nbr       = lm_cb_data->column;
+  send_cb = TRUE;
+  break;
+  case LM_CB_COL_MOVE:
+  xiev.type                   = XIE_COL_MOVE;
+  xiev.v.column.list          = lm_obj;
+  xiev.v.column.col_nbr       = lm_cb_data->column;
+  xiev.v.column.new_col_nbr   = lm_cb_data->v.column.new_col_nbr;
+  xiev.v.column.in_fixed      = lm_cb_data->v.column.in_fixed;
+  send_cb = TRUE;
+  break;
+  case LM_CB_COL_SIZE:
+  xiev.type                   = XIE_COL_SIZE;
+  xiev.v.column.list          = lm_obj;
+  xiev.v.column.col_nbr       = lm_cb_data->column;
+  xiev.v.column.new_col_width = lm_cb_data->v.column.new_col_width;
+  xiev.v.column.new_col_pixel_width =
+                      lm_cb_data->v.column.new_col_pixel_width;
+  send_cb = TRUE;
+  break;
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20009", 20009, "XI: unknown LM callback");
+  }
+  if (send_cb)
+    call_cb(lm_obj->itf, &xiev);
+  if (lm_cb_data->cb_type == LM_CB_CHAR)
+  {
+    lm_cb_data->v.chr.refused = xiev.refused;
+    lm_cb_data->v.chr.ch = xiev.v.chr.ch;
+  }
+  if (lm_cb_data->cb_type == LM_CB_SELECT)
+    lm_cb_data->v.select.refused = xiev.refused;
+  if (lm_cb_data->cb_type == LM_CB_ROW_SIZE)
+    lm_cb_data->v.row_size.refused = xiev.refused;
+  if (lm_cb_data->cb_type == LM_CB_TEXT)
+  {
+    lm_cb_data->v.text.icon_rid = xiev.v.cell_request.icon_rid;
+    lm_cb_data->v.text.attrib = xiev.v.cell_request.attrib;
+    lm_cb_data->v.text.color = xiev.v.cell_request.color;
+    lm_cb_data->v.text.back_color = xiev.v.cell_request.back_color;
+    lm_cb_data->v.text.font = xiev.v.cell_request.font;
+    lm_cb_data->v.text.font_id = xiev.v.cell_request.font_id;
+    lm_cb_data->v.text.button = xiev.v.cell_request.button;
+    lm_cb_data->v.text.button_on_left = xiev.v.cell_request.button_on_left;
+    lm_cb_data->v.text.button_on_focus = xiev.v.cell_request.button_on_focus;
+    lm_cb_data->v.text.button_icon_rid = xiev.v.cell_request.button_icon_rid;
+  }
+  if (lm_cb_data->cb_type == LM_CB_GET_PERCENT)
+    lm_cb_data->v.get_percent.percent = xiev.v.get_percent.percent;
+  if (lm_cb_data->cb_type == LM_CB_REC_ALLOCATE)
+    lm_cb_data->v.rec_allocate.record = xiev.v.rec_allocate.record;
+
+  switch (lm_cb_data->cb_type)
+  {
+  case LM_CB_GET_FIRST:
+  case LM_CB_GET_NEXT:
+  case LM_CB_GET_PREV:
+  case LM_CB_GET_LAST:
+    lm_cb_data->v.rec_request.data_rec = xiev.v.rec_request.data_rec;
+    lm_cb_data->v.rec_request.attrib = xiev.v.rec_request.attrib;
+    lm_cb_data->v.rec_request.color = xiev.v.rec_request.color;
+    lm_cb_data->v.rec_request.row_height = xiev.v.rec_request.row_height;
+    lm_cb_data->v.rec_request.refused = xiev.refused;
+    lm_cb_data->v.rec_request.has_focus = xiev.v.rec_request.has_focus;
+    break;
+  case LM_CB_COL_DELETE:
+  case LM_CB_COL_MOVE:
+  case LM_CB_COL_SIZE:
+    lm_cb_data->v.column.refused = xiev.refused;
+    break;
+  }
+}
+
+/*
+  This queue is more of a stack than a queue but event ordering
+  is not important.  This function is used to queue up events for
+  later processing to avoid recursive callbacks at bad times.
+
+  For example, XIE_INIT is queued up during interface creation.
+*/
+static void near
+xi_enqueue(XI_EVENT *xiev, XI_OBJ *itf)
+{
+  XI_EQ* xi_el;
+
+  xi_el = (XI_EQ *)xi_tree_malloc(sizeof(XI_EQ), NULL);
+  xi_el->xiev = *xiev;
+  xi_el->itf = itf;
+  xi_el->next = NULL;
+  if (xi_eq == NULL)
+    xi_eq = xi_el;
+  else
+  {
+    XI_EQ* last = xi_eq;
+
+    while (last->next != NULL)
+      last = last->next;
+    last->next = xi_el;
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+/* remove all events associated with an interface from the que               */
+/* ------------------------------------------------------------------------- */
+
+static void xi_que_remove( XI_OBJ* itf )
+{
+  XI_EQ* current;
+  XI_EQ* last;
+
+  last = NULL;
+  current = xi_eq;
+  while (current != NULL)
+  {
+    if (current->itf != itf)
+    {
+      last = current;
+      current = current->next;
+    } else
+    {
+      XI_EQ* next = current->next;
+
+      if (last == NULL)
+        xi_eq = next;
+      else
+        last->next = next;
+      xi_tree_free( current );
+      current = next;
+    }
+  }
+}
+
+/*
+  This function will dequeue all events queued up via xi_enqueue.
+  This function is called at the end of xi_event, so that any
+  events that were queued would be flushed out at that time.
+*/
+void
+xi_dequeue(void)
+{
+  XI_EQ *xi_el;
+  XI_OBJ * *objp;
+  XI_OBJ *editable;
+  int i;
+  static BOOLEAN inside;      /* avoid recursive calls */
+
+  if (inside)
+    return;
+  inside = TRUE;
+  while (xi_eq != NULL)
+  {
+    xi_el = xi_eq;
+
+    call_cb(xi_el->itf, &xi_el->xiev);
+    if (xi_el == xi_eq)
+    {
+      xi_eq = xi_eq->next;
+      if (xi_el->xiev.type == XIE_INIT)
+      {
+        /* fill in all lists */
+        for (objp = xi_el->itf->children, i = xi_el->itf->nbr_children;
+            i != 0; i--, objp++)
+        {
+          if ((*objp)->type == XIT_LIST)
+          {
+            if (! (*objp)->v.list->done_initial_xi_scroll)
+            {
+              if (xi_get_attrib(*objp) & XI_ATR_VISIBLE)
+              {
+                (*objp)->v.list->done_initial_xi_scroll = TRUE;
+                xi_scroll_internal(*objp, XI_SCROLL_FIRST,
+                                  (*objp)->v.list->start_percent, FALSE );
+              }
+            }
+          }
+        }
+        editable = xi_search_itf(xi_el->itf, XI_SEARCH_FOR_FOCUSABLE, 0);
+        if (editable)
+          xi_move_focus_internal(editable, TRUE, FALSE, 0);
+      }
+      xi_tree_free((char *)xi_el);
+    }
+  }
+  inside = FALSE;
+}
+
+/*
+  xi_add_window_to_list: Record a window as being an XI window,
+  so that XI can tell its windows apart from other windows.
+*/
+static void near
+xi_add_window_to_list(WINDOW win, XI_OBJ *itf)
+{
+  XI_WINDOW_LIST *list;
+
+  /*
+    list_parent is the tree memory parent of all structures in the
+    linked list of windows.  It is used to avoid clogging up the
+    FIRSTNODE's child list too much.
+  */
+  if (list_parent == NULL)
+    list_parent = (char *)xi_tree_malloc(1, NULL);
+  list = (XI_WINDOW_LIST *)xi_tree_malloc(sizeof(XI_WINDOW_LIST), list_parent);
+  list->next = xi_window_list;
+  list->win = win;
+  list->itf = itf;
+  xi_window_list = list;
+}
+
+void
+xi_remove_window_from_list(WINDOW win)
+{
+  XI_WINDOW_LIST *list;
+  XI_WINDOW_LIST *next;
+
+  if (win == xi_window_list->win)
+  {
+    list = xi_window_list;
+    xi_window_list = xi_window_list->next;
+    xi_que_remove( list->itf );
+    xi_tree_free(list);
+    if (xi_window_list == NULL)
+    {
+      xi_tree_free(list_parent);
+      list_parent = NULL;
+    }
+    return;
+  }
+  else
+  {
+    for (list = xi_window_list;
+        list != NULL && (next = list->next) != NULL;
+        list = next)
+    {
+      if (next->win == win)
+      {
+        list->next = next->next;
+        xi_que_remove( next->itf );
+        xi_tree_free(next);
+        return;
+      }
+    }
+  }
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20004",
+    20004, "Internal XI error");   
+}
+
+/* find an interface from its id */
+XI_OBJ *xi_get_itf_from_id( int id )
+{
+  XI_WINDOW_LIST *list;
+
+  list = xi_window_list;
+  while (list != NULL && list->itf->cid != id)
+    list = list->next;
+  if (list == NULL)
+    return NULL;
+  return list->itf;
+}
+
+BOOLEAN
+xi_is_window(WINDOW win)
+{
+  register XI_WINDOW_LIST *list;
+
+  for (list = xi_window_list; list != NULL; list = list->next)
+    if (list->win == win)
+      return TRUE;
+  return FALSE;
+}
+
+BOOLEAN
+xi_is_itf(XI_OBJ *itf)
+{
+  register XI_WINDOW_LIST *list;
+
+  for (list = xi_window_list; list != NULL; list = list->next)
+    if (list->itf == itf)
+      return TRUE;
+  return FALSE;
+}
+
+BOOLEAN
+xi_is_changed( XI_OBJ* obj )
+{
+  return obj->itf->v.itf->chg_flag;
+}
+
+XI_OBJ *
+xi_get_itf(WINDOW win)
+{
+  XI_WINDOW_LIST *next;
+
+  for (next = xi_window_list; next != NULL; next = next->next)
+    if (next->win == win)
+    {
+      return next->itf;
+    }
+  return NULL;
+}
+
+/* ------------------------------------------------------------------------ */
+/*  create_children                                                         */
+/* ------------------------------------------------------------------------ */
+static XI_OBJ * xi_create_internal( XI_OBJ * parent, XI_OBJ_DEF* xi_obj_def,
+                                    BOOLEAN creating_list );
+
+
+static void create_children( XI_OBJ_DEF* xi_obj_def, XI_OBJ* obj,
+BOOLEAN creating_list  )
+{
+  XI_OBJ_DEF * * child;
+  int                  i;
+
+  /* create children of the object if there are any */
+  child = xi_obj_def->children;
+  for (i = 0; i < xi_obj_def->nbr_children; child++, i++)
+    /* xi_create automatically adds object to the parent list */
+    xi_create_internal(obj, *child, creating_list );
+}
+
+/* ------------------------------------------------------------------------ */
+/*  create_interface                                                        */
+/* ------------------------------------------------------------------------ */
+static void
+interface_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* itf )
+{
+  static BOOLEAN   first_itf = TRUE;
+  XI_ITF_DATA *    itf_data;
+  XI_ITF_DEF *     itf_def;
+  RCT              def_rct;
+  RCT *            rctp;
+  RCT              rct;
+  WINDOW           itf_win;
+  BOOLEAN          do_move_window = FALSE;
+  XI_EVENT         xiev;
+
+  itf_def = xi_obj_def->v.itf;
+  rctp = itf_def->rctp;
+  xi_get_def_rect(xi_obj_def, &def_rct);
+  def_rct.left = 12;
+  def_rct.right += 12;
+  if (rctp == NULL || rctp->top == rctp->bottom)
+  {
+    rct = def_rct;
+    if (rctp)
+      xvt_rect_offset(&rct, rctp->left, rctp->top);
+  }
+  else
+    rct = *rctp;
+  itf_data = (XI_ITF_DATA *)xi_tree_malloc(sizeof(XI_ITF_DATA),
+      (char *)itf);
+  itf_data->xi_eh = itf_def->xi_eh;
+  itf_data->half_baked = TRUE;
+  itf_data->edit_menu = itf_def->edit_menu;
+  itf_data->back_color = itf_def->back_color;
+  itf_data->automatic_back_color = itf_def->automatic_back_color;
+  if (itf_def->automatic_back_color)
+  {
+#if (XIWS == XOLWS)
+    itf_data->back_color = COLOR_GRAY;
+#else
+    if (xi_get_pref(XI_PREF_3D_LOOK))
+      itf_data->back_color = COLOR_LTGRAY;
+    else
+      itf_data->back_color = COLOR_WHITE;
+#endif
+  }
+  itf_data->virtual_itf = itf_def->virtual_itf;
+  itf_data->modal = itf_def->modal;
+  itf_data->size_font_to_win = itf_def->size_font_to_win;
+  itf_data->tab_on_enter = itf_def->tab_on_enter;
+  itf_data->prev_modal = NULL_WIN;
+  itf->v.itf = itf_data;
+  itf_data->use_xil_win = itf_def->use_xil_win;
+  if (itf_def->font_id)
+  {
+  itf_data->font = (FONT_OBJ *)xi_tree_malloc(sizeof(FONT_OBJ),
+      itf_data);
+  *itf_data->font = xi_create_copy_font_id(itf->itf,
+      itf_def->font_id, 0);
+  }
+  itf_data->fu_height = xi_get_fu_height_font(
+      itf_data->font ? itf_data->font : &xi_sysfont);
+  itf_data->fu_width = xi_get_fu_width_font(
+      itf_data->font ? itf_data->font : &xi_sysfont);
+  itf_data->max_xi_pnt.h = def_rct.right - def_rct.left;
+  itf_data->max_xi_pnt.v = def_rct.bottom - def_rct.top;
+  xi_pu_to_fu(itf->itf, &itf_data->max_xi_pnt, 1);
+  xi_even_fu_pnt(&itf_data->max_xi_pnt);
+
+    itf_data->menu_win = itf_def->menu_win;
+    if (itf_def->win)
+    {
+      itf_data->xvt_win = itf_def->win;
+      itf_win = itf_def->win;
+      if (itf_def->size_win)
+        do_move_window = TRUE;
+    }
+    else
+    {
+      WIN_TYPE win_type;
+      WINDOW parent;
+
+      win_type = W_DOC;
+      parent = NULL_WIN;
+    if (itf_data->modal)
+    {
+      parent = SCREEN_WIN;
+#if XIWS == WINWS
+      xvt_vobj_set_attr(0, ATTR_WIN_POPUP_DETACHED, TRUE);
+#endif
+    }
+    if (rct.top < xi_get_pref(XI_PREF_ITF_MIN_TOP))
+      {
+        int delta;
+
+        delta = (int)xi_get_pref(XI_PREF_ITF_MIN_TOP) - rct.top;
+        rct.top += delta;
+        rct.bottom += delta;
+      }
+      if (rct.left < xi_get_pref(XI_PREF_ITF_MIN_LEFT))
+    {
+      int delta;
+
+      delta = (int)xi_get_pref(XI_PREF_ITF_MIN_LEFT) - rct.left;
+      rct.left += delta;
+      rct.right += delta;
+    }
+    itf_data->xvt_win = xi_new_child_window(&rct,
+      itf_def->title, win_type, itf_def->ctl_size,
+      itf_def->ctl_vscroll, itf_def->ctl_hscroll,
+      itf_def->ctl_close, itf_def->ctl_iconized,
+      itf_def->ctl_iconizable, parent, PTR_LONG(itf),
+      0, 0L, TRUE, TRUE, itf_def->menu_bar_rid);
+    if (itf_data->modal)
+    {
+      if (xi_modal_win != NULL_WIN)
+      {   /* Nested modal */
+      itf_data->prev_modal = xi_modal_win;
+#if (XIWS == WINWS) || (XIWS == PMWS)
+      xvt_vobj_set_enabled(xi_modal_win, FALSE);
+#endif
+#if (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS)
+      xvt_vobj_set_enabled(xi_modal_win, FALSE);
+#if XIWS == MACWS
+      xvt_scr_set_focus_vobj( itf_data->xvt_win );
+      xvt_vobj_raise( itf_data->xvt_win );          
+#endif
+#endif
+      xi_modal_win = itf_data->xvt_win;
+      } else
+      {
+#if (XIWS == WINWS) || (XIWS == PMWS)
+      xvt_vobj_set_enabled(TASK_WIN, FALSE);
+#endif
+      xi_modal_win = itf_data->xvt_win;
+#if (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS)
+      {
+        SLIST win_list = xvt_scr_list_wins();
+        SLIST_ELT elt;
+
+        for (elt = xvt_slist_get_first(win_list); elt != NULL;
+          elt = xvt_slist_get_next(win_list, elt))
+        {
+          if ((WINDOW)*xvt_slist_get_data(elt) != xi_modal_win)
+          {
+          xvt_vobj_set_enabled((WINDOW)*xvt_slist_get_data(elt), FALSE);
+          }
+        }
+        xvt_slist_destroy(win_list);
+      }
+#endif
+      }
+    }
+    itf_win = itf_data->xvt_win;
+    itf_data->win_xi_pnt.v = rct.bottom - rct.top;
+    itf_data->win_xi_pnt.h = rct.right - rct.left;
+    xi_pu_to_fu(itf->itf, &itf_data->win_xi_pnt, 1);
+    xi_even_fu_pnt(&itf_data->win_xi_pnt);
+  }
+  xvt_vobj_get_client_rect(itf_win, &itf_data->original_win_rct);
+  if (itf_data->font)
+    itf_data->original_font_size = (int)xvt_font_get_size(*itf_data->font);
+  xi_add_window_to_list(itf_data->xvt_win, itf);
+  if (xi_get_pref(XI_PREF_USE_APP_DATA))
+  xvt_vobj_set_data(itf_data->xvt_win, PTR_LONG(itf));
+  if (itf_data->virtual_itf)
+  {
+  xi_adjust_sb_vir_itf(itf_win, itf);
+  xvt_sbar_set_range(itf_data->xvt_win, HSCROLL, 0, 100);
+    xvt_sbar_set_range(itf_data->xvt_win, VSCROLL, 0, 100);
+  }
+  first_itf = FALSE;
+  xi_add_to_parent_list(itf, -1);
+#if XI_IS_CH
+  CTOS_IS_CH;
+  xi_coalesce_invalidates(itf, TRUE);
+  CTOS_END;
+#endif
+  create_children( xi_obj_def, itf, FALSE );
+  /* queue up initialization event */
+  xiev.type = XIE_INIT;
+  xiev.v.xi_obj = itf;
+  xi_enqueue(&xiev, itf);
+
+#if XI_IS_CH
+  CTOS_IS_CH;
+  xi_coalesce_invalidates(itf, FALSE);
+  CTOS_END;
+#endif
+  if (do_move_window)
+    xvt_vobj_move(itf_win, &rct);
+}
+
+/* ------------------------------------------------------------------------ */
+/*  assign rectangles                                                       */
+/* ------------------------------------------------------------------------ */
+static void assign_rectangles( XI_OBJ* itf, XI_RCT* dest_form_rect,
+                              XI_RCT* dest_pixel_rect,
+                              XI_RCT* source_form_rect,
+                              XI_RCT* source_pixel_rect )
+{
+  if (source_pixel_rect->left || source_pixel_rect->right
+      || source_pixel_rect->top || source_pixel_rect->bottom )
+  {
+    *dest_pixel_rect = *dest_form_rect = *source_pixel_rect;
+    xi_pu_to_fu( itf, (PNT *)dest_form_rect, 2);
+  } else
+  {
+    *dest_pixel_rect = *dest_form_rect = *source_form_rect;
+    xi_fu_to_pu(itf, (PNT *)dest_pixel_rect, 2);
+  }
+}
+
+/* ------------------------------------------------------------------------ */
+/*  container_create                                                        */
+/* ------------------------------------------------------------------------ */
+static void container_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* container )
+{
+  XI_CONTAINER_DEF*  cdef;
+  XI_OBJ_DEF*        child;
+  XI_CONTAINER_DATA* cdata;
+  int                i, len, max_len;
+  XI_BTN_TYPE        button_type;
+
+  xvt_errmsg_sig_if(!(xi_obj_def->nbr_children > 0), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20011",
+    20011, "Can't create empty container");   
+  max_len     = 0;
+  for (i = 0; i < xi_obj_def->nbr_children; ++i)
+  {
+    child = xi_obj_def->children[i];
+  xvt_errmsg_sig_if(!(child->type == XIT_BTN), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20012",
+    20012, "Containers can only contain buttons");   
+    if (i ==0)
+      button_type = child->v.btn->type;
+    else
+    xvt_errmsg_sig_if(!(child->v.btn->type == button_type), NULL_WIN,
+      SEV_FATAL, ERR_ASSERT_4,"20013",
+      20013, "Can't mix button types in a container");   
+    if ((len = (int)strlen(child->v.btn->text)) > max_len)
+      max_len = len;
+  }
+  cdef                = xi_obj_def->v.container;
+  cdata               = (XI_CONTAINER_DATA *)
+      xi_tree_malloc(sizeof(XI_CONTAINER_DATA), (char *)container);
+  assign_rectangles( container->itf, &cdata->xi_rct, &cdata->rct, &cdef->xi_rct,
+                    &cdef->pixel_rect );
+  cdata->orientation  = cdef->orientation;
+  cdata->tab_cid      = cdef->tab_cid;
+  cdata->btn_height   = cdef->btn_height;
+  cdata->btn_width    = cdef->btn_width;
+  cdata->nbr_buttons  = xi_obj_def->nbr_children;
+  cdata->packed       = cdef->packed;
+  container->v.container    = cdata;
+  xi_container_rect_calc(container, max_len, button_type);
+  xi_add_to_parent_list( container, -1);
+  create_children( xi_obj_def, container, FALSE );
+}
+
+/* ------------------------------------------------------------------------ */
+/*  rectangle_create                                                        */
+/* ------------------------------------------------------------------------ */
+static void rectangle_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* rectangle )
+{
+  XI_RECT_DATA *rect_data;
+  XI_RECT_DEF *rect_def = xi_obj_def->v.rect;
+
+  rect_data = (XI_RECT_DATA *)xi_tree_malloc(sizeof(XI_RECT_DATA),
+    rectangle);
+  rect_data->fore_color = rect_def->fore_color;
+  rect_data->back_color = rect_def->back_color;
+  rect_data->hilight_color = rect_def->hilight_color;
+  rect_data->shadow_color = rect_def->shadow_color;
+  rect_data->well = rect_def->well;
+  rect_data->ridge = rect_def->ridge;
+  rect_data->attrib = rect_def->attrib;
+#if XI_IS_CH
+  CTOS_IS_CH;
+  {
+  RCT rct;
+  rect_data->xi_rct = rect_def->xi_rct;
+  rct = rect_def->xi_rct;
+  rct.top = (rct.top / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+  rct.left = (rct.left / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+  rct.bottom = ((rct.bottom + XI_FU_MULTIPLE / 2) / XI_FU_MULTIPLE) *
+    XI_FU_MULTIPLE;
+  rct.right = ((rct.right + XI_FU_MULTIPLE / 2) / XI_FU_MULTIPLE) *
+    XI_FU_MULTIPLE;
+  rect_data->rct = rct;
+  }
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  assign_rectangles( rectangle->itf, &rect_data->xi_rct, &rect_data->rct,
+                    &rect_def->xi_rct, &rect_def->pixel_rect );
+  CTOS_END;
+#endif
+  rectangle->v.rect = rect_data;
+#if XI_IS_CH
+  xi_invalidate_rect( rectangle->itf->v.itf->xvt_win, &rct);
+#endif
+  xi_add_to_parent_list(rectangle, -1);
+  xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20050", 20050,
+    "xi_create: Rectangles cannot have children");   
+}
+
+/* ------------------------------------------------------------------------ */
+/*  line_create                                                             */
+/* ------------------------------------------------------------------------ */
+static void line_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* line )
+{
+  XI_LINE_DATA *line_data;
+  XI_LINE_DEF  *line_def = xi_obj_def->v.line;
+  PNT pnt1, pnt2;
+  RCT rct;
+
+  line_data = (XI_LINE_DATA *)xi_tree_malloc(
+      sizeof(XI_LINE_DATA), line);
+  line_data->fore_color = line_def->fore_color;
+  line_data->well = line_def->well;
+  line_data->attrib = line_def->attrib;
+  if ( line_def->pixel_pnt1.h || line_def->pixel_pnt1.v
+      || line_def->pixel_pnt2.h || line_def->pixel_pnt2.v )
+  {
+    pnt1 = line_def->pixel_pnt1;
+    pnt2 = line_def->pixel_pnt2;
+    line_data->xi_pnt1 = pnt1;
+    line_data->xi_pnt2 = pnt2;
+    xi_pu_to_fu(line->itf, &line_data->xi_pnt1, 1);
+    xi_pu_to_fu(line->itf, &line_data->xi_pnt2, 1);
+  } else
+  {
+    pnt1 = line_def->pnt1;
+    pnt2 = line_def->pnt2;
+    line_data->xi_pnt1 = pnt1;
+    line_data->xi_pnt2 = pnt2;
+#if XI_IS_CH
+    CTOS_IS_CH;
+    pnt1.h = (pnt1.h / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+    pnt1.v = (pnt1.v / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+    pnt2.h = (pnt2.h / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+    pnt2.v = (pnt2.v / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+    CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    xi_fu_to_pu(line->itf, &pnt1, 1);
+    xi_fu_to_pu(line->itf, &pnt2, 1);
+    CTOS_END;
+#endif
+  }
+  line_data->pnt1 = pnt1;
+  line_data->pnt2 = pnt2;
+  line->v.line = line_data;
+  rct.top = min(pnt1.v, pnt2.v);
+  rct.left = min(pnt1.h, pnt2.h);
+  rct.bottom = max(pnt1.v, pnt2.v);
+  rct.right = max(pnt1.h, pnt2.h);
+  xi_invalidate_rect( line->itf->v.itf->xvt_win, &rct);
+  xi_add_to_parent_list(line, -1);
+  xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20051", 20051,
+    "xi_create: Lines cannot have children");   
+}
+
+/* ------------------------------------------------------------------------ */
+/*  button_create                                                           */
+/* ------------------------------------------------------------------------ */
+static void button_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* button )
+{
+  XI_BTN_DATA *btn_data;
+  XI_BTN_DEF  *btn_def = xi_obj_def->v.btn;
+  RCT              rct;
+  WINDOW           itf_win;
+
+  itf_win = button->itf->v.itf->xvt_win;
+  btn_data = (XI_BTN_DATA *) xi_tree_malloc(sizeof(XI_BTN_DATA), button);
+  btn_data->attrib    = btn_def->attrib;
+  btn_data->tab_cid   = btn_def->tab_cid;
+  btn_data->dflt      = btn_def->dflt;
+  btn_data->down_icon_rid     = btn_def->down_icon_rid;
+  btn_data->up_icon_rid       = btn_def->up_icon_rid;
+  btn_data->disabled_icon_rid = btn_def->disabled_icon_rid;
+  btn_data->icon_x    = btn_def->icon_x;
+  btn_data->icon_y    = btn_def->icon_y;
+  btn_data->text      = (char *)
+      xi_tree_malloc(strlen(btn_def->text) + 1, btn_data);
+  btn_data->checked   = btn_def->checked;
+  btn_data->type      = btn_def->type;
+  btn_data->fore_color    = btn_def->fore_color;
+  btn_data->drawable  = btn_def->drawable;
+  strcpy(btn_data->text, btn_def->text);
+  assign_rectangles( button->itf, &btn_data->xi_rct, &btn_data->rct,
+                    &btn_def->xi_rct, &btn_def->pixel_rect );
+  button->v.btn       = btn_data;
+  xi_button_rect_calc(button, button->parent->nbr_children);
+  rct = btn_data->rct;
+  if (! (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS))
+    xi_invalidate_rect(itf_win, &rct);
+  else
+  {
+    WIN_TYPE type;
+
+    switch (btn_def->type)
+    {
+    case XIBT_BUTTON:
+    case XIBT_BUTTON_CHECKBOX:
+    case XIBT_BUTTON_RADIOBTN:
+      type = WC_PUSHBUTTON;
+      break;
+    case XIBT_RADIOBTN:
+    case XIBT_TABBTN:
+      type = WC_RADIOBUTTON;
+      break;
+    case XIBT_CHECKBOX:
+      type = WC_CHECKBOX;
+      break;
+    }
+    btn_data->btnctl = xi_new_control(&rct, btn_def->text,
+        type, itf_win,
+        (BOOLEAN)((btn_def->attrib & XI_ATR_VISIBLE) != 0),
+        xi_obj_def->cid, NULL);
+    if ((btn_def->attrib & XI_ATR_ENABLED) == 0)
+      xvt_vobj_set_enabled(btn_data->btnctl, FALSE);
+    if (btn_def->checked && type == WC_CHECKBOX)
+      xvt_ctl_set_checked(btn_data->btnctl, TRUE);
+  }
+  xi_add_to_parent_list(button, -1);
+  xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN,
+    SEV_FATAL, ERR_ASSERT_4,"20052", 20052,
+    "xi_create: Buttons cannot have children");   
+}
+
+/* ------------------------------------------------------------------------ */
+/*  form_create                                                             */
+/* ------------------------------------------------------------------------ */
+static void form_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* form )
+{
+  XI_FORM_DATA *form_data;
+  XI_FORM_DEF *form_def;
+
+  form_def = xi_obj_def->v.form;
+  form_data = (XI_FORM_DATA *)
+      xi_tree_malloc(sizeof(XI_FORM_DATA), (char *)form);
+  form_data->attrib = XI_ATR_VISIBLE | XI_ATR_ENABLED;
+  form_data->tab_cid = form_def->tab_cid;
+  form->v.form = form_data;
+  xi_add_to_parent_list(form, -1);
+  create_children( xi_obj_def, form, FALSE );
+}
+
+/* ------------------------------------------------------------------------ */
+/*  field_create                                                            */
+/* ------------------------------------------------------------------------ */
+static void field_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* field )
+{
+  STX_DEF            stxdef;
+  XI_FIELD_DATA * field_data;
+  XI_FIELD_DEF *  xi_fd;
+  int                btn_dim_x;
+  int                btn_dim_x2;
+  int                fu_width;
+  int                fu_height;
+  int                edit_height;
+  int                btn_space;
+  WINDOW             itf_win;
+  int                leading, ascent, descent, font_height;
+
+  itf_win = field->itf->v.itf->xvt_win;
+  fu_width = xi_get_fu_width(field->itf);
+  fu_height = xi_get_fu_height(field->itf);
+  btn_dim_x = (fu_height * XI_FU_MULTIPLE) / fu_width;
+  /* btn_dim_x is actual width of button */
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  /* make buttons 70% wide as high */
+  btn_dim_x = (int)((long)btn_dim_x * 83L / 100L);
+  CTOS_END;
+#endif
+  btn_space = btn_dim_x / 6;
+  /* btn_dim_x2 is the button width + space, rounded up to */
+  /* the next even form unit */
+  btn_dim_x2 = btn_dim_x + btn_space;
+  btn_dim_x2 = ((btn_dim_x2 + XI_FU_MULTIPLE) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+  btn_dim_x = (int)(((long)btn_dim_x * fu_width) / XI_FU_MULTIPLE);
+  btn_dim_x2 = (int) (((long)btn_dim_x2 * fu_width) / XI_FU_MULTIPLE);
+  MEMCLEAR(stxdef);
+  stxdef.cid = xi_obj_def->cid;
+  xi_fd = xi_obj_def->v.field;
+  stxdef.pnt = xi_fd->pixel_origin;
+  if (stxdef.pnt.v == 0 && stxdef.pnt.h == 0)
+  {
+    stxdef.pnt = xi_fd->pnt;
+    xi_fu_to_pu(field->itf, &stxdef.pnt, 1);
+  }
+  stxdef.pixel_width = xi_fd->pixel_width;
+  if (stxdef.pixel_width == 0)
+    stxdef.pixel_width = xi_fd->field_width * fu_width / XI_FU_MULTIPLE;
+  stxdef.xi_rct = xi_fd->xi_rct;
+  field_data = (XI_FIELD_DATA *)xi_tree_malloc(sizeof(XI_FIELD_DATA),
+      (char *)field);
+  if (xi_fd->font_id)
+  {
+  stxdef.font = xi_create_copy_font_id(field->itf, xi_fd->font_id, 0);
+  field_data->font_set = TRUE;
+  }
+  else if (field->itf->v.itf->font)
+  {
+  stxdef.font = *field->itf->v.itf->font;
+  field_data->font_set = TRUE;
+  }
+  else
+  {
+  stxdef.font = xi_sysfont;
+  field_data->font_set = FALSE;
+  }
+  field_data->rct.top = stxdef.pnt.v;
+  field_data->rct.left = stxdef.pnt.h;
+  field_data->rct.right = stxdef.pnt.h + stxdef.pixel_width;
+  field_data->rct.bottom = stxdef.pnt.v + fu_height;
+  xi_set_xvt_font(itf_win, &stxdef.font, FALSE);
+  xi_get_font_metrics(itf_win, &leading, &ascent, &descent);
+  font_height = ascent + leading + descent;
+  edit_height = font_height + (2 * EDIT_BORDER_WIDTH_Y) +
+      (2 * EDIT_BORDER_SPACE_Y);
+  if (! (xi_fd->xi_rct.top || xi_fd->xi_rct.bottom ||
+      xi_fd->xi_rct.left || xi_fd->xi_rct.right))
+  {
+    if (xi_fd->button)
+    {
+
+      field_data->btn_rct.top = stxdef.pnt.v;
+      if (xi_fd->button_on_left)
+      {
+        field_data->btn_rct.left = stxdef.pnt.h;
+        field_data->btn_rct.right =
+            field_data->btn_rct.left + btn_dim_x;
+        if (xi_fd->pixel_button_distance)
+          stxdef.pnt.h = field_data->btn_rct.right
+                        + xi_fd->pixel_button_distance;
+        else
+          stxdef.pnt.h += btn_dim_x2;
+      } else
+      {
+#if XI_IS_CH
+        BOOLEAN b;
+
+        CTOS_IS_CH;
+        b = (BOOLEAN)(xi_fd->attrib & XI_ATR_BORDER);
+        field_data->btn_rct.left = stxdef.pnt.h + stxdef.pixel_width
+                                  + (b ? 24 : 8);
+        field_data->btn_rct.right = field_data->btn_rct.left + 8;
+        CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+        /* TODO problem with this code */
+        /* TODO Need a boolean - place button next to field */
+        /* TODO Need to handle correctly if use a button on a field with xi_rct
+specified */
+        CTOS_IS_PM;
+        if (xi_fd->pixel_button_distance)
+        {
+          field_data->btn_rct.left = stxdef.pnt.h + stxdef.pixel_width
+                                    + xi_fd->pixel_button_distance;
+          field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x;
+        } else
+        {
+          int right;
+
+          right = stxdef.pnt.h + stxdef.pixel_width + btn_dim_x2;
+          /* convert to form units */
+          right = (int)(((long)right * XI_FU_MULTIPLE) / fu_width );
+          /* round up to nearest FU multiple */
+          right = ((right + XI_FU_MULTIPLE) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+          /* convert to pixels */
+          right = (int)(((long)right * fu_width) / XI_FU_MULTIPLE);
+          field_data->btn_rct.right = right;
+          field_data->btn_rct.left = right - btn_dim_x;
+        }
+        CTOS_END;
+#endif
+      }
+    }
+  }
+  else
+  {
+    field_data->rct = xi_fd->xi_rct;
+    xi_fu_to_pu(field->itf, (PNT *)&field_data->rct, 2);
+    if (xi_fd->button)
+    {
+      field_data->btn_rct = xi_fd->xi_rct;
+      xi_fu_to_pu(field->itf, (PNT *)&field_data->btn_rct, 2);
+      if (xi_fd->button_on_left)
+      {
+        PNT p;
+
+        p.h = btn_dim_x2;
+        xi_pu_to_fu(field->itf, &p, 1);
+        field_data->btn_rct.right =
+            field_data->btn_rct.left + btn_dim_x;
+        stxdef.xi_rct.left += p.h;
+        stxdef.xi_rct.right += p.h;
+      }
+      else
+      {
+        int right;
+
+        right = field_data->btn_rct.right + btn_space + btn_dim_x2;
+        /* convert to form units */
+        right = (int)(((long)right * XI_FU_MULTIPLE) / fu_width );
+        /* round up to nearest FU multiple */
+        right = ((right + XI_FU_MULTIPLE) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+        /* convert to pixels */
+        right = (int)(((long)right * fu_width) / XI_FU_MULTIPLE);
+        field_data->btn_rct.right = right;
+        field_data->btn_rct.left = right - btn_dim_x;
+      }
+    }
+  }
+  field_data->btn_rct.bottom = field_data->btn_rct.top +
+      edit_height;
+  stxdef.pix_char_width = fu_width;
+  stxdef.attrib = xi_fd->attrib;
+  stxdef.text_size = xi_fd->text_size;
+  stxdef.back_color = xi_fd->back_color;
+  stxdef.enabled_color = xi_fd->enabled_color;
+  stxdef.disabled_color = xi_fd->disabled_color;
+  stxdef.disabled_back_color = xi_fd->disabled_back_color;
+  stxdef.active_color = xi_fd->active_color;
+  stxdef.active_back_color = xi_fd->active_back_color;
+  stxdef.hilight_color = xi_fd->hilight_color;
+  stxdef.shadow_color = xi_fd->shadow_color;
+  stxdef.stx_cb = xi_stx_cb;
+  stxdef.app_data = PTR_LONG(field);
+  stxdef.parent = (char *)field_data;
+  stxdef.well = xi_fd->well;
+  stxdef.platform = xi_fd->platform;
+  stxdef.auto_tab = xi_fd->auto_tab;
+  field_data->stx = stx_create(itf_win, &stxdef);
+  field_data->tab_cid = xi_fd->tab_cid;
+  field_data->button = xi_fd->button;
+  field_data->button_on_left = xi_fd->button_on_left;
+  field_data->icon_rid = xi_fd->icon_rid;
+  field_data->well = xi_fd->well;
+  field_data->platform = xi_fd->platform;
+  field_data->xi_rct = xi_fd->xi_rct;
+  field_data->xi_pnt = xi_fd->pnt;
+  field_data->field_width = xi_fd->field_width;
+  field->v.field = field_data;
+  xi_add_to_parent_list(field, -1);
+  xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN,
+    SEV_FATAL, ERR_ASSERT_4,"20053", 20053,
+    "xi_create: Fields cannot have children");   
+}
+
+
+/* ------------------------------------------------------------------------ */
+/*  text_create                                                             */
+/* ------------------------------------------------------------------------ */
+static void text_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* text )
+{
+  XI_TEXT_DATA *text_data;
+  XI_TEXT_DEF *text_def = xi_obj_def->v.text;
+
+  text_data = (XI_TEXT_DATA *)
+    xi_tree_malloc(sizeof(XI_TEXT_DATA), text);
+  text_data->attrib = text_def->attrib;
+  assign_rectangles( text->itf, &text_data->xi_rct, &text_data->rct,
+              &text_def->xi_rct, &text_def->pixel_rect );
+  if (text_def->font_id)
+  {
+  text_data->font = (FONT_OBJ *)xi_tree_malloc(sizeof(FONT_OBJ), text_data);
+  *text_data->font = xi_create_copy_font_id(text->itf, text_def->font_id, 0);
+  }
+  text_data->text =
+    (char *)xi_tree_malloc(strlen(text_def->text) + 1, text);
+  strcpy(text_data->text, text_def->text);
+  text_data->fore_color = text_def->fore_color;
+  text_data->back_color = text_def->back_color;
+  text->v.text = text_data;
+  xi_invalidate_rect( text->itf->v.itf->xvt_win, &text_data->rct);
+  xi_add_to_parent_list(text, -1);
+  xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20055", 20055,
+    "xi_create: Static text controls cannot have children");
+}
+
+/* ------------------------------------------------------------------------ */
+/*  group_create                                                            */
+/* ------------------------------------------------------------------------ */
+static void group_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* group,
+                          BOOLEAN creating_list )
+{
+  XI_GROUP_DEF *group_def = xi_obj_def->v.group;
+  XI_GROUP_DATA *group_data;
+
+  group_data = (XI_GROUP_DATA *)xi_tree_malloc( sizeof(XI_GROUP_DATA),
+      group);
+  group_data->nbr_cids = group_def->nbr_cids;
+  group_data->cidlist = (int *)xi_tree_malloc(
+      sizeof(int) * group_def->nbr_cids, group_data);
+  memcpy((char *)group_data->cidlist,
+      (char *)group_def->cids,
+      sizeof(int) * group_def->nbr_cids);
+  group->v.group = group_data;
+  xi_add_to_parent_list(group, -1);
+  create_children( xi_obj_def, group, creating_list );
+}
+
+/* ------------------------------------------------------------------------ */
+/*  column_create                                                           */
+/* ------------------------------------------------------------------------ */
+static void column_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* obj,
+                          BOOLEAN creating_list )
+{
+  LM_COLUMN_DEF       lm_column_def;
+  XI_COLUMN_DATA * column_data;
+  XI_COLUMN_DEF *  col_def;
+  XI_OBJ * *    column;
+  int                 i;
+  int                 pixel_width;
+  LM_DATA *        lmp;
+  XI_LIST_DATA *   list_data;
+  int                 char_pixel_width;
+
+  list_data = obj->parent->v.list;
+  lmp = (LM_DATA *)list_data->lm;
+  MEMCLEAR(lm_column_def);
+  column_data = (XI_COLUMN_DATA *)xi_tree_malloc(sizeof(XI_COLUMN_DATA),
+      (char *)obj);
+  col_def = xi_obj_def->v.column;
+  lm_column_def.attrib = col_def->attrib;
+  char_pixel_width = xi_get_fu_width( obj->itf );
+  if (col_def->pixel_width == 0)
+  if (xi_get_xil_pref((XI_OBJ*) obj ))
+    col_def->pixel_width = col_def->width * char_pixel_width;
+  else
+    col_def->pixel_width = col_def->width * char_pixel_width / XI_FU_MULTIPLE;
+  pixel_width = col_def->pixel_width;
+  if (list_data->width)
+  {
+    pixel_width = lmp->pixel_width;
+    for (i = 0; i < min(lmp->fixed_columns, lmp->nbr_columns); ++i)
+      pixel_width -= lmp->lm_column_data[i]->pix_width;
+    pixel_width = min(pixel_width, col_def->pixel_width);
+  }
+
+  if (col_def->position)
+    lm_column_def.position = min(col_def->position, lmp->nbr_columns);
+  else
+  {
+    for ( lm_column_def.position = i = 0,
+        column = obj->parent->children;
+        i < obj->parent->nbr_children; i++, column++)
+    {
+    xvt_errmsg_sig_if(!((*column)->type == XIT_COLUMN), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4,"20015", 20015,
+      "Internal XI error");   
+      if ((*column)->v.column->sort_number <
+          col_def->sort_number)
+        lm_column_def.position++;
+    }
+  }
+  lm_column_def.pix_width = pixel_width;
+  lm_column_def.text_size = col_def->text_size;
+  if (lm_column_def.text_size < 2)
+  lm_column_def.text_size = 2;
+  lm_column_def.heading_text = col_def->heading_text;
+  lm_column_def.center_heading = col_def->center_heading;
+#if XVTWS != WMWS
+  lm_column_def.heading_well = col_def->heading_well;
+  lm_column_def.heading_platform = col_def->heading_platform;
+  lm_column_def.column_well = col_def->column_well;
+  lm_column_def.column_platform = col_def->column_platform;
+#else
+  lm_column_def.heading_well = FALSE;
+  lm_column_def.heading_platform = FALSE;
+  lm_column_def.column_well = FALSE;
+  lm_column_def.column_platform = FALSE;
+#endif
+  if (col_def->font || col_def->font_id)
+  {
+    lm_column_def.font = (FONT_OBJ *)xi_tree_malloc(sizeof(FONT_OBJ),
+        NULL);
+  if (col_def->font_id)
+    *lm_column_def.font = xi_create_copy_font_id(obj->itf,
+      col_def->font_id, 0);
+  }
+  lm_column_def.icon_rid = col_def->icon_rid;
+  lm_column_def.icon_x = col_def->icon_x;
+  lm_column_def.icon_y = col_def->icon_y;
+  lm_column_def.size_rows = col_def->size_rows;
+  lm_column_def.suppress_update_heading = col_def->suppress_update_heading;
+  lm_column_def.suppress_update_cells = col_def->suppress_update_cells;
+  lm_column_def.vertical_align_center = col_def->vertical_align_center;
+  lm_column_def.vertical_align_bottom = col_def->vertical_align_bottom;
+  lm_column_def.wrap_text = col_def->wrap_text;
+  if (col_def->wrap_text)
+  if (lmp->max_lines_in_cell == 1) lmp->max_lines_in_cell = 5;
+  lm_column_def.auto_tab = col_def->auto_tab;
+
+  obj->v.column = column_data;
+  column_data->sort_number = col_def->sort_number;
+  xi_add_to_parent_list(obj, lm_column_def.position);
+  lm_create_column( obj->parent->v.list->lm, &lm_column_def,
+    (BOOLEAN)!creating_list, TRUE);
+  xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0),
+    NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20056", 20056,
+    "xi_create: Columns cannot have children");
+  if (list_data->width == 0 && list_data->sb_win)
+    xi_move_list_scroll_bar( obj->parent);
+}
+
+/* ------------------------------------------------------------------------ */
+/*  list_data_create                                                        */
+/* ------------------------------------------------------------------------ */
+static void list_data_create( XI_LIST_DEF* list_def, XI_OBJ* list )
+{
+  XI_LIST_DATA * list_data;
+
+  list_data = (XI_LIST_DATA *)xi_tree_malloc( sizeof(XI_LIST_DATA),
+      (char *)list);
+  list->v.list = list_data;
+  list_data->xi_pnt = list_def->xi_pnt;
+  list_data->height = list_def->height;
+  list_data->one_row_list = list_def->one_row_list;
+  list_data->start_percent = list_def->start_percent;
+  list_data->horz_sync_list = list_def->horz_sync_list;
+  list_data->vert_sync_list = list_def->vert_sync_list;
+  list_data->row_focus_border = list_def->row_focus_border;
+  list_data->row_focus_border_color = list_def->row_focus_border_color;
+  list_data->max_lines_in_cell = list_def->max_lines_in_cell;
+  list_data->single_select = list_def->single_select;
+
+  list_data->font = (FONT_OBJ *)xi_tree_malloc( sizeof(FONT_OBJ),
+      list_data);
+  if (list_def->font || list_def->font_id)
+  {
+  if (list_def->font_id)
+    *list_data->font = xi_create_copy_font_id( list->itf, list_def->font_id, 0);
+  }
+  else if (list->itf->v.itf->font)
+  {
+  *list_data->font = *list->itf->v.itf->font;
+  }
+  else
+  *list_data->font = xi_sysfont;
+}
+
+/* ------------------------------------------------------------------------ */
+/*  list_module_def_create                                                  */
+/* ------------------------------------------------------------------------ */
+static void list_module_def_create( LM_DEF* lm_def, XI_LIST_DEF* list_def,
+                                    XI_OBJ* list )
+{
+  /* create LM */
+  XI_LIST_DATA* list_data = list->v.list;
+
+  MEMCLEAR(*lm_def);
+  lm_def->cid = list->cid;
+  lm_def->pnt = list_def->xi_pnt;
+  if (xi_get_xil_pref((XI_OBJ*) list->parent))
+    lm_def->pixel_height = list_def->height;
+  else
+  {
+    if (list_def->pixel_origin.h || list_def->pixel_origin.v )
+      lm_def->pnt = list_def->pixel_origin;
+    else
+    {
+      lm_def->pnt = list_def->xi_pnt;
+      xi_fu_to_pu(list->itf, &lm_def->pnt, 1);
+    }
+    if (list_def->pixel_height)
+      lm_def->pixel_height = list_def->pixel_height;
+    else
+      lm_def->pixel_height = list_def->height * xi_get_fu_height( list->itf )
+                          / XI_FU_MULTIPLE;
+  }
+  lm_def->pix_char_width = xi_get_fu_width( list->itf );
+  lm_def->attrib = list_def->attrib;
+  lm_def->back_color = list_def->back_color;
+  lm_def->enabled_color = list_def->enabled_color;
+  lm_def->disabled_color = list_def->disabled_color;
+  lm_def->disabled_back_color = list_def->disabled_back_color;
+  lm_def->active_color = list_def->active_color;
+  lm_def->active_back_color = list_def->active_back_color;
+  lm_def->white_space_color = list_def->white_space_color;
+  if (! lm_def->white_space_color)
+    lm_def->white_space_color = COLOR_LTGRAY;
+  lm_def->rule_color = list_def->rule_color;
+  if (! lm_def->rule_color )
+    lm_def->rule_color = COLOR_BLACK;
+  lm_def->lm_cb = xi_lm_cb;
+  if (list_data->font)
+    lm_def->font = list_data->font;
+  else if ( list->itf->v.itf->font)
+    lm_def->font = list->itf->v.itf->font;
+  else
+    lm_def->font = &xi_sysfont;
+  lm_def->no_heading = list_def->no_heading;
+  lm_def->one_row_list = list_def->one_row_list;
+  lm_def->sizable_columns = list_def->sizable_columns;
+  lm_def->movable_columns = list_def->movable_columns;
+  lm_def->fixed_columns = list_def->fixed_columns;
+#if XI_IS_CH
+  CTOS_IS_CH;
+  lm_def->min_cell_height = 8;
+  lm_def->min_heading_height = list_def->min_heading_height;
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  lm_def->min_cell_height = list_def->min_cell_height;
+  lm_def->min_heading_height = list_def->min_heading_height;
+  CTOS_END;
+#endif
+  lm_def->no_horz_lines      = list_def->no_horz_lines;
+  lm_def->no_vert_lines      = list_def->no_vert_lines;
+  lm_def->first_vis_column   = list_def->first_vis_column;
+  lm_def->drop_and_delete    = list_def->drop_and_delete;
+  lm_def->select_cells       = list_def->select_cells;
+  lm_def->get_all_records    = list_def->get_all_records;
+  lm_def->keep_all_records   = list_def->keep_all_records;
+  lm_def->resize_with_window = list_def->resize_with_window;
+  lm_def->horz_sync_list     = list_def->horz_sync_list;
+  lm_def->vert_sync_list     = list_def->vert_sync_list;
+  lm_def->row_focus_border   = list_def->row_focus_border;
+  lm_def->row_focus_border_color = list_def->row_focus_border_color;
+  lm_def->single_select = list_def->single_select;
+  lm_def->retain_back_color_on_select = list_def->retain_back_color_on_select;
+  if (xi_get_xil_pref((XI_OBJ*) list->parent))
+    lm_def->pixel_width = list_def->width;
+  else
+  {
+    if (list_def->pixel_width)
+    lm_def->pixel_width = list_def->pixel_width;
+    else
+    {
+      PNT  p;
+      p.h = list_def->width;
+      p.v = 0;
+      xi_fu_to_pu(list->itf, &p, 1);
+      lm_def->pixel_width = p.h;
+    }
+    lm_def->max_lines_in_cell = list_def->max_lines_in_cell;
+  }
+}
+
+/* ------------------------------------------------------------------------ */
+/*  lm_get_width                                                            */
+/* ------------------------------------------------------------------------ */
+static int lm_get_width( XI_OBJ_DEF* obj_def, int fu_width, int columns )
+{
+  XI_LIST_DEF*  list_def = obj_def->v.list;
+  int           i;
+  int           number_fixed_columns;
+  int           fixed_column_width;
+  int           max_movable_column;
+  int           movable_column_width;
+  int           total_columns;
+  int           width;
+  XI_OBJ_DEF**  column;
+
+    /* calculate all pixel widths */
+  column = obj_def->children;
+  total_columns = obj_def->nbr_children;
+
+    /* If it is an empty list, just return */
+  if (total_columns <= 0) return 0;
+
+  for ( i = 0; i < total_columns; ++column, ++i )
+  {
+    XI_COLUMN_DEF* col = (*column)->v.column;
+    if (!col->pixel_width)
+    {
+        if (xi_get_xil_pref((XI_OBJ*) obj_def->parent))
+          col->pixel_width = col->width * fu_width;
+        else
+          col->pixel_width = col->width * fu_width / XI_FU_MULTIPLE;
+    }
+  }
+  /* find sum of fixed column widths */
+  number_fixed_columns = min( list_def->fixed_columns, total_columns);
+  column = obj_def->children;
+  fixed_column_width = 0;
+  for ( i = 0; i < number_fixed_columns; ++column, ++i )
+    fixed_column_width += (*column)->v.column->pixel_width;
+  /* add the internal rule widths to the fixed columns */
+  if (number_fixed_columns > 1)
+    fixed_column_width += (number_fixed_columns - 1) * lm_get_col_spacing();
+  /* find largest moveable column width, and sum of movable column widths */
+  max_movable_column = 0;
+  movable_column_width = 0;
+  if (columns <= number_fixed_columns)
+  {
+    columns = number_fixed_columns;
+    /* if we have any movable columns, columns must be at least */
+    /* # fixed_columns + 1                                       */
+    if ( total_columns > number_fixed_columns )
+      columns++;
+  }
+  for (; i < columns; ++column, ++i)
+  {
+    XI_COLUMN_DEF* col = (*column)->v.column;
+
+    movable_column_width += col->pixel_width;
+    max_movable_column = max( max_movable_column, col->pixel_width);
+  }
+  for (; i < total_columns; ++column, ++i )
+    max_movable_column = max( max_movable_column,
+                              (*column)->v.column->pixel_width);
+  /* add the internal column rules for movable columns */
+  if (columns > number_fixed_columns + 1)
+    movable_column_width += (columns - number_fixed_columns - 1)
+                            * lm_get_col_spacing();
+  /* use either the sum of the movable columns, or the largest movable column */
+  movable_column_width = max( movable_column_width, max_movable_column );
+  /* calculate width */
+  width = 2 * BORDER_WIDTH + fixed_column_width + movable_column_width;
+  /* add the rule between fixed & movable columns */
+  if (columns > number_fixed_columns && number_fixed_columns > 0)
+    width += lm_get_col_spacing();
+  return width;
+}
+
+/* ------------------------------------------------------------------------ */
+/*  xi_list_def_get_client_width                                            */
+/* ------------------------------------------------------------------------ */
+int xi_list_def_get_client_width( XI_OBJ_DEF* obj_def, int columns )
+{
+  FONT_OBJ* font;
+
+  font = xi_def_get_font( obj_def );
+  return lm_get_width( obj_def, xi_get_fu_width_font( font ), columns );
+}
+
+/* ------------------------------------------------------------------------ */
+/*  xi_list_def_get_outer_width                                             */
+/* ------------------------------------------------------------------------ */
+int xi_list_def_get_outer_width( XI_OBJ_DEF* obj_def, int columns )
+{
+  int result;
+
+  result = xi_list_def_get_client_width( obj_def, columns );
+  if (obj_def->v.list->scroll_bar)
+    result += (int)xi_get_pref(XI_PREF_SB_OFFSET)
+              + (int)xi_get_pref(XI_PREF_SB_WIDTH);
+#ifdef XI_IS_CH
+  return result;
+#else
+  return result + 2 * BORDER_WIDTH;
+#endif
+}
+
+#if XIWS == PMWS
+/* This function is required to fix a scrolling problem on PM. */
+PFNWP oldProc = NULL;
+
+MRESULT EXPENTRY win_sub_proc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
+{
+  switch( msg )
+  {
+  case WM_HSCROLL:
+  case WM_VSCROLL:
+  {
+    if( SHORT2FROMMP( mp2 ) == SB_ENDSCROLL )
+    {
+      WinSetFocus( HWND_DESKTOP, hwnd );
+      return( (MRESULT)0 );
+    }
+  }
+    break;
+  }
+
+  return( oldProc( hwnd, msg, mp1, mp2 ) );
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+/*  list_create                                                             */
+/* ------------------------------------------------------------------------ */
+static void list_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ * list )
+{
+  XI_LIST_DEF*  list_def = xi_obj_def->v.list;
+  XI_LIST_DATA* list_data;
+  LM_DEF        lm_def;
+  int           i, min_height;
+  RCT           rct, min_rct;
+  WINDOW        itf_win;
+  BOOLEAN       save_or;
+  BOOLEAN       use_wrap = TRUE;
+
+  itf_win = list->itf->v.itf->xvt_win;
+  list_data_create( list_def, list );
+  list_data = list->v.list;
+  list_module_def_create( &lm_def, list_def, list );
+  if (lm_def.pixel_width)
+  {
+  int min_width;
+
+  min_width = lm_get_width( xi_obj_def, lm_def.pix_char_width, 1 );
+  /* insure minimum size */
+  if ( min_width > lm_def.pixel_width )
+    lm_def.pixel_width = min_width;
+  }
+  if ( list_def->resize_with_window && list->parent
+    && list->parent->itf->v.itf->xvt_win)
+  {
+  RCT cr;
+
+  xvt_vobj_get_client_rect( list->parent->itf->v.itf->xvt_win, &cr);
+
+  save_or = xi_obj_def->v.list->one_row_list;
+  xi_obj_def->v.list->one_row_list = TRUE;
+  xi_get_def_rect(xi_obj_def, &min_rct);
+  xi_obj_def->v.list->one_row_list = save_or;
+  min_height = min_rct.bottom - min_rct.top;
+
+  lm_def.pixel_height = cr.bottom - lm_def.pnt.v;
+  if (lm_def.pixel_width)
+    lm_def.pixel_height -= (int)xi_get_pref(XI_PREF_SB_HEIGHT);
+  lm_def.pixel_height = max(lm_def.pixel_height, min_height);
+
+  if (lm_def.pixel_width)
+  {
+    int idx, min_width, max_hs;
+    XI_OBJ_DEF *col_def;
+    RCT col_rct;
+
+    min_width = 0;
+    if (xi_obj_def->nbr_children > 0 )
+      {
+      for (idx = 0; idx < xi_obj_def->v.list->fixed_columns; ++idx)
+      {
+      col_def = xi_obj_def->children[idx];
+      xi_get_def_rect(col_def, &col_rct);
+      min_width += (col_rct.right - col_rct.left);
+      }
+      max_hs = 0;
+      for ( idx = xi_obj_def->v.list->fixed_columns;
+          idx < xi_obj_def->nbr_children; ++idx)
+      {
+      col_def = xi_obj_def->children[idx];
+      xi_get_def_rect(col_def, &col_rct);
+      if (!col_def->v.column->wrap_text) use_wrap = FALSE;
+      max_hs = max(max_hs, (col_rct.right - col_rct.left));
+      }
+      min_width += max_hs;
+    }
+    lm_def.pixel_width = cr.right - lm_def.pnt.h - 2 * BORDER_WIDTH;
+    if (list_def->scroll_bar)
+      lm_def.pixel_width -= (int)xi_get_pref(XI_PREF_SB_WIDTH);
+    lm_def.pixel_width = max( lm_def.pixel_width, min_width );
+  }
+  }
+
+  lm_def.list_obj = list;
+  lm_def.itf_obj = list->itf;
+  lm_def.parent = (char *)list_data;
+  list_data->width = lm_def.pixel_width;
+
+  if (!use_wrap) xi_set_pref(XI_PREF_DEFAULT_MAX_LINES_IN_CELL, 1);
+  /*
+TODO calculate and set realized_rows_array_len
+TODO also set nbr_rows, if user specified a specific nbr of rows.
+*/
+
+  list_data->lm = lm_create( itf_win, &lm_def, list_data);
+  list_data->scroll_bar_button = list_def->scroll_bar_button;
+  /*
+  *   Initialize focus obj data. Use list object for defaults.
+  */
+  list_data->focus_cell_array[0] = *list;
+  list_data->focus_cell_array[0].parent = list;
+  list_data->focus_cell_array[0].type = XIT_CELL;
+  list_data->focus_cell_array[0].v.cell.row =
+    list_data->focus_cell_array[0].v.cell.column = 0;
+  list_data->focus_cell_array[0].v.cell.is_vert_scrolled = FALSE;
+  for (i = 1; i < FOCUS_CELL_ARRAY_LEN; ++i)
+  list_data->focus_cell_array[i] =
+      list_data->focus_cell_array[0];
+  list_data->focus_cell = &list_data->focus_cell_array[0];
+  list_data->tab_cid = list_def->tab_cid;
+  list_data->scroll_bar = list_def->scroll_bar;
+
+  xi_add_to_parent_list(list, -1);
+  create_children( xi_obj_def, list, TRUE );
+  if (list_def->scroll_bar)
+  {
+  if (list_data->sb_win)
+    xi_move_list_scroll_bar(list);
+  else
+  {
+    RCT rct;
+    long attrib;
+
+    attrib = lm_get_attrib(list_data->lm, LM_LIST, 0, 0, FALSE);
+    xi_get_sb_rect(list, &rct);
+      list_data->sb_win = xi_new_control(&rct, "", WC_VSCROLL, itf_win,
+          (BOOLEAN)((attrib & XI_ATR_VISIBLE) != 0), list->cid, NULL);
+    xvt_sbar_set_range(list_data->sb_win, HVSCROLL, 0, 100);
+      if (! (attrib & XI_ATR_ENABLED))
+        xvt_vobj_set_enabled(list_data->sb_win, FALSE);
+      xi_get_sb_rect(list, &rct);
+      if (list_data->scroll_bar_button)
+        xi_invalidate_rect(list->itf->v.itf->xvt_win,
+            &list_data->sbb_rct);
+    }
+  }
+  if (lm_def.pixel_width != 0)
+  {
+    unsigned long attrib;
+
+    attrib = lm_get_attrib(list_data->lm, LM_LIST, 0, 0, FALSE);
+    xi_get_hsb_rect( list, &rct);
+    list_data->hsb_win = xi_new_control( &rct, "", WC_HSCROLL, itf_win,
+        (BOOLEAN)((attrib & XI_ATR_VISIBLE) != 0),
+        list->cid + HSCROLL_CID_CONST, NULL);
+  if (! (attrib & XI_ATR_ENABLED))
+      xvt_vobj_set_enabled(list_data->hsb_win, FALSE);
+    lm_set_hscroll_range(list_data->lm);
+  }
+  xi_get_rect( list, &rct);
+  xi_inflate_rect(&rct, 8);
+  xi_invalidate_rect(itf_win, &rct);
+  lm_set_hscroll_range(list->v.list->lm);
+  if (xi_obj_def->v.list->first_vis_column)
+  {
+    xvt_dwin_update(itf_win);
+    xi_hscroll_internal( list, xi_obj_def->v.list->first_vis_column
+        - xi_obj_def->v.list->fixed_columns, 0);
+  }
+#if XIWS == PMWS
+  {
+    HWND hwnd = (HWND)xvt_vobj_get_attr( itf_win, ATTR_NATIVE_WINDOW );
+
+    if( hwnd && (oldProc == NULL))
+      oldProc = WinSubclassWindow( hwnd, win_sub_proc );
+  }
+#endif
+}
+
+
+/* ------------------------------------------------------------------------ */
+/*  xi_create_internal                                                      */
+/* ------------------------------------------------------------------------ */
+static XI_OBJ * xi_create_internal( XI_OBJ * parent, XI_OBJ_DEF* xi_obj_def,
+                                    BOOLEAN creating_list )
+{
+  XI_OBJ * obj;
+
+  if (! inited)
+    xi_init();
+  /* object data initialization common to all types */
+  obj = (XI_OBJ *)xi_tree_malloc(sizeof(XI_OBJ), (char *)parent);
+  obj->parent = parent;
+  obj->cid = xi_obj_def->cid;
+  obj->type = xi_obj_def->type;
+  obj->app_data = xi_obj_def->app_data;
+  obj->app_data2 = xi_obj_def->app_data2;
+
+  if (xi_obj_def->type != XIT_ITF)
+  {
+    RCT rct;
+    XI_ITF_DATA *itf_data;
+
+    obj->itf = parent->itf;
+    xi_get_def_rect(xi_obj_def, &rct);
+    xi_pu_to_fu(NULL, (XI_PNT *)&rct, 2);
+    itf_data = obj->itf->v.itf;
+    itf_data->max_xi_pnt.h = max(itf_data->max_xi_pnt.h, rct.right);
+    itf_data->max_xi_pnt.v = max(itf_data->max_xi_pnt.v, rct.bottom);
+  }
+  else
+    obj->itf = obj;
+
+  switch (xi_obj_def->type)
+  {
+  case XIT_ITF:
+    interface_create( xi_obj_def, obj );
+    break;
+  case XIT_CONTAINER:
+    container_create( xi_obj_def, obj );
+    break;
+  case XIT_RECT:
+    rectangle_create( xi_obj_def, obj );
+    break;
+  case XIT_LINE:
+    line_create( xi_obj_def, obj );
+    break;
+  case XIT_BTN:
+    button_create( xi_obj_def, obj );
+    break;
+  case XIT_FORM:
+    form_create( xi_obj_def, obj );
+    break;
+  case XIT_FIELD:
+    field_create( xi_obj_def, obj );
+    break;
+  case XIT_LIST:
+    list_create( xi_obj_def, obj );
+    break;
+  case XIT_COLUMN:
+    column_create( xi_obj_def, obj, creating_list );
+    break;
+  case XIT_TEXT:
+  text_create( xi_obj_def, obj );
+  break;
+  case XIT_GROUP:
+    group_create( xi_obj_def, obj, creating_list );
+    break;
+  case XIT_CELL:
+  case XIT_ROW:
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20016",
+    20016, "xi_create: Invalid XI_OBJ_TYPE");   
+  }
+  return obj;
+}
+
+/* ------------------------------------------------------------------------ */
+/*  xi_create                                                               */
+/* ------------------------------------------------------------------------ */
+/*
+  xi_create performs the following steps:
+
+  1. Copy the *_DEFs into *_DATAs
+  2. Call creation functions for LM, STX, buttons
+  3. Initialize event routing
+*/
+XI_OBJ * xi_create(XI_OBJ *parent, XI_OBJ_DEF *xi_obj_def)
+{
+  return xi_create_internal( parent, xi_obj_def, FALSE );
+}
+
+void
+xi_close_window_internal(XI_OBJ *itf)
+{
+  XI_ITF_DATA *itf_data = itf->v.itf;
+  if (itf_data->modal)
+  {
+  if (itf_data->xvt_win != xi_modal_win)
+  {   /* Modal closing, but not on top */
+    XI_OBJ *temp_itf;
+    WINDOW curWin = xi_modal_win;
+    do
+    {
+      temp_itf = xi_get_itf(curWin);
+      curWin = temp_itf->v.itf->prev_modal;
+    } while (curWin != itf_data->xvt_win);
+    temp_itf->v.itf->prev_modal = itf_data->prev_modal;
+  } else
+  {
+    xi_modal_win = itf_data->prev_modal;
+    if (xi_modal_win == NULL_WIN)
+    {
+#if (XIWS == WINWS) || (XIWS == PMWS)
+      xvt_vobj_set_enabled(TASK_WIN, TRUE);
+#endif
+#if (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS)
+      {
+      SLIST win_list = xvt_scr_list_wins();
+      SLIST_ELT elt;
+
+      for (elt = xvt_slist_get_first(win_list); elt != NULL;
+          elt = xvt_slist_get_next(win_list, elt))
+        xvt_vobj_set_enabled((WINDOW)*xvt_slist_get_data(elt), TRUE);
+      xvt_slist_destroy(win_list);
+      }
+#endif
+    } else
+    {
+#if (XIWS == WINWS) || (XIWS == PMWS)
+      xvt_vobj_set_enabled(xi_modal_win, TRUE);
+#if XIWS == PMWS
+      xvt_scr_set_focus_vobj(xi_modal_win);
+      xvt_vobj_raise(xi_modal_win);
+#endif
+#endif
+#if (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS)
+      xvt_vobj_set_enabled(xi_modal_win, TRUE);
+      xvt_scr_set_focus_vobj(xi_modal_win);
+      xvt_vobj_raise(xi_modal_win);          
+#endif
+    }
+  }
+  }
+  xvt_vobj_destroy(itf_data->xvt_win);
+}
+
+static void near
+xi_delete_internal(XI_OBJ *xi_obj, BOOLEAN recursive)
+{
+  RCT         rct;
+  XI_OBJ_TYPE type = xi_obj->type;
+
+  if (xi_obj->itf->v.itf->focus_obj == xi_obj)
+    xi_obj->itf->v.itf->focus_obj = NULL;
+
+  switch(type)
+  {
+  case XIT_FIELD:
+    xi_get_rect(xi_obj, &rct);
+    xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct);
+    stx_delete(xi_obj->v.field->stx);
+    break;
+  case XIT_FORM:
+  case XIT_CONTAINER:
+    {
+      XI_OBJ * *objlist;
+      int n;
+
+      /* loop over sub-objects */
+      if (!recursive)
+      {
+        objlist = xi_get_member_list(xi_obj, &n);
+        for (; n > 0; n--, objlist++)
+          xi_delete_internal(*objlist, TRUE);
+        break;
+      }
+    }
+  case XIT_GROUP:
+    break;
+  case XIT_ITF:
+    {
+      XI_ITF_DATA *itf_data;
+
+      itf_data = xi_obj->v.itf;
+      if (itf_data->in_callback)
+        itf_data->closing = TRUE;
+      else
+        xi_close_window_internal(xi_obj);
+      return;
+    }
+  case XIT_LIST:
+    {
+      XI_LIST_DATA *list_data;
+
+      list_data = xi_obj->v.list;
+      xi_get_rect(xi_obj, &rct);
+      if (list_data->scroll_bar)
+        xvt_vobj_destroy(list_data->sb_win);
+      if (list_data->hsb_win)
+        xvt_vobj_destroy(list_data->hsb_win);
+      xi_inflate_rect(&rct, 8);
+      xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct);
+      if (!recursive)
+        lm_delete(list_data->lm);
+      break;
+    }
+  case XIT_COLUMN:
+    {
+      XI_LIST_DATA *list_data;
+      int col_nbr;
+      BOOLEAN move_hsb;
+
+      list_data = xi_obj->parent->v.list;
+      col_nbr = xi_obj_to_idx(xi_obj);
+      move_hsb = (col_nbr < ((LM_DATA *)(list_data->lm))->fixed_columns);
+      if (!recursive)
+        lm_delete_column(list_data->lm, col_nbr, TRUE);
+      if (list_data->scroll_bar && (! list_data->width))
+        xi_move_list_scroll_bar(xi_obj->parent);
+      if (! recursive)
+      {
+        if (list_data->hsb_win && move_hsb)
+        {
+          list_data->have_hsb_rct = FALSE;
+          xi_move_list_hscroll_bar(xi_obj->parent);
+        }
+      }
+      break;
+    }
+  case XIT_TEXT:
+  case XIT_RECT:
+  case XIT_LINE:
+    xi_get_rect(xi_obj, &rct);
+    xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct);
+    break;
+  case XIT_BTN:
+    if (xi_obj->v.btn->btnctl)
+      xvt_vobj_destroy(xi_obj->v.btn->btnctl);
+    else
+    {
+      xi_get_rect(xi_obj, &rct);
+      xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct);
+    }
+    break;
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4,"20017", 20017,
+      "Invalid XI object passed to xi_delete");
+    break;
+  }
+  if (!recursive)
+  {
+    xi_remove_from_parent_list(xi_obj);
+    if (type == XIT_COLUMN)             /* an ugly hack */
+    {
+      XI_LIST_DATA *list_data;
+
+      list_data = xi_obj->parent->v.list;
+      lm_make_rrr_room_pix( (LM_DATA*) list_data->lm, 0, FALSE );
+    }
+    xi_tree_free((char *)xi_obj);
+  }
+}
+
+void
+xi_delete(XI_OBJ *xi_obj)
+{
+  xi_delete_internal(xi_obj, FALSE);
+}
+
+void
+xi_move_column_internal(XI_OBJ *column, int position, BOOLEAN in_hscrolling)
+{
+  XI_OBJ *list;
+  XI_LIST_DATA *list_data;
+  LM_DATA *lm_data;
+  LM_COLUMN_DATA *col_data;
+  LM_COLUMN_DEF lm_column_def;
+  int col_nbr, i;
+  FONT_OBJ *font;
+  BOOLEAN move_hsb = FALSE;
+  int focus_row, focus_column;
+  BOOLEAN v_scrolled;
+  BOOLEAN redraw_row = FALSE;
+
+  list = column->parent;
+  list_data = list->v.list;
+  lm_data = (LM_DATA *)list_data->lm;
+
+  i = xi_obj_to_idx(column);
+  lm_get_focus_cell(lm_data, &focus_row, &focus_column, &v_scrolled);
+  if (focus_column == i && lm_data->row_focus_border)
+    redraw_row = TRUE;
+  if (list_data->hsb_win)
+    if (i < lm_data->fixed_columns || position < lm_data->fixed_columns)
+      move_hsb = TRUE;
+  if (position == lm_data->fixed_columns && ! in_hscrolling)
+    move_hsb = TRUE;
+
+  col_nbr = xi_obj_to_idx(column);
+  col_data = lm_data->lm_column_data[col_nbr];
+
+  MEMCLEAR(lm_column_def);
+  lm_column_def.attrib = col_data->attrib;
+  lm_column_def.position = position;
+  lm_column_def.pix_width = col_data->pix_width;
+  lm_column_def.text_size = col_data->text_size;
+  lm_column_def.heading_text = (char *)xi_tree_malloc(
+    strlen(col_data->heading_text) + 1, list_data);
+  strcpy(lm_column_def.heading_text, col_data->heading_text);
+  lm_column_def.center_heading = col_data->center_heading;
+#if XVTWS != WMWS
+  lm_column_def.heading_well = col_data->heading_well;
+  lm_column_def.heading_platform = col_data->heading_platform;
+  lm_column_def.column_well = col_data->column_well;
+  lm_column_def.column_platform = col_data->column_platform;
+#else
+  lm_column_def.heading_well = FALSE;
+  lm_column_def.heading_platform = FALSE;
+  lm_column_def.column_well = FALSE;
+  lm_column_def.column_platform = FALSE;
+#endif
+  lm_column_def.icon_rid = col_data->icon_rid;
+  lm_column_def.icon_x = col_data->icon_x;
+  lm_column_def.icon_y = col_data->icon_y;
+  lm_column_def.vertical_align_center = col_data->vertical_align_center;
+  lm_column_def.vertical_align_bottom = col_data->vertical_align_bottom;
+  lm_column_def.wrap_text = col_data->wrap_text;
+  lm_column_def.auto_tab = col_data->auto_tab;
+  if (col_data->font)
+  {
+    font = (FONT_OBJ*)xi_tree_malloc(sizeof(FONT_OBJ), NULL);
+    lm_column_def.font = font;
+    *lm_column_def.font = *col_data->font;
+  }
+
+  lm_delete_column((LM)lm_data, col_nbr, FALSE);
+
+  xi_remove_from_parent_list(column);
+  xi_add_to_parent_list(column, lm_column_def.position);
+
+  lm_create_column((LM)lm_data, &lm_column_def, TRUE, in_hscrolling);
+
+  if (move_hsb)
+  {
+    list->v.list->have_hsb_rct = FALSE;
+    xi_move_list_hscroll_bar(column->parent);
+  }
+  lm_set_hscroll_range((LM)lm_data);
+  if (redraw_row)
+    lm_redraw_row(lm_data, focus_row, FALSE);
+}
+
+void
+xi_move_column(XI_OBJ *column, int position)
+{
+  XI_OBJ *list;
+  XI_LIST_DATA *list_data;
+  LM_DATA *lm_data;
+  int current_pos;
+
+  list = column->parent;
+  list_data = list->v.list;
+  lm_data = (LM_DATA *)list_data->lm;
+  current_pos = xi_obj_to_idx(column);
+  xi_move_column_internal(column, position,
+    (BOOLEAN)(current_pos >= lm_data->fixed_columns));
+}
+
+BOOLEAN
+xi_is_auto_tab( XI_OBJ *xi_obj )
+{
+  if ( xi_obj->type == XIT_FIELD )
+    return ((STX_DATA*)xi_obj->v.field->stx)->auto_tab;
+  if ( xi_obj->type == XIT_COLUMN )
+    return LMP(xi_obj->parent->v.list->lm)->
+          lm_column_data[xi_obj_to_idx(xi_obj)]->auto_tab;
+  return FALSE;
+}
+
+void 
+xi_init(void)
+{
+  if (! inited)
+  {
+    inited = TRUE;
+    xi_init_sysvals();
+  }
+}
+
+
+
+
+
diff --git a/xi/xi_int.h b/xi/xi_int.h
new file mode 100755
index 000000000..346fd6f5a
--- /dev/null
+++ b/xi/xi_int.h
@@ -0,0 +1,22 @@
+#ifndef INCL_XI_INT
+#define INCL_XI_INT
+
+int         xi_scroll_internal( XI_OBJ *xi_obj, int nbr_lines, int percent,
+                                BOOLEAN same_cell );
+void        realloc_ptrs(void * * *ptrs, int nbr_ptrs, void *parent);
+BOOLEAN     xi_move_focus_internal( XI_OBJ *xi_obj, BOOLEAN make_callbacks,
+                                    BOOLEAN next_if_disabled,
+                                    int check_for_reenabled);
+XI_OBJ*     xi_search_itf( XI_OBJ *xi_obj, XI_SEARCH_TYPE search_type,
+                          int parm1);
+XI_OBJ *    xi_find_next_obj( XI_OBJ *focus_obj, XI_NEXT_TYPE tab_type, long c);
+void        xi_remove_window_from_list(WINDOW win);
+void        xi_clear_lasts(void);
+void        xi_close_window_internal(XI_OBJ *itf);
+BOOLEAN     call_cb(XI_OBJ *itf, XI_EVENT *xiev);
+void        xi_hscroll_internal(XI_OBJ *xi_obj, int nbr_lines, int pos);
+void        XVT_CALLCONV1 xi_hscroll XVT_CC_ARGS((XI_OBJ *xi_obj,
+                                    int nbr_columns));
+
+#endif
+
diff --git a/xi/xicf.c b/xi/xicf.c
new file mode 100755
index 000000000..8cb3b0535
--- /dev/null
+++ b/xi/xicf.c
@@ -0,0 +1,1151 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#define XI_INTERNAL
+#include "xi.h"
+#include "xiutils.h"
+#include "xitext.h"
+#include "xistx.h"
+#include "xitext.h"
+#include "xilm.h"
+
+/* ERROR CODES 20101-20112 */
+
+void realloc_ptrs(void * * *ptrs, int nbr_ptrs, void *parent);
+
+#define XI_PTR_INC 10
+
+/*
+  realloc_ptrs: reallocate an array of pointers by adding one to
+  the current number of pointers.  This function will attempt to
+  reallocate by blocks to improve performance.
+*/
+void
+realloc_ptrs(void * * *ptrs, int nbr_ptrs, void *parent)
+{
+  int cur_nbr_alloc;
+  int nbr_alloc;
+
+  cur_nbr_alloc = ((nbr_ptrs - 1) / XI_PTR_INC + 1) * XI_PTR_INC;
+  nbr_alloc = (nbr_ptrs / XI_PTR_INC + 1) * XI_PTR_INC;
+
+  if (*ptrs == NULL)
+  {
+    *ptrs = (void * *)
+        xi_tree_malloc(sizeof(void *) * nbr_alloc, parent);
+  }
+  else
+  {
+    if (cur_nbr_alloc != nbr_alloc)
+    {
+      *ptrs = (void * *)
+          xi_tree_realloc(*ptrs, sizeof(void *) * nbr_alloc);
+    }
+  }
+}
+
+XI_OBJ_DEF *
+xi_create_itf_def(int cid, XI_EVENT_HANDLER xi_eh, RCT *rctp, char *title,
+long app_data)
+{
+  XI_OBJ_DEF *itf;
+  XI_ITF_DEF *xi_id;
+
+  itf = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), NULL);
+  itf->type = XIT_ITF;
+  itf->cid = cid;
+  itf->v.itf = xi_id = (XI_ITF_DEF *)xi_tree_malloc(sizeof(XI_ITF_DEF), itf);
+  itf->app_data = app_data;
+  xi_id->xi_eh = xi_eh;
+  itf->v.itf->use_xil_win = FALSE;
+  if (rctp)
+  {
+    xi_id->rctp = (RCT *)xi_tree_malloc(sizeof(XI_RCT), itf->v.itf);
+    *(xi_id->rctp) = *rctp;
+  }
+  else
+    xi_id->rctp = NULL;
+  xi_id->title = title;
+  xi_id->ctl_close = TRUE;
+  xi_id->ctl_iconized = FALSE;
+  xi_id->ctl_iconizable = FALSE;
+  itf->nbr_children = 0;
+  itf->children = NULL;
+  return itf;
+}
+
+XI_OBJ_DEF *
+xi_add_form_def(XI_OBJ_DEF *itf, int cid, int tab_cid)
+{
+  XI_OBJ_DEF *form;
+  XI_FORM_DEF *xi_fd;
+
+  form = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), itf);
+  form->type = XIT_FORM;
+  form->cid = cid;
+  form->parent = itf;
+  form->nbr_children = 0;
+  form->children = NULL;
+  form->v.form = xi_fd = (XI_FORM_DEF *)xi_tree_malloc(sizeof(XI_FORM_DEF), form);
+  xi_fd->tab_cid = tab_cid;
+  if (itf != NULL)
+  {
+  xvt_errmsg_sig_if(!(itf->type == XIT_ITF), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20101", 20101,
+      "Invalid interface passed to xi_add_form_def");
+    realloc_ptrs((void * * *)&itf->children, itf->nbr_children, itf);
+    itf->children[itf->nbr_children] = form;
+    itf->nbr_children++;
+  }
+  return form;
+}
+
+XI_OBJ_DEF *
+xi_add_line_def(XI_OBJ_DEF *itf, int cid, XI_PNT *pnt1,
+XI_PNT *pnt2, unsigned long attrib, COLOR fore_color,
+COLOR back_color, BOOLEAN well)
+{
+  XI_OBJ_DEF *line_obj;
+  XI_LINE_DEF *xi_ld;
+
+  line_obj = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), itf);
+  line_obj->type = XIT_LINE;
+  line_obj->cid = cid;
+  line_obj->parent = itf;
+  line_obj->v.line = xi_ld = (XI_LINE_DEF *)xi_tree_malloc(sizeof(XI_LINE_DEF), line_obj);
+  xi_ld->pnt1 = *pnt1;
+  xi_ld->pnt2 = *pnt2;
+  xi_ld->fore_color = fore_color;
+  xi_ld->back_color = back_color;
+  xi_ld->well = well;
+  xi_ld->attrib = attrib;
+  if (itf != NULL)
+  {
+  xvt_errmsg_sig_if(!(itf->type == XIT_ITF), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20108", 20108,
+      "Invalid interface passed to xi_add_line_def");
+  realloc_ptrs((void * * *)&itf->children, itf->nbr_children, itf);
+  itf->children[itf->nbr_children] = line_obj;
+  itf->nbr_children++;
+  }
+  return line_obj;
+}
+
+XI_OBJ_DEF *
+xi_add_list_def(XI_OBJ_DEF *itf, int cid, int v, int h,
+int height, unsigned long attrib, COLOR enabled_color, COLOR back_color,
+COLOR disabled_color, COLOR disabled_back_color, COLOR active_color,
+int tab_cid)
+{
+  XI_OBJ_DEF *list;
+  XI_LIST_DEF *xi_ld;
+
+  list = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), itf);
+  list->type = XIT_LIST;
+  list->cid = cid;
+  list->parent = itf;
+  list->nbr_children = 0;
+  list->children = NULL;
+  list->v.list = xi_ld = (XI_LIST_DEF *)xi_tree_malloc(sizeof(XI_LIST_DEF), list);
+  xi_ld->xi_pnt.v = v;
+  xi_ld->xi_pnt.h = h;
+  xi_ld->height = height;
+  xi_ld->attrib = attrib;
+  xi_ld->enabled_color = enabled_color;
+  xi_ld->back_color = back_color;
+  xi_ld->disabled_color = disabled_color;
+  xi_ld->disabled_back_color = disabled_back_color;
+  xi_ld->active_color = active_color;
+  xi_ld->active_back_color = back_color;
+  xi_ld->tab_cid = tab_cid;
+  if (itf != NULL)
+  {
+  xvt_errmsg_sig_if(!(itf->type == XIT_ITF), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20102", 20102,
+      "Invalid interface passed to xi_add_list_def");
+  realloc_ptrs((void * * *)&itf->children, itf->nbr_children, itf);
+    itf->children[itf->nbr_children] = list;
+    itf->nbr_children++;
+  }
+  return list;
+}
+
+XI_OBJ_DEF *
+xi_add_column_def(XI_OBJ_DEF *list, int cid,
+unsigned long attrib, int sort_number, int width, int text_size,
+char *heading_text)
+{
+  XI_OBJ_DEF *column;
+  XI_COLUMN_DEF *xi_cd;
+
+  column = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), list);
+  column->type = XIT_COLUMN;
+  column->cid = cid;
+  column->parent = list;
+  column->v.column = xi_cd = (XI_COLUMN_DEF *)xi_tree_malloc(sizeof(XI_COLUMN_DEF), column);
+  xi_cd->attrib = attrib;
+  xi_cd->sort_number = sort_number;
+  xi_cd->width = width;
+  xi_cd->text_size = text_size;
+  xi_cd->heading_text = (char *)xi_tree_malloc(strlen(heading_text) + 1, column);
+  strcpy(xi_cd->heading_text, heading_text);
+  if (list != NULL)
+  {
+  xvt_errmsg_sig_if(!(list->type == XIT_LIST), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20103", 20103,
+      "Invalid list passed to xi_add_column_def");
+    realloc_ptrs((void * * *)&list->children, list->nbr_children, list);
+    list->children[list->nbr_children] = column;
+    list->nbr_children++;
+  }
+  return column;
+}
+
+XI_OBJ_DEF *
+xi_add_field_def(XI_OBJ_DEF *form, int cid,
+int v, int h, int field_width, unsigned long attrib,
+int tab_cid, int text_size, COLOR enabled_color,
+COLOR back_color, COLOR disabled_color, COLOR disabled_back_color,
+COLOR active_color)
+{
+  XI_OBJ_DEF *field;
+  XI_FIELD_DEF *xi_fd;
+
+  xvt_errmsg_sig_if(!(text_size > 0), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20112",
+    20112, "Invalid field buffer size");
+  field = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), form);
+  field->type = XIT_FIELD;
+  field->cid = cid;
+  field->parent = form;
+  field->v.field = xi_fd = (XI_FIELD_DEF *)xi_tree_malloc(sizeof(XI_FIELD_DEF), field);
+  xi_fd->pnt.h = h;
+  xi_fd->pnt.v = v;
+  xi_fd->field_width = field_width;
+  xi_fd->attrib = attrib;
+  xi_fd->tab_cid = tab_cid;
+  xi_fd->text_size = text_size;
+  xi_fd->back_color = back_color;
+  xi_fd->enabled_color = enabled_color;
+  xi_fd->disabled_color = disabled_color;
+  xi_fd->disabled_back_color = disabled_back_color;
+  xi_fd->active_color = active_color;
+  xi_fd->active_back_color = back_color;
+  if (form != NULL)
+  {
+  xvt_errmsg_sig_if(!(form->type == XIT_FORM), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20104", 20104,
+      "Invalid form passed to xi_add_field_def");
+    realloc_ptrs((void * * *)&form->children,
+        form->nbr_children, form);
+    form->children[form->nbr_children] = field;
+    form->nbr_children++;
+  }
+  return field;
+}
+
+XI_OBJ_DEF *
+xi_add_container_def(XI_OBJ_DEF *itf, int cid,
+XI_RCT *xi_rct, XI_CONTAINER_ORIENTATION orientation, int tab_cid)
+{
+  XI_OBJ_DEF *container;
+  XI_CONTAINER_DEF *xi_cd;
+
+  container = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), itf);
+  container->type = XIT_CONTAINER;
+  container->cid = cid;
+  container->parent = itf;
+  container->nbr_children = 0;
+  container->children = NULL;
+  container->v.container = xi_cd =
+      (XI_CONTAINER_DEF *)xi_tree_malloc(sizeof(XI_CONTAINER_DEF), container);
+  xi_cd->xi_rct = *xi_rct;
+  xi_cd->orientation = orientation;
+  xi_cd->tab_cid = tab_cid;
+  if (itf != NULL)
+  {
+  xvt_errmsg_sig_if(!(itf->type == XIT_ITF), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20105", 20105,
+      "Invalid interface passed to xi_add_container_def");
+    realloc_ptrs((void * * *)&itf->children, itf->nbr_children, itf);
+    itf->children[itf->nbr_children] = container;
+    itf->nbr_children++;
+  }
+  return container;
+}
+
+XI_OBJ_DEF *
+xi_add_button_def(XI_OBJ_DEF *parent, int cid, XI_RCT *rct,
+unsigned long attrib, char *text, int tab_cid)
+{
+  XI_OBJ_DEF *btn;
+  XI_BTN_DEF *xi_bd;
+
+  btn = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), parent);
+  btn->type = XIT_BTN;
+  btn->cid = cid;
+  btn->parent = parent;
+  btn->v.btn = xi_bd = (XI_BTN_DEF *)xi_tree_malloc(sizeof(XI_BTN_DEF), btn);
+  if (rct != NULL)
+    xi_bd->xi_rct = *rct;
+  xi_bd->attrib = attrib;
+  xi_bd->text = (char *)xi_tree_malloc(strlen(text) + 1, btn);
+  strcpy(xi_bd->text, text);
+  xi_bd->tab_cid = tab_cid;
+  if (parent != NULL)
+  {
+  xvt_errmsg_sig_if(!(parent->type == XIT_ITF || parent->type == XIT_CONTAINER),
+      NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20106", 20106,
+      "Invalid parent passed to xi_add_button_def");
+    realloc_ptrs((void * * *)&parent->children, parent->nbr_children, parent);
+    parent->children[parent->nbr_children] = btn;
+    parent->nbr_children++;
+  }
+  return btn;
+}
+
+XI_OBJ_DEF *
+xi_add_text_def(XI_OBJ_DEF *itf, int cid, XI_RCT *rct,
+unsigned long attrib, char *text)
+{
+  XI_OBJ_DEF *text_obj;
+  XI_TEXT_DEF *xi_td;
+
+  text_obj = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), itf);
+  text_obj->type = XIT_TEXT;
+  text_obj->cid = cid;
+  text_obj->parent = itf;
+  text_obj->v.text = xi_td = (XI_TEXT_DEF *)xi_tree_malloc(sizeof(XI_TEXT_DEF), text_obj);
+  xi_td->xi_rct = *rct;
+  xi_td->attrib = attrib;
+  xi_td->text = (char *)xi_tree_malloc(strlen(text) + 1, text_obj);
+  strcpy(xi_td->text, text);
+  if (itf != NULL)
+  {
+  xvt_errmsg_sig_if(!(itf->type == XIT_ITF), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20107", 20107,
+      "Invalid interface passed to xi_add_text_def");
+    realloc_ptrs((void * * *)&itf->children, itf->nbr_children, itf);
+    itf->children[itf->nbr_children] = text_obj;
+    itf->nbr_children++;
+  }
+  return text_obj;
+}
+
+XI_OBJ_DEF *
+xi_add_rect_def(XI_OBJ_DEF *itf, int cid, XI_RCT *rct,
+unsigned long attrib, COLOR fore_color, COLOR back_color)
+{
+  XI_OBJ_DEF *rect_obj;
+  XI_RECT_DEF *xi_rd;
+
+  rect_obj = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), itf);
+  rect_obj->type = XIT_RECT;
+  rect_obj->cid = cid;
+  rect_obj->parent = itf;
+  rect_obj->v.rect = xi_rd = (XI_RECT_DEF *)xi_tree_malloc(sizeof(XI_RECT_DEF), rect_obj);
+  xi_rd->xi_rct = *rct;
+  xi_rd->fore_color = fore_color;
+  xi_rd->back_color = back_color;
+  xi_rd->attrib = attrib;
+  if (itf != NULL)
+  {
+  xvt_errmsg_sig_if(!(itf->type == XIT_ITF), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20111", 20111,
+      "Invalid interface passed to xi_add_rect_def");
+    realloc_ptrs((void * * *)&itf->children, itf->nbr_children, itf);
+    itf->children[itf->nbr_children] = rect_obj;
+    itf->nbr_children++;
+  }
+  return rect_obj;
+}
+
+XI_OBJ_DEF *
+xi_add_group_def(XI_OBJ_DEF *itf, int cid, int nbr_cids,
+int *cid_list)
+{
+  XI_OBJ_DEF *group;
+  XI_GROUP_DEF *xi_gd;
+
+  group = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), itf);
+  group->type = XIT_GROUP;
+  group->cid = cid;
+  group->parent = itf;
+  group->v.group = xi_gd = (XI_GROUP_DEF *)xi_tree_malloc(sizeof(XI_GROUP_DEF), group);
+  xi_gd->nbr_cids = nbr_cids;
+  xvt_errmsg_sig_if(!(nbr_cids > 0), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20109",
+    20109, "Groups must have at least one member");
+  xi_gd->cids = (int *)xi_tree_malloc(sizeof(int) * nbr_cids, xi_gd);
+  memcpy((char *)xi_gd->cids, (char *)cid_list,
+      (size_t)(sizeof(int) * nbr_cids));
+  if (itf != NULL)
+  {
+  xvt_errmsg_sig_if(!(itf->type == XIT_ITF), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20110", 20110,
+      "Invalid interface passed to xi_add_group_def");
+    realloc_ptrs((void * * *)&itf->children, itf->nbr_children, itf);
+    itf->children[itf->nbr_children] = group;
+    itf->nbr_children++;
+  }
+  return group;
+}
+
+XI_OBJ_DEF * xi_get_column_def( XI_OBJ *column_obj,
+LM_COLUMN_DATA *lmcdp, int index,
+void * parent )
+{
+  XI_OBJ_DEF    *column;
+  XI_COLUMN_DEF *xi_cd;
+
+  column = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), parent );
+  column->type = XIT_COLUMN;
+  column->cid = column_obj->cid;
+  column->app_data = column_obj->app_data;
+  column->v.column = xi_cd = (XI_COLUMN_DEF *) xi_tree_malloc(
+    sizeof(XI_COLUMN_DEF), column);
+  xi_cd->attrib = lmcdp->attrib;
+  xi_cd->sort_number = index * 10;
+  if (xi_get_xil_pref((XI_OBJ*)column_obj->itf))
+  {
+    xi_cd->pixel_width = lmcdp->pix_width;
+    xi_cd->width = lmcdp->width;
+  }
+  else
+  {
+    xi_cd->pixel_width = lmcdp->pix_width;
+    xi_cd->width = lmcdp->width * XI_FU_MULTIPLE;
+  }
+  xi_cd->text_size = lmcdp->text_size;
+  xi_cd->heading_text = (char *)xi_tree_malloc( strlen(
+      lmcdp->heading_text ) + 1, column );
+  strcpy(xi_cd->heading_text, lmcdp->heading_text);
+  xi_cd->center_heading = lmcdp->center_heading;
+  xi_cd->heading_well = lmcdp->heading_well;
+  xi_cd->heading_platform = lmcdp->heading_platform;
+  xi_cd->column_well = lmcdp->column_well;
+  xi_cd->column_platform = lmcdp->column_platform;
+  if (lmcdp->font)
+  {
+  xi_cd->font_id = *lmcdp->font;
+  }
+  xi_cd->icon_rid = lmcdp->icon_rid;
+  xi_cd->icon_x = lmcdp->icon_x;
+  xi_cd->icon_y = lmcdp->icon_y;
+  xi_cd->size_rows = lmcdp->size_rows;
+  xi_cd->suppress_update_heading = lmcdp->suppress_update_heading;
+  xi_cd->suppress_update_cells = lmcdp->suppress_update_cells;
+  xi_cd->vertical_align_center = lmcdp->vertical_align_center;
+  xi_cd->vertical_align_bottom = lmcdp->vertical_align_bottom;
+  xi_cd->wrap_text = lmcdp->wrap_text;
+  xi_cd->auto_tab = lmcdp->auto_tab;
+  return column;
+}
+
+XI_OBJ_DEF *
+xi_get_list_def(XI_OBJ *list_obj)
+{
+  XI_OBJ_DEF *list;
+  XI_LIST_DEF *xi_ld;
+  XI_LIST_DATA *list_data;
+  LM_DATA *lmp;
+  PNT p;
+  int i;
+  int nbr_recs;
+  long *recs;
+
+  list_data = list_obj->v.list;
+  lmp = (LM_DATA *)list_data->lm;
+  list = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), NULL);
+  list->type = XIT_LIST;
+  list->cid = list_obj->cid;
+  list->app_data = list_obj->app_data;
+  list->v.list = xi_ld = (XI_LIST_DEF *)xi_tree_malloc(sizeof(XI_LIST_DEF), list);
+  xi_ld->xi_pnt = list_data->xi_pnt;
+  xi_ld->height = list_data->height;
+  xi_ld->pixel_height = lmp->pixel_height;
+  xi_ld->attrib = lmp->attrib;
+  xi_ld->enabled_color = lmp->enabled_color;
+  xi_ld->back_color = lmp->back_color;
+  xi_ld->disabled_color = lmp->disabled_color;
+  xi_ld->disabled_back_color = lmp->disabled_back_color;
+  xi_ld->active_color = lmp->active_color;
+  xi_ld->active_back_color = lmp->active_back_color;
+  xi_ld->white_space_color = lmp->white_space_color;
+  xi_ld->tab_cid = list_data->tab_cid;
+  xi_ld->no_heading = lmp->no_heading;
+  xi_ld->one_row_list = list_data->one_row_list;
+  xi_ld->scroll_bar = list_data->scroll_bar;
+  xi_ld->sizable_columns = lmp->sizable_columns;
+  xi_ld->movable_columns = lmp->movable_columns;
+  xi_ld->scroll_bar_button = list_data->scroll_bar_button;
+  xi_ld->fixed_columns = lmp->fixed_columns;
+  xi_ld->resize_with_window = lmp->resize_with_window;
+  xi_ld->horz_sync_list = lmp->horz_sync_list;
+  xi_ld->vert_sync_list = lmp->vert_sync_list;
+  xi_ld->row_focus_border = lmp->row_focus_border;
+  xi_ld->row_focus_border_color = lmp->row_focus_border_color;
+  xi_ld->max_lines_in_cell = lmp->max_lines_in_cell;
+  xi_ld->single_select = lmp->single_select;
+  if (xi_get_xil_pref((XI_OBJ*)list_obj->parent))
+    xi_ld->width = lmp->pixel_width;
+  else
+  {
+    p.h = lmp->pixel_width;
+    xi_pu_to_fu(list_obj->itf, &p, 1);
+    xi_ld->width = p.h;
+  }
+  xi_ld->min_cell_height = lmp->min_cell_height;
+  xi_ld->min_heading_height = lmp->min_heading_height;
+  xi_ld->no_horz_lines = lmp->no_horz_lines;
+  xi_ld->no_vert_lines = lmp->no_vert_lines;
+  xi_ld->drop_and_delete = lmp->drop_and_delete;
+  xi_ld->select_cells = lmp->select_cells;
+  xi_ld->get_all_records = lmp->get_all_records;
+  if (lmp->font)
+  {
+    xi_ld->font_id = *lmp->font;
+  }
+
+  recs = lm_get_list_info(list_data->lm, &nbr_recs);
+  if (nbr_recs > 0)
+  {
+  XI_EVENT xiev;
+    XI_OBJ *itf;
+
+    itf = list_obj->itf;
+    MEMCLEAR(xiev);
+    xiev.type = XIE_GET_PERCENT;
+    xiev.v.get_percent.record = recs[0];
+    xiev.v.get_percent.list = list_obj;
+    (*(XI_EH_TYPE)itf->v.itf->xi_eh)(itf, &xiev);
+    xi_ld->start_percent = xiev.v.get_percent.percent;
+  }
+  xi_ld->first_vis_column = lmp->first_vis;
+
+  list->nbr_children = lmp->nbr_columns;
+  realloc_ptrs((void * * *)&list->children, list->nbr_children,
+      list);
+  for (i = 0; i < list->nbr_children; ++i)
+    list->children[i] = xi_get_column_def( list_obj->children[i],
+        lmp->lm_column_data[i], i, list );
+  return list;
+}
+
+XI_OBJ_DEF * xi_get_column_def2( XI_OBJ *column_obj )
+{
+  XI_OBJ       *list_obj;
+  LM_DATA      *lmp;
+  int          i;
+
+  list_obj = column_obj->parent;
+  lmp = (LM_DATA *)list_obj->v.list->lm;
+
+  for (i = 0; i < list_obj->nbr_children; ++i)
+  if (list_obj->children[i] == column_obj)
+    return xi_get_column_def( column_obj, lmp->lm_column_data[i], i, NULL );
+  return 0;
+}
+
+XI_OBJ_DEF *
+xi_get_def(XI_OBJ *xi_obj)
+{
+  switch (xi_obj->type)
+  {
+  case XIT_LIST:
+    return xi_get_list_def(xi_obj);
+  case XIT_COLUMN:
+  return xi_get_column_def2( xi_obj );
+  case XIT_FIELD:
+  {
+    XI_OBJ_DEF *field;
+    XI_FIELD_DEF *xi_fd;
+    XI_FIELD_DATA *field_data;
+    STX_DATA *stxp;
+
+    field_data = xi_obj->v.field;
+    stxp = (STX_DATA *)field_data->stx;
+    field = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), NULL);
+    field->type = XIT_FIELD;
+    field->cid = xi_obj->cid;
+    field->app_data = xi_obj->app_data;
+    field->v.field = xi_fd =
+      (XI_FIELD_DEF *)xi_tree_malloc(sizeof(XI_FIELD_DEF), field);
+    xi_fd->xi_rct = field_data->xi_rct;
+    xi_fd->pnt = field_data->xi_pnt;
+    xi_fd->field_width = field_data->field_width;
+    xi_fd->attrib = stxp->attrib;
+    xi_fd->tab_cid = field_data->tab_cid;
+    xi_fd->text_size = stxp->text_size;
+    xi_fd->back_color = stxp->back_color;
+    xi_fd->enabled_color = stxp->enabled_color;
+    xi_fd->disabled_color = stxp->disabled_color;
+    xi_fd->disabled_back_color = stxp->disabled_back_color;
+    xi_fd->active_color = stxp->active_color;
+    xi_fd->active_back_color = stxp->active_back_color;
+    xi_fd->hilight_color = stxp->hilight_color;
+    xi_fd->shadow_color = stxp->shadow_color;
+    xi_fd->button = field_data->button;
+    xi_fd->button_on_left = field_data->button_on_left;
+    xi_fd->icon_rid = field_data->icon_rid;
+    xi_fd->well = field_data->well;
+    xi_fd->platform = field_data->platform;
+    if (field_data->font_set)
+    {
+      xi_fd->font_id = stxp->font;
+    }
+    return field;
+  }
+  case XIT_TEXT:
+  {
+    XI_OBJ_DEF *text;
+    XI_TEXT_DEF *xi_td;
+    XI_TEXT_DATA *text_data;
+
+    text_data = xi_obj->v.text;
+    text = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), NULL);
+    text->type = XIT_TEXT;
+    text->cid = xi_obj->cid;
+    text->app_data = xi_obj->app_data;
+    text->v.text = xi_td =
+      (XI_TEXT_DEF *)xi_tree_malloc(sizeof(XI_TEXT_DEF), text);
+    xi_td->xi_rct = text_data->xi_rct;
+    xi_td->attrib = text_data->attrib;
+    if (text_data->text)
+    {
+      xi_td->text = (char *)xi_tree_malloc(strlen(text_data->text) + 1,
+        xi_td);
+      strcpy(xi_td->text, text_data->text);
+    }
+    xi_td->fore_color = text_data->fore_color;
+    xi_td->back_color = text_data->back_color;
+    if (text_data->font)
+    {
+      xi_td->font_id = *text_data->font;
+    }
+    return text;
+  }
+  case XIT_BTN:
+  {
+    XI_OBJ_DEF *btn;
+    XI_BTN_DEF *xi_bd;
+    XI_BTN_DATA *btn_data;
+
+    btn_data = xi_obj->v.btn;
+    btn = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), NULL);
+    btn->type = XIT_BTN;
+    btn->cid = xi_obj->cid;
+    btn->app_data = xi_obj->app_data;
+    btn->v.btn = xi_bd =
+      (XI_BTN_DEF *)xi_tree_malloc(sizeof(XI_BTN_DEF), btn);
+    xi_bd->xi_rct = btn_data->xi_rct;
+    xi_bd->pixel_rect = btn_data->rct;
+    xi_bd->attrib = btn_data->attrib;
+    if (btn_data->text)
+    {
+      xi_bd->text = (char *)xi_tree_malloc(strlen(btn_data->text) + 1,
+        xi_bd);
+      strcpy(xi_bd->text, btn_data->text);
+    }
+    xi_bd->tab_cid = btn_data->tab_cid;
+    xi_bd->dflt = btn_data->dflt;
+    xi_bd->down_icon_rid = btn_data->down_icon_rid;
+    xi_bd->up_icon_rid = btn_data->up_icon_rid;
+    xi_bd->disabled_icon_rid = btn_data->disabled_icon_rid;
+    xi_bd->icon_x = btn_data->icon_x;
+    xi_bd->icon_y = btn_data->icon_y;
+    xi_bd->checked = btn_data->checked;
+    xi_bd->fore_color = btn_data->fore_color;
+    xi_bd->drawable = btn_data->drawable;
+    return btn;
+  }
+  case XIT_LINE:
+  {
+    XI_OBJ_DEF *line;
+    XI_LINE_DEF *xi_ld;
+    XI_LINE_DATA *line_data;
+
+    line_data = xi_obj->v.line;
+    line = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), NULL);
+    line->type = XIT_LINE;
+    line->cid = xi_obj->cid;
+    line->app_data = xi_obj->app_data;
+    line->v.line = xi_ld =
+      (XI_LINE_DEF *)xi_tree_malloc(sizeof(XI_LINE_DEF), line);
+    xi_ld->pnt1 = line_data->xi_pnt1;
+    xi_ld->pnt2 = line_data->xi_pnt2;
+    xi_ld->pixel_pnt1 = line_data->pnt1;
+    xi_ld->pixel_pnt2 = line_data->pnt2;
+    xi_ld->fore_color = line_data->fore_color;
+    xi_ld->back_color = line_data->back_color;
+    xi_ld->well = line_data->well;
+    xi_ld->attrib = line_data->attrib;
+    return line;
+  }
+  case XIT_RECT:
+  {
+    XI_OBJ_DEF *rect;
+    XI_RECT_DEF *xi_rd;
+    XI_RECT_DATA *rect_data;
+
+    rect_data = xi_obj->v.rect;
+    rect = (XI_OBJ_DEF *)xi_tree_malloc(sizeof(XI_OBJ_DEF), NULL);
+    rect->type = XIT_RECT;
+    rect->cid = xi_obj->cid;
+    rect->app_data = xi_obj->app_data;
+    rect->v.rect = xi_rd =
+      (XI_RECT_DEF *)xi_tree_malloc(sizeof(XI_RECT_DEF), rect);
+    xi_rd->xi_rct = rect_data->xi_rct;
+    xi_rd->pixel_rect = rect_data->rct;
+    xi_rd->fore_color = rect_data->fore_color;
+    xi_rd->back_color = rect_data->back_color;
+    xi_rd->hilight_color = rect_data->hilight_color;
+    xi_rd->shadow_color = rect_data->shadow_color;
+    xi_rd->well = rect_data->well;
+    xi_rd->attrib = rect_data->attrib;
+    return rect;
+  }
+  }
+  return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* get_button_def_rect                                                      */
+/*--------------------------------------------------------------------------*/
+static void get_button_def_rect( FONT_OBJ* font, XI_OBJ_DEF* obj_def,
+                      RCT* rect )
+{
+  *rect = obj_def->v.btn->pixel_rect;
+  if (rect->right == 0 && rect->left == 0 && rect->top == 0
+    && rect->bottom == 0)
+  {
+  *rect = obj_def->v.btn->xi_rct;
+  xi_fu_to_pu_font( font, (PNT*) rect, 2 );
+  }
+  if (rect->top == rect->bottom)
+  rect->bottom = rect->top + (int)xi_get_pref(XI_PREF_BUTTON_HEIGHT);
+}
+
+/*--------------------------------------------------------------------------*/
+/* get_container_def_rect                                                   */
+/*--------------------------------------------------------------------------*/
+static void get_container_def_rect( FONT_OBJ* font, XI_OBJ_DEF* obj_def,
+                        RCT* rect )
+{
+  *rect = obj_def->v.container->pixel_rect;
+  if (!rect->right && !rect->left && !rect->top && !rect->bottom )
+  {
+  *rect = obj_def->v.container->xi_rct;
+  xi_fu_to_pu_font( font, (PNT*) rect, 2 );
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+/* get_column_def_rect                                                   */
+/*--------------------------------------------------------------------------*/
+static void get_column_def_rect( FONT_OBJ* font, XI_OBJ_DEF* obj_def,
+                      RCT* rect )
+{
+  XI_OBJ_DEF * list;
+  XI_OBJ_DEF * itf;
+  /* left and height is undefined without list context */
+  rect->top = rect->bottom = 0;
+  rect->left = 0;
+  if (obj_def->v.column->pixel_width)
+  rect->right = obj_def->v.column->pixel_width;
+  else
+  {
+  rect->right = obj_def->v.column->width;
+  list = obj_def->parent;
+  if (list == NULL)
+    itf = NULL;
+  else
+    itf = list->parent;
+
+  if (xi_get_xil_pref((XI_OBJ*)itf))
+  {
+    if (font)
+      rect->right *= xi_get_fu_width_font(font);
+    else
+      rect->right *= xi_get_fu_width(NULL);
+  }
+  else
+    xi_fu_to_pu_font( font, (PNT*) rect, 2 );
+
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+/* get_interface_def_rect                                                   */
+/*--------------------------------------------------------------------------*/
+static void get_interface_def_rect( FONT_OBJ* font, XI_OBJ_DEF* obj_def,
+                                    RCT* rect )
+{
+  BOOLEAN      first_rect = TRUE;
+  XI_OBJ_DEF** defp;
+  int          i, n;
+
+  MEMCLEAR(*rect);
+  defp = obj_def->children;
+  n = obj_def->nbr_children;
+  for (i = 0; i < n; defp++, i++)
+  {
+  if (first_rect)
+  {
+    if (xi_get_def_rect(*defp, rect) != NULL)
+      first_rect = FALSE;
+  }
+  else
+  {
+    RCT rct;
+
+    if (xi_get_def_rect(*defp, &rct) != NULL)
+      xi_get_enclosing_rect(rect, &rct, rect);
+  }
+  }
+  if (obj_def->type == XIT_ITF)
+  {
+  int fu_width, fu_height, ws_right, ws_bottom;
+  int ws_right_pix, ws_bottom_pix;
+
+  rect->left = 0;
+  rect->top = 0;
+  if (!xi_get_xil_pref((XI_OBJ*)obj_def))
+  {
+    if (font)
+    {
+      fu_width = xi_get_fu_width_font(font);
+      fu_height = xi_get_fu_height_font(font);
+    }
+    else
+    {
+      fu_width = xi_get_fu_width(NULL);
+      fu_height = xi_get_fu_height(NULL);
+    }
+    ws_right = (int)xi_get_pref(XI_PREF_ITF_WS_RIGHT);
+    ws_bottom = (int)xi_get_pref(XI_PREF_ITF_WS_BOTTOM);
+    if (obj_def->v.itf->use_whitespace)
+    {
+      ws_right = obj_def->v.itf->whitespace_right;
+      ws_bottom = obj_def->v.itf->whitespace_bottom;
+    }
+    ws_right_pix = fu_width * ws_right / XI_FU_MULTIPLE;
+    ws_bottom_pix = fu_height * ws_bottom / XI_FU_MULTIPLE;
+    rect->bottom += ws_bottom_pix;
+    rect->right += ws_right_pix;
+  }
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+/* get_field_def_rect                                                       */
+/*--------------------------------------------------------------------------*/
+static void get_field_def_rect( FONT_OBJ* font, XI_OBJ_DEF* obj_def,
+                      RCT* rect )
+{
+  XI_FIELD_DEF *flddef = obj_def->v.field;
+  FONT_OBJ* parent_font = xi_def_get_font(obj_def->parent);
+
+  if (flddef->xi_rct.top || flddef->xi_rct.left ||
+    flddef->xi_rct.bottom || flddef->xi_rct.right)
+  {
+  *rect = flddef->xi_rct;
+  xi_fu_to_pu_font( parent_font, (PNT*)rect, 2 );
+  } else
+  {
+  if (flddef->pixel_origin.v || flddef->pixel_origin.h)
+  {
+    rect->top = flddef->pixel_origin.v;
+    rect->left = flddef->pixel_origin.h;
+  } else
+  {
+    rect->top = flddef->pnt.v;
+    rect->left = flddef->pnt.h;
+    xi_fu_to_pu_font( parent_font, (PNT *)rect, 1);
+  }
+  {
+    PNT pnt;
+
+#if 0
+    /* TODO why is this code here? */
+    if (flddef->pixel_width)
+      pnt.h = 2 * XI_FU_MULTIPLE;
+    else
+      pnt.h = 2 * XI_FU_MULTIPLE + flddef->field_width;
+#else
+    if (flddef->pixel_width)
+      pnt.h = 2 * XI_FU_MULTIPLE;
+    else
+      pnt.h = flddef->field_width;
+#endif
+    pnt.v = XI_FU_MULTIPLE;
+    xi_fu_to_pu_font( font, &pnt, 1 );
+    rect->bottom = rect->top + pnt.v;
+    if (flddef->pixel_width)
+      rect->right = rect->left + flddef->pixel_width + pnt.h;
+    else
+      /* add 4 for the 3d rect */
+      rect->right = rect->left + pnt.h + 4;
+  }
+  }
+  if (flddef->button)
+  {
+  RCT r;
+  int fu_width, fu_height, btn_dim_x, btn_dim_x2, btn_space;
+
+  r.top = 0;
+  r.left = 0;
+  r.bottom = 8;
+  r.right = 8;
+  xi_fu_to_pu_font( font, (PNT*)&r, 2 );
+  fu_width = r.right;
+  fu_height = r.bottom;
+  btn_dim_x = (fu_height * XI_FU_MULTIPLE) / fu_width;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  /* make buttons 70% wide as high */
+  btn_dim_x = (int)((long)btn_dim_x * 83L / 100L);
+  CTOS_END;
+#endif
+  btn_space = btn_dim_x / 6;
+  /* btn_dim_x2 is the button width + space, rounded up to */
+  /* the next even form unit */
+  btn_dim_x2 = btn_dim_x + btn_space;
+  btn_dim_x2 = ((btn_dim_x2 + XI_FU_MULTIPLE) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+  btn_dim_x = (int)(((long)btn_dim_x * fu_width) / XI_FU_MULTIPLE);
+  btn_dim_x2 = (int) (((long)btn_dim_x2 * fu_width) / XI_FU_MULTIPLE);
+  if (flddef->button_on_left)
+  {
+    rect->right += btn_dim_x;
+    if (flddef->pixel_button_distance)
+      rect->right += flddef->pixel_button_distance;
+    else
+      rect->right += (btn_dim_x2 - btn_dim_x);
+  } else
+  {
+    rect->right += btn_dim_x;
+    if (flddef->pixel_button_distance)
+      rect->right += flddef->pixel_button_distance;
+    else
+    {
+      rect->right += (btn_dim_x2 - btn_dim_x);
+      /* convert to form units */
+      rect->right = (int)(((long)rect->right * XI_FU_MULTIPLE) / fu_width );
+      /* round up to nearest FU multiple */
+      rect->right = ((rect->right + XI_FU_MULTIPLE) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+      /* convert to pixels */
+      rect->right = (int)(((long)rect->right * fu_width) / XI_FU_MULTIPLE);
+    }
+  }
+  }
+}
+/*--------------------------------------------------------------------------*/
+/* get_list_def_rect                                                       */
+/*--------------------------------------------------------------------------*/
+static void get_list_def_rect( FONT_OBJ* font, XI_OBJ_DEF* obj_def,
+                    RCT* rect )
+{
+  XI_LIST_DEF* list_def;
+  int          list_xborder, list_col_div, width, list_bottom;
+  int          col_offset;
+  FONT_OBJ* parent_font = xi_def_get_font(obj_def->parent);
+
+  list_def = obj_def->v.list;
+  lm_get_metrics( obj_def, &list_xborder, &list_col_div, &list_bottom);
+  col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+  if (xi_get_xil_pref((XI_OBJ*)obj_def->parent))
+  {
+  rect->top = list_def->xi_pnt.v;
+  rect->left = list_def->xi_pnt.h;
+  width = list_def->width;
+  }
+  else
+  {
+  if (list_def->pixel_origin.h || list_def->pixel_origin.v)
+  {
+    rect->top = list_def->pixel_origin.h;
+    rect->left = list_def->pixel_origin.v;
+  } else
+  {
+    rect->top = list_def->xi_pnt.v;
+    rect->left = list_def->xi_pnt.h;
+    xi_fu_to_pu_font( parent_font, (PNT*) rect, 1 );
+  }
+  width = list_def->pixel_width;
+  if (!width)
+  {
+    PNT p;
+
+    p.h = list_def->width;
+    p.v = 0;
+    xi_fu_to_pu_font( font, &p, 1);
+    width = p.h;
+  }
+  }
+  rect->bottom = 0;
+  if (width)
+  rect->right = rect->left + width + 2 * BORDER_WIDTH;
+  else
+  {
+  XI_OBJ_DEF** defp;
+  int          i, n;
+
+  defp = obj_def->children;
+  n = obj_def->nbr_children;
+  rect->right = rect->left;
+  for (i = 0; i < n; defp++, i++)
+  {
+    RCT rct;
+
+    xi_get_def_rect(*defp, &rct);
+    rect->right += rct.right;
+    if (i)
+      rect->right += list_col_div;
+    else
+      rect->right += 2 * col_offset;
+  }
+  rect->right += BORDER_WIDTH * 2;
+  }
+  rect->bottom = list_bottom;
+  if (list_def->scroll_bar)
+  rect->right = rect->right + (int)xvt_vobj_get_attr(NULL_WIN, ATTR_CTL_VERT_SBAR_WIDTH) - 1;
+  if (width)
+#if XVTWS != WMWS
+  rect->bottom += (int)xvt_vobj_get_attr(NULL_WIN, ATTR_CTL_HORZ_SBAR_HEIGHT) + 3;
+#else
+  rect->bottom += (int)xvt_vobj_get_attr(NULL_WIN, ATTR_CTL_HORZ_SBAR_HEIGHT);
+#endif
+}
+
+/*--------------------------------------------------------------------------*/
+/* xi_get_def_rect                                                          */
+/*--------------------------------------------------------------------------*/
+
+RCT* xi_get_def_rect(XI_OBJ_DEF *xi_obj_def, RCT *rect)
+{
+  FONT_OBJ*    font = NULL;
+
+  xi_init();
+  font = xi_def_get_font( xi_obj_def );
+  MEMCLEAR(*rect);
+  switch(xi_obj_def->type)
+  {
+  case XIT_BTN:
+  get_button_def_rect( font, xi_obj_def, rect );
+  break;
+  case XIT_CONTAINER:
+  get_container_def_rect( font, xi_obj_def, rect );
+  break;
+  case XIT_COLUMN:
+  get_column_def_rect( font, xi_obj_def, rect );
+  break;
+  case XIT_ITF:
+  case XIT_FORM:
+  get_interface_def_rect( font, xi_obj_def, rect );
+  break;
+  case XIT_FIELD:
+  get_field_def_rect( font, xi_obj_def, rect );
+  break;
+  case XIT_LIST:
+  get_list_def_rect( font, xi_obj_def, rect );
+  break;
+  case XIT_TEXT:
+  *rect = xi_obj_def->v.text->pixel_rect;
+  if (!rect->left && !rect->right && !rect->top && !rect->bottom)
+  {
+    font = xi_def_get_font( xi_obj_def->parent );
+    *rect = xi_obj_def->v.text->xi_rct;
+    xi_fu_to_pu_font( font, (PNT*)rect, 2);
+  }
+  break;
+  case XIT_GROUP:
+  /* no bounding rect for these guys! */
+  return(NULL);
+  case XIT_RECT:
+  *rect = xi_obj_def->v.rect->xi_rct;
+  xi_fu_to_pu_font( font, (PNT*)rect, 2 );
+  break;
+  case XIT_LINE:
+  {
+    XI_LINE_DEF *line;
+
+    line = xi_obj_def->v.line;
+    rect->top = min(line->pnt1.v, line->pnt2.v);
+    rect->bottom = max(line->pnt1.v, line->pnt2.v);
+    rect->left = min(line->pnt1.h, line->pnt2.h);
+    rect->right = max(line->pnt1.h, line->pnt2.h);
+    xi_fu_to_pu_font( font, (PNT*)rect, 2 );
+    break;
+  }
+  case XIT_CELL:
+  case XIT_ROW:
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20019", 20019,
+      "xi_get_def_rect: Invalid XI_OBJ_TYPE in tree");
+  }
+  return(rect);
+}
+
+/* --------------------------------------------------------------------------*/
+/*  xi_button_set_default                                                    */
+/* --------------------------------------------------------------------------*/
+static void invalidate_button_rect( XI_OBJ* xi_obj )
+{
+  RCT    rect = xi_obj->v.btn->rct;
+  WINDOW win;
+
+  if (xi_obj->v.btn->type == XIBT_TABBTN)
+    rect.bottom += 2;
+  win = xi_obj->itf->v.itf->xvt_win;
+  xi_invalidate_rect(win, &rect);
+}
+
+BOOLEAN xi_button_set_default(XI_OBJ* xi_obj, BOOLEAN set )
+{
+  if (xi_obj == NULL)
+    return FALSE;
+  if (set)  /* clear previous default button */
+  {
+    if (xi_obj->type != XIT_BTN)
+      return FALSE;
+    if (!xi_obj->v.btn->dflt)
+    {
+      xi_button_set_default( xi_obj->itf, FALSE );
+      xi_obj->v.btn->dflt = TRUE;
+      invalidate_button_rect( xi_obj );
+    }
+    return TRUE;
+  }
+  switch (xi_obj->type)
+  {
+    case XIT_BTN:
+      if (xi_obj->v.btn->dflt)
+      {
+        xi_obj->v.btn->dflt = FALSE;
+        invalidate_button_rect( xi_obj );
+      }
+      return TRUE;
+    case XIT_CONTAINER:
+    case XIT_ITF:
+    {
+      XI_OBJ** ptr;
+      int      i;
+      int      n;
+
+      ptr = xi_obj->children;
+      n = xi_obj->nbr_children;
+      for (i = 0; i < n; ptr++, i++)
+        xi_button_set_default( *ptr, FALSE );
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
diff --git a/xi/xidbg.c b/xi/xidbg.c
new file mode 100755
index 000000000..95e339c50
--- /dev/null
+++ b/xi/xidbg.c
@@ -0,0 +1,304 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#define XI_INTERNAL
+#include "xiextend.h"
+#include "xi.h"
+#include "xiutils.h"
+
+#define UNDEFINED 1000
+#define BUFFERLEN 200
+
+static char * near
+bool_to_str(BOOLEAN b)
+{
+  if (b)
+    return "TRUE";
+  else
+    return "FALSE";
+}
+
+void
+xi_event_debug(char *tag, XI_EVENT *xiev, char *s, int len)
+{
+  char *tmp;
+  char str[BUFFERLEN], str2[BUFFERLEN];
+  int i, j, k;
+  XI_OBJ *xi_obj;
+
+  static struct
+    {
+    int type;
+    char *desc;
+  } event_text[] =
+  {
+    {
+      XIE_CHAR_FIELD, "XIE_CHAR_FIELD  "},
+      {XIE_DBL_FIELD,   "XIE_DBL_FIELD   "},
+      {XIE_CHG_FIELD,   "XIE_CHG_FIELD   "},
+      {XIE_OFF_FIELD,   "XIE_OFF_FIELD   "},
+      {XIE_ON_FIELD,    "XIE_ON_FIELD    "},
+      {XIE_OFF_GROUP,   "XIE_OFF_GROUP   "},
+      {XIE_ON_GROUP,    "XIE_ON_GROUP    "},
+      {XIE_OFF_FORM,    "XIE_OFF_FORM    "},
+      {XIE_ON_FORM,   "XIE_ON_FORM     "},
+      {XIE_VIR_PAN,   "XIE_VIR_PAN     "},
+      {XIE_XVT_EVENT,   "XIE_XVT_EVENT   "},
+      {XIE_XVT_POST_EVENT,"XIE_XVT_POST_EVENT"},
+      {XIE_INIT,      "XIE_INIT        "},
+      {XIE_BUTTON,    "XIE_BUTTON      "},
+      {XIE_CHAR_CELL,   "XIE_CHAR_CELL   "},
+      {XIE_CLEANUP,   "XIE_CLEANUP     "},
+      {XIE_CLOSE,     "XIE_CLOSE       "},
+      {XIE_COMMAND,   "XIE_COMMAND     "},
+      {XIE_DBL_CELL,    "XIE_DBL_CELL    "},
+      {XIE_GET_FIRST,   "XIE_GET_FIRST   "},
+      {XIE_GET_LAST,    "XIE_GET_LAST    "},
+      {XIE_GET_NEXT,    "XIE_GET_NEXT    "},
+      {XIE_GET_PERCENT, "XIE_GET_PERCENT "},
+      {XIE_GET_PREV,    "XIE_GET_PREV    "},
+      {XIE_CELL_REQUEST,  "XIE_CELL_REQUEST"},
+      {XIE_CHG_CELL,    "XIE_CHG_CELL    "},
+      {XIE_OFF_CELL,    "XIE_OFF_CELL    "},
+      {XIE_ON_CELL,   "XIE_ON_CELL     "},
+      {XIE_OFF_ROW,   "XIE_OFF_ROW     "},
+      {XIE_ON_ROW,    "XIE_ON_ROW      "},
+      {XIE_OFF_COLUMN,  "XIE_OFF_COLUMN  "},
+      {XIE_ON_COLUMN,   "XIE_ON_COLUMN   "},
+      {XIE_OFF_LIST,    "XIE_OFF_LIST    "},
+      {XIE_ON_LIST,   "XIE_ON_LIST     "},
+      {XIE_REC_ALLOCATE,  "XIE_REC_ALLOCATE"},
+      {XIE_REC_FREE,    "XIE_REC_FREE    "},
+      {XIE_ROW_SIZE,    "XIE_ROW_SIZE    "},
+      {XIE_SELECT,    "XIE_SELECT      "},
+      {XIE_UPDATE,    "XIE_UPDATE      "},
+      {XIE_COL_DELETE,  "XIE_COL_DELETE  "},
+      {XIE_COL_MOVE,    "XIE_COL_MOVE    "},
+      {XIE_COL_SIZE,    "XIE_COL_SIZE    "},
+      {UNDEFINED,     "Unknown XI Event"    }
+  };
+
+  static struct
+    {
+    int type;
+    char *desc;
+  } xvt_event_text[] =
+  {
+    {E_MOUSE_UP,  "E_MOUSE_UP"},
+    {E_MOUSE_DOWN,  "E_MOUSE_DOWN"},
+    {E_CREATE,  "E_CREATE"},
+    {E_MOUSE_MOVE,  "E_MOUSE_MOVE"},
+    {E_MOUSE_DBL, "E_MOUSE_DBL"},
+    {E_CHAR,    "E_CHAR"},
+    {E_UPDATE,    "E_UPDATE"},
+    {E_ACTIVATE,  "E_FOCUS"},
+    {E_KILL_WINDOW, "E_DESTROY"},
+    {E_VSCROLL,   "E_VSCROLL"},
+    {E_HSCROLL,   "E_HSCROLL"},
+    {E_COMMAND,   "E_COMMAND"},
+    {E_CLOSE,   "E_CLOSE"},
+    {E_SIZE,    "E_SIZE"},
+    {E_FONT,    "E_FONT"},
+    {E_QUIT,    "E_QUIT"},
+    {E_CONTROL,   "E_CONTROL"},
+    {UNDEFINED,   "Unknown XVT Event"}
+  };  
+
+
+  static struct
+    {
+    int type;
+    char *desc;
+  } object_type[] =
+  {
+    {
+      XIT_BTN,    "XIT_BTN"},
+      {XIT_CONTAINER, "XIT_CONTAINER"},
+      {XIT_FORM,    "XIT_FORM"},
+      {XIT_FIELD,   "XIT_FIELD"},
+      {XIT_GROUP,   "XIT_GROUP"},
+      {XIT_LINE,    "XIT_LINE"},
+      {XIT_RECT,    "XIT_RECT"},
+      {XIT_TEXT,    "XIT_TEXT"},
+      {XIT_CELL,    "XIT_CELL"},
+      {XIT_COLUMN,  "XIT_COLUMN"},
+      {XIT_ITF,   "XIT_ITF"},
+      {XIT_LIST,    "XIT_LIST"},
+      {XIT_ROW,   "XIT_ROW"},
+      {UNDEFINED,   "Unknown XI Object Type"    }
+  };
+
+  for (i = 0; event_text[i].type != xiev->type &&
+      event_text[i].type != UNDEFINED; ++i)
+    ;
+  sprintf(str, "%s: %s", tag, event_text[i].desc);
+  *str2 = '\0';
+  switch (xiev->type)
+  {
+  case XIE_XVT_EVENT:
+  case XIE_XVT_POST_EVENT:
+    for (j = 0; xvt_event_text[j].type != xiev->v.xvte.type &&
+        xvt_event_text[j].type != UNDEFINED; ++j)
+      ;
+    sprintf(str2, "  %s", xvt_event_text[j].desc);
+    break;
+  case XIE_COMMAND:
+    sprintf(str2, "  tag %d, shift %s, control %s", xiev->v.cmd.tag,
+        bool_to_str(xiev->v.cmd.shift), bool_to_str(xiev->v.cmd.control));
+    break;
+  case XIE_INIT:
+  case XIE_BUTTON:
+  case XIE_CLOSE:
+  case XIE_DBL_CELL:
+  case XIE_DBL_FIELD:
+  case XIE_CHG_FIELD:
+  case XIE_OFF_FIELD:
+  case XIE_ON_FIELD:
+  case XIE_OFF_GROUP:
+  case XIE_ON_GROUP:
+  case XIE_OFF_FORM:
+  case XIE_ON_FORM:
+  case XIE_CHG_CELL:
+  case XIE_OFF_CELL:
+  case XIE_ON_CELL:
+  case XIE_OFF_ROW:
+  case XIE_ON_ROW:
+  case XIE_OFF_COLUMN:
+  case XIE_ON_COLUMN:
+  case XIE_OFF_LIST:
+  case XIE_ON_LIST:
+  case XIE_CLEANUP:
+    xi_obj = xiev->v.xi_obj;
+    for (k = 0; object_type[k].type != xi_obj->type &&
+        object_type[k].type != UNDEFINED; ++k)
+      ;
+    switch (xi_obj->type)
+    {
+    case XIT_CELL:
+      sprintf(str2, "  cid %3d, type %s r %d c %d v %d",
+          xi_obj->cid, object_type[k].desc, xi_obj->v.cell.row,
+          xi_obj->v.cell.column, !xi_obj->v.cell.is_vert_scrolled);
+      break;
+    case XIT_ROW:
+      sprintf(str2, "  cid %3d, type %s  r %d", xi_obj->cid,
+          object_type[k].desc, xi_obj->v.row);
+      break;
+    default:
+      sprintf(str2, "  cid %3d, type %s", xi_obj->cid,
+          object_type[k].desc);
+      break;
+    }
+    break;
+  case XIE_CHAR_CELL:
+  case XIE_CHAR_FIELD:
+    {
+      char char_str[20];
+      int ch;
+
+      ch = xiev->v.chr.ch;
+      switch (ch)
+      {
+      case K_CLEAR:
+        strcpy(char_str, "K_CLEAR");
+        break;
+      case K_DEL:
+        strcpy(char_str, "K_DEL");
+        break;
+      case '\b':
+        strcpy(char_str, "BS");
+        break;
+      default:
+        char_str[0] = (char)ch;
+        char_str[1] = '\0';
+        break;
+      }
+      xi_obj = xiev->v.chr.xi_obj;
+      for (k = 0; object_type[k].type != xi_obj->type &&
+          object_type[k].type != UNDEFINED; ++k)
+        ;
+      switch (xi_obj->type)
+      {
+      case XIT_CELL:
+        sprintf(str2,
+            "  cid %3d type %s r %d c %d ch %s shft %d ctrl %d",
+            xi_obj->cid, object_type[k].desc, xi_obj->v.cell.row,
+            xi_obj->v.cell.column, char_str, xiev->v.chr.shift,
+            xiev->v.chr.control);
+        break;
+      case XIT_FIELD:
+        sprintf(str2, "  cid %3d type %s ch %s shft %d ctrl %d", xi_obj->cid,
+            object_type[k].desc, char_str, xiev->v.chr.shift,
+            xiev->v.chr.control);
+        break;
+      }
+      break;
+    }
+  case XIE_GET_FIRST:
+  case XIE_GET_LAST:
+    sprintf(str2, "  data_rec %08.8lx", (long)xiev->v.rec_request.data_rec);
+    break;
+  case XIE_GET_NEXT:
+  case XIE_GET_PREV:
+    sprintf(str2, "  spec_rec %08.8lx, data_rec %08.8lx",
+        (long)xiev->v.rec_request.spec_rec, (long)xiev->v.rec_request.data_rec);
+    break;
+  case XIE_CELL_REQUEST:
+    sprintf(str2, "  c %2d, rec %08.8lx, len %3d",
+        (int)xiev->v.cell_request.col_nbr, (long)xiev->v.cell_request.rec,
+        xiev->v.cell_request.len);
+    break;
+  case XIE_GET_PERCENT:
+    sprintf(str2, "  list->cid %d, record %08.8lx",
+        xiev->v.get_percent.list->cid,
+        (long)xiev->v.get_percent.record);
+    break;
+  case XIE_SELECT:
+    sprintf(str2, "  row %d, selected %d, dbl_click %d shift %d control %d column %d",
+        xiev->v.select.xi_obj->v.row, xiev->v.select.selected,
+        xiev->v.select.dbl_click, xiev->v.select.shift, xiev->v.select.control, xiev->v.select.column);
+    break;
+  case XIE_REC_ALLOCATE:
+    sprintf(str2, "  list cid %d", xiev->v.rec_allocate.list->cid);
+    break;
+  case XIE_REC_FREE:
+    sprintf(str2, "  list cid %d, record %08.8lx", xiev->v.rec_free.list->cid, xiev->v.rec_free.record);
+    break;
+  case XIE_ROW_SIZE:
+    sprintf(str2, "  row %d, new_size %d", xiev->v.row_size.xi_obj->v.row, xiev->v.row_size.new_row_height);
+    break;
+  case XIE_VIR_PAN:
+    sprintf(str2, "  delta_x %d, delta_y %d, before_pan %d",
+        xiev->v.vir_pan.delta_x, xiev->v.vir_pan.delta_y,
+        xiev->v.vir_pan.before_pan);
+    break;
+  case XIE_COL_DELETE:
+    sprintf(str2, "  list cid %d, col_nbr %d",
+        xiev->v.column.list->cid, xiev->v.column.col_nbr);
+    break;
+  case XIE_COL_MOVE:
+    sprintf(str2, "  list cid %d, col_nbr %d, new_col_nbr %d",
+        xiev->v.column.list->cid, xiev->v.column.col_nbr,
+        xiev->v.column.new_col_nbr);
+    break;
+  case XIE_COL_SIZE:
+  sprintf(str2,
+      "  list cid %d, col_nbr %d, new_col_width %d new_col_pixel_width %d",
+      xiev->v.column.list->cid, xiev->v.column.col_nbr,
+      xiev->v.column.new_col_width, xiev->v.column.new_col_pixel_width);
+  break;
+  }
+  tmp = (char *)xi_tree_malloc(strlen(str) + strlen(str2) + 2, NULL);
+  strcpy(tmp, str);
+  strcat(tmp, str2);
+  if ((int)strlen(tmp) >= len)
+  tmp[len] = '\0';
+  strcpy(s, tmp);
+  xi_tree_free(tmp);
+}
+
diff --git a/xi/xidisply.h b/xi/xidisply.h
new file mode 100755
index 000000000..4108aec26
--- /dev/null
+++ b/xi/xidisply.h
@@ -0,0 +1,27 @@
+#define C_UL        218             /* upper left */
+#define C_UR        191             /* upper right */
+#define C_LL        192             /* lower left */
+#define C_LR        217             /* lower right */
+#define C_XD        194             /* T-intersection down */
+#define C_XU        193             /* T-intersection up */
+#define C_XR        195             /* T-intersection right */
+#define C_XL        180             /* T-intersection left */
+#define C_XX        197             /* 4-way intersection */
+#define C_H         196             /* horizontal line */
+#define C_V         179             /* vertical line */
+#define C_ULD       201             /* next group same as above, but double */
+#define C_URD       187
+#define C_LLD       200
+#define C_LRD       188
+#define C_XDD       203
+#define C_XUD       202
+#define C_XRD       204
+#define C_XLD       185
+#define C_XXD       206
+#define C_HD        205
+#define C_VD        186
+#define C_HATCH     176             /* hatching */
+#define C_SPACE     255             
+
+
+
diff --git a/xi/xiextend.h b/xi/xiextend.h
new file mode 100755
index 000000000..0d539e8c6
--- /dev/null
+++ b/xi/xiextend.h
@@ -0,0 +1,65 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.                  *
+*******************************************************************************/
+
+#ifdef WSWIN
+#define NOCOMM
+#define NOMINMAX
+#define NOGDICAPMASKS
+#define NOVIRTUALKEYCODES
+#define NOWINMESSAGES
+#define NOWINSTYLES
+#define NOSYSMETRICS
+#define NOMENUS 
+#define NOICONS 
+#define NOKEYSTATES
+#define NOSYSCOMMANDS
+#define NORASTEROPS
+#define NOSHOWWINDOW
+#define OEMRESOURCE
+#define NOATOM  
+#define NOCLIPBOARD
+#define NOCOLOR 
+#define NOCTLMGR  
+#define NODRAWTEXT  
+#define NOGDI 
+#define NOKERNEL  
+/* #define NOUSER  */
+#define NOMB  
+#define NOMEMMGR  
+#define NOMETAFILE  
+#define NOMINMAX  
+#define NOMSG 
+#define NOOPENFILE  
+#define NOSCROLL  
+#define NOSOUND 
+#define NOTEXTMETRIC
+#define NOWH  
+#define NOWINOFFSETS
+#define NOCOMM  
+#define NOKANJI 
+#define NOHELP
+#define NOPROFILER  
+#define NODEFERWINDOWPOS
+#include <windows.h>
+#define INTERNAL
+#endif
+
+#ifdef OSOS2
+#define INCL_DOS
+#define INCL_WIN
+#define INCL_GPI
+#define COLOR pm_COLOR
+#define UINT pm_UINT
+#define ULONG pm_ULONG
+#include <os2.h>
+#undef COLOR
+#undef UINT
+#undef ULONG
+#define INTERNAL
+#endif
+
+
diff --git a/xi/xiheap.c b/xi/xiheap.c
new file mode 100755
index 000000000..9b9755201
--- /dev/null
+++ b/xi/xiheap.c
@@ -0,0 +1,57 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#define XI_INTERNAL
+
+#include "xi.h"
+#include "xiheap.h"
+
+#ifdef DEBUG
+int nbr_malloc, nbr_free;
+#endif
+
+void *
+heap_malloc(size_t size)
+{
+  void *p;
+
+#ifdef DEBUG
+  nbr_malloc++;
+#endif
+  p = malloc(size);
+  if ( p != NULL )
+    memset((char *)p, '\0', (size_t)size);
+  return(p);
+}
+
+void
+heap_free(void *p)
+{
+#ifdef DEBUG
+  nbr_free++;
+#endif
+  free((char *)p);
+}
+
+void *
+heap_realloc(void *p, size_t size)
+{
+  return( realloc((char *)p, size ));
+}
+
+void
+heap_dbg(char *title)
+{
+#ifdef DEBUG
+  xvt_debug_printf("heap check (%s): malloc's=%u, free's=%u", title, nbr_malloc, nbr_free);
+#else
+  NOREF(title);
+#endif
+}
+
diff --git a/xi/xiheap.h b/xi/xiheap.h
new file mode 100755
index 000000000..599c4daec
--- /dev/null
+++ b/xi/xiheap.h
@@ -0,0 +1,48 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.                  *
+*******************************************************************************/
+
+/******************************************************************
+Heap module
+******************************************************************/
+void *heap_malloc(size_t size);
+void heap_free(void *p);
+void *heap_realloc(void *p, size_t size);
+void heap_dbg(char *title);
+#define MAX_NODE_SIZE 16000
+#define HEAP_SIZE 32000
+
+#define NODE_SET_MAGIC(node) (node->size = 0xFFFF)
+#define NODE_IS_MAGIC(node) (node->size == 0xFFFF)
+
+#define NODE_MARK_ALLOCATED(node) (node->size |= 0x8000)
+#define NODE_MARK_FREE(node) (node->size &= 0x7FFF)
+#define NODE_IS_FREE(node) ( (node->size & 0x8000) == 0 )
+
+#define NODE_SET_SIZE(node, n) (node->size = (node->size & 0x8000) | (n))
+#define NODE_GET_SIZE(node) (node->size & 0x7FFF)
+
+#define PTR_IS_GLOBAL(p) ((PTR_LONG(p) & 0xFFFF) == 0)
+#define NEXT_NODE(node) ( (NODE *)((char *)node + sizeof(NODE) + NODE_GET_SIZE(node)))
+
+#define PTR_TO_NODE(p) ((NODE *)(p) - 1)
+#define NODE_TO_PTR(node) ((char *)(node + 1))
+
+typedef struct _s_node
+{
+  unsigned short size;
+} NODE;
+
+typedef struct _s_enode
+{
+  unsigned short size;    /* equal to NODE_MAGIC */
+  struct _s_node *next; /* pointer to next heap */
+} E_NODE;
+
+#define ALIGNMENT (sizeof(NODE))
+
+
+
diff --git a/xi/xil.h b/xi/xil.h
new file mode 100755
index 000000000..736f7d12a
--- /dev/null
+++ b/xi/xil.h
@@ -0,0 +1,37 @@
+#ifndef INCL_XIL
+#define INCL_XIL
+
+#include "xi.h"
+#include "xvtcm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  typedef struct
+  {
+    XVTCM_CONTROL_INFO ci;
+    XI_OBJ* itf;
+    XI_EVENT* xiev;
+  } XIL_DATA;
+
+WINDOW      XVT_CALLCONV1 xil_create XVT_CC_ARGS((int cid, int left, int top,
+                                    int right, int bottom, int prop_count,
+                                    char** prop_list, WINDOW parent_win,
+                                    int parent_rid, long parent_flags,
+                                    char* parent_class));
+XI_OBJ_DEF* XVT_CALLCONV1 xil_parse XVT_CC_ARGS((int cid, int prop_count,
+                                    char** prop_list));
+
+WINDOW      XVT_CALLCONV1 xis_create XVT_CC_ARGS((int cid, int left, int top,
+                                    int right, int bottom, int prop_count,
+                                    char** prop_list, WINDOW parent_win,
+                                    int parent_rid, long parent_flags,
+                                    char* parent_class));
+
+#ifdef __cplusplus
+}
+// End of extern "C"
+#endif
+#endif
+
diff --git a/xi/xilm.c b/xi/xilm.c
new file mode 100755
index 000000000..c307c28fd
--- /dev/null
+++ b/xi/xilm.c
@@ -0,0 +1,5806 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distribfuted, in printed or  *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+#define XI_INTERNAL
+#include "xi.h"
+#include "xitext.h"
+#include "xilm.h"
+#include "xiutils.h"
+#include "xidisply.h"
+
+/*-------------------------------------------------------------------------
+Metrics Documentation
+lmp->rct.top and lmp->rct.bottom are the top and bottom of the list, excluding the
+  horizontal scroll bar.
+lmp->rct.left is the physical left position of the list
+lmp->rct.right is the position of the physical right position of the list.  However, if the
+  list is a horizontal scrolling list, then lmp->rct.right will be beyond lmp->width.
+  It is useful for drawing using the virtual functions, but it is necessary to subtract
+  lmp->rct.left before calling the drawing functions, because the drawing functions will
+  add lmp->rct.left to the h values before drawing.
+-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------
+ROWS: REALIZED, and ALLOCATED-USED, and ALLOCATED-NOT USED.
+
+In the realized rows array, there are three types of rows.
+
+First, there are rows that are not being used at all.  These are the rows
+after lmp->nbr_realized_rows. The record handles for these rows are 0L.
+
+Second, there are rows that are allocated, and used.  These are the rows
+after 0, and before lmp->nbr_realized_rows.
+The record handles for these rows are not 0L.
+
+Third, there are rows that are allocated, and not used.  These are the rows
+after 0, and less than lmp->nbr_realized_rows.
+The record handles for these rows are not 0L.  If one of these rows is requested
+to be allocated, and the handle is not 0L, then then allocation event is not
+done.  If one of these rows is requested to be freed, and the handle is 0L,
+then the free event is not done.
+-------------------------------------------------------------------------*/
+
+/* Error codes: 20900 - 20918 */
+
+#define SELECT_CELLS_OFFSET 1
+
+#define LM_COL_ATTR(lm, col) (LMP(lm)->lm_column_data[col]->attrib)
+#define LM_CELL_TEXT(lm, row, col)  (LMP(lm)->buffer[row] + LMP(lm)->lm_column_data[col]->text_offset)
+
+#define LM_REDRAW_ATR (LM_ATR_VISIBLE | LM_ATR_ENABLED)
+#define LM_REDRAW_COL_ATR (LM_COL_ATR_ENABLED | LM_COL_ATR_RJUST |   LM_COL_ATR_PASSWORD | LM_COL_ATR_SELECTED)
+#define LM_REDRAW_ROW_ATR (LM_ROW_ATR_ENABLED | LM_ROW_ATR_SELECTED)
+
+#define LM_REDRAW_CELL_ATR (LM_CELL_ATR_SELECTED | LM_CELL_ATR_RJUST | LM_CELL_ATR_HCENTER)
+
+#define BUFLEN 256
+
+/*-------------------------------------------------------------------------
+function:   lm_adj_v
+lmp:        current lmp
+v:          to vertical coord to convert
+-------------------------------------------------------------------------*/
+#define lm_adj_v(lmp, v) (v = v + lmp->mlr.top + lmp->rrr_offset)
+
+static CBRUSH lm_white_cbrush;
+static CPEN lm_black_cpen;
+static DRAW_CTOOLS lm_normal_ctools;
+static BOOLEAN lm_tools_inited = FALSE;
+
+typedef struct {
+  BOOLEAN needs_update;
+  RCT rct;
+  RCT prct;
+} ROW_INFO;
+
+/*-------------------------------------------------------------------------
+function:   calc_last_vis
+lmp:        current lmp
+process:    calculates the last fully visible column in the list
+-------------------------------------------------------------------------*/
+void
+lm_calc_last_vis(LM_DATA *lmp)
+{
+  LM_COLUMN_DATA *column_data;
+  int l1;
+
+  if (! lmp->pixel_width)
+    lmp->last_vis = lmp->nbr_columns - 1;
+  else
+  {
+    lmp->last_vis = lmp->first_vis;
+    for (l1 = lmp->first_vis + 1; l1 < lmp->nbr_columns; ++l1)
+    {
+      column_data = lmp->lm_column_data[l1];
+      if ((column_data->x_pix_pos - lmp->delta_x + column_data->pix_width)
+          >= lmp->pixel_width)
+      {
+        lmp->last_vis = l1 - 1;
+        return;
+      }
+      lmp->last_vis = l1;
+    }
+    if (l1 == lmp->nbr_columns)
+      lmp->last_vis = l1 - 1;
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_get_col_spacing
+returns:    column spacing
+-------------------------------------------------------------------------*/
+int
+lm_get_col_spacing(void)
+{
+  return (2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET) + RULE_WIDTH_V);
+}
+
+/*-------------------------------------------------------------------------
+function:       lm_get_left_most_far_right_column
+lmp:            current lmp
+nbr_columns:    column, from which we will count back
+notes:          This function is also used when the users presses page up on the
+          horizontal scroll bar, to determine the new left most column.
+        Get the column number for the column that would be visible if the
+          list is scrolled entirely over to the right.  This is necessary
+          to compute the position of the horizontal thumb, and other reasons.
+-------------------------------------------------------------------------*/
+int
+lm_get_left_most_far_right_col(LM_DATA *lmp, int nbr_columns)
+{
+  int width, i;
+
+#if XVTWS == WMWS
+  width = lmp->pixel_width;
+#else
+  width = lmp->pixel_width + (int)xi_get_pref(XI_PREF_COLUMN_OFFSET)
+          + RULE_WIDTH_V;
+#endif
+  for (i = 0; i < min(lmp->fixed_columns, lmp->nbr_columns); ++i)
+    width -= lmp->lm_column_data[i]->pix_width + lm_get_col_spacing();
+  for (i = nbr_columns - 1; i >= lmp->fixed_columns; --i)
+  {
+    width -= lmp->lm_column_data[i]->pix_width + lm_get_col_spacing();
+    if (width <= 0)
+      break;
+  }
+  return (i + 1);
+}
+
+
+/*-------------------------------------------------------------------------
+function:       lm_get_cell_rect
+rctp:           pointer to rectangle to be filled in
+lm:             current lm
+row:            relevant row
+col:            relevant column
+inner:          if TRUE, get the inner rectangle of the cell, else get the outer
+          rectangle of the cell
+physical_rct:   if TRUE, get the physical rectangle, else get the virtual
+          rectangle
+notes:          This function is called before starting the text edit object for the cell.
+returns:        rctp
+-------------------------------------------------------------------------*/
+RCT *
+lm_get_cell_rect(RCT *rctp, LM lm, int row, int col, BOOLEAN inner, BOOLEAN physical_rct)
+{
+  LM_COLUMN_DATA *temp_lmcd;
+  int col_offset;
+  LM_DATA *lmp = LMP(lm);
+
+  col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+  temp_lmcd = lmp->lm_column_data[col];
+
+  rctp->top = lmp->pix_offsets[row];
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  rctp->bottom = rctp->top + lmp->pix_heights[row] - RULE_WIDTH_V;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  rctp->bottom = rctp->top + lmp->pix_heights[row];
+  CTOS_END;
+#endif
+
+  rctp->left = temp_lmcd->x_pix_pos;
+  rctp->right = rctp->left + temp_lmcd->pix_width + 2 *
+      (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+
+  if (inner)
+  {
+    rctp->left += col_offset;
+    rctp->right -= col_offset;
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    rctp->top += RULE_Y_OFFSET_TOP;
+    rctp->bottom -= RULE_Y_OFFSET_BOTTOM;
+    CTOS_END;
+#endif
+  }
+  if (physical_rct)
+  {
+    rctp->left += lmp->rct.left;
+    rctp->right += lmp->rct.left;
+
+    if (rctp->left >= lmp->vir_left)
+    {
+      rctp->left -= lmp->delta_x;
+      rctp->right -= lmp->delta_x;
+    }
+
+    rctp->top = rctp->top + lmp->rrr_offset + lmp->mlr.top;
+    rctp->bottom = rctp->bottom + lmp->rrr_offset + lmp->mlr.top;
+  }
+  return(rctp);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   get_row_rect
+rctp:       pointer to rectangle to be filled in
+lm:         current lm
+row:        relevant row
+returns:    rctp
+-------------------------------------------------------------------------*/
+RCT*
+lm_get_row_rect(RCT *rctp, LM lm, int row)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  rctp->top = lmp->pix_offsets[row];
+  rctp->bottom = rctp->top + lmp->pix_heights[row];
+
+  rctp->left = lmp->rct.left + BORDER_WIDTH;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  rctp->right =  lmp->rct.right - BORDER_WIDTH;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  rctp->right =  lmp->rct.right;
+  CTOS_END;
+#endif
+  if (lmp->pixel_width)
+    rctp->right = rctp->left + lmp->pixel_width;
+
+  return(rctp);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_adj_h
+lmp:        current lmp
+h:          pointer to horizontal coord to convert
+returns:    TRUE if position is visible
+-------------------------------------------------------------------------*/
+BOOLEAN
+lm_adj_h(LM_DATA *lmp, short *h)
+{
+  if (*h >= lmp->vir_left)
+  {
+    RCT r;
+
+    *h -= lmp->delta_x;
+    if (*h < lmp->vir_left)
+      return FALSE;
+    r = lmp->rct;
+    if (lmp->pixel_width)
+      r.right = r.left + lmp->pixel_width + 2 * BORDER_WIDTH;
+    return (*h <= r.right);
+  }
+  return TRUE;
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_get_list_rct
+lmp:        current lmp
+r:          pointer to rectangle to be filled in
+returns:    r
+-------------------------------------------------------------------------*/
+RCT*
+lm_get_list_rct(LM_DATA *lmp, RCT *r)
+{
+  *r = lmp->rct;
+  if (lmp->pixel_width)
+    r->right = r->left + lmp->pixel_width + 2 * BORDER_WIDTH;
+  return r;
+}
+
+/*-------------------------------------------------------------------------
+function:           lm_set_fixed_columns
+-------------------------------------------------------------------------*/
+void
+lm_set_fixed_columns( LM lm, int new_fixed_count )
+{
+  LM_DATA *lmp = (LM_DATA *)lm;
+  int col_spacing, i;
+  RCT rct_to_invalidate, rct;
+
+  if (new_fixed_count > lmp->nbr_columns)
+    new_fixed_count = lmp->nbr_columns;
+  col_spacing = lm_get_col_spacing();
+  lmp->fixed_columns = new_fixed_count;
+  lmp->first_vis = lmp->fixed_columns;
+  lmp->delta_x = 0;
+
+  /* calculate the left boundary of the virtual space for the list */
+  lmp->vir_left = lmp->rct.left + BORDER_WIDTH;
+  for (i = 0; i < min(lmp->nbr_columns, lmp->fixed_columns); ++i)
+  {
+    lmp->vir_left += lmp->lm_column_data[i]->pix_width;
+    lmp->vir_left += col_spacing;
+  }
+  lmp->list_obj->v.list->have_hsb_rct = FALSE;
+  lm_get_list_rct(lmp, &rct_to_invalidate);
+  xi_invalidate_rect(lmp->win, &rct_to_invalidate);
+  lm_set_hscroll_range((LM)lmp);
+  lm_set_hscroll_bar((LM) lmp);
+  xi_get_hsb_rect(lmp->list_obj, &rct);
+  xvt_vobj_move(lmp->list_obj->v.list->hsb_win, &rct);
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_stop_edit
+lm:         current lm
+-------------------------------------------------------------------------*/
+static void
+lm_stop_edit(LM lm, BOOLEAN do_update, int row, int column)
+{
+  LM_DATA *lmp = LMP(lm);
+  int new_row_height;
+
+  if (lmp->txt)
+  {
+    txt_hide_caret(lmp->txt);
+    txt_caret(lmp->txt, FALSE);
+    xi_tree_free((char *)lmp->txt);
+    lmp->txt = NULL;
+    new_row_height = lm_calculate_row_height(lmp, row);
+    if (new_row_height != lmp->old_row_height)
+    {
+      xvt_dwin_update(lmp->win);
+      lm_set_row_height(lm, row, new_row_height,
+          FALSE, lmp->old_row_height, TRUE);
+      xvt_dwin_update(lmp->win);
+    }
+  }
+  /*
+  if lmp->row_focus_border is TRUE, don't redraw, because old
+  focus row will be invalidated
+  */
+  if (do_update && !lmp->txt_is_invisible)
+    redraw_cell(lm, row, column, FALSE );
+  lmp->txt_is_invisible = FALSE;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_focus_cb
+lm:         current lm
+row:        relevant row
+column:     relevant column
+set:        if TRUE, start editing on specified cell
+            if FALSE, stop editing altogether
+-------------------------------------------------------------------------*/
+void lm_focus_cb( long lm, int row, int column, BOOLEAN vert_scrolled,
+                  BOOLEAN set)
+{
+  LM_DATA *lmp = (LM_DATA *)lm;
+
+  if (set)
+  {
+    if (lm_list_has_focus(lmp))
+    {
+      int     focus_row, focus_column;
+      BOOLEAN is_vert_scrolled;
+
+      lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
+      if ( lmp->txt == NULL || row != focus_row || column != focus_column
+          || vert_scrolled != is_vert_scrolled )
+      {
+        BOOLEAN remake_vis = FALSE;
+
+        if (! lmp->focus_rec)
+        {
+          lm_make_invis(lmp);
+          remake_vis = TRUE;
+        }
+        lm_set_focus_cell(lmp, row, column, vert_scrolled );
+        if (remake_vis)
+          lm_force_vis(lmp);
+      }
+    }
+    else
+    {
+    xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+      ERR_ASSERT_4, "20930",
+      20930, "lm_focus_cb: Internal Error");   
+#if 0
+    /*
+    the following line was never executed when doing coverage.  If the
+    above assert gets triggered, research, and uncomment the following line.
+      Remove after 7/31/95.
+      */
+      lm_start_edit(lm, row, column);
+#endif
+    }
+  }
+  else
+  {
+    int idx;
+    BOOLEAN found = FALSE;
+
+    lm_stop_edit(lm, TRUE, row, column);
+    if (lmp->focus_rec)
+    {
+      lmp->txt_is_invisible = FALSE;
+      for (idx = 0; idx < lmp->nbr_realized_rows; ++idx)
+      {
+        if (lmp->recs[idx] == lmp->focus_rec)
+        {
+          found = TRUE;
+          break;
+        }
+      }
+      if (found)
+      {
+        lmp->focus_rec = 0L;
+        lmp->txt_is_invisible = FALSE;
+      }
+      else
+      {
+        LM_CB_DATA lm_cb_data;
+
+        lm_cb_data.lm = (LM)lmp;
+        lm_cb_data.cb_type = LM_CB_REC_FREE;
+        lm_cb_data.cid = lmp->cid;
+        lm_cb_data.win = lmp->win;
+        lm_cb_data.v.rec_free.record = lmp->focus_rec;
+        (*lmp->lm_cb)(&lm_cb_data);
+        lm_allocate_rec_info(lmp, lmp->nbr_realized_rows - 1);
+        --lmp->nbr_realized_rows;
+        lmp->focus_rec = 0L;
+        lmp->txt_is_invisible = FALSE;
+      }
+    }
+  }
+
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_delete
+lm:         current lm
+notes:      do not call this function in response to E_KILL_WINDOW.
+-------------------------------------------------------------------------*/
+void
+lm_delete(LM lm)
+{
+  RCT r;
+  LM_DATA *lmp = LMP(lm);
+  int     focus_row, focus_column;
+  BOOLEAN v_scrolled;
+
+  lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled );
+  lm_stop_edit(lm, TRUE, focus_row, focus_column);
+  lm_remove_all_rows( lmp, TRUE );
+  lm_get_list_rct(lmp, &r);
+  xi_invalidate_rect(lmp->win, &r);
+  xi_tree_free((char *)lm);
+}
+
+/*-------------------------------------------------------------------------
+function:   calc_x_pix_pos
+lm:         current lm
+lcdata:     column data pointer
+position:   position of column
+-------------------------------------------------------------------------*/
+void
+calc_x_pix_pos(LM lm, LM_COLUMN_DATA *lcdata, int position)
+{
+  LM_DATA *lmp = LMP(lm);
+  LM_COLUMN_DATA *lmcd;
+
+  if (position)
+    lmcd = lmp->lm_column_data[position - 1];
+  lcdata->x_pix_pos = (! position) ? BORDER_WIDTH :
+      lmcd->x_pix_pos + lmcd->pix_width + lm_get_col_spacing();
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_invalidate_rect
+lmp:        current lmp
+rctp:       rectangle to invalidate
+adj_h:      adjust the horizontal coords
+-------------------------------------------------------------------------*/
+void
+lm_invalidate_rect(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_h)
+{
+  RCT r;
+
+  r = *rctp;
+  if (adj_h)
+  {
+    lm_adj_h(lmp, &r.left);
+    lm_adj_h(lmp, &r.right);
+  }
+
+  lm_adj_v(lmp, r.top);
+  lm_adj_v(lmp, r.bottom);
+
+  xi_invalidate_rect(lmp->win, &r);
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_invalidate_rect2
+lmp:        current lmp
+rctp:       rectangle to invalidate
+adj_left:   if TRUE, adjust left of rctp
+-------------------------------------------------------------------------*/
+void
+lm_invalidate_rect2(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_left)
+{
+  RCT r;
+
+  r = *rctp;
+  if (adj_left)
+    lm_adj_h(lmp, &r.left);
+  xi_invalidate_rect(lmp->win, &r);
+}
+
+
+/*-------------------------------------------------------------------------
+function:           lm_get_fixed_columns
+-------------------------------------------------------------------------*/
+int lm_get_fixed_columns( LM lm )
+{
+  return ((LM_DATA*)lm)->fixed_columns;
+}
+
+
+void
+lm_local_hscroll(LM lm, int nbr_columns)
+{
+  LM_DATA *lmp;
+  XI_LIST_DATA *list_data;
+  XI_OBJ *other_list;
+
+  lmp = (LM_DATA *)lm;
+  list_data = lmp->list_obj->v.list;
+  lm_hscroll(lm, nbr_columns, 0);
+  if (list_data->horz_sync_list &&
+      ! list_data->scrolling_in_progress)
+  {
+    list_data->scrolling_in_progress = TRUE;
+    other_list = xi_get_obj(lmp->itf_obj,
+        list_data->horz_sync_list);
+    if (other_list)
+      lm_hscroll(other_list->v.list->lm, nbr_columns, 0);
+    list_data->scrolling_in_progress = FALSE;
+  }
+}
+
+
+void lm_make_vis(LM_DATA *lmp)
+{
+  int     focus_row, focus_column;
+  BOOLEAN v_scrolled;
+  BOOLEAN is_hscrolled;
+
+  if (! lm_list_has_focus(lmp))
+    return;
+
+  lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+  if (v_scrolled)
+    return;
+  if (lm_is_cell_visible(lmp, focus_row, focus_column, TRUE, &is_hscrolled))
+  {
+    TXT_DATA *txt;
+    LM_COLUMN_DATA *column_data;
+    DRAW_CTOOLS ct;
+    RCT cell_r;
+    unsigned long attrib, cell_attrib;
+    LM_CELL_DATA *cell_data;
+    BOOLEAN button;
+    BOOLEAN button_on_left;
+    RCT mr;
+    COLOR color;
+    int leading, ascent, descent, char_width;
+    BOOLEAN text_was_invisible;
+
+    if (lmp->focus_rec && lmp->txt_is_invisible && ! is_hscrolled)
+    {
+      int cnt;
+
+      /*
+      the following loop should *always* find a row, because
+      lmp->txt_is_invisible is TRUE, and the cell is now visible.
+      */
+      for (cnt = 0; cnt < lmp->nbr_realized_rows; ++cnt)
+      {
+        if (lmp->recs[cnt] == lmp->focus_rec)
+        {
+          lm_set_focus_cell(lmp, cnt, focus_column, FALSE );
+          focus_row = cnt;
+          break;
+        }
+      }
+    }
+    mr = lmp->mlr;
+    if (lmp->pixel_width)
+      mr.right = mr.left + lmp->pixel_width + BORDER_WIDTH;
+    column_data = lmp->lm_column_data[focus_column];
+    attrib = column_data->attrib;
+    cell_data = &lmp->cell_data[focus_row][focus_column];
+    button = cell_data->button;
+    button_on_left = cell_data->button_on_left;
+    cell_attrib = cell_data->attrib &
+        (XI_ATR_HCENTER | XI_ATR_RJUST);
+    if (cell_attrib)
+    {
+      attrib &= ~(XI_ATR_HCENTER | XI_ATR_RJUST);
+      attrib |= cell_attrib;
+    }
+    txt = lmp->txt = (TXT_DATA *)xi_tree_malloc(sizeof(TXT_DATA), lmp);
+    lm_get_cell_rect(&cell_r, (LM)lmp, focus_row, focus_column, FALSE, TRUE);
+    if (button)
+    {
+      RCT r2;
+
+      r2 = cell_r;
+      xi_inflate_rect(&r2, 1);
+      if (button_on_left)
+        cell_r.left = r2.left + lmp->pix_row_spacing;
+      else
+        cell_r.right = r2.right - lmp->pix_row_spacing;
+    }
+    txt->parent_obj = lmp->list_obj;
+    txt->attrib = attrib | (TXT_ATR_ENABLED | TXT_ATR_VISIBLE);
+    txt->attrib &= ~XI_ATR_VCENTER;
+    txt->inside_only = TRUE;
+    txt->attrib &= ~TXT_ATR_BORDER;
+    if (lmp->min_cell_height && (! column_data->wrap_text))
+      txt->attrib |= XI_ATR_VCENTER;
+    txt->text = lmp->buffer[focus_row] + column_data->text_offset;
+    txt->text_size = column_data->text_size;
+    txt->auto_tab = column_data->auto_tab;
+    cell_data = &(lmp->cell_data[focus_row][focus_column]);
+    if (cell_data->font)
+      txt->font = cell_data->font;
+    else
+      txt->font = lmp->font;
+    xi_get_font_metrics_font(txt->font, &leading, &ascent, &descent, &char_width);
+    if (column_data->vertical_align_center)
+    {
+      int height, delta, new_top, new_bottom;
+
+      height = leading + ascent + descent;
+      delta = (cell_r.bottom - cell_r.top - height) / 2;
+      new_top = cell_r.top + delta;
+      new_bottom = cell_r.bottom - delta;
+      cell_r.top = max(cell_r.top, new_top);
+      cell_r.bottom = min(cell_r.bottom, new_bottom);
+    }
+    else if (column_data->vertical_align_bottom)
+    {
+      int new_top;
+
+      new_top = cell_r.bottom - (leading + ascent + descent) - 3;
+      cell_r.top = max(cell_r.top, new_top);
+    }
+    else
+    {
+      int new_bottom;
+#if XVTWS != WMWS
+      new_bottom = cell_r.top + leading + ascent + descent + 4;
+#else
+      new_bottom = cell_r.top + leading + ascent + descent;
+#endif
+      cell_r.bottom = min(cell_r.bottom, new_bottom);
+    }
+    txt->rct = cell_r;
+#if XVTWS != WMWS
+    txt->rct.top++;
+    txt->rct.bottom--;
+#endif
+    txt->back_color = lmp->active_back_color;
+    txt->fore_color = lmp->active_color;
+    txt->win = lmp->win;
+    xvt_app_get_default_ctools(&ct);
+    ct.pen = hollow_cpen;
+    ct.fore_color = lmp->enabled_color;
+    ct.brush.color = lmp->back_color;
+    xi_set_draw_ctools(lmp->win, &ct);
+    xi_set_xvt_font(lmp->win, lmp->font, FALSE);
+    text_was_invisible = lmp->txt_is_invisible;
+    lmp->old_row_height = lmp->pix_heights[focus_row];
+    lmp->txt_is_invisible = FALSE;
+    lmp->focus_rec = 0L;
+    redraw_cell((LM)lmp, focus_row, focus_column, FALSE );
+    color = lmp->cell_data[focus_row][focus_column].back_color;
+    if (color)
+      txt->back_color = color;
+    txt_reset(txt);
+    if (text_was_invisible)
+    {
+      txt_set_text(txt, lmp->focus_cell_text);
+      txt_set_sel(txt, lmp->focus_cell_ip1, lmp->focus_cell_ip2);
+    }
+    else
+    {
+      if (lmp->have_mouse)
+      {
+        if ((column_data->attrib & (LM_COL_ATR_AUTOSELECT | LM_COL_ATR_READONLY)) ==
+            (LM_COL_ATR_AUTOSELECT | LM_COL_ATR_READONLY))
+          txt_set_sel(txt, 0, SHRT_MAX);
+        if ((column_data->attrib & LM_COL_ATR_AUTOSELECT) && xi_get_pref(XI_PREF_AUTOSEL_ON_MOUSE))
+          txt_set_sel(txt, 0, SHRT_MAX);
+      }
+      else
+      {
+        if (column_data->attrib & LM_COL_ATR_AUTOSELECT)
+          txt_set_sel(txt, 0, SHRT_MAX);
+        else
+          txt_set_sel(txt, 0, 0);
+      }
+    }
+    txt_caret(txt, TRUE);
+  }
+  else
+  {
+    if (lmp->focus_rec && is_hscrolled && lmp->txt_is_invisible)
+    {
+      int cnt;
+
+      /*
+      the following loop should *always* find a row, because
+      the only reason the cell is not visible is because the
+      list is horizontally scrolled.
+      */
+      for (cnt = 0; cnt < lmp->nbr_realized_rows; ++cnt)
+      {
+        if (lmp->recs[cnt] == lmp->focus_rec)
+        {
+          lm_set_focus_cell(lmp, cnt, focus_column, FALSE );
+          break;
+        }
+      }
+    }
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:   do_lm_cb_text
+lm:         current lm
+row:      row
+col:      column
+-------------------------------------------------------------------------*/
+void
+do_lm_cb_text(LM_DATA *lmp, int row, int col, BOOLEAN preserve_focus )
+{
+  LM_CELL_DATA *cell_data;
+  LM_CB_DATA lm_cb_data;
+  LM_COLUMN_DATA *lm_column_data;
+
+  lm_cb_data.lm = (LM)lmp;
+  lm_cb_data.cb_type = LM_CB_TEXT;
+  lm_cb_data.cid = lmp->cid;
+  lm_cb_data.win = lmp->win;
+  lm_cb_data.row = (unsigned char)row;
+  lm_cb_data.rec = lmp->recs[row];
+  lm_cb_data.column = (unsigned char)col;
+  lm_column_data = lmp->lm_column_data[col];
+  lm_cb_data.v.text.text = lmp->buffer[row] + lm_column_data->text_offset;
+  lm_cb_data.v.text.len = lm_column_data->text_size;
+  lm_cb_data.v.text.text[0] = '\0';
+  lm_cb_data.v.text.font = NULL;
+  lm_cb_data.v.text.font_id = 0L;
+  cell_data = &(lmp->cell_data[row][col]);
+  lm_cb_data.v.text.icon_rid = cell_data->icon_rid;
+  lm_cb_data.v.text.attrib = cell_data->attrib;
+  lm_cb_data.v.text.color = 0;
+  lm_cb_data.v.text.back_color = 0;
+  (*lmp->lm_cb)(&lm_cb_data);
+  cell_data->valid_data = TRUE;
+  cell_data->icon_rid = lm_cb_data.v.text.icon_rid;
+  cell_data->attrib = lm_cb_data.v.text.attrib;
+  cell_data->color = lm_cb_data.v.text.color;
+  cell_data->back_color = lm_cb_data.v.text.back_color;
+  if (lmp->txt_is_invisible) /* update the focus_cell_text */
+  {
+    XI_OBJ* focus_obj;
+
+    focus_obj = lmp->itf_obj->v.itf->focus_obj;
+
+    if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
+        focus_obj->type == XIT_CELL)
+    {
+      XI_CELL_DATA* focus_cell;
+      focus_cell = &focus_obj->v.cell;
+      if ( focus_cell->row == row && focus_cell->column == col )
+      {
+        if (preserve_focus && lmp->focus_cell_text != NULL)
+          strncpy( lm_cb_data.v.text.text, lmp->focus_cell_text,
+                  lm_column_data->text_size - 1 );
+        else
+        {
+          lm_set_focus_text( lmp, lm_cb_data.v.text.text );
+          lmp->focus_cell_ip1 = 0;
+          lmp->focus_cell_ip2 = strlen( lmp->focus_cell_text );
+        }
+      }
+    }
+  }
+  else
+  {
+    XI_OBJ* focus_obj;
+
+    focus_obj = lmp->itf_obj->v.itf->focus_obj;
+
+    if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
+        focus_obj->type == XIT_CELL)
+    {
+      XI_CELL_DATA* focus_cell;
+      focus_cell = &focus_obj->v.cell;
+      if ( focus_cell->row == row && focus_cell->column == col )
+      {
+      if (lmp->txt)
+    {
+          lm_set_focus_text( lmp, lm_cb_data.v.text.text );
+          lmp->focus_cell_ip1 = 0;
+          lmp->focus_cell_ip2 = strlen( lmp->focus_cell_text );
+          txt_set_text(lmp->txt, lm_cb_data.v.text.text);
+    }
+      }
+    }
+  }
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  /* cell buttons not supported for XVT/CH */
+  cell_data->button = lm_cb_data.v.text.button;
+  cell_data->button_on_left = lm_cb_data.v.text.button_on_left;
+  cell_data->button_on_focus = lm_cb_data.v.text.button_on_focus;
+  cell_data->button_icon_rid = lm_cb_data.v.text.button_icon_rid;
+  CTOS_END;
+#endif
+  if (lm_cb_data.v.text.font_id)
+  {
+    XVT_FNTID old_font_id;
+    if (! cell_data->font)
+      cell_data->font = (FONT_OBJ *)
+        xi_tree_malloc(sizeof(FONT_OBJ), lmp);
+    old_font_id = *cell_data->font;
+    *cell_data->font = xi_create_copy_font_id(lmp->itf_obj,
+      lm_cb_data.v.text.font_id, old_font_id);
+  }
+  else
+  {
+  if (cell_data->font)
+  {
+    xi_free_font_id(lmp->itf_obj, *cell_data->font);
+    xi_tree_free(cell_data->font);
+    cell_data->font = NULL;
+  }
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_get_attrib
+lm:         current lm
+lm_part:    may be LM_LIST, LM_ROW, LM_COLUMN, or LM_CELL
+returns:    attribute
+notes:      all rows are
+-------------------------------------------------------------------------*/
+unsigned long lm_get_attrib( LM lm, LM_PART lm_part, int idx, int idx2,
+                            BOOLEAN v_scrolled)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  switch (lm_part)
+  {
+    case LM_LIST:
+      return(lmp->attrib);
+    case LM_ROW:
+      return(lmp->row_attribs[idx]);
+    case LM_COLUMN:
+      return(lmp->lm_column_data[idx]->attrib);
+    case LM_CELL:
+    {
+      LM_CELL_DATA *cell_data;
+
+      cell_data = &lmp->cell_data[idx][idx2];
+      if (! cell_data->valid_data)
+      {
+        do_lm_cb_text(lmp, idx, idx2, TRUE );
+      }
+      if (v_scrolled)
+        return lmp->focus_rec_attrib;
+      return(cell_data->attrib);
+    }
+  }
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20907",
+    20907, "lm_get_attrib: Invalid LM part");   
+  return 0L;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_get_buf_size
+lm:         current lm
+part:       must be LM_COLUMN
+idx:        column number
+-------------------------------------------------------------------------*/
+int
+lm_get_buf_size(LM lm, LM_PART part, int idx)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  NOREF(part);
+  return(lmp->lm_column_data[idx]->text_size);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_get_cid
+lm:         current lm
+returns:    control id of list
+-------------------------------------------------------------------------*/
+int
+lm_get_cid(LM lm)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  return lmp->cid;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_get_rect
+lm:         current lm
+part:       may be LM_LIST, LM_COLUMN, or LM_ROW
+idx:        if LM_LIST, not used
+      if LM_COLUMN, column number
+      if LM_ROW, row number
+rct:        rectangle to be filled in
+returns:    rct
+-------------------------------------------------------------------------*/
+RCT *
+lm_get_rect(LM lm, LM_PART part, int idx, RCT *rct)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  switch (part)
+  {
+  case LM_LIST:
+    *rct = lmp->rct;
+    if (lmp->pixel_width)
+      rct->right = rct->left + lmp->pixel_width + 2 * BORDER_WIDTH;
+    break;
+  case LM_COLUMN:
+    {
+      LM_COLUMN_DATA *column_data;
+
+      column_data = lmp->lm_column_data[idx];
+      if (idx >= lmp->fixed_columns)
+        rct->left = lmp->rct.left + column_data->x_pix_pos - lmp->delta_x;
+      else
+        rct->left = lmp->rct.left + column_data->x_pix_pos;
+      rct->right = rct->left + column_data->pix_width +
+          2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+      rct->top = lmp->rct.top;
+      rct->bottom = lmp->rct.bottom;
+      break;
+    }
+  case LM_ROW:
+    {
+      int con;
+
+      con = lmp->rrr_offset + lmp->mlr.top;
+
+      rct->top = lmp->pix_offsets[idx] + con;
+      rct->bottom = rct->top + lmp->pix_heights[idx];
+
+      rct->left = lmp->rct.left;
+      rct->right = lmp->rct.right;
+      break;
+    }
+  }
+  return rct;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_get_text
+lm:         current lm
+s:          string to be filled in
+      NULL is valid
+len:        size of string to be filled in
+      if the length of the text is longer than the size of the buffer s,
+      then len-1 characters will be copied, and s[len-1] will be set
+      to '\0'
+row:        row number of cell
+column:     column number of cell
+returns:    s
+-------------------------------------------------------------------------*/
+char* lm_get_text( LM lm, char *s, int len, int row, int column,
+                  BOOLEAN v_scrolled )
+{
+  LM_DATA *lmp = LMP(lm);
+  char *b;
+
+  if (row == LM_HEADING_TEXT)
+    b = lmp->lm_column_data[column]->heading_text;
+  else if (v_scrolled)
+    b = lmp->focus_cell_text;
+  else
+  {
+    LM_CELL_DATA *cell_data;
+
+    cell_data = &lmp->cell_data[row][column];
+    if (! cell_data->valid_data)
+      do_lm_cb_text(lmp, row, column, TRUE );
+    b = LM_CELL_TEXT(lm, row, column);
+  }
+  if (s)
+  {
+    tgstrncpy(s, b, len);
+    return s;
+  }
+  else
+    return b;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_get_sel
+lm:         current lm
+c1:         pointer to integer to contain selection start
+c2:         pointer to integer to contain selection stop
+-------------------------------------------------------------------------*/
+void
+lm_get_sel(LM lm, int *c1, int *c2)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  if (lm_list_has_focus(lmp) && lmp->txt)
+  {
+    *c1 = lmp->txt->selstart;
+    *c2 = lmp->txt->selstop;
+  }
+  else
+    *c1 = *c2 = 0;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_invalidate_rows_internal
+lm:         current lm
+row_start:  starting row
+row_end:    ending row
+redraw:     if TRUE, then redraw the rows
+column:     if -1, then do for all columns
+      if set, then do for a specific column
+-------------------------------------------------------------------------*/
+void
+lm_invalidate_rows_internal( LM lm, int row_start, int row_end,
+                            BOOLEAN redraw, int column,
+                            BOOLEAN preserve_focus_text )
+{
+  int row, col;
+  RCT rct1, rct2;
+  LM_DATA *lmp = LMP(lm);
+
+  row_end = min(row_end, lmp->nbr_realized_rows - 1);
+  if (row_start > row_end || row_start < 0)
+    return;
+  for (row = row_start; row <= row_end; row++)
+  {
+    for (col = (column == -1) ? 0 : column;
+        col < ((column == -1) ? (lmp->nbr_columns) : (column + 1));
+        col++)
+    {
+      if (xi_get_pref(XI_PREF_OPTIMIZE_CELL_REQUESTS))
+      {
+        LM_CELL_DATA *cell_data;
+        cell_data = &(lmp->cell_data[row][col]);
+        cell_data->valid_data = FALSE;
+      }
+      else
+      {
+        do_lm_cb_text(lmp, row, col, preserve_focus_text );
+    }
+  }
+  }
+  if (redraw)
+  {
+    if( (column == -1) && (row_start == 0) &&
+        (row_end == lmp->nbr_realized_rows - 1) ){
+      lm_get_row_rect(&rct1, lm, row_start);
+      lm_get_row_rect(&rct2, lm, row_end);
+      rct1.bottom = rct2.bottom;
+      lm_invalidate_rect(lmp, &rct1, FALSE);
+    }else{
+      int col_start, col_end;
+      if( column == -1 ){
+        col_start = 0;
+        col_end = lmp->nbr_columns - 1;
+      }else
+        col_start = col_end = column;
+      draw_cell_range( lmp, row_start, row_end, col_start,
+          col_end, FALSE);
+    }
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_invalidate_rows
+lm:         current lm
+row_start:  starting row
+row_end:    ending row
+redraw:     if TRUE, then redraw the rows
+-------------------------------------------------------------------------*/
+void
+lm_invalidate_rows(LM lm, int row_start, int row_end, BOOLEAN redraw)
+{
+  lm_invalidate_rows_internal(lm, row_start, row_end, redraw, -1, TRUE );
+}
+
+
+/*-------------------------------------------------------------------------
+function:   find_selection
+-------------------------------------------------------------------------*/
+static int find_selection( LM_DATA* lmp )
+{
+  int row_num;
+  for ( row_num = 0; row_num < lmp->nbr_realized_rows; row_num++ )
+    if ( lm_get_attrib( (LM)lmp, LM_ROW, row_num, 0, FALSE )
+        & LM_ROW_ATR_SELECTED )
+      return row_num;
+  return -1;
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_set_attrib
+lm:         current lm
+lm_part:    must be LM_LIST, LM_COLUMN, LM_ROW, or LM_CELL
+idx:        if LM_LIST, not used
+      if LM_COLUMN, column number
+      if LM_ROW, row number
+      if LM_CELL, row number
+idx2:       if LM_LIST, not used
+      if LM_COLUMN, not used
+      if LM_ROW, not used
+      if LM_CELL, column number
+attrib:     attribute to set
+half_baked: if set, don't redraw
+-------------------------------------------------------------------------*/
+void lm_set_attrib( LM lm, LM_PART lm_part, int idx, int idx2,
+                    BOOLEAN v_scrolled, unsigned long attrib, int half_baked)
+{
+  unsigned long do_redraw;
+  LM_DATA *lmp = LMP(lm);
+
+  switch (lm_part)
+  {
+  case LM_LIST:
+    {
+      RCT r;
+
+      lmp->attrib = attrib;
+      xi_get_rect(lmp->list_obj, &r);
+      r.right += 10;
+      r.bottom += 4;
+      xi_invalidate_rect(lmp->win, &r);
+      break;
+    }
+  case LM_COLUMN:
+    {
+      LM_COLUMN_DATA *column_data;
+      RCT rct;
+
+      column_data = lmp->lm_column_data[idx];
+      do_redraw = ((column_data->attrib ^ attrib) & LM_REDRAW_COL_ATR);
+      column_data->attrib = attrib;
+      if (do_redraw)
+      {
+        int focus_row, focus_column;
+        BOOLEAN is_vert_scrolled;
+
+        lm_get_rect(lm, LM_COLUMN, idx, &rct);
+        xi_invalidate_rect(lmp->win, &rct);
+        lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
+        if ((! is_vert_scrolled) && (focus_column == idx) && (lmp->txt))
+          txt_redraw(lmp->txt, FALSE);
+      }
+      break;
+    }
+  case LM_ROW:
+    {
+      unsigned long old_attrib;
+
+      do_redraw = ((lmp->row_attribs[idx] ^ attrib) & LM_REDRAW_ROW_ATR);
+      old_attrib = lmp->row_attribs[idx];
+      if ( lmp->single_select && (attrib & XI_ATR_SELECTED))
+      {
+        int old_row;
+
+        old_row = find_selection( lmp );
+        if (old_row != -1 && old_row != idx)
+          lm_set_attrib( lm, LM_ROW, old_row, 0, FALSE,
+                        lmp->row_attribs[old_row] & ~XI_ATR_SELECTED,
+                        half_baked );
+      }
+      lmp->row_attribs[idx] = attrib;
+      if (! half_baked && do_redraw)
+      {
+        if ((old_attrib & XI_ATR_SELECTED) != (attrib & XI_ATR_SELECTED))
+        {
+          int focus_row, focus_column;
+          BOOLEAN is_vert_scrolled;
+
+          lm_redraw_row(lmp, idx, FALSE );
+          lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
+          if ((! is_vert_scrolled) && (focus_row == idx) && (lmp->txt))
+            txt_redraw(lmp->txt, FALSE);
+        }
+        else
+        {
+          RCT r;
+
+          lm_get_row_rect(&r, lm, idx);
+          xi_set_clip(lmp->win, NULL);
+          lm_invalidate_rect(lmp, &r, FALSE);
+        }
+      }
+      break;
+    }
+  case LM_CELL:
+    {
+      unsigned long old_attrib;
+      LM_CELL_DATA *cell_data;
+
+      cell_data = &lmp->cell_data[idx][idx2];
+      if (! cell_data->valid_data)
+        return;
+      if (v_scrolled)
+        lmp->focus_rec_attrib = attrib;
+      else
+      {
+        old_attrib = lmp->cell_data[idx][idx2].attrib;
+        do_redraw = ((old_attrib ^ attrib) & LM_REDRAW_CELL_ATR);
+        cell_data->attrib = attrib;
+        if (! half_baked && do_redraw)
+        {
+          int focus_row, focus_column;
+          BOOLEAN is_vert_scrolled;
+
+          redraw_cell(lm, idx, idx2, FALSE );
+          lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
+          if ((! is_vert_scrolled) && (focus_row == idx) && (focus_column == idx2) && (lmp->txt))
+            txt_redraw(lmp->txt, FALSE);
+        }
+      }
+    }
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_set_color
+lm:         current lm
+part:       must be LM_ROW, or LM_CELL
+idx:        if LM_ROW, row number
+            if LM_CELL, row number
+idx2:       if LM_ROW, not used
+            if LM_CELL, column number
+color:      color to set
+half_baked: if set, don't redraw
+-------------------------------------------------------------------------*/
+void lm_set_color( LM lm, LM_PART part, int idx, int idx2, BOOLEAN v_scrolled,
+                  COLOR color, BOOLEAN half_baked)
+{
+  BOOLEAN do_redraw;
+  LM_DATA *lmp = LMP(lm);
+
+  switch (part)
+  {
+  case LM_ROW:
+    do_redraw = (color != lmp->row_colors[idx]);
+    lmp->row_colors[idx] = color;
+    if (! half_baked && do_redraw)
+    {
+      RCT r;
+
+      lm_get_row_rect(&r, lm, idx);
+      lm_invalidate_rect(lmp, &r, FALSE);
+    }
+    break;
+  case LM_CELL:
+  {
+    LM_CELL_DATA *cell_data;
+
+    cell_data = &lmp->cell_data[idx][idx2];
+    if (! cell_data->valid_data)
+      return;
+    if (v_scrolled)
+      lmp->focus_rec_color = color;
+    else
+      cell_data->color = color;
+    break;
+  }
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_draw_rect
+lmp:        current lmp
+rctp:       rectangle to draw
+-------------------------------------------------------------------------*/
+static void
+lm_draw_rect(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_v)
+{
+  RCT r;
+  BOOLEAN leftb, rightb;
+
+  r = *rctp;
+  r.left += lmp->rct.left;
+  r.right += lmp->rct.left;
+
+  if (adj_v)
+  {
+    lm_adj_v(lmp, r.top);
+    lm_adj_v(lmp, r.bottom);
+  }
+
+  leftb = lm_adj_h(lmp, &r.left);
+  rightb = lm_adj_h(lmp, &r.right);
+  if ( ! leftb && ! rightb )
+    return;
+  xi_draw_rect(lmp->win, &r);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_draw_3d_rect
+lmp:        current lmp
+rctp:       rectangle
+well:       or platform
+depth:      in pixels
+-------------------------------------------------------------------------*/
+static void
+lm_draw_3d_rect(LM_DATA *lmp, RCT *rctp, BOOLEAN well, int depth, BOOLEAN adj_v)
+{
+  RCT r;
+  BOOLEAN left, right;
+
+  r = *rctp;
+
+  r.left += lmp->rct.left;
+  r.right += lmp->rct.left;
+
+  if (adj_v)
+  {
+    lm_adj_v(lmp, r.top);
+    lm_adj_v(lmp, r.bottom);
+  }
+
+  left = lm_adj_h(lmp, &r.left);
+  right = lm_adj_h(lmp, &r.right);
+  if (! left && ! right)
+    return;
+  xi_draw_3d_rect(lmp->win, &r, well, depth, 0L, 0L, 0L);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_draw_icon
+lmp:        current lmp
+left:       h position
+top:        v position
+icon_rid:   resource id
+vir_clip:   virtual clip rectangle
+phys_rct:
+fore_color: desired colors if icons
+back_color:
+-------------------------------------------------------------------------*/
+static void
+lm_draw_icon(LM_DATA *lmp, int left, int top, int icon_rid, RCT *vir_clip,
+RCT *phys_rct, BOOLEAN adj_v, COLOR fore_color, COLOR back_color)
+{
+  RCT crct, r;
+  short sleft;
+  BOOLEAN leftb, rightb;
+
+  left += lmp->rct.left;
+  r = *vir_clip;
+
+  r.left += lmp->rct.left;
+  r.right += lmp->rct.left;
+
+  if (adj_v)
+  {
+    lm_adj_v(lmp, r.top);
+    lm_adj_v(lmp, r.bottom);
+  }
+
+  leftb = lm_adj_h(lmp, &r.left);
+  rightb = lm_adj_h(lmp, &r.right);
+  if ( ! leftb && ! rightb )
+    return;
+  if (adj_v)
+    lm_adj_v(lmp, top);
+  xi_rect_intersect(&crct, &r, phys_rct);
+  xi_set_clip(lmp->win, &crct);
+  sleft = left;
+  if (lm_adj_h(lmp, &sleft))
+    xi_draw_icon(lmp->win, sleft, top, icon_rid, fore_color, back_color);
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_move_to
+lmp:        current lmp
+p:          point
+-------------------------------------------------------------------------*/
+void
+lm_move_to(LM_DATA *lmp, PNT p, BOOLEAN adj_v, BOOLEAN adj_h)
+{
+
+  if (adj_h)
+  {
+    p.h += lmp->rct.left;
+    lm_adj_h(lmp, &p.h);
+  }
+
+  if (adj_v)
+    lm_adj_v(lmp, p.v);
+
+  xi_move_to(lmp->win, p);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_draw_line
+lmp:        current lmp
+p:          point
+-------------------------------------------------------------------------*/
+void
+lm_draw_line(LM_DATA *lmp, PNT p, BOOLEAN adj_v, BOOLEAN adj_h)
+{
+  if (adj_h)
+  {
+    p.h += lmp->rct.left;
+    if (lm_adj_h(lmp, &p.h))
+    {
+      if (adj_v)
+        lm_adj_v(lmp, p.v);
+      xi_draw_line(lmp->win, p);
+    }
+  }
+  else
+  {
+    if (adj_v)
+      lm_adj_v(lmp, p.v);
+    xi_draw_line(lmp->win, p);
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:   redraw_cell_button
+lmp:        current lmp
+row:
+col:                 0
+clip_rct:   clip rectangle
+down:       if TRUE, then button is depressed
+-------------------------------------------------------------------------*/
+static void near
+redraw_cell_button(LM_DATA *lmp, int row, int col, RCT *clip_rct,
+BOOLEAN down, BOOLEAN clear_button)
+{
+  RCT r, outer_rct, col_rct, clip_rect;
+  int cell_btn_icon_x, cell_btn_icon_y;
+  LM_CELL_DATA *cell_data;
+  BOOLEAN button_on_left;
+  int button_icon_rid;
+  LM_COLUMN_DATA *column_data;
+  PNT p;
+  DRAW_CTOOLS ct;
+  RCT actual_rct;
+  int actual_r;
+
+  actual_rct = lmp->rct;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  if (lmp->pixel_width)
+    actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
+  else
+    actual_r = lmp->rct.right;
+  actual_rct.right = actual_r - BORDER_WIDTH;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  if (lmp->pixel_width)
+    actual_r = lmp->rct.left + lmp->pixel_width;
+  else
+    actual_r = lmp->rct.right;
+  actual_rct.right = actual_r;
+  CTOS_END;
+#endif
+  column_data = lmp->lm_column_data[col];
+  col_rct.left = column_data->x_pix_pos;
+  col_rct.right = col_rct.left + column_data->pix_width +
+      2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+  col_rct.top = clip_rct->top;
+  col_rct.bottom = clip_rct->bottom;
+  cell_data = &lmp->cell_data[row][col];
+  button_on_left = cell_data->button_on_left;
+  button_icon_rid = cell_data->button_icon_rid;
+  lm_get_cell_rect(&outer_rct, (LM)lmp, row, col, FALSE, FALSE);
+  r = outer_rct;
+  xi_inflate_rect(&r, 1);
+  if (button_on_left)
+  {
+    r.right = r.left + lmp->pix_row_spacing;
+    p.h = r.right - 1;
+  }
+  else
+  {
+    r.left = r.right - lmp->pix_row_spacing;
+    p.h = r.left;
+  }
+  xi_set_cpen(lmp->win, &black_cpen);
+  xi_set_draw_mode(lmp->win, M_COPY);
+  clip_rect = col_rct;
+  clip_rect.left += lmp->rct.left;
+  clip_rect.right += lmp->rct.left;
+
+  lm_adj_h(lmp, &clip_rect.left);
+  lm_adj_h(lmp, &clip_rect.right);
+  xi_rect_intersect(&clip_rect, &clip_rect, &lmp->mlr);
+  xi_rect_intersect(&clip_rect, &clip_rect, &actual_rct);
+  xi_set_clip(lmp->win, &clip_rect);
+  if (clear_button)
+  {
+    if (lmp->no_horz_lines)
+    {
+      /* if there is a button below, then decrement r.bottom */
+      int nr;
+      LM_CELL_DATA *cd;
+
+      nr = row;
+      cd = &lmp->cell_data[nr + 1][col];
+      if (row < lmp->nbr_realized_rows - 1 &&
+          cd->button &&
+          cd->button_on_left == lmp->cell_data[nr][col].button_on_left &&
+          (! cd->button_on_focus))
+        r.bottom--;
+
+      xi_set_cpen(lmp->win, &hollow_cpen);
+      xi_set_cbrush(lmp->win, &white_cbrush);
+      lm_draw_rect(lmp, &r, TRUE);
+    }
+    return;
+  }
+  if (lmp->no_horz_lines || lmp->no_vert_lines)
+    lm_draw_rect(lmp, &r, TRUE);
+  else
+  {
+    p.v = r.top;
+    lm_move_to(lmp, p, TRUE, TRUE);
+    p.v = r.bottom;
+  lm_draw_line(lmp, p, TRUE, TRUE);
+  }
+  xi_inflate_rect(&r, -1);
+  lm_draw_3d_rect(lmp, &r, down, 2, TRUE);
+  xi_inflate_rect(&r, -2);
+  cell_btn_icon_x = (int)xi_get_pref(XI_PREF_CELL_BTN_ICON_X);
+  cell_btn_icon_y = (int)xi_get_pref(XI_PREF_CELL_BTN_ICON_Y);
+  r.left = max(r.left, col_rct.left);
+  r.right = min(r.right, col_rct.right);
+  xi_get_draw_ctools(lmp->win, &ct);
+  ct.fore_color = lmp->enabled_color;
+  ct.back_color = xi_get_pref(XI_PREF_COLOR_CTRL);
+  ct.opaque_text = TRUE;
+  if (lmp->row_colors[row])
+    ct.fore_color = lmp->row_colors[row];
+  if (cell_data->color)
+    ct.fore_color = cell_data->color;
+  xi_set_draw_ctools(lmp->win, &ct);
+  lm_draw_icon(lmp, r.left + cell_btn_icon_x, r.top + cell_btn_icon_y + down,
+        button_icon_rid ? button_icon_rid : (int)xi_get_pref(XI_PREF_COMBO_ICON),
+        &r, clip_rct, TRUE, COLOR_BLACK, xi_get_pref(XI_PREF_COLOR_CTRL));
+}
+
+
+/*-------------------------------------------------------------------------
+function:   xvtch_draw_line
+lmp:        current lm pointer
+from:       from point
+to:         to point
+-------------------------------------------------------------------------*/
+#if XI_IS_CH
+static void
+xvtch_draw_line(LM_DATA *lmp, PNT *from, PNT *to, BOOLEAN adj_h)
+{
+  int i, len;
+
+#if XVT_OS != XVT_OS_CTOS
+
+  char c_v = (char)C_V;
+#else
+  char c_v = 225;
+#endif
+  char *s, *s2;
+
+  if (from->h == to->h)
+  {
+    /* draw vertical line */
+    if (adj_h)
+    {
+      from->h += lmp->rct.left;
+      if (lm_adj_h(lmp, &from->h))
+      {
+        for (i = from->v + VPIX_PER_CH; i <= to->v; i += VPIX_PER_CH)
+          xi_draw_text(lmp->win, from->h, i, &c_v, 1);
+      }
+    }
+    else
+    {
+      for (i = from->v + VPIX_PER_CH; i <= to->v; i += VPIX_PER_CH)
+        xi_draw_text(lmp->win, from->h, i, &c_v, 1);
+    }
+  }
+  else
+  {
+    len = (to->h - from->h) / VPIX_PER_CH;
+    s = xi_tree_malloc(len + 4, NULL);
+    s2 = s;
+    for (i = 0; i < len; ++i)
+    {
+
+#if XVT_OS != XVT_OS_CTOS
+      *s2 = C_H;
+
+#else
+      *s2 = 218;
+#endif
+      ++s2;
+    }
+    xi_draw_text(lmp->win, from->h, from->v + VPIX_PER_CH, s, len);
+    xi_tree_free(s);
+  }
+}
+#endif
+
+
+#if XI_IS_CH
+static char c_xd, c_xu, c_v, c_xx;
+#endif
+
+/*********** draw border around entire list ***********/
+static void
+draw_list_rect(LM_DATA *lmp, RCT *vr, RCT *hr)
+{
+  RCT r;
+  XI_OBJ *list_obj = lmp->list_obj;
+  XI_LIST_DATA *list_data = list_obj->v.list;
+
+  r = lmp->rct;
+  if (list_data->sb_win)
+    r.right = vr->right;
+  else
+    r.right += BORDER_WIDTH;
+  if (list_data->hsb_win)
+    r.bottom = hr->bottom;
+  xi_draw_rect(lmp->win, &r);
+}
+
+
+/*********** draw heading rules ***********/
+static void
+draw_heading_rules(LM_DATA *lmp, int hrule_h)
+{
+  if (! (lmp->update_rows_at_top + lmp->update_rows_at_bottom))
+  {
+    if (! lmp->no_heading)
+    {
+      int r2, i;
+      PNT p;
+      WINDOW win = lmp->win;
+
+#if XI_IS_CH
+      NOREF(r2);
+      NOREF(win);
+#endif
+#if XI_IS_CH
+      CTOS_IS_CH;
+      /* heading rule, Release 3.0 */
+      p.h = lmp->rct.left;
+      p.v = lmp->pix_hdr_bottom;
+      xi_move_to(lmp->win, p);
+      p.h = hrule_h - VPIX_PER_CH;
+      xi_draw_line(lmp->win, p);
+      CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+      CTOS_IS_PM;
+      r2 = lmp->rct.right - lmp->delta_x;
+      r2 = min(r2, hrule_h);
+      WIDTHLOOP(i, BORDER_WIDTH)
+      {
+        p.h = lmp->rct.left;
+        p.v = lmp->pix_row1_top - BORDER_WIDTH + i;
+        xi_move_to(win, p);
+        p.h = r2;
+        xi_draw_line(win, p);
+      }
+      CTOS_END;
+#endif
+    }
+  }
+}
+
+
+/*********** draw column rules ***********/
+static void
+draw_column_rules(LM_DATA *lmp)
+{
+  LM_COLUMN_DATA * *lmcd;
+  int col;
+  PNT p;
+#if XI_IS_CH
+  PNT from_p;
+#endif
+
+  if (lmp->no_vert_lines)
+  {
+    CPEN back_cpen;
+
+    back_cpen = black_cpen;
+    back_cpen.color = lmp->back_color;
+    xi_set_cpen(lmp->win, &back_cpen);
+  }
+  else
+  {
+    CPEN back_cpen;
+
+    back_cpen = black_cpen;
+    back_cpen.color = lmp->rule_color;
+    xi_set_cpen(lmp->win, &back_cpen);
+  }
+  for (col = 1, lmcd = &lmp->lm_column_data[1]; col < lmp->nbr_columns; col++, ++lmcd)
+  {
+    p.h = (*lmcd)->x_pix_pos - RULE_WIDTH_V;
+#if XI_IS_CH
+    CTOS_IS_CH;
+    p.v = lmp->pix_top;
+    lm_move_to(lmp, p, FALSE, TRUE);
+    p.v = lmp->mlr.bottom - VPIX_PER_CH;
+    lm_draw_line(lmp, p, FALSE, TRUE);
+    CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    /* if RULE_WIDTH_V were used, this is where it would be used */
+    p.v = lmp->rct.top;
+    lm_move_to(lmp, p, FALSE, TRUE);
+    p.v = min(lmp->rct.bottom, lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top);
+    lm_draw_line(lmp, p, FALSE, TRUE);
+    CTOS_END;
+#endif
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_needs_update
+lmp:        current lmp
+rctp:       rectangle to test
+adj_h:      adjust h
+adj_v:      adjust v
+returns:    TRUE if rectangle needs update
+-------------------------------------------------------------------------*/
+static BOOLEAN
+lm_needs_update(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_h, BOOLEAN adj_v)
+{
+  RCT r;
+
+  r = *rctp;
+  if (adj_h)
+  {
+    r.left += lmp->rct.left;
+    r.right += lmp->rct.left;
+  }
+
+  if (adj_v)
+  {
+    lm_adj_v(lmp, r.top);
+    lm_adj_v(lmp, r.bottom);
+  }
+
+  if (adj_h)
+  {
+    BOOLEAN leftb, rightb;
+
+    leftb = lm_adj_h(lmp, &r.left);
+    rightb = lm_adj_h(lmp, &r.right);
+    if ( ! leftb && ! rightb )
+      return FALSE;
+    else
+      return xi_needs_update(lmp->win, &r);
+  }
+  else
+  {
+    return xi_needs_update(lmp->win, &r);
+  }
+}
+
+
+/*********** draw row rules ***********/
+static void
+draw_row_rules(LM_DATA *lmp, int first_row_to_draw, int last_row_to_draw, BOOLEAN update)
+{
+  int r2, first_row, last_row;
+  int row, actual_r, hrule_h, col;
+  PNT p;
+  RCT r;
+  RCT    actual_rct = lmp->mlr;
+
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  if (lmp->pixel_width)
+    actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
+  else
+    actual_r = lmp->rct.right;
+  actual_rct.right = actual_r;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  if (lmp->pixel_width)
+    actual_r = lmp->rct.left + lmp->pixel_width;
+  else
+    actual_r = lmp->rct.right;
+  actual_rct.right = actual_r;
+  CTOS_END;
+#endif
+  hrule_h = actual_r;
+  xi_set_clip(lmp->win, &actual_rct);
+
+  if (lmp->no_horz_lines)
+  {
+    CPEN back_cpen;
+
+    back_cpen = black_cpen;
+    back_cpen.color = lmp->back_color;
+    xi_set_cpen(lmp->win, &back_cpen);
+  }
+  else
+  {
+#if XIWS != WMWS
+    CPEN back_cpen;
+
+    back_cpen = black_cpen;
+    back_cpen.color = lmp->rule_color;
+    xi_set_cpen(lmp->win, &back_cpen);
+#else
+    xi_set_cpen(lmp->win, &black_cpen);
+#endif
+  }
+  r2 = lmp->rct.right - lmp->delta_x;
+  r2 = min(r2, hrule_h);
+
+  first_row = max(0, lmp->first_fully_vis - 1);
+  last_row = min(lmp->nbr_realized_rows, lmp->last_fully_vis + 1);
+
+  if (lmp->update_rows_at_top)
+  {
+    RCT row_rct;
+    int old_last_row = last_row;
+
+    last_row = min(last_row, first_row + lmp->update_rows_at_top + 1);
+    lm_get_row_rect(&row_rct, (LM)lmp, last_row);
+    row_rct.bottom = lmp->mlr.bottom - lmp->mlr.top;
+    if (update && lm_needs_update(lmp, &row_rct, FALSE, TRUE))
+      last_row = old_last_row;
+  }
+  if (lmp->update_rows_at_bottom)
+  {
+    RCT row_rct;
+    int old_first_row = first_row;
+
+    first_row = max(first_row, lmp->last_fully_vis - lmp->update_rows_at_bottom);
+    lm_get_row_rect(&row_rct, (LM)lmp, first_row);
+    row_rct.top = 0;
+    if (update && lm_needs_update(lmp, &row_rct, FALSE, TRUE))
+      first_row = old_first_row;
+  }
+
+  if (first_row_to_draw != -1)
+  {
+    first_row = max(first_row_to_draw - 1, first_row);
+    last_row = min(last_row_to_draw + 1, last_row);
+  }
+
+  r = lmp->rct;
+  for (col = 0; col < lmp->nbr_columns; ++col)
+    if (! lmp->lm_column_data[col]->suppress_update_cells)
+      break;
+  if (col)
+    r.left = lmp->lm_column_data[col]->x_pix_pos;
+
+  for (row = first_row; row < last_row; ++row)
+  {
+    p.h = r.left;
+    p.v = lmp->pix_offsets[row] + lmp->pix_heights[row] - 1;
+    lm_move_to(lmp, p, TRUE, FALSE);
+    p.h = r2;
+    lm_draw_line(lmp, p, TRUE, FALSE);
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_draw_clipped_text
+lmp:        current lmp
+s:          string
+bound_rctp:
+clip_rctp:
+attrib:
+set_the_cpen:
+rule_and_space:
+-------------------------------------------------------------------------*/
+static void
+lm_draw_clipped_text(LM_DATA *lmp, char *s, RCT *bound_rctp,
+    RCT *clip_rctp, unsigned long attrib, BOOLEAN set_the_cpen,
+    int rule_and_space, BOOLEAN adj_v)
+{
+  RCT br, cr;
+  BOOLEAN left, right;
+
+  br = *bound_rctp;
+  br.left += lmp->rct.left;
+  br.right += lmp->rct.left;
+
+  if (adj_v)
+  {
+    lm_adj_v(lmp, br.top);
+    lm_adj_v(lmp, br.bottom);
+  }
+
+  left = lm_adj_h(lmp, &br.left);
+  right = lm_adj_h(lmp, &br.right);
+  if ( ! left && ! right )
+    return;
+  xi_rect_intersect(&cr, &br, clip_rctp);
+  xi_draw_clipped_text(lmp->win, s, &br, &cr, attrib, set_the_cpen,
+        rule_and_space, -1);
+}
+
+/*********** draw column headings ***********/
+static void
+draw_column_headings(LM_DATA *lmp, RCT *actual_rct)
+{
+  WINDOW win = lmp->win;
+  LM lm = (LM)lmp;
+
+  if (! lmp->update_cells_only)
+  {
+    if (! (lmp->update_rows_at_top + lmp->update_rows_at_bottom))
+    {
+      if ( !lmp->no_heading)
+      {
+        int col;
+
+        for (col = 0; col < lmp->nbr_columns; col++)
+        {
+          RCT heading_rct, cell_rct;
+          LM_COLUMN_DATA *col_data;
+          unsigned long attrib;
+
+          col_data = lmp->lm_column_data[col];
+          if (col_data->suppress_update_heading)
+            continue;
+
+          lm_get_cell_rect(&heading_rct, lm, 1, col, FALSE, FALSE);
+          heading_rct.top = lmp->pix_top + BORDER_WIDTH;
+#if XI_IS_CH
+          CTOS_IS_CH;
+          heading_rct.bottom = lmp->pix_hdr_bottom - VPIX_PER_CH;
+          lm_get_cell_rect(&cell_rct, lm, 1, col, TRUE, FALSE);
+          cell_rct.top = lmp->rct.top + VPIX_PER_CH;
+          CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+          CTOS_IS_PM;
+          heading_rct.bottom = lmp->pix_hdr_bottom;
+          lm_get_cell_rect(&cell_rct, lm, 1, col, TRUE, FALSE);
+          cell_rct.top = lmp->rct.top + 2 * BORDER_WIDTH;
+          CTOS_END;
+#endif
+          cell_rct.bottom = lmp->pix_hdr_bottom;
+          xi_set_cpen(win, &hollow_cpen);
+          xi_set_cbrush(win, &white_cbrush);
+          xi_set_draw_mode(win, M_COPY);
+          xi_set_clip(win, actual_rct);
+          if (col_data->font)
+            xi_set_xvt_font(win, col_data->font, FALSE);
+          else
+            xi_set_xvt_font(win, lmp->font, FALSE);
+
+          if (col_data->heading_well || col_data->heading_platform)
+          {
+            COLOR fore_color, back_color;
+
+            lm_draw_3d_rect(lmp, &heading_rct,
+                (BOOLEAN)(COLUMN_IS_SELECTED(lm, col) ?
+                !col_data->heading_well :
+                col_data->heading_well),
+                2, FALSE);
+            if (COLUMN_IS_ENABLED(lm, col))
+        {
+          if (LIST_IS_ENABLED(lmp))
+          fore_color = lmp->enabled_color;
+          else
+          fore_color = lmp->disabled_color;
+          back_color = lmp->back_color;
+        }
+        else
+        {
+          fore_color = lmp->disabled_color;
+          back_color = lmp->disabled_back_color;
+        }
+        if (col_data->heading_well || col_data->heading_platform)
+          back_color = xi_get_pref(XI_PREF_COLOR_CTRL);
+        xi_set_xvt_fore_color(win, fore_color);
+        xi_set_xvt_back_color(win, back_color);
+      }
+      else
+      {
+        COLOR fore_color;
+
+        if (COLUMN_IS_ENABLED(lm, col))
+        {
+          if (LIST_IS_ENABLED(lmp))
+          fore_color = lmp->enabled_color;
+          else
+          fore_color = lmp->disabled_color;
+          xi_set_xvt_fore_color(win, fore_color);
+          xi_set_xvt_back_color(win, lmp->back_color);
+        }
+        else
+        {
+          fore_color = lmp->disabled_color;
+          xi_set_xvt_fore_color(win, fore_color);
+          xi_set_xvt_back_color(win, lmp->disabled_back_color);
+        }
+        if (COLUMN_IS_SELECTED(lm, col))
+        {
+          CBRUSH cb;
+
+          cb = white_cbrush;
+          cb.color = fore_color;
+          xi_set_cbrush(win, &cb);
+          xi_set_xvt_fore_color(win, COLOR_WHITE);
+        }
+        lm_draw_rect(lmp, &heading_rct, FALSE);
+      }
+      if (col_data->heading_well || col_data->heading_platform)
+      {
+        cell_rct.left++;
+        cell_rct.right--;
+      }
+      attrib = ((LM_COL_ATTR(lm, col) | XI_ATR_VISIBLE) &
+          ~XI_ATR_PASSWORD) |
+          (lmp->min_heading_height ? XI_ATR_VCENTER : 0);
+      if (col_data->center_heading)
+      {
+        attrib |= XI_ATR_HCENTER;
+        attrib &= ~XI_ATR_RJUST;
+      }
+      if (col_data->icon_rid)
+      {
+        COLOR fore_color, back_color;
+
+        if (COLUMN_IS_ENABLED(lm, col))
+        {
+          if (LIST_IS_ENABLED(lmp))
+          fore_color = lmp->enabled_color;
+          else
+          fore_color = lmp->disabled_color;
+          back_color = lmp->back_color;
+        }
+        else
+        {
+          fore_color = lmp->disabled_color;
+          back_color = lmp->disabled_back_color;
+            }
+            if (col_data->heading_well || col_data->heading_platform)
+              back_color = xi_get_pref(XI_PREF_COLOR_CTRL);
+            lm_draw_icon(lmp, cell_rct.left + col_data->icon_x,
+                cell_rct.top + col_data->icon_y, col_data->icon_rid,
+                &cell_rct, actual_rct, FALSE, fore_color, back_color);
+          }
+          else
+          {
+            char *ch;
+            int lines;
+#if 0
+#if XI_IS_CH
+            char buf[BUFLEN];
+            int i;
+
+            CTOS_IS_CH;
+            for (i = 0; i < BUFLEN; ++i)
+              buf[i] = ' ';
+            buf[BUFLEN - 1] = '\0';
+            lm_draw_clipped_text(lmp, buf, &cell_rct, &actual_rct,
+                ((LM_COL_ATTR(lm, col) | XI_ATR_VISIBLE) & ~XI_ATR_PASSWORD) |
+                (col_data->center_heading ? XI_ATR_HCENTER : 0),
+                TRUE, 0, FALSE);
+            CTOS_END;
+#endif
+#endif
+            ch = col_data->heading_text;
+            lines = 1;
+            while (*ch != '\0')
+            {
+              if (*ch == '\n')
+                ++lines;
+              ++ch;
+            }
+            if (lines == 1)
+            {
+              lm_draw_clipped_text(lmp, col_data->heading_text, &cell_rct,
+                  actual_rct,
+                  attrib, TRUE, 0, FALSE);
+            }
+            else
+            {
+              char *s;
+              char *first_char;
+              char *ch;
+              BOOLEAN bk = FALSE;
+              int leading, ascent, descent;
+
+              s = xvt_mem_alloc(strlen(col_data->heading_text) + 1);
+              strcpy(s, col_data->heading_text);
+              ch = s;
+              first_char = ch;
+              xi_get_font_metrics(win, &leading, &ascent, &descent);
+              cell_rct.top +=
+                  (cell_rct.bottom - cell_rct.top -
+                  (leading + ascent + descent) * lines) / 2;
+              cell_rct.bottom = cell_rct.top + leading + ascent + descent;
+              while (TRUE)
+              {
+                while (*ch != '\n' && *ch != '\0')
+                  ++ch;
+                if (*ch == '\0')
+                  bk = TRUE;
+                *ch = 0;
+                lm_draw_clipped_text(lmp, first_char, &cell_rct,
+                    actual_rct,
+                    attrib & ~XI_ATR_VCENTER, TRUE, 0, FALSE);
+                if (bk)
+                  break;
+                cell_rct.top += (leading + ascent + descent);
+                cell_rct.bottom += (leading + ascent + descent);
+                ++ch;
+                first_char = ch;
+              }
+              xvt_mem_free(s);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+
+/* ------------------------------------------------------------------------- */
+/*  fast_calc_col_needs_update                                               */
+/* ------------------------------------------------------------------------- */
+static void
+fast_calc_col_needs_update(LM_DATA *lmp, int first_col, int last_col,
+                          BOOLEAN update)
+{
+  int col;
+  LM_COLUMN_DATA *column_data;
+  
+#if XVTWS == WMWS
+  NOREF(update);
+#endif
+
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  lmp->lm_column_data[col]->needs_update = FALSE;
+  for (col = first_col; col <= last_col; ++col)
+  {
+    RCT rct;
+    BOOLEAN rightb, leftb;
+
+    column_data = lmp->lm_column_data[col];
+    if (column_data->suppress_update_cells)
+      continue;
+    rct.left = lmp->rct.left + column_data->x_pix_pos;
+    rct.right = rct.left + column_data->pix_width +
+        2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+    rct.top = lmp->rct.top;
+  rct.bottom = lmp->rct.bottom;
+    column_data->column_rct = rct;
+#if XIWS != WMWS
+    leftb = lm_adj_h(lmp, &rct.left);
+    rightb = lm_adj_h(lmp, &rct.right);
+    column_data->prct = rct;
+    if (! leftb && !rightb)
+    column_data->needs_update = FALSE;
+    else
+    {
+      if (update)
+      {
+        if (xi_needs_update(lmp->win, &column_data->prct))
+      column_data->needs_update = TRUE;
+      else
+      column_data->needs_update = FALSE;
+      }
+      else
+      column_data->needs_update = TRUE;
+  }
+#else
+    leftb = lm_adj_h(lmp, &rct.left);
+    rightb = lm_adj_h(lmp, &rct.right);
+    column_data->prct = rct;
+  if (! leftb && !rightb)
+    column_data->needs_update = FALSE;
+  else
+      column_data->needs_update = TRUE;
+#endif
+  }
+}
+
+static void
+fast_draw_exception_rects(LM_DATA *lmp, WINDOW win, ROW_INFO *row_info, int first_row, int last_row)
+{
+  COLOR last_brush_color;
+  int col, row;
+  LM_COLUMN_DATA *column_data;
+  ROW_INFO *ri;
+  extern CPEN hollow_cpen;
+
+  /* draw exception rectangles - draw enabled, not selected cells */
+  last_brush_color = 0L;
+  xi_set_cpen(win, &hollow_cpen);
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+    column_data = lmp->lm_column_data[col];
+    if (! column_data->needs_update)
+      continue;
+
+  for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+    {
+      COLOR brush_color;
+      LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
+    BOOLEAN do_draw;
+
+    if (! ri->needs_update)
+      continue;
+      if (! cell_data->valid_data)
+        do_lm_cb_text(lmp, row, col, TRUE );
+    do_draw = lm_cell_has_focus( lmp, row, col, FALSE );
+      if ((CELL_IS_ENABLED(lmp, row, col)) && ! (CELL_IS_SELECTED(lmp, row, col)))
+    do_draw = TRUE;
+    if (do_draw)
+      {
+        RCT rct;
+
+        brush_color = lmp->back_color;
+        if (cell_data->back_color)
+          brush_color = cell_data->back_color;
+/*
+TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
+        if (brush_color == lmp->back_color)
+          continue;
+*/
+        if (brush_color != last_brush_color)
+        {
+          CBRUSH cbrush;
+
+          cbrush.color = brush_color;
+          cbrush.pat = PAT_SOLID;
+          xi_set_cbrush(win, &cbrush);
+        }
+        rct = column_data->prct;
+        rct.top = ri->prct.top;
+        rct.bottom = ri->prct.bottom;
+        xi_draw_rect(win, &rct);
+      }
+    }
+  }
+
+  /* draw exception rectangles - draw disabled, not selected cells */
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+    column_data = lmp->lm_column_data[col];
+    if (! column_data->needs_update)
+      continue;
+
+    for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+    {
+      COLOR brush_color;
+      LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
+
+      if (! ri->needs_update)
+        continue;
+      if (! cell_data->valid_data)
+        do_lm_cb_text(lmp, row, col, TRUE );
+      if (! (CELL_IS_ENABLED(lmp, row, col)) && ! (CELL_IS_SELECTED(lmp, row, col)))
+      {
+        RCT rct;
+
+        brush_color = lmp->disabled_back_color;
+/*
+TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
+        if (brush_color == lmp->back_color)
+          continue;
+*/
+        if (brush_color != last_brush_color)
+        {
+          CBRUSH cbrush;
+
+          cbrush.color = brush_color;
+          cbrush.pat = PAT_SOLID;
+          xi_set_cbrush(win, &cbrush);
+        }
+        rct = column_data->prct;
+        rct.top = ri->prct.top;
+        rct.bottom = ri->prct.bottom;
+        xi_draw_rect(win, &rct);
+      }
+    }
+  }
+
+  /* draw exception rectangles - draw selected cells */
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+    column_data = lmp->lm_column_data[col];
+    if (! column_data->needs_update)
+      continue;
+
+    for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+    {
+      COLOR brush_color;
+      LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
+
+      if (! ri->needs_update)
+        continue;
+      if (! cell_data->valid_data)
+        do_lm_cb_text(lmp, row, col, TRUE );
+      if (CELL_IS_SELECTED(lmp, row, col) && ! lm_cell_has_focus(lmp, row, col, FALSE))
+      {
+        RCT rct;
+
+        if (CELL_IS_ENABLED(lmp, row, col))
+        {
+          brush_color = lmp->enabled_color;
+          if (lmp->row_colors[row])
+            brush_color = lmp->row_colors[row];
+          if (cell_data->color)
+            brush_color = cell_data->color;
+        }
+        else
+          brush_color = lmp->disabled_color;
+        if (cell_data->back_color && lmp->retain_back_color_on_select)
+          brush_color = cell_data->back_color;
+/*
+TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
+        if (brush_color == lmp->back_color)
+          continue;
+*/
+        if (brush_color != last_brush_color)
+        {
+          CBRUSH cbrush;
+
+          cbrush.color = brush_color;
+          cbrush.pat = PAT_SOLID;
+          xi_set_cbrush(win, &cbrush);
+        }
+        rct = column_data->prct;
+        rct.top = ri->prct.top;
+        rct.bottom = ri->prct.bottom;
+        xi_draw_rect(win, &rct);
+      }
+    }
+  }
+
+#if XVTWS != WMWS 
+  /* draw 3d rectangles */
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+    column_data = lmp->lm_column_data[col];
+    if (! column_data->needs_update)
+      continue;
+
+    for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+    {
+      RCT rct;
+      LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
+
+      if (! ri->needs_update)
+        continue;
+      if (! cell_data->valid_data)
+        do_lm_cb_text(lmp, row, col, TRUE );
+
+      rct = column_data->prct;
+      rct.top = ri->prct.top;
+      rct.bottom = ri->prct.bottom;
+      if (column_data->column_well || column_data->column_platform)
+        xi_draw_3d_rect(win, &rct, (BOOLEAN)(CELL_IS_SELECTED(lmp, row, col) ? ! column_data->column_well :
+                        column_data->column_well), 2, 0L, 0L, 0L);
+    }
+  }
+#else
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+    column_data = lmp->lm_column_data[col];
+    if (! column_data->needs_update)
+      continue;
+
+    for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+    {
+      COLOR brush_color;
+      LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
+    BOOLEAN do_draw;
+
+      if (! ri->needs_update)
+        continue;
+      if (! cell_data->valid_data)
+        do_lm_cb_text(lmp, row, col);
+    do_draw = lm_cell_has_focus( lmp, row, col, FALSE );
+      if ((CELL_IS_ENABLED(lmp, row, col)) && ! (CELL_IS_SELECTED(lmp, row, col)))
+    do_draw = TRUE;
+    if (do_draw)
+      {
+      if (column_data->column_well || column_data->column_platform)
+    {
+          RCT rct;
+
+          brush_color = lmp->back_color;
+          if (cell_data->back_color)
+            brush_color = cell_data->back_color;
+          if (brush_color != last_brush_color)
+          {
+            CBRUSH cbrush;
+
+            cbrush.color = brush_color;
+            cbrush.pat = PAT_SOLID;
+            xi_set_cbrush(win, &cbrush);
+          }
+          rct = column_data->prct;
+          rct.top = ri->prct.top;
+          rct.bottom = ri->prct.bottom;
+          xi_draw_rect(win, &rct);
+    }
+      }
+    }
+  }
+#endif
+}
+
+static void
+fast_draw_cell_icons(LM_DATA *lmp, WINDOW win, ROW_INFO *row_info, int first_row, int last_row)
+{
+  int col, row;
+  LM_COLUMN_DATA *column_data;
+  ROW_INFO *ri;
+  DRAW_CTOOLS ct;
+#if XIWS != PMWS
+  COLOR last_fore_color, last_back_color;
+#endif
+
+  xi_get_draw_ctools(win, &ct);
+  ct.fore_color = lmp->enabled_color;
+  ct.back_color = lmp->back_color;
+  ct.opaque_text = TRUE;
+  xi_set_draw_ctools(win, &ct);
+
+#if XIWS != PMWS
+  last_back_color = 0L;
+  last_fore_color = 0L;
+#endif
+  /* draw cell icons */
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+    column_data = lmp->lm_column_data[col];
+    if (! column_data->needs_update)
+      continue;
+
+    for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+    {
+      RCT rct;
+      LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
+      COLOR fore_color, back_color;
+      if (! ri->needs_update)
+        continue;
+      if (! cell_data->valid_data)
+        do_lm_cb_text(lmp, row, col, TRUE );
+      rct = column_data->prct;
+      rct.top = ri->rct.top;
+      rct.bottom = ri->rct.bottom;
+      lm_adj_v(lmp, rct.top);
+      lm_adj_v(lmp, rct.bottom);
+      {
+        RCT mlr = lmp->mlr;
+
+        if (lmp->pixel_width)
+          mlr.right = mlr.left + lmp->pixel_width + BORDER_WIDTH;
+        xi_rect_intersect(&mlr, &mlr, &rct);
+        xi_set_clip(win, &mlr);
+      }
+      fore_color = ct.fore_color;
+      back_color = ct.back_color;
+      if (lmp->row_colors[row])
+        fore_color = lmp->row_colors[row];
+      if (cell_data->color)
+        fore_color = cell_data->color;
+      if (cell_data->back_color)
+      {
+        back_color = cell_data->back_color;
+      }
+      if (! cell_data->icon_rid)
+        continue;
+#if XIWS == PMWS
+      xi_draw_icon(win, rct.left, rct.top, cell_data->icon_rid, fore_color, back_color);
+#else
+      if (fore_color != last_fore_color || back_color != last_back_color)
+        xi_draw_icon(win, rct.left, rct.top, cell_data->icon_rid, fore_color, back_color);
+      else
+        xi_draw_icon(win, rct.left, rct.top, cell_data->icon_rid, 0L, 0L);
+#endif
+    }
+  }
+}
+
+static void
+fast_draw_cell_buttons(LM_DATA *lmp, ROW_INFO *row_info, int first_row, int last_row)
+{
+  int col, row;
+  LM_COLUMN_DATA *column_data;
+  ROW_INFO *ri;
+
+  /* draw exception rectangles - draw enabled, not selected cells */
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+    column_data = lmp->lm_column_data[col];
+    if (! column_data->needs_update)
+      continue;
+
+    for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+    {
+      RCT mr;
+      BOOLEAN button;
+      BOOLEAN button_on_focus;
+      LM_CELL_DATA *cell_data;
+
+      if (! ri->needs_update)
+        continue;
+      mr = lmp->mlr;
+      if (lmp->pixel_width)
+        mr.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
+      cell_data = &lmp->cell_data[row][col];
+      if (! cell_data->valid_data)
+        do_lm_cb_text(lmp, row, col, TRUE );
+      button = cell_data->button;
+      button_on_focus = cell_data->button_on_focus;
+      if ((button && ! button_on_focus) ||
+        (button && button_on_focus &&
+        lm_row_has_focus(lmp, row, FALSE)))
+      redraw_cell_button(lmp, row, col, &mr, FALSE, FALSE);
+    }
+  }
+}
+
+static void
+fast_draw_cell_text(LM_DATA *lmp, LM_CELL_DATA *cell_data, LM_COLUMN_DATA *column_data,
+  int row, int col, ROW_INFO *ri, int col_offset, int leading, int ascent,
+  int descent, BOOLEAN xvt_dwin_set_clip)
+{
+  RCT rct;
+  unsigned long attrib, cell_attrib;
+  char *s;
+  int len, rule_and_space, baseline, wid;
+  char buf[256];
+  WINDOW win = lmp->win;
+  BOOLEAN button, button_on_left;
+
+#if XVTWS == WMWS
+  NOREF(rule_and_space);
+#endif
+  if (lm_cell_has_focus( lmp, row, col, FALSE ))
+  return;
+  button = cell_data->button;
+  button_on_left = cell_data->button_on_left;
+  cell_attrib = cell_data->attrib &
+    (XI_ATR_HCENTER | XI_ATR_RJUST);
+  attrib = LM_COL_ATTR(lmp, col) | XI_ATR_VISIBLE |
+    (lmp->min_cell_height ? XI_ATR_VCENTER : 0);
+  if (cell_attrib)
+  {
+  attrib &= ~(XI_ATR_HCENTER | XI_ATR_RJUST);
+  attrib |= cell_attrib;
+  }
+  rct = column_data->prct;
+  rct.top = ri->prct.top;
+  rct.bottom = ri->prct.bottom;
+  rct.left += col_offset;
+  rct.right -= col_offset;
+  if (! column_data->wrap_text)
+  {
+  if (column_data->vertical_align_bottom)
+  {
+    int new_top;
+
+#if XVTWS == WMWS
+    new_top = rct.bottom - (leading + ascent + descent);
+#else
+    new_top = rct.bottom - (leading + ascent + descent) - 3;
+#endif
+    rct.top = max(rct.top, new_top);
+  }
+  else if (! column_data->vertical_align_center)
+  {
+    int new_bottom;
+
+#if XVTWS == WMWS
+    new_bottom = rct.top + leading + ascent + descent;
+#else
+    new_bottom = rct.top + leading + ascent + descent + 4;
+#endif
+    rct.bottom = min(rct.bottom, new_bottom);
+  }
+  }
+  if (button)
+  {
+  RCT r;
+
+  r = rct;
+  xi_inflate_rect(&r, 1);
+  if (button_on_left)
+  {
+    r.right = r.left + lmp->pix_row_spacing;
+    rct.left = r.right;
+  }
+  else
+  {
+    r.left = r.right - lmp->pix_row_spacing;
+    rct.right = r.left - (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+  }
+  }
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  rct.top += RULE_Y_OFFSET_TOP;
+  rct.bottom -= RULE_Y_OFFSET_BOTTOM;
+  CTOS_END;
+#endif
+
+  if (column_data->column_well || column_data->column_platform)
+  {
+    rct.left++;
+    rct.right--;
+  }
+  if (xvt_dwin_set_clip)
+  {
+    RCT mlr = lmp->mlr;
+
+    if (lmp->pixel_width)
+      mlr.right = mlr.left + lmp->pixel_width + BORDER_WIDTH;
+    xi_rect_intersect(&mlr, &mlr, &rct);
+    xi_set_clip(win, &mlr);
+  }
+  if (column_data->wrap_text)
+  {
+    int   nbr_lines, cnt;
+    char* s;
+
+    lm_wrap_text(lmp, row, col, FALSE);
+    nbr_lines = min(cell_data->nbr_lines, lmp->max_lines_in_cell);
+    s = LM_CELL_TEXT(lmp, row, col);
+    for (cnt = 0; cnt < nbr_lines; ++cnt)
+    {
+      int len = -1;
+
+      if (cnt < nbr_lines - 1)
+        len = cell_data->line_breaks[cnt + 1] - cell_data->line_breaks[cnt];
+#if XIWS == WMWS
+      baseline = rct.top + 8;
+#else
+      baseline = rct.top + leading + ascent;
+#endif
+      if ((&s[cell_data->line_breaks[cnt]])[len - 1] == '\n')
+        len--;
+      xi_draw_text(win, rct.left, baseline, &s[cell_data->line_breaks[cnt]], len);
+#if XVTWS == WMWS
+      rct.top += cell_data->font_height;
+#else
+      rct.top += cell_data->font_height - 1;
+#endif
+    }
+  }
+  else
+  {
+    s = lmp->buffer[row] + column_data->text_offset;
+    len = strlen(s);
+    len = min(len, sizeof(buf) - 1);
+    if (attrib & XI_ATR_PASSWORD)
+      memset(buf, XI_PASSWORD_CHAR, len);
+    else
+      gstrncpy(buf, s, len);
+    buf[len] = '\0';
+    rule_and_space = lmp->min_cell_height ? RULE_Y_OFFSET_TOP : 0;
+#if XIWS == WMWS
+    baseline = rct.top + 8;
+#else
+    if (attrib & XI_ATR_VCENTER)
+      baseline = rct.top + leading + ascent + rule_and_space +
+      (rct.bottom - rct.top - leading - ascent - descent) / 2 - 1;
+    else
+      baseline = rct.top + leading + ascent + rule_and_space;
+#endif
+    if (attrib & XI_ATR_RJUST)
+    {
+      wid = xi_xvt_get_text_width(win, buf, -1);
+      xi_draw_text(win, rct.right - wid, baseline, buf, len);
+    }
+    else
+    {
+      if (attrib & XI_ATR_HCENTER)
+      {
+        int x;
+
+        wid = xi_xvt_get_text_width(win, buf, len);
+        x = (rct.left + rct.right) / 2 - wid / 2;
+        if (x < rct.left)
+          x = rct.left;
+        xi_draw_text(win, x, baseline, buf, len);
+      }
+      else
+        xi_draw_text(win, rct.left, baseline, buf, len);
+    }
+  }
+}
+
+
+static void
+fast_draw_all_cell_text(LM_DATA *lmp, WINDOW win, ROW_INFO *row_info,
+  int col_offset, int first_row, int last_row, RCT* list_rect)
+{
+  DRAW_CTOOLS ctools;
+  int row, col;
+  ROW_INFO *ri;
+  LM_COLUMN_DATA *column_data;
+  int leading, ascent, descent;
+  BOOLEAN have_last_font;
+  XVT_FNTID *last_font;
+
+  ctools = lm_normal_ctools;
+
+  /* the following two lines must come before the xi_set_xvt_font, because in
+  R3, setting the draw ctools also sets the font.
+  */
+
+  if (LIST_IS_ENABLED(lmp))
+    ctools.fore_color = lmp->enabled_color;
+  else
+    ctools.fore_color = lmp->disabled_color;
+#if XVTWS == WMWS
+  ctools.back_color = lmp->back_color;
+#endif
+  xi_set_draw_ctools(win, &ctools);
+
+  xi_set_xvt_font(win, lmp->font, FALSE);
+  xi_get_font_metrics(win, &leading, &ascent, &descent);
+
+  /* draw default font, not wrapped text, not selected cells */
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+  RCT clip_rect;
+  column_data = lmp->lm_column_data[col];
+  if (! column_data->needs_update)
+    continue;
+  if (column_data->wrap_text)
+    continue;
+  if ((column_data->attrib & XI_ATR_ENABLED) == 0)
+    xi_set_xvt_fore_color(win, lmp->disabled_color);
+  else
+    xi_set_xvt_fore_color(win, ctools.fore_color);
+  if (!xi_rect_intersect( &clip_rect, &column_data->prct, list_rect ))
+    continue;
+  xi_set_clip(win, &clip_rect);
+  for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+  {
+    LM_CELL_DATA *cell_data;
+
+    if (! ri->needs_update)
+      continue;
+    if (lmp->row_colors[row])
+      continue;
+    cell_data = &lmp->cell_data[row][col];
+    if (! cell_data->valid_data)
+      do_lm_cb_text(lmp, row, col, TRUE );
+    if (cell_data->color)
+      continue;
+    if (cell_data->font)
+      continue;
+    if (cell_data->icon_rid)
+      continue;
+    if (CELL_IS_SELECTED(lmp, row, col))
+      continue;
+    fast_draw_cell_text(lmp, cell_data, column_data,
+      row, col, ri, col_offset, leading, ascent,
+      descent, FALSE);
+  }
+  }
+
+  /*
+  draw default font, colored text
+  */
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+  RCT clip_rect;
+
+  column_data = lmp->lm_column_data[col];
+  if (! column_data->needs_update)
+    continue;
+  if (column_data->wrap_text)
+    continue;
+  if (!xi_rect_intersect( &clip_rect, &column_data->prct, list_rect ))
+    continue;
+  xi_set_clip(win, &clip_rect);
+  for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+  {
+    LM_CELL_DATA *cell_data;
+    COLOR color;
+
+    if (! ri->needs_update)
+      continue;
+    cell_data = &lmp->cell_data[row][col];
+    if (! cell_data->valid_data)
+      do_lm_cb_text(lmp, row, col, TRUE );
+    if (cell_data->font)
+      continue;
+    if (cell_data->icon_rid)
+      continue;
+    if (CELL_IS_SELECTED(lmp, row, col))
+    {
+      color = lmp->back_color;
+      if (column_data->column_well || column_data->column_platform)
+      color = lmp->enabled_color;
+      if (cell_data->back_color)
+      if (lmp->retain_back_color_on_select)
+        color = lmp->enabled_color;
+      else
+        color = cell_data->back_color;
+    }
+    else
+    {
+      color = lmp->row_colors[row];
+      if (cell_data->color)
+      color = cell_data->color;
+      if ((column_data->attrib & XI_ATR_ENABLED) == 0)
+      color = lmp->disabled_color;
+    }
+    if (! color)
+      continue;
+    xi_set_xvt_fore_color(win, color);
+#if XVTWS == WMWS
+    xi_set_xvt_back_color(win, lmp->enabled_color);
+#endif
+    fast_draw_cell_text(lmp, cell_data, column_data,
+      row, col, ri, col_offset, leading, ascent,
+      descent, FALSE);
+  }
+  }
+
+
+  /* draw default font, black text, wrapped text */
+  /*
+  this needs to be a separate loop from above, because this loop sets the
+  clipping region for each cell, and the above loop sets the clipping region
+  for each column.
+  */
+  xi_set_xvt_fore_color(win, COLOR_BLACK);
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+  column_data = lmp->lm_column_data[col];
+  if (! column_data->needs_update)
+    continue;
+  if (! column_data->wrap_text)
+    continue;
+  if ((column_data->attrib & XI_ATR_ENABLED) == 0)
+    xi_set_xvt_fore_color(win, lmp->disabled_color);
+  else
+    xi_set_xvt_fore_color(win, COLOR_BLACK);
+  for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+  {
+    LM_CELL_DATA *cell_data;
+
+    if (! ri->needs_update)
+      continue;
+    if (lmp->row_colors[row])
+      continue;
+    cell_data = &lmp->cell_data[row][col];
+    if (! cell_data->valid_data)
+      do_lm_cb_text(lmp, row, col, TRUE );
+    if (cell_data->color)
+      continue;
+    if (cell_data->font)
+      continue;
+    if (cell_data->icon_rid)
+      continue;
+    if (CELL_IS_SELECTED(lmp, row, col))
+      continue;
+    fast_draw_cell_text(lmp, cell_data, column_data,
+      row, col, ri, col_offset, leading, ascent,
+      descent, TRUE);
+  }
+  }
+
+  /* draw default font, colored text, wrapped text */
+  /*
+  this needs to be a separate loop from above, because this loop sets the
+  colors for each cell, and the above loop only draws black.
+  */
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+  column_data = lmp->lm_column_data[col];
+  if (! column_data->needs_update)
+    continue;
+  if (! column_data->wrap_text)
+    continue;
+  for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+  {
+    LM_CELL_DATA *cell_data;
+    COLOR color;
+
+    if (! ri->needs_update)
+      continue;
+    cell_data = &lmp->cell_data[row][col];
+    if (! cell_data->valid_data)
+      do_lm_cb_text(lmp, row, col, TRUE );
+    if (cell_data->font)
+      continue;
+    if (cell_data->icon_rid)
+      continue;
+    if (CELL_IS_SELECTED(lmp, row, col))
+    {
+      color = lmp->back_color;
+      if (column_data->column_well || column_data->column_platform)
+      color = lmp->enabled_color;
+      if (cell_data->back_color)
+      if (lmp->retain_back_color_on_select)
+        color = lmp->enabled_color;
+      else
+        color = cell_data->back_color;
+    }
+    else
+    {
+      color = lmp->row_colors[row];
+      if (cell_data->color)
+      color = cell_data->color;
+      if ((column_data->attrib & XI_ATR_ENABLED) == 0)
+      color = lmp->disabled_color;
+    }
+    if (! color)
+      continue;
+    xi_set_xvt_fore_color(win, color);
+    fast_draw_cell_text(lmp, cell_data, column_data,
+      row, col, ri, col_offset, leading, ascent,
+      descent, TRUE);
+  }
+  }
+
+  /* draw all of the rest of the text */
+  have_last_font = FALSE;
+  last_font = NULL;
+  for (col = 0; col < lmp->nbr_columns; ++col)
+  {
+  column_data = lmp->lm_column_data[col];
+  if (! column_data->needs_update)
+    continue;
+  for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+  {
+    LM_CELL_DATA *cell_data;
+    COLOR color;
+    BOOLEAN need_to_set;
+
+    if (! ri->needs_update)
+      continue;
+    cell_data = &lmp->cell_data[row][col];
+    if (! cell_data->valid_data)
+      do_lm_cb_text(lmp, row, col, TRUE );
+    if (! cell_data->font)
+      continue;
+    if (cell_data->icon_rid)
+      continue;
+    need_to_set = FALSE;
+    if (! have_last_font)
+      need_to_set = TRUE;
+    if (have_last_font && ! font_compare(*last_font, *cell_data->font))
+      need_to_set = TRUE;
+    if (need_to_set)
+    {
+      int char_width;
+
+      xi_set_xvt_font(win, cell_data->font, FALSE);
+      xi_get_font_metrics_font(cell_data->font, &leading, &ascent,
+          &descent, &char_width);
+      last_font = cell_data->font;
+      have_last_font = TRUE;
+    }
+    if (CELL_IS_SELECTED(lmp, row, col))
+    {
+      color = lmp->back_color;
+      if (cell_data->back_color)
+      if (lmp->retain_back_color_on_select)
+        color = lmp->enabled_color;
+      else
+        color = cell_data->back_color;
+    }
+    else
+    {
+      color = lmp->row_colors[row];
+      if (cell_data->color)
+      color = cell_data->color;
+      if ((column_data->attrib & XI_ATR_ENABLED) == 0)
+      color = lmp->disabled_color;
+    }
+    xi_set_xvt_fore_color(win, color);
+
+      fast_draw_cell_text(lmp, cell_data, column_data,
+          row, col, ri, col_offset, leading, ascent,
+          descent, TRUE);
+    }
+  }
+}
+
+#if XVTWS != WMWS
+static void
+fast_draw_row_focus_border(LM_DATA *lmp, ROW_INFO *row_info, int first_row, int last_row)
+{
+  int col, row;
+  LM_COLUMN_DATA *column_data;
+  ROW_INFO *ri;
+  CPEN color_cpen;
+  CPEN rule_cpen;
+  BOOLEAN last_was_rule = TRUE;
+  RCT mr;
+
+  if (! lmp->row_focus_border)
+    return;
+  color_cpen.width = 1;
+  color_cpen.color = lmp->row_focus_border_color;
+  color_cpen.pat = PAT_SOLID;
+  color_cpen.style = P_SOLID;
+  rule_cpen.width = 1;
+  rule_cpen.color = lmp->rule_color;
+  rule_cpen.pat = PAT_SOLID;
+  rule_cpen.style = P_SOLID;
+  xi_set_cpen(lmp->win, &rule_cpen);
+  {
+    mr = lmp->mlr;
+    if (lmp->pixel_width)
+      mr.right = mr.left + lmp->pixel_width + BORDER_WIDTH;
+    xi_set_clip(lmp->win, &mr);
+  }
+  for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
+  {
+    RCT rct;
+    PNT p;
+    WINDOW win = lmp->win;
+    BOOLEAN row_has_focus = lm_row_has_focus(lmp, row, FALSE);
+
+    if (! ri->needs_update)
+      continue;
+    if (row_has_focus)
+    {
+      if (last_was_rule)
+      {
+        xi_set_cpen(lmp->win, &color_cpen);
+        last_was_rule = FALSE;
+      }
+    }
+    else
+    {
+      if (! last_was_rule)
+      {
+        xi_set_cpen(lmp->win, &rule_cpen);
+        last_was_rule = TRUE;
+      }
+    }
+    for (col = 0; col < lmp->nbr_columns; ++col)
+    {
+      column_data = lmp->lm_column_data[col];
+      if (! column_data->needs_update)
+        continue;
+      rct = column_data->prct;
+      rct.top = ri->prct.top;
+      rct.bottom = ri->prct.bottom;
+
+      /* draw top line */
+      p.h = rct.left;
+      p.v = rct.top - 1;
+      xi_move_to(win, p);
+      p.h = rct.right;
+      xi_draw_line(win, p);
+
+      if (row_has_focus)
+      {
+        /* draw next line down */
+        p.v++;
+        p.h = rct.left;
+        xi_move_to(win, p);
+        p.h = rct.right;
+        xi_draw_line(win, p);
+      }
+
+      /* draw bottom line */
+      p.h = rct.left;
+      p.v = rct.bottom;
+      xi_move_to(win, p);
+      p.h = rct.right;
+      xi_draw_line(win, p);
+
+      if (row_has_focus)
+      {
+        /* draw line above bottom line */
+        p.v--;
+        p.h = rct.left;
+        xi_move_to(win, p);
+        p.h = rct.right;
+        xi_draw_line(win, p);
+      }
+    }
+  }
+}
+#endif
+
+
+/* ------------------------------------------------------------------------- */
+/*  draw_cell_block                                                          */
+/* ------------------------------------------------------------------------- */
+
+static void
+draw_cell_block( LM_DATA* lmp, int first_row, int last_row,
+                ROW_INFO* row_info )
+{
+  WINDOW win = lmp->win;
+  RCT    actual_rct = lmp->mlr;
+  int    actual_r;
+  int    col_offset;
+
+  col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  if (lmp->pixel_width)
+    actual_r = lmp->mlr.left + lmp->pixel_width;
+  else
+    actual_r = lmp->mlr.right;
+  actual_rct.right = actual_r;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  if (lmp->pixel_width)
+    actual_r = lmp->mlr.left + lmp->pixel_width;
+  else
+    actual_r = lmp->mlr.right;
+  actual_rct.right = actual_r;
+  CTOS_END;
+#endif
+
+  xi_set_clip(win, &actual_rct);
+
+  /* draw all rectangles that are not white */
+  fast_draw_exception_rects(lmp, win, row_info, first_row, last_row);
+
+  /* draw all of the text in the cells */
+  fast_draw_all_cell_text(lmp, win, row_info, col_offset, first_row, last_row,
+                          &actual_rct );
+
+  /* draw cell buttons */
+  fast_draw_cell_buttons(lmp, row_info, first_row, last_row);
+
+  fast_draw_cell_icons(lmp, win, row_info, first_row, last_row);
+
+#if XVTWS != WMWS
+  draw_row_rules(lmp, first_row, last_row, FALSE);
+
+  fast_draw_row_focus_border(lmp, row_info, first_row, last_row);
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+/*  draw_cell_range                                                          */
+/* ------------------------------------------------------------------------- */
+void
+draw_cell_range( LM_DATA* lmp, int first_row, int last_row,
+                int first_col, int last_col,
+                BOOLEAN in_event_update )
+{
+  int       row, col;
+  ROW_INFO* row_info;
+  ROW_INFO* row_ptr;
+
+  if (lmp->list_obj->nbr_children <= 0) return;
+  if (xi_get_attrib(lmp->list_obj) & XI_ATR_VISIBLE)
+  {
+    row_info = (ROW_INFO *)xvt_mem_alloc(sizeof(ROW_INFO) * (last_row + 1));
+    for ( row = first_row, row_ptr = row_info + first_row; row <= last_row;
+          ++row, ++row_ptr)
+    {
+      lm_get_row_rect(&row_ptr->rct, (LM)lmp, row);
+      /* don't need to test for the rule, it is drawn elsewhere */
+#if XVTWS != WMWS
+    row_ptr->rct.bottom--;
+    if (row_ptr->rct.bottom < row_ptr->rct.top)
+        row_ptr->rct.bottom = row_ptr->rct.top;
+#endif
+      row_ptr->prct = row_ptr->rct;
+      lm_adj_v(lmp, row_ptr->prct.top);
+      lm_adj_v(lmp, row_ptr->prct.bottom);
+      if (in_event_update)
+      {
+        if (lm_needs_update(lmp, &row_ptr->rct, FALSE, TRUE))
+          row_ptr->needs_update = TRUE;
+        else
+          row_ptr->needs_update = FALSE;
+      }
+      else
+      row_ptr->needs_update = TRUE;
+    }
+
+    /*
+    force cell requests for cells that have suppress_update_cells set to true
+    */
+    for (col = first_col; col <= last_col; ++col)
+    {
+      if (lmp->lm_column_data[col]->suppress_update_cells)
+      {
+        for (row = first_row; row <= last_row; ++row)
+        {
+          LM_CELL_DATA *cell_data;
+
+          cell_data = &(lmp->cell_data[row][col]);
+          if (! cell_data->valid_data)
+            do_lm_cb_text(lmp, row, col, TRUE );
+        }
+      }
+    }
+
+    /*
+    determine which columns need to be updated
+    */
+    fast_calc_col_needs_update(lmp, first_col, last_col, in_event_update);
+
+    /*
+    at this point, we should never need to call lm_needs_update again in this function
+    or any called functions.
+    */
+    draw_cell_block( lmp, first_row, last_row, row_info );
+    xvt_mem_free((char *)row_info);
+  }
+}
+
+/*********** draw cells ***********/
+static void
+fast_draw_cells(LM_DATA *lmp, BOOLEAN update)
+{
+  int first_row;
+  int last_row;
+
+  first_row = lmp->first_fully_vis;
+  if (first_row < 0)
+    first_row = 0;
+  last_row = min(lmp->last_fully_vis + 1, lmp->nbr_realized_rows - 1);
+  if (last_row < 0)
+    return;
+  draw_cell_range( lmp, first_row, last_row, 0, lmp->nbr_columns - 1, update );
+}
+
+
+/*-------------------------------------------------------------------------
+function:   redraw_cell
+lm:         current lm
+row:
+col:
+update:     if TRUE, redraw_cell is being called due to an E_UPDATE event.
+clip_rct:   clip rectangle
+-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+/* redraw_cell                                                             */
+/*-------------------------------------------------------------------------*/
+void redraw_cell( LM lm, int row, int col, BOOLEAN update )
+{
+  draw_cell_range( (LM_DATA*)lm, row, row, col, col, update );
+}
+
+/*-------------------------------------------------------------------------*/
+/* lm_redraw_row                                                              */
+/*-------------------------------------------------------------------------*/
+void lm_redraw_row(LM_DATA *lmp, int row, BOOLEAN update )
+{
+  draw_cell_range( lmp, row, row, 0, lmp->nbr_columns - 1, update );
+}
+
+/*-------------------------------------------------------------------------*/
+/* draw_other_rectangles                                                   */
+/*-------------------------------------------------------------------------*/
+static void
+draw_other_rectangles(LM_DATA *lmp, RCT *actual_rct)
+{
+  WINDOW win = lmp->win;
+  RCT lmp_rct, vr, hr;
+  int i, actual_r, hrule_h;
+  CBRUSH cbrush;
+  XI_LIST_DATA *list_data;
+  XI_OBJ *list_obj;
+
+#if XVTWS == WMWS
+  NOREF(lmp_rct);
+  NOREF(hrule_h);
+  NOREF(list_data);
+#endif
+  lmp_rct = lmp->rct;
+  if (lmp->pixel_width)
+    actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
+  else
+    actual_r = lmp->rct.right;
+  list_obj = lmp->list_obj;
+  list_data = list_obj->v.list;
+  hrule_h = actual_r;
+
+  /*********** Graphical: border at right of last column ***********/
+  /*********** Graphical: rectangle around entire list ***********/
+  /*********** Graphical: rectangle at bottom of list ***********/
+  /* NOTE: GRAPHICAL SYSTEMS ONLY, HERE.  CH is in beginning of draw_lm */
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  xi_set_clip(win, actual_rct);
+  xi_set_cpen(win, &black_cpen);
+  xi_set_draw_mode(win, M_COPY);
+  if (lmp->pixel_width)
+  {
+  PNT p, p2;
+  int width;
+  RCT r;
+
+  p.h = lmp->rct.right - 1 - lmp->rct.left;
+  p.v = lmp_rct.top;
+  p2 = p;
+  p2.v = min(lmp_rct.bottom, lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top);
+  width = BORDER_WIDTH;
+  if (lmp->no_vert_lines)
+  {
+    CPEN back_cpen;
+
+    back_cpen = black_cpen;
+    back_cpen.color = lmp->back_color;
+    xi_set_cpen(win, &back_cpen);
+  } else
+    xi_set_cpen(win, &black_cpen);
+  WIDTHLOOP(i, width)
+  {
+    lm_move_to(lmp, p, FALSE, TRUE);
+    lm_draw_line(lmp, p2, FALSE, TRUE);
+    --p.h;
+    --p2.h;
+  }
+  r = lmp->rct;
+  r.left = lmp->rct.right - lmp->rct.left;
+  if (lmp->list_obj->nbr_children <= 0) r.left -= lmp->pixel_width;
+  r.right = 9999;
+  xi_set_cpen(win, &hollow_cpen);
+    cbrush.pat = PAT_SOLID;
+    cbrush.color = lmp->white_space_color;
+    xi_set_cbrush(win, &cbrush);
+    xi_set_clip(win, actual_rct);
+
+#if XIWS == XOLWS || XIWS == MTFWS
+    /* X GRAY SCALE HACK */
+    xi_set_xvt_back_color(win, COLOR_WHITE);
+    {
+      DRAW_CTOOLS ct;
+
+      xi_get_draw_ctools(win, &ct);
+      ct.opaque_text = FALSE;
+      xi_set_draw_ctools(win, &ct);
+      xi_draw_text(win, r.left, r.top, " ", -1);
+    }
+#endif
+
+    lm_draw_rect(lmp, &r, FALSE);
+
+    /* draw border around entire list */
+    lmp_rct.right = actual_r;
+    {
+      RCT r;
+      CBRUSH cb;
+
+      r = lmp->rct;
+      if (list_data->sb_win)
+      {
+        xi_get_sb_rect(list_obj, &vr);
+        /*
+        add one, so that one pixel of the double border will overlap one pixel of the
+        scroll bar.
+        */
+        r.right = vr.right + 1;
+      }
+      else
+      if (list_data->hsb_win)
+        r.right = r.left + lmp->pixel_width + 2 * BORDER_WIDTH;
+      xi_get_hsb_rect(list_obj, &hr);
+      r.bottom = hr.bottom + 1;
+      xi_set_cbrush(win, &hollow_cbrush);
+      xi_set_cpen(win, &black_cpen);
+      xi_set_clip(win, NULL);
+      xi_draw_rect(win, &r);
+      xi_inflate_rect(&r, -1);
+      xi_draw_rect(win, &r);
+
+      cb = white_cbrush;
+      cb.color = lmp->white_space_color;
+      xi_set_cbrush(win, &cb);
+      xi_set_cpen(win, &hollow_cpen);
+      r.left += 1;
+      r.top = lmp->rct.bottom;
+      r.right -= 1;
+      r.bottom -= 1;
+      xi_draw_rect(win, &r);
+    }
+  }
+
+  {   /* rectangle at bottom of list */
+    RCT r;
+    RCT hsb_rect;
+
+    xi_get_hsb_rect(lmp->list_obj, &hsb_rect);
+    cbrush.pat = PAT_SOLID;
+    cbrush.color = lmp->white_space_color;
+    xi_set_cbrush(win, &cbrush);
+    r = lmp->mlr;
+    r.top = lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top;
+    r.top = min(r.top, hsb_rect.top);
+    r.bottom = hsb_rect.bottom;
+    r.right = lmp->rct.right;
+    if (lmp->pixel_width)
+      r.right = lmp->rct.left + lmp->pixel_width + 2;
+    if (r.top < r.bottom)
+    {
+#if XIWS == XOLWS || XIWS == MTFWS
+      /* X GRAY SCALE HACK */
+      xi_set_xvt_back_color(win, COLOR_WHITE);
+      {
+        DRAW_CTOOLS ct;
+
+        xi_get_draw_ctools(win, &ct);
+        ct.opaque_text = FALSE;
+        xi_set_draw_ctools(win, &ct);
+        xi_draw_text(win, r.left, r.top, " ", -1);
+      }
+#endif
+    }
+    xi_draw_rect(win, &r);
+  }
+
+  /* border around entire list */
+  if (! (lmp->update_rows_at_top + lmp->update_rows_at_bottom))
+  {
+    xi_set_cpen(win, &black_cpen);
+    xi_set_cbrush(win, &hollow_cbrush);
+    xi_set_draw_mode(win, M_COPY);
+    xi_set_clip(win, NULL);
+    lmp_rct = lmp->rct;
+    if (lmp->pixel_width)
+      lmp_rct.right = hrule_h;
+    WIDTHLOOP(i, BORDER_WIDTH)
+    {
+      xi_draw_rect(win, &lmp_rct);
+      xi_inflate_rect(&lmp_rct, -1);
+    }
+    CTOS_END;
+  }
+
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  xi_set_clip(win, actual_rct);
+  xi_set_cpen(win, &black_cpen);
+  xi_set_draw_mode(win, M_COPY);
+  if (lmp->pixel_width)
+  {
+    RCT r;
+    PNT p1, p2;
+
+    r = lmp->rct;
+    r.left = lmp->rct.right - lmp->rct.left + BORDER_WIDTH;
+    r.top += BORDER_WIDTH;
+    r.right = 9999;
+    xi_set_cpen(win, &hollow_cpen);
+    cbrush.pat = PAT_SOLID;
+    cbrush.color = lmp->white_space_color;
+    xi_set_cbrush(win, &cbrush);
+    xi_set_clip(win, actual_rct);
+    lm_draw_rect(lmp, &r, FALSE);
+
+    xi_set_cpen(win, &black_cpen);
+    p1.h = r.left;
+    p1.v = lmp->rct.top;
+    p2.h = r.left;
+    p2.v = r.bottom;
+    lm_move_to(lmp, p1, FALSE, TRUE);
+    lm_draw_line(lmp, p2, FALSE, TRUE);
+
+  }
+
+  {   /* rectangle at bottom of list */
+    RCT r;
+
+    cbrush.pat = PAT_SOLID;
+    cbrush.color = lmp->white_space_color;
+    xi_set_cbrush(win, &cbrush);
+    xi_set_cpen(win, &hollow_cpen);
+    r = lmp->mlr;
+    r.left += BORDER_WIDTH;
+    r.top = lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top;
+    r.right = lmp->rct.right;
+    if (lmp->pixel_width)
+      r.right = lmp->rct.left + 2 * lmp->pixel_width;
+    if (r.top < r.bottom)
+      xi_draw_rect(win, &r);
+  }
+  CTOS_END;
+#endif
+  lmp->update_rows_at_top = 0;
+  lmp->update_rows_at_bottom = 0;
+  lmp->update_cells_only = FALSE;
+}
+
+
+/*-------------------------------------------------------------------------
+lm:         current lm
+update:     if TRUE, draw_lm is being called due to an E_UPDATE event
+-------------------------------------------------------------------------*/
+static void near
+draw_lm(LM lm, BOOLEAN update)
+{
+  int hrule_h, actual_r, idx;
+  RCT lmp_rct, actual_rct, clip_rct;
+  RCT hr, vr, urct;
+  XI_OBJ *list_obj;
+  XI_LIST_DATA *list_data;
+  LM_DATA *lmp = LMP(lm);
+  WINDOW win = lmp->win;
+  CBRUSH back_cbrush;
+#if XI_IS_CH
+  CBRUSH lm_cbrush;
+  PNT from_p;
+
+#if XVTWS == WMWS
+  NOREF(urct);
+#endif
+/***********************************************************************/
+/* set up variables for drawing */
+#if XVT_OS != XVT_OS_CTOS
+  c_xd = C_XD;
+  c_xu = C_XU;
+  c_v = C_V;
+  c_xx = C_XX;
+#else
+  c_xd = 220;
+  c_xu = 221;
+  c_v = 225;
+  c_xx = 218;
+  c_xr = 226;
+  c_xl = 227;
+#endif
+#endif
+  if (! (lmp->attrib & LM_ATR_VISIBLE))
+  {
+    lmp->update_rows_at_top = 0;
+    lmp->update_rows_at_bottom = 0;
+    return;
+  }
+  list_obj = lmp->list_obj;
+  list_data = list_obj->v.list;
+  lmp_rct = lmp->rct;
+  actual_rct = lmp_rct;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  if (lmp->pixel_width)
+    actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
+  else
+    actual_r = lmp->rct.right;
+  actual_rct.right = actual_r - BORDER_WIDTH;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  if (lmp->pixel_width)
+    actual_r = lmp->rct.left + lmp->pixel_width;
+  else
+    actual_r = lmp->rct.right + 8;
+  actual_rct.right = actual_r;
+  CTOS_END;
+#endif
+  hrule_h = actual_r;
+  if (lmp->pixel_width)
+    lmp_rct.right = hrule_h;
+  urct = lmp_rct;
+  if (list_data->sb_win)
+  {
+    if (list_data->have_sb_rct)
+      vr = list_data->sb_rct;
+    else
+      xi_get_sb_rect(list_obj, &vr);
+    urct.right = vr.right;
+  }
+  if (list_data->hsb_win)
+  {
+    if (list_data->have_hsb_rct)
+      hr = list_data->hsb_rct;
+    else
+      xi_get_hsb_rect(list_obj, &hr);
+    urct.bottom = hr.bottom;
+  }
+#if XIWS != WMWS
+  if (update && !xi_needs_update(win, &urct))
+  {
+    lmp->update_rows_at_top = 0;
+    lmp->update_rows_at_bottom = 0;
+    return;
+  }
+#endif
+  lmp_rct = lmp->rct;
+  if (lmp->nbr_realized_rows)
+  {
+    idx = lmp->nbr_realized_rows - 1;
+    lmp->rrr_bottom = lmp->pix_offsets[idx] + lmp->pix_heights[idx];
+  }
+  else
+    lmp->rrr_bottom = 0;
+  if (! lm_tools_inited)
+  {
+    lm_white_cbrush.color = COLOR_WHITE;
+    lm_white_cbrush.pat = PAT_SOLID;
+    lm_black_cpen.width = 1;
+    lm_black_cpen.color = COLOR_BLACK;
+    lm_black_cpen.pat = PAT_SOLID;
+    lm_black_cpen.style = P_SOLID;
+    xvt_app_get_default_ctools(&lm_normal_ctools);
+  }
+
+  /***********************************************************************/
+  /* draw anything other than in the cell region */
+  /* prior to this, there are no calls to XVT for drawing */
+
+  back_cbrush = lm_white_cbrush;
+/*
+TO OPTIMIZE BACKGROUND DRAWING, USE THE FOLLOWING LINE, AND DON'T SET TO HOLLOW
+  back_cbrush.color = lmp->back_color;
+*/
+#if XIWS != WMWS
+  back_cbrush.pat = PAT_HOLLOW;
+#endif
+  xi_set_cbrush(win, &back_cbrush);
+  xi_set_cpen(win, &lm_black_cpen);
+  clip_rct = actual_rct;
+#if XVTWS == WMWS
+  if (list_data->hsb_win)
+  clip_rct.bottom += 8;
+  clip_rct.right += 8;
+#endif
+  xi_set_clip(win, &clip_rct);
+  xi_set_draw_mode(win, M_COPY);
+
+  /*
+  CBRUSH: white_cbrush
+  CPEN:   black_cpen
+  CLIP:   actual_rct
+  */
+
+  /*********** draw the rectangle around the list ***********/
+  draw_list_rect(lmp, &vr, &hr);
+
+#if XVTWS == WMWS
+  xi_set_clip(win, &actual_rct);
+#endif
+
+  /*********** draw the rules between the heading and the cells ***********/
+  if (! lmp->update_cells_only)
+    draw_heading_rules(lmp, hrule_h);
+
+  /*********** draw column rules ***********/
+  draw_column_rules(lmp);
+
+  /*
+  CBRUSH: white_cbrush
+  CPEN:   black_cpen OR back_color cpen
+  CLIP:   actual_rct
+  */
+
+#if 0
+  /*********** draw row rules ***********/
+  /* this was moved to draw_cell_block */
+  draw_row_rules(lmp, -1, -1, update);
+#endif
+
+  /*********** draw column headings ***********/
+  if (! lmp->update_cells_only)
+    draw_column_headings(lmp, &actual_rct);
+  xi_set_clip(win, NULL);
+
+  /*********** draw text in cells ***********/
+  fast_draw_cells(lmp, update);
+
+  draw_other_rectangles(lmp, &actual_rct);
+
+    /*********** draw column rules ***********/
+    /* Moved after the draw row rules otherwise
+      no_horz_lines results in spotted vertical lines */
+  if (lmp->no_horz_lines && ! lmp->no_vert_lines)
+    draw_column_rules(lmp);
+
+
+  xi_set_clip(win, NULL);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_hit_test
+lm:         current lm
+ep:         xvt event
+oevt:       original xvt event, without virtual space coordinate conversions
+rowp:       if set, to be filled in with the results of the row hit test
+columnp:    if set, to be filled in with the results of the column hit test
+is_vis:     row is fully visible
+is_part_vis:row is partially visible
+returns:    0 - no hit
+      1 - hit
+      5 - hit on cell button
+-------------------------------------------------------------------------*/
+static int near
+lm_hit_test(LM lm, EVENT *ep, EVENT *oevt, int *rowp, int *columnp,
+            BOOLEAN *is_vis, BOOLEAN *is_hit, BOOLEAN *is_part_vis)
+{
+  int row, column, temp, col_offset, tmp_v, i, first, last;
+  int *pix_offsetsp, *pix_heightsp;
+  LM_DATA *lmp = LMP(lm);
+  PNT where;
+
+  if (is_vis)
+    *is_vis = TRUE;
+  if (is_hit)
+    *is_hit = FALSE;
+  if (is_part_vis)
+    *is_part_vis = FALSE;
+  col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+  where = ep->v.mouse.where;
+
+  /* if the mouse is to the left or the right of the list, return 0 */
+  if (oevt->v.mouse.where.h < 0)
+    return 0;
+  if (lmp->pixel_width &&
+      (oevt->v.mouse.where.h > (lmp->rct.left + lmp->pixel_width
+      + BORDER_WIDTH)))
+    return 0;
+
+  /* if the mouse is in the column headings */
+  if (where.v > lmp->pix_top && where.v < lmp->pix_row1_top)
+  {
+    for (column = 0; column < lmp->nbr_columns; column++)
+    {
+      LM_COLUMN_DATA *column_data;
+
+      column_data = lmp->lm_column_data[column];
+      temp = column_data->x_pix_pos + col_offset;
+      if (where.h >= temp && where.h < temp + column_data->pix_width)
+      {
+        *rowp = -1;
+        *columnp = column;
+        return 1;
+      }
+    }
+    return 0;
+  }
+
+  /* if the mouse is above the list, return 0 */
+  if (where.v < lmp->pix_row1_top)
+    return 0;
+
+  /* figure out what row the mouse is in */
+  tmp_v = where.v - lmp->mlr.top - lmp->rrr_offset;
+  first = max(lmp->first_fully_vis - 1, 0);
+  last = min(lmp->last_fully_vis + 1, lmp->nbr_realized_rows - 1);
+  for (i = first,
+      pix_offsetsp = &lmp->pix_offsets[i],
+      pix_heightsp = &lmp->pix_heights[i];
+      i <= last; ++i, ++pix_offsetsp, ++pix_heightsp)
+  {
+    if (tmp_v >= *pix_offsetsp && tmp_v < (*pix_offsetsp + *pix_heightsp))
+    {
+      row = i;
+      break;
+    }
+  }
+  if (i > last)
+  {
+    if (is_vis)
+      *is_vis = FALSE;
+    return 0;
+  }
+  if (is_vis)
+  {
+    if (i < lmp->first_fully_vis || i > lmp->last_fully_vis)
+    {
+      *is_vis = FALSE;
+      if ((i == lmp->last_fully_vis + 1) && (ep->v.mouse.where.v < lmp->mlr.bottom))
+      {
+        if (is_part_vis)
+          *is_part_vis = TRUE;
+      }
+    }
+    else
+      *is_vis = TRUE;
+  }
+  else
+    if (i < lmp->first_fully_vis || i > lmp->last_fully_vis)
+      return 0;
+  for (column = 0; column < lmp->nbr_columns; column++)
+  {
+    LM_COLUMN_DATA *column_data;
+
+    column_data = lmp->lm_column_data[column];
+    temp = column_data->x_pix_pos + col_offset;
+    if (where.h >= temp && where.h < temp + column_data->pix_width)
+    {
+      if (((lmp->attrib & (LM_ATR_ENABLED | LM_ATR_VISIBLE)) == (LM_ATR_ENABLED | LM_ATR_VISIBLE))
+        && (lmp->lm_column_data[column]->attrib & (LM_COL_ATR_ENABLED | LM_COL_ATR_SELECTABLE)))
+      {
+        LM_CELL_DATA *cell_data;
+
+        *rowp = row;
+        *columnp = column;
+        if (is_hit)
+          *is_hit = TRUE;
+        cell_data = &lmp->cell_data[row][column];
+        if (cell_data->button)
+        {
+          RCT outer_rct;
+          PNT p;
+
+          lm_get_cell_rect(&outer_rct, lm, row, column, FALSE, FALSE);
+          xi_inflate_rect(&outer_rct, 1);
+          if (cell_data->button_on_left)
+            outer_rct.right = outer_rct.left + lmp->pix_row_spacing;
+          else
+            outer_rct.left = outer_rct.right - lmp->pix_row_spacing;
+          p = ep->v.mouse.where;
+          p.v = tmp_v;
+          if (xvt_rect_has_point(&outer_rct, p))
+          {
+            return 5;
+          }
+        }
+        return 1;
+      }
+      else
+      {
+        *rowp = row;
+        *columnp = column;
+        if (is_hit)
+          *is_hit = TRUE;
+        if (is_part_vis)
+          *is_part_vis = FALSE;
+        return 0;
+      }
+    }
+  }
+  if (is_part_vis)
+    *is_part_vis = FALSE;
+  return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_vsize_hit_test
+lm:         current lm
+ep:         xvt event
+rowp:       row, to be filled in
+columnp:    column, to be filled in
+returns:    FALSE if hit test did not fall on place where column could be vertically sized.
+-------------------------------------------------------------------------*/
+static BOOLEAN near
+lm_vsize_hit_test(LM_DATA *lmp, EVENT *ep, int *rowp, int *columnp)
+{
+  int i, n, v;
+  int *pix_offsetsp;
+  int *pix_heightsp;
+
+  if (lmp->lm_column_data[*columnp]->size_rows)
+  {
+    v = ep->v.mouse.where.v - lmp->rrr_offset - lmp->mlr.top;
+    for (i = 0,
+        pix_offsetsp = &lmp->pix_offsets[i],
+        pix_heightsp = &lmp->pix_heights[i];
+        i < lmp->nbr_realized_rows;
+        ++i, ++pix_offsetsp, ++pix_heightsp)
+    {
+      n = *pix_offsetsp + *pix_heightsp;
+      if (v >= n - 3 && v <= n + 1)
+      {
+        *rowp = i;
+        return TRUE;
+      }
+    }
+    return FALSE;
+  }
+  else
+    return FALSE;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_size_hit_test
+lm:         current lm
+ep:         xvt event
+columnp:    column, to be filled in
+returns:    FALSE if hit test did not fall on place where column could be sized.
+-------------------------------------------------------------------------*/
+static BOOLEAN near
+lm_size_hit_test(LM lm, EVENT *ep, int *columnp)
+{
+  int column, temp, col_offset;
+  LM_DATA *lmp = LMP(lm);
+  PNT where;
+
+  col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+  where = ep->v.mouse.where;
+  if (where.h < 0)
+    return FALSE;
+  if (lmp->pixel_width && (where.h > (lmp->pixel_width + lmp->delta_x)
+      + 2 * BORDER_WIDTH))
+    return FALSE;
+  if (where.v > lmp->pix_top && where.v < lmp->pix_row1_top)
+  {
+    for (column = 0; column < lmp->nbr_columns; column++)
+    {
+      LM_COLUMN_DATA *column_data;
+
+      if (column >= lmp->fixed_columns && column < lmp->first_vis)
+        continue;
+      column_data = lmp->lm_column_data[column];
+      temp = column_data->x_pix_pos +
+          col_offset +
+          column_data->pix_width;
+      if (where.h >= temp &&
+          where.h < temp + col_offset * 2 + RULE_WIDTH_V)
+      {
+        *columnp = column;
+        return TRUE;
+      }
+    }
+    return FALSE;
+  }
+  return FALSE;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   calc_y
+lmp:        current lmp
+ep:         xvt event
+returns:    Calculates and returns the Y pixel position of the rubber band line.
+      Used only when sizing rows.
+-------------------------------------------------------------------------*/
+static int
+calc_y(LM_DATA *lmp, EVENT *ep)
+{
+  int row = lmp->row_being_sized;
+  int temp;
+  int min_height_in_pix = 4;
+  int v;
+
+  v = min(lmp->mlr.bottom, ep->v.mouse.where.v) - lmp->rrr_offset - lmp->mlr.top;
+  temp = lmp->pix_offsets[row] + min_height_in_pix;
+  temp = max(v, temp);
+  return temp;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   rubber_y
+lmp:        current lmp
+y:          draw a rubber line at position y
+-------------------------------------------------------------------------*/
+static void
+rubber_y(LM_DATA *lmp, int y)
+{
+#if XI_IS_NOT_CH
+  int left, right;
+  DRAW_CTOOLS new_ctools;
+  PNT pnt;
+  WINDOW win = lmp->win;
+
+  CTOS_IS_PM;
+  left = lmp->mlr.left;
+  right = lmp->mlr.right;
+  if (lmp->pixel_width)
+    right = left + lmp->pixel_width + BORDER_WIDTH;
+  xvt_app_get_default_ctools(&new_ctools);
+  xi_set_draw_ctools(win, &new_ctools);
+  xi_set_cpen(win, &rubber_cpen);
+  xi_set_draw_mode(win, M_XOR);
+  xi_set_clip(win, NULL);
+  pnt.h = left;
+  pnt.v = y;
+  lm_move_to(lmp, pnt, TRUE, FALSE);
+  pnt.h = right;
+  lm_draw_line(lmp, pnt, TRUE, FALSE);
+  CTOS_END;
+#endif
+  NOREF(lmp);
+  NOREF(y);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_vsize_event
+lmp:        current lmp
+ep:         xvt event
+-------------------------------------------------------------------------*/
+static void
+lm_vsize_event(LM_DATA *lmp, EVENT *ep)
+{
+  int y;
+
+  switch (ep->type)
+  {
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+    y = calc_y(lmp, ep);
+    lmp->last_y = y;
+    rubber_y(lmp, y);
+    break;
+  case E_MOUSE_MOVE:
+    y = calc_y(lmp, ep);
+    rubber_y(lmp, lmp->last_y);
+    lmp->last_y = y;
+    rubber_y(lmp, y);
+    break;
+  case E_MOUSE_UP:
+    {
+      int delta, row;
+      XI_OBJ row_obj;
+
+      row = lmp->row_being_sized;
+      y = calc_y(lmp, ep);
+      rubber_y(lmp, lmp->last_y);
+      delta = y - lmp->pix_offsets[row] + 1;
+      XI_MAKE_ROW(&row_obj, lmp->list_obj, row);
+      if (do_lm_cb((LM)lmp, LM_CB_ROW_SIZE, row, 0, NULL, NULL, delta))
+      {
+        xi_set_row_height(&row_obj, delta);
+        calculate_pix_offsets(lmp, FALSE );
+      }
+      lm_make_vis(lmp);
+      break;
+    }
+  }
+}
+
+
+
+
+/*-------------------------------------------------------------------------
+function:       send_txt_event
+lm:             current lm
+txt:            txt object
+ep:             xvt event
+gaining_focus:  if TRUE, the edit control is gaining focus as this function is called
+returns:        TRUE if the event was used
+-------------------------------------------------------------------------*/
+static BOOLEAN near
+send_txt_event(LM lm, TXT_DATA *txt, EVENT *ep,
+BOOLEAN gaining_focus, BOOLEAN send_to_txt)
+{
+  BOOLEAN retval = FALSE;
+  int ch;
+  LM_DATA *lmp = LMP(lm);
+
+  if (! lmp->txt)
+    return FALSE;
+  if (ep->type == E_CHAR)
+  {
+    ch = ep->v.chr.ch;
+    if ( (ch >= ' ' || ch == K_CLEAR || ch == K_DEL || ch == '\b')
+        && ch != K_BTAB && ch != K_UP && ch != K_DOWN )
+    {
+      int     focus_row, focus_column;
+      BOOLEAN v_scrolled;
+
+      lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+      retval = do_lm_cb( lm, LM_CB_CHAR, focus_row, focus_column, ep, NULL, 0);
+      /* retval = FALSE if event refused */
+      if (! retval)
+        return FALSE;
+    }
+  }
+
+  if (send_to_txt)
+  {
+    retval = txt_event(txt, ep, gaining_focus);
+
+    /* check flags */
+    if (txt->flags & TXT_FLAG_TEXT)
+    {
+      int     focus_row, focus_column;
+      BOOLEAN v_scrolled;
+
+      lmp->itf_obj->v.itf->chg_flag = TRUE;
+      lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+      do_lm_cb(lm, LM_CB_CHANGE, focus_row, focus_column, NULL, NULL, 0);
+    }
+    /* reset flags */
+    txt->flags = 0;
+  }
+  return retval;
+}
+
+
+/*-------------------------------------------------------------------------
+function:       lm_select_cells_hit_test
+lmp:            current lmp
+ep:             xvt event
+rowp:           row number, to be filled in
+columnp:        column number, to be filled in
+on_disabled:    if TRUE, then the hit was on a disabled column
+returns:        TRUE if there was a hit
+-------------------------------------------------------------------------*/
+static BOOLEAN
+lm_select_cells_hit_test(LM_DATA *lmp, EVENT *ep, int *rowp,
+int *columnp, BOOLEAN *on_disabled)
+{
+  int delta_top, column, col_offset, last_vis, row, idx;
+  LM_COLUMN_DATA *column_data;
+  BOOLEAN retval;
+  BOOLEAN inv_v, inv_h;   /* if set to TRUE, then invalid v or invalid h */
+
+  retval = TRUE;
+  if (columnp)
+    *columnp = 0;
+  if (on_disabled)
+    *on_disabled = FALSE;
+  inv_v = FALSE;
+  inv_h = FALSE;
+  last_vis = lmp->last_vis;
+  delta_top = ep->v.mouse.where.v - lmp->mlr.top - lmp->rrr_offset;
+
+  /* If list has no columns */
+  if (lmp->nbr_columns <= 0) return FALSE;
+  /*
+  If mouse is above the top of the first row
+  */
+  if (ep->v.mouse.where.v < lmp->pix_row1_top - RULE_WIDTH_V -
+      RULE_Y_OFFSET_TOP)
+  {
+    if (rowp)
+      *rowp = 0;
+    retval = FALSE;
+    inv_v = TRUE;
+  }
+
+  /*
+  if mouse is below the bottom of the list, or if the mouse is
+  below the bottom of the last row if there are fewer rows than
+  can be displayed in the list
+    */
+  idx = lmp->nbr_realized_rows - 1;
+  if (ep->v.mouse.where.v >= lmp->mlr.bottom ||
+      delta_top > lmp->pix_offsets[idx] + lmp->pix_heights[idx])
+  {
+    if (rowp)
+      *rowp = lmp->nbr_realized_rows;
+    retval = FALSE;
+    inv_v = TRUE;
+  }
+
+  /*
+  if mouse is to the right of the list, or if the mouse is to the right of the
+  rightmost column
+  */
+  column_data = lmp->lm_column_data[lmp->nbr_columns - 1];
+  if ((ep->v.mouse.where.h >= (lmp->rct.right - lmp->rct.left)) ||
+      (ep->v.mouse.where.h >= (column_data->x_pix_pos + column_data->pix_width)))
+  {
+    if (columnp)
+      *columnp = last_vis + 1;
+    retval = FALSE;
+    inv_h = TRUE;
+  }
+
+  /*
+  if mouse has a valid y coordinate
+    */
+  if (! inv_v)
+  {
+
+    if (rowp)
+      *rowp = 0;
+    retval = FALSE;
+    for (row = 0; row < lmp->nbr_realized_rows; ++row)
+    {
+      int pix_offset, pix_height;
+
+      pix_offset = lmp->pix_offsets[row];
+      pix_height = lmp->pix_heights[row];
+      if (delta_top >= pix_offset - SELECT_CELLS_OFFSET - 2
+          && delta_top <= pix_offset + SELECT_CELLS_OFFSET)
+      {
+        if (rowp)
+          *rowp = row;
+        if (! inv_h)
+          retval = TRUE;
+        break;
+      }
+      if (delta_top >= (pix_offset + pix_height) - SELECT_CELLS_OFFSET - 2
+          && delta_top <= (pix_offset + pix_height) + SELECT_CELLS_OFFSET)
+      {
+        if (rowp)
+          *rowp = row + 1;
+        if (! inv_h)
+          retval = TRUE;
+        break;
+      }
+      if (delta_top >= pix_offset &&
+          delta_top <= pix_offset + pix_height)
+      {
+        if (rowp)
+          *rowp = row;
+      }
+    }
+    if (rowp && ! retval && *rowp < lmp->down_row)
+      ++*rowp;
+  }
+
+  /*
+  if mouse has a valid x coordinate
+    */
+  if (! inv_h)
+  {
+    column_data = lmp->lm_column_data[0];
+    col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+    if (((! (column_data->attrib & XI_ATR_ENABLED) || lmp->down_on_disabled) &&
+        (! (column_data->attrib & XI_ATR_SELECTABLE))) &&
+        ((ep->v.mouse.where.h >= column_data->x_pix_pos) &&
+        (ep->v.mouse.where.h < (column_data->x_pix_pos + column_data->pix_width))))
+    {
+      if (columnp)
+        *columnp = 0;
+      if (on_disabled)
+        *on_disabled = TRUE;
+    }
+    else if ((ep->v.mouse.where.h >= column_data->x_pix_pos) &&
+        (ep->v.mouse.where.h < (column_data->x_pix_pos + col_offset)))
+    {
+      if (columnp)
+        *columnp = 0;
+    }
+    else
+    {
+      BOOLEAN found = FALSE;
+      int last_col;
+
+    last_col = -1;
+    for (column = 0; column < lmp->nbr_columns; column++)
+      {
+        int temp;
+
+        column_data = lmp->lm_column_data[column];
+        if (((! (column_data->attrib & XI_ATR_ENABLED) || lmp->down_on_disabled) &&
+            (! (column_data->attrib & XI_ATR_SELECTABLE))) &&
+            ((ep->v.mouse.where.h >= column_data->x_pix_pos) &&
+            (ep->v.mouse.where.h <
+            (column_data->x_pix_pos + column_data->pix_width))))
+        {
+          if (columnp)
+            *columnp = column;
+          if (on_disabled)
+            *on_disabled = TRUE;
+          found = TRUE;
+          break;
+        }
+        temp = column_data->x_pix_pos +
+            col_offset +
+            column_data->pix_width - SELECT_CELLS_OFFSET;
+        if (ep->v.mouse.where.h >= temp &&
+            ep->v.mouse.where.h < (temp + col_offset * 2
+            + 2 * SELECT_CELLS_OFFSET
+            + RULE_WIDTH_V))
+        {
+          if (columnp)
+            *columnp = column + 1;
+          found = TRUE;
+          break;
+        }
+        if (ep->v.mouse.where.h >= temp)
+          last_col = column;
+      }
+      if (! found)
+      {
+        retval = FALSE;
+        if (columnp)
+        {
+          if ((last_col + 1) < lmp->down_column)
+            *columnp = last_col + 2;
+          else
+            *columnp = last_col + 1;
+        }
+      }
+    }
+  }
+  /*
+  If v is not invalid, and if h is not invalid, and if the column is valid, then
+  if the column is enabled, then the hit test must be within a range of the rules.
+  If the column is not enabled, then the hit test may be anywhere within the cell.
+  */
+  if (! inv_v)
+  {
+    BOOLEAN enabled_col = FALSE;
+
+    if (columnp && ! inv_h)
+    {
+      if (*columnp >= lmp->nbr_columns)
+        enabled_col = FALSE;
+      else
+        enabled_col = (lmp->lm_column_data[*columnp]->attrib & XI_ATR_ENABLED &&
+        ! lmp->down_on_disabled);
+      if (enabled_col)
+      {
+        delta_top = ep->v.mouse.where.v - lmp->mlr.top - lmp->rrr_offset;
+        retval = FALSE;
+        for (row = 0; row < lmp->nbr_realized_rows; ++row)
+        {
+          int pix_offset, pix_height;
+
+          pix_offset = lmp->pix_offsets[row];
+          pix_height = lmp->pix_heights[row];
+          if (delta_top >= pix_offset - SELECT_CELLS_OFFSET - 2
+              && delta_top <= pix_offset + SELECT_CELLS_OFFSET)
+          {
+            if (rowp)
+              *rowp = row;
+            retval = TRUE;
+            break;
+          }
+          if (delta_top >= (pix_offset + pix_height) - SELECT_CELLS_OFFSET - 2
+              && delta_top <= (pix_offset + pix_height) + SELECT_CELLS_OFFSET)
+          {
+            if (rowp)
+              *rowp = row + 1;
+            retval = TRUE;
+            break;
+          }
+        }
+        return retval;
+      }
+    }
+  }
+  return retval;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   invert_selection
+lmp:        current lmp
+r:          row
+c:          column
+-------------------------------------------------------------------------*/
+static void invert_selection(LM_DATA *lmp, int r, int c, BOOLEAN v_scrolled)
+{
+  unsigned long attrib;
+
+  attrib = lm_get_attrib((LM)lmp, LM_CELL, r, c, v_scrolled);
+  if (attrib & LM_CELL_ATR_SELECTED)
+    lm_set_attrib((LM)lmp, LM_CELL, r, c, v_scrolled,
+        attrib & ~LM_CELL_ATR_SELECTED, FALSE);
+  else
+    lm_set_attrib((LM)lmp, LM_CELL, r, c, v_scrolled,
+        attrib | LM_CELL_ATR_SELECTED, FALSE);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   in_rct
+rct:        rectangle
+r:          row
+c:          column
+returns:    TRUE if c and r are in rct
+-------------------------------------------------------------------------*/
+static BOOLEAN
+in_rct(RCT *rct, int r, int c)
+{
+  if (c >= rct->left && c < rct->right && r >= rct->top && r < rct->bottom)
+    return TRUE;
+  return FALSE;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_select_cell_event
+lmp:        current lmp
+ep:         xvt event
+-------------------------------------------------------------------------*/
+static void
+lm_select_cell_event(LM_DATA *lmp, EVENT *ep)
+{
+  int row, column;
+
+  switch (ep->type)
+  {
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+    if (! ep->v.mouse.shift)
+    {
+      int r, c;
+
+      for (r = 0; r < lmp->nbr_realized_rows; ++r)
+        for (c = 0; c < lmp->nbr_columns; ++c)
+        {
+          unsigned long attrib;
+
+          attrib = lm_get_attrib((LM)lmp, LM_CELL, r, c, FALSE);
+          if (attrib & LM_CELL_ATR_SELECTED)
+            lm_set_attrib((LM)lmp, LM_CELL, r, c, FALSE,
+                attrib & ~LM_CELL_ATR_SELECTED, FALSE);
+        }
+    }
+    break;
+  case E_MOUSE_MOVE:
+  case E_MOUSE_UP:
+    {
+      int last_cur_row, last_cur_column, r, c, down_row, down_column;
+      RCT old_rct, new_rct, enclosing_rct;
+
+      lm_select_cells_hit_test(lmp, ep, &row, &column, NULL);
+      last_cur_row = lmp->cur_row;
+      last_cur_column = lmp->cur_column;
+      down_row = lmp->down_row;
+      down_column = lmp->down_column;
+      if (lmp->down_on_disabled)
+      {
+        if (ep->type == E_MOUSE_UP)
+          lmp->down_on_disabled = FALSE;
+        if (row >= lmp->down_row)
+          lmp->cur_row = row + 1;
+        else
+          lmp->cur_row = row;
+        if (column >= lmp->down_column)
+          lmp->cur_column = column + 1;
+        else
+          lmp->cur_column = column;
+      }
+      else
+      {
+        lmp->cur_row = row;
+        lmp->cur_column = column;
+      }
+      if (lmp->cur_row == last_cur_row && lmp->cur_column == last_cur_column &&
+          (ep->type == E_MOUSE_MOVE || ep->type == E_MOUSE_UP))
+        break;
+      old_rct.left = min(down_column, last_cur_column);
+      old_rct.right = max(down_column, last_cur_column);
+      old_rct.top = min(down_row, last_cur_row);
+      old_rct.bottom = max(down_row, last_cur_row);
+      new_rct.left = min(down_column, lmp->cur_column);
+      new_rct.right = max(down_column, lmp->cur_column);
+      new_rct.top = min(down_row, lmp->cur_row);
+      new_rct.bottom = max(down_row, lmp->cur_row);
+      enclosing_rct.top = min(old_rct.top, new_rct.top);
+      enclosing_rct.bottom = max(old_rct.bottom, new_rct.bottom);
+      enclosing_rct.left = min(old_rct.left, new_rct.left);
+      enclosing_rct.right = max(old_rct.right, new_rct.right);
+      for (c = enclosing_rct.left; c <= enclosing_rct.right; ++c)
+      {
+        for (r = enclosing_rct.top; r <= enclosing_rct.bottom; ++r)
+        {
+          if ((in_rct(&old_rct, r, c) &&
+              in_rct(&new_rct, r, c)) ||
+              (! in_rct(&old_rct, r, c) &&
+              ! in_rct(&new_rct, r, c)))
+            continue;
+          if (r >= lmp->nbr_realized_rows || c >= lmp->nbr_columns ||
+              r < 0 || c < 0)
+            continue;
+          invert_selection(lmp, r, c, FALSE);
+        }
+      }
+    }
+    break;
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_cell_btn_event
+lmp:        current lmp
+ep:         xvt event
+oevp:       xvt event, without virtual coordinate conversion
+-------------------------------------------------------------------------*/
+static void
+lm_cell_btn_event(LM_DATA *lmp, EVENT *ep, EVENT *oevp)
+{
+  RCT mr;
+  int hit_test_value, row, col;
+
+  mr = lmp->mlr;
+  if (lmp->pixel_width)
+    mr.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
+
+  hit_test_value = lm_hit_test((LM)lmp, ep, oevp, &row, &col, NULL, NULL, NULL);
+
+  if (hit_test_value)
+  {
+    switch (ep->type)
+    {
+    case E_MOUSE_DOWN:
+    case E_MOUSE_DBL:
+      lmp->down_in_btn = TRUE;
+      lmp->btn_down = TRUE;
+      lmp->btn_down_row = row;
+      lmp->btn_down_col = col;
+      xi_trap_mouse(lmp->win);
+      xi_set_trap_obj(lmp->list_obj);
+      redraw_cell_button(lmp, row, col, &mr, lmp->btn_down, FALSE);
+      break;
+    case E_MOUSE_MOVE:
+      {
+        BOOLEAN last = lmp->btn_down;
+
+        if (hit_test_value != 5 || row != lmp->btn_down_row || col != lmp->btn_down_col)
+          lmp->btn_down = FALSE;
+        else
+          lmp->btn_down = TRUE;
+        if (last != lmp->btn_down)
+        {
+          redraw_cell_button(lmp, lmp->btn_down_row, lmp->btn_down_col, &mr,
+              lmp->btn_down, FALSE);
+          last = lmp->btn_down;
+        }
+        break;
+      }
+    case E_MOUSE_UP:
+      if (lmp->btn_down)
+        redraw_cell_button(lmp, lmp->btn_down_row, lmp->btn_down_col, &mr,
+            FALSE, FALSE);
+      lmp->btn_down = FALSE;
+      lmp->down_in_btn = FALSE;
+      if (hit_test_value == 5 && row == lmp->btn_down_row && col == lmp->btn_down_col)
+        do_lm_cb((LM)lmp, LM_CB_CELL_BTN, row, col, ep, NULL, 0);
+      break;
+    }
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:   get_select_column
+-------------------------------------------------------------------------*/
+static int get_select_column( LM_DATA* lmp )
+{
+  int col;
+
+  for ( col = 0; col < lmp->nbr_columns; col++ )
+    if ( LM_COL_ATTR( (LM)lmp, col ) & XI_ATR_SELECTABLE )
+      return col;
+  return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   select_row
+-------------------------------------------------------------------------*/
+void select_row( LM lm, int row, int column, BOOLEAN dbl_click )
+{
+  unsigned long attrib;
+  LM_CB_DATA lm_cb_data;
+  XI_OBJ *old_itf;
+  int old_row;
+  LM_DATA* lmp = LMP(lm);
+
+  old_row = find_selection( lmp );
+  if ( old_row != row && old_row != -1 )
+  {
+    attrib = lm_get_attrib( lm, LM_ROW, old_row, 0, FALSE );
+    attrib &= ~LM_ROW_ATR_SELECTED;
+    lm_set_attrib( lm, LM_ROW, old_row, 0, FALSE, attrib, FALSE );
+  }
+  attrib = lm_get_attrib( lm, LM_ROW, row, 0, FALSE );
+  attrib |= LM_ROW_ATR_SELECTED;
+  lm_cb_data.lm = lm;
+  lm_cb_data.cb_type = LM_CB_SELECT;
+  lm_cb_data.cid = lmp->cid;
+  lm_cb_data.win = lmp->win;
+  lm_cb_data.row = (unsigned char)row;
+  if ( column == -1 )
+    column = (unsigned char)get_select_column( lmp );
+  lm_cb_data.column = column;
+  lm_cb_data.v.select.selected = TRUE;
+  lm_cb_data.v.select.dbl_click = dbl_click;
+  lm_cb_data.v.select.shift = FALSE;
+  lm_cb_data.v.select.control = FALSE;
+  old_itf = lmp->itf_obj;
+  (*lmp->lm_cb)(&lm_cb_data);
+  if (xi_is_itf(old_itf))
+    if ( !lm_cb_data.v.select.refused && old_row != row )
+      lm_set_attrib( lm, LM_ROW, row, 0, FALSE, attrib, FALSE );
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_event
+lm:         current lm
+ep:         xvt event
+return:     TRUE if event is consumed
+-------------------------------------------------------------------------*/
+int
+lm_event(LM lm, EVENT *ep)
+{
+  int row, column;
+  LM_DATA *lmp = LMP(lm);
+  BOOLEAN send_event = FALSE;
+  int retval = 1;
+  EVENT oevt;
+  XI_OBJ *itf = lmp->itf_obj;
+
+  oevt = *ep;
+  switch(ep->type)
+  {
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+  case E_MOUSE_MOVE:
+  case E_MOUSE_UP:
+    {
+      RCT rct;
+
+      if (lmp->attrib & XI_ATR_VISIBLE)
+      {
+        /*
+        COORDINATE CONVERSION
+        changes horizontal coordinates - moves mouse to the right -
+        increases where.h if where.h is > lmp->vir_left, so that where.h
+        is in the correct virtual horizontal space - also makes where.h
+        be relative to the list, not the window.
+        */
+        lm_get_rect(lm, LM_LIST, 0, &rct);
+        if (xvt_rect_has_point(&rct, ep->v.mouse.where) ||
+            lmp->selecting_cells || lmp->sizing_column || lmp->moving_column ||
+            lmp->down_in_btn || lmp->selecting_text || lmp->sizing_row)
+        {
+          if (ep->type == E_MOUSE_DOWN)
+          {
+            if (ep->v.mouse.where.h >= lmp->vir_left)
+              lmp->down_in_hscrolling = TRUE;
+            else
+              lmp->down_in_hscrolling = FALSE;
+          }
+          if (! lmp->sizing_column)
+          {
+            if ((lmp->pixel_width && (ep->v.mouse.where.h >= lmp->vir_left)))
+            {
+              ep->v.mouse.where.h += lmp->delta_x;
+              lmp->in_hscrolling = TRUE;
+            }
+            else
+              lmp->in_hscrolling = FALSE;
+          }
+          else
+          {
+            if (lmp->down_in_hscrolling)
+              ep->v.mouse.where.h += lmp->delta_x;
+          }
+          ep->v.mouse.where.h -= lmp->rct.left;
+        }
+        else
+        {
+          *ep = oevt;
+          return FALSE;
+        }
+      }
+      else
+      {
+        *ep = oevt;
+        return FALSE;
+      }
+      break;
+    }
+  }
+  switch(ep->type)
+  {
+  case E_UPDATE:
+    /* the following code sends the event directly on to redraw_cell
+      if text is being scrolled in a text object. This speeds horizontal
+      scrolling. see also lm_text_scrolling.
+      */
+    if (lmp->text_scrolling)
+    {
+      int row, col;
+      BOOLEAN is_vert_scrolled;
+
+      lm_get_focus_cell(lmp, &row, &col, &is_vert_scrolled);
+      draw_cell_range(lmp, row, row, col, col, FALSE);
+      if ( lmp->txt != NULL )
+        send_txt_event( lm, lmp->txt, &oevt, FALSE, TRUE );
+      lmp->text_scrolling = FALSE;
+    }
+    else
+    {
+      draw_lm(lm, TRUE);
+      if ( lmp->txt != NULL )
+        send_txt_event( lm, lmp->txt, &oevt, FALSE, TRUE );
+    }
+    retval = 0;
+    break;
+  case E_SIZE:
+    {
+      int new_height, new_width;
+      RCT hr, vr, cr;
+      XI_OBJ *list_obj;
+
+      if (lmp->resize_with_window)
+      {
+        RCT rct, wrct;
+
+        list_obj = lmp->list_obj;
+        if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+          lm_make_invis(lmp);
+        else
+        {
+          if (lm_list_has_focus(lmp))
+          {
+            if (! xi_move_focus(list_obj->itf))
+            {
+              retval = 0;
+              break;
+            }
+          }
+        }
+        xi_get_hsb_rect(list_obj, &hr);
+        xi_get_sb_rect(list_obj, &vr);
+        xvt_vobj_get_client_rect(lmp->win, &cr);
+        new_height = cr.bottom - lmp->pix_top;
+        new_width = cr.right - lmp->rct.left;
+        xi_set_list_size(list_obj, new_height, new_width);
+        if ((BOOLEAN)xi_get_pref( XI_PREF_LIMIT_MIN_WIN_SIZE ))
+        {
+          xi_get_rect(list_obj, &rct);
+          if (abs(rct.bottom - cr.bottom) > 4 ||
+              abs(rct.right - cr.right) > 4)
+          {
+            wrct = cr;
+            wrct.bottom = max(rct.bottom, cr.bottom);
+            wrct.right = max(rct.right, cr.right);
+            if ( wrct.bottom != cr.bottom || wrct.right != cr.right )
+            {
+              xvt_vobj_translate_points(lmp->win, xvt_vobj_get_parent(lmp->win), (PNT *)&wrct, 2);
+              xvt_vobj_move(lmp->win, &wrct);
+            }
+          }
+        }
+        if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+          lm_make_vis(lmp);
+      }
+      retval = 0;
+      break;
+    }
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+    {
+      RCT rct;
+      int last_vis, hit_test_value;
+      BOOLEAN is_vis, is_hit, is_part_vis;
+
+      if (ep->v.mouse.button > 0)
+        break;
+
+      hit_test_value = lm_hit_test(lm, ep, &oevt, &row, &column, &is_vis, &is_hit, &is_part_vis);
+      if (is_part_vis && ep->type != E_MOUSE_DBL)
+      {
+        EVENT lep;
+        LM_SCROLL_ARG lm_scroll_arg;
+        static BOOLEAN in_here = FALSE;
+
+        if (in_here)
+          return FALSE;
+        MEMCLEAR(lm_scroll_arg);
+        lm_scroll_arg.lm = lm;
+        lm_scroll_arg.nbr_lines = 1;
+        /*
+        lm_scroll_arg.percent = 0;
+        lm_scroll_arg.same_cell = 0;
+        lm_scroll_arg.rec = 0L;
+        lm_scroll_arg.have_rec = FALSE;
+        lm_scroll_arg.color = 0L;
+        lm_scroll_arg.attrib = 0L;
+        lm_scroll_arg.row_height = 0;
+        lm_scroll_arg.rec_at_top = FALSE;
+        */
+        lm_scroll(&lm_scroll_arg);
+        lep = oevt;
+        lep.v.mouse.where.v -= lm_scroll_arg.pixels_scrolled;
+        in_here = TRUE;
+        lm_event(lm, &lep);
+        in_here = FALSE;
+        return TRUE;
+      }
+      if (is_hit)
+      {
+        if (lm_vsize_hit_test(lmp, ep, &row, &column))
+        {
+          XI_OBJ *itf, *list;
+
+          itf = lmp->itf_obj;
+          list = lmp->list_obj;
+          if (list && xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+          {
+            lm_make_invis(lmp);
+            xi_set_trap_obj(list);
+            lmp->row_being_sized = row;
+            lmp->sizing_row = TRUE;
+            xi_trap_mouse(lmp->win);
+            lm_vsize_event(lmp, ep);
+          }
+          else
+          {
+            if (list && xi_move_focus(itf))
+            {
+              xi_set_trap_obj(list);
+              lmp->row_being_sized = row;
+              lmp->sizing_row = TRUE;
+              xi_trap_mouse(lmp->win);
+              lm_vsize_event(lmp, ep);
+            }
+          }
+          break;
+        }
+
+      }
+
+      if (lmp->select_cells)
+      {
+        int row, column;
+        BOOLEAN on_disabled;
+
+        if (lm_select_cells_hit_test(lmp, ep, &row, &column, &on_disabled))
+        {
+          XI_OBJ *list;
+
+          list = lmp->list_obj;
+          xi_set_trap_obj(list);
+          lmp->selecting_cells = TRUE;
+          lmp->down_row = row;
+          lmp->cur_row = row;
+          lmp->down_column = column;
+          lmp->cur_column = column;
+          lmp->down_on_disabled = on_disabled;
+          lm_select_cell_event(lmp, ep);
+          xi_trap_mouse(lmp->win);
+          if (on_disabled)
+          {
+            invert_selection(lmp, row, column, FALSE );
+            lmp->cur_row = row + 1;
+            lmp->cur_column = column + 1;
+          }
+          break;
+        }
+      }
+
+      /* check for cell button hit */
+      if (hit_test_value == 5)
+        if (LIST_IS_ENABLED(lm))
+          lm_cell_btn_event(lmp, ep, &oevt);
+
+      /* check for focus acquisition */
+      if (hit_test_value == 1)
+      {
+        if (row == -1)
+        {
+          if (LIST_IS_ENABLED(lm) &&
+              COLUMN_IS_SELECTABLE(lm, column) &&
+              (ep->type == E_MOUSE_DBL ||
+              (ep->type == E_MOUSE_DOWN && !
+              lmp->movable_columns)
+              ))
+          {
+            unsigned long attrib;
+            LM_CB_DATA lm_cb_data;
+
+            attrib = lm_get_attrib(lm, LM_COLUMN, column, 0, FALSE);
+            if (ep->type == E_MOUSE_DBL && !lmp->movable_columns)
+              attrib |= LM_COL_ATR_SELECTED;
+            else
+            {
+              if (attrib & LM_COL_ATR_SELECTED)
+                attrib &= ~LM_COL_ATR_SELECTED;
+              else
+                attrib |= LM_COL_ATR_SELECTED;
+            }
+            lm_cb_data.lm = lm;
+            lm_cb_data.cb_type = LM_CB_SELECT;
+            lm_cb_data.cid = lmp->cid;
+            lm_cb_data.win = lmp->win;
+            lm_cb_data.row = (unsigned char)255;
+            lm_cb_data.column = (unsigned char)column;
+            lm_cb_data.v.select.selected =
+                ((attrib & LM_COL_ATR_SELECTED) != 0);
+            lm_cb_data.v.select.dbl_click =
+                (ep->type == E_MOUSE_DBL);
+            lm_cb_data.v.select.shift = ep->v.mouse.shift;
+            lm_cb_data.v.select.control = ep->v.mouse.control;
+            (*lmp->lm_cb)(&lm_cb_data);
+            if (! lm_cb_data.v.select.refused)
+              lm_set_attrib( lm, LM_COLUMN, column, 0, FALSE, attrib,
+                            FALSE);
+          }
+          if (LIST_IS_ENABLED(lm) &&
+              (ep->type == E_MOUSE_DOWN ||
+              (ep->type == E_MOUSE_DBL &&
+              ! COLUMN_IS_SELECTABLE(lm, column))) &&
+              lmp->movable_columns)
+          {
+            XI_OBJ *itf, *list;
+
+            itf = lmp->itf_obj;
+            list = lmp->list_obj;
+            if (list && xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+            {
+              lm_make_invis(lmp);
+              xi_set_trap_obj(list);
+              lmp->column_being_moved = column;
+              lmp->moving_column = TRUE;
+              xi_trap_mouse(lmp->win);
+              lm_move_event(lmp, ep);
+            }
+            else
+            {
+              if (list && xi_move_focus(itf))
+              {
+                xi_set_trap_obj(list);
+                lmp->column_being_moved = column;
+                lmp->moving_column = TRUE;
+                xi_trap_mouse(lmp->win);
+                lm_move_event(lmp, ep);
+              }
+            }
+          }
+          break;
+        }
+
+        if (CELL_IS_SELECTABLE(lm, row, column))
+        {
+          if ( lmp->single_select )
+            select_row( lm, row, column, (BOOLEAN)(ep->type == E_MOUSE_DBL) );
+          else
+          {
+            unsigned long attrib;
+            LM_CB_DATA lm_cb_data;
+            XI_OBJ *old_itf;
+
+            attrib = lm_get_attrib(lm, LM_ROW, row, 0, FALSE);
+            if (ep->type == E_MOUSE_DBL)
+              attrib |= LM_ROW_ATR_SELECTED;
+            else
+            {
+              if (attrib & LM_ROW_ATR_SELECTED)
+                attrib &= ~LM_ROW_ATR_SELECTED;
+              else
+                attrib |= LM_ROW_ATR_SELECTED;
+            }
+            lm_cb_data.lm = lm;
+            lm_cb_data.cb_type = LM_CB_SELECT;
+            lm_cb_data.cid = lmp->cid;
+            lm_cb_data.win = lmp->win;
+            lm_cb_data.row = (unsigned char)row;
+            lm_cb_data.column = (unsigned char)column;
+            lm_cb_data.v.select.selected =
+                ((attrib & LM_COL_ATR_SELECTED) != 0);
+            lm_cb_data.v.select.dbl_click = (ep->type == E_MOUSE_DBL);
+            lm_cb_data.v.select.shift = ep->v.mouse.shift;
+            lm_cb_data.v.select.control = ep->v.mouse.control;
+            old_itf = lmp->itf_obj;
+            (*lmp->lm_cb)(&lm_cb_data);
+            if (xi_is_itf(old_itf))
+              if (! lm_cb_data.v.select.refused)
+                lm_set_attrib(lm, LM_ROW, row, 0, FALSE, attrib, FALSE);
+          }
+        }
+        else
+        {
+          BOOLEAN gaining_focus = FALSE;
+
+          if (! is_vis)
+            break;
+
+          if (! lmp->cell_data[row][column].icon_rid)
+          {
+            /* set this flag here, not later! */
+            lmp->have_mouse = TRUE;
+
+            if (! lm_list_has_focus(lmp))
+            {
+              send_event = do_lm_cb(lm, LM_CB_FOCUS, row, column,
+                  NULL, NULL, 0);
+              gaining_focus = TRUE;
+            }
+            else
+            {
+              if (! lm_cell_has_focus(lmp, row, column, FALSE))
+              {
+                send_event = do_lm_cb(lm, LM_CB_FOCUS, row, column, NULL, NULL, 0);
+                /* send_event = FALSE if refused */
+
+                gaining_focus = send_event;
+              }
+              else
+                send_event = TRUE;
+            }
+            if (send_event)
+            {
+              int focus_row, focus_column;
+              BOOLEAN v_scrolled;
+
+              lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+              if ( ( lmp->lm_column_data[focus_column]->attrib
+                    & LM_COL_ATR_AUTOSELECT )
+                    && xi_get_pref(XI_PREF_AUTOSEL_ON_MOUSE)
+                    && gaining_focus)
+                ;
+              else
+              {
+                xi_trap_mouse(lmp->win);
+                lmp->selecting_text = TRUE;
+                send_txt_event( lm, lmp->txt, &oevt, gaining_focus, TRUE);
+              }
+            }
+            else
+              lmp->have_mouse = FALSE;
+            if (ep->type == E_MOUSE_DBL)
+              do_lm_cb(lm, LM_CB_DBL, row, column, NULL, NULL, 0);
+          }
+        }
+      }
+      else
+      {
+        if (LIST_IS_ENABLED(lm) &&
+            lmp->sizable_columns &&
+            lm_size_hit_test(lm, ep, &column))
+        {
+          XI_OBJ *itf, *list;
+
+          itf = lmp->itf_obj;
+          list = lmp->list_obj;
+          if (list && xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+          {
+            lm_make_invis(lmp);
+            xi_set_trap_obj(list);
+            lmp->column_being_sized = column;
+            lmp->sizing_column = TRUE;
+            xi_trap_mouse(lmp->win);
+            lm_size_event(lmp, ep);
+          }
+          else
+          {
+            if (list && xi_move_focus(itf))
+            {
+              xi_set_trap_obj(list);
+              lmp->column_being_sized = column;
+              lmp->sizing_column = TRUE;
+              xi_trap_mouse(lmp->win);
+              lm_size_event(lmp, ep);
+            }
+          }
+        }
+        else
+          retval = 0;
+      }
+      /*
+      The following code implements the behavor where if the user clicks on a partially
+      visible column, then the list scrolls to the left.
+      */
+
+      if (xi_is_itf( itf ))
+      {
+        if (! (lmp->attrib & XI_ATR_VISIBLE))
+          break;
+        if (lmp->pixel_width)
+        {
+          last_vis = lmp->last_vis;
+          if (last_vis >= lmp->fixed_columns && last_vis < lmp->nbr_columns - 1)
+          {
+            lm_get_rect(lm, LM_COLUMN, last_vis + 1, &rct);
+            rct.left += (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+            rct.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
+            if (xvt_rect_has_point(&rct, oevt.v.mouse.where))
+            {
+              if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+              {
+                lm_make_invis(lmp);
+                lm_local_hscroll(lm, 1);
+                lm_make_vis(lmp);
+              }
+              else
+              {
+                if (xi_move_focus(lmp->itf_obj))
+                {
+                  lm_local_hscroll(lm, 1);
+                  break;
+                }
+              }
+            }
+          }
+        }
+      }
+
+      break;
+    }
+  case E_MOUSE_UP:
+    if (lmp->selecting_cells)
+    {
+      LM_CB_DATA lm_cb_data;
+
+      lm_select_cell_event(lmp, ep);
+      xi_release_mouse();
+      lmp->selecting_cells = FALSE;
+      lmp->down_row = 0;
+      lmp->down_column = 0;
+      lm_cb_data.lm = lm;
+      lm_cb_data.cb_type = LM_CB_SELECT;
+      lm_cb_data.cid = lmp->cid;
+      lm_cb_data.win = lmp->win;
+      lm_cb_data.row = (unsigned char)255;
+      lm_cb_data.column = (unsigned char)255;
+      lm_cb_data.v.select.selected = TRUE;
+      lm_cb_data.v.select.dbl_click = FALSE;
+      lm_cb_data.v.select.shift = ep->v.mouse.shift;
+      lm_cb_data.v.select.control = ep->v.mouse.control;
+      (*lmp->lm_cb)(&lm_cb_data);
+    }
+    if (lmp->sizing_column)
+    {
+      lm_size_event(lmp, ep);
+      xi_release_mouse();
+      lmp->sizing_column = FALSE;
+      lmp->column_being_sized = 0;
+      break;
+    }
+    if (lmp->sizing_row)
+    {
+      lm_vsize_event(lmp, ep);
+      xi_release_mouse();
+      lmp->sizing_row = FALSE;
+      lmp->row_being_sized = 0;
+      break;
+    }
+    if (lmp->moving_column)
+    {
+      lm_move_event(lmp, ep);
+      xi_release_mouse();
+      lmp->moving_column = FALSE;
+      lmp->column_being_moved = 0;
+      break;
+    }
+    if (lmp->down_in_btn)
+    {
+      lm_cell_btn_event(lmp, ep, &oevt);
+      xi_release_mouse();
+      lmp->down_in_btn = FALSE;
+      lmp->btn_down = FALSE;
+      break;
+    }
+    if (lm_list_has_focus(lmp))
+    {
+      send_txt_event(lm, lmp->txt, &oevt, FALSE, TRUE);
+      lmp->selecting_text = FALSE;
+      xi_release_mouse();
+      lmp->have_mouse = FALSE;
+      break;
+    }
+    break;
+  case E_MOUSE_MOVE:
+    {
+      BOOLEAN is_vis, is_hit, is_part_vis;
+
+      if (! (lmp->attrib & XI_ATR_VISIBLE))
+      {
+        retval = FALSE;
+        break;
+      }
+      if (lmp->selecting_cells)
+      {
+        lm_select_cell_event(lmp, ep);
+        break;
+      }
+      if (lmp->sizing_column)
+      {
+        lm_size_event(lmp, ep);
+        break;
+      }
+      if (lmp->sizing_row)
+      {
+        lm_vsize_event(lmp, ep);
+        break;
+      }
+      if (lmp->moving_column)
+      {
+        lm_move_event(lmp, ep);
+        break;
+      }
+      if (lmp->down_in_btn)
+      {
+        lm_cell_btn_event(lmp, ep, &oevt);
+        break;
+      }
+      if (lm_list_has_focus(lmp))
+        send_txt_event(lm, lmp->txt, &oevt, FALSE, TRUE);
+      retval = lm_hit_test(lm, ep, &oevt, &row, &column, &is_vis, &is_hit, &is_part_vis);
+      if (is_part_vis)
+      {
+        unsigned long attrib;
+
+        attrib = lmp->lm_column_data[column]->attrib;
+        if (attrib & XI_ATR_SELECTABLE)
+          return 0;
+        if (! retval)
+          retval = 1;
+        return retval;
+      }
+      if (is_hit)
+      {
+        if (LIST_IS_ENABLED(lm) &&
+            lm_vsize_hit_test(lmp, ep, &row, &column))
+        {
+          *ep = oevt;
+          return 6;
+        }
+      }
+      if (LIST_IS_ENABLED(lm) &&
+          lmp->select_cells &&
+          lm_select_cells_hit_test(lmp, ep, NULL, NULL, NULL))
+      {
+        *ep = oevt;
+        return 4;
+      }
+      if (LIST_IS_ENABLED(lm) &&
+          lmp->sizable_columns &&
+          lm_size_hit_test(lm, ep, &column))
+      {
+        *ep = oevt;
+        return 2;
+      }
+      if (retval)
+      {
+        if (! is_vis)
+        {
+          *ep = oevt;
+          return 5;
+        }
+        if (CELL_IS_SELECTABLE(lm, row, column))
+          retval = 5;
+        if (row == -1)
+          retval = 5;
+        if (row >= 0 && lmp->cell_data[row][column].icon_rid)
+          retval = 5;
+        if (LIST_IS_ENABLED(lm) &&
+            lmp->movable_columns &&
+            lm_hit_test(lm, ep, &oevt, &row, &column, NULL, NULL, NULL))
+          if (row == -1)
+            retval = 3;
+      }
+      break;
+    }
+  case E_CHAR:
+    if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+    {
+      if (lmp->focus_rec)
+      {
+        LM_SCROLL_ARG lm_scroll_arg;
+        int row;
+        BOOLEAN found = FALSE;
+
+        for (row = 0; row < lmp->nbr_realized_rows; ++row)
+        {
+          if (lmp->focus_rec == lmp->recs[row])
+          {
+            found = TRUE;
+            break;
+          }
+        }
+        if (! found)
+        {
+          MEMCLEAR(lm_scroll_arg);
+          lm_scroll_arg.lm = lm;
+          /*
+          lm_scroll_arg.nbr_lines = 0;
+          lm_scroll_arg.percent = 0;
+          lm_scroll_arg.same_cell = 0;
+          */
+          lm_scroll_arg.rec = lmp->focus_rec;
+          lm_scroll_arg.have_rec = TRUE;
+          lm_scroll_arg.color = lmp->focus_rec_color;
+          lm_scroll_arg.attrib = lmp->focus_rec_attrib;
+          lm_scroll_arg.row_height = lmp->focus_rec_height;
+          lm_scroll_arg.rec_at_top = lmp->focus_rec_is_above;
+          lm_scroll(&lm_scroll_arg);
+
+          lmp->focus_rec = 0L;
+          xvt_dwin_update(lmp->win);
+        }
+      }
+      if (lmp->txt_is_invisible)
+      {
+        int     focus_row, focus_column;
+        BOOLEAN v_scrolled;
+
+        lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+        if (focus_column >= lmp->fixed_columns)
+        {
+          if (focus_column < lmp->first_vis)
+          {
+            lm_local_hscroll((LM)lmp, focus_column - lmp->first_vis);
+          }
+          else if (focus_column > lmp->last_vis)
+          {
+            int first_col, c;
+
+            c = focus_column;
+            c++;
+            c = min(c, lmp->nbr_columns);
+            first_col = lm_get_left_most_far_right_col(lmp, c);
+            lm_local_hscroll((LM)lmp, first_col - lmp->first_vis);
+          }
+        }
+      }
+    }
+    {
+      long button_key;
+      BOOLEAN shift, control;
+      int     focus_row, focus_column;
+      BOOLEAN h_scrolled;
+
+      button_key = xi_get_pref(XI_PREF_BUTTON_KEY);
+      shift = (BOOLEAN)((button_key & XI_MOD_SHIFT) != 0);
+      control = (BOOLEAN)((button_key & XI_MOD_CONTROL) != 0);
+      button_key &= 0xffffffL;
+      if ( button_key == ep->v.chr.ch &&
+          shift == ep->v.chr.shift &&
+          control == ep->v.chr.control )
+      {
+        lm_get_focus_cell(lmp, &focus_row, &focus_column, &h_scrolled );
+        do_lm_cb((LM)lmp, LM_CB_CELL_BTN, focus_row, focus_column, ep, NULL, 0);
+        return FALSE;
+      }
+    }
+
+    if ( lmp->single_select )
+    {
+      switch ( ep->v.chr.ch )
+      {
+        case K_UP:
+        {
+          int cur_row = find_selection( lmp );
+          if ( cur_row == -1 )
+            cur_row = 0;
+          else
+          {
+            if ( cur_row == 0 )
+              xi_scroll( lmp->list_obj, -1 );
+            else
+              cur_row--;
+          }
+          select_row( lm, cur_row, -1, FALSE );
+          break;
+        }
+        case K_DOWN:
+        {
+          int cur_row = find_selection( lmp );
+          if ( cur_row == -1 )
+            cur_row = 0;
+          else
+          {
+            if ( cur_row == lmp->last_fully_vis )
+              xi_scroll( lmp->list_obj, 1 );
+            else
+              cur_row++;
+          }
+          select_row( lm, cur_row, -1, FALSE );
+          break;
+        }
+        case K_PREV:
+          xi_scroll( lmp->list_obj, XI_SCROLL_PGUP );
+          select_row( lm, lmp->last_fully_vis, -1, FALSE );
+          break;
+        case K_NEXT:
+          xi_scroll( lmp->list_obj, XI_SCROLL_PGDOWN );
+          select_row( lm, 0, -1, FALSE );
+          break;
+        case K_HOME:
+        case K_LHOME:
+          xi_scroll( lmp->list_obj, XI_SCROLL_FIRST );
+          select_row( lm, 0, -1, FALSE );
+          break;
+        case K_END:
+        case K_LEND:
+          xi_scroll( lmp->list_obj, XI_SCROLL_LAST );
+          select_row( lm, lmp->last_fully_vis, -1, FALSE );
+          break;
+        case '\r':
+        case ' ':
+          row = find_selection( lmp );
+          select_row( lm, row, -1, TRUE );
+#if 0
+          if ( row != -1 )
+          {
+            LM_CB_DATA lm_cb_data;
+
+            lm_cb_data.lm = lm;
+            lm_cb_data.cb_type = LM_CB_SELECT;
+            lm_cb_data.cid = lmp->cid;
+            lm_cb_data.win = lmp->win;
+            lm_cb_data.row = (unsigned char)row;
+            lm_cb_data.column = (unsigned char)get_select_column( lmp );
+            lm_cb_data.v.select.selected = TRUE;
+            lm_cb_data.v.select.dbl_click = TRUE;
+            lm_cb_data.v.select.shift = FALSE;
+            lm_cb_data.v.select.control = FALSE;
+            (*lmp->lm_cb)(&lm_cb_data);
+          }
+#endif
+          break;
+        default:
+          return FALSE;
+      }
+      return TRUE;
+    }
+
+    if ( !lmp->sizing_row )
+    {
+      BOOLEAN nav_ret = FALSE;
+
+      if (! lmp->itf_obj->v.itf->pasting)
+        nav_ret = (BOOLEAN)navigate_char_event(lm, ep);
+      retval = send_txt_event(lm, lmp->txt, ep, FALSE, (BOOLEAN)(!nav_ret));
+    }
+    break;
+  case E_KILL_WINDOW:
+    /* xi_tree_free((char *)lm); */ /* unneeded */
+    retval = 0;
+    break;
+  case E_TIMER:
+  case E_COMMAND:
+    if (lmp->txt)
+      retval = send_txt_event(lm, lmp->txt, ep, FALSE, TRUE);
+    break;
+  }
+  *ep = oevt;
+  return(retval);
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_set_font
+lm:         current lm
+part:       must be LM_COLUMN, or LM_CELL
+idx:        column number
+idx2:       if LM_CELL, row number
+font:       font to set
+-------------------------------------------------------------------------*/
+void
+lm_set_font(LM lm, LM_PART part, int idx, int idx2, FONT_OBJ *font)
+{
+  LM_DATA *lmp = LMP(lm);
+  LM_CELL_DATA *cell_data;
+
+  switch (part)
+  {
+  case LM_COLUMN:
+    {
+      LM_COLUMN_DATA *lmcd;
+      RCT rct;
+
+      lmcd = lmp->lm_column_data[idx];
+      if (font)
+      {
+        if (! lmcd->font)
+          lmcd->font = (FONT_OBJ *)xi_tree_malloc(
+              sizeof(FONT_OBJ), lmp);
+        *lmcd->font = xi_create_copy_font_id(lmp->itf_obj, *font, 0);
+      }
+      lm_get_rect(lm, LM_COLUMN, idx, &rct);
+      lm_invalidate_rect(lmp, &rct, TRUE);
+      break;
+    }
+  case LM_CELL:
+    {
+      cell_data = &lmp->cell_data[idx][idx2];
+      if (font)
+      {
+        XVT_FNTID old_font_id;
+        if (! cell_data->font)
+          cell_data->font = (FONT_OBJ *)xi_tree_malloc(
+              sizeof(FONT_OBJ), lmp);
+        old_font_id = *cell_data->font;
+        *cell_data->font = xi_create_copy_font_id(lmp->itf_obj,
+            *font, old_font_id);
+      }
+      break;
+    }
+  }
+}
+
+
+/*********************************************************************/
+
+/* LM drawing functions */
+
+#if 0
+/*-------------------------------------------------------------------------
+function:   lm_set_clip
+lmp:        current lmp
+rctp:       clipping rectangle
+-------------------------------------------------------------------------*/
+static void
+lm_set_clip(LM_DATA *lmp, RCT *rctp)
+{
+  RCT r;
+
+  r = *rctp;
+  r.left += lmp->rct.left;
+  r.right += lmp->rct.left;
+
+  lm_adj_h(lmp, &r.left);
+  lm_adj_h(lmp, &r.right);
+
+  xi_set_clip(lmp->win, &r);
+}
+#endif
+
+/*-------------------------------------------------------------------------
+function:   lm_draw_text
+lmp:        current lmp
+h:          h position
+v:          v position
+s:          string
+len:        length of string
+-------------------------------------------------------------------------*/
+#if XI_IS_CH
+static void
+lm_draw_text(LM_DATA *lmp, int h, int v, char *s, int len)
+{
+  short sh;
+
+  sh = h;
+  sh += lmp->rct.left;
+  if (lm_adj_h(lmp, &sh))
+  {
+    lm_adj_v(lmp, v);
+    xi_draw_text(lmp->win, sh, v, s, len);
+  }
+}
+#endif
+
+
+static void
+add_seg(void *parent, LM_CELL_DATA *cell_data, int seg_starting_pos)
+{
+  ++cell_data->nbr_lines;
+  if (cell_data->line_breaks)
+    cell_data->line_breaks = (int*)xi_tree_realloc(cell_data->line_breaks,
+      sizeof(int) * cell_data->nbr_lines);
+  else
+    cell_data->line_breaks = (int*)xi_tree_malloc(
+      sizeof(int) * cell_data->nbr_lines, parent);
+  cell_data->line_breaks[cell_data->nbr_lines - 1] = seg_starting_pos;
+}
+
+
+#define is_word_char(ch) (ch != ' ' && ch != '\n')
+
+
+/*-------------------------------------------------------------------------
+lmp:        current lmp
+row:
+col:
+-------------------------------------------------------------------------*/
+void
+lm_wrap_text(LM_DATA *lmp, int row, int col, BOOLEAN set_font)
+{
+  LM_CELL_DATA *cell_data;
+  LM_COLUMN_DATA *column_data;
+  int len, pix_width;
+  char *cell_text;
+  FONT_OBJ *font;
+  int leading, ascent, descent, char_width;
+  int cur_seg, cur_seg_starting_pos, avg_line_len, seg_len;
+
+  cell_data = &lmp->cell_data[row][col];
+  column_data = lmp->lm_column_data[col];
+  cell_text = lmp->buffer[row] + lmp->lm_column_data[col]->text_offset;
+  pix_width = column_data->pix_width - lm_get_col_spacing();
+  if (cell_data->button)
+  {
+    pix_width -= lmp->pix_row_spacing;
+  }
+  if (cell_data->string)
+    if (cell_data->pix_width == pix_width &&
+        strcmp(cell_data->string, cell_text) == 0)
+      return;
+  if (cell_data->font)
+    font = cell_data->font;
+  else
+    font = lmp->font;
+  if (set_font)
+    xi_set_xvt_font(lmp->win, font, FALSE);
+  len = strlen(cell_text) + 1;
+  if (cell_data->string)
+    cell_data->string = (char*)xi_tree_realloc(cell_data->string, len);
+  else
+    cell_data->string = (char*)xi_tree_malloc(len, lmp);
+  cell_data->pix_width = pix_width;
+  strcpy(cell_data->string, cell_text);
+  if (cell_data->line_breaks)
+  {
+    xi_tree_free(cell_data->line_breaks);
+    cell_data->line_breaks = NULL;
+  }
+  cell_data->nbr_lines = 0;
+  xi_get_font_metrics_font(font, &leading, &ascent, &descent, &char_width);
+  cell_data->font_height = ascent + descent + leading;
+  avg_line_len = pix_width / char_width;
+  cur_seg_starting_pos = 0;
+  cur_seg = 0;
+
+  /* find all segments in cell_text */
+  while (TRUE)
+  {
+    int this_seg_len, possible_word_break, cur_seg_len, word_break, cnt;
+    BOOLEAN continue_loop;
+
+    cur_seg_len = strlen(&cell_text[cur_seg_starting_pos]);
+
+    /* if there is a new line in the text, will the line fit in the wrap space */
+    while (TRUE)
+    {
+      continue_loop = FALSE;
+      for (cnt = 0; cnt < cur_seg_len; ++cnt)
+      {
+        if (cell_text[cur_seg_starting_pos + cnt] == '\n')
+        {
+          seg_len = xi_xvt_get_text_width(lmp->win,
+            &cell_text[cur_seg_starting_pos], cnt);
+          if (seg_len <= pix_width)
+          {
+            add_seg(lmp, cell_data, cur_seg_starting_pos);
+            cur_seg_starting_pos += cnt + 1;
+            cur_seg_len = strlen(&cell_text[cur_seg_starting_pos]);
+            continue_loop = TRUE;
+            break;
+          }
+          else
+          {
+            continue_loop = FALSE;
+            break;
+          }
+        }
+      }
+      if (! continue_loop)
+        break;
+    }
+
+    this_seg_len = min(avg_line_len, cur_seg_len);
+
+    /* find character that is beyond pix_width */
+    while (TRUE)
+    {
+      seg_len = xi_xvt_get_text_width(lmp->win,
+        &cell_text[cur_seg_starting_pos], this_seg_len);
+      if (seg_len > pix_width)
+        break;
+      if (seg_len <= pix_width &&
+          cell_text[cur_seg_starting_pos + this_seg_len] == '\0')
+      {
+        /* this is the last segment of the text */
+        add_seg(lmp, cell_data, cur_seg_starting_pos);
+        return;
+      }
+      ++this_seg_len;
+    }
+
+    /* add the first segment */
+    add_seg(lmp, cell_data, cur_seg_starting_pos);
+
+    /* find character that is just below pix_width */
+    while (TRUE)
+    {
+      --this_seg_len;
+      seg_len = xi_xvt_get_text_width(lmp->win,
+        &cell_text[cur_seg_starting_pos], this_seg_len);
+    if (seg_len <= pix_width)
+        break;
+    }
+
+    /* find possible word break */
+    possible_word_break = this_seg_len + 1;
+    while (possible_word_break > 0)
+    {
+      if (! is_word_char(
+          cell_text[cur_seg_starting_pos + possible_word_break]))
+        break;
+      --possible_word_break;
+    }
+
+    /* if there is no possible word break, then break at this_seg_len */
+    if (possible_word_break == 0)
+      word_break = this_seg_len;
+    else
+      word_break = possible_word_break;
+
+    /* move forward so that word break is on a word */
+    while (! is_word_char(cell_text[cur_seg_starting_pos + word_break]))
+      ++word_break;
+
+    ++cur_seg;
+    cur_seg_starting_pos += word_break;
+  }
+}
+
+
+
+
+/*
+Make it so a row can have the focus.
+Tab will move focus to a cell in the row, if there is a cell in the row
+  that can take focus.
+If XI_ATR_SELECTABLE is set for any columns, space will select the
+  row.
+Up arrow and down arrow work.  If the focus is on a cell, the focus stays
+  on a cell.  If the focus is on a row, the focus stays on a row.
+Page up and down should work.
+If the focus is on the last editable cell, and tab_wrap is set, then the
+  focus moves to the next row.
+If the focus is on the last editable cell, and tab_wrap is not set, then
+  the focus move to the current row.
+Have an option on a list by list basis, enter selects if a row has the 
+  focus.  Enter will act like a double click selection.
+If the row focus option is set, put up the other hand cursor.
+
+if spreadsheet is resized, then limit size change to max_lines in lmp
+
+have option to have scroll bars on multi-line edit controls in list
+possibly revisit how text is stored in cells - may want indefinite buffer
+  size for a column.
+when entering text in a cell, continually evaluate the correct height of
+  the cell.  The function to recalc number of rows and break points should
+  compare line by line, until there is a difference, then do detailed
+  comparison after the difference.
+it should be possible to scroll the list backwards to gain more room above
+  if the cell is at the bottom of the list
+if the cell is already the maximum possible height, then not necessary to
+  do any more comparisons
+limit text edit to buffer size
+make sure that the clipboard works
+
+TODO in the future
+------------------
+disabled rows should use colors
+need option for lm to keep n records - caching
+make disabled rows really work
+if height is 0, make the list height be the same as the window height
+expose lm drawing functions
+xi_set_icon for buttons
+make an option so that when the user tabs to an edit control that already contains text, the
+  insertion point is set to the right of the text.
+settable background color for text on a 3d radio button or check box, (tab buttons also)
+make function xi_is_nav_char
+make readonly cells
+need colors for static text
+want ability on XVT/CH to have single character fields.  Eliminate the [ and ].
+*/
+
diff --git a/xi/xilm.h b/xi/xilm.h
new file mode 100755
index 000000000..67d75b608
--- /dev/null
+++ b/xi/xilm.h
@@ -0,0 +1,650 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.                  *
+*******************************************************************************/
+
+/******************************************************************
+LM module
+******************************************************************/
+#define LM_ATR_ENABLED    XI_ATR_ENABLED
+
+#define LM_ATR_VISIBLE    XI_ATR_VISIBLE
+#define LM_ATR_NAVIGATE   XI_ATR_NAVIGATE
+#define LM_ATR_TABWRAP    XI_ATR_TABWRAP
+
+typedef enum _lm_cb_type
+{
+  LM_CB_CHAR,
+  LM_CB_CHANGE,
+  LM_CB_DBL,
+  LM_CB_FOCUS,
+  LM_CB_TEXT,
+  LM_CB_SELECT,
+  LM_CB_CELL_BTN,
+  LM_CB_GET_FIRST,
+  LM_CB_GET_NEXT,
+  LM_CB_GET_PREV,
+  LM_CB_GET_LAST,
+  LM_CB_GET_PERCENT,
+  LM_CB_REC_ALLOCATE,
+  LM_CB_REC_FREE,
+  LM_CB_ROW_SIZE,
+  LM_CB_COL_DELETE,
+  LM_CB_COL_MOVE,
+  LM_CB_COL_SIZE
+} 
+LM_CB_TYPE;
+
+typedef struct _lm_cb_data
+{
+  LM lm;
+  LM_CB_TYPE cb_type;
+  int cid;
+  WINDOW win;
+  int row;
+  int column;
+  long rec;
+  union
+    {
+    struct
+    {
+      long spec_rec;
+      long data_rec;
+      int percent;
+      unsigned long attrib;
+      COLOR color;
+      BOOLEAN refused;
+      int row_height;
+      BOOLEAN has_focus;
+    } rec_request;
+    struct
+    {
+      int new_row_height;
+      BOOLEAN refused;
+    } row_size;
+    struct
+    {
+      long record;
+    } rec_allocate;
+    struct
+    {
+      long record;
+    } rec_free;
+    struct
+    {
+      long record;
+      int percent;
+    } get_percent;
+    struct
+    {
+      char *text;
+      int len;
+      int icon_rid;
+      unsigned long attrib;
+      COLOR color;
+      COLOR back_color;
+      FONT *font;
+      XVT_FNTID font_id;
+      BOOLEAN button;
+      BOOLEAN button_on_left;
+      BOOLEAN button_on_focus;
+      int button_icon_rid;
+    } text;
+    BOOLEAN refused;
+    struct
+    {
+      int ch;
+      BOOLEAN shift;
+      BOOLEAN control;
+      BOOLEAN is_paste;
+      BOOLEAN refused;
+    } chr;
+    struct
+    {
+      BOOLEAN dbl_click;
+      BOOLEAN selected;
+      BOOLEAN refused;
+      BOOLEAN shift;
+      BOOLEAN control;
+      int column;
+    } select;
+    struct
+    {
+      BOOLEAN shift;
+      BOOLEAN control;
+    } cell_btn;
+    struct
+    {
+      int   new_col_nbr;
+      BOOLEAN in_fixed;
+      int   new_col_width;
+    int   new_col_pixel_width;
+    BOOLEAN refused;
+    } column;
+    /* nothing for LM_CB_CHANGE */
+  } v;
+} LM_CB_DATA;
+
+typedef void (*LM_CB)(LM_CB_DATA *lm_cb_data);
+
+#define LM_COL_ATR_ENABLED    XI_ATR_ENABLED
+#define LM_COL_ATR_EDITMENU   XI_ATR_EDITMENU
+#define LM_COL_ATR_AUTOSELECT XI_ATR_AUTOSELECT
+#define LM_COL_ATR_AUTOSCROLL XI_ATR_AUTOSCROLL
+#define LM_COL_ATR_RJUST    XI_ATR_RJUST
+#define LM_COL_ATR_READONLY   XI_ATR_READONLY
+#define LM_COL_ATR_PASSWORD   XI_ATR_PASSWORD
+#define LM_COL_ATR_SELECTED   XI_ATR_SELECTED
+#define LM_COL_ATR_SELECTABLE XI_ATR_SELECTABLE
+#define LM_COL_ATR_COL_SELECTABLE XI_ATR_COL_SELECTABLE
+#define LM_COL_ATR_VISIBLE    XI_ATR_VISIBLE
+
+#define LM_ROW_ATR_ENABLED    XI_ATR_ENABLED
+#define LM_ROW_ATR_SELECTED   XI_ATR_SELECTED
+
+#define LM_CELL_ATR_SELECTED  XI_ATR_SELECTED
+#define LM_CELL_ATR_RJUST   XI_ATR_RJUST
+#define LM_CELL_ATR_HCENTER   XI_ATR_HCENTER
+
+typedef struct _lm_column_data
+{
+  unsigned long attrib;
+  short pix_width;
+  short x_pix_pos;
+  short text_offset;      /* offset into row text buffer */
+  short text_size;
+  char *heading_text;
+  short width;
+  BOOLEAN center_heading;
+  BOOLEAN heading_well;
+  BOOLEAN heading_platform;
+  BOOLEAN column_well;
+  BOOLEAN column_platform;
+  FONT_OBJ *font;
+  int icon_rid;
+  short icon_x;
+  short icon_y;
+  BOOLEAN size_rows;
+  BOOLEAN suppress_update_heading;
+  BOOLEAN suppress_update_cells;
+  BOOLEAN vertical_align_center;
+  BOOLEAN vertical_align_bottom;
+  BOOLEAN wrap_text;
+  BOOLEAN auto_tab;
+
+  /* temporary variables - don't assume this is good */
+  RCT column_rct;  /* used for caching column rectangles to speed drawing */
+  RCT prct;        /* physical rect */ 
+  BOOLEAN needs_update;
+} LM_COLUMN_DATA;
+
+typedef struct _lm_column_def
+{
+  unsigned long attrib;
+  short position;
+  short pix_width; /* pixels */
+  short text_size;
+  char *heading_text;
+  BOOLEAN center_heading;
+  BOOLEAN heading_well;
+  BOOLEAN heading_platform;
+  BOOLEAN column_well;
+  BOOLEAN column_platform;
+  FONT_OBJ *font;
+  int icon_rid;
+  short icon_x;
+  short icon_y;
+  BOOLEAN size_rows;
+  BOOLEAN suppress_update_heading;
+  BOOLEAN suppress_update_cells;
+  BOOLEAN vertical_align_center;
+  BOOLEAN vertical_align_bottom;
+  BOOLEAN wrap_text;
+  BOOLEAN auto_tab;
+} LM_COLUMN_DEF;
+
+typedef struct _lm_def
+{
+  int cid;
+  XI_OBJ *list_obj;
+  XI_OBJ *itf_obj;
+
+  /* XI may specify this */
+  PNT pnt;
+  short pixel_height;
+  /* If absolute height is set, then the height of the list will be exactly height pixels high */
+  BOOLEAN absolute_height;
+  short pixel_width;
+
+  short pix_char_width;
+  unsigned long attrib;
+  LM_CB lm_cb;
+  FONT_OBJ *font;
+  COLOR back_color;
+  COLOR enabled_color;  /* but inactive */
+  COLOR disabled_color;
+  COLOR active_color;
+  COLOR active_back_color;
+  COLOR disabled_back_color;
+  COLOR white_space_color;
+  COLOR rule_color;
+  char *parent;
+  BOOLEAN no_heading;
+  BOOLEAN one_row_list;
+  int nbr_rows;
+  int realized_rows_array_len;
+  BOOLEAN sizable_columns;
+  BOOLEAN movable_columns;
+  short fixed_columns;
+  short min_cell_height;
+  short min_heading_height;
+  BOOLEAN no_horz_lines;
+  BOOLEAN no_vert_lines;
+  int first_vis_column;
+  BOOLEAN drop_and_delete;
+  BOOLEAN select_cells;
+  BOOLEAN fixed_row_height;
+  BOOLEAN sizable_rows;
+  BOOLEAN get_all_records;
+  BOOLEAN keep_all_records;
+  BOOLEAN resize_with_window;
+  int horz_sync_list;
+  int vert_sync_list;
+  BOOLEAN row_focus_border;
+  COLOR row_focus_border_color;
+  int max_lines_in_cell;
+  BOOLEAN single_select;
+  BOOLEAN retain_back_color_on_select;
+} LM_DEF;
+
+#define LM_HEADING_TEXT 1001
+
+typedef enum
+{
+  LM_LIST,
+  LM_ROW,
+  LM_COLUMN,
+  LM_CELL
+} 
+LM_PART;
+
+typedef struct _lm_cell_data
+{
+  unsigned long attrib;
+  FONT_OBJ *font;
+  COLOR color;
+  COLOR back_color;
+  int icon_rid;
+  BOOLEAN button;
+  BOOLEAN button_on_left;
+  BOOLEAN button_on_focus;
+  int button_icon_rid;
+  BOOLEAN valid_data;
+
+  /* multiline cell info */
+  char *string;
+  int pix_width;
+  int nbr_lines;
+  int *line_breaks;
+  int font_height;
+} LM_CELL_DATA;
+
+typedef struct _lm_data
+{
+  int cid;
+  WINDOW win;
+  RCT rct;
+  short pix_top;
+  short pix_hdr_bottom;
+  short pix_row1_top;
+  short pix_char_width;
+  short pix_cell_height;
+  short pix_row_spacing;
+  unsigned long attrib;
+  short nbr_columns;
+  LM_COLUMN_DATA * *lm_column_data;
+  COLOR back_color;
+  COLOR enabled_color;  /* but inactive */
+  COLOR disabled_color;
+  COLOR disabled_back_color;
+  COLOR active_color;
+  COLOR active_back_color;
+  COLOR white_space_color;
+  COLOR rule_color;
+  BOOLEAN no_heading;
+  BOOLEAN sizable_columns;
+  BOOLEAN movable_columns;
+  short fixed_columns;
+  short pixel_width;
+  short pixel_height;
+  BOOLEAN moving_column;
+  BOOLEAN sizing_column;
+  int column_being_sized;
+  short min_cell_height;
+  short min_heading_height;
+  BOOLEAN no_horz_lines;
+  BOOLEAN no_vert_lines;
+  BOOLEAN drop_and_delete;
+  BOOLEAN select_cells;
+  BOOLEAN selecting_text;
+  BOOLEAN sizing_row;
+  BOOLEAN resize_with_window;
+  int row_being_sized;
+  int horz_sync_list;
+  int vert_sync_list;
+  BOOLEAN row_focus_border;
+  COLOR row_focus_border_color;
+  int max_lines_in_cell;
+  BOOLEAN single_select;
+  BOOLEAN retain_back_color_on_select;
+
+  /*
+  The following fields contain state information about focus and the
+  list.  If txt is not NULL, then editing is currently happening.
+  If txt_is_invisible is TRUE, then editing is suspended because the cell
+  with the focus is not visible, but could be at any point in time.
+  The fields after txt_is_invisible contain state information about
+  restarting editing if the focus becomes visible.
+  */
+  TXT_DATA *txt;
+  BOOLEAN txt_is_invisible;
+  long focus_rec;
+  long saved_focus_rec;
+  BOOLEAN focus_rec_is_above;
+  COLOR focus_rec_color;
+  unsigned long focus_rec_attrib;
+  int focus_rec_height;
+  char *focus_cell_text;
+  int focus_cell_ip1;
+  int focus_cell_ip2;
+
+  /* run time data */
+  LM_CB lm_cb;
+  XI_OBJ *list_obj;
+  XI_OBJ *itf_obj;
+  FONT_OBJ *font;
+  short text_size;
+  BOOLEAN have_mouse;
+  int column_being_moved;
+  int last_x;
+  int last_y;
+  BOOLEAN down_in_hscrolling;
+  BOOLEAN in_hscrolling;
+  BOOLEAN last_in_hscrolling;
+  int org_x;
+  int org_y;
+  int ascent;
+  int descent;
+  int leading;
+  BOOLEAN selecting_cells;
+  int down_row;
+  int down_column;
+  int cur_row;
+  int cur_column;
+  BOOLEAN down_on_disabled;
+  int delta_x;
+  int first_vis;
+  int last_vis;
+  int vir_left;
+  int vir_right;
+  BOOLEAN btn_down;        /* or up */
+  BOOLEAN down_in_btn;
+  int btn_down_row;
+  int btn_down_col;
+  int update_rows_at_top;
+  int update_rows_at_bottom;
+  BOOLEAN update_cells_only;
+  BOOLEAN text_scrolling;
+  int old_row_height;
+  BOOLEAN horizontally_scrolling_list;
+
+  /* vertical scrolling information */
+  RCT mlr;
+  int mlr_height;
+  int rrr_offset;         /* offset of mlr */
+  int rrr_bottom;         /* total number of vertical pixels in realized row rect */
+  int nbr_rows;               /* visible, specified by XI */
+  int realized_rows_array_len;  /* also specified by XI */
+  int nbr_realized_rows;      /* number of rows actually used in realized row array */
+  int first_fully_vis;
+  int last_fully_vis;
+  BOOLEAN fixed_row_height;
+  BOOLEAN sizable_rows;
+  BOOLEAN get_all_records;
+  BOOLEAN keep_all_records;
+
+  /* the following arrays are all allocated to the length of realized_rows_array_len */
+  long *recs;
+  int *pix_offsets;     /* pixel offsets of each row */
+  int *pix_heights;     /* pixel heights of each row */
+  BOOLEAN *set_heights;
+  char **buffer;
+  unsigned long *row_attribs;
+  COLOR *row_colors;
+  LM_CELL_DATA * *cell_data;
+
+} LM_DATA;
+
+#define NULL_LM (LM)0
+
+/*
+There are several intrinsic functions having to do with focus.
+1.  Put focus on the list, start editing
+    Example: starting editing on the list when the focus moves to the list
+    from some other place in XI.
+    lm_start_edit
+2.  Move the focus from one cell on the list to another, make visible if not.
+    Example: tabing from one cell to another.
+    lm_make_invis
+    lm_force_vis
+    lm_make_vis
+3.  Possible transition of the focus from visible to invisible or from
+    invisible to visible.
+    Example: operating the horizontal or vertical scroll bar.
+    Example: resizing the list.
+    lm_make_invis
+    lm_make_vis
+4.  Stop editing, remove focus from the list altogether.
+    Example: stopping editing when the focus moves elsewhere in XI.
+    lm_stop_edit
+*/
+
+
+/*
+Activities to test
+1.  Resize list
+2.  Resize column
+3.  Move columns around
+4.  Add columns
+5.  Delete columns
+6.  xi_cell_request
+7.  Tab around
+8.  Horizontal scroll
+9.  Vertical scroll
+10. Drop horizontal thumb
+11. Drop vertical thumb
+12. Select range of cells
+13. Set font on range of cells
+14. Click on partially vis column
+15. Size row
+16. Change wrapping of text in cell
+*/
+
+typedef struct _lm_scroll_arg
+{
+  LM lm;
+  int nbr_lines;
+  int percent;
+  BOOLEAN same_cell;
+  long rec;
+  BOOLEAN have_rec;
+  COLOR color;
+  unsigned long attrib;
+  int row_height;
+  BOOLEAN rec_at_top;
+  int pixels_scrolled;   /* this is a return value from lm_scroll */
+} LM_SCROLL_ARG;
+
+
+void    calculate_pix_offsets(LM_DATA *lmp, BOOLEAN draw_changes );
+void    calculate_visibles(LM_DATA *lmp);
+void    calc_x_pix_pos( LM lm, LM_COLUMN_DATA *lcdata, int position);
+BOOLEAN do_lm_cb(LM lm, LM_CB_TYPE cb_reason, int row, int column,
+            EVENT *ep, int *percent, int pixels);
+BOOLEAN do_lm_cb_get(LM lm, LM_CB_TYPE cb_reason, long *spec_rec,
+              long *data_rec, int percent, COLOR *color,
+              unsigned long *attrib, int *row_height);
+void    do_lm_cb_text(LM_DATA *lmp, int row, int col, BOOLEAN preserve_focus );
+void    do_scroll_bar(XI_LIST_DATA *listdata);
+BOOLEAN lm_adj_h(LM_DATA *lmp, short *h);
+void    lm_allocate_rec_info(LM_DATA *lmp, int realized_rows_array_len);
+void    lm_calc_last_vis(LM_DATA *lmp);
+int     lm_calculate_row_height(LM_DATA *lmp, int row);
+BOOLEAN lm_cell_has_focus( LM_DATA* lmp, int row, int column,
+                  BOOLEAN is_vert_scrolled );
+void    lm_cell_request( LM lm, LM_PART lm_part, int idx1, int idx2);
+void    lm_column_set_pixel_width(LM lm, int idx, int width);
+LM      lm_create( WINDOW win, LM_DEF *lm_def, void *parent);
+void    lm_create_column( LM lm, LM_COLUMN_DEF *lm_column_def,
+                  BOOLEAN do_cell_requests, BOOLEAN in_hscrolling);
+void    lm_delete(LM lm);
+void    lm_delete_column(LM lm, int column_nbr, BOOLEAN adjust_hscrolling);
+BOOLEAN lm_delete_row(LM lm, int row);
+void    lm_draw_line(LM_DATA *lmp, PNT p, BOOLEAN adj_v, BOOLEAN adj_h);
+int     lm_event(LM lm, EVENT *ep);
+void    lm_focus_cb( long lm, int row, int column, BOOLEAN invisible,
+              BOOLEAN set);
+void    lm_force_vis(LM_DATA *lmp);
+unsigned long lm_get_attrib( LM lm, LM_PART lm_part, int idx, int idx2,
+                    BOOLEAN invisible );
+int     lm_get_buf_size(LM lm, LM_PART part, int idx);
+int     lm_get_cid(LM lm);
+RCT *   lm_get_cell_rect( RCT *rctp, LM lm, int row, int col, BOOLEAN inner,
+                  BOOLEAN physical_rct);
+int     lm_get_col_spacing(void);
+int     lm_get_fixed_columns( LM lm );
+void    lm_get_focus_cell( LM_DATA *lmp, int *rowp, int *columnp,
+                  BOOLEAN* is_vert_scrolled );
+int     lm_get_left_most_far_right_col(LM_DATA *lmp, int nbr_columns);
+long*   lm_get_list_info(LM lm, int *nbr_recs);
+XI_OBJ* lm_get_list_obj(LM lm);
+RCT*    lm_get_list_rct(LM_DATA *lmp, RCT *r);
+void    lm_get_metrics( XI_OBJ_DEF *obj_def, int *hborder, int *column_div,
+                int *list_bottom);
+RCT*    lm_get_rect(LM lm, LM_PART part, int idx, RCT *rct);
+RCT*    lm_get_row_rect(RCT *rctp, LM lm, int row);
+void    lm_get_sel(LM lm, int *c1, int *c2);
+char*   lm_get_text( LM lm, char *s, int len, int row, int column,
+              BOOLEAN invisible );
+void    lm_get_vertical_metrics( XI_OBJ_DEF* obj_def, int* first_row_y,
+                      int* row_spacing, int *client_height,
+                      int* title_height );
+void    lm_get_visible_columns(LM lm, int *first_vis, int *last_vis);
+int     lm_get_visible_rows(LM lm, int *first_vis, int *last_vis);
+void    lm_hscroll(LM lm, int nbr_columns, int pos);
+BOOLEAN lm_insert_row(LM lm, int row);
+BOOLEAN lm_is_cell_visible(LM_DATA *lmp, int focus_row, int focus_column,
+                  BOOLEAN use_txt_is_visible, BOOLEAN *is_hscrolled);
+
+void    lm_invalidate_rect(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_h);
+void    lm_invalidate_rect2( LM_DATA *lmp, RCT *rct_to_invalidate,
+                    BOOLEAN adj_left);
+void    lm_invalidate_rows( LM lm, int row_start, int row_end,
+                  BOOLEAN invalidate);
+void    lm_invalidate_rows_internal(LM lm, int row_start, int row_end,
+                        BOOLEAN redraw, int column,
+                        BOOLEAN preserve_focus_text );
+BOOLEAN lm_list_has_focus(LM_DATA *lmp);
+void    lm_local_hscroll(LM lm, int nbr_columns);
+void    lm_make_invis(LM_DATA *lmp);
+void    lm_make_vis(LM_DATA *lmp);
+void    lm_move_event(LM_DATA *lmp, EVENT *ep);
+void    lm_move_to(LM_DATA *lmp, PNT p, BOOLEAN adj_v, BOOLEAN adj_h);
+void    lm_recalc_metrics(LM lm);
+void    lm_redraw_row(LM_DATA *lmp, int row, BOOLEAN update );
+void    lm_remove_all_rows( LM_DATA far* lm, BOOLEAN delete_focus );
+BOOLEAN lm_row_has_focus( LM_DATA *lmp, int row, BOOLEAN is_vert_scrolled);
+int     lm_scroll(LM_SCROLL_ARG *arg);
+void    lm_scroll_rect(LM_DATA *lmp, RCT *rctp, int dh, int dv);
+void    lm_set_fixed_columns( LM lm, int new_fixed_count );
+void    lm_set_focus_cell( LM_DATA *lmp, int row, int column,
+                  BOOLEAN is_vert_scrolled );
+void    lm_set_attrib( LM lm, LM_PART lm_part, int idx, int idx2,
+                BOOLEAN invisible, unsigned long attrib,
+                int half_baked);
+void    lm_set_buf_size(LM lm, LM_PART part, int idx, int size);
+void    lm_set_column_width(LM lm, int idx, int width);
+void    lm_set_color( LM lm, LM_PART part, int row, int column,
+              BOOLEAN invisible, COLOR color, BOOLEAN half_baked);
+void    lm_set_fixed_columns( LM lm, int new_fixed_count );
+void    lm_set_hscroll_bar(LM lm);
+void    lm_set_hscroll_range(LM lm);
+void    lm_set_icon(LM lm, int icon_rid, int row, int column);
+void    lm_set_focus(LM lm, int row, int column);
+void    lm_set_focus_text( LM_DATA* lmp, const char* new_text );
+void    lm_set_font(LM lm, LM_PART part, int idx, int idx2, FONT_OBJ *font);
+void    lm_set_list_size(LM lm, int height, int width);
+void    lm_set_row_height(LM lm, int row, int height, BOOLEAN set_height,
+                  int old_height, BOOLEAN only_update);
+void    lm_set_sel( LM lm, int row, int column, BOOLEAN invisible, int c1,
+              int c2 );
+void    lm_set_text(LM lm, char *s, int row, int column, BOOLEAN invisible);
+void    lm_size_event(LM_DATA *lmp, EVENT *ep);
+void    lm_text_scrolling(XI_OBJ *xi_obj);
+void    lm_wrap_text(LM_DATA *lmp, int row, int col, BOOLEAN set_font);
+int     lm_make_rrr_room_pix(LM_DATA *lmp, int pixels, BOOLEAN do_redraw );
+BOOLEAN navigate_char_event(LM lm, EVENT *ep);
+void    redraw_cell(LM lm, int row, int col, BOOLEAN update );
+void    select_row( LM lm, int row, int column, BOOLEAN dbl_click );
+void    draw_cell_range( LM_DATA* lmp, int first_row, int last_row,
+                int first_col, int last_col,
+                BOOLEAN in_event_update );
+
+
+
+#define LMP(l) ((LM_DATA *)(l))
+
+#if XVT_OS == XVT_OS_CTOS
+#define RULE_Y_OFFSET_TOP ((npctos_env == CHSERVICE) ? 0 : 1)
+#define RULE_Y_OFFSET_BOTTOM ((npctos_env == CHSERVICE) ? 0 : 1)
+#define BORDER_WIDTH ((npctos_env == CHSERVICE) ? 8 : 2)
+#define RULE_WIDTH_V ((npctos_env == CHSERVICE) ? 8 : 1)
+#define RULE_WIDTH_H ((npctos_env == CHSERVICE) ? 0 : 1)
+#define HPIX_PER_CH 8
+#define VPIX_PER_CH 8
+#define WIDTHLOOP(idx, wid) for (idx = 0; idx < wid; idx++)
+#else
+#if XIWS == WMWS
+#define RULE_Y_OFFSET_TOP 0
+#define RULE_Y_OFFSET_BOTTOM 0
+#define BORDER_WIDTH 8
+#define RULE_WIDTH_V 8    /* width of vertical lines */
+#define RULE_WIDTH_H 0    /* width of horz lines */
+#define HPIX_PER_CH 8
+#define VPIX_PER_CH 8
+#else
+#define RULE_Y_OFFSET_TOP 1
+#define RULE_Y_OFFSET_BOTTOM 1
+#define BORDER_WIDTH 2
+#define RULE_WIDTH_V 1
+#define RULE_WIDTH_H 1
+#define WIDTHLOOP(idx, wid) for (idx = 0; idx < wid; idx++)
+#endif
+#endif
+
+#if 0
+#define ROW_IS_ENABLED(lm, row)   (LMP(lm)->row_attribs[row] & LM_ROW_ATR_ENABLED)
+#define CELL_IS_ENABLED(lm, row, col)   (LIST_IS_ENABLED(lm) && ROW_IS_ENABLED(lm, row) &&      COLUMN_IS_ENABLED(lm, col))
+#else
+#define CELL_IS_ENABLED(lm, row, col)   (LIST_IS_ENABLED(lm) && COLUMN_IS_ENABLED(lm, col))
+#endif
+#define CELL_IS_SELECTED(lm, row, col)  ((LMP(lm)->row_attribs[row] & LM_ROW_ATR_SELECTED) ||   (LMP(lm)->lm_column_data[col]->attrib & LM_COL_ATR_SELECTED) || \
+  (LMP(lm)->cell_data[row][col].attrib & LM_CELL_ATR_SELECTED))
+#define CELL_IS_SELECTABLE(lm, row, col)  (LMP(lm)->lm_column_data[col]->attrib & LM_COL_ATR_SELECTABLE)
+#define LIST_IS_ENABLED(lm)   ((LMP(lm)->attrib & (LM_ATR_ENABLED | LM_ATR_VISIBLE)) ==         (LM_ATR_ENABLED | LM_ATR_VISIBLE))
+#define COLUMN_IS_ENABLED(lm, col)  (LMP(lm)->lm_column_data[col]->attrib & LM_COL_ATR_ENABLED)
+#define COLUMN_IS_SELECTABLE(lm, col)   (LMP(lm)->lm_column_data[col]->attrib & LM_COL_ATR_COL_SELECTABLE)
+#define COLUMN_IS_SELECTED(lm, col)   (LMP(lm)->lm_column_data[col]->attrib & LM_COL_ATR_SELECTED)
+
diff --git a/xi/xilm2.c b/xi/xilm2.c
new file mode 100755
index 000000000..d4b5c2de5
--- /dev/null
+++ b/xi/xilm2.c
@@ -0,0 +1,4913 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distribfuted, in printed or  *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#define XI_INTERNAL
+#include "xi.h"
+#include "xitext.h"
+#include "xilm.h"
+#include "xiutils.h"
+#include "xidisply.h"
+
+#define REALIZED_ROWS_GRANULE 4
+#define REC_AT_TOP 1
+#define REC_AT_BOTTOM 0
+#define CELL_VERTICAL_MARGIN (RULE_Y_OFFSET_TOP + RULE_Y_OFFSET_BOTTOM + 2)
+
+static void adjust_rows(LM_DATA *lmp, int delta );
+
+/*-------------------------------------------------------------------------
+function:                   lm_allocate_rec_info
+lmp:                        current lmp
+realized_rows_array_len:    number of realized rows in the realized rows array
+-------------------------------------------------------------------------*/
+void
+lm_allocate_rec_info(LM_DATA *lmp, int realized_rows_array_len)
+{
+  int old_len = lmp->realized_rows_array_len;
+  int i;
+
+  lmp->realized_rows_array_len = realized_rows_array_len;
+
+  /* recs */
+  if (lmp->recs)
+  {
+    lmp->recs = (long *)xi_tree_realloc(lmp->recs, sizeof(long) * realized_rows_array_len);
+    for (i = old_len; i < realized_rows_array_len; ++i)
+      lmp->recs[i] = 0L;
+  }
+  else
+    lmp->recs = (long *)xi_tree_malloc(sizeof(long) * realized_rows_array_len, lmp);
+
+  /* pix_offsets */
+  if (lmp->pix_offsets)
+    lmp->pix_offsets = (int *)xi_tree_realloc(lmp->pix_offsets,
+        sizeof(int) * realized_rows_array_len);
+  else
+    lmp->pix_offsets = (int *)xi_tree_malloc(sizeof(int) * realized_rows_array_len, lmp);
+
+  /* pix_heights */
+  if (lmp->pix_heights)
+    lmp->pix_heights = (int *)xi_tree_realloc(lmp->pix_heights,
+        sizeof(int) * realized_rows_array_len);
+  else
+    lmp->pix_heights = (int *)xi_tree_malloc(sizeof(int) * realized_rows_array_len, lmp);
+
+  /* set_heights */
+  if (lmp->set_heights)
+    lmp->set_heights = (short *)xi_tree_realloc(lmp->set_heights,
+        sizeof(int) * realized_rows_array_len);
+  else
+    lmp->set_heights = (short *)xi_tree_malloc(sizeof(int) * realized_rows_array_len, lmp);
+
+  /* buffer */
+  if (lmp->buffer)
+  {
+    for (i = realized_rows_array_len; i < old_len; ++i)
+      xi_tree_free(lmp->buffer[i]);
+    lmp->buffer = (char * *)xi_tree_realloc(lmp->buffer,
+        sizeof(char *) * realized_rows_array_len);
+    for (i = old_len; i < realized_rows_array_len; ++i)
+      lmp->buffer[i] = (char *)xi_tree_malloc(lmp->text_size, lmp);
+  }
+  else
+    lmp->buffer = (char * *)xi_tree_malloc(sizeof(char *) * realized_rows_array_len,
+        lmp);
+
+  /* row_attribs */
+  if (lmp->row_attribs)
+  {
+    lmp->row_attribs = (unsigned long *)xi_tree_realloc(lmp->row_attribs,
+        sizeof(unsigned long) * realized_rows_array_len);
+    for (i = old_len; i < realized_rows_array_len; ++i)
+      lmp->row_attribs[i] = LM_ROW_ATR_ENABLED;
+  }
+  else
+    lmp->row_attribs = (unsigned long *)xi_tree_malloc(sizeof(unsigned long) * realized_rows_array_len,
+        lmp);
+
+  /* row_colors */
+  if (lmp->row_colors)
+  {
+    lmp->row_colors = (COLOR *)xi_tree_realloc(lmp->row_colors,
+        sizeof(COLOR) * realized_rows_array_len);
+    for (i = old_len; i < realized_rows_array_len; ++i)
+      lmp->row_colors[i] = 0L;
+  }
+  else
+    lmp->row_colors = (COLOR *)xi_tree_malloc(sizeof(COLOR) * realized_rows_array_len,
+        lmp);
+
+  /* cell_data */
+  if (lmp->cell_data)
+  {
+    for (i = realized_rows_array_len; i < old_len; ++i)
+      xi_tree_free(lmp->cell_data[i]);
+    lmp->cell_data = (LM_CELL_DATA * *)xi_tree_realloc(lmp->cell_data,
+        sizeof(LM_CELL_DATA *) * realized_rows_array_len);
+    for (i = old_len; i < realized_rows_array_len; ++i)
+      lmp->cell_data[i] = (LM_CELL_DATA *)xi_tree_malloc((lmp->nbr_columns + 1) * sizeof(LM_CELL_DATA),
+          lmp);
+  }
+  else
+    lmp->cell_data = (LM_CELL_DATA * *)xi_tree_malloc(sizeof(LM_CELL_DATA *) * realized_rows_array_len,
+        lmp);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_create
+win:        window in which to put list
+lm_def:     list definition
+parent:     tree memory parent
+-------------------------------------------------------------------------*/
+LM
+lm_create(WINDOW win, LM_DEF *lm_def, void *parent)
+{
+  LM_DATA *lmp;
+  int i, font_height, leading, ascent, descent, mch, realized_rows_array_len;
+
+  lmp = LMP(xi_tree_malloc(sizeof(LM_DATA), parent));
+  lmp->cid = lm_def->cid;
+  lmp->list_obj = lm_def->list_obj;
+  lmp->itf_obj = lm_def->itf_obj;
+  lmp->win = win;
+  lmp->font = lm_def->font;
+  lmp->back_color = lm_def->back_color;
+  lmp->enabled_color = lm_def->enabled_color;
+  lmp->disabled_color = lm_def->disabled_color;
+  lmp->disabled_back_color = lm_def->disabled_back_color;
+  lmp->active_color = lm_def->active_color;
+  lmp->active_back_color = lm_def->active_back_color;
+  lmp->white_space_color = lm_def->white_space_color;
+  lmp->rule_color = lm_def->rule_color;
+  lmp->attrib = lm_def->attrib;
+  lmp->lm_cb = lm_def->lm_cb;
+  lmp->no_heading = lm_def->no_heading;
+  lmp->sizable_columns = lm_def->sizable_columns;
+  lmp->movable_columns = lm_def->movable_columns;
+  lmp->fixed_columns = lm_def->fixed_columns;
+  lmp->resize_with_window = lm_def->resize_with_window;
+  lmp->horz_sync_list = lm_def->horz_sync_list;
+  lmp->vert_sync_list = lm_def->vert_sync_list;
+  lmp->row_focus_border = lm_def->row_focus_border;
+  lmp->row_focus_border_color = lm_def->row_focus_border_color;
+  lmp->single_select = lm_def->single_select;
+  lmp->pixel_width = lm_def->pixel_width;
+  lmp->pixel_height = lm_def->pixel_height;
+#if XI_IS_CH
+  CTOS_IS_CH;
+  lmp->min_cell_height = 0;
+  lmp->min_heading_height = lm_def->min_heading_height;
+  CTOS_END
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  lmp->min_cell_height = lm_def->min_cell_height;
+  lmp->min_heading_height = lm_def->min_heading_height;
+  CTOS_END;
+#endif
+  lmp->no_horz_lines = lm_def->no_horz_lines;
+  lmp->no_vert_lines = lm_def->no_vert_lines;
+  lmp->first_vis = lmp->fixed_columns;
+  lmp->drop_and_delete = lm_def->drop_and_delete;
+  lmp->select_cells = lm_def->select_cells;
+  lmp->get_all_records = lm_def->get_all_records;
+  lmp->keep_all_records = lm_def->keep_all_records;
+  lmp->retain_back_color_on_select = lm_def->retain_back_color_on_select;
+  lmp->max_lines_in_cell = lm_def->max_lines_in_cell;
+  if (! lmp->max_lines_in_cell)
+    lmp->max_lines_in_cell =
+        (int)xi_get_pref(XI_PREF_DEFAULT_MAX_LINES_IN_CELL);
+  xi_set_xvt_font(win, lm_def->font, FALSE);
+  xi_get_font_metrics(win, &leading, &ascent, &descent);
+  lmp->leading = leading;
+  lmp->ascent = ascent;
+  lmp->descent = descent;
+  font_height = lmp->ascent + lmp->leading + lmp->descent;
+
+  /* we add two to the following line so that there is room in the cell for the
+    row focus border */
+#if XVTWS == WMWS
+  lmp->pix_cell_height = font_height;
+#else
+  lmp->pix_cell_height = font_height + CELL_VERTICAL_MARGIN;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  mch = 8;
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  mch = lm_def->min_cell_height;
+  CTOS_END;
+#endif
+  lmp->pix_cell_height = max(lmp->pix_cell_height, mch);
+  lmp->pix_row_spacing = lmp->pix_cell_height + RULE_WIDTH_H;
+  lmp->pix_top = lm_def->pnt.v;
+#if XVTWS == WMWS
+  lmp->pix_hdr_bottom = lm_def->pnt.v + lmp->leading + lmp->ascent +
+      lmp->descent + BORDER_WIDTH +
+      RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
+  lmp->pix_hdr_bottom = max(lmp->pix_hdr_bottom, (lm_def->pnt.v
+                            + lmp->min_heading_height - BORDER_WIDTH));
+#else
+  lmp->pix_hdr_bottom = lm_def->pnt.v + lmp->leading + lmp->ascent +
+    lmp->descent + BORDER_WIDTH + RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
+  lmp->pix_hdr_bottom = max( lmp->pix_hdr_bottom, (lm_def->pnt.v + lmp->min_heading_height));
+#endif
+  if (lmp->no_heading)
+    lmp->pix_row1_top = lm_def->pnt.v + BORDER_WIDTH;
+  else
+    lmp->pix_row1_top = lmp->pix_hdr_bottom + BORDER_WIDTH;
+  lmp->pix_char_width = lm_def->pix_char_width;
+  lmp->nbr_columns = 0;
+  lmp->lm_column_data = NULL;
+
+  /* compute number of rows */
+  lmp->nbr_rows = lm_def->nbr_rows;
+  if (lm_def->nbr_rows)
+    lmp->nbr_rows = lm_def->nbr_rows;
+  else
+    lmp->nbr_rows = (lm_def->pixel_height - (lmp->pix_row1_top - lm_def->pnt.v)
+                    - BORDER_WIDTH) / lmp->pix_row_spacing;
+  if (lm_def->one_row_list)
+    lmp->nbr_rows = 1;
+
+  lmp->rct.left = lm_def->pnt.h;
+  lmp->rct.top = lm_def->pnt.v;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  lmp->rct.right = lm_def->pnt.h + 2 * BORDER_WIDTH;
+  if (lm_def->resize_with_window)
+    lmp->rct.bottom = lm_def->pnt.v + lm_def->pixel_height;
+  else
+    lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing +
+        (BORDER_WIDTH - RULE_WIDTH_H);
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  lmp->rct.right = lm_def->pnt.h + BORDER_WIDTH;
+  if (lm_def->resize_with_window)
+    lmp->rct.bottom = lm_def->pnt.v + lm_def->pixel_height;
+  else
+    lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing
+        + BORDER_WIDTH;
+  CTOS_END;
+#endif
+  lmp->vir_left = lmp->rct.left + BORDER_WIDTH;
+  lmp->vir_right = lmp->vir_left + lmp->pixel_width;
+  lmp->text_size = 0;
+
+  realized_rows_array_len = lm_def->realized_rows_array_len;
+  if (! realized_rows_array_len)
+    realized_rows_array_len = lmp->nbr_rows + 1;
+  lm_allocate_rec_info(lmp, realized_rows_array_len);
+
+  /* calculate mathematical list rectangle */
+  lmp->mlr.top = lmp->pix_row1_top;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
+  lmp->mlr.left = lmp->rct.left + BORDER_WIDTH;
+  lmp->mlr.right = lmp->rct.right - BORDER_WIDTH;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  if (lmp->pixel_width)
+    lmp->mlr.bottom = lmp->rct.bottom;
+  else
+    lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
+  lmp->mlr.left = lmp->rct.left;
+  lmp->mlr.right = lmp->rct.right;
+  CTOS_END;
+#endif
+  lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
+
+  for (i = 0; i < lmp->realized_rows_array_len; ++i)
+  {
+    lmp->cell_data[i] = (LM_CELL_DATA *)xi_tree_malloc(
+        lmp->nbr_columns * sizeof(LM_CELL_DATA), lmp);
+    lmp->row_attribs[i] = LM_ROW_ATR_ENABLED;
+  }
+
+  return((LM)PTR_LONG(lmp));
+}
+
+
+/*-------------------------------------------------------------------------
+function:   do_rec_event
+lmp:        current lmp
+row:        row to do event on
+type:       XI_EVENT_TYPE
+notes:      In this case, row is not really a row.  It is an index into the
+      realized rows array.
+-------------------------------------------------------------------------*/
+static void
+do_rec_event(LM_DATA *lmp, int row, XI_EVENT_TYPE type)
+{
+  LM_CELL_DATA *lmcdp;
+  int i;
+
+  if (type == XIE_REC_FREE)
+  {
+    if (lmp->recs[row] != lmp->focus_rec)
+      do_lm_cb((LM)lmp, LM_CB_REC_FREE, row, 0, NULL, NULL, 0);
+    lmcdp = lmp->cell_data[row];
+    for (i = 0; i < lmp->nbr_columns; ++i, ++lmcdp)
+    {
+      if (lmcdp->font)
+      {
+        xi_free_font_id(lmp->itf_obj, *lmcdp->font);
+        xi_tree_free(lmcdp->font);
+      }
+      if (lmcdp->string)
+        xi_tree_free(lmcdp->string);
+      if (lmcdp->line_breaks)
+        xi_tree_free(lmcdp->line_breaks);
+      memset((char *)lmcdp, '\0', sizeof(LM_CELL_DATA));
+    }
+    lmp->recs[row] = 0L;
+    /* we technically do not need to do the following lines.  it just keeps the data structures clean. */
+    lmp->pix_heights[row] = 0;
+    lmp->set_heights[row] = FALSE;
+    lmp->pix_offsets[row] = 0;
+    memset(lmp->buffer[row], '\0', lmp->text_size);
+    lmp->row_attribs[row] = 0L;
+    lmp->row_colors[row] = 0L;
+  }
+  if (type == XIE_REC_ALLOCATE)
+  {
+    do_lm_cb((LM)lmp, LM_CB_REC_ALLOCATE, row, 0, NULL, NULL, 0);
+    lmcdp = lmp->cell_data[row];
+    for (i = 0; i < lmp->nbr_columns; ++i, ++lmcdp)
+      memset((char *)lmcdp, '\0', sizeof(LM_CELL_DATA));
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   row_copy
+lmp:        current lmp
+source_row: row from which to copy
+dest_row:   destination row
+-------------------------------------------------------------------------*/
+static void
+row_copy(LM_DATA *lmp, int source_row, int dest_row)
+{
+  int idx;
+  LM_CELL_DATA *lmcdpd, *lmcdps;
+
+  lmp->recs[dest_row] = lmp->recs[source_row];
+  lmp->pix_heights[dest_row] = lmp->pix_heights[source_row];
+  lmp->set_heights[dest_row] = lmp->set_heights[source_row];
+  lmp->pix_offsets[dest_row] = lmp->pix_offsets[source_row];
+  memcpy(lmp->buffer[dest_row], lmp->buffer[source_row], lmp->text_size);
+  lmp->row_attribs[dest_row] = lmp->row_attribs[source_row];
+  lmp->row_colors[dest_row] = lmp->row_colors[source_row];
+  for (idx = 0,
+      lmcdpd = lmp->cell_data[dest_row],
+      lmcdps = lmp->cell_data[source_row];
+      idx < lmp->nbr_columns;
+      ++idx,
+      ++lmcdpd,
+      ++lmcdps)
+  {
+    *lmcdpd = *lmcdps;
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   init_row
+lmp:        current lmp
+row:        row to init
+-------------------------------------------------------------------------*/
+static void
+init_row(LM_DATA *lmp, int row)
+{
+  int idx;
+  LM_CELL_DATA *lmcdp;
+
+  lmp->recs[row] = 0L;
+  lmp->pix_heights[row] = 0;
+  lmp->set_heights[row] = 0;
+  lmp->pix_offsets[row] = 0;
+  lmp->row_attribs[row] = LM_ROW_ATR_ENABLED;
+  lmp->row_colors[row] = 0;
+  for (idx = 0,
+      lmcdp = lmp->cell_data[row];
+      idx < lmp->nbr_columns;
+      ++idx,
+      ++lmcdp)
+  {
+    memset((char *)lmcdp, '\0', sizeof(LM_CELL_DATA));
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   make_rec_available
+lmp:        current lmp
+top:        record to become available is at the top of the realized_row array,
+            else the record to become available is at the bottom of the realized
+            row array.
+allocate_rec:   if TRUE, then send XIE_REC_ALLOCATE event
+notes:      if, in order to get a record at the bottom of the realized row array,
+              we must discard a record at the beginning of the rrr array, then
+              we must change lmp->rrr_offset.
+            whenever we make a record be available, make sure that we free
+              fonts in cell_data.
+            Also, clear cell_data.
+-------------------------------------------------------------------------*/
+static void make_rec_available( LM_DATA *lmp, BOOLEAN top, BOOLEAN allocate_rec,
+                                BOOLEAN doing_scroll_first)
+{
+  int cnt;
+
+  if (top)
+  {
+    int idx;
+
+    if (! lmp->get_all_records)
+    {
+      int nbr_to_free;
+
+      nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
+      if (nbr_to_free > 0)
+      {
+        /* free as many records at the end of the list as possible */
+        for (idx = lmp->last_fully_vis + 2; idx < lmp->nbr_realized_rows;
+            ++idx)
+          do_rec_event(lmp, idx, XIE_REC_FREE);
+        lmp->nbr_realized_rows -= nbr_to_free;
+      }
+
+      if (lmp->nbr_realized_rows >= lmp->realized_rows_array_len)
+        lm_allocate_rec_info(lmp, lmp->realized_rows_array_len + 1);
+
+      /* copy all the records, making room at the beginning of the realized_row array */
+      ++lmp->nbr_realized_rows;
+      for (idx = lmp->nbr_realized_rows - 1;
+          idx > 0; --idx)
+        row_copy(lmp, idx - 1, idx);
+      adjust_rows(lmp, 1);
+      init_row(lmp, 0);
+      if (allocate_rec)
+        do_rec_event(lmp, 0, XIE_REC_ALLOCATE);
+      return;
+    }
+  }
+  else
+  {
+    if (! lmp->get_all_records || doing_scroll_first)
+    {
+      /* free as many records at the beginning of the list as possible */
+      cnt = lmp->first_fully_vis - 2;
+      if (cnt > 0)
+      {
+        int idx, jidx;
+
+        for (idx = 0; idx < cnt; ++idx)
+        {
+          lmp->rrr_offset += lmp->pix_heights[idx];
+          do_rec_event(lmp, idx, XIE_REC_FREE);
+        }
+
+        lmp->nbr_realized_rows -= cnt;
+
+        /* copy all the records, making room at the end of the realized row array */
+        for (idx = cnt, jidx = 0;
+            jidx < lmp->nbr_realized_rows;
+            ++idx, ++jidx)
+          row_copy(lmp, idx, idx - cnt);
+        adjust_rows(lmp, -cnt);
+      }
+      if (lmp->nbr_realized_rows >= lmp->realized_rows_array_len)
+        lm_allocate_rec_info(lmp, lmp->realized_rows_array_len + 1);
+      ++lmp->nbr_realized_rows;
+      init_row(lmp, lmp->nbr_realized_rows - 1);
+      if (allocate_rec)
+        do_rec_event(lmp, lmp->nbr_realized_rows - 1, XIE_REC_ALLOCATE);
+      return;
+    }
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   get_next_rec
+lmp:        current lmp
+returns:    TRUE if next record was available
+            FALSE if not
+-------------------------------------------------------------------------*/
+static BOOLEAN
+get_next_rec(LM_DATA *lmp, BOOLEAN doing_scroll_first)
+{
+  int idx, row_height;
+
+  make_rec_available(lmp, REC_AT_BOTTOM, TRUE, doing_scroll_first);
+  idx = lmp->nbr_realized_rows - 1;
+  if (do_lm_cb_get((LM)lmp, LM_CB_GET_NEXT,
+      &lmp->recs[idx - 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
+      &lmp->row_attribs[idx], &row_height))
+  {
+    do_rec_event(lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE);
+    --lmp->nbr_realized_rows;
+    return FALSE;
+  }
+
+  if (row_height)
+  {
+    lmp->pix_heights[idx] = row_height;
+    lmp->set_heights[idx] = TRUE;
+  }
+  else
+  {
+    lmp->pix_heights[idx] = 0;
+    lmp->set_heights[idx] = FALSE;
+  }
+
+  lm_invalidate_rows_internal((LM)lmp, idx, idx, FALSE, -1, TRUE );
+
+  return TRUE;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   get_previous_rec
+lmp:        current lmp
+returns:    TRUE if previous record was available
+      FALSE if not
+-------------------------------------------------------------------------*/
+static BOOLEAN get_previous_rec(LM_DATA *lmp)
+{
+  int row_height, cnt;
+
+  make_rec_available(lmp, REC_AT_TOP, TRUE, FALSE);
+  if (do_lm_cb_get((LM)lmp, LM_CB_GET_PREV,
+      &lmp->recs[1], &lmp->recs[0], 0, &lmp->row_colors[0],
+      &lmp->row_attribs[0], &row_height))
+  {
+    do_rec_event(lmp, 0, XIE_REC_FREE);
+    for (cnt = 0; cnt < lmp->nbr_realized_rows - 1; ++cnt)
+      row_copy(lmp, cnt + 1, cnt);
+    adjust_rows(lmp, -1);
+    --lmp->nbr_realized_rows;
+    return FALSE;
+  }
+  if (row_height)
+  {
+    lmp->pix_heights[0] = row_height;
+    lmp->set_heights[0] = TRUE;
+  }
+  else
+  {
+    lmp->pix_heights[0] = 0;
+    lmp->set_heights[0] = FALSE;
+  }
+  lm_invalidate_rows_internal((LM)lmp, 0, 0, FALSE, -1, TRUE );
+  return TRUE;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   calculate_cell_height
+lmp:        current lmp
+row:        row number of cell to calculate
+column:     column number of cell to calculate
+returns:    height of cell in pixels
+notes:      this function does not need to take into consideration the
+            variable fixed_row_height.  This function is only used by
+            lm_calculate_row_height, and will only be called if
+            fixed_row_height is false.
+notes:      In the future, we may wish to support word wrap. At this
+            point, the only way to have multiple lines in a cell is to
+            have '\n' characters in the text.
+-------------------------------------------------------------------------*/
+static int
+calculate_cell_height(LM_DATA *lmp, int row, int column)
+{
+  int pix_height;     /* pix_height does include the width of the rules */
+  int nbr_lines;
+  LM_CELL_DATA *cell_data;
+
+  cell_data = &lmp->cell_data[row][column];
+  if (lmp->lm_column_data[column]->wrap_text)
+  {
+    if (! cell_data->valid_data)
+      do_lm_cb_text(lmp, row, column, TRUE );
+    lm_wrap_text(lmp, row, column, TRUE);
+    nbr_lines = min(cell_data->nbr_lines, lmp->max_lines_in_cell);
+  }
+  else
+  {
+    nbr_lines = 1;
+    if (! cell_data->font_height)
+    {
+      FONT_OBJ *font;
+      int leading, ascent, descent, char_width;
+
+      if (cell_data->font)
+        font = cell_data->font;
+      else
+        font = lmp->font;
+      xi_get_font_metrics_font(font, &leading, &ascent, &descent, &char_width);
+      cell_data->font_height = leading + ascent + descent;
+    }
+  }
+#if XVTWS != WMWS
+  pix_height = nbr_lines * cell_data->font_height + CELL_VERTICAL_MARGIN
+              + RULE_WIDTH_H;
+#else
+  pix_height = nbr_lines * cell_data->font_height;
+#endif
+  pix_height = max(pix_height, lmp->pix_row_spacing);
+  return pix_height;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_calculate_row_height
+lmp:        current lmp
+row:        row number to calculate
+returns:    height of row in pixels
+notes:      if fixed_row_height is TRUE, then the calculation is easy.
+            if fixed_row_height is FALSE, then the calculation must take
+            word wrap into consideration, etc.
+            row height includes the height of the horizontal rule below
+            the row.
+-------------------------------------------------------------------------*/
+int
+lm_calculate_row_height(LM_DATA *lmp, int row)
+{
+  int pix_height;
+
+  if (lmp->fixed_row_height)
+    pix_height = lmp->pix_row_spacing;
+  else if (lmp->set_heights[row])
+    pix_height = lmp->pix_heights[row];
+  else
+  {
+    int cnt;
+    int cell_height;
+
+    pix_height = 0;
+    for (cnt = 0; cnt < lmp->nbr_columns; ++cnt)
+    {
+      cell_height = calculate_cell_height(lmp, row, cnt);
+      pix_height = max(pix_height, cell_height);
+    }
+  }
+  if (pix_height > lmp->mlr_height)
+    pix_height = lmp->mlr_height;
+  return pix_height;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   calculate_visibles
+lmp:        current lmp
+process:    calculates lmp->first_fully_vis
+            calculates lmp->last_fully_vis
+-------------------------------------------------------------------------*/
+void
+calculate_visibles(LM_DATA *lmp)
+{
+  int i, idx;
+  int *pix_offsetsp;
+  int *pix_heightsp;
+  BOOLEAN have_first;
+
+  have_first = FALSE;
+  lmp->first_fully_vis = 0;
+  lmp->last_fully_vis = 0;
+  for (i = 0,
+      pix_offsetsp = &lmp->pix_offsets[i],
+      pix_heightsp = &lmp->pix_heights[i];
+      i < lmp->nbr_realized_rows;
+      ++i, ++pix_offsetsp, ++pix_heightsp)
+  {
+    if (! have_first && *pix_offsetsp >= (-lmp->rrr_offset))
+    {
+      have_first = TRUE;
+      lmp->first_fully_vis = i;
+    }
+    /*
+    should be <, because we are dealing with mathematical rects, but we don't care if
+      the rule is not on the list.
+    *pix_offsetp + *pix_heightsp is the mathematical rect of the row, in rrr terms.
+    lmp->rrr_offset + lmp->mlr_height is the mathematical rect of the list, in rrr terms.
+    */
+#if XI_IS_CH
+    CTOS_IS_CH;
+    if (*pix_offsetsp + *pix_heightsp + lmp->rrr_offset <= lmp->mlr_height)
+      lmp->last_fully_vis = i;
+    CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    if (*pix_offsetsp + *pix_heightsp - 1 + lmp->rrr_offset <= lmp->mlr_height)
+      lmp->last_fully_vis = i;
+    CTOS_END;
+#endif
+  }
+  if (lmp->nbr_realized_rows)
+  {
+    idx = lmp->nbr_realized_rows - 1;
+    lmp->rrr_bottom = lmp->pix_offsets[idx] + lmp->pix_heights[idx];
+  }
+  else
+    lmp->rrr_bottom = 0;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   calculate_pix_offsets
+lmp:        current lmp
+process:    calculates the lmp->pix_offsets array
+      calculates lmp->first_fully_vis
+      calculates lmp->last_fully_vis
+-------------------------------------------------------------------------*/
+void
+calculate_pix_offsets(LM_DATA *lmp, BOOLEAN draw_changes )
+{
+  int i, cur_pix, idx;
+  int *pix_offsetsp;
+  int *pix_heightsp;
+  BOOLEAN have_first;
+
+  cur_pix = 0;
+  have_first = FALSE;
+  for (i = 0,
+      pix_offsetsp = &lmp->pix_offsets[i],
+      pix_heightsp = &lmp->pix_heights[i];
+      i < lmp->nbr_realized_rows;
+      ++i, ++pix_offsetsp, ++pix_heightsp)
+  {
+    int new_height;
+
+    new_height = lm_calculate_row_height(lmp, i);
+    if ( draw_changes &&
+        (*pix_offsetsp != cur_pix || *pix_heightsp != new_height ))
+    {
+      RCT rect;
+
+      lm_get_row_rect( &rect, (LM)lmp, i );
+      lm_invalidate_rect( lmp, &rect, FALSE );
+      rect.top = cur_pix;
+      rect.bottom = cur_pix + new_height;
+      lm_invalidate_rect( lmp, &rect, FALSE );
+    }
+    *pix_offsetsp = cur_pix;
+    *pix_heightsp = new_height;
+    if (! have_first && cur_pix >= (-lmp->rrr_offset))
+    {
+      have_first = TRUE;
+      lmp->first_fully_vis = i;
+    }
+    cur_pix += new_height;
+    /*
+    should be <=, because we are dealing with mathematical rects, but we don't care if
+      the rule is not on the list.
+    *pix_offsetp + *pix_heightsp is the mathematical rect of the row, in rrr terms.
+    lmp->rrr_offset + lmp->mlr_height is the mathematical rect of the list, in rrr terms.
+    */
+#if XI_IS_CH
+    CTOS_IS_CH;
+    if (cur_pix + lmp->rrr_offset <= lmp->mlr_height)
+      lmp->last_fully_vis = i;
+    CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    if ( cur_pix - 1 + lmp->rrr_offset <= lmp->mlr_height)
+      lmp->last_fully_vis = i;
+    CTOS_END;
+#endif
+  }
+  if (lmp->nbr_realized_rows)
+  {
+    idx = lmp->nbr_realized_rows - 1;
+    lmp->rrr_bottom = lmp->pix_offsets[idx] + lmp->pix_heights[idx];
+  }
+  else
+    lmp->rrr_bottom = 0;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   make_rrr_room_pix
+lmp:        current lmp
+pixels:     number of additional pixels desired in realized row rect
+            pixels may be negative, in which case, the desired pixels
+              are above the realized row rect
+            pixels may be positive, in which case, the desired pixels
+              are below the realized row rect
+returns:    recs read
+-------------------------------------------------------------------------*/
+int
+lm_make_rrr_room_pix(LM_DATA *lmp, int pixels, BOOLEAN do_redraw )
+{
+  int recs_read = 0;
+  int idx;
+
+  if (lmp->nbr_realized_rows == 0)
+  {
+    lmp->rrr_bottom = 0;
+    calculate_pix_offsets(lmp, FALSE );
+    return 0;
+  }
+
+  idx = lmp->nbr_realized_rows - 1;
+  lmp->rrr_bottom = lmp->pix_offsets[idx] + lmp->pix_heights[idx];
+
+  if (pixels < 0)
+  {
+    while (TRUE)
+    {
+      if (pixels >= lmp->rrr_offset)
+        return recs_read;
+      if (get_previous_rec(lmp))
+      {
+        int row_height;
+
+        row_height = lm_calculate_row_height(lmp, 0);
+        lmp->rrr_offset -= row_height;
+        calculate_pix_offsets(lmp, do_redraw);
+        calculate_visibles(lmp);
+        ++recs_read;
+      }
+      else
+        return recs_read;
+    }
+  }
+  else
+  {
+    while (TRUE)
+    {
+      if (lmp->rrr_bottom - lmp->mlr_height + lmp->rrr_offset >= pixels)
+        return recs_read;
+      if (lmp->get_all_records) return recs_read;
+      if (get_next_rec(lmp, FALSE))
+      {
+        calculate_pix_offsets(lmp, do_redraw);
+        calculate_visibles(lmp);
+        ++recs_read;
+      }
+      else
+        return recs_read;
+    }
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   make_rrr_room_rows
+lmp:        current lmp
+nbr_rows:   nbr of rows to scroll
+returns:    pixels to scroll
+-------------------------------------------------------------------------*/
+static int
+make_rrr_room_rows(LM_DATA *lmp, int* rows, BOOLEAN do_redraw)
+{
+  int nbr_rows = *rows;
+
+  if (nbr_rows < 0)
+  {
+    /* convert nbr_rows to positive, for ease of programming */
+    nbr_rows = -nbr_rows;
+    while (TRUE)
+    {
+      if (! nbr_rows )
+      {
+        *rows = 0;
+        return 0;
+      }
+      if (lmp->first_fully_vis - nbr_rows >= 0)
+      {
+        int pixels;
+
+        pixels = -(lmp->pix_offsets[lmp->first_fully_vis] -
+            lmp->pix_offsets[lmp->first_fully_vis - nbr_rows]);
+        lmp->update_rows_at_top = nbr_rows;
+        *rows = nbr_rows;
+        return pixels;
+      }
+      else
+      {
+        if (!lmp->get_all_records && get_previous_rec(lmp))
+        {
+          lmp->pix_heights[0] = lm_calculate_row_height(lmp, 0);
+          lmp->rrr_offset -= lmp->pix_heights[0];
+          calculate_pix_offsets(lmp, do_redraw);
+        }
+        else
+        {
+          calculate_pix_offsets(lmp, do_redraw);
+          nbr_rows = lmp->first_fully_vis;
+        }
+      }
+    }
+  }
+  else
+  {
+    BOOLEAN get_next_accepted = TRUE;
+    int pixels;
+
+    pixels = lmp->pix_offsets[lmp->first_fully_vis + nbr_rows] -
+            lmp->pix_offsets[lmp->first_fully_vis];
+    while (TRUE)
+    {
+      int delta_avail;
+
+      if (! nbr_rows)
+      {
+        *rows = 0;
+        return 0;
+      }
+      /*
+      if get_all_records is true, then we never need to get more records
+      if there is a row beyond the last partially visible row, then we
+        don't need to get more records
+      if a get next has been refused, then we have all the records that
+        we are going to get
+      */
+      if (lmp->get_all_records ||
+          lmp->last_fully_vis + 1 + nbr_rows < lmp->nbr_realized_rows ||
+          ! get_next_accepted)
+      {
+        delta_avail = lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
+                      lmp->pix_heights[lmp->nbr_realized_rows - 1] +
+                      lmp->rrr_offset - lmp->mlr_height;
+        if (lmp->get_all_records || pixels <= delta_avail || ! get_next_accepted)
+        {
+          int nrows, cnt, pcnt;
+
+          for (nrows = 0, cnt = lmp->last_fully_vis + 1, pcnt = 0;
+              pcnt < pixels && cnt < lmp->nbr_realized_rows;
+              ++nrows, ++cnt, pcnt += lmp->pix_heights[cnt])
+            ;
+          lmp->update_rows_at_bottom = nrows;
+          *rows = nbr_rows;
+          return pixels;
+        }
+      }
+      if (!lmp->get_all_records
+          && (get_next_accepted = get_next_rec(lmp, FALSE)) != 0)
+        calculate_pix_offsets(lmp, do_redraw);
+      else
+      {
+        calculate_pix_offsets(lmp, do_redraw);
+        nbr_rows = lmp->nbr_realized_rows - 1 - lmp->last_fully_vis;
+      }
+    }
+  }
+}
+
+static int make_room_rows( LM_DATA* lm_data, int rows, BOOLEAN do_draw )
+{
+  return make_rrr_room_rows( lm_data, &rows, do_draw );
+}
+
+/*-------------------------------------------------------------------------
+function:   do_scroll_bar
+itf:        current itf
+listdata:   list_data
+list:       list
+-------------------------------------------------------------------------*/
+void
+do_scroll_bar(XI_LIST_DATA *listdata)
+{
+  LM_DATA *lmp;
+
+  if (listdata->scroll_bar)
+  {
+    lmp = (LM_DATA *)listdata->lm;
+    if (lmp->get_all_records)
+    {
+      int top, prop;
+
+      if (lmp->rrr_offset == 0 && lmp->rrr_bottom < lmp->mlr_height)
+      {
+        top = 0;
+        prop = 100;
+      } else
+      {
+        top = (int)(-lmp->rrr_offset * 100L / lmp->rrr_bottom);
+        if (lmp->mlr_height - lmp->rrr_offset >= lmp->rrr_bottom - 1)
+          prop = 100 - top;
+        else
+          prop = (int)(lmp->mlr_height * 100L / lmp->rrr_bottom);
+      }
+      xvt_sbar_set_proportion(listdata->sb_win, HVSCROLL, prop);
+      xvt_sbar_set_pos(listdata->sb_win, HVSCROLL, top);
+    } else
+    {
+      int percent1 = 0;
+      int percent2 = 100;
+
+      if (lmp->nbr_realized_rows > 1)
+      {
+        do_lm_cb(listdata->lm, LM_CB_GET_PERCENT, lmp->first_fully_vis,
+            0, NULL, &percent1, 0);
+        do_lm_cb(listdata->lm, LM_CB_GET_PERCENT, lmp->last_fully_vis,
+            0, NULL, &percent2, 0);
+      }
+    xvt_sbar_set_proportion(listdata->sb_win, HVSCROLL, percent2 - percent1);
+    xvt_sbar_set_pos(listdata->sb_win, HVSCROLL, percent1);
+#if XI_IS_CH
+    CTOS_IS_CH;
+    xvt_sbar_set_range(listdata->sb_win, HVSCROLL, 0, 100 - (percent2 - percent1));
+      CTOS_END;
+#endif
+    }
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:       lm_remove_all_rows
+lm:             current lm
+-------------------------------------------------------------------------*/
+
+void lm_remove_all_rows( LM_DATA* lmp, BOOLEAN delete_focus )
+{
+  int i;
+  LM_CB_DATA lm_cb_data;
+
+  if (lmp->focus_rec && delete_focus )
+  {
+    int idx;
+    BOOLEAN found = FALSE;
+
+    for (idx = 0; idx < lmp->nbr_realized_rows; ++idx)
+    {
+      if (lmp->focus_rec == lmp->recs[idx])
+      {
+        found = TRUE;
+        break;
+      }
+    }
+    if (! found)
+    {
+      lm_cb_data.lm = (LM)lmp;
+      lm_cb_data.cb_type = LM_CB_REC_FREE;
+      lm_cb_data.cid = lmp->cid;
+      lm_cb_data.win = lmp->win;
+      lm_cb_data.v.rec_free.record = lmp->focus_rec;
+      (*lmp->lm_cb)(&lm_cb_data);
+    }
+  }
+
+  for (i = 0; i < lmp->nbr_realized_rows; ++i)
+    do_rec_event(lmp, i, XIE_REC_FREE);
+
+  lmp->nbr_realized_rows = 0;
+  lmp->rrr_bottom = 0;
+  lmp->rrr_offset = 0;
+}
+
+
+BOOLEAN
+lm_list_has_focus(LM_DATA *lmp)
+{
+  XI_ITF_DATA *itf;
+  BOOLEAN retval;
+
+  itf = lmp->itf_obj->v.itf;
+  retval = (itf->focus_obj != NULL && itf->focus_obj->parent == lmp->list_obj);
+  return retval;
+}
+
+
+BOOLEAN
+lm_cell_has_focus( LM_DATA *lmp, int row, int column,
+                          BOOLEAN is_vert_scrolled)
+{
+  XI_ITF_DATA *itf;
+  XI_OBJ *focus_obj;
+  XI_CELL_DATA *cd;
+
+  if (lmp->txt_is_invisible)
+    return FALSE;
+  itf = lmp->itf_obj->v.itf;
+  focus_obj = itf->focus_obj;
+  if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
+      focus_obj->type == XIT_CELL)
+  {
+    cd = &focus_obj->v.cell;
+    return (cd->row == row && cd->column == column
+            && cd->is_vert_scrolled == is_vert_scrolled);
+  }
+  return FALSE;
+}
+
+
+BOOLEAN
+lm_row_has_focus( LM_DATA *lmp, int row, BOOLEAN is_vert_scrolled)
+{
+  XI_ITF_DATA *itf;
+  XI_OBJ *focus_obj;
+  XI_CELL_DATA *cd;
+
+#if 0
+  if (lmp->txt_is_invisible && ! lmp->horizontally_scrolling_list)
+    return FALSE;
+#endif
+  itf = lmp->itf_obj->v.itf;
+  focus_obj = itf->focus_obj;
+  if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
+      focus_obj->type == XIT_CELL)
+  {
+    cd = &focus_obj->v.cell;
+    return (cd->row == row && cd->is_vert_scrolled == is_vert_scrolled);
+  }
+  return FALSE;
+}
+
+
+void
+lm_get_focus_cell(LM_DATA *lmp, int *rowp, int *columnp, BOOLEAN* is_vert_scrolled)
+{
+  XI_ITF_DATA *itf;
+  XI_OBJ *focus_obj;
+  XI_CELL_DATA *cd;
+
+  itf = lmp->itf_obj->v.itf;
+  focus_obj = itf->focus_obj;
+  if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
+      focus_obj->type == XIT_CELL)
+  {
+    cd = &focus_obj->v.cell;
+    *rowp = cd->row;
+    *columnp = cd->column;
+    *is_vert_scrolled = cd->is_vert_scrolled;
+    return;
+  }
+  *rowp = 0;
+  *columnp = 0;
+  *is_vert_scrolled = FALSE;
+  return;
+}
+
+
+void lm_set_focus_cell(LM_DATA *lmp, int row, int column, BOOLEAN is_vert_scrolled)
+{
+  XI_ITF_DATA *itf;
+  XI_OBJ *focus_obj;
+  XI_CELL_DATA *cd;
+
+  itf = lmp->itf_obj->v.itf;
+  focus_obj = itf->focus_obj;
+  if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
+      focus_obj->type == XIT_CELL)
+  {
+    cd = &focus_obj->v.cell;
+    cd->row = row;
+    cd->column = column;
+    cd->is_vert_scrolled = (unsigned char)is_vert_scrolled;
+    return;
+  }
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20921", 20921,
+    "lm_set_focus_cell called when list does not have focus");
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* lm_set_focus_text                                                          */
+/* -------------------------------------------------------------------------- */
+void lm_set_focus_text( LM_DATA* lmp, const char* new_text )
+{
+  int len = strlen(new_text) + 1;
+  if (lmp->focus_cell_text)
+    lmp->focus_cell_text = (char *)xi_tree_realloc(lmp->focus_cell_text, len);
+  else
+    lmp->focus_cell_text = (char *)xi_tree_malloc(len, lmp);
+  strcpy(lmp->focus_cell_text, new_text);
+}
+
+void
+lm_make_invis(LM_DATA *lmp)
+{
+  TXT_DATA *txt;
+
+  if (! lm_list_has_focus(lmp))
+    return;
+  if (lmp->txt_is_invisible)
+    return;
+  if (lmp->txt)
+  {
+    int     focus_row, focus_column;
+    BOOLEAN v_scrolled;
+
+    lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+    lmp->txt_is_invisible = TRUE;
+    lmp->focus_rec = lmp->recs[focus_row];
+    lmp->focus_rec_color = lmp->row_colors[focus_row];
+    lmp->focus_rec_attrib = lmp->row_attribs[focus_row];
+    lmp->focus_rec_height = lmp->pix_heights[focus_row];
+    txt = lmp->txt;
+    lm_set_focus_text( lmp, txt->text );
+    lmp->focus_cell_ip1 = txt->selstart;
+    lmp->focus_cell_ip2 = txt->selstop;
+    txt_hide_caret(lmp->txt);
+    txt_caret(lmp->txt, FALSE);
+    if (lmp->focus_cell_ip1 != lmp->focus_cell_ip2)
+      redraw_cell((LM)lmp, focus_row, focus_column, FALSE );
+    xi_tree_free((char *)lmp->txt);
+    lmp->txt = NULL;
+  }
+  else
+  {
+    lmp->txt_is_invisible = FALSE;
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:       fill_previous
+returns:        # of records read
+-------------------------------------------------------------------------*/
+static int fill_previous( LM_DATA* lmp )
+{
+  int *pix_heights, *pix_offsets;
+  int offset, height;
+  int i;
+  int result = 0;
+
+  while (TRUE)
+  {
+
+    if (! get_previous_rec(lmp))
+      break;
+    result++;
+    /* recalculate the heights and offsets of every row */
+    lmp->pix_heights[0] = lm_calculate_row_height(lmp, 0);
+    offset = 0;
+    for (i = 0, pix_heights = &lmp->pix_heights[0],
+        pix_offsets = &lmp->pix_offsets[0];
+        i < lmp->nbr_realized_rows;
+        ++i, ++pix_heights, ++pix_offsets)
+    {
+      *pix_offsets = offset;
+      offset += *pix_heights;
+    }
+
+    calculate_visibles(lmp);
+
+    /*
+    if we finally have enough rows to display the entire list
+
+    note: we subtract 1 from the space necessary because it is not
+    necessary to create space for the pixel at the bottom of the
+    last row.
+    */
+    height = lmp->pix_heights[lmp->nbr_realized_rows - 1];
+    if (! height)
+      height = lmp->pix_row_spacing;
+    if (! lmp->get_all_records &&
+        (lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
+        height - 1
+        >= lmp->mlr_height))
+      break;
+  }
+
+  calculate_pix_offsets(lmp, FALSE);
+
+  lmp->rrr_bottom = lmp->pix_offsets[lmp->nbr_realized_rows - 1]
+      + lmp->pix_heights[lmp->nbr_realized_rows - 1];
+  /*
+  subtract 1 from rrr_bottom because of the pixel at the bottom of the
+  last row.
+  */
+  lmp->rrr_offset = lmp->mlr_height - (lmp->rrr_bottom - 1);
+  lmp->rrr_offset = min(0, lmp->rrr_offset);
+
+  /*
+  although we have adjusted pix_offsets, and pix_heights, it is still necessary to calculate
+  the first and last fully visible rows
+  */
+  calculate_visibles(lmp);
+
+  /*
+  if the page down does not make the first row editable, then
+  scroll the exact amount to make it editable
+  */
+  if (-lmp->rrr_offset !=
+      lmp->pix_offsets[lmp->first_fully_vis])
+  {
+    lmp->rrr_offset = -lmp->pix_offsets[lmp->first_fully_vis];
+    calculate_visibles(lmp);
+  }
+  return result;
+}
+
+/*-------------------------------------------------------------------------*/
+/*           data structure for passing around lm_scroll functions         */
+/*-------------------------------------------------------------------------*/
+
+typedef struct {
+  int           nbr_lines;
+  int           percent;
+  long          rec;
+  BOOLEAN       have_rec;
+  COLOR         color;
+  unsigned long attrib;
+  int           row_height_arg;
+  int           scroll_type;
+  int           pix_overlap;
+  int           nbr_pixels;
+  RCT           focus_cell_rct;
+  BOOLEAN       have_pixels;
+  BOOLEAN       list_had_focus;
+  BOOLEAN       is_first_or_last;
+  int           focus_row;
+  int           focus_column;
+  BOOLEAN       v_scrolled;
+  int           pixels_scrolled;
+} lm_scroll_data;
+
+/*-------------------------------------------------------------------------*/
+/*  lm_scroll_data_construct                                               */
+/*-------------------------------------------------------------------------*/
+
+static void lm_scroll_data_construct( LM_DATA* lmp, lm_scroll_data* data,
+                                      LM_SCROLL_ARG* arg )
+{
+  int pref_overlap;
+
+  data->nbr_lines = arg->nbr_lines;
+  data->percent = arg->percent;
+  data->rec = arg->rec;
+  data->have_rec = arg->have_rec;
+  data->color = arg->color;
+  data->attrib = arg->attrib;
+  data->row_height_arg = arg->row_height;
+  data->have_pixels = FALSE;
+  data->list_had_focus = FALSE;
+  data->is_first_or_last = FALSE;
+  if (arg->nbr_lines == XI_SCROLL_FIRST && arg->percent == 100)
+    data->nbr_lines = XI_SCROLL_LAST;
+  if (! lmp->nbr_realized_rows)
+    data->nbr_lines = XI_SCROLL_FIRST;
+  if (arg->have_rec)
+  {
+    if (arg->rec_at_top)
+      data->nbr_lines = XI_SCROLL_FIRST;
+    else
+      data->nbr_lines = XI_SCROLL_LAST;
+  }
+  data->scroll_type = data->nbr_lines;
+  pref_overlap = (int)xi_get_pref(XI_PREF_OVERLAP);
+  data->pix_overlap = pref_overlap * lmp->pix_row_spacing;
+  data->pixels_scrolled = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/*  lm_scroll_remove focus                                                 */
+/*-------------------------------------------------------------------------*/
+
+static BOOLEAN lm_scroll_remove_focus( LM_DATA* lmp, lm_scroll_data* data,
+                                      XI_OBJ* old_focus_obj )
+{
+  /* remove the focus from the list being scrolled */
+  if (lm_list_has_focus(lmp))
+  {
+    data->list_had_focus = TRUE;
+    lm_get_focus_cell( lmp, &data->focus_row, &data->focus_column,
+                      &data->v_scrolled );
+    if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+    {
+      if (lmp->focus_rec == 0)
+      {
+        lm_make_invis(lmp);
+        switch (data->nbr_lines)
+        {
+          case XI_SCROLL_FIRST:
+          {
+            int current_percent;
+
+            do_lm_cb( (LM)lmp, LM_CB_GET_PERCENT,
+                      lmp->first_fully_vis, 0, NULL,&current_percent, 0);
+            lmp->focus_rec_is_above = (data->percent > current_percent);
+            break;
+          }
+          case XI_SCROLL_LAST:
+            lmp->focus_rec_is_above = TRUE;
+            break;
+          case XI_SCROLL_PGUP:
+            lmp->focus_rec_is_above = FALSE;
+            break;
+          case XI_SCROLL_PGDOWN:
+            lmp->focus_rec_is_above = TRUE;
+            break;
+          default:
+            lmp->focus_rec_is_above = (data->nbr_lines > 0);
+            break;
+        }
+      }
+    }
+    else
+    {
+      xi_get_rect(old_focus_obj, &data->focus_cell_rct);
+      if (! xi_move_focus(lmp->itf_obj))
+        return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+/*------------------------------------------------------------------------- */
+/*  lm_scroll_calc_lines                                                    */
+/*  if nbr_lines is not an integral, and instead is one of XI_SCROLL_FIRST, */
+/*  XI_SCROLL_LAST, XI_SCROLL_PGUP, or XI_SCROLL_PGDOWN, then calculate     */
+/*  the number of lines.                                                    */
+/*------------------------------------------------------------------------- */
+static void lm_scroll_calc_lines( LM_DATA* lmp, lm_scroll_data* data )
+{
+  switch (data->nbr_lines)
+  {
+    case XI_SCROLL_FIRST:
+    case XI_SCROLL_LAST:
+      data->is_first_or_last = TRUE;
+      break;
+    case XI_SCROLL_PGUP:
+#if XI_IS_CH
+      CTOS_IS_CH;
+      data->nbr_pixels = -(lmp->mlr_height - data->pix_overlap);
+      CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+      CTOS_IS_PM;
+      data->nbr_pixels = -(lmp->mlr_height - data->pix_overlap + 1);
+      CTOS_END;
+#endif
+      data->have_pixels = TRUE;
+      break;
+    case XI_SCROLL_PGDOWN:
+#if XI_IS_CH
+      CTOS_IS_CH;
+      data->nbr_pixels = lmp->mlr_height - data->pix_overlap;
+      CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+      CTOS_IS_PM;
+      data->nbr_pixels = lmp->mlr_height - data->pix_overlap + 1;
+      CTOS_END;
+#endif
+      data->have_pixels = TRUE;
+      break;
+  }
+}
+
+/*------------------------------------------------------------------------- */
+/*   lm_scroll_get_initial_rec                                              */
+/*------------------------------------------------------------------------- */
+static BOOLEAN lm_scroll_get_initial_rec( LM_DATA* lmp, lm_scroll_data* data,
+                            int record_location, int event_type )
+{
+  int     row_height;
+  BOOLEAN refused;
+
+  /* first, get rid of all rows */
+  lm_remove_all_rows( lmp, FALSE );
+  make_rec_available(lmp, (BOOLEAN)record_location, (BOOLEAN)!data->have_rec, TRUE);
+  if (data->have_rec)
+  {
+  lmp->recs[0] = data->rec;
+  lmp->row_colors[0] = data->color;
+  lmp->row_attribs[0] = data->attrib;
+  row_height = data->row_height_arg;
+  refused = FALSE;
+  }
+  else
+  {
+  refused = do_lm_cb_get( (LM)lmp, event_type, &lmp->recs[0], &lmp->recs[0],
+                  data->percent, &lmp->row_colors[0],
+                  &lmp->row_attribs[0], &row_height);
+    if (refused)
+    {
+      do_rec_event(lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE);
+      --lmp->nbr_realized_rows;
+    calculate_visibles(lmp);
+    }
+  }
+  if (! refused)
+  {
+    if (row_height)
+    {
+      lmp->pix_heights[0] = row_height;
+      lmp->set_heights[0] = TRUE;
+    }
+    else
+    {
+      lmp->pix_heights[0] = 0;
+      lmp->set_heights[0] = FALSE;
+    }
+    lmp->pix_offsets[0] = 0;
+    lmp->pix_heights[0] = lm_calculate_row_height(lmp, 0);
+    lm_invalidate_rows_internal((LM)lmp, 0, 0, FALSE, -1, TRUE );
+  }
+  return !refused;
+}
+
+/*------------------------------------------------------------------------- */
+/*   lm_scroll_fill_forward                                                 */
+/*   returns # of records read if fill previous called, otherwise 0         */
+/*------------------------------------------------------------------------- */
+
+static int lm_scroll_fill_forward( LM_DATA* lmp, BOOLEAN have_rec )
+{
+  BOOLEAN refused;
+
+  while (TRUE)
+  {
+    int idx;
+
+    refused = !get_next_rec(lmp, TRUE);
+    if ( refused )
+      break;
+    idx = lmp->nbr_realized_rows - 1;
+    lmp->pix_heights[idx] = lm_calculate_row_height(lmp, idx);
+    if (idx > 0)
+      lmp->pix_offsets[idx] = lmp->pix_offsets[idx - 1]
+                              + lmp->pix_heights[idx - 1];
+    else
+      lmp->pix_offsets[idx] = 0;
+
+    /* if we finally have enough rows to display the entire list */
+    if (!lmp->get_all_records && ( lmp->pix_offsets[idx] + lmp->pix_heights[idx]
+        >= lmp->mlr_height))
+      break;
+  }
+
+  /*
+  although we have adjusted pix_offsets, and pix_heights, it is still
+  necessary to calculate the first and last fully visible rows
+  */
+  calculate_visibles(lmp);
+
+  /*
+  If we have the first record and the list is not full, try getting
+  previous records.
+  */
+  if ( have_rec && refused )
+    return fill_previous( lmp );
+  return 0;
+}
+
+/*------------------------------------------------------------------------- */
+/*   lm_scroll_first                                                        */
+/*   returns row # of first record requested - i.e. for xi_scroll_rec, the  */
+/*   row # of the new record.  for scroll first with a percentage, the      */
+/*   row # of that percentage.  Normally 0, but with back-fill, can be      */
+/*   a positive number.                                                     */
+/*------------------------------------------------------------------------- */
+static int lm_scroll_first( LM_DATA* lmp, lm_scroll_data* data )
+{
+  int result = 0;
+
+  if ( (lmp->get_all_records || lmp->keep_all_records)
+      && lmp->nbr_realized_rows > 0)
+  {
+    /* have_rec */
+    lmp->rrr_offset = -(int)((long)lmp->rrr_bottom * data->percent / 100);
+    calculate_visibles(lmp);
+    lmp->rrr_offset = -lmp->pix_offsets[lmp->first_fully_vis];
+  } else
+  {
+    if (lm_scroll_get_initial_rec( lmp, data, REC_AT_BOTTOM, LM_CB_GET_FIRST ))
+      result = lm_scroll_fill_forward( lmp, data->have_rec );
+    if (! lmp->get_all_records && ! lmp->keep_all_records)
+    {
+      int nbr_to_free, cnt, idx;
+
+      nbr_to_free = lmp->first_fully_vis - 1;
+      if ( nbr_to_free > 0 )
+      {
+        for (cnt = 0; cnt < nbr_to_free; cnt++)
+        {
+          lmp->rrr_offset += lmp->pix_heights[cnt];
+          do_rec_event(lmp, cnt, XIE_REC_FREE);
+        }
+
+        for (idx = nbr_to_free; idx < lmp->nbr_realized_rows; ++idx)
+          row_copy(lmp, idx, idx - nbr_to_free);
+        result -= nbr_to_free;
+        adjust_rows(lmp, -nbr_to_free);
+        lmp->nbr_realized_rows -= nbr_to_free;
+      }
+      /* free any unnecessary records at the end of the list */
+      nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
+      for (idx = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
+          cnt < nbr_to_free; idx++, cnt++)
+        do_rec_event(lmp, idx, XIE_REC_FREE);
+      lmp->nbr_realized_rows -= cnt;
+      calculate_pix_offsets(lmp, FALSE);
+    }
+  }
+  return result;
+}
+
+/*------------------------------------------------------------------------- */
+/*   lm_scroll_last                                                         */
+/*   returns row # of requested row                                         */
+/*------------------------------------------------------------------------- */
+static int lm_scroll_last( LM_DATA* lmp, lm_scroll_data* data )
+{   /* scroll last */
+  int result = 0;
+
+  if (lmp->get_all_records)
+  {
+    if (lmp->rrr_bottom < lmp->mlr_height)
+      lmp->rrr_offset = 0;
+    else
+#if XI_IS_CH
+      CTOS_IS_CH;
+    lmp->rrr_offset = lmp->mlr_height - lmp->rrr_bottom;
+    CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    lmp->rrr_offset = lmp->mlr_height - lmp->rrr_bottom + 1;
+    CTOS_END;
+#endif
+    calculate_visibles(lmp);
+
+    /*
+    if the page up does not make the first row editable, then
+    scroll the exact amount to make it editable
+    */
+    if (-lmp->rrr_offset !=
+        lmp->pix_offsets[lmp->first_fully_vis])
+    {
+      int p;
+
+      p = lmp->pix_offsets[lmp->first_fully_vis] +
+          lmp->rrr_offset;
+      data->nbr_pixels += p;
+      lmp->rrr_offset -= p;
+      calculate_visibles(lmp);
+    }
+  } else
+  {
+    data->percent = 0;
+    if (lm_scroll_get_initial_rec( lmp, data, REC_AT_TOP, LM_CB_GET_LAST ))
+    {
+      result = fill_previous( lmp );
+      /*
+      get one record after the last record, so that there will not be a
+      gray space below the last record, unless there are no more records.
+      */
+      get_next_rec(lmp, FALSE);
+      calculate_pix_offsets(lmp, FALSE);
+    }
+  }
+  return result;
+}
+
+/*------------------------------------------------------------------------- */
+/*   lm_scroll_calc_pixels                                                  */
+/*------------------------------------------------------------------------- */
+static void lm_scroll_calc_pixels( LM_DATA* lmp, lm_scroll_data* data )
+{
+  /* calculate the max number of pixels that we should scroll */
+  if (data->nbr_pixels < 0)
+  {
+    int p;
+
+    data->nbr_pixels = max(data->nbr_pixels, lmp->rrr_offset);
+    lmp->rrr_offset -= data->nbr_pixels;
+    calculate_visibles(lmp);
+
+    /*
+    if the page up does not make the first row editable, then
+    scroll the exact amount to make it editable
+    */
+    if (-lmp->rrr_offset !=
+        lmp->pix_offsets[lmp->first_fully_vis])
+    {
+      p = lmp->pix_offsets[lmp->first_fully_vis - 1] +
+          lmp->rrr_offset;
+      data->nbr_pixels += p;
+      lmp->rrr_offset -= p;
+      calculate_visibles(lmp);
+    }
+  } else
+  {
+    int p;
+
+    calculate_pix_offsets(lmp, FALSE);
+
+    /*
+    following line puts row coming onto the list at the bottom of the list
+    completly on the list.  new behavior is to have the row at the top of
+    the list to always be completely on the list.
+    nbr_pixels = min(nbr_pixels, lmp->rrr_bottom - lmp->mlr_height + lmp->rrr_offset);
+    */
+    data->nbr_pixels = max(data->nbr_pixels, 0);
+    lmp->rrr_offset -= data->nbr_pixels;
+    calculate_visibles(lmp);
+
+    /*
+    if the page down does not make the first row editable, then
+    scroll the exact amount to make it editable
+    */
+    if (-lmp->rrr_offset !=
+        lmp->pix_offsets[lmp->first_fully_vis])
+    {
+      p = lmp->pix_offsets[lmp->first_fully_vis - 1] +
+          lmp->rrr_offset;
+      data->nbr_pixels += p;
+      lmp->rrr_offset -= p;
+      calculate_visibles(lmp);
+    }
+
+    /*
+    if the page down leaves too much room at the bottom, then make more
+    rows visible.
+    */
+    while (TRUE)
+    {
+      int h, pix_left;
+
+      if (lmp->first_fully_vis == 0)
+        break;
+      h = lmp->pix_heights[lmp->first_fully_vis - 1];
+      /*
+      Add 1 to pix_left (pixels left in mlr), because it is ok for the pixel
+      required for the rule at the bottom of the row to fall below the
+      visible portion of the list.
+      */
+      pix_left = -(lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
+          lmp->pix_heights[lmp->nbr_realized_rows - 1] +
+          lmp->rrr_offset - lmp->mlr_height) + 1;
+      if (pix_left < h)
+        break;
+      data->nbr_pixels -= h;
+      lmp->rrr_offset += h;
+      calculate_visibles(lmp);
+    }
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_get_scroll_rct
+lmp:        current lmp
+r:          pointer to rectangle to be filled in
+returns:    r
+-------------------------------------------------------------------------*/
+static RCT* lm_get_scroll_rct(LM_DATA *lmp, RCT *r)
+{
+  *r = lmp->mlr;
+  if (lmp->pixel_width)
+    r->right = r->left + lmp->pixel_width + 2 * BORDER_WIDTH;
+  return r;
+}
+
+
+/*------------------------------------------------------------------------- */
+/*   lm_scroll_middle                                                       */
+/*------------------------------------------------------------------------- */
+static int lm_scroll_middle( LM_DATA* lmp, lm_scroll_data* data,
+                            BOOLEAN invalidate )
+{
+  int recs_read;
+
+  recs_read = 0;
+  if (data->have_pixels)
+    recs_read = lm_make_rrr_room_pix(lmp, data->nbr_pixels, FALSE);
+  else if (data->nbr_lines)
+  {
+    recs_read = data->nbr_lines;
+    data->nbr_pixels = make_rrr_room_rows(lmp, &recs_read, FALSE);
+  }
+  lm_scroll_calc_pixels( lmp, data );
+  if (! lmp->get_all_records && ! lmp->keep_all_records)
+  {
+    int nbr_to_free, cnt, idx;
+
+    nbr_to_free = lmp->first_fully_vis;
+    if (nbr_to_free)
+    {
+      for (cnt = 0; cnt < nbr_to_free; cnt++)
+      {
+        lmp->rrr_offset += lmp->pix_heights[cnt];
+        do_rec_event(lmp, cnt, XIE_REC_FREE);
+      }
+
+      for (cnt = nbr_to_free; cnt < lmp->nbr_realized_rows; ++cnt)
+        row_copy(lmp, cnt, cnt - nbr_to_free);
+      adjust_rows(lmp, -nbr_to_free);
+      lmp->nbr_realized_rows -= nbr_to_free;
+    }
+
+    /* free any unnecessary records at the end of the list */
+    nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
+    for (idx = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
+        cnt < nbr_to_free;
+        idx++, cnt++)
+      do_rec_event(lmp, idx, XIE_REC_FREE);
+    lmp->nbr_realized_rows -= cnt;
+
+    for (idx = lmp->nbr_realized_rows;
+        idx < lmp->realized_rows_array_len;
+        ++idx)
+      init_row(lmp, idx);
+    calculate_pix_offsets(lmp, FALSE);
+  }
+
+  if (invalidate)
+  {
+    RCT r;
+
+    lm_get_scroll_rct(lmp, &r);
+    xi_set_clip(lmp->win, NULL);
+    if (data->nbr_pixels)
+    {
+      xvt_dwin_update(lmp->win);
+      xi_set_update_obj(lmp->list_obj);
+      lmp->update_cells_only = TRUE;
+      xi_scroll_rect(lmp->win, &r, 0, -data->nbr_pixels);
+      data->pixels_scrolled = data->nbr_pixels;
+    }
+  }
+  return recs_read;
+}
+
+/*------------------------------------------------------------------------- */
+/*   lm_scroll_replace_focus                                                */
+/*------------------------------------------------------------------------- */
+static void lm_scroll_replace_focus( LM_DATA* lmp, lm_scroll_data* data,
+                                    XI_OBJ* old_focus_obj, BOOLEAN same_cell )
+{
+  /* put the focus back */
+  if (data->list_had_focus)
+  {
+    if (old_focus_obj->type == XIT_CELL)
+    {
+      if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+        lm_make_vis(lmp);
+      else
+      {
+        if (same_cell)
+        {
+          int col = old_focus_obj->v.cell.column;
+          int row, t, b;
+          int max_intersect, intersect_row;
+          XI_OBJ cell;
+          RCT cell_rct;
+          int tr;
+
+          max_intersect = 0;
+          intersect_row = -1;
+          tr = min(lmp->nbr_realized_rows, lmp->last_fully_vis + 1);
+          for (row = lmp->first_fully_vis; row < tr; ++row)
+          {
+            XI_MAKE_CELL(&cell, lmp->list_obj, (unsigned char)row,
+                (unsigned char)col);
+            xi_get_rect(&cell, &cell_rct);
+            t = max(cell_rct.top, data->focus_cell_rct.top);
+            b = min(cell_rct.bottom, data->focus_cell_rct.bottom);
+            if ((b - t) > max_intersect)
+            {
+              max_intersect = b - t;
+              intersect_row = row;
+            }
+          }
+          if (intersect_row != -1)
+          {
+            XI_MAKE_CELL(&cell, lmp->list_obj, (unsigned char)intersect_row,
+                (unsigned char)col);
+            xi_move_focus(&cell);
+          }
+        }
+        else
+        {
+          switch (data->scroll_type)
+          {
+            case XI_SCROLL_FIRST:
+            case XI_SCROLL_PGUP:
+              data->focus_row = lmp->first_fully_vis;
+              break;
+            case XI_SCROLL_LAST:
+            case XI_SCROLL_PGDOWN:
+              data->focus_row = lmp->last_fully_vis;
+              break;
+            default:
+              data->focus_row = clip( data->focus_row, lmp->first_fully_vis,
+                                    lmp->last_fully_vis);
+              break;
+          }
+        }
+      }
+    }
+    else
+      xi_move_focus(old_focus_obj);
+  }
+}
+/*-------------------------------------------------------------------------
+function:       lm_scroll
+lm:             current lm
+nbr_lines:      nbr of lines to scroll, may be positive or negative, may be set
+                to XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, or XI_SCROLL_PGDN
+percent:        passed with XI_SCROLL_FIRST event
+same_cell:      sometimes the focus goes back onto the same cell.  In other cases,
+                for instance, XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, and
+                XI_SCROLL_PGDN, we don't want to put the focus back on the same cell,
+                but instead, want to put the focus on the first or last fully visible
+                row.
+invalidate:     indicates whether to invalidate the list. This is only set to FALSE when
+                xi_scroll_internal is called when the interface is created.
+rec:            if have_rec is TRUE, then use rec for the first record, and don't do get first
+-------------------------------------------------------------------------*/
+int lm_scroll(LM_SCROLL_ARG *arg)
+{
+  lm_scroll_data data;
+  int            result = 0;
+  XI_OBJ*        old_focus_obj;
+  LM_DATA*       lmp = (LM_DATA*)arg->lm;
+  XI_OBJ*        itf = lmp->itf_obj;
+  BOOLEAN        invalidate = !itf->v.itf->half_baked;
+
+  if ((xi_get_attrib(lmp->list_obj) & XI_ATR_VISIBLE) == 0)
+    invalidate = FALSE;
+  lm_scroll_data_construct( lmp, &data, arg );
+  /*
+  If the focus is on the first row, and scrolling up, or the focus is on the
+  last row and scrolling down, return 0.
+  */
+  if (lmp->get_all_records)
+  {
+    if (lmp->first_fully_vis == 0 && data.nbr_lines < 0)
+      return 0;
+    if (lmp->last_fully_vis == lmp->nbr_realized_rows &&
+        data.nbr_lines > 0 && data.nbr_lines < XI_SCROLL_PGUP)
+      return 0;
+  }
+  if (! lmp->itf_obj->v.itf->half_baked && invalidate)
+    xvt_dwin_update(lmp->win);
+  old_focus_obj = itf->v.itf->focus_obj;
+  if (!lm_scroll_remove_focus( lmp, &data, old_focus_obj ))
+    return 0;
+  lm_scroll_calc_lines( lmp, &data );
+  if (data.is_first_or_last)
+  {
+    if (data.nbr_lines == XI_SCROLL_FIRST)
+      result = lm_scroll_first( lmp, &data );
+    else
+      result = lm_scroll_last( lmp, &data );
+    if (invalidate)
+    {
+      RCT r;
+
+      xi_invalidate_rect(lmp->win, lm_get_scroll_rct(lmp, &r));
+    }
+  } else
+  {
+    result = lm_scroll_middle( lmp, &data, invalidate );
+    arg->pixels_scrolled = data.pixels_scrolled;
+  }
+
+  lm_scroll_replace_focus( lmp, &data, old_focus_obj, arg->same_cell );
+  if (lmp->row_focus_border && lmp->nbr_realized_rows > 0)
+  {
+    int focus_row, focus_column;
+    BOOLEAN is_vert_scrolled;
+    BOOLEAN is_hscrolled;
+    BOOLEAN is_vis;
+
+    lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
+    is_vis = lm_is_cell_visible( lmp, focus_row, focus_column, TRUE,
+                                &is_hscrolled);
+    if ((is_vis || is_hscrolled) && !is_vert_scrolled )
+    {
+      lm_redraw_row(lmp, focus_row, FALSE);
+      if ( lmp->txt != NULL )
+        txt_redraw(lmp->txt, FALSE);
+    }
+  }
+  do_scroll_bar( lmp->list_obj->v.list );
+  if (invalidate)
+    xvt_dwin_update( lmp->win );
+  return result;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_set_text
+lm:         current lm
+s:          string to set
+row:
+column:
+-------------------------------------------------------------------------*/
+void lm_set_text(LM lm, char *s, int row, int column, BOOLEAN v_scrolled )
+{
+  BOOLEAN was_suspended = FALSE;
+  LM_COLUMN_DATA *lmcd;
+  RCT rct;
+  LM_DATA *lmp = LMP(lm);
+
+  lmcd = lmp->lm_column_data[column];
+  if (row == LM_HEADING_TEXT)
+  {
+    lmcd->heading_text = (char *)xi_tree_realloc(lmcd->heading_text,
+        strlen(s) + 1);
+    strcpy(lmcd->heading_text, s);
+    lm_get_cell_rect(&rct, lm, 1, column, FALSE, TRUE);
+    rct.top = lmp->pix_hdr_bottom -
+        max(lmp->pix_cell_height, lmp->min_heading_height +
+        2 * BORDER_WIDTH);
+    rct.bottom = lmp->pix_hdr_bottom;
+    if ( (lmp->attrib & LM_ATR_VISIBLE) != 0)
+      xi_invalidate_rect(lmp->win, &rct);
+  } else
+  {
+    int     new_row_height;
+    int     focus_row, focus_column;
+    BOOLEAN v_scroll;
+
+    if (lm_cell_has_focus(lmp, row, column, v_scrolled))
+    {
+      was_suspended = TRUE;
+      lm_make_invis(lmp);
+    }
+    if (!v_scrolled)
+      tgstrncpy( lmp->buffer[row] + lmcd->text_offset, s, lmcd->text_size);
+    lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scroll);
+    if (lmp->txt_is_invisible && row == focus_row && column == focus_column)
+    {
+      int len;
+
+      len = strlen(s) + 1;
+      if (lmp->focus_cell_text)
+      lmp->focus_cell_text = (char *)xi_tree_realloc(lmp->focus_cell_text, len);
+      else
+        lmp->focus_cell_text = (char *)xi_tree_malloc(len, lmp);
+      strcpy(lmp->focus_cell_text, s);
+      if (lmp->lm_column_data[column]->attrib | XI_ATR_AUTOSELECT)
+      {
+        lmp->focus_cell_ip1 = 0;
+        lmp->focus_cell_ip2 = strlen(s);
+      }
+      else
+      {
+        lmp->focus_cell_ip1 = 0;
+        lmp->focus_cell_ip2 = 0;
+      }
+    }
+    if (!v_scrolled)
+    {
+      new_row_height = lm_calculate_row_height(lmp, row);
+      if (new_row_height != lmp->pix_heights[row])
+        lm_set_row_height(lm, row, new_row_height, FALSE, 0, FALSE);
+      if (LMP(lm)->attrib & XI_ATR_VISIBLE)
+        redraw_cell(lm, row, column, FALSE );
+    }
+    if (was_suspended)
+      lm_make_vis(lmp);
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   next cell
+lm:         current lm
+c:          character causing the focus to change
+next_row:   int pointer to be filled in with next row 
+next_col:   int pointer to be filled in with next column
+-------------------------------------------------------------------------*/
+static void
+next_cell(LM lm, int c, int *next_row, int *next_col)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  switch (c)
+  {
+  case K_BTAB:
+    --*next_col;
+    if (*next_col < 0)
+    {
+      *next_col = lmp->nbr_columns - 1;
+      if ((lmp->attrib & LM_ATR_TABWRAP))
+        --*next_row;
+    }
+    break;
+  case '\t':
+    ++*next_col;
+    if (*next_col >= lmp->nbr_columns)
+    {
+      *next_col = 0;
+      if ((lmp->attrib & LM_ATR_TABWRAP))
+        ++*next_row;
+    }
+    break;
+  case K_UP:
+    --*next_row;
+    break;
+  case K_DOWN:
+    ++*next_row;
+    break;
+  case K_WLEFT:
+  case K_LEFT:
+    --*next_col;
+    if (*next_col < 0)
+      *next_col = lmp->nbr_columns - 1;
+    break;
+  case K_WRIGHT:
+  case K_RIGHT:
+    ++*next_col;
+    if (*next_col >= lmp->nbr_columns)
+      *next_col = 0;
+    break;
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   do_lm_cb
+lm:         current lm
+cb_reason:  one of LM_CB_CHAR, LM_CB_CHANGE, LM_CB_FOCUS, LM_CB_REC_ALLOCATE,
+        LM_CB_REC_FREE
+row:        relevent row
+column:     relevent column
+ep:         xvt event that caused the LM event, used to pass on shift and control
+-------------------------------------------------------------------------*/
+BOOLEAN
+do_lm_cb(LM lm, LM_CB_TYPE cb_reason, int row, int column, EVENT *ep, int *percent, int pixels)
+{
+  LM_CB_DATA lm_cb_data;
+  LM_DATA *lmp = LMP(lm);
+
+  lm_cb_data.lm = lm;
+  lm_cb_data.cb_type = cb_reason;
+  lm_cb_data.cid = lmp->cid;
+  lm_cb_data.win = lmp->win;
+  lm_cb_data.row = (unsigned char)row;
+  lm_cb_data.column = (unsigned char)column;
+  switch (cb_reason)
+  {
+  case LM_CB_REC_ALLOCATE:
+    lm_cb_data.v.rec_allocate.record = lmp->recs[row];
+    if (lm_cb_data.v.rec_allocate.record)
+      return FALSE;
+    break;
+  case LM_CB_REC_FREE:
+    lm_cb_data.v.rec_free.record = lmp->recs[row];
+    if (! lm_cb_data.v.rec_allocate.record)
+      return FALSE;
+    break;
+  case LM_CB_CHAR:
+    lm_cb_data.v.chr.ch = ep->v.chr.ch;
+    lm_cb_data.v.chr.shift = ep->v.chr.shift;
+    lm_cb_data.v.chr.control = ep->v.chr.control;
+    lm_cb_data.v.chr.is_paste = FALSE;
+    lm_cb_data.v.chr.refused = FALSE;
+    break;
+  case LM_CB_CELL_BTN:
+    lm_cb_data.v.cell_btn.shift = ep->v.chr.shift;
+    lm_cb_data.v.cell_btn.control = ep->v.chr.control;
+    break;
+  case LM_CB_GET_PERCENT:
+    lm_cb_data.v.get_percent.record = lmp->recs[row];
+    break;
+  case LM_CB_ROW_SIZE:
+    lm_cb_data.v.row_size.new_row_height = pixels;
+    break;
+  default:
+    lm_cb_data.v.refused = FALSE;
+    break;
+  }
+  (*lmp->lm_cb)(&lm_cb_data);
+  /* retval = FALSE if event refused */
+  switch (cb_reason)
+  {
+  case LM_CB_REC_ALLOCATE:
+    lmp->recs[row] = lm_cb_data.v.rec_allocate.record;
+    return FALSE;
+  case LM_CB_REC_FREE:
+    lmp->recs[row] = 0L;
+    return FALSE;
+  case LM_CB_CHAR:
+    if (! lm_cb_data.v.chr.refused)
+      ep->v.chr.ch = lm_cb_data.v.chr.ch;
+    return (! lm_cb_data.v.chr.refused);
+  case LM_CB_GET_PERCENT:
+    *percent = lm_cb_data.v.get_percent.percent;
+    return FALSE;
+  case LM_CB_ROW_SIZE:
+    return (! lm_cb_data.v.row_size.refused);
+  default:
+    return (! lm_cb_data.v.refused);
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   do_lm_cb_get
+lm:         current lm
+cb_reason:  one of LM_CB_GET_FIRST, LM_CB_GET_LAST, LM_CB_GET_NEXT,
+        LM_CB_GET_PREV
+spec_rec:
+data_rec:
+percent:
+returns:    TRUE if event refused
+-------------------------------------------------------------------------*/
+BOOLEAN
+do_lm_cb_get(LM lm, LM_CB_TYPE cb_reason, long *spec_rec,
+long *data_rec, int percent, COLOR *color, unsigned long *attrib, int *row_height)
+{
+  LM_CB_DATA lm_cb_data;
+  LM_DATA *lmp = LMP(lm);
+
+  lm_cb_data.lm = lm;
+  lm_cb_data.cb_type = cb_reason;
+  lm_cb_data.cid = lmp->cid;
+  lm_cb_data.win = lmp->win;
+  lm_cb_data.v.rec_request.spec_rec = *spec_rec;
+  lm_cb_data.v.rec_request.data_rec = *data_rec;
+  lm_cb_data.v.rec_request.percent = percent;
+  lm_cb_data.v.rec_request.color = *color;
+  lm_cb_data.v.rec_request.attrib = *attrib;
+  lm_cb_data.v.rec_request.refused = FALSE;
+  (*lmp->lm_cb)(&lm_cb_data);
+  /* retval = FALSE if event refused */
+  if (! lm_cb_data.v.rec_request.refused)
+  {
+    *data_rec = lm_cb_data.v.rec_request.data_rec;
+    *color = lm_cb_data.v.rec_request.color;
+    *attrib = lm_cb_data.v.rec_request.attrib;
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    *row_height = lm_cb_data.v.rec_request.row_height;
+    CTOS_END;
+#endif
+#if XI_IS_CH
+    CTOS_IS_CH;
+    *row_height = 0;
+    CTOS_END;
+#endif
+    if ( lm_cb_data.v.rec_request.has_focus
+        && xi_get_pref(XI_PREF_UNUSED_PREFERENCE) )
+    {
+      if ( lmp->focus_rec )
+      {
+        lm_cb_data.lm = (LM)lmp;
+        lm_cb_data.cb_type = LM_CB_REC_FREE;
+        lm_cb_data.cid = lmp->cid;
+        lm_cb_data.win = lmp->win;
+        lm_cb_data.v.rec_free.record = lmp->focus_rec;
+        (*lmp->lm_cb)(&lm_cb_data);
+      }
+      lmp->focus_rec = *data_rec;
+    }
+  }
+  return lm_cb_data.v.rec_request.refused;
+}
+
+
+static void calculate_next_cell( LM_DATA *lmp, int *next_row, int *next_col,
+                                BOOLEAN *use_key, EVENT *ep, BOOLEAN *off_top,
+                                BOOLEAN *off_bottom)
+{
+  BOOLEAN keep_looking;
+  int     focus_row, focus_column;
+  BOOLEAN v_scrolled;
+
+  keep_looking = *use_key;
+  lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+  *next_row = focus_row;
+  *next_col = focus_column;
+  while (keep_looking)
+  {
+    next_cell((LM)lmp, ep->v.chr.ch, next_row, next_col);
+    if (*next_row < 0)
+    {
+      /* off top logic */
+      if (lmp->get_all_records)
+      {
+        *use_key = FALSE;
+        break;
+      }
+      else
+      {
+        keep_looking = FALSE;
+        *off_top = TRUE;
+      }
+    }
+    else
+      if (*next_row >= lmp->nbr_realized_rows)
+      {
+        /* off bottom logic */
+        if (lmp->get_all_records)
+        {
+          *use_key = FALSE;
+          break;
+        }
+        else
+        {
+          keep_looking = FALSE;
+          *off_bottom = TRUE;
+        }
+      }
+      else
+        if ( CELL_IS_ENABLED(lmp, *next_row, *next_col)
+            && !CELL_IS_SELECTABLE(lmp, *next_row, *next_col)
+            && lmp->cell_data[*next_row][*next_col].icon_rid
+            == 0 )
+        {
+          /* found a valid cell */
+          keep_looking = FALSE;
+        }
+  }
+}
+
+
+static void adjust_rows(LM_DATA *lmp, int delta)
+{
+  XI_OBJ *focus_obj;
+
+  focus_obj = lmp->itf_obj->v.itf->focus_obj;
+  if (focus_obj && focus_obj->cid == lmp->cid)
+  {
+    if (focus_obj && focus_obj->type == XIT_CELL)
+    {
+      focus_obj->v.cell.row += delta;
+      if ( !focus_obj->v.cell.is_vert_scrolled
+          && (long)focus_obj->v.cell.row >= (long)lmp->nbr_realized_rows )
+        focus_obj->v.cell.is_vert_scrolled = TRUE;
+    }
+    if (focus_obj && focus_obj->type == XIT_ROW)
+      focus_obj->v.row += delta;
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:   navigate_char_event
+lm:         current lm
+ep:         xvt event
+returns:    TRUE if key was used.
+-------------------------------------------------------------------------*/
+BOOLEAN
+navigate_char_event(LM lm, EVENT *ep)
+{
+  BOOLEAN use_key = FALSE;
+  BOOLEAN off_top = FALSE;
+  BOOLEAN off_bottom = FALSE;
+  BOOLEAN should_redraw = TRUE;
+  int next_row, next_col, row_inc, col_inc;
+  LM_DATA *lmp = LMP(lm);
+
+  if (!lm_list_has_focus(lmp))
+    return FALSE;
+  switch (ep->v.chr.ch) {
+    case '\t':
+    case K_BTAB:
+    case K_UP:
+    case K_DOWN:
+      use_key = TRUE;
+      break;
+    case K_WRIGHT:
+    case K_WLEFT:
+    case K_LEFT:
+    case K_RIGHT:
+      if ((lmp->attrib & LM_ATR_NAVIGATE) || ep->v.chr.control)
+        use_key = TRUE;
+      break;
+  }
+  calculate_next_cell(lmp, &next_row, &next_col,
+    &use_key, ep, &off_top, &off_bottom);
+  if (use_key)
+  {
+    XI_LIST_DATA *list_data;
+
+    list_data = lmp->list_obj->v.list;
+    if (off_top || off_bottom)
+    {
+      int old_row_height, focus_row, focus_column;
+      BOOLEAN v_scrolled;
+      BOOLEAN do_redraw;
+
+      lm_make_invis(lmp);
+      lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+      old_row_height = lmp->pix_heights[focus_row];
+      do_redraw = (lm_calculate_row_height(lmp, focus_row) != old_row_height);
+      if (off_top)
+        make_room_rows(lmp, -1, do_redraw);
+      else
+        make_room_rows(lmp, 1, do_redraw);
+      /*
+      calculate next cell again, because the desired next cell
+      may have changed.
+      */
+      calculate_next_cell( lmp, &next_row, &next_col, &use_key, ep, &off_top,
+                          &off_bottom);
+      lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+      row_inc = next_row - focus_row;
+      col_inc = next_col - focus_column;
+      next_row = focus_row + row_inc;
+      if (next_row >= lmp->nbr_realized_rows)
+        next_row = lmp->nbr_realized_rows - 1;
+      if (next_row < 0)
+        next_row = 0;
+      next_col = focus_column + col_inc;
+
+      while (TRUE)
+      {
+        if (CELL_IS_ENABLED(lm, next_row, next_col) &&
+            ! CELL_IS_SELECTABLE(lm, next_row, next_col))
+          break;
+        next_cell(lm, off_bottom ? '\t' :
+            K_BTAB, &next_row, &next_col);
+      }
+      if (list_data->vert_sync_list &&
+          ! list_data->scrolling_in_progress)
+      {
+        XI_OBJ *other_list;
+
+        list_data->scrolling_in_progress = TRUE;
+        other_list = xi_get_obj(lmp->itf_obj,
+            list_data->vert_sync_list);
+        if (other_list)
+          xi_scroll(other_list, off_top ? -1 : 1);
+        xvt_dwin_update(lmp->win);
+        list_data->scrolling_in_progress = FALSE;
+      }
+      xvt_dwin_update(lmp->win);
+      lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+      if (focus_row > lmp->last_fully_vis)
+      {
+        lm_force_vis(lmp);
+        lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+        next_row = focus_row;
+        calculate_pix_offsets( lmp, FALSE );
+      }
+      lm_make_vis(lmp);
+    }
+
+    else if (next_row < lmp->first_fully_vis || next_row > lmp->last_fully_vis)
+    {
+      if (list_data->vert_sync_list &&
+          ! list_data->scrolling_in_progress)
+      {
+        XI_OBJ *other_list;
+
+        list_data->scrolling_in_progress = TRUE;
+        other_list = xi_get_obj(lmp->itf_obj,
+            list_data->vert_sync_list);
+        if (other_list)
+          xi_scroll(other_list,
+              next_row < lmp->first_fully_vis ? -1 : 1);
+        xvt_dwin_update(lmp->win);
+        list_data->scrolling_in_progress = FALSE;
+      }
+    }
+
+    if (next_row < lmp->first_fully_vis)
+    {
+      int delta, idx2, pix2, old_pix, cnt, height;
+      RCT tmp_rct;
+
+      if (lmp->first_fully_vis == 0)
+        return use_key;
+      lm_make_invis(lmp);
+      idx2 = lmp->first_fully_vis - 1;
+      pix2 = lmp->pix_offsets[idx2];
+      old_pix = -lmp->rrr_offset;
+      delta = old_pix - pix2;
+      lmp->rrr_offset += delta;
+      calculate_pix_offsets(lmp, FALSE );
+      if (! lmp->itf_obj->v.itf->half_baked)
+        xvt_dwin_update(lmp->win);
+      xi_set_update_obj(lmp->list_obj);
+      lm_get_scroll_rct(lmp, &tmp_rct);
+
+      /*
+      calculate lmp->update_rows_at_top to speed up scrolling the list
+      */
+      height = delta;
+      for (cnt = 0; cnt < lmp->nbr_realized_rows && height > 0; ++cnt)
+        height -= lmp->pix_heights[cnt];
+      lmp->update_rows_at_top = cnt;
+
+      xi_scroll_rect(lmp->win, &tmp_rct, 0, delta);
+      do_scroll_bar(lmp->list_obj->v.list);
+      lm_make_vis(lmp);
+      should_redraw = FALSE;
+    }
+
+    if (next_row > lmp->last_fully_vis)
+    {
+      int delta, delta2, diff, cnt, height, first, old_row_height, focus_row;
+      int focus_column, new_row_height;
+      BOOLEAN v_scrolled;
+      RCT tmp_rct;
+
+      if (lmp->last_fully_vis >= lmp->nbr_realized_rows)
+        return use_key;
+      lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+      old_row_height = lmp->pix_heights[focus_row];
+      lm_make_invis(lmp);
+      delta = lmp->pix_heights[lmp->first_fully_vis];
+      lm_make_rrr_room_pix(lmp, delta, TRUE);
+      if (lmp->last_fully_vis + 1 < lmp->nbr_realized_rows)
+        delta = max(delta, lmp->pix_heights[lmp->last_fully_vis + 1]);
+      lmp->rrr_offset -= delta;
+      calculate_pix_offsets(lmp, TRUE);
+      calculate_visibles(lmp);
+      if (-lmp->rrr_offset != lmp->pix_offsets[lmp->first_fully_vis])
+      {
+        delta2 = lmp->pix_offsets[lmp->first_fully_vis] +
+            lmp->rrr_offset;
+        lmp->rrr_offset -= delta2;
+        calculate_pix_offsets(lmp, FALSE);
+        calculate_visibles(lmp);
+        delta += delta2;
+      }
+      diff = lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
+          lmp->pix_heights[lmp->nbr_realized_rows - 1] -
+          lmp->mlr_height + lmp->rrr_offset;
+      if (! lmp->itf_obj->v.itf->half_baked)
+        xvt_dwin_update(lmp->win);
+      if (diff < 0)
+        lm_make_rrr_room_pix(lmp, -diff, FALSE);
+      xi_set_update_obj(lmp->list_obj);
+      lm_get_scroll_rct(lmp, &tmp_rct);
+
+      /*
+      calculate lmp->update_rows_at_bottom to speed up scrolling the list
+      */
+      height = lmp->mlr.bottom - lmp->mlr.top - delta;
+      for (cnt = 0; cnt < lmp->nbr_realized_rows && height > 0; ++cnt)
+        height -= lmp->pix_heights[cnt];
+      first = cnt - 1;
+      height += delta;
+      for (;height > 0; ++cnt)
+        height -= lmp->pix_heights[cnt];
+      lmp->update_rows_at_bottom = cnt - first;
+
+      /*
+      scroll the list
+      */
+      xi_scroll_rect(lmp->win, &tmp_rct, 0, -delta);
+      do_scroll_bar(lmp->list_obj->v.list);
+
+      /*
+      if the row height changed, then we need to redraw the row
+      */
+      lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+      new_row_height = lmp->pix_heights[focus_row];
+      if (new_row_height != old_row_height)
+      {
+        lm_redraw_row(lmp, focus_row, FALSE );
+        calculate_pix_offsets(lmp, TRUE );
+      }
+      should_redraw = FALSE;
+    }
+
+    if (! lmp->get_all_records && ! lmp->keep_all_records)
+    {
+      int nbr_to_free, cnt, i, idx;
+
+      nbr_to_free = lmp->first_fully_vis;
+      if (nbr_to_free > 0)
+      {
+        for (cnt = 0; cnt < nbr_to_free; cnt++)
+        {
+          lmp->rrr_offset += lmp->pix_heights[cnt];
+          do_rec_event(lmp, cnt, XIE_REC_FREE);
+        }
+
+        for (idx = nbr_to_free; idx < lmp->nbr_realized_rows; ++idx)
+          row_copy(lmp, idx, idx - nbr_to_free);
+        adjust_rows(lmp, -nbr_to_free);
+
+        /*
+        calculate next cell again, because the desired next cell
+        may have changed.
+        */
+        calculate_next_cell(lmp, &next_row, &next_col,
+          &use_key, ep, &off_top, &off_bottom);
+        lmp->nbr_realized_rows -= cnt;
+        calculate_pix_offsets(lmp, should_redraw );
+        calculate_visibles(lmp);
+      }
+
+      /* free any unnecessary records at the end of the list */
+      nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
+      if (nbr_to_free > 0)
+      {
+        for (i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0; cnt < nbr_to_free;
+            i++, cnt++)
+          do_rec_event(lmp, i, XIE_REC_FREE);
+        lmp->nbr_realized_rows -= cnt;
+      }
+
+      calculate_pix_offsets(lmp, should_redraw );
+
+      lm_make_rrr_room_pix(lmp, 0, FALSE );
+    }
+    do_lm_cb(lm, LM_CB_FOCUS, next_row, next_col, NULL, NULL, 0);
+  }
+  return use_key;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_insert_row
+lm:         current lm
+row:        row to insert
+-------------------------------------------------------------------------*/
+BOOLEAN
+lm_insert_row(LM lm, int row)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  xvt_errmsg_sig_if(!(! lmp->get_all_records), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20919", 20919,
+    "xi_insert_row called with get_all_records set to TRUE");
+  if (xi_move_focus(lmp->itf_obj))
+  {
+  if (row > 0 && lmp->nbr_realized_rows)
+    {
+      int idx, row_height, pix;
+      RCT r, row_rect;
+      BOOLEAN is_visible;
+
+      row = min(row, lmp->nbr_realized_rows);
+
+      pix = lmp->pix_offsets[row - 1] + lmp->pix_heights[row - 1]
+            + 1;
+      is_visible = (pix <= lmp->mlr_height - lmp->rrr_offset);
+
+      if (is_visible || lmp->get_all_records)
+      {
+        LM_CELL_DATA *lmcdp;
+        int i;
+
+        make_rec_available(lmp, REC_AT_BOTTOM, FALSE, FALSE);
+        for (i = lmp->nbr_realized_rows - 2; i >= row; i--)
+          row_copy(lmp, i, i + 1);
+        idx = row;
+        lmcdp = lmp->cell_data[idx];
+        for (i = 0; i < lmp->nbr_columns; ++i, ++lmcdp)
+          memset((char *)lmcdp, '\0', sizeof(LM_CELL_DATA));
+        lmp->recs[idx] = 0L;
+        do_rec_event(lmp, idx, XIE_REC_ALLOCATE);
+        if (do_lm_cb_get((LM)lmp, LM_CB_GET_NEXT,
+            &lmp->recs[idx - 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
+            &lmp->row_attribs[idx], &row_height))
+        {
+          do_rec_event(lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE);
+          for (i = row; i < lmp->nbr_realized_rows - 2; ++i)
+            row_copy(lmp, i + 1, i);
+          --lmp->nbr_realized_rows;
+          return FALSE;
+        }
+        if (row_height)
+        {
+          lmp->pix_heights[idx] = row_height;
+          lmp->set_heights[idx] = TRUE;
+        }
+        else
+        {
+          lmp->pix_heights[idx] = lm_calculate_row_height(lmp, idx);
+          lmp->set_heights[idx] = FALSE;
+        }
+
+        lm_invalidate_rows_internal((LM)lmp, idx, idx, FALSE, -1, TRUE);
+      }
+
+      if (is_visible)
+      {
+        lm_get_scroll_rct(lmp, &r);
+        row_height = lm_calculate_row_height(lmp, idx);
+        calculate_pix_offsets(lmp, FALSE );
+        lm_get_rect(lm, LM_ROW, idx, &row_rect);
+        r.top = row_rect.top;
+        xi_scroll_rect(lmp->win, &r, 0, row_height);
+      }
+      do_scroll_bar(lmp->list_obj->v.list);
+      return TRUE;
+    }
+    else
+    {
+      int idx, row_height, cnt;
+      RCT r;
+      BOOLEAN need_first = ! lmp->nbr_realized_rows;
+
+      make_rec_available(lmp, REC_AT_TOP, TRUE, FALSE);
+      idx = 0;
+      if (do_lm_cb_get((LM)lmp, need_first ? LM_CB_GET_FIRST : LM_CB_GET_PREV,
+          &lmp->recs[idx + 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
+          &lmp->row_attribs[idx], &row_height))
+      {
+        do_rec_event(lmp, 0, XIE_REC_FREE);
+        for (cnt = 1; cnt < lmp->nbr_realized_rows; ++cnt)
+          row_copy(lmp, cnt, cnt - 1);
+        --lmp->nbr_realized_rows;
+        return FALSE;
+      }
+
+      if (row_height)
+      {
+        lmp->pix_heights[idx] = row_height;
+        lmp->set_heights[idx] = TRUE;
+      }
+      else
+      {
+        lmp->pix_heights[idx] = lm_calculate_row_height(lmp, idx);
+        lmp->set_heights[idx] = FALSE;
+      }
+      lm_invalidate_rows_internal((LM)lmp, idx, idx, FALSE, -1, TRUE );
+      lm_get_scroll_rct(lmp, &r);
+      row_height = lm_calculate_row_height(lmp, idx);
+      calculate_pix_offsets(lmp, FALSE );
+      xi_scroll_rect(lmp->win, &r, 0, row_height);
+      do_scroll_bar(lmp->list_obj->v.list);
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_delete_row
+lm:         current lm
+row:        row to delete
+-------------------------------------------------------------------------*/
+BOOLEAN
+lm_delete_row(LM lm, int row)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  xvt_errmsg_sig_if(!(! lmp->get_all_records), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20920", 20920,
+    "xi_delete_row called with get_all_records set to TRUE");   
+  if (xi_move_focus(lmp->itf_obj))
+  {
+    int pix_height, i;
+    int recs_read;
+    RCT r, row_rct;
+
+    pix_height = lmp->pix_heights[row];
+    lm_get_rect(lm, LM_ROW, row, &row_rct);
+    do_rec_event(lmp, row, XIE_REC_FREE);
+    for (i = row + 1; i < lmp->nbr_realized_rows; i++)
+      row_copy(lmp, i, i - 1);
+    lmp->recs[--lmp->nbr_realized_rows] = 0;
+    calculate_pix_offsets(lmp, FALSE );
+    recs_read = lm_make_rrr_room_pix(lmp, pix_height, FALSE);
+    pix_height = max(pix_height, 0);
+    lm_get_scroll_rct(lmp, &r);
+    r.top = max(r.top, row_rct.top);
+    if (recs_read)
+      xi_invalidate_rect( lmp->win, &r );
+    else
+      xi_scroll_rect(lmp->win, &r, 0, -pix_height);
+    do_scroll_bar(lmp->list_obj->v.list);
+  }
+  return TRUE;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_set_row_height
+lm:         current lm
+row:        row to set
+height:     height
+-------------------------------------------------------------------------*/
+void
+lm_set_row_height(LM lm, int row, int height, BOOLEAN set_height,
+    int old_height, BOOLEAN only_update)
+{
+  LM_DATA *lmp = (LM_DATA *)lm;
+  int idx = row;
+  int old_row_height, delta;
+  RCT r, r2;
+
+  if (! lmp->itf_obj->v.itf->half_baked)
+    xvt_dwin_update(lmp->win);
+  if (only_update)
+    old_row_height = old_height;
+  else
+  {
+    old_row_height = lmp->pix_heights[idx];
+    lmp->pix_heights[idx] = height;
+    lmp->set_heights[idx] = set_height;
+  }
+  calculate_pix_offsets(lmp, FALSE );
+
+  /* Adjust row information */
+  if (! lmp->get_all_records && ! lmp->keep_all_records)
+  {
+    if (height < old_row_height)
+      lm_make_rrr_room_pix(lmp, 0, FALSE);
+    else
+    {   /* Free rows at bottom */
+      int i, cnt;
+      int nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
+      for (i = lmp->nbr_realized_rows - nbr_to_free,
+          cnt = 0; cnt < nbr_to_free; i++, cnt++)
+        do_rec_event(lmp, i, XIE_REC_FREE);
+      if (nbr_to_free > 0)
+        lmp->nbr_realized_rows -= nbr_to_free;
+    }
+  }
+  lm_get_scroll_rct(lmp, &r);
+  if (row < lmp->nbr_realized_rows - 1)
+  {
+    r.top = lmp->pix_offsets[idx + 1] + lmp->rrr_offset + lmp->mlr.top;
+    delta = height - old_row_height;
+    xi_scroll_rect(lmp->win, &r, 0, delta);
+  }
+  lm_get_rect(lm, LM_ROW, row, &r);
+  if (row == lmp->nbr_realized_rows - 1)
+  {
+    r2 = r;
+    r2.top = r2.bottom;
+    r2.bottom = lmp->mlr.bottom;
+    if (r2.top < r2.bottom)
+      xi_invalidate_rect(lmp->win, &r2);
+  }
+  xi_invalidate_rect(lmp->win, &r);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_set_list_size
+lm:         current lm
+height:     new height
+width:      new width
+-------------------------------------------------------------------------*/
+void
+lm_set_list_size(LM lm, int height, int width)
+{
+  LM_DATA* lmp = (LM_DATA *)lm;
+  RCT      vert_scrollbar_rect;
+  RCT      horz_scrollbar_rect;
+  RCT      ir, old_rct;
+  int      old_height;
+  int      col_offset;
+  int      max_row_height;
+  int      row_height;
+  int      heading_height;
+  int      i;
+  XI_LIST_DATA* list_data;
+  int           nbr_to_free, cnt;
+
+  list_data = lmp->list_obj->v.list;
+  xi_get_rect(lmp->list_obj, &old_rct);
+  col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+  xi_get_hsb_rect(lmp->list_obj, &horz_scrollbar_rect);
+  xi_get_sb_rect(lmp->list_obj, &vert_scrollbar_rect);
+
+  /* calculate minumum height */
+  {
+    int leading;
+    int ascent;
+    int descent;
+    int char_width;
+    int font_height;
+
+    xi_get_font_metrics_font(lmp->font, &leading, &ascent, &descent,
+                            &char_width);
+    font_height = leading + ascent + descent;
+    max_row_height = lmp->max_lines_in_cell * font_height + RULE_Y_OFFSET_TOP
+                    + RULE_Y_OFFSET_BOTTOM + RULE_WIDTH_H;
+  }
+  for (i = 0; i < lmp->nbr_realized_rows; ++i)
+  {
+    row_height = lmp->pix_heights[i];
+    max_row_height = max(row_height, max_row_height);
+  }
+  heading_height = (lmp->pix_row1_top - lmp->rct.top) + BORDER_WIDTH;
+  i = max_row_height + heading_height + (horz_scrollbar_rect.bottom
+      - horz_scrollbar_rect.top);
+  height = max(height, i);
+
+  /* calculate new list metrics */
+  lmp->rct.bottom = lmp->rct.top + height
+                    - ((list_data->hsb_win) ? (horz_scrollbar_rect.bottom
+                                              - horz_scrollbar_rect.top - 1)
+                                              : 0);
+#if XI_IS_CH
+  CTOS_IS_CH;
+  lmp->mlr.bottom = lmp->rct.bottom;
+  CTOS_END;
+#else
+  CTOS_IS_PM;
+  lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
+  CTOS_END;
+#endif
+  old_height = lmp->mlr_height;
+  lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
+  calculate_pix_offsets( lmp, FALSE );
+  if (! lmp->get_all_records)
+  {
+    /* fill in with more records */
+    if (old_height < lmp->mlr_height)
+      lm_make_rrr_room_pix(lmp, lmp->mlr_height - old_height, FALSE);
+  }
+
+  calculate_visibles(lmp);
+
+  if (width && lmp->pixel_width)
+  {
+    int i, min_width, max_col_width;
+
+    max_col_width = 0;
+    for (i = lmp->fixed_columns; i < lmp->nbr_columns; ++i)
+      max_col_width = max(lmp->lm_column_data[i]->pix_width, max_col_width);
+    max_col_width += BORDER_WIDTH;
+    min_width = (lmp->vir_left - lmp->rct.left) + max_col_width
+                + (vert_scrollbar_rect.right - vert_scrollbar_rect.left)
+                + BORDER_WIDTH + 2 * col_offset;
+    if ( list_data->sb_win )
+      min_width += ( vert_scrollbar_rect.right
+                    - vert_scrollbar_rect.left );
+    width = max(min_width, width);
+
+    lmp->pixel_width = width - (2 * BORDER_WIDTH);
+    if ( list_data->sb_win )
+      lmp->pixel_width -= ( vert_scrollbar_rect.right
+                            - vert_scrollbar_rect.left - 1 );
+    lmp->vir_right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
+  }
+
+  /* move scroll bars */
+  list_data->have_sb_rct = FALSE;
+  list_data->have_hsb_rct = FALSE;
+  xi_move_list_scroll_bar(lmp->list_obj);
+  xi_move_list_hscroll_bar(lmp->list_obj);
+  lm_set_hscroll_range(lm);
+
+  ir = lmp->rct;
+  xi_get_hsb_rect(lmp->list_obj, &horz_scrollbar_rect);
+  ir.bottom = horz_scrollbar_rect.bottom + BORDER_WIDTH;
+  xi_get_sb_rect(lmp->list_obj, &vert_scrollbar_rect);
+  ir.right = vert_scrollbar_rect.right + BORDER_WIDTH;
+  ir.right = max(ir.right, old_rct.right);
+  ir.bottom = max(ir.bottom, old_rct.bottom);
+  xi_invalidate_rect(lmp->win, &ir);
+
+  do_scroll_bar(lmp->list_obj->v.list);
+
+  if (width && lmp->pixel_width)
+  {
+    /* calculate visible columns */
+    i = lm_get_left_most_far_right_col(lmp, lmp->nbr_columns);
+    if (i < lmp->first_vis)
+    {
+      xvt_dwin_update(lmp->win);
+      lm_hscroll(lm, lmp->first_vis - i, 0);
+    } else
+    {
+      lm_calc_last_vis(lmp);
+      lm_set_hscroll_bar((LM)lmp);
+    }
+  }
+
+  if (! lmp->get_all_records)
+  {
+    /* free any unnecessary records at the end of the list */
+    nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
+    for (i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0; cnt < nbr_to_free;
+        i++, cnt++)
+      do_rec_event(lmp, i, XIE_REC_FREE);
+    lmp->nbr_realized_rows -= cnt;
+    calculate_visibles(lmp);
+  }
+}
+
+void
+lm_recalc_metrics(LM lm)
+{
+  LM_DATA *lmp = (LM_DATA *)lm;
+  int leading, ascent, descent, font_height, mch, i;
+  WINDOW win;
+  LM_COLUMN_DATA * * lmcdp;
+  int old_char_width;
+  XI_LIST_DATA *list_data;
+  PNT pnt;
+  RCT rct;
+
+  list_data = lmp->list_obj->v.list;
+  pnt = list_data->xi_pnt;
+  xi_fu_to_pu(lmp->itf_obj, &pnt, 1);
+  lmp->rct.top = pnt.v;
+  lmp->rct.left = pnt.h;
+
+  if (! lmp->resize_with_window)
+  {
+    lmp->pixel_width = list_data->width *
+        xi_get_fu_width(lmp->itf_obj) / XI_FU_MULTIPLE;
+  }
+
+  *lmp->font = *lmp->itf_obj->v.itf->font;
+  win = lmp->win;
+  xi_set_xvt_font(win, lmp->font, FALSE);
+  xi_get_font_metrics(win, &leading, &ascent, &descent);
+  lmp->leading = leading;
+  lmp->ascent = ascent;
+  lmp->descent = descent;
+  font_height = lmp->ascent + lmp->leading + lmp->descent;
+  lmp->pix_cell_height = font_height + (RULE_Y_OFFSET_TOP +
+      RULE_Y_OFFSET_BOTTOM);
+#if XI_IS_CH
+  CTOS_IS_CH;
+  mch = 8;
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  mch = lmp->min_cell_height;
+  CTOS_END;
+#endif
+  lmp->pix_cell_height = max(lmp->pix_cell_height, mch);
+  lmp->pix_row_spacing = lmp->pix_cell_height + RULE_WIDTH_H;
+  lmp->pix_top = lmp->rct.top;
+  lmp->pix_hdr_bottom = lmp->rct.top + lmp->leading + lmp->ascent +
+      lmp->descent + BORDER_WIDTH +
+      RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
+  lmp->pix_hdr_bottom = max(lmp->pix_hdr_bottom,
+      (lmp->rct.top + lmp->min_heading_height + 2 * BORDER_WIDTH));
+  if (lmp->no_heading)
+    lmp->pix_row1_top = lmp->rct.top + BORDER_WIDTH;
+  else
+    lmp->pix_row1_top = lmp->pix_hdr_bottom + BORDER_WIDTH;
+
+  old_char_width = lmp->pix_char_width;
+  lmp->pix_char_width = xi_get_fu_width(lmp->itf_obj);
+  calculate_pix_offsets(lmp, FALSE);
+
+  for (i = 0, lmcdp = lmp->lm_column_data; i < lmp->nbr_columns; ++i, ++lmcdp)
+    (*lmcdp)->pix_width = (*lmcdp)->pix_width * lmp->pix_char_width /
+        old_char_width;
+
+  for (i = 0; i < lmp->nbr_columns; ++i)
+    calc_x_pix_pos(lm, lmp->lm_column_data[i], i);
+
+  lmp->rct.right = lmp->rct.left +
+      lmp->lm_column_data[lmp->nbr_columns - 1]->x_pix_pos +
+      lmp->lm_column_data[lmp->nbr_columns - 1]->pix_width +
+      2 * BORDER_WIDTH;
+
+  if (! lmp->resize_with_window)
+  {
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing +
+        (BORDER_WIDTH - RULE_WIDTH_H);
+    CTOS_END;
+#endif
+#if XI_IS_CH
+    CTOS_IS_CH;
+    lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing
+        + BORDER_WIDTH;
+    CTOS_END;
+#endif
+  }
+
+  if (lmp->fixed_columns >= lmp->nbr_columns)
+    lmp->delta_x = 0;
+  else
+    lmp->delta_x = lmp->lm_column_data[lmp->first_vis]->x_pix_pos -
+        lmp->lm_column_data[lmp->fixed_columns]->x_pix_pos;
+
+  lmp->mlr.top = lmp->pix_row1_top;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  if (lmp->pixel_width)
+    lmp->mlr.bottom = lmp->rct.bottom;
+  else
+    lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
+  CTOS_END;
+#endif
+  lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
+
+  if (lmp->rrr_bottom < lmp->mlr_height)
+    lm_make_rrr_room_pix(lmp, lmp->mlr_height - lmp->rrr_bottom, FALSE);
+
+  list_data->have_sb_rct = FALSE;
+  list_data->have_hsb_rct = FALSE;
+
+  xi_get_sb_rect(lmp->list_obj, &rct);
+  xvt_vobj_move(list_data->sb_win, &rct);
+
+  xi_get_hsb_rect(lmp->list_obj, &rct);
+  xvt_vobj_move(list_data->hsb_win, &rct);
+
+  lm_calc_last_vis(lmp);
+}
+
+void
+lm_text_scrolling(XI_OBJ *xi_obj)
+{
+  LM_DATA *lmp = (LM_DATA *)xi_obj->v.list->lm;
+
+  lmp->text_scrolling = TRUE;
+}
+
+void
+lm_set_hscroll_range(LM lm)
+{
+  LM_DATA *lmp = (LM_DATA *)lm;
+  int hscroll_width, fixed_width, cnt;
+  RCT mlr;
+  XI_LIST_DATA *listdata;
+
+  if (lmp->list_obj->nbr_children <= 0) return;
+
+  listdata = lmp->list_obj->v.list;
+  lm_get_scroll_rct(lmp, &mlr);
+  if (lmp->pixel_width)
+  {
+    int prop;
+
+    hscroll_width = 0;
+    fixed_width = 0;
+    for (cnt = lmp->fixed_columns; cnt < lmp->nbr_columns; ++cnt)
+      hscroll_width += lmp->lm_column_data[cnt]->pix_width + lm_get_col_spacing();
+    for (cnt = 0; cnt < lmp->fixed_columns; ++cnt)
+      fixed_width += lmp->lm_column_data[cnt]->pix_width + lm_get_col_spacing();
+#if XIWS == MTFWS
+    if ( hscroll_width != 0 )
+    {
+#endif
+    xvt_sbar_set_range(listdata->hsb_win, HVSCROLL, 0, hscroll_width);
+    prop = mlr.right - mlr.left - fixed_width - BORDER_WIDTH;
+    prop = min(prop, hscroll_width);
+    prop = max(prop, 0);
+    xvt_sbar_set_proportion(listdata->hsb_win, HVSCROLL, prop);
+#if XIWS == MTFWS
+    }
+#endif
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_column_set_pixel_width
+lm:         current lm
+idx:        column number
+width:      in pixels
+-------------------------------------------------------------------------*/
+void lm_column_set_pixel_width(LM lm, int idx, int width)
+{
+  LM_DATA *lmp = (LM_DATA *) lm;
+  LM_COLUMN_DATA * column;
+  RCT invalid_rct, old_rct;
+  int i, old_width, new_row_height, cnt;
+
+  old_rct = lmp->rct;
+  column = lmp->lm_column_data[idx];
+  old_width = column->pix_width;
+  column->width = width / lmp->pix_char_width;
+  column->pix_width = width;
+  for (i = idx + 1; i < lmp->nbr_columns; ++i)
+    calc_x_pix_pos(lm, lmp->lm_column_data[i], i);
+
+  /* adjust bounding rectangle */
+  lmp->rct.right += column->pix_width - old_width;
+  lmp->mlr.right += column->pix_width - old_width;
+  if (idx < lmp->fixed_columns)
+    lmp->vir_left += column->pix_width - old_width;
+  /* The x_pix_pos of the first visible column may have changed so
+    recalculate delta_x */
+  if (lmp->fixed_columns >= lmp->nbr_columns)
+    lmp->delta_x = 0;
+  else
+    lmp->delta_x = lmp->lm_column_data[lmp->first_vis]->x_pix_pos -
+        lmp->lm_column_data[lmp->fixed_columns]->x_pix_pos;
+
+  invalid_rct = lmp->rct;
+  invalid_rct.left = column->x_pix_pos;
+  invalid_rct.right = max(invalid_rct.right, old_rct.right);
+  if (lmp->pixel_width)
+    invalid_rct.right = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
+  lmp->list_obj->v.list->have_sb_rct = FALSE;
+  lmp->list_obj->v.list->have_hsb_rct = FALSE;
+  lm_set_hscroll_range((LM)lmp);
+  lm_calc_last_vis(lmp);
+
+  if (column->wrap_text)
+  {
+    int first_fully_vis = lmp->first_fully_vis;
+    int last_row = lmp->nbr_realized_rows - 1;
+    int height;
+
+    for (cnt = 0; cnt < lmp->nbr_realized_rows; ++cnt)
+    {
+      int old_row_height;
+
+      old_row_height = lmp->pix_heights[cnt];
+      new_row_height = lm_calculate_row_height(lmp, cnt);
+      lmp->pix_heights[cnt] = new_row_height;
+      if (old_row_height != new_row_height)
+        invalid_rct.left = lmp->rct.left;
+    }
+    calculate_pix_offsets(lmp, FALSE);
+    height = lmp->pix_offsets[last_row] + lmp->pix_heights[last_row] -
+            lmp->pix_offsets[first_fully_vis];
+    if (height < lmp->mlr_height)
+      lm_make_rrr_room_pix(lmp, lmp->mlr_height - height, FALSE);
+    if (! lmp->get_all_records)
+    {
+      int nbr_to_free;
+
+      /* free any unnecessary records at the end of the list */
+      nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
+      for (i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
+          cnt < nbr_to_free;
+          i++, cnt++)
+        do_rec_event(lmp, i, XIE_REC_FREE);
+      lmp->nbr_realized_rows -= cnt;
+      calculate_visibles(lmp);
+    }
+  }
+  lm_invalidate_rect2(lmp, &invalid_rct, TRUE);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_set_column_width
+lm:         current lm
+idx:        column number
+width:      in characters
+-------------------------------------------------------------------------*/
+void lm_set_column_width(LM lm, int idx, int width)
+{
+  lm_column_set_pixel_width( lm, idx,
+      width * ((LM_DATA *)lm)->pix_char_width );
+}
+
+/* ------------------------------------------------------------------- */
+/* lm_cell_is_visible                                                  */
+/* ------------------------------------------------------------------- */
+
+BOOLEAN
+lm_is_cell_visible( LM_DATA *lmp, int row, int column,
+                            BOOLEAN use_txt_is_visible,
+                            BOOLEAN *is_hscrolled)
+{
+  if (is_hscrolled)
+    *is_hscrolled = FALSE;
+  if (use_txt_is_visible && lmp->txt_is_invisible)
+  {
+    int r;
+
+    if (lmp->focus_rec == 0L)
+    {
+      if (column < lmp->fixed_columns || (column >= lmp->first_vis && column <= lmp->last_vis))
+        return TRUE;
+      *is_hscrolled = TRUE;
+      return FALSE;
+    }
+    for (r = 0; r < lmp->nbr_realized_rows; ++r)
+    {
+      if (lmp->recs[r] == lmp->focus_rec)
+      {
+        if (r >= lmp->first_fully_vis && r <= lmp->last_fully_vis)
+        {
+          if (column < lmp->fixed_columns || (column >= lmp->first_vis && column <= lmp->last_vis))
+          {
+            return TRUE;
+          }
+          else
+          {
+            if (is_hscrolled)
+              *is_hscrolled = TRUE;
+            return FALSE;
+          }
+        }
+        else
+          return FALSE;
+      }
+    }
+    return FALSE;
+  }
+  else
+  {
+    if (row >= lmp->first_fully_vis && row <= lmp->last_fully_vis + 1)
+    {
+      if (column < lmp->fixed_columns || (column >= lmp->first_vis && column <= lmp->last_vis))
+      {
+        return TRUE;
+      }
+      else
+      {
+        if (is_hscrolled)
+          *is_hscrolled = TRUE;
+        return FALSE;
+      }
+    }
+    else
+      return FALSE;
+  }
+}
+
+void lm_force_vis(LM_DATA *lmp)
+{
+  LM_COLUMN_DATA* lmcdp;
+  unsigned long   attrib, cell_attrib;
+  int             c;
+  RCT             mr;
+  int             focus_row, focus_column;
+  BOOLEAN         v_scrolled;
+
+  mr = lmp->mlr;
+  if (lmp->pixel_width)
+    mr.right = mr.left + lmp->pixel_width + BORDER_WIDTH;
+  lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
+  lmcdp = lmp->lm_column_data[focus_column];
+  attrib = lmcdp->attrib;
+
+  cell_attrib = lm_get_attrib( (LM) lmp, LM_CELL, focus_row, focus_column,
+                              v_scrolled ) & (XI_ATR_HCENTER | XI_ATR_RJUST);
+  if (cell_attrib)
+  {
+    attrib &= ~(XI_ATR_HCENTER | XI_ATR_RJUST);
+    attrib |= cell_attrib;
+  }
+
+  /* force cell to be visible */
+  c = min(focus_column, lmp->nbr_columns - 1);
+  if (c >= lmp->fixed_columns && c < lmp->first_vis)
+    lm_local_hscroll((LM)lmp, c - lmp->first_vis);
+  else
+  {
+    if (c > lmp->last_vis)
+    {
+      int first_col;
+
+      c++;
+      c = min(c, lmp->nbr_columns);
+      first_col = lm_get_left_most_far_right_col(lmp, c);
+      lm_local_hscroll((LM)lmp, first_col - lmp->first_vis);
+    }
+  }
+  if (focus_row < lmp->first_fully_vis)
+  {
+    int delta, idx2, pix2, old_pix;
+    RCT tmp_rct;
+
+    make_room_rows(lmp, focus_row - lmp->first_fully_vis, FALSE);
+    idx2 = focus_row;
+    pix2 = lmp->pix_offsets[idx2];
+    old_pix = -lmp->rrr_offset;
+    delta = old_pix - pix2;
+    lmp->rrr_offset += delta;
+    calculate_pix_offsets(lmp, FALSE);
+    if (! lmp->itf_obj->v.itf->half_baked)
+      xvt_dwin_update(lmp->win);
+    xi_set_update_obj(lmp->list_obj);
+    lm_get_scroll_rct(lmp, &tmp_rct);
+    xi_scroll_rect(lmp->win, &tmp_rct, 0, delta);
+    do_scroll_bar(lmp->list_obj->v.list);
+  }
+  if (focus_row > lmp->last_fully_vis)
+  {
+    int pix, delta;
+    RCT tmp_rct;
+
+    delta = 0;
+    while (TRUE)
+    {
+      if (focus_row <= lmp->last_fully_vis)
+        break;
+      pix = lmp->pix_heights[0];
+      delta += pix;
+      lm_make_rrr_room_pix(lmp, pix, FALSE);
+      lmp->rrr_offset -= pix;
+      calculate_pix_offsets(lmp, FALSE);
+      calculate_visibles(lmp);
+    }
+    if (! lmp->itf_obj->v.itf->half_baked)
+      xvt_dwin_update(lmp->win);
+    xi_set_update_obj(lmp->list_obj);
+    lm_get_scroll_rct(lmp, &tmp_rct);
+    xi_scroll_rect(lmp->win, &tmp_rct, 0, -delta);
+    do_scroll_bar(lmp->list_obj->v.list);
+
+    if (! lmp->get_all_records && ! lmp->keep_all_records)
+    {
+      int nbr_to_free, cnt, i, idx;
+
+      nbr_to_free = lmp->first_fully_vis;
+      if (nbr_to_free > 0)
+      {
+        for (cnt = 0; cnt < nbr_to_free; cnt++)
+        {
+          lmp->rrr_offset += lmp->pix_heights[cnt];
+          do_rec_event(lmp, cnt, XIE_REC_FREE);
+        }
+
+        for (idx = nbr_to_free; idx < lmp->nbr_realized_rows; ++idx)
+          row_copy(lmp, idx, idx - nbr_to_free);
+        adjust_rows(lmp, -nbr_to_free);
+
+        lmp->nbr_realized_rows -= cnt;
+      }
+
+      /* free any unnecessary records at the end of the list */
+      nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
+      if (nbr_to_free > 0)
+      {
+        for (i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0; cnt < nbr_to_free;
+            i++, cnt++)
+          do_rec_event(lmp, i, XIE_REC_FREE);
+        lmp->nbr_realized_rows -= cnt;
+      }
+
+      calculate_pix_offsets(lmp, TRUE );
+    }
+  }
+  lm_make_vis(lmp);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_get_visible_columns
+lm:         current lm
+first_vis:
+last_vis:
+-------------------------------------------------------------------------*/
+void
+lm_get_visible_columns(LM lm, int *first_vis, int *last_vis)
+{
+  LM_DATA *lmp = (LM_DATA *)lm;
+
+  *first_vis = lmp->first_vis;
+  *last_vis = lmp->last_vis;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_get_list_info
+lm:         current lm
+nbr_recs:   number of records
+returns:    array of record handles
+-------------------------------------------------------------------------*/
+long *
+lm_get_list_info(LM lm, int *nbr_recs)
+{
+  LM_DATA *lmp = (LM_DATA *)lm;
+
+  *nbr_recs = lmp->nbr_realized_rows;
+  return &lmp->recs[0];
+
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_cell_request
+lm:         current lm
+lm_part:    may be LM_LIST, LM_ROW, LM_COLUMN, or LM_CELL ??
+-------------------------------------------------------------------------*/
+void
+lm_cell_request( LM lm, LM_PART lm_part, int idx1, int idx2 )
+{
+  LM_DATA *lmp = LMP(lm);
+  BOOLEAN redraw;
+
+  redraw = (BOOLEAN)(lmp->attrib & (LM_ATR_VISIBLE));
+  lm_make_invis(lmp);
+  switch (lm_part)
+  {
+  case LM_LIST:
+    lm_invalidate_rows_internal( lm, 0, lmp->nbr_realized_rows - 1, redraw, -1,
+                                FALSE );
+    lm_make_vis(lmp);
+    return;
+  case LM_ROW:
+    lm_invalidate_rows_internal(lm, idx1, idx1, redraw, -1, FALSE);
+    lm_make_vis(lmp);
+    return;
+  case LM_COLUMN:
+    lm_invalidate_rows_internal(lm, 0, lmp->nbr_realized_rows - 1, redraw, idx1,
+                                FALSE );
+    lm_make_vis(lmp);
+    return;
+  case LM_CELL:
+    lm_invalidate_rows_internal(lm, idx1, idx1, redraw, idx2, FALSE);
+    lm_make_vis(lmp);
+    return;
+  }
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20918", 20918, "lm_cell_request: Invalid LM part");
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_get_visible_rows
+  ------------------------------------------------------------------------- */
+int
+lm_get_visible_rows(LM lm, int *first_vis, int *last_vis)
+{
+  LM_DATA *lmp = (LM_DATA *)lm;
+
+  if (first_vis)
+    *first_vis = lmp->first_fully_vis;
+  if (last_vis)
+    *last_vis = lmp->last_fully_vis;
+  if (! lmp->nbr_realized_rows)
+    return 0;
+  else
+    return lmp->last_fully_vis - lmp->first_fully_vis + 1;
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_get_list_obj
+lm:         current lm
+returns:    XI_OBJ * for list
+-------------------------------------------------------------------------*/
+XI_OBJ *
+lm_get_list_obj(LM lm)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  return(lmp->list_obj);
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_set_buf_size_internal
+lm:         current lm
+part:       must be LM_COLUMN
+idx:        column number
+size:       the new buffer size
+redraw:     if TRUE, then redraw the cell
+-------------------------------------------------------------------------*/
+static void near
+lm_set_buf_size_internal(LM lm, LM_PART part, int idx, int size, BOOLEAN redraw)
+{
+  int i, toff;
+  int oldlen, diff;
+  int oldbufsize;
+  char *p;
+  LM_COLUMN_DATA *lmcd, *lmcdm1;
+  LM_DATA *lmp = LMP(lm);
+
+  xvt_errmsg_sig_if(!(part == LM_COLUMN), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4,"20917",
+    20917, "lm_set_buf_size: Invalid LM part");
+  lmcd = lmp->lm_column_data[idx];
+  oldlen = lmcd->text_size;
+  oldbufsize = lmp->text_size;
+  lmcd->text_size = size;
+  diff = size - oldlen;
+  lmp->text_size += diff;
+  toff = lmcd->text_offset;
+
+  for (i = 0; i < lmp->realized_rows_array_len; i++)
+  {
+    p = lmp->buffer[i];
+    if (diff < 0) {
+      p[toff + size - 1] = '\0';
+      gmemmove(p + toff + size, p + toff + oldlen,
+          (long)(oldbufsize - toff - oldlen));
+      lmp->buffer[i] = (char *)xi_tree_realloc(p, oldbufsize + diff);
+      /* redraw cause might obliterate some text */
+      if (redraw)
+        redraw_cell(lm, i, idx, FALSE );
+    }
+    else
+    {
+      p = lmp->buffer[i] = (char *)xi_tree_realloc(p, oldbufsize + diff);
+      gmemmove(p + toff + size, p + toff + oldlen,
+          (long)(oldbufsize - toff - oldlen));
+    }
+  }
+  for (i = 0; i < lmp->nbr_columns; ++i)
+  {
+    lmcd = lmp->lm_column_data[i];
+    if (i)
+      lmcdm1 = lmp->lm_column_data[i - 1];
+    lmcd->text_offset = (i == 0) ? 0 :
+        lmcdm1->text_offset + lmcdm1->text_size;
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_set_buf_size
+lm:         current lm
+part:       must be LM_COLUMN
+idx:        column number
+size:       the new buffer size
+-------------------------------------------------------------------------*/
+void
+lm_set_buf_size(LM lm, LM_PART part, int idx, int size)
+{
+  lm_set_buf_size_internal(lm, part, idx, size, TRUE);
+}
+
+/* ------------------------------------------------------------------------ */
+/* adjust_focus_for_column_delete                                           */
+/* if the focus is on a column after the deleted column, adjust the focus   */
+/* objects.                                                                 */
+/* if the focus is on the deleted column, move the focus to the interface   */
+/* ------------------------------------------------------------------------ */
+
+static void adjust_focus_for_column_delete( LM_DATA* lmp, int column_nbr )
+{
+  XI_OBJ* focus_obj;
+
+  focus_obj = lmp->itf_obj->v.itf->focus_obj;
+  if (focus_obj == NULL || focus_obj->parent != lmp->list_obj
+      || focus_obj->type != XIT_CELL)
+    return;
+  if ( focus_obj->v.cell.column == column_nbr )
+  {
+    xi_set_focus( lmp->itf_obj );
+    return;
+  }
+  if ( (int)focus_obj->v.cell.column > (int)column_nbr )
+  focus_obj->v.cell.column--;
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_delete_column
+lm:         current lm
+column_nbr: column to delete
+adjust_hscrolling: if TRUE, then make more horizontal columns visible
+-------------------------------------------------------------------------*/
+void
+lm_delete_column(LM lm, int column_nbr, BOOLEAN adjust_hscrolling)
+{
+  LM_DATA *lmp = LMP(lm);
+  LM_COLUMN_DATA *lmcd;
+  RCT invalid_rct, old_rct;
+  int i, old_width, old_left, col_spacing;
+  int old_x_pix_pos;
+  LM_CELL_DATA *cell_data;
+
+  adjust_focus_for_column_delete( lmp, column_nbr );
+  col_spacing = lm_get_col_spacing();
+  xvt_errmsg_sig_if(!(column_nbr < lmp->nbr_columns), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20915", 20915,
+    "Invalid column number passed to lm_delete_column");
+  old_rct = lmp->rct;
+  lmcd = lmp->lm_column_data[column_nbr];
+  old_left = lmcd->x_pix_pos - lmp->delta_x;
+  old_x_pix_pos = lmcd->x_pix_pos;
+  old_width = lmcd->pix_width;
+  lm_set_buf_size_internal(lm, LM_COLUMN, column_nbr, 0, FALSE);
+  xi_tree_free(lmp->lm_column_data[column_nbr]);
+
+  for (i = 0; i < lmp->nbr_realized_rows; ++i)
+  {
+  cell_data = &(lmp->cell_data[i][column_nbr]);
+  if (cell_data->font)
+  {
+    xi_free_font_id(lmp->itf_obj, *cell_data->font);
+    xi_tree_free(cell_data->font);
+  }
+  if (cell_data->string)
+    xi_tree_free(cell_data->string);
+  if (cell_data->line_breaks)
+    xi_tree_free(cell_data->line_breaks);
+  }
+
+  for (i = 0; i < lmp->realized_rows_array_len; ++i)
+  {
+  int j;
+
+  for (j = column_nbr; j < lmp->nbr_columns - 1; ++j)
+    lmp->cell_data[i][j] = lmp->cell_data[i][j + 1];
+  lmp->cell_data[i] = (LM_CELL_DATA *)xi_tree_realloc(lmp->cell_data[i],
+      (lmp->nbr_columns - 1) * sizeof(LM_CELL_DATA));
+  }
+
+  for (i = column_nbr; i < lmp->nbr_columns - 1; ++i)
+  lmp->lm_column_data[i] = lmp->lm_column_data[i + 1];
+  --lmp->nbr_columns;
+
+  for (i = column_nbr; i < lmp->nbr_columns; ++i)
+  calc_x_pix_pos(lm, lmp->lm_column_data[i], i);
+
+  /*
+  adjust bounding rectangle
+  */
+  lmp->rct.right = lmp->rct.right - old_width - lm_get_col_spacing();
+  /* single-column lists do not have a vertical rule seperating columns */
+  if (lmp->nbr_columns == 0)
+  lmp->rct.right += RULE_WIDTH_V;
+
+  /* adjust left border of horizontal virtual space */
+  if (column_nbr < lmp->fixed_columns)
+  lmp->vir_left -= (old_width + col_spacing);
+
+
+  /*
+  if the column is invisible
+  */
+  calculate_pix_offsets( lmp, TRUE );
+  if (column_nbr >= lmp->fixed_columns && old_x_pix_pos < lmp->delta_x)
+  {
+  lmp->delta_x -= (old_width + lm_get_col_spacing());
+  --lmp->first_vis;
+  lm_set_hscroll_range((LM)lmp);
+  }
+  else
+  {
+  if (column_nbr < lmp->fixed_columns)
+  {
+    --lmp->first_vis;
+    --lmp->fixed_columns;
+    lm_set_hscroll_range((LM)lmp);
+  }
+
+  invalid_rct = lmp->rct;
+  invalid_rct.left = old_left;
+  invalid_rct.right = max(invalid_rct.right, old_rct.right);
+    if (lmp->pixel_width)
+      invalid_rct.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
+
+    /*
+    if we add the following two lines in, it prevents flashing of the top and bottom borders when
+    moving columns, however, the top and bottom borders need to get invalidated
+    invalid_rct.top += BORDER_WIDTH;
+    invalid_rct.bottom -= BORDER_WIDTH;
+    */
+
+    lm_invalidate_rect2(lmp, &invalid_rct, FALSE);
+    lmp->list_obj->v.list->have_sb_rct = FALSE;
+    lmp->list_obj->v.list->have_hsb_rct = FALSE;
+
+    i = lm_get_left_most_far_right_col(lmp, lmp->nbr_columns);
+    if (lmp->first_vis >= lmp->nbr_columns)
+    {
+      RCT r;
+
+      xvt_dwin_update(lmp->win);
+      lmp->delta_x = lmp->lm_column_data[i]->x_pix_pos - lmp->vir_left;
+      xi_set_update_obj(lmp->list_obj);
+      lmp->last_vis = lmp->first_vis = i;
+      lm_calc_last_vis(lmp);
+      r.left = lmp->vir_left;
+      r.right = lmp->vir_right;
+#if XI_IS_NOT_CH
+      CTOS_IS_PM;
+      r.top = lmp->rct.top + BORDER_WIDTH;
+      r.bottom = lmp->rct.bottom - BORDER_WIDTH;
+      CTOS_END;
+#endif
+#if XI_IS_CH
+      CTOS_IS_CH;
+      r.top = lmp->rct.top;
+      r.bottom = lmp->rct.bottom;
+      CTOS_END;
+#endif
+      xi_invalidate_rect(lmp->win, &r);
+      xvt_dwin_update(lmp->win);
+      lm_set_hscroll_bar((LM)lmp);
+    }
+    else
+    {
+      if (i < lmp->first_vis && adjust_hscrolling)
+      {
+        xvt_dwin_update(lmp->win);
+        lm_hscroll(lm, i - lmp->first_vis, 0);
+      }
+      else
+      {
+        lm_calc_last_vis(lmp);
+        lm_set_hscroll_range((LM)lmp);
+      }
+    }
+  }
+}
+
+/*
+TODO this function will change.  pix_row_spacing will no longer be used.
+instead, min_row_height, and absolute_height will be used.
+*/
+
+/*-------------------------------------------------------------------------
+  lm_get_vertical_metrics
+-------------------------------------------------------------------------*/
+void lm_get_vertical_metrics( XI_OBJ_DEF* obj_def, int* first_row_y,
+                              int* row_spacing, int *client_height,
+                              int* title_height )
+{
+  XI_LIST_DEF* list_def;
+  XI_OBJ_DEF*  itf_def;
+  int leading, ascent, descent, char_width, font_height, pix_cell_height,
+      pix_hdr_bottom, min_cell_height;
+  PNT p;
+  FONT_OBJ *fontp = NULL;
+
+  list_def = obj_def->v.list;
+
+#if XI_IS_CH
+  NOREF(char_width);
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+
+  itf_def = obj_def->parent;
+  if (itf_def && itf_def->v.itf->font_id)
+    fontp = &itf_def->v.itf->font_id;
+  if (list_def->font_id)
+  xi_get_font_metrics_font( &list_def->font_id, &leading, &ascent, &descent,
+                    &char_width);
+  else if (fontp)
+  xi_get_font_metrics_font(fontp, &leading, &ascent, &descent, &char_width);
+  else
+    xi_get_font_metrics_font( &xi_sysfont, &leading, &ascent, &descent,
+                              &char_width);
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  leading = 0;
+  ascent = 8;
+  descent = 0;
+  CTOS_END;
+#endif
+  font_height = ascent + leading + descent;
+#if XI_IS_CH
+  CTOS_IS_CH;
+  min_cell_height = 8;
+  pix_cell_height = font_height;
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  min_cell_height = list_def->min_cell_height;
+  pix_cell_height = font_height + CELL_VERTICAL_MARGIN;
+  CTOS_END;
+#endif
+  pix_cell_height = max(pix_cell_height, min_cell_height);
+#if XVTWS == WMWS
+  *row_spacing = pix_cell_height;
+#else
+  *row_spacing = pix_cell_height + RULE_WIDTH_H;
+#endif
+  itf_def = obj_def->parent;
+  if (itf_def && itf_def->v.itf->font_id)
+  fontp = &itf_def->v.itf->font_id;
+  if (xi_get_xil_pref((XI_OBJ *)itf_def))
+  {
+    p = list_def->xi_pnt;
+  }
+  else
+  {
+    p = list_def->pixel_origin;
+    if (!p.v && !p.h)
+    {
+      p = list_def->xi_pnt;
+    if (list_def->font_id)
+      xi_fu_to_pu_font(&list_def->font_id, &p, 1);
+    else if (fontp)
+      xi_fu_to_pu_font(fontp, &p, 1);
+    else
+      xi_fu_to_pu_font(&xi_sysfont, &p, 1);
+    }
+  }
+#if XVTWS != WMWS
+  pix_hdr_bottom = p.v + leading + ascent + descent + BORDER_WIDTH
+                  + RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
+  pix_hdr_bottom = max( pix_hdr_bottom, p.v + list_def->min_heading_height
+                                        + BORDER_WIDTH);
+#else
+  pix_hdr_bottom = p.v + leading + ascent + descent + BORDER_WIDTH;
+  pix_hdr_bottom = max( pix_hdr_bottom, p.v + list_def->min_heading_height);
+#endif
+  if (list_def->no_heading)
+  {
+    int first_row_y_pos = p.v + BORDER_WIDTH;
+
+    *first_row_y = first_row_y_pos;
+  }
+  else
+  {
+    *first_row_y = pix_hdr_bottom + BORDER_WIDTH;
+  }
+  if (xi_get_xil_pref((XI_OBJ *)itf_def))
+  {
+    *client_height = list_def->height;
+  }
+  else
+  {
+    if (list_def->pixel_height)
+      *client_height = list_def->pixel_height;
+    else
+    {
+      int height;
+
+    if (list_def->font_id)
+      height = xi_get_fu_height_font(&list_def->font_id);
+    else if (fontp)
+      height = xi_get_fu_height_font(fontp);
+    else
+        height = xi_get_fu_height_font(&xi_sysfont);
+      *client_height = list_def->height * height / XI_FU_MULTIPLE;
+    }
+  }
+  *title_height = *first_row_y - p.v;
+  *client_height -= *title_height + BORDER_WIDTH;
+}
+
+
+/*-------------------------------------------------------------------------
+function:       lm_get_metrics
+lm_def:         definition of a list
+hborder:        to be filled in with the horizontal border width
+column_div:     to be filled in with the column spacing in pixels
+list_button:    bottom of the list, in pixels
+-------------------------------------------------------------------------*/
+void lm_get_metrics(XI_OBJ_DEF *obj_def, int *hborder, int *column_div,
+                    int *list_bottom)
+{
+  if (hborder != NULL)
+    *hborder = BORDER_WIDTH;
+  if (column_div != NULL)
+    *column_div = lm_get_col_spacing();
+  if (obj_def->v.list)
+  {
+    int pix_row_spacing, nbr_rows, height, pix_row1_top, title_height;
+
+    lm_get_vertical_metrics( obj_def, &pix_row1_top, &pix_row_spacing,
+                            &height, &title_height );
+    if (obj_def->v.list->one_row_list)
+      nbr_rows = 1;
+    else
+      nbr_rows = height / pix_row_spacing;
+#if XVTWS == WMWS
+    *list_bottom = pix_row1_top + nbr_rows * pix_row_spacing + BORDER_WIDTH;
+#else
+    *list_bottom = pix_row1_top + nbr_rows * pix_row_spacing
+                  + (BORDER_WIDTH - RULE_WIDTH_H);
+#endif
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_start_edit
+lm:         current lm
+row:        relevant row
+column:     relevant column
+notes:      create a text core edit field in the position of the
+            cell of interest, and copy in the necessary attributes
+            and text from the list
+-------------------------------------------------------------------------*/
+static void lm_start_edit(LM lm, int row, int column)
+{
+  LM_DATA* lmp = LMP(lm);
+  int      focus_row, focus_column;
+  BOOLEAN  v_scrolled;
+
+  lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled );
+  xvt_errmsg_sig_if(!( focus_row == row && focus_column == column), NULL_WIN,
+    SEV_FATAL, ERR_ASSERT_4, "20919", 20919,
+    "lm_start_edit: Internal error, called with focus not poperly set");
+  lm_force_vis(lmp);
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_set_focus
+lm:         current lm
+row:        row
+column:     column
+-------------------------------------------------------------------------*/
+void lm_set_focus(LM lm, int row, int column)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  if (lm_list_has_focus(lmp))
+  {
+    int focus_row, focus_column;
+    BOOLEAN v_scrolled;
+
+    lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled );
+    if (row != focus_row || column != focus_column)
+    {
+      lm_make_invis(lmp);
+      lm_make_vis(lmp);
+    }
+  }
+  else
+    lm_start_edit(lm, row, column);
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_set_hscroll_bar
+lm:         current lm
+notes:      Calculate the percentage for the horizontal scroll bar, and set the
+        thumb position on the horizontal scroll bar.
+-------------------------------------------------------------------------*/
+void
+lm_set_hscroll_bar(LM lm)
+{
+  XI_OBJ *list_obj;
+  int i, first_vis, p;
+  LM_DATA *lmp;
+  int rng1, rng2;
+  int prop;
+
+  lmp = (LM_DATA *)lm;
+  list_obj = lmp->list_obj;
+  if (list_obj->v.list->hsb_win)
+  {
+    xvt_sbar_get_range(list_obj->v.list->hsb_win, HVSCROLL,
+        &rng1, &rng2);
+    prop = xvt_sbar_get_proportion(list_obj->v.list->hsb_win, HVSCROLL);
+    rng2 -= prop;
+    i = lm_get_left_most_far_right_col(lmp, lmp->nbr_columns);
+    if (i == 0)
+      p = 0;
+    else
+    {
+      i = i - lmp->fixed_columns;
+      first_vis = lmp->first_vis - lmp->fixed_columns;
+      if (i)
+        p = (int)(((long)rng2 * (long)first_vis) / i);
+      else
+        p = 0;
+    }
+    if (p < 0)
+      p = 0;
+    if (p > rng2)
+      p = rng2;
+    xvt_sbar_set_pos(list_obj->v.list->hsb_win, HVSCROLL,
+        p);
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:           lm_create_column
+lcdef:              column definition
+not_creating_list:  if TRUE, do all of the cell requests for the column
+in_hscrolling:    if TRUE, and if on border between fixed and scrolling columns
+-------------------------------------------------------------------------*/
+void
+lm_create_column(LM lm, LM_COLUMN_DEF *lcdef, BOOLEAN not_creating_list,
+                BOOLEAN in_hscrolling)
+{
+  LM_COLUMN_DATA *lcdata, *lcdatam1;
+  LM_COLUMN_DATA * *column_data;
+  LM_DATA *lmp = LMP(lm);
+  RCT rct_to_invalidate;
+  int new_textlen;
+  int text_copyidx;
+  int i;
+  char *src;
+  char *dst;
+  char *target;
+  char *buf;
+  int position, col_spacing;
+  int focus_row, focus_column;
+  BOOLEAN made_invis = FALSE;
+
+  col_spacing = lm_get_col_spacing();
+  position = min(lcdef->position, lmp->nbr_columns);
+  if (lm_list_has_focus(lmp))
+  {
+    BOOLEAN vert_scrolled;
+
+    lm_get_focus_cell(lmp, &focus_row, &focus_column, &vert_scrolled);
+    if (focus_column >= position)
+      ++focus_column;
+    lm_set_focus_cell(lmp, focus_row, focus_column, vert_scrolled );
+    if (! lmp->txt_is_invisible)
+    {
+      lm_make_invis(lmp);
+      made_invis = TRUE;
+    }
+  }
+  lcdata = (LM_COLUMN_DATA *)xi_tree_malloc(sizeof(LM_COLUMN_DATA),
+      (char *)lm);
+  lcdata->attrib = lcdef->attrib;
+/*
+  lcdata->pix_width = lcdef->width * lmp->pix_char_width;
+  lcdata->width = lcdef->width;
+*/
+  lcdata->pix_width = lcdef->pix_width;
+  lcdata->width = lcdef->pix_width / lmp->pix_char_width;
+  calc_x_pix_pos(lm, lcdata, position);
+  if (position)
+    lcdatam1 = lmp->lm_column_data[position - 1];
+  text_copyidx = (position == 0) ? 0 : lcdatam1->text_offset +
+      lcdatam1->text_size;
+  lcdata->text_offset = text_copyidx;
+  lcdata->text_size = lcdef->text_size;
+  lcdata->center_heading = lcdef->center_heading;
+  lcdata->heading_well = lcdef->heading_well;
+  lcdata->heading_platform = lcdef->heading_platform;
+  lcdata->column_well = lcdef->column_well;
+  lcdata->column_platform = lcdef->column_platform;
+  lcdata->heading_text = (char *)xi_tree_malloc(
+      strlen(lcdef->heading_text) + 1, (char *)lm);
+  strcpy(lcdata->heading_text, lcdef->heading_text);
+  if (lcdef->font)
+  {
+#if 0
+    /* reparenting font object, not reallocating */
+    lcdata->font = (FONT_OBJ *)xi_tree_malloc(sizeof(FONT_OBJ),
+        (void *)lm);
+#endif
+    lcdata->font = lcdef->font;
+    xi_tree_reparent(lcdata->font, lcdata);
+  }
+  lcdata->icon_rid = lcdef->icon_rid;
+  lcdata->icon_x = lcdef->icon_x;
+  lcdata->icon_y = lcdef->icon_y;
+  lcdata->size_rows = lcdef->size_rows;
+  lcdata->suppress_update_heading = lcdef->suppress_update_heading;
+  lcdata->suppress_update_cells = lcdef->suppress_update_cells;
+  lcdata->vertical_align_center = lcdef->vertical_align_center;
+  lcdata->vertical_align_bottom = lcdef->vertical_align_bottom;
+  lcdata->wrap_text = lcdef->wrap_text;
+  lcdata->auto_tab = lcdef->auto_tab;
+
+  new_textlen = lmp->text_size + lcdata->text_size;
+
+  /* allocate new text for each row and move text if necessary */
+  for (i = 0; i < lmp->realized_rows_array_len; i++)
+  {
+    buf = lmp->buffer[i] = (char *)xi_tree_realloc2(lmp->buffer[i],
+        new_textlen, (char *)lm);
+    /* zero out new text */
+    memset(buf + lmp->text_size, '\0', (size_t)lcdata->text_size);
+
+    /* copy text for old columns that were moved */
+    /* degenerate zero-column case is handled correctly */
+    dst = buf + new_textlen;
+    src = buf + lmp->text_size;
+    target = buf + text_copyidx;
+    while (src > target)
+      *--dst = *--src;
+  }
+
+  /* allocate new columns */
+  column_data = lmp->lm_column_data =
+      (LM_COLUMN_DATA * *)xi_tree_realloc2(
+      (char *)lmp->lm_column_data,
+      sizeof(LM_COLUMN_DATA *) * (lmp->nbr_columns + 1),
+      (char *)lm);
+
+  /* create space for cell data */
+  for (i = 0; i < lmp->realized_rows_array_len; i++)
+  {
+    int j;
+
+    lmp->cell_data[i] = (LM_CELL_DATA *)xi_tree_realloc(lmp->cell_data[i],
+        (lmp->nbr_columns + 1) * sizeof(LM_CELL_DATA));
+    for (j = lmp->nbr_columns; j > position; j--)
+      lmp->cell_data[i][j] = lmp->cell_data[i][j - 1];
+    memset((char *)&lmp->cell_data[i][position], '\0',
+        sizeof(LM_CELL_DATA));
+  }
+
+  /* move column pointers around in the column list */
+  for (i = lmp->nbr_columns; i > position; i--)
+  {
+    column_data[i] = column_data[i - 1];
+    column_data[i]->x_pix_pos += lcdata->pix_width + col_spacing;
+    column_data[i]->text_offset += lcdata->text_size;
+  }
+  column_data[position] = lcdata;
+
+  lmp->nbr_columns++;
+
+  if ((not_creating_list) && (position < lmp->fixed_columns))
+  {
+    lmp->first_vis++;
+    lmp->fixed_columns++;
+  }
+
+  if (not_creating_list && (! in_hscrolling) && position == lmp->fixed_columns)
+  {
+    lmp->first_vis++;
+    lmp->fixed_columns++;
+  }
+
+  if (lmp->first_vis < lmp->fixed_columns &&
+      lmp->nbr_columns > lmp->fixed_columns)
+    lmp->first_vis = lmp->fixed_columns;
+
+  lmp->text_size = new_textlen;
+
+  /* adjust bounding rectangle */
+  lmp->rct.right += lcdata->pix_width + col_spacing;
+  if (lmp->nbr_columns == 1)
+    lmp->rct.right -= RULE_WIDTH_V; /* did not add divider rule */
+#if XI_IS_CH
+  CTOS_IS_CH;
+  lmp->mlr.right = lmp->rct.right;
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  lmp->mlr.right = lmp->rct.right - BORDER_WIDTH;
+  CTOS_END;
+#endif
+
+  /* calculate the left boundary of the virtual space for the list */
+  lmp->vir_left = lmp->rct.left + BORDER_WIDTH;
+  for (i = 0; i < min(lmp->nbr_columns, lmp->fixed_columns); ++i)
+  {
+    lmp->vir_left += lmp->lm_column_data[i]->pix_width;
+    lmp->vir_left += col_spacing;
+  }
+  if (not_creating_list)
+  {
+    lm_invalidate_rows_internal(lm, 0, INT_MAX, FALSE, position, TRUE);
+    calculate_pix_offsets( lmp, TRUE );
+  }
+  if (position >= lmp->fixed_columns && column_data[position]->x_pix_pos < lmp->delta_x)
+  {
+    lmp->delta_x += (column_data[position]->pix_width + lm_get_col_spacing());
+    ++lmp->first_vis;
+    lm_set_hscroll_range((LM)lmp);
+  }
+  else
+  {
+    /* invalidate changed rectangle */
+    lm_get_list_rct(lmp, &rct_to_invalidate);
+
+    /*
+    if we add the following two lines in, it prevents flashing of the top and bottom borders when
+    moving columns, however, the top and bottom borders need to get invalidated
+    rct_to_invalidate.top += BORDER_WIDTH;
+    rct_to_invalidate.bottom -= BORDER_WIDTH;
+    */
+
+    rct_to_invalidate.left = lcdata->x_pix_pos;
+    lm_adj_h(lmp, &rct_to_invalidate.left);
+    if (rct_to_invalidate.bottom > rct_to_invalidate.top &&
+        rct_to_invalidate.right > rct_to_invalidate.left)
+      lm_invalidate_rect2(lmp, &rct_to_invalidate, FALSE);
+  }
+  lm_calc_last_vis(lmp);
+  lmp->list_obj->v.list->have_sb_rct = FALSE;
+  if (not_creating_list && lmp->list_obj->v.list->hsb_win)
+  {
+    RCT rct;
+
+    lmp->list_obj->v.list->have_hsb_rct = FALSE;
+    lm_set_hscroll_range((LM)lmp);
+    lm_set_hscroll_bar((LM) lmp);
+    xi_get_hsb_rect(lmp->list_obj, &rct);
+    xvt_vobj_move(lmp->list_obj->v.list->hsb_win, &rct);
+  }
+  if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+  {
+    if (not_creating_list && made_invis)
+      lm_make_vis(lmp);
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:   do_lm_cb_column
+lm:         current lm
+cb_reason:  one of LM_CB_COL_DELETE, LM_CB_COL_MOVE, LM_CB_COL_SIZE
+col_nbr:    column being deleted, moved, or re-sized
+new_col_nbr:    new column number on LM_CB_COL_MOVE
+new_col_width:  new column width on LM_CB_COL_SIZE
+new_col_pixel_width:  new column pixel width on LM_CB_COL_SIZE
+in_fixed: if TRUE, then column is being moved to fixed portion of list
+returns:    TRUE if event refused
+-------------------------------------------------------------------------*/
+static BOOLEAN
+near do_lm_cb_column(LM lm, LM_CB_TYPE cb_reason, int col_nbr,
+int new_col_nbr, int new_col_width, int new_col_pixel_width,
+BOOLEAN in_fixed)
+{
+  LM_CB_DATA lm_cb_data;
+
+  lm_cb_data.lm       = lm;
+  lm_cb_data.cb_type  = cb_reason;
+  lm_cb_data.cid      = LMP(lm)->cid;
+  lm_cb_data.win      = LMP(lm)->win;
+  lm_cb_data.column   = (unsigned char)col_nbr;
+  lm_cb_data.v.column.new_col_nbr = new_col_nbr;
+  lm_cb_data.v.column.in_fixed = in_fixed;
+  lm_cb_data.v.column.new_col_width = new_col_width;
+  lm_cb_data.v.column.new_col_pixel_width = new_col_pixel_width;
+  lm_cb_data.v.column.refused = FALSE;
+  (*LMP(lm)->lm_cb)(&lm_cb_data);
+  return (lm_cb_data.v.column.refused);
+  }
+
+/*-------------------------------------------------------------------------
+function:   get_rubber_rect
+lmp:        current lmp
+rctp:       rectangle to be filled in
+x:          current mouse x position
+y:          current mouse y position
+-------------------------------------------------------------------------*/
+static void
+get_rubber_rect(LM_DATA *lmp, RCT *rctp, int x, int y,
+BOOLEAN last_in_hscrolling)
+{
+  RCT rct;
+  int col, delta_x, delta_y;
+
+  col = lmp->column_being_moved;
+  /*
+  lm_get_cell_rect returns the exact physical rectangle of the cell - not
+  shifted to the right or to the left.
+  */
+  lm_get_cell_rect(&rct, (LM)lmp, 1, col, FALSE, TRUE);
+  rct.top = lmp->pix_top + BORDER_WIDTH;
+  rct.bottom = lmp->pix_hdr_bottom;
+  delta_x = x - lmp->org_x;
+  if (lmp->down_in_hscrolling && ! last_in_hscrolling)
+    delta_x += lmp->delta_x;
+  if (! lmp->down_in_hscrolling && last_in_hscrolling)
+    delta_x -= lmp->delta_x;
+  delta_y = y - lmp->org_y;
+  rct.left += delta_x;
+  rct.right += delta_x;
+  rct.top += delta_y;
+  rct.bottom += delta_y;
+  *rctp = rct;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   rubber_rect
+lmp:        current lmp
+-------------------------------------------------------------------------*/
+static void
+rubber_rect(LM_DATA *lmp)
+{
+#if XI_IS_NOT_CH
+  RCT rct;
+  DRAW_CTOOLS new_ctools;
+  WINDOW win = lmp->win;
+
+  CTOS_IS_PM;
+  xvt_app_get_default_ctools(&new_ctools);
+  xi_set_draw_ctools(win, &new_ctools);
+  xi_set_cpen(win, &rubber_cpen);
+  xi_set_cbrush(win, &hollow_cbrush);
+  xi_set_draw_mode(win, M_XOR);
+  xi_set_clip(win, NULL);
+  get_rubber_rect(lmp, &rct, lmp->last_x, lmp->last_y, lmp->last_in_hscrolling);
+  xi_draw_rect(win, &rct);
+  CTOS_END;
+#endif
+  NOREF(lmp);
+}
+
+/*-------------------------------------------------------------------------
+function:   lm_move_event
+lmp:        current lmp
+ep:         xvt event
+-------------------------------------------------------------------------*/
+void
+lm_move_event(LM_DATA *lmp, EVENT *ep)
+{
+  PNT where;
+  int col_offset;
+
+  col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+  where = ep->v.mouse.where;
+  switch (ep->type)
+  {
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+    lmp->last_x = where.h;
+    lmp->org_x = lmp->last_x;
+    lmp->last_y = where.v;
+    lmp->org_y = lmp->last_y;
+    lmp->last_in_hscrolling = lmp->in_hscrolling;
+    rubber_rect(lmp);
+    break;
+  case E_MOUSE_MOVE:
+    if (where.h != lmp->last_x || where.v != lmp->last_y)
+    {
+      rubber_rect(lmp);
+      lmp->last_x = where.h;
+      lmp->last_y = where.v;
+      lmp->last_in_hscrolling = lmp->in_hscrolling;
+      rubber_rect(lmp);
+    }
+    break;
+  case E_MOUSE_UP:
+    {
+      int column;
+      XI_OBJ *list_obj, * *members;
+      int nbr_members, col_cnt, temp1, temp2, dist1, dist2, min_dist,
+      position;
+      RCT rct;
+      PNT where;
+
+      where = ep->v.mouse.where;
+      rubber_rect(lmp);
+      column = lmp->column_being_moved;
+      list_obj = lmp->list_obj;
+      if (list_obj)
+        get_rubber_rect(lmp, &rct, where.h, where.v, lmp->in_hscrolling);
+      if (lmp->drop_and_delete &&
+          (rct.bottom < (lmp->pix_top - 8) ||
+          rct.top > (lmp->pix_row1_top + 8)))
+      {
+      if (do_lm_cb_column((long)lmp, LM_CB_COL_DELETE, column,
+        0, 0, 0, FALSE) == FALSE)
+      {
+      members = xi_get_member_list(list_obj, &nbr_members);
+      xi_delete(members[column]);
+      lm_set_hscroll_range((LM)lmp);
+      }
+    }
+    if (where.v > lmp->pix_top && where.v < lmp->pix_row1_top &&
+          where.h >= lmp->rct.left)
+      {
+        BOOLEAN in_hscrolling, old_in_hscrolling;
+
+        /*
+        determine where to move the column, if anywhere
+        */
+        in_hscrolling = FALSE;
+        old_in_hscrolling = (column >= lmp->fixed_columns);
+        min_dist = INT_MAX;
+        position = 0;
+        for (col_cnt = 0; col_cnt < lmp->nbr_columns; col_cnt++)
+        {
+          LM_COLUMN_DATA *column_data;
+
+          if (col_cnt >= lmp->fixed_columns &&
+              col_cnt < lmp->first_vis)
+            continue;
+          column_data = lmp->lm_column_data[col_cnt];
+          temp1 = column_data->x_pix_pos;
+          temp2 = temp1 + 2 * col_offset + column_data->pix_width;
+          dist1 = abs(temp1 - where.h);
+          dist2 = abs(temp2 - where.h);
+          if (dist1 < min_dist)
+          {
+            position = col_cnt;
+            min_dist = dist1;
+          }
+          if (dist2 < min_dist)
+          {
+            position = col_cnt + 1;
+            min_dist = dist2;
+          }
+          if (col_cnt == lmp->fixed_columns)
+          {
+            if (where.h < column_data->x_pix_pos)
+              in_hscrolling = FALSE;
+            else
+              in_hscrolling = TRUE;
+          }
+        }
+
+        /*
+        if we need to move the column, then move it
+        */
+        if (position < column || position > column + 1 ||
+            position == lmp->fixed_columns)
+        {
+          if (column == position && position == lmp->fixed_columns &&
+              in_hscrolling && (! old_in_hscrolling))
+            position -= 1;
+          else if (position > column)
+            position -= 1;
+
+          /*
+          if there is only one fixed column left, then don't move it
+          */
+          if (column != 0 || lmp->fixed_columns != 1)
+          {
+            int widest_remaining, col_width, width_remaining,
+            new_fixed_width, cnt;
+            BOOLEAN do_move = TRUE;
+            LM_COLUMN_DATA *column_data, *lmcdp2;
+            RCT r;
+
+            if (lmp->fixed_columns < lmp->nbr_columns)
+            {
+              /*
+              if there is not room in the horizontal scrolling portion of the
+              list for the widest column remaining in the horizontal scrolling
+              portion of the list, then don't move the column
+              */
+              widest_remaining = 0;
+              for (cnt = lmp->fixed_columns; cnt < lmp->nbr_columns;
+                  ++cnt)
+              {
+                if (cnt == column)
+                  continue;
+                column_data = lmp->lm_column_data[cnt];
+                col_width = column_data->pix_width + 2 * col_offset;
+                if (col_width > widest_remaining)
+                  widest_remaining = col_width;
+              }
+              column_data = lmp->lm_column_data[lmp->fixed_columns];
+              lmcdp2 = lmp->lm_column_data[column];
+              new_fixed_width = column_data->x_pix_pos;
+              if (position < lmp->fixed_columns || ! in_hscrolling)
+                new_fixed_width += lmcdp2->pix_width + 2 * col_offset;
+              if (column < lmp->fixed_columns)
+                new_fixed_width -= lmcdp2->pix_width + 2 * col_offset;
+              lm_get_list_rct(lmp, &r);
+              width_remaining = r.right - r.left - new_fixed_width;
+              if (widest_remaining > width_remaining)
+                do_move = FALSE;
+            }
+
+            if (do_move)
+            {
+              BOOLEAN in_fixed = ! in_hscrolling;
+
+              if (position > lmp->fixed_columns)
+                in_fixed = FALSE;
+          if (do_lm_cb_column((long)lmp, LM_CB_COL_MOVE, column,
+            position, 0, 0, in_fixed) == FALSE)
+              {
+                members = xi_get_member_list(list_obj, &nbr_members);
+                xi_move_column_internal(members[column], position,
+                    in_hscrolling);
+                lm_calc_last_vis(lmp);
+                lm_set_hscroll_bar((LM)lmp);
+              }
+            }
+          }
+        }
+      }
+      lm_make_vis(lmp);
+      break;
+    }
+  }
+}
+
+/*-------------------------------------------------------------------------
+function:   calc_x
+lmp:        current lmp
+ep:         xvt event
+returns:    Calculates and returns the X pixel position of the rubber band line.
+      Used only when sizing columns.
+-------------------------------------------------------------------------*/
+static int
+calc_x(LM_DATA *lmp, EVENT *ep)
+{
+  int column = lmp->column_being_sized;
+  int temp, temp2, widest_remaining;
+  int min_width_in_pix = 16;
+  int col_offset;
+
+  col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+
+  /*
+  temp is the min width position of the column, relative to the
+  left edge of the list.
+  */
+  temp = lmp->lm_column_data[column]->x_pix_pos + col_offset +
+      min_width_in_pix;
+  temp = max(ep->v.mouse.where.h, temp);
+  widest_remaining = 0;
+  if (lmp->pixel_width)
+  {
+    int col_offset, col_width, cnt;
+    LM_COLUMN_DATA *column_data;
+
+    col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+    if (column < lmp->fixed_columns)
+    {
+      /*
+      figure out the widest column in the horizontal scrolling
+      portion of the list
+      */
+      for (cnt = lmp->fixed_columns; cnt < lmp->nbr_columns; ++cnt)
+      {
+        column_data = lmp->lm_column_data[cnt];
+        col_width = column_data->pix_width + 2 * col_offset;
+        if (col_width > widest_remaining)
+          widest_remaining = col_width;
+      }
+      /*
+      add the widths of all of the columns to the right of this column
+      in the fixed portion of the list
+      */
+      temp2 = 0;
+      for (cnt = column + 1; cnt < lmp->fixed_columns; ++cnt)
+      {
+        column_data = lmp->lm_column_data[cnt];
+        col_width = column_data->pix_width + 2 * col_offset;
+        temp2 += col_width;
+      }
+      temp = min((lmp->pixel_width - widest_remaining - temp2) - BORDER_WIDTH,
+          temp);
+    }
+    else
+      temp = min((lmp->pixel_width + lmp->delta_x) - BORDER_WIDTH, temp);
+  }
+  return temp;
+}
+
+
+/*-------------------------------------------------------------------------
+function:   rubber_x
+lmp:        current lmp
+x:          draw a rubber line at position x
+-------------------------------------------------------------------------*/
+static void
+rubber_x(LM_DATA *lmp, int x)
+{
+#if XI_IS_NOT_CH
+  int top, bottom;
+  DRAW_CTOOLS new_ctools;
+  PNT pnt;
+  WINDOW win = lmp->win;
+
+  CTOS_IS_PM;
+  top = lmp->pix_top;
+  bottom = lmp->mlr.bottom;
+  xvt_app_get_default_ctools(&new_ctools);
+  xi_set_draw_ctools(win, &new_ctools);
+  xi_set_cpen(win, &rubber_cpen);
+  xi_set_draw_mode(win, M_XOR);
+  xi_set_clip(win, NULL);
+  pnt.h = x;
+  pnt.v = top;
+  if (! lmp->down_in_hscrolling)
+    pnt.h += lmp->rct.left;
+  lm_move_to(lmp, pnt, FALSE, lmp->down_in_hscrolling);
+  pnt.v = bottom;
+  lm_draw_line(lmp, pnt, FALSE, lmp->down_in_hscrolling);
+  CTOS_END;
+#endif
+  NOREF(lmp);
+  NOREF(x);
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_size_event
+lmp:        current lmp
+ep:         xvt event
+-------------------------------------------------------------------------*/
+void
+lm_size_event(LM_DATA *lmp, EVENT *ep)
+{
+  int x;
+
+  switch (ep->type)
+  {
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+    x = calc_x(lmp, ep);
+    lmp->last_x = x;
+    rubber_x(lmp, x);
+    break;
+  case E_MOUSE_MOVE:
+    x = calc_x(lmp, ep);
+    rubber_x(lmp, lmp->last_x);
+    lmp->last_x = x;
+  rubber_x(lmp, x);
+  break;
+  case E_MOUSE_UP:
+  {
+    int         col_offset;
+    int         column;
+    int         temp;
+    int         width_in_chars;
+    int         pixel_width;
+    XI_OBJ * list_obj, * *members;
+    int nbr_members;
+    int char_width;
+
+    col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
+    x = calc_x(lmp, ep);
+    rubber_x(lmp, lmp->last_x);
+    column = lmp->column_being_sized;
+    temp = lmp->lm_column_data[column]->x_pix_pos + col_offset;
+    pixel_width = (x - temp) - col_offset;
+    width_in_chars = (int)(pixel_width / (long)xi_get_fu_width(lmp->itf_obj));
+    list_obj = lmp->list_obj;
+
+    char_width = width_in_chars * XI_FU_MULTIPLE;
+    if (xi_get_xil_pref(list_obj->itf))
+      char_width = width_in_chars;
+
+    if (do_lm_cb_column((long)lmp, LM_CB_COL_SIZE, column,
+      0, char_width, pixel_width, FALSE) == FALSE)
+    {
+      int i;
+
+      members = xi_get_member_list(list_obj, &nbr_members);
+      xi_column_set_pixel_width( members[column], pixel_width );
+      i = lm_get_left_most_far_right_col(lmp, lmp->nbr_columns);
+      if (i < lmp->first_vis)
+      {
+      xvt_dwin_update(lmp->win);
+      lm_hscroll((LM)lmp, lmp->first_vis - i, 0);
+      }
+      else
+      {
+      lm_calc_last_vis(lmp);
+      lm_set_hscroll_bar((LM)lmp);
+      }
+    }
+    lm_make_vis(lmp);
+    break;
+  }
+  }
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_set_icon
+lm:         current lm
+icon_rid:   icon resource id
+row:      
+column:
+-------------------------------------------------------------------------*/
+void
+lm_set_icon(LM lm, int icon_rid, int row, int column)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  lmp->cell_data[row][column].icon_rid = icon_rid;
+  if (LMP(lm)->attrib & XI_ATR_VISIBLE)
+    redraw_cell(lm, row, column, FALSE );
+}
+
+
+/*-------------------------------------------------------------------------
+function:   lm_set_sel
+lm:         current lm
+row:        row
+column:     column
+c1:         starting position in selection
+c2:         ending position
+-------------------------------------------------------------------------*/
+void lm_set_sel(LM lm, int row, int column, BOOLEAN v_scrolled, int c1, int c2)
+{
+  LM_DATA *lmp = LMP(lm);
+
+  if (!lm_list_has_focus(lmp))
+  {
+    lm_set_focus(lm, row, column);
+  } else
+  {
+    int     focus_row, focus_column;
+    BOOLEAN is_v_scrolled;
+
+    lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_v_scrolled);
+    if (focus_row != row || focus_column != column || v_scrolled != is_v_scrolled)
+      lm_set_focus(lm, row, column);
+  }
+  if (v_scrolled)
+  {
+    lmp->focus_cell_ip1 = c1;
+    lmp->focus_cell_ip2 = c2;
+  } else
+    txt_set_sel(lmp->txt, c1, c2);
+}
+
+/*-------------------------------------------------------------------------
+function:   scroll_list
+lmp:        current lmp
+left_col:
+right_col:
+-------------------------------------------------------------------------*/
+static void
+scroll_list(LM_DATA *lmp, int left_col, int right_col)
+{
+  RCT r;
+  int l1, l2, dist;
+
+  if (left_col == right_col)
+  {
+    if (lmp->nbr_columns == lmp->fixed_columns)
+      lmp->delta_x = 0;
+    return;
+  }
+  l1 = lmp->rct.left + lmp->lm_column_data[left_col]->x_pix_pos;
+  l2 = lmp->rct.left + lmp->lm_column_data[right_col]->x_pix_pos;
+  dist = l2 - l1;
+  lmp->delta_x += dist;
+  r.left = lmp->vir_left;
+  r.right = lmp->vir_right;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  r.top = lmp->rct.top + BORDER_WIDTH;
+  r.bottom = lmp->rct.bottom - BORDER_WIDTH;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  r.top = lmp->rct.top;
+  r.bottom = lmp->rct.bottom;
+  CTOS_END;
+#endif
+  if (! lmp->itf_obj->v.itf->half_baked)
+    xvt_dwin_update(lmp->win);
+  xi_set_update_obj(lmp->list_obj);
+  lmp->last_vis = lmp->first_vis;
+  lm_calc_last_vis(lmp);
+
+#if XI_IS_CH
+  CTOS_IS_CH;
+  xi_invalidate_rect(lmp->win, &r);
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  xi_scroll_rect(lmp->win, &r, -dist, 0);
+  CTOS_END;
+#endif
+
+  if (! lmp->itf_obj->v.itf->half_baked)
+    xvt_dwin_update(lmp->win);
+  lm_set_hscroll_bar((LM)lmp);
+}
+
+
+/*-------------------------------------------------------------------------
+function:       lm_hscroll
+lm:             current lm
+nbr_columns:    number of columns to scroll
+pos:            if set, pos is a percentage based on where the thumb was dropped.
+-------------------------------------------------------------------------*/
+void
+lm_hscroll(LM lm, int nbr_columns, int pos)
+{
+  LM_DATA *lmp = LMP(lm);
+  int first_vis, last_vis, lmfrc, starting_column;
+
+  xvt_dwin_update(lmp->win);
+  lmfrc = lm_get_left_most_far_right_col(LMP(lm), lmp->nbr_columns);
+  first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
+  last_vis = min(lmp->last_vis, lmp->nbr_columns - 1);
+  if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
+    lm_make_invis(lmp);
+  else
+  {
+    if (! lmp->itf_obj->v.itf->moving_focus)
+      if (! xi_move_focus(lmp->itf_obj))
+        return;
+  }
+  if (nbr_columns == XI_SCROLL_FIRST)
+  {
+    starting_column = lmfrc;
+    if (starting_column)
+    {
+      starting_column = starting_column - lmp->fixed_columns;
+      starting_column = (int)(((long)pos * (long)starting_column) /
+          (long)100);
+    }
+    starting_column += lmp->fixed_columns;
+    lmp->first_vis = starting_column;
+    lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
+    scroll_list(lmp, first_vis, lmp->first_vis);
+    lm_make_vis(lmp);
+    return;
+  }
+  if (nbr_columns == XI_SCROLL_PGDOWN)
+  {
+    starting_column = min(last_vis + 1, lmfrc);
+    starting_column = min(starting_column, lmp->nbr_columns - 1);
+    lmp->first_vis = starting_column;
+    lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
+    scroll_list(lmp, first_vis, lmp->first_vis);
+    lm_make_vis(lmp);
+    return;
+  }
+  if (nbr_columns == XI_SCROLL_PGUP)
+  {
+    starting_column = lm_get_left_most_far_right_col(lmp, first_vis);
+    starting_column = min(starting_column, lmp->nbr_columns - 1);
+    lmp->first_vis = starting_column;
+    lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
+    scroll_list(lmp, first_vis, lmp->first_vis);
+    lm_make_vis(lmp);
+    return;
+  }
+  lmp->first_vis += nbr_columns;
+  if (nbr_columns > 0)
+  {
+    lmp->first_vis = min(lmp->first_vis, lm_get_left_most_far_right_col(lmp, lmp->nbr_columns));
+    lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
+  }
+  else
+  {
+    lmp->first_vis = max(lmp->first_vis, lmp->fixed_columns);
+    lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
+  }
+  scroll_list(lmp, first_vis, lmp->first_vis);
+  lm_make_vis(lmp);
+}
+
+
+
diff --git a/xi/xistx.c b/xi/xistx.c
new file mode 100755
index 000000000..633be131b
--- /dev/null
+++ b/xi/xistx.c
@@ -0,0 +1,1140 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#define XI_INTERNAL
+
+#include "xi.h"
+#include "xitext.h"
+#include "xistx.h"
+#include "xiutils.h"
+
+#define tx_create
+#define xvt_tx_process_event xvt_tx_process_event
+
+/* error codes 30100 - 30104 */
+
+#if XVT_OS == XVT_OS_CTOS
+#define BORDER_WIDTH_X ((npctos_env == CHSERVICE) ? 8 : 1)
+#define BORDER_WIDTH_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#define BORDER_SPACE_X ((npctos_env == CHSERVICE) ? 0 : 1)
+#define BORDER_SPACE_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#define CHR_LEFTBRACKET "["
+#define CHR_RIGHTBRACKET "]"
+#else
+#if XIWS != WMWS
+#define BORDER_WIDTH_X 1
+#define BORDER_WIDTH_Y 1
+#define BORDER_SPACE_X 1
+#define BORDER_SPACE_Y 1
+#else
+#define BORDER_WIDTH_X 8
+#define BORDER_WIDTH_Y 0
+#define BORDER_SPACE_X 0
+#define BORDER_SPACE_Y 0
+#define CHR_LEFTBRACKET "["
+#define CHR_RIGHTBRACKET "]"
+#endif
+#endif
+
+#define STXP(stx) ((STX_DATA *)(stx))
+#define STX_IS_ENABLED(stx) ((STXP(stx)->attrib & STX_ATR_ENABLED) != 0)
+#define STX_IS_VISIBLE(stx) ((STXP(stx)->attrib & STX_ATR_VISIBLE) != 0)
+#define STX_HAS_BORDER(stx) ((STXP(stx)->attrib & STX_ATR_BORDER) != 0)
+
+#define STX_REDRAW_ATR (STX_ATR_VISIBLE | STX_ATR_ENABLED | STX_ATR_RJUST | STX_ATR_PASSWORD)
+
+static void near stx_stop_edit(STX stx);
+static void  draw_text_edit_border(STX_DATA *stxptr);
+
+static void near
+get_text_rect(STX stx, RCT *rct)
+{
+  *rct = STXP(stx)->rct;
+  rct->top += BORDER_WIDTH_Y + BORDER_SPACE_Y;
+  rct->bottom -= BORDER_WIDTH_Y + BORDER_SPACE_Y;
+  rct->left += BORDER_WIDTH_X + BORDER_SPACE_X;
+  rct->right -= BORDER_WIDTH_X + BORDER_SPACE_X;
+}
+
+TXEDIT
+stx_get_txedit(STX stx)
+{
+  return STXP(stx)->txedit;
+}
+
+STX
+stx_create(WINDOW win, STX_DEF *stx_def)
+{
+  STX_DATA *stxd;
+  RCT rct;
+  int ascent, descent, leading, font_height;
+  short rct_r, rct_b, edit_height;
+  XI_OBJ *itf;
+
+  itf = xi_get_itf(win);
+  NOREF(itf);
+  xi_set_xvt_font(win, &stx_def->font, FALSE);
+  xi_get_font_metrics(win, &leading, &ascent, &descent);
+  font_height = ascent + leading + descent;
+  stxd = (STX_DATA *)xi_tree_malloc(sizeof(STX_DATA), stx_def->parent);
+  stxd->cid = stx_def->cid;
+  stxd->win = win;
+  stxd->attrib = stx_def->attrib;
+  rct_r = stx_def->pnt.h + stx_def->pixel_width + 2 *
+        BORDER_WIDTH_X + 2 * BORDER_SPACE_X;
+  edit_height = font_height + 2 * BORDER_WIDTH_Y + 2 * BORDER_SPACE_Y;
+  rct_b = stx_def->pnt.v + edit_height;
+  xvt_rect_set( &rct, stx_def->pnt.h, stx_def->pnt.v, rct_r, rct_b);
+  stxd->rct = rct;
+  stxd->font = stx_def->font;
+  stxd->back_color = stx_def->back_color;
+  stxd->enabled_color = stx_def->enabled_color;
+  stxd->disabled_color = stx_def->disabled_color;
+  stxd->active_color = stx_def->active_color;
+  stxd->active_back_color = stx_def->active_back_color;
+  stxd->disabled_back_color = stx_def->disabled_back_color;
+  stxd->hilight_color = stx_def->hilight_color;
+  stxd->shadow_color = stx_def->shadow_color;
+  stxd->stx_cb = stx_def->stx_cb;
+  stxd->text_size = stx_def->text_size;
+  stxd->app_data = stx_def->app_data;
+  stxd->text = (char *)xi_tree_malloc(stx_def->text_size, (char *)stxd);
+  stxd->text[0] = '\0';
+  stxd->has_focus = FALSE;
+  stxd->well = stx_def->well;
+  stxd->platform = stx_def->platform;
+  stxd->auto_tab = stx_def->auto_tab;
+  stxd->txedit = BAD_TXEDIT;
+#ifndef XI_DONT_USE_TX_EDIT
+  if (stx_def->xi_rct.top || stx_def->xi_rct.left ||
+      stx_def->xi_rct.bottom || stx_def->xi_rct.right)
+  {
+    unsigned attrib;
+    RCT rct;
+
+  if ((stx_def->xi_rct.bottom - stx_def->xi_rct.top) <=
+      XI_FU_MULTIPLE)
+  {
+    rct = stx_def->xi_rct;
+    xi_fu_to_pu(xi_get_itf(win), (PNT *)&rct, 2);
+    rct.bottom = rct.top + edit_height;
+    stxd->rct = rct;
+  }
+  else
+  {
+    FONT_OBJ font;
+
+    attrib = TX_WRAP;
+    if (stxd->attrib & XI_ATR_READONLY)
+      attrib |= TX_READONLY;
+    if (stxd->attrib & XI_ATR_BORDER)
+      attrib |= TX_BORDER;
+    if (stxd->attrib & XI_ATR_AUTOSCROLL)
+      attrib |= TX_AUTOHSCROLL | TX_AUTOVSCROLL;
+    if (! itf->v.itf->edit_menu)
+      attrib |= TX_NOMENU;
+    stxd->use_text_edit = TRUE;
+    rct = stx_def->xi_rct;
+    xi_fu_to_pu(xi_get_itf(win), (PNT *)&rct, 2);
+    rct.bottom -= BORDER_SPACE_Y;
+    stxd->rct = rct;
+    if (((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK))
+      &&((stxd->well == TRUE) || (stxd->platform == TRUE)))
+    {
+      xi_inflate_rect(&rct, -2);
+      attrib  &= ~TX_BORDER;
+    }
+    if ((stxd->attrib & XI_ATR_FOCUSBORDER) || ((stxd->attrib & XI_ATR_BORDER)))
+      xi_inflate_rect(&rct, -1);
+    font = stx_def->font;
+    stxd->txedit = xvt_tx_create(win, &rct, attrib,
+      font, rct.right - rct.left - 4, INT_MAX);
+    xvt_tx_set_colors(stxd->txedit, stxd->enabled_color,
+      stxd->enabled_color, stxd->back_color);
+    xvt_tx_add_par(stxd->txedit, 0, "");
+
+    /* the following line is a hack for ms-windows */
+    { PNT _p; _p.h =  -100; _p.v =  -100;
+    xvt_win_set_caret_pos(win, _p);  /*xvt_R3MIG caret_on*/
+    xvt_win_set_caret_visible(win, TRUE); };
+    xvt_win_set_caret_visible(win, FALSE );
+  }
+  }
+#endif
+  xi_invalidate_rect(win, &stxd->rct);
+  return((STX)PTR_LONG(stxd));
+}
+
+void
+stx_delete(STX stx)
+{
+#ifndef XI_DONT_USE_TX_EDIT
+  if (STXP(stx)->use_text_edit)
+    xvt_tx_destroy(STXP(stx)->txedit);
+  else
+#endif
+    {
+      if (STXP(stx)->has_focus)
+        stx_stop_edit(stx);
+      xi_invalidate_rect(STXP(stx)->win, &STXP(stx)->rct);
+    }
+  xi_tree_free((char *)stx);
+}
+
+static void near
+redraw_stx(STX stx, BOOLEAN update, BOOLEAN inside_only)
+{
+  RCT rct;
+  DRAW_CTOOLS ct;
+  FONT_OBJ *ct_font;
+  STX_DATA *stxp = STXP(stx);
+#if XI_IS_NOT_CH
+  RCT rct2, rr;
+#endif
+
+#if XI_IS_CH
+  NOREF(inside_only);
+#endif
+
+  if (STXP(stx)->use_text_edit)
+    return;
+  rct = stxp->rct;
+  if (update && !xi_needs_update(stxp->win, &rct))
+    return;
+  if (STX_IS_VISIBLE(stx))
+  {
+    xvt_app_get_default_ctools(&ct);
+#if XI_IS_CH
+    CTOS_IS_CH;
+    ct.pen = hollow_cpen;
+    CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    if (STX_HAS_BORDER(stx) && !inside_only)
+      ct.pen = black_cpen;
+    else
+      ct.pen = hollow_cpen;
+    CTOS_END;
+#endif
+    ct_font = &stxp->font;
+    if (STX_IS_ENABLED(stx))
+    {
+      ct.fore_color = ct.pen.color =
+          (stxp->has_focus ? stxp->active_color : stxp->enabled_color);
+      ct.brush.color =
+      (stxp->has_focus ? stxp->active_back_color : stxp->back_color);
+  }
+  else
+  {
+    /* draw disabled cells with grey background */
+    ct.fore_color = ct.pen.color = stxp->disabled_color;
+    ct.brush.color = stxp->disabled_back_color;
+  }
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  rct2 = rct;
+  if ((stxp->attrib & XI_ATR_FOCUSBORDER) || (! (stxp->attrib & XI_ATR_BORDER)))
+  {
+    if (! stxp->has_focus)
+    {
+      static XI_OBJ *itf;
+      COLOR back_color;
+
+      ct.pen = black_cpen;
+      itf = xi_get_itf(stxp->win);
+      back_color = itf->v.itf->back_color;
+      if (back_color)
+      ct.pen.color = back_color;
+      else
+      ct.pen.color = xi_get_pref(XI_PREF_COLOR_CTRL);
+    }
+  }
+
+  /* TODO only draw inside only if not well or plat */
+  if (! stxp->well && ! stxp->platform)
+    if ((! (stxp->attrib & XI_ATR_FOCUSBORDER)) && (! (stxp->attrib & XI_ATR_BORDER)))
+    {
+      ct.pen = hollow_cpen;
+      inside_only = TRUE;
+    }
+
+  xi_set_draw_ctools(stxp->win, &ct);
+
+  /* TODO moved following two lines down */
+  if (stxp->well || stxp->platform)
+    xi_set_cbrush(stxp->win, &hollow_cbrush);
+
+  xi_set_xvt_font(stxp->win, ct_font, FALSE);
+  if (inside_only)
+    xi_inflate_rect(&rct2, -1);
+  rr = rct2;
+  xi_set_clip(stxp->win, NULL);
+  xi_draw_rect(stxp->win, &rr);
+  if (stxp->well || stxp->platform)
+  {
+    RCT r;
+
+    r = rct2;
+    if (!inside_only)
+      xi_inflate_rect(&r, -1);
+    xi_draw_3d_rect(stxp->win, &r, stxp->well, 1, stxp->hilight_color,
+      stxp->attrib & XI_ATR_ENABLED ? stxp->back_color : stxp->disabled_back_color, stxp->shadow_color);
+  }
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  ct.back_color = xi_get_itf(stxp->win)->v.itf->back_color;
+  xi_set_draw_ctools(stxp->win, &ct);
+  xi_set_xvt_font(stxp->win, ct_font, FALSE);
+  if (STX_HAS_BORDER(stx))
+  {
+    xi_draw_text(stxp->win, rct.left, rct.bottom, CHR_LEFTBRACKET, -1);
+    xi_draw_text(stxp->win, rct.right - 8, rct.bottom, CHR_RIGHTBRACKET, -1);
+  }
+  if (STX_IS_ENABLED(stx))
+    xi_set_xvt_back_color(stxp->win, stxp->back_color);
+  else
+    xi_set_xvt_back_color(stxp->win, stxp->disabled_back_color);
+  {
+      RCT r;
+
+      r = rct;
+      if (STX_HAS_BORDER(stx))
+      {
+        r.right -= 8;
+        r.left += 8;
+      }
+      xi_draw_rect(stxp->win, &r);
+    }
+    CTOS_END;
+#endif
+    if (stxp->has_focus)
+      txt_redraw(stxp->txt, FALSE);
+    else
+    {
+      /* draw cell text */
+      get_text_rect(stx, &rct);
+      xi_draw_clipped_text(stxp->win, stxp->text, &rct, &rct, stxp->attrib,
+          TRUE, 0, -1);
+    }
+  }
+}
+
+/*
+  stx_start_edit: create a text core edit field in the position of the
+  field of interest, and copy in the necessary attributes and text from
+  the field.
+*/
+static void near
+stx_start_edit(STX stx)
+{
+  TXT_DATA *txt;
+
+  STXP(stx)->has_focus = TRUE;
+#ifndef XI_DONT_USE_TX_EDIT
+  if (STXP(stx)->use_text_edit)
+  {
+    xvt_tx_set_active(STXP(stx)->txedit);
+    xi_invalidate_rect(STXP(stx)->win, &STXP(stx)->rct);
+  }
+  else
+#endif
+    {
+      txt = STXP(stx)->txt = (TXT_DATA *)xi_tree_malloc(sizeof(TXT_DATA),
+          (char *)stx);
+      txt->rct = STXP(stx)->rct;
+      txt->parent_obj = xi_get_obj(xi_get_itf(STXP(stx)->win), STXP(stx)->cid);
+      txt->attrib = STXP(stx)->attrib | TXT_ATR_VISIBLE;
+      txt->text = STXP(stx)->text;
+      txt->text_size = STXP(stx)->text_size;
+      txt->font = &(STXP(stx)->font);
+      txt->back_color = STXP(stx)->active_back_color;
+      txt->fore_color = STXP(stx)->active_color;
+      txt->hilight_color = STXP(stx)->hilight_color;
+      txt->shadow_color = STXP(stx)->shadow_color;
+      txt->well = STXP(stx)->well;
+      txt->platform = STXP(stx)->platform;
+      txt->auto_tab = STXP(stx)->auto_tab;
+      txt->win = STXP(stx)->win;
+      txt_reset(txt);
+      if (STXP(stx)->have_mouse)
+      {
+        if ((STXP(stx)->attrib & (STX_ATR_AUTOSELECT | STX_ATR_READONLY)) ==
+            (STX_ATR_AUTOSELECT | STX_ATR_READONLY))
+          txt_set_sel(txt, 0, SHRT_MAX);
+        if ((STXP(stx)->attrib & STX_ATR_AUTOSELECT) && xi_get_pref(XI_PREF_AUTOSEL_ON_MOUSE))
+          txt_set_sel(txt, 0, SHRT_MAX);
+      }
+      else
+      {
+        if (STXP(stx)->attrib & STX_ATR_AUTOSELECT)
+          txt_set_sel(txt, 0, SHRT_MAX);
+        else
+          txt_set_sel(txt, 0, 0);
+      }
+      txt_caret(txt, TRUE);
+#if XI_IS_CH
+      CTOS_IS_CH;
+      if ((STXP(stx)->attrib & STX_ATR_AUTOSELECT) == 0)
+      txt_set_sel(txt, 0, 0);
+    CTOS_END;
+#endif
+  }
+}
+
+static void near
+stx_stop_edit(STX stx)
+{
+#ifndef XI_DONT_USE_TX_EDIT
+  if (STXP(stx)->use_text_edit)
+  {
+  WINDOW win;
+
+  STXP(stx)->has_focus = FALSE;
+  win = STXP(stx)->win;
+#if XVTWS == WINWS
+  { PNT _p; _p.h =  -100; _p.v =  -100;
+    xvt_win_set_caret_pos(win, _p);
+    xvt_win_set_caret_visible(win, TRUE); };
+#endif
+  xi_caret_off(win);
+  xi_invalidate_rect(win, &STXP(stx)->rct);
+  }
+  else
+#endif
+  {
+    txt_hide_caret(STXP(stx)->txt);
+    txt_caret(STXP(stx)->txt, FALSE);
+    xi_tree_free((char *)STXP(stx)->txt);
+      STXP(stx)->txt = NULL;
+    STXP(stx)->has_focus = FALSE;
+      redraw_stx(stx, FALSE, FALSE);
+    }
+}
+
+/*
+  do_stx_cb: handles the STX_CB_CHAR, STX_CB_CHANGE, STX_CB_FOCUS cases.
+*/
+static BOOLEAN near
+do_stx_cb(STX stx, STX_CB_TYPE cb_reason, EVENT *ep)
+{
+  STX_CB_DATA stx_cb_data;
+
+  stx_cb_data.stx = stx;
+  stx_cb_data.cb_type = cb_reason;
+  stx_cb_data.cid = STXP(stx)->cid;
+  stx_cb_data.win = STXP(stx)->win;
+  if (cb_reason == STX_CB_CHAR)
+  {
+    stx_cb_data.v.chr.ch = ep->v.chr.ch;
+    stx_cb_data.v.chr.shift = ep->v.chr.shift;
+    stx_cb_data.v.chr.control = ep->v.chr.control;
+    stx_cb_data.v.chr.is_paste = FALSE;
+    stx_cb_data.v.chr.refused = FALSE;
+  } else
+    stx_cb_data.v.refused = FALSE;
+  (*STXP(stx)->stx_cb)(&stx_cb_data);
+  /* retval = FALSE if event refused */
+  if (cb_reason == STX_CB_CHAR)
+  {
+    if (! stx_cb_data.v.chr.refused)
+      ep->v.chr.ch = stx_cb_data.v.chr.ch;
+    return (! stx_cb_data.v.chr.refused);
+  }
+  else
+    return (! stx_cb_data.v.refused);
+}
+
+void
+stx_focus_cb(long stx, BOOLEAN set)
+{
+  xvt_errmsg_sig_if(!(set != STXP(stx)->has_focus),
+    NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "30101",
+    30101, "Internal focus error");
+  if (set)
+  stx_start_edit(stx);
+  else
+  stx_stop_edit(stx);
+}
+
+/*
+The parameter gaining_focus is here so that on an E_MOUSE_DOWN, if the
+field is gaining the focus, and XI_PREF_AUTOSEL_ON_MOUSE is TRUE, then
+txt_event knows to select the entire field, not set an insertion point.
+*/
+static BOOLEAN near
+send_txt_event(STX stx, TXT_DATA *txt, EVENT *ep,
+BOOLEAN gaining_focus)
+{
+  BOOLEAN retval;
+  int ch;
+
+  if (ep->type == E_CHAR)
+  {
+    ch = ep->v.chr.ch;
+    if ((ch >= ' ' || ch == K_CLEAR || ch == K_DEL ||
+        ch == '\b') && ch != K_BTAB && ch != K_UP && ch != K_DOWN)
+    {
+      retval = do_stx_cb(stx, STX_CB_CHAR, ep);
+      /* retval = FALSE if event refused */
+      if (! retval)
+        return FALSE;
+    }
+  }
+#ifndef XI_DONT_USE_TX_EDIT
+  if (STXP(stx)->use_text_edit)
+  {
+    EVENT e;
+
+    e = *ep;
+    if (ep->type == E_CHAR && (ep->v.chr.ch == '\t' || ep->v.chr.ch == K_BTAB))
+      retval = FALSE;
+    else
+    {
+      if (xi_get_pref(XI_PREF_TRIPLE_CLICK_TIME))
+      {
+        if (ep->type == E_MOUSE_DBL)
+        {
+          STXP(stx)->timer_id = xvt_timer_create(STXP(stx)->win,
+              xi_get_pref(XI_PREF_TRIPLE_CLICK_TIME));
+          STXP(stx)->timer_set = TRUE;
+        }
+      }
+      if (ep->type == E_TIMER &&
+          ep->v.timer.id == STXP(stx)->timer_id)
+      {
+        xvt_timer_destroy(ep->v.timer.id);
+        STXP(stx)->timer_id = 0;
+        STXP(stx)->timer_set = FALSE;
+      }
+      if (ep->type == E_MOUSE_DOWN &&
+          STXP(stx)->timer_set)
+      {
+        xvt_timer_destroy(STXP(stx)->timer_id);
+        STXP(stx)->timer_set = FALSE;
+        STXP(stx)->timer_id = 0;
+        stx_set_sel(stx, 0, 32000);
+        return FALSE;
+      }
+      if (ep->type == E_UPDATE)
+        draw_text_edit_border(STXP(stx));
+      if (ep->type != E_COMMAND)
+        retval = xvt_tx_process_event(STXP(stx)->win, &e);
+      if (ep->type == E_COMMAND && xi_get_pref(XI_PREF_MULTILINE_QUICK_PASTE))
+        retval = xvt_tx_process_event(STXP(stx)->win, &e);
+      if ( retval )
+      {
+        ((XI_OBJ*)STXP(stx)->app_data)->itf->v.itf->chg_flag = TRUE;
+        do_stx_cb( stx, STX_CB_CHANGE, ep );
+      }
+    }
+  }
+  else
+#endif
+    {
+      retval = txt_event(txt, ep, gaining_focus);
+
+      /* check flags */
+      if (txt->flags & TXT_FLAG_TEXT)
+      {
+        ((XI_OBJ*)STXP(stx)->app_data)->itf->v.itf->chg_flag = TRUE;
+        do_stx_cb(stx, STX_CB_CHANGE, ep);
+      }
+      /* reset flags */
+      txt->flags = 0;
+    }
+  return(retval);
+}
+
+BOOLEAN
+stx_event(STX stx, EVENT *ep)
+{
+  STX_DATA *stxp = STXP(stx);
+  BOOLEAN retval = TRUE;
+
+  switch(ep->type)
+  {
+  case E_SIZE:
+    retval = FALSE;
+    break;
+  case E_TIMER:
+    if (stxp->txt)
+      send_txt_event(stx, stxp->txt, ep, FALSE);
+    retval = FALSE;
+    break;
+  case E_UPDATE:
+#ifndef XI_DONT_USE_TX_EDIT
+    if (stxp->use_text_edit)
+    {
+      if ((stxp->attrib & STX_ATR_VISIBLE) != 0)
+      {
+        EVENT e;
+        CBRUSH cbrush;
+        RCT r;
+
+        e = *ep;
+        if (ep->type == E_UPDATE)
+          draw_text_edit_border(STXP(stx));
+        cbrush.color = STXP(stx)->back_color;
+        cbrush.pat = PAT_SOLID;
+        xi_set_cbrush(STXP(stx)->win, &cbrush);
+        xi_set_cpen(STXP(stx)->win, &hollow_cpen);
+        r = STXP(stx)->rct;
+        if (STXP(stx)->attrib & XI_ATR_BORDER || STXP(stx)->attrib & XI_ATR_FOCUSBORDER)
+          xi_inflate_rect(&r, -1);
+        xi_inflate_rect(&r, -2);
+        xi_draw_rect(STXP(stx)->win, &r);
+        xvt_tx_process_event(stxp->win, &e);
+      }
+    }
+    else
+#endif
+      redraw_stx(stx, TRUE, FALSE);
+    retval = FALSE;
+    break;
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+    {
+      BOOLEAN gaining_focus = FALSE;
+
+      /* check for focus acquisition */
+      if (xvt_rect_has_point(&stxp->rct, ep->v.mouse.where) &&
+          (stxp->attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) ==
+          (XI_ATR_ENABLED | XI_ATR_VISIBLE))
+      {
+        stxp->have_mouse = TRUE;
+        if (!STXP(stx)->has_focus)
+        {
+          if (!do_stx_cb(stx, STX_CB_FOCUS, ep))
+          {
+            stxp->have_mouse = FALSE;
+            break;
+          }
+          gaining_focus = TRUE;
+        }
+        /* the stx may have lost the focus, due to a field being
+          disabled, in which case, stxp->txt == NULL */
+        if (stxp->txt || stxp->use_text_edit)
+        {
+          send_txt_event(stx, stxp->txt, ep, gaining_focus);
+          if (stxp->txt)
+            xi_trap_mouse(stxp->win);
+          if (ep->type == E_MOUSE_DBL)
+            do_stx_cb(stx, STX_CB_DBL, ep);
+        }
+      }
+      else
+        retval = FALSE;
+      break;
+    }
+  case E_MOUSE_UP:
+    if (stxp->has_focus)
+    {
+      send_txt_event(stx, stxp->txt, ep, FALSE);
+      xi_release_mouse();
+      stxp->have_mouse = FALSE;
+    }
+    break;
+  case E_MOUSE_MOVE:
+    {
+      unsigned long attrib;
+
+      if (stxp->has_focus)
+        send_txt_event(stx, stxp->txt, ep, FALSE);
+      attrib = stxp->attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE);
+      if ((attrib != (XI_ATR_ENABLED | XI_ATR_VISIBLE)) ||
+          (! xvt_rect_has_point(&stxp->rct, ep->v.mouse.where)))
+        retval = FALSE;
+      break;
+    }
+  case E_CHAR:
+    retval = send_txt_event(stx, stxp->txt, ep, FALSE);
+    break;
+  case E_KILL_WINDOW:
+    retval = FALSE;
+    break;
+  case E_COMMAND:
+    retval = send_txt_event(stx, stxp->txt, ep, FALSE);
+    break;
+  }
+  return(retval);
+}
+
+unsigned long
+stx_get_attrib(STX stx)
+{
+  return(STXP(stx)->attrib);
+}
+
+int
+stx_get_cid(STX stx)
+{
+  return(STXP(stx)->cid);
+}
+
+void
+stx_get_sel(STX stx, int *c1, int *c2)
+{
+#ifndef XI_DONT_USE_TX_EDIT
+  if (STXP(stx)->use_text_edit)
+  {
+    int accum_cnt;
+    T_PNUM par;
+    T_PNUM start_par, end_par;
+    T_LNUM start_line, end_line;
+    T_CNUM start_char, end_char;
+    BOOLEAN ex;
+
+    accum_cnt = 0;
+    xvt_tx_get_sel(STXP(stx)->txedit, &start_par, &start_line, &start_char,
+        &end_par, &end_line, &end_char);
+    ex = FALSE;
+    for (par = 0; par <= start_par; par++)
+    {
+      T_LNUM nbr_lins, lin;
+
+      nbr_lins = xvt_tx_get_num_par_lines(STXP(stx)->txedit, par);
+      for (lin = 0; lin < nbr_lins; lin++)
+      {
+        if (par == start_par && lin == start_line)
+        {
+          accum_cnt += start_char;
+          ex = TRUE;
+          break;
+        }
+        accum_cnt += xvt_tx_get_num_chars(STXP(stx)->txedit, par, lin);
+      }
+      if (ex)
+        break;
+      accum_cnt   += 1;   /* add eol at end of paragraph */
+    }
+    *c1 = accum_cnt;
+    if (start_par == end_par && start_line == end_line &&
+        start_char == end_char)
+    {
+      *c2 = accum_cnt;
+      return;
+    }
+    ex = FALSE;
+    for (par = start_par; par <= end_par; par++)
+    {
+      T_LNUM nbr_lins, lin;
+
+      nbr_lins = xvt_tx_get_num_par_lines(STXP(stx)->txedit, par);
+      for (lin = 0; lin < nbr_lins; lin++)
+      {
+        if (par == end_par && lin == end_line)
+        {
+          accum_cnt += end_char;
+          if (par == start_par && lin == start_line)
+            accum_cnt -= start_char;
+          ex = TRUE;
+          break;
+        }
+        accum_cnt += xvt_tx_get_num_chars(STXP(stx)->txedit, par, lin);
+        if (par == start_par && lin == start_line)
+          accum_cnt -= start_char;
+      }
+      if (ex)
+        break;
+      accum_cnt   += 1;   /* add eol at end of paragraph */
+    }
+    *c2 = accum_cnt;
+    return;
+  }
+#endif
+  if (STXP(stx)->has_focus)
+  {
+    *c1 = STXP(stx)->txt->selstart;
+    *c2 = STXP(stx)->txt->selstop;
+  }
+  else
+    *c1 = *c2 = 0;
+}
+
+RCT *
+stx_get_rect(STX stx, RCT *rct)
+{
+  *rct = STXP(stx)->rct;
+  return(rct);
+}
+
+#ifndef XI_DONT_USE_TX_EDIT
+static void
+tx_get_text(TXEDIT tx, char *string, int string_len)
+{
+  char *s;
+  int slen, cnt, nbr_pars;
+  unsigned len;
+
+  slen = 0;
+  s = NULL;
+  nbr_pars = xvt_tx_get_num_pars(tx);
+  for (cnt = 0; cnt < nbr_pars; ++cnt)
+  {
+    int nbr_lines, cnt2;
+
+    nbr_lines = xvt_tx_get_num_par_lines(tx, (short)cnt);
+    for (cnt2 = 0; cnt2 < nbr_lines; ++cnt2)
+    {
+      char *str;
+      int old_len;
+
+      xvt_tx_get_line(tx, (short)cnt, A_LOCK, (short)cnt2, NULL);
+      str = xvt_tx_get_line(tx, (short)cnt, A_GET, (short)cnt2, &len);
+      old_len = slen;
+      slen = slen + len;
+      if (s)
+        s = (char *)xi_tree_realloc(s, slen + 2);
+      else
+        s = (char *)xi_tree_malloc(slen + 2, NULL);
+
+      gstrncpy(&s[old_len], str, len);
+    }
+    slen++;
+#if XIWS == MACWS
+    s[slen - 1] = '\r';
+#else
+    s[slen - 1] = '\n';
+#endif
+  }
+  if (! slen)
+    string[0] = '\0';
+  else
+  {
+    s[slen - 1] = '\0';
+    gstrncpy(string, s, string_len);
+    string[string_len - 1] = '\0';
+    xi_tree_free(s);
+  }
+}
+
+static int
+tx_get_len(TXEDIT tx)
+{
+  int nbr_pars, cnt, charcnt;
+
+  charcnt = 0;
+  nbr_pars = xvt_tx_get_num_pars(tx);
+  for (cnt = 0; cnt < nbr_pars; ++cnt)
+  {
+    int nbr_lines, cnt2;
+
+    nbr_lines = xvt_tx_get_num_par_lines(tx, (short)cnt);
+    for (cnt2 = 0; cnt2 < nbr_lines; ++cnt2)
+      charcnt += (xvt_tx_get_num_chars(tx, (short)cnt, (short)cnt2) + 1);
+  }
+  return charcnt;
+}
+#endif
+
+char *
+stx_get_text(STX stx, char *s, int len)
+{
+  char *b;
+#ifndef XI_DONT_USE_TX_EDIT
+
+  if (STXP(stx)->use_text_edit)
+  {
+    if (s)
+    {
+      tx_get_text(STXP(stx)->txedit, s, len);
+      b = s;
+    }
+    else
+    {
+      int len;
+
+      len = tx_get_len(STXP(stx)->txedit);
+      if (STXP(stx)->buf)
+        STXP(stx)->buf = (char*)xi_tree_realloc(STXP(stx)->buf, len);
+      else
+        STXP(stx)->buf = (char*)xi_tree_malloc(len, NULL);
+      tx_get_text(STXP(stx)->txedit, STXP(stx)->buf, len);
+      b = STXP(stx)->buf;
+    }
+  }
+  else
+#endif
+    b = STXP(stx)->text;
+  if (s)
+    tgstrncpy(s, b, len);
+  return b;
+}
+
+void
+stx_set_bufsize(STX stx, short size)
+{
+  /*
+  TODO
+  if (STXP(stx)->use_text_edit)
+    set buffer size
+  */
+  STXP(stx)->text = (char *)xi_tree_realloc(STXP(stx)->text, (size_t)size);
+  STXP(stx)->text[size - 1] = '\0';
+  STXP(stx)->text_size = size;
+}
+
+void
+stx_set_attrib(STX stx, unsigned long attrib)
+{
+  unsigned long do_redraw;
+
+  if (STXP(stx)->use_text_edit)
+  {
+    if (attrib & XI_ATR_VISIBLE)
+    {
+      if (!(STXP(stx)->attrib & XI_ATR_VISIBLE))
+        xvt_tx_resume(STXP(stx)->txedit);
+    } else
+    {
+      if (STXP(stx)->attrib & XI_ATR_VISIBLE)
+        xvt_tx_suspend(STXP(stx)->txedit);
+    }
+  }
+
+  do_redraw = ((STXP(stx)->attrib ^ attrib) & STX_REDRAW_ATR);
+  STXP(stx)->attrib = attrib;
+  if (do_redraw)
+    xi_invalidate_rect(STXP(stx)->win, &(STXP(stx)->rct));
+}
+
+void
+stx_set_focus(STX stx)
+{
+  if (xvt_scr_get_focus_vobj()!= STXP(stx)->win)
+  {
+  xvt_scr_set_focus_vobj(STXP(stx)->win);
+  }
+  if (!STXP(stx)->has_focus)
+  stx_start_edit(stx);
+}
+
+void
+stx_set_pos(STX stx, PNT p)
+{
+  int dh, dv;
+
+  dh = p.h - STXP(stx)->rct.left;
+  dv = p.v - STXP(stx)->rct.top;
+
+  STXP(stx)->rct.top += dv;
+  STXP(stx)->rct.left += dh;
+  STXP(stx)->rct.bottom += dv;
+  STXP(stx)->rct.right += dh;
+}
+
+void
+stx_set_sel(STX stx, int c1, int c2)
+{
+#ifndef XI_DONT_USE_TX_EDIT
+  if (STXP(stx)->use_text_edit)
+  {
+    int         accum_cnt, selidx;
+    int         sel[2];
+    T_PNUM      parsel[2], par, nbr_pars;
+    T_LNUM      linsel[2], lin, nbr_lins;
+    T_CNUM      chrsel[2], nbr_chrs;
+
+    accum_cnt   = 0;
+    selidx      = 0;
+    sel[0]      = c1;
+    sel[1]      = c2;
+    nbr_pars    = xvt_tx_get_num_pars(STXP(stx)->txedit);
+    for (par = 0; par < nbr_pars; par++)
+    {
+      nbr_lins = xvt_tx_get_num_par_lines(STXP(stx)->txedit, par);
+      for (lin = 0; lin < nbr_lins; lin++)
+      {
+        nbr_chrs    = xvt_tx_get_num_chars(STXP(stx)->txedit, par, lin);
+        while ((int)(accum_cnt + nbr_chrs) >= sel[selidx])
+        {
+          parsel[selidx]  = par;
+          linsel[selidx]  = lin;
+          chrsel[selidx]  = sel[selidx] - accum_cnt;
+          selidx++;
+          if (selidx >= 2)
+            goto set_sel;
+        }
+        accum_cnt   += nbr_chrs;
+      }
+      accum_cnt   += 1;   /* add eol at end of paragraph */
+    }
+    while (selidx < 2)
+    {
+      parsel[selidx]  = nbr_pars-1;
+      linsel[selidx]  = nbr_lins-1;
+      chrsel[selidx]  = nbr_chrs-1;
+      if (selidx == 1)
+        chrsel[selidx] = nbr_chrs;
+      selidx++;
+    }
+set_sel:
+    xvt_tx_set_sel(STXP(stx)->txedit, parsel[0], linsel[0], chrsel[0],
+        parsel[1], linsel[1], chrsel[1]);
+    return;
+  }
+#endif
+  if (!STXP(stx)->has_focus)
+    stx_start_edit(stx);
+  txt_set_sel(STXP(stx)->txt, c1, c2);
+}
+
+#ifndef XI_DONT_USE_TX_EDIT
+static void do_tx_add_par(TXEDIT tx, int limit, char *text)
+{
+  char *s, *bp, *ep;
+  int cnt, nbr_pars;
+
+  nbr_pars = xvt_tx_get_num_pars(tx);
+  xvt_tx_suspend(tx);
+  for (cnt = 0; cnt < nbr_pars; ++cnt)
+    xvt_tx_rem_par(tx, 0);
+  s = (char *)xi_tree_malloc(limit + 1, NULL);
+  bp = text;
+  if (text[0] == '\0')
+  {
+    xvt_tx_add_par(tx, (unsigned short)USHRT_MAX, s);
+    xvt_tx_resume(tx);
+    xi_tree_free(s);
+    return;
+  }
+  while (TRUE)
+  {
+    int cnt, min_cnt;
+
+    if (*bp == '\0')
+      break;
+    ep = bp;
+    cnt = 0;
+    while (*ep != '\r' && *ep != '\n' && *ep != '\0')
+    {
+      ++ep;
+      ++cnt;
+    }
+    min_cnt = min(limit, cnt);
+    gstrncpy(s, bp, min_cnt);
+    s[min_cnt] = '\0';
+    xvt_tx_add_par(tx, (unsigned short)USHRT_MAX, s);
+    if (*ep == '\0')
+      break;
+    bp = ep + 1;
+  }
+  xvt_tx_resume(tx);
+  xi_tree_free(s);
+}
+#endif
+
+void
+stx_set_text(STX stx, char *s)
+{
+#ifndef XI_DONT_USE_TX_EDIT
+  if (STXP(stx)->use_text_edit)
+  {
+    do_tx_add_par(STXP(stx)->txedit, STXP(stx)->text_size, s);
+    xvt_tx_set_sel(STXP(stx)->txedit, 0, 0, 0, 0, 0, 0);
+  }
+  else
+#endif
+    {
+      if (STXP(stx)->has_focus)
+        txt_set_text(STXP(stx)->txt, s);
+      else
+      {
+        tgstrncpy(STXP(stx)->text, s, STXP(stx)->text_size);
+        if ((STXP(stx)->attrib & STX_ATR_VISIBLE) != 0
+            && !xi_half_baked(STXP(stx)->win))
+          redraw_stx(stx, FALSE, TRUE);
+      }
+    }
+}
+
+void
+stx_set_app_data(STX stx, long data)
+{
+  STXP(stx)->app_data = data;
+}
+
+long
+stx_get_app_data(STX stx)
+{
+  return(STXP(stx)->app_data);
+}
+
+/*---------------------------------------------------------------------
+function:   draw_text_edit_border
+stxptr:     
+process:    TODO
+---------------------------------------------------------------------*/
+static void
+draw_text_edit_border(STX_DATA  *stxptr)
+{
+  RCT     rct;
+
+  xi_set_draw_mode(stxptr->win, M_COPY);
+  xi_set_cpen(stxptr->win, &black_cpen);
+  xi_set_cbrush(stxptr->win, &hollow_cbrush);
+  rct = stxptr->rct;
+  if (stxptr->attrib & XI_ATR_BORDER)
+  {
+    xi_draw_rect(stxptr->win, &rct);
+    xi_inflate_rect(&rct, -1);
+  }
+  else
+  {
+    if (stxptr->attrib & XI_ATR_FOCUSBORDER)
+    {
+      COLOR pen_color;
+      CPEN cpen;
+
+      if (stxptr->has_focus)
+      {
+        pen_color = COLOR_BLACK;
+      }
+      else
+      {
+        static XI_OBJ *itf;
+        COLOR back_color;
+
+        itf = xi_get_itf(stxptr->win);
+        back_color = itf->v.itf->back_color;
+        if (back_color)
+          pen_color = back_color;
+        else
+          pen_color = xi_get_pref(XI_PREF_COLOR_CTRL);
+      }
+      cpen.color = pen_color;
+      cpen.pat = PAT_SOLID;
+      cpen.width = 1;
+      cpen.style = P_SOLID;
+      xi_set_cpen(stxptr->win, &cpen);
+      xi_draw_rect(stxptr->win, &rct);
+      xi_inflate_rect(&rct, -1);
+    }
+  }
+  if (((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK) == FALSE)
+      ||((stxptr->well == FALSE) && (stxptr->platform == FALSE)))
+    return;
+  xi_draw_3d_rect(stxptr->win, &rct, stxptr->well, 1, 0L, 0L, 0L);
+}
+
+RCT*
+stx_get_inside_rect( STX stx, RCT* rect )
+{
+  STX_DATA* stx_ptr = (STX_DATA*)stx;
+
+  *rect = stx_ptr->rct;
+  if (((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK)) &&
+      ((stx_ptr->well == TRUE) || (stx_ptr->platform == TRUE)))
+    xi_inflate_rect(rect, -2);
+  return rect;
+}
+
diff --git a/xi/xistx.h b/xi/xistx.h
new file mode 100755
index 000000000..587c21664
--- /dev/null
+++ b/xi/xistx.h
@@ -0,0 +1,139 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.                  *
+*******************************************************************************/
+
+/******************************************************************
+STX module
+******************************************************************/
+#define NULL_STX (STX)0
+
+#define STX_ATR_ENABLED   XI_ATR_ENABLED
+#define STX_ATR_EDITMENU  XI_ATR_EDITMENU
+#define STX_ATR_AUTOSELECT  XI_ATR_AUTOSELECT
+#define STX_ATR_AUTOSCROLL  XI_ATR_AUTOSCROLL
+#define STX_ATR_RJUST   XI_ATR_RJUST
+#define STX_ATR_BORDER    XI_ATR_BORDER
+#define STX_ATR_VISIBLE   XI_ATR_VISIBLE
+#define STX_ATR_READONLY  XI_ATR_READONLY
+#define STX_ATR_PASSWORD  XI_ATR_PASSWORD
+
+typedef enum
+{
+  STX_CB_CHAR,
+  STX_CB_CHANGE,
+  STX_CB_DBL,
+  STX_CB_FOCUS
+} 
+STX_CB_TYPE;
+
+typedef struct _stx_cb_data
+{
+  STX stx;
+  STX_CB_TYPE cb_type;
+  int cid;
+  WINDOW win;
+  union
+    {
+    /* nothing for change notify */
+    BOOLEAN refused;
+    struct
+        {
+      int ch;
+      BOOLEAN shift;
+      BOOLEAN control;
+      BOOLEAN is_paste;
+      BOOLEAN refused;
+    } chr;
+  } v;
+} STX_CB_DATA;
+
+typedef void (*STX_CB)(STX_CB_DATA *stx_cb_data);
+
+typedef struct _stx_def
+{
+  int cid;
+  PNT pnt;
+  short pixel_width;
+  short pix_char_width;
+  unsigned long attrib;
+  short text_size;
+  FONT_OBJ font;
+  COLOR back_color;
+  COLOR enabled_color;  /* but inactive */
+  COLOR disabled_color;
+  COLOR active_color;
+  COLOR active_back_color;
+  COLOR disabled_back_color;
+  COLOR hilight_color;    /* for well and platform fields */
+  COLOR shadow_color;   /* for well and platform fields */
+  XI_RCT xi_rct;
+  STX_CB stx_cb;
+  long app_data;
+  char *parent;
+  BOOLEAN well;
+  BOOLEAN platform;
+  BOOLEAN auto_tab;
+} STX_DEF;
+
+typedef struct _stx_data
+{
+  int cid;
+  WINDOW win;
+  RCT rct;
+  unsigned long attrib;
+  short pix_baseline;
+  FONT_OBJ font;
+  COLOR back_color;
+  COLOR enabled_color;  /* but inactive */
+  COLOR disabled_color;
+  COLOR disabled_back_color;
+  COLOR active_color;
+  COLOR active_back_color;
+  COLOR hilight_color;    /* for well and platform fields */
+  COLOR shadow_color;   /* for well and platform fields */
+  STX_CB stx_cb;
+  short text_size;
+  char *text;
+  BOOLEAN has_focus;
+  TXT_DATA *txt;
+  long app_data;
+  BOOLEAN have_mouse;
+  BOOLEAN use_text_edit;
+  TXEDIT txedit;
+  BOOLEAN well;
+  BOOLEAN platform;
+  BOOLEAN auto_tab;
+  char *buf;
+  long timer_id;
+  BOOLEAN timer_set;
+} STX_DATA;
+
+#define STX_LOSE_FOCUS NULL_STX
+
+STX     stx_create(WINDOW win, STX_DEF *stx_def);
+void    stx_delete(STX stx);
+BOOLEAN stx_event(STX stx, EVENT *ep);
+void    stx_focus_cb(long stx, BOOLEAN set);
+unsigned long stx_get_attrib(STX stx);
+int     stx_get_cid(STX stx);
+long    stx_get_app_data(STX stx);
+void    stx_get_sel(STX stx, int *c1, int *c2);
+RCT*    stx_get_rect(STX stx, RCT *rct);
+RCT*    stx_get_inside_rect( STX stx, RCT* rect );
+char*   stx_get_text(STX stx, char *s, int len);
+TXEDIT  stx_get_txedit(STX stx);
+void    stx_set_app_data(STX stx, long data);
+void    stx_set_attrib(STX stx, unsigned long attrib);
+void    stx_set_bufsize(STX stx, short size);
+void    stx_set_focus(STX stx);
+void    stx_set_pos(STX stx, PNT p);
+void    stx_set_sel(STX stx, int c1, int c2);
+void    stx_set_text(STX stx, char *s);
+
+
+
+
+
diff --git a/xi/xitext.c b/xi/xitext.c
new file mode 100755
index 000000000..17a51ca77
--- /dev/null
+++ b/xi/xitext.c
@@ -0,0 +1,1419 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#define XI_INTERNAL
+
+#include "xi.h"
+#include "xitext.h"
+#include "xiutils.h"
+#include "xilm.h"
+#include <ctype.h>
+
+#if XIWS == MTFWS
+#include <X11/Xatom.h>
+#include <X11/StringDefs.h>
+#include <X11/Intrinsic.h>
+#endif
+
+/* Error codes 30200-30206 */
+
+#define TXT_REDRAW_ATR (TXT_ATR_RJUST | TXT_ATR_ENABLED | TXT_ATR_BORDER | TXT_ATR_VISIBLE)
+#define TXT_ACTIVE_ATR (TXT_ATR_ENABLED | TXT_ATR_VISIBLE)
+#define BS 8
+
+#if XVT_OS == XVT_OS_CTOS
+#define BORDER_WIDTH_X ((npctos_env == CHSERVICE) ? 8 : 1)
+#define BORDER_WIDTH_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#define BORDER_SPACE_X ((npctos_env == CHSERVICE) ? 0 : 1)
+#define BORDER_SPACE_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#define CHR_LEFTBRACKET "["
+#define CHR_RIGHTBRACKET "]"
+#else
+#if XIWS != WMWS
+#define BORDER_WIDTH_X 1
+#define BORDER_WIDTH_Y 1
+#define BORDER_SPACE_X 1
+#define BORDER_SPACE_Y 1
+#else
+#define BORDER_WIDTH_X 8
+#define BORDER_WIDTH_Y 0
+#define BORDER_SPACE_X 0
+#define BORDER_SPACE_Y 0
+#define CHR_LEFTBRACKET "["
+#define CHR_RIGHTBRACKET "]"
+#endif
+#endif
+
+
+#ifndef NO_PRIMARY_SELECTION
+#if XIWS == MTFWS
+/* statics used for implementing cut, copy & paste with the PRIMARY selection */
+static char *primesel_text = NULL;    /* text for primary selection */
+static int primesel_len;        /* length of primary selection */
+static Widget primesel_widget = NULL; /* widget owning primary selection */
+
+/*  deliver_primesel - this functions delivers the value of the primary
+  selection when another application or something else in this application
+  requests it
+*/
+static Boolean
+deliver_primesel(Widget widget, Atom *selection, Atom *target,
+Atom *type, XtPointer *value, unsigned long *length, int *format)
+{
+  static Atom xa_targets = 0;
+  XrmValue source, dest;
+
+  /* printf("deliver_primesel: ENTERED, widget %d, selection %d, target %d\n",
+    widget, *selection, *target); */
+
+  /* get value for Atom "TARGETS" */
+  if (xa_targets == 0)
+  {
+    source.size = strlen("TARGETS") + 1;
+    source.addr = "TARGETS";
+    dest.size = sizeof(Atom);
+    dest.addr = (XtPointer) &xa_targets;
+    (void) XtConvertAndStore(primesel_widget, XtRString, &source, XtRAtom,
+        &dest);
+  }
+
+  /* handle request for PRIMARY selection as a string */
+  if (*target == XA_STRING)
+  {
+    *type = XA_STRING;
+    *value = (XtPointer) XtNewString(primesel_text);
+    *length = primesel_len;
+    *format = 8;
+    /* printf("deliver_primesel: RETURNING primary selection '%s'\n",
+      primesel_text); */
+    return(TRUE);
+  }
+
+  /* handle request for TARGETS */
+  if (*target == xa_targets)
+  {
+    /* printf("deliver_primesel: RETURNING targets \n"); */
+    *type = XA_ATOM;
+    *value = (XtPointer) XtNew(Atom);
+    *(Atom *) *value = XA_STRING;
+    *length = 1;
+    *format = 32;
+    return(TRUE);
+  }
+
+  /* anything else return FALSE */
+  /* printf("deliver_primesel: RETURNING FALSE\n"); */
+  return(FALSE);
+}
+
+void clean_primesel()
+{
+  if (primesel_text)
+  xvt_mem_free(primesel_text);
+}
+
+/*
+  lose_primesel - this function is called by the Intrinsics when
+  the primary selection is lost to another application
+*/
+static void
+lose_primesel(Widget widget, Atom *selection)
+{
+  /* printf("lose_primesel: ENTERED, widget %d, selection %d\n", */
+  /*  widget, *selection); */
+  primesel_widget = NULL;
+  if (primesel_text)
+  xvt_mem_free(primesel_text);
+  primesel_text = NULL;
+}
+
+void  xi_widgetDestroyCallBack(Widget w, XtPointer closure, XtPointer data)
+{
+  /* need to define a local Atom bcos lose_primesel expects it */
+  Atom garbageAtom;
+  lose_primesel(w, &garbageAtom);
+}
+
+/*
+  set_primary_selection - this function sets or clears the primary selection
+*/
+static void
+set_primary_selection(WINDOW win, char *txt, int len)
+{
+  Widget widget;
+  Time time;
+
+  /* printf("set_primary_selection: ENTERED, win %d, len %d\n", win, len); */
+
+  /* check if clearing selection */
+  if (len == 0)
+  {
+#if 0
+    /* The following clears the selection if an insertion point is set. */
+    if (primesel_widget != NULL)
+    {
+      /* printf("set_primary_selection: clearing selection\n"); */
+      XtDisownSelection(primesel_widget, XA_PRIMARY,
+          XtLastTimestampProcessed(XtDisplay(primesel_widget)));
+      xvt_mem_free(primesel_text);
+      primesel_text = NULL;
+      primesel_widget = NULL;
+    }
+#endif
+    return;
+  }
+
+  /* allocate space and save text string */
+  primesel_text = xvt_mem_alloc(len + 1);
+  /* xvt_errmsg_sig_if not NULL "out of memory" */
+  strncpy(primesel_text, txt, len);
+  primesel_text[len] = '\0';
+  primesel_len = len;
+
+  /* get widget and selection time */
+  widget = (Widget) xvt_vobj_get_attr(win, ATTR_X_WIDGET);
+  time = XtLastTimestampProcessed(XtDisplay(widget));
+
+  /* try to take ownership of the primary selection */
+  /* printf("set_primary_selection: before XtOwnSelection\n"); */
+  /* printf("                       widget %d, text '%s', len %d, time %d\n",
+    widget, primesel_text, primesel_len, time); */
+  if (XtOwnSelection(widget, XA_PRIMARY, time, deliver_primesel,
+      lose_primesel, NULL))
+  {
+    /* printf("set_primary_selection: XtOwnSelection SUCCESSFUL\n"); */
+
+    XtAddCallback(widget, XtNdestroyCallback, xi_widgetDestroyCallBack,
+        (XtPointer)NULL);
+
+    primesel_widget = widget;
+  }
+  else
+  {
+    /* printf("set_primary_selection: XtOwnSelection FAILED\n"); */
+    xvt_mem_free(primesel_text);
+    primesel_text = NULL;
+  }
+
+}
+#endif
+#endif
+
+#if defined(NO_PRIMARY_SELECTION) || XIWS != MTFWS
+static void
+set_primary_selection(WINDOW win, char *txt, int len)
+{
+  NOREF(win);
+  NOREF(txt);
+  NOREF(len);
+}
+#endif
+
+#if XIWS == PMWS
+#define recalc_hit_test(a)
+#else
+
+static void
+recalc_hit_test(TXT_DATA *txt)
+{
+  int i;
+  char *s;
+  short *h;
+
+  if (! txt->hit_test)
+    txt->hit_test = (short *)xi_tree_malloc(txt->text_size * sizeof(short), txt);
+
+  xi_set_xvt_font(txt->win, txt->font, FALSE);
+  for (i = 0, s = txt->text, h = txt->hit_test; i < txt->len;
+      i++, s++, h++)
+    *h = (short)xi_get_text_width(txt->win, s, 1, txt->attrib);
+}
+
+#endif
+
+static int
+stx_get_text_width(TXT_DATA *txt, short *hit_test, char *text, int len)
+{
+#if XIWS == PMWS
+  NOREF(hit_test);
+  return xi_get_text_width(txt->win, text, len, txt->attrib);
+#else
+  int c, r;
+  short *s;
+
+  NOREF(txt);
+  NOREF(text);
+  r = 0;
+  for (c = 0, s = hit_test; c < len; ++c, ++s)
+    r += *s;
+  return r;
+#endif
+}
+
+
+static DRAW_CTOOLS * near
+get_txt_ctools(TXT_DATA *txt, DRAW_CTOOLS *ct, FONT_OBJ *font,
+BOOLEAN do_border, BOOLEAN inverted)
+{
+  COLOR fore_color, back_color;
+
+  if (inverted)
+  {
+    fore_color = txt->back_color;
+    if (! txt->hilight_color && (txt->well || txt->platform))
+      fore_color = xi_get_pref(XI_PREF_COLOR_CTRL);
+    back_color = txt->fore_color;
+  }
+  else
+  {
+    back_color = txt->back_color;
+    if (! txt->hilight_color && (txt->well || txt->platform))
+      back_color = xi_get_pref(XI_PREF_COLOR_CTRL);
+    fore_color = txt->fore_color;
+  }
+
+  xvt_app_get_default_ctools(ct);
+  ct->pen.color = ct->fore_color = fore_color;
+  ct->back_color = ct->brush.color = back_color;
+  ct->pen.width = do_border ? 1 : 0;
+#if XI_IS_CH
+  CTOS_IS_CH;
+  ct->pen.pat = PAT_HOLLOW;
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  ct->pen.pat = do_border ? PAT_SOLID : PAT_HOLLOW;
+  CTOS_END;
+#endif
+  ct->opaque_text = TRUE;
+  *font = *txt->font;
+  ct->mode = M_COPY;
+  return(ct);
+}
+
+static RCT * near
+get_txt_clip_rect(TXT_DATA *txt, RCT *rct)
+{
+#if XI_IS_CH
+  BOOLEAN do_border;
+
+  CTOS_IS_CH;
+  do_border = (BOOLEAN)(txt->attrib & XI_ATR_BORDER);
+  CTOS_END;
+#endif
+  *rct = txt->rct;
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  xi_inflate_rect(rct, -2);
+  CTOS_END;
+#endif
+  if (txt->inside_only)
+  {
+    rct->top -= BORDER_SPACE_Y;
+    rct->bottom += BORDER_SPACE_Y;
+  }
+#if XI_IS_CH
+  CTOS_IS_CH;
+  if (do_border)
+  {
+    rct->right -= 8;
+    rct->left += 8;
+  }
+  CTOS_END;
+#endif
+  return(rct);
+}
+
+static void near
+get_txt_positions(TXT_DATA *txt, int *ip1, int *ip2, int *clipleft,
+int *clipright)
+{
+  RCT rct;
+
+  xi_set_xvt_font(txt->win, txt->font, FALSE);
+  get_txt_clip_rect(txt, &rct);
+  xvt_errmsg_sig_if(!(txt->selstart <= txt->len), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"30201",
+    30201, "Internal TEXT error");   
+  *ip1 = txt->string_xpos + stx_get_text_width(txt, txt->hit_test, txt->text, 
+      txt->selstart);
+  *ip2 = *ip1 + stx_get_text_width(txt, txt->hit_test + txt->selstart,
+      txt->text + txt->selstart, txt->selstop - txt->selstart);
+  *clipleft = rct.left;
+  *clipright = rct.right;
+}
+
+void
+txt_display_caret(TXT_DATA *txt)
+{
+  int clipleft, clipright, caretpos1, caretpos2;
+  int height1, height2, pos1, pos2;
+
+  if (!txt->hasfocus)
+    return;
+  get_txt_positions(txt, &caretpos1, &caretpos2, &clipleft, &clipright);
+  if (caretpos1 == caretpos2 && caretpos1 <= clipright &&
+      caretpos2 >= clipleft)
+  {
+#if XIWS == MTFWS
+    {
+      /* ugly hack for XVT/XM so that caret will get displayed. */
+      RCT rct;
+      DRAW_CTOOLS new_ctools;
+      FONT_OBJ new_font;
+
+      xi_set_draw_ctools(txt->win, get_txt_ctools(txt, &new_ctools,
+          &new_font, FALSE, FALSE));
+      xi_set_xvt_font(txt->win, &new_font, FALSE);
+      get_txt_clip_rect(txt, &rct);
+      rct.right++;
+      xi_set_clip(txt->win, &rct);
+      if (txt->attrib & TXT_ATR_RJUST)
+        xi_draw_text_attrib(txt->win, txt->string_xpos, txt->pix_baseline, txt->text,
+            txt->len - txt->scroll_pos, txt->attrib);
+      else
+        xi_draw_text_attrib(txt->win, rct.left, txt->pix_baseline,
+            txt->text + txt->scroll_pos, -1, txt->attrib);
+    }
+#endif
+    height1 = txt->rct.bottom - txt->rct.top - 2;
+    if ( height1 < 1 )
+      height1 = 1;
+    height2 = txt->ascent + txt->descent;
+    height1 = min(height1, height2);
+    pos1 = txt->pix_baseline + txt->descent;
+    pos2 = txt->rct.bottom - 1;
+    pos1 = min(pos1, pos2);
+    xi_caret_on(txt->win, caretpos1, pos1, height1);
+  }
+  else
+    xi_caret_off(txt->win);
+}
+
+static void near
+recalc_string_xpos(TXT_DATA *txt)
+{
+  RCT rct;
+  int wid;
+
+  xi_set_xvt_font(txt->win, txt->font, FALSE);
+  get_txt_clip_rect(txt, &rct);
+  if (txt->scroll_pos > txt->len)
+    txt->scroll_pos = txt->len;
+  xvt_errmsg_sig_if(!(txt->selstart <= txt->len), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"30202",
+    30202, "Internal TEXT error");   
+  if (txt->attrib & TXT_ATR_RJUST)
+  {
+    wid = stx_get_text_width(txt, txt->hit_test,
+        txt->text, txt->len - txt->scroll_pos);
+    txt->string_xpos = rct.right - wid;
+  }
+  else
+  {
+    /* left justified */
+    wid = stx_get_text_width(txt, txt->hit_test, txt->text, txt->scroll_pos);
+    txt->string_xpos = rct.left - wid;
+  }
+}
+
+void
+txt_hide_caret(TXT_DATA *txt)
+{
+  xi_caret_off(txt->win);
+}
+
+void
+txt_redraw(TXT_DATA *txt, BOOLEAN inside_only)
+{
+  DRAW_CTOOLS new_ctools;
+  FONT_OBJ new_font;
+  RCT rct;
+  RCT clip_r;
+  BOOLEAN do_border;
+  int ip1, ip2, clipleft, clipright;
+  long tattrib = txt->attrib;
+#if XI_IS_CH
+  RCT r;
+#endif
+
+#if XI_IS_CH
+  NOREF(clip_r);
+#endif
+  txt_hide_caret(txt);
+  do_border = ((tattrib & (TXT_ATR_BORDER | TXT_ATR_VISIBLE)) ==
+      (TXT_ATR_BORDER | TXT_ATR_VISIBLE));
+  get_txt_positions(txt, &ip1, &ip2, &clipleft, &clipright);
+  rct = txt->rct;
+  if (inside_only)
+    xi_inflate_rect(&rct, -1);
+  xi_set_draw_ctools(txt->win, get_txt_ctools(txt, &new_ctools, &new_font,
+      (BOOLEAN)(do_border && !inside_only), FALSE));
+  xi_set_xvt_font(txt->win, &new_font, FALSE);
+#if XI_IS_CH
+  {
+    char *buf;
+    int len, i;
+
+    CTOS_IS_CH;
+    r = rct;
+    if (do_border)
+    {
+      r.right -= 8;
+      r.left += 8;
+    }
+    len = (r.right - r.left) / 8 + 1;
+    /* optimize here? reallocating with every re-draw? CH only? */
+    /* optimize by not setting DRAW_CTOOLS so often */
+    buf = xi_tree_malloc(len + 1, NULL);
+    for (i = 0; i < len; ++i)
+      buf[i] = ' ';
+    buf[len] = '\0';
+    get_txt_clip_rect(txt, &rct);
+    xi_set_clip(txt->win, &rct);
+    xi_draw_text(txt->win, r.left, txt->pix_baseline, buf, -1);
+    xi_tree_free(buf);
+    CTOS_END;
+  }
+#endif  /* CH */
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+
+  if (inside_only)
+  {
+    clip_r = rct;
+    if (txt->well || txt->platform)
+      xi_inflate_rect(&clip_r, -1);
+    xi_draw_rect(txt->win, &clip_r);
+  }
+  else
+  {
+    xi_draw_rect(txt->win, &rct);
+    clip_r = rct;
+  }
+#if (XIWS == PMWS) && (XVT_OS != XVT_OS_CTOS)
+  {
+    CBRUSH hollow_cbrush;
+    RCT rct;
+    DRAW_CTOOLS t;
+    WINDOW win = txt->win;
+  
+    /* Bad bug with XVT/PM, needs this before can draw COLOR_LTGRAY */
+    xvt_app_get_default_ctools(&t);
+    xvt_dwin_set_draw_ctools(win, &t);
+    hollow_cbrush.color = COLOR_WHITE;
+    hollow_cbrush.pat = PAT_HOLLOW;
+    xvt_dwin_set_cbrush(win, &hollow_cbrush);
+    rct.top = 0;
+    rct.left = 0;
+    rct.bottom = 0;
+    rct.right = 0;
+    xvt_dwin_draw_rect(win, &rct);
+    xi_set_draw_ctools(win, get_txt_ctools(txt, &new_ctools, &new_font,
+        do_border && !inside_only, FALSE));
+    xi_set_xvt_font(txt->win, &new_font, FALSE);
+  }
+#endif /* PM AND NOT CTOS */
+  if (! inside_only && (txt->well || txt->platform))
+  {
+    RCT r;
+  
+    r = rct;
+    xi_inflate_rect(&r, -1);
+    xi_draw_3d_rect(txt->win, &r, txt->well, 1, txt->hilight_color, txt->back_color, txt->shadow_color);
+  }
+  if (tattrib & TXT_ATR_FOCUSBORDER)
+  {
+    if (! inside_only)
+    {
+      CPEN cpen;
+      RCT r;
+
+      cpen = black_cpen;
+      r = rct;
+      xi_set_cpen(txt->win, &cpen);
+      xi_set_draw_mode(txt->win, M_COPY);
+      xi_set_cbrush(txt->win, &hollow_cbrush);
+      xi_set_clip(txt->win, NULL);
+      xi_draw_rect(txt->win, &r);
+    }
+  }
+CTOS_END;
+#endif  /* NOT CH */
+
+  if ((tattrib & TXT_ATR_VISIBLE) == 0)
+    return;
+  get_txt_clip_rect(txt, &rct);
+  xi_set_clip(txt->win, &rct);
+  if (tattrib & TXT_ATR_RJUST)
+    xi_draw_text_attrib(txt->win, txt->string_xpos, txt->pix_baseline, txt->text,
+      txt->len - txt->scroll_pos, txt->attrib);
+  else
+    xi_draw_text_attrib(txt->win, rct.left, txt->pix_baseline,
+      txt->text + txt->scroll_pos, -1, txt->attrib);
+  if (txt->selstart != txt->selstop)
+  {
+    xi_set_draw_ctools(txt->win, get_txt_ctools(txt, &new_ctools, &new_font,
+      (BOOLEAN)(do_border && !inside_only), TRUE));
+    xi_set_xvt_font(txt->win, &new_font, FALSE);
+
+#if XIWS == PMWS
+{
+RCT r;
+r.top = txt->pix_baseline - txt->ascent;
+r.left = ip1;
+r.bottom = txt->pix_baseline + txt->descent;
+r.right = rct.left + xi_xvt_get_text_width(txt->win, txt->text + txt->selstart, txt->selstop - txt->selstart);
+r.right = ip2;
+xi_draw_rect(txt->win, &r);
+}
+#endif
+
+    /* display inverted selection */
+    xi_draw_text_attrib(txt->win, ip1, txt->pix_baseline, txt->text + txt->selstart,
+      txt->selstop - txt->selstart, txt->attrib);
+  }
+  txt_display_caret(txt);
+  xi_set_clip(txt->win, NULL);
+}
+
+/*
+  This function performs a binary search to locate the nearest
+  character to the mouse, including characters that are not
+  visible because they are outside the bounding box of the control.
+*/
+static int near
+hit_test(TXT_DATA *txt, int x, int y)
+{
+  int lstop, start, stop, wid;
+  int curtextpos;
+
+  NOREF(y);
+  xi_set_xvt_font(txt->win, txt->font, FALSE);
+  if (x <= txt->string_xpos)
+    return 0;
+  if (x >= txt->string_xpos + stx_get_text_width(txt, txt->hit_test, 
+      txt->text, txt->len))
+    return(txt->len);
+  lstop = txt->len;
+  start = 0;
+  stop = txt->len / 2;
+  curtextpos = txt->string_xpos;
+  while (stop > start)
+  {
+    wid = stx_get_text_width(txt, txt->hit_test + start, 
+        txt->text + start, stop - start);
+    if (x <= curtextpos + wid /* && x >= curtextpos */) {
+      if (stop - start == 1)
+        break;
+      /* subdivide this range */
+      lstop = stop;
+      stop = start + (stop - start) / 2;
+    }
+    else
+    {
+      /* use other range */
+      start = stop;
+      stop = lstop;
+      curtextpos += wid;
+    }
+  }
+  /*
+    Now that the bisection has hit a character, determine which
+    side of the character is closer.
+  */
+  if (x - curtextpos > curtextpos + wid - x)
+    return(stop);
+  else
+    return(start);
+}
+
+TXT_DATA *
+txt_reset(TXT_DATA *txt)
+{
+  int leading, ascent, descent;
+
+  xi_set_xvt_font(txt->win, txt->font, FALSE);
+  xi_get_font_metrics(txt->win, &leading, &ascent, &descent);
+  txt->leading = (short)leading;
+  txt->ascent = (short)ascent;
+  txt->descent = (short)descent;
+  txt->select_start = txt->selstart = txt->selstop =
+      txt->scroll_pos = txt->flags = 0;
+  set_primary_selection(txt->win, "", 0);
+  txt->len = strlen(txt->text);
+  txt->hasfocus = FALSE;
+  txt->state = TXT_STATE_NULL;
+#if XIWS == WMWS
+  txt->pix_baseline = txt->rct.top + BORDER_SPACE_Y + leading +
+      ascent + descent;
+#else
+  txt->pix_baseline = txt->rct.top + leading + ascent;
+#endif
+  if (! txt->inside_only)
+  {
+    txt->pix_baseline += BORDER_WIDTH_Y;
+  }
+  if (txt->attrib & XI_ATR_VCENTER)
+  {
+    txt->pix_baseline +=
+        (txt->rct.bottom - txt->rct.top - leading - ascent -
+        descent) / 2;
+  }
+
+  recalc_hit_test(txt);
+  recalc_string_xpos(txt);
+  if (! xi_half_baked(txt->win))
+    txt_redraw(txt, FALSE);
+  return txt;
+}
+
+static void near
+invert_selection(TXT_DATA *txt, BOOLEAN invert)
+{
+  int ip1, ip2, clipleft, clipright;
+  DRAW_CTOOLS new_ctools;
+  FONT_OBJ new_font;
+  RCT rct;
+
+  txt_hide_caret(txt);
+  get_txt_positions(txt, &ip1, &ip2, &clipleft, &clipright);
+  xi_set_draw_ctools(txt->win, get_txt_ctools(txt, &new_ctools, &new_font,
+      FALSE, invert));
+  xi_set_xvt_font(txt->win, &new_font, FALSE);
+  get_txt_clip_rect(txt, &rct);
+  xi_set_clip(txt->win, &rct);
+  /* display inverted selection */
+
+  /* display inverted selection */
+  xi_draw_text_attrib(txt->win, ip1, txt->pix_baseline, txt->text + txt->selstart,
+      txt->selstop - txt->selstart, txt->attrib);
+  xi_set_clip(txt->win, NULL);
+}
+
+static void near
+deselect(TXT_DATA *txt)
+{
+  if (txt->selstart != txt->selstop)
+    invert_selection(txt, FALSE);
+  txt->selstart = txt->selstop;
+  txt->flags |= TXT_FLAG_SELECTION;
+  set_primary_selection(txt->win, "", 0);
+}
+
+static void near
+make_ip_viewable(TXT_DATA *txt, BOOLEAN redraw)
+{
+  int ip1, ip2, clipleft, clipright, pos;
+  BOOLEAN rjust = (txt->attrib & TXT_ATR_RJUST) != 0;
+  int oldxpos = txt->string_xpos;
+  RCT rct;
+
+  if ((txt->attrib & TXT_ATR_AUTOSCROLL) == 0)
+    return;
+  xi_set_xvt_font(txt->win, txt->font, FALSE);
+  get_txt_positions(txt, &ip1, &ip2, &clipleft, &clipright);
+  pos = (txt->selstart == txt->select_start) ? ip2 : ip1;
+  while (pos < clipleft || pos >= clipright)
+  {
+    if (pos < clipleft && rjust || pos >= clipright && !rjust)
+    {
+      if (txt->scroll_pos >= txt->len)
+        break;
+      /* increase scroll_pos */
+      txt->scroll_pos++;
+    }
+    else
+      if (pos < clipleft && !rjust || pos >= clipright && rjust)
+      {
+        if (txt->scroll_pos <= 0)
+          break;
+        /* decrease scroll_pos */
+        txt->scroll_pos--;
+      }
+    recalc_string_xpos(txt);
+    get_txt_positions(txt, &ip1, &ip2, &clipleft, &clipright);
+    pos = (txt->selstart == txt->select_start) ? ip2 : ip1;
+  }
+  if (oldxpos != txt->string_xpos)
+  {
+    txt->flags |= TXT_FLAG_SCROLL;
+    if (redraw)
+    {
+      xvt_dwin_update(txt->win);
+      get_txt_clip_rect(txt, &rct);
+      if (txt->parent_obj)
+      {
+        xi_set_update_obj(txt->parent_obj);
+        if (txt->parent_obj->type == XIT_LIST)
+          lm_text_scrolling(txt->parent_obj);
+      }
+      xi_scroll_rect(txt->win, &rct, txt->string_xpos - oldxpos, 0);
+      /* txt_redraw(txt, TRUE); */
+    }
+  }
+}
+
+static void near
+delete_selection(TXT_DATA *txt)
+{
+  int offset = txt->selstop - txt->selstart;
+  int i;
+
+  if (offset == 0)
+    return;
+  /*
+    Make redraw more efficient later
+  */
+  for (i = txt->selstop; txt->text[i] != 0; i++)
+    txt->text[i - offset] = txt->text[i];
+  txt->text[i - offset] = 0;
+  txt->len = strlen(txt->text);
+  recalc_hit_test(txt);
+  txt->select_start = txt->selstop = txt->selstart;
+  set_primary_selection(txt->win, "", 0);
+  recalc_string_xpos(txt);
+  make_ip_viewable(txt, FALSE);
+  txt_redraw(txt, TRUE);
+  txt->flags |= (TXT_FLAG_TEXT | TXT_FLAG_SELECTION);
+}
+
+static void near
+delete_char_idx(TXT_DATA *txt, int idx)
+{
+  int offset = txt->selstop - txt->selstart;
+  int i;
+
+  if (idx < 0 || idx >= txt->len || offset != 0)
+    return;
+  /*
+    Make redraw more efficient later
+  */
+  for (i = idx; txt->text[i + 1] != 0; i++)
+    txt->text[i] = txt->text[i + 1];
+  txt->text[i] = 0;
+  txt->len--;
+  recalc_hit_test(txt);
+  if (txt->selstart > idx)
+    txt->select_start = txt->selstop = txt->selstart = txt->selstart - 1;
+  recalc_string_xpos(txt);
+  make_ip_viewable(txt, FALSE);
+  txt_redraw(txt, TRUE);
+  txt->flags |= TXT_FLAG_TEXT;
+  set_primary_selection(txt->win, &txt->text[txt->selstart], 
+      txt->selstop - txt->selstart);
+}
+
+static void near
+delete_char_next(TXT_DATA *txt)
+{
+  delete_char_idx(txt, txt->selstart);
+}
+
+static void near
+delete_char_prev(TXT_DATA *txt)
+{
+  delete_char_idx(txt, txt->selstart - 1);
+}
+
+static BOOLEAN near
+char_is_displayable(int c)
+{
+  return((c >= ' ' && c <= 255) && (c != K_DEL));
+}
+
+static BOOLEAN near
+wordbrk(int c)
+{
+  return(strchr(" .,`~!@#$%^&*()-=+|[]{}\'\";:<>/?", c) != NULL);
+}
+
+static void near
+txt_set_sel_internal(TXT_DATA *txt, int ip1, int ip2,
+BOOLEAN autoscroll, BOOLEAN set_primary_sel)
+{
+  int oldp1, oldp2, dummy;
+  int selstart, selstop, old_selstart, old_selstop;
+  int p1, p2;
+  RCT rct;
+
+  ip2 = clip(ip2, 0, txt->len);
+  ip1 = clip(ip1, 0, txt->len);
+  if (txt->selstart != ip1 && txt->selstop != ip2 && txt->selstart != ip2)
+  {
+    /* both changed at once -- reset the selection start point */
+    txt->select_start = ip1;
+  }
+  get_txt_clip_rect(txt, &rct);
+  xi_set_clip(txt->win, &rct);
+  old_selstart = txt->selstart;
+  old_selstop = txt->selstop;
+  get_txt_positions(txt, &oldp1, &oldp2, &dummy, &dummy);
+  selstart = txt->selstart = ip1;
+  selstop = txt->selstop = ip2;
+  get_txt_positions(txt, &p1, &p2, &dummy, &dummy);
+  if (txt->hasfocus)
+  {
+    DRAW_CTOOLS new_ctools;
+    FONT_OBJ new_font;
+
+    /* only show selection if it has focus */
+    if (p1 >= oldp2 || p2 <= oldp1)
+    {
+      RCT r;
+      txt_hide_caret(txt);
+
+#if XVTWS == WMWS
+      NOREF(r);
+#endif
+      r.top = txt->pix_baseline - txt->ascent - txt->leading;
+      r.bottom = txt->pix_baseline + txt->descent;
+
+      xi_set_draw_ctools(txt->win, get_txt_ctools(txt, &new_ctools,
+          &new_font, FALSE, FALSE));
+      xi_set_xvt_font(txt->win, &new_font, FALSE);
+      /* clear old inverted selection */
+      if (txt->attrib & TXT_ATR_RJUST)
+      {
+#if XIWS == WINWS
+        r.left = oldp1;
+        r.right = r.left + stx_get_text_width(txt, 
+            txt->hit_test + old_selstart, txt->text + old_selstart,
+            old_selstop - old_selstart);
+        xi_rect_intersect(&r, &r, &rct);
+        xi_set_clip(txt->win, &r);
+#endif
+        xi_draw_text_attrib(txt->win, oldp1, txt->pix_baseline,
+            txt->text + old_selstart,
+            old_selstop - old_selstart, txt->attrib);
+      }
+      else
+      {
+#if XIWS == WINWS
+        r.left = oldp1;
+        r.right = r.left + stx_get_text_width(txt,
+            txt->hit_test + old_selstart, txt->text + old_selstart,
+            old_selstop - old_selstart);
+        xi_rect_intersect(&r, &r, &rct);
+        xi_set_clip(txt->win, &r);
+#endif
+        xi_draw_text_attrib(txt->win, oldp1, txt->pix_baseline, txt->text + old_selstart,
+            old_selstop - old_selstart, txt->attrib);
+      }
+
+      xi_set_draw_ctools(txt->win, get_txt_ctools(txt, &new_ctools,
+          &new_font, FALSE, TRUE));
+      xi_set_xvt_font(txt->win, &new_font, FALSE);
+      /* display inverted selection */
+#if XIWS == WINWS
+      r.left = p1;
+      r.right = r.left + stx_get_text_width(txt,
+          txt->hit_test + txt->selstart, txt->text + txt->selstart,
+          txt->selstop - txt->selstart);
+      xi_rect_intersect(&r, &r, &rct);
+      xi_set_clip(txt->win, &r);
+#endif
+      xi_draw_text_attrib(txt->win, p1, txt->pix_baseline,
+          txt->text + txt->selstart,
+          txt->selstop - txt->selstart, txt->attrib);
+    }
+    else
+    {
+      if (p1 != oldp1)
+      {
+        BOOLEAN invert = p1 < oldp1;
+#if XIWS == WINWS
+        RCT r;
+#endif
+
+        order_ints(&p1, &oldp1);
+        order_ints(&selstart, &old_selstart);
+        txt_hide_caret(txt);
+
+#if XIWS == WINWS
+        r.top = txt->pix_baseline - txt->ascent - txt->leading;
+        r.bottom = txt->pix_baseline + txt->descent;
+        r.left = p1;
+        r.right = r.left + stx_get_text_width(txt,
+            txt->hit_test + selstart, txt->text + selstart,
+            old_selstart - selstart);
+        xi_rect_intersect(&r, &r, &rct);
+        xi_set_clip(txt->win, &r);
+#endif
+
+        xi_set_draw_ctools(txt->win, get_txt_ctools(txt, &new_ctools,
+            &new_font, FALSE, invert));
+        xi_set_xvt_font(txt->win, &new_font, FALSE);
+        /* display inverted selection */
+        xi_draw_text_attrib(txt->win, p1, txt->pix_baseline,
+            txt->text + selstart, old_selstart - selstart,
+            txt->attrib);
+      }
+      if (p2 != oldp2)
+      {
+        BOOLEAN invert = p2 > oldp2;
+
+        order_ints(&p2, &oldp2);
+        order_ints(&selstop, &old_selstop);
+
+        txt_hide_caret(txt);
+
+        xi_set_draw_ctools(txt->win, get_txt_ctools(txt, &new_ctools,
+            &new_font, FALSE, invert));
+        xi_set_xvt_font(txt->win, &new_font, FALSE);
+
+        /* display inverted selection */
+        if (txt->attrib & TXT_ATR_RJUST)
+        {
+#if XIWS == WINWS
+          RCT r;
+
+          r.top = txt->pix_baseline - txt->ascent - txt->leading;
+          r.bottom = txt->pix_baseline + txt->descent;
+          r.left = p2;
+          r.right = r.left + stx_get_text_width(txt,
+              txt->hit_test + selstop, txt->text + selstop,
+              old_selstop - selstop);
+          xi_rect_intersect(&r, &r, &rct);
+          xi_set_clip(txt->win, &r);
+#endif
+
+          xi_draw_text_attrib(txt->win, p2, txt->pix_baseline, txt->text + selstop,
+              old_selstop - selstop, txt->attrib);
+        }
+        else
+        {
+#if XIWS == WINWS
+          RCT r;
+
+          r.top = txt->pix_baseline - txt->ascent - txt->leading;
+          r.bottom = txt->pix_baseline + txt->descent;
+          r.left = p2;
+          r.right = r.left + stx_get_text_width(txt,
+              txt->hit_test + selstop, txt->text + selstop,
+              old_selstop - selstop);
+          xi_rect_intersect(&r, &r, &rct);
+          xi_set_clip(txt->win, &r);
+#endif
+
+          xi_draw_text_attrib(txt->win, p2, txt->pix_baseline,
+              txt->text + selstop, old_selstop - selstop,
+              txt->attrib);
+        }
+      }
+    }
+    if (autoscroll)
+      make_ip_viewable(txt, TRUE);
+    txt_display_caret(txt);
+  }
+  xi_set_clip(txt->win, NULL);
+  if (set_primary_sel)
+    set_primary_selection(txt->win, &txt->text[txt->selstart], 
+        txt->selstop - txt->selstart);
+}
+
+static void near
+insert_char(TXT_DATA *txt, int c)
+{
+  int i;
+
+  xvt_errmsg_sig_if(!(txt->selstart == txt->selstop), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"30203",
+    30203, "Internal error");   
+  if (txt->len >= txt->text_size - 1)
+  {
+    /* beep(); */
+    txt->flags |= TXT_FLAG_OVF;
+    return;
+  }
+  for (i = txt->len; i >= txt->selstart; i--)
+    txt->text[i+1] = txt->text[i];
+  txt->text[txt->selstart] = (char)c;
+  txt->len++;
+  recalc_hit_test(txt);
+  txt->selstart++;
+  txt->selstop++;
+  recalc_string_xpos(txt);
+  make_ip_viewable(txt, FALSE);
+  txt_redraw(txt, TRUE);
+  txt->flags |= TXT_FLAG_TEXT;
+  set_primary_selection(txt->win, &txt->text[txt->selstart], 
+      txt->selstop - txt->selstart);
+}
+
+/*
+Process incoming events.  Return TRUE if event is consumed.
+*/
+BOOLEAN
+txt_event(TXT_DATA *txt, EVENT *ep, BOOLEAN gaining_focus)
+{
+  int hit, hit1, hit2;
+  int c, pos, oldpos;
+  static PNT last_pos = { 
+    -1, -1  };
+  EVENT_TYPE et;
+  BOOLEAN retval = TRUE;
+  /* This exists to avoid a compiler bug on the Mac/MPW */
+  BOOLEAN check_txt = ( txt != NULL );
+
+  et = ep->type;
+  xvt_errmsg_sig_if(!(check_txt), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"30206",
+    30206, "Invalid TXT passed to txt_event");   
+  if ((txt->attrib & TXT_ACTIVE_ATR) != TXT_ACTIVE_ATR &&
+      et != E_UPDATE)
+    return(FALSE);
+  switch (et)
+  {
+  case E_UPDATE:
+    txt_redraw(txt, FALSE);
+    break;
+  case E_CHAR:
+    if (txt->attrib & TXT_ATR_READONLY)
+    {
+      retval = FALSE;
+      break;
+    }
+    c = ep->v.chr.ch;
+    if (!char_is_displayable(c))
+    {
+      switch (c)
+      {
+      case K_LEFT:
+      case K_RIGHT:
+      case K_LHOME:
+      case K_LEND:
+      case K_WLEFT:
+      case K_WRIGHT:
+#if (XIWS == WMWS)
+        ep->v.chr.shift = FALSE;
+#endif
+        if (txt->selstart == txt->selstop)
+          txt->select_start = txt->selstart;
+        if (abs(txt->selstart - txt->select_start) >
+            abs(txt->selstop - txt->select_start))
+          pos = txt->selstart;
+        else
+          pos = txt->selstop;
+        oldpos = pos;
+        switch(c)
+        {
+        case K_LEFT:
+          pos = clip(pos - 1, 0, txt->len);
+          break;
+        case K_RIGHT:
+          pos = clip(pos + 1, 0, txt->len);
+          break;
+        case K_LHOME:
+          pos = 0;
+          break;
+        case K_LEND:
+          pos = txt->len;
+          break;
+        case K_WLEFT:
+          do
+          {
+            if (pos > 0)
+              pos--;
+          } while (pos > 0 && !wordbrk(txt->text[pos]));
+          break;
+        case K_WRIGHT:
+          do
+          {
+            if (pos < txt->len)
+              pos++;
+          } while (pos < txt->len &&
+              !wordbrk(txt->text[pos]));
+          break;
+        }
+        if (ep->v.chr.shift)
+        {
+          /* change current selection */
+          if (pos > txt->select_start)
+            txt_set_sel_internal(txt, txt->select_start,
+                pos, TRUE, TRUE);
+          else
+            txt_set_sel_internal(txt, pos,
+                txt->select_start, TRUE, TRUE);
+        }
+        else
+        {
+          /* move caret */
+          deselect(txt);
+          txt->select_start = txt->selstop = txt->selstart
+              = pos;
+          make_ip_viewable(txt, TRUE);
+          txt_display_caret(txt);
+        }
+        if (pos != oldpos)
+          txt->flags |= TXT_FLAG_SELECTION;
+        break;
+      case K_CLEAR:
+      case K_DEL:
+        if (txt->selstart != txt->selstop)
+          delete_selection(txt);
+        else
+          delete_char_next(txt);
+        break;
+      case BS:
+        if (txt->selstart != txt->selstop)
+          delete_selection(txt);
+        else
+          delete_char_prev(txt);
+        break;
+      default:
+        retval = FALSE;     /* event not consumed */
+        break;
+      }
+      break;
+    }
+    /* if we get to here then char is displayable */
+    if (txt->selstart != txt->selstop)
+      delete_selection(txt);
+    insert_char(txt, c);
+    if ( txt->auto_tab && txt->len >= txt->text_size - 1 )
+    {
+      EVENT ev;
+
+      MEMCLEAR(ev);
+      ev.type = E_CHAR;
+      ev.v.chr.ch = '\t';
+      xi_event( txt->win, &ev );
+    }
+    break;
+  case E_MOUSE_DOWN:
+  case E_MOUSE_DBL:
+    if (ep->v.mouse.button != 0)
+    {
+      retval = FALSE;
+      break;
+    }
+    if (txt->attrib & TXT_ATR_READONLY)
+    {
+      retval = FALSE;
+      break;
+    }
+    last_pos.h = last_pos.v = -1;
+    hit = hit_test(txt, ep->v.mouse.where.h, ep->v.mouse.where.v);
+    if (ep->v.mouse.shift)
+    {
+      /* alter old selection */
+      if (abs(txt->selstart - hit) > abs(txt->selstop - hit))
+        txt->select_start = txt->selstart;
+      else
+        txt->select_start = txt->selstop;
+    }
+    else
+    {
+      txt->select_start = hit;
+    }
+
+    /*
+      If XI_PREF_AUTOSEL_ON_MOUSE is set to true, don't fall through,
+      so that a mouse down on an AUTOSELECT field selects the entire
+      field.  Also, untrap the mouse to the object, so that mouse
+      moves and mouse up events do not go to the object.
+      */
+    if (gaining_focus && (txt->attrib & TXT_ATR_AUTOSELECT) && xi_get_pref(XI_PREF_AUTOSEL_ON_MOUSE))
+    {
+      XI_OBJ *itf;
+      XI_ITF_DATA *itf_data;
+
+      itf = xi_get_itf(txt->win);
+      itf_data = itf->v.itf;
+      itf_data->trap_obj = NULL;
+      /*
+        Inform the XI module that another module is taking
+        responsibility for trapping the mouse to an object,
+        explicitly.
+        */
+      itf_data->trap_explicit = TRUE;
+      break;
+    }
+    /*
+      Set the state to select characters or select words.
+      */
+    txt->state = (et == E_MOUSE_DOWN) ? TXT_STATE_SELC :
+        TXT_STATE_SELW;
+    if (et == E_MOUSE_DOWN && txt->timer_set)
+    {
+      txt_set_sel_internal(txt, 0, 32000, FALSE, TRUE);
+      txt->state = TXT_STATE_NULL;
+      xvt_timer_destroy(txt->timer_id);
+      txt->timer_id = 0;
+      txt->timer_set = FALSE;
+      break;
+    }
+    if (xi_get_pref(XI_PREF_TRIPLE_CLICK_TIME))
+    {
+      if (et == E_MOUSE_DBL)
+      {
+        txt->timer_id = xvt_timer_create(txt->win,
+            xi_get_pref(XI_PREF_TRIPLE_CLICK_TIME));
+        txt->timer_set = TRUE;
+      }
+    }
+    et = E_MOUSE_MOVE;
+    /*************
+        fall through to E_MOUSE_MOVE
+      *************/
+  case E_MOUSE_MOVE:
+#if 0
+    if (last_pos.h == ep->v.mouse.where.h &&
+        last_pos.v == ep->v.mouse.where.v) {
+      RCT rct;
+      /*
+          The mouse did not move from last position.
+          This event should be discarded unless we have dragged
+          off the edge of the edit field.
+        */
+      get_txt_clip_rect(txt, &rct);
+      if (xvt_rect_has_point(&rct, last_pos))
+        break;
+    }
+#endif
+    last_pos = ep->v.mouse.where;
+    if (txt->state != TXT_STATE_SELW && txt->state != TXT_STATE_SELC)
+      break;
+    hit = hit_test(txt, ep->v.mouse.where.h, ep->v.mouse.where.v);
+    hit1 = hit;
+    hit2 = txt->select_start;
+    order_ints(&hit1, &hit2);
+    if (txt->state == TXT_STATE_SELW)
+    {
+      /*
+          select from select_start to here, rounding both ends
+          to an even word boundary
+        */
+      while (hit1 > 0 && !wordbrk(txt->text[hit1-1]))
+        hit1--;
+      while (hit2 < txt->len && !wordbrk(txt->text[hit2]))
+        hit2++;
+    }
+    txt_set_sel_internal(txt, hit1, hit2, TRUE, FALSE);
+    break;
+  case E_TIMER:
+    if (txt->timer_id == ep->v.timer.id)
+    {
+      xvt_timer_destroy(txt->timer_id);
+      txt->timer_id = 0;
+      txt->timer_set = FALSE;
+    }
+    break;
+  case E_MOUSE_UP:
+    txt->state = TXT_STATE_NULL;
+    set_primary_selection(txt->win, &txt->text[txt->selstart], 
+        txt->selstop - txt->selstart);
+    break;
+  case E_COMMAND:
+    /* todo process clipboard events */
+    retval = FALSE;
+    break;
+  }
+  return(retval);
+}
+
+unsigned long
+txt_get_attrib(TXT_DATA *txt)
+{
+  return(txt->attrib);
+}
+
+void
+txt_get_sel(TXT_DATA *txt, int *c1, int *c2)
+{
+  *c1 = txt->selstart;
+  *c2 = txt->selstop;
+}
+
+RCT *
+txt_get_rect(TXT_DATA *txt, RCT *rct)
+{
+  *rct = txt->rct;
+  return(rct);
+}
+
+RCT *
+txt_set_rect(TXT_DATA *txt, RCT *rct)
+{
+  txt->rct = *rct;
+  return(rct);
+}
+
+void
+txt_get_text(TXT_DATA *txt, char *s, int len)
+{
+  tgstrncpy(s, txt->text, len);
+}
+
+void
+txt_set_attrib(TXT_DATA *txt, unsigned long attrib)
+{
+  BOOLEAN do_redraw;
+
+  do_redraw = (((txt->attrib ^ attrib) & TXT_REDRAW_ATR) != 0);
+  txt->attrib = attrib;
+  if (do_redraw)
+    txt_redraw(txt, FALSE);
+}
+
+/* turns on/off caret if selstart == selstop */
+void
+txt_caret(TXT_DATA *txt, BOOLEAN caret_state)
+{
+  xvt_errmsg_sig_if(!((txt->attrib & TXT_ACTIVE_ATR) == TXT_ACTIVE_ATR || !caret_state), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"30205",
+    30205, "txt_caret called with disabled field");
+  if (txt->hasfocus &&  !caret_state || !txt->hasfocus && caret_state)
+  {
+    if (caret_state == TRUE && txt->selstart != txt->selstop)
+    {
+      invert_selection(txt, TRUE);
+    }
+#if XIWS != WMWS
+    if (caret_state && (txt->attrib & TXT_ATR_FOCUSBORDER))
+    {
+      CPEN cpen;
+      RCT r;
+
+      cpen = black_cpen;
+      r = txt->rct;
+      xi_set_cpen(txt->win, &cpen);
+      xi_set_draw_mode(txt->win, M_COPY);
+      xi_set_cbrush(txt->win, &hollow_cbrush);
+      xi_draw_rect(txt->win, &r);
+    }
+#endif
+  }
+  txt->hasfocus = caret_state;
+  txt_display_caret(txt);
+}
+
+void
+txt_set_sel(TXT_DATA *txt, int ip1, int ip2)
+{
+  txt_set_sel_internal(txt, ip1, ip2, FALSE, FALSE);
+}
+
+void
+txt_set_text(TXT_DATA *txt, char *s)
+{
+  txt->select_start = txt->selstart = txt->selstop = txt->scroll_pos = 0;
+  txt->state = TXT_STATE_NULL;
+  if (s)
+  {
+    tgstrncpy(txt->text, s, txt->text_size);
+    txt->len = strlen(txt->text);
+    recalc_hit_test(txt);
+    recalc_string_xpos(txt);
+    txt_redraw(txt, TRUE);
+    set_primary_selection(txt->win, &txt->text[txt->selstart], 
+        txt->selstop - txt->selstart);
+  }
+}
+
+
+
+
diff --git a/xi/xitext.h b/xi/xitext.h
new file mode 100755
index 000000000..19d18975d
--- /dev/null
+++ b/xi/xitext.h
@@ -0,0 +1,102 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.                  *
+*******************************************************************************/
+
+#ifndef TXT_INCLUDED
+#define TXT_INCLUDED
+
+typedef long TXT;
+#define NULL_TXT (TXT)0
+
+#define TXT_ATR_ENABLED   XI_ATR_ENABLED
+#define TXT_ATR_EDITMENU  XI_ATR_EDITMENU
+#define TXT_ATR_AUTOSCROLL  XI_ATR_AUTOSCROLL
+#define TXT_ATR_AUTOSELECT  XI_ATR_AUTOSELECT
+#define TXT_ATR_RJUST   XI_ATR_RJUST
+#define TXT_ATR_BORDER    XI_ATR_BORDER
+#define TXT_ATR_VISIBLE   XI_ATR_VISIBLE
+#define TXT_ATR_FOCUSBORDER XI_ATR_FOCUSBORDER
+#define TXT_ATR_READONLY  XI_ATR_READONLY
+
+#define TXT_FLAG_TEXT   0x1   /* text has changed */
+#define TXT_FLAG_SELECTION  0x2   /* includes insertion point */
+#define TXT_FLAG_SCROLL   0x4   /* scroll position has changed */
+#define TXT_FLAG_OVF    0x8   /* user filled buffer */
+
+typedef enum
+{
+  TXT_STATE_NULL,
+  TXT_STATE_SELC,
+  TXT_STATE_SELW
+} 
+TXT_STATE;
+
+typedef struct _txt_def
+{
+  /* must be initialized by creator */
+  RCT rct;
+  XI_OBJ *parent_obj;
+  unsigned long attrib;
+  FONT_OBJ *font;
+  COLOR back_color;
+  COLOR fore_color;
+  COLOR hilight_color;    /* for well and platform fields */
+  COLOR shadow_color;   /* for well and platform fields */
+  short text_size;
+  char *text;
+  short *hit_test;
+  WINDOW win;
+  BOOLEAN well;
+  BOOLEAN platform;
+  BOOLEAN inside_only;
+  BOOLEAN auto_tab;
+  long timer_id;
+  BOOLEAN timer_set;
+
+  /* initialized by txt_reset */
+  short pix_baseline;
+  unsigned short flags;
+  TXT_STATE state;
+  short selstart, selstop;
+  short scroll_pos;
+  short select_start;
+  short string_xpos;
+  short len;
+  BOOLEAN hasfocus;
+  short ascent;
+  short descent;
+  short leading;
+} TXT_DATA;
+/*
+  NOTE: if TXT_ATR_RJUST is set, then scroll_pos indicates how many
+  characters are to the right of the right margin. Otherwise, it indicates
+  how many characters are to the left of the left margin.
+*/
+
+
+TXT_DATA *txt_reset(TXT_DATA *txt);
+BOOLEAN txt_event(TXT_DATA *txt, EVENT *ep, BOOLEAN gaining_focus);
+unsigned long txt_get_attrib(TXT_DATA *txt);
+void txt_get_sel(TXT_DATA *txt, int *c1, int *c2);
+RCT *txt_get_rect(TXT_DATA *txt, RCT *rct);
+RCT *txt_set_rect(TXT_DATA *txt, RCT *rct);
+void txt_get_text(TXT_DATA *txt, char *s, int len);
+void txt_redraw(TXT_DATA *txt, BOOLEAN inside_only);
+void txt_set_attrib(TXT_DATA *txt, unsigned long attrib);
+/* turns on/off caret if selstart == selstop */
+void txt_caret(TXT_DATA *txt, BOOLEAN caret_state);
+void txt_set_sel(TXT_DATA *txt, int c1, int c2);
+void txt_set_text(TXT_DATA *txt, char *s);
+void txt_display_caret(TXT_DATA *txt);
+void txt_hide_caret(TXT_DATA *txt);
+#if XIWS == MTFWS
+void clean_primesel();
+#endif
+
+#endif /* TXT_INCLUDED */
+
+
+
diff --git a/xi/xitree.c b/xi/xitree.c
new file mode 100755
index 000000000..7313800f3
--- /dev/null
+++ b/xi/xitree.c
@@ -0,0 +1,495 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+/* ERROR CODES 20201-20201 */
+
+#define XI_INTERNAL
+
+#include "xi.h"
+#include "xiheap.h"
+#include "xiutils.h"
+
+#ifndef R2
+#define fatal xvt_dm_post_fatal_exit
+#endif
+
+#define PADCHAR ((char)0x8e)
+#define MAGIC 0xe8
+
+/*
+  constants to define for more debugging
+  
+  PAD - pad allocations with N bytes of magic and check magic number when
+      xi_tree_check_sanity is called
+  FENCE - call xi_tree_check_sanity on every Nth xi_tree_* call
+  PREPAD - put an extra N bytes between the node struct and the data.
+      This padding is never checked.
+  
+  sample usage:
+  
+  #define PAD 20
+  #define FENCE 10
+  #define PREPAD 10
+*/
+/*
+#define PAD 100
+#define FENCE 1
+*/
+
+typedef struct _tree_node
+{
+  struct _tree_node *parent;
+  struct _tree_node *sibling;
+  struct _tree_node *child;
+#if XIWS == MTFWS
+  struct _tree_node *dummy;
+#endif
+#ifdef TREEDEBUG
+  int line;
+  char *file;
+  int magic;    /* for sanity checks */
+  int size;
+#ifdef PREPAD
+  char prepad[PREPAD];
+#endif
+#endif
+} TREE_NODE;
+
+#ifdef TREEDEBUG
+#undef xi_tree_malloc
+#undef xi_tree_realloc
+#define xi_tree_malloc_body xi_tree_malloc_d
+#define xi_tree_realloc_body  xi_tree_realloc_d
+#define xi_tree_malloc_stub xi_tree_malloc
+#define xi_tree_realloc_stub  xi_tree_realloc
+#else
+#define xi_tree_malloc_body xi_tree_malloc
+#define xi_tree_realloc_body  xi_tree_realloc
+#define xi_tree_malloc_stub xi_tree_malloc_d
+#define xi_tree_realloc_stub  xi_tree_realloc_d
+#endif
+
+#define VOIDPTR_TO_TREEPTR(p) ((TREE_NODE *)((char *)(p) - sizeof(TREE_NODE)))
+#define TREEPTR_TO_VOIDPTR(t) ((void *)((t) + 1))
+
+#define DBGTAB 3
+
+static TREE_NODE topnode =
+{ 
+  NULL, &topnode, NULL
+#if XIWS == MTFWS
+  , NULL
+#endif
+#ifdef TREEDEBUG
+  , 0, "TOPNODE", MAGIC, 0
+#endif
+};
+static TREE_NODE *top = &topnode;
+#ifdef TREEDEBUG
+#ifdef FENCE
+static int fence_count;
+#endif
+static int node_count = 1;    /* start with just top node */
+#endif
+
+static void
+dflt_error_fcn(void)
+{
+  xvt_dm_post_fatal_exit( "xi_tree_memory: Out of memory" );
+}
+
+static void (* error_fcn)(void) = dflt_error_fcn;
+
+#ifdef TREEDEBUG
+void xi_tree_check_fence(void);
+void
+xi_tree_check_fence(void)
+{
+#ifdef FENCE
+  static int fence_count;
+
+  fence_count++;
+  if (fence_count % FENCE == 0)
+    xi_tree_check_sanity("FENCE CHECK");
+#endif
+}
+
+static void near
+adjust_size(size_t *size)
+{
+  NOREF(size);
+#ifdef PAD
+  *size += PAD;
+#endif
+}
+
+static void near
+validate_node(void *p)
+{
+  if (p != NULL && VOIDPTR_TO_TREEPTR(p)->magic != MAGIC)
+    fatal( "Bad tree node detected: file %s, line %d",
+          VOIDPTR_TO_TREEPTR(p)->file, VOIDPTR_TO_TREEPTR(p)->line );
+}
+#endif
+
+static void near
+remove_from_siblings_and_parent(TREE_NODE *remove_t)
+{
+  TREE_NODE *tp;
+
+      /* remove from sibling list */
+  tp = remove_t;
+      while (tp->sibling != remove_t)
+      tp = tp->sibling;
+      tp->sibling = remove_t->sibling;
+
+      /* adjust parent pointers */
+  if (remove_t->parent->child == remove_t)
+      {
+    remove_t->parent->child = ((remove_t->sibling == remove_t) ?
+        NULL : remove_t->sibling);
+  }
+}
+
+static void near
+xi_tree_free_internal(TREE_NODE *remove_t, BOOLEAN toplevel)
+{
+  TREE_NODE *tp;
+    TREE_NODE *nexttp;
+
+    if (toplevel)
+    {
+  remove_from_siblings_and_parent(remove_t);
+      remove_t->sibling = NULL;
+  }
+
+  /* free all child nodes */
+  tp = remove_t->child;
+    if (tp != NULL)
+    do
+  {
+  /* store next pointer before nuking node */
+  nexttp = tp->sibling;
+      xi_tree_free_internal(tp, FALSE);
+      tp = nexttp;
+  } while (tp != remove_t->child);
+
+    /* free underlying heap manager memory */
+#ifdef TREEDEBUG
+  heap_free(remove_t->file);
+    node_count--;
+#endif
+    heap_free(remove_t);
+}
+
+void
+xi_tree_reparent(void *p, void *parent)
+{
+  TREE_NODE *tn;
+
+#ifdef TREEDEBUG
+      xi_tree_check_fence();
+      validate_node(p);
+#endif
+      remove_from_siblings_and_parent(VOIDPTR_TO_TREEPTR(p));
+      tn = VOIDPTR_TO_TREEPTR(p);
+      if (parent == NULL)
+      parent = TREEPTR_TO_VOIDPTR(top);
+      tn->parent = VOIDPTR_TO_TREEPTR(parent);
+      if (tn->parent->child == NULL)
+      {
+    tn->parent->child = tn;
+        tn->sibling = tn;
+  }
+  else
+  {
+    /* insert tn in the sibling list */
+    tn->sibling = tn->parent->child->sibling;
+        tn->parent->child->sibling = tn;
+  }
+}
+
+void
+xi_tree_free(void *p)
+{
+#ifdef TREEDEBUG
+  xi_tree_check_fence();
+      validate_node(p);
+#endif
+      xi_tree_free_internal(VOIDPTR_TO_TREEPTR(p), TRUE);
+}
+
+void *
+xi_tree_get_parent(void *p)
+{
+  TREE_NODE *parent;
+
+#ifdef TREEDEBUG
+      validate_node(p);
+#endif
+      parent = VOIDPTR_TO_TREEPTR(p)->parent;
+      return((parent == top) ? NULL : TREEPTR_TO_VOIDPTR(parent));
+}
+
+void *
+xi_tree_malloc_body(size_t size, void *parent
+#ifdef TREEDEBUG
+, int line, char *file
+#endif
+)
+{
+  TREE_NODE *tn;
+#ifdef TREEDEBUG
+      size_t orig_size = size;
+
+      xi_tree_check_fence();
+    validate_node(parent);
+      adjust_size(&size);
+#endif
+    tn = (TREE_NODE *)heap_malloc(size + sizeof(TREE_NODE));
+      if (! tn)
+      {
+    (* error_fcn)();
+        return NULL;
+  }
+#ifdef TREEDEBUG
+  gmemset((char *)tn + sizeof(TREE_NODE) + orig_size,
+      PADCHAR, (long)(size - orig_size));
+      tn->file = (char *)heap_malloc(gstrlen(file) + 1);
+      if (! tn->file)
+      {
+    (* error_fcn)();
+        return NULL;
+  }
+  gstrcpy(tn->file, file);
+      tn->line = line;
+      tn->magic = MAGIC;
+      tn->size = size;
+      node_count++;
+#endif
+      tn->child = NULL;
+      tn->sibling = tn;
+      if (parent == NULL)
+      parent = TREEPTR_TO_VOIDPTR(top);
+      tn->parent = VOIDPTR_TO_TREEPTR(parent);
+      if (tn->parent->child == NULL)
+      tn->parent->child = tn;
+      else
+  {
+    /* insert tn in the sibling list */
+    tn->sibling = tn->parent->child->sibling;
+        tn->parent->child->sibling = tn;
+  }
+  return(TREEPTR_TO_VOIDPTR(tn));
+}
+
+void *
+xi_tree_realloc_body(void *p, size_t size
+#ifdef TREEDEBUG
+, int line, char *file
+#endif
+)
+{
+  TREE_NODE *old_t;
+    TREE_NODE *new_t;
+    TREE_NODE *tp;
+#ifdef TREEDEBUG
+    size_t orig_size = size;
+
+    xi_tree_check_fence();
+    adjust_size(&size);
+#endif
+    old_t = VOIDPTR_TO_TREEPTR(p);
+#ifdef TREEDEBUG
+    validate_node(p);
+#endif
+    new_t = (TREE_NODE *)heap_realloc(old_t, (size + sizeof(TREE_NODE)));
+#ifdef TREEDEBUG
+    if (! new_t)
+    {
+  (* error_fcn)();
+      return NULL;
+  }
+  gmemset((char *)new_t + sizeof(TREE_NODE) + orig_size,
+    PADCHAR, (long)(size - orig_size));
+    new_t->line = line;
+    new_t->size = size;
+    heap_free(new_t->file);
+    new_t->file = (char *)heap_malloc(gstrlen(file) + 1);
+      if (! new_t->file)
+      {
+    (* error_fcn)();
+        return NULL;
+  }
+  gstrcpy(new_t->file, file);
+#endif
+
+      if (new_t != old_t)
+      {
+    /* change parent pointer */
+    if (new_t->parent->child == old_t)
+        new_t->parent->child = new_t;
+
+        /* change sibling pointers */
+    for (tp = new_t; tp->sibling != old_t; tp = tp->sibling)
+        ;
+        tp->sibling = new_t;
+
+        /* change children pointers */
+    tp = new_t->child;
+        if (tp != NULL)
+        do
+    {
+      tp->parent = new_t;
+          tp = tp->sibling;
+    } while (tp != new_t->child);
+  }
+  return(TREEPTR_TO_VOIDPTR(new_t))
+      ;
+}
+
+static void near
+xi_tree_dbg_internal(TREE_NODE *tn, int level)
+{
+  char buf[150];
+      char *s;
+      TREE_NODE *tn2;
+      int i, l;
+
+      if (tn == NULL)
+      return;
+      /* print tab indent indicating level */
+  s = buf;
+      for (l = level; l; l--)
+      {
+    for (i=0; i<DBGTAB; i++)
+        *s++ = ' ';
+  }
+#ifdef TREEDEBUG
+  sprintf( s, "node %08lx: par=%08lx, sib=%08lx, ch=%08lx, file=%s, line=%d",
+          PTR_LONG(tn), PTR_LONG(tn->parent), PTR_LONG(tn->sibling),
+          PTR_LONG(tn->child), tn->file, tn->line );
+#else
+  sprintf( s, "node %08lx: par=%08lx, sib=%08lx, ch=%08lx",
+          PTR_LONG(tn), PTR_LONG(tn->parent), PTR_LONG(tn->sibling),
+          PTR_LONG(tn->child) );
+#endif
+      xi_dbg(buf);
+      tn2 = tn->child;
+      if (tn2 != NULL)
+      do
+  {
+    xi_tree_dbg_internal(tn2, level + 1);
+        tn2 = tn2->sibling;
+  } while (tn2 != tn->child);
+}
+
+void
+xi_tree_dbg(char *title)
+{
+  char buf[100];
+
+      sprintf(buf, "TREE MEMORY DEBUG TRACE (%s)", title);
+      xi_dbg(buf);
+      xi_dbg("=======================");
+      xi_tree_dbg_internal(top, 0);
+    heap_dbg(title);
+      xi_tree_check_sanity(title);
+}
+
+static void near
+xi_tree_check_sanity_internal(TREE_NODE *tn, char *title,
+int *count)
+{
+  TREE_NODE *tn2;
+
+#ifdef TREEDEBUG
+#ifdef PAD
+      int i;
+
+      /* check pad bytes for node */
+  if (tn != &topnode)
+      for (i = tn->size - PAD; i < tn->size; i++)
+      if (*((char *)tn + sizeof(TREE_NODE) + i) != PADCHAR)
+        fatal( "xi_tree_node padding corrupted: node=%08lx, file=%s, line=%d",
+              PTR_LONG(tn), tn->file, tn->line );
+#endif
+#endif
+      /* check that all children point to this node */
+  tn2 = tn->child;
+      (*count)++;
+      if (tn2 != NULL)
+    do
+  {
+    if (tn2->parent != tn)
+    fatal( "memory check %s: tree node %08lx has bad parent",
+            title, PTR_LONG(tn2) );
+    xi_tree_check_sanity_internal(tn2, title, count);
+    tn2 = tn2->sibling;
+  } while (tn2 != tn->child);
+}
+
+void
+xi_tree_check_sanity(char *title)
+{
+  int count = 0;
+
+      xi_tree_check_sanity_internal(top, title, &count);
+#ifdef TREEDEBUG
+      if (count != node_count)
+      fatal("tree sanity check failed: tree count=%d, allocation count=%d",
+      count, node_count);
+#endif
+}
+
+#ifdef TREEDEBUG
+void *xi_tree_malloc_stub(size_t size, void *parent);
+void *
+xi_tree_malloc_stub(size_t size, void *parent)
+{
+  return(xi_tree_malloc_body(size, parent, 0, "(unknown)"));
+}
+
+void *xi_tree_realloc_stub(void *p, size_t size);
+void *
+xi_tree_realloc_stub(void *p, size_t size)
+{
+  return(xi_tree_realloc_body(p, size, 0, "(unknown)"));
+}
+#else
+void *xi_tree_malloc_stub(size_t size, void *parent,
+int line, char *file);
+void *
+xi_tree_malloc_stub(size_t size, void *parent,
+int line, char *file)
+{
+  NOREF(line);
+      NOREF(file);
+      return(xi_tree_malloc_body(size, parent));
+}
+
+void *xi_tree_realloc_stub(void *p, size_t size,
+int line, char *file);
+void *
+xi_tree_realloc_stub(void *p, size_t size,
+int line, char *file)
+{
+  NOREF(line);
+      NOREF(file);
+      return(xi_tree_realloc_body(p, size));
+}
+#endif
+
+void
+xi_tree_reg_error_fcn(void (* fcn)(void))
+{
+  error_fcn = fcn;
+}
+
+
diff --git a/xi/xiutils.c b/xi/xiutils.c
new file mode 100755
index 000000000..f0365f6d1
--- /dev/null
+++ b/xi/xiutils.c
@@ -0,0 +1,4343 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.  May not be      *
+*  distributed as object code, separately or linked with other object modules, *
+*  without permission.                                                         *
+*******************************************************************************/
+
+#define XI_INTERNAL
+#include "xiextend.h"
+#include "xi.h"
+#include "xiutils.h"
+#include "xitext.h"
+#include "xistx.h"
+#include "xilm.h"
+
+#if XIWS == WINWS
+#include "dos.h"
+#endif
+
+#if XVT_OS == XVT_OS_CTOS
+#define STX_VERT_FUDGE ((npctos_env == CHSERVICE) ? 0 : 6)
+#define BORDER_WIDTH ((npctos_env == CHSERVICE) ? 8 : 2)
+#define EDIT_BORDER_WIDTH_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#define EDIT_BORDER_SPACE_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#define BORDER_WIDTH_X ((npctos_env == CHSERVICE) ? 8 : 1)
+#define BORDER_WIDTH_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#define BORDER_SPACE_X ((npctos_env == CHSERVICE) ? 0 : 1)
+#define BORDER_SPACE_Y ((npctos_env == CHSERVICE) ? 0 : 1)
+#else
+#if XIWS == WMWS
+#define STX_VERT_FUDGE 0
+#define BORDER_WIDTH 8
+#define EDIT_BORDER_WIDTH_Y 0
+#define EDIT_BORDER_SPACE_Y 0
+#define BORDER_WIDTH_X 8
+#define BORDER_WIDTH_Y 0
+#define BORDER_SPACE_X 0
+#define BORDER_SPACE_Y 0
+#else
+#define STX_VERT_FUDGE 6
+#define BORDER_WIDTH 2
+#define EDIT_BORDER_WIDTH_Y 1
+#define EDIT_BORDER_SPACE_Y 1
+#define BORDER_WIDTH_X 1
+#define BORDER_WIDTH_Y 1
+#define BORDER_SPACE_X 1
+#define BORDER_SPACE_Y 1
+#endif
+#endif
+
+#define MAX_RADIO_BUTTONS 30
+
+CBRUSH ltgray_cbrush = {
+  PAT_SOLID, COLOR_LTGRAY };
+CBRUSH gray_cbrush = { 
+  PAT_SOLID, COLOR_GRAY };
+CBRUSH hollow_cbrush = { 
+  PAT_HOLLOW, COLOR_WHITE };
+
+FONT_OBJ xi_sysfont;
+
+#if (XIWS != GRWS) || (XVT_CC != XVT_CC_MS70)
+CPEN hollow_cpen = {
+  0, PAT_HOLLOW, P_SOLID, COLOR_WHITE };
+CPEN black_cpen = {
+  1, PAT_SOLID, P_SOLID, COLOR_BLACK };
+CPEN rubber_cpen = {
+  1, PAT_RUBBER, P_DASH, COLOR_BLACK };
+CBRUSH white_cbrush = {
+  PAT_SOLID, COLOR_WHITE };
+#endif
+
+/* added following lines for 386 port of dgr */
+#if XIWS == GRWS
+CPEN hollow_cpen = {
+  0, PAT_HOLLOW, P_SOLID, COLOR_WHITE };
+CPEN black_cpen = {
+  1, PAT_SOLID, P_SOLID, COLOR_BLACK };
+CPEN rubber_cpen = {
+  1, PAT_RUBBER, P_DASH, COLOR_BLACK };
+CBRUSH white_cbrush = {
+  PAT_SOLID, COLOR_WHITE };
+#endif
+
+static WINDOW cur_window;
+
+static XI_OBJ *cur_itf;
+static int cur_delta_x;
+static int cur_delta_y;
+
+static BOOLEAN font_set = FALSE;
+static BOOLEAN update_pending = FALSE;
+
+static int xi_sysvals[XI_NBR_SYSVALS];
+static long xi_preferences[XI_NBR_PREFERENCES] =
+{
+  1,                  /* XI_PREF_OVERLAP */
+  '\t',               /* XI_PREF_FORM_TAB_CHAR */
+  K_BTAB,             /* XI_PREF_FORM_BACKTAB_CHAR */
+  1,                  /* XI_PREF_SCROLL_INC */
+  TRUE,               /* XI_PREF_3D_LOOK */
+  FALSE,              /* XI_PREF_USE_APP_DATA */
+  FALSE,              /* XI_PREF_AUTOSEL_ON_MOUSE */
+  1,                  /* XI_PREF_CELL_BTN_ICON_X */
+  1,                  /* XI_PREF_CELL_BTN_ICON_Y */
+
+#if XVT_OS == XVT_OS_CTOS
+  2,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  16,                 /* XI_PREF_SB_WIDTH */
+  16,                 /* XI_PREF_SB_HEIGHT */
+  XI_CURSOR_RESIZE,   /* XI_PREF_SIZE_CURSOR_RID */
+  XI_CURSOR_HAND,     /* XI_PREF_HAND_CURSOR_RID */
+  XI_CURSOR_VRESIZE,  /* XI_PREF_VSIZE_CURSOR_RID */
+  COMBO_ICON,         /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_LTGRAY,       /* XI_PREF_COLOR_CTRL */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DARK */
+  TRUE,               /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  0,                  /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+  12,                 /* XI_PREF_BUTTON_HEIGHT */
+  32,                 /* XI_PREF_BUTTON_PAD */
+  16,                 /* XI_PREF_HORZ_SPACING */
+  0,                  /* XI_PREF_VERT_SPACING */
+  0,                  /* XI_PREF_HORZ_PIXEL_SPACING */
+  0,                  /* XI_PREF_VERT_PIXEL_SPACING */
+  24,                 /* XI_PREF_ITF_MIN_TOP */
+  8,                  /* XI_PREF_ITF_MIN_LEFT */
+  FALSE,              /* XI_PREF_XIL */
+  FALSE,              /* XI_PREF_ASSERT_ON_NULL_CID */
+
+#else
+#if XIWS == WMWS
+  0,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  8,                  /* XI_PREF_SB_WIDTH */
+  8,                  /* XI_PREF_SB_HEIGHT */
+  0,                  /* XI_PREF_SIZE_CURSOR_RID */
+  0,                  /* XI_PREF_HAND_CURSOR_RID */
+  0,                  /* XI_PREF_VSIZE_CURSOR_RID */
+  0,                  /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_LTGRAY,       /* XI_PREF_COLOR_CTRL */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DARK */
+  TRUE,               /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  K_F2,               /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+  24,                 /* XI_PREF_BUTTON_HEIGHT */
+  32,                 /* XI_PREF_BUTTON_PAD */
+  16,                 /* XI_PREF_HORZ_SPACING */
+  0,                  /* XI_PREF_VERT_SPACING */
+  0,                  /* XI_PREF_HORZ_PIXEL_SPACING */
+  0,                  /* XI_PREF_VERT_PIXEL_SPACING */
+  16,                 /* XI_PREF_ITF_MIN_TOP */
+  8,                  /* XI_PREF_ITF_MIN_LEFT */
+  FALSE,              /* XI_PREF_XIL */
+  FALSE,              /* XI_PREF_ASSERT_ON_NULL_CID */
+
+#elif XIWS == PMWS
+  2,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  16,                 /* XI_PREF_SB_WIDTH */
+  16,                 /* XI_PREF_SB_HEIGHT */
+  XI_CURSOR_RESIZE,   /* XI_PREF_SIZE_CURSOR_RID */
+  XI_CURSOR_HAND,     /* XI_PREF_HAND_CURSOR_RID */
+  XI_CURSOR_VRESIZE,  /* XI_PREF_VSIZE_CURSOR_RID */
+  COMBO_ICON,         /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_LTGRAY,       /* XI_PREF_COLOR_CTRL */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DARK */
+  TRUE,               /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  0,                  /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+  12,                 /* XI_PREF_BUTTON_HEIGHT */
+  32,                 /* XI_PREF_BUTTON_PAD */
+  16,                 /* XI_PREF_HORZ_SPACING */
+  2,                  /* XI_PREF_VERT_SPACING */
+  0,                  /* XI_PREF_HORZ_PIXEL_SPACING */
+  0,                  /* XI_PREF_VERT_PIXEL_SPACING */
+  24,                 /* XI_PREF_ITF_MIN_TOP */
+  8,                  /* XI_PREF_ITF_MIN_LEFT */
+  FALSE,              /* XI_PREF_XIL */
+  FALSE,              /* XI_PREF_ASSERT_ON_NULL_CID */
+
+#elif XIWS == GRWS
+  2,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  12,                 /* XI_PREF_SB_WIDTH */
+  12,                 /* XI_PREF_SB_HEIGHT */
+  0,                  /* XI_PREF_SIZE_CURSOR_RID */
+  0,                  /* XI_PREF_HAND_CURSOR_RID */
+  0,                  /* XI_PREF_VSIZE_CURSOR_RID */
+  0,                  /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_LTGRAY,       /* XI_PREF_COLOR_CTRL */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DARK */
+  FALSE,              /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  0,                  /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+
+#elif XIWS == MACWS
+  2,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  16,                 /* XI_PREF_SB_WIDTH */
+  16,                 /* XI_PREF_SB_HEIGHT */
+  XI_CURSOR_RESIZE,   /* XI_PREF_SIZE_CURSOR_RID */
+  XI_CURSOR_HAND,     /* XI_PREF_HAND_CURSOR_RID */
+  XI_CURSOR_VRESIZE,  /* XI_PREF_VSIZE_CURSOR_RID */
+  COMBO_ICON,         /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_LTGRAY,       /* XI_PREF_COLOR_CTRL */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DARK */
+  TRUE,               /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  0,                  /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+  12,                 /* XI_PREF_BUTTON_HEIGHT */
+  32,                 /* XI_PREF_BUTTON_PAD */
+  16,                 /* XI_PREF_HORZ_SPACING */
+  2,                  /* XI_PREF_VERT_SPACING */
+  0,                  /* XI_PREF_HORZ_PIXEL_SPACING */
+  0,                  /* XI_PREF_VERT_PIXEL_SPACING */
+  40,                 /* XI_PREF_ITF_MIN_TOP */
+  8,                  /* XI_PREF_ITF_MIN_LEFT */
+  FALSE,              /* XI_PREF_XIL */
+  FALSE,              /* XI_PREF_ASSERT_ON_NULL_CID */
+
+#elif XIWS == XOLWS
+  2,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  16,                 /* XI_PREF_SB_WIDTH */
+  16,                 /* XI_PREF_SB_HEIGHT */
+  XI_CURSOR_RESIZE,   /* XI_PREF_SIZE_CURSOR_RID */
+  XI_CURSOR_HAND,     /* XI_PREF_HAND_CURSOR_RID */
+  XI_CURSOR_VRESIZE,  /* XI_PREF_VSIZE_CURSOR_RID */
+  COMBO_ICON,         /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_GRAY,         /* XI_PREF_COLOR_CTRL */
+  COLOR_DKGRAY,       /* XI_PREF_COLOR_DARK */
+  FALSE,              /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  0,                  /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+  12,                 /* XI_PREF_BUTTON_HEIGHT */
+  32,                 /* XI_PREF_BUTTON_PAD */
+  16,                 /* XI_PREF_HORZ_SPACING */
+  2,                  /* XI_PREF_VERT_SPACING */
+  0,                  /* XI_PREF_HORZ_PIXEL_SPACING */
+  0,                  /* XI_PREF_VERT_PIXEL_SPACING */
+  0,                  /* XI_PREF_ITF_MIN_TOP */
+  8,                  /* XI_PREF_ITF_MIN_LEFT */
+  FALSE,              /* XI_PREF_XIL */
+  FALSE,              /* XI_PREF_ASSERT_ON_NULL_CID */
+
+#elif XIWS == MTFWS
+  2,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  16,                 /* XI_PREF_SB_WIDTH */
+  16,                 /* XI_PREF_SB_HEIGHT */
+  XI_CURSOR_RESIZE,   /* XI_PREF_SIZE_CURSOR_RID */
+  XI_CURSOR_HAND,     /* XI_PREF_HAND_CURSOR_RID */
+  XI_CURSOR_VRESIZE,  /* XI_PREF_VSIZE_CURSOR_RID */
+  COMBO_ICON,         /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_LTGRAY,       /* XI_PREF_COLOR_CTRL */
+  COLOR_DKGRAY,       /* XI_PREF_COLOR_DARK */
+  TRUE,               /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  0,                  /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+  12,                 /* XI_PREF_BUTTON_HEIGHT */
+  32,                 /* XI_PREF_BUTTON_PAD */
+  16,                 /* XI_PREF_HORZ_SPACING */
+  2,                  /* XI_PREF_VERT_SPACING */
+  0,                  /* XI_PREF_HORZ_PIXEL_SPACING */
+  0,                  /* XI_PREF_VERT_PIXEL_SPACING */
+  0,                  /* XI_PREF_ITF_MIN_TOP */
+  8,                  /* XI_PREF_ITF_MIN_LEFT */
+  FALSE,              /* XI_PREF_XIL */
+  FALSE,              /* XI_PREF_ASSERT_ON_NULL_CID */
+
+#elif XIWS == WINWS
+  2,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  16,                 /* XI_PREF_SB_WIDTH */
+  16,                 /* XI_PREF_SB_HEIGHT */
+  XI_CURSOR_RESIZE,   /* XI_PREF_SIZE_CURSOR_RID */
+  XI_CURSOR_HAND,     /* XI_PREF_HAND_CURSOR_RID */
+  XI_CURSOR_VRESIZE,  /* XI_PREF_VSIZE_CURSOR_RID */
+  COMBO_ICON,         /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_LTGRAY,       /* XI_PREF_COLOR_CTRL */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DARK */
+  FALSE,              /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  K_DOWN | XI_MOD_CONTROL,    /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+  12,                 /* XI_PREF_BUTTON_HEIGHT */
+  32,                 /* XI_PREF_BUTTON_PAD */
+  16,                 /* XI_PREF_HORZ_SPACING */
+  2,                  /* XI_PREF_VERT_SPACING */
+  0,                  /* XI_PREF_HORZ_PIXEL_SPACING */
+  0,                  /* XI_PREF_VERT_PIXEL_SPACING */
+  30,                 /* XI_PREF_ITF_MIN_TOP */
+  8,                  /* XI_PREF_ITF_MIN_LEFT */
+  FALSE,              /* XI_PREF_XIL */
+  FALSE,              /* XI_PREF_ASSERT_ON_NULL_CID */
+
+#else
+  2,                  /* XI_PREF_COLUMN_OFFSET */
+  0,                  /* XI_PREF_SB_OFFSET */
+  16,                 /* XI_PREF_SB_WIDTH */
+  16,                 /* XI_PREF_SB_HEIGHT */
+  0,                  /* XI_PREF_SIZE_CURSOR_RID */
+  0,                  /* XI_PREF_HAND_CURSOR_RID */
+  0,                  /* XI_PREF_VSIZE_CURSOR_RID */
+  0,                  /* XI_PREF_COMBO_ICON */
+  COLOR_WHITE,        /* XI_PREF_COLOR_LIGHT */
+  COLOR_LTGRAY,       /* XI_PREF_COLOR_CTRL */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DARK */
+  TRUE,               /* XI_PREF_OPTIMIZE_CELL_REQUESTS */
+  1,                  /* XI_PREF_CARET_WIDTH */
+  500,                /* XI_PREF_TRIPLE_CLICK_TIME */
+  0,                  /* XI_PREF_BUTTON_KEY */
+  TRUE,               /* XI_PREF_LIMIT_MIN_WIN_SIZE */
+  5,                  /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */
+  FALSE,              /* XI_PREF_KEEP_FOCUS_FIXED */
+  TRUE,               /* XI_PREF_NATIVE_CTRLS */
+  K_F3,               /* XI_PREF_ITF_TAB_CHAR */
+  K_F4,               /* XI_PREF_ITF_BACKTAB_CHAR */
+  16,                 /* XI_PREF_ITF_WS_RIGHT */
+  4,                  /* XI_PREF_ITF_WS_BOTTOM */
+  40,                 /* XI_PREF_VIR_SP_H */
+  20,                 /* XI_PREF_VIR_SP_V */
+  TRUE,               /* XI_PREF_DBL_PRESSES_BUTTON */
+  1,                  /* XI_PREF_CONTAINER_GRID_WIDTH */
+  TRUE,               /* XI_PREF_MULTILINE_QUICK_PASTE */
+  COLOR_GRAY,         /* XI_PREF_COLOR_DISABLED */
+  12,                 /* XI_PREF_BUTTON_HEIGHT */
+  32,                 /* XI_PREF_BUTTON_PAD */
+  16,                 /* XI_PREF_HORZ_SPACING */
+  2,                  /* XI_PREF_VERT_SPACING */
+  0,                  /* XI_PREF_HORZ_PIXEL_SPACING */
+  0,                  /* XI_PREF_VERT_PIXEL_SPACING */
+  0,                  /* XI_PREF_ITF_MIN_TOP */
+  8,                  /* XI_PREF_ITF_MIN_LEFT */
+  FALSE,              /* XI_PREF_XIL */
+  FALSE,              /* XI_PREF_ASSERT_ON_NULL_CID */
+
+#endif
+#endif
+
+};
+
+
+RCT big_clip = {
+  0, 0, 10000, 10000 };
+
+static void xi_caret_suspend(WINDOW win);
+static void xi_caret_restore(WINDOW win);
+
+#if XIWS == WMWS
+void
+xi_fix_color(COLOR *color)
+{
+  if (*color == COLOR_BLACK)
+  *color = COLOR_WHITE;
+  else
+  if (*color == COLOR_WHITE)
+    *color = COLOR_BLACK;
+}
+#endif
+
+char *
+tgstrncpy(char *dst, char *src, int n)
+{
+  gstrncpy(dst, src, n);
+  dst[n - 1] = '\0';
+  return(dst);
+}
+
+char *
+gstrncpy(char *dst, char *src, int n)
+{
+  char *p = dst;
+
+  while (n > 0 && *src != 0)
+  {
+    *p++ = *src++;
+    n--;
+  }
+  if (n != 0)
+    *p++ = '\0';
+  return(dst);
+}
+
+void
+order_ints(int *ip1, int *ip2)
+{
+  int temp;
+
+  if (*ip1 > *ip2)
+  {
+    temp = *ip1;
+    *ip1 = *ip2;
+    *ip2 = temp;
+  }
+}
+
+RCT *
+xi_inflate_rect(RCT *rct, int amount)
+{
+  rct->bottom += amount;
+  rct->right += amount;
+  rct->left -= amount;
+  rct->top -= amount;
+  return(rct);
+}
+
+static void
+xi_offset_rect(RCT *rct, int delta_x, int delta_y)
+{
+  rct->top -= delta_y;
+  rct->bottom -= delta_y;
+  rct->right -= delta_x;
+  rct->left -= delta_x;
+}
+
+int
+clip(int val, int mn, int mx)
+{
+  return(val < mn ? mn : (val > mx ? mx : val));
+}
+
+void
+xi_realloc_array(void **ptr, int nbr, size_t sz, void *parent)
+{
+  BOOLEAN is_zero = (nbr * sz) == 0;
+
+  if (! *ptr)
+  {
+    if (is_zero)
+      *ptr = NULL;
+    else
+      *ptr = (void *)xi_tree_malloc(nbr * sz, parent);
+  }
+  else
+  {
+    if (is_zero)
+    {
+      xi_tree_free(*ptr);
+      *ptr = NULL;
+    }
+    else
+      *ptr = (void *)xi_tree_realloc(*ptr, nbr * sz);
+  }
+}
+
+XVT_FNTID
+xi_create_copy_font_id(XI_OBJ *itf, XVT_FNTID font_id, XVT_FNTID old_font_id)
+{
+  int i, j;
+  XVT_FNTID copy_font_id;
+  XI_ITF_DATA *itf_data;
+  BOOLEAN found = FALSE;
+
+  itf_data = itf->v.itf;
+  if (old_font_id)
+  {
+  for (i = 0; i < itf_data->nbr_font_ids; ++i)
+  {
+    if (itf_data->font_ids[i] == old_font_id)
+    {
+      found = TRUE;
+      break;
+    }
+  }
+
+  if (found)
+  {
+    if (font_compare(old_font_id, itf_data->font_ids[i]))
+      return old_font_id;
+
+    xvt_font_destroy(font_id);
+    if (i < itf_data->nbr_font_ids)
+    {
+      for (j = i; j < itf_data->nbr_font_ids - 1; ++j)
+        itf_data->font_ids[j] = itf_data->font_ids[j + 1];
+      itf_data->nbr_font_ids--;
+      xi_realloc_array((void **)&itf_data->font_ids, itf_data->nbr_font_ids,
+          sizeof(XVT_FNTID), itf_data);
+    }
+  }
+  }
+
+  copy_font_id = xvt_font_create();
+  xvt_font_copy(copy_font_id, font_id, (unsigned long)XVT_FA_ALL);
+  itf_data->nbr_font_ids++;
+  xi_realloc_array((void **)&itf_data->font_ids, itf_data->nbr_font_ids,
+    sizeof(XVT_FNTID), itf_data);
+  itf_data->font_ids[itf_data->nbr_font_ids - 1] = copy_font_id;
+  return copy_font_id;
+}
+
+void
+xi_free_font_id(XI_OBJ *itf, XVT_FNTID font_id)
+{
+  XI_ITF_DATA *itf_data;
+  int i, j;
+
+  itf_data = itf->v.itf;
+  for (i = 0; i < itf_data->nbr_font_ids; ++i)
+  if (itf_data->font_ids[i] == font_id)
+    break;
+  xvt_font_destroy(font_id);
+  if (i < itf_data->nbr_font_ids)
+  {
+  for (j = i; j < itf_data->nbr_font_ids - 1; ++j)
+    itf_data->font_ids[j] = itf_data->font_ids[j + 1];
+  itf_data->nbr_font_ids--;
+  xi_realloc_array((void **)&itf_data->font_ids, itf_data->nbr_font_ids,
+  sizeof(XVT_FNTID), itf_data);
+  }
+}
+
+static void
+do_vir_pan_event(XI_OBJ *itf, int h, int v, BOOLEAN before)
+{
+  XI_EVENT xiev;
+
+  MEMCLEAR(xiev);
+  xiev.type = XIE_VIR_PAN;
+  xiev.v.vir_pan.before_pan = before;
+  xiev.v.vir_pan.delta_x = h;
+  xiev.v.vir_pan.delta_y = v;
+  (*(XI_EH_TYPE)itf->v.itf->xi_eh)(itf, &xiev);
+}
+
+static void
+set_sb_positions(XI_OBJ *itf)
+{
+  XI_ITF_DATA *itf_data;
+  WINDOW win;
+  int ps;
+
+  itf_data = itf->v.itf;
+  win = xi_get_window(itf);
+  if (itf_data->max_xi_pnt.v - itf_data->win_xi_pnt.v)
+    ps = (int)(100L * (long)(itf_data->phys_xi_pnt.v) /
+  ((long)itf_data->max_xi_pnt.v -
+  (long)itf_data->win_xi_pnt.v));
+  else
+    ps = 0;
+  xvt_sbar_set_pos(win, VSCROLL, ps);
+  if (itf_data->max_xi_pnt.h - itf_data->win_xi_pnt.h)
+    ps = (int)(100L * (long)(itf_data->phys_xi_pnt.h) /
+  ((long)itf_data->max_xi_pnt.h -
+  (long)itf_data->win_xi_pnt.h));
+  else
+    ps = 0;
+  xvt_sbar_set_pos(win, HSCROLL, ps);
+}
+
+void
+xi_get_hsb_rect(XI_OBJ *xi_obj, RCT *rctp)
+{
+  XI_LIST_DATA *list_data;
+  LM_DATA *lmp;
+  RCT rct1, rct3;
+  XI_OBJ * *members;
+  int nbr_members;
+#if (XIWS == WINWS) || (XIWS == GRWS)
+  RCT r;
+#endif
+
+  list_data = xi_obj->v.list;
+  lmp = (LM_DATA *)list_data->lm;
+  if (list_data->have_hsb_rct)
+  {
+    *rctp = list_data->hsb_rct;
+    return;
+  }
+#if (XIWS == WINWS) || (XIWS == GRWS)
+  if (list_data->hsb_win)
+    xvt_vobj_get_client_rect(list_data->hsb_win, &r);
+#endif
+  members = xi_get_member_list(xi_obj, &nbr_members);
+  if (! lmp->nbr_columns)
+  {
+    rct3.left = lmp->rct.left;
+    rct1 = lmp->rct;
+  }
+  else
+  {
+    if (lmp->fixed_columns)
+    {
+    xi_get_rect(members[lmp->fixed_columns - 1], &rct1);
+      rct3.left = rct1.right;
+    }
+    else
+    {
+      xi_get_rect(members[0], &rct1);
+      rct3.left = lmp->rct.left;
+    }
+  }
+  /*
+  subtract one so that the top of the horizontal scroll bar overlaps the bottom of the
+  list by one pixel.
+  */
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  rct3.top = rct1.bottom - 1;
+  rct3.right = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  rct3.top = rct1.bottom;
+  rct3.right = lmp->rct.left + lmp->pixel_width;
+  CTOS_END;
+#endif
+  rct3.bottom = rct3.top + (int)xi_get_pref(XI_PREF_SB_HEIGHT);
+#if (XIWS == WINWS) || (XIWS == GRWS)
+  if (list_data->hsb_win)
+    rct3.bottom = rct3.top + r.bottom;
+#endif
+  *rctp = rct3;
+  list_data->hsb_rct = rct3;
+  list_data->have_hsb_rct = TRUE;
+}
+
+void
+xi_get_sb_rect(XI_OBJ *xi_obj, RCT *rctp)
+{
+  RCT rct;
+  int offset, width;
+  XI_LIST_DATA *list_data;
+  LM_DATA *lmp;
+#if (XIWS == WINWS) || (XIWS == GRWS)
+  RCT r;
+#endif
+
+  list_data = xi_obj->v.list;
+  lmp = (LM_DATA *)list_data->lm;
+  if (list_data->have_sb_rct)
+  {
+    *rctp = list_data->sb_rct;
+    return;
+  }
+#if (XIWS == WINWS) || (XIWS == GRWS)
+  if (list_data->sb_win)
+    xvt_vobj_get_client_rect(list_data->sb_win, &r);
+#endif
+  lm_get_rect(list_data->lm, LM_LIST, 0, &rct);
+  list_data->sb_offset = offset = (int)xi_get_pref(XI_PREF_SB_OFFSET);
+  list_data->sb_width = width = (int)xi_get_pref(XI_PREF_SB_WIDTH);
+
+  /*
+  subtract one from the left of the scroll bar rectangle, so that the left edge of the
+  scroll bar overlaps the right double wide line, by one pixel.
+  */
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  if (list_data->width)
+    rct.left = rct.left + lmp->pixel_width + offset + 2 * BORDER_WIDTH - 1;
+  else
+    rct.left = rct.right + offset - 1;
+  CTOS_END;
+#endif
+#if XI_IS_CH
+  CTOS_IS_CH;
+  if (list_data->width)
+    rct.left = rct.left + lmp->pixel_width + offset;
+  else
+    rct.left = rct.right + offset;
+  CTOS_END;
+#endif
+  rct.right = rct.left + width;
+#if (XIWS == WINWS) || (XIWS == GRWS)
+  if (list_data->sb_win)
+    rct.right = rct.left + r.right;
+#endif
+  if (list_data->scroll_bar_button)
+  {
+    LM_DATA *lm_data;
+
+    lm_data = (LM_DATA *)list_data->lm;
+    list_data->sbb_rct.top = rct.top + 1;       /* Add one, so that there is room for the
+            double line border */
+    list_data->sbb_rct.bottom = lm_data->pix_row1_top - BORDER_WIDTH + 1;
+    list_data->sbb_rct.left = rct.left;
+    list_data->sbb_rct.right = rct.right;
+#if (XIWS == WINWS) || (XIWS == GRWS)
+    if (list_data->sb_win)
+      list_data->sbb_rct.right = list_data->sbb_rct.left + r.right;
+#endif
+#if XI_IS_CH
+    CTOS_IS_CH;
+    rct.top = lm_data->pix_row1_top;
+    CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+    CTOS_IS_PM;
+    rct.top = list_data->sbb_rct.bottom;
+    CTOS_END;
+#endif
+  }
+  *rctp = rct;
+  list_data->sb_rct = rct;
+  list_data->have_sb_rct = TRUE;
+}
+
+void
+xi_move_list_scroll_bar(XI_OBJ *xi_obj)
+{
+  RCT rct;
+  WINDOW win = xi_obj->itf->v.itf->xvt_win;
+  WINDOW sb_win;
+  XI_LIST_DATA *list_data;
+  XI_ITF_DATA *itf_data;
+
+  list_data = xi_obj->v.list;
+  if (list_data->scroll_bar_button)
+    xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win,
+  &list_data->sbb_rct);
+  xi_get_sb_rect(xi_obj, &rct);
+
+  itf_data = xi_obj->itf->v.itf;
+  xi_offset_rect(&rct, itf_data->delta_x, itf_data->delta_y);
+
+  sb_win = list_data->sb_win;
+  if (sb_win && rct.left < rct.right && rct.top < rct.bottom)
+    xvt_vobj_move(sb_win, &rct);
+  if (list_data->scroll_bar_button)
+    xi_invalidate_rect(win, &list_data->sbb_rct);
+}
+
+void
+xi_move_list_hscroll_bar(XI_OBJ *xi_obj)
+{
+  RCT rct;
+  WINDOW hsb_win;
+  XI_LIST_DATA *list_data;
+  XI_ITF_DATA *itf_data;
+
+  list_data = xi_obj->v.list;
+  xi_get_hsb_rect(xi_obj, &rct);
+
+  itf_data = xi_obj->itf->v.itf;
+  xi_offset_rect(&rct, itf_data->delta_x, itf_data->delta_y);
+  hsb_win = list_data->hsb_win;
+  if (hsb_win)
+    xvt_vobj_move(hsb_win, &rct);
+}
+
+BOOLEAN
+xi_half_baked(WINDOW win)
+{
+  XI_OBJ *itf;
+
+  itf = xi_get_itf(win);
+  if (itf)
+    return itf->v.itf->half_baked;
+  return FALSE;
+}
+
+int
+xi_get_sysval(XI_SV_TYPE valtype)
+{
+  return(xi_sysvals[valtype]);
+}
+
+void
+xi_set_sysval(XI_SV_TYPE valtype, int value)
+{
+  xi_sysvals[valtype] = value;
+}
+
+void
+xi_clean_up()
+{
+#if XIWS == MTFWS
+  clean_primesel();
+#endif
+  xvt_font_destroy(xi_sysfont);
+}
+
+long
+xi_get_pref(XI_PREF_TYPE pref_type)
+{
+  long pref;
+
+  pref = xi_preferences[pref_type];
+#if XVT_OS == XVT_OS_CTOS
+  CTOS_IS_CH;
+  switch (pref_type)
+  {
+  case XI_PREF_COLUMN_OFFSET:
+    pref = 0;
+    break;
+  case XI_PREF_SB_OFFSET:
+    pref = 0;
+    break;
+  case XI_PREF_SB_WIDTH:
+    pref = 8;
+    break;
+  case XI_PREF_SB_HEIGHT:
+    pref = 8;
+    break;
+  case XI_PREF_BUTTON_HEIGHT:
+    pref = 24;
+    break;
+  case XI_PREF_BUTTON_PAD:
+    pref = 32;
+    break;
+  case XI_PREF_HORZ_SPACING:
+    pref = 16;
+    break;
+  case XI_PREF_VERT_SPACING:
+    pref = 0;
+    break;
+  case XI_PREF_VERT_PIXEL_SPACING:
+  case XI_PREF_HORZ_PIXEL_SPACING:
+    pref = 0;
+  break;
+  case XI_PREF_ITF_MIN_TOP:
+  pref = 16;
+  break;
+  }
+  CTOS_END;
+#endif
+  return pref;
+}
+
+void xi_set_pref(XI_PREF_TYPE preftype, long value)
+{
+  xi_preferences[preftype] = value;
+}
+
+void
+xi_set_font_id(XVT_FNTID font_id)
+{
+  font_set = TRUE;
+  xi_sysfont = xvt_font_create();
+  xvt_font_copy(xi_sysfont, font_id, (unsigned long)XVT_FA_ALL);
+}
+
+void
+xi_init_sysvals(void)
+{
+  static RCT rct =
+  {
+    -1000,
+    -1000,
+    -900,
+    -900
+  };
+  WINDOW win;
+  int ascent, descent, leading, height;
+
+  if (! font_set)
+  {
+  xi_sysfont = xvt_font_create();
+  xvt_font_set_family(xi_sysfont, XVT_FFN_HELVETICA);
+    xvt_font_set_size(xi_sysfont, 9);
+  }
+  /*
+  Determine height and average width of chosen font.
+  We do this by creating an invisible window and selecting the font
+  into it and getting its metrics.
+  */
+  win = xi_new_child_window(&rct, "", W_DOC, FALSE, FALSE, FALSE, FALSE,
+    FALSE, FALSE, NULL_WIN, 0L, 0, 0L, FALSE, FALSE, 0);
+
+  xvt_font_map(xi_sysfont, win);
+  xvt_dwin_set_font(win, xi_sysfont);
+  xvt_font_get_metrics(xi_sysfont, &leading, &ascent, &descent);
+  xi_set_sysval(XI_SV_SYSFONT_ASCENT, ascent);
+  xi_set_sysval(XI_SV_SYSFONT_DESCENT, descent);
+  xi_set_sysval(XI_SV_SYSFONT_LEADING, leading);
+  height = ascent + descent + leading;
+  xi_set_sysval(XI_SV_FU_HEIGHT, height + STX_VERT_FUDGE);
+  xi_set_sysval(XI_SV_FU_WIDTH,
+    xi_xvt_get_text_width(win,
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", -1) / 52);
+  xi_set_sysval(XI_SV_SYSFONT_HEIGHT, height);
+  xvt_vobj_destroy(win);
+}
+
+/*
+  xi_get_enclosing_rect - get the enclosing rectangle of two other rectangles.
+  ENTRY - src1, src2 are the rects of interest.
+  EXIT  - dst is set to the enclosing rect and returned.
+  If is OK for dst to equal one of the sources.
+*/
+RCT *
+xi_get_enclosing_rect(RCT *dst, RCT *src1, RCT *src2)
+{
+  RCT rct;
+
+  rct.top = min(src1->top, src2->top);
+  rct.left = min(src1->left, src2->left);
+  rct.bottom = max(src1->bottom, src2->bottom);
+  rct.right = max(src1->right, src2->right);
+  *dst = rct;
+  return(dst);
+}
+
+void
+xi_fu_to_pu(XI_OBJ *itf, PNT *pnts, int nbr_pnts)
+{
+  NOREF(itf);
+
+  while (nbr_pnts != 0)
+  {
+    pnts->v = (short)(((long)pnts->v * (long)xi_get_fu_height(itf)) / (long)XI_FU_MULTIPLE);
+    pnts->h = (short)(((long)pnts->h * (long)xi_get_fu_width(itf)) / (long)XI_FU_MULTIPLE);
+    pnts++;
+    nbr_pnts--;
+  }
+}
+
+void
+xi_pu_to_fu(XI_OBJ *itf, PNT *pnts, int nbr_pnts)
+{
+  long fu_h, fu_w;
+
+  NOREF(itf);
+  fu_h = (long)xi_get_fu_height(itf);
+  fu_w = (long)xi_get_fu_width(itf);
+
+  while (nbr_pnts != 0)
+  {
+    pnts->v = (short)(((long)pnts->v * (long)XI_FU_MULTIPLE) / fu_h);
+    pnts->h = (short)(((long)pnts->h * (long)XI_FU_MULTIPLE) / fu_w);
+    pnts++;
+    nbr_pnts--;
+  }
+}
+
+/*
+* xi_tree_realloc2() handles the degenerate case of passing in a NULL
+* pointer for the old pointer.
+*/
+#ifdef TREEDEBUG
+char *
+xi_tree_realloc_d2(char *oldp, size_t size, char *parent, int line,
+char *filename)
+{
+  if (oldp == NULL)
+    return((char *)xi_tree_malloc_d(size, parent, line, filename));
+  else
+    return((char *)xi_tree_realloc_d(oldp, size, line, filename));
+}
+#else
+char *
+xi_tree_realloc2(char *oldp, size_t size, char *parent)
+{
+  if (oldp == NULL)
+    return((char *)xi_tree_malloc(size, parent));
+  else
+    return((char *)xi_tree_realloc(oldp, size));
+}
+#endif
+
+int
+xi_get_text_width(WINDOW win, char *s, int len, unsigned long attrib)
+{
+  char buf[4];
+  int pw_size;
+
+  if (len == -1)
+  len = strlen(s);
+  if (attrib & XI_ATR_PASSWORD)
+  {
+    buf[0] = XI_PASSWORD_CHAR;
+    buf[1] = '\0';
+    pw_size = xi_xvt_get_text_width(win, buf, 1);
+    return (pw_size * len);
+  }
+  else
+    return(xi_xvt_get_text_width(win, s, len));
+}
+
+void
+xi_draw_clipped_text(WINDOW win, char *s, RCT *bound_rctp,
+  RCT *clip_rctp, unsigned long attrib, BOOLEAN set_the_cpen,
+  int rule_and_space, int str_len)
+{
+  int ascent, descent, leading, wid;
+  char buf[256];
+  int len;
+  int baseline;
+  RCT tmp_rct;
+
+  if (! (attrib & XI_ATR_VISIBLE))
+  return;
+  xi_get_font_metrics(win, &leading, &ascent, &descent);
+  tmp_rct = *clip_rctp;
+  /*  Adjust bottom so border is not overwritten */
+  tmp_rct.bottom = tmp_rct.bottom - BORDER_WIDTH;
+  xi_set_clip(win, &tmp_rct);
+  NOREF( set_the_cpen );
+  /*
+  TODO ?????
+  if (set_the_cpen)
+  xi_set_cpen(win, &black_cpen);
+  */
+  len = strlen(s);
+  len = min(len, sizeof(buf) - 1);
+  if (attrib & XI_ATR_PASSWORD)
+    memset(buf, XI_PASSWORD_CHAR, len);
+  else
+    gstrncpy(buf, s, len);
+  buf[len] = '\0';
+#if XI_IS_CH
+  CTOS_IS_CH;
+  NOREF(rule_and_space);
+  baseline = bound_rctp->top + 8;
+  CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+  CTOS_IS_PM;
+  if (attrib & XI_ATR_VCENTER)
+  baseline = bound_rctp->top + leading + ascent + rule_and_space +
+      (bound_rctp->bottom - bound_rctp->top - leading - ascent - descent) / 2 - 1;
+  else
+  baseline = bound_rctp->top + leading + ascent + rule_and_space - 1;
+  CTOS_END;
+#endif
+  if (attrib & XI_ATR_RJUST)
+  {
+  wid = xi_xvt_get_text_width(win, buf, -1);
+  xi_draw_text(win, bound_rctp->right - wid, baseline, buf, str_len);
+  }
+  else
+  {
+  if (attrib & XI_ATR_HCENTER)
+  {
+    int x;
+
+    wid = xi_xvt_get_text_width(win, buf, str_len);
+    x = (bound_rctp->left + bound_rctp->right) / 2 - wid / 2;
+    if (x < bound_rctp->left)
+      x = bound_rctp->left;
+    xi_draw_text(win, x, baseline, buf, str_len);
+  }
+  else
+    xi_draw_text(win, bound_rctp->left, baseline, buf, str_len);
+  }
+  xi_set_clip(win, (RCT *)NULL);
+}
+
+void
+xi_draw_text_attrib(WINDOW win, int x, int y, char *s, int len, unsigned long attrib)
+{
+  char buf[256];
+
+  if (! (attrib & XI_ATR_VISIBLE))
+    return;
+  if (len == -1)
+    len = strlen(s);
+  len = min(len, sizeof(buf) - 1);
+  if (attrib & XI_ATR_PASSWORD)
+    memset(buf, XI_PASSWORD_CHAR, len);
+  else
+    gstrncpy(buf, s, len);
+  buf[len] = '\0';
+#if 0
+#if XIWS == PMWS
+  /* Nasty hack for OS2, because OS2 doesn't draw LTGRAY rectangles
+    correctly, but does if you draw opaque spaces with LTGRAY
+    back color */
+#define BUFSZ 200
+  {
+    char s[BUFSZ], *sp;
+    int i;
+
+    for (i = 0, sp = s; i < BUFSZ; ++i, ++sp)
+      *sp = ' ';
+    s[BUFSZ - 1] = '\0';
+    xi_draw_text(win, x, y, s, -1);
+  }
+#endif
+#endif
+  xi_draw_text(win, x, y, buf, -1);
+}
+
+void
+xi_draw_3d_rect(WINDOW win, RCT *rctp, BOOLEAN well, int height, COLOR color_light, COLOR color_ctrl, COLOR color_dark)
+{
+  RCT rct;
+  PNT pnt, pnt2;
+  CPEN cpen;
+  CBRUSH cbrush;
+
+  if (! color_light)
+  {
+    color_light = xi_get_pref(XI_PREF_COLOR_LIGHT);
+    color_ctrl = xi_get_pref(XI_PREF_COLOR_CTRL);
+    color_dark = xi_get_pref(XI_PREF_COLOR_DARK);
+  }
+  cpen = black_cpen;
+  rct = *rctp;
+  xi_set_draw_mode(win, M_COPY);
+
+  /* draw upper left lines */
+  cpen.color = well ? color_dark : color_light;
+  xi_set_cpen(win, &cpen);
+  pnt.h = rct.left;
+  pnt.v = rct.top;
+  xi_move_to(win, pnt);
+  pnt2.h = rct.left;
+  pnt2.v = rct.bottom - 1;
+  xi_draw_line(win, pnt2);
+
+  xi_move_to(win, pnt);
+  pnt2.h = rct.right - 1;
+  pnt2.v = rct.top;
+  xi_draw_line(win, pnt2);
+
+  if (height == 2)
+  {
+    pnt.h++;
+    pnt.v++;
+    xi_move_to(win, pnt);
+    pnt2.h = pnt.h;
+    pnt2.v = rct.bottom - 2;
+    xi_draw_line(win, pnt2);
+
+    xi_move_to(win, pnt);
+    pnt2.h = rct.right - 2;
+    pnt2.v = pnt.v;
+    xi_draw_line(win, pnt2);
+  }
+
+  /* draw lower right lines */
+  cpen.color = well ? color_light : color_dark;
+  xi_set_cpen(win, &cpen);
+
+  pnt.h = rct.left;
+  pnt.v = rct.bottom - 1;
+  xi_move_to(win, pnt);
+  pnt2.h = rct.right;
+  pnt2.v = pnt.v;
+  xi_draw_line(win, pnt2);
+
+  if (height == 2)
+  {
+    pnt.h++;
+    pnt.v--;
+    xi_move_to(win, pnt);
+    pnt2.v--;
+    xi_draw_line(win, pnt2);
+  }
+
+  pnt.h = rct.right - 1;
+  pnt.v = rct.top;
+  xi_move_to(win, pnt);
+  pnt2.h = pnt.h;
+  pnt2.v = rct.bottom;
+  xi_draw_line(win, pnt2);
+
+  if (height == 2)
+  {
+    pnt.h--;
+    pnt.v++;
+    xi_move_to(win, pnt);
+    pnt2.h = pnt.h;
+    pnt2.v = rct.bottom;
+    xi_draw_line(win, pnt2);
+  }
+
+  xi_set_cpen(win, &hollow_cpen);
+  cbrush = white_cbrush;
+  cbrush.color = color_ctrl;
+  xi_set_cbrush(win, &cbrush);
+  if (height == 2)
+  {
+    rct.top += 2;
+    rct.left += 2;
+    rct.bottom -= 2;
+    rct.right -= 2;
+  }
+  else
+  {
+    rct.top++;
+    rct.left++;
+    rct.bottom--;
+    rct.right--;
+  }
+
+#if XIWS == XOLWS || XIWS == MTFWS
+  /* X GRAY SCALE HACK */
+  xi_set_xvt_back_color(win, COLOR_WHITE);
+  {
+    DRAW_CTOOLS ct;
+
+    xi_get_draw_ctools(win, &ct);
+    ct.opaque_text = FALSE;
+    xi_set_draw_ctools(win, &ct);
+    xi_draw_text(win, rctp->left, rctp->top, " ", -1);
+  }
+#endif
+
+  xi_draw_rect(win, &rct);
+}
+
+void
+xi_draw_3d_line(WINDOW win, PNT pnt1, PNT pnt2, BOOLEAN well)
+{
+  COLOR color_light, color_dark;
+  PNT pnt1x, pnt2x;
+  CPEN cpen;
+
+  color_light = xi_get_pref(XI_PREF_COLOR_LIGHT);
+  color_dark = xi_get_pref(XI_PREF_COLOR_DARK);
+  cpen = black_cpen;
+  xi_set_draw_mode(win, M_COPY);
+
+  cpen.color = well ? color_dark : color_light;
+  xi_set_cpen(win, &cpen);
+  xi_move_to(win, pnt1);
+  xi_draw_line(win, pnt2);
+
+  pnt1x = pnt1;
+  pnt2x = pnt2;
+  if (pnt1x.v == pnt2x.v)
+  {
+  pnt1x.v++;
+  pnt2x.v++;
+  }
+  else
+  {
+  pnt1x.h++;
+  pnt2x.h++;
+  }
+
+  cpen.color = well ? color_light : color_dark;
+  xi_set_cpen(win, &cpen);
+  xi_move_to(win, pnt1x);
+  xi_draw_line(win, pnt2x);
+}
+
+void
+xi_draw_thick_rect(WINDOW win, RCT *rctp, int width)
+{
+  RCT mrct;
+  int i;
+
+  mrct = *rctp;
+  for (i = 0; i < width; ++i)
+  {
+    xi_draw_rect(win, &mrct);
+    mrct.top++;
+    mrct.left++;
+    mrct.bottom--;
+    mrct.right--;
+  }
+}
+
+void
+xi_draw_diamond(WINDOW win, RCT *rctp, BOOLEAN well, BOOLEAN black, BOOLEAN fill,
+COLOR color)
+{
+  PNT pnt1, pnt2;
+  int half_width, width;
+  RCT rct;
+  COLOR color_light, color_ctrl, color_dark;
+  CPEN cpen;
+
+  rct = *rctp;
+  width = (rct.right - rct.left) / 2;
+  width = width * 2 + 1;
+  half_width = width / 2 + 1;
+  rct.right = rct.left + width;
+  rct.bottom = rct.top + width;
+
+  color_light = xi_get_pref(XI_PREF_COLOR_LIGHT);
+  color_ctrl = xi_get_pref(XI_PREF_COLOR_CTRL);
+  color_dark = xi_get_pref(XI_PREF_COLOR_DARK);
+
+  cpen = black_cpen;
+  cpen.color = well ? color_dark : color_light;
+  if (black)
+    cpen.color = COLOR_BLACK;
+  if (color)
+    cpen.color = color;
+  xi_set_cpen(win, &cpen);
+  xi_set_draw_mode(win, M_COPY);
+
+  /* upper left */
+  pnt1.h = rct.left;
+  pnt1.v = rct.top + half_width;
+  xi_move_to(win, pnt1);
+  pnt2.h = rct.left + half_width;
+  pnt2.v = rct.top;
+  xi_draw_line(win, pnt2);
+
+  /* lower left */
+  pnt1.h = rct.left;
+  pnt1.v = rct.top + half_width - 1;
+  xi_move_to(win, pnt1);
+  pnt2.h = rct.left + half_width - 1;
+  pnt2.v = rct.bottom - 1;
+  xi_draw_line(win, pnt2);
+
+  cpen.color = well ? color_light : color_dark;
+  if (black)
+    cpen.color = COLOR_BLACK;
+  if (color)
+    cpen.color = color;
+  xi_set_cpen(win, &cpen);
+
+  /* upper right */
+  pnt1.h = rct.left + half_width;
+  pnt1.v = rct.top + 1;
+  xi_move_to(win, pnt1);
+  pnt2.h = rct.right;
+  pnt2.v = rct.top + half_width;
+  xi_draw_line(win, pnt2);
+
+  /* lower right */
+  pnt1.h = rct.left + half_width - 1;
+  pnt1.v = rct.bottom;
+  xi_move_to(win, pnt1);
+  pnt2.h = rct.right;
+  pnt2.v = rct.top + half_width - 1;
+  xi_draw_line(win, pnt2);
+
+  if (fill)
+  {
+    int h, v1, v2, hwm1;
+    PNT pnt1, pnt2;
+
+    v1 = rct.top + half_width - 1;
+    v2 = rct.top + half_width;
+    cpen.color = color_ctrl;
+    xi_set_cpen(win, &cpen);
+    hwm1 = rct.left + half_width - 1;
+    for (h = rct.left + 1; h <= rct.right - 2; ++h)
+    {
+      pnt1.h = h;
+      pnt1.v = v1;
+      xi_move_to(win, pnt1);
+      pnt2.h = h;
+      pnt2.v = v2;
+      xi_draw_line(win, pnt2);
+      if (h < hwm1)
+      {
+  v1--;
+  v2++;
+      }
+      else
+      {
+  v1++;
+  v2--;
+      }
+    }
+  }
+}
+
+void
+xi_draw_3d_diamond(WINDOW win, RCT *rctp, BOOLEAN well, BOOLEAN black, int height,
+COLOR color)
+{
+  RCT rct;
+  int i;
+
+  rct = *rctp;
+  for (i = 0; i < height; ++i)
+  {
+    xi_draw_diamond(win, &rct, well, black, (BOOLEAN)(i == height - 1), color);
+    rct.top++;
+    rct.left++;
+    rct.bottom--;
+    rct.right--;
+    if (rct.top > rct.bottom || rct.left > rct.right)
+      break;
+  }
+}
+
+char *
+gmemmove(register char *d, register char *s, long n)
+{
+  char *dst = d;
+
+  /* remove when MEDIUM goes away */
+  if (d < s)
+    while (n-- > 0)
+      *d++ = *s++;
+  else
+  {
+    d += (int)n - 1;
+    s += (int)n - 1;
+    while (n-- > 0)
+      *d-- = *s--;
+  }
+  return dst;
+}
+
+#ifdef NEED_MEMMOVE
+char *
+memmove(register char *d, register char *s, long n)
+{
+  char *dst = d;
+
+  /* remove when MEDIUM goes away */
+  if (d < s)
+    while (n-- > 0)
+      *d++ = *s++;
+  else
+  {
+    d += (int)n - 1;
+    s += (int)n - 1;
+    while (n-- > 0)
+      *d-- = *s--;
+  }
+  return dst;
+}
+#endif
+
+#if XIWS != WMWS
+void
+dbg_rct(char *tag, RCT *rct)
+{
+  char buf[100];
+
+  sprintf(buf,
+      "%s: top %d left %d bottom %d right %d", tag, rct->top, rct->left,
+      rct->bottom, rct->right);
+  xi_dbg(buf);
+}
+#endif
+
+void
+xi_get_font_metrics(WINDOW win, int *leadingp, int *ascentp, int *descentp)
+{
+  xvt_dwin_get_font_metrics(win, leadingp, ascentp, descentp);
+#if XVTWS == WINWS
+  if (*leadingp == 0)
+  {
+  *leadingp = 2;
+    *ascentp -= 2;
+  }
+#endif
+}
+
+void
+xi_set_xvt_font(WINDOW win, FONT_OBJ *fontp, BOOLEAN scale)
+{
+  NOREF(scale);
+/*  xvt_font_map(*fontp, win);  this causes GPF in XVT, even though it is valid */
+  xvt_dwin_set_font(win, *fontp);
+}
+
+void
+xi_set_cur_window(WINDOW win)
+{
+  cur_window = win;
+  cur_itf = xi_get_itf(win);
+  if (cur_itf)
+  {
+    cur_delta_x = cur_itf->v.itf->delta_x;
+    cur_delta_y = cur_itf->v.itf->delta_y;
+  }
+  else
+  {
+    cur_delta_x = 0;
+    cur_delta_y = 0;
+  }
+}
+
+void
+xi_set_draw_ctools(WINDOW win, DRAW_CTOOLS *ct)
+{
+  xvt_dwin_set_draw_ctools(win, ct);
+#if XIWS == WMWS
+  {
+  DRAW_CTOOLS lct;
+
+  lct = *ct;
+  xi_fix_color(&lct.pen.color);
+  xi_fix_color(&lct.brush.color);
+  xi_fix_color(&lct.back_color);
+  xi_fix_color(&lct.fore_color);
+  xvt_dwin_set_draw_ctools(win, &lct);
+  }
+#else
+  xvt_dwin_set_draw_ctools(win, ct);
+#endif
+}
+
+void
+xi_set_draw_mode(WINDOW win, DRAW_MODE mode)
+{
+  xvt_dwin_set_draw_mode(win, mode);
+}
+
+void
+xi_set_cbrush(WINDOW win, CBRUSH *cbrush)
+{
+#if XIWS == WMWS
+  {
+  CBRUSH lcbrush;
+
+  lcbrush = *cbrush;
+  xi_fix_color(&lcbrush.color);
+  xvt_dwin_set_cbrush(win, &lcbrush);
+  }
+#else
+  xvt_dwin_set_cbrush(win, cbrush);
+#endif
+}
+
+void
+xi_set_cpen(WINDOW win, CPEN *cpen)
+{
+#if XIWS == WMWS
+  {
+  CPEN lcpen;
+
+  lcpen = *cpen;
+  xi_fix_color(&lcpen.color);
+  xvt_dwin_set_cpen(win, &lcpen);
+  }
+#else
+  xvt_dwin_set_cpen(win, cpen);
+#endif
+}
+
+void
+xi_set_xvt_back_color(WINDOW win, COLOR color)
+{
+#if XIWS == WMWS
+  xi_fix_color(&color);
+#endif
+  xvt_dwin_set_back_color(win, color);
+}
+
+void
+xi_set_xvt_fore_color(WINDOW win, COLOR color)
+{
+  xvt_dwin_set_fore_color(win, color);
+}
+
+DRAW_CTOOLS *
+xi_get_draw_ctools(WINDOW win, DRAW_CTOOLS *ct)
+{
+  return xvt_dwin_get_draw_ctools(win, ct);
+}
+
+void
+xi_dbg(char *buf)
+{
+  xvt_debug_printf(buf);
+}
+
+WINDOW xi_new_child_window(RCT *rctp, char *title, WIN_TYPE t,
+BOOLEAN ctl_size, BOOLEAN ctl_vscroll, BOOLEAN ctl_hscroll,
+BOOLEAN ctl_close, BOOLEAN ctl_iconized, BOOLEAN ctl_iconizable,
+WINDOW parent, long app_data, short reserve1,
+long reserve2, BOOLEAN visible, BOOLEAN enabled, int menu_bar_rid)
+{
+  long flags;
+  WINDOW win;
+
+  NOREF(reserve1);
+  NOREF(reserve2);
+  if (! parent)
+#if (XIWS != XOLWS)
+  parent = TASK_WIN;
+#else
+  parent = SCREEN_WIN;
+#endif
+  flags = (ctl_size ? WSF_SIZE : 0) |
+    (ctl_close ? WSF_CLOSE : 0) |
+    (ctl_iconized ? WSF_ICONIZED : 0) |
+    (ctl_iconizable ? WSF_ICONIZABLE : 0) |
+    (ctl_hscroll ? WSF_HSCROLL : 0) |
+    (ctl_vscroll ? WSF_VSCROLL : 0) |
+    (visible ? 0 : WSF_INVISIBLE) |
+    (enabled ? 0 : WSF_DISABLED) |
+    (menu_bar_rid ? 0 : WSF_NO_MENUBAR);
+  win = xvt_win_create(t, rctp, title, menu_bar_rid, parent, flags, EM_ALL,
+    (EVENT_HANDLER)xi_event, app_data);
+  xvt_errmsg_sig_if(!(win), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20090",
+    20090, "xvt_win_create returned NULL");   
+  xvt_vobj_set_attr(NULL_WIN, ATTR_SUPPRESS_UPDATE_CHECK, (long)TRUE);
+  return win;
+}
+
+void
+xi_terminate(void)
+{
+  xvt_app_destroy();
+}
+
+int
+xi_xvt_get_text_width(WINDOW win, char *string, int len)
+{
+  return xvt_dwin_get_text_width(win, string, len);
+}
+
+void xi_even_fu(int *f)
+{
+  *f = (*f * XI_FU_MULTIPLE + XI_FU_MULTIPLE / 2) / XI_FU_MULTIPLE;
+}
+
+void xi_even_fu_pnt(PNT *p)
+{
+  p->h = (p->h * XI_FU_MULTIPLE + XI_FU_MULTIPLE / 2) / XI_FU_MULTIPLE;
+  p->v = (p->v * XI_FU_MULTIPLE + XI_FU_MULTIPLE / 2) / XI_FU_MULTIPLE;
+}
+
+int
+xi_get_fu_width(XI_OBJ *itf)
+{
+  if (itf)
+    return itf->v.itf->fu_width;
+  else
+    return xi_get_fu_width_font(&xi_sysfont);
+}
+
+int
+xi_get_fu_height(XI_OBJ *itf)
+{
+  if (itf)
+    return itf->v.itf->fu_height;
+  else
+    return xi_get_fu_height_font(&xi_sysfont);
+}
+
+int
+xi_get_fu_width_font(FONT_OBJ *font)
+{
+  int leading, ascent, descent, char_width;
+
+  xi_get_font_metrics_font(font, &leading, &ascent, &descent, &char_width);
+  return char_width;
+}
+
+int
+xi_get_fu_height_font(FONT_OBJ *font)
+{
+  int leading, ascent, descent, char_width;
+  int height;
+
+  xi_get_font_metrics_font(font, &leading, &ascent, &descent, &char_width);
+  height = leading + ascent + descent + STX_VERT_FUDGE;
+  return height;
+}
+
+void
+xi_fu_to_pu_font(FONT_OBJ *font, PNT *pnts, int nbr_pnts)
+{
+  int leading, ascent, descent, char_width;
+  int height;
+
+  xi_get_font_metrics_font(font, &leading, &ascent, &descent, &char_width);
+  height = leading + ascent + descent + STX_VERT_FUDGE;
+  while (nbr_pnts != 0)
+  {
+    pnts->v = (short)(((long)pnts->v * (long)height) / (long)XI_FU_MULTIPLE);
+    pnts->h = (short)(((long)pnts->h * (long)char_width) / (long)XI_FU_MULTIPLE);
+    pnts++;
+    nbr_pnts--;
+  }
+}
+
+#define FONT_ATTR_SIZE 256  /* family or native_desc size */
+
+/*
+  The following font comparison routine is not general
+  purpose, it does not properly handle the case where one
+  of the compared fonts has the native descriptor and the
+  other one does not.
+  This does not matter in case of xi, where we compare
+  if an (unmapped) font matches an already mapped one,
+  and thus native descriptor is only important when
+  both fonts have it set.
+*/
+BOOLEAN font_compare ( XVT_FNTID f1, XVT_FNTID f2 ) {
+  char  buf1[FONT_ATTR_SIZE];
+  char  buf2[FONT_ATTR_SIZE];
+
+  if (f1 == f2)
+  return TRUE;
+
+  /* If both font have valid native descs, compare those */
+  if ( xvt_font_get_native_desc(f1, buf1, FONT_ATTR_SIZE) &&
+    xvt_font_get_native_desc(f2, buf2, FONT_ATTR_SIZE)) {
+  if ( *buf1 && *buf2 )
+    return ( strncmp(buf1, buf2, FONT_ATTR_SIZE ) == 0 );
+  }
+
+  /* If one of the fonts lacks nd, compare portable attrs */
+  if ( xvt_font_get_style(f1) != xvt_font_get_style(f2) )
+  return FALSE;
+
+  if ( xvt_font_get_size (f1) != xvt_font_get_size (f2) )
+  return FALSE;
+
+  if ( !xvt_font_get_family( f1, buf1, FONT_ATTR_SIZE ))
+  return FALSE;
+  if ( !xvt_font_get_family( f2, buf2, FONT_ATTR_SIZE ))
+  return FALSE;
+
+  return ( strncmp(buf1, buf2, FONT_ATTR_SIZE ) == 0 );
+}
+
+void
+xi_get_font_metrics_font(FONT_OBJ *font, int *leading,
+int *ascent, int *descent, int *char_width)
+{
+  typedef struct
+  {
+  XVT_FNTID font_id;
+  int leading;
+  int ascent;
+  int descent;
+  int char_width;
+  } FONT_INFO;
+
+  static FONT_INFO *font_info, *fi;
+  static int font_info_cnt = 0;
+  int i;
+  WINDOW win;
+  BOOLEAN close_win = FALSE;
+
+  for (i = 0, fi = font_info; i < font_info_cnt; ++i, ++fi)
+  {
+  if (font_compare(fi->font_id, *font))
+  {
+    *leading = fi->leading;
+    *ascent = fi->ascent;
+    *descent = fi->descent;
+    *char_width = fi->char_width;
+    return;
+  }
+  }
+  ++font_info_cnt;
+  if (font_info)
+  font_info = (FONT_INFO *)xi_tree_realloc(font_info, sizeof(FONT_INFO) * font_info_cnt);
+  else
+  font_info = (FONT_INFO *)xi_tree_malloc(sizeof(FONT_INFO) * font_info_cnt, (void *)NULL);
+  fi = &font_info[font_info_cnt - 1];
+  fi->font_id = xvt_font_create();
+  xvt_font_copy(fi->font_id, *font, (unsigned long)XVT_FA_ALL);
+/* Remove this code because we can't assume that a window with focus is
+  drawable - it could be a dialog. Create a dummy window in all cases.
+
+  win = xvt_scr_get_focus_vobj();
+  if (! win || win == TASK_WIN)
+*/
+  {
+  RCT rct;
+
+  rct.top = -200;
+  rct.left = -200;
+  rct.bottom = -100;
+  rct.right = -100;
+  win = xi_new_child_window(&rct, "", W_DOC, FALSE, FALSE, FALSE, FALSE,
+  FALSE, FALSE, NULL_WIN, 0L, 0, 0L, FALSE, FALSE, 0);
+  close_win = TRUE;
+  }
+  xi_set_xvt_font(win, font, FALSE);
+  {
+  int tl, ta, td;
+  xi_get_font_metrics(win, &tl, &ta, &td);
+  fi->leading = tl;
+  fi->ascent = ta;
+  fi->descent = td;
+  }
+  fi->char_width = xi_xvt_get_text_width(win, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", -
+    1) / 52;
+  if (close_win)
+  xvt_vobj_destroy(win);
+  *leading = fi->leading;
+  *ascent = fi->ascent;
+  *descent = fi->descent;
+  *char_width = fi->char_width;
+}
+
+/********************************************************************/
+/* FUNCTIONS THAT NEED TRANSPOSING */
+
+static void
+ppnt_to_vpnt(WINDOW win, PNT *pnt)
+{
+  XI_OBJ *itf;
+  XI_ITF_DATA *itf_data;
+
+  itf = xi_get_itf(win);
+  if (itf)
+  {
+    itf_data = itf->v.itf;
+    pnt->h += itf_data->delta_x;
+    pnt->v += itf_data->delta_y;
+  }
+}
+
+static void
+vpnt_to_ppnt(WINDOW win, PNT *pnt)
+{
+  XI_ITF_DATA *itf_data;
+
+  itf_data = (xi_get_itf(win))->v.itf;
+  pnt->h -= itf_data->delta_x;
+  pnt->v -= itf_data->delta_y;
+}
+
+#define VPNT_TO_PPNT(pp) \
+  (pp)->h -= cur_delta_x; \
+  (pp)->v -= cur_delta_y;
+
+static void
+vrct_to_prct(WINDOW win, RCT *rct)
+{
+  XI_ITF_DATA *itf_data;
+
+  itf_data = (xi_get_itf(win))->v.itf;
+  rct->left -= itf_data->delta_x;
+  rct->right -= itf_data->delta_x;
+  rct->top -= itf_data->delta_y;
+  rct->bottom -= itf_data->delta_y;
+}
+
+#define VRCT_TO_PRCT(rp) \
+  (rp)->left -= cur_delta_x; \
+  (rp)->right -= cur_delta_x; \
+  (rp)->top -= cur_delta_y; \
+  (rp)->bottom -= cur_delta_y;
+
+static void move_tx_edit( XI_OBJ* xi_obj )
+{
+  TXEDIT       text_edit;
+  XI_ITF_DATA* itf_data;
+  RCT          rect;
+  RCT          new_rect;
+  WINDOW       window;
+
+  text_edit = xi_get_txedit( xi_obj );
+  if (text_edit == BAD_TXEDIT)
+    return;
+  window = xvt_tx_get_win( text_edit );
+  itf_data = xi_obj->itf->v.itf;
+  xvt_tx_get_rect( text_edit , &rect); 
+  stx_get_inside_rect( xi_obj->v.field->stx, &new_rect );
+  xi_offset_rect(&new_rect, itf_data->delta_x, itf_data->delta_y);
+  xvt_tx_move(text_edit, &new_rect );
+  xi_inflate_rect(&new_rect, 1);
+  xvt_dwin_invalidate_rect(window, &new_rect);
+  xi_inflate_rect(&rect, 1);
+  xvt_dwin_invalidate_rect(window, &rect);
+}
+
+static void move_xvt_controls(XI_OBJ *xi_obj )
+{
+  XI_OBJ * *objlist;
+  int n;
+  RCT rct;
+
+  switch (xi_obj->type)
+  {
+  case XIT_ITF:
+    if (! xi_obj->v.itf->half_baked)
+      xvt_dwin_update(xi_obj->v.itf->xvt_win);
+    break;
+  case XIT_FIELD:
+    move_tx_edit( xi_obj );
+    break;
+  case XIT_LIST:
+    {
+      XI_LIST_DATA *list_data;
+      XI_ITF_DATA *itf_data;
+
+      itf_data = xi_obj->itf->v.itf;
+      list_data = xi_obj->v.list;
+      if (list_data->sb_win)
+      {
+  xi_get_sb_rect(xi_obj, &rct);
+  xi_offset_rect(&rct, itf_data->delta_x, itf_data->delta_y);
+  xvt_vobj_move(list_data->sb_win, &rct);
+      }
+      if (list_data->hsb_win)
+      {
+  xi_get_hsb_rect(xi_obj, &rct);
+  xi_offset_rect(&rct, itf_data->delta_x, itf_data->delta_y);
+  xvt_vobj_move(list_data->hsb_win, &rct);
+      }
+      break;
+    }
+  case XIT_BTN:
+    {
+      RCT rct;
+      XI_ITF_DATA *itf_data;
+      XI_BTN_DATA *btn_data;
+
+      btn_data = xi_obj->v.btn;
+      if (btn_data->btnctl)
+      {
+  itf_data = xi_obj->itf->v.itf;
+  rct = btn_data->rct;
+  xi_offset_rect(&rct, itf_data->delta_x, itf_data->delta_y);
+  xvt_vobj_move(btn_data->btnctl, &rct);
+      }
+      break;
+    }
+  }
+  objlist = xi_get_member_list(xi_obj, &n);
+  for (; n > 0; n--, objlist++)
+    move_xvt_controls(*objlist );
+  if (xi_obj->type == XIT_ITF)
+    xi_set_clip(xi_obj->v.itf->xvt_win, NULL);
+}
+
+
+void
+xi_adjust_sb_vir_itf(WINDOW win, XI_OBJ *itf)
+{
+  RCT rct;
+  XI_ITF_DATA *itf_data;
+
+  itf_data = itf->v.itf;
+  xvt_vobj_get_client_rect(win, &rct);
+  itf_data->win_xi_pnt.v = rct.bottom - rct.top;
+  itf_data->win_xi_pnt.h = rct.right - rct.left;
+  xi_pu_to_fu(itf, &itf_data->win_xi_pnt, 1);
+  xi_even_fu_pnt(&itf_data->win_xi_pnt);
+  if (itf_data->win_xi_pnt.h + itf_data->phys_xi_pnt.h >
+      itf_data->max_xi_pnt.h ||
+      itf_data->win_xi_pnt.v + itf_data->phys_xi_pnt.v >
+      itf_data->max_xi_pnt.v)
+  {
+    PNT p;
+    int old_delta_x, old_delta_y;
+
+    if (itf_data->win_xi_pnt.h + itf_data->phys_xi_pnt.h >
+  itf_data->max_xi_pnt.h)
+      itf_data->phys_xi_pnt.h = itf_data->max_xi_pnt.h -
+    itf_data->win_xi_pnt.h;
+    if (itf_data->phys_xi_pnt.h < 0)
+      itf_data->phys_xi_pnt.h = 0;
+    if (itf_data->win_xi_pnt.v + itf_data->phys_xi_pnt.v >
+  itf_data->max_xi_pnt.v)
+      itf_data->phys_xi_pnt.v = itf_data->max_xi_pnt.v -
+    itf_data->win_xi_pnt.v;
+    if (itf_data->phys_xi_pnt.v < 0)
+      itf_data->phys_xi_pnt.v = 0;
+    p.h = itf_data->phys_xi_pnt.h;
+    p.v = itf_data->phys_xi_pnt.v;
+    xi_fu_to_pu(itf, &p, 1);
+    cur_delta_x = p.h;
+    cur_delta_y = p.v;
+    old_delta_x = itf_data->delta_x;
+    old_delta_y = itf_data->delta_y;
+    itf_data->delta_x = cur_delta_x;
+    itf_data->delta_y = cur_delta_y;
+    xi_caret_suspend(win);
+    if (old_delta_x != cur_delta_x || old_delta_y != cur_delta_y)
+      xvt_dwin_invalidate_rect(win, NULL);
+    move_xvt_controls( itf );
+    xi_caret_restore(win);
+  }
+  set_sb_positions(itf);
+}
+
+
+BOOLEAN
+xi_eh(WINDOW win, EVENT *ep)
+{
+  switch (ep->type)
+  {
+  case E_UPDATE:
+    update_pending = FALSE;
+  xi_set_cur_window(win);
+  break;
+  case E_CHAR:
+  if (update_pending && (ep->v.chr.ch == K_UP || ep->v.chr.ch == K_DOWN))
+    return FALSE;
+  break;
+  case E_SIZE:
+    {
+      XI_OBJ *itf;
+      XI_ITF_DATA *itf_data;
+      RCT rct;
+
+      itf = xi_get_itf(win);
+      if (! itf)
+  break;
+      itf_data = itf->v.itf;
+      if (itf_data->size_font_to_win)
+      {
+  RCT old_win_rct;
+  int bottom, right;
+  XVT_FNTID *itf_font_id;
+
+  xvt_vobj_get_client_rect(win, &rct);
+  old_win_rct = itf->v.itf->original_win_rct;
+  bottom = old_win_rct.bottom;
+  right = old_win_rct.right;
+  itf_font_id = itf_data->font;
+  if (itf_font_id)
+  {
+    int point_size, point_size2;
+
+    point_size = itf->v.itf->original_font_size;
+    point_size = (point_size * rct.bottom + bottom / 2) / bottom;
+    point_size2 = itf->v.itf->original_font_size;
+    point_size2 = (point_size2 * rct.right + right / 2) / right;
+    xvt_font_set_size(*itf_font_id, point_size2 - 1);
+    xi_set_obj_font_id(itf, *itf_font_id);
+  }
+  break;
+    }
+    if (itf_data->virtual_itf)
+  xi_adjust_sb_vir_itf(win, itf);
+    break;
+  }
+  case E_MOUSE_DOWN:
+  case E_MOUSE_UP:
+  case E_MOUSE_DBL:
+  case E_MOUSE_MOVE:
+    ppnt_to_vpnt(win, &ep->v.mouse.where);
+    break;
+  case E_HSCROLL:
+    {
+      XI_OBJ *itf;
+      XI_ITF_DATA *itf_data;
+      int delta_x, old, d;
+
+      itf = xi_get_itf(win);
+      if (! itf)
+  break;
+      itf_data = itf->v.itf;
+      if (! itf_data->virtual_itf)
+  break;
+      switch (ep->v.scroll.what)
+      {
+      case SC_LINE_UP:
+  delta_x = -4 * XI_FU_MULTIPLE;
+  break;
+      case SC_LINE_DOWN:
+  delta_x = 4 * XI_FU_MULTIPLE;
+  break;
+      case SC_PAGE_UP:
+  delta_x = -10 * XI_FU_MULTIPLE;
+  break;
+      case SC_PAGE_DOWN:
+  delta_x = 10 * XI_FU_MULTIPLE;
+  break;
+      case SC_THUMB:
+  {
+    int oldp, newp;
+
+    oldp = itf_data->phys_xi_pnt.h;
+    newp = (int)((long)ep->v.scroll.pos *
+        ((long)itf_data->max_xi_pnt.h -
+        (long)itf_data->win_xi_pnt.h) / 100L);
+    xi_even_fu(&newp);
+    delta_x = newp - oldp;
+    break;
+  }
+      case SC_THUMBTRACK:
+  delta_x = 0;
+  break;
+      }
+      old = itf_data->phys_xi_pnt.h;
+      itf_data->phys_xi_pnt.h += delta_x;
+      itf_data->phys_xi_pnt.h =
+    min(itf_data->phys_xi_pnt.h, itf_data->max_xi_pnt.h -
+    itf_data->win_xi_pnt.h);
+      itf_data->phys_xi_pnt.h =
+    max(itf_data->phys_xi_pnt.h, 0);
+      d = itf_data->phys_xi_pnt.h - old;
+
+      /* d is now the delta in form units */
+      if (d)
+      {
+  RCT client_rct;
+  PNT pnt;
+
+  xvt_dwin_update(win);
+  xvt_vobj_get_client_rect(win, &client_rct);
+  pnt.h = itf_data->phys_xi_pnt.h;
+  xi_fu_to_pu(itf, &pnt, 1);
+  cur_delta_x = pnt.h;
+  pnt.h = d;
+  xi_fu_to_pu(itf, &pnt, 1);
+  xi_caret_suspend(win);
+  do_vir_pan_event(itf, pnt.h, 0, TRUE);
+  itf_data->delta_x += pnt.h;
+#if XIWS == WMWS
+  /*
+  Hack for *VERY* nasty bug in XVT/CH - need to call
+  xvt_dwin_set_clip twice, to make XVT/CH have no clipping region
+  for xvt_dwin_scroll_rect.
+  */
+  {
+    RCT rct;
+
+    rct = client_rct;
+    xi_inflate_rect(&rct, 120);
+    xi_set_clip(win, &rct);
+    xi_set_clip(win, NULL);
+  }
+#endif
+  xvt_dwin_scroll_rect(win, &client_rct, -pnt.h, 0);
+  set_sb_positions(itf);
+  move_xvt_controls(itf );
+  do_vir_pan_event(itf, pnt.h, 0, FALSE);
+  xi_caret_restore(win);
+      }
+      break;
+    }
+  case E_VSCROLL:
+    {
+      XI_OBJ *itf;
+      XI_ITF_DATA *itf_data;
+      int delta_y, old, d;
+
+      itf = xi_get_itf(win);
+      if (! itf)
+  break;
+      itf_data = itf->v.itf;
+      if (! itf_data->virtual_itf)
+  break;
+      switch (ep->v.scroll.what)
+      {
+      case SC_LINE_UP:
+  delta_y = -XI_FU_MULTIPLE;
+  break;
+      case SC_LINE_DOWN:
+  delta_y = XI_FU_MULTIPLE;
+  break;
+      case SC_PAGE_UP:
+  delta_y = -10 * XI_FU_MULTIPLE;
+  break;
+      case SC_PAGE_DOWN:
+  delta_y = 10 * XI_FU_MULTIPLE;
+  break;
+      case SC_THUMB:
+  {
+    int oldp, newp;
+
+    oldp = itf_data->phys_xi_pnt.v;
+    newp = (int)((long)ep->v.scroll.pos *
+        ((long)itf_data->max_xi_pnt.v -
+        (long)itf_data->win_xi_pnt.v) / 100L);
+    xi_even_fu(&newp);
+    delta_y = newp - oldp;
+    break;
+  }
+      case SC_THUMBTRACK:
+  delta_y = 0;
+  break;
+      }
+      old = itf_data->phys_xi_pnt.v;
+      itf_data->phys_xi_pnt.v += delta_y;
+      itf_data->phys_xi_pnt.v =
+    min(itf_data->phys_xi_pnt.v, itf_data->max_xi_pnt.v -
+    itf_data->win_xi_pnt.v);
+      itf_data->phys_xi_pnt.v =
+    max(itf_data->phys_xi_pnt.v, 0);
+      d = itf_data->phys_xi_pnt.v - old;
+      if (d)
+      {
+  RCT client_rct;
+  PNT pnt;
+
+  xvt_dwin_update(win);
+  xvt_vobj_get_client_rect(win, &client_rct);
+  pnt.v = itf_data->phys_xi_pnt.v;
+  xi_fu_to_pu(itf, &pnt, 1);
+  cur_delta_y = pnt.v;
+  pnt.v = d;
+  xi_fu_to_pu(itf, &pnt, 1);
+  xi_caret_suspend(win);
+  do_vir_pan_event(itf, 0, pnt.v, TRUE);
+  itf_data->delta_y += pnt.v;
+#if XIWS == WMWS
+  {
+    RCT rct;
+
+    rct = client_rct;
+    rct.bottom += 24;
+    xi_set_clip(win, &rct);
+    xi_set_clip(win, NULL);
+  }
+#endif
+  xvt_dwin_scroll_rect(win, &client_rct, 0, -pnt.v);
+  set_sb_positions(itf);
+  move_xvt_controls(itf );
+  do_vir_pan_event(itf, 0, pnt.v, FALSE);
+  xi_caret_restore(win);
+      }
+      break;
+    }
+  }
+  return TRUE;
+}
+
+void
+xi_vir_pan(XI_OBJ *itf, int delta_x, int delta_y)
+{
+  RCT cr;
+  WINDOW win;
+  XI_ITF_DATA *itf_data;
+  PNT pf, p;
+  int old;
+
+  pf.h = delta_x;
+  pf.v = delta_y;
+  itf_data = itf->v.itf;
+  win = xi_get_window(itf);
+  xvt_vobj_get_client_rect(win, &cr);
+  xvt_dwin_update(win);
+
+  /* clip y delta to appropriate bounding */
+  old = itf_data->phys_xi_pnt.v;
+  itf_data->phys_xi_pnt.v += pf.v;
+  itf_data->phys_xi_pnt.v =
+      min(itf_data->phys_xi_pnt.v, itf_data->max_xi_pnt.v -
+      itf_data->win_xi_pnt.v);
+  if (itf_data->phys_xi_pnt.v < 0)
+    itf_data->phys_xi_pnt.v = 0;
+  pf.v = itf_data->phys_xi_pnt.v - old;
+
+  /* clip x delta to appropriate bounding */
+  old = itf_data->phys_xi_pnt.h;
+  itf_data->phys_xi_pnt.h += pf.h;
+  itf_data->phys_xi_pnt.h =
+      min(itf_data->phys_xi_pnt.h, itf_data->max_xi_pnt.h -
+      itf_data->win_xi_pnt.h);
+  if (itf_data->phys_xi_pnt.h < 0)
+    itf_data->phys_xi_pnt.h = 0;
+  pf.h = itf_data->phys_xi_pnt.h - old;
+
+  /* convert to pixel coordinates */
+  p = pf;
+  xi_fu_to_pu(itf, &p, 1);
+
+  /* add to current delta x and y */
+  cur_delta_y += p.v;
+  cur_delta_x += p.h;
+
+  /* do the virtual pan */
+  xi_caret_suspend(win);
+  do_vir_pan_event(itf, p.h, p.v, TRUE);
+  itf_data->delta_y = cur_delta_y;
+  itf_data->delta_x = cur_delta_x;
+#if XIWS == WMWS
+  {
+  RCT rct;
+
+  rct = cr;
+  rct.bottom += 24;
+  xi_set_clip(win, &cr);
+  xi_set_clip(win, NULL);
+  }
+#endif
+  xvt_dwin_scroll_rect(win, &cr, -p.h, -p.v);
+  set_sb_positions(itf);
+  move_xvt_controls(itf);
+  do_vir_pan_event(itf, p.h, p.v, FALSE);
+  xi_caret_restore(win);
+}
+
+void
+xi_make_obj_visible(XI_OBJ *xi_obj)
+{
+  RCT or, cr, cr2;
+  XI_OBJ *itf;
+  XI_ITF_DATA *itf_data;
+  WINDOW win;
+  int dt, db, dl, dr, dh, dv;
+  PNT p, pf, pp;
+  int pref_h, pref_v;
+
+  switch (xi_obj->type)
+  {
+  case XIT_ITF:
+  case XIT_GROUP:
+  case XIT_FORM:
+  case XIT_LIST:
+  case XIT_COLUMN:
+  case XIT_CONTAINER:
+    return;
+  }
+  pref_h = (int)xi_get_pref(XI_PREF_VIR_SP_H);
+  pref_v = (int)xi_get_pref(XI_PREF_VIR_SP_V);
+  itf = xi_obj->itf;
+  itf_data = itf->v.itf;
+  win = xi_get_window(itf);
+  xi_set_cur_window(win);
+  xvt_vobj_get_client_rect(win, &cr);
+  pp.v = itf_data->max_xi_pnt.v;
+  pp.h = itf_data->max_xi_pnt.h;
+  xi_fu_to_pu(xi_obj->itf, &pp, 1);
+  xi_get_rect(xi_obj, &or);
+  or.top -= pref_v;
+  if (or.top < 0)
+    or.top = 0;
+  or.bottom += pref_v;
+  if (or.bottom > pp.v)
+    or.bottom = pp.v;
+  or.left -= pref_h;
+  if (or.left < 0)
+    or.left = 0;
+  or.right += pref_h;
+  if (or.right > pp.h)
+    or.right = pp.h;
+  cr2 = cr;
+  cr2.left += itf_data->delta_x;
+  cr2.right += itf_data->delta_x;
+  cr2.top += itf_data->delta_y;
+  cr2.bottom += itf_data->delta_y;
+  dr = or.right - cr2.right;  /* positive if not ok */
+  dr = max(0, dr);
+  dr = min(dr, pp.h);
+  db = or.bottom - cr2.bottom;  /* positive if not ok */
+  db = max(0, db);
+  db = min(db, pp.v);
+  dl = cr2.left - or.left;  /* positive if not ok */
+  dl = max(0, dl);
+  dt = cr2.top - or.top;  /* positive if not ok */
+  dt = max(0, dt);
+  if (dl && dr)
+    dr = 0;
+  if (db && dt)
+    db = 0;
+  if (dl)
+    dh = -dl;
+  else
+    dh = dr;
+  if (dt)
+    dv = -dt;
+  else
+    dv = db;
+  p.h = dh;
+  p.v = dv;
+  xi_pu_to_fu(xi_obj->itf, &p, 1);
+  xi_even_fu_pnt(&p);
+  pf = p;
+  xi_fu_to_pu(xi_obj->itf, &p, 1);
+  if (p.h || p.v)
+  {
+    xvt_dwin_update(win);
+    itf_data->phys_xi_pnt.v += pf.v;
+    itf_data->phys_xi_pnt.h += pf.h;
+    cur_delta_y += p.v;
+    cur_delta_x += p.h;
+    xi_caret_suspend(win);
+    do_vir_pan_event(itf, p.h, p.v, TRUE);
+    itf_data->delta_y = cur_delta_y;
+    itf_data->delta_x = cur_delta_x;
+#if XIWS == WMWS
+  {
+    RCT rct;
+
+    xvt_vobj_get_client_rect(win, &rct);
+    rct.bottom += 24;
+    xi_set_clip(win, &rct);
+    xi_set_clip(win, NULL);
+  }
+#endif
+  xvt_dwin_scroll_rect(win, &cr, -p.h, -p.v);
+  set_sb_positions(itf);
+  move_xvt_controls(itf);
+  do_vir_pan_event(itf, p.h, p.v, FALSE);
+  xi_caret_restore(win);
+  }
+}
+
+WINDOW
+xi_new_control(RCT *lrctp, char *title, WIN_TYPE t, WINDOW parent,
+BOOLEAN visible, int id, char *templat)
+{
+  long ctl_flags;
+  RCT r;
+
+  r = *lrctp;
+  vrct_to_prct(parent, &r);
+
+  NOREF(templat);
+  ctl_flags = (visible ? 0 : CTL_FLAG_INVISIBLE);
+  return xvt_ctl_create(t, &r, title, parent, ctl_flags, 0L, id);
+}
+
+void
+xi_scroll_rect(WINDOW win, RCT *rctp, int dh, int dv)
+{
+  RCT r;
+
+  xi_set_cur_window(win);
+  r = *rctp;
+  VRCT_TO_PRCT(&r);
+  update_pending = TRUE;
+#if 0
+  {
+  HWND hwnd;
+  RECT rect;
+
+  rect.left = r.left;
+  rect.top = r.top;
+  rect.right = r.right;
+  rect.bottom = r.bottom;
+  hwnd = xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW);
+  ScrollWindow(hwnd, dh, dv, &rect, &rect);
+  }
+#endif
+#if XIWS == WMWS
+  NOREF(dh);
+  NOREF(dv);
+  xvt_dwin_invalidate_rect(win, &r);
+#else
+  xvt_dwin_set_clip(win, &r);
+  xvt_dwin_scroll_rect(win, &r, dh, dv);
+#endif
+}
+
+void
+xi_draw_text(WINDOW win, int x, int y, char *string, int len)
+{
+  xi_set_cur_window(win);
+    x -= cur_delta_x;
+    y -= cur_delta_y;
+#if XIWS == WMWS
+  y -= 8;
+  {
+  DRAW_CTOOLS ct;
+
+  xvt_dwin_get_draw_ctools(win, &ct);
+  if (ct.mode == M_XOR)
+    xvt_dwin_set_draw_mode(win, M_COPY);
+  }
+#endif
+  xvt_dwin_draw_text(win, x, y, string, len);
+}
+
+void
+xi_set_clip(WINDOW win, RCT *rctp)
+{
+  RCT r;
+
+  if (rctp)
+  {
+    r = *rctp;
+    vrct_to_prct(win, &r);
+
+    if (r.right <= r.left)
+      r.right = r.left + 1;
+    if (r.top > r.bottom)
+      r.top = r.bottom;
+    xvt_dwin_set_clip(win, &r);
+  }
+  else
+    xvt_dwin_set_clip(win, NULL);
+}
+
+
+void
+xi_caret_on(WINDOW win, int x, int y, int height)
+{
+  XI_ITF_DATA *itf_data;
+  PNT p;
+
+  itf_data = xi_get_itf(win)->v.itf;
+  if (itf_data->caret_is_on)
+  {
+    xvt_win_set_caret_visible(win, FALSE );
+  }
+  xvt_win_set_caret_size(win, (int)xi_get_pref(XI_PREF_CARET_WIDTH), height);
+  itf_data->caret_x = x;
+  itf_data->caret_y = y;
+  itf_data->caret_height = height;
+  itf_data->caret_is_on = TRUE;
+
+  p.h = x;
+  p.v = y;
+  vpnt_to_ppnt(win, &p);
+  x = p.h;
+  y = p.v;
+  xvt_win_set_caret_pos(win, p);
+  xvt_win_set_caret_visible(win, TRUE);
+}
+
+void
+xi_caret_off(WINDOW win)
+{
+  XI_ITF_DATA *itf_data;
+
+  itf_data = xi_get_itf(win)->v.itf;
+  if (itf_data->caret_is_on)
+  {
+  itf_data->caret_is_on = FALSE;
+#if XVTWS == WINWS
+  { PNT _p; _p.h =  -100; _p.v =  -100;
+    xvt_win_set_caret_pos(win, _p);
+    xvt_win_set_caret_visible(win, TRUE); };
+#endif
+  xvt_win_set_caret_visible(win, FALSE );
+  }
+}
+
+static void
+xi_caret_suspend(WINDOW win)
+{
+  XI_ITF_DATA *itf_data;
+
+  itf_data = xi_get_itf(win)->v.itf;
+  if (itf_data->caret_is_on)
+  {
+    xvt_win_set_caret_visible(win, FALSE );
+  }
+}
+
+static void
+xi_caret_restore(WINDOW win)
+{
+  XI_ITF_DATA *itf_data;
+  PNT p;
+
+  itf_data = xi_get_itf(win)->v.itf;
+  if (itf_data->caret_is_on)
+  {
+    int leading, ascent, descent, x, y;
+
+    p.h = itf_data->caret_x;
+    p.v = itf_data->caret_y;
+    /* This patches a bug in the caret position in XVT/WIN */
+#if XIWS == WINWS
+    xvt_dwin_get_font_metrics( win, &leading, &ascent, &descent );
+    p.v -= itf_data->caret_height - (leading + ascent + descent );
+#endif
+    vpnt_to_ppnt(win, &p);
+    x = p.h;
+    y = p.v;
+#if XIWS == GRWS
+    ++x;
+#endif
+  { PNT _p; _p.h =  x; _p.v =  y;
+    xvt_win_set_caret_pos(win, _p);  
+    xvt_win_set_caret_visible(win, TRUE); };
+  xvt_win_set_caret_size(win, (int)xi_get_pref(XI_PREF_CARET_WIDTH), itf_data->caret_height);
+  }
+}
+
+#if XI_IS_CH
+void
+xi_coalesce_invalidates(XI_OBJ *itf, BOOLEAN coalesce)
+{
+  XI_ITF_DATA *itf_data;
+
+  CTOS_IS_CH;
+  itf_data = itf->v.itf;
+  if (coalesce)
+  {
+    if (! itf_data->coalescing)
+    {
+      itf_data->inv_rct.top = SHRT_MAX;
+      itf_data->inv_rct.left = SHRT_MAX;
+      itf_data->inv_rct.bottom = 0;
+      itf_data->inv_rct.right = 0;
+      itf_data->invalidated = FALSE;
+    }
+    ++itf_data->coalescing;
+  }
+  else
+  {
+    --itf_data->coalescing;
+    if (! itf_data->coalescing && itf_data->invalidated)
+      xvt_dwin_invalidate_rect(itf_data->xvt_win, &itf_data->inv_rct);
+  }
+  CTOS_END;
+}
+#endif
+
+void
+xi_invalidate_rect(WINDOW win, RCT *rct)
+{
+  RCT r, cr, dr;
+#if XI_IS_CH
+  XI_OBJ *itf;
+  XI_ITF_DATA *itf_data;
+#endif
+
+  if (rct != NULL && (rct->top >= rct->bottom || rct->left >= rct->right))
+    return;
+
+#if XI_IS_CH
+  CTOS_IS_CH;
+  itf = xi_get_itf(win);
+  if (itf)
+  {
+    itf_data = itf->v.itf;
+    if (itf_data->coalescing)
+    {
+      itf_data->invalidated = TRUE;
+      xi_get_enclosing_rect(&itf_data->inv_rct, &itf_data->inv_rct, rct);
+      return;
+    }
+  }
+  CTOS_END;
+#endif
+  if (! rct)
+  {
+    xvt_dwin_invalidate_rect(win, NULL);
+    return;
+  }
+  r = *rct;
+  vrct_to_prct(win, &r);
+
+  xvt_vobj_get_client_rect(win, &cr);
+  if (xi_rect_intersect(&dr, &r, &cr))
+  {
+    update_pending = TRUE;
+    xvt_dwin_invalidate_rect(win, &r);
+  }
+}
+
+BOOLEAN xi_needs_update(WINDOW win, RCT *rct)
+{
+  RCT r;
+
+  r = *rct;
+  vrct_to_prct(win, &r);
+  return xvt_dwin_is_update_needed(win, &r);
+}
+
+void
+xi_draw_icon(WINDOW win, int x, int y, int rid, COLOR fore_color,
+COLOR back_color)
+{
+#if XIWS == PMWS
+  DRAW_CTOOLS save_ctools;
+#endif
+
+#if XVTWS == WMWS
+  NOREF(x);
+  NOREF(y);
+  NOREF(rid);
+#endif
+  NOREF(fore_color);
+  NOREF(back_color);
+  xi_set_cur_window(win);
+#if XI_IS_CH
+  return;
+#else
+
+  x -= cur_delta_x;
+  y -= cur_delta_y;
+#if (XIWS == MTFWS) || (XIWS == MACWS)
+  if (fore_color)
+  xvt_dwin_set_fore_color(win, fore_color);
+  if (back_color)
+  xvt_dwin_set_back_color(win, back_color);
+#endif
+#if XIWS == PMWS
+  {
+  DRAW_CTOOLS new_ctools;
+
+  new_ctools.pen.width = 1;
+  new_ctools.pen.color = COLOR_BLACK;
+  new_ctools.pen.pat = PAT_SOLID;
+  new_ctools.pen.style = P_SOLID;
+
+  new_ctools.brush.pat = PAT_SOLID;
+  new_ctools.brush.color = COLOR_BLACK;
+
+  new_ctools.mode = M_COPY;
+
+  new_ctools.opaque_text = TRUE;
+  new_ctools.fore_color = fore_color;
+  new_ctools.back_color = back_color;
+
+  xvt_dwin_get_draw_ctools(win, &save_ctools);
+  xvt_dwin_set_draw_ctools(win, &new_ctools);
+  {
+    RCT r;
+    r.top = y;
+    r.left = x;
+    r.bottom = y + 1;
+    r.right = x + 1;
+    xvt_dwin_draw_rect(win, &r);
+  }
+  }
+#endif
+  if (rid)
+  xvt_dwin_draw_icon(win, x, y, rid);
+#if XIWS == PMWS
+  xvt_dwin_set_draw_ctools(win, &save_ctools);
+#endif
+#endif
+}
+
+#if XIWS == WMWS
+static void
+adjust_point(short *p)
+{
+  *p = ((*p + 4) / 8) * 8;
+}
+#endif
+
+void
+xi_draw_rect(WINDOW win, RCT *rctp)
+{
+  if (rctp->top >= rctp->bottom || rctp->left >= rctp->right)
+    return;
+  {
+#if XVT_OS == XVT_OS_CTOS
+    {
+      RCT r;
+
+      xi_set_cur_window(win);
+      CTOS_IS_CH;
+      r = *rctp;
+      VRCT_TO_PRCT(&r);
+      draw_rect(&r);
+      CTOS_END;
+    }
+    {
+      RCT rct;
+      DRAW_CTOOLS ct;
+      RCT r;
+
+      xi_set_cur_window(win);
+      CTOS_IS_PM;
+      r = *rctp;
+      VRCT_TO_PRCT(&r);
+      xi_get_draw_ctools(win, &ct);
+      rct = r;
+      if (ct.mode == M_XOR || ct.brush.pat == PAT_SOLID)
+    xvt_dwin_draw_rect(win, &rct);
+else
+{
+  rct.top++;
+  rct.right--;
+  xvt_dwin_draw_rect(win, &rct);
+}
+CTOS_END;
+  }
+#else /* XVT_OS_CTOS */
+
+#if XIWS == WMWS
+  DRAW_CTOOLS ct;
+  RCT r;
+
+  r = *rctp;
+  adjust_point(&r.top);
+  adjust_point(&r.left);
+  adjust_point(&r.bottom);
+  adjust_point(&r.right);
+  xi_set_cur_window(win);
+  VRCT_TO_PRCT(&r);
+  xi_get_draw_ctools(win, &ct);
+  if (ct.mode == M_XOR && ! xvt_rect_is_empty(&r))
+    ct.brush.color = COLOR_BLACK;
+  if (ct.brush.pat == PAT_HOLLOW)
+    ct.brush.color = ct.back_color;
+  xvt_dwin_set_draw_ctools(win, &ct);
+  xvt_dwin_draw_rect(win, &r);
+
+#else /* WMWS */
+
+    /************************************* XM *****************************/
+#if (XIWS == MTFWS) || (XIWS == PMWS) || (XIWS == XOLWS)
+    RCT rct;
+    DRAW_CTOOLS ct;
+#endif /* (XIWS == MTFWS) || (XIWS == PMWS) || (XIWS == XOLWS) */
+    RCT r;
+
+    r = *rctp;
+    xi_set_cur_window(win);
+    VRCT_TO_PRCT(&r);
+#if (XIWS == MTFWS) || (XIWS == XOLWS)
+    xi_get_draw_ctools(win, &ct);
+    rct = r;
+    if (ct.mode == M_XOR || ct.brush.pat == PAT_SOLID)
+  xvt_dwin_draw_rect(win, &rct);
+else
+{
+  xvt_dwin_draw_rect(win, &rct);
+}
+#endif /* MTFWS || XOLWS */
+
+/************************************* PM *****************************/
+#if XIWS == PMWS
+xi_get_draw_ctools(win, &ct);
+rct = r;
+if (ct.mode == M_XOR || ct.brush.pat == PAT_SOLID)
+xvt_dwin_draw_rect(win, &rct);
+else
+{
+  xvt_dwin_draw_rect(win, &rct);
+}
+#endif /* PMWS */
+
+#if (XIWS != MTFWS) && (XIWS != PMWS) && (XIWS != XOLWS)
+  xvt_dwin_draw_rect(win, &r);
+#endif /* MTFWS || PMWS || XOLWS */
+
+#endif /* WMWS */
+
+#endif /* XVT_OS_CTOS */
+  }
+}
+
+static PNT move_to_pnt;
+
+void
+xi_move_to(WINDOW win, PNT pnt)
+{
+  NOREF(win);
+  VPNT_TO_PPNT(&pnt);
+  move_to_pnt = pnt;
+}
+
+void
+xi_draw_line(WINDOW win, PNT pnt)
+{
+  PNT mpnt, mtp;
+
+  xi_set_cur_window(win);
+  VPNT_TO_PPNT(&pnt);
+  mpnt = pnt;
+  mtp = move_to_pnt;
+  if (mtp.v != mpnt.v && mtp.h != mpnt.h)
+  {
+  if (mtp.h > mpnt.h)
+  {
+    PNT tpnt;
+
+    tpnt = mtp;
+    mtp = mpnt;
+    mpnt = tpnt;
+  }
+#if XI_IS_PM
+  CTOS_IS_PM;
+  if (mtp.v > mpnt.v)
+  {
+    mtp.v--;
+    mpnt.h--;
+  }
+  else
+  {
+    mpnt.v--;
+    mpnt.h--;
+  }
+  CTOS_END;
+#endif
+#if XIWS == MACWS
+  if (mtp.v > mpnt.v)
+  {
+    mpnt.h--;
+    mpnt.v++;
+  }
+  else
+  {
+    mtp.v++;
+    mpnt.h--;
+  }
+  mtp.v--;
+  mpnt.v--;
+#endif
+#if XIWS == WINWS
+  if (mtp.v > mpnt.v)
+    {
+      mpnt.v--;
+      mtp.v--;
+    }
+#endif
+#if XIWS == GRWS
+    if (mtp.v > mpnt.v)
+    {
+      mtp.v--;
+      mpnt.h--;
+    }
+  else
+    {
+      mpnt.v--;
+      mpnt.h--;
+    }
+#endif
+#if (XIWS == MTFWS) || (XIWS == XOLWS)
+    if (mtp.v > mpnt.v)
+    {
+      mpnt.h--;
+      mtp.v--;
+    }
+  else
+    {
+      mpnt.h--;
+      mpnt.v--;
+    }
+#endif
+  xvt_dwin_draw_set_pos(win, mtp);
+  xvt_dwin_draw_line(win, mpnt);
+  }
+  else
+  {
+#if (XVT_OS == XVT_OS_CTOS)
+    CTOS_IS_PM;
+    move_to_pnt.v++;
+    mpnt.v++;
+    if (move_to_pnt.v == mpnt.v)
+      --mpnt.h;
+    if (move_to_pnt.h == mpnt.h)
+    --mpnt.v;
+    CTOS_END;
+#else
+#if (XIWS == MACWS) || (XIWS == MTFWS) || (XIWS == PMWS) || (XIWS == GRWS) || (XIWS == XOLWS)
+  if (move_to_pnt.v == mpnt.v)
+    --mpnt.h;
+  if (move_to_pnt.h == mpnt.h)
+      --mpnt.v;
+#endif
+#endif
+  xvt_dwin_draw_set_pos(win, move_to_pnt);
+    xvt_dwin_draw_line(win, mpnt);
+  }
+}
+
+BOOLEAN
+xi_rect_intersect(RCT *rctp, RCT *rctp1, RCT *rctp2)
+{
+  RCT r, r2, *rpnt;
+
+  if (rctp == NULL)
+    rpnt = &r;
+  else
+    rpnt = rctp;
+  rpnt->left = max(rctp1->left, rctp2->left);
+  rpnt->top = max(rctp1->top, rctp2->top);
+  rpnt->right = min(rctp1->right, rctp2->right);
+  rpnt->bottom = min(rctp1->bottom, rctp2->bottom);
+  r2 = *rpnt;
+  return !xvt_rect_is_empty(&r2);
+}
+
+
+void
+xi_trap_mouse(WINDOW win)
+{
+  xvt_win_trap_pointer(win);
+}
+
+
+void
+xi_release_mouse(void)
+{
+  xvt_win_release_pointer();
+}
+
+
+/* Functions moved from XI.C because MPW cannot have too much code in one module. */
+
+void
+xi_menu_enable(XI_OBJ *itf, int tag, BOOLEAN enable)
+{
+  XI_OBJ *xi_obj;
+
+  WINDOW win;
+
+  win = xi_get_window(itf);
+  xvt_menu_set_item_enabled(win, (short)tag, enable);
+  xi_obj = xi_get_obj(itf, tag);
+  if (xi_obj != NULL && xi_obj->type == XIT_BTN)
+    if (enable)
+      xi_set_attrib(xi_obj, xi_get_attrib(xi_obj) | XI_ATR_ENABLED);
+    else
+      xi_set_attrib(xi_obj, xi_get_attrib(xi_obj) & ~XI_ATR_ENABLED);
+}
+
+void
+xi_set_icon(XI_OBJ *xi_obj, int icon_rid, int down_icon_rid)
+{
+  NOREF(down_icon_rid);
+  switch (xi_obj->type)
+  {
+  case XIT_CELL:
+    if (!xi_obj->v.cell.is_vert_scrolled)
+      lm_set_icon(xi_obj->parent->v.list->lm, icon_rid,
+      xi_obj->v.cell.row, xi_obj->v.cell.column);
+    break;
+  case XIT_BTN:
+    {
+      XI_BTN_DATA *bd;
+
+      bd = xi_obj->v.btn;
+      bd->up_icon_rid = icon_rid;
+      bd->down_icon_rid = down_icon_rid;
+      xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &bd->rct);
+      break;
+    }
+  default:
+  xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20088",
+    20088, "xi_set_icon: Invalid object");   
+    break;
+  }
+}
+
+XI_RCT *
+xi_get_xi_rct(XI_OBJ *xi_obj, XI_RCT *xi_rct)
+{
+  int fu_width, fu_height;
+
+  fu_width = xi_get_fu_width(xi_obj);
+  fu_height = xi_get_fu_height(xi_obj);
+  switch (xi_obj->type)
+  {
+  case XIT_ITF:
+    {
+      RCT r;
+
+      xvt_vobj_get_client_rect(xi_get_window(xi_obj), &r);
+      xi_rct->top = 0;
+      xi_rct->left = 0;
+      xi_rct->bottom = (r.bottom / fu_height) * XI_FU_MULTIPLE;
+      xi_rct->right = (r.right / fu_width) * XI_FU_MULTIPLE;
+      return xi_rct;
+    }
+  default:
+    return NULL;
+  }
+}
+
+static void
+recalc_metrics(XI_OBJ *xi_obj)
+{
+  int i;
+
+  switch (xi_obj->type)
+  {
+  case XIT_ITF:
+    {
+      XI_ITF_DATA *itf_data;
+
+      itf_data = xi_obj->v.itf;
+
+      /* recalculate fu_width and fu_height */
+      itf_data->fu_height = xi_get_fu_height_font(itf_data->font);
+      itf_data->fu_width = xi_get_fu_width_font(itf_data->font);
+
+      break;
+    }
+  case XIT_TEXT:
+    {
+      XI_TEXT_DATA *text_data;
+
+      text_data = xi_obj->v.text;
+
+      text_data->rct = text_data->xi_rct;
+      xi_fu_to_pu(xi_obj->itf, (PNT *)&text_data->rct, 2);
+      break;
+    }
+  case XIT_RECT:
+    {
+      XI_RECT_DATA *rect_data;
+
+      rect_data = xi_obj->v.rect;
+
+      rect_data->rct = rect_data->xi_rct;
+      xi_fu_to_pu(xi_obj->itf, (PNT *)&rect_data->rct, 2);
+      break;
+    }
+  case XIT_LINE:
+    {
+      XI_LINE_DATA *line_data;
+
+      line_data = xi_obj->v.line;
+
+      line_data->pnt1 = line_data->xi_pnt1;
+      line_data->pnt2 = line_data->xi_pnt2;
+
+      xi_fu_to_pu(xi_obj->itf, &line_data->pnt1, 1);
+      xi_fu_to_pu(xi_obj->itf, &line_data->pnt2, 1);
+
+      break;
+    }
+  case XIT_LIST:
+    lm_recalc_metrics(xi_obj->v.list->lm);
+
+    /* TODO recalc sbb_rct, sb_rct, hsb_rct */
+
+    break;
+  case XIT_COLUMN:
+    break;
+  case XIT_FIELD:
+    {
+      XI_FIELD_DATA *field_data;
+      int btn_dim_x, btn_dim_x2, fu_width, fu_height, edit_height, btn_space;
+      WINDOW itf_win;
+      STX_DATA *stxp;
+      int leading, ascent, descent, font_height;
+
+      field_data = xi_obj->v.field;
+      stxp = (STX_DATA *)field_data->stx;
+      if (! field_data->font_set)
+  stxp->font = *xi_obj->itf->v.itf->font;
+      itf_win = xi_get_window(xi_obj->itf);
+      fu_width = xi_get_fu_width(xi_obj->itf);
+      fu_height = xi_get_fu_height(xi_obj->itf);
+      xi_set_xvt_font(itf_win, &stxp->font, FALSE);
+      xi_get_font_metrics(itf_win, &leading, &ascent, &descent);
+      font_height = ascent + leading + descent;
+      edit_height = font_height + (2 * EDIT_BORDER_WIDTH_Y) +
+    (2 * EDIT_BORDER_SPACE_Y);
+      if (field_data->xi_rct.top || field_data->xi_rct.left ||
+    field_data->xi_rct.bottom || field_data->xi_rct.right)
+      {
+  stxp->rct = field_data->xi_rct;
+  if ((stxp->rct.bottom - stxp->rct.top) <=
+      XI_FU_MULTIPLE)
+  {
+    xi_fu_to_pu(xi_obj->itf, (PNT *)&stxp->rct, 2);
+    stxp->rct.bottom = stxp->rct.top + edit_height;
+  }
+  else
+  {
+    xi_fu_to_pu(xi_obj->itf, (PNT *)&stxp->rct, 2);
+    stxp->rct.bottom -= BORDER_SPACE_Y;
+    /* TODO move text edit object */
+  }
+      }
+      else
+      {
+  PNT p;
+  RCT rct;
+  short rct_r, rct_b;
+
+  p = field_data->xi_pnt;
+  xi_fu_to_pu(xi_obj->itf, &p, 1);
+  rct_r = p.h + (field_data->field_width / XI_FU_MULTIPLE)
+    * fu_width + 2 * BORDER_WIDTH_X + 2 * BORDER_SPACE_X;
+  rct_b = p.v + edit_height;
+  xvt_rect_set(&rct, p.h, p.v, rct_r, rct_b);
+  stxp->rct = rct;
+    }
+    btn_dim_x = (XI_FU_MULTIPLE * fu_height) / fu_width;
+      /* btn_dim_x is actual width of button */
+#if XI_IS_NOT_CH
+      CTOS_IS_PM;
+      /* make buttons 70% wide as high */
+      btn_dim_x = (int)((long)btn_dim_x * 83L / 100L);
+      CTOS_END;
+#endif
+      btn_space = btn_dim_x / 6;
+      /* btn_dim_x2 is the button width + space, rounded up to the next even form unit */
+      btn_dim_x2 = btn_dim_x + btn_space;
+      btn_dim_x2 = ((btn_dim_x2 + XI_FU_MULTIPLE) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+      if (! (field_data->xi_rct.top || field_data->xi_rct.bottom ||
+    field_data->xi_rct.left || field_data->xi_rct.right))
+      {
+  if (field_data->button)
+  {
+    int leading, ascent, descent, font_height;
+
+    xi_set_xvt_font(itf_win, &stxp->font, FALSE);
+    xi_get_font_metrics(itf_win, &leading, &ascent, &descent);
+    font_height = ascent + leading + descent;
+    edit_height = font_height + (2 * EDIT_BORDER_WIDTH_Y) +
+        (2 * EDIT_BORDER_SPACE_Y);
+    field_data->btn_rct.top = field_data->xi_pnt.v;
+    if (field_data->button_on_left)
+    {
+      field_data->btn_rct.left = field_data->xi_pnt.h;
+      field_data->btn_rct.right =
+    field_data->btn_rct.left + btn_dim_x;
+    }
+    else
+    {
+#if XI_IS_CH
+      BOOLEAN b;
+      STX_DATA *stxp;
+
+      CTOS_IS_CH;
+      stxp = (STX_DATA *)field_data->stx;
+      b = (BOOLEAN)(stxp->attrib & XI_ATR_BORDER);
+      field_data->btn_rct.left = stxp->rct.left +
+    field_data->field_width + (b ? 24 : 8);
+      field_data->btn_rct.right =
+    field_data->btn_rct.left + 8;
+      CTOS_END;
+#endif
+#if XI_IS_NOT_CH
+      /* TODO problem with this code */
+      /* TODO Need a boolean - place button next to field */
+      /* TODO Need to handle correctly if use a button on a field with xi_rct
+specified */
+      CTOS_IS_PM;
+      field_data->btn_rct.right = field_data->xi_pnt.h +
+    field_data->field_width + btn_dim_x2;
+      field_data->btn_rct.right = ((field_data->btn_rct.right + XI_FU_MULTIPLE)
+    / XI_FU_MULTIPLE) * XI_FU_MULTIPLE;
+      field_data->btn_rct.left = field_data->btn_rct.right
+    - btn_dim_x;
+      CTOS_END;
+#endif
+    }
+  }
+      }
+      else
+      {
+  if (field_data->button)
+  {
+    field_data->btn_rct = field_data->xi_rct;
+    if (field_data->button_on_left)
+    {
+      field_data->btn_rct.right =
+    field_data->btn_rct.left + btn_dim_x2;
+    }
+    else
+    {
+      field_data->btn_rct.left =
+    field_data->btn_rct.right;
+      field_data->btn_rct.right += btn_dim_x2;
+    }
+  }
+      }
+      xi_fu_to_pu(xi_obj->itf, (PNT *)&field_data->btn_rct, 2);
+      field_data->btn_rct.bottom = field_data->btn_rct.top +
+    edit_height;
+      if (field_data->xi_pnt.h || field_data->xi_pnt.v)
+      {
+  field_data->rct.top = field_data->xi_pnt.v;
+  field_data->rct.left = field_data->xi_pnt.h;
+  field_data->rct.right = field_data->rct.left +
+      field_data->field_width;
+  field_data->rct.bottom = field_data->rct.top +
+      XI_FU_MULTIPLE;
+      }
+      else
+  field_data->rct = field_data->xi_rct;
+      xi_fu_to_pu(xi_obj->itf, (PNT *)&field_data->rct, 2);
+      break;
+    }
+  case XIT_BTN:
+    {
+      XI_BTN_DATA *btn_data;
+
+      if (xi_obj->parent->type != XIT_CONTAINER)
+      {
+  btn_data = xi_obj->v.btn;
+  btn_data->rct = btn_data->xi_rct;
+  xi_fu_to_pu(xi_obj->itf, (PNT *)&btn_data->rct, 2);
+      }
+      break;
+    }
+  case XIT_CONTAINER:
+    {
+      XI_CONTAINER_DATA *container_data;
+      PNT p;
+      int i, max_len, len;
+      XI_OBJ *child;
+      XI_BTN_TYPE btn_type;
+
+      container_data = xi_obj->v.container;
+      container_data->rct = container_data->xi_rct;
+
+      xi_fu_to_pu(xi_obj->itf, (PNT *)&container_data->rct, 2);
+      p.v = container_data->btn_height;
+      p.h = container_data->btn_width;
+      xi_fu_to_pu(xi_obj->itf, &p, 1);
+      container_data->pix_height = p.v;
+      container_data->pix_width = p.h;
+
+      max_len = 0;
+      for (i = 0; i < xi_obj->nbr_children; ++i)
+      {
+  child = xi_obj->children[i];
+  if ((len = (int)strlen(child->v.btn->text)) > max_len)
+    max_len = len;
+      }
+      btn_type = xi_obj->children[0]->v.btn->type;
+      xi_container_rect_calc(xi_obj, max_len, btn_type);
+      for (i = 0; i < xi_obj->nbr_children; ++i)
+  xi_button_rect_calc(xi_obj->children[i], i);
+
+      break;
+    }
+  }
+  for (i = 0; i < xi_obj->nbr_children; ++i)
+  recalc_metrics(xi_obj->children[i]);
+}
+
+void
+xi_set_obj_font_id(XI_OBJ *xi_obj, XVT_FNTID font_id)
+{
+  XVT_FNTID font2;
+
+  font2 = xi_create_copy_font_id(xi_obj->itf, font_id, 0);
+  switch (xi_obj->type)
+  {
+  case XIT_COLUMN:
+  {
+    XI_OBJ *list;
+
+    list = xi_obj->parent;
+    lm_set_font(list->v.list->lm, LM_COLUMN, xi_obj_to_idx(xi_obj),
+    0, &font2);
+    break;
+  }
+  case XIT_CELL:
+  if (!xi_obj->v.cell.is_vert_scrolled)
+  {
+    XI_OBJ *list;
+    RCT rct;
+
+    list = xi_obj->parent;
+    lm_set_font( list->v.list->lm, LM_CELL, xi_obj->v.cell.row,
+      xi_obj->v.cell.column, &font2 );
+    xi_get_rect(xi_obj, &rct);
+    xi_invalidate_rect(xi_get_window(xi_obj->itf), &rct);
+  }
+  break;
+  }
+}
+
+XI_CELL_SPEC *
+xi_get_cell_selection(XI_OBJ *list, int *nbr_cellsp)
+{
+  int r, c, nbr_rows, nbr_columns, nbr_cells, cnt;
+  XI_OBJ cell_obj, row_obj;
+  XI_LIST_DATA *list_data;
+  XI_OBJ * *members;
+  int nbr_members;
+
+  members = xi_get_member_list(list, &nbr_members);
+  xi_get_list_info(list, &nbr_rows);
+  nbr_columns = list->nbr_children;
+  nbr_cells = 0;
+  for (r = 0; r < nbr_rows; ++r)
+    for (c = 0; c < nbr_columns; ++c)
+    {
+      XI_MAKE_CELL(&cell_obj, list, (unsigned char)r, (unsigned char)c);
+      XI_MAKE_ROW(&row_obj, list, (unsigned char)r);
+      if ((xi_get_attrib(&cell_obj) & XI_ATR_SELECTED) ||
+    (xi_get_attrib(members[c]) & XI_ATR_SELECTED) ||
+    (xi_get_attrib(&row_obj) & XI_ATR_SELECTED))
+  ++nbr_cells;
+    }
+  *nbr_cellsp = nbr_cells;
+  list_data = list->v.list;
+  if (list_data->cell_spec)
+    list_data->cell_spec = (XI_CELL_SPEC *)xi_tree_realloc(list_data->cell_spec,
+  (size_t)nbr_cells * sizeof(XI_CELL_SPEC));
+  else
+    list_data->cell_spec = (XI_CELL_SPEC *)xi_tree_malloc(
+  (size_t)nbr_cells * sizeof(XI_CELL_SPEC), list_data);
+  cnt = 0;
+  for (r = 0; r < nbr_rows; ++r)
+    for (c = 0; c < nbr_columns; ++c)
+    {
+      XI_MAKE_CELL(&cell_obj, list, (unsigned char)r, (unsigned char)c);
+      XI_MAKE_ROW(&row_obj, list, (unsigned char)r);
+      if ((xi_get_attrib(&cell_obj) & XI_ATR_SELECTED) ||
+    (xi_get_attrib(members[c]) & XI_ATR_SELECTED) ||
+    (xi_get_attrib(&row_obj) & XI_ATR_SELECTED))
+      {
+  list_data->cell_spec[cnt].row = r;
+  list_data->cell_spec[cnt].column = c;
+  ++cnt;
+      }
+    }
+  return list_data->cell_spec;
+}
+
+BOOLEAN
+xi_is_checked(XI_OBJ *xi_obj)
+{
+  BOOLEAN retval = FALSE;
+
+  if (xi_obj->type == XIT_BTN)
+  retval = xi_obj->v.btn->checked;
+  return retval;
+}
+
+void
+xi_check(XI_OBJ *xi_obj, BOOLEAN check)
+{
+  WINDOW win;
+  static BOOLEAN inside = FALSE;
+  XI_BTN_DATA *btn;
+
+  if (check != 0 && check != 1)
+    check = 1;
+  if (! xi_get_pref(XI_PREF_NATIVE_CTRLS))
+    if (xi_is_checked(xi_obj) == check)
+      return;
+  win = xi_obj->itf->v.itf->xvt_win;
+  btn = xi_obj->v.btn;
+  xi_obj->v.btn->checked = check;
+  if (! (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS))
+  {
+    switch (btn->type)
+    {
+    case XIBT_BUTTON:
+      xi_invalidate_rect(win, &btn->rct);
+      break;
+    case XIBT_BUTTON_CHECKBOX:
+    case XIBT_BUTTON_RADIOBTN:
+    case XIBT_RADIOBTN:
+    case XIBT_CHECKBOX:
+    case XIBT_TABBTN:
+      {
+  BOOLEAN enabled, visible, focus;
+  unsigned long attrib;
+
+  attrib = xi_get_attrib(xi_obj);
+  enabled = ((attrib & XI_ATR_ENABLED) != 0);
+  visible = ((attrib & XI_ATR_VISIBLE) != 0);
+  focus = (xi_get_focus(xi_obj->itf) == xi_obj);
+  if (btn->drawable)
+    xi_invalidate_rect(win, &btn->rct);
+  else
+    xi_draw_button(xi_obj, &btn->rct, btn->text,
+        btn->down_icon_rid, btn->up_icon_rid,
+        btn->disabled_icon_rid, enabled,
+        visible, focus, btn->down, btn->dflt, btn->checked,
+        TRUE);
+  break;
+      }
+    }
+  }
+  else
+  {
+    switch (btn->type)
+    {
+    case XIBT_CHECKBOX:
+      xvt_ctl_set_checked(btn->btnctl, check);
+      break;
+    case XIBT_RADIOBTN:
+    case XIBT_TABBTN:
+      {
+  WINDOW wins[MAX_RADIO_BUTTONS];
+  XI_BTN_TYPE type;
+  XI_OBJ *parent;
+
+  type = xi_obj->v.btn->type;
+  parent = xi_obj->parent;
+  if (parent->type == XIT_CONTAINER &&
+      (type == XIBT_RADIOBTN || type == XIBT_TABBTN))
+  {
+    int i;
+
+    xvt_errmsg_sig_if(!(parent->nbr_children <= MAX_RADIO_BUTTONS),
+    NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20089",
+    20089, "Too many radio buttons in a container");   
+    for (i = 0; i < parent->nbr_children; ++i)
+      wins[i] = parent->children[i]->v.btn->btnctl;
+    xvt_ctl_check_radio_button(btn->btnctl, wins,
+        parent->nbr_children);
+    return;
+  }
+  if (type == XIBT_RADIOBTN || type == XIBT_TABBTN)
+  {
+    xvt_ctl_set_checked(btn->btnctl, check);
+    return;
+  }
+  break;
+      }
+    }
+  }
+  if (! inside && xi_obj->parent->type == XIT_CONTAINER &&
+      (xi_obj->v.btn->type == XIBT_RADIOBTN ||
+      xi_obj->v.btn->type == XIBT_TABBTN ||
+      xi_obj->v.btn->type == XIBT_BUTTON_RADIOBTN))
+  {
+    XI_OBJ * *child;
+    XI_OBJ *parent;
+    int i;
+
+    inside = TRUE;
+    parent = xi_obj->parent;
+    child = parent->children;
+    for (i = 0, child = parent->children; i < parent->nbr_children;
+  ++i, ++child)
+      if (*child != xi_obj)
+  if (xi_is_checked(*child))
+    xi_check(*child, FALSE);
+    inside = FALSE;
+  }
+}
+
+int
+xi_obj_to_idx(XI_OBJ *xi_obj)
+{
+  int column_idx;
+  XI_OBJ * *objp;
+  int n;
+
+  n = xi_obj->parent->nbr_children;
+  objp = xi_obj->parent->children;
+  for (column_idx = 0; column_idx < n; objp++, ++column_idx)
+  {
+    if ((*objp) == xi_obj)
+      break;
+  }
+  return column_idx;
+}
+
+
+void
+xi_set_update_obj(XI_OBJ *xi_obj)
+{
+  XI_OBJ *itf;
+
+  itf = xi_obj->itf;
+  itf->v.itf->update_obj = xi_obj;
+}
+
+
+int
+xi_get_visible_rows(XI_OBJ *xi_obj, int *first_vis, int *last_vis)
+{
+  return lm_get_visible_rows(xi_obj->v.list->lm, first_vis, last_vis);
+}
+
+
+void
+xi_set_row_height(XI_OBJ *xi_obj, int height)
+{
+  XI_OBJ *list;
+
+  list = xi_obj->parent;
+  lm_set_row_height(list->v.list->lm, xi_obj->v.row, height, TRUE, 0, FALSE);
+}
+
+
+#if 0
+long
+xi_long_time(void)
+{
+#if XVT_OS == XVT_OS_DOS
+  struct time t;
+  long l;
+
+  gettime(&t);
+  l = t.ti_hund +
+      t.ti_sec * 100 +
+      t.ti_min * 6000 +
+      t.ti_hour * 360000L;
+  return l;
+#endif
+}
+#endif
+
+
+void
+xi_set_color(XI_OBJ *xi_obj, XI_COLOR_PART part, COLOR color)
+{
+  RCT     rct;
+  BOOLEAN changed;
+
+  changed = FALSE;
+  switch (xi_obj->type)
+  {
+  case XIT_FIELD:
+  {
+    STX_DATA *stxp;
+
+    stxp = (STX_DATA *)xi_obj->v.field->stx;
+    switch (part)
+    {
+    case XIC_ENABLED:
+      changed = (stxp->enabled_color != color);
+      stxp->enabled_color = color;
+      break;
+    case XIC_BACK:
+      changed = (stxp->back_color != color);
+      stxp->back_color = color;
+      break;
+    case XIC_HILIGHT:
+      changed = (stxp->hilight_color != color);
+      stxp->hilight_color = color;
+      break;
+    case XIC_ACTIVE:
+      changed = (stxp->active_color != color);
+      stxp->active_color = color;
+      break;
+    case XIC_ACTIVE_BACK:
+      changed = (stxp->active_back_color != color);
+      stxp->active_back_color = color;
+      break;
+    case XIC_SHADOW:
+      changed = (stxp->shadow_color != color);
+      stxp->shadow_color = color;
+      break;
+    case XIC_DISABLED:
+      changed = (stxp->disabled_color != color);
+      stxp->disabled_color = color;
+      break;
+    case XIC_DISABLED_BACK:
+      changed = (stxp->disabled_back_color != color);
+      stxp->disabled_back_color = color;
+      break;
+    }
+    break;
+  }
+  case XIT_CELL:
+  if (!xi_obj->v.cell.is_vert_scrolled)
+  {
+    LM_CELL_DATA *lmcdp;
+    XI_OBJ *list_obj;
+    LM_DATA *lmp;
+    int row = xi_obj->v.cell.row;
+    int col = xi_obj->v.cell.column;
+
+    list_obj = xi_obj->parent;
+    lmp = (LM_DATA *)list_obj->v.list->lm;
+    lmcdp = &lmp->cell_data[row][col];
+    switch (part)
+    {
+    case XIC_ENABLED:
+      changed = (lmcdp->color != color);
+      lmcdp->color = color;
+      break;
+    case XIC_BACK:
+      changed = (lmcdp->back_color != color);
+      lmcdp->back_color = color;
+      break;
+    }
+  }
+  break;
+  case XIT_ROW:
+  if (part == XIC_ENABLED)
+    lm_set_color(xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row,
+            0, FALSE, color, FALSE);
+  changed = TRUE;
+  break;
+  case XIT_BTN:
+  {
+  XI_BTN_DATA *xi_bd;
+  xi_bd = (XI_BTN_DATA*)xi_obj->v.btn;
+    switch (part)
+    {
+    case XIC_FORE:
+    case XIC_ENABLED:
+      changed = (xi_bd->fore_color != color);
+      xi_bd->fore_color = color;
+    }
+  break;
+  }
+  case XIT_TEXT:
+  {
+  XI_TEXT_DATA *xi_td;
+  xi_td = (XI_TEXT_DATA*)xi_obj->v.text;
+    switch (part)
+    {
+    case XIC_FORE:
+    case XIC_ENABLED:
+      changed = (xi_td->fore_color != color);
+      xi_td->fore_color = color;
+      break;
+    case XIC_BACK:
+      changed = (xi_td->back_color != color);
+      xi_td->back_color = color;
+      break;
+    }
+  break;
+  }
+  case XIT_LINE:
+  {
+  XI_LINE_DATA *xi_ld;
+  xi_ld = (XI_LINE_DATA*)xi_obj->v.line;
+    switch (part)
+    {
+    case XIC_FORE:
+    case XIC_ENABLED:
+      changed = (xi_ld->fore_color != color);
+      xi_ld->fore_color = color;
+      break;
+    case XIC_BACK:
+      changed = (xi_ld->back_color != color);
+      xi_ld->back_color = color;
+      break;
+    }
+  break;
+  }
+  case XIT_RECT:
+  {
+  XI_RECT_DATA *xi_rd;
+  xi_rd = (XI_RECT_DATA*)xi_obj->v.rect;
+    switch (part)
+    {
+    case XIC_FORE:
+    case XIC_ENABLED:
+      changed = (xi_rd->fore_color != color);
+      xi_rd->fore_color = color;
+      break;
+    case XIC_BACK:
+      changed = (xi_rd->back_color != color);
+      xi_rd->back_color = color;
+      break;
+    case XIC_HILIGHT:
+      changed = (xi_rd->hilight_color != color);
+      xi_rd->hilight_color = color;
+      break;
+    case XIC_SHADOW:
+      changed = (xi_rd->shadow_color != color);
+      xi_rd->shadow_color = color;
+      break;
+    }
+  break;
+  }
+  case XIT_ITF:
+  {
+  XI_ITF_DATA *xi_id;
+  xi_id = (XI_ITF_DATA*)xi_obj->v.itf;
+  if (part == XIC_BACK)
+      changed = (xi_id->back_color != color);
+      xi_id->back_color = color;
+  break;
+  }
+  case XIT_LIST:
+    {
+    LM_DATA *lmp;
+
+    lmp = (LM_DATA *)xi_obj->v.list->lm;
+    switch (part)
+    {
+    case XIC_ENABLED:
+      changed = (lmp->enabled_color != color);
+      lmp->enabled_color = color;
+      break;
+    case XIC_BACK:
+      changed = (lmp->back_color != color);
+      lmp->back_color = color;
+      break;
+    case XIC_ACTIVE:
+      changed = (lmp->active_color != color);
+      lmp->active_color = color;
+      break;
+    case XIC_ACTIVE_BACK:
+      changed = (lmp->active_back_color != color);
+      lmp->active_back_color = color;
+      break;
+    case XIC_DISABLED:
+      changed = (lmp->disabled_color != color);
+      lmp->disabled_color = color;
+      break;
+    case XIC_DISABLED_BACK:
+      changed = (lmp->disabled_back_color != color);
+      lmp->disabled_back_color = color;
+      break;
+    case XIC_WHITE_SPACE:
+      changed = (lmp->white_space_color != color);
+      lmp->white_space_color = color;
+      break;
+    }
+    break;
+  }
+  }
+
+  if (changed)
+  {
+  if (xi_obj->type == XIT_ITF)
+  {
+    xi_get_rect(xi_obj, &rct);
+    xi_invalidate_rect(xi_get_window(xi_obj->itf), &rct);
+  }
+  else
+    if ((xi_get_attrib( xi_obj ) & XI_ATR_VISIBLE) != 0 )
+  {
+    xi_get_rect(xi_obj, &rct);
+
+    /* Returned rectangle does not cause an update for a line.
+      Adjust the coordinates so it does.  */
+    if (xi_obj->type == XIT_LINE)
+    {
+    rct.top = rct.top - 1;
+    rct.bottom = rct.bottom + 1;
+    }
+    xi_invalidate_rect(xi_get_window(xi_obj->itf), &rct);
+  }
+  }
+}
+
+void xi_cell_request(XI_OBJ *xi_obj)
+{
+  switch (xi_obj->type)
+  {
+  case XIT_LIST:
+    lm_cell_request(xi_obj->v.list->lm, LM_LIST, 0, 0);
+    break;
+  case XIT_COLUMN:
+  lm_cell_request(xi_obj->parent->v.list->lm, LM_COLUMN, xi_obj_to_idx(xi_obj), 0);
+  break;
+  case XIT_ROW:
+  lm_cell_request(xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row, 0);
+  break;
+  case XIT_CELL:
+  if (!xi_obj->v.cell.is_vert_scrolled)
+    lm_cell_request( xi_obj->parent->v.list->lm, LM_CELL, xi_obj->v.cell.row,
+                xi_obj->v.cell.column );
+  break;
+  }
+}
+
+
+void
+xi_get_visible_columns(XI_OBJ *xi_obj, int *first_vis, int *last_vis)
+{
+  lm_get_visible_columns(xi_obj->v.list->lm, first_vis, last_vis);
+}
+
+
+void
+xi_set_list_size(XI_OBJ *xi_obj, int height, int width)
+{
+  lm_set_list_size(xi_obj->v.list->lm, height, width);
+}
+
+/*---------------------------------------------------------------------
+function:   xi_container_rect_calc
+cnt_obj:    container object
+max_text_len:   longest button text (only used for XI_STACK_HORIZONTAL)
+btn_type    type of buttons in container
+process:    Calculate the container size & button positioning parameters
+---------------------------------------------------------------------*/
+static void calc_horizontal_stack( XI_OBJ* itf, XI_CONTAINER_DATA* container,
+                        XI_BTN_TYPE btn_type, int max_text_len )
+{
+  int     btn_width, max_width, horz_spacing, btn_height;
+  long    horz_form_unit;
+  long    vert_form_unit;
+  BOOLEAN center;
+  XI_RCT  container_rect;
+
+  container_rect = container->rct;
+  btn_width = max_text_len;
+#if XIWS == MACWS
+  btn_width   *= (XI_FU_MULTIPLE + 2);
+#else
+#if XIWS == WINWS
+  if (xi_get_pref(XI_PREF_NATIVE_CTRLS))
+    btn_width   *= (XI_FU_MULTIPLE + 2);
+  else
+    btn_width   *= XI_FU_MULTIPLE;
+#else
+  btn_width   *= XI_FU_MULTIPLE;
+#endif
+#endif
+  horz_form_unit = xi_get_fu_width(itf);
+  vert_form_unit = xi_get_fu_height(itf);
+  btn_width += (int)xi_get_pref(XI_PREF_BUTTON_PAD);
+  if ( btn_type == XIBT_TABBTN )
+    btn_width += (int)xi_get_pref(XI_PREF_BUTTON_PAD) / 2;
+  /* convert to pixels */
+  btn_width = (int)((btn_width * horz_form_unit)/XI_FU_MULTIPLE);
+  if (container->packed)
+    horz_spacing = 0;
+  else if ((horz_spacing = (int)xi_get_pref(XI_PREF_HORZ_PIXEL_SPACING))
+      == 0)
+    horz_spacing = (short)((xi_get_pref(XI_PREF_HORZ_SPACING)
+          * horz_form_unit) / XI_FU_MULTIPLE);
+  /* figure out if maximum width is too wide, and if so, truncate */
+  max_width   = ((container_rect.right - container_rect.left) -
+      (container->nbr_buttons - 1) * horz_spacing) / container->nbr_buttons;
+  if (btn_width > max_width)
+    btn_width   = max_width;
+  switch(btn_type)
+  {
+    case XIBT_BUTTON:
+    case XIBT_BUTTON_CHECKBOX:
+    case XIBT_BUTTON_RADIOBTN:
+      btn_height  =  (int)((xi_get_pref(XI_PREF_BUTTON_HEIGHT) * vert_form_unit)
+        / XI_FU_MULTIPLE );
+      center      = TRUE;
+      break;
+    case XIBT_TABBTN:
+      btn_height  = container_rect.bottom - container_rect.top;
+      center      = FALSE;
+      break;
+    case XIBT_CHECKBOX:
+    case XIBT_RADIOBTN:
+      btn_height = (int)vert_form_unit;
+      center = TRUE;
+      break;
+  }
+  if (center == TRUE)
+  {
+    container_rect.top += (container_rect.bottom - container_rect.top
+        - btn_height) / 2;
+    container_rect.bottom = container_rect.top + btn_height;
+  }
+  container->rct = container_rect;
+  container->nbr_across  = container->nbr_buttons;
+  container->nbr_down = 1;
+  container->pix_width = btn_width;
+  container->pix_height = btn_height;
+  container->step_across = btn_width + horz_spacing;
+  container->step_down = 0;
+}
+
+static void calc_vertical_stack( XI_OBJ* itf, XI_CONTAINER_DATA* container,
+        XI_BTN_TYPE btn_type )
+{
+  int    btn_height, max_height, top_ofst, vert_spacing;
+  XI_RCT container_rect;
+  long   vert_form_unit;
+
+  vert_form_unit = xi_get_fu_height( itf );
+  container_rect = container->rct;
+  switch(btn_type)
+  {
+    case XIBT_BUTTON:
+    case XIBT_BUTTON_CHECKBOX:
+    case XIBT_BUTTON_RADIOBTN:
+    case XIBT_TABBTN:
+      if (container->packed)
+  vert_spacing = 0;
+      else if ((vert_spacing = (int)xi_get_pref( XI_PREF_VERT_PIXEL_SPACING))
+        == 0)
+  vert_spacing = (int)((xi_get_pref(XI_PREF_VERT_SPACING)
+          * vert_form_unit) / XI_FU_MULTIPLE );
+      top_ofst = vert_spacing / 2;
+      break;
+    case XIBT_CHECKBOX:
+    case XIBT_RADIOBTN:
+      vert_spacing    = 0;
+      top_ofst        = 0;
+      break;
+  }
+  btn_height  = (int)((xi_get_pref(XI_PREF_BUTTON_HEIGHT) * vert_form_unit)
+    / XI_FU_MULTIPLE);
+  max_height  = (container_rect.bottom - container_rect.top - top_ofst
+      - ((container->nbr_buttons - 1) * vert_spacing)) / container->nbr_buttons;
+  switch (btn_type)
+  {
+    case XIBT_CHECKBOX:
+    case XIBT_RADIOBTN:
+      btn_height = (int)vert_form_unit;
+      break;
+  }
+  if (btn_height > max_height)
+    btn_height  = max_height;
+  xvt_errmsg_sig_if(!( btn_height >= vert_form_unit), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20014", 20014,
+    "Not enough room in container for buttons");   
+  container_rect.top += top_ofst;
+  container->rct = container_rect;
+  container->nbr_across  = 1;
+  container->nbr_down = container->nbr_buttons;
+  container->pix_width = container->rct.right - container->rct.left;
+  container->pix_height = btn_height;
+  container->step_across = 0;
+  container->step_down = btn_height + vert_spacing;
+}
+
+static void calc_grid( XI_OBJ* itf, XI_CONTAINER_DATA* container )
+{
+  int     hz_pix_space, vt_pix_space, slack;
+  PNT     pnt;
+  XI_RCT  container_rect;
+
+  container_rect = container->rct;
+  xvt_errmsg_sig_if(!((container->btn_width > 0)||(container->btn_height > 0)),
+    NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20039", 20039,
+    "width  or height required with grid");   
+  pnt.v = container->btn_height;
+  pnt.h = container->btn_width;
+  xi_fu_to_pu(itf, &pnt, 1);
+  if ((pnt.v == 0) || (pnt.h == 0))
+  {
+  /* make it so that pnt.h and pnt.v are the same */
+  if (pnt.v == 0)
+    pnt.v = pnt.h;
+  if (pnt.h == 0)
+    pnt.h = pnt.v;
+  }
+  container->pix_height  = pnt.v;
+  container->pix_width   = pnt.h;
+  xvt_errmsg_sig_if(!( container->pix_height <= container_rect.bottom - container_rect.top),
+    NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20032",
+    20032, "button height exceeds container height");   
+  xvt_errmsg_sig_if(!(container->pix_width <= container_rect.right - container_rect.left),
+    NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20033",
+    20033, "button width exceeds container width");   
+  pnt.v = XI_FU_MULTIPLE;
+  xi_fu_to_pu(itf, &pnt, 1);
+  xvt_errmsg_sig_if(!((container->pix_height >= pnt.v)), NULL_WIN,
+    SEV_FATAL, ERR_ASSERT_4, "20034", 20034,
+    "height must be at least 8 form units");   
+  if (container->packed == TRUE)
+  {
+  /* note that if not native, the space is NEGATIVE */
+  vt_pix_space    = ((BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS))
+  ? 0 : -(int)xi_get_pref(XI_PREF_CONTAINER_GRID_WIDTH);
+    hz_pix_space    = vt_pix_space;
+  }
+  else
+  {
+    pnt.v   = (int)xi_get_pref(XI_PREF_VERT_SPACING);
+    pnt.h   = (int)xi_get_pref(XI_PREF_HORZ_SPACING);
+    xi_fu_to_pu(itf, &pnt, 1);
+    vt_pix_space    = pnt.v;
+    hz_pix_space    = pnt.h;
+  }
+  container->step_down   = container->pix_height + vt_pix_space;
+  container->step_across = container->pix_width + hz_pix_space;
+  if (container->orientation == XI_GRID_HORIZONTAL)
+  {
+    container->nbr_across  = (container_rect.right - container_rect.left
+            + hz_pix_space) / container->step_across;
+    container->nbr_down    = 1 + (container->nbr_buttons - 1)
+          /container->nbr_across;
+    slack = (container_rect.bottom - container_rect.top + vt_pix_space)
+      - (container->nbr_down * container->step_down);
+  }
+  else
+  {
+    container->nbr_down = (container_rect.bottom - container_rect.top
+        + vt_pix_space) / container->step_down;
+    container->nbr_across  = 1 + (container->nbr_buttons - 1)
+          /container->nbr_down;
+    slack = (container_rect.right - container_rect.left + hz_pix_space)
+      - (container->nbr_across * container->step_across);
+  }
+  xvt_errmsg_sig_if(!(slack >= 0), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20035",
+    20035, "Buttons won't fit in container");   
+}
+
+void xi_container_rect_calc( XI_OBJ *cnt_obj, int max_text_len,
+          XI_BTN_TYPE btn_type)
+{
+  XI_CONTAINER_DATA* container;
+
+  container   = cnt_obj->v.container;
+  if ( container->rct.left == 0 && container->rct.top == 0
+      && container->rct.bottom == 0 && container->rct.right == 0)
+  {
+    XI_RCT rect;
+
+    rect = container->xi_rct;
+    xi_fu_to_pu(cnt_obj->itf, (PNT *)&rect, 2);
+    container->rct = rect;
+  }
+  switch (container->orientation)
+  {
+    case XI_STACK_HORIZONTAL:
+      calc_horizontal_stack( cnt_obj->itf, container, btn_type, max_text_len );
+      break;
+    case XI_STACK_VERTICAL:
+      calc_vertical_stack( cnt_obj->itf, container, btn_type );
+      break;
+    case XI_GRID_HORIZONTAL:
+    case XI_GRID_VERTICAL:
+      calc_grid( cnt_obj->itf, container );
+      break;
+  }
+}
+
+/*---------------------------------------------------------------------
+function:   xi_button_rect_calc
+btn_obj:    Button object (with data structure complete except for rct)
+sequence:   button sequence within parent (used for contained buttons only)
+process:    Calculate the button rectangle size, either from the
+      container information or the xi rectangle.
+---------------------------------------------------------------------*/
+void
+xi_button_rect_calc(XI_OBJ  *btn_obj, int sequence)
+{
+  RCT     rct;
+  BOOLEAN packed; /* button has no dflt or focus rects */
+
+  if (btn_obj->parent->type == XIT_CONTAINER)
+  {
+    int                     row, col;
+    XI_CONTAINER_DATA   *cdata;
+
+    cdata   = btn_obj->parent->v.container;
+    switch(cdata->orientation)
+    {
+    case XI_STACK_HORIZONTAL:
+      row     = 0;
+      col     = sequence;
+      packed  = FALSE;
+      break;
+    case XI_STACK_VERTICAL:
+      row     = sequence;
+      col     = 0;
+      packed  = FALSE;
+      break;
+    case XI_GRID_HORIZONTAL:
+      row     = sequence / cdata->nbr_across;
+      col     = sequence - row * cdata->nbr_across;
+      packed  = cdata->packed;
+      break;
+    case XI_GRID_VERTICAL:
+      col     = sequence / cdata->nbr_down;
+      row     = sequence - col * cdata->nbr_down;
+      packed  = cdata->packed;
+      break;
+    }
+    rct.top     = cdata->rct.top + row * cdata->step_down;
+    rct.left    = cdata->rct.left + col * cdata->step_across;
+    rct.bottom  = rct.top + cdata->pix_height;
+    rct.right   = rct.left + cdata->pix_width;
+  }
+  else
+  {
+    rct = btn_obj->v.btn->rct;
+    if (rct.left == 0 && rct.top == 0 && rct.bottom == 0 && rct.right == 0)
+    {
+      rct = btn_obj->v.btn->xi_rct;
+      xi_fu_to_pu(btn_obj->itf, (PNT *)&rct, 2);
+    }
+    if (rct.top == rct.bottom)
+    {
+      /* use default height */
+      rct.bottom = rct.top + (int)xi_get_pref(XI_PREF_BUTTON_HEIGHT);
+    }
+    packed  = FALSE;
+  }
+  btn_obj->v.btn->rct     = rct;
+  btn_obj->v.btn->packed  = packed;
+}
+
+/*---------------------------------------------------------------------
+function:   xi_container_reorient
+cnt_obj:    The EXISTING container object
+cnt_def:    A revised definition of the container:
+  XI_RCT  xi_rct;     // new rectangle, if empty, use old
+  XI_CONTAINER_ORIENTATION orientation;   new value
+  int     tab_cid;    // NOT USED
+  short   btn_width;  // for grids, new value in form units
+  short   btn_height; // for grids, new value in form units
+  BOOLEAN packed;     // new value
+process:    change the container position, orientation, etc.
+---------------------------------------------------------------------*/
+void 
+xi_container_reorient(XI_OBJ  *cnt_obj, XI_CONTAINER_DEF  *cnt_def)
+{
+  int                     i, len, max_len;
+  XI_CONTAINER_DATA   *cdata;
+
+  xvt_errmsg_sig_if(!(cnt_obj->type == XIT_CONTAINER), NULL_WIN, SEV_FATAL,
+    ERR_ASSERT_4, "20036", 20036,
+    "xi_container_reorient() passed wrong object type");   
+  cdata   = cnt_obj->v.container;
+  xi_invalidate_rect(xi_get_window(cnt_obj->itf), &cdata->rct);
+  if ((cnt_def->xi_rct.bottom > cnt_def->xi_rct.top)
+      ||(cnt_def->xi_rct.right > cnt_def->xi_rct.left))
+    cdata->xi_rct   = cnt_def->xi_rct;
+  cdata->rct = cnt_def->pixel_rect;
+  cdata->orientation  = cnt_def->orientation;
+  cdata->btn_height   = cnt_def->btn_height;
+  cdata->btn_width    = cnt_def->btn_width;
+  cdata->packed       = cnt_def->packed;
+  max_len     = 0;
+  for (i = 0; i < cnt_obj->nbr_children; ++i)
+  {
+    if ((len = (int)strlen(cnt_obj->children[i]->v.btn->text)) > max_len)
+      max_len = len;
+  }
+  xi_container_rect_calc(cnt_obj, max_len, cnt_obj->children[0]->v.btn->type);
+  for (i = 0; i < cnt_obj->nbr_children; ++i)
+  {
+    xi_button_rect_calc(cnt_obj->children[i], i);
+  }
+  xi_invalidate_rect(xi_get_window(cnt_obj->itf), &cdata->rct);
+}
+
+/*--------------------------------------------------------------------------*/
+/* xi_def_get_font                                                          */
+/*--------------------------------------------------------------------------*/
+
+FONT_OBJ* xi_def_get_font( XI_OBJ_DEF* obj_def )
+{
+  FONT_OBJ* font = NULL;
+
+  if (!obj_def)
+    return &xi_sysfont;
+  switch (obj_def->type)
+  {
+  case XIT_FIELD:
+    if (obj_def->v.field->font_id)
+  font = &obj_def->v.field->font_id;
+    break;
+  case XIT_TEXT:
+    if (obj_def->v.text->font_id)
+  font = &obj_def->v.text->font_id;
+    break;
+  case XIT_LIST:
+    if (obj_def->v.list->font_id)
+  font = &obj_def->v.list->font_id;
+    break;
+  case XIT_ITF:
+    if (obj_def->v.itf->font_id)
+  font = &obj_def->v.itf->font_id;
+    break;
+  }
+  if (font != NULL)
+  return font;
+  return xi_def_get_font( obj_def->parent );
+}
+
+/*--------------------------------------------------------------------------*/
+/* xi_get_xil_pref                                                          */
+/*--------------------------------------------------------------------------*/
+
+BOOLEAN xi_get_xil_pref( XI_OBJ* obj )
+{
+  /* Determine if the passed object is the interface */
+  if (xi_is_itf(obj))
+  {
+    /* If the local variable is set use XIL coordinates */
+    if (obj->v.itf->use_xil_win) return TRUE;
+    /* If the PREF is set use XIL coordinates */
+  if ((BOOLEAN)xi_get_pref(XI_PREF_XIL)) return TRUE;
+  /* The interface was not passed in so use the PREF */
+  }else
+  if ((BOOLEAN)xi_get_pref(XI_PREF_XIL)) return TRUE;
+
+  return FALSE;
+}
+
+
diff --git a/xi/xiutils.h b/xi/xiutils.h
new file mode 100755
index 000000000..289b7c023
--- /dev/null
+++ b/xi/xiutils.h
@@ -0,0 +1,115 @@
+/*******************************************************************************
+*  Copyright 1991-1995 by ORCA Software, Inc.                                  *
+*                                                                              *
+*  All rights reserved.  May not be reproduced or distributed, in printed or   *
+*  electronic form, without permission of ORCA Software, Inc.                  *
+*******************************************************************************/
+
+extern CBRUSH ltgray_cbrush;
+extern CBRUSH gray_cbrush;
+extern CBRUSH hollow_cbrush;
+extern FONT_OBJ xi_sysfont;
+extern RCT big_clip;
+
+/* DIMENSIONS FOR FIELD OBJET BORDER */
+#define XI_FLD_XBORDER XI_FU_MULTIPLE /* may change for OL implementation */
+
+/* UTILITY FUNCTIONS */
+#ifdef DEBUG
+void pr_xi_event(XI_OBJ *itf, XI_EVENT *xiev);
+#endif
+
+#if 0 /* this is platform-dependent */
+#define XI_COLUMN_XDIV XI_FU_MULTIPLE
+#define XI_LIST_XBORDER XI_FU_MULTIPLE
+#endif
+
+RCT*     adjust_rect(RCT *rct, int pwid);
+int      clip(int val, int mn, int mx);
+void     dbg_rct(char *tag, RCT *rct);
+void     order_ints(int *ip1, int *ip2);
+char*    gmemmove(char *d, char *s, long n);
+char*    gstrncpy(char *dst, char *src, int n);
+char*    tgstrncpy(char *dst, char *src, int n);
+
+void     xi_adjust_sb_vir_itf(WINDOW win, XI_OBJ *itf);
+void     xi_button_rect_calc(XI_OBJ *btn_obj, int sequence);
+void     xi_container_rect_calc( XI_OBJ *cnt_obj, int max_text_len,
+                                XI_BTN_TYPE btn_type);
+FONT_OBJ* xi_def_get_font( XI_OBJ_DEF* obj_def );
+BOOLEAN   xi_get_xil_pref( XI_OBJ* obj );
+void      xi_draw_clipped_text( WINDOW win, char *s, RCT *bound_rct,
+                                RCT *clip_rct, unsigned long attrib,
+                                BOOLEAN set_the_cpen, int rule_and_space,
+                                int len);
+void     xi_dbg(char *buf);
+void     xi_draw_button( XI_OBJ *xi_obj, RCT *rct, char *text,
+                        int down_icon_rid, int up_icon_rid,
+                        int disabled_icon_rid, BOOLEAN enabled,
+                        BOOLEAN visible, BOOLEAN focus, BOOLEAN down,
+                        BOOLEAN dflt, BOOLEAN checked, BOOLEAN box_only);
+BOOLEAN  xi_eh(WINDOW win, EVENT *ep);
+void     xi_even_fu(int *f);
+void     xi_even_fu_pnt(PNT *p);
+RCT*     xi_inflate_rect(RCT *rct, int amount);
+#if XIWS == WMWS
+void     xi_coalesce_invalidates(XI_OBJ *itf, BOOLEAN coalesce);
+void     xi_fix_color(COLOR *color);
+#endif
+void     xi_fu_to_pu_font(FONT_OBJ *font, PNT *pnt, int nbr_pnts);
+RCT*     xi_get_enclosing_rect(RCT *dst, RCT *src1, RCT *src2);
+void     xi_get_font_metrics_font( FONT_OBJ *font, int *leading, int *ascent,
+                                  int *descent, int *char_width);
+int      xi_get_fu_height(XI_OBJ *itf);
+int      xi_get_fu_height_font(FONT_OBJ *font);
+int      xi_get_fu_width(XI_OBJ *itf);
+int      xi_get_fu_width_font(FONT_OBJ *font);
+void     xi_get_hsb_rect(XI_OBJ *xi_obj, RCT *rctp);
+XI_OBJ*  xi_get_itf_from_id( int id );
+RCT*     xi_get_rect_internal( XI_OBJ *xi_obj, RCT *rctp, RCT *old_win_rct,
+                              RCT *new_win_rct);
+void     xi_get_sb_rect(XI_OBJ *xi_obj, RCT *rctp);
+BOOLEAN  xi_half_baked(WINDOW win);
+void     xi_init_sysvals(void);
+void     xi_make_obj_visible(XI_OBJ *xi_obj);
+void     xi_menu_enable(XI_OBJ *itf, int tag, BOOLEAN enable);
+void     xi_move_column_internal( XI_OBJ *column, int position,
+                                  BOOLEAN in_hscrolling);
+void     xi_move_list_hscroll_bar(XI_OBJ *xi_obj);
+void     xi_move_list_scroll_bar(XI_OBJ *xi_obj);
+WINDOW   xi_new_control( RCT *lrctp, char *title, WIN_TYPE t, WINDOW parent,
+                        BOOLEAN visible, int id, char *templat);
+int      xi_obj_to_idx(XI_OBJ *xi_obj);
+void     xi_realloc_array( void **ptr, int nbr, size_t sz, void *parent);
+void     xi_set_sysval(XI_SV_TYPE valtype, int value);
+void     xi_set_trap_obj(XI_OBJ *obj);
+void     xi_set_update_obj(XI_OBJ *xi_obj);
+void     xi_terminate(void);
+#ifdef TREEDEBUG
+#define xi_tree_realloc2(o, s, p) xi_tree_realloc_d2(o, s, p, __LINE__, __FILE__)
+char*    xi_tree_realloc_d2(char *oldp, size_t size, char *parent, int line,
+                            char *filename);
+#else
+char*    xi_tree_realloc2(char *oldp, size_t size, char *parent);
+#endif
+XVT_FNTID* xi_font_to_fontid(XI_OBJ *itf, void *a_font, XVT_FNTID *font_id);
+FONT*      xi_fontid_to_font(XVT_FNTID font_id, void *parent);
+FONT_OBJ   xi_create_copy_font_id(XI_OBJ *itf, FONT_OBJ font_id, FONT_OBJ old_font_id);
+void       xi_free_font_id(XI_OBJ *itf, FONT_OBJ font_id);
+BOOLEAN    font_compare ( XVT_FNTID f1, XVT_FNTID f2 );
+
+/*********************************************************************/
+/* XI minimal compatability layer */
+
+extern CPEN hollow_cpen;
+extern CPEN black_cpen;
+extern CPEN rubber_cpen;
+extern CBRUSH white_cbrush;
+extern CBRUSH hollow_cbrush;
+
+#define E_KILL_WINDOW E_DESTROY
+#define E_ACTIVATE E_FOCUS
+
+
+/*********************************************************************/
+