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,¤t_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 + + +/*********************************************************************/ +