*** empty log message ***
authorpcg <pcg>
Mon, 24 Nov 2003 17:28:07 +0000 (17:28 +0000)
committerpcg <pcg>
Mon, 24 Nov 2003 17:28:07 +0000 (17:28 +0000)
66 files changed:
Makefile.in [new file with mode: 0644]
autoconf/aclocal.m4 [new file with mode: 0644]
autoconf/configure.in [new file with mode: 0644]
autoconf/xpm.m4 [new file with mode: 0644]
doc/Makefile.in [new file with mode: 0644]
doc/yodl/masonyodl.yo [new file with mode: 0644]
doc/yodl/rxvt-colours.yo [new file with mode: 0644]
doc/yodl/rxvt-environment.yo [new file with mode: 0644]
doc/yodl/rxvt-files.yo [new file with mode: 0644]
doc/yodl/rxvt-fonts.yo [new file with mode: 0644]
doc/yodl/rxvt-login.yo [new file with mode: 0644]
doc/yodl/rxvt-mousereporting.yo [new file with mode: 0644]
doc/yodl/rxvt-options.yo [new file with mode: 0644]
doc/yodl/rxvt-resources.yo [new file with mode: 0644]
doc/yodl/rxvt-scrollbar.yo [new file with mode: 0644]
doc/yodl/rxvt-textselection.yo [new file with mode: 0644]
doc/yodl/rxvt.yo [new file with mode: 0644]
doc/yodl/rxvtRef-csi.yo [new file with mode: 0644]
doc/yodl/rxvtRef-definitions.yo [new file with mode: 0644]
doc/yodl/rxvtRef-graphics.yo [new file with mode: 0644]
doc/yodl/rxvtRef-keycodes.yo [new file with mode: 0644]
doc/yodl/rxvtRef-menubar.yo [new file with mode: 0644]
doc/yodl/rxvtRef-mouse.yo [new file with mode: 0644]
doc/yodl/rxvtRef-privatemodes.yo [new file with mode: 0644]
doc/yodl/rxvtRef-sequences.yo [new file with mode: 0644]
doc/yodl/rxvtRef-values.yo [new file with mode: 0644]
doc/yodl/rxvtRef-xpm.yo [new file with mode: 0644]
doc/yodl/rxvtRef-xterm.yo [new file with mode: 0644]
doc/yodl/rxvtRef.yo [new file with mode: 0644]
doc/yodl/versioninfo.yo.in [new file with mode: 0644]
src/Makefile.in [new file with mode: 0644]
src/command.C [new file with mode: 0644]
src/command.h [new file with mode: 0644]
src/defaultfont.h [new file with mode: 0644]
src/feature.h [new file with mode: 0644]
src/graphics.C [new file with mode: 0644]
src/graphics/Makefile.in [new file with mode: 0644]
src/graphics/grxlib.c [new file with mode: 0644]
src/graphics/grxlib.h [new file with mode: 0644]
src/graphics/qplot.c [new file with mode: 0644]
src/grkelot.C [new file with mode: 0644]
src/grkelot.h [new file with mode: 0644]
src/init.C [new file with mode: 0644]
src/init.h [new file with mode: 0644]
src/logging.C [new file with mode: 0644]
src/logging.h [new file with mode: 0644]
src/main.C [new file with mode: 0644]
src/makeextprotos-sed [new file with mode: 0644]
src/makeintprotos-sed [new file with mode: 0644]
src/menubar.C [new file with mode: 0644]
src/menubar.h [new file with mode: 0644]
src/misc.C [new file with mode: 0644]
src/netdisp.C [new file with mode: 0644]
src/protos.h [new file with mode: 0644]
src/ptytty.C [new file with mode: 0644]
src/rxvt.h [new file with mode: 0644]
src/rxvtgrx.h [new file with mode: 0644]
src/rxvtlib.h.in [new file with mode: 0644]
src/screen.C [new file with mode: 0644]
src/scrollbar-next.C [new file with mode: 0644]
src/scrollbar-rxvt.C [new file with mode: 0644]
src/scrollbar-xterm.C [new file with mode: 0644]
src/scrollbar.C [new file with mode: 0644]
src/strings.C [new file with mode: 0644]
src/xdefaults.C [new file with mode: 0644]
src/xpm.C [new file with mode: 0644]

diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..55266f5
--- /dev/null
@@ -0,0 +1,118 @@
+# ./Makefile.in                        -*- Makefile -*-
+# $Id: Makefile.in,v 1.1 2003-11-24 17:28:07 pcg Exp $
+@MCOMMON@
+
+srcdir =       @srcdir@
+VPATH =                @srcdir@
+.PATH:         @srcdir@
+
+first_rule: all
+dummy:
+
+subdirs = src doc src/graphics src/test
+allsubdirs = W11 $(subdirs)
+
+DIST = INSTALL README.configure configure Makefile Makefile.in ChangeLog
+
+DIST_CFG = autoconf/aclocal.m4 autoconf/xpm.m4 autoconf/libtool.m4 \
+       autoconf/configure.in  autoconf/config.h.in \
+       autoconf/Make.common.in autoconf/install-sh autoconf/mkinstalldirs \
+       autoconf/config.guess autoconf/config.sub \
+       autoconf/ltmain.sh \
+
+MKDIR = $(srcdir)/autoconf/mkinstalldirs
+
+#-------------------------------------------------------------------------
+
+all allbin alldoc tags:
+       @if test x@host_os@ = xcygwin; then (cd W11; ${MAKE} $@) || exit 1; fi
+       @for I in ${subdirs}; do (cd $$I; ${MAKE} $@) || exit 1; done
+
+realclean: clean
+       $(RMF) config.h config.status config.log libtool
+
+clean:
+       $(RMF) *~ config.cache
+       $(RMF) -r autom4te.cache
+       @if test x@host_os@ = xcygwin; then (cd W11; ${MAKE} $@) || exit 1; fi
+       @for I in ${subdirs}; do (cd $$I; ${MAKE} $@) || exit 1; done
+
+#
+# entry points for other programs
+#
+rxvt:
+       (cd src; ${MAKE})
+
+clock:
+       (cd rclock; ${MAKE})
+
+graphics qplot:
+       (cd src/graphics; ${MAKE} qplot)
+
+tests:
+       (cd src/test; ${MAKE} tests)
+
+#-------------------------------------------------------------------------
+configure: autoconf/configure.in autoconf/aclocal.m4 autoconf/config.h.in
+       cd $(srcdir);
+       ./.prebuild
+
+config.status:
+       if test -x config.status; then config.status --recheck; \
+       else $(SHELL) configure; fi
+
+autoconf/config.h.in: autoconf/configure.in
+       cd $(srcdir);
+       ./.prebuild
+
+installdirs:
+       $(MKDIR) $(DESTDIR)$(bindir)
+       $(MKDIR) $(DESTDIR)$(mandir)
+
+install: installdirs
+       @if test x@host_os@ = xcygwin; then (cd W11; ${MAKE} $@) || exit 1; fi
+       @for I in $(subdirs); do (cd $$I; $(MAKE) DESTDIR=$(DESTDIR) $@) || exit 1; done
+
+Makefiles:
+       $(SHELL) config.status
+
+cleandir: realclean
+
+# distclean goal is for making a clean source tree, but if you have run
+# configure from a different directory, then doesn't destroy all your
+# hardly compiled and linked stuff. That's why there is always $(srcdir)/
+# In that case most of those commands do nothing, except cleaning *~
+# and cleaning source links.
+distclean:
+       (cd $(srcdir); $(RMF) *~ config.cache config.h config.log config.status libtool)
+       @for I in $(allsubdirs); do (cd $$I; $(MAKE) $@) || exit 1; done
+       (cd $(srcdir); $(RMF) Makefile autoconf/Make.common)
+
+distdirs:
+       mkdir ../$(VERNAME);
+       mkdir ../$(VERNAME)/autoconf;
+       @for I in $(allsubdirs); do (cd $$I; $(MAKE) $@ || (echo "Failed to make distclean in $$I"; exit 0) ); done
+
+distcopy:
+       $(CP) -p $(DIST) ../$(VERNAME);
+       $(CP) -p $(DIST_CFG) ../$(VERNAME)/autoconf;
+       @for I in $(allsubdirs); do (cd $$I; $(MAKE) $@) || exit 1; done
+
+distrib: configure autoconf/config.h.in distdirs distcopy
+
+tar.gz:  ../$(VERNAME).tar.gz
+../$(VERNAME).tar.gz:
+       (cd ..; tar cvf - $(VERNAME) | gzip -f9 > $(VERNAME).tar.gz)
+
+tar.Z: ../$(VERNAME).tar.Z
+../$(VERNAME).tar.Z:
+       (cd ..; tar cvf - $(VERNAME) | compress > $(VERNAME).tar.Z)
+
+tar.bz2: ../$(VERNAME).tar.bz2
+../$(VERNAME).tar.bz2:
+       (cd ..; tar cvf - $(VERNAME) | bzip2 -f9 > $(VERNAME).tar.bz2)
+
+uuencode: tar.gz
+       uuencode ../$(VERNAME).tar.gz $(VERNAME).tar.gz > ../$(VERNAME).tgz.uu
+
+# ------------------------------------------------------------------------
diff --git a/autoconf/aclocal.m4 b/autoconf/aclocal.m4
new file mode 100644 (file)
index 0000000..1b08d45
--- /dev/null
@@ -0,0 +1,4 @@
+dnl> $Id: aclocal.m4,v 1.1 2003-11-24 17:28:08 pcg Exp $
+
+builtin(include, xpm.m4)
+builtin(include, libtool.m4)
diff --git a/autoconf/configure.in b/autoconf/configure.in
new file mode 100644 (file)
index 0000000..f542ab8
--- /dev/null
@@ -0,0 +1,1360 @@
+dnl# -*- sh -*-
+dnl#
+dnl# $Id: configure.in,v 1.1 2003-11-24 17:28:08 pcg Exp $
+dnl#
+dnl# Process this file with autoconf to produce a configure script.
+dnl#
+AC_INIT(src/feature.h)
+AC_CONFIG_AUX_DIR(autoconf)
+AC_CONFIG_HEADER(config.h:autoconf/config.h.in)
+
+dnl RXVT version
+changequote(, )dnl
+VERSION=`sed -n -e 's/^.*[ \t]VERSION.*"\(.*\)"$/\1/p' ${srcdir}/src/version.h`
+DATE=`sed -n -e 's/^.*[ \t]DATE.*"\(.*\)"$/\1/p' ${srcdir}/src/version.h`
+LSMDATE=`sed -n -e 's/^.*[ \t]LSMDATE.*"\(.*\)"$/\1/p' ${srcdir}/src/version.h`
+LIBVERSION=`sed -n -e 's/^.*[ \t]LIBVERSION.*"\(.*\)"$/\1/p' ${srcdir}/src/version.h`
+changequote([, ])dnl
+AC_SUBST(VERSION)dnl 
+AC_SUBST(DATE)dnl 
+AC_SUBST(LSMDATE)dnl 
+AC_SUBST(LIBVERSION)dnl 
+echo ""
+echo "configuring for rxvt $VERSION"
+echo ""
+
+dnl# Checks for programs.
+dnl AC_MAKE_SET
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_AWK
+
+dnl# system hacks
+AC_AIX
+AC_ISC_POSIX
+
+AC_ENABLE_SHARED(no)dnl#       libtool
+AC_ENABLE_STATIC(yes)dnl#      libtool
+AC_PROG_LIBTOOL()dnl#          libtool
+
+MALLOC_TYPE=S
+support_addstrings=no
+support_frills=no
+support_linespace=no
+support_graphics=no
+support_inheritpixmap=no
+support_keepscrolling=no
+support_selectionscrolling=no
+support_menubar=no 
+support_mousewheel=no
+support_mouseslipwheel=no
+support_oldselection=no
+support_utmp=no
+support_wtmp=no
+support_lastlog=no
+support_cursor_blink=no
+support_pointer_blank=no
+support_scroll_rxvt=no
+support_scroll_next=no
+support_scroll_xterm=no
+support_xim=no
+support_xpm=no
+support_xft=no
+support_unicode3=no
+codesets=
+
+dnl# --------------------------------------------------------------------------
+dnl# CHECKING COMMAND LINE OPTIONS
+dnl# --------------------------------------------------------------------------
+
+if test "x$enable_shared" = xyes; then
+    AC_DEFINE(LIBRXVT, 1, Build shared library version - specify via configure only)
+    INSTALL_LIBRXVT=yes
+fi
+AC_SUBST(INSTALL_LIBRXVT)
+
+AC_ARG_ENABLE(everything,
+  [  --enable-everything     enable standard non-multichoice features: marked *
+                     NOTE: this option is order dependent
+                     NOTE: automatically enabled with --enable-shared],
+  [if test x$enableval = xyes; then
+    support_24bit=yes
+    support_frills=yes
+    support_linespace=yes
+    support_graphics=yes
+    support_inheritpixmap=yes
+    support_keepscrolling=yes
+    support_selectionscrolling=yes
+    support_lastlog=yes
+    support_menubar=yes
+    support_mousewheel=yes
+    support_mouseslipwheel=yes
+    support_oldselection=yes
+    support_cursor_blink=yes
+    support_pointer_blank=yes
+    support_scroll_rxvt=yes
+    support_scroll_next=yes
+    support_scroll_xterm=yes
+    support_utmp=yes
+    support_wtmp=yes
+    support_xim=yes
+    support_xpm=yes
+    support_xft=yes
+    support_unicode3=yes
+    codesets=all
+  fi])
+
+AC_ARG_ENABLE(unicode3,
+  [  --enable-unicode3       use 21 instead of 16 bits to represent unicode characters],
+  [if test x$enableval = xyes; then
+    support_unicode3=yes
+  fi])
+
+AC_ARG_ENABLE(xft,
+  [  --enable-xft       enable xft support on systems that have it],
+  [if test x$enableval = xyes; then
+    support_xft=yes
+  fi])
+
+AC_ARG_WITH(codesets,
+  [  --with-codesets=NAME,...    compile in additional codesets (hp,jp_ext,kr,cn,cn_ext,vn,all)],
+  [if test x$enableval = xyes; then
+    codesets="$withval"
+  fi])
+
+AC_ARG_WITH(encoding,
+  [  --with-encoding=NAME    set language default encoding to NAME (default: sjis)
+                          (eucj|sjis|big5|gb|kr|noenc)],
+  [if test x$enableval = xyes; then
+    withval=`echo $withval | tr '[a-z]' '[A-Z]'`
+    AC_DEFINE_UNQUOTED(MULTICHAR_ENCODING, $withval, Define default multichar glyph encoding)
+  fi])
+
+AC_ARG_ENABLE(utmp,
+  [  --enable-utmp           enable utmp (utmpx) support                         *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_utmp=$enableval
+  fi])
+
+AC_ARG_ENABLE(wtmp,
+  [  --enable-wtmp           enable wtmp (wtmpx) support (requires --enable-utmp)*],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_wtmp=$enableval
+  fi])
+
+AC_ARG_ENABLE(lastlog,
+  [  --enable-lastlog        enable lastlog support (requires --enable-utmp)     *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_lastlog=$enableval
+  fi])
+
+AC_ARG_ENABLE(xpm-background,
+  [  --enable-xpm-background enable XPM background pixmaps                       *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_xpm=$enableval
+  fi])
+
+AC_ARG_ENABLE(transparency,
+  [  --enable-transparency   enable transparent backgrounds                      *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_inheritpixmap=$enableval
+  fi])
+
+AC_ARG_ENABLE(menubar,
+  [  --enable-menubar        enable menubar                                      *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_menubar=$enableval
+  fi])
+
+AC_ARG_ENABLE(graphics,
+  [  --enable-graphics       enable rxvt own graphics mode (see src/graphics)    *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_graphics=$enableval
+  fi])
+
+AC_ARG_ENABLE(rxvt-scroll,
+  [  --enable-rxvt-scroll    enable rxvt style scrollbar                         *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_scroll_rxvt=$enableval
+  fi])
+
+AC_ARG_ENABLE(next-scroll,
+  [  --enable-next-scroll    enable NeXT style scrollbar                         *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_scroll_next=$enableval
+  fi])
+
+AC_ARG_ENABLE(xterm-scroll,
+  [  --enable-xterm-scroll   enable Xterm style scrollbar                        *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_scroll_xterm=$enableval
+  fi])
+
+AC_ARG_ENABLE(half-shadow,
+  [  --enable-half-shadow    use half width/height shadow on rxvt scrollbar],
+  [if test x$enableval = xyes; then
+    AC_DEFINE(HALFSHADOW, 1, Define if you want the depth of scrollbars and menus to be less)
+  fi])
+
+AC_ARG_ENABLE(xim,
+  [  --enable-xim            XIM (X Input Method) protocol support               *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_xim=$enableval
+  fi])
+
+AC_ARG_ENABLE(greek,
+  [  --enable-greek          enable greek keyboard support],
+  [if test x$enableval = xyes; then
+    AC_DEFINE(GREEK_SUPPORT, 1, Define if you want support for Greek Elot-928 & IBM-437 keyboard)
+  fi])
+
+AC_ARG_ENABLE(ttygid,
+  [  --enable-ttygid         enable tty setting to group named "tty"],
+  [if test x$enableval = xyes; then
+    AC_DEFINE(TTY_GID_SUPPORT, 1, Define to change gid of ttys to group tty)
+  fi])
+
+AC_ARG_ENABLE(backspace-key,
+  [  --disable-backspace-key disable handling of the backspace key],
+  [if test x$enableval = xno; then
+    AC_DEFINE(NO_BACKSPACE_KEY, 1, Define if you don't want support for the backspace key)
+  fi])
+
+AC_ARG_ENABLE(delete-key,
+  [  --disable-delete-key    disable handling of the delete key],
+  [if test x$enableval = xno; then
+    AC_DEFINE(NO_DELETE_KEY, 1, Define if you don't want support for the (non-keypad) delete key)
+  fi])
+
+AC_ARG_ENABLE(resources,
+  [  --disable-resources     disable all resource checking],
+  [if test x$enableval = xno; then
+    AC_DEFINE(NO_RESOURCES, 1, Define if you don't want any resources read)
+  fi])
+
+AC_ARG_ENABLE(xgetdefault,
+  [  --enable-xgetdefault    enable resources via X instead of our small version],
+  [if test x$enableval = xyes; then
+    AC_DEFINE(USE_XGETDEFAULT, 1, Define if you want to use XGetDefault instead of our internal version)
+  fi])
+
+AC_ARG_ENABLE(strings,
+  [  --enable-strings        enable some replacement system functions],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_addstrings=$enableval
+  fi])
+
+AC_ARG_ENABLE(swapscreen,
+  [  --disable-swapscreen    disable swap screen support],
+  [if test x$enableval = xno; then
+    AC_DEFINE(NO_SECONDARY_SCREEN, 1, Disable the secondary screen. Many programs use the secondary screen as their workplace)
+  fi])
+
+AC_ARG_ENABLE(frills,
+  [  --enable-frills         enable support for rarely used features             *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_frills=$enableval
+  fi])
+
+AC_ARG_ENABLE(linespace,
+  [  --enable-linespace      enable support for linespace                        *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_linespace=$enableval
+  fi])
+
+AC_ARG_ENABLE(24bit,
+  [  --enable-24bit          enable support for using 24bit visuals if available *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_24bit=$enableval
+  fi])
+
+AC_ARG_ENABLE(keepscrolling,
+  [  --enable-keepscrolling  enable continual scrolling on scrollbar arrow press *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_keepscrolling=$enableval
+  fi])
+
+AC_ARG_ENABLE(selectionscrolling,
+  [  --enable-selectionscrolling  enable scrolling during selections             *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_selectionscrolling=$enableval
+  fi])
+
+AC_ARG_ENABLE(mousewheel,
+  [  --enable-mousewheel     enable scrolling via mouse wheel or buttons 4 & 5   *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_mousewheel=$enableval
+  fi])
+
+AC_ARG_ENABLE(slipwheeling,
+  [  --enable-slipwheeling   enable slip wheel scrolling     (requires previous) *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_mouseslipwheel=$enableval
+  fi])
+
+AC_ARG_ENABLE(old-selection,
+  [  --enable-old-selection  enable v2.20 (& prior) mouse selection style support*],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_oldselection=$enableval
+  fi])
+
+AC_ARG_ENABLE(new-selection,
+  [  --disable-new-selection disable new mouse (xterm) selection style support],
+  [if test x$enableval = xno; then
+    AC_DEFINE(NO_NEW_SELECTION, 1, Define to remove xterm style mouse selection)
+  fi])
+
+AC_ARG_ENABLE(dmalloc,
+  [  --enable-dmalloc        enable Gray Watson's malloc - for debugging use],
+  [if test x$enableval = xyes; then
+    MALLOC_TYPE=G
+    DEBUG=-DDEBUG_MALLOC
+    DLIB="-L/usr/local/lib -ldmalloc"
+    DINCLUDE=-I/usr/local/include
+  fi])
+
+AC_ARG_ENABLE(dlmalloc,
+  [  --enable-dlmalloc       enable Doug Lea's malloc - for production use
+                     NOTE: enable only one malloc package],
+  [if test x$enableval = xyes; then
+    MALLOC_TYPE=D
+    DEBUG=
+    DLIB="-L/usr/local/lib -ldlmalloc"
+    DINCLUDE=
+  fi])
+
+AC_ARG_ENABLE(smart-resize,
+  [  --enable-smart-resize   enable smart growth/shrink behaviour],
+  [if test x$enableval = xyes; then
+    AC_DEFINE(SMART_RESIZE, 1, Define to use "smart" resize behavior)
+  fi])
+
+AC_ARG_ENABLE(256-color,
+  [  --enable-256-color      enable 256-color support],
+  [if test x$enableval = xyes; then
+    AC_DEFINE(TTY_256COLOR, 1, Define if you want 256 colour support)
+  fi])
+
+AC_ARG_ENABLE(cursor-blink,
+  [  --enable-cursor-blink   enable blinking cursor                              *],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_cursor_blink=$enableval
+  fi])
+
+AC_ARG_ENABLE(pointer-blank,
+  [  --enable-pointer-blank  enable pointer blank when typing or inactive pointer*],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_pointer_blank=$enableval
+  fi])
+
+AC_ARG_WITH(term,
+  [  --with-term=NAME        set the terminal to NAME (default \"xterm\")],
+  [if test x$withval != x; then
+    AC_DEFINE_UNQUOTED(TERMENV, "$withval",Set TERM to the value given by configure) term="$withval"
+  fi])
+
+AC_ARG_WITH(terminfo,
+  [  --with-terminfo=PATH    set the path to the terminfo tree to PATH],
+  [if test x$withval != x; then
+    AC_DEFINE_UNQUOTED(RXVT_TERMINFO, "$withval", Set TERMINFO value to the value given by configure) terminfo="$withval"
+  fi])
+
+dnl# --------------------------------------------------------------------------
+
+AC_DEFINE(PROTOTYPES, 1, Define if you need function prototypes)
+
+dnl# --------------------------------------------------------------------------
+dnl# Supply default CFLAGS, if not specified by `CFLAGS=flags ./configure'
+dnl#
+if test -z "$CFLAGS"; then
+    if test -z "$CCOPTS"; then
+       CCOPTS='-O'
+dnl>   if test "x$GCC" = xyes; then
+dnl>       if test x$system = xLinux; then
+dnl>           CCOPTS="$CCOPTS "'-O2 -fno-strength-reduce'
+dnl>       fi
+dnl>   fi
+    fi
+    CFLAGS="$CCOPTS"
+fi
+
+AC_PATH_PROG(MV, mv, mv)
+AC_PATH_PROG(RM, rm, rm)
+AC_PATH_PROG(CP, cp, cp)
+AC_PATH_PROG(LN, ln, ln)
+AC_PATH_PROG(SED, sed, sed)
+AC_PATH_PROG(ECHO, echo, echo)
+AC_PATH_PROG(CMP, cmp, cmp)
+AC_PATH_PROG(TBL, tbl)
+
+dnl# need a neat way to detect SVR4 or its features
+dnl# in src/command.c we use these functions:
+dnl# grantpt(), unlockpt(), ptsname(), which are defined in <sys/ptms.h>
+dnl# - but are these also defined for other systems?
+
+dnl# hack to find if this is SVR4 -- who knows?
+dnl## AC_MSG_CHECKING(for SVR4)
+dnl## AC_EGREP_CPP(yes,
+dnl## [#if defined (SVR4) || defined (_SVR4) || defined (__svr4__)
+dnl##   yes;
+dnl## #endif
+dnl## ], [AC_MSG_RESULT(yes); AC_DEFINE(PERHAPS_SVR4)], AC_MSG_RESULT(perhaps not?))
+
+AC_PATH_XTRA
+
+dnl# the only reasonable way to find libXpm is do-it-yourself
+dnl# only check if we want xpm-background
+
+if test x$support_xpm = xyes; then
+  VT_FIND_LIBXPM
+  if test x$no_xpm = xyes; then
+    support_xpm=needsmanualspecification
+  fi
+fi
+
+dnl# --------------------------------------------------------------------------
+dnl# CHECKING FOR HEADER FILES
+dnl# --------------------------------------------------------------------------
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS( \
+       assert.h \
+       fcntl.h \
+       grp.h \
+       libc.h \
+       lastlog.h \
+       stdarg.h \
+       stdlib.h \
+       string.h \
+       termios.h \
+       unistd.h \
+       sys/byteorder.h \
+       sys/ioctl.h \
+       sys/select.h \
+       sys/sockio.h \
+       sys/strredir.h \
+       sys/time.h \
+       utmp.h \
+       utmpx.h \
+        stdint.h \
+)
+
+AC_HEADER_TIME
+
+dnl# check to allow both <termios.h> and <sys/ioctl.h>
+AC_CACHE_CHECK(whether termios.h and sys/ioctl.h may both be included, rxvt_cv_header_sysioctl,
+[AC_TRY_COMPILE([#include <stdio.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif], [int a = ECHO;], rxvt_cv_header_sysioctl=yes, rxvt_cv_header_sysioctl=no)])
+
+dnl# ELF systems may want to store paths for dynamic libraries.
+dnl# Lets see if the compiler can accept "-Rpath" or "-Wl,-Rpath"
+dnl# At least one version of SunOS wants "-R path" but it's not checked yet.
+if test -n "$GCC"; then
+  LDARG="-Wl,"
+else
+  LDARG=""
+fi
+changequote(, )dnl
+R_TRANSLATE='s/-L\([^ ]*\)/-L\1 '$LDARG'-rpath '$LDARG'\1/g'
+changequote([, ])dnl
+
+ac_save_CFLAGS=$CFLAGS
+ac_save_LIBS=$LIBS
+CFLAGS="$CFLAGS $X_CFLAGS"
+LIBS=`echo "$LIBS $X_LIBS $X_EXTRA_LIBS -lX11" | sed "$R_TRANSLATE"`
+AC_CACHE_CHECK([for -rpath dynamic library path recording], rxvt_cv_rpath,
+[AC_TRY_RUN([
+main()
+{
+    exit(0);
+    (void) XOpenDisplay("foobar");
+}], rxvt_cv_rpath=yes, rxvt_cv_rpath=no, dnl                  
+  AC_MSG_WARN([You may need to check the LIBS line]))])             
+if test x$rxvt_cv_rpath != xyes; then
+  changequote(, )dnl
+  R_TRANSLATE='s/-L\([^ ]*\)/-L\1 '$LDARG'-R\1/g'
+  changequote([, ])dnl
+  LIBS=`echo "$ac_save_LIBS $X_LIBS $X_EXTRA_LIBS -lX11" | sed "$R_TRANSLATE"`
+  AC_CACHE_CHECK([for -R dynamic library path recording], rxvt_cv_R,
+[AC_TRY_RUN([
+main()
+{
+    exit(0);
+    (void) XOpenDisplay("foobar");
+}], rxvt_cv_R=yes, rxvt_cv_R=no, rxvt_cv_R=no)])             
+  if test x$rxvt_cv_R != xyes; then
+    LIBS="$ac_save_LIBS $X_LIBS $X_EXTRA_LIBS -lX11"
+  fi
+fi
+
+AC_CACHE_CHECK([for XPointer], rxvt_cv_xpointer,
+[AC_TRY_COMPILE([#include <X11/Xlib.h>], [XPointer dummy;],
+rxvt_cv_xpointer=yes, rxvt_cv_xpointer=no)])
+if test x$rxvt_cv_xpointer = xyes; then
+  AC_DEFINE(HAVE_XPOINTER, 1, Define if you have XPointer typedef)
+fi
+LIBS=$ac_save_LIBS
+CFLAGS=$ac_save_CFLAGS
+
+
+AC_C_CONST
+AC_C_INLINE
+
+dnl> AC_HEADER_STDC     dnl# skip this test, Sun always fails anyhow.
+
+dnl# --------------------------------------------------------------------------
+dnl# CHECKING FOR MISSING TYPEDEFS
+dnl# --------------------------------------------------------------------------
+dnl# Missing typedefs and replacements
+AC_TYPE_MODE_T
+dnl> AC_CHECK_TYPE(umode_t, int)
+dnl> AC_CHECK_TYPE(off_t, long)
+AC_TYPE_PID_T
+AC_TYPE_UID_T
+
+
+AC_CHECK_SIZEOF(char, 1)
+AC_CHECK_SIZEOF(short, 2)
+AC_CHECK_SIZEOF(int, 4)
+AC_CHECK_SIZEOF(long, 4)
+AC_CHECK_SIZEOF(long long, 8)
+AC_CHECK_SIZEOF(int *, 4)
+
+dnl# see usage below
+AC_DEFUN(RXVT_CHECK_SIZE,
+  [AC_CACHE_CHECK([for $2], $1,
+    [AC_TRY_COMPILE([#include <stdint.h>], $2 dummy;,
+      [$1=yes],
+      [dnl
+if test $ac_cv_sizeof_char -ge $3; then
+  $1="$4 char"
+else
+  if test $ac_cv_sizeof_short -ge $3; then
+    $1="$4 short"
+  else
+    if test $ac_cv_sizeof_int -ge $3; then
+      $1="$4 int"
+    else
+      if test $ac_cv_sizeof_long -ge $3; then
+        $1="$4 long"
+      else
+        if test $ac_cv_sizeof_long_long -ge $3; then
+          $1="$4 long long"
+        else
+          $1="$4 $5" # we _must_ have a (possibly wrong) default
+        fi
+      fi
+    fi
+  fi
+fi])])]
+if test x"$$1" != xyes; then
+  $6="typedef $$1 $2;"
+else
+  if test x"$4" = x; then
+    $6="/* typedef $5 $2; */"
+  else
+    $6="/* typedef $4 $5 $2; */"
+  fi
+fi dnl
+)
+dnl#
+dnl# Look for types the system may know about anyway.
+dnl#
+RXVT_CHECK_SIZE(rxvt_cv_int16_t, int16_t, 2, , short, rxvt_int16_typedef)
+AC_SUBST(rxvt_int16_typedef)
+RXVT_CHECK_SIZE(rxvt_cv_uint16_t, uint16_t, 2, unsigned, short, rxvt_uint16_typedef)
+AC_SUBST(rxvt_uint16_typedef)
+RXVT_CHECK_SIZE(rxvt_cv_int32_t, int32_t, 4, , int, rxvt_int32_typedef)
+AC_SUBST(rxvt_int32_typedef)
+RXVT_CHECK_SIZE(rxvt_cv_uint32_t, uint32_t, 4, unsigned, int, rxvt_uint32_typedef)
+AC_SUBST(rxvt_uint32_typedef)
+dnl RXVT_CHECK_SIZE(rxvt_cv_int64_t, int64_t, 8, , long long, rxvt_int64_typedef)
+dnl AC_SUBST(rxvt_int64_typedef)
+dnl RXVT_CHECK_SIZE(rxvt_cv_uint64_t, uint64_t, 8, unsigned, long long, rxvt_uint64_typedef)
+dnl AC_SUBST(rxvt_uint64_typedef)
+dnl#
+dnl# Now look for another we use
+dnl#
+if test $ac_cv_sizeof_int_p -eq 8; then
+  rxvt_intp_define="#define intp_t int64_t"
+  rxvt_u_intp_define="#define u_intp_t u_int64_t"
+else
+  if test $ac_cv_sizeof_int_p -eq 4; then
+    rxvt_intp_define="#define intp_t int32_t"
+    rxvt_u_intp_define="#define u_intp_t u_int32_t"
+  else
+    if test $ac_cv_sizeof_int_p -eq 2; then
+      rxvt_intp_define="#define intp_t int16_t"
+      rxvt_u_intp_define="#define u_intp_t u_int16_t"
+    else
+      rxvt_intp_define="#error set intp_t"
+      rxvt_u_intp_define="#error set u_intp_t"
+    fi
+  fi
+fi
+AC_SUBST(rxvt_intp_define)
+AC_SUBST(rxvt_u_intp_define)
+
+dnl# --------------------------------------------------------------------------
+dnl# CHECKING FOR LIBRARY FUNCTIONS
+dnl# --------------------------------------------------------------------------
+AC_TYPE_SIGNAL
+dnl> AC_FUNC_VPRINTF
+
+dnl# Note: On Ultrix, setsid() does weirdo stuff, disable it
+case "$host_alias" in
+    *ultrix) ac_cv_func_setsid='no' ;;
+    *) break;;
+esac
+
+AC_CHECK_FUNCS( \
+       atexit \
+       revoke \
+       unsetenv \
+       setutent \
+       seteuid \
+       setreuid \
+       setsid \
+       setpgrp \
+       setpgid \
+       openpty \
+       _getpty \
+       grantpt \
+       unlockpt \
+       isastream \
+       on_exit \
+       nanosleep \
+       updwtmp \
+       ttyslot \
+)
+dnl# Note: On NetBSD, openpty() exists in libutil.  Don't pull it in
+
+dnl# --------------------------------------------------------------------------
+dnl# DO ALL UTMP AND WTMP CHECKING
+dnl# --------------------------------------------------------------------------
+dnl# check for host field in utmp structure
+
+dnl# --------------------------------------------
+AC_CHECK_HEADER(utmp.h,
+[AC_CACHE_CHECK([for struct utmp], rxvt_cv_struct_utmp,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <stdint.h>
+#include <utmp.h>],
+[struct utmp ut;],
+rxvt_cv_struct_utmp=yes, rxvt_cv_struct_utmp=no)])
+if test x$rxvt_cv_struct_utmp = xyes; then
+  AC_DEFINE(HAVE_STRUCT_UTMP, 1, Define if utmp.h has struct utmp)
+fi
+]
+
+AC_CACHE_CHECK(for ut_host in utmp struct, rxvt_cv_struct_utmp_host,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmp.h>],
+[struct utmp ut; ut.ut_host;],
+rxvt_cv_struct_utmp_host=yes, rxvt_cv_struct_utmp_host=no)])
+if test x$rxvt_cv_struct_utmp_host = xyes; then
+  AC_DEFINE(HAVE_UTMP_HOST, 1, Define if struct utmp contains ut_host)
+fi
+
+AC_CACHE_CHECK(for ut_pid in utmp struct, rxvt_cv_struct_utmp_pid,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmp.h>],
+[struct utmp ut; ut.ut_pid;],
+rxvt_cv_struct_utmp_pid=yes, rxvt_cv_struct_utmp_pid=no)])
+if test x$rxvt_cv_struct_utmp_pid = xyes; then
+  AC_DEFINE(HAVE_UTMP_PID, 1, Define if struct utmp contains ut_pid)
+fi
+) dnl# AC_CHECK_HEADER(utmp.h
+
+dnl# --------------------------------------------
+
+AC_CHECK_HEADER(utmpx.h,
+[AC_CACHE_CHECK([for struct utmpx], rxvt_cv_struct_utmpx,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmpx.h>],
+[struct utmpx ut;],
+rxvt_cv_struct_utmpx=yes, rxvt_cv_struct_utmpx=no)])
+if test x$rxvt_cv_struct_utmpx = xyes; then
+  AC_DEFINE(HAVE_STRUCT_UTMPX, 1, Define if utmpx.h has struct utmpx)
+fi
+]
+
+AC_CACHE_CHECK(for host in utmpx struct, rxvt_cv_struct_utmpx_host,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmpx.h>],
+[struct utmpx utx; utx.ut_host;],
+rxvt_cv_struct_utmpx_host=yes, rxvt_cv_struct_utmpx_host=no)])
+if test x$rxvt_cv_struct_utmpx_host = xyes; then
+  AC_DEFINE(HAVE_UTMPX_HOST, 1, Define if struct utmpx contains ut_host)
+fi
+) dnl# AC_CHECK_HEADER(utmpx.h
+
+
+dnl# --------------------------------------------------------------------------
+dnl# check for struct lastlog
+AC_CACHE_CHECK(for struct lastlog, rxvt_cv_struct_lastlog,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_LASTLOG_H
+#include <lastlog.h>
+#endif
+],
+[struct lastlog ll;],
+rxvt_cv_struct_lastlog=yes, rxvt_cv_struct_lastlog=no)])
+if test x$rxvt_cv_struct_lastlog = xyes; then
+  AC_DEFINE(HAVE_STRUCT_LASTLOG, 1, Define if utmp.h or lastlog.h has struct lastlog)
+fi
+
+dnl# check for struct lastlogx
+AC_CACHE_CHECK(for struct lastlogx, rxvt_cv_struct_lastlogx,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmpx.h>
+#ifdef HAVE_LASTLOG_H
+#include <lastlog.h>
+#endif
+],
+[struct lastlogx ll;],
+rxvt_cv_struct_lastlogx=yes, rxvt_cv_struct_lastlogx=no)])
+if test x$rxvt_cv_struct_lastlogx = xyes; then
+  AC_DEFINE(HAVE_STRUCT_LASTLOGX, 1, Define if utmpx.h or lastlog.h has struct lastlogx)
+fi
+
+dnl# --------------------------------------------------------------------------
+dnl# FIND FILES
+dnl# --------------------------------------------------------------------------
+
+dnl# find utmp
+AC_CACHE_CHECK(where utmp is located, rxvt_cv_path_utmp,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+#include <utmp.h>
+#include <errno.h>
+main()
+{
+    char **u, *utmplist[] = {
+    "/var/run/utmp", "/var/adm/utmp", "/etc/utmp", "/usr/etc/utmp", "/usr/adm/utmp", NULL };
+    FILE *a, *f=fopen("conftestval", "w");
+    if (!f) exit(1);
+#ifdef UTMP_FILE
+    fprintf(f, "%s\n", UTMP_FILE);
+    exit(0);
+#endif
+#ifdef _PATH_UTMP
+    fprintf(f, "%s\n", _PATH_UTMP);
+    exit(0);
+#endif
+    for (u = utmplist; *u; u++) {
+       if ((a = fopen(*u, "r")) != NULL || errno == EACCES) {
+           fprintf(f, "%s\n", *u);
+           exit(0);
+       }
+    }
+    exit(0);
+}], rxvt_cv_path_utmp=`cat conftestval`, rxvt_cv_path_utmp=, dnl
+  AC_MSG_WARN([Define RXVT_UTMP_FILE in config.h manually]))])
+if test x$rxvt_cv_path_utmp != x; then
+  AC_DEFINE_UNQUOTED(RXVT_UTMP_FILE, "$rxvt_cv_path_utmp", Define location of utmp)
+fi
+
+dnl# --------------------------------------------------------------------------
+
+dnl# find utmpx - if a utmp file exists at the same location and is more than
+dnl# a day newer, then dump the utmpx.  People leave lots of junk around.
+AC_CACHE_CHECK(where utmpx is located, rxvt_cv_path_utmpx,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+#include <utmpx.h>
+#include <errno.h>
+#include <sys/stat.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+main()
+{
+    char **u, *p, *utmplist[] = {
+#ifdef UTMPX_FILE
+       UTMPX_FILE,
+#endif
+#ifdef _PATH_UTMPX
+       _PATH_UTMPX,
+#endif
+    "/var/adm/utmpx", "/etc/utmpx", NULL };
+    FILE *a, *f=fopen("conftestval", "w");
+    struct stat statu, statux;
+    if (!f) exit(1);
+    for (u = utmplist; *u; u++) {
+       if ((a = fopen(*u, "r")) != NULL || errno == EACCES) {
+           if (stat(*u, &statux) < 0)
+               continue;
+           p = strdup(*u);
+           p[strlen(p) - 1] = '\0';
+           if (stat(p, &statu) >= 0
+               && (statu.st_mtime - statux.st_mtime > 86400))
+               continue;
+           fprintf(f, "%s\n", *u);
+           exit(0);
+       }
+    }
+    exit(0);
+}], rxvt_cv_path_utmpx=`cat conftestval`, rxvt_cv_path_utmpx=, dnl
+  AC_MSG_WARN([Define RXVT_UTMPX_FILE in config.h manually]))])
+if test x$rxvt_cv_path_utmpx != x; then
+  AC_DEFINE_UNQUOTED(RXVT_UTMPX_FILE, "$rxvt_cv_path_utmpx", Define location of utmpx)
+fi
+
+dnl# --------------------------------------------------------------------------
+
+dnl# find wtmp
+AC_CACHE_CHECK(where wtmp is located, rxvt_cv_path_wtmp,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+#include <errno.h>
+main()
+{
+    char **w, *wtmplist[] = {
+    "/var/log/wtmp", "/var/adm/wtmp", "/etc/wtmp", "/usr/etc/wtmp", "/usr/adm/wtmp", NULL }; 
+    FILE *a, *f=fopen("conftestval", "w");
+    if (!f) exit(1);
+#ifdef WTMP_FILE
+    fprintf(f, "%s\n", WTMP_FILE);
+    exit(0);
+#endif
+#ifdef _PATH_WTMP
+    fprintf(f, "%s\n", _PATH_WTMP);
+    exit(0);
+#endif
+    for (w = wtmplist; *w; w++) {
+       if ((a = fopen(*w, "r")) != NULL || errno == EACCES) {
+           fprintf(f, "%s\n", *w);
+           exit(0);
+       }
+    }
+    exit(0);
+}], rxvt_cv_path_wtmp=`cat conftestval`, rxvt_cv_path_wtmp=, dnl
+  AC_MSG_WARN([Define RXVT_WTMP_FILE in config.h manually]))])
+if test x$rxvt_cv_path_wtmp != x; then
+  AC_DEFINE_UNQUOTED(RXVT_WTMP_FILE, "$rxvt_cv_path_wtmp", Define location of wtmp)
+fi
+dnl# --------------------------------------------------------------------------
+
+dnl# find wtmpx
+AC_CACHE_CHECK(where wtmpx is located, rxvt_cv_path_wtmpx,
+[AC_TRY_RUN([#include <stdio.h>
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+#include <errno.h>
+main()
+{
+    char **w, *wtmplist[] = {
+    "/var/log/wtmpx", "/var/adm/wtmpx", NULL }; 
+    FILE *a, *f=fopen("conftestval", "w");
+    if (!f) exit(1);
+#ifdef WTMPX_FILE
+    fprintf(f, "%s\n", WTMPX_FILE);
+    exit(0);
+#endif
+#ifdef _PATH_WTMPX
+    fprintf(f, "%s\n", _PATH_WTMPX);
+    exit(0);
+#endif
+    for (w = wtmplist; *w; w++) {
+       if ((a = fopen(*w, "r")) != NULL || errno == EACCES) {
+           fprintf(f, "%s\n", *w);
+           exit(0);
+       }
+    }
+    exit(0);
+}], rxvt_cv_path_wtmpx=`cat conftestval`, rxvt_cv_path_wtmpx=, dnl
+  AC_MSG_WARN([Define RXVT_WTMPX_FILE in config.h manually]))])
+if test x$rxvt_cv_path_wtmpx != x; then
+  AC_DEFINE_UNQUOTED(RXVT_WTMPX_FILE, "$rxvt_cv_path_wtmpx", Define location of wtmpx)
+fi
+dnl# --------------------------------------------------------------------------
+
+dnl# find lastlog
+AC_CACHE_CHECK(where lastlog is located, rxvt_cv_path_lastlog,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#elif defined(HAVE_UTMP_H)
+#include <utmp.h>
+#endif
+#ifdef HAVE_LASTLOG_H
+#include <lastlog.h>
+#endif
+#include <errno.h>
+main()
+{
+    char **w, *lastloglist[] = { "/var/log/lastlog", NULL };
+    FILE *a, *f=fopen("conftestval", "w");
+    if (!f) exit(1);
+#ifdef LASTLOG_FILE
+    fprintf(f, "%s\n", LASTLOG_FILE);
+    exit(0);
+#endif
+#ifdef _PATH_LASTLOG
+    fprintf(f, "%s\n", _PATH_LASTLOG);
+    exit(0);
+#endif
+    for (w = lastloglist; *w; w++) {
+       if ((a = fopen(*w, "r")) != NULL || errno == EACCES) {
+           fprintf(f, "%s\n", *w);
+           exit(0);
+       }
+    }
+    exit(0);
+}], rxvt_cv_path_lastlog=`cat conftestval`, rxvt_cv_path_lastlog=, dnl
+  AC_MSG_WARN([Define RXVT_LASTLOG_FILE in config.h manually]))])
+if test x$rxvt_cv_path_lastlog != x; then
+  AC_DEFINE_UNQUOTED(RXVT_LASTLOG_FILE, "$rxvt_cv_path_lastlog", Define location of lastlog)
+  if test -d "$rxvt_cv_path_lastlog"; then
+    AC_DEFINE(LASTLOG_IS_DIR, 1, Define if lastlog is provided via a directory)
+  fi
+fi
+dnl# --------------------------------------------------------------------------
+
+dnl# find lastlogx
+AC_CACHE_CHECK(where lastlogx is located, rxvt_cv_path_lastlogx,
+[AC_TRY_RUN([#include <stdio.h>
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+#include <errno.h>
+main()
+{
+    char **w, *wtmplist[] = { "/var/log/lastlogx", "/var/adm/lastlogx", NULL };
+    FILE *a, *f=fopen("conftestval", "w");
+    if (!f) exit(1);
+#ifdef LASTLOGX_FILE
+    fprintf(f, "%s\n", LASTLOGX_FILE);
+    exit(0);
+#endif
+#ifdef _PATH_LASTLOGX
+    fprintf(f, "%s\n", _PATH_LASTLOGX);
+    exit(0);
+#endif
+    for (w = wtmplist; *w; w++) {
+       if ((a = fopen(*w, "r")) != NULL || errno == EACCES) {
+           fprintf(f, "%s\n", *w);
+           exit(0);
+       }
+    }
+    exit(0);
+}], rxvt_cv_path_lastlogx=`cat conftestval`, rxvt_cv_path_lastlogx=, dnl
+  AC_MSG_WARN([Define RXVT_LASTLOGX_FILE in config.h manually]))])
+if test x$rxvt_cv_path_lastlogx != x; then
+  AC_DEFINE_UNQUOTED(RXVT_LASTLOGX_FILE, "$rxvt_cv_path_lastlogx", Define location of lastlogx)
+fi
+
+dnl# --------------------------------------------------------------------------
+
+dnl# find ttys/ttytab
+AC_CACHE_CHECK(where ttys/ttytab is located, rxvt_cv_path_ttytab,
+[for ttys_file in   dnl
+  /etc/ttys /etc/ttytab;
+do
+  if test -f "$ttys_file" ; then 
+    rxvt_cv_path_ttytab=$ttys_file
+    break
+  fi
+done
+])
+if test x$rxvt_cv_path_ttytab != x; then
+  AC_DEFINE_UNQUOTED(TTYTAB_FILENAME, "$rxvt_cv_path_ttytab", Define location of ttys/ttytab)
+fi
+
+dnl# --------------------------------------------------------------------------
+dnl# --------------------------------------------------------------------------
+
+dnl# this is a really hack test for some basic Xlocale stuff
+ac_save_LIBS=$LIBS
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="$CFLAGS $X_CFLAGS"
+LIBS="$LIBS $X_LIBS $X_EXTRA_LIBS -lX11"
+if test x$rxvt_cv_rpath = xyes -o x$rxvt_cv_R = xyes; then
+  LIBS=`echo $LIBS | sed "$R_TRANSLATE"`
+fi
+AC_CACHE_CHECK(for working Xlocale, rxvt_cv_func_xlocale,
+[AC_TRY_RUN([#include <X11/Xlib.h>
+main() {
+char *p;
+if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
+exit (XSupportsLocale() ? 0 : 1);
+else
+exit (1);}],  dnl
+  rxvt_cv_func_xlocale=yes, rxvt_cv_func_xlocale=no,  dnl
+  AC_MSG_WARN([Define NO_XLOCALE in config.h manually]))])
+if test x$rxvt_cv_func_xlocale = xyes; then
+  AC_DEFINE(HAVE_XLOCALE, 1, Define if Xlocale support works)
+fi
+
+AC_CACHE_CHECK(for working X setlocale, rxvt_cv_func_xsetlocale,
+[AC_TRY_LINK([#define X_LOCALE 1
+#include <X11/Xlocale.h>],
+  [setlocale(LC_CTYPE, "");],
+  rxvt_cv_func_xsetlocale=yes, rxvt_cv_func_xsetlocale=no)])
+if test x$rxvt_cv_func_xsetlocale = xyes; then
+  AC_DEFINE(HAVE_XSETLOCALE, 1, Define if setlocale (defined to Xsetlocale) works)
+fi
+LIBS=$ac_save_LIBS
+CFLAGS=$ac_save_CFLAGS
+
+AC_CACHE_CHECK(for working plain setlocale, rxvt_cv_func_setlocale,
+[AC_TRY_LINK([#include <locale.h>],
+  [setlocale(LC_CTYPE, "");],
+  rxvt_cv_func_setlocale=yes, rxvt_cv_func_setlocale=no)])
+if test x$rxvt_cv_func_setlocale = xyes; then
+  AC_DEFINE(HAVE_SETLOCALE, 1, Define if plain old setlocale works)
+fi
+
+AC_CACHE_CHECK(for working nl_langinfo, rxvt_cv_func_nl_langinfo,
+[AC_TRY_LINK([#include <langinfo.h>],
+  [nl_langinfo(CODESET);],
+  rxvt_cv_func_nl_langinfo=yes, rxvt_cv_func_nl_langinfo=no)])
+if test x$rxvt_cv_func_nl_langinfo = xyes; then
+  AC_DEFINE(HAVE_NL_LANGINFO, 1, Define if nl_langinfo(CODESET) works)
+fi
+
+AC_CACHE_CHECK(for getpt, rxvt_cv_func_getpt,
+[AC_TRY_LINK([#define _GNU_SOURCE
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif],
+  [(void)getpt();],
+  rxvt_cv_func_getpt=yes, rxvt_cv_func_getpt=no)])
+if test x$rxvt_cv_func_getpt = xyes; then
+  AC_DEFINE(HAVE_GETPT, 1, Define if you have _GNU_SOURCE getpt() )
+fi
+
+dnl# if we don't guess right then it's up to the user
+AC_CACHE_CHECK(for pty/tty type, rxvt_cv_ptys,
+[if test x$ac_cv_func_openpty = xyes; then
+    rxvt_cv_ptys=OPENPTY
+ else if test x$ac_cv_func__getpty = xyes; then
+    rxvt_cv_ptys=SGI4
+ else if test -c /dev/ttyp20; then
+    rxvt_cv_ptys=SCO
+ else if test -c /dev/ptym/clone; then
+    rxvt_cv_ptys=HPUX
+ else if test x$rxvt_cv_func_getpt = xyes; then
+    rxvt_cv_ptys=GLIBC
+ else if test -c /dev/ptc -a -c /dev/pts; then
+    rxvt_cv_ptys=PTC
+ else if test -c /dev/ptc -a -d /dev/pts; then
+    rxvt_cv_ptys=PTC
+ else if test -c /dev/ptmx -a -c /dev/pts/0; then
+    rxvt_cv_ptys=STREAMS
+ else if test x$ac_cv_func_grantpt = xyes && test x$ac_cv_func_unlockpt = xyes; then
+dnl# catch CYGWIN
+    rxvt_cv_ptys=STREAMS
+ else
+    rxvt_cv_ptys=BSD
+fi
+fi
+fi
+fi
+fi
+fi
+fi
+fi
+fi
+])
+
+if test x$rxvt_cv_ptys = xOPENPTY; then
+  AC_DEFINE(PTYS_ARE_OPENPTY, 1, Define for this pty type)
+fi
+if test x$rxvt_cv_ptys = xSCO; then
+  AC_DEFINE(PTYS_ARE_NUMERIC, 1, Define for this pty type)
+fi
+if test x$rxvt_cv_ptys = xSTREAMS; then
+  AC_DEFINE(PTYS_ARE_PTMX, 1, Define for this pty type)
+fi
+if test x$rxvt_cv_ptys = xPTC; then
+  AC_DEFINE(PTYS_ARE_PTC, 1, Define for this pty type)
+fi
+if test x$rxvt_cv_ptys = xSGI4; then
+  AC_DEFINE(PTYS_ARE__GETPTY, 1, Define for this pty type)
+fi
+if test x$rxvt_cv_ptys = xCONVEX; then
+  AC_DEFINE(PTYS_ARE_GETPTY, 1, Define for this pty type)
+fi
+if test x$rxvt_cv_ptys = xGLIBC; then
+  AC_DEFINE(PTYS_ARE_GETPT, 1, Define for this pty type)
+fi
+if test x$rxvt_cv_ptys = xHPUX; then
+  AC_DEFINE(PTYS_ARE_CLONE, 1, Define for this pty type)
+fi
+if test x$rxvt_cv_ptys = xBSD -o x$rxvt_cv_ptys = xHPUX -o x$rxvt_cv_ptys = xGLIBC; then
+  AC_DEFINE(PTYS_ARE_SEARCHED, 1, Define for this pty type)
+fi
+
+
+AC_CHECKING(for pty ranges)
+ptys=`echo /dev/pty??`
+pch1=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\).$/\1/g' | sort -u | tr -d '\012'`
+pch2=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\)$/\1/g' | sort -u | tr -d '\012'`
+if test x$pch1 != x; then
+  AC_DEFINE_UNQUOTED(PTYCHAR1, "$pch1", Define for first char in devptyXX)
+fi
+if test x$pch2 != x; then
+  AC_DEFINE_UNQUOTED(PTYCHAR2, "$pch2", Define for second char in devptyXX)
+fi
+
+dnl# FreeBSD needs to link libxpg4
+AC_CHECK_LIB(xpg4, setlocale, [LIBS="$LIBS -lxpg4"])
+
+dnl# --------------------------------------------------------------------------
+dnl# now add and remove other stuff
+dnl# --------------------------------------------------------------------------
+if test x$support_graphics = xyes; then
+  AC_DEFINE(RXVT_GRAPHICS, 1, Define if you want Rob Nation's own graphic mode)
+fi
+if test x$support_inheritpixmap = xyes; then
+  AC_DEFINE(TRANSPARENT, 1, Define if you want your background to use the parent window background)
+fi
+if test x$support_keepscrolling = xno; then
+  AC_DEFINE(NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING, 1, Define for continual scrolling when you keep the scrollbar button pressed)
+fi
+if test x$support_selectionscrolling = xyes; then
+  AC_DEFINE(SELECTION_SCROLLING, 1, Define to allow scrolling when the selection moves to the top or bottom of the screen)
+fi
+if test x$support_menubar = xyes; then
+  AC_DEFINE(MENUBAR, 1, Define if you want Menubar support)
+fi
+if test x$support_frills = xno; then
+  AC_DEFINE(NO_FRILLS, 1, Define if you don't want handling for rarely used features)
+fi
+if test x$support_linespace = xno; then
+  AC_DEFINE(NO_LINESPACE, 1, Define if you don't want support linespace)
+fi
+if test x$support_24bit = xyes; then
+  AC_DEFINE(PREFER_24BIT, 1, Define to use a 24 bit visual if the screen has 24 bit mode, even if the default is 8 bit)
+fi
+if test x$support_mousewheel = xyes; then
+  AC_DEFINE(MOUSE_WHEEL, 1, Define to use wheel events (button4 and button5) to scroll)
+fi
+if test x$support_mouseslipwheel = xyes; then
+  AC_DEFINE(MOUSE_SLIP_WHEELING, 1, Define to have CTRL cause wheel events to accelerate scrolling. Release CTRL to halt scrolling)
+fi
+if test x$support_oldselection = xno; then
+  AC_DEFINE(NO_OLD_SELECTION, 1, Define to remove old rxvt (ver 2.20 and before) style selection)
+fi
+if test x$support_utmp = xyes; then
+  AC_DEFINE(UTMP_SUPPORT, 1, Define if you want to have utmp/utmpx support)
+fi
+if test x$support_wtmp = xyes; then
+  AC_DEFINE(WTMP_SUPPORT, 1, Define if you want to have wtmp support when utmp/utmpx is enabled)
+fi
+if test x$support_lastlog = xyes; then
+  AC_DEFINE(LASTLOG_SUPPORT, 1, Define if you want to have lastlog support when utmp/utmpx is enabled)
+fi
+if test x$support_xim = xyes -o x$multichar_set = xyes; then
+  if test x$rxvt_cv_func_xlocale = xyes; then
+    AC_DEFINE(USE_XIM, 1, Define if you want to have XIM (X Input Method) protocol support - required for multibyte characters input)
+  fi
+fi
+if test x$support_xpm = xyes; then
+  AC_DEFINE(XPM_BACKGROUND, 1, Define if you want to have sexy-looking background pixmaps. Needs libXpm)
+fi
+if test x$support_scroll_rxvt = xyes; then
+  AC_DEFINE(RXVT_SCROLLBAR, 1, Support Rxvt original style scrollbars)
+  scrolltypes="rxvt"
+fi
+if test x$support_scroll_next = xyes; then
+  AC_DEFINE(NEXT_SCROLLBAR, 1, Support NeXT style scrollbars)
+  scrolltypes="$scrolltypes next"
+fi
+if test x$support_scroll_xterm = xyes; then
+  AC_DEFINE(XTERM_SCROLLBAR, 1, Support Xterm style scrollbars)
+  scrolltypes="$scrolltypes xterm"
+fi
+if test x$support_pointer_blank = xyes; then
+  AC_DEFINE(POINTER_BLANK, 1, Define if you want hide the pointer while typing)
+fi
+if test x$support_cursor_blink = xyes; then
+  AC_DEFINE(CURSOR_BLINK, 1, Define if you want blinking cursor support)
+fi
+if test x$support_unicode3 = xyes; then
+  AC_DEFINE(UNICODE_3, 1, Define if you want to represent unicode characters outside plane 0)
+fi
+if test x$codesets = xall; then
+  codesets=jp,jp-ext,kr,cn,cn-ext,vn
+fi
+for codeset in `echo $codesets | tr "[a-z,\\-]" "[A-Z _]"`; do
+  AC_DEFINE(ENCODING_EU, 1, Define if you want europeean extended codesets)
+  case "$codeset" in
+    VN     ) AC_DEFINE(ENCODING_VN,     1, Define if you want vietnamese codesets) ;;
+    JP     ) AC_DEFINE(ENCODING_JP,     1, Define if you want japanese codesets) ;;
+    JP_EXT ) AC_DEFINE(ENCODING_JP_EXT, 1, Define if you want extended japanese codesets) ;;
+    KR     ) AC_DEFINE(ENCODING_KR,     1, Define if you want korean codesets) ;;
+    CN     ) AC_DEFINE(ENCODING_CN,     1, Define if you want chinese codesets) ;;
+    CN_EXT ) AC_DEFINE(ENCODING_CN_EXT, 1, Define if you want extended chinese codesets) ;;
+  esac
+done
+
+dnl> AC_CHECK_FUNCS(gettimeofday putenv select socket)
+
+CFLAGS=${CFLAGS--O}
+LDFLAGS=${LDFLAGS--O}
+
+CPPFLAGS="$CPPFLAGS"
+AC_SUBST(DEBUG)
+AC_SUBST(DINCLUDE)
+AC_SUBST(CFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
+AC_SUBST(X_CFLAGS)
+
+dnl# Attack the libs
+if test x$rxvt_cv_rpath = xyes -o x$rxvt_cv_R = xyes; then
+  DLIB=`echo $DLIB | sed "$R_TRANSLATE"`
+  LIBS=`echo $LIBS | sed "$R_TRANSLATE"`
+  X_LIBS=`echo $X_LIBS | sed "$R_TRANSLATE"`
+  X_EXTRA_LIBS=`echo $X_EXTRA_LIBS | sed "$R_TRANSLATE"`
+  XPM_LIBS=`echo $XPM_LIBS | sed "$R_TRANSLATE"`
+fi
+AC_SUBST(DLIB)
+AC_SUBST(LIBS)
+AC_SUBST(X_LIBS)
+AC_SUBST(X_EXTRA_LIBS)
+
+if test x$support_addstrings = xno; then
+    AC_DEFINE(NO_STRINGS, 1, Define if you don't need to use our replacement string functions)
+fi
+
+dnl# common parts of the Makefile
+MCOMMON=./autoconf/Make.common
+AC_SUBST_FILE(MCOMMON)
+
+AC_ARG_PROGRAM
+
+RXVTNAME=`echo rxvt|sed "$program_transform_name"`
+AC_SUBST(RXVTNAME)
+
+dnl# test for "sun" or "__sun__" before include sys_ioctl
+
+dnl# revert HAVE_BLAH_H into a "#include <blah.h>"
+AC_DEFUN(RXVT_DEFINE_TO_INCLUDE, dnl
+[if test "$$3" = "$4" -o "$$5" = "$6"; then
+  $1="#include <$2>"
+else
+  $1="/* #include <$2> */"
+fi dnl
+AC_SUBST($1)])
+
+RXVT_DEFINE_TO_INCLUDE(include_stdint_h, stdint.h, ac_cv_header_stdint_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_stdarg_h, stdarg.h, ac_cv_header_stdarg_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_stdlib_h, stdlib.h, ac_cv_header_stdlib_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_unistd_h, unistd.h, ac_cv_header_unistd_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_string_h, string.h, ac_cv_header_string_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_fcntl_h, fcntl.h, ac_cv_header_fcntl_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_util_h, util.h, ac_cv_header_util_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_assert_h, assert.h, ac_cv_header_assert_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_sys_ioctl_h, sys/ioctl.h, rxvt_cv_header_sysioctl, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_sys_select_h, sys/select.h, ac_cv_header_sys_select_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_sys_strredir_h, sys/strredir.h, ac_cv_header_sys_strredir_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_sys_time_h, sys/time.h, ac_cv_header_sys_time_h, yes, notset, dontmatch)
+RXVT_DEFINE_TO_INCLUDE(include_time_h, time.h, ac_cv_header_sys_time_h, no, ac_cv_header_time, yes)
+
+if test x$support_xft = xyes; then
+  LIBS="$LIBS `pkg-config xft --libs`"
+  CFLAGS="$CFLAGS `pkg-config xft --cflags`"
+  CPPFLAGS="$CPPFLAGS `pkg-config xft --cflags`"
+
+  AC_CHECK_HEADERS(X11/Xft/Xft.h,,[support_xft=no])
+  AC_CHECK_LIB(Xft,XftDrawString32,,[support_xft=no])
+  AC_DEFINE(XFT, 1, Define to enable xft support)
+fi
+
+AC_OUTPUT(autoconf/Make.common \
+Makefile \
+doc/Makefile \
+src/Makefile \
+src/graphics/Makefile \
+src/test/Makefile \
+src/rxvtlib.h \
+W11/Makefile \
+)
+
+echo "Configuration:
+
+  Rxvt version:               $VERSION : $DATE
+  Source code location:       $srcdir
+  Install path:               ${prefix}/bin
+  Compiler:                   $CC
+  Compiler flags:             $CFLAGS"
+
+if test "$MALLOC_TYPE" = S; then
+  echo "  malloc support:             system default"
+fi
+if test "$MALLOC_TYPE" = G; then
+  echo "  malloc support:             Gray Watson's dmalloc"
+fi
+if test "$MALLOC_TYPE" = D; then
+  echo "  malloc support:             Doug Lea's malloc"
+fi
+
+if test x$support_xpm = xyes; then
+  echo "  Xpm library:                $XPM_LIBS"
+fi
+
+echo "
+The following are set in config.h
+"
+echo "  pty/tty type:               "$rxvt_cv_ptys
+if test x$support_utmp != xyes; then
+  echo "  utmp support:               disabled
+"
+else
+  echo "  utmp support:               enabled
+  utmp file:                  $rxvt_cv_path_utmp
+  utmpx file:                 $rxvt_cv_path_utmpx
+  wtmp file:                  $rxvt_cv_path_wtmp
+  wtmpx file:                 $rxvt_cv_path_wtmpx
+  lastlog file:               $rxvt_cv_path_lastlog
+  ttys/ttytab file:           $rxvt_cv_path_ttytab
+"
+fi
+if test x$term != x; then
+  echo "  set TERM to:                $term
+"
+fi
+if test x$terminfo != x; then
+  echo "  set TERMINFO to:            $terminfo
+"
+fi
+if test x$rxvt_cv_ptys = xUNKNOWN; then
+  echo ".----------------------------------------------------------------."
+  echo ". WARNING: could not determine pty/tty type.  Do not build until ."
+  echo ".          the appropriate PTYS_ARE_* is defined in config.h     ."
+  echo ".----------------------------------------------------------------."
+fi
+if test x$support_xpm = xneedsmanualspecification; then
+  echo ".----------------------------------------------------------------."
+  echo ". WARNING: --enable-xpm-background was specified however the     ."
+  echo ".          XPM includes files and libraries could not be found.  ."
+  echo ".          XPM backgrounds are now being DISABLED!  If you want  ."
+  echo ".          to use them you should rerun   configure   with the   ."
+  echo ".          appropriate --with-xpm-includes=/path/to/xpm/includes ."
+  echo ".          and --with-xpm-library=/path/to/xpm/library lines.    ."
+  echo ".----------------------------------------------------------------."
+fi
+if test x$support_xim = xyes -a x$rxvt_cv_func_xlocale = xno; then
+  echo ".----------------------------------------------------------------."
+  echo ". WARNING: --enable-xim was specified however the locale support ."
+  echo ".          functions could not be found.                         ."
+  echo ".          XIM is now being DISABLED!                            ."
+  echo ".----------------------------------------------------------------."
+fi
+echo "  *** Please check src/feature.h for further options ***
+"
diff --git a/autoconf/xpm.m4 b/autoconf/xpm.m4
new file mode 100644 (file)
index 0000000..3bb74cb
--- /dev/null
@@ -0,0 +1,232 @@
+dnl> $Id: xpm.m4,v 1.1 2003-11-24 17:28:08 pcg Exp $
+dnl> test to find the hard-to-find libXpm
+dnl> mostly copied from AC_PATH_X & AC_PATH_DIRECT, but explictly set
+
+AC_DEFUN(VT_FIND_LIBXPM,
+[
+AC_REQUIRE_CPP()
+
+# Initialize some more variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+
+# If we find XPM, set shell vars xpm_includes and xpm_libraries to the
+# paths, otherwise set no_xpm=yes.
+# Uses ac_ vars as temps to allow command line to override cache and checks.
+AC_MSG_CHECKING(for libXpm)
+
+AC_ARG_WITH(xpm_includes,
+  [  --with-xpm-includes=DIR use XPM includes in DIR],
+  xpm_includes="$withval", xpm_includes=NO)
+AC_ARG_WITH(xpm_library,
+  [  --with-xpm-library=DIR  use XPM library in DIR],
+  xpm_libraries="$withval", xpm_libraries=NO)
+
+# --without-xpm overrides everything else, but does not touch the cache.
+AC_ARG_WITH(xpm,
+  [  --with-xpm              use XPM])
+if test "$with_xpm" = no; then
+  have_xpm=disabled
+else
+  AC_CACHE_VAL(ac_cv_have_xpm, [
+  vt_xpm_include_X11=no
+  if test -n "$xpm_includes"; then
+    vt_xpm_includes=$xpm_includes
+  else
+    vt_xpm_includes=NO
+  fi
+  if test -n "$xpm_libraries"; then
+    vt_xpm_libraries=$xpm_libraries
+  else
+    vt_xpm_libraries=NO
+  fi
+
+  VT_XPM_DIRECT
+
+  if test "$vt_xpm_includes" = NO -o "$vt_xpm_libraries" = NO; then
+    ac_cv_have_xpm="have_xpm=no"
+  else
+    ac_cv_have_xpm="have_xpm=yes \
+        vt_xpm_includes=$vt_xpm_includes vt_xpm_libraries=$vt_xpm_libraries \
+       vt_xpm_include_X11=$vt_xpm_include_X11"
+  fi])dnl
+  eval "$ac_cv_have_xpm"
+fi
+
+if test "$have_xpm" != yes; then
+  AC_MSG_RESULT($have_xpm)
+  no_xpm=yes
+else
+  if test "$xpm_includes" != NO; then
+    if test "$xpm_includes" = "$vt_xpm_includes"; then
+      if test -r "$xpm_includes/X11/xpm.h"; then
+       vt_xpm_include_X11=yes
+      fi
+    else
+      vt_xpm_include_X11=no
+      if test -z "$xpm_includes"; then
+       AC_TRY_CPP([#include <X11/xpm.h>],
+       vt_xpm_include_X11=yes)
+      else
+        if test -r "$xpm_includes/X11/xpm.h"; then
+         vt_xpm_include_X11=yes
+        fi
+      fi
+    fi
+    vt_xpm_includes=$xpm_includes
+  fi
+  if test "x$xpm_libraries" != xNO; then
+    vt_xpm_libraries=$xpm_libraries
+  fi
+  # Update the cache value to reflect the command line values.
+  ac_cv_have_xpm="have_xpm=yes \
+       vt_xpm_includes=$vt_xpm_includes vt_xpm_libraries=$vt_xpm_libraries \
+       vt_xpm_include_X11=$vt_xpm_include_X11"
+  eval "$ac_cv_have_xpm"
+  AC_MSG_RESULT([-I$vt_xpm_includes, -L$vt_xpm_libraries])
+  if test -n "$vt_xpm_includes"; then
+    XPM_CPPFLAGS="-DHAVE_LIBXPM"
+  fi
+  if test -n "$vt_xpm_includes"; then
+    XPM_CFLAGS="-I$vt_xpm_includes"
+  fi
+  XPM_LIBS="-lXpm"
+  if test -n "$vt_xpm_libraries"; then
+    XPM_LIBS="-L$vt_xpm_libraries $XPM_LIBS"
+  fi
+  if test "x$vt_xpm_include_X11" = xyes; then
+    AC_DEFINE(XPM_INC_X11, 1, Define if you include <X11/xpm.h> on a normal include path (be careful))
+  fi
+fi
+
+AC_SUBST(XPM_CPPFLAGS)
+AC_SUBST(XPM_CFLAGS)
+AC_SUBST(XPM_LIBS)
+])
+
+dnl Internal subroutine of VT_FIND_LIBXPM
+dnl Set vt_xpm_include and vt_xpm_libr
+# -------------- find xpm.h and Xpm.a/Xpm.so/Xpm.sl
+AC_DEFUN(VT_XPM_DIRECT,
+[if test "$vt_xpm_includes" = NO; then
+  # Guess where to find xpm.h
+
+ac_save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+
+  # First, try using that file with no special directory specified.
+AC_TRY_CPP([#include <X11/xpm.h>],
+[# We can compile using X headers with no special include directory.
+vt_xpm_includes=
+vt_xpm_include_X11=yes],
+[CPPFLAGS="$ac_save_CPPFLAGS"
+# Look for the header file in a standard set of common directories.
+  for ac_dir in               \
+    /usr/X11/include          \
+    /usr/X11R6/include        \
+    /usr/X11R5/include        \
+    /usr/X11R4/include        \
+                              \
+    /usr/include/X11          \
+    /usr/include/X11R6        \
+    /usr/include/X11R5        \
+    /usr/include/X11R4        \
+                              \
+    /usr/local/X11/include    \
+    /usr/local/X11R6/include  \
+    /usr/local/X11R5/include  \
+    /usr/local/X11R4/include  \
+                              \
+    /usr/local/include/X11    \
+    /usr/local/include/X11R6  \
+    /usr/local/include/X11R5  \
+    /usr/local/include/X11R4  \
+                              \
+    /usr/X386/include         \
+    /usr/x386/include         \
+    /usr/XFree86/include/X11  \
+                              \
+    /usr/include              \
+    /usr/local/include        \
+    /usr/unsupported/include  \
+    /usr/athena/include       \
+    /usr/local/x11r5/include  \
+    /usr/lpp/Xamples/include  \
+                              \
+    /usr/openwin/include      \
+    /usr/openwin/share/include \
+    ; \
+  do
+    if test -r "$ac_dir/X11/xpm.h"; then
+      vt_xpm_includes="$ac_dir"
+      vt_xpm_include_X11=yes
+      break
+    else
+      if test -r "$ac_dir/xpm.h"; then
+        vt_xpm_includes=$ac_dir
+        break
+      fi
+    fi
+  done])
+fi
+
+if test "$vt_xpm_libraries" = NO; then
+  # Check for the libraries.
+
+  # See if we find them without any special options.
+  # Don't add to $LIBS permanently.
+  ac_save_LIBS="$LIBS"
+  LIBS="$LIBS $X_LIBS -lXpm -lX11"
+AC_TRY_LINK(, [XpmReadFileToPixmap()],
+[LIBS="$ac_save_LIBS"
+# We can link libXpm with no special library path.
+vt_xpm_libraries=],
+[LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+for ac_dir in \
+    `echo "$vt_xpm_includes" | sed 's,include/X11,lib,;s,include,lib,'` \
+    /usr/X11/lib          \
+    /usr/X11R6/lib        \
+    /usr/X11R5/lib        \
+    /usr/X11R4/lib        \
+                          \
+    /usr/lib/X11          \
+    /usr/lib/X11R6        \
+    /usr/lib/X11R5        \
+    /usr/lib/X11R4        \
+                          \
+    /usr/local/X11/lib    \
+    /usr/local/X11R6/lib  \
+    /usr/local/X11R5/lib  \
+    /usr/local/X11R4/lib  \
+                          \
+    /usr/local/lib/X11    \
+    /usr/local/lib/X11R6  \
+    /usr/local/lib/X11R5  \
+    /usr/local/lib/X11R4  \
+                          \
+    /usr/X386/lib         \
+    /usr/x386/lib         \
+    /usr/XFree86/lib/X11  \
+                          \
+    /usr/lib              \
+    /usr/local/lib        \
+    /usr/unsupported/lib  \
+    /usr/athena/lib       \
+    /usr/local/x11r5/lib  \
+    /usr/lpp/Xamples/lib  \
+                          \
+    /usr/openwin/lib      \
+    /usr/openwin/share/lib \
+    ; \
+do
+dnl XXX Shouldn't this really use AC_TRY_LINK to be portable & robust??
+  for ac_extension in a so sl; do
+    if test -r $ac_dir/libXpm.$ac_extension; then
+      vt_xpm_libraries=$ac_dir
+      break 2
+    fi
+  done
+done])
+fi
+])
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644 (file)
index 0000000..2652ded
--- /dev/null
@@ -0,0 +1,111 @@
+# doc/Makefile.in      -*- Makefile -*-
+# $Id: Makefile.in,v 1.1 2003-11-24 17:28:08 pcg Exp $
+@MCOMMON@
+
+srcdir =       @srcdir@
+VPATH =                @srcdir@
+.PATH:         @srcdir@
+
+basedir = ..
+thisdir = doc
+
+first_rule: all
+dummy:
+
+#
+# Distribution variables
+#
+
+YODL_RXVT = yodl/rxvt-colours.yo yodl/rxvt-environment.yo\
+           yodl/rxvt-files.yo yodl/rxvt-fonts.yo yodl/rxvt-login.yo\
+           yodl/rxvt-mousereporting.yo yodl/rxvt-options.yo\
+           yodl/rxvt-resources.yo yodl/rxvt-scrollbar.yo\
+           yodl/rxvt-textselection.yo
+YODL_RREF = yodl/rxvtRef-csi.yo yodl/rxvtRef-definitions.yo\
+           yodl/rxvtRef-graphics.yo yodl/rxvtRef-keycodes.yo\
+           yodl/rxvtRef-menubar.yo yodl/rxvtRef-mouse.yo\
+           yodl/rxvtRef-privatemodes.yo yodl/rxvtRef-sequences.yo\
+           yodl/rxvtRef-values.yo yodl/rxvtRef-xpm.yo yodl/rxvtRef-xterm.yo
+
+DIST_ETC  = etc/rxvt.termcap etc/rxvt.terminfo etc/XTerm.ad
+DIST_YODL = yodl/masonyodl.yo yodl/versioninfo.yo yodl/versioninfo.yo.in\
+           $(YODL_RXVT) yodl/rxvt.yo $(YODL_RREF) yodl/rxvtRef.yo
+DIST_MENU = menu/menu menu/example.menu menu/rxvt.menu menu/rxvt.zh-menu\
+           menu/terminal.menu menu/jedmenu.sl
+DIST     = Makefile.in README.greek README.menu README.xvt BUGS FAQ TODO\
+           changes.txt xterm.seq LSM.in rxvt.1 rxvt.tbl rxvtRef.txt\
+           rxvtRef.html rxvtRef-frame.html rxvtRef-toc.html rxvt.html 
+
+#-------------------------------------------------------------------------
+
+all:   rxvt.1
+
+rxvt.1: rxvt.tbl Makefile
+       @if test x$(TBL) = x; then : ; else echo "$(TBL) $(srcdir)/rxvt.tbl | grep -v '^.lf' > rxvt.1"; $(TBL) $(srcdir)/rxvt.tbl | grep -v '^.lf' > rxvt.1 ; fi
+
+SEDREPLACE = -e 's%@RXVT_VERSION@%$(VERSION)%g;'\
+            -e 's%@RXVT_LSMDATE@%$(LSMDATE)%g;'\
+            -e 's%@RXVT_DATE@%$(DATE)%g;'\
+            -e 's%@RXVT_MAINTEMAIL@%$(MAINTEMAIL)%g;'\
+            -e 's%@RXVT_MAINT@%$(MAINT)%g;'\
+            -e 's%@RXVT_WEBPAGE@%$(WEBPAGE)%g;'\
+            -e 's%@RXVT_WEBMAINTEMAIL@%$(WEBMAINTEMAIL)%g;'\
+            -e 's%@RXVT_WEBMAINT@%$(WEBMAINT)%g;'\
+            -e 's%@RXVT_FTPSITENAME@%$(FTPSITENAME)%g;'\
+            -e 's%@RXVT_FTPSITEDIR@%$(FTPSITEDIR)%g;'
+
+tags allbin:
+
+alldoc:        $(basedir)/$(VERNAME).lsm yodl/versioninfo.yo rxvt.1 rxvt.html rxvtRef.html rxvtRef.txt
+
+yodl/versioninfo.yo: yodl/versioninfo.yo.in ../src/version.h
+       $(SED) $(SEDREPLACE) < $(srcdir)/yodl/versioninfo.yo.in > $@
+
+$(basedir)/$(VERNAME).lsm: LSM.in $(srcdir)/../autoconf/Make.common.in $(srcdir)/../src/version.h
+       $(SED) $(SEDREPLACE) < $(srcdir)/LSM.in > $@
+
+rxvt.tbl: yodl/rxvt.yo $(YODL_RXVT) yodl/masonyodl.yo
+       (cd $(srcdir)/yodl; yodl2man -o../rxvt.tbl rxvt.yo)
+
+rxvt.html: yodl/rxvt.yo $(YODL_RXVT) yodl/masonyodl.yo
+       (cd $(srcdir)/yodl; yodl2html -o../rxvt.html rxvt.yo)
+
+rxvtRef.html: $(YODL_RREF) yodl/rxvtRef.yo yodl/masonyodl.yo
+       (cd $(srcdir)/yodl; yodl2html -o../rxvtRef.html rxvtRef.yo)
+
+rxvtRef.txt: $(YODL_RREF) yodl/rxvtRef.yo yodl/masonyodl.yo
+       (cd $(srcdir)/yodl; yodl2txt -o../rxvtRef.txt rxvtRef.yo)
+
+clean:
+       $(RMF) rxvt.man *~ yodl/*~
+
+realclean: clean
+       $(RMF) tags rxvt.1 rxvt.html rxvtRef.html rxvtRef.txt
+
+cleandir: realclean
+
+distclean:
+
+install:
+       $(INSTALL_DATA) rxvt.1 $(DESTDIR)$(mandir)/$(RXVTNAME).$(manext)
+
+uninstall:
+       -(cd $(mandir); $(RMF) $(RXVTNAME).$(manext) )
+
+distdirs:
+       mkdir $(basedir)/../$(VERNAME)/$(thisdir)
+       mkdir $(basedir)/../$(VERNAME)/$(thisdir)/etc
+       mkdir $(basedir)/../$(VERNAME)/$(thisdir)/menu
+       mkdir $(basedir)/../$(VERNAME)/$(thisdir)/yodl
+
+distcopy: realclean distdepend
+       $(CP) -p $(basedir)/$(VERNAME).lsm $(basedir)/../$(VERNAME);
+       $(CP) -p $(DIST)      $(basedir)/../$(VERNAME)/$(thisdir)
+       $(CP) -p $(DIST_ETC)  $(basedir)/../$(VERNAME)/$(thisdir)/etc
+       $(CP) -p $(DIST_MENU) $(basedir)/../$(VERNAME)/$(thisdir)/menu
+       $(CP) -p $(DIST_YODL) $(basedir)/../$(VERNAME)/$(thisdir)/yodl
+
+distdepend: alldoc
+
+# ------------------------------------------------------------------------
+# DO NOT DELETE: ugly dependency list follows
diff --git a/doc/yodl/masonyodl.yo b/doc/yodl/masonyodl.yo
new file mode 100644 (file)
index 0000000..38d1cc6
--- /dev/null
@@ -0,0 +1,125 @@
+COMMENT(-- $Id: masonyodl.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(-----------------------------------------------------------------------
+-- We want more functionality and some better layout
+-- proto changes:
+--     starttable(nColumns)(Alignment)(borderwidth)
+------------------------------------------------------------------------------)
+NEWCOUNTER(RRindentlevel)
+NEWCOUNTER(RRnl)
+SETCOUNTER(RRindentlevel)(0)
+\
+DEFINEMACRO(nltxt)(0)(\
+    IFZERO(RRnl)()( ADDTOCOUNTER(RRnl)(-1)nltxt()))
+\
+UNDEFINEMACRO(XXnl)
+DEFINEMACRO(XXnl)(0)(\
+    NOTRANS(
+)\
+    whentxt(SETCOUNTER(RRnl)(RRindentlevel)nltxt()))
+\
+DEFINEMACRO(P)(0)(\
+    SETCOUNTER(RRnl)(0)\
+    whenhtml(SETCOUNTER(RRnl)(1)htmlcommand(<p>))\
+    IFZERO(RRnl)(nl())())
+\
+UNDEFINEMACRO(starttable)
+DEFINEMACRO(starttable)(3)(\
+    SETCOUNTER(XXtablewidth)(ARG1)\
+    whenhtml(IFZERO(ARG3)(htmlcommand(<table>))\
+                        (htmlcommand(<table border=ARG3>))XXnl())\
+    whenlatex(latexcommand(\begin{tabular}{)ARG2+latexcommand(}))\
+    whenman(roffcmd(.TS)()()())\
+    whenman(IFZERO(ARG3)(roffcmd(tab(`);)()()())\
+                       (roffcmd(allbox,tab(`);)()()()))\
+    whenman(ARG2 NOTRANS(.
+))\
+    whenms(roffcmd(.TS)()()())\
+    whenms(IFZERO(ARG3)(roffcmd(tab(`);)()()())\
+                      (roffcmd(allbox,tab(`);)()()()))\
+    whenms(ARG2+mscommand(.))\
+    SETCOUNTER(XXtablewidth)(ARG1)\
+    SETCOUNTER(XXparcounter)(0))
+COMMENT(        For HTML, we'll need <table>, for
+        LaTeX we'll need \begin{tabular}{alignment}. Also, we don't want
+        paragraph delimiters.)
+\
+UNDEFINEMACRO(cell)
+DEFINEMACRO(cell)(1)(\
+    ADDTOCOUNTER(XXtableline)(1)\
+    whenhtml(htmlcommand(<td>) ARG1 \
+             IFZERO(XXcellcounter)\
+                (htmlcommand(<br>))\
+                ()\
+             htmlcommand(</td>) XXnl())\
+    whenlatex(ARG1 \
+              IFZERO(XXcellcounter)\
+                ()(latexcommand( & )))\
+    whentxt( ARG1 )\
+    whenms( ARG1 )\
+             IFZERO(XXcellcounter)\
+                ()\
+                (mscommand(`\))\
+    whenman( ARG1 )\
+             IFZERO(XXcellcounter)\
+                ()\
+                (mancommand(`\))\
+    ADDTOCOUNTER(XXcellcounter)(-1))
+COMMENT(For HTML we need:
+<td> text </td>, so that's fairly easy. If we're already at the last
+cell, we need <td> text <br></td>.
+For LaTeX: we need text followed by &, unless
+        we're already at the last cell 'cuz in that case we need only text.
+        Also we need to decrement the cell counter..)
+\
+UNDEFINEMACRO(cells)
+DEFINEMACRO(cells)(2)(\
+    ADDTOCOUNTER(XXtableline)(ARG1)\
+    ADDTOCOUNTER(XXcellcounter)(-ARG1)\
+    ADDTOCOUNTER(XXcellcounter)(1)\
+    whenhtml(htmlcommand(<td colspan=ARG1 align=center>) ARG2 \
+             IFZERO(XXcellcounter)\
+                (htmlcommand(<br>))\
+                ()\
+             htmlcommand(</td>) XXnl())\
+    whenlatex(\
+    latexcommand(\multicolumn{)ARG1+latexcommand(}{c}{)ARG2+latexcommand(})\
+              IFZERO(XXcellcounter)\
+                ()(latexcommand( & )))\
+    whentxt( ARG1 )\
+    whenms( ARG1 )\
+             IFZERO(XXcellcounter)\
+                ()\
+                (mscommand(`\))\
+    whenman( ARG1 )\
+             IFZERO(XXcellcounter)\
+                ()\
+                (mancommand(`\))\
+    ADDTOCOUNTER(XXcellcounter)(-1))
+\
+DEFINEMACRO(indent)(1)(\
+    whenhtml(htmlcommand(<ul>)ARG1+htmlcommand(</ul>))\
+    whentxt(ADDTOCOUNTER(RRindentlevel)(4)ARG1+ADDTOCOUNTER(RRindentlevel)(-4))\
+    whenman(roffcmd(.RS)()()()roffcmd(.HP)()()()ARG1+roffcmd(.RE)()()())\
+    whenms())
+\
+DEFINEMACRO(startdl)(0)(\
+    whenhtml(htmlcommand(<dl>))\
+    whentxt(ADDTOCOUNTER(RRindentlevel)(4))\
+    whenman(startdit()))
+\
+DEFINEMACRO(enddl)(0)(\
+    whenhtml(htmlcommand(</dl>))\
+    whentxt(ADDTOCOUNTER(RRindentlevel)(-4))\
+    whenman(enddit()))
+\
+DEFINEMACRO(dl)(2)(\
+    whenhtml(htmlcommand(<dt>)ARG1+htmlcommand(</dt><dd>)\
+            ARG2+htmlcommand(</dd>))\
+    whentxt(ADDTOCOUNTER(RRindentlevel)(2)dit(ARG1)\
+           ADDTOCOUNTER(RRindentlevel)(2)nl()\
+           ARG2+ADDTOCOUNTER(RRindentlevel)(-4))\
+    whenman(dit(ARG1)ARG2))
+\
+DEFINEMACRO(manpageauthors)(0)(\
+    manpagesection(AUTHORS)\
+    DEFINESYMBOL(XXmanpageAuthor))
diff --git a/doc/yodl/rxvt-colours.yo b/doc/yodl/rxvt-colours.yo
new file mode 100644 (file)
index 0000000..8952041
--- /dev/null
@@ -0,0 +1,50 @@
+COMMENT(-- $Id: rxvt-colours.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(COLORS AND GRAPHICS)
+
+If graphics support was enabled at compile-time, bf(rxvt) can be queried
+with ANSI escape sequences and can address individual pixels instead of
+text characters.  Note the graphics support is still considered beta code.
+
+In addition to the default foreground and background colours, bf(rxvt)
+can display up to 16 colours (8 ANSI colours plus high-intensity bold/blink
+versions of the same).
+Here is a list of the colours with their bf(rgb.txt) names.
+
+starttable(3)(l l l)(0)\
+    row(cell(bf(color0))cell((black))cell(= Black))\
+    row(cell(bf(color1))cell((red))cell(= Red3))\
+    row(cell(bf(color2))cell((green))cell(= Green3))\
+    row(cell(bf(color3))cell((yellow))cell(= Yellow3))\
+    row(cell(bf(color4))cell((blue))cell(= Blue3))\
+    row(cell(bf(color5))cell((magenta))cell(= Magenta3))\
+    row(cell(bf(color6))cell((cyan))cell(= Cyan3))\
+    row(cell(bf(color7))cell((white))cell(= AntiqueWhite))\
+    row(cell(bf(color8))cell((bright black))cell(= Grey25))\
+    row(cell(bf(color9))cell((bright red))cell(= Red))\
+    row(cell(bf(color10))cell((bright green))cell(= Green))\
+    row(cell(bf(color11))cell((bright yellow))cell(= Yellow))\
+    row(cell(bf(color12))cell((bright blue))cell(= Blue))\
+    row(cell(bf(color13))cell((bright magenta))cell(= Magenta))\
+    row(cell(bf(color14))cell((bright cyan))cell(= Cyan))\
+    row(cell(bf(color15))cell((bright white))cell(= White))\
+    row(cell(bf(foreground))cell()cell(= Black))\
+    row(cell(bf(background))cell()cell(= White))\
+endtable()
+
+It is also possible to specify the colour values of bf(foreground),
+bf(background), bf(cursorColor), bf(cursorColor2), bf(colorBD), bf(colorUL)
+as a number 0-15, as a convenient shorthand to reference the colour name of
+color0-color15.
+
+Note that bf(-rv) (bf("reverseVideo: True")) simulates reverse video by
+always swapping the foreground/background colours.  This is in contrast to
+em(xterm)(1) where the colours are only swapped if they have not otherwise been
+specified.
+For example,
+
+startdit()
+   dit(bf(rxvt -fg Black -bg White -rv))
+       would yield White on Black, while on em(xterm)(1) it would yield
+       Black on White.
+enddit()
diff --git a/doc/yodl/rxvt-environment.yo b/doc/yodl/rxvt-environment.yo
new file mode 100644 (file)
index 0000000..b5b6a7c
--- /dev/null
@@ -0,0 +1,9 @@
+COMMENT(-- $Id: rxvt-environment.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(ENVIRONMENT)
+
+bf(rxvt) sets the environment variables bf(TERM), bf(COLORTERM) and
+bf(COLORFGBG).  The environment variable bf(WINDOWID) is set to the X window
+id number of the bf(rxvt) window and it also uses and sets the environment
+variable bf(DISPLAY) to specify which display terminal to use.  bf(rxvt) uses
+the environment variables bf(RXVTPATH) and bf(PATH) to find XPM files.
diff --git a/doc/yodl/rxvt-files.yo b/doc/yodl/rxvt-files.yo
new file mode 100644 (file)
index 0000000..d0f0102
--- /dev/null
@@ -0,0 +1,8 @@
+COMMENT(-- $Id: rxvt-files.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(FILES)
+
+startdit()
+    dit(bf(/etc/utmp)) System file for login records.
+    dit(bf(/usr/lib/X11/rgb.txt)) Color names.
+enddit()
diff --git a/doc/yodl/rxvt-fonts.yo b/doc/yodl/rxvt-fonts.yo
new file mode 100644 (file)
index 0000000..c5b8f87
--- /dev/null
@@ -0,0 +1,9 @@
+COMMENT(-- $Id: rxvt-fonts.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(CHANGING FONTS)
+
+You can change fonts on-the-fly, which is to say cycle through the default
+font and others of various sizes, by using bf(Shift-KP_Add) and
+bf(Shift-KP_Subtract).  Or, alternatively (if enabled) with
+bf(HOTKEY()-BIGFONT()) and bf(HOTKEY()-SMALLFONT()), where the actual key
+can be selected using resources bf(smallfont_key)/bf(bigfont_key).
diff --git a/doc/yodl/rxvt-login.yo b/doc/yodl/rxvt-login.yo
new file mode 100644 (file)
index 0000000..6868097
--- /dev/null
@@ -0,0 +1,7 @@
+COMMENT(-- $Id: rxvt-login.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(LOGIN STAMP)
+
+bf(rxvt) tries to write an entry into the em(utmp)(5) file so that it can be
+seen via the em(who(1)) command, and can accept messages.  To allow this
+feature, bf(rxvt) must be installed setuid root on some systems.
diff --git a/doc/yodl/rxvt-mousereporting.yo b/doc/yodl/rxvt-mousereporting.yo
new file mode 100644 (file)
index 0000000..7dd2a6b
--- /dev/null
@@ -0,0 +1,14 @@
+COMMENT(-- $Id: rxvt-mousereporting.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(MOUSE REPORTING)
+
+To temporarily override mouse reporting, for either the scrollbar or the
+normal text selection/insertion, hold either the Shift or the Meta (Alt) key
+while performing the desired mouse action.
+
+If mouse reporting mode is active, the normal scrollbar actions are disabled
+-- on the assumption that we are using a fullscreen application.
+Instead, pressing Button1 and Button3 sends
+bf(ESC[6~) (Next) and bf(ESC[5~) (Prior), respectively.
+Similarly, clicking on the up and down arrows sends bf(ESC[A) (Up) and
+bf(ESC[B) (Down), respectively.
diff --git a/doc/yodl/rxvt-options.yo b/doc/yodl/rxvt-options.yo
new file mode 100644 (file)
index 0000000..e7f7f40
--- /dev/null
@@ -0,0 +1,191 @@
+COMMENT(-- $Id: rxvt-options.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpageoptions()
+
+The bf(rxvt) options (mostly a subset of em(xterm)'s) are listed below.
+In keeping with the smaller-is-better philosophy, options may be eliminated
+or default values chosen at compile-time, so options and defaults listed
+may not accurately reflect the version installed on your system.  
+`rxvt -h' gives a list of major compile-time options on the em(Options) line.
+Option descriptions may be prefixed with which compile option each is
+dependent upon.  e.g. `Compile em(XIM):' requires em(XIM) on the em(Options)
+line.  Note: `rxvt -help' gives a list of all command-line options compiled
+into your version.
+
+Note that bf(rxvt) permits the resource name to be used as a long-option
+(--/++ option) so the potential command-line options are far greater than
+those listed.
+For example: `rxvt --loginShell --color1 Orange'.
+
+Also note that if you do not explictly specify a font (bf(-fn) and bf(-fm))
+or a multichar encoding method (bf(-km)), rxvt will select a font for the
+preferable encoding according to your locale.  Supported encodings are:
+bf(ISO-8859-)n (n=bf(1)...bf(15)), bf(KOI8-R), bf(KOI8-U), bf(EUC-JP),
+bf(Shift_JIS), bf(EUC-KR), bf(EUC-CN) (aka bf(GB)), and bf(Big5).
+
+The following options are available:
+
+startdit()
+    dit(bf(-help), bf(--help))
+       Print out a message describing available options.
+    dit(bf(-display) em(displayname))
+       Attempt to open a window on the named X display (bf(-d) still
+       respected).  In the absence of this option, the display specified
+       by the bf(DISPLAY) environment variable is used.
+    dit(bf(-geometry) em(geom))
+       Window geometry (bf(-g) still respected);
+        resource bf(geometry).
+    dit(bf(-rv)|bf(+rv))
+       Turn on/off simulated reverse video;
+        resource bf(reverseVideo).
+    dit(bf(-j)|bf(+j))
+       Turn on/off jump scrolling;
+        resource bf(jumpScroll).
+    dit(bf(-ip)|bf(+ip))
+       Turn on/off inheriting parent window's pixmap.  Alternative form
+       is bf(-tr);
+       resource bf(inheritPixmap).
+    dit(bf(-bg) em(colour))
+       Window background colour;
+        resource bf(background).
+    dit(bf(-fg) em(colour))
+       Window foreground colour;
+       resource bf(foreground).
+    dit(bf(-pixmap:) em(file[;geom]))
+       Compile em(XPM): Specify XPM file for the background and also
+       optionally specify its scaling with a geometry string.  Note you
+       may need to add quotes to avoid special shell interpretation of
+       the `;' in the command-line;
+       resource bf(backgroundPixmap).
+    dit(bf(-cr) em(colour))
+       The cursor colour;
+       resource bf(cursorColor).
+    dit(bf(-pr) em(colour))
+       The mouse pointer colour;
+       resource bf(pointerColor).
+    dit(bf(-bd) em(colour))
+       The colour of the border between the xterm scrollbar and the text;
+       resource bf(borderColor).
+    dit(bf(-fn) em(fontname))
+       Main normal text font;
+       resource bf(font).
+    dit(bf(-fb) em(fontname))
+       Main bold text font;
+       resource bf(boldFont).
+    dit(bf(-fm) em(fontname))
+       Main multicharacter font;
+       resource bf(mfont).
+    dit(bf(-km) em(mode))
+       Compile em(multichar_languages): 
+       Multiple-character font-set encoding mode;
+       bf(eucj): EUC Japanese encoding.
+       bf(sjis): Shift JIS encoding.
+       bf(big5): BIG5 encoding.
+       bf(gb): GB encoding.
+       bf(kr): EUC Korean encoding.
+       bf(noenc): no encoding;
+       resource bf(multichar_encoding).
+    dit(bf(-grk) em(mode))
+       Compile em(Greek): Greek keyboard translation;
+       bf(iso): ISO-8859 mapping.
+       bf(ibm): IBM-437 mapping;
+       resource bf(greek_keyboard).
+    dit(bf(-name) em(name))
+       Specify the application name under which resources
+       are to be obtained, rather than the default executable file name.
+       Name should not contain `.' or `*' characters.
+       Also sets the icon and title name.
+    dit(bf(-ls)|bf(+ls))
+       Start as a login-shell/sub-shell;
+       resource bf(loginShell).
+    dit(bf(-ut)|bf(+ut))
+       Compile em(utmp): Inhibit/enable writing a utmp entry;
+       resource bf(utmpInhibit).
+    dit(bf(-vb)|bf(+vb))
+       Turn on/off visual bell on receipt of a bell character;
+       resource bf(visualBell).
+    dit(bf(-sb)|bf(+sb))
+       Turn on/off scrollbar;
+       resource bf(scrollBar).
+    dit(bf(-si)|bf(+si))
+       Turn on/off scroll-to-bottom on TTY output inhibit;
+       resource bf(scrollTtyOutput) has opposite effect.
+    dit(bf(-sk)|bf(+sk))
+       Turn on/off scroll-to-bottom on keypress;
+       resource bf(scrollTtyKeypress).
+    dit(bf(-sw)|bf(+sw))
+       Turn on/off scrolling with the scrollback buffer as new
+       lines appear.  This only takes effect if bf(-si) is also given;
+       resource bf(scrollWithBuffer).
+    dit(bf(-sr)|bf(+sr)) 
+       Put scrollbar on right/left;
+       resource bf(scrollBar_right).
+    dit(bf(-st)|bf(+st)) 
+       Display normal (non XTerm/NeXT) scrollbar without/with a trough;
+       resource bf(scrollBar_floating).
+    dit(bf(-mcc)|bf(+mcc))
+       Compile em(multichar_languages): treat multibyte glyphs as single
+       character for backspace, delete and cursor movement keys;
+       resource bf(multibyte_cursor).
+    dit(bf(-bc)|bf(+bc))
+       Blink the cursor; resource bf(cursorBlink).
+    dit(bf(-iconic)) 
+       Start iconified, if the window manager supports that option.
+       Alternative form is bf(-ic).
+    dit(bf(-sl) em(number))
+       Save em(number) lines in the scrollback buffer.  See resource entry
+       for limits; 
+       resource bf(saveLines).
+    dit(bf(-b) em(number))
+       Compile em(frills): Internal border of em(number) pixels.  See
+       resource entry for limits;
+       resource bf(internalBorder).
+    dit(bf(-w) em(number))
+       Compile em(frills): External border of em(number) pixels. 
+       Also, bf(-bw) and bf(-borderwidth).  See resource entry for limits;
+       resource bf(externalBorder).
+    dit(bf(-lsp) em(number))
+       Compile em(linespace): Lines (pixel height) to insert between each
+       row of the display;
+       resource bf(linespace).
+    dit(bf(-tn) em(termname)) 
+       This option specifies the name of the terminal type to be set in the
+       bf(TERM) environment variable. This terminal type must exist in the
+       em(termcap(5)) database and should have em(li#) and em(co#) entries;
+       resource bf(termName).
+    dit(bf(-e) em(command [arguments]))
+       Run the command with its command-line arguments in the bf(rxvt)
+       window; also sets the window title and icon name to be the basename
+       of the program being executed if neither em(-title) (em(-T)) nor
+       em(-n) are given on the command line.  If this option is used, it
+       must be the last on the command-line.  If there is no bf(-e) option
+       then the default is to run the program specified by the bf(SHELL)
+       environment variable or, failing that, em(sh(1)).
+    dit(bf(-title) em(text))
+       Window title (bf(-T) still respected); the default title is the
+       basename of the program specified after the bf(-e) option, if
+       any, otherwise the application name;
+       resource bf(title).
+    dit(bf(-n) em(text))
+       Icon name; the default name is the basename of the program specified
+       after the bf(-e) option, if any, otherwise the application name;
+       resource bf(iconName).
+    dit(bf(-C))
+       Capture system console messages.
+    dit(bf(-pt) em(style))
+       Compile em(XIM): input style for input method;
+       bf(OverTheSpot), bf(OffTheSpot), bf(Root);
+       resource bf(preeditType).
+    dit(bf(-im) em(text))
+       Compile em(XIM): input method name.
+       resource bf(inputMethod).
+    dit(bf(-mod) em(modifier))
+       Override detection of Meta modifier with specified key:
+       bf(alt), bf(meta), bf(hyper), bf(super), bf(mod1), bf(mod2), bf(mod3),
+       bf(mod4), bf(mod5);
+       resource em(modifier).
+    dit(bf(-xrm) em(resourcestring))
+       No effect on rxvt.  Simply passes through an argument to be made
+       available in the instance's argument list.  Appears in em(WM_COMMAND)
+       in some window managers.
+enddit()
diff --git a/doc/yodl/rxvt-resources.yo b/doc/yodl/rxvt-resources.yo
new file mode 100644 (file)
index 0000000..676f1c0
--- /dev/null
@@ -0,0 +1,303 @@
+COMMENT(-- $Id: rxvt-resources.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(RESOURCES (available also as long-options))
+
+Note: `rxvt --help' gives a list of all resources (long options) compiled
+into your version.
+If compiled with internal Xresources support (i.e. bf(rxvt -h) lists 
+bf(.Xdefaults)) then bf(rxvt) accepts application defaults set in
+XAPPLOADDIR/Rxvt (compile-time defined: usually
+bf(/usr/lib/X11/app-defaults/Rxvt)) and resources set in bf(~/.Xdefaults),
+or bf(~/.Xresources) if bf(~/.Xdefaults) does not exist.  Note that when
+reading X resources, bf(rxvt) recognizes two class names: bf(XTerm) and
+bf(Rxvt).  The class name bf(XTerm) allows resources common to both
+bf(rxvt) and em(xterm) to be easily configured, while the class name
+bf(Rxvt) allows resources unique to bf(rxvt), notably colours and
+key-handling, to be shared between different bf(rxvt) configurations. 
+If no resources are specified, suitable defaults will be used. 
+Command-line arguments can be used to override resource settings.  The
+following resources are allowed:
+
+startdit()
+    dit(bf(geometry:) em(geom))
+       Create the window with the specified X window geometry [default
+       80x24];
+       option bf(-geometry).
+    dit(bf(background:) em(colour))
+       Use the specified colour as the window's background colour [default
+       White];
+       option bf(-bg).
+    dit(bf(foreground:) em(colour))
+       Use the specified colour as the window's foreground colour [default
+       Black];
+       option bf(-fg).
+    dit(bf(color)em(n)bf(:) em(colour))
+       Use the specified colour for the colour value em(n), where 0-7
+       corresponds to low-intensity (normal) colours and 8-15 corresponds to
+       high-intensity (bold = bright foreground, blink = bright
+       background) colours.  The canonical names are as follows:
+       0=black, 1=red, 2=green, 3=yellow, 4=blue, 5=magenta, 6=cyan, 7=white,
+       but the actual colour names used are listed in the
+       bf(COLORS AND GRAPHICS) section.
+    dit(bf(colorBD:) em(colour))
+       Use the specified colour to display bold characters when the
+       foreground colour is the default.
+    dit(bf(colorUL:) em(colour))
+       Use the specified colour to display underlined characters when the
+       foreground colour is the default.
+    dit(bf(colorRV:) em(colour))
+       Use the specified colour as the background for reverse video
+       characters.
+    dit(bf(cursorColor:) em(colour))
+       Use the specified colour for the cursor.  The default is to use the
+       foreground colour;
+       option bf(-cr).
+    dit(bf(cursorColor2:) em(colour))
+       Use the specified colour for the colour of the cursor text.  For this
+       to take effect, bf(cursorColor) must also be specified.  The default
+       is to use the background colour.
+    dit(bf(reverseVideo:) em(boolean))
+       bf(True): simulate reverse video by foreground and background colours;
+       option bf(-rv).
+       bf(False): regular screen colours [default];
+       option bf(+rv).
+       See note in bf(COLORS AND GRAPHICS) section.
+    dit(bf(jumpScroll:) em(boolean))
+       bf(True): specify that jump scrolling should be used.  When scrolling
+       quickly, fewer screen updates are performed [default];
+       option bf(-j).
+       bf(False): specify that smooth scrolling should be used;
+       option bf(+j).
+    dit(bf(inheritPixmap:) em(boolean))
+       bf(True): make the background inherit the parent windows' pixmap,
+       giving artificial transparency.
+       bf(False): do not inherit the parent windows' pixmap.
+    dit(bf(scrollColor:) em(colour))
+       Use the specified colour for the scrollbar [default #B2B2B2].
+    dit(bf(troughColor:) em(colour))
+       Use the specified colour for the scrollbar's trough area [default
+       #969696].  Only relevant for normal (non XTerm/NeXT) scrollbar.
+    dit(bf(backgroundPixmap:) em(file[;geom]))
+       Use the specified XPM file (note the `.xpm' extension is optional)
+       for the background and also optionally specify its scaling with a
+       geometry string bf(WxH+X+Y), in which bf("W" / "H") specify the
+       horizontal/vertical scale (percent) and bf("X" / "Y") locate the
+       image centre (percent).  A scale of 0 displays the image with tiling.
+       A scale of 1 displays the image without any scaling.  A scale of 2 to
+       9 specifies an integer number of images in that direction.  No image
+       will be magnified beyond 10 times its original size.  The maximum
+       permitted scale is 1000.  [default 0x0+50+50]
+    dit(bf(menu:) em(file[;tag]))
+       Read in the specified menu file (note the `.menu' extension is
+       optional) and also optionally specify a starting tag to find.  See
+       the reference documentation for details on the syntax for the menuBar.
+    dit(bf(path:) em(path))
+       Specify the colon-delimited search path for finding files (XPM and
+       menus), in addition to the paths specified by the bf(RXVTPATH) and
+       bf(PATH) environment variables.
+    dit(bf(font:) em(fontname))
+       Select the main text font used [default 7x14];
+       option bf(-fn).
+    dit(bf(font)em(n)bf(:) em(fontname))
+       Specify the alternative font em(n).  The default font values: nl()\
+       indent(\
+           starttable(2)(l l)(0)\
+               row(cell(bf(font):)cell(7x14))\
+               row(cell(bf(font1):)cell(6x10))\
+               row(cell(bf(font2):)cell(6x13))\
+               row(cell(bf(font3):)cell(8x13))\
+               row(cell(bf(font4):)cell(9x15))\
+           endtable())
+    dit(bf(boldFont:) em(fontname))
+       Specify the name of the bold font to use if bf(colorBD) has not been
+       specified and it is not possible to map the default foreground colour
+       to colour 8-15 [default NONE].  This font must be the same height and
+       width as the normal font;
+       option bf(-fb).
+    dit(bf(mfont:) em(fontname))
+       Select the main multiple-character text font used [default k14];
+       option bf(-fk).
+    dit(bf(mfont)em(n)bf(:) em(fontname))
+       Specify the alternative multiple-character font em(n).  If compiled
+       for multiple-character fonts, the Roman and multiple-character font
+       sizes should match.
+    dit(bf(multichar_encoding:) em(mode))
+       Set the encoding mode to be used when multicharacter encoding is
+       received;
+       bf(eucj): EUC Japanese encoding [default for Kanji].
+       bf(sjis): Shift JIS encoding.
+       bf(big5): BIG5 encoding.
+       bf(gb): GB encoding.
+       bf(kr): EUC Korean encoding.
+       bf(noenc): no encoding;
+       option bf(-km).
+    dit(bf(greek_keyboard:) em(mode))
+       Set the Greek keyboard translation mode to be used;
+       bf(iso): ISO-8859 mapping (elot-928) [default].
+       bf(ibm): IBM-437 mapping (DOS codepage 737);
+       option bf(-grk).
+    dit(bf(greektoggle_key:) em(keysym))
+       Set the key to toggle keyboard input between no translation and
+       Greek translation  [default bf(Mode_switch)].
+       For more details, see the distributed file bf(README.greek).
+    dit(bf(selectstyle:) em(mode))
+       Set mouse selection style to bf(old) which is 2.20, bf(oldword) which
+       is xterm style with 2.20 old word selection, or anything else which
+       gives xterm style selection.
+    dit(bf(scrollstyle:) em(mode))
+       Set scrollbar style to bf(rxvt), bf(next) or bf(xterm)
+    dit(bf(title:) em(string))
+       Set window title string, the default title is the command-line
+       specified after the bf(-e) option, if any, otherwise the application
+       name;
+       option bf(-title).
+    dit(bf(iconName:) em(string))
+       Set the name used to label the window's icon or displayed in an icon
+       manager window, it also sets the window's title unless it is
+       explicitly set;
+       option bf(-n).
+    dit(bf(mapAlert:) em(boolean))
+       bf(True): de-iconify (map) on receipt of a bell character.
+       bf(False): no de-iconify (map) on receipt of a bell character
+       [default].
+    dit(bf(visualBell:) em(boolean))
+       bf(True): use visual bell on receipt of a bell character;
+       option bf(-vb).
+       bf(False): no visual bell [default];
+       option bf(+vb).
+    dit(bf(loginShell:) em(boolean))
+       bf(True): start as a login shell by prepending a `-' to bf(argv[0])
+       of the shell;
+       option bf(-ls).
+       bf(False): start as a normal sub-shell [default];
+       option bf(+ls).
+    dit(bf(utmpInhibit:) em(boolean))
+       bf(True): inhibit writing record into the system log file bf(utmp);
+       option bf(-ut).
+       bf(False): write record into the system log file bf(utmp) [default];
+       option bf(+ut).
+    dit(bf(print-pipe:) em(string))
+       Specify a command pipe for vt100 printer [default em(lpr(1))].  Use
+       bf(Print) to initiate a screen dump to the printer and bf(Ctrl-Print)
+       or bf(Shift-Print) to include the scrollback as well.
+    dit(bf(scrollBar:) em(boolean))
+       bf(True): enable the scrollbar [default];
+       option bf(-sb).
+       bf(False): disable the scrollbar;
+       option bf(+sb).
+    dit(bf(scrollBar_right:) em(boolean))
+       bf(True): place the scrollbar on the right of the window;
+       option bf(-sr).
+       bf(False): place the scrollbar on the left of the window;
+       option bf(+sr).
+    dit(bf(scrollBar_floating:) em(boolean))
+       bf(True): display an rxvt scrollbar without a trough;
+       option bf(-st).
+       bf(False): display an rxvt scrollbar with a trough;
+       option bf(+st).
+    dit(bf(scrollBar_align:) em(mode))
+       Align the bf(top), bf(bottom) or bf(centre) [default] of
+       the scrollbar thumb with the pointer on middle button
+       press/drag.
+    dit(bf(scrollTtyOutput:) em(boolean))
+       bf(True): scroll to bottom when tty receives output;
+       option(+si).
+       bf(False): do not scroll to bottom when tty receives output;
+       option(-si).
+    dit(bf(scrollWithBuffer:) em(boolean))
+       bf(True): scroll with scrollback buffer when tty recieves
+       new lines (and bf(scrollTtyOutput) is False);
+       option(+sw).
+       bf(False): do not scroll with scrollback buffer when tty
+       recieves new lines;
+       option(-sw).
+    dit(bf(scrollTtyKeypress:) em(boolean))
+       bf(True): scroll to bottom when a non-special key is pressed.
+       Special keys are those which are intercepted by rxvt for special
+       handling and are not passed onto the shell;
+       option(-sk).
+       bf(False): do not scroll to bottom when a non-special key is pressed;
+       option(+sk).
+    dit(bf(smallfont_key:) em(keysym))
+       If enabled, use bf(HOTKEY()-)em(keysym) to toggle to a smaller font
+       [default bf(HOTKEY()-SMALLFONT())]
+    dit(bf(bigfont_key:) em(keysym))
+       If enabled, use bf(HOTKEY()-)em(keysym) to toggle to a bigger font
+       [default bf(HOTKEY()-BIGFONT())]
+    dit(bf(saveLines:) em(number))
+       Save em(number) lines in the scrollback buffer [default 64].  This
+       resource is limited on most machines to 65535;
+       option bf(-sl).
+    dit(bf(internalBorder:) em(number))
+       Internal border of em(number) pixels. This resource is limited to 100;
+       option bf(-b).
+    dit(bf(externalBorder:) em(number))
+       External border of em(number) pixels.  This resource is limited to 100;
+       option bf(-w), bf(-bw), bf(-borderwidth).
+    dit(bf(termName:) em(termname))
+       Specifies the terminal type name to be set in the bf(TERM)
+       environment variable;
+       option bf(-tn).
+    dit(bf(linespace:) em(number))
+       Specifies number of lines (pixel height) to insert between each row
+       of the display [default 0];
+       option bf(-lsp).
+    dit(bf(meta8:) em(boolean))
+       bf(True): handle Meta (Alt) + keypress to set the 8th bit.
+       bf(False): handle Meta (Alt) + keypress as an escape prefix [default].
+    dit(bf(mouseWheelScrollPage:) em(boolean))
+       bf(True): the mouse wheel scrolls a page full.
+       bf(False): the mouse wheel scrolls five lines [default].
+    dit(bf(cursorBlink:) em(boolean))
+       bf(True): blink the cursor.
+       bf(False): do not blink the cursor [default];
+       option bf(-bc).
+    dit(bf(pointerBlank:) em(boolean))
+       bf(True): blank the pointer when a key is pressed or after a set number
+       of seconds of inactivity.
+       bf(False): the pointer is always visible [default].
+    dit(bf(pointerBlankDelay:) em(number))
+       Specifies number of seconds before blanking the pointer [default 2].
+    dit(bf(multibyte_cursor:) em(boolean))
+       bf(True): consider multibyte glyphs as single character for backspace,
+       delete and cursor movement keys;
+       option bf(-mcc).
+       bf(False): move through all components of all glyphs;
+       option bf(+mcc).
+    dit(bf(backspacekey:) em(string))
+       The string to send when the backspace key is pressed.  If set to
+       bf(DEC) or unset it will send bf(Delete) (code 127) or, if shifted,
+       bf(Backspace) (code 8) - which can be reversed with the appropriate
+       DEC private mode escape sequence.
+    dit(bf(deletekey:) em(string))
+       The string to send when the delete key (not the keypad delete key) is
+       pressed.  If unset it will send the sequence traditionally associated
+       with the bf(Execute) key.
+    dit(bf(cutchars:) em(string))
+       The characters used as delimiters for double-click word selection. 
+       The built-in default: nl()\
+       bf(BACKSLASH `"'&()*,;<=>?@[]{|})
+    dit(bf(preeditType:) em(style))
+       bf(OverTheSpot), bf(OffTheSpot), bf(Root);
+       option bf(-pt).
+    dit(bf(inputMethod:) em(name))
+       em(name) of inputMethod to use;
+       option bf(-im).
+    dit(bf(modifier:) em(modifier))
+       Set the key to be interpreted as the Meta key to:
+       bf(alt), bf(meta), bf(hyper), bf(super), bf(mod1), bf(mod2), bf(mod3),
+       bf(mod4), bf(mod5);
+       option bf(-mod).
+    dit(bf(answerbackString:) em(string))
+       Specify the reply rxvt sends to the shell when an ENQ (control-E)
+       character is passed through.  It may contain escape values as
+       described in the entry on bf(keysym) following.
+    dit(bf(keysym.)em(sym): em(string))
+       Associate em(string) with keysym em(sym) (bf(0xFF00 - 0xFFFF)).  It
+       may contain escape values (\a: bell, \b: backspace, \e, \E: escape,
+       \n: newline, \r: return, \t: tab, \000: octal number) or control
+       characters (^?: delete, ^@: null, ^A ...) and may enclosed with
+       double quotes so that it can start or end with whitespace.  The
+       intervening resource name bf(keysym.) cannot be omitted.  This
+       resource is only available when compiled with KEYSYM_RESOURCE.
+enddit()
diff --git a/doc/yodl/rxvt-scrollbar.yo b/doc/yodl/rxvt-scrollbar.yo
new file mode 100644 (file)
index 0000000..add585f
--- /dev/null
@@ -0,0 +1,13 @@
+COMMENT(-- $Id: rxvt-scrollbar.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(THE SCROLLBAR)
+
+Lines of text that scroll off the top of the bf(rxvt) window (resource:
+bf(saveLines)) and can be scrolled back using the scrollbar or by keystrokes. 
+The normal bf(rxvt) scrollbar has arrows and its behaviour is fairly
+intuitive.  The bf(xterm-scrollbar) is without arrows and its behaviour
+mimics that of em(xterm)
+
+Scroll down with bf(Button1) (bf(xterm-scrollbar)) or bf(Shift-Next).
+Scroll up with bf(Button3) (bf(xterm-scrollbar)) or bf(Shift-Prior).
+Continuous scroll with bf(Button2).
diff --git a/doc/yodl/rxvt-textselection.yo b/doc/yodl/rxvt-textselection.yo
new file mode 100644 (file)
index 0000000..6a66f52
--- /dev/null
@@ -0,0 +1,18 @@
+COMMENT(-- $Id: rxvt-textselection.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(----------------------------------------------------------------------)
+manpagesection(TEXT SELECTION AND INSERTION)
+
+The behaviour of text selection and insertion mechanism is similar to
+em(xterm)(1).
+
+startdit()
+    dit(bf(Selection):)
+       Left click at the beginning of the region, drag to the end of the
+       region and release; Right click to extend the marked region;
+       Left double-click to select a word; Left triple-click to select
+       the entire line.
+    dit(bf(Insertion):)
+       Pressing and releasing the Middle mouse button (or bf(Shift-Insert))
+       in an bf(rxvt) window causes the current text selection to be inserted
+       as if it had been typed on the keyboard.
+enddit()
diff --git a/doc/yodl/rxvt.yo b/doc/yodl/rxvt.yo
new file mode 100644 (file)
index 0000000..12bc75d
--- /dev/null
@@ -0,0 +1,117 @@
+COMMENT(-- $Id: rxvt.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+includefile(versioninfo.yo)
+includefile(masonyodl.yo)
+mailto(gcw@pobox.com)
+
+DEFINEMACRO(HOTKEY)(0)(Alt)
+DEFINEMACRO(BIGFONT)(0)(>)
+DEFINEMACRO(SMALLFONT)(0)(<)
+
+COMMENT(-----------------------------------------------------------------------
+-- We want the following macro's to be pre-defined
+--  RXVTDATE()
+--  RXVTVERSION()
+--  RXVTMAINT()
+--  RXVTMAINTEMAIL()
+--  RXVTWEBPAGE()
+--  RXVTWEBMAINT()
+--  RXVTWEBMAINTEMAIL()
+--  RXVTFTPSITE()
+------------------------------------------------------------------------------)
+
+COMMENT(----------------------------------------------------------------------)
+manpage(RXVT)(1)(RXVTDATE())(X Version 11)(X Tools)
+manpagename(rxvt (ouR XVT))(a VT102 emulator for the X window system)
+
+COMMENT(----------------------------------------------------------------------)
+manpagesynopsis()
+
+bf(rxvt) [options] [-e command [ args ]]
+
+COMMENT(----------------------------------------------------------------------)
+manpagedescription()
+
+bf(rxvt), version bf(RXVTVERSION()), is a colour vt102 terminal emulator
+intended as an em(xterm)(1) replacement for users who do not require
+features such as Tektronix 4014 emulation and toolkit-style configurability.
+As a result, bf(rxvt) uses much less swap space -- a significant
+advantage on a machine serving many X sessions.
+
+COMMENT(----------------------------------------------------------------------)
+
+includefile(rxvt-options.yo)
+includefile(rxvt-resources.yo)
+includefile(rxvt-scrollbar.yo)
+includefile(rxvt-mousereporting.yo)
+includefile(rxvt-textselection.yo)
+includefile(rxvt-fonts.yo)
+includefile(rxvt-login.yo)
+includefile(rxvt-colours.yo)
+includefile(rxvt-environment.yo)
+includefile(rxvt-files.yo)
+
+COMMENT(----------------------------------------------------------------------)
+manpageseealso()
+
+em(xterm)(1), em(sh)(1), em(resize)(1), em(X)(1), em(pty)(4), em(tty)(4),
+em(utmp)(5)
+
+See rxvtRef.html rxvtRef.txt for detailed information on recognized escape
+sequences and menuBar syntax, etc.
+
+COMMENT(----------------------------------------------------------------------)
+manpagebugs()
+
+Check the BUGS file for an up-to-date list.
+
+Cursor change support is not yet implemented.
+
+Click-and-drag doesn't work with X11 mouse report overriding.
+
+Graphics support is fairly crude.
+
+
+COMMENT(----------------------------------------------------------------------)
+manpagesection(FTP LOCATION)
+
+rxvt-+RXVTVERSION().tar.gz can be found at the following ftp sites
+url(RXVTFTPSITE())(RXVTFTPSITE())
+
+COMMENT(----------------------------------------------------------------------)
+manpagesection(CURRENT PROJECT COORDINATOR)
+
+startdit()
+    dit(Project Coordinator)
+       RXVTMAINT() email(RXVTMAINTEMAIL())nl()\
+    dit(Web page maintainter)
+       RXVTWEBMAINT() email(RXVTWEBMAINTEMAIL())nl()\
+       url(RXVTWEBPAGE())(RXVTWEBPAGE())nl()\
+    dit(Mailing list)
+       The Rxvt Workers email(<rxvt-workers@rxvt.org>)
+       mailing list has also been established for rxvt development, to
+       subscribe, email to 
+       email(<rxvt-workers-subscribe@rxvt.org>).
+       There is also a mailing list for announcements of new releases of
+       rxvt. To subscribe, email to
+       email(<rxvt-announce-subscribe@rxvt.org>).
+enddit()
+
+COMMENT(----------------------------------------------------------------------)
+manpageauthors()
+
+startdit()
+    dit(John Bovey)
+       University of Kent, 1992, wrote the original Xvt.
+    dit(Rob Nation email(<nation@rocket.sanders.lockheed.com>))
+       very heavily modified Xvt and came up with Rxvt
+    dit(Angelo Haritsis email(<ah@doc.ic.ac.uk>))
+       wrote the Greek Keyboard Input
+    dit(mj olesen email(<olesen@me.QueensU.CA>))
+       Wrote the menu system. nl()\
+       Project Coordinator (changes.txt 2.11 to 2.21)
+    dit(Oezguer Kesim email(<kesim@math.fu-berlin.de>))
+       Project Coordinator (changes.txt 2.21a to 2.4.5)
+    dit(Geoff Wing email(<gcw@pobox.com>))
+       Rewrote screen display and text selection routines. nl()\
+       Project Coordinator (changes.txt 2.4.6 - )
+enddit()
diff --git a/doc/yodl/rxvtRef-csi.yo b/doc/yodl/rxvtRef-csi.yo
new file mode 100644 (file)
index 0000000..2652784
--- /dev/null
@@ -0,0 +1,169 @@
+COMMENT(-- $Id: rxvtRef-csi.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(CSI)
+nsect(CSI (Code Sequence Introducer) Sequences)
+
+startdl()
+    dl(bf(tt(ESC [ Ps @)))
+       (Insert bf(tt(Ps)) (Blank) Character(s) [default: 1] (ICH))\
+P()\
+label(ESCOBPsA)
+    dl(bf(tt(ESC [ Ps A)))
+       (Cursor Up bf(tt(Ps)) Times [default: 1] (CUU))
+P()\
+    dl(bf(tt(ESC [ Ps B)))
+       (Cursor Down bf(tt(Ps)) Times [default: 1] (CUD))\
+label(ESCOBPsC)
+    dl(bf(tt(ESC [ Ps C)))
+       (Cursor Forward bf(tt(Ps)) Times [default: 1] (CUF))
+P()\
+    dl(bf(tt(ESC [ Ps D)))
+       (Cursor Backward bf(tt(Ps)) Times [default: 1] (CUB))
+P()\
+    dl(bf(tt(ESC [ Ps E)))
+       (Cursor Down bf(tt(Ps)) Times [default: 1] and to first column)
+P()\
+    dl(bf(tt(ESC [ Ps F)))
+       (Cursor Up bf(tt(Ps)) Times [default: 1] and to first column)\
+P()\
+label(ESCOBPsG)
+    dl(bf(tt(ESC [ Ps G)))
+       (Cursor to Column bf(tt(Ps)) (HPA))
+P()\
+    dl(bf(tt(ESC [ Ps;Ps H)))
+       (Cursor Position [row;column] [default: 1;1] (CUP))
+P()\
+    dl(bf(tt(ESC [ Ps I)))
+       (Move forward bf(tt(Ps)) tab stops [default: 1])
+P()\
+    dl(bf(tt(ESC [ Ps J)))
+       (Erase in Display (ED) nl()\
+        starttable(2)(l l)(0)\
+           row(cell(bf(tt(Ps = 0)))cell(Clear Below (default)))\
+           row(cell(bf(tt(Ps = 1)))cell(Clear Above))\
+           row(cell(bf(tt(Ps = 2)))cell(Clear All))\
+       endtable())
+    dl(bf(tt(ESC [ Ps K)))
+       (Erase in Line (EL) nl()\
+        starttable(2)(l l)(0)\
+           row(cell(bf(tt(Ps = 0)))cell(Clear to Right (default)))\
+           row(cell(bf(tt(Ps = 1)))cell(Clear to Left))\
+           row(cell(bf(tt(Ps = 2)))cell(Clear All))\
+       endtable())
+    dl(bf(tt(ESC [ Ps L)))
+       (Insert bf(tt(Ps)) Line(s) [default: 1] (IL))
+P()\
+    dl(bf(tt(ESC [ Ps M)))
+       (Delete bf(tt(Ps)) Line(s) [default: 1] (DL))
+P()\
+    dl(bf(tt(ESC [ Ps P)))
+       (Delete bf(tt(Ps)) Character(s) [default: 1] (DCH))
+P()\
+    dl(bf(tt(ESC [ Ps;Ps;Ps;Ps;Ps T)))
+       (Initiate link(hilite mouse tracking)(Mouse).  em(unimplemented)
+       Parameters are [func;startx;starty;firstrow;lastrow].)
+P()\
+    dl(bf(tt(ESC [ Ps W)))
+       (Tabulator functions nl()\
+        starttable(2)(l l)(0)\
+           row(cell(bf(tt(Ps = 0)))cell(Tab Set (HTS)))\
+           row(cell(bf(tt(Ps = 2)))cell(Tab Clear (TBC), Clear Current \
+               Column (default)))\
+           row(cell(bf(tt(Ps = 5)))cell(Tab Clear (TBC), Clear All))\
+       endtable())
+    dl(bf(tt(ESC [ Ps X)))
+       (Erase bf(tt(Ps)) Character(s) [default: 1] (ECH))
+P()\
+    dl(bf(tt(ESC [ Ps Z)))
+       (Move backward bf(tt(Ps)) [default: 1] tab stops)
+P()\
+    dl(bf(tt(ESC [ Ps ')))
+       (== link(tt(ESC [ Ps G))(ESCOBPsG))
+P()\
+    dl(bf(tt(ESC [ Ps a)))
+       (== link(tt(ESC [ Ps C))(ESCOBPsC))\
+P()\
+label(ESCOBPsc)
+    dl(bf(tt(ESC [ Ps c)))
+       (Send Device Attributes (DA)nl()\
+       bf(tt(Ps = 0)) (or omitted) : request attributes from terminal nl()\
+       returns: bf(tt(ESC[?1;2c)) (``I am a VT100 with Advanced Video
+       Option''))
+P()\
+    dl(bf(tt(ESC [ Ps d)))
+       (Cursor to Line bf(tt(Ps)) (VPA))
+P()\
+    dl(bf(tt(ESC [ Ps e)))
+       (== link(ESC [ Ps A)(ESCOBPsA))
+P()\
+    dl(bf(tt(ESC [ Ps;Ps f)))
+       (Horizontal and Vertical Position [row;column] (HVP) [default: 1;1])
+P()\
+    dl(bf(tt(ESC [ Ps g)))
+       (Tab Clear (TBC) nl()\
+        starttable(2)(l l)(0)\
+           row(cell(bf(tt(Ps = 0)))cell(Clear Current Column (default)))\
+           row(cell(bf(tt(Ps = 3)))cell(Clear All (TBC)))\
+       endtable())
+    dl(bf(tt(ESC [ Ps i)))
+       (Printing nl()\
+        starttable(2)(l l)(0)\
+           row(cell(bf(tt(Ps = 4)))cell(disable transparent print mode (MC4)))\
+           row(cell(bf(tt(Ps = 5)))cell(enable transparent print mode (MC5) \
+               em(unimplemented)))\
+       endtable())
+    dl(bf(tt(ESC [ Pm h)nl()tt(ESC [ Pm l)))
+       (Set Mode (SM) nl()Reset Mode (RM)\
+       startdl()
+           dl(bf(tt(Ps = 4)))
+               (starttable(2)(l l)(0)\
+                   row(cell(bf(tt(h)))cell(Insert Mode (SMIR)))\
+                   row(cell(bf(tt(l)))cell(Replace Mode (RMIR)))\
+               endtable())
+           dl(bf(tt(Ps = 20)) em(unimplemented))
+               (starttable(2)(l l)(0)\
+                   row(cell(bf(tt(h)))cell(Automatic Newline (LNM)))\
+                   row(cell(bf(tt(h)))cell(Normal Linefeed (LNM)))\
+               endtable())
+       enddl())
+    dl(bf(tt(ESC [ Pm m)))
+       (Character Attributes (SGR) nl()\
+       starttable(2)(l l)(0)\
+           row(cell(bf(tt(Ps = 0)))cell(Normal (default)))\
+           row(cell(bf(tt(Ps = 1 / 22)))cell(On / Off Bold (bright fg)))\
+           row(cell(bf(tt(Ps = 4 / 24)))cell(On / Off Underline))\
+           row(cell(bf(tt(Ps = 5 / 25)))cell(On / Off Blink (bright bg)))\
+           row(cell(bf(tt(Ps = 7 / 27)))cell(On / Off Inverse))\
+           row(cell(bf(tt(Ps = 30 / 40)))cell(fg/bg Black))\
+           row(cell(bf(tt(Ps = 31 / 41)))cell(fg/bg Red))\
+           row(cell(bf(tt(Ps = 32 / 42)))cell(fg/bg Green))\
+           row(cell(bf(tt(Ps = 33 / 43)))cell(fg/bg Yellow))\
+           row(cell(bf(tt(Ps = 34 / 44)))cell(fg/bg Blue))\
+           row(cell(bf(tt(Ps = 35 / 45)))cell(fg/bg Magenta))\
+           row(cell(bf(tt(Ps = 36 / 46)))cell(fg/bg Cyan))\
+           row(cell(bf(tt(Ps = 37 / 47)))cell(fg/bg White))\
+           row(cell(bf(tt(Ps = 39 / 49)))cell(fg/bg Default))\
+       endtable())
+    dl(bf(tt(ESC [ Ps n)))
+       (Device Status Report (DSR) nl()\
+       starttable(2)(l l)(0)\
+           row(cell(bf(tt(Ps = 5)))cell(Status Report bf(tt(ESC [ 0 n)) \
+               (``OK'')))\
+           row(cell(bf(tt(Ps = 6)))cell(Report Cursor Position (CPR) \
+               [row;column] as bf(tt(ESC [ r ; c R))))\
+           row(cell(bf(tt(Ps = 7)))cell(Request Display Name))\
+           row(cell(bf(tt(Ps = 8)))cell(Request Version Number (place in \
+               window title)))\
+       endtable())
+    dl(bf(tt(ESC [ Ps;Ps r)))
+       (Set Scrolling Region [top;bottom] nl()\
+       [default: full size of window] (CSR))
+P()\
+    dl(bf(tt(ESC [ s)))
+       (Save Cursor (SC))
+P()\
+    dl(bf(tt(ESC [ Ps x)))
+       (Request Terminal Parameters (DECREQTPARM))
+P()\
+    dl(bf(tt(ESC [ u)))
+       (Restore Cursor)
+enddl()
diff --git a/doc/yodl/rxvtRef-definitions.yo b/doc/yodl/rxvtRef-definitions.yo
new file mode 100644 (file)
index 0000000..6707b6d
--- /dev/null
@@ -0,0 +1,22 @@
+COMMENT(-- $Id: rxvtRef-definitions.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(Definitions)
+nsect(Definitions)
+
+startdl()
+    dl(bf(tt(c)))
+       (The literal character c.)
+P()\
+    dl(bf(tt(C)))
+       (A single (required) character.)
+P()\
+    dl(bf(tt(Ps)))
+       (A single (usually optional) numeric parameter, composed of one or
+       more digits.)
+P()\
+    dl(bf(tt(Pm)))
+       (A multiple numeric parameter composed of any number of single numeric
+       parameters, separated by ; character(s).)
+P()\
+    dl(bf(tt(Pt)))
+       (A text parameter composed of printable characters.)
+enddl()
diff --git a/doc/yodl/rxvtRef-graphics.yo b/doc/yodl/rxvtRef-graphics.yo
new file mode 100644 (file)
index 0000000..a0cb7e8
--- /dev/null
@@ -0,0 +1,33 @@
+COMMENT(-- $Id: rxvtRef-graphics.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(Graphics)
+nsect(Special Graphics Mode)
+
+Add more documentation here, em(if anyone actually cares.)
+
+startdl()
+    dl(bf(tt(ESC G Q)))
+       (query if graphics are available nl()\
+       returns: bf(tt(ESC G 0)) no graphics available nl()\
+       returns: bf(tt(ESC G 1)) graphics available (colour only))
+P()\
+    dl(bf(tt(ESC G W <;x>;<y>;<w>;<h>:)))
+       (create window)
+P()\
+    dl(bf(tt(ESC G C <id>)))
+       (clear window)
+P()\
+    dl(bf(tt(ESC G G <it>:)))
+       (query window nl()\
+       returns: bf(tt(ESC G <id> <x> <y> <w> <h> <fw> <fh> <nw> <nh>)))
+P()\
+    dl(bf(tt(ESC G L <id>)nl()tt(ESC G P <id>)nl()tt(ESC G F <id>)))
+       (start point nl()\
+       start line nl()\
+       start fill)
+P()\
+    dl(bf(tt(;<x>;<y>)))
+       (extend point/line/fill)
+P()\
+    dl(bf(tt(ESC G T <id>;<x>;<y>;<mode>;<len>:<text>)))
+       (place text)
+enddl()
diff --git a/doc/yodl/rxvtRef-keycodes.yo b/doc/yodl/rxvtRef-keycodes.yo
new file mode 100644 (file)
index 0000000..6dfbc67
--- /dev/null
@@ -0,0 +1,73 @@
+COMMENT(-- $Id: rxvtRef-keycodes.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(KeyCodes)
+nsect(Key Codes)
+
+Note: bf(Shift) + bf(F1)-bf(F10) generates bf(F11)-bf(F20)
+
+For the keypad, use bf(Shift) to temporarily override Application-Keypad
+setting use bf(Num_Lock) to toggle Application-Keypad setting if bf(Num_Lock)
+is off, link(escape sequences)(ESCequals) toggle Application-Keypad setting.
+Also note that values of bf(Home), bf(End), bf(Delete) may have been compiled
+differently on your system.
+
+COMMENT(-- Edited in a wide window --)
+starttable(5)(l l l l l)(1)\
+    row(cell(               )cell(bf(Normal)     )cell(bf(Shift)      )cell(bf(Control)    )cell(bf(Ctrl+Shift)))\
+    row(cell(Tab            )cell(^I         )cell(ESC [ Z    )cell(^I         )cell(ESC [ Z))\
+    row(cell(BackSpace      )cell(^H         )cell(^?         )cell(^?         )cell(^?))\
+    row(cell(Find           )cell(ESC [ 1 ~  )cell(ESC [ 1 $  )cell(ESC [ 1 ^  )cell(ESC [ 1 @))\
+    row(cell(Insert         )cell(ESC [ 2 ~  )cell(em(paste)      )cell(ESC [ 2 ^  )cell(ESC [ 2 @))\
+    row(cell(Execute        )cell(ESC [ 3 ~  )cell(ESC [ 3 $  )cell(ESC [ 3 ^  )cell(ESC [ 3 @))\
+    row(cell(Select         )cell(ESC [ 4 ~  )cell(ESC [ 4 $  )cell(ESC [ 4 ^  )cell(ESC [ 4 @))\
+    row(cell(Prior          )cell(ESC [ 5 ~  )cell(em(scroll-up)  )cell(ESC [ 5 ^  )cell(ESC [ 5 @))\
+    row(cell(Next           )cell(ESC [ 6 ~  )cell(em(scroll-down))cell(ESC [ 6 ^  )cell(ESC [ 6 @))\
+    row(cell(Home           )cell(ESC [ 7 ~  )cell(ESC [ 7 $  )cell(ESC [ 7 ^  )cell(ESC [ 7 @))\
+    row(cell(End            )cell(ESC [ 8 ~  )cell(ESC [ 8 $  )cell(ESC [ 8 ^  )cell(ESC [ 8 @))\
+    row(cell(Delete         )cell(ESC [ 3 ~  )cell(ESC [ 3 $  )cell(ESC [ 3 ^  )cell(ESC [ 3 @))\
+    row(cell(F1             )cell(ESC [ 11 ~ )cell(ESC [ 23 ~ )cell(ESC [ 11 ^ )cell(ESC [ 23 ^))\
+    row(cell(F2             )cell(ESC [ 12 ~ )cell(ESC [ 24 ~ )cell(ESC [ 12 ^ )cell(ESC [ 24 ^))\
+    row(cell(F3             )cell(ESC [ 13 ~ )cell(ESC [ 25 ~ )cell(ESC [ 13 ^ )cell(ESC [ 25 ^))\
+    row(cell(F4             )cell(ESC [ 14 ~ )cell(ESC [ 26 ~ )cell(ESC [ 14 ^ )cell(ESC [ 26 ^))\
+    row(cell(F5             )cell(ESC [ 15 ~ )cell(ESC [ 28 ~ )cell(ESC [ 15 ^ )cell(ESC [ 28 ^))\
+    row(cell(F6             )cell(ESC [ 17 ~ )cell(ESC [ 29 ~ )cell(ESC [ 17 ^ )cell(ESC [ 29 ^))\
+    row(cell(F7             )cell(ESC [ 18 ~ )cell(ESC [ 31 ~ )cell(ESC [ 18 ^ )cell(ESC [ 31 ^))\
+    row(cell(F8             )cell(ESC [ 19 ~ )cell(ESC [ 32 ~ )cell(ESC [ 19 ^ )cell(ESC [ 32 ^))\
+    row(cell(F9             )cell(ESC [ 20 ~ )cell(ESC [ 33 ~ )cell(ESC [ 20 ^ )cell(ESC [ 33 ^))\
+    row(cell(F10            )cell(ESC [ 21 ~ )cell(ESC [ 34 ~ )cell(ESC [ 21 ^ )cell(ESC [ 34 ^))\
+    row(cell(F11            )cell(ESC [ 23 ~ )cell(ESC [ 23 $ )cell(ESC [ 23 ^ )cell(ESC [ 23 @))\
+    row(cell(F12            )cell(ESC [ 24 ~ )cell(ESC [ 24 $ )cell(ESC [ 24 ^ )cell(ESC [ 24 @))\
+    row(cell(F13            )cell(ESC [ 25 ~ )cell(ESC [ 25 $ )cell(ESC [ 25 ^ )cell(ESC [ 25 @))\
+    row(cell(F14            )cell(ESC [ 26 ~ )cell(ESC [ 26 $ )cell(ESC [ 26 ^ )cell(ESC [ 26 @))\
+    row(cell(F15 (Help)     )cell(ESC [ 28 ~ )cell(ESC [ 28 $ )cell(ESC [ 28 ^ )cell(ESC [ 28 @))\
+    row(cell(F16 (Menu)     )cell(ESC [ 29 ~ )cell(ESC [ 29 $ )cell(ESC [ 29 ^ )cell(ESC [ 29 @))\
+    row(cell(F17            )cell(ESC [ 31 ~ )cell(ESC [ 31 $ )cell(ESC [ 31 ^ )cell(ESC [ 31 @))\
+    row(cell(F18            )cell(ESC [ 32 ~ )cell(ESC [ 32 $ )cell(ESC [ 32 ^ )cell(ESC [ 32 @))\
+    row(cell(F19            )cell(ESC [ 33 ~ )cell(ESC [ 33 $ )cell(ESC [ 33 ^ )cell(ESC [ 33 @))\
+    row(cell(F20            )cell(ESC [ 34 ~ )cell(ESC [ 34 $ )cell(ESC [ 34 ^ )cell(ESC [ 34 @))\
+    row(cell(               )cell(           )cell(           )cell(           )cell(bf(Application)))\
+    row(cell(Up             )cell(ESC [ A    )cell(ESC [ a    )cell(ESC O a    )cell(ESC O A))\
+    row(cell(Down           )cell(ESC [ B    )cell(ESC [ b    )cell(ESC O b    )cell(ESC O B))\
+    row(cell(Right          )cell(ESC [ C    )cell(ESC [ c    )cell(ESC O c    )cell(ESC O C))\
+    row(cell(Left           )cell(ESC [ D    )cell(ESC [ d    )cell(ESC O d    )cell(ESC O D))\
+    row(cell(KP_Enter       )cell(^M         )cell(           )cell(           )cell(ESC O M))\
+    row(cell(KP_F1          )cell(ESC O P    )cell(           )cell(           )cell(ESC O P))\
+    row(cell(KP_F2          )cell(ESC O Q    )cell(           )cell(           )cell(ESC O Q))\
+    row(cell(KP_F3          )cell(ESC O R    )cell(           )cell(           )cell(ESC O R))\
+    row(cell(KP_F4          )cell(ESC O S    )cell(           )cell(           )cell(ESC O S))\
+    row(cell(XK_KP_Multiply )cell(*          )cell(           )cell(           )cell(ESC O j))\
+    row(cell(XK_KP_Add      )cell(+          )cell(           )cell(           )cell(ESC O k))\
+    row(cell(XK_KP_Separator)cell(,          )cell(           )cell(           )cell(ESC O l))\
+    row(cell(XK_KP_Subtract )cell(-          )cell(           )cell(           )cell(ESC O m))\
+    row(cell(XK_KP_Decimal  )cell(.          )cell(           )cell(           )cell(ESC O n))\
+    row(cell(XK_KP_Divide   )cell(/          )cell(           )cell(           )cell(ESC O o))\
+    row(cell(XK_KP_0        )cell(0          )cell(           )cell(           )cell(ESC O p))\
+    row(cell(XK_KP_1        )cell(1          )cell(           )cell(           )cell(ESC O q))\
+    row(cell(XK_KP_2        )cell(2          )cell(           )cell(           )cell(ESC O r))\
+    row(cell(XK_KP_3        )cell(3          )cell(           )cell(           )cell(ESC O s))\
+    row(cell(XK_KP_4        )cell(4          )cell(           )cell(           )cell(ESC O t))\
+    row(cell(XK_KP_5        )cell(5          )cell(           )cell(           )cell(ESC O u))\
+    row(cell(XK_KP_6        )cell(6          )cell(           )cell(           )cell(ESC O v))\
+    row(cell(XK_KP_7        )cell(7          )cell(           )cell(           )cell(ESC O w))\
+    row(cell(XK_KP_8        )cell(8          )cell(           )cell(           )cell(ESC O x))\
+    row(cell(XK_KP_9        )cell(9          )cell(           )cell(           )cell(ESC O y))\
+endtable()
diff --git a/doc/yodl/rxvtRef-menubar.yo b/doc/yodl/rxvtRef-menubar.yo
new file mode 100644 (file)
index 0000000..a94ad7a
--- /dev/null
@@ -0,0 +1,283 @@
+COMMENT(-- $Id: rxvtRef-menubar.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(menuBar)
+nsect(menuBar)
+
+bf(The exact syntax used is em(almost) solidified.) nl()\
+In the menus, bf(DON'T) try to use menuBar commands that add or remove a
+menuBar.
+
+Note that in all of the commands, the bf(em(/path/)) em(cannot) be omitted:
+use bf(./) to specify a menu relative to the current menu.
+
+nsubsect(Overview of menuBar operation)
+
+For the menuBar XTerm escape sequence tt(ESC ] 10 ; Pt ST), the
+syntax of tt(Pt) can be used for a variety of tasks:
+startit()
+    it()link(Commands)(menuBarCommands)
+    it()link(Adding and accessing menus)(menuBarAdd)
+    it()link(Removing menus)(menuBarRemove)
+    it()link(Quick Arrows)(menuBarArrows)
+    it()link(Command Summary)(menuBarSummary)
+endit()
+
+At the top level is the current menuBar which is a member of a circular
+linked-list of other such menuBars.
+
+The menuBar acts as a parent for the various drop-down menus, which in turn,
+may have labels, separator lines, menuItems and subMenus.
+
+The menuItems are the useful bits: you can use them to mimic keyboard input
+or even to send text or escape sequences back to rxvt.
+
+The menuBar syntax is intended to provide a simple yet robust method of
+constructing and manipulating menus and navigating through the menuBars.
+
+The first step is to use the tag bf([menu:em(name)]) which creates the
+menuBar called em(name) and allows access.
+You may now link(add)(menuBarAdd) or link(remove)(menuBarRemove) menus,
+subMenus, and menuItems. Finally, use the tag bf([done]) to set the menuBar
+access as bf(readonly) to prevent accidental corruption of the menus.
+To re-access the current menuBar for alterations, use the tag bf([menu]),
+make the alterations and then use bf([done])
+
+label(menuBarCommands)
+nsubsect(Commands)
+
+startdl()
+    dl(bf([menu:+em(name)]))
+       (access the named menuBar for creation or alteration. If a new menuBar
+       is created, it is called em(name) (max of 15 chars) and the current
+       menuBar is pushed onto the stack)
+P()\
+    dl(bf([menu]))
+       (access the current menuBar for alteration)
+P()\
+    dl(bf([title:+em(string)]))
+       (set the current menuBar's title to em(string), which may contain the
+       following format specifiers: nl()\
+       bf(%%) : literal bf(%) character nl()\
+       bf(%n) : rxvt name (as per the bf(-name) command-line option) nl()\
+       bf(%v) : rxvt version)
+P()\
+    dl(bf([done]))
+       (set menuBar access as bf(readonly). nl()\
+       End-of-file tag for bf([read:+em(file)]) operations.)
+P()\
+    dl(bf([read:+em(file)]))
+       (read menu commands directly from em(file) (extension ".menu" will be
+       appended if required.) Start reading at a line with bf([menu]) or
+       bf([menu:+em(name)) and continuing until bf([done]) is encountered.
+
+       Blank and comment lines (starting with bf(#)) are ignored.
+       Actually, since any invalid menu commands are also ignored, almost
+       anything could be construed as a comment line, but this may be
+       tightened up in the future ... so don't count on it!.)
+P()\
+    dl(bf([read:+em(file);+em(name)]))
+       (The same as bf([read:+em(file)]), but start reading at a line with
+       bf([menu:+em(name)]) and continuing until bf([done:+em(name)]) or
+       bf([done]) is encountered.)
+P()\
+    dl(bf([dump]))
+       (dump all menuBars to the file bf(/tmp/rxvt-PID) in a format suitable
+       for later rereading.)
+P()\
+    dl(bf([rm:name]nl()[rm] [rm:]nl()[rm*] [rm:*]))
+       (remove the named menuBar nl()\
+       remove the current menuBar nl()\
+       remove all menuBars)
+P()\
+    dl(bf([swap]))
+       (swap the top two menuBars)
+P()\
+    dl(bf([prev]nl()[next]))
+       (access the previous or next menuBar)
+P()\
+    dl(bf([show]nl()[hide]))
+       (control display of the menuBar ... just like
+       link(ESC[?10 h/l)(Priv10))
+P()\
+    dl(bf([pixmap:+em(name)]nl()[pixmap:+em(name);em(scaling)]))
+       (set the background pixmap globally ... just like
+       link(ESC ] 20 ; Pt ST)(XPM)
+
+       bf(A Future implementation em(may) make this local to the menubar))
+P()\
+    dl(bf([:+em(command):]))
+       (ignore the menu readonly status and issue a em(command) to
+       link(Add/Modify)(menuBarAdd) or link(Remove)(menuBarRemove) a menu or
+       menuitem or change the link(Quick Arrows)(menuBarArrows); a useful
+       shortcut for setting the quick arrows from a menuBar.)
+enddl()
+
+label(menuBarAdd)
+nsubsect(Adding and accessing menus)
+
+The following commands may also be bf(+) prefixed.
+startdl()
+    dl(bf(/+nl()./+nl()../+nl()../../))
+       (access menuBar top level nl()\
+       access current menu level nl()\
+       access parent menu (1 level up) nl()\
+       access parent menu (multiple levels up))
+    dl(bf(em(/path/)menu))
+       (add/access menu)
+    dl(bf(em(/path/)menu/*))
+       (add/access menu and clear it if it exists)
+    dl(bf(em(/path/){-}))
+       (add separator)
+    dl(bf(em(/path/){item}))
+       (add bf(item) as a label)
+    dl(bf(em(/path/){item} action))
+       (add/alter em(menuitem) with an associated em(action))
+    dl(bf(em(/path/){item}{right-text}))
+       (add/alter em(menuitem) with bf(right-text) as the right-justified
+       text and as the associated em(action))
+    dl(bf(em(/path/){item}{rtext} action))
+       (add/alter em(menuitem) with an associated em(action) and with
+       bf(rtext) as the right-justified text.)
+enddl()
+startdl()
+    dl(Special characters in em(action) must be backslash-escaped:)
+       (bf(\a \b \E \e \n \r \t \octal))
+    dl(or in control-character notation:)
+       (bf(^@, ^A .. ^Z .. ^_, ^?))
+enddl()
+
+To send a string starting with a bf(NUL) (bf(^@)) character to the program,
+start em(action) with a pair of bf(NUL) characters (bf(^@^@)), the first of
+which will be stripped off and the balance directed to the program.
+Otherwise if em(action) begins with bf(NUL) followed by non-+bf(NUL)
+characters, the leading bf(NUL) is stripped off and the balance is sent back
+to rxvt.
+
+As a convenience for the many Emacs-type editors, em(action) may start
+with bf(M-) (eg, bf(M-$) is equivalent to bf(\E$)) and a bf(CR) will be
+appended if missed from bf(M-x) commands.
+
+As a convenience for issuing XTerm bf(ESC]) sequences from a menubar
+(or quick arrow), a bf(BEL) (bf(^G)) will be appended if needed.
+
+startdl()
+    dl(For example,)
+       (bf(M-xapropos) is equivalent to bf(\Exapropos\r))
+    dl(and)
+       (bf(\E]10;mona;100) is equivalent to bf(\E]10;mona;100\a))
+enddl()
+
+The option bf({em(right-rtext)}) will be right-justified.  In the absence of
+a specified action, this text will be used as the em(action) as well.
+
+startdl()
+    dl(For example,)
+       (bf(/File/{Open}{^X^F}) is equivalent to bf(/File/{Open}{^X^F} ^X^F))
+enddl()
+
+The left label em(is) necessary, since it's used for matching,
+but implicitly hiding the left label (by using same name for both left
+and right labels), or explicitly hiding the left label (by preceeding
+it with a dot), makes it possible to have right-justified text only.
+startdl()
+    dl(For example,)
+       (bf(/File/{Open}{Open} Open-File-Action))
+    dl(or hiding it)
+       (bf(/File/{.anylabel}{Open} Open-File-Action))
+enddl()
+
+label(menuBarRemove)
+nsubsect(Removing menus)
+
+startdl()
+    dl(bf(-/*+nl()-+em(/path)menu+nl()-+em(/path){item}+nl()-+em(/path){-}))
+       (remove all menus from the menuBar, the same as bf([clear])nl()\
+       remove menu nl()\
+       remove item nl()\
+       remove separator)
+    dl(bf(-/path/menu/*))
+       (remove all items, separators and submenus from menu)
+enddl()
+
+label(menuBarArrows)
+nsubsect(Quick Arrows)
+
+The menus also provide a hook for em(quick arrows) to provide easier user
+access. If nothing has been explicitly set, the default is to emulate the
+curror keys. The syntax permits each arrow to be altered individually or
+all four at once without re-entering their common beginning/end text. For
+example, to explicitly associate cursor actions with the arrows, any of
+the following forms could be used:
+
+startdl()
+    dl(bf(<r>+em(Right)nl()<l>+em(Left)nl()<u>+em(Up)nl()<d>+em(Down)))
+       (Define actions for the respective arrow buttons)
+    dl(bf(<b>+em(Begin)nl()<e>+em(End)))
+       (Define common beginning/end parts for em(quick arrows) which used
+       in conjunction with the above <r> <l> <u> <d> constructs)
+enddl()
+
+startdl()
+    dl(For example, define arrows individually,)
+       (bf(<u>\E[A nl()\
+       <d>\E[B nl()\
+       <r>\E[C nl()\
+       <l>\E[D))
+    dl(or all at once)
+        (bf(<u>\E[A<d>\E[B<r>\E[C<l>\E[D))
+    dl(or more compactly (factoring out common parts))
+       (bf(<b>\E[<u>A<d>B<r>C<l>D))
+enddl()
+
+label(menuBarSummary)
+nsubsect(Command Summary)
+
+A short summary of the most em(common) commands:
+
+startdl()
+    dl([menu:name])
+       (use an existing named menuBar or start a new one)
+    dl([menu])
+       (use the current menuBar)
+    dl([title:string])
+       (set menuBar title)
+    dl([done])
+       (set menu access to readonly and, if reading from a file, signal EOF)
+    dl([done:name])
+       (if reading from a file using [read:file;name] signal EOF)
+    dl([rm:name]+nl()[rm] [rm:]+nl()[rm*] [rm:*])
+       (remove named, current, or all menuBar(s))
+    dl([swap])
+       (swap top two menuBars)
+    dl([prev]+nl()[next])
+       (access the previous/next menuBar)
+    dl([show]+nl()[hide])
+       (map/unmap menuBar)
+    dl([pixmap;file]+nl()[pixmap;file;scaling])
+       (set a background pixmap)
+    dl([read:file]+nl()[read:file;name])
+       (read in a menu from a file)
+    dl([dump])
+       (dump out all menuBars to /tmp/rxvt-PID)
+    dl(/)
+       (access menuBar top level)
+    dl(./+nl()../+nl()../../)
+       (access current or parent menu level)
+    dl(/path/menu)
+       (add/access menu)
+    dl(/path/{-})
+       (add separator)
+    dl(/path/{item}{rtext} action)
+       (add/alter menu item+nl()({rtext} and/or action, may be omitted))
+    dl(-/*)
+       (remove all menus from the menuBar)
+    dl(-/path/menu)
+       (remove menu items, separators and submenus from menu)
+    dl(-/path/menu)
+       (remove menu)
+    dl(-/path/{item})
+       (remove item)
+    dl(-/path/{-})
+       (remove separator)
+    dl(<b>Begin<r>Right<l>Left<u>Up<d>Down<e>End)
+       (menu quick arrows)
+enddl()
diff --git a/doc/yodl/rxvtRef-mouse.yo b/doc/yodl/rxvtRef-mouse.yo
new file mode 100644 (file)
index 0000000..0cbb44d
--- /dev/null
@@ -0,0 +1,29 @@
+COMMENT(-- $Id: rxvtRef-mouse.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(Mouse)
+nsect(Mouse Reporting)
+
+startdl()
+    dl(bf(tt(ESC [ M <b> <x> <y>)))
+       (report mouse position)
+enddl()
+The lower 2 bits of bf(tt(<b>)) indicate the button:
+startdl()
+    dl(Button = bf(tt((<b> - SPACE) & 3)))
+       (0 = Button1 pressed nl()\
+       1 = Button2 pressed nl()\
+       2 = Button3 pressed nl()\
+       3 = button released (X11 mouse report))
+enddl()
+
+The upper bits of bf(tt(<b>)) indicate the modifiers when the button was
+pressed and are added together (X11 mouse report only):
+
+startdl()
+    dl(State = bf(tt((<b> - SPACE) & 60)))
+        (4 = Shift nl()\
+       8 = Meta nl()\
+       16 = Control nl()\
+       32 = Double Click em((Rxvt extension)) nl()\
+       Col = bf(tt(<x> - SPACE)) nl()\
+       Row = bf(tt(<y> - SPACE)))
+enddl()
diff --git a/doc/yodl/rxvtRef-privatemodes.yo b/doc/yodl/rxvtRef-privatemodes.yo
new file mode 100644 (file)
index 0000000..6bf7423
--- /dev/null
@@ -0,0 +1,164 @@
+COMMENT(-- $Id: rxvtRef-privatemodes.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(PrivateModes)
+nsect(DEC Private Modes)
+
+startdl()
+    dl(bf(tt(ESC [ ? Pm h)))
+        (DEC Private Mode Set (DECSET))
+P()\
+    dl(bf(tt(ESC [ ? Pm l)))
+        (DEC Private Mode Reset (DECRST))
+P()\
+    dl(bf(tt(ESC [ ? Pm r)))
+        (Restore previously saved DEC Private Mode Values.)
+P()\
+    dl(bf(tt(ESC [ ? Pm s)))
+        (Save DEC Private Mode Values.)
+P()\
+    dl(bf(tt(ESC [ ? Pm t)))
+        (Toggle DEC Private Mode Values (rxvt extension).)
+    em(where) nl()\
+startdl()
+        dl(bf(tt(Ps = 1)) (DECCKM))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Application Cursor Keys))\
+                row(cell(bf(tt(l)))cell(Normal Cursor Keys))\
+            endtable())
+        dl(bf(tt(Ps = 2)) (ANSI/VT52 mode))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Enter VT52 mode))\
+                row(cell(bf(tt(l)))cell(Enter VT52 mode))\
+            endtable())
+        dl(bf(tt(Ps = 3)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(132 Column Mode (DECCOLM)))\
+                row(cell(bf(tt(l)))cell(80 Column Mode (DECCOLM)))\
+            endtable())
+        dl(bf(tt(Ps = 4)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Smooth (Slow) Scroll (DECSCLM)))\
+                row(cell(bf(tt(l)))cell(Jump (Fast) Scroll (DECSCLM)))\
+            endtable())
+        dl(bf(tt(Ps = 5)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Reverse Video (DECSCNM)))\
+                row(cell(bf(tt(l)))cell(Normal Video (DECSCNM)))\
+            endtable())
+        dl(bf(tt(Ps = 6)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Origin Mode (DECOM)))\
+                row(cell(bf(tt(l)))cell(Normal Cursor Mode (DECOM)))\
+            endtable())
+        dl(bf(tt(Ps = 7)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Wraparound Mode (DECAWM)))\
+                row(cell(bf(tt(l)))cell(No Wraparound Mode (DECAWM)))\
+            endtable())
+        dl(bf(tt(Ps = 8)) em(unimplemented))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Auto-repeat Keys (DECARM)))\
+                row(cell(bf(tt(l)))cell(No Auto-repeat Keys (DECARM)))\
+            endtable())
+        dl(bf(tt(Ps = 9)) X10 XTerm link(mouse reporting)(Mouse))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Send Mouse X & Y on button press.))\
+                row(cell(bf(tt(l)))cell(No mouse reporting.))\
+            endtable())\
+label(Priv10)
+        dl(bf(tt(Ps = 10)) (bf(rxvt)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(link(menuBar)(menuBar) visible))\
+                row(cell(bf(tt(l)))cell(link(menuBar)(menuBar) invisible))\
+            endtable())
+        dl(bf(tt(Ps = 25)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Visible cursor {cnorm/cvvis}))\
+                row(cell(bf(tt(l)))cell(Invisible cursor {civis}))\
+            endtable())
+        dl(bf(tt(Ps = 30)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(scrollBar visisble))\
+                row(cell(bf(tt(l)))cell(scrollBar invisisble))\
+            endtable())
+        dl(bf(tt(Ps = 35)) (bf(rxvt)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Allow XTerm Shift+key sequences))\
+                row(cell(bf(tt(l)))cell(Disallow XTerm Shift+key sequences))\
+            endtable())
+        dl(bf(tt(Ps = 38)) em(unimplemented))
+            (Enter Tektronix Mode (DECTEK))
+        dl(bf(tt(Ps = 40)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Allow 80/132 Mode))\
+                row(cell(bf(tt(l)))cell(Disallow 80/132 Mode))\
+            endtable())
+        dl(bf(tt(Ps = 44)) em(unimplemented))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Turn On Margin Bell))\
+                row(cell(bf(tt(l)))cell(Turn Off Margin Bell))\
+            endtable())
+        dl(bf(tt(Ps = 45)) em(unimplemented))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Reverse-wraparound Mode))\
+                row(cell(bf(tt(l)))cell(No Reverse-wraparound Mode))\
+            endtable())
+        dl(bf(tt(Ps = 46)) em(unimplemented))
+            ()
+P()\
+        dl(bf(tt(Ps = 47)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Use Alternate Screen Buffer))\
+                row(cell(bf(tt(l)))cell(Use Normal Screen Buffer))\
+            endtable())
+label(Priv66)   
+        dl(bf(tt(Ps = 66)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Application Keypad (DECPAM) == \
+                    link(tt(ESC =))(ESCequals)))\
+                row(cell(bf(tt(l)))cell(Normal Keypad (DECPNM) == \
+                    link(tt(ESC >))(ESCequals)))\
+            endtable())
+        dl(bf(tt(Ps = 67)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Backspace key sends bf(tt(BS) \
+                   (DECBKM))))\
+                row(cell(bf(tt(l)))cell(Backspace key sends bf(tt(DEL))))\
+            endtable())
+        dl(bf(tt(Ps = 1000)) (X11 XTerm link(mouse reporting)(Mouse)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Send Mouse X & Y on button press and \
+                    release.))\
+                row(cell(bf(tt(l)))cell(No mouse reporting.))\
+            endtable())
+        dl(bf(tt(Ps = 1001)) (X11 XTerm link(mouse tracking)(Mouse)) \
+            em(unimplemented))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Use Hilite Mouse Tracking.))\
+                row(cell(bf(tt(l)))cell(No mouse reporting.))\
+            endtable())
+        dl(bf(tt(Ps = 1010)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Don't scroll to bottom on TTY output))\
+                row(cell(bf(tt(l)))cell(Scroll to bottom on TTY output))\
+            endtable())
+        dl(bf(tt(Ps = 1011)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Scroll to bottom when a key is \
+                   pressed))\
+                row(cell(bf(tt(l)))cell(Don't scroll to bottom when a key is \
+                    pressed))\
+            endtable())
+        dl(bf(tt(Ps = 1047)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Use Alternate Screen Buffer))\
+                row(cell(bf(tt(l)))cell(Use Normal Screen Buffer - clear \
+                   Alternate Screen Buffer if returning from it))\
+            endtable())
+        dl(bf(tt(Ps = 1048)))
+            (starttable(2)(l l)(0)\
+                row(cell(bf(tt(h)))cell(Save cursor position))\
+                row(cell(bf(tt(l)))cell(Restore cursor position))\
+            endtable())
+   enddl()
+enddl()
+    
diff --git a/doc/yodl/rxvtRef-sequences.yo b/doc/yodl/rxvtRef-sequences.yo
new file mode 100644 (file)
index 0000000..0cd8fda
--- /dev/null
@@ -0,0 +1,77 @@
+COMMENT(-- $Id: rxvtRef-sequences.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(Sequences)
+nsect(Escape Sequences)
+
+startdl()
+    dl(bf(tt(ESC # 8)))
+       (DEC Screen Alignment Test (DECALN))
+P()\
+    dl(bf(tt(ESC 7)nl()tt(ESC 8)))
+       (Save Cursor (SC)nl()Restore Cursor)\
+P()\
+label(ESCequals)
+    dl(bf(tt(ESC =)nl()tt(ESC >)))
+       (Application Keypad (SMKX) == link(tt(ESC[?66h))(Priv66)nl()\
+       Normal Keypad (RMKX) == link(tt(ESC[?66l))(Priv66))nl()\
+bf(Note:) If the numeric keypad is activated, eg, bf(Num_Lock) has been
+    pressed, numbers or control functions are generated by the numeric keypad
+    (see link(Key Codes)(KeyCodes))
+P()\
+    dl(bf(tt(ESC D)))
+       (Index (IND))
+P()\
+    dl(bf(tt(ESC E)))
+       (Next Line (NEL))
+P()\
+    dl(bf(tt(ESC H)))
+       (Tab Set (HTS))
+P()\
+    dl(bf(tt(ESC M)))
+       (Reverse Index (RI))
+P()\
+    dl(bf(tt(ESC N)))
+       (Single Shift Select of G2 Character Set (SS2): affects next character
+       only em(unimplemented))
+P()\
+    dl(bf(tt(ESC O)))
+       (Single Shift Select of G3 Character Set (SS3): affects next character
+       only em(unimplemented))
+P()\
+    dl(bf(tt(ESC Z)))
+       (Obsolete form of link(tt(ESC[c))(ESCOBPsc) nl()\
+       returns: bf(tt(ESC[?1;2C)) em(rxvt compile-time option))
+P()\
+    dl(bf(tt(ESC c)))
+       (Full reset (RIS))
+P()\
+    dl(bf(tt(ESC n)))
+       (Invoke the G2 Character Set (LS2))
+P()\
+    dl(bf(tt(ESC o)))
+       (Invoke the G3 Character Set (LS3))
+P()\
+    dl(bf(tt(ESC )CHAR(40)tt( C)nl()tt(ESC )CHAR(41)tt( C)nl()tt(ESC * C)nl()\
+       tt(ESC + C)nl()tt(ESC $ C)))
+       (Designate G0 Character Set (ISO 2022)nl()\
+       Designate G1 Character Set (ISO 2022)nl()\
+       Designate G2 Character Set (ISO 2022)nl()\
+       Designate G3 Character Set (ISO 2022)nl()\
+       Designate Kanji Character Set nl()\
+       em(where) bf(tt(C)) is nl()\
+       starttable(2)(l l)(0)\
+           row(cell(bf(tt(C = 0)))\
+               cell(DEC Special Character and Line Drawing Set))\
+           row(cell(bf(tt(C = A)))\
+               cell(United Kingdom (UK)))\
+           row(cell(bf(tt(C = B)))\
+               cell(United States (USASCII)))\
+           row(cell(bf(tt(C = <)))\
+               cell(Multinational character set em(unimplemented)))\
+           row(cell(bf(tt(C = 5)))\
+               cell(Finnish character set em(unimplemented)))\
+           row(cell(bf(tt(C = C)))\
+               cell(Finnish character set em(unimplemented)))\
+           row(cell(bf(tt(C = K)))\
+               cell(German character set em(unimplemented)))\
+       endtable())
+enddl()
diff --git a/doc/yodl/rxvtRef-values.yo b/doc/yodl/rxvtRef-values.yo
new file mode 100644 (file)
index 0000000..8b738f8
--- /dev/null
@@ -0,0 +1,41 @@
+COMMENT(-- $Id: rxvtRef-values.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(Values)
+nsect(Values)
+
+startdl()
+    dl(bf(tt(ENQ)))
+       (Enquiry (Ctrl-E) = Send Device Attributes (DA) nl()\
+       request attributes from terminal == link(ESC[Psc)(ESCOBPsc))
+P()\
+    dl(bf(tt(BEL)))
+       (Bell (Ctrl-G))
+P()\
+    dl(bf(tt(BS)))
+       (Backspace (Ctrl-H))
+P()\
+    dl(bf(tt(TAB)))
+       (Horizontal Tab (HT) (Ctrl-I))
+P()\
+    dl(bf(tt(LF)))
+       (Line Feed or New Line (NL) (Ctrl-J))
+P()\
+    dl(bf(tt(VT)))
+       (Vertical Tab (Ctrl-K) same as bf(tt(LF)))
+P()\
+    dl(bf(tt(FF)))
+       (Form Feed or New Page (NP) (Ctrl-L) same as bf(tt(LF)))
+P()\
+    dl(bf(tt(CR)))
+       (Carriage Return (Ctrl-M))
+P()\
+    dl(bf(tt(SO)))
+       (Shift Out (Ctrl-N), invokes the G1 character set. nl()\
+       Switch to Alternate Character Set)
+P()\
+    dl(bf(tt(SI)))
+       (Shift In (Ctrl-O), invokes the G0 character set (the default) nl()\
+       Switch to Standard Character Set)
+P()\
+    dl(bf(tt(SPC)))
+       (Space Character)
+enddl()
diff --git a/doc/yodl/rxvtRef-xpm.yo b/doc/yodl/rxvtRef-xpm.yo
new file mode 100644 (file)
index 0000000..37fcb92
--- /dev/null
@@ -0,0 +1,47 @@
+COMMENT(-- $Id: rxvtRef-xpm.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+label(XPM)
+nsect(XPM)
+
+For the XPM XTerm escape sequence bf(tt(ESC ] 20 ; Pt ST)) then value of
+bf(tt(Pt)) can be the name of the background pixmap followed by a sequence of
+scaling/positioning commands separated by semi-colons. The scaling/positioning
+commands are as follows:
+
+startdl()
+    dl(query scale/position)
+       (bf(?))
+P()\
+    dl(change scale and position)
+       (bf(WxH+X+Y)nl()\
+        bf(WxH+X) (== bf(WxH+X+X))nl()\
+        bf(WxH) (same as bf(WxH+50+50))nl()\
+        bf(W+X+Y) (same as bf(WxW+X+Y))nl()\
+        bf(W+X) (same as bf(WxW+X+X))nl()\
+        bf(W) (same as bf(WxW+50+50)))
+P()\
+    dl(change position (absolute))
+       (bf(=+X+Y)nl()\
+       bf(=+X) (same as bf(=+X+Y)))
+P()\
+    dl(change position (relative))
+       (bf(+X+Y)nl()\
+       bf(+X) (same as bf(+X+Y)))
+P()\
+    dl(rescale (relative))
+       (bf(Wx0) -> bf(W *= (W/100))nl()\
+       bf(0xH) -> bf(H *= (H/100)))
+enddl()
+
+For example:
+
+startdl()
+    dl(bf(\E]20;funky\a))
+       (load bf(funky.xpm) as a tiled image)
+P()\
+    dl(bf(\E]20;mona;100\a))
+       (load bf(mona.xpm) with a scaling of 100%)
+P()\
+    dl(bf(\E]20;;200;?\a))
+       (rescale the current pixmap to 200% and display the image geometry in \
+       the title)
+enddl()
diff --git a/doc/yodl/rxvtRef-xterm.yo b/doc/yodl/rxvtRef-xterm.yo
new file mode 100644 (file)
index 0000000..e8fc663
--- /dev/null
@@ -0,0 +1,67 @@
+COMMENT(-- $Id: rxvtRef-xterm.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+COMMENT(OSC: Operating System Commands)
+label(XTerm)
+nsect(XTerm Operating System Commands)
+
+startdl()
+    dl(bf(tt(ESC ] Ps;Pt ST)))
+       (Set XTerm Parameters nl()\
+       8-bit ST: 0x9c, nl()\
+       7-bit ST sequence: ESC \ (0x1b, 0x5c), nl()\
+       backwards compatible terminator BEL (0x07) is also accepted. nl()\
+       starttable(2)(l l)(0)\
+           row(cell(bf(tt(Ps = 0)))\
+               cell(Change Icon Name and Window Title to bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 1)))\
+               cell(Change Icon Name to bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 2)))\
+               cell(Change Window Title to bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 4)))\
+               cell(bf(tt(Pt)) is a semi-colon separated sequence of one \
+                   or more semi-colon separated bf(number)/bf(name) pairs, \
+                   where bf(number) is an index to a colour and bf(name) is \
+                   the name of a colour.  Each pair causes the bf(number)ed \
+                   colour to be changed to bf(name).  nl()\
+                   Numbers 0-7 corresponds to low-intensity (normal) colours \
+                   and 8-15 corresponds to high-intensity colours. \
+                   0=black, 1=red, 2=green, 3=yellow, 4=blue, 5=magenta, \
+                   6=cyan, 7=white))\
+           row(cell(bf(tt(Ps = 10)) bf((NB: may change in future)))\
+               cell(link(menuBar)(menuBar) command bf(tt(Pt)) \
+                   em(rxvt compile-time option)))\
+           row(cell(bf(tt(Ps = 12)))\
+               cell(Change colour of text cursor foreground to bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 13)))\
+               cell(Change colour of mouse foreground to bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 17)))\
+               cell(Change colour of highlight characters to bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 18)))\
+               cell(Change colour of bold characters to bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 19)))\
+               cell(Change colour of underlined characters to bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 20)))\
+               cell(Change default background link(pixmap)(XPM) to \
+                   bf(tt(Pt))))\
+           row(cell(bf(tt(Ps = 39)))\
+               cell(Change default foreground colour to bf(tt(Pt)) \
+                   em(rxvt compile-time option)))\
+           row(cell(bf(tt(Ps = 46)))\
+               cell(Change Log File to bf(tt(Pt)) \
+                   em(unimplemented)))\
+           row(cell(bf(tt(Ps = 49)))\
+               cell(Change default background colour to bf(tt(Pt)) \
+                   em(rxvt compile-time option)))\
+           row(cell(bf(tt(Ps = 50)))\
+               cell(Set Font to bf(tt(Pt)), with the following special \
+                   values of \
+                   bf(tt(Pt)) (bf(rxvt)) nl()\
+                   bf(tt(#+n)) change up bf(tt(n)) font(s) nl()\
+                   bf(tt(#-n)) change down bf(tt(n)) font(s) nl()\
+                   if bf(tt(n)) is missing of 0, a value of 1 is used nl()\
+                   em(empty) change to font0 nl()\
+                   bf(tt(n)) change to font bf(tt(n))))\
+           row(cell(bf(tt(Ps = 55)))\
+               cell(Log all scrollback buffer and all of screen to \
+                   bf(tt(Pt))))\
+       endtable())
+enddl()
diff --git a/doc/yodl/rxvtRef.yo b/doc/yodl/rxvtRef.yo
new file mode 100644 (file)
index 0000000..b733f16
--- /dev/null
@@ -0,0 +1,65 @@
+COMMENT(-- $Id: rxvtRef.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+mailto(gcw@pobox.com)
+htmlbodyopt(BGCOLOR)(#FFFFFF)
+notableofcontents()
+article(Rxvt Technical Reference)
+       (Geoff Wing (gcw@pobox.com))
+       (18 April 1998)
+label(toc)
+COMMENT(-----------------------------------------------------------------------
+-- Originally written: Mark Olesen, Fri Feb 14 14:16:00 1997
+-- Converted to yodl: Geoff Wing
+------------------------------------------------------------------------------)
+COMMENT(---
+  <meta name="Author" content="mj olesen <olesen@me.queensu.ca>">
+  <meta name="Description" content="Documentation of VT, XTerm, and other escape sequences used by rxvt.">
+---)
+includefile(masonyodl.yo)
+
+startit()
+    it()link(Definitions)(Definitions)
+    it()link(Values)(Values)
+    it()link(Escape Sequences)(Sequences)
+    it()link(CSI (Code Sequence Introducer) Sequences)(CSI)
+    it()link(DEC Private Modes)(PrivateModes)
+    it()link(XTerm Operating System Commands)(XTerm)
+    it()link(menuBar)(menuBar)
+    it()link(XPM)(XPM)
+    it()link(Mouse Reporting)(Mouse)
+    it()link(Special Graphics Mode)(Graphics)
+    it()link(Key Codes)(KeyCodes)
+endit()
+
+Reworked from XTerm documentation and other sources
+includefile(rxvtRef-definitions.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-values.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-sequences.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-csi.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-privatemodes.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-xterm.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-menubar.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-xpm.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-mouse.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-graphics.yo)
+link(Top)(toc)
+clearpage()
+includefile(rxvtRef-keycodes.yo)
+link(Top)(toc)
diff --git a/doc/yodl/versioninfo.yo.in b/doc/yodl/versioninfo.yo.in
new file mode 100644 (file)
index 0000000..7ba9234
--- /dev/null
@@ -0,0 +1,17 @@
+COMMENT(-- $Id: versioninfo.yo.in,v 1.1 2003-11-24 17:28:08 pcg Exp $ --)
+DEFINEMACRO(RXVTDATE)(0)
+       (@RXVT_DATE@)
+DEFINEMACRO(RXVTVERSION)(0)
+       (@RXVT_VERSION@)
+DEFINEMACRO(RXVTMAINT)(0)
+       (@RXVT_MAINT@)
+DEFINEMACRO(RXVTMAINTEMAIL)(0)
+       (@RXVT_MAINTEMAIL@)
+DEFINEMACRO(RXVTWEBMAINT)(0)
+       (@RXVT_WEBMAINT@)
+DEFINEMACRO(RXVTWEBMAINTEMAIL)(0)
+       (@RXVT_WEBMAINTEMAIL@)
+DEFINEMACRO(RXVTWEBPAGE)(0)
+       (@RXVT_WEBPAGE@)
+DEFINEMACRO(RXVTFTPSITE)(0)
+       (ftp://@RXVT_FTPSITENAME@@RXVT_FTPSITEDIR@)
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644 (file)
index 0000000..3228dba
--- /dev/null
@@ -0,0 +1,235 @@
+# $Id: Makefile.in,v 1.1 2003-11-24 17:28:08 pcg Exp $
+@MCOMMON@
+
+LINT = lint -DNARROWPROTO=1 $(XINC) -chapbxz
+
+srcdir =       @srcdir@
+VPATH =                @srcdir@
+.PATH:         @srcdir@
+
+top_builddir = ..
+basedir = ..
+thisdir = src
+MKDIR = @top_srcdir@/autoconf/mkinstalldirs
+
+SUPLIB = -lsupc++
+
+# for developers: the following debug options may be used
+#      -DDEBUG_CMD -DDEBUG_MAIN -DDEBUG_MENU -DDEBUG_MENUARROWS
+#      -DDEBUG_MENUBAR_STACKING -DDEBUG_MENU_LAYOUT -DDEBUG_RESOURCES
+#      -DDEBUG_SCREEN -DDEBUG_SEARCH_PATH -DDEBUG_SELECT -DDEBUG_SIZE
+#      -DDEBUG_TTY -DDEBUG_TTYMODE -DDEBUG_X
+DEBUG=-DDEBUG_STRICT @DEBUG@
+
+first_rule: all
+dummy:
+
+LIBSRCS = command.C defaultfont.C graphics.C grkelot.C init.C logging.C \
+       main.C menubar.C misc.C netdisp.C ptytty.C screen.C scrollbar.C \
+       scrollbar-rxvt.C scrollbar-next.C scrollbar-xterm.C strings.C \
+       xdefaults.C xpm.C encoding.C rxvtcolor.C rxvtvec.C
+
+SRCS =  rxvt.C $(LIBSRCS)
+
+HDRS = command.h defaultfont.h feature.h grkelot.h init.h logging.h \
+       menubar.h netdisp.h protos.h rxvt.h rxvtgrx.h version.h encoding.h rxvtvec.h
+
+EXTRAHDRS = rxvtlib.h rxvtdaemon.h
+
+OBJS = command.o defaultfont.o init.o graphics.o grkelot.o logging.o \
+       main.o menubar.o misc.o netdisp.o ptytty.o screen.o \
+       scrollbar.o scrollbar-next.o scrollbar-rxvt.o scrollbar-xterm.o \
+       strings.o xdefaults.o xpm.o rxvt.o encoding.o rxvtcolor.o rxvtvec.o
+LIBOBJS = command.lo defaultfont.lo init.lo graphics.lo grkelot.lo logging.lo \
+       main.lo menubar.lo misc.lo netdisp.lo ptytty.lo screen.lo \
+       scrollbar.lo scrollbar-next.lo scrollbar-rxvt.lo scrollbar-xterm.lo \
+       strings.lo xdefaults.lo xpm.lo encoding.lo rxvt.lo rxvtcolor.lo rxvtvec.lo
+
+LIBVERSION = @LIBVERSION@
+INSTALL_LIBRXVT = @INSTALL_LIBRXVT@
+
+RXVT_BASENAME=`$(ECHO) $(RXVTNAME)|$(SED) 's/$(EXEEXT)$$//'|$(SED) '$(transform)'`
+RXVT_BINNAME=$(DESTDIR)$(bindir)/$(RXVT_BASENAME)$(EXEEXT)
+RXVT_VERNAME=$(DESTDIR)$(bindir)/$(RXVT_BASENAME)-$(VERSION)$(EXEEXT)
+RXVT_OLDNAME=$(DESTDIR)$(bindir)/$(RXVT_BASENAME)-old$(EXEEXT)
+
+EXTPROS = command.extpro defaultfont.extpro graphics.extpro grkelot.extpro \
+       init.extpro logging.extpro main.extpro menubar.extpro misc.extpro \
+       netdisp.extpro ptytty.extpro screen.extpro scrollbar.extpro \
+       scrollbar-rxvt.extpro scrollbar-next.extpro scrollbar-xterm.extpro \
+       strings.extpro xdefaults.extpro xpm.extpro
+
+INTPROS = command.intpro defaultfont.intpro graphics.intpro grkelot.intpro \
+       init.intpro logging.intpro main.intpro menubar.intpro misc.intpro \
+       netdisp.intpro ptytty.intpro screen.intpro scrollbar.intpro \
+       scrollbar-rxvt.intpro scrollbar-next.intpro scrollbar-xterm.intpro \
+       strings.intpro xdefaults.intpro xpm.intpro
+
+DEPS =  rxvt.h rxvtlib.h ${basedir}/config.h feature.h .protos
+
+#
+# Distribution variables
+#
+
+DIST = $(HDRS) $(SRCS) Makefile.in gcc-Wall rxvtlib.h.in .indent.pro \
+       makeintprotos-awk makeextprotos-awk $(INTPROS) $(EXTPROS) .protos
+
+.SUFFIXES:     .C .o .extpro .intpro .lo
+
+#-------------------------------------------------------------------------
+# inference rules
+.C.o:
+       $(COMPILE) -c $<
+
+.C.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.C.intpro:
+       @$(RMF) $@.tmp
+       @$(AWK) -f $(srcdir)/makeintprotos-awk $< > $@.tmp
+       @if $(CMP) -s $@ $@.tmp ; then : ; else $(ECHO) "$(AWK) -f $(srcdir)/makeintprotos-awk $< > $@"; $(CP) $@.tmp $@; fi
+       @$(RMF) $@.tmp
+
+.C.extpro:
+       @$(RMF) $@.tmp
+       @$(AWK) -f $(srcdir)/makeextprotos-awk $< > $@.tmp
+       @if $(CMP) -s $@ $@.tmp ; then : ; else $(ECHO) "$(AWK) -f $(srcdir)/makeextprotos-awk $< > $@"; $(CP) $@.tmp $@; fi
+       @$(RMF) $@.tmp
+#-------------------------------------------------------------------------
+all: allbin
+
+rxvt: version.h rxvt.o librxvt.la
+       $(LIBTOOL) --mode=link $(LINK) rxvt.o librxvt.la $(LIBS) $(XLIB) $(DLIB) $(SUPLIB) -o $@
+
+rxvtd: version.h rxvtd.o librxvt.la iom.o rxvtdaemon.o
+       $(LIBTOOL) --mode=link $(LINK) rxvtd.o rxvtdaemon.o iom.o librxvt.la $(LIBS) $(XLIB) $(DLIB) $(SUPLIB) -o $@
+
+rxvtc: version.h rxvtc.o rxvtdaemon.o
+       $(LIBTOOL) --mode=link $(LINK) rxvtc.o rxvtdaemon.o $(LIBS) $(DLIB) $(SUPLIB) -o $@
+
+.protos: $(EXTPROS)
+       @$(RMF) .protos
+       date >.protos
+
+librxvt.la: $(LIBOBJS)
+       $(LIBTOOL) --mode=link $(LINK) -rpath $(libdir) -version-info $(LIBVERSION) $(LIBOBJS) $(LIBS) $(SUPLIB) -o $@
+#-------------------------------------------------------------------------
+tags: $(SRCS) $(HDRS) $(EXTRAHDRS)
+       ctags $(SRCS) $(HDRS) $(EXTRAHDRS)
+
+allbin: .protos rxvt rxvtd rxvtc
+
+alldoc:
+
+clean:
+       $(RMF) rxvt core a.out *.o *.lo *.bak *~ *.intpro *.extpro .libs/* librxvt.la tmpproto .protos *.tmp
+
+realclean: clean
+       $(RMF) tags librxvt.h
+
+cleandir: realclean
+
+distclean: realclean
+       if test $(srcdir) = .; then $(MAKE) realclean; fi
+       (cd $(srcdir); $(RMF) Makefile)
+
+install: allbin alldoc
+       $(MKDIR) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir)
+       @if test x$(INSTALL_LIBRXVT) = xyes; then \
+           $(ECHO) "$(LIBTOOL) --mode=install $(INSTALL_DATA) rxvtlib.h $(DESTDIR)$(includedir)/rxvtlib.h"; \
+           $(LIBTOOL) --mode=install $(INSTALL_DATA) rxvtlib.h $(DESTDIR)$(includedir)/rxvtlib.h; \
+           $(ECHO) "$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) librxvt.la $(DESTDIR)$(libdir)/librxvt.la"; \
+           $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) librxvt.la $(DESTDIR)$(libdir)/librxvt.la; \
+       fi
+       @if test -f $(RXVT_BINNAME); then \
+           $(ECHO) "$(RMF) $(RXVT_OLDNAME)"; \
+           $(RMF) $(RXVT_OLDNAME); \
+           $(ECHO) "$(MV) $(RXVT_BINNAME) $(RXVT_OLDNAME)"; \
+           $(MV) $(RXVT_BINNAME) $(RXVT_OLDNAME); \
+       fi
+       @$(ECHO) "$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) rxvt $(RXVT_VERNAME)"
+       @$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) rxvt $(RXVT_VERNAME)
+       @$(ECHO) "$(LN) $(RXVT_VERNAME) $(RXVT_BINNAME)"
+       @$(LN) $(RXVT_VERNAME) $(RXVT_BINNAME)
+
+uninstall:
+       @$(ECHO) $(RMF) $(RXVT_VERNAME)
+       @$(RMF) $(RXVT_VERNAME)
+       @$(ECHO) "$(LIBTOOL) --mode=uninstall $(RMF) $(RXVT_BINNAME)"
+       @$(LIBTOOL) --mode=uninstall $(RMF) $(RXVT_BINNAME)
+       @if test x$(INSTALL_LIBRXVT) = xyes; then \
+           $(ECHO) "$(LIBTOOL) --mode=uninstall $(RMF) $(DESTDIR)$(libdir)/librxvt.la"; \
+           $(LIBTOOL) --mode=uninstall $(RMF) $(DESTDIR)$(libdir)/librxvt.la; \
+           $(ECHO) "$(LIBTOOL) --mode=uninstall $(RMF) $(DESTDIR)$(includedir)/rxvtlib.h"; \
+           $(LIBTOOL) --mode=uninstall $(RMF) $(DESTDIR)$(includedir)/rxvtlib.h; \
+       fi
+
+distdirs:
+       mkdir $(basedir)/../$(VERNAME)/$(thisdir)
+
+distcopy: .protos $(INTPROS)
+       $(CP) -p $(DIST) $(basedir)/../$(VERNAME)/$(thisdir)
+
+# -----------------------------------------------------------------------
+# DO NOT DELETE: nice dependency list follows
+#
+
+defaultfont.h: encoding.h rxvtvec.h
+rxvtlib.h: rxvtcolor.h defaultfont.h
+
+command.o:          command.C   $(DEPS) command.intpro command.h version.h
+defaultfont.o:      defaultfont.C $(DEPS) defaultfont.intpro defaultfont.h
+graphics.o:         graphics.C  $(DEPS) graphics.intpro
+grkelot.o:          grkelot.C   $(DEPS) grkelot.intpro grkelot.h
+init.o:             init.C      $(DEPS) init.intpro    init.h  defaultfont.h
+logging.o:          logging.C   $(DEPS) logging.intpro logging.h
+main.o:             main.C      $(DEPS) main.intpro
+menubar.o:          menubar.C   $(DEPS) menubar.intpro menubar.h version.h
+misc.o:             misc.C      $(DEPS) misc.intpro
+netdisp.o:          netdisp.C   $(DEPS) netdisp.intpro netdisp.h
+ptytty.o:           ptytty.C    $(DEPS) ptytty.intpro
+rxvt.o:             rxvt.C      $(DEPS) 
+rxvtd.o:            rxvtd.C     $(DEPS) rxvtdaemon.h
+screen.o:           screen.C    $(DEPS) screen.intpro  defaultfont.h
+scrollbar.o:        scrollbar.C $(DEPS) scrollbar.intpro
+scrollbar-rxvt.o:   scrollbar-rxvt.C  $(DEPS) scrollbar-rxvt.intpro
+scrollbar-next.o:   scrollbar-next.C  $(DEPS) scrollbar-next.intpro
+scrollbar-xterm.o:  scrollbar-xterm.C $(DEPS) scrollbar-xterm.intpro
+strings.o:          strings.C   $(DEPS) strings.intpro
+xdefaults.o:        xdefaults.C $(DEPS) xdefaults.intpro         version.h
+xpm.o:              xpm.C       $(DEPS) xpm.intpro
+encoding.o:         encoding.C $(DEPS) encoding.h
+rxvtcolor.o:        rxvtcolor.C        $(DEPS)
+
+command.lo:         command.C   $(DEPS) command.intpro command.h version.h
+defaultfont.lo:     defaultfont.C $(DEPS) defaultfont.intpro defaultfont.h encoding.h
+graphics.lo:        graphics.C  $(DEPS) graphics.intpro        defaultfont.h
+grkelot.lo:         grkelot.C   $(DEPS) grkelot.intpro grkelot.h
+init.lo:            init.C      $(DEPS) init.intpro    init.h  
+logging.lo:         logging.C   $(DEPS) logging.intpro logging.h
+main.lo:            main.C      $(DEPS) main.intpro
+menubar.lo:         menubar.C   $(DEPS) menubar.intpro menubar.h version.h
+misc.lo:            misc.C      $(DEPS) misc.intpro
+netdisp.lo:         netdisp.C   $(DEPS) netdisp.intpro netdisp.h
+ptytty.lo:          ptytty.C    $(DEPS) ptytty.intpro
+rxvt.lo:            rxvt.C      $(DEPS) 
+screen.lo:          screen.C    $(DEPS) screen.intpro  defaultfont.h
+scrollbar.lo:       scrollbar.C $(DEPS) scrollbar.intpro
+scrollbar-rxvt.lo:  scrollbar-rxvt.C  $(DEPS) scrollbar-rxvt.intpro
+scrollbar-next.lo:  scrollbar-next.C  $(DEPS) scrollbar-next.intpro
+scrollbar-xterm.lo: scrollbar-xterm.C $(DEPS) scrollbar-xterm.intpro
+strings.lo:         strings.C   $(DEPS) strings.intpro
+xdefaults.lo:       xdefaults.C $(DEPS) xdefaults.intpro         version.h
+xpm.lo:             xpm.C       $(DEPS) xpm.intpro
+encoding.lo:        encoding.C $(DEPS) encoding.h
+rxvtcolor.lo:       rxvtcolor.C        $(DEPS)
+
+iom.o:              iom.C              iom.h
+rxvtdaemon.o:       rxvtdaemon.C       rxvtdaemon.h
+
diff --git a/src/command.C b/src/command.C
new file mode 100644 (file)
index 0000000..7201dfc
--- /dev/null
@@ -0,0 +1,3583 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       command.c
+ *----------------------------------------------------------------------*
+ * $Id: command.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1992      John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
+ *                             - original version
+ * Copyright (c) 1994      Robert Nation <nation@rocket.sanders.lockheed.com>
+ *                             - extensive modifications
+ * Copyright (c) 1995      Garrett D'Amore <garrett@netcom.com>
+ *                             - vt100 printing
+ * Copyright (c) 1995      Steven Hirsch <hirsch@emba.uvm.edu>
+ *                             - X11 mouse report mode and support for
+ *                               DEC "private mode" save/restore functions.
+ * Copyright (c) 1995      Jakub Jelinek <jj@gnu.ai.mit.edu>
+ *                             - key-related changes to handle Shift+function
+ *                               keys properly.
+ * Copyright (c) 1997      MJ Olesen <olesen@me.queensu.ca>
+ *                             - extensive modifications
+ * Copyright (c) 1997      Raul Garcia Garcia <rgg@tid.es>
+ *                             - modification and cleanups for Solaris 2.x
+ *                               and Linux 1.2.x
+ * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
+ * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
+ *                             - extensive modifications
+ * Copyright (c) 1998      Alfredo K. Kojima <kojima@windowmaker.org>
+ * Copyright (c) 2001      Marius Gedminas
+ *                             - Ctrl/Mod4+Tab works like Meta+Tab (options)
+ * Copyright (c) 2003      Rob McMullen <robm@flipturn.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+
+/*{{{ includes: */
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "version.h"
+#include "command.h"
+
+/*----------------------------------------------------------------------*/
+
+/*{{{ Convert the keypress event into a string */
+/* INTPROTO */
+void
+rxvt_lookup_key(pR_ XKeyEvent *ev)
+{
+    int             ctrl, meta, shft, len;
+    unsigned int    newlen;
+    KeySym          keysym;
+#ifdef DEBUG_CMD
+    static int      debug_key = 1;     /* accessible by a debugger only */
+#endif
+#ifdef USE_XIM
+    int             valid_keysym;
+#endif
+    unsigned char  *kbuf = R->h->kbuf;
+
+/*
+ * use Num_Lock to toggle Keypad on/off.  If Num_Lock is off, allow an
+ * escape sequence to toggle the Keypad.
+ *
+ * Always permit `shift' to override the current setting
+ */
+    shft = (ev->state & ShiftMask);
+    ctrl = (ev->state & ControlMask);
+    meta = (ev->state & R->h->ModMetaMask);
+    if (R->numlock_state || (ev->state & R->h->ModNumLockMask)) {
+       R->numlock_state = (ev->state & R->h->ModNumLockMask);
+       PrivMode((!R->numlock_state), PrivMode_aplKP);
+    }
+#ifdef USE_XIM
+    if (R->h->Input_Context != NULL) {
+       Status          status_return;
+
+       kbuf[0] = '\0';
+#ifdef X_HAVE_UTF8_STRING
+       len = Xutf8LookupString(R->h->Input_Context, ev, (char *)kbuf,
+                             KBUFSZ, &keysym, &status_return);
+#else
+       len = XmbLookupString(R->h->Input_Context, ev, (char *)kbuf,
+                             KBUFSZ, &keysym, &status_return);
+#endif
+       valid_keysym = ((status_return == XLookupKeySym)
+                       || (status_return == XLookupBoth));
+    } else {
+       len = XLookupString(ev, (char *)kbuf, KBUFSZ, &keysym,
+                           &R->h->compose);
+       valid_keysym = 1;
+    }
+#else                          /* USE_XIM */
+    len = XLookupString(ev, (char *)kbuf, KBUFSZ, &keysym,
+                       &R->h->compose);
+/*
+ * map unmapped Latin[2-4]/Katakana/Arabic/Cyrillic/Greek entries -> Latin1
+ * good for installations with correct fonts, but without XLOCALE
+ */
+    if (!len) {
+       if ((keysym >= 0x0100) && (keysym < 0x0800)) {
+           kbuf[0] = (keysym & 0xFF);
+           kbuf[1] = '\0';
+           len = 1;
+       } else
+           kbuf[0] = '\0';
+    }
+#endif                         /* USE_XIM */
+
+#ifdef USE_XIM
+    if (valid_keysym)
+#endif
+    {
+/* for some backwards compatibility */
+#if defined(HOTKEY_CTRL) || defined(HOTKEY_META)
+# ifdef HOTKEY_CTRL
+       if (ctrl) {
+# else
+       if (meta) {
+# endif
+           if (keysym == R->h->ks_bigfont) {
+               rxvt_change_font(aR_ 0, FONT_UP);
+               return;
+           } else if (keysym == R->h->ks_smallfont) {
+               rxvt_change_font(aR_ 0, FONT_DN);
+               return;
+           }
+       }
+#endif
+
+       if (R->TermWin.saveLines) {
+#ifdef UNSHIFTED_SCROLLKEYS
+           if (!ctrl && !meta) {
+#else
+           if (IS_SCROLL_MOD) {
+#endif
+               int             lnsppg;
+
+#ifdef PAGING_CONTEXT_LINES
+               lnsppg = R->TermWin.nrow - PAGING_CONTEXT_LINES;
+#else
+               lnsppg = R->TermWin.nrow * 4 / 5;
+#endif
+               if (keysym == XK_Prior) {
+                   rxvt_scr_page(aR_ UP, lnsppg);
+                   return;
+               } else if (keysym == XK_Next) {
+                   rxvt_scr_page(aR_ DN, lnsppg);
+                   return;
+               }
+           }
+#ifdef SCROLL_ON_UPDOWN_KEYS
+           if (IS_SCROLL_MOD) {
+               if (keysym == XK_Up) {
+                   rxvt_scr_page(aR_ UP, 1);
+                   return;
+               } else if (keysym == XK_Down) {
+                   rxvt_scr_page(aR_ DN, 1);
+                   return;
+               }
+           }
+#endif
+#ifdef SCROLL_ON_HOMEEND_KEYS
+           if (IS_SCROLL_MOD) {
+               if (keysym == XK_Home) {
+                   rxvt_scr_move_to(aR_ 0, 1);
+                   return;
+               } else if (keysym == XK_End) {
+                   rxvt_scr_move_to(aR_ 1, 0);
+                   return;
+               }
+           }
+#endif
+       }
+
+       if (shft) {
+       /* Shift + F1 - F10 generates F11 - F20 */
+           if (keysym >= XK_F1 && keysym <= XK_F10) {
+               keysym += (XK_F11 - XK_F1);
+               shft = 0;       /* turn off Shift */
+           } else if (!ctrl && !meta && (R->h->PrivateModes & PrivMode_ShiftKeys)) {
+               switch (keysym) {
+               /* normal XTerm key bindings */
+               case XK_Insert: /* Shift+Insert = paste mouse selection */
+                   rxvt_selection_request(aR_ ev->time, 0, 0);
+                   return;
+               /* rxvt extras */
+               case XK_KP_Add: /* Shift+KP_Add = bigger font */
+                   rxvt_change_font(aR_ 0, FONT_UP);
+                   return;
+               case XK_KP_Subtract:    /* Shift+KP_Subtract = smaller font */
+                   rxvt_change_font(aR_ 0, FONT_DN);
+                   return;
+               }
+           }
+       }
+#ifdef PRINTPIPE
+       if (keysym == XK_Print) {
+           rxvt_scr_printscreen(aR_ ctrl | shft);
+           return;
+       }
+#endif
+#ifdef GREEK_SUPPORT
+       if (keysym == R->h->ks_greekmodeswith) {
+           R->h->greek_mode = !R->h->greek_mode;
+           if (R->h->greek_mode) {
+               rxvt_xterm_seq(aR_ XTerm_title,
+                              (greek_getmode() == GREEK_ELOT928
+                               ? "[Greek: iso]" : "[Greek: ibm]"), CHAR_ST);
+               greek_reset();
+           } else
+               rxvt_xterm_seq(aR_ XTerm_title, APL_NAME "-" VERSION, CHAR_ST);
+           return;
+       }
+#endif
+
+       if (keysym >= 0xFF00 && keysym <= 0xFFFF) {
+#ifdef KEYSYM_RESOURCE
+           if (!(shft | ctrl) && R->h->Keysym_map[keysym & 0xFF] != NULL) {
+               unsigned int    l;
+               const unsigned char *kbuf0;
+               const unsigned char ch = C0_ESC;
+
+               kbuf0 = (R->h->Keysym_map[keysym & 0xFF]);
+               l = (unsigned int)*kbuf0++;
+
+           /* escape prefix */
+               if (meta)
+# ifdef META8_OPTION
+                   if (R->h->meta_char == C0_ESC)
+# endif
+                       rxvt_tt_write(aR_ &ch, 1);
+               rxvt_tt_write(aR_ kbuf0, l);
+               return;
+           } else
+#endif
+           {
+               newlen = 1;
+               switch (keysym) {
+#ifndef NO_BACKSPACE_KEY
+               case XK_BackSpace:
+                   if (R->h->PrivateModes & PrivMode_HaveBackSpace) {
+                       kbuf[0] = (!!(R->h->PrivateModes & PrivMode_BackSpace)
+                                  ^ !!ctrl) ? '\b' : '\177';
+                       kbuf[1] = '\0';
+                   } else
+                       STRCPY(kbuf, R->h->key_backspace);
+# ifdef MULTICHAR_SET
+                   if ((R->Options & Opt_mc_hack) && R->screen.cur.col > 0) {
+                       int             col, row;
+
+                       newlen = STRLEN(kbuf);
+                       col = R->screen.cur.col - 1;
+                       row = R->screen.cur.row + R->TermWin.saveLines;
+                       if (IS_MULTI2(R->screen.rend[row][col]))
+                           MEMMOVE(kbuf + newlen, kbuf, newlen + 1);
+                   }
+# endif
+                   break;
+#endif
+#ifndef NO_DELETE_KEY
+               case XK_Delete:
+                   STRCPY(kbuf, R->h->key_delete);
+# ifdef MULTICHAR_SET
+                   if (R->Options & Opt_mc_hack) {
+                       int             col, row;
+                       newlen = STRLEN(kbuf);
+                       col = R->screen.cur.col;
+                       row = R->screen.cur.row + R->TermWin.saveLines;
+                       if (IS_MULTI1(R->screen.rend[row][col]))
+                           MEMMOVE(kbuf + newlen, kbuf, newlen + 1);
+                   }
+# endif
+                   break;
+#endif
+               case XK_Tab:
+                   if (shft)
+                       STRCPY(kbuf, "\033[Z");
+                   else {
+#ifdef CTRL_TAB_MAKES_META
+                       if (ctrl)
+                           meta = 1;
+#endif
+#ifdef MOD4_TAB_MAKES_META
+                       if (ev->state & Mod4Mask)
+                           meta = 1;
+#endif
+                       newlen = 0;
+                   }
+                   break;
+
+
+#ifdef XK_KP_Left
+               case XK_KP_Up:          /* \033Ox or standard */
+               case XK_KP_Down:        /* \033Or or standard */
+               case XK_KP_Right:       /* \033Ov or standard */
+               case XK_KP_Left:        /* \033Ot or standard */
+                   if ((R->h->PrivateModes & PrivMode_aplKP) ? !shft : shft) {
+                       STRCPY(kbuf, "\033OZ");
+                       kbuf[2] = ("txvr"[keysym - XK_KP_Left]);
+                       break;
+                   } else
+                   /* translate to std. cursor key */
+                       keysym = XK_Left + (keysym - XK_KP_Left);
+               /* FALLTHROUGH */
+#endif
+               case XK_Up:     /* "\033[A" */
+               case XK_Down:   /* "\033[B" */
+               case XK_Right:  /* "\033[C" */
+               case XK_Left:   /* "\033[D" */
+                   STRCPY(kbuf, "\033[Z");
+                   kbuf[2] = ("DACB"[keysym - XK_Left]);
+               /* do Shift first */
+                   if (shft)
+                       kbuf[2] = ("dacb"[keysym - XK_Left]);
+                   else if (ctrl) {
+                       kbuf[1] = 'O';
+                       kbuf[2] = ("dacb"[keysym - XK_Left]);
+                   } else if (R->h->PrivateModes & PrivMode_aplCUR)
+                       kbuf[1] = 'O';
+#ifdef MULTICHAR_SET
+                    //TODO: ??
+                   if (R->Options & Opt_mc_hack) {
+                       int             col, row, m;
+
+                       col = R->screen.cur.col;
+                       row = R->screen.cur.row + R->TermWin.saveLines;
+                       m = 0;
+                       if (keysym == XK_Right
+                           && IS_MULTI1(R->screen.rend[row][col]))
+                           m = 1;
+                       else if (keysym == XK_Left) {
+                           if (col > 0) {
+                               if (IS_MULTI2(R->screen.rend[row][col - 1]))
+                                   m = 1;
+                           } else if (R->screen.cur.row > 0) {
+                               col = R->screen.tlen[--row];
+                               if (col == -1)
+                                   col = R->TermWin.ncol - 1;
+                               else
+                                   col--;
+                               if (col > 0
+                                   && IS_MULTI2(R->screen.rend[row][col]))
+                                   m = 1;
+                           }
+                       }
+                       if (m)
+                           MEMMOVE(kbuf + 3, kbuf, 3 + 1);
+                   }
+#endif
+                   break;
+
+#ifndef UNSHIFTED_SCROLLKEYS
+# ifdef XK_KP_Prior
+               case XK_KP_Prior:
+               /* allow shift to override */
+                   if ((R->h->PrivateModes & PrivMode_aplKP) ? !shft : shft) {
+                       STRCPY(kbuf, "\033Oy");
+                       break;
+                   }
+               /* FALLTHROUGH */
+# endif
+               case XK_Prior:
+                   STRCPY(kbuf, "\033[5~");
+                   break;
+# ifdef XK_KP_Next
+               case XK_KP_Next:
+               /* allow shift to override */
+                   if ((R->h->PrivateModes & PrivMode_aplKP) ? !shft : shft) {
+                       STRCPY(kbuf, "\033Os");
+                       break;
+                   }
+               /* FALLTHROUGH */
+# endif
+               case XK_Next:
+                   STRCPY(kbuf, "\033[6~");
+                   break;
+#endif
+               case XK_KP_Enter:
+               /* allow shift to override */
+                   if ((R->h->PrivateModes & PrivMode_aplKP) ? !shft : shft) {
+                       STRCPY(kbuf, "\033OM");
+                   } else {
+                       kbuf[0] = '\r';
+                       kbuf[1] = '\0';
+                   }
+                   break;
+
+#ifdef XK_KP_Begin
+               case XK_KP_Begin:
+                   STRCPY(kbuf, "\033Ou");
+                   break;
+
+               case XK_KP_Insert:
+                   STRCPY(kbuf, "\033Op");
+                   break;
+
+               case XK_KP_Delete:
+                   STRCPY(kbuf, "\033On");
+                   break;
+#endif
+               case XK_KP_F1:  /* "\033OP" */
+               case XK_KP_F2:  /* "\033OQ" */
+               case XK_KP_F3:  /* "\033OR" */
+               case XK_KP_F4:  /* "\033OS" */
+                   STRCPY(kbuf, "\033OP");
+                   kbuf[2] += (keysym - XK_KP_F1);
+                   break;
+
+               case XK_KP_Multiply:    /* "\033Oj" : "*" */
+               case XK_KP_Add:         /* "\033Ok" : "+" */
+               case XK_KP_Separator:   /* "\033Ol" : "," */
+               case XK_KP_Subtract:    /* "\033Om" : "-" */
+               case XK_KP_Decimal:     /* "\033On" : "." */
+               case XK_KP_Divide:      /* "\033Oo" : "/" */
+               case XK_KP_0:           /* "\033Op" : "0" */
+               case XK_KP_1:           /* "\033Oq" : "1" */
+               case XK_KP_2:           /* "\033Or" : "2" */
+               case XK_KP_3:           /* "\033Os" : "3" */
+               case XK_KP_4:           /* "\033Ot" : "4" */
+               case XK_KP_5:           /* "\033Ou" : "5" */
+               case XK_KP_6:           /* "\033Ov" : "6" */
+               case XK_KP_7:           /* "\033Ow" : "7" */
+               case XK_KP_8:           /* "\033Ox" : "8" */
+               case XK_KP_9:           /* "\033Oy" : "9" */
+               /* allow shift to override */
+                   if ((R->h->PrivateModes & PrivMode_aplKP) ? !shft : shft) {
+                       STRCPY(kbuf, "\033Oj");
+                       kbuf[2] += (keysym - XK_KP_Multiply);
+                   } else {
+                       kbuf[0] = ('*' + (keysym - XK_KP_Multiply));
+                       kbuf[1] = '\0';
+                   }
+                   break;
+
+               case XK_Find:
+                   STRCPY(kbuf, "\033[1~");
+                   break;
+               case XK_Insert:
+                   STRCPY(kbuf, "\033[2~");
+                   break;
+#ifdef DXK_Remove              /* support for DEC remove like key */
+               case DXK_Remove:
+               /* FALLTHROUGH */
+#endif
+               case XK_Execute:
+                   STRCPY(kbuf, "\033[3~");
+                   break;
+               case XK_Select:
+                   STRCPY(kbuf, "\033[4~");
+                   break;
+#ifdef XK_KP_End
+               case XK_KP_End:
+               /* allow shift to override */
+                   if ((R->h->PrivateModes & PrivMode_aplKP) ? !shft : shft) {
+                       STRCPY(kbuf, "\033Oq");
+                       break;
+                   }
+               /* FALLTHROUGH */
+#endif
+               case XK_End:
+                   STRCPY(kbuf, KS_END);
+                   break;
+#ifdef XK_KP_Home
+               case XK_KP_Home:
+               /* allow shift to override */
+                   if ((R->h->PrivateModes & PrivMode_aplKP) ? !shft : shft) {
+                       STRCPY(kbuf, "\033Ow");
+                       break;
+                   }
+               /* FALLTHROUGH */
+#endif
+               case XK_Home:
+                   STRCPY(kbuf, KS_HOME);
+                   break;
+
+#define FKEY(n, fkey)                                                  \
+    sprintf((char *)kbuf,"\033[%2d~", (int)((n) + (keysym - fkey)))
+
+               case XK_F1:     /* "\033[11~" */
+               case XK_F2:     /* "\033[12~" */
+               case XK_F3:     /* "\033[13~" */
+               case XK_F4:     /* "\033[14~" */
+               case XK_F5:     /* "\033[15~" */
+                   FKEY(11, XK_F1);
+                   break;
+               case XK_F6:     /* "\033[17~" */
+               case XK_F7:     /* "\033[18~" */
+               case XK_F8:     /* "\033[19~" */
+               case XK_F9:     /* "\033[20~" */
+               case XK_F10:    /* "\033[21~" */
+                   FKEY(17, XK_F6);
+                   break;
+               case XK_F11:    /* "\033[23~" */
+               case XK_F12:    /* "\033[24~" */
+               case XK_F13:    /* "\033[25~" */
+               case XK_F14:    /* "\033[26~" */
+                   FKEY(23, XK_F11);
+                   break;
+               case XK_F15:    /* "\033[28~" */
+               case XK_F16:    /* "\033[29~" */
+                   FKEY(28, XK_F15);
+                   break;
+               case XK_Help:   /* "\033[28~" */
+                   FKEY(28, XK_Help);
+                   break;
+               case XK_Menu:   /* "\033[29~" */
+                   FKEY(29, XK_Menu);
+                   break;
+               case XK_F17:    /* "\033[31~" */
+               case XK_F18:    /* "\033[32~" */
+               case XK_F19:    /* "\033[33~" */
+               case XK_F20:    /* "\033[34~" */
+               case XK_F21:    /* "\033[35~" */
+               case XK_F22:    /* "\033[36~" */
+               case XK_F23:    /* "\033[37~" */
+               case XK_F24:    /* "\033[38~" */
+               case XK_F25:    /* "\033[39~" */
+               case XK_F26:    /* "\033[40~" */
+               case XK_F27:    /* "\033[41~" */
+               case XK_F28:    /* "\033[42~" */
+               case XK_F29:    /* "\033[43~" */
+               case XK_F30:    /* "\033[44~" */
+               case XK_F31:    /* "\033[45~" */
+               case XK_F32:    /* "\033[46~" */
+               case XK_F33:    /* "\033[47~" */
+               case XK_F34:    /* "\033[48~" */
+               case XK_F35:    /* "\033[49~" */
+                   FKEY(31, XK_F17);
+                   break;
+#undef FKEY
+               default:
+                   newlen = 0;
+                   break;
+               }
+               if (newlen)
+                   len = STRLEN(kbuf);
+           }
+       /*
+        * Pass meta for all function keys, if 'meta' option set
+        */
+#ifdef META8_OPTION
+           if (meta && (R->h->meta_char == 0x80) && len > 0)
+               kbuf[len - 1] |= 0x80;
+#endif
+       } else if (ctrl && keysym == XK_minus) {
+           len = 1;
+           kbuf[0] = '\037';   /* Ctrl-Minus generates ^_ (31) */
+       } else {
+#ifdef META8_OPTION
+       /* set 8-bit on */
+           if (meta && (R->h->meta_char == 0x80)) {
+               unsigned char  *ch;
+
+               for (ch = kbuf; ch < kbuf + len; ch++)
+                   *ch |= 0x80;
+               meta = 0;
+           }
+#endif
+#ifdef GREEK_SUPPORT
+           if (R->h->greek_mode)
+               len = greek_xlat(kbuf, len);
+#endif
+       /* nil */ ;
+       }
+    }
+
+    if (len <= 0)
+       return;                 /* not mapped */
+
+    if (R->Options & Opt_scrollTtyKeypress)
+       if (R->TermWin.view_start) {
+           R->TermWin.view_start = 0;
+           R->h->want_refresh = 1;
+       }
+
+/*
+ * these modifications only affect the static keybuffer
+ * pass Shift/Control indicators for function keys ending with `~'
+ *
+ * eg,
+ *   Prior = "ESC[5~"
+ *   Shift+Prior = "ESC[5$"
+ *   Ctrl+Prior = "ESC[5^"
+ *   Ctrl+Shift+Prior = "ESC[5@"
+ * Meta adds an Escape prefix (with META8_OPTION, if meta == <escape>).
+ */
+    if (kbuf[0] == C0_ESC && kbuf[1] == '[' && kbuf[len - 1] == '~')
+       kbuf[len - 1] = (shft ? (ctrl ? '@' : '$') : (ctrl ? '^' : '~'));
+
+/* escape prefix */
+    if (meta
+#ifdef META8_OPTION
+       && (R->h->meta_char == C0_ESC)
+#endif
+       ) {
+       const unsigned char ch = C0_ESC;
+
+       rxvt_tt_write(aR_ &ch, 1);
+    }
+#ifdef DEBUG_CMD
+    if (debug_key) {           /* Display keyboard buffer contents */
+       char           *p;
+       int             i;
+
+       fprintf(stderr, "key 0x%04X [%d]: `", (unsigned int)keysym, len);
+       for (i = 0, p = kbuf; i < len; i++, p++)
+           fprintf(stderr, (*p >= ' ' && *p < '\177' ? "%c" : "\\%03o"), *p);
+       fprintf(stderr, "'\n");
+    }
+#endif                         /* DEBUG_CMD */
+    rxvt_tt_write(aR_ kbuf, (unsigned int)len);
+}
+/*}}} */
+
+#if (MENUBAR_MAX)
+/*{{{ rxvt_cmd_write(), rxvt_cmd_getc() */
+/* attempt to `write' count to the input buffer */
+/* EXTPROTO */
+unsigned int
+rxvt_cmd_write(pR_ const unsigned char *str, unsigned int count)
+{
+    unsigned int    n, s;
+    unsigned char  *cmdbuf_base = R->h->cmdbuf_base,
+                   *cmdbuf_endp = R->h->cmdbuf_endp,
+                   *cmdbuf_ptr = R->h->cmdbuf_ptr;
+
+    n = cmdbuf_ptr - cmdbuf_base;
+    s = cmdbuf_base + BUFSIZ - 1 - cmdbuf_endp;
+    if (n > 0 && s < count) {
+       MEMMOVE(cmdbuf_base, cmdbuf_ptr,
+               (unsigned int)(cmdbuf_endp - cmdbuf_ptr));
+       cmdbuf_ptr = cmdbuf_base;
+       cmdbuf_endp -= n;
+       s += n;
+    }
+    if (count > s) {
+       rxvt_print_error("data loss: cmd_write too large");
+       count = s;
+    }
+    for (; count--;)
+       *cmdbuf_endp++ = *str++;
+    R->h->cmdbuf_ptr = cmdbuf_ptr;
+    R->h->cmdbuf_endp = cmdbuf_endp;
+    return 0;
+}
+#endif                         /* MENUBAR_MAX */
+
+// read the next character, currently handles UTF-8
+// will probably handle all sorts of other stuff in the future
+static uint32_t
+next_char (pR)
+{
+  rxvt_hidden *h = R->h;
+  mbstate &s = h->mbstate;
+
+  while (h->cmdbuf_ptr < h->cmdbuf_endp)
+    {
+      uint8_t ch = *h->cmdbuf_ptr;
+
+      if (s.cnt)
+        {
+          if ((ch & 0xc0) == 0x80)
+            {
+              h->cmdbuf_ptr++;
+
+              /* continuation */
+              s.reg = (s.reg << 6) | (ch & 0x7f);
+
+              if (--s.cnt == 0 && s.reg >= 128) /* if !inrange then corruption or hacking */
+                return s.reg;
+
+              continue;
+            }
+          else
+            {
+              s.cnt = 0;
+              return s.orig; /* the _occasional_ non-utf-8 character may slip through... */
+            }
+        }
+      
+      if ((ch & 0xc0) == 0xc0)
+        {
+          h->cmdbuf_ptr++;
+
+          /* first byte */
+          s.orig = ch; /* for broken encodings */
+          s.reg = ch;
+          if ((ch & 0xe0) == 0xc0) { s.reg &= 0x1f; s.cnt = 1; }
+          if ((ch & 0xf0) == 0xe0) { s.reg &= 0x0f; s.cnt = 2; }
+          if ((ch & 0xf8) == 0xf0) { s.reg &= 0x07; s.cnt = 3; }
+          if ((ch & 0xfc) == 0xf8) { s.reg &= 0x03; s.cnt = 4; }
+          if ((ch & 0xfe) == 0xfc) { s.reg &= 0x01; s.cnt = 5; }
+        }
+      else
+        {
+          h->cmdbuf_ptr++; /* _occasional_ non-utf8 may slip through... */
+          return ch;
+        }
+    }
+
+  return NOCHAR;
+}
+
+/* rxvt_cmd_getc() - Return next input character */
+/*
+ * Return the next input character after first passing any keyboard input
+ * to the command.
+ */
+/* INTPROTO */
+uint32_t
+rxvt_cmd_getc(pR)
+{
+#define TIMEOUT_USEC   5000
+    fd_set          readfds;
+    int             quick_timeout, select_res;
+    int             want_motion_time, want_keypress_time;
+    struct timeval  value;
+#if defined(POINTER_BLANK) || defined(CURSOR_BLINK)
+    struct timeval  tp;
+#endif
+    struct rxvt_hidden *h = R->h;
+
+    uint32_t c = next_char (aR);
+    if (c != NOCHAR)
+      return c;
+
+    for (;;) {
+    /* loop until we can return something */
+
+       if (h->v_bufstr < h->v_bufptr)  /* output any pending chars */
+           rxvt_tt_write(aR_ NULL, 0);
+
+#if defined(POINTER_BLANK) || defined(CURSOR_BLINK)
+       tp.tv_sec = 0;          /* presume == 0 implies time not yet retrieved */
+#endif
+#if defined(CURSOR_BLINK)
+       want_keypress_time = 0;
+#endif
+#if defined(POINTER_BLANK)
+       want_motion_time = 0;
+#endif
+
+       while (XPending(R->Xdisplay)) { /* process pending X events */
+           XEvent          xev;
+
+           XNextEvent(R->Xdisplay, &xev);
+#if defined(CURSOR_BLINK)
+           if ((R->Options & Opt_cursorBlink)
+               && xev.type == KeyPress) {
+               if (h->hidden_cursor) {
+                   h->hidden_cursor = 0;
+                   h->want_refresh = 1;
+               }
+               want_keypress_time = 1;
+           }
+#endif
+#if defined(POINTER_BLANK)
+           if ((R->Options & Opt_pointerBlank)
+               && (h->pointerBlankDelay > 0)) {
+               if (xev.type == MotionNotify
+                   || xev.type == ButtonPress
+                   || xev.type == ButtonRelease) {
+                   if (R->h->hidden_pointer)
+                       rxvt_pointer_unblank(aR);
+                   want_motion_time = 1;
+               }
+               if (xev.type == KeyPress && R->h->hidden_pointer == 0)
+                   rxvt_pointer_blank(aR);
+           }
+#endif
+#ifdef USE_XIM
+           if (!XFilterEvent(&xev, xev.xany.window))
+               rxvt_process_x_event(aR_ &xev);
+           h->event_type = xev.type;
+#else
+           rxvt_process_x_event(aR_ &xev);
+#endif
+       /* in case button actions pushed chars to cmdbuf */
+           if (h->cmdbuf_ptr < h->cmdbuf_endp)
+               return *h->cmdbuf_ptr++;
+       }
+
+#if defined(CURSOR_BLINK)
+       if (want_keypress_time) {
+           (void)gettimeofday(&tp, NULL);
+           h->lastcursorchange.tv_sec = tp.tv_sec;
+           h->lastcursorchange.tv_usec = tp.tv_usec;
+       }
+#endif
+#if defined(POINTER_BLANK)
+       if (want_motion_time) {
+           if (!tp.tv_sec)
+               (void)gettimeofday(&tp, NULL);
+           h->lastmotion.tv_sec = tp.tv_sec;
+           h->lastmotion.tv_usec = tp.tv_usec;
+       }
+#endif
+
+/*
+ * the command input buffer is empty and we have no pending X events
+ */
+       quick_timeout = 0;
+
+#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
+       if (h->mouse_slip_wheel_speed) {
+           quick_timeout = 1;
+           if (!h->mouse_slip_wheel_delay--
+               && rxvt_scr_page(aR_ h->mouse_slip_wheel_speed > 0 ? UP : DN,
+                                abs(h->mouse_slip_wheel_speed))) {
+               h->mouse_slip_wheel_delay = SCROLLBAR_CONTINUOUS_DELAY;
+               h->refresh_type |= SMOOTH_REFRESH;
+               h->want_refresh = 1;
+           }
+       }
+#endif /* MOUSE_WHEEL && MOUSE_SLIP_WHEELING */
+#ifdef SELECTION_SCROLLING
+       if (h->pending_scroll_selection) {
+           quick_timeout = 1;
+           if (!h->scroll_selection_delay--
+               && rxvt_scr_page(aR_ h->scroll_selection_dir,
+                   h->scroll_selection_lines)) {
+               rxvt_selection_extend(aR_ h->selection_save_x,
+                   h->selection_save_y, h->selection_save_state);
+               h->scroll_selection_delay = SCROLLBAR_CONTINUOUS_DELAY;
+               h->refresh_type |= SMOOTH_REFRESH;
+               h->want_refresh = 1;
+           }
+       }
+#endif
+#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
+       if (scrollbar_isUp() || scrollbar_isDn()) {
+           quick_timeout = 1;
+           if (!h->scroll_arrow_delay--
+               && rxvt_scr_page(aR_ scrollbar_isUp() ? UP : DN, 1)) {
+               h->scroll_arrow_delay = SCROLLBAR_CONTINUOUS_DELAY;
+               h->refresh_type |= SMOOTH_REFRESH;
+               h->want_refresh = 1;
+           }
+       }
+#endif                         /* NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING */
+
+       FD_ZERO(&readfds);
+       FD_SET(R->cmd_fd, &readfds);
+       FD_SET(R->Xfd, &readfds);
+       value.tv_usec = TIMEOUT_USEC;
+       value.tv_sec = 0;
+
+       if (!R->TermWin.mapped)
+           quick_timeout = 0;
+       else {
+           quick_timeout |= h->want_refresh;
+#ifdef TRANSPARENT
+           quick_timeout |= h->want_full_refresh;
+#endif
+       }
+
+#if defined(POINTER_BLANK) || defined(CURSOR_BLINK)
+       {
+           int             set_quick_timeout = 0;
+           long            csdiff, psdiff;
+
+#define BLINK_TIME     500000L
+           csdiff = psdiff = 60000000L;        /* or, say, LONG_MAX */
+# if defined(CURSOR_BLINK)
+           if (R->Options & Opt_cursorBlink) {
+               if (!tp.tv_sec) /* didn't get it before so get it now */
+                   (void)gettimeofday(&tp, NULL);
+
+               csdiff = (tp.tv_sec - h->lastcursorchange.tv_sec) * 1000000L
+                        + tp.tv_usec - h->lastcursorchange.tv_usec;
+               if (csdiff > BLINK_TIME) { /* XXX: settable blink times */
+                   h->lastcursorchange.tv_sec = tp.tv_sec;
+                   h->lastcursorchange.tv_usec = tp.tv_usec;
+                   h->hidden_cursor = !h->hidden_cursor;
+                   csdiff = 0;
+               } else
+                   csdiff = BLINK_TIME - csdiff;
+               set_quick_timeout = 1;
+           }
+# endif
+# if defined(POINTER_BLANK)
+       /*
+        * If we haven't moved the pointer for a while
+        */
+           if ((R->Options & Opt_pointerBlank)
+               && (h->pointerBlankDelay > 0)
+               && (h->hidden_pointer == 0)) {
+               long            pdelay;
+
+               if (!tp.tv_sec) /* didn't get it before so get it now */
+                   (void)gettimeofday(&tp, NULL);
+               psdiff = (tp.tv_sec - h->lastmotion.tv_sec) * 1000000L
+                        + tp.tv_usec - h->lastmotion.tv_usec;
+               pdelay = h->pointerBlankDelay * 1000000L;
+               if (psdiff >= pdelay)
+                   rxvt_pointer_blank(aR);
+               else {
+                   set_quick_timeout = 1;
+                   psdiff = pdelay - psdiff;
+               }
+           }
+# endif
+           if (!quick_timeout && set_quick_timeout) {
+               MIN_IT(csdiff, psdiff);
+               value.tv_sec =  csdiff / 1000000L;
+               value.tv_usec = csdiff % 1000000L;
+               quick_timeout = 1;
+           }
+       }
+#endif
+
+       if ((select_res = select(R->num_fds, &readfds, NULL, NULL,
+                                (quick_timeout ? &value : NULL))) == 0) {
+       /* select statement timed out - we're not hard and fast scrolling */
+           h->refresh_limit = 1;
+       }
+#if defined(CURSOR_BLINK)
+       if (R->Options & Opt_cursorBlink)
+           h->want_refresh = 1;
+#endif
+
+    /* See if we can read new data from the application */
+       if (select_res > 0 && FD_ISSET(R->cmd_fd, &readfds)) {
+           int             n;
+           unsigned int    count;
+
+           h->cmdbuf_ptr = h->cmdbuf_endp = h->cmdbuf_base;
+           for (count = BUFSIZ; count; count -= n, h->cmdbuf_endp += n)
+               if ((n = read(R->cmd_fd, h->cmdbuf_endp, count)) > 0)
+                   continue;
+               else if (n == 0 || (n < 0 && errno == EAGAIN))
+                   break;
+               else {
+                   rxvt_clean_exit();
+                   exit(EXIT_FAILURE); /* bad order of events? */
+               }
+
+           if (count != BUFSIZ)        /* some characters read in */
+              {
+                uint32_t c = next_char (aR);
+                if (c != NOCHAR)
+                  return c;
+              }
+       }
+#ifdef TRANSPARENT
+       if (h->want_full_refresh) {
+           h->want_full_refresh = 0;
+           rxvt_scr_clear(aR);
+           rxvt_scr_touch(aR_ False);
+           h->want_refresh = 1;
+       }
+#endif
+       if (h->want_refresh) {
+           rxvt_scr_refresh(aR_ h->refresh_type);
+           rxvt_scrollbar_show(aR_ 1);
+#ifdef USE_XIM
+           rxvt_IMSendSpot(aR);
+#endif
+       }
+    }
+/* NOTREACHED */
+}
+/*}}} */
+
+/* EXTPROTO */
+void
+rxvt_pointer_unblank(pR)
+{
+    XDefineCursor(R->Xdisplay, R->TermWin.vt, R->TermWin_cursor);
+    rxvt_recolour_cursor(aR);
+#ifdef POINTER_BLANK
+    R->h->hidden_pointer = 0;
+    if (R->h->pointerBlankDelay > 0) {
+       struct timeval  tp;
+
+       (void)gettimeofday(&tp, NULL);
+       R->h->lastmotion.tv_sec = tp.tv_sec;
+       R->h->lastmotion.tv_usec = tp.tv_usec;
+    }
+#endif
+}
+
+#ifdef POINTER_BLANK
+/* INTPROTO */
+void
+rxvt_pointer_blank(pR)
+{
+    XDefineCursor(R->Xdisplay, R->TermWin.vt, R->h->pointer_blank);
+    XFlush(R->Xdisplay);
+    R->h->hidden_pointer = 1;
+}
+#endif
+
+/* INTPROTO */
+void
+rxvt_mouse_report(pR_ const XButtonEvent *ev)
+{
+    int             button_number, key_state = 0;
+    int             x, y;
+
+    x = ev->x;
+    y = ev->y;
+    rxvt_pixel_position(aR_ &x, &y);
+
+    if (R->h->MEvent.button == AnyButton) {
+       button_number = 3;
+    } else {
+       button_number = R->h->MEvent.button - Button1;
+       /* add 0x3D for wheel events, like xterm does */
+       if (button_number >= 3)
+           button_number += (64 - 3);
+    }
+
+    if (R->h->PrivateModes & PrivMode_MouseX10) {
+    /*
+     * do not report ButtonRelease
+     * no state info allowed
+     */
+       key_state = 0;
+       if (button_number == 3)
+           return;
+    } else {
+    /* XTerm mouse reporting needs these values:
+     *   4 = Shift
+     *   8 = Meta
+     *  16 = Control
+     * plus will add in our own Double-Click reporting
+     *  32 = Double Click
+     */
+       key_state = ((R->h->MEvent.state & ShiftMask) ? 4 : 0)
+                    + ((R->h->MEvent.state & R->h->ModMetaMask) ? 8 : 0)
+                    + ((R->h->MEvent.state & ControlMask) ? 16 : 0);
+#ifdef MOUSE_REPORT_DOUBLECLICK
+       key_state += ((R->h->MEvent.clicks > 1) ? 32 : 0);
+#endif
+    }
+
+#ifdef DEBUG_MOUSEREPORT
+    fprintf(stderr, "Mouse [");
+    if (key_state & 16)
+       fputc('C', stderr);
+    if (key_state & 4)
+       fputc('S', stderr);
+    if (key_state & 8)
+       fputc('A', stderr);
+    if (key_state & 32)
+       fputc('2', stderr);
+    fprintf(stderr, "]: <%d>, %d/%d\n",
+           button_number,
+           x + 1,
+           y + 1);
+#else
+    rxvt_tt_printf(aR_ "\033[M%c%c%c",
+             (32 + button_number + key_state),
+             (32 + x + 1),
+             (32 + y + 1));
+#endif
+}
+
+#ifdef USING_W11LIB
+/* EXTPROTO */
+void
+rxvt_W11_process_x_event(XEvent *ev)
+{
+    rxvt_t         *r = rxvt_get_r();
+
+    rxvt_process_x_event(aR_ ev);
+}
+#endif
+
+/*{{{ process an X event */
+/* INTPROTO */
+void
+rxvt_process_x_event(pR_ XEvent *ev)
+{
+    int             i, want_timeout;
+    Window          unused_root, unused_child;
+    int             unused_root_x, unused_root_y;
+    unsigned int    unused_mask;
+    struct timeval  tp;
+    struct rxvt_hidden *h = R->h;
+#ifdef DEBUG_X
+    const char *const eventnames[] =
+    {                          /* mason - this matches my system */
+       "",
+       "",
+       "KeyPress",
+       "KeyRelease",
+       "ButtonPress",
+       "ButtonRelease",
+       "MotionNotify",
+       "EnterNotify",
+       "LeaveNotify",
+       "FocusIn",
+       "FocusOut",
+       "KeymapNotify",
+       "Expose",
+       "GraphicsExpose",
+       "NoExpose",
+       "VisibilityNotify",
+       "CreateNotify",
+       "DestroyNotify",
+       "UnmapNotify",
+       "MapNotify",
+       "MapRequest",
+       "ReparentNotify",
+       "ConfigureNotify",
+       "ConfigureRequest",
+       "GravityNotify",
+       "ResizeRequest",
+       "CirculateNotify",
+       "CirculateRequest",
+       "PropertyNotify",
+       "SelectionClear",
+       "SelectionRequest",
+       "SelectionNotify",
+       "ColormapNotify",
+       "ClientMessage",
+       "MappingNotify"
+    };
+    struct tm      *ltt;
+#endif
+
+    /*
+     * check if we need to get the time for any timeouts
+     */
+
+    for (i = NUM_TIMEOUTS; i--; )
+       if (h->timeout[i].tv_sec) {
+           want_timeout = 1;
+           break;
+       }
+
+#ifndef DEBUG_X
+    if (want_timeout)
+#endif
+       (void)gettimeofday(&tp, NULL);
+
+#ifdef DEBUG_X
+    ltt = localtime(&(tp.tv_sec));
+    D_X((stderr, "Event: %-16s %-7s %08lx (%4d-%02d-%02d %02d:%02d:%02d.%.6ld) %s %lu", eventnames[ev->type], (ev->xany.window == R->TermWin.parent[0] ? "parent" : (ev->xany.window == R->TermWin.vt ? "vt" : (ev->xany.window == R->scrollBar.win ? "scroll" : (ev->xany.window == R->menuBar.win ? "menubar" : "UNKNOWN")))), (ev->xany.window == R->TermWin.parent[0] ? R->TermWin.parent[0] : (ev->xany.window == R->TermWin.vt ? R->TermWin.vt : (ev->xany.window == R->scrollBar.win ? R->scrollBar.win : (ev->xany.window == R->menuBar.win ? R->menuBar.win : 0)))), ltt->tm_year + 1900, ltt->tm_mon + 1, ltt->tm_mday, ltt->tm_hour, ltt->tm_min, ltt->tm_sec, tp.tv_usec, ev->xany.send_event ? "S" : " ", ev->xany.serial));
+#endif
+
+    /* X event timeouts */
+    if (want_timeout)
+       for (i = NUM_TIMEOUTS; i--; ) {
+           if (h->timeout[i].tv_sec == 0)
+               continue;
+           if ((tp.tv_sec < h->timeout[i].tv_sec)
+               || (tp.tv_sec == h->timeout[i].tv_sec
+                   && tp.tv_usec < h->timeout[i].tv_usec))
+               continue;
+           h->timeout[i].tv_sec = 0;
+           switch(i) {
+           case TIMEOUT_INCR:
+               rxvt_print_error("data loss: timeout on INCR selection paste");
+               h->selection_wait = Sel_none;
+               break;
+           default:
+               break;
+           }
+       }
+
+    switch (ev->type) {
+    case KeyPress:
+       rxvt_lookup_key(aR_ (XKeyEvent *)ev);
+       break;
+
+#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
+    case KeyRelease:
+       {
+           if (!(ev->xkey.state & ControlMask))
+               h->mouse_slip_wheel_speed = 0;
+           else {
+               KeySym          ks;
+               
+               ks = XKeycodeToKeysym(R->Xdisplay, ev->xkey.keycode, 0);
+               if (ks == XK_Control_L || ks == XK_Control_R)
+                   h->mouse_slip_wheel_speed = 0;
+           }
+           break;
+       }
+#endif
+
+    case ButtonPress:
+       rxvt_button_press(aR_ (XButtonEvent *)ev);
+       break;
+
+    case ButtonRelease:
+       rxvt_button_release(aR_ (XButtonEvent *)ev);
+       break;
+
+    case ClientMessage:
+       if (ev->xclient.format == 32
+           && (Atom)ev->xclient.data.l[0] == h->xa[XA_WMDELETEWINDOW])
+           exit(EXIT_SUCCESS);
+#ifdef OFFIX_DND
+    /* OffiX Dnd (drag 'n' drop) protocol */
+       if (ev->xclient.message_type == h->xa[XA_DNDPROTOCOL]
+           && (ev->xclient.data.l[0] == DndFile
+               || ev->xclient.data.l[0] == DndDir
+               || ev->xclient.data.l[0] == DndLink)) {
+       /* Get Dnd data */
+           Atom            ActualType;
+           int             ActualFormat;
+           unsigned char  *data;
+           unsigned long   Size, RemainingBytes;
+
+           XGetWindowProperty(R->Xdisplay, Xroot,
+                              R->h->xa[XA_DNDSELECTION],
+                              0L, 1000000L,
+                              False, AnyPropertyType,
+                              &ActualType, &ActualFormat,
+                              &Size, &RemainingBytes,
+                              &data);
+           XChangeProperty(R->Xdisplay, Xroot,
+                           XA_CUT_BUFFER0, XA_STRING,
+                           8, PropModeReplace,
+                           data, STRLEN(data));
+           rxvt_selection_paste(aR_ Xroot, XA_CUT_BUFFER0, True);
+           XSetInputFocus(R->Xdisplay, Xroot, RevertToNone, CurrentTime);
+       }
+#endif                         /* OFFIX_DND */
+       break;
+
+    case MappingNotify:
+       XRefreshKeyboardMapping(&(ev->xmapping));
+       break;
+
+    /*
+     * XXX: this is not the _current_ arrangement
+     * Here's my conclusion:
+     * If the window is completely unobscured, use bitblt's
+     * to scroll. Even then, they're only used when doing partial
+     * screen scrolling. When partially obscured, we have to fill
+     * in the GraphicsExpose parts, which means that after each refresh,
+     * we need to wait for the graphics expose or Noexpose events,
+     * which ought to make things real slow!
+     */
+    case VisibilityNotify:
+       switch (ev->xvisibility.state) {
+       case VisibilityUnobscured:
+           h->refresh_type = FAST_REFRESH;
+           break;
+       case VisibilityPartiallyObscured:
+           h->refresh_type = SLOW_REFRESH;
+           break;
+       default:
+           h->refresh_type = NO_REFRESH;
+           break;
+       }
+       break;
+
+    case FocusIn:
+       if (!R->TermWin.focus) {
+           R->TermWin.focus = 1;
+           h->want_refresh = 1;
+#ifdef USE_XIM
+           if (h->Input_Context != NULL)
+               XSetICFocus(h->Input_Context);
+#endif
+       }
+       break;
+
+    case FocusOut:
+       if (R->TermWin.focus) {
+           R->TermWin.focus = 0;
+           h->want_refresh = 1;
+#ifdef USE_XIM
+           if (h->Input_Context != NULL)
+               XUnsetICFocus(h->Input_Context);
+#endif
+       }
+       break;
+
+    case ConfigureNotify:
+       if (ev->xconfigure.window == R->TermWin.parent[0]) {
+           int             height, width;
+
+           do {        /* Wrap lots of configures into one */
+               width = ev->xconfigure.width;
+               height = ev->xconfigure.height;
+               D_SIZE((stderr, "Size: ConfigureNotify: %4d x %4d", width, height));
+           } while (XCheckTypedWindowEvent(R->Xdisplay, ev->xconfigure.window,
+                                           ConfigureNotify, ev));
+           if (R->szHint.width != width || R->szHint.height != height) {
+               D_SIZE((stderr, "Size: Resizing from: %4d x %4d", R->szHint.width, R->szHint.height));
+               rxvt_resize_all_windows(aR_ (unsigned int)width,
+                                       (unsigned int)height, 1);
+           }
+#ifdef DEBUG_SIZE
+           else {
+               D_SIZE((stderr, "Size: Not resizing"));
+           }
+#endif
+#ifdef TRANSPARENT             /* XXX: maybe not needed - leave in for now */
+           if (R->Options & Opt_transparent) {
+               rxvt_check_our_parents(aR);
+               if (h->am_transparent)
+                   h->want_full_refresh = 1;
+           }
+#endif
+       }
+       break;
+
+    case SelectionClear:
+       rxvt_selection_clear(aR);
+       break;
+
+    case SelectionNotify:
+       if (h->selection_wait == Sel_normal)
+           rxvt_selection_paste(aR_ ev->xselection.requestor,
+                                ev->xselection.property, True);
+       break;
+
+    case SelectionRequest:
+       rxvt_selection_send(aR_ &(ev->xselectionrequest));
+       break;
+
+    case UnmapNotify:
+       R->TermWin.mapped = 0;
+       break;
+
+    case MapNotify:
+       R->TermWin.mapped = 1;
+       break;
+
+    case PropertyNotify:
+       if (ev->xproperty.atom == h->xa[XA_VT_SELECTION]) {
+           if (ev->xproperty.state == PropertyNewValue)
+               rxvt_selection_property(aR_ ev->xproperty.window,
+                                       ev->xproperty.atom);
+           break;
+       }
+#ifdef TRANSPARENT
+    /*
+     * if user used some Esetroot compatible prog to set the root bg,
+     * use the property to determine the pixmap.  We use it later on.
+     */
+       if (h->xa[XA_XROOTPMAPID] == 0)
+           h->xa[XA_XROOTPMAPID] = XInternAtom(R->Xdisplay,
+                                              "_XROOTPMAP_ID", False);
+       if (ev->xproperty.atom != h->xa[XA_XROOTPMAPID])
+           break;
+    /* FALLTHROUGH */
+    case ReparentNotify:
+       if ((R->Options & Opt_transparent) && rxvt_check_our_parents(aR)) {
+           if (h->am_transparent)
+               h->want_full_refresh = 1;
+       }
+#endif                         /* TRANSPARENT */
+       break;
+
+    case GraphicsExpose:
+    case Expose:
+       if (ev->xany.window == R->TermWin.vt) {
+#ifdef NO_SLOW_LINK_SUPPORT
+           rxvt_scr_expose(aR_ ev->xexpose.x, ev->xexpose.y,
+                           ev->xexpose.width, ev->xexpose.height, False);
+#else
+            // don't understand this, so commented it out
+           rxvt_scr_expose(aR_ ev->xexpose.x, ev->xexpose.y,
+                           ev->xexpose.width, ev->xexpose.height, False);
+           //rxvt_scr_expose(aR_ ev->xexpose.x, 0,
+           //              ev->xexpose.width, R->TermWin.height, False);
+#endif
+           h->want_refresh = 1;
+       } else {
+           XEvent          unused_xevent;
+
+           while (XCheckTypedWindowEvent(R->Xdisplay, ev->xany.window,
+                                         Expose,
+                                         &unused_xevent)) ;
+           while (XCheckTypedWindowEvent(R->Xdisplay, ev->xany.window,
+                                         GraphicsExpose,
+                                         &unused_xevent)) ;
+           if (isScrollbarWindow(ev->xany.window)) {
+               scrollbar_setIdle();
+               rxvt_scrollbar_show(aR_ 0);
+           }
+#ifdef MENUBAR
+           if (menubar_visible(aR) && isMenuBarWindow(ev->xany.window))
+               rxvt_menubar_expose(aR);
+#endif
+#ifdef RXVT_GRAPHICS
+           rxvt_Gr_expose(aR_ ev->xany.window);
+#endif
+       }
+       break;
+
+    case MotionNotify:
+#ifdef POINTER_BLANK
+       if (R->h->hidden_pointer)
+           rxvt_pointer_unblank(aR);
+#endif
+#if MENUBAR
+       if (isMenuBarWindow(ev->xany.window)) {
+           rxvt_menubar_control(aR_ &(ev->xbutton));
+           break;
+       }
+#endif
+       if ((h->PrivateModes & PrivMode_mouse_report) && !(h->bypass_keystate))
+           break;
+
+       if (ev->xany.window == R->TermWin.vt) {
+           if ((ev->xbutton.state & (Button1Mask | Button3Mask))) {
+               while (XCheckTypedWindowEvent(R->Xdisplay, R->TermWin.vt,
+                                             MotionNotify, ev)) ;
+               XQueryPointer(R->Xdisplay, R->TermWin.vt,
+                             &unused_root, &unused_child,
+                             &unused_root_x, &unused_root_y,
+                             &(ev->xbutton.x), &(ev->xbutton.y),
+                             &unused_mask);
+#ifdef MOUSE_THRESHOLD
+           /* deal with a `jumpy' mouse */
+               if ((ev->xmotion.time - h->MEvent.time) > MOUSE_THRESHOLD) {
+#endif
+                   rxvt_selection_extend(aR_ (ev->xbutton.x), (ev->xbutton.y),
+                                 (ev->xbutton.state & Button3Mask) ? 2 : 0);
+#ifdef SELECTION_SCROLLING
+                   if (ev->xbutton.y<R->TermWin.int_bwidth ||
+                       Pixel2Row(ev->xbutton.y)>(R->TermWin.nrow-1)) {
+                       int dist;
+                       
+                       h->pending_scroll_selection=1;
+                       
+                         /* don't clobber the current delay if we are
+                          * already in the middle of scrolling.
+                          */
+                       if (h->scroll_selection_delay<=0)
+                           h->scroll_selection_delay=SCROLLBAR_CONTINUOUS_DELAY;
+
+                         /* save the event params so we can highlight
+                          * the selection in the pending-scroll loop
+                          */
+                       h->selection_save_x=ev->xbutton.x;
+                       h->selection_save_y=ev->xbutton.y;
+                       h->selection_save_state=
+                           (ev->xbutton.state & Button3Mask) ? 2 : 0;
+
+                         /* calc number of lines to scroll */
+                       if (ev->xbutton.y<R->TermWin.int_bwidth) {
+                           h->scroll_selection_dir = UP;
+                           dist = R->TermWin.int_bwidth - ev->xbutton.y;
+                       }
+                       else {
+                           h->scroll_selection_dir = DN;
+                           dist = ev->xbutton.y -
+                               (R->TermWin.int_bwidth + R->TermWin.height);
+                       }
+                       h->scroll_selection_lines=(Pixel2Height(dist)/
+                           SELECTION_SCROLL_LINE_SPEEDUP)+1;
+                       MIN_IT(h->scroll_selection_lines,
+                           SELECTION_SCROLL_MAX_LINES);
+                   }
+                   else {
+                         /* we are within the text window, so we
+                          * shouldn't be scrolling
+                          */
+                       h->pending_scroll_selection = 0;
+                   }
+#endif
+#ifdef MOUSE_THRESHOLD
+               }
+#endif
+           }
+       } else if (isScrollbarWindow(ev->xany.window) && scrollbar_isMotion()) {
+           while (XCheckTypedWindowEvent(R->Xdisplay, R->scrollBar.win,
+                                         MotionNotify, ev)) ;
+           XQueryPointer(R->Xdisplay, R->scrollBar.win,
+                         &unused_root, &unused_child,
+                         &unused_root_x, &unused_root_y,
+                         &(ev->xbutton.x), &(ev->xbutton.y),
+                         &unused_mask);
+           rxvt_scr_move_to(aR_ scrollbar_position(ev->xbutton.y) - h->csrO,
+                            scrollbar_size());
+           rxvt_scr_refresh(aR_ h->refresh_type);
+           h->refresh_limit = 0;
+           rxvt_scrollbar_show(aR_ 1);
+       }
+       break;
+    }
+}
+
+/* INTPROTO */
+void
+rxvt_button_press(pR_ XButtonEvent *ev)
+{
+    int             reportmode = 0, clickintime;
+    struct rxvt_hidden *h = R->h;
+
+    h->bypass_keystate = ev->state & (h->ModMetaMask | ShiftMask);
+    if (!h->bypass_keystate)
+       reportmode = !!(h->PrivateModes & PrivMode_mouse_report);
+/*
+ * VT window processing of button press
+ */
+    if (ev->window == R->TermWin.vt)
+      {
+#if RXVT_GRAPHICS
+       if (ev->subwindow != None)
+         rxvt_Gr_ButtonPress(ev->x, ev->y);
+       else
+#endif
+          {
+           clickintime = ev->time - h->MEvent.time < MULTICLICK_TIME;
+           if (reportmode)
+              {
+               /* mouse report from vt window */
+               /* save the xbutton state (for ButtonRelease) */
+               h->MEvent.state = ev->state;
+#ifdef MOUSE_REPORT_DOUBLECLICK
+               if (ev->button == h->MEvent.button && clickintime)
+                  {
+                   /* same button, within alloted time */
+                   h->MEvent.clicks++;
+                   if (h->MEvent.clicks > 1)
+                      {
+                       /* only report double clicks */
+                       h->MEvent.clicks = 2;
+                       rxvt_mouse_report(aR_ ev);
+
+                       /* don't report the release */
+                       h->MEvent.clicks = 0;
+                       h->MEvent.button = AnyButton;
+                     }
+                 }
+                else
+                  {
+                   /* different button, or time expired */
+                   h->MEvent.clicks = 1;
+                   h->MEvent.button = ev->button;
+                   rxvt_mouse_report(aR_ ev);
+                 }
+#else
+               h->MEvent.button = ev->button;
+               rxvt_mouse_report(aR_ ev);
+#endif                         /* MOUSE_REPORT_DOUBLECLICK */
+             }
+            else
+              {
+               if (ev->button != h->MEvent.button)
+                   h->MEvent.clicks = 0;
+               switch (ev->button)
+                  {
+                    case Button1:
+                        if (h->MEvent.button == Button1 && clickintime)
+                          h->MEvent.clicks++;
+                        else
+                          h->MEvent.clicks = 1;
+                        rxvt_selection_click(aR_ h->MEvent.clicks, ev->x, ev->y);
+                        h->MEvent.button = Button1;
+                        break;
+
+                    case Button3:
+                        if (h->MEvent.button == Button3 && clickintime)
+                          rxvt_selection_rotate(aR_ ev->x, ev->y);
+                        else
+                          rxvt_selection_extend(aR_ ev->x, ev->y, 1);
+                        h->MEvent.button = Button3;
+                        break;
+                 }
+             }
+           h->MEvent.time = ev->time;
+           return;
+         }
+      }
+
+/*
+ * Scrollbar window processing of button press
+ */
+    if (isScrollbarWindow(ev->window))
+      {
+       scrollbar_setIdle();
+       /*
+        * Rxvt-style scrollbar:
+        * move up if mouse is above slider
+        * move dn if mouse is below slider
+        *
+        * XTerm-style scrollbar:
+        * Move display proportional to pointer location
+        * pointer near top -> scroll one line
+        * pointer near bot -> scroll full page
+        */
+#ifndef NO_SCROLLBAR_REPORT
+       if (reportmode) {
+           /*
+            * Mouse report disabled scrollbar:
+            * arrow buttons - send up/down
+            * click on scrollbar - send pageup/down
+            */
+           if ((R->scrollBar.style == R_SB_NEXT
+                && scrollbarnext_upButton(ev->y))
+               || (R->scrollBar.style == R_SB_RXVT
+                   && scrollbarrxvt_upButton(ev->y)))
+               rxvt_tt_printf(aR_ "\033[A");
+           else if ((R->scrollBar.style == R_SB_NEXT
+                     && scrollbarnext_dnButton(ev->y))
+                    || (R->scrollBar.style == R_SB_RXVT
+                        && scrollbarrxvt_dnButton(ev->y)))
+               rxvt_tt_printf(aR_ "\033[B");
+           else
+               switch (ev->button) {
+               case Button2:
+                   rxvt_tt_printf(aR_ "\014");
+                   break;
+               case Button1:
+                   rxvt_tt_printf(aR_ "\033[6~");
+                   break;
+               case Button3:
+                   rxvt_tt_printf(aR_ "\033[5~");
+                   break;
+               }
+         }
+        else
+#endif                         /* NO_SCROLLBAR_REPORT */
+         {
+           char            upordown = 0;
+
+           if (R->scrollBar.style == R_SB_NEXT) {
+               if (scrollbarnext_upButton(ev->y))
+                   upordown = -1;      /* up */
+               else if (scrollbarnext_dnButton(ev->y))
+                   upordown = 1;       /* down */
+           } else if (R->scrollBar.style == R_SB_RXVT) {
+               if (scrollbarrxvt_upButton(ev->y))
+                   upordown = -1;      /* up */
+               else if (scrollbarrxvt_dnButton(ev->y))
+                   upordown = 1;       /* down */
+           }
+           if (upordown) { 
+#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
+               h->scroll_arrow_delay = SCROLLBAR_INITIAL_DELAY;
+#endif
+               if (rxvt_scr_page(aR_ upordown < 0 ? UP : DN, 1)) {
+                   if (upordown < 0)
+                       scrollbar_setUp();
+                   else
+                       scrollbar_setDn();
+               }
+           } else
+               switch (ev->button) {
+               case Button2:
+                   switch (h->scrollbar_align) {
+                   case R_SB_ALIGN_TOP:
+                       h->csrO = 0;
+                       break;
+                   case R_SB_ALIGN_CENTRE:
+                       h->csrO = (R->scrollBar.bot - R->scrollBar.top) / 2;
+                       break;
+                   case R_SB_ALIGN_BOTTOM:
+                       h->csrO = R->scrollBar.bot - R->scrollBar.top;
+                       break;
+                   }
+                   if (R->scrollBar.style == R_SB_XTERM
+                       || scrollbar_above_slider(ev->y)
+                       || scrollbar_below_slider(ev->y))
+                       rxvt_scr_move_to(aR_
+                                        scrollbar_position(ev->y) - h->csrO,
+                                        scrollbar_size());
+                   scrollbar_setMotion();
+                   break;
+
+               case Button1:
+                   if (h->scrollbar_align == R_SB_ALIGN_CENTRE)
+                       h->csrO = ev->y - R->scrollBar.top;
+                   /* FALLTHROUGH */
+
+               case Button3:
+                   if (R->scrollBar.style != R_SB_XTERM) {
+                       if (scrollbar_above_slider(ev->y))
+# ifdef RXVT_SCROLL_FULL
+                           rxvt_scr_page(aR_ UP, R->TermWin.nrow - 1);
+# else
+                           rxvt_scr_page(aR_ UP, R->TermWin.nrow / 4);
+# endif
+                       else if (scrollbar_below_slider(ev->y))
+# ifdef RXVT_SCROLL_FULL
+                           rxvt_scr_page(aR_ DN, R->TermWin.nrow - 1);
+# else
+                           rxvt_scr_page(aR_ DN, R->TermWin.nrow / 4);
+# endif
+                       else
+                           scrollbar_setMotion();
+                   } else {
+                       rxvt_scr_page(aR_ (ev->button == Button1 ? DN : UP),
+                                     (R->TermWin.nrow
+                                      * scrollbar_position(ev->y)
+                                      / scrollbar_size()));
+                   }
+                   break;
+               }
+         }
+       return;
+    }
+#if MENUBAR
+    /*
+     * Menubar window processing of button press
+     */
+    if (isMenuBarWindow(ev->window))
+       rxvt_menubar_control(aR_ ev);
+#endif
+}
+
+/* INTPROTO */
+void
+rxvt_button_release(pR_ XButtonEvent *ev)
+{
+    int             reportmode = 0;
+
+    R->h->csrO = 0;            /* reset csr Offset */
+    if (!R->h->bypass_keystate)
+       reportmode = !!(R->h->PrivateModes & PrivMode_mouse_report);
+
+    if (scrollbar_isUpDn()) {
+       scrollbar_setIdle();
+       rxvt_scrollbar_show(aR_ 0);
+#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
+       R->h->refresh_type &= ~SMOOTH_REFRESH;
+#endif
+    }
+#ifdef SELECTION_SCROLLING
+    R->h->pending_scroll_selection=0;
+#endif
+    if (ev->window == R->TermWin.vt) 
+      {
+#ifdef RXVT_GRAPHICS
+       if (ev->subwindow != None)
+         rxvt_Gr_ButtonRelease(ev->x, ev->y);
+       else 
+#endif
+          {
+           if (reportmode) 
+              {
+               /* mouse report from vt window */
+               /* don't report release of wheel "buttons" */
+               if (ev->button >= 4)
+                   return;
+#ifdef MOUSE_REPORT_DOUBLECLICK
+               /* only report the release of 'slow' single clicks */
+               if (R->h->MEvent.button != AnyButton
+                   && (ev->button != R->h->MEvent.button
+                       || (ev->time - R->h->MEvent.time
+                           > MULTICLICK_TIME / 2))) 
+                  {
+                   R->h->MEvent.clicks = 0;
+                   R->h->MEvent.button = AnyButton;
+                   rxvt_mouse_report(aR_ ev);
+                 }
+#else                          /* MOUSE_REPORT_DOUBLECLICK */
+               R->h->MEvent.button = AnyButton;
+               rxvt_mouse_report(aR_ ev);
+#endif                         /* MOUSE_REPORT_DOUBLECLICK */
+               return;
+           }
+           /*
+            * dumb hack to compensate for the failure of click-and-drag
+            * when overriding mouse reporting
+            */
+           if (R->h->PrivateModes & PrivMode_mouse_report
+               && R->h->bypass_keystate
+               && ev->button == Button1 && R->h->MEvent.clicks <= 1)
+               rxvt_selection_extend(aR_ ev->x, ev->y, 0);
+
+           switch (ev->button) {
+           case Button1:
+           case Button3:
+               rxvt_selection_make(aR_ ev->time);
+               break;
+           case Button2:
+               rxvt_selection_request(aR_ ev->time, ev->x, ev->y);
+               break;
+#ifdef MOUSE_WHEEL
+           case Button4:
+           case Button5:
+                 {
+                   int             i, v;
+
+                   v = (ev->button == Button4) ? UP : DN;
+                   if (ev->state & ShiftMask)
+                       i = 1;
+                   else if ((R->Options & Opt_mouseWheelScrollPage))
+                       i = R->TermWin.nrow - 1;
+                   else
+                       i = 5;
+# ifdef MOUSE_SLIP_WHEELING
+                    if (ev->state & ControlMask) 
+                      {
+                       R->h->mouse_slip_wheel_speed += (v ? -1 : 1);
+                       R->h->mouse_slip_wheel_delay = SCROLLBAR_CONTINUOUS_DELAY;
+                     }
+# endif
+# ifdef JUMP_MOUSE_WHEEL
+                   rxvt_scr_page(aR_ v, i);
+                   rxvt_scr_refresh(aR_ SMOOTH_REFRESH);
+                   rxvt_scrollbar_show(aR_ 1);
+# else
+                   for (; i--;)
+                      {
+                       rxvt_scr_page(aR_ v, 1);
+                       rxvt_scr_refresh(aR_ SMOOTH_REFRESH);
+                       rxvt_scrollbar_show(aR_ 1);
+                     }
+# endif
+                 }
+               break;
+#endif
+             }
+         }
+      }
+#ifdef MENUBAR
+    else if (isMenuBarWindow(ev->window))
+       rxvt_menubar_control(aR_ ev);
+#endif
+}
+
+
+#ifdef TRANSPARENT
+/*
+ * Check our parents are still who we think they are.
+ * Do transparency updates if required
+ */
+/* EXTPROTO */
+int
+rxvt_check_our_parents(pR)
+{
+    int             i, pchanged, aformat, have_pixmap, rootdepth;
+    unsigned long   nitems, bytes_after;
+    Atom            atype;
+    unsigned char   *prop = NULL;
+    Window          root, oldp, *list;
+    Pixmap          rootpixmap = None;
+    XWindowAttributes wattr, wrootattr;
+
+    pchanged = 0;
+
+    if (!(R->Options & Opt_transparent))
+       return pchanged;        /* Don't try any more */
+
+    XGetWindowAttributes(R->Xdisplay, Xroot, &wrootattr);
+    rootdepth = wrootattr.depth;
+
+    XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr);
+    if (rootdepth != wattr.depth) {
+       if (R->h->am_transparent) {
+           pchanged = 1;
+           XSetWindowBackground(R->Xdisplay, R->TermWin.vt,
+                                R->PixColors[Color_bg]);
+           R->h->am_transparent = R->h->am_pixmap_trans = 0;
+       }
+       return pchanged;        /* Don't try any more */
+    }
+
+/* Get all X ops out of the queue so that our information is up-to-date. */
+    XSync(R->Xdisplay, False);
+
+/*
+ * Make the frame window set by the window manager have
+ * the root background. Some window managers put multiple nested frame
+ * windows for each client, so we have to take care about that.
+ */
+    i = (R->h->xa[XA_XROOTPMAPID] != 0
+        && (XGetWindowProperty(R->Xdisplay, Xroot, R->h->xa[XA_XROOTPMAPID],
+                               0L, 1L, False, XA_PIXMAP, &atype, &aformat,
+                               &nitems, &bytes_after, &prop) == Success));
+    if (!i || prop == NULL)
+       have_pixmap = 0;
+    else {
+       have_pixmap = 1;
+       rootpixmap = *((Pixmap *)prop);
+       XFree(prop);
+    }
+    if (have_pixmap) {
+/*
+ * Copy Xroot pixmap transparency
+ */
+       int             sx, sy, nx, ny;
+       unsigned int    nw, nh;
+       Window          cr;
+       XImage         *image;
+       GC              gc;
+       XGCValues       gcvalue;
+
+       XTranslateCoordinates(R->Xdisplay, R->TermWin.parent[0], Xroot,
+                             0, 0, &sx, &sy, &cr);
+       nw = (unsigned int)R->szHint.width;
+       nh = (unsigned int)R->szHint.height;
+       nx = ny = 0;
+       if (sx < 0) {
+           nw += sx;
+           nx = -sx;
+           sx = 0;
+       }
+       if (sy < 0) {
+           nh += sy;
+           ny = -sy;
+           sy = 0;
+       }
+       MIN_IT(nw, (unsigned int)(wrootattr.width - sx));
+       MIN_IT(nh, (unsigned int)(wrootattr.height - sy));
+       R->h->allowedxerror = -1;
+       image = XGetImage(R->Xdisplay, rootpixmap, sx, sy, nw, nh, AllPlanes,
+                         ZPixmap);
+       /* XXX: handle BadMatch - usually because we're outside the pixmap */
+       /* XXX: may need a delay here? */
+       R->h->allowedxerror = 0;
+       if (image == NULL) {
+           if (R->h->am_transparent && R->h->am_pixmap_trans) {
+               pchanged = 1;
+               if (R->TermWin.pixmap != None) {
+                   XFreePixmap(R->Xdisplay, R->TermWin.pixmap);
+                   R->TermWin.pixmap = None;
+               }
+           }
+           R->h->am_pixmap_trans = 0;
+       } else {
+           if (R->TermWin.pixmap != None)
+               XFreePixmap(R->Xdisplay, R->TermWin.pixmap);
+           R->TermWin.pixmap = XCreatePixmap(R->Xdisplay, R->TermWin.vt,
+                                             (unsigned int)R->szHint.width,
+                                             (unsigned int)R->szHint.height,
+                                             (unsigned int)image->depth);
+           gc = XCreateGC(R->Xdisplay, R->TermWin.vt, 0UL, &gcvalue);
+           XPutImage(R->Xdisplay, R->TermWin.pixmap, gc, image, 0, 0,
+                     nx, ny, (unsigned int)image->width,
+                     (unsigned int)image->height);
+           XFreeGC(R->Xdisplay, gc);
+           XDestroyImage(image);
+           XSetWindowBackgroundPixmap(R->Xdisplay, R->TermWin.vt,
+                                      R->TermWin.pixmap);
+           if (!R->h->am_transparent || !R->h->am_pixmap_trans)
+               pchanged = 1;
+           R->h->am_transparent = R->h->am_pixmap_trans = 1;
+       }
+    }
+    if (!R->h->am_pixmap_trans) {
+       unsigned int    n;
+/*
+ * InheritPixmap transparency
+ */
+       D_X((stderr, "InheritPixmap Seeking to  %08lx", Xroot));
+       for (i = 1; i < (int)(sizeof(R->TermWin.parent) / sizeof(Window));
+            i++) {
+           oldp = R->TermWin.parent[i];
+           XQueryTree(R->Xdisplay, R->TermWin.parent[i - 1], &root,
+                      &R->TermWin.parent[i], &list, &n);
+           XFree(list);
+           D_X((stderr, "InheritPixmap Parent[%d] = %08lx", i, R->TermWin.parent[i]));
+           if (R->TermWin.parent[i] == Xroot) {
+               if (oldp != None)
+                   pchanged = 1;
+               break;
+           }
+           if (oldp != R->TermWin.parent[i])
+               pchanged = 1;
+       }
+       n = 0;
+       if (pchanged) {
+           for (; n < (unsigned int)i; n++) {
+               XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[n], &wattr);
+               D_X((stderr, "InheritPixmap Checking Parent[%d]: %s", n, (wattr.depth == rootdepth && wattr.class != InputOnly) ? "OK" : "FAIL"));
+               if (wattr.depth != rootdepth || wattr.class == InputOnly) {
+                   n = (int)(sizeof(R->TermWin.parent) / sizeof(Window)) + 1;
+                   break;
+               }
+           }
+       }
+       if (n > (int)(sizeof(R->TermWin.parent)
+                     / sizeof(R->TermWin.parent[0]))) {
+           D_X((stderr, "InheritPixmap Turning off"));
+           XSetWindowBackground(R->Xdisplay, R->TermWin.parent[0],
+                                R->PixColors[Color_fg]);
+           XSetWindowBackground(R->Xdisplay, R->TermWin.vt,
+                                R->PixColors[Color_bg]);
+           R->h->am_transparent = 0;
+           /* XXX: also turn off Opt_transparent? */
+       } else {
+           /* wait (an arbitrary period) for the WM to do its thing
+            * needed for fvwm2.2.2 (and before?) */
+# ifdef HAVE_NANOSLEEP
+           struct timespec rqt;
+
+           rqt.tv_sec = 1;
+           rqt.tv_nsec = 0;
+           nanosleep(&rqt, NULL);
+# else
+           sleep(1);   
+# endif
+           D_X((stderr, "InheritPixmap Turning on (%d parents)", i - 1));
+           for (n = 0; n < (unsigned int)i; n++)
+               XSetWindowBackgroundPixmap(R->Xdisplay, R->TermWin.parent[n],
+                                          ParentRelative);
+           XSetWindowBackgroundPixmap(R->Xdisplay, R->TermWin.vt,
+                                      ParentRelative);
+           R->h->am_transparent = 1;
+       }
+       for (; i < (int)(sizeof(R->TermWin.parent) / sizeof(Window)); i++)
+           R->TermWin.parent[i] = None;
+    }
+    return pchanged;
+}
+#endif
+
+/*}}} */
+
+/*{{{ print pipe */
+/*----------------------------------------------------------------------*/
+#ifdef PRINTPIPE
+/* EXTPROTO */
+FILE           *
+rxvt_popen_printer(pR)
+{
+    FILE           *stream = popen(R->h->rs[Rs_print_pipe], "w");
+
+    if (stream == NULL)
+       rxvt_print_error("can't open printer pipe");
+    return stream;
+}
+
+/* EXTPROTO */
+int
+rxvt_pclose_printer(FILE *stream)
+{
+    fflush(stream);
+/* pclose() reported not to work on SunOS 4.1.3 */
+# if defined (__sun__)         /* TODO: RESOLVE THIS */
+/* pclose works provided SIGCHLD handler uses waitpid */
+    return pclose(stream);     /* return fclose (stream); */
+# else
+    return pclose(stream);
+# endif
+}
+
+/*
+ * simulate attached vt100 printer
+ */
+/* INTPROTO */
+void
+rxvt_process_print_pipe(pR)
+{
+    int             done;
+    FILE           *fd;
+
+    if ((fd = rxvt_popen_printer(aR)) == NULL)
+       return;
+
+/*
+ * Send all input to the printer until either ESC[4i or ESC[?4i
+ * is received.
+ */
+    for (done = 0; !done;) {
+       unsigned char   buf[8];
+       unsigned char   ch;
+       unsigned int    i, len;
+
+       if ((ch = rxvt_cmd_getc(aR)) != C0_ESC) {
+           if (putc(ch, fd) == EOF)
+               break;          /* done = 1 */
+       } else {
+           len = 0;
+           buf[len++] = ch;
+
+           if ((buf[len++] = rxvt_cmd_getc(aR)) == '[') {
+               if ((ch = rxvt_cmd_getc(aR)) == '?') {
+                   buf[len++] = '?';
+                   ch = rxvt_cmd_getc(aR);
+               }
+               if ((buf[len++] = ch) == '4') {
+                   if ((buf[len++] = rxvt_cmd_getc(aR)) == 'i')
+                       break;  /* done = 1 */
+               }
+           }
+           for (i = 0; i < len; i++)
+               if (putc(buf[i], fd) == EOF) {
+                   done = 1;
+                   break;
+               }
+       }
+    }
+    rxvt_pclose_printer(fd);
+}
+#endif                         /* PRINTPIPE */
+/*}}} */
+
+/* *INDENT-OFF* */
+enum {
+    C1_40 = 0x40,
+           C1_41 , C1_BPH, C1_NBH, C1_44 , C1_NEL, C1_SSA, C1_ESA,
+    C1_HTS, C1_HTJ, C1_VTS, C1_PLD, C1_PLU, C1_RI , C1_SS2, C1_SS3,
+    C1_DCS, C1_PU1, C1_PU2, C1_STS, C1_CCH, C1_MW , C1_SPA, C1_EPA,
+    C1_SOS, C1_59 , C1_SCI, C1_CSI, CS_ST , C1_OSC, C1_PM , C1_APC
+};
+/* *INDENT-ON* */
+
+/*{{{ process non-printing single characters */
+/* INTPROTO */
+void
+rxvt_process_nonprinting(pR_ unsigned char ch)
+{
+    switch (ch) {
+    case C0_ENQ:       /* terminal Status */
+       if (R->h->rs[Rs_answerbackstring])
+           rxvt_tt_write(aR_
+               (const unsigned char *)R->h->rs[Rs_answerbackstring],
+               (unsigned int)STRLEN(R->h->rs[Rs_answerbackstring]));
+       else
+           rxvt_tt_write(aR_ (unsigned char *)VT100_ANS,
+                         (unsigned int)STRLEN(VT100_ANS));
+       break;
+    case C0_BEL:       /* bell */
+       rxvt_scr_bell(aR);
+       break;
+    case C0_BS:                /* backspace */
+       rxvt_scr_backspace(aR);
+       break;
+    case C0_HT:                /* tab */
+       rxvt_scr_tab(aR_ 1);
+       break;
+    case C0_CR:                /* carriage return */
+       rxvt_scr_gotorc(aR_ 0, 0, R_RELATIVE);
+       break;
+    case C0_VT:                /* vertical tab, form feed */
+    case C0_FF:
+    case C0_LF:                /* line feed */
+       rxvt_scr_index(aR_ UP);
+       break;
+    case C0_SO:                /* shift out - acs */
+       rxvt_scr_charset_choose(aR_ 1);
+       break;
+    case C0_SI:                /* shift in - acs */
+       rxvt_scr_charset_choose(aR_ 0);
+       break;
+    }
+}
+/*}}} */
+
+
+/*{{{ process VT52 escape sequences */
+/* INTPROTO */
+void
+rxvt_process_escape_vt52(pR_ unsigned char ch)
+{
+    int row, col;
+    
+    switch (ch) {
+    case 'A':          /* cursor up */
+       rxvt_scr_gotorc(aR_ -1, 0, R_RELATIVE | C_RELATIVE);    
+       break;
+    case 'B':          /* cursor down */
+       rxvt_scr_gotorc(aR_ 1, 0, R_RELATIVE | C_RELATIVE);     
+       break;
+    case 'C':          /* cursor right */
+       rxvt_scr_gotorc(aR_ 0, 1, R_RELATIVE | C_RELATIVE);     
+       break;
+    case 'D':          /* cursor left */
+       rxvt_scr_gotorc(aR_ 0, -1, R_RELATIVE | C_RELATIVE);    
+       break;
+    case 'H':          /* cursor home */
+       rxvt_scr_gotorc(aR_ 0, 0, 0);   
+       break;
+    case 'I':          /* cursor up and scroll down if needed */
+       rxvt_scr_index(aR_ DN);
+       break;
+    case 'J':          /* erase to end of screen */
+       rxvt_scr_erase_screen(aR_ 0);
+       break;
+    case 'K':          /* erase to end of line */
+       rxvt_scr_erase_line(aR_ 0);
+       break;
+    case 'Y':          /* move to specified row and col */
+         /* full command is 'ESC Y row col' where row and col
+          * are encoded by adding 32 and sending the ascii
+          * character.  eg. SPACE = 0, '+' = 13, '0' = 18,
+          * etc. */
+       row = rxvt_cmd_getc(aR) - ' ';
+       col = rxvt_cmd_getc(aR) - ' ';
+       rxvt_scr_gotorc(aR_ row, col, 0);
+       break;
+    case 'Z':          /* identify the terminal type */
+       rxvt_tt_printf(aR_ "\033/Z");   /* I am a VT100 emulating a VT52 */
+        break;
+    case '<':          /* turn off VT52 mode */
+        PrivMode(0, PrivMode_vt52);
+       break;
+    case 'F':          /* use special graphics character set */
+    case 'G':           /* use regular character set */
+         /* unimplemented */
+       break;
+    case '=':          /* use alternate keypad mode */
+    case '>':           /* use regular keypad mode */
+         /* unimplemented */
+       break;
+    }
+}
+/*}}} */
+
+
+/*{{{ process escape sequences */
+/* INTPROTO */
+void
+rxvt_process_escape_seq(pR)
+{
+    unsigned char   ch = rxvt_cmd_getc(aR);
+
+    if (R->h->PrivateModes & PrivMode_vt52) {
+       rxvt_process_escape_vt52(aR_ ch);
+       return;
+    }
+    
+    switch (ch) {
+    /* case 1:        do_tek_mode (); break; */
+    case '#':
+       if (rxvt_cmd_getc(aR) == '8')
+           rxvt_scr_E(aR);
+       break;
+    case '(':
+       rxvt_scr_charset_set(aR_ 0, (unsigned int)rxvt_cmd_getc(aR));
+       break;
+    case ')':
+       rxvt_scr_charset_set(aR_ 1, (unsigned int)rxvt_cmd_getc(aR));
+       break;
+    case '*':
+       rxvt_scr_charset_set(aR_ 2, (unsigned int)rxvt_cmd_getc(aR));
+       break;
+    case '+':
+       rxvt_scr_charset_set(aR_ 3, (unsigned int)rxvt_cmd_getc(aR));
+       break;
+#ifdef MULTICHAR_SET
+    case '$':
+       rxvt_scr_charset_set(aR_ -2, (unsigned int)rxvt_cmd_getc(aR));
+       break;
+#endif
+#ifndef NO_FRILLS
+    case '6':
+       rxvt_scr_backindex(aR);
+       break;
+#endif
+    case '7':
+       rxvt_scr_cursor(aR_ SAVE);
+       break;
+    case '8':
+       rxvt_scr_cursor(aR_ RESTORE);
+       break;
+#ifndef NO_FRILLS
+    case '9':
+       rxvt_scr_forwardindex(aR);
+       break;
+#endif
+    case '=':
+    case '>':
+       PrivMode((ch == '='), PrivMode_aplKP);
+       break;
+
+    case C1_40:
+       rxvt_cmd_getc(aR);
+       break;
+    case C1_44:
+       rxvt_scr_index(aR_ UP);
+       break;
+
+    /* 8.3.87: NEXT LINE */
+    case C1_NEL:               /* ESC E */
+        {
+          uint32_t nlcr[] = { '\n', '\r' };
+          rxvt_scr_add_lines(aR_ nlcr, 1, 2);
+        }
+       break;
+
+    /* kidnapped escape sequence: Should be 8.3.48 */
+    case C1_ESA:               /* ESC G */
+       rxvt_process_graphics(aR);
+       break;
+
+    /* 8.3.63: CHARACTER TABULATION SET */
+    case C1_HTS:               /* ESC H */
+       rxvt_scr_set_tab(aR_ 1);
+       break;
+
+    /* 8.3.105: REVERSE LINE FEED */
+    case C1_RI:                        /* ESC M */
+       rxvt_scr_index(aR_ DN);
+       break;
+
+    /* 8.3.142: SINGLE-SHIFT TWO */
+    /*case C1_SS2: scr_single_shift (2);   break; */
+
+    /* 8.3.143: SINGLE-SHIFT THREE */
+    /*case C1_SS3: scr_single_shift (3);   break; */
+
+    /* 8.3.27: DEVICE CONTROL STRING */
+    case C1_DCS:               /* ESC P */
+       rxvt_process_dcs_seq(aR);
+       break;
+
+    /* 8.3.110: SINGLE CHARACTER INTRODUCER */
+    case C1_SCI:               /* ESC Z */
+       rxvt_tt_write(aR_ (const unsigned char *)ESCZ_ANSWER,
+                     (unsigned int)(sizeof(ESCZ_ANSWER) - 1));
+       break;                  /* steal obsolete ESC [ c */
+
+    /* 8.3.16: CONTROL SEQUENCE INTRODUCER */
+    case C1_CSI:               /* ESC [ */
+       rxvt_process_csi_seq(aR);
+       break;
+
+    /* 8.3.90: OPERATING SYSTEM COMMAND */
+    case C1_OSC:               /* ESC ] */
+       rxvt_process_osc_seq(aR);
+       break;
+
+    /* 8.3.106: RESET TO INITIAL STATE */
+    case 'c':
+       rxvt_scr_poweron(aR);
+       rxvt_scrollbar_show(aR_ 1);
+       break;
+
+    /* 8.3.79: LOCKING-SHIFT TWO (see ISO2022) */
+    case 'n':
+       rxvt_scr_charset_choose(aR_ 2);
+       break;
+
+    /* 8.3.81: LOCKING-SHIFT THREE (see ISO2022) */
+    case 'o':
+       rxvt_scr_charset_choose(aR_ 3);
+       break;
+    }
+}
+/*}}} */
+
+/*{{{ process CONTROL SEQUENCE INTRODUCER (CSI) sequences `ESC[' */
+/* *INDENT-OFF* */
+enum {
+    CSI_ICH = 0x40,
+            CSI_CUU, CSI_CUD, CSI_CUF, CSI_CUB, CSI_CNL, CSI_CPL, CSI_CHA,
+    CSI_CUP, CSI_CHT, CSI_ED , CSI_EL , CSI_IL , CSI_DL , CSI_EF , CSI_EA ,
+    CSI_DCH, CSI_SEE, CSI_CPR, CSI_SU , CSI_SD , CSI_NP , CSI_PP , CSI_CTC,
+    CSI_ECH, CSI_CVT, CSI_CBT, CSI_SRS, CSI_PTX, CSI_SDS, CSI_SIMD, CSI_5F,
+    CSI_HPA, CSI_HPR, CSI_REP, CSI_DA , CSI_VPA, CSI_VPR, CSI_HVP, CSI_TBC,
+    CSI_SM , CSI_MC , CSI_HPB, CSI_VPB, CSI_RM , CSI_SGR, CSI_DSR, CSI_DAQ,
+    CSI_70 , CSI_71 , CSI_72 , CSI_73 , CSI_74 , CSI_75 , CSI_76 , CSI_77 ,
+    CSI_78 , CSI_79 , CSI_7A , CSI_7B , CSI_7C , CSI_7D , CSI_7E , CSI_7F 
+};
+
+#define make_byte(b7,b6,b5,b4,b3,b2,b1,b0)                     \
+    (((b7) << 7) | ((b6) << 6) | ((b5) << 5) | ((b4) << 4)     \
+     | ((b3) << 3) | ((b2) << 2) | ((b1) << 1) | (b0))
+#define get_byte_array_bit(array, bit)                         \
+    (!!((array)[(bit) / 8] & (128 >> ((bit) & 7))))
+
+const unsigned char csi_defaults[] = {
+    make_byte(1,1,1,1,1,1,1,1),        /* @, A, B, C, D, E, F, G, */
+    make_byte(1,1,0,0,1,1,0,0),        /* H, I, J, K, L, M, N, O, */
+    make_byte(1,0,1,1,1,1,1,0),        /* P, Q, R, S, T, U, V, W, */
+    make_byte(1,1,1,0,0,0,1,0),        /* X, Y, Z, [, \, ], ^, _, */
+    make_byte(1,1,1,0,1,1,1,0),        /* `, a, b, c, d, e, f, g, */
+    make_byte(0,0,1,1,0,0,0,0),        /* h, i, j, k, l, m, n, o, */
+    make_byte(0,0,0,0,0,0,0,0),        /* p, q, r, s, t, u, v, w, */
+    make_byte(0,0,0,0,0,0,0,0) /* x, y, z, {, |, }, ~,    */
+};
+/* *INDENT-ON* */
+
+/* INTPROTO */
+void
+rxvt_process_csi_seq(pR)
+{
+    unsigned char   ch, priv, i;
+    unsigned int    nargs, p;
+    int             n, ndef;
+    int             arg[ESC_ARGS];
+
+    for (nargs = ESC_ARGS; nargs > 0;)
+       arg[--nargs] = 0;
+
+    priv = 0;
+    ch = rxvt_cmd_getc(aR);
+    if (ch >= '<' && ch <= '?') {      /* '<' '=' '>' '?' */
+       priv = ch;
+       ch = rxvt_cmd_getc(aR);
+    }
+/* read any numerical arguments */
+    for (n = -1; ch < CSI_ICH; ) {
+       if (isdigit(ch)) {
+           if (n < 0)
+               n = ch - '0';
+           else
+               n = n * 10 + ch - '0';
+       } else if (ch == ';') {
+           if (nargs < ESC_ARGS)
+               arg[nargs++] = n;
+           n = -1;
+       } else if (ch == '\b') {
+           rxvt_scr_backspace(aR);
+       } else if (ch == C0_ESC) {
+           rxvt_process_escape_seq(aR);
+           return;
+       } else if (ch < ' ') {
+           rxvt_process_nonprinting(aR_ ch);
+       }
+       ch = rxvt_cmd_getc(aR);
+    }
+
+    if (ch > CSI_7F)
+       return;
+
+    if (nargs < ESC_ARGS)
+       arg[nargs++] = n;
+
+    i = ch - CSI_ICH;
+    ndef = get_byte_array_bit(csi_defaults, i);
+    for (p = 0; p < nargs; p++)
+       if (arg[p] == -1)
+           arg[p] = ndef;
+
+#ifdef DEBUG_CMD
+    fprintf(stderr, "CSI ");
+    for (p = 0; p < nargs; p++)
+       fprintf(stderr, "%d%s", arg[p], p < nargs - 1 ? ";" : "");
+    fprintf(stderr, "%c\n", ch);
+#endif
+
+/*
+ * private mode handling
+ */
+    if (priv) {
+       switch (priv) {
+       case '>':
+           if (ch == CSI_DA)   /* secondary device attributes */
+               rxvt_tt_printf(aR_ "\033[>%d;%-.8s;0c", 'R', VSTRING);
+           break;
+       case '?':
+           if (ch == 'h' || ch == 'l' || ch == 'r' || ch == 's' || ch == 't')
+               rxvt_process_terminal_mode(aR_ ch, priv, nargs, arg);
+           break;
+       }
+       return;
+    }
+
+    switch (ch) {
+/*
+ * ISO/IEC 6429:1992(E) CSI sequences (defaults in parentheses)
+ */
+#ifdef PRINTPIPE
+    case CSI_MC:               /* 8.3.83: (0) MEDIA COPY */
+       switch (arg[0]) {
+       case 0:                 /* initiate transfer to primary aux device */
+           rxvt_scr_printscreen(aR_ 0);
+           break;
+       case 5:                 /* start relay to primary aux device */
+           rxvt_process_print_pipe(aR);
+           break;
+       }
+       break;
+#endif
+
+    case CSI_CUU:              /* 8.3.22: (1) CURSOR UP */
+    case CSI_VPR:              /* 8.3.161: (1) LINE POSITION FORWARD */
+       arg[0] = -arg[0];
+    /* FALLTHROUGH */
+    case CSI_CUD:              /* 8.3.19: (1) CURSOR DOWN */
+    case CSI_VPB:              /* 8.3.160: (1) LINE POSITION BACKWARD */
+       rxvt_scr_gotorc(aR_ arg[0], 0, RELATIVE);
+       break;
+
+    case CSI_CUB:              /* 8.3.18: (1) CURSOR LEFT */
+    case CSI_HPB:              /* 8.3.59: (1) CHARACTER POSITION BACKWARD */
+#ifdef ISO6429
+       arg[0] = -arg[0];
+#else                          /* emulate common DEC VTs */
+       arg[0] = arg[0] ? -arg[0] : -1;
+#endif
+    /* FALLTHROUGH */
+    case CSI_CUF:              /* 8.3.20: (1) CURSOR RIGHT */
+    case CSI_HPR:              /* 8.3.60: (1) CHARACTER POSITION FORWARD */
+#ifdef ISO6429
+       rxvt_scr_gotorc(aR_ 0, arg[0], RELATIVE);
+#else                          /* emulate common DEC VTs */
+       rxvt_scr_gotorc(aR_ 0, arg[0] ? arg[0] : 1, RELATIVE);
+#endif
+       break;
+
+    case CSI_CPL:              /* 8.3.13: (1) CURSOR PRECEDING LINE */
+       arg[0] = -arg[0];
+    /* FALLTHROUGH */
+    case CSI_CNL:              /* 8.3.12: (1) CURSOR NEXT LINE */
+       rxvt_scr_gotorc(aR_ arg[0], 0, R_RELATIVE);
+       break;
+
+    case CSI_CHA:              /* 8.3.9: (1) CURSOR CHARACTER ABSOLUTE */
+    case CSI_HPA:              /* 8.3.58: (1) CURSOR POSITION ABSOLUTE */
+       rxvt_scr_gotorc(aR_ 0, arg[0] - 1, R_RELATIVE);
+       break;
+
+    case CSI_VPA:              /* 8.3.159: (1) LINE POSITION ABSOLUTE */
+       rxvt_scr_gotorc(aR_ arg[0] - 1, 0, C_RELATIVE);
+       break;
+
+    case CSI_CUP:              /* 8.3.21: (1,1) CURSOR POSITION */
+    case CSI_HVP:              /* 8.3.64: (1,1) CHARACTER AND LINE POSITION */
+       rxvt_scr_gotorc(aR_ arg[0] - 1, nargs < 2 ? 0 : (arg[1] - 1), 0);
+       break;
+
+    case CSI_CBT:              /* 8.3.7: (1) CURSOR BACKWARD TABULATION */
+       arg[0] = -arg[0];
+    /* FALLTHROUGH */
+    case CSI_CHT:              /* 8.3.10: (1) CURSOR FORWARD TABULATION */
+       rxvt_scr_tab(aR_ arg[0]);
+       break;
+
+    case CSI_ED:               /* 8.3.40: (0) ERASE IN PAGE */
+       rxvt_scr_erase_screen(aR_ arg[0]);
+       break;
+
+    case CSI_EL:               /* 8.3.42: (0) ERASE IN LINE */
+       rxvt_scr_erase_line(aR_ arg[0]);
+       break;
+
+    case CSI_ICH:              /* 8.3.65: (1) INSERT CHARACTER */
+       rxvt_scr_insdel_chars(aR_ arg[0], INSERT);
+       break;
+
+    case CSI_IL:               /* 8.3.68: (1) INSERT LINE */
+       rxvt_scr_insdel_lines(aR_ arg[0], INSERT);
+       break;
+
+    case CSI_DL:               /* 8.3.33: (1) DELETE LINE */
+       rxvt_scr_insdel_lines(aR_ arg[0], DELETE);
+       break;
+
+    case CSI_ECH:              /* 8.3.39: (1) ERASE CHARACTER */
+       rxvt_scr_insdel_chars(aR_ arg[0], ERASE);
+       break;
+
+    case CSI_DCH:              /* 8.3.26: (1) DELETE CHARACTER */
+       rxvt_scr_insdel_chars(aR_ arg[0], DELETE);
+       break;
+
+    case CSI_SD:               /* 8.3.114: (1) SCROLL DOWN */
+       arg[0] = -arg[0];
+    /* FALLTHROUGH */
+    case CSI_SU:               /* 8.3.148: (1) SCROLL UP */
+       rxvt_scroll_text(aR_ R->screen.tscroll, R->screen.bscroll, arg[0], 0);
+       break;
+
+    case CSI_DA:               /* 8.3.24: (0) DEVICE ATTRIBUTES */
+       rxvt_tt_write(aR_ (const unsigned char *)VT100_ANS,
+                     (unsigned int)(sizeof(VT100_ANS) - 1));
+       break;
+
+    case CSI_SGR:              /* 8.3.118: (0) SELECT GRAPHIC RENDITION */
+       rxvt_process_sgr_mode(aR_ nargs, arg);
+       break;
+
+    case CSI_DSR:              /* 8.3.36: (0) DEVICE STATUS REPORT */
+       switch (arg[0]) {
+       case 5:                 /* DSR requested */
+           rxvt_tt_printf(aR_ "\033[0n");
+           break;
+       case 6:                 /* CPR requested */
+           rxvt_scr_report_position(aR);
+           break;
+#if defined (ENABLE_DISPLAY_ANSWER)
+       case 7:                 /* unofficial extension */
+           rxvt_tt_printf(aR_ "%-.250s\n", R->h->rs[Rs_display_name]);
+           break;
+#endif
+       case 8:                 /* unofficial extension */
+           rxvt_xterm_seq(aR_ XTerm_title, APL_NAME "-" VERSION, CHAR_ST);
+           break;
+       }
+       break;
+
+    case CSI_TBC:              /* 8.3.155: (0) TABULATION CLEAR */
+       switch (arg[0]) {
+       case 0:                 /* char tab stop cleared at active position */
+           rxvt_scr_set_tab(aR_ 0);
+           break;
+       /* case 1: */           /* line tab stop cleared in active line */
+       /* case 2: */           /* char tab stops cleared in active line */
+       case 3:                 /* all char tab stops are cleared */
+       /* case 4: */           /* all line tab stops are cleared */
+       case 5:                 /* all tab stops are cleared */
+           rxvt_scr_set_tab(aR_ -1);
+           break;
+       }
+       break;
+
+    case CSI_CTC:              /* 8.3.17: (0) CURSOR TABULATION CONTROL */
+       switch (arg[0]) {
+       case 0:                 /* char tab stop set at active position */
+           rxvt_scr_set_tab(aR_ 1);
+           break;              /* = ESC H */
+       /* case 1: */           /* line tab stop set at active line */
+       case 2:                 /* char tab stop cleared at active position */
+           rxvt_scr_set_tab(aR_ 0);
+           break;              /* = ESC [ 0 g */
+       /* case 3: */           /* line tab stop cleared at active line */
+       /* case 4: */           /* char tab stops cleared at active line */
+       case 5:                 /* all char tab stops are cleared */
+           rxvt_scr_set_tab(aR_ -1);
+           break;              /* = ESC [ 3 g */
+       /* case 6: */           /* all line tab stops are cleared */
+       }
+       break;
+
+    case CSI_RM:               /* 8.3.107: RESET MODE */
+       if (arg[0] == 4)
+           rxvt_scr_insert_mode(aR_ 0);
+       break;
+
+    case CSI_SM:               /* 8.3.126: SET MODE */
+       if (arg[0] == 4)
+           rxvt_scr_insert_mode(aR_ 1);
+       break;
+
+/*
+ * PRIVATE USE beyond this point.  All CSI_7? sequences here
+ */ 
+    case CSI_72:               /* DECSTBM: set top and bottom margins */
+       if (nargs == 1)
+           rxvt_scr_scroll_region(aR_ arg[0] - 1, MAX_ROWS - 1);
+       else if (nargs == 0 || arg[0] >= arg[1])
+           rxvt_scr_scroll_region(aR_ 0, MAX_ROWS - 1);
+       else 
+           rxvt_scr_scroll_region(aR_ arg[0] - 1, arg[1] - 1);
+       break;
+
+    case CSI_73:
+       rxvt_scr_cursor(aR_ SAVE);
+       break;
+    case CSI_75:
+       rxvt_scr_cursor(aR_ RESTORE);
+       break;
+
+#ifndef NO_FRILLS
+    case CSI_74:
+       rxvt_process_window_ops(aR_ arg, nargs);
+       break;
+#endif
+
+    case CSI_78:               /* DECREQTPARM */
+       if (arg[0] == 0 || arg[0] == 1)
+           rxvt_tt_printf(aR_ "\033[%d;1;1;112;112;1;0x", arg[0] + 2);
+    /* FALLTHROUGH */
+
+    default:
+       break;
+    }
+}
+/*}}} */
+
+#ifndef NO_FRILLS
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_process_window_ops(pR_ const int *args, unsigned int nargs)
+{
+    int             x, y;
+#if 0
+    char           *s;
+#endif
+    XWindowAttributes wattr;
+    Window          wdummy;
+
+    if (nargs == 0)
+       return;
+    switch (args[0]) {
+    /*
+     * commands
+     */
+    case 1:                    /* deiconify window */
+       XMapWindow(R->Xdisplay, R->TermWin.parent[0]);
+       break;
+    case 2:                    /* iconify window */
+       XIconifyWindow(R->Xdisplay, R->TermWin.parent[0],
+                      DefaultScreen(R->Xdisplay));
+       break;
+    case 3:                    /* set position (pixels) */
+       XMoveWindow(R->Xdisplay, R->TermWin.parent[0], args[1], args[2]);
+       break;
+    case 4:                    /* set size (pixels) */
+       rxvt_set_widthheight(aR_ (unsigned int)args[2], (unsigned int)args[1]);
+       break;
+    case 5:                    /* raise window */
+       XRaiseWindow(R->Xdisplay, R->TermWin.parent[0]);
+       break;
+    case 6:                    /* lower window */
+       XLowerWindow(R->Xdisplay, R->TermWin.parent[0]);
+       break;
+    case 7:                    /* refresh window */
+       rxvt_scr_touch(aR_ True);
+       break;
+    case 8:                    /* set size (chars) */
+       rxvt_set_widthheight(aR_ (unsigned int)(args[2] * R->TermWin.fwidth),
+                            (unsigned int)(args[1] * R->TermWin.fheight));
+       break;
+    default:
+       if (args[0] >= 24)      /* set height (chars) */
+           rxvt_set_widthheight(aR_ (unsigned int)R->TermWin.width,
+                                (unsigned int)(args[1] * R->TermWin.fheight));
+       break;
+    /*
+     * reports - some output format copied from XTerm
+     */
+    case 11:                   /* report window state */
+       XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr);
+       rxvt_tt_printf(aR_ "\033[%dt", wattr.map_state == IsViewable ? 1 : 2);
+       break;
+    case 13:                   /* report window position */
+       XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr);
+       XTranslateCoordinates(R->Xdisplay, R->TermWin.parent[0], wattr.root,
+                             -wattr.border_width, -wattr.border_width,
+                             &x, &y, &wdummy);
+       rxvt_tt_printf(aR_ "\033[3;%d;%dt", x, y);
+       break;
+    case 14:                   /* report window size (pixels) */
+       XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr);
+       rxvt_tt_printf(aR_ "\033[4;%d;%dt", wattr.height, wattr.width);
+       break;
+    case 18:                   /* report window size (chars) */
+       rxvt_tt_printf(aR_ "\033[8;%d;%dt", R->TermWin.nrow, R->TermWin.ncol);
+       break;
+#if 0 /* XXX: currently disabled due to security concerns */
+    case 20:                   /* report icon label */
+       XGetIconName(R->Xdisplay, R->TermWin.parent[0], &s);
+       rxvt_tt_printf(aR_ "\033]L%-.200s\234", s ? s : "");    /* 8bit ST */
+       break;
+    case 21:                   /* report window title */
+       XFetchName(R->Xdisplay, R->TermWin.parent[0], &s);
+       rxvt_tt_printf(aR_ "\033]l%-.200s\234", s ? s : "");    /* 8bit ST */
+       break;
+#endif
+    }
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+/*
+ * get input up until STRING TERMINATOR (or BEL)
+ * ends_how is terminator used.  returned input must be free()d
+ */
+/* INTPROTO */
+unsigned char  *
+rxvt_get_to_st(pR_ unsigned char *ends_how)
+{
+    int             seen_esc = 0;      /* seen escape? */
+    unsigned int    n = 0;
+    unsigned char  *s;
+    unsigned char   ch, string[STRING_MAX];
+
+    for (; (ch = rxvt_cmd_getc(aR));) {
+       if (ch == C0_BEL
+           || ch == CHAR_ST
+           || (ch == 0x5c && seen_esc))        /* 7bit ST */
+           break;
+       if (ch == C0_ESC) {
+           seen_esc = 1;
+           continue;
+       } else if (ch == '\t')
+           ch = ' ';   /* translate '\t' to space */
+       else if (ch < 0x08 || (ch > 0x0d && ch < 0x20))
+           return NULL;        /* other control character - exit */
+       if (n < sizeof(string) - 1)
+           string[n++] = ch;
+       seen_esc = 0;
+    }
+    string[n++] = '\0';
+    if ((s = (unsigned char *)rxvt_malloc(n)) == NULL)
+       return NULL;
+    *ends_how = (ch == 0x5c ? C0_ESC : ch);
+    STRNCPY(s, string, n);
+    return s;
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * process DEVICE CONTROL STRING `ESC P ... (ST|BEL)' or `0x90 ... (ST|BEL)'
+ */
+/* INTPROTO */
+void
+rxvt_process_dcs_seq(pR)
+{
+    unsigned char    eh, *s;
+/*
+ * Not handled yet
+ */
+    s = rxvt_get_to_st(aR_ &eh);
+    if (s)
+       free(s);
+    return;
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * process OPERATING SYSTEM COMMAND sequence `ESC ] Ps ; Pt (ST|BEL)'
+ */
+/* INTPROTO */
+void
+rxvt_process_osc_seq(pR)
+{
+    unsigned char   ch, eh, *s;
+    int             arg;
+
+    ch = rxvt_cmd_getc(aR);
+    for (arg = 0; isdigit(ch); ch = rxvt_cmd_getc(aR))
+       arg = arg * 10 + (ch - '0');
+
+    if (ch == ';') {
+       s = rxvt_get_to_st(aR_ &eh);
+       if (s) {
+    /*
+     * rxvt_menubar_dispatch() violates the constness of the string,
+     * so do it here
+     */
+           if (arg == XTerm_Menu)
+#if 0 /* XXX: currently disabled due to security concerns */
+               rxvt_menubar_dispatch(aR_ (char *)s);
+#else
+               0;
+#endif
+           else
+               rxvt_xterm_seq(aR_ arg, (char *)s, eh);
+           free(s);
+       }
+    }
+}
+/*
+ * XTerm escape sequences: ESC ] Ps;Pt (ST|BEL)
+ *       0 = change iconName/title
+ *       1 = change iconName
+ *       2 = change title
+ *       4 = change color
+ *      12 = change text color
+ *      13 = change mouse foreground color 
+ *      17 = change highlight character colour
+ *      18 = change bold character color
+ *      19 = change underlined character color 
+ *      46 = change logfile (not implemented)
+ *      50 = change font
+ *
+ * rxvt extensions:
+ *      10 = menu (may change in future)
+ *      20 = bg pixmap
+ *      39 = change default fg color
+ *      49 = change default bg color
+ *      55 = dump scrollback buffer and all of screen
+ */
+/* EXTPROTO */
+void
+rxvt_xterm_seq(pR_ int op, const char *str, unsigned char resp __attribute__((unused)))
+{
+    int             changed = 0;
+    int             color;
+    char           *buf, *name;
+
+    assert(str != NULL);
+    switch (op) {
+    case XTerm_name:
+       rxvt_set_title(aR_ str);
+    /* FALLTHROUGH */
+    case XTerm_iconName:
+       rxvt_set_iconName(aR_ str);
+       break;
+    case XTerm_title:
+       rxvt_set_title(aR_ str);
+       break;
+    case XTerm_Color:
+       for (buf = (char *)str; buf && *buf;) {
+           if ((name = STRCHR(buf, ';')) == NULL)
+               break;
+           *name++ = '\0';
+           color = atoi(buf);
+           if (color < 0 || color >= TOTAL_COLORS)
+               break;
+           if ((buf = STRCHR(name, ';')) != NULL)
+               *buf++ = '\0';
+           rxvt_set_window_color(aR_ color + minCOLOR, name);
+       }
+       break;
+#ifndef NO_CURSORCOLOR
+    case XTerm_Color_cursor:
+       rxvt_set_window_color(aR_ Color_cursor, str);
+       break;
+#endif
+    case XTerm_Color_pointer:
+       rxvt_set_window_color(aR_ Color_pointer, str);
+       break;
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+    case XTerm_Color_BD:
+       rxvt_set_window_color(aR_ Color_BD, str);
+       break;
+    case XTerm_Color_UL:
+       rxvt_set_window_color(aR_ Color_UL, str);
+       break;
+    case XTerm_Color_RV:
+       rxvt_set_window_color(aR_ Color_RV, str);
+       break;
+#endif
+
+    case XTerm_Menu:
+        /*
+         * rxvt_menubar_dispatch() violates the constness of the string,
+         * so DON'T do it here
+         */
+       break;
+    case XTerm_Pixmap:
+       if (*str != ';') {
+#if XPM_BACKGROUND
+           rxvt_scale_pixmap(aR_ "");  /* reset to default scaling */
+           rxvt_set_bgPixmap(aR_ str); /* change pixmap */
+#endif
+           rxvt_scr_touch(aR_ True);
+       }
+       while ((str = STRCHR(str, ';')) != NULL) {
+           str++;
+#if XPM_BACKGROUND
+           changed += rxvt_scale_pixmap(aR_ str);
+#endif
+       }
+       if (changed) {
+#ifdef XPM_BACKGROUND
+           rxvt_resize_pixmap(aR);
+#endif
+           rxvt_scr_touch(aR_ True);
+       }
+       break;
+
+    case XTerm_restoreFG:
+       rxvt_set_window_color(aR_ Color_fg, str);
+       break;
+    case XTerm_restoreBG:
+       rxvt_set_window_color(aR_ Color_bg, str);
+       break;
+    case XTerm_logfile:
+       break;
+    case XTerm_font:
+       rxvt_change_font(aR_ 0, str);
+       break;
+#if 0
+    case XTerm_dumpscreen:     /* no error notices */
+       {
+           int             fd;
+           if ((fd = open(str, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0) {
+               rxvt_scr_dump(aR_ fd);
+               close(fd);
+           }
+       }
+       break;
+#endif
+    }
+}
+/*----------------------------------------------------------------------*/
+
+/*{{{ process DEC private mode sequences `ESC [ ? Ps mode' */
+/*
+ * mode can only have the following values:
+ *      'l' = low
+ *      'h' = high
+ *      's' = save
+ *      'r' = restore
+ *      't' = toggle
+ * so no need for fancy checking
+ */
+/* INTPROTO */
+int
+rxvt_privcases(pR_ int mode, unsigned long bit)
+{
+    int             state;
+
+    if (mode == 's') {
+       R->h->SavedModes |= (R->h->PrivateModes & bit);
+       return -1;
+    } else {
+       if (mode == 'r')
+           state = (R->h->SavedModes & bit) ? 1 : 0;   /* no overlapping */
+       else
+           state = (mode == 't') ? !(R->h->PrivateModes & bit) : mode;
+       PrivMode(state, bit);
+    }
+    return state;
+}
+
+/* we're not using priv _yet_ */
+/* INTPROTO */
+void
+rxvt_process_terminal_mode(pR_ int mode, int priv __attribute__((unused)), unsigned int nargs, const int *arg)
+{
+    unsigned int    i, j;
+    int             state;
+    static const struct {
+       const int       argval;
+       const unsigned long bit;
+    } argtopriv[] = {
+       { 1, PrivMode_aplCUR },
+       { 2, PrivMode_vt52 },
+       { 3, PrivMode_132 },
+       { 4, PrivMode_smoothScroll },
+       { 5, PrivMode_rVideo },
+       { 6, PrivMode_relOrigin },
+       { 7, PrivMode_Autowrap },
+       { 9, PrivMode_MouseX10 },
+#ifdef menuBar_esc
+       { menuBar_esc, PrivMode_menuBar },
+#endif
+#ifdef scrollBar_esc
+       { scrollBar_esc, PrivMode_scrollBar },
+#endif
+       { 25, PrivMode_VisibleCursor },
+       { 35, PrivMode_ShiftKeys },
+       { 40, PrivMode_132OK },
+       { 47, PrivMode_Screen },
+       { 66, PrivMode_aplKP },
+#ifndef NO_BACKSPACE_KEY
+       { 67, PrivMode_BackSpace },
+#endif
+       { 1000, PrivMode_MouseX11 },
+       { 1010, PrivMode_TtyOutputInh },
+       { 1011, PrivMode_Keypress },
+       { 1047, PrivMode_Screen },
+    };
+
+    if (nargs == 0)
+       return;
+
+/* make lo/hi boolean */
+    if (mode == 'l')
+       mode = 0;               /* reset */
+    else if (mode == 'h')
+       mode = 1;               /* set */
+
+    for (i = 0; i < nargs; i++) {
+       state = -1;
+
+       /* basic handling */
+       for (j = 0; j < (sizeof(argtopriv)/sizeof(argtopriv[0])); j++)
+           if (argtopriv[j].argval == arg[i]) {
+               state = rxvt_privcases(aR_ mode, argtopriv[j].bit);
+               break;
+           }
+       
+       /* extra handling for values with state unkept  */
+       if (state == -1)
+           switch (arg[i]) {
+           case 1048:          /* alternative cursor save */
+               if (mode == 0)
+                   rxvt_scr_cursor(aR_ RESTORE);
+               else if (mode == 1)
+                   rxvt_scr_cursor(aR_ SAVE);
+           /* FALLTHROUGH */
+           default:
+               continue;       /* for(;i;) */
+           }
+
+       /* extra handling for values with valid 0 or 1 state */
+       switch (arg[i]) {
+       /* case 1:      - application cursor keys */
+       case 2:                 /* VT52 mode */
+             /* oddball mode.  should be set regardless of set/reset
+              * parameter.  Return from VT52 mode with an ESC < from
+              * within VT52 mode
+              */
+           PrivMode(1, PrivMode_vt52);
+           break;
+       case 3:                 /* 80/132 */
+           if (R->h->PrivateModes & PrivMode_132OK)
+               rxvt_set_widthheight(aR_
+                   (unsigned int)((state ? 132 : 80) * R->TermWin.fwidth),
+                   (unsigned int)R->TermWin.height);
+           break;
+       case 4:                 /* smooth scrolling */
+           if (state)
+               R->Options &= ~Opt_jumpScroll;
+           else
+               R->Options |= Opt_jumpScroll;
+           break;
+       case 5:                 /* reverse video */
+           rxvt_scr_rvideo_mode(aR_ state);
+           break;
+       case 6:                 /* relative/absolute origins  */
+           rxvt_scr_relative_origin(aR_ state);
+           break;
+       case 7:                 /* autowrap */
+           rxvt_scr_autowrap(aR_ state);
+           break;
+       /* case 8:      - auto repeat, can't do on a per window basis */
+       case 9:                 /* X10 mouse reporting */
+           if (state)          /* orthogonal */
+               R->h->PrivateModes &= ~(PrivMode_MouseX11);
+           break;
+#ifdef menuBar_esc
+       case menuBar_esc:
+#ifdef MENUBAR
+           rxvt_map_menuBar(aR_ state);
+#endif
+           break;
+#endif
+#ifdef scrollBar_esc
+       case scrollBar_esc:
+           if (rxvt_scrollbar_mapping(aR_ state)) {
+               rxvt_resize_all_windows(aR_ 0, 0, 0);
+               rxvt_scr_touch(aR_ True);
+           }
+           break;
+#endif
+       case 25:                /* visible/invisible cursor */
+           rxvt_scr_cursor_visible(aR_ state);
+           break;
+       /* case 35:     - shift keys */
+       /* case 40:     - 80 <--> 132 mode */
+       case 47:                /* secondary screen */
+           rxvt_scr_change_screen(aR_ state);
+           break;
+       /* case 66:     - application key pad */
+       /* case 67:     - backspace key */
+       case 1000:              /* X11 mouse reporting */
+           if (state)          /* orthogonal */
+               R->h->PrivateModes &= ~(PrivMode_MouseX10);
+           break;
+#if 0
+       case 1001:
+           break;              /* X11 mouse highlighting */
+#endif
+       case 1010:              /* scroll to bottom on TTY output inhibit */
+           if (state)
+               R->Options &= ~Opt_scrollTtyOutput;
+           else
+               R->Options |= Opt_scrollTtyOutput;
+           break;
+       case 1011:              /* scroll to bottom on key press */
+           if (state)
+               R->Options |= Opt_scrollTtyKeypress;
+           else
+               R->Options &= ~Opt_scrollTtyKeypress;
+           break;
+       case 1047:              /* secondary screen w/ clearing */
+           if (R->h->current_screen != PRIMARY)
+               rxvt_scr_erase_screen(aR_ 2);
+           rxvt_scr_change_screen(aR_ state);
+       /* FALLTHROUGH */
+       default:
+           break;
+       }
+    }
+}
+/*}}} */
+
+/*{{{ process sgr sequences */
+/* INTPROTO */
+void
+rxvt_process_sgr_mode(pR_ unsigned int nargs, const int *arg)
+{
+    unsigned int    i;
+    short           rendset;
+    int             rendstyle;
+
+    if (nargs == 0) {
+       rxvt_scr_rendition(aR_ 0, ~RS_None);
+       return;
+    }
+    for (i = 0; i < nargs; i++) {
+       rendset = -1;
+       switch (arg[i]) {
+       case 0:
+           rendset = 0, rendstyle = ~RS_None;
+           break;
+       case 1:
+           rendset = 1, rendstyle = RS_Bold;
+           break;
+       case 4:
+           rendset = 1, rendstyle = RS_Uline;
+           break;
+       case 5:
+           rendset = 1, rendstyle = RS_Blink;
+           break;
+       case 7:
+           rendset = 1, rendstyle = RS_RVid;
+           break;
+       case 22:
+           rendset = 0, rendstyle = RS_Bold;
+           break;
+       case 24:
+           rendset = 0, rendstyle = RS_Uline;
+           break;
+       case 25:
+           rendset = 0, rendstyle = RS_Blink;
+           break;
+       case 27:
+           rendset = 0, rendstyle = RS_RVid;
+           break;
+       }
+       if (rendset != -1) {
+           rxvt_scr_rendition(aR_ rendset, rendstyle);
+           continue;           /* for(;i;) */
+       }
+
+       switch (arg[i]) {
+       case 30:
+       case 31:                /* set fg color */
+       case 32:
+       case 33:
+       case 34:
+       case 35:
+       case 36:
+       case 37:
+           rxvt_scr_color(aR_ (unsigned int)(minCOLOR + (arg[i] - 30)),
+                          Color_fg);
+           break;
+#ifdef TTY_256COLOR
+       case 38:
+           if (nargs > i + 2 && arg[i + 1] == 5) {
+               rxvt_scr_color(aR_ (unsigned int)(minCOLOR + arg[i + 2]),
+                              Color_fg);
+               i += 2;
+           }
+           break;
+#endif
+       case 39:                /* default fg */
+           rxvt_scr_color(aR_ Color_fg, Color_fg);
+           break;
+
+       case 40:
+       case 41:                /* set bg color */
+       case 42:
+       case 43:
+       case 44:
+       case 45:
+       case 46:
+       case 47:
+           rxvt_scr_color(aR_ (unsigned int)(minCOLOR + (arg[i] - 40)),
+                          Color_bg);
+           break;
+#ifdef TTY_256COLOR
+       case 48:
+           if (nargs > i + 2 && arg[i + 1] == 5) {
+               rxvt_scr_color(aR_ (unsigned int)(minCOLOR + arg[i + 2]),
+                              Color_bg);
+               i += 2;
+           }
+           break;
+#endif
+       case 49:                /* default bg */
+           rxvt_scr_color(aR_ Color_bg, Color_bg);
+           break;
+
+#ifndef NO_BRIGHTCOLOR
+       case 90:
+       case 91:                /* set bright fg color */
+       case 92:
+       case 93:
+       case 94:
+       case 95:
+       case 96:
+       case 97:
+           rxvt_scr_color(aR_ (unsigned int)(minBrightCOLOR + (arg[i] - 90)),
+                          Color_fg);
+           break;
+       case 100:
+       case 101:               /* set bright bg color */
+       case 102:
+       case 103:
+       case 104:
+       case 105:
+       case 106:
+       case 107:
+           rxvt_scr_color(aR_ (unsigned int)(minBrightCOLOR + (arg[i] - 100)),
+                          Color_bg);
+           break;
+#endif
+       }
+    }
+}
+/*}}} */
+
+/*{{{ process Rob Nation's own graphics mode sequences */
+/* INTPROTO */
+void
+rxvt_process_graphics(pR)
+{
+    unsigned char   ch, cmd = rxvt_cmd_getc(aR);
+
+#ifndef RXVT_GRAPHICS
+    if (cmd == 'Q') {          /* query graphics */
+       rxvt_tt_printf(aR_ "\033G0\n"); /* no graphics */
+       return;
+    }
+/* swallow other graphics sequences until terminating ':' */
+    do
+       ch = rxvt_cmd_getc(aR);
+    while (ch != ':');
+#else
+    unsigned int    nargs;
+    int             args[NGRX_PTS];
+    unsigned char  *text = NULL;
+
+    if (cmd == 'Q') {          /* query graphics */
+       rxvt_tt_printf(aR_ "\033G1\n"); /* yes, graphics (color) */
+       return;
+    }
+    for (nargs = 0; nargs < (sizeof(args) / sizeof(args[0])) - 1;) {
+       int             neg;
+
+       ch = rxvt_cmd_getc(aR);
+       neg = (ch == '-');
+       if (neg || ch == '+')
+           ch = rxvt_cmd_getc(aR);
+
+       for (args[nargs] = 0; isdigit(ch); ch = rxvt_cmd_getc(aR))
+           args[nargs] = args[nargs] * 10 + (ch - '0');
+       if (neg)
+           args[nargs] = -args[nargs];
+
+       nargs++;
+       args[nargs] = 0;
+       if (ch != ';')
+           break;
+    }
+
+    if ((cmd == 'T') && (nargs >= 5)) {
+       int             i, len = args[4];
+
+       text = rxvt_malloc((len + 1) * sizeof(char));
+
+       if (text != NULL) {
+           for (i = 0; i < len; i++)
+               text[i] = rxvt_cmd_getc(aR);
+           text[len] = '\0';
+       }
+    }
+    rxvt_Gr_do_graphics(aR_ cmd, nargs, args, text);
+#endif
+}
+/*}}} */
+
+/* ------------------------------------------------------------------------- */
+
+/*{{{ Read and process output from the application */
+/* LIBPROTO */
+void
+rxvt_main_loop(pR)
+{
+    uint32_t ch, *str, buf[BUFSIZ];
+    int nlines, refreshnow;
+    struct rxvt_hidden *h = R->h;
+
+    h->cmdbuf_ptr = h->cmdbuf_endp = h->cmdbuf_base;
+
+    /* once we know the shell is running, send the screen size.  Again! */
+    ch = rxvt_cmd_getc(aR);    /* wait for something */
+    rxvt_tt_winsize(R->cmd_fd, R->TermWin.ncol, R->TermWin.nrow, R->h->cmd_pid);
+
+    refreshnow = 0;
+    for (;;) {
+        if (ch == NOCHAR)
+          ch = rxvt_cmd_getc(aR);
+
+       if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+          {
+            /* Read a text string from the input buffer */
+            nlines = 0;
+            str = buf;
+            *str++ = ch;
+            for (;;)
+              {
+                ch = next_char (aR);
+
+               if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
+                  break;
+                else
+                  {
+                    *str++ = ch;
+
+                    if (ch == '\n')
+                      {
+                        nlines++;
+                        h->refresh_count++;
+                        if (!(R->Options & Opt_jumpScroll)
+                            || (h->refresh_count >= (h->refresh_limit
+                                                     * (R->TermWin.nrow - 1))))
+                          {
+                            refreshnow = 1;
+                            ch = NOCHAR;
+                            break;
+                          }
+                      }
+
+                    if (str >= buf + BUFSIZ)
+                      {
+                        ch = NOCHAR;
+                        break;
+                      }
+                  }
+             }
+
+           rxvt_scr_add_lines(aR_ buf, nlines, str - buf);
+
+            /*
+             * If there have been a lot of new lines, then update the screen
+             * What the heck I'll cheat and only refresh less than every page-full.
+             * the number of pages between refreshes is h->refresh_limit, which
+             * is incremented here because we must be doing flat-out scrolling.
+             *
+             * refreshing should be correct for small scrolls, because of the
+             * time-out
+             */
+
+            //TODO: REFRESH_PERIOD is one, fix it
+           if (refreshnow)
+              {
+               refreshnow = 0;
+
+               if ((R->Options & Opt_jumpScroll) && h->refresh_limit < REFRESH_PERIOD)
+                 h->refresh_limit++;
+
+               rxvt_scr_refresh(aR_ h->refresh_type);
+             }
+
+         }
+        else
+          {
+           switch (ch)
+              {
+                default:
+                    rxvt_process_nonprinting(aR_ ch);
+                    break;
+                case C0_ESC:   /* escape char */
+                    rxvt_process_escape_seq(aR);
+                    break;
+                /* case 0x9b: */       /* CSI */
+                /*  rxvt_process_csi_seq(aR); */
+              }
+
+            ch = NOCHAR;
+          }
+    }
+/* NOTREACHED */
+}
+
+/*
+ * Send printf() formatted output to the command.
+ * Only use for small amounts of data.
+ */
+/* EXTPROTO */
+void
+rxvt_tt_printf(pR_ const char *fmt,...)
+{
+    va_list         arg_ptr;
+    unsigned char   buf[256];
+
+    va_start(arg_ptr, fmt);
+    vsprintf((char *)buf, fmt, arg_ptr);
+    va_end(arg_ptr);
+    rxvt_tt_write(aR_ buf, (unsigned int)STRLEN(buf));
+}
+
+/* ---------------------------------------------------------------------- */
+/* Addresses pasting large amounts of data and rxvt hang
+ * code pinched from xterm (v_write()) and applied originally to
+ * rxvt-2.18 - Hops
+ * Write data to the pty as typed by the user, pasted with the mouse,
+ * or generated by us in response to a query ESC sequence.
+ */
+/* EXTPROTO */
+void
+rxvt_tt_write(pR_ const unsigned char *d, unsigned int len)
+{
+#define MAX_PTY_WRITE 256      /* POSIX minimum MAX_INPUT */
+    int             riten;
+    unsigned int    p;
+    unsigned char  *v_buffer,  /* start of physical buffer        */
+                  *v_bufstr,   /* start of current buffer pending */
+                  *v_bufptr,   /* end of current buffer pending   */
+                  *v_bufend;   /* end of physical buffer          */
+
+    if (R->h->v_bufstr == NULL && len > 0) {
+       p = (len / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE;
+       v_buffer = v_bufstr = v_bufptr = (unsigned char *)rxvt_malloc(p);
+       v_bufend = v_buffer + p;
+    } else {
+       v_buffer = R->h->v_buffer;
+       v_bufstr = R->h->v_bufstr;
+       v_bufptr = R->h->v_bufptr;
+       v_bufend = R->h->v_bufend;
+    }
+
+    /*
+     * Append to the block we already have.  Always doing this simplifies the
+     * code, and isn't too bad, either.  If this is a short block, it isn't
+     * too expensive, and if this is a long block, we won't be able to write
+     * it all anyway.
+     */
+    if (len > 0) {
+       if (v_bufend < v_bufptr + len) {        /* run out of room */
+           if (v_bufstr != v_buffer) {
+           /* there is unused space, move everything down */
+               MEMMOVE(v_buffer, v_bufstr,
+                       (unsigned int)(v_bufptr - v_bufstr));
+               v_bufptr -= v_bufstr - v_buffer;
+               v_bufstr = v_buffer;
+           }
+           if (v_bufend < v_bufptr + len) {
+           /* still won't fit: get more space */
+           /* use most basic realloc because an error is not fatal. */
+               unsigned int    size = v_bufptr - v_buffer;
+               unsigned int    reallocto;
+
+               reallocto = ((size + len) / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE;
+               v_buffer = (unsigned char *)realloc(v_buffer, reallocto);
+           /* save across realloc */
+               if (v_buffer) {
+                   v_bufstr = v_buffer;
+                   v_bufptr = v_buffer + size;
+                   v_bufend = v_buffer + reallocto;
+               } else {        /* no memory: ignore entire write request */
+                   rxvt_print_error("data loss: cannot allocate buffer space");
+                   v_buffer = v_bufstr;        /* restore clobbered pointer */
+               }
+           }
+       }
+       if (v_bufend >= v_bufptr + len) {       /* new stuff will fit */
+           MEMCPY(v_bufptr, d, len);
+           v_bufptr += len;
+       }
+    }
+
+    /*
+     * Write out as much of the buffer as we can.
+     * Be careful not to overflow the pty's input silo.
+     * We are conservative here and only write a small amount at a time.
+     *
+     * If we can't push all the data into the pty yet, we expect write
+     * to return a non-negative number less than the length requested
+     * (if some data written) or -1 and set errno to EAGAIN,
+     * EWOULDBLOCK, or EINTR (if no data written).
+     *
+     * (Not all systems do this, sigh, so the code is actually
+     * a little more forgiving.)
+     */
+    if ((p = v_bufptr - v_bufstr) > 0) {
+       riten = write(R->cmd_fd, v_bufstr, min(p, MAX_PTY_WRITE));
+       if (riten < 0)
+           riten = 0;
+       v_bufstr += riten;
+       if (v_bufstr >= v_bufptr)       /* we wrote it all */
+           v_bufstr = v_bufptr = v_buffer;
+    }
+    /*
+     * If we have lots of unused memory allocated, return it
+     */
+    if (v_bufend - v_bufptr > MAX_PTY_WRITE * 8) { /* arbitrary hysteresis */
+    /* save pointers across realloc */
+       unsigned int    start = v_bufstr - v_buffer;
+       unsigned int    size = v_bufptr - v_buffer;
+       unsigned int    reallocto;
+       
+       reallocto = (size / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE;
+       v_buffer = (unsigned char *)realloc(v_buffer, reallocto);
+       if (v_buffer) {
+           v_bufstr = v_buffer + start;
+           v_bufptr = v_buffer + size;
+           v_bufend = v_buffer + reallocto;
+       } else {
+       /* should we print a warning if couldn't return memory? */
+           v_buffer = v_bufstr - start;        /* restore clobbered pointer */
+       }
+    }
+    R->h->v_buffer = v_buffer;
+    R->h->v_bufstr = v_bufstr;
+    R->h->v_bufptr = v_bufptr;
+    R->h->v_bufend = v_bufend;
+}
+/*----------------------- end-of-file (C source) -----------------------*/
+
diff --git a/src/command.h b/src/command.h
new file mode 100644 (file)
index 0000000..121f937
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * $Id: command.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#ifndef _COMMAND_H_
+#define _COMMAND_H_
+
+#define STRING_MAX     512     /* max string size for process_rxvt_xterm_seq() */
+#define ESC_ARGS       32      /* max # of args for esc sequences */
+
+#ifdef OFFIX_DND
+# define DndFile       2
+# define DndDir                5
+# define DndLink       7
+#endif
+
+/* a large REFRESH_PERIOD causes problems with `cat' */
+#define REFRESH_PERIOD         10
+
+#ifndef MULTICLICK_TIME
+# define MULTICLICK_TIME       500
+#endif
+#ifndef SCROLLBAR_INITIAL_DELAY
+# ifdef NEXT_SCROLLER
+#  define SCROLLBAR_INITIAL_DELAY      20
+# else
+#  define SCROLLBAR_INITIAL_DELAY      40
+# endif
+#endif
+#ifndef SCROLLBAR_CONTINUOUS_DELAY
+# define SCROLLBAR_CONTINUOUS_DELAY    2
+#endif
+
+/*
+ * key-strings: if only these keys were standardized <sigh>
+ */
+#ifdef LINUX_KEYS
+# define KS_HOME       "\033[1~"       /* Home == Find */
+# define KS_END                "\033[4~"       /* End == Select */
+#else
+# define KS_HOME       "\033[7~"       /* Home */
+# define KS_END                "\033[8~"       /* End */
+#endif
+
+#ifdef SCROLL_ON_SHIFT
+# define SCROLL_SHIFTKEY (shft)
+#else
+# define SCROLL_SHIFTKEY 0
+#endif
+#ifdef SCROLL_ON_CTRL
+# define SCROLL_CTRLKEY  (ctrl)
+#else
+# define SCROLL_CTRLKEY 0
+#endif
+#ifdef SCROLL_ON_META
+# define SCROLL_METAKEY  (meta)
+#else
+# define SCROLL_METAKEY 0
+#endif
+#define IS_SCROLL_MOD  (SCROLL_SHIFTKEY || SCROLL_CTRLKEY || SCROLL_METAKEY)
+
+/*
+ * ESC-Z processing:
+ *
+ * By stealing a sequence to which other xterms respond, and sending the
+ * same number of characters, but having a distinguishable sequence,
+ * we can avoid having a timeout (when not under an rxvt) for every login
+ * shell to auto-set its DISPLAY.
+ *
+ * This particular sequence is even explicitly stated as obsolete since
+ * about 1985, so only very old software is likely to be confused, a
+ * confusion which can likely be remedied through termcap or TERM. Frankly,
+ * I doubt anyone will even notice.  We provide a #ifdef just in case they
+ * don't care about auto-display setting.  Just in case the ancient
+ * software in question is broken enough to be case insensitive to the 'c'
+ * character in the answerback string, we make the distinguishing
+ * characteristic be capitalization of that character. The length of the
+ * two strings should be the same so that identical read(2) calls may be
+ * used.
+ */
+#define VT100_ANS      "\033[?1;2c"    /* vt100 answerback */
+#ifndef ESCZ_ANSWER
+# define ESCZ_ANSWER   VT100_ANS       /* obsolete ANSI ESC[c */
+#endif
+
+#include "command.intpro"      /* PROTOS for internal routines */
+#endif /* _COMMAND_H_ */
diff --git a/src/defaultfont.h b/src/defaultfont.h
new file mode 100644 (file)
index 0000000..c61aa84
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * $Id: defaultfont.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#ifndef _DEFAULTFONT_H_
+#define _DEFAULTFONT_H_
+
+#ifdef HAVE_XSETLOCALE
+# define X_LOCALE
+# include <X11/Xlocale.h>
+#else
+# ifdef HAVE_SETLOCALE
+#  include <locale.h>
+# endif
+#endif                         /* HAVE_XLOCALE */
+
+#ifdef HAVE_NL_LANGINFO
+# include <langinfo.h>
+#endif
+
+#include "rxvtlib.h"
+#include "feature.h"
+#include "encoding.h"
+#include "rxvtvec.h"
+
+#include "defaultfont.intpro"  /* PROTOS for internal routines */
+
+typedef struct rxvt_vars rxvt_t;
+
+struct rxvt_font {
+  // managed by the fontset
+#if EXPLICIT_CONTEXT
+  rxvt_t *rxvt_term;
+  void set_term (pR) { this->rxvt_term = R; }
+#else
+  void set_term (pR) { }
+#endif
+  char *name;
+  codeset cs;
+  bool loaded;
+
+  // managed by the font object
+  bool prop; // wether this is a proportional font or has other funny characteristics
+  int ascent, descent,
+      width, height;
+
+  void set_name (char *name)
+  {
+    if (this->name) free (this->name); // let the compiler optimize
+    this->name = name;
+  }
+
+  rxvt_font () { name = 0; }
+  ~rxvt_font () { free (name); clear (); };
+
+  void clear_rect (int x, int y, int w, int h, int color);
+
+  virtual void clear () { };
+
+  virtual bool load (int maxheight) = 0;
+  virtual bool has_codepoint (uint32_t unicode) = 0;
+
+  virtual void draw (int x, int y,
+                     const text_t *text, int len,
+                     int fg, int bg) = 0;
+};
+
+//#define FONT_REF(obj) (obj)->refcnt++
+//#define FONT_UNREF(obj) if (!--(obj)->refcnt) delete (obj)
+#define FONT_UNREF(f) delete f
+
+struct rxvt_fallback_font;
+
+struct rxvt_fontset {
+  rxvt_fontset (pR);
+  ~rxvt_fontset ();
+
+  rxvt_font *new_font (const char *name, codeset cs);
+
+  void populate (const char *desc);
+  int find_font (uint32_t unicode);
+
+  rxvt_font *operator [](int id) const
+  {
+    return fonts[id];
+  }
+
+  rxvt_font *base_font () const
+  {
+    return fonts[base_id];
+  }
+
+private:
+#ifdef EXPLICIT_CONTEXT
+  rxvt_t *rxvt_term;
+#endif
+  simplevec<rxvt_font *> fonts;
+  const rxvt_fallback_font *fallback;
+
+  int height;
+  int base_id;
+
+  bool realize_font (int i);
+  void add_fonts (const char *desc);
+  void clear ();
+};
+
+#endif /* _DEFAULTFONT_H_ */
+
diff --git a/src/feature.h b/src/feature.h
new file mode 100644 (file)
index 0000000..f142b14
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * File:       feature.h
+ * $Id: feature.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Compile-time configuration.
+ *-----------------------------------------------------------------------
+ * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *----------------------------------------------------------------------*/
+#ifndef _FEATURE_H
+#define _FEATURE_H
+
+#ifndef X11USRLIBDIR
+# define X11USRLIBDIR          "/usr/X11R6/lib"
+#endif
+#ifndef X11LIBDIR
+# define X11LIBDIR             X11USRLIBDIR "/X11"
+#endif
+#ifndef XAPPLOADDIR
+# define XAPPLOADDIR           X11LIBDIR "/app-defaults" 
+# define XAPPLOADDIRLOCALE     X11LIBDIR "/%-.*s/app-defaults"
+#endif
+
+/*-----------------------SCREEN OPTIONS AND COLOURS---------------------*/
+/*
+ * Define the name of the environment variable to be used in
+ * addition to the "PATH" environment and the `path' resource.
+ * Usually it should point to where you keep your background pixmaps and/or
+ * your menu files
+ */
+#define PATH_ENV       "RXVTPATH"
+
+/*
+ * Avoid enabling the colour cursor (-cr, cursorColor, cursorColor2)
+ */
+/* #define NO_CURSORCOLOR */
+
+/*
+ * Suppress use of BOLD and BLINK attributes for setting bright foreground
+ * and background, respectively.  Simulate BOLD using colorBD, boldFont or
+ * overstrike characters.
+ */
+/* #define NO_BRIGHTCOLOR */
+
+/*
+ * Make colours match xterm colours instead of `traditional' rxvt colours
+ */
+#define XTERM_COLORS
+
+/*
+ * Disable separate colours for bold, underline and reverse video
+ */
+/* #define NO_BOLD_UNDERLINE_REVERSE */
+
+/*
+ * Disable using simulated bold using overstrike.  You can also turn off
+ * overstrike just for multi char fonts
+ * Note: NO_BOLDOVERSTRIKE implies NO_BOLDOVERSTRIKE_MULTI
+ */
+/* #define NO_BOLDOVERSTRIKE */
+/* #define NO_BOLDOVERSTRIKE_MULTI */
+
+/*
+ * Don't bother cleaning up pixel droppings.  If you don't use bold
+ * overstrike then you don't usually need this
+ */
+#define NO_PIXEL_DROPPING_AVOIDANCE
+
+/*
+ * Also use bold font or overstrike even if we use colour for bold
+ */
+/*#define VERYBOLD*/
+
+/*
+ * Compile without support for real bold fonts
+ */
+/* #define NO_BOLDFONT */
+
+/*
+ * Add support for '-hc colour' for background highlight of selection
+ */
+#define OPTION_HC
+
+/*
+ * Define maximum possible columns and rows
+ */
+#define MAX_COLS       4000
+#define MAX_ROWS       1000
+
+/*
+ * Define default colours for certain items.  If you have a low colour
+ * display, then consider using colours which are already pre-allocated:
+ *   Black             (#000000)
+ *   Red3              (#CD0000)       + these
+ *   Green3            (#00CD00)       + colours
+ *   Yellow3           (#CDCD00)       + are
+ *   Blue3             (#0000CD)       + not
+ *   Magenta3          (#CD00CD)       + pre-allocated
+ *   Cyan3             (#00CDCD)       + if
+ *   AntiqueWhite      (#FAEBD7)       + NO_BRIGHTCOLOR
+ *   Grey25            (#404040)       + defined
+ *   Red               (#FF0000)
+ *   Green             (#00FF00)
+ *   Yellow            (#FFFF00)
+ *   Blue              (#0000FF)
+ *   Magenta           (#FF00FF)
+ *   Cyan              (#00FFFF)
+ *   White             (#FFFFFF)
+ */
+/* These colours MUST be defined */
+#define COLOR_FOREGROUND       "Black"
+#define COLOR_BACKGROUND       "White"
+#define COLOR_SCROLLBAR                "#B2B2B2"       /* scrollColor match Netscape */
+#define COLOR_SCROLLTROUGH     "#969696"
+/*
+ * The cursor colours are special.  Be very careful about setting these:
+ * foreground/background colours may be modified by command line or resources
+ * prior to this allocation.  Also, they are not valid if NO_CURSORCOLOR is
+ * defined
+ */
+#define COLOR_CURSOR_FOREGROUND        NULL    /* if NULL, use background colour */
+#define COLOR_CURSOR_BACKGROUND        NULL    /* if NULL, use foreground colour */
+
+/*
+ * Define to remove support for XCopyArea() support.  XCopyArea() is useful
+ * for scrolling on non-local X displays
+ */
+/* #define NO_SLOW_LINK_SUPPORT */
+
+/*
+ * Printer pipe which will be used for emulation of attached vt100 printer
+ */
+#define PRINTPIPE      "lpr"
+
+/*
+ * Allow 80/132 mode switching on startup
+ */
+/* #define ALLOW_132_MODE */
+/*------------------------------RESOURCES-------------------------------*/
+/*
+ * Define to find installed application defaults for rxvt
+ * Only if USE_XGETDEFAULT is not defined.
+ */
+/* #define USE_XAPPLOADDIR */
+
+/*
+ * Add support for the Offix DND (Drag 'n' Drop) protocol
+ */
+/* #define OFFIX_DND */
+
+/*---------------------------------KEYS---------------------------------*/
+
+/*
+ * Define defaults for backspace and delete keys - unless they have been
+ * configured out with --disable-backspace-key / --disable-delete-key
+ */
+/* #define DEFAULT_BACKSPACE   "DEC"           */ /* SPECIAL */
+#define DEFAULT_BACKSPACE      "\010"
+#define DEFAULT_DELETE "\033[3~"
+
+/*
+ * Choose one of these values to be the `hotkey' for changing font.
+ * This has been superceded and is only for you older users
+ */
+/* #define HOTKEY_CTRL */
+/* #define HOTKEY_META */
+
+/*
+ * To use
+ *     Home = "\E[1~", End = "\E[4~"
+ * instead of
+ *     Home = "\E[7~", End = "\E[8~"   [default]
+ */
+/* #define LINUX_KEYS */
+
+/*
+ * Enable the keysym resource which allows you to define strings associated
+ * with various KeySyms (0xFF00 - 0xFFFF).
+ * Only works with the default hand-rolled resources.
+ */
+#ifndef NO_RESOURCES
+# define KEYSYM_RESOURCE
+#endif
+
+/*
+ * Modifier/s to use to allow up/down arrows and Priot/Next keys
+ * to scroll single or page-fulls
+ */
+#define SCROLL_ON_SHIFT
+/* #define SCROLL_ON_CTRL */
+/* #define SCROLL_ON_META */
+
+/*
+ * Allow scrolling with modifier+Up/Down keys, in addition
+ * to modifier+Prior/Next? (modifier is controlled with
+ * SCROLL_ON_* defines above.). 
+ * Also for modifier+Home/End keys to move to top/bottom
+ */
+/* #define SCROLL_ON_UPDOWN_KEYS */
+/* #define SCROLL_ON_HOMEEND_KEYS */
+
+/*
+ * Allow unshifted Next/Prior keys to scroll forward/back
+ * (in addition to shift+Next/shift+Prior)       --pjh
+ */
+/* #define UNSHIFTED_SCROLLKEYS */
+
+/* (Hops) Set to choose a number of lines of context between pages
+ *      (rather than a proportion (1/5) of savedlines buffer)
+ *      when paging the savedlines with SHIFT-{Prior,Next} keys.
+ */
+#define PAGING_CONTEXT_LINES 1 /* */
+
+/*
+ * Have either Ctrl+Tab or Mod4+Tab emit \e\t
+ * Useful when window manager grabs Alt+Tab   -- mg
+ */
+/* #define CTRL_TAB_MAKES_META */
+/* #define MOD4_TAB_MAKES_META */
+
+/*
+ * default mode switch when greek keyboard is enabled (i.e. GREEK_SUPPORT)
+ */
+#ifndef GREEK_KEYBOARD_MODESWITCH
+# define GREEK_KEYBOARD_MODESWITCH XK_Mode_switch
+#endif
+
+/*--------------------------------MOUSE---------------------------------*/
+/*
+ * Disable sending escape sequences (up, down, page up/down)
+ * from the scrollbar when XTerm mouse reporting is enabled
+ */
+/* #define NO_SCROLLBAR_REPORT */
+
+/*
+ * Default separating chars for multiple-click selection
+ * Space and tab are separate separating characters and are not settable
+ */
+#define CUTCHARS       "\"&'()*,;<=>?@[\\]^`{|}~"
+
+/*
+ * Add run-time support for changing the cutchars for double click selection
+ */
+#define CUTCHAR_RESOURCE
+
+/*
+ * Have mouse reporting include double-click info for button1
+ */
+/* #define MOUSE_REPORT_DOUBLECLICK */
+
+/*
+ * Set delay between multiple click events [default: 500 milliseconds]
+ */
+/* #define MULTICLICK_TIME 500 */
+
+/*
+ * Time factor to slow down a `jumpy' mouse.  Motion isn't recognised until
+ * this long after the last mouse click [default: 50 milliseconds]
+ */
+#define MOUSE_THRESHOLD                50
+
+/*
+ * If mouse wheel is defined, then scrolling is by 5 lines (or 1 line
+ * if the shift key is down).  Scrolling can be smooth or jump scrolling
+ */
+/* #define JUMP_MOUSE_WHEEL */
+
+/*
+ * Set delay periods for continuous scrolling with scrollbar buttons
+ */
+/* #define SCROLLBAR_INITIAL_DELAY 40 */
+/* #define SCROLLBAR_CONTINUOUS_DELAY 2 */
+
+/*
+ * The speed of selection scrolling is proportional to the distance
+ * the mouse pointer is out of the text window.  This is the max
+ * number of lines to scroll at a time.
+ */
+#define SELECTION_SCROLL_MAX_LINES 2
+
+/*
+ * The number of lines (measured in character's heights, not pixels)
+ * the pointer must be out of the window for each increase in the
+ * number of lines scrolled.
+ */
+#define SELECTION_SCROLL_LINE_SPEEDUP 4
+
+/*--------------------------------MISC----------------------------------*/
+/*
+ * Disable to reset tty device to pre-incovation state
+ */
+#define RESET_TTY_TO_COMMON_DEFAULTS
+
+/*
+ * Only log in wtmp file when we're a login shell (-ls option)
+ */
+#define WTMP_ONLY_ON_LOGIN
+
+/*
+ * When pasting ACS characters, convert to similar normal characters
+ */
+/* #define ACS_ASCII */
+
+/*
+ * Default ascii characters to which ACS symbols are converted
+ */
+#ifdef ACS_ASCII
+# define ACS_CHARS ".#    o+  ----+---__++--|<> =#. "
+#endif
+
+/*--------------------------------BELL----------------------------------*/
+/*
+ * Disable all bell indications
+ */
+/* #define NO_BELL */
+
+/*
+ * Disable automatic de-iconify when a bell is received
+ */
+/* #define NO_MAPALERT */
+
+/*
+ * Have mapAlert behaviour selectable with mapAlert resource
+ */
+#define MAPALERT_OPTION
+
+/*-----------------------------SCROLL BAR-------------------------------*/
+/*
+ * Choose the rxvt style scrollbar width
+ * - should be an even number [default: 10]
+ */
+/* #define SB_WIDTH_RXVT 10 */
+
+/*
+ * Minimum and maximum widths of the scrollbar (all styles)
+ */
+#define SB_WIDTH_MINIMUM       5
+#define SB_WIDTH_MAXIMUM       100
+
+/*
+ * When using Rxvt scrollbar, clicking above or below the slider will move
+ * 1/4 of the screen height, if possible.  Setting RXVT_SCROLL_FULL will move
+ * it one screen height less one line, if possible
+ */
+#define RXVT_SCROLL_FULL 1
+
+/*
+ * (Hops) draw an internal border line on inside edge of the scrollbar
+ */
+/* #define SB_BORDER */
+
+/*------------------------------MENU BAR--------------------------------*/
+/*
+ * Choose how many of (experimental) menuBars you want to be able to stack at
+ * one time.
+ *  A value of 1 disables menuBar stacking.
+ *  A value of 0 disables menuBar all together.
+ *  Note that the amount of memory overhead is the same for any value >= 2.
+ */
+#define MENUBAR_MAX 8
+
+/*
+ * Change the default shadow style
+ */
+/* #define MENUBAR_SHADOW_IN */
+
+/*
+ * Change the default shadow style
+ */
+#define MENU_SHADOW_IN
+
+/*---------------------------MULTILINGUAL-------------------------------*/
+/*
+ * Allow run-time selection of Meta (Alt) to set the 8th bit on
+ */
+#define META8_OPTION
+
+/*---------------------------DISPLAY OPTIONS----------------------------*/
+/*
+ * Force local connection to be socket (or other local) communication
+ */
+/* #define LOCAL_X_IS_UNIX */
+
+/*
+ * Have DISPLAY environment variable & "\E[7n" transmit display with IP number
+ */
+/* #define DISPLAY_IS_IP */
+
+/*
+ * Have "\E[7n" transmit the display name.
+ * This has been cited as a potential security hole.
+ */
+#define ENABLE_DISPLAY_ANSWER
+
+/*
+ * Change what ESC Z transmits instead of the default "\E[?1;2c"
+ */
+/* #define ESCZ_ANSWER "\033[?1;2C" */
+
+/*
+ * Check the current value of the window-time/icon-name and avoid
+ * re-setting it to the same value -- avoids unnecessary window refreshes
+ */
+#define SMART_WINDOW_TITLE
+
+/*
+ * Allow foreground/background colour to be changed with an
+ * xterm escape sequence "\E]39;colour^G" -- still experimental
+ */
+#define XTERM_COLOR_CHANGE
+
+/*
+ * Remove secondary screen's independent cursor position, a la xterm
+ */
+/* #define NO_SECONDARY_SCREEN_CURSOR */
+
+/*
+ * If no secondary screen is available (NO_SECONDARY_SCREEN in config.h),
+ * then scroll the text up on a window change request
+ */
+#define SCROLL_ON_NO_SECONDARY
+
+/*
+ * Width of the term internal border
+ */
+#define INTERNALBORDERWIDTH    2
+
+/*
+ * Width of the term external border
+ */
+#define EXTERNALBORDERWIDTH    0
+
+/*
+ * Default number of extra dots between lines
+ */
+#define LINESPACE      0
+
+/*
+ * Default number of lines in the scrollback buffer
+ */
+#define SAVELINES      64
+
+/*
+ * Provide termcap/terminfo bw support
+ */
+/* #define TERMCAP_HAS_BW */
+
+/*
+ * MAX_NFONTS is the maximum allowed number of fonts in the list
+ * FONT0_IDX is the default font in the list (starting at 0)
+ * Sizes between multi-char fonts sets (MFONT_LIST) and single-char font
+ * sets (NFONT_LIST) have been matched up
+ */
+#define MAX_NFONTS     7
+#define FONT0_IDX      2
+
+#define UNICODE 1 /* TODO */
+#define UTF8 1 /* TODO */
+
+#endif
diff --git a/src/graphics.C b/src/graphics.C
new file mode 100644 (file)
index 0000000..697f795
--- /dev/null
@@ -0,0 +1,549 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       graphics.c
+ *----------------------------------------------------------------------*
+ * $Id: graphics.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1994      Rob Nation <nation@rocket.sanders.lockheed.com>
+ *                             - original version
+ * Copyright (c) 1997      Raul Garcia Garcia <rgg@tid.es>
+ * Copyright (c) 1997,1998 mj olesen <olesen@me.queensu.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#ifdef RXVT_GRAPHICS
+#include "rxvt.h"              /* NECESSARY */
+#include "rxvtgrx.h"
+
+typedef struct grcmd_t {
+    char            cmd;
+    short           color;
+    short           ncoords;
+    int            *coords;
+    unsigned char  *text;
+    struct grcmd_t *next;
+} grcmd_t;
+
+typedef struct grwin_t {
+    Window          win;
+    int             x, y;
+    unsigned int    w, h;
+    short           screen;
+    grcmd_t        *graphics;
+    struct grwin_t *prev, *next;
+} grwin_t;
+
+#include "graphics.intpro"     /* PROTOS for internal routines */
+#include <X11/cursorfont.h>
+
+/* commands:
+ * 'C' = Clear
+ * 'F' = Fill
+ * 'G' = Geometry
+ * 'L' = Line
+ * 'P' = Points
+ * 'T' = Text
+ * 'W' = Window
+ */
+
+#ifndef GRX_SCALE
+# define GRX_SCALE     10000
+#endif
+
+/*----------------------------------------------------------------------*
+ * local functions
+ */
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_Gr_NewWindow(pR_ int nargs, int args[])
+{
+    int             x, y;
+    unsigned int    w, h;
+    Window          win;
+    grwin_t        *grwin;
+    Cursor          cursor;
+
+    if (nargs != 4) {
+       rxvt_print_error("NewWindow: 4 args needed, got %d\n", nargs);
+       return;
+    }
+    x = args[0] * TermWin_TotalWidth() / GRX_SCALE;
+    y = args[1] * TermWin_TotalHeight() / GRX_SCALE;
+    w = args[2] * TermWin_TotalWidth() / GRX_SCALE;
+    h = args[3] * TermWin_TotalHeight() / GRX_SCALE;
+
+    win = XCreateSimpleWindow(R->Xdisplay, R->TermWin.vt,
+                             x, y, w, h,
+                             0,
+                             R->PixColors[Color_fg],
+                             R->PixColors[Color_bg]);
+
+    cursor = XCreateFontCursor(R->Xdisplay, XC_crosshair);
+    XDefineCursor(R->Xdisplay, win, cursor);
+    XMapWindow(R->Xdisplay, win);
+    XSelectInput(R->Xdisplay, win, ExposureMask);
+
+    grwin = (grwin_t *) rxvt_malloc(sizeof(grwin_t));
+    grwin->win = win;
+    grwin->x = x;
+    grwin->y = y;
+    grwin->w = w;
+    grwin->h = h;
+    grwin->screen = 0;
+    grwin->prev = NULL;
+    grwin->next = R->h->gr_root;
+    if (grwin->next)
+       grwin->next->prev = grwin;
+    R->h->gr_root = grwin;
+    grwin->graphics = NULL;
+    R->h->graphics_up++;
+
+    rxvt_tt_printf(aR_ "\033W%ld\n", (long)grwin->win);
+}
+
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_Gr_ClearWindow(pR_ grwin_t *grwin)
+{
+    grcmd_t        *cmd, *next;
+
+    for (cmd = grwin->graphics; cmd != NULL; cmd = next) {
+       next = cmd->next;
+       free(cmd->coords);
+       if (cmd->text != NULL)
+           free(cmd->text);
+       free(cmd);
+    }
+    grwin->graphics = NULL;
+    XClearWindow(R->Xdisplay, grwin->win);
+}
+
+/*
+ * arg [0] = x
+ * arg [1] = y
+ * arg [2] = alignment
+ * arg [3] = strlen (text)
+ */
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_Gr_Text(pR_ grwin_t *grwin, grcmd_t *data)
+{
+    int             x, y, align;
+
+    if (data->ncoords < 4 || data->text == NULL || *(data->text) == '\0')
+       return;
+
+    x = data->coords[0] * grwin->w / GRX_SCALE;
+    y = data->coords[1] * grwin->h / GRX_SCALE;
+    align = data->coords[2];
+
+    if ((align & HORIZONTAL_ALIGNMENT) == RIGHT_TEXT)
+       x -= XTextWidth(R->TermWin.font, data->text, data->coords[3]);
+    else if ((align & HORIZONTAL_ALIGNMENT) == HCENTER_TEXT)
+       x -= (XTextWidth(R->TermWin.font, data->text, data->coords[3]) >> 1);
+
+    if ((align & VERTICAL_ALIGNMENT) == TOP_TEXT)
+       y += R->TermWin.font->ascent;
+    else if ((align & VERTICAL_ALIGNMENT) == BOTTOM_TEXT)
+       y -= R->TermWin.font->descent;
+
+    if ((align & VERTICAL_ALIGNMENT) == VCENTER_TEXT)
+       y -= R->TermWin.font->descent
+            + ((R->TermWin.font->ascent + R->TermWin.font->descent) >> 1);
+    if ((align & VERTICAL_ALIGNMENT) == VCAPS_CENTER_TEXT)
+       y += (R->TermWin.font->ascent >> 1);
+
+    XPMClearArea(R->Xdisplay, grwin->win, x, y - R->TermWin.font->ascent,
+                Width2Pixel(data->coords[3]), Height2Pixel(1), 0);
+    XDrawString(R->Xdisplay, grwin->win, R->TermWin.gc, x, y,
+               data->text, data->coords[3]);
+}
+
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_Gr_Geometry(pR_ grwin_t *grwin, grcmd_t *data __attribute__((unused)))
+{
+    if (grwin)
+       rxvt_tt_printf(aR_ "\033G%ld %d %d %u %u %d %d %ld %ld %d\n",
+                 (long)grwin->win,
+                 grwin->x, grwin->y, grwin->w, grwin->h,
+                 R->TermWin.fwidth,
+                 R->TermWin.fheight,
+                 (long)GRX_SCALE * R->TermWin.fwidth / grwin->w,
+                 (long)GRX_SCALE * R->TermWin.fheight / grwin->h,
+                 XDEPTH);
+    else                       /* rxvt terminal window size */
+       rxvt_tt_printf(aR_ "\033G0 0 0 %d %d %d %d %ld %ld %d\n",
+                 TermWin_TotalWidth(), TermWin_TotalHeight(),
+                 R->TermWin.fwidth, R->TermWin.fheight,
+                 (long)GRX_SCALE * R->TermWin.fwidth / R->TermWin.width,
+                 (long)GRX_SCALE * R->TermWin.fheight / R->TermWin.height,
+                 XDEPTH);
+}
+
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_Gr_DestroyWindow(pR_ grwin_t *grwin)
+{
+    grcmd_t        *cmd, *next;
+
+    if (grwin == NULL)
+       return;
+
+    for (cmd = grwin->graphics; cmd; cmd = next) {
+       next = cmd->next;
+       free(cmd->coords);
+       if (cmd->text != NULL)
+           free(cmd->text);
+       free(cmd);
+    }
+
+    XDestroyWindow(R->Xdisplay, grwin->win);
+    if (grwin->next != NULL)
+       grwin->next->prev = grwin->prev;
+    if (grwin->prev != NULL)
+       grwin->prev->next = grwin->next;
+    else
+       R->h->gr_root = grwin->next;
+    free(grwin);
+
+    R->h->graphics_up--;
+}
+
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_Gr_Dispatch(pR_ grwin_t *grwin, grcmd_t *data)
+{
+    int             i, n;
+    union {
+       XPoint          pt[NGRX_PTS / 2];
+       XRectangle      rect[NGRX_PTS / 4];
+    } xdata;
+
+    if (data->color != Color_fg) {
+       XGCValues       gcv;
+
+       gcv.foreground = R->PixColors[data->color];
+       XChangeGC(R->Xdisplay, R->TermWin.gc, GCForeground, &gcv);
+    }
+    if (grwin)
+       switch (data->cmd) {
+       case 'L':
+           if (data->ncoords > 3) {
+               for (n = i = 0; i < data->ncoords; i += 2, n++) {
+                   xdata.pt[n].x = data->coords[i] * grwin->w / GRX_SCALE;
+                   xdata.pt[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE;
+               }
+               XDrawLines(R->Xdisplay,
+                      grwin->win, R->TermWin.gc, xdata.pt, n, CoordModeOrigin);
+           }
+           break;
+
+       case 'P':
+           if (data->ncoords > 3) {
+               for (n = i = 0; i < data->ncoords; i += 2, n++) {
+                   xdata.pt[n].x = data->coords[i] * grwin->w / GRX_SCALE;
+                   xdata.pt[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE;
+               }
+               XDrawPoints(R->Xdisplay,
+                      grwin->win, R->TermWin.gc, xdata.pt, n, CoordModeOrigin);
+           }
+           break;
+
+       case 'F':
+           if (data->ncoords > 0) {
+               for (n = i = 0; i < data->ncoords; i += 4, n++) {
+                   xdata.rect[n].x = data->coords[i] * grwin->w / GRX_SCALE;
+                   xdata.rect[n].y = data->coords[i + 1] * grwin->h
+                                     / GRX_SCALE;
+                   xdata.rect[n].width = ((data->coords[i + 2]
+                                           - data->coords[i] + 1) *
+                                          grwin->w / GRX_SCALE);
+                   xdata.rect[n].height = ((data->coords[i + 3]
+                                            - data->coords[i + 1] + 1) *
+                                           grwin->h / GRX_SCALE);
+                   XPMClearArea(R->Xdisplay, grwin->win,
+                                xdata.rect[n].x, xdata.rect[n].y,
+                                xdata.rect[n].width, xdata.rect[n].height,
+                                0);
+               }
+               XFillRectangles(R->Xdisplay, grwin->win, R->TermWin.gc, xdata.rect,
+                               n);
+           }
+           break;
+       case 'T':
+           rxvt_Gr_Text(aR_ grwin, data);
+           break;
+       case 'C':
+           rxvt_Gr_ClearWindow(aR_ grwin);
+           break;
+       }
+    if (data->color != Color_fg) {
+       XGCValues       gcv;
+
+       gcv.foreground = R->PixColors[Color_fg];
+       XChangeGC(R->Xdisplay, R->TermWin.gc, GCForeground, &gcv);
+    }
+}
+
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_Gr_Redraw(pR_ grwin_t *grwin)
+{
+    grcmd_t        *cmd;
+
+    for (cmd = grwin->graphics; cmd != NULL; cmd = cmd->next)
+       rxvt_Gr_Dispatch(aR_ grwin, cmd);
+}
+
+/*----------------------------------------------------------------------*
+ * end of static functions
+ */
+/* ARGSUSED */
+/* EXTPROTO */
+void
+rxvt_Gr_ButtonReport(pR_ int but, int x, int y)
+{
+    grwin_t        *grwin;
+
+    for (grwin = R->h->gr_root; grwin != NULL; grwin = grwin->next)
+       if ((x > grwin->x)
+           && (y > grwin->y)
+           && ((unsigned int)x < grwin->x + grwin->w)
+           && ((unsigned int)y < grwin->y + grwin->h))
+           break;
+
+    if (grwin == NULL)
+       return;
+
+    x = GRX_SCALE * (x - grwin->x) / grwin->w;
+    y = GRX_SCALE * (y - grwin->y) / grwin->h;
+    rxvt_tt_printf(aR_ "\033%c%ld;%d;%d;\n", but, (long)grwin->win, x, y);
+}
+
+/* ARGSUSED */
+/* EXTPROTO */
+void
+rxvt_Gr_do_graphics(pR_ int cmd, unsigned int nargs, int args[], unsigned char *text)
+{
+    int             i;
+    Window          win_id;
+    grwin_t        *grwin;
+    grcmd_t        *newcmd, *oldcmd;
+
+    if (cmd == 'W') {
+       rxvt_Gr_NewWindow(aR_ nargs, args);
+       return;
+    }
+    win_id = (nargs > 0) ? (Window) args[0] : None;
+
+    if ((cmd == 'G') && (win_id == None)) {
+       rxvt_Gr_Geometry(aR_ NULL, NULL);
+       return;
+    }
+    if ((win_id == None) && (R->h->gr_last_id != None))
+       win_id = R->h->gr_last_id;
+
+    if (win_id == None)
+       return;
+
+    grwin = R->h->gr_root;
+    while ((grwin != NULL) && (grwin->win != win_id))
+       grwin = grwin->next;
+
+    if (grwin == NULL)
+       return;
+
+    if (cmd == 'G') {
+       rxvt_Gr_Geometry(aR_ grwin, NULL);
+       return;
+    }
+    nargs--;
+    args++;                    /* skip over window id */
+
+/* record this new command */
+    newcmd = (grcmd_t *) rxvt_malloc(sizeof(grcmd_t));
+    newcmd->ncoords = nargs;
+    newcmd->coords = (int *)rxvt_malloc((newcmd->ncoords * sizeof(int)));
+
+    newcmd->next = NULL;
+    newcmd->cmd = cmd;
+    newcmd->color = rxvt_scr_get_fgcolor(aR);
+    newcmd->text = text;
+
+    for (i = 0; i < newcmd->ncoords; i++)
+       newcmd->coords[i] = args[i];
+
+/*
+ * If newcmd == fill, and rectangle is full window, drop all prior
+ * commands.
+ */
+    if ((newcmd->cmd == 'F') && (grwin) && (grwin->graphics)) {
+       for (i = 0; i < newcmd->ncoords; i += 4) {
+           if ((newcmd->coords[i] == 0)
+               && (newcmd->coords[i + 1] == 0)
+               && (newcmd->coords[i + 2] == GRX_SCALE)
+               && (newcmd->coords[i + 3] == GRX_SCALE)) {
+           /* drop previous commands */
+               oldcmd = grwin->graphics;
+               while (oldcmd->next != NULL) {
+                   grcmd_t        *tmp = oldcmd;
+
+                   oldcmd = oldcmd->next;
+                   free(tmp);
+               }
+               grwin->graphics = NULL;
+           }
+       }
+    }
+/* insert new command into command list */
+    oldcmd = grwin->graphics;
+    if (oldcmd == NULL)
+       grwin->graphics = newcmd;
+    else {
+       while (oldcmd->next != NULL)
+           oldcmd = oldcmd->next;
+       oldcmd->next = newcmd;
+    }
+    rxvt_Gr_Dispatch(aR_ grwin, newcmd);
+}
+
+/* ARGSUSED */
+/* EXTPROTO */
+void
+rxvt_Gr_scroll(pR_ int count)
+{
+    grwin_t        *grwin, *next;
+
+    if ((count == 0) && (R->h->gr_prev_start == R->TermWin.view_start))
+       return;
+
+    R->h->gr_prev_start = R->TermWin.view_start;
+
+    for (grwin = R->h->gr_root; grwin != NULL; grwin = next) {
+       next = grwin->next;
+       grwin->y -= (count * R->TermWin.fheight);
+       if ((long)(grwin->y + grwin->h)
+           < -(long)(R->TermWin.saveLines * R->TermWin.fheight))
+           rxvt_Gr_DestroyWindow(aR_ grwin);
+       else
+           XMoveWindow(R->Xdisplay, grwin->win,
+                       grwin->x,
+                       grwin->y + (R->TermWin.view_start * R->TermWin.fheight));
+    }
+}
+
+/* EXTPROTO */
+void
+rxvt_Gr_ClearScreen(pR)
+{
+    grwin_t        *grwin, *next;
+
+    for (grwin = R->h->gr_root; grwin != NULL; grwin = next) {
+       next = grwin->next;
+       if ((grwin->screen == 0) && (grwin->y + grwin->h > 0)) {
+           if (grwin->y >= 0)
+               rxvt_Gr_DestroyWindow(aR_ grwin);
+           else
+               XResizeWindow(R->Xdisplay, grwin->win,
+                             grwin->w, -grwin->y);
+       }
+    }
+}
+
+/* EXTPROTO */
+void
+rxvt_Gr_ChangeScreen(pR)
+{
+    grwin_t        *grwin, *next;
+
+    for (grwin = R->h->gr_root; grwin != NULL; grwin = next) {
+       next = grwin->next;
+       if (grwin->y + grwin->h > 0) {
+           if (grwin->screen == 1) {
+               XMapWindow(R->Xdisplay, grwin->win);
+               grwin->screen = 0;
+           } else {
+               XUnmapWindow(R->Xdisplay, grwin->win);
+               grwin->screen = 1;
+           }
+       }
+    }
+}
+
+/* ARGSUSED */
+/* EXTPROTO */
+void
+rxvt_Gr_expose(pR_ Window win)
+{
+    grwin_t        *grwin;
+
+    for (grwin = R->h->gr_root; grwin != NULL; grwin = grwin->next) {
+       if (grwin->win == win) {
+           rxvt_Gr_Redraw(aR_ grwin);
+           break;
+       }
+    }
+}
+
+/* ARGSUSED */
+/* EXTPROTO */
+void
+rxvt_Gr_Resize(pR_ int w __attribute__((unused)), int h)
+{
+    grwin_t        *grwin;
+
+    for (grwin = R->h->gr_root; grwin != NULL; grwin = grwin->next) {
+       if (R->TermWin.height != h) {
+           grwin->y += (R->TermWin.height - h);
+           XMoveWindow(R->Xdisplay, grwin->win,
+                       grwin->x,
+                       grwin->y + (R->TermWin.view_start * R->TermWin.fheight));
+       }
+       rxvt_Gr_Redraw(aR_ grwin);
+    }
+}
+
+/* EXTPROTO */
+void
+rxvt_Gr_reset(pR)
+{
+    grwin_t        *grwin, *next;
+
+    for (grwin = R->h->gr_root; grwin != NULL; grwin = next) {
+       next = grwin->next;
+       rxvt_Gr_DestroyWindow(aR_ grwin);
+    }
+
+    R->h->graphics_up = 0;
+}
+
+/* EXTPROTO */
+int
+rxvt_Gr_Displayed(pR)
+{
+    return R->h->graphics_up;
+}
+#endif
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/graphics/Makefile.in b/src/graphics/Makefile.in
new file mode 100644 (file)
index 0000000..b9873f5
--- /dev/null
@@ -0,0 +1,66 @@
+# test/graphics/Makefile.in    -*- Makefile -*-
+# $Id: Makefile.in,v 1.1 2003-11-24 17:28:08 pcg Exp $
+@MCOMMON@
+
+srcdir =       @srcdir@
+VPATH =                @srcdir@
+.PATH:         @srcdir@
+
+basedir = ../..
+thisdir = src/graphics
+
+first_rule: qplot
+dummy:
+
+SRCS = grxlib.c qplot.c
+OBJS = grxlib.o qplot.o
+HDRS = grxlib.h
+
+#
+# Distribution variables
+#
+
+DIST = $(HDRS) $(SRCS) README data Makefile.in
+
+# inference rules
+.c.o:
+       $(COMPILE) -I$(srcdir)/.. -c $<
+
+#-------------------------------------------------------------------------
+all:
+
+graphics: qplot
+
+qplot: $(OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) -lm
+
+tags: $(SRCS)
+       ctags $(SRCS)
+
+alldoc:
+
+allbin: qplot
+
+clean:
+       $(RMF) qplot core a.out *.o *.bak *~
+
+realclean: clean
+       $(RMF) tags
+
+cleandir: realclean
+
+distclean:
+       (cd $(srcdir); $(RMF) qplot *~ *.o core a.out)
+       if test $(srcdir) = .; then $(MAKE) realclean; fi
+       (cd $(srcdir); $(RMF) Makefile)
+
+install uninstall:
+
+distdirs:
+       mkdir $(basedir)/../$(VERNAME)/$(thisdir)
+
+distcopy:
+       $(CP) -p $(DIST) $(basedir)/../$(VERNAME)/$(thisdir)
+
+# -----------------------------------------------------------------------
+# forget dependencies, there are too few
diff --git a/src/graphics/grxlib.c b/src/graphics/grxlib.c
new file mode 100644 (file)
index 0000000..56301bf
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * $Id: grxlib.c,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#include "../../config.h"
+#include "rxvt.h"
+#include "init.h"              /* for GET_TERMIOS / SET_TERMIOS */
+#include "grxlib.h"
+
+/*----------------------------------------------------------------------*/
+
+void
+Done(void)
+{
+    putchar(':');
+}
+
+void
+StartLine(long id)
+{
+    printf("\033GL%ld", id);
+}
+
+void
+StartPoint(long id)
+{
+    printf("\033GP%ld", id);
+}
+
+void
+StartFill(long id)
+{
+    printf("\033GF%ld", id);
+}
+
+void
+Extend(int x, int y)
+{
+    printf(";%d;%d", x, y);
+}
+
+void
+FillArea(int x1, int y1, int x2, int y2)
+{
+    printf(";%d;%d;%d;%d", x1, y1, x2, y2);
+}
+
+void
+PlaceText(long id, int x, int y, int mode, char *text)
+{
+    printf("\033GT%ld;%d;%d;%d;%d:%s", id, x, y, mode, strlen(text), text);
+    fflush(stdout);
+}
+
+void
+ClearWindow(long id)
+{
+    printf("\033GC%ld:", id);
+}
+
+void
+ForeColor(int col)
+{
+    printf("\033[3%dm", (col < 0 || col > 7) ? 0 : col);
+}
+
+void
+DefaultRendition(void)
+{
+    printf("\033[m");
+}
+
+#define LINESZ 100
+static char     line[LINESZ];
+static FILE    *infd = NULL;
+
+long
+CreateWin(int x, int y, int w, int h)
+{
+    long            id = 0;
+
+    fflush(stdout);
+    printf("\033GW%d;%d;%d;%d:", x, y, w, h);
+    fflush(stdout);
+    while (1) {
+       if ((fgets(line, LINESZ, infd) != NULL) &&
+           (sscanf(line, "\033W%ld", &id) == 1))
+           break;
+    }
+    return id;
+}
+
+void
+QueryWin(long id, int *nfwidth, int *nfheight)
+{
+    int             id1, x, y, width, height, fwidth, fheight;
+
+    printf("\033GG%ld:", id);
+    fflush(stdout);
+    while (1) {
+       if ((fgets(line, sizeof(line), infd) != NULL) &&
+           (sscanf(line, "\033G%ld %ld %ld %ld %ld %ld %ld %ld %ld",
+                   &id1, &x, &y, &width, &height,
+                   &fwidth, &fheight, nfwidth, nfheight) != 0))
+           break;
+    }
+}
+
+int
+WaitForCarriageReturn(long *win, int *x, int *y)
+{
+    int             i, len;
+
+    fgets(line, LINESZ, infd);
+    line[LINESZ - 1] = 0;
+    len = strlen(line);
+    for (i = 0; i < len; i++) {
+       if (line[i] == '\033') {
+           int             ret = 1;
+
+           i++;
+           switch (line[i]) {
+           case 'R':
+               ret++;
+               /* drop */
+           case 'P':
+               sscanf(&line[i + 1], "%ld;%d;%d", win, x, y);
+               return ret;
+               break;
+           }
+       }
+    }
+    return 0;
+}
+
+static int      fno2;
+static ttymode_t ttmode;
+
+int
+InitializeGraphics(int scroll_text_up)
+{
+    int             fno, i;
+    char           *screen_tty;
+    struct winsize  winsize;
+
+    fno = fileno(stdout);
+    if (!isatty(fno)) {
+       fprintf(stderr, "stdout must be a tty\n");
+       return 0;
+    }
+    screen_tty = ttyname(fno);
+
+#ifdef HAVE_TERMIOS_H
+    GET_TERMIOS(fno, &ttmode);
+    ttmode.c_lflag &= ~ECHO;
+    SET_TERMIOS(fno, &ttmode);
+#endif
+
+    infd = fopen(screen_tty, "rw");
+
+#ifdef HAVE_TERMIOS_H
+    fno2 = fileno(infd);
+    GET_TERMIOS(fno2, &ttmode);
+    ttmode.c_lflag &= ~ECHO;
+    SET_TERMIOS(fno2, &ttmode);
+#endif
+
+    /* query rxvt to find if graphics are available */
+    fflush(stdout);
+    printf("\033GQ");
+    fflush(stdout);
+    while (1) {
+       if ((fgets(line, LINESZ, infd) != NULL) &&
+           (sscanf(line, "\033G%d", &i) == 1)) {
+           if (!i) {
+               fprintf(stderr, "rxvt graphics not available\n");
+               CloseGraphics();
+               return 0;
+           }
+           break;
+       }
+    }
+    if (scroll_text_up) {
+       ioctl(fno, TIOCGWINSZ, &winsize);
+       fflush(stdout);
+       for (i = 0; i < winsize.ws_row; i++)
+           putchar('\n');
+       fflush(stdout);
+    }
+    return i;
+}
+
+void
+CloseGraphics(void)
+{
+    DefaultRendition();
+    fflush(stdout);
+#ifdef HAVE_TERMIOS_H
+    ttmode.c_lflag |= ECHO;
+    SET_TERMIOS(fno2, &ttmode);
+#endif
+    fclose(infd);
+}
+
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/graphics/grxlib.h b/src/graphics/grxlib.h
new file mode 100644 (file)
index 0000000..fd7228e
--- /dev/null
@@ -0,0 +1,31 @@
+/* 
+ * $Id: grxlib.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+#include "rxvtgrx.h"           /* text alignment */
+
+/*function pointer to either StartLine or StartPoint */
+typedef void (*LineFunction) (long id);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+   extern void StartLine (long id);
+   extern void StartPoint (long id);
+   extern void Extend (int x, int y);
+   extern void StartFill (long id);
+   extern void FillArea (int x1, int y1, int x2, int y2);
+   extern void Done (void);
+   extern void PlaceText (long id, int x, int y, int mode, char *text);
+
+   extern void ClearWindow (long id);
+   extern long CreateWin (int x, int y, int w, int h);
+   extern void QueryWin (long id, int *nfwidth, int *nfheight);
+   extern void ForeColor (int color);
+   extern void DefaultRendition (void);
+   extern int  WaitForCarriageReturn (long *win, int *x, int *y);
+   extern int  InitializeGraphics (int scroll_text_up);
+   extern void CloseGraphics (void);
+#ifdef __cplusplus
+}
+#endif
+/*----------------------- end-of-file (C header) -----------------------*/
diff --git a/src/graphics/qplot.c b/src/graphics/qplot.c
new file mode 100644 (file)
index 0000000..a4062af
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * $Id: qplot.c,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <signal.h>
+#include "grxlib.h"
+
+#define Real float
+
+#ifndef GRX_SCALE
+#  define GRX_SCALE    10000
+#endif
+
+#define DEFAULT_DATA_FILE      "data"
+
+static void
+axis_round(Real * min, Real * max, Real * grid_spacing)
+{
+    int             logspace;
+
+    logspace = (int)(log10((*max - *min) / 10.0) + 0.5);
+    *grid_spacing = pow(10, (double)logspace);
+    *min = (Real) ((int)(*min / (*grid_spacing))) * (*grid_spacing);
+    *max = (Real) ((int)(*max / (*grid_spacing)) + 1) * (*grid_spacing);
+}
+
+static int
+nice_end(int junk)
+{
+    CloseGraphics();
+    putchar('\n');
+    exit(EXIT_SUCCESS);
+    return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    char           *file = NULL;
+    int             Do_Start = 1, tmp;
+    int             m, p, i, j, n, nchars, theight, twidth, xclick, yclick;
+    int             downx = 1000, downy = 1000, upx, upy;
+    long            id, winclick;
+    Real            xmax, xmin, ymax, ymin, xdiff, ydiff, xgrid_spacing,
+                   ygrid_spacing;
+    Real           *x, *y, *nls;
+    LineFunction    linetype = StartLine;
+    char            axis[100], line[256];
+    FILE           *fd;
+
+    x = (Real *)malloc(1000000 * sizeof(Real));
+    y = (Real *)malloc(1000000 * sizeof(Real));
+    nls = (Real *)malloc(1000 * sizeof(Real));
+    if (x == NULL || y == NULL || nls == NULL) {
+       fprintf(stderr, "Can't allocate initial memory\n");
+       exit(1);
+    }
+
+    ymax = xmax = -HUGE_VAL;
+    ymin = xmin = HUGE_VAL;
+
+    for (i = 1; i < argc; i++) {
+       if (*argv[i] == '-') {
+           if (!strcmp(argv[i], "-nl"))
+               linetype = StartPoint;
+           else if (argv[i][1] == '\0')        /* use stdin */
+               file = argv[i];
+           else {
+
+               fprintf(stderr, "Usage:\n\t %s [options] [file]\n\n", argv[0]);
+               fprintf(stderr,
+                       "where options include:\n"
+                       "  -pt                   plot with points instead of lines\n\n");
+
+               fprintf(stderr,
+                       "file name `-' specifies stdin\n"
+                       "if no file name is specified, "
+                       "the default is \"%s\"\n\n", DEFAULT_DATA_FILE);
+
+               return EXIT_FAILURE;
+           }
+       } else
+           file = argv[i];
+    }
+
+    if (file && !strcmp(file, "-")) {
+       fd = stdin;
+       file = "stdin";
+    } else {
+       if (file == NULL)
+           file = DEFAULT_DATA_FILE;
+
+       if ((fd = fopen(file, "r")) == NULL) {
+           fprintf(stderr, "%s: can't open file \"%s\"\n", argv[0], file);
+           return EXIT_FAILURE;
+       }
+    }
+    m = 0;
+    p = 0;
+    while (fgets(line, sizeof(line), fd) != NULL) {
+       if (sscanf(line, "%f %f", &x[m], &y[m]) == 2) {
+           if (x[m] > xmax)
+               xmax = x[m];
+           else if (x[m] < xmin)
+               xmin = x[m];
+           if (y[m] > ymax)
+               ymax = y[m];
+           else if (y[m] < ymin)
+               ymin = y[m];
+           m++;
+       } else {
+           nls[p] = m;
+           p++;
+       }
+    }
+    nls[p++] = m;
+
+    if (m == 0)
+       return;
+
+    signal(SIGTERM, nice_end);
+    signal(SIGSTOP, nice_end);
+    signal(SIGTSTP, nice_end);
+    signal(SIGINT, nice_end);
+    signal(SIGQUIT, nice_end);
+    if (!InitializeGraphics(1))
+       return EXIT_FAILURE;
+
+    n = 1;
+    do {
+       axis_round(&xmin, &xmax, &xgrid_spacing);
+       axis_round(&ymin, &ymax, &ygrid_spacing);
+
+       id = CreateWin(0, 0, GRX_SCALE, GRX_SCALE);
+       if (id == 0) {
+           fprintf(stderr, "Help id = 0\n");
+           return EXIT_FAILURE;
+       }
+       /* Fill the window in black for real eye-catching graphics! */
+       ForeColor(0);
+       StartFill(id);
+       FillArea(0, 0, GRX_SCALE, GRX_SCALE);
+       Done();
+
+       /* draw outline box in white */
+       ForeColor(7);
+
+       /* Draw outline box */
+       StartLine(id);
+       Extend(1000, 1000);
+       Extend(1000, 9000);
+       Extend(9000, 9000);
+       Extend(9000, 1000);
+       Extend(1000, 1000);
+       Done();
+
+       /* Draw the data - either lines or dots */
+       xdiff = 8000 / (xmax - xmin);
+       ydiff = 8000 / (ymax - ymin);
+
+       for (i = j = 0; j < p; j++) {
+           int             n = 0;
+
+           ForeColor(j % 6 + 1);
+           while (((x[i] < xmin) || (x[i] > xmax) ||
+                   (y[i] < ymin) || (y[i] > ymax)) && (i < nls[j]))
+               i++;
+
+           while (i < nls[j]) {
+               if (n == 0)
+                   linetype(id);
+               Extend(1000 + (x[i] - xmin) * xdiff,
+                      9000 - (y[i] - ymin) * ydiff);
+               n++;
+               if (n > 450) {
+                   Done();
+                   n = 0;
+                   continue;
+               }
+               i++;
+               while ((i < nls[j]) &&
+                      ((x[i] < xmin) || (x[i] > xmax) ||
+                       (y[i] < ymin) || (y[i] > ymax)))
+                   i++;
+           }
+           if (n > 0)
+               Done();
+       }
+
+       /* Do axis labels in black */
+       ForeColor(7);
+       QueryWin(id, &twidth, &theight);
+       PlaceText(id, GRX_SCALE / 2, 0, HCENTER_TEXT | TOP_TEXT, file);
+       PlaceText(id, GRX_SCALE / 2, GRX_SCALE, HCENTER_TEXT | BOTTOM_TEXT,
+                 "X");
+       PlaceText(id, 0, GRX_SCALE / 2, LEFT_TEXT | VCENTER_TEXT, "Y");
+       sprintf(axis, "%f", ymax);
+       nchars = 1000 / twidth;
+       axis[nchars] = 0;
+       PlaceText(id, GRX_SCALE / 10, GRX_SCALE / 10,
+                 RIGHT_TEXT | TOP_TEXT, axis);
+       sprintf(axis, "%f", ymin);
+       axis[nchars] = 0;
+       PlaceText(id, GRX_SCALE / 10, 9 * GRX_SCALE / 10,
+                 RIGHT_TEXT | BOTTOM_TEXT, axis);
+       sprintf(axis, "%f", xmax);
+       PlaceText(id, 9 * GRX_SCALE / 10, 9 * GRX_SCALE / 10,
+                 HCENTER_TEXT | TOP_TEXT, axis);
+       sprintf(axis, "%f", xmin);
+       PlaceText(id, GRX_SCALE / 10, 9 * GRX_SCALE / 10,
+                 HCENTER_TEXT | TOP_TEXT, axis);
+       fflush(stdout);
+
+       do {
+           n = WaitForCarriageReturn(&winclick, &xclick, &yclick);
+           switch (n) {
+           case 1:
+               downx = xclick;
+               downy = yclick;
+               break;
+           case 2:
+               upx = xclick;
+               upy = yclick;
+               if (upx < downx) {
+                   tmp = downx;
+                   downx = upx;
+                   upx = tmp;
+               }
+               if (upy < downy) {
+                   tmp = downy;
+                   downy = upy;
+                   upy = tmp;
+               }
+               xmin = (xmax - xmin) * (downx - 1000) / (8000) + xmin;
+               xmax = (xmax - xmin) * (upx - 1000) / (8000) + xmin;
+               ymax = ymax - (ymax - ymin) * (downy - 1000) / (8000);
+               ymin = ymax - (ymax - ymin) * (upy - 1000) / (8000);
+               break;
+           }
+       } while (n && (n != 2));
+    } while (n);
+    nice_end(EXIT_SUCCESS);
+    return EXIT_SUCCESS;
+}
+
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/grkelot.C b/src/grkelot.C
new file mode 100644 (file)
index 0000000..6486f5b
--- /dev/null
@@ -0,0 +1,428 @@
+/*---------------------------------*C*--------------------------------------*
+ * File:      grkelot.c
+ *--------------------------------------------------------------------------*
+ * $Id: grkelot.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1994,1995 Angelo Haritsis. All rights reserved.
+ *                             - original version
+ * Copyright (c) 1997,1998 Oezger Kesim <kesim@math.fu-berlin.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *--------------------------------------------------------------------------*
+ * Synopsis:    string -> greek ELOT928 or IBM437 string;
+ *              4-state FSM implementation.
+ *
+ * System:      Any (ANSI C)
+ *
+ * This is code derived from a more generic key remapper written by the same
+ * author and used in other environments. It was not written only
+ * for greek kbd bindings. An extension to other languages is easy
+ * (well don't know how the FSM lends itself to Far East languages).
+ *
+ * The FSM can have MAX_STATES states (change it for more).
+ * Each state contains:
+ * 1.  many tranlsation tables (registered via kstate_add_xlat())
+ * 2.  many switch codes for transition to other states (registered via
+ *      kstate_add_switcher()) : limit is static now: MAX_SWITCHER
+ * 3.   life: the number of xlations allowed in a state (0 = unlimited)
+ *
+ * Format of tranlation strings:
+ *      <first>-<last>:n1,n2,n3,...
+ * Format of switcher string:
+ *      A<char>:<state_no>
+ * (other switchers apart from A=ascii can be supported; not in this context)
+ * Format of life string:
+ *      L<N>            (N=0,1,...)
+ *-------------------------------------------------------------------------*
+ * Written by Angelo Haritis.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that the above copyright notice and this paragraph are duplicated in all
+ * such forms and that any documentation, advertising materials, and other
+ * materials related to such distribution and use acknowledge that the
+ * software was developed by Angelo Haritsis.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * NB: DO NOT ALTER! THIS CODE IS USED IN MANY PLATFORMS!!!
+ *
+ * TODO: make it more dynamic (linked lists is an idea but slower)
+ */
+
+#define RXVT                   /* define for use by rxvt */
+
+#ifdef RXVT
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "grkelot.intpro"      /* PROTOS for internal routines */
+#endif                         /* RXVT */
+
+#ifdef GREEK_SUPPORT
+#include "grkelot.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* --- Macros, Types --------- */
+#define MAX_STATES     4       /* max # states for the FSM */
+#define MAX_SWITCHER   2U      /* per state */
+#define MAX_VAL        256     /* for temp allocation */
+
+typedef unsigned char u_char;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+
+typedef struct s_xlat {
+    u_int           first, last;
+    u_int          *pval;      /* array of translated values */
+} K_XLAT;
+
+typedef struct s_switch {
+    u_char          type;      /* Ascii, Virtual, Scan */
+    u_int           code;
+    u_char          nextstate;
+    u_char          on;                /* current state of key: 0 = off */
+} K_SWITCH;
+
+typedef struct s_state {
+    u_int           num_xlat;  /* number of translations */
+    K_XLAT         *xlat;      /* State translations ((dynamic - realloc'ed) */
+    u_int           num_switcher;      /* number of switcher keys */
+    K_SWITCH        switcher[MAX_SWITCHER];    /* switcher keys to other states */
+    u_char          life;      /* 0 = until switched by key */
+    u_char          prev_state;        /* filled when jumped to a new state */
+} K_STATE;
+
+/* type for each one of the different greek standards (xlat types) */
+typedef struct s_xlat_type {
+    char           *plain;
+    char           *accent;
+    char           *accent_xtra;
+    char           *umlaut;
+    char           *acc_uml;
+} XLAT_TYPE;
+
+/* --- Local Data ------------ */
+static K_STATE  State[MAX_STATES];
+
+/* Current State */
+static u_char   nStateNow = 0;
+static K_STATE *pStateNow = &State[0];
+static int      GreekMode = GREEK_ELOT928;
+
+/*
+ * The following are hard-coded for now. The idea is that such strings would
+ * be read from a config file making it possible to change language/encodings
+ * more flexibly.
+ */
+/* elot 928 xlations */
+static char     elot_xlat_plain[] = "65-122:193,194,216,196,197,214,195,199,201,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,213,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,233,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,245,230";
+
+/* c and s give copyright and section sign */
+static char     elot_xlat_acc[] = "65-122:182,194,216,196,184,214,195,185,186,206,202,203,204,205,188,208,81,209,211,212,200,191,87,215,190,198,91,92,93,94,95,96,220,226," /*248 */ "169,228,221,246,227,222,223,238,234,235,236,237,252,240,113,241," /*243 */ "167,244,232,254,242,247,253,230";
+static char     elot_xlat_acc_xtra[] = "46-62:183,47,48,49,50,51,52,53,54,55,56,57,58,59,171,61,187";  /* anw teleia, quotes */
+static char     elot_xlat_uml[] = "65-122:193,194,216,196,197,214,195,199,218,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,219,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,250,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,251,230";
+static char     elot_xlat_umacc[] = "65-122:193,194,216,196,197,214,195,199,201,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,213,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,192,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,224,230";
+
+/* ibm 437 xlations */
+static char     i437_xlat_plain[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,160,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,172,157";
+static char     i437_xlat_acc[] = "65-122:234,129,150,131,235,148,130,236,237,141,137,138,139,140,238,143,81,144,145,146,135,240,87,149,239,133,91,92,93,94,95,96,225,153,175,155,226,173,154,227,229,165,161,162,163,164,230,167,113,168,169,171,159,233,170,174,231,157";
+static char     i437_xlat_acc_xtra[] = "46-46:250";    /* anw teleia */
+static char     i437_xlat_uml[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,228,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,232,157";
+static char     i437_xlat_umacc[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,42,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,42,157";
+
+/*
+ * currently ELOT928 and IBM437 are supported; easy to include others
+ * (not recommended: stick to just these 2 if not only the ELOT one)
+ */
+static XLAT_TYPE xlat_type[] =
+{
+    {elot_xlat_plain, elot_xlat_acc, elot_xlat_acc_xtra, elot_xlat_uml, elot_xlat_umacc},
+    {i437_xlat_plain, i437_xlat_acc, i437_xlat_acc_xtra, i437_xlat_uml, i437_xlat_umacc},
+};
+
+/* the current trasnaltion type */
+static XLAT_TYPE *xlat_now = &xlat_type[GREEK_ELOT928];
+
+#define NUM_XLAT_TYPES (sizeof(xlat_type) / sizeof(xlat_type[0]))
+
+static void     kstate_add_xlat(char *str);
+static void     kstate_add_switcher(char *str);
+static void     kstate_set_life(char *str);
+
+/* --- Functions ------------- */
+/* INTPROTO */
+void
+kstate_setcurr(int stateno)
+{
+    u_char          prev_state;
+
+    if ((u_int) stateno > (u_int) MAX_STATES)
+       return;
+    if (pStateNow->life == 1)
+       prev_state = pStateNow->prev_state;
+    else
+       prev_state = nStateNow;
+    pStateNow = &State[nStateNow = stateno];
+    pStateNow->prev_state = prev_state;
+}
+
+/* INTPROTO */
+void
+kstate_init(void)
+{
+    pStateNow->num_xlat = pStateNow->num_switcher = pStateNow->life = pStateNow->prev_state = 0;
+    pStateNow->xlat = NULL;
+}
+
+/* INTPROTO */
+void
+kstate_end(void)
+{
+    int             i;
+
+    for (i = 0; i < pStateNow->num_xlat; i++)
+       free(pStateNow->xlat[i].pval);
+    if (pStateNow->num_xlat > 0)
+       free(pStateNow->xlat);
+}
+
+/*
+ * Hard coded ELOT-928 translations. Could read these from an rc-type file
+ * to support other remappers.
+ */
+/* INTPROTO */
+void
+kstate_init_all(int greek_mode)
+{
+/* the translation tables for the 4 FSM states for ELOT-928 mappings */
+    int             i;
+
+    for (i = 0; i < MAX_STATES; i++) {
+       kstate_setcurr(i);
+       kstate_init();
+    }
+    if (greek_mode < 0 || greek_mode >= NUM_XLAT_TYPES)                /* avoid death */
+       greek_mode = GREEK_ELOT928;
+    xlat_now = &xlat_type[greek_mode];
+    kstate_setcurr(0);
+    kstate_add_xlat(xlat_now->plain);
+    kstate_add_switcher("A;:1");
+    kstate_add_switcher("A::2");
+    kstate_set_life("L0");
+
+    kstate_setcurr(1);
+    kstate_add_xlat(xlat_now->accent);
+    kstate_add_xlat(xlat_now->accent_xtra);
+    kstate_add_switcher("A::3");
+    kstate_set_life("L1");
+
+    kstate_setcurr(2);
+    kstate_add_xlat(xlat_now->umlaut);
+    kstate_add_switcher("A;:3");
+    kstate_set_life("L1");
+
+    kstate_setcurr(3);
+    kstate_add_xlat(xlat_now->acc_uml);
+    kstate_set_life("L1");
+}
+
+/* INTPROTO */
+void
+kstate_end_all(void)
+{
+    int             i;
+
+    for (i = 0; i < MAX_STATES; i++) {
+       kstate_setcurr(i);
+       kstate_end();
+    }
+    kstate_setcurr(0);
+}
+
+/*
+ * reset FSM
+ */
+/* INTPROTO */
+void
+kstate_reset(void)
+{
+    kstate_setcurr(0);
+}
+
+/* INTPROTO */
+void
+kstate_add_xlat(char *str)
+{
+    K_XLAT         *xlat;
+    u_int          *pval_tmp;
+    char           *sval;
+    int             i;
+
+    if (str == NULL)
+       return;
+/* add a new xlat table in state */
+    if (pStateNow->num_xlat == 0) {
+       pStateNow->xlat = malloc(sizeof(K_XLAT));
+    } else                     /* prefer contiguous data, realloc */
+       pStateNow->xlat = realloc(pStateNow->xlat, (pStateNow->num_xlat + 1) * sizeof(K_XLAT));
+    xlat = &pStateNow->xlat[pStateNow->num_xlat];
+/* parse str and derive first, last, values */
+    xlat->first = (u_int) atoi(strtok(str, "-"));
+    xlat->last = (u_int) atoi(strtok(NULL, ":"));
+    i = 0;
+    pval_tmp = calloc(MAX_VAL, sizeof(K_XLAT));
+    while ((sval = strtok(NULL, ",")) != NULL)
+       pval_tmp[i++] = (u_int) (atoi(sval));
+    xlat->pval = calloc(i, sizeof(K_XLAT));
+    if (xlat->pval != NULL)
+       memcpy(xlat->pval, pval_tmp, i * sizeof(u_int));
+    free(pval_tmp);
+    pStateNow->num_xlat++;
+}
+
+/*
+ * Ascii only for this implementation
+ */
+/* INTPROTO */
+void
+kstate_add_switcher(char *str)
+{
+    K_SWITCH       *switcher;
+
+    if (str == NULL)
+       return;
+    if (pStateNow->num_switcher >= MAX_SWITCHER)
+       return;
+    switcher = &pStateNow->switcher[pStateNow->num_switcher];
+    switch (switcher->type = str[0]) {
+    case 'A':                  /* ascii eg: A;:2 */
+       switcher->code = str[1];
+       switcher->nextstate = atoi(&str[3]);
+       break;
+    }
+    switcher->on = 0;
+    pStateNow->num_switcher++;
+}
+
+/* L1 or L0 */
+/* INTPROTO */
+void
+kstate_set_life(char *str)
+{
+    pStateNow->life = atoi(&str[1]);
+}
+
+/* INTPROTO */
+unsigned int
+kstate_cxlat(unsigned int c)
+{
+    int             i;
+
+/* check for ascii switcher */
+    for (i = 0; i < pStateNow->num_switcher; i++)
+       if (pStateNow->switcher[i].type == 'A' &&       /* only ascii here */
+           c == pStateNow->switcher[i].code) {
+           kstate_setcurr(pStateNow->switcher[i].nextstate);
+           pStateNow->switcher[i].on = 1;
+           return ((unsigned int)-1);
+       }
+/* do translation */
+    for (i = 0; i < pStateNow->num_xlat; i++)
+       if (c >= pStateNow->xlat[i].first && c <= pStateNow->xlat[i].last) {
+           c = pStateNow->xlat[i].pval[c - pStateNow->xlat[i].first];
+           break;
+       }
+/* switch back to previous state if life of current is 1 */
+    if (pStateNow->life == 1)
+       kstate_setcurr(pStateNow->prev_state);
+    return (c);
+}
+
+#ifdef RXVT
+/* EXTPROTO */
+void
+greek_init(void)
+{
+    kstate_init_all(GreekMode);
+}
+
+/* EXTPROTO */
+void
+greek_end(void)
+{
+    kstate_end_all();
+}
+
+/* EXTPROTO */
+void
+greek_reset(void)
+{
+    kstate_reset();
+}
+
+/* EXTPROTO */
+void
+greek_setmode(int greek_mode)
+{
+    GreekMode = greek_mode;
+}
+
+/* EXTPROTO */
+int
+greek_getmode(void)
+{
+    return (GreekMode);
+}
+
+/*
+ * xlate a given string in-place - return new string length
+ */
+/* EXTPROTO */
+int
+greek_xlat(char *s, int num_chars)
+{
+    int             i, count;
+    unsigned int    c;
+
+    for (i = 0, count = 0; i < num_chars; i++) {
+       c = kstate_cxlat((unsigned int)s[i]);
+       if (c != -1)
+           s[count++] = (char)c;
+    }
+    s[count] = '\0';
+    return (count);
+
+}
+
+#ifdef TEST
+int
+main(void)
+{
+/*char text[] = "abcdef;aGDZXC"; */
+    char            text[] = "abcdef;a:ibgdezhuiklmnjoprstyfxcv";
+
+    kstate_init_all(GREEK_ELOT928);
+    printf("text: %s\n", text);
+    greek_xlat(text, strlen(text));
+    printf("xlat'ed text: %s\n", text);
+    kstate_end_all();
+    return 0;
+}
+#endif
+#endif                         /* RXVT */
+
+#endif                         /* GREEK_SUPPORT */
diff --git a/src/grkelot.h b/src/grkelot.h
new file mode 100644 (file)
index 0000000..b0b2b23
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * File:       grkelot.h
+ * $Id: grkelot.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Synopsis:   string -> greek ELOT928 string; 4-state FSM.
+ *
+ * Copyright (c) 1994 Angelo Haritsis. All rights reserved.
+ * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _GRKELOT_H
+#define _GRKELOT_H
+
+#define GREEK_ELOT928  0
+#define GREEK_IBM437   1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+   extern void greek_init (void);
+   extern void greek_end (void);
+   extern void greek_reset (void);
+   extern void  greek_setmode(int greek_mode);
+   extern int   greek_getmode(void);
+   extern int  greek_xlat (char *s, int num_chars);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _GRKELOT_H */
diff --git a/src/init.C b/src/init.C
new file mode 100644 (file)
index 0000000..858e429
--- /dev/null
@@ -0,0 +1,1701 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       init.c
+ *----------------------------------------------------------------------*
+ * $Id: init.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1992      John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
+ *                             - original version
+ * Copyright (c) 1994      Robert Nation <nation@rocket.sanders.lockheed.com>
+ *                             - extensive modifications
+ * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
+ *                             - extensive modifications
+ * Copyright (c) 1999      D J Hawkey Jr <hawkeyd@visi.com>
+ *                             - QNX support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *---------------------------------------------------------------------*/
+/*
+ * Initialisation routines.
+ */
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "init.h"
+
+#include <signal.h>
+
+const char *const def_colorName[] = {
+    COLOR_FOREGROUND,
+    COLOR_BACKGROUND,
+/* low-intensity colors */
+    "Black",                   /* 0: black             (#000000) */
+#ifndef NO_BRIGHTCOLOR
+    "Red3",                    /* 1: red               (#CD0000) */
+    "Green3",                  /* 2: green             (#00CD00) */
+    "Yellow3",                 /* 3: yellow            (#CDCD00) */
+    "Blue3",                   /* 4: blue              (#0000CD) */
+    "Magenta3",                        /* 5: magenta           (#CD00CD) */
+    "Cyan3",                   /* 6: cyan              (#00CDCD) */
+# ifdef XTERM_COLORS
+    "Grey90",                  /* 7: white             (#E5E5E5) */
+# else
+    "AntiqueWhite",            /* 7: white             (#FAEBD7) */
+# endif
+/* high-intensity colors */
+# ifdef XTERM_COLORS
+    "Grey30",                  /* 8: bright black      (#4D4D4D) */
+# else
+    "Grey25",                  /* 8: bright black      (#404040) */
+# endif
+#endif                         /* NO_BRIGHTCOLOR */
+    "Red",                     /* 1/9: bright red      (#FF0000) */
+    "Green",                   /* 2/10: bright green   (#00FF00) */
+    "Yellow",                  /* 3/11: bright yellow  (#FFFF00) */
+    "Blue",                    /* 4/12: bright blue    (#0000FF) */
+    "Magenta",                 /* 5/13: bright magenta (#FF00FF) */
+    "Cyan",                    /* 6/14: bright cyan    (#00FFFF) */
+    "White",                   /* 7/15: bright white   (#FFFFFF) */
+#ifdef TTY_256COLOR
+    "rgb:00/00/00",            /* default 16-255 color table     */
+    "rgb:00/00/2a",
+    "rgb:00/00/55",
+    "rgb:00/00/7f",
+    "rgb:00/00/aa",
+    "rgb:00/00/d4",
+    "rgb:00/2a/00",
+    "rgb:00/2a/2a",
+    "rgb:00/2a/55",
+    "rgb:00/2a/7f",
+    "rgb:00/2a/aa",
+    "rgb:00/2a/d4",
+    "rgb:00/55/00",
+    "rgb:00/55/2a",
+    "rgb:00/55/55",
+    "rgb:00/55/7f",
+    "rgb:00/55/aa",
+    "rgb:00/55/d4",
+    "rgb:00/7f/00",
+    "rgb:00/7f/2a",
+    "rgb:00/7f/55",
+    "rgb:00/7f/7f",
+    "rgb:00/7f/aa",
+    "rgb:00/7f/d4",
+    "rgb:00/aa/00",
+    "rgb:00/aa/2a",
+    "rgb:00/aa/55",
+    "rgb:00/aa/7f",
+    "rgb:00/aa/aa",
+    "rgb:00/aa/d4",
+    "rgb:00/d4/00",
+    "rgb:00/d4/2a",
+    "rgb:00/d4/55",
+    "rgb:00/d4/7f",
+    "rgb:00/d4/aa",
+    "rgb:00/d4/d4",
+    "rgb:2a/00/00",
+    "rgb:2a/00/2a",
+    "rgb:2a/00/55",
+    "rgb:2a/00/7f",
+    "rgb:2a/00/aa",
+    "rgb:2a/00/d4",
+    "rgb:2a/2a/00",
+    "rgb:2a/2a/2a",
+    "rgb:2a/2a/55",
+    "rgb:2a/2a/7f",
+    "rgb:2a/2a/aa",
+    "rgb:2a/2a/d4",
+    "rgb:2a/55/00",
+    "rgb:2a/55/2a",
+    "rgb:2a/55/55",
+    "rgb:2a/55/7f",
+    "rgb:2a/55/aa",
+    "rgb:2a/55/d4",
+    "rgb:2a/7f/00",
+    "rgb:2a/7f/2a",
+    "rgb:2a/7f/55",
+    "rgb:2a/7f/7f",
+    "rgb:2a/7f/aa",
+    "rgb:2a/7f/d4",
+    "rgb:2a/aa/00",
+    "rgb:2a/aa/2a",
+    "rgb:2a/aa/55",
+    "rgb:2a/aa/7f",
+    "rgb:2a/aa/aa",
+    "rgb:2a/aa/d4",
+    "rgb:2a/d4/00",
+    "rgb:2a/d4/2a",
+    "rgb:2a/d4/55",
+    "rgb:2a/d4/7f",
+    "rgb:2a/d4/aa",
+    "rgb:2a/d4/d4",
+    "rgb:55/00/00",
+    "rgb:55/00/2a",
+    "rgb:55/00/55",
+    "rgb:55/00/7f",
+    "rgb:55/00/aa",
+    "rgb:55/00/d4",
+    "rgb:55/2a/00",
+    "rgb:55/2a/2a",
+    "rgb:55/2a/55",
+    "rgb:55/2a/7f",
+    "rgb:55/2a/aa",
+    "rgb:55/2a/d4",
+    "rgb:55/55/00",
+    "rgb:55/55/2a",
+    "rgb:55/55/55",
+    "rgb:55/55/7f",
+    "rgb:55/55/aa",
+    "rgb:55/55/d4",
+    "rgb:55/7f/00",
+    "rgb:55/7f/2a",
+    "rgb:55/7f/55",
+    "rgb:55/7f/7f",
+    "rgb:55/7f/aa",
+    "rgb:55/7f/d4",
+    "rgb:55/aa/00",
+    "rgb:55/aa/2a",
+    "rgb:55/aa/55",
+    "rgb:55/aa/7f",
+    "rgb:55/aa/aa",
+    "rgb:55/aa/d4",
+    "rgb:55/d4/00",
+    "rgb:55/d4/2a",
+    "rgb:55/d4/55",
+    "rgb:55/d4/7f",
+    "rgb:55/d4/aa",
+    "rgb:55/d4/d4",
+    "rgb:7f/00/00",
+    "rgb:7f/00/2a",
+    "rgb:7f/00/55",
+    "rgb:7f/00/7f",
+    "rgb:7f/00/aa",
+    "rgb:7f/00/d4",
+    "rgb:7f/2a/00",
+    "rgb:7f/2a/2a",
+    "rgb:7f/2a/55",
+    "rgb:7f/2a/7f",
+    "rgb:7f/2a/aa",
+    "rgb:7f/2a/d4",
+    "rgb:7f/55/00",
+    "rgb:7f/55/2a",
+    "rgb:7f/55/55",
+    "rgb:7f/55/7f",
+    "rgb:7f/55/aa",
+    "rgb:7f/55/d4",
+    "rgb:7f/7f/00",
+    "rgb:7f/7f/2a",
+    "rgb:7f/7f/55",
+    "rgb:7f/7f/7f",
+    "rgb:7f/7f/aa",
+    "rgb:7f/7f/d4",
+    "rgb:7f/aa/00",
+    "rgb:7f/aa/2a",
+    "rgb:7f/aa/55",
+    "rgb:7f/aa/7f",
+    "rgb:7f/aa/aa",
+    "rgb:7f/aa/d4",
+    "rgb:7f/d4/00",
+    "rgb:7f/d4/2a",
+    "rgb:7f/d4/55",
+    "rgb:7f/d4/7f",
+    "rgb:7f/d4/aa",
+    "rgb:7f/d4/d4",
+    "rgb:aa/00/00",
+    "rgb:aa/00/2a",
+    "rgb:aa/00/55",
+    "rgb:aa/00/7f",
+    "rgb:aa/00/aa",
+    "rgb:aa/00/d4",
+    "rgb:aa/2a/00",
+    "rgb:aa/2a/2a",
+    "rgb:aa/2a/55",
+    "rgb:aa/2a/7f",
+    "rgb:aa/2a/aa",
+    "rgb:aa/2a/d4",
+    "rgb:aa/55/00",
+    "rgb:aa/55/2a",
+    "rgb:aa/55/55",
+    "rgb:aa/55/7f",
+    "rgb:aa/55/aa",
+    "rgb:aa/55/d4",
+    "rgb:aa/7f/00",
+    "rgb:aa/7f/2a",
+    "rgb:aa/7f/55",
+    "rgb:aa/7f/7f",
+    "rgb:aa/7f/aa",
+    "rgb:aa/7f/d4",
+    "rgb:aa/aa/00",
+    "rgb:aa/aa/2a",
+    "rgb:aa/aa/55",
+    "rgb:aa/aa/7f",
+    "rgb:aa/aa/aa",
+    "rgb:aa/aa/d4",
+    "rgb:aa/d4/00",
+    "rgb:aa/d4/2a",
+    "rgb:aa/d4/55",
+    "rgb:aa/d4/7f",
+    "rgb:aa/d4/aa",
+    "rgb:aa/d4/d4",
+    "rgb:d4/00/00",
+    "rgb:d4/00/2a",
+    "rgb:d4/00/55",
+    "rgb:d4/00/7f",
+    "rgb:d4/00/aa",
+    "rgb:d4/00/d4",
+    "rgb:d4/2a/00",
+    "rgb:d4/2a/2a",
+    "rgb:d4/2a/55",
+    "rgb:d4/2a/7f",
+    "rgb:d4/2a/aa",
+    "rgb:d4/2a/d4",
+    "rgb:d4/55/00",
+    "rgb:d4/55/2a",
+    "rgb:d4/55/55",
+    "rgb:d4/55/7f",
+    "rgb:d4/55/aa",
+    "rgb:d4/55/d4",
+    "rgb:d4/7f/00",
+    "rgb:d4/7f/2a",
+    "rgb:d4/7f/55",
+    "rgb:d4/7f/7f",
+    "rgb:d4/7f/aa",
+    "rgb:d4/7f/d4",
+    "rgb:d4/aa/00",
+    "rgb:d4/aa/2a",
+    "rgb:d4/aa/55",
+    "rgb:d4/aa/7f",
+    "rgb:d4/aa/aa",
+    "rgb:d4/aa/d4",
+    "rgb:d4/d4/00",
+    "rgb:d4/d4/2a",
+    "rgb:d4/d4/55",
+    "rgb:d4/d4/7f",
+    "rgb:d4/d4/aa",
+    "rgb:d4/d4/d4",
+    "rgb:08/08/08",
+    "rgb:12/12/12",
+    "rgb:1c/1c/1c",
+    "rgb:26/26/26",
+    "rgb:30/30/30",
+    "rgb:3a/3a/3a",
+    "rgb:44/44/44",
+    "rgb:4e/4e/4e",
+    "rgb:58/58/58",
+    "rgb:62/62/62",
+    "rgb:6c/6c/6c",
+    "rgb:76/76/76",
+    "rgb:80/80/80",
+    "rgb:8a/8a/8a",
+    "rgb:94/94/94",
+    "rgb:9e/9e/9e",
+    "rgb:a8/a8/a8",
+    "rgb:b2/b2/b2",
+    "rgb:bc/bc/bc",
+    "rgb:c6/c6/c6",
+    "rgb:d0/d0/d0",
+    "rgb:da/da/da",
+    "rgb:e4/e4/e4",
+    "rgb:ee/ee/ee",
+#endif
+#ifndef NO_CURSORCOLOR
+    COLOR_CURSOR_BACKGROUND,
+    COLOR_CURSOR_FOREGROUND,
+#endif                         /* ! NO_CURSORCOLOR */
+    NULL,                      /* Color_pointer                  */
+    NULL,                      /* Color_border                   */
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+    NULL,                      /* Color_BD                       */
+    NULL,                      /* Color_UL                       */
+    NULL,                      /* Color_RV                       */
+#endif                         /* ! NO_BOLD_UNDERLINE_REVERSE */
+#ifdef OPTION_HC
+    NULL,
+#endif
+#ifdef KEEP_SCROLLCOLOR
+    COLOR_SCROLLBAR,
+    COLOR_SCROLLTROUGH,
+#endif                         /* KEEP_SCROLLCOLOR */
+};
+
+const char *const xa_names[NUM_XA] = {
+    "COMPOUND_TEXT",
+    "MULTIPLE",        
+    "TARGETS", 
+    "TEXT",
+    "TIMESTAMP",
+    "VT_SELECTION",
+    "INCR",
+    "WM_DELETE_WINDOW",
+#ifdef TRANSPARENT
+    "_XROOTPMAP_ID",
+#endif
+#ifdef OFFIX_DND
+    "DndProtocol",
+    "DndSelection",
+#endif
+    "CLIPBOARD"
+};
+
+/*----------------------------------------------------------------------*/
+/* substitute system functions */
+#if defined(__svr4__) && ! defined(_POSIX_VERSION)
+/* INTPROTO */
+int
+rxvt_getdtablesize(void)
+{
+    struct rlimit   rlim;
+
+    getrlimit(RLIMIT_NOFILE, &rlim);
+    return rlim.rlim_cur;
+}
+#endif
+/*----------------------------------------------------------------------*/
+/* EXTPROTO */
+int
+rxvt_init_vars(pR)
+{
+    struct rxvt_hidden *h;
+
+#ifndef NULLS_ARE_NOT_ZEROS
+    MEMSET(R, 0, sizeof(rxvt_t));
+#endif
+    h = R->h = (struct rxvt_hidden *)rxvt_calloc(1, sizeof(struct rxvt_hidden));
+
+    R->PixColors = (rxvt_color *)rxvt_malloc(sizeof(rxvt_color) * TOTAL_COLORS);
+    if (R->h == NULL || R->PixColors == NULL)
+       return -1;
+
+#if defined(XPM_BACKGROUND) || defined(TRANSPARENT)
+    R->TermWin.pixmap = None;
+#endif
+#ifdef UTMP_SUPPORT
+    h->next_utmp_action = SAVE;
+#endif
+#ifndef NO_SETOWNER_TTYDEV
+    h->next_tty_action = SAVE;
+#endif
+    h->MEvent.time = CurrentTime;
+    h->MEvent.button = AnyButton;
+    R->Options = DEFAULT_OPTIONS;
+    h->want_refresh = 1;
+    h->cmd_pid = -1;
+    R->cmd_fd = R->tty_fd = R->Xfd = -1;
+    h->PrivateModes = h->SavedModes = PrivMode_Default;
+    R->TermWin.focus = 1;
+    R->TermWin.ncol = 80;
+    R->TermWin.nrow = 24;
+    R->TermWin.int_bwidth = INTERNALBORDERWIDTH;
+    R->TermWin.ext_bwidth = EXTERNALBORDERWIDTH;
+    R->TermWin.lineSpace = LINESPACE;
+    R->TermWin.saveLines = SAVELINES;
+    R->numPixColors = TOTAL_COLORS;
+#ifndef NO_NEW_SELECTION
+    R->selection_style = NEW_SELECT;
+#else
+    R->selection_style = OLD_SELECT;
+#endif
+#ifndef NO_BRIGHTCOLOR
+    h->colorfgbg = DEFAULT_RSTYLE;
+#endif
+#if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
+    h->ks_bigfont = XK_greater;
+    h->ks_smallfont = XK_less;
+#endif
+#ifdef GREEK_SUPPORT
+    h->ks_greekmodeswith = GREEK_KEYBOARD_MODESWITCH;
+#endif
+    h->refresh_limit = 1;
+    h->refresh_type = SLOW_REFRESH;
+    h->prev_nrow = h->prev_ncol = 0;
+#ifdef MULTICHAR_SET
+# ifdef MULTICHAR_ENCODING
+    R->encoding_method = MULTICHAR_ENCODING;
+# endif
+    h->multichar_decode = rxvt_euc2jis;
+#endif
+    h->oldcursor.row = h->oldcursor.col = -1;
+#ifdef XPM_BACKGROUND
+/*  h->bgPixmap.w = h->bgPixmap.h = 0; */
+    h->bgPixmap.x = h->bgPixmap.y = 50;
+    h->bgPixmap.pixmap = None;
+#endif
+    h->last_bot = h->last_state = -1;
+#ifdef MENUBAR
+    h->menu_readonly = 1;
+# if !(MENUBAR_MAX > 1)
+    h->CurrentBar = &(h->BarList);
+# endif                                /* (MENUBAR_MAX > 1) */
+#endif
+    return 0;
+}
+
+/* EXTPROTO */
+void
+rxvt_init_secondary(pR)
+{
+    int             i;
+#ifdef TTY_GID_SUPPORT
+    struct group   *gr = getgrnam("tty");
+
+    if (gr) {          /* change group ownership of tty to "tty" */
+       R->h->ttymode = S_IRUSR | S_IWUSR | S_IWGRP;
+       R->h->ttygid = gr->gr_gid;
+    } else
+#endif                         /* TTY_GID_SUPPORT */
+    {
+       R->h->ttymode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
+       R->h->ttygid = getgid();
+    }
+#if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
+    R->h->locale = setlocale(LC_CTYPE, "");
+#endif
+
+/* get number of available file descriptors */
+#if defined(_POSIX_VERSION) || ! defined(__svr4__)
+    R->num_fds = (int)sysconf(_SC_OPEN_MAX);
+#else
+    R->num_fds = rxvt_getdtablesize();
+#endif
+
+/*
+ * Close all unused file descriptors
+ * We don't want them, we don't need them.
+ */
+    if ((i = open("/dev/null", O_RDONLY)) < 0) {
+       /* TODO: BOO HISS */
+       dup2(STDERR_FILENO, STDIN_FILENO);
+    } else if (i > STDIN_FILENO) {
+       dup2(i, STDIN_FILENO);
+       close(i);
+    }
+    dup2(STDERR_FILENO, STDOUT_FILENO);
+    for (i = STDERR_FILENO + 1; i < R->num_fds; i++) {
+#ifdef __sgi                   /* Alex Coventry says we need 4 & 7 too */
+       if (i == 4 || i == 7)
+           continue;
+#endif
+       close(i);
+    }
+}
+
+/*----------------------------------------------------------------------*/
+/* EXTPROTO */
+const char    **
+rxvt_init_resources(pR_ int argc, const char *const *argv)
+{
+    int             i, r_argc;
+    char           *val;
+    const char    **cmd_argv, **r_argv;
+    const char    **rs;
+
+/*
+ * Look for -exec option.  Find => split and make cmd_argv[] of command args
+ */
+    for (r_argc = 0; r_argc < argc; r_argc++)
+       if (!STRCMP(argv[r_argc], "-e") || !STRCMP(argv[r_argc], "-exec"))
+           break;
+    r_argv = (const char **)rxvt_malloc(sizeof(char *) * (r_argc + 1));
+
+    for (i = 0; i < r_argc; i++)
+       r_argv[i] = (const char *)argv[i];
+    r_argv[i] = NULL;
+    if (r_argc == argc)
+       cmd_argv = NULL;
+    else {
+       cmd_argv = (const char **)rxvt_malloc(sizeof(char *) * (argc - r_argc));
+
+       for (i = 0; i < argc - r_argc - 1; i++)
+           cmd_argv[i] = (const char *)argv[i + r_argc + 1];
+       cmd_argv[i] = NULL;
+    }
+
+/* clear all resources */
+    rs = R->h->rs;
+    for (i = 0; i < NUM_RESOURCES;)
+       rs[i++] = NULL;
+
+    rs[Rs_name] = rxvt_r_basename(argv[0]);
+/*
+ * Open display, get options/resources and create the window
+ */
+    if ((rs[Rs_display_name] = getenv("DISPLAY")) == NULL)
+       rs[Rs_display_name] = ":0";
+
+    rxvt_get_options(aR_ r_argc, r_argv);
+    free(r_argv);
+
+#ifdef LOCAL_X_IS_UNIX
+    if (rs[Rs_display_name][0] == ':') {
+       val = rxvt_malloc(5 + STRLEN(rs[Rs_display_name]));
+       STRCPY(val, "unix");
+       STRCAT(val, rs[Rs_display_name]);
+       R->Xdisplay = XOpenDisplay(val);
+       free(val);
+    }
+#endif
+
+    if (R->Xdisplay == NULL
+       && (R->Xdisplay = XOpenDisplay(rs[Rs_display_name])) == NULL) {
+       rxvt_print_error("can't open display %s", rs[Rs_display_name]);
+       exit(EXIT_FAILURE);
+    }
+
+    rxvt_extract_resources(aR_ R->Xdisplay, rs[Rs_name]);
+
+/*
+ * set any defaults not already set
+ */
+    if (cmd_argv && cmd_argv[0]) {
+       if (!rs[Rs_title])
+           rs[Rs_title] = rxvt_r_basename(cmd_argv[0]);
+       if (!rs[Rs_iconName])
+           rs[Rs_iconName] = rs[Rs_title];
+    } else {
+       if (!rs[Rs_title])
+           rs[Rs_title] = rs[Rs_name];
+       if (!rs[Rs_iconName])
+           rs[Rs_iconName] = rs[Rs_name];
+    }
+    if (rs[Rs_saveLines] && (i = atoi(rs[Rs_saveLines])) >= 0)
+       R->TermWin.saveLines = BOUND_POSITIVE_INT16(i);
+#ifndef NO_FRILLS
+    if (rs[Rs_int_bwidth] && (i = atoi(rs[Rs_int_bwidth])) >= 0)
+       R->TermWin.int_bwidth = min(i, 100);    /* arbitrary limit */
+    if (rs[Rs_ext_bwidth] && (i = atoi(rs[Rs_ext_bwidth])) >= 0)
+       R->TermWin.ext_bwidth = min(i, 100);    /* arbitrary limit */
+#endif
+#ifndef NO_LINESPACE
+    if (rs[Rs_lineSpace] && (i = atoi(rs[Rs_lineSpace])) >= 0)
+       R->TermWin.lineSpace = min(i, 100);     /* arbitrary limit */
+#endif
+
+#ifdef POINTER_BLANK
+    if (rs[Rs_pointerBlankDelay] && (i = atoi(rs[Rs_pointerBlankDelay])) >= 0)
+       R->h->pointerBlankDelay = i;
+    else
+       R->h->pointerBlankDelay = 2;
+#endif
+
+/* no point having a scrollbar without having any scrollback! */
+    if (!R->TermWin.saveLines)
+       R->Options &= ~Opt_scrollBar;
+
+#ifdef PRINTPIPE
+    if (!rs[Rs_print_pipe])
+       rs[Rs_print_pipe] = PRINTPIPE;
+#endif
+    if (!rs[Rs_cutchars])
+       rs[Rs_cutchars] = CUTCHARS;
+#ifdef ACS_ASCII
+    if (!rs[Rs_acs_chars])
+       rs[Rs_acs_chars] = ACS_CHARS;
+    if ((i = STRLEN(rs[Rs_acs_chars])) < 0x20) {
+       val = rxvt_realloc((void *)rs[Rs_acs_chars], 0x20);
+       for (; i < 0x20; )
+           val[i] = ' ';
+       rs[Rs_acs_chars] = val;
+    }
+#endif
+#ifndef NO_BACKSPACE_KEY
+    if (!rs[Rs_backspace_key])
+# ifdef DEFAULT_BACKSPACE
+       R->h->key_backspace = DEFAULT_BACKSPACE;
+# else
+       R->h->key_backspace = "DEC";    /* can toggle between \010 or \177 */
+# endif
+    else {
+       val = STRDUP(rs[Rs_backspace_key]);
+       rxvt_Str_trim(val);
+       rxvt_Str_escaped(val);
+       R->h->key_backspace = val;
+    }
+#endif
+#ifndef NO_DELETE_KEY
+    if (!rs[Rs_delete_key])
+# ifdef DEFAULT_DELETE
+       R->h->key_delete = DEFAULT_DELETE;
+# else
+       R->h->key_delete = "\033[3~";
+# endif
+    else {
+       val = STRDUP(rs[Rs_delete_key]);
+       rxvt_Str_trim(val);
+       rxvt_Str_escaped(val);
+       R->h->key_delete = val;
+    }
+#endif
+    if (rs[Rs_answerbackstring]) {
+       rxvt_Str_trim((char *)rs[Rs_answerbackstring]);
+       rxvt_Str_escaped((char *)rs[Rs_answerbackstring]);
+    }
+
+    if (rs[Rs_selectstyle]) {
+       if (STRNCASECMP(rs[Rs_selectstyle], "oldword", 7) == 0)
+           R->selection_style = OLD_WORD_SELECT;
+#ifndef NO_OLD_SELECTION
+       else if (STRNCASECMP(rs[Rs_selectstyle], "old", 3) == 0)
+           R->selection_style = OLD_SELECT;
+#endif
+    }
+
+#ifdef HAVE_SCROLLBARS
+    rxvt_setup_scrollbar(aR_ rs[Rs_scrollBar_align], rs[Rs_scrollstyle],
+                        rs[Rs_scrollBar_thickness]);
+#endif
+
+    R->TermWin.fontset = new rxvt_fontset (aR);
+    R->TermWin.fontset->populate (rs[Rs_font]);
+    R->TermWin.fwidth  = R->TermWin.fontset->base_font ()->width;
+    R->TermWin.fheight = R->TermWin.fontset->base_font ()->height;
+    R->TermWin.fbase   = R->TermWin.fontset->base_font ()->ascent;
+
+#ifdef XTERM_REVERSE_VIDEO
+/* this is how xterm implements reverseVideo */
+    if (R->Options & Opt_reverseVideo) {
+       if (!rs[Rs_color + Color_fg])
+           rs[Rs_color + Color_fg] = def_colorName[Color_bg];
+       if (!rs[Rs_color + Color_bg])
+           rs[Rs_color + Color_bg] = def_colorName[Color_fg];
+    }
+#endif
+
+    for (i = 0; i < NRS_COLORS; i++)
+       if (!rs[Rs_color + i])
+           rs[Rs_color + i] = def_colorName[i];
+
+#ifndef XTERM_REVERSE_VIDEO
+/* this is how we implement reverseVideo */
+    if (R->Options & Opt_reverseVideo)
+       SWAP_IT(rs[Rs_color + Color_fg], rs[Rs_color + Color_bg], const char *);
+#endif
+
+/* convenient aliases for setting fg/bg to colors */
+    rxvt_color_aliases(aR_ Color_fg);
+    rxvt_color_aliases(aR_ Color_bg);
+#ifndef NO_CURSORCOLOR
+    rxvt_color_aliases(aR_ Color_cursor);
+    rxvt_color_aliases(aR_ Color_cursor2);
+#endif                         /* NO_CURSORCOLOR */
+    rxvt_color_aliases(aR_ Color_pointer);
+    rxvt_color_aliases(aR_ Color_border);
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+    rxvt_color_aliases(aR_ Color_BD);
+    rxvt_color_aliases(aR_ Color_UL);
+    rxvt_color_aliases(aR_ Color_RV);
+#endif                         /* ! NO_BOLD_UNDERLINE_REVERSE */
+
+    return cmd_argv;
+}
+
+/*----------------------------------------------------------------------*/
+/* EXTPROTO */
+void
+rxvt_init_env(pR)
+{
+    int             i;
+    unsigned int    u;
+    char           *val;
+
+#ifdef DISPLAY_IS_IP
+/* Fixup display_name for export over pty to any interested terminal
+ * clients via "ESC[7n" (e.g. shells).  Note we use the pure IP number
+ * (for the first non-loopback interface) that we get from
+ * rxvt_network_display().  This is more "name-resolution-portable", if you
+ * will, and probably allows for faster x-client startup if your name
+ * server is beyond a slow link or overloaded at client startup.  Of
+ * course that only helps the shell's child processes, not us.
+ *
+ * Giving out the display_name also affords a potential security hole
+ */
+    val = rxvt_network_display(R->h->rs[Rs_display_name]);
+    R->h->rs[Rs_display_name] = (const char *)val;
+    if (val == NULL)
+#endif                         /* DISPLAY_IS_IP */
+       val = XDisplayString(R->Xdisplay);
+    if (R->h->rs[Rs_display_name] == NULL)
+       R->h->rs[Rs_display_name] = val;        /* use broken `:0' value */
+
+    i = STRLEN(val);
+    R->h->env_display = (char *)rxvt_malloc((i + 9) * sizeof(char));
+
+    sprintf(R->h->env_display, "DISPLAY=%s", val);
+
+    /* avoiding the math library:
+     * i = (int)(ceil(log10((unsigned int)R->TermWin.parent[0]))) */
+    for (i = 0, u = (unsigned int)R->TermWin.parent[0]; u; u /= 10, i++) ;
+    MAX_IT(i, 1);
+    R->h->env_windowid = (char *)rxvt_malloc((i + 10) * sizeof(char));
+
+    sprintf(R->h->env_windowid, "WINDOWID=%u",
+           (unsigned int)R->TermWin.parent[0]);
+
+/* add entries to the environment:
+ * @ DISPLAY:   in case we started with -display
+ * @ WINDOWID:  X window id number of the window
+ * @ COLORTERM: terminal sub-name and also indicates its color
+ * @ TERM:      terminal name
+ * @ TERMINFO: path to terminfo directory
+ */
+    putenv(R->h->env_display);
+    putenv(R->h->env_windowid);
+#ifdef RXVT_TERMINFO
+    putenv("TERMINFO=" RXVT_TERMINFO);
+#endif
+    if (XDEPTH <= 2)
+       putenv("COLORTERM=" COLORTERMENV "-mono");
+    else
+       putenv("COLORTERM=" COLORTERMENVFULL);
+    if (R->h->rs[Rs_term_name] != NULL) {
+       R->h->env_term = (char *)rxvt_malloc((STRLEN(R->h->rs[Rs_term_name]) + 6) * sizeof(char));
+       sprintf(R->h->env_term, "TERM=%s", R->h->rs[Rs_term_name]);
+       putenv(R->h->env_term);
+    } else
+       putenv("TERM=" TERMENV);
+
+#ifdef HAVE_UNSETENV
+/* avoid passing old settings and confusing term size */
+    unsetenv("LINES");
+    unsetenv("COLUMNS");
+    unsetenv("TERMCAP");       /* terminfo should be okay */
+#endif                         /* HAVE_UNSETENV */
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * This is more or less stolen straight from XFree86 xterm.
+ * This should support all European type languages.
+ */
+/* EXTPROTO */
+void
+rxvt_init_xlocale(pR)
+{
+#ifdef USE_XIM
+    if (R->h->locale == NULL)
+       rxvt_print_error("Setting locale failed.");
+    else {
+       Atom            wmlocale;
+
+       wmlocale = XInternAtom(R->Xdisplay, "WM_LOCALE_NAME", False);
+       XChangeProperty(R->Xdisplay, R->TermWin.parent[0], wmlocale,
+                       XA_STRING, 8, PropModeReplace,
+                       (unsigned char *)R->h->locale, STRLEN(R->h->locale));
+
+       if (XSupportsLocale() != True) {
+           rxvt_print_error("The locale is not supported by Xlib");
+           return;
+       }
+       rxvt_setTermFontSet(aR_ 0);
+
+       /* see if we can connect yet */
+       rxvt_IMInstantiateCallback(R->Xdisplay, NULL, NULL);
+
+       /* To avoid Segmentation Fault in C locale: Solaris only? */
+       if (STRCMP(R->h->locale, "C"))
+           XRegisterIMInstantiateCallback(R->Xdisplay, NULL, NULL, NULL,
+                                          rxvt_IMInstantiateCallback, NULL);
+    }
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/* EXTPROTO */
+void
+rxvt_init_command(pR_ const char *const *argv)
+{
+/*
+ * Initialize the command connection.
+ * This should be called after the X server connection is established.
+ */
+    int             i;
+
+    for (i = 0; i < NUM_XA; i++)
+       R->h->xa[i] = XInternAtom(R->Xdisplay, xa_names[i], False);
+
+/* Enable delete window protocol */
+    XSetWMProtocols(R->Xdisplay, R->TermWin.parent[0],
+                   &(R->h->xa[XA_WMDELETEWINDOW]), 1);
+
+#ifdef USING_W11LIB
+/* enable W11 callbacks */
+    W11AddEventHandler(R->Xdisplay, rxvt_W11_process_x_event);
+#endif
+
+#ifdef META8_OPTION
+    R->h->meta_char = (R->Options & Opt_meta8 ? 0x80 : C0_ESC);
+#endif
+    rxvt_get_ourmods(aR);
+    if (!(R->Options & Opt_scrollTtyOutput))
+       R->h->PrivateModes |= PrivMode_TtyOutputInh;
+    if (R->Options & Opt_scrollTtyKeypress)
+       R->h->PrivateModes |= PrivMode_Keypress;
+    if (!(R->Options & Opt_jumpScroll))
+       R->h->PrivateModes |= PrivMode_smoothScroll;
+#ifndef NO_BACKSPACE_KEY
+    if (STRCMP(R->h->key_backspace, "DEC") == 0)
+       R->h->PrivateModes |= PrivMode_HaveBackSpace;
+#endif
+/* add value for scrollBar */
+    if (scrollbar_visible(R)) {
+       R->h->PrivateModes |= PrivMode_scrollBar;
+       R->h->SavedModes |= PrivMode_scrollBar;
+    }
+    if (menubar_visible(R)) {
+       R->h->PrivateModes |= PrivMode_menuBar;
+       R->h->SavedModes |= PrivMode_menuBar;
+    }
+#ifdef GREEK_SUPPORT
+    greek_init();
+#endif
+
+    R->Xfd = XConnectionNumber(R->Xdisplay);
+
+#ifdef CURSOR_BLINK
+    if (R->Options & Opt_cursorBlink)
+       (void)gettimeofday(&R->h->lastcursorchange, NULL);
+#endif
+
+    if ((R->cmd_fd = rxvt_run_command(aR_ argv)) < 0) {
+       rxvt_print_error("aborting");
+       exit(EXIT_FAILURE);
+    }
+}
+
+/*----------------------------------------------------------------------*/
+/* INTPROTO */
+void
+rxvt_Get_Colours(pR)
+{
+    int             i;
+
+    for (i = 0; i < (XDEPTH <= 2 ? 2 : NRS_COLORS); i++) {
+       rxvt_color          xcol;
+
+       if (!R->h->rs[Rs_color + i])
+           continue;
+
+       if (!rxvt_rXParseAllocColor(aR_ &xcol, R->h->rs[Rs_color + i])) {
+#ifndef XTERM_REVERSE_VIDEO
+           if (i < 2 && (R->Options & Opt_reverseVideo)) {
+               R->h->rs[Rs_color + i] = def_colorName[!i];
+           } else
+#endif
+               R->h->rs[Rs_color + i] = def_colorName[i];
+           if (!R->h->rs[Rs_color + i])
+               continue;
+           if (!rxvt_rXParseAllocColor(aR_ &xcol, R->h->rs[Rs_color + i])) {
+               switch (i) {
+               case Color_fg:
+               case Color_bg:
+                   /* fatal: need bg/fg color */
+                   rxvt_print_error("aborting");
+                   exit(EXIT_FAILURE);
+               /* NOTREACHED */
+                   break;
+#ifndef NO_CURSORCOLOR
+               case Color_cursor2:
+                   xcol = R->PixColors[Color_fg];
+                   break;
+#endif                         /* ! NO_CURSORCOLOR */
+               case Color_pointer:
+                   xcol = R->PixColors[Color_fg];
+                   break;
+               default:
+                   xcol = R->PixColors[Color_bg];      /* None */
+                   break;
+               }
+           }
+       }
+       R->PixColors[i] = xcol;
+       SET_PIXCOLOR(R->h, i);
+    }
+
+    if (XDEPTH <= 2 || !R->h->rs[Rs_color + Color_pointer])
+       R->PixColors[Color_pointer] = R->PixColors[Color_fg];
+    if (XDEPTH <= 2 || !R->h->rs[Rs_color + Color_border])
+       R->PixColors[Color_border] = R->PixColors[Color_fg];
+
+/*
+ * get scrollBar/menuBar shadow colors
+ *
+ * The calculations of topShadow/bottomShadow values are adapted
+ * from the fvwm window manager.
+ */
+#ifdef KEEP_SCROLLCOLOR
+    if (XDEPTH <= 2) { /* Monochrome */
+       R->PixColors[Color_scroll] = R->PixColors[Color_fg];
+       R->PixColors[Color_topShadow] = R->PixColors[Color_bg];
+       R->PixColors[Color_bottomShadow] = R->PixColors[Color_bg];
+    } else {
+       rxvt_color          xcol[3];
+       /* xcol[0] == white
+        * xcol[1] == top shadow
+        * xcol[2] == bot shadow */
+
+       xcol[1] = R->PixColors[Color_scroll];
+# ifdef PREFER_24BIT
+        xcol[0].set (r, -1, -1, -1);
+/*        XFreeColors(R->Xdisplay, XCMAP, &(xcol[0].pixel), 1, ~0); */
+# else
+        xcol[0].set (WhitePixel(R->Xdisplay, Xscreen));
+# endif
+
+        unsigned short R1, G1, B1, R0, G0, B0;
+
+        xcol[0].get (r, R0, G0, B0);
+        xcol[1].get (r, R1, G1, B1);
+
+       /* bottomShadowColor */
+        if (!xcol[2].set (aR_ R1 / 2, G1 / 2, B1 / 2))
+           xcol[2] = R->PixColors[Color_Black];
+
+       R->PixColors[Color_bottomShadow] = xcol[2];
+
+       /* topShadowColor */
+        if (!xcol[1].set (aR_
+                          min (R0, max (R0 / 5, R1) * 7 / 5),
+                          min (G0, max (G0 / 5, G1) * 7 / 5),
+                          min (B0, max (B0 / 5, B1) * 7 / 5)))
+           xcol[1] = R->PixColors[Color_White];
+
+       R->PixColors[Color_topShadow] = xcol[1];
+    }
+#endif                         /* KEEP_SCROLLCOLOR */
+}
+
+/*----------------------------------------------------------------------*/
+/* color aliases, fg/bg bright-bold */
+/* INTPROTO */
+void
+rxvt_color_aliases(pR_ int idx)
+{
+    if (R->h->rs[Rs_color + idx] && isdigit(*(R->h->rs[Rs_color + idx]))) {
+       int             i = atoi(R->h->rs[Rs_color + idx]);
+
+       if (i >= 8 && i <= 15) {        /* bright colors */
+           i -= 8;
+#ifndef NO_BRIGHTCOLOR
+           R->h->rs[Rs_color + idx] = R->h->rs[Rs_color + minBrightCOLOR + i];
+           return;
+#endif
+       }
+       if (i >= 0 && i <= 7)   /* normal colors */
+           R->h->rs[Rs_color + idx] = R->h->rs[Rs_color + minCOLOR + i];
+    }
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * Probe the modifier keymap to get the Meta (Alt) and Num_Lock settings
+ * Use resource ``modifier'' to override the Meta modifier
+ */
+/* INTPROTO */
+void
+rxvt_get_ourmods(pR)
+{
+    int             i, j, k;
+    int             requestedmeta, realmeta, realalt;
+    const char     *cm, *rsmod;
+    XModifierKeymap *map;
+    KeyCode        *kc;
+    const unsigned int modmasks[] =
+       { Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
+
+    requestedmeta = realmeta = realalt = 0;
+    rsmod = R->h->rs[Rs_modifier];
+    if (rsmod
+       && STRCASECMP(rsmod, "mod1") >= 0 && STRCASECMP(rsmod, "mod5") <= 0)
+       requestedmeta = rsmod[3] - '0';
+
+    map = XGetModifierMapping(R->Xdisplay);
+    kc = map->modifiermap;
+    for (i = 1; i < 6; i++) {
+       k = (i + 2) * map->max_keypermod;       /* skip shift/lock/control */
+       for (j = map->max_keypermod; j--; k++) {
+           if (kc[k] == 0)
+               break;
+           switch (XKeycodeToKeysym(R->Xdisplay, kc[k], 0)) {
+           case XK_Num_Lock:
+               R->h->ModNumLockMask = modmasks[i - 1];
+               /* FALLTHROUGH */
+           default:
+               continue;       /* for(;;) */
+           case XK_Meta_L:
+           case XK_Meta_R:
+               cm = "meta";
+               realmeta = i;
+               break;
+           case XK_Alt_L:
+           case XK_Alt_R:
+               cm = "alt";
+               realalt = i;
+               break;
+           case XK_Super_L:
+           case XK_Super_R:
+               cm = "super";
+               break;
+           case XK_Hyper_L:
+           case XK_Hyper_R:
+               cm = "hyper";
+               break;
+           }
+           if (rsmod && STRNCASECMP(rsmod, cm, STRLEN(cm)) == 0)
+               requestedmeta = i;
+       }
+    }
+    XFreeModifiermap(map);
+    i = (requestedmeta ? requestedmeta
+                      : (realmeta ? realmeta
+                                  : (realalt ? realalt : 0)));
+    if (i)
+       R->h->ModMetaMask = modmasks[i - 1];
+}
+
+/*----------------------------------------------------------------------*/
+/* rxvt_Create_Windows() - Open and map the window */
+/* EXTPROTO */
+void
+rxvt_Create_Windows(pR_ int argc, const char *const *argv)
+{
+    XClassHint      classHint;
+    XWMHints        wmHint;
+    XGCValues       gcvalue;
+    long            vt_emask;
+
+#ifdef PREFER_24BIT
+    XSetWindowAttributes attributes;
+    XWindowAttributes gattr;
+
+    XCMAP = DefaultColormap(R->Xdisplay, Xscreen);
+    XVISUAL = DefaultVisual(R->Xdisplay, Xscreen);
+
+#ifdef POINTER_BLANK
+    static rxvt_color blackcolour;
+    blackcolour.set (r, 0, 0, 0);
+#endif
+    if (R->Options & Opt_transparent) {
+       XGetWindowAttributes(R->Xdisplay, RootWindow(R->Xdisplay, Xscreen),
+                            &gattr);
+       XDEPTH = gattr.depth;
+    } else {
+       XDEPTH = DefaultDepth(R->Xdisplay, Xscreen);
+/*
+ * If depth is not 24, look for a 24bit visual.
+ */
+       if (XDEPTH != 24) {
+           XVisualInfo     vinfo;
+
+           if (XMatchVisualInfo(R->Xdisplay, Xscreen, 24, TrueColor, &vinfo)) {
+               XDEPTH = 24;
+               XVISUAL = vinfo.visual;
+               XCMAP = XCreateColormap(R->Xdisplay,
+                                       RootWindow(R->Xdisplay, Xscreen),
+                                       XVISUAL, AllocNone);
+           }
+       }
+    }
+#endif
+
+/* grab colors before netscape does */
+    rxvt_Get_Colours(aR);
+
+    rxvt_change_font(aR_ 1, NULL);
+    rxvt_window_calc(aR_ 0, 0);
+    R->h->old_width = R->szHint.width;
+    R->h->old_height = R->szHint.height;
+
+/* parent window - reverse video so we can see placement errors
+ * sub-window placement & size in rxvt_resize_subwindows()
+ */
+
+#ifdef PREFER_24BIT
+    attributes.background_pixel = R->PixColors[Color_fg];
+    attributes.border_pixel = R->PixColors[Color_border];
+    attributes.colormap = XCMAP;
+    R->TermWin.parent[0] = XCreateWindow(R->Xdisplay, Xroot,
+                                        R->szHint.x, R->szHint.y,
+                                        R->szHint.width, R->szHint.height,
+                                        R->TermWin.ext_bwidth,
+                                        XDEPTH, InputOutput,
+                                        XVISUAL,
+                                        CWBackPixel | CWBorderPixel
+                                        | CWColormap, &attributes);
+#else
+    R->TermWin.parent[0] = XCreateSimpleWindow(R->Xdisplay, Xroot,
+                                              R->szHint.x, R->szHint.y,
+                                              R->szHint.width,
+                                              R->szHint.height,
+                                              R->TermWin.ext_bwidth,
+                                              R->PixColors[Color_border],
+                                              R->PixColors[Color_fg]);
+#endif
+    rxvt_xterm_seq(aR_ XTerm_title, R->h->rs[Rs_title], CHAR_ST);
+    rxvt_xterm_seq(aR_ XTerm_iconName, R->h->rs[Rs_iconName], CHAR_ST);
+
+    classHint.res_name = (char *)R->h->rs[Rs_name];
+    classHint.res_class = (char *)APL_CLASS;
+
+    wmHint.flags = (InputHint | StateHint | WindowGroupHint);
+    wmHint.input = True;
+    wmHint.initial_state = (R->Options & Opt_iconic ? IconicState
+                                                   : NormalState);
+    wmHint.window_group = R->TermWin.parent[0];
+
+    XSetWMProperties(R->Xdisplay, R->TermWin.parent[0], NULL, NULL,
+                    (char **)argv, argc, &R->szHint, &wmHint, &classHint);
+    XSelectInput(R->Xdisplay, R->TermWin.parent[0],
+                (KeyPressMask
+#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
+                 | KeyReleaseMask
+#endif
+                 | FocusChangeMask | VisibilityChangeMask
+                 | StructureNotifyMask));
+
+/* vt cursor: Black-on-White is standard, but this is more popular */
+    R->TermWin_cursor = XCreateFontCursor(R->Xdisplay, XC_xterm);
+
+#if defined(HAVE_SCROLLBARS) || defined(MENUBAR)
+/* cursor (menuBar/scrollBar): Black-on-White */
+    R->h->pointer_leftptr = XCreateFontCursor(R->Xdisplay, XC_left_ptr);
+#endif
+
+#ifdef POINTER_BLANK
+    R->h->pointer_blank = XCreateGlyphCursor(R->Xdisplay, R->TermWin.font->fid,
+                                            R->TermWin.font->fid, ' ', ' ',
+                                            &blackcolour, &blackcolour);
+#endif
+
+/* the vt window */
+    R->TermWin.vt = XCreateSimpleWindow(R->Xdisplay, R->TermWin.parent[0],
+                                       R->h->window_vt_x, R->h->window_vt_y,
+                                       TermWin_TotalWidth(),
+                                       TermWin_TotalHeight(),
+                                       0,
+                                       R->PixColors[Color_fg],
+                                       R->PixColors[Color_bg]);
+#ifdef DEBUG_X
+    XStoreName(R->Xdisplay, R->TermWin.vt, "vt window");
+#endif
+    rxvt_pointer_unblank(aR);
+    vt_emask = (ExposureMask | ButtonPressMask | ButtonReleaseMask
+               | PropertyChangeMask);
+#ifdef POINTER_BLANK
+    if ((R->Options & Opt_pointerBlank))
+       vt_emask |= PointerMotionMask;
+    else
+#endif
+       vt_emask |= (Button1MotionMask | Button3MotionMask);
+    XSelectInput(R->Xdisplay, R->TermWin.vt, vt_emask);
+
+#if defined(MENUBAR) && (MENUBAR_MAX > 1)
+    if (menuBar_height()) {
+       R->menuBar.win = XCreateSimpleWindow(R->Xdisplay, R->TermWin.parent[0],
+                                            R->h->window_vt_x, 0,
+                                            TermWin_TotalWidth(),
+                                            menuBar_TotalHeight(),
+                                            0,
+                                            R->PixColors[Color_fg],
+                                            R->PixColors[Color_scroll]);
+#ifdef DEBUG_X
+    XStoreName(R->Xdisplay, R->menuBar.win, "menubar");
+#endif
+       XDefineCursor(R->Xdisplay, R->menuBar.win, R->h->pointer_leftptr);
+       XSelectInput(R->Xdisplay, R->menuBar.win,
+                    (ExposureMask | ButtonPressMask | ButtonReleaseMask
+                     | Button1MotionMask));
+    }
+#endif
+#ifdef XPM_BACKGROUND
+    if (R->h->rs[Rs_backgroundPixmap] != NULL
+       && !(R->Options & Opt_transparent)) {
+       const char     *p = R->h->rs[Rs_backgroundPixmap];
+
+       if ((p = STRCHR(p, ';')) != NULL) {
+           p++;
+           rxvt_scale_pixmap(aR_ p);
+       }
+       rxvt_set_bgPixmap(aR_ R->h->rs[Rs_backgroundPixmap]);
+       rxvt_scr_touch(aR_ True);
+    }
+#endif
+
+/* graphics context for the vt window */
+    gcvalue.foreground = R->PixColors[Color_fg];
+    gcvalue.background = R->PixColors[Color_bg];
+    gcvalue.graphics_exposures = 1;
+    R->TermWin.gc = XCreateGC(R->Xdisplay, R->TermWin.vt,
+                             GCForeground | GCBackground
+                             | GCGraphicsExposures, &gcvalue);
+
+#if defined(MENUBAR) || defined(RXVT_SCROLLBAR)
+    gcvalue.foreground = R->PixColors[Color_topShadow];
+    R->h->topShadowGC = XCreateGC(R->Xdisplay, R->TermWin.vt,
+                                 GCForeground, &gcvalue);
+    gcvalue.foreground = R->PixColors[Color_bottomShadow];
+    R->h->botShadowGC = XCreateGC(R->Xdisplay, R->TermWin.vt,
+                                 GCForeground, &gcvalue);
+    gcvalue.foreground = R->PixColors[(XDEPTH <= 2 ? Color_fg
+                                                  : Color_scroll)];
+    R->h->scrollbarGC = XCreateGC(R->Xdisplay, R->TermWin.vt,
+                                 GCForeground, &gcvalue);
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * Run the command in a subprocess and return a file descriptor for the
+ * master end of the pseudo-teletype pair with the command talking to
+ * the slave.
+ */
+/* INTPROTO */
+int
+rxvt_run_command(pR_ const char *const *argv)
+{
+    int             cfd, er;
+
+/* get master (pty) */
+    if ((cfd = rxvt_get_pty(&(R->tty_fd), &(R->h->ttydev))) < 0) {
+       rxvt_print_error("can't open pseudo-tty");
+       return -1;
+    }
+#ifdef FD_SETSIZE
+    if (R->Xfd > FD_SETSIZE || cfd > FD_SETSIZE) {
+       rxvt_print_error("fd too high: %d max", FD_SETSIZE);
+       rxvt_clean_exit();
+       exit(EXIT_FAILURE);
+    }
+#endif
+    fcntl(cfd, F_SETFL, O_NDELAY);
+
+/* get slave (tty) */
+    if (R->tty_fd < 0) {
+#ifndef NO_SETOWNER_TTYDEV
+       rxvt_privileged_ttydev(aR_ SAVE);
+#endif
+       if ((R->tty_fd = rxvt_get_tty(R->h->ttydev)) < 0) {
+           close(cfd);
+           rxvt_print_error("can't open slave tty %s", R->h->ttydev);
+           return -1;
+       }
+    }
+#ifndef NO_BACKSPACE_KEY
+    if (R->h->key_backspace[0] && !R->h->key_backspace[1])
+       er = R->h->key_backspace[0];
+    else if (STRCMP(R->h->key_backspace, "DEC") == 0)
+       er = '\177';            /* the initial state anyway */
+    else
+#endif
+       er = -1;
+    rxvt_get_ttymode(&(R->h->tio), er);
+
+/* install exit handler for cleanup */
+#ifdef HAVE_ATEXIT
+    atexit(rxvt_clean_exit);
+#else
+# ifdef HAVE_ON_EXIT
+    on_exit(rxvt_clean_exit, NULL);    /* non-ANSI exit handler */
+# endif
+#endif
+
+    signal(SIGHUP, rxvt_Exit_signal);
+#ifndef __svr4__
+    signal(SIGINT, rxvt_Exit_signal);
+#endif
+    signal(SIGQUIT, rxvt_Exit_signal);
+    signal(SIGTERM, rxvt_Exit_signal);
+    signal(SIGCHLD, rxvt_Child_signal);
+
+/* need to trap SIGURG for SVR4 (Unixware) rlogin */
+/* signal (SIGURG, SIG_DFL); */
+
+#ifndef __QNX__
+/* spin off the command interpreter */
+    switch (R->h->cmd_pid = fork()) {
+    case -1:
+       rxvt_print_error("can't fork");
+       return -1;
+    case 0:
+       close(cfd);             /* only keep R->tty_fd and STDERR open */
+       close(R->Xfd);
+       if (rxvt_control_tty(R->tty_fd, R->h->ttydev) < 0)
+           rxvt_print_error("could not obtain control of tty");
+       else {
+       /* Reopen stdin, stdout and stderr over the tty file descriptor */
+           dup2(R->tty_fd, STDIN_FILENO);
+           dup2(R->tty_fd, STDOUT_FILENO);
+           dup2(R->tty_fd, STDERR_FILENO);
+           if (R->tty_fd > 2)
+               close(R->tty_fd);
+           rxvt_run_child(aR_ argv);
+       }
+       exit(EXIT_FAILURE);
+       /* NOTREACHED */
+    default:
+       {
+#if defined(HAVE_STRUCT_UTMP) && defined(HAVE_TTYSLOT)
+           int             fdstdin;
+
+           fdstdin = dup(STDIN_FILENO);
+           dup2(R->tty_fd, STDIN_FILENO);
+#endif
+           rxvt_privileged_utmp(aR_ SAVE);
+#if defined(HAVE_STRUCT_UTMP) && defined(HAVE_TTYSLOT)
+           dup2(fdstdin, STDIN_FILENO);
+           close(fdstdin);
+#endif
+       }
+       close(R->tty_fd);       /* keep STDERR_FILENO, R->cmd_fd, R->Xfd open */
+       break;
+    }
+#else                          /* __QNX__ uses qnxspawn() */
+    fchmod(R->tty_fd, 0622);
+    fcntl(R->tty_fd, F_SETFD, FD_CLOEXEC);
+    fcntl(cfd, F_SETFD, FD_CLOEXEC);
+
+    if (rxvt_run_child(aR_ argv) == -1)
+       exit(EXIT_FAILURE);
+#endif
+/*
+ * Reduce R->num_fds to what we use, so select() is more efficient
+ */
+    R->num_fds = max(STDERR_FILENO, cfd);
+    MAX_IT(R->num_fds, R->Xfd);
+#ifdef __sgi                   /* Alex Coventry says we need 4 & 7 too */
+    MAX_IT(R->num_fds, 7);
+#endif
+    R->num_fds++;              /* counts from 0 */
+
+    return cfd;
+}
+
+/* ------------------------------------------------------------------------- *
+ *                          CHILD PROCESS OPERATIONS                         *
+ * ------------------------------------------------------------------------- */
+/*
+ * The only open file descriptor is the slave tty - so no error messages.
+ * returns are fatal
+ */
+/* INTPROTO */
+int
+rxvt_run_child(pR_ const char *const *argv)
+{
+    char           *login;
+
+    SET_TTYMODE(STDIN_FILENO, &(R->h->tio));   /* init terminal attributes */
+
+    if (R->Options & Opt_console) {    /* be virtual console, fail silently */
+#ifdef TIOCCONS
+       unsigned int    on = 1;
+
+       ioctl(STDIN_FILENO, TIOCCONS, &on);
+#elif defined (SRIOCSREDIR)
+       int             fd;
+
+       fd = open(CONSOLE, O_WRONLY, 0);
+       if (fd >= 0) {
+           if (ioctl(fd, SRIOCSREDIR, NULL) < 0)
+               close(fd);
+       }
+#endif                         /* SRIOCSREDIR */
+    }
+
+/* reset signals and spin off the command interpreter */
+    signal(SIGINT, SIG_DFL);
+    signal(SIGQUIT, SIG_DFL);
+    signal(SIGCHLD, SIG_DFL);
+/*
+ * mimick login's behavior by disabling the job control signals
+ * a shell that wants them can turn them back on
+ */
+#ifdef SIGTSTP
+    signal(SIGTSTP, SIG_IGN);
+    signal(SIGTTIN, SIG_IGN);
+    signal(SIGTTOU, SIG_IGN);
+#endif                         /* SIGTSTP */
+
+    /* set window size */
+    rxvt_tt_winsize(STDIN_FILENO, R->TermWin.ncol, R->TermWin.nrow, 0);
+
+#ifndef __QNX__
+/* command interpreter path */
+    if (argv != NULL) {
+# ifdef DEBUG_CMD
+       int             i;
+
+       for (i = 0; argv[i]; i++)
+           fprintf(stderr, "argv [%d] = \"%s\"\n", i, argv[i]);
+# endif
+       execvp(argv[0], (char *const *)argv);
+       /* no error message: STDERR is closed! */
+    } else {
+       const char     *argv0, *shell;
+
+       if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
+           shell = "/bin/sh";
+
+       argv0 = (const char *)rxvt_r_basename(shell);
+       if (R->Options & Opt_loginShell) {
+           login = (char *)rxvt_malloc((STRLEN(argv0) + 2) * sizeof(char));
+
+           login[0] = '-';
+           STRCPY(&login[1], argv0);
+           argv0 = login;
+       }
+       execlp(shell, argv0, NULL);
+       /* no error message: STDERR is closed! */
+    }
+#else                          /* __QNX__ uses qnxspawn() */
+    {
+       char            iov_a[10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+       char           *command = NULL, fullcommand[_MAX_PATH];
+       char          **arg_v, *arg_a[2] = { NULL, NULL };
+
+       if (argv != NULL) {
+           if (access(argv[0], X_OK) == -1) {
+               if (STRCHR(argv[0], '/') == NULL) {
+                   searchenv(argv[0], "PATH", fullcommand);
+                   if (fullcommand[0] != '\0')
+                       command = fullcommand;
+               }
+               if (access(command, X_OK) == -1)
+                   return -1;
+           } else
+               command = argv[0];
+           arg_v = argv;
+       } else {
+           if ((command = getenv("SHELL")) == NULL || *command == '\0')
+               command = "/bin/sh";
+
+           arg_a[0] = my_basename(command);
+           if (R->Options & Opt_loginShell) {
+               login = rxvt_malloc((STRLEN(arg_a[0]) + 2) * sizeof(char));
+
+               login[0] = '-';
+               STRCPY(&login[1], arg_a[0]);
+               arg_a[0] = login;
+           }
+           arg_v = arg_a;
+       }
+       iov_a[0] = iov_a[1] = iov_a[2] = R->tty_fd;
+       R->h->cmd_pid = qnx_spawn(0, 0, 0, -1, -1,
+                                 _SPAWN_SETSID | _SPAWN_TCSETPGRP,
+                                 command, arg_v, environ, iov_a, 0);
+       if (login)
+           free(login);
+       close(R->tty_fd);
+       return R->cmd_fd;
+    }
+#endif
+    return -1;
+}
+
+/* ------------------------------------------------------------------------- *
+ *                            GET TTY CURRENT STATE                          *
+ * ------------------------------------------------------------------------- */
+/* rxvt_get_ttymode() */
+/* INTPROTO */
+void
+rxvt_get_ttymode(ttymode_t *tio, int erase)
+{
+#ifdef HAVE_TERMIOS_H
+/*
+ * standard System V termios interface
+ */
+    if (GET_TERMIOS(STDIN_FILENO, tio) < 0) {
+       /* return error - use system defaults */
+       tio->c_cc[VINTR] = CINTR;
+       tio->c_cc[VQUIT] = CQUIT;
+       tio->c_cc[VERASE] = CERASE;
+       tio->c_cc[VKILL] = CKILL;
+       tio->c_cc[VSTART] = CSTART;
+       tio->c_cc[VSTOP] = CSTOP;
+       tio->c_cc[VSUSP] = CSUSP;
+# ifdef VDSUSP
+       tio->c_cc[VDSUSP] = CDSUSP;
+# endif
+# ifdef VREPRINT
+       tio->c_cc[VREPRINT] = CRPRNT;
+# endif
+# ifdef VDISCRD
+       tio->c_cc[VDISCRD] = CFLUSH;
+# endif
+# ifdef VWERSE
+       tio->c_cc[VWERSE] = CWERASE;
+# endif
+# ifdef VLNEXT
+       tio->c_cc[VLNEXT] = CLNEXT;
+# endif
+    }
+    tio->c_cc[VEOF] = CEOF;
+    tio->c_cc[VEOL] = VDISABLE;
+# ifdef VEOL2
+    tio->c_cc[VEOL2] = VDISABLE;
+# endif
+# ifdef VSWTC
+    tio->c_cc[VSWTC] = VDISABLE;
+# endif
+# ifdef VSWTCH
+    tio->c_cc[VSWTCH] = VDISABLE;
+# endif
+# if VMIN != VEOF
+    tio->c_cc[VMIN] = 1;
+# endif
+# if VTIME != VEOL
+    tio->c_cc[VTIME] = 0;
+# endif
+    if (erase != -1)
+       tio->c_cc[VERASE] = (char)erase;
+
+/* input modes */
+    tio->c_iflag = (BRKINT | IGNPAR | ICRNL
+# ifdef IMAXBEL
+                   | IMAXBEL
+# endif
+                   | IXON);
+
+/* output modes */
+    tio->c_oflag = (OPOST | ONLCR);
+
+/* control modes */
+    tio->c_cflag = (CS8 | CREAD);
+
+/* line discipline modes */
+    tio->c_lflag = (ISIG | ICANON | IEXTEN | ECHO
+# if defined (ECHOCTL) && defined (ECHOKE)
+                   | ECHOCTL | ECHOKE
+# endif
+                   | ECHOE | ECHOK);
+# else                         /* HAVE_TERMIOS_H */
+
+/*
+ * sgtty interface
+ */
+
+/* get parameters -- gtty */
+    if (ioctl(STDIN_FILENO, TIOCGETP, &(tio->sg)) < 0) {
+       tio->sg.sg_erase = CERASE;      /* ^H */
+       tio->sg.sg_kill = CKILL;        /* ^U */
+    }
+    if (erase != -1)
+       tio->sg.sg_erase = (char)erase;
+
+    tio->sg.sg_flags = (CRMOD | ECHO | EVENP | ODDP);
+
+/* get special characters */
+    if (ioctl(STDIN_FILENO, TIOCGETC, &(tio->tc)) < 0) {
+       tio->tc.t_intrc = CINTR;        /* ^C */
+       tio->tc.t_quitc = CQUIT;        /* ^\ */
+       tio->tc.t_startc = CSTART;      /* ^Q */
+       tio->tc.t_stopc = CSTOP;        /* ^S */
+       tio->tc.t_eofc = CEOF;  /* ^D */
+       tio->tc.t_brkc = -1;
+    }
+/* get local special chars */
+    if (ioctl(STDIN_FILENO, TIOCGLTC, &(tio->lc)) < 0) {
+       tio->lc.t_suspc = CSUSP;        /* ^Z */
+       tio->lc.t_dsuspc = CDSUSP;      /* ^Y */
+       tio->lc.t_rprntc = CRPRNT;      /* ^R */
+       tio->lc.t_flushc = CFLUSH;      /* ^O */
+       tio->lc.t_werasc = CWERASE;     /* ^W */
+       tio->lc.t_lnextc = CLNEXT;      /* ^V */
+    }
+/* get line discipline */
+    ioctl(STDIN_FILENO, TIOCGETD, &(tio->line));
+# ifdef NTTYDISC
+    tio->line = NTTYDISC;
+# endif                                /* NTTYDISC */
+    tio->local = (LCRTBS | LCRTERA | LCTLECH | LPASS8 | LCRTKIL);
+#endif                         /* HAVE_TERMIOS_H */
+
+/*
+ * Debugging
+ */
+#ifdef DEBUG_TTYMODE
+#ifdef HAVE_TERMIOS_H
+/* c_iflag bits */
+    fprintf(stderr, "Input flags\n");
+
+/* cpp token stringize doesn't work on all machines <sigh> */
+# define FOO(flag,name)                        \
+    if ((tio->c_iflag) & flag)         \
+       fprintf (stderr, "%s ", name)
+
+/* c_iflag bits */
+    FOO(IGNBRK, "IGNBRK");
+    FOO(BRKINT, "BRKINT");
+    FOO(IGNPAR, "IGNPAR");
+    FOO(PARMRK, "PARMRK");
+    FOO(INPCK, "INPCK");
+    FOO(ISTRIP, "ISTRIP");
+    FOO(INLCR, "INLCR");
+    FOO(IGNCR, "IGNCR");
+    FOO(ICRNL, "ICRNL");
+    FOO(IXON, "IXON");
+    FOO(IXOFF, "IXOFF");
+# ifdef IUCLC
+    FOO(IUCLC, "IUCLC");
+# endif
+# ifdef IXANY
+    FOO(IXANY, "IXANY");
+# endif
+# ifdef IMAXBEL
+    FOO(IMAXBEL, "IMAXBEL");
+# endif
+    fprintf(stderr, "\n");
+
+# undef FOO
+# define FOO(entry, name)                                      \
+    fprintf(stderr, "%-8s = %#04o\n", name, tio->c_cc [entry])
+
+    FOO(VINTR, "VINTR");
+    FOO(VQUIT, "VQUIT");
+    FOO(VERASE, "VERASE");
+    FOO(VKILL, "VKILL");
+    FOO(VEOF, "VEOF");
+    FOO(VEOL, "VEOL");
+# ifdef VEOL2
+    FOO(VEOL2, "VEOL2");
+# endif
+# ifdef VSWTC
+    FOO(VSWTC, "VSWTC");
+# endif
+# ifdef VSWTCH
+    FOO(VSWTCH, "VSWTCH");
+# endif
+    FOO(VSTART, "VSTART");
+    FOO(VSTOP, "VSTOP");
+    FOO(VSUSP, "VSUSP");
+# ifdef VDSUSP
+    FOO(VDSUSP, "VDSUSP");
+# endif
+# ifdef VREPRINT
+    FOO(VREPRINT, "VREPRINT");
+# endif
+# ifdef VDISCRD
+    FOO(VDISCRD, "VDISCRD");
+# endif
+# ifdef VWERSE
+    FOO(VWERSE, "VWERSE");
+# endif
+# ifdef VLNEXT
+    FOO(VLNEXT, "VLNEXT");
+# endif
+    fprintf(stderr, "\n");
+# undef FOO
+# endif                                /* HAVE_TERMIOS_H */
+#endif                         /* DEBUG_TTYMODE */
+}
+
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/init.h b/src/init.h
new file mode 100644 (file)
index 0000000..6c3e578
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * $Id: init.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#ifndef _INIT_H_
+#define _INIT_H_
+
+#undef CERASE /* TODO */
+#define CERASE '\010'  /* ^H */
+
+#ifdef HAVE_XSETLOCALE
+# define X_LOCALE
+# include <X11/Xlocale.h>
+#else
+# ifdef HAVE_SETLOCALE
+#  include <locale.h>
+# endif
+#endif                         /* HAVE_XLOCALE */
+
+#if defined(PTYS_ARE_PTMX) && !defined(__CYGWIN32__)
+# include <sys/resource.h>     /* for struct rlimit */
+# define _NEW_TTY_CTRL         /* to get proper defines in <termios.h> */
+#endif
+
+#ifdef __QNX__                 /* autoconf someday */
+# include <process.h>
+#endif
+
+#ifdef TTY_GID_SUPPORT
+# include <grp.h>
+#endif
+
+/* ways to deal with getting/setting termios structure */
+
+#ifdef HAVE_TERMIOS_H
+/* termios interface */
+# ifdef TCSANOW                        /* POSIX */
+#  define GET_TERMIOS(fd,tios) tcgetattr (fd, tios)
+#  define SET_TERMIOS(fd,tios)         \
+       cfsetospeed (tios, BAUDRATE),   \
+       cfsetispeed (tios, BAUDRATE),   \
+       tcsetattr (fd, TCSANOW, tios)
+# else
+#  ifdef TIOCSETA
+#   define GET_TERMIOS(fd,tios)        ioctl (fd, TIOCGETA, tios)
+#   define SET_TERMIOS(fd,tios)                \
+       tios->c_cflag |= BAUDRATE,      \
+       ioctl (fd, TIOCSETA, tios)
+#  else
+#   define GET_TERMIOS(fd,tios)        ioctl (fd, TCGETS, tios)
+#   define SET_TERMIOS(fd,tios)                \
+       tios->c_cflag |= BAUDRATE,      \
+       ioctl (fd, TCSETS, tios)
+#  endif
+# endif
+# define SET_TTYMODE(fd,tios)          SET_TERMIOS (fd, tios)
+#else
+/* sgtty interface */
+
+# define SET_TTYMODE(fd,tt)                            \
+       tt->sg.sg_ispeed = tt->sg.sg_ospeed = BAUDRATE, \
+       ioctl (fd, TIOCSETP, &(tt->sg)),                \
+       ioctl (fd, TIOCSETC, &(tt->tc)),                \
+       ioctl (fd, TIOCSLTC, &(tt->lc)),                \
+       ioctl (fd, TIOCSETD, &(tt->line)),              \
+       ioctl (fd, TIOCLSET, &(tt->local))
+#endif                         /* HAVE_TERMIOS_H */
+
+/* use the fastest baud-rate */
+#ifdef B38400
+# define BAUDRATE      B38400
+#else
+# ifdef B19200
+#  define BAUDRATE     B19200
+# else
+#  define BAUDRATE     B9600
+# endif
+#endif
+
+/* Disable special character functions */
+#ifdef _POSIX_VDISABLE
+# define VDISABLE      _POSIX_VDISABLE
+#else
+# define VDISABLE      255
+#endif
+
+/*----------------------------------------------------------------------*
+ * system default characters if defined and reasonable
+ */
+#ifndef CINTR
+# define CINTR         '\003'  /* ^C */
+#endif
+#ifndef CQUIT
+# define CQUIT         '\034'  /* ^\ */
+#endif
+#ifndef CERASE
+# ifdef linux
+#  define CERASE       '\177'  /* ^? */
+# else
+#  define CERASE       '\010'  /* ^H */
+# endif
+#endif
+#ifndef CKILL
+# define CKILL         '\025'  /* ^U */
+#endif
+#ifndef CEOF
+# define CEOF          '\004'  /* ^D */
+#endif
+#ifndef CSTART
+# define CSTART                '\021'  /* ^Q */
+#endif
+#ifndef CSTOP
+# define CSTOP         '\023'  /* ^S */
+#endif
+#ifndef CSUSP
+# define CSUSP         '\032'  /* ^Z */
+#endif
+#ifndef CDSUSP
+# define CDSUSP                '\031'  /* ^Y */
+#endif
+#ifndef CRPRNT
+# define CRPRNT                '\022'  /* ^R */
+#endif
+#ifndef CFLUSH
+# define CFLUSH                '\017'  /* ^O */
+#endif
+#ifndef CWERASE
+# define CWERASE       '\027'  /* ^W */
+#endif
+#ifndef CLNEXT
+# define CLNEXT                '\026'  /* ^V */
+#endif
+
+#ifndef VDISCRD
+# ifdef VDISCARD
+#  define VDISCRD      VDISCARD
+# endif
+#endif
+
+#ifndef VWERSE
+# ifdef VWERASE
+#  define VWERSE       VWERASE
+# endif
+#endif
+
+#ifndef O_NOCTTY
+# define O_NOCTTY      0
+#endif
+#ifndef O_NDELAY
+# define O_NDELAY      O_NONBLOCK      /* QNX, at least */
+#endif
+#ifndef ONLCR
+# define ONLCR         0               /* QNX, at least */
+#endif
+
+#define CONSOLE                "/dev/console"  /* console device */
+
+#include "init.intpro" /* PROTOS for internal routines */
+#endif /* _INIT_H_ */
diff --git a/src/logging.C b/src/logging.C
new file mode 100644 (file)
index 0000000..226f47d
--- /dev/null
@@ -0,0 +1,430 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       logging.c
+ *----------------------------------------------------------------------*
+ * $Id: logging.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1992      John Bovey <jdb@ukc.ac.uk>
+ *                             - original version
+ * Copyright (c) 1993      lipka
+ * Copyright (c) 1993      Brian Stempien <stempien@cs.wmich.edu>
+ * Copyright (c) 1995      Raul Garcia Garcia <rgg@tid.es>
+ * Copyright (c) 1995      Piet W. Plomp <piet@idefix.icce.rug.nl>
+ * Copyright (c) 1997      Raul Garcia Garcia <rgg@tid.es>
+ * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
+ *                             - extensive modifications
+ * Copyright (c) 1999      D J Hawkey Jr <hawkeyd@visi.com>
+ *                             - lastlog support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*
+ * Public:
+ *     extern void cleanutent (void);
+ *     extern void makeutent (const char * pty, const char * hostname);
+ *
+ * Private:
+ *     rxvt_update_wtmp ();
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "logging.h"
+#ifdef UTMP_SUPPORT
+
+/*
+ * BSD style utmp entry
+ *      ut_line, ut_name, ut_host, ut_time
+ * SYSV style utmp (and utmpx) entry
+ *      ut_user, ut_id, ut_line, ut_pid, ut_type, ut_exit, ut_time
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * make and write utmp and wtmp entries
+ */
+/* EXTPROTO */
+void
+rxvt_makeutent(pR_ const char *pty, const char *hostname)
+{
+#ifdef HAVE_STRUCT_UTMP
+    struct utmp    *ut = &(R->h->ut);
+#endif
+#ifdef HAVE_STRUCT_UTMPX
+    struct utmpx   *utx = &(R->h->utx);
+#endif
+#ifdef HAVE_UTMP_PID
+    int             i;
+#endif
+    char            ut_id[5];
+    struct passwd  *pwent = getpwuid(getuid());
+
+    if (!STRNCMP(pty, "/dev/", 5))
+       pty += 5;               /* skip /dev/ prefix */
+
+    if (!STRNCMP(pty, "pty", 3) || !STRNCMP(pty, "tty", 3)) {
+       STRNCPY(ut_id, (pty + 3), sizeof(ut_id));
+    }
+#ifdef HAVE_UTMP_PID
+    else if (sscanf(pty, "pts/%d", &i) == 1)
+       sprintf(ut_id, "vt%02x", (i & 0xff));   /* sysv naming */
+#endif
+    else if (STRNCMP(pty, "pty", 3) && STRNCMP(pty, "tty", 3)) {
+       rxvt_print_error("can't parse tty name \"%s\"", pty);
+       return;
+    }
+
+#ifdef HAVE_STRUCT_UTMP
+    MEMSET(ut, 0, sizeof(struct utmp));
+# ifdef HAVE_UTMP_PID
+    setutent();
+    STRNCPY(ut->ut_id, ut_id, sizeof(ut->ut_id));
+    ut->ut_type = DEAD_PROCESS;
+    getutid(ut);               /* position to entry in utmp file */
+    STRNCPY(R->h->ut_id, ut_id, sizeof(R->h->ut_id));
+# endif
+#endif
+
+#ifdef HAVE_STRUCT_UTMPX
+    MEMSET(utx, 0, sizeof(struct utmpx));
+    setutxent();
+    STRNCPY(utx->ut_id, ut_id, sizeof(utx->ut_id));
+    utx->ut_type = DEAD_PROCESS;
+    getutxid(utx);             /* position to entry in utmp file */
+    STRNCPY(R->h->ut_id, ut_id, sizeof(R->h->ut_id));
+#endif
+
+#ifdef HAVE_STRUCT_UTMP
+    STRNCPY(ut->ut_line, pty, sizeof(ut->ut_line));
+    ut->ut_time = time(NULL);
+# ifdef HAVE_UTMP_PID
+    STRNCPY(ut->ut_user, (pwent && pwent->pw_name) ? pwent->pw_name : "?",
+           sizeof(ut->ut_user));
+    STRNCPY(ut->ut_id, ut_id, sizeof(ut->ut_id));
+    ut->ut_time = time(NULL);
+    ut->ut_pid = R->h->cmd_pid;
+#  ifdef HAVE_UTMP_HOST
+    STRNCPY(ut->ut_host, hostname, sizeof(ut->ut_host));
+#  endif
+    ut->ut_type = USER_PROCESS;
+    pututline(ut);
+    endutent();                        /* close the file */
+    R->h->utmp_pos = 0;
+# else
+    STRNCPY(ut->ut_name, (pwent && pwent->pw_name) ? pwent->pw_name : "?",
+           sizeof(ut->ut_name));
+#  ifdef HAVE_UTMP_HOST
+    STRNCPY(ut->ut_host, hostname, sizeof(ut->ut_host));
+#  endif
+# endif
+#endif
+
+#ifdef HAVE_STRUCT_UTMPX
+    STRNCPY(utx->ut_line, pty, sizeof(utx->ut_line));
+    STRNCPY(utx->ut_user, (pwent && pwent->pw_name) ? pwent->pw_name : "?",
+           sizeof(utx->ut_user));
+    STRNCPY(utx->ut_id, ut_id, sizeof(utx->ut_id));
+    utx->ut_session = getsid(0);
+    utx->ut_tv.tv_sec = time(NULL);
+    utx->ut_tv.tv_usec = 0;
+    utx->ut_pid = R->h->cmd_pid;
+# ifdef HAVE_UTMPX_HOST
+    STRNCPY(utx->ut_host, hostname, sizeof(utx->ut_host));
+#  if 0
+    {
+       char           *colon;
+
+       if ((colon = STRRCHR(ut->ut_host, ':')) != NULL)
+           *colon = '\0';
+    }
+#  endif
+# endif
+    utx->ut_type = USER_PROCESS;
+    pututxline(utx);
+    endutxent();               /* close the file */
+    R->h->utmp_pos = 0;
+#endif
+
+#if defined(HAVE_STRUCT_UTMP) && !defined(HAVE_UTMP_PID)
+    {
+       int             i;
+# ifdef HAVE_TTYSLOT
+       i = ttyslot();
+       if (rxvt_write_bsd_utmp(i, ut))
+           R->h->utmp_pos = i;
+# else
+       FILE           *fd0;
+
+       if ((fd0 = fopen(TTYTAB_FILENAME, "r")) != NULL) {
+           char            buf[256], name[256];
+
+           buf[sizeof(buf) - 1] = '\0';
+           for (i = 1; (fgets(buf, sizeof(buf) - 1, fd0) != NULL);) {
+               if (*buf == '#' || sscanf(buf, "%s", name) != 1)
+                   continue;
+               if (!STRCMP(ut->ut_line, name)) {
+                   if (!rxvt_write_bsd_utmp(i, ut))
+                       i = 0;
+                   R->h->utmp_pos = i;
+                   fclose(fd0);
+                   break;
+               }
+               i++;
+           }
+           fclose(fd0);
+       }
+# endif
+    }
+#endif
+
+#ifdef WTMP_SUPPORT
+# ifdef WTMP_ONLY_ON_LOGIN
+    if (R->Options & Opt_loginShell)
+# endif
+    {
+# ifdef HAVE_STRUCT_UTMP
+#  ifdef HAVE_UPDWTMP
+       updwtmp(RXVT_WTMP_FILE, ut);
+#  else
+       rxvt_update_wtmp(RXVT_WTMP_FILE, ut);
+#  endif
+# endif
+# ifdef HAVE_STRUCT_UTMPX
+       updwtmpx(RXVT_WTMPX_FILE, utx);
+# endif
+    }
+#endif
+#if defined(LASTLOG_SUPPORT) && defined(RXVT_LASTLOG_FILE)
+    if (R->Options & Opt_loginShell)
+       rxvt_update_lastlog(RXVT_LASTLOG_FILE, pty, hostname);
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * remove utmp and wtmp entries
+ */
+/* EXTPROTO */
+void
+rxvt_cleanutent(pR)
+{
+#ifdef HAVE_STRUCT_UTMP
+    struct utmp    *ut = &(R->h->ut);
+#endif
+#ifdef HAVE_STRUCT_UTMPX
+    struct utmpx   *tmputx, *utx = &(R->h->utx);
+#endif
+
+#ifdef HAVE_STRUCT_UTMP
+# ifdef HAVE_UTMP_PID
+    MEMSET(ut, 0, sizeof(struct utmp));
+    setutent();
+    STRNCPY(ut->ut_id, R->h->ut_id, sizeof(ut->ut_id));
+    ut->ut_type = USER_PROCESS;
+    {
+       struct utmp    *tmput = getutid(ut);
+
+       if (tmput)              /* position to entry in utmp file */
+           ut = tmput;
+    }
+    ut->ut_type = DEAD_PROCESS;
+# else 
+    MEMSET(ut->ut_name, 0, sizeof(ut->ut_name));
+#  ifdef HAVE_UTMP_HOST
+    MEMSET(ut->ut_host, 0, sizeof(ut->ut_host));
+#  endif
+# endif
+    ut->ut_time = time(NULL);
+#endif
+
+#ifdef HAVE_STRUCT_UTMPX
+    MEMSET(utx, 0, sizeof(struct utmpx));
+    setutxent();
+    STRNCPY(utx->ut_id, R->h->ut_id, sizeof(utx->ut_id));
+    utx->ut_type = USER_PROCESS;
+    if ((tmputx = getutxid(utx)))      /* position to entry in utmp file */
+       utx = tmputx;
+    utx->ut_type = DEAD_PROCESS;
+    utx->ut_session = getsid(0);
+    utx->ut_tv.tv_sec = time(NULL);
+    utx->ut_tv.tv_usec = 0;
+#endif
+
+    /*
+     * Write ending wtmp entry
+     */
+#ifdef WTMP_SUPPORT
+# ifdef WTMP_ONLY_ON_LOGIN
+    if (R->Options & Opt_loginShell)
+# endif
+    {
+# ifdef HAVE_STRUCT_UTMP
+#  ifdef HAVE_UPDWTMP
+       updwtmp(RXVT_WTMP_FILE, ut);
+#  else
+       rxvt_update_wtmp(RXVT_WTMP_FILE, ut);
+#  endif
+# endif
+# ifdef HAVE_STRUCT_UTMPX
+       updwtmpx(RXVT_WTMPX_FILE, utx);
+# endif
+    }
+#endif
+
+    /*
+     * Write utmp entry
+     */
+#ifdef HAVE_STRUCT_UTMP
+# ifdef HAVE_UTMP_PID
+    if (ut->ut_pid == R->h->cmd_pid)
+       pututline(ut);
+    endutent();
+# else
+    MEMSET(ut, 0, sizeof(struct utmp));
+    rxvt_write_bsd_utmp(R->h->utmp_pos, ut);
+# endif
+#endif
+#ifdef HAVE_STRUCT_UTMPX
+    if (utx->ut_pid == R->h->cmd_pid)
+       pututxline(utx);
+    endutxent();
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Write a BSD style utmp entry
+ */
+#ifdef HAVE_UTMP_H
+/* INTPROTO */
+int
+rxvt_write_bsd_utmp(int utmp_pos, struct utmp *wu)
+{
+    int             fd;
+
+    if (utmp_pos <= 0 || (fd = open(RXVT_UTMP_FILE, O_WRONLY)) == -1)
+       return 0;
+
+    if (lseek(fd, (off_t) (utmp_pos * sizeof(struct utmp)), SEEK_SET) != -1)
+       write(fd, wu, sizeof(struct utmp));
+    close(fd);
+    return 1;
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Update a BSD style wtmp entry
+ */
+#if defined(WTMP_SUPPORT) && !defined(HAVE_UPDWTMP)
+/* INTPROTO */
+void
+rxvt_update_wtmp(const char *fname, const struct utmp *putmp)
+{
+    int             fd, gotlock, retry;
+    struct flock    lck;       /* fcntl locking scheme */
+    struct stat     sbuf;
+
+    if ((fd = open(fname, O_WRONLY | O_APPEND, 0)) < 0)
+       return;
+
+    lck.l_whence = SEEK_END;   /* start lock at current eof */
+    lck.l_len = 0;             /* end at ``largest possible eof'' */
+    lck.l_start = 0;
+    lck.l_type = F_WRLCK;      /* we want a write lock */
+
+    /* attempt lock with F_SETLK; F_SETLKW would cause a deadlock! */
+    for (retry = 10, gotlock = 0; retry--;)
+       if (fcntl(fd, F_SETLK, &lck) != -1) {
+           gotlock = 1;
+           break;
+       } else if (errno != EAGAIN && errno != EACCES)
+           break;
+    if (!gotlock) {            /* give it up */
+       close(fd);
+       return;
+    }
+    if (fstat(fd, &sbuf) == 0)
+       if (write(fd, putmp, sizeof(struct utmp)) != sizeof(struct utmp))
+           ftruncate(fd, sbuf.st_size);        /* remove bad writes */
+
+    lck.l_type = F_UNLCK;      /* unlocking the file */
+    fcntl(fd, F_SETLK, &lck);
+    close(fd);
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+#ifdef LASTLOG_SUPPORT
+/* INTPROTO */
+void
+rxvt_update_lastlog(const char *fname, const char *pty, const char *host)
+{
+# ifdef HAVE_STRUCT_LASTLOGX
+    struct lastlogx llx;
+# endif
+# ifdef HAVE_STRUCT_LASTLOG
+    int             fd;
+    struct lastlog  ll;
+#  ifdef LASTLOG_IS_DIR
+    char            lastlogfile[256];
+#  endif
+    struct passwd  *pwent;
+# endif
+
+# ifdef HAVE_STRUCT_LASTLOGX
+    MEMSET(&llx, 0, sizeof(llx));
+    llx.ll_tv.tv_sec = time(NULL);
+    llx.ll_tv.tv_usec = 0;
+    STRNCPY(llx.ll_line, pty, sizeof(llx.ll_line));
+    STRNCPY(llx.ll_host, host, sizeof(llx.ll_host));
+    updlastlogx(RXVT_LASTLOGX_FILE, getuid(), &llx);
+# endif
+
+# ifdef HAVE_STRUCT_LASTLOG
+    pwent = getpwuid(getuid());
+    if (!pwent) {
+       rxvt_print_error("no entry in password file");
+       return;
+    }
+    MEMSET(&ll, 0, sizeof(ll));
+    ll.ll_time = time(NULL);
+    STRNCPY(ll.ll_line, pty, sizeof(ll.ll_line));
+    STRNCPY(ll.ll_host, host, sizeof(ll.ll_host));
+#  ifdef LASTLOG_IS_DIR
+    sprintf(lastlogfile, "%.*s/%.*s",
+           sizeof(lastlogfile) - sizeof(pwent->pw_name) - 2, fname,
+           sizeof(pwent->pw_name),
+           (!pwent->pw_name || pwent->pw_name[0] == '\0') ? "unknown"
+                                                          : pwent->pw_name);
+    if ((fd = open(lastlogfile, O_WRONLY | O_CREAT, 0644)) >= 0) {
+       write(fd, &ll, sizeof(ll));
+       close(fd);
+    }
+#  else
+    if ((fd = open(fname, O_RDWR)) != -1) {
+       if (lseek(fd, (off_t) ((long)pwent->pw_uid * sizeof(ll)),
+                 SEEK_SET) != -1)
+           write(fd, &ll, sizeof(ll));
+       close(fd);
+    }
+#  endif                       /* LASTLOG_IS_DIR */
+# endif                                /* HAVE_STRUCT_LASTLOG */
+}
+#endif                         /* LASTLOG_SUPPORT */
+/* ------------------------------------------------------------------------- */
+
+#endif                         /* UTMP_SUPPORT */
diff --git a/src/logging.h b/src/logging.h
new file mode 100644 (file)
index 0000000..0d40847
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * $Id: logging.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#ifndef _LOGGING_H_
+#define _LOGGING_H_
+
+#ifdef UTMP_SUPPORT
+# if ! defined(HAVE_STRUCT_UTMPX) && ! defined(HAVE_STRUCT_UTMP)
+#  error cannot build with utmp support - no utmp or utmpx struct found
+# endif
+
+# ifdef HAVE_LASTLOG_H
+#  include <lastlog.h>
+# endif
+# include <pwd.h>
+
+# ifdef RXVT_UTMP_SYSV
+#  ifndef USER_PROCESS
+#   define USER_PROCESS                7
+#  endif
+#  ifndef DEAD_PROCESS
+#   define DEAD_PROCESS                8
+#  endif
+# endif
+
+# ifdef __QNX__
+#  include <sys/utsname.h>
+#  define ut_name              ut_user
+# endif
+
+#include "logging.intpro"              /* PROTOS for internal routines */
+#endif
+#endif /* _LOGGING_H_ */
diff --git a/src/main.C b/src/main.C
new file mode 100644 (file)
index 0000000..b2830e6
--- /dev/null
@@ -0,0 +1,1207 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       main.c
+ *----------------------------------------------------------------------*
+ * $Id: main.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1992      John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
+ *                             - original version
+ * Copyright (c) 1994      Robert Nation <nation@rocket.sanders.lockheed.com>
+ *                             - extensive modifications
+ * Copyright (c) 1995      Garrett D'Amore <garrett@netcom.com>
+ * Copyright (c) 1997      mj olesen <olesen@me.QueensU.CA>
+ *                             - extensive modifications
+ * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
+ * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
+ *                             - extensive modifications
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *---------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "main.intpro"         /* PROTOS for internal routines */
+
+#include <signal.h>
+
+#ifdef TTY_GID_SUPPORT
+# include <grp.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* rxvt_init() */
+/* LIBPROTO */
+rxvt_t         *
+rxvt_init(int argc, const char *const *argv)
+{
+    const char    **cmd_argv;
+
+    SET_R ((rxvt_t *)rxvt_calloc(1, sizeof(rxvt_t)));
+
+    dR;
+    if (rxvt_init_vars(aR) < 0) {
+       free(R);
+       return NULL;
+    }
+
+/*
+ * Save and then give up any super-user privileges
+ * If we need privileges in any area then we must specifically request it.
+ * We should only need to be root in these cases:
+ *  1.  write utmp entries on some systems
+ *  2.  chown tty on some systems
+ */
+    rxvt_privileges(aR_ SAVE);
+    rxvt_privileges(aR_ IGNORE);
+
+    rxvt_init_secondary(aR);
+
+    cmd_argv = rxvt_init_resources(aR_ argc, argv);
+
+#if (MENUBAR_MAX)
+    rxvt_menubar_read(aR_ R->h->rs[Rs_menu]);
+#endif
+#ifdef HAVE_SCROLLBARS
+    if (R->Options & Opt_scrollBar)
+      scrollbar_setIdle();     /* set existence for size calculations */
+#endif
+
+    rxvt_Create_Windows(aR_ argc, argv);
+
+    rxvt_init_xlocale(aR);
+
+    rxvt_scr_reset(aR);                /* initialize screen */
+#ifdef RXVT_GRAPHICS
+    rxvt_Gr_reset(aR);         /* reset graphics */
+#endif
+
+#if 0
+#ifdef DEBUG_X
+    XSynchronize(R->Xdisplay, True);
+    XSetErrorHandler((XErrorHandler) abort);
+#else
+    XSetErrorHandler((XErrorHandler) rxvt_xerror_handler);
+#endif
+#endif
+
+#ifdef HAVE_SCROLLBARS
+    if (R->Options & Opt_scrollBar)
+       rxvt_Resize_scrollBar(aR);      /* create and map scrollbar */
+#endif
+#if (MENUBAR_MAX)
+    if (menubar_visible(r))
+       XMapWindow(R->Xdisplay, R->menuBar.win);
+#endif
+#ifdef TRANSPARENT
+    if (R->Options & Opt_transparent) {
+       XSelectInput(R->Xdisplay, Xroot, PropertyChangeMask);
+       rxvt_check_our_parents(aR);
+    }
+#endif
+    XMapWindow(R->Xdisplay, R->TermWin.vt);
+    XMapWindow(R->Xdisplay, R->TermWin.parent[0]);
+
+    rxvt_init_env(aR);
+    rxvt_init_command(aR_ cmd_argv);
+
+    return R;
+}
+
+/* ------------------------------------------------------------------------- *
+ *                       SIGNAL HANDLING & EXIT HANDLER                      *
+ * ------------------------------------------------------------------------- */
+/*
+ * Catch a SIGCHLD signal and exit if the direct child has died
+ */
+/* ARGSUSED */
+/* EXTPROTO */
+RETSIGTYPE
+rxvt_Child_signal(int sig __attribute__((unused)))
+{
+    dR;
+    int             pid, save_errno = errno;
+
+    do {
+       errno = 0;
+    } while ((pid = waitpid(-1, NULL, WNOHANG)) == -1 && errno == EINTR);
+
+    if (pid == R->h->cmd_pid)
+       exit(EXIT_SUCCESS);
+
+    errno = save_errno;
+    signal(SIGCHLD, rxvt_Child_signal);
+}
+
+/*
+ * Catch a fatal signal and tidy up before quitting
+ */
+/* EXTPROTO */
+RETSIGTYPE
+rxvt_Exit_signal(int sig)
+{
+    signal(sig, SIG_DFL);
+#ifdef DEBUG_CMD
+    rxvt_print_error("signal %d", sig);
+#endif
+    rxvt_clean_exit();
+    kill(getpid(), sig);
+}
+
+/* ARGSUSED */
+/* INTPROTO */
+int
+rxvt_xerror_handler(const Display *display __attribute__((unused)), const XErrorEvent *event)
+{
+    dR;
+
+    if (R->h->allowedxerror == -1) {
+       R->h->allowedxerror = event->error_code;
+       return 0;               /* ignored anyway */
+    }
+    rxvt_print_error("XError: Request: %d . %d, Error: %d",
+                    event->request_code, event->minor_code,
+                    event->error_code);
+    /* XXX: probably should call rxvt_clean_exit() bypassing X routines */
+    exit(EXIT_FAILURE);
+    /* NOTREACHED */
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * Exit gracefully, clearing the utmp entry and restoring tty attributes
+ * TODO: if debugging, this should free up any known resources if we can
+ */
+/* EXTPROTO */
+void
+rxvt_clean_exit(void)
+{
+    dR;
+
+#ifdef DEBUG_SCREEN
+    rxvt_scr_release(aR);
+#endif
+#ifndef NO_SETOWNER_TTYDEV
+    rxvt_privileged_ttydev(aR_ RESTORE);
+#endif
+#ifdef UTMP_SUPPORT
+    rxvt_privileged_utmp(aR_ RESTORE);
+#endif
+#ifdef USE_XIM
+    if (R->h->Input_Context != NULL) {
+       XDestroyIC(R->h->Input_Context);
+       R->h->Input_Context = NULL;
+    }
+#endif
+}
+
+/* ------------------------------------------------------------------------- *
+ *                         MEMORY ALLOCATION WRAPPERS                        *
+ * ------------------------------------------------------------------------- */
+/* EXTPROTO */
+void           *
+rxvt_malloc(size_t size)
+{
+     void           *p;
+
+     p = malloc(size);
+     if (p)
+       return p;
+
+     fprintf(stderr, APL_NAME ": memory allocation failure.  Aborting");
+     rxvt_clean_exit();
+     exit(EXIT_FAILURE);
+     /* NOTREACHED */
+}
+
+/* EXTPROTO */
+void           *
+rxvt_calloc(size_t number, size_t size)
+{
+     void           *p;
+
+     p = calloc(number, size);
+     if (p)
+       return p;
+
+     fprintf(stderr, APL_NAME ": memory allocation failure.  Aborting");
+     rxvt_clean_exit();
+     exit(EXIT_FAILURE);
+     /* NOTREACHED */
+}
+
+/* EXTPROTO */
+void           *
+rxvt_realloc(void *ptr, size_t size)
+{
+     void           *p;
+
+     if (ptr)
+       p = realloc(ptr, size);
+     else
+       p = malloc(size);
+     if (p)
+       return p;
+
+     fprintf(stderr, APL_NAME ": memory allocation failure.  Aborting");
+     rxvt_clean_exit();
+     exit(EXIT_FAILURE);
+     /* NOTREACHED */
+}
+/* ------------------------------------------------------------------------- *
+ *                            PRIVILEGED OPERATIONS                          *
+ * ------------------------------------------------------------------------- */
+/* take care of suid/sgid super-user (root) privileges */
+/* INTPROTO */
+void
+rxvt_privileges(pR_ int mode)
+{
+#if ! defined(__CYGWIN32__)
+# if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
+/* setreuid() is the poor man's setuid(), seteuid() */
+#  define seteuid(a)   setreuid(-1, (a))
+#  define setegid(a)   setregid(-1, (a))
+#  define HAVE_SETEUID
+# endif
+# ifdef HAVE_SETEUID
+    switch (mode) {
+    case IGNORE:
+       /*
+        * change effective uid/gid - not real uid/gid - so we can switch
+        * back to root later, as required
+        */
+       seteuid(getuid());
+       setegid(getgid());
+       break;
+    case SAVE:
+       R->h->euid = geteuid();
+       R->h->egid = getegid();
+       break;
+    case RESTORE:
+       seteuid(R->h->euid);
+       setegid(R->h->egid);
+       break;
+    }
+# else
+    switch (mode) {
+    case IGNORE:
+       setuid(getuid());
+       setgid(getgid());
+    /* FALLTHROUGH */
+    case SAVE:
+    /* FALLTHROUGH */
+    case RESTORE:
+       break;
+    }
+# endif
+#endif
+}
+
+#ifdef UTMP_SUPPORT
+/* EXTPROTO */
+void
+rxvt_privileged_utmp(pR_ char action)
+{
+    struct rxvt_hidden *h = R->h;
+
+    D_MAIN((stderr, "rxvt_privileged_utmp(%c); waiting for: %c (pid: %d)", action, h->next_utmp_action, getpid()));
+    if (h->next_utmp_action != action
+       || (action != SAVE && action != RESTORE)
+       || (R->Options & Opt_utmpInhibit)
+       || h->ttydev == NULL
+       || *h->ttydev == '\0')
+       return;
+
+    rxvt_privileges(aR_ RESTORE);
+    if (action == SAVE) {
+       h->next_utmp_action = RESTORE;
+       rxvt_makeutent(aR_ h->ttydev, h->rs[Rs_display_name]);
+    } else {           /* action == RESTORE */
+       h->next_utmp_action = IGNORE;
+       rxvt_cleanutent(aR);
+    }
+    rxvt_privileges(aR_ IGNORE);
+}
+#endif
+
+#ifndef NO_SETOWNER_TTYDEV
+/* EXTPROTO */
+void
+rxvt_privileged_ttydev(pR_ char action)
+{
+    struct rxvt_hidden *h = R->h;
+
+    D_MAIN((stderr, "rxvt_privileged_ttydev(aR_ %c); waiting for: %c (pid: %d)", action, h->next_tty_action, getpid()));
+    if (h->next_tty_action != action
+       || (action != SAVE && action != RESTORE)
+       || h->ttydev == NULL
+       || *h->ttydev == '\0')
+       return;
+
+    rxvt_privileges(aR_ RESTORE);
+
+    if (action == SAVE) {
+       h->next_tty_action = RESTORE;
+# ifndef RESET_TTY_TO_COMMON_DEFAULTS
+/* store original tty status for restoration rxvt_clean_exit() -- rgg 04/12/95 */
+       if (lstat(h->ttydev, &h->ttyfd_stat) < 0)       /* you lose out */
+           h->next_tty_action = IGNORE;
+       else
+# endif
+       {
+           chown(h->ttydev, getuid(), h->ttygid); /* fail silently */
+           chmod(h->ttydev, h->ttymode);
+# ifdef HAVE_REVOKE
+           revoke(h->ttydev);
+# endif
+       }
+    } else {                   /* action == RESTORE */
+       h->next_tty_action = IGNORE;
+# ifndef RESET_TTY_TO_COMMON_DEFAULTS
+       chmod(h->ttydev, h->ttyfd_stat.st_mode);
+       chown(h->ttydev, h->ttyfd_stat.st_uid, h->ttyfd_stat.st_gid);
+# else
+       chmod(h->ttydev,
+             (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH));
+       chown(h->ttydev, 0, 0);
+# endif
+    }
+
+    rxvt_privileges(aR_ IGNORE);
+
+# ifndef RESET_TTY_TO_COMMON_DEFAULTS
+    D_MAIN((stderr, "%s \"%s\": mode %03o, uid %d, gid %d", action == RESTORE ? "Restoring" : (action == SAVE ? "Saving" : "UNKNOWN ERROR for"), h->ttydev, h->ttyfd_stat.st_mode, h->ttyfd_stat.st_uid, h->ttyfd_stat.st_gid));
+# endif
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+/*
+ * window size/position calculcations for XSizeHint and other storage.
+ * if width/height are non-zero then override calculated width/height
+ */
+/* EXTPROTO */
+void
+rxvt_window_calc(pR_ unsigned int width, unsigned int height)
+{
+    short           recalc_x, recalc_y;
+    int             x, y, sb_w, mb_h, flags;
+    unsigned int    w, h;
+    unsigned int    max_width, max_height;
+
+    D_SIZE((stderr, "< Cols/Rows: %3d x %3d ; Width/Height: %4d x %4d", R->TermWin.ncol, R->TermWin.nrow, R->szHint.width, R->szHint.height));
+    R->szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity;
+    R->szHint.win_gravity = NorthWestGravity;
+    /* R->szHint.min_aspect.x = R->szHint.min_aspect.y = 1; */
+
+    recalc_x = recalc_y = 0;
+    flags = 0;
+    if (!R->h->parsed_geometry) {
+       R->h->parsed_geometry = 1;
+       if (R->h->rs[Rs_geometry])
+           flags = XParseGeometry(R->h->rs[Rs_geometry], &x, &y, &w, &h);
+       if (flags & WidthValue) {
+           R->TermWin.ncol = BOUND_POSITIVE_INT16(w);
+           R->szHint.flags |= USSize;
+       }
+       if (flags & HeightValue) {
+           R->TermWin.nrow = BOUND_POSITIVE_INT16(h);
+           R->szHint.flags |= USSize;
+       }
+       if (flags & XValue) {
+           R->szHint.x = x;
+           R->szHint.flags |= USPosition;
+           if (flags & XNegative) {
+               recalc_x = 1;
+               R->szHint.win_gravity = NorthEastGravity;
+           }
+       }
+       if (flags & YValue) {
+           R->szHint.y = y;
+           R->szHint.flags |= USPosition;
+           if (flags & YNegative) {
+               recalc_y = 1;
+               if (R->szHint.win_gravity == NorthEastGravity)
+                   R->szHint.win_gravity = SouthEastGravity;
+               else
+                   R->szHint.win_gravity = SouthWestGravity;
+           }
+       }
+    }
+/* TODO: BOUNDS */
+    R->TermWin.width = R->TermWin.ncol * R->TermWin.fwidth;
+    R->TermWin.height = R->TermWin.nrow * R->TermWin.fheight;
+    max_width = MAX_COLS * R->TermWin.fwidth;
+    max_height = MAX_ROWS * R->TermWin.fheight;
+
+    R->szHint.base_width = R->szHint.base_height = 2 * R->TermWin.int_bwidth;
+
+    sb_w = mb_h = 0;
+    R->h->window_vt_x = R->h->window_vt_y = 0;
+    if (scrollbar_visible(R)) {
+       sb_w = scrollbar_TotalWidth();
+       R->szHint.base_width += sb_w;
+       if (!(R->Options & Opt_scrollBar_right))
+           R->h->window_vt_x = sb_w;
+    }
+    if (menubar_visible(R)) {
+       mb_h = menuBar_TotalHeight();
+       R->szHint.base_height += mb_h;
+       R->h->window_vt_y = mb_h;
+    }
+    R->szHint.width_inc = R->TermWin.fwidth;
+    R->szHint.height_inc = R->TermWin.fheight;
+    R->szHint.min_width = R->szHint.base_width + R->szHint.width_inc;
+    R->szHint.min_height = R->szHint.base_height + R->szHint.height_inc;
+
+    if (width && width - R->szHint.base_width < max_width) {
+       R->szHint.width = width;
+       R->TermWin.width = width - R->szHint.base_width;
+    } else {
+       MIN_IT(R->TermWin.width, max_width);
+       R->szHint.width = R->szHint.base_width + R->TermWin.width;
+    }
+    if (height && height - R->szHint.base_height < max_height) {
+       R->szHint.height = height;
+       R->TermWin.height = height - R->szHint.base_height;
+    } else {
+       MIN_IT(R->TermWin.height, max_height);
+       R->szHint.height = R->szHint.base_height + R->TermWin.height;
+    }
+    if (scrollbar_visible(R) && (R->Options & Opt_scrollBar_right))
+       R->h->window_sb_x = R->szHint.width - sb_w;
+
+    if (recalc_x)
+       R->szHint.x += (DisplayWidth(R->Xdisplay, Xscreen)
+                       - R->szHint.width - 2 * R->TermWin.ext_bwidth);
+    if (recalc_y)
+       R->szHint.y += (DisplayHeight(R->Xdisplay, Xscreen)
+                       - R->szHint.height - 2 * R->TermWin.ext_bwidth);
+
+    R->TermWin.ncol = R->TermWin.width / R->TermWin.fwidth;
+    R->TermWin.nrow = R->TermWin.height / R->TermWin.fheight;
+    D_SIZE((stderr, "> Cols/Rows: %3d x %3d ; Width/Height: %4d x %4d", R->TermWin.ncol, R->TermWin.nrow, R->szHint.width, R->szHint.height));
+    return;
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * Tell the teletype handler what size the window is.
+ * Called after a window size change.
+ */
+/* EXTPROTO */
+void
+rxvt_tt_winsize(int fd, unsigned short col, unsigned short row, int pid)
+{
+    struct winsize  ws;
+
+    if (fd < 0)
+       return;
+    ws.ws_col = col;
+    ws.ws_row = row;
+    ws.ws_xpixel = ws.ws_ypixel = 0;
+#ifndef DEBUG_SIZE
+    (void)ioctl(fd, TIOCSWINSZ, &ws);
+#else
+    if (ioctl(fd, TIOCSWINSZ, &ws) < 0) {
+       D_SIZE((stderr, "Failed to send TIOCSWINSZ to fd %d", fd));
+    }
+# ifdef SIGWINCH
+    else if (pid)              /* force through to the command */
+       kill(pid, SIGWINCH);
+# endif
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/* rxvt_change_font() - Switch to a new font */
+/*
+ * init = 1   - initialize
+ *
+ * fontname == FONT_UP  - switch to bigger font
+ * fontname == FONT_DN  - switch to smaller font
+ */
+/* EXTPROTO */
+void
+rxvt_change_font(pR_ int init, const char *fontname)
+{
+}
+
+/* INTPROTO */
+void
+rxvt_font_up_down(pR_ int n, int direction)
+{
+}
+
+/*----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+/* xterm sequences - title, iconName, color (exptl) */
+/* EXTPROTO */
+void
+rxvt_set_title(pR_ const char *str)
+{
+#ifndef SMART_WINDOW_TITLE
+    XStoreName(R->Xdisplay, R->TermWin.parent[0], str);
+#else
+    char           *name;
+
+    if (XFetchName(R->Xdisplay, R->TermWin.parent[0], &name) == 0)
+       name = NULL;
+    if (name == NULL || STRCMP(name, str))
+       XStoreName(R->Xdisplay, R->TermWin.parent[0], str);
+    if (name)
+       XFree(name);
+#endif
+}
+
+/* EXTPROTO */
+void
+rxvt_set_iconName(pR_ const char *str)
+{
+#ifndef SMART_WINDOW_TITLE
+    XSetIconName(R->Xdisplay, R->TermWin.parent[0], str);
+#else
+    char           *name;
+
+    if (XGetIconName(R->Xdisplay, R->TermWin.parent[0], &name))
+       name = NULL;
+    if (name == NULL || STRCMP(name, str))
+       XSetIconName(R->Xdisplay, R->TermWin.parent[0], str);
+    if (name)
+       XFree(name);
+#endif
+}
+
+#ifdef XTERM_COLOR_CHANGE
+/* EXTPROTO */
+void
+rxvt_set_window_color(pR_ int idx, const char *color)
+{
+    rxvt_color      xcol;
+    int             i;
+
+    if (color == NULL || *color == '\0')
+       return;
+
+/* handle color aliases */
+    if (isdigit(*color)) {
+       i = atoi(color);
+       if (i >= 8 && i <= 15) {        /* bright colors */
+           i -= 8;
+# ifndef NO_BRIGHTCOLOR
+           R->PixColors[idx] = R->PixColors[minBrightCOLOR + i];
+           SET_PIXCOLOR(R->h, idx);
+           goto Done;
+# endif
+       }
+       if (i >= 0 && i <= 7) { /* normal colors */
+           R->PixColors[idx] = R->PixColors[minCOLOR + i];
+           SET_PIXCOLOR(R->h, idx);
+           goto Done;
+       }
+    }
+    if (!rxvt_rXParseAllocColor(aR_ &xcol, color))
+       return;
+/* XStoreColor (R->Xdisplay, XCMAP, XColor*); */
+
+/*
+ * FIXME: should free colors here, but no idea how to do it so instead,
+ * so just keep gobbling up the colormap
+ */
+# if 0
+    for (i = Color_Black; i <= Color_White; i++)
+       if (R->PixColors[idx] == R->PixColors[i])
+           break;
+    if (i > Color_White) {
+       /* fprintf (stderr, "XFreeColors: R->PixColors [%d] = %lu\n", idx, R->PixColors [idx]); */
+       XFreeColors(R->Xdisplay, XCMAP, (R->PixColors + idx), 1,
+                   DisplayPlanes(R->Xdisplay, Xscreen));
+    }
+# endif
+
+    R->PixColors[idx] = xcol;
+    SET_PIXCOLOR(R->h, idx);
+
+/* XSetWindowAttributes attr; */
+/* Cursor cursor; */
+  Done:
+    if (idx == Color_bg && !(R->Options & Opt_transparent))
+       XSetWindowBackground(R->Xdisplay, R->TermWin.vt,
+                            R->PixColors[Color_bg]);
+
+/* handle Color_BD, scrollbar background, etc. */
+
+    rxvt_set_colorfgbg(aR);
+    rxvt_recolour_cursor(aR);
+/* the only reasonable way to enforce a clean update */
+    rxvt_scr_poweron(aR);
+}
+
+#else
+# define rxvt_set_window_color(aR_ idx,color)  ((void)0)
+#endif                         /* XTERM_COLOR_CHANGE */
+
+/* EXTPROTO */
+void
+rxvt_recolour_cursor(pR)
+{
+    rxvt_color      xcol[2];
+
+#if TODO
+    xcol[0] = R->PixColors[Color_pointer];
+    xcol[1] = R->PixColors[Color_bg];
+    XQueryColors(R->Xdisplay, XCMAP, xcol, 2);
+    XRecolorCursor(R->Xdisplay, R->TermWin_cursor, &(xcol[0]), &(xcol[1]));
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * find if fg/bg matches any of the normal (low-intensity) colors
+ */
+/* INTPROTO */
+void
+rxvt_set_colorfgbg(pR)
+{
+    unsigned int    i;
+    const char     *xpmb = "\0";
+    char            fstr[sizeof("default") + 1], bstr[sizeof("default") + 1];
+
+    R->h->env_colorfgbg = (char *)rxvt_malloc(sizeof("COLORFGBG=default;default;bg") + 1);
+    STRCPY(fstr, "default");
+    STRCPY(bstr, "default");
+    for (i = Color_Black; i <= Color_White; i++)
+       if (R->PixColors[Color_fg] == R->PixColors[i]) {
+           sprintf(fstr, "%d", (i - Color_Black));
+           break;
+       }
+    for (i = Color_Black; i <= Color_White; i++)
+       if (R->PixColors[Color_bg] == R->PixColors[i]) {
+           sprintf(bstr, "%d", (i - Color_Black));
+#ifdef XPM_BACKGROUND
+           xpmb = "default;";
+#endif
+           break;
+       }
+    sprintf(R->h->env_colorfgbg, "COLORFGBG=%s;%s%s", fstr, xpmb, bstr);
+    putenv(R->h->env_colorfgbg);
+
+#ifndef NO_BRIGHTCOLOR
+    R->h->colorfgbg = DEFAULT_RSTYLE;
+    for (i = minCOLOR; i <= maxCOLOR; i++) {
+       if (R->PixColors[Color_fg] == R->PixColors[i])
+           R->h->colorfgbg = SET_FGCOLOR(R->h->colorfgbg, i);
+       if (R->PixColors[Color_bg] == R->PixColors[i])
+           R->h->colorfgbg = SET_BGCOLOR(R->h->colorfgbg, i);
+    }
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * Colour determination for low colour displays, routine from
+ *     Hans de Goede <hans@highrise.nl>
+ */
+
+/* EXTPROTO */
+int
+rxvt_rXParseAllocColor(pR_ rxvt_color *screen_in_out, const char *colour)
+{
+    screen_in_out->set (aR_ colour);
+
+    if (!screen_in_out->set (aR_ colour))
+      {
+       rxvt_print_error("can't allocate colour: %s", colour);
+        return false;
+      }
+
+    return true;
+}
+
+/* -------------------------------------------------------------------- *
+ * -                         WINDOW RESIZING                          - *
+ * -------------------------------------------------------------------- */
+/* EXTPROTO */
+void
+rxvt_resize_all_windows(pR_ unsigned int width, unsigned int height, int ignoreparent)
+{
+    int             fix_screen;
+#ifdef SMART_RESIZE    
+    int             old_width = R->szHint.width,
+                   old_height = R->szHint.height;
+#endif
+
+    rxvt_window_calc(aR_ width, height);
+    XSetWMNormalHints(R->Xdisplay, R->TermWin.parent[0], &R->szHint);
+    if (!ignoreparent) {
+#ifdef SMART_RESIZE    
+/*
+ * resize by Marius Gedminas <marius.gedminas@uosis.mif.vu.lt>
+ * reposition window on resize depending on placement on screen
+ */
+       int             x, y, x1, y1;
+       int             dx, dy;
+       unsigned int    unused_w1, unused_h1, unused_b1, unused_d1;
+       Window          unused_cr;
+
+       XTranslateCoordinates(R->Xdisplay, R->TermWin.parent[0], Xroot,
+                             0, 0, &x, &y, &unused_cr);
+       XGetGeometry(R->Xdisplay, R->TermWin.parent[0], &unused_cr, &x1, &y1,
+                    &unused_w1, &unused_h1, &unused_b1, &unused_d1);
+       /*
+        * if Xroot isn't the parent window, a WM will probably have offset
+        * our position for handles and decorations.  Counter it
+        */
+       if (x1 != x || y1 != y) {
+           x -= x1;
+           y -= y1;
+       }
+
+       x1 = (DisplayWidth(R->Xdisplay, Xscreen) - old_width) / 2;
+       y1 = (DisplayHeight(R->Xdisplay, Xscreen) - old_height) / 2;
+       dx = old_width - R->szHint.width;
+       dy = old_height - R->szHint.height;
+
+       /* Check position of the center of the window */
+       if (x < x1)             /* left half */
+           dx = 0;
+       else if (x == x1)       /* exact center */
+           dx /= 2;
+       if (y < y1)             /* top half */
+           dy = 0;
+       else if (y == y1)       /* exact center */
+           dy /= 2;
+
+       XMoveResizeWindow(R->Xdisplay, R->TermWin.parent[0], x + dx, y + dy,
+                         R->szHint.width, R->szHint.height);
+#else
+       XResizeWindow(R->Xdisplay, R->TermWin.parent[0], R->szHint.width,
+                     R->szHint.height);
+#endif
+    }
+
+    fix_screen = (R->TermWin.ncol != R->h->prev_ncol
+                 || R->TermWin.nrow != R->h->prev_nrow);
+    if (fix_screen || width != R->h->old_width || height != R->h->old_height) {
+       if (scrollbar_visible(R)) {
+           XMoveResizeWindow(R->Xdisplay, R->scrollBar.win, R->h->window_sb_x,
+                             0, scrollbar_TotalWidth(), R->szHint.height);
+           rxvt_Resize_scrollBar(aR);
+       }
+       if (menubar_visible(R))
+           XMoveResizeWindow(R->Xdisplay, R->menuBar.win, R->h->window_vt_x,
+                             0, TermWin_TotalWidth(), menuBar_TotalHeight());
+       XMoveResizeWindow(R->Xdisplay, R->TermWin.vt, R->h->window_vt_x,
+                         R->h->window_vt_y, TermWin_TotalWidth(),
+                         TermWin_TotalHeight());
+#ifdef RXVT_GRAPHICS
+       if (R->h->old_height)
+           rxvt_Gr_Resize(aR_ R->h->old_width - R->szHint.base_width,
+                          R->h->old_height - R->szHint.base_height);
+#endif
+       rxvt_scr_clear(aR);
+#ifdef XPM_BACKGROUND
+       rxvt_resize_pixmap(aR);
+#endif
+    }
+
+    if (fix_screen || R->h->old_height == 0) {
+       int             curr_screen = -1;
+       uint16_t       old_ncol = R->h->prev_ncol;
+
+       /* scr_reset only works on the primary screen */
+       if (R->h->old_height)   /* this is not the first time through */
+           curr_screen = rxvt_scr_change_screen(aR_ PRIMARY);
+       rxvt_scr_reset(aR);
+       if (curr_screen >= 0) { /* this is not the first time through */
+           rxvt_scr_change_screen(aR_ curr_screen);
+           rxvt_selection_check(aR_ (old_ncol != R->TermWin.ncol ? 4 : 0));
+       }
+    }
+
+    R->h->old_width = R->szHint.width;
+    R->h->old_height = R->szHint.height;
+
+#ifdef USE_XIM
+    rxvt_IMSetStatusPosition(aR);
+#endif
+}
+
+/*
+ * Set the width/height of the vt window in characters.  Units are pixels.
+ * good for toggling 80/132 columns
+ */
+/* EXTPROTO */
+void
+rxvt_set_widthheight(pR_ unsigned int width, unsigned int height)
+{
+    XWindowAttributes wattr;
+
+    if (width == 0 || height == 0) {
+       XGetWindowAttributes(R->Xdisplay, Xroot, &wattr);
+       if (width == 0)
+           width = wattr.width - R->szHint.base_width;
+       if (height == 0)
+           height = wattr.height - R->szHint.base_height;
+    }
+    if (width != R->TermWin.width || height != R->TermWin.height) {
+       width += R->szHint.base_width;
+       height += R->szHint.base_height;
+       rxvt_resize_all_windows(aR_ width, height, 0);
+    }
+}
+
+/* -------------------------------------------------------------------- *
+ * -                      X INPUT METHOD ROUTINES                     - *
+ * -------------------------------------------------------------------- */
+#ifdef USE_XIM
+/* INTPROTO */
+void
+rxvt_setSize(pR_ XRectangle *size)
+{
+    size->x = R->TermWin.int_bwidth;
+    size->y = R->TermWin.int_bwidth;
+    size->width = Width2Pixel(R->TermWin.ncol);
+    size->height = Height2Pixel(R->TermWin.nrow);
+}
+
+/* INTPROTO */
+void
+rxvt_setColor(pR_ unsigned long *fg, unsigned long *bg)
+{
+    *fg = R->PixColors[Color_fg];
+    *bg = R->PixColors[Color_bg];
+}
+
+/* Checking whether input method is running. */
+/* INTPROTO */
+Bool
+rxvt_IMisRunning(pR)
+{
+    char           *p;
+    Atom            atom;
+    Window          win;
+    char            server[IMBUFSIZ];
+
+    /* get current locale modifier */
+    if ((p = XSetLocaleModifiers(NULL)) != NULL) {
+       STRCPY(server, "@server=");
+       STRNCAT(server, &(p[4]), IMBUFSIZ - 9); /* skip "@im=" */
+       if ((p = STRCHR(server + 1, '@')) != NULL)      /* first one only */
+           *p = '\0';
+
+       atom = XInternAtom(R->Xdisplay, server, False);
+       win = XGetSelectionOwner(R->Xdisplay, atom);
+       if (win != None)
+           return True;
+    }
+    return False;
+}
+
+/* EXTPROTO */
+void
+rxvt_IMSendSpot(pR)
+{
+    XPoint          spot;
+    XVaNestedList   preedit_attr;
+
+    if (R->h->Input_Context == NULL
+       || !R->TermWin.focus
+       || !(R->h->input_style & XIMPreeditPosition)
+       || !(R->h->event_type == KeyPress
+            || R->h->event_type == Expose
+            || R->h->event_type == NoExpose
+            || R->h->event_type == SelectionNotify
+            || R->h->event_type == ButtonRelease
+            || R->h->event_type == FocusIn)
+       || !rxvt_IMisRunning(aR))
+       return;
+
+    rxvt_setPosition(aR_ &spot);
+
+    preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
+    XSetICValues(R->h->Input_Context, XNPreeditAttributes, preedit_attr, NULL);
+    XFree(preedit_attr);
+}
+
+/* EXTPROTO */
+void
+rxvt_setTermFontSet(pR_ int idx)
+{
+    char           *string;
+    long            length;
+    int             success = 0;
+
+    if (idx < 0 || idx >= MAX_NFONTS)
+       return;
+}
+
+/* INTPROTO */
+void
+rxvt_setPreeditArea(pR_ XRectangle *preedit_rect, XRectangle *status_rect, XRectangle *needed_rect)
+{
+    int             mbh, vtx = 0;
+
+    if (scrollbar_visible(R) && !(R->Options & Opt_scrollBar_right))
+       vtx = scrollbar_TotalWidth();
+    mbh = menubar_visible(R) ? menuBar_TotalHeight() : 0;
+    mbh -= R->TermWin.lineSpace;
+
+    preedit_rect->x = needed_rect->width + vtx;
+    preedit_rect->y = Height2Pixel(R->TermWin.nrow - 1) + mbh;
+
+    preedit_rect->width = Width2Pixel(R->TermWin.ncol + 1) - needed_rect->width
+                         + vtx;
+    preedit_rect->height = Height2Pixel(1);
+
+    status_rect->x = vtx;
+    status_rect->y = Height2Pixel(R->TermWin.nrow - 1) + mbh;
+
+    status_rect->width = needed_rect->width ? needed_rect->width
+                                           : Width2Pixel(R->TermWin.ncol + 1);
+    status_rect->height = Height2Pixel(1);
+}
+
+/* ARGSUSED */
+/* INTPROTO */
+void
+rxvt_IMDestroyCallback(XIM xim __attribute__((unused)), XPointer client_data __attribute__((unused)), XPointer call_data __attribute__((unused)))
+{
+    dR;
+
+    R->h->Input_Context = NULL;
+    /* To avoid Segmentation Fault in C locale: Solaris only? */
+    if (STRCMP(R->h->locale, "C"))
+       XRegisterIMInstantiateCallback(R->Xdisplay, NULL, NULL, NULL,
+                                      rxvt_IMInstantiateCallback, NULL);
+}
+
+/*
+ * X manual pages and include files don't match on some systems:
+ * some think this is an XIDProc and others an XIMProc so we can't
+ * use the first argument - need to update this to be nice for
+ * both types via some sort of configure detection
+ */
+/* ARGSUSED */
+/* EXTPROTO */
+void
+rxvt_IMInstantiateCallback(Display *unused __attribute__((unused)), XPointer client_data __attribute__((unused)), XPointer call_data __attribute__((unused)))
+{
+    dR;
+    int             i, found, had_im;
+    const char     *p;
+    char          **s;
+    char            buf[IMBUFSIZ];
+
+    D_MAIN((stderr, "rxvt_IMInstantiateCallback()"));
+    if (R->h->Input_Context)
+       return;
+
+    found = had_im = 0;
+    p = R->h->rs[Rs_inputMethod];
+    if (p && *p) {
+       had_im = 1;
+       s = rxvt_splitcommastring(p);
+       for (i = 0; s[i]; i++) {
+           if (*s[i]) {
+               STRCPY(buf, "@im=");
+               STRNCAT(buf, s[i], IMBUFSIZ - 5);
+               if ((p = XSetLocaleModifiers(buf)) != NULL && *p
+                   && (rxvt_IM_get_IC(aR) == True)) {
+                   found = 1;
+                   break;
+               }
+           }
+       }
+       for (i = 0; s[i]; i++)
+           free(s[i]);
+       free(s);
+    }
+    if (found)
+       return;
+
+/* try with XMODIFIERS env. var. */
+    if ((p = XSetLocaleModifiers("")) != NULL && *p) {
+       rxvt_IM_get_IC(aR);
+       return;
+    }
+
+/* try with no modifiers base IF the user didn't specify an IM */
+    if (!had_im && (p = XSetLocaleModifiers("@im=none")) != NULL && *p
+       && rxvt_IM_get_IC(aR) == True)
+       return;
+}
+
+/*
+ * Try to open a XIM with the current modifiers, then see if we can
+ * open a suitable preedit type
+ */
+/* INTPROTO */
+Bool
+rxvt_IM_get_IC(pR)
+{
+    int             i, j, found;
+    XIM             xim;
+    XPoint          spot;
+    XRectangle      rect, status_rect, needed_rect;
+    unsigned long   fg, bg;
+    const char     *p;
+    char          **s;
+    XIMStyles      *xim_styles;
+    XVaNestedList   preedit_attr, status_attr;
+    XIMCallback     ximcallback;
+    struct rxvt_hidden *h = R->h;
+
+    D_MAIN((stderr, "rxvt_IM_get_IC()"));
+    xim = XOpenIM(R->Xdisplay, NULL, NULL, NULL);
+    if (xim == NULL)
+       return False;
+
+    xim_styles = NULL;
+    if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL)
+       || !xim_styles || !xim_styles->count_styles) {
+       XCloseIM(xim);
+       return False;
+    }
+
+    p = h->rs[Rs_preeditType] ? h->rs[Rs_preeditType]
+                             : "OverTheSpot,OffTheSpot,Root";
+    s = rxvt_splitcommastring(p);
+    for (i = found = 0; !found && s[i]; i++) {
+       if (!STRCMP(s[i], "OverTheSpot"))
+           h->input_style = (XIMPreeditPosition | XIMStatusNothing);
+       else if (!STRCMP(s[i], "OffTheSpot"))
+           h->input_style = (XIMPreeditArea | XIMStatusArea);
+       else if (!STRCMP(s[i], "Root"))
+           h->input_style = (XIMPreeditNothing | XIMStatusNothing);
+
+       for (j = 0; j < xim_styles->count_styles; j++)
+           if (h->input_style == xim_styles->supported_styles[j]) {
+               found = 1;
+               break;
+           }
+    }
+    for (i = 0; s[i]; i++)
+       free(s[i]);
+    free(s);
+    XFree(xim_styles);
+
+    if (!found) {
+       XCloseIM(xim);
+       return False;
+    }
+
+    ximcallback.callback = rxvt_IMDestroyCallback;
+
+    /* XXX: not sure why we need this (as well as IC one below) */
+    XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
+
+    preedit_attr = status_attr = NULL;
+
+    if (h->input_style & XIMPreeditPosition) {
+       rxvt_setSize(aR_ &rect);
+       rxvt_setPosition(aR_ &spot);
+       rxvt_setColor(aR_ &fg, &bg);
+
+       preedit_attr = XVaCreateNestedList(0, XNArea, &rect,
+                                          XNSpotLocation, &spot,
+                                          XNForeground, fg,
+                                          XNBackground, bg,
+                                          //XNFontSet, R->TermWin.fontset,
+                                          NULL);
+    } else if (h->input_style & XIMPreeditArea) {
+       rxvt_setColor(aR_ &fg, &bg);
+
+       /*
+        * The necessary width of preedit area is unknown
+        * until create input context.
+        */
+       needed_rect.width = 0;
+
+       rxvt_setPreeditArea(aR_ &rect, &status_rect, &needed_rect);
+
+       preedit_attr = XVaCreateNestedList(0, XNArea, &rect,
+                                          XNForeground, fg,
+                                          XNBackground, bg,
+                                          //XNFontSet, R->TermWin.fontset,
+                                          NULL);
+       status_attr = XVaCreateNestedList(0, XNArea, &status_rect,
+                                         XNForeground, fg,
+                                         XNBackground, bg,
+                                         //XNFontSet, R->TermWin.fontset,
+                                          NULL);
+    }
+    h->Input_Context = XCreateIC(xim, XNInputStyle, h->input_style,
+                                XNClientWindow, R->TermWin.parent[0],
+                                XNFocusWindow, R->TermWin.parent[0],
+                                XNDestroyCallback, &ximcallback,
+                                preedit_attr ? XNPreeditAttributes : NULL,
+                                preedit_attr,
+                                status_attr ? XNStatusAttributes : NULL,
+                                status_attr, NULL);
+    if (preedit_attr)
+       XFree(preedit_attr);
+    if (status_attr)
+       XFree(status_attr);
+    if (h->Input_Context == NULL) {
+       rxvt_print_error("failed to create input context");
+       XCloseIM(xim);
+       return False;
+    }
+    if (h->input_style & XIMPreeditArea)
+       rxvt_IMSetStatusPosition(aR);
+    D_MAIN((stderr, "rxvt_IM_get_IC() - successful connection"));
+    return True;
+}
+
+/* EXTPROTO */
+void
+rxvt_IMSetStatusPosition(pR)
+{
+    XRectangle      preedit_rect, status_rect, *needed_rect;
+    XVaNestedList   preedit_attr, status_attr;
+
+    if (R->h->Input_Context == NULL
+       || !R->TermWin.focus
+       || !(R->h->input_style & XIMPreeditArea)
+       || !rxvt_IMisRunning(aR))
+       return;
+
+    /* Getting the necessary width of preedit area */
+    status_attr = XVaCreateNestedList(0, XNAreaNeeded, &needed_rect, NULL);
+    XGetICValues(R->h->Input_Context, XNStatusAttributes, status_attr, NULL);
+    XFree(status_attr);
+
+    rxvt_setPreeditArea(aR_ &preedit_rect, &status_rect, needed_rect);
+
+    preedit_attr = XVaCreateNestedList(0, XNArea, &preedit_rect, NULL);
+    status_attr = XVaCreateNestedList(0, XNArea, &status_rect, NULL);
+
+    XSetICValues(R->h->Input_Context,
+                XNPreeditAttributes, preedit_attr,
+                XNStatusAttributes, status_attr, NULL);
+
+    XFree(preedit_attr);
+    XFree(status_attr);
+}
+#endif                         /* USE_XIM */
+
+/*----------------------------------------------------------------------*/
+rxvt_t *rxvt_current_term;
+
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/makeextprotos-sed b/src/makeextprotos-sed
new file mode 100644 (file)
index 0000000..69b6685
--- /dev/null
@@ -0,0 +1,18 @@
+# Get prototypes from a .c file
+# $Id: makeextprotos-sed,v 1.1 2003-11-24 17:28:08 pcg Exp $
+# /* EXTPROTO */   must be above return type which are above function.
+#              Args are on one line
+# eg.
+# /* EXTPROTO */
+# void                           ------>   void main(int argc, char **argv);
+# main(int argc, char **argv)
+# {
+# }
+#
+/^[/][*] EXTPROTO [*][/]$/{
+n
+N
+s/\n\([_a-zA-Z][_a-zA-Z0-9]* *\)(/ \1 __PROTO((/
+s/$/);/
+p
+}
diff --git a/src/makeintprotos-sed b/src/makeintprotos-sed
new file mode 100644 (file)
index 0000000..e2abaee
--- /dev/null
@@ -0,0 +1,18 @@
+# Get prototypes from a .c file
+# $Id: makeintprotos-sed,v 1.1 2003-11-24 17:28:08 pcg Exp $
+# /* INTPROTO */   must be above return type which are above function.
+#              Args are on one line
+# eg.
+# /* INTPROTO */
+# void                           ------>   void main(int argc, char **argv);
+# main(int argc, char **argv)
+# {
+# }
+#
+/^[/][*] INTPROTO [*][/]$/{
+n
+N
+s/\n\([_a-zA-Z][_a-zA-Z0-9]* *\)(/ \1 __PROTO((/
+s/$/);/
+p
+}
diff --git a/src/menubar.C b/src/menubar.C
new file mode 100644 (file)
index 0000000..775a278
--- /dev/null
@@ -0,0 +1,2252 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       menubar.c
+ *----------------------------------------------------------------------*
+ * $Id: menubar.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Copyright (c) 1997,1998  mj olesen <olesen@me.QueensU.CA>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*
+ * refer.html (or refer.txt) contains up-to-date documentation.  The
+ * summary that appears at the end of this file was taken from there.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#ifdef MENUBAR
+#include "version.h"
+#include "menubar.h"
+#include "menubar.intpro"      /* PROTOS for internal routines */
+
+#define Menu_PixelWidth(menu)                                  \
+    (2 * SHADOW + Width2Pixel ((menu)->width + 3 * HSPACE))
+
+static const struct {
+    const char      name;      /* (l)eft, (u)p, (d)own, (r)ight */
+    const unsigned char str[5];        /* str[0] = STRLEN (str+1) */
+} Arrows[NARROWS] = {
+    { 'l', "\003\033[D" },
+    { 'u', "\003\033[A" },
+    { 'd', "\003\033[B" },
+    { 'r', "\003\033[C" }
+};
+
+/*}}} */
+
+/*
+ * find an item called NAME in MENU
+ */
+/* INTPROTO */
+menuitem_t     *
+rxvt_menuitem_find(const menu_t *menu, const char *name)
+{
+    menuitem_t     *item;
+
+#ifdef DEBUG_STRICT
+    assert(name != NULL);
+    assert(menu != NULL);
+#endif
+
+/* find the last item in the menu, this is good for separators */
+    for (item = menu->tail; item != NULL; item = item->prev) {
+       if (item->entry.type == MenuSubMenu) {
+           if (!STRCMP(name, (item->entry.submenu.menu)->name))
+               break;
+       } else if ((isSeparator(name) && isSeparator(item->name))
+                  || !STRCMP(name, item->name))
+           break;
+    }
+    return item;
+}
+
+/*
+ * unlink ITEM from its MENU and free its memory
+ */
+/* INTPROTO */
+void
+rxvt_menuitem_free(pR_ menu_t *menu, menuitem_t *item)
+{
+/* disconnect */
+    menuitem_t     *prev, *next;
+
+#ifdef DEBUG_STRICT
+    assert(menu != NULL);
+#endif
+
+    prev = item->prev;
+    next = item->next;
+    if (prev != NULL)
+       prev->next = next;
+    if (next != NULL)
+       next->prev = prev;
+
+/* new head, tail */
+    if (menu->tail == item)
+       menu->tail = prev;
+    if (menu->head == item)
+       menu->head = next;
+
+    switch (item->entry.type) {
+    case MenuAction:
+    case MenuTerminalAction:
+       free(item->entry.action.str);
+       break;
+    case MenuSubMenu:
+       rxvt_menu_delete(aR_ item->entry.submenu.menu);
+       break;
+    }
+    if (item->name != NULL)
+       free(item->name);
+    if (item->name2 != NULL)
+       free(item->name2);
+    free(item);
+}
+
+/*
+ * sort command vs. terminal actions and
+ * remove the first character of STR if it's '\0'
+ */
+/* INTPROTO */
+int
+rxvt_action_type(action_t *action, unsigned char *str)
+{
+    unsigned int    len;
+
+#if defined (DEBUG_MENU) || defined (DEBUG_MENUARROWS)
+    len = STRLEN(str);
+    fprintf(stderr, "(len %d) = %s\n", len, str);
+#else
+    len = rxvt_Str_escaped((char *)str);
+#endif
+
+    if (!len)
+       return -1;
+
+/* sort command vs. terminal actions */
+    action->type = MenuAction;
+    if (str[0] == '\0') {
+       /* the functional equivalent: memmove (str, str+1, len); */
+       unsigned char  *dst = (str);
+       unsigned char  *src = (str + 1);
+       unsigned char  *end = (str + len);
+
+       while (src <= end)
+           *dst++ = *src++;
+
+       len--;                  /* decrement length */
+       if (str[0] != '\0')
+           action->type = MenuTerminalAction;
+    }
+    action->str = str;
+    action->len = len;
+
+    return 0;
+}
+
+/* INTPROTO */
+int
+rxvt_action_dispatch(pR_ action_t *action)
+{
+    switch (action->type) {
+    case MenuTerminalAction:
+       rxvt_cmd_write(aR_ action->str, action->len);
+       break;
+
+    case MenuAction:
+       rxvt_tt_write(aR_ action->str, action->len);
+       break;
+
+    default:
+       return -1;
+       break;
+    }
+    return 0;
+}
+
+/* return the arrow index corresponding to NAME */
+/* INTPROTO */
+int
+rxvt_menuarrow_find(char name)
+{
+    int             i;
+
+    for (i = 0; i < NARROWS; i++)
+       if (name == Arrows[i].name)
+           return i;
+    return -1;
+}
+
+/* free the memory associated with arrow NAME of the current menubar */
+/* INTPROTO */
+void
+rxvt_menuarrow_free(pR_ char name)
+{
+    int             i;
+
+    if (name) {
+       i = rxvt_menuarrow_find(name);
+       if (i >= 0) {
+           action_t       *act = &(R->h->CurrentBar->arrows[i]);
+
+           switch (act->type) {
+           case MenuAction:
+           case MenuTerminalAction:
+               free(act->str);
+               act->str = NULL;
+               act->len = 0;
+               break;
+           }
+           act->type = MenuLabel;
+       }
+    } else {
+       for (i = 0; i < NARROWS; i++)
+           rxvt_menuarrow_free(aR_ Arrows[i].name);
+    }
+}
+
+/* INTPROTO */
+void
+rxvt_menuarrow_add(pR_ char *string)
+{
+    int             i;
+    unsigned        xtra_len;
+    char           *p;
+    struct {
+       char           *str;
+       int             len;
+    }
+    beg = { NULL, 0 },
+    end = { NULL, 0 },
+    *cur,
+    parse[NARROWS];
+
+    MEMSET(parse, 0, sizeof(parse));
+
+/* fprintf(stderr, "add arrows = `%s'\n", string); */
+    for (p = string; p != NULL && *p; string = p) {
+       p = (string + 3);
+       /* fprintf(stderr, "parsing at %s\n", string); */
+       switch (string[1]) {
+       case 'b':
+           cur = &beg;
+           break;
+       case 'e':
+           cur = &end;
+           break;
+
+       default:
+           i = rxvt_menuarrow_find(string[1]);
+           if (i >= 0)
+               cur = &(parse[i]);
+           else
+               continue;       /* not found */
+           break;
+       }
+
+       string = p;
+       cur->str = string;
+       cur->len = 0;
+
+       if (cur == &end) {
+           p = STRCHR(string, '\0');
+       } else {
+           char           *next = string;
+
+           while (1) {
+               p = STRCHR(next, '<');
+               if (p != NULL) {
+                   if (p[1] && p[2] == '>')
+                       break;
+                   /* parsed */
+               } else {
+                   if (beg.str == NULL)        /* no end needed */
+                       p = STRCHR(next, '\0');
+                   break;
+               }
+               next = (p + 1);
+           }
+       }
+
+       if (p == NULL)
+           return;
+       cur->len = (p - string);
+    }
+
+#ifdef DEBUG_MENUARROWS
+    cur = &beg;
+    fprintf(stderr, "<b>(len %d) = %.*s\n",
+           cur->len, cur->len, (cur->str ? cur->str : ""));
+    for (i = 0; i < NARROWS; i++) {
+       cur = &(parse[i]);
+       fprintf(stderr, "<%c>(len %d) = %.*s\n",
+               Arrows[i].name,
+               cur->len, cur->len, (cur->str ? cur->str : ""));
+    }
+    cur = &end;
+    fprintf(stderr, "<e>(len %d) = %.*s\n",
+           cur->len, cur->len, (cur->str ? cur->str : ""));
+#endif
+
+    xtra_len = (beg.len + end.len);
+    for (i = 0; i < NARROWS; i++) {
+       if (xtra_len || parse[i].len)
+           rxvt_menuarrow_free(aR_ Arrows[i].name);
+    }
+
+    for (i = 0; i < NARROWS; i++) {
+       unsigned char  *str;
+       unsigned int    len;
+
+       if (!parse[i].len)
+           continue;
+
+       str = rxvt_malloc(parse[i].len + xtra_len + 1);
+
+       len = 0;
+       if (beg.len) {
+           STRNCPY(str + len, beg.str, beg.len);
+           len += beg.len;
+       }
+       STRNCPY(str + len, parse[i].str, parse[i].len);
+       len += parse[i].len;
+
+       if (end.len) {
+           STRNCPY(str + len, end.str, end.len);
+           len += end.len;
+       }
+       str[len] = '\0';
+
+#ifdef DEBUG_MENUARROWS
+       fprintf(stderr, "<%c>(len %d) = %s\n", Arrows[i].name, len, str);
+#endif
+       if (rxvt_action_type(&(R->h->CurrentBar->arrows[i]), str) < 0)
+           free(str);
+    }
+}
+
+/* INTPROTO */
+menuitem_t     *
+rxvt_menuitem_add(menu_t *menu, const char *name, const char *name2, const char *action)
+{
+    menuitem_t     *item;
+    unsigned int    len;
+
+#ifdef DEBUG_STRICT
+    assert(name != NULL);
+    assert(action != NULL);
+#endif
+
+    if (menu == NULL)
+       return NULL;
+
+    if (isSeparator(name)) {
+       /* add separator, no action */
+       name = "";
+       action = "";
+    } else {
+       /*
+        * add/replace existing menu item
+        */
+       item = rxvt_menuitem_find(menu, name);
+       if (item != NULL) {
+           if (item->name2 != NULL && name2 != NULL) {
+               free(item->name2);
+               item->len2 = 0;
+               item->name2 = NULL;
+           }
+           switch (item->entry.type) {
+           case MenuAction:
+           case MenuTerminalAction:
+               free(item->entry.action.str);
+               item->entry.action.str = NULL;
+               break;
+           }
+           goto Item_Found;
+       }
+    }
+/* allocate a new itemect */
+    item = (menuitem_t *) rxvt_malloc(sizeof(menuitem_t));
+
+    item->len2 = 0;
+    item->name2 = NULL;
+
+    len = STRLEN(name);
+    item->name = rxvt_malloc(len + 1);
+    STRCPY(item->name, name);
+    if (name[0] == '.' && name[1] != '.')
+       len = 0;                /* hidden menu name */
+    item->len = len;
+
+/* add to tail of list */
+    item->prev = menu->tail;
+    item->next = NULL;
+
+    if (menu->tail != NULL)
+       (menu->tail)->next = item;
+    menu->tail = item;
+/* fix head */
+    if (menu->head == NULL)
+       menu->head = item;
+
+/*
+ * add action
+ */
+  Item_Found:
+    if (name2 != NULL && item->name2 == NULL) {
+       len = STRLEN(name2);
+       if (len == 0)
+           item->name2 = NULL;
+       else {
+           item->name2 = rxvt_malloc(len + 1);
+           STRCPY(item->name2, name2);
+       }
+       item->len2 = len;
+    }
+    item->entry.type = MenuLabel;
+    len = STRLEN(action);
+
+    if (len == 0 && item->name2 != NULL) {
+       action = item->name2;
+       len = item->len2;
+    }
+    if (len) {
+       unsigned char  *str = rxvt_malloc(len + 1);
+
+       STRCPY(str, action);
+
+       if (rxvt_action_type(&(item->entry.action), str) < 0)
+           free(str);
+    }
+/* new item and a possible increase in width */
+    if (menu->width < (item->len + item->len2))
+       menu->width = (item->len + item->len2);
+
+    return item;
+}
+
+/*
+ * search for the base starting menu for NAME.
+ * return a pointer to the portion of NAME that remains
+ */
+/* INTPROTO */
+char           *
+rxvt_menu_find_base(pR_ menu_t **menu, char *path)
+{
+    menu_t         *m = NULL;
+    menuitem_t     *item;
+
+#ifdef DEBUG_STRICT
+    assert(menu != NULL);
+    assert(R->h->CurrentBar != NULL);
+#endif
+
+    if (path[0] == '\0')
+       return path;
+
+    if (STRCHR(path, '/') != NULL) {
+       char           *p = path;
+
+       while ((p = STRCHR(p, '/')) != NULL) {
+           p++;
+           if (*p == '/')
+               path = p;
+       }
+       if (path[0] == '/') {
+           path++;
+           *menu = NULL;
+       }
+       while ((p = STRCHR(path, '/')) != NULL) {
+           p[0] = '\0';
+           if (path[0] == '\0')
+               return NULL;
+           if (!STRCMP(path, DOT)) {
+               /* nothing to do */
+           } else if (!STRCMP(path, DOTS)) {
+               if (*menu != NULL)
+                   *menu = (*menu)->parent;
+           } else {
+               path = rxvt_menu_find_base(aR_ menu, path);
+               if (path[0] != '\0') {  /* not found */
+                   p[0] = '/'; /* fix-up name again */
+                   return path;
+               }
+           }
+
+           path = (p + 1);
+       }
+    }
+    if (!STRCMP(path, DOTS)) {
+       path += STRLEN(DOTS);
+       if (*menu != NULL)
+           *menu = (*menu)->parent;
+       return path;
+    }
+/* find this menu */
+    if (*menu == NULL) {
+       for (m = R->h->CurrentBar->tail; m != NULL; m = m->prev) {
+           if (!STRCMP(path, m->name))
+               break;
+       }
+    } else {
+       /* find this menu */
+       for (item = (*menu)->tail; item != NULL; item = item->prev) {
+           if (item->entry.type == MenuSubMenu
+               && !STRCMP(path, (item->entry.submenu.menu)->name)) {
+               m = (item->entry.submenu.menu);
+               break;
+           }
+       }
+    }
+    if (m != NULL) {
+       *menu = m;
+       path += STRLEN(path);
+    }
+    return path;
+}
+
+/*
+ * delete this entire menu
+ */
+/* INTPROTO */
+menu_t         *
+rxvt_menu_delete(pR_ menu_t *menu)
+{
+    menu_t         *parent = NULL, *prev, *next;
+    menuitem_t     *item;
+    bar_t          *CurrentBar = R->h->CurrentBar;
+
+#ifdef DEBUG_STRICT
+    assert(CurrentBar != NULL);
+#endif
+
+/* delete the entire menu */
+    if (menu == NULL)
+       return NULL;
+
+    parent = menu->parent;
+
+/* unlink MENU */
+    prev = menu->prev;
+    next = menu->next;
+    if (prev != NULL)
+       prev->next = next;
+    if (next != NULL)
+       next->prev = prev;
+
+/* fix the index */
+    if (parent == NULL) {
+       const int       len = (menu->len + HSPACE);
+
+       if (CurrentBar->tail == menu)
+           CurrentBar->tail = prev;
+       if (CurrentBar->head == menu)
+           CurrentBar->head = next;
+
+       for (next = menu->next; next != NULL; next = next->next)
+           next->x -= len;
+    } else {
+       for (item = parent->tail; item != NULL; item = item->prev) {
+           if (item->entry.type == MenuSubMenu
+               && item->entry.submenu.menu == menu) {
+               item->entry.submenu.menu = NULL;
+               rxvt_menuitem_free(aR_ menu->parent, item);
+               break;
+           }
+       }
+    }
+
+    item = menu->tail;
+    while (item != NULL) {
+       menuitem_t     *p = item->prev;
+
+       rxvt_menuitem_free(aR_ menu, item);
+       item = p;
+    }
+
+    if (menu->name != NULL)
+       free(menu->name);
+    free(menu);
+
+    return parent;
+}
+
+/* INTPROTO */
+menu_t         *
+rxvt_menu_add(pR_ menu_t *parent, char *path)
+{
+    menu_t         *menu;
+    bar_t          *CurrentBar = R->h->CurrentBar;
+
+#ifdef DEBUG_STRICT
+    assert(CurrentBar != NULL);
+#endif
+
+    if (STRCHR(path, '/') != NULL) {
+       char           *p;
+
+       if (path[0] == '/') {
+           /* shouldn't happen */
+           path++;
+           parent = NULL;
+       }
+       while ((p = STRCHR(path, '/')) != NULL) {
+           p[0] = '\0';
+           if (path[0] == '\0')
+               return NULL;
+
+           parent = rxvt_menu_add(aR_ parent, path);
+           path = (p + 1);
+       }
+    }
+    if (!STRCMP(path, DOTS))
+       return (parent != NULL ? parent->parent : parent);
+
+    if (!STRCMP(path, DOT) || path[0] == '\0')
+       return parent;
+
+/* allocate a new menu */
+    menu = (menu_t *) rxvt_malloc(sizeof(menu_t));
+
+    menu->width = 0;
+    menu->parent = parent;
+    menu->len = STRLEN(path);
+    menu->name = rxvt_malloc((menu->len + 1));
+    STRCPY(menu->name, path);
+
+/* initialize head/tail */
+    menu->head = menu->tail = NULL;
+    menu->prev = menu->next = NULL;
+
+    menu->win = None;
+    menu->x = menu->y = menu->w = menu->h = 0;
+    menu->item = NULL;
+
+/* add to tail of list */
+    if (parent == NULL) {
+       menu->prev = CurrentBar->tail;
+       if (CurrentBar->tail != NULL)
+           CurrentBar->tail->next = menu;
+       CurrentBar->tail = menu;
+       if (CurrentBar->head == NULL)
+           CurrentBar->head = menu;    /* fix head */
+       if (menu->prev)
+           menu->x = (menu->prev->x + menu->prev->len + HSPACE);
+    } else {
+       menuitem_t     *item;
+
+       item = rxvt_menuitem_add(parent, path, "", "");
+       if (item == NULL) {
+           free(menu);
+           return parent;
+       }
+#ifdef DEBUG_STRICT
+       assert(item->entry.type == MenuLabel);
+#endif
+       item->entry.type = MenuSubMenu;
+       item->entry.submenu.menu = menu;
+    }
+
+    return menu;
+}
+
+/* INTPROTO */
+void
+rxvt_drawbox_menubar(pR_ int x, int len, int state)
+{
+    GC              top, bot;
+
+    x = Width2Pixel(x);
+    len = Width2Pixel(len + HSPACE);
+    if (x >= R->TermWin.width)
+       return;
+    else if (x + len >= R->TermWin.width)
+       len = (TermWin_TotalWidth() - x);
+
+#ifdef MENUBAR_SHADOW_IN
+    state = -state;
+#endif
+    switch (state) {
+    case +1:
+       top = R->h->topShadowGC;
+       bot = R->h->botShadowGC;
+       break;                  /* SHADOW_OUT */
+    case -1:
+       top = R->h->botShadowGC;
+       bot = R->h->topShadowGC;
+       break;                  /* SHADOW_IN */
+    default:
+       top = bot = R->h->scrollbarGC;
+       break;                  /* neutral */
+    }
+
+    rxvt_Draw_Shadow(R->Xdisplay, R->menuBar.win, top, bot,
+                    x, 0, len, menuBar_TotalHeight());
+}
+
+/* INTPROTO */
+void
+rxvt_drawtriangle(pR_ int x, int y, int state)
+{
+    GC              top, bot;
+    int             w;
+
+#ifdef MENU_SHADOW_IN
+    state = -state;
+#endif
+    switch (state) {
+    case +1:
+       top = R->h->topShadowGC;
+       bot = R->h->botShadowGC;
+       break;                  /* SHADOW_OUT */
+    case -1:
+       top = R->h->botShadowGC;
+       bot = R->h->topShadowGC;
+       break;                  /* SHADOW_IN */
+    default:
+       top = bot = R->h->scrollbarGC;
+       break;                  /* neutral */
+    }
+
+    w = Height2Pixel(1) - 2 * SHADOW;
+
+    x -= SHADOW + (3 * w / 2);
+    y += SHADOW * 3;
+
+    rxvt_Draw_Triangle(R->Xdisplay, R->h->ActiveMenu->win, top, bot, x, y, w,
+                      'r');
+}
+
+/* INTPROTO */
+void
+rxvt_drawbox_menuitem(pR_ int y, int state)
+{
+    GC              top, bot;
+
+#ifdef MENU_SHADOW_IN
+    state = -state;
+#endif
+    switch (state) {
+    case +1:
+       top = R->h->topShadowGC;
+       bot = R->h->botShadowGC;
+       break;                  /* SHADOW_OUT */
+    case -1:
+       top = R->h->botShadowGC;
+       bot = R->h->topShadowGC;
+       break;                  /* SHADOW_IN */
+    default:
+       top = bot = R->h->scrollbarGC;
+       break;                  /* neutral */
+    }
+
+    rxvt_Draw_Shadow(R->Xdisplay, R->h->ActiveMenu->win, top, bot,
+                    SHADOW + 0, SHADOW + y,
+                    R->h->ActiveMenu->w - 2 * (SHADOW),
+                    HEIGHT_TEXT + 2 * SHADOW);
+    XFlush(R->Xdisplay);
+}
+
+#ifdef DEBUG_MENU_LAYOUT
+/* INTPROTO */
+void
+rxvt_print_menu_ancestors(menu_t *menu)
+{
+    if (menu == NULL) {
+       fprintf(stderr, "Top Level menu\n");
+       return;
+    }
+    fprintf(stderr, "menu %s ", menu->name);
+    if (menu->parent != NULL) {
+       menuitem_t     *item;
+
+       for (item = menu->parent->head; item != NULL; item = item->next) {
+           if (item->entry.type == MenuSubMenu
+               && item->entry.submenu.menu == menu) {
+               break;
+           }
+       }
+       if (item == NULL) {
+           fprintf(stderr, "is an orphan!\n");
+           return;
+       }
+    }
+    fprintf(stderr, "\n");
+    rxvt_print_menu_ancestors(menu->parent);
+}
+
+/* INTPROTO */
+void
+rxvt_print_menu_descendants(menu_t *menu)
+{
+    menuitem_t     *item;
+    menu_t         *parent;
+    int             i, level = 0;
+
+    parent = menu;
+    do {
+       level++;
+       parent = parent->parent;
+    }
+    while (parent != NULL);
+
+    for (i = 0; i < level; i++)
+       fprintf(stderr, ">");
+    fprintf(stderr, "%s\n", menu->name);
+
+    for (item = menu->head; item != NULL; item = item->next) {
+       if (item->entry.type == MenuSubMenu) {
+           if (item->entry.submenu.menu == NULL)
+               fprintf(stderr, "> %s == NULL\n", item->name);
+           else
+               rxvt_print_menu_descendants(item->entry.submenu.menu);
+       } else {
+           for (i = 0; i < level; i++)
+               fprintf(stderr, "+");
+           if (item->entry.type == MenuLabel)
+               fprintf(stderr, "label: ");
+           fprintf(stderr, "%s\n", item->name);
+       }
+    }
+
+    for (i = 0; i < level; i++)
+       fprintf(stderr, "<");
+    fprintf(stderr, "\n");
+}
+#endif
+
+/* pop up/down the current menu and redraw the menuBar button */
+/* INTPROTO */
+void
+rxvt_menu_show(pR)
+{
+    int             x, y, xright;
+    menu_t         *ActiveMenu = R->h->ActiveMenu;
+    menuitem_t     *item;
+
+    if (ActiveMenu == NULL)
+       return;
+
+    x = ActiveMenu->x;
+    if (ActiveMenu->parent == NULL) {
+       register int    h;
+
+       rxvt_drawbox_menubar(aR_ x, ActiveMenu->len, -1);
+       x = Width2Pixel(x);
+
+       ActiveMenu->y = 1;
+       ActiveMenu->w = Menu_PixelWidth(ActiveMenu);
+
+       if ((x + ActiveMenu->w) >= R->TermWin.width)
+           x = (TermWin_TotalWidth() - ActiveMenu->w);
+
+       /* find the height */
+       for (h = 0, item = ActiveMenu->head; item != NULL; item = item->next)
+           h += isSeparator(item->name) ? HEIGHT_SEPARATOR
+                                        : HEIGHT_TEXT + 2 * SHADOW;
+       ActiveMenu->h = h + 2 * SHADOW;
+    }
+    if (ActiveMenu->win == None) {
+       ActiveMenu->win = XCreateSimpleWindow(R->Xdisplay, R->TermWin.vt,
+                                             x, ActiveMenu->y,
+                                             ActiveMenu->w, ActiveMenu->h,
+                                             0,
+                                             R->PixColors[Color_fg],
+                                             R->PixColors[Color_scroll]);
+       XMapWindow(R->Xdisplay, ActiveMenu->win);
+    }
+    rxvt_Draw_Shadow(R->Xdisplay, ActiveMenu->win,
+                    R->h->topShadowGC, R->h->botShadowGC,
+                    0, 0, ActiveMenu->w, ActiveMenu->h);
+
+/* determine the correct right-alignment */
+    for (xright = 0, item = ActiveMenu->head; item != NULL; item = item->next)
+       if (item->len2 > xright)
+           xright = item->len2;
+
+    for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) {
+       const int       xoff = (SHADOW + Width2Pixel(HSPACE) / 2);
+       register int    h;
+       GC              gc = R->h->menubarGC;
+
+       if (isSeparator(item->name)) {
+           rxvt_Draw_Shadow(R->Xdisplay, ActiveMenu->win,
+                            R->h->topShadowGC, R->h->botShadowGC,
+                            SHADOW, y + SHADOW + 1,
+                            ActiveMenu->w - 2 * SHADOW, 0);
+           h = HEIGHT_SEPARATOR;
+       } else {
+           char           *name = item->name;
+           int             len = item->len;
+
+           if (item->entry.type == MenuLabel) {
+               gc = R->h->botShadowGC;
+           } else if (item->entry.type == MenuSubMenu) {
+               int             x1, y1;
+               menuitem_t     *it;
+               menu_t         *menu = item->entry.submenu.menu;
+
+               rxvt_drawtriangle(aR_ ActiveMenu->w, y, +1);
+
+               name = menu->name;
+               len = menu->len;
+
+               y1 = ActiveMenu->y + y;
+
+               menu->w = Menu_PixelWidth(menu);
+
+               /* place sub-menu at midpoint of parent menu */
+               x1 = ActiveMenu->w / 2;
+               if (x1 > menu->w)       /* right-flush menu if too small */
+                   x1 += (x1 - menu->w);
+               x1 += x;
+
+               /* find the height of this submenu */
+               for (h = 0, it = menu->head; it != NULL; it = it->next)
+                   h += isSeparator(it->name) ? HEIGHT_SEPARATOR
+                                              : HEIGHT_TEXT + 2 * SHADOW;
+               menu->h = h + 2 * SHADOW;
+
+               /* ensure menu is in window limits */
+               if ((x1 + menu->w) >= R->TermWin.width)
+                   x1 = (TermWin_TotalWidth() - menu->w);
+
+               if ((y1 + menu->h) >= R->TermWin.height)
+                   y1 = (TermWin_TotalHeight() - menu->h);
+
+               menu->x = (x1 < 0 ? 0 : x1);
+               menu->y = (y1 < 0 ? 0 : y1);
+           } else if (item->name2 && !STRCMP(name, item->name2))
+               name = NULL;
+
+           if (len && name) {
+#ifdef USE_XIM
+               if (R->TermWin.fontset)
+                   XmbDrawString(R->Xdisplay,
+                                 ActiveMenu->win, R->TermWin.fontset,
+                                 gc, xoff,
+                                 2 * SHADOW + y + R->TermWin.font->ascent + 1,
+                                 name, len);
+               else
+#endif
+                   XDrawString(R->Xdisplay, ActiveMenu->win, gc, xoff,
+                               2 * SHADOW + y + R->TermWin.font->ascent + 1,
+                               name, len);
+           }
+
+           len = item->len2;
+           name = item->name2;
+           if (len && name) {
+#ifdef USE_XIM
+               if (R->TermWin.fontset)
+                   XmbDrawString(R->Xdisplay,
+                                 ActiveMenu->win, R->TermWin.fontset,
+                                 gc,
+                                 ActiveMenu->w - (xoff + Width2Pixel(xright)),
+                                 2 * SHADOW + y + R->TermWin.font->ascent + 1,
+                                 name, len);
+               else
+#endif
+                   XDrawString(R->Xdisplay, ActiveMenu->win, gc,
+                               ActiveMenu->w - (xoff + Width2Pixel(xright)),
+                               2 * SHADOW + y + R->TermWin.font->ascent + 1,
+                               name, len);
+           }
+           h = HEIGHT_TEXT + 2 * SHADOW;
+       }
+       y += h;
+    }
+}
+
+/* INTPROTO */
+void
+rxvt_menu_display(pR_ void (*update)(rxvt_t *))
+{
+    menu_t         *ActiveMenu = R->h->ActiveMenu;
+
+    if (ActiveMenu == NULL)
+       return;
+    if (ActiveMenu->win != None)
+       XDestroyWindow(R->Xdisplay, ActiveMenu->win);
+    ActiveMenu->win = None;
+    ActiveMenu->item = NULL;
+
+    if (ActiveMenu->parent == NULL)
+       rxvt_drawbox_menubar(aR_ ActiveMenu->x, ActiveMenu->len, +1);
+    R->h->ActiveMenu = ActiveMenu->parent;
+    update(r);
+}
+
+/* INTPROTO */
+void
+rxvt_menu_hide_all(pR)
+{
+    rxvt_menu_display(aR_ rxvt_menu_hide_all);
+}
+
+/* INTPROTO */
+void
+rxvt_menu_hide(pR)
+{
+    rxvt_menu_display(aR_ rxvt_menu_show);
+}
+
+/* INTPROTO */
+void
+rxvt_menu_clear(pR_ menu_t *menu)
+{
+    if (menu != NULL) {
+       menuitem_t     *item = menu->tail;
+
+       while (item != NULL) {
+           rxvt_menuitem_free(aR_ menu, item);
+           /* it didn't get freed ... why? */
+           if (item == menu->tail)
+               return;
+           item = menu->tail;
+       }
+       menu->width = 0;
+    }
+}
+
+/* INTPROTO */
+void
+rxvt_menubar_clear(pR)
+{
+    bar_t          *CurrentBar = R->h->CurrentBar;
+
+    if (CurrentBar != NULL) {
+       menu_t         *menu = CurrentBar->tail;
+
+       while (menu != NULL) {
+           menu_t         *prev = menu->prev;
+
+           rxvt_menu_delete(aR_ menu);
+           menu = prev;
+       }
+       CurrentBar->head = CurrentBar->tail = NULL;
+
+       if (CurrentBar->title) {
+           free(CurrentBar->title);
+           CurrentBar->title = NULL;
+       }
+       rxvt_menuarrow_free(aR_ 0);     /* remove all arrow functions */
+    }
+    R->h->ActiveMenu = NULL;
+}
+
+#if (MENUBAR_MAX > 1)
+/* find if menu already exists */
+/* INTPROTO */
+bar_t          *
+rxvt_menubar_find(pR_ const char *name)
+{
+    bar_t          *bar = R->h->CurrentBar;
+
+#ifdef DEBUG_MENUBAR_STACKING
+    fprintf(stderr, "looking for [menu:%s] ...", name ? name : "(nil)");
+#endif
+    if (bar == NULL || name == NULL)
+       return NULL;
+
+    if (STRLEN(name) && STRCMP(name, "*")) {
+       do {
+           if (!STRCMP(bar->name, name)) {
+#ifdef DEBUG_MENUBAR_STACKING
+               fprintf(stderr, " found!\n");
+#endif
+               return bar;
+           }
+           bar = bar->next;
+       }
+       while (bar != R->h->CurrentBar);
+       bar = NULL;
+    }
+#ifdef DEBUG_MENUBAR_STACKING
+    fprintf(stderr, "%s found!\n", (bar ? "" : " NOT"));
+#endif
+
+    return bar;
+}
+
+/* INTPROTO */
+int
+rxvt_menubar_push(pR_ const char *name)
+{
+    int             ret = 1;
+    bar_t          *bar;
+
+    if (R->h->CurrentBar == NULL) {
+       /* allocate first one */
+       bar = (bar_t *) rxvt_malloc(sizeof(bar_t));
+
+       MEMSET(bar, 0, sizeof(bar_t));
+       /* circular linked-list */
+       bar->next = bar->prev = bar;
+       bar->head = bar->tail = NULL;
+       bar->title = NULL;
+       R->h->CurrentBar = bar;
+       R->h->Nbars++;
+
+       rxvt_menubar_clear(aR);
+    } else {
+       /* find if menu already exists */
+       bar = rxvt_menubar_find(aR_ name);
+       if (bar != NULL) {
+           /* found it, use it */
+           R->h->CurrentBar = bar;
+       } else {
+           /* create if needed, or reuse the existing empty menubar */
+           if (R->h->CurrentBar->head != NULL) {
+               /* need to malloc another one */
+               if (R->h->Nbars < MENUBAR_MAX)
+                   bar = (bar_t *) rxvt_malloc(sizeof(bar_t));
+               else
+                   bar = NULL;
+
+               /* malloc failed or too many menubars, reuse another */
+               if (bar == NULL) {
+                   bar = R->h->CurrentBar->next;
+                   ret = -1;
+               } else {
+                   bar->head = bar->tail = NULL;
+                   bar->title = NULL;
+
+                   bar->next = R->h->CurrentBar->next;
+                   R->h->CurrentBar->next = bar;
+                   bar->prev = R->h->CurrentBar;
+                   bar->next->prev = bar;
+
+                   R->h->Nbars++;
+               }
+               R->h->CurrentBar = bar;
+
+           }
+           rxvt_menubar_clear(aR);
+       }
+    }
+
+/* give menubar this name */
+    STRNCPY(R->h->CurrentBar->name, name, MAXNAME);
+    R->h->CurrentBar->name[MAXNAME - 1] = '\0';
+
+    return ret;
+}
+
+/* switch to a menu called NAME and remove it */
+/* INTPROTO */
+void
+rxvt_menubar_remove(pR_ const char *name)
+{
+    bar_t          *bar;
+
+    if ((bar = rxvt_menubar_find(aR_ name)) == NULL)
+       return;
+    R->h->CurrentBar = bar;
+
+    do {
+       rxvt_menubar_clear(aR);
+       /*
+        * pop a menubar, clean it up first
+        */
+       if (R->h->CurrentBar != NULL) {
+           bar_t          *prev = R->h->CurrentBar->prev;
+           bar_t          *next = R->h->CurrentBar->next;
+
+           if (prev == next && prev == R->h->CurrentBar) {     /* only 1 left */
+               prev = NULL;
+               R->h->Nbars = 0;        /* safety */
+           } else {
+               next->prev = prev;
+               prev->next = next;
+               R->h->Nbars--;
+           }
+
+           free(R->h->CurrentBar);
+           R->h->CurrentBar = prev;
+       }
+    }
+    while (R->h->CurrentBar && !STRCMP(name, "*"));
+}
+
+/* INTPROTO */
+void
+rxvt_action_decode(FILE *fp, action_t *act)
+{
+    unsigned char  *str;
+    short           len;
+
+    if (act == NULL || (len = act->len) == 0 || (str = act->str) == NULL)
+       return;
+
+    if (act->type == MenuTerminalAction) {
+       fprintf(fp, "^@");
+       /* can strip trailing ^G from XTerm sequence */
+       if (str[0] == C0_ESC && str[1] == ']' && str[len - 1] == C0_BEL)
+           len--;
+    } else if (str[0] == C0_ESC) {
+       switch (str[1]) {
+       case '[':
+       case ']':
+           break;
+
+       case 'x':
+           /* can strip trailing '\r' from M-x sequence */
+           if (str[len - 1] == '\r')
+               len--;
+           /* FALLTHROUGH */
+
+       default:
+           fprintf(fp, "M-");  /* meta prefix */
+           str++;
+           len--;
+           break;
+       }
+    }
+/*
+ * control character form is preferred, since backslash-escaping
+ * can be really ugly looking when the backslashes themselves also
+ * have to be escaped to avoid Shell (or whatever scripting
+ * language) interpretation
+ */
+    while (len > 0) {
+       unsigned char   ch = *str++;
+
+       switch (ch) {
+       case C0_ESC:
+           fprintf(fp, "\\E");
+           break;              /* escape */
+       case '\r':
+           fprintf(fp, "\\r");
+           break;              /* carriage-return */
+       case '\\':
+           fprintf(fp, "\\\\");
+           break;              /* backslash */
+       case '^':
+           fprintf(fp, "\\^");
+           break;              /* caret */
+       case 127:
+           fprintf(fp, "^?");
+       default:
+           if (ch <= 31)
+               fprintf(fp, "^%c", ('@' + ch));
+           else if (ch > 127)
+               fprintf(fp, "\\%o", ch);
+           else
+               fprintf(fp, "%c", ch);
+           break;
+       }
+       len--;
+    }
+    fprintf(fp, "\n");
+}
+
+/* INTPROTO */
+void
+rxvt_menu_dump(FILE *fp, menu_t *menu)
+{
+    menuitem_t     *item;
+
+/* create a new menu and clear it */
+    fprintf(fp, (menu->parent ? "./%s/*\n" : "/%s/*\n"), menu->name);
+
+    for (item = menu->head; item != NULL; item = item->next) {
+       switch (item->entry.type) {
+       case MenuSubMenu:
+           if (item->entry.submenu.menu == NULL)
+               fprintf(fp, "> %s == NULL\n", item->name);
+           else
+               rxvt_menu_dump(fp, item->entry.submenu.menu);
+           break;
+
+       case MenuLabel:
+           fprintf(fp, "{%s}\n", (STRLEN(item->name) ? item->name : "-"));
+           break;
+
+       case MenuTerminalAction:
+       case MenuAction:
+           fprintf(fp, "{%s}", item->name);
+           if (item->name2 != NULL && STRLEN(item->name2))
+               fprintf(fp, "{%s}", item->name2);
+           fprintf(fp, "\t");
+           rxvt_action_decode(fp, &(item->entry.action));
+           break;
+       }
+    }
+
+    fprintf(fp, (menu->parent ? "../\n" : "/\n\n"));
+}
+
+/* INTPROTO */
+void
+rxvt_menubar_dump(pR_ FILE *fp)
+{
+    bar_t          *bar = R->h->CurrentBar;
+    time_t          t;
+
+    if (bar == NULL || fp == NULL)
+       return;
+    time(&t);
+
+    fprintf(fp,
+           "# " APL_SUBCLASS " (%s)  Pid: %u\n# Date: %s\n\n",
+           R->h->rs[Rs_name], (unsigned int)getpid(), ctime(&t));
+
+/* dump in reverse order */
+    bar = R->h->CurrentBar->prev;
+    do {
+       menu_t         *menu;
+       int             i;
+
+       fprintf(fp, "[menu:%s]\n", bar->name);
+
+       if (bar->title != NULL)
+           fprintf(fp, "[title:%s]\n", bar->title);
+
+       for (i = 0; i < NARROWS; i++) {
+           switch (bar->arrows[i].type) {
+           case MenuTerminalAction:
+           case MenuAction:
+               fprintf(fp, "<%c>", Arrows[i].name);
+               rxvt_action_decode(fp, &(bar->arrows[i]));
+               break;
+           }
+       }
+       fprintf(fp, "\n");
+
+       for (menu = bar->head; menu != NULL; menu = menu->next)
+           rxvt_menu_dump(fp, menu);
+
+       fprintf(fp, "\n[done:%s]\n\n", bar->name);
+       bar = bar->prev;
+    }
+    while (bar != R->h->CurrentBar->prev);
+}
+#endif                         /* (MENUBAR_MAX > 1) */
+
+/*
+ * read in menubar commands from FILENAME
+ * ignore all input before the tag line [menu] or [menu:???]
+ *
+ * Note that since File_find () is used, FILENAME can be semi-colon
+ * delimited such that the second part can refer to a tag
+ * so that a large `database' of menus can be collected together
+ *
+ * FILENAME = "file"
+ * FILENAME = "file;"
+ *      read `file' starting with first [menu] or [menu:???] line
+ *
+ * FILENAME = "file;tag"
+ *      read `file' starting with [menu:tag]
+ */
+/* EXTPROTO */
+void
+rxvt_menubar_read(pR_ const char *filename)
+{
+/* read in a menu from a file */
+    FILE           *fp;
+    char            buffer[256];
+    char           *p, *file, *tag = NULL;
+
+    file = (char *)rxvt_File_find(filename, ".menu", R->h->rs[Rs_path]);
+    if (file == NULL)
+       return;
+    fp = fopen(file, "rb");
+    free(file);
+    if (fp == NULL)
+       return;
+
+#if (MENUBAR_MAX > 1)
+/* semi-colon delimited */
+    if ((tag = STRCHR(filename, ';')) != NULL) {
+       tag++;
+       if (*tag == '\0')
+           tag = NULL;
+    }
+#endif                         /* (MENUBAR_MAX > 1) */
+#ifdef DEBUG_MENU
+    fprintf(stderr, "[read:%s]\n", p);
+    if (tag)
+       fprintf(stderr, "looking for [menu:%s]\n", tag);
+#endif
+
+    while ((p = fgets(buffer, sizeof(buffer), fp)) != NULL) {
+       int             n;
+
+       if ((n = rxvt_Str_match(p, "[menu")) != 0) {
+           if (tag) {
+               /* looking for [menu:tag] */
+               if (p[n] == ':' && p[n + 1] != ']') {
+                   n++;
+                   n += rxvt_Str_match(p + n, tag);
+                   if (p[n] == ']') {
+#ifdef DEBUG_MENU
+                       fprintf(stderr, "[menu:%s]\n", tag);
+#endif
+                       break;
+                   }
+               }
+           } else if (p[n] == ':' || p[n] == ']')
+               break;
+       }
+    }
+
+/* found [menu], [menu:???] tag */
+    while (p != NULL) {
+       int             n;
+
+#ifdef DEBUG_MENU
+       fprintf(stderr, "read line = %s\n", p);
+#endif
+
+       /* looking for [done:tag] or [done:] */
+       if ((n = rxvt_Str_match(p, "[done")) != 0) {
+           if (p[n] == ']') {
+               R->h->menu_readonly = 1;
+               break;
+           } else if (p[n] == ':') {
+               n++;
+               if (p[n] == ']') {
+                   R->h->menu_readonly = 1;
+                   break;
+               } else if (tag) {
+                   n += rxvt_Str_match(p + n, tag);
+                   if (p[n] == ']') {
+#ifdef DEBUG_MENU
+                       fprintf(stderr, "[done:%s]\n", tag);
+#endif
+                       R->h->menu_readonly = 1;
+                       break;
+                   }
+               } else {
+                   /* what? ... skip this line */
+                   p[0] = COMMENT_CHAR;
+               }
+           }
+       }
+       /*
+        * remove leading/trailing space
+        * and strip-off leading/trailing quotes
+        * skip blank or comment lines
+        */
+       rxvt_Str_trim(p);
+       if (*p && *p != '#') {
+           R->h->menu_readonly = 0;    /* if case we read another file */
+           rxvt_menubar_dispatch(aR_ p);
+       }
+       /* get another line */
+       p = fgets(buffer, sizeof(buffer), fp);
+    }
+
+    fclose(fp);
+}
+
+/*
+ * user interface for building/deleting and otherwise managing menus
+ */
+/* EXTPROTO */
+void
+rxvt_menubar_dispatch(pR_ char *str)
+{
+    int             n, cmd;
+    char           *path, *name, *name2;
+
+    if (menubar_visible(r) && R->h->ActiveMenu != NULL)
+       rxvt_menubar_expose(aR);
+    else
+       R->h->ActiveMenu = NULL;
+
+    cmd = *str;
+    switch (cmd) {
+    case '.':
+    case '/':                  /* absolute & relative path */
+    case MENUITEM_BEG:         /* menuitem */
+       /* add `+' prefix for these cases */
+       cmd = '+';
+       break;
+
+    case '+':
+    case '-':
+       str++;                  /* skip cmd character */
+       break;
+
+    case '<':
+#if (MENUBAR_MAX > 1)
+       if (R->h->CurrentBar == NULL)
+           break;
+#endif                         /* (MENUBAR_MAX > 1) */
+       if (str[1] && str[2] == '>')    /* arrow commands */
+           rxvt_menuarrow_add(aR_ str);
+       break;
+
+    case '[':                  /* extended command */
+       while (str[0] == '[') {
+           char           *next = (++str);     /* skip leading '[' */
+
+           if (str[0] == ':') {        /* [:command:] */
+               do {
+                   next++;
+                   if ((next = STRCHR(next, ':')) == NULL)
+                       return; /* parse error */
+               }
+               while (next[1] != ']');
+               /* remove and skip ':]' */
+               *next = '\0';
+               next += 2;
+           } else {
+               if ((next = STRCHR(next, ']')) == NULL)
+                   return;     /* parse error */
+               /* remove and skip ']' */
+               *next = '\0';
+               next++;
+           }
+
+           if (str[0] == ':') {
+               int             saved;
+
+               /* try and dispatch it, regardless of read/write status */
+               saved = R->h->menu_readonly;
+               R->h->menu_readonly = 0;
+               rxvt_menubar_dispatch(aR_ str + 1);
+               R->h->menu_readonly = saved;
+           }
+           /* these ones don't require menu stacking */
+           else if (!STRCMP(str, "clear")) {
+               rxvt_menubar_clear(aR);
+           } else if (!STRCMP(str, "done") || rxvt_Str_match(str, "done:")) {
+               R->h->menu_readonly = 1;
+           } else if (!STRCMP(str, "show")) {
+               rxvt_map_menuBar(aR_ 1);
+               R->h->menu_readonly = 1;
+           } else if (!STRCMP(str, "hide")) {
+               rxvt_map_menuBar(aR_ 0);
+               R->h->menu_readonly = 1;
+           } else if ((n = rxvt_Str_match(str, "read:")) != 0) {
+               /* read in a menu from a file */
+               str += n;
+               rxvt_menubar_read(aR_ str);
+           } else if ((n = rxvt_Str_match(str, "title:")) != 0) {
+               str += n;
+               if (R->h->CurrentBar != NULL && !R->h->menu_readonly) {
+                   if (*str) {
+                       name = rxvt_realloc(R->h->CurrentBar->title,
+                                           STRLEN(str) + 1);
+                       if (name != NULL) {
+                           STRCPY(name, str);
+                           R->h->CurrentBar->title = name;
+                       }
+                       rxvt_menubar_expose(aR);
+                   } else {
+                       free(R->h->CurrentBar->title);
+                       R->h->CurrentBar->title = NULL;
+                   }
+               }
+           } else if ((n = rxvt_Str_match(str, "pixmap:")) != 0) {
+               str += n;
+               rxvt_xterm_seq(aR_ XTerm_Pixmap, str, CHAR_ST);
+           }
+#if (MENUBAR_MAX > 1)
+           else if ((n = rxvt_Str_match(str, "rm")) != 0) {
+               str += n;
+               switch (str[0]) {
+               case ':':
+                   str++;
+               /* FALLTHROUGH */
+               case '\0':
+               /* FALLTHROUGH */
+               case '*':
+                   rxvt_menubar_remove(aR_ str);
+                   break;
+               }
+               R->h->menu_readonly = 1;
+           } else if ((n = rxvt_Str_match(str, "menu")) != 0) {
+               str += n;
+               switch (str[0]) {
+               case ':':
+                   str++;
+                   /* add/access menuBar */
+                   if (*str != '\0' && *str != '*')
+                       rxvt_menubar_push(aR_ str);
+                   break;
+               default:
+                   if (R->h->CurrentBar == NULL) {
+                       rxvt_menubar_push(aR_ "default");
+                   }
+               }
+
+               if (R->h->CurrentBar != NULL)
+                   R->h->menu_readonly = 0;    /* allow menu build commands */
+           } else if (!STRCMP(str, "dump")) {
+               /* dump current menubars to a file */
+               FILE           *fp;
+
+               /* enough space to hold the results */
+               char            buffer[32];
+
+               sprintf(buffer, "/tmp/" APL_SUBCLASS "-%u",
+                       (unsigned int)getpid());
+
+               if ((fp = fopen(buffer, "wb")) != NULL) {
+                   rxvt_xterm_seq(aR_ XTerm_title, buffer, CHAR_ST);
+                   rxvt_menubar_dump(aR_ fp);
+                   fclose(fp);
+               }
+           } else if (!STRCMP(str, "next")) {
+               if (R->h->CurrentBar) {
+                   R->h->CurrentBar = R->h->CurrentBar->next;
+                   R->h->menu_readonly = 1;
+               }
+           } else if (!STRCMP(str, "prev")) {
+               if (R->h->CurrentBar) {
+                   R->h->CurrentBar = R->h->CurrentBar->prev;
+                   R->h->menu_readonly = 1;
+               }
+           } else if (!STRCMP(str, "swap")) {
+               /* swap the top 2 menus */
+               if (R->h->CurrentBar) {
+                   bar_t          *cbprev = R->h->CurrentBar->prev;
+                   bar_t          *cbnext = R->h->CurrentBar->next;
+
+                   cbprev->next = cbnext;
+                   cbnext->prev = cbprev;
+
+                   R->h->CurrentBar->next = cbprev;
+                   R->h->CurrentBar->prev = cbprev->prev;
+
+                   cbprev->prev->next = R->h->CurrentBar;
+                   cbprev->prev = R->h->CurrentBar;
+
+                   R->h->CurrentBar = cbprev;
+                   R->h->menu_readonly = 1;
+               }
+           }
+#endif                         /* (MENUBAR_MAX > 1) */
+           str = next;
+
+           R->h->BuildMenu = R->h->ActiveMenu = NULL;
+           rxvt_menubar_expose(aR);
+#ifdef DEBUG_MENUBAR_STACKING
+           fprintf(stderr, "menus are read%s\n",
+                   R->h->menu_readonly ? "only" : "/write");
+#endif
+       }
+       return;
+       break;
+    }
+
+#if (MENUBAR_MAX > 1)
+    if (R->h->CurrentBar == NULL)
+       return;
+    if (R->h->menu_readonly) {
+#ifdef DEBUG_MENUBAR_STACKING
+       fprintf(stderr, "menus are read%s\n",
+               R->h->menu_readonly ? "only" : "/write");
+#endif
+       return;
+    }
+#endif                         /* (MENUBAR_MAX > 1) */
+
+    switch (cmd) {
+    case '+':
+    case '-':
+       path = name = str;
+
+       name2 = NULL;
+       /* parse STR, allow spaces inside (name)  */
+       if (path[0] != '\0') {
+           name = STRCHR(path, MENUITEM_BEG);
+           str = STRCHR(path, MENUITEM_END);
+           if (name != NULL || str != NULL) {
+               if (name == NULL || str == NULL || str <= (name + 1)
+                   || (name > path && name[-1] != '/')) {
+                   rxvt_print_error("menu error <%s>\n", path);
+                   break;
+               }
+               if (str[1] == MENUITEM_BEG) {
+                   name2 = (str + 2);
+                   str = STRCHR(name2, MENUITEM_END);
+
+                   if (str == NULL) {
+                       rxvt_print_error("menu error <%s>\n", path);
+                       break;
+                   }
+                   name2[-2] = '\0';   /* remove prev MENUITEM_END */
+               }
+               if (name > path && name[-1] == '/')
+                   name[-1] = '\0';
+
+               *name++ = '\0'; /* delimit */
+               *str++ = '\0';  /* delimit */
+
+               while (isspace(*str))
+                   str++;      /* skip space */
+           }
+#ifdef DEBUG_MENU
+           fprintf(stderr,
+                   "`%c' path = <%s>, name = <%s>, name2 = <%s>, action = <%s>\n",
+                   cmd, (path ? path : "(nil)"), (name ? name : "(nil)"),
+                   (name2 ? name2 : "(nil)"), (str ? str : "(nil)")
+               );
+#endif
+       }
+       /* process the different commands */
+       switch (cmd) {
+       case '+':               /* add/replace existing menu or menuitem */
+           if (path[0] != '\0') {
+               int             len;
+
+               path = rxvt_menu_find_base(aR_ &(R->h->BuildMenu), path);
+               len = STRLEN(path);
+
+               /* don't allow menus called `*' */
+               if (path[0] == '*') {
+                   rxvt_menu_clear(aR_ R->h->BuildMenu);
+                   break;
+               } else if (len >= 2 && !STRCMP((path + len - 2), "/*")) {
+                   path[len - 2] = '\0';
+               }
+               if (path[0] != '\0')
+                   R->h->BuildMenu = rxvt_menu_add(aR_ R->h->BuildMenu, path);
+           }
+           if (name != NULL && name[0] != '\0')
+               rxvt_menuitem_add(R->h->BuildMenu,
+                                 (STRCMP(name, SEPARATOR_NAME) ? name : ""),
+                                 name2, str);
+           break;
+
+       case '-':               /* delete menu entry */
+           if (!STRCMP(path, "/*") && (name == NULL || name[0] == '\0')) {
+               rxvt_menubar_clear(aR);
+               R->h->BuildMenu = NULL;
+               rxvt_menubar_expose(aR);
+               break;
+           } else if (path[0] != '\0') {
+               int             len;
+               menu_t         *menu = R->h->BuildMenu;
+
+               path = rxvt_menu_find_base(aR_ &menu, path);
+               len = STRLEN(path);
+
+               /* submenu called `*' clears all menu items */
+               if (path[0] == '*') {
+                   rxvt_menu_clear(aR_ menu);
+                   break;      /* done */
+               } else if (len >= 2 && !STRCMP(&path[len - 2], "/*")) {
+                   /* done */
+                   break;
+               } else if (path[0] != '\0') {
+                   R->h->BuildMenu = NULL;
+                   break;
+               } else
+                   R->h->BuildMenu = menu;
+           }
+           if (R->h->BuildMenu != NULL) {
+               if (name == NULL || name[0] == '\0')
+                   R->h->BuildMenu = rxvt_menu_delete(aR_ R->h->BuildMenu);
+               else {
+                   const char     *n1;
+                   menuitem_t     *item;
+                   menu_t         *BuildMenu = R->h->BuildMenu;
+
+                   n1 = STRCMP(name, SEPARATOR_NAME) ? name : "";
+                   item = rxvt_menuitem_find(BuildMenu, n1);
+                   if (item != NULL && item->entry.type != MenuSubMenu) {
+                       rxvt_menuitem_free(aR_ BuildMenu, item);
+
+                       /* fix up the width */
+                       BuildMenu->width = 0;
+                       for (item = BuildMenu->head; item != NULL;
+                            item = item->next) {
+                           short           l = item->len + item->len2;
+
+                           MAX_IT(BuildMenu->width, l);
+                       }
+                   }
+               }
+               rxvt_menubar_expose(aR);
+           }
+           break;
+       }
+       break;
+    }
+}
+
+/* INTPROTO */
+void
+rxvt_draw_Arrows(pR_ int name, int state)
+{
+    GC              top, bot;
+
+    int             i;
+
+#ifdef MENU_SHADOW_IN
+    state = -state;
+#endif
+    switch (state) {
+    case +1:
+       top = R->h->topShadowGC;
+       bot = R->h->botShadowGC;
+       break;                  /* SHADOW_OUT */
+    case -1:
+       top = R->h->botShadowGC;
+       bot = R->h->topShadowGC;
+       break;                  /* SHADOW_IN */
+    default:
+       top = bot = R->h->scrollbarGC;
+       break;                  /* neutral */
+    }
+
+    if (!R->h->Arrows_x)
+       return;
+
+    for (i = 0; i < NARROWS; i++) {
+       const int       w = Width2Pixel(1);
+       const int       y = (menuBar_TotalHeight() - w) / 2;
+       int             x = R->h->Arrows_x + (5 * Width2Pixel(i)) / 4;
+
+       if (!name || name == Arrows[i].name)
+           rxvt_Draw_Triangle(R->Xdisplay, R->menuBar.win, top, bot, x, y, w,
+                              Arrows[i].name);
+    }
+    XFlush(R->Xdisplay);
+}
+
+/* EXTPROTO */
+void
+rxvt_menubar_expose(pR)
+{
+    menu_t         *menu;
+    int             x;
+
+    if (!menubar_visible(r) || R->menuBar.win == 0)
+       return;
+
+    if (R->h->menubarGC == None) {
+       /* Create the graphics context */
+       XGCValues       gcvalue;
+
+       gcvalue.font = R->TermWin.font->fid;
+
+       gcvalue.foreground = (XDEPTH <= 2 ? R->PixColors[Color_fg]
+                                         : R->PixColors[Color_Black]);
+       R->h->menubarGC = XCreateGC(R->Xdisplay, R->menuBar.win,
+                                   GCForeground | GCFont, &gcvalue);
+
+    }
+/* make sure the font is correct */
+    XSetFont(R->Xdisplay, R->h->menubarGC, R->TermWin.font->fid);
+    XSetFont(R->Xdisplay, R->h->botShadowGC, R->TermWin.font->fid);
+    XClearWindow(R->Xdisplay, R->menuBar.win);
+
+    rxvt_menu_hide_all(aR);
+
+    x = 0;
+    if (R->h->CurrentBar != NULL) {
+       for (menu = R->h->CurrentBar->head; menu != NULL; menu = menu->next) {
+           int             len = menu->len;
+
+           x = (menu->x + menu->len + HSPACE);
+
+#ifdef DEBUG_MENU_LAYOUT
+           rxvt_print_menu_descendants(menu);
+#endif
+
+           if (x >= R->TermWin.ncol)
+               len = (R->TermWin.ncol - (menu->x + HSPACE));
+
+           rxvt_drawbox_menubar(aR_ menu->x, len, +1);
+#ifdef USE_XIM
+           if (R->TermWin.fontset)
+               XmbDrawString(R->Xdisplay,
+                             R->menuBar.win, R->TermWin.fontset,
+                             R->h->menubarGC,
+                             (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2),
+                             menuBar_height() - SHADOW, menu->name, len);
+           else
+#endif
+               XDrawString(R->Xdisplay, R->menuBar.win, R->h->menubarGC,
+                           (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2),
+                           menuBar_height() - SHADOW, menu->name, len);
+
+           if (x >= R->TermWin.ncol)
+               break;
+       }
+    }
+    rxvt_drawbox_menubar(aR_ x, R->TermWin.ncol, (R->h->CurrentBar ? +1 : -1));
+
+/* add the menuBar title, if it exists and there's plenty of room */
+    R->h->Arrows_x = 0;
+    if (x < R->TermWin.ncol) {
+       const char     *str;
+       int             ncol;
+       unsigned int    len;
+       char            title[256];
+
+       ncol = (int)R->TermWin.ncol;
+       if (x < (ncol - (NARROWS + 1))) {
+           ncol -= (NARROWS + 1);
+           R->h->Arrows_x = Width2Pixel(ncol);
+       }
+       rxvt_draw_Arrows(aR_ 0, +1);
+
+       str = (R->h->CurrentBar
+              && R->h->CurrentBar->title) ? R->h->CurrentBar->title : "%n-%v";
+       for (len = 0; str[0] && len < sizeof(title) - 1; str++) {
+           const char     *s = NULL;
+
+           switch (str[0]) {
+           case '%':
+               str++;
+               switch (str[0]) {
+               case 'n':
+                   s = R->h->rs[Rs_name];
+                   break;      /* resource name */
+               case 'v':
+                   s = VERSION;
+                   break;      /* version number */
+               case '%':
+                   s = "%";
+                   break;      /* literal '%' */
+               }
+               if (s != NULL)
+                   while (*s && len < sizeof(title) - 1)
+                       title[len++] = *s++;
+               break;
+
+           default:
+               title[len++] = str[0];
+               break;
+           }
+       }
+       title[len] = '\0';
+
+       ncol -= (x + len + HSPACE);
+       if (len > 0 && ncol >= 0) {
+#ifdef USE_XIM
+           if (R->TermWin.fontset)
+               XmbDrawString(R->Xdisplay,
+                             R->menuBar.win, R->TermWin.fontset,
+                             R->h->menubarGC,
+                             Width2Pixel(x) + Width2Pixel(ncol + HSPACE) / 2,
+                             menuBar_height() - SHADOW, title, len);
+           else
+#endif
+               XDrawString(R->Xdisplay, R->menuBar.win, R->h->menubarGC,
+                           Width2Pixel(x) + Width2Pixel(ncol + HSPACE) / 2,
+                           menuBar_height() - SHADOW, title, len);
+       }
+    }
+}
+
+/* INTPROTO */
+int
+rxvt_menubar_mapping(pR_ int map)
+{
+    int             change = 0;
+
+    if (map && !menubar_visible(r)) {
+       R->menuBar.state = 1;
+       if (R->menuBar.win == 0)
+           return 0;
+       XMapWindow(R->Xdisplay, R->menuBar.win);
+       change = 1;
+    } else if (!map && menubar_visible(r)) {
+       rxvt_menubar_expose(aR);
+       R->menuBar.state = 0;
+       XUnmapWindow(R->Xdisplay, R->menuBar.win);
+       change = 1;
+    } else
+       rxvt_menubar_expose(aR);
+
+    return change;
+}
+
+/* INTPROTO */
+int
+rxvt_menu_select(pR_ XButtonEvent *ev)
+{
+    menuitem_t     *thisitem, *item = NULL;
+    int             this_y, y;
+    menu_t         *ActiveMenu = R->h->ActiveMenu;
+
+    Window          unused_root, unused_child;
+    int             unused_root_x, unused_root_y;
+    unsigned int    unused_mask;
+
+    if (ActiveMenu == NULL)
+       return 0;
+
+    XQueryPointer(R->Xdisplay, ActiveMenu->win,
+                 &unused_root, &unused_child,
+                 &unused_root_x, &unused_root_y,
+                 &(ev->x), &(ev->y), &unused_mask);
+
+    if (ActiveMenu->parent != NULL && (ev->x < 0 || ev->y < 0)) {
+       rxvt_menu_hide(aR);
+       return 1;
+    }
+/* determine the menu item corresponding to the Y index */
+    y = SHADOW;
+    if (ev->x >= 0 && ev->x <= (ActiveMenu->w - SHADOW)) {
+       for (item = ActiveMenu->head; item != NULL; item = item->next) {
+           int             h = HEIGHT_TEXT + 2 * SHADOW;
+
+           if (isSeparator(item->name))
+               h = HEIGHT_SEPARATOR;
+           else if (ev->y >= y && ev->y < (y + h))
+               break;
+           y += h;
+       }
+    }
+    if (item == NULL && ev->type == ButtonRelease) {
+       rxvt_menu_hide_all(aR);
+       return 0;
+    }
+    thisitem = item;
+    this_y = y - SHADOW;
+
+/* erase the last item */
+    if (ActiveMenu->item != NULL) {
+       if (ActiveMenu->item != thisitem) {
+           for (y = 0, item = ActiveMenu->head; item != NULL;
+                item = item->next) {
+               int             h;
+
+               if (isSeparator(item->name))
+                   h = HEIGHT_SEPARATOR;
+               else if (item == ActiveMenu->item) {
+                   /* erase old menuitem */
+                   rxvt_drawbox_menuitem(aR_ y, 0);    /* No Shadow */
+                   if (item->entry.type == MenuSubMenu)
+                       rxvt_drawtriangle(aR_ ActiveMenu->w, y, +1);
+                   break;
+               } else
+                   h = HEIGHT_TEXT + 2 * SHADOW;
+               y += h;
+           }
+       } else {
+           switch (ev->type) {
+           case ButtonRelease:
+               switch (item->entry.type) {
+               case MenuLabel:
+               case MenuSubMenu:
+                   rxvt_menu_hide_all(aR);
+                   break;
+
+               case MenuAction:
+               case MenuTerminalAction:
+                   rxvt_drawbox_menuitem(aR_ this_y, -1);
+                   {
+#ifdef HAVE_NANOSLEEP
+                       struct timespec rqt;
+
+                       rqt.tv_sec = 0;
+                       rqt.tv_nsec = MENU_DELAY_USEC * 1000;
+                       nanosleep(&rqt, NULL);
+#else
+                   /* use select for timing */
+                       struct timeval  tv;
+
+                       tv.tv_sec = 0;
+                       tv.tv_usec = MENU_DELAY_USEC;
+                       select(0, NULL, NULL, NULL, &tv);
+#endif
+                   }
+                   /* remove menu before sending keys to the application */
+                   rxvt_menu_hide_all(aR);
+#ifndef DEBUG_MENU
+                   rxvt_action_dispatch(aR_ &(item->entry.action));
+#else                          /* DEBUG_MENU */
+                   fprintf(stderr, "%s: %s\n", item->name,
+                           item->entry.action.str);
+#endif                         /* DEBUG_MENU */
+                   break;
+               }
+               break;
+
+           default:
+               if (item->entry.type == MenuSubMenu)
+                   goto DoMenu;
+               break;
+           }
+           return 0;
+       }
+    }
+  DoMenu:
+    ActiveMenu->item = thisitem;
+    y = this_y;
+    if (thisitem != NULL) {
+       item = ActiveMenu->item;
+       if (item->entry.type != MenuLabel)
+           rxvt_drawbox_menuitem(aR_ y, +1);
+       if (item->entry.type == MenuSubMenu) {
+           int             x;
+
+           rxvt_drawtriangle(aR_ ActiveMenu->w, y, -1);
+
+           x = ev->x + (ActiveMenu->parent
+                        ? ActiveMenu->x
+                        : Width2Pixel(ActiveMenu->x));
+
+           if (x >= item->entry.submenu.menu->x) {
+               R->h->ActiveMenu = item->entry.submenu.menu;
+               rxvt_menu_show(aR);
+               return 1;
+           }
+       }
+    }
+    return 0;
+}
+
+/* INTPROTO */
+void
+rxvt_menubar_select(pR_ XButtonEvent *ev)
+{
+    menu_t         *menu = NULL;
+
+/* determine the pulldown menu corresponding to the X index */
+    if (ev->y >= 0 && ev->y <= menuBar_height() && R->h->CurrentBar != NULL) {
+       for (menu = R->h->CurrentBar->head; menu != NULL; menu = menu->next) {
+           int             x = Width2Pixel(menu->x);
+           int             w = Width2Pixel(menu->len + HSPACE);
+
+           if ((ev->x >= x && ev->x < x + w))
+               break;
+       }
+    }
+    switch (ev->type) {
+    case ButtonRelease:
+       rxvt_menu_hide_all(aR);
+       break;
+
+    case ButtonPress:
+       if (menu == NULL && R->h->Arrows_x && ev->x >= R->h->Arrows_x) {
+           int             i;
+
+           for (i = 0; i < NARROWS; i++) {
+               if (ev->x >= (R->h->Arrows_x + (Width2Pixel(4 * i + i)) / 4)
+                   && ev->x < (R->h->Arrows_x
+                               + (Width2Pixel(4 * i + i + 4)) / 4)) {
+                   rxvt_draw_Arrows(aR_ Arrows[i].name, -1);
+                   {
+#ifdef HAVE_NANOSLEEP
+                       struct timespec rqt;
+
+                       rqt.tv_sec = 0;
+                       rqt.tv_nsec = MENU_DELAY_USEC * 1000;
+                       nanosleep(&rqt, NULL);
+#else
+                   /* use select for timing */
+                       struct timeval  tv;
+
+                       tv.tv_sec = 0;
+                       tv.tv_usec = MENU_DELAY_USEC;
+                       select(0, NULL, NULL, NULL, &tv);
+#endif
+                   }
+                   rxvt_draw_Arrows(aR_ Arrows[i].name, +1);
+#ifdef DEBUG_MENUARROWS
+                   fprintf(stderr, "'%c': ", Arrows[i].name);
+
+                   if (R->h->CurrentBar == NULL
+                       || (R->h->CurrentBar->arrows[i].type != MenuAction
+                           && R->h->CurrentBar->arrows[i].type !=
+                           MenuTerminalAction)) {
+                       if (Arrows[i].str != NULL && Arrows[i].str[0])
+                           fprintf(stderr, "(default) \\033%s\n",
+                                   &(Arrows[i].str[2]));
+                   } else {
+                       fprintf(stderr, "%s\n",
+                               R->h->CurrentBar->arrows[i].str);
+                   }
+#else                          /* DEBUG_MENUARROWS */
+                   if (R->h->CurrentBar == NULL
+                       || rxvt_action_dispatch(r,
+                                               &(R->h->CurrentBar->arrows[i]))
+                      ) {
+                       if (Arrows[i].str != NULL && Arrows[i].str[0] != 0)
+                           rxvt_tt_write(aR_ (Arrows[i].str + 1),
+                                         Arrows[i].str[0]);
+                   }
+#endif                         /* DEBUG_MENUARROWS */
+                   return;
+               }
+           }
+       }
+       /* FALLTHROUGH */
+
+    default:
+       /*
+        * press menubar or move to a new entry
+        */
+       if (menu != NULL && menu != R->h->ActiveMenu) {
+           rxvt_menu_hide_all(aR);     /* pop down old menu */
+           R->h->ActiveMenu = menu;
+           rxvt_menu_show(aR); /* pop up new menu */
+       }
+       break;
+    }
+}
+
+/*
+ * general dispatch routine,
+ * it would be nice to have `sticky' menus
+ */
+/* EXTPROTO */
+void
+rxvt_menubar_control(pR_ XButtonEvent *ev)
+{
+    switch (ev->type) {
+    case ButtonPress:
+       if (ev->button == Button1)
+           rxvt_menubar_select(aR_ ev);
+       break;
+
+    case ButtonRelease:
+       if (ev->button == Button1)
+           rxvt_menu_select(aR_ ev);
+       break;
+
+    case MotionNotify:
+       while (XCheckTypedWindowEvent(R->Xdisplay, R->TermWin.parent[0],
+                                     MotionNotify, (XEvent *) ev)) ;
+
+       if (R->h->ActiveMenu)
+           while (rxvt_menu_select(aR_ ev)) ;
+       else
+           ev->y = -1;
+       if (ev->y < 0) {
+           Window          unused_root, unused_child;
+           int             unused_root_x, unused_root_y;
+           unsigned int    unused_mask;
+
+           XQueryPointer(R->Xdisplay, R->menuBar.win,
+                         &unused_root, &unused_child,
+                         &unused_root_x, &unused_root_y,
+                         &(ev->x), &(ev->y), &unused_mask);
+           rxvt_menubar_select(aR_ ev);
+       }
+       break;
+    }
+}
+
+/* EXTPROTO */
+void
+rxvt_map_menuBar(pR_ int map)
+{
+    if (rxvt_menubar_mapping(aR_ map))
+       rxvt_resize_all_windows(aR_ 0, 0, 0);
+}
+#endif
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/menubar.h b/src/menubar.h
new file mode 100644 (file)
index 0000000..e496ccd
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * $Id: menubar.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#ifndef _MENUBAR_H_
+#define _MENUBAR_H_
+
+typedef struct {
+    short           type;      /* must not be changed; first element */
+    short           len;       /* strlen (str) */
+    unsigned char  *str;       /* action to take */
+} action_t;
+
+typedef struct {
+    short           type;      /* must not be changed; first element */
+    struct menu_t  *menu;      /* sub-menu */
+} submenu_t;
+
+typedef struct menuitem_t {
+    struct menuitem_t *prev;   /* prev menu-item */
+    struct menuitem_t *next;   /* next menu-item */
+    char           *name;      /* character string displayed */
+    char           *name2;     /* character string displayed (right) */
+    short           len;       /* strlen (name) */
+    short           len2;      /* strlen (name) */
+    union {
+       short           type;   /* must not be changed; first element */
+       action_t        action;
+       submenu_t       submenu;
+    } entry;
+} menuitem_t;
+
+enum menuitem_t_action {
+    MenuLabel,
+    MenuAction,
+    MenuTerminalAction,
+    MenuSubMenu
+};
+
+typedef struct menu_t {
+    struct menu_t  *parent;    /* parent menu */
+    struct menu_t  *prev;      /* prev menu */
+    struct menu_t  *next;      /* next menu */
+    menuitem_t     *head;      /* double-linked list */
+    menuitem_t     *tail;      /* double-linked list */
+    menuitem_t     *item;      /* current item */
+    char           *name;      /* menu name */
+    short           len;       /* strlen (name) */
+    short           width;     /* maximum menu width [chars] */
+    Window          win;       /* window of the menu */
+    short           x;         /* x location [pixels] (chars if parent == NULL) */
+    short           y;         /* y location [pixels] */
+    short           w, h;      /* window width, height [pixels] */
+} menu_t;
+
+typedef struct bar_t {
+    menu_t         *head, *tail;       /* double-linked list of menus */
+    char           *title;     /* title to put in the empty menuBar */
+#if (MENUBAR_MAX > 1)
+# define MAXNAME 16
+    char            name[MAXNAME];     /* name to use to refer to menubar */
+    struct bar_t   *next, *prev;       /* circular linked-list */
+#endif                         /* (MENUBAR_MAX > 1) */
+#define NARROWS        4
+    action_t        arrows[NARROWS];
+} bar_t;
+
+/* #define DEBUG_MENU */
+/* #define DEBUG_MENU_LAYOUT */
+/* #define DEBUG_MENUBAR_STACKING */
+
+#define HSPACE         1       /* one space */
+#define isSeparator(name)      ((name)[0] == '\0')
+#define HEIGHT_SEPARATOR       (SHADOW + 1)
+#define HEIGHT_TEXT            (Height2Pixel(1) + 2)
+
+#define MENU_DELAY_USEC        250000  /* 1/4 sec */
+
+
+#define SEPARATOR_NAME         "-"
+#define MENUITEM_BEG           '{'
+#define MENUITEM_END           '}'
+#define COMMENT_CHAR           '#'
+
+#define DOT    "."
+#define DOTS   ".."
+
+#endif /* _MENUBAR_H_ */
diff --git a/src/misc.C b/src/misc.C
new file mode 100644 (file)
index 0000000..ad8b87d
--- /dev/null
@@ -0,0 +1,406 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       misc.c
+ *----------------------------------------------------------------------*
+ * $Id: misc.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1996      mj olesen <olesen@me.QueensU.CA> Queen's Univ at Kingston
+ * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
+ * Copyright (c) 1998-2000 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "misc.intpro"         /* PROTOS for internal routines */
+
+/* EXTPROTO */
+char           *
+rxvt_r_basename(const char *str)
+{
+    char           *base = STRRCHR(str, '/');
+
+    return (char *)(base ? base + 1 : str);
+}
+
+/*
+ * Print an error message
+ */
+/* EXTPROTO */
+void
+rxvt_print_error(const char *fmt,...)
+{
+    va_list         arg_ptr;
+
+    va_start(arg_ptr, fmt);
+    fprintf(stderr, APL_NAME ": ");
+    vfprintf(stderr, fmt, arg_ptr);
+    fprintf(stderr, "\n");
+    va_end(arg_ptr);
+}
+
+/*
+ * check that the first characters of S1 match S2
+ *
+ * No Match
+ *      return: 0
+ * Match
+ *      return: STRLEN (S2)
+ */
+/* EXTPROTO */
+int
+rxvt_Str_match(const char *s1, const char *s2)
+{
+    int             n = STRLEN(s2);
+
+    return ((STRNCMP(s1, s2, n) == 0) ? n : 0);
+}
+
+/* EXTPROTO */
+const char     *
+rxvt_Str_skip_space(const char *str)
+{
+    if (str)
+       while (*str && isspace(*str))
+           str++;
+    return str;
+}
+
+/*
+ * remove leading/trailing space and strip-off leading/trailing quotes.
+ * in place.
+ */
+/* EXTPROTO */
+char           *
+rxvt_Str_trim(char *str)
+{
+    char           *r, *s;
+    int             n;
+
+    if (!str || !*str)         /* shortcut */
+       return str;
+
+/* skip leading spaces */
+    for (s = str; *s && isspace(*s); s++) ;
+/* goto end of string */
+    for (n = 0, r = s; *r++; n++) ;
+    r -= 2;
+/* dump return */
+    if (n > 0 && *r == '\n')
+       n--, r--;
+/* backtrack along trailing spaces */
+    for (; n > 0 && isspace(*r); r--, n--) ;
+/* skip matching leading/trailing quotes */
+    if (*s == '"' && *r == '"' && n > 1) {
+       s++;
+       n -= 2;
+    }
+/* copy back over: forwards copy */
+    for (r = str; n; n--)
+       *r++ = *s++;
+    *r = '\0';
+
+    return str;
+}
+
+/*
+ * in-place interpretation of string:
+ *
+ *      backslash-escaped:      "\a\b\E\e\n\r\t", "\octal"
+ *      Ctrl chars:     ^@ .. ^_, ^?
+ *
+ *      Emacs-style:    "M-" prefix
+ *
+ * Also,
+ *      "M-x" prefixed strings, append "\r" if needed
+ *      "\E]" prefixed strings (XTerm escape sequence) append ST if needed
+ *
+ * returns the converted string length
+ */
+/* EXTPROTO */
+int
+rxvt_Str_escaped(char *str)
+{
+    char            ch, *s, *d;
+    int             i, num, append = 0;
+
+    if (!str || !*str)
+       return 0;
+
+    d = s = str;
+
+    if (*s == 'M' && s[1] == '-') {
+       /* Emacs convenience, replace leading `M-..' with `\E..' */
+       *d++ = C0_ESC;
+       s += 2;
+       if (toupper(*s) == 'X')
+           /* append carriage-return for `M-xcommand' */
+           for (*d++ = 'x', append = '\r', s++; isspace(*s); s++) ;
+    }
+    for (; (ch = *s++);) {
+       if (ch == '\\') {
+           ch = *s++;
+           if (ch >= '0' && ch <= '7') {       /* octal */
+               num = ch - '0';
+               for (i = 0; i < 2; i++, s++) {
+                   ch = *s;
+                   if (ch < '0' || ch > '7')
+                       break;
+                   num = num * 8 + ch - '0';
+               }
+               ch = (char)num;
+           } else if (ch == 'a')
+               ch = C0_BEL;    /* bell */
+           else if (ch == 'b')
+               ch = C0_BS;     /* backspace */
+           else if (ch == 'E' || ch == 'e')
+               ch = C0_ESC;    /* escape */
+           else if (ch == 'n')
+               ch = '\n';      /* newline */
+           else if (ch == 'r')
+               ch = '\r';      /* carriage-return */
+           else if (ch == 't')
+               ch = C0_HT;     /* tab */
+       } else if (ch == '^') {
+           ch = *s++;
+           ch = toupper(ch);
+           ch = (ch == '?' ? 127 : (ch - '@'));
+       }
+       *d++ = ch;
+    }
+
+/* ESC] is an XTerm escape sequence, must be terminated */
+    if (*str == '\0' && str[1] == C0_ESC && str[2] == ']')
+       append = CHAR_ST;
+
+/* add trailing character as required */
+    if (append && d[-1] != append)
+       *d++ = append;
+    *d = '\0';
+
+    return (d - str);
+}
+
+/*
+ * Split a comma-separated string into an array, stripping leading and
+ * trailing spaces (and paired quotes) from each entry.  Empty strings
+ * are properly returned
+ * Caller should free each entry and array when done
+ */
+/* EXTPROTO */
+char          **
+rxvt_splitcommastring(const char *cs)
+{
+    int             l, n, p;
+    const char     *s, *t;
+    char          **ret;
+
+    if ((s = cs) == NULL)
+       s = "";
+
+    for (n = 1, t = s; *t; t++)
+       if (*t == ',')
+           n++;
+    ret = (char **)malloc((n + 1) * sizeof(char *));
+    ret[n] = NULL;
+
+    for (l = 0, t = s; l < n; l++) {
+       for ( ; *t && *t != ','; t++) ;
+       p = t - s;
+       ret[l] = (char *)malloc(p + 1);
+       strncpy(ret[l], s, p);
+       ret[l][p] = '\0';
+       rxvt_Str_trim(ret[l]);
+       s = ++t;
+    }
+    return ret;
+}
+
+/*----------------------------------------------------------------------*
+ * file searching
+ */
+
+/* #define DEBUG_SEARCH_PATH */
+
+#if defined (XPM_BACKGROUND) || (MENUBAR_MAX)
+/*
+ * search for FILE in the current working directory, and within the
+ * colon-delimited PATHLIST, adding the file extension EXT if required.
+ *
+ * FILE is either semi-colon or zero terminated
+ */
+/* INTPROTO */
+char           *
+rxvt_File_search_path(const char *pathlist, const char *file, const char *ext)
+{
+    int             maxpath, len;
+    const char     *p, *path;
+    char            name[256];
+
+    if (!access(file, R_OK))   /* found (plain name) in current directory */
+       return STRDUP(file);
+
+/* semi-colon delimited */
+    if ((p = STRCHR(file, ';')))
+       len = (p - file);
+    else
+       len = STRLEN(file);
+
+#ifdef DEBUG_SEARCH_PATH
+    getcwd(name, sizeof(name));
+    fprintf(stderr, "pwd: \"%s\"\n", name);
+    fprintf(stderr, "find: \"%.*s\"\n", len, file);
+#endif
+
+/* leave room for an extra '/' and trailing '\0' */
+    maxpath = sizeof(name) - (len + (ext ? STRLEN(ext) : 0) + 2);
+    if (maxpath <= 0)
+       return NULL;
+
+/* check if we can find it now */
+    STRNCPY(name, file, len);
+    name[len] = '\0';
+
+    if (!access(name, R_OK))
+       return STRDUP(name);
+    if (ext) {
+       STRCAT(name, ext);
+       if (!access(name, R_OK))
+           return STRDUP(name);
+    }
+    for (path = pathlist; path != NULL && *path != '\0'; path = p) {
+       int             n;
+
+       /* colon delimited */
+       if ((p = STRCHR(path, ':')) == NULL)
+           p = STRCHR(path, '\0');
+
+       n = (p - path);
+       if (*p != '\0')
+           p++;
+
+       if (n > 0 && n <= maxpath) {
+           STRNCPY(name, path, n);
+           if (name[n - 1] != '/')
+               name[n++] = '/';
+           name[n] = '\0';
+           STRNCAT(name, file, len);
+
+           if (!access(name, R_OK))
+               return STRDUP(name);
+           if (ext) {
+               STRCAT(name, ext);
+               if (!access(name, R_OK))
+                   return STRDUP(name);
+           }
+       }
+    }
+    return NULL;
+}
+
+/* EXTPROTO */
+char           *
+rxvt_File_find(const char *file, const char *ext, const char *path)
+{
+    char           *f;
+
+    if (file == NULL || *file == '\0')
+       return NULL;
+
+/* search environment variables here too */
+    if ((f = rxvt_File_search_path(path, file, ext)) == NULL)
+#ifdef PATH_ENV
+       if ((f = rxvt_File_search_path(getenv(PATH_ENV), file, ext)) == NULL)
+#endif
+           f = rxvt_File_search_path(getenv("PATH"), file, ext);
+
+#ifdef DEBUG_SEARCH_PATH
+    if (f)
+       fprintf(stderr, "found: \"%s\"\n", f);
+#endif
+
+    return f;
+}
+#endif                         /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */
+
+/*----------------------------------------------------------------------*
+ * miscellaneous drawing routines
+ */
+
+/*
+ * Draw top/left and bottom/right border shadows around windows
+ */
+#if defined(RXVT_SCROLLBAR) || defined(MENUBAR)
+/* EXTPROTO */
+void
+rxvt_Draw_Shadow(Display *Xdisplay, Window win, GC topShadow, GC botShadow, int x, int y, int w, int h)
+{
+    int             shadow;
+
+    shadow = (w == 0 || h == 0) ? 1 : SHADOW;
+    w += x - 1;
+    h += y - 1;
+    for (; shadow-- > 0; x++, y++, w--, h--) {
+       XDrawLine(Xdisplay, win, topShadow, x, y, w, y);
+       XDrawLine(Xdisplay, win, topShadow, x, y, x, h);
+       XDrawLine(Xdisplay, win, botShadow, w, h, w, y + 1);
+       XDrawLine(Xdisplay, win, botShadow, w, h, x + 1, h);
+    }
+}
+#endif
+
+/* button shapes */
+#ifdef MENUBAR
+/* EXTPROTO */
+void
+rxvt_Draw_Triangle(Display *Xdisplay, Window win, GC topShadow, GC botShadow, int x, int y, int w, int type)
+{
+    switch (type) {
+    case 'r':                  /* right triangle */
+       XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w);
+       XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y + w / 2);
+       XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w / 2);
+       break;
+
+    case 'l':                  /* left triangle */
+       XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y);
+       XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w / 2);
+       XDrawLine(Xdisplay, win, topShadow, x, y + w / 2, x + w, y);
+       break;
+
+    case 'd':                  /* down triangle */
+       XDrawLine(Xdisplay, win, topShadow, x, y, x + w / 2, y + w);
+       XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y);
+       XDrawLine(Xdisplay, win, botShadow, x + w, y, x + w / 2, y + w);
+       break;
+
+    case 'u':                  /* up triangle */
+       XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w / 2, y);
+       XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w);
+       XDrawLine(Xdisplay, win, topShadow, x, y + w, x + w / 2, y);
+       break;
+#if 0
+    case 's':                  /* square */
+       XDrawLine(Xdisplay, win, topShadow, x + w, y, x, y);
+       XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w);
+       XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w);
+       XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y);
+       break;
+#endif
+    }
+}
+#endif
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/netdisp.C b/src/netdisp.C
new file mode 100644 (file)
index 0000000..c556f83
--- /dev/null
@@ -0,0 +1,104 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       netdisp.c
+ *----------------------------------------------------------------------*
+ * $Id: netdisp.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1996      Chuck Blake <cblake@BBN.COM>
+ *                             - original version
+ * Copyright (c) 1997      mj olesen <olesen@me.queensu.ca>
+ * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*
+ * support for resolving the actual IP number of the host for remote
+ * DISPLAYs.  When the display is local (i.e. :0), we add support for
+ * sending the first non-loopback interface IP number as the DISPLAY
+ * instead of just sending the incorrect ":0".  This way telnet/rlogin
+ * shells can actually get the correct information into DISPLAY for
+ * xclients.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+
+#ifdef DISPLAY_IS_IP
+#include "netdisp.h"
+
+/*----------------------------------------------------------------------*/
+/* return NULL a pointer to buffer which may be freed */
+/* EXTPROTO */
+char           *
+rxvt_network_display(const char *display)
+{
+    char            buffer[1024], *rval = NULL;
+    struct ifconf   ifc;
+    struct ifreq   *ifr;
+    int             i, skfd;
+
+    if (display[0] != ':' && STRNCMP(display, "unix:", 5))
+       return (char *) display;                /* nothing to do */
+
+    ifc.ifc_len = sizeof(buffer);      /* Get names of all ifaces */
+    ifc.ifc_buf = buffer;
+
+    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+       perror("socket");
+       return NULL;
+    }
+    if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
+       perror("SIOCGIFCONF");
+       close(skfd);
+       return NULL;
+    }
+    for (i = 0, ifr = ifc.ifc_req;
+        i < (ifc.ifc_len / sizeof(struct ifreq));
+        i++, ifr++) {
+       struct ifreq    ifr2;
+
+       STRCPY(ifr2.ifr_name, ifr->ifr_name);
+       if (ioctl(skfd, SIOCGIFADDR, &ifr2) >= 0) {
+           unsigned long   addr;
+           struct sockaddr_in *p_addr;
+
+           p_addr = (struct sockaddr_in *)&(ifr2.ifr_addr);
+           addr = htonl((unsigned long)p_addr->sin_addr.s_addr);
+
+       /*
+        * not "0.0.0.0" or "127.0.0.1" - so format the address
+        */
+           if (addr && addr != 0x7F000001) {
+               char           *colon = STRCHR(display, ':');
+
+               if (colon == NULL)
+                   colon = ":0.0";
+
+               rval = rxvt_malloc(STRLEN(colon) + 16);
+               sprintf(rval, "%d.%d.%d.%d%s",
+                       (int)((addr >> 030) & 0xFF),
+                       (int)((addr >> 020) & 0xFF),
+                       (int)((addr >> 010) & 0xFF),
+                       (int)(addr & 0xFF), colon);
+               break;
+           }
+       }
+    }
+
+    close(skfd);
+    return rval;
+}
+#endif                         /* DISPLAY_IS_IP */
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/protos.h b/src/protos.h
new file mode 100644 (file)
index 0000000..d4f531e
--- /dev/null
@@ -0,0 +1,57 @@
+/* Include prototypes for all files */
+/*
+ * $Id: protos.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+#include "command.extpro"
+
+#include "defaultfont.extpro"
+
+#ifdef RXVT_GRAPHICS
+# include "graphics.extpro"
+#endif
+#ifdef GREEK_SUPPORT
+# include "grkelot.extpro"
+#endif
+
+#include "init.extpro"
+
+#ifdef UTMP_SUPPORT
+# include "logging.extpro"
+#endif
+
+#include "main.extpro"
+
+#ifdef MENUBAR
+# include "menubar.extpro"
+#endif
+
+#include "misc.extpro"
+
+#ifdef DISPLAY_IS_IP
+# include "netdisp.extpro"
+#endif
+
+#include "ptytty.extpro"
+
+#if !defined(NO_STRINGS) && !defined(HAVE_STRING_H)
+# include "strings.extpro"
+#endif
+
+#include "screen.extpro"
+
+#include "scrollbar.extpro"
+#ifdef RXVT_SCROLLBAR
+# include "scrollbar-rxvt.extpro"
+#endif
+#ifdef NEXT_SCROLLBAR
+# include "scrollbar-next.extpro"
+#endif
+#ifdef XTERM_SCROLLBAR
+# include "scrollbar-xterm.extpro"
+#endif
+
+#include "xdefaults.extpro"
+
+#ifdef XPM_BACKGROUND
+# include "xpm.extpro"
+#endif
diff --git a/src/ptytty.C b/src/ptytty.C
new file mode 100644 (file)
index 0000000..09e5d56
--- /dev/null
@@ -0,0 +1,291 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       ptytty.c
+ *----------------------------------------------------------------------*
+ * $Id: ptytty.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *---------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+
+/*
+ * Try to be self-contained except for the above autoconfig'd defines
+ */
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#if defined(HAVE_STRING_H)
+# include <string.h>
+#endif
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if defined(PTYS_ARE_PTMX) && !defined(__CYGWIN32__)
+# include <sys/stropts.h>      /* for I_PUSH */
+#endif
+
+
+#ifdef DEBUG_TTY
+# define D_TTY(x)              fprintf x ; fputc('\n', stderr) ; fflush(stderr)
+#else
+# define D_TTY(x)
+#endif
+
+/* ------------------------------------------------------------------------- *
+ *                  GET PSEUDO TELETYPE - MASTER AND SLAVE                   *
+ * ------------------------------------------------------------------------- */
+/*
+ * Returns pty file descriptor, or -1 on failure 
+ * If successful, ttydev is set to the name of the slave device.
+ * fd_tty _may_ also be set to an open fd to the slave device
+ */
+/* EXTPROTO */
+int
+rxvt_get_pty(int *fd_tty, const char **ttydev)
+{
+    int             pfd;
+
+#ifdef PTYS_ARE_OPENPTY
+    char            tty_name[sizeof "/dev/pts/????\0"];
+
+    if (openpty(&pfd, fd_tty, tty_name, NULL, NULL) != -1) {
+       *ttydev = strdup(tty_name);
+       return pfd;
+    }
+#endif
+
+#ifdef PTYS_ARE__GETPTY
+    *ttydev = _getpty(&pfd, O_RDWR | O_NDELAY | O_NOCTTY, 0622, 0);
+    if (*ttydev != NULL)
+       return pfd;
+#endif
+
+#ifdef PTYS_ARE_GETPTY
+    char           *ptydev;
+
+    while ((ptydev = getpty()) != NULL)
+       if ((pfd = open(ptydev, O_RDWR | O_NOCTTY, 0)) >= 0) {
+           *ttydev = ptydev;
+           return pfd;
+       }
+#endif
+
+#if defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT)
+# if defined(PTYS_ARE_GETPT) || defined(PTYS_ARE_PTMX)
+    {
+#  ifdef PTYS_ARE_GETPT
+       pfd = getpt();
+#  else
+       pfd = open("/dev/ptmx", O_RDWR | O_NOCTTY, 0);
+#  endif
+       if (pfd >= 0) {
+           if (grantpt(pfd) == 0       /* change slave permissions */
+               && unlockpt(pfd) == 0) {        /* slave now unlocked */
+               *ttydev = ptsname(pfd); /* get slave's name */
+               return pfd;
+           }
+           close(pfd);
+       }
+    }
+# endif
+#endif
+
+#ifdef PTYS_ARE_PTC
+    if ((pfd = open("/dev/ptc", O_RDWR | O_NOCTTY, 0)) >= 0) {
+       *ttydev = ttyname(pfd);
+       return pfd;
+    }
+#endif
+
+#ifdef PTYS_ARE_CLONE
+    if ((pfd = open("/dev/ptym/clone", O_RDWR | O_NOCTTY, 0)) >= 0) {
+       *ttydev = ptsname(pfd);
+       return pfd;
+    }
+#endif
+
+#ifdef PTYS_ARE_NUMERIC
+    {
+       int             idx;
+       char           *c1, *c2;
+       char            pty_name[] = "/dev/ptyp???";
+       char            tty_name[] = "/dev/ttyp???";
+
+       c1 = &(pty_name[sizeof(pty_name) - 4]);
+       c2 = &(tty_name[sizeof(tty_name) - 4]);
+       for (idx = 0; idx < 256; idx++) {
+           sprintf(c1, "%d", idx);
+           sprintf(c2, "%d", idx);
+           if (access(tty_name, F_OK) < 0) {
+               idx = 256;
+               break;
+           }
+           if ((pfd = open(pty_name, O_RDWR | O_NOCTTY, 0)) >= 0) {
+               if (access(tty_name, R_OK | W_OK) == 0) {
+                   *ttydev = strdup(tty_name);
+                   return pfd;
+               }
+               close(pfd);
+           }
+       }
+    }
+#endif
+#ifdef PTYS_ARE_SEARCHED
+    {
+       const char     *c1, *c2;
+       char            pty_name[] = "/dev/pty??";
+       char            tty_name[] = "/dev/tty??";
+
+# ifndef PTYCHAR1
+#  define PTYCHAR1     "pqrstuvwxyz"
+# endif
+# ifndef PTYCHAR2
+#  define PTYCHAR2     "0123456789abcdef"
+# endif
+       for (c1 = PTYCHAR1; *c1; c1++) {
+           pty_name[(sizeof(pty_name) - 3)] =
+               tty_name[(sizeof(pty_name) - 3)] = *c1;
+           for (c2 = PTYCHAR2; *c2; c2++) {
+               pty_name[(sizeof(pty_name) - 2)] =
+                   tty_name[(sizeof(pty_name) - 2)] = *c2;
+               if ((pfd = open(pty_name, O_RDWR | O_NOCTTY, 0)) >= 0) {
+                   if (access(tty_name, R_OK | W_OK) == 0) {
+                       *ttydev = strdup(tty_name);
+                       return pfd;
+                   }
+                   close(pfd);
+               }
+           }
+       }
+    }
+#endif
+    return -1;
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * Returns tty file descriptor, or -1 on failure 
+ */
+/* EXTPROTO */
+int
+rxvt_get_tty(const char *ttydev)
+{
+    return open(ttydev, O_RDWR | O_NOCTTY, 0);
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * Make our tty a controlling tty so that /dev/tty points to us
+ */
+/* EXTPROTO */
+int
+rxvt_control_tty(int fd_tty, const char *ttydev)
+{
+#ifndef __QNX__
+    int             fd;
+
+    D_TTY((stderr, "rxvt_control_tty(): pid: %d, tty fd: %d, dev: %s", getpid(), fd_tty, ttydev));
+/* ---------------------------------------- */
+# ifdef HAVE_SETSID
+    setsid();
+# endif
+# if defined(HAVE_SETPGID)
+    setpgid(0, 0);
+# elif defined(HAVE_SETPGRP)
+    setpgrp(0, 0);
+# endif
+/* ---------------------------------------- */
+# ifdef TIOCNOTTY
+    fd = open("/dev/tty", O_RDWR | O_NOCTTY);
+    D_TTY((stderr, "rxvt_control_tty(): Voiding tty associations: previous=%s", fd < 0 ? "no" : "yes"));
+    if (fd >= 0) {
+       ioctl(fd, TIOCNOTTY, NULL);     /* void tty associations */
+       close(fd);
+    }
+# endif
+/* ---------------------------------------- */
+    fd = open("/dev/tty", O_RDWR | O_NOCTTY);
+    D_TTY((stderr, "rxvt_control_tty(): /dev/tty has controlling tty? %s", fd < 0 ? "no (good)" : "yes (bad)"));
+    if (fd >= 0)
+       close(fd);              /* ouch: still have controlling tty */
+/* ---------------------------------------- */
+#if defined(PTYS_ARE_PTMX) && defined(I_PUSH)
+/*
+ * Push STREAMS modules:
+ *    ptem: pseudo-terminal hardware emulation module.
+ *    ldterm: standard terminal line discipline.
+ *    ttcompat: V7, 4BSD and XENIX STREAMS compatibility module.
+ *
+ * After we push the STREAMS modules, the first open() on the slave side
+ * (i.e. the next section between the dashes giving us "tty opened OK")
+ * should make the "ptem" (or "ldterm" depending upon either which OS
+ * version or which set of manual pages you have) module give us a
+ * controlling terminal.  We must already have close()d the master side
+ * fd in this child process before we push STREAMS modules on because the
+ * documentation is really unclear about whether it is any close() on
+ * the master side or the last close() - i.e. a proper STREAMS dismantling
+ * close() - on the master side which causes a hang up to be sent
+ * through - Geoff Wing
+ */
+# ifdef HAVE_ISASTREAM
+    if (isastream(fd_tty) == 1)
+# endif
+    {
+       D_TTY((stderr, "rxvt_control_tty(): Pushing STREAMS modules"));
+       ioctl(fd_tty, I_PUSH, "ptem");
+       ioctl(fd_tty, I_PUSH, "ldterm");
+       ioctl(fd_tty, I_PUSH, "ttcompat");
+    }
+#endif
+/* ---------------------------------------- */
+# if defined(TIOCSCTTY)
+    fd = ioctl(fd_tty, TIOCSCTTY, NULL);
+    D_TTY((stderr, "rxvt_control_tty(): ioctl(..,TIOCSCTTY): %d", fd));
+# elif defined(TIOCSETCTTY)
+    fd = ioctl(fd_tty, TIOCSETCTTY, NULL);
+    D_TTY((stderr, "rxvt_control_tty(): ioctl(..,TIOCSETCTTY): %d", fd));
+# else
+    fd = open(ttydev, O_RDWR);
+    D_TTY((stderr, "rxvt_control_tty(): tty open%s", fd < 0 ? " failure" : "ed OK"));
+    if (fd >= 0)
+       close(fd);
+# endif
+/* ---------------------------------------- */
+    fd = open("/dev/tty", O_WRONLY);
+    D_TTY((stderr, "rxvt_control_tty(): do we have controlling tty now: %s", fd < 0 ? "no (fatal)" : "yes (good)"));
+    if (fd < 0)
+       return -1;              /* fatal */
+    close(fd);
+/* ---------------------------------------- */
+    D_TTY((stderr, "rxvt_control_tty(): tcgetpgrp(): %d  getpgrp(): %d", tcgetpgrp(fd_tty), getpgrp()));
+/* ---------------------------------------- */
+#endif                         /* ! __QNX__ */
+    return 0;
+}
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/rxvt.h b/src/rxvt.h
new file mode 100644 (file)
index 0000000..859d4fa
--- /dev/null
@@ -0,0 +1,1144 @@
+/*
+ * $Id: rxvt.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#ifndef _RXVT_H_               /* include once only */
+#define _RXVT_H_
+
+#include "rxvtlib.h"
+
+#include "feature.h"
+
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <X11/keysymdef.h>
+#include <X11/Xatom.h>
+
+#include "defaultfont.h"
+#include "rxvtcolor.h"
+
+/*
+ *****************************************************************************
+ * SYSTEM HACKS
+ *****************************************************************************
+ */
+/* Consistent defines - please report on the necessity
+ * @ Unixware: defines (__svr4__)
+ */
+#if defined (SVR4) && !defined (__svr4__)
+# define __svr4__
+#endif
+#if defined (sun) && !defined (__sun__)
+# define __sun__
+#endif
+
+
+#ifndef HAVE_XPOINTER
+typedef char   *XPointer;
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+typedef struct termios ttymode_t;
+#else
+# include <sgtty.h>
+typedef struct {
+    struct sgttyb   sg;
+    struct tchars   tc;
+    struct ltchars  lc;
+    int             line;
+    int             local;
+} ttymode_t;
+#endif
+
+#ifdef GREEK_SUPPORT
+# include "grkelot.h"
+#endif
+#ifdef XPM_BACKGROUND
+# ifdef XPM_INC_X11
+#  include <X11/xpm.h>
+# else
+#  include <xpm.h>
+# endif
+#endif
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO  0
+# define STDOUT_FILENO 1
+# define STDERR_FILENO 2
+#endif
+
+#if defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT)
+# if defined(PTYS_ARE_GETPT) || defined(PTYS_ARE_PTMX)
+#  define NO_SETOWNER_TTYDEV
+# endif
+#endif
+#if defined(__CYGWIN32__) || defined(PTYS_ARE_OPENPTY)
+# define NO_SETOWNER_TTYDEV
+#endif
+
+/*
+ *****************************************************************************
+ * STRUCTURES AND TYPEDEFS
+ *****************************************************************************
+ */
+struct rxvt_vars;              /* Later REDEFINED and typedef'd to rxvt_t */
+struct rxvt_hidden;
+struct grwin_t;
+
+
+/* Sanitize menubar info */
+#ifndef MENUBAR
+# undef MENUBAR_MAX
+#endif
+#ifndef MENUBAR_MAX
+# define MENUBAR_MAX   0
+#endif
+
+/* If we're using either the rxvt scrollbar or menu bars, keep the
+ * scrollColor resource.
+ */
+#if defined(RXVT_SCROLLBAR) || defined(MENUBAR)
+# define KEEP_SCROLLCOLOR 1
+#else
+# undef KEEP_SCROLLCOLOR
+#endif
+
+#ifdef XPM_BACKGROUND
+typedef struct {
+    short           w, h, x, y;
+    Pixmap          pixmap;
+} bgPixmap_t;
+#endif
+
+/*
+ * the 'essential' information for reporting Mouse Events
+ * pared down from XButtonEvent
+ */
+struct mouse_event {
+    int             clicks;
+    Time            time;      /* milliseconds */
+    unsigned int    state;     /* key or button mask */
+    unsigned int    button;    /* detail */
+};
+
+#ifndef min
+# define min(a,b)      (((a) < (b)) ? (a) : (b))
+# define max(a,b)      (((a) > (b)) ? (a) : (b))
+#endif
+
+#define MAX_IT(current, other) if ((other) > (current)) (current) = (other)
+#define MIN_IT(current, other) if ((other) < (current)) (current) = (other)
+#define SWAP_IT(one, two, typeof)                                      \
+    do {                                                               \
+       typeof          swapittmp;                                      \
+       (swapittmp) = (one); (one) = (two); (two) = (swapittmp);        \
+    } while (/* CONSTCOND */ 0)
+#define BOUND_POSITIVE_INT16(val)                      \
+    (int16_t)((val) <= 0                               \
+             ? 0                                       \
+             : min((val), (((uint16_t)-1)>>1)))
+
+/*
+ *****************************************************************************
+ * NORMAL DEFINES
+ *****************************************************************************
+ */
+
+#if defined (NO_OLD_SELECTION) && defined(NO_NEW_SELECTION)
+# error if you disable both selection styles, how can you select, silly?
+#endif
+
+#define APL_CLASS      "XTerm" /* class name */
+#define APL_SUBCLASS   "Rxvt"  /* also check resources under this name */
+#define APL_NAME       "rxvt"  /* normal name */
+
+/* COLORTERM, TERM environment variables */
+#define COLORTERMENV   "rxvt"
+#ifdef XPM_BACKGROUND
+# define COLORTERMENVFULL COLORTERMENV "-xpm"
+#else
+# define COLORTERMENVFULL COLORTERMENV
+#endif
+#ifndef TERMENV
+# define TERMENV       "xterm"
+#endif
+
+#if defined (NO_MOUSE_REPORT) && !defined (NO_MOUSE_REPORT_SCROLLBAR)
+# define NO_MOUSE_REPORT_SCROLLBAR
+#endif
+
+#ifdef NO_RESOURCES
+# undef USE_XGETDEFAULT
+#endif
+
+/* now look for other badly set stuff */
+
+#if !defined (EACCESS) && defined(EAGAIN)
+# define EACCESS EAGAIN
+#endif
+
+#ifndef EXIT_SUCCESS           /* missing from <stdlib.h> */
+# define EXIT_SUCCESS          0       /* exit function success */
+# define EXIT_FAILURE          1       /* exit function failure */
+#endif
+
+#define menuBar_esc            10
+#define scrollBar_esc          30
+#define menuBar_margin         2       /* margin below text */
+
+#if defined(RXVT_SCROLLBAR) || defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR)
+# define HAVE_SCROLLBARS
+#endif
+
+/* width of scrollBar, menuBar shadow, must be 1 or 2 */
+#ifdef HALFSHADOW
+# define SHADOW 1
+#else
+# define SHADOW 2
+#endif
+
+#define R_SB_ALIGN_CENTRE      0
+#define R_SB_ALIGN_TOP         1
+#define R_SB_ALIGN_BOTTOM      2
+
+#define R_SB_RXVT              0
+#define R_SB_NEXT              1
+#define R_SB_XTERM             2
+
+#define SB_WIDTH_NEXT          19
+#define SB_WIDTH_XTERM         7
+#ifndef SB_WIDTH_RXVT
+# define SB_WIDTH_RXVT         10
+#endif
+
+/*
+ * NeXT scrollbar defines
+ */
+#define SB_PADDING             1
+#define SB_BORDER_WIDTH                1
+#define SB_BEVEL_WIDTH_UPPER_LEFT      1
+#define SB_BEVEL_WIDTH_LOWER_RIGHT     2
+#define SB_LEFT_PADDING                (SB_PADDING + SB_BORDER_WIDTH)
+#define SB_MARGIN_SPACE                (SB_PADDING * 2)
+#define SB_BUTTON_WIDTH                (SB_WIDTH_NEXT - SB_MARGIN_SPACE - SB_BORDER_WIDTH)
+#define SB_BUTTON_HEIGHT       (SB_BUTTON_WIDTH)
+#define SB_BUTTON_SINGLE_HEIGHT        (SB_BUTTON_HEIGHT + SB_PADDING)
+#define SB_BUTTON_BOTH_HEIGHT  (SB_BUTTON_SINGLE_HEIGHT * 2)
+#define SB_BUTTON_TOTAL_HEIGHT (SB_BUTTON_BOTH_HEIGHT + SB_PADDING)
+#define SB_BUTTON_BEVEL_X      (SB_LEFT_PADDING)
+#define SB_BUTTON_FACE_X       (SB_BUTTON_BEVEL_X + SB_BEVEL_WIDTH_UPPER_LEFT)
+#define SB_THUMB_MIN_HEIGHT    (SB_BUTTON_WIDTH - (SB_PADDING * 2))
+ /*
+  *    +-------------+
+  *    |             | <---< SB_PADDING
+  *    | ::::::::::: |
+  *    | ::::::::::: |
+  *   '''''''''''''''''
+  *   ,,,,,,,,,,,,,,,,,
+  *    | ::::::::::: |
+  *    | ::::::::::: |
+  *    |  +---------------< SB_BEVEL_WIDTH_UPPER_LEFT
+  *    |  | :::::::: |
+  *    |  V :::: vv-------< SB_BEVEL_WIDTH_LOWER_RIGHT
+  *    | +---------+ |
+  *    | | ......%%| |
+  *    | | ......%%| |
+  *    | | ..()..%%| |
+  *    | | ......%%| |
+  *    | | %%%%%%%%| |
+  *    | +---------+ | <.........................
+  *    |             | <---< SB_PADDING         :
+  *    | +---------+ | <-+..........            :---< SB_BUTTON_TOTAL_HEIGHT
+  *    | | ......%%| |   |         :            :
+  *    | | ../\..%%| |   |---< SB_BUTTON_HEIGHT :
+  *    | | %%%%%%%%| |   |         :            :
+  *    | +---------+ | <-+         :            :
+  *    |             |             :            :
+  *    | +---------+ | <-+         :---< SB_BUTTON_BOTH_HEIGHT
+  *    | | ......%%| |   |         :            :
+  *    | | ..\/..%%| |   |         :            :
+  *    | | %%%%%%%%| |   |---< SB_BUTTON_SINGLE_HEIGHT
+  *    | +---------+ |   |         :            :
+  *    |             |   |         :            :
+  *    +-------------+ <-+.........:............:
+  *    ^^|_________| :
+  *    ||     |      :
+  *    ||     +---< SB_BUTTON_WIDTH
+  *    ||            :
+  *    |+------< SB_PADDING
+  *    |:            :
+  *    +----< SB_BORDER_WIDTH
+  *     :            :
+  *     :............:
+  *           |
+  *           +---< SB_WIDTH_NEXT
+  */
+
+#define NO_REFRESH             0       /* Window not visible at all!        */
+#define FAST_REFRESH           (1<<0)  /* Fully exposed window              */
+#define SLOW_REFRESH           (1<<1)  /* Partially exposed window          */
+#define SMOOTH_REFRESH         (1<<2)  /* Do sync'ing to make it smooth     */
+#define REFRESH_BOUNDS         (1<<3)
+
+#ifdef NO_SECONDARY_SCREEN
+# define NSCREENS              0
+#else
+# define NSCREENS              1
+#endif
+
+#define IGNORE                 0
+#define SAVE                   's'
+#define RESTORE                        'r'
+
+/* special (internal) prefix for font commands */
+#define FONT_CMD               '#'
+#define FONT_DN                        "#-"
+#define FONT_UP                        "#+"
+
+/* flags for rxvt_scr_gotorc() */
+#define C_RELATIVE             1       /* col movement is relative */
+#define R_RELATIVE             2       /* row movement is relative */
+#define RELATIVE               (R_RELATIVE|C_RELATIVE)
+
+/* modes for rxvt_scr_insdel_chars(), rxvt_scr_insdel_lines() */
+#define INSERT                 -1      /* don't change these values */
+#define DELETE                 +1
+#define ERASE                  +2
+
+/* modes for rxvt_scr_page() - scroll page. used by scrollbar window */
+enum page_dirn {
+    UP,
+    DN,
+    NO_DIR
+};
+
+/* arguments for rxvt_scr_change_screen() */
+enum {
+    PRIMARY = 0,
+    SECONDARY
+};
+
+enum {
+    SBYTE = 0,
+    WBYTE
+};
+
+
+#define RS_None                        0       /* Normal */
+
+#define RS_fgMask              0x000001FFu     /* 512 colors */
+#define RS_bgMask              0x0003FE00u     /* 512 colors */
+#define RS_Bold                        0x00040000u     /* bold */
+#define RS_Blink               0x00080000u     /* blink */
+#define RS_RVid                        0x00100000u     /* reverse video */
+#define RS_Uline               0x00200000u     /* underline */
+
+#define RS_wide                        0x00400000u     /* only multibyte characters */
+#define IS_WIDE(r)             ((r) & RS_wide)
+
+#define RS_fontMask            0xff000000u     /* plenty(?) of fonts */
+#define RS_fontShift           24
+
+#define RS_baseattrMask                (RS_Bold|RS_Blink|RS_RVid|RS_Uline)
+#define RS_attrMask            (RS_baseattrMask|RS_fontMask|RS_wide)
+
+#define Sel_none               0       /* Not waiting */
+#define Sel_normal             0x01    /* normal selection */
+#define Sel_incr               0x02    /* incremental selection */
+#define Sel_direct             0x00
+#define Sel_Primary            0x01
+#define Sel_Secondary          0x02
+#define Sel_Clipboard          0x03
+#define Sel_whereMask          0x0f
+#define Sel_CompoundText       0x10    /* last request was Compound */
+
+enum {
+    C0_NUL = 0x00,
+            C0_SOH, C0_STX, C0_ETX, C0_EOT, C0_ENQ, C0_ACK, C0_BEL,
+    C0_BS , C0_HT , C0_LF , C0_VT , C0_FF , C0_CR , C0_SO , C0_SI ,
+    C0_DLE, C0_DC1, C0_DC2, D0_DC3, C0_DC4, C0_NAK, C0_SYN, C0_ETB,
+    C0_CAN, C0_EM , C0_SUB, C0_ESC, C0_IS4, C0_IS3, C0_IS2, C0_IS1
+}; 
+#define CHAR_ST                        0x9c    /* 0234 */
+
+/*
+ * XTerm Operating System Commands: ESC ] Ps;Pt (ST|BEL)
+ * colour extensions by Christian W. Zuckschwerdt <zany@triq.net>
+ */
+#define XTerm_name             0
+#define XTerm_iconName         1
+#define XTerm_title            2
+#define XTerm_Color            4       /* change colors */
+#define XTerm_Color_cursor     12      /* change actual 'Cursor' color */
+#define XTerm_Color_pointer    13      /* change actual 'Pointer' color */
+#define XTerm_Color_RV         17      /* change actual 'Highlight' color */
+#define XTerm_Color_BD         18      /* change actual 'Bold' color */
+#define XTerm_Color_UL         19      /* change actual 'Underline' color */
+#define XTerm_logfile          46      /* not implemented */
+#define XTerm_font             50
+
+/*
+ * rxvt extensions of XTerm OSCs: ESC ] Ps;Pt (ST|BEL)
+ */
+#define XTerm_Menu             10      /* set menu item */
+#define XTerm_Pixmap           20      /* new bg pixmap */
+#define XTerm_restoreFG                39      /* change default fg color */
+#define XTerm_restoreBG                49      /* change default bg color */
+#define XTerm_dumpscreen       55      /* dump scrollback and all of screen */
+
+/* Words starting with `Color_' are colours.  Others are counts */
+/*
+ * The following comment is mostly obsolete since pixcolor_set was expanded:
+ * We're currently upto 29 colours.  Only 3 more available.  The
+ * PixColor and rendition colour usage should probably be decoupled
+ * on the unnecessary items, e.g. Color_pointer, but won't bother
+ * until we need to.  Also, be aware of usage in pixcolor_set
+ */
+
+enum colour_list {
+    Color_fg = 0,
+    Color_bg,
+    minCOLOR,                  /* 2 */
+    Color_Black = minCOLOR,
+    Color_Red3,
+    Color_Green3,
+    Color_Yellow3,
+    Color_Blue3,
+    Color_Magenta3,
+    Color_Cyan3,
+    maxCOLOR,                  /* minCOLOR + 7 */
+#ifndef NO_BRIGHTCOLOR
+    Color_AntiqueWhite = maxCOLOR,
+    minBrightCOLOR,            /* maxCOLOR + 1 */
+    Color_Grey25 = minBrightCOLOR,
+    Color_Red,
+    Color_Green,
+    Color_Yellow,
+    Color_Blue,
+    Color_Magenta,
+    Color_Cyan,
+    maxBrightCOLOR,            /* minBrightCOLOR + 7 */
+    Color_White = maxBrightCOLOR,
+#else
+    Color_White = maxCOLOR,
+#endif
+#ifdef TTY_256COLOR
+    min256COLOR = Color_White + 1,
+    max256COLOR = minCOLOR + 255,
+#endif
+#ifndef NO_CURSORCOLOR
+    Color_cursor,
+    Color_cursor2,
+#endif
+    Color_pointer,
+    Color_border,
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+    Color_BD,
+    Color_UL,
+    Color_RV,
+#endif
+#ifdef OPTION_HC
+    Color_HC,
+#endif
+#ifdef KEEP_SCROLLCOLOR
+    Color_scroll,
+    Color_trough,
+#endif
+    NRS_COLORS,                        /* */
+#ifdef KEEP_SCROLLCOLOR
+    Color_topShadow = NRS_COLORS,
+    Color_bottomShadow,
+    TOTAL_COLORS               /* upto 30 */
+#else
+    TOTAL_COLORS = NRS_COLORS  /* */
+#endif
+};
+
+#define Color_Bits     9
+#define NPIXCLR_SETS   9       /* (256 + 14) bits / 32 bits */
+#define NPIXCLR_BITS   32
+
+#define DEFAULT_RSTYLE         (RS_None | (Color_fg) | (Color_bg<<Color_Bits))
+
+/*
+ * Resource list
+ */
+enum {
+    Rs_display_name = 0,
+    Rs_term_name,
+    Rs_iconName,
+    Rs_geometry,
+    Rs_reverseVideo,
+    Rs_color,
+    _Rs_color = Rs_color + NRS_COLORS - 1,
+    Rs_font,
+    Rs_name,
+    Rs_title,
+#if defined (XPM_BACKGROUND) || (MENUBAR_MAX)
+    Rs_path,
+#endif
+#ifdef XPM_BACKGROUND
+    Rs_backgroundPixmap,
+#endif
+#if (MENUBAR_MAX)
+    Rs_menu,
+#endif
+#ifndef NO_BOLDFONT
+    Rs_boldFont,
+#endif
+#ifdef GREEK_SUPPORT
+    Rs_greek_keyboard,
+    Rs_greektoggle_key,
+#endif
+    Rs_loginShell,
+    Rs_jumpScroll,
+#ifdef HAVE_SCROLLBARS
+    Rs_scrollBar,
+    Rs_scrollBar_right,
+    Rs_scrollBar_floating,
+    Rs_scrollBar_align,
+#endif
+    Rs_scrollstyle,    /* Rs_scrollBar_style */
+    Rs_scrollTtyOutput,
+    Rs_scrollTtyKeypress,
+    Rs_scrollWithBuffer,
+    Rs_saveLines,
+    Rs_utmpInhibit,
+    Rs_visualBell,
+#if ! defined(NO_MAPALERT) && defined(MAPALERT_OPTION)
+    Rs_mapAlert,
+#endif
+#ifdef META8_OPTION
+    Rs_meta8,
+#endif
+#ifdef MOUSE_WHEEL
+    Rs_mouseWheelScrollPage,
+#endif
+#ifndef NO_BACKSPACE_KEY
+    Rs_backspace_key,
+#endif
+#ifndef NO_DELETE_KEY
+    Rs_delete_key,
+#endif
+    Rs_selectstyle,
+#ifdef PRINTPIPE
+    Rs_print_pipe,
+#endif
+#ifdef USE_XIM
+    Rs_preeditType,
+    Rs_inputMethod,
+#endif
+#if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
+    Rs_bigfont_key,
+    Rs_smallfont_key,
+#endif
+#ifdef TRANSPARENT
+    Rs_transparent,
+    Rs_transparent_all,
+#endif
+#ifndef NO_FRILLS
+    Rs_ext_bwidth,
+    Rs_int_bwidth,
+#endif
+    Rs_scrollBar_thickness,
+#ifndef NO_LINESPACE
+    Rs_lineSpace,
+#endif
+    Rs_cutchars,
+#ifdef ACS_ASCII
+    Rs_acs_chars,
+#endif
+    Rs_modifier,
+    Rs_answerbackstring,
+    Rs_tripleclickwords,
+    Rs_cursorBlink,
+    Rs_pointerBlank,
+    Rs_pointerBlankDelay,
+    NUM_RESOURCES
+} ;
+
+enum {
+    TIMEOUT_INCR = 0,
+    NUM_TIMEOUTS
+} ;
+
+enum {
+    XA_COMPOUND_TEXT = 0,
+    XA_MULTIPLE,
+    XA_TARGETS,
+    XA_TEXT,
+    XA_TIMESTAMP,
+    XA_VT_SELECTION,
+    XA_INCR,
+    XA_WMDELETEWINDOW,
+#ifdef TRANSPARENT
+    XA_XROOTPMAPID,
+#endif
+#ifdef OFFIX_DND               /* OffiX Dnd (drag 'n' drop) support */
+    XA_DNDPROTOCOL,
+    XA_DNDSELECTION,
+#endif                         /* OFFIX_DND */
+    XA_CLIPBOARD,
+    NUM_XA
+} ;
+
+/*
+ * number of graphics points
+ * divisible by 2 (num lines)
+ * divisible by 4 (num rect)
+ */
+#define        NGRX_PTS        1000
+
+/* DEC private modes */
+#define PrivMode_132           (1LU<<0)
+#define PrivMode_132OK         (1LU<<1)
+#define PrivMode_rVideo                (1LU<<2)
+#define PrivMode_relOrigin     (1LU<<3)
+#define PrivMode_Screen                (1LU<<4)
+#define PrivMode_Autowrap      (1LU<<5)
+#define PrivMode_aplCUR                (1LU<<6)
+#define PrivMode_aplKP         (1LU<<7)
+#define PrivMode_HaveBackSpace (1LU<<8)
+#define PrivMode_BackSpace     (1LU<<9)
+#define PrivMode_ShiftKeys     (1LU<<10)
+#define PrivMode_VisibleCursor (1LU<<11)
+#define PrivMode_MouseX10      (1LU<<12)
+#define PrivMode_MouseX11      (1LU<<13)
+#define PrivMode_scrollBar     (1LU<<14)
+#define PrivMode_menuBar       (1LU<<15)
+#define PrivMode_TtyOutputInh  (1LU<<16)
+#define PrivMode_Keypress      (1LU<<17)
+#define PrivMode_smoothScroll  (1LU<<18)
+#define PrivMode_vt52          (1LU<<19)
+/* too annoying to implement X11 highlight tracking */
+/* #define PrivMode_MouseX11Track       (1LU<<18) */
+
+#define PrivMode_mouse_report  (PrivMode_MouseX10|PrivMode_MouseX11)
+#define PrivMode(test,bit)             \
+    if (test)                          \
+       R->h->PrivateModes |= (bit);    \
+    else                               \
+       R->h->PrivateModes &= ~(bit)
+
+#ifdef ALLOW_132_MODE
+# define PrivMode_Default                                               \
+(PrivMode_Autowrap|PrivMode_aplKP|PrivMode_ShiftKeys|PrivMode_VisibleCursor|PrivMode_132OK)
+#else
+# define PrivMode_Default                                               \
+(PrivMode_Autowrap|PrivMode_aplKP|PrivMode_ShiftKeys|PrivMode_VisibleCursor)
+#endif
+
+#ifdef PREFER_24BIT
+# define XDEPTH                        R->Xdepth
+# define XCMAP                 R->Xcmap
+# define XVISUAL               R->h->Xvisual
+#else
+# ifdef DEBUG_DEPTH
+#  define XDEPTH               DEBUG_DEPTH
+# else
+#  define XDEPTH               DefaultDepth(R->Xdisplay,Xscreen)
+#  define XCMAP                        DefaultColormap(R->Xdisplay,Xscreen)
+#  define XVISUAL              DefaultVisual(R->Xdisplay,Xscreen)
+# endif
+#endif
+#define IMBUFSIZ               128     /* input modifier buffer sizes */
+#ifndef BUFSIZ
+# define BUFSIZ                        4096
+#endif
+#define KBUFSZ                 512     /* size of keyboard mapping buffer */
+
+/*
+ *****************************************************************************
+ * MACRO DEFINES
+ *****************************************************************************
+ */
+#define MEMSET(x, y, z)                memset((x), (y), (size_t)(z))
+#define MEMCPY(x, y, z)                memcpy((void *)(x), (const void *)(y), (z))
+#define MEMMOVE(x, y, z)       memmove((void *)(x), (const void *)(y), (z))
+#define STRCASECMP(x, y)       strcasecmp((x), (y))
+#define STRNCASECMP(x, y, z)   strncasecmp((x), (y), (z))
+#define STRCPY(x, y)           strcpy((char *)(x), (const char *)(y))
+#define STRNCPY(x, y, z)       strncpy((char *)(x), (const char *)(y), (z))
+#define STRCMP(x, y)           strcmp((const char *)(x), (const char *)(y))
+#define STRNCMP(x, y, z)       strncmp((const char *)(x), (const char *)(y), (z))
+#define STRCAT(x, y)           strcat((char *)(x), (const char *)(y))
+#define STRNCAT(x, y, z)       strncat((char *)(x), (const char *)(y), (z))
+#define STRDUP(x)              strdup((const char *)(x))
+#define STRLEN(x)              strlen((const char *)(x))
+#define STRCHR(x, y)           strchr((const char *)(x), (int)(y))
+#define STRRCHR(x, y)          strrchr((const char *)(x), (int)(y))
+
+/* convert pixel dimensions to row/column values.  Everything as int32_t */
+#define Pixel2Col(x)           Pixel2Width((int32_t)(x) - (int32_t)R->TermWin.int_bwidth)
+#define Pixel2Row(y)           Pixel2Height((int32_t)(y) - (int32_t)R->TermWin.int_bwidth)
+#define Pixel2Width(x)         ((int32_t)(x) / (int32_t)R->TermWin.fwidth)
+#define Pixel2Height(y)                ((int32_t)(y) / (int32_t)R->TermWin.fheight)
+#define Col2Pixel(col)         ((int32_t)Width2Pixel(col) + (int32_t)R->TermWin.int_bwidth)
+#define Row2Pixel(row)         ((int32_t)Height2Pixel(row) + (int32_t)R->TermWin.int_bwidth)
+#define Width2Pixel(n)         ((int32_t)(n) * (int32_t)R->TermWin.fwidth)
+#define Height2Pixel(n)                ((int32_t)(n) * (int32_t)R->TermWin.fheight)
+
+#define TermWin_TotalWidth()   ((int32_t)R->TermWin.width  + 2 * (int32_t)R->TermWin.int_bwidth)
+#define TermWin_TotalHeight()  ((int32_t)R->TermWin.height + 2 * (int32_t)R->TermWin.int_bwidth)
+
+#define Xscreen                        DefaultScreen(R->Xdisplay)
+#define Xroot                  DefaultRootWindow(R->Xdisplay)
+
+/* how to build & extract colors and attributes */
+#define GET_BASEFG(x)          (((x) & RS_fgMask))
+#define GET_BASEBG(x)          (((x) & RS_bgMask)>>Color_Bits)
+#ifndef NO_BRIGHTCOLOR
+# define GET_FGCOLOR(x)                                                \
+    ((((x) & RS_Bold) == 0                                     \
+      || GET_BASEFG(x) < minCOLOR                              \
+      || GET_BASEFG(x) >= minBrightCOLOR)                      \
+     ? GET_BASEFG(x)                                           \
+     : (GET_BASEFG(x) + (minBrightCOLOR - minCOLOR)))
+# define GET_BGCOLOR(x)                                                \
+    ((((x) & RS_Blink) == 0                                    \
+      || GET_BASEBG(x) < minCOLOR                              \
+      || GET_BASEBG(x) >= minBrightCOLOR)                      \
+     ? GET_BASEBG(x)                                           \
+     : (GET_BASEBG(x) + (minBrightCOLOR - minCOLOR)))
+#else
+# define GET_FGCOLOR(x)                GET_BASEFG(x)
+# define GET_BGCOLOR(x)                GET_BASEBG(x)
+#endif
+
+#define GET_FONT(x)            (((x) & RS_fontMask) >> RS_fontShift)
+#define SET_FONT(x,fid)                ((x) & ~RS_fontMask) | ((fid) << RS_fontShift)
+
+#define GET_ATTR(x)            (((x) & RS_attrMask))
+#define GET_BGATTR(x)                                                  \
+    (((x) & RS_RVid) ? (((x) & (RS_attrMask & ~RS_RVid))               \
+                       | (((x) & RS_fgMask)<<Color_Bits))              \
+                    : ((x) & (RS_attrMask | RS_bgMask)))
+#define SET_FGCOLOR(x,fg)      (((x) & ~RS_fgMask)  | (fg))
+#define SET_BGCOLOR(x,bg)      (((x) & ~RS_bgMask)  | ((bg)<<Color_Bits))
+#define SET_ATTR(x,a)          (((x) & ~RS_attrMask)| (a))
+
+#define SET_PIXCOLOR(h, x)     ((h)->pixcolor_set[(x) / NPIXCLR_BITS] |= (1 << ((x) % NPIXCLR_BITS)))
+#define ISSET_PIXCOLOR(h, x)   ((h)->pixcolor_set[(x) / NPIXCLR_BITS] & (1 << ((x) % NPIXCLR_BITS)))
+
+#ifdef HAVE_SCROLLBARS
+# define scrollbar_TotalWidth()        (R->scrollBar.width + R->sb_shadow * 2)
+#else
+# define scrollbar_TotalWidth()        (0)
+#endif
+#define scrollbar_isMotion()   (R->scrollBar.state == 'm')
+#define scrollbar_isUp()       (R->scrollBar.state == 'U')
+#define scrollbar_isDn()       (R->scrollBar.state == 'D')
+#define scrollbar_isUpDn()     isupper (R->scrollBar.state)
+#define isScrollbarWindow(w)   (R->scrollBar.state && (w) == R->scrollBar.win)
+
+#define scrollbar_setIdle()    R->scrollBar.state = 1
+#define scrollbar_setMotion()  R->scrollBar.state = 'm'
+#define scrollbar_setUp()      R->scrollBar.state = 'U'
+#define scrollbar_setDn()      R->scrollBar.state = 'D'
+
+#define scrollbarnext_dnval()  (R->scrollBar.end + (R->scrollBar.width + 1))
+#define scrollbarnext_upButton(y)      ((y) > R->scrollBar.end \
+                                        && (y) <= scrollbarnext_dnval())
+#define scrollbarnext_dnButton(y)      ((y) > scrollbarnext_dnval())
+#define SCROLLNEXT_MINHEIGHT   SB_THUMB_MIN_HEIGHT
+#define scrollbarrxvt_upButton(y)      ((y) < R->scrollBar.beg)
+#define scrollbarrxvt_dnButton(y)      ((y) > R->scrollBar.end)
+#define SCROLLRXVT_MINHEIGHT   10
+#define SCROLLXTERM_MINHEIGHT  10
+
+#define scrollbar_minheight()  (R->scrollBar.style == R_SB_NEXT        \
+                                ? SCROLLNEXT_MINHEIGHT                 \
+                                : SCROLLRXVT_MINHEIGHT)
+#define scrollbar_above_slider(y)      ((y) < R->scrollBar.top)
+#define scrollbar_below_slider(y)      ((y) > R->scrollBar.bot)
+#define scrollbar_position(y)          ((y) - R->scrollBar.beg)
+#define scrollbar_size()               (R->scrollBar.end - R->scrollBar.beg \
+                                        - scrollbar_minheight())
+
+#if (MENUBAR_MAX > 1)
+/* rendition style flags */
+# define menuBar_height()      (R->TermWin.fheight + SHADOW)
+# define menuBar_TotalHeight() (menuBar_height() + SHADOW + menuBar_margin)
+# define isMenuBarWindow(w)    ((w) == R->menuBar.win)
+#else
+# define menuBar_height()      (0)
+# define menuBar_TotalHeight() (0)
+# define isMenuBarWindow(w)    (0)
+#endif
+
+#ifdef XPM_BACKGROUND
+# define XPMClearArea(a, b, c, d, e, f, g)     XClearArea((a), (b), (c), (d), (e), (f), (g))
+#else
+# define XPMClearArea(a, b, c, d, e, f, g)
+#endif
+
+#ifndef STRICT_FONT_CHECKING
+# define rxvt_get_fontwidest(font)     ((font)->max_bounds.width)
+#endif
+
+#define rxvt_Gr_ButtonPress(x,y)       rxvt_Gr_ButtonReport (r, 'P',(x),(y))
+#define rxvt_Gr_ButtonRelease(x,y)     rxvt_Gr_ButtonReport (r, 'R',(x),(y))
+
+#ifdef UTMP_SUPPORT
+# if !defined(RXVT_UTMPX_FILE) || !defined(HAVE_STRUCT_UTMPX)
+#  undef HAVE_UTMPX_H
+#  undef HAVE_STRUCT_UTMPX
+# endif
+# if !defined(RXVT_UTMP_FILE) || !defined(HAVE_STRUCT_UTMP)
+#  undef HAVE_UTMP_H
+#  undef HAVE_STRUCT_UTMP
+# endif
+
+# ifdef HAVE_UTMPX_H
+#  include <utmpx.h>
+# endif
+# ifdef HAVE_UTMP_H
+#  include <utmp.h>
+# endif
+#endif
+
+#ifdef DEBUG_CMD
+# define D_CMD(x)              fprintf x ; fputc('\n', stderr)
+#else
+# define D_CMD(x)
+#endif
+#ifdef DEBUG_INIT
+# define D_INIT(x)             fprintf x ; fputc('\n', stderr)
+#else
+# define D_INIT(x)
+#endif
+#ifdef DEBUG_MAIN
+# define D_MAIN(x)             fprintf x ; fputc('\n', stderr)
+#else
+# define D_MAIN(x)
+#endif
+#ifdef DEBUG_SCREEN
+# define D_SCREEN(x)           fprintf x ; fputc('\n', stderr)
+#else
+# define D_SCREEN(x)
+#endif
+#ifdef DEBUG_SELECT
+# define D_SELECT(x)           fprintf x ; fputc('\n', stderr)
+#else
+# define D_SELECT(x)
+#endif
+#ifdef DEBUG_SIZE
+# define D_SIZE(x)             fprintf x ; fputc('\n', stderr)
+#else
+# define D_SIZE(x)
+#endif
+#ifdef DEBUG_X
+# define D_X(x)                        fprintf x ; fputc('\n', stderr)
+#else
+# define D_X(x)
+#endif
+
+/*
+ *****************************************************************************
+ * VARIABLES
+ *****************************************************************************
+ */
+#ifdef MENUBAR
+# include "menubar.h"
+#endif
+
+struct mbstate {
+  unsigned char orig;
+  uint32_t reg;
+  int cnt;
+
+  mbstate ()
+  {
+    cnt = 0;
+  }
+};
+
+struct rxvt_hidden {
+    struct          mbstate mbstate;
+#ifdef __GNUC__
+    unsigned char   want_refresh:1,
+                    want_full_refresh:1,
+                    am_transparent:1,
+                    am_pixmap_trans:1, 
+                    current_screen:1,
+                    hate_those_clicks:1,
+                    num_scr_allow:1,
+                    bypass_keystate:1;
+    unsigned char   chstat:1,
+                    lost_multi:1,
+                    multi_byte:1,
+                    hidden_cursor:1,
+                    hidden_pointer:1,
+                    parsed_geometry:1;
+#else
+    unsigned char   want_refresh,
+# ifdef TRANSPARENT
+                    want_full_refresh, /* awaiting full screen refresh      */
+# endif
+# if defined(XPM_BACKGROUND) || defined(TRANSPARENT)
+                    am_transparent,    /* is a transparent term             */
+                    am_pixmap_trans,   /* transparency w/known root pixmap  */
+# endif
+                    current_screen,    /* primary or secondary              */
+                    hate_those_clicks, /* a.k.a. keep mark position         */
+                    num_scr_allow,
+                    bypass_keystate,
+# ifdef MULTICHAR_SET
+                    chstat,
+                    lost_multi,        /* set ==> we only got half a glyph */
+                    multi_byte,        /* set ==> currently using 2 bytes per glyph */
+# endif
+# ifdef CURSOR_BLINK
+                    hidden_cursor,
+# endif
+# ifdef POINTER_BLANK
+                    hidden_pointer,
+# endif
+                    parsed_geometry;
+#endif /* !__GNUC__ */
+
+    unsigned char   refresh_type,
+#ifdef UTMP_SUPPORT
+                    next_utmp_action,
+#endif
+#ifndef NO_SETOWNER_TTYDEV
+                    next_tty_action,
+#endif
+#ifdef META8_OPTION
+                    meta_char, /* Alt-key prefix                            */
+#endif
+                   scrollbar_align,
+                    selection_wait,
+                    selection_type;
+/* ---------- */
+#ifdef GREEK_SUPPORT
+    short           greek_mode;                /* greek keyboard mode               */
+#endif
+    short           rvideo;
+    int16_t         num_scr;   /* screen: number lines scrolled             */
+    uint16_t       prev_ncol,  /* screen: previous number of columns        */
+                    prev_nrow; /* screen: previous number of rows           */
+#ifdef RXVT_GRAPHICS
+    uint16_t       gr_prev_start;
+#endif
+/* ---------- */
+    rend_t          rstyle;
+/* ---------- */
+    uint32_t       pixcolor_set[NPIXCLR_SETS];
+/* ---------- */
+#ifdef SELECTION_SCROLLING
+    int                    scroll_selection_delay,
+                   scroll_selection_lines;
+    enum page_dirn  scroll_selection_dir;
+    int                    selection_save_x,
+                   selection_save_y,
+                   selection_save_state,
+                   pending_scroll_selection;
+#endif
+/* ---------- */
+    int             csrO,      /* Hops - csr offset in thumb/slider to      */
+                               /*   give proper Scroll behaviour            */
+#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
+                    scroll_arrow_delay,
+#endif
+#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
+                   mouse_slip_wheel_delay,
+                   mouse_slip_wheel_speed,
+#endif
+                    refresh_count,
+                    refresh_limit,
+                    fnum,      /* logical font number                       */
+                    last_bot,  /* scrollbar last bottom position            */
+                    last_top,  /* scrollbar last top position               */
+                    last_state,        /* scrollbar last state                      */
+                    scrollbar_len,
+                    currmaxcol,
+#ifdef MENUBAR
+                    menu_readonly,     /* okay to alter menu? */
+                    Arrows_x,
+#endif
+#if (MENUBAR_MAX > 1)
+                    Nbars,
+#endif
+                    window_vt_x,
+                    window_vt_y,
+                    window_sb_x,
+# ifdef POINTER_BLANK
+                   pointerBlankDelay,
+# endif
+                    allowedxerror;
+/* ---------- */
+    unsigned int    ModMetaMask,
+                    ModNumLockMask,
+                    old_width, /* last used width in screen resize          */
+                    old_height,        /* last used height in screen resize         */
+#ifndef NO_BRIGHTCOLOR
+                    colorfgbg,
+#endif
+                    ttymode;
+    unsigned long   PrivateModes,
+                    SavedModes;
+/* ---------- */
+#ifdef PREFER_24BIT
+    Visual         *Xvisual;
+#endif
+/* ---------- */
+    Atom            xa[NUM_XA];
+/* ---------- */
+#ifdef MENUBAR
+    GC              menubarGC;
+#endif
+#if defined(MENUBAR) || defined(RXVT_SCROLLBAR)
+    GC              scrollbarGC,
+                    topShadowGC,
+                    botShadowGC;
+#endif
+#ifdef XTERM_SCROLLBAR
+    GC              xscrollbarGC,
+                    ShadowGC;
+#endif
+#ifdef NEXT_SCROLLBAR
+    GC              blackGC,
+                    whiteGC,
+                    grayGC,
+                    darkGC,
+                    stippleGC;
+    Pixmap          dimple,
+                    upArrow,
+                    downArrow,
+                    upArrowHi,
+                    downArrowHi;
+#endif
+/* ---------- */
+    Time            selection_time,
+                    selection_request_time;
+    pid_t           cmd_pid;   /* process id of child */
+    gid_t           ttygid;
+#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__)
+    uid_t           euid;
+    gid_t           egid;
+#endif
+/* ---------- */
+    Cursor          pointer_leftptr;
+#ifdef POINTER_BLANK
+    Cursor          pointer_blank;
+#endif
+/* ---------- */
+    const char     *ttydev;    /* pty/tty name */
+#ifndef NO_BACKSPACE_KEY
+    const char     *key_backspace;
+#endif
+#ifndef NO_DELETE_KEY
+    const char     *key_delete;
+#endif
+#if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
+    KeySym          ks_bigfont, ks_smallfont;
+#endif
+#ifdef GREEK_SUPPORT
+    KeySym          ks_greekmodeswith;
+#endif
+#ifdef USE_XIM
+    XIC             Input_Context;
+    XIMStyle        input_style;
+    int             event_type;
+#endif
+    struct mouse_event MEvent;
+    XComposeStatus  compose;
+#ifdef RXVT_GRAPHICS
+    int             graphics_up;
+    struct grwin_t *gr_root;
+#endif
+    ttymode_t       tio;
+#ifdef UTMP_SUPPORT
+# ifdef HAVE_STRUCT_UTMP
+    struct utmp     ut;
+# endif
+# ifdef HAVE_STRUCT_UTMPX
+    struct utmpx    utx;
+# endif
+# if (defined(HAVE_STRUCT_UTMP) && defined(HAVE_UTMP_PID)) || defined(HAVE_STRUCT_UTMPX)
+    char            ut_id[5];
+# endif
+    int             utmp_pos;
+#endif
+    row_col_t       oldcursor;
+#ifdef XPM_BACKGROUND
+    bgPixmap_t      bgPixmap;
+    XpmAttributes   xpmAttr;   /* originally loaded pixmap and its scaling */
+#endif
+#ifdef MULTICHAR_SET
+    int             oldcursormulti;
+    void            (*multichar_decode)(unsigned char *str, int len);
+#endif
+#ifndef RESET_TTY_TO_COMMON_DEFAULTS
+    struct stat     ttyfd_stat;        /* original status of our tty */
+#endif
+#ifdef MENUBAR
+    menu_t         *ActiveMenu,                /* currently active menu */
+                   *BuildMenu;         /* the menu currently being built */
+    bar_t          *CurrentBar;
+# if !(MENUBAR_MAX > 1)
+    bar_t           BarList;
+# endif                                /* (MENUBAR_MAX > 1) */
+#endif
+#ifdef RXVT_GRAPHICS
+    Window          gr_last_id;
+#endif
+#ifdef CURSOR_BLINK
+    struct timeval  lastcursorchange;
+#endif
+#ifdef POINTER_BLANK
+    struct timeval  lastmotion;
+#endif
+    struct timeval  timeout[NUM_TIMEOUTS];
+
+/* these three don't need to be kept but do so to placate some mem checkers */
+    char           *env_windowid;      /* environmental variable WINDOWID */
+    char          *env_display;        /* environmental variable DISPLAY  */
+    char          *env_term;           /* environmental variable TERM     */
+    char           *env_colorfgbg;
+    char           *buffer;
+    char           *locale;
+    char            charsets[4];
+    unsigned char  *v_buffer;  /* pointer to physical buffer */
+    unsigned char  *v_bufstr;  /* beginning of area to write */
+    unsigned char  *v_bufptr;  /* end of area to write */
+    unsigned char  *v_bufend;  /* end of physical buffer */
+    char           *newfont[MAX_NFONTS];
+#ifdef KEYSYM_RESOURCE
+    const unsigned char *Keysym_map[256];
+#endif
+    const char     *rs[NUM_RESOURCES];
+/* command input buffering */
+    unsigned char  *cmdbuf_ptr, *cmdbuf_endp;
+    unsigned char   cmdbuf_base[BUFSIZ];
+    unsigned char   kbuf[KBUFSZ];
+};
+
+#ifndef __attribute__
+# ifdef __GNUC__
+#  if (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || (__GNUC__ < 2)
+#   define __attribute__(x)
+#  endif
+# endif
+# define __attribute__(x)
+#endif
+
+/*
+ *****************************************************************************
+ * PROTOTYPES
+ *****************************************************************************
+ */
+#ifdef PROTOTYPES
+# define __PROTO(p)    p
+#else
+# define __PROTO(p)    ()
+#endif
+#include "protos.h"
+
+#ifdef DEBUG_malloc
+# include "dmalloc.h"          /* This comes last */
+#endif
+
+#endif                         /* _RXVT_H_ */
diff --git a/src/rxvtgrx.h b/src/rxvtgrx.h
new file mode 100644 (file)
index 0000000..650041e
--- /dev/null
@@ -0,0 +1,54 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       rxvtgrx.h
+ * $Id: rxvtgrx.h,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Stuff for text alignment for rxvt special graphics mode
+ *
+ * alignment
+ * Top:
+ *     text is placed so that the specified point is at the top of the
+ *     capital letters
+ * Center:
+ *     text is placed so that the specified point is equidistant from the
+ *     bottom of descenders and the top of the capital letters
+ * Bottom:
+ *     text is placed so that the bottom of descenders is on the specified
+ *     point
+ * Base:
+ *     text is placed so that the bottom of the characters with no descenders
+ *     is on the specified point
+ * Caps_Center:
+ *     text is placed so that the specified point is equidistant from the
+ *     bottom and tops of capital letters
+ *----------------------------------------------------------------------*/
+#ifndef _RXVTGRX_H_
+#define _RXVTGRX_H_
+
+#define GRX_SCALE              10000
+
+#define RIGHT_TEXT             0x10
+#define HCENTER_TEXT           0x20
+#define LEFT_TEXT              0x30
+#define HORIZONTAL_ALIGNMENT   0x70
+
+#define TOP_TEXT               0x01
+#define VCENTER_TEXT           0x02
+#define BOTTOM_TEXT            0x03
+#define BASE_TEXT              0x04
+#define VCAPS_CENTER_TEXT      0x05
+#define VERTICAL_ALIGNMENT     0x0F
+
+#if 0  /* this would be nicer */
+# define TXT_RIGHT             'r'
+# define TXT_CENTER            'c'
+# define TXT_LEFT              'l'
+
+# define TXT_TOP               't'
+# define TXT_VCENTER           'v'
+# define TXT_BOTTOM            'b'
+# define TXT_BASE              '_'
+# define TXT_VCAPS_CENTER      'C'
+#endif
+
+#endif /* _RXVTGRX_H_ */
+/*----------------------- end-of-file (C header) -----------------------*/
diff --git a/src/rxvtlib.h.in b/src/rxvtlib.h.in
new file mode 100644 (file)
index 0000000..96fccc2
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * $Id: rxvtlib.h.in,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ */
+
+#ifndef _RXVTLIB_H_            /* include once only */
+#define _RXVTLIB_H_
+
+/*
+ * section 1 generated by GNU autoconf for @build@
+ * this section may be changed as appropriate _before_ building
+ */
+/*****************************************************************************
+ *                                 SECTION 1                                 *
+ *****************************************************************************/
+
+/*
+ * The following line MUST not be changed without also changing
+ * config.h in the main directory before building
+ */
+// none anymore
+
+/*****************************************************************************
+ *                                 INCLUDES                                  *
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+@include_stdarg_h@
+@include_stdlib_h@
+@include_stdint_h@
+#include <sys/types.h>
+@include_unistd_h@
+@include_string_h@
+@include_fcntl_h@
+@include_util_h@
+@include_assert_h@
+@include_sys_ioctl_h@
+@include_sys_time_h@
+@include_time_h@
+@include_sys_select_h@
+@include_sys_strredir_h@
+
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+extern "C" {
+#include <X11/Intrinsic.h>     /* Xlib, Xutil, Xresource, Xfuncproto */
+}
+
+/*
+ * If we haven't pulled in typedef's like  int16_t  then do them ourself
+ * type of (normal and unsigned) basic sizes
+ */
+@rxvt_int16_typedef@
+@rxvt_uint16_typedef@
+@rxvt_int32_typedef@
+@rxvt_uint32_typedef@
+
+/* whatever normal size corresponds to a integer pointer */
+@rxvt_intp_define@
+/* whatever normal size corresponds to a unsigned integer pointer */
+@rxvt_u_intp_define@
+
+/*****************************************************************************
+ *                                 SECTION 2                                 *
+ *                      DO NOT TOUCH ANYTHING BELOW HERE                     *
+ *****************************************************************************/
+
+struct rxvt_fontset;
+struct rxvt_color;
+struct rxvt_vars;              /* defined later on */
+struct rxvt_hidden;            /* not defined here */
+
+extern struct rxvt_vars *rxvt_current_term;
+
+#if EXPLICIT_CONTEXT
+
+# define pR struct rxvt_vars *rxvt_term
+# define aR rxvt_term
+# define pR_ pR,
+# define aR_ aR,
+
+# define R rxvt_term
+
+# define SET_R(r) rxvt_current_term = (r)
+# define GET_R rxvt_current_term
+
+#else
+
+# define pR
+# define pR_
+# define aR
+# define aR_
+
+# define R rxvt_current_term
+
+# define SET_R(r) rxvt_current_term = (r)
+# define GET_R R
+
+#endif
+
+#define dR rxvt_t *rxvt_term = GET_R
+
+#define scrollbar_visible(rxvtvars)    ((rxvtvars)->scrollBar.state)
+#define menubar_visible(rxvtvars)      ((rxvtvars)->menuBar.state)
+
+typedef struct {
+    int32_t         row;
+    int32_t         col;
+} row_col_t;
+
+#if UNICODE3
+typedef uint32_t text_t;
+#else
+typedef uint16_t text_t; // saves lots of memory
+#endif
+typedef uint32_t rend_t;
+
+/*
+ * TermWin elements limits
+ *  width     : 1 <= width
+ *  height    : 1 <= height
+ *  ncol      : 1 <= ncol       <= MAX(int16_t)
+ *  nrow      : 1 <= nrow       <= MAX(int16_t)
+ *  saveLines : 0 <= saveLines  <= MAX(int16_t)
+ *  nscrolled : 0 <= nscrolled  <= saveLines
+ *  view_start: 0 <= view_start <= nscrolled
+ */
+
+typedef struct {
+    uint16_t       width;      /* window width                    [pixels] */
+    uint16_t       height;     /* window height                   [pixels] */
+    uint16_t       fwidth;     /* font width                      [pixels] */
+    uint16_t       fheight;    /* font height                     [pixels] */
+    uint16_t       fbase;      /* font ascent (baseline)          [pixels] */
+    uint16_t       propfont;   /* font proportional flags                  */
+    uint16_t       ncol;       /* window columns              [characters] */
+    uint16_t       nrow;       /* window rows                 [characters] */
+    uint16_t       focus;      /* window has focus                         */
+    uint16_t       mapped;     /* window state mapped?                     */
+    uint16_t       int_bwidth; /* internal border width                    */
+    uint16_t       ext_bwidth; /* external border width                    */
+    uint16_t       lineSpace;  /* number of extra pixels between rows      */
+    uint16_t       saveLines;  /* number of lines that fit in scrollback   */
+    uint16_t       nscrolled;  /* number of line actually scrolled         */
+    uint16_t       view_start; /* scrollback view starts here              */
+    Window          parent[6]; /* parent identifiers - we're parent[0]     */
+    Window          vt;                /* vt100 window                             */
+    GC              gc;                /* GC for drawing                           */
+    Pixmap          pixmap;
+    rxvt_fontset   *fontset;
+} TermWin_t;
+
+/*
+ * screen accounting:
+ * screen_t elements
+ *   text:      Contains all text information including the scrollback buffer.
+ *              Each line is length TermWin.ncol
+ *   tlen:      The length of the line or -1 for wrapped lines.
+ *   rend:      Contains rendition information: font, bold, colour, etc.
+ * * Note: Each line for both text and rend are only allocated on demand, and
+ *         text[x] is allocated <=> rend[x] is allocated  for all x.
+ *   row:       Cursor row position                   : 0 <= row < TermWin.nrow
+ *   col:       Cursor column position                : 0 <= col < TermWin.ncol
+ *   tscroll:   Scrolling region top row inclusive    : 0 <= row < TermWin.nrow
+ *   bscroll:   Scrolling region bottom row inclusive : 0 <= row < TermWin.nrow
+ *
+ * selection_t elements
+ *   clicks:    1, 2 or 3 clicks - 4 indicates a special condition of 1 where
+ *              nothing is selected
+ *   beg:       row/column of beginning of selection  : never past mark
+ *   mark:      row/column of initial click           : never past end
+ *   end:       row/column of one character past end of selection
+ * * Note: -TermWin.nscrolled <= beg.row <= mark.row <= end.row < TermWin.nrow
+ * * Note: col == -1 ==> we're left of screen
+ *
+ * Layout of text/rend information in the screen_t text/rend structures:
+ *   Rows [0] ... [TermWin.saveLines - 1]
+ *     scrollback region : we're only here if TermWin.view_start != 0
+ *   Rows [TermWin.saveLines] ... [TermWin.saveLines + TermWin.nrow - 1]
+ *     normal `unscrolled' screen region
+ */
+typedef struct {
+    text_t        **text;      /* _all_ the text                            */
+    int16_t       *tlen;       /* length of each text line                  */
+    rend_t        **rend;      /* rendition, uses RS_ flags                 */
+    row_col_t       cur;       /* cursor position on the screen             */
+    uint16_t       tscroll;    /* top of settable scroll region             */
+    uint16_t       bscroll;    /* bottom of settable scroll region          */
+    uint16_t       charset;    /* character set number [0..3]               */
+    unsigned int    flags;     /* see below                                 */
+    row_col_t      s_cur;      /* saved cursor position                     */
+    uint16_t       s_charset;  /* saved character set number [0..3]         */
+    char            s_charset_char;
+    rend_t          s_rstyle;  /* saved rendition style                     */
+} screen_t;
+
+enum selection_op_t {
+    SELECTION_CLEAR = 0,       /* nothing selected                          */
+    SELECTION_INIT,            /* marked a point                            */
+    SELECTION_BEGIN,   /* started a selection                       */
+    SELECTION_CONT,            /* continued selection                       */
+    SELECTION_DONE             /* selection put in CUT_BUFFER0              */
+};
+
+typedef struct {
+    unsigned char  *text;      /* selected text                             */
+    uint32_t       len;        /* length of selected text                   */
+    short           screen;    /* screen being used                         */
+    short           clicks;    /* number of clicks                          */
+    selection_op_t  op;                /* current operation                         */
+    row_col_t       beg;       /* beginning of selection   <= mark          */
+    row_col_t       mark;      /* point of initial click   <= end           */
+    row_col_t       end;       /* one character past end point              */
+} selection_t;
+
+typedef enum {
+    OLD_SELECT, OLD_WORD_SELECT, NEW_SELECT
+} sstyle_t;
+
+/* ------------------------------------------------------------------------- */
+
+/* screen_t flags */
+#define Screen_Relative                (1<<0)  /* relative origin mode flag         */
+#define Screen_VisibleCursor   (1<<1)  /* cursor visible?                   */
+#define Screen_Autowrap                (1<<2)  /* auto-wrap flag                    */
+#define Screen_Insert          (1<<3)  /* insert mode (vs. overstrike)      */
+#define Screen_WrapNext                (1<<4)  /* need to wrap for next char?       */
+#define Screen_DefaultFlags    (Screen_VisibleCursor|Screen_Autowrap)
+
+/* rxvt_vars.Options */
+#define        Opt_console             (1LU<<0)
+#define Opt_loginShell         (1LU<<1)
+#define Opt_iconic             (1LU<<2)
+#define Opt_visualBell         (1LU<<3)
+#define Opt_mapAlert           (1LU<<4)
+#define Opt_reverseVideo       (1LU<<5)
+#define Opt_utmpInhibit                (1LU<<6)
+#define Opt_scrollBar          (1LU<<7)
+#define Opt_scrollBar_right    (1LU<<8)
+#define Opt_scrollBar_floating (1LU<<9)
+#define Opt_meta8              (1LU<<10)
+#define Opt_scrollTtyOutput    (1LU<<11)
+#define Opt_scrollTtyKeypress  (1LU<<12)
+#define Opt_transparent                (1LU<<13)
+#define Opt_transparent_all    (1LU<<14)
+#define Opt_mc_hack            (1LU<<15)
+#define Opt_tripleclickwords   (1LU<<16)
+#define Opt_scrollWithBuffer   (1LU<<17)
+#define Opt_jumpScroll         (1LU<<18)
+#define Opt_mouseWheelScrollPage (1LU<<19)
+#define Opt_pointerBlank       (1LU<<20)
+#define Opt_cursorBlink                (1LU<<21)
+/* place holder used for parsing command-line options */
+#define Opt_Reverse            (1LU<<30)
+#define Opt_Boolean            (1LU<<31)
+
+#define DEFAULT_OPTIONS                (Opt_scrollBar | Opt_scrollTtyOutput \
+                                | Opt_jumpScroll)
+
+#define PROPFONT_NORMAL                (1<<0)
+#define PROPFONT_BOLD          (1<<1)
+
+/* ------------------------------------------------------------------------- */
+
+typedef enum {
+    EUCJ, SJIS,                        /* Japanese KANJI methods                    */
+    BIG5, CNS,                 /* Chinese BIG5 methods: CNS not implemented */
+    GB,                                /* Chinese GB method                         */
+    KR,                                /* Korean method                             */
+    NOENC                      /* no encoding                               */
+} ENC_METHOD;
+
+typedef struct {
+    short          method;
+    void           (*func)(unsigned char *, int);
+    char          *name;
+} KNOWN_ENCODINGS;
+
+typedef struct {
+    short           state;
+    Window          win;
+} menuBar_t;
+
+typedef struct {
+    char            state;     /* scrollbar state                          */
+    char            init;      /* scrollbar has been initialised           */
+    short           beg;       /* slider sub-window begin height           */
+    short           end;       /* slider sub-window end height             */
+    short           top;       /* slider top position                      */
+    short           bot;       /* slider bottom position                   */
+    short           style;     /* style: rxvt, xterm, next                 */
+    short           width;     /* scrollbar width                          */
+    Window          win;
+    int             (*update)(pR_ int, int, int, int);
+} scrollBar_t;
+
+typedef struct rxvt_vars {
+/*
+ * These ``hidden'' items are not for public consumption and
+ * must not be accessed externally
+ */
+    struct rxvt_hidden *h;
+
+/*
+ * Exposed items
+ *   Changes to structure here require library version number change
+ */
+    TermWin_t       TermWin;
+    scrollBar_t     scrollBar;
+    menuBar_t       menuBar;
+    Display        *Xdisplay;
+    unsigned long   Options;
+    XSizeHints      szHint;
+    Colormap        Xcmap;
+    rxvt_color     *PixColors;
+    short           numPixColors;
+    Cursor          TermWin_cursor;    /* cursor for vt window */
+    int             Xdepth;
+    int             sb_shadow; /* scrollbar shadow width                    */
+    int             Xfd;       /* file descriptor of X server connection    */
+    int             cmd_fd;    /* pty file descriptor; connected to command */
+    int             tty_fd;    /* tty file descriptor; connected to child   */
+    int             num_fds;   /* number of file descriptors being used     */
+    int             numlock_state;
+    text_t        **drawn_text;        /* text drawn on screen (characters)         */
+    rend_t        **drawn_rend;        /* text drawn on screen (rendition)          */
+    text_t        **buf_text;
+    rend_t        **buf_rend;
+    char           *tabs;      /* per location: 1 == tab-stop               */
+    screen_t        screen;
+    screen_t        swap;
+    selection_t     selection;
+    sstyle_t        selection_style;
+    ENC_METHOD      encoding_method;
+} rxvt_t;
+
+/*****************************************************************************
+ *                                PROTOTYPES                                 *
+ *****************************************************************************/
+void             rxvt_main_loop(pR);
+rxvt_t          *rxvt_init(int, const char *const *);
+
+#endif                         /* _RXVTLIB_H_ */
diff --git a/src/screen.C b/src/screen.C
new file mode 100644 (file)
index 0000000..3b134c4
--- /dev/null
@@ -0,0 +1,3383 @@
+/*--------------------------------*-C-*--------------------------------------*
+ * File:       screen.c
+ *---------------------------------------------------------------------------*
+ * $Id: screen.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *--------------------------------------------------------------------------*/
+/*
+ * We handle _all_ screen updates and selections
+ */
+
+#include "../config.h"         /* NECESSARY */
+#define INTERN_SCREEN
+#include "rxvt.h"              /* NECESSARY */
+#include "screen.intpro"       /* PROTOS for internal routines */
+
+#include <X11/Xmd.h>           /* get the typedef for CARD32 */
+
+#include <stdint.h>
+#include <wchar.h>
+
+inline void fill_text (text_t *start, text_t value, int len)
+{
+  while (len--)
+    *start++ = value;
+}
+
+#define RESET_CHSTAT(H)                                \
+    if ((H)->chstat == WBYTE)                  \
+       (H)->chstat = SBYTE, (H)->lost_multi = 1
+
+/* ------------------------------------------------------------------------- */
+#define PROP_SIZE              16384
+#define TABSIZE                        8       /* default tab size */
+
+/* ------------------------------------------------------------------------- *
+ *             GENERAL SCREEN AND SELECTION UPDATE ROUTINES                  *
+ * ------------------------------------------------------------------------- */
+#define ZERO_SCROLLBACK(R)                                             \
+    if (((R)->Options & Opt_scrollTtyOutput) == Opt_scrollTtyOutput)   \
+       (R)->TermWin.view_start = 0
+#define CLEAR_SELECTION(R)                                             \
+    (R)->selection.beg.row = (R)->selection.beg.col                    \
+       = (R)->selection.end.row = (R)->selection.end.col = 0
+#define CLEAR_ALL_SELECTION(R)                                         \
+    (R)->selection.beg.row = (R)->selection.beg.col                    \
+       = (R)->selection.mark.row = (R)->selection.mark.col             \
+       = (R)->selection.end.row = (R)->selection.end.col = 0
+
+#define ROW_AND_COL_IS_AFTER(A, B, C, D)                               \
+    (((A) > (C)) || (((A) == (C)) && ((B) > (D))))
+#define ROW_AND_COL_IS_BEFORE(A, B, C, D)                              \
+    (((A) < (C)) || (((A) == (C)) && ((B) < (D))))
+#define ROW_AND_COL_IN_ROW_AFTER(A, B, C, D)                           \
+    (((A) == (C)) && ((B) > (D)))
+#define ROW_AND_COL_IN_ROW_AT_OR_AFTER(A, B, C, D)                     \
+    (((A) == (C)) && ((B) >= (D)))
+#define ROW_AND_COL_IN_ROW_BEFORE(A, B, C, D)                          \
+    (((A) == (C)) && ((B) < (D)))
+#define ROW_AND_COL_IN_ROW_AT_OR_BEFORE(A, B, C, D)                    \
+    (((A) == (C)) && ((B) <= (D)))
+
+/* these must be row_col_t */
+#define ROWCOL_IS_AFTER(X, Y)                                          \
+    ROW_AND_COL_IS_AFTER((X).row, (X).col, (Y).row, (Y).col)
+#define ROWCOL_IS_BEFORE(X, Y)                                         \
+    ROW_AND_COL_IS_BEFORE((X).row, (X).col, (Y).row, (Y).col)
+#define ROWCOL_IN_ROW_AFTER(X, Y)                                      \
+    ROW_AND_COL_IN_ROW_AFTER((X).row, (X).col, (Y).row, (Y).col)
+#define ROWCOL_IN_ROW_BEFORE(X, Y)                                     \
+    ROW_AND_COL_IN_ROW_BEFORE((X).row, (X).col, (Y).row, (Y).col)
+#define ROWCOL_IN_ROW_AT_OR_AFTER(X, Y)                                        \
+    ROW_AND_COL_IN_ROW_AT_OR_AFTER((X).row, (X).col, (Y).row, (Y).col)
+#define ROWCOL_IN_ROW_AT_OR_BEFORE(X, Y)                               \
+    ROW_AND_COL_IN_ROW_AT_OR_BEFORE((X).row, (X).col, (Y).row, (Y).col)
+
+/*
+ * CLEAR_ROWS : clear <num> rows starting from row <row>
+ * CLEAR_CHARS: clear <num> chars starting from pixel position <x,y>
+ * ERASE_ROWS : set <num> rows starting from row <row> to the foreground colour
+ */
+#define drawBuffer     (R->TermWin.vt)
+
+#define CLEAR_ROWS(row, num)                                           \
+    if (R->TermWin.mapped)                                             \
+       XClearArea(R->Xdisplay, drawBuffer, R->TermWin.int_bwidth,      \
+                  Row2Pixel(row), (unsigned int)R->TermWin.width,      \
+                  (unsigned int)Height2Pixel(num), False)
+
+#define CLEAR_CHARS(x, y, num)                                         \
+    if (R->TermWin.mapped)                                             \
+       XClearArea(R->Xdisplay, drawBuffer, x, y,                       \
+                  (unsigned int)Width2Pixel(num),                      \
+                  (unsigned int)Height2Pixel(1), False)
+
+#define ERASE_ROWS(row, num)                                           \
+    XFillRectangle(R->Xdisplay, drawBuffer, R->TermWin.gc,             \
+                  R->TermWin.int_bwidth, Row2Pixel(row),               \
+                  (unsigned int)R->TermWin.width,                      \
+                  (unsigned int)Height2Pixel(num))
+
+/* ------------------------------------------------------------------------- *
+ *                        SCREEN `COMMON' ROUTINES                           *
+ * ------------------------------------------------------------------------- */
+/* Fill part/all of a line with blanks. */
+/* INTPROTO */
+void
+rxvt_blank_line(pR_ text_t *et, rend_t *er, unsigned int width, rend_t efs)
+{
+    efs &= ~RS_baseattrMask;
+    efs = SET_FONT (efs, R->TermWin.fontset->find_font (' '));
+
+    while (width--)
+      {
+        *et++ = ' ';
+       *er++ = efs;
+      }
+}
+
+/* ------------------------------------------------------------------------- */
+/* Fill a full line with blanks - make sure it is allocated first */
+/* INTPROTO */
+void
+rxvt_blank_screen_mem(pR_ text_t **tp, rend_t **rp, unsigned int row, rend_t efs)
+{
+    int             width = R->TermWin.ncol;
+    rend_t         *er;
+
+#ifdef DEBUG_STRICT
+    assert((tp[row] && rp[row]) || (tp[row] == NULL && rp[row] == NULL));
+#endif
+    if (tp[row] == NULL) {
+       tp[row] = (text_t *)rxvt_malloc(sizeof(text_t) * width);
+       rp[row] = (rend_t *)rxvt_malloc(sizeof(rend_t) * width);
+    }
+    rxvt_blank_line (aR_ tp[row], rp[row], width, efs);
+}
+
+/* ------------------------------------------------------------------------- *
+ *                          SCREEN INITIALISATION                            *
+ * ------------------------------------------------------------------------- */
+/* EXTPROTO */
+void
+rxvt_scr_reset(pR)
+{
+    unsigned int    ncol, nrow, prev_ncol, prev_nrow,
+                   total_rows, prev_total_rows;
+    unsigned int    p, q;
+    int             k;
+    rend_t          setrstyle;
+
+    D_SCREEN((stderr, "rxvt_scr_reset()"));
+
+    R->TermWin.view_start = 0;
+    RESET_CHSTAT(R->h);
+    R->h->num_scr = 0;
+
+    prev_ncol = R->h->prev_ncol;
+    prev_nrow = R->h->prev_nrow;
+    if (R->TermWin.ncol == 0)
+       R->TermWin.ncol = 80;
+    if (R->TermWin.nrow == 0)
+       R->TermWin.nrow = 24;
+    ncol = R->TermWin.ncol;
+    nrow = R->TermWin.nrow;
+    if (ncol == prev_ncol && nrow == prev_nrow)
+       return;
+
+    R->h->want_refresh = 1;
+
+    total_rows = nrow + R->TermWin.saveLines;
+    prev_total_rows = prev_nrow + R->TermWin.saveLines;
+
+    R->screen.tscroll = 0;
+    R->screen.bscroll = nrow - 1;
+
+    if (prev_nrow == 0) {
+/*
+ * A: first time called so just malloc everything : don't rely on realloc
+ *    Note: this is still needed so that all the scrollback lines are NULL
+ */
+       R->screen.text = (text_t **)rxvt_calloc(total_rows, sizeof(text_t *));
+       R->buf_text = (text_t **)rxvt_calloc(total_rows, sizeof(text_t *));
+       R->drawn_text = (text_t **)rxvt_calloc(nrow, sizeof(text_t *));
+       R->swap.text = (text_t **)rxvt_calloc(nrow, sizeof(text_t *));
+
+       R->screen.tlen = (int16_t *)rxvt_calloc(total_rows, sizeof(int16_t));
+       R->swap.tlen = (int16_t *)rxvt_calloc(nrow, sizeof(int16_t));
+
+       R->screen.rend = (rend_t **)rxvt_calloc(total_rows, sizeof(rend_t *));
+       R->buf_rend = (rend_t **)rxvt_calloc(total_rows, sizeof(rend_t *));
+       R->drawn_rend = (rend_t **)rxvt_calloc(nrow, sizeof(rend_t *));
+       R->swap.rend = (rend_t **)rxvt_calloc(nrow, sizeof(rend_t *));
+
+       for (p = 0; p < nrow; p++) {
+           q = p + R->TermWin.saveLines;
+           rxvt_blank_screen_mem(aR_ R->screen.text, R->screen.rend,
+                                 q, DEFAULT_RSTYLE);
+           rxvt_blank_screen_mem(aR_ R->swap.text, R->swap.rend,
+                                 p, DEFAULT_RSTYLE);
+           R->screen.tlen[q] = R->swap.tlen[p] = 0;
+           rxvt_blank_screen_mem(aR_ R->drawn_text, R->drawn_rend,
+                                 p, DEFAULT_RSTYLE);
+       }
+       MEMSET(R->h->charsets, 'B', sizeof(R->h->charsets));
+       R->TermWin.nscrolled = 0;       /* no saved lines */
+       R->h->rstyle = DEFAULT_RSTYLE;
+       R->screen.flags = Screen_DefaultFlags;
+       R->screen.cur.row = R->screen.cur.col = 0;
+       R->screen.charset = 0;
+       R->h->current_screen = PRIMARY;
+       rxvt_scr_cursor(aR_ SAVE);
+#if NSCREENS
+       R->swap.flags = Screen_DefaultFlags;
+       R->swap.cur.row = R->swap.cur.col = 0;
+       R->swap.charset = 0;
+       R->h->current_screen = SECONDARY;
+       rxvt_scr_cursor(aR_ SAVE);
+       R->h->current_screen = PRIMARY;
+#endif
+       R->selection.text = NULL;
+       R->selection.len = 0;
+       R->selection.op = SELECTION_CLEAR;
+       R->selection.screen = PRIMARY;
+       R->selection.clicks = 0;
+       CLEAR_ALL_SELECTION(R);
+       R->h->rvideo = 0;
+
+    } else {
+/*
+ * B1: add or delete rows as appropriate
+ */
+       setrstyle = DEFAULT_RSTYLE;
+
+       if (nrow < prev_nrow) {
+           /* delete rows */
+           k = min(R->TermWin.nscrolled, prev_nrow - nrow);
+           rxvt_scroll_text(aR_ 0, (int)prev_nrow - 1, k, 1);
+           for (p = nrow; p < prev_nrow; p++) {
+               q = p + R->TermWin.saveLines;
+               if (R->screen.text[q]) {
+#ifdef DEBUG_STRICT
+                   assert(R->screen.rend[q]);
+#endif
+                   free(R->screen.text[q]);
+                   free(R->screen.rend[q]);
+               }
+               if (R->swap.text[p]) {
+#ifdef DEBUG_STRICT
+                   assert(R->swap.rend[p]);
+#endif
+                   free(R->swap.text[p]);
+                   free(R->swap.rend[p]);
+               }
+#ifdef DEBUG_STRICT
+               assert(R->drawn_text[p] && R->drawn_rend[p]);
+#endif
+               free(R->drawn_text[p]);
+               free(R->drawn_rend[p]);
+           }
+           /* we have fewer rows so fix up cursor position */
+           MIN_IT(R->screen.cur.row, (int32_t)nrow - 1);
+           MIN_IT(R->swap.cur.row, (int32_t)nrow - 1);
+
+           rxvt_scr_reset_realloc(aR); /* realloc _last_ */
+
+       } else if (nrow > prev_nrow) {
+           /* add rows */
+           rxvt_scr_reset_realloc(aR); /* realloc _first_ */
+
+           k = min(R->TermWin.nscrolled, nrow - prev_nrow);
+           for (p = prev_total_rows; p < total_rows; p++) {
+               R->screen.tlen[p] = 0;
+               R->screen.text[p] = NULL;
+               R->screen.rend[p] = NULL;
+           }
+           for (p = prev_total_rows; p < total_rows - k; p++)
+               rxvt_blank_screen_mem(aR_ R->screen.text, R->screen.rend,
+                                     p, setrstyle);
+           for (p = prev_nrow; p < nrow; p++) {
+               R->swap.tlen[p] = 0;
+               R->swap.text[p] = NULL;
+               R->swap.rend[p] = NULL;
+               R->drawn_text[p] = NULL;
+               R->drawn_rend[p] = NULL;
+               rxvt_blank_screen_mem(aR_ R->swap.text, R->swap.rend,
+                                     p, setrstyle);
+               rxvt_blank_screen_mem(aR_ R->drawn_text, R->drawn_rend,
+                                     p, setrstyle);
+           }
+           if (k > 0) {
+               rxvt_scroll_text(aR_ 0, (int)nrow - 1, -k, 1);
+               R->screen.cur.row += k;
+               R->screen.s_cur.row += k;
+               R->TermWin.nscrolled -= k;
+           }
+#ifdef DEBUG_STRICT
+           assert(R->screen.cur.row < R->TermWin.nrow);
+           assert(R->swap.cur.row < R->TermWin.nrow);
+#else                          /* drive with your eyes closed */
+           MIN_IT(R->screen.cur.row, nrow - 1);
+           MIN_IT(R->swap.cur.row, nrow - 1);
+#endif
+       }
+/* B2: resize columns */
+       if (ncol != prev_ncol) {
+           for (p = 0; p < total_rows; p++) {
+               if (R->screen.text[p]) {
+                   R->screen.text[p] = (text_t *)rxvt_realloc(R->screen.text[p], ncol * sizeof(text_t));
+                   R->screen.rend[p] = (rend_t *)rxvt_realloc(R->screen.rend[p], ncol * sizeof(rend_t));
+                   MIN_IT(R->screen.tlen[p], (int16_t)ncol);
+                   if (ncol > prev_ncol)
+                       rxvt_blank_line(aR_
+                                        &(R->screen.text[p][prev_ncol]),
+                                       &(R->screen.rend[p][prev_ncol]),
+                                       ncol - prev_ncol,
+                                       setrstyle);
+               }
+           }
+           for (p = 0; p < nrow; p++) {
+               R->drawn_text[p] = (text_t *)rxvt_realloc(R->drawn_text[p], ncol * sizeof(text_t));
+               R->drawn_rend[p] = (rend_t *)rxvt_realloc(R->drawn_rend[p], ncol * sizeof(rend_t));
+               if (R->swap.text[p]) {
+                   R->swap.text[p] = (text_t *)rxvt_realloc(R->swap.text[p], ncol * sizeof(text_t));
+                   R->swap.rend[p] = (rend_t *)rxvt_realloc(R->swap.rend[p], ncol * sizeof(rend_t));
+                   MIN_IT(R->swap.tlen[p], (int16_t)ncol);
+                   if (ncol > prev_ncol)
+                       rxvt_blank_line(aR_
+                                        &(R->swap.text[p][prev_ncol]),
+                                       &(R->swap.rend[p][prev_ncol]),
+                                       ncol - prev_ncol, setrstyle);
+               }
+               if (ncol > prev_ncol)
+                   rxvt_blank_line(aR_
+                                    &(R->drawn_text[p][prev_ncol]),
+                                   &(R->drawn_rend[p][prev_ncol]),
+                                   ncol - prev_ncol, setrstyle);
+           }
+           MIN_IT(R->screen.cur.col, (int16_t)ncol - 1);
+           MIN_IT(R->swap.cur.col, (int16_t)ncol - 1);
+       }
+       if (R->tabs)
+           free(R->tabs);
+    }
+
+    R->tabs = (char *)rxvt_malloc(ncol * sizeof(char));
+
+    for (p = 0; p < ncol; p++)
+       R->tabs[p] = (p % TABSIZE == 0) ? 1 : 0;
+
+    R->h->prev_nrow = nrow;
+    R->h->prev_ncol = ncol;
+
+    rxvt_tt_winsize(R->cmd_fd, R->TermWin.ncol, R->TermWin.nrow, R->h->cmd_pid);
+}
+
+/* INTPROTO */
+void
+rxvt_scr_reset_realloc(pR)
+{
+    uint16_t       total_rows, nrow;
+
+    nrow = R->TermWin.nrow;
+    total_rows = nrow + R->TermWin.saveLines;
+/* *INDENT-OFF* */
+    R->screen.text = (text_t **)rxvt_realloc(R->screen.text, total_rows * sizeof(text_t *));
+    R->buf_text    = (text_t **)rxvt_realloc(R->buf_text   , total_rows * sizeof(text_t *));
+    R->drawn_text  = (text_t **)rxvt_realloc(R->drawn_text , nrow       * sizeof(text_t *));
+    R->swap.text   = (text_t **)rxvt_realloc(R->swap.text  , nrow       * sizeof(text_t *));
+
+    R->screen.tlen = (int16_t *)rxvt_realloc(R->screen.tlen, total_rows * sizeof(int16_t));
+    R->swap.tlen   = (int16_t *)rxvt_realloc(R->swap.tlen  , total_rows * sizeof(int16_t));
+
+    R->screen.rend = (rend_t **)rxvt_realloc(R->screen.rend, total_rows * sizeof(rend_t *));
+    R->buf_rend    = (rend_t **)rxvt_realloc(R->buf_rend   , total_rows * sizeof(rend_t *));
+    R->drawn_rend  = (rend_t **)rxvt_realloc(R->drawn_rend , nrow       * sizeof(rend_t *));
+    R->swap.rend   = (rend_t **)rxvt_realloc(R->swap.rend  , nrow       * sizeof(rend_t *));
+/* *INDENT-ON* */
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Free everything.  That way malloc debugging can find leakage.
+ */
+/* EXTPROTO */
+void
+rxvt_scr_release(pR)
+{
+    uint16_t       total_rows;
+    int             i;
+
+    total_rows = R->TermWin.nrow + R->TermWin.saveLines;
+    for (i = 0; i < total_rows; i++) {
+       if (R->screen.text[i]) {        /* then so is R->screen.rend[i] */
+           free(R->screen.text[i]);
+#ifdef DEBUG_STRICT
+           assert(R->screen.rend[i]);
+#endif
+           free(R->screen.rend[i]);
+       }
+    }
+    for (i = 0; i < R->TermWin.nrow; i++) {
+       free(R->drawn_text[i]);
+       free(R->drawn_rend[i]);
+       free(R->swap.text[i]);
+       free(R->swap.rend[i]);
+    }
+    free(R->screen.text);
+    free(R->screen.tlen);
+    free(R->screen.rend);
+    free(R->drawn_text);
+    free(R->drawn_rend);
+    free(R->swap.text);
+    free(R->swap.tlen);
+    free(R->swap.rend);
+    free(R->buf_text);
+    free(R->buf_rend);
+    free(R->tabs);
+
+/* NULL these so if anything tries to use them, we'll know about it */
+    R->screen.text = R->drawn_text = R->swap.text = NULL;
+    R->screen.rend = R->drawn_rend = R->swap.rend = NULL;
+    R->screen.tlen = R->swap.tlen = NULL;
+    R->buf_text = NULL;
+    R->buf_rend = NULL;
+    R->tabs = NULL;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Hard reset
+ */
+/* EXTPROTO */
+void
+rxvt_scr_poweron(pR)
+{
+    D_SCREEN((stderr, "rxvt_scr_poweron()"));
+
+    rxvt_scr_release(aR);
+    R->h->prev_nrow = R->h->prev_ncol = 0;
+    rxvt_scr_reset(aR);
+
+    rxvt_scr_clear(aR);
+    rxvt_scr_refresh(aR_ SLOW_REFRESH);
+#ifdef RXVT_GRAPHICS
+    rxvt_Gr_reset(aR);
+#endif
+}
+
+/* ------------------------------------------------------------------------- *
+ *                         PROCESS SCREEN COMMANDS                           *
+ * ------------------------------------------------------------------------- */
+/*
+ * Save and Restore cursor
+ * XTERM_SEQ: Save cursor   : ESC 7
+ * XTERM_SEQ: Restore cursor: ESC 8
+ */
+/* EXTPROTO */
+void
+rxvt_scr_cursor(pR_ int mode)
+{
+    screen_t       *s;
+
+    D_SCREEN((stderr, "rxvt_scr_cursor(%c)", mode));
+
+#if NSCREENS && !defined(NO_SECONDARY_SCREEN_CURSOR)
+    if (R->h->current_screen == SECONDARY)
+       s = &(R->swap);
+    else
+#endif
+       s = &(R->screen);
+    switch (mode) {
+    case SAVE:
+       s->s_cur.row = s->cur.row;
+       s->s_cur.col = s->cur.col;
+       s->s_rstyle = R->h->rstyle;
+       s->s_charset = s->charset;
+       s->s_charset_char = R->h->charsets[s->charset];
+       break;
+    case RESTORE:
+       R->h->want_refresh = 1;
+       s->cur.row = s->s_cur.row;
+       s->cur.col = s->s_cur.col;
+       s->flags &= ~Screen_WrapNext;
+       R->h->rstyle = s->s_rstyle;
+       s->charset = s->s_charset;
+       R->h->charsets[s->charset] = s->s_charset_char;
+       rxvt_set_font_style(aR);
+       break;
+    }
+/* boundary check in case screen size changed between SAVE and RESTORE */
+    MIN_IT(s->cur.row, R->TermWin.nrow - 1);
+    MIN_IT(s->cur.col, R->TermWin.ncol - 1);
+#ifdef DEBUG_STRICT
+    assert(s->cur.row >= 0);
+    assert(s->cur.col >= 0);
+#else                          /* drive with your eyes closed */
+    MAX_IT(s->cur.row, 0);
+    MAX_IT(s->cur.col, 0);
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Swap between primary and secondary screens
+ * XTERM_SEQ: Primary screen  : ESC [ ? 4 7 h
+ * XTERM_SEQ: Secondary screen: ESC [ ? 4 7 l
+ */
+/* EXTPROTO */
+int
+rxvt_scr_change_screen(pR_ int scrn)
+{
+    int             i;
+#if NSCREENS
+    int             offset;
+#endif
+
+    R->h->want_refresh = 1;
+
+    D_SCREEN((stderr, "rxvt_scr_change_screen(%d)", scrn));
+
+    R->TermWin.view_start = 0;
+    RESET_CHSTAT(R->h);
+
+    if (R->h->current_screen == scrn)
+       return R->h->current_screen;
+
+    rxvt_selection_check(aR_ 2);       /* check for boundary cross */
+
+    SWAP_IT(R->h->current_screen, scrn, int);
+#if NSCREENS
+    R->h->num_scr = 0;
+    offset = R->TermWin.saveLines;
+    for (i = R->h->prev_nrow; i--;) {
+       SWAP_IT(R->screen.text[i + offset], R->swap.text[i], text_t *);
+       SWAP_IT(R->screen.tlen[i + offset], R->swap.tlen[i], int16_t);
+       SWAP_IT(R->screen.rend[i + offset], R->swap.rend[i], rend_t *);
+    }
+    SWAP_IT(R->screen.cur.row, R->swap.cur.row, int16_t);
+    SWAP_IT(R->screen.cur.col, R->swap.cur.col, int16_t);
+# ifdef DEBUG_STRICT
+    assert((R->screen.cur.row >= 0) && (R->screen.cur.row < R->h->prev_nrow));
+    assert((R->screen.cur.col >= 0) && (R->screen.cur.col < R->h->prev_ncol));
+# else                         /* drive with your eyes closed */
+    MAX_IT(R->screen.cur.row, 0);
+    MIN_IT(R->screen.cur.row, (int32_t)R->h->prev_nrow - 1);
+    MAX_IT(R->screen.cur.col, 0);
+    MIN_IT(R->screen.cur.col, (int32_t)R->h->prev_ncol - 1);
+# endif
+    SWAP_IT(R->screen.charset, R->swap.charset, int16_t);
+    SWAP_IT(R->screen.flags, R->swap.flags, int);
+    R->screen.flags |= Screen_VisibleCursor;
+    R->swap.flags |= Screen_VisibleCursor;
+
+# ifdef RXVT_GRAPHICS
+
+    if (rxvt_Gr_Displayed(aR)) {
+       rxvt_Gr_scroll(aR_ 0);
+       rxvt_Gr_ChangeScreen(aR);
+    }
+# endif
+#else
+# ifdef SCROLL_ON_NO_SECONDARY
+#  ifdef RXVT_GRAPHICS
+    if (rxvt_Gr_Displayed(aR))
+       rxvt_Gr_ClearScreen(aR);
+#  endif
+    if (R->h->current_screen == PRIMARY
+#  ifdef RXVT_GRAPHICS
+        && !rxvt_Gr_Displayed(aR)
+#  endif
+        )
+       rxvt_scroll_text(aR_ 0, (R->h->prev_nrow - 1), R->h->prev_nrow, 0);
+# endif
+#endif
+    return scrn;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Change the colour for following text
+ */
+/* EXTPROTO */
+void
+rxvt_scr_color(pR_ unsigned int color, int fgbg)
+{
+    color &= RS_fgMask;
+    if (fgbg == Color_fg)
+       R->h->rstyle = SET_FGCOLOR(R->h->rstyle, color);
+    else 
+       R->h->rstyle = SET_BGCOLOR(R->h->rstyle, color);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Change the rendition style for following text
+ */
+/* EXTPROTO */
+void
+rxvt_scr_rendition(pR_ int set, int style)
+{
+    if (set)
+       R->h->rstyle |= style;
+    else if (style == ~RS_None)
+       R->h->rstyle = DEFAULT_RSTYLE;
+    else
+       R->h->rstyle &= ~style;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Scroll text between <row1> and <row2> inclusive, by <count> lines
+ * count positive ==> scroll up
+ * count negative ==> scroll down
+ * spec == 0 for normal routines
+ */
+/* EXTPROTO */
+int
+rxvt_scroll_text(pR_ int row1, int row2, int count, int spec)
+{
+    int             i, j;
+    long            nscrolled;
+
+    if (count == 0 || (row1 > row2))
+       return 0;
+
+    R->h->want_refresh = 1;
+    D_SCREEN((stderr, "rxvt_scroll_text(%d,%d,%d,%d): %s", row1, row2, count, spec, (R->h->current_screen == PRIMARY) ? "Primary" : "Secondary"));
+
+    if ((count > 0) && (row1 == 0) && (R->h->current_screen == PRIMARY)) {
+       nscrolled = (long)R->TermWin.nscrolled + (long)count;;
+       if (nscrolled > (long)R->TermWin.saveLines)
+           R->TermWin.nscrolled = R->TermWin.saveLines;
+       else
+           R->TermWin.nscrolled = (uint16_t)nscrolled;
+       if ((R->Options & Opt_scrollWithBuffer)
+           && R->TermWin.view_start != 0
+           && R->TermWin.view_start != R->TermWin.saveLines)
+           rxvt_scr_page(aR_ UP, count);
+    } else if (!spec)
+       row1 += R->TermWin.saveLines;
+    row2 += R->TermWin.saveLines;
+
+    if (R->selection.op && R->h->current_screen == R->selection.screen) {
+       i = R->selection.beg.row + R->TermWin.saveLines;
+       j = R->selection.end.row + R->TermWin.saveLines;
+       if ((i < row1 && j > row1)
+           || (i < row2 && j > row2)
+           || (i - count < row1 && i >= row1)
+           || (i - count > row2 && i <= row2)
+           || (j - count < row1 && j >= row1)
+           || (j - count > row2 && j <= row2)) {
+           CLEAR_ALL_SELECTION(R);
+           R->selection.op = SELECTION_CLEAR;  /* XXX: too aggressive? */
+       } else if (j >= row1 && j <= row2) {
+           /* move selected region too */
+           R->selection.beg.row -= count;
+           R->selection.end.row -= count;
+           R->selection.mark.row -= count;
+       }
+    }
+    rxvt_selection_check(aR_ 0);       /* _after_ R->TermWin.nscrolled update */
+
+    R->h->num_scr += count;
+    j = count;
+    if (count < 0)
+       count = -count;
+    i = row2 - row1 + 1;
+    MIN_IT(count, i);
+
+    if (j > 0) {
+/* A: scroll up */
+
+/* A1: Copy lines that will get clobbered by the rotation */
+       for (i = 0, j = row1; i < count; i++, j++) {
+           R->buf_text[i] = R->screen.text[j];
+           R->buf_rend[i] = R->screen.rend[j];
+       }
+/* A2: Rotate lines */
+       for (j = row1, i = j + count; i <= row2; i++, j++) {
+           R->screen.tlen[j] = R->screen.tlen[i];
+           R->screen.text[j] = R->screen.text[i];
+           R->screen.rend[j] = R->screen.rend[i];
+       }
+       j = row2 - count + 1, i = count;
+    } else /* if (j < 0) */ {
+/* B: scroll down */
+
+/* B1: Copy lines that will get clobbered by the rotation */
+       for (i = 0, j = row2; i < count; i++, j--) {
+           R->buf_text[i] = R->screen.text[j];
+           R->buf_rend[i] = R->screen.rend[j];
+       }
+/* B2: Rotate lines */
+       for (j = row2, i = j - count; i >= row1; i--, j--) {
+           R->screen.tlen[j] = R->screen.tlen[i];
+           R->screen.text[j] = R->screen.text[i];
+           R->screen.rend[j] = R->screen.rend[i];
+       }
+       j = row1, i = count;
+       count = -count;
+    }
+
+/* C: Resurrect lines */
+    for (; i--; j++) {
+       R->screen.tlen[j] = 0;
+       R->screen.text[j] = R->buf_text[i];
+       R->screen.rend[j] = R->buf_rend[i];
+       if (!spec)              /* line length may not equal TermWin.ncol */
+           rxvt_blank_screen_mem(aR_ R->screen.text, R->screen.rend,
+                                 (unsigned int)j, R->h->rstyle);
+    }
+
+#ifdef RXVT_GRAPHICS
+    if (rxvt_Gr_Displayed(aR))
+       rxvt_Gr_scroll(aR_ count);
+#endif
+    return count;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Add text given in <str> of length <len> to screen struct
+ */
+/* EXTPROTO */
+void
+rxvt_scr_add_lines(pR_ const uint32_t *str, int nlines, int len)
+{
+    unsigned char   checksel, clearsel;
+    uint32_t        c;
+    int             i, row, last_col;
+    text_t         *stp;
+    rend_t         *srp;
+    struct rxvt_hidden *h = R->h;
+
+    if (len <= 0)              /* sanity */
+       return;
+
+    h->want_refresh = 1;
+    last_col = R->TermWin.ncol;
+
+    D_SCREEN((stderr, "rxvt_scr_add_lines(%d,%d)", nlines, len));
+    ZERO_SCROLLBACK(R);
+    if (nlines > 0) {
+       nlines += (R->screen.cur.row - R->screen.bscroll);
+       if ((nlines > 0)
+           && (R->screen.tscroll == 0)
+           && (R->screen.bscroll == (R->TermWin.nrow - 1))) {
+           /* _at least_ this many lines need to be scrolled */
+           rxvt_scroll_text(aR_ R->screen.tscroll, R->screen.bscroll, nlines,
+                            0);
+           R->screen.cur.row -= nlines;
+       }
+    }
+#ifdef DEBUG_STRICT
+    assert(R->screen.cur.col < last_col);
+    assert((R->screen.cur.row < R->TermWin.nrow)
+          && (R->screen.cur.row >= -(int32_t)R->TermWin.nscrolled));
+#else                          /* drive with your eyes closed */
+    MIN_IT(R->screen.cur.col, last_col - 1);
+    MIN_IT(R->screen.cur.row, (int32_t)R->TermWin.nrow - 1);
+    MAX_IT(R->screen.cur.row, -(int32_t)R->TermWin.nscrolled);
+#endif
+    row = R->screen.cur.row + R->TermWin.saveLines;
+
+    checksel = (R->selection.op
+               && h->current_screen == R->selection.screen) ? 1 : 0;
+    clearsel = 0;
+
+    stp = R->screen.text[row];
+    srp = R->screen.rend[row];
+
+    for (i = 0; i < len;) {
+       c = str[i++];
+       switch (c) {
+       case '\t':
+           rxvt_scr_tab(aR_ 1);
+           continue;
+       case '\n':
+           if (R->screen.tlen[row] != -1)      /* XXX: think about this */
+               MAX_IT(R->screen.tlen[row], R->screen.cur.col);
+           R->screen.flags &= ~Screen_WrapNext;
+           if (R->screen.cur.row == R->screen.bscroll)
+               rxvt_scroll_text(aR_ R->screen.tscroll, R->screen.bscroll, 1, 0);
+           else if (R->screen.cur.row < (R->TermWin.nrow - 1))
+               row = (++R->screen.cur.row) + R->TermWin.saveLines;
+           stp = R->screen.text[row];  /* _must_ refresh */
+           srp = R->screen.rend[row];  /* _must_ refresh */
+           RESET_CHSTAT(h);
+           continue;
+       case '\r':
+           if (R->screen.tlen[row] != -1)      /* XXX: think about this */
+               MAX_IT(R->screen.tlen[row], R->screen.cur.col);
+           R->screen.flags &= ~Screen_WrapNext;
+           R->screen.cur.col = 0;
+           RESET_CHSTAT(h);
+           continue;
+       default:
+           if (c == 127)
+               continue;       /* yummmm..... */
+           break;
+       }
+
+       if (checksel            /* see if we're writing within selection */
+           && !ROWCOL_IS_BEFORE(R->screen.cur, R->selection.beg)
+           && ROWCOL_IS_BEFORE(R->screen.cur, R->selection.end)) {
+           checksel = 0;
+           clearsel = 1;
+       }
+       if (R->screen.flags & Screen_WrapNext) {
+           R->screen.tlen[row] = -1;
+           if (R->screen.cur.row == R->screen.bscroll)
+               rxvt_scroll_text(aR_ R->screen.tscroll, R->screen.bscroll, 1, 0);
+           else if (R->screen.cur.row < (R->TermWin.nrow - 1))
+               row = (++R->screen.cur.row) + R->TermWin.saveLines;
+           stp = R->screen.text[row];  /* _must_ refresh */
+           srp = R->screen.rend[row];  /* _must_ refresh */
+           R->screen.cur.col = 0;
+           R->screen.flags &= ~Screen_WrapNext;
+       }
+       if (R->screen.flags & Screen_Insert)
+           rxvt_scr_insdel_chars(aR_ 1, INSERT);
+
+        if (R->h->charsets[R->screen.charset] == '0') // DEC SPECIAL
+          switch (c)
+            {
+              case '+': c = 0x2192; break; case ',': c = 0x2190; break; case '-': c = 0x2191; break;
+              case '.': c = 0x2193; break; case '0': c = 0x25ae; break; case '`': c = 0x25c6; break;
+              case 'a': c = 0x2592; break; case 'f': c = 0x00b0; break; case 'g': c = 0x00b1; break;
+              case 'h': c = 0x2592; break; case 'i': c = 0x2603; break; case 'j': c = 0x2518; break;
+              case 'k': c = 0x2510; break; case 'l': c = 0x250c; break; case 'm': c = 0x2514; break;
+              case 'n': c = 0x253c; break; case 'o': c = 0x23ba; break; case 'p': c = 0x23bb; break;
+              case 'q': c = 0x2500; break; case 'r': c = 0x23bc; break; case 's': c = 0x23bd; break;
+              case 't': c = 0x251c; break; case 'u': c = 0x2524; break; case 'v': c = 0x2534; break;
+              case 'w': c = 0x252c; break; case 'x': c = 0x2502; break; case 'y': c = 0x2264; break;
+              case 'z': c = 0x2265; break; case '{': c = 0x03c0; break; case '|': c = 0x2260; break;
+              case '}': c = 0x00a3; break; case '~': c = 0x00b7; break;
+            }
+
+        rend_t rend = SET_FONT (h->rstyle, R->TermWin.fontset->find_font (c));
+
+       stp[R->screen.cur.col] = c;
+       srp[R->screen.cur.col] = rend;
+
+        if (c > 255)
+          {
+            // rely on wcwidth to tell us the character width, at least for non iso-8859-1
+            int width = wcwidth (c);
+            
+            if (width > 1)
+              {
+                while (--width > 0 && R->screen.cur.col < last_col - 1)
+                  {
+
+                    srp[R->screen.cur.col] |= RS_wide;
+
+                    R->screen.cur.col++;
+                    stp[R->screen.cur.col] = NOCHAR;
+                    srp[R->screen.cur.col] = rend;
+                  }
+              }
+          }
+
+       if (R->screen.cur.col < last_col - 1)
+           R->screen.cur.col++;
+       else {
+           R->screen.tlen[row] = last_col;
+           if (R->screen.flags & Screen_Autowrap)
+               R->screen.flags |= Screen_WrapNext;
+       }
+    }
+    if (R->screen.tlen[row] != -1)     /* XXX: think about this */
+       MAX_IT(R->screen.tlen[row], R->screen.cur.col);
+
+/*
+ * If we wrote anywhere in the selected area, kill the selection
+ * XXX: should we kill the mark too?  Possibly, but maybe that
+ *      should be a similar check.
+ */
+    if (clearsel)
+       CLEAR_SELECTION(R);
+
+#ifdef DEBUG_STRICT
+    assert(R->screen.cur.row >= 0);
+#else                          /* drive with your eyes closed */
+    MAX_IT(R->screen.cur.row, 0);
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Process Backspace.  Move back the cursor back a position, wrap if have to
+ * XTERM_SEQ: CTRL-H
+ */
+/* EXTPROTO */
+void
+rxvt_scr_backspace(pR)
+{
+    RESET_CHSTAT(R->h);
+    R->h->want_refresh = 1;
+    if (R->screen.cur.col == 0) {
+       if (R->screen.cur.row > 0) {
+#ifdef TERMCAP_HAS_BW
+           R->screen.cur.col = R->TermWin.ncol - 1;
+           R->screen.cur.row--;
+           return;
+#endif
+       }
+    } else if ((R->screen.flags & Screen_WrapNext) == 0)
+       rxvt_scr_gotorc(aR_ 0, -1, RELATIVE);
+    R->screen.flags &= ~Screen_WrapNext;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Process Horizontal Tab
+ * count: +ve = forward; -ve = backwards
+ * XTERM_SEQ: CTRL-I
+ */
+/* EXTPROTO */
+void
+rxvt_scr_tab(pR_ int count)
+{
+    int             i, x;
+
+    D_SCREEN((stderr, "rxvt_scr_tab(%d)", count));
+    R->h->want_refresh = 1;
+    RESET_CHSTAT(R->h);
+    i = x = R->screen.cur.col;
+    if (count == 0)
+       return;
+    else if (count > 0) {
+       for (; ++i < R->TermWin.ncol; )
+           if (R->tabs[i]) {
+               x = i;
+               if (!--count)
+                   break;
+           }
+       if (count)
+           x = R->TermWin.ncol - 1;
+    } else /* if (count < 0) */ {
+       for (; --i >= 0; )
+           if (R->tabs[i]) {
+               x = i;
+               if (!++count)
+                   break;
+           }
+       if (count)
+           x = 0;
+    }
+    if (x != R->screen.cur.col)
+       rxvt_scr_gotorc(aR_ 0, x, R_RELATIVE);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Process DEC Back Index
+ * XTERM_SEQ: ESC 6
+ * Move cursor left in row.  If we're at the left boundary, shift everything
+ * in that row right.  Clear left column.
+ */
+#ifndef NO_FRILLS
+/* EXTPROTO */
+void
+rxvt_scr_backindex(pR)
+{
+    if (R->screen.cur.col > 0)
+       rxvt_scr_gotorc(aR_ 0, -1, R_RELATIVE | C_RELATIVE);
+    else {
+       if (R->screen.tlen[R->screen.cur.row + R->TermWin.saveLines] == 0)
+           return;             /* um, yeah? */
+       rxvt_scr_insdel_chars(aR_ 1, INSERT);
+    }
+}
+#endif
+/* ------------------------------------------------------------------------- */
+/*
+ * Process DEC Forward Index
+ * XTERM_SEQ: ESC 9
+ * Move cursor right in row.  If we're at the right boundary, shift everything
+ * in that row left.  Clear right column.
+ */
+#ifndef NO_FRILLS
+/* EXTPROTO */
+void
+rxvt_scr_forwardindex(pR)
+{
+    int             row;
+
+    if (R->screen.cur.col < R->TermWin.ncol - 1)
+       rxvt_scr_gotorc(aR_ 0, 1, R_RELATIVE | C_RELATIVE);
+    else {
+       row = R->screen.cur.row + R->TermWin.saveLines;
+       if (R->screen.tlen[row] == 0)
+           return;             /* um, yeah? */
+       else if (R->screen.tlen[row] == -1)
+           R->screen.tlen[row] = R->TermWin.ncol;
+       rxvt_scr_gotorc(aR_ 0, 0, R_RELATIVE);
+       rxvt_scr_insdel_chars(aR_ 1, DELETE);
+       rxvt_scr_gotorc(aR_ 0, R->TermWin.ncol - 1, R_RELATIVE);
+    }
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Goto Row/Column
+ */
+/* EXTPROTO */
+void
+rxvt_scr_gotorc(pR_ int row, int col, int relative)
+{
+    R->h->want_refresh = 1;
+    ZERO_SCROLLBACK(R);
+    RESET_CHSTAT(R->h);
+#ifdef RXVT_GRAPHICS
+    if (rxvt_Gr_Displayed(aR))
+       rxvt_Gr_scroll(aR_ 0);
+#endif
+
+    D_SCREEN((stderr, "rxvt_scr_gotorc(r:%s%d,c:%s%d): from (r:%d,c:%d)", (relative & R_RELATIVE ? "+" : ""), row, (relative & C_RELATIVE ? "+" : ""), col, R->screen.cur.row, R->screen.cur.col));
+
+    R->screen.cur.col = ((relative & C_RELATIVE) ? (R->screen.cur.col + col)
+                                                : col);
+    MAX_IT(R->screen.cur.col, 0);
+    MIN_IT(R->screen.cur.col, (int32_t)R->TermWin.ncol - 1);
+
+    R->screen.flags &= ~Screen_WrapNext;
+    if (relative & R_RELATIVE) {
+       if (row > 0) {
+           if (R->screen.cur.row <= R->screen.bscroll
+               && (R->screen.cur.row + row) > R->screen.bscroll)
+               R->screen.cur.row = R->screen.bscroll;
+           else
+               R->screen.cur.row += row;
+       } else if (row < 0) {
+           if (R->screen.cur.row >= R->screen.tscroll
+               && (R->screen.cur.row + row) < R->screen.tscroll)
+               R->screen.cur.row = R->screen.tscroll;
+           else
+               R->screen.cur.row += row;
+       }
+    } else {
+       if (R->screen.flags & Screen_Relative) {        /* relative origin mode */
+           R->screen.cur.row = row + R->screen.tscroll;
+           MIN_IT(R->screen.cur.row, R->screen.bscroll);
+       } else
+           R->screen.cur.row = row;
+    }
+    MAX_IT(R->screen.cur.row, 0);
+    MIN_IT(R->screen.cur.row, (int32_t)R->TermWin.nrow - 1);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * direction  should be UP or DN
+ */
+/* EXTPROTO */
+void
+rxvt_scr_index(pR_ enum page_dirn direction)
+{
+    int             dirn;
+
+    R->h->want_refresh = 1;
+    dirn = ((direction == UP) ? 1 : -1);
+    D_SCREEN((stderr, "rxvt_scr_index(%d)", dirn));
+
+    ZERO_SCROLLBACK(R);
+    RESET_CHSTAT(R->h);
+
+#ifdef RXVT_GRAPHICS
+    if (rxvt_Gr_Displayed(aR))
+       rxvt_Gr_scroll(aR_ 0);
+#endif
+
+    R->screen.flags &= ~Screen_WrapNext;
+    if ((R->screen.cur.row == R->screen.bscroll && direction == UP)
+       || (R->screen.cur.row == R->screen.tscroll && direction == DN))
+       rxvt_scroll_text(aR_ R->screen.tscroll, R->screen.bscroll, dirn, 0);
+    else
+       R->screen.cur.row += dirn;
+    MAX_IT(R->screen.cur.row, 0);
+    MIN_IT(R->screen.cur.row, (int32_t)R->TermWin.nrow - 1);
+    rxvt_selection_check(aR_ 0);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Erase part or whole of a line
+ * XTERM_SEQ: Clear line to right: ESC [ 0 K
+ * XTERM_SEQ: Clear line to left : ESC [ 1 K
+ * XTERM_SEQ: Clear whole line   : ESC [ 2 K
+ */
+/* EXTPROTO */
+void
+rxvt_scr_erase_line(pR_ int mode)
+{
+    unsigned int    row, col, num;
+
+    R->h->want_refresh = 1;
+    D_SCREEN((stderr, "rxvt_scr_erase_line(%d) at screen row: %d", mode, R->screen.cur.row));
+    ZERO_SCROLLBACK(R);
+    RESET_CHSTAT(R->h);
+
+#ifdef RXVT_GRAPHICS
+    if (rxvt_Gr_Displayed(aR))
+       rxvt_Gr_scroll(aR_ 0);
+#endif
+
+    rxvt_selection_check(aR_ 1);
+
+    R->screen.flags &= ~Screen_WrapNext;
+
+    row = R->TermWin.saveLines + R->screen.cur.row;
+    switch (mode) {
+    case 0:                    /* erase to end of line */
+       col = R->screen.cur.col;
+       num = R->TermWin.ncol - col;
+       MIN_IT(R->screen.tlen[row], (int16_t)col);
+       if (ROWCOL_IN_ROW_AT_OR_AFTER(R->selection.beg, R->screen.cur)
+           || ROWCOL_IN_ROW_AT_OR_AFTER(R->selection.end, R->screen.cur))
+           CLEAR_SELECTION(R);
+       break;
+    case 1:                    /* erase to beginning of line */
+       col = 0;
+       num = R->screen.cur.col + 1;
+       if (ROWCOL_IN_ROW_AT_OR_BEFORE(R->selection.beg, R->screen.cur)
+           || ROWCOL_IN_ROW_AT_OR_BEFORE(R->selection.end, R->screen.cur))
+           CLEAR_SELECTION(R);
+       break;
+    case 2:                    /* erase whole line */
+       col = 0;
+       num = R->TermWin.ncol;
+       R->screen.tlen[row] = 0;
+       if (R->selection.beg.row <= R->screen.cur.row
+           && R->selection.end.row >= R->screen.cur.row)
+           CLEAR_SELECTION(R);
+       break;
+    default:
+       return;
+    }
+    if (R->screen.text[row])
+       rxvt_blank_line(aR_
+                        &(R->screen.text[row][col]),
+                       &(R->screen.rend[row][col]), num, R->h->rstyle);
+    else
+       rxvt_blank_screen_mem(aR_ R->screen.text, R->screen.rend, row,
+                             R->h->rstyle);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Erase part of whole of the screen
+ * XTERM_SEQ: Clear screen after cursor : ESC [ 0 J
+ * XTERM_SEQ: Clear screen before cursor: ESC [ 1 J
+ * XTERM_SEQ: Clear whole screen        : ESC [ 2 J
+ */
+/* EXTPROTO */
+void
+rxvt_scr_erase_screen(pR_ int mode)
+{
+    int             num;
+    int32_t         row, row_offset;
+    rend_t          ren;
+    XGCValues       gcvalue;
+
+    R->h->want_refresh = 1;
+    D_SCREEN((stderr, "rxvt_scr_erase_screen(%d) at screen row: %d", mode, R->screen.cur.row));
+    ZERO_SCROLLBACK(R);
+    RESET_CHSTAT(R->h);
+    row_offset = (int32_t)R->TermWin.saveLines;
+
+    switch (mode) {
+    case 0:                    /* erase to end of screen */
+       rxvt_selection_check(aR_ 1);
+       rxvt_scr_erase_line(aR_ 0);
+       row = R->screen.cur.row + 1;    /* possible OOB */
+       num = R->TermWin.nrow - row;
+       break;
+    case 1:                    /* erase to beginning of screen */
+       rxvt_selection_check(aR_ 3);
+       rxvt_scr_erase_line(aR_ 1);
+       row = 0;
+       num = R->screen.cur.row;
+       break;
+    case 2:                    /* erase whole screen */
+       rxvt_selection_check(aR_ 3);
+#ifdef RXVT_GRAPHICS
+       rxvt_Gr_ClearScreen(aR);
+#endif
+       row = 0;
+       num = R->TermWin.nrow;
+       break;
+    default:
+       return;
+    }
+    R->h->refresh_type |= REFRESH_BOUNDS;
+    if (R->selection.op && R->h->current_screen == R->selection.screen
+       && ((R->selection.beg.row >= row && R->selection.beg.row <= row + num)
+           || (R->selection.end.row >= row
+               && R->selection.end.row <= row + num)))
+       CLEAR_SELECTION(R);
+    if (row >= R->TermWin.nrow)        /* Out Of Bounds */
+       return;
+    MIN_IT(num, (R->TermWin.nrow - row));
+    if (R->h->rstyle & (RS_RVid | RS_Uline))
+       ren = (rend_t) ~RS_None;
+    else if (GET_BASEBG(R->h->rstyle) == Color_bg) {
+       ren = DEFAULT_RSTYLE;
+       CLEAR_ROWS(row, num);
+    } else {
+       ren = (R->h->rstyle & (RS_fgMask | RS_bgMask));
+       gcvalue.foreground = R->PixColors[GET_BGCOLOR(R->h->rstyle)];
+       XChangeGC(R->Xdisplay, R->TermWin.gc, GCForeground, &gcvalue);
+       ERASE_ROWS(row, num);
+       gcvalue.foreground = R->PixColors[Color_fg];
+       XChangeGC(R->Xdisplay, R->TermWin.gc, GCForeground, &gcvalue);
+    }
+    for (; num--; row++) {
+       rxvt_blank_screen_mem(aR_ R->screen.text, R->screen.rend,
+                             (unsigned int)(row + row_offset), R->h->rstyle);
+       R->screen.tlen[row + row_offset] = 0;
+       rxvt_blank_line(aR_
+                        R->drawn_text[row], R->drawn_rend[row],
+                       (unsigned int)R->TermWin.ncol, ren);
+    }
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Fill the screen with `E's
+ * XTERM_SEQ: Screen Alignment Test: ESC # 8
+ */
+/* EXTPROTO */
+void
+rxvt_scr_E(pR)
+{
+    int             i, j, k;
+    rend_t         *r1, fs;
+
+    R->h->want_refresh = 1;
+    R->h->num_scr_allow = 0;
+    ZERO_SCROLLBACK(R);
+    RESET_CHSTAT(R->h);
+    rxvt_selection_check(aR_ 3);
+
+    fs = SET_FONT (R->h->rstyle, R->TermWin.fontset->find_font ('E'));
+    for (k = R->TermWin.saveLines, i = R->TermWin.nrow; i--; k++) {
+       R->screen.tlen[k] = R->TermWin.ncol;    /* make the `E's selectable */
+       fill_text (R->screen.text[k], 'E', R->TermWin.ncol);
+       for (r1 = R->screen.rend[k], j = R->TermWin.ncol; j--; )
+           *r1++ = fs;
+    }
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Insert/Delete <count> lines
+ */
+/* EXTPROTO */
+void
+rxvt_scr_insdel_lines(pR_ int count, int insdel)
+{
+    int             end;
+
+    ZERO_SCROLLBACK(R);
+    RESET_CHSTAT(R->h);
+
+#ifdef RXVT_GRAPHICS
+    if (rxvt_Gr_Displayed(aR))
+       rxvt_Gr_scroll(aR_ 0);
+#endif
+
+    rxvt_selection_check(aR_ 1);
+
+    if (R->screen.cur.row > R->screen.bscroll)
+       return;
+
+    end = R->screen.bscroll - R->screen.cur.row + 1;
+    if (count > end) {
+       if (insdel == DELETE)
+           return;
+       else if (insdel == INSERT)
+           count = end;
+    }
+    R->screen.flags &= ~Screen_WrapNext;
+
+    rxvt_scroll_text(aR_ R->screen.cur.row, R->screen.bscroll, insdel * count,
+                    0);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Insert/Delete <count> characters from the current position
+ */
+/* EXTPROTO */
+void
+rxvt_scr_insdel_chars(pR_ int count, int insdel)
+{
+    int             col, row;
+    rend_t          tr;
+    text_t         *stp;
+    rend_t         *srp;
+    int16_t        *slp;
+
+    R->h->want_refresh = 1;
+    ZERO_SCROLLBACK(R);
+#if 0
+    RESET_CHSTAT(R->h);
+#endif
+
+#ifdef RXVT_GRAPHICS
+    if (rxvt_Gr_Displayed(aR))
+       rxvt_Gr_scroll(aR_ 0);
+#endif
+
+    if (count <= 0)
+       return;
+
+    rxvt_selection_check(aR_ 1);
+    MIN_IT(count, (R->TermWin.ncol - R->screen.cur.col));
+
+    row = R->screen.cur.row + R->TermWin.saveLines;
+    R->screen.flags &= ~Screen_WrapNext;
+
+    stp = R->screen.text[row];
+    srp = R->screen.rend[row];
+    slp = &(R->screen.tlen[row]);
+    switch (insdel) {
+    case INSERT:
+       for (col = R->TermWin.ncol - 1; (col - count) >= R->screen.cur.col;
+            col--) {
+           stp[col] = stp[col - count];
+           srp[col] = srp[col - count];
+       }
+       if (*slp != -1) {
+           *slp += count;
+           MIN_IT(*slp, R->TermWin.ncol);
+       }
+       if (R->selection.op && R->h->current_screen == R->selection.screen
+           && ROWCOL_IN_ROW_AT_OR_AFTER(R->selection.beg, R->screen.cur)) {
+           if (R->selection.end.row != R->screen.cur.row
+               || (R->selection.end.col + count >= R->TermWin.ncol))
+               CLEAR_SELECTION(R);
+           else {              /* shift selection */
+               R->selection.beg.col += count;
+               R->selection.mark.col += count; /* XXX: yes? */
+               R->selection.end.col += count;
+           }
+       }
+       rxvt_blank_line(aR_ &(stp[R->screen.cur.col]), &(srp[R->screen.cur.col]),
+                       (unsigned int)count, R->h->rstyle);
+       break;
+    case ERASE:
+       R->screen.cur.col += count;     /* don't worry if > R->TermWin.ncol */
+       rxvt_selection_check(aR_ 1);
+       R->screen.cur.col -= count;
+       rxvt_blank_line(aR_ &(stp[R->screen.cur.col]), &(srp[R->screen.cur.col]),
+                       (unsigned int)count, R->h->rstyle);
+       break;
+    case DELETE:
+       tr = srp[R->TermWin.ncol - 1]
+            & (RS_fgMask | RS_bgMask | RS_baseattrMask);
+       for (col = R->screen.cur.col; (col + count) < R->TermWin.ncol; col++) {
+           stp[col] = stp[col + count];
+           srp[col] = srp[col + count];
+       }
+       rxvt_blank_line(aR_
+                        &(stp[R->TermWin.ncol - count]),
+                       &(srp[R->TermWin.ncol - count]),
+                       (unsigned int)count, tr);
+       if (*slp == -1) /* break line continuation */
+           *slp = R->TermWin.ncol;
+       *slp -= count;
+       MAX_IT(*slp, 0);
+       if (R->selection.op && R->h->current_screen == R->selection.screen
+           && ROWCOL_IN_ROW_AT_OR_AFTER(R->selection.beg, R->screen.cur)) {
+           if (R->selection.end.row != R->screen.cur.row
+               || (R->screen.cur.col >= R->selection.beg.col - count)
+               || R->selection.end.col >= R->TermWin.ncol)
+               CLEAR_SELECTION(R);
+           else {
+               /* shift selection */
+               R->selection.beg.col -= count;
+               R->selection.mark.col -= count; /* XXX: yes? */
+               R->selection.end.col -= count;
+           }
+       }
+       break;
+    }
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Set the scrolling region
+ * XTERM_SEQ: Set region <top> - <bot> inclusive: ESC [ <top> ; <bot> r
+ */
+/* EXTPROTO */
+void
+rxvt_scr_scroll_region(pR_ int top, int bot)
+{
+    MAX_IT(top, 0);
+    MIN_IT(bot, (int)R->TermWin.nrow - 1);
+    if (top > bot)
+       return;
+    R->screen.tscroll = top;
+    R->screen.bscroll = bot;
+    rxvt_scr_gotorc(aR_ 0, 0, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Make the cursor visible/invisible
+ * XTERM_SEQ: Make cursor visible  : ESC [ ? 25 h
+ * XTERM_SEQ: Make cursor invisible: ESC [ ? 25 l
+ */
+/* EXTPROTO */
+void
+rxvt_scr_cursor_visible(pR_ int mode)
+{
+    R->h->want_refresh = 1;
+    if (mode)
+       R->screen.flags |= Screen_VisibleCursor;
+    else
+       R->screen.flags &= ~Screen_VisibleCursor;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Set/unset automatic wrapping
+ * XTERM_SEQ: Set Wraparound  : ESC [ ? 7 h
+ * XTERM_SEQ: Unset Wraparound: ESC [ ? 7 l
+ */
+/* EXTPROTO */
+void
+rxvt_scr_autowrap(pR_ int mode)
+{
+    if (mode)
+       R->screen.flags |= Screen_Autowrap;
+    else
+       R->screen.flags &= ~(Screen_Autowrap | Screen_WrapNext);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Set/unset margin origin mode
+ * Absolute mode: line numbers are counted relative to top margin of screen
+ *      and the cursor can be moved outside the scrolling region.
+ * Relative mode: line numbers are relative to top margin of scrolling region
+ *      and the cursor cannot be moved outside.
+ * XTERM_SEQ: Set Absolute: ESC [ ? 6 h
+ * XTERM_SEQ: Set Relative: ESC [ ? 6 l
+ */
+/* EXTPROTO */
+void
+rxvt_scr_relative_origin(pR_ int mode)
+{
+    if (mode)
+       R->screen.flags |= Screen_Relative;
+    else
+       R->screen.flags &= ~Screen_Relative;
+    rxvt_scr_gotorc(aR_ 0, 0, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Set insert/replace mode
+ * XTERM_SEQ: Set Insert mode : ESC [ ? 4 h
+ * XTERM_SEQ: Set Replace mode: ESC [ ? 4 l
+ */
+/* EXTPROTO */
+void
+rxvt_scr_insert_mode(pR_ int mode)
+{
+    if (mode)
+       R->screen.flags |= Screen_Insert;
+    else
+       R->screen.flags &= ~Screen_Insert;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Set/Unset tabs
+ * XTERM_SEQ: Set tab at current column  : ESC H
+ * XTERM_SEQ: Clear tab at current column: ESC [ 0 g
+ * XTERM_SEQ: Clear all tabs             : ESC [ 3 g
+ */
+/* EXTPROTO */
+void
+rxvt_scr_set_tab(pR_ int mode)
+{
+    if (mode < 0)
+       MEMSET(R->tabs, 0, R->TermWin.ncol * sizeof(char));
+    else if (R->screen.cur.col < R->TermWin.ncol)
+       R->tabs[R->screen.cur.col] = (mode ? 1 : 0);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Set reverse/normal video
+ * XTERM_SEQ: Reverse video: ESC [ ? 5 h
+ * XTERM_SEQ: Normal video : ESC [ ? 5 l
+ */
+/* EXTPROTO */
+void
+rxvt_scr_rvideo_mode(pR_ int mode)
+{
+    XGCValues       gcvalue;
+
+    if (R->h->rvideo != mode) {
+       R->h->rvideo = mode;
+       SWAP_IT(R->PixColors[Color_fg], R->PixColors[Color_bg], rxvt_color);
+#if defined(XPM_BACKGROUND)
+       if (R->h->bgPixmap.pixmap == None)
+#endif
+#if defined(TRANSPARENT)
+           if (!(R->Options & Opt_transparent) || R->h->am_transparent == 0)
+#endif
+           XSetWindowBackground(R->Xdisplay, R->TermWin.vt,
+                                R->PixColors[Color_bg]);
+
+       gcvalue.foreground = R->PixColors[Color_fg];
+       gcvalue.background = R->PixColors[Color_bg];
+       XChangeGC(R->Xdisplay, R->TermWin.gc, GCBackground | GCForeground,
+                 &gcvalue);
+       rxvt_scr_clear(aR);
+       rxvt_scr_touch(aR_ True);
+    }
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Report current cursor position
+ * XTERM_SEQ: Report position: ESC [ 6 n
+ */
+/* EXTPROTO */
+void
+rxvt_scr_report_position(pR)
+{
+    rxvt_tt_printf(aR_ "\033[%d;%dR", R->screen.cur.row + 1,
+                  R->screen.cur.col + 1);
+}
+\f
+/* ------------------------------------------------------------------------- *
+ *                                  FONTS                                    *
+ * ------------------------------------------------------------------------- */
+
+/*
+ * Set font style
+ */
+/* INTPROTO */
+void
+rxvt_set_font_style(pR)
+{
+    switch (R->h->charsets[R->screen.charset]) {
+    case '0':                  /* DEC Special Character & Line Drawing Set */
+       break;
+    case 'A':                  /* United Kingdom (UK) */
+       break;
+    case 'B':                  /* United States (USASCII) */
+       break;
+    case '<':                  /* Multinational character set */
+       break;
+    case '5':                  /* Finnish character set */
+       break;
+    case 'C':                  /* Finnish character set */
+       break;
+    case 'K':                  /* German character set */
+       break;
+    }
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Choose a font
+ * XTERM_SEQ: Invoke G0 character set: CTRL-O
+ * XTERM_SEQ: Invoke G1 character set: CTRL-N
+ * XTERM_SEQ: Invoke G2 character set: ESC N
+ * XTERM_SEQ: Invoke G3 character set: ESC O
+ */
+/* EXTPROTO */
+void
+rxvt_scr_charset_choose(pR_ int set)
+{
+    R->screen.charset = set;
+    rxvt_set_font_style(aR);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Set a font
+ * XTERM_SEQ: Set G0 character set: ESC ( <C>
+ * XTERM_SEQ: Set G1 character set: ESC ) <C>
+ * XTERM_SEQ: Set G2 character set: ESC * <C>
+ * XTERM_SEQ: Set G3 character set: ESC + <C>
+ * See set_font_style for possible values for <C>
+ */
+/* EXTPROTO */
+void
+rxvt_scr_charset_set(pR_ int set, unsigned int ch)
+{
+    R->h->charsets[set] = (unsigned char)ch;
+    rxvt_set_font_style(aR);
+}
+
+\f
+/* ------------------------------------------------------------------------- *
+ *                           GRAPHICS COLOURS                                *
+ * ------------------------------------------------------------------------- */
+
+#ifdef RXVT_GRAPHICS
+/* EXTPROTO */
+int
+rxvt_scr_get_fgcolor(pR)
+{
+    return GET_FGCOLOR(R->h->rstyle);
+}
+
+/* ------------------------------------------------------------------------- */
+/* EXTPROTO */
+int
+rxvt_scr_get_bgcolor(pR)
+{
+    return GET_BGCOLOR(R->h->rstyle);
+}
+#endif
+\f
+/* ------------------------------------------------------------------------- *
+ *                        MAJOR SCREEN MANIPULATION                          *
+ * ------------------------------------------------------------------------- */
+
+/*
+ * Refresh an area
+ */
+enum {
+    PART_BEG = 0,
+    PART_END,
+    RC_COUNT
+};
+
+/* EXTPROTO */
+void
+rxvt_scr_expose(pR_ int x, int y, int width, int height, Bool refresh)
+{
+    int             i;
+    row_col_t       rc[RC_COUNT];
+
+    if (R->drawn_text == NULL) /* sanity check */
+       return;
+
+#ifdef DEBUG_STRICT
+    x = max(x, (int)R->TermWin.int_bwidth);
+    x = min(x, (int)R->TermWin.width);
+    y = max(y, (int)R->TermWin.int_bwidth);
+    y = min(y, (int)R->TermWin.height);
+#endif
+
+/* round down */
+    rc[PART_BEG].col = Pixel2Col(x);
+    rc[PART_BEG].row = Pixel2Row(y);
+/* round up */
+    rc[PART_END].col = Pixel2Width(x + width + R->TermWin.fwidth - 1);
+    rc[PART_END].row = Pixel2Row(y + height + R->TermWin.fheight - 1);
+
+/* sanity checks */
+    for (i = PART_BEG; i < RC_COUNT; i++) {
+       MIN_IT(rc[i].col, R->TermWin.ncol - 1);
+       MIN_IT(rc[i].row, R->TermWin.nrow - 1);
+    }
+
+    D_SCREEN((stderr, "rxvt_scr_expose(x:%d, y:%d, w:%d, h:%d) area (c:%d,r:%d)-(c:%d,r:%d)", x, y, width, height, rc[PART_BEG].col, rc[PART_BEG].row, rc[PART_END].col, rc[PART_END].row));
+
+    for (i = rc[PART_BEG].row; i <= rc[PART_END].row; i++)
+       fill_text (&(R->drawn_text[i][rc[PART_BEG].col]), 0,
+                  (rc[PART_END].col - rc[PART_BEG].col + 1));
+
+    if (refresh)
+       rxvt_scr_refresh(aR_ SLOW_REFRESH | REFRESH_BOUNDS);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Refresh the entire screen
+ */
+/* EXTPROTO */
+void
+rxvt_scr_touch(pR_ Bool refresh)
+{
+    rxvt_scr_expose(aR_ 0, 0, R->TermWin.width, R->TermWin.height, refresh);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Move the display so that the line represented by scrollbar value Y is at
+ * the top of the screen
+ */
+/* EXTPROTO */
+int
+rxvt_scr_move_to(pR_ int y, int len)
+{
+    long            p = 0;
+    uint16_t       oldviewstart;
+
+    oldviewstart = R->TermWin.view_start;
+    if (y < len) {
+       p = (R->TermWin.nrow + R->TermWin.nscrolled) * (len - y) / len;
+       p -= (long)(R->TermWin.nrow - 1);
+       p = max(p, 0);
+    }
+    R->TermWin.view_start = (uint16_t)min(p, R->TermWin.nscrolled);
+    D_SCREEN((stderr, "rxvt_scr_move_to(%d, %d) view_start:%d", y, len, R->TermWin.view_start));
+
+    return rxvt_scr_changeview(aR_ oldviewstart);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Page the screen up/down nlines
+ * direction should be UP or DN
+ */
+/* EXTPROTO */
+int
+rxvt_scr_page(pR_ enum page_dirn direction, int nlines)
+{
+    int             n;
+    uint16_t       oldviewstart;
+
+    D_SCREEN((stderr, "rxvt_scr_page(%s, %d) view_start:%d", ((direction == UP) ? "UP" : "DN"), nlines, R->TermWin.view_start));
+#ifdef DEBUG_STRICT
+    assert((nlines >= 0) && (nlines <= R->TermWin.nrow));
+#endif
+    oldviewstart = R->TermWin.view_start;
+    if (direction == UP) {
+       n = R->TermWin.view_start + nlines;
+       R->TermWin.view_start = min(n, R->TermWin.nscrolled);
+    } else {
+       n = R->TermWin.view_start - nlines;
+       R->TermWin.view_start = max(n, 0);
+    }
+    return rxvt_scr_changeview(aR_ oldviewstart);
+}
+
+/* INTPROTO */
+int
+rxvt_scr_changeview(pR_ uint16_t oldviewstart)
+{
+    if (R->TermWin.view_start != oldviewstart) {
+       R->h->want_refresh = 1;
+#ifdef RXVT_GRAPHICS
+       if (rxvt_Gr_Displayed(aR))
+           rxvt_Gr_scroll(aR_ 0);
+#endif
+       R->h->num_scr -= (R->TermWin.view_start - oldviewstart);
+    }
+    return (int)(R->TermWin.view_start - oldviewstart);
+}
+
+/* ------------------------------------------------------------------------- */
+/* EXTPROTO */
+void
+rxvt_scr_bell(pR)
+{
+#ifndef NO_BELL
+# ifndef NO_MAPALERT
+#  ifdef MAPALERT_OPTION
+    if (R->Options & Opt_mapAlert)
+#  endif
+       XMapWindow(R->Xdisplay, R->TermWin.parent[0]);
+# endif
+    if (R->Options & Opt_visualBell) {
+       rxvt_scr_rvideo_mode(aR_ !R->h->rvideo); /* refresh also done */
+       rxvt_scr_rvideo_mode(aR_ !R->h->rvideo); /* refresh also done */
+    } else
+       XBell(R->Xdisplay, 0);
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+/* ARGSUSED */
+/* EXTPROTO */
+void
+rxvt_scr_printscreen(pR_ int fullhist)
+{
+#ifdef PRINTPIPE
+    int             i, r1, nrows, row_offset;
+    text_t         *t;
+    FILE           *fd;
+
+    if ((fd = rxvt_popen_printer(aR)) == NULL)
+       return;
+    nrows = R->TermWin.nrow;
+    row_offset = R->TermWin.saveLines;
+    if (!fullhist)
+       row_offset -= R->TermWin.view_start;
+    else {
+       nrows += R->TermWin.nscrolled;
+       row_offset -= R->TermWin.nscrolled;
+    }
+
+    for (r1 = 0; r1 < nrows; r1++) {
+       t = R->screen.text[r1 + row_offset];
+       for (i = R->TermWin.ncol - 1; i >= 0; i--)
+           if (!isspace(t[i]))
+               break;
+       fprintf(fd, "%.*s\n", (i + 1), t);
+    }
+    rxvt_pclose_printer(fd);
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Refresh the screen
+ * R->drawn_text/R->drawn_rend contain the screen information before the update.
+ * R->screen.text/R->screen.rend contain what the screen will change to.
+ */
+
+#if defined (NO_BRIGHTCOLOR) || defined (VERYBOLD)
+# define MONO_BOLD(x)          ((x) & (RS_Bold|RS_Blink))
+# define MONO_BOLD_FG(x, fg)   MONO_BOLD(x)
+#else
+# define MONO_BOLD(x)                                          \
+    (((x) & (RS_Bold | RS_fgMask)) == (RS_Bold | Color_fg))
+# define MONO_BOLD_FG(x, fg)   (((x) & RS_Bold) && (fg) == Color_fg)
+#endif
+
+#define FONT_WIDTH(X, Y)                                               \
+    (X)->per_char[(Y) - (X)->min_char_or_byte2].width
+#define FONT_RBEAR(X, Y)                                               \
+    (X)->per_char[(Y) - (X)->min_char_or_byte2].rbearing
+#define FONT_LBEAR(X, Y)                                               \
+    (X)->per_char[(Y) - (X)->min_char_or_byte2].lbearing
+#define IS_FONT_CHAR(X, Y)                                             \
+    ((Y) >= (X)->min_char_or_byte2 && (Y) <= (X)->max_char_or_byte2)
+
+/* EXTPROTO */
+void
+rxvt_scr_refresh(pR_ unsigned char refresh_type)
+{
+    unsigned char   clearfirst,        /* first character writes before cell        */
+                   clearlast,  /* last character writes beyond cell         */
+                   must_clear, /* use draw_string not draw_image_string     */
+#ifndef NO_BOLDFONT
+                   bfont,      /* we've changed font to bold font           */
+#endif
+                   rvid,       /* reverse video this position               */
+                   wbyte,      /* we're in multibyte                        */
+                   showcursor; /* show the cursor                           */
+    int             fore, back;        /* desired foreground/background             */
+    int16_t         col, row,  /* column/row we're processing               */
+                    ocrow;     /* old cursor row                            */
+    int             cursorwidth;
+    int             i,         /* tmp                                       */
+                   row_offset; /* basic offset in screen structure          */
+#ifndef NO_CURSORCOLOR
+    rend_t         cc1;        /* store colours at cursor position(s)       */
+    rend_t          cc2;       /* store colours at cursor position(s)       */
+#endif
+    rend_t         *drp, *srp; /* drawn-rend-pointer, screen-rend-pointer   */
+    text_t         *dtp, *stp; /* drawn-text-pointer, screen-text-pointer   */
+    char           *buffer;    /* local copy of R->h->buffer                */
+    struct rxvt_hidden *h = R->h;
+
+    if (refresh_type == NO_REFRESH || !R->TermWin.mapped)
+       return;
+
+/*
+ * A: set up vars
+ */
+    clearfirst = clearlast = must_clear = wbyte = 0;
+#ifndef NO_BOLDFONT
+    bfont = 0;
+#endif
+
+    if (h->currmaxcol < R->TermWin.ncol) {
+       h->currmaxcol = R->TermWin.ncol;
+       h->buffer = (char *)rxvt_realloc (h->buffer,
+                                          sizeof(char) * (h->currmaxcol + 1) * MB_CUR_MAX);
+    }
+    buffer = h->buffer;
+    h->refresh_count = 0;
+
+    row_offset = R->TermWin.saveLines - R->TermWin.view_start;
+
+    if ((refresh_type & REFRESH_BOUNDS)) {
+       clearfirst = clearlast = 1;
+       h->refresh_type &= ~REFRESH_BOUNDS;
+    }
+#if defined(XPM_BACKGROUND)
+    must_clear |= (h->bgPixmap.pixmap != None);
+#endif
+#if defined(TRANSPARENT)
+    must_clear |= ((R->Options & Opt_transparent) && h->am_transparent);
+#endif
+    ocrow = h->oldcursor.row; /* is there an old outline cursor on screen? */
+
+/*
+ * B: reverse any characters which are selected
+ */
+    rxvt_scr_reverse_selection(aR);
+
+/*
+ * C: set the cursor character(s)
+ */
+    {
+       unsigned char   setoldcursor;
+       rend_t          ccol1,  /* Cursor colour       */
+                       ccol2;  /* Cursor colour2      */
+
+       showcursor = (R->screen.flags & Screen_VisibleCursor);
+        cursorwidth = 0;
+#ifdef CURSOR_BLINK
+       if (R->h->hidden_cursor)
+           showcursor = 0;
+#endif
+
+        cursorwidth = 0;
+
+        if (showcursor)
+          {
+            cursorwidth++;
+
+            srp = &(R->screen.rend[R->screen.cur.row + R->TermWin.saveLines]
+                                  [R->screen.cur.col]);
+
+            if (showcursor && R->TermWin.focus)
+              {
+                *srp ^= RS_RVid;
+#ifndef NO_CURSORCOLOR
+                cc1 = *srp & (RS_fgMask | RS_bgMask);
+                if (XDEPTH > 2 && ISSET_PIXCOLOR(h, Color_cursor))
+                    ccol1 = Color_cursor;
+                else
+#ifdef CURSOR_COLOR_IS_RENDITION_COLOR
+                    ccol1 = GET_FGCOLOR(h->rstyle);
+#else
+                    ccol1 = Color_fg;
+#endif
+                if (XDEPTH > 2 && ISSET_PIXCOLOR(h, Color_cursor2))
+                    ccol2 = Color_cursor2;
+                else
+#ifdef CURSOR_COLOR_IS_RENDITION_COLOR
+                    ccol2 = GET_BGCOLOR(h->rstyle);
+#else
+                    ccol2 = Color_bg;
+#endif
+                *srp = SET_FGCOLOR(*srp, ccol1);
+                *srp = SET_BGCOLOR(*srp, ccol2);
+#endif
+              }
+
+            while (IS_WIDE (*srp))
+              cursorwidth++, srp++;
+          }
+
+       /* make sure no outline cursor is left around */
+       setoldcursor = 0;
+       if (ocrow != -1) {
+           if (R->screen.cur.row + R->TermWin.view_start != ocrow
+               || R->screen.cur.col != h->oldcursor.col) {
+               if (ocrow < R->TermWin.nrow
+                   && h->oldcursor.col < R->TermWin.ncol) {
+                   R->drawn_rend[ocrow][h->oldcursor.col] ^= (RS_RVid | RS_Uline);
+               }
+               if (R->TermWin.focus || !showcursor)
+                   h->oldcursor.row = -1;
+               else
+                   setoldcursor = 1;
+           }
+       } else if (!R->TermWin.focus)
+           setoldcursor = 1;
+       if (setoldcursor) {
+           if (R->screen.cur.row + R->TermWin.view_start >= R->TermWin.nrow)
+               h->oldcursor.row = -1;
+           else {
+               h->oldcursor.row = R->screen.cur.row + R->TermWin.view_start;
+               h->oldcursor.col = R->screen.cur.col;
+           }
+       }
+    }
+
+#ifndef NO_SLOW_LINK_SUPPORT
+/*
+ * D: CopyArea pass - very useful for slower links
+ *    This has been deliberately kept simple.
+ */
+    i = h->num_scr;
+    if (refresh_type == FAST_REFRESH && h->num_scr_allow && i
+       && abs(i) < R->TermWin.nrow && !must_clear) {
+       int16_t         nits;
+       int             j;
+       rend_t         *drp2;
+       text_t         *dtp2;
+        int             len, wlen;
+
+       j = R->TermWin.nrow;
+       wlen = len = -1;
+       row = i > 0 ? 0 : j - 1;
+       for (; j-- >= 0; row += (i > 0 ? 1 : -1)) {
+           if (row + i >= 0 && row + i < R->TermWin.nrow && row + i != ocrow) {
+               stp = R->screen.text[row + row_offset];
+               srp = R->screen.rend[row + row_offset];
+               dtp = R->drawn_text[row];
+               dtp2 = R->drawn_text[row + i];
+               drp = R->drawn_rend[row];
+               drp2 = R->drawn_rend[row + i];
+               for (nits = 0, col = R->TermWin.ncol; col--; )
+                   if (stp[col] != dtp2[col] || srp[col] != drp2[col])
+                       nits--;
+                   else if (stp[col] != dtp[col] || srp[col] != drp[col])
+                       nits++;
+               if (nits > 8) { /* XXX: arbitrary choice */
+                   for (col = R->TermWin.ncol; col--; ) {
+                       *dtp++ = *dtp2++;
+                       *drp++ = *drp2++;
+                   }
+                   if (len == -1)
+                       len = row;
+                   wlen = row;
+                   continue;
+               }
+           }
+           if (len != -1) {
+               /* also comes here at end if needed because of >= above */
+               if (wlen < len)
+                   SWAP_IT(wlen, len, int);
+               D_SCREEN((stderr, "rxvt_scr_refresh(): XCopyArea: %d -> %d (height: %d)", len + i, len, wlen - len + 1));
+               XCopyArea(R->Xdisplay, R->TermWin.vt, R->TermWin.vt,
+                         R->TermWin.gc, 0, Row2Pixel(len + i),
+                         (unsigned int)TermWin_TotalWidth(),
+                         (unsigned int)Height2Pixel(wlen - len + 1),
+                         0, Row2Pixel(len));
+               len = -1;
+           }
+       }
+    }
+#endif
+
+/*
+ * E: main pass across every character
+ */
+    for (row = 0; row < R->TermWin.nrow; row++)
+      {
+        stp = R->screen.text[row + row_offset];
+        srp = R->screen.rend[row + row_offset];
+        dtp = R->drawn_text[row];
+        drp = R->drawn_rend[row];
+
+/*
+ * E2: OK, now the real pass
+ */
+       int ypixel = (int)Row2Pixel(row);
+
+       for (col = 0; col < R->TermWin.ncol; col++) {
+           /* compare new text with old - if exactly the same then continue */
+           rend_t rend = srp[col];     /* screen rendition (target rendtion) */
+
+           if (stp[col] == dtp[col]    /* Must match characters to skip. */
+               && (rend == drp[col]    /* Either rendition the same or   */
+                   || (stp[col] == ' ' /* space w/ no background change  */
+                       && GET_BGATTR(rend) == GET_BGATTR(drp[col]))))
+             continue;
+
+            text_t *text = stp + col;
+            int count = 1;
+
+           /* redraw one or more characters */
+
+            dtp[col] = stp[col];
+           drp[col] = rend;
+
+            if (*text == NOCHAR) // never start redrawing at invisible characters. */
+              continue;
+
+           int xpixel = Col2Pixel(col);
+
+            // this loop looks very messy, it can probably be optimized
+            // and cleaned a bit by you?
+            for (i = 0; ++col < R->TermWin.ncol; )
+              {
+                if (stp[col] == NOCHAR)
+                  {
+                    dtp[col] = stp[col];
+                    drp[col] = rend;
+                    count++;
+
+                    if (i) // only possible skip if char unchanged
+                      i++;
+
+                    continue;
+                  }
+
+                if (((rend ^ srp[col]) & ~RS_wide) != 0)
+                  break;
+
+                count++;
+
+                if (stp[col] != dtp[col]
+                    || srp[col] != drp[col])
+                  {
+                    if (must_clear && (i++ > (count / 2)))
+                      break;
+
+                    dtp[col] = stp[col];
+                    drp[col] = rend;
+                    i = 0;
+                  }
+                else if (must_clear || (stp[col] != ' ' && ++i >= 32))
+                  break;
+              }
+
+            col--;     /* went one too far.  move back */
+            count -= i;        /* dump any matching trailing chars */
+
+/*
+ * Determine the attributes for the string
+ */
+            int fid = GET_FONT(rend);
+           fore = GET_FGCOLOR(rend);
+           back = GET_BGCOLOR(rend);
+           rend = GET_ATTR(rend);
+
+           rvid = (rend & RS_RVid) ? 1 : 0;
+#ifdef OPTION_HC
+           if (!rvid && (rend & RS_Blink))
+              {
+               if (XDEPTH > 2 && ISSET_PIXCOLOR(h, Color_HC))
+                 back = Color_HC;
+               else
+                 rvid = !rvid; /* fall back */
+              }
+#endif
+           if (rvid)
+              {
+               SWAP_IT(fore, back, int);
+
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+               if (XDEPTH > 2 && ISSET_PIXCOLOR(h, Color_RV)
+# ifndef NO_CURSORCOLOR
+                   && !ISSET_PIXCOLOR(h, Color_cursor)
+# endif
+                    )
+                 back = Color_RV;
+#endif
+             }
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+           else if (rend & RS_Bold)
+              {
+               if (XDEPTH > 2 && ISSET_PIXCOLOR(h, Color_BD))
+                  {
+                   fore = Color_BD;
+# ifndef VERYBOLD
+                   rend &= ~RS_Bold;   /* we've taken care of it */
+# endif
+                  }
+             }
+            else if (rend & RS_Uline)
+              {
+               if (XDEPTH > 2 && ISSET_PIXCOLOR(h, Color_UL))
+                  {
+                   fore = Color_UL;
+                   rend &= ~RS_Uline;  /* we've taken care of it */
+                  }
+             }
+#endif
+
+/*
+ * Actually do the drawing of the string here
+ */
+            rxvt_font *font = (*R->TermWin.fontset)[fid];
+
+            if (back == Color_bg)
+              {
+               if (must_clear)
+                  {
+                    for (i = 0; i < count; i++)        /* don't draw empty strings */
+                        if (text[i] != ' ') {
+                            font->draw (xpixel, ypixel, text, count, fore, -1);
+                            goto nodraw;
+                        }
+                    CLEAR_CHARS(xpixel, ypixel, count);
+nodraw: ;
+                  }
+                else
+                  font->draw (xpixel, ypixel, text, count, fore, Color_bg);
+           } else
+                font->draw (xpixel, ypixel, text, count, fore, back);
+
+           if ((rend & RS_Uline) && (font->descent > 1))
+               XDrawLine(R->Xdisplay, drawBuffer, R->TermWin.gc,
+                         xpixel, ypixel + font->ascent + 1,
+                         xpixel + Width2Pixel(count) - 1, ypixel + font->ascent + 1);
+       }                       /* for (col....) */
+    }                          /* for (row....) */
+
+/*
+ * G: cleanup cursor and display outline cursor if necessary
+ */
+    if (showcursor) {
+       if (R->TermWin.focus) {
+           srp = &(R->screen.rend[R->screen.cur.row + R->TermWin.saveLines]
+                                 [R->screen.cur.col]);
+           *srp ^= RS_RVid;
+#ifndef NO_CURSORCOLOR
+           *srp = (*srp & ~(RS_fgMask | RS_bgMask)) | cc1;
+#endif
+       } else if (h->oldcursor.row >= 0) {
+#ifndef NO_CURSORCOLOR
+           unsigned long   gcmask;     /* Graphics Context mask */
+
+           if (XDEPTH > 2 && ISSET_PIXCOLOR(h, Color_cursor)) {
+                XSetForeground (R->Xdisplay, R->TermWin.gc, R->PixColors[Color_cursor]);
+           }
+#endif
+           XDrawRectangle(R->Xdisplay, drawBuffer, R->TermWin.gc,
+                          Col2Pixel(h->oldcursor.col),
+                          Row2Pixel(h->oldcursor.row),
+                          (unsigned int)(Width2Pixel(cursorwidth) - 1),
+                          (unsigned int)(Height2Pixel(1) - R->TermWin.lineSpace - 1));
+       }
+    }
+/*
+ * H: cleanup selection
+ */
+    rxvt_scr_reverse_selection(aR);
+
+/*
+ * I: other general cleanup
+ */
+    if (clearfirst && R->TermWin.int_bwidth)
+       /* 
+        * clear the whole screen height, note that width == 0 is treated
+        * specially by XClearArea
+        */
+       XClearArea(R->Xdisplay, R->TermWin.vt, 0, 0,
+                  (unsigned int)R->TermWin.int_bwidth,
+                  (unsigned int)TermWin_TotalHeight(), False);
+    if (clearlast && R->TermWin.int_bwidth)
+       /* 
+        * clear the whole screen height, note that width == 0 is treated
+        * specially by XClearArea
+        */
+       XClearArea(R->Xdisplay, R->TermWin.vt,
+                  R->TermWin.width + R->TermWin.int_bwidth, 0,
+                  (unsigned int)R->TermWin.int_bwidth,
+                  (unsigned int)TermWin_TotalHeight(), False);
+    if (refresh_type & SMOOTH_REFRESH)
+       XSync(R->Xdisplay, False);
+
+    h->num_scr = 0;
+    h->num_scr_allow = 1;
+    h->want_refresh = 0;       /* screen is current */
+}
+/* ------------------------------------------------------------------------- */
+
+/* EXTPROTO */
+void
+rxvt_scr_clear(pR)
+{
+    if (!R->TermWin.mapped)
+       return;
+    R->h->num_scr_allow = 0;
+    R->h->want_refresh = 1;
+#ifdef TRANSPARENT
+    if ((R->Options & Opt_transparent) && (R->h->am_pixmap_trans == 0)) {
+       int             i;
+
+       if (!(R->Options & Opt_transparent_all))
+           i = 0;
+       else
+           i = (int)(sizeof(R->TermWin.parent) / sizeof(Window));
+       for (; i--;)
+           if (R->TermWin.parent[i] != None)
+               XClearWindow(R->Xdisplay, R->TermWin.parent[i]);
+    }
+#endif
+    XClearWindow(R->Xdisplay, R->TermWin.vt);
+}
+
+/* ------------------------------------------------------------------------- */
+/* INTPROTO */
+void
+rxvt_scr_reverse_selection(pR)
+{
+    int             i, col, row, end_row;
+    rend_t         *srp;
+
+    if (R->selection.op && R->h->current_screen == R->selection.screen) {
+       end_row = R->TermWin.saveLines - R->TermWin.view_start;
+       i = R->selection.beg.row + R->TermWin.saveLines;
+       row = R->selection.end.row + R->TermWin.saveLines;
+       if (i >= end_row)
+           col = R->selection.beg.col;
+       else {
+           col = 0;
+           i = end_row;
+       }
+       end_row += R->TermWin.nrow;
+       for (; i < row && i < end_row; i++, col = 0)
+           for (srp = R->screen.rend[i]; col < R->TermWin.ncol; col++)
+#ifndef OPTION_HC
+               srp[col] ^= RS_RVid;
+#else
+               srp[col] ^= RS_Blink;
+#endif
+       if (i == row && i < end_row)
+           for (srp = R->screen.rend[i]; col < R->selection.end.col; col++)
+#ifndef OPTION_HC
+               srp[col] ^= RS_RVid;
+#else
+               srp[col] ^= RS_Blink;
+#endif
+    }
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Dump the whole scrollback and screen to the passed filedescriptor.  The
+ * invoking routine must close the fd.
+ */
+#if 0
+/* EXTPROTO */
+void
+rxvt_scr_dump(pR_ int fd)
+{
+    int             row, wrote;
+    unsigned int    width, towrite;
+    char            r1[] = "\n";
+
+    for (row = R->TermWin.saveLines - R->TermWin.nscrolled;
+        row < R->TermWin.saveLines + R->TermWin.nrow - 1; row++) {
+       width = R->screen.tlen[row] >= 0 ? R->screen.tlen[row]
+                                        : R->TermWin.ncol;
+       for (towrite = width; towrite; towrite -= wrote) {
+           wrote = write(fd, &(R->screen.text[row][width - towrite]),
+                         towrite);
+           if (wrote < 0)
+               return;         /* XXX: death, no report */
+       }
+       if (R->screen.tlen[row] >= 0)
+           if (write(fd, r1, 1) <= 0)
+               return; /* XXX: death, no report */
+    }
+}
+#endif
+\f
+/* ------------------------------------------------------------------------- *
+ *                           CHARACTER SELECTION                             *
+ * ------------------------------------------------------------------------- */
+
+/*
+ * -R->TermWin.nscrolled <= (selection row) <= R->TermWin.nrow - 1
+ */
+/* EXTPROTO */
+void
+rxvt_selection_check(pR_ int check_more)
+{
+    row_col_t       pos;
+
+    if (!R->selection.op)
+       return;
+
+    pos.row = pos.col = 0;
+    if ((R->selection.beg.row < -(int32_t)R->TermWin.nscrolled)
+       || (R->selection.beg.row >= R->TermWin.nrow)
+       || (R->selection.mark.row < -(int32_t)R->TermWin.nscrolled)
+       || (R->selection.mark.row >= R->TermWin.nrow)
+       || (R->selection.end.row < -(int32_t)R->TermWin.nscrolled)
+       || (R->selection.end.row >= R->TermWin.nrow)
+        || (check_more == 1
+           && R->h->current_screen == R->selection.screen
+           && !ROWCOL_IS_BEFORE(R->screen.cur, R->selection.beg)
+           && ROWCOL_IS_BEFORE(R->screen.cur, R->selection.end))
+       || (check_more == 2
+           && ROWCOL_IS_BEFORE(R->selection.beg, pos)
+           && ROWCOL_IS_AFTER(R->selection.end, pos))
+       || (check_more == 3
+           && ROWCOL_IS_AFTER(R->selection.end, pos))
+       || (check_more == 4     /* screen width change */
+           && (R->selection.beg.row != R->selection.end.row
+               || R->selection.end.col > R->TermWin.ncol)))
+       CLEAR_SELECTION(R);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Paste a selection direct to the command fd
+ */
+/* INTPROTO */
+void
+rxvt_PasteIt(pR_ const unsigned char *data, unsigned int nitems)
+{
+    unsigned int    i, j, n;
+    unsigned char  *ds = (unsigned char *)rxvt_malloc(PROP_SIZE);
+    
+/* convert normal newline chars into common keyboard Return key sequence */
+    for (i = 0; i < nitems; i += PROP_SIZE) {
+       n = min(nitems - i, PROP_SIZE);
+       MEMCPY(ds, data + i, n);
+       for (j = 0; j < n; j++)
+           if (ds[j] == '\n')
+               ds[j] = '\r';
+       rxvt_tt_write(aR_ ds, (int)n);
+    }
+    free(ds);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Respond to a notification that a primary selection has been sent
+ * EXT: SelectionNotify
+ */
+/* EXTPROTO */
+int
+rxvt_selection_paste(pR_ Window win, Atom prop, Bool delete_prop)
+{
+    long            nread = 0;
+    unsigned long   bytes_after;
+    XTextProperty   ct;
+#ifdef MULTICHAR_SET
+    int             dummy_count;
+    char          **cl;
+#endif
+
+    D_SELECT((stderr, "rxvt_selection_paste(%08lx, %lu, %d), wait=%2x", win, (unsigned long)prop, (int)delete_prop, R->h->selection_wait));
+
+    if (prop == None) {                /* check for failed XConvertSelection */
+#ifdef MULTICHAR_SET
+       if ((R->h->selection_type & Sel_CompoundText)) {
+           int             selnum = R->h->selection_type & Sel_whereMask;
+
+           R->h->selection_type = 0;
+           if (selnum != Sel_direct)
+               rxvt_selection_request_other(aR_ XA_STRING, selnum);
+       }
+#endif
+       return 0;
+    }
+    for (;;) {
+       if (XGetWindowProperty(R->Xdisplay, win, prop, (long)(nread / 4),
+                              (long)(PROP_SIZE / 4), delete_prop,
+                              AnyPropertyType, &ct.encoding, &ct.format,
+                              &ct.nitems, &bytes_after,
+                              &ct.value) != Success)
+           break;
+       if (ct.encoding == 0) {
+           D_SELECT((stderr, "rxvt_selection_paste: property didn't exist!"));
+           break;
+       }
+       if (ct.value == NULL) {
+           D_SELECT((stderr, "rxvt_selection_paste: property shooting blanks!"));
+           continue;
+       }
+       if (ct.nitems == 0) {
+           D_SELECT((stderr, "rxvt_selection_paste: property empty - also INCR end"));
+           if (R->h->selection_wait == Sel_normal && nread == 0) {
+           /*
+            * pass through again trying CUT_BUFFER0 if we've come from
+            * XConvertSelection() but nothing was presented
+            */
+               D_SELECT((stderr, "rxvt_selection_request: pasting CUT_BUFFER0"));
+               rxvt_selection_paste(aR_ Xroot, XA_CUT_BUFFER0, False);
+           }
+           nread = -1;         /* discount any previous stuff */
+           break;
+       }
+       nread += ct.nitems;
+#ifdef MULTICHAR_SET
+       if (XmbTextPropertyToTextList(R->Xdisplay, &ct, &cl,
+                                     &dummy_count) == Success && cl) {
+           rxvt_PasteIt(aR_ cl[0], STRLEN(cl[0]));
+           XFreeStringList(cl);
+       } else
+#endif
+           rxvt_PasteIt(aR_ ct.value, (unsigned int)ct.nitems);
+       if (bytes_after == 0)
+           break;
+       XFree(ct.value);
+    }
+    if (ct.value)
+       XFree(ct.value);
+    if (R->h->selection_wait == Sel_normal)
+       R->h->selection_wait = Sel_none;
+    D_SELECT((stderr, "rxvt_selection_paste: bytes written: %ld", nread));
+    return (int)nread;
+}
+
+/*
+ * INCR support originally provided by Paul Sheer <psheer@obsidian.co.za>
+ */
+/* EXTPROTO */
+void
+rxvt_selection_property(pR_ Window win, Atom prop)
+{
+    int             reget_time = 0;
+
+    if (prop == None)
+       return;
+    D_SELECT((stderr, "rxvt_selection_property(%08lx, %lu)", win, (unsigned long)prop));
+    if (R->h->selection_wait == Sel_normal) {
+       int             a, afmt;
+       Atom            atype;
+       unsigned long   bytes_after, nitems;
+       unsigned char  *s = NULL;
+
+       a = XGetWindowProperty(R->Xdisplay, win, prop, 0L, 1L, False,
+                              R->h->xa[XA_INCR], &atype, &afmt, &nitems,
+                              &bytes_after, &s);
+       if (s)
+           XFree(s);
+       if (a != Success)
+           return;
+#ifndef __CYGWIN32__
+       if (atype == R->h->xa[XA_INCR]) {       /* start an INCR transfer */
+           D_SELECT((stderr, "rxvt_selection_property: INCR: starting transfer"));
+           XDeleteProperty(R->Xdisplay, win, prop);
+           XFlush(R->Xdisplay);
+           reget_time = 1;
+           R->h->selection_wait = Sel_incr;
+       }
+#endif
+    } else if (R->h->selection_wait == Sel_incr) {
+       reget_time = 1;
+       if (rxvt_selection_paste(aR_ win, prop, True) == -1) {
+           D_SELECT((stderr, "rxvt_selection_property: INCR: clean end"));
+           R->h->selection_wait = Sel_none;
+           R->h->timeout[TIMEOUT_INCR].tv_sec = 0;     /* turn off timer */
+       }
+    }
+    if (reget_time) {  /* received more data so reget time */
+       (void)gettimeofday(&(R->h->timeout[TIMEOUT_INCR]), NULL);
+       R->h->timeout[TIMEOUT_INCR].tv_sec += 10;       /* ten seconds wait */
+    }
+}
+/* ------------------------------------------------------------------------- */
+/*
+ * Request the current selection: 
+ * Order: > internal selection if available
+ *        > PRIMARY, SECONDARY, CLIPBOARD if ownership is claimed (+)
+ *        > CUT_BUFFER0
+ * (+) if ownership is claimed but property is empty, rxvt_selection_paste()
+ *     will auto fallback to CUT_BUFFER0
+ * EXT: button 2 release
+ */
+/* EXTPROTO */
+void
+rxvt_selection_request(pR_ Time tm, int x, int y)
+{
+    D_SELECT((stderr, "rxvt_selection_request(%lu, %d, %d)", tm, x, y));
+    if (x < 0 || x >= R->TermWin.width || y < 0 || y >= R->TermWin.height)
+       return;                 /* outside window */
+
+    if (R->selection.text != NULL) {   /* internal selection */
+       D_SELECT((stderr, "rxvt_selection_request: pasting internal"));
+       rxvt_PasteIt(aR_ R->selection.text, R->selection.len);
+       return;
+    } else {
+       int             i;
+
+       R->h->selection_request_time = tm;
+       R->h->selection_wait = Sel_normal;
+       for (i = Sel_Primary; i <= Sel_Clipboard; i++) {
+#ifdef MULTICHAR_SET
+           R->h->selection_type = Sel_CompoundText;
+#else
+           R->h->selection_type = 0;
+#endif
+           if (rxvt_selection_request_other(aR_
+#ifdef MULTICHAR_SET
+                                            R->h->xa[XA_COMPOUND_TEXT],
+#else
+                                            XA_STRING,
+#endif
+                                            i))
+               return;
+       }
+    }
+    R->h->selection_wait = Sel_none;   /* don't loop in rxvt_selection_paste() */
+    D_SELECT((stderr, "rxvt_selection_request: pasting CUT_BUFFER0"));
+    rxvt_selection_paste(aR_ Xroot, XA_CUT_BUFFER0, False);
+}
+
+/* INTPROTO */
+int
+rxvt_selection_request_other(pR_ Atom target, int selnum)
+{
+    Atom            sel;
+#ifdef DEBUG_SELECT
+    char           *debug_xa_names[] = { "PRIMARY", "SECONDARY", "CLIPBOARD" };
+#endif
+
+    R->h->selection_type |= selnum;
+    if (selnum == Sel_Primary)
+       sel = XA_PRIMARY;
+    else if (selnum == Sel_Secondary)
+       sel = XA_SECONDARY;
+    else
+       sel = R->h->xa[XA_CLIPBOARD];
+    if (XGetSelectionOwner(R->Xdisplay, sel) != None) {
+       D_SELECT((stderr, "rxvt_selection_request_other: pasting %s", debug_xa_names[selnum]));
+       XConvertSelection(R->Xdisplay, sel, target, R->h->xa[XA_VT_SELECTION],
+                         R->TermWin.vt, R->h->selection_request_time);
+       return 1;
+    }
+    return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Clear all selected text
+ * EXT: SelectionClear
+ */
+/* EXTPROTO */
+void
+rxvt_selection_clear(pR)
+{
+    D_SELECT((stderr, "rxvt_selection_clear()"));
+
+    R->h->want_refresh = 1;
+    if (R->selection.text)
+       free(R->selection.text);
+    R->selection.text = NULL;
+    R->selection.len = 0;
+    CLEAR_SELECTION(R);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Copy a selection into the cut buffer
+ * EXT: button 1 or 3 release
+ */
+/* EXTPROTO */
+void
+rxvt_selection_make(pR_ Time tm)
+{
+    int             i, col, end_col, row, end_row;
+    unsigned char  *new_selection_text;
+    char           *str;
+    text_t         *t;
+#ifdef ACS_ASCII
+    rend_t         *re;
+#endif
+
+    D_SELECT((stderr, "rxvt_selection_make(): R->selection.op=%d, R->selection.clicks=%d", R->selection.op, R->selection.clicks));
+    switch (R->selection.op) {
+    case SELECTION_CONT:
+       break;
+    case SELECTION_INIT:
+       CLEAR_SELECTION(R);
+    /* FALLTHROUGH */
+    case SELECTION_BEGIN:
+       R->selection.op = SELECTION_DONE;
+    /* FALLTHROUGH */
+    default:
+       return;
+    }
+    R->selection.op = SELECTION_DONE;
+
+    if (R->selection.clicks == 4)
+       return;                 /* nothing selected, go away */
+
+    i = (R->selection.end.row - R->selection.beg.row + 1) * (R->TermWin.ncol + 1) + 1;
+    str = (char *)rxvt_malloc(i * MB_CUR_MAX + 1);
+
+    new_selection_text = (unsigned char *)str;
+
+    col = R->selection.beg.col;
+    MAX_IT(col, 0);
+    row = R->selection.beg.row + R->TermWin.saveLines;
+    end_row = R->selection.end.row + R->TermWin.saveLines;
+
+    for (; row <= end_row; row++, col = 0)
+      {
+       t = &(R->screen.text[row][col]);
+
+        end_col = R->screen.tlen[row];
+
+        if (end_col == -1)
+         end_col = R->TermWin.ncol;
+
+        if (row == end_row)
+          MIN_IT (end_col, R->selection.end.col);
+
+       for (; col < end_col; col++)
+          if (*t == NOCHAR)
+            t++;
+          else
+            {
+              int len = wctomb (str, *t++);
+              if (len > 0)
+                str += len;
+            }
+
+       if (R->screen.tlen[row] != -1 && row != end_row)
+           *str++ = '\n';
+      }
+
+#ifndef NO_OLD_SELECTION
+    if (R->selection_style == OLD_SELECT)
+       if (end_col == R->TermWin.ncol)
+           *str++ = '\n';
+#endif
+#ifndef NO_NEW_SELECTION
+    if (R->selection_style != OLD_SELECT)
+       if (end_col != R->selection.end.col)
+           *str++ = '\n';
+#endif
+    *str = '\0';
+
+    i = str - (char *)new_selection_text;
+    if (i == 0)
+      {
+       free (new_selection_text);
+       return;
+      }
+
+    // due to MB_MAX_CUR, selection wastage is usually high
+    if (str - (char *)new_selection_text > 1024)
+      new_selection_text = (unsigned char *)rxvt_realloc (new_selection_text, i + 1);
+
+    R->selection.len = i;
+    if (R->selection.text)
+       free (R->selection.text);
+
+    R->selection.text = new_selection_text;
+
+    XSetSelectionOwner(R->Xdisplay, XA_PRIMARY, R->TermWin.vt, tm);
+    if (XGetSelectionOwner(R->Xdisplay, XA_PRIMARY) != R->TermWin.vt)
+       rxvt_print_error("can't get primary selection");
+    XChangeProperty(R->Xdisplay, Xroot, XA_CUT_BUFFER0, XA_STRING, 8,
+                   PropModeReplace, R->selection.text, (int)R->selection.len);
+    R->h->selection_time = tm;
+    D_SELECT((stderr, "rxvt_selection_make(): R->selection.len=%d", R->selection.len));
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Mark or select text based upon number of clicks: 1, 2, or 3
+ * EXT: button 1 press
+ */
+/* EXTPROTO */
+void
+rxvt_selection_click(pR_ int clicks, int x, int y)
+{
+    D_SELECT((stderr, "rxvt_selection_click(%d, %d, %d)", clicks, x, y));
+
+    clicks = ((clicks - 1) % 3) + 1;
+    R->selection.clicks = clicks;      /* save clicks so extend will work */
+
+    rxvt_selection_start_colrow(aR_ Pixel2Col(x), Pixel2Row(y));
+    if (clicks == 2 || clicks == 3)
+       rxvt_selection_extend_colrow(aR_ R->selection.mark.col,
+                                    R->selection.mark.row
+                                    + R->TermWin.view_start,
+                                    0, /* button 3     */
+                                    1, /* button press */
+                                    0);        /* click change */
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Mark a selection at the specified col/row
+ */
+/* INTPROTO */
+void
+rxvt_selection_start_colrow(pR_ int col, int row)
+{
+    R->h->want_refresh = 1;
+    R->selection.mark.col = col;
+    R->selection.mark.row = row - R->TermWin.view_start;
+    MAX_IT(R->selection.mark.row, -(int32_t)R->TermWin.nscrolled);
+    MIN_IT(R->selection.mark.row, (int32_t)R->TermWin.nrow - 1);
+    MAX_IT(R->selection.mark.col, 0);
+    MIN_IT(R->selection.mark.col, (int32_t)R->TermWin.ncol - 1);
+
+    if (R->selection.op) {     /* clear the old selection */
+       R->selection.beg.row = R->selection.end.row = R->selection.mark.row;
+       R->selection.beg.col = R->selection.end.col = R->selection.mark.col;
+    }
+    R->selection.op = SELECTION_INIT;
+    R->selection.screen = R->h->current_screen;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Word select: select text for 2 clicks
+ * We now only find out the boundary in one direction
+ */
+
+/* what do we want: spaces/tabs are delimiters or cutchars or non-cutchars */
+#define DELIMIT_TEXT(x) \
+    (((x) == ' ' || (x) == '\t') ? 2 : (STRCHR(R->h->rs[Rs_cutchars], (x)) != NULL))
+#ifdef MULTICHAR_SET
+# define DELIMIT_REND(x)       (((x) & RS_multiMask) ? 1 : 0)
+#else
+# define DELIMIT_REND(x)       1
+#endif
+
+/* INTPROTO */
+void
+rxvt_selection_delimit_word(pR_ enum page_dirn dirn, const row_col_t *mark, row_col_t *ret)
+{
+    int             col, row, dirnadd, tcol, trow, w1, w2;
+    row_col_t       bound;
+    text_t         *stp;
+    rend_t         *srp;
+
+    if (dirn == UP) {
+       bound.row = R->TermWin.saveLines - R->TermWin.nscrolled - 1;
+       bound.col = 0;
+       dirnadd = -1;
+    } else {
+       bound.row = R->TermWin.saveLines + R->TermWin.nrow;
+       bound.col = R->TermWin.ncol - 1;
+       dirnadd = 1;
+    }
+    row = mark->row + R->TermWin.saveLines;
+    col = mark->col;
+    MAX_IT(col, 0);
+/* find the edge of a word */
+    stp = &(R->screen.text[row][col]);
+    w1 = DELIMIT_TEXT(*stp);
+
+    if (R->selection_style != NEW_SELECT) {
+       if (w1 == 1) {
+           stp += dirnadd;
+           if (DELIMIT_TEXT(*stp) == 1)
+               goto Old_Word_Selection_You_Die;
+           col += dirnadd;
+       }
+       w1 = 0;
+    }
+    srp = (&R->screen.rend[row][col]);
+    w2 = DELIMIT_REND(*srp);
+
+    for (;;) {
+       for (; col != bound.col; col += dirnadd) {
+           stp += dirnadd;
+           if (DELIMIT_TEXT(*stp) != w1)
+               break;
+           srp += dirnadd;
+           if (DELIMIT_REND(*srp) != w2)
+               break;
+       }
+       if ((col == bound.col) && (row != bound.row)) {
+           if (R->screen.tlen[(row - (dirn == UP ? 1 : 0))] == -1) {
+               trow = row + dirnadd;
+               tcol = dirn == UP ? R->TermWin.ncol - 1 : 0;
+               if (R->screen.text[trow] == NULL)
+                   break;
+               stp = &(R->screen.text[trow][tcol]);
+               srp = &(R->screen.rend[trow][tcol]);
+               if (DELIMIT_TEXT(*stp) != w1 || DELIMIT_REND(*srp) != w2)
+                   break;
+               row = trow;
+               col = tcol;
+               continue;
+           }
+       }
+       break;
+    }
+  Old_Word_Selection_You_Die:
+    D_SELECT((stderr, "rxvt_selection_delimit_word(%s,...) @ (r:%3d, c:%3d) has boundary (r:%3d, c:%3d)", (dirn == UP ? "up    " : "down"), mark->row, mark->col, row - R->TermWin.saveLines, col));
+
+    if (dirn == DN)
+       col++;                  /* put us on one past the end */
+
+/* Poke the values back in */
+    ret->row = row - R->TermWin.saveLines;
+    ret->col = col;
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Extend the selection to the specified x/y pixel location
+ * EXT: button 3 press; button 1 or 3 drag
+ * flag == 0 ==> button 1
+ * flag == 1 ==> button 3 press
+ * flag == 2 ==> button 3 motion
+ */
+/* EXTPROTO */
+void
+rxvt_selection_extend(pR_ int x, int y, int flag)
+{
+    int             col, row;
+
+    col = Pixel2Col(x);
+    row = Pixel2Row(y);
+    MAX_IT(row, 0);
+    MIN_IT(row, (int)R->TermWin.nrow - 1);
+    MAX_IT(col, 0);
+    MIN_IT(col, (int)R->TermWin.ncol);
+#ifndef NO_NEW_SELECTION
+/*
+ * If we're selecting characters (single click) then we must check first
+ * if we are at the same place as the original mark.  If we are then
+ * select nothing.  Otherwise, if we're to the right of the mark, you have to
+ * be _past_ a character for it to be selected.
+ */
+    if (R->selection_style != OLD_SELECT) {
+       if (((R->selection.clicks % 3) == 1) && !flag
+           && (col == R->selection.mark.col
+               && (row == R->selection.mark.row + R->TermWin.view_start))) {
+           /* select nothing */
+           R->selection.beg.row = R->selection.end.row = 0;
+           R->selection.beg.col = R->selection.end.col = 0;
+           R->selection.clicks = 4;
+           R->h->want_refresh = 1;
+           D_SELECT((stderr, "rxvt_selection_extend() R->selection.clicks = 4"));
+           return;
+       }
+    }
+#endif
+    if (R->selection.clicks == 4)
+       R->selection.clicks = 1;
+    rxvt_selection_extend_colrow(aR_ col, row, !!flag, /* ? button 3      */
+                                flag == 1 ? 1 : 0,     /* ? button press  */
+                                0);    /* no click change */
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Extend the selection to the specified col/row
+ */
+/* INTPROTO */
+void
+rxvt_selection_extend_colrow(pR_ int32_t col, int32_t row, int button3, int buttonpress, int clickchange)
+{
+    int16_t         ncol = R->TermWin.ncol;
+    int             end_col;
+    row_col_t       pos;
+    enum {
+       LEFT, RIGHT
+    } closeto = RIGHT;
+
+    D_SELECT((stderr, "rxvt_selection_extend_colrow(c:%d, r:%d, %d, %d) clicks:%d, op:%d", col, row, button3, buttonpress, R->selection.clicks, R->selection.op));
+    D_SELECT((stderr, "rxvt_selection_extend_colrow() ENT  b:(r:%d,c:%d) m:(r:%d,c:%d), e:(r:%d,c:%d)", R->selection.beg.row, R->selection.beg.col, R->selection.mark.row, R->selection.mark.col, R->selection.end.row, R->selection.end.col));
+
+    R->h->want_refresh = 1;
+    switch (R->selection.op) {
+    case SELECTION_INIT:
+       CLEAR_SELECTION(R);
+       R->selection.op = SELECTION_BEGIN;
+    /* FALLTHROUGH */
+    case SELECTION_BEGIN:
+       if (row != R->selection.mark.row || col != R->selection.mark.col
+           || (!button3 && buttonpress))
+           R->selection.op = SELECTION_CONT;
+       break;
+    case SELECTION_DONE:
+       R->selection.op = SELECTION_CONT;
+    /* FALLTHROUGH */
+    case SELECTION_CONT:
+       break;
+    case SELECTION_CLEAR:
+       rxvt_selection_start_colrow(aR_ col, row);
+    /* FALLTHROUGH */
+    default:
+       return;
+    }
+    if (R->selection.beg.col == R->selection.end.col
+       && R->selection.beg.col != R->selection.mark.col
+       && R->selection.beg.row == R->selection.end.row
+       && R->selection.beg.row != R->selection.mark.row) {
+       R->selection.beg.col = R->selection.end.col = R->selection.mark.col;
+       R->selection.beg.row = R->selection.end.row = R->selection.mark.row;
+       D_SELECT((stderr, "rxvt_selection_extend_colrow() ENT2 b:(r:%d,c:%d) m:(r:%d,c:%d), e:(r:%d,c:%d)", R->selection.beg.row, R->selection.beg.col, R->selection.mark.row, R->selection.mark.col, R->selection.end.row, R->selection.end.col));
+    }
+
+    pos.col = col;
+    pos.row = row;
+
+    pos.row -= R->TermWin.view_start;  /* adjust for scroll */
+
+#ifndef NO_OLD_SELECTION
+/*
+ * This mimics some of the selection behaviour of version 2.20 and before.
+ * There are no ``selection modes'', button3 is always character extension.
+ * Note: button3 drag is always available, c.f. v2.20
+ * Selection always terminates (left or right as appropriate) at the mark.
+ */
+    if (R->selection_style == OLD_SELECT) {
+       if (R->selection.clicks == 1 || button3) {
+           if (R->h->hate_those_clicks) {
+               R->h->hate_those_clicks = 0;
+               if (R->selection.clicks == 1) {
+                   R->selection.beg.row = R->selection.mark.row;
+                   R->selection.beg.col = R->selection.mark.col;
+               } else {
+                   R->selection.mark.row = R->selection.beg.row;
+                   R->selection.mark.col = R->selection.beg.col;
+               }
+           }
+           if (ROWCOL_IS_BEFORE(pos, R->selection.mark)) {
+               R->selection.end.row = R->selection.mark.row;
+               R->selection.end.col = R->selection.mark.col + 1;
+               R->selection.beg.row = pos.row;
+               R->selection.beg.col = pos.col;
+           } else {
+               R->selection.beg.row = R->selection.mark.row;
+               R->selection.beg.col = R->selection.mark.col;
+               R->selection.end.row = pos.row;
+               R->selection.end.col = pos.col + 1;
+           }
+       } else if (R->selection.clicks == 2) {
+           rxvt_selection_delimit_word(aR_ UP, &(R->selection.mark),
+                                       &(R->selection.beg));
+           rxvt_selection_delimit_word(aR_ DN, &(R->selection.mark),
+                                       &(R->selection.end));
+           R->h->hate_those_clicks = 1;
+       } else if (R->selection.clicks == 3) {
+           R->selection.beg.row = R->selection.end.row = R->selection.mark.row;
+           R->selection.beg.col = 0;
+           R->selection.end.col = ncol;
+           R->h->hate_those_clicks = 1;
+       }
+       D_SELECT((stderr, "rxvt_selection_extend_colrow() EXIT b:(r:%d,c:%d) m:(r:%d,c:%d), e:(r:%d,c:%d)", R->selection.beg.row, R->selection.beg.col, R->selection.mark.row, R->selection.mark.col, R->selection.end.row, R->selection.end.col));
+       return;
+    }
+#endif                         /* ! NO_OLD_SELECTION */
+#ifndef NO_NEW_SELECTION
+/* selection_style must not be OLD_SELECT to get here */
+/*
+ * This is mainly xterm style selection with a couple of differences, mainly
+ * in the way button3 drag extension works.
+ * We're either doing: button1 drag; button3 press; or button3 drag
+ *  a) button1 drag : select around a midpoint/word/line - that point/word/line
+ *     is always at the left/right edge of the R->selection.
+ *  b) button3 press: extend/contract character/word/line at whichever edge of
+ *     the selection we are closest to.
+ *  c) button3 drag : extend/contract character/word/line - we select around
+ *     a point/word/line which is either the start or end of the selection
+ *     and it was decided by whichever point/word/line was `fixed' at the
+ *     time of the most recent button3 press
+ */
+    if (button3 && buttonpress) {      /* button3 press */
+       /*
+        * first determine which edge of the selection we are closest to
+        */
+       if (ROWCOL_IS_BEFORE(pos, R->selection.beg)
+           || (!ROWCOL_IS_AFTER(pos, R->selection.end)
+               && (((pos.col - R->selection.beg.col)
+                    + ((pos.row - R->selection.beg.row) * ncol))
+                   < ((R->selection.end.col - pos.col)
+                      + ((R->selection.end.row - pos.row) * ncol)))))
+            closeto = LEFT;
+       if (closeto == LEFT) {
+           R->selection.beg.row = pos.row;
+           R->selection.beg.col = pos.col;
+           R->selection.mark.row = R->selection.end.row;
+           R->selection.mark.col = R->selection.end.col
+                                   - (R->selection.clicks == 2);
+       } else {
+           R->selection.end.row = pos.row;
+           R->selection.end.col = pos.col;
+           R->selection.mark.row = R->selection.beg.row;
+           R->selection.mark.col = R->selection.beg.col;
+       }
+    } else {                   /* button1 drag or button3 drag */
+       if (ROWCOL_IS_AFTER(R->selection.mark, pos)) {
+           if ((R->selection.mark.row == R->selection.end.row)
+               && (R->selection.mark.col == R->selection.end.col)
+               && clickchange && R->selection.clicks == 2)
+               R->selection.mark.col--;
+           R->selection.beg.row = pos.row;
+           R->selection.beg.col = pos.col;
+           R->selection.end.row = R->selection.mark.row;
+           R->selection.end.col = R->selection.mark.col
+                                  + (R->selection.clicks == 2);
+       } else {
+           R->selection.beg.row = R->selection.mark.row;
+           R->selection.beg.col = R->selection.mark.col;
+           R->selection.end.row = pos.row;
+           R->selection.end.col = pos.col;
+       }
+    }
+
+    if (R->selection.clicks == 1) {
+       end_col = R->screen.tlen[R->selection.beg.row + R->TermWin.saveLines];
+       if (end_col != -1 && R->selection.beg.col > end_col) {
+#if 1
+           R->selection.beg.col = ncol;
+#else
+           if (R->selection.beg.row != R->selection.end.row)
+               R->selection.beg.col = ncol;
+           else
+               R->selection.beg.col = R->selection.mark.col;
+#endif
+       }
+       end_col = R->screen.tlen[R->selection.end.row + R->TermWin.saveLines];
+       if (end_col != -1 && R->selection.end.col > end_col)
+           R->selection.end.col = ncol;
+
+    } else if (R->selection.clicks == 2) {
+       if (ROWCOL_IS_AFTER(R->selection.end, R->selection.beg))
+           R->selection.end.col--;
+       rxvt_selection_delimit_word(aR_ UP, &(R->selection.beg),
+                                   &(R->selection.beg));
+       rxvt_selection_delimit_word(aR_ DN, &(R->selection.end),
+                                   &(R->selection.end));
+    } else if (R->selection.clicks == 3) {
+#ifndef NO_FRILLS
+       if ((R->Options & Opt_tripleclickwords)) {
+           int             end_row;
+
+           rxvt_selection_delimit_word(aR_ UP, &(R->selection.beg),
+                                       &(R->selection.beg));
+           end_row = R->screen.tlen[R->selection.mark.row
+                                    + R->TermWin.saveLines];
+           for (end_row = R->selection.mark.row; end_row < R->TermWin.nrow;
+                end_row++) {
+               end_col = R->screen.tlen[end_row + R->TermWin.saveLines];
+               if (end_col != -1) {
+                   R->selection.end.row = end_row;
+                   R->selection.end.col = end_col;
+                   rxvt_selection_remove_trailing_spaces(aR);
+                   break;
+               }
+           }
+       } else
+#endif
+       {
+           if (ROWCOL_IS_AFTER(R->selection.mark, R->selection.beg))
+               R->selection.mark.col++;
+           R->selection.beg.col = 0;
+           R->selection.end.col = ncol;
+       }
+    }
+    if (button3 && buttonpress) {      /* mark may need to be changed */
+       if (closeto == LEFT) {
+           R->selection.mark.row = R->selection.end.row;
+           R->selection.mark.col = R->selection.end.col
+                                   - (R->selection.clicks == 2);
+       } else {
+           R->selection.mark.row = R->selection.beg.row;
+           R->selection.mark.col = R->selection.beg.col;
+       }
+    }
+    D_SELECT((stderr, "rxvt_selection_extend_colrow() EXIT b:(r:%d,c:%d) m:(r:%d,c:%d), e:(r:%d,c:%d)", R->selection.beg.row, R->selection.beg.col, R->selection.mark.row, R->selection.mark.col, R->selection.end.row, R->selection.end.col));
+#endif                         /* ! NO_NEW_SELECTION */
+}
+
+#ifndef NO_FRILLS
+/* INTPROTO */
+void
+rxvt_selection_remove_trailing_spaces(pR)
+{
+    int32_t         end_col, end_row;
+    text_t         *stp; 
+
+    end_col = R->selection.end.col;
+    end_row = R->selection.end.row;
+    for ( ; end_row >= R->selection.beg.row; ) {
+       stp = R->screen.text[end_row + R->TermWin.saveLines];
+       while (--end_col >= 0) {
+           if (stp[end_col] != ' ' && stp[end_col] != '\t')
+               break;
+       }
+       if (end_col >= 0
+           || R->screen.tlen[end_row - 1 + R->TermWin.saveLines] != -1) {
+           R->selection.end.col = end_col + 1;
+           R->selection.end.row = end_row;
+           break;
+       }
+       end_row--;
+       end_col = R->TermWin.ncol;
+    }
+    if (R->selection.mark.row > R->selection.end.row) {
+       R->selection.mark.row = R->selection.end.row;
+       R->selection.mark.col = R->selection.end.col;
+    } else if (R->selection.mark.row == R->selection.end.row
+              && R->selection.mark.col > R->selection.end.col)
+       R->selection.mark.col = R->selection.end.col;
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Double click on button 3 when already selected
+ * EXT: button 3 double click
+ */
+/* EXTPROTO */
+void
+rxvt_selection_rotate(pR_ int x, int y)
+{
+    R->selection.clicks = R->selection.clicks % 3 + 1;
+    rxvt_selection_extend_colrow(aR_ Pixel2Col(x), Pixel2Row(y), 1, 0, 1);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * On some systems, the Atom typedef is 64 bits wide.  We need to have a type
+ * that is exactly 32 bits wide, because a format of 64 is not allowed by
+ * the X11 protocol.
+ */
+typedef CARD32  Atom32;
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Respond to a request for our current selection
+ * EXT: SelectionRequest
+ */
+/* EXTPROTO */
+void
+rxvt_selection_send(pR_ const XSelectionRequestEvent *rq)
+{
+    XSelectionEvent ev;
+#ifdef USE_XIM
+    Atom32          target_list[4];
+#else
+    Atom32          target_list[3];
+#endif
+    Atom            target;
+    XTextProperty   ct;
+    XICCEncodingStyle style;
+    char           *cl[2], dummy[1];
+
+    ev.type = SelectionNotify;
+    ev.property = None;
+    ev.display = rq->display;
+    ev.requestor = rq->requestor;
+    ev.selection = rq->selection;
+    ev.target = rq->target;
+    ev.time = rq->time;
+
+    if (rq->target == R->h->xa[XA_TARGETS]) {
+       target_list[0] = (Atom32) R->h->xa[XA_TARGETS];
+       target_list[1] = (Atom32) XA_STRING;
+       target_list[2] = (Atom32) R->h->xa[XA_TEXT];
+#ifdef USE_XIM
+       target_list[3] = (Atom32) R->h->xa[XA_COMPOUND_TEXT];
+#endif
+       XChangeProperty(R->Xdisplay, rq->requestor, rq->property, XA_ATOM,
+                       (8 * sizeof(target_list[0])), PropModeReplace,
+                       (unsigned char *)target_list,
+                       (sizeof(target_list) / sizeof(target_list[0])));
+       ev.property = rq->property;
+    } else if (rq->target == R->h->xa[XA_MULTIPLE]) {
+       /* TODO: Handle MULTIPLE */
+    } else if (rq->target == R->h->xa[XA_TIMESTAMP] && R->selection.text) {
+       XChangeProperty(R->Xdisplay, rq->requestor, rq->property, XA_INTEGER,
+                       (8 * sizeof(Time)), PropModeReplace,
+                       (unsigned char *)&R->h->selection_time, 1);
+       ev.property = rq->property;
+    } else if (rq->target == XA_STRING
+              || rq->target == R->h->xa[XA_COMPOUND_TEXT]
+              || rq->target == R->h->xa[XA_TEXT]) {
+#ifdef USE_XIM
+       short           freect = 0;
+#endif
+       int             selectlen;
+
+#ifdef USE_XIM
+       if (rq->target != XA_STRING) {
+           target = R->h->xa[XA_COMPOUND_TEXT];
+           style = (rq->target == R->h->xa[XA_COMPOUND_TEXT])
+                   ? XCompoundTextStyle : XStdICCTextStyle;
+       } else
+#endif
+       {
+           target = XA_STRING;
+           style = XStringStyle;
+       }
+       if (R->selection.text) {
+           cl[0] = (char *)R->selection.text;
+           selectlen = R->selection.len;
+       } else {
+           cl[0] = dummy;
+           *dummy = '\0';
+           selectlen = 0;
+       }
+#ifdef USE_XIM
+       if (XmbTextListToTextProperty(R->Xdisplay, cl, 1, style, &ct)
+           == Success)         /* if we failed to convert then send it raw */
+           freect = 1;
+       else
+#endif
+       {
+           ct.value = (unsigned char *)cl[0];
+           ct.nitems = selectlen;
+       }
+       XChangeProperty(R->Xdisplay, rq->requestor, rq->property,
+                       target, 8, PropModeReplace,
+                       ct.value, (int)ct.nitems);
+       ev.property = rq->property;
+#ifdef USE_XIM
+       if (freect)
+           XFree(ct.value);
+#endif
+    }
+    XSendEvent(R->Xdisplay, rq->requestor, False, 0L, (XEvent *)&ev);
+}
+\f
+/* ------------------------------------------------------------------------- *
+ *                              MOUSE ROUTINES                               *
+ * ------------------------------------------------------------------------- */
+
+/*
+ * return col/row values corresponding to x/y pixel values
+ */
+/* EXTPROTO */
+void
+rxvt_pixel_position(pR_ int *x, int *y)
+{
+    *x = Pixel2Col(*x);
+/* MAX_IT(*x, 0); MIN_IT(*x, (int)R->TermWin.ncol - 1); */
+    *y = Pixel2Row(*y);
+/* MAX_IT(*y, 0); MIN_IT(*y, (int)R->TermWin.nrow - 1); */
+}
+/* ------------------------------------------------------------------------- */
+#ifdef USE_XIM
+/* EXTPROTO */
+void
+rxvt_setPosition(pR_ XPoint *pos)
+{
+    XWindowAttributes xwa;
+
+    XGetWindowAttributes(R->Xdisplay, R->TermWin.vt, &xwa);
+    pos->x = Col2Pixel(R->screen.cur.col) + xwa.x;
+    pos->y = Height2Pixel((R->screen.cur.row + 1)) + xwa.y
+            - R->TermWin.lineSpace;
+}
+#endif
+/* ------------------------------------------------------------------------- */
+\f
+/* ------------------------------------------------------------------------- *
+ *                              DEBUG ROUTINES                               *
+ * ------------------------------------------------------------------------- */
+#if 0
+/* INTPROTO */
+void
+rxvt_debug_colors(void)
+{
+    int             color;
+    const char     *name[] = {
+       "fg", "bg",
+       "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"
+    };
+
+    fprintf(stderr, "Color ( ");
+    if (R->h->rstyle & RS_RVid)
+       fprintf(stderr, "rvid ");
+    if (R->h->rstyle & RS_Bold)
+       fprintf(stderr, "bold ");
+    if (R->h->rstyle & RS_Blink)
+       fprintf(stderr, "blink ");
+    if (R->h->rstyle & RS_Uline)
+       fprintf(stderr, "uline ");
+    fprintf(stderr, "): ");
+
+    color = GET_FGCOLOR(R->h->rstyle);
+#ifndef NO_BRIGHTCOLOR
+    if (color >= minBrightCOLOR && color <= maxBrightCOLOR) {
+       color -= (minBrightCOLOR - minCOLOR);
+       fprintf(stderr, "bright ");
+    }
+#endif
+    fprintf(stderr, "%s on ", name[color]);
+
+    color = GET_BGCOLOR(R->h->rstyle);
+#ifndef NO_BRIGHTCOLOR
+    if (color >= minBrightCOLOR && color <= maxBrightCOLOR) {
+       color -= (minBrightCOLOR - minCOLOR);
+       fprintf(stderr, "bright ");
+    }
+#endif
+    fprintf(stderr, "%s\n", name[color]);
+}
+#endif
diff --git a/src/scrollbar-next.C b/src/scrollbar-next.C
new file mode 100644 (file)
index 0000000..6e2ae97
--- /dev/null
@@ -0,0 +1,289 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       scrollbar-next.c
+ *----------------------------------------------------------------------*
+ * $Id: scrollbar-next.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Copyright (c) 1997,1998 mj olesen <olesen@me.QueensU.CA>
+ * Copyright (c) 1998      Alfredo K. Kojima <kojima@windowmaker.org>
+ *                             - N*XTstep like scrollbars
+ * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "scrollbar-next.intpro"       /* PROTOS for internal routines */
+
+/*----------------------------------------------------------------------*/
+#if defined(NEXT_SCROLLBAR)
+
+#define n_stp_width    8
+#define n_stp_height   2
+const unsigned char n_stp_bits[] = { 0x55, 0xaa };
+
+/*
+ * N*XTSTEP like scrollbar - written by Alfredo K. Kojima
+ */
+#define SCROLLER_DIMPLE_WIDTH   6
+#define SCROLLER_DIMPLE_HEIGHT  6
+#define ARROW_WIDTH   13
+#define ARROW_HEIGHT  13
+
+const char     *const SCROLLER_DIMPLE[] = {
+    ".%###.",
+    "%#%%%%",
+    "#%%...",
+    "#%..  ",
+    "#%.   ",
+    ".%.  ."
+};
+const char     *const SCROLLER_ARROW_UP[] = {
+    ".............",
+    ".............",
+    "......%......",
+    "......#......",
+    ".....%#%.....",
+    ".....###.....",
+    "....%###%....",
+    "....#####....",
+    "...%#####%...",
+    "...#######...",
+    "..%#######%..",
+    ".............",
+    "............."
+};
+const char     *const SCROLLER_ARROW_DOWN[] = {
+    ".............",
+    ".............",
+    "..%#######%..",
+    "...#######...",
+    "...%#####%...",
+    "....#####....",
+    "....%###%....",
+    ".....###.....",
+    ".....%#%.....",
+    "......#......",
+    "......%......",
+    ".............",
+    "............."
+};
+const char     *const HI_SCROLLER_ARROW_UP[] = {
+    "             ",
+    "             ",
+    "      %      ",
+    "      %      ",
+    "     %%%     ",
+    "     %%%     ",
+    "    %%%%%    ",
+    "    %%%%%    ",
+    "   %%%%%%%   ",
+    "   %%%%%%%   ",
+    "  %%%%%%%%%  ",
+    "             ",
+    "             "
+};
+const char     *const HI_SCROLLER_ARROW_DOWN[] = {
+    "             ",
+    "             ",
+    "  %%%%%%%%%  ",
+    "   %%%%%%%   ",
+    "   %%%%%%%   ",
+    "    %%%%%    ",
+    "    %%%%%    ",
+    "     %%%     ",
+    "     %%%     ",
+    "      %      ",
+    "      %      ",
+    "             ",
+    "             "
+};
+
+/* INTPROTO */
+Pixmap
+rxvt_renderPixmap(pR_ const char *const *data, int width, int height)
+{
+    char            a;
+    int             x, y;
+    Pixmap          d;
+    GC              pointcolour;
+
+    d = XCreatePixmap(R->Xdisplay, R->scrollBar.win, width, height, XDEPTH);
+
+    for (y = 0; y < height; y++) {
+       for (x = 0; x < width; x++) {
+           if ((a = data[y][x]) == ' ' || a == 'w')
+               pointcolour = R->h->whiteGC;
+           else if (a == '.' || a == 'l')
+               pointcolour = R->h->grayGC;
+           else if (a == '%' || a == 'd')
+               pointcolour = R->h->darkGC;
+           else                /* if (a == '#' || a == 'b' || a) */
+               pointcolour = R->h->blackGC;
+           XDrawPoint(R->Xdisplay, d, pointcolour, x, y);
+       }
+    }
+    return d;
+}
+
+/* INTPROTO */
+void
+rxvt_init_scrollbar_stuff(pR)
+{
+    XGCValues       gcvalue;
+    XColor          xcol;
+    Pixmap          stipple;
+    unsigned long   light, dark;
+
+    gcvalue.graphics_exposures = False;
+
+    gcvalue.foreground = R->PixColors[Color_Black];
+    R->h->blackGC = XCreateGC(R->Xdisplay, R->scrollBar.win,
+                             GCForeground | GCGraphicsExposures, &gcvalue);
+
+    gcvalue.foreground = R->PixColors[Color_White];
+    R->h->whiteGC = XCreateGC(R->Xdisplay, R->scrollBar.win,
+                             GCForeground | GCGraphicsExposures, &gcvalue);
+
+    xcol.red = 0xaeba;
+    xcol.green = 0xaaaa;
+    xcol.blue = 0xaeba;
+    if (!rxvt_rXAllocColor(aR_ &xcol, "light gray"))
+       xcol.pixel = R->PixColors[Color_AntiqueWhite];
+    light = gcvalue.foreground = xcol.pixel;
+    R->h->grayGC = XCreateGC(R->Xdisplay, R->scrollBar.win,
+                            GCForeground | GCGraphicsExposures, &gcvalue);
+
+    xcol.red = 0x51aa;
+    xcol.green = 0x5555;
+    xcol.blue = 0x5144;
+    if (!rxvt_rXAllocColor(aR_ &xcol, "dark gray"))
+       xcol.pixel = R->PixColors[Color_Grey25];
+    dark = gcvalue.foreground = xcol.pixel;
+    R->h->darkGC = XCreateGC(R->Xdisplay, R->scrollBar.win,
+                            GCForeground | GCGraphicsExposures, &gcvalue);
+
+    stipple = XCreateBitmapFromData(R->Xdisplay, R->scrollBar.win,
+                                   (char *)n_stp_bits, n_stp_width,
+                                   n_stp_height);
+
+    gcvalue.foreground = dark;
+    gcvalue.background = light;
+    gcvalue.fill_style = FillOpaqueStippled;
+    gcvalue.stipple = stipple;
+
+/*    XSetWindowBackground(R->Xdisplay, R->scrollBar.win, R->PixColors[Color_Red]); */
+
+    R->h->stippleGC = XCreateGC(R->Xdisplay, R->scrollBar.win,
+                               GCForeground | GCBackground | GCStipple
+                               | GCFillStyle | GCGraphicsExposures, &gcvalue);
+
+    R->h->dimple = rxvt_renderPixmap(aR_ SCROLLER_DIMPLE, SCROLLER_DIMPLE_WIDTH,
+                                    SCROLLER_DIMPLE_HEIGHT);
+
+    R->h->upArrow = rxvt_renderPixmap(aR_ SCROLLER_ARROW_UP, ARROW_WIDTH,
+                                     ARROW_HEIGHT);
+    R->h->downArrow = rxvt_renderPixmap(aR_ SCROLLER_ARROW_DOWN, ARROW_WIDTH,
+                                       ARROW_HEIGHT);
+    R->h->upArrowHi = rxvt_renderPixmap(aR_ HI_SCROLLER_ARROW_UP, ARROW_WIDTH,
+                                       ARROW_HEIGHT);
+    R->h->downArrowHi = rxvt_renderPixmap(aR_ HI_SCROLLER_ARROW_DOWN,
+                                         ARROW_WIDTH, ARROW_HEIGHT);
+}
+
+/* Draw bevel & arrows */
+/* INTPROTO */
+void
+rxvt_drawBevel(pR_ Drawable d, int x1, int y1, int w, int h)
+{
+    int             x2, y2;
+
+    x2 = x1 + w - 1;           /* right  point */
+    y2 = y1 + h - 1;           /* bottom point */
+/* white top and left */
+    XDrawLine(R->Xdisplay, d, R->h->whiteGC, x1, y1, x2, y1);
+    XDrawLine(R->Xdisplay, d, R->h->whiteGC, x1, y1, x1, y2);
+/* black bottom and right */
+    XDrawLine(R->Xdisplay, d, R->h->blackGC, x1, y2, x2, y2);
+    XDrawLine(R->Xdisplay, d, R->h->blackGC, x2, y1, x2, y2);
+/* dark inside bottom and right */
+    x1++, y1++, x2--, y2--;    /* move in one point */
+    XDrawLine(R->Xdisplay, d, R->h->darkGC, x1, y2, x2, y2);
+    XDrawLine(R->Xdisplay, d, R->h->darkGC, x2, y1, x2, y2);
+}
+
+/* EXTPROTO */
+int
+rxvt_scrollbar_show_next(pR_ int update, int last_top, int last_bot, int scrollbar_len)
+{
+    int             height = R->scrollBar.end + SB_BUTTON_TOTAL_HEIGHT + SB_PADDING;
+    Drawable        s;
+
+    if ((R->scrollBar.init & R_SB_NEXT) == 0) {
+       R->scrollBar.init |= R_SB_NEXT;
+       rxvt_init_scrollbar_stuff(aR);
+    }
+
+    if (R->TermWin.nscrolled == 0 || !update) {
+       XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->grayGC, 0, 0,
+                      SB_WIDTH_NEXT + 1, height);
+       XDrawRectangle(R->Xdisplay, R->scrollBar.win, R->h->blackGC, 0,
+                      -SB_BORDER_WIDTH, SB_WIDTH_NEXT,
+                      height + SB_BORDER_WIDTH);
+       XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->stippleGC,
+                      SB_LEFT_PADDING, 0, SB_BUTTON_WIDTH, height);
+    }
+    if (R->TermWin.nscrolled) {
+       if (last_top < R->scrollBar.top || !update)
+           XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->stippleGC,
+                          SB_LEFT_PADDING, SB_PADDING + last_top,
+                          SB_BUTTON_WIDTH, R->scrollBar.top - last_top);
+       if (R->scrollBar.bot < last_bot || !update)
+           XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->stippleGC,
+                          SB_LEFT_PADDING, R->scrollBar.bot + SB_PADDING,
+                          SB_BUTTON_WIDTH, (last_bot - R->scrollBar.bot));
+       XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->grayGC,
+                      SB_LEFT_PADDING, R->scrollBar.top + SB_PADDING,
+                      SB_BUTTON_WIDTH, scrollbar_len);
+       XCopyArea(R->Xdisplay, R->h->dimple, R->scrollBar.win, R->h->whiteGC, 0, 0,
+                 SCROLLER_DIMPLE_WIDTH, SCROLLER_DIMPLE_HEIGHT,
+                 (SB_WIDTH_NEXT - SCROLLER_DIMPLE_WIDTH) / 2,
+                 R->scrollBar.top + SB_BEVEL_WIDTH_UPPER_LEFT +
+                 (scrollbar_len - SCROLLER_DIMPLE_HEIGHT) / 2);
+
+       rxvt_drawBevel(aR_ R->scrollBar.win, SB_BUTTON_BEVEL_X,
+                      R->scrollBar.top + SB_PADDING, SB_BUTTON_WIDTH,
+                      scrollbar_len);
+       rxvt_drawBevel(aR_ R->scrollBar.win, SB_BUTTON_BEVEL_X,
+                      height - SB_BUTTON_BOTH_HEIGHT, SB_BUTTON_WIDTH,
+                      SB_BUTTON_HEIGHT);
+       rxvt_drawBevel(aR_ R->scrollBar.win, SB_BUTTON_BEVEL_X,
+                      height - SB_BUTTON_SINGLE_HEIGHT, SB_BUTTON_WIDTH,
+                      SB_BUTTON_HEIGHT);
+
+       s = (scrollbar_isUp()) ? R->h->upArrowHi : R->h->upArrow;
+       XCopyArea(R->Xdisplay, s, R->scrollBar.win, R->h->whiteGC, 0, 0,
+                 ARROW_WIDTH, ARROW_HEIGHT, SB_BUTTON_FACE_X,
+                 height - SB_BUTTON_BOTH_HEIGHT + SB_BEVEL_WIDTH_UPPER_LEFT);
+
+       s = (scrollbar_isDn()) ? R->h->downArrowHi : R->h->downArrow;
+       XCopyArea(R->Xdisplay, s, R->scrollBar.win, R->h->whiteGC, 0, 0,
+                 ARROW_WIDTH, ARROW_HEIGHT, SB_BUTTON_FACE_X,
+                 height - SB_BUTTON_SINGLE_HEIGHT + SB_BEVEL_WIDTH_UPPER_LEFT);
+    }
+    return 1;
+}
+#endif                         /* NEXT_SCROLLBAR */
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/scrollbar-rxvt.C b/src/scrollbar-rxvt.C
new file mode 100644 (file)
index 0000000..b91e80c
--- /dev/null
@@ -0,0 +1,188 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       scrollbar-rxvt.c
+ *----------------------------------------------------------------------*
+ * $Id: scrollbar-rxvt.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Copyright (c) 1997,1998 mj olesen <olesen@me.QueensU.CA>
+ * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "scrollbar-rxvt.intpro"       /* PROTOS for internal routines */
+
+/*----------------------------------------------------------------------*/
+#if defined(RXVT_SCROLLBAR)
+
+/* draw triangular button with a shadow of SHADOW (1 or 2) pixels */
+/* INTPROTO */
+void
+rxvt_Draw_button(pR_ int x, int y, int state, int dirn)
+{
+    unsigned int    sz, sz2;
+    XPoint          pt[3];
+    GC              top, bot;
+
+    sz = R->scrollBar.width;
+    sz2 = sz / 2;
+    switch (state) {
+    case +1:
+       top = R->h->topShadowGC;
+       bot = R->h->botShadowGC;
+       break;
+    case -1:
+       top = R->h->botShadowGC;
+       bot = R->h->topShadowGC;
+       break;
+    default:
+       top = bot = R->h->scrollbarGC;
+       break;
+    }
+
+/* fill triangle */
+    pt[0].x = x;
+    pt[1].x = x + sz - 1;
+    pt[2].x = x + sz2;
+    if (dirn == UP) {
+       pt[0].y = pt[1].y = y + sz - 1;
+       pt[2].y = y;
+    } else {
+       pt[0].y = pt[1].y = y;
+       pt[2].y = y + sz - 1;
+    }
+    XFillPolygon(R->Xdisplay, R->scrollBar.win, R->h->scrollbarGC,
+                pt, 3, Convex, CoordModeOrigin);
+
+/* draw base */
+    XDrawLine(R->Xdisplay, R->scrollBar.win, (dirn == UP ? bot : top),
+             pt[0].x, pt[0].y, pt[1].x, pt[1].y);
+
+/* draw shadow on left */
+    pt[1].x = x + sz2 - 1;
+    pt[1].y = y + (dirn == UP ? 0 : sz - 1);
+    XDrawLine(R->Xdisplay, R->scrollBar.win, top,
+             pt[0].x, pt[0].y, pt[1].x, pt[1].y);
+
+#if (SHADOW > 1)
+/* doubled */
+    pt[0].x++;
+    if (dirn == UP) {
+       pt[0].y--;
+       pt[1].y++;
+    } else {
+       pt[0].y++;
+       pt[1].y--;
+    }
+    XDrawLine(R->Xdisplay, R->scrollBar.win, top,
+             pt[0].x, pt[0].y, pt[1].x, pt[1].y);
+#endif
+/* draw shadow on right */
+    pt[1].x = x + sz - 1;
+/*  pt[2].x = x + sz2; */
+    pt[1].y = y + (dirn == UP ? sz - 1 : 0);
+    pt[2].y = y + (dirn == UP ? 0 : sz - 1);
+    XDrawLine(R->Xdisplay, R->scrollBar.win, bot,
+             pt[2].x, pt[2].y, pt[1].x, pt[1].y);
+#if (SHADOW > 1)
+/* doubled */
+    pt[1].x--;
+    if (dirn == UP) {
+       pt[2].y++;
+       pt[1].y--;
+    } else {
+       pt[2].y--;
+       pt[1].y++;
+    }
+    XDrawLine(R->Xdisplay, R->scrollBar.win, bot,
+             pt[2].x, pt[2].y, pt[1].x, pt[1].y);
+#endif
+}
+
+/* EXTPROTO */
+int
+rxvt_scrollbar_show_rxvt(pR_ int update __attribute__((unused)), int last_top, int last_bot, int scrollbar_len)
+{
+    int             sbshadow = R->sb_shadow;
+    int             sbwidth = (int)R->scrollBar.width;
+
+    if ((R->scrollBar.init & R_SB_RXVT) == 0) {
+       XGCValues       gcvalue;
+
+       R->scrollBar.init |= R_SB_RXVT;
+       gcvalue.foreground = R->PixColors[Color_trough];
+       if (sbshadow) {
+           XSetWindowBackground(R->Xdisplay, R->scrollBar.win,
+                                gcvalue.foreground);
+           XClearWindow(R->Xdisplay, R->scrollBar.win);
+       }
+    } else {
+/* instead of XClearWindow (R->Xdisplay, R->scrollBar.win); */
+       if (last_top < R->scrollBar.top)
+           XClearArea(R->Xdisplay, R->scrollBar.win,
+                      sbshadow, last_top,
+                      sbwidth, (R->scrollBar.top - last_top),
+                      False);
+
+       if (R->scrollBar.bot < last_bot)
+           XClearArea(R->Xdisplay, R->scrollBar.win,
+                      sbshadow, R->scrollBar.bot,
+                      sbwidth, (last_bot - R->scrollBar.bot),
+                      False);
+    }
+
+/* scrollbar slider */
+#ifdef SB_BORDER
+    {
+       int             xofs;
+
+       if (R->Options & Opt_scrollBar_right)
+           xofs = 0;
+       else
+           xofs = sbshadow ? sbwidth : sbwidth - 1;
+
+       XDrawLine(R->Xdisplay, R->scrollBar.win, R->h->botShadowGC,
+                 xofs, 0, xofs, R->scrollBar.end + sbwidth);
+    }
+#endif
+    XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->scrollbarGC,
+                  sbshadow, R->scrollBar.top, sbwidth,
+                  scrollbar_len);
+
+    if (sbshadow)
+       /* trough shadow */
+       rxvt_Draw_Shadow(R->Xdisplay, R->scrollBar.win,
+                        R->h->botShadowGC, R->h->topShadowGC,
+                        0, 0,
+                        sbwidth + 2 * sbshadow, /* scrollbar_TotalWidth() */
+                        R->scrollBar.end + (sbwidth + 1) + sbshadow);
+/* shadow for scrollbar slider */
+    rxvt_Draw_Shadow(R->Xdisplay, R->scrollBar.win,
+                    R->h->topShadowGC, R->h->botShadowGC,
+                    sbshadow, R->scrollBar.top, sbwidth,
+                    scrollbar_len);
+
+/*
+ * Redraw scrollbar arrows
+ */
+    rxvt_Draw_button(aR_ sbshadow, sbshadow,
+                    (scrollbar_isUp() ? -1 : +1), UP);
+    rxvt_Draw_button(aR_ sbshadow, (R->scrollBar.end + 1),
+                    (scrollbar_isDn() ? -1 : +1), DN);
+    return 1;
+}
+#endif                         /* RXVT_SCROLLBAR */
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/scrollbar-xterm.C b/src/scrollbar-xterm.C
new file mode 100644 (file)
index 0000000..d50654f
--- /dev/null
@@ -0,0 +1,86 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       scrollbar-xterm.c
+ *----------------------------------------------------------------------*
+ * $Id: scrollbar-xterm.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Copyright (c) 1997,1998 mj olesen <olesen@me.QueensU.CA>
+ * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "scrollbar-xterm.intpro"      /* PROTOS for internal routines */
+
+/*----------------------------------------------------------------------*/
+#if defined(XTERM_SCROLLBAR)
+
+#define x_stp_width    8
+#define x_stp_height   2
+const unsigned char x_stp_bits[] = { 0xff, 0xff };
+
+/* EXTPROTO */
+int
+rxvt_scrollbar_show_xterm(pR_ int update __attribute__((unused)), int last_top, int last_bot, int scrollbar_len)
+{
+    int             xsb = 0;
+    int             sbwidth = R->scrollBar.width - 1;
+
+    if ((R->scrollBar.init & R_SB_XTERM) == 0) {
+       XGCValues       gcvalue;
+
+       R->scrollBar.init |= R_SB_XTERM;
+       gcvalue.stipple = XCreateBitmapFromData(R->Xdisplay, R->scrollBar.win,
+                                               (char *)x_stp_bits, x_stp_width,
+                                               x_stp_height);
+       if (!gcvalue.stipple) {
+           rxvt_print_error("can't create bitmap");
+           exit(EXIT_FAILURE);
+       }
+       gcvalue.fill_style = FillOpaqueStippled;
+       gcvalue.foreground = R->PixColors[Color_fg];
+       gcvalue.background = R->PixColors[Color_bg];
+
+       R->h->xscrollbarGC = XCreateGC(R->Xdisplay, R->scrollBar.win,
+                                      GCForeground | GCBackground
+                                      | GCFillStyle | GCStipple, &gcvalue);
+       gcvalue.foreground = R->PixColors[Color_border];
+       R->h->ShadowGC = XCreateGC(R->Xdisplay, R->scrollBar.win, GCForeground,
+                                  &gcvalue);
+    }
+/* instead of XClearWindow (R->Xdisplay, R->scrollBar.win); */
+    xsb = (R->Options & Opt_scrollBar_right) ? 1 : 0;
+    if (last_top < R->scrollBar.top)
+       XClearArea(R->Xdisplay, R->scrollBar.win,
+                  R->sb_shadow + xsb, last_top,
+                  sbwidth + 1, (R->scrollBar.top - last_top), False);
+
+    if (R->scrollBar.bot < last_bot)
+       XClearArea(R->Xdisplay, R->scrollBar.win,
+                  R->sb_shadow + xsb, R->scrollBar.bot,
+                  sbwidth + 1, (last_bot - R->scrollBar.bot), False);
+
+/* scrollbar slider */
+    XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->xscrollbarGC,
+                  xsb + 1, R->scrollBar.top, sbwidth, scrollbar_len);
+
+    /*XDrawLine(R->Xdisplay, R->scrollBar.win, R->h->ShadowGC,
+             xsb ? 0 : sbwidth, R->scrollBar.beg,
+             xsb ? 0 : sbwidth, R->scrollBar.end);*/
+    return 1;
+}
+#endif                         /* XTERM_SCROLLBAR */
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/scrollbar.C b/src/scrollbar.C
new file mode 100644 (file)
index 0000000..22855a3
--- /dev/null
@@ -0,0 +1,224 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       scrollbar.c
+ *----------------------------------------------------------------------*
+ * $Id: scrollbar.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * Copyright (c) 1997,1998 mj olesen <olesen@me.QueensU.CA>
+ * Copyright (c) 1998      Alfredo K. Kojima <kojima@windowmaker.org>
+ *                             - N*XTstep like scrollbars
+ * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "scrollbar.intpro"    /* PROTOS for internal routines */
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Map or unmap a scrollbar.  Returns non-zero upon change of state
+ */
+/* EXTPROTO */
+int
+rxvt_scrollbar_mapping(pR_ int map)
+{
+    int             change = 0;
+#ifdef HAVE_SCROLLBARS
+
+    if (map && !scrollbar_visible(R)) {
+       scrollbar_setIdle();
+       if (!R->scrollBar.win)
+           rxvt_Resize_scrollBar(aR);
+       if (R->scrollBar.win) {
+           XMapWindow(R->Xdisplay, R->scrollBar.win);
+           change = 1;
+       }
+    } else if (!map && scrollbar_visible(R)) {
+       R->scrollBar.state = 0;
+       XUnmapWindow(R->Xdisplay, R->scrollBar.win);
+       change = 1;
+    }
+#endif
+    return change;
+}
+
+/* EXTPROTO */
+void
+rxvt_Resize_scrollBar(pR)
+{
+#ifdef HAVE_SCROLLBARS
+    int             delayed_init = 0;
+
+#define R_SCROLLBEG_XTERM      0
+#define R_SCROLLEND_XTERM      R->szHint.height
+#define R_SCROLLBEG_NEXT       0
+#define R_SCROLLEND_NEXT       R->szHint.height - (SB_BUTTON_TOTAL_HEIGHT + \
+                                                   SB_PADDING)
+#define R_SCROLLBEG_RXVT       (R->scrollBar.width + 1) + R->sb_shadow
+#define R_SCROLLEND_RXVT       R->szHint.height - R_SCROLLBEG_RXVT - \
+                                   (2 * R->sb_shadow)
+
+#if defined(XTERM_SCROLLBAR)
+    if (R->scrollBar.style == R_SB_XTERM) {
+       R->scrollBar.beg = R_SCROLLBEG_XTERM;
+       R->scrollBar.end = R_SCROLLEND_XTERM;
+       R->scrollBar.update = rxvt_scrollbar_show_xterm;
+    }
+#endif
+#if defined(NEXT_SCROLLBAR)
+    if (R->scrollBar.style == R_SB_NEXT) {
+       R->scrollBar.beg = R_SCROLLBEG_NEXT;
+       R->scrollBar.end = R_SCROLLEND_NEXT;
+       R->scrollBar.update = rxvt_scrollbar_show_next;
+    }
+#endif
+#if defined(RXVT_SCROLLBAR)
+    if (R->scrollBar.style == R_SB_RXVT) {
+       R->scrollBar.beg = R_SCROLLBEG_RXVT;
+       R->scrollBar.end = R_SCROLLEND_RXVT;
+       R->scrollBar.update = rxvt_scrollbar_show_rxvt;
+    }
+#endif
+
+    if (!R->scrollBar.win) {
+/* create the scrollbar window */
+       R->scrollBar.win = XCreateSimpleWindow(R->Xdisplay,
+                                              R->TermWin.parent[0],
+                                              R->h->window_sb_x, 0,
+                                              scrollbar_TotalWidth(),
+                                              R->szHint.height,
+                                              0,
+                                              R->PixColors[Color_fg],
+                                              R->PixColors[Color_bg]);
+#ifdef DEBUG_X
+       XStoreName(R->Xdisplay, R->scrollBar.win, "scrollbar");
+#endif
+       XDefineCursor(R->Xdisplay, R->scrollBar.win, R->h->pointer_leftptr);
+       XSelectInput(R->Xdisplay, R->scrollBar.win,
+                    (ExposureMask | ButtonPressMask | ButtonReleaseMask
+                     | Button1MotionMask | Button2MotionMask
+                     | Button3MotionMask));
+       delayed_init = 1;
+    }
+    rxvt_scrollbar_show(aR_ 1);
+    if (delayed_init)
+       XMapWindow(R->Xdisplay, R->scrollBar.win);
+#endif
+}
+
+/*
+ * Update current scrollbar view w.r.t. slider heights, etc.
+ */
+/* EXTPROTO */
+int
+rxvt_scrollbar_show(pR_ int update)
+{
+    int             ret = 0;
+#ifdef HAVE_SCROLLBARS
+    int             top, bot, len, adj;
+
+    if (!scrollbar_visible(R))
+       return 0;
+
+    if (update) {
+       top = (R->TermWin.nscrolled - R->TermWin.view_start);
+       bot = top + (R->TermWin.nrow - 1);
+       len = max((R->TermWin.nscrolled + (R->TermWin.nrow - 1)), 1);
+       adj = (((bot - top) * scrollbar_size()) % len) > 0 ? 1 : 0;
+
+       R->scrollBar.top = (R->scrollBar.beg + (top * scrollbar_size()) / len);
+       R->h->scrollbar_len = ((bot - top) * scrollbar_size()) / len +
+                             scrollbar_minheight() + adj;
+       R->scrollBar.bot = (R->scrollBar.top + R->h->scrollbar_len);
+       /* no change */
+       if (R->scrollBar.top == R->h->last_top
+           && R->scrollBar.bot == R->h->last_bot
+           && (R->scrollBar.state == R->h->last_state || !scrollbar_isUpDn()))
+           return 0;
+    }
+
+    ret = R->scrollBar.update(aR_ update, R->h->last_top, R->h->last_bot,
+                             R->h->scrollbar_len);
+
+    R->h->last_top = R->scrollBar.top;
+    R->h->last_bot = R->scrollBar.bot;
+    R->h->last_state = R->scrollBar.state;
+
+#endif
+    return ret;
+}
+
+/* EXTPROTO */
+void
+rxvt_setup_scrollbar(pR_ const char *scrollalign, const char *scrollstyle, const char *thickness)
+{
+#ifdef HAVE_SCROLLBARS
+    int             i;
+    short           style, width;
+
+# if defined(RXVT_SCROLLBAR) || !(defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR))
+    style = R_SB_RXVT;
+# else
+#  ifdef NEXT_SCROLLBAR
+    style = R_SB_NEXT;
+#  elif defined(XTERM_SCROLLBAR)
+    style = R_SB_XTERM;
+#  endif
+# endif
+
+# if (defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR))
+    if (scrollstyle) {
+#  ifdef NEXT_SCROLLBAR
+       if (STRNCASECMP(scrollstyle, "next", 4) == 0)
+           style = R_SB_NEXT;
+#  endif
+#  ifdef XTERM_SCROLLBAR
+       if (STRNCASECMP(scrollstyle, "xterm", 5) == 0)
+           style = R_SB_XTERM;
+#  endif
+    }
+# endif
+    if (style == R_SB_NEXT)
+       width = SB_WIDTH_NEXT;
+    else if (style == R_SB_XTERM)
+       width = SB_WIDTH_XTERM;
+    else /* if (style == R_SB_RXVT) */
+       width = SB_WIDTH_RXVT;
+
+    if (style != R_SB_NEXT)    /* dishonour request - for now */
+    if (thickness && (i = atoi(thickness)) >= SB_WIDTH_MINIMUM)
+       width = min(i, SB_WIDTH_MAXIMUM);
+
+# if defined(RXVT_SCROLLBAR)
+    if (!(R->Options & Opt_scrollBar_floating) && style == R_SB_RXVT)
+       R->sb_shadow = SHADOW;
+# endif
+
+    R->scrollBar.style = style;
+    R->scrollBar.width = width;
+
+    /* R->h->scrollbar_align = R_SB_ALIGN_CENTRE; */
+    if (scrollalign) {
+       if (STRNCASECMP(scrollalign, "top", 3) == 0)
+           R->h->scrollbar_align = R_SB_ALIGN_TOP;
+       else if (STRNCASECMP(scrollalign, "bottom", 6) == 0)
+           R->h->scrollbar_align = R_SB_ALIGN_BOTTOM;
+    }
+#endif
+}
+
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/strings.C b/src/strings.C
new file mode 100644 (file)
index 0000000..8d7e264
--- /dev/null
@@ -0,0 +1,308 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       strings.c
+ *----------------------------------------------------------------------*
+ * $Id: strings.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "strings.intpro"      /* PROTOS for internal routines */
+
+#ifndef NO_STRINGS
+/*----------------------------------------------------------------------*/
+/*
+ * a replacement for strcasecmp() to avoid linking an entire library.
+ * Mark Olesen added this in 2.15 but for which OS & library? - Geoff Wing
+ */
+/* EXTPROTO */
+int
+strcasecmp(const char *s1, const char *s2)
+{
+    for ( ; tolower(*s1) == tolower(*s2); s1++, s2++)
+       if (!*s1)
+           return 0;
+    return (int)(tolower(*s1) - tolower(*s2));
+}
+
+/* EXTPROTO */
+int
+strncasecmp(const char *s1, const char *s2, size_t n)
+{
+    for ( ; n-- && (tolower(*s1) == tolower(*s2)); s1++, s2++)
+       if (!*s1)
+           return 0;
+    if (n == 0)
+       return 0;
+    return (int)(tolower(*s1) - tolower(*s2));
+}
+
+/* EXTPROTO */
+char           *
+strcpy(char *d, const char *s)
+{
+    char          *r = d;
+
+    for ( ; (*r++ = *s++) != '\0'; ) ;
+    return d;
+}
+
+/* EXTPROTO */
+char           *
+strncpy(char *d, const char *s, size_t len)
+{
+    char          *r = d;
+
+    if (len)
+       for ( ; len; len--)
+           if ((*r++ = *s++) == '\0') {
+               for ( ; --len; )
+                   *r++ = '\0';
+               break;
+           }
+    return d;
+}
+
+/* EXTPROTO */
+int
+strcmp(const char *s1, const char *s2)
+{
+    for ( ; (*s1 == *s2++); )
+       if (*s1++ == '\0')
+           return 0;
+    return (int) ((unsigned char) *s1 - (unsigned char) *--s2);
+}
+
+/* EXTPROTO */
+int
+strncmp(const char *s1, const char *s2, size_t len)
+{
+    if (len) {
+       for ( ; len-- && (*s1++ == *s2++); ) ;
+       if (++len)
+           return (int) ((unsigned char) *--s1 - (unsigned char) *--s2);
+    }
+    return 0;
+}
+
+/* EXTPROTO */
+char           *
+strcat(char *s1, const char *s2)
+{
+    char           *r = s1;
+
+    if (*r != '\0')
+       for ( ; *++r != '\0'; ) ;
+    for ( ; (*r++ = *s2++) != '\0'; ) ;
+
+    return s1;
+}
+
+/* EXTPROTO */
+char           *
+strncat(char *s1, const char *s2, size_t len)
+{
+    char           *r = s1;
+
+    if (*r != '\0')
+       for ( ; *++r != '\0'; ) ;
+    for ( ; len-- && ((*r++ = *s2++) != '\0'); ) ;
+    *r = '\0';
+
+    return s1;
+}
+
+/* EXTPROTO */
+size_t
+strlen(const char *s)
+{
+    size_t         len = 0;
+
+    for ( ; *s++ != '\0'; len++) ;
+    return len;
+}
+
+/* EXTPROTO */
+char           *
+strdup(const char *s)
+{
+    size_t         len = STRLEN(s) + 1;
+    char          *c;
+
+    if ((c = malloc(len)) != NULL)
+       MEMCPY(c, s, len);
+    return c;
+}
+
+/* EXTPROTO */
+char           *
+index(const char *s, int c)
+{
+    return STRCHR(s, c);
+}
+
+/* EXTPROTO */
+char           *
+strchr(const char *s, int c)
+{
+    char          *p = NULL;
+
+    for (;;) {
+       if (*s == (char)c) {
+           p = (char *)s;
+           break;
+       }
+       if (*s++ == '\0')
+           break;
+    }
+    return p;
+
+}
+
+/* EXTPROTO */
+char           *
+rindex(const char *s, int c)
+{
+    return STRRCHR(s, c);
+}
+
+/* EXTPROTO */
+char           *
+strrchr(const char *s, int c)
+{
+    char          *p = NULL;
+
+    for (;;) {
+       if (*s == (char)c)
+           p = (char *)s;
+       if (*s++ == '\0')
+           break;
+    }
+    return p;
+}
+
+/* EXTPROTO */
+void           *
+memcpy(void *s1, const void *s2, size_t len)
+{
+    /* has extra stack and time but less code space */
+    return MEMMOVE(s1, s2, len);
+}
+
+/*--------------------------------------------------------------------------*
+ * Possibly faster memmove() by Geoff Wing <mason@primenet.com.au>
+ *--------------------------------------------------------------------------*/
+/* EXTPROTO */
+void           *
+memmove(void *d, const void *s, size_t len)
+{
+    u_intp_t        i;
+    unsigned char  *dst = (unsigned char *)d;
+    const unsigned char *src = (const unsigned char *)s;
+
+    if (len && d != s) {
+       if ((u_intp_t)d < (u_intp_t)s) {
+       /* forwards */
+           i = (-(u_intp_t)dst) & (SIZEOF_INT_P - 1);
+           if (len >= 16 && i == ((-(u_intp_t)src) & (SIZEOF_INT_P - 1))) {
+           /* speed up since src & dst are offset correctly */
+               len -= (size_t)i;
+               for ( ; i--; )
+                   *dst++ = *src++;
+               for (i = (u_intp_t)(len / SIZEOF_INT_P); i--; )
+                   *((u_intp_t *)dst)++ = *((const u_intp_t *)src)++;
+               len &= (SIZEOF_INT_P - 1);
+           }
+           for ( ; len--; )
+               *dst++ = *src++;
+       } else {
+       /* backwards */
+           dst += len;
+           src += len;
+           i = ((u_intp_t)dst) & (SIZEOF_INT_P - 1);
+           if (len >= 16 && i == (((u_intp_t)src) & (SIZEOF_INT_P - 1))) {
+           /* speed up since src & dst are offset correctly */
+               len -= (size_t)i;
+               for ( ; i--; )
+                   *--dst = *--src;
+               for (i = (u_intp_t)(len / SIZEOF_INT_P); i--; )
+                   *--((u_intp_t *)dst) = *--((const u_intp_t *)src);
+               len &= (SIZEOF_INT_P - 1);
+           }
+           for ( ; len--; )
+               *--dst = *--src;
+       }
+    }
+    return d;
+}
+
+/*--------------------------------------------------------------------------*
+ * Possibly faster memset() by Geoff Wing <mason@primenet.com.au>
+ * presumptions:
+ *   1) intp_t write the best
+ *   2) SIZEOF_INT_P == power of 2
+ *--------------------------------------------------------------------------*/
+
+/* EXTPROTO */
+void
+bzero(void *b, size_t len)
+{
+    MEMSET(b, 0, len);
+}
+
+/* EXTPROTO */
+void           *
+memset(void *p, int c1, size_t len)
+{
+    u_intp_t        i, val;
+    unsigned char   c = (unsigned char) c1;
+    unsigned char  *lp = (unsigned char *) p;
+
+    if (len) {
+       if (len >= 16) { /* < 16 probably not worth all the calculations */
+/* write out preceding characters so we align on an integer boundary */
+           if ((i = ((-(u_intp_t)p) & (SIZEOF_INT_P - 1)))) {
+               len -= (size_t)i;
+               for (; i--;)
+                   *lp++ = c;
+           }
+
+/* do the fast writing */
+           val = (c << 8) + c;
+#if SIZEOF_INT_P >= 4
+           val |= (val << 16);
+#endif
+#if SIZEOF_INT_P >= 8
+           val |= (val << 32);
+#endif
+#if SIZEOF_INT_P == 16
+           val |= (val << 64);
+#endif
+           for (i = (u_intp_t)(len / SIZEOF_INT_P); i--;)
+               *((u_intp_t *)lp)++ = val;
+           len &= (SIZEOF_INT_P - 1);
+       }
+/* write trailing characters */
+       for (; len--;)
+           *lp++ = c;
+    }
+    return p;
+}
+#endif
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/xdefaults.C b/src/xdefaults.C
new file mode 100644 (file)
index 0000000..23870f0
--- /dev/null
@@ -0,0 +1,998 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       xdefaults.c
+ *----------------------------------------------------------------------*
+ * $Id: xdefaults.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1994      Robert Nation <nation@rocket.sanders.lockheed.com>
+ *                             - original version
+ * Copyright (c) 1997,1998 mj olesen <olesen@me.queensu.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*
+ * get resources from ~/.Xdefaults or ~/.Xresources with the memory-saving
+ * default or with XGetDefault() (#define USE_XGETDEFAULT)
+ *----------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "version.h"
+#include "xdefaults.intpro"    /* PROTOS for internal routines */
+
+/* #define DEBUG_RESOURCES */
+
+static const char *const xnames[2] = { ".Xdefaults", ".Xresources" };
+
+/*{{{ monolithic option/resource structure: */
+/*
+ * `string' options MUST have a usage argument
+ * `switch' and `boolean' options have no argument
+ * if there's no desc(ription), it won't appear in rxvt_usage()
+ */
+
+/* INFO() - descriptive information only */
+#define INFO(opt, arg, desc)                                   \
+    {0, -1, NULL, (opt), (arg), (desc)}
+
+/* STRG() - command-line option, with/without resource */
+#define STRG(rsp, kw, opt, arg, desc)                          \
+    {0, (rsp), (kw), (opt), (arg), (desc)}
+
+/* RSTRG() - resource/long-option */
+#define RSTRG(rsp, kw, arg)                                    \
+    {0, (rsp), (kw), NULL, (arg), NULL}
+
+/* BOOL() - regular boolean `-/+' flag */
+#define BOOL(rsp, kw, opt, flag, desc)                         \
+    {(Opt_Boolean|(flag)), (rsp), (kw), (opt), NULL, (desc)}
+
+/* SWCH() - `-' flag */
+#define SWCH(opt, flag, desc)                                  \
+    {(flag), -1, NULL, (opt), NULL, (desc)}
+
+/* convenient macros */
+#define optList_strlen(i)                                              \
+    (optList[i].flag ? 0 : (optList[i].arg ? STRLEN(optList[i].arg) : 1))
+#define optList_isBool(i)                                              \
+    (optList[i].flag & Opt_Boolean)
+#define optList_isReverse(i)                                           \
+    (optList[i].flag & Opt_Reverse)
+#define optList_size()                                                 \
+    (sizeof(optList) / sizeof(optList[0]))
+
+static const struct {
+    const unsigned long flag;  /* Option flag */
+    const int       doff;      /* data offset */
+    const char     *kw;                /* keyword */
+    const char     *opt;       /* option */
+    const char     *arg;       /* argument */
+    const char     *desc;      /* description */
+} optList[] = {
+    STRG(Rs_display_name, NULL, "d", NULL, NULL),      /* short form */
+    STRG(Rs_display_name, NULL, "display", "string", "X server to contact"),
+    STRG(Rs_term_name, "termName", "tn", "string",
+        "value of the TERM environment variable"),
+    STRG(Rs_geometry, NULL, "g", NULL, NULL),  /* short form */
+    STRG(Rs_geometry, "geometry", "geometry", "geometry",
+        "size (in characters) and position"),
+    SWCH("C", Opt_console, "intercept console messages"),
+    SWCH("iconic", Opt_iconic, "start iconic"),
+    SWCH("ic", Opt_iconic, NULL),      /* short form */
+    BOOL(Rs_reverseVideo, "reverseVideo", "rv", Opt_reverseVideo,
+        "reverse video"),
+    BOOL(Rs_loginShell, "loginShell", "ls", Opt_loginShell, "login shell"),
+    BOOL(Rs_jumpScroll, "jumpScroll", "j", Opt_jumpScroll, "jump scrolling"),
+#ifdef HAVE_SCROLLBARS
+    BOOL(Rs_scrollBar, "scrollBar", "sb", Opt_scrollBar, "scrollbar"),
+    BOOL(Rs_scrollBar_right, "scrollBar_right", "sr", Opt_scrollBar_right,
+        "scrollbar right"),
+    BOOL(Rs_scrollBar_floating, "scrollBar_floating", "st",
+        Opt_scrollBar_floating, "scrollbar without a trough"),
+#endif
+    BOOL(Rs_scrollTtyOutput, "scrollTtyOutput", NULL, Opt_scrollTtyOutput,
+        NULL),
+    BOOL(Rs_scrollTtyOutput, NULL, "si", Opt_Reverse | Opt_scrollTtyOutput,
+        "scroll-on-tty-output inhibit"),
+    BOOL(Rs_scrollTtyKeypress, "scrollTtyKeypress", "sk", Opt_scrollTtyKeypress,
+        "scroll-on-keypress"),
+    BOOL(Rs_scrollWithBuffer, "scrollWithBuffer", "sw", Opt_scrollWithBuffer,
+        "scroll-with-buffer"),
+#ifdef TRANSPARENT
+    BOOL(Rs_transparent, "inheritPixmap", "ip", Opt_transparent,
+        "inherit parent pixmap"),
+    BOOL(Rs_transparent_all, "inheritPixmapforce", "ipf", Opt_transparent_all,
+        "forcefully inherit root pixmap"),
+    SWCH("tr", Opt_transparent, NULL),
+#endif
+    BOOL(Rs_utmpInhibit, "utmpInhibit", "ut", Opt_utmpInhibit, "utmp inhibit"),
+#ifndef NO_BELL
+    BOOL(Rs_visualBell, "visualBell", "vb", Opt_visualBell, "visual bell"),
+# if ! defined(NO_MAPALERT) && defined(MAPALERT_OPTION)
+    BOOL(Rs_mapAlert, "mapAlert", NULL, Opt_mapAlert, NULL),
+# endif
+#endif
+#ifdef META8_OPTION
+    BOOL(Rs_meta8, "meta8", NULL, Opt_meta8, NULL),
+#endif
+#ifdef MOUSE_WHEEL
+    BOOL(Rs_mouseWheelScrollPage, "mouseWheelScrollPage", NULL, Opt_mouseWheelScrollPage,
+        NULL),
+#endif
+#ifdef MULTICHAR_SET
+    BOOL(Rs_mc_hack, "multibyte_cursor", "mcc", Opt_mc_hack,
+        "Multibyte character cursor movement"),
+#endif
+#ifndef NO_FRILLS
+    BOOL(Rs_tripleclickwords, "tripleclickwords", "tcw", Opt_tripleclickwords,
+        "triple click word selection"),
+#endif
+#ifdef CURSOR_BLINK
+    BOOL(Rs_cursorBlink, "cursorBlink", "bc", Opt_cursorBlink, "blinking cursor"),
+#endif
+#ifdef POINTER_BLANK
+    BOOL(Rs_pointerBlank, "pointerBlank", NULL, Opt_pointerBlank, NULL),
+#endif
+    STRG(Rs_color + Color_bg, "background", "bg", "color", "background color"),
+    STRG(Rs_color + Color_fg, "foreground", "fg", "color", "foreground color"),
+    RSTRG(Rs_color + minCOLOR + 0, "color0", "color"),
+    RSTRG(Rs_color + minCOLOR + 1, "color1", "color"),
+    RSTRG(Rs_color + minCOLOR + 2, "color2", "color"),
+    RSTRG(Rs_color + minCOLOR + 3, "color3", "color"),
+    RSTRG(Rs_color + minCOLOR + 4, "color4", "color"),
+    RSTRG(Rs_color + minCOLOR + 5, "color5", "color"),
+    RSTRG(Rs_color + minCOLOR + 6, "color6", "color"),
+    RSTRG(Rs_color + minCOLOR + 7, "color7", "color"),
+#ifndef NO_BRIGHTCOLOR
+    RSTRG(Rs_color + minBrightCOLOR + 0, "color8", "color"),
+    RSTRG(Rs_color + minBrightCOLOR + 1, "color9", "color"),
+    RSTRG(Rs_color + minBrightCOLOR + 2, "color10", "color"),
+    RSTRG(Rs_color + minBrightCOLOR + 3, "color11", "color"),
+    RSTRG(Rs_color + minBrightCOLOR + 4, "color12", "color"),
+    RSTRG(Rs_color + minBrightCOLOR + 5, "color13", "color"),
+    RSTRG(Rs_color + minBrightCOLOR + 6, "color14", "color"),
+    RSTRG(Rs_color + minBrightCOLOR + 7, "color15", "color"),
+#endif                         /* NO_BRIGHTCOLOR */
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+    RSTRG(Rs_color + Color_BD, "colorBD", "color"),
+    RSTRG(Rs_color + Color_UL, "colorUL", "color"),
+    RSTRG(Rs_color + Color_RV, "colorRV", "color"),
+#endif                         /* ! NO_BOLD_UNDERLINE_REVERSE */
+#ifdef KEEP_SCROLLCOLOR
+    RSTRG(Rs_color + Color_scroll, "scrollColor", "color"),
+    RSTRG(Rs_color + Color_trough, "troughColor", "color"),
+#endif                         /* KEEP_SCROLLCOLOR */
+#ifdef OPTION_HC
+    STRG(Rs_color + Color_HC, "highlightColor", "hc", "color", "highlight color"),
+#endif
+#if defined (XPM_BACKGROUND) || (MENUBAR_MAX)
+    RSTRG(Rs_path, "path", "search path"),
+#endif                         /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */
+#ifdef XPM_BACKGROUND
+    STRG(Rs_backgroundPixmap, "backgroundPixmap", "pixmap", "file[;geom]",
+        "background pixmap"),
+#endif                         /* XPM_BACKGROUND */
+#if (MENUBAR_MAX)
+    RSTRG(Rs_menu, "menu", "name[;tag]"),
+#endif
+#ifndef NO_BOLDFONT
+    STRG(Rs_boldFont, "boldFont", "fb", "fontname", "bold text font"),
+#endif
+    STRG(Rs_font + 0, "font", "fn", "fontname", "normal text font"),
+/* fonts: command-line option = resource name */
+#ifdef MULTICHAR_SET
+    STRG(Rs_multichar_encoding, "multichar_encoding", "km", "mode",
+        "multichar encoding; mode = eucj|sjis|big5|gb|kr|noenc"),
+#endif                         /* MULTICHAR_SET */
+#ifdef USE_XIM
+    STRG(Rs_inputMethod, "inputMethod", "im", "name", "name of input method"),
+    STRG(Rs_preeditType, "preeditType", "pt", "style",
+        "input style: style = OverTheSpot|OffTheSpot|Root"),
+#endif                         /* USE_XIM */
+#ifdef GREEK_SUPPORT
+    STRG(Rs_greek_keyboard, "greek_keyboard", "grk", "mode",
+        "greek keyboard mapping; mode = iso | ibm"),
+    RSTRG(Rs_greektoggle_key, "greektoggle_key", "keysym"),
+#endif
+    STRG(Rs_name, NULL, "name", "string",
+        "client instance, icon, and title strings"),
+    STRG(Rs_title, "title", "title", "string", "title name for window"),
+    STRG(Rs_title, NULL, "T", NULL, NULL),     /* short form */
+    STRG(Rs_iconName, "iconName", "n", "string", "icon name for window"),
+#ifndef NO_CURSORCOLOR
+    STRG(Rs_color + Color_cursor, "cursorColor", "cr", "color", "cursor color"),
+/* command-line option = resource name */
+    RSTRG(Rs_color + Color_cursor2, "cursorColor2", "color"),
+#endif                         /* NO_CURSORCOLOR */
+    STRG(Rs_color + Color_pointer, "pointerColor", "pr", "color",
+        "pointer color"),
+    STRG(Rs_color + Color_border, "borderColor", "bd", "color",
+        "border color"),
+    STRG(Rs_saveLines, "saveLines", "sl", "number",
+        "number of scrolled lines to save"),
+#ifndef NO_FRILLS
+    STRG(Rs_ext_bwidth, "externalBorder", "w", "number",
+        "external border in pixels"),
+    STRG(Rs_ext_bwidth, NULL, "bw", NULL, NULL),
+    STRG(Rs_ext_bwidth, NULL, "borderwidth", NULL, NULL),
+    STRG(Rs_int_bwidth, "internalBorder", "b", "number",
+        "internal border in pixels"),
+#endif
+#ifndef NO_LINESPACE
+    STRG(Rs_lineSpace, "lineSpace", "lsp", "number",
+        "number of extra pixels between rows"),
+#endif
+    STRG(Rs_scrollBar_thickness, "thickness", "sbt", "number",
+        "scrollbar thickness/width in pixels"),
+#ifdef POINTER_BLANK
+    RSTRG(Rs_pointerBlankDelay, "pointerBlankDelay", "number"),
+#endif
+#ifndef NO_BACKSPACE_KEY
+    RSTRG(Rs_backspace_key, "backspacekey", "string"),
+#endif
+#ifndef NO_DELETE_KEY
+    RSTRG(Rs_delete_key, "deletekey", "string"),
+#endif
+    RSTRG(Rs_selectstyle, "selectstyle", "mode"),
+    RSTRG(Rs_scrollstyle, "scrollstyle", "mode"),
+#ifdef HAVE_SCROLLBARS
+    RSTRG(Rs_scrollBar_align, "scrollBar_align", "mode"),
+#endif
+#ifdef PRINTPIPE
+    RSTRG(Rs_print_pipe, "print-pipe", "string"),
+#endif
+#if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
+    RSTRG(Rs_bigfont_key, "bigfont_key", "keysym"),
+    RSTRG(Rs_smallfont_key, "smallfont_key", "keysym"),
+#endif
+    STRG(Rs_modifier, "modifier", "mod", "modifier",
+        "meta modifier = alt|meta|hyper|super|mod1|...|mod5"),
+    INFO("xrm", "string", "X resource"),
+#ifdef CUTCHAR_RESOURCE
+    RSTRG(Rs_cutchars, "cutchars", "string"),
+#endif                         /* CUTCHAR_RESOURCE */
+#ifdef ACS_ASCII
+    RSTRG(Rs_acs_chars, "acsChars", "string"),
+#endif                         /* ACS_ASCII */
+    RSTRG(Rs_answerbackstring, "answerbackString", "string"),
+    INFO("e", "command arg ...", "command to execute")
+};
+
+#undef INFO
+#undef STRG
+#undef RSTRG
+#undef SWCH
+#undef BOOL
+/*}}} */
+
+static const char releasestring[] = "Rxvt v" VERSION " - released: " DATE "\n";
+static const char optionsstring[] = "Options: "
+#if defined(XPM_BACKGROUND)
+    "XPM,"
+#endif
+#if defined(TRANSPARENT)
+    "transparent,"
+#endif
+#if defined(UTMP_SUPPORT)
+    "utmp,"
+#endif
+#if defined(MENUBAR)
+    "menubar,"
+#endif
+#if !defined(NO_FRILLS)
+    "frills,"
+#endif
+#if !defined(NO_LINESPACE)
+    "linespace,"
+#endif
+#if defined(PREFER_24BIT)
+    "24bit,"
+#endif
+#if defined(USE_XIM)
+    "XIM,"
+#endif
+#if defined(MULTICHAR_SET)
+    "multichar_languages,"
+#endif
+    "scrollbars="
+#if !defined(HAVE_SCROLLBARS)
+    "NONE"
+#else
+# if defined(RXVT_SCROLLBAR)
+    "rxvt"
+#  if defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR)
+    "+"
+#  endif
+# endif
+# if defined(NEXT_SCROLLBAR)
+    "NeXT"
+#  if defined(XTERM_SCROLLBAR)
+    "+"
+#  endif
+# endif
+# if defined(XTERM_SCROLLBAR)
+    "xterm"
+# endif
+#endif
+    ","
+#if defined(GREEK_SUPPORT)
+    "Greek,"
+#endif
+#if defined(RXVT_GRAPHICS)
+    "graphics,"
+#endif
+#if defined(NO_BACKSPACE_KEY)
+    "no_backspace,"
+#endif
+#if defined(NO_DELETE_KEY)
+    "no_delete,"
+#endif
+#if !defined(NO_STRINGS)
+    "strings,"
+#endif
+#if defined(TTY_256COLOR)
+    "256colour,"
+#endif
+#if defined(NO_RESOURCES)
+    "NoResources"
+#else
+# if defined(USE_XGETDEFAULT)
+    "XGetDefaults"
+# else
+    ".Xdefaults"
+# endif
+#endif
+    "\nUsage: ";               /* Usage */
+
+#define INDENT 18
+
+/*{{{ usage: */
+/*----------------------------------------------------------------------*/
+/* EXTPROTO */
+void
+rxvt_usage(int type)
+{
+    unsigned int    i, col;
+
+    write(STDERR_FILENO, releasestring, sizeof(releasestring) - 1);
+    write(STDERR_FILENO, optionsstring, sizeof(optionsstring) - 1);
+    write(STDERR_FILENO, APL_NAME, sizeof(APL_NAME) - 1);
+
+    switch (type) {
+    case 0:                    /* brief listing */
+       fprintf(stderr, " [-help] [--help]\n");
+       for (col = 1, i = 0; i < optList_size(); i++)
+           if (optList[i].desc != NULL) {
+               int             len = 0;
+
+               if (!optList_isBool(i)) {
+                   len = optList_strlen(i);
+                   if (len > 0)
+                       len++;  /* account for space */
+               }
+#ifdef DEBUG_STRICT
+               assert(optList[i].opt != NULL);
+#endif
+               len += 4 + STRLEN(optList[i].opt) + (optList_isBool(i) ? 2: 0);
+               col += len;
+               if (col > 79) { /* assume regular width */
+                   putc('\n', stderr);
+                   col = 1 + len;
+               }
+               fprintf(stderr, " [-%s%s", (optList_isBool(i) ? "/+" : ""),
+                       optList[i].opt);
+               if (optList_strlen(i))
+                   fprintf(stderr, " %s]", optList[i].arg);
+               else
+                   fprintf(stderr, "]");
+           }
+       break;
+
+    case 1:                    /* full command-line listing */
+       fprintf(stderr, " [options] [-e command args]\n\n"
+               "where options include:\n");
+       for (i = 0; i < optList_size(); i++)
+           if (optList[i].desc != NULL) {
+#ifdef DEBUG_STRICT
+               assert(optList[i].opt != NULL);
+#endif
+               fprintf(stderr, "  %s%s %-*s%s%s\n",
+                       (optList_isBool(i) ? "-/+" : "-"), optList[i].opt,
+                       (INDENT - STRLEN(optList[i].opt)
+                        + (optList_isBool(i) ? 0 : 2)),
+                       (optList[i].arg ? optList[i].arg : ""),
+                       (optList_isBool(i) ? "turn on/off " : ""),
+                       optList[i].desc);
+           }
+       fprintf(stderr, "\n  --help to list long-options");
+       break;
+
+    case 2:                    /* full resource listing */
+       fprintf(stderr,
+               " [options] [-e command args]\n\n"
+               "where resources (long-options) include:\n");
+
+       for (i = 0; i < optList_size(); i++)
+           if (optList[i].kw != NULL)
+               fprintf(stderr, "  %s: %*s%s\n",
+                       optList[i].kw,
+                       (INDENT - STRLEN(optList[i].kw)), "", /* XXX */
+                       (optList_isBool(i) ? "boolean" : optList[i].arg));
+#ifdef KEYSYM_RESOURCE
+       fprintf(stderr, "  " "keysym.sym" ": %*s%s\n",
+               (INDENT - sizeof("keysym.sym") + 1), "", /* XXX */
+               "keysym");
+#endif
+       fprintf(stderr, "\n  -help to list options");
+       break;
+    }
+    fprintf(stderr, "\n\n");
+    exit(EXIT_FAILURE);
+    /* NOTREACHED */
+}
+
+/*}}} */
+
+/*{{{ get command-line options before getting resources */
+/* EXTPROTO */
+void
+rxvt_get_options(pR_ int argc, const char *const *argv)
+{
+    int             i, bad_option = 0;
+    static const char On[3] = "ON", Off[4] = "OFF";
+
+    for (i = 1; i < argc; i++) {
+       unsigned int    entry, longopt = 0;
+       const char     *flag, *opt;
+
+       opt = argv[i];
+#ifdef DEBUG_RESOURCES
+       fprintf(stderr, "argv[%d] = %s: ", i, opt);
+#endif
+       if (*opt == '-') {
+           flag = On;
+           if (*++opt == '-')
+               longopt = *opt++;       /* long option */
+       } else if (*opt == '+') {
+           flag = Off;
+           if (*++opt == '+')
+               longopt = *opt++;       /* long option */
+       } else {
+           bad_option = 1;
+           rxvt_print_error("bad option \"%s\"", opt);
+           continue;
+       }
+
+       if (!STRCMP(opt, "help"))
+           rxvt_usage(longopt ? 2 : 1);
+       if (!STRCMP(opt, "h"))
+           rxvt_usage(0);
+
+       /* feature: always try to match long-options */
+       for (entry = 0; entry < optList_size(); entry++)
+           if ((optList[entry].kw && !STRCMP(opt, optList[entry].kw))
+               || (!longopt
+                   && optList[entry].opt && !STRCMP(opt, optList[entry].opt)))
+               break;
+
+       if (entry < optList_size()) {
+           if (optList_isReverse(entry))
+               flag = flag == On ? Off : On;
+           if (optList_strlen(entry)) {        /* string value */
+               const char     *str = argv[++i];
+
+#ifdef DEBUG_RESOURCES
+               fprintf(stderr, "string (%s,%s) = ",
+                       optList[entry].opt ? optList[entry].opt : "nil",
+                       optList[entry].kw ? optList[entry].kw : "nil");
+#endif
+               if (flag == On && str && (optList[entry].doff != -1)) {
+#ifdef DEBUG_RESOURCES
+                   fprintf(stderr, "\"%s\"\n", str);
+#endif
+                   R->h->rs[optList[entry].doff] = str;
+                   /*
+                    * special cases are handled in main.c:main() to allow
+                    * X resources to set these values before we settle for
+                    * default values
+                    */
+               }
+#ifdef DEBUG_RESOURCES
+               else
+                   fprintf(stderr, "???\n");
+#endif
+           } else {            /* boolean value */
+#ifdef DEBUG_RESOURCES
+               fprintf(stderr, "boolean (%s,%s) = %s\n",
+                       optList[entry].opt, optList[entry].kw, flag);
+#endif
+               if (flag == On)
+                   R->Options |= (optList[entry].flag);
+               else
+                   R->Options &= ~(optList[entry].flag);
+
+               if (optList[entry].doff != -1)
+                   R->h->rs[optList[entry].doff] = flag;
+           }
+       } else
+#ifdef KEYSYM_RESOURCE
+           /* if (!STRNCMP(opt, "keysym.", sizeof("keysym.") - 1)) */
+       if (rxvt_Str_match(opt, "keysym.")) {
+           const char     *str = argv[++i];
+
+           if (str != NULL)
+               rxvt_parse_keysym(aR_ opt + sizeof("keysym.") - 1, str);
+       } else
+#endif
+          ;
+    }
+
+    if (bad_option)
+       rxvt_usage(0);
+}
+
+/*}}} */
+
+#ifndef NO_RESOURCES
+/*----------------------------------------------------------------------*/
+
+# ifdef KEYSYM_RESOURCE
+/*
+ * Define key from XrmEnumerateDatabase.
+ *   quarks will be something like
+ *      "rxvt" "keysym" "0xFF01"
+ *   value will be a string
+ */
+/* ARGSUSED */
+/* INTPROTO */
+Bool
+rxvt_define_key(XrmDatabase *database __attribute__((unused)), XrmBindingList bindings __attribute__((unused)), XrmQuarkList quarks, XrmRepresentation *type __attribute__((unused)), XrmValue *value, XPointer closure __attribute__((unused)))
+{
+    dR;
+    int             last;
+
+    for (last = 0; quarks[last] != NULLQUARK; last++)  /* look for last quark in list */
+       ;
+    last--;
+    rxvt_parse_keysym(aR_ XrmQuarkToString(quarks[last]), (char *)value->addr);
+    return False;
+}
+
+/*
+ * look for something like this (XK_Delete)
+ * rxvt*keysym.0xFFFF: "\177"
+ *
+ * arg will be
+ *      NULL for ~/.Xdefaults and
+ *      non-NULL for command-line options (need to allocate)
+ */
+#define NEWARGLIM      500     /* `reasonable' size */
+/* INTPROTO */
+int
+rxvt_parse_keysym(pR_ const char *str, const char *arg)
+{
+    int             n, sym;
+    char           *key_string, *newarg = NULL;
+    char            newargstr[NEWARGLIM];
+
+    if (arg == NULL) {
+       if ((n = rxvt_Str_match(str, "keysym.")) == 0)
+           return 0;
+       str += n;               /* skip `keysym.' */
+    }
+/* some scanf() have trouble with a 0x prefix */
+    if (isdigit(str[0])) {
+       if (str[0] == '0' && toupper(str[1]) == 'X')
+           str += 2;
+       if (arg) {
+           if (sscanf(str, (STRCHR(str, ':') ? "%x:" : "%x"), &sym) != 1)
+               return -1;
+       } else {
+           if (sscanf(str, "%x:", &sym) != 1)
+               return -1;
+
+           /* cue to ':', it's there since sscanf() worked */
+           STRNCPY(newargstr, STRCHR(str, ':') + 1, NEWARGLIM - 1);
+           newargstr[NEWARGLIM - 1] = '\0';
+           newarg = newargstr;
+       }
+    } else {
+       /*
+        * convert keysym name to keysym number
+        */
+       STRNCPY(newargstr, str, NEWARGLIM - 1);
+       newargstr[NEWARGLIM - 1] = '\0';
+       if (arg == NULL) {
+           if ((newarg = STRCHR(newargstr, ':')) == NULL)
+               return -1;
+           *newarg++ = '\0';   /* terminate keysym name */
+       }
+       if ((sym = XStringToKeysym(newargstr)) == None)
+           return -1;
+    }
+
+    if (sym < 0xFF00 || sym > 0xFFFF)  /* we only do extended keys */
+       return -1;
+    sym &= 0xFF;
+    if (R->h->Keysym_map[sym] != NULL) /* already set ? */
+       return -1;
+
+    if (newarg == NULL) {
+       STRNCPY(newargstr, arg, NEWARGLIM - 1);
+       newargstr[NEWARGLIM - 1] = '\0';
+       newarg = newargstr;
+    }
+    rxvt_Str_trim(newarg);
+    if (*newarg == '\0' || (n = rxvt_Str_escaped(newarg)) == 0)
+       return -1;
+    MIN_IT(n, 255);
+    key_string = (char *)rxvt_malloc((n + 1) * sizeof(char));
+
+    key_string[0] = n;
+    STRNCPY(key_string + 1, newarg, n);
+    R->h->Keysym_map[sym] = (unsigned char *)key_string;
+
+    return 1;
+}
+
+# endif                                /* KEYSYM_RESOURCE */
+
+# ifndef USE_XGETDEFAULT
+/*{{{ rxvt_get_xdefaults() */
+/*
+ * the matching algorithm used for memory-save fake resources
+ */
+/* INTPROTO */
+void
+rxvt_get_xdefaults(pR_ FILE *stream, const char *name)
+{
+    unsigned int    len;
+    char           *str, buffer[256];
+
+    if (stream == NULL)
+       return;
+    len = STRLEN(name);
+    while ((str = fgets(buffer, sizeof(buffer), stream)) != NULL) {
+       unsigned int    entry, n;
+
+       while (*str && isspace(*str))
+           str++;              /* leading whitespace */
+
+       if ((str[len] != '*' && str[len] != '.')
+           || (len && STRNCMP(str, name, len)))
+           continue;
+       str += (len + 1);       /* skip `name*' or `name.' */
+
+# ifdef KEYSYM_RESOURCE
+       if (!rxvt_parse_keysym(aR_ str, NULL))
+# endif                                /* KEYSYM_RESOURCE */
+           for (entry = 0; entry < optList_size(); entry++) {
+               const char     *kw = optList[entry].kw;
+
+               if (kw == NULL)
+                   continue;
+               n = STRLEN(kw);
+               if (str[n] == ':' && rxvt_Str_match(str, kw)) {
+                   /* skip `keyword:' */
+                   str += (n + 1);
+                   rxvt_Str_trim(str);
+                   n = STRLEN(str);
+                   if (n && R->h->rs[optList[entry].doff] == NULL) {
+                       /* not already set */
+                       int             s;
+                       char           *p = (char *)rxvt_malloc((n + 1) * sizeof(char));
+
+                       STRCPY(p, str);
+                       R->h->rs[optList[entry].doff] = p;
+                       if (optList_isBool(entry)) {
+                           s = STRCASECMP(str, "TRUE") == 0
+                               || STRCASECMP(str, "YES") == 0
+                               || STRCASECMP(str, "ON") == 0
+                               || STRCASECMP(str, "1") == 0;
+                           if (optList_isReverse(entry))
+                               s = !s;
+                           if (s)
+                               R->Options |= (optList[entry].flag);
+                           else
+                               R->Options &= ~(optList[entry].flag);
+                       }
+                   }
+                   break;
+               }
+           }
+    }
+    rewind(stream);
+}
+
+/*}}} */
+# endif                                /* ! USE_XGETDEFAULT */
+#endif                         /* NO_RESOURCES */
+
+/*{{{ read the resources files */
+/*
+ * using XGetDefault() or the hand-rolled replacement
+ */
+/* ARGSUSED */
+/* EXTPROTO */
+void
+rxvt_extract_resources(pR_ Display *display __attribute__((unused)), const char *name)
+{
+#ifndef NO_RESOURCES
+
+# if defined XAPPLOADDIR
+#  if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
+    /* Compute the path of the possibly available localized Rxvt file */ 
+    char           *localepath = NULL;
+
+    if (R->h->locale != NULL) {        /* XXX: must limit length of string */
+       localepath = (char *)rxvt_malloc(256); 
+       sprintf(localepath, XAPPLOADDIRLOCALE "/" APL_SUBCLASS,
+               (int)(258 - sizeof(XAPPLOADDIRLOCALE) - sizeof(APL_SUBCLASS)),
+               R->h->locale);  /* 258 = 255 + 4 (-.*s) - 1 (/) */
+    }
+
+    {
+#  endif
+# endif
+
+# ifdef USE_XGETDEFAULT
+/*
+ * get resources using the X library function
+ */
+    int             entry;
+
+#  ifdef XrmEnumOneLevel
+    int             i;
+    char           *displayResource, *xe;
+    XrmName         name_prefix[3];
+    XrmClass        class_prefix[3];
+    XrmDatabase     database, rdb1;
+    char            fname[1024];
+
+    XrmInitialize();
+    database = NULL;
+
+/* Get any Xserver defaults */
+
+    displayResource = XResourceManagerString(display);
+    if (displayResource != NULL)
+       database = XrmGetStringDatabase(displayResource);
+
+#   ifdef HAVE_EXTRA_XRESOURCE_FILES
+/* Add in ~/.Xdefaults or ~/.Xresources */
+    {
+       char           *ptr;
+
+       if ((ptr = (char *)getenv("HOME")) == NULL)
+           ptr = ".";
+
+       for (i = 0; i < (sizeof(xnames) / sizeof(xnames[0])); i++) {
+           sprintf(fname, "%-.*s/%s", sizeof(fname) - STRLEN(xnames[i]) - 2,
+                   ptr, xnames[i]);
+           if ((rdb1 = XrmGetFileDatabase(fname)) != NULL) {
+               XrmMergeDatabases(rdb1, &database);
+#    ifndef HAVE_BOTH_XRESOURCE_FILES
+               break;
+#    endif
+           }
+       }
+    }
+#   endif
+
+/* Add in XENVIRONMENT file */
+
+    if ((xe = (char *)getenv("XENVIRONMENT")) != NULL
+       && (rdb1 = XrmGetFileDatabase(xe)) != NULL)
+       XrmMergeDatabases(rdb1, &database);
+
+/* Add in Rxvt file */
+#   if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
+    if (localepath == NULL || (rdb1 = XrmGetFileDatabase(localepath)) == NULL)
+#   endif
+    rdb1 = XrmGetFileDatabase(XAPPLOADDIR "/" APL_SUBCLASS);
+    if (rdb1 != NULL)
+        XrmMergeDatabases(rdb1, &database);
+
+/* Add in $XAPPLRESDIR/Rxvt only; not bothering with XUSERFILESEARCHPATH */
+    if ((xe = (char *)getenv("XAPPLRESDIR")) != NULL) {
+       sprintf(fname, "%-.*s/" APL_SUBCLASS, sizeof(fname)
+               - sizeof(APL_SUBCLASS) - 2, xe);
+       if ((rdb1 = XrmGetFileDatabase(fname)) != NULL)
+           XrmMergeDatabases(rdb1, &database);
+    }
+
+    XrmSetDatabase(display, database);
+#  endif
+
+/*
+ * Query resources for options that affect us
+ */
+    for (entry = 0; entry < optList_size(); entry++) {
+       int             s;
+       char           *p, *p0;
+       const char     *kw = optList[entry].kw;
+
+       if (kw == NULL || R->h->rs[optList[entry].doff] != NULL)
+           continue;           /* previously set */
+
+       p = XGetDefault(display, name, kw);
+       p0 = XGetDefault(display, "!INVALIDPROGRAMMENAMEDONTMATCH!", kw);
+       if (p == NULL || (p0 && STRCMP(p, p0) == 0)) {
+           p = XGetDefault(display, APL_SUBCLASS, kw);
+           if (p == NULL || (p0 && STRCMP(p, p0) == 0))
+               p = XGetDefault(display, APL_CLASS, kw);
+       }
+       if (p == NULL && p0)
+           p = p0;
+       if (p) {
+           R->h->rs[optList[entry].doff] = p;
+
+           if (optList_isBool(entry)) {
+               s = STRCASECMP(p, "TRUE") == 0
+                   || STRCASECMP(p, "YES") == 0
+                   || STRCASECMP(p, "ON") == 0
+                   || STRCASECMP(p, "1") == 0;
+               if (optList_isReverse(entry))
+                   s = !s;
+               if (s)
+                   R->Options |= (optList[entry].flag);
+               else
+                   R->Options &= ~(optList[entry].flag);
+           }
+       }
+    }
+
+/*
+ * [R5 or later]: enumerate the resource database
+ */
+#  ifdef XrmEnumOneLevel
+#   ifdef KEYSYM_RESOURCE
+    name_prefix[0] = XrmStringToName(name);
+    name_prefix[1] = XrmStringToName("keysym");
+    name_prefix[2] = NULLQUARK;
+    class_prefix[0] = XrmStringToName(APL_SUBCLASS);
+    class_prefix[1] = XrmStringToName("Keysym");
+    class_prefix[2] = NULLQUARK;
+/* XXX: Need to check sizeof(rxvt_t) == sizeof(XPointer) */
+    XrmEnumerateDatabase(XrmGetDatabase(display), name_prefix, class_prefix,
+                        XrmEnumOneLevel, rxvt_define_key, NULL);
+    name_prefix[0] = XrmStringToName(APL_CLASS);
+    name_prefix[1] = XrmStringToName("keysym");
+    class_prefix[0] = XrmStringToName(APL_CLASS);
+    class_prefix[1] = XrmStringToName("Keysym");
+/* XXX: Need to check sizeof(rxvt_t) == sizeof(XPointer) */
+    XrmEnumerateDatabase(XrmGetDatabase(display), name_prefix, class_prefix,
+                        XrmEnumOneLevel, rxvt_define_key, NULL);
+#   endif
+#  endif
+
+# else                         /* USE_XGETDEFAULT */
+/* get resources the hard way, but save lots of memory */
+    FILE           *fd = NULL;
+    char           *home;
+
+    if ((home = getenv("HOME")) != NULL) {
+       unsigned int    i, len = STRLEN(home) + 2;
+       char           *f = NULL;
+
+       for (i = 0; i < (sizeof(xnames) / sizeof(xnames[0])); i++) {
+           f = (char *)rxvt_realloc(f, (len + STRLEN(xnames[i])) * sizeof(char));
+
+           sprintf(f, "%s/%s", home, xnames[i]);
+
+           if ((fd = fopen(f, "r")) != NULL)
+               break;
+       }
+       free(f);
+    }
+/*
+ * The normal order to match resources is the following:
+ * @ global resources (partial match, ~/.Xdefaults)
+ * @ application file resources (XAPPLOADDIR/Rxvt)
+ * @ class resources (~/.Xdefaults)
+ * @ private resources (~/.Xdefaults)
+ *
+ * However, for the hand-rolled resources, the matching algorithm
+ * checks if a resource string value has already been allocated
+ * and won't overwrite it with (in this case) a less specific
+ * resource value.
+ *
+ * This avoids multiple allocation.  Also, when we've called this
+ * routine command-line string options have already been applied so we
+ * needn't to allocate for those resources.
+ *
+ * So, search in resources from most to least specific.
+ *
+ * Also, use a special sub-class so that we can use either or both of
+ * "XTerm" and "Rxvt" as class names.
+ */
+
+    rxvt_get_xdefaults(aR_ fd, name);
+    rxvt_get_xdefaults(aR_ fd, APL_SUBCLASS);
+
+#  if defined(XAPPLOADDIR) && defined(USE_XAPPLOADDIR)
+    {
+       FILE           *ad = NULL;
+
+#   if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
+       if (localepath == NULL || (ad = fopen(localepath, "r")) == NULL)
+#   endif
+       ad = fopen(XAPPLOADDIR "/" APL_SUBCLASS, "r");
+       if (ad != NULL) {
+           rxvt_get_xdefaults(aR_ ad, APL_SUBCLASS);
+           rxvt_get_xdefaults(aR_ ad, "");
+           fclose(ad);
+       }
+    }
+#  endif                       /* XAPPLOADDIR */
+
+    rxvt_get_xdefaults(aR_ fd, APL_CLASS);
+    rxvt_get_xdefaults(aR_ fd, "");    /* partial match */
+    if (fd != NULL)
+       fclose(fd);
+# endif                                /* USE_XGETDEFAULT */
+
+# if defined XAPPLOADDIR
+#  if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
+    }
+
+    /* Free the path of the possibly available localized Rxvt file */ 
+    free(localepath);
+#  endif
+# endif
+
+#endif                         /* NO_RESOURCES */
+
+/*
+ * even without resources, at least do this setup for command-line
+ * options and command-line long options
+ */
+#ifdef MULTICHAR_SET
+    rxvt_set_multichar_encoding(aR_ R->h->rs[Rs_multichar_encoding]);
+#endif
+#ifdef GREEK_SUPPORT
+/* this could be a function in grkelot.c */
+/* void set_greek_keyboard (const char * str); */
+    if (R->h->rs[Rs_greek_keyboard]) {
+       if (!STRCMP(R->h->rs[Rs_greek_keyboard], "iso"))
+           greek_setmode(GREEK_ELOT928);       /* former -grk9 */
+       else if (!STRCMP(R->h->rs[Rs_greek_keyboard], "ibm"))
+           greek_setmode(GREEK_IBM437);        /* former -grk4 */
+    }
+    {
+       KeySym          sym;
+
+       if (R->h->rs[Rs_greektoggle_key]
+           && ((sym = XStringToKeysym(R->h->rs[Rs_greektoggle_key])) != 0))
+           R->h->ks_greekmodeswith = sym;
+    }
+#endif                         /* GREEK_SUPPORT */
+
+#if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
+    {
+       KeySym          sym;
+
+       if (R->h->rs[Rs_bigfont_key]
+           && ((sym = XStringToKeysym(R->h->rs[Rs_bigfont_key])) != 0))
+           R->h->ks_bigfont = sym;
+       if (R->h->rs[Rs_smallfont_key]
+           && ((sym = XStringToKeysym(R->h->rs[Rs_smallfont_key])) != 0))
+           R->h->ks_smallfont = sym;
+    }
+#endif
+}
+
+/*}}} */
+/*----------------------- end-of-file (C source) -----------------------*/
diff --git a/src/xpm.C b/src/xpm.C
new file mode 100644 (file)
index 0000000..be94d50
--- /dev/null
+++ b/src/xpm.C
@@ -0,0 +1,361 @@
+/*--------------------------------*-C-*---------------------------------*
+ * File:       xpm.c
+ *----------------------------------------------------------------------*
+ * $Id: xpm.C,v 1.1 2003-11-24 17:28:08 pcg Exp $
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1997      Carsten Haitzler <raster@zip.com.au>
+ * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
+ * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *---------------------------------------------------------------------*/
+
+#include "../config.h"         /* NECESSARY */
+#include "rxvt.h"              /* NECESSARY */
+#include "xpm.intpro"          /* PROTOS for internal routines */
+
+#ifdef XPM_BACKGROUND
+
+/*
+ * These GEOM strings indicate absolute size/position:
+ * @ `WxH+X+Y'
+ * @ `WxH+X'    -> Y = X
+ * @ `WxH'      -> Y = X = 50
+ * @ `W+X+Y'    -> H = W
+ * @ `W+X'      -> H = W, Y = X
+ * @ `W'        -> H = W, X = Y = 50
+ * @ `0xH'      -> H *= H/100, X = Y = 50 (W unchanged)
+ * @ `Wx0'      -> W *= W/100, X = Y = 50 (H unchanged)
+ * @ `=+X+Y'    -> (H, W unchanged)
+ * @ `=+X'      -> Y = X (H, W unchanged)
+ *
+ * These GEOM strings adjust position relative to current position:
+ * @ `+X+Y'
+ * @ `+X'       -> Y = X
+ *
+ * And this GEOM string is for querying current scale/position:
+ * @ `?'
+ */
+/* EXTPROTO */
+int
+rxvt_scale_pixmap(pR_ const char *geom)
+{
+    int             flags, changed = 0;
+    int             x = 0, y = 0;
+    unsigned int    w = 0, h = 0;
+    unsigned int    n;
+    char           *p, *str;
+    bgPixmap_t     *bgpixmap = &(R->h->bgPixmap);
+
+#define MAXLEN_GEOM            sizeof("[1000x1000+1000+1000]")
+
+    if (geom == NULL)
+       return 0;
+    str = rxvt_malloc(MAXLEN_GEOM + 1);
+    if (!STRCMP(geom, "?")) {
+       sprintf(str, "[%dx%d+%d+%d]",   /* can't presume snprintf() ! */
+               min(bgpixmap->w, 9999), min(bgpixmap->h, 9999),
+               min(bgpixmap->x, 9999), min(bgpixmap->y, 9999));
+       rxvt_xterm_seq(aR_ XTerm_title, str, CHAR_ST);
+       free(str);
+       return 0;
+    }
+
+    if ((p = STRCHR(geom, ';')) == NULL)
+       p = STRCHR(geom, '\0');
+    n = (p - geom);
+    if (n <= MAXLEN_GEOM) {
+       STRNCPY(str, geom, n);
+       str[n] = '\0';
+
+       flags = XParseGeometry(str, &x, &y, &w, &h);
+       if (!flags) {
+           flags |= WidthValue;
+           w = 0;
+       }                       /* default is tile */
+       if (flags & WidthValue) {
+           if (!(flags & XValue))
+               x = 50;
+           if (!(flags & HeightValue))
+               h = w;
+           if (w && !h) {
+               w = (bgpixmap->w * w) / 100;
+               h = bgpixmap->h;
+           } else if (h && !w) {
+               w = bgpixmap->w;
+               h = (bgpixmap->h * h) / 100;
+           }
+           if (w > 1000)
+               w = 1000;
+           if (h > 1000)
+               h = 1000;
+           if (bgpixmap->w != (short)w) {
+               bgpixmap->w = (short)w;
+               changed++;
+           }
+           if (bgpixmap->h != (short)h) {
+               bgpixmap->h = (short)h;
+               changed++;
+           }
+       }
+       if (!(flags & YValue)) {
+           if (flags & XNegative)
+               flags |= YNegative;
+           y = x;
+       }
+
+       if (!(flags & WidthValue) && geom[0] != '=') {
+           x += bgpixmap->x;
+           y += bgpixmap->y;
+       } else {
+           if (flags & XNegative)
+               x += 100;
+           if (flags & YNegative)
+               y += 100;
+       }
+       MIN_IT(x, 100);
+       MIN_IT(y, 100);
+       MAX_IT(x, 0);
+       MAX_IT(y, 0);
+       if (bgpixmap->x != x) {
+           bgpixmap->x = x;
+           changed++;
+       }
+       if (bgpixmap->y != y) {
+           bgpixmap->y = y;
+           changed++;
+       }
+    }
+    free(str);
+    return changed;
+}
+
+/* EXTPROTO */
+void
+rxvt_resize_pixmap(pR)
+{
+    XGCValues       gcvalue;
+    GC              gc;
+    unsigned int    width = TermWin_TotalWidth();
+    unsigned int    height = TermWin_TotalHeight();
+
+    if (R->TermWin.pixmap != None)
+       XFreePixmap(R->Xdisplay, R->TermWin.pixmap);
+
+    if (R->h->bgPixmap.pixmap == None) { /* So be it: I'm not using pixmaps */
+       R->TermWin.pixmap = None;
+       if (!(R->Options & Opt_transparent) || R->h->am_transparent == 0)
+           XSetWindowBackground(R->Xdisplay, R->TermWin.vt,
+                                R->PixColors[Color_bg]);
+       return;
+    }
+
+    gcvalue.foreground = R->PixColors[Color_bg];
+    gc = XCreateGC(R->Xdisplay, R->TermWin.vt, GCForeground, &gcvalue);
+
+    if (R->h->bgPixmap.pixmap != None) {       /* we have a specified pixmap */
+       unsigned int    w = R->h->bgPixmap.w, h = R->h->bgPixmap.h,
+                       x = R->h->bgPixmap.x, y = R->h->bgPixmap.y;
+        unsigned int    xpmh = R->h->xpmAttr.height,
+                       xpmw = R->h->xpmAttr.width;
+
+       /*
+        * don't zoom pixmap too much nor expand really small pixmaps
+        */
+       if (w > 1000 || h > 1000)
+           w = 1;
+       else if (width > (10 * xpmw)
+                || height > (10 * xpmh))
+           w = 0;              /* tile */
+
+       if (w == 0) {
+           /* basic X tiling - let the X server do it */
+           R->TermWin.pixmap = XCreatePixmap(R->Xdisplay, R->TermWin.vt,
+                                             xpmw, xpmh,
+                                             (unsigned int)XDEPTH);
+           XCopyArea(R->Xdisplay, R->h->bgPixmap.pixmap, R->TermWin.pixmap, gc,
+                     0, 0, xpmw, xpmh, 0, 0);
+       } else {
+           float           incr, p;
+           Pixmap          tmp;
+
+           R->TermWin.pixmap = XCreatePixmap(R->Xdisplay, R->TermWin.vt,
+                                             width, height,
+                                             (unsigned int)XDEPTH);
+           /*
+            * horizontal scaling
+            */
+           rxvt_pixmap_incr(&w, &x, &incr, &p, width, xpmw);
+
+           tmp = XCreatePixmap(R->Xdisplay, R->TermWin.vt,
+                               width, xpmh, (unsigned int)XDEPTH);
+           XFillRectangle(R->Xdisplay, tmp, gc, 0, 0, width,
+                          xpmh);
+
+           for ( /*nil */ ; x < w; x++, p += incr) {
+               if (p >= xpmw)
+                   p = 0;
+               /* copy one column from the original pixmap to the tmp pixmap */
+               XCopyArea(R->Xdisplay, R->h->bgPixmap.pixmap, tmp, gc,
+                         (int)p, 0, 1, xpmh, (int)x, 0);
+           }
+
+           /*
+            * vertical scaling
+            */
+           rxvt_pixmap_incr(&h, &y, &incr, &p, height, xpmh);
+
+           if (y > 0)
+               XFillRectangle(R->Xdisplay, R->TermWin.pixmap, gc, 0, 0, width,
+                              y);
+           if (h < height)
+               XFillRectangle(R->Xdisplay, R->TermWin.pixmap, gc, 0, (int)h,
+                              width, height - h + 1);
+           for ( /*nil */ ; y < h; y++, p += incr) {
+               if (p >= xpmh)
+                   p = 0;
+               /* copy one row from the tmp pixmap to the main pixmap */
+               XCopyArea(R->Xdisplay, tmp, R->TermWin.pixmap, gc,
+                         0, (int)p, width, 1, 0, (int)y);
+           }
+           XFreePixmap(R->Xdisplay, tmp);
+       }
+    }
+    XSetWindowBackgroundPixmap(R->Xdisplay, R->TermWin.vt, R->TermWin.pixmap);
+    XFreeGC(R->Xdisplay, gc);
+    R->h->am_transparent = 0;
+
+    XClearWindow(R->Xdisplay, R->TermWin.vt);
+
+    XSync(R->Xdisplay, False);
+}
+
+/*
+ * Calculate tiling sizes and increments
+ * At start, p == 0, incr == xpmwidthheight
+ */
+/* INTPROTO */
+void
+rxvt_pixmap_incr(unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
+{
+    unsigned int    cwh, cxy;
+    float           cincr, cp;
+
+    cp = 0;
+    cincr = (float)xpmwidthheight;
+    cxy = *xy;
+    cwh = *wh;
+    if (cwh == 1) {    /* display one image, no horizontal/vertical scaling */
+       cincr = (float)widthheight;
+       if (xpmwidthheight <= widthheight) {
+           cwh = xpmwidthheight;
+           cxy = (cxy * (widthheight - cwh)) / 100;    /* beware! order */
+           cwh += cxy;
+       } else {
+           cxy = 0;
+           cwh = widthheight;
+       }
+    } else if (cwh < 10) {     /* fit WH images across/down screen */
+       cincr *= cwh;
+       cxy = 0;
+       cwh = widthheight;
+    } else {
+       cincr *= 100.0 / cwh;
+       if (cwh < 100) {        /* contract */
+           float           pos;
+
+           cwh = (cwh * widthheight) / 100;
+           pos = (float)cxy / 100 * widthheight - (cwh / 2);
+
+           cxy = (widthheight - cwh);
+           if (pos <= 0)
+               cxy = 0;
+           else if (pos < cxy)
+               cxy = pos;
+           cwh += cxy;
+       } else {        /* expand */
+           if (cxy > 0) {      /* position */
+               float           pos;
+
+               pos = (float)cxy / 100 * xpmwidthheight - (cincr / 2);
+               cp = xpmwidthheight - cincr;
+               if (pos <= 0)
+                   cp = 0;
+               else if (pos < cp)
+                   cp = pos;
+           }
+           cxy = 0;
+           cwh = widthheight;
+       }
+    }
+    cincr /= widthheight;
+    *wh = cwh;
+    *xy = cxy;
+    *incr = cincr;
+    *p = cp;
+}
+
+/* EXTPROTO */
+Pixmap
+rxvt_set_bgPixmap(pR_ const char *file)
+{
+    char           *f;
+
+    assert(file != NULL);
+
+    if (R->h->bgPixmap.pixmap != None) {
+       XFreePixmap(R->Xdisplay, R->h->bgPixmap.pixmap);
+       R->h->bgPixmap.pixmap = None;
+    }
+    XSetWindowBackground(R->Xdisplay, R->TermWin.vt, R->PixColors[Color_bg]);
+
+    if (*file != '\0') {
+/*      XWindowAttributes attr; */
+
+       /*
+        * we already have the required attributes
+        */
+/*      XGetWindowAttributes(R->Xdisplay, R->TermWin.vt, &attr); */
+
+       R->h->xpmAttr.closeness = 30000;
+       R->h->xpmAttr.colormap = XCMAP;
+       R->h->xpmAttr.visual = XVISUAL;
+       R->h->xpmAttr.depth = XDEPTH;
+       R->h->xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual |
+                                  XpmDepth | XpmSize | XpmReturnPixels);
+
+       /* search environment variables here too */
+       f = (char *)rxvt_File_find(file, ".xpm", R->h->rs[Rs_path]);
+       if (f == NULL
+           || XpmReadFileToPixmap(R->Xdisplay, Xroot, f,
+                                  &R->h->bgPixmap.pixmap, NULL,
+                                  &R->h->xpmAttr)) {
+           char           *p;
+
+           /* semi-colon delimited */
+           if ((p = STRCHR(file, ';')) == NULL)
+               p = STRCHR(file, '\0');
+
+           rxvt_print_error("couldn't load XPM file \"%.*s\"", (p - file),
+                            file);
+       }
+       free(f);
+    }
+    rxvt_resize_pixmap(aR);
+    return R->h->bgPixmap.pixmap;
+}
+
+#endif                         /* XPM_BACKGROUND */