--- /dev/null
+# ./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
+
+# ------------------------------------------------------------------------
--- /dev/null
+dnl> $Id: aclocal.m4,v 1.1 2003-11-24 17:28:08 pcg Exp $
+
+builtin(include, xpm.m4)
+builtin(include, libtool.m4)
--- /dev/null
+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 ***
+"
--- /dev/null
+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
+])
--- /dev/null
+# 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
--- /dev/null
+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))
--- /dev/null
+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()
--- /dev/null
+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.
--- /dev/null
+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()
--- /dev/null
+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).
--- /dev/null
+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.
--- /dev/null
+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.
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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).
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
+
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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()
--- /dev/null
+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)
--- /dev/null
+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@)
--- /dev/null
+# $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
+
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
+
--- /dev/null
+/*
+ * $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_ */
--- /dev/null
+/*
+ * $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_ */
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+# 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
--- /dev/null
+/*
+ * $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) -----------------------*/
--- /dev/null
+/*
+ * $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) -----------------------*/
--- /dev/null
+/*
+ * $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) -----------------------*/
--- /dev/null
+/*---------------------------------*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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*
+ * $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_ */
--- /dev/null
+/*--------------------------------*-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 */
--- /dev/null
+/*
+ * $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_ */
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+# 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
+}
--- /dev/null
+# 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
+}
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*
+ * $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_ */
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/* 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
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*
+ * $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_ */
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*
+ * $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_ */
--- /dev/null
+/*--------------------------------*-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
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*--------------------------------*-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) -----------------------*/
--- /dev/null
+/*--------------------------------*-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 */