From 61a358583c752e37075f0058c4335e94ac06e129 Mon Sep 17 00:00:00 2001 From: pcg Date: Mon, 24 Nov 2003 17:28:07 +0000 Subject: [PATCH] *** empty log message *** --- Makefile.in | 118 + autoconf/aclocal.m4 | 4 + autoconf/configure.in | 1360 ++++++++++++ autoconf/xpm.m4 | 232 ++ doc/Makefile.in | 111 + doc/yodl/masonyodl.yo | 125 ++ doc/yodl/rxvt-colours.yo | 50 + doc/yodl/rxvt-environment.yo | 9 + doc/yodl/rxvt-files.yo | 8 + doc/yodl/rxvt-fonts.yo | 9 + doc/yodl/rxvt-login.yo | 7 + doc/yodl/rxvt-mousereporting.yo | 14 + doc/yodl/rxvt-options.yo | 191 ++ doc/yodl/rxvt-resources.yo | 303 +++ doc/yodl/rxvt-scrollbar.yo | 13 + doc/yodl/rxvt-textselection.yo | 18 + doc/yodl/rxvt.yo | 117 + doc/yodl/rxvtRef-csi.yo | 169 ++ doc/yodl/rxvtRef-definitions.yo | 22 + doc/yodl/rxvtRef-graphics.yo | 33 + doc/yodl/rxvtRef-keycodes.yo | 73 + doc/yodl/rxvtRef-menubar.yo | 283 +++ doc/yodl/rxvtRef-mouse.yo | 29 + doc/yodl/rxvtRef-privatemodes.yo | 164 ++ doc/yodl/rxvtRef-sequences.yo | 77 + doc/yodl/rxvtRef-values.yo | 41 + doc/yodl/rxvtRef-xpm.yo | 47 + doc/yodl/rxvtRef-xterm.yo | 67 + doc/yodl/rxvtRef.yo | 65 + doc/yodl/versioninfo.yo.in | 17 + src/Makefile.in | 235 ++ src/command.C | 3583 ++++++++++++++++++++++++++++++ src/command.h | 87 + src/defaultfont.h | 109 + src/feature.h | 475 ++++ src/graphics.C | 549 +++++ src/graphics/Makefile.in | 66 + src/graphics/grxlib.c | 205 ++ src/graphics/grxlib.h | 31 + src/graphics/qplot.c | 249 +++ src/grkelot.C | 428 ++++ src/grkelot.h | 43 + src/init.C | 1701 ++++++++++++++ src/init.h | 159 ++ src/logging.C | 430 ++++ src/logging.h | 34 + src/main.C | 1207 ++++++++++ src/makeextprotos-sed | 18 + src/makeintprotos-sed | 18 + src/menubar.C | 2252 +++++++++++++++++++ src/menubar.h | 88 + src/misc.C | 406 ++++ src/netdisp.C | 104 + src/protos.h | 57 + src/ptytty.C | 291 +++ src/rxvt.h | 1144 ++++++++++ src/rxvtgrx.h | 54 + src/rxvtlib.h.in | 345 +++ src/screen.C | 3383 ++++++++++++++++++++++++++++ src/scrollbar-next.C | 289 +++ src/scrollbar-rxvt.C | 188 ++ src/scrollbar-xterm.C | 86 + src/scrollbar.C | 224 ++ src/strings.C | 308 +++ src/xdefaults.C | 998 +++++++++ src/xpm.C | 361 +++ 66 files changed, 23981 insertions(+) create mode 100644 Makefile.in create mode 100644 autoconf/aclocal.m4 create mode 100644 autoconf/configure.in create mode 100644 autoconf/xpm.m4 create mode 100644 doc/Makefile.in create mode 100644 doc/yodl/masonyodl.yo create mode 100644 doc/yodl/rxvt-colours.yo create mode 100644 doc/yodl/rxvt-environment.yo create mode 100644 doc/yodl/rxvt-files.yo create mode 100644 doc/yodl/rxvt-fonts.yo create mode 100644 doc/yodl/rxvt-login.yo create mode 100644 doc/yodl/rxvt-mousereporting.yo create mode 100644 doc/yodl/rxvt-options.yo create mode 100644 doc/yodl/rxvt-resources.yo create mode 100644 doc/yodl/rxvt-scrollbar.yo create mode 100644 doc/yodl/rxvt-textselection.yo create mode 100644 doc/yodl/rxvt.yo create mode 100644 doc/yodl/rxvtRef-csi.yo create mode 100644 doc/yodl/rxvtRef-definitions.yo create mode 100644 doc/yodl/rxvtRef-graphics.yo create mode 100644 doc/yodl/rxvtRef-keycodes.yo create mode 100644 doc/yodl/rxvtRef-menubar.yo create mode 100644 doc/yodl/rxvtRef-mouse.yo create mode 100644 doc/yodl/rxvtRef-privatemodes.yo create mode 100644 doc/yodl/rxvtRef-sequences.yo create mode 100644 doc/yodl/rxvtRef-values.yo create mode 100644 doc/yodl/rxvtRef-xpm.yo create mode 100644 doc/yodl/rxvtRef-xterm.yo create mode 100644 doc/yodl/rxvtRef.yo create mode 100644 doc/yodl/versioninfo.yo.in create mode 100644 src/Makefile.in create mode 100644 src/command.C create mode 100644 src/command.h create mode 100644 src/defaultfont.h create mode 100644 src/feature.h create mode 100644 src/graphics.C create mode 100644 src/graphics/Makefile.in create mode 100644 src/graphics/grxlib.c create mode 100644 src/graphics/grxlib.h create mode 100644 src/graphics/qplot.c create mode 100644 src/grkelot.C create mode 100644 src/grkelot.h create mode 100644 src/init.C create mode 100644 src/init.h create mode 100644 src/logging.C create mode 100644 src/logging.h create mode 100644 src/main.C create mode 100644 src/makeextprotos-sed create mode 100644 src/makeintprotos-sed create mode 100644 src/menubar.C create mode 100644 src/menubar.h create mode 100644 src/misc.C create mode 100644 src/netdisp.C create mode 100644 src/protos.h create mode 100644 src/ptytty.C create mode 100644 src/rxvt.h create mode 100644 src/rxvtgrx.h create mode 100644 src/rxvtlib.h.in create mode 100644 src/screen.C create mode 100644 src/scrollbar-next.C create mode 100644 src/scrollbar-rxvt.C create mode 100644 src/scrollbar-xterm.C create mode 100644 src/scrollbar.C create mode 100644 src/strings.C create mode 100644 src/xdefaults.C create mode 100644 src/xpm.C diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..55266f55 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,118 @@ +# ./Makefile.in -*- Makefile -*- +# $Id: Makefile.in,v 1.1 2003-11-24 17:28:07 pcg Exp $ +@MCOMMON@ + +srcdir = @srcdir@ +VPATH = @srcdir@ +.PATH: @srcdir@ + +first_rule: all +dummy: + +subdirs = src doc src/graphics src/test +allsubdirs = W11 $(subdirs) + +DIST = INSTALL README.configure configure Makefile Makefile.in ChangeLog + +DIST_CFG = autoconf/aclocal.m4 autoconf/xpm.m4 autoconf/libtool.m4 \ + autoconf/configure.in autoconf/config.h.in \ + autoconf/Make.common.in autoconf/install-sh autoconf/mkinstalldirs \ + autoconf/config.guess autoconf/config.sub \ + autoconf/ltmain.sh \ + +MKDIR = $(srcdir)/autoconf/mkinstalldirs + +#------------------------------------------------------------------------- + +all allbin alldoc tags: + @if test x@host_os@ = xcygwin; then (cd W11; ${MAKE} $@) || exit 1; fi + @for I in ${subdirs}; do (cd $$I; ${MAKE} $@) || exit 1; done + +realclean: clean + $(RMF) config.h config.status config.log libtool + +clean: + $(RMF) *~ config.cache + $(RMF) -r autom4te.cache + @if test x@host_os@ = xcygwin; then (cd W11; ${MAKE} $@) || exit 1; fi + @for I in ${subdirs}; do (cd $$I; ${MAKE} $@) || exit 1; done + +# +# entry points for other programs +# +rxvt: + (cd src; ${MAKE}) + +clock: + (cd rclock; ${MAKE}) + +graphics qplot: + (cd src/graphics; ${MAKE} qplot) + +tests: + (cd src/test; ${MAKE} tests) + +#------------------------------------------------------------------------- +configure: autoconf/configure.in autoconf/aclocal.m4 autoconf/config.h.in + cd $(srcdir); + ./.prebuild + +config.status: + if test -x config.status; then config.status --recheck; \ + else $(SHELL) configure; fi + +autoconf/config.h.in: autoconf/configure.in + cd $(srcdir); + ./.prebuild + +installdirs: + $(MKDIR) $(DESTDIR)$(bindir) + $(MKDIR) $(DESTDIR)$(mandir) + +install: installdirs + @if test x@host_os@ = xcygwin; then (cd W11; ${MAKE} $@) || exit 1; fi + @for I in $(subdirs); do (cd $$I; $(MAKE) DESTDIR=$(DESTDIR) $@) || exit 1; done + +Makefiles: + $(SHELL) config.status + +cleandir: realclean + +# distclean goal is for making a clean source tree, but if you have run +# configure from a different directory, then doesn't destroy all your +# hardly compiled and linked stuff. That's why there is always $(srcdir)/ +# In that case most of those commands do nothing, except cleaning *~ +# and cleaning source links. +distclean: + (cd $(srcdir); $(RMF) *~ config.cache config.h config.log config.status libtool) + @for I in $(allsubdirs); do (cd $$I; $(MAKE) $@) || exit 1; done + (cd $(srcdir); $(RMF) Makefile autoconf/Make.common) + +distdirs: + mkdir ../$(VERNAME); + mkdir ../$(VERNAME)/autoconf; + @for I in $(allsubdirs); do (cd $$I; $(MAKE) $@ || (echo "Failed to make distclean in $$I"; exit 0) ); done + +distcopy: + $(CP) -p $(DIST) ../$(VERNAME); + $(CP) -p $(DIST_CFG) ../$(VERNAME)/autoconf; + @for I in $(allsubdirs); do (cd $$I; $(MAKE) $@) || exit 1; done + +distrib: configure autoconf/config.h.in distdirs distcopy + +tar.gz: ../$(VERNAME).tar.gz +../$(VERNAME).tar.gz: + (cd ..; tar cvf - $(VERNAME) | gzip -f9 > $(VERNAME).tar.gz) + +tar.Z: ../$(VERNAME).tar.Z +../$(VERNAME).tar.Z: + (cd ..; tar cvf - $(VERNAME) | compress > $(VERNAME).tar.Z) + +tar.bz2: ../$(VERNAME).tar.bz2 +../$(VERNAME).tar.bz2: + (cd ..; tar cvf - $(VERNAME) | bzip2 -f9 > $(VERNAME).tar.bz2) + +uuencode: tar.gz + uuencode ../$(VERNAME).tar.gz $(VERNAME).tar.gz > ../$(VERNAME).tgz.uu + +# ------------------------------------------------------------------------ diff --git a/autoconf/aclocal.m4 b/autoconf/aclocal.m4 new file mode 100644 index 00000000..1b08d45a --- /dev/null +++ b/autoconf/aclocal.m4 @@ -0,0 +1,4 @@ +dnl> $Id: aclocal.m4,v 1.1 2003-11-24 17:28:08 pcg Exp $ + +builtin(include, xpm.m4) +builtin(include, libtool.m4) diff --git a/autoconf/configure.in b/autoconf/configure.in new file mode 100644 index 00000000..f542ab83 --- /dev/null +++ b/autoconf/configure.in @@ -0,0 +1,1360 @@ +dnl# -*- sh -*- +dnl# +dnl# $Id: configure.in,v 1.1 2003-11-24 17:28:08 pcg Exp $ +dnl# +dnl# Process this file with autoconf to produce a configure script. +dnl# +AC_INIT(src/feature.h) +AC_CONFIG_AUX_DIR(autoconf) +AC_CONFIG_HEADER(config.h:autoconf/config.h.in) + +dnl RXVT version +changequote(, )dnl +VERSION=`sed -n -e 's/^.*[ \t]VERSION.*"\(.*\)"$/\1/p' ${srcdir}/src/version.h` +DATE=`sed -n -e 's/^.*[ \t]DATE.*"\(.*\)"$/\1/p' ${srcdir}/src/version.h` +LSMDATE=`sed -n -e 's/^.*[ \t]LSMDATE.*"\(.*\)"$/\1/p' ${srcdir}/src/version.h` +LIBVERSION=`sed -n -e 's/^.*[ \t]LIBVERSION.*"\(.*\)"$/\1/p' ${srcdir}/src/version.h` +changequote([, ])dnl +AC_SUBST(VERSION)dnl +AC_SUBST(DATE)dnl +AC_SUBST(LSMDATE)dnl +AC_SUBST(LIBVERSION)dnl +echo "" +echo "configuring for rxvt $VERSION" +echo "" + +dnl# Checks for programs. +dnl AC_MAKE_SET + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_AWK + +dnl# system hacks +AC_AIX +AC_ISC_POSIX + +AC_ENABLE_SHARED(no)dnl# libtool +AC_ENABLE_STATIC(yes)dnl# libtool +AC_PROG_LIBTOOL()dnl# libtool + +MALLOC_TYPE=S +support_addstrings=no +support_frills=no +support_linespace=no +support_graphics=no +support_inheritpixmap=no +support_keepscrolling=no +support_selectionscrolling=no +support_menubar=no +support_mousewheel=no +support_mouseslipwheel=no +support_oldselection=no +support_utmp=no +support_wtmp=no +support_lastlog=no +support_cursor_blink=no +support_pointer_blank=no +support_scroll_rxvt=no +support_scroll_next=no +support_scroll_xterm=no +support_xim=no +support_xpm=no +support_xft=no +support_unicode3=no +codesets= + +dnl# -------------------------------------------------------------------------- +dnl# CHECKING COMMAND LINE OPTIONS +dnl# -------------------------------------------------------------------------- + +if test "x$enable_shared" = xyes; then + AC_DEFINE(LIBRXVT, 1, Build shared library version - specify via configure only) + INSTALL_LIBRXVT=yes +fi +AC_SUBST(INSTALL_LIBRXVT) + +AC_ARG_ENABLE(everything, + [ --enable-everything enable standard non-multichoice features: marked * + NOTE: this option is order dependent + NOTE: automatically enabled with --enable-shared], + [if test x$enableval = xyes; then + support_24bit=yes + support_frills=yes + support_linespace=yes + support_graphics=yes + support_inheritpixmap=yes + support_keepscrolling=yes + support_selectionscrolling=yes + support_lastlog=yes + support_menubar=yes + support_mousewheel=yes + support_mouseslipwheel=yes + support_oldselection=yes + support_cursor_blink=yes + support_pointer_blank=yes + support_scroll_rxvt=yes + support_scroll_next=yes + support_scroll_xterm=yes + support_utmp=yes + support_wtmp=yes + support_xim=yes + support_xpm=yes + support_xft=yes + support_unicode3=yes + codesets=all + fi]) + +AC_ARG_ENABLE(unicode3, + [ --enable-unicode3 use 21 instead of 16 bits to represent unicode characters], + [if test x$enableval = xyes; then + support_unicode3=yes + fi]) + +AC_ARG_ENABLE(xft, + [ --enable-xft enable xft support on systems that have it], + [if test x$enableval = xyes; then + support_xft=yes + fi]) + +AC_ARG_WITH(codesets, + [ --with-codesets=NAME,... compile in additional codesets (hp,jp_ext,kr,cn,cn_ext,vn,all)], + [if test x$enableval = xyes; then + codesets="$withval" + fi]) + +AC_ARG_WITH(encoding, + [ --with-encoding=NAME set language default encoding to NAME (default: sjis) + (eucj|sjis|big5|gb|kr|noenc)], + [if test x$enableval = xyes; then + withval=`echo $withval | tr '[a-z]' '[A-Z]'` + AC_DEFINE_UNQUOTED(MULTICHAR_ENCODING, $withval, Define default multichar glyph encoding) + fi]) + +AC_ARG_ENABLE(utmp, + [ --enable-utmp enable utmp (utmpx) support *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_utmp=$enableval + fi]) + +AC_ARG_ENABLE(wtmp, + [ --enable-wtmp enable wtmp (wtmpx) support (requires --enable-utmp)*], + [if test x$enableval = xyes -o x$enableval = xno; then + support_wtmp=$enableval + fi]) + +AC_ARG_ENABLE(lastlog, + [ --enable-lastlog enable lastlog support (requires --enable-utmp) *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_lastlog=$enableval + fi]) + +AC_ARG_ENABLE(xpm-background, + [ --enable-xpm-background enable XPM background pixmaps *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_xpm=$enableval + fi]) + +AC_ARG_ENABLE(transparency, + [ --enable-transparency enable transparent backgrounds *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_inheritpixmap=$enableval + fi]) + +AC_ARG_ENABLE(menubar, + [ --enable-menubar enable menubar *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_menubar=$enableval + fi]) + +AC_ARG_ENABLE(graphics, + [ --enable-graphics enable rxvt own graphics mode (see src/graphics) *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_graphics=$enableval + fi]) + +AC_ARG_ENABLE(rxvt-scroll, + [ --enable-rxvt-scroll enable rxvt style scrollbar *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_scroll_rxvt=$enableval + fi]) + +AC_ARG_ENABLE(next-scroll, + [ --enable-next-scroll enable NeXT style scrollbar *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_scroll_next=$enableval + fi]) + +AC_ARG_ENABLE(xterm-scroll, + [ --enable-xterm-scroll enable Xterm style scrollbar *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_scroll_xterm=$enableval + fi]) + +AC_ARG_ENABLE(half-shadow, + [ --enable-half-shadow use half width/height shadow on rxvt scrollbar], + [if test x$enableval = xyes; then + AC_DEFINE(HALFSHADOW, 1, Define if you want the depth of scrollbars and menus to be less) + fi]) + +AC_ARG_ENABLE(xim, + [ --enable-xim XIM (X Input Method) protocol support *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_xim=$enableval + fi]) + +AC_ARG_ENABLE(greek, + [ --enable-greek enable greek keyboard support], + [if test x$enableval = xyes; then + AC_DEFINE(GREEK_SUPPORT, 1, Define if you want support for Greek Elot-928 & IBM-437 keyboard) + fi]) + +AC_ARG_ENABLE(ttygid, + [ --enable-ttygid enable tty setting to group named "tty"], + [if test x$enableval = xyes; then + AC_DEFINE(TTY_GID_SUPPORT, 1, Define to change gid of ttys to group tty) + fi]) + +AC_ARG_ENABLE(backspace-key, + [ --disable-backspace-key disable handling of the backspace key], + [if test x$enableval = xno; then + AC_DEFINE(NO_BACKSPACE_KEY, 1, Define if you don't want support for the backspace key) + fi]) + +AC_ARG_ENABLE(delete-key, + [ --disable-delete-key disable handling of the delete key], + [if test x$enableval = xno; then + AC_DEFINE(NO_DELETE_KEY, 1, Define if you don't want support for the (non-keypad) delete key) + fi]) + +AC_ARG_ENABLE(resources, + [ --disable-resources disable all resource checking], + [if test x$enableval = xno; then + AC_DEFINE(NO_RESOURCES, 1, Define if you don't want any resources read) + fi]) + +AC_ARG_ENABLE(xgetdefault, + [ --enable-xgetdefault enable resources via X instead of our small version], + [if test x$enableval = xyes; then + AC_DEFINE(USE_XGETDEFAULT, 1, Define if you want to use XGetDefault instead of our internal version) + fi]) + +AC_ARG_ENABLE(strings, + [ --enable-strings enable some replacement system functions], + [if test x$enableval = xyes -o x$enableval = xno; then + support_addstrings=$enableval + fi]) + +AC_ARG_ENABLE(swapscreen, + [ --disable-swapscreen disable swap screen support], + [if test x$enableval = xno; then + AC_DEFINE(NO_SECONDARY_SCREEN, 1, Disable the secondary screen. Many programs use the secondary screen as their workplace) + fi]) + +AC_ARG_ENABLE(frills, + [ --enable-frills enable support for rarely used features *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_frills=$enableval + fi]) + +AC_ARG_ENABLE(linespace, + [ --enable-linespace enable support for linespace *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_linespace=$enableval + fi]) + +AC_ARG_ENABLE(24bit, + [ --enable-24bit enable support for using 24bit visuals if available *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_24bit=$enableval + fi]) + +AC_ARG_ENABLE(keepscrolling, + [ --enable-keepscrolling enable continual scrolling on scrollbar arrow press *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_keepscrolling=$enableval + fi]) + +AC_ARG_ENABLE(selectionscrolling, + [ --enable-selectionscrolling enable scrolling during selections *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_selectionscrolling=$enableval + fi]) + +AC_ARG_ENABLE(mousewheel, + [ --enable-mousewheel enable scrolling via mouse wheel or buttons 4 & 5 *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_mousewheel=$enableval + fi]) + +AC_ARG_ENABLE(slipwheeling, + [ --enable-slipwheeling enable slip wheel scrolling (requires previous) *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_mouseslipwheel=$enableval + fi]) + +AC_ARG_ENABLE(old-selection, + [ --enable-old-selection enable v2.20 (& prior) mouse selection style support*], + [if test x$enableval = xyes -o x$enableval = xno; then + support_oldselection=$enableval + fi]) + +AC_ARG_ENABLE(new-selection, + [ --disable-new-selection disable new mouse (xterm) selection style support], + [if test x$enableval = xno; then + AC_DEFINE(NO_NEW_SELECTION, 1, Define to remove xterm style mouse selection) + fi]) + +AC_ARG_ENABLE(dmalloc, + [ --enable-dmalloc enable Gray Watson's malloc - for debugging use], + [if test x$enableval = xyes; then + MALLOC_TYPE=G + DEBUG=-DDEBUG_MALLOC + DLIB="-L/usr/local/lib -ldmalloc" + DINCLUDE=-I/usr/local/include + fi]) + +AC_ARG_ENABLE(dlmalloc, + [ --enable-dlmalloc enable Doug Lea's malloc - for production use + NOTE: enable only one malloc package], + [if test x$enableval = xyes; then + MALLOC_TYPE=D + DEBUG= + DLIB="-L/usr/local/lib -ldlmalloc" + DINCLUDE= + fi]) + +AC_ARG_ENABLE(smart-resize, + [ --enable-smart-resize enable smart growth/shrink behaviour], + [if test x$enableval = xyes; then + AC_DEFINE(SMART_RESIZE, 1, Define to use "smart" resize behavior) + fi]) + +AC_ARG_ENABLE(256-color, + [ --enable-256-color enable 256-color support], + [if test x$enableval = xyes; then + AC_DEFINE(TTY_256COLOR, 1, Define if you want 256 colour support) + fi]) + +AC_ARG_ENABLE(cursor-blink, + [ --enable-cursor-blink enable blinking cursor *], + [if test x$enableval = xyes -o x$enableval = xno; then + support_cursor_blink=$enableval + fi]) + +AC_ARG_ENABLE(pointer-blank, + [ --enable-pointer-blank enable pointer blank when typing or inactive pointer*], + [if test x$enableval = xyes -o x$enableval = xno; then + support_pointer_blank=$enableval + fi]) + +AC_ARG_WITH(term, + [ --with-term=NAME set the terminal to NAME (default \"xterm\")], + [if test x$withval != x; then + AC_DEFINE_UNQUOTED(TERMENV, "$withval",Set TERM to the value given by configure) term="$withval" + fi]) + +AC_ARG_WITH(terminfo, + [ --with-terminfo=PATH set the path to the terminfo tree to PATH], + [if test x$withval != x; then + AC_DEFINE_UNQUOTED(RXVT_TERMINFO, "$withval", Set TERMINFO value to the value given by configure) terminfo="$withval" + fi]) + +dnl# -------------------------------------------------------------------------- + +AC_DEFINE(PROTOTYPES, 1, Define if you need function prototypes) + +dnl# -------------------------------------------------------------------------- +dnl# Supply default CFLAGS, if not specified by `CFLAGS=flags ./configure' +dnl# +if test -z "$CFLAGS"; then + if test -z "$CCOPTS"; then + CCOPTS='-O' +dnl> if test "x$GCC" = xyes; then +dnl> if test x$system = xLinux; then +dnl> CCOPTS="$CCOPTS "'-O2 -fno-strength-reduce' +dnl> fi +dnl> fi + fi + CFLAGS="$CCOPTS" +fi + +AC_PATH_PROG(MV, mv, mv) +AC_PATH_PROG(RM, rm, rm) +AC_PATH_PROG(CP, cp, cp) +AC_PATH_PROG(LN, ln, ln) +AC_PATH_PROG(SED, sed, sed) +AC_PATH_PROG(ECHO, echo, echo) +AC_PATH_PROG(CMP, cmp, cmp) +AC_PATH_PROG(TBL, tbl) + +dnl# need a neat way to detect SVR4 or its features +dnl# in src/command.c we use these functions: +dnl# grantpt(), unlockpt(), ptsname(), which are defined in +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 and +AC_CACHE_CHECK(whether termios.h and sys/ioctl.h may both be included, rxvt_cv_header_sysioctl, +[AC_TRY_COMPILE([#include +#include +#ifdef HAVE_TERMIOS_H +#include +#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 ], [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 ], $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 +#include +#include ], +[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 +#include ], +[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 +#include ], +[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 +#include ], +[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 +#include ], +[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 +#include +#ifdef HAVE_LASTLOG_H +#include +#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 +#include +#ifdef HAVE_LASTLOG_H +#include +#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 +#include +#include +#include +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 +#include +#include +#include +#include +#ifdef HAVE_STRING_H +#include +#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 +#include +#ifdef HAVE_UTMP_H +#include +#endif +#include +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 +#ifdef HAVE_UTMPX_H +#include +#endif +#include +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 +#include +#ifdef HAVE_UTMPX_H +#include +#elif defined(HAVE_UTMP_H) +#include +#endif +#ifdef HAVE_LASTLOG_H +#include +#endif +#include +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 +#ifdef HAVE_UTMPX_H +#include +#endif +#include +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 +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 ], + [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 ], + [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 ], + [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 +#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 " +AC_DEFUN(RXVT_DEFINE_TO_INCLUDE, dnl +[if test "$$3" = "$4" -o "$$5" = "$6"; then + $1="#include <$2>" +else + $1="/* #include <$2> */" +fi dnl +AC_SUBST($1)]) + +RXVT_DEFINE_TO_INCLUDE(include_stdint_h, stdint.h, ac_cv_header_stdint_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_stdarg_h, stdarg.h, ac_cv_header_stdarg_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_stdlib_h, stdlib.h, ac_cv_header_stdlib_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_unistd_h, unistd.h, ac_cv_header_unistd_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_string_h, string.h, ac_cv_header_string_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_fcntl_h, fcntl.h, ac_cv_header_fcntl_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_util_h, util.h, ac_cv_header_util_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_assert_h, assert.h, ac_cv_header_assert_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_sys_ioctl_h, sys/ioctl.h, rxvt_cv_header_sysioctl, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_sys_select_h, sys/select.h, ac_cv_header_sys_select_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_sys_strredir_h, sys/strredir.h, ac_cv_header_sys_strredir_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_sys_time_h, sys/time.h, ac_cv_header_sys_time_h, yes, notset, dontmatch) +RXVT_DEFINE_TO_INCLUDE(include_time_h, time.h, ac_cv_header_sys_time_h, no, ac_cv_header_time, yes) + +if test x$support_xft = xyes; then + LIBS="$LIBS `pkg-config xft --libs`" + CFLAGS="$CFLAGS `pkg-config xft --cflags`" + CPPFLAGS="$CPPFLAGS `pkg-config xft --cflags`" + + AC_CHECK_HEADERS(X11/Xft/Xft.h,,[support_xft=no]) + AC_CHECK_LIB(Xft,XftDrawString32,,[support_xft=no]) + AC_DEFINE(XFT, 1, Define to enable xft support) +fi + +AC_OUTPUT(autoconf/Make.common \ +Makefile \ +doc/Makefile \ +src/Makefile \ +src/graphics/Makefile \ +src/test/Makefile \ +src/rxvtlib.h \ +W11/Makefile \ +) + +echo "Configuration: + + Rxvt version: $VERSION : $DATE + Source code location: $srcdir + Install path: ${prefix}/bin + Compiler: $CC + Compiler flags: $CFLAGS" + +if test "$MALLOC_TYPE" = S; then + echo " malloc support: system default" +fi +if test "$MALLOC_TYPE" = G; then + echo " malloc support: Gray Watson's dmalloc" +fi +if test "$MALLOC_TYPE" = D; then + echo " malloc support: Doug Lea's malloc" +fi + +if test x$support_xpm = xyes; then + echo " Xpm library: $XPM_LIBS" +fi + +echo " +The following are set in config.h +" +echo " pty/tty type: "$rxvt_cv_ptys +if test x$support_utmp != xyes; then + echo " utmp support: disabled +" +else + echo " utmp support: enabled + utmp file: $rxvt_cv_path_utmp + utmpx file: $rxvt_cv_path_utmpx + wtmp file: $rxvt_cv_path_wtmp + wtmpx file: $rxvt_cv_path_wtmpx + lastlog file: $rxvt_cv_path_lastlog + ttys/ttytab file: $rxvt_cv_path_ttytab +" +fi +if test x$term != x; then + echo " set TERM to: $term +" +fi +if test x$terminfo != x; then + echo " set TERMINFO to: $terminfo +" +fi +if test x$rxvt_cv_ptys = xUNKNOWN; then + echo ".----------------------------------------------------------------." + echo ". WARNING: could not determine pty/tty type. Do not build until ." + echo ". the appropriate PTYS_ARE_* is defined in config.h ." + echo ".----------------------------------------------------------------." +fi +if test x$support_xpm = xneedsmanualspecification; then + echo ".----------------------------------------------------------------." + echo ". WARNING: --enable-xpm-background was specified however the ." + echo ". XPM includes files and libraries could not be found. ." + echo ". XPM backgrounds are now being DISABLED! If you want ." + echo ". to use them you should rerun configure with the ." + echo ". appropriate --with-xpm-includes=/path/to/xpm/includes ." + echo ". and --with-xpm-library=/path/to/xpm/library lines. ." + echo ".----------------------------------------------------------------." +fi +if test x$support_xim = xyes -a x$rxvt_cv_func_xlocale = xno; then + echo ".----------------------------------------------------------------." + echo ". WARNING: --enable-xim was specified however the locale support ." + echo ". functions could not be found. ." + echo ". XIM is now being DISABLED! ." + echo ".----------------------------------------------------------------." +fi +echo " *** Please check src/feature.h for further options *** +" diff --git a/autoconf/xpm.m4 b/autoconf/xpm.m4 new file mode 100644 index 00000000..3bb74cb9 --- /dev/null +++ b/autoconf/xpm.m4 @@ -0,0 +1,232 @@ +dnl> $Id: xpm.m4,v 1.1 2003-11-24 17:28:08 pcg Exp $ +dnl> test to find the hard-to-find libXpm +dnl> mostly copied from AC_PATH_X & AC_PATH_DIRECT, but explictly set + +AC_DEFUN(VT_FIND_LIBXPM, +[ +AC_REQUIRE_CPP() + +# Initialize some more variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. + +# If we find XPM, set shell vars xpm_includes and xpm_libraries to the +# paths, otherwise set no_xpm=yes. +# Uses ac_ vars as temps to allow command line to override cache and checks. +AC_MSG_CHECKING(for libXpm) + +AC_ARG_WITH(xpm_includes, + [ --with-xpm-includes=DIR use XPM includes in DIR], + xpm_includes="$withval", xpm_includes=NO) +AC_ARG_WITH(xpm_library, + [ --with-xpm-library=DIR use XPM library in DIR], + xpm_libraries="$withval", xpm_libraries=NO) + +# --without-xpm overrides everything else, but does not touch the cache. +AC_ARG_WITH(xpm, + [ --with-xpm use XPM]) +if test "$with_xpm" = no; then + have_xpm=disabled +else + AC_CACHE_VAL(ac_cv_have_xpm, [ + vt_xpm_include_X11=no + if test -n "$xpm_includes"; then + vt_xpm_includes=$xpm_includes + else + vt_xpm_includes=NO + fi + if test -n "$xpm_libraries"; then + vt_xpm_libraries=$xpm_libraries + else + vt_xpm_libraries=NO + fi + + VT_XPM_DIRECT + + if test "$vt_xpm_includes" = NO -o "$vt_xpm_libraries" = NO; then + ac_cv_have_xpm="have_xpm=no" + else + ac_cv_have_xpm="have_xpm=yes \ + vt_xpm_includes=$vt_xpm_includes vt_xpm_libraries=$vt_xpm_libraries \ + vt_xpm_include_X11=$vt_xpm_include_X11" + fi])dnl + eval "$ac_cv_have_xpm" +fi + +if test "$have_xpm" != yes; then + AC_MSG_RESULT($have_xpm) + no_xpm=yes +else + if test "$xpm_includes" != NO; then + if test "$xpm_includes" = "$vt_xpm_includes"; then + if test -r "$xpm_includes/X11/xpm.h"; then + vt_xpm_include_X11=yes + fi + else + vt_xpm_include_X11=no + if test -z "$xpm_includes"; then + AC_TRY_CPP([#include ], + 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 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 ], +[# We can compile using X headers with no special include directory. +vt_xpm_includes= +vt_xpm_include_X11=yes], +[CPPFLAGS="$ac_save_CPPFLAGS" +# Look for the header file in a standard set of common directories. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/X11/xpm.h"; then + vt_xpm_includes="$ac_dir" + vt_xpm_include_X11=yes + break + else + if test -r "$ac_dir/xpm.h"; then + vt_xpm_includes=$ac_dir + break + fi + fi + done]) +fi + +if test "$vt_xpm_libraries" = NO; then + # Check for the libraries. + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="$LIBS $X_LIBS -lXpm -lX11" +AC_TRY_LINK(, [XpmReadFileToPixmap()], +[LIBS="$ac_save_LIBS" +# We can link libXpm with no special library path. +vt_xpm_libraries=], +[LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +for ac_dir in \ + `echo "$vt_xpm_includes" | sed 's,include/X11,lib,;s,include,lib,'` \ + /usr/X11/lib \ + /usr/X11R6/lib \ + /usr/X11R5/lib \ + /usr/X11R4/lib \ + \ + /usr/lib/X11 \ + /usr/lib/X11R6 \ + /usr/lib/X11R5 \ + /usr/lib/X11R4 \ + \ + /usr/local/X11/lib \ + /usr/local/X11R6/lib \ + /usr/local/X11R5/lib \ + /usr/local/X11R4/lib \ + \ + /usr/local/lib/X11 \ + /usr/local/lib/X11R6 \ + /usr/local/lib/X11R5 \ + /usr/local/lib/X11R4 \ + \ + /usr/X386/lib \ + /usr/x386/lib \ + /usr/XFree86/lib/X11 \ + \ + /usr/lib \ + /usr/local/lib \ + /usr/unsupported/lib \ + /usr/athena/lib \ + /usr/local/x11r5/lib \ + /usr/lpp/Xamples/lib \ + \ + /usr/openwin/lib \ + /usr/openwin/share/lib \ + ; \ +do +dnl XXX Shouldn't this really use AC_TRY_LINK to be portable & robust?? + for ac_extension in a so sl; do + if test -r $ac_dir/libXpm.$ac_extension; then + vt_xpm_libraries=$ac_dir + break 2 + fi + done +done]) +fi +]) diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 00000000..2652ded6 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,111 @@ +# doc/Makefile.in -*- Makefile -*- +# $Id: Makefile.in,v 1.1 2003-11-24 17:28:08 pcg Exp $ +@MCOMMON@ + +srcdir = @srcdir@ +VPATH = @srcdir@ +.PATH: @srcdir@ + +basedir = .. +thisdir = doc + +first_rule: all +dummy: + +# +# Distribution variables +# + +YODL_RXVT = yodl/rxvt-colours.yo yodl/rxvt-environment.yo\ + yodl/rxvt-files.yo yodl/rxvt-fonts.yo yodl/rxvt-login.yo\ + yodl/rxvt-mousereporting.yo yodl/rxvt-options.yo\ + yodl/rxvt-resources.yo yodl/rxvt-scrollbar.yo\ + yodl/rxvt-textselection.yo +YODL_RREF = yodl/rxvtRef-csi.yo yodl/rxvtRef-definitions.yo\ + yodl/rxvtRef-graphics.yo yodl/rxvtRef-keycodes.yo\ + yodl/rxvtRef-menubar.yo yodl/rxvtRef-mouse.yo\ + yodl/rxvtRef-privatemodes.yo yodl/rxvtRef-sequences.yo\ + yodl/rxvtRef-values.yo yodl/rxvtRef-xpm.yo yodl/rxvtRef-xterm.yo + +DIST_ETC = etc/rxvt.termcap etc/rxvt.terminfo etc/XTerm.ad +DIST_YODL = yodl/masonyodl.yo yodl/versioninfo.yo yodl/versioninfo.yo.in\ + $(YODL_RXVT) yodl/rxvt.yo $(YODL_RREF) yodl/rxvtRef.yo +DIST_MENU = menu/menu menu/example.menu menu/rxvt.menu menu/rxvt.zh-menu\ + menu/terminal.menu menu/jedmenu.sl +DIST = Makefile.in README.greek README.menu README.xvt BUGS FAQ TODO\ + changes.txt xterm.seq LSM.in rxvt.1 rxvt.tbl rxvtRef.txt\ + rxvtRef.html rxvtRef-frame.html rxvtRef-toc.html rxvt.html + +#------------------------------------------------------------------------- + +all: rxvt.1 + +rxvt.1: rxvt.tbl Makefile + @if test x$(TBL) = x; then : ; else echo "$(TBL) $(srcdir)/rxvt.tbl | grep -v '^.lf' > rxvt.1"; $(TBL) $(srcdir)/rxvt.tbl | grep -v '^.lf' > rxvt.1 ; fi + +SEDREPLACE = -e 's%@RXVT_VERSION@%$(VERSION)%g;'\ + -e 's%@RXVT_LSMDATE@%$(LSMDATE)%g;'\ + -e 's%@RXVT_DATE@%$(DATE)%g;'\ + -e 's%@RXVT_MAINTEMAIL@%$(MAINTEMAIL)%g;'\ + -e 's%@RXVT_MAINT@%$(MAINT)%g;'\ + -e 's%@RXVT_WEBPAGE@%$(WEBPAGE)%g;'\ + -e 's%@RXVT_WEBMAINTEMAIL@%$(WEBMAINTEMAIL)%g;'\ + -e 's%@RXVT_WEBMAINT@%$(WEBMAINT)%g;'\ + -e 's%@RXVT_FTPSITENAME@%$(FTPSITENAME)%g;'\ + -e 's%@RXVT_FTPSITEDIR@%$(FTPSITEDIR)%g;' + +tags allbin: + +alldoc: $(basedir)/$(VERNAME).lsm yodl/versioninfo.yo rxvt.1 rxvt.html rxvtRef.html rxvtRef.txt + +yodl/versioninfo.yo: yodl/versioninfo.yo.in ../src/version.h + $(SED) $(SEDREPLACE) < $(srcdir)/yodl/versioninfo.yo.in > $@ + +$(basedir)/$(VERNAME).lsm: LSM.in $(srcdir)/../autoconf/Make.common.in $(srcdir)/../src/version.h + $(SED) $(SEDREPLACE) < $(srcdir)/LSM.in > $@ + +rxvt.tbl: yodl/rxvt.yo $(YODL_RXVT) yodl/masonyodl.yo + (cd $(srcdir)/yodl; yodl2man -o../rxvt.tbl rxvt.yo) + +rxvt.html: yodl/rxvt.yo $(YODL_RXVT) yodl/masonyodl.yo + (cd $(srcdir)/yodl; yodl2html -o../rxvt.html rxvt.yo) + +rxvtRef.html: $(YODL_RREF) yodl/rxvtRef.yo yodl/masonyodl.yo + (cd $(srcdir)/yodl; yodl2html -o../rxvtRef.html rxvtRef.yo) + +rxvtRef.txt: $(YODL_RREF) yodl/rxvtRef.yo yodl/masonyodl.yo + (cd $(srcdir)/yodl; yodl2txt -o../rxvtRef.txt rxvtRef.yo) + +clean: + $(RMF) rxvt.man *~ yodl/*~ + +realclean: clean + $(RMF) tags rxvt.1 rxvt.html rxvtRef.html rxvtRef.txt + +cleandir: realclean + +distclean: + +install: + $(INSTALL_DATA) rxvt.1 $(DESTDIR)$(mandir)/$(RXVTNAME).$(manext) + +uninstall: + -(cd $(mandir); $(RMF) $(RXVTNAME).$(manext) ) + +distdirs: + mkdir $(basedir)/../$(VERNAME)/$(thisdir) + mkdir $(basedir)/../$(VERNAME)/$(thisdir)/etc + mkdir $(basedir)/../$(VERNAME)/$(thisdir)/menu + mkdir $(basedir)/../$(VERNAME)/$(thisdir)/yodl + +distcopy: realclean distdepend + $(CP) -p $(basedir)/$(VERNAME).lsm $(basedir)/../$(VERNAME); + $(CP) -p $(DIST) $(basedir)/../$(VERNAME)/$(thisdir) + $(CP) -p $(DIST_ETC) $(basedir)/../$(VERNAME)/$(thisdir)/etc + $(CP) -p $(DIST_MENU) $(basedir)/../$(VERNAME)/$(thisdir)/menu + $(CP) -p $(DIST_YODL) $(basedir)/../$(VERNAME)/$(thisdir)/yodl + +distdepend: alldoc + +# ------------------------------------------------------------------------ +# DO NOT DELETE: ugly dependency list follows diff --git a/doc/yodl/masonyodl.yo b/doc/yodl/masonyodl.yo new file mode 100644 index 00000000..38d1cc62 --- /dev/null +++ b/doc/yodl/masonyodl.yo @@ -0,0 +1,125 @@ +COMMENT(-- $Id: masonyodl.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------- +-- We want more functionality and some better layout +-- proto changes: +-- starttable(nColumns)(Alignment)(borderwidth) +------------------------------------------------------------------------------) +NEWCOUNTER(RRindentlevel) +NEWCOUNTER(RRnl) +SETCOUNTER(RRindentlevel)(0) +\ +DEFINEMACRO(nltxt)(0)(\ + IFZERO(RRnl)()( ADDTOCOUNTER(RRnl)(-1)nltxt())) +\ +UNDEFINEMACRO(XXnl) +DEFINEMACRO(XXnl)(0)(\ + NOTRANS( +)\ + whentxt(SETCOUNTER(RRnl)(RRindentlevel)nltxt())) +\ +DEFINEMACRO(P)(0)(\ + SETCOUNTER(RRnl)(0)\ + whenhtml(SETCOUNTER(RRnl)(1)htmlcommand(

))\ + IFZERO(RRnl)(nl())()) +\ +UNDEFINEMACRO(starttable) +DEFINEMACRO(starttable)(3)(\ + SETCOUNTER(XXtablewidth)(ARG1)\ + whenhtml(IFZERO(ARG3)(htmlcommand())\ + (htmlcommand(
))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
, 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() 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: +, so that's fairly easy. If we're already at the last +cell, we need . +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() 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(
    )ARG1+htmlcommand(
))\ + whentxt(ADDTOCOUNTER(RRindentlevel)(4)ARG1+ADDTOCOUNTER(RRindentlevel)(-4))\ + whenman(roffcmd(.RS)()()()roffcmd(.HP)()()()ARG1+roffcmd(.RE)()()())\ + whenms()) +\ +DEFINEMACRO(startdl)(0)(\ + whenhtml(htmlcommand(
))\ + whentxt(ADDTOCOUNTER(RRindentlevel)(4))\ + whenman(startdit())) +\ +DEFINEMACRO(enddl)(0)(\ + whenhtml(htmlcommand(
))\ + whentxt(ADDTOCOUNTER(RRindentlevel)(-4))\ + whenman(enddit())) +\ +DEFINEMACRO(dl)(2)(\ + whenhtml(htmlcommand(
)ARG1+htmlcommand(
)\ + ARG2+htmlcommand(
))\ + whentxt(ADDTOCOUNTER(RRindentlevel)(2)dit(ARG1)\ + ADDTOCOUNTER(RRindentlevel)(2)nl()\ + ARG2+ADDTOCOUNTER(RRindentlevel)(-4))\ + whenman(dit(ARG1)ARG2)) +\ +DEFINEMACRO(manpageauthors)(0)(\ + manpagesection(AUTHORS)\ + DEFINESYMBOL(XXmanpageAuthor)) diff --git a/doc/yodl/rxvt-colours.yo b/doc/yodl/rxvt-colours.yo new file mode 100644 index 00000000..89520411 --- /dev/null +++ b/doc/yodl/rxvt-colours.yo @@ -0,0 +1,50 @@ +COMMENT(-- $Id: rxvt-colours.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(COLORS AND GRAPHICS) + +If graphics support was enabled at compile-time, bf(rxvt) can be queried +with ANSI escape sequences and can address individual pixels instead of +text characters. Note the graphics support is still considered beta code. + +In addition to the default foreground and background colours, bf(rxvt) +can display up to 16 colours (8 ANSI colours plus high-intensity bold/blink +versions of the same). +Here is a list of the colours with their bf(rgb.txt) names. + +starttable(3)(l l l)(0)\ + row(cell(bf(color0))cell((black))cell(= Black))\ + row(cell(bf(color1))cell((red))cell(= Red3))\ + row(cell(bf(color2))cell((green))cell(= Green3))\ + row(cell(bf(color3))cell((yellow))cell(= Yellow3))\ + row(cell(bf(color4))cell((blue))cell(= Blue3))\ + row(cell(bf(color5))cell((magenta))cell(= Magenta3))\ + row(cell(bf(color6))cell((cyan))cell(= Cyan3))\ + row(cell(bf(color7))cell((white))cell(= AntiqueWhite))\ + row(cell(bf(color8))cell((bright black))cell(= Grey25))\ + row(cell(bf(color9))cell((bright red))cell(= Red))\ + row(cell(bf(color10))cell((bright green))cell(= Green))\ + row(cell(bf(color11))cell((bright yellow))cell(= Yellow))\ + row(cell(bf(color12))cell((bright blue))cell(= Blue))\ + row(cell(bf(color13))cell((bright magenta))cell(= Magenta))\ + row(cell(bf(color14))cell((bright cyan))cell(= Cyan))\ + row(cell(bf(color15))cell((bright white))cell(= White))\ + row(cell(bf(foreground))cell()cell(= Black))\ + row(cell(bf(background))cell()cell(= White))\ +endtable() + +It is also possible to specify the colour values of bf(foreground), +bf(background), bf(cursorColor), bf(cursorColor2), bf(colorBD), bf(colorUL) +as a number 0-15, as a convenient shorthand to reference the colour name of +color0-color15. + +Note that bf(-rv) (bf("reverseVideo: True")) simulates reverse video by +always swapping the foreground/background colours. This is in contrast to +em(xterm)(1) where the colours are only swapped if they have not otherwise been +specified. +For example, + +startdit() + dit(bf(rxvt -fg Black -bg White -rv)) + would yield White on Black, while on em(xterm)(1) it would yield + Black on White. +enddit() diff --git a/doc/yodl/rxvt-environment.yo b/doc/yodl/rxvt-environment.yo new file mode 100644 index 00000000..b5b6a7c5 --- /dev/null +++ b/doc/yodl/rxvt-environment.yo @@ -0,0 +1,9 @@ +COMMENT(-- $Id: rxvt-environment.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(ENVIRONMENT) + +bf(rxvt) sets the environment variables bf(TERM), bf(COLORTERM) and +bf(COLORFGBG). The environment variable bf(WINDOWID) is set to the X window +id number of the bf(rxvt) window and it also uses and sets the environment +variable bf(DISPLAY) to specify which display terminal to use. bf(rxvt) uses +the environment variables bf(RXVTPATH) and bf(PATH) to find XPM files. diff --git a/doc/yodl/rxvt-files.yo b/doc/yodl/rxvt-files.yo new file mode 100644 index 00000000..d0f0102b --- /dev/null +++ b/doc/yodl/rxvt-files.yo @@ -0,0 +1,8 @@ +COMMENT(-- $Id: rxvt-files.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(FILES) + +startdit() + dit(bf(/etc/utmp)) System file for login records. + dit(bf(/usr/lib/X11/rgb.txt)) Color names. +enddit() diff --git a/doc/yodl/rxvt-fonts.yo b/doc/yodl/rxvt-fonts.yo new file mode 100644 index 00000000..c5b8f87a --- /dev/null +++ b/doc/yodl/rxvt-fonts.yo @@ -0,0 +1,9 @@ +COMMENT(-- $Id: rxvt-fonts.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(CHANGING FONTS) + +You can change fonts on-the-fly, which is to say cycle through the default +font and others of various sizes, by using bf(Shift-KP_Add) and +bf(Shift-KP_Subtract). Or, alternatively (if enabled) with +bf(HOTKEY()-BIGFONT()) and bf(HOTKEY()-SMALLFONT()), where the actual key +can be selected using resources bf(smallfont_key)/bf(bigfont_key). diff --git a/doc/yodl/rxvt-login.yo b/doc/yodl/rxvt-login.yo new file mode 100644 index 00000000..68680979 --- /dev/null +++ b/doc/yodl/rxvt-login.yo @@ -0,0 +1,7 @@ +COMMENT(-- $Id: rxvt-login.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(LOGIN STAMP) + +bf(rxvt) tries to write an entry into the em(utmp)(5) file so that it can be +seen via the em(who(1)) command, and can accept messages. To allow this +feature, bf(rxvt) must be installed setuid root on some systems. diff --git a/doc/yodl/rxvt-mousereporting.yo b/doc/yodl/rxvt-mousereporting.yo new file mode 100644 index 00000000..7dd2a6b7 --- /dev/null +++ b/doc/yodl/rxvt-mousereporting.yo @@ -0,0 +1,14 @@ +COMMENT(-- $Id: rxvt-mousereporting.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(MOUSE REPORTING) + +To temporarily override mouse reporting, for either the scrollbar or the +normal text selection/insertion, hold either the Shift or the Meta (Alt) key +while performing the desired mouse action. + +If mouse reporting mode is active, the normal scrollbar actions are disabled +-- on the assumption that we are using a fullscreen application. +Instead, pressing Button1 and Button3 sends +bf(ESC[6~) (Next) and bf(ESC[5~) (Prior), respectively. +Similarly, clicking on the up and down arrows sends bf(ESC[A) (Up) and +bf(ESC[B) (Down), respectively. diff --git a/doc/yodl/rxvt-options.yo b/doc/yodl/rxvt-options.yo new file mode 100644 index 00000000..e7f7f403 --- /dev/null +++ b/doc/yodl/rxvt-options.yo @@ -0,0 +1,191 @@ +COMMENT(-- $Id: rxvt-options.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpageoptions() + +The bf(rxvt) options (mostly a subset of em(xterm)'s) are listed below. +In keeping with the smaller-is-better philosophy, options may be eliminated +or default values chosen at compile-time, so options and defaults listed +may not accurately reflect the version installed on your system. +`rxvt -h' gives a list of major compile-time options on the em(Options) line. +Option descriptions may be prefixed with which compile option each is +dependent upon. e.g. `Compile em(XIM):' requires em(XIM) on the em(Options) +line. Note: `rxvt -help' gives a list of all command-line options compiled +into your version. + +Note that bf(rxvt) permits the resource name to be used as a long-option +(--/++ option) so the potential command-line options are far greater than +those listed. +For example: `rxvt --loginShell --color1 Orange'. + +Also note that if you do not explictly specify a font (bf(-fn) and bf(-fm)) +or a multichar encoding method (bf(-km)), rxvt will select a font for the +preferable encoding according to your locale. Supported encodings are: +bf(ISO-8859-)n (n=bf(1)...bf(15)), bf(KOI8-R), bf(KOI8-U), bf(EUC-JP), +bf(Shift_JIS), bf(EUC-KR), bf(EUC-CN) (aka bf(GB)), and bf(Big5). + +The following options are available: + +startdit() + dit(bf(-help), bf(--help)) + Print out a message describing available options. + dit(bf(-display) em(displayname)) + Attempt to open a window on the named X display (bf(-d) still + respected). In the absence of this option, the display specified + by the bf(DISPLAY) environment variable is used. + dit(bf(-geometry) em(geom)) + Window geometry (bf(-g) still respected); + resource bf(geometry). + dit(bf(-rv)|bf(+rv)) + Turn on/off simulated reverse video; + resource bf(reverseVideo). + dit(bf(-j)|bf(+j)) + Turn on/off jump scrolling; + resource bf(jumpScroll). + dit(bf(-ip)|bf(+ip)) + Turn on/off inheriting parent window's pixmap. Alternative form + is bf(-tr); + resource bf(inheritPixmap). + dit(bf(-bg) em(colour)) + Window background colour; + resource bf(background). + dit(bf(-fg) em(colour)) + Window foreground colour; + resource bf(foreground). + dit(bf(-pixmap:) em(file[;geom])) + Compile em(XPM): Specify XPM file for the background and also + optionally specify its scaling with a geometry string. Note you + may need to add quotes to avoid special shell interpretation of + the `;' in the command-line; + resource bf(backgroundPixmap). + dit(bf(-cr) em(colour)) + The cursor colour; + resource bf(cursorColor). + dit(bf(-pr) em(colour)) + The mouse pointer colour; + resource bf(pointerColor). + dit(bf(-bd) em(colour)) + The colour of the border between the xterm scrollbar and the text; + resource bf(borderColor). + dit(bf(-fn) em(fontname)) + Main normal text font; + resource bf(font). + dit(bf(-fb) em(fontname)) + Main bold text font; + resource bf(boldFont). + dit(bf(-fm) em(fontname)) + Main multicharacter font; + resource bf(mfont). + dit(bf(-km) em(mode)) + Compile em(multichar_languages): + Multiple-character font-set encoding mode; + bf(eucj): EUC Japanese encoding. + bf(sjis): Shift JIS encoding. + bf(big5): BIG5 encoding. + bf(gb): GB encoding. + bf(kr): EUC Korean encoding. + bf(noenc): no encoding; + resource bf(multichar_encoding). + dit(bf(-grk) em(mode)) + Compile em(Greek): Greek keyboard translation; + bf(iso): ISO-8859 mapping. + bf(ibm): IBM-437 mapping; + resource bf(greek_keyboard). + dit(bf(-name) em(name)) + Specify the application name under which resources + are to be obtained, rather than the default executable file name. + Name should not contain `.' or `*' characters. + Also sets the icon and title name. + dit(bf(-ls)|bf(+ls)) + Start as a login-shell/sub-shell; + resource bf(loginShell). + dit(bf(-ut)|bf(+ut)) + Compile em(utmp): Inhibit/enable writing a utmp entry; + resource bf(utmpInhibit). + dit(bf(-vb)|bf(+vb)) + Turn on/off visual bell on receipt of a bell character; + resource bf(visualBell). + dit(bf(-sb)|bf(+sb)) + Turn on/off scrollbar; + resource bf(scrollBar). + dit(bf(-si)|bf(+si)) + Turn on/off scroll-to-bottom on TTY output inhibit; + resource bf(scrollTtyOutput) has opposite effect. + dit(bf(-sk)|bf(+sk)) + Turn on/off scroll-to-bottom on keypress; + resource bf(scrollTtyKeypress). + dit(bf(-sw)|bf(+sw)) + Turn on/off scrolling with the scrollback buffer as new + lines appear. This only takes effect if bf(-si) is also given; + resource bf(scrollWithBuffer). + dit(bf(-sr)|bf(+sr)) + Put scrollbar on right/left; + resource bf(scrollBar_right). + dit(bf(-st)|bf(+st)) + Display normal (non XTerm/NeXT) scrollbar without/with a trough; + resource bf(scrollBar_floating). + dit(bf(-mcc)|bf(+mcc)) + Compile em(multichar_languages): treat multibyte glyphs as single + character for backspace, delete and cursor movement keys; + resource bf(multibyte_cursor). + dit(bf(-bc)|bf(+bc)) + Blink the cursor; resource bf(cursorBlink). + dit(bf(-iconic)) + Start iconified, if the window manager supports that option. + Alternative form is bf(-ic). + dit(bf(-sl) em(number)) + Save em(number) lines in the scrollback buffer. See resource entry + for limits; + resource bf(saveLines). + dit(bf(-b) em(number)) + Compile em(frills): Internal border of em(number) pixels. See + resource entry for limits; + resource bf(internalBorder). + dit(bf(-w) em(number)) + Compile em(frills): External border of em(number) pixels. + Also, bf(-bw) and bf(-borderwidth). See resource entry for limits; + resource bf(externalBorder). + dit(bf(-lsp) em(number)) + Compile em(linespace): Lines (pixel height) to insert between each + row of the display; + resource bf(linespace). + dit(bf(-tn) em(termname)) + This option specifies the name of the terminal type to be set in the + bf(TERM) environment variable. This terminal type must exist in the + em(termcap(5)) database and should have em(li#) and em(co#) entries; + resource bf(termName). + dit(bf(-e) em(command [arguments])) + Run the command with its command-line arguments in the bf(rxvt) + window; also sets the window title and icon name to be the basename + of the program being executed if neither em(-title) (em(-T)) nor + em(-n) are given on the command line. If this option is used, it + must be the last on the command-line. If there is no bf(-e) option + then the default is to run the program specified by the bf(SHELL) + environment variable or, failing that, em(sh(1)). + dit(bf(-title) em(text)) + Window title (bf(-T) still respected); the default title is the + basename of the program specified after the bf(-e) option, if + any, otherwise the application name; + resource bf(title). + dit(bf(-n) em(text)) + Icon name; the default name is the basename of the program specified + after the bf(-e) option, if any, otherwise the application name; + resource bf(iconName). + dit(bf(-C)) + Capture system console messages. + dit(bf(-pt) em(style)) + Compile em(XIM): input style for input method; + bf(OverTheSpot), bf(OffTheSpot), bf(Root); + resource bf(preeditType). + dit(bf(-im) em(text)) + Compile em(XIM): input method name. + resource bf(inputMethod). + dit(bf(-mod) em(modifier)) + Override detection of Meta modifier with specified key: + bf(alt), bf(meta), bf(hyper), bf(super), bf(mod1), bf(mod2), bf(mod3), + bf(mod4), bf(mod5); + resource em(modifier). + dit(bf(-xrm) em(resourcestring)) + No effect on rxvt. Simply passes through an argument to be made + available in the instance's argument list. Appears in em(WM_COMMAND) + in some window managers. +enddit() diff --git a/doc/yodl/rxvt-resources.yo b/doc/yodl/rxvt-resources.yo new file mode 100644 index 00000000..676f1c0f --- /dev/null +++ b/doc/yodl/rxvt-resources.yo @@ -0,0 +1,303 @@ +COMMENT(-- $Id: rxvt-resources.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(RESOURCES (available also as long-options)) + +Note: `rxvt --help' gives a list of all resources (long options) compiled +into your version. +If compiled with internal Xresources support (i.e. bf(rxvt -h) lists +bf(.Xdefaults)) then bf(rxvt) accepts application defaults set in +XAPPLOADDIR/Rxvt (compile-time defined: usually +bf(/usr/lib/X11/app-defaults/Rxvt)) and resources set in bf(~/.Xdefaults), +or bf(~/.Xresources) if bf(~/.Xdefaults) does not exist. Note that when +reading X resources, bf(rxvt) recognizes two class names: bf(XTerm) and +bf(Rxvt). The class name bf(XTerm) allows resources common to both +bf(rxvt) and em(xterm) to be easily configured, while the class name +bf(Rxvt) allows resources unique to bf(rxvt), notably colours and +key-handling, to be shared between different bf(rxvt) configurations. +If no resources are specified, suitable defaults will be used. +Command-line arguments can be used to override resource settings. The +following resources are allowed: + +startdit() + dit(bf(geometry:) em(geom)) + Create the window with the specified X window geometry [default + 80x24]; + option bf(-geometry). + dit(bf(background:) em(colour)) + Use the specified colour as the window's background colour [default + White]; + option bf(-bg). + dit(bf(foreground:) em(colour)) + Use the specified colour as the window's foreground colour [default + Black]; + option bf(-fg). + dit(bf(color)em(n)bf(:) em(colour)) + Use the specified colour for the colour value em(n), where 0-7 + corresponds to low-intensity (normal) colours and 8-15 corresponds to + high-intensity (bold = bright foreground, blink = bright + background) colours. The canonical names are as follows: + 0=black, 1=red, 2=green, 3=yellow, 4=blue, 5=magenta, 6=cyan, 7=white, + but the actual colour names used are listed in the + bf(COLORS AND GRAPHICS) section. + dit(bf(colorBD:) em(colour)) + Use the specified colour to display bold characters when the + foreground colour is the default. + dit(bf(colorUL:) em(colour)) + Use the specified colour to display underlined characters when the + foreground colour is the default. + dit(bf(colorRV:) em(colour)) + Use the specified colour as the background for reverse video + characters. + dit(bf(cursorColor:) em(colour)) + Use the specified colour for the cursor. The default is to use the + foreground colour; + option bf(-cr). + dit(bf(cursorColor2:) em(colour)) + Use the specified colour for the colour of the cursor text. For this + to take effect, bf(cursorColor) must also be specified. The default + is to use the background colour. + dit(bf(reverseVideo:) em(boolean)) + bf(True): simulate reverse video by foreground and background colours; + option bf(-rv). + bf(False): regular screen colours [default]; + option bf(+rv). + See note in bf(COLORS AND GRAPHICS) section. + dit(bf(jumpScroll:) em(boolean)) + bf(True): specify that jump scrolling should be used. When scrolling + quickly, fewer screen updates are performed [default]; + option bf(-j). + bf(False): specify that smooth scrolling should be used; + option bf(+j). + dit(bf(inheritPixmap:) em(boolean)) + bf(True): make the background inherit the parent windows' pixmap, + giving artificial transparency. + bf(False): do not inherit the parent windows' pixmap. + dit(bf(scrollColor:) em(colour)) + Use the specified colour for the scrollbar [default #B2B2B2]. + dit(bf(troughColor:) em(colour)) + Use the specified colour for the scrollbar's trough area [default + #969696]. Only relevant for normal (non XTerm/NeXT) scrollbar. + dit(bf(backgroundPixmap:) em(file[;geom])) + Use the specified XPM file (note the `.xpm' extension is optional) + for the background and also optionally specify its scaling with a + geometry string bf(WxH+X+Y), in which bf("W" / "H") specify the + horizontal/vertical scale (percent) and bf("X" / "Y") locate the + image centre (percent). A scale of 0 displays the image with tiling. + A scale of 1 displays the image without any scaling. A scale of 2 to + 9 specifies an integer number of images in that direction. No image + will be magnified beyond 10 times its original size. The maximum + permitted scale is 1000. [default 0x0+50+50] + dit(bf(menu:) em(file[;tag])) + Read in the specified menu file (note the `.menu' extension is + optional) and also optionally specify a starting tag to find. See + the reference documentation for details on the syntax for the menuBar. + dit(bf(path:) em(path)) + Specify the colon-delimited search path for finding files (XPM and + menus), in addition to the paths specified by the bf(RXVTPATH) and + bf(PATH) environment variables. + dit(bf(font:) em(fontname)) + Select the main text font used [default 7x14]; + option bf(-fn). + dit(bf(font)em(n)bf(:) em(fontname)) + Specify the alternative font em(n). The default font values: nl()\ + indent(\ + starttable(2)(l l)(0)\ + row(cell(bf(font):)cell(7x14))\ + row(cell(bf(font1):)cell(6x10))\ + row(cell(bf(font2):)cell(6x13))\ + row(cell(bf(font3):)cell(8x13))\ + row(cell(bf(font4):)cell(9x15))\ + endtable()) + dit(bf(boldFont:) em(fontname)) + Specify the name of the bold font to use if bf(colorBD) has not been + specified and it is not possible to map the default foreground colour + to colour 8-15 [default NONE]. This font must be the same height and + width as the normal font; + option bf(-fb). + dit(bf(mfont:) em(fontname)) + Select the main multiple-character text font used [default k14]; + option bf(-fk). + dit(bf(mfont)em(n)bf(:) em(fontname)) + Specify the alternative multiple-character font em(n). If compiled + for multiple-character fonts, the Roman and multiple-character font + sizes should match. + dit(bf(multichar_encoding:) em(mode)) + Set the encoding mode to be used when multicharacter encoding is + received; + bf(eucj): EUC Japanese encoding [default for Kanji]. + bf(sjis): Shift JIS encoding. + bf(big5): BIG5 encoding. + bf(gb): GB encoding. + bf(kr): EUC Korean encoding. + bf(noenc): no encoding; + option bf(-km). + dit(bf(greek_keyboard:) em(mode)) + Set the Greek keyboard translation mode to be used; + bf(iso): ISO-8859 mapping (elot-928) [default]. + bf(ibm): IBM-437 mapping (DOS codepage 737); + option bf(-grk). + dit(bf(greektoggle_key:) em(keysym)) + Set the key to toggle keyboard input between no translation and + Greek translation [default bf(Mode_switch)]. + For more details, see the distributed file bf(README.greek). + dit(bf(selectstyle:) em(mode)) + Set mouse selection style to bf(old) which is 2.20, bf(oldword) which + is xterm style with 2.20 old word selection, or anything else which + gives xterm style selection. + dit(bf(scrollstyle:) em(mode)) + Set scrollbar style to bf(rxvt), bf(next) or bf(xterm) + dit(bf(title:) em(string)) + Set window title string, the default title is the command-line + specified after the bf(-e) option, if any, otherwise the application + name; + option bf(-title). + dit(bf(iconName:) em(string)) + Set the name used to label the window's icon or displayed in an icon + manager window, it also sets the window's title unless it is + explicitly set; + option bf(-n). + dit(bf(mapAlert:) em(boolean)) + bf(True): de-iconify (map) on receipt of a bell character. + bf(False): no de-iconify (map) on receipt of a bell character + [default]. + dit(bf(visualBell:) em(boolean)) + bf(True): use visual bell on receipt of a bell character; + option bf(-vb). + bf(False): no visual bell [default]; + option bf(+vb). + dit(bf(loginShell:) em(boolean)) + bf(True): start as a login shell by prepending a `-' to bf(argv[0]) + of the shell; + option bf(-ls). + bf(False): start as a normal sub-shell [default]; + option bf(+ls). + dit(bf(utmpInhibit:) em(boolean)) + bf(True): inhibit writing record into the system log file bf(utmp); + option bf(-ut). + bf(False): write record into the system log file bf(utmp) [default]; + option bf(+ut). + dit(bf(print-pipe:) em(string)) + Specify a command pipe for vt100 printer [default em(lpr(1))]. Use + bf(Print) to initiate a screen dump to the printer and bf(Ctrl-Print) + or bf(Shift-Print) to include the scrollback as well. + dit(bf(scrollBar:) em(boolean)) + bf(True): enable the scrollbar [default]; + option bf(-sb). + bf(False): disable the scrollbar; + option bf(+sb). + dit(bf(scrollBar_right:) em(boolean)) + bf(True): place the scrollbar on the right of the window; + option bf(-sr). + bf(False): place the scrollbar on the left of the window; + option bf(+sr). + dit(bf(scrollBar_floating:) em(boolean)) + bf(True): display an rxvt scrollbar without a trough; + option bf(-st). + bf(False): display an rxvt scrollbar with a trough; + option bf(+st). + dit(bf(scrollBar_align:) em(mode)) + Align the bf(top), bf(bottom) or bf(centre) [default] of + the scrollbar thumb with the pointer on middle button + press/drag. + dit(bf(scrollTtyOutput:) em(boolean)) + bf(True): scroll to bottom when tty receives output; + option(+si). + bf(False): do not scroll to bottom when tty receives output; + option(-si). + dit(bf(scrollWithBuffer:) em(boolean)) + bf(True): scroll with scrollback buffer when tty recieves + new lines (and bf(scrollTtyOutput) is False); + option(+sw). + bf(False): do not scroll with scrollback buffer when tty + recieves new lines; + option(-sw). + dit(bf(scrollTtyKeypress:) em(boolean)) + bf(True): scroll to bottom when a non-special key is pressed. + Special keys are those which are intercepted by rxvt for special + handling and are not passed onto the shell; + option(-sk). + bf(False): do not scroll to bottom when a non-special key is pressed; + option(+sk). + dit(bf(smallfont_key:) em(keysym)) + If enabled, use bf(HOTKEY()-)em(keysym) to toggle to a smaller font + [default bf(HOTKEY()-SMALLFONT())] + dit(bf(bigfont_key:) em(keysym)) + If enabled, use bf(HOTKEY()-)em(keysym) to toggle to a bigger font + [default bf(HOTKEY()-BIGFONT())] + dit(bf(saveLines:) em(number)) + Save em(number) lines in the scrollback buffer [default 64]. This + resource is limited on most machines to 65535; + option bf(-sl). + dit(bf(internalBorder:) em(number)) + Internal border of em(number) pixels. This resource is limited to 100; + option bf(-b). + dit(bf(externalBorder:) em(number)) + External border of em(number) pixels. This resource is limited to 100; + option bf(-w), bf(-bw), bf(-borderwidth). + dit(bf(termName:) em(termname)) + Specifies the terminal type name to be set in the bf(TERM) + environment variable; + option bf(-tn). + dit(bf(linespace:) em(number)) + Specifies number of lines (pixel height) to insert between each row + of the display [default 0]; + option bf(-lsp). + dit(bf(meta8:) em(boolean)) + bf(True): handle Meta (Alt) + keypress to set the 8th bit. + bf(False): handle Meta (Alt) + keypress as an escape prefix [default]. + dit(bf(mouseWheelScrollPage:) em(boolean)) + bf(True): the mouse wheel scrolls a page full. + bf(False): the mouse wheel scrolls five lines [default]. + dit(bf(cursorBlink:) em(boolean)) + bf(True): blink the cursor. + bf(False): do not blink the cursor [default]; + option bf(-bc). + dit(bf(pointerBlank:) em(boolean)) + bf(True): blank the pointer when a key is pressed or after a set number + of seconds of inactivity. + bf(False): the pointer is always visible [default]. + dit(bf(pointerBlankDelay:) em(number)) + Specifies number of seconds before blanking the pointer [default 2]. + dit(bf(multibyte_cursor:) em(boolean)) + bf(True): consider multibyte glyphs as single character for backspace, + delete and cursor movement keys; + option bf(-mcc). + bf(False): move through all components of all glyphs; + option bf(+mcc). + dit(bf(backspacekey:) em(string)) + The string to send when the backspace key is pressed. If set to + bf(DEC) or unset it will send bf(Delete) (code 127) or, if shifted, + bf(Backspace) (code 8) - which can be reversed with the appropriate + DEC private mode escape sequence. + dit(bf(deletekey:) em(string)) + The string to send when the delete key (not the keypad delete key) is + pressed. If unset it will send the sequence traditionally associated + with the bf(Execute) key. + dit(bf(cutchars:) em(string)) + The characters used as delimiters for double-click word selection. + The built-in default: nl()\ + bf(BACKSLASH `"'&()*,;<=>?@[]{|}) + dit(bf(preeditType:) em(style)) + bf(OverTheSpot), bf(OffTheSpot), bf(Root); + option bf(-pt). + dit(bf(inputMethod:) em(name)) + em(name) of inputMethod to use; + option bf(-im). + dit(bf(modifier:) em(modifier)) + Set the key to be interpreted as the Meta key to: + bf(alt), bf(meta), bf(hyper), bf(super), bf(mod1), bf(mod2), bf(mod3), + bf(mod4), bf(mod5); + option bf(-mod). + dit(bf(answerbackString:) em(string)) + Specify the reply rxvt sends to the shell when an ENQ (control-E) + character is passed through. It may contain escape values as + described in the entry on bf(keysym) following. + dit(bf(keysym.)em(sym): em(string)) + Associate em(string) with keysym em(sym) (bf(0xFF00 - 0xFFFF)). It + may contain escape values (\a: bell, \b: backspace, \e, \E: escape, + \n: newline, \r: return, \t: tab, \000: octal number) or control + characters (^?: delete, ^@: null, ^A ...) and may enclosed with + double quotes so that it can start or end with whitespace. The + intervening resource name bf(keysym.) cannot be omitted. This + resource is only available when compiled with KEYSYM_RESOURCE. +enddit() diff --git a/doc/yodl/rxvt-scrollbar.yo b/doc/yodl/rxvt-scrollbar.yo new file mode 100644 index 00000000..add585f8 --- /dev/null +++ b/doc/yodl/rxvt-scrollbar.yo @@ -0,0 +1,13 @@ +COMMENT(-- $Id: rxvt-scrollbar.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(THE SCROLLBAR) + +Lines of text that scroll off the top of the bf(rxvt) window (resource: +bf(saveLines)) and can be scrolled back using the scrollbar or by keystrokes. +The normal bf(rxvt) scrollbar has arrows and its behaviour is fairly +intuitive. The bf(xterm-scrollbar) is without arrows and its behaviour +mimics that of em(xterm) + +Scroll down with bf(Button1) (bf(xterm-scrollbar)) or bf(Shift-Next). +Scroll up with bf(Button3) (bf(xterm-scrollbar)) or bf(Shift-Prior). +Continuous scroll with bf(Button2). diff --git a/doc/yodl/rxvt-textselection.yo b/doc/yodl/rxvt-textselection.yo new file mode 100644 index 00000000..6a66f522 --- /dev/null +++ b/doc/yodl/rxvt-textselection.yo @@ -0,0 +1,18 @@ +COMMENT(-- $Id: rxvt-textselection.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(----------------------------------------------------------------------) +manpagesection(TEXT SELECTION AND INSERTION) + +The behaviour of text selection and insertion mechanism is similar to +em(xterm)(1). + +startdit() + dit(bf(Selection):) + Left click at the beginning of the region, drag to the end of the + region and release; Right click to extend the marked region; + Left double-click to select a word; Left triple-click to select + the entire line. + dit(bf(Insertion):) + Pressing and releasing the Middle mouse button (or bf(Shift-Insert)) + in an bf(rxvt) window causes the current text selection to be inserted + as if it had been typed on the keyboard. +enddit() diff --git a/doc/yodl/rxvt.yo b/doc/yodl/rxvt.yo new file mode 100644 index 00000000..12bc75d0 --- /dev/null +++ b/doc/yodl/rxvt.yo @@ -0,0 +1,117 @@ +COMMENT(-- $Id: rxvt.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +includefile(versioninfo.yo) +includefile(masonyodl.yo) +mailto(gcw@pobox.com) + +DEFINEMACRO(HOTKEY)(0)(Alt) +DEFINEMACRO(BIGFONT)(0)(>) +DEFINEMACRO(SMALLFONT)(0)(<) + +COMMENT(----------------------------------------------------------------------- +-- We want the following macro's to be pre-defined +-- RXVTDATE() +-- RXVTVERSION() +-- RXVTMAINT() +-- RXVTMAINTEMAIL() +-- RXVTWEBPAGE() +-- RXVTWEBMAINT() +-- RXVTWEBMAINTEMAIL() +-- RXVTFTPSITE() +------------------------------------------------------------------------------) + +COMMENT(----------------------------------------------------------------------) +manpage(RXVT)(1)(RXVTDATE())(X Version 11)(X Tools) +manpagename(rxvt (ouR XVT))(a VT102 emulator for the X window system) + +COMMENT(----------------------------------------------------------------------) +manpagesynopsis() + +bf(rxvt) [options] [-e command [ args ]] + +COMMENT(----------------------------------------------------------------------) +manpagedescription() + +bf(rxvt), version bf(RXVTVERSION()), is a colour vt102 terminal emulator +intended as an em(xterm)(1) replacement for users who do not require +features such as Tektronix 4014 emulation and toolkit-style configurability. +As a result, bf(rxvt) uses much less swap space -- a significant +advantage on a machine serving many X sessions. + +COMMENT(----------------------------------------------------------------------) + +includefile(rxvt-options.yo) +includefile(rxvt-resources.yo) +includefile(rxvt-scrollbar.yo) +includefile(rxvt-mousereporting.yo) +includefile(rxvt-textselection.yo) +includefile(rxvt-fonts.yo) +includefile(rxvt-login.yo) +includefile(rxvt-colours.yo) +includefile(rxvt-environment.yo) +includefile(rxvt-files.yo) + +COMMENT(----------------------------------------------------------------------) +manpageseealso() + +em(xterm)(1), em(sh)(1), em(resize)(1), em(X)(1), em(pty)(4), em(tty)(4), +em(utmp)(5) + +See rxvtRef.html rxvtRef.txt for detailed information on recognized escape +sequences and menuBar syntax, etc. + +COMMENT(----------------------------------------------------------------------) +manpagebugs() + +Check the BUGS file for an up-to-date list. + +Cursor change support is not yet implemented. + +Click-and-drag doesn't work with X11 mouse report overriding. + +Graphics support is fairly crude. + + +COMMENT(----------------------------------------------------------------------) +manpagesection(FTP LOCATION) + +rxvt-+RXVTVERSION().tar.gz can be found at the following ftp sites +url(RXVTFTPSITE())(RXVTFTPSITE()) + +COMMENT(----------------------------------------------------------------------) +manpagesection(CURRENT PROJECT COORDINATOR) + +startdit() + dit(Project Coordinator) + RXVTMAINT() email(RXVTMAINTEMAIL())nl()\ + dit(Web page maintainter) + RXVTWEBMAINT() email(RXVTWEBMAINTEMAIL())nl()\ + url(RXVTWEBPAGE())(RXVTWEBPAGE())nl()\ + dit(Mailing list) + The Rxvt Workers email() + mailing list has also been established for rxvt development, to + subscribe, email to + email(). + There is also a mailing list for announcements of new releases of + rxvt. To subscribe, email to + email(). +enddit() + +COMMENT(----------------------------------------------------------------------) +manpageauthors() + +startdit() + dit(John Bovey) + University of Kent, 1992, wrote the original Xvt. + dit(Rob Nation email()) + very heavily modified Xvt and came up with Rxvt + dit(Angelo Haritsis email()) + wrote the Greek Keyboard Input + dit(mj olesen email()) + Wrote the menu system. nl()\ + Project Coordinator (changes.txt 2.11 to 2.21) + dit(Oezguer Kesim email()) + Project Coordinator (changes.txt 2.21a to 2.4.5) + dit(Geoff Wing email()) + Rewrote screen display and text selection routines. nl()\ + Project Coordinator (changes.txt 2.4.6 - ) +enddit() diff --git a/doc/yodl/rxvtRef-csi.yo b/doc/yodl/rxvtRef-csi.yo new file mode 100644 index 00000000..2652784f --- /dev/null +++ b/doc/yodl/rxvtRef-csi.yo @@ -0,0 +1,169 @@ +COMMENT(-- $Id: rxvtRef-csi.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(CSI) +nsect(CSI (Code Sequence Introducer) Sequences) + +startdl() + dl(bf(tt(ESC [ Ps @))) + (Insert bf(tt(Ps)) (Blank) Character(s) [default: 1] (ICH))\ +P()\ +label(ESCOBPsA) + dl(bf(tt(ESC [ Ps A))) + (Cursor Up bf(tt(Ps)) Times [default: 1] (CUU)) +P()\ + dl(bf(tt(ESC [ Ps B))) + (Cursor Down bf(tt(Ps)) Times [default: 1] (CUD))\ +label(ESCOBPsC) + dl(bf(tt(ESC [ Ps C))) + (Cursor Forward bf(tt(Ps)) Times [default: 1] (CUF)) +P()\ + dl(bf(tt(ESC [ Ps D))) + (Cursor Backward bf(tt(Ps)) Times [default: 1] (CUB)) +P()\ + dl(bf(tt(ESC [ Ps E))) + (Cursor Down bf(tt(Ps)) Times [default: 1] and to first column) +P()\ + dl(bf(tt(ESC [ Ps F))) + (Cursor Up bf(tt(Ps)) Times [default: 1] and to first column)\ +P()\ +label(ESCOBPsG) + dl(bf(tt(ESC [ Ps G))) + (Cursor to Column bf(tt(Ps)) (HPA)) +P()\ + dl(bf(tt(ESC [ Ps;Ps H))) + (Cursor Position [row;column] [default: 1;1] (CUP)) +P()\ + dl(bf(tt(ESC [ Ps I))) + (Move forward bf(tt(Ps)) tab stops [default: 1]) +P()\ + dl(bf(tt(ESC [ Ps J))) + (Erase in Display (ED) nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(Ps = 0)))cell(Clear Below (default)))\ + row(cell(bf(tt(Ps = 1)))cell(Clear Above))\ + row(cell(bf(tt(Ps = 2)))cell(Clear All))\ + endtable()) + dl(bf(tt(ESC [ Ps K))) + (Erase in Line (EL) nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(Ps = 0)))cell(Clear to Right (default)))\ + row(cell(bf(tt(Ps = 1)))cell(Clear to Left))\ + row(cell(bf(tt(Ps = 2)))cell(Clear All))\ + endtable()) + dl(bf(tt(ESC [ Ps L))) + (Insert bf(tt(Ps)) Line(s) [default: 1] (IL)) +P()\ + dl(bf(tt(ESC [ Ps M))) + (Delete bf(tt(Ps)) Line(s) [default: 1] (DL)) +P()\ + dl(bf(tt(ESC [ Ps P))) + (Delete bf(tt(Ps)) Character(s) [default: 1] (DCH)) +P()\ + dl(bf(tt(ESC [ Ps;Ps;Ps;Ps;Ps T))) + (Initiate link(hilite mouse tracking)(Mouse). em(unimplemented) + Parameters are [func;startx;starty;firstrow;lastrow].) +P()\ + dl(bf(tt(ESC [ Ps W))) + (Tabulator functions nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(Ps = 0)))cell(Tab Set (HTS)))\ + row(cell(bf(tt(Ps = 2)))cell(Tab Clear (TBC), Clear Current \ + Column (default)))\ + row(cell(bf(tt(Ps = 5)))cell(Tab Clear (TBC), Clear All))\ + endtable()) + dl(bf(tt(ESC [ Ps X))) + (Erase bf(tt(Ps)) Character(s) [default: 1] (ECH)) +P()\ + dl(bf(tt(ESC [ Ps Z))) + (Move backward bf(tt(Ps)) [default: 1] tab stops) +P()\ + dl(bf(tt(ESC [ Ps '))) + (== link(tt(ESC [ Ps G))(ESCOBPsG)) +P()\ + dl(bf(tt(ESC [ Ps a))) + (== link(tt(ESC [ Ps C))(ESCOBPsC))\ +P()\ +label(ESCOBPsc) + dl(bf(tt(ESC [ Ps c))) + (Send Device Attributes (DA)nl()\ + bf(tt(Ps = 0)) (or omitted) : request attributes from terminal nl()\ + returns: bf(tt(ESC[?1;2c)) (``I am a VT100 with Advanced Video + Option'')) +P()\ + dl(bf(tt(ESC [ Ps d))) + (Cursor to Line bf(tt(Ps)) (VPA)) +P()\ + dl(bf(tt(ESC [ Ps e))) + (== link(ESC [ Ps A)(ESCOBPsA)) +P()\ + dl(bf(tt(ESC [ Ps;Ps f))) + (Horizontal and Vertical Position [row;column] (HVP) [default: 1;1]) +P()\ + dl(bf(tt(ESC [ Ps g))) + (Tab Clear (TBC) nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(Ps = 0)))cell(Clear Current Column (default)))\ + row(cell(bf(tt(Ps = 3)))cell(Clear All (TBC)))\ + endtable()) + dl(bf(tt(ESC [ Ps i))) + (Printing nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(Ps = 4)))cell(disable transparent print mode (MC4)))\ + row(cell(bf(tt(Ps = 5)))cell(enable transparent print mode (MC5) \ + em(unimplemented)))\ + endtable()) + dl(bf(tt(ESC [ Pm h)nl()tt(ESC [ Pm l))) + (Set Mode (SM) nl()Reset Mode (RM)\ + startdl() + dl(bf(tt(Ps = 4))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Insert Mode (SMIR)))\ + row(cell(bf(tt(l)))cell(Replace Mode (RMIR)))\ + endtable()) + dl(bf(tt(Ps = 20)) em(unimplemented)) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Automatic Newline (LNM)))\ + row(cell(bf(tt(h)))cell(Normal Linefeed (LNM)))\ + endtable()) + enddl()) + dl(bf(tt(ESC [ Pm m))) + (Character Attributes (SGR) nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(Ps = 0)))cell(Normal (default)))\ + row(cell(bf(tt(Ps = 1 / 22)))cell(On / Off Bold (bright fg)))\ + row(cell(bf(tt(Ps = 4 / 24)))cell(On / Off Underline))\ + row(cell(bf(tt(Ps = 5 / 25)))cell(On / Off Blink (bright bg)))\ + row(cell(bf(tt(Ps = 7 / 27)))cell(On / Off Inverse))\ + row(cell(bf(tt(Ps = 30 / 40)))cell(fg/bg Black))\ + row(cell(bf(tt(Ps = 31 / 41)))cell(fg/bg Red))\ + row(cell(bf(tt(Ps = 32 / 42)))cell(fg/bg Green))\ + row(cell(bf(tt(Ps = 33 / 43)))cell(fg/bg Yellow))\ + row(cell(bf(tt(Ps = 34 / 44)))cell(fg/bg Blue))\ + row(cell(bf(tt(Ps = 35 / 45)))cell(fg/bg Magenta))\ + row(cell(bf(tt(Ps = 36 / 46)))cell(fg/bg Cyan))\ + row(cell(bf(tt(Ps = 37 / 47)))cell(fg/bg White))\ + row(cell(bf(tt(Ps = 39 / 49)))cell(fg/bg Default))\ + endtable()) + dl(bf(tt(ESC [ Ps n))) + (Device Status Report (DSR) nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(Ps = 5)))cell(Status Report bf(tt(ESC [ 0 n)) \ + (``OK'')))\ + row(cell(bf(tt(Ps = 6)))cell(Report Cursor Position (CPR) \ + [row;column] as bf(tt(ESC [ r ; c R))))\ + row(cell(bf(tt(Ps = 7)))cell(Request Display Name))\ + row(cell(bf(tt(Ps = 8)))cell(Request Version Number (place in \ + window title)))\ + endtable()) + dl(bf(tt(ESC [ Ps;Ps r))) + (Set Scrolling Region [top;bottom] nl()\ + [default: full size of window] (CSR)) +P()\ + dl(bf(tt(ESC [ s))) + (Save Cursor (SC)) +P()\ + dl(bf(tt(ESC [ Ps x))) + (Request Terminal Parameters (DECREQTPARM)) +P()\ + dl(bf(tt(ESC [ u))) + (Restore Cursor) +enddl() diff --git a/doc/yodl/rxvtRef-definitions.yo b/doc/yodl/rxvtRef-definitions.yo new file mode 100644 index 00000000..6707b6df --- /dev/null +++ b/doc/yodl/rxvtRef-definitions.yo @@ -0,0 +1,22 @@ +COMMENT(-- $Id: rxvtRef-definitions.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(Definitions) +nsect(Definitions) + +startdl() + dl(bf(tt(c))) + (The literal character c.) +P()\ + dl(bf(tt(C))) + (A single (required) character.) +P()\ + dl(bf(tt(Ps))) + (A single (usually optional) numeric parameter, composed of one or + more digits.) +P()\ + dl(bf(tt(Pm))) + (A multiple numeric parameter composed of any number of single numeric + parameters, separated by ; character(s).) +P()\ + dl(bf(tt(Pt))) + (A text parameter composed of printable characters.) +enddl() diff --git a/doc/yodl/rxvtRef-graphics.yo b/doc/yodl/rxvtRef-graphics.yo new file mode 100644 index 00000000..a0cb7e8e --- /dev/null +++ b/doc/yodl/rxvtRef-graphics.yo @@ -0,0 +1,33 @@ +COMMENT(-- $Id: rxvtRef-graphics.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(Graphics) +nsect(Special Graphics Mode) + +Add more documentation here, em(if anyone actually cares.) + +startdl() + dl(bf(tt(ESC G Q))) + (query if graphics are available nl()\ + returns: bf(tt(ESC G 0)) no graphics available nl()\ + returns: bf(tt(ESC G 1)) graphics available (colour only)) +P()\ + dl(bf(tt(ESC G W <;x>;;;:))) + (create window) +P()\ + dl(bf(tt(ESC G C ))) + (clear window) +P()\ + dl(bf(tt(ESC G G :))) + (query window nl()\ + returns: bf(tt(ESC G ))) +P()\ + dl(bf(tt(ESC G L )nl()tt(ESC G P )nl()tt(ESC G F ))) + (start point nl()\ + start line nl()\ + start fill) +P()\ + dl(bf(tt(;;))) + (extend point/line/fill) +P()\ + dl(bf(tt(ESC G T ;;;;:))) + (place text) +enddl() diff --git a/doc/yodl/rxvtRef-keycodes.yo b/doc/yodl/rxvtRef-keycodes.yo new file mode 100644 index 00000000..6dfbc675 --- /dev/null +++ b/doc/yodl/rxvtRef-keycodes.yo @@ -0,0 +1,73 @@ +COMMENT(-- $Id: rxvtRef-keycodes.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(KeyCodes) +nsect(Key Codes) + +Note: bf(Shift) + bf(F1)-bf(F10) generates bf(F11)-bf(F20) + +For the keypad, use bf(Shift) to temporarily override Application-Keypad +setting use bf(Num_Lock) to toggle Application-Keypad setting if bf(Num_Lock) +is off, link(escape sequences)(ESCequals) toggle Application-Keypad setting. +Also note that values of bf(Home), bf(End), bf(Delete) may have been compiled +differently on your system. + +COMMENT(-- Edited in a wide window --) +starttable(5)(l l l l l)(1)\ + row(cell( )cell(bf(Normal) )cell(bf(Shift) )cell(bf(Control) )cell(bf(Ctrl+Shift)))\ + row(cell(Tab )cell(^I )cell(ESC [ Z )cell(^I )cell(ESC [ Z))\ + row(cell(BackSpace )cell(^H )cell(^? )cell(^? )cell(^?))\ + row(cell(Find )cell(ESC [ 1 ~ )cell(ESC [ 1 $ )cell(ESC [ 1 ^ )cell(ESC [ 1 @))\ + row(cell(Insert )cell(ESC [ 2 ~ )cell(em(paste) )cell(ESC [ 2 ^ )cell(ESC [ 2 @))\ + row(cell(Execute )cell(ESC [ 3 ~ )cell(ESC [ 3 $ )cell(ESC [ 3 ^ )cell(ESC [ 3 @))\ + row(cell(Select )cell(ESC [ 4 ~ )cell(ESC [ 4 $ )cell(ESC [ 4 ^ )cell(ESC [ 4 @))\ + row(cell(Prior )cell(ESC [ 5 ~ )cell(em(scroll-up) )cell(ESC [ 5 ^ )cell(ESC [ 5 @))\ + row(cell(Next )cell(ESC [ 6 ~ )cell(em(scroll-down))cell(ESC [ 6 ^ )cell(ESC [ 6 @))\ + row(cell(Home )cell(ESC [ 7 ~ )cell(ESC [ 7 $ )cell(ESC [ 7 ^ )cell(ESC [ 7 @))\ + row(cell(End )cell(ESC [ 8 ~ )cell(ESC [ 8 $ )cell(ESC [ 8 ^ )cell(ESC [ 8 @))\ + row(cell(Delete )cell(ESC [ 3 ~ )cell(ESC [ 3 $ )cell(ESC [ 3 ^ )cell(ESC [ 3 @))\ + row(cell(F1 )cell(ESC [ 11 ~ )cell(ESC [ 23 ~ )cell(ESC [ 11 ^ )cell(ESC [ 23 ^))\ + row(cell(F2 )cell(ESC [ 12 ~ )cell(ESC [ 24 ~ )cell(ESC [ 12 ^ )cell(ESC [ 24 ^))\ + row(cell(F3 )cell(ESC [ 13 ~ )cell(ESC [ 25 ~ )cell(ESC [ 13 ^ )cell(ESC [ 25 ^))\ + row(cell(F4 )cell(ESC [ 14 ~ )cell(ESC [ 26 ~ )cell(ESC [ 14 ^ )cell(ESC [ 26 ^))\ + row(cell(F5 )cell(ESC [ 15 ~ )cell(ESC [ 28 ~ )cell(ESC [ 15 ^ )cell(ESC [ 28 ^))\ + row(cell(F6 )cell(ESC [ 17 ~ )cell(ESC [ 29 ~ )cell(ESC [ 17 ^ )cell(ESC [ 29 ^))\ + row(cell(F7 )cell(ESC [ 18 ~ )cell(ESC [ 31 ~ )cell(ESC [ 18 ^ )cell(ESC [ 31 ^))\ + row(cell(F8 )cell(ESC [ 19 ~ )cell(ESC [ 32 ~ )cell(ESC [ 19 ^ )cell(ESC [ 32 ^))\ + row(cell(F9 )cell(ESC [ 20 ~ )cell(ESC [ 33 ~ )cell(ESC [ 20 ^ )cell(ESC [ 33 ^))\ + row(cell(F10 )cell(ESC [ 21 ~ )cell(ESC [ 34 ~ )cell(ESC [ 21 ^ )cell(ESC [ 34 ^))\ + row(cell(F11 )cell(ESC [ 23 ~ )cell(ESC [ 23 $ )cell(ESC [ 23 ^ )cell(ESC [ 23 @))\ + row(cell(F12 )cell(ESC [ 24 ~ )cell(ESC [ 24 $ )cell(ESC [ 24 ^ )cell(ESC [ 24 @))\ + row(cell(F13 )cell(ESC [ 25 ~ )cell(ESC [ 25 $ )cell(ESC [ 25 ^ )cell(ESC [ 25 @))\ + row(cell(F14 )cell(ESC [ 26 ~ )cell(ESC [ 26 $ )cell(ESC [ 26 ^ )cell(ESC [ 26 @))\ + row(cell(F15 (Help) )cell(ESC [ 28 ~ )cell(ESC [ 28 $ )cell(ESC [ 28 ^ )cell(ESC [ 28 @))\ + row(cell(F16 (Menu) )cell(ESC [ 29 ~ )cell(ESC [ 29 $ )cell(ESC [ 29 ^ )cell(ESC [ 29 @))\ + row(cell(F17 )cell(ESC [ 31 ~ )cell(ESC [ 31 $ )cell(ESC [ 31 ^ )cell(ESC [ 31 @))\ + row(cell(F18 )cell(ESC [ 32 ~ )cell(ESC [ 32 $ )cell(ESC [ 32 ^ )cell(ESC [ 32 @))\ + row(cell(F19 )cell(ESC [ 33 ~ )cell(ESC [ 33 $ )cell(ESC [ 33 ^ )cell(ESC [ 33 @))\ + row(cell(F20 )cell(ESC [ 34 ~ )cell(ESC [ 34 $ )cell(ESC [ 34 ^ )cell(ESC [ 34 @))\ + row(cell( )cell( )cell( )cell( )cell(bf(Application)))\ + row(cell(Up )cell(ESC [ A )cell(ESC [ a )cell(ESC O a )cell(ESC O A))\ + row(cell(Down )cell(ESC [ B )cell(ESC [ b )cell(ESC O b )cell(ESC O B))\ + row(cell(Right )cell(ESC [ C )cell(ESC [ c )cell(ESC O c )cell(ESC O C))\ + row(cell(Left )cell(ESC [ D )cell(ESC [ d )cell(ESC O d )cell(ESC O D))\ + row(cell(KP_Enter )cell(^M )cell( )cell( )cell(ESC O M))\ + row(cell(KP_F1 )cell(ESC O P )cell( )cell( )cell(ESC O P))\ + row(cell(KP_F2 )cell(ESC O Q )cell( )cell( )cell(ESC O Q))\ + row(cell(KP_F3 )cell(ESC O R )cell( )cell( )cell(ESC O R))\ + row(cell(KP_F4 )cell(ESC O S )cell( )cell( )cell(ESC O S))\ + row(cell(XK_KP_Multiply )cell(* )cell( )cell( )cell(ESC O j))\ + row(cell(XK_KP_Add )cell(+ )cell( )cell( )cell(ESC O k))\ + row(cell(XK_KP_Separator)cell(, )cell( )cell( )cell(ESC O l))\ + row(cell(XK_KP_Subtract )cell(- )cell( )cell( )cell(ESC O m))\ + row(cell(XK_KP_Decimal )cell(. )cell( )cell( )cell(ESC O n))\ + row(cell(XK_KP_Divide )cell(/ )cell( )cell( )cell(ESC O o))\ + row(cell(XK_KP_0 )cell(0 )cell( )cell( )cell(ESC O p))\ + row(cell(XK_KP_1 )cell(1 )cell( )cell( )cell(ESC O q))\ + row(cell(XK_KP_2 )cell(2 )cell( )cell( )cell(ESC O r))\ + row(cell(XK_KP_3 )cell(3 )cell( )cell( )cell(ESC O s))\ + row(cell(XK_KP_4 )cell(4 )cell( )cell( )cell(ESC O t))\ + row(cell(XK_KP_5 )cell(5 )cell( )cell( )cell(ESC O u))\ + row(cell(XK_KP_6 )cell(6 )cell( )cell( )cell(ESC O v))\ + row(cell(XK_KP_7 )cell(7 )cell( )cell( )cell(ESC O w))\ + row(cell(XK_KP_8 )cell(8 )cell( )cell( )cell(ESC O x))\ + row(cell(XK_KP_9 )cell(9 )cell( )cell( )cell(ESC O y))\ +endtable() diff --git a/doc/yodl/rxvtRef-menubar.yo b/doc/yodl/rxvtRef-menubar.yo new file mode 100644 index 00000000..a94ad7a5 --- /dev/null +++ b/doc/yodl/rxvtRef-menubar.yo @@ -0,0 +1,283 @@ +COMMENT(-- $Id: rxvtRef-menubar.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(menuBar) +nsect(menuBar) + +bf(The exact syntax used is em(almost) solidified.) nl()\ +In the menus, bf(DON'T) try to use menuBar commands that add or remove a +menuBar. + +Note that in all of the commands, the bf(em(/path/)) em(cannot) be omitted: +use bf(./) to specify a menu relative to the current menu. + +nsubsect(Overview of menuBar operation) + +For the menuBar XTerm escape sequence tt(ESC ] 10 ; Pt ST), the +syntax of tt(Pt) can be used for a variety of tasks: +startit() + it()link(Commands)(menuBarCommands) + it()link(Adding and accessing menus)(menuBarAdd) + it()link(Removing menus)(menuBarRemove) + it()link(Quick Arrows)(menuBarArrows) + it()link(Command Summary)(menuBarSummary) +endit() + +At the top level is the current menuBar which is a member of a circular +linked-list of other such menuBars. + +The menuBar acts as a parent for the various drop-down menus, which in turn, +may have labels, separator lines, menuItems and subMenus. + +The menuItems are the useful bits: you can use them to mimic keyboard input +or even to send text or escape sequences back to rxvt. + +The menuBar syntax is intended to provide a simple yet robust method of +constructing and manipulating menus and navigating through the menuBars. + +The first step is to use the tag bf([menu:em(name)]) which creates the +menuBar called em(name) and allows access. +You may now link(add)(menuBarAdd) or link(remove)(menuBarRemove) menus, +subMenus, and menuItems. Finally, use the tag bf([done]) to set the menuBar +access as bf(readonly) to prevent accidental corruption of the menus. +To re-access the current menuBar for alterations, use the tag bf([menu]), +make the alterations and then use bf([done]) + +label(menuBarCommands) +nsubsect(Commands) + +startdl() + dl(bf([menu:+em(name)])) + (access the named menuBar for creation or alteration. If a new menuBar + is created, it is called em(name) (max of 15 chars) and the current + menuBar is pushed onto the stack) +P()\ + dl(bf([menu])) + (access the current menuBar for alteration) +P()\ + dl(bf([title:+em(string)])) + (set the current menuBar's title to em(string), which may contain the + following format specifiers: nl()\ + bf(%%) : literal bf(%) character nl()\ + bf(%n) : rxvt name (as per the bf(-name) command-line option) nl()\ + bf(%v) : rxvt version) +P()\ + dl(bf([done])) + (set menuBar access as bf(readonly). nl()\ + End-of-file tag for bf([read:+em(file)]) operations.) +P()\ + dl(bf([read:+em(file)])) + (read menu commands directly from em(file) (extension ".menu" will be + appended if required.) Start reading at a line with bf([menu]) or + bf([menu:+em(name)) and continuing until bf([done]) is encountered. + + Blank and comment lines (starting with bf(#)) are ignored. + Actually, since any invalid menu commands are also ignored, almost + anything could be construed as a comment line, but this may be + tightened up in the future ... so don't count on it!.) +P()\ + dl(bf([read:+em(file);+em(name)])) + (The same as bf([read:+em(file)]), but start reading at a line with + bf([menu:+em(name)]) and continuing until bf([done:+em(name)]) or + bf([done]) is encountered.) +P()\ + dl(bf([dump])) + (dump all menuBars to the file bf(/tmp/rxvt-PID) in a format suitable + for later rereading.) +P()\ + dl(bf([rm:name]nl()[rm] [rm:]nl()[rm*] [rm:*])) + (remove the named menuBar nl()\ + remove the current menuBar nl()\ + remove all menuBars) +P()\ + dl(bf([swap])) + (swap the top two menuBars) +P()\ + dl(bf([prev]nl()[next])) + (access the previous or next menuBar) +P()\ + dl(bf([show]nl()[hide])) + (control display of the menuBar ... just like + link(ESC[?10 h/l)(Priv10)) +P()\ + dl(bf([pixmap:+em(name)]nl()[pixmap:+em(name);em(scaling)])) + (set the background pixmap globally ... just like + link(ESC ] 20 ; Pt ST)(XPM) + + bf(A Future implementation em(may) make this local to the menubar)) +P()\ + dl(bf([:+em(command):])) + (ignore the menu readonly status and issue a em(command) to + link(Add/Modify)(menuBarAdd) or link(Remove)(menuBarRemove) a menu or + menuitem or change the link(Quick Arrows)(menuBarArrows); a useful + shortcut for setting the quick arrows from a menuBar.) +enddl() + +label(menuBarAdd) +nsubsect(Adding and accessing menus) + +The following commands may also be bf(+) prefixed. +startdl() + dl(bf(/+nl()./+nl()../+nl()../../)) + (access menuBar top level nl()\ + access current menu level nl()\ + access parent menu (1 level up) nl()\ + access parent menu (multiple levels up)) + dl(bf(em(/path/)menu)) + (add/access menu) + dl(bf(em(/path/)menu/*)) + (add/access menu and clear it if it exists) + dl(bf(em(/path/){-})) + (add separator) + dl(bf(em(/path/){item})) + (add bf(item) as a label) + dl(bf(em(/path/){item} action)) + (add/alter em(menuitem) with an associated em(action)) + dl(bf(em(/path/){item}{right-text})) + (add/alter em(menuitem) with bf(right-text) as the right-justified + text and as the associated em(action)) + dl(bf(em(/path/){item}{rtext} action)) + (add/alter em(menuitem) with an associated em(action) and with + bf(rtext) as the right-justified text.) +enddl() +startdl() + dl(Special characters in em(action) must be backslash-escaped:) + (bf(\a \b \E \e \n \r \t \octal)) + dl(or in control-character notation:) + (bf(^@, ^A .. ^Z .. ^_, ^?)) +enddl() + +To send a string starting with a bf(NUL) (bf(^@)) character to the program, +start em(action) with a pair of bf(NUL) characters (bf(^@^@)), the first of +which will be stripped off and the balance directed to the program. +Otherwise if em(action) begins with bf(NUL) followed by non-+bf(NUL) +characters, the leading bf(NUL) is stripped off and the balance is sent back +to rxvt. + +As a convenience for the many Emacs-type editors, em(action) may start +with bf(M-) (eg, bf(M-$) is equivalent to bf(\E$)) and a bf(CR) will be +appended if missed from bf(M-x) commands. + +As a convenience for issuing XTerm bf(ESC]) sequences from a menubar +(or quick arrow), a bf(BEL) (bf(^G)) will be appended if needed. + +startdl() + dl(For example,) + (bf(M-xapropos) is equivalent to bf(\Exapropos\r)) + dl(and) + (bf(\E]10;mona;100) is equivalent to bf(\E]10;mona;100\a)) +enddl() + +The option bf({em(right-rtext)}) will be right-justified. In the absence of +a specified action, this text will be used as the em(action) as well. + +startdl() + dl(For example,) + (bf(/File/{Open}{^X^F}) is equivalent to bf(/File/{Open}{^X^F} ^X^F)) +enddl() + +The left label em(is) necessary, since it's used for matching, +but implicitly hiding the left label (by using same name for both left +and right labels), or explicitly hiding the left label (by preceeding +it with a dot), makes it possible to have right-justified text only. +startdl() + dl(For example,) + (bf(/File/{Open}{Open} Open-File-Action)) + dl(or hiding it) + (bf(/File/{.anylabel}{Open} Open-File-Action)) +enddl() + +label(menuBarRemove) +nsubsect(Removing menus) + +startdl() + dl(bf(-/*+nl()-+em(/path)menu+nl()-+em(/path){item}+nl()-+em(/path){-})) + (remove all menus from the menuBar, the same as bf([clear])nl()\ + remove menu nl()\ + remove item nl()\ + remove separator) + dl(bf(-/path/menu/*)) + (remove all items, separators and submenus from menu) +enddl() + +label(menuBarArrows) +nsubsect(Quick Arrows) + +The menus also provide a hook for em(quick arrows) to provide easier user +access. If nothing has been explicitly set, the default is to emulate the +curror keys. The syntax permits each arrow to be altered individually or +all four at once without re-entering their common beginning/end text. For +example, to explicitly associate cursor actions with the arrows, any of +the following forms could be used: + +startdl() + dl(bf(+em(Right)nl()+em(Left)nl()+em(Up)nl()+em(Down))) + (Define actions for the respective arrow buttons) + dl(bf(+em(Begin)nl()+em(End))) + (Define common beginning/end parts for em(quick arrows) which used + in conjunction with the above constructs) +enddl() + +startdl() + dl(For example, define arrows individually,) + (bf(\E[A nl()\ + \E[B nl()\ + \E[C nl()\ + \E[D)) + dl(or all at once) + (bf(\E[A\E[B\E[C\E[D)) + dl(or more compactly (factoring out common parts)) + (bf(\E[ABCD)) +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(BeginRightLeftUpDownEnd) + (menu quick arrows) +enddl() diff --git a/doc/yodl/rxvtRef-mouse.yo b/doc/yodl/rxvtRef-mouse.yo new file mode 100644 index 00000000..0cbb44db --- /dev/null +++ b/doc/yodl/rxvtRef-mouse.yo @@ -0,0 +1,29 @@ +COMMENT(-- $Id: rxvtRef-mouse.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(Mouse) +nsect(Mouse Reporting) + +startdl() + dl(bf(tt(ESC [ M ))) + (report mouse position) +enddl() +The lower 2 bits of bf(tt()) indicate the button: +startdl() + dl(Button = bf(tt(( - 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()) indicate the modifiers when the button was +pressed and are added together (X11 mouse report only): + +startdl() + dl(State = bf(tt(( - SPACE) & 60))) + (4 = Shift nl()\ + 8 = Meta nl()\ + 16 = Control nl()\ + 32 = Double Click em((Rxvt extension)) nl()\ + Col = bf(tt( - SPACE)) nl()\ + Row = bf(tt( - SPACE))) +enddl() diff --git a/doc/yodl/rxvtRef-privatemodes.yo b/doc/yodl/rxvtRef-privatemodes.yo new file mode 100644 index 00000000..6bf74233 --- /dev/null +++ b/doc/yodl/rxvtRef-privatemodes.yo @@ -0,0 +1,164 @@ +COMMENT(-- $Id: rxvtRef-privatemodes.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(PrivateModes) +nsect(DEC Private Modes) + +startdl() + dl(bf(tt(ESC [ ? Pm h))) + (DEC Private Mode Set (DECSET)) +P()\ + dl(bf(tt(ESC [ ? Pm l))) + (DEC Private Mode Reset (DECRST)) +P()\ + dl(bf(tt(ESC [ ? Pm r))) + (Restore previously saved DEC Private Mode Values.) +P()\ + dl(bf(tt(ESC [ ? Pm s))) + (Save DEC Private Mode Values.) +P()\ + dl(bf(tt(ESC [ ? Pm t))) + (Toggle DEC Private Mode Values (rxvt extension).) + em(where) nl()\ +startdl() + dl(bf(tt(Ps = 1)) (DECCKM)) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Application Cursor Keys))\ + row(cell(bf(tt(l)))cell(Normal Cursor Keys))\ + endtable()) + dl(bf(tt(Ps = 2)) (ANSI/VT52 mode)) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Enter VT52 mode))\ + row(cell(bf(tt(l)))cell(Enter VT52 mode))\ + endtable()) + dl(bf(tt(Ps = 3))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(132 Column Mode (DECCOLM)))\ + row(cell(bf(tt(l)))cell(80 Column Mode (DECCOLM)))\ + endtable()) + dl(bf(tt(Ps = 4))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Smooth (Slow) Scroll (DECSCLM)))\ + row(cell(bf(tt(l)))cell(Jump (Fast) Scroll (DECSCLM)))\ + endtable()) + dl(bf(tt(Ps = 5))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Reverse Video (DECSCNM)))\ + row(cell(bf(tt(l)))cell(Normal Video (DECSCNM)))\ + endtable()) + dl(bf(tt(Ps = 6))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Origin Mode (DECOM)))\ + row(cell(bf(tt(l)))cell(Normal Cursor Mode (DECOM)))\ + endtable()) + dl(bf(tt(Ps = 7))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Wraparound Mode (DECAWM)))\ + row(cell(bf(tt(l)))cell(No Wraparound Mode (DECAWM)))\ + endtable()) + dl(bf(tt(Ps = 8)) em(unimplemented)) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Auto-repeat Keys (DECARM)))\ + row(cell(bf(tt(l)))cell(No Auto-repeat Keys (DECARM)))\ + endtable()) + dl(bf(tt(Ps = 9)) X10 XTerm link(mouse reporting)(Mouse)) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Send Mouse X & Y on button press.))\ + row(cell(bf(tt(l)))cell(No mouse reporting.))\ + endtable())\ +label(Priv10) + dl(bf(tt(Ps = 10)) (bf(rxvt))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(link(menuBar)(menuBar) visible))\ + row(cell(bf(tt(l)))cell(link(menuBar)(menuBar) invisible))\ + endtable()) + dl(bf(tt(Ps = 25))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Visible cursor {cnorm/cvvis}))\ + row(cell(bf(tt(l)))cell(Invisible cursor {civis}))\ + endtable()) + dl(bf(tt(Ps = 30))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(scrollBar visisble))\ + row(cell(bf(tt(l)))cell(scrollBar invisisble))\ + endtable()) + dl(bf(tt(Ps = 35)) (bf(rxvt))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Allow XTerm Shift+key sequences))\ + row(cell(bf(tt(l)))cell(Disallow XTerm Shift+key sequences))\ + endtable()) + dl(bf(tt(Ps = 38)) em(unimplemented)) + (Enter Tektronix Mode (DECTEK)) + dl(bf(tt(Ps = 40))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Allow 80/132 Mode))\ + row(cell(bf(tt(l)))cell(Disallow 80/132 Mode))\ + endtable()) + dl(bf(tt(Ps = 44)) em(unimplemented)) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Turn On Margin Bell))\ + row(cell(bf(tt(l)))cell(Turn Off Margin Bell))\ + endtable()) + dl(bf(tt(Ps = 45)) em(unimplemented)) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Reverse-wraparound Mode))\ + row(cell(bf(tt(l)))cell(No Reverse-wraparound Mode))\ + endtable()) + dl(bf(tt(Ps = 46)) em(unimplemented)) + () +P()\ + dl(bf(tt(Ps = 47))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Use Alternate Screen Buffer))\ + row(cell(bf(tt(l)))cell(Use Normal Screen Buffer))\ + endtable()) +label(Priv66) + dl(bf(tt(Ps = 66))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Application Keypad (DECPAM) == \ + link(tt(ESC =))(ESCequals)))\ + row(cell(bf(tt(l)))cell(Normal Keypad (DECPNM) == \ + link(tt(ESC >))(ESCequals)))\ + endtable()) + dl(bf(tt(Ps = 67))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Backspace key sends bf(tt(BS) \ + (DECBKM))))\ + row(cell(bf(tt(l)))cell(Backspace key sends bf(tt(DEL))))\ + endtable()) + dl(bf(tt(Ps = 1000)) (X11 XTerm link(mouse reporting)(Mouse))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Send Mouse X & Y on button press and \ + release.))\ + row(cell(bf(tt(l)))cell(No mouse reporting.))\ + endtable()) + dl(bf(tt(Ps = 1001)) (X11 XTerm link(mouse tracking)(Mouse)) \ + em(unimplemented)) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Use Hilite Mouse Tracking.))\ + row(cell(bf(tt(l)))cell(No mouse reporting.))\ + endtable()) + dl(bf(tt(Ps = 1010))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Don't scroll to bottom on TTY output))\ + row(cell(bf(tt(l)))cell(Scroll to bottom on TTY output))\ + endtable()) + dl(bf(tt(Ps = 1011))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Scroll to bottom when a key is \ + pressed))\ + row(cell(bf(tt(l)))cell(Don't scroll to bottom when a key is \ + pressed))\ + endtable()) + dl(bf(tt(Ps = 1047))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Use Alternate Screen Buffer))\ + row(cell(bf(tt(l)))cell(Use Normal Screen Buffer - clear \ + Alternate Screen Buffer if returning from it))\ + endtable()) + dl(bf(tt(Ps = 1048))) + (starttable(2)(l l)(0)\ + row(cell(bf(tt(h)))cell(Save cursor position))\ + row(cell(bf(tt(l)))cell(Restore cursor position))\ + endtable()) + enddl() +enddl() + diff --git a/doc/yodl/rxvtRef-sequences.yo b/doc/yodl/rxvtRef-sequences.yo new file mode 100644 index 00000000..0cd8fdab --- /dev/null +++ b/doc/yodl/rxvtRef-sequences.yo @@ -0,0 +1,77 @@ +COMMENT(-- $Id: rxvtRef-sequences.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(Sequences) +nsect(Escape Sequences) + +startdl() + dl(bf(tt(ESC # 8))) + (DEC Screen Alignment Test (DECALN)) +P()\ + dl(bf(tt(ESC 7)nl()tt(ESC 8))) + (Save Cursor (SC)nl()Restore Cursor)\ +P()\ +label(ESCequals) + dl(bf(tt(ESC =)nl()tt(ESC >))) + (Application Keypad (SMKX) == link(tt(ESC[?66h))(Priv66)nl()\ + Normal Keypad (RMKX) == link(tt(ESC[?66l))(Priv66))nl()\ +bf(Note:) If the numeric keypad is activated, eg, bf(Num_Lock) has been + pressed, numbers or control functions are generated by the numeric keypad + (see link(Key Codes)(KeyCodes)) +P()\ + dl(bf(tt(ESC D))) + (Index (IND)) +P()\ + dl(bf(tt(ESC E))) + (Next Line (NEL)) +P()\ + dl(bf(tt(ESC H))) + (Tab Set (HTS)) +P()\ + dl(bf(tt(ESC M))) + (Reverse Index (RI)) +P()\ + dl(bf(tt(ESC N))) + (Single Shift Select of G2 Character Set (SS2): affects next character + only em(unimplemented)) +P()\ + dl(bf(tt(ESC O))) + (Single Shift Select of G3 Character Set (SS3): affects next character + only em(unimplemented)) +P()\ + dl(bf(tt(ESC Z))) + (Obsolete form of link(tt(ESC[c))(ESCOBPsc) nl()\ + returns: bf(tt(ESC[?1;2C)) em(rxvt compile-time option)) +P()\ + dl(bf(tt(ESC c))) + (Full reset (RIS)) +P()\ + dl(bf(tt(ESC n))) + (Invoke the G2 Character Set (LS2)) +P()\ + dl(bf(tt(ESC o))) + (Invoke the G3 Character Set (LS3)) +P()\ + dl(bf(tt(ESC )CHAR(40)tt( C)nl()tt(ESC )CHAR(41)tt( C)nl()tt(ESC * C)nl()\ + tt(ESC + C)nl()tt(ESC $ C))) + (Designate G0 Character Set (ISO 2022)nl()\ + Designate G1 Character Set (ISO 2022)nl()\ + Designate G2 Character Set (ISO 2022)nl()\ + Designate G3 Character Set (ISO 2022)nl()\ + Designate Kanji Character Set nl()\ + em(where) bf(tt(C)) is nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(C = 0)))\ + cell(DEC Special Character and Line Drawing Set))\ + row(cell(bf(tt(C = A)))\ + cell(United Kingdom (UK)))\ + row(cell(bf(tt(C = B)))\ + cell(United States (USASCII)))\ + row(cell(bf(tt(C = <)))\ + cell(Multinational character set em(unimplemented)))\ + row(cell(bf(tt(C = 5)))\ + cell(Finnish character set em(unimplemented)))\ + row(cell(bf(tt(C = C)))\ + cell(Finnish character set em(unimplemented)))\ + row(cell(bf(tt(C = K)))\ + cell(German character set em(unimplemented)))\ + endtable()) +enddl() diff --git a/doc/yodl/rxvtRef-values.yo b/doc/yodl/rxvtRef-values.yo new file mode 100644 index 00000000..8b738f8c --- /dev/null +++ b/doc/yodl/rxvtRef-values.yo @@ -0,0 +1,41 @@ +COMMENT(-- $Id: rxvtRef-values.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(Values) +nsect(Values) + +startdl() + dl(bf(tt(ENQ))) + (Enquiry (Ctrl-E) = Send Device Attributes (DA) nl()\ + request attributes from terminal == link(ESC[Psc)(ESCOBPsc)) +P()\ + dl(bf(tt(BEL))) + (Bell (Ctrl-G)) +P()\ + dl(bf(tt(BS))) + (Backspace (Ctrl-H)) +P()\ + dl(bf(tt(TAB))) + (Horizontal Tab (HT) (Ctrl-I)) +P()\ + dl(bf(tt(LF))) + (Line Feed or New Line (NL) (Ctrl-J)) +P()\ + dl(bf(tt(VT))) + (Vertical Tab (Ctrl-K) same as bf(tt(LF))) +P()\ + dl(bf(tt(FF))) + (Form Feed or New Page (NP) (Ctrl-L) same as bf(tt(LF))) +P()\ + dl(bf(tt(CR))) + (Carriage Return (Ctrl-M)) +P()\ + dl(bf(tt(SO))) + (Shift Out (Ctrl-N), invokes the G1 character set. nl()\ + Switch to Alternate Character Set) +P()\ + dl(bf(tt(SI))) + (Shift In (Ctrl-O), invokes the G0 character set (the default) nl()\ + Switch to Standard Character Set) +P()\ + dl(bf(tt(SPC))) + (Space Character) +enddl() diff --git a/doc/yodl/rxvtRef-xpm.yo b/doc/yodl/rxvtRef-xpm.yo new file mode 100644 index 00000000..37fcb924 --- /dev/null +++ b/doc/yodl/rxvtRef-xpm.yo @@ -0,0 +1,47 @@ +COMMENT(-- $Id: rxvtRef-xpm.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +label(XPM) +nsect(XPM) + +For the XPM XTerm escape sequence bf(tt(ESC ] 20 ; Pt ST)) then value of +bf(tt(Pt)) can be the name of the background pixmap followed by a sequence of +scaling/positioning commands separated by semi-colons. The scaling/positioning +commands are as follows: + +startdl() + dl(query scale/position) + (bf(?)) +P()\ + dl(change scale and position) + (bf(WxH+X+Y)nl()\ + bf(WxH+X) (== bf(WxH+X+X))nl()\ + bf(WxH) (same as bf(WxH+50+50))nl()\ + bf(W+X+Y) (same as bf(WxW+X+Y))nl()\ + bf(W+X) (same as bf(WxW+X+X))nl()\ + bf(W) (same as bf(WxW+50+50))) +P()\ + dl(change position (absolute)) + (bf(=+X+Y)nl()\ + bf(=+X) (same as bf(=+X+Y))) +P()\ + dl(change position (relative)) + (bf(+X+Y)nl()\ + bf(+X) (same as bf(+X+Y))) +P()\ + dl(rescale (relative)) + (bf(Wx0) -> bf(W *= (W/100))nl()\ + bf(0xH) -> bf(H *= (H/100))) +enddl() + +For example: + +startdl() + dl(bf(\E]20;funky\a)) + (load bf(funky.xpm) as a tiled image) +P()\ + dl(bf(\E]20;mona;100\a)) + (load bf(mona.xpm) with a scaling of 100%) +P()\ + dl(bf(\E]20;;200;?\a)) + (rescale the current pixmap to 200% and display the image geometry in \ + the title) +enddl() diff --git a/doc/yodl/rxvtRef-xterm.yo b/doc/yodl/rxvtRef-xterm.yo new file mode 100644 index 00000000..e8fc6638 --- /dev/null +++ b/doc/yodl/rxvtRef-xterm.yo @@ -0,0 +1,67 @@ +COMMENT(-- $Id: rxvtRef-xterm.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +COMMENT(OSC: Operating System Commands) +label(XTerm) +nsect(XTerm Operating System Commands) + +startdl() + dl(bf(tt(ESC ] Ps;Pt ST))) + (Set XTerm Parameters nl()\ + 8-bit ST: 0x9c, nl()\ + 7-bit ST sequence: ESC \ (0x1b, 0x5c), nl()\ + backwards compatible terminator BEL (0x07) is also accepted. nl()\ + starttable(2)(l l)(0)\ + row(cell(bf(tt(Ps = 0)))\ + cell(Change Icon Name and Window Title to bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 1)))\ + cell(Change Icon Name to bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 2)))\ + cell(Change Window Title to bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 4)))\ + cell(bf(tt(Pt)) is a semi-colon separated sequence of one \ + or more semi-colon separated bf(number)/bf(name) pairs, \ + where bf(number) is an index to a colour and bf(name) is \ + the name of a colour. Each pair causes the bf(number)ed \ + colour to be changed to bf(name). nl()\ + Numbers 0-7 corresponds to low-intensity (normal) colours \ + and 8-15 corresponds to high-intensity colours. \ + 0=black, 1=red, 2=green, 3=yellow, 4=blue, 5=magenta, \ + 6=cyan, 7=white))\ + row(cell(bf(tt(Ps = 10)) bf((NB: may change in future)))\ + cell(link(menuBar)(menuBar) command bf(tt(Pt)) \ + em(rxvt compile-time option)))\ + row(cell(bf(tt(Ps = 12)))\ + cell(Change colour of text cursor foreground to bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 13)))\ + cell(Change colour of mouse foreground to bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 17)))\ + cell(Change colour of highlight characters to bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 18)))\ + cell(Change colour of bold characters to bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 19)))\ + cell(Change colour of underlined characters to bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 20)))\ + cell(Change default background link(pixmap)(XPM) to \ + bf(tt(Pt))))\ + row(cell(bf(tt(Ps = 39)))\ + cell(Change default foreground colour to bf(tt(Pt)) \ + em(rxvt compile-time option)))\ + row(cell(bf(tt(Ps = 46)))\ + cell(Change Log File to bf(tt(Pt)) \ + em(unimplemented)))\ + row(cell(bf(tt(Ps = 49)))\ + cell(Change default background colour to bf(tt(Pt)) \ + em(rxvt compile-time option)))\ + row(cell(bf(tt(Ps = 50)))\ + cell(Set Font to bf(tt(Pt)), with the following special \ + values of \ + bf(tt(Pt)) (bf(rxvt)) nl()\ + bf(tt(#+n)) change up bf(tt(n)) font(s) nl()\ + bf(tt(#-n)) change down bf(tt(n)) font(s) nl()\ + if bf(tt(n)) is missing of 0, a value of 1 is used nl()\ + em(empty) change to font0 nl()\ + bf(tt(n)) change to font bf(tt(n))))\ + row(cell(bf(tt(Ps = 55)))\ + cell(Log all scrollback buffer and all of screen to \ + bf(tt(Pt))))\ + endtable()) +enddl() diff --git a/doc/yodl/rxvtRef.yo b/doc/yodl/rxvtRef.yo new file mode 100644 index 00000000..b733f164 --- /dev/null +++ b/doc/yodl/rxvtRef.yo @@ -0,0 +1,65 @@ +COMMENT(-- $Id: rxvtRef.yo,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +mailto(gcw@pobox.com) +htmlbodyopt(BGCOLOR)(#FFFFFF) +notableofcontents() +article(Rxvt Technical Reference) + (Geoff Wing (gcw@pobox.com)) + (18 April 1998) +label(toc) +COMMENT(----------------------------------------------------------------------- +-- Originally written: Mark Olesen, Fri Feb 14 14:16:00 1997 +-- Converted to yodl: Geoff Wing +------------------------------------------------------------------------------) +COMMENT(--- + + +---) +includefile(masonyodl.yo) + +startit() + it()link(Definitions)(Definitions) + it()link(Values)(Values) + it()link(Escape Sequences)(Sequences) + it()link(CSI (Code Sequence Introducer) Sequences)(CSI) + it()link(DEC Private Modes)(PrivateModes) + it()link(XTerm Operating System Commands)(XTerm) + it()link(menuBar)(menuBar) + it()link(XPM)(XPM) + it()link(Mouse Reporting)(Mouse) + it()link(Special Graphics Mode)(Graphics) + it()link(Key Codes)(KeyCodes) +endit() + +Reworked from XTerm documentation and other sources +includefile(rxvtRef-definitions.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-values.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-sequences.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-csi.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-privatemodes.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-xterm.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-menubar.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-xpm.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-mouse.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-graphics.yo) +link(Top)(toc) +clearpage() +includefile(rxvtRef-keycodes.yo) +link(Top)(toc) diff --git a/doc/yodl/versioninfo.yo.in b/doc/yodl/versioninfo.yo.in new file mode 100644 index 00000000..7ba92344 --- /dev/null +++ b/doc/yodl/versioninfo.yo.in @@ -0,0 +1,17 @@ +COMMENT(-- $Id: versioninfo.yo.in,v 1.1 2003-11-24 17:28:08 pcg Exp $ --) +DEFINEMACRO(RXVTDATE)(0) + (@RXVT_DATE@) +DEFINEMACRO(RXVTVERSION)(0) + (@RXVT_VERSION@) +DEFINEMACRO(RXVTMAINT)(0) + (@RXVT_MAINT@) +DEFINEMACRO(RXVTMAINTEMAIL)(0) + (@RXVT_MAINTEMAIL@) +DEFINEMACRO(RXVTWEBMAINT)(0) + (@RXVT_WEBMAINT@) +DEFINEMACRO(RXVTWEBMAINTEMAIL)(0) + (@RXVT_WEBMAINTEMAIL@) +DEFINEMACRO(RXVTWEBPAGE)(0) + (@RXVT_WEBPAGE@) +DEFINEMACRO(RXVTFTPSITE)(0) + (ftp://@RXVT_FTPSITENAME@@RXVT_FTPSITEDIR@) diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 00000000..3228dba1 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,235 @@ +# $Id: Makefile.in,v 1.1 2003-11-24 17:28:08 pcg Exp $ +@MCOMMON@ + +LINT = lint -DNARROWPROTO=1 $(XINC) -chapbxz + +srcdir = @srcdir@ +VPATH = @srcdir@ +.PATH: @srcdir@ + +top_builddir = .. +basedir = .. +thisdir = src +MKDIR = @top_srcdir@/autoconf/mkinstalldirs + +SUPLIB = -lsupc++ + +# for developers: the following debug options may be used +# -DDEBUG_CMD -DDEBUG_MAIN -DDEBUG_MENU -DDEBUG_MENUARROWS +# -DDEBUG_MENUBAR_STACKING -DDEBUG_MENU_LAYOUT -DDEBUG_RESOURCES +# -DDEBUG_SCREEN -DDEBUG_SEARCH_PATH -DDEBUG_SELECT -DDEBUG_SIZE +# -DDEBUG_TTY -DDEBUG_TTYMODE -DDEBUG_X +DEBUG=-DDEBUG_STRICT @DEBUG@ + +first_rule: all +dummy: + +LIBSRCS = command.C defaultfont.C graphics.C grkelot.C init.C logging.C \ + main.C menubar.C misc.C netdisp.C ptytty.C screen.C scrollbar.C \ + scrollbar-rxvt.C scrollbar-next.C scrollbar-xterm.C strings.C \ + xdefaults.C xpm.C encoding.C rxvtcolor.C rxvtvec.C + +SRCS = rxvt.C $(LIBSRCS) + +HDRS = command.h defaultfont.h feature.h grkelot.h init.h logging.h \ + menubar.h netdisp.h protos.h rxvt.h rxvtgrx.h version.h encoding.h rxvtvec.h + +EXTRAHDRS = rxvtlib.h rxvtdaemon.h + +OBJS = command.o defaultfont.o init.o graphics.o grkelot.o logging.o \ + main.o menubar.o misc.o netdisp.o ptytty.o screen.o \ + scrollbar.o scrollbar-next.o scrollbar-rxvt.o scrollbar-xterm.o \ + strings.o xdefaults.o xpm.o rxvt.o encoding.o rxvtcolor.o rxvtvec.o +LIBOBJS = command.lo defaultfont.lo init.lo graphics.lo grkelot.lo logging.lo \ + main.lo menubar.lo misc.lo netdisp.lo ptytty.lo screen.lo \ + scrollbar.lo scrollbar-next.lo scrollbar-rxvt.lo scrollbar-xterm.lo \ + strings.lo xdefaults.lo xpm.lo encoding.lo rxvt.lo rxvtcolor.lo rxvtvec.lo + +LIBVERSION = @LIBVERSION@ +INSTALL_LIBRXVT = @INSTALL_LIBRXVT@ + +RXVT_BASENAME=`$(ECHO) $(RXVTNAME)|$(SED) 's/$(EXEEXT)$$//'|$(SED) '$(transform)'` +RXVT_BINNAME=$(DESTDIR)$(bindir)/$(RXVT_BASENAME)$(EXEEXT) +RXVT_VERNAME=$(DESTDIR)$(bindir)/$(RXVT_BASENAME)-$(VERSION)$(EXEEXT) +RXVT_OLDNAME=$(DESTDIR)$(bindir)/$(RXVT_BASENAME)-old$(EXEEXT) + +EXTPROS = command.extpro defaultfont.extpro graphics.extpro grkelot.extpro \ + init.extpro logging.extpro main.extpro menubar.extpro misc.extpro \ + netdisp.extpro ptytty.extpro screen.extpro scrollbar.extpro \ + scrollbar-rxvt.extpro scrollbar-next.extpro scrollbar-xterm.extpro \ + strings.extpro xdefaults.extpro xpm.extpro + +INTPROS = command.intpro defaultfont.intpro graphics.intpro grkelot.intpro \ + init.intpro logging.intpro main.intpro menubar.intpro misc.intpro \ + netdisp.intpro ptytty.intpro screen.intpro scrollbar.intpro \ + scrollbar-rxvt.intpro scrollbar-next.intpro scrollbar-xterm.intpro \ + strings.intpro xdefaults.intpro xpm.intpro + +DEPS = rxvt.h rxvtlib.h ${basedir}/config.h feature.h .protos + +# +# Distribution variables +# + +DIST = $(HDRS) $(SRCS) Makefile.in gcc-Wall rxvtlib.h.in .indent.pro \ + makeintprotos-awk makeextprotos-awk $(INTPROS) $(EXTPROS) .protos + +.SUFFIXES: .C .o .extpro .intpro .lo + +#------------------------------------------------------------------------- +# inference rules +.C.o: + $(COMPILE) -c $< + +.C.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.C.intpro: + @$(RMF) $@.tmp + @$(AWK) -f $(srcdir)/makeintprotos-awk $< > $@.tmp + @if $(CMP) -s $@ $@.tmp ; then : ; else $(ECHO) "$(AWK) -f $(srcdir)/makeintprotos-awk $< > $@"; $(CP) $@.tmp $@; fi + @$(RMF) $@.tmp + +.C.extpro: + @$(RMF) $@.tmp + @$(AWK) -f $(srcdir)/makeextprotos-awk $< > $@.tmp + @if $(CMP) -s $@ $@.tmp ; then : ; else $(ECHO) "$(AWK) -f $(srcdir)/makeextprotos-awk $< > $@"; $(CP) $@.tmp $@; fi + @$(RMF) $@.tmp +#------------------------------------------------------------------------- +all: allbin + +rxvt: version.h rxvt.o librxvt.la + $(LIBTOOL) --mode=link $(LINK) rxvt.o librxvt.la $(LIBS) $(XLIB) $(DLIB) $(SUPLIB) -o $@ + +rxvtd: version.h rxvtd.o librxvt.la iom.o rxvtdaemon.o + $(LIBTOOL) --mode=link $(LINK) rxvtd.o rxvtdaemon.o iom.o librxvt.la $(LIBS) $(XLIB) $(DLIB) $(SUPLIB) -o $@ + +rxvtc: version.h rxvtc.o rxvtdaemon.o + $(LIBTOOL) --mode=link $(LINK) rxvtc.o rxvtdaemon.o $(LIBS) $(DLIB) $(SUPLIB) -o $@ + +.protos: $(EXTPROS) + @$(RMF) .protos + date >.protos + +librxvt.la: $(LIBOBJS) + $(LIBTOOL) --mode=link $(LINK) -rpath $(libdir) -version-info $(LIBVERSION) $(LIBOBJS) $(LIBS) $(SUPLIB) -o $@ +#------------------------------------------------------------------------- +tags: $(SRCS) $(HDRS) $(EXTRAHDRS) + ctags $(SRCS) $(HDRS) $(EXTRAHDRS) + +allbin: .protos rxvt rxvtd rxvtc + +alldoc: + +clean: + $(RMF) rxvt core a.out *.o *.lo *.bak *~ *.intpro *.extpro .libs/* librxvt.la tmpproto .protos *.tmp + +realclean: clean + $(RMF) tags librxvt.h + +cleandir: realclean + +distclean: realclean + if test $(srcdir) = .; then $(MAKE) realclean; fi + (cd $(srcdir); $(RMF) Makefile) + +install: allbin alldoc + $(MKDIR) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir) + @if test x$(INSTALL_LIBRXVT) = xyes; then \ + $(ECHO) "$(LIBTOOL) --mode=install $(INSTALL_DATA) rxvtlib.h $(DESTDIR)$(includedir)/rxvtlib.h"; \ + $(LIBTOOL) --mode=install $(INSTALL_DATA) rxvtlib.h $(DESTDIR)$(includedir)/rxvtlib.h; \ + $(ECHO) "$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) librxvt.la $(DESTDIR)$(libdir)/librxvt.la"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) librxvt.la $(DESTDIR)$(libdir)/librxvt.la; \ + fi + @if test -f $(RXVT_BINNAME); then \ + $(ECHO) "$(RMF) $(RXVT_OLDNAME)"; \ + $(RMF) $(RXVT_OLDNAME); \ + $(ECHO) "$(MV) $(RXVT_BINNAME) $(RXVT_OLDNAME)"; \ + $(MV) $(RXVT_BINNAME) $(RXVT_OLDNAME); \ + fi + @$(ECHO) "$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) rxvt $(RXVT_VERNAME)" + @$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) rxvt $(RXVT_VERNAME) + @$(ECHO) "$(LN) $(RXVT_VERNAME) $(RXVT_BINNAME)" + @$(LN) $(RXVT_VERNAME) $(RXVT_BINNAME) + +uninstall: + @$(ECHO) $(RMF) $(RXVT_VERNAME) + @$(RMF) $(RXVT_VERNAME) + @$(ECHO) "$(LIBTOOL) --mode=uninstall $(RMF) $(RXVT_BINNAME)" + @$(LIBTOOL) --mode=uninstall $(RMF) $(RXVT_BINNAME) + @if test x$(INSTALL_LIBRXVT) = xyes; then \ + $(ECHO) "$(LIBTOOL) --mode=uninstall $(RMF) $(DESTDIR)$(libdir)/librxvt.la"; \ + $(LIBTOOL) --mode=uninstall $(RMF) $(DESTDIR)$(libdir)/librxvt.la; \ + $(ECHO) "$(LIBTOOL) --mode=uninstall $(RMF) $(DESTDIR)$(includedir)/rxvtlib.h"; \ + $(LIBTOOL) --mode=uninstall $(RMF) $(DESTDIR)$(includedir)/rxvtlib.h; \ + fi + +distdirs: + mkdir $(basedir)/../$(VERNAME)/$(thisdir) + +distcopy: .protos $(INTPROS) + $(CP) -p $(DIST) $(basedir)/../$(VERNAME)/$(thisdir) + +# ----------------------------------------------------------------------- +# DO NOT DELETE: nice dependency list follows +# + +defaultfont.h: encoding.h rxvtvec.h +rxvtlib.h: rxvtcolor.h defaultfont.h + +command.o: command.C $(DEPS) command.intpro command.h version.h +defaultfont.o: defaultfont.C $(DEPS) defaultfont.intpro defaultfont.h +graphics.o: graphics.C $(DEPS) graphics.intpro +grkelot.o: grkelot.C $(DEPS) grkelot.intpro grkelot.h +init.o: init.C $(DEPS) init.intpro init.h defaultfont.h +logging.o: logging.C $(DEPS) logging.intpro logging.h +main.o: main.C $(DEPS) main.intpro +menubar.o: menubar.C $(DEPS) menubar.intpro menubar.h version.h +misc.o: misc.C $(DEPS) misc.intpro +netdisp.o: netdisp.C $(DEPS) netdisp.intpro netdisp.h +ptytty.o: ptytty.C $(DEPS) ptytty.intpro +rxvt.o: rxvt.C $(DEPS) +rxvtd.o: rxvtd.C $(DEPS) rxvtdaemon.h +screen.o: screen.C $(DEPS) screen.intpro defaultfont.h +scrollbar.o: scrollbar.C $(DEPS) scrollbar.intpro +scrollbar-rxvt.o: scrollbar-rxvt.C $(DEPS) scrollbar-rxvt.intpro +scrollbar-next.o: scrollbar-next.C $(DEPS) scrollbar-next.intpro +scrollbar-xterm.o: scrollbar-xterm.C $(DEPS) scrollbar-xterm.intpro +strings.o: strings.C $(DEPS) strings.intpro +xdefaults.o: xdefaults.C $(DEPS) xdefaults.intpro version.h +xpm.o: xpm.C $(DEPS) xpm.intpro +encoding.o: encoding.C $(DEPS) encoding.h +rxvtcolor.o: rxvtcolor.C $(DEPS) + +command.lo: command.C $(DEPS) command.intpro command.h version.h +defaultfont.lo: defaultfont.C $(DEPS) defaultfont.intpro defaultfont.h encoding.h +graphics.lo: graphics.C $(DEPS) graphics.intpro defaultfont.h +grkelot.lo: grkelot.C $(DEPS) grkelot.intpro grkelot.h +init.lo: init.C $(DEPS) init.intpro init.h +logging.lo: logging.C $(DEPS) logging.intpro logging.h +main.lo: main.C $(DEPS) main.intpro +menubar.lo: menubar.C $(DEPS) menubar.intpro menubar.h version.h +misc.lo: misc.C $(DEPS) misc.intpro +netdisp.lo: netdisp.C $(DEPS) netdisp.intpro netdisp.h +ptytty.lo: ptytty.C $(DEPS) ptytty.intpro +rxvt.lo: rxvt.C $(DEPS) +screen.lo: screen.C $(DEPS) screen.intpro defaultfont.h +scrollbar.lo: scrollbar.C $(DEPS) scrollbar.intpro +scrollbar-rxvt.lo: scrollbar-rxvt.C $(DEPS) scrollbar-rxvt.intpro +scrollbar-next.lo: scrollbar-next.C $(DEPS) scrollbar-next.intpro +scrollbar-xterm.lo: scrollbar-xterm.C $(DEPS) scrollbar-xterm.intpro +strings.lo: strings.C $(DEPS) strings.intpro +xdefaults.lo: xdefaults.C $(DEPS) xdefaults.intpro version.h +xpm.lo: xpm.C $(DEPS) xpm.intpro +encoding.lo: encoding.C $(DEPS) encoding.h +rxvtcolor.lo: rxvtcolor.C $(DEPS) + +iom.o: iom.C iom.h +rxvtdaemon.o: rxvtdaemon.C rxvtdaemon.h + diff --git a/src/command.C b/src/command.C new file mode 100644 index 00000000..7201dfca --- /dev/null +++ b/src/command.C @@ -0,0 +1,3583 @@ +/*--------------------------------*-C-*---------------------------------* + * File: command.c + *----------------------------------------------------------------------* + * $Id: command.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1992 John Bovey, University of Kent at Canterbury + * - original version + * Copyright (c) 1994 Robert Nation + * - extensive modifications + * Copyright (c) 1995 Garrett D'Amore + * - vt100 printing + * Copyright (c) 1995 Steven Hirsch + * - X11 mouse report mode and support for + * DEC "private mode" save/restore functions. + * Copyright (c) 1995 Jakub Jelinek + * - key-related changes to handle Shift+function + * keys properly. + * Copyright (c) 1997 MJ Olesen + * - extensive modifications + * Copyright (c) 1997 Raul Garcia Garcia + * - modification and cleanups for Solaris 2.x + * and Linux 1.2.x + * Copyright (c) 1997,1998 Oezguer Kesim + * Copyright (c) 1998-2001 Geoff Wing + * - extensive modifications + * Copyright (c) 1998 Alfredo K. Kojima + * Copyright (c) 2001 Marius Gedminas + * - Ctrl/Mod4+Tab works like Meta+Tab (options) + * Copyright (c) 2003 Rob McMullen + * + * 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 == ). + */ + 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.yTermWin.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.yTermWin.int_bwidth) { + h->scroll_selection_dir = UP; + dist = R->TermWin.int_bwidth - ev->xbutton.y; + } + else { + h->scroll_selection_dir = DN; + dist = ev->xbutton.y - + (R->TermWin.int_bwidth + R->TermWin.height); + } + h->scroll_selection_lines=(Pixel2Height(dist)/ + SELECTION_SCROLL_LINE_SPEEDUP)+1; + MIN_IT(h->scroll_selection_lines, + SELECTION_SCROLL_MAX_LINES); + } + else { + /* we are within the text window, so we + * shouldn't be scrolling + */ + h->pending_scroll_selection = 0; + } +#endif +#ifdef MOUSE_THRESHOLD + } +#endif + } + } else if (isScrollbarWindow(ev->xany.window) && scrollbar_isMotion()) { + while (XCheckTypedWindowEvent(R->Xdisplay, R->scrollBar.win, + MotionNotify, ev)) ; + XQueryPointer(R->Xdisplay, R->scrollBar.win, + &unused_root, &unused_child, + &unused_root_x, &unused_root_y, + &(ev->xbutton.x), &(ev->xbutton.y), + &unused_mask); + rxvt_scr_move_to(aR_ scrollbar_position(ev->xbutton.y) - h->csrO, + scrollbar_size()); + rxvt_scr_refresh(aR_ h->refresh_type); + h->refresh_limit = 0; + rxvt_scrollbar_show(aR_ 1); + } + break; + } +} + +/* INTPROTO */ +void +rxvt_button_press(pR_ XButtonEvent *ev) +{ + int reportmode = 0, clickintime; + struct rxvt_hidden *h = R->h; + + h->bypass_keystate = ev->state & (h->ModMetaMask | ShiftMask); + if (!h->bypass_keystate) + reportmode = !!(h->PrivateModes & PrivMode_mouse_report); +/* + * VT window processing of button press + */ + if (ev->window == R->TermWin.vt) + { +#if RXVT_GRAPHICS + if (ev->subwindow != None) + rxvt_Gr_ButtonPress(ev->x, ev->y); + else +#endif + { + clickintime = ev->time - h->MEvent.time < MULTICLICK_TIME; + if (reportmode) + { + /* mouse report from vt window */ + /* save the xbutton state (for ButtonRelease) */ + h->MEvent.state = ev->state; +#ifdef MOUSE_REPORT_DOUBLECLICK + if (ev->button == h->MEvent.button && clickintime) + { + /* same button, within alloted time */ + h->MEvent.clicks++; + if (h->MEvent.clicks > 1) + { + /* only report double clicks */ + h->MEvent.clicks = 2; + rxvt_mouse_report(aR_ ev); + + /* don't report the release */ + h->MEvent.clicks = 0; + h->MEvent.button = AnyButton; + } + } + else + { + /* different button, or time expired */ + h->MEvent.clicks = 1; + h->MEvent.button = ev->button; + rxvt_mouse_report(aR_ ev); + } +#else + h->MEvent.button = ev->button; + rxvt_mouse_report(aR_ ev); +#endif /* MOUSE_REPORT_DOUBLECLICK */ + } + else + { + if (ev->button != h->MEvent.button) + h->MEvent.clicks = 0; + switch (ev->button) + { + case Button1: + if (h->MEvent.button == Button1 && clickintime) + h->MEvent.clicks++; + else + h->MEvent.clicks = 1; + rxvt_selection_click(aR_ h->MEvent.clicks, ev->x, ev->y); + h->MEvent.button = Button1; + break; + + case Button3: + if (h->MEvent.button == Button3 && clickintime) + rxvt_selection_rotate(aR_ ev->x, ev->y); + else + rxvt_selection_extend(aR_ ev->x, ev->y, 1); + h->MEvent.button = Button3; + break; + } + } + h->MEvent.time = ev->time; + return; + } + } + +/* + * Scrollbar window processing of button press + */ + if (isScrollbarWindow(ev->window)) + { + scrollbar_setIdle(); + /* + * Rxvt-style scrollbar: + * move up if mouse is above slider + * move dn if mouse is below slider + * + * XTerm-style scrollbar: + * Move display proportional to pointer location + * pointer near top -> scroll one line + * pointer near bot -> scroll full page + */ +#ifndef NO_SCROLLBAR_REPORT + if (reportmode) { + /* + * Mouse report disabled scrollbar: + * arrow buttons - send up/down + * click on scrollbar - send pageup/down + */ + if ((R->scrollBar.style == R_SB_NEXT + && scrollbarnext_upButton(ev->y)) + || (R->scrollBar.style == R_SB_RXVT + && scrollbarrxvt_upButton(ev->y))) + rxvt_tt_printf(aR_ "\033[A"); + else if ((R->scrollBar.style == R_SB_NEXT + && scrollbarnext_dnButton(ev->y)) + || (R->scrollBar.style == R_SB_RXVT + && scrollbarrxvt_dnButton(ev->y))) + rxvt_tt_printf(aR_ "\033[B"); + else + switch (ev->button) { + case Button2: + rxvt_tt_printf(aR_ "\014"); + break; + case Button1: + rxvt_tt_printf(aR_ "\033[6~"); + break; + case Button3: + rxvt_tt_printf(aR_ "\033[5~"); + break; + } + } + else +#endif /* NO_SCROLLBAR_REPORT */ + { + char upordown = 0; + + if (R->scrollBar.style == R_SB_NEXT) { + if (scrollbarnext_upButton(ev->y)) + upordown = -1; /* up */ + else if (scrollbarnext_dnButton(ev->y)) + upordown = 1; /* down */ + } else if (R->scrollBar.style == R_SB_RXVT) { + if (scrollbarrxvt_upButton(ev->y)) + upordown = -1; /* up */ + else if (scrollbarrxvt_dnButton(ev->y)) + upordown = 1; /* down */ + } + if (upordown) { +#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + h->scroll_arrow_delay = SCROLLBAR_INITIAL_DELAY; +#endif + if (rxvt_scr_page(aR_ upordown < 0 ? UP : DN, 1)) { + if (upordown < 0) + scrollbar_setUp(); + else + scrollbar_setDn(); + } + } else + switch (ev->button) { + case Button2: + switch (h->scrollbar_align) { + case R_SB_ALIGN_TOP: + h->csrO = 0; + break; + case R_SB_ALIGN_CENTRE: + h->csrO = (R->scrollBar.bot - R->scrollBar.top) / 2; + break; + case R_SB_ALIGN_BOTTOM: + h->csrO = R->scrollBar.bot - R->scrollBar.top; + break; + } + if (R->scrollBar.style == R_SB_XTERM + || scrollbar_above_slider(ev->y) + || scrollbar_below_slider(ev->y)) + rxvt_scr_move_to(aR_ + scrollbar_position(ev->y) - h->csrO, + scrollbar_size()); + scrollbar_setMotion(); + break; + + case Button1: + if (h->scrollbar_align == R_SB_ALIGN_CENTRE) + h->csrO = ev->y - R->scrollBar.top; + /* FALLTHROUGH */ + + case Button3: + if (R->scrollBar.style != R_SB_XTERM) { + if (scrollbar_above_slider(ev->y)) +# ifdef RXVT_SCROLL_FULL + rxvt_scr_page(aR_ UP, R->TermWin.nrow - 1); +# else + rxvt_scr_page(aR_ UP, R->TermWin.nrow / 4); +# endif + else if (scrollbar_below_slider(ev->y)) +# ifdef RXVT_SCROLL_FULL + rxvt_scr_page(aR_ DN, R->TermWin.nrow - 1); +# else + rxvt_scr_page(aR_ DN, R->TermWin.nrow / 4); +# endif + else + scrollbar_setMotion(); + } else { + rxvt_scr_page(aR_ (ev->button == Button1 ? DN : UP), + (R->TermWin.nrow + * scrollbar_position(ev->y) + / scrollbar_size())); + } + break; + } + } + return; + } +#if MENUBAR + /* + * Menubar window processing of button press + */ + if (isMenuBarWindow(ev->window)) + rxvt_menubar_control(aR_ ev); +#endif +} + +/* INTPROTO */ +void +rxvt_button_release(pR_ XButtonEvent *ev) +{ + int reportmode = 0; + + R->h->csrO = 0; /* reset csr Offset */ + if (!R->h->bypass_keystate) + reportmode = !!(R->h->PrivateModes & PrivMode_mouse_report); + + if (scrollbar_isUpDn()) { + scrollbar_setIdle(); + rxvt_scrollbar_show(aR_ 0); +#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + R->h->refresh_type &= ~SMOOTH_REFRESH; +#endif + } +#ifdef SELECTION_SCROLLING + R->h->pending_scroll_selection=0; +#endif + if (ev->window == R->TermWin.vt) + { +#ifdef RXVT_GRAPHICS + if (ev->subwindow != None) + rxvt_Gr_ButtonRelease(ev->x, ev->y); + else +#endif + { + if (reportmode) + { + /* mouse report from vt window */ + /* don't report release of wheel "buttons" */ + if (ev->button >= 4) + return; +#ifdef MOUSE_REPORT_DOUBLECLICK + /* only report the release of 'slow' single clicks */ + if (R->h->MEvent.button != AnyButton + && (ev->button != R->h->MEvent.button + || (ev->time - R->h->MEvent.time + > MULTICLICK_TIME / 2))) + { + R->h->MEvent.clicks = 0; + R->h->MEvent.button = AnyButton; + rxvt_mouse_report(aR_ ev); + } +#else /* MOUSE_REPORT_DOUBLECLICK */ + R->h->MEvent.button = AnyButton; + rxvt_mouse_report(aR_ ev); +#endif /* MOUSE_REPORT_DOUBLECLICK */ + return; + } + /* + * dumb hack to compensate for the failure of click-and-drag + * when overriding mouse reporting + */ + if (R->h->PrivateModes & PrivMode_mouse_report + && R->h->bypass_keystate + && ev->button == Button1 && R->h->MEvent.clicks <= 1) + rxvt_selection_extend(aR_ ev->x, ev->y, 0); + + switch (ev->button) { + case Button1: + case Button3: + rxvt_selection_make(aR_ ev->time); + break; + case Button2: + rxvt_selection_request(aR_ ev->time, ev->x, ev->y); + break; +#ifdef MOUSE_WHEEL + case Button4: + case Button5: + { + int i, v; + + v = (ev->button == Button4) ? UP : DN; + if (ev->state & ShiftMask) + i = 1; + else if ((R->Options & Opt_mouseWheelScrollPage)) + i = R->TermWin.nrow - 1; + else + i = 5; +# ifdef MOUSE_SLIP_WHEELING + if (ev->state & ControlMask) + { + R->h->mouse_slip_wheel_speed += (v ? -1 : 1); + R->h->mouse_slip_wheel_delay = SCROLLBAR_CONTINUOUS_DELAY; + } +# endif +# ifdef JUMP_MOUSE_WHEEL + rxvt_scr_page(aR_ v, i); + rxvt_scr_refresh(aR_ SMOOTH_REFRESH); + rxvt_scrollbar_show(aR_ 1); +# else + for (; i--;) + { + rxvt_scr_page(aR_ v, 1); + rxvt_scr_refresh(aR_ SMOOTH_REFRESH); + rxvt_scrollbar_show(aR_ 1); + } +# endif + } + break; +#endif + } + } + } +#ifdef MENUBAR + else if (isMenuBarWindow(ev->window)) + rxvt_menubar_control(aR_ ev); +#endif +} + + +#ifdef TRANSPARENT +/* + * Check our parents are still who we think they are. + * Do transparency updates if required + */ +/* EXTPROTO */ +int +rxvt_check_our_parents(pR) +{ + int i, pchanged, aformat, have_pixmap, rootdepth; + unsigned long nitems, bytes_after; + Atom atype; + unsigned char *prop = NULL; + Window root, oldp, *list; + Pixmap rootpixmap = None; + XWindowAttributes wattr, wrootattr; + + pchanged = 0; + + if (!(R->Options & Opt_transparent)) + return pchanged; /* Don't try any more */ + + XGetWindowAttributes(R->Xdisplay, Xroot, &wrootattr); + rootdepth = wrootattr.depth; + + XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr); + if (rootdepth != wattr.depth) { + if (R->h->am_transparent) { + pchanged = 1; + XSetWindowBackground(R->Xdisplay, R->TermWin.vt, + R->PixColors[Color_bg]); + R->h->am_transparent = R->h->am_pixmap_trans = 0; + } + return pchanged; /* Don't try any more */ + } + +/* Get all X ops out of the queue so that our information is up-to-date. */ + XSync(R->Xdisplay, False); + +/* + * Make the frame window set by the window manager have + * the root background. Some window managers put multiple nested frame + * windows for each client, so we have to take care about that. + */ + i = (R->h->xa[XA_XROOTPMAPID] != 0 + && (XGetWindowProperty(R->Xdisplay, Xroot, R->h->xa[XA_XROOTPMAPID], + 0L, 1L, False, XA_PIXMAP, &atype, &aformat, + &nitems, &bytes_after, &prop) == Success)); + if (!i || prop == NULL) + have_pixmap = 0; + else { + have_pixmap = 1; + rootpixmap = *((Pixmap *)prop); + XFree(prop); + } + if (have_pixmap) { +/* + * Copy Xroot pixmap transparency + */ + int sx, sy, nx, ny; + unsigned int nw, nh; + Window cr; + XImage *image; + GC gc; + XGCValues gcvalue; + + XTranslateCoordinates(R->Xdisplay, R->TermWin.parent[0], Xroot, + 0, 0, &sx, &sy, &cr); + nw = (unsigned int)R->szHint.width; + nh = (unsigned int)R->szHint.height; + nx = ny = 0; + if (sx < 0) { + nw += sx; + nx = -sx; + sx = 0; + } + if (sy < 0) { + nh += sy; + ny = -sy; + sy = 0; + } + MIN_IT(nw, (unsigned int)(wrootattr.width - sx)); + MIN_IT(nh, (unsigned int)(wrootattr.height - sy)); + R->h->allowedxerror = -1; + image = XGetImage(R->Xdisplay, rootpixmap, sx, sy, nw, nh, AllPlanes, + ZPixmap); + /* XXX: handle BadMatch - usually because we're outside the pixmap */ + /* XXX: may need a delay here? */ + R->h->allowedxerror = 0; + if (image == NULL) { + if (R->h->am_transparent && R->h->am_pixmap_trans) { + pchanged = 1; + if (R->TermWin.pixmap != None) { + XFreePixmap(R->Xdisplay, R->TermWin.pixmap); + R->TermWin.pixmap = None; + } + } + R->h->am_pixmap_trans = 0; + } else { + if (R->TermWin.pixmap != None) + XFreePixmap(R->Xdisplay, R->TermWin.pixmap); + R->TermWin.pixmap = XCreatePixmap(R->Xdisplay, R->TermWin.vt, + (unsigned int)R->szHint.width, + (unsigned int)R->szHint.height, + (unsigned int)image->depth); + gc = XCreateGC(R->Xdisplay, R->TermWin.vt, 0UL, &gcvalue); + XPutImage(R->Xdisplay, R->TermWin.pixmap, gc, image, 0, 0, + nx, ny, (unsigned int)image->width, + (unsigned int)image->height); + XFreeGC(R->Xdisplay, gc); + XDestroyImage(image); + XSetWindowBackgroundPixmap(R->Xdisplay, R->TermWin.vt, + R->TermWin.pixmap); + if (!R->h->am_transparent || !R->h->am_pixmap_trans) + pchanged = 1; + R->h->am_transparent = R->h->am_pixmap_trans = 1; + } + } + if (!R->h->am_pixmap_trans) { + unsigned int n; +/* + * InheritPixmap transparency + */ + D_X((stderr, "InheritPixmap Seeking to %08lx", Xroot)); + for (i = 1; i < (int)(sizeof(R->TermWin.parent) / sizeof(Window)); + i++) { + oldp = R->TermWin.parent[i]; + XQueryTree(R->Xdisplay, R->TermWin.parent[i - 1], &root, + &R->TermWin.parent[i], &list, &n); + XFree(list); + D_X((stderr, "InheritPixmap Parent[%d] = %08lx", i, R->TermWin.parent[i])); + if (R->TermWin.parent[i] == Xroot) { + if (oldp != None) + pchanged = 1; + break; + } + if (oldp != R->TermWin.parent[i]) + pchanged = 1; + } + n = 0; + if (pchanged) { + for (; n < (unsigned int)i; n++) { + XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[n], &wattr); + D_X((stderr, "InheritPixmap Checking Parent[%d]: %s", n, (wattr.depth == rootdepth && wattr.class != InputOnly) ? "OK" : "FAIL")); + if (wattr.depth != rootdepth || wattr.class == InputOnly) { + n = (int)(sizeof(R->TermWin.parent) / sizeof(Window)) + 1; + break; + } + } + } + if (n > (int)(sizeof(R->TermWin.parent) + / sizeof(R->TermWin.parent[0]))) { + D_X((stderr, "InheritPixmap Turning off")); + XSetWindowBackground(R->Xdisplay, R->TermWin.parent[0], + R->PixColors[Color_fg]); + XSetWindowBackground(R->Xdisplay, R->TermWin.vt, + R->PixColors[Color_bg]); + R->h->am_transparent = 0; + /* XXX: also turn off Opt_transparent? */ + } else { + /* wait (an arbitrary period) for the WM to do its thing + * needed for fvwm2.2.2 (and before?) */ +# ifdef HAVE_NANOSLEEP + struct timespec rqt; + + rqt.tv_sec = 1; + rqt.tv_nsec = 0; + nanosleep(&rqt, NULL); +# else + sleep(1); +# endif + D_X((stderr, "InheritPixmap Turning on (%d parents)", i - 1)); + for (n = 0; n < (unsigned int)i; n++) + XSetWindowBackgroundPixmap(R->Xdisplay, R->TermWin.parent[n], + ParentRelative); + XSetWindowBackgroundPixmap(R->Xdisplay, R->TermWin.vt, + ParentRelative); + R->h->am_transparent = 1; + } + for (; i < (int)(sizeof(R->TermWin.parent) / sizeof(Window)); i++) + R->TermWin.parent[i] = None; + } + return pchanged; +} +#endif + +/*}}} */ + +/*{{{ print pipe */ +/*----------------------------------------------------------------------*/ +#ifdef PRINTPIPE +/* EXTPROTO */ +FILE * +rxvt_popen_printer(pR) +{ + FILE *stream = popen(R->h->rs[Rs_print_pipe], "w"); + + if (stream == NULL) + rxvt_print_error("can't open printer pipe"); + return stream; +} + +/* EXTPROTO */ +int +rxvt_pclose_printer(FILE *stream) +{ + fflush(stream); +/* pclose() reported not to work on SunOS 4.1.3 */ +# if defined (__sun__) /* TODO: RESOLVE THIS */ +/* pclose works provided SIGCHLD handler uses waitpid */ + return pclose(stream); /* return fclose (stream); */ +# else + return pclose(stream); +# endif +} + +/* + * simulate attached vt100 printer + */ +/* INTPROTO */ +void +rxvt_process_print_pipe(pR) +{ + int done; + FILE *fd; + + if ((fd = rxvt_popen_printer(aR)) == NULL) + return; + +/* + * Send all input to the printer until either ESC[4i or ESC[?4i + * is received. + */ + for (done = 0; !done;) { + unsigned char buf[8]; + unsigned char ch; + unsigned int i, len; + + if ((ch = rxvt_cmd_getc(aR)) != C0_ESC) { + if (putc(ch, fd) == EOF) + break; /* done = 1 */ + } else { + len = 0; + buf[len++] = ch; + + if ((buf[len++] = rxvt_cmd_getc(aR)) == '[') { + if ((ch = rxvt_cmd_getc(aR)) == '?') { + buf[len++] = '?'; + ch = rxvt_cmd_getc(aR); + } + if ((buf[len++] = ch) == '4') { + if ((buf[len++] = rxvt_cmd_getc(aR)) == 'i') + break; /* done = 1 */ + } + } + for (i = 0; i < len; i++) + if (putc(buf[i], fd) == EOF) { + done = 1; + break; + } + } + } + rxvt_pclose_printer(fd); +} +#endif /* PRINTPIPE */ +/*}}} */ + +/* *INDENT-OFF* */ +enum { + C1_40 = 0x40, + C1_41 , C1_BPH, C1_NBH, C1_44 , C1_NEL, C1_SSA, C1_ESA, + C1_HTS, C1_HTJ, C1_VTS, C1_PLD, C1_PLU, C1_RI , C1_SS2, C1_SS3, + C1_DCS, C1_PU1, C1_PU2, C1_STS, C1_CCH, C1_MW , C1_SPA, C1_EPA, + C1_SOS, C1_59 , C1_SCI, C1_CSI, CS_ST , C1_OSC, C1_PM , C1_APC +}; +/* *INDENT-ON* */ + +/*{{{ process non-printing single characters */ +/* INTPROTO */ +void +rxvt_process_nonprinting(pR_ unsigned char ch) +{ + switch (ch) { + case C0_ENQ: /* terminal Status */ + if (R->h->rs[Rs_answerbackstring]) + rxvt_tt_write(aR_ + (const unsigned char *)R->h->rs[Rs_answerbackstring], + (unsigned int)STRLEN(R->h->rs[Rs_answerbackstring])); + else + rxvt_tt_write(aR_ (unsigned char *)VT100_ANS, + (unsigned int)STRLEN(VT100_ANS)); + break; + case C0_BEL: /* bell */ + rxvt_scr_bell(aR); + break; + case C0_BS: /* backspace */ + rxvt_scr_backspace(aR); + break; + case C0_HT: /* tab */ + rxvt_scr_tab(aR_ 1); + break; + case C0_CR: /* carriage return */ + rxvt_scr_gotorc(aR_ 0, 0, R_RELATIVE); + break; + case C0_VT: /* vertical tab, form feed */ + case C0_FF: + case C0_LF: /* line feed */ + rxvt_scr_index(aR_ UP); + break; + case C0_SO: /* shift out - acs */ + rxvt_scr_charset_choose(aR_ 1); + break; + case C0_SI: /* shift in - acs */ + rxvt_scr_charset_choose(aR_ 0); + break; + } +} +/*}}} */ + + +/*{{{ process VT52 escape sequences */ +/* INTPROTO */ +void +rxvt_process_escape_vt52(pR_ unsigned char ch) +{ + int row, col; + + switch (ch) { + case 'A': /* cursor up */ + rxvt_scr_gotorc(aR_ -1, 0, R_RELATIVE | C_RELATIVE); + break; + case 'B': /* cursor down */ + rxvt_scr_gotorc(aR_ 1, 0, R_RELATIVE | C_RELATIVE); + break; + case 'C': /* cursor right */ + rxvt_scr_gotorc(aR_ 0, 1, R_RELATIVE | C_RELATIVE); + break; + case 'D': /* cursor left */ + rxvt_scr_gotorc(aR_ 0, -1, R_RELATIVE | C_RELATIVE); + break; + case 'H': /* cursor home */ + rxvt_scr_gotorc(aR_ 0, 0, 0); + break; + case 'I': /* cursor up and scroll down if needed */ + rxvt_scr_index(aR_ DN); + break; + case 'J': /* erase to end of screen */ + rxvt_scr_erase_screen(aR_ 0); + break; + case 'K': /* erase to end of line */ + rxvt_scr_erase_line(aR_ 0); + break; + case 'Y': /* move to specified row and col */ + /* full command is 'ESC Y row col' where row and col + * are encoded by adding 32 and sending the ascii + * character. eg. SPACE = 0, '+' = 13, '0' = 18, + * etc. */ + row = rxvt_cmd_getc(aR) - ' '; + col = rxvt_cmd_getc(aR) - ' '; + rxvt_scr_gotorc(aR_ row, col, 0); + break; + case 'Z': /* identify the terminal type */ + rxvt_tt_printf(aR_ "\033/Z"); /* I am a VT100 emulating a VT52 */ + break; + case '<': /* turn off VT52 mode */ + PrivMode(0, PrivMode_vt52); + break; + case 'F': /* use special graphics character set */ + case 'G': /* use regular character set */ + /* unimplemented */ + break; + case '=': /* use alternate keypad mode */ + case '>': /* use regular keypad mode */ + /* unimplemented */ + break; + } +} +/*}}} */ + + +/*{{{ process escape sequences */ +/* INTPROTO */ +void +rxvt_process_escape_seq(pR) +{ + unsigned char ch = rxvt_cmd_getc(aR); + + if (R->h->PrivateModes & PrivMode_vt52) { + rxvt_process_escape_vt52(aR_ ch); + return; + } + + switch (ch) { + /* case 1: do_tek_mode (); break; */ + case '#': + if (rxvt_cmd_getc(aR) == '8') + rxvt_scr_E(aR); + break; + case '(': + rxvt_scr_charset_set(aR_ 0, (unsigned int)rxvt_cmd_getc(aR)); + break; + case ')': + rxvt_scr_charset_set(aR_ 1, (unsigned int)rxvt_cmd_getc(aR)); + break; + case '*': + rxvt_scr_charset_set(aR_ 2, (unsigned int)rxvt_cmd_getc(aR)); + break; + case '+': + rxvt_scr_charset_set(aR_ 3, (unsigned int)rxvt_cmd_getc(aR)); + break; +#ifdef MULTICHAR_SET + case '$': + rxvt_scr_charset_set(aR_ -2, (unsigned int)rxvt_cmd_getc(aR)); + break; +#endif +#ifndef NO_FRILLS + case '6': + rxvt_scr_backindex(aR); + break; +#endif + case '7': + rxvt_scr_cursor(aR_ SAVE); + break; + case '8': + rxvt_scr_cursor(aR_ RESTORE); + break; +#ifndef NO_FRILLS + case '9': + rxvt_scr_forwardindex(aR); + break; +#endif + case '=': + case '>': + PrivMode((ch == '='), PrivMode_aplKP); + break; + + case C1_40: + rxvt_cmd_getc(aR); + break; + case C1_44: + rxvt_scr_index(aR_ UP); + break; + + /* 8.3.87: NEXT LINE */ + case C1_NEL: /* ESC E */ + { + uint32_t nlcr[] = { '\n', '\r' }; + rxvt_scr_add_lines(aR_ nlcr, 1, 2); + } + break; + + /* kidnapped escape sequence: Should be 8.3.48 */ + case C1_ESA: /* ESC G */ + rxvt_process_graphics(aR); + break; + + /* 8.3.63: CHARACTER TABULATION SET */ + case C1_HTS: /* ESC H */ + rxvt_scr_set_tab(aR_ 1); + break; + + /* 8.3.105: REVERSE LINE FEED */ + case C1_RI: /* ESC M */ + rxvt_scr_index(aR_ DN); + break; + + /* 8.3.142: SINGLE-SHIFT TWO */ + /*case C1_SS2: scr_single_shift (2); break; */ + + /* 8.3.143: SINGLE-SHIFT THREE */ + /*case C1_SS3: scr_single_shift (3); break; */ + + /* 8.3.27: DEVICE CONTROL STRING */ + case C1_DCS: /* ESC P */ + rxvt_process_dcs_seq(aR); + break; + + /* 8.3.110: SINGLE CHARACTER INTRODUCER */ + case C1_SCI: /* ESC Z */ + rxvt_tt_write(aR_ (const unsigned char *)ESCZ_ANSWER, + (unsigned int)(sizeof(ESCZ_ANSWER) - 1)); + break; /* steal obsolete ESC [ c */ + + /* 8.3.16: CONTROL SEQUENCE INTRODUCER */ + case C1_CSI: /* ESC [ */ + rxvt_process_csi_seq(aR); + break; + + /* 8.3.90: OPERATING SYSTEM COMMAND */ + case C1_OSC: /* ESC ] */ + rxvt_process_osc_seq(aR); + break; + + /* 8.3.106: RESET TO INITIAL STATE */ + case 'c': + rxvt_scr_poweron(aR); + rxvt_scrollbar_show(aR_ 1); + break; + + /* 8.3.79: LOCKING-SHIFT TWO (see ISO2022) */ + case 'n': + rxvt_scr_charset_choose(aR_ 2); + break; + + /* 8.3.81: LOCKING-SHIFT THREE (see ISO2022) */ + case 'o': + rxvt_scr_charset_choose(aR_ 3); + break; + } +} +/*}}} */ + +/*{{{ process CONTROL SEQUENCE INTRODUCER (CSI) sequences `ESC[' */ +/* *INDENT-OFF* */ +enum { + CSI_ICH = 0x40, + CSI_CUU, CSI_CUD, CSI_CUF, CSI_CUB, CSI_CNL, CSI_CPL, CSI_CHA, + CSI_CUP, CSI_CHT, CSI_ED , CSI_EL , CSI_IL , CSI_DL , CSI_EF , CSI_EA , + CSI_DCH, CSI_SEE, CSI_CPR, CSI_SU , CSI_SD , CSI_NP , CSI_PP , CSI_CTC, + CSI_ECH, CSI_CVT, CSI_CBT, CSI_SRS, CSI_PTX, CSI_SDS, CSI_SIMD, CSI_5F, + CSI_HPA, CSI_HPR, CSI_REP, CSI_DA , CSI_VPA, CSI_VPR, CSI_HVP, CSI_TBC, + CSI_SM , CSI_MC , CSI_HPB, CSI_VPB, CSI_RM , CSI_SGR, CSI_DSR, CSI_DAQ, + CSI_70 , CSI_71 , CSI_72 , CSI_73 , CSI_74 , CSI_75 , CSI_76 , CSI_77 , + CSI_78 , CSI_79 , CSI_7A , CSI_7B , CSI_7C , CSI_7D , CSI_7E , CSI_7F +}; + +#define make_byte(b7,b6,b5,b4,b3,b2,b1,b0) \ + (((b7) << 7) | ((b6) << 6) | ((b5) << 5) | ((b4) << 4) \ + | ((b3) << 3) | ((b2) << 2) | ((b1) << 1) | (b0)) +#define get_byte_array_bit(array, bit) \ + (!!((array)[(bit) / 8] & (128 >> ((bit) & 7)))) + +const unsigned char csi_defaults[] = { + make_byte(1,1,1,1,1,1,1,1), /* @, A, B, C, D, E, F, G, */ + make_byte(1,1,0,0,1,1,0,0), /* H, I, J, K, L, M, N, O, */ + make_byte(1,0,1,1,1,1,1,0), /* P, Q, R, S, T, U, V, W, */ + make_byte(1,1,1,0,0,0,1,0), /* X, Y, Z, [, \, ], ^, _, */ + make_byte(1,1,1,0,1,1,1,0), /* `, a, b, c, d, e, f, g, */ + make_byte(0,0,1,1,0,0,0,0), /* h, i, j, k, l, m, n, o, */ + make_byte(0,0,0,0,0,0,0,0), /* p, q, r, s, t, u, v, w, */ + make_byte(0,0,0,0,0,0,0,0) /* x, y, z, {, |, }, ~, */ +}; +/* *INDENT-ON* */ + +/* INTPROTO */ +void +rxvt_process_csi_seq(pR) +{ + unsigned char ch, priv, i; + unsigned int nargs, p; + int n, ndef; + int arg[ESC_ARGS]; + + for (nargs = ESC_ARGS; nargs > 0;) + arg[--nargs] = 0; + + priv = 0; + ch = rxvt_cmd_getc(aR); + if (ch >= '<' && ch <= '?') { /* '<' '=' '>' '?' */ + priv = ch; + ch = rxvt_cmd_getc(aR); + } +/* read any numerical arguments */ + for (n = -1; ch < CSI_ICH; ) { + if (isdigit(ch)) { + if (n < 0) + n = ch - '0'; + else + n = n * 10 + ch - '0'; + } else if (ch == ';') { + if (nargs < ESC_ARGS) + arg[nargs++] = n; + n = -1; + } else if (ch == '\b') { + rxvt_scr_backspace(aR); + } else if (ch == C0_ESC) { + rxvt_process_escape_seq(aR); + return; + } else if (ch < ' ') { + rxvt_process_nonprinting(aR_ ch); + } + ch = rxvt_cmd_getc(aR); + } + + if (ch > CSI_7F) + return; + + if (nargs < ESC_ARGS) + arg[nargs++] = n; + + i = ch - CSI_ICH; + ndef = get_byte_array_bit(csi_defaults, i); + for (p = 0; p < nargs; p++) + if (arg[p] == -1) + arg[p] = ndef; + +#ifdef DEBUG_CMD + fprintf(stderr, "CSI "); + for (p = 0; p < nargs; p++) + fprintf(stderr, "%d%s", arg[p], p < nargs - 1 ? ";" : ""); + fprintf(stderr, "%c\n", ch); +#endif + +/* + * private mode handling + */ + if (priv) { + switch (priv) { + case '>': + if (ch == CSI_DA) /* secondary device attributes */ + rxvt_tt_printf(aR_ "\033[>%d;%-.8s;0c", 'R', VSTRING); + break; + case '?': + if (ch == 'h' || ch == 'l' || ch == 'r' || ch == 's' || ch == 't') + rxvt_process_terminal_mode(aR_ ch, priv, nargs, arg); + break; + } + return; + } + + switch (ch) { +/* + * ISO/IEC 6429:1992(E) CSI sequences (defaults in parentheses) + */ +#ifdef PRINTPIPE + case CSI_MC: /* 8.3.83: (0) MEDIA COPY */ + switch (arg[0]) { + case 0: /* initiate transfer to primary aux device */ + rxvt_scr_printscreen(aR_ 0); + break; + case 5: /* start relay to primary aux device */ + rxvt_process_print_pipe(aR); + break; + } + break; +#endif + + case CSI_CUU: /* 8.3.22: (1) CURSOR UP */ + case CSI_VPR: /* 8.3.161: (1) LINE POSITION FORWARD */ + arg[0] = -arg[0]; + /* FALLTHROUGH */ + case CSI_CUD: /* 8.3.19: (1) CURSOR DOWN */ + case CSI_VPB: /* 8.3.160: (1) LINE POSITION BACKWARD */ + rxvt_scr_gotorc(aR_ arg[0], 0, RELATIVE); + break; + + case CSI_CUB: /* 8.3.18: (1) CURSOR LEFT */ + case CSI_HPB: /* 8.3.59: (1) CHARACTER POSITION BACKWARD */ +#ifdef ISO6429 + arg[0] = -arg[0]; +#else /* emulate common DEC VTs */ + arg[0] = arg[0] ? -arg[0] : -1; +#endif + /* FALLTHROUGH */ + case CSI_CUF: /* 8.3.20: (1) CURSOR RIGHT */ + case CSI_HPR: /* 8.3.60: (1) CHARACTER POSITION FORWARD */ +#ifdef ISO6429 + rxvt_scr_gotorc(aR_ 0, arg[0], RELATIVE); +#else /* emulate common DEC VTs */ + rxvt_scr_gotorc(aR_ 0, arg[0] ? arg[0] : 1, RELATIVE); +#endif + break; + + case CSI_CPL: /* 8.3.13: (1) CURSOR PRECEDING LINE */ + arg[0] = -arg[0]; + /* FALLTHROUGH */ + case CSI_CNL: /* 8.3.12: (1) CURSOR NEXT LINE */ + rxvt_scr_gotorc(aR_ arg[0], 0, R_RELATIVE); + break; + + case CSI_CHA: /* 8.3.9: (1) CURSOR CHARACTER ABSOLUTE */ + case CSI_HPA: /* 8.3.58: (1) CURSOR POSITION ABSOLUTE */ + rxvt_scr_gotorc(aR_ 0, arg[0] - 1, R_RELATIVE); + break; + + case CSI_VPA: /* 8.3.159: (1) LINE POSITION ABSOLUTE */ + rxvt_scr_gotorc(aR_ arg[0] - 1, 0, C_RELATIVE); + break; + + case CSI_CUP: /* 8.3.21: (1,1) CURSOR POSITION */ + case CSI_HVP: /* 8.3.64: (1,1) CHARACTER AND LINE POSITION */ + rxvt_scr_gotorc(aR_ arg[0] - 1, nargs < 2 ? 0 : (arg[1] - 1), 0); + break; + + case CSI_CBT: /* 8.3.7: (1) CURSOR BACKWARD TABULATION */ + arg[0] = -arg[0]; + /* FALLTHROUGH */ + case CSI_CHT: /* 8.3.10: (1) CURSOR FORWARD TABULATION */ + rxvt_scr_tab(aR_ arg[0]); + break; + + case CSI_ED: /* 8.3.40: (0) ERASE IN PAGE */ + rxvt_scr_erase_screen(aR_ arg[0]); + break; + + case CSI_EL: /* 8.3.42: (0) ERASE IN LINE */ + rxvt_scr_erase_line(aR_ arg[0]); + break; + + case CSI_ICH: /* 8.3.65: (1) INSERT CHARACTER */ + rxvt_scr_insdel_chars(aR_ arg[0], INSERT); + break; + + case CSI_IL: /* 8.3.68: (1) INSERT LINE */ + rxvt_scr_insdel_lines(aR_ arg[0], INSERT); + break; + + case CSI_DL: /* 8.3.33: (1) DELETE LINE */ + rxvt_scr_insdel_lines(aR_ arg[0], DELETE); + break; + + case CSI_ECH: /* 8.3.39: (1) ERASE CHARACTER */ + rxvt_scr_insdel_chars(aR_ arg[0], ERASE); + break; + + case CSI_DCH: /* 8.3.26: (1) DELETE CHARACTER */ + rxvt_scr_insdel_chars(aR_ arg[0], DELETE); + break; + + case CSI_SD: /* 8.3.114: (1) SCROLL DOWN */ + arg[0] = -arg[0]; + /* FALLTHROUGH */ + case CSI_SU: /* 8.3.148: (1) SCROLL UP */ + rxvt_scroll_text(aR_ R->screen.tscroll, R->screen.bscroll, arg[0], 0); + break; + + case CSI_DA: /* 8.3.24: (0) DEVICE ATTRIBUTES */ + rxvt_tt_write(aR_ (const unsigned char *)VT100_ANS, + (unsigned int)(sizeof(VT100_ANS) - 1)); + break; + + case CSI_SGR: /* 8.3.118: (0) SELECT GRAPHIC RENDITION */ + rxvt_process_sgr_mode(aR_ nargs, arg); + break; + + case CSI_DSR: /* 8.3.36: (0) DEVICE STATUS REPORT */ + switch (arg[0]) { + case 5: /* DSR requested */ + rxvt_tt_printf(aR_ "\033[0n"); + break; + case 6: /* CPR requested */ + rxvt_scr_report_position(aR); + break; +#if defined (ENABLE_DISPLAY_ANSWER) + case 7: /* unofficial extension */ + rxvt_tt_printf(aR_ "%-.250s\n", R->h->rs[Rs_display_name]); + break; +#endif + case 8: /* unofficial extension */ + rxvt_xterm_seq(aR_ XTerm_title, APL_NAME "-" VERSION, CHAR_ST); + break; + } + break; + + case CSI_TBC: /* 8.3.155: (0) TABULATION CLEAR */ + switch (arg[0]) { + case 0: /* char tab stop cleared at active position */ + rxvt_scr_set_tab(aR_ 0); + break; + /* case 1: */ /* line tab stop cleared in active line */ + /* case 2: */ /* char tab stops cleared in active line */ + case 3: /* all char tab stops are cleared */ + /* case 4: */ /* all line tab stops are cleared */ + case 5: /* all tab stops are cleared */ + rxvt_scr_set_tab(aR_ -1); + break; + } + break; + + case CSI_CTC: /* 8.3.17: (0) CURSOR TABULATION CONTROL */ + switch (arg[0]) { + case 0: /* char tab stop set at active position */ + rxvt_scr_set_tab(aR_ 1); + break; /* = ESC H */ + /* case 1: */ /* line tab stop set at active line */ + case 2: /* char tab stop cleared at active position */ + rxvt_scr_set_tab(aR_ 0); + break; /* = ESC [ 0 g */ + /* case 3: */ /* line tab stop cleared at active line */ + /* case 4: */ /* char tab stops cleared at active line */ + case 5: /* all char tab stops are cleared */ + rxvt_scr_set_tab(aR_ -1); + break; /* = ESC [ 3 g */ + /* case 6: */ /* all line tab stops are cleared */ + } + break; + + case CSI_RM: /* 8.3.107: RESET MODE */ + if (arg[0] == 4) + rxvt_scr_insert_mode(aR_ 0); + break; + + case CSI_SM: /* 8.3.126: SET MODE */ + if (arg[0] == 4) + rxvt_scr_insert_mode(aR_ 1); + break; + +/* + * PRIVATE USE beyond this point. All CSI_7? sequences here + */ + case CSI_72: /* DECSTBM: set top and bottom margins */ + if (nargs == 1) + rxvt_scr_scroll_region(aR_ arg[0] - 1, MAX_ROWS - 1); + else if (nargs == 0 || arg[0] >= arg[1]) + rxvt_scr_scroll_region(aR_ 0, MAX_ROWS - 1); + else + rxvt_scr_scroll_region(aR_ arg[0] - 1, arg[1] - 1); + break; + + case CSI_73: + rxvt_scr_cursor(aR_ SAVE); + break; + case CSI_75: + rxvt_scr_cursor(aR_ RESTORE); + break; + +#ifndef NO_FRILLS + case CSI_74: + rxvt_process_window_ops(aR_ arg, nargs); + break; +#endif + + case CSI_78: /* DECREQTPARM */ + if (arg[0] == 0 || arg[0] == 1) + rxvt_tt_printf(aR_ "\033[%d;1;1;112;112;1;0x", arg[0] + 2); + /* FALLTHROUGH */ + + default: + break; + } +} +/*}}} */ + +#ifndef NO_FRILLS +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_process_window_ops(pR_ const int *args, unsigned int nargs) +{ + int x, y; +#if 0 + char *s; +#endif + XWindowAttributes wattr; + Window wdummy; + + if (nargs == 0) + return; + switch (args[0]) { + /* + * commands + */ + case 1: /* deiconify window */ + XMapWindow(R->Xdisplay, R->TermWin.parent[0]); + break; + case 2: /* iconify window */ + XIconifyWindow(R->Xdisplay, R->TermWin.parent[0], + DefaultScreen(R->Xdisplay)); + break; + case 3: /* set position (pixels) */ + XMoveWindow(R->Xdisplay, R->TermWin.parent[0], args[1], args[2]); + break; + case 4: /* set size (pixels) */ + rxvt_set_widthheight(aR_ (unsigned int)args[2], (unsigned int)args[1]); + break; + case 5: /* raise window */ + XRaiseWindow(R->Xdisplay, R->TermWin.parent[0]); + break; + case 6: /* lower window */ + XLowerWindow(R->Xdisplay, R->TermWin.parent[0]); + break; + case 7: /* refresh window */ + rxvt_scr_touch(aR_ True); + break; + case 8: /* set size (chars) */ + rxvt_set_widthheight(aR_ (unsigned int)(args[2] * R->TermWin.fwidth), + (unsigned int)(args[1] * R->TermWin.fheight)); + break; + default: + if (args[0] >= 24) /* set height (chars) */ + rxvt_set_widthheight(aR_ (unsigned int)R->TermWin.width, + (unsigned int)(args[1] * R->TermWin.fheight)); + break; + /* + * reports - some output format copied from XTerm + */ + case 11: /* report window state */ + XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr); + rxvt_tt_printf(aR_ "\033[%dt", wattr.map_state == IsViewable ? 1 : 2); + break; + case 13: /* report window position */ + XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr); + XTranslateCoordinates(R->Xdisplay, R->TermWin.parent[0], wattr.root, + -wattr.border_width, -wattr.border_width, + &x, &y, &wdummy); + rxvt_tt_printf(aR_ "\033[3;%d;%dt", x, y); + break; + case 14: /* report window size (pixels) */ + XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr); + rxvt_tt_printf(aR_ "\033[4;%d;%dt", wattr.height, wattr.width); + break; + case 18: /* report window size (chars) */ + rxvt_tt_printf(aR_ "\033[8;%d;%dt", R->TermWin.nrow, R->TermWin.ncol); + break; +#if 0 /* XXX: currently disabled due to security concerns */ + case 20: /* report icon label */ + XGetIconName(R->Xdisplay, R->TermWin.parent[0], &s); + rxvt_tt_printf(aR_ "\033]L%-.200s\234", s ? s : ""); /* 8bit ST */ + break; + case 21: /* report window title */ + XFetchName(R->Xdisplay, R->TermWin.parent[0], &s); + rxvt_tt_printf(aR_ "\033]l%-.200s\234", s ? s : ""); /* 8bit ST */ + break; +#endif + } +} +#endif + +/*----------------------------------------------------------------------*/ +/* + * get input up until STRING TERMINATOR (or BEL) + * ends_how is terminator used. returned input must be free()d + */ +/* INTPROTO */ +unsigned char * +rxvt_get_to_st(pR_ unsigned char *ends_how) +{ + int seen_esc = 0; /* seen escape? */ + unsigned int n = 0; + unsigned char *s; + unsigned char ch, string[STRING_MAX]; + + for (; (ch = rxvt_cmd_getc(aR));) { + if (ch == C0_BEL + || ch == CHAR_ST + || (ch == 0x5c && seen_esc)) /* 7bit ST */ + break; + if (ch == C0_ESC) { + seen_esc = 1; + continue; + } else if (ch == '\t') + ch = ' '; /* translate '\t' to space */ + else if (ch < 0x08 || (ch > 0x0d && ch < 0x20)) + return NULL; /* other control character - exit */ + if (n < sizeof(string) - 1) + string[n++] = ch; + seen_esc = 0; + } + string[n++] = '\0'; + if ((s = (unsigned char *)rxvt_malloc(n)) == NULL) + return NULL; + *ends_how = (ch == 0x5c ? C0_ESC : ch); + STRNCPY(s, string, n); + return s; +} + +/*----------------------------------------------------------------------*/ +/* + * process DEVICE CONTROL STRING `ESC P ... (ST|BEL)' or `0x90 ... (ST|BEL)' + */ +/* INTPROTO */ +void +rxvt_process_dcs_seq(pR) +{ + unsigned char eh, *s; +/* + * Not handled yet + */ + s = rxvt_get_to_st(aR_ &eh); + if (s) + free(s); + return; +} + +/*----------------------------------------------------------------------*/ +/* + * process OPERATING SYSTEM COMMAND sequence `ESC ] Ps ; Pt (ST|BEL)' + */ +/* INTPROTO */ +void +rxvt_process_osc_seq(pR) +{ + unsigned char ch, eh, *s; + int arg; + + ch = rxvt_cmd_getc(aR); + for (arg = 0; isdigit(ch); ch = rxvt_cmd_getc(aR)) + arg = arg * 10 + (ch - '0'); + + if (ch == ';') { + s = rxvt_get_to_st(aR_ &eh); + if (s) { + /* + * rxvt_menubar_dispatch() violates the constness of the string, + * so do it here + */ + if (arg == XTerm_Menu) +#if 0 /* XXX: currently disabled due to security concerns */ + rxvt_menubar_dispatch(aR_ (char *)s); +#else + 0; +#endif + else + rxvt_xterm_seq(aR_ arg, (char *)s, eh); + free(s); + } + } +} +/* + * XTerm escape sequences: ESC ] Ps;Pt (ST|BEL) + * 0 = change iconName/title + * 1 = change iconName + * 2 = change title + * 4 = change color + * 12 = change text color + * 13 = change mouse foreground color + * 17 = change highlight character colour + * 18 = change bold character color + * 19 = change underlined character color + * 46 = change logfile (not implemented) + * 50 = change font + * + * rxvt extensions: + * 10 = menu (may change in future) + * 20 = bg pixmap + * 39 = change default fg color + * 49 = change default bg color + * 55 = dump scrollback buffer and all of screen + */ +/* EXTPROTO */ +void +rxvt_xterm_seq(pR_ int op, const char *str, unsigned char resp __attribute__((unused))) +{ + int changed = 0; + int color; + char *buf, *name; + + assert(str != NULL); + switch (op) { + case XTerm_name: + rxvt_set_title(aR_ str); + /* FALLTHROUGH */ + case XTerm_iconName: + rxvt_set_iconName(aR_ str); + break; + case XTerm_title: + rxvt_set_title(aR_ str); + break; + case XTerm_Color: + for (buf = (char *)str; buf && *buf;) { + if ((name = STRCHR(buf, ';')) == NULL) + break; + *name++ = '\0'; + color = atoi(buf); + if (color < 0 || color >= TOTAL_COLORS) + break; + if ((buf = STRCHR(name, ';')) != NULL) + *buf++ = '\0'; + rxvt_set_window_color(aR_ color + minCOLOR, name); + } + break; +#ifndef NO_CURSORCOLOR + case XTerm_Color_cursor: + rxvt_set_window_color(aR_ Color_cursor, str); + break; +#endif + case XTerm_Color_pointer: + rxvt_set_window_color(aR_ Color_pointer, str); + break; +#ifndef NO_BOLD_UNDERLINE_REVERSE + case XTerm_Color_BD: + rxvt_set_window_color(aR_ Color_BD, str); + break; + case XTerm_Color_UL: + rxvt_set_window_color(aR_ Color_UL, str); + break; + case XTerm_Color_RV: + rxvt_set_window_color(aR_ Color_RV, str); + break; +#endif + + case XTerm_Menu: + /* + * rxvt_menubar_dispatch() violates the constness of the string, + * so DON'T do it here + */ + break; + case XTerm_Pixmap: + if (*str != ';') { +#if XPM_BACKGROUND + rxvt_scale_pixmap(aR_ ""); /* reset to default scaling */ + rxvt_set_bgPixmap(aR_ str); /* change pixmap */ +#endif + rxvt_scr_touch(aR_ True); + } + while ((str = STRCHR(str, ';')) != NULL) { + str++; +#if XPM_BACKGROUND + changed += rxvt_scale_pixmap(aR_ str); +#endif + } + if (changed) { +#ifdef XPM_BACKGROUND + rxvt_resize_pixmap(aR); +#endif + rxvt_scr_touch(aR_ True); + } + break; + + case XTerm_restoreFG: + rxvt_set_window_color(aR_ Color_fg, str); + break; + case XTerm_restoreBG: + rxvt_set_window_color(aR_ Color_bg, str); + break; + case XTerm_logfile: + break; + case XTerm_font: + rxvt_change_font(aR_ 0, str); + break; +#if 0 + case XTerm_dumpscreen: /* no error notices */ + { + int fd; + if ((fd = open(str, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0) { + rxvt_scr_dump(aR_ fd); + close(fd); + } + } + break; +#endif + } +} +/*----------------------------------------------------------------------*/ + +/*{{{ process DEC private mode sequences `ESC [ ? Ps mode' */ +/* + * mode can only have the following values: + * 'l' = low + * 'h' = high + * 's' = save + * 'r' = restore + * 't' = toggle + * so no need for fancy checking + */ +/* INTPROTO */ +int +rxvt_privcases(pR_ int mode, unsigned long bit) +{ + int state; + + if (mode == 's') { + R->h->SavedModes |= (R->h->PrivateModes & bit); + return -1; + } else { + if (mode == 'r') + state = (R->h->SavedModes & bit) ? 1 : 0; /* no overlapping */ + else + state = (mode == 't') ? !(R->h->PrivateModes & bit) : mode; + PrivMode(state, bit); + } + return state; +} + +/* we're not using priv _yet_ */ +/* INTPROTO */ +void +rxvt_process_terminal_mode(pR_ int mode, int priv __attribute__((unused)), unsigned int nargs, const int *arg) +{ + unsigned int i, j; + int state; + static const struct { + const int argval; + const unsigned long bit; + } argtopriv[] = { + { 1, PrivMode_aplCUR }, + { 2, PrivMode_vt52 }, + { 3, PrivMode_132 }, + { 4, PrivMode_smoothScroll }, + { 5, PrivMode_rVideo }, + { 6, PrivMode_relOrigin }, + { 7, PrivMode_Autowrap }, + { 9, PrivMode_MouseX10 }, +#ifdef menuBar_esc + { menuBar_esc, PrivMode_menuBar }, +#endif +#ifdef scrollBar_esc + { scrollBar_esc, PrivMode_scrollBar }, +#endif + { 25, PrivMode_VisibleCursor }, + { 35, PrivMode_ShiftKeys }, + { 40, PrivMode_132OK }, + { 47, PrivMode_Screen }, + { 66, PrivMode_aplKP }, +#ifndef NO_BACKSPACE_KEY + { 67, PrivMode_BackSpace }, +#endif + { 1000, PrivMode_MouseX11 }, + { 1010, PrivMode_TtyOutputInh }, + { 1011, PrivMode_Keypress }, + { 1047, PrivMode_Screen }, + }; + + if (nargs == 0) + return; + +/* make lo/hi boolean */ + if (mode == 'l') + mode = 0; /* reset */ + else if (mode == 'h') + mode = 1; /* set */ + + for (i = 0; i < nargs; i++) { + state = -1; + + /* basic handling */ + for (j = 0; j < (sizeof(argtopriv)/sizeof(argtopriv[0])); j++) + if (argtopriv[j].argval == arg[i]) { + state = rxvt_privcases(aR_ mode, argtopriv[j].bit); + break; + } + + /* extra handling for values with state unkept */ + if (state == -1) + switch (arg[i]) { + case 1048: /* alternative cursor save */ + if (mode == 0) + rxvt_scr_cursor(aR_ RESTORE); + else if (mode == 1) + rxvt_scr_cursor(aR_ SAVE); + /* FALLTHROUGH */ + default: + continue; /* for(;i;) */ + } + + /* extra handling for values with valid 0 or 1 state */ + switch (arg[i]) { + /* case 1: - application cursor keys */ + case 2: /* VT52 mode */ + /* oddball mode. should be set regardless of set/reset + * parameter. Return from VT52 mode with an ESC < from + * within VT52 mode + */ + PrivMode(1, PrivMode_vt52); + break; + case 3: /* 80/132 */ + if (R->h->PrivateModes & PrivMode_132OK) + rxvt_set_widthheight(aR_ + (unsigned int)((state ? 132 : 80) * R->TermWin.fwidth), + (unsigned int)R->TermWin.height); + break; + case 4: /* smooth scrolling */ + if (state) + R->Options &= ~Opt_jumpScroll; + else + R->Options |= Opt_jumpScroll; + break; + case 5: /* reverse video */ + rxvt_scr_rvideo_mode(aR_ state); + break; + case 6: /* relative/absolute origins */ + rxvt_scr_relative_origin(aR_ state); + break; + case 7: /* autowrap */ + rxvt_scr_autowrap(aR_ state); + break; + /* case 8: - auto repeat, can't do on a per window basis */ + case 9: /* X10 mouse reporting */ + if (state) /* orthogonal */ + R->h->PrivateModes &= ~(PrivMode_MouseX11); + break; +#ifdef menuBar_esc + case menuBar_esc: +#ifdef MENUBAR + rxvt_map_menuBar(aR_ state); +#endif + break; +#endif +#ifdef scrollBar_esc + case scrollBar_esc: + if (rxvt_scrollbar_mapping(aR_ state)) { + rxvt_resize_all_windows(aR_ 0, 0, 0); + rxvt_scr_touch(aR_ True); + } + break; +#endif + case 25: /* visible/invisible cursor */ + rxvt_scr_cursor_visible(aR_ state); + break; + /* case 35: - shift keys */ + /* case 40: - 80 <--> 132 mode */ + case 47: /* secondary screen */ + rxvt_scr_change_screen(aR_ state); + break; + /* case 66: - application key pad */ + /* case 67: - backspace key */ + case 1000: /* X11 mouse reporting */ + if (state) /* orthogonal */ + R->h->PrivateModes &= ~(PrivMode_MouseX10); + break; +#if 0 + case 1001: + break; /* X11 mouse highlighting */ +#endif + case 1010: /* scroll to bottom on TTY output inhibit */ + if (state) + R->Options &= ~Opt_scrollTtyOutput; + else + R->Options |= Opt_scrollTtyOutput; + break; + case 1011: /* scroll to bottom on key press */ + if (state) + R->Options |= Opt_scrollTtyKeypress; + else + R->Options &= ~Opt_scrollTtyKeypress; + break; + case 1047: /* secondary screen w/ clearing */ + if (R->h->current_screen != PRIMARY) + rxvt_scr_erase_screen(aR_ 2); + rxvt_scr_change_screen(aR_ state); + /* FALLTHROUGH */ + default: + break; + } + } +} +/*}}} */ + +/*{{{ process sgr sequences */ +/* INTPROTO */ +void +rxvt_process_sgr_mode(pR_ unsigned int nargs, const int *arg) +{ + unsigned int i; + short rendset; + int rendstyle; + + if (nargs == 0) { + rxvt_scr_rendition(aR_ 0, ~RS_None); + return; + } + for (i = 0; i < nargs; i++) { + rendset = -1; + switch (arg[i]) { + case 0: + rendset = 0, rendstyle = ~RS_None; + break; + case 1: + rendset = 1, rendstyle = RS_Bold; + break; + case 4: + rendset = 1, rendstyle = RS_Uline; + break; + case 5: + rendset = 1, rendstyle = RS_Blink; + break; + case 7: + rendset = 1, rendstyle = RS_RVid; + break; + case 22: + rendset = 0, rendstyle = RS_Bold; + break; + case 24: + rendset = 0, rendstyle = RS_Uline; + break; + case 25: + rendset = 0, rendstyle = RS_Blink; + break; + case 27: + rendset = 0, rendstyle = RS_RVid; + break; + } + if (rendset != -1) { + rxvt_scr_rendition(aR_ rendset, rendstyle); + continue; /* for(;i;) */ + } + + switch (arg[i]) { + case 30: + case 31: /* set fg color */ + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + rxvt_scr_color(aR_ (unsigned int)(minCOLOR + (arg[i] - 30)), + Color_fg); + break; +#ifdef TTY_256COLOR + case 38: + if (nargs > i + 2 && arg[i + 1] == 5) { + rxvt_scr_color(aR_ (unsigned int)(minCOLOR + arg[i + 2]), + Color_fg); + i += 2; + } + break; +#endif + case 39: /* default fg */ + rxvt_scr_color(aR_ Color_fg, Color_fg); + break; + + case 40: + case 41: /* set bg color */ + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + rxvt_scr_color(aR_ (unsigned int)(minCOLOR + (arg[i] - 40)), + Color_bg); + break; +#ifdef TTY_256COLOR + case 48: + if (nargs > i + 2 && arg[i + 1] == 5) { + rxvt_scr_color(aR_ (unsigned int)(minCOLOR + arg[i + 2]), + Color_bg); + i += 2; + } + break; +#endif + case 49: /* default bg */ + rxvt_scr_color(aR_ Color_bg, Color_bg); + break; + +#ifndef NO_BRIGHTCOLOR + case 90: + case 91: /* set bright fg color */ + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + rxvt_scr_color(aR_ (unsigned int)(minBrightCOLOR + (arg[i] - 90)), + Color_fg); + break; + case 100: + case 101: /* set bright bg color */ + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + rxvt_scr_color(aR_ (unsigned int)(minBrightCOLOR + (arg[i] - 100)), + Color_bg); + break; +#endif + } + } +} +/*}}} */ + +/*{{{ process Rob Nation's own graphics mode sequences */ +/* INTPROTO */ +void +rxvt_process_graphics(pR) +{ + unsigned char ch, cmd = rxvt_cmd_getc(aR); + +#ifndef RXVT_GRAPHICS + if (cmd == 'Q') { /* query graphics */ + rxvt_tt_printf(aR_ "\033G0\n"); /* no graphics */ + return; + } +/* swallow other graphics sequences until terminating ':' */ + do + ch = rxvt_cmd_getc(aR); + while (ch != ':'); +#else + unsigned int nargs; + int args[NGRX_PTS]; + unsigned char *text = NULL; + + if (cmd == 'Q') { /* query graphics */ + rxvt_tt_printf(aR_ "\033G1\n"); /* yes, graphics (color) */ + return; + } + for (nargs = 0; nargs < (sizeof(args) / sizeof(args[0])) - 1;) { + int neg; + + ch = rxvt_cmd_getc(aR); + neg = (ch == '-'); + if (neg || ch == '+') + ch = rxvt_cmd_getc(aR); + + for (args[nargs] = 0; isdigit(ch); ch = rxvt_cmd_getc(aR)) + args[nargs] = args[nargs] * 10 + (ch - '0'); + if (neg) + args[nargs] = -args[nargs]; + + nargs++; + args[nargs] = 0; + if (ch != ';') + break; + } + + if ((cmd == 'T') && (nargs >= 5)) { + int i, len = args[4]; + + text = rxvt_malloc((len + 1) * sizeof(char)); + + if (text != NULL) { + for (i = 0; i < len; i++) + text[i] = rxvt_cmd_getc(aR); + text[len] = '\0'; + } + } + rxvt_Gr_do_graphics(aR_ cmd, nargs, args, text); +#endif +} +/*}}} */ + +/* ------------------------------------------------------------------------- */ + +/*{{{ Read and process output from the application */ +/* LIBPROTO */ +void +rxvt_main_loop(pR) +{ + uint32_t ch, *str, buf[BUFSIZ]; + int nlines, refreshnow; + struct rxvt_hidden *h = R->h; + + h->cmdbuf_ptr = h->cmdbuf_endp = h->cmdbuf_base; + + /* once we know the shell is running, send the screen size. Again! */ + ch = rxvt_cmd_getc(aR); /* wait for something */ + rxvt_tt_winsize(R->cmd_fd, R->TermWin.ncol, R->TermWin.nrow, R->h->cmd_pid); + + refreshnow = 0; + for (;;) { + if (ch == NOCHAR) + ch = rxvt_cmd_getc(aR); + + if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r') + { + /* Read a text string from the input buffer */ + nlines = 0; + str = buf; + *str++ = ch; + for (;;) + { + ch = next_char (aR); + + if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r')) + break; + else + { + *str++ = ch; + + if (ch == '\n') + { + nlines++; + h->refresh_count++; + if (!(R->Options & Opt_jumpScroll) + || (h->refresh_count >= (h->refresh_limit + * (R->TermWin.nrow - 1)))) + { + refreshnow = 1; + ch = NOCHAR; + break; + } + } + + if (str >= buf + BUFSIZ) + { + ch = NOCHAR; + break; + } + } + } + + rxvt_scr_add_lines(aR_ buf, nlines, str - buf); + + /* + * If there have been a lot of new lines, then update the screen + * What the heck I'll cheat and only refresh less than every page-full. + * the number of pages between refreshes is h->refresh_limit, which + * is incremented here because we must be doing flat-out scrolling. + * + * refreshing should be correct for small scrolls, because of the + * time-out + */ + + //TODO: REFRESH_PERIOD is one, fix it + if (refreshnow) + { + refreshnow = 0; + + if ((R->Options & Opt_jumpScroll) && h->refresh_limit < REFRESH_PERIOD) + h->refresh_limit++; + + rxvt_scr_refresh(aR_ h->refresh_type); + } + + } + else + { + switch (ch) + { + default: + rxvt_process_nonprinting(aR_ ch); + break; + case C0_ESC: /* escape char */ + rxvt_process_escape_seq(aR); + break; + /* case 0x9b: */ /* CSI */ + /* rxvt_process_csi_seq(aR); */ + } + + ch = NOCHAR; + } + } +/* NOTREACHED */ +} + +/* + * Send printf() formatted output to the command. + * Only use for small amounts of data. + */ +/* EXTPROTO */ +void +rxvt_tt_printf(pR_ const char *fmt,...) +{ + va_list arg_ptr; + unsigned char buf[256]; + + va_start(arg_ptr, fmt); + vsprintf((char *)buf, fmt, arg_ptr); + va_end(arg_ptr); + rxvt_tt_write(aR_ buf, (unsigned int)STRLEN(buf)); +} + +/* ---------------------------------------------------------------------- */ +/* Addresses pasting large amounts of data and rxvt hang + * code pinched from xterm (v_write()) and applied originally to + * rxvt-2.18 - Hops + * Write data to the pty as typed by the user, pasted with the mouse, + * or generated by us in response to a query ESC sequence. + */ +/* EXTPROTO */ +void +rxvt_tt_write(pR_ const unsigned char *d, unsigned int len) +{ +#define MAX_PTY_WRITE 256 /* POSIX minimum MAX_INPUT */ + int riten; + unsigned int p; + unsigned char *v_buffer, /* start of physical buffer */ + *v_bufstr, /* start of current buffer pending */ + *v_bufptr, /* end of current buffer pending */ + *v_bufend; /* end of physical buffer */ + + if (R->h->v_bufstr == NULL && len > 0) { + p = (len / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE; + v_buffer = v_bufstr = v_bufptr = (unsigned char *)rxvt_malloc(p); + v_bufend = v_buffer + p; + } else { + v_buffer = R->h->v_buffer; + v_bufstr = R->h->v_bufstr; + v_bufptr = R->h->v_bufptr; + v_bufend = R->h->v_bufend; + } + + /* + * Append to the block we already have. Always doing this simplifies the + * code, and isn't too bad, either. If this is a short block, it isn't + * too expensive, and if this is a long block, we won't be able to write + * it all anyway. + */ + if (len > 0) { + if (v_bufend < v_bufptr + len) { /* run out of room */ + if (v_bufstr != v_buffer) { + /* there is unused space, move everything down */ + MEMMOVE(v_buffer, v_bufstr, + (unsigned int)(v_bufptr - v_bufstr)); + v_bufptr -= v_bufstr - v_buffer; + v_bufstr = v_buffer; + } + if (v_bufend < v_bufptr + len) { + /* still won't fit: get more space */ + /* use most basic realloc because an error is not fatal. */ + unsigned int size = v_bufptr - v_buffer; + unsigned int reallocto; + + reallocto = ((size + len) / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE; + v_buffer = (unsigned char *)realloc(v_buffer, reallocto); + /* save across realloc */ + if (v_buffer) { + v_bufstr = v_buffer; + v_bufptr = v_buffer + size; + v_bufend = v_buffer + reallocto; + } else { /* no memory: ignore entire write request */ + rxvt_print_error("data loss: cannot allocate buffer space"); + v_buffer = v_bufstr; /* restore clobbered pointer */ + } + } + } + if (v_bufend >= v_bufptr + len) { /* new stuff will fit */ + MEMCPY(v_bufptr, d, len); + v_bufptr += len; + } + } + + /* + * Write out as much of the buffer as we can. + * Be careful not to overflow the pty's input silo. + * We are conservative here and only write a small amount at a time. + * + * If we can't push all the data into the pty yet, we expect write + * to return a non-negative number less than the length requested + * (if some data written) or -1 and set errno to EAGAIN, + * EWOULDBLOCK, or EINTR (if no data written). + * + * (Not all systems do this, sigh, so the code is actually + * a little more forgiving.) + */ + if ((p = v_bufptr - v_bufstr) > 0) { + riten = write(R->cmd_fd, v_bufstr, min(p, MAX_PTY_WRITE)); + if (riten < 0) + riten = 0; + v_bufstr += riten; + if (v_bufstr >= v_bufptr) /* we wrote it all */ + v_bufstr = v_bufptr = v_buffer; + } + /* + * If we have lots of unused memory allocated, return it + */ + if (v_bufend - v_bufptr > MAX_PTY_WRITE * 8) { /* arbitrary hysteresis */ + /* save pointers across realloc */ + unsigned int start = v_bufstr - v_buffer; + unsigned int size = v_bufptr - v_buffer; + unsigned int reallocto; + + reallocto = (size / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE; + v_buffer = (unsigned char *)realloc(v_buffer, reallocto); + if (v_buffer) { + v_bufstr = v_buffer + start; + v_bufptr = v_buffer + size; + v_bufend = v_buffer + reallocto; + } else { + /* should we print a warning if couldn't return memory? */ + v_buffer = v_bufstr - start; /* restore clobbered pointer */ + } + } + R->h->v_buffer = v_buffer; + R->h->v_bufstr = v_bufstr; + R->h->v_bufptr = v_bufptr; + R->h->v_bufend = v_bufend; +} +/*----------------------- end-of-file (C source) -----------------------*/ + diff --git a/src/command.h b/src/command.h new file mode 100644 index 00000000..121f9374 --- /dev/null +++ b/src/command.h @@ -0,0 +1,87 @@ +/* + * $Id: command.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#ifndef _COMMAND_H_ +#define _COMMAND_H_ + +#define STRING_MAX 512 /* max string size for process_rxvt_xterm_seq() */ +#define ESC_ARGS 32 /* max # of args for esc sequences */ + +#ifdef OFFIX_DND +# define DndFile 2 +# define DndDir 5 +# define DndLink 7 +#endif + +/* a large REFRESH_PERIOD causes problems with `cat' */ +#define REFRESH_PERIOD 10 + +#ifndef MULTICLICK_TIME +# define MULTICLICK_TIME 500 +#endif +#ifndef SCROLLBAR_INITIAL_DELAY +# ifdef NEXT_SCROLLER +# define SCROLLBAR_INITIAL_DELAY 20 +# else +# define SCROLLBAR_INITIAL_DELAY 40 +# endif +#endif +#ifndef SCROLLBAR_CONTINUOUS_DELAY +# define SCROLLBAR_CONTINUOUS_DELAY 2 +#endif + +/* + * key-strings: if only these keys were standardized + */ +#ifdef LINUX_KEYS +# define KS_HOME "\033[1~" /* Home == Find */ +# define KS_END "\033[4~" /* End == Select */ +#else +# define KS_HOME "\033[7~" /* Home */ +# define KS_END "\033[8~" /* End */ +#endif + +#ifdef SCROLL_ON_SHIFT +# define SCROLL_SHIFTKEY (shft) +#else +# define SCROLL_SHIFTKEY 0 +#endif +#ifdef SCROLL_ON_CTRL +# define SCROLL_CTRLKEY (ctrl) +#else +# define SCROLL_CTRLKEY 0 +#endif +#ifdef SCROLL_ON_META +# define SCROLL_METAKEY (meta) +#else +# define SCROLL_METAKEY 0 +#endif +#define IS_SCROLL_MOD (SCROLL_SHIFTKEY || SCROLL_CTRLKEY || SCROLL_METAKEY) + +/* + * ESC-Z processing: + * + * By stealing a sequence to which other xterms respond, and sending the + * same number of characters, but having a distinguishable sequence, + * we can avoid having a timeout (when not under an rxvt) for every login + * shell to auto-set its DISPLAY. + * + * This particular sequence is even explicitly stated as obsolete since + * about 1985, so only very old software is likely to be confused, a + * confusion which can likely be remedied through termcap or TERM. Frankly, + * I doubt anyone will even notice. We provide a #ifdef just in case they + * don't care about auto-display setting. Just in case the ancient + * software in question is broken enough to be case insensitive to the 'c' + * character in the answerback string, we make the distinguishing + * characteristic be capitalization of that character. The length of the + * two strings should be the same so that identical read(2) calls may be + * used. + */ +#define VT100_ANS "\033[?1;2c" /* vt100 answerback */ +#ifndef ESCZ_ANSWER +# define ESCZ_ANSWER VT100_ANS /* obsolete ANSI ESC[c */ +#endif + +#include "command.intpro" /* PROTOS for internal routines */ +#endif /* _COMMAND_H_ */ diff --git a/src/defaultfont.h b/src/defaultfont.h new file mode 100644 index 00000000..c61aa84c --- /dev/null +++ b/src/defaultfont.h @@ -0,0 +1,109 @@ +/* + * $Id: defaultfont.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#ifndef _DEFAULTFONT_H_ +#define _DEFAULTFONT_H_ + +#ifdef HAVE_XSETLOCALE +# define X_LOCALE +# include +#else +# ifdef HAVE_SETLOCALE +# include +# endif +#endif /* HAVE_XLOCALE */ + +#ifdef HAVE_NL_LANGINFO +# include +#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 fonts; + const rxvt_fallback_font *fallback; + + int height; + int base_id; + + bool realize_font (int i); + void add_fonts (const char *desc); + void clear (); +}; + +#endif /* _DEFAULTFONT_H_ */ + diff --git a/src/feature.h b/src/feature.h new file mode 100644 index 00000000..f142b142 --- /dev/null +++ b/src/feature.h @@ -0,0 +1,475 @@ +/* + * File: feature.h + * $Id: feature.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Compile-time configuration. + *----------------------------------------------------------------------- + * Copyright (c) 1997,1998 Oezguer Kesim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + *----------------------------------------------------------------------*/ +#ifndef _FEATURE_H +#define _FEATURE_H + +#ifndef X11USRLIBDIR +# define X11USRLIBDIR "/usr/X11R6/lib" +#endif +#ifndef X11LIBDIR +# define X11LIBDIR X11USRLIBDIR "/X11" +#endif +#ifndef XAPPLOADDIR +# define XAPPLOADDIR X11LIBDIR "/app-defaults" +# define XAPPLOADDIRLOCALE X11LIBDIR "/%-.*s/app-defaults" +#endif + +/*-----------------------SCREEN OPTIONS AND COLOURS---------------------*/ +/* + * Define the name of the environment variable to be used in + * addition to the "PATH" environment and the `path' resource. + * Usually it should point to where you keep your background pixmaps and/or + * your menu files + */ +#define PATH_ENV "RXVTPATH" + +/* + * Avoid enabling the colour cursor (-cr, cursorColor, cursorColor2) + */ +/* #define NO_CURSORCOLOR */ + +/* + * Suppress use of BOLD and BLINK attributes for setting bright foreground + * and background, respectively. Simulate BOLD using colorBD, boldFont or + * overstrike characters. + */ +/* #define NO_BRIGHTCOLOR */ + +/* + * Make colours match xterm colours instead of `traditional' rxvt colours + */ +#define XTERM_COLORS + +/* + * Disable separate colours for bold, underline and reverse video + */ +/* #define NO_BOLD_UNDERLINE_REVERSE */ + +/* + * Disable using simulated bold using overstrike. You can also turn off + * overstrike just for multi char fonts + * Note: NO_BOLDOVERSTRIKE implies NO_BOLDOVERSTRIKE_MULTI + */ +/* #define NO_BOLDOVERSTRIKE */ +/* #define NO_BOLDOVERSTRIKE_MULTI */ + +/* + * Don't bother cleaning up pixel droppings. If you don't use bold + * overstrike then you don't usually need this + */ +#define NO_PIXEL_DROPPING_AVOIDANCE + +/* + * Also use bold font or overstrike even if we use colour for bold + */ +/*#define VERYBOLD*/ + +/* + * Compile without support for real bold fonts + */ +/* #define NO_BOLDFONT */ + +/* + * Add support for '-hc colour' for background highlight of selection + */ +#define OPTION_HC + +/* + * Define maximum possible columns and rows + */ +#define MAX_COLS 4000 +#define MAX_ROWS 1000 + +/* + * Define default colours for certain items. If you have a low colour + * display, then consider using colours which are already pre-allocated: + * Black (#000000) + * Red3 (#CD0000) + these + * Green3 (#00CD00) + colours + * Yellow3 (#CDCD00) + are + * Blue3 (#0000CD) + not + * Magenta3 (#CD00CD) + pre-allocated + * Cyan3 (#00CDCD) + if + * AntiqueWhite (#FAEBD7) + NO_BRIGHTCOLOR + * Grey25 (#404040) + defined + * Red (#FF0000) + * Green (#00FF00) + * Yellow (#FFFF00) + * Blue (#0000FF) + * Magenta (#FF00FF) + * Cyan (#00FFFF) + * White (#FFFFFF) + */ +/* These colours MUST be defined */ +#define COLOR_FOREGROUND "Black" +#define COLOR_BACKGROUND "White" +#define COLOR_SCROLLBAR "#B2B2B2" /* scrollColor match Netscape */ +#define COLOR_SCROLLTROUGH "#969696" +/* + * The cursor colours are special. Be very careful about setting these: + * foreground/background colours may be modified by command line or resources + * prior to this allocation. Also, they are not valid if NO_CURSORCOLOR is + * defined + */ +#define COLOR_CURSOR_FOREGROUND NULL /* if NULL, use background colour */ +#define COLOR_CURSOR_BACKGROUND NULL /* if NULL, use foreground colour */ + +/* + * Define to remove support for XCopyArea() support. XCopyArea() is useful + * for scrolling on non-local X displays + */ +/* #define NO_SLOW_LINK_SUPPORT */ + +/* + * Printer pipe which will be used for emulation of attached vt100 printer + */ +#define PRINTPIPE "lpr" + +/* + * Allow 80/132 mode switching on startup + */ +/* #define ALLOW_132_MODE */ + +/*------------------------------RESOURCES-------------------------------*/ +/* + * Define to find installed application defaults for rxvt + * Only if USE_XGETDEFAULT is not defined. + */ +/* #define USE_XAPPLOADDIR */ + +/* + * Add support for the Offix DND (Drag 'n' Drop) protocol + */ +/* #define OFFIX_DND */ + +/*---------------------------------KEYS---------------------------------*/ + +/* + * Define defaults for backspace and delete keys - unless they have been + * configured out with --disable-backspace-key / --disable-delete-key + */ +/* #define DEFAULT_BACKSPACE "DEC" */ /* SPECIAL */ +#define DEFAULT_BACKSPACE "\010" +#define DEFAULT_DELETE "\033[3~" + +/* + * Choose one of these values to be the `hotkey' for changing font. + * This has been superceded and is only for you older users + */ +/* #define HOTKEY_CTRL */ +/* #define HOTKEY_META */ + +/* + * To use + * Home = "\E[1~", End = "\E[4~" + * instead of + * Home = "\E[7~", End = "\E[8~" [default] + */ +/* #define LINUX_KEYS */ + +/* + * Enable the keysym resource which allows you to define strings associated + * with various KeySyms (0xFF00 - 0xFFFF). + * Only works with the default hand-rolled resources. + */ +#ifndef NO_RESOURCES +# define KEYSYM_RESOURCE +#endif + +/* + * Modifier/s to use to allow up/down arrows and Priot/Next keys + * to scroll single or page-fulls + */ +#define SCROLL_ON_SHIFT +/* #define SCROLL_ON_CTRL */ +/* #define SCROLL_ON_META */ + +/* + * Allow scrolling with modifier+Up/Down keys, in addition + * to modifier+Prior/Next? (modifier is controlled with + * SCROLL_ON_* defines above.). + * Also for modifier+Home/End keys to move to top/bottom + */ +/* #define SCROLL_ON_UPDOWN_KEYS */ +/* #define SCROLL_ON_HOMEEND_KEYS */ + +/* + * Allow unshifted Next/Prior keys to scroll forward/back + * (in addition to shift+Next/shift+Prior) --pjh + */ +/* #define UNSHIFTED_SCROLLKEYS */ + +/* (Hops) Set to choose a number of lines of context between pages + * (rather than a proportion (1/5) of savedlines buffer) + * when paging the savedlines with SHIFT-{Prior,Next} keys. + */ +#define PAGING_CONTEXT_LINES 1 /* */ + +/* + * Have either Ctrl+Tab or Mod4+Tab emit \e\t + * Useful when window manager grabs Alt+Tab -- mg + */ +/* #define CTRL_TAB_MAKES_META */ +/* #define MOD4_TAB_MAKES_META */ + +/* + * default mode switch when greek keyboard is enabled (i.e. GREEK_SUPPORT) + */ +#ifndef GREEK_KEYBOARD_MODESWITCH +# define GREEK_KEYBOARD_MODESWITCH XK_Mode_switch +#endif + +/*--------------------------------MOUSE---------------------------------*/ +/* + * Disable sending escape sequences (up, down, page up/down) + * from the scrollbar when XTerm mouse reporting is enabled + */ +/* #define NO_SCROLLBAR_REPORT */ + +/* + * Default separating chars for multiple-click selection + * Space and tab are separate separating characters and are not settable + */ +#define CUTCHARS "\"&'()*,;<=>?@[\\]^`{|}~" + +/* + * Add run-time support for changing the cutchars for double click selection + */ +#define CUTCHAR_RESOURCE + +/* + * Have mouse reporting include double-click info for button1 + */ +/* #define MOUSE_REPORT_DOUBLECLICK */ + +/* + * Set delay between multiple click events [default: 500 milliseconds] + */ +/* #define MULTICLICK_TIME 500 */ + +/* + * Time factor to slow down a `jumpy' mouse. Motion isn't recognised until + * this long after the last mouse click [default: 50 milliseconds] + */ +#define MOUSE_THRESHOLD 50 + +/* + * If mouse wheel is defined, then scrolling is by 5 lines (or 1 line + * if the shift key is down). Scrolling can be smooth or jump scrolling + */ +/* #define JUMP_MOUSE_WHEEL */ + +/* + * Set delay periods for continuous scrolling with scrollbar buttons + */ +/* #define SCROLLBAR_INITIAL_DELAY 40 */ +/* #define SCROLLBAR_CONTINUOUS_DELAY 2 */ + +/* + * The speed of selection scrolling is proportional to the distance + * the mouse pointer is out of the text window. This is the max + * number of lines to scroll at a time. + */ +#define SELECTION_SCROLL_MAX_LINES 2 + +/* + * The number of lines (measured in character's heights, not pixels) + * the pointer must be out of the window for each increase in the + * number of lines scrolled. + */ +#define SELECTION_SCROLL_LINE_SPEEDUP 4 + +/*--------------------------------MISC----------------------------------*/ +/* + * Disable to reset tty device to pre-incovation state + */ +#define RESET_TTY_TO_COMMON_DEFAULTS + +/* + * Only log in wtmp file when we're a login shell (-ls option) + */ +#define WTMP_ONLY_ON_LOGIN + +/* + * When pasting ACS characters, convert to similar normal characters + */ +/* #define ACS_ASCII */ + +/* + * Default ascii characters to which ACS symbols are converted + */ +#ifdef ACS_ASCII +# define ACS_CHARS ".# o+ ----+---__++--|<> =#. " +#endif + +/*--------------------------------BELL----------------------------------*/ +/* + * Disable all bell indications + */ +/* #define NO_BELL */ + +/* + * Disable automatic de-iconify when a bell is received + */ +/* #define NO_MAPALERT */ + +/* + * Have mapAlert behaviour selectable with mapAlert resource + */ +#define MAPALERT_OPTION + +/*-----------------------------SCROLL BAR-------------------------------*/ +/* + * Choose the rxvt style scrollbar width + * - should be an even number [default: 10] + */ +/* #define SB_WIDTH_RXVT 10 */ + +/* + * Minimum and maximum widths of the scrollbar (all styles) + */ +#define SB_WIDTH_MINIMUM 5 +#define SB_WIDTH_MAXIMUM 100 + +/* + * When using Rxvt scrollbar, clicking above or below the slider will move + * 1/4 of the screen height, if possible. Setting RXVT_SCROLL_FULL will move + * it one screen height less one line, if possible + */ +#define RXVT_SCROLL_FULL 1 + +/* + * (Hops) draw an internal border line on inside edge of the scrollbar + */ +/* #define SB_BORDER */ + +/*------------------------------MENU BAR--------------------------------*/ +/* + * Choose how many of (experimental) menuBars you want to be able to stack at + * one time. + * A value of 1 disables menuBar stacking. + * A value of 0 disables menuBar all together. + * Note that the amount of memory overhead is the same for any value >= 2. + */ +#define MENUBAR_MAX 8 + +/* + * Change the default shadow style + */ +/* #define MENUBAR_SHADOW_IN */ + +/* + * Change the default shadow style + */ +#define MENU_SHADOW_IN + +/*---------------------------MULTILINGUAL-------------------------------*/ +/* + * Allow run-time selection of Meta (Alt) to set the 8th bit on + */ +#define META8_OPTION + +/*---------------------------DISPLAY OPTIONS----------------------------*/ +/* + * Force local connection to be socket (or other local) communication + */ +/* #define LOCAL_X_IS_UNIX */ + +/* + * Have DISPLAY environment variable & "\E[7n" transmit display with IP number + */ +/* #define DISPLAY_IS_IP */ + +/* + * Have "\E[7n" transmit the display name. + * This has been cited as a potential security hole. + */ +#define ENABLE_DISPLAY_ANSWER + +/* + * Change what ESC Z transmits instead of the default "\E[?1;2c" + */ +/* #define ESCZ_ANSWER "\033[?1;2C" */ + +/* + * Check the current value of the window-time/icon-name and avoid + * re-setting it to the same value -- avoids unnecessary window refreshes + */ +#define SMART_WINDOW_TITLE + +/* + * Allow foreground/background colour to be changed with an + * xterm escape sequence "\E]39;colour^G" -- still experimental + */ +#define XTERM_COLOR_CHANGE + +/* + * Remove secondary screen's independent cursor position, a la xterm + */ +/* #define NO_SECONDARY_SCREEN_CURSOR */ + +/* + * If no secondary screen is available (NO_SECONDARY_SCREEN in config.h), + * then scroll the text up on a window change request + */ +#define SCROLL_ON_NO_SECONDARY + +/* + * Width of the term internal border + */ +#define INTERNALBORDERWIDTH 2 + +/* + * Width of the term external border + */ +#define EXTERNALBORDERWIDTH 0 + +/* + * Default number of extra dots between lines + */ +#define LINESPACE 0 + +/* + * Default number of lines in the scrollback buffer + */ +#define SAVELINES 64 + +/* + * Provide termcap/terminfo bw support + */ +/* #define TERMCAP_HAS_BW */ + +/* + * MAX_NFONTS is the maximum allowed number of fonts in the list + * FONT0_IDX is the default font in the list (starting at 0) + * Sizes between multi-char fonts sets (MFONT_LIST) and single-char font + * sets (NFONT_LIST) have been matched up + */ +#define MAX_NFONTS 7 +#define FONT0_IDX 2 + +#define UNICODE 1 /* TODO */ +#define UTF8 1 /* TODO */ + +#endif diff --git a/src/graphics.C b/src/graphics.C new file mode 100644 index 00000000..697f7954 --- /dev/null +++ b/src/graphics.C @@ -0,0 +1,549 @@ +/*--------------------------------*-C-*---------------------------------* + * File: graphics.c + *----------------------------------------------------------------------* + * $Id: graphics.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1994 Rob Nation + * - original version + * Copyright (c) 1997 Raul Garcia Garcia + * Copyright (c) 1997,1998 mj olesen + * + * 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 + +/* commands: + * 'C' = Clear + * 'F' = Fill + * 'G' = Geometry + * 'L' = Line + * 'P' = Points + * 'T' = Text + * 'W' = Window + */ + +#ifndef GRX_SCALE +# define GRX_SCALE 10000 +#endif + +/*----------------------------------------------------------------------* + * local functions + */ +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_Gr_NewWindow(pR_ int nargs, int args[]) +{ + int x, y; + unsigned int w, h; + Window win; + grwin_t *grwin; + Cursor cursor; + + if (nargs != 4) { + rxvt_print_error("NewWindow: 4 args needed, got %d\n", nargs); + return; + } + x = args[0] * TermWin_TotalWidth() / GRX_SCALE; + y = args[1] * TermWin_TotalHeight() / GRX_SCALE; + w = args[2] * TermWin_TotalWidth() / GRX_SCALE; + h = args[3] * TermWin_TotalHeight() / GRX_SCALE; + + win = XCreateSimpleWindow(R->Xdisplay, R->TermWin.vt, + x, y, w, h, + 0, + R->PixColors[Color_fg], + R->PixColors[Color_bg]); + + cursor = XCreateFontCursor(R->Xdisplay, XC_crosshair); + XDefineCursor(R->Xdisplay, win, cursor); + XMapWindow(R->Xdisplay, win); + XSelectInput(R->Xdisplay, win, ExposureMask); + + grwin = (grwin_t *) rxvt_malloc(sizeof(grwin_t)); + grwin->win = win; + grwin->x = x; + grwin->y = y; + grwin->w = w; + grwin->h = h; + grwin->screen = 0; + grwin->prev = NULL; + grwin->next = R->h->gr_root; + if (grwin->next) + grwin->next->prev = grwin; + R->h->gr_root = grwin; + grwin->graphics = NULL; + R->h->graphics_up++; + + rxvt_tt_printf(aR_ "\033W%ld\n", (long)grwin->win); +} + +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_Gr_ClearWindow(pR_ grwin_t *grwin) +{ + grcmd_t *cmd, *next; + + for (cmd = grwin->graphics; cmd != NULL; cmd = next) { + next = cmd->next; + free(cmd->coords); + if (cmd->text != NULL) + free(cmd->text); + free(cmd); + } + grwin->graphics = NULL; + XClearWindow(R->Xdisplay, grwin->win); +} + +/* + * arg [0] = x + * arg [1] = y + * arg [2] = alignment + * arg [3] = strlen (text) + */ +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_Gr_Text(pR_ grwin_t *grwin, grcmd_t *data) +{ + int x, y, align; + + if (data->ncoords < 4 || data->text == NULL || *(data->text) == '\0') + return; + + x = data->coords[0] * grwin->w / GRX_SCALE; + y = data->coords[1] * grwin->h / GRX_SCALE; + align = data->coords[2]; + + if ((align & HORIZONTAL_ALIGNMENT) == RIGHT_TEXT) + x -= XTextWidth(R->TermWin.font, data->text, data->coords[3]); + else if ((align & HORIZONTAL_ALIGNMENT) == HCENTER_TEXT) + x -= (XTextWidth(R->TermWin.font, data->text, data->coords[3]) >> 1); + + if ((align & VERTICAL_ALIGNMENT) == TOP_TEXT) + y += R->TermWin.font->ascent; + else if ((align & VERTICAL_ALIGNMENT) == BOTTOM_TEXT) + y -= R->TermWin.font->descent; + + if ((align & VERTICAL_ALIGNMENT) == VCENTER_TEXT) + y -= R->TermWin.font->descent + + ((R->TermWin.font->ascent + R->TermWin.font->descent) >> 1); + if ((align & VERTICAL_ALIGNMENT) == VCAPS_CENTER_TEXT) + y += (R->TermWin.font->ascent >> 1); + + XPMClearArea(R->Xdisplay, grwin->win, x, y - R->TermWin.font->ascent, + Width2Pixel(data->coords[3]), Height2Pixel(1), 0); + XDrawString(R->Xdisplay, grwin->win, R->TermWin.gc, x, y, + data->text, data->coords[3]); +} + +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_Gr_Geometry(pR_ grwin_t *grwin, grcmd_t *data __attribute__((unused))) +{ + if (grwin) + rxvt_tt_printf(aR_ "\033G%ld %d %d %u %u %d %d %ld %ld %d\n", + (long)grwin->win, + grwin->x, grwin->y, grwin->w, grwin->h, + R->TermWin.fwidth, + R->TermWin.fheight, + (long)GRX_SCALE * R->TermWin.fwidth / grwin->w, + (long)GRX_SCALE * R->TermWin.fheight / grwin->h, + XDEPTH); + else /* rxvt terminal window size */ + rxvt_tt_printf(aR_ "\033G0 0 0 %d %d %d %d %ld %ld %d\n", + TermWin_TotalWidth(), TermWin_TotalHeight(), + R->TermWin.fwidth, R->TermWin.fheight, + (long)GRX_SCALE * R->TermWin.fwidth / R->TermWin.width, + (long)GRX_SCALE * R->TermWin.fheight / R->TermWin.height, + XDEPTH); +} + +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_Gr_DestroyWindow(pR_ grwin_t *grwin) +{ + grcmd_t *cmd, *next; + + if (grwin == NULL) + return; + + for (cmd = grwin->graphics; cmd; cmd = next) { + next = cmd->next; + free(cmd->coords); + if (cmd->text != NULL) + free(cmd->text); + free(cmd); + } + + XDestroyWindow(R->Xdisplay, grwin->win); + if (grwin->next != NULL) + grwin->next->prev = grwin->prev; + if (grwin->prev != NULL) + grwin->prev->next = grwin->next; + else + R->h->gr_root = grwin->next; + free(grwin); + + R->h->graphics_up--; +} + +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_Gr_Dispatch(pR_ grwin_t *grwin, grcmd_t *data) +{ + int i, n; + union { + XPoint pt[NGRX_PTS / 2]; + XRectangle rect[NGRX_PTS / 4]; + } xdata; + + if (data->color != Color_fg) { + XGCValues gcv; + + gcv.foreground = R->PixColors[data->color]; + XChangeGC(R->Xdisplay, R->TermWin.gc, GCForeground, &gcv); + } + if (grwin) + switch (data->cmd) { + case 'L': + if (data->ncoords > 3) { + for (n = i = 0; i < data->ncoords; i += 2, n++) { + xdata.pt[n].x = data->coords[i] * grwin->w / GRX_SCALE; + xdata.pt[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE; + } + XDrawLines(R->Xdisplay, + grwin->win, R->TermWin.gc, xdata.pt, n, CoordModeOrigin); + } + break; + + case 'P': + if (data->ncoords > 3) { + for (n = i = 0; i < data->ncoords; i += 2, n++) { + xdata.pt[n].x = data->coords[i] * grwin->w / GRX_SCALE; + xdata.pt[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE; + } + XDrawPoints(R->Xdisplay, + grwin->win, R->TermWin.gc, xdata.pt, n, CoordModeOrigin); + } + break; + + case 'F': + if (data->ncoords > 0) { + for (n = i = 0; i < data->ncoords; i += 4, n++) { + xdata.rect[n].x = data->coords[i] * grwin->w / GRX_SCALE; + xdata.rect[n].y = data->coords[i + 1] * grwin->h + / GRX_SCALE; + xdata.rect[n].width = ((data->coords[i + 2] + - data->coords[i] + 1) * + grwin->w / GRX_SCALE); + xdata.rect[n].height = ((data->coords[i + 3] + - data->coords[i + 1] + 1) * + grwin->h / GRX_SCALE); + XPMClearArea(R->Xdisplay, grwin->win, + xdata.rect[n].x, xdata.rect[n].y, + xdata.rect[n].width, xdata.rect[n].height, + 0); + } + XFillRectangles(R->Xdisplay, grwin->win, R->TermWin.gc, xdata.rect, + n); + } + break; + case 'T': + rxvt_Gr_Text(aR_ grwin, data); + break; + case 'C': + rxvt_Gr_ClearWindow(aR_ grwin); + break; + } + if (data->color != Color_fg) { + XGCValues gcv; + + gcv.foreground = R->PixColors[Color_fg]; + XChangeGC(R->Xdisplay, R->TermWin.gc, GCForeground, &gcv); + } +} + +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_Gr_Redraw(pR_ grwin_t *grwin) +{ + grcmd_t *cmd; + + for (cmd = grwin->graphics; cmd != NULL; cmd = cmd->next) + rxvt_Gr_Dispatch(aR_ grwin, cmd); +} + +/*----------------------------------------------------------------------* + * end of static functions + */ +/* ARGSUSED */ +/* EXTPROTO */ +void +rxvt_Gr_ButtonReport(pR_ int but, int x, int y) +{ + grwin_t *grwin; + + for (grwin = R->h->gr_root; grwin != NULL; grwin = grwin->next) + if ((x > grwin->x) + && (y > grwin->y) + && ((unsigned int)x < grwin->x + grwin->w) + && ((unsigned int)y < grwin->y + grwin->h)) + break; + + if (grwin == NULL) + return; + + x = GRX_SCALE * (x - grwin->x) / grwin->w; + y = GRX_SCALE * (y - grwin->y) / grwin->h; + rxvt_tt_printf(aR_ "\033%c%ld;%d;%d;\n", but, (long)grwin->win, x, y); +} + +/* ARGSUSED */ +/* EXTPROTO */ +void +rxvt_Gr_do_graphics(pR_ int cmd, unsigned int nargs, int args[], unsigned char *text) +{ + int i; + Window win_id; + grwin_t *grwin; + grcmd_t *newcmd, *oldcmd; + + if (cmd == 'W') { + rxvt_Gr_NewWindow(aR_ nargs, args); + return; + } + win_id = (nargs > 0) ? (Window) args[0] : None; + + if ((cmd == 'G') && (win_id == None)) { + rxvt_Gr_Geometry(aR_ NULL, NULL); + return; + } + if ((win_id == None) && (R->h->gr_last_id != None)) + win_id = R->h->gr_last_id; + + if (win_id == None) + return; + + grwin = R->h->gr_root; + while ((grwin != NULL) && (grwin->win != win_id)) + grwin = grwin->next; + + if (grwin == NULL) + return; + + if (cmd == 'G') { + rxvt_Gr_Geometry(aR_ grwin, NULL); + return; + } + nargs--; + args++; /* skip over window id */ + +/* record this new command */ + newcmd = (grcmd_t *) rxvt_malloc(sizeof(grcmd_t)); + newcmd->ncoords = nargs; + newcmd->coords = (int *)rxvt_malloc((newcmd->ncoords * sizeof(int))); + + newcmd->next = NULL; + newcmd->cmd = cmd; + newcmd->color = rxvt_scr_get_fgcolor(aR); + newcmd->text = text; + + for (i = 0; i < newcmd->ncoords; i++) + newcmd->coords[i] = args[i]; + +/* + * If newcmd == fill, and rectangle is full window, drop all prior + * commands. + */ + if ((newcmd->cmd == 'F') && (grwin) && (grwin->graphics)) { + for (i = 0; i < newcmd->ncoords; i += 4) { + if ((newcmd->coords[i] == 0) + && (newcmd->coords[i + 1] == 0) + && (newcmd->coords[i + 2] == GRX_SCALE) + && (newcmd->coords[i + 3] == GRX_SCALE)) { + /* drop previous commands */ + oldcmd = grwin->graphics; + while (oldcmd->next != NULL) { + grcmd_t *tmp = oldcmd; + + oldcmd = oldcmd->next; + free(tmp); + } + grwin->graphics = NULL; + } + } + } +/* insert new command into command list */ + oldcmd = grwin->graphics; + if (oldcmd == NULL) + grwin->graphics = newcmd; + else { + while (oldcmd->next != NULL) + oldcmd = oldcmd->next; + oldcmd->next = newcmd; + } + rxvt_Gr_Dispatch(aR_ grwin, newcmd); +} + +/* ARGSUSED */ +/* EXTPROTO */ +void +rxvt_Gr_scroll(pR_ int count) +{ + grwin_t *grwin, *next; + + if ((count == 0) && (R->h->gr_prev_start == R->TermWin.view_start)) + return; + + R->h->gr_prev_start = R->TermWin.view_start; + + for (grwin = R->h->gr_root; grwin != NULL; grwin = next) { + next = grwin->next; + grwin->y -= (count * R->TermWin.fheight); + if ((long)(grwin->y + grwin->h) + < -(long)(R->TermWin.saveLines * R->TermWin.fheight)) + rxvt_Gr_DestroyWindow(aR_ grwin); + else + XMoveWindow(R->Xdisplay, grwin->win, + grwin->x, + grwin->y + (R->TermWin.view_start * R->TermWin.fheight)); + } +} + +/* EXTPROTO */ +void +rxvt_Gr_ClearScreen(pR) +{ + grwin_t *grwin, *next; + + for (grwin = R->h->gr_root; grwin != NULL; grwin = next) { + next = grwin->next; + if ((grwin->screen == 0) && (grwin->y + grwin->h > 0)) { + if (grwin->y >= 0) + rxvt_Gr_DestroyWindow(aR_ grwin); + else + XResizeWindow(R->Xdisplay, grwin->win, + grwin->w, -grwin->y); + } + } +} + +/* EXTPROTO */ +void +rxvt_Gr_ChangeScreen(pR) +{ + grwin_t *grwin, *next; + + for (grwin = R->h->gr_root; grwin != NULL; grwin = next) { + next = grwin->next; + if (grwin->y + grwin->h > 0) { + if (grwin->screen == 1) { + XMapWindow(R->Xdisplay, grwin->win); + grwin->screen = 0; + } else { + XUnmapWindow(R->Xdisplay, grwin->win); + grwin->screen = 1; + } + } + } +} + +/* ARGSUSED */ +/* EXTPROTO */ +void +rxvt_Gr_expose(pR_ Window win) +{ + grwin_t *grwin; + + for (grwin = R->h->gr_root; grwin != NULL; grwin = grwin->next) { + if (grwin->win == win) { + rxvt_Gr_Redraw(aR_ grwin); + break; + } + } +} + +/* ARGSUSED */ +/* EXTPROTO */ +void +rxvt_Gr_Resize(pR_ int w __attribute__((unused)), int h) +{ + grwin_t *grwin; + + for (grwin = R->h->gr_root; grwin != NULL; grwin = grwin->next) { + if (R->TermWin.height != h) { + grwin->y += (R->TermWin.height - h); + XMoveWindow(R->Xdisplay, grwin->win, + grwin->x, + grwin->y + (R->TermWin.view_start * R->TermWin.fheight)); + } + rxvt_Gr_Redraw(aR_ grwin); + } +} + +/* EXTPROTO */ +void +rxvt_Gr_reset(pR) +{ + grwin_t *grwin, *next; + + for (grwin = R->h->gr_root; grwin != NULL; grwin = next) { + next = grwin->next; + rxvt_Gr_DestroyWindow(aR_ grwin); + } + + R->h->graphics_up = 0; +} + +/* EXTPROTO */ +int +rxvt_Gr_Displayed(pR) +{ + return R->h->graphics_up; +} +#endif +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/graphics/Makefile.in b/src/graphics/Makefile.in new file mode 100644 index 00000000..b9873f50 --- /dev/null +++ b/src/graphics/Makefile.in @@ -0,0 +1,66 @@ +# test/graphics/Makefile.in -*- Makefile -*- +# $Id: Makefile.in,v 1.1 2003-11-24 17:28:08 pcg Exp $ +@MCOMMON@ + +srcdir = @srcdir@ +VPATH = @srcdir@ +.PATH: @srcdir@ + +basedir = ../.. +thisdir = src/graphics + +first_rule: qplot +dummy: + +SRCS = grxlib.c qplot.c +OBJS = grxlib.o qplot.o +HDRS = grxlib.h + +# +# Distribution variables +# + +DIST = $(HDRS) $(SRCS) README data Makefile.in + +# inference rules +.c.o: + $(COMPILE) -I$(srcdir)/.. -c $< + +#------------------------------------------------------------------------- +all: + +graphics: qplot + +qplot: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) -lm + +tags: $(SRCS) + ctags $(SRCS) + +alldoc: + +allbin: qplot + +clean: + $(RMF) qplot core a.out *.o *.bak *~ + +realclean: clean + $(RMF) tags + +cleandir: realclean + +distclean: + (cd $(srcdir); $(RMF) qplot *~ *.o core a.out) + if test $(srcdir) = .; then $(MAKE) realclean; fi + (cd $(srcdir); $(RMF) Makefile) + +install uninstall: + +distdirs: + mkdir $(basedir)/../$(VERNAME)/$(thisdir) + +distcopy: + $(CP) -p $(DIST) $(basedir)/../$(VERNAME)/$(thisdir) + +# ----------------------------------------------------------------------- +# forget dependencies, there are too few diff --git a/src/graphics/grxlib.c b/src/graphics/grxlib.c new file mode 100644 index 00000000..56301bfa --- /dev/null +++ b/src/graphics/grxlib.c @@ -0,0 +1,205 @@ +/* + * $Id: grxlib.c,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#include "../../config.h" +#include "rxvt.h" +#include "init.h" /* for GET_TERMIOS / SET_TERMIOS */ +#include "grxlib.h" + +/*----------------------------------------------------------------------*/ + +void +Done(void) +{ + putchar(':'); +} + +void +StartLine(long id) +{ + printf("\033GL%ld", id); +} + +void +StartPoint(long id) +{ + printf("\033GP%ld", id); +} + +void +StartFill(long id) +{ + printf("\033GF%ld", id); +} + +void +Extend(int x, int y) +{ + printf(";%d;%d", x, y); +} + +void +FillArea(int x1, int y1, int x2, int y2) +{ + printf(";%d;%d;%d;%d", x1, y1, x2, y2); +} + +void +PlaceText(long id, int x, int y, int mode, char *text) +{ + printf("\033GT%ld;%d;%d;%d;%d:%s", id, x, y, mode, strlen(text), text); + fflush(stdout); +} + +void +ClearWindow(long id) +{ + printf("\033GC%ld:", id); +} + +void +ForeColor(int col) +{ + printf("\033[3%dm", (col < 0 || col > 7) ? 0 : col); +} + +void +DefaultRendition(void) +{ + printf("\033[m"); +} + +#define LINESZ 100 +static char line[LINESZ]; +static FILE *infd = NULL; + +long +CreateWin(int x, int y, int w, int h) +{ + long id = 0; + + fflush(stdout); + printf("\033GW%d;%d;%d;%d:", x, y, w, h); + fflush(stdout); + while (1) { + if ((fgets(line, LINESZ, infd) != NULL) && + (sscanf(line, "\033W%ld", &id) == 1)) + break; + } + return id; +} + +void +QueryWin(long id, int *nfwidth, int *nfheight) +{ + int id1, x, y, width, height, fwidth, fheight; + + printf("\033GG%ld:", id); + fflush(stdout); + while (1) { + if ((fgets(line, sizeof(line), infd) != NULL) && + (sscanf(line, "\033G%ld %ld %ld %ld %ld %ld %ld %ld %ld", + &id1, &x, &y, &width, &height, + &fwidth, &fheight, nfwidth, nfheight) != 0)) + break; + } +} + +int +WaitForCarriageReturn(long *win, int *x, int *y) +{ + int i, len; + + fgets(line, LINESZ, infd); + line[LINESZ - 1] = 0; + len = strlen(line); + for (i = 0; i < len; i++) { + if (line[i] == '\033') { + int ret = 1; + + i++; + switch (line[i]) { + case 'R': + ret++; + /* drop */ + case 'P': + sscanf(&line[i + 1], "%ld;%d;%d", win, x, y); + return ret; + break; + } + } + } + return 0; +} + +static int fno2; +static ttymode_t ttmode; + +int +InitializeGraphics(int scroll_text_up) +{ + int fno, i; + char *screen_tty; + struct winsize winsize; + + fno = fileno(stdout); + if (!isatty(fno)) { + fprintf(stderr, "stdout must be a tty\n"); + return 0; + } + screen_tty = ttyname(fno); + +#ifdef HAVE_TERMIOS_H + GET_TERMIOS(fno, &ttmode); + ttmode.c_lflag &= ~ECHO; + SET_TERMIOS(fno, &ttmode); +#endif + + infd = fopen(screen_tty, "rw"); + +#ifdef HAVE_TERMIOS_H + fno2 = fileno(infd); + GET_TERMIOS(fno2, &ttmode); + ttmode.c_lflag &= ~ECHO; + SET_TERMIOS(fno2, &ttmode); +#endif + + /* query rxvt to find if graphics are available */ + fflush(stdout); + printf("\033GQ"); + fflush(stdout); + while (1) { + if ((fgets(line, LINESZ, infd) != NULL) && + (sscanf(line, "\033G%d", &i) == 1)) { + if (!i) { + fprintf(stderr, "rxvt graphics not available\n"); + CloseGraphics(); + return 0; + } + break; + } + } + if (scroll_text_up) { + ioctl(fno, TIOCGWINSZ, &winsize); + fflush(stdout); + for (i = 0; i < winsize.ws_row; i++) + putchar('\n'); + fflush(stdout); + } + return i; +} + +void +CloseGraphics(void) +{ + DefaultRendition(); + fflush(stdout); +#ifdef HAVE_TERMIOS_H + ttmode.c_lflag |= ECHO; + SET_TERMIOS(fno2, &ttmode); +#endif + fclose(infd); +} + +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/graphics/grxlib.h b/src/graphics/grxlib.h new file mode 100644 index 00000000..fd7228ea --- /dev/null +++ b/src/graphics/grxlib.h @@ -0,0 +1,31 @@ +/* + * $Id: grxlib.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ +#include "rxvtgrx.h" /* text alignment */ + +/*function pointer to either StartLine or StartPoint */ +typedef void (*LineFunction) (long id); + +#ifdef __cplusplus +extern "C" { +#endif + extern void StartLine (long id); + extern void StartPoint (long id); + extern void Extend (int x, int y); + extern void StartFill (long id); + extern void FillArea (int x1, int y1, int x2, int y2); + extern void Done (void); + extern void PlaceText (long id, int x, int y, int mode, char *text); + + extern void ClearWindow (long id); + extern long CreateWin (int x, int y, int w, int h); + extern void QueryWin (long id, int *nfwidth, int *nfheight); + extern void ForeColor (int color); + extern void DefaultRendition (void); + extern int WaitForCarriageReturn (long *win, int *x, int *y); + extern int InitializeGraphics (int scroll_text_up); + extern void CloseGraphics (void); +#ifdef __cplusplus +} +#endif +/*----------------------- end-of-file (C header) -----------------------*/ diff --git a/src/graphics/qplot.c b/src/graphics/qplot.c new file mode 100644 index 00000000..a4062af2 --- /dev/null +++ b/src/graphics/qplot.c @@ -0,0 +1,249 @@ +/* + * $Id: qplot.c,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#include +#include +#include +#include +#include "grxlib.h" + +#define Real float + +#ifndef GRX_SCALE +# define GRX_SCALE 10000 +#endif + +#define DEFAULT_DATA_FILE "data" + +static void +axis_round(Real * min, Real * max, Real * grid_spacing) +{ + int logspace; + + logspace = (int)(log10((*max - *min) / 10.0) + 0.5); + *grid_spacing = pow(10, (double)logspace); + *min = (Real) ((int)(*min / (*grid_spacing))) * (*grid_spacing); + *max = (Real) ((int)(*max / (*grid_spacing)) + 1) * (*grid_spacing); +} + +static int +nice_end(int junk) +{ + CloseGraphics(); + putchar('\n'); + exit(EXIT_SUCCESS); + return 0; +} + +int +main(int argc, char **argv) +{ + char *file = NULL; + int Do_Start = 1, tmp; + int m, p, i, j, n, nchars, theight, twidth, xclick, yclick; + int downx = 1000, downy = 1000, upx, upy; + long id, winclick; + Real xmax, xmin, ymax, ymin, xdiff, ydiff, xgrid_spacing, + ygrid_spacing; + Real *x, *y, *nls; + LineFunction linetype = StartLine; + char axis[100], line[256]; + FILE *fd; + + x = (Real *)malloc(1000000 * sizeof(Real)); + y = (Real *)malloc(1000000 * sizeof(Real)); + nls = (Real *)malloc(1000 * sizeof(Real)); + if (x == NULL || y == NULL || nls == NULL) { + fprintf(stderr, "Can't allocate initial memory\n"); + exit(1); + } + + ymax = xmax = -HUGE_VAL; + ymin = xmin = HUGE_VAL; + + for (i = 1; i < argc; i++) { + if (*argv[i] == '-') { + if (!strcmp(argv[i], "-nl")) + linetype = StartPoint; + else if (argv[i][1] == '\0') /* use stdin */ + file = argv[i]; + else { + + fprintf(stderr, "Usage:\n\t %s [options] [file]\n\n", argv[0]); + fprintf(stderr, + "where options include:\n" + " -pt plot with points instead of lines\n\n"); + + fprintf(stderr, + "file name `-' specifies stdin\n" + "if no file name is specified, " + "the default is \"%s\"\n\n", DEFAULT_DATA_FILE); + + return EXIT_FAILURE; + } + } else + file = argv[i]; + } + + if (file && !strcmp(file, "-")) { + fd = stdin; + file = "stdin"; + } else { + if (file == NULL) + file = DEFAULT_DATA_FILE; + + if ((fd = fopen(file, "r")) == NULL) { + fprintf(stderr, "%s: can't open file \"%s\"\n", argv[0], file); + return EXIT_FAILURE; + } + } + m = 0; + p = 0; + while (fgets(line, sizeof(line), fd) != NULL) { + if (sscanf(line, "%f %f", &x[m], &y[m]) == 2) { + if (x[m] > xmax) + xmax = x[m]; + else if (x[m] < xmin) + xmin = x[m]; + if (y[m] > ymax) + ymax = y[m]; + else if (y[m] < ymin) + ymin = y[m]; + m++; + } else { + nls[p] = m; + p++; + } + } + nls[p++] = m; + + if (m == 0) + return; + + signal(SIGTERM, nice_end); + signal(SIGSTOP, nice_end); + signal(SIGTSTP, nice_end); + signal(SIGINT, nice_end); + signal(SIGQUIT, nice_end); + if (!InitializeGraphics(1)) + return EXIT_FAILURE; + + n = 1; + do { + axis_round(&xmin, &xmax, &xgrid_spacing); + axis_round(&ymin, &ymax, &ygrid_spacing); + + id = CreateWin(0, 0, GRX_SCALE, GRX_SCALE); + if (id == 0) { + fprintf(stderr, "Help id = 0\n"); + return EXIT_FAILURE; + } + /* Fill the window in black for real eye-catching graphics! */ + ForeColor(0); + StartFill(id); + FillArea(0, 0, GRX_SCALE, GRX_SCALE); + Done(); + + /* draw outline box in white */ + ForeColor(7); + + /* Draw outline box */ + StartLine(id); + Extend(1000, 1000); + Extend(1000, 9000); + Extend(9000, 9000); + Extend(9000, 1000); + Extend(1000, 1000); + Done(); + + /* Draw the data - either lines or dots */ + xdiff = 8000 / (xmax - xmin); + ydiff = 8000 / (ymax - ymin); + + for (i = j = 0; j < p; j++) { + int n = 0; + + ForeColor(j % 6 + 1); + while (((x[i] < xmin) || (x[i] > xmax) || + (y[i] < ymin) || (y[i] > ymax)) && (i < nls[j])) + i++; + + while (i < nls[j]) { + if (n == 0) + linetype(id); + Extend(1000 + (x[i] - xmin) * xdiff, + 9000 - (y[i] - ymin) * ydiff); + n++; + if (n > 450) { + Done(); + n = 0; + continue; + } + i++; + while ((i < nls[j]) && + ((x[i] < xmin) || (x[i] > xmax) || + (y[i] < ymin) || (y[i] > ymax))) + i++; + } + if (n > 0) + Done(); + } + + /* Do axis labels in black */ + ForeColor(7); + QueryWin(id, &twidth, &theight); + PlaceText(id, GRX_SCALE / 2, 0, HCENTER_TEXT | TOP_TEXT, file); + PlaceText(id, GRX_SCALE / 2, GRX_SCALE, HCENTER_TEXT | BOTTOM_TEXT, + "X"); + PlaceText(id, 0, GRX_SCALE / 2, LEFT_TEXT | VCENTER_TEXT, "Y"); + sprintf(axis, "%f", ymax); + nchars = 1000 / twidth; + axis[nchars] = 0; + PlaceText(id, GRX_SCALE / 10, GRX_SCALE / 10, + RIGHT_TEXT | TOP_TEXT, axis); + sprintf(axis, "%f", ymin); + axis[nchars] = 0; + PlaceText(id, GRX_SCALE / 10, 9 * GRX_SCALE / 10, + RIGHT_TEXT | BOTTOM_TEXT, axis); + sprintf(axis, "%f", xmax); + PlaceText(id, 9 * GRX_SCALE / 10, 9 * GRX_SCALE / 10, + HCENTER_TEXT | TOP_TEXT, axis); + sprintf(axis, "%f", xmin); + PlaceText(id, GRX_SCALE / 10, 9 * GRX_SCALE / 10, + HCENTER_TEXT | TOP_TEXT, axis); + fflush(stdout); + + do { + n = WaitForCarriageReturn(&winclick, &xclick, &yclick); + switch (n) { + case 1: + downx = xclick; + downy = yclick; + break; + case 2: + upx = xclick; + upy = yclick; + if (upx < downx) { + tmp = downx; + downx = upx; + upx = tmp; + } + if (upy < downy) { + tmp = downy; + downy = upy; + upy = tmp; + } + xmin = (xmax - xmin) * (downx - 1000) / (8000) + xmin; + xmax = (xmax - xmin) * (upx - 1000) / (8000) + xmin; + ymax = ymax - (ymax - ymin) * (downy - 1000) / (8000); + ymin = ymax - (ymax - ymin) * (upy - 1000) / (8000); + break; + } + } while (n && (n != 2)); + } while (n); + nice_end(EXIT_SUCCESS); + return EXIT_SUCCESS; +} + +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/grkelot.C b/src/grkelot.C new file mode 100644 index 00000000..6486f5b5 --- /dev/null +++ b/src/grkelot.C @@ -0,0 +1,428 @@ +/*---------------------------------*C*--------------------------------------* + * File: grkelot.c + *--------------------------------------------------------------------------* + * $Id: grkelot.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1994,1995 Angelo Haritsis. All rights reserved. + * - original version + * Copyright (c) 1997,1998 Oezger Kesim + * + * 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: + * -:n1,n2,n3,... + * Format of switcher string: + * A: + * (other switchers apart from A=ascii can be supported; not in this context) + * Format of life string: + * L (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 +#include + +/* --- Macros, Types --------- */ +#define MAX_STATES 4 /* max # states for the FSM */ +#define MAX_SWITCHER 2U /* per state */ +#define MAX_VAL 256 /* for temp allocation */ + +typedef unsigned char u_char; +typedef unsigned int u_int; +typedef unsigned long u_long; + +typedef struct s_xlat { + u_int first, last; + u_int *pval; /* array of translated values */ +} K_XLAT; + +typedef struct s_switch { + u_char type; /* Ascii, Virtual, Scan */ + u_int code; + u_char nextstate; + u_char on; /* current state of key: 0 = off */ +} K_SWITCH; + +typedef struct s_state { + u_int num_xlat; /* number of translations */ + K_XLAT *xlat; /* State translations ((dynamic - realloc'ed) */ + u_int num_switcher; /* number of switcher keys */ + K_SWITCH switcher[MAX_SWITCHER]; /* switcher keys to other states */ + u_char life; /* 0 = until switched by key */ + u_char prev_state; /* filled when jumped to a new state */ +} K_STATE; + +/* type for each one of the different greek standards (xlat types) */ +typedef struct s_xlat_type { + char *plain; + char *accent; + char *accent_xtra; + char *umlaut; + char *acc_uml; +} XLAT_TYPE; + +/* --- Local Data ------------ */ +static K_STATE State[MAX_STATES]; + +/* Current State */ +static u_char nStateNow = 0; +static K_STATE *pStateNow = &State[0]; +static int GreekMode = GREEK_ELOT928; + +/* + * The following are hard-coded for now. The idea is that such strings would + * be read from a config file making it possible to change language/encodings + * more flexibly. + */ +/* elot 928 xlations */ +static char elot_xlat_plain[] = "65-122:193,194,216,196,197,214,195,199,201,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,213,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,233,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,245,230"; + +/* c and s give copyright and section sign */ +static char elot_xlat_acc[] = "65-122:182,194,216,196,184,214,195,185,186,206,202,203,204,205,188,208,81,209,211,212,200,191,87,215,190,198,91,92,93,94,95,96,220,226," /*248 */ "169,228,221,246,227,222,223,238,234,235,236,237,252,240,113,241," /*243 */ "167,244,232,254,242,247,253,230"; +static char elot_xlat_acc_xtra[] = "46-62:183,47,48,49,50,51,52,53,54,55,56,57,58,59,171,61,187"; /* anw teleia, quotes */ +static char elot_xlat_uml[] = "65-122:193,194,216,196,197,214,195,199,218,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,219,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,250,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,251,230"; +static char elot_xlat_umacc[] = "65-122:193,194,216,196,197,214,195,199,201,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,213,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,192,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,224,230"; + +/* ibm 437 xlations */ +static char i437_xlat_plain[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,160,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,172,157"; +static char i437_xlat_acc[] = "65-122:234,129,150,131,235,148,130,236,237,141,137,138,139,140,238,143,81,144,145,146,135,240,87,149,239,133,91,92,93,94,95,96,225,153,175,155,226,173,154,227,229,165,161,162,163,164,230,167,113,168,169,171,159,233,170,174,231,157"; +static char i437_xlat_acc_xtra[] = "46-46:250"; /* anw teleia */ +static char i437_xlat_uml[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,228,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,232,157"; +static char i437_xlat_umacc[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,42,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,42,157"; + +/* + * currently ELOT928 and IBM437 are supported; easy to include others + * (not recommended: stick to just these 2 if not only the ELOT one) + */ +static XLAT_TYPE xlat_type[] = +{ + {elot_xlat_plain, elot_xlat_acc, elot_xlat_acc_xtra, elot_xlat_uml, elot_xlat_umacc}, + {i437_xlat_plain, i437_xlat_acc, i437_xlat_acc_xtra, i437_xlat_uml, i437_xlat_umacc}, +}; + +/* the current trasnaltion type */ +static XLAT_TYPE *xlat_now = &xlat_type[GREEK_ELOT928]; + +#define NUM_XLAT_TYPES (sizeof(xlat_type) / sizeof(xlat_type[0])) + +static void kstate_add_xlat(char *str); +static void kstate_add_switcher(char *str); +static void kstate_set_life(char *str); + +/* --- Functions ------------- */ +/* INTPROTO */ +void +kstate_setcurr(int stateno) +{ + u_char prev_state; + + if ((u_int) stateno > (u_int) MAX_STATES) + return; + if (pStateNow->life == 1) + prev_state = pStateNow->prev_state; + else + prev_state = nStateNow; + pStateNow = &State[nStateNow = stateno]; + pStateNow->prev_state = prev_state; +} + +/* INTPROTO */ +void +kstate_init(void) +{ + pStateNow->num_xlat = pStateNow->num_switcher = pStateNow->life = pStateNow->prev_state = 0; + pStateNow->xlat = NULL; +} + +/* INTPROTO */ +void +kstate_end(void) +{ + int i; + + for (i = 0; i < pStateNow->num_xlat; i++) + free(pStateNow->xlat[i].pval); + if (pStateNow->num_xlat > 0) + free(pStateNow->xlat); +} + +/* + * Hard coded ELOT-928 translations. Could read these from an rc-type file + * to support other remappers. + */ +/* INTPROTO */ +void +kstate_init_all(int greek_mode) +{ +/* the translation tables for the 4 FSM states for ELOT-928 mappings */ + int i; + + for (i = 0; i < MAX_STATES; i++) { + kstate_setcurr(i); + kstate_init(); + } + if (greek_mode < 0 || greek_mode >= NUM_XLAT_TYPES) /* avoid death */ + greek_mode = GREEK_ELOT928; + xlat_now = &xlat_type[greek_mode]; + kstate_setcurr(0); + kstate_add_xlat(xlat_now->plain); + kstate_add_switcher("A;:1"); + kstate_add_switcher("A::2"); + kstate_set_life("L0"); + + kstate_setcurr(1); + kstate_add_xlat(xlat_now->accent); + kstate_add_xlat(xlat_now->accent_xtra); + kstate_add_switcher("A::3"); + kstate_set_life("L1"); + + kstate_setcurr(2); + kstate_add_xlat(xlat_now->umlaut); + kstate_add_switcher("A;:3"); + kstate_set_life("L1"); + + kstate_setcurr(3); + kstate_add_xlat(xlat_now->acc_uml); + kstate_set_life("L1"); +} + +/* INTPROTO */ +void +kstate_end_all(void) +{ + int i; + + for (i = 0; i < MAX_STATES; i++) { + kstate_setcurr(i); + kstate_end(); + } + kstate_setcurr(0); +} + +/* + * reset FSM + */ +/* INTPROTO */ +void +kstate_reset(void) +{ + kstate_setcurr(0); +} + +/* INTPROTO */ +void +kstate_add_xlat(char *str) +{ + K_XLAT *xlat; + u_int *pval_tmp; + char *sval; + int i; + + if (str == NULL) + return; +/* add a new xlat table in state */ + if (pStateNow->num_xlat == 0) { + pStateNow->xlat = malloc(sizeof(K_XLAT)); + } else /* prefer contiguous data, realloc */ + pStateNow->xlat = realloc(pStateNow->xlat, (pStateNow->num_xlat + 1) * sizeof(K_XLAT)); + xlat = &pStateNow->xlat[pStateNow->num_xlat]; +/* parse str and derive first, last, values */ + xlat->first = (u_int) atoi(strtok(str, "-")); + xlat->last = (u_int) atoi(strtok(NULL, ":")); + i = 0; + pval_tmp = calloc(MAX_VAL, sizeof(K_XLAT)); + while ((sval = strtok(NULL, ",")) != NULL) + pval_tmp[i++] = (u_int) (atoi(sval)); + xlat->pval = calloc(i, sizeof(K_XLAT)); + if (xlat->pval != NULL) + memcpy(xlat->pval, pval_tmp, i * sizeof(u_int)); + free(pval_tmp); + pStateNow->num_xlat++; +} + +/* + * Ascii only for this implementation + */ +/* INTPROTO */ +void +kstate_add_switcher(char *str) +{ + K_SWITCH *switcher; + + if (str == NULL) + return; + if (pStateNow->num_switcher >= MAX_SWITCHER) + return; + switcher = &pStateNow->switcher[pStateNow->num_switcher]; + switch (switcher->type = str[0]) { + case 'A': /* ascii eg: A;:2 */ + switcher->code = str[1]; + switcher->nextstate = atoi(&str[3]); + break; + } + switcher->on = 0; + pStateNow->num_switcher++; +} + +/* L1 or L0 */ +/* INTPROTO */ +void +kstate_set_life(char *str) +{ + pStateNow->life = atoi(&str[1]); +} + +/* INTPROTO */ +unsigned int +kstate_cxlat(unsigned int c) +{ + int i; + +/* check for ascii switcher */ + for (i = 0; i < pStateNow->num_switcher; i++) + if (pStateNow->switcher[i].type == 'A' && /* only ascii here */ + c == pStateNow->switcher[i].code) { + kstate_setcurr(pStateNow->switcher[i].nextstate); + pStateNow->switcher[i].on = 1; + return ((unsigned int)-1); + } +/* do translation */ + for (i = 0; i < pStateNow->num_xlat; i++) + if (c >= pStateNow->xlat[i].first && c <= pStateNow->xlat[i].last) { + c = pStateNow->xlat[i].pval[c - pStateNow->xlat[i].first]; + break; + } +/* switch back to previous state if life of current is 1 */ + if (pStateNow->life == 1) + kstate_setcurr(pStateNow->prev_state); + return (c); +} + +#ifdef RXVT +/* EXTPROTO */ +void +greek_init(void) +{ + kstate_init_all(GreekMode); +} + +/* EXTPROTO */ +void +greek_end(void) +{ + kstate_end_all(); +} + +/* EXTPROTO */ +void +greek_reset(void) +{ + kstate_reset(); +} + +/* EXTPROTO */ +void +greek_setmode(int greek_mode) +{ + GreekMode = greek_mode; +} + +/* EXTPROTO */ +int +greek_getmode(void) +{ + return (GreekMode); +} + +/* + * xlate a given string in-place - return new string length + */ +/* EXTPROTO */ +int +greek_xlat(char *s, int num_chars) +{ + int i, count; + unsigned int c; + + for (i = 0, count = 0; i < num_chars; i++) { + c = kstate_cxlat((unsigned int)s[i]); + if (c != -1) + s[count++] = (char)c; + } + s[count] = '\0'; + return (count); + +} + +#ifdef TEST +int +main(void) +{ +/*char text[] = "abcdef;aGDZXC"; */ + char text[] = "abcdef;a:ibgdezhuiklmnjoprstyfxcv"; + + kstate_init_all(GREEK_ELOT928); + printf("text: %s\n", text); + greek_xlat(text, strlen(text)); + printf("xlat'ed text: %s\n", text); + kstate_end_all(); + return 0; +} +#endif +#endif /* RXVT */ + +#endif /* GREEK_SUPPORT */ diff --git a/src/grkelot.h b/src/grkelot.h new file mode 100644 index 00000000..b0b2b233 --- /dev/null +++ b/src/grkelot.h @@ -0,0 +1,43 @@ +/* + * File: grkelot.h + * $Id: grkelot.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Synopsis: string -> greek ELOT928 string; 4-state FSM. + * + * Copyright (c) 1994 Angelo Haritsis. All rights reserved. + * Copyright (c) 1997,1998 Oezguer Kesim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GRKELOT_H +#define _GRKELOT_H + +#define GREEK_ELOT928 0 +#define GREEK_IBM437 1 + +#ifdef __cplusplus +extern "C" { +#endif + extern void greek_init (void); + extern void greek_end (void); + extern void greek_reset (void); + extern void greek_setmode(int greek_mode); + extern int greek_getmode(void); + extern int greek_xlat (char *s, int num_chars); +#ifdef __cplusplus +} +#endif +#endif /* _GRKELOT_H */ diff --git a/src/init.C b/src/init.C new file mode 100644 index 00000000..858e429b --- /dev/null +++ b/src/init.C @@ -0,0 +1,1701 @@ +/*--------------------------------*-C-*---------------------------------* + * File: init.c + *----------------------------------------------------------------------* + * $Id: init.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1992 John Bovey, University of Kent at Canterbury + * - original version + * Copyright (c) 1994 Robert Nation + * - extensive modifications + * Copyright (c) 1998-2001 Geoff Wing + * - extensive modifications + * Copyright (c) 1999 D J Hawkey Jr + * - 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 + +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 */ +# define FOO(flag,name) \ + if ((tio->c_iflag) & flag) \ + fprintf (stderr, "%s ", name) + +/* c_iflag bits */ + FOO(IGNBRK, "IGNBRK"); + FOO(BRKINT, "BRKINT"); + FOO(IGNPAR, "IGNPAR"); + FOO(PARMRK, "PARMRK"); + FOO(INPCK, "INPCK"); + FOO(ISTRIP, "ISTRIP"); + FOO(INLCR, "INLCR"); + FOO(IGNCR, "IGNCR"); + FOO(ICRNL, "ICRNL"); + FOO(IXON, "IXON"); + FOO(IXOFF, "IXOFF"); +# ifdef IUCLC + FOO(IUCLC, "IUCLC"); +# endif +# ifdef IXANY + FOO(IXANY, "IXANY"); +# endif +# ifdef IMAXBEL + FOO(IMAXBEL, "IMAXBEL"); +# endif + fprintf(stderr, "\n"); + +# undef FOO +# define FOO(entry, name) \ + fprintf(stderr, "%-8s = %#04o\n", name, tio->c_cc [entry]) + + FOO(VINTR, "VINTR"); + FOO(VQUIT, "VQUIT"); + FOO(VERASE, "VERASE"); + FOO(VKILL, "VKILL"); + FOO(VEOF, "VEOF"); + FOO(VEOL, "VEOL"); +# ifdef VEOL2 + FOO(VEOL2, "VEOL2"); +# endif +# ifdef VSWTC + FOO(VSWTC, "VSWTC"); +# endif +# ifdef VSWTCH + FOO(VSWTCH, "VSWTCH"); +# endif + FOO(VSTART, "VSTART"); + FOO(VSTOP, "VSTOP"); + FOO(VSUSP, "VSUSP"); +# ifdef VDSUSP + FOO(VDSUSP, "VDSUSP"); +# endif +# ifdef VREPRINT + FOO(VREPRINT, "VREPRINT"); +# endif +# ifdef VDISCRD + FOO(VDISCRD, "VDISCRD"); +# endif +# ifdef VWERSE + FOO(VWERSE, "VWERSE"); +# endif +# ifdef VLNEXT + FOO(VLNEXT, "VLNEXT"); +# endif + fprintf(stderr, "\n"); +# undef FOO +# endif /* HAVE_TERMIOS_H */ +#endif /* DEBUG_TTYMODE */ +} + +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/init.h b/src/init.h new file mode 100644 index 00000000..6c3e578a --- /dev/null +++ b/src/init.h @@ -0,0 +1,159 @@ +/* + * $Id: init.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#ifndef _INIT_H_ +#define _INIT_H_ + +#undef CERASE /* TODO */ +#define CERASE '\010' /* ^H */ + +#ifdef HAVE_XSETLOCALE +# define X_LOCALE +# include +#else +# ifdef HAVE_SETLOCALE +# include +# endif +#endif /* HAVE_XLOCALE */ + +#if defined(PTYS_ARE_PTMX) && !defined(__CYGWIN32__) +# include /* for struct rlimit */ +# define _NEW_TTY_CTRL /* to get proper defines in */ +#endif + +#ifdef __QNX__ /* autoconf someday */ +# include +#endif + +#ifdef TTY_GID_SUPPORT +# include +#endif + +/* ways to deal with getting/setting termios structure */ + +#ifdef HAVE_TERMIOS_H +/* termios interface */ +# ifdef TCSANOW /* POSIX */ +# define GET_TERMIOS(fd,tios) tcgetattr (fd, tios) +# define SET_TERMIOS(fd,tios) \ + cfsetospeed (tios, BAUDRATE), \ + cfsetispeed (tios, BAUDRATE), \ + tcsetattr (fd, TCSANOW, tios) +# else +# ifdef TIOCSETA +# define GET_TERMIOS(fd,tios) ioctl (fd, TIOCGETA, tios) +# define SET_TERMIOS(fd,tios) \ + tios->c_cflag |= BAUDRATE, \ + ioctl (fd, TIOCSETA, tios) +# else +# define GET_TERMIOS(fd,tios) ioctl (fd, TCGETS, tios) +# define SET_TERMIOS(fd,tios) \ + tios->c_cflag |= BAUDRATE, \ + ioctl (fd, TCSETS, tios) +# endif +# endif +# define SET_TTYMODE(fd,tios) SET_TERMIOS (fd, tios) +#else +/* sgtty interface */ + +# define SET_TTYMODE(fd,tt) \ + tt->sg.sg_ispeed = tt->sg.sg_ospeed = BAUDRATE, \ + ioctl (fd, TIOCSETP, &(tt->sg)), \ + ioctl (fd, TIOCSETC, &(tt->tc)), \ + ioctl (fd, TIOCSLTC, &(tt->lc)), \ + ioctl (fd, TIOCSETD, &(tt->line)), \ + ioctl (fd, TIOCLSET, &(tt->local)) +#endif /* HAVE_TERMIOS_H */ + +/* use the fastest baud-rate */ +#ifdef B38400 +# define BAUDRATE B38400 +#else +# ifdef B19200 +# define BAUDRATE B19200 +# else +# define BAUDRATE B9600 +# endif +#endif + +/* Disable special character functions */ +#ifdef _POSIX_VDISABLE +# define VDISABLE _POSIX_VDISABLE +#else +# define VDISABLE 255 +#endif + +/*----------------------------------------------------------------------* + * system default characters if defined and reasonable + */ +#ifndef CINTR +# define CINTR '\003' /* ^C */ +#endif +#ifndef CQUIT +# define CQUIT '\034' /* ^\ */ +#endif +#ifndef CERASE +# ifdef linux +# define CERASE '\177' /* ^? */ +# else +# define CERASE '\010' /* ^H */ +# endif +#endif +#ifndef CKILL +# define CKILL '\025' /* ^U */ +#endif +#ifndef CEOF +# define CEOF '\004' /* ^D */ +#endif +#ifndef CSTART +# define CSTART '\021' /* ^Q */ +#endif +#ifndef CSTOP +# define CSTOP '\023' /* ^S */ +#endif +#ifndef CSUSP +# define CSUSP '\032' /* ^Z */ +#endif +#ifndef CDSUSP +# define CDSUSP '\031' /* ^Y */ +#endif +#ifndef CRPRNT +# define CRPRNT '\022' /* ^R */ +#endif +#ifndef CFLUSH +# define CFLUSH '\017' /* ^O */ +#endif +#ifndef CWERASE +# define CWERASE '\027' /* ^W */ +#endif +#ifndef CLNEXT +# define CLNEXT '\026' /* ^V */ +#endif + +#ifndef VDISCRD +# ifdef VDISCARD +# define VDISCRD VDISCARD +# endif +#endif + +#ifndef VWERSE +# ifdef VWERASE +# define VWERSE VWERASE +# endif +#endif + +#ifndef O_NOCTTY +# define O_NOCTTY 0 +#endif +#ifndef O_NDELAY +# define O_NDELAY O_NONBLOCK /* QNX, at least */ +#endif +#ifndef ONLCR +# define ONLCR 0 /* QNX, at least */ +#endif + +#define CONSOLE "/dev/console" /* console device */ + +#include "init.intpro" /* PROTOS for internal routines */ +#endif /* _INIT_H_ */ diff --git a/src/logging.C b/src/logging.C new file mode 100644 index 00000000..226f47da --- /dev/null +++ b/src/logging.C @@ -0,0 +1,430 @@ +/*--------------------------------*-C-*---------------------------------* + * File: logging.c + *----------------------------------------------------------------------* + * $Id: logging.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1992 John Bovey + * - original version + * Copyright (c) 1993 lipka + * Copyright (c) 1993 Brian Stempien + * Copyright (c) 1995 Raul Garcia Garcia + * Copyright (c) 1995 Piet W. Plomp + * Copyright (c) 1997 Raul Garcia Garcia + * Copyright (c) 1998-2001 Geoff Wing + * - extensive modifications + * Copyright (c) 1999 D J Hawkey Jr + * - lastlog support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------* + * Public: + * extern void cleanutent (void); + * extern void makeutent (const char * pty, const char * hostname); + * + * Private: + * rxvt_update_wtmp (); + *----------------------------------------------------------------------*/ + +#include "../config.h" /* NECESSARY */ +#include "rxvt.h" /* NECESSARY */ +#include "logging.h" +#ifdef UTMP_SUPPORT + +/* + * BSD style utmp entry + * ut_line, ut_name, ut_host, ut_time + * SYSV style utmp (and utmpx) entry + * ut_user, ut_id, ut_line, ut_pid, ut_type, ut_exit, ut_time + */ + +/* ------------------------------------------------------------------------- */ + +/* + * make and write utmp and wtmp entries + */ +/* EXTPROTO */ +void +rxvt_makeutent(pR_ const char *pty, const char *hostname) +{ +#ifdef HAVE_STRUCT_UTMP + struct utmp *ut = &(R->h->ut); +#endif +#ifdef HAVE_STRUCT_UTMPX + struct utmpx *utx = &(R->h->utx); +#endif +#ifdef HAVE_UTMP_PID + int i; +#endif + char ut_id[5]; + struct passwd *pwent = getpwuid(getuid()); + + if (!STRNCMP(pty, "/dev/", 5)) + pty += 5; /* skip /dev/ prefix */ + + if (!STRNCMP(pty, "pty", 3) || !STRNCMP(pty, "tty", 3)) { + STRNCPY(ut_id, (pty + 3), sizeof(ut_id)); + } +#ifdef HAVE_UTMP_PID + else if (sscanf(pty, "pts/%d", &i) == 1) + sprintf(ut_id, "vt%02x", (i & 0xff)); /* sysv naming */ +#endif + else if (STRNCMP(pty, "pty", 3) && STRNCMP(pty, "tty", 3)) { + rxvt_print_error("can't parse tty name \"%s\"", pty); + return; + } + +#ifdef HAVE_STRUCT_UTMP + MEMSET(ut, 0, sizeof(struct utmp)); +# ifdef HAVE_UTMP_PID + setutent(); + STRNCPY(ut->ut_id, ut_id, sizeof(ut->ut_id)); + ut->ut_type = DEAD_PROCESS; + getutid(ut); /* position to entry in utmp file */ + STRNCPY(R->h->ut_id, ut_id, sizeof(R->h->ut_id)); +# endif +#endif + +#ifdef HAVE_STRUCT_UTMPX + MEMSET(utx, 0, sizeof(struct utmpx)); + setutxent(); + STRNCPY(utx->ut_id, ut_id, sizeof(utx->ut_id)); + utx->ut_type = DEAD_PROCESS; + getutxid(utx); /* position to entry in utmp file */ + STRNCPY(R->h->ut_id, ut_id, sizeof(R->h->ut_id)); +#endif + +#ifdef HAVE_STRUCT_UTMP + STRNCPY(ut->ut_line, pty, sizeof(ut->ut_line)); + ut->ut_time = time(NULL); +# ifdef HAVE_UTMP_PID + STRNCPY(ut->ut_user, (pwent && pwent->pw_name) ? pwent->pw_name : "?", + sizeof(ut->ut_user)); + STRNCPY(ut->ut_id, ut_id, sizeof(ut->ut_id)); + ut->ut_time = time(NULL); + ut->ut_pid = R->h->cmd_pid; +# ifdef HAVE_UTMP_HOST + STRNCPY(ut->ut_host, hostname, sizeof(ut->ut_host)); +# endif + ut->ut_type = USER_PROCESS; + pututline(ut); + endutent(); /* close the file */ + R->h->utmp_pos = 0; +# else + STRNCPY(ut->ut_name, (pwent && pwent->pw_name) ? pwent->pw_name : "?", + sizeof(ut->ut_name)); +# ifdef HAVE_UTMP_HOST + STRNCPY(ut->ut_host, hostname, sizeof(ut->ut_host)); +# endif +# endif +#endif + +#ifdef HAVE_STRUCT_UTMPX + STRNCPY(utx->ut_line, pty, sizeof(utx->ut_line)); + STRNCPY(utx->ut_user, (pwent && pwent->pw_name) ? pwent->pw_name : "?", + sizeof(utx->ut_user)); + STRNCPY(utx->ut_id, ut_id, sizeof(utx->ut_id)); + utx->ut_session = getsid(0); + utx->ut_tv.tv_sec = time(NULL); + utx->ut_tv.tv_usec = 0; + utx->ut_pid = R->h->cmd_pid; +# ifdef HAVE_UTMPX_HOST + STRNCPY(utx->ut_host, hostname, sizeof(utx->ut_host)); +# if 0 + { + char *colon; + + if ((colon = STRRCHR(ut->ut_host, ':')) != NULL) + *colon = '\0'; + } +# endif +# endif + utx->ut_type = USER_PROCESS; + pututxline(utx); + endutxent(); /* close the file */ + R->h->utmp_pos = 0; +#endif + +#if defined(HAVE_STRUCT_UTMP) && !defined(HAVE_UTMP_PID) + { + int i; +# ifdef HAVE_TTYSLOT + i = ttyslot(); + if (rxvt_write_bsd_utmp(i, ut)) + R->h->utmp_pos = i; +# else + FILE *fd0; + + if ((fd0 = fopen(TTYTAB_FILENAME, "r")) != NULL) { + char buf[256], name[256]; + + buf[sizeof(buf) - 1] = '\0'; + for (i = 1; (fgets(buf, sizeof(buf) - 1, fd0) != NULL);) { + if (*buf == '#' || sscanf(buf, "%s", name) != 1) + continue; + if (!STRCMP(ut->ut_line, name)) { + if (!rxvt_write_bsd_utmp(i, ut)) + i = 0; + R->h->utmp_pos = i; + fclose(fd0); + break; + } + i++; + } + fclose(fd0); + } +# endif + } +#endif + +#ifdef WTMP_SUPPORT +# ifdef WTMP_ONLY_ON_LOGIN + if (R->Options & Opt_loginShell) +# endif + { +# ifdef HAVE_STRUCT_UTMP +# ifdef HAVE_UPDWTMP + updwtmp(RXVT_WTMP_FILE, ut); +# else + rxvt_update_wtmp(RXVT_WTMP_FILE, ut); +# endif +# endif +# ifdef HAVE_STRUCT_UTMPX + updwtmpx(RXVT_WTMPX_FILE, utx); +# endif + } +#endif +#if defined(LASTLOG_SUPPORT) && defined(RXVT_LASTLOG_FILE) + if (R->Options & Opt_loginShell) + rxvt_update_lastlog(RXVT_LASTLOG_FILE, pty, hostname); +#endif +} + +/* ------------------------------------------------------------------------- */ +/* + * remove utmp and wtmp entries + */ +/* EXTPROTO */ +void +rxvt_cleanutent(pR) +{ +#ifdef HAVE_STRUCT_UTMP + struct utmp *ut = &(R->h->ut); +#endif +#ifdef HAVE_STRUCT_UTMPX + struct utmpx *tmputx, *utx = &(R->h->utx); +#endif + +#ifdef HAVE_STRUCT_UTMP +# ifdef HAVE_UTMP_PID + MEMSET(ut, 0, sizeof(struct utmp)); + setutent(); + STRNCPY(ut->ut_id, R->h->ut_id, sizeof(ut->ut_id)); + ut->ut_type = USER_PROCESS; + { + struct utmp *tmput = getutid(ut); + + if (tmput) /* position to entry in utmp file */ + ut = tmput; + } + ut->ut_type = DEAD_PROCESS; +# else + MEMSET(ut->ut_name, 0, sizeof(ut->ut_name)); +# ifdef HAVE_UTMP_HOST + MEMSET(ut->ut_host, 0, sizeof(ut->ut_host)); +# endif +# endif + ut->ut_time = time(NULL); +#endif + +#ifdef HAVE_STRUCT_UTMPX + MEMSET(utx, 0, sizeof(struct utmpx)); + setutxent(); + STRNCPY(utx->ut_id, R->h->ut_id, sizeof(utx->ut_id)); + utx->ut_type = USER_PROCESS; + if ((tmputx = getutxid(utx))) /* position to entry in utmp file */ + utx = tmputx; + utx->ut_type = DEAD_PROCESS; + utx->ut_session = getsid(0); + utx->ut_tv.tv_sec = time(NULL); + utx->ut_tv.tv_usec = 0; +#endif + + /* + * Write ending wtmp entry + */ +#ifdef WTMP_SUPPORT +# ifdef WTMP_ONLY_ON_LOGIN + if (R->Options & Opt_loginShell) +# endif + { +# ifdef HAVE_STRUCT_UTMP +# ifdef HAVE_UPDWTMP + updwtmp(RXVT_WTMP_FILE, ut); +# else + rxvt_update_wtmp(RXVT_WTMP_FILE, ut); +# endif +# endif +# ifdef HAVE_STRUCT_UTMPX + updwtmpx(RXVT_WTMPX_FILE, utx); +# endif + } +#endif + + /* + * Write utmp entry + */ +#ifdef HAVE_STRUCT_UTMP +# ifdef HAVE_UTMP_PID + if (ut->ut_pid == R->h->cmd_pid) + pututline(ut); + endutent(); +# else + MEMSET(ut, 0, sizeof(struct utmp)); + rxvt_write_bsd_utmp(R->h->utmp_pos, ut); +# endif +#endif +#ifdef HAVE_STRUCT_UTMPX + if (utx->ut_pid == R->h->cmd_pid) + pututxline(utx); + endutxent(); +#endif +} + +/* ------------------------------------------------------------------------- */ +/* + * Write a BSD style utmp entry + */ +#ifdef HAVE_UTMP_H +/* INTPROTO */ +int +rxvt_write_bsd_utmp(int utmp_pos, struct utmp *wu) +{ + int fd; + + if (utmp_pos <= 0 || (fd = open(RXVT_UTMP_FILE, O_WRONLY)) == -1) + return 0; + + if (lseek(fd, (off_t) (utmp_pos * sizeof(struct utmp)), SEEK_SET) != -1) + write(fd, wu, sizeof(struct utmp)); + close(fd); + return 1; +} +#endif + +/* ------------------------------------------------------------------------- */ +/* + * Update a BSD style wtmp entry + */ +#if defined(WTMP_SUPPORT) && !defined(HAVE_UPDWTMP) +/* INTPROTO */ +void +rxvt_update_wtmp(const char *fname, const struct utmp *putmp) +{ + int fd, gotlock, retry; + struct flock lck; /* fcntl locking scheme */ + struct stat sbuf; + + if ((fd = open(fname, O_WRONLY | O_APPEND, 0)) < 0) + return; + + lck.l_whence = SEEK_END; /* start lock at current eof */ + lck.l_len = 0; /* end at ``largest possible eof'' */ + lck.l_start = 0; + lck.l_type = F_WRLCK; /* we want a write lock */ + + /* attempt lock with F_SETLK; F_SETLKW would cause a deadlock! */ + for (retry = 10, gotlock = 0; retry--;) + if (fcntl(fd, F_SETLK, &lck) != -1) { + gotlock = 1; + break; + } else if (errno != EAGAIN && errno != EACCES) + break; + if (!gotlock) { /* give it up */ + close(fd); + return; + } + if (fstat(fd, &sbuf) == 0) + if (write(fd, putmp, sizeof(struct utmp)) != sizeof(struct utmp)) + ftruncate(fd, sbuf.st_size); /* remove bad writes */ + + lck.l_type = F_UNLCK; /* unlocking the file */ + fcntl(fd, F_SETLK, &lck); + close(fd); +} +#endif + +/* ------------------------------------------------------------------------- */ +#ifdef LASTLOG_SUPPORT +/* INTPROTO */ +void +rxvt_update_lastlog(const char *fname, const char *pty, const char *host) +{ +# ifdef HAVE_STRUCT_LASTLOGX + struct lastlogx llx; +# endif +# ifdef HAVE_STRUCT_LASTLOG + int fd; + struct lastlog ll; +# ifdef LASTLOG_IS_DIR + char lastlogfile[256]; +# endif + struct passwd *pwent; +# endif + +# ifdef HAVE_STRUCT_LASTLOGX + MEMSET(&llx, 0, sizeof(llx)); + llx.ll_tv.tv_sec = time(NULL); + llx.ll_tv.tv_usec = 0; + STRNCPY(llx.ll_line, pty, sizeof(llx.ll_line)); + STRNCPY(llx.ll_host, host, sizeof(llx.ll_host)); + updlastlogx(RXVT_LASTLOGX_FILE, getuid(), &llx); +# endif + +# ifdef HAVE_STRUCT_LASTLOG + pwent = getpwuid(getuid()); + if (!pwent) { + rxvt_print_error("no entry in password file"); + return; + } + MEMSET(&ll, 0, sizeof(ll)); + ll.ll_time = time(NULL); + STRNCPY(ll.ll_line, pty, sizeof(ll.ll_line)); + STRNCPY(ll.ll_host, host, sizeof(ll.ll_host)); +# ifdef LASTLOG_IS_DIR + sprintf(lastlogfile, "%.*s/%.*s", + sizeof(lastlogfile) - sizeof(pwent->pw_name) - 2, fname, + sizeof(pwent->pw_name), + (!pwent->pw_name || pwent->pw_name[0] == '\0') ? "unknown" + : pwent->pw_name); + if ((fd = open(lastlogfile, O_WRONLY | O_CREAT, 0644)) >= 0) { + write(fd, &ll, sizeof(ll)); + close(fd); + } +# else + if ((fd = open(fname, O_RDWR)) != -1) { + if (lseek(fd, (off_t) ((long)pwent->pw_uid * sizeof(ll)), + SEEK_SET) != -1) + write(fd, &ll, sizeof(ll)); + close(fd); + } +# endif /* LASTLOG_IS_DIR */ +# endif /* HAVE_STRUCT_LASTLOG */ +} +#endif /* LASTLOG_SUPPORT */ +/* ------------------------------------------------------------------------- */ + +#endif /* UTMP_SUPPORT */ diff --git a/src/logging.h b/src/logging.h new file mode 100644 index 00000000..0d408479 --- /dev/null +++ b/src/logging.h @@ -0,0 +1,34 @@ +/* + * $Id: logging.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#ifndef _LOGGING_H_ +#define _LOGGING_H_ + +#ifdef UTMP_SUPPORT +# if ! defined(HAVE_STRUCT_UTMPX) && ! defined(HAVE_STRUCT_UTMP) +# error cannot build with utmp support - no utmp or utmpx struct found +# endif + +# ifdef HAVE_LASTLOG_H +# include +# endif +# include + +# ifdef RXVT_UTMP_SYSV +# ifndef USER_PROCESS +# define USER_PROCESS 7 +# endif +# ifndef DEAD_PROCESS +# define DEAD_PROCESS 8 +# endif +# endif + +# ifdef __QNX__ +# include +# define ut_name ut_user +# endif + +#include "logging.intpro" /* PROTOS for internal routines */ +#endif +#endif /* _LOGGING_H_ */ diff --git a/src/main.C b/src/main.C new file mode 100644 index 00000000..b2830e65 --- /dev/null +++ b/src/main.C @@ -0,0 +1,1207 @@ +/*--------------------------------*-C-*---------------------------------* + * File: main.c + *----------------------------------------------------------------------* + * $Id: main.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1992 John Bovey, University of Kent at Canterbury + * - original version + * Copyright (c) 1994 Robert Nation + * - extensive modifications + * Copyright (c) 1995 Garrett D'Amore + * Copyright (c) 1997 mj olesen + * - extensive modifications + * Copyright (c) 1997,1998 Oezguer Kesim + * Copyright (c) 1998-2001 Geoff Wing + * - 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 + +#ifdef TTY_GID_SUPPORT +# include +#endif + +#ifdef HAVE_TERMIOS_H +# include +#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 + */ + +/* 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 + * reposition window on resize depending on placement on screen + */ + int x, y, x1, y1; + int dx, dy; + unsigned int unused_w1, unused_h1, unused_b1, unused_d1; + Window unused_cr; + + XTranslateCoordinates(R->Xdisplay, R->TermWin.parent[0], Xroot, + 0, 0, &x, &y, &unused_cr); + XGetGeometry(R->Xdisplay, R->TermWin.parent[0], &unused_cr, &x1, &y1, + &unused_w1, &unused_h1, &unused_b1, &unused_d1); + /* + * if Xroot isn't the parent window, a WM will probably have offset + * our position for handles and decorations. Counter it + */ + if (x1 != x || y1 != y) { + x -= x1; + y -= y1; + } + + x1 = (DisplayWidth(R->Xdisplay, Xscreen) - old_width) / 2; + y1 = (DisplayHeight(R->Xdisplay, Xscreen) - old_height) / 2; + dx = old_width - R->szHint.width; + dy = old_height - R->szHint.height; + + /* Check position of the center of the window */ + if (x < x1) /* left half */ + dx = 0; + else if (x == x1) /* exact center */ + dx /= 2; + if (y < y1) /* top half */ + dy = 0; + else if (y == y1) /* exact center */ + dy /= 2; + + XMoveResizeWindow(R->Xdisplay, R->TermWin.parent[0], x + dx, y + dy, + R->szHint.width, R->szHint.height); +#else + XResizeWindow(R->Xdisplay, R->TermWin.parent[0], R->szHint.width, + R->szHint.height); +#endif + } + + fix_screen = (R->TermWin.ncol != R->h->prev_ncol + || R->TermWin.nrow != R->h->prev_nrow); + if (fix_screen || width != R->h->old_width || height != R->h->old_height) { + if (scrollbar_visible(R)) { + XMoveResizeWindow(R->Xdisplay, R->scrollBar.win, R->h->window_sb_x, + 0, scrollbar_TotalWidth(), R->szHint.height); + rxvt_Resize_scrollBar(aR); + } + if (menubar_visible(R)) + XMoveResizeWindow(R->Xdisplay, R->menuBar.win, R->h->window_vt_x, + 0, TermWin_TotalWidth(), menuBar_TotalHeight()); + XMoveResizeWindow(R->Xdisplay, R->TermWin.vt, R->h->window_vt_x, + R->h->window_vt_y, TermWin_TotalWidth(), + TermWin_TotalHeight()); +#ifdef RXVT_GRAPHICS + if (R->h->old_height) + rxvt_Gr_Resize(aR_ R->h->old_width - R->szHint.base_width, + R->h->old_height - R->szHint.base_height); +#endif + rxvt_scr_clear(aR); +#ifdef XPM_BACKGROUND + rxvt_resize_pixmap(aR); +#endif + } + + if (fix_screen || R->h->old_height == 0) { + int curr_screen = -1; + uint16_t old_ncol = R->h->prev_ncol; + + /* scr_reset only works on the primary screen */ + if (R->h->old_height) /* this is not the first time through */ + curr_screen = rxvt_scr_change_screen(aR_ PRIMARY); + rxvt_scr_reset(aR); + if (curr_screen >= 0) { /* this is not the first time through */ + rxvt_scr_change_screen(aR_ curr_screen); + rxvt_selection_check(aR_ (old_ncol != R->TermWin.ncol ? 4 : 0)); + } + } + + R->h->old_width = R->szHint.width; + R->h->old_height = R->szHint.height; + +#ifdef USE_XIM + rxvt_IMSetStatusPosition(aR); +#endif +} + +/* + * Set the width/height of the vt window in characters. Units are pixels. + * good for toggling 80/132 columns + */ +/* EXTPROTO */ +void +rxvt_set_widthheight(pR_ unsigned int width, unsigned int height) +{ + XWindowAttributes wattr; + + if (width == 0 || height == 0) { + XGetWindowAttributes(R->Xdisplay, Xroot, &wattr); + if (width == 0) + width = wattr.width - R->szHint.base_width; + if (height == 0) + height = wattr.height - R->szHint.base_height; + } + if (width != R->TermWin.width || height != R->TermWin.height) { + width += R->szHint.base_width; + height += R->szHint.base_height; + rxvt_resize_all_windows(aR_ width, height, 0); + } +} + +/* -------------------------------------------------------------------- * + * - X INPUT METHOD ROUTINES - * + * -------------------------------------------------------------------- */ +#ifdef USE_XIM +/* INTPROTO */ +void +rxvt_setSize(pR_ XRectangle *size) +{ + size->x = R->TermWin.int_bwidth; + size->y = R->TermWin.int_bwidth; + size->width = Width2Pixel(R->TermWin.ncol); + size->height = Height2Pixel(R->TermWin.nrow); +} + +/* INTPROTO */ +void +rxvt_setColor(pR_ unsigned long *fg, unsigned long *bg) +{ + *fg = R->PixColors[Color_fg]; + *bg = R->PixColors[Color_bg]; +} + +/* Checking whether input method is running. */ +/* INTPROTO */ +Bool +rxvt_IMisRunning(pR) +{ + char *p; + Atom atom; + Window win; + char server[IMBUFSIZ]; + + /* get current locale modifier */ + if ((p = XSetLocaleModifiers(NULL)) != NULL) { + STRCPY(server, "@server="); + STRNCAT(server, &(p[4]), IMBUFSIZ - 9); /* skip "@im=" */ + if ((p = STRCHR(server + 1, '@')) != NULL) /* first one only */ + *p = '\0'; + + atom = XInternAtom(R->Xdisplay, server, False); + win = XGetSelectionOwner(R->Xdisplay, atom); + if (win != None) + return True; + } + return False; +} + +/* EXTPROTO */ +void +rxvt_IMSendSpot(pR) +{ + XPoint spot; + XVaNestedList preedit_attr; + + if (R->h->Input_Context == NULL + || !R->TermWin.focus + || !(R->h->input_style & XIMPreeditPosition) + || !(R->h->event_type == KeyPress + || R->h->event_type == Expose + || R->h->event_type == NoExpose + || R->h->event_type == SelectionNotify + || R->h->event_type == ButtonRelease + || R->h->event_type == FocusIn) + || !rxvt_IMisRunning(aR)) + return; + + rxvt_setPosition(aR_ &spot); + + preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); + XSetICValues(R->h->Input_Context, XNPreeditAttributes, preedit_attr, NULL); + XFree(preedit_attr); +} + +/* EXTPROTO */ +void +rxvt_setTermFontSet(pR_ int idx) +{ + char *string; + long length; + int success = 0; + + if (idx < 0 || idx >= MAX_NFONTS) + return; +} + +/* INTPROTO */ +void +rxvt_setPreeditArea(pR_ XRectangle *preedit_rect, XRectangle *status_rect, XRectangle *needed_rect) +{ + int mbh, vtx = 0; + + if (scrollbar_visible(R) && !(R->Options & Opt_scrollBar_right)) + vtx = scrollbar_TotalWidth(); + mbh = menubar_visible(R) ? menuBar_TotalHeight() : 0; + mbh -= R->TermWin.lineSpace; + + preedit_rect->x = needed_rect->width + vtx; + preedit_rect->y = Height2Pixel(R->TermWin.nrow - 1) + mbh; + + preedit_rect->width = Width2Pixel(R->TermWin.ncol + 1) - needed_rect->width + + vtx; + preedit_rect->height = Height2Pixel(1); + + status_rect->x = vtx; + status_rect->y = Height2Pixel(R->TermWin.nrow - 1) + mbh; + + status_rect->width = needed_rect->width ? needed_rect->width + : Width2Pixel(R->TermWin.ncol + 1); + status_rect->height = Height2Pixel(1); +} + +/* ARGSUSED */ +/* INTPROTO */ +void +rxvt_IMDestroyCallback(XIM xim __attribute__((unused)), XPointer client_data __attribute__((unused)), XPointer call_data __attribute__((unused))) +{ + dR; + + R->h->Input_Context = NULL; + /* To avoid Segmentation Fault in C locale: Solaris only? */ + if (STRCMP(R->h->locale, "C")) + XRegisterIMInstantiateCallback(R->Xdisplay, NULL, NULL, NULL, + rxvt_IMInstantiateCallback, NULL); +} + +/* + * X manual pages and include files don't match on some systems: + * some think this is an XIDProc and others an XIMProc so we can't + * use the first argument - need to update this to be nice for + * both types via some sort of configure detection + */ +/* ARGSUSED */ +/* EXTPROTO */ +void +rxvt_IMInstantiateCallback(Display *unused __attribute__((unused)), XPointer client_data __attribute__((unused)), XPointer call_data __attribute__((unused))) +{ + dR; + int i, found, had_im; + const char *p; + char **s; + char buf[IMBUFSIZ]; + + D_MAIN((stderr, "rxvt_IMInstantiateCallback()")); + if (R->h->Input_Context) + return; + + found = had_im = 0; + p = R->h->rs[Rs_inputMethod]; + if (p && *p) { + had_im = 1; + s = rxvt_splitcommastring(p); + for (i = 0; s[i]; i++) { + if (*s[i]) { + STRCPY(buf, "@im="); + STRNCAT(buf, s[i], IMBUFSIZ - 5); + if ((p = XSetLocaleModifiers(buf)) != NULL && *p + && (rxvt_IM_get_IC(aR) == True)) { + found = 1; + break; + } + } + } + for (i = 0; s[i]; i++) + free(s[i]); + free(s); + } + if (found) + return; + +/* try with XMODIFIERS env. var. */ + if ((p = XSetLocaleModifiers("")) != NULL && *p) { + rxvt_IM_get_IC(aR); + return; + } + +/* try with no modifiers base IF the user didn't specify an IM */ + if (!had_im && (p = XSetLocaleModifiers("@im=none")) != NULL && *p + && rxvt_IM_get_IC(aR) == True) + return; +} + +/* + * Try to open a XIM with the current modifiers, then see if we can + * open a suitable preedit type + */ +/* INTPROTO */ +Bool +rxvt_IM_get_IC(pR) +{ + int i, j, found; + XIM xim; + XPoint spot; + XRectangle rect, status_rect, needed_rect; + unsigned long fg, bg; + const char *p; + char **s; + XIMStyles *xim_styles; + XVaNestedList preedit_attr, status_attr; + XIMCallback ximcallback; + struct rxvt_hidden *h = R->h; + + D_MAIN((stderr, "rxvt_IM_get_IC()")); + xim = XOpenIM(R->Xdisplay, NULL, NULL, NULL); + if (xim == NULL) + return False; + + xim_styles = NULL; + if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) + || !xim_styles || !xim_styles->count_styles) { + XCloseIM(xim); + return False; + } + + p = h->rs[Rs_preeditType] ? h->rs[Rs_preeditType] + : "OverTheSpot,OffTheSpot,Root"; + s = rxvt_splitcommastring(p); + for (i = found = 0; !found && s[i]; i++) { + if (!STRCMP(s[i], "OverTheSpot")) + h->input_style = (XIMPreeditPosition | XIMStatusNothing); + else if (!STRCMP(s[i], "OffTheSpot")) + h->input_style = (XIMPreeditArea | XIMStatusArea); + else if (!STRCMP(s[i], "Root")) + h->input_style = (XIMPreeditNothing | XIMStatusNothing); + + for (j = 0; j < xim_styles->count_styles; j++) + if (h->input_style == xim_styles->supported_styles[j]) { + found = 1; + break; + } + } + for (i = 0; s[i]; i++) + free(s[i]); + free(s); + XFree(xim_styles); + + if (!found) { + XCloseIM(xim); + return False; + } + + ximcallback.callback = rxvt_IMDestroyCallback; + + /* XXX: not sure why we need this (as well as IC one below) */ + XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL); + + preedit_attr = status_attr = NULL; + + if (h->input_style & XIMPreeditPosition) { + rxvt_setSize(aR_ &rect); + rxvt_setPosition(aR_ &spot); + rxvt_setColor(aR_ &fg, &bg); + + preedit_attr = XVaCreateNestedList(0, XNArea, &rect, + XNSpotLocation, &spot, + XNForeground, fg, + XNBackground, bg, + //XNFontSet, R->TermWin.fontset, + NULL); + } else if (h->input_style & XIMPreeditArea) { + rxvt_setColor(aR_ &fg, &bg); + + /* + * The necessary width of preedit area is unknown + * until create input context. + */ + needed_rect.width = 0; + + rxvt_setPreeditArea(aR_ &rect, &status_rect, &needed_rect); + + preedit_attr = XVaCreateNestedList(0, XNArea, &rect, + XNForeground, fg, + XNBackground, bg, + //XNFontSet, R->TermWin.fontset, + NULL); + status_attr = XVaCreateNestedList(0, XNArea, &status_rect, + XNForeground, fg, + XNBackground, bg, + //XNFontSet, R->TermWin.fontset, + NULL); + } + h->Input_Context = XCreateIC(xim, XNInputStyle, h->input_style, + XNClientWindow, R->TermWin.parent[0], + XNFocusWindow, R->TermWin.parent[0], + XNDestroyCallback, &ximcallback, + preedit_attr ? XNPreeditAttributes : NULL, + preedit_attr, + status_attr ? XNStatusAttributes : NULL, + status_attr, NULL); + if (preedit_attr) + XFree(preedit_attr); + if (status_attr) + XFree(status_attr); + if (h->Input_Context == NULL) { + rxvt_print_error("failed to create input context"); + XCloseIM(xim); + return False; + } + if (h->input_style & XIMPreeditArea) + rxvt_IMSetStatusPosition(aR); + D_MAIN((stderr, "rxvt_IM_get_IC() - successful connection")); + return True; +} + +/* EXTPROTO */ +void +rxvt_IMSetStatusPosition(pR) +{ + XRectangle preedit_rect, status_rect, *needed_rect; + XVaNestedList preedit_attr, status_attr; + + if (R->h->Input_Context == NULL + || !R->TermWin.focus + || !(R->h->input_style & XIMPreeditArea) + || !rxvt_IMisRunning(aR)) + return; + + /* Getting the necessary width of preedit area */ + status_attr = XVaCreateNestedList(0, XNAreaNeeded, &needed_rect, NULL); + XGetICValues(R->h->Input_Context, XNStatusAttributes, status_attr, NULL); + XFree(status_attr); + + rxvt_setPreeditArea(aR_ &preedit_rect, &status_rect, needed_rect); + + preedit_attr = XVaCreateNestedList(0, XNArea, &preedit_rect, NULL); + status_attr = XVaCreateNestedList(0, XNArea, &status_rect, NULL); + + XSetICValues(R->h->Input_Context, + XNPreeditAttributes, preedit_attr, + XNStatusAttributes, status_attr, NULL); + + XFree(preedit_attr); + XFree(status_attr); +} +#endif /* USE_XIM */ + +/*----------------------------------------------------------------------*/ +rxvt_t *rxvt_current_term; + +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/makeextprotos-sed b/src/makeextprotos-sed new file mode 100644 index 00000000..69b6685d --- /dev/null +++ b/src/makeextprotos-sed @@ -0,0 +1,18 @@ +# Get prototypes from a .c file +# $Id: makeextprotos-sed,v 1.1 2003-11-24 17:28:08 pcg Exp $ +# /* EXTPROTO */ must be above return type which are above function. +# Args are on one line +# eg. +# /* EXTPROTO */ +# void ------> void main(int argc, char **argv); +# main(int argc, char **argv) +# { +# } +# +/^[/][*] EXTPROTO [*][/]$/{ +n +N +s/\n\([_a-zA-Z][_a-zA-Z0-9]* *\)(/ \1 __PROTO((/ +s/$/);/ +p +} diff --git a/src/makeintprotos-sed b/src/makeintprotos-sed new file mode 100644 index 00000000..e2abaeee --- /dev/null +++ b/src/makeintprotos-sed @@ -0,0 +1,18 @@ +# Get prototypes from a .c file +# $Id: makeintprotos-sed,v 1.1 2003-11-24 17:28:08 pcg Exp $ +# /* INTPROTO */ must be above return type which are above function. +# Args are on one line +# eg. +# /* INTPROTO */ +# void ------> void main(int argc, char **argv); +# main(int argc, char **argv) +# { +# } +# +/^[/][*] INTPROTO [*][/]$/{ +n +N +s/\n\([_a-zA-Z][_a-zA-Z0-9]* *\)(/ \1 __PROTO((/ +s/$/);/ +p +} diff --git a/src/menubar.C b/src/menubar.C new file mode 100644 index 00000000..775a278c --- /dev/null +++ b/src/menubar.C @@ -0,0 +1,2252 @@ +/*--------------------------------*-C-*---------------------------------* + * File: menubar.c + *----------------------------------------------------------------------* + * $Id: menubar.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Copyright (c) 1997,1998 mj olesen + * + * 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, "(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, "(len %d) = %.*s\n", + cur->len, cur->len, (cur->str ? cur->str : "")); +#endif + + xtra_len = (beg.len + end.len); + for (i = 0; i < NARROWS; i++) { + if (xtra_len || parse[i].len) + rxvt_menuarrow_free(aR_ Arrows[i].name); + } + + for (i = 0; i < NARROWS; i++) { + unsigned char *str; + unsigned int len; + + if (!parse[i].len) + continue; + + str = rxvt_malloc(parse[i].len + xtra_len + 1); + + len = 0; + if (beg.len) { + STRNCPY(str + len, beg.str, beg.len); + len += beg.len; + } + STRNCPY(str + len, parse[i].str, parse[i].len); + len += parse[i].len; + + if (end.len) { + STRNCPY(str + len, end.str, end.len); + len += end.len; + } + str[len] = '\0'; + +#ifdef DEBUG_MENUARROWS + fprintf(stderr, "<%c>(len %d) = %s\n", Arrows[i].name, len, str); +#endif + if (rxvt_action_type(&(R->h->CurrentBar->arrows[i]), str) < 0) + free(str); + } +} + +/* INTPROTO */ +menuitem_t * +rxvt_menuitem_add(menu_t *menu, const char *name, const char *name2, const char *action) +{ + menuitem_t *item; + unsigned int len; + +#ifdef DEBUG_STRICT + assert(name != NULL); + assert(action != NULL); +#endif + + if (menu == NULL) + return NULL; + + if (isSeparator(name)) { + /* add separator, no action */ + name = ""; + action = ""; + } else { + /* + * add/replace existing menu item + */ + item = rxvt_menuitem_find(menu, name); + if (item != NULL) { + if (item->name2 != NULL && name2 != NULL) { + free(item->name2); + item->len2 = 0; + item->name2 = NULL; + } + switch (item->entry.type) { + case MenuAction: + case MenuTerminalAction: + free(item->entry.action.str); + item->entry.action.str = NULL; + break; + } + goto Item_Found; + } + } +/* allocate a new itemect */ + item = (menuitem_t *) rxvt_malloc(sizeof(menuitem_t)); + + item->len2 = 0; + item->name2 = NULL; + + len = STRLEN(name); + item->name = rxvt_malloc(len + 1); + STRCPY(item->name, name); + if (name[0] == '.' && name[1] != '.') + len = 0; /* hidden menu name */ + item->len = len; + +/* add to tail of list */ + item->prev = menu->tail; + item->next = NULL; + + if (menu->tail != NULL) + (menu->tail)->next = item; + menu->tail = item; +/* fix head */ + if (menu->head == NULL) + menu->head = item; + +/* + * add action + */ + Item_Found: + if (name2 != NULL && item->name2 == NULL) { + len = STRLEN(name2); + if (len == 0) + item->name2 = NULL; + else { + item->name2 = rxvt_malloc(len + 1); + STRCPY(item->name2, name2); + } + item->len2 = len; + } + item->entry.type = MenuLabel; + len = STRLEN(action); + + if (len == 0 && item->name2 != NULL) { + action = item->name2; + len = item->len2; + } + if (len) { + unsigned char *str = rxvt_malloc(len + 1); + + STRCPY(str, action); + + if (rxvt_action_type(&(item->entry.action), str) < 0) + free(str); + } +/* new item and a possible increase in width */ + if (menu->width < (item->len + item->len2)) + menu->width = (item->len + item->len2); + + return item; +} + +/* + * search for the base starting menu for NAME. + * return a pointer to the portion of NAME that remains + */ +/* INTPROTO */ +char * +rxvt_menu_find_base(pR_ menu_t **menu, char *path) +{ + menu_t *m = NULL; + menuitem_t *item; + +#ifdef DEBUG_STRICT + assert(menu != NULL); + assert(R->h->CurrentBar != NULL); +#endif + + if (path[0] == '\0') + return path; + + if (STRCHR(path, '/') != NULL) { + char *p = path; + + while ((p = STRCHR(p, '/')) != NULL) { + p++; + if (*p == '/') + path = p; + } + if (path[0] == '/') { + path++; + *menu = NULL; + } + while ((p = STRCHR(path, '/')) != NULL) { + p[0] = '\0'; + if (path[0] == '\0') + return NULL; + if (!STRCMP(path, DOT)) { + /* nothing to do */ + } else if (!STRCMP(path, DOTS)) { + if (*menu != NULL) + *menu = (*menu)->parent; + } else { + path = rxvt_menu_find_base(aR_ menu, path); + if (path[0] != '\0') { /* not found */ + p[0] = '/'; /* fix-up name again */ + return path; + } + } + + path = (p + 1); + } + } + if (!STRCMP(path, DOTS)) { + path += STRLEN(DOTS); + if (*menu != NULL) + *menu = (*menu)->parent; + return path; + } +/* find this menu */ + if (*menu == NULL) { + for (m = R->h->CurrentBar->tail; m != NULL; m = m->prev) { + if (!STRCMP(path, m->name)) + break; + } + } else { + /* find this menu */ + for (item = (*menu)->tail; item != NULL; item = item->prev) { + if (item->entry.type == MenuSubMenu + && !STRCMP(path, (item->entry.submenu.menu)->name)) { + m = (item->entry.submenu.menu); + break; + } + } + } + if (m != NULL) { + *menu = m; + path += STRLEN(path); + } + return path; +} + +/* + * delete this entire menu + */ +/* INTPROTO */ +menu_t * +rxvt_menu_delete(pR_ menu_t *menu) +{ + menu_t *parent = NULL, *prev, *next; + menuitem_t *item; + bar_t *CurrentBar = R->h->CurrentBar; + +#ifdef DEBUG_STRICT + assert(CurrentBar != NULL); +#endif + +/* delete the entire menu */ + if (menu == NULL) + return NULL; + + parent = menu->parent; + +/* unlink MENU */ + prev = menu->prev; + next = menu->next; + if (prev != NULL) + prev->next = next; + if (next != NULL) + next->prev = prev; + +/* fix the index */ + if (parent == NULL) { + const int len = (menu->len + HSPACE); + + if (CurrentBar->tail == menu) + CurrentBar->tail = prev; + if (CurrentBar->head == menu) + CurrentBar->head = next; + + for (next = menu->next; next != NULL; next = next->next) + next->x -= len; + } else { + for (item = parent->tail; item != NULL; item = item->prev) { + if (item->entry.type == MenuSubMenu + && item->entry.submenu.menu == menu) { + item->entry.submenu.menu = NULL; + rxvt_menuitem_free(aR_ menu->parent, item); + break; + } + } + } + + item = menu->tail; + while (item != NULL) { + menuitem_t *p = item->prev; + + rxvt_menuitem_free(aR_ menu, item); + item = p; + } + + if (menu->name != NULL) + free(menu->name); + free(menu); + + return parent; +} + +/* INTPROTO */ +menu_t * +rxvt_menu_add(pR_ menu_t *parent, char *path) +{ + menu_t *menu; + bar_t *CurrentBar = R->h->CurrentBar; + +#ifdef DEBUG_STRICT + assert(CurrentBar != NULL); +#endif + + if (STRCHR(path, '/') != NULL) { + char *p; + + if (path[0] == '/') { + /* shouldn't happen */ + path++; + parent = NULL; + } + while ((p = STRCHR(path, '/')) != NULL) { + p[0] = '\0'; + if (path[0] == '\0') + return NULL; + + parent = rxvt_menu_add(aR_ parent, path); + path = (p + 1); + } + } + if (!STRCMP(path, DOTS)) + return (parent != NULL ? parent->parent : parent); + + if (!STRCMP(path, DOT) || path[0] == '\0') + return parent; + +/* allocate a new menu */ + menu = (menu_t *) rxvt_malloc(sizeof(menu_t)); + + menu->width = 0; + menu->parent = parent; + menu->len = STRLEN(path); + menu->name = rxvt_malloc((menu->len + 1)); + STRCPY(menu->name, path); + +/* initialize head/tail */ + menu->head = menu->tail = NULL; + menu->prev = menu->next = NULL; + + menu->win = None; + menu->x = menu->y = menu->w = menu->h = 0; + menu->item = NULL; + +/* add to tail of list */ + if (parent == NULL) { + menu->prev = CurrentBar->tail; + if (CurrentBar->tail != NULL) + CurrentBar->tail->next = menu; + CurrentBar->tail = menu; + if (CurrentBar->head == NULL) + CurrentBar->head = menu; /* fix head */ + if (menu->prev) + menu->x = (menu->prev->x + menu->prev->len + HSPACE); + } else { + menuitem_t *item; + + item = rxvt_menuitem_add(parent, path, "", ""); + if (item == NULL) { + free(menu); + return parent; + } +#ifdef DEBUG_STRICT + assert(item->entry.type == MenuLabel); +#endif + item->entry.type = MenuSubMenu; + item->entry.submenu.menu = menu; + } + + return menu; +} + +/* INTPROTO */ +void +rxvt_drawbox_menubar(pR_ int x, int len, int state) +{ + GC top, bot; + + x = Width2Pixel(x); + len = Width2Pixel(len + HSPACE); + if (x >= R->TermWin.width) + return; + else if (x + len >= R->TermWin.width) + len = (TermWin_TotalWidth() - x); + +#ifdef MENUBAR_SHADOW_IN + state = -state; +#endif + switch (state) { + case +1: + top = R->h->topShadowGC; + bot = R->h->botShadowGC; + break; /* SHADOW_OUT */ + case -1: + top = R->h->botShadowGC; + bot = R->h->topShadowGC; + break; /* SHADOW_IN */ + default: + top = bot = R->h->scrollbarGC; + break; /* neutral */ + } + + rxvt_Draw_Shadow(R->Xdisplay, R->menuBar.win, top, bot, + x, 0, len, menuBar_TotalHeight()); +} + +/* INTPROTO */ +void +rxvt_drawtriangle(pR_ int x, int y, int state) +{ + GC top, bot; + int w; + +#ifdef MENU_SHADOW_IN + state = -state; +#endif + switch (state) { + case +1: + top = R->h->topShadowGC; + bot = R->h->botShadowGC; + break; /* SHADOW_OUT */ + case -1: + top = R->h->botShadowGC; + bot = R->h->topShadowGC; + break; /* SHADOW_IN */ + default: + top = bot = R->h->scrollbarGC; + break; /* neutral */ + } + + w = Height2Pixel(1) - 2 * SHADOW; + + x -= SHADOW + (3 * w / 2); + y += SHADOW * 3; + + rxvt_Draw_Triangle(R->Xdisplay, R->h->ActiveMenu->win, top, bot, x, y, w, + 'r'); +} + +/* INTPROTO */ +void +rxvt_drawbox_menuitem(pR_ int y, int state) +{ + GC top, bot; + +#ifdef MENU_SHADOW_IN + state = -state; +#endif + switch (state) { + case +1: + top = R->h->topShadowGC; + bot = R->h->botShadowGC; + break; /* SHADOW_OUT */ + case -1: + top = R->h->botShadowGC; + bot = R->h->topShadowGC; + break; /* SHADOW_IN */ + default: + top = bot = R->h->scrollbarGC; + break; /* neutral */ + } + + rxvt_Draw_Shadow(R->Xdisplay, R->h->ActiveMenu->win, top, bot, + SHADOW + 0, SHADOW + y, + R->h->ActiveMenu->w - 2 * (SHADOW), + HEIGHT_TEXT + 2 * SHADOW); + XFlush(R->Xdisplay); +} + +#ifdef DEBUG_MENU_LAYOUT +/* INTPROTO */ +void +rxvt_print_menu_ancestors(menu_t *menu) +{ + if (menu == NULL) { + fprintf(stderr, "Top Level menu\n"); + return; + } + fprintf(stderr, "menu %s ", menu->name); + if (menu->parent != NULL) { + menuitem_t *item; + + for (item = menu->parent->head; item != NULL; item = item->next) { + if (item->entry.type == MenuSubMenu + && item->entry.submenu.menu == menu) { + break; + } + } + if (item == NULL) { + fprintf(stderr, "is an orphan!\n"); + return; + } + } + fprintf(stderr, "\n"); + rxvt_print_menu_ancestors(menu->parent); +} + +/* INTPROTO */ +void +rxvt_print_menu_descendants(menu_t *menu) +{ + menuitem_t *item; + menu_t *parent; + int i, level = 0; + + parent = menu; + do { + level++; + parent = parent->parent; + } + while (parent != NULL); + + for (i = 0; i < level; i++) + fprintf(stderr, ">"); + fprintf(stderr, "%s\n", menu->name); + + for (item = menu->head; item != NULL; item = item->next) { + if (item->entry.type == MenuSubMenu) { + if (item->entry.submenu.menu == NULL) + fprintf(stderr, "> %s == NULL\n", item->name); + else + rxvt_print_menu_descendants(item->entry.submenu.menu); + } else { + for (i = 0; i < level; i++) + fprintf(stderr, "+"); + if (item->entry.type == MenuLabel) + fprintf(stderr, "label: "); + fprintf(stderr, "%s\n", item->name); + } + } + + for (i = 0; i < level; i++) + fprintf(stderr, "<"); + fprintf(stderr, "\n"); +} +#endif + +/* pop up/down the current menu and redraw the menuBar button */ +/* INTPROTO */ +void +rxvt_menu_show(pR) +{ + int x, y, xright; + menu_t *ActiveMenu = R->h->ActiveMenu; + menuitem_t *item; + + if (ActiveMenu == NULL) + return; + + x = ActiveMenu->x; + if (ActiveMenu->parent == NULL) { + register int h; + + rxvt_drawbox_menubar(aR_ x, ActiveMenu->len, -1); + x = Width2Pixel(x); + + ActiveMenu->y = 1; + ActiveMenu->w = Menu_PixelWidth(ActiveMenu); + + if ((x + ActiveMenu->w) >= R->TermWin.width) + x = (TermWin_TotalWidth() - ActiveMenu->w); + + /* find the height */ + for (h = 0, item = ActiveMenu->head; item != NULL; item = item->next) + h += isSeparator(item->name) ? HEIGHT_SEPARATOR + : HEIGHT_TEXT + 2 * SHADOW; + ActiveMenu->h = h + 2 * SHADOW; + } + if (ActiveMenu->win == None) { + ActiveMenu->win = XCreateSimpleWindow(R->Xdisplay, R->TermWin.vt, + x, ActiveMenu->y, + ActiveMenu->w, ActiveMenu->h, + 0, + R->PixColors[Color_fg], + R->PixColors[Color_scroll]); + XMapWindow(R->Xdisplay, ActiveMenu->win); + } + rxvt_Draw_Shadow(R->Xdisplay, ActiveMenu->win, + R->h->topShadowGC, R->h->botShadowGC, + 0, 0, ActiveMenu->w, ActiveMenu->h); + +/* determine the correct right-alignment */ + for (xright = 0, item = ActiveMenu->head; item != NULL; item = item->next) + if (item->len2 > xright) + xright = item->len2; + + for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { + const int xoff = (SHADOW + Width2Pixel(HSPACE) / 2); + register int h; + GC gc = R->h->menubarGC; + + if (isSeparator(item->name)) { + rxvt_Draw_Shadow(R->Xdisplay, ActiveMenu->win, + R->h->topShadowGC, R->h->botShadowGC, + SHADOW, y + SHADOW + 1, + ActiveMenu->w - 2 * SHADOW, 0); + h = HEIGHT_SEPARATOR; + } else { + char *name = item->name; + int len = item->len; + + if (item->entry.type == MenuLabel) { + gc = R->h->botShadowGC; + } else if (item->entry.type == MenuSubMenu) { + int x1, y1; + menuitem_t *it; + menu_t *menu = item->entry.submenu.menu; + + rxvt_drawtriangle(aR_ ActiveMenu->w, y, +1); + + name = menu->name; + len = menu->len; + + y1 = ActiveMenu->y + y; + + menu->w = Menu_PixelWidth(menu); + + /* place sub-menu at midpoint of parent menu */ + x1 = ActiveMenu->w / 2; + if (x1 > menu->w) /* right-flush menu if too small */ + x1 += (x1 - menu->w); + x1 += x; + + /* find the height of this submenu */ + for (h = 0, it = menu->head; it != NULL; it = it->next) + h += isSeparator(it->name) ? HEIGHT_SEPARATOR + : HEIGHT_TEXT + 2 * SHADOW; + menu->h = h + 2 * SHADOW; + + /* ensure menu is in window limits */ + if ((x1 + menu->w) >= R->TermWin.width) + x1 = (TermWin_TotalWidth() - menu->w); + + if ((y1 + menu->h) >= R->TermWin.height) + y1 = (TermWin_TotalHeight() - menu->h); + + menu->x = (x1 < 0 ? 0 : x1); + menu->y = (y1 < 0 ? 0 : y1); + } else if (item->name2 && !STRCMP(name, item->name2)) + name = NULL; + + if (len && name) { +#ifdef USE_XIM + if (R->TermWin.fontset) + XmbDrawString(R->Xdisplay, + ActiveMenu->win, R->TermWin.fontset, + gc, xoff, + 2 * SHADOW + y + R->TermWin.font->ascent + 1, + name, len); + else +#endif + XDrawString(R->Xdisplay, ActiveMenu->win, gc, xoff, + 2 * SHADOW + y + R->TermWin.font->ascent + 1, + name, len); + } + + len = item->len2; + name = item->name2; + if (len && name) { +#ifdef USE_XIM + if (R->TermWin.fontset) + XmbDrawString(R->Xdisplay, + ActiveMenu->win, R->TermWin.fontset, + gc, + ActiveMenu->w - (xoff + Width2Pixel(xright)), + 2 * SHADOW + y + R->TermWin.font->ascent + 1, + name, len); + else +#endif + XDrawString(R->Xdisplay, ActiveMenu->win, gc, + ActiveMenu->w - (xoff + Width2Pixel(xright)), + 2 * SHADOW + y + R->TermWin.font->ascent + 1, + name, len); + } + h = HEIGHT_TEXT + 2 * SHADOW; + } + y += h; + } +} + +/* INTPROTO */ +void +rxvt_menu_display(pR_ void (*update)(rxvt_t *)) +{ + menu_t *ActiveMenu = R->h->ActiveMenu; + + if (ActiveMenu == NULL) + return; + if (ActiveMenu->win != None) + XDestroyWindow(R->Xdisplay, ActiveMenu->win); + ActiveMenu->win = None; + ActiveMenu->item = NULL; + + if (ActiveMenu->parent == NULL) + rxvt_drawbox_menubar(aR_ ActiveMenu->x, ActiveMenu->len, +1); + R->h->ActiveMenu = ActiveMenu->parent; + update(r); +} + +/* INTPROTO */ +void +rxvt_menu_hide_all(pR) +{ + rxvt_menu_display(aR_ rxvt_menu_hide_all); +} + +/* INTPROTO */ +void +rxvt_menu_hide(pR) +{ + rxvt_menu_display(aR_ rxvt_menu_show); +} + +/* INTPROTO */ +void +rxvt_menu_clear(pR_ menu_t *menu) +{ + if (menu != NULL) { + menuitem_t *item = menu->tail; + + while (item != NULL) { + rxvt_menuitem_free(aR_ menu, item); + /* it didn't get freed ... why? */ + if (item == menu->tail) + return; + item = menu->tail; + } + menu->width = 0; + } +} + +/* INTPROTO */ +void +rxvt_menubar_clear(pR) +{ + bar_t *CurrentBar = R->h->CurrentBar; + + if (CurrentBar != NULL) { + menu_t *menu = CurrentBar->tail; + + while (menu != NULL) { + menu_t *prev = menu->prev; + + rxvt_menu_delete(aR_ menu); + menu = prev; + } + CurrentBar->head = CurrentBar->tail = NULL; + + if (CurrentBar->title) { + free(CurrentBar->title); + CurrentBar->title = NULL; + } + rxvt_menuarrow_free(aR_ 0); /* remove all arrow functions */ + } + R->h->ActiveMenu = NULL; +} + +#if (MENUBAR_MAX > 1) +/* find if menu already exists */ +/* INTPROTO */ +bar_t * +rxvt_menubar_find(pR_ const char *name) +{ + bar_t *bar = R->h->CurrentBar; + +#ifdef DEBUG_MENUBAR_STACKING + fprintf(stderr, "looking for [menu:%s] ...", name ? name : "(nil)"); +#endif + if (bar == NULL || name == NULL) + return NULL; + + if (STRLEN(name) && STRCMP(name, "*")) { + do { + if (!STRCMP(bar->name, name)) { +#ifdef DEBUG_MENUBAR_STACKING + fprintf(stderr, " found!\n"); +#endif + return bar; + } + bar = bar->next; + } + while (bar != R->h->CurrentBar); + bar = NULL; + } +#ifdef DEBUG_MENUBAR_STACKING + fprintf(stderr, "%s found!\n", (bar ? "" : " NOT")); +#endif + + return bar; +} + +/* INTPROTO */ +int +rxvt_menubar_push(pR_ const char *name) +{ + int ret = 1; + bar_t *bar; + + if (R->h->CurrentBar == NULL) { + /* allocate first one */ + bar = (bar_t *) rxvt_malloc(sizeof(bar_t)); + + MEMSET(bar, 0, sizeof(bar_t)); + /* circular linked-list */ + bar->next = bar->prev = bar; + bar->head = bar->tail = NULL; + bar->title = NULL; + R->h->CurrentBar = bar; + R->h->Nbars++; + + rxvt_menubar_clear(aR); + } else { + /* find if menu already exists */ + bar = rxvt_menubar_find(aR_ name); + if (bar != NULL) { + /* found it, use it */ + R->h->CurrentBar = bar; + } else { + /* create if needed, or reuse the existing empty menubar */ + if (R->h->CurrentBar->head != NULL) { + /* need to malloc another one */ + if (R->h->Nbars < MENUBAR_MAX) + bar = (bar_t *) rxvt_malloc(sizeof(bar_t)); + else + bar = NULL; + + /* malloc failed or too many menubars, reuse another */ + if (bar == NULL) { + bar = R->h->CurrentBar->next; + ret = -1; + } else { + bar->head = bar->tail = NULL; + bar->title = NULL; + + bar->next = R->h->CurrentBar->next; + R->h->CurrentBar->next = bar; + bar->prev = R->h->CurrentBar; + bar->next->prev = bar; + + R->h->Nbars++; + } + R->h->CurrentBar = bar; + + } + rxvt_menubar_clear(aR); + } + } + +/* give menubar this name */ + STRNCPY(R->h->CurrentBar->name, name, MAXNAME); + R->h->CurrentBar->name[MAXNAME - 1] = '\0'; + + return ret; +} + +/* switch to a menu called NAME and remove it */ +/* INTPROTO */ +void +rxvt_menubar_remove(pR_ const char *name) +{ + bar_t *bar; + + if ((bar = rxvt_menubar_find(aR_ name)) == NULL) + return; + R->h->CurrentBar = bar; + + do { + rxvt_menubar_clear(aR); + /* + * pop a menubar, clean it up first + */ + if (R->h->CurrentBar != NULL) { + bar_t *prev = R->h->CurrentBar->prev; + bar_t *next = R->h->CurrentBar->next; + + if (prev == next && prev == R->h->CurrentBar) { /* only 1 left */ + prev = NULL; + R->h->Nbars = 0; /* safety */ + } else { + next->prev = prev; + prev->next = next; + R->h->Nbars--; + } + + free(R->h->CurrentBar); + R->h->CurrentBar = prev; + } + } + while (R->h->CurrentBar && !STRCMP(name, "*")); +} + +/* INTPROTO */ +void +rxvt_action_decode(FILE *fp, action_t *act) +{ + unsigned char *str; + short len; + + if (act == NULL || (len = act->len) == 0 || (str = act->str) == NULL) + return; + + if (act->type == MenuTerminalAction) { + fprintf(fp, "^@"); + /* can strip trailing ^G from XTerm sequence */ + if (str[0] == C0_ESC && str[1] == ']' && str[len - 1] == C0_BEL) + len--; + } else if (str[0] == C0_ESC) { + switch (str[1]) { + case '[': + case ']': + break; + + case 'x': + /* can strip trailing '\r' from M-x sequence */ + if (str[len - 1] == '\r') + len--; + /* FALLTHROUGH */ + + default: + fprintf(fp, "M-"); /* meta prefix */ + str++; + len--; + break; + } + } +/* + * control character form is preferred, since backslash-escaping + * can be really ugly looking when the backslashes themselves also + * have to be escaped to avoid Shell (or whatever scripting + * language) interpretation + */ + while (len > 0) { + unsigned char ch = *str++; + + switch (ch) { + case C0_ESC: + fprintf(fp, "\\E"); + break; /* escape */ + case '\r': + fprintf(fp, "\\r"); + break; /* carriage-return */ + case '\\': + fprintf(fp, "\\\\"); + break; /* backslash */ + case '^': + fprintf(fp, "\\^"); + break; /* caret */ + case 127: + fprintf(fp, "^?"); + default: + if (ch <= 31) + fprintf(fp, "^%c", ('@' + ch)); + else if (ch > 127) + fprintf(fp, "\\%o", ch); + else + fprintf(fp, "%c", ch); + break; + } + len--; + } + fprintf(fp, "\n"); +} + +/* INTPROTO */ +void +rxvt_menu_dump(FILE *fp, menu_t *menu) +{ + menuitem_t *item; + +/* create a new menu and clear it */ + fprintf(fp, (menu->parent ? "./%s/*\n" : "/%s/*\n"), menu->name); + + for (item = menu->head; item != NULL; item = item->next) { + switch (item->entry.type) { + case MenuSubMenu: + if (item->entry.submenu.menu == NULL) + fprintf(fp, "> %s == NULL\n", item->name); + else + rxvt_menu_dump(fp, item->entry.submenu.menu); + break; + + case MenuLabel: + fprintf(fp, "{%s}\n", (STRLEN(item->name) ? item->name : "-")); + break; + + case MenuTerminalAction: + case MenuAction: + fprintf(fp, "{%s}", item->name); + if (item->name2 != NULL && STRLEN(item->name2)) + fprintf(fp, "{%s}", item->name2); + fprintf(fp, "\t"); + rxvt_action_decode(fp, &(item->entry.action)); + break; + } + } + + fprintf(fp, (menu->parent ? "../\n" : "/\n\n")); +} + +/* INTPROTO */ +void +rxvt_menubar_dump(pR_ FILE *fp) +{ + bar_t *bar = R->h->CurrentBar; + time_t t; + + if (bar == NULL || fp == NULL) + return; + time(&t); + + fprintf(fp, + "# " APL_SUBCLASS " (%s) Pid: %u\n# Date: %s\n\n", + R->h->rs[Rs_name], (unsigned int)getpid(), ctime(&t)); + +/* dump in reverse order */ + bar = R->h->CurrentBar->prev; + do { + menu_t *menu; + int i; + + fprintf(fp, "[menu:%s]\n", bar->name); + + if (bar->title != NULL) + fprintf(fp, "[title:%s]\n", bar->title); + + for (i = 0; i < NARROWS; i++) { + switch (bar->arrows[i].type) { + case MenuTerminalAction: + case MenuAction: + fprintf(fp, "<%c>", Arrows[i].name); + rxvt_action_decode(fp, &(bar->arrows[i])); + break; + } + } + fprintf(fp, "\n"); + + for (menu = bar->head; menu != NULL; menu = menu->next) + rxvt_menu_dump(fp, menu); + + fprintf(fp, "\n[done:%s]\n\n", bar->name); + bar = bar->prev; + } + while (bar != R->h->CurrentBar->prev); +} +#endif /* (MENUBAR_MAX > 1) */ + +/* + * read in menubar commands from FILENAME + * ignore all input before the tag line [menu] or [menu:???] + * + * Note that since File_find () is used, FILENAME can be semi-colon + * delimited such that the second part can refer to a tag + * so that a large `database' of menus can be collected together + * + * FILENAME = "file" + * FILENAME = "file;" + * read `file' starting with first [menu] or [menu:???] line + * + * FILENAME = "file;tag" + * read `file' starting with [menu:tag] + */ +/* EXTPROTO */ +void +rxvt_menubar_read(pR_ const char *filename) +{ +/* read in a menu from a file */ + FILE *fp; + char buffer[256]; + char *p, *file, *tag = NULL; + + file = (char *)rxvt_File_find(filename, ".menu", R->h->rs[Rs_path]); + if (file == NULL) + return; + fp = fopen(file, "rb"); + free(file); + if (fp == NULL) + return; + +#if (MENUBAR_MAX > 1) +/* semi-colon delimited */ + if ((tag = STRCHR(filename, ';')) != NULL) { + tag++; + if (*tag == '\0') + tag = NULL; + } +#endif /* (MENUBAR_MAX > 1) */ +#ifdef DEBUG_MENU + fprintf(stderr, "[read:%s]\n", p); + if (tag) + fprintf(stderr, "looking for [menu:%s]\n", tag); +#endif + + while ((p = fgets(buffer, sizeof(buffer), fp)) != NULL) { + int n; + + if ((n = rxvt_Str_match(p, "[menu")) != 0) { + if (tag) { + /* looking for [menu:tag] */ + if (p[n] == ':' && p[n + 1] != ']') { + n++; + n += rxvt_Str_match(p + n, tag); + if (p[n] == ']') { +#ifdef DEBUG_MENU + fprintf(stderr, "[menu:%s]\n", tag); +#endif + break; + } + } + } else if (p[n] == ':' || p[n] == ']') + break; + } + } + +/* found [menu], [menu:???] tag */ + while (p != NULL) { + int n; + +#ifdef DEBUG_MENU + fprintf(stderr, "read line = %s\n", p); +#endif + + /* looking for [done:tag] or [done:] */ + if ((n = rxvt_Str_match(p, "[done")) != 0) { + if (p[n] == ']') { + R->h->menu_readonly = 1; + break; + } else if (p[n] == ':') { + n++; + if (p[n] == ']') { + R->h->menu_readonly = 1; + break; + } else if (tag) { + n += rxvt_Str_match(p + n, tag); + if (p[n] == ']') { +#ifdef DEBUG_MENU + fprintf(stderr, "[done:%s]\n", tag); +#endif + R->h->menu_readonly = 1; + break; + } + } else { + /* what? ... skip this line */ + p[0] = COMMENT_CHAR; + } + } + } + /* + * remove leading/trailing space + * and strip-off leading/trailing quotes + * skip blank or comment lines + */ + rxvt_Str_trim(p); + if (*p && *p != '#') { + R->h->menu_readonly = 0; /* if case we read another file */ + rxvt_menubar_dispatch(aR_ p); + } + /* get another line */ + p = fgets(buffer, sizeof(buffer), fp); + } + + fclose(fp); +} + +/* + * user interface for building/deleting and otherwise managing menus + */ +/* EXTPROTO */ +void +rxvt_menubar_dispatch(pR_ char *str) +{ + int n, cmd; + char *path, *name, *name2; + + if (menubar_visible(r) && R->h->ActiveMenu != NULL) + rxvt_menubar_expose(aR); + else + R->h->ActiveMenu = NULL; + + cmd = *str; + switch (cmd) { + case '.': + case '/': /* absolute & relative path */ + case MENUITEM_BEG: /* menuitem */ + /* add `+' prefix for these cases */ + cmd = '+'; + break; + + case '+': + case '-': + str++; /* skip cmd character */ + break; + + case '<': +#if (MENUBAR_MAX > 1) + if (R->h->CurrentBar == NULL) + break; +#endif /* (MENUBAR_MAX > 1) */ + if (str[1] && str[2] == '>') /* arrow commands */ + rxvt_menuarrow_add(aR_ str); + break; + + case '[': /* extended command */ + while (str[0] == '[') { + char *next = (++str); /* skip leading '[' */ + + if (str[0] == ':') { /* [:command:] */ + do { + next++; + if ((next = STRCHR(next, ':')) == NULL) + return; /* parse error */ + } + while (next[1] != ']'); + /* remove and skip ':]' */ + *next = '\0'; + next += 2; + } else { + if ((next = STRCHR(next, ']')) == NULL) + return; /* parse error */ + /* remove and skip ']' */ + *next = '\0'; + next++; + } + + if (str[0] == ':') { + int saved; + + /* try and dispatch it, regardless of read/write status */ + saved = R->h->menu_readonly; + R->h->menu_readonly = 0; + rxvt_menubar_dispatch(aR_ str + 1); + R->h->menu_readonly = saved; + } + /* these ones don't require menu stacking */ + else if (!STRCMP(str, "clear")) { + rxvt_menubar_clear(aR); + } else if (!STRCMP(str, "done") || rxvt_Str_match(str, "done:")) { + R->h->menu_readonly = 1; + } else if (!STRCMP(str, "show")) { + rxvt_map_menuBar(aR_ 1); + R->h->menu_readonly = 1; + } else if (!STRCMP(str, "hide")) { + rxvt_map_menuBar(aR_ 0); + R->h->menu_readonly = 1; + } else if ((n = rxvt_Str_match(str, "read:")) != 0) { + /* read in a menu from a file */ + str += n; + rxvt_menubar_read(aR_ str); + } else if ((n = rxvt_Str_match(str, "title:")) != 0) { + str += n; + if (R->h->CurrentBar != NULL && !R->h->menu_readonly) { + if (*str) { + name = rxvt_realloc(R->h->CurrentBar->title, + STRLEN(str) + 1); + if (name != NULL) { + STRCPY(name, str); + R->h->CurrentBar->title = name; + } + rxvt_menubar_expose(aR); + } else { + free(R->h->CurrentBar->title); + R->h->CurrentBar->title = NULL; + } + } + } else if ((n = rxvt_Str_match(str, "pixmap:")) != 0) { + str += n; + rxvt_xterm_seq(aR_ XTerm_Pixmap, str, CHAR_ST); + } +#if (MENUBAR_MAX > 1) + else if ((n = rxvt_Str_match(str, "rm")) != 0) { + str += n; + switch (str[0]) { + case ':': + str++; + /* FALLTHROUGH */ + case '\0': + /* FALLTHROUGH */ + case '*': + rxvt_menubar_remove(aR_ str); + break; + } + R->h->menu_readonly = 1; + } else if ((n = rxvt_Str_match(str, "menu")) != 0) { + str += n; + switch (str[0]) { + case ':': + str++; + /* add/access menuBar */ + if (*str != '\0' && *str != '*') + rxvt_menubar_push(aR_ str); + break; + default: + if (R->h->CurrentBar == NULL) { + rxvt_menubar_push(aR_ "default"); + } + } + + if (R->h->CurrentBar != NULL) + R->h->menu_readonly = 0; /* allow menu build commands */ + } else if (!STRCMP(str, "dump")) { + /* dump current menubars to a file */ + FILE *fp; + + /* enough space to hold the results */ + char buffer[32]; + + sprintf(buffer, "/tmp/" APL_SUBCLASS "-%u", + (unsigned int)getpid()); + + if ((fp = fopen(buffer, "wb")) != NULL) { + rxvt_xterm_seq(aR_ XTerm_title, buffer, CHAR_ST); + rxvt_menubar_dump(aR_ fp); + fclose(fp); + } + } else if (!STRCMP(str, "next")) { + if (R->h->CurrentBar) { + R->h->CurrentBar = R->h->CurrentBar->next; + R->h->menu_readonly = 1; + } + } else if (!STRCMP(str, "prev")) { + if (R->h->CurrentBar) { + R->h->CurrentBar = R->h->CurrentBar->prev; + R->h->menu_readonly = 1; + } + } else if (!STRCMP(str, "swap")) { + /* swap the top 2 menus */ + if (R->h->CurrentBar) { + bar_t *cbprev = R->h->CurrentBar->prev; + bar_t *cbnext = R->h->CurrentBar->next; + + cbprev->next = cbnext; + cbnext->prev = cbprev; + + R->h->CurrentBar->next = cbprev; + R->h->CurrentBar->prev = cbprev->prev; + + cbprev->prev->next = R->h->CurrentBar; + cbprev->prev = R->h->CurrentBar; + + R->h->CurrentBar = cbprev; + R->h->menu_readonly = 1; + } + } +#endif /* (MENUBAR_MAX > 1) */ + str = next; + + R->h->BuildMenu = R->h->ActiveMenu = NULL; + rxvt_menubar_expose(aR); +#ifdef DEBUG_MENUBAR_STACKING + fprintf(stderr, "menus are read%s\n", + R->h->menu_readonly ? "only" : "/write"); +#endif + } + return; + break; + } + +#if (MENUBAR_MAX > 1) + if (R->h->CurrentBar == NULL) + return; + if (R->h->menu_readonly) { +#ifdef DEBUG_MENUBAR_STACKING + fprintf(stderr, "menus are read%s\n", + R->h->menu_readonly ? "only" : "/write"); +#endif + return; + } +#endif /* (MENUBAR_MAX > 1) */ + + switch (cmd) { + case '+': + case '-': + path = name = str; + + name2 = NULL; + /* parse STR, allow spaces inside (name) */ + if (path[0] != '\0') { + name = STRCHR(path, MENUITEM_BEG); + str = STRCHR(path, MENUITEM_END); + if (name != NULL || str != NULL) { + if (name == NULL || str == NULL || str <= (name + 1) + || (name > path && name[-1] != '/')) { + rxvt_print_error("menu error <%s>\n", path); + break; + } + if (str[1] == MENUITEM_BEG) { + name2 = (str + 2); + str = STRCHR(name2, MENUITEM_END); + + if (str == NULL) { + rxvt_print_error("menu error <%s>\n", path); + break; + } + name2[-2] = '\0'; /* remove prev MENUITEM_END */ + } + if (name > path && name[-1] == '/') + name[-1] = '\0'; + + *name++ = '\0'; /* delimit */ + *str++ = '\0'; /* delimit */ + + while (isspace(*str)) + str++; /* skip space */ + } +#ifdef DEBUG_MENU + fprintf(stderr, + "`%c' path = <%s>, name = <%s>, name2 = <%s>, action = <%s>\n", + cmd, (path ? path : "(nil)"), (name ? name : "(nil)"), + (name2 ? name2 : "(nil)"), (str ? str : "(nil)") + ); +#endif + } + /* process the different commands */ + switch (cmd) { + case '+': /* add/replace existing menu or menuitem */ + if (path[0] != '\0') { + int len; + + path = rxvt_menu_find_base(aR_ &(R->h->BuildMenu), path); + len = STRLEN(path); + + /* don't allow menus called `*' */ + if (path[0] == '*') { + rxvt_menu_clear(aR_ R->h->BuildMenu); + break; + } else if (len >= 2 && !STRCMP((path + len - 2), "/*")) { + path[len - 2] = '\0'; + } + if (path[0] != '\0') + R->h->BuildMenu = rxvt_menu_add(aR_ R->h->BuildMenu, path); + } + if (name != NULL && name[0] != '\0') + rxvt_menuitem_add(R->h->BuildMenu, + (STRCMP(name, SEPARATOR_NAME) ? name : ""), + name2, str); + break; + + case '-': /* delete menu entry */ + if (!STRCMP(path, "/*") && (name == NULL || name[0] == '\0')) { + rxvt_menubar_clear(aR); + R->h->BuildMenu = NULL; + rxvt_menubar_expose(aR); + break; + } else if (path[0] != '\0') { + int len; + menu_t *menu = R->h->BuildMenu; + + path = rxvt_menu_find_base(aR_ &menu, path); + len = STRLEN(path); + + /* submenu called `*' clears all menu items */ + if (path[0] == '*') { + rxvt_menu_clear(aR_ menu); + break; /* done */ + } else if (len >= 2 && !STRCMP(&path[len - 2], "/*")) { + /* done */ + break; + } else if (path[0] != '\0') { + R->h->BuildMenu = NULL; + break; + } else + R->h->BuildMenu = menu; + } + if (R->h->BuildMenu != NULL) { + if (name == NULL || name[0] == '\0') + R->h->BuildMenu = rxvt_menu_delete(aR_ R->h->BuildMenu); + else { + const char *n1; + menuitem_t *item; + menu_t *BuildMenu = R->h->BuildMenu; + + n1 = STRCMP(name, SEPARATOR_NAME) ? name : ""; + item = rxvt_menuitem_find(BuildMenu, n1); + if (item != NULL && item->entry.type != MenuSubMenu) { + rxvt_menuitem_free(aR_ BuildMenu, item); + + /* fix up the width */ + BuildMenu->width = 0; + for (item = BuildMenu->head; item != NULL; + item = item->next) { + short l = item->len + item->len2; + + MAX_IT(BuildMenu->width, l); + } + } + } + rxvt_menubar_expose(aR); + } + break; + } + break; + } +} + +/* INTPROTO */ +void +rxvt_draw_Arrows(pR_ int name, int state) +{ + GC top, bot; + + int i; + +#ifdef MENU_SHADOW_IN + state = -state; +#endif + switch (state) { + case +1: + top = R->h->topShadowGC; + bot = R->h->botShadowGC; + break; /* SHADOW_OUT */ + case -1: + top = R->h->botShadowGC; + bot = R->h->topShadowGC; + break; /* SHADOW_IN */ + default: + top = bot = R->h->scrollbarGC; + break; /* neutral */ + } + + if (!R->h->Arrows_x) + return; + + for (i = 0; i < NARROWS; i++) { + const int w = Width2Pixel(1); + const int y = (menuBar_TotalHeight() - w) / 2; + int x = R->h->Arrows_x + (5 * Width2Pixel(i)) / 4; + + if (!name || name == Arrows[i].name) + rxvt_Draw_Triangle(R->Xdisplay, R->menuBar.win, top, bot, x, y, w, + Arrows[i].name); + } + XFlush(R->Xdisplay); +} + +/* EXTPROTO */ +void +rxvt_menubar_expose(pR) +{ + menu_t *menu; + int x; + + if (!menubar_visible(r) || R->menuBar.win == 0) + return; + + if (R->h->menubarGC == None) { + /* Create the graphics context */ + XGCValues gcvalue; + + gcvalue.font = R->TermWin.font->fid; + + gcvalue.foreground = (XDEPTH <= 2 ? R->PixColors[Color_fg] + : R->PixColors[Color_Black]); + R->h->menubarGC = XCreateGC(R->Xdisplay, R->menuBar.win, + GCForeground | GCFont, &gcvalue); + + } +/* make sure the font is correct */ + XSetFont(R->Xdisplay, R->h->menubarGC, R->TermWin.font->fid); + XSetFont(R->Xdisplay, R->h->botShadowGC, R->TermWin.font->fid); + XClearWindow(R->Xdisplay, R->menuBar.win); + + rxvt_menu_hide_all(aR); + + x = 0; + if (R->h->CurrentBar != NULL) { + for (menu = R->h->CurrentBar->head; menu != NULL; menu = menu->next) { + int len = menu->len; + + x = (menu->x + menu->len + HSPACE); + +#ifdef DEBUG_MENU_LAYOUT + rxvt_print_menu_descendants(menu); +#endif + + if (x >= R->TermWin.ncol) + len = (R->TermWin.ncol - (menu->x + HSPACE)); + + rxvt_drawbox_menubar(aR_ menu->x, len, +1); +#ifdef USE_XIM + if (R->TermWin.fontset) + XmbDrawString(R->Xdisplay, + R->menuBar.win, R->TermWin.fontset, + R->h->menubarGC, + (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2), + menuBar_height() - SHADOW, menu->name, len); + else +#endif + XDrawString(R->Xdisplay, R->menuBar.win, R->h->menubarGC, + (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2), + menuBar_height() - SHADOW, menu->name, len); + + if (x >= R->TermWin.ncol) + break; + } + } + rxvt_drawbox_menubar(aR_ x, R->TermWin.ncol, (R->h->CurrentBar ? +1 : -1)); + +/* add the menuBar title, if it exists and there's plenty of room */ + R->h->Arrows_x = 0; + if (x < R->TermWin.ncol) { + const char *str; + int ncol; + unsigned int len; + char title[256]; + + ncol = (int)R->TermWin.ncol; + if (x < (ncol - (NARROWS + 1))) { + ncol -= (NARROWS + 1); + R->h->Arrows_x = Width2Pixel(ncol); + } + rxvt_draw_Arrows(aR_ 0, +1); + + str = (R->h->CurrentBar + && R->h->CurrentBar->title) ? R->h->CurrentBar->title : "%n-%v"; + for (len = 0; str[0] && len < sizeof(title) - 1; str++) { + const char *s = NULL; + + switch (str[0]) { + case '%': + str++; + switch (str[0]) { + case 'n': + s = R->h->rs[Rs_name]; + break; /* resource name */ + case 'v': + s = VERSION; + break; /* version number */ + case '%': + s = "%"; + break; /* literal '%' */ + } + if (s != NULL) + while (*s && len < sizeof(title) - 1) + title[len++] = *s++; + break; + + default: + title[len++] = str[0]; + break; + } + } + title[len] = '\0'; + + ncol -= (x + len + HSPACE); + if (len > 0 && ncol >= 0) { +#ifdef USE_XIM + if (R->TermWin.fontset) + XmbDrawString(R->Xdisplay, + R->menuBar.win, R->TermWin.fontset, + R->h->menubarGC, + Width2Pixel(x) + Width2Pixel(ncol + HSPACE) / 2, + menuBar_height() - SHADOW, title, len); + else +#endif + XDrawString(R->Xdisplay, R->menuBar.win, R->h->menubarGC, + Width2Pixel(x) + Width2Pixel(ncol + HSPACE) / 2, + menuBar_height() - SHADOW, title, len); + } + } +} + +/* INTPROTO */ +int +rxvt_menubar_mapping(pR_ int map) +{ + int change = 0; + + if (map && !menubar_visible(r)) { + R->menuBar.state = 1; + if (R->menuBar.win == 0) + return 0; + XMapWindow(R->Xdisplay, R->menuBar.win); + change = 1; + } else if (!map && menubar_visible(r)) { + rxvt_menubar_expose(aR); + R->menuBar.state = 0; + XUnmapWindow(R->Xdisplay, R->menuBar.win); + change = 1; + } else + rxvt_menubar_expose(aR); + + return change; +} + +/* INTPROTO */ +int +rxvt_menu_select(pR_ XButtonEvent *ev) +{ + menuitem_t *thisitem, *item = NULL; + int this_y, y; + menu_t *ActiveMenu = R->h->ActiveMenu; + + Window unused_root, unused_child; + int unused_root_x, unused_root_y; + unsigned int unused_mask; + + if (ActiveMenu == NULL) + return 0; + + XQueryPointer(R->Xdisplay, ActiveMenu->win, + &unused_root, &unused_child, + &unused_root_x, &unused_root_y, + &(ev->x), &(ev->y), &unused_mask); + + if (ActiveMenu->parent != NULL && (ev->x < 0 || ev->y < 0)) { + rxvt_menu_hide(aR); + return 1; + } +/* determine the menu item corresponding to the Y index */ + y = SHADOW; + if (ev->x >= 0 && ev->x <= (ActiveMenu->w - SHADOW)) { + for (item = ActiveMenu->head; item != NULL; item = item->next) { + int h = HEIGHT_TEXT + 2 * SHADOW; + + if (isSeparator(item->name)) + h = HEIGHT_SEPARATOR; + else if (ev->y >= y && ev->y < (y + h)) + break; + y += h; + } + } + if (item == NULL && ev->type == ButtonRelease) { + rxvt_menu_hide_all(aR); + return 0; + } + thisitem = item; + this_y = y - SHADOW; + +/* erase the last item */ + if (ActiveMenu->item != NULL) { + if (ActiveMenu->item != thisitem) { + for (y = 0, item = ActiveMenu->head; item != NULL; + item = item->next) { + int h; + + if (isSeparator(item->name)) + h = HEIGHT_SEPARATOR; + else if (item == ActiveMenu->item) { + /* erase old menuitem */ + rxvt_drawbox_menuitem(aR_ y, 0); /* No Shadow */ + if (item->entry.type == MenuSubMenu) + rxvt_drawtriangle(aR_ ActiveMenu->w, y, +1); + break; + } else + h = HEIGHT_TEXT + 2 * SHADOW; + y += h; + } + } else { + switch (ev->type) { + case ButtonRelease: + switch (item->entry.type) { + case MenuLabel: + case MenuSubMenu: + rxvt_menu_hide_all(aR); + break; + + case MenuAction: + case MenuTerminalAction: + rxvt_drawbox_menuitem(aR_ this_y, -1); + { +#ifdef HAVE_NANOSLEEP + struct timespec rqt; + + rqt.tv_sec = 0; + rqt.tv_nsec = MENU_DELAY_USEC * 1000; + nanosleep(&rqt, NULL); +#else + /* use select for timing */ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = MENU_DELAY_USEC; + select(0, NULL, NULL, NULL, &tv); +#endif + } + /* remove menu before sending keys to the application */ + rxvt_menu_hide_all(aR); +#ifndef DEBUG_MENU + rxvt_action_dispatch(aR_ &(item->entry.action)); +#else /* DEBUG_MENU */ + fprintf(stderr, "%s: %s\n", item->name, + item->entry.action.str); +#endif /* DEBUG_MENU */ + break; + } + break; + + default: + if (item->entry.type == MenuSubMenu) + goto DoMenu; + break; + } + return 0; + } + } + DoMenu: + ActiveMenu->item = thisitem; + y = this_y; + if (thisitem != NULL) { + item = ActiveMenu->item; + if (item->entry.type != MenuLabel) + rxvt_drawbox_menuitem(aR_ y, +1); + if (item->entry.type == MenuSubMenu) { + int x; + + rxvt_drawtriangle(aR_ ActiveMenu->w, y, -1); + + x = ev->x + (ActiveMenu->parent + ? ActiveMenu->x + : Width2Pixel(ActiveMenu->x)); + + if (x >= item->entry.submenu.menu->x) { + R->h->ActiveMenu = item->entry.submenu.menu; + rxvt_menu_show(aR); + return 1; + } + } + } + return 0; +} + +/* INTPROTO */ +void +rxvt_menubar_select(pR_ XButtonEvent *ev) +{ + menu_t *menu = NULL; + +/* determine the pulldown menu corresponding to the X index */ + if (ev->y >= 0 && ev->y <= menuBar_height() && R->h->CurrentBar != NULL) { + for (menu = R->h->CurrentBar->head; menu != NULL; menu = menu->next) { + int x = Width2Pixel(menu->x); + int w = Width2Pixel(menu->len + HSPACE); + + if ((ev->x >= x && ev->x < x + w)) + break; + } + } + switch (ev->type) { + case ButtonRelease: + rxvt_menu_hide_all(aR); + break; + + case ButtonPress: + if (menu == NULL && R->h->Arrows_x && ev->x >= R->h->Arrows_x) { + int i; + + for (i = 0; i < NARROWS; i++) { + if (ev->x >= (R->h->Arrows_x + (Width2Pixel(4 * i + i)) / 4) + && ev->x < (R->h->Arrows_x + + (Width2Pixel(4 * i + i + 4)) / 4)) { + rxvt_draw_Arrows(aR_ Arrows[i].name, -1); + { +#ifdef HAVE_NANOSLEEP + struct timespec rqt; + + rqt.tv_sec = 0; + rqt.tv_nsec = MENU_DELAY_USEC * 1000; + nanosleep(&rqt, NULL); +#else + /* use select for timing */ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = MENU_DELAY_USEC; + select(0, NULL, NULL, NULL, &tv); +#endif + } + rxvt_draw_Arrows(aR_ Arrows[i].name, +1); +#ifdef DEBUG_MENUARROWS + fprintf(stderr, "'%c': ", Arrows[i].name); + + if (R->h->CurrentBar == NULL + || (R->h->CurrentBar->arrows[i].type != MenuAction + && R->h->CurrentBar->arrows[i].type != + MenuTerminalAction)) { + if (Arrows[i].str != NULL && Arrows[i].str[0]) + fprintf(stderr, "(default) \\033%s\n", + &(Arrows[i].str[2])); + } else { + fprintf(stderr, "%s\n", + R->h->CurrentBar->arrows[i].str); + } +#else /* DEBUG_MENUARROWS */ + if (R->h->CurrentBar == NULL + || rxvt_action_dispatch(r, + &(R->h->CurrentBar->arrows[i])) + ) { + if (Arrows[i].str != NULL && Arrows[i].str[0] != 0) + rxvt_tt_write(aR_ (Arrows[i].str + 1), + Arrows[i].str[0]); + } +#endif /* DEBUG_MENUARROWS */ + return; + } + } + } + /* FALLTHROUGH */ + + default: + /* + * press menubar or move to a new entry + */ + if (menu != NULL && menu != R->h->ActiveMenu) { + rxvt_menu_hide_all(aR); /* pop down old menu */ + R->h->ActiveMenu = menu; + rxvt_menu_show(aR); /* pop up new menu */ + } + break; + } +} + +/* + * general dispatch routine, + * it would be nice to have `sticky' menus + */ +/* EXTPROTO */ +void +rxvt_menubar_control(pR_ XButtonEvent *ev) +{ + switch (ev->type) { + case ButtonPress: + if (ev->button == Button1) + rxvt_menubar_select(aR_ ev); + break; + + case ButtonRelease: + if (ev->button == Button1) + rxvt_menu_select(aR_ ev); + break; + + case MotionNotify: + while (XCheckTypedWindowEvent(R->Xdisplay, R->TermWin.parent[0], + MotionNotify, (XEvent *) ev)) ; + + if (R->h->ActiveMenu) + while (rxvt_menu_select(aR_ ev)) ; + else + ev->y = -1; + if (ev->y < 0) { + Window unused_root, unused_child; + int unused_root_x, unused_root_y; + unsigned int unused_mask; + + XQueryPointer(R->Xdisplay, R->menuBar.win, + &unused_root, &unused_child, + &unused_root_x, &unused_root_y, + &(ev->x), &(ev->y), &unused_mask); + rxvt_menubar_select(aR_ ev); + } + break; + } +} + +/* EXTPROTO */ +void +rxvt_map_menuBar(pR_ int map) +{ + if (rxvt_menubar_mapping(aR_ map)) + rxvt_resize_all_windows(aR_ 0, 0, 0); +} +#endif +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/menubar.h b/src/menubar.h new file mode 100644 index 00000000..e496ccd6 --- /dev/null +++ b/src/menubar.h @@ -0,0 +1,88 @@ +/* + * $Id: menubar.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#ifndef _MENUBAR_H_ +#define _MENUBAR_H_ + +typedef struct { + short type; /* must not be changed; first element */ + short len; /* strlen (str) */ + unsigned char *str; /* action to take */ +} action_t; + +typedef struct { + short type; /* must not be changed; first element */ + struct menu_t *menu; /* sub-menu */ +} submenu_t; + +typedef struct menuitem_t { + struct menuitem_t *prev; /* prev menu-item */ + struct menuitem_t *next; /* next menu-item */ + char *name; /* character string displayed */ + char *name2; /* character string displayed (right) */ + short len; /* strlen (name) */ + short len2; /* strlen (name) */ + union { + short type; /* must not be changed; first element */ + action_t action; + submenu_t submenu; + } entry; +} menuitem_t; + +enum menuitem_t_action { + MenuLabel, + MenuAction, + MenuTerminalAction, + MenuSubMenu +}; + +typedef struct menu_t { + struct menu_t *parent; /* parent menu */ + struct menu_t *prev; /* prev menu */ + struct menu_t *next; /* next menu */ + menuitem_t *head; /* double-linked list */ + menuitem_t *tail; /* double-linked list */ + menuitem_t *item; /* current item */ + char *name; /* menu name */ + short len; /* strlen (name) */ + short width; /* maximum menu width [chars] */ + Window win; /* window of the menu */ + short x; /* x location [pixels] (chars if parent == NULL) */ + short y; /* y location [pixels] */ + short w, h; /* window width, height [pixels] */ +} menu_t; + +typedef struct bar_t { + menu_t *head, *tail; /* double-linked list of menus */ + char *title; /* title to put in the empty menuBar */ +#if (MENUBAR_MAX > 1) +# define MAXNAME 16 + char name[MAXNAME]; /* name to use to refer to menubar */ + struct bar_t *next, *prev; /* circular linked-list */ +#endif /* (MENUBAR_MAX > 1) */ +#define NARROWS 4 + action_t arrows[NARROWS]; +} bar_t; + +/* #define DEBUG_MENU */ +/* #define DEBUG_MENU_LAYOUT */ +/* #define DEBUG_MENUBAR_STACKING */ + +#define HSPACE 1 /* one space */ +#define isSeparator(name) ((name)[0] == '\0') +#define HEIGHT_SEPARATOR (SHADOW + 1) +#define HEIGHT_TEXT (Height2Pixel(1) + 2) + +#define MENU_DELAY_USEC 250000 /* 1/4 sec */ + + +#define SEPARATOR_NAME "-" +#define MENUITEM_BEG '{' +#define MENUITEM_END '}' +#define COMMENT_CHAR '#' + +#define DOT "." +#define DOTS ".." + +#endif /* _MENUBAR_H_ */ diff --git a/src/misc.C b/src/misc.C new file mode 100644 index 00000000..ad8b87d2 --- /dev/null +++ b/src/misc.C @@ -0,0 +1,406 @@ +/*--------------------------------*-C-*---------------------------------* + * File: misc.c + *----------------------------------------------------------------------* + * $Id: misc.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1996 mj olesen Queen's Univ at Kingston + * Copyright (c) 1997,1998 Oezguer Kesim + * Copyright (c) 1998-2000 Geoff Wing + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *----------------------------------------------------------------------*/ + +#include "../config.h" /* NECESSARY */ +#include "rxvt.h" /* NECESSARY */ +#include "misc.intpro" /* PROTOS for internal routines */ + +/* EXTPROTO */ +char * +rxvt_r_basename(const char *str) +{ + char *base = STRRCHR(str, '/'); + + return (char *)(base ? base + 1 : str); +} + +/* + * Print an error message + */ +/* EXTPROTO */ +void +rxvt_print_error(const char *fmt,...) +{ + va_list arg_ptr; + + va_start(arg_ptr, fmt); + fprintf(stderr, APL_NAME ": "); + vfprintf(stderr, fmt, arg_ptr); + fprintf(stderr, "\n"); + va_end(arg_ptr); +} + +/* + * check that the first characters of S1 match S2 + * + * No Match + * return: 0 + * Match + * return: STRLEN (S2) + */ +/* EXTPROTO */ +int +rxvt_Str_match(const char *s1, const char *s2) +{ + int n = STRLEN(s2); + + return ((STRNCMP(s1, s2, n) == 0) ? n : 0); +} + +/* EXTPROTO */ +const char * +rxvt_Str_skip_space(const char *str) +{ + if (str) + while (*str && isspace(*str)) + str++; + return str; +} + +/* + * remove leading/trailing space and strip-off leading/trailing quotes. + * in place. + */ +/* EXTPROTO */ +char * +rxvt_Str_trim(char *str) +{ + char *r, *s; + int n; + + if (!str || !*str) /* shortcut */ + return str; + +/* skip leading spaces */ + for (s = str; *s && isspace(*s); s++) ; +/* goto end of string */ + for (n = 0, r = s; *r++; n++) ; + r -= 2; +/* dump return */ + if (n > 0 && *r == '\n') + n--, r--; +/* backtrack along trailing spaces */ + for (; n > 0 && isspace(*r); r--, n--) ; +/* skip matching leading/trailing quotes */ + if (*s == '"' && *r == '"' && n > 1) { + s++; + n -= 2; + } +/* copy back over: forwards copy */ + for (r = str; n; n--) + *r++ = *s++; + *r = '\0'; + + return str; +} + +/* + * in-place interpretation of string: + * + * backslash-escaped: "\a\b\E\e\n\r\t", "\octal" + * Ctrl chars: ^@ .. ^_, ^? + * + * Emacs-style: "M-" prefix + * + * Also, + * "M-x" prefixed strings, append "\r" if needed + * "\E]" prefixed strings (XTerm escape sequence) append ST if needed + * + * returns the converted string length + */ +/* EXTPROTO */ +int +rxvt_Str_escaped(char *str) +{ + char ch, *s, *d; + int i, num, append = 0; + + if (!str || !*str) + return 0; + + d = s = str; + + if (*s == 'M' && s[1] == '-') { + /* Emacs convenience, replace leading `M-..' with `\E..' */ + *d++ = C0_ESC; + s += 2; + if (toupper(*s) == 'X') + /* append carriage-return for `M-xcommand' */ + for (*d++ = 'x', append = '\r', s++; isspace(*s); s++) ; + } + for (; (ch = *s++);) { + if (ch == '\\') { + ch = *s++; + if (ch >= '0' && ch <= '7') { /* octal */ + num = ch - '0'; + for (i = 0; i < 2; i++, s++) { + ch = *s; + if (ch < '0' || ch > '7') + break; + num = num * 8 + ch - '0'; + } + ch = (char)num; + } else if (ch == 'a') + ch = C0_BEL; /* bell */ + else if (ch == 'b') + ch = C0_BS; /* backspace */ + else if (ch == 'E' || ch == 'e') + ch = C0_ESC; /* escape */ + else if (ch == 'n') + ch = '\n'; /* newline */ + else if (ch == 'r') + ch = '\r'; /* carriage-return */ + else if (ch == 't') + ch = C0_HT; /* tab */ + } else if (ch == '^') { + ch = *s++; + ch = toupper(ch); + ch = (ch == '?' ? 127 : (ch - '@')); + } + *d++ = ch; + } + +/* ESC] is an XTerm escape sequence, must be terminated */ + if (*str == '\0' && str[1] == C0_ESC && str[2] == ']') + append = CHAR_ST; + +/* add trailing character as required */ + if (append && d[-1] != append) + *d++ = append; + *d = '\0'; + + return (d - str); +} + +/* + * Split a comma-separated string into an array, stripping leading and + * trailing spaces (and paired quotes) from each entry. Empty strings + * are properly returned + * Caller should free each entry and array when done + */ +/* EXTPROTO */ +char ** +rxvt_splitcommastring(const char *cs) +{ + int l, n, p; + const char *s, *t; + char **ret; + + if ((s = cs) == NULL) + s = ""; + + for (n = 1, t = s; *t; t++) + if (*t == ',') + n++; + ret = (char **)malloc((n + 1) * sizeof(char *)); + ret[n] = NULL; + + for (l = 0, t = s; l < n; l++) { + for ( ; *t && *t != ','; t++) ; + p = t - s; + ret[l] = (char *)malloc(p + 1); + strncpy(ret[l], s, p); + ret[l][p] = '\0'; + rxvt_Str_trim(ret[l]); + s = ++t; + } + return ret; +} + +/*----------------------------------------------------------------------* + * file searching + */ + +/* #define DEBUG_SEARCH_PATH */ + +#if defined (XPM_BACKGROUND) || (MENUBAR_MAX) +/* + * search for FILE in the current working directory, and within the + * colon-delimited PATHLIST, adding the file extension EXT if required. + * + * FILE is either semi-colon or zero terminated + */ +/* INTPROTO */ +char * +rxvt_File_search_path(const char *pathlist, const char *file, const char *ext) +{ + int maxpath, len; + const char *p, *path; + char name[256]; + + if (!access(file, R_OK)) /* found (plain name) in current directory */ + return STRDUP(file); + +/* semi-colon delimited */ + if ((p = STRCHR(file, ';'))) + len = (p - file); + else + len = STRLEN(file); + +#ifdef DEBUG_SEARCH_PATH + getcwd(name, sizeof(name)); + fprintf(stderr, "pwd: \"%s\"\n", name); + fprintf(stderr, "find: \"%.*s\"\n", len, file); +#endif + +/* leave room for an extra '/' and trailing '\0' */ + maxpath = sizeof(name) - (len + (ext ? STRLEN(ext) : 0) + 2); + if (maxpath <= 0) + return NULL; + +/* check if we can find it now */ + STRNCPY(name, file, len); + name[len] = '\0'; + + if (!access(name, R_OK)) + return STRDUP(name); + if (ext) { + STRCAT(name, ext); + if (!access(name, R_OK)) + return STRDUP(name); + } + for (path = pathlist; path != NULL && *path != '\0'; path = p) { + int n; + + /* colon delimited */ + if ((p = STRCHR(path, ':')) == NULL) + p = STRCHR(path, '\0'); + + n = (p - path); + if (*p != '\0') + p++; + + if (n > 0 && n <= maxpath) { + STRNCPY(name, path, n); + if (name[n - 1] != '/') + name[n++] = '/'; + name[n] = '\0'; + STRNCAT(name, file, len); + + if (!access(name, R_OK)) + return STRDUP(name); + if (ext) { + STRCAT(name, ext); + if (!access(name, R_OK)) + return STRDUP(name); + } + } + } + return NULL; +} + +/* EXTPROTO */ +char * +rxvt_File_find(const char *file, const char *ext, const char *path) +{ + char *f; + + if (file == NULL || *file == '\0') + return NULL; + +/* search environment variables here too */ + if ((f = rxvt_File_search_path(path, file, ext)) == NULL) +#ifdef PATH_ENV + if ((f = rxvt_File_search_path(getenv(PATH_ENV), file, ext)) == NULL) +#endif + f = rxvt_File_search_path(getenv("PATH"), file, ext); + +#ifdef DEBUG_SEARCH_PATH + if (f) + fprintf(stderr, "found: \"%s\"\n", f); +#endif + + return f; +} +#endif /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */ + +/*----------------------------------------------------------------------* + * miscellaneous drawing routines + */ + +/* + * Draw top/left and bottom/right border shadows around windows + */ +#if defined(RXVT_SCROLLBAR) || defined(MENUBAR) +/* EXTPROTO */ +void +rxvt_Draw_Shadow(Display *Xdisplay, Window win, GC topShadow, GC botShadow, int x, int y, int w, int h) +{ + int shadow; + + shadow = (w == 0 || h == 0) ? 1 : SHADOW; + w += x - 1; + h += y - 1; + for (; shadow-- > 0; x++, y++, w--, h--) { + XDrawLine(Xdisplay, win, topShadow, x, y, w, y); + XDrawLine(Xdisplay, win, topShadow, x, y, x, h); + XDrawLine(Xdisplay, win, botShadow, w, h, w, y + 1); + XDrawLine(Xdisplay, win, botShadow, w, h, x + 1, h); + } +} +#endif + +/* button shapes */ +#ifdef MENUBAR +/* EXTPROTO */ +void +rxvt_Draw_Triangle(Display *Xdisplay, Window win, GC topShadow, GC botShadow, int x, int y, int w, int type) +{ + switch (type) { + case 'r': /* right triangle */ + XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w); + XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y + w / 2); + XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w / 2); + break; + + case 'l': /* left triangle */ + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y); + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w / 2); + XDrawLine(Xdisplay, win, topShadow, x, y + w / 2, x + w, y); + break; + + case 'd': /* down triangle */ + XDrawLine(Xdisplay, win, topShadow, x, y, x + w / 2, y + w); + XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y); + XDrawLine(Xdisplay, win, botShadow, x + w, y, x + w / 2, y + w); + break; + + case 'u': /* up triangle */ + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w / 2, y); + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w); + XDrawLine(Xdisplay, win, topShadow, x, y + w, x + w / 2, y); + break; +#if 0 + case 's': /* square */ + XDrawLine(Xdisplay, win, topShadow, x + w, y, x, y); + XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w); + XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w); + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y); + break; +#endif + } +} +#endif +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/netdisp.C b/src/netdisp.C new file mode 100644 index 00000000..c556f837 --- /dev/null +++ b/src/netdisp.C @@ -0,0 +1,104 @@ +/*--------------------------------*-C-*---------------------------------* + * File: netdisp.c + *----------------------------------------------------------------------* + * $Id: netdisp.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1996 Chuck Blake + * - original version + * Copyright (c) 1997 mj olesen + * Copyright (c) 1997,1998 Oezguer Kesim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------* + * support for resolving the actual IP number of the host for remote + * DISPLAYs. When the display is local (i.e. :0), we add support for + * sending the first non-loopback interface IP number as the DISPLAY + * instead of just sending the incorrect ":0". This way telnet/rlogin + * shells can actually get the correct information into DISPLAY for + * xclients. + *----------------------------------------------------------------------*/ + +#include "../config.h" /* NECESSARY */ +#include "rxvt.h" /* NECESSARY */ + +#ifdef DISPLAY_IS_IP +#include "netdisp.h" + +/*----------------------------------------------------------------------*/ +/* return NULL a pointer to buffer which may be freed */ +/* EXTPROTO */ +char * +rxvt_network_display(const char *display) +{ + char buffer[1024], *rval = NULL; + struct ifconf ifc; + struct ifreq *ifr; + int i, skfd; + + if (display[0] != ':' && STRNCMP(display, "unix:", 5)) + return (char *) display; /* nothing to do */ + + ifc.ifc_len = sizeof(buffer); /* Get names of all ifaces */ + ifc.ifc_buf = buffer; + + if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return NULL; + } + if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { + perror("SIOCGIFCONF"); + close(skfd); + return NULL; + } + for (i = 0, ifr = ifc.ifc_req; + i < (ifc.ifc_len / sizeof(struct ifreq)); + i++, ifr++) { + struct ifreq ifr2; + + STRCPY(ifr2.ifr_name, ifr->ifr_name); + if (ioctl(skfd, SIOCGIFADDR, &ifr2) >= 0) { + unsigned long addr; + struct sockaddr_in *p_addr; + + p_addr = (struct sockaddr_in *)&(ifr2.ifr_addr); + addr = htonl((unsigned long)p_addr->sin_addr.s_addr); + + /* + * not "0.0.0.0" or "127.0.0.1" - so format the address + */ + if (addr && addr != 0x7F000001) { + char *colon = STRCHR(display, ':'); + + if (colon == NULL) + colon = ":0.0"; + + rval = rxvt_malloc(STRLEN(colon) + 16); + sprintf(rval, "%d.%d.%d.%d%s", + (int)((addr >> 030) & 0xFF), + (int)((addr >> 020) & 0xFF), + (int)((addr >> 010) & 0xFF), + (int)(addr & 0xFF), colon); + break; + } + } + } + + close(skfd); + return rval; +} +#endif /* DISPLAY_IS_IP */ +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/protos.h b/src/protos.h new file mode 100644 index 00000000..d4f531eb --- /dev/null +++ b/src/protos.h @@ -0,0 +1,57 @@ +/* Include prototypes for all files */ +/* + * $Id: protos.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ +#include "command.extpro" + +#include "defaultfont.extpro" + +#ifdef RXVT_GRAPHICS +# include "graphics.extpro" +#endif +#ifdef GREEK_SUPPORT +# include "grkelot.extpro" +#endif + +#include "init.extpro" + +#ifdef UTMP_SUPPORT +# include "logging.extpro" +#endif + +#include "main.extpro" + +#ifdef MENUBAR +# include "menubar.extpro" +#endif + +#include "misc.extpro" + +#ifdef DISPLAY_IS_IP +# include "netdisp.extpro" +#endif + +#include "ptytty.extpro" + +#if !defined(NO_STRINGS) && !defined(HAVE_STRING_H) +# include "strings.extpro" +#endif + +#include "screen.extpro" + +#include "scrollbar.extpro" +#ifdef RXVT_SCROLLBAR +# include "scrollbar-rxvt.extpro" +#endif +#ifdef NEXT_SCROLLBAR +# include "scrollbar-next.extpro" +#endif +#ifdef XTERM_SCROLLBAR +# include "scrollbar-xterm.extpro" +#endif + +#include "xdefaults.extpro" + +#ifdef XPM_BACKGROUND +# include "xpm.extpro" +#endif diff --git a/src/ptytty.C b/src/ptytty.C new file mode 100644 index 00000000..09e5d565 --- /dev/null +++ b/src/ptytty.C @@ -0,0 +1,291 @@ +/*--------------------------------*-C-*---------------------------------* + * File: ptytty.c + *----------------------------------------------------------------------* + * $Id: ptytty.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1999-2001 Geoff Wing + * + * 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 +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#if defined(HAVE_STRING_H) +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#if defined(PTYS_ARE_PTMX) && !defined(__CYGWIN32__) +# include /* for I_PUSH */ +#endif + + +#ifdef DEBUG_TTY +# define D_TTY(x) fprintf x ; fputc('\n', stderr) ; fflush(stderr) +#else +# define D_TTY(x) +#endif + +/* ------------------------------------------------------------------------- * + * GET PSEUDO TELETYPE - MASTER AND SLAVE * + * ------------------------------------------------------------------------- */ +/* + * Returns pty file descriptor, or -1 on failure + * If successful, ttydev is set to the name of the slave device. + * fd_tty _may_ also be set to an open fd to the slave device + */ +/* EXTPROTO */ +int +rxvt_get_pty(int *fd_tty, const char **ttydev) +{ + int pfd; + +#ifdef PTYS_ARE_OPENPTY + char tty_name[sizeof "/dev/pts/????\0"]; + + if (openpty(&pfd, fd_tty, tty_name, NULL, NULL) != -1) { + *ttydev = strdup(tty_name); + return pfd; + } +#endif + +#ifdef PTYS_ARE__GETPTY + *ttydev = _getpty(&pfd, O_RDWR | O_NDELAY | O_NOCTTY, 0622, 0); + if (*ttydev != NULL) + return pfd; +#endif + +#ifdef PTYS_ARE_GETPTY + char *ptydev; + + while ((ptydev = getpty()) != NULL) + if ((pfd = open(ptydev, O_RDWR | O_NOCTTY, 0)) >= 0) { + *ttydev = ptydev; + return pfd; + } +#endif + +#if defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT) +# if defined(PTYS_ARE_GETPT) || defined(PTYS_ARE_PTMX) + { +# ifdef PTYS_ARE_GETPT + pfd = getpt(); +# else + pfd = open("/dev/ptmx", O_RDWR | O_NOCTTY, 0); +# endif + if (pfd >= 0) { + if (grantpt(pfd) == 0 /* change slave permissions */ + && unlockpt(pfd) == 0) { /* slave now unlocked */ + *ttydev = ptsname(pfd); /* get slave's name */ + return pfd; + } + close(pfd); + } + } +# endif +#endif + +#ifdef PTYS_ARE_PTC + if ((pfd = open("/dev/ptc", O_RDWR | O_NOCTTY, 0)) >= 0) { + *ttydev = ttyname(pfd); + return pfd; + } +#endif + +#ifdef PTYS_ARE_CLONE + if ((pfd = open("/dev/ptym/clone", O_RDWR | O_NOCTTY, 0)) >= 0) { + *ttydev = ptsname(pfd); + return pfd; + } +#endif + +#ifdef PTYS_ARE_NUMERIC + { + int idx; + char *c1, *c2; + char pty_name[] = "/dev/ptyp???"; + char tty_name[] = "/dev/ttyp???"; + + c1 = &(pty_name[sizeof(pty_name) - 4]); + c2 = &(tty_name[sizeof(tty_name) - 4]); + for (idx = 0; idx < 256; idx++) { + sprintf(c1, "%d", idx); + sprintf(c2, "%d", idx); + if (access(tty_name, F_OK) < 0) { + idx = 256; + break; + } + if ((pfd = open(pty_name, O_RDWR | O_NOCTTY, 0)) >= 0) { + if (access(tty_name, R_OK | W_OK) == 0) { + *ttydev = strdup(tty_name); + return pfd; + } + close(pfd); + } + } + } +#endif +#ifdef PTYS_ARE_SEARCHED + { + const char *c1, *c2; + char pty_name[] = "/dev/pty??"; + char tty_name[] = "/dev/tty??"; + +# ifndef PTYCHAR1 +# define PTYCHAR1 "pqrstuvwxyz" +# endif +# ifndef PTYCHAR2 +# define PTYCHAR2 "0123456789abcdef" +# endif + for (c1 = PTYCHAR1; *c1; c1++) { + pty_name[(sizeof(pty_name) - 3)] = + tty_name[(sizeof(pty_name) - 3)] = *c1; + for (c2 = PTYCHAR2; *c2; c2++) { + pty_name[(sizeof(pty_name) - 2)] = + tty_name[(sizeof(pty_name) - 2)] = *c2; + if ((pfd = open(pty_name, O_RDWR | O_NOCTTY, 0)) >= 0) { + if (access(tty_name, R_OK | W_OK) == 0) { + *ttydev = strdup(tty_name); + return pfd; + } + close(pfd); + } + } + } + } +#endif + return -1; +} + +/*----------------------------------------------------------------------*/ +/* + * Returns tty file descriptor, or -1 on failure + */ +/* EXTPROTO */ +int +rxvt_get_tty(const char *ttydev) +{ + return open(ttydev, O_RDWR | O_NOCTTY, 0); +} + +/*----------------------------------------------------------------------*/ +/* + * Make our tty a controlling tty so that /dev/tty points to us + */ +/* EXTPROTO */ +int +rxvt_control_tty(int fd_tty, const char *ttydev) +{ +#ifndef __QNX__ + int fd; + + D_TTY((stderr, "rxvt_control_tty(): pid: %d, tty fd: %d, dev: %s", getpid(), fd_tty, ttydev)); +/* ---------------------------------------- */ +# ifdef HAVE_SETSID + setsid(); +# endif +# if defined(HAVE_SETPGID) + setpgid(0, 0); +# elif defined(HAVE_SETPGRP) + setpgrp(0, 0); +# endif +/* ---------------------------------------- */ +# ifdef TIOCNOTTY + fd = open("/dev/tty", O_RDWR | O_NOCTTY); + D_TTY((stderr, "rxvt_control_tty(): Voiding tty associations: previous=%s", fd < 0 ? "no" : "yes")); + if (fd >= 0) { + ioctl(fd, TIOCNOTTY, NULL); /* void tty associations */ + close(fd); + } +# endif +/* ---------------------------------------- */ + fd = open("/dev/tty", O_RDWR | O_NOCTTY); + D_TTY((stderr, "rxvt_control_tty(): /dev/tty has controlling tty? %s", fd < 0 ? "no (good)" : "yes (bad)")); + if (fd >= 0) + close(fd); /* ouch: still have controlling tty */ +/* ---------------------------------------- */ +#if defined(PTYS_ARE_PTMX) && defined(I_PUSH) +/* + * Push STREAMS modules: + * ptem: pseudo-terminal hardware emulation module. + * ldterm: standard terminal line discipline. + * ttcompat: V7, 4BSD and XENIX STREAMS compatibility module. + * + * After we push the STREAMS modules, the first open() on the slave side + * (i.e. the next section between the dashes giving us "tty opened OK") + * should make the "ptem" (or "ldterm" depending upon either which OS + * version or which set of manual pages you have) module give us a + * controlling terminal. We must already have close()d the master side + * fd in this child process before we push STREAMS modules on because the + * documentation is really unclear about whether it is any close() on + * the master side or the last close() - i.e. a proper STREAMS dismantling + * close() - on the master side which causes a hang up to be sent + * through - Geoff Wing + */ +# ifdef HAVE_ISASTREAM + if (isastream(fd_tty) == 1) +# endif + { + D_TTY((stderr, "rxvt_control_tty(): Pushing STREAMS modules")); + ioctl(fd_tty, I_PUSH, "ptem"); + ioctl(fd_tty, I_PUSH, "ldterm"); + ioctl(fd_tty, I_PUSH, "ttcompat"); + } +#endif +/* ---------------------------------------- */ +# if defined(TIOCSCTTY) + fd = ioctl(fd_tty, TIOCSCTTY, NULL); + D_TTY((stderr, "rxvt_control_tty(): ioctl(..,TIOCSCTTY): %d", fd)); +# elif defined(TIOCSETCTTY) + fd = ioctl(fd_tty, TIOCSETCTTY, NULL); + D_TTY((stderr, "rxvt_control_tty(): ioctl(..,TIOCSETCTTY): %d", fd)); +# else + fd = open(ttydev, O_RDWR); + D_TTY((stderr, "rxvt_control_tty(): tty open%s", fd < 0 ? " failure" : "ed OK")); + if (fd >= 0) + close(fd); +# endif +/* ---------------------------------------- */ + fd = open("/dev/tty", O_WRONLY); + D_TTY((stderr, "rxvt_control_tty(): do we have controlling tty now: %s", fd < 0 ? "no (fatal)" : "yes (good)")); + if (fd < 0) + return -1; /* fatal */ + close(fd); +/* ---------------------------------------- */ + D_TTY((stderr, "rxvt_control_tty(): tcgetpgrp(): %d getpgrp(): %d", tcgetpgrp(fd_tty), getpgrp())); +/* ---------------------------------------- */ +#endif /* ! __QNX__ */ + return 0; +} +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/rxvt.h b/src/rxvt.h new file mode 100644 index 00000000..859d4fae --- /dev/null +++ b/src/rxvt.h @@ -0,0 +1,1144 @@ +/* + * $Id: rxvt.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#ifndef _RXVT_H_ /* include once only */ +#define _RXVT_H_ + +#include "rxvtlib.h" + +#include "feature.h" + +#include +#include +#include +#include + +#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 +typedef struct termios ttymode_t; +#else +# include +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 +# else +# include +# 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 */ +# 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 + */ +#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<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)<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 +# endif +# ifdef HAVE_UTMP_H +# include +# endif +#endif + +#ifdef DEBUG_CMD +# define D_CMD(x) fprintf x ; fputc('\n', stderr) +#else +# define D_CMD(x) +#endif +#ifdef DEBUG_INIT +# define D_INIT(x) fprintf x ; fputc('\n', stderr) +#else +# define D_INIT(x) +#endif +#ifdef DEBUG_MAIN +# define D_MAIN(x) fprintf x ; fputc('\n', stderr) +#else +# define D_MAIN(x) +#endif +#ifdef DEBUG_SCREEN +# define D_SCREEN(x) fprintf x ; fputc('\n', stderr) +#else +# define D_SCREEN(x) +#endif +#ifdef DEBUG_SELECT +# define D_SELECT(x) fprintf x ; fputc('\n', stderr) +#else +# define D_SELECT(x) +#endif +#ifdef DEBUG_SIZE +# define D_SIZE(x) fprintf x ; fputc('\n', stderr) +#else +# define D_SIZE(x) +#endif +#ifdef DEBUG_X +# define D_X(x) fprintf x ; fputc('\n', stderr) +#else +# define D_X(x) +#endif + +/* + ***************************************************************************** + * VARIABLES + ***************************************************************************** + */ +#ifdef MENUBAR +# include "menubar.h" +#endif + +struct mbstate { + unsigned char orig; + uint32_t reg; + int cnt; + + mbstate () + { + cnt = 0; + } +}; + +struct rxvt_hidden { + struct mbstate mbstate; +#ifdef __GNUC__ + unsigned char want_refresh:1, + want_full_refresh:1, + am_transparent:1, + am_pixmap_trans:1, + current_screen:1, + hate_those_clicks:1, + num_scr_allow:1, + bypass_keystate:1; + unsigned char chstat:1, + lost_multi:1, + multi_byte:1, + hidden_cursor:1, + hidden_pointer:1, + parsed_geometry:1; +#else + unsigned char want_refresh, +# ifdef TRANSPARENT + want_full_refresh, /* awaiting full screen refresh */ +# endif +# if defined(XPM_BACKGROUND) || defined(TRANSPARENT) + am_transparent, /* is a transparent term */ + am_pixmap_trans, /* transparency w/known root pixmap */ +# endif + current_screen, /* primary or secondary */ + hate_those_clicks, /* a.k.a. keep mark position */ + num_scr_allow, + bypass_keystate, +# ifdef MULTICHAR_SET + chstat, + lost_multi, /* set ==> we only got half a glyph */ + multi_byte, /* set ==> currently using 2 bytes per glyph */ +# endif +# ifdef CURSOR_BLINK + hidden_cursor, +# endif +# ifdef POINTER_BLANK + hidden_pointer, +# endif + parsed_geometry; +#endif /* !__GNUC__ */ + + unsigned char refresh_type, +#ifdef UTMP_SUPPORT + next_utmp_action, +#endif +#ifndef NO_SETOWNER_TTYDEV + next_tty_action, +#endif +#ifdef META8_OPTION + meta_char, /* Alt-key prefix */ +#endif + scrollbar_align, + selection_wait, + selection_type; +/* ---------- */ +#ifdef GREEK_SUPPORT + short greek_mode; /* greek keyboard mode */ +#endif + short rvideo; + int16_t num_scr; /* screen: number lines scrolled */ + uint16_t prev_ncol, /* screen: previous number of columns */ + prev_nrow; /* screen: previous number of rows */ +#ifdef RXVT_GRAPHICS + uint16_t gr_prev_start; +#endif +/* ---------- */ + rend_t rstyle; +/* ---------- */ + uint32_t pixcolor_set[NPIXCLR_SETS]; +/* ---------- */ +#ifdef SELECTION_SCROLLING + int scroll_selection_delay, + scroll_selection_lines; + enum page_dirn scroll_selection_dir; + int selection_save_x, + selection_save_y, + selection_save_state, + pending_scroll_selection; +#endif +/* ---------- */ + int csrO, /* Hops - csr offset in thumb/slider to */ + /* give proper Scroll behaviour */ +#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + scroll_arrow_delay, +#endif +#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING) + mouse_slip_wheel_delay, + mouse_slip_wheel_speed, +#endif + refresh_count, + refresh_limit, + fnum, /* logical font number */ + last_bot, /* scrollbar last bottom position */ + last_top, /* scrollbar last top position */ + last_state, /* scrollbar last state */ + scrollbar_len, + currmaxcol, +#ifdef MENUBAR + menu_readonly, /* okay to alter menu? */ + Arrows_x, +#endif +#if (MENUBAR_MAX > 1) + Nbars, +#endif + window_vt_x, + window_vt_y, + window_sb_x, +# ifdef POINTER_BLANK + pointerBlankDelay, +# endif + allowedxerror; +/* ---------- */ + unsigned int ModMetaMask, + ModNumLockMask, + old_width, /* last used width in screen resize */ + old_height, /* last used height in screen resize */ +#ifndef NO_BRIGHTCOLOR + colorfgbg, +#endif + ttymode; + unsigned long PrivateModes, + SavedModes; +/* ---------- */ +#ifdef PREFER_24BIT + Visual *Xvisual; +#endif +/* ---------- */ + Atom xa[NUM_XA]; +/* ---------- */ +#ifdef MENUBAR + GC menubarGC; +#endif +#if defined(MENUBAR) || defined(RXVT_SCROLLBAR) + GC scrollbarGC, + topShadowGC, + botShadowGC; +#endif +#ifdef XTERM_SCROLLBAR + GC xscrollbarGC, + ShadowGC; +#endif +#ifdef NEXT_SCROLLBAR + GC blackGC, + whiteGC, + grayGC, + darkGC, + stippleGC; + Pixmap dimple, + upArrow, + downArrow, + upArrowHi, + downArrowHi; +#endif +/* ---------- */ + Time selection_time, + selection_request_time; + pid_t cmd_pid; /* process id of child */ + gid_t ttygid; +#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__) + uid_t euid; + gid_t egid; +#endif +/* ---------- */ + Cursor pointer_leftptr; +#ifdef POINTER_BLANK + Cursor pointer_blank; +#endif +/* ---------- */ + const char *ttydev; /* pty/tty name */ +#ifndef NO_BACKSPACE_KEY + const char *key_backspace; +#endif +#ifndef NO_DELETE_KEY + const char *key_delete; +#endif +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) + KeySym ks_bigfont, ks_smallfont; +#endif +#ifdef GREEK_SUPPORT + KeySym ks_greekmodeswith; +#endif +#ifdef USE_XIM + XIC Input_Context; + XIMStyle input_style; + int event_type; +#endif + struct mouse_event MEvent; + XComposeStatus compose; +#ifdef RXVT_GRAPHICS + int graphics_up; + struct grwin_t *gr_root; +#endif + ttymode_t tio; +#ifdef UTMP_SUPPORT +# ifdef HAVE_STRUCT_UTMP + struct utmp ut; +# endif +# ifdef HAVE_STRUCT_UTMPX + struct utmpx utx; +# endif +# if (defined(HAVE_STRUCT_UTMP) && defined(HAVE_UTMP_PID)) || defined(HAVE_STRUCT_UTMPX) + char ut_id[5]; +# endif + int utmp_pos; +#endif + row_col_t oldcursor; +#ifdef XPM_BACKGROUND + bgPixmap_t bgPixmap; + XpmAttributes xpmAttr; /* originally loaded pixmap and its scaling */ +#endif +#ifdef MULTICHAR_SET + int oldcursormulti; + void (*multichar_decode)(unsigned char *str, int len); +#endif +#ifndef RESET_TTY_TO_COMMON_DEFAULTS + struct stat ttyfd_stat; /* original status of our tty */ +#endif +#ifdef MENUBAR + menu_t *ActiveMenu, /* currently active menu */ + *BuildMenu; /* the menu currently being built */ + bar_t *CurrentBar; +# if !(MENUBAR_MAX > 1) + bar_t BarList; +# endif /* (MENUBAR_MAX > 1) */ +#endif +#ifdef RXVT_GRAPHICS + Window gr_last_id; +#endif +#ifdef CURSOR_BLINK + struct timeval lastcursorchange; +#endif +#ifdef POINTER_BLANK + struct timeval lastmotion; +#endif + struct timeval timeout[NUM_TIMEOUTS]; + +/* these three don't need to be kept but do so to placate some mem checkers */ + char *env_windowid; /* environmental variable WINDOWID */ + char *env_display; /* environmental variable DISPLAY */ + char *env_term; /* environmental variable TERM */ + char *env_colorfgbg; + char *buffer; + char *locale; + char charsets[4]; + unsigned char *v_buffer; /* pointer to physical buffer */ + unsigned char *v_bufstr; /* beginning of area to write */ + unsigned char *v_bufptr; /* end of area to write */ + unsigned char *v_bufend; /* end of physical buffer */ + char *newfont[MAX_NFONTS]; +#ifdef KEYSYM_RESOURCE + const unsigned char *Keysym_map[256]; +#endif + const char *rs[NUM_RESOURCES]; +/* command input buffering */ + unsigned char *cmdbuf_ptr, *cmdbuf_endp; + unsigned char cmdbuf_base[BUFSIZ]; + unsigned char kbuf[KBUFSZ]; +}; + +#ifndef __attribute__ +# ifdef __GNUC__ +# if (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || (__GNUC__ < 2) +# define __attribute__(x) +# endif +# endif +# define __attribute__(x) +#endif + +/* + ***************************************************************************** + * PROTOTYPES + ***************************************************************************** + */ +#ifdef PROTOTYPES +# define __PROTO(p) p +#else +# define __PROTO(p) () +#endif +#include "protos.h" + +#ifdef DEBUG_malloc +# include "dmalloc.h" /* This comes last */ +#endif + +#endif /* _RXVT_H_ */ diff --git a/src/rxvtgrx.h b/src/rxvtgrx.h new file mode 100644 index 00000000..650041e0 --- /dev/null +++ b/src/rxvtgrx.h @@ -0,0 +1,54 @@ +/*--------------------------------*-C-*---------------------------------* + * File: rxvtgrx.h + * $Id: rxvtgrx.h,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Stuff for text alignment for rxvt special graphics mode + * + * alignment + * Top: + * text is placed so that the specified point is at the top of the + * capital letters + * Center: + * text is placed so that the specified point is equidistant from the + * bottom of descenders and the top of the capital letters + * Bottom: + * text is placed so that the bottom of descenders is on the specified + * point + * Base: + * text is placed so that the bottom of the characters with no descenders + * is on the specified point + * Caps_Center: + * text is placed so that the specified point is equidistant from the + * bottom and tops of capital letters + *----------------------------------------------------------------------*/ +#ifndef _RXVTGRX_H_ +#define _RXVTGRX_H_ + +#define GRX_SCALE 10000 + +#define RIGHT_TEXT 0x10 +#define HCENTER_TEXT 0x20 +#define LEFT_TEXT 0x30 +#define HORIZONTAL_ALIGNMENT 0x70 + +#define TOP_TEXT 0x01 +#define VCENTER_TEXT 0x02 +#define BOTTOM_TEXT 0x03 +#define BASE_TEXT 0x04 +#define VCAPS_CENTER_TEXT 0x05 +#define VERTICAL_ALIGNMENT 0x0F + +#if 0 /* this would be nicer */ +# define TXT_RIGHT 'r' +# define TXT_CENTER 'c' +# define TXT_LEFT 'l' + +# define TXT_TOP 't' +# define TXT_VCENTER 'v' +# define TXT_BOTTOM 'b' +# define TXT_BASE '_' +# define TXT_VCAPS_CENTER 'C' +#endif + +#endif /* _RXVTGRX_H_ */ +/*----------------------- end-of-file (C header) -----------------------*/ diff --git a/src/rxvtlib.h.in b/src/rxvtlib.h.in new file mode 100644 index 00000000..96fccc21 --- /dev/null +++ b/src/rxvtlib.h.in @@ -0,0 +1,345 @@ +/* + * $Id: rxvtlib.h.in,v 1.1 2003-11-24 17:28:08 pcg Exp $ + */ + +#ifndef _RXVTLIB_H_ /* include once only */ +#define _RXVTLIB_H_ + +/* + * section 1 generated by GNU autoconf for @build@ + * this section may be changed as appropriate _before_ building + */ +/***************************************************************************** + * SECTION 1 * + *****************************************************************************/ + +/* + * The following line MUST not be changed without also changing + * config.h in the main directory before building + */ +// none anymore + +/***************************************************************************** + * INCLUDES * + *****************************************************************************/ + +#include +#include +#include +@include_stdarg_h@ +@include_stdlib_h@ +@include_stdint_h@ +#include +@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 +#include + +extern "C" { +#include /* Xlib, Xutil, Xresource, Xfuncproto */ +} + +/* + * If we haven't pulled in typedef's like int16_t then do them ourself + * type of (normal and unsigned) basic sizes + */ +@rxvt_int16_typedef@ +@rxvt_uint16_typedef@ +@rxvt_int32_typedef@ +@rxvt_uint32_typedef@ + +/* whatever normal size corresponds to a integer pointer */ +@rxvt_intp_define@ +/* whatever normal size corresponds to a unsigned integer pointer */ +@rxvt_u_intp_define@ + +/***************************************************************************** + * SECTION 2 * + * DO NOT TOUCH ANYTHING BELOW HERE * + *****************************************************************************/ + +struct rxvt_fontset; +struct rxvt_color; +struct rxvt_vars; /* defined later on */ +struct rxvt_hidden; /* not defined here */ + +extern struct rxvt_vars *rxvt_current_term; + +#if EXPLICIT_CONTEXT + +# define pR struct rxvt_vars *rxvt_term +# define aR rxvt_term +# define pR_ pR, +# define aR_ aR, + +# define R rxvt_term + +# define SET_R(r) rxvt_current_term = (r) +# define GET_R rxvt_current_term + +#else + +# define pR +# define pR_ +# define aR +# define aR_ + +# define R rxvt_current_term + +# define SET_R(r) rxvt_current_term = (r) +# define GET_R R + +#endif + +#define dR rxvt_t *rxvt_term = GET_R + +#define scrollbar_visible(rxvtvars) ((rxvtvars)->scrollBar.state) +#define menubar_visible(rxvtvars) ((rxvtvars)->menuBar.state) + +typedef struct { + int32_t row; + int32_t col; +} row_col_t; + +#if UNICODE3 +typedef uint32_t text_t; +#else +typedef uint16_t text_t; // saves lots of memory +#endif +typedef uint32_t rend_t; + +/* + * TermWin elements limits + * width : 1 <= width + * height : 1 <= height + * ncol : 1 <= ncol <= MAX(int16_t) + * nrow : 1 <= nrow <= MAX(int16_t) + * saveLines : 0 <= saveLines <= MAX(int16_t) + * nscrolled : 0 <= nscrolled <= saveLines + * view_start: 0 <= view_start <= nscrolled + */ + +typedef struct { + uint16_t width; /* window width [pixels] */ + uint16_t height; /* window height [pixels] */ + uint16_t fwidth; /* font width [pixels] */ + uint16_t fheight; /* font height [pixels] */ + uint16_t fbase; /* font ascent (baseline) [pixels] */ + uint16_t propfont; /* font proportional flags */ + uint16_t ncol; /* window columns [characters] */ + uint16_t nrow; /* window rows [characters] */ + uint16_t focus; /* window has focus */ + uint16_t mapped; /* window state mapped? */ + uint16_t int_bwidth; /* internal border width */ + uint16_t ext_bwidth; /* external border width */ + uint16_t lineSpace; /* number of extra pixels between rows */ + uint16_t saveLines; /* number of lines that fit in scrollback */ + uint16_t nscrolled; /* number of line actually scrolled */ + uint16_t view_start; /* scrollback view starts here */ + Window parent[6]; /* parent identifiers - we're parent[0] */ + Window vt; /* vt100 window */ + GC gc; /* GC for drawing */ + Pixmap pixmap; + rxvt_fontset *fontset; +} TermWin_t; + +/* + * screen accounting: + * screen_t elements + * text: Contains all text information including the scrollback buffer. + * Each line is length TermWin.ncol + * tlen: The length of the line or -1 for wrapped lines. + * rend: Contains rendition information: font, bold, colour, etc. + * * Note: Each line for both text and rend are only allocated on demand, and + * text[x] is allocated <=> rend[x] is allocated for all x. + * row: Cursor row position : 0 <= row < TermWin.nrow + * col: Cursor column position : 0 <= col < TermWin.ncol + * tscroll: Scrolling region top row inclusive : 0 <= row < TermWin.nrow + * bscroll: Scrolling region bottom row inclusive : 0 <= row < TermWin.nrow + * + * selection_t elements + * clicks: 1, 2 or 3 clicks - 4 indicates a special condition of 1 where + * nothing is selected + * beg: row/column of beginning of selection : never past mark + * mark: row/column of initial click : never past end + * end: row/column of one character past end of selection + * * Note: -TermWin.nscrolled <= beg.row <= mark.row <= end.row < TermWin.nrow + * * Note: col == -1 ==> we're left of screen + * + * Layout of text/rend information in the screen_t text/rend structures: + * Rows [0] ... [TermWin.saveLines - 1] + * scrollback region : we're only here if TermWin.view_start != 0 + * Rows [TermWin.saveLines] ... [TermWin.saveLines + TermWin.nrow - 1] + * normal `unscrolled' screen region + */ +typedef struct { + text_t **text; /* _all_ the text */ + int16_t *tlen; /* length of each text line */ + rend_t **rend; /* rendition, uses RS_ flags */ + row_col_t cur; /* cursor position on the screen */ + uint16_t tscroll; /* top of settable scroll region */ + uint16_t bscroll; /* bottom of settable scroll region */ + uint16_t charset; /* character set number [0..3] */ + unsigned int flags; /* see below */ + row_col_t s_cur; /* saved cursor position */ + uint16_t s_charset; /* saved character set number [0..3] */ + char s_charset_char; + rend_t s_rstyle; /* saved rendition style */ +} screen_t; + +enum selection_op_t { + SELECTION_CLEAR = 0, /* nothing selected */ + SELECTION_INIT, /* marked a point */ + SELECTION_BEGIN, /* started a selection */ + SELECTION_CONT, /* continued selection */ + SELECTION_DONE /* selection put in CUT_BUFFER0 */ +}; + +typedef struct { + unsigned char *text; /* selected text */ + uint32_t len; /* length of selected text */ + short screen; /* screen being used */ + short clicks; /* number of clicks */ + selection_op_t op; /* current operation */ + row_col_t beg; /* beginning of selection <= mark */ + row_col_t mark; /* point of initial click <= end */ + row_col_t end; /* one character past end point */ +} selection_t; + +typedef enum { + OLD_SELECT, OLD_WORD_SELECT, NEW_SELECT +} sstyle_t; + +/* ------------------------------------------------------------------------- */ + +/* screen_t flags */ +#define Screen_Relative (1<<0) /* relative origin mode flag */ +#define Screen_VisibleCursor (1<<1) /* cursor visible? */ +#define Screen_Autowrap (1<<2) /* auto-wrap flag */ +#define Screen_Insert (1<<3) /* insert mode (vs. overstrike) */ +#define Screen_WrapNext (1<<4) /* need to wrap for next char? */ +#define Screen_DefaultFlags (Screen_VisibleCursor|Screen_Autowrap) + +/* rxvt_vars.Options */ +#define Opt_console (1LU<<0) +#define Opt_loginShell (1LU<<1) +#define Opt_iconic (1LU<<2) +#define Opt_visualBell (1LU<<3) +#define Opt_mapAlert (1LU<<4) +#define Opt_reverseVideo (1LU<<5) +#define Opt_utmpInhibit (1LU<<6) +#define Opt_scrollBar (1LU<<7) +#define Opt_scrollBar_right (1LU<<8) +#define Opt_scrollBar_floating (1LU<<9) +#define Opt_meta8 (1LU<<10) +#define Opt_scrollTtyOutput (1LU<<11) +#define Opt_scrollTtyKeypress (1LU<<12) +#define Opt_transparent (1LU<<13) +#define Opt_transparent_all (1LU<<14) +#define Opt_mc_hack (1LU<<15) +#define Opt_tripleclickwords (1LU<<16) +#define Opt_scrollWithBuffer (1LU<<17) +#define Opt_jumpScroll (1LU<<18) +#define Opt_mouseWheelScrollPage (1LU<<19) +#define Opt_pointerBlank (1LU<<20) +#define Opt_cursorBlink (1LU<<21) +/* place holder used for parsing command-line options */ +#define Opt_Reverse (1LU<<30) +#define Opt_Boolean (1LU<<31) + +#define DEFAULT_OPTIONS (Opt_scrollBar | Opt_scrollTtyOutput \ + | Opt_jumpScroll) + +#define PROPFONT_NORMAL (1<<0) +#define PROPFONT_BOLD (1<<1) + +/* ------------------------------------------------------------------------- */ + +typedef enum { + EUCJ, SJIS, /* Japanese KANJI methods */ + BIG5, CNS, /* Chinese BIG5 methods: CNS not implemented */ + GB, /* Chinese GB method */ + KR, /* Korean method */ + NOENC /* no encoding */ +} ENC_METHOD; + +typedef struct { + short method; + void (*func)(unsigned char *, int); + char *name; +} KNOWN_ENCODINGS; + +typedef struct { + short state; + Window win; +} menuBar_t; + +typedef struct { + char state; /* scrollbar state */ + char init; /* scrollbar has been initialised */ + short beg; /* slider sub-window begin height */ + short end; /* slider sub-window end height */ + short top; /* slider top position */ + short bot; /* slider bottom position */ + short style; /* style: rxvt, xterm, next */ + short width; /* scrollbar width */ + Window win; + int (*update)(pR_ int, int, int, int); +} scrollBar_t; + +typedef struct rxvt_vars { +/* + * These ``hidden'' items are not for public consumption and + * must not be accessed externally + */ + struct rxvt_hidden *h; + +/* + * Exposed items + * Changes to structure here require library version number change + */ + TermWin_t TermWin; + scrollBar_t scrollBar; + menuBar_t menuBar; + Display *Xdisplay; + unsigned long Options; + XSizeHints szHint; + Colormap Xcmap; + rxvt_color *PixColors; + short numPixColors; + Cursor TermWin_cursor; /* cursor for vt window */ + int Xdepth; + int sb_shadow; /* scrollbar shadow width */ + int Xfd; /* file descriptor of X server connection */ + int cmd_fd; /* pty file descriptor; connected to command */ + int tty_fd; /* tty file descriptor; connected to child */ + int num_fds; /* number of file descriptors being used */ + int numlock_state; + text_t **drawn_text; /* text drawn on screen (characters) */ + rend_t **drawn_rend; /* text drawn on screen (rendition) */ + text_t **buf_text; + rend_t **buf_rend; + char *tabs; /* per location: 1 == tab-stop */ + screen_t screen; + screen_t swap; + selection_t selection; + sstyle_t selection_style; + ENC_METHOD encoding_method; +} rxvt_t; + +/***************************************************************************** + * PROTOTYPES * + *****************************************************************************/ +void rxvt_main_loop(pR); +rxvt_t *rxvt_init(int, const char *const *); + +#endif /* _RXVTLIB_H_ */ diff --git a/src/screen.C b/src/screen.C new file mode 100644 index 00000000..3b134c4e --- /dev/null +++ b/src/screen.C @@ -0,0 +1,3383 @@ +/*--------------------------------*-C-*--------------------------------------* + * File: screen.c + *---------------------------------------------------------------------------* + * $Id: screen.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Copyright (c) 1997-2001 Geoff Wing + * + * 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 /* get the typedef for CARD32 */ + +#include +#include + +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 rows starting from row + * CLEAR_CHARS: clear chars starting from pixel position + * ERASE_ROWS : set rows starting from 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 and inclusive, by 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 of length 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 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 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 - inclusive: ESC [ ; 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); +} + +/* ------------------------------------------------------------------------- * + * 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 ( + * XTERM_SEQ: Set G1 character set: ESC ) + * XTERM_SEQ: Set G2 character set: ESC * + * XTERM_SEQ: Set G3 character set: ESC + + * See set_font_style for possible values for + */ +/* EXTPROTO */ +void +rxvt_scr_charset_set(pR_ int set, unsigned int ch) +{ + R->h->charsets[set] = (unsigned char)ch; + rxvt_set_font_style(aR); +} + + +/* ------------------------------------------------------------------------- * + * 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 + +/* ------------------------------------------------------------------------- * + * 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 + +/* ------------------------------------------------------------------------- * + * 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 + */ +/* 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); +} + +/* ------------------------------------------------------------------------- * + * 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 +/* ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- * + * DEBUG ROUTINES * + * ------------------------------------------------------------------------- */ +#if 0 +/* INTPROTO */ +void +rxvt_debug_colors(void) +{ + int color; + const char *name[] = { + "fg", "bg", + "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white" + }; + + fprintf(stderr, "Color ( "); + if (R->h->rstyle & RS_RVid) + fprintf(stderr, "rvid "); + if (R->h->rstyle & RS_Bold) + fprintf(stderr, "bold "); + if (R->h->rstyle & RS_Blink) + fprintf(stderr, "blink "); + if (R->h->rstyle & RS_Uline) + fprintf(stderr, "uline "); + fprintf(stderr, "): "); + + color = GET_FGCOLOR(R->h->rstyle); +#ifndef NO_BRIGHTCOLOR + if (color >= minBrightCOLOR && color <= maxBrightCOLOR) { + color -= (minBrightCOLOR - minCOLOR); + fprintf(stderr, "bright "); + } +#endif + fprintf(stderr, "%s on ", name[color]); + + color = GET_BGCOLOR(R->h->rstyle); +#ifndef NO_BRIGHTCOLOR + if (color >= minBrightCOLOR && color <= maxBrightCOLOR) { + color -= (minBrightCOLOR - minCOLOR); + fprintf(stderr, "bright "); + } +#endif + fprintf(stderr, "%s\n", name[color]); +} +#endif diff --git a/src/scrollbar-next.C b/src/scrollbar-next.C new file mode 100644 index 00000000..6e2ae97e --- /dev/null +++ b/src/scrollbar-next.C @@ -0,0 +1,289 @@ +/*--------------------------------*-C-*---------------------------------* + * File: scrollbar-next.c + *----------------------------------------------------------------------* + * $Id: scrollbar-next.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Copyright (c) 1997,1998 mj olesen + * Copyright (c) 1998 Alfredo K. Kojima + * - N*XTstep like scrollbars + * Copyright (c) 1999-2001 Geoff Wing + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *----------------------------------------------------------------------*/ + +#include "../config.h" /* NECESSARY */ +#include "rxvt.h" /* NECESSARY */ +#include "scrollbar-next.intpro" /* PROTOS for internal routines */ + +/*----------------------------------------------------------------------*/ +#if defined(NEXT_SCROLLBAR) + +#define n_stp_width 8 +#define n_stp_height 2 +const unsigned char n_stp_bits[] = { 0x55, 0xaa }; + +/* + * N*XTSTEP like scrollbar - written by Alfredo K. Kojima + */ +#define SCROLLER_DIMPLE_WIDTH 6 +#define SCROLLER_DIMPLE_HEIGHT 6 +#define ARROW_WIDTH 13 +#define ARROW_HEIGHT 13 + +const char *const SCROLLER_DIMPLE[] = { + ".%###.", + "%#%%%%", + "#%%...", + "#%.. ", + "#%. ", + ".%. ." +}; +const char *const SCROLLER_ARROW_UP[] = { + ".............", + ".............", + "......%......", + "......#......", + ".....%#%.....", + ".....###.....", + "....%###%....", + "....#####....", + "...%#####%...", + "...#######...", + "..%#######%..", + ".............", + "............." +}; +const char *const SCROLLER_ARROW_DOWN[] = { + ".............", + ".............", + "..%#######%..", + "...#######...", + "...%#####%...", + "....#####....", + "....%###%....", + ".....###.....", + ".....%#%.....", + "......#......", + "......%......", + ".............", + "............." +}; +const char *const HI_SCROLLER_ARROW_UP[] = { + " ", + " ", + " % ", + " % ", + " %%% ", + " %%% ", + " %%%%% ", + " %%%%% ", + " %%%%%%% ", + " %%%%%%% ", + " %%%%%%%%% ", + " ", + " " +}; +const char *const HI_SCROLLER_ARROW_DOWN[] = { + " ", + " ", + " %%%%%%%%% ", + " %%%%%%% ", + " %%%%%%% ", + " %%%%% ", + " %%%%% ", + " %%% ", + " %%% ", + " % ", + " % ", + " ", + " " +}; + +/* INTPROTO */ +Pixmap +rxvt_renderPixmap(pR_ const char *const *data, int width, int height) +{ + char a; + int x, y; + Pixmap d; + GC pointcolour; + + d = XCreatePixmap(R->Xdisplay, R->scrollBar.win, width, height, XDEPTH); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + if ((a = data[y][x]) == ' ' || a == 'w') + pointcolour = R->h->whiteGC; + else if (a == '.' || a == 'l') + pointcolour = R->h->grayGC; + else if (a == '%' || a == 'd') + pointcolour = R->h->darkGC; + else /* if (a == '#' || a == 'b' || a) */ + pointcolour = R->h->blackGC; + XDrawPoint(R->Xdisplay, d, pointcolour, x, y); + } + } + return d; +} + +/* INTPROTO */ +void +rxvt_init_scrollbar_stuff(pR) +{ + XGCValues gcvalue; + XColor xcol; + Pixmap stipple; + unsigned long light, dark; + + gcvalue.graphics_exposures = False; + + gcvalue.foreground = R->PixColors[Color_Black]; + R->h->blackGC = XCreateGC(R->Xdisplay, R->scrollBar.win, + GCForeground | GCGraphicsExposures, &gcvalue); + + gcvalue.foreground = R->PixColors[Color_White]; + R->h->whiteGC = XCreateGC(R->Xdisplay, R->scrollBar.win, + GCForeground | GCGraphicsExposures, &gcvalue); + + xcol.red = 0xaeba; + xcol.green = 0xaaaa; + xcol.blue = 0xaeba; + if (!rxvt_rXAllocColor(aR_ &xcol, "light gray")) + xcol.pixel = R->PixColors[Color_AntiqueWhite]; + light = gcvalue.foreground = xcol.pixel; + R->h->grayGC = XCreateGC(R->Xdisplay, R->scrollBar.win, + GCForeground | GCGraphicsExposures, &gcvalue); + + xcol.red = 0x51aa; + xcol.green = 0x5555; + xcol.blue = 0x5144; + if (!rxvt_rXAllocColor(aR_ &xcol, "dark gray")) + xcol.pixel = R->PixColors[Color_Grey25]; + dark = gcvalue.foreground = xcol.pixel; + R->h->darkGC = XCreateGC(R->Xdisplay, R->scrollBar.win, + GCForeground | GCGraphicsExposures, &gcvalue); + + stipple = XCreateBitmapFromData(R->Xdisplay, R->scrollBar.win, + (char *)n_stp_bits, n_stp_width, + n_stp_height); + + gcvalue.foreground = dark; + gcvalue.background = light; + gcvalue.fill_style = FillOpaqueStippled; + gcvalue.stipple = stipple; + +/* XSetWindowBackground(R->Xdisplay, R->scrollBar.win, R->PixColors[Color_Red]); */ + + R->h->stippleGC = XCreateGC(R->Xdisplay, R->scrollBar.win, + GCForeground | GCBackground | GCStipple + | GCFillStyle | GCGraphicsExposures, &gcvalue); + + R->h->dimple = rxvt_renderPixmap(aR_ SCROLLER_DIMPLE, SCROLLER_DIMPLE_WIDTH, + SCROLLER_DIMPLE_HEIGHT); + + R->h->upArrow = rxvt_renderPixmap(aR_ SCROLLER_ARROW_UP, ARROW_WIDTH, + ARROW_HEIGHT); + R->h->downArrow = rxvt_renderPixmap(aR_ SCROLLER_ARROW_DOWN, ARROW_WIDTH, + ARROW_HEIGHT); + R->h->upArrowHi = rxvt_renderPixmap(aR_ HI_SCROLLER_ARROW_UP, ARROW_WIDTH, + ARROW_HEIGHT); + R->h->downArrowHi = rxvt_renderPixmap(aR_ HI_SCROLLER_ARROW_DOWN, + ARROW_WIDTH, ARROW_HEIGHT); +} + +/* Draw bevel & arrows */ +/* INTPROTO */ +void +rxvt_drawBevel(pR_ Drawable d, int x1, int y1, int w, int h) +{ + int x2, y2; + + x2 = x1 + w - 1; /* right point */ + y2 = y1 + h - 1; /* bottom point */ +/* white top and left */ + XDrawLine(R->Xdisplay, d, R->h->whiteGC, x1, y1, x2, y1); + XDrawLine(R->Xdisplay, d, R->h->whiteGC, x1, y1, x1, y2); +/* black bottom and right */ + XDrawLine(R->Xdisplay, d, R->h->blackGC, x1, y2, x2, y2); + XDrawLine(R->Xdisplay, d, R->h->blackGC, x2, y1, x2, y2); +/* dark inside bottom and right */ + x1++, y1++, x2--, y2--; /* move in one point */ + XDrawLine(R->Xdisplay, d, R->h->darkGC, x1, y2, x2, y2); + XDrawLine(R->Xdisplay, d, R->h->darkGC, x2, y1, x2, y2); +} + +/* EXTPROTO */ +int +rxvt_scrollbar_show_next(pR_ int update, int last_top, int last_bot, int scrollbar_len) +{ + int height = R->scrollBar.end + SB_BUTTON_TOTAL_HEIGHT + SB_PADDING; + Drawable s; + + if ((R->scrollBar.init & R_SB_NEXT) == 0) { + R->scrollBar.init |= R_SB_NEXT; + rxvt_init_scrollbar_stuff(aR); + } + + if (R->TermWin.nscrolled == 0 || !update) { + XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->grayGC, 0, 0, + SB_WIDTH_NEXT + 1, height); + XDrawRectangle(R->Xdisplay, R->scrollBar.win, R->h->blackGC, 0, + -SB_BORDER_WIDTH, SB_WIDTH_NEXT, + height + SB_BORDER_WIDTH); + XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->stippleGC, + SB_LEFT_PADDING, 0, SB_BUTTON_WIDTH, height); + } + if (R->TermWin.nscrolled) { + if (last_top < R->scrollBar.top || !update) + XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->stippleGC, + SB_LEFT_PADDING, SB_PADDING + last_top, + SB_BUTTON_WIDTH, R->scrollBar.top - last_top); + if (R->scrollBar.bot < last_bot || !update) + XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->stippleGC, + SB_LEFT_PADDING, R->scrollBar.bot + SB_PADDING, + SB_BUTTON_WIDTH, (last_bot - R->scrollBar.bot)); + XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->grayGC, + SB_LEFT_PADDING, R->scrollBar.top + SB_PADDING, + SB_BUTTON_WIDTH, scrollbar_len); + XCopyArea(R->Xdisplay, R->h->dimple, R->scrollBar.win, R->h->whiteGC, 0, 0, + SCROLLER_DIMPLE_WIDTH, SCROLLER_DIMPLE_HEIGHT, + (SB_WIDTH_NEXT - SCROLLER_DIMPLE_WIDTH) / 2, + R->scrollBar.top + SB_BEVEL_WIDTH_UPPER_LEFT + + (scrollbar_len - SCROLLER_DIMPLE_HEIGHT) / 2); + + rxvt_drawBevel(aR_ R->scrollBar.win, SB_BUTTON_BEVEL_X, + R->scrollBar.top + SB_PADDING, SB_BUTTON_WIDTH, + scrollbar_len); + rxvt_drawBevel(aR_ R->scrollBar.win, SB_BUTTON_BEVEL_X, + height - SB_BUTTON_BOTH_HEIGHT, SB_BUTTON_WIDTH, + SB_BUTTON_HEIGHT); + rxvt_drawBevel(aR_ R->scrollBar.win, SB_BUTTON_BEVEL_X, + height - SB_BUTTON_SINGLE_HEIGHT, SB_BUTTON_WIDTH, + SB_BUTTON_HEIGHT); + + s = (scrollbar_isUp()) ? R->h->upArrowHi : R->h->upArrow; + XCopyArea(R->Xdisplay, s, R->scrollBar.win, R->h->whiteGC, 0, 0, + ARROW_WIDTH, ARROW_HEIGHT, SB_BUTTON_FACE_X, + height - SB_BUTTON_BOTH_HEIGHT + SB_BEVEL_WIDTH_UPPER_LEFT); + + s = (scrollbar_isDn()) ? R->h->downArrowHi : R->h->downArrow; + XCopyArea(R->Xdisplay, s, R->scrollBar.win, R->h->whiteGC, 0, 0, + ARROW_WIDTH, ARROW_HEIGHT, SB_BUTTON_FACE_X, + height - SB_BUTTON_SINGLE_HEIGHT + SB_BEVEL_WIDTH_UPPER_LEFT); + } + return 1; +} +#endif /* NEXT_SCROLLBAR */ +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/scrollbar-rxvt.C b/src/scrollbar-rxvt.C new file mode 100644 index 00000000..b91e80c5 --- /dev/null +++ b/src/scrollbar-rxvt.C @@ -0,0 +1,188 @@ +/*--------------------------------*-C-*---------------------------------* + * File: scrollbar-rxvt.c + *----------------------------------------------------------------------* + * $Id: scrollbar-rxvt.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Copyright (c) 1997,1998 mj olesen + * Copyright (c) 1999-2001 Geoff Wing + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *----------------------------------------------------------------------*/ + +#include "../config.h" /* NECESSARY */ +#include "rxvt.h" /* NECESSARY */ +#include "scrollbar-rxvt.intpro" /* PROTOS for internal routines */ + +/*----------------------------------------------------------------------*/ +#if defined(RXVT_SCROLLBAR) + +/* draw triangular button with a shadow of SHADOW (1 or 2) pixels */ +/* INTPROTO */ +void +rxvt_Draw_button(pR_ int x, int y, int state, int dirn) +{ + unsigned int sz, sz2; + XPoint pt[3]; + GC top, bot; + + sz = R->scrollBar.width; + sz2 = sz / 2; + switch (state) { + case +1: + top = R->h->topShadowGC; + bot = R->h->botShadowGC; + break; + case -1: + top = R->h->botShadowGC; + bot = R->h->topShadowGC; + break; + default: + top = bot = R->h->scrollbarGC; + break; + } + +/* fill triangle */ + pt[0].x = x; + pt[1].x = x + sz - 1; + pt[2].x = x + sz2; + if (dirn == UP) { + pt[0].y = pt[1].y = y + sz - 1; + pt[2].y = y; + } else { + pt[0].y = pt[1].y = y; + pt[2].y = y + sz - 1; + } + XFillPolygon(R->Xdisplay, R->scrollBar.win, R->h->scrollbarGC, + pt, 3, Convex, CoordModeOrigin); + +/* draw base */ + XDrawLine(R->Xdisplay, R->scrollBar.win, (dirn == UP ? bot : top), + pt[0].x, pt[0].y, pt[1].x, pt[1].y); + +/* draw shadow on left */ + pt[1].x = x + sz2 - 1; + pt[1].y = y + (dirn == UP ? 0 : sz - 1); + XDrawLine(R->Xdisplay, R->scrollBar.win, top, + pt[0].x, pt[0].y, pt[1].x, pt[1].y); + +#if (SHADOW > 1) +/* doubled */ + pt[0].x++; + if (dirn == UP) { + pt[0].y--; + pt[1].y++; + } else { + pt[0].y++; + pt[1].y--; + } + XDrawLine(R->Xdisplay, R->scrollBar.win, top, + pt[0].x, pt[0].y, pt[1].x, pt[1].y); +#endif +/* draw shadow on right */ + pt[1].x = x + sz - 1; +/* pt[2].x = x + sz2; */ + pt[1].y = y + (dirn == UP ? sz - 1 : 0); + pt[2].y = y + (dirn == UP ? 0 : sz - 1); + XDrawLine(R->Xdisplay, R->scrollBar.win, bot, + pt[2].x, pt[2].y, pt[1].x, pt[1].y); +#if (SHADOW > 1) +/* doubled */ + pt[1].x--; + if (dirn == UP) { + pt[2].y++; + pt[1].y--; + } else { + pt[2].y--; + pt[1].y++; + } + XDrawLine(R->Xdisplay, R->scrollBar.win, bot, + pt[2].x, pt[2].y, pt[1].x, pt[1].y); +#endif +} + +/* EXTPROTO */ +int +rxvt_scrollbar_show_rxvt(pR_ int update __attribute__((unused)), int last_top, int last_bot, int scrollbar_len) +{ + int sbshadow = R->sb_shadow; + int sbwidth = (int)R->scrollBar.width; + + if ((R->scrollBar.init & R_SB_RXVT) == 0) { + XGCValues gcvalue; + + R->scrollBar.init |= R_SB_RXVT; + gcvalue.foreground = R->PixColors[Color_trough]; + if (sbshadow) { + XSetWindowBackground(R->Xdisplay, R->scrollBar.win, + gcvalue.foreground); + XClearWindow(R->Xdisplay, R->scrollBar.win); + } + } else { +/* instead of XClearWindow (R->Xdisplay, R->scrollBar.win); */ + if (last_top < R->scrollBar.top) + XClearArea(R->Xdisplay, R->scrollBar.win, + sbshadow, last_top, + sbwidth, (R->scrollBar.top - last_top), + False); + + if (R->scrollBar.bot < last_bot) + XClearArea(R->Xdisplay, R->scrollBar.win, + sbshadow, R->scrollBar.bot, + sbwidth, (last_bot - R->scrollBar.bot), + False); + } + +/* scrollbar slider */ +#ifdef SB_BORDER + { + int xofs; + + if (R->Options & Opt_scrollBar_right) + xofs = 0; + else + xofs = sbshadow ? sbwidth : sbwidth - 1; + + XDrawLine(R->Xdisplay, R->scrollBar.win, R->h->botShadowGC, + xofs, 0, xofs, R->scrollBar.end + sbwidth); + } +#endif + XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->scrollbarGC, + sbshadow, R->scrollBar.top, sbwidth, + scrollbar_len); + + if (sbshadow) + /* trough shadow */ + rxvt_Draw_Shadow(R->Xdisplay, R->scrollBar.win, + R->h->botShadowGC, R->h->topShadowGC, + 0, 0, + sbwidth + 2 * sbshadow, /* scrollbar_TotalWidth() */ + R->scrollBar.end + (sbwidth + 1) + sbshadow); +/* shadow for scrollbar slider */ + rxvt_Draw_Shadow(R->Xdisplay, R->scrollBar.win, + R->h->topShadowGC, R->h->botShadowGC, + sbshadow, R->scrollBar.top, sbwidth, + scrollbar_len); + +/* + * Redraw scrollbar arrows + */ + rxvt_Draw_button(aR_ sbshadow, sbshadow, + (scrollbar_isUp() ? -1 : +1), UP); + rxvt_Draw_button(aR_ sbshadow, (R->scrollBar.end + 1), + (scrollbar_isDn() ? -1 : +1), DN); + return 1; +} +#endif /* RXVT_SCROLLBAR */ +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/scrollbar-xterm.C b/src/scrollbar-xterm.C new file mode 100644 index 00000000..d50654f7 --- /dev/null +++ b/src/scrollbar-xterm.C @@ -0,0 +1,86 @@ +/*--------------------------------*-C-*---------------------------------* + * File: scrollbar-xterm.c + *----------------------------------------------------------------------* + * $Id: scrollbar-xterm.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Copyright (c) 1997,1998 mj olesen + * Copyright (c) 1999-2001 Geoff Wing + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *----------------------------------------------------------------------*/ + +#include "../config.h" /* NECESSARY */ +#include "rxvt.h" /* NECESSARY */ +#include "scrollbar-xterm.intpro" /* PROTOS for internal routines */ + +/*----------------------------------------------------------------------*/ +#if defined(XTERM_SCROLLBAR) + +#define x_stp_width 8 +#define x_stp_height 2 +const unsigned char x_stp_bits[] = { 0xff, 0xff }; + +/* EXTPROTO */ +int +rxvt_scrollbar_show_xterm(pR_ int update __attribute__((unused)), int last_top, int last_bot, int scrollbar_len) +{ + int xsb = 0; + int sbwidth = R->scrollBar.width - 1; + + if ((R->scrollBar.init & R_SB_XTERM) == 0) { + XGCValues gcvalue; + + R->scrollBar.init |= R_SB_XTERM; + gcvalue.stipple = XCreateBitmapFromData(R->Xdisplay, R->scrollBar.win, + (char *)x_stp_bits, x_stp_width, + x_stp_height); + if (!gcvalue.stipple) { + rxvt_print_error("can't create bitmap"); + exit(EXIT_FAILURE); + } + gcvalue.fill_style = FillOpaqueStippled; + gcvalue.foreground = R->PixColors[Color_fg]; + gcvalue.background = R->PixColors[Color_bg]; + + R->h->xscrollbarGC = XCreateGC(R->Xdisplay, R->scrollBar.win, + GCForeground | GCBackground + | GCFillStyle | GCStipple, &gcvalue); + gcvalue.foreground = R->PixColors[Color_border]; + R->h->ShadowGC = XCreateGC(R->Xdisplay, R->scrollBar.win, GCForeground, + &gcvalue); + } +/* instead of XClearWindow (R->Xdisplay, R->scrollBar.win); */ + xsb = (R->Options & Opt_scrollBar_right) ? 1 : 0; + if (last_top < R->scrollBar.top) + XClearArea(R->Xdisplay, R->scrollBar.win, + R->sb_shadow + xsb, last_top, + sbwidth + 1, (R->scrollBar.top - last_top), False); + + if (R->scrollBar.bot < last_bot) + XClearArea(R->Xdisplay, R->scrollBar.win, + R->sb_shadow + xsb, R->scrollBar.bot, + sbwidth + 1, (last_bot - R->scrollBar.bot), False); + +/* scrollbar slider */ + XFillRectangle(R->Xdisplay, R->scrollBar.win, R->h->xscrollbarGC, + xsb + 1, R->scrollBar.top, sbwidth, scrollbar_len); + + /*XDrawLine(R->Xdisplay, R->scrollBar.win, R->h->ShadowGC, + xsb ? 0 : sbwidth, R->scrollBar.beg, + xsb ? 0 : sbwidth, R->scrollBar.end);*/ + return 1; +} +#endif /* XTERM_SCROLLBAR */ +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/scrollbar.C b/src/scrollbar.C new file mode 100644 index 00000000..22855a3b --- /dev/null +++ b/src/scrollbar.C @@ -0,0 +1,224 @@ +/*--------------------------------*-C-*---------------------------------* + * File: scrollbar.c + *----------------------------------------------------------------------* + * $Id: scrollbar.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * Copyright (c) 1997,1998 mj olesen + * Copyright (c) 1998 Alfredo K. Kojima + * - N*XTstep like scrollbars + * Copyright (c) 1999-2001 Geoff Wing + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *----------------------------------------------------------------------*/ + +#include "../config.h" /* NECESSARY */ +#include "rxvt.h" /* NECESSARY */ +#include "scrollbar.intpro" /* PROTOS for internal routines */ + +/*----------------------------------------------------------------------*/ + +/* + * Map or unmap a scrollbar. Returns non-zero upon change of state + */ +/* EXTPROTO */ +int +rxvt_scrollbar_mapping(pR_ int map) +{ + int change = 0; +#ifdef HAVE_SCROLLBARS + + if (map && !scrollbar_visible(R)) { + scrollbar_setIdle(); + if (!R->scrollBar.win) + rxvt_Resize_scrollBar(aR); + if (R->scrollBar.win) { + XMapWindow(R->Xdisplay, R->scrollBar.win); + change = 1; + } + } else if (!map && scrollbar_visible(R)) { + R->scrollBar.state = 0; + XUnmapWindow(R->Xdisplay, R->scrollBar.win); + change = 1; + } +#endif + return change; +} + +/* EXTPROTO */ +void +rxvt_Resize_scrollBar(pR) +{ +#ifdef HAVE_SCROLLBARS + int delayed_init = 0; + +#define R_SCROLLBEG_XTERM 0 +#define R_SCROLLEND_XTERM R->szHint.height +#define R_SCROLLBEG_NEXT 0 +#define R_SCROLLEND_NEXT R->szHint.height - (SB_BUTTON_TOTAL_HEIGHT + \ + SB_PADDING) +#define R_SCROLLBEG_RXVT (R->scrollBar.width + 1) + R->sb_shadow +#define R_SCROLLEND_RXVT R->szHint.height - R_SCROLLBEG_RXVT - \ + (2 * R->sb_shadow) + +#if defined(XTERM_SCROLLBAR) + if (R->scrollBar.style == R_SB_XTERM) { + R->scrollBar.beg = R_SCROLLBEG_XTERM; + R->scrollBar.end = R_SCROLLEND_XTERM; + R->scrollBar.update = rxvt_scrollbar_show_xterm; + } +#endif +#if defined(NEXT_SCROLLBAR) + if (R->scrollBar.style == R_SB_NEXT) { + R->scrollBar.beg = R_SCROLLBEG_NEXT; + R->scrollBar.end = R_SCROLLEND_NEXT; + R->scrollBar.update = rxvt_scrollbar_show_next; + } +#endif +#if defined(RXVT_SCROLLBAR) + if (R->scrollBar.style == R_SB_RXVT) { + R->scrollBar.beg = R_SCROLLBEG_RXVT; + R->scrollBar.end = R_SCROLLEND_RXVT; + R->scrollBar.update = rxvt_scrollbar_show_rxvt; + } +#endif + + if (!R->scrollBar.win) { +/* create the scrollbar window */ + R->scrollBar.win = XCreateSimpleWindow(R->Xdisplay, + R->TermWin.parent[0], + R->h->window_sb_x, 0, + scrollbar_TotalWidth(), + R->szHint.height, + 0, + R->PixColors[Color_fg], + R->PixColors[Color_bg]); +#ifdef DEBUG_X + XStoreName(R->Xdisplay, R->scrollBar.win, "scrollbar"); +#endif + XDefineCursor(R->Xdisplay, R->scrollBar.win, R->h->pointer_leftptr); + XSelectInput(R->Xdisplay, R->scrollBar.win, + (ExposureMask | ButtonPressMask | ButtonReleaseMask + | Button1MotionMask | Button2MotionMask + | Button3MotionMask)); + delayed_init = 1; + } + rxvt_scrollbar_show(aR_ 1); + if (delayed_init) + XMapWindow(R->Xdisplay, R->scrollBar.win); +#endif +} + +/* + * Update current scrollbar view w.r.t. slider heights, etc. + */ +/* EXTPROTO */ +int +rxvt_scrollbar_show(pR_ int update) +{ + int ret = 0; +#ifdef HAVE_SCROLLBARS + int top, bot, len, adj; + + if (!scrollbar_visible(R)) + return 0; + + if (update) { + top = (R->TermWin.nscrolled - R->TermWin.view_start); + bot = top + (R->TermWin.nrow - 1); + len = max((R->TermWin.nscrolled + (R->TermWin.nrow - 1)), 1); + adj = (((bot - top) * scrollbar_size()) % len) > 0 ? 1 : 0; + + R->scrollBar.top = (R->scrollBar.beg + (top * scrollbar_size()) / len); + R->h->scrollbar_len = ((bot - top) * scrollbar_size()) / len + + scrollbar_minheight() + adj; + R->scrollBar.bot = (R->scrollBar.top + R->h->scrollbar_len); + /* no change */ + if (R->scrollBar.top == R->h->last_top + && R->scrollBar.bot == R->h->last_bot + && (R->scrollBar.state == R->h->last_state || !scrollbar_isUpDn())) + return 0; + } + + ret = R->scrollBar.update(aR_ update, R->h->last_top, R->h->last_bot, + R->h->scrollbar_len); + + R->h->last_top = R->scrollBar.top; + R->h->last_bot = R->scrollBar.bot; + R->h->last_state = R->scrollBar.state; + +#endif + return ret; +} + +/* EXTPROTO */ +void +rxvt_setup_scrollbar(pR_ const char *scrollalign, const char *scrollstyle, const char *thickness) +{ +#ifdef HAVE_SCROLLBARS + int i; + short style, width; + +# if defined(RXVT_SCROLLBAR) || !(defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR)) + style = R_SB_RXVT; +# else +# ifdef NEXT_SCROLLBAR + style = R_SB_NEXT; +# elif defined(XTERM_SCROLLBAR) + style = R_SB_XTERM; +# endif +# endif + +# if (defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR)) + if (scrollstyle) { +# ifdef NEXT_SCROLLBAR + if (STRNCASECMP(scrollstyle, "next", 4) == 0) + style = R_SB_NEXT; +# endif +# ifdef XTERM_SCROLLBAR + if (STRNCASECMP(scrollstyle, "xterm", 5) == 0) + style = R_SB_XTERM; +# endif + } +# endif + if (style == R_SB_NEXT) + width = SB_WIDTH_NEXT; + else if (style == R_SB_XTERM) + width = SB_WIDTH_XTERM; + else /* if (style == R_SB_RXVT) */ + width = SB_WIDTH_RXVT; + + if (style != R_SB_NEXT) /* dishonour request - for now */ + if (thickness && (i = atoi(thickness)) >= SB_WIDTH_MINIMUM) + width = min(i, SB_WIDTH_MAXIMUM); + +# if defined(RXVT_SCROLLBAR) + if (!(R->Options & Opt_scrollBar_floating) && style == R_SB_RXVT) + R->sb_shadow = SHADOW; +# endif + + R->scrollBar.style = style; + R->scrollBar.width = width; + + /* R->h->scrollbar_align = R_SB_ALIGN_CENTRE; */ + if (scrollalign) { + if (STRNCASECMP(scrollalign, "top", 3) == 0) + R->h->scrollbar_align = R_SB_ALIGN_TOP; + else if (STRNCASECMP(scrollalign, "bottom", 6) == 0) + R->h->scrollbar_align = R_SB_ALIGN_BOTTOM; + } +#endif +} + +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/strings.C b/src/strings.C new file mode 100644 index 00000000..8d7e264e --- /dev/null +++ b/src/strings.C @@ -0,0 +1,308 @@ +/*--------------------------------*-C-*---------------------------------* + * File: strings.c + *----------------------------------------------------------------------* + * $Id: strings.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1997-2001 Geoff Wing + * + * 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 + *--------------------------------------------------------------------------*/ +/* 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 + * presumptions: + * 1) intp_t write the best + * 2) SIZEOF_INT_P == power of 2 + *--------------------------------------------------------------------------*/ + +/* EXTPROTO */ +void +bzero(void *b, size_t len) +{ + MEMSET(b, 0, len); +} + +/* EXTPROTO */ +void * +memset(void *p, int c1, size_t len) +{ + u_intp_t i, val; + unsigned char c = (unsigned char) c1; + unsigned char *lp = (unsigned char *) p; + + if (len) { + if (len >= 16) { /* < 16 probably not worth all the calculations */ +/* write out preceding characters so we align on an integer boundary */ + if ((i = ((-(u_intp_t)p) & (SIZEOF_INT_P - 1)))) { + len -= (size_t)i; + for (; i--;) + *lp++ = c; + } + +/* do the fast writing */ + val = (c << 8) + c; +#if SIZEOF_INT_P >= 4 + val |= (val << 16); +#endif +#if SIZEOF_INT_P >= 8 + val |= (val << 32); +#endif +#if SIZEOF_INT_P == 16 + val |= (val << 64); +#endif + for (i = (u_intp_t)(len / SIZEOF_INT_P); i--;) + *((u_intp_t *)lp)++ = val; + len &= (SIZEOF_INT_P - 1); + } +/* write trailing characters */ + for (; len--;) + *lp++ = c; + } + return p; +} +#endif +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/xdefaults.C b/src/xdefaults.C new file mode 100644 index 00000000..23870f0f --- /dev/null +++ b/src/xdefaults.C @@ -0,0 +1,998 @@ +/*--------------------------------*-C-*---------------------------------* + * File: xdefaults.c + *----------------------------------------------------------------------* + * $Id: xdefaults.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1994 Robert Nation + * - original version + * Copyright (c) 1997,1998 mj olesen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------* + * get resources from ~/.Xdefaults or ~/.Xresources with the memory-saving + * default or with XGetDefault() (#define USE_XGETDEFAULT) + *----------------------------------------------------------------------*/ + +#include "../config.h" /* NECESSARY */ +#include "rxvt.h" /* NECESSARY */ +#include "version.h" +#include "xdefaults.intpro" /* PROTOS for internal routines */ + +/* #define DEBUG_RESOURCES */ + +static const char *const xnames[2] = { ".Xdefaults", ".Xresources" }; + +/*{{{ monolithic option/resource structure: */ +/* + * `string' options MUST have a usage argument + * `switch' and `boolean' options have no argument + * if there's no desc(ription), it won't appear in rxvt_usage() + */ + +/* INFO() - descriptive information only */ +#define INFO(opt, arg, desc) \ + {0, -1, NULL, (opt), (arg), (desc)} + +/* STRG() - command-line option, with/without resource */ +#define STRG(rsp, kw, opt, arg, desc) \ + {0, (rsp), (kw), (opt), (arg), (desc)} + +/* RSTRG() - resource/long-option */ +#define RSTRG(rsp, kw, arg) \ + {0, (rsp), (kw), NULL, (arg), NULL} + +/* BOOL() - regular boolean `-/+' flag */ +#define BOOL(rsp, kw, opt, flag, desc) \ + {(Opt_Boolean|(flag)), (rsp), (kw), (opt), NULL, (desc)} + +/* SWCH() - `-' flag */ +#define SWCH(opt, flag, desc) \ + {(flag), -1, NULL, (opt), NULL, (desc)} + +/* convenient macros */ +#define optList_strlen(i) \ + (optList[i].flag ? 0 : (optList[i].arg ? STRLEN(optList[i].arg) : 1)) +#define optList_isBool(i) \ + (optList[i].flag & Opt_Boolean) +#define optList_isReverse(i) \ + (optList[i].flag & Opt_Reverse) +#define optList_size() \ + (sizeof(optList) / sizeof(optList[0])) + +static const struct { + const unsigned long flag; /* Option flag */ + const int doff; /* data offset */ + const char *kw; /* keyword */ + const char *opt; /* option */ + const char *arg; /* argument */ + const char *desc; /* description */ +} optList[] = { + STRG(Rs_display_name, NULL, "d", NULL, NULL), /* short form */ + STRG(Rs_display_name, NULL, "display", "string", "X server to contact"), + STRG(Rs_term_name, "termName", "tn", "string", + "value of the TERM environment variable"), + STRG(Rs_geometry, NULL, "g", NULL, NULL), /* short form */ + STRG(Rs_geometry, "geometry", "geometry", "geometry", + "size (in characters) and position"), + SWCH("C", Opt_console, "intercept console messages"), + SWCH("iconic", Opt_iconic, "start iconic"), + SWCH("ic", Opt_iconic, NULL), /* short form */ + BOOL(Rs_reverseVideo, "reverseVideo", "rv", Opt_reverseVideo, + "reverse video"), + BOOL(Rs_loginShell, "loginShell", "ls", Opt_loginShell, "login shell"), + BOOL(Rs_jumpScroll, "jumpScroll", "j", Opt_jumpScroll, "jump scrolling"), +#ifdef HAVE_SCROLLBARS + BOOL(Rs_scrollBar, "scrollBar", "sb", Opt_scrollBar, "scrollbar"), + BOOL(Rs_scrollBar_right, "scrollBar_right", "sr", Opt_scrollBar_right, + "scrollbar right"), + BOOL(Rs_scrollBar_floating, "scrollBar_floating", "st", + Opt_scrollBar_floating, "scrollbar without a trough"), +#endif + BOOL(Rs_scrollTtyOutput, "scrollTtyOutput", NULL, Opt_scrollTtyOutput, + NULL), + BOOL(Rs_scrollTtyOutput, NULL, "si", Opt_Reverse | Opt_scrollTtyOutput, + "scroll-on-tty-output inhibit"), + BOOL(Rs_scrollTtyKeypress, "scrollTtyKeypress", "sk", Opt_scrollTtyKeypress, + "scroll-on-keypress"), + BOOL(Rs_scrollWithBuffer, "scrollWithBuffer", "sw", Opt_scrollWithBuffer, + "scroll-with-buffer"), +#ifdef TRANSPARENT + BOOL(Rs_transparent, "inheritPixmap", "ip", Opt_transparent, + "inherit parent pixmap"), + BOOL(Rs_transparent_all, "inheritPixmapforce", "ipf", Opt_transparent_all, + "forcefully inherit root pixmap"), + SWCH("tr", Opt_transparent, NULL), +#endif + BOOL(Rs_utmpInhibit, "utmpInhibit", "ut", Opt_utmpInhibit, "utmp inhibit"), +#ifndef NO_BELL + BOOL(Rs_visualBell, "visualBell", "vb", Opt_visualBell, "visual bell"), +# if ! defined(NO_MAPALERT) && defined(MAPALERT_OPTION) + BOOL(Rs_mapAlert, "mapAlert", NULL, Opt_mapAlert, NULL), +# endif +#endif +#ifdef META8_OPTION + BOOL(Rs_meta8, "meta8", NULL, Opt_meta8, NULL), +#endif +#ifdef MOUSE_WHEEL + BOOL(Rs_mouseWheelScrollPage, "mouseWheelScrollPage", NULL, Opt_mouseWheelScrollPage, + NULL), +#endif +#ifdef MULTICHAR_SET + BOOL(Rs_mc_hack, "multibyte_cursor", "mcc", Opt_mc_hack, + "Multibyte character cursor movement"), +#endif +#ifndef NO_FRILLS + BOOL(Rs_tripleclickwords, "tripleclickwords", "tcw", Opt_tripleclickwords, + "triple click word selection"), +#endif +#ifdef CURSOR_BLINK + BOOL(Rs_cursorBlink, "cursorBlink", "bc", Opt_cursorBlink, "blinking cursor"), +#endif +#ifdef POINTER_BLANK + BOOL(Rs_pointerBlank, "pointerBlank", NULL, Opt_pointerBlank, NULL), +#endif + STRG(Rs_color + Color_bg, "background", "bg", "color", "background color"), + STRG(Rs_color + Color_fg, "foreground", "fg", "color", "foreground color"), + RSTRG(Rs_color + minCOLOR + 0, "color0", "color"), + RSTRG(Rs_color + minCOLOR + 1, "color1", "color"), + RSTRG(Rs_color + minCOLOR + 2, "color2", "color"), + RSTRG(Rs_color + minCOLOR + 3, "color3", "color"), + RSTRG(Rs_color + minCOLOR + 4, "color4", "color"), + RSTRG(Rs_color + minCOLOR + 5, "color5", "color"), + RSTRG(Rs_color + minCOLOR + 6, "color6", "color"), + RSTRG(Rs_color + minCOLOR + 7, "color7", "color"), +#ifndef NO_BRIGHTCOLOR + RSTRG(Rs_color + minBrightCOLOR + 0, "color8", "color"), + RSTRG(Rs_color + minBrightCOLOR + 1, "color9", "color"), + RSTRG(Rs_color + minBrightCOLOR + 2, "color10", "color"), + RSTRG(Rs_color + minBrightCOLOR + 3, "color11", "color"), + RSTRG(Rs_color + minBrightCOLOR + 4, "color12", "color"), + RSTRG(Rs_color + minBrightCOLOR + 5, "color13", "color"), + RSTRG(Rs_color + minBrightCOLOR + 6, "color14", "color"), + RSTRG(Rs_color + minBrightCOLOR + 7, "color15", "color"), +#endif /* NO_BRIGHTCOLOR */ +#ifndef NO_BOLD_UNDERLINE_REVERSE + RSTRG(Rs_color + Color_BD, "colorBD", "color"), + RSTRG(Rs_color + Color_UL, "colorUL", "color"), + RSTRG(Rs_color + Color_RV, "colorRV", "color"), +#endif /* ! NO_BOLD_UNDERLINE_REVERSE */ +#ifdef KEEP_SCROLLCOLOR + RSTRG(Rs_color + Color_scroll, "scrollColor", "color"), + RSTRG(Rs_color + Color_trough, "troughColor", "color"), +#endif /* KEEP_SCROLLCOLOR */ +#ifdef OPTION_HC + STRG(Rs_color + Color_HC, "highlightColor", "hc", "color", "highlight color"), +#endif +#if defined (XPM_BACKGROUND) || (MENUBAR_MAX) + RSTRG(Rs_path, "path", "search path"), +#endif /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */ +#ifdef XPM_BACKGROUND + STRG(Rs_backgroundPixmap, "backgroundPixmap", "pixmap", "file[;geom]", + "background pixmap"), +#endif /* XPM_BACKGROUND */ +#if (MENUBAR_MAX) + RSTRG(Rs_menu, "menu", "name[;tag]"), +#endif +#ifndef NO_BOLDFONT + STRG(Rs_boldFont, "boldFont", "fb", "fontname", "bold text font"), +#endif + STRG(Rs_font + 0, "font", "fn", "fontname", "normal text font"), +/* fonts: command-line option = resource name */ +#ifdef MULTICHAR_SET + STRG(Rs_multichar_encoding, "multichar_encoding", "km", "mode", + "multichar encoding; mode = eucj|sjis|big5|gb|kr|noenc"), +#endif /* MULTICHAR_SET */ +#ifdef USE_XIM + STRG(Rs_inputMethod, "inputMethod", "im", "name", "name of input method"), + STRG(Rs_preeditType, "preeditType", "pt", "style", + "input style: style = OverTheSpot|OffTheSpot|Root"), +#endif /* USE_XIM */ +#ifdef GREEK_SUPPORT + STRG(Rs_greek_keyboard, "greek_keyboard", "grk", "mode", + "greek keyboard mapping; mode = iso | ibm"), + RSTRG(Rs_greektoggle_key, "greektoggle_key", "keysym"), +#endif + STRG(Rs_name, NULL, "name", "string", + "client instance, icon, and title strings"), + STRG(Rs_title, "title", "title", "string", "title name for window"), + STRG(Rs_title, NULL, "T", NULL, NULL), /* short form */ + STRG(Rs_iconName, "iconName", "n", "string", "icon name for window"), +#ifndef NO_CURSORCOLOR + STRG(Rs_color + Color_cursor, "cursorColor", "cr", "color", "cursor color"), +/* command-line option = resource name */ + RSTRG(Rs_color + Color_cursor2, "cursorColor2", "color"), +#endif /* NO_CURSORCOLOR */ + STRG(Rs_color + Color_pointer, "pointerColor", "pr", "color", + "pointer color"), + STRG(Rs_color + Color_border, "borderColor", "bd", "color", + "border color"), + STRG(Rs_saveLines, "saveLines", "sl", "number", + "number of scrolled lines to save"), +#ifndef NO_FRILLS + STRG(Rs_ext_bwidth, "externalBorder", "w", "number", + "external border in pixels"), + STRG(Rs_ext_bwidth, NULL, "bw", NULL, NULL), + STRG(Rs_ext_bwidth, NULL, "borderwidth", NULL, NULL), + STRG(Rs_int_bwidth, "internalBorder", "b", "number", + "internal border in pixels"), +#endif +#ifndef NO_LINESPACE + STRG(Rs_lineSpace, "lineSpace", "lsp", "number", + "number of extra pixels between rows"), +#endif + STRG(Rs_scrollBar_thickness, "thickness", "sbt", "number", + "scrollbar thickness/width in pixels"), +#ifdef POINTER_BLANK + RSTRG(Rs_pointerBlankDelay, "pointerBlankDelay", "number"), +#endif +#ifndef NO_BACKSPACE_KEY + RSTRG(Rs_backspace_key, "backspacekey", "string"), +#endif +#ifndef NO_DELETE_KEY + RSTRG(Rs_delete_key, "deletekey", "string"), +#endif + RSTRG(Rs_selectstyle, "selectstyle", "mode"), + RSTRG(Rs_scrollstyle, "scrollstyle", "mode"), +#ifdef HAVE_SCROLLBARS + RSTRG(Rs_scrollBar_align, "scrollBar_align", "mode"), +#endif +#ifdef PRINTPIPE + RSTRG(Rs_print_pipe, "print-pipe", "string"), +#endif +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) + RSTRG(Rs_bigfont_key, "bigfont_key", "keysym"), + RSTRG(Rs_smallfont_key, "smallfont_key", "keysym"), +#endif + STRG(Rs_modifier, "modifier", "mod", "modifier", + "meta modifier = alt|meta|hyper|super|mod1|...|mod5"), + INFO("xrm", "string", "X resource"), +#ifdef CUTCHAR_RESOURCE + RSTRG(Rs_cutchars, "cutchars", "string"), +#endif /* CUTCHAR_RESOURCE */ +#ifdef ACS_ASCII + RSTRG(Rs_acs_chars, "acsChars", "string"), +#endif /* ACS_ASCII */ + RSTRG(Rs_answerbackstring, "answerbackString", "string"), + INFO("e", "command arg ...", "command to execute") +}; + +#undef INFO +#undef STRG +#undef RSTRG +#undef SWCH +#undef BOOL +/*}}} */ + +static const char releasestring[] = "Rxvt v" VERSION " - released: " DATE "\n"; +static const char optionsstring[] = "Options: " +#if defined(XPM_BACKGROUND) + "XPM," +#endif +#if defined(TRANSPARENT) + "transparent," +#endif +#if defined(UTMP_SUPPORT) + "utmp," +#endif +#if defined(MENUBAR) + "menubar," +#endif +#if !defined(NO_FRILLS) + "frills," +#endif +#if !defined(NO_LINESPACE) + "linespace," +#endif +#if defined(PREFER_24BIT) + "24bit," +#endif +#if defined(USE_XIM) + "XIM," +#endif +#if defined(MULTICHAR_SET) + "multichar_languages," +#endif + "scrollbars=" +#if !defined(HAVE_SCROLLBARS) + "NONE" +#else +# if defined(RXVT_SCROLLBAR) + "rxvt" +# if defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR) + "+" +# endif +# endif +# if defined(NEXT_SCROLLBAR) + "NeXT" +# if defined(XTERM_SCROLLBAR) + "+" +# endif +# endif +# if defined(XTERM_SCROLLBAR) + "xterm" +# endif +#endif + "," +#if defined(GREEK_SUPPORT) + "Greek," +#endif +#if defined(RXVT_GRAPHICS) + "graphics," +#endif +#if defined(NO_BACKSPACE_KEY) + "no_backspace," +#endif +#if defined(NO_DELETE_KEY) + "no_delete," +#endif +#if !defined(NO_STRINGS) + "strings," +#endif +#if defined(TTY_256COLOR) + "256colour," +#endif +#if defined(NO_RESOURCES) + "NoResources" +#else +# if defined(USE_XGETDEFAULT) + "XGetDefaults" +# else + ".Xdefaults" +# endif +#endif + "\nUsage: "; /* Usage */ + +#define INDENT 18 + +/*{{{ usage: */ +/*----------------------------------------------------------------------*/ +/* EXTPROTO */ +void +rxvt_usage(int type) +{ + unsigned int i, col; + + write(STDERR_FILENO, releasestring, sizeof(releasestring) - 1); + write(STDERR_FILENO, optionsstring, sizeof(optionsstring) - 1); + write(STDERR_FILENO, APL_NAME, sizeof(APL_NAME) - 1); + + switch (type) { + case 0: /* brief listing */ + fprintf(stderr, " [-help] [--help]\n"); + for (col = 1, i = 0; i < optList_size(); i++) + if (optList[i].desc != NULL) { + int len = 0; + + if (!optList_isBool(i)) { + len = optList_strlen(i); + if (len > 0) + len++; /* account for space */ + } +#ifdef DEBUG_STRICT + assert(optList[i].opt != NULL); +#endif + len += 4 + STRLEN(optList[i].opt) + (optList_isBool(i) ? 2: 0); + col += len; + if (col > 79) { /* assume regular width */ + putc('\n', stderr); + col = 1 + len; + } + fprintf(stderr, " [-%s%s", (optList_isBool(i) ? "/+" : ""), + optList[i].opt); + if (optList_strlen(i)) + fprintf(stderr, " %s]", optList[i].arg); + else + fprintf(stderr, "]"); + } + break; + + case 1: /* full command-line listing */ + fprintf(stderr, " [options] [-e command args]\n\n" + "where options include:\n"); + for (i = 0; i < optList_size(); i++) + if (optList[i].desc != NULL) { +#ifdef DEBUG_STRICT + assert(optList[i].opt != NULL); +#endif + fprintf(stderr, " %s%s %-*s%s%s\n", + (optList_isBool(i) ? "-/+" : "-"), optList[i].opt, + (INDENT - STRLEN(optList[i].opt) + + (optList_isBool(i) ? 0 : 2)), + (optList[i].arg ? optList[i].arg : ""), + (optList_isBool(i) ? "turn on/off " : ""), + optList[i].desc); + } + fprintf(stderr, "\n --help to list long-options"); + break; + + case 2: /* full resource listing */ + fprintf(stderr, + " [options] [-e command args]\n\n" + "where resources (long-options) include:\n"); + + for (i = 0; i < optList_size(); i++) + if (optList[i].kw != NULL) + fprintf(stderr, " %s: %*s%s\n", + optList[i].kw, + (INDENT - STRLEN(optList[i].kw)), "", /* XXX */ + (optList_isBool(i) ? "boolean" : optList[i].arg)); +#ifdef KEYSYM_RESOURCE + fprintf(stderr, " " "keysym.sym" ": %*s%s\n", + (INDENT - sizeof("keysym.sym") + 1), "", /* XXX */ + "keysym"); +#endif + fprintf(stderr, "\n -help to list options"); + break; + } + fprintf(stderr, "\n\n"); + exit(EXIT_FAILURE); + /* NOTREACHED */ +} + +/*}}} */ + +/*{{{ get command-line options before getting resources */ +/* EXTPROTO */ +void +rxvt_get_options(pR_ int argc, const char *const *argv) +{ + int i, bad_option = 0; + static const char On[3] = "ON", Off[4] = "OFF"; + + for (i = 1; i < argc; i++) { + unsigned int entry, longopt = 0; + const char *flag, *opt; + + opt = argv[i]; +#ifdef DEBUG_RESOURCES + fprintf(stderr, "argv[%d] = %s: ", i, opt); +#endif + if (*opt == '-') { + flag = On; + if (*++opt == '-') + longopt = *opt++; /* long option */ + } else if (*opt == '+') { + flag = Off; + if (*++opt == '+') + longopt = *opt++; /* long option */ + } else { + bad_option = 1; + rxvt_print_error("bad option \"%s\"", opt); + continue; + } + + if (!STRCMP(opt, "help")) + rxvt_usage(longopt ? 2 : 1); + if (!STRCMP(opt, "h")) + rxvt_usage(0); + + /* feature: always try to match long-options */ + for (entry = 0; entry < optList_size(); entry++) + if ((optList[entry].kw && !STRCMP(opt, optList[entry].kw)) + || (!longopt + && optList[entry].opt && !STRCMP(opt, optList[entry].opt))) + break; + + if (entry < optList_size()) { + if (optList_isReverse(entry)) + flag = flag == On ? Off : On; + if (optList_strlen(entry)) { /* string value */ + const char *str = argv[++i]; + +#ifdef DEBUG_RESOURCES + fprintf(stderr, "string (%s,%s) = ", + optList[entry].opt ? optList[entry].opt : "nil", + optList[entry].kw ? optList[entry].kw : "nil"); +#endif + if (flag == On && str && (optList[entry].doff != -1)) { +#ifdef DEBUG_RESOURCES + fprintf(stderr, "\"%s\"\n", str); +#endif + R->h->rs[optList[entry].doff] = str; + /* + * special cases are handled in main.c:main() to allow + * X resources to set these values before we settle for + * default values + */ + } +#ifdef DEBUG_RESOURCES + else + fprintf(stderr, "???\n"); +#endif + } else { /* boolean value */ +#ifdef DEBUG_RESOURCES + fprintf(stderr, "boolean (%s,%s) = %s\n", + optList[entry].opt, optList[entry].kw, flag); +#endif + if (flag == On) + R->Options |= (optList[entry].flag); + else + R->Options &= ~(optList[entry].flag); + + if (optList[entry].doff != -1) + R->h->rs[optList[entry].doff] = flag; + } + } else +#ifdef KEYSYM_RESOURCE + /* if (!STRNCMP(opt, "keysym.", sizeof("keysym.") - 1)) */ + if (rxvt_Str_match(opt, "keysym.")) { + const char *str = argv[++i]; + + if (str != NULL) + rxvt_parse_keysym(aR_ opt + sizeof("keysym.") - 1, str); + } else +#endif + ; + } + + if (bad_option) + rxvt_usage(0); +} + +/*}}} */ + +#ifndef NO_RESOURCES +/*----------------------------------------------------------------------*/ + +# ifdef KEYSYM_RESOURCE +/* + * Define key from XrmEnumerateDatabase. + * quarks will be something like + * "rxvt" "keysym" "0xFF01" + * value will be a string + */ +/* ARGSUSED */ +/* INTPROTO */ +Bool +rxvt_define_key(XrmDatabase *database __attribute__((unused)), XrmBindingList bindings __attribute__((unused)), XrmQuarkList quarks, XrmRepresentation *type __attribute__((unused)), XrmValue *value, XPointer closure __attribute__((unused))) +{ + dR; + int last; + + for (last = 0; quarks[last] != NULLQUARK; last++) /* look for last quark in list */ + ; + last--; + rxvt_parse_keysym(aR_ XrmQuarkToString(quarks[last]), (char *)value->addr); + return False; +} + +/* + * look for something like this (XK_Delete) + * rxvt*keysym.0xFFFF: "\177" + * + * arg will be + * NULL for ~/.Xdefaults and + * non-NULL for command-line options (need to allocate) + */ +#define NEWARGLIM 500 /* `reasonable' size */ +/* INTPROTO */ +int +rxvt_parse_keysym(pR_ const char *str, const char *arg) +{ + int n, sym; + char *key_string, *newarg = NULL; + char newargstr[NEWARGLIM]; + + if (arg == NULL) { + if ((n = rxvt_Str_match(str, "keysym.")) == 0) + return 0; + str += n; /* skip `keysym.' */ + } +/* some scanf() have trouble with a 0x prefix */ + if (isdigit(str[0])) { + if (str[0] == '0' && toupper(str[1]) == 'X') + str += 2; + if (arg) { + if (sscanf(str, (STRCHR(str, ':') ? "%x:" : "%x"), &sym) != 1) + return -1; + } else { + if (sscanf(str, "%x:", &sym) != 1) + return -1; + + /* cue to ':', it's there since sscanf() worked */ + STRNCPY(newargstr, STRCHR(str, ':') + 1, NEWARGLIM - 1); + newargstr[NEWARGLIM - 1] = '\0'; + newarg = newargstr; + } + } else { + /* + * convert keysym name to keysym number + */ + STRNCPY(newargstr, str, NEWARGLIM - 1); + newargstr[NEWARGLIM - 1] = '\0'; + if (arg == NULL) { + if ((newarg = STRCHR(newargstr, ':')) == NULL) + return -1; + *newarg++ = '\0'; /* terminate keysym name */ + } + if ((sym = XStringToKeysym(newargstr)) == None) + return -1; + } + + if (sym < 0xFF00 || sym > 0xFFFF) /* we only do extended keys */ + return -1; + sym &= 0xFF; + if (R->h->Keysym_map[sym] != NULL) /* already set ? */ + return -1; + + if (newarg == NULL) { + STRNCPY(newargstr, arg, NEWARGLIM - 1); + newargstr[NEWARGLIM - 1] = '\0'; + newarg = newargstr; + } + rxvt_Str_trim(newarg); + if (*newarg == '\0' || (n = rxvt_Str_escaped(newarg)) == 0) + return -1; + MIN_IT(n, 255); + key_string = (char *)rxvt_malloc((n + 1) * sizeof(char)); + + key_string[0] = n; + STRNCPY(key_string + 1, newarg, n); + R->h->Keysym_map[sym] = (unsigned char *)key_string; + + return 1; +} + +# endif /* KEYSYM_RESOURCE */ + +# ifndef USE_XGETDEFAULT +/*{{{ rxvt_get_xdefaults() */ +/* + * the matching algorithm used for memory-save fake resources + */ +/* INTPROTO */ +void +rxvt_get_xdefaults(pR_ FILE *stream, const char *name) +{ + unsigned int len; + char *str, buffer[256]; + + if (stream == NULL) + return; + len = STRLEN(name); + while ((str = fgets(buffer, sizeof(buffer), stream)) != NULL) { + unsigned int entry, n; + + while (*str && isspace(*str)) + str++; /* leading whitespace */ + + if ((str[len] != '*' && str[len] != '.') + || (len && STRNCMP(str, name, len))) + continue; + str += (len + 1); /* skip `name*' or `name.' */ + +# ifdef KEYSYM_RESOURCE + if (!rxvt_parse_keysym(aR_ str, NULL)) +# endif /* KEYSYM_RESOURCE */ + for (entry = 0; entry < optList_size(); entry++) { + const char *kw = optList[entry].kw; + + if (kw == NULL) + continue; + n = STRLEN(kw); + if (str[n] == ':' && rxvt_Str_match(str, kw)) { + /* skip `keyword:' */ + str += (n + 1); + rxvt_Str_trim(str); + n = STRLEN(str); + if (n && R->h->rs[optList[entry].doff] == NULL) { + /* not already set */ + int s; + char *p = (char *)rxvt_malloc((n + 1) * sizeof(char)); + + STRCPY(p, str); + R->h->rs[optList[entry].doff] = p; + if (optList_isBool(entry)) { + s = STRCASECMP(str, "TRUE") == 0 + || STRCASECMP(str, "YES") == 0 + || STRCASECMP(str, "ON") == 0 + || STRCASECMP(str, "1") == 0; + if (optList_isReverse(entry)) + s = !s; + if (s) + R->Options |= (optList[entry].flag); + else + R->Options &= ~(optList[entry].flag); + } + } + break; + } + } + } + rewind(stream); +} + +/*}}} */ +# endif /* ! USE_XGETDEFAULT */ +#endif /* NO_RESOURCES */ + +/*{{{ read the resources files */ +/* + * using XGetDefault() or the hand-rolled replacement + */ +/* ARGSUSED */ +/* EXTPROTO */ +void +rxvt_extract_resources(pR_ Display *display __attribute__((unused)), const char *name) +{ +#ifndef NO_RESOURCES + +# if defined XAPPLOADDIR +# if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE) + /* Compute the path of the possibly available localized Rxvt file */ + char *localepath = NULL; + + if (R->h->locale != NULL) { /* XXX: must limit length of string */ + localepath = (char *)rxvt_malloc(256); + sprintf(localepath, XAPPLOADDIRLOCALE "/" APL_SUBCLASS, + (int)(258 - sizeof(XAPPLOADDIRLOCALE) - sizeof(APL_SUBCLASS)), + R->h->locale); /* 258 = 255 + 4 (-.*s) - 1 (/) */ + } + + { +# endif +# endif + +# ifdef USE_XGETDEFAULT +/* + * get resources using the X library function + */ + int entry; + +# ifdef XrmEnumOneLevel + int i; + char *displayResource, *xe; + XrmName name_prefix[3]; + XrmClass class_prefix[3]; + XrmDatabase database, rdb1; + char fname[1024]; + + XrmInitialize(); + database = NULL; + +/* Get any Xserver defaults */ + + displayResource = XResourceManagerString(display); + if (displayResource != NULL) + database = XrmGetStringDatabase(displayResource); + +# ifdef HAVE_EXTRA_XRESOURCE_FILES +/* Add in ~/.Xdefaults or ~/.Xresources */ + { + char *ptr; + + if ((ptr = (char *)getenv("HOME")) == NULL) + ptr = "."; + + for (i = 0; i < (sizeof(xnames) / sizeof(xnames[0])); i++) { + sprintf(fname, "%-.*s/%s", sizeof(fname) - STRLEN(xnames[i]) - 2, + ptr, xnames[i]); + if ((rdb1 = XrmGetFileDatabase(fname)) != NULL) { + XrmMergeDatabases(rdb1, &database); +# ifndef HAVE_BOTH_XRESOURCE_FILES + break; +# endif + } + } + } +# endif + +/* Add in XENVIRONMENT file */ + + if ((xe = (char *)getenv("XENVIRONMENT")) != NULL + && (rdb1 = XrmGetFileDatabase(xe)) != NULL) + XrmMergeDatabases(rdb1, &database); + +/* Add in Rxvt file */ +# if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE) + if (localepath == NULL || (rdb1 = XrmGetFileDatabase(localepath)) == NULL) +# endif + rdb1 = XrmGetFileDatabase(XAPPLOADDIR "/" APL_SUBCLASS); + if (rdb1 != NULL) + XrmMergeDatabases(rdb1, &database); + +/* Add in $XAPPLRESDIR/Rxvt only; not bothering with XUSERFILESEARCHPATH */ + if ((xe = (char *)getenv("XAPPLRESDIR")) != NULL) { + sprintf(fname, "%-.*s/" APL_SUBCLASS, sizeof(fname) + - sizeof(APL_SUBCLASS) - 2, xe); + if ((rdb1 = XrmGetFileDatabase(fname)) != NULL) + XrmMergeDatabases(rdb1, &database); + } + + XrmSetDatabase(display, database); +# endif + +/* + * Query resources for options that affect us + */ + for (entry = 0; entry < optList_size(); entry++) { + int s; + char *p, *p0; + const char *kw = optList[entry].kw; + + if (kw == NULL || R->h->rs[optList[entry].doff] != NULL) + continue; /* previously set */ + + p = XGetDefault(display, name, kw); + p0 = XGetDefault(display, "!INVALIDPROGRAMMENAMEDONTMATCH!", kw); + if (p == NULL || (p0 && STRCMP(p, p0) == 0)) { + p = XGetDefault(display, APL_SUBCLASS, kw); + if (p == NULL || (p0 && STRCMP(p, p0) == 0)) + p = XGetDefault(display, APL_CLASS, kw); + } + if (p == NULL && p0) + p = p0; + if (p) { + R->h->rs[optList[entry].doff] = p; + + if (optList_isBool(entry)) { + s = STRCASECMP(p, "TRUE") == 0 + || STRCASECMP(p, "YES") == 0 + || STRCASECMP(p, "ON") == 0 + || STRCASECMP(p, "1") == 0; + if (optList_isReverse(entry)) + s = !s; + if (s) + R->Options |= (optList[entry].flag); + else + R->Options &= ~(optList[entry].flag); + } + } + } + +/* + * [R5 or later]: enumerate the resource database + */ +# ifdef XrmEnumOneLevel +# ifdef KEYSYM_RESOURCE + name_prefix[0] = XrmStringToName(name); + name_prefix[1] = XrmStringToName("keysym"); + name_prefix[2] = NULLQUARK; + class_prefix[0] = XrmStringToName(APL_SUBCLASS); + class_prefix[1] = XrmStringToName("Keysym"); + class_prefix[2] = NULLQUARK; +/* XXX: Need to check sizeof(rxvt_t) == sizeof(XPointer) */ + XrmEnumerateDatabase(XrmGetDatabase(display), name_prefix, class_prefix, + XrmEnumOneLevel, rxvt_define_key, NULL); + name_prefix[0] = XrmStringToName(APL_CLASS); + name_prefix[1] = XrmStringToName("keysym"); + class_prefix[0] = XrmStringToName(APL_CLASS); + class_prefix[1] = XrmStringToName("Keysym"); +/* XXX: Need to check sizeof(rxvt_t) == sizeof(XPointer) */ + XrmEnumerateDatabase(XrmGetDatabase(display), name_prefix, class_prefix, + XrmEnumOneLevel, rxvt_define_key, NULL); +# endif +# endif + +# else /* USE_XGETDEFAULT */ +/* get resources the hard way, but save lots of memory */ + FILE *fd = NULL; + char *home; + + if ((home = getenv("HOME")) != NULL) { + unsigned int i, len = STRLEN(home) + 2; + char *f = NULL; + + for (i = 0; i < (sizeof(xnames) / sizeof(xnames[0])); i++) { + f = (char *)rxvt_realloc(f, (len + STRLEN(xnames[i])) * sizeof(char)); + + sprintf(f, "%s/%s", home, xnames[i]); + + if ((fd = fopen(f, "r")) != NULL) + break; + } + free(f); + } +/* + * The normal order to match resources is the following: + * @ global resources (partial match, ~/.Xdefaults) + * @ application file resources (XAPPLOADDIR/Rxvt) + * @ class resources (~/.Xdefaults) + * @ private resources (~/.Xdefaults) + * + * However, for the hand-rolled resources, the matching algorithm + * checks if a resource string value has already been allocated + * and won't overwrite it with (in this case) a less specific + * resource value. + * + * This avoids multiple allocation. Also, when we've called this + * routine command-line string options have already been applied so we + * needn't to allocate for those resources. + * + * So, search in resources from most to least specific. + * + * Also, use a special sub-class so that we can use either or both of + * "XTerm" and "Rxvt" as class names. + */ + + rxvt_get_xdefaults(aR_ fd, name); + rxvt_get_xdefaults(aR_ fd, APL_SUBCLASS); + +# if defined(XAPPLOADDIR) && defined(USE_XAPPLOADDIR) + { + FILE *ad = NULL; + +# if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE) + if (localepath == NULL || (ad = fopen(localepath, "r")) == NULL) +# endif + ad = fopen(XAPPLOADDIR "/" APL_SUBCLASS, "r"); + if (ad != NULL) { + rxvt_get_xdefaults(aR_ ad, APL_SUBCLASS); + rxvt_get_xdefaults(aR_ ad, ""); + fclose(ad); + } + } +# endif /* XAPPLOADDIR */ + + rxvt_get_xdefaults(aR_ fd, APL_CLASS); + rxvt_get_xdefaults(aR_ fd, ""); /* partial match */ + if (fd != NULL) + fclose(fd); +# endif /* USE_XGETDEFAULT */ + +# if defined XAPPLOADDIR +# if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE) + } + + /* Free the path of the possibly available localized Rxvt file */ + free(localepath); +# endif +# endif + +#endif /* NO_RESOURCES */ + +/* + * even without resources, at least do this setup for command-line + * options and command-line long options + */ +#ifdef MULTICHAR_SET + rxvt_set_multichar_encoding(aR_ R->h->rs[Rs_multichar_encoding]); +#endif +#ifdef GREEK_SUPPORT +/* this could be a function in grkelot.c */ +/* void set_greek_keyboard (const char * str); */ + if (R->h->rs[Rs_greek_keyboard]) { + if (!STRCMP(R->h->rs[Rs_greek_keyboard], "iso")) + greek_setmode(GREEK_ELOT928); /* former -grk9 */ + else if (!STRCMP(R->h->rs[Rs_greek_keyboard], "ibm")) + greek_setmode(GREEK_IBM437); /* former -grk4 */ + } + { + KeySym sym; + + if (R->h->rs[Rs_greektoggle_key] + && ((sym = XStringToKeysym(R->h->rs[Rs_greektoggle_key])) != 0)) + R->h->ks_greekmodeswith = sym; + } +#endif /* GREEK_SUPPORT */ + +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) + { + KeySym sym; + + if (R->h->rs[Rs_bigfont_key] + && ((sym = XStringToKeysym(R->h->rs[Rs_bigfont_key])) != 0)) + R->h->ks_bigfont = sym; + if (R->h->rs[Rs_smallfont_key] + && ((sym = XStringToKeysym(R->h->rs[Rs_smallfont_key])) != 0)) + R->h->ks_smallfont = sym; + } +#endif +} + +/*}}} */ +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/xpm.C b/src/xpm.C new file mode 100644 index 00000000..be94d503 --- /dev/null +++ b/src/xpm.C @@ -0,0 +1,361 @@ +/*--------------------------------*-C-*---------------------------------* + * File: xpm.c + *----------------------------------------------------------------------* + * $Id: xpm.C,v 1.1 2003-11-24 17:28:08 pcg Exp $ + * + * All portions of code are copyright by their respective author/s. + * Copyright (c) 1997 Carsten Haitzler + * Copyright (c) 1997,1998 Oezguer Kesim + * Copyright (c) 1998-2001 Geoff Wing + * + * 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 */ -- 2.34.1
) ARG1 \ + IFZERO(XXcellcounter)\ + (htmlcommand(
))\ + ()\ + htmlcommand(
text text
) ARG2 \ + IFZERO(XXcellcounter)\ + (htmlcommand(
))\ + ()\ + htmlcommand(