summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadrul Habib Chowdhury <sadrul@users.sourceforge.net>2010-03-16 10:31:46 -0400
committerSadrul Habib Chowdhury <sadrul@users.sourceforge.net>2010-03-16 10:31:46 -0400
commitad5e07310ad8474358334fcff8de86d0b9ab6cad (patch)
treef46a86bf622cdc7c711d3428a9a292fde584d2ba
parentf823083eee6bb3bf4c52cc2b32b1617bf291b1c0 (diff)
parent8a6abbab0161e6df1cea2ae0033a4c7f4a47f8e9 (diff)
downloadscreen-cmd-alias.tar.gz
Merge branch 'master' into cmd-aliascmd-alias
-rw-r--r--src/ChangeLog115
-rw-r--r--src/HACKING2
-rw-r--r--src/INSTALL2
-rw-r--r--src/Makefile.in85
-rw-r--r--src/acconfig.h13
-rw-r--r--src/acls.c7
-rw-r--r--src/acls.h2
-rw-r--r--src/ansi.c20
-rw-r--r--src/ansi.h4
-rw-r--r--src/attacher.c98
-rw-r--r--src/braille.c2
-rw-r--r--src/braille.h2
-rw-r--r--src/canvas.c916
-rw-r--r--src/canvas.h101
-rw-r--r--src/comm.c30
-rw-r--r--src/comm.sh6
-rw-r--r--src/configure.in8
-rw-r--r--src/display.c1429
-rw-r--r--src/display.h93
-rw-r--r--src/doc/screen.1296
-rw-r--r--src/doc/screen.texinfo716
-rw-r--r--src/extern.h43
-rw-r--r--src/fileio.c50
-rw-r--r--src/help.c832
-rw-r--r--src/image.h13
-rw-r--r--src/input.c128
-rw-r--r--src/layer.c250
-rw-r--r--src/layer.h64
-rw-r--r--src/layout.c367
-rw-r--r--src/layout.h57
-rw-r--r--src/list_display.c243
-rw-r--r--src/list_generic.c486
-rw-r--r--src/list_generic.h73
-rw-r--r--src/list_window.c678
-rw-r--r--src/loadav.c2
-rw-r--r--src/logfile.c2
-rw-r--r--src/logfile.h4
-rw-r--r--src/mark.c147
-rw-r--r--src/mark.h4
-rw-r--r--src/misc.c48
-rw-r--r--src/nethack.c6
-rw-r--r--src/os.h11
-rw-r--r--src/osdef.h.in2
-rw-r--r--src/patchlevel.h6
-rw-r--r--src/process.c757
-rw-r--r--src/pty.c2
-rw-r--r--src/putenv.c2
-rw-r--r--src/resize.c211
-rw-r--r--src/sched.c2
-rw-r--r--src/sched.h4
-rw-r--r--src/screen.c181
-rw-r--r--src/screen.h24
-rw-r--r--src/search.c2
-rw-r--r--src/socket.c104
-rw-r--r--src/teln.c2
-rw-r--r--src/term.c8
-rw-r--r--src/termcap.c19
-rw-r--r--src/terminfo/screeninfo.src7
-rw-r--r--src/tty.sh2
-rw-r--r--src/utmp.c4
-rw-r--r--src/viewport.c140
-rw-r--r--src/viewport.h51
-rw-r--r--src/window.c103
-rw-r--r--src/window.h32
64 files changed, 6104 insertions, 3016 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 2256d80..df04dca 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,118 @@
+Version 4.1.0 (??/??/20??):
+ New Commands:
+ * 'unbindall' to unbind all commands
+ * 'up', 'down', 'left', 'right' sub-commands for 'focus'
+ * 'rendition' to specify rendition to use in caption/hardstatus for
+ window-names that have bell/monitor/silence/so turned on.
+ * 'layout', with the following sub-commands
+ - 'title'
+ - 'number'
+ - 'autosave' ('autosave on' or 'autosave off')
+ - 'new'
+ - 'save' ('save <name>')
+ - 'select'
+ - 'next'
+ - 'prev'
+ - 'attach'
+ - 'show'
+ - 'remove'
+ - 'dump'
+ * 'group' for moving window(s) into a group.
+ * 'defmousetrack' and 'mousetrack', to turn on/off mouse-tracking for
+ displays. It's turned off by default. With mouse-tracking turned on, it's
+ possible to switch to a region ('focus') using mouse clicks. It's also
+ possible to select a text region in copy-mode using a mouse click to place
+ a mark and the scroll wheel to scroll through the buffer. Additional
+ features might be to allow clicking on window-titles in the caption to
+ switch to that window.
+
+ Changed Commands:
+ * '-v' parameter to 'split' command for vertical splits.
+ * 'sorendition' deprecated in favour of 'rendition so'.
+ * 'digraph' can take a second parameter to specify custom digraphs. For
+ example,
+ 'digraph >= ≥' or 'digraph >= U+2265'
+ Using '0' as the second parameter will remove the digraph.
+ * 'stuff' will prompt for input if there's nothing to stuff.
+ * The argument to ":number" can be prefixed with '+' or '-' to use it as a
+ relative argument.
+ * '-g' parameter to 'windowlist' to show nested list of windows.
+ * '//group' parameter to 'screen' to create a grouped window.
+ * 'blankerprg' shows the currently set command on no argument.
+ * 'maxwin' can now be used to increase the number of maximum windows.
+
+ .screenrc:
+ * $PID expands to the PID of the screen session.
+ * $STY expands to the session name.
+ * Tilde-expansion in pathnames (e.g. for the 'source' command)
+ * C-style escapes can be used (e.g. "\n" to get a newline with 'stuff')
+ * '%p' in caption/hardstatus string expands to the PID of the backend, and
+ '%+p' expands to the PID of the frontend (display).
+ * '%S' in caption/hardstatus string expands to the session name.
+ * '%P' in the caption string evaluates to true if the region is in copy mode.
+
+ Window List:
+ * Nested views when there are window groups (with 'windowlist -g').
+ * Press 'm' to toggle the most-recent view.
+ * Press 'g' to toggle nestedness.
+ * Press 'a' to view all windows in the list.
+ * Press '/' to search in the list.
+ * Press ',' and '.' to re-order windows in the list.
+ * Press 'K' to kill a window (requires confirmation).
+
+ Display List:
+ * Press 'd' to detach a display, 'D' to power-detach.
+
+ Others:
+ * Start using 'ChangeLog' for logging changes again.
+ * Terminfo update for 256-color support.
+ * Multiple input history (partially from Romain Francoise).
+ * vi-like fFtT;, searching in copy mode.
+ * In copy mode, search in reverse direction when 'N' is pressed.
+ * Tab-completion for command input.
+ * Some more readline-like bindings in input mode (e.g. ^W, ^D, ^P, ^N etc.)
+ * Fix displaying unicode characters in the caption/hardstatus on UTF8 locale.
+ * A revamped displays list (for 'displays' command)
+ * Increased default maximum number of windows from 40 to 100.
+ * Increased number color/attribute changes in caption/hardstatus string from 16 to 256.
+ * Some commands can be remotely queried using the -Q command-line flag.
+
+ In-Progress:
+ * Scripting support (thanks to Google Summer of Code 2009 project by Rui Guo)
+
+ Developers:
+ * Juergen Weigert <jw@suse.de>
+ * Michael Schroeder <mls@suse.de>
+ * Micah Cowan <micah@cowan.name>
+ * Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
+
+ Contributors:
+ * Clavelito <maromomo@hotmail.com>
+ * Dick <dick@mrns.nl>
+ * Gabriel <g2p.code@gmail.com>
+ * Benjamin Andresen <bandresen@gmail.com>
+ * Takeshi Banse <takebi@laafc.net>
+ * Maarten Billemont <lhunath@gmail.com>
+ * Curtis Brown <mrbrown8@juno.com>
+ * Cyril Brulebois <kibi@debian.org>
+ * Trent W Buck <trentbuck@gmail.com>
+ * Stephane Chazelas <stephane_chazelas@yahoo.fr>
+ * Kees Cook <kees@ubuntu.com>
+ * Thomas Dickey <tom@invisible-island.net>
+ * Christian Ebert <blacktrash@gmx.net>
+ * Geraint Edwards <gedge-lists-screen@yadn.org>
+ * Romain Francoise <romain@orebokech.com>
+ * Emanuele Giaquinta <e.giaquinta@glauco.it>
+ * Yi-Hsuan Hsin <mhsin@mhsin.org>
+ * Chris Jones <cjns1989@gmail.com>
+ * Steve Kemp <steve@steve.org.uk>
+ * Ryan Niebur <ryan@debian.org>
+ * Jan Christoph Nordholz <hesso@pool.math.tu-berlin.de>
+ * William Pursell <bill.pursell@gmail.com>
+ * Michael Scherer <misc@mandriva.org>
+ * Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+ * Peter Teichman <peter@teichman.org>
+
30.10.94
This is a quick overview of screen's life story. But it is not up
diff --git a/src/HACKING b/src/HACKING
index 3d41cf4..b78d40f 100644
--- a/src/HACKING
+++ b/src/HACKING
@@ -35,3 +35,5 @@ WIP notes on hacking the Screen source.
window list: WListProcess
command input line: InpProcess
+* Handling string escapes (in hardstatus and the like), such as %w or
+ %{= bw}, is done in screen.c, MakeWinMsgEv().
diff --git a/src/INSTALL b/src/INSTALL
index 17c2212..f9750e6 100644
--- a/src/INSTALL
+++ b/src/INSTALL
@@ -44,7 +44,7 @@ Run 'make'. Screen should compile without too many warnings :)
The creation of term.h, comm.h, tty.c or osdef.h may fail on some machines
for some odd reason. (E.g. the sed under SCO-unix is known to be
case-insensitive and breaks term.h.) If so, please mail a short description
-of the problem to screen@uni-erlangen.de and use the files ending in .dist
+of the problem to screen-devel@gnu.org and use the files ending in .dist
as a replacement (or in case of osdef.h retry with an empty file).
You can then try 'make install' (if you dare).
diff --git a/src/Makefile.in b/src/Makefile.in
index c551067..2ae57d0 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -61,12 +61,14 @@ CFILES= screen.c ansi.c fileio.c mark.c misc.c resize.c socket.c \
search.c tty.c term.c window.c utmp.c loadav.c putenv.c help.c \
termcap.c input.c attacher.c pty.c process.c display.c comm.c \
kmapdef.c acls.c braille.c braille_tsi.c logfile.c layer.c \
- sched.c teln.c nethack.c encoding.c
+ sched.c teln.c nethack.c encoding.c canvas.c layout.c viewport.c \
+ list_display.c list_generic.c list_window.c
OFILES= screen.o ansi.o fileio.o mark.o misc.o resize.o socket.o \
search.o tty.o term.o window.o utmp.o loadav.o putenv.o help.o \
termcap.o input.o attacher.o pty.o process.o display.o comm.o \
kmapdef.o acls.o braille.o braille_tsi.o logfile.o layer.o \
- sched.o teln.o nethack.o encoding.o
+ list_generic.o list_display.o list_window.o \
+ sched.o teln.o nethack.o encoding.o canvas.o layout.o viewport.o
all: screen
@@ -273,66 +275,79 @@ depend.in: $(CFILES) term.h
###############################################################################
### Dependencies:
-screen.o: screen.c config.h screen.h os.h osdef.h ansi.h acls.h \
+screen.o: layout.h viewport.h canvas.h screen.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h braille.h \
patchlevel.h logfile.h extern.h
-ansi.o: ansi.c config.h screen.h os.h osdef.h ansi.h acls.h \
+ansi.o: layout.h viewport.h canvas.h ansi.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h braille.h extern.h \
logfile.h
-fileio.o: fileio.c config.h screen.h os.h osdef.h ansi.h acls.h \
+fileio.o: layout.h viewport.h canvas.h fileio.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-mark.o: mark.c config.h screen.h os.h osdef.h ansi.h acls.h \
+mark.o: layout.h viewport.h canvas.h mark.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h mark.h extern.h
-misc.o: misc.c config.h screen.h os.h osdef.h ansi.h acls.h \
+misc.o: layout.h viewport.h canvas.h misc.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-resize.o: resize.c config.h screen.h os.h osdef.h ansi.h acls.h \
+resize.o: layout.h viewport.h canvas.h resize.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-socket.o: socket.c config.h screen.h os.h osdef.h ansi.h acls.h \
+socket.o: layout.h viewport.h canvas.h socket.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-search.o: search.c config.h screen.h os.h osdef.h ansi.h acls.h \
+search.o: layout.h viewport.h canvas.h search.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h mark.h extern.h
-tty.o: tty.c config.h screen.h os.h osdef.h ansi.h acls.h comm.h \
+tty.o: layout.h viewport.h canvas.h tty.c config.h screen.h os.h osdef.h ansi.h acls.h comm.h \
layer.h term.h image.h display.h window.h extern.h
-term.o: term.c term.h
-window.o: window.c config.h screen.h os.h osdef.h ansi.h acls.h \
+term.o: layout.h viewport.h canvas.h term.c term.h
+window.o: layout.h viewport.h canvas.h window.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h logfile.h
-utmp.o: utmp.c config.h screen.h os.h osdef.h ansi.h acls.h \
+utmp.o: layout.h viewport.h canvas.h utmp.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-loadav.o: loadav.c config.h screen.h os.h osdef.h ansi.h acls.h \
+loadav.o: layout.h viewport.h canvas.h loadav.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-putenv.o: putenv.c config.h
-help.o: help.c config.h screen.h os.h osdef.h ansi.h acls.h \
+putenv.o: layout.h viewport.h canvas.h putenv.c config.h
+help.o: layout.h viewport.h canvas.h help.c config.h screen.h os.h osdef.h ansi.h acls.h \
+ comm.h layer.h term.h image.h display.h window.h extern.h list_generic.h
+termcap.o: layout.h viewport.h canvas.h termcap.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-termcap.o: termcap.c config.h screen.h os.h osdef.h ansi.h acls.h \
+input.o: layout.h viewport.h canvas.h input.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-input.o: input.c config.h screen.h os.h osdef.h ansi.h acls.h \
- comm.h layer.h term.h image.h display.h window.h extern.h
-attacher.o: attacher.c config.h screen.h os.h osdef.h ansi.h \
+attacher.o: layout.h viewport.h canvas.h attacher.c config.h screen.h os.h osdef.h ansi.h \
acls.h comm.h layer.h term.h image.h display.h window.h extern.h
-pty.o: pty.c config.h screen.h os.h osdef.h ansi.h acls.h comm.h \
+pty.o: layout.h viewport.h canvas.h pty.c config.h screen.h os.h osdef.h ansi.h acls.h comm.h \
layer.h term.h image.h display.h window.h extern.h
-process.o: process.c config.h screen.h os.h osdef.h ansi.h acls.h \
+process.o: layout.h viewport.h canvas.h process.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h logfile.h
-display.o: display.c config.h screen.h os.h osdef.h ansi.h acls.h \
+display.o: layout.h viewport.h canvas.h display.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h braille.h
-comm.o: comm.c config.h acls.h comm.h
-kmapdef.o: kmapdef.c config.h
-acls.o: acls.c config.h screen.h os.h osdef.h ansi.h acls.h comm.h \
+canvas.o: layout.h viewport.h canvas.h canvas.c config.h screen.h os.h osdef.h ansi.h acls.h \
+ comm.h layer.h term.h image.h display.h window.h extern.h \
+ braille.h
+comm.o: layout.h viewport.h canvas.h comm.c config.h acls.h comm.h
+kmapdef.o: layout.h viewport.h canvas.h kmapdef.c config.h
+acls.o: layout.h viewport.h canvas.h acls.c config.h screen.h os.h osdef.h ansi.h acls.h comm.h \
layer.h term.h image.h display.h window.h extern.h
-braille.o: braille.c config.h screen.h os.h osdef.h ansi.h acls.h \
+braille.o: layout.h viewport.h canvas.h braille.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h braille.h
-braille_tsi.o: braille_tsi.c config.h screen.h os.h osdef.h ansi.h \
+braille_tsi.o: layout.h viewport.h canvas.h braille_tsi.c config.h screen.h os.h osdef.h ansi.h \
acls.h comm.h layer.h term.h image.h display.h window.h extern.h \
braille.h
-logfile.o: logfile.c config.h screen.h os.h osdef.h ansi.h acls.h \
+logfile.o: layout.h viewport.h canvas.h logfile.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h logfile.h
-layer.o: layer.c config.h screen.h os.h osdef.h ansi.h acls.h \
+layer.o: layout.h viewport.h canvas.h layer.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-sched.o: sched.c config.h screen.h os.h osdef.h ansi.h acls.h \
+sched.o: layout.h viewport.h canvas.h sched.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h logfile.h
-teln.o: teln.c config.h screen.h os.h osdef.h ansi.h acls.h \
+teln.o: layout.h viewport.h canvas.h teln.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-nethack.o: nethack.c config.h screen.h os.h osdef.h ansi.h acls.h \
+nethack.o: layout.h viewport.h canvas.h nethack.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
-encoding.o: encoding.c config.h screen.h os.h osdef.h ansi.h acls.h \
+encoding.o: layout.h viewport.h canvas.h encoding.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
+layout.o: layout.h viewport.h canvas.h layout.c config.h screen.h os.h osdef.h ansi.h acls.h \
+ comm.h layer.h term.h image.h display.h window.h extern.h \
+ braille.h
+viewport.o: layout.h viewport.h canvas.h viewport.c config.h screen.h os.h osdef.h ansi.h acls.h \
+ comm.h layer.h term.h image.h display.h window.h extern.h \
+ braille.h
+list_generic.o: list_generic.h list_generic.c layer.h
+list_display.o: list_generic.h list_display.c layer.h
+list_window.o: list_generic.h list_window.c window.h layer.h
+
diff --git a/src/acconfig.h b/src/acconfig.h
index bc324d5..2e46985 100644
--- a/src/acconfig.h
+++ b/src/acconfig.h
@@ -19,7 +19,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
@@ -35,7 +35,7 @@
* Maximum of simultaneously allowed windows per screen session.
*/
#ifndef MAXWIN
-# define MAXWIN 40
+# define MAXWIN 100
#endif
/*
@@ -445,6 +445,11 @@
#undef HAVE_SETEUID
/*
+ * execvpe is now defined in some systems.
+ */
+#undef HAVE_EXECVPE
+
+/*
* If you want the "time" command to display the current load average
* define LOADAV. Maybe you must install screen with the needed
* privileges to read /dev/kmem.
@@ -521,12 +526,12 @@
#undef USESETENV
/*
- * If setenv() takes 3 arguments sefine HAVE_SETENV_3
+ * If setenv() takes 3 arguments define HAVE_SETENV_3
*/
#undef HAVE_SETENV_3
/*
- * If setenv() takes 2 arguments sefine HAVE_SETENV_2
+ * If setenv() takes 2 arguments define HAVE_SETENV_2
*/
#undef HAVE_SETENV_2
diff --git a/src/acls.c b/src/acls.c
index 02b182b..e728bb8 100644
--- a/src/acls.c
+++ b/src/acls.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -26,10 +26,9 @@
****************************************************************
*/
-#include <sys/types.h>
-
#include "config.h"
+#include <sys/types.h>
/* XXX: WHY IS THIS HERE?? :XXX */
@@ -56,7 +55,7 @@
************************************************************************/
extern struct comm comms[];
-extern struct win *windows, *wtab[];
+extern struct win *windows, **wtab;
extern char NullStr[];
extern char SockPath[];
extern struct display *display, *displays;
diff --git a/src/acls.h b/src/acls.h
index a62933e..907e953 100644
--- a/src/acls.h
+++ b/src/acls.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/ansi.c b/src/ansi.c
index 2ac0f60..b75d14f 100644
--- a/src/ansi.c
+++ b/src/ansi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -78,8 +78,10 @@ struct mchar mchar_null;
struct mchar mchar_blank = {' ' /* , 0, 0, ... */};
struct mchar mchar_so = {' ', A_SO /* , 0, 0, ... */};
+int renditions[NUM_RENDS] = {65529 /* =ub */, 65531 /* =b */, 65533 /* =u */ };
+
/* keep string_t and string_t_string in sync! */
-static char *string_t_string[] =
+static char *string_t_string[] =
{
"NONE",
"DCS", /* Device control string */
@@ -320,7 +322,7 @@ register int len;
curr->w_monitor = MON_FOUND;
}
- if (cols && rows)
+ if (cols > 0 && rows > 0)
{
do
{
@@ -1528,7 +1530,7 @@ StringEnd()
}
#endif
#ifdef RXVT_OSC
- if (typ == 0 || typ == 1 || typ == 20 || typ == 39 || typ == 49)
+ if (typ == 0 || typ == 1 || typ == 2 || typ == 20 || typ == 39 || typ == 49)
{
int typ2;
typ2 = typ / 10;
@@ -1538,7 +1540,7 @@ StringEnd()
{
strncpy(curr->w_xtermosc[typ2], p, sizeof(curr->w_xtermosc[typ2]) - 1);
curr->w_xtermosc[typ2][sizeof(curr->w_xtermosc[typ2]) - 1] = 0;
-
+
for (display = displays; display; display = display->d_next)
{
if (!D_CXT)
@@ -1672,7 +1674,7 @@ PrintFlush()
AddCStr(D_PO);
AddStrn(curr->w_string, curr->w_stringp - curr->w_string);
AddCStr(D_PF);
- Flush();
+ Flush(3);
}
curr->w_stringp = curr->w_string;
}
@@ -2933,7 +2935,7 @@ char *str;
extern struct layer *flayer;
struct layer *oldflayer = flayer;
flayer = &p->w_layer;
- LMsg(err, str);
+ LMsg(err, "%s", str);
flayer = oldflayer;
}
@@ -3068,7 +3070,7 @@ int what;
p = D_fore;
if (inhstr || (inhstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
RefreshHStatus();
- if (ox != -1 && ox != -1)
+ if (ox != -1 && oy != -1)
GotoPos(ox, oy);
}
display = olddisplay;
@@ -3100,7 +3102,7 @@ int what;
}
if (got && inhstr && p == D_fore)
RefreshHStatus();
- if (ox != -1 && ox != -1)
+ if (ox != -1 && oy != -1)
GotoPos(ox, oy);
}
display = olddisplay;
diff --git a/src/ansi.h b/src/ansi.h
index cada63a..72992b4 100644
--- a/src/ansi.h
+++ b/src/ansi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
#define NATTR 6
diff --git a/src/attacher.c b/src/attacher.c
index 1866582..370d594 100644
--- a/src/attacher.c
+++ b/src/attacher.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -26,12 +26,12 @@
****************************************************************
*/
+#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <signal.h>
-#include "config.h"
#include "screen.h"
#include "extern.h"
@@ -51,9 +51,7 @@ static void screen_builtin_lck __P((void));
#ifdef DEBUG
static sigret_t AttacherChld __P(SIGPROTOARG);
#endif
-#ifdef MULTIUSER
static sigret_t AttachSigCont __P(SIGPROTOARG);
-#endif
extern int real_uid, real_gid, eff_uid, eff_gid;
extern char *SockName, *SockMatch, SockPath[];
@@ -75,7 +73,6 @@ static int multipipe[2];
#endif
-#ifdef MULTIUSER
static int ContinuePlease;
static sigret_t
@@ -85,8 +82,22 @@ AttachSigCont SIGDEFARG
ContinuePlease = 1;
SIGRETURN;
}
-#endif
+static int QueryResult;
+
+static sigret_t
+QueryResultSuccess SIGDEFARG
+{
+ QueryResult = 1;
+ SIGRETURN;
+}
+
+static sigret_t
+QueryResultFail SIGDEFARG
+{
+ QueryResult = 2;
+ SIGRETURN;
+}
/*
* Send message to a screen backend.
@@ -407,9 +418,7 @@ int how;
}
-#if defined(DEBUG) || !defined(DO_NOT_POLL_MASTER)
static int AttacherPanic = 0;
-#endif
#ifdef DEBUG
static sigret_t
@@ -444,7 +453,7 @@ AttacherSigInt SIGDEFARG
}
/*
- * Unfortunatelly this is also the SIGHUP handler, so we have to
+ * Unfortunately this is also the SIGHUP handler, so we have to
* check if the backend is already detached.
*/
@@ -599,7 +608,6 @@ Attacher()
#endif
for (;;)
{
-#ifndef DO_NOT_POLL_MASTER
signal(SIGALRM, AttacherSigAlarm);
alarm(15);
pause();
@@ -609,10 +617,6 @@ Attacher()
debug1("attacher: Panic! MasterPid %d does not exist.\n", MasterPid);
AttacherPanic++;
}
-#else
- pause();
-#endif
-#if defined(DEBUG) || !defined(DO_NOT_POLL_MASTER)
if (AttacherPanic)
{
fcntl(0, F_SETFL, 0);
@@ -620,7 +624,6 @@ Attacher()
printf("\nSuddenly the Dungeon collapses!! - You die...\n");
eexit(1);
}
-#endif
#ifdef BSDJOBS
if (SuspendPlease)
{
@@ -753,7 +756,7 @@ LockTerminal()
debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat));
}
else
- printf(LockEnd);
+ printf("%s", LockEnd);
}
}
else
@@ -935,10 +938,11 @@ screen_builtin_lck()
void
-SendCmdMessage(sty, match, av)
+SendCmdMessage(sty, match, av, query)
char *sty;
char *match;
char **av;
+int query;
{
int i, s;
struct msg m;
@@ -966,7 +970,7 @@ char **av;
exit(1);
}
bzero((char *)&m, sizeof(m));
- m.type = MSG_COMMAND;
+ m.type = query ? MSG_QUERY : MSG_COMMAND;
if (attach_tty)
{
strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1);
@@ -991,7 +995,59 @@ char **av;
m.m.command.preselect[sizeof(m.m.command.preselect) - 1] = 0;
m.m.command.apid = getpid();
debug1("SendCommandMsg writing '%s'\n", m.m.command.cmd);
- if (WriteMessage(s, &m))
- Msg(errno, "write");
- close(s);
+ if (query)
+ {
+ /* Create a server socket so we can get back the result */
+ char *sp = SockPath + strlen(SockPath);
+ char query[] = "-queryX";
+ char c;
+ int r = -1;
+ for (c = 'A'; c <= 'Z'; c++)
+ {
+ query[6] = c;
+ strcpy(sp, query); /* XXX: strncpy? */
+ if ((r = MakeServerSocket()) >= 0)
+ break;
+ }
+ if (r < 0)
+ {
+ for (c = '0'; c <= '9'; c++)
+ {
+ query[6] = c;
+ strcpy(sp, query);
+ if ((r = MakeServerSocket()) >= 0)
+ break;
+ }
+ }
+
+ if (r < 0)
+ Panic(0, "Could not create a listening socket to read the results.");
+
+ strncpy(m.m.command.writeback, SockPath, sizeof(m.m.command.writeback) - 1);
+ m.m.command.writeback[sizeof(m.m.command.writeback) - 1] = '\0';
+
+ /* Send the message, then wait for a response */
+ signal(SIGCONT, QueryResultSuccess);
+ signal(SIG_BYE, QueryResultFail);
+ if (WriteMessage(s, &m))
+ Msg(errno, "write");
+ close(s);
+ while (!QueryResult)
+ pause();
+ signal(SIGCONT, SIG_DFL);
+ signal(SIG_BYE, SIG_DFL);
+
+ /* Read the result and spit it out to stdout */
+ ReceiveRaw(r);
+ unlink(SockPath);
+ if (QueryResult == 2) /* An error happened */
+ exit(1);
+ }
+ else
+ {
+ if (WriteMessage(s, &m))
+ Msg(errno, "write");
+ close(s);
+ }
}
+
diff --git a/src/braille.c b/src/braille.c
index 37c9c11..e12fc8f 100644
--- a/src/braille.c
+++ b/src/braille.c
@@ -388,7 +388,7 @@ bd_signal()
else
{
AddCStr(D_BL);
- Flush();
+ Flush(0);
}
}
diff --git a/src/braille.h b/src/braille.h
index ff5fde7..a0cb4e9 100644
--- a/src/braille.h
+++ b/src/braille.h
@@ -22,7 +22,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
#ifdef HAVE_BRAILLE
diff --git a/src/canvas.c b/src/canvas.c
new file mode 100644
index 0000000..0121892
--- /dev/null
+++ b/src/canvas.c
@@ -0,0 +1,916 @@
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+#include "config.h"
+#include "screen.h"
+#include "extern.h"
+#include "canvas.h"
+#include "list_generic.h"
+
+extern struct display *display;
+extern struct win *fore, *windows;
+extern struct layer *flayer;
+extern int captionalways;
+extern struct LayFuncs BlankLf;
+extern int focusminwidth, focusminheight;
+
+static void
+CanvasInitBlank(cv)
+struct canvas *cv;
+{
+ cv->c_blank.l_cvlist = cv;
+ cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
+ cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
+ cv->c_blank.l_x = cv->c_blank.l_y = 0;
+ cv->c_blank.l_layfn = &BlankLf;
+ cv->c_blank.l_data = 0;
+ cv->c_blank.l_next = 0;
+ cv->c_blank.l_bottom = &cv->c_blank;
+ cv->c_blank.l_blocking = 0;
+ cv->c_layer = &cv->c_blank;
+}
+
+static void
+FreePerp(pcv)
+struct canvas *pcv;
+{
+ struct canvas *cv;
+
+ if (!pcv->c_slperp)
+ return;
+ cv = pcv->c_slperp;
+ cv->c_slprev = pcv->c_slprev;
+ if (cv->c_slprev)
+ cv->c_slprev->c_slnext = cv;
+ cv->c_slback = pcv->c_slback;
+ if (cv->c_slback && cv->c_slback->c_slperp == pcv)
+ cv->c_slback->c_slperp = cv;
+ cv->c_slorient = pcv->c_slorient;
+ cv->c_slweight = pcv->c_slweight;
+ while (cv->c_slnext)
+ {
+ cv = cv->c_slnext;
+ cv->c_slorient = pcv->c_slorient;
+ cv->c_slback = pcv->c_slback;
+ cv->c_slweight = pcv->c_slweight;
+ }
+ cv->c_slnext = pcv->c_slnext;
+ if (cv->c_slnext)
+ cv->c_slnext->c_slprev = cv;
+ LayerCleanupMemory(&pcv->c_blank);
+ free(pcv);
+}
+
+void
+FreeCanvas(cv)
+struct canvas *cv;
+{
+ struct viewport *vp, *nvp;
+ struct canvas **cvp;
+ struct win *p;
+
+ if (cv->c_slprev)
+ cv->c_slprev->c_slnext = cv->c_slnext;
+ if (cv->c_slnext)
+ cv->c_slnext->c_slprev = cv->c_slprev;
+ if (cv->c_slback && cv->c_slback->c_slperp == cv)
+ cv->c_slback->c_slperp = cv->c_slnext ? cv->c_slnext : cv->c_slprev;
+ if (cv->c_slperp)
+ {
+ while (cv->c_slperp)
+ FreeCanvas(cv->c_slperp);
+ LayerCleanupMemory(&cv->c_blank);
+ free(cv);
+ return;
+ }
+
+ if (display)
+ {
+ if (D_forecv == cv)
+ D_forecv = 0;
+ /* remove from canvas chain as SetCanvasWindow might call
+ * some layer function */
+ for (cvp = &D_cvlist; *cvp ; cvp = &(*cvp)->c_next)
+ if (*cvp == cv)
+ {
+ *cvp = cv->c_next;
+ break;
+ }
+ }
+ p = cv->c_layer ? Layer2Window(cv->c_layer) : 0;
+ SetCanvasWindow(cv, 0);
+ if (p)
+ WindowChanged(p, 'u');
+ if (flayer == cv->c_layer)
+ flayer = 0;
+ for (vp = cv->c_vplist; vp; vp = nvp)
+ {
+ vp->v_canvas = 0;
+ nvp = vp->v_next;
+ vp->v_next = 0;
+ free(vp);
+ }
+ evdeq(&cv->c_captev);
+ LayerCleanupMemory(&cv->c_blank);
+ free(cv);
+}
+
+int
+CountCanvas(cv)
+struct canvas *cv;
+{
+ int num = 0;
+ for (; cv; cv = cv->c_slnext)
+ {
+ if (cv->c_slperp)
+ {
+ struct canvas *cvp;
+ int nump = 1, n;
+ for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
+ if (cvp->c_slperp)
+ {
+ n = CountCanvas(cvp->c_slperp);
+ if (n > nump)
+ nump = n;
+ }
+ num += nump;
+ }
+ else
+ num++;
+ }
+ return num;
+}
+
+int
+CountCanvasPerp(cv)
+struct canvas *cv;
+{
+ struct canvas *cvp;
+ int num = 1, n;
+ for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
+ if (cvp->c_slperp)
+ {
+ n = CountCanvas(cvp->c_slperp);
+ if (n > num)
+ num = n;
+ }
+ return num;
+}
+
+struct canvas *
+FindCanvas(x, y)
+int x, y;
+{
+ struct canvas *cv, *mcv = 0;
+ int m, mm = 0;
+
+ for (cv = D_cvlist; cv; cv = cv->c_next)
+ {
+ /* ye + 1 because of caption line */
+ if (x >= cv->c_xs && x <= cv->c_xe && y >= cv->c_ys && y <= cv->c_ye + 1)
+ return cv;
+ if (cv == D_forecv)
+ continue;
+ m = 0;
+ if (x >= D_forecv->c_xs && x <= D_forecv->c_xe)
+ {
+ if (x < cv->c_xs || x > cv->c_xe)
+ continue;
+ if (y < D_forecv->c_ys && y < cv->c_ys)
+ continue;
+ if (y > D_forecv->c_ye + 1 && y > cv->c_ye + 1)
+ continue;
+ if (y < cv->c_ys)
+ m = cv->c_ys - y;
+ if (y > cv->c_ye + 1)
+ m = y - (cv->c_ye + 1);
+ }
+ if (y >= D_forecv->c_ys && y <= D_forecv->c_ye + 1)
+ {
+ if (y < cv->c_ys || y > cv->c_ye + 1)
+ continue;
+ if (x < D_forecv->c_xs && x < cv->c_xs)
+ continue;
+ if (x > D_forecv->c_xe && x > cv->c_xe)
+ continue;
+ if (x < cv->c_xs)
+ m = cv->c_xs - x;
+ if (x > cv->c_xe)
+ m = x - cv->c_xe;
+ }
+ if (m && (!mm || m < mm))
+ {
+ mcv = cv;
+ mm = m;
+ }
+ }
+ return mcv ? mcv : D_forecv;
+}
+
+void
+SetCanvasWindow(cv, wi)
+struct canvas *cv;
+struct win *wi;
+{
+ struct win *p = 0, **pp;
+ struct layer *l;
+ struct canvas *cvp, **cvpp;
+
+ l = cv->c_layer;
+ display = cv->c_display;
+
+ if (l)
+ {
+ /* remove old layer */
+ for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
+ if (cvp == cv)
+ break;
+ ASSERT(cvp);
+ *cvpp = cvp->c_lnext;
+
+ p = Layer2Window(l);
+ l = cv->c_layer;
+ cv->c_layer = 0;
+
+ if (p && cv == D_forecv)
+ {
+#ifdef MULTIUSER
+ ReleaseAutoWritelock(display, p);
+#endif
+ if (p->w_silence)
+ {
+ SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
+ evenq(&p->w_silenceev);
+ }
+ D_other = fore;
+ D_fore = 0;
+ }
+ if (l->l_cvlist == 0 && (p == 0 || l != p->w_savelayer))
+ KillLayerChain(l);
+ }
+
+ /* find right layer to display on canvas */
+ if (wi && wi->w_type != W_TYPE_GROUP)
+ {
+ l = &wi->w_layer;
+ if (wi->w_savelayer && (wi->w_blocked || wi->w_savelayer->l_cvlist == 0))
+ l = wi->w_savelayer;
+ }
+ else
+ {
+ l = &cv->c_blank;
+ if (wi)
+ l->l_data = (char *)wi;
+ else
+ l->l_data = 0;
+ }
+
+ /* add our canvas to the layer's canvaslist */
+ ASSERT(l->l_cvlist != cv);
+ cv->c_lnext = l->l_cvlist;
+ l->l_cvlist = cv;
+ cv->c_layer = l;
+ cv->c_xoff = cv->c_xs;
+ cv->c_yoff = cv->c_ys;
+ RethinkViewportOffsets(cv);
+
+ if (flayer == 0)
+ flayer = l;
+
+ if (wi && wi->w_type == W_TYPE_GROUP)
+ {
+ /* auto-start windowlist on groups */
+ struct display *d = display;
+ struct layer *oldflayer = flayer;
+ flayer = l;
+ display_windows(0, 0, wi);
+ flayer = oldflayer;
+ display = d;
+ }
+
+ if (wi && D_other == wi)
+ D_other = wi->w_next; /* Might be 0, but that's OK. */
+ if (cv == D_forecv)
+ {
+ D_fore = wi;
+ fore = D_fore; /* XXX ? */
+ if (wi)
+ {
+#ifdef MULTIUSER
+ ObtainAutoWritelock(display, wi);
+#endif
+ /*
+ * Place the window at the head of the most-recently-used list
+ */
+ if (windows != wi)
+ {
+ for (pp = &windows; (p = *pp); pp = &p->w_next)
+ if (p == wi)
+ break;
+ ASSERT(p);
+ *pp = p->w_next;
+ p->w_next = windows;
+ windows = p;
+ WListLinkChanged();
+ }
+ }
+ }
+}
+
+static void
+cv_winid_fn(ev, data)
+struct event *ev;
+char *data;
+{
+ int ox, oy;
+ struct canvas *cv = (struct canvas *)data;
+
+ display = cv->c_display;
+ if (D_status == STATUS_ON_WIN)
+ {
+ SetTimeout(ev, 1);
+ evenq(ev);
+ return;
+ }
+ ox = D_x;
+ oy = D_y;
+ if (cv->c_ye + 1 < D_height)
+ RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
+ if (ox != -1 && oy != -1)
+ GotoPos(ox, oy);
+}
+
+int
+MakeDefaultCanvas()
+{
+ struct canvas *cv;
+
+ ASSERT(display);
+ if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
+ return -1;
+ cv->c_xs = 0;
+ cv->c_xe = D_width - 1;
+ cv->c_ys = 0;
+ cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways;
+ debug2("MakeDefaultCanvas 0,0 %d,%d\n", cv->c_xe, cv->c_ye);
+ cv->c_xoff = 0;
+ cv->c_yoff = 0;
+ cv->c_next = 0;
+ cv->c_display = display;
+ cv->c_vplist = 0;
+ cv->c_slnext = 0;
+ cv->c_slprev = 0;
+ cv->c_slperp = 0;
+ cv->c_slweight = 1;
+ cv->c_slback = &D_canvas;
+ D_canvas.c_slperp = cv;
+ D_canvas.c_xs = cv->c_xs;
+ D_canvas.c_xe = cv->c_xe;
+ D_canvas.c_ys = cv->c_ys;
+ D_canvas.c_ye = cv->c_ye;
+ cv->c_slorient = SLICE_UNKN;
+ cv->c_captev.type = EV_TIMEOUT;
+ cv->c_captev.data = (char *)cv;
+ cv->c_captev.handler = cv_winid_fn;
+
+ CanvasInitBlank(cv);
+ cv->c_lnext = 0;
+
+ D_cvlist = cv;
+ RethinkDisplayViewports();
+ D_forecv = cv; /* default input focus */
+ return 0;
+}
+
+static struct canvas **
+CreateCanvasChainRec(cv, cvp)
+struct canvas *cv;
+struct canvas **cvp;
+{
+ for (; cv; cv = cv->c_slnext)
+ {
+ if (cv->c_slperp)
+ cvp = CreateCanvasChainRec(cv->c_slperp, cvp);
+ else
+ {
+ *cvp = cv;
+ cvp = &cv->c_next;
+ }
+ }
+ return cvp;
+}
+
+void
+RecreateCanvasChain()
+{
+ struct canvas **cvp;
+ cvp = CreateCanvasChainRec(D_canvas.c_slperp, &D_cvlist);
+ *cvp = 0;
+}
+
+void
+EqualizeCanvas(cv, gflag)
+struct canvas *cv;
+int gflag;
+{
+ struct canvas *cv2;
+ for (; cv; cv = cv->c_slnext)
+ {
+ if (cv->c_slperp && gflag)
+ {
+ cv->c_slweight = CountCanvasPerp(cv);
+ for (cv2 = cv->c_slperp; cv2; cv2 = cv2->c_slnext)
+ if (cv2->c_slperp)
+ EqualizeCanvas(cv2->c_slperp, gflag);
+ }
+ else
+ cv->c_slweight = 1;
+ }
+}
+
+void
+ResizeCanvas(cv)
+struct canvas *cv;
+{
+ struct canvas *cv2, *cvn, *fcv;
+ int nh, i, maxi, hh, m, w, wsum;
+ int need, got;
+ int xs, ys, xe, ye;
+ int focusmin = 0;
+
+ xs = cv->c_xs;
+ ys = cv->c_ys;
+ xe = cv->c_xe;
+ ye = cv->c_ye;
+ cv = cv->c_slperp;
+ debug2("ResizeCanvas: %d,%d", xs, ys);
+ debug2(" %d,%d\n", xe, ye);
+ if (cv == 0)
+ return;
+ if (cv->c_slorient == SLICE_UNKN)
+ {
+ ASSERT(!cv->c_slnext && !cv->c_slperp);
+ cv->c_xs = xs;
+ cv->c_xe = xe;
+ cv->c_ys = ys;
+ cv->c_ye = ye;
+ cv->c_xoff = cv->c_xs;
+ cv->c_yoff = cv->c_ys;
+ cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
+ cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
+ return;
+ }
+
+ fcv = 0;
+ if (focusminwidth || focusminheight)
+ {
+ debug("searching for focus canvas\n");
+ cv2 = D_forecv;
+ while (cv2->c_slback)
+ {
+ if (cv2->c_slback == cv->c_slback)
+ {
+ fcv = cv2;
+ focusmin = cv->c_slorient == SLICE_VERT ? focusminheight : focusminwidth;
+ if (focusmin > 0)
+ focusmin--;
+ else if (focusmin < 0)
+ focusmin = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
+ debug1("found, focusmin=%d\n", focusmin);
+ }
+ cv2 = cv2->c_slback;
+ }
+ }
+ if (focusmin)
+ {
+ m = CountCanvas(cv) * 2;
+ nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
+ nh -= m;
+ if (nh < 0)
+ nh = 0;
+ if (focusmin > nh)
+ focusmin = nh;
+ debug1("corrected to %d\n", focusmin);
+ }
+
+ /* pass 1: calculate weight sum */
+ for (cv2 = cv, wsum = 0; cv2; cv2 = cv2->c_slnext)
+ {
+ debug1(" weight %d\n", cv2->c_slweight);
+ wsum += cv2->c_slweight;
+ }
+ debug1("wsum = %d\n", wsum);
+ if (wsum == 0)
+ wsum = 1;
+ w = wsum;
+
+ /* pass 2: calculate need/excess space */
+ nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
+ for (cv2 = cv, need = got = 0; cv2; cv2 = cv2->c_slnext)
+ {
+ m = cv2->c_slperp ? CountCanvasPerp(cv2) * 2 - 1 : 1;
+ if (cv2 == fcv)
+ m += focusmin;
+ hh = cv2->c_slweight ? nh * cv2->c_slweight / w : 0;
+ w -= cv2->c_slweight;
+ nh -= hh;
+ debug2(" should %d min %d\n", hh, m);
+ if (hh <= m + 1)
+ need += m + 1 - hh;
+ else
+ got += hh - m - 1;
+ }
+ debug2("need: %d, got %d\n", need, got);
+ if (need > got)
+ need = got;
+
+ /* pass 3: distribute space */
+ nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
+ i = cv->c_slorient == SLICE_VERT ? ys : xs;
+ maxi = cv->c_slorient == SLICE_VERT ? ye : xe;
+ w = wsum;
+ for (; cv; cv = cvn)
+ {
+ cvn = cv->c_slnext;
+ if (i > maxi)
+ {
+ if (cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slprev->c_slperp && !cv->c_slprev->c_slprev)
+ {
+ cv->c_slprev->c_slorient = SLICE_UNKN;
+ if (!captionalways)
+ {
+ cv->c_slback->c_ye++;
+ cv->c_slprev->c_ye++;
+ }
+ }
+ SetCanvasWindow(cv, 0);
+ FreeCanvas(cv);
+ continue;
+ }
+ m = cv->c_slperp ? CountCanvasPerp(cv) * 2 - 1 : 1;
+ if (cv == fcv)
+ m += focusmin;
+ hh = cv->c_slweight ? nh * cv->c_slweight / w : 0;
+ w -= cv->c_slweight;
+ nh -= hh;
+ debug2(" should %d min %d\n", hh, m);
+ if (hh <= m + 1)
+ {
+ hh = m + 1;
+ debug1(" -> %d\n", hh);
+ }
+ else
+ {
+ int hx = need * (hh - m - 1) / got;
+ debug3(" -> %d - %d = %d\n", hh, hx, hh - hx);
+ got -= (hh - m - 1);
+ hh -= hx;
+ need -= hx;
+ debug2(" now need=%d got=%d\n", need, got);
+ }
+ ASSERT(hh >= m + 1);
+ /* hh is window size plus pation line */
+ if (i + hh > maxi + 2)
+ {
+ hh = maxi + 2 - i;
+ debug1(" not enough space, reducing to %d\n", hh);
+ }
+ if (i + hh == maxi + 1)
+ {
+ hh++;
+ debug(" incrementing as no other canvas will fit\n");
+ }
+ if (cv->c_slorient == SLICE_VERT)
+ {
+ cv->c_xs = xs;
+ cv->c_xe = xe;
+ cv->c_ys = i;
+ cv->c_ye = i + hh - 2;
+ cv->c_xoff = xs;
+ cv->c_yoff = i;
+ }
+ else
+ {
+ cv->c_xs = i;
+ cv->c_xe = i + hh - 2;
+ cv->c_ys = ys;
+ cv->c_ye = ye;
+ cv->c_xoff = i;
+ cv->c_yoff = ys;
+ }
+ cv->c_xoff = cv->c_xs;
+ cv->c_yoff = cv->c_ys;
+ cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
+ cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
+ if (cv->c_slperp)
+ {
+ ResizeCanvas(cv);
+ if (!cv->c_slperp->c_slnext)
+ {
+ debug("deleting perp node\n");
+ FreePerp(cv->c_slperp);
+ FreePerp(cv);
+ }
+ }
+ i += hh;
+ }
+}
+
+static struct canvas *
+AddPerp(cv)
+struct canvas *cv;
+{
+ struct canvas *pcv;
+ debug("Creating new perp node\n");
+
+ if ((pcv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
+ return 0;
+ pcv->c_next = 0;
+ pcv->c_display = cv->c_display;
+ pcv->c_slnext = cv->c_slnext;
+ pcv->c_slprev = cv->c_slprev;
+ pcv->c_slperp = cv;
+ pcv->c_slback = cv->c_slback;
+ if (cv->c_slback && cv->c_slback->c_slperp == cv)
+ cv->c_slback->c_slperp = pcv;
+ pcv->c_slorient = cv->c_slorient;
+ pcv->c_xoff = 0;
+ pcv->c_yoff = 0;
+ pcv->c_xs = cv->c_xs;
+ pcv->c_xe = cv->c_xe;
+ pcv->c_ys = cv->c_ys;
+ pcv->c_ye = cv->c_ye;
+ if (pcv->c_slnext)
+ pcv->c_slnext->c_slprev = pcv;
+ if (pcv->c_slprev)
+ pcv->c_slprev->c_slnext = pcv;
+ pcv->c_slweight = cv->c_slweight;
+ CanvasInitBlank(pcv);
+ cv->c_slweight = 1;
+ cv->c_slnext = 0;
+ cv->c_slprev = 0;
+ cv->c_slperp = 0;
+ cv->c_slback = pcv;
+ cv->c_slorient = SLICE_UNKN;
+ return pcv;
+}
+
+int
+AddCanvas(orient)
+int orient;
+{
+ struct canvas *cv;
+ int xs, xe, ys, ye;
+ int h, num;
+
+ cv = D_forecv;
+ debug2("AddCanvas orient %d, forecv is %d\n", orient, cv->c_slorient);
+
+ if (cv->c_slorient != SLICE_UNKN && cv->c_slorient != orient)
+ if (!AddPerp(cv))
+ return -1;
+
+ cv = D_forecv;
+ xs = cv->c_slback->c_xs;
+ xe = cv->c_slback->c_xe;
+ ys = cv->c_slback->c_ys;
+ ye = cv->c_slback->c_ye;
+ if (!captionalways && cv == D_canvas.c_slperp && !cv->c_slnext)
+ ye--; /* need space for caption */
+ debug2("Adding Canvas to slice %d,%d ", xs, ys);
+ debug2("%d,%d\n", xe, ye);
+
+ num = CountCanvas(cv->c_slback->c_slperp) + 1;
+ debug1("Num = %d\n", num);
+ if (orient == SLICE_VERT)
+ h = ye - ys + 1;
+ else
+ h = xe - xs + 1;
+
+ h -= 2 * num - 1;
+ if (h < 0)
+ return -1; /* can't fit in */
+
+ if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
+ return -1;
+
+ D_forecv->c_slback->c_ye = ye; /* in case we modified it above */
+ D_forecv->c_slorient = orient; /* in case it was UNKN */
+ cv->c_slnext = D_forecv->c_slnext;
+ cv->c_slprev = D_forecv;
+ D_forecv->c_slnext = cv;
+ if (cv->c_slnext)
+ cv->c_slnext->c_slprev = cv;
+ cv->c_slorient = orient;
+ cv->c_slback = D_forecv->c_slback;
+
+ cv->c_xs = xs;
+ cv->c_xe = xe;
+ cv->c_ys = ys;
+ cv->c_ye = ye;
+ cv->c_xoff = 0;
+ cv->c_yoff = 0;
+ cv->c_display = display;
+ cv->c_vplist = 0;
+ cv->c_captev.type = EV_TIMEOUT;
+ cv->c_captev.data = (char *)cv;
+ cv->c_captev.handler = cv_winid_fn;
+
+ CanvasInitBlank(cv);
+ cv->c_lnext = 0;
+
+ cv->c_next = 0;
+
+ cv = cv->c_slback;
+ EqualizeCanvas(cv->c_slperp, 0);
+ ResizeCanvas(cv);
+ RecreateCanvasChain();
+ RethinkDisplayViewports();
+ ResizeLayersToCanvases();
+ return 0;
+}
+
+void
+RemCanvas()
+{
+ int xs, xe, ys, ye;
+ struct canvas *cv;
+
+ debug("RemCanvas\n");
+ cv = D_forecv;
+ if (cv->c_slorient == SLICE_UNKN)
+ return;
+ while (cv->c_slprev)
+ cv = cv->c_slprev;
+ if (!cv->c_slnext)
+ return;
+ if (!cv->c_slnext->c_slnext && cv->c_slback->c_slback)
+ {
+ /* two canvases in slice, kill perp node */
+ cv = D_forecv;
+ debug("deleting perp node\n");
+ FreePerp(cv->c_slprev ? cv->c_slprev : cv->c_slnext);
+ FreePerp(cv->c_slback);
+ }
+ xs = cv->c_slback->c_xs;
+ xe = cv->c_slback->c_xe;
+ ys = cv->c_slback->c_ys;
+ ye = cv->c_slback->c_ye;
+ /* free canvas */
+ cv = D_forecv;
+ D_forecv = cv->c_slprev;
+ if (!D_forecv)
+ D_forecv = cv->c_slnext;
+ FreeCanvas(cv);
+
+ cv = D_forecv;
+ while (D_forecv->c_slperp)
+ D_forecv = D_forecv->c_slperp;
+
+ /* if only one canvas left, set orient back to unknown */
+ if (!cv->c_slnext && !cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slperp)
+ {
+ cv->c_slorient = SLICE_UNKN;
+ if (!captionalways)
+ cv->c_slback->c_ye = ++ye; /* caption line no longer needed */
+ }
+ cv = cv->c_slback;
+ EqualizeCanvas(cv->c_slperp, 0);
+ ResizeCanvas(cv);
+
+ D_fore = Layer2Window(D_forecv->c_layer);
+ flayer = D_forecv->c_layer;
+
+ RecreateCanvasChain();
+ RethinkDisplayViewports();
+ ResizeLayersToCanvases();
+}
+
+void
+OneCanvas()
+{
+ struct canvas *cv = D_forecv, *ocv = 0;
+
+ if (cv->c_slprev)
+ {
+ ocv = cv->c_slprev;
+ cv->c_slprev->c_slnext = cv->c_slnext;
+ }
+ if (cv->c_slnext)
+ {
+ ocv = cv->c_slnext;
+ cv->c_slnext->c_slprev = cv->c_slprev;
+ }
+ if (!ocv)
+ return;
+ if (cv->c_slback && cv->c_slback->c_slperp == cv)
+ cv->c_slback->c_slperp = ocv;
+ cv->c_slorient = SLICE_UNKN;
+ while (D_canvas.c_slperp)
+ FreeCanvas(D_canvas.c_slperp);
+ cv = D_forecv;
+ D_canvas.c_slperp = cv;
+ cv->c_slback = &D_canvas;
+ cv->c_slnext = 0;
+ cv->c_slprev = 0;
+ ASSERT(!cv->c_slperp);
+ if (!captionalways)
+ D_canvas.c_ye++; /* caption line no longer needed */
+ ResizeCanvas(&D_canvas);
+ RecreateCanvasChain();
+ RethinkDisplayViewports();
+ ResizeLayersToCanvases();
+}
+
+void
+DupLayoutCv(cvf, cvt, save)
+struct canvas *cvf, *cvt;
+int save;
+{
+ while(cvf)
+ {
+ cvt->c_slorient = cvf->c_slorient;
+ cvt->c_slweight = cvf->c_slweight;
+ if (cvf == D_forecv)
+ D_forecv = cvt;
+ if (!save)
+ {
+ cvt->c_display = display;
+ if (!cvf->c_slperp)
+ {
+ cvt->c_captev.type = EV_TIMEOUT;
+ cvt->c_captev.data = (char *)cvt;
+ cvt->c_captev.handler = cv_winid_fn;
+ cvt->c_blank.l_cvlist = 0;
+ cvt->c_blank.l_layfn = &BlankLf;
+ cvt->c_blank.l_bottom = &cvt->c_blank;
+ }
+ cvt->c_layer = cvf->c_layer;
+ }
+ else
+ {
+ struct win *p = cvf->c_layer ? Layer2Window(cvf->c_layer) : 0;
+ cvt->c_layer = p ? &p->w_layer : 0;
+ }
+ if (cvf->c_slperp)
+ {
+ cvt->c_slperp = (struct canvas *)calloc(1, sizeof(struct canvas));
+ cvt->c_slperp->c_slback = cvt;
+ CanvasInitBlank(cvt->c_slperp);
+ DupLayoutCv(cvf->c_slperp, cvt->c_slperp, save);
+ }
+ if (cvf->c_slnext)
+ {
+ cvt->c_slnext = (struct canvas *)calloc(1, sizeof(struct canvas));
+ cvt->c_slnext->c_slprev = cvt;
+ cvt->c_slnext->c_slback = cvt->c_slback;
+ CanvasInitBlank(cvt->c_slnext);
+ }
+ cvf = cvf->c_slnext;
+ cvt = cvt->c_slnext;
+ }
+}
+
+void
+PutWindowCv(cv)
+struct canvas *cv;
+{
+ struct win *p;
+ for (; cv; cv = cv->c_slnext)
+ {
+ if (cv->c_slperp)
+ {
+ PutWindowCv(cv->c_slperp);
+ continue;
+ }
+ p = cv->c_layer ? (struct win *)cv->c_layer->l_data : 0;
+ cv->c_layer = 0;
+ SetCanvasWindow(cv, p);
+ }
+}
+
diff --git a/src/canvas.h b/src/canvas.h
new file mode 100644
index 0000000..6aeb3d8
--- /dev/null
+++ b/src/canvas.h
@@ -0,0 +1,101 @@
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ * $Id$ GNU
+ */
+
+#ifndef SCREEN_CANVAS_H
+#define SCREEN_CANVAS_H
+
+#define SLICE_UNKN 0
+#define SLICE_VERT (1 << 0)
+#define SLICE_HORI (1 << 1)
+
+#define SLICE_THIS (1 << 2) /* used in equal test */
+#define SLICE_GLOBAL (1 << 3)
+
+struct canvas
+{
+ struct canvas *c_next; /* next canvas on display */
+ struct display *c_display; /* back pointer to display */
+
+ struct canvas *c_slnext; /* next canvas in display slice */
+ struct canvas *c_slprev; /* prev canvas in display slice */
+ struct canvas *c_slperp; /* perpendicular slice */
+ struct canvas *c_slback; /* perpendicular slice back pointer */
+ int c_slorient; /* our slice orientation */
+ int c_slweight; /* size ratio */
+
+ struct viewport *c_vplist;
+ struct layer *c_layer; /* layer on this canvas */
+ struct canvas *c_lnext; /* next canvas that displays layer */
+ struct layer c_blank; /* bottom layer, always blank */
+ int c_xoff; /* canvas x offset on display */
+ int c_yoff; /* canvas y offset on display */
+ int c_xs;
+ int c_xe;
+ int c_ys;
+ int c_ye;
+ struct event c_captev; /* caption changed event */
+};
+
+struct win; /* forward declaration */
+
+extern void SetCanvasWindow __P((struct canvas *, struct win *));
+extern void SetForeCanvas __P((struct display *, struct canvas *));
+extern struct canvas *FindCanvas __P((int, int));
+extern int MakeDefaultCanvas __P((void));
+extern int AddCanvas __P((int));
+extern void RemCanvas __P((void));
+extern void OneCanvas __P((void));
+extern void FreeCanvas __P((struct canvas *));
+extern void ResizeCanvas __P((struct canvas *));
+extern void RecreateCanvasChain __P((void));
+extern void RethinkViewportOffsets __P((struct canvas *));
+extern int CountCanvasPerp __P((struct canvas *));
+extern void EqualizeCanvas __P((struct canvas *, int));
+extern void DupLayoutCv __P((struct canvas *, struct canvas *, int));
+extern void PutWindowCv __P((struct canvas *));
+
+#define CV_CALL(cv, cmd) \
+{ \
+ struct display *olddisplay = display; \
+ struct layer *oldflayer = flayer; \
+ struct layer *l = cv->c_layer; \
+ struct canvas *cvlist = l->l_cvlist; \
+ struct canvas *cvlnext = cv->c_lnext; \
+ flayer = l; \
+ l->l_cvlist = cv; \
+ cv->c_lnext = 0; \
+ cmd; \
+ flayer = oldflayer; \
+ l->l_cvlist = cvlist; \
+ cv->c_lnext = cvlnext; \
+ display = olddisplay; \
+}
+
+#endif /* SCREEN_CANVAS_H */
+
diff --git a/src/comm.c b/src/comm.c
index 36585cb..46f5aba 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -59,7 +59,7 @@ struct comm comms[RC_LAST + 1] =
{ "alias", ARGS_12|ARGS_ORMORE },
{ "allpartial", NEED_DISPLAY|ARGS_1 },
{ "altscreen", ARGS_01 },
- { "at", NEED_DISPLAY|ARGS_2|ARGS_ORMORE },
+ { "at", ARGS_2|ARGS_ORMORE },
#ifdef COLOR
{ "attrcolor", ARGS_12 },
#endif
@@ -104,7 +104,7 @@ struct comm comms[RC_LAST + 1] =
#endif
{ "blanker", NEED_DISPLAY|ARGS_0},
#ifdef BLANKER_PRG
- { "blankerprg", ARGS_1|ARGS_ORMORE },
+ { "blankerprg", ARGS_0|ARGS_ORMORE },
#endif
{ "break", NEED_FORE|ARGS_01 },
{ "breaktype", NEED_FORE|ARGS_01 },
@@ -158,6 +158,7 @@ struct comm comms[RC_LAST + 1] =
#endif
{ "defmode", ARGS_1 },
{ "defmonitor", ARGS_1 },
+ { "defmousetrack", ARGS_1 },
#ifdef MULTI
{ "defnonblock", ARGS_1 },
#endif
@@ -176,11 +177,11 @@ struct comm comms[RC_LAST + 1] =
#ifdef DETACH
{ "detach", NEED_DISPLAY|ARGS_01 },
#endif
- { "digraph", NEED_LAYER|ARGS_01 },
+ { "digraph", NEED_LAYER|ARGS_012 },
{ "dinfo", NEED_DISPLAY|ARGS_0 },
{ "displays", NEED_LAYER|ARGS_0 },
{ "dumptermcap", NEED_FORE|ARGS_0 },
- { "echo", ARGS_12 },
+ { "echo", CAN_QUERY|ARGS_12 },
#ifdef ENCODINGS
{ "encoding", ARGS_12 },
#endif
@@ -207,12 +208,12 @@ struct comm comms[RC_LAST + 1] =
{ "hstatus", NEED_FORE|ARGS_1 },
{ "idle", ARGS_0|ARGS_ORMORE },
{ "ignorecase", ARGS_01 },
- { "info", NEED_LAYER|ARGS_0 },
+ { "info", CAN_QUERY|NEED_LAYER|ARGS_0 },
#ifdef ENCODINGS
{ "kanji", NEED_FORE|ARGS_12 },
#endif
{ "kill", NEED_FORE|ARGS_0 },
- { "lastmsg", NEED_DISPLAY|ARGS_0 },
+ { "lastmsg", CAN_QUERY|NEED_DISPLAY|ARGS_0 },
{ "layout", ARGS_1|ARGS_ORMORE},
{ "license", NEED_LAYER|ARGS_0 },
#ifdef LOCK
@@ -232,9 +233,10 @@ struct comm comms[RC_LAST + 1] =
#ifdef COPY_PASTE
{ "markkeys", ARGS_1 },
#endif
- { "maxwin", ARGS_1 },
+ { "maxwin", ARGS_01 },
{ "meta", NEED_LAYER|ARGS_0 },
{ "monitor", NEED_FORE|ARGS_01 },
+ { "mousetrack", NEED_DISPLAY | ARGS_01 },
{ "msgminwait", ARGS_1 },
{ "msgwait", ARGS_1 },
#ifdef MULTIUSER
@@ -247,7 +249,7 @@ struct comm comms[RC_LAST + 1] =
#ifdef MULTI
{ "nonblock", NEED_DISPLAY|ARGS_01 },
#endif
- { "number", NEED_FORE|ARGS_01 },
+ { "number", CAN_QUERY|NEED_FORE|ARGS_01 },
{ "obuflimit", NEED_DISPLAY|ARGS_01 },
{ "only", NEED_DISPLAY|ARGS_0 },
{ "other", ARGS_0 },
@@ -278,13 +280,14 @@ struct comm comms[RC_LAST + 1] =
#ifdef COPY_PASTE
{ "removebuf", ARGS_0 },
#endif
+ { "rendition", ARGS_23 },
{ "reset", NEED_FORE|ARGS_0 },
{ "resize", NEED_DISPLAY|ARGS_0|ARGS_ORMORE },
{ "screen", ARGS_0|ARGS_ORMORE },
#ifdef COPY_PASTE
{ "scrollback", NEED_FORE|ARGS_1 },
#endif
- { "select", ARGS_01 },
+ { "select", CAN_QUERY|ARGS_01 },
{ "sessionname", ARGS_01 },
{ "setenv", ARGS_012 },
{ "setsid", ARGS_1 },
@@ -309,9 +312,10 @@ struct comm comms[RC_LAST + 1] =
{ "termcap", ARGS_23 },
{ "termcapinfo", ARGS_23 },
{ "terminfo", ARGS_23 },
- { "time", ARGS_01 },
- { "title", NEED_FORE|ARGS_01 },
+ { "time", CAN_QUERY|ARGS_01 },
+ { "title", CAN_QUERY|NEED_FORE|ARGS_01 },
{ "umask", ARGS_1|ARGS_ORMORE },
+ { "unbindall", ARGS_0 },
{ "unsetenv", ARGS_1 },
#ifdef UTF8
{ "utf8", NEED_FORE|ARGS_012 },
@@ -324,7 +328,7 @@ struct comm comms[RC_LAST + 1] =
{ "wall", NEED_DISPLAY|ARGS_1},
{ "width", ARGS_0123 },
{ "windowlist", ARGS_012 },
- { "windows", NEED_DISPLAY|ARGS_0 },
+ { "windows", CAN_QUERY|ARGS_0 },
{ "wrap", NEED_FORE|ARGS_01 },
#ifdef COPY_PASTE
{ "writebuf", ARGS_0123 },
diff --git a/src/comm.sh b/src/comm.sh
index 44c83dd..4fc8cb2 100644
--- a/src/comm.sh
+++ b/src/comm.sh
@@ -43,6 +43,8 @@ struct comm
#define NEED_FORE (1<<6) /* this command needs a fore window */
#define NEED_DISPLAY (1<<7) /* this command needs a display */
#define NEED_LAYER (1<<8) /* this command needs a layer */
+#define CAN_QUERY (1<<9) /* this command can be queried, i.e. used with -Q to
+ get back a result to stdout */
#define ARGS_01 (ARGS_0 | ARGS_PLUS1)
#define ARGS_02 (ARGS_0 | ARGS_PLUS2)
@@ -61,6 +63,10 @@ struct action
int nr;
char **args;
int *argl;
+ int quiet; /* Suppress (currently unused)
+ 0x01 - Error message
+ 0x02 - Normal message
+ */
};
#define RC_ILLEGAL -1
diff --git a/src/configure.in b/src/configure.in
index 9db3dd6..bd29de2 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
dnl
-dnl $Id$ FAU
+dnl $Id$ GNU
dnl
dnl Many thanks to David MacKenzie for writing autoconf and
dnl providing a sample configure.in file for screen.
@@ -284,6 +284,12 @@ seteuid(0);
#endif
], AC_DEFINE(HAVE_SETEUID))
+dnl execvpe
+AC_CHECKING(execvpe)
+AC_TRY_LINK(,[
+ execvpe(0, 0, 0);
+], AC_DEFINE(HAVE_EXECVPE))
+
dnl
dnl **** select() ****
dnl
diff --git a/src/display.c b/src/display.c
index 3e0bdae..5fc5f4b 100644
--- a/src/display.c
+++ b/src/display.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -37,12 +37,12 @@
#include "screen.h"
#include "extern.h"
#include "braille.h"
+#include "canvas.h"
static int CountChars __P((int));
static int DoAddChar __P((int));
static int BlankResize __P((int, int));
static int CallRewrite __P((int, int, int, int));
-static void FreeCanvas __P((struct canvas *));
static void disp_readev_fn __P((struct event *, char *));
static void disp_writeev_fn __P((struct event *, char *));
#ifdef linux
@@ -65,8 +65,7 @@ static void RAW_PUTCHAR __P((int));
#ifdef COLOR
static void SetBackColor __P((int));
#endif
-static void FreePerp __P((struct canvas *));
-static struct canvas *AddPerp __P((struct canvas *));
+static void RemoveStatusMinWait __P((void));
extern struct layer *flayer;
@@ -122,6 +121,7 @@ struct display TheDisplay;
*/
int defobuflimit = OBUF_MAX;
int defnonblock = -1;
+int defmousetrack = 0;
#ifdef AUTO_NUKE
int defautonuke = 0;
#endif
@@ -200,7 +200,8 @@ struct LayFuncs BlankLf =
DefClearLine,
DefRewrite,
BlankResize,
- DefRestore
+ DefRestore,
+ 0
};
/*ARGSUSED*/
@@ -313,6 +314,7 @@ struct mode *Mode;
D_termname[sizeof(D_termname) - 1] = 0;
D_user = *u;
D_processinput = ProcessInput;
+ D_mousetrack = defmousetrack;
return display;
}
@@ -333,7 +335,7 @@ FreeDisplay()
#endif
if (D_userfd >= 0)
{
- Flush();
+ Flush(3);
if (!display)
return;
SetTTY(D_userfd, &D_OldMode);
@@ -411,738 +413,17 @@ FreeDisplay()
if (p->w_zdisplay == display)
zmodem_abort(p, 0);
#endif
+ if (D_mousetrack)
+ {
+ D_mousetrack = 0;
+ MouseMode(0);
+ }
#ifdef MULTI
free((char *)display);
#endif
display = 0;
}
-static void
-CanvasInitBlank(cv)
-struct canvas *cv;
-{
- cv->c_blank.l_cvlist = cv;
- cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
- cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
- cv->c_blank.l_x = cv->c_blank.l_y = 0;
- cv->c_blank.l_layfn = &BlankLf;
- cv->c_blank.l_data = 0;
- cv->c_blank.l_next = 0;
- cv->c_blank.l_bottom = &cv->c_blank;
- cv->c_blank.l_blocking = 0;
- cv->c_layer = &cv->c_blank;
-}
-
-int
-MakeDefaultCanvas()
-{
- struct canvas *cv;
-
- ASSERT(display);
- if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
- return -1;
- cv->c_xs = 0;
- cv->c_xe = D_width - 1;
- cv->c_ys = 0;
- cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways;
- debug2("MakeDefaultCanvas 0,0 %d,%d\n", cv->c_xe, cv->c_ye);
- cv->c_xoff = 0;
- cv->c_yoff = 0;
- cv->c_next = 0;
- cv->c_display = display;
- cv->c_vplist = 0;
- cv->c_slnext = 0;
- cv->c_slprev = 0;
- cv->c_slperp = 0;
- cv->c_slweight = 1;
- cv->c_slback = &D_canvas;
- D_canvas.c_slperp = cv;
- D_canvas.c_xs = cv->c_xs;
- D_canvas.c_xe = cv->c_xe;
- D_canvas.c_ys = cv->c_ys;
- D_canvas.c_ye = cv->c_ye;
- cv->c_slorient = SLICE_UNKN;
- cv->c_captev.type = EV_TIMEOUT;
- cv->c_captev.data = (char *)cv;
- cv->c_captev.handler = cv_winid_fn;
-
- CanvasInitBlank(cv);
- cv->c_lnext = 0;
-
- D_cvlist = cv;
- RethinkDisplayViewports();
- D_forecv = cv; /* default input focus */
- return 0;
-}
-
-static struct canvas **
-CreateCanvasChainRec(cv, cvp)
-struct canvas *cv;
-struct canvas **cvp;
-{
- for (; cv; cv = cv->c_slnext)
- {
- if (cv->c_slperp)
- cvp = CreateCanvasChainRec(cv->c_slperp, cvp);
- else
- {
- *cvp = cv;
- cvp = &cv->c_next;
- }
- }
- return cvp;
-}
-
-void
-RecreateCanvasChain()
-{
- struct canvas **cvp;
- cvp = CreateCanvasChainRec(D_canvas.c_slperp, &D_cvlist);
- *cvp = 0;
-}
-
-static void
-FreeCanvas(cv)
-struct canvas *cv;
-{
- struct viewport *vp, *nvp;
- struct canvas **cvp;
- struct win *p;
-
- if (cv->c_slprev)
- cv->c_slprev->c_slnext = cv->c_slnext;
- if (cv->c_slnext)
- cv->c_slnext->c_slprev = cv->c_slprev;
- if (cv->c_slback && cv->c_slback->c_slperp == cv)
- cv->c_slback->c_slperp = cv->c_slnext ? cv->c_slnext : cv->c_slprev;
- if (cv->c_slperp)
- {
- while (cv->c_slperp)
- FreeCanvas(cv->c_slperp);
- free(cv);
- return;
- }
-
- if (display)
- {
- if (D_forecv == cv)
- D_forecv = 0;
- /* remove from canvas chain as SetCanvasWindow might call
- * some layer function */
- for (cvp = &D_cvlist; *cvp ; cvp = &(*cvp)->c_next)
- if (*cvp == cv)
- {
- *cvp = cv->c_next;
- break;
- }
- }
- p = cv->c_layer ? Layer2Window(cv->c_layer) : 0;
- SetCanvasWindow(cv, 0);
- if (p)
- WindowChanged(p, 'u');
- if (flayer == cv->c_layer)
- flayer = 0;
- for (vp = cv->c_vplist; vp; vp = nvp)
- {
- vp->v_canvas = 0;
- nvp = vp->v_next;
- vp->v_next = 0;
- free(vp);
- }
- evdeq(&cv->c_captev);
- free(cv);
-}
-
-int
-CountCanvas(cv)
-struct canvas *cv;
-{
- int num = 0;
- for (; cv; cv = cv->c_slnext)
- {
- if (cv->c_slperp)
- {
- struct canvas *cvp;
- int nump = 1, n;
- for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
- if (cvp->c_slperp)
- {
- n = CountCanvas(cvp->c_slperp);
- if (n > nump)
- nump = n;
- }
- num += nump;
- }
- else
- num++;
- }
- return num;
-}
-
-int
-CountCanvasPerp(cv)
-struct canvas *cv;
-{
- struct canvas *cvp;
- int num = 1, n;
- for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
- if (cvp->c_slperp)
- {
- n = CountCanvas(cvp->c_slperp);
- if (n > num)
- num = n;
- }
- return num;
-}
-
-void
-EqualizeCanvas(cv, gflag)
-struct canvas *cv;
-int gflag;
-{
- struct canvas *cv2;
- for (; cv; cv = cv->c_slnext)
- {
- if (cv->c_slperp && gflag)
- {
- cv->c_slweight = CountCanvasPerp(cv);
- for (cv2 = cv->c_slperp; cv2; cv2 = cv2->c_slnext)
- if (cv2->c_slperp)
- EqualizeCanvas(cv2->c_slperp, gflag);
- }
- else
- cv->c_slweight = 1;
- }
-}
-
-void
-ResizeCanvas(cv)
-struct canvas *cv;
-{
- struct canvas *cv2, *cvn, *fcv;
- int nh, i, maxi, hh, m, w, wsum;
- int need, got;
- int xs, ys, xe, ye;
- int focusmin = 0;
-
- xs = cv->c_xs;
- ys = cv->c_ys;
- xe = cv->c_xe;
- ye = cv->c_ye;
- cv = cv->c_slperp;
- debug2("ResizeCanvas: %d,%d", xs, ys);
- debug2(" %d,%d\n", xe, ye);
- if (cv == 0)
- return;
- if (cv->c_slorient == SLICE_UNKN)
- {
- ASSERT(!cv->c_slnext && !cv->c_slperp);
- cv->c_xs = xs;
- cv->c_xe = xe;
- cv->c_ys = ys;
- cv->c_ye = ye;
- cv->c_xoff = cv->c_xs;
- cv->c_yoff = cv->c_ys;
- cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
- cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
- return;
- }
-
- fcv = 0;
- if (focusminwidth || focusminheight)
- {
- debug("searching for focus canvas\n");
- cv2 = D_forecv;
- while (cv2->c_slback)
- {
- if (cv2->c_slback == cv->c_slback)
- {
- fcv = cv2;
- focusmin = cv->c_slorient == SLICE_VERT ? focusminheight : focusminwidth;
- if (focusmin > 0)
- focusmin--;
- else if (focusmin < 0)
- focusmin = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
- debug1("found, focusmin=%d\n", focusmin);
- }
- cv2 = cv2->c_slback;
- }
- }
- if (focusmin)
- {
- m = CountCanvas(cv) * 2;
- nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
- nh -= m;
- if (nh < 0)
- nh = 0;
- if (focusmin > nh)
- focusmin = nh;
- debug1("corrected to %d\n", focusmin);
- }
-
- /* pass 1: calculate weight sum */
- for (cv2 = cv, wsum = 0; cv2; cv2 = cv2->c_slnext)
- {
- debug1(" weight %d\n", cv2->c_slweight);
- wsum += cv2->c_slweight;
- }
- debug1("wsum = %d\n", wsum);
- if (wsum == 0)
- wsum = 1;
- w = wsum;
-
- /* pass 2: calculate need/excess space */
- nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
- for (cv2 = cv, need = got = 0; cv2; cv2 = cv2->c_slnext)
- {
- m = cv2->c_slperp ? CountCanvasPerp(cv2) * 2 - 1 : 1;
- if (cv2 == fcv)
- m += focusmin;
- hh = cv2->c_slweight ? nh * cv2->c_slweight / w : 0;
- w -= cv2->c_slweight;
- nh -= hh;
- debug2(" should %d min %d\n", hh, m);
- if (hh <= m + 1)
- need += m + 1 - hh;
- else
- got += hh - m - 1;
- }
- debug2("need: %d, got %d\n", need, got);
- if (need > got)
- need = got;
-
- /* pass 3: distribute space */
- nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
- i = cv->c_slorient == SLICE_VERT ? ys : xs;
- maxi = cv->c_slorient == SLICE_VERT ? ye : xe;
- w = wsum;
- for (; cv; cv = cvn)
- {
- cvn = cv->c_slnext;
- if (i > maxi)
- {
- if (cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slprev->c_slperp && !cv->c_slprev->c_slprev)
- {
- cv->c_slprev->c_slorient = SLICE_UNKN;
- if (!captionalways)
- {
- cv->c_slback->c_ye++;
- cv->c_slprev->c_ye++;
- }
- }
- SetCanvasWindow(cv, 0);
- FreeCanvas(cv);
- continue;
- }
- m = cv->c_slperp ? CountCanvasPerp(cv) * 2 - 1 : 1;
- if (cv == fcv)
- m += focusmin;
- hh = cv->c_slweight ? nh * cv->c_slweight / w : 0;
- w -= cv->c_slweight;
- nh -= hh;
- debug2(" should %d min %d\n", hh, m);
- if (hh <= m + 1)
- {
- hh = m + 1;
- debug1(" -> %d\n", hh);
- }
- else
- {
- int hx = need * (hh - m - 1) / got;
- debug3(" -> %d - %d = %d\n", hh, hx, hh - hx);
- got -= (hh - m - 1);
- hh -= hx;
- need -= hx;
- debug2(" now need=%d got=%d\n", need, got);
- }
- ASSERT(hh >= m + 1);
- /* hh is window size plus pation line */
- if (i + hh > maxi + 2)
- {
- hh = maxi + 2 - i;
- debug1(" not enough space, reducing to %d\n", hh);
- }
- if (i + hh == maxi + 1)
- {
- hh++;
- debug(" incrementing as no other canvas will fit\n");
- }
- if (cv->c_slorient == SLICE_VERT)
- {
- cv->c_xs = xs;
- cv->c_xe = xe;
- cv->c_ys = i;
- cv->c_ye = i + hh - 2;
- cv->c_xoff = xs;
- cv->c_yoff = i;
- }
- else
- {
- cv->c_xs = i;
- cv->c_xe = i + hh - 2;
- cv->c_ys = ys;
- cv->c_ye = ye;
- cv->c_xoff = i;
- cv->c_yoff = ys;
- }
- cv->c_xoff = cv->c_xs;
- cv->c_yoff = cv->c_ys;
- cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
- cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
- if (cv->c_slperp)
- {
- ResizeCanvas(cv);
- if (!cv->c_slperp->c_slnext)
- {
- debug("deleting perp node\n");
- FreePerp(cv->c_slperp);
- FreePerp(cv);
- }
- }
- i += hh;
- }
-}
-
-static struct canvas *
-AddPerp(cv)
-struct canvas *cv;
-{
- struct canvas *pcv;
- debug("Creating new perp node\n");
-
- if ((pcv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
- return 0;
- pcv->c_next = 0;
- pcv->c_display = cv->c_display;
- pcv->c_slnext = cv->c_slnext;
- pcv->c_slprev = cv->c_slprev;
- pcv->c_slperp = cv;
- pcv->c_slback = cv->c_slback;
- if (cv->c_slback && cv->c_slback->c_slperp == cv)
- cv->c_slback->c_slperp = pcv;
- pcv->c_slorient = cv->c_slorient;
- pcv->c_xoff = 0;
- pcv->c_yoff = 0;
- pcv->c_xs = cv->c_xs;
- pcv->c_xe = cv->c_xe;
- pcv->c_ys = cv->c_ys;
- pcv->c_ye = cv->c_ye;
- if (pcv->c_slnext)
- pcv->c_slnext->c_slprev = pcv;
- if (pcv->c_slprev)
- pcv->c_slprev->c_slnext = pcv;
- pcv->c_slweight = cv->c_slweight;
- CanvasInitBlank(pcv);
- cv->c_slweight = 1;
- cv->c_slnext = 0;
- cv->c_slprev = 0;
- cv->c_slperp = 0;
- cv->c_slback = pcv;
- cv->c_slorient = SLICE_UNKN;
- return pcv;
-}
-
-static void
-FreePerp(pcv)
-struct canvas *pcv;
-{
- struct canvas *cv;
-
- if (!pcv->c_slperp)
- return;
- cv = pcv->c_slperp;
- cv->c_slprev = pcv->c_slprev;
- if (cv->c_slprev)
- cv->c_slprev->c_slnext = cv;
- cv->c_slback = pcv->c_slback;
- if (cv->c_slback && cv->c_slback->c_slperp == pcv)
- cv->c_slback->c_slperp = cv;
- cv->c_slorient = pcv->c_slorient;
- cv->c_slweight = pcv->c_slweight;
- while (cv->c_slnext)
- {
- cv = cv->c_slnext;
- cv->c_slorient = pcv->c_slorient;
- cv->c_slback = pcv->c_slback;
- cv->c_slweight = pcv->c_slweight;
- }
- cv->c_slnext = pcv->c_slnext;
- if (cv->c_slnext)
- cv->c_slnext->c_slprev = cv;
- free(pcv);
-}
-
-int
-AddCanvas(orient)
-int orient;
-{
- struct canvas *cv;
- int xs, xe, ys, ye;
- int h, num;
-
- cv = D_forecv;
- debug2("AddCanvas orient %d, forecv is %d\n", orient, cv->c_slorient);
-
- if (cv->c_slorient != SLICE_UNKN && cv->c_slorient != orient)
- if (!AddPerp(cv))
- return -1;
-
- cv = D_forecv;
- xs = cv->c_slback->c_xs;
- xe = cv->c_slback->c_xe;
- ys = cv->c_slback->c_ys;
- ye = cv->c_slback->c_ye;
- if (!captionalways && cv == D_canvas.c_slperp && !cv->c_slnext)
- ye--; /* need space for caption */
- debug2("Adding Canvas to slice %d,%d ", xs, ys);
- debug2("%d,%d\n", xe, ye);
-
- num = CountCanvas(cv->c_slback->c_slperp) + 1;
- debug1("Num = %d\n", num);
- if (orient == SLICE_VERT)
- h = ye - ys + 1;
- else
- h = xe - xs + 1;
-
- h -= 2 * num - 1;
- if (h < 0)
- return -1; /* can't fit in */
-
- if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
- return -1;
-
- D_forecv->c_slback->c_ye = ye; /* in case we modified it above */
- D_forecv->c_slorient = orient; /* in case it was UNKN */
- cv->c_slnext = D_forecv->c_slnext;
- cv->c_slprev = D_forecv;
- D_forecv->c_slnext = cv;
- if (cv->c_slnext)
- cv->c_slnext->c_slprev = cv;
- cv->c_slorient = orient;
- cv->c_slback = D_forecv->c_slback;
-
- cv->c_xs = xs;
- cv->c_xe = xe;
- cv->c_ys = ys;
- cv->c_ye = ye;
- cv->c_xoff = 0;
- cv->c_yoff = 0;
- cv->c_display = display;
- cv->c_vplist = 0;
- cv->c_captev.type = EV_TIMEOUT;
- cv->c_captev.data = (char *)cv;
- cv->c_captev.handler = cv_winid_fn;
-
- CanvasInitBlank(cv);
- cv->c_lnext = 0;
-
- cv->c_next = 0;
-
- cv = cv->c_slback;
- EqualizeCanvas(cv->c_slperp, 0);
- ResizeCanvas(cv);
- RecreateCanvasChain();
- RethinkDisplayViewports();
- ResizeLayersToCanvases();
- return 0;
-}
-
-void
-RemCanvas()
-{
- int xs, xe, ys, ye;
- struct canvas *cv;
-
- debug("RemCanvas\n");
- cv = D_forecv;
- if (cv->c_slorient == SLICE_UNKN)
- return;
- while (cv->c_slprev)
- cv = cv->c_slprev;
- if (!cv->c_slnext)
- return;
- if (!cv->c_slnext->c_slnext && cv->c_slback->c_slback)
- {
- /* two canvases in slice, kill perp node */
- cv = D_forecv;
- debug("deleting perp node\n");
- FreePerp(cv->c_slprev ? cv->c_slprev : cv->c_slnext);
- FreePerp(cv->c_slback);
- }
- xs = cv->c_slback->c_xs;
- xe = cv->c_slback->c_xe;
- ys = cv->c_slback->c_ys;
- ye = cv->c_slback->c_ye;
- /* free canvas */
- cv = D_forecv;
- D_forecv = cv->c_slprev;
- if (!D_forecv)
- D_forecv = cv->c_slnext;
- FreeCanvas(cv);
-
- cv = D_forecv;
- while (D_forecv->c_slperp)
- D_forecv = D_forecv->c_slperp;
-
- /* if only one canvas left, set orient back to unknown */
- if (!cv->c_slnext && !cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slperp)
- {
- cv->c_slorient = SLICE_UNKN;
- if (!captionalways)
- cv->c_slback->c_ye = ++ye; /* caption line no longer needed */
- }
- cv = cv->c_slback;
- EqualizeCanvas(cv->c_slperp, 0);
- ResizeCanvas(cv);
-
- D_fore = Layer2Window(D_forecv->c_layer);
- flayer = D_forecv->c_layer;
-
- RecreateCanvasChain();
- RethinkDisplayViewports();
- ResizeLayersToCanvases();
-}
-
-void
-OneCanvas()
-{
- struct canvas *cv = D_forecv, *ocv = 0;
-
- if (cv->c_slprev)
- {
- ocv = cv->c_slprev;
- cv->c_slprev->c_slnext = cv->c_slnext;
- }
- if (cv->c_slnext)
- {
- ocv = cv->c_slnext;
- cv->c_slnext->c_slprev = cv->c_slprev;
- }
- if (!ocv)
- return;
- if (cv->c_slback && cv->c_slback->c_slperp == cv)
- cv->c_slback->c_slperp = ocv;
- cv->c_slorient = SLICE_UNKN;
- while (D_canvas.c_slperp)
- FreeCanvas(D_canvas.c_slperp);
- cv = D_forecv;
- D_canvas.c_slperp = cv;
- cv->c_slback = &D_canvas;
- cv->c_slnext = 0;
- cv->c_slprev = 0;
- ASSERT(!cv->c_slperp);
- if (!captionalways)
- D_canvas.c_ye++; /* caption line no longer needed */
- ResizeCanvas(&D_canvas);
- RecreateCanvasChain();
- RethinkDisplayViewports();
- ResizeLayersToCanvases();
-}
-
-int
-RethinkDisplayViewports()
-{
- struct canvas *cv;
- struct viewport *vp, *vpn;
-
- /* free old viewports */
- for (cv = display->d_cvlist; cv; cv = cv->c_next)
- {
- for (vp = cv->c_vplist; vp; vp = vpn)
- {
- vp->v_canvas = 0;
- vpn = vp->v_next;
- bzero((char *)vp, sizeof(*vp));
- free(vp);
- }
- cv->c_vplist = 0;
- }
- display->d_vpxmin = -1;
- display->d_vpxmax = -1;
-
- for (cv = display->d_cvlist; cv; cv = cv->c_next)
- {
- if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0)
- return -1;
-#ifdef HOLE
- vp->v_canvas = cv;
- vp->v_xs = cv->c_xs;
- vp->v_ys = (cv->c_ys + cv->c_ye) / 2;
- vp->v_xe = cv->c_xe;
- vp->v_ye = cv->c_ye;
- vp->v_xoff = cv->c_xoff;
- vp->v_yoff = cv->c_yoff;
- vp->v_next = cv->c_vplist;
- cv->c_vplist = vp;
-
- if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0)
- return -1;
- vp->v_canvas = cv;
- vp->v_xs = (cv->c_xs + cv->c_xe) / 2;
- vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4;
- vp->v_xe = cv->c_xe;
- vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1;
- vp->v_xoff = cv->c_xoff;
- vp->v_yoff = cv->c_yoff;
- vp->v_next = cv->c_vplist;
- cv->c_vplist = vp;
-
- if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0)
- return -1;
- vp->v_canvas = cv;
- vp->v_xs = cv->c_xs;
- vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4;
- vp->v_xe = (3 * cv->c_xs + cv->c_xe) / 4 - 1;
- vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1;
- vp->v_xoff = cv->c_xoff;
- vp->v_yoff = cv->c_yoff;
- vp->v_next = cv->c_vplist;
- cv->c_vplist = vp;
-
- if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0)
- return -1;
- vp->v_canvas = cv;
- vp->v_xs = cv->c_xs;
- vp->v_ys = cv->c_ys;
- vp->v_xe = cv->c_xe;
- vp->v_ye = (3 * cv->c_ys + cv->c_ye) / 4 - 1;
- vp->v_xoff = cv->c_xoff;
- vp->v_yoff = cv->c_yoff;
- vp->v_next = cv->c_vplist;
- cv->c_vplist = vp;
-#else
- vp->v_canvas = cv;
- vp->v_xs = cv->c_xs;
- vp->v_ys = cv->c_ys;
- vp->v_xe = cv->c_xe;
- vp->v_ye = cv->c_ye;
- vp->v_xoff = cv->c_xoff;
- vp->v_yoff = cv->c_yoff;
- vp->v_next = cv->c_vplist;
- cv->c_vplist = vp;
-#endif
-
- if (cv->c_xs < display->d_vpxmin || display->d_vpxmin == -1)
- display->d_vpxmin = cv->c_xs;
- if (cv->c_xe > display->d_vpxmax || display->d_vpxmax == -1)
- display->d_vpxmax = cv->c_xe;
- }
- return 0;
-}
-
-void
-RethinkViewportOffsets(cv)
-struct canvas *cv;
-{
- struct viewport *vp;
-
- for (vp = cv->c_vplist; vp; vp = vp->v_next)
- {
- vp->v_xoff = cv->c_xoff;
- vp->v_yoff = cv->c_yoff;
- }
-}
-
/*
* if the adaptflag is on, we keep the size of this display, else
* we may try to restore our old window sizes.
@@ -1154,8 +435,8 @@ int adapt;
ASSERT(display);
ASSERT(D_tcinited);
D_top = D_bot = -1;
- AddCStr(D_TI);
AddCStr(D_IS);
+ AddCStr(D_TI);
/* Check for toggle */
if (D_IM && strcmp(D_IM, D_EI))
AddCStr(D_EI);
@@ -1181,7 +462,7 @@ int adapt;
ResizeDisplay(D_defwidth, D_defheight);
ChangeScrollRegion(0, D_height - 1);
D_x = D_y = 0;
- Flush();
+ Flush(3);
ClearAll();
debug1("we %swant to adapt all our windows to the display\n",
(adapt) ? "" : "don't ");
@@ -1204,6 +485,8 @@ FinitTerm()
KeypadMode(0);
CursorkeysMode(0);
CursorVisibility(0);
+ if (D_mousetrack)
+ D_mousetrack = 0;
MouseMode(0);
SetRendition(&mchar_null);
SetFlow(FLOW_NOW);
@@ -1222,7 +505,7 @@ FinitTerm()
AddChar('\n');
AddCStr(D_TE);
}
- Flush();
+ Flush(3);
}
@@ -1335,7 +618,15 @@ int c;
AddCStr(D_CE0);
goto addedutf8;
}
- AddUtf8(c);
+ if (c < 0x80)
+ {
+ if (D_xtable && D_xtable[(int)(unsigned char)D_rend.font] && D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c])
+ AddStr(D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c]);
+ else
+ AddChar(c);
+ }
+ else
+ AddUtf8(c);
goto addedutf8;
}
# endif
@@ -1521,7 +812,13 @@ void
MouseMode(mode)
int mode;
{
- if (display && D_mouse != mode)
+ if (!display)
+ return;
+
+ if (mode < D_mousetrack)
+ mode = D_mousetrack;
+
+ if (D_mouse != mode)
{
char mousebuf[20];
if (!D_CXT)
@@ -2660,7 +1957,7 @@ char *msg;
return; /* XXX: better */
AddStr(msg);
AddStr("\r\n");
- Flush();
+ Flush(0);
return;
}
if (!use_hardstatus || !D_HS)
@@ -2677,19 +1974,11 @@ char *msg;
if (strcmp(msg, D_status_lastmsg) == 0)
{
debug("same message - increase timeout");
- SetTimeout(&D_statusev, MsgWait);
+ if (!D_status_obufpos)
+ SetTimeout(&D_statusev, MsgWait);
return;
}
- if (!D_status_bell)
- {
- struct timeval now;
- int ti;
- gettimeofday(&now, NULL);
- ti = (now.tv_sec - D_status_time.tv_sec) * 1000 + (now.tv_usec - D_status_time.tv_usec) / 1000;
- if (ti < MsgMinWait)
- DisplaySleep1000(MsgMinWait - ti, 0);
- }
- RemoveStatus();
+ RemoveStatusMinWait();
}
for (s = t = msg; *s && t - msg < max; ++s)
if (*s == BELL)
@@ -2746,15 +2035,15 @@ char *msg;
D_status = STATUS_ON_HS;
ShowHStatus(msg);
}
- Flush();
- if (!display)
- return;
+
+ D_status_obufpos = D_obufp - D_obuf;
+ ASSERT(D_status_obufpos > 0);
+
if (D_status == STATUS_ON_WIN)
{
struct display *olddisplay = display;
struct layer *oldflayer = flayer;
- ASSERT(D_obuffree == D_obuflen);
/* this is copied over from RemoveStatus() */
D_status = 0;
GotoPos(0, STATLINE);
@@ -2765,17 +2054,8 @@ char *msg;
LaySetCursor();
display = olddisplay;
flayer = oldflayer;
- D_status_obuflen = D_obuflen;
- D_status_obuffree = D_obuffree;
- D_obuffree = D_obuflen = 0;
D_status = STATUS_ON_WIN;
}
- gettimeofday(&D_status_time, NULL);
- SetTimeout(&D_statusev, MsgWait);
- evenq(&D_statusev);
-#ifdef HAVE_BRAILLE
- RefreshBraille(); /* let user see multiple Msg()s */
-#endif
}
void
@@ -2798,6 +2078,7 @@ RemoveStatus()
D_status_obuffree = -1;
}
D_status = 0;
+ D_status_obufpos = 0;
D_status_bell = 0;
evdeq(&D_statusev);
olddisplay = display;
@@ -2820,6 +2101,86 @@ RemoveStatus()
flayer = oldflayer;
}
+/* Remove the status but make sure that it is seen for MsgMinWait ms */
+static void
+RemoveStatusMinWait()
+{
+ /* XXX: should flush output first if D_status_obufpos is set */
+ if (!D_status_bell && !D_status_obufpos)
+ {
+ struct timeval now;
+ int ti;
+ gettimeofday(&now, NULL);
+ ti = (now.tv_sec - D_status_time.tv_sec) * 1000 + (now.tv_usec - D_status_time.tv_usec) / 1000;
+ if (ti < MsgMinWait)
+ DisplaySleep1000(MsgMinWait - ti, 0);
+ }
+ RemoveStatus();
+}
+
+#ifdef UTF8
+static int
+strlen_onscreen(unsigned char *c, unsigned char *end)
+{
+ int len = 0;
+ char *s = c;
+ while (*c && (!end || c < end))
+ {
+ int v, dec = 0;
+ do
+ {
+ v = FromUtf8(*c++, &dec);
+ if (v == -2)
+ c--;
+ }
+ while (v < 0 && (!end || c < end));
+ if (!utf8_iscomb(v))
+ {
+ if (utf8_isdouble(v))
+ len++;
+ len++;
+ }
+ }
+
+ return len;
+}
+
+static int
+PrePutWinMsg(s, start, max)
+char *s;
+int start, max;
+{
+ /* Avoid double-encoding problem for a UTF-8 message on a UTF-8 locale.
+ Ideally, this would not be necessary. But fixing it the Right Way will
+ probably take way more time. So this will have to do for now. */
+ if (D_encoding == UTF8)
+ {
+ int chars = strlen_onscreen(s + start, s + max);
+ D_encoding = 0;
+ PutWinMsg(s, start, max);
+ D_encoding = UTF8;
+ D_x -= (max - chars); /* Yak! But this is necessary to count for
+ the fact that not every byte represents a
+ character. */
+ return start + chars;
+ }
+ else
+ {
+ PutWinMsg(s, start, max);
+ return max;
+ }
+}
+#else
+static int
+PrePutWinMsg(s, start, max)
+char *s;
+int start, max;
+{
+ PutWinMsg(s, start, max);
+ return max;
+}
+#endif
+
/* refresh the display's hstatus line */
void
ShowHStatus(str)
@@ -2864,7 +2225,7 @@ char *str;
l = D_width;
GotoPos(0, D_height - 1);
SetRendition(captionalways || D_cvlist == 0 || D_cvlist->c_next ? &mchar_null: &mchar_so);
- PutWinMsg(str, 0, l);
+ l = PrePutWinMsg(str, 0, l);
if (!captionalways && D_cvlist && !D_cvlist->c_next)
while (l++ < D_width)
PUTCHARLP(' ');
@@ -2966,26 +2327,7 @@ int y, from, to, isblank;
return; /* can't refresh status */
}
- /* The following check makes plenty of sense. Unfortunately,
- vte-based terminals (notably gnome-terminal) experience a quirk
- that causes the final line not to update properly when it falls outside
- the scroll region; clearing the line with D_CE avoids the glitch,
- so we'll disable this perfectly sensible shortcut until such a time
- as widespread vte installations lack the glitch.
-
- See http://bugzilla.gnome.org/show_bug.cgi?id=542087 for current
- status of the VTE bug report, and
- https://savannah.gnu.org/bugs/index.php?23699 for the history from
- the Savannah BTS. */
-#if 0
- if (y == D_height - 1 && D_has_hstatus == HSTATUS_LASTLINE)
- {
- RefreshHStatus();
- return;
- }
-#endif
-
- if (isblank == 0 && D_CE && to == D_width - 1 && from < to)
+ if (isblank == 0 && D_CE && to == D_width - 1 && from < to && D_status != STATUS_ON_HS)
{
GotoPos(from, y);
if (D_UT || D_BE)
@@ -2993,6 +2335,13 @@ int y, from, to, isblank;
AddCStr(D_CE);
isblank = 1;
}
+
+ if (y == D_height - 1 && D_has_hstatus == HSTATUS_LASTLINE)
+ {
+ RefreshHStatus();
+ return;
+ }
+
while (from <= to)
{
lcv = 0;
@@ -3011,7 +2360,7 @@ int y, from, to, isblank;
SetRendition(&mchar_so);
if (l > xx - cv->c_xs + 1)
l = xx - cv->c_xs + 1;
- PutWinMsg(buf, from - cv->c_xs, l);
+ l = PrePutWinMsg(buf, from - cv->c_xs, l);
from = cv->c_xs + l;
for (; from <= xx; from++)
PUTCHARLP(' ');
@@ -3181,8 +2530,8 @@ int from, to, y, bce;
void
DisplayLine(oml, ml, y, from, to)
struct mline *oml, *ml;
-int from, to, y;{
-
+int from, to, y;
+{
register int x;
int last2flag = 0, delete_lp = 0;
@@ -3503,12 +2852,19 @@ int newtop, newbot;
}
#ifdef RXVT_OSC
+#define WT_FLAG "2" /* change to "0" to set both title and icon */
+
void
SetXtermOSC(i, s)
int i;
char *s;
{
- static char oscs[] = "1;\000\00020;\00039;\00049;\000";
+ static char *oscs[][2] = {
+ { WT_FLAG ";", "screen" }, /* set window title */
+ { "20;", "" }, /* background */
+ { "39;", "black" }, /* default foreground (black?) */
+ { "49;", "white" } /* default background (white?) */
+ };
ASSERT(display);
if (!D_CXT)
@@ -3517,17 +2873,13 @@ char *s;
s = "";
if (!D_xtermosc[i] && !*s)
return;
- if (i == 0 && !*s)
- s = "screen"; /* always set icon name */
- if (i == 1 && !*s)
- s = ""; /* no background */
- if (i == 2 && !*s)
- s = "black"; /* black text */
- if (i == 3 && !*s)
- s = "white"; /* on white background */
+ if (i == 0 && !D_xtermosc[0])
+ AddStr("\033[22;" WT_FLAG "t"); /* stack titles (xterm patch #251) */
+ if (!*s)
+ s = oscs[i][1];
D_xtermosc[i] = 1;
AddStr("\033]");
- AddStr(oscs + i * 4);
+ AddStr(oscs[i][0]);
AddStr(s);
AddChar(7);
}
@@ -3538,7 +2890,10 @@ ClearAllXtermOSC()
int i;
for (i = 3; i >= 0; i--)
SetXtermOSC(i, 0);
+ if (D_xtermosc[0])
+ AddStr("\033[23;" WT_FLAG "t"); /* unstack titles (xterm patch #251) */
}
+#undef WT_FLAG
#endif
/*
@@ -3588,9 +2943,11 @@ int n;
}
void
-Flush()
+Flush(progress)
+int progress;
{
register int l;
+ int wr;
register char *p;
ASSERT(display);
@@ -3606,29 +2963,57 @@ Flush()
return;
}
p = D_obuf;
- if (fcntl(D_userfd, F_SETFL, 0))
- debug1("Warning: BLOCK fcntl failed: %d\n", errno);
+ if (!progress)
+ {
+ if (fcntl(D_userfd, F_SETFL, 0))
+ debug1("Warning: BLOCK fcntl failed: %d\n", errno);
+ }
while (l)
{
- register int wr;
+ if (progress)
+ {
+ fd_set w;
+ FD_ZERO(&w);
+ FD_SET(D_userfd, &w);
+ struct timeval t;
+ t.tv_sec = progress;
+ t.tv_usec = 0;
+ wr = select(FD_SETSIZE, (fd_set *)0, &w, (fd_set *)0, &t);
+ if (wr == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ debug1("Warning: select failed: %d\n", errno);
+ break;
+ }
+ if (wr == 0)
+ {
+ /* no progress after 3 seconds. sorry. */
+ debug1("Warning: no progress after %d seconds\n", progress);
+ break;
+ }
+ }
wr = write(D_userfd, p, l);
- if (wr <= 0)
+ if (wr <= 0)
{
- if (errno == EINTR)
+ if (errno == EINTR)
continue;
debug1("Writing to display: %d\n", errno);
- wr = l;
+ break;
}
- if (!display)
- return;
D_obuffree += wr;
p += wr;
l -= wr;
}
+ if (l)
+ debug1("Warning: Flush could not write %d bytes\n", l);
D_obuffree += l;
D_obufp = D_obuf;
- if (fcntl(D_userfd, F_SETFL, FNBLOCK))
- debug1("Warning: NBLOCK fcntl failed: %d\n", errno);
+ if (!progress)
+ {
+ if (fcntl(D_userfd, F_SETFL, FNBLOCK))
+ debug1("Warning: NBLOCK fcntl failed: %d\n", errno);
+ }
if (D_blocked == 1)
D_blocked = 0;
D_blocked_fuzz = 0;
@@ -3666,16 +3051,7 @@ Resize_obuf()
if (D_status_obuffree >= 0)
{
ASSERT(D_obuffree == -1);
- if (!D_status_bell)
- {
- struct timeval now;
- int ti;
- gettimeofday(&now, NULL);
- ti = (now.tv_sec - D_status_time.tv_sec) * 1000 + (now.tv_usec - D_status_time.tv_usec) / 1000;
- if (ti < MsgMinWait)
- DisplaySleep1000(MsgMinWait - ti, 0);
- }
- RemoveStatus();
+ RemoveStatusMinWait();
if (--D_obuffree > 0) /* redo AddChar decrement */
return;
}
@@ -3757,8 +3133,8 @@ NukePending()
D_obufp = D_obuf;
D_obuffree += len;
D_top = D_bot = -1;
- AddCStr(D_TI);
AddCStr(D_IS);
+ AddCStr(D_TI);
/* Turn off all attributes. (Tim MacKenzie) */
if (D_ME)
AddCStr(D_ME);
@@ -3843,6 +3219,8 @@ char *data;
len = D_obufp - D_obuf;
if (len < size)
size = len;
+ if (D_status_obufpos && size > D_status_obufpos)
+ size = D_status_obufpos;
ASSERT(len >= 0);
size = write(D_userfd, D_obuf, size);
if (size >= 0)
@@ -3855,6 +3233,30 @@ char *data;
}
D_obufp -= size;
D_obuffree += size;
+ if (D_status_obufpos)
+ {
+ D_status_obufpos -= size;
+ if (!D_status_obufpos)
+ {
+ debug("finished writing the status message\n");
+ /* we're finished displaying the message! */
+ if (D_status == STATUS_ON_WIN)
+ {
+ /* setup continue trigger */
+ D_status_obuflen = D_obuflen;
+ D_status_obuffree = D_obuffree;
+ /* setting obbuffree to 0 will make AddChar call
+ * ResizeObuf */
+ D_obuffree = D_obuflen = 0;
+ }
+ gettimeofday(&D_status_time, NULL);
+ SetTimeout(&D_statusev, MsgWait);
+ evenq(&D_statusev);
+#ifdef HAVE_BRAILLE
+ RefreshBraille(); /* let user see multiple Msg()s */
+#endif
+ }
+ }
if (D_blocked_fuzz)
{
D_blocked_fuzz -= size;
@@ -3882,7 +3284,7 @@ char *data;
Activate(D_fore ? D_fore->w_norefresh : 0);
D_blocked_fuzz = D_obufp - D_obuf;
}
- }
+ }
else
{
#ifdef linux
@@ -4016,15 +3418,29 @@ char *data;
y = bp[4] - 33;
if (x >= D_forecv->c_xs && x <= D_forecv->c_xe && y >= D_forecv->c_ys && y <= D_forecv->c_ye)
{
- x -= D_forecv->c_xoff;
- y -= D_forecv->c_yoff;
- if (x >= 0 && x < D_forecv->c_layer->l_width && y >= 0 && y < D_forecv->c_layer->l_height)
+ if ((D_fore && D_fore->w_mouse) || (D_mousetrack && D_forecv->c_layer->l_mode == 1))
+ {
+ /* Send clicks only if the window is expecting clicks */
+ x -= D_forecv->c_xoff;
+ y -= D_forecv->c_yoff;
+ if (x >= 0 && x < D_forecv->c_layer->l_width && y >= 0 && y < D_forecv->c_layer->l_height)
+ {
+ bp[3] = x + 33;
+ bp[4] = y + 33;
+ i -= 4;
+ bp += 4;
+ continue;
+ }
+ }
+ }
+ else if (D_mousetrack && bp[2] == '#')
+ {
+ /* 'focus' to the clicked region, only on mouse up */
+ struct canvas *cv = FindCanvas(x, y);
+ if (cv)
{
- bp[3] = x + 33;
- bp[4] = y + 33;
- i -= 4;
- bp += 4;
- continue;
+ SetForeCanvas(display, cv);
+ /* XXX: Do we want to reset the input buffer? */
}
}
if (bp[0] == '[')
@@ -4121,29 +3537,6 @@ char *data;
}
}
-static void
-cv_winid_fn(ev, data)
-struct event *ev;
-char *data;
-{
- int ox, oy;
- struct canvas *cv = (struct canvas *)data;
-
- display = cv->c_display;
- if (D_status == STATUS_ON_WIN)
- {
- SetTimeout(ev, 1);
- evenq(ev);
- return;
- }
- ox = D_x;
- oy = D_y;
- if (cv->c_ye + 1 < D_height)
- RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
- if (ox != -1 && oy != -1)
- GotoPos(ox, oy);
-}
-
#ifdef MAPKEYS
static void
disp_map_fn(ev, data)
@@ -4367,7 +3760,7 @@ char **cmdv;
#endif
display = 0;
execvpe(*cmdv, cmdv, NewEnv + 3);
- Panic(errno, *cmdv);
+ Panic(errno, "%s", *cmdv);
default:
break;
}
@@ -4377,338 +3770,6 @@ char **cmdv;
ClearAll();
}
-#endif
-
-struct layout *layouts;
-struct layout *laytab[MAXLAY];
-struct layout *layout_last, layout_last_marker;
-struct layout *layout_attach = &layout_last_marker;
-
-void
-FreeLayoutCv(cv)
-struct canvas *cv;
-{
- struct canvas *cnext, *c = cv;
- for (; cv; cv = cnext)
- {
- if (cv->c_slperp)
- {
- FreeLayoutCv(cv->c_slperp);
- free(cv->c_slperp);
- cv->c_slperp = 0;
- }
- cnext = cv->c_slnext;
- cv->c_slnext = 0;
- if (cv != c)
- free(cv);
- }
-}
-
-static void
-DupLayoutCv(cvf, cvt, save)
-struct canvas *cvf, *cvt;
-int save;
-{
- while(cvf)
- {
- cvt->c_slorient = cvf->c_slorient;
- cvt->c_slweight = cvf->c_slweight;
- if (cvf == D_forecv)
- D_forecv = cvt;
- if (!save)
- {
- cvt->c_display = display;
- if (!cvf->c_slperp)
- {
- cvt->c_captev.type = EV_TIMEOUT;
- cvt->c_captev.data = (char *)cvt;
- cvt->c_captev.handler = cv_winid_fn;
- cvt->c_blank.l_cvlist = 0;
- cvt->c_blank.l_layfn = &BlankLf;
- cvt->c_blank.l_bottom = &cvt->c_blank;
- }
- cvt->c_layer = cvf->c_layer;
- }
- else
- {
- struct win *p = cvf->c_layer ? Layer2Window(cvf->c_layer) : 0;
- cvt->c_layer = p ? &p->w_layer : 0;
- }
- if (cvf->c_slperp)
- {
- cvt->c_slperp = (struct canvas *)calloc(1, sizeof(struct canvas));
- cvt->c_slperp->c_slback = cvt;
- CanvasInitBlank(cvt->c_slperp);
- DupLayoutCv(cvf->c_slperp, cvt->c_slperp, save);
- }
- if (cvf->c_slnext)
- {
- cvt->c_slnext = (struct canvas *)calloc(1, sizeof(struct canvas));
- cvt->c_slnext->c_slprev = cvt;
- cvt->c_slnext->c_slback = cvt->c_slback;
- CanvasInitBlank(cvt->c_slnext);
- }
- cvf = cvf->c_slnext;
- cvt = cvt->c_slnext;
- }
-}
-
-void
-PutWindowCv(cv)
-struct canvas *cv;
-{
- struct win *p;
- for (; cv; cv = cv->c_slnext)
- {
- if (cv->c_slperp)
- {
- PutWindowCv(cv->c_slperp);
- continue;
- }
- p = cv->c_layer ? (struct win *)cv->c_layer->l_data : 0;
- cv->c_layer = 0;
- SetCanvasWindow(cv, p);
- }
-}
-
-struct layout *
-CreateLayout(title, startat)
-char *title;
-int startat;
-{
- struct layout *lay;
- int i;
-
- if (startat >= MAXLAY || startat < 0)
- startat = 0;
- for (i = startat; ;)
- {
- if (!laytab[i])
- break;
- if (++i == MAXLAY)
- i = 0;
- if (i == startat)
- {
- Msg(0, "No more layouts\n");
- return 0;
- }
- }
- lay = (struct layout *)calloc(1, sizeof(*lay));
- lay->lay_title = SaveStr(title);
- lay->lay_autosave = 1;
- lay->lay_number = i;
- laytab[i] = lay;
- lay->lay_next = layouts;
- layouts = lay;
- return lay;
-}
-
-void
-SaveLayout(name, cv)
-char *name;
-struct canvas *cv;
-{
- struct layout *lay;
- struct canvas *fcv;
- for (lay = layouts; lay; lay = lay->lay_next)
- if (!strcmp(lay->lay_title, name))
- break;
- if (lay)
- FreeLayoutCv(&lay->lay_canvas);
- else
- lay = CreateLayout(name, 0);
- if (!lay)
- return;
- fcv = D_forecv;
- DupLayoutCv(cv, &lay->lay_canvas, 1);
- lay->lay_forecv = D_forecv;
- D_forecv = fcv;
- D_layout = lay;
-}
-
-void
-AutosaveLayout(lay)
-struct layout *lay;
-{
- struct canvas *fcv;
- if (!lay || !lay->lay_autosave)
- return;
- FreeLayoutCv(&lay->lay_canvas);
- fcv = D_forecv;
- DupLayoutCv(&D_canvas, &lay->lay_canvas, 1);
- lay->lay_forecv = D_forecv;
- D_forecv = fcv;
-}
-
-struct layout *
-FindLayout(name)
-char *name;
-{
- struct layout *lay;
- char *s;
- int i;
- for (i = 0, s = name; *s >= '0' && *s <= '9'; s++)
- i = i * 10 + (*s - '0');
- if (!*s && s != name && i >= 0 && i < MAXLAY)
- return laytab[i];
- for (lay = layouts; lay; lay = lay->lay_next)
- if (!strcmp(lay->lay_title, name))
- break;
- return lay;
-}
-
-void
-LoadLayout(lay, cv)
-struct layout *lay;
-struct canvas *cv;
-{
- AutosaveLayout(D_layout);
- if (!lay)
- {
- while (D_canvas.c_slperp)
- FreeCanvas(D_canvas.c_slperp);
- MakeDefaultCanvas();
- SetCanvasWindow(D_forecv, 0);
- D_layout = 0;
- return;
- }
- while (D_canvas.c_slperp)
- FreeCanvas(D_canvas.c_slperp);
- D_cvlist = 0;
- D_forecv = lay->lay_forecv;
- DupLayoutCv(&lay->lay_canvas, &D_canvas, 0);
- D_canvas.c_ye = D_height - 1 - ((D_canvas.c_slperp && D_canvas.c_slperp->c_slnext) || captionalways) - (D_has_hstatus == HSTATUS_LASTLINE);
- ResizeCanvas(&D_canvas);
- RecreateCanvasChain();
- RethinkDisplayViewports();
- PutWindowCv(&D_canvas);
- ResizeLayersToCanvases();
- D_layout = lay;
-}
-
-void
-NewLayout(title, startat)
-char *title;
-int startat;
-{
- struct layout *lay;
- struct canvas *fcv;
-
- lay = CreateLayout(title, startat);
- if (!lay)
- return;
- LoadLayout(0, &D_canvas);
- fcv = D_forecv;
- DupLayoutCv(&D_canvas, &lay->lay_canvas, 1);
- lay->lay_forecv = D_forecv;
- D_forecv = fcv;
- D_layout = lay;
- lay->lay_autosave = 1;
-}
-
-static char *
-AddLayoutsInfo(buf, len, where)
-char *buf;
-int len;
-int where;
-{
- char *s, *ss, *t;
- struct layout *p, **pp;
- int l;
-
- s = ss = buf;
- for (pp = laytab; pp < laytab + MAXLAY; pp++)
- {
- if (pp - laytab == where && ss == buf)
- ss = s;
- if ((p = *pp) == 0)
- continue;
- t = p->lay_title;
- l = strlen(t);
- if (l > 20)
- l = 20;
- if (s - buf + l > len - 24)
- break;
- if (s > buf)
- {
- *s++ = ' ';
- *s++ = ' ';
- }
- sprintf(s, "%d", p->lay_number);
- if (p->lay_number == where)
- ss = s;
- s += strlen(s);
- if (display && p == D_layout)
- *s++ = '*';
- *s++ = ' ';
- strncpy(s, t, l);
- s += l;
- }
- *s = 0;
- return ss;
-}
-
-void
-ShowLayouts(where)
-int where;
-{
- char buf[1024];
- char *s, *ss;
+#endif /* BLANKER_PRG */
- if (!display)
- return;
- if (!layouts)
- {
- Msg(0, "No layouts defined\n");
- return;
- }
- if (where == -1 && D_layout)
- where = D_layout->lay_number;
- ss = AddLayoutsInfo(buf, sizeof(buf), where);
- s = buf + strlen(buf);
- if (ss - buf > D_width / 2)
- {
- ss -= D_width / 2;
- if (s - ss < D_width)
- {
- ss = s - D_width;
- if (ss < buf)
- ss = buf;
- }
- }
- else
- ss = buf;
- Msg(0, "%s", ss);
-}
-
-void
-RemoveLayout(lay)
-struct layout *lay;
-{
- struct layout **layp = &layouts;
-
- for (; *layp; layp = &(*layp)->lay_next)
- {
- if (*layp == lay)
- {
- *layp = lay->lay_next;
- break;
- }
- }
- laytab[lay->lay_number] = (struct layout *)0;
-
- if (display && D_layout == lay)
- D_layout = (struct layout *)0;
-
- FreeLayoutCv(&lay->lay_canvas);
-
- if (lay->lay_title)
- free(lay->lay_title);
- free(lay);
-
- if (layouts)
- LoadLayout((display && D_layout) ? D_layout : *layp ? *layp : layouts,
- display ? &D_canvas : (struct canvas *)0);
- Activate(0);
-}
diff --git a/src/display.h b/src/display.h
index de25859..e8b3b80 100644
--- a/src/display.h
+++ b/src/display.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,9 +24,16 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
+#ifndef SCREEN_DISPLAY_H
+#define SCREEN_DISPLAY_H
+
+#include "layout.h"
+#include "canvas.h"
+#include "viewport.h"
+
#ifdef MAPKEYS
#define KMAP_KEYS (T_OCAPS-T_CAPS)
@@ -51,63 +58,6 @@ struct kmap_ext
struct win; /* forward declaration */
-#define MAXLAY 10
-
-#define SLICE_UNKN 0
-#define SLICE_VERT (1 << 0)
-#define SLICE_HORI (1 << 1)
-
-#define SLICE_THIS (1 << 2) /* used in equal test */
-#define SLICE_GLOBAL (1 << 3)
-
-struct canvas
-{
- struct canvas *c_next; /* next canvas on display */
- struct display *c_display; /* back pointer to display */
-
- struct canvas *c_slnext; /* next canvas in display slice */
- struct canvas *c_slprev; /* prev canvas in display slice */
- struct canvas *c_slperp; /* perpendicular slice */
- struct canvas *c_slback; /* perpendicular slice back pointer */
- int c_slorient; /* our slice orientation */
- int c_slweight; /* size ratio */
-
- struct viewport *c_vplist;
- struct layer *c_layer; /* layer on this canvas */
- struct canvas *c_lnext; /* next canvas that displays layer */
- struct layer c_blank; /* bottom layer, always blank */
- int c_xoff; /* canvas x offset on display */
- int c_yoff; /* canvas y offset on display */
- int c_xs;
- int c_xe;
- int c_ys;
- int c_ye;
- struct event c_captev; /* caption changed event */
-};
-
-struct layout
-{
- struct layout *lay_next;
- char *lay_title;
- int lay_number;
- struct canvas lay_canvas;
- struct canvas *lay_forecv;
- struct canvas *lay_cvlist;
- int lay_autosave;
-};
-
-struct viewport
-{
- struct viewport *v_next; /* next vp on canvas */
- struct canvas *v_canvas; /* back pointer to canvas */
- int v_xoff; /* layer x offset on display */
- int v_yoff; /* layer y offset on display */
- int v_xs; /* vp upper left */
- int v_xe; /* vp upper right */
- int v_ys; /* vp lower left */
- int v_ye; /* vp lower right */
-};
-
struct display
{
struct display *d_next; /* linked list */
@@ -150,6 +100,8 @@ struct display
int d_hstatus; /* hardstatus used */
int d_lp_missing; /* last character on bot line missing */
int d_mouse; /* mouse mode */
+ int d_mousetrack; /* set when user wants to use mouse even when the window
+ does not */
#ifdef RXVT_OSC
int d_xtermosc[4]; /* osc used */
#endif
@@ -164,6 +116,7 @@ struct display
int d_status_lasty; /* before status was displayed */
int d_status_obuflen; /* saved obuflen */
int d_status_obuffree; /* saved obuffree */
+ int d_status_obufpos; /* end of status position in obuf */
struct event d_statusev; /* timeout event */
struct event d_hstatusev; /* hstatus changed event */
int d_kaablamm; /* display kaablamm msg */
@@ -274,6 +227,7 @@ extern struct display TheDisplay;
#define D_hstatus DISPLAY(d_hstatus)
#define D_lp_missing DISPLAY(d_lp_missing)
#define D_mouse DISPLAY(d_mouse)
+#define D_mousetrack DISPLAY(d_mousetrack)
#define D_xtermosc DISPLAY(d_xtermosc)
#define D_lpchar DISPLAY(d_lpchar)
#define D_status DISPLAY(d_status)
@@ -286,6 +240,7 @@ extern struct display TheDisplay;
#define D_status_lasty DISPLAY(d_status_lasty)
#define D_status_obuflen DISPLAY(d_status_obuflen)
#define D_status_obuffree DISPLAY(d_status_obuffree)
+#define D_status_obufpos DISPLAY(d_status_obufpos)
#define D_statusev DISPLAY(d_statusev)
#define D_hstatusev DISPLAY(d_hstatusev)
#define D_kaablamm DISPLAY(d_kaablamm)
@@ -357,23 +312,6 @@ do \
} \
while (0)
-#define CV_CALL(cv, cmd) \
-{ \
- struct display *olddisplay = display; \
- struct layer *oldflayer = flayer; \
- struct layer *l = cv->c_layer; \
- struct canvas *cvlist = l->l_cvlist; \
- struct canvas *cvlnext = cv->c_lnext; \
- flayer = l; \
- l->l_cvlist = cv; \
- cv->c_lnext = 0; \
- cmd; \
- flayer = oldflayer; \
- l->l_cvlist = cvlist; \
- cv->c_lnext = cvlnext; \
- display = olddisplay; \
-}
-
#define STATUS_OFF 0
#define STATUS_ON_WIN 1
#define STATUS_ON_HS 2
@@ -383,3 +321,6 @@ while (0)
#define HSTATUS_MESSAGE 2
#define HSTATUS_HS 3
#define HSTATUS_ALWAYS (1<<2)
+
+#endif /* SCREEN_DISPLAY_H */
+
diff --git a/src/doc/screen.1 b/src/doc/screen.1
index 879dc83..a250b92 100644
--- a/src/doc/screen.1
+++ b/src/doc/screen.1
@@ -97,7 +97,9 @@ but will instead supply the command name and its arguments to the window
manager (specified in the $STY environment variable) who will use it to
create the new window.
The above example would start the emacs editor (editing prog.c) and switch
-to its window.
+to its window. - Note that you cannot transport environment variables from
+the invoking shell to the application (emacs in this case), because it is
+forked from the parent screen process, not from the invoking shell.
.PP
If \*Q/etc/utmp\*U is writable by
.IR screen ,
@@ -231,7 +233,11 @@ The use of this option is discouraged.
turns login mode on or off (for /etc/utmp updating).
This can also be defined through the \*Qdeflogin\*U .screenrc command.
.TP 5
-.BR \-ls " and " \-list
+.BR \-ls " [" \fImatch ]
+.PD 0
+.TP 5
+.BR \-list " [" \fImatch ]
+.PD
does not start
.IR screen ,
but prints a list of
@@ -282,12 +288,14 @@ emulation (only affects auto-margin terminals without `LP').
This can also be set in your .screenrc by specifying `OP' in a \*Qtermcap\*U
command.
.TP 5
-.BI "\-p " number_or_name
+.BI "\-p " number_or_name|-|=|+
Preselect a window. This is useful when you want to reattach to a
specific window or you want to send a command via the \*Q-X\*U
option to a specific window. As with screen's select command, \*Q-\*U
selects the blank window. As a special case for reattach, \*Q=\*U
-brings up the windowlist on the blank window.
+brings up the windowlist on the blank window, while a \*Q+\*U
+will create a new window. The command will not be
+executed if the specified window could not be found.
.TP 5
.B \-q
Suppress printing of error messages. In combination with \*Q-ls\*U the exit
@@ -299,6 +307,23 @@ there is no session to resume. 12 (or more) indicates that there are 2 (or
more) sessions to resume and you should specify which one to choose.
In all other cases \*Q-q\*U has no effect.
.TP 5
+.B \-Q
+Some commands now can be queried from a remote session using this
+flag, e.g. 'screen -Q windows'. The commands will send the
+response to the stdout of the querying process. If there was an
+error in the command, then the querying process will exit with
+a non-zero status.
+
+The commands that can be queried now are:
+ \fBecho\fP
+ \fBinfo\fP
+ \fBlastmsg\fP
+ \fBnumber\fP
+ \fBselect\fP
+ \fBtime\fP
+ \fBtitle\fP
+ \fBwindows\fP
+.TP 5
.BR \-r " [" \fIpid.tty.host ]
.PD 0
.TP 5
@@ -326,7 +351,7 @@ had not been specified. The option is set by default if
is run as a login-shell (actually screen uses \*Q-xRR\*U in that case).
For combinations with the \fB\-d\fP/\fB\-D\fP option see there.
.TP 5
-.B \-s
+.BI "\-s " program
sets the default shell to the program specified, instead of the value
in the environment variable $SHELL (or \*Q/bin/sh\*U if not defined).
This can also be defined through the \*Qshell\*U .screenrc command.
@@ -341,6 +366,10 @@ default [\fItty.host\fP] suffix.
sets the title (a.\|k.\|a.) for the default shell or specified program.
See also the \*Qshelltitle\*U .screenrc command.
.TP 5
+.BI "\-T " term
+Set the $TERM enviroment varible using the spcified term as
+opposed to the defualt setting of \fBscreen\fP.
+.TP 5
.B \-U
Run screen in UTF-8 mode. This option tells screen that your terminal
sends and understands UTF-8 encoded characters. It also sets the default
@@ -370,7 +399,6 @@ the \fB-d\fP or \fB-r\fP option to tell screen to look only for
attached or detached screen sessions. Note that this command doesn't
work if the session is password protected.
-
.SH "DEFAULT KEY BINDINGS"
.ta 12n 26n
As mentioned, each
@@ -509,7 +537,7 @@ automatic margins on and off).
.PD
Send a control-s to the current window.
.IP "\fBC-a S\fP (split)"
-Split the current region into two new ones.
+Split the current region horizontally into two new ones.
See also \fIonly, remove, focus\fP.
.IP "\fBC-a t\fP"
.PD 0
@@ -561,6 +589,8 @@ Enter command line mode.
.IP "\fBC-a esc\fP (copy)"
.PD
Enter copy/scrollback mode.
+.IP "\fBC-a C-]\fP"
+.PD 0
.IP "\fBC-a ]\fP (paste .)"
.PD
Write the contents of the paste buffer to the stdin queue of the
@@ -582,6 +612,8 @@ Shows where
comes from, where it went to and why you can use it.
.IP "\fBC-a _\fP (silence)"
Start/stop monitoring the current window for inactivity.
+.IP "\fBC-a |\fP (split -v)"
+Split the current region vertically into two new ones.
.IP "\fBC-a *\fP (displays)"
Show a listing of all currently attached displays.
@@ -1084,7 +1116,8 @@ This command is normally used together with the \*Qidle\*U command.
.B blankerprg
.RI [ "program args" ]
.PP
-Defines a blanker program. Disables the blanker program if no
+Defines a blanker program. Disables the blanker program if an
+empty argument is given. Shows the currently set blanker program if no
arguments are given.
.sp
.ne 3
@@ -1550,6 +1583,12 @@ Same as the \fBmonitor\fP command except that the default setting for new
windows is changed. Initial setting is `off'.
.sp
.ne 3
+.BR "defmousetrack on" | off
+.PP
+Same as the \fBmousetrack\fP command except that the default setting for new
+windows is changed. Initial setting is `off'.
+.sp
+.ne 3
.B defnonblock
.BR on | off | \fInumsecs
.PP
@@ -1645,7 +1684,7 @@ Shows a tabular listing of all currently connected user front-ends (displays).
This is most useful for multiuser sessions.
.sp
.ne 3
-.BR "digraph " [ \fIpreset ]
+.BR "digraph " [ \fIpreset [ \fI unicode-value ] ]
.PP
This command prompts the user for a digraph sequence. The next
two characters typed are looked up in a builtin table and the
@@ -1659,6 +1698,11 @@ number instead. The optional argument
is treated as user input, thus one can create an \*Qumlaut\*U key.
For example the command "bindkey ^K digraph '"'" enables the user
to generate an a-umlaut by typing CTRL-K a.
+When a non-zero
+.I unicode-value
+is specified, a new digraph is created with the specified preset. The digraph is unset
+if a zero value is provided for the
+.I unicode-value.
.sp
.ne 3
.B dumptermcap
@@ -1855,6 +1899,20 @@ region respectively. Useful bindings are (j and k as in vi)
Note that \fBk\fP is traditionally bound to the \fIkill\fP command.
.sp
.ne 3
+.BI "focusminsize [ ( " width "|max|_ ) ( " height "|max|_ ) ]"
+.PP
+This forces any currently selected region to be automatically
+resized at least a certain \fIwidth\fP and \fIheight\fP. All
+other surrounding regions will be resized in order to accommodate.
+This constraint follows everytime the \*Qfocus\*U command is
+used. The \*Qresize\*U command can be used to increase either
+dimension of a region, but never below what is set with
+\*Qfocusminsize\*U. The underscore `_' is a synonym for
+\fBmax\fP. Setting a \fIwidth\fP and \fIheight\fP of `0 0'
+(zero zero) will undo any constraints and allow for manual resizing.
+Without any parameters, the minimum width and height is shown.
+.sp
+.ne 3
.BR "gr " [ on | off ]
.PP
Turn GR charset switching on/off. Whenever screen sees an input
@@ -1864,6 +1922,15 @@ default (see also \*Qdefgr\*U) is not to process GR switching because
otherwise the ISO88591 charset would not work.
.sp
.ne 3
+.BI group
+.RI [ grouptitle ]
+.PP
+Change or show the group the current window belongs to. Windows can
+be moved around between different groups by specifying the name of
+the destination group. Without specifying a group, the title of the
+current group is displayed.
+.sp
+.ne 3
.B hardcopy
.RB [ -h ]
.RI [ file ]
@@ -2002,7 +2069,7 @@ Sets a command that is run after the specified number of seconds
inactivity is reached. This command will normally be the \*Qblanker\*U
command to create a screen blanker, but it can be any screen command.
If no command is specified, only the timeout is set. A timeout of
-zero (ot the special timeout \fBoff\fP) disables the timer.
+zero (or the special timeout \fBoff\fP) disables the timer.
If no arguments are given, the current settings are displayed.
.sp
.ne 3
@@ -2085,6 +2152,123 @@ away when you press a key (unless your terminal has a hardware status line).
Refer to the commands \*Qmsgwait\*U and \*Qmsgminwait\*U for fine tuning.
.sp
.ne 3
+.BR "layout new " [\fItitle\fP]
+.PP
+Create a new layout. The screen will change to one whole region
+and be switched to the blank window. From here, you build the
+regions and the windows they show as you desire. The new layout
+will be numbered with the smallest available integer, starting
+with zero. You can optionally give a title to your new layout.
+Otherwise, it will have a default title of \*Qlayout\*U. You
+can always change the title later by using the command
+\fBlayout title\fP.
+.sp
+.ne 3
+.BR "layout remove " [\fIn|title\fP]
+.PP
+Remove, or in other words, delete the specified layout. Either
+the number or the title can be specified. Without either
+specification, \fIscreen\fP will remove the current layout.
+
+Removing a layout does not affect your set windows or regions.
+.sp
+.ne 3
+.B layout next
+.PP
+Switch to the next layout available
+.sp
+.ne 3
+.B layout prev
+.PP
+Switch to the previous layout available
+.sp
+.ne 3
+.BR "layout select " [\fIn|title\fP]
+.PP
+Select the desired layout. Either the number or the title can
+be specified. Without either specification, \fIscreen\fP will
+prompt and ask which screen is desired. To see which layouts are
+available, use the \fBlayout show\fP command.
+.sp
+.ne 3
+.B layout show
+.PP
+List on the message line the number(s) and title(s) of the available
+layout(s). The current layout is flagged.
+.sp
+.ne 3
+.BR "layout title " [\fItitle\fP]
+.PP
+Change or display the title of the current layout. A string given
+will be used to name the layout. Without any options, the current
+title and number is displayed on the message line.
+.sp
+.ne 3
+.BR "layout number " [\fIn\fP]
+.PP
+Change or display the number of the current layout. An integer given
+will be used to number the layout. Without any options, the current
+number and title is displayed on the message line.
+.sp
+.ne 3
+.BR "layout attach " [\fItitle\fP|\fB:last\fP]
+.PP
+Change or display which layout to reattach back to. The default is
+\fB:last\fP, which tells \fIscreen\fP to reattach back to the last
+used layout just before detachment. By supplying a title, You can
+instruct \fIscreen\fP to reattach to a particular layout regardless
+which one was used at the time of detachment. Without any options,
+the layout to reattach to will be shown in the message line.
+.sp
+.ne 3
+.BR "layout save " [\fIn|title\fP]
+.PP
+Remember the current arrangement of regions. When used, \fIscreen\fP
+will remember the arrangement of vertically and horizontally split
+regions. This arrangement is restored when a \fIscreen\fP session
+is reattached or switched back from a different layout. If the
+session ends or the \fIscreen\fP process dies, the layout
+arrangements are lost. The \fBlayout dump\fP command should help
+in this siutation. If a number
+or title is supplied, \fIscreen\fP will remember the arrangement of
+that particular layout. Without any options, \fIscreen\fP will
+remember the current layout.
+
+Saving your regions can be done automatically by using the
+\fBlayout autosave\fP command.
+.sp
+.ne 3
+.BR "layout autosave " [\fBon|off\fP]
+.PP
+Change or display the status of automatcally saving layouts. The
+default is \fBon\fP, meaning when \fIscreen\fP is detached or
+changed to a different layout, the arrangement of regions and windows
+will be remembered at the time of change and restored upon return.
+If autosave is set to \fBoff\fP, that arrangement will only be
+restored to either to the last manual save, using \fBlayout save\fP,
+or to when the layout was first created, to a single region with
+a single window. Without either an \fBon\fP or \fBoff\fP, the
+current status is displayed on the message line.
+.sp
+.ne 3
+.BR "layout dump " [\fIfilename\fP]
+.PP
+Write to a file the order of splits made in the current layout. This
+is useful to recreate the order of your regions used in your current
+layout. Only the current layout is recorded. While the order of the
+regions are recorded, the sizes of those regions and which windows
+correspond to which regions are not. If no filename is specified,
+the default is \fIlayout-dump\fP, saved in the directory that the
+\fIscreen\fP process was started in. If the file already exists,
+\fBlayout dump\fP will append to that file. As an example:
+.PP
+.nf
+ C-a : layout dump /home/user/.screenrc
+.fi
+.PP
+will save or append the layout to the user's \fI.screenrc\fP file.
+.sp
+.ne 3
.B license
.PP
Display the disclaimer page. This is done whenever
@@ -2218,7 +2402,8 @@ single statement.
.BI "maxwin " num
.PP
Set the maximum window number screen will create. Doesn't affect
-already existing windows. The number may only be decreased.
+already existing windows. The number can be increased only when there are no
+existing windows.
.sp
.ne 3
.B meta
@@ -2236,6 +2421,18 @@ with an `@' in the window-status display.
Monitoring is initially off for all windows.
.sp
.ne 3
+.BR "mousetrack " [ on | off ]
+.PP
+This command determines whether
+.I screen
+will watch for
+mouse clicks. When this command is enabled, regions that have
+been split in various ways can be selected by pointing to them
+with a mouse and left-clicking them. Without specifying \fBon\fP
+or \fBoff\fP, the current state is displayed. The default state
+is determined by the \*Qdefmousetrack\*U command.
+.sp
+.ne 3
.BI "msgminwait " sec
.PP
Defines the time
@@ -2276,7 +2473,8 @@ available if
.I screen
was compiled with the NETHACK flag defined. The
default setting is then determined by the presence of the environment
-variable $NETHACKOPTIONS.
+variable $NETHACKOPTIONS and the file ~/.nethackrc - if either one is present,
+the default is \fBon\fP.
.sp
.ne 3
.B next
@@ -2300,11 +2498,12 @@ some time it restarts to accept characters, screen will unblock
the display and redisplay the updated window contents.
.sp
.ne 3
-.BR "number " [ \fIn ]
+.BR "number " [[+|-] \fIn ]
.PP
-Change the current windows number. If the given number \fIn\fP is already
+Change the current window's number. If the given number \fIn\fP is already
used by another window, both windows exchange their numbers. If no argument is
-specified, the current window number (and title) is shown.
+specified, the current window number (and title) is shown. Using `+' or `-'
+will change the window's number by the relative amount specified.
.sp
.ne 3
.BR "obuflimit " [ \fIlimit ]
@@ -2518,6 +2717,15 @@ Unlinks the screen-exchange file used by the commands \*Qwritebuf\*U and
\*Qreadbuf\*U.
.sp
.ne 3
+.B "rendition bell" | monitor | silence | so
+.RB "\fIattr\fR " [ \fIcolor ]
+.PP
+Change the way
+.I screen
+renders the titles of windows that have monitor or bell flags set in caption or hardstatus or windowlist. See the \*QSTRING ESCAPES\*U chapter for the syntax of the modifiers.
+The default for monitor is currently \*Q=b \*U (bold, active colors), for bell \*Q=ub \*U (underline, bold and active colors), and \*Q=u \*U for silence.
+.sp
+.ne 3
.B "reset"
.PP
Reset the virtual terminal to its \*Qpower-on\*U values. Useful when strange
@@ -2544,7 +2752,7 @@ resize min minimize current region height
.PP
.sp
.ne 3
-.B "screen \fP[\fI-opts\fP] [\fIn\fP] [\fIcmd\fP [\fIargs\fP]]"
+.B "screen \fP[\fI-opts\fP] [\fIn\fP] [\fIcmd\fP [\fIargs\fP]|\fB//group\fP]"
.PP
Establish a new window.
The flow-control options (\fB\-f\fP, \fB\-fn\fP and \fB\-fa\fP),
@@ -2553,11 +2761,14 @@ title (a.\|k.\|a.) option (\fB\-t\fP), login options (\fB-l\fP and \fB-ln\fP)
and scrollback option (\fB-h\fP <num>) may be specified with each command.
The option (\fB-M\fP) turns monitoring on for this window.
The option (\fB-L\fP) turns output logging on for this window.
-If an optional number \fIn\fP in the range 0..9 is given, the window
-number \fIn\fP is assigned to the newly created window (or, if this
-number is already in-use, the next available number).
+If an optional number \fIn\fP in the range 0..MAXWIN-1 is given,
+the window number \fIn\fP is assigned to the newly created window
+(or, if this number is already in-use, the next available number).
If a command is specified after \*Qscreen\*U, this command (with the given
arguments) is started in the window; otherwise, a shell is created.
+If \fB//group\fP is supplied, a container-type window is created in
+which other windows may be created inside it.
+
Thus, if your \*Q.screenrc\*U contains the lines
.sp
.nf
@@ -2601,7 +2812,7 @@ When a new window is established, the first available number
is assigned to this window.
Thus, the first window can be activated by \*Qselect 0\*U.
The number of windows is limited at compile-time by the MAXWIN
-configuration parameter.
+configuration parameter (which defaults to 40).
There are two special WindowIDs, \*Q-\*U selects the
internal blank window and \*Q.\*U selects the current window. The
latter is useful if used with screen's \*Q-X\*U option.
@@ -2612,8 +2823,10 @@ latter is useful if used with screen's \*Q-X\*U option.
Rename the current session. Note, that for \*Qscreen -list\*U the
name shows up with the process-id prepended. If the argument \*Qname\*U
is omitted, the name of this session is displayed. Caution: The $STY
-environment variables still reflects the old name. This may result in
-confusion.
+environment variables will still reflect the old name in pre-existing
+shells. This may result in confusion. Use of this command is generally
+discouraged. Use the \*Q-S\*U command-line option if you want to
+name a new session.
The default is constructed from the tty and host names.
.sp
.ne 3
@@ -2705,20 +2918,17 @@ default screenrc files to have an effect.
.B sorendition
.RB [ "\fIattr\fR " [ \fIcolor ]]
.PP
-Change the way
-.I screen
-does highlighting for text marking and printing messages.
-See the \*QSTRING ESCAPES\*U chapter for the syntax of the modifiers.
-The default is currently \*Q=s dd\*U (standout, default colors).
+This command is deprecated. See "rendition so" instead.
.sp
.ne 3
.B split
+.RB [ -v ]
.PP
Split the current region into two new ones. All regions on the
display are resized to make room for the new region. The blank
-window is displayed on the new region. Use the \*Qremove\*U or the
-\*Qonly\*U command to delete regions.
-Use \*Qfocus\*U to toggle between regions.
+window is displayed on the new region. Splits are made horizontally
+unless -v is used. Use the \*Qremove\*U or the \*Qonly\*U command
+to delete regions. Use \*Qfocus\*U to toggle between regions.
.sp
.ne 3
.B "startup_message on\fP|\fBoff"
@@ -2727,21 +2937,22 @@ Select whether you want to see the copyright notice during startup.
Default is `on', as you probably noticed.
.sp
.ne 3
-.B stuff
-.I string
+.B stuff
+.RB [ "\fIstring\fR" ]
.PP
Stuff the string
.I string
in the input buffer of the current window.
This is like the \*Qpaste\*U command but with much less overhead.
+Without a paramter, screen will prompt for a string to stuff.
You cannot paste
large buffers with the \*Qstuff\*U command. It is most useful for key
bindings. See also \*Qbindkey\*U.
.sp
.ne 3
.B su
-.RB [ username " [" password
-.RB [ password2 ]]
+.RI [ username " [" password
+.RI [ password2 ]]]
.PP
Substitute the user of a display. The command prompts for all parameters that
are omitted. If passwords are specified as parameters, they have to be
@@ -2904,6 +3115,14 @@ prompts for one. This command was known as `aka' in previous
releases.
.sp
.ne 3
+.BI "unbindall "
+.PP
+Unbind all the bindings. This can be useful when
+screen is used solely for its detaching abilities, such as when
+letting a console application run as a daemon. If, for some reason,
+it is necessary to bind commands after this, use 'screen -X'.
+.sp
+.ne 3
.BI "unsetenv " var
.PP
Unset an environment variable.
@@ -2992,6 +3211,7 @@ vice versa.
.B windowlist
.RB [ -b ]
.RB [ -m ]
+.RB [ -g ]
.br
.B windowlist
.B string
@@ -3004,6 +3224,8 @@ vice versa.
Display all windows in a table for visual window selection. The
desired window can be selected via the standard movement keys (see
the \*Qcopy\*U command) and activated via the return key.
+If screen was in a window group, screen will
+back out of the group and then display the windows in that group.
If the
.B -b
option is given, screen will switch to the blank window before
@@ -3012,6 +3234,10 @@ The
.B -m
option changes the order of the windows, instead of sorting by
window numbers screen uses its internal most-recently-used list.
+The
+.B -g
+option will show the windows inside any groups in that level
+and downwards.
The table format can be changed with the \fBstring\fP and
\fBtitle\fP option, the title is displayed as table heading, while
@@ -3307,6 +3533,8 @@ month number
month name
.IP n
window number
+.IP P
+sets %? to true if the current region is in copy/paste mode
.IP S
session name
.IP s
diff --git a/src/doc/screen.texinfo b/src/doc/screen.texinfo
index 2c60317..03dccdf 100644
--- a/src/doc/screen.texinfo
+++ b/src/doc/screen.texinfo
@@ -73,6 +73,9 @@ except that this permission notice may be stated in a translation approved
by the Foundation.
@end titlepage
+@shortcontents
+@contents
+
@node Top, Overview, (dir), (dir)
@ifinfo
@@ -175,6 +178,9 @@ run another copy of @code{screen}, but will instead supply the command
name and its arguments to the window manager (specified in the $STY environment
variable) who will use it to create the new window. The above example would
start the @code{emacs} editor (editing @file{prog.c}) and switch to its window.
+- Note that you cannot transport environment variables from
+the invoking shell to the application (emacs in this case), because it is
+forked from the parent screen process, not from the invoking shell.
If @file{/etc/utmp} is writable by @code{screen}, an appropriate record
will be written to this file for each window, and removed when the
@@ -344,12 +350,20 @@ This also starts @code{screen} in @emph{detached} mode, but doesn't fork
a new process. The command exits if the session terminates.
@end table
-@item -p @var{name_or_number}
+@item -O
+Select a more optimal output mode for your terminal rather than true VT100
+emulation (only affects auto-margin terminals without @samp{LP}). This
+can also be set in your @file{.screenrc} by specifying @samp{OP} in the
+@code{termcap} command.
+
+@item -p @var{name_or_number}|-|=|+
Preselect a window. This is useful when you want to reattach to a
specific window or you want to send a command via the @samp{-X}
option to a specific window. As with screen's select command, @samp{-}
selects the blank window. As a special case for reattach, @samp{=}
-brings up the windowlist on the blank window.
+brings up the windowlist on the blank window, while a @samp{+} will
+create new window. The command will not be executed if the specified
+window could not be found.
@item -q
Suppress printing of error messages. In combination with @samp{-ls} the exit
@@ -361,6 +375,23 @@ there is no session to resume. 12 (or more) indicates that there are 2 (or
more) sessions to resume and you should specify which one to choose.
In all other cases @samp{-q} has no effect.
+@item -Q
+Some commands now can be queried from a remote session using this
+flag, e.g. 'screen -Q windows'. The commands will send the
+response to the stdout of the querying process. If there was an
+error in the command, then the querying process will exit with
+a non-zero status.
+
+The commands that can be queried now are:
+ @code{echo}
+ @code{info}
+ @code{lastmsg}
+ @code{number}
+ @code{select}
+ @code{time}
+ @code{title}
+ @code{windows}
+
@item -r [@var{pid.sessionname}]
@itemx -r @var{sessionowner}/[@var{pid.sessionname}]
Resume a detached @code{screen} session. No other options (except
@@ -400,6 +431,10 @@ Set the title (name) for the default shell or specified program.
This option is equivalent to the @code{shelltitle} command
(@pxref{Shell}).
+@item -T @var{term}
+Set the $TERM enviroment varible using the spcified @emph{term} as
+opposed to the defualt setting of @code{screen}.
+
@item -U
Run screen in UTF-8 mode. This option tells screen that your terminal
sends and understands UTF-8 encoded characters. It also sets the default
@@ -620,7 +655,7 @@ Cycle flow among @samp{on}, @samp{off} or @samp{auto}. @xref{Flow}.
@item @kbd{C-a F}
(fit)@*
-Resize the window to the current region size. @xref{Window Size}.
+Resize the window to the current region size. @xref{Fit}.
@item @kbd{C-a C-g}
(vbell)@*
@@ -705,7 +740,7 @@ Send a ^S (ASCII XOFF) to the current window. @xref{XON/XOFF}.
@item @kbd{C-a S}
(split)@*
-Split the current region into two new ones. @xref{Regions}.
+Split the current region horizontally into two new ones. @xref{Regions}.
@item @kbd{C-a t}
@itemx @kbd{C-a C-t}
@@ -797,15 +832,19 @@ Delete the screen-exchange file. @xref{Screen Exchange}.
@item @kbd{C-a _}
(silence)@*
-Start/stop monitoring the current window for inactivity. @xref{Silence},
+Start/stop monitoring the current window for inactivity. @xref{Monitor}.
+
+@item @kbd{C-a |}
+(split -v)@*
+Split the current region vertically into two new ones. @xref{Regions}.
@item @kbd{C-a ,}
(license)@*
-Show the copyright page.
+Show the copyright page. @xref{License}.
@item @kbd{C-a *}
(displays)@*
-Show the listing of attached displays.
+Show the listing of attached displays. @xref{Displays}.
@end table
@node Command Summary, , Default Key Bindings, Commands
@@ -915,6 +954,8 @@ Select default utmp logging behavior. @xref{Login}.
Select default file mode for ptys. @xref{Mode}.
@item defmonitor @var{state}
Select default activity monitoring behavior. @xref{Monitor}.
+@item defmousetrack @var{on}|@var{off}
+Select the default mouse tracking behavior. @xref{Mousetrack}.
@item defnonblock @var{state}|@var{numsecs}
Select default nonblock mode. @xref{Nonblock}.
@item defobuflimit @var{limit}
@@ -924,7 +965,7 @@ Set default lines of scrollback. @xref{Scrollback}.
@item defshell @var{command}
Set the default program for new windows. @xref{Shell}.
@item defsilence @var{state}
-Select default idle monitoring behavior. @xref{Silence}.
+Select default idle monitoring behavior. @xref{Monitor}.
@item defslowpaste @var{msec}
Select the default inter-character timeout when pasting. @xref{Paste}.
@item defutf8 @var{state}
@@ -937,8 +978,8 @@ Set default writelock behavior. @xref{Multiuser Session}.
Keep dead windows. @xref{Zombie}.
@item detach [-h]
Disconnect @code{screen} from the terminal. @xref{Detach}.
-@item digraph
-Enter digraph sequence. @xref{Digraph}.
+@item digraph [@var{preset} [@var{unicode-value}]]
+Enter a digraph sequence. @xref{Digraph}.
@item dinfo
Display terminal information. @xref{Info}.
@item displays
@@ -961,8 +1002,12 @@ Change window size to current display size. @xref{Window Size}.
Set flow control behavior. @xref{Flow}.
@item focus
Move focus to next region. @xref{Regions}.
+@item focusminsize
+Force the current region to a certain size. @xref{Focusminsize}.
@item gr [@var{state}]
Change GR charset processing. @xref{Character Processing}.
+@item group [@var{grouptitle}]
+Change or show the group the current window belongs to. @xref{Window Groups}.
@item hardcopy [-h] [@var{file}]
Write out the contents of the current window. @xref{Hardcopy}.
@item hardcopy_append @var{state}
@@ -991,6 +1036,30 @@ Removed, use @code{paste} instead. @xref{Registers}.
Destroy the current window. @xref{Kill}.
@item lastmsg
Redisplay the last message. @xref{Last Message}.
+@item layout new [@var{title}]
+Create a layout. @xref{Layout}.
+@item layout remove [@var{n}|@var{title}]
+Delete a layout. @xref{Layout}.
+@item layout next
+Select the next layout. @xref{Layout}.
+@item layout prev
+Select the previous layout. @xref{Layout}.
+@item layout select [@var{n}|@var{title}]
+Jump to a layout. @xref{Layout}.
+@item layout show
+List the available layouts. @xref{Layout}.
+@item layout title [@var{title}]
+Show or set the title of a layout. @xref{Layout}.
+@item layout number [@var{n}]
+Show or set the number of a layout. @xref{Layout}.
+@item layout attach [@var{title}|:last]
+Show or set which layout to reattach to. @xref{Layout}.
+@item layout save [@var{n}|@var{title}]
+Remember the organization of a layout. @xref{Layout}.
+@item layout autosave [@var{on}|@var{off}]
+Show or set the status of layout saving. @xref{Layout}.
+@item layout dump [filename]
+Save the layout arrangement to a file. @xref{Layout}.
@item license
Display licensing information. @xref{Startup}.
@item lockscreen
@@ -1007,7 +1076,7 @@ Configure logfile time-stamps. @xref{Log}.
Use only the default mapping table for the next keystroke. @xref{Bindkey Control}.
@item mapnotnext
Don't try to do keymapping on the next keystroke. @xref{Bindkey Control}.
-@item maptimeout @var{timo}
+@item maptimeout @var{n}
Set the inter-character timeout used for keymapping. @xref{Bindkey Control}.
@item markkeys @var{string}
Rebind keys in copy mode. @xref{Copy Mode Keys}.
@@ -1017,6 +1086,8 @@ Set the maximum window number. @xref{Maxwin}.
Insert the command character. @xref{Command Character}.
@item monitor [@var{state}]
Monitor activity in window. @xref{Monitor}.
+@item mousetrack [@var{on}|@var{off}]
+Enable selecting split regions with mouse clicks. @xref{Mousetrack}.
@item msgminwait @var{sec}
Set minimum message wait. @xref{Message Wait}.
@item msgwait @var{sec}
@@ -1071,15 +1142,17 @@ Store a string to a register. @xref{Registers}.
Kill current region. @xref{Regions}.
@item removebuf
Delete the screen-exchange file. @xref{Screen Exchange}.
+@item rendition bell | monitor | silence | so @var{attr} [@var{color}]
+Change text attributes in caption for flagged windows. @xref{Rendition}.
@item reset
Reset the terminal settings for the window. @xref{Reset}.
@item resize [(+/-)lines]
Grow or shrink a region
-@item screen [@var{opts}] [@var{n}] [@var{cmd} [@var{args}]]
+@item screen [@var{opts}] [@var{n}] [@var{cmd} [@var{args}] | //group]
Create a new window. @xref{Screen Command}.
@item scrollback @var{num}
Set size of scrollback buffer. @xref{Scrollback}.
-@item select [@var{n}]
+@item select [@var{n}|-|.]
Switch to a specified window. @xref{Selecting}.
@item sessionname [@var{name}]
Name this session. @xref{Session Name}.
@@ -1092,9 +1165,9 @@ Set the default program for new windows. @xref{Shell}.
@item shelltitle @var{title}
Set the default name for new windows. @xref{Shell}.
@item silence [@var{state}|@var{seconds}]
-Monitor a window for inactivity. @xref{Silence}.
+Monitor a window for inactivity. @xref{Monitor}.
@item silencewait @var{seconds}
-Default timeout to trigger an inactivity notify. @xref{Silence}.
+Default timeout to trigger an inactivity notify. @xref{Monitor}.
@item sleep @var{num}
Pause during startup. @xref{Startup}.
@item slowpaste @var{msec}
@@ -1102,12 +1175,12 @@ Slow down pasting in windows. @xref{Paste}.
@item source @var{file}
Run commands from a file. @xref{Source}.
@item sorendition [@var{attr} [@var{color}]]
-Change text highlighting. @xref{Sorendition}.
+Deprecated. Use @code{rendition so} instead. @xref{Rendition}.
@item split
Split region into two parts. @xref{Regions}.
@item startup_message @var{state}
Display copyright notice on startup. @xref{Startup}.
-@item stuff @var{string}
+@item stuff [@var{string}]
Stuff a string in the input buffer of a window. @xref{Paste}.
@item su [@var{username} [@var{password} [@var{password2}]]]
Identify a user. @xref{Multiuser Session}.
@@ -1127,6 +1200,8 @@ Display time and load average. @xref{Time}.
Set the name of the current window. @xref{Title Command}.
@item umask [@var{users}]+/-@var{bits} ...
Synonym to @code{aclumask}. @xref{Umask}.
+@item unbindall
+Unset all keybindings. @xref{Bind}.
@item unsetenv @var{var}
Unset environment variable for new windows. @xref{Setenv}.
@item utf8 [@var{state} [@var{dstate}]]
@@ -1143,7 +1218,7 @@ Display @code{screen} version. @xref{Version}.
Write a message to all displays. @xref{Multiuser Session}.
@item width [@var{cols} [@var{lines}]]
Set the width of the window. @xref{Window Size}.
-@item windowlist [-b] | string [@var{string}] | title [@var{title}]
+@item windowlist [[-b] [-m] [-g]] | string [@var{string}] | title [@var{title}]
Present a list of all windows for selection. @xref{Windowlist}.
@item windows
List active windows. @xref{Windows}.
@@ -1168,9 +1243,9 @@ Keep dead windows. @xref{Zombie}.
This section describes the commands for creating a new window for
running programs. When a new window is created, the first available
-number from the range 0@dots{}9 is assigned to it.
+number is assigned to it.
The number of windows is limited at compile-time by the MAXWIN
-configuration parameter.
+configuration parameter (which defaults to 40).
@menu
* Chdir:: Change the working directory for new windows.
@@ -1179,6 +1254,7 @@ configuration parameter.
* Shell:: Parameters for shell windows.
* Term:: Set the terminal type for new windows.
* Window Types:: Creating different types of windows.
+* Window Groups:: Grouping windows together
@end menu
@node Chdir, Screen Command, , New Window
@@ -1203,7 +1279,7 @@ affect all the windows you create interactively.
@section Screen Command
@kindex c
@kindex C-c
-@deffn Command screen [opts] [n] [cmd [args]]
+@deffn Command screen [opts] [n] [cmd [args] @var{| //group}]
(@kbd{C-a c}, @kbd{C-a C-c})@*
Establish a new window. The flow-control options (@samp{-f}, @samp{-fn}
and @samp{-fa}), title option (@samp{-t}), login options
@@ -1212,11 +1288,13 @@ the all-capability-flag (@samp{-a}) and scrollback option
(@samp{-h @var{num}}) may be specified with each command.
The option (@samp{-M}) turns monitoring on for this window.
The option (@samp{-L}) turns output logging on for this window.
-If an optional number @var{n} in the range 0@dots{}9 is given,
+If an optional number @var{n} in the range 0@dots{}MAXWIN-1 is given,
the window number @var{n} is assigned to the newly created window (or,
if this number is already in-use, the next available number). If a
command is specified after @code{screen}, this command (with the given
arguments) is started in the window; otherwise, a shell is created.
+If @samp{//group} is supplied, a container-type window is created in
+which other windows may be created inside it. @xref{Window Groups}.
Screen has built in some functionality of @samp{cu} and @samp{telnet}.
@xref{Window Types}.
@@ -1292,7 +1370,7 @@ the next @code{screen rlogin othermachine} command. Use the command
and resetting the default.
@end deffn
-@node Window Types, , Term, New Window
+@node Window Types, Window Groups, Term, New Window
@section Window Types
@cindex window types
Screen provides three different window types. New windows are created
@@ -1392,6 +1470,37 @@ For telnet windows, the command @code{break} sends the telnet code
@end itemize
+@node Window Groups, , Window Types, New Window
+@section Window Groups
+@cindex window groups
+Screen provides a method for grouping windows together. Windows can be
+organized in a hierarchical fashion, resembling a tree structure. New
+screens are created using the @code{screen} command while new groups
+are created using @code{screen //group}. @xref{Screen Command}.
+
+Once a new group is created, it will act as a container for windows
+and even other groups. When a group is selected, you will see the
+output of the @code{windowlist} command, allowing you to select a
+window inside. If there are no windows inside a group, use the
+@code{screen} command to create one. Once inside a group, using the
+commands @code{next} and @code{prev} will switch between windows only
+in that group. Using the @code{windowlist} command will give you the
+opportunity to leave the group you are in. @xref{Windowlist}.
+
+@deffn Command group [grouptitle]
+(none)@*
+Change or show the group the current window belongs to. Windows can
+be moved around between different groups by specifying the name of
+the destination group. Without specifying a group, the title of the
+current group is displayed.
+@end deffn
+
+Using groups in combination with layouts will help create a
+multi-desktop experience. One group can be assigned for each
+layout made. Windows can be made, split, and organized within each
+group as desired. Afterwhich, switching between groups can be as easy
+as switching layouts.
+
@node Selecting, Session Management, New Window, Top
@chapter Selecting a Window
@@ -1421,8 +1530,10 @@ pressing space.)
@kindex p
@kindex C-p
+@kindex C-h
+@kindex Backspace
@deffn Command prev
-(@kbd{C-a p}, @kbd{C-a C-p})@*
+(@kbd{C-a p}, @kbd{C-a C-p}, @kbd{C-a C-h}, @kbd{C-a @key{Backspace}})@*
Switch to the previous window (the opposite of @kbd{C-a n}).
@end deffn
@@ -1441,7 +1552,7 @@ this command becomes @kbd{]]} (@pxref{Command Character}).
@section Select
@kindex 0@dots{}9
@kindex '
-@deffn Command select [n]
+@deffn Command select [n @var{|-|.}]
(@kbd{C-a @var{n}}, @kbd{C-a '})@*
Switch to the window with the number @var{n}.
If no window number is specified, you get prompted for an
@@ -1461,19 +1572,22 @@ current window. The latter is useful if used with screen's
@node Windowlist, , Select, Selecting
@section Windowlist
@kindex "
-@deffn Command windowlist [-b] [-m]
+@deffn Command windowlist [-b] [-m] [-g]
@deffnx Command windowlist string [@var{string}]
@deffnx Command windowlist title [@var{title}]
(@kbd{C-a "})@*
Display all windows in a table for visual window selection.
The desired window can be selected via the standard
movement keys (@pxref{Movement}) and activated via
-the return key. If the @code{-b} option is given, screen will
+the return key. If screen was in a window group, screen will
+back out of the group and then display the windows in that
+group. If the @code{-b} option is given, screen will
switch to the blank window before presenting the list, so
that the current window is also selectable.
The @code{-m} option changes the order of the windows, instead of
sorting by window numbers screen uses its internal most-recently-used
-list.
+list. The @code{-g} option will show the windows inside any groups
+in that level and downwards.
The table format can be changed with the string and title
option, the title is displayed as table heading, while the
@@ -1555,7 +1669,7 @@ logout if @code{screen} was started from your login shell.
The @var{message} specified here is output whenever a power detach is
performed. It may be used as a replacement for a logout message or to reset
baud rate, etc.
-Without parameter, the current message is shown.
+Without a parameter, the current message is shown.
@end deffn
@node Lock, Multiuser Session, Power Detach, Session Management
@@ -1758,8 +1872,11 @@ Rename the current session. Note that for @code{screen -list} the name
shows up with the process-id prepended. If the argument @var{name} is
omitted, the name of this session is displayed.@*
@emph{Caution}: The @code{$STY}
-environment variable still reflects the old name. This may result in
-confusion. The default is constructed from the tty and host names.
+environment variable will still reflect the old name in pre-existing
+shells. This may result in
+confusion. Use of this command is generally
+discouraged. Use the @code{-S} command-line option if you want to
+name a new session.The default is constructed from the tty and host names.
@end deffn
@node Suspend, Quit, Session Name, Session Management
@@ -1800,16 +1917,27 @@ which can contain different windows.
* Resize:: Grow or shrink a region
* Caption:: Control the window's caption
* Fit:: Resize a window to fit the region
+* Focusminsize:: Force a minimum size on a current region
+* Layout:: Manage groups of regions
@end menu
@node Split, Focus, , Regions
@section Split
@kindex S
-@deffn Command split
-(@kbd{C-a S})@*
+@kindex |
+@deffn Command split [-v]
+(@kbd{C-a S}, @kbd{C-a |})@*
Split the current region into two new ones. All regions on the
display are resized to make room for the new region. The blank
-window is displayed on the new region.
+window is displayed on the new region. The default is to create
+a horizontal split, putting the new regions on the top and
+bottom of each other. Using -v will create a vertical split,
+causing the new regions to appear side by side of each other.
+
+With this current implementation of @code{screen}, scrolling data
+will appear much slower in a vertically split region than one
+that is not. This should be taken into consideration if you need
+to use system commands such as @code{cat} or @code{tail -f}.
@end deffn
@node Focus, Only, Split, Regions
@@ -1882,7 +2010,7 @@ You can mix both forms by providing the string as an additional
argument.
@end deffn
-@node Fit, , Caption, Regions
+@node Fit, Focusminsize, Caption, Regions
@section Fit
@kindex F
@deffn Command fit
@@ -1892,6 +2020,154 @@ command is needed because screen doesn't adapt the window size
automatically if the window is displayed more than once.
@end deffn
+@node Focusminsize, Layout, Fit, Regions
+@section Focusminsize
+@deffn Command focusminsize [ (width|@code{max}|@code{_}) (height|@code{max}|@code{_}) ]
+(none)@*
+This forces any currently selected region to be automatically
+resized at least a certain @var{width} and @var{height}. All
+other surrounding regions will be resized in order to accommodate.
+This constraint follows every time the @code{focus} command is
+used. The @code{resize} command can be used to increase either
+dimension of a region, but never below what is set with
+@code{focusminsize}. The underscore @samp{_} is a synonym for
+@code{max}. Setting a @var{width} and @var{height} of @code{0 0}
+(zero zero) will undo any constraints and allow for manual resizing.
+Without any parameters, the minimum width and height is shown.
+@end deffn
+
+@node Layout, , Focusminsize, Regions
+@section Layout
+@cindex layout
+Using regions, and perhaps a large enough terminal, you can give
+@code{screen} more of a desktop feel. By being able to split
+regions horizontally or vertically, you can take advantage of the
+lesser used spaces of your terminal. The catch to these splits has
+been that they're not kept between screen detachments and reattachments.
+
+Layouts will help organize your regions. You can create one
+layout of four horizontal regions and then create a separate layout
+of regions in a two by two array. The regions could contain the same windows,
+but they don't have to. You can easily switch between layouts and keep
+them between detachments and reattachments.
+
+Note that there are several subcommands to @code{layout}.
+
+@deffn Command layout @code{new} [title]
+(none)@*
+Create a new layout. The screen will change to one whole region
+and be switched to the blank window. From here, you build the
+regions and the windows they show as you desire. The new layout
+will be numbered with the smallest available integer, starting
+with zero. You can optionally give a title to your new layout.
+Otherwise, it will have a default title of @code{layout}. You
+can always change the title later by using the command
+@code{layout title}.
+@end deffn
+
+@deffn Command layout @code{remove} [n|title]
+(none)@*
+Remove, or in other words, delete the specified layout. Either
+the number or the title can be specified. Without either
+specification, @code{screen} will remove the current layout.
+
+Removing a layout does not affect your set windows or regions.
+@end deffn
+
+@deffn Command layout @code{next}
+(none)@*
+Switch to the next layout available
+@end deffn
+
+@deffn Command layout @code{prev}
+(none)@*
+Switch to the previous layout available
+@end deffn
+
+@deffn Command layout @code{select} [n|title]
+(none)@*
+Select the desired layout. Either the number or the title can
+be specified. Without either specification, @code{screen} will
+prompt and ask which screen is desired. To see which layouts are
+available, use the @code{layout show} command.
+@end deffn
+
+@deffn Command layout @code{show}
+(none)@*
+List on the message line the number(s) and title(s) of the available
+layout(s). The current layout is flagged.
+@end deffn
+
+@deffn Command layout @code{title} [title]
+(none)@*
+Change or display the title of the current layout. A string given
+will be used to name the layout. Without any options, the current
+title and number is displayed on the message line.
+@end deffn
+
+@deffn Command layout @code{number} [n]
+(none)@*
+Change or display the number of the current layout. An integer given
+will be used to number the layout. Without any options, the current
+number and title is displayed on the message line.
+@end deffn
+
+@deffn Command layout @code{attach} [title|@code{:last}]
+(none)@*
+Change or display which layout to reattach back to. The default is
+@code{:last}, which tells @code{screen} to reattach back to the last
+used layout just before detachment. By supplying a title, You can
+instruct @code{screen} to reattach to a particular layout regardless
+which one was used at the time of detachment. Without any options,
+the layout to reattach to will be shown in the message line.
+@end deffn
+
+@deffn Command layout @code{save} [n|title]
+(none)@*
+Remember the current arrangement of regions. When used, @code{screen}
+will remember the arrangement of vertically and horizontally split
+regions. This arrangement is restored when a @code{screen} session
+is reattached or switched back from a different layout. If the
+session ends or the @code{screen} process dies, the layout
+arrangements are lost. The @code{layout dump} command should help
+in this siutation. If a number
+or title is supplied, @code{screen} will remember the arrangement of
+that particular layout. Without any options, @code{screen} will
+remember the current layout.
+
+Saving your regions can be done automatically by using the
+@code{layout autosave} command.
+@end deffn
+
+@deffn Command layout @code{autosave} [@code{on}|@code{off}]
+(none)@*
+Change or display the status of automatically saving layouts. The
+default is @code{on}, meaning when @code{screen} is detached or
+changed to a different layout, the arrangement of regions and windows
+will be remembered at the time of change and restored upon return.
+If autosave is set to @code{off}, that arrangement will only be
+restored to either to the last manual save, using @code{layout save},
+or to when the layout was first created, to a single region with
+a single window. Without either an @code{on} or an @code{off}, the
+current status is displayed on the message line.
+@end deffn
+
+@deffn Command layout @code{dump} [filename]
+(none)@*
+Write to a file the order of splits made in the current layout. This
+is useful to recreate the order of your regions used in your current
+layout. Only the current layout is recorded. While the order of the
+regions are recorded, the sizes of those regions and which windows
+correspond to which regions are not. If no filename is specified,
+the default is @file{layout-dump}, saved in the directory that the
+@code{screen} process was started in. If the file already exists,
+@code{layout dump} will append to that file. As an example:
+@example
+layout dump /home/user/.screenrc
+@end example
+will save or append the layout to the user's @file{.screenrc} file.
+@end deffn
+
@node Window Settings, Virtual Terminal, Regions, Top
@chapter Window Settings
@@ -1905,7 +2181,7 @@ terminal emulation itself.
* Kill:: Destroy an unwanted window
* Login:: Control @file{/etc/utmp} logging
* Mode:: Control the file mode of the pty
-* Monitor:: Watch for activity in a window
+* Monitor:: Watch for activity or inactivity in a window
* Windows:: List the active windows
* Hardstatus:: Set a window's hardstatus line
@end menu
@@ -2168,6 +2444,29 @@ the window-status display (@pxref{Windows}). Monitoring defaults to
@samp{off} for all windows.
@end deffn
+@kindex _
+@deffn Command silence [@var{state}|@var{sec}]
+(@kbd{C-a _})@*
+Toggles silence monitoring of windows. When silence is turned on and an
+affected window is switched into the background, you will receive the
+silence notification message in the status line after a specified period
+of inactivity (silence). The default timeout can be changed with the
+@code{silencewait} command or by specifying a number of seconds instead of
+@code{on} or @code{off}. Silence is initially off for all windows.
+@end deffn
+
+@deffn Command defsilence state
+(none)@*
+Same as the @code{silence} command except that the default setting for
+new windows is changed. Initial setting is `off'.
+@end deffn
+
+@deffn Command silencewait @var{seconds}
+(none)@*
+Define the time that all windows monitored for silence should wait
+before displaying a message. Default is 30 seconds.
+@end deffn
+
@node Windows, Hardstatus, Monitor, Window Settings
@section Windows
@kindex w
@@ -2193,7 +2492,7 @@ If this list is too long to fit on the terminal's status line only the
portion around the current window is displayed.
@end deffn
-@node Hardstatus, , Windows, Window Settings
+@node Hardstatus, Mousetrack, Windows, Window Settings
@section Hardstatus
@code{Screen} maintains a hardstatus line for every window. If a window
@@ -2224,6 +2523,25 @@ Per default the hardstatus line of new windows is empty.
Changes the current window's hardstatus line to @var{status}.
@end deffn
+@node Mousetrack, , Hardstatus, Miscellaneous
+@section Mousetrack
+
+@deffn Command mousetrack [ @code{on|off} ]
+(none)@*
+This command determines whether @code{screen} will watch for
+mouse clicks. When this command is enabled, regions that have
+been split in various ways can be selected by pointing to them
+with a mouse and left-clicking them. Without specifying @var{on}
+or @var{off}, the current state is displayed. The default state
+is determined by the @code{defmousetrack} command.
+@end deffn
+
+@deffn Command defmousetrack @code{on|off}
+(none)@*
+This command determines the default state of the @code{mousetrack}
+command, currently defaulting of @var{off}.
+@end deffn
+
@node Virtual Terminal, Copy and Paste, Window Settings, Top
@chapter Virtual Terminal
@@ -2476,8 +2794,8 @@ Keypad enter fe stuff \015
@section Digraph
@kindex C-v
-@deffn Command digraph [preset]
-(none)@*
+@deffn Command digraph [preset [unicode-value]]
+(@kbd{C-a C-v})@*
This command prompts the user for a digraph sequence. The next
two characters typed are looked up in a builtin table and the
resulting character is inserted in the input stream. For example,
@@ -2487,7 +2805,190 @@ will treat the following characters (up to three) as an octal
number instead. The optional argument @var{preset}
is treated as user input, thus one can create an "umlaut" key.
For example the command @samp{bindkey ^K digraph '"'} enables the user
-to generate an a-umlaut by typing @samp{CTRL-K a}.
+to generate an a-umlaut by typing @samp{CTRL-K a}. When a non-zero
+@var{unicode-value} is specified, a new digraph is created with the
+specified preset. The digraph is unset if a zero value is provided
+for the @var{unicode-value}.
+
+The following table is the builtin sequences.
+
+@documentencoding ISO-8859-1
+@example
+ Sequence Octal Digraph Unicode Equivalent
+ -----------------------------------------------
+ ' ', ' ' 160 (space) U+00A0
+ 'N', 'S' 160 (space) U+00A0
+ '~', '!' 161 ¡ U+00A1
+ '!', '!' 161 ¡ U+00A1
+ '!', 'I' 161 ¡ U+00A1
+ 'c', '|' 162 ¢ U+00A2
+ 'c', 't' 162 ¢ U+00A2
+ '$', '$' 163 £ U+00A3
+ 'P', 'd' 163 £ U+00A3
+ 'o', 'x' 164 ¤ U+00A4
+ 'C', 'u' 164 ¤ U+00A4
+ 'C', 'u' 164 ¤ U+00A4
+ 'E', 'u' 164 ¤ U+00A4
+ 'Y', '-' 165 ¥ U+00A5
+ 'Y', 'e' 165 ¥ U+00A5
+ '|', '|' 166 ¦ U+00A6
+ 'B', 'B' 166 ¦ U+00A6
+ 'p', 'a' 167 § U+00A7
+ 'S', 'E' 167 § U+00A7
+ '"', '"' 168 ¨ U+00A8
+ ''', ':' 168 ¨ U+00A8
+ 'c', 'O' 169 © U+00A9
+ 'C', 'o' 169 © U+00A9
+ 'a', '-' 170 ª U+00AA
+ '<', '<' 171 « U+00AB
+ '-', ',' 172 ¬ U+00AC
+ 'N', 'O' 172 ¬ U+00AC
+ '-', '-' 173 ­ U+00AD
+ 'r', 'O' 174 ® U+00AE
+ 'R', 'g' 174 ® U+00AE
+ '-', '=' 175 ¯ U+00AF
+ ''', 'm' 175 ¯ U+00AF
+ '~', 'o' 176 ° U+00B0
+ 'D', 'G' 176 ° U+00B0
+ '+', '-' 177 ± U+00B1
+ '2', '2' 178 ² U+00B2
+ '2', 'S' 178 ² U+00B2
+ '3', '3' 179 ³ U+00B3
+ '3', 'S' 179 ³ U+00B3
+ ''', ''' 180 ´ U+00B4
+ 'j', 'u' 181 µ U+00B5
+ 'M', 'y' 181 µ U+00B5
+ 'p', 'p' 182 ¶ U+00B6
+ 'P', 'I' 182 ¶ U+00B6
+ '~', '.' 183 · U+00B7
+ '.', 'M' 183 · U+00B7
+ ',', ',' 184 ¸ U+00B8
+ ''', ',' 184 ¸ U+00B8
+ '1', '1' 185 ¹ U+00B9
+ '1', 'S' 185 ¹ U+00B9
+ 'o', '-' 186 º U+00BA
+ '>', '>' 187 » U+00BB
+ '1', '4' 188 ¼ U+00BC
+ '1', '2' 189 ½ U+00BD
+ '3', '4' 190 ¾ U+00BE
+ '~', '?' 191 ¿ U+00BF
+ '?', '?' 191 ¿ U+00BF
+ '?', 'I' 191 ¿ U+00BF
+ 'A', '`' 192 À U+00C0
+ 'A', '!' 192 À U+00C0
+ 'A', ''' 193 Á U+00C1
+ 'A', '^' 194 Â U+00C2
+ 'A', '>' 194 Â U+00C2
+ 'A', '~' 195 Ã U+00C3
+ 'A', '?' 195 Ã U+00C3
+ 'A', '"' 196 Ä U+00C4
+ 'A', ':' 196 Ä U+00C4
+ 'A', '@@' 197 Å U+00C5
+ 'A', 'A' 197 Å U+00C5
+ 'A', 'E' 198 Æ U+00C6
+ 'C', ',' 199 Ç U+00C7
+ 'E', '`' 200 È U+00C8
+ 'E', '!' 200 È U+00C8
+ 'E', ''' 201 É U+00C9
+ 'E', '^' 202 Ê U+00CA
+ 'E', '>' 202 Ê U+00CA
+ 'E', '"' 203 Ë U+00CB
+ 'E', ':' 203 Ë U+00CB
+ 'I', '`' 204 Ì U+00CC
+ 'I', '!' 204 Ì U+00CC
+ 'I', ''' 205 Í U+00CD
+ 'I', '^' 206 Î U+00CE
+ 'I', '>' 206 Î U+00CE
+ 'I', '"' 207 Ï U+00CF
+ 'I', ':' 207 Ï U+00CF
+ 'D', '-' 208 Ð U+00D0
+ 'N', '~' 209 Ñ U+00D1
+ 'N', '?' 209 Ñ U+00D1
+ 'O', '`' 210 Ò U+00D2
+ 'O', '!' 210 Ò U+00D2
+ 'O', ''' 211 Ó U+00D3
+ 'O', '^' 212 Ô U+00D4
+ 'O', '>' 212 Ô U+00D4
+ 'O', '~' 213 Õ U+00D5
+ 'O', '?' 213 Õ U+00D5
+ 'O', '"' 214 Ö U+00D6
+ 'O', ':' 214 Ö U+00D6
+ '/', '\' 215 × U+00D7
+ '*', 'x' 215 × U+00D7
+ 'O', '/' 216 Ø U+00D8
+ 'U', '`' 217 Ù U+00D9
+ 'U', '!' 217 Ù U+00D9
+ 'U', ''' 218 Ú U+00DA
+ 'U', '^' 219 Û U+00DB
+ 'U', '>' 219 Û U+00DB
+ 'U', '"' 220 Ü U+00DC
+ 'U', ':' 220 Ü U+00DC
+ 'Y', ''' 221 Ý U+00DD
+ 'I', 'p' 222 Þ U+00DE
+ 'T', 'H' 222 Þ U+00DE
+ 's', 's' 223 ß U+00DF
+ 's', '"' 223 ß U+00DF
+ 'a', '`' 224 à U+00E0
+ 'a', '!' 224 à U+00E0
+ 'a', ''' 225 á U+00E1
+ 'a', '^' 226 â U+00E2
+ 'a', '>' 226 â U+00E2
+ 'a', '~' 227 ã U+00E3
+ 'a', '?' 227 ã U+00E3
+ 'a', '"' 228 ä U+00E4
+ 'a', ':' 228 ä U+00E4
+ 'a', 'a' 229 å U+00E5
+ 'a', 'e' 230 æ U+00E6
+ 'c', ',' 231 ç U+00E7
+ 'e', '`' 232 è U+00E8
+ 'e', '!' 232 è U+00E8
+ 'e', ''' 233 é U+00E9
+ 'e', '^' 234 ê U+00EA
+ 'e', '>' 234 ê U+00EA
+ 'e', '"' 235 ë U+00EB
+ 'e', ':' 235 ë U+00EB
+ 'i', '`' 236 ì U+00EC
+ 'i', '!' 236 ì U+00EC
+ 'i', ''' 237 í U+00ED
+ 'i', '^' 238 î U+00EE
+ 'i', '>' 238 î U+00EE
+ 'i', '"' 239 ï U+00EF
+ 'i', ':' 239 ï U+00EF
+ 'd', '-' 240 ð U+00F0
+ 'n', '~' 241 ñ U+00F1
+ 'n', '?' 241 ñ U+00F1
+ 'o', '`' 242 ò U+00F2
+ 'o', '!' 242 ò U+00F2
+ 'o', ''' 243 ó U+00F3
+ 'o', '^' 244 ô U+00F4
+ 'o', '>' 244 ô U+00F4
+ 'o', '~' 245 õ U+00F5
+ 'o', '?' 245 õ U+00F5
+ 'o', '"' 246 ö U+00F6
+ 'o', ':' 246 ö U+00F6
+ ':', '-' 247 ÷ U+00F7
+ 'o', '/' 248 ø U+00F8
+ 'u', '`' 249 ù U+00F9
+ 'u', '!' 249 ù U+00F9
+ 'u', ''' 250 ú U+00FA
+ 'u', '^' 251 û U+00FB
+ 'u', '>' 251 û U+00FB
+ 'u', '"' 252 ü U+00FC
+ 'u', ':' 252 ü U+00FC
+ 'y', ''' 253 ý U+00FD
+ 'i', 'p' 254 þ U+00FE
+ 't', 'h' 254 þ U+00FE
+ 'y', '"' 255 ÿ U+00FF
+ 'y', ':' 255 ÿ U+00FF
+ '"', '[' 196 Ä U+00C4
+ '"', '\' 214 Ö U+00D6
+ '"', ']' 220 Ü U+00DC
+ '"', '@{' 228 ä U+00E4
+ '"', '|' 246 ö U+00F6
+ '"', '@}' 252 ü U+00FC
+ '"', '~' 223 ß U+00DF
+@end example
+
@end deffn
@node Bell, Clear, Digraph, Virtual Terminal
@@ -2509,7 +3010,7 @@ The default message is
An empty message can be supplied to the @code{bell_msg} command to suppress
output of a message line (@code{bell_msg ""}).
-Without parameter, the current message is shown.
+Without a parameter, the current message is shown.
@end deffn
@kindex C-g
@@ -2533,7 +3034,7 @@ Sets the visual bell message. @var{Message} is printed to the status
line if the window receives a bell character (^G), @code{vbell} is
set to @samp{on} and the terminal does not support a visual bell.
The default message is @samp{Wuff, Wuff!!}.
-Without parameter, the current message is shown.
+Without a parameter, the current message is shown.
@end deffn
@deffn Command vbellwait sec
@@ -2593,7 +3094,7 @@ For system information use @code{time}.
@deffn Command dinfo
(none)@*
-Show what screen thinks about your terminal. Useful if you want to know
+Show what @code{screen} thinks about your terminal. Useful if you want to know
why features like color or the alternate charset don't work.
@end deffn
@@ -2851,7 +3352,7 @@ outlined below.
@subsection CR/LF
@deffn Command crlf [state]
(none)@*
-This affects the copying of text regions with the @kbd{C-a [} command.
+This affects the copying of text regions with the @code{copy} command.
If it is set to @samp{on}, lines will be separated by the two character
sequence @samp{CR}/@samp{LF}. Otherwise only @samp{LF} is used.
@code{crlf} is off by default.
@@ -2860,6 +3361,7 @@ When no parameter is given, the state is toggled.
@node Scrollback, Copy Mode Keys, Line Termination, Copy
@subsection Scrollback
+To access and use the contents in the scrollback buffer, use the @code{copy} command. @xref{Copy}.
@deffn Command defscrollback num
(none)@*
Same as the @code{scrollback} command except that the default setting
@@ -2869,7 +3371,7 @@ for new windows is changed. Defaults to 100.
@deffn Command scrollback num
(none)@*
Set the size of the scrollback buffer for the current window to
-@var{num} lines. The default scrollback is 100 lines. Use @kbd{C-a i}
+@var{num} lines. The default scrollback is 100 lines. Use @code{info}
to view the current setting.
@end deffn
@@ -3076,10 +3578,11 @@ display (terminal attached), as the registers are a global resource. The
paste buffer exists once for every user.
@end deffn
-@deffn Command stuff string
+@deffn Command stuff [string]
(none)@*
Stuff the string @var{string} in the input buffer of the current window.
This is like the @code{paste} command, but with much less overhead.
+Without a paramter, @code{screen} will prompt for a string to stuff.
You cannot paste large buffers with the @code{stuff} command. It is most
useful for key bindings. @xref{Bindkey}.
@end deffn
@@ -3196,8 +3699,9 @@ See also
@section History
@kindex @{
+@kindex @}
@deffn Command history
-(@kbd{C-a @{})@*
+(@kbd{C-a @{}, @kbd{C-a @}})@*
Usually users work with a shell that allows easy access to previous
commands. For example, @code{csh} has the command @code{!!} to repeat
the last command executed. @code{screen} provides a primitive way of
@@ -3351,11 +3855,19 @@ command to activate a class. Command classes can be used
to create multiple command keys or multi-character bindings.
By default, most suitable commands are bound to one or more keys
-(@pxref{Default Key Bindings}; for instance, the command to create a
+(@pxref{Default Key Bindings}); for instance, the command to create a
new window is bound to @kbd{C-c} and @kbd{c}. The @code{bind} command
can be used to redefine the key bindings and to define new bindings.
@end deffn
+@deffn Command unbindall
+(none)@*
+Unbind all the bindings. This can be useful when
+screen is used solely for its detaching abilities, such as when
+letting a console application run as a daemon. If, for some reason,
+it is necessary to bind commands after this, use 'screen -X'.
+@end deffn
+
@node Bind Examples, Command Character, Bind, Key Binding
@section Examples of the @code{bind} command
@noindent
@@ -3540,10 +4052,10 @@ in the default bindkey table.
(none)@*
Like mapdefault, but don't even look in the default bindkey table.
@end deffn
-@deffn Command maptimeout timo
+@deffn Command maptimeout n
(none)@*
Set the inter-character timer for input sequence detection to a timeout
-of @var{timo} ms. The default timeout is 300ms. Maptimeout with no
+of @var{n} ms. The default timeout is 300ms. Maptimeout with no
arguments shows the current setting.
@end deffn
@@ -3652,7 +4164,7 @@ Send a ^S (ASCII XOFF) to the program in the current window.
@node Termcap, Message Line, Flow Control, Top
@chapter Termcap
-@code{screen} demands the most out of your terminal so that it can
+@code{Screen} demands the most out of your terminal so that it can
perform its VT100 emulation most efficiently. These functions provide
means for tweaking the termcap entries for both your physical terminal
and the one simulated by @code{screen}.
@@ -4095,7 +4607,7 @@ template is just @samp{%}, so the mapping is straightforward:
@chapter The Message Line
@cindex message line
-@code{screen} displays informational messages and other diagnostics in a
+@code{Screen} displays informational messages and other diagnostics in a
@dfn{message line} at the bottom of the screen. If your terminal has a
status line defined in its termcap, screen will use this for displaying
its messages, otherwise the last line of the screen will be temporarily
@@ -4198,9 +4710,8 @@ This section describes the commands for keeping a record of your session.
@node Hardcopy, Log, , Logging
@section hardcopy
@kindex h
-@kindex C-h
@deffn Command hardcopy [-h] [@var{file}]
-(@kbd{C-a h}, @kbd{C-a C-h})@*
+(@kbd{C-a h})@*
Writes out the currently displayed image to the file @var{file}, or,
if no filename is specified, to @file{hardcopy.@var{n}}
in the default directory, where @var{n} is the number of the
@@ -4325,12 +4836,12 @@ categories.
* Nethack:: Use @code{nethack}-like error messages.
* Nonblock:: Disable flow-control to a display.
* Number:: Change the current window's number.
-* Silence:: Notify on inactivity.
* Time:: Display the time and load average.
* Verbose:: Display window creation commands.
* Version:: Display the version of @code{screen}.
* Zombie:: Keep dead windows.
* Printcmd:: Set command for VT100 printer port emulation.
+* Rendition:: Change text attributes in caption for flagged windows.
* Sorendition:: Change the text highlighting method.
* Attrcolor:: Map attributes to colors.
* Setsid:: Change process group management.
@@ -4339,6 +4850,7 @@ categories.
* Backtick:: Program a command for a backtick string escape.
* Screen Saver:: Define a screen safer.
* Zmodem:: Define how screen treats zmodem requests.
+* Mousetrack:: Set whether screen should track mouse events.
@end menu
@node At, Break, , Miscellaneous
@@ -4377,8 +4889,10 @@ work correctly under @code{at} looping over windows.
@node Break, Debug, At, Miscellaneous
@section Break
+@kindex b
+@kindex C-b
@deffn Command break [duration]
-(none)@*
+(@kbd{C-a b}, @kbd{C-a C-b})@*
Send a break signal for @var{duration}*0.25 seconds to this window.
For non-Posix systems the time interval is rounded up to full seconds.
Most useful if a character device is attached to the window rather than
@@ -4386,8 +4900,9 @@ a shell process (@pxref{Window Types}). The maximum duration of
a break signal is limited to 15 seconds.
@end deffn
+@kindex B
@deffn Command pow_break
-(none)@*
+(@kbd{C-a B})@*
Reopen the window's terminal line and send a break condition.
@end deffn
@@ -4427,8 +4942,9 @@ be turned off once and forever.
@node License, Nethack, Debug, Miscellaneous
@section License
+@kindex ,
@deffn Command license
-(none)@*
+(@kbd{C-a ,})@*
Display the disclaimer page. This is done whenever @code{screen} is
started without options, which should be often enough.
@end deffn
@@ -4445,7 +4961,8 @@ to read. Anyway, standard messages often tend to be unclear as well.
This option is only available if @code{screen} was compiled with the
NETHACK flag defined (@pxref{Installation}). The default setting is then
determined by the presence of the environment variable
-@code{$NETHACKOPTIONS}.
+@code{$NETHACKOPTIONS} and the file @code{~/.nethackrc} - if either one is
+present, the default is @code{on}.
@end deffn
@node Nonblock, Number, Nethack, Miscellaneous
@@ -4468,41 +4985,19 @@ Same as the @code{nonblock} command except that the default setting for
displays is changed. Initial setting is @code{off}.
@end deffn
-@node Number, Silence, Nonblock, Miscellaneous
+@node Number, Time, Nonblock, Miscellaneous
@section Number
@kindex N
-@deffn Command number [@var{n}]
+@deffn Command number [[+|-]@var{n}]
(@kbd{C-a N})@*
Change the current window's number. If the given number @var{n} is already
used by another window, both windows exchange their numbers. If no argument is
-specified, the current window number (and title) is shown.
-@end deffn
-
-@node Silence, Time, Number, Miscellaneous
-@section Silence
-@deffn Command silence [@var{state}|@var{sec}]
-(none)@*
-Toggles silence monitoring of windows. When silence is turned on and an
-affected window is switched into the background, you will receive the
-silence notification message in the status line after a specified period
-of inactivity (silence). The default timeout can be changed with the
-@code{silencewait} command or by specifying a number of seconds instead of
-@code{on} or @code{off}. Silence is initially off for all windows.
-@end deffn
-
-@deffn Command defsilence state
-(none)@*
-Same as the @code{silence} command except that the default setting for
-new windows is changed. Initial setting is `off'.
-@end deffn
-
-@deffn Command silencewait @var{seconds}
-(none)@*
-Define the time that all windows monitored for silence should wait
-before displaying a message. Default is 30 seconds.
+specified, the current window number (and title) is shown. Using either a
+plus (`+') or minus (`-') will change the window's number by the relative
+amount specified.
@end deffn
-@node Time, Verbose, Silence, Miscellaneous
+@node Time, Verbose, Number, Miscellaneous
@section Time
@kindex t
@kindex C-t
@@ -4520,7 +5015,7 @@ like it is described in the string escapes chapter (@pxref{String Escapes}). Scr
@deffn Command verbose [on|off]
If verbose is switched on, the command name is echoed, whenever a window
is created (or resurrected from zombie state). Default is off.
-Without parameter, the current setting is shown.
+Without a parameter, the current setting is shown.
@end deffn
@node Version, Zombie, Verbose, Miscellaneous
@@ -4556,7 +5051,7 @@ If it exits normally ('0'), the window disappears. Any other exit value
causes the window to become a zombie.
@end deffn
-@node Printcmd, Sorendition, Zombie, Miscellaneous
+@node Printcmd, Rendition, Zombie, Miscellaneous
@section Printcmd
@deffn Command printcmd [@var{cmd}]
(none)@*
@@ -4572,16 +5067,24 @@ Warning: Be careful with this command! If other user have write
access to your terminal, they will be able to fire off print commands.
@end deffn
-@node Sorendition, Attrcolor, Printcmd, Miscellaneous
-@section Sorendition
-@deffn Command sorendition [@var{attr} [@var{color}]]
+@node Rendition, Sorendition, Printcmd, Miscellaneous
+@section Rendition
+@deffn Command rendition bell | monitor | silence | so @var{attr} [@var{color}]
(none)@*
-Change the way screen does highlighting for text marking and printing
-messages.
+Change the way screen renders the titles of windows that have monitor
+or bell flags set in caption or hardstatus or windowlist.
See the chapter
about string escapes (@pxref{String Escapes}) for the syntax of
-the modifiers. The default is currently @samp{=s dd} (standout,
-default colors).
+the modifiers. The default for monitor is currently @samp{=b} (bold,
+active colors), for bell @samp{=ub} (underline, bold and active colors), and
+for silence @samp{=u}.
+@end deffn
+
+@node Sorendition, Attrcolor, Rendition, Miscellaneous
+@section Sorendition
+@deffn Command sorendition [@var{attr} [@var{color}]]
+(none)@*
+This command has been deprecated. Use @code{rendition so} instead.
@end deffn
@node Attrcolor, Setsid, Sorendition, Miscellaneous
@@ -4594,7 +5097,7 @@ the text. If the attribute
is in use, the specified attribute/color modifier is also applied. If no
modifier is given, the current one is deleted. See the chapter
about string escapes (@pxref{String Escapes}) for the syntax of
-the modifier. Screen understands two pseudo-attributes, @code{i}
+the modifier. @code{Screen} understands two pseudo-attributes, @code{i}
stands for high-intensity foreground color and @code{I} for
high-intensity background color.
@@ -4617,7 +5120,7 @@ Make bright colored text also bold.
@section Setsid
@deffn Command setsid state
(none)@*
-Normally screen uses different sessions and process groups for
+Normally @code{screen} uses different sessions and process groups for
the windows. If setsid is turned @code{off}, this is not done
anymore and all windows will be in the same process group as the
screen backend process. This also breaks job-control, so be careful.
@@ -4637,7 +5140,8 @@ Parses and executes each argument as separate command.
@deffn Command maxwin @var{n}
(none)@*
Set the maximum window number screen will create. Doesn't affect
-already existing windows. The number may only be decreased.
+already existing windows. The number can be increased only when there are no
+existing windows.
@end deffn
@node Backtick, Screen Saver, Maxwin, Miscellaneous
@@ -4693,8 +5197,10 @@ command.
@end deffn
@deffn Command blankerprg [@var{program args}]
-Defines a blanker program. Disables the blanker program if
-no arguments are given.
+Defines a blanker program. Disables the blanker program if an
+empty argument is given. Shows the currently set blanker program if no
+arguments are given.
+
@end deffn
@node Zmodem, , Screen Saver, Miscellaneous
@@ -4703,7 +5209,7 @@ no arguments are given.
@deffnx Command zmodem sendcmd [string]
@deffnx Command zmodem recvcmd [string]
(none)@*
-Define zmodem support for screen. Screen understands two
+Define zmodem support for @code{screen}. @code{Screen} understands two
different modes when it detects a zmodem request: @code{pass}
and @code{catch}. If the mode is set to @code{pass}, screen will
relay all data to the attacher until the end of the
@@ -4745,7 +5251,7 @@ day number
@item D
weekday name
@item f
-flags of the window
+flags of the window. @xref{Windows}, for meanings of the various flags.
@item F
sets %? to true if the window has the focus
@item h
@@ -4760,6 +5266,8 @@ month number
month name
@item n
window number
+@item P
+sets %? to true if the current region is in copy/paste mode
@item s
seconds
@item S
@@ -5259,7 +5767,5 @@ from the key sequences, since it is the same for all bindings.
@printindex ky
-@shortcontents
-@contents
@bye
diff --git a/src/extern.h b/src/extern.h
index 6ca155b..ee655f5 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
#if !defined(__GNUC__) || __GNUC__ < 2
@@ -35,13 +35,13 @@
/* screen.c */
extern int main __P((int, char **));
extern sigret_t SigHup __P(SIGPROTOARG);
-extern void eexit __P((int));
+extern void eexit __P((int)) __attribute__((__noreturn__));
extern void Detach __P((int));
extern void Hangup __P((void));
extern void Kill __P((int, int));
#ifdef USEVARARGS
-extern void Msg __P((int, char *, ...)) __attribute__((format(printf, 2, 3)));
-extern void Panic __P((int, char *, ...)) __attribute__((format(printf, 2, 3)));
+extern void Msg __P((int, const char *, ...)) __attribute__((format(printf, 2, 3)));
+extern void Panic __P((int, const char *, ...)) __attribute__((format(printf, 2, 3))) __attribute__((__noreturn__));
#else
extern void Msg __P(());
extern void Panic __P(());
@@ -50,6 +50,7 @@ extern void Finit __P((int));
extern void MakeNewEnv __P((void));
extern char *MakeWinMsg __P((char *, struct win *, int));
extern char *MakeWinMsgEv __P((char *, struct win *, int, int, struct event *, int));
+extern int AddWinMsgRend __P((const char *, int));
extern void PutWinMsg __P((char *, int, int));
#ifdef BSDWAIT
extern void WindowDied __P((struct win *, union wait, int));
@@ -131,7 +132,6 @@ extern void display_help __P((char *, struct action *));
extern void display_copyright __P((void));
extern void display_displays __P((void));
extern void display_bindkey __P((char *, struct action *));
-extern void display_wlist __P((int, int, struct win *));
extern int InWList __P((void));
extern void WListUpdatecv __P((struct canvas *, struct win *));
extern void WListLinkChanged __P((void));
@@ -155,7 +155,9 @@ extern void CloseDevice __P((struct win *));
#ifdef ZMODEM
extern void zmodem_abort __P((struct win *, struct display *));
#endif
+#ifndef HAVE_EXECVPE
extern void execvpe __P((char *, char **, char **));
+#endif
/* utmp.c */
#ifdef UTMPOK
@@ -194,7 +196,7 @@ extern void ProcessInput2 __P((char *, int));
#endif
extern void DoProcess __P((struct win *, char **, int *, struct paster *));
extern void DoAction __P((struct action *, int));
-extern int FindCommnr __P((char *));
+extern int FindCommnr __P((const char *));
extern void DoCommand __P((char **, int *));
extern void Activate __P((int));
extern void KillWindow __P((struct win *));
@@ -238,7 +240,7 @@ extern void FreeTransTable __P((void));
extern int Attach __P((int));
extern void Attacher __P((void));
extern sigret_t AttacherFinit __P(SIGPROTOARG);
-extern void SendCmdMessage __P((char *, char *, char **));
+extern void SendCmdMessage __P((char *, char *, char **, int));
/* display.c */
extern struct display *MakeDisplay __P((char *, char *, char *, int, int, struct mode *));
@@ -290,23 +292,12 @@ extern void RemoveStatus __P((void));
extern int ResizeDisplay __P((int, int));
extern void AddStr __P((char *));
extern void AddStrn __P((char *, int));
-extern void Flush __P((void));
+extern void Flush __P((int));
extern void freetty __P((void));
extern void Resize_obuf __P((void));
#ifdef AUTO_NUKE
extern void NukePending __P((void));
#endif
-extern void SetCanvasWindow __P((struct canvas *, struct win *));
-extern int MakeDefaultCanvas __P((void));
-extern int AddCanvas __P((int));
-extern void RemCanvas __P((void));
-extern void OneCanvas __P((void));
-extern void ResizeCanvas __P((struct canvas *));
-extern void RecreateCanvasChain __P((void));
-extern int RethinkDisplayViewports __P((void));
-extern void RethinkViewportOffsets __P((struct canvas *));
-extern int CountCanvasPerp __P((struct canvas *));
-extern void EqualizeCanvas __P((struct canvas *, int));
#ifdef RXVT_OSC
extern void ClearAllXtermOSC __P((void));
extern void SetXtermOSC __P((int, char *));
@@ -320,12 +311,6 @@ extern int color256to88 __P((int));
extern void ResetIdle __P((void));
extern void KillBlanker __P((void));
extern void DisplaySleep1000 __P((int, int));
-extern void AutosaveLayout __P((struct layout *));
-extern void LoadLayout __P((struct layout *, struct canvas *));
-extern void NewLayout __P((char *, int));
-extern void SaveLayout __P((char *, struct canvas *));
-extern void ShowLayouts __P((int));
-extern struct layout *FindLayout __P((char *));
/* resize.c */
extern int ChangeWindowSize __P((struct win *, int, int, int));
@@ -364,7 +349,7 @@ extern char *InStr __P((char *, const char *));
extern char *strerror __P((int));
#endif
extern void centerline __P((char *, int));
-extern void leftline __P((char *, int));
+extern void leftline __P((char *, int, struct mchar *));
extern char *Filename __P((char *));
extern char *stripdev __P((char *));
#ifdef NEED_OWN_BCOPY
@@ -456,7 +441,7 @@ extern void LKeypadMode __P((struct layer *, int));
extern void LCursorkeysMode __P((struct layer *, int));
extern void LMouseMode __P((struct layer *, int));
#ifdef USEVARARGS
-extern void LMsg __P((int, char *, ...)) __attribute__((format(printf, 2, 3)));
+extern void LMsg __P((int, const char *, ...)) __attribute__((format(printf, 2, 3)));
#else
extern void LMsg __P(());
#endif
@@ -478,7 +463,7 @@ extern void TelStatus __P((struct win *, char *, int));
#endif
/* nethack.c */
-extern char *DoNLS __P((char *));
+extern const char *DoNLS __P((const char *));
/* encoding.c */
#ifdef ENCODINGS
diff --git a/src/fileio.c b/src/fileio.c
index 1dd13c2..88fbf64 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -75,7 +75,7 @@ register char *str1, *str2;
{
len2 = strlen(str2);
if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
bcopy(cp, cp + len1 + add_colon, len2 + 1);
}
else
@@ -83,8 +83,8 @@ register char *str1, *str2;
if (len1 == 0)
return 0;
if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL)
- Panic(0, strnomem);
- cp[len1 + add_colon] = '\0';
+ Panic(0, "%s", strnomem);
+ cp[len1 + add_colon] = '\0';
}
bcopy(str1, cp, len1);
if (add_colon)
@@ -112,7 +112,7 @@ char *rcfile;
if (!home)
{
Msg(0, "%s: source: tilde expansion failed", rc_name);
- return;
+ return NULL;
}
snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", home, rcfile+2);
}
@@ -124,14 +124,14 @@ char *rcfile;
if (!p)
{
Msg(0, "%s: source: tilde expansion failed for user %s", rc_name, rcfile+1);
- return;
+ return NULL;
}
snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", p->pw_dir, slash_position+1);
}
else
{
Msg(0, "%s: source: illegal tilde expression.", rc_name);
- return;
+ return NULL;
}
rcfile = rcfilename_tilde_exp;
}
@@ -192,21 +192,23 @@ int nopanic;
rc_name = findrcfile(rcfilename);
- if ((fp = secfopen(rc_name, "r")) == NULL)
+ if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL)
{
- if (!rc_recursion && RcFileName && !strcmp(RcFileName, rc_name))
+ const char *rc_nonnull = rc_name ? rc_name : rcfilename;
+ if (!rc_recursion && RcFileName && !strcmp(RcFileName, rc_nonnull))
{
/*
* User explicitly gave us that name,
* this is the only case, where we get angry, if we can't read
* the file.
*/
- debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name, rcfilename);
- if (!nopanic) Panic(0, "Unable to open \"%s\".", rc_name);
+ debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name ? rc_name : "(null)", rcfilename);
+ if (!nopanic) Panic(0, "Unable to open \"%s\".", rc_nonnull);
/* possibly NOTREACHED */
}
- debug1("StartRc: '%s' no good. ignored\n", rc_name);
- Free(rc_name);
+ debug1("StartRc: '%s' no good. ignored\n", rc_nonnull);
+ if (rc_name)
+ Free(rc_name);
rc_name = oldrc_name;
return 1;
}
@@ -229,7 +231,7 @@ int nopanic;
if (argc != 3)
{
AddStr("\r\n");
- Flush();
+ Flush(0);
}
}
else if (strcmp(args[0], "sleep") == 0)
@@ -302,23 +304,25 @@ char *rcfilename;
rc_name = findrcfile(rcfilename);
- if ((fp = secfopen(rc_name, "r")) == NULL)
+ if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL)
{
+ const char *rc_nonnull = rc_name ? rc_name : rcfilename;
if (rc_recursion)
- Msg(errno, "%s: source %s", oldrc_name, rc_name);
- else if (RcFileName && !strcmp(RcFileName, rc_name))
+ Msg(errno, "%s: source %s", oldrc_name, rc_nonnull);
+ else if (RcFileName && !strcmp(RcFileName, rc_nonnull))
{
/*
* User explicitly gave us that name,
* this is the only case, where we get angry, if we can't read
* the file.
*/
- debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name, rcfilename);
- Panic(0, "Unable to open \"%s\".", rc_name);
+ debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name ? rc_name : "(null)", rcfilename);
+ Panic(0, "Unable to open \"%s\".", rc_nonnull);
/* NOTREACHED */
}
- debug1("FinishRc: '%s' no good. ignored\n", rc_name);
- Free(rc_name);
+ debug1("FinishRc: '%s' no good. ignored\n", rc_nonnull);
+ if (rc_name)
+ Free(rc_name);
rc_name = oldrc_name;
return;
}
@@ -623,7 +627,7 @@ int *lenp;
if ((buf = malloc(size)) == NULL)
{
close(i);
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return NULL;
}
errno = 0;
@@ -873,7 +877,7 @@ char **cmdv;
#endif
execvp(*cmdv, cmdv);
close(1);
- Panic(errno, *cmdv);
+ Panic(errno, "%s", *cmdv);
default:
break;
}
diff --git a/src/help.c b/src/help.c
index aa570fe..f2fdd18 100644
--- a/src/help.c
+++ b/src/help.c
@@ -1,4 +1,7 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -33,19 +36,25 @@
#include "screen.h"
#include "extern.h"
+#include "list_generic.h"
+
char version[60]; /* initialised by main() */
extern struct layer *flayer;
extern struct display *display, *displays;
extern struct win *windows;
+extern int maxwin;
extern char *noargs[];
extern struct mchar mchar_blank, mchar_so;
+extern int renditions[];
extern unsigned char *blank;
-extern struct win *wtab[];
+extern struct win **wtab;
#ifdef MAPKEYS
extern struct term term[];
#endif
+extern struct LayFuncs ListLf;
+
static void PadStr __P((char *, int, int, int));
extern char *wliststr;
@@ -73,13 +82,13 @@ char *myname, *message, *arg;
#if defined(LOGOUTOK) && defined(UTMPOK)
printf("-l Login mode on (update %s), -ln = off.\n", UTMPFILE);
#endif
- printf("-list or -ls. Do nothing, just list our SockDir.\n");
+ printf("-ls [match] or -list. Do nothing, just list our SockDir [on possible matches].\n");
printf("-L Turn on output logging.\n");
printf("-m ignore $STY variable, do create a new screen session.\n");
printf("-O Choose optimal output rather than exact vt100 emulation.\n");
printf("-p window Preselect the named window if it exists.\n");
printf("-q Quiet startup. Exits with non-zero return code if unsuccessful.\n");
- printf("-r Reattach to a detached screen process.\n");
+ printf("-r [session] Reattach to a detached screen process.\n");
printf("-R Reattach if possible, otherwise start a new session.\n");
printf("-s shell Shell to execute rather than $SHELL.\n");
printf("-S sockname Name this session <pid>.sockname instead of <pid>.<tty>.<host>.\n");
@@ -89,7 +98,7 @@ char *myname, *message, *arg;
printf("-U Tell screen to use UTF-8 encoding.\n");
#endif
printf("-v Print \"Screen version %s\".\n", version);
- printf("-wipe Do nothing, just clean up SockDir.\n");
+ printf("-wipe [match] Do nothing, just clean up SockDir [on possible matches].\n");
#ifdef MULTI
printf("-x Attach to a not detached screen. (Multi display mode).\n");
#endif /* MULTI */
@@ -139,7 +148,8 @@ static struct LayFuncs HelpLf =
DefClearLine,
DefRewrite,
DefResize,
- DefRestore
+ DefRestore,
+ 0
};
@@ -495,14 +505,16 @@ static struct LayFuncs CopyrightLf =
DefClearLine,
DefRewrite,
DefResize,
- DefRestore
+ DefRestore,
+ 0
};
static const char cpmsg[] = "\
\n\
Screen version %v\n\
\n\
-Copyright (c) 2008 Juergen Weigert, Michael Schroeder, Micah Cowan, Sadrul Habib Chowdhury\n\
+Copyright (c) 2010 Juergen Weigert, Sadrul Habib Chowdhury\n\
+Copyright (c) 2008, 2009 Juergen Weigert, Michael Schroeder, Micah Cowan, Sadrul Habib Chowdhury\n\
Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 Juergen Weigert, Michael Schroeder\n\
Copyright (c) 1987 Oliver Laumann\n\
\n\
@@ -679,804 +691,6 @@ int y, xs, xe, isblank;
}
-
-/*
-**
-** here is all the displays stuff
-**
-*/
-
-#ifdef MULTI
-
-static void DisplaysProcess __P((char **, int *));
-static void DisplaysRedisplayLine __P((int, int, int, int));
-static void displayspage __P((void));
-
-struct displaysdata
-{
- int dummy_element_for_solaris;
-};
-
-static struct LayFuncs DisplaysLf =
-{
- DisplaysProcess,
- HelpAbort,
- DisplaysRedisplayLine,
- DefClearLine,
- DefRewrite,
- DefResize,
- DefRestore
-};
-
-static void
-DisplaysProcess(ppbuf, plen)
-char **ppbuf;
-int *plen;
-{
- int done = 0;
-
- ASSERT(flayer);
- while (!done && *plen > 0)
- {
- switch (**ppbuf)
- {
- case ' ':
- displayspage();
- break;
- case '\r':
- case '\n':
- HelpAbort();
- done = 1;
- break;
- default:
- break;
- }
- ++*ppbuf;
- --*plen;
- }
-}
-
-
-void
-display_displays()
-{
- if (flayer->l_width < 10 || flayer->l_height < 5)
- {
- LMsg(0, "Window size too small for displays page");
- return;
- }
- if (InitOverlayPage(sizeof(struct displaysdata), &DisplaysLf, 0))
- return;
- flayer->l_x = 0;
- flayer->l_y = flayer->l_height - 1;
- displayspage();
-}
-
-/*
- * layout of the displays page is as follows:
-
-xterm 80x42 jnweiger@/dev/ttyp4 0(m11) &rWx
-facit 80x24 nb mlschroe@/dev/ttyhf 11(tcsh) rwx
-xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x
-
- | | | | | | | | ¦___ window permissions
- | | | | | | | | (R. is locked r-only,
- | | | | | | | | W has wlock)
- | | | | | | | |___ Window is shared
- | | | | | | |___ Name/Title of window
- | | | | | |___ Number of window
- | | | | |___ Name of the display (the attached device)
- | | | |___ Username who is logged in at the display
- | | |___ Display is in nonblocking mode. Shows 'NB' if obuf is full.
- | |___ Displays geometry as width x height.
- |___ the terminal type known by screen for this display.
-
- */
-
-static void
-displayspage()
-{
- int y, l;
- char tbuf[80];
- struct display *d;
- struct win *w;
- static char *blockstates[5] = {"nb", "NB", "Z<", "Z>", "BL"};
-
- LClearAll(flayer, 0);
-
- leftline("term-type size user interface window", 0);
- leftline("---------- ------- ---------- ----------------- ----------", 1);
- y = 2;
-
- for (d = displays; d; d = d->d_next)
- {
- w = d->d_fore;
-
- if (y >= flayer->l_height - 3)
- break;
- sprintf(tbuf, "%-10.10s%4dx%-4d%10.10s@%-16.16s%s",
- d->d_termname, d->d_width, d->d_height, d->d_user->u_name,
- d->d_usertty,
- (d->d_blocked || d->d_nonblock >= 0) && d->d_blocked <= 4 ? blockstates[d->d_blocked] : " ");
-
- if (w)
- {
- l = 10 - strlen(w->w_title);
- if (l < 0)
- l = 0;
- sprintf(tbuf + strlen(tbuf), "%3d(%.10s)%*s%c%c%c%c",
- w->w_number, w->w_title, l, "",
- /* w->w_dlist->next */ 0 ? '&' : ' ',
- /*
- * The rwx triple:
- * -,r,R no read, read, read only due to foreign wlock
- * -,.,w,W no write, write suppressed by foreign wlock,
- * write, own wlock
- * -,x no execute, execute
- */
-#ifdef MULTIUSER
- (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
- ((w->w_wlock == WLOCK_OFF || d->d_user == w->w_wlockuser) ?
- 'r' : 'R')),
- (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
- ((w->w_wlock == WLOCK_OFF) ? 'w' :
- ((d->d_user == w->w_wlockuser) ? 'W' : 'v'))),
- (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : 'x')
-#else
- 'r', 'w', 'x'
-#endif
- );
- }
- leftline(tbuf, y);
- y++;
- }
- sprintf(tbuf,"[Press Space %s Return to end.]",
- 1 ? "to refresh;" : "or");
- centerline(tbuf, flayer->l_height - 2);
- LaySetCursor();
-}
-
-static void
-DisplaysRedisplayLine(y, xs, xe, isblank)
-int y, xs, xe, isblank;
-{
- ASSERT(flayer);
- if (y < 0)
- {
- displayspage();
- return;
- }
- if (y != 0 && y != flayer->l_height - 1)
- return;
- if (isblank)
- return;
- LClearArea(flayer, xs, y, xe, y, 0, 0);
- /* To be filled in... */
-}
-
-#endif /* MULTI */
-
-
-/*
-**
-** here is the windowlist
-**
-*/
-
-struct wlistdata;
-
-static void WListProcess __P((char **, int *));
-static void WListRedisplayLine __P((int, int, int, int));
-static void wlistpage __P((void));
-static void WListLine __P((int, int, int, int));
-static void WListLines __P((int, int));
-static void WListMove __P((int, int));
-static void WListUpdate __P((struct win *));
-static int WListNormalize __P((void));
-static int WListResize __P((int, int));
-static int WListNext __P((struct wlistdata *, int, int));
-
-struct wlistdata {
- int pos;
- int ypos;
- int npos;
- int numwin;
- int first;
- int last;
- int start;
- int order;
- struct win *group;
- int nested;
- int list[MAXWIN];
-};
-
-static struct LayFuncs WListLf =
-{
- WListProcess,
- HelpAbort,
- WListRedisplayLine,
- DefClearLine,
- DefRewrite,
- WListResize,
- DefRestore
-};
-
-#define WTAB_GROUP_MATCHES(i) (group == wtab[i]->w_group)
-
-static int
-WListResize(wi, he)
-int wi, he;
-{
- struct wlistdata *wlistdata;
- if (wi < 10 || he < 5)
- return -1;
- wlistdata = (struct wlistdata *)flayer->l_data;
- flayer->l_width = wi;
- flayer->l_height = he;
- wlistdata->numwin = he - 3;
- if (wlistdata->ypos >= wlistdata->numwin)
- wlistdata->ypos = wlistdata->numwin - 1;
- flayer->l_y = he - 1;
- return 0;
-}
-
-static void
-WListProcess(ppbuf, plen)
-char **ppbuf;
-int *plen;
-{
- int done = 0;
- struct wlistdata *wlistdata;
- struct display *olddisplay = display;
- int h;
- struct win *group;
-
- ASSERT(flayer);
- wlistdata = (struct wlistdata *)flayer->l_data;
- group = wlistdata->group;
- h = wlistdata->numwin;
- while (!done && *plen > 0)
- {
- if ((unsigned char)**ppbuf >= '0' && (unsigned char)**ppbuf <= '9')
- {
- int n = (unsigned char)**ppbuf - '0';
- int d = 0;
- if (n < MAXWIN && wtab[n] && WTAB_GROUP_MATCHES(n))
- {
- int i;
- for (d = -wlistdata->npos, i = WListNext(wlistdata, -1, 0); i != n; i = WListNext(wlistdata, i, 1), d++)
- ;
- }
- if (d)
- WListMove(d, -1);
- }
- switch ((unsigned char)**ppbuf)
- {
- case 0220: /* up */
- case 16: /* ^P like emacs */
- case 'k':
- WListMove(-1, -1);
- break;
- case 0216: /* down */
- case 14: /* ^N like emacs */
- case 'j':
- WListMove(1, -1);
- break;
- case '\025':
- WListMove(-(h / 2), wlistdata->ypos);
- break;
- case '\004':
- WListMove(h / 2, wlistdata->ypos);
- break;
- case 0002:
- case 'b':
- WListMove(-h, -1);
- break;
- case 0006:
- case 'f':
- WListMove(h, -1);
- break;
- case 0201: /* home */
- WListMove(-wlistdata->pos, -1);
- break;
- case 0205: /* end */
- WListMove(MAXWIN, -1);
- break;
- case 'a':
- /* All-window view */
- wlistdata->group = 0;
- wlistdata->nested = WLIST_NESTED;
- wlistpage();
- break;
- case 'g':
- /* Toggle nested view */
- wlistdata->nested ^= WLIST_NESTED;
- wlistpage();
- break;
- case 'm':
- /* Toggle MRU view */
- wlistdata->order ^= 1;
- wlistpage();
- break;
- case '\r':
- case '\n':
- case ' ':
- h = wlistdata->pos;
- if (h == MAXWIN && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
- break;
- if (display && h != MAXWIN && wtab[h] && (wtab[h]->w_type == W_TYPE_GROUP || wtab[h] == D_fore))
- {
- wlistdata->group = wtab[h];
- wlistdata->pos = wtab[h]->w_number;
- wlistpage();
- break;
- }
- done = 1;
- if (!display || h == MAXWIN || !wtab[h] || wtab[h] == D_fore || (flayer->l_cvlist && flayer->l_cvlist->c_lnext))
- HelpAbort();
-#ifdef MULTIUSER
- else if (AclCheckPermWin(D_user, ACL_READ, wtab[h]))
- HelpAbort();
-#endif
- else
- ExitOverlayPage(); /* no need to redisplay */
- /* restore display, don't switch wrong user */
- display = olddisplay;
- if (h != MAXWIN)
- SwitchWindow(h);
- break;
- case 0033:
- case 0007:
- h = wlistdata->start;
- if (h == -1 && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
- {
- struct win *p = Layer2Window(flayer);
- if (wlistdata->group != p)
- {
- wlistdata->group = p;
- wlistpage();
- }
- break;
- }
- HelpAbort();
- display = olddisplay;
- if (h >= 0 && wtab[h])
- SwitchWindow(h);
- else if (h == -2)
- {
- struct win *p = FindNiceWindow(display ? D_other : (struct win *)0, 0);
- if (p)
- SwitchWindow(p->w_number);
- }
- done = 1;
- break;
- case '\010': /* ctrl-h */
- case 0177:
- if (!wlistdata->group)
- break;
- wlistdata->pos = wlistdata->group->w_number;
- wlistdata->group = wlistdata->group->w_group;
- if (wlistdata->group)
- wlistdata->pos = wlistdata->group->w_number;
- wlistpage();
- break;
- default:
- break;
- }
- ++*ppbuf;
- --*plen;
- }
-}
-
-static void
-WListLine(y, i, pos, isblank)
-int y, i;
-int pos;
-int isblank;
-{
- char *str;
- int n;
- int yoff, xoff = 0;
- struct wlistdata *wlistdata;
- struct win *group;
-
- if (i == MAXWIN)
- return;
- wlistdata = (struct wlistdata *)flayer->l_data;
- if (wlistdata->nested && wtab[i])
- for (group = wtab[i]->w_group, xoff = 0; group != wlistdata->group;
- group = group->w_group, xoff += 2)
- ;
- yoff = wlistdata->group ? 3 : 2;
- display = Layer2Window(flayer) ? 0 : flayer->l_cvlist ? flayer->l_cvlist->c_display : 0;
- str = MakeWinMsgEv(wliststr, wtab[i], '%', flayer->l_width - xoff, (struct event *)0, 0);
- n = strlen(str);
- if (i != pos && isblank)
- while (n && str[n - 1] == ' ')
- n--;
- LPutWinMsg(flayer, str, (i == pos || !isblank) ? flayer->l_width : n, i == pos ? &mchar_so : &mchar_blank, xoff, y + yoff);
- if (xoff)
- LPutWinMsg(flayer, "", xoff, i == pos ? &mchar_so : &mchar_blank, 0, y + yoff);
-#if 0
- LPutStr(flayer, str, n, i == pos ? &mchar_so : &mchar_blank, 0, y + yoff);
- if (i == pos || !isblank)
- while(n < flayer->l_width)
- LPutChar(flayer, i == pos ? &mchar_so : &mchar_blank, n++, y + yoff);
-#endif
- return;
-}
-
-
-static int
-WListNext(wlistdata, old, delta)
-struct wlistdata *wlistdata;
-int old, delta;
-{
- int i;
-
- if (old == MAXWIN)
- return MAXWIN;
- if (old == -1)
- old = 0;
- else
- {
- for (i = 0; i < MAXWIN && wlistdata->list[i] != -1; i++)
- if (wlistdata->list[i] == old)
- break;
- if (i < MAXWIN && wlistdata->list[i] != -1)
- old = i;
- }
-
- old += delta;
- if (old < 0 || old >= MAXWIN || wlistdata->list[old] == -1)
- old -= delta;
- return wlistdata->list[old];
-}
-
-static void
-WListLines(up, oldpos)
-int up, oldpos;
-{
- struct wlistdata *wlistdata;
- int ypos, pos;
- int y, i, oldi;
-
- wlistdata = (struct wlistdata *)flayer->l_data;
- ypos = wlistdata->ypos;
- pos = wlistdata->pos;
-
- i = WListNext(wlistdata, pos, -ypos);
- for (y = 0; y < wlistdata->numwin; y++)
- {
- if (i == MAXWIN || !wtab[i])
- return;
- if (y == 0)
- wlistdata->first = i;
- wlistdata->last = i;
- if (((i == oldpos || i == pos) && pos != oldpos) || (up > 0 && y >= wlistdata->numwin - up) || (up < 0 && y < -up))
- WListLine(y, i, pos, i != oldpos);
- if (i == pos)
- wlistdata->ypos = y;
- oldi = i;
- i = WListNext(wlistdata, i, 1);
- if (i == MAXWIN || i == oldi)
- break;
- }
-}
-
-static int
-WListNormalize()
-{
- struct wlistdata *wlistdata;
- int i, oldi, n;
- int ypos, pos;
-
- wlistdata = (struct wlistdata *)flayer->l_data;
- ypos = wlistdata->ypos;
- pos = wlistdata->pos;
- if (ypos < 0)
- ypos = 0;
- if (ypos >= wlistdata->numwin)
- ypos = wlistdata->numwin - 1;
- for (n = 0, oldi = MAXWIN, i = pos; i != MAXWIN && i != oldi && n < wlistdata->numwin; oldi = i, i = WListNext(wlistdata, i, 1))
- n++;
- if (ypos < wlistdata->numwin - n)
- ypos = wlistdata->numwin - n;
- for (n = 0, oldi = MAXWIN, i = WListNext(wlistdata, -1, 0); i != MAXWIN && i != oldi && i != pos; oldi = i, i = WListNext(wlistdata, i, 1))
- n++;
- if (ypos > n)
- ypos = n;
- wlistdata->ypos = ypos;
- wlistdata->npos = n;
- return ypos;
-}
-
-static void
-WListMove(num, ypos)
-int num;
-int ypos;
-{
- struct wlistdata *wlistdata;
- int oldpos, oldypos, oldnpos;
- int pos, up;
-
- wlistdata = (struct wlistdata *)flayer->l_data;
- oldpos = wlistdata->pos;
- oldypos = wlistdata->ypos;
- oldnpos = wlistdata->npos;
- wlistdata->ypos = ypos == -1 ? oldypos + num : ypos;
- pos = WListNext(wlistdata, oldpos, num);
- wlistdata->pos = pos;
- ypos = WListNormalize();
- up = wlistdata->npos - ypos - (oldnpos - oldypos);
- if (up)
- {
- LScrollV(flayer, up, 2, 2 + wlistdata->numwin - 1, 0);
- WListLines(up, oldpos);
- LaySetCursor();
- return;
- }
- if (pos == oldpos)
- return;
- WListLine(oldypos, oldpos, pos, 0);
- WListLine(ypos, pos, pos, 1);
- LaySetCursor();
-}
-
-static void
-WListRedisplayLine(y, xs, xe, isblank)
-int y, xs, xe, isblank;
-{
- ASSERT(flayer);
- if (y < 0)
- {
- wlistpage();
- return;
- }
- if (y != 0 && y != flayer->l_height - 1)
- return;
- if (!isblank)
- LClearArea(flayer, xs, y, xe, y, 0, 0);
-}
-
-static int
-WListOrder(wlistdata, ind, start, group)
-struct wlistdata *wlistdata;
-int ind, start;
-struct win *group;
-{
- int i;
-
- if (ind >= MAXWIN)
- return ind;
- if (ind == 0)
- for (i = 0; i < MAXWIN; i++)
- wlistdata->list[i] = -1;
-
- if (wlistdata->order == WLIST_MRU)
- {
- if (start == -1)
- start = windows->w_number;
- }
- else
- {
- if (start == -1)
- start = 0;
- while (start < MAXWIN && !wtab[start])
- start++;
- }
-
- if (start >= MAXWIN || !wtab[start])
- return ind;
-
- if (!WTAB_GROUP_MATCHES(start))
- {
- while (start < MAXWIN && (!wtab[start] || !WTAB_GROUP_MATCHES(start)))
- if (wlistdata->order != WLIST_MRU)
- start++;
- else if (wtab[start]->w_next)
- start = wtab[start]->w_next->w_number;
- else
- start = MAXWIN;
- if (start >= MAXWIN || !wtab[start])
- return ind;
- }
-
- wlistdata->list[ind++] = start;
- if (wlistdata->nested && wtab[start]->w_type == W_TYPE_GROUP)
- ind = WListOrder(wlistdata, ind, -1, wtab[start]);
-
- if (wlistdata->order != WLIST_MRU)
- start++;
- else if (wtab[start]->w_next)
- start = wtab[start]->w_next->w_number;
- else
- return ind;
- return WListOrder(wlistdata, ind, start, group);
-}
-
-void
-display_wlist(onblank, order, group)
-int onblank;
-int order;
-struct win *group;
-{
- struct win *p;
- struct wlistdata *wlistdata;
-
- if (flayer->l_width < 10 || flayer->l_height < 6)
- {
- LMsg(0, "Window size too small for window list page");
- return;
- }
- if (onblank)
- {
- debug3("flayer %x %d %x\n", flayer, flayer->l_width, flayer->l_height);
- if (!display)
- {
- LMsg(0, "windowlist -b: display required");
- return;
- }
- p = D_fore;
- if (p)
- {
- SetForeWindow((struct win *)0);
- if (p->w_group)
- {
- D_fore = p->w_group;
- flayer->l_data = (char *)p->w_group;
- }
- Activate(0);
- }
- if (flayer->l_width < 10 || flayer->l_height < 6)
- {
- LMsg(0, "Window size too small for window list page");
- return;
- }
- }
- else
- p = Layer2Window(flayer);
- if (!group && p)
- group = p->w_group;
- if (InitOverlayPage(sizeof(*wlistdata), &WListLf, 0))
- return;
- wlistdata = (struct wlistdata *)flayer->l_data;
- flayer->l_x = 0;
- flayer->l_y = flayer->l_height - 1;
- wlistdata->start = onblank && p ? p->w_number : -1;
- wlistdata->order = (order & 0x1);
- wlistdata->group = group;
- wlistdata->pos = p ? p->w_number : WListNext(wlistdata, -1, 0);
- wlistdata->ypos = wlistdata->npos = 0;
- wlistdata->numwin = flayer->l_height - (group ? 4 : 3);
- wlistdata->nested = (order & WLIST_NESTED);
- wlistpage();
-}
-
-static void
-wlistpage()
-{
- struct wlistdata *wlistdata;
- char *str;
- int pos;
- struct win *group;
-
- wlistdata = (struct wlistdata *)flayer->l_data;
- group = wlistdata->group;
-
- LClearAll(flayer, 0);
- if (wlistdata->start >= 0 && wtab[wlistdata->start] == 0)
- wlistdata->start = -2;
-
- WListOrder(wlistdata, 0, -1, group);
- pos = wlistdata->pos;
- if (pos == MAXWIN || !wtab[pos] || !WTAB_GROUP_MATCHES(pos))
- {
- if (wlistdata->order == WLIST_MRU)
- pos = WListNext(wlistdata, -1, wlistdata->npos);
- else
- {
- /* find new position */
- if (pos < MAXWIN)
- while(++pos < MAXWIN)
- if (wtab[pos] && WTAB_GROUP_MATCHES(pos))
- break;
- if (pos == MAXWIN)
- while (--pos >= 0)
- if (wtab[pos] && WTAB_GROUP_MATCHES(pos))
- break;
- if (pos == -1)
- pos = MAXWIN;
- }
- }
- wlistdata->pos = pos;
-
- display = 0;
- str = MakeWinMsgEv(wlisttit, (struct win *)0, '%', flayer->l_width, (struct event *)0, 0);
- if (wlistdata->group)
- {
- LPutWinMsg(flayer, "Group: ", 7, &mchar_blank, 0, 0);
- LPutWinMsg(flayer, wlistdata->group->w_title, strlen(wlistdata->group->w_title), &mchar_blank, 7, 0);
- LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, 1);
- }
- else
- {
- LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, 0);
- }
- WListNormalize();
- WListLines(wlistdata->numwin, -1);
- LaySetCursor();
-}
-
-static void
-WListUpdate(p)
-struct win *p;
-{
- struct wlistdata *wlistdata;
- int i, n, y;
-
- if (p == 0)
- {
- wlistpage();
- return;
- }
- wlistdata = (struct wlistdata *)flayer->l_data;
- n = p->w_number;
- if (wlistdata->order == WLIST_NUM && (n < wlistdata->first || n > wlistdata->last))
- return;
- i = wlistdata->first;
- for (y = 0; y < wlistdata->numwin; y++)
- {
- if (i == n)
- break;
- i = WListNext(wlistdata, i, 1);
- }
- if (y == wlistdata->numwin)
- return;
- WListLine(y, i, wlistdata->pos, 0);
- LaySetCursor();
-}
-
-void
-WListUpdatecv(cv, p)
-struct canvas *cv;
-struct win *p;
-{
- if (cv->c_layer->l_layfn != &WListLf)
- return;
- CV_CALL(cv, WListUpdate(p));
-}
-
-void
-WListLinkChanged()
-{
- struct display *olddisplay = display;
- struct canvas *cv;
- struct wlistdata *wlistdata;
-
- for (display = displays; display; display = display->d_next)
- for (cv = D_cvlist; cv; cv = cv->c_next)
- {
- if (!cv->c_layer || cv->c_layer->l_layfn != &WListLf)
- continue;
- wlistdata = (struct wlistdata *)cv->c_layer->l_data;
- if (wlistdata->order != WLIST_MRU)
- continue;
- CV_CALL(cv, WListUpdate(0));
- }
- display = olddisplay;
-}
-
-int
-InWList()
-{
- if (flayer && flayer->l_layfn == &WListLf)
- return 1;
- return 0;
-}
-
-
-
/*
**
** The bindkey help page
@@ -1513,7 +727,8 @@ static struct LayFuncs BindkeyLf =
DefClearLine,
DefRewrite,
DefResize,
- DefRestore
+ DefRestore,
+ 0
};
@@ -1710,7 +925,8 @@ static struct LayFuncs ZmodemLf =
DefClearLine,
DefRewrite,
ZmodemResize,
- DefRestore
+ DefRestore,
+ 0
};
/*ARGSUSED*/
diff --git a/src/image.h b/src/image.h
index 67d0aec..c105949 100644
--- a/src/image.h
+++ b/src/image.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
@@ -166,3 +166,12 @@ IFDWCHAR((mc)->mbcs = 0; ) \
# define cole2i(c) ((c) ^ 9)
# endif
#endif
+
+enum
+{
+ REND_BELL = 0,
+ REND_MONITOR,
+ REND_SILENCE,
+ NUM_RENDS
+};
+
diff --git a/src/input.c b/src/input.c
index c9624a6..f0f9982 100644
--- a/src/input.c
+++ b/src/input.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -46,10 +46,14 @@ struct inpline
char buf[101]; /* text buffer */
int len; /* length of the editible string */
int pos; /* cursor position in editable string */
+ struct inpline *next, *prev;
};
-static struct inpline inphist; /* XXX: should be a dynamic list */
-
+/* 'inphist' is used to store the current input when scrolling through history.
+ * inpline->prev == history-prev
+ * inpline->next == history-next
+ */
+static struct inpline inphist;
struct inpdata
{
@@ -61,6 +65,7 @@ struct inpdata
void (*inpfinfunc) __P((char *buf, int len, char *priv));
char *priv; /* private data for finfunc */
int privdata; /* private data space */
+ char *search; /* the search string */
};
static struct LayFuncs InpLf =
@@ -71,7 +76,8 @@ static struct LayFuncs InpLf =
DefClearLine,
DefRewrite,
DefResize,
- DefRestore
+ DefRestore,
+ 0
};
/*
@@ -143,10 +149,12 @@ int data;
}
if (InitOverlayPage(sizeof(*inpdata), &InpLf, 1))
return;
+ flayer->l_mode = 1;
inpdata = (struct inpdata *)flayer->l_data;
inpdata->inpmaxlen = len;
inpdata->inpfinfunc = finfunc;
inpdata->inp.pos = inpdata->inp.len = 0;
+ inpdata->inp.prev = inphist.prev;
inpdata->inpmode = mode;
inpdata->privdata = data;
if (!priv)
@@ -154,6 +162,7 @@ int data;
inpdata->priv = priv;
inpdata->inpstringlen = 0;
inpdata->inpstring = NULL;
+ inpdata->search = NULL;
if (istr)
inp_setprompt(istr, (char *)NULL);
}
@@ -204,10 +213,13 @@ int *plen;
char ch;
struct inpdata *inpdata;
struct display *inpdisplay;
+ int prev, next, search = 0;
inpdata = (struct inpdata *)flayer->l_data;
inpdisplay = display;
+#define RESET_SEARCH do { if (inpdata->search) Free(inpdata->search); } while (0)
+
LGotoPos(flayer, inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), INPUTLINE);
if (ppbuf == 0)
{
@@ -265,14 +277,16 @@ int *plen;
LGotoPos(flayer, x, INPUTLINE);
}
}
+ RESET_SEARCH;
}
else if ((ch == '\b' || ch == 0177) && inpdata->inp.pos > 0)
{
erase_chars(inpdata, p-1, p, x, 1);
+ RESET_SEARCH;
}
else if (ch == '\025') /* CTRL-U */
{
- x = inpdata->inpstringlen;
+ x = inpdata->inpstringlen;
if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
{
LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - 1, INPUTLINE, 0, 0);
@@ -282,7 +296,7 @@ int *plen;
}
else if (ch == '\013') /* CTRL-K */
{
- x = inpdata->inpstringlen + inpdata->inp.pos;
+ x = inpdata->inpstringlen + inpdata->inp.pos;
if (inpdata->inp.len > inpdata->inp.pos && !(inpdata->inpmode & INP_NOECHO))
{
LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - inpdata->inp.pos - 1, INPUTLINE, 0, 0);
@@ -298,10 +312,12 @@ int *plen;
while (p > inpdata->inp.buf && *(p - 1) != ' ')
p--;
erase_chars(inpdata, p, oldp, x, 1);
+ RESET_SEARCH;
}
else if (ch == '\004' && inpdata->inp.pos < inpdata->inp.len) /* CTRL-D */
{
erase_chars(inpdata, p, p+1, x, 0);
+ RESET_SEARCH;
}
else if (ch == '\001' || (unsigned char)ch == 0201) /* CTRL-A */
{
@@ -323,22 +339,57 @@ int *plen;
LGotoPos(flayer, ++x, INPUTLINE);
inpdata->inp.pos++;
}
- else if (ch == '\020' || (unsigned char)ch == 0220) /* CTRL-P */
- {
+ else if ((prev = ((ch == '\020' || (unsigned char)ch == 0220) && /* CTRL-P */
+ inpdata->inp.prev)) ||
+ (next = ((ch == '\016' || (unsigned char)ch == 0216) && /* CTRL-N */
+ inpdata->inp.next)) ||
+ (search = ((ch == '\022' || (unsigned char)ch == 0222) && inpdata->inp.prev)))
+ {
struct mchar mc;
+ struct inpline *sel;
+ int pos = -1;
+
mc = mchar_so;
+
+ if (prev)
+ sel = inpdata->inp.prev;
+ else if (next)
+ sel = inpdata->inp.next;
+ else
+ {
+ /* search */
+ inpdata->inp.buf[inpdata->inp.len] = 0; /* Remove the ctrl-r from the end */
+ if (!inpdata->search)
+ inpdata->search = SaveStr(inpdata->inp.buf);
+ for (sel = inpdata->inp.prev; sel; sel = sel->prev)
+ {
+ char *f;
+ if ((f = strstr(sel->buf, inpdata->search)))
+ {
+ pos = f - sel->buf;
+ break;
+ }
+ }
+ if (!sel)
+ continue; /* Did not find a match. Process the next input. */
+ }
+
if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
LClearArea(flayer, inpdata->inpstringlen, INPUTLINE, inpdata->inpstringlen + inpdata->inp.len - 1, INPUTLINE, 0, 0);
- inpdata->inp = inphist; /* structure copy */
+ if ((prev || search) && !inpdata->inp.next)
+ inphist = inpdata->inp;
+ memcpy(&inpdata->inp, sel, sizeof(struct inpline));
+ if (pos != -1)
+ inpdata->inp.pos = pos;
if (inpdata->inp.len > inpdata->inpmaxlen)
inpdata->inp.len = inpdata->inpmaxlen;
if (inpdata->inp.pos > inpdata->inp.len)
inpdata->inp.pos = inpdata->inp.len;
- x = inpdata->inpstringlen;
+ x = inpdata->inpstringlen;
p = inpdata->inp.buf;
-
+
if (!(inpdata->inpmode & INP_NOECHO))
{
while (p < inpdata->inp.buf+inpdata->inp.len)
@@ -347,7 +398,7 @@ int *plen;
LPutChar(flayer, &mc, x++, INPUTLINE);
}
}
- x = inpdata->inpstringlen + inpdata->inp.pos;
+ x = inpdata->inpstringlen + inpdata->inp.pos;
LGotoPos(flayer, x, INPUTLINE);
}
@@ -359,9 +410,36 @@ int *plen;
inpdata->inp.buf[inpdata->inp.len] = 0;
if (inpdata->inp.len && !(inpdata->inpmode & (INP_NOECHO | INP_RAW)))
- inphist = inpdata->inp; /* structure copy */
-
- flayer->l_data = 0; /* so inpdata does not get freed */
+ {
+ struct inpline *store;
+
+ /* Look for a duplicate first */
+ for (store = inphist.prev; store; store = store->prev)
+ {
+ if (strcmp(store->buf, inpdata->inp.buf) == 0)
+ {
+ if (store->next)
+ store->next->prev = store->prev;
+ if (store->prev)
+ store->prev->next = store->next;
+ store->pos = inpdata->inp.pos;
+ break;
+ }
+ }
+
+ if (!store)
+ {
+ store = malloc(sizeof(struct inpline));
+ memcpy(store, &inpdata->inp, sizeof(struct inpline));
+ }
+ store->next = &inphist;
+ store->prev = inphist.prev;
+ if (inphist.prev)
+ inphist.prev->next = store;
+ inphist.prev = store;
+ }
+
+ flayer->l_data = 0; /* so inpdata does not get freed */
InpAbort(); /* redisplays... */
*ppbuf = pbuf;
*plen = len;
@@ -370,9 +448,17 @@ int *plen;
(*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
else
(*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv);
- free((char *)inpdata);
+ if (inpdata->search)
+ free(inpdata->search);
+ free(inpdata);
return;
}
+ else
+ {
+ /* The user was searching, and then pressed some non-control input. So reset
+ * the search string. */
+ RESET_SEARCH;
+ }
}
if (!(inpdata->inpmode & INP_RAW))
{
@@ -396,7 +482,7 @@ int y, xs, xe, isblank;
{
int q, r, s, l, v;
struct inpdata *inpdata;
-
+
inpdata = (struct inpdata *)flayer->l_data;
if (y != INPUTLINE)
{
@@ -440,11 +526,3 @@ int y, xs, xe, isblank;
}
}
-int
-InInput()
-{
- if (flayer && flayer->l_layfn == &InpLf)
- return 1;
- return 0;
-}
-
diff --git a/src/layer.c b/src/layer.c
index a2fd74a..b7cea6a 100644
--- a/src/layer.c
+++ b/src/layer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -86,6 +86,12 @@ int off;
# define RECODE_MLINE(ml) (ml)
#endif
+#define FOR_EACH_UNPAUSED_CANVAS(l, fn) for (cv = (l)->l_cvlist; cv; cv = cv->c_lnext) \
+ { \
+ if ((l)->l_pause.d && cv->c_slorient) \
+ continue; \
+ fn \
+ }
void
LGotoPos(l, x, y)
@@ -96,11 +102,14 @@ int x, y;
struct viewport *vp;
int x2, y2;
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, x, x, y, y);
+
#ifdef HAVE_BRAILLE
if (bd.bd_refreshing)
return;
#endif
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ FOR_EACH_UNPAUSED_CANVAS(l,
{
display = cv->c_display;
if (D_blocked)
@@ -128,6 +137,7 @@ int x, y;
break;
}
}
+ );
}
void
@@ -143,7 +153,9 @@ struct mline *ol;
if (n == 0)
return;
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, xs, xe, y, y);
+ FOR_EACH_UNPAUSED_CANVAS(l,
for (vp = cv->c_vplist; vp; vp = vp->v_next)
{
y2 = y + vp->v_yoff;
@@ -180,6 +192,7 @@ struct mline *ol;
if (xs2 <= xe2)
RefreshArea(xs2, y2, xe2, y2, 1);
}
+ );
}
void
@@ -194,7 +207,9 @@ int bce;
int ys2, ye2, xs2, xe2;
if (n == 0)
return;
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, 0, l->l_width - 1, ys, ye);
+ FOR_EACH_UNPAUSED_CANVAS(l,
for (vp = cv->c_vplist; vp; vp = vp->v_next)
{
xs2 = vp->v_xoff;
@@ -242,6 +257,7 @@ int bce;
if (ys2 <= ye2)
RefreshArea(xs2, ys2, xe2, ye2, 1);
}
+ );
}
void
@@ -257,7 +273,9 @@ struct mline *ol;
struct mchar *c2, cc;
struct mline *rol;
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, x, l->l_width - 1, y, y);
+ FOR_EACH_UNPAUSED_CANVAS(l,
for (vp = cv->c_vplist; vp; vp = vp->v_next)
{
y2 = y + vp->v_yoff;
@@ -296,6 +314,7 @@ struct mline *ol;
if (f)
RefreshArea(xs2, y2, xs2, y2, 1);
}
+ );
}
void
@@ -314,7 +333,11 @@ int x, y;
return;
}
#endif
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, x, x, y, y);
+
+ FOR_EACH_UNPAUSED_CANVAS(l,
{
display = cv->c_display;
if (D_blocked)
@@ -331,6 +354,7 @@ int x, y;
break;
}
}
+ );
}
void
@@ -355,7 +379,10 @@ int x, y;
return;
}
#endif
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, x, x + n - 1, y, y);
+
+ FOR_EACH_UNPAUSED_CANVAS(l,
for (vp = cv->c_vplist; vp; vp = vp->v_next)
{
y2 = y + vp->v_yoff;
@@ -391,6 +418,7 @@ int x, y;
while (xs2++ <= xe2)
PUTCHARLP(*s2++);
}
+ );
}
void
@@ -415,10 +443,12 @@ int x, y;
return;
}
#endif
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, x, x + n - 1, y, y);
len = strlen(s);
if (len > n)
len = n;
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ FOR_EACH_UNPAUSED_CANVAS(l,
for (vp = cv->c_vplist; vp; vp = vp->v_next)
{
y2 = y + vp->v_yoff;
@@ -450,6 +480,7 @@ int x, y;
while (xs2++ <= xe2)
PUTCHARLP(' ');
}
+ );
}
void
@@ -467,7 +498,9 @@ struct mline *ol;
xs = l->l_width - 1;
if (xe >= l->l_width)
xe = l->l_width - 1;
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, xs, xe, y, y);
+ FOR_EACH_UNPAUSED_CANVAS(l,
for (vp = cv->c_vplist; vp; vp = vp->v_next)
{
xs2 = xs + vp->v_xoff;
@@ -486,6 +519,7 @@ struct mline *ol;
continue;
ClearLine(ol ? mloff(RECODE_MLINE(ol), -vp->v_xoff) : (struct mline *)0, y2, xs2, xe2, bce);
}
+ );
}
void
@@ -511,7 +545,9 @@ int uself;
xs = l->l_width - 1;
if (xe >= l->l_width)
xe = l->l_width - 1;
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, xs, xe, ys, ye);
+ FOR_EACH_UNPAUSED_CANVAS(l,
{
display = cv->c_display;
if (D_blocked)
@@ -561,6 +597,7 @@ int uself;
#endif
}
}
+ );
}
void
@@ -580,7 +617,9 @@ int isblank;
return;
}
#endif
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ if (l->l_pause.d)
+ LayPauseUpdateRegion(l, xs, xe, y, y);
+ FOR_EACH_UNPAUSED_CANVAS(l,
{
display = cv->c_display;
if (D_blocked)
@@ -604,6 +643,7 @@ int isblank;
DisplayLine(isblank ? &mline_blank : &mline_null, mloff(RECODE_MLINE(ml), -vp->v_xoff), y2, xs2, xe2);
}
}
+ );
}
void
@@ -656,6 +696,10 @@ int ins;
int yy, y2, yy2, top2, bot2;
int bce;
+ if (l->l_pause.d)
+ /* XXX: 'y'? */
+ LayPauseUpdateRegion(l, 0, l->l_width - 1, top, bot);
+
#ifdef COLOR
bce = rend_getbg(c);
#else
@@ -668,7 +712,7 @@ int ins;
/* cursor after wrapping */
yy = y == l->l_height - 1 ? y : y + 1;
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ FOR_EACH_UNPAUSED_CANVAS(l,
{
y2 = 0; /* gcc -Wall */
display = cv->c_display;
@@ -708,12 +752,13 @@ int ins;
WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins);
}
}
+ );
}
else
{
/* hard case: scroll up*/
- for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ FOR_EACH_UNPAUSED_CANVAS(l,
{
display = cv->c_display;
if (D_blocked)
@@ -761,6 +806,7 @@ int ins;
WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins);
}
}
+ );
}
}
@@ -879,11 +925,11 @@ int isblank;
void
/*VARARGS2*/
#if defined(USEVARARGS) && defined(__STDC__)
-LMsg(int err, char *fmt, VA_DOTS)
+LMsg(int err, const char *fmt, VA_DOTS)
#else
LMsg(err, fmt, VA_DOTS)
int err;
-char *fmt;
+const char *fmt;
VA_DECL
#endif
{
@@ -1060,7 +1106,11 @@ ExitOverlayPage()
debug1("Exiting layer %#x\n", (unsigned int)flayer);
oldlay = flayer;
if (oldlay->l_data)
- free(oldlay->l_data);
+ {
+ if (oldlay->l_layfn->lf_LayFree)
+ LayFree(oldlay->l_data);
+ free(oldlay->l_data);
+ }
p = Layer2Window(flayer);
@@ -1111,7 +1161,175 @@ ExitOverlayPage()
ocv->c_lnext = cv;
}
oldlay->l_cvlist = 0;
+ LayerCleanupMemory(oldlay);
free((char *)oldlay);
LayRestore();
LaySetCursor();
}
+
+int
+LayProcessMouse(struct layer *l, unsigned char ch)
+{
+ /* XXX: Make sure the layer accepts mouse events */
+ int len;
+
+ if (l->l_mouseevent.len >= sizeof(l->l_mouseevent.buffer))
+ return -1;
+
+ len = l->l_mouseevent.len++;
+ l->l_mouseevent.buffer[len] = (len > 0 ? ch - 33 : ch);
+ return (l->l_mouseevent.len == sizeof(l->l_mouseevent.buffer));
+}
+
+int
+LayProcessMouseSwitch(struct layer *l, int s)
+{
+ if ((l->l_mouseevent.start = s))
+ {
+ l->l_mouseevent.len = 0;
+ }
+}
+
+void LayPause(layer, pause)
+struct layer *layer;
+int pause;
+{
+ struct canvas *cv;
+ struct display *olddisplay = display;
+ int line;
+ struct win *win;
+
+ pause = !!pause;
+
+ if (layer->l_pause.d == pause)
+ return;
+
+ if ((layer->l_pause.d = pause))
+ {
+ /* Start pausing */
+ layer->l_pause.top = layer->l_pause.bottom = -1;
+ return;
+ }
+
+ /* Unpause. So refresh the regions in the displays! */
+ if (layer->l_pause.top == -1 &&
+ layer->l_pause.bottom == -1)
+ return;
+
+ if (layer->l_layfn == &WinLf) /* Currently, this will always be the case! */
+ win = layer->l_data;
+ else
+ win = NULL;
+
+ for (cv = layer->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ struct viewport *vp;
+
+ if (!cv->c_slorient)
+ continue; /* Wasn't split, so already updated. */
+
+ display = cv->c_display;
+
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ for (line = layer->l_pause.top; line <= layer->l_pause.bottom; line++)
+ {
+ int xs, xe;
+
+ if (line + vp->v_yoff >= vp->v_ys && line + vp->v_yoff <= vp->v_ye &&
+ ((xs = layer->l_pause.left[line]) >= 0) &&
+ ((xe = layer->l_pause.right[line]) >= 0))
+ {
+ xs += vp->v_xoff;
+ xe += vp->v_xoff;
+
+ if (xs < vp->v_xs) xs = vp->v_xs;
+ if (xe > vp->v_xe) xe = vp->v_xe;
+
+#if defined(DW_CHARS) && defined(UTF8)
+ if (layer->l_encoding == UTF8 && xe < vp->v_xe && win)
+ {
+ struct mline *ml = win->w_mlines + line;
+ if (dw_left(ml, xe, UTF8))
+ xe++;
+ }
+#endif
+
+ if (xs <= xe)
+ RefreshLine(line + vp->v_yoff, xs, xe, 0);
+ }
+ }
+ }
+
+ if (cv == D_forecv)
+ {
+ int cx = layer->l_x + cv->c_xoff;
+ int cy = layer->l_y + cv->c_yoff;
+
+ if (cx < cv->c_xs) cx = cv->c_xs;
+ if (cy < cv->c_ys) cy = cv->c_ys;
+ if (cx > cv->c_xe) cx = cv->c_xe;
+ if (cy > cv->c_ye) cy = cv->c_ye;
+
+ GotoPos(cx, cy);
+ }
+ }
+
+ for (line = layer->l_pause.top; line <= layer->l_pause.bottom; line++)
+ layer->l_pause.left[line] = layer->l_pause.right[line] = -1;
+ olddisplay = display;
+}
+
+void
+LayPauseUpdateRegion(layer, xs, xe, ys, ye)
+struct layer *layer;
+int xs, xe;
+int ys, ye;
+{
+ if (!layer->l_pause.d)
+ return;
+ if (ys < 0)
+ ys = 0;
+ if (ye >= layer->l_height)
+ ye = layer->l_height - 1;
+ if (xe >= layer->l_width)
+ xe = layer->l_width - 1;
+
+ if (layer->l_pause.top == -1 || layer->l_pause.top > ys)
+ layer->l_pause.top = ys;
+ if (layer->l_pause.bottom < ye)
+ {
+ layer->l_pause.bottom = ye;
+ if (layer->l_pause.lines <= ye)
+ {
+ int o = layer->l_pause.lines;
+ layer->l_pause.lines = ye + 32;
+ layer->l_pause.left = realloc(layer->l_pause.left, sizeof(int) * layer->l_pause.lines);
+ layer->l_pause.right = realloc(layer->l_pause.right, sizeof(int) * layer->l_pause.lines);
+ while (o < layer->l_pause.lines)
+ {
+ layer->l_pause.left[o] = layer->l_pause.right[o] = -1;
+ o++;
+ }
+ }
+ }
+
+ while (ys <= ye)
+ {
+ if (layer->l_pause.left[ys] == -1 || layer->l_pause.left[ys] > xs)
+ layer->l_pause.left[ys] = xs;
+ if (layer->l_pause.right[ys] < xe)
+ layer->l_pause.right[ys] = xe;
+ ys++;
+ }
+}
+
+void
+LayerCleanupMemory(layer)
+struct layer *layer;
+{
+ if (layer->l_pause.left)
+ free(layer->l_pause.left);
+ if (layer->l_pause.right)
+ free(layer->l_pause.right);
+}
diff --git a/src/layer.h b/src/layer.h
index d45a5c3..8c42d2b 100644
--- a/src/layer.h
+++ b/src/layer.h
@@ -1,4 +1,9 @@
-/* Copyright (c) 1995-2002
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Copyright (c) 1987 Oliver Laumann
@@ -19,9 +24,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
+#ifndef SCREEN_LAYER_H
+#define SCREEN_LAYER_H
+
/*
* This is the overlay structure. It is used to create a seperate
* layer over the current windows.
@@ -38,6 +46,8 @@ struct LayFuncs
int (*lf_LayRewrite) __P((int, int, int, struct mchar *, int));
int (*lf_LayResize) __P((int, int));
void (*lf_LayRestore) __P((void));
+ void (*lf_LayFree) __P((void *)); /* Should only free any data kept in
+ flayer->l_data (but not flayer->l_data itself). */
};
struct layer
@@ -49,11 +59,30 @@ struct layer
int l_y;
int l_encoding;
struct LayFuncs *l_layfn;
- char *l_data;
+ void *l_data;
struct layer *l_next; /* layer stack, should be in data? */
struct layer *l_bottom; /* bottom element of layer stack */
int l_blocking;
+ int l_mode; /* non-zero == edit mode */
+
+ struct {
+ unsigned char buffer[3]; /* [0]: the button
+ [1]: x
+ [2]: y
+ */
+ int len;
+ int start;
+ } l_mouseevent;
+
+ struct {
+ int d : 1; /* Is the output for the layer blocked? */
+
+ /* After unpausing, what region should we refresh? */
+ int *left, *right;
+ int top, bottom;
+ int lines;
+ } l_pause;
};
#define LayProcess (*flayer->l_layfn->lf_LayProcess)
@@ -63,6 +92,7 @@ struct layer
#define LayRewrite (*flayer->l_layfn->lf_LayRewrite)
#define LayResize (*flayer->l_layfn->lf_LayResize)
#define LayRestore (*flayer->l_layfn->lf_LayRestore)
+#define LayFree (*flayer->l_layfn->lf_LayFree)
#define LaySetCursor() LGotoPos(flayer, flayer->l_x, flayer->l_y)
#define LayCanResize(l) (l->l_layfn->LayResize != DefResize)
@@ -103,3 +133,31 @@ struct layer
display = olddisplay; \
} while(0)
+#endif /* SCREEN_LAYER_H */
+
+/**
+ * (Un)Pauses a layer.
+ *
+ * @param layer The layer that should be (un)paused.
+ * @param pause Should we pause the layer?
+ */
+void LayPause __P((struct layer *layer, int pause));
+
+/**
+ * Update the region to refresh after a layer is unpaused.
+ *
+ * @param layer The layer.
+ * @param xs The left-end of the region.
+ * @param xe The right-end of the region.
+ * @param ys The top-end of the region.
+ * @param ye The bottom-end of the region.
+ */
+void LayPauseUpdateRegion __P((struct layer *layer, int xs, int xe, int ys, int ye));
+
+/**
+ * Free any internal memory for the layer.
+ *
+ * @param layer The layer.
+ */
+void LayerCleanupMemory __P((struct layer *layer));
+
diff --git a/src/layout.c b/src/layout.c
new file mode 100644
index 0000000..6100b5d
--- /dev/null
+++ b/src/layout.c
@@ -0,0 +1,367 @@
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+#include "config.h"
+#include "screen.h"
+#include "extern.h"
+#include "layout.h"
+
+extern struct display *display;
+extern int captionalways;
+
+struct layout *layouts;
+struct layout *laytab[MAXLAY];
+struct layout *layout_last, layout_last_marker;
+struct layout *layout_attach = &layout_last_marker;
+
+void
+FreeLayoutCv(cv)
+struct canvas *cv;
+{
+ struct canvas *cnext, *c = cv;
+ for (; cv; cv = cnext)
+ {
+ if (cv->c_slperp)
+ {
+ FreeLayoutCv(cv->c_slperp);
+ free(cv->c_slperp);
+ cv->c_slperp = 0;
+ }
+ cnext = cv->c_slnext;
+ cv->c_slnext = 0;
+ if (cv != c)
+ free(cv);
+ }
+}
+
+struct layout *
+CreateLayout(title, startat)
+char *title;
+int startat;
+{
+ struct layout *lay;
+ int i;
+
+ if (startat >= MAXLAY || startat < 0)
+ startat = 0;
+ for (i = startat; ;)
+ {
+ if (!laytab[i])
+ break;
+ if (++i == MAXLAY)
+ i = 0;
+ if (i == startat)
+ {
+ Msg(0, "No more layouts\n");
+ return 0;
+ }
+ }
+ lay = (struct layout *)calloc(1, sizeof(*lay));
+ lay->lay_title = SaveStr(title);
+ lay->lay_autosave = 1;
+ lay->lay_number = i;
+ laytab[i] = lay;
+ lay->lay_next = layouts;
+ layouts = lay;
+ return lay;
+}
+
+void
+SaveLayout(name, cv)
+char *name;
+struct canvas *cv;
+{
+ struct layout *lay;
+ struct canvas *fcv;
+ for (lay = layouts; lay; lay = lay->lay_next)
+ if (!strcmp(lay->lay_title, name))
+ break;
+ if (lay)
+ FreeLayoutCv(&lay->lay_canvas);
+ else
+ lay = CreateLayout(name, 0);
+ if (!lay)
+ return;
+ fcv = D_forecv;
+ DupLayoutCv(cv, &lay->lay_canvas, 1);
+ lay->lay_forecv = D_forecv;
+ D_forecv = fcv;
+ D_layout = lay;
+}
+
+void
+AutosaveLayout(lay)
+struct layout *lay;
+{
+ struct canvas *fcv;
+ if (!lay || !lay->lay_autosave)
+ return;
+ FreeLayoutCv(&lay->lay_canvas);
+ fcv = D_forecv;
+ DupLayoutCv(&D_canvas, &lay->lay_canvas, 1);
+ lay->lay_forecv = D_forecv;
+ D_forecv = fcv;
+}
+
+struct layout *
+FindLayout(name)
+char *name;
+{
+ struct layout *lay;
+ char *s;
+ int i;
+ for (i = 0, s = name; *s >= '0' && *s <= '9'; s++)
+ i = i * 10 + (*s - '0');
+ if (!*s && s != name && i >= 0 && i < MAXLAY)
+ return laytab[i];
+ for (lay = layouts; lay; lay = lay->lay_next)
+ if (!strcmp(lay->lay_title, name))
+ break;
+ return lay;
+}
+
+void
+LoadLayout(lay, cv)
+struct layout *lay;
+struct canvas *cv;
+{
+ AutosaveLayout(D_layout);
+ if (!lay)
+ {
+ while (D_canvas.c_slperp)
+ FreeCanvas(D_canvas.c_slperp);
+ MakeDefaultCanvas();
+ SetCanvasWindow(D_forecv, 0);
+ D_layout = 0;
+ return;
+ }
+ while (D_canvas.c_slperp)
+ FreeCanvas(D_canvas.c_slperp);
+ D_cvlist = 0;
+ D_forecv = lay->lay_forecv;
+ DupLayoutCv(&lay->lay_canvas, &D_canvas, 0);
+ D_canvas.c_ye = D_height - 1 - ((D_canvas.c_slperp && D_canvas.c_slperp->c_slnext) || captionalways) - (D_has_hstatus == HSTATUS_LASTLINE);
+ ResizeCanvas(&D_canvas);
+ RecreateCanvasChain();
+ RethinkDisplayViewports();
+ PutWindowCv(&D_canvas);
+ ResizeLayersToCanvases();
+ D_layout = lay;
+}
+
+void
+NewLayout(title, startat)
+char *title;
+int startat;
+{
+ struct layout *lay;
+ struct canvas *fcv;
+
+ lay = CreateLayout(title, startat);
+ if (!lay)
+ return;
+ LoadLayout(0, &D_canvas);
+ fcv = D_forecv;
+ DupLayoutCv(&D_canvas, &lay->lay_canvas, 1);
+ lay->lay_forecv = D_forecv;
+ D_forecv = fcv;
+ D_layout = lay;
+ lay->lay_autosave = 1;
+}
+
+
+static char *
+AddLayoutsInfo(buf, len, where)
+char *buf;
+int len;
+int where;
+{
+ char *s, *ss, *t;
+ struct layout *p, **pp;
+ int l;
+
+ s = ss = buf;
+ for (pp = laytab; pp < laytab + MAXLAY; pp++)
+ {
+ if (pp - laytab == where && ss == buf)
+ ss = s;
+ if ((p = *pp) == 0)
+ continue;
+ t = p->lay_title;
+ l = strlen(t);
+ if (l > 20)
+ l = 20;
+ if (s - buf + l > len - 24)
+ break;
+ if (s > buf)
+ {
+ *s++ = ' ';
+ *s++ = ' ';
+ }
+ sprintf(s, "%d", p->lay_number);
+ if (p->lay_number == where)
+ ss = s;
+ s += strlen(s);
+ if (display && p == D_layout)
+ *s++ = '*';
+ *s++ = ' ';
+ strncpy(s, t, l);
+ s += l;
+ }
+ *s = 0;
+ return ss;
+}
+
+void
+ShowLayouts(where)
+int where;
+{
+ char buf[1024];
+ char *s, *ss;
+
+ if (!display)
+ return;
+ if (!layouts)
+ {
+ Msg(0, "No layouts defined\n");
+ return;
+ }
+ if (where == -1 && D_layout)
+ where = D_layout->lay_number;
+ ss = AddLayoutsInfo(buf, sizeof(buf), where);
+ s = buf + strlen(buf);
+ if (ss - buf > D_width / 2)
+ {
+ ss -= D_width / 2;
+ if (s - ss < D_width)
+ {
+ ss = s - D_width;
+ if (ss < buf)
+ ss = buf;
+ }
+ }
+ else
+ ss = buf;
+ Msg(0, "%s", ss);
+}
+
+void
+RemoveLayout(lay)
+struct layout *lay;
+{
+ struct layout **layp = &layouts;
+
+ for (; *layp; layp = &(*layp)->lay_next)
+ {
+ if (*layp == lay)
+ {
+ *layp = lay->lay_next;
+ break;
+ }
+ }
+ laytab[lay->lay_number] = (struct layout *)0;
+
+ if (display && D_layout == lay)
+ D_layout = (struct layout *)0;
+
+ FreeLayoutCv(&lay->lay_canvas);
+
+ if (lay->lay_title)
+ free(lay->lay_title);
+ free(lay);
+
+ if (layouts)
+ LoadLayout((display && D_layout) ? D_layout : *layp ? *layp : layouts,
+ display ? &D_canvas : (struct canvas *)0);
+ Activate(0);
+}
+
+void
+UpdateLayoutCanvas(cv, wi)
+struct canvas *cv;
+struct win *wi;
+{
+ for (; cv; cv = cv->c_slnext)
+ {
+ if (cv->c_layer && Layer2Window(cv->c_layer) == wi)
+ {
+ /* A simplistic version of SetCanvasWindow(cv, 0) */
+ struct layer *l = cv->c_layer;
+ cv->c_layer = 0;
+ if (l->l_cvlist == 0 && (wi == 0 || l != wi->w_savelayer))
+ KillLayerChain(l);
+ l = &cv->c_blank;
+ l->l_data = 0;
+ if (l->l_cvlist != cv)
+ {
+ cv->c_lnext = l->l_cvlist;
+ l->l_cvlist = cv;
+ }
+ cv->c_layer = l;
+ /* Do not end here. Multiple canvases can have the same window */
+ }
+
+ if (cv->c_slperp)
+ UpdateLayoutCanvas(cv->c_slperp, wi);
+ }
+}
+
+
+static void
+dump_canvas(cv, file)
+struct canvas *cv;
+FILE *file;
+{
+ struct canvas *c;
+ for (c = cv->c_slperp; c && c->c_slnext; c = c->c_slnext)
+ {
+ fprintf(file, "split%s\n", c->c_slorient == SLICE_HORI ? " -v" : "");
+ }
+
+ for (c = cv->c_slperp; c; c = c->c_slnext)
+ {
+ if (c->c_slperp)
+ dump_canvas(c, file);
+ else
+ fprintf(file, "focus\n");
+ }
+}
+
+int
+LayoutDumpCanvas(cv, filename)
+struct canvas *cv;
+char *filename;
+{
+ FILE *file = secfopen(filename, "a");
+ if (!file)
+ return 0;
+ dump_canvas(cv, file);
+ fclose(file);
+ return 1;
+}
+
diff --git a/src/layout.h b/src/layout.h
new file mode 100644
index 0000000..065edb7
--- /dev/null
+++ b/src/layout.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ * $Id$ GNU
+ */
+
+#ifndef SCREEN_LAYOUT_H
+#define SCREEN_LAYOUT_H
+
+#include "canvas.h"
+
+#define MAXLAY 10
+
+struct layout
+{
+ struct layout *lay_next;
+ char *lay_title;
+ int lay_number;
+ struct canvas lay_canvas;
+ struct canvas *lay_forecv;
+ struct canvas *lay_cvlist;
+ int lay_autosave;
+};
+
+extern void AutosaveLayout __P((struct layout *));
+extern void LoadLayout __P((struct layout *, struct canvas *));
+extern void NewLayout __P((char *, int));
+extern void SaveLayout __P((char *, struct canvas *));
+extern void ShowLayouts __P((int));
+extern struct layout *FindLayout __P((char *));
+extern void UpdateLayoutCanvas __P((struct canvas *, struct win *));
+
+#endif /* SCREEN_LAYOUT_H */
+
diff --git a/src/list_display.c b/src/list_display.c
new file mode 100644
index 0000000..4e740c1
--- /dev/null
+++ b/src/list_display.c
@@ -0,0 +1,243 @@
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+/* Deals with the list of displays */
+
+#include "config.h"
+
+#include "screen.h"
+#include "list_generic.h"
+
+#ifdef MULTI
+
+extern struct layer *flayer;
+extern struct display *display, *displays;
+extern struct mchar mchar_blank, mchar_so;
+
+static char ListID[] = "display";
+
+/*
+ * layout of the displays page is as follows:
+
+xterm 80x42 jnweiger@/dev/ttyp4 0(m11) &rWx
+facit 80x24 nb mlschroe@/dev/ttyhf 11(tcsh) rwx
+xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x
+
+ | | | | | | | | ¦___ window permissions
+ | | | | | | | | (R. is locked r-only,
+ | | | | | | | | W has wlock)
+ | | | | | | | |___ Window is shared
+ | | | | | | |___ Name/Title of window
+ | | | | | |___ Number of window
+ | | | | |___ Name of the display (the attached device)
+ | | | |___ Username who is logged in at the display
+ | | |___ Display is in nonblocking mode. Shows 'NB' if obuf is full.
+ | |___ Displays geometry as width x height.
+ |___ the terminal type known by screen for this display.
+
+ */
+
+static int
+gl_Display_header(struct ListData *ldata)
+{
+ leftline("term-type size user interface window Perms", 0, 0);
+ leftline("---------- ------- ---------- ----------------- ---------- -----", 1, 0);
+ return 2;
+}
+
+static int
+gl_Display_footer(struct ListData *ldata)
+{
+ centerline("[Press Space to refresh; Return to end.]", flayer->l_height - 1);
+}
+
+static int
+gl_Display_row(struct ListData *ldata, struct ListRow *lrow)
+{
+ struct display *d = lrow->data;
+ char tbuf[80];
+ static char *blockstates[5] = {"nb", "NB", "Z<", "Z>", "BL"};
+ struct win *w = d->d_fore;
+ struct mchar m_current = mchar_blank;
+ m_current.attr = A_BD;
+
+ sprintf(tbuf, " %-10.10s%4dx%-4d%10.10s@%-16.16s%s",
+ d->d_termname, d->d_width, d->d_height, d->d_user->u_name,
+ d->d_usertty,
+ (d->d_blocked || d->d_nonblock >= 0) && d->d_blocked <= 4 ? blockstates[d->d_blocked] : " ");
+
+ if (w)
+ {
+ int l = 10 - strlen(w->w_title);
+ if (l < 0)
+ l = 0;
+ sprintf(tbuf + strlen(tbuf), "%3d(%.10s)%*s%c%c%c%c",
+ w->w_number, w->w_title, l, "",
+ /* w->w_dlist->next */ 0 ? '&' : ' ',
+ /*
+ * The rwx triple:
+ * -,r,R no read, read, read only due to foreign wlock
+ * -,.,w,W no write, write suppressed by foreign wlock,
+ * write, own wlock
+ * -,x no execute, execute
+ */
+#ifdef MULTIUSER
+ (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
+ ((w->w_wlock == WLOCK_OFF || d->d_user == w->w_wlockuser) ?
+ 'r' : 'R')),
+ (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
+ ((w->w_wlock == WLOCK_OFF) ? 'w' :
+ ((d->d_user == w->w_wlockuser) ? 'W' : 'v'))),
+ (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : 'x')
+#else
+ 'r', 'w', 'x'
+#endif
+ );
+ }
+ leftline(tbuf, lrow->y, lrow == ldata->selected ? &mchar_so : d == display ? &m_current : 0);
+
+ return 1;
+}
+
+static void
+gl_Display_rebuild(struct ListData *ldata)
+{
+ /* recreate the rows */
+ struct display *d;
+ struct ListRow *row = NULL;
+ for (d = displays; d; d = d->d_next)
+ {
+ row = glist_add_row(ldata, d, row);
+ if (d == display)
+ ldata->selected = row;
+ }
+
+ glist_display_all(ldata);
+}
+
+static int
+gl_Display_input(struct ListData *ldata, char **inp, int *len)
+{
+ struct display *cd = display;
+ unsigned char ch;
+
+ if (!ldata->selected)
+ return 0;
+
+ ch = (unsigned char) **inp;
+ ++*inp;
+ --*len;
+
+ switch (ch)
+ {
+ case ' ': /* Space to refresh */
+ glist_remove_rows(ldata);
+ gl_Display_rebuild(ldata);
+ break;
+
+ case '\r':
+ case '\n':
+ glist_abort();
+ *len = 0;
+ break;
+
+#ifdef REMOTE_DETACH
+ case 'd': /* Detach */
+ case 'D': /* Power detach */
+ display = ldata->selected->data;
+ if (display == cd) /* We do not allow detaching the current display */
+ break;
+ Detach(
+#ifdef POW_DETACH
+ ch == 'D' ? D_REMOTE_POWER : D_REMOTE
+#else
+ D_REMOTE
+#endif
+ );
+ display = cd;
+ glist_remove_rows(ldata);
+ gl_Display_rebuild(ldata);
+ break;
+#endif
+
+ default:
+ /* We didn't actually process the input. */
+ --*inp;
+ ++*len;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+gl_Display_freerow(struct ListData *ldata, struct ListRow *row)
+{
+ /* There was no allocation when row->data was set. So nothing to do here. */
+ return 0;
+}
+
+static int
+gl_Display_free(struct ListData *ldata)
+{
+ /* There was no allocation in ldata->data. So nothing to do here. */
+ return 0;
+}
+
+static struct GenericList gl_Display =
+{
+ gl_Display_header,
+ gl_Display_footer,
+ gl_Display_row,
+ gl_Display_input,
+ gl_Display_freerow,
+ gl_Display_free,
+ NULL /* We do not allow searching in the display list, at the moment */
+};
+
+void
+display_displays()
+{
+ struct ListData *ldata;
+ if (flayer->l_width < 10 || flayer->l_height < 5)
+ {
+ LMsg(0, "Window size too small for displays page");
+ return;
+ }
+
+ ldata = glist_display(&gl_Display, ListID);
+ if (!ldata)
+ return;
+
+ gl_Display_rebuild(ldata);
+}
+
+#endif /* MULTI */
+
diff --git a/src/list_generic.c b/src/list_generic.c
new file mode 100644
index 0000000..e32acf7
--- /dev/null
+++ b/src/list_generic.c
@@ -0,0 +1,486 @@
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+#include "config.h"
+#include "screen.h"
+#include "list_generic.h"
+#include "layer.h"
+#include "extern.h"
+
+/* Deals with a generic list display */
+
+extern struct layer *flayer;
+
+static void ListProcess __P((char **, int *));
+static void ListAbort __P((void));
+static void ListRedisplayLine __P((int, int, int, int));
+static void ListClearLine __P((int, int, int, int));
+static int ListRewrite __P((int, int, int, struct mchar *, int));
+static int ListResize __P((int, int));
+static void ListRestore __P((void));
+static void ListFree __P((void *));
+
+struct LayFuncs ListLf =
+{
+ ListProcess,
+ ListAbort,
+ ListRedisplayLine,
+ ListClearLine,
+ ListRewrite,
+ ListResize,
+ ListRestore,
+ ListFree
+};
+
+/** Returns non-zero on success. */
+struct ListData *
+glist_display(struct GenericList *list, const char *name)
+{
+ struct ListData *ldata;
+
+ if (InitOverlayPage(sizeof(struct ListData), &ListLf, 0))
+ return NULL;
+ ldata = flayer->l_data;
+
+ ldata->name = name; /* We do not SaveStr, since the strings should be all static literals */
+ ldata->list_fn = list;
+
+ flayer->l_mode = 1;
+ flayer->l_x = 0;
+ flayer->l_y = flayer->l_height - 1;
+
+ return ldata;
+}
+
+static void
+glist_decide_top(struct ListData *ldata)
+{
+ int count = flayer->l_height - 5; /* 2 for header, 1 for footer */
+ struct ListRow *top = ldata->selected;
+ for (; count && top != ldata->root; top = top->prev, count--)
+ ;
+ ldata->top = top;
+}
+
+static struct ListRow *
+glist_search_dir(struct ListData *ldata, struct ListRow *start, int dir)
+{
+ struct ListRow *row = (dir == 1) ? start->next : start->prev;
+ for (; row; row = (dir == 1) ? row->next : row->prev)
+ if (ldata->list_fn->gl_matchrow(ldata, row, ldata->search))
+ return row;
+
+ if (dir == 1)
+ row = ldata->root;
+ else
+ {
+ /* First, go to the end */
+ if (!start->next)
+ row = start;
+ else
+ for (row = start->next; row->next; row = row->next)
+ ;
+ }
+
+ for (; row != start; row = (dir == 1) ? row->next : row->prev)
+ if (ldata->list_fn->gl_matchrow(ldata, row, ldata->search))
+ break;
+
+ return row;
+}
+
+static void
+glist_search(char *buf, int len, char *data)
+{
+ struct ListData *ldata = (struct ListData *)data;
+ struct ListRow *row;
+
+ if (ldata->search)
+ Free(ldata->search);
+ if (len > 0)
+ ldata->search = SaveStr(buf);
+ else
+ return;
+
+ for (row = ldata->selected; row; row = row->next)
+ if (ldata->list_fn->gl_matchrow(ldata, row, ldata->search))
+ break;
+
+ if (!row)
+ for (row = ldata->root; row != ldata->selected; row = row->next)
+ if (ldata->list_fn->gl_matchrow(ldata, row, ldata->search))
+ break;
+
+ if (row == ldata->selected)
+ return;
+
+ ldata->selected = row;
+ if (ldata->selected->y == -1)
+ glist_decide_top(ldata);
+ glist_display_all(ldata);
+}
+
+static void ListProcess(char **ppbuf, int *plen)
+{
+ struct ListData *ldata = flayer->l_data;
+ int count = 0;
+
+ while (*plen > 0)
+ {
+ struct ListRow *old;
+ unsigned char ch;
+
+ if (!flayer->l_mouseevent.start && ldata->list_fn->gl_pinput &&
+ ldata->list_fn->gl_pinput(ldata, ppbuf, plen))
+ continue;
+
+ ch = **ppbuf;
+ ++*ppbuf;
+ --*plen;
+
+ if (flayer->l_mouseevent.start)
+ {
+ int r = LayProcessMouse(flayer, ch);
+ if (r == -1)
+ {
+ LayProcessMouseSwitch(flayer, 0);
+ continue;
+ }
+ else
+ {
+ if (r)
+ ch = 0222;
+ else
+ continue;
+ }
+ }
+
+ if (!ldata->selected)
+ {
+ *plen = 0;
+ break;
+ }
+
+ old = ldata->selected;
+
+processchar:
+ switch (ch)
+ {
+ case ' ':
+ break;
+
+ case '\r':
+ case '\n':
+ break;
+
+ case 0220: /* up */
+ case 16: /* ^P */
+ case 'k':
+ if (!ldata->selected->prev) /* There's no where to go */
+ break;
+ ldata->selected = old->prev;
+ break;
+
+ case 0216: /* down */
+ case 14: /* ^N like emacs */
+ case 'j':
+ if (!ldata->selected->next) /* Nothing to do */
+ break;
+ ldata->selected = old->next;
+ break;
+
+ case 033: /* escape */
+ case 007: /* ^G */
+ ListAbort();
+ *plen = 0;
+ return;
+
+ case 0201: /* home */
+ case 0001: /* ^A */
+ ldata->selected = ldata->root;
+ break;
+
+ case 0205: /* end */
+ case 0005: /* ^E */
+ while (ldata->selected->next)
+ ldata->selected = ldata->selected->next;
+ if (ldata->selected->y != -1)
+ {
+ /* Both old and current selections are on the screen. So we can just
+ * redraw these two affected rows. */
+ }
+ break;
+
+ case 0004: /* ^D (half-page down) */
+ case 0006: /* page-down, ^F */
+ count = (flayer->l_height - 4) >> (ch == 0004);
+ for (; ldata->selected->next && --count;
+ ldata->selected = ldata->selected->next)
+ ;
+ break;
+
+ case 0025: /* ^U (half-page up) */
+ case 0002: /* page-up, ^B */
+ count = (flayer->l_height - 4) >> (ch == 0025);
+ for (; ldata->selected->prev && --count;
+ ldata->selected = ldata->selected->prev)
+ ;
+ break;
+
+ case '/': /* start searching */
+ if (ldata->list_fn->gl_matchrow)
+ {
+ char *s;
+ Input("Search: ", 80, INP_COOKED, glist_search, (char *)ldata, 0);
+ if ((s = ldata->search))
+ {
+ for (; *s; s++)
+ {
+ char *ss = s;
+ int n = 1;
+ LayProcess(&ss, &n);
+ }
+ }
+ }
+ break;
+
+ /* The following deal with searching. */
+
+ case 'n': /* search next */
+ if (ldata->list_fn->gl_matchrow && ldata->search)
+ ldata->selected = glist_search_dir(ldata, ldata->selected, 1);
+ break;
+
+ case 'N': /* search prev */
+ if (ldata->list_fn->gl_matchrow && ldata->search)
+ ldata->selected = glist_search_dir(ldata, ldata->selected, -1);
+ break;
+
+ /* Now, mouse events. */
+ case 0222:
+ if (flayer->l_mouseevent.start)
+ {
+ int button = flayer->l_mouseevent.buffer[0];
+ if (button == 'a') /* Scroll down */
+ ch = 'j';
+ else if (button == '`') /* Scroll up */
+ ch = 'k';
+ else if (button == ' ') /* Left click */
+ {
+ int y = flayer->l_mouseevent.buffer[2];
+ struct ListRow *r = ldata->top;
+ for (r = ldata->top; r && r->y != -1 && r->y != y; r = r->next)
+ ;
+ if (r && r->y == y)
+ ldata->selected = r;
+ ch = 0;
+ }
+ else
+ ch = 0;
+ LayProcessMouseSwitch(flayer, 0);
+ if (ch)
+ goto processchar;
+ }
+ else
+ LayProcessMouseSwitch(flayer, 1);
+ break;
+ }
+
+ if (old == ldata->selected) /* The selection didn't change */
+ continue;
+
+ if (ldata->selected->y == -1)
+ {
+ /* We need to list all the rows, since we are scrolling down. But first,
+ * find the top of the visible list. */
+ glist_decide_top(ldata);
+ glist_display_all(ldata);
+ }
+ else
+ {
+ /* just redisplay the two lines. */
+ ldata->list_fn->gl_printrow(ldata, old);
+ ldata->list_fn->gl_printrow(ldata, ldata->selected);
+ flayer->l_y = ldata->selected->y;
+ LaySetCursor();
+ }
+ }
+}
+
+static void ListAbort(void)
+{
+ LAY_CALL_UP(LRefreshAll(flayer, 0));
+ ExitOverlayPage();
+}
+
+static void ListFree(void *d)
+{
+ struct ListData *ldata = d;
+ glist_remove_rows(ldata);
+ if (ldata->list_fn->gl_free)
+ ldata->list_fn->gl_free(ldata);
+ if (ldata->search)
+ Free(ldata->search);
+}
+
+static void ListRedisplayLine(int y, int xs, int xe, int isblank)
+{
+ struct ListData *ldata;
+ ASSERT(flayer);
+
+ ldata = flayer->l_data;
+ if (y < 0)
+ {
+ glist_display_all(ldata);
+ return;
+ }
+
+ if (!isblank)
+ LClearArea(flayer, xs, y, xe, y, 0, 0);
+
+ if (ldata->top && y < ldata->top->y)
+ ldata->list_fn->gl_printheader(ldata);
+ else if (y + 1 == flayer->l_height)
+ ldata->list_fn->gl_printfooter(ldata);
+ else
+ {
+ struct ListRow *row;
+ for (row = ldata->top; row && row->y != -1; row = row->next)
+ if (row->y == y)
+ {
+ ldata->list_fn->gl_printrow(ldata, row);
+ break;
+ }
+ }
+}
+
+static void ListClearLine(int y, int xs, int xe, int bce)
+{
+ DefClearLine(y, xs, xe, bce);
+}
+
+static int ListRewrite(int y, int xs, int xe, struct mchar *rend, int doit)
+{
+ return EXPENSIVE;
+}
+
+static int ListResize (int wi, int he)
+{
+ if (wi < 10 || he < 5)
+ return -1;
+
+ flayer->l_width = wi;
+ flayer->l_height = he;
+ flayer->l_y = he - 1;
+
+ return 0;
+}
+
+static void ListRestore (void)
+{
+ DefRestore();
+}
+
+struct ListRow *
+glist_add_row(struct ListData *ldata, void *data, struct ListRow *after)
+{
+ struct ListRow *r = calloc(1, sizeof(struct ListRow));
+ r->data = data;
+
+ if (after)
+ {
+ r->next = after->next;
+ r->prev = after;
+ after->next = r;
+ if (r->next)
+ r->next->prev = r;
+ }
+ else
+ {
+ r->next = ldata->root;
+ if (ldata->root)
+ ldata->root->prev = r;
+ ldata->root = r;
+ }
+
+ return r;
+}
+
+void
+glist_remove_rows(struct ListData *ldata)
+{
+ struct ListRow *row;
+ for (row = ldata->root; row; )
+ {
+ struct ListRow *r = row;
+ row = row->next;
+ ldata->list_fn->gl_freerow(ldata, r);
+ free(r);
+ }
+ ldata->root = ldata->selected = ldata->top = NULL;
+}
+
+void
+glist_display_all(struct ListData *list)
+{
+ int y;
+ struct ListRow *row;
+
+ LClearAll(flayer, 0);
+
+ y = list->list_fn->gl_printheader(list);
+
+ if (!list->top)
+ list->top = list->root;
+ if (!list->selected)
+ list->selected = list->root;
+
+ for (row = list->root; row != list->top; row = row->next)
+ row->y = -1;
+
+ for (row = list->top; row; row = row->next)
+ {
+ row->y = y++;
+ if (!list->list_fn->gl_printrow(list, row))
+ {
+ row->y = -1;
+ y--;
+ }
+ if (y + 1 == flayer->l_height)
+ break;
+ }
+ for (; row; row = row->next)
+ row->y = -1;
+
+ list->list_fn->gl_printfooter(list);
+ if (list->selected && list->selected->y != -1)
+ flayer->l_y = list->selected->y;
+ else
+ flayer->l_y = flayer->l_height - 1;
+ LaySetCursor();
+}
+
+void glist_abort(void)
+{
+ ListAbort();
+}
+
diff --git a/src/list_generic.h b/src/list_generic.h
new file mode 100644
index 0000000..234f6de
--- /dev/null
+++ b/src/list_generic.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+struct ListData;
+
+struct ListRow
+{
+ void *data; /* Some data relevant to this row */
+ struct ListRow *next, *prev; /* doubly linked list */
+ int y; /* -1 if not on display */
+};
+
+struct GenericList
+{
+ int (*gl_printheader) __P((struct ListData *)); /* Print the header */
+ int (*gl_printfooter) __P((struct ListData *)); /* Print the footer */
+ int (*gl_printrow) __P((struct ListData *, struct ListRow *)); /* Print one row */
+ int (*gl_pinput) __P((struct ListData *, char **inp, int *len)); /* Process input */
+ int (*gl_freerow) __P((struct ListData *, struct ListRow *)); /* Free data for a row */
+ int (*gl_free) __P((struct ListData *)); /* Free data for the list */
+ int (*gl_matchrow) __P((struct ListData *, struct ListRow *, const char *));
+};
+
+struct ListData
+{
+ const char *name; /* An identifier for the list */
+ struct ListRow *root; /* The first item in the list */
+ struct ListRow *selected; /* The selected row */
+ struct ListRow *top; /* The topmost visible row */
+
+ struct GenericList *list_fn; /* The functions that deal with the list */
+
+ char *search; /* The search term, if any */
+
+ void *data; /* List specific data */
+};
+
+extern struct LayFuncs ListLf;
+
+
+struct ListRow * glist_add_row __P((struct ListData *ldata, void *data, struct ListRow *after));
+
+void glist_remove_rows __P((struct ListData *ldata));
+
+void glist_display_all __P((struct ListData *list));
+
+struct ListData * glist_display __P((struct GenericList *list, const char *name));
+
+void glist_abort __P((void));
+
+void display_displays __P((void));
+
+void display_windows __P((int onblank, int order, struct win *group));
+
diff --git a/src/list_window.c b/src/list_window.c
new file mode 100644
index 0000000..b65600d
--- /dev/null
+++ b/src/list_window.c
@@ -0,0 +1,678 @@
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+/* Deals with the list of windows */
+
+/* NOTE: A 'struct win *' is used as the 'data' for each row. It might make more sense
+ * to use 'struct win* ->w_number' as the 'data', instead, because that way, we can
+ * verify that the window does exist (by looking at wtab[]).
+ */
+
+#include "config.h"
+#include "screen.h"
+#include "layer.h"
+#include "extern.h"
+#include "list_generic.h"
+
+extern struct layer *flayer;
+extern struct display *display, *displays;
+
+extern char *wlisttit;
+extern char *wliststr;
+
+extern struct mchar mchar_blank, mchar_so;
+extern int renditions[];
+
+extern struct win **wtab, *windows, *fore;
+extern int maxwin;
+
+extern char *noargs[];
+
+static char ListID[] = "window";
+
+struct gl_Window_Data
+{
+ struct win *group; /* Set only for a W_TYPE_GROUP window */
+ int order; /* MRU? NUM? */
+ int onblank;
+ int nested;
+ struct win *fore; /* The foreground window we had. */
+};
+
+/* Is this wdata for a group window? */
+#define WLIST_FOR_GROUP(wdate) ((wdata)->group && !(wdata)->onblank && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
+
+/* This macro should not be used if 'fn' is expected to update the window list */
+#define FOR_EACH_WINDOW(_wdata, _w, fn) do { \
+ if ((_wdata)->order == WLIST_MRU) \
+ { \
+ struct win *_ww; \
+ for (_ww = windows; _ww; _ww = _ww->w_next) \
+ { \
+ _w = _ww; \
+ fn \
+ } \
+ } \
+ else \
+ { \
+ struct win **_ww, *_witer; \
+ for (_ww = wtab, _witer = windows; _witer && _ww - wtab < maxwin; _ww++) \
+ { \
+ if (!(_w = *_ww)) continue; \
+ fn \
+ _witer = _witer->w_next; \
+ } \
+ } \
+ } while (0)
+
+/* Is 'a' an ancestor of 'd'? */
+static int
+window_ancestor(struct win *a, struct win *d)
+{
+ if (!a)
+ return 1; /* Every window is a descendant of the 'null' group */
+ for (; d; d = d->w_group)
+ if (d->w_group == a)
+ return 1;
+ return 0;
+}
+
+static void
+window_kill_confirm(char *buf, int len, char *data)
+{
+ struct win *w = windows;
+ struct action act;
+
+ if (len || (*buf != 'y' && *buf != 'Y'))
+ {
+ *buf = 0;
+ return;
+ }
+
+ /* Loop over the windows to make sure that the window actually still exists. */
+ for (; w; w = w->w_next)
+ if (w == (struct win *)data)
+ break;
+
+ if (!w)
+ return;
+
+ /* Pretend the selected window is the foreground window. Then trigger a non-interactive 'kill' */
+ fore = w;
+ act.nr = RC_KILL;
+ act.args = noargs;
+ act.argl = 0;
+ act.quiet = 0;
+ DoAction(&act, -1);
+}
+
+static struct ListRow *
+gl_Window_add_group(struct ListData *ldata, struct ListRow *row)
+{
+ /* Right now, 'row' doesn't have any child. */
+ struct gl_Window_Data *wdata = ldata->data;
+ struct win *group = row->data, *w;
+ struct ListRow *cur = row;
+
+ ASSERT(wdata->nested);
+
+ FOR_EACH_WINDOW(wdata, w,
+ if (w->w_group != group)
+ continue;
+
+ cur = glist_add_row(ldata, w, cur);
+ if (w == wdata->fore)
+ ldata->selected = cur;
+
+ if (w->w_type == W_TYPE_GROUP)
+ cur = gl_Window_add_group(ldata, cur);
+ );
+
+ return cur;
+}
+
+static void
+gl_Window_rebuild(struct ListData *ldata)
+{
+ struct ListRow *row = NULL;
+ struct gl_Window_Data *wdata = ldata->data;
+ struct win *w;
+
+ FOR_EACH_WINDOW(wdata, w,
+ if (w->w_group != wdata->group)
+ continue;
+ row = glist_add_row(ldata, w, row);
+ if (w == wdata->fore)
+ ldata->selected = row;
+ if (w->w_type == W_TYPE_GROUP && wdata->nested)
+ row = gl_Window_add_group(ldata, row);
+ );
+ glist_display_all(ldata);
+}
+
+static struct ListRow *
+gl_Window_findrow(struct ListData *ldata, struct win *p)
+{
+ struct ListRow *row = ldata->root;
+ for (; row; row = row->next)
+ {
+ if (row->data == p)
+ break;
+ }
+ return row;
+}
+
+static int
+gl_Window_remove(struct ListData *ldata, struct win *p)
+{
+ struct ListRow *row = gl_Window_findrow(ldata, p);
+ if (!row)
+ return 0;
+
+ /* Remove 'row'. Update 'selected', 'top', 'root' if necessary. */
+ if (row->next)
+ row->next->prev = row->prev;
+ if (row->prev)
+ row->prev->next = row->next;
+
+ if (ldata->selected == row)
+ ldata->selected = row->prev ? row->prev : row->next;
+ if (ldata->top == row)
+ ldata->top = row->prev ? row->prev : row->next;
+ if (ldata->root == row)
+ ldata->root = row->next;
+
+ ldata->list_fn->gl_freerow(ldata, row);
+ free(row);
+
+ return 1;
+}
+
+static int
+gl_Window_header(struct ListData *ldata)
+{
+ char *str;
+ struct gl_Window_Data *wdata = ldata->data;
+ int g;
+
+ if ((g = (wdata->group != NULL)))
+ {
+ LPutWinMsg(flayer, "Group: ", 7, &mchar_blank, 0, 0);
+ LPutWinMsg(flayer, wdata->group->w_title, strlen(wdata->group->w_title), &mchar_blank, 7, 0);
+ }
+
+ display = 0;
+ str = MakeWinMsgEv(wlisttit, (struct win *)0, '%', flayer->l_width, (struct event *)0, 0);
+
+ LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, g);
+ return 2 + g;
+}
+
+static int
+gl_Window_footer(struct ListData *ldata)
+{
+ return 0;
+}
+
+static int
+gl_Window_row(struct ListData *ldata, struct ListRow *lrow)
+{
+ char *str;
+ struct win *w, *g;
+ int xoff;
+ struct mchar *mchar;
+ struct mchar mchar_rend = mchar_blank;
+ struct gl_Window_Data *wdata = ldata->data;
+
+ w = lrow->data;
+
+ /* First, make sure we want to display this window in the list.
+ * If we are showing a list for a group, and not on blank, then we must
+ * only show the windows directly belonging to that group.
+ * Otherwise, do some more checks. */
+
+ for (xoff = 0, g = w->w_group; g != wdata->group; g = g->w_group)
+ xoff += 2;
+ display = Layer2Window(flayer) ? 0 : flayer->l_cvlist ? flayer->l_cvlist->c_display : 0;
+ str = MakeWinMsgEv(wliststr, w, '%', flayer->l_width - xoff, NULL, 0);
+ if (ldata->selected == lrow)
+ mchar = &mchar_so;
+ else if (w->w_monitor == MON_DONE && renditions[REND_MONITOR] != -1)
+ {
+ mchar = &mchar_rend;
+ ApplyAttrColor(renditions[REND_MONITOR], mchar);
+ }
+ else if ((w->w_bell == BELL_DONE || w->w_bell == BELL_FOUND) && renditions[REND_BELL] != -1)
+ {
+ mchar = &mchar_rend;
+ ApplyAttrColor(renditions[REND_BELL], mchar);
+ }
+ else if ((w->w_silence == SILENCE_FOUND || w->w_silence == SILENCE_DONE) && renditions[REND_SILENCE] != -1)
+ {
+ mchar = &mchar_rend;
+ ApplyAttrColor(renditions[REND_SILENCE], mchar);
+ }
+ else
+ mchar = &mchar_blank;
+
+ LPutWinMsg(flayer, str, flayer->l_width, mchar, xoff, lrow->y);
+ if (xoff)
+ LPutWinMsg(flayer, "", xoff, mchar, 0, lrow->y);
+
+ return 1;
+}
+
+static int
+gl_Window_input(struct ListData *ldata, char **inp, int *len)
+{
+ struct win *win;
+ unsigned char ch;
+ struct display *cd = display;
+ struct gl_Window_Data *wdata = ldata->data;
+
+ if (!ldata->selected)
+ return 0;
+
+ ch = (unsigned char) **inp;
+ ++*inp;
+ --*len;
+
+ win = ldata->selected->data;
+ switch (ch)
+ {
+ case ' ':
+ case '\n':
+ case '\r':
+ if (!win)
+ break;
+#ifdef MULTIUSER
+ if (display && AclCheckPermWin(D_user, ACL_READ, win))
+ return; /* Not allowed to switch to this window. */
+#endif
+ if (WLIST_FOR_GROUP(wdata))
+ SwitchWindow(win->w_number);
+ else
+ {
+ /* Abort list only when not in a group window. */
+ glist_abort();
+ display = cd;
+ if (D_fore != win)
+ SwitchWindow(win->w_number);
+ }
+ *len = 0;
+ break;
+
+ case 'm':
+ /* Toggle MRU-ness */
+ wdata->order = wdata->order == WLIST_MRU ? WLIST_NUM : WLIST_MRU;
+ glist_remove_rows(ldata);
+ gl_Window_rebuild(ldata);
+ break;
+
+ case 'g':
+ /* Toggle nestedness */
+ wdata->nested = !wdata->nested;
+ glist_remove_rows(ldata);
+ gl_Window_rebuild(ldata);
+ break;
+
+ case 'a':
+ /* All-window view */
+ if (wdata->group)
+ {
+ int order = wdata->order | (wdata->nested ? WLIST_NESTED : 0);
+ glist_abort();
+ display = cd;
+ display_windows(1, order, NULL);
+ *len = 0;
+ }
+ else if (!wdata->nested)
+ {
+ wdata->nested = 1;
+ glist_remove_rows(ldata);
+ gl_Window_rebuild(ldata);
+ }
+ break;
+
+ case 010: /* ^H */
+ case 0177: /* Backspace */
+ if (!wdata->group)
+ break;
+ if (wdata->group->w_group)
+ {
+ /* The parent is another group window. So switch to that window. */
+ struct win *g = wdata->group->w_group;
+ glist_abort();
+ display = cd;
+ SetForeWindow(g);
+ *len = 0;
+ }
+ else
+ {
+ /* We were in a group view. Now we are moving to an all-window view.
+ * So treat it as 'windowlist on blank'. */
+ int order = wdata->order | (wdata->nested ? WLIST_NESTED : 0);
+ glist_abort();
+ display = cd;
+ display_windows(1, order, NULL);
+ *len = 0;
+ }
+ break;
+
+ case ',': /* Switch numbers with the previous window. */
+ if (wdata->order == WLIST_NUM && ldata->selected->prev)
+ {
+ struct win *pw = ldata->selected->prev->data;
+ if (win->w_group != pw->w_group)
+ break; /* Do not allow switching with the parent group */
+
+ /* When a windows's number is successfully changed, it triggers a WListUpdatecv
+ * with NULL window. So that causes a redraw of the entire list. So reset the
+ * 'selected' after that. */
+ wdata->fore = win;
+ WindowChangeNumber(win, pw->w_number);
+ }
+ break;
+
+ case '.': /* Switch numbers with the next window. */
+ if (wdata->order == WLIST_NUM && ldata->selected->next)
+ {
+ struct win *nw = ldata->selected->next->data;
+ if (win->w_group != nw->w_group)
+ break; /* Do not allow switching with the parent group */
+
+ wdata->fore = win;
+ WindowChangeNumber(win, nw->w_number);
+ }
+ break;
+
+ case 'K': /* Kill a window */
+ {
+ char str[MAXSTR];
+ snprintf(str, sizeof(str) - 1, "Really kill window %d (%s) [y/n]",
+ win->w_number, win->w_title);
+ Input(str, 1, INP_RAW, window_kill_confirm, (char *)win, 0);
+ }
+ break;
+
+ case 033: /* escape */
+ case 007: /* ^G */
+ if (!WLIST_FOR_GROUP(wdata))
+ {
+ int fnumber = wdata->onblank ? wdata->fore->w_number : -1;
+ glist_abort();
+ display = cd;
+ if (fnumber >= 0)
+ SwitchWindow(fnumber);
+ *len = 0;
+ }
+ break;
+ default:
+ --*inp;
+ ++*len;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+gl_Window_freerow(struct ListData *ldata, struct ListRow *row)
+{
+ return 0;
+}
+
+static int
+gl_Window_free(struct ListData *ldata)
+{
+ Free(ldata->data);
+ return 0;
+}
+
+static int
+gl_Window_match(struct ListData *ldata, struct ListRow *row, const char *needle)
+{
+ struct win *w = row->data;
+ if (InStr(w->w_title, needle))
+ return 1;
+ return 0;
+}
+
+static struct GenericList gl_Window =
+{
+ gl_Window_header,
+ gl_Window_footer,
+ gl_Window_row,
+ gl_Window_input,
+ gl_Window_freerow,
+ gl_Window_free,
+ gl_Window_match
+};
+
+void
+display_windows(int onblank, int order, struct win *group)
+{
+ struct win *p;
+ struct ListData *ldata;
+ struct gl_Window_Data *wdata;
+
+ if (flayer->l_width < 10 || flayer->l_height < 6)
+ {
+ LMsg(0, "Window size too small for window list page");
+ return;
+ }
+
+ if (group)
+ onblank = 0; /* When drawing a group window, ignore 'onblank' */
+
+ if (onblank)
+ {
+ debug3("flayer %x %d %x\n", flayer, flayer->l_width, flayer->l_height);
+ if (!display)
+ {
+ LMsg(0, "windowlist -b: display required");
+ return;
+ }
+ p = D_fore;
+ if (p)
+ {
+ SetForeWindow((struct win *)0);
+ if (p->w_group)
+ {
+ D_fore = p->w_group;
+ flayer->l_data = (char *)p->w_group;
+ }
+ Activate(0);
+ }
+ if (flayer->l_width < 10 || flayer->l_height < 6)
+ {
+ LMsg(0, "Window size too small for window list page");
+ return;
+ }
+ }
+ else
+ p = Layer2Window(flayer);
+ if (!group && p)
+ group = p->w_group;
+
+ ldata = glist_display(&gl_Window, ListID);
+ if (!ldata)
+ {
+ if (onblank && p)
+ {
+ /* Could not display the list. So restore the window. */
+ SetForeWindow(p);
+ Activate(1);
+ }
+ return;
+ }
+
+ wdata = calloc(1, sizeof(struct gl_Window_Data));
+ wdata->group = group;
+ wdata->order = (order & ~WLIST_NESTED);
+ wdata->nested = !!(order & WLIST_NESTED);
+ wdata->onblank = onblank;
+
+ /* Set the most recent window as selected. */
+ wdata->fore = windows;
+ while (wdata->fore && wdata->fore->w_group != group)
+ wdata->fore = wdata->fore->w_next;
+
+ ldata->data = wdata;
+
+ gl_Window_rebuild(ldata);
+}
+
+static void
+WListUpdate(struct win *p, struct ListData *ldata)
+{
+ struct gl_Window_Data *wdata = ldata->data;
+ struct ListRow *row, *rbefore;
+ struct win *before;
+ int d = 0, sel = 0;
+
+ if (!p)
+ {
+ if (ldata->selected)
+ wdata->fore = ldata->selected->data; /* Try to retain the current selection */
+ glist_remove_rows(ldata);
+ gl_Window_rebuild(ldata);
+ return;
+ }
+
+ /* First decide if this window should be displayed at all. */
+ d = 1;
+ if (wdata->order == WLIST_NUM || wdata->order == WLIST_MRU)
+ {
+ if (p->w_group != wdata->group)
+ {
+ if (!wdata->nested)
+ d = 0;
+ else
+ d = window_ancestor(wdata->group, p);
+ }
+ }
+
+ if (!d)
+ {
+ if (gl_Window_remove(ldata, p))
+ glist_display_all(ldata);
+ return;
+ }
+
+ /* OK, so we keep the window in the list. Update the ordering.
+ * First, find the row where this window should go to. Then, either create
+ * a new row for that window, or move the exising row for the window to the
+ * correct place. */
+ before = NULL;
+ if (wdata->order == WLIST_MRU)
+ {
+ if (windows != p)
+ for (before = windows; before; before = before->w_next)
+ if (before->w_next == p)
+ break;
+ }
+ else if (wdata->order == WLIST_NUM)
+ {
+ if (p->w_number != 0)
+ {
+ struct win **w = wtab + p->w_number - 1;
+ for (; w >= wtab; w--)
+ {
+ if (*w && (*w)->w_group == wdata->group)
+ {
+ before = *w;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Now, find the row belonging to 'before' */
+ if (before)
+ rbefore = gl_Window_findrow(ldata, before);
+ else if (wdata->nested && p->w_group) /* There's no 'before'. So find the group window */
+ rbefore = gl_Window_findrow(ldata, p->w_group);
+ else
+ rbefore = NULL;
+
+ /* For now, just remove the row containing 'p' if it is not already in the right place . */
+ row = gl_Window_findrow(ldata, p);
+ if (row)
+ {
+ if (row->prev != rbefore)
+ {
+ sel = ldata->selected->data == p;
+ gl_Window_remove(ldata, p);
+ }
+ else
+ p = NULL; /* the window is in the correct place */
+ }
+ if (p)
+ {
+ row = glist_add_row(ldata, p, rbefore);
+ if (sel)
+ ldata->selected = row;
+ }
+ glist_display_all(ldata);
+}
+
+void
+WListUpdatecv(cv, p)
+struct canvas *cv;
+struct win *p;
+{
+ struct ListData *ldata;
+ struct gl_Window_Data *wdata;
+
+ if (cv->c_layer->l_layfn != &ListLf)
+ return;
+ ldata = cv->c_layer->l_data;
+ if (ldata->name != ListID)
+ return;
+ wdata = ldata->data;
+ CV_CALL(cv, WListUpdate(p, ldata));
+}
+
+void
+WListLinkChanged()
+{
+ struct display *olddisplay = display;
+ struct canvas *cv;
+ struct ListData *ldata;
+ struct gl_Window_Data *wdata;
+
+ for (display = displays; display; display = display->d_next)
+ for (cv = D_cvlist; cv; cv = cv->c_next)
+ {
+ if (!cv->c_layer || cv->c_layer->l_layfn != &ListLf)
+ continue;
+ ldata = cv->c_layer->l_data;
+ if (ldata->name != ListID)
+ continue;
+ wdata = ldata->data;
+ if (!(wdata->order & WLIST_MRU))
+ continue;
+ CV_CALL(cv, WListUpdate(0, ldata));
+ }
+ display = olddisplay;
+}
+
diff --git a/src/loadav.c b/src/loadav.c
index 3e2c28e..770010c 100644
--- a/src/loadav.c
+++ b/src/loadav.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/logfile.c b/src/logfile.c
index 0e2eee0..edee89d 100644
--- a/src/logfile.c
+++ b/src/logfile.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/logfile.h b/src/logfile.h
index 59c4b36..c588a32 100644
--- a/src/logfile.h
+++ b/src/logfile.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
struct logfile
diff --git a/src/mark.c b/src/mark.c
index 9ff7b65..ccb74f9 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -77,7 +77,8 @@ struct LayFuncs MarkLf =
DefClearLine,
MarkRewrite,
DefResize,
- DefRestore
+ DefRestore,
+ 0
};
int join_with_cr = 0;
@@ -162,14 +163,18 @@ nextchar(int *xp, int *yp, int direction, char target, int num)
displayed_line = (char *)WIN(*yp) -> image;
switch(direction) {
- case 't': adjust = -1; /* fall through */
- case 'f': step = 1; /* fall through */
- break;
- case 'T': adjust = 1; /* fall through */
- case 'F': step = -1; /* fall through */
- break;
- default:
- ASSERT(0);
+ case 't':
+ adjust = -1; /* fall through */
+ case 'f':
+ step = 1;
+ break;
+ case 'T':
+ adjust = 1; /* fall through */
+ case 'F':
+ step = -1;
+ break;
+ default:
+ ASSERT(0);
}
x += step;
@@ -498,6 +503,7 @@ MarkRoutine()
if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1))
return;
flayer->l_encoding = fore->w_encoding;
+ flayer->l_mode = 1;
markdata = (struct markdata *)flayer->l_data;
markdata->md_user = D_user; /* XXX: Correct? */
markdata->md_window = fore;
@@ -556,19 +562,22 @@ int *inlenp;
in_mark = 1;
while (in_mark && (inlen /* || extrap */))
{
-/*
- if (extrap)
+ unsigned char ch = (unsigned char )*pt++;
+ inlen--;
+ if (flayer->l_mouseevent.start)
{
- od = *extrap++;
- if (*extrap == 0)
- extrap = 0;
- }
- else
-*/
- {
- od = mark_key_tab[(int)(unsigned char)*pt++];
- inlen--;
+ int r = LayProcessMouse(flayer, ch);
+ if (r == -1)
+ LayProcessMouseSwitch(flayer, 0);
+ else
+ {
+ if (r)
+ ch = 0222;
+ else
+ continue;
+ }
}
+ od = mark_key_tab[(int)ch];
rep_cnt = markdata->rep_cnt;
if (od >= '0' && od <= '9' && !markdata->f_cmd.flag)
{
@@ -605,49 +614,36 @@ int *inlenp;
}
}
- switch (od)
+processchar:
+ switch (od)
{
case 'f': /* fall through */
case 'F': /* fall through */
case 't': /* fall through */
case 'T': /* fall through */
- /*
- * Set f_cmd to do a search on the next key stroke.
- * If we break, rep_cnt will be reset, so we
- * continue instead. It might be cleaner to
- * store the rep_count in f_cmd and
- * break here so later followon code will be
- * hit.
- */
- markdata->f_cmd.flag = 1;
- markdata->f_cmd.direction = od;
- debug("entering char search\n");
- continue;
+ /*
+ * Set f_cmd to do a search on the next key stroke.
+ * If we break, rep_cnt will be reset, so we
+ * continue instead. It might be cleaner to
+ * store the rep_count in f_cmd and
+ * break here so later followon code will be
+ * hit.
+ */
+ markdata->f_cmd.flag = 1;
+ markdata->f_cmd.direction = od;
+ debug("entering char search\n");
+ continue;
case ';':
+ case ',':
if (!markdata->f_cmd.target)
break;
if (!rep_cnt)
rep_cnt = 1;
- nextchar(&cx, &cy, markdata->f_cmd.direction, markdata->f_cmd.target, rep_cnt );
- revto(cx, cy);
- break;
- case ',': {
- int search_dir;
- if (!markdata->f_cmd.target)
- break;
- if (!rep_cnt)
- rep_cnt = 1;
- switch (markdata->f_cmd.direction) {
- case 't': search_dir = 'T'; break;
- case 'T': search_dir = 't'; break;
- case 'f': search_dir = 'F'; break;
- case 'F': search_dir = 'f'; break;
- }
- nextchar(&cx, &cy, search_dir, markdata->f_cmd.target, rep_cnt );
+ nextchar(&cx, &cy,
+ od == ';' ? markdata->f_cmd.direction : (markdata->f_cmd.direction ^ 0x20),
+ markdata->f_cmd.target, rep_cnt );
revto(cx, cy);
break;
- }
-
case 'o':
case 'x':
if (!markdata->second)
@@ -1040,6 +1036,7 @@ int *inlenp;
LAY_CALL_UP(LRefreshAll(flayer, 0));
}
ExitOverlayPage();
+ WindowChanged(fore, 'P');
if (append_mode)
LMsg(0, "Appended %d characters to buffer",
newcopylen);
@@ -1050,6 +1047,39 @@ int *inlenp;
in_mark = 0;
break;
}
+
+ case 0222:
+ if (flayer->l_mouseevent.start)
+ {
+ int button = flayer->l_mouseevent.buffer[0];
+ if (button == 'a')
+ {
+ /* Scroll down */
+ od = 'j';
+ }
+ else if (button == '`')
+ {
+ /* Scroll up */
+ od = 'k';
+ }
+ else if (button == ' ')
+ {
+ /* Left click */
+ cx = flayer->l_mouseevent.buffer[1];
+ cy = D2W(flayer->l_mouseevent.buffer[2]);
+ revto(cx, cy);
+ od = ' ';
+ }
+ else
+ od = 0;
+ LayProcessMouseSwitch(flayer, 0);
+ if (od)
+ goto processchar;
+ }
+ else
+ LayProcessMouseSwitch(flayer, 1);
+ break;
+
default:
MarkAbort();
LMsg(0, "Copy mode aborted");
@@ -1126,6 +1156,8 @@ int tx, ty, line;
if (markdata->second == 0)
{
+ flayer->l_x = tx;
+ flayer->l_y = W2D(ty);
LGotoPos(flayer, tx, W2D(ty));
return;
}
@@ -1222,6 +1254,8 @@ int tx, ty, line;
#endif
}
}
+ flayer->l_x = tx;
+ flayer->l_y = W2D(ty);
LGotoPos(flayer, tx, W2D(ty));
}
@@ -1249,6 +1283,7 @@ MarkAbort()
rem(markdata->x1, markdata->y1, markdata->cx, markdata->cy, redisp, (char *)0, yend);
}
ExitOverlayPage();
+ WindowChanged(fore, 'P');
}
@@ -1455,14 +1490,6 @@ int n;
return n;
}
-int
-InMark()
-{
- if (flayer && flayer->l_layfn == &MarkLf)
- return 1;
- return 0;
-}
-
void
MakePaster(pa, buf, len, bufiscopy)
struct paster *pa;
diff --git a/src/mark.h b/src/mark.h
index d9e3c33..a275fe9 100644
--- a/src/mark.h
+++ b/src/mark.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
struct markdata
diff --git a/src/misc.c b/src/misc.c
index dd20ab1..43e93a2 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -57,7 +57,7 @@ register const char *str;
register char *cp;
if ((cp = malloc(strlen(str) + 1)) == NULL)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
else
strcpy(cp, str);
return cp;
@@ -71,7 +71,7 @@ int n;
register char *cp;
if ((cp = malloc(n + 1)) == NULL)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
else
{
bcopy((char *)str, cp, n);
@@ -125,9 +125,10 @@ int y;
}
void
-leftline(str, y)
+leftline(str, y, rend)
char *str;
int y;
+struct mchar *rend;
{
int l, n;
struct mchar mchar_dol;
@@ -139,7 +140,7 @@ int y;
l = n = strlen(str);
if (n > flayer->l_width - 1)
n = flayer->l_width - 1;
- LPutStr(flayer, str, n, &mchar_blank, 0, y);
+ LPutStr(flayer, str, n, rend ? rend : &mchar_blank, 0, y);
if (n != l)
LPutChar(flayer, &mchar_dol, n, y);
}
@@ -608,7 +609,7 @@ char *value;
* the string space, we can free our buf now.
*/
free(buf);
-# else /* NEEDSETENV */
+# else /* NEEDPUTENV */
/*
* For all sysv-ish systems that link a standard putenv()
* the string-space buf is added to the environment and must not
@@ -616,7 +617,7 @@ char *value;
* We are sorry to say that memory is lost here, when setting
* the same variable again and again.
*/
-# endif /* NEEDSETENV */
+# endif /* NEEDPUTENV */
#else /* USESETENV */
# if HAVE_SETENV_3
setenv(var, value, 1);
@@ -651,39 +652,6 @@ int (*outc) __P((int));
return 0;
}
-# ifdef linux
-
-/* stupid stupid linux ncurses! It won't to padding with
- * zeros but sleeps instead. This breaks CalcCost, of course.
- * Also, the ncurses wait functions use a global variable
- * to store the current outc function. Oh well...
- */
-
-int (*save_outc) __P((int));
-
-# undef tputs
-
-void
-xtputs(str, affcnt, outc)
-char *str;
-int affcnt;
-int (*outc) __P((int));
-{
- extern int tputs __P((const char *, int, int (*)(int)));
- save_outc = outc;
- tputs(str, affcnt, outc);
-}
-
-int
-_nc_timed_wait(mode, ms, tlp)
-int mode, ms, *tlp;
-{
- _delay(ms * 10, save_outc);
- return 0;
-}
-
-# endif /* linux */
-
#endif /* TERMINFO */
diff --git a/src/nethack.c b/src/nethack.c
index 788fbbe..d8ae456 100644
--- a/src/nethack.c
+++ b/src/nethack.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -120,9 +120,9 @@ static struct nlstrans nethacktrans[] = {
};
#endif
-char *
+const char *
DoNLS(from)
-char *from;
+const char *from;
{
#ifdef NETHACK
struct nlstrans *t;
diff --git a/src/os.h b/src/os.h
index be20572..5c17c83 100644
--- a/src/os.h
+++ b/src/os.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
#include <stdio.h>
@@ -41,7 +41,7 @@
# include <signal.h>
#endif /* __bsdi__ || __386BSD__ || _CX_UX || hpux || _IBMR2 || linux */
-#ifndef HAVE_LONG_FILE_NAMES
+#if !defined(HAVE_LONG_FILE_NAMES) && !defined(NAME_MAX)
#define NAME_MAX 14
#endif
@@ -234,11 +234,6 @@ extern int errno;
# undef TIOCPKT
#endif
-/* linux ncurses is broken, we have to use our own tputs */
-#if defined(linux) && defined(TERMINFO)
-# define tputs xtputs
-#endif
-
/* Alexandre Oliva: SVR4 style ptys don't work with osf */
#ifdef __osf__
# undef HAVE_SVR4_PTYS
diff --git a/src/osdef.h.in b/src/osdef.h.in
index 36964fb..2253218 100644
--- a/src/osdef.h.in
+++ b/src/osdef.h.in
@@ -19,7 +19,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
/****************************************************************
diff --git a/src/patchlevel.h b/src/patchlevel.h
index 2eebfb4..0695698 100644
--- a/src/patchlevel.h
+++ b/src/patchlevel.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
/****************************************************************
@@ -530,7 +530,7 @@
* 2005-12-19, 4.00.03jw3 syntax error.
*/
-#define ORIGIN "FAU"
+#define ORIGIN "GNU"
#define REV 4
#define VERS 1
#define PATCHLEVEL 0
diff --git a/src/process.c b/src/process.c
index 1ea7d0c..1cf26e4 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1,4 +1,7 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -26,6 +29,8 @@
****************************************************************
*/
+#include "config.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
@@ -39,8 +44,6 @@
#endif
-#include "config.h"
-
/* for solaris 2.1, Unixware (SVR4.2) and possibly others: */
#ifdef HAVE_STROPTS_H
# include <sys/stropts.h>
@@ -49,6 +52,9 @@
#include "screen.h"
#include "extern.h"
#include "logfile.h"
+#include "layout.h"
+#include "viewport.h"
+#include "list_generic.h"
extern struct comm comms[];
extern char *rc_name;
@@ -57,6 +63,7 @@ extern char *BellString, *ActivityString, *ShellProg, *ShellArgs[];
extern char *hstatusstring, *captionstring, *timestring;
extern char *wliststr, *wlisttit;
extern int captionalways;
+extern int queryflag;
extern char *hardcopydir, *screenlogfile, *logtstamp_string;
extern int log_flush, logtstamp_on, logtstamp_after;
extern char *VisualBellString;
@@ -75,6 +82,7 @@ extern char *printcmd;
extern int default_startup;
extern int defobuflimit;
extern int defnonblock;
+extern int defmousetrack;
extern int ZombieKey_destroy;
extern int ZombieKey_resurrect;
extern int ZombieKey_onerror;
@@ -106,6 +114,7 @@ extern char *kmapadef[];
extern char *kmapmdef[];
#endif
extern struct mchar mchar_so, mchar_null;
+extern int renditions[];
extern int VerboseCreate;
#ifdef UTF8
extern char *screenencodings;
@@ -153,6 +162,7 @@ static void pass2 __P((char *, int, char *));
static void pow_detach_fn __P((char *, int, char *));
#endif
static void digraph_fn __P((char *, int, char *));
+static int digraph_find __P((const char *buf));
static void confirm_fn __P((char *, int, char *));
static int IsOnDisplay __P((struct win *));
static void ResizeRegions __P((char *, int));
@@ -187,7 +197,7 @@ extern int nethackflag;
#endif
-struct win *wtab[MAXWIN]; /* window table, should be dynamic */
+extern struct win **wtab;
#ifdef MULTIUSER
extern char *multi;
@@ -234,6 +244,15 @@ int kmap_extn;
static int maptimeout = 300;
#endif
+#ifndef MAX_DIGRAPH
+#define MAX_DIGRAPH 512
+#endif
+
+struct digraph
+{
+ unsigned char d[2];
+ int value;
+};
/*
* Command aliases.
@@ -250,7 +269,7 @@ struct alias *g_aliases_list = NULL;
/* digraph table taken from old vim and rfc1345 */
-static const unsigned char digraphs[][3] = {
+static struct digraph digraphs[MAX_DIGRAPH + 1] = {
{' ', ' ', 160}, /*   */
{'N', 'S', 160}, /*   */
{'~', '!', 161}, /* ¡ */
@@ -439,6 +458,44 @@ static char *resizeprompts[] = {
"resize -l -b # lines: ",
};
+static int
+parse_input_int(buf, len, val)
+const char *buf;
+int len;
+int *val;
+{
+ int x = 0, i;
+ if (len >= 1 && ((*buf == 'U' && buf[1] == '+') || (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X'))))
+ {
+ x = 0;
+ for (i = 2; i < len; i++)
+ {
+ if (buf[i] >= '0' && buf[i] <= '9')
+ x = x * 16 | (buf[i] - '0');
+ else if (buf[i] >= 'a' && buf[i] <= 'f')
+ x = x * 16 | (buf[i] - ('a' - 10));
+ else if (buf[i] >= 'A' && buf[i] <= 'F')
+ x = x * 16 | (buf[i] - ('A' - 10));
+ else
+ return 0;
+ }
+ }
+ else if (buf[0] == '0')
+ {
+ x = 0;
+ for (i = 1; i < len; i++)
+ {
+ if (buf[i] < '0' || buf[i] > '7')
+ return 0;
+ x = x * 8 | (buf[i] - '0');
+ }
+ }
+ else
+ return 0;
+ *val = x;
+ return 1;
+}
+
char *noargs[1];
void
@@ -554,7 +611,7 @@ InitKeytab()
args[1] = NULL;
SaveAction(ktab + '-', RC_SELECT, args, 0);
}
- for (i = 0; i < ((MAXWIN < 10) ? MAXWIN : 10); i++)
+ for (i = 0; i < ((maxwin && maxwin < 10) ? maxwin : 10); i++)
{
char *args[2], arg1[10];
args[0] = arg1;
@@ -602,7 +659,7 @@ InitKeytab()
ktab['\t'].nr = RC_FOCUS;
{
char *args[2];
- args[0] = "up";
+ args[0] = "prev";
args[1] = 0;
SaveAction(ktab + T_BACKTAB - T_CAPS + 256, RC_FOCUS, args, 0);
}
@@ -654,7 +711,7 @@ int create;
kp = malloc(sizeof(*kp));
if (kp == 0)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return 0;
}
kp->name = SaveStr(class);
@@ -662,6 +719,8 @@ int create;
{
kp->ktab[i].nr = RC_ILLEGAL;
kp->ktab[i].args = noargs;
+ kp->ktab[i].argl = 0;
+ kp->ktab[i].quiet = 0;
}
kp->next = 0;
*kpp = kp;
@@ -958,7 +1017,7 @@ struct paster *pa;
int
FindCommnr(str)
-char *str;
+const char *str;
{
int x, m, l = 0, r = RC_LAST;
while (l <= r)
@@ -1126,19 +1185,35 @@ int key;
}
n = comms[nr].flags;
+ /* Commands will have a CAN_QUERY flag, depending on whether they have
+ * something to return on a query. For example, 'windows' can return a result,
+ * but 'other' cannot.
+ * If some command causes an error, then it should reset queryflag to -1, so that
+ * the process requesting the query can be notified that an error happened.
+ */
+ if (!(n & CAN_QUERY) && queryflag >= 0)
+ {
+ /* Query flag is set, but this command cannot be queried. */
+ Msg(0, "%s command cannot be queried.", comms[nr].name);
+ queryflag = -1;
+ return;
+ }
if ((n & NEED_DISPLAY) && display == 0)
{
Msg(0, "%s: %s: display required", rc_name, comms[nr].name);
+ queryflag = -1;
return;
}
if ((n & NEED_FORE) && fore == 0)
{
Msg(0, "%s: %s: window required", rc_name, comms[nr].name);
+ queryflag = -1;
return;
}
if ((n & NEED_LAYER) && flayer == 0)
{
Msg(0, "%s: %s: display or window required", rc_name, comms[nr].name);
+ queryflag = -1;
return;
}
if ((argc = CheckArgNum(nr, args)) < 0)
@@ -1150,6 +1225,7 @@ int key;
{
Msg(0, "%s: %s: permission denied (user %s)",
rc_name, comms[nr].name, (EffectiveAclUser ? EffectiveAclUser : D_user)->u_name);
+ queryflag = -1;
return;
}
}
@@ -1169,7 +1245,10 @@ int key;
else if (args[0][0] == '.' && !args[0][1])
{
if (!fore)
- Msg(0, "select . needs a window");
+ {
+ Msg(0, "select . needs a window");
+ queryflag = -1;
+ }
else
{
SetForeWindow(fore);
@@ -1178,6 +1257,8 @@ int key;
}
else if (ParseWinNum(act, &n) == 0)
SwitchWindow(n);
+ else if (queryflag >= 0)
+ queryflag = -1; /* ParseWinNum already prints out an appropriate error message. */
break;
#ifdef AUTO_NUKE
case RC_DEFAUTONUKE:
@@ -1380,6 +1461,15 @@ int key;
Msg(0, "zmodem mode is %s", zmodes[zmodem_mode]);
break;
#endif
+ case RC_UNBINDALL:
+ {
+ register unsigned int i;
+
+ for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++)
+ ClearAction(&ktab[i]);
+ Msg(0, "Unbound all keys." );
+ break;
+ }
case RC_ZOMBIE:
{
if (!(s = *args))
@@ -1422,12 +1512,14 @@ int key;
break;
case RC_AT:
/* where this AT command comes from: */
+ if (!user)
+ break;
#ifdef MULTIUSER
- s = SaveStr(D_user->u_name);
+ s = SaveStr(user->u_name);
/* DO NOT RETURN FROM HERE WITHOUT RESETTING THIS: */
- EffectiveAclUser = D_user;
+ EffectiveAclUser = user;
#else
- s = SaveStr(D_usertty);
+ s = SaveStr(display ? D_usertty : user->u_name);
#endif
n = strlen(args[0]);
if (n) n--;
@@ -1444,14 +1536,22 @@ int key;
struct acluser *u;
if (!n)
- u = D_user;
+ u = user;
else
- for (u = users; u; u = u->u_next)
- {
- debug3("strncmp('%s', '%s', %d)\n", *args, u->u_name, n);
- if (!strncmp(*args, u->u_name, n))
+ {
+ for (u = users; u; u = u->u_next)
+ {
+ debug3("strncmp('%s', '%s', %d)\n", *args, u->u_name, n);
+ if (!strncmp(*args, u->u_name, n))
+ break;
+ }
+ if (!u)
+ {
+ args[0][n] = '\0';
+ Msg(0, "Did not find any user matching '%s'", args[0]);
break;
- }
+ }
+ }
debug1("at all displays of user %s\n", u->u_name);
for (display = displays; display; display = nd)
{
@@ -1510,7 +1610,7 @@ int key;
struct win *nw;
int ch;
- n++;
+ n++;
ch = args[0][n];
args[0][n] = '\0';
if (!*args[0] || (i = WindowByNumber(args[0])) < 0)
@@ -1549,7 +1649,7 @@ int key;
Msg(0, "%s: at '%s': no such window.\n", rc_name, args[0]);
break;
}
- else if (i < MAXWIN && (fore = wtab[i]))
+ else if (i < maxwin && (fore = wtab[i]))
{
args[0][n] = ch; /* must restore string in case of bind */
debug2("AT window %d (%s)\n", fore->w_number, fore->w_title);
@@ -1986,6 +2086,13 @@ int key;
}
break;
case RC_TITLE:
+ if (queryflag >= 0)
+ {
+ if (fore)
+ Msg(0, "%s", fore->w_title);
+ else
+ queryflag = -1;
+ }
if (*args == 0)
InputAKA();
else
@@ -2132,7 +2239,7 @@ int key;
#endif
case RC_WINDOWLIST:
if (!*args)
- display_wlist(0, WLIST_NUM, (struct win *)0);
+ display_windows(0, WLIST_NUM, (struct win *)0);
else if (!strcmp(*args, "string"))
{
if (args[1])
@@ -2174,7 +2281,7 @@ int key;
break;
}
if (i == argc)
- display_wlist(blank, flag, (struct win *)0);
+ display_windows(blank, flag, (struct win *)0);
}
break;
case RC_HELP:
@@ -2202,6 +2309,7 @@ int key;
break;
}
MarkRoutine();
+ WindowChanged(fore, 'P');
break;
case RC_HISTORY:
{
@@ -2305,7 +2413,7 @@ int key;
*/
if ((dbuf = (char *)malloc(l)) == 0)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
break;
}
l = 0;
@@ -2392,7 +2500,7 @@ int key;
newbuf = malloc(l + 1);
if (!newbuf)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
break;
}
user->u_plop.len = RecodeBuf((unsigned char *)oldplop.buf, oldplop.len, oldplop.enc, enc, (unsigned char *)newbuf);
@@ -2600,7 +2708,10 @@ int key;
if (s)
Msg(0, "%s", s);
else
- Msg(0, "%s: 'echo [-n] [-p] \"string\"' expected.", rc_name);
+ {
+ Msg(0, "%s: 'echo [-n] [-p] \"string\"' expected.", rc_name);
+ queryflag = -1;
+ }
break;
case RC_BELL:
case RC_BELL_MSG:
@@ -2707,6 +2818,22 @@ int key;
if (ParseOnOff(act, &n) == 0)
nwin_default.monitor = (n == 0) ? MON_OFF : MON_ON;
break;
+ case RC_DEFMOUSETRACK:
+ if (ParseOnOff(act, &n) == 0)
+ defmousetrack = (n == 0) ? 0 : 1000;
+ break;
+ case RC_MOUSETRACK:
+ if (!args[0])
+ {
+ Msg(0, "Mouse tracking for this display is turned %s", D_mousetrack ? "on" : "off");
+ }
+ else if (ParseOnOff(act, &n) == 0)
+ {
+ D_mousetrack = n == 0 ? 0 : 1000;
+ if (D_fore)
+ MouseMode(D_fore->w_mouse);
+ }
+ break;
case RC_DEFSILENCE:
if (ParseOnOff(act, &n) == 0)
nwin_default.silence = (n == 0) ? SILENCE_OFF : SILENCE_ON;
@@ -2877,7 +3004,7 @@ int key;
break;
case RC_NUMBER:
if (*args == 0)
- Msg(0, "This is window %d (%s).\n", fore->w_number, fore->w_title);
+ Msg(0, queryflag >= 0 ? "%d (%s)" : "This is window %d (%s).", fore->w_number, fore->w_title);
else
{
int old = fore->w_number;
@@ -2897,41 +3024,12 @@ int key;
n += old;
else if (rel < 0)
n = old - n;
- if (n < 0 || n >= maxwin)
+ if (!WindowChangeNumber(fore, n))
{
- Msg(0, "Given window position is invalid.");
+ /* Window number could not be changed. */
+ queryflag = -1;
return;
}
- p = wtab[n];
- wtab[n] = fore;
- fore->w_number = n;
- wtab[old] = p;
- if (p)
- p->w_number = old;
-#ifdef MULTIUSER
- /* exchange the acls for these windows. */
- AclWinSwap(old, n);
-#endif
-#ifdef UTMPOK
- /* exchange the utmp-slots for these windows */
- if ((fore->w_slot != (slot_t) -1) && (fore->w_slot != (slot_t) 0))
- {
- RemoveUtmp(fore);
- SetUtmp(fore);
- }
- if (p && (p->w_slot != (slot_t) -1) && (p->w_slot != (slot_t) 0))
- {
- /* XXX: first display wins? */
- display = fore->w_layer.l_cvlist ? fore->w_layer.l_cvlist->c_display : 0;
- RemoveUtmp(p);
- SetUtmp(p);
- }
-#endif
-
- WindowChanged(fore, 'n');
- WindowChanged((struct win *)0, 'w');
- WindowChanged((struct win *)0, 'W');
- WindowChanged((struct win *)0, 0);
}
break;
case RC_SILENCE:
@@ -3309,6 +3407,7 @@ int key;
kme->str = 0;
kme->dm.nr = kme->mm.nr = kme->um.nr = RC_ILLEGAL;
kme->dm.args = kme->mm.args = kme->um.args = noargs;
+ kme->dm.argl = kme->mm.argl = kme->um.argl = 0;
}
i -= 8;
kme -= 8;
@@ -3683,6 +3782,45 @@ int key;
break;
case RC_DIGRAPH:
+ if (argl && argl[0] > 0 && argl[1] > 0)
+ {
+ if (argl[0] != 2)
+ {
+ Msg(0, "Two characters expected to define a digraph");
+ break;
+ }
+ i = digraph_find(args[0]);
+ digraphs[i].d[0] = args[0][0];
+ digraphs[i].d[1] = args[0][1];
+ if (!parse_input_int(args[1], argl[1], &digraphs[i].value))
+ {
+ if (!(digraphs[i].value = atoi(args[1])))
+ {
+ if (!args[1][1])
+ digraphs[i].value = (int)args[1][0];
+#ifdef UTF8
+ else
+ {
+ int t;
+ unsigned char *s = args[1];
+ digraphs[i].value = 0;
+ while (*s)
+ {
+ t = FromUtf8(*s++, &digraphs[i].value);
+ if (t == -1)
+ continue;
+ if (t == -2)
+ digraphs[i].value = 0;
+ else
+ digraphs[i].value = t;
+ break;
+ }
+ }
+#endif
+ }
+ }
+ break;
+ }
Input("Enter digraph: ", 10, INP_EVERY, digraph_fn, NULL, 0);
if (*args && **args)
{
@@ -3795,6 +3933,40 @@ int key;
nattr2color = n;
break;
#endif
+ case RC_RENDITION:
+ i = -1;
+ if (strcmp(args[0], "bell") == 0)
+ {
+ i = REND_BELL;
+ }
+ else if (strcmp(args[0], "monitor") == 0)
+ {
+ i = REND_MONITOR;
+ }
+ else if (strcmp(args[0], "silence") == 0)
+ {
+ i = REND_SILENCE;
+ }
+ else if (strcmp(args[0], "so") != 0)
+ {
+ Msg(0, "Invalid option '%s' for rendition", args[0]);
+ break;
+ }
+
+ ++args;
+ ++argl;
+
+ if (i != -1)
+ {
+ renditions[i] = ParseAttrColor(args[0], args[1], 1);
+ WindowChanged((struct win *)0, 'w');
+ WindowChanged((struct win *)0, 'W');
+ WindowChanged((struct win *)0, 0);
+ break;
+ }
+
+ /* We are here, means we want to set the sorendition. */
+ /* FALLTHROUGH*/
case RC_SORENDITION:
i = 0;
if (*args)
@@ -3803,6 +3975,7 @@ int key;
if (i == -1)
break;
ApplyAttrColor(i, &mchar_so);
+ WindowChanged((struct win *)0, 0);
debug2("--> %x %x\n", mchar_so.attr, mchar_so.color);
}
if (msgok)
@@ -3860,55 +4033,37 @@ int key;
LaySetCursor();
break;
case RC_FOCUS:
- if (!*args || !strcmp(*args, "down"))
- D_forecv = D_forecv->c_next ? D_forecv->c_next : D_cvlist;
- else if (!strcmp(*args, "up"))
- {
- struct canvas *cv;
- for (cv = D_cvlist; cv->c_next && cv->c_next != D_forecv; cv = cv->c_next)
- ;
- D_forecv = cv;
- }
- else if (!strcmp(*args, "top"))
- D_forecv = D_cvlist;
- else if (!strcmp(*args, "bottom"))
- {
- struct canvas *cv;
- for (cv = D_cvlist; cv->c_next; cv = cv->c_next)
- ;
- D_forecv = cv;
- }
- else
- {
- Msg(0, "%s: usage: focus [up|down|top|bottom]", rc_name);
- break;
- }
- if ((focusminwidth && (focusminwidth < 0 || D_forecv->c_xe - D_forecv->c_xs + 1 < focusminwidth)) ||
- (focusminheight && (focusminheight < 0 || D_forecv->c_ye - D_forecv->c_ys + 1 < focusminheight)))
- {
- ResizeCanvas(&D_canvas);
- RecreateCanvasChain();
- RethinkDisplayViewports();
- ResizeLayersToCanvases(); /* redisplays */
- }
- fore = D_fore = Layer2Window(D_forecv->c_layer);
- if (D_other == fore)
- D_other = 0;
- flayer = D_forecv->c_layer;
-#ifdef RXVT_OSC
- if (D_xtermosc[2] || D_xtermosc[3])
- {
- Activate(-1);
- break;
- }
-#endif
- RefreshHStatus();
-#ifdef RXVT_OSC
- RefreshXtermOSC();
-#endif
- flayer = D_forecv->c_layer;
- CV_CALL(D_forecv, LayRestore();LaySetCursor());
- WindowChanged(0, 'F');
+ {
+ struct canvas *cv = 0;
+ if (!*args || !strcmp(*args, "next"))
+ cv = D_forecv->c_next ? D_forecv->c_next : D_cvlist;
+ else if (!strcmp(*args, "prev"))
+ {
+ for (cv = D_cvlist; cv->c_next && cv->c_next != D_forecv; cv = cv->c_next)
+ ;
+ }
+ else if (!strcmp(*args, "top"))
+ cv = D_cvlist;
+ else if (!strcmp(*args, "bottom"))
+ {
+ for (cv = D_cvlist; cv->c_next; cv = cv->c_next)
+ ;
+ }
+ else if (!strcmp(*args, "up"))
+ cv = FindCanvas(D_forecv->c_xs, D_forecv->c_ys - 1);
+ else if (!strcmp(*args, "down"))
+ cv = FindCanvas(D_forecv->c_xs, D_forecv->c_ye + 2);
+ else if (!strcmp(*args, "left"))
+ cv = FindCanvas(D_forecv->c_xs - 1, D_forecv->c_ys);
+ else if (!strcmp(*args, "right"))
+ cv = FindCanvas(D_forecv->c_xe + 1, D_forecv->c_ys);
+ else
+ {
+ Msg(0, "%s: usage: focus [next|prev|up|down|left|right|top|bottom]", rc_name);
+ break;
+ }
+ SetForeCanvas(display, cv);
+ }
break;
case RC_RESIZE:
i = 0;
@@ -3961,14 +4116,25 @@ int key;
Msg(0, "Will %sdo alternate screen switching", use_altscreen ? "" : "not ");
break;
case RC_MAXWIN:
+ if (!args[0])
+ {
+ Msg(0, "maximum windows allowed: %d", maxwin);
+ break;
+ }
if (ParseNum(act, &n))
break;
if (n < 1)
Msg(0, "illegal maxwin number specified");
- else if (n > maxwin)
- Msg(0, "may only decrease maxwin number");
+ else if (n > 2048)
+ Msg(0, "maximum 2048 windows allowed");
+ else if (n > maxwin && windows)
+ Msg(0, "may increase maxwin only when there's no window");
else
- maxwin = n;
+ {
+ if (!windows)
+ wtab = realloc(wtab, n * sizeof(struct win *));
+ maxwin = n;
+ }
break;
case RC_BACKTICK:
if (ParseBase(act, *args, &n, 10, "decimal"))
@@ -4005,6 +4171,21 @@ int key;
break;
#ifdef BLANKER_PRG
case RC_BLANKERPRG:
+ if (!args[0])
+ {
+ if (blankerprg)
+ {
+ char path[MAXPATHLEN];
+ char *p = path, **pp;
+ for (pp = blankerprg; *pp; pp++)
+ p += snprintf(p, sizeof(path) - (p - path) - 1, "%s ", *pp);
+ *(p - 1) = '\0';
+ Msg(0, "blankerprg: %s", path);
+ }
+ else
+ Msg(0, "No blankerprg set.");
+ break;
+ }
if (blankerprg)
{
char **pp;
@@ -4087,7 +4268,7 @@ int key;
if (args[0][0])
{
fore->w_group = WindowByName(*args);
- if (fore->w_group && fore->w_group->w_type != W_TYPE_GROUP)
+ if (fore->w_group == fore || (fore->w_group && fore->w_group->w_type != W_TYPE_GROUP))
fore->w_group = 0;
}
WindowChanged((struct win *)0, 'w');
@@ -4122,6 +4303,11 @@ int key;
{
int old;
struct layout *lay;
+ if (!D_layout)
+ {
+ Msg(0, "not on a layout");
+ break;
+ }
if (!args[1])
{
Msg(0, "This is layout %d (%s).\n", D_layout->lay_number, D_layout->lay_title);
@@ -4285,6 +4471,15 @@ int key;
if (lay)
RemoveLayout(lay);
}
+ else if (!strcmp(args[0], "dump"))
+ {
+ if (!display)
+ Msg(0, "Must have a display for 'layout dump'.");
+ else if (!LayoutDumpCanvas(&D_canvas, args[1] ? args[1] : "layout-dump"))
+ Msg(errno, "Error dumping layout.");
+ else
+ Msg(0, "Layout dumped to \"%s\"", args[1] ? args[1] : "layout-dump");
+ }
else
Msg(0, "unknown layout subcommand");
break;
@@ -4366,14 +4561,27 @@ char **argv;
int *argl;
{
struct action act;
+ const char *cmd = *argv;
+
+ act.quiet = 0;
+ if (*cmd == '@') /* Suppress error */
+ {
+ act.quiet |= 0x01;
+ cmd++;
+ }
+ if (*cmd == '-') /* Suppress normal message */
+ {
+ act.quiet |= 0x02;
+ cmd++;
+ }
/* Alias? */
- if (DoAlias(*argv, argv + 1, argl + 1))
+ if (DoAlias(cmd, argv + 1, argl + 1))
return;
- if ((act.nr = FindCommnr(*argv)) == RC_ILLEGAL)
+ if ((act.nr = FindCommnr(cmd)) == RC_ILLEGAL)
{
- Msg(0, "%s: unknown command '%s'", rc_name, *argv);
+ Msg(0, "%s: unknown command '%s'", rc_name, cmd);
return;
}
act.args = argv + 1;
@@ -4403,9 +4611,9 @@ int *argl;
return;
}
if ((pp = (char **)malloc((unsigned)(argc + 1) * sizeof(char **))) == 0)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
if ((lp = (int *)malloc((unsigned)(argc) * sizeof(int *))) == 0)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
act->nr = nr;
act->args = pp;
act->argl = lp;
@@ -4427,7 +4635,7 @@ char **args;
while (args[argc])
argc++;
if ((pp = ap = (char **)malloc((unsigned)(argc + 1) * sizeof(char **))) == 0)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
while (argc--)
*pp++ = SaveStr(*args++);
*pp = 0;
@@ -4459,6 +4667,7 @@ int bufl, *argl;
delim = 0;
for (;;)
{
+ *lp = 0;
while (*p && (*p == ' ' || *p == '\t'))
++p;
#ifdef PSEUDOS
@@ -4491,7 +4700,7 @@ int bufl, *argl;
{
if (*p == delim)
delim = 0;
- else if (delim != '\'' && *p == '\\' && (p[1] == '\'' || p[1] == '"' || p[1] == '\\' || p[1] == '$' || p[1] == '#' || p[1] == '^' || (p[1] >= '0' && p[1] <= '7')))
+ else if (delim != '\'' && *p == '\\' && (p[1] == 'n' || p[1] == 'r' || p[1] == 't' || p[1] == '\'' || p[1] == '"' || p[1] == '\\' || p[1] == '$' || p[1] == '#' || p[1] == '^' || (p[1] >= '0' && p[1] <= '7')))
{
p++;
if (*p >= '0' && *p <= '7')
@@ -4510,7 +4719,16 @@ int bufl, *argl;
pp++;
}
else
- *pp++ = *p;
+ {
+ switch (*p)
+ {
+ case 'n': *pp = '\n'; break;
+ case 'r': *pp = '\r'; break;
+ case 't': *pp = '\t'; break;
+ default: *pp = *p; break;
+ }
+ pp++;
+ }
}
else if (delim != '\'' && *p == '$' && (p[1] == '{' || p[1] == ':' || (p[1] >= 'a' && p[1] <= 'z') || (p[1] >= 'A' && p[1] <= 'Z') || (p[1] >= '0' && p[1] <= '9') || p[1] == '_'))
@@ -4557,6 +4775,15 @@ int bufl, *argl;
sprintf(xbuf, "%d", display ? D_width : -1);
else if (!strcmp(ps, "LINES"))
sprintf(xbuf, "%d", display ? D_height : -1);
+ else if (!strcmp(ps, "PID"))
+ sprintf(xbuf, "%d", getpid());
+ else if (!strcmp(ps, "STY"))
+ {
+ if ((v = strchr(SockName, '.'))) /* Skip the PID */
+ v++;
+ else
+ v = SockName;
+ }
else
v = getenv(ps);
}
@@ -4828,7 +5055,7 @@ char *str;
int i;
struct win *p;
- if ((i = WindowByNumber(str)) < 0 || i >= MAXWIN)
+ if ((i = WindowByNumber(str)) < 0 || i >= maxwin)
{
if ((p = WindowByName(str)))
return p->w_number;
@@ -4933,7 +5160,7 @@ int n;
struct win *p;
debug1("SwitchWindow %d\n", n);
- if (n < 0 || n >= MAXWIN)
+ if (n < 0 || n >= maxwin)
{
ShowWindows(-1);
return;
@@ -4964,118 +5191,6 @@ int n;
Activate(fore->w_norefresh);
}
-
-void
-SetCanvasWindow(cv, wi)
-struct canvas *cv;
-struct win *wi;
-{
- struct win *p = 0, **pp;
- struct layer *l;
- struct canvas *cvp, **cvpp;
-
- l = cv->c_layer;
- display = cv->c_display;
-
- if (l)
- {
- /* remove old layer */
- for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
- if (cvp == cv)
- break;
- ASSERT(cvp);
- *cvpp = cvp->c_lnext;
-
- p = Layer2Window(l);
- l = cv->c_layer;
- cv->c_layer = 0;
-
- if (p && cv == D_forecv)
- {
-#ifdef MULTIUSER
- ReleaseAutoWritelock(display, p);
-#endif
- if (p->w_silence)
- {
- SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
- evenq(&p->w_silenceev);
- }
- D_other = fore;
- D_fore = 0;
- }
- if (l->l_cvlist == 0 && (p == 0 || l != p->w_savelayer))
- KillLayerChain(l);
- }
-
- /* find right layer to display on canvas */
- if (wi && wi->w_type != W_TYPE_GROUP)
- {
- l = &wi->w_layer;
- if (wi->w_savelayer && (wi->w_blocked || wi->w_savelayer->l_cvlist == 0))
- l = wi->w_savelayer;
- }
- else
- {
- l = &cv->c_blank;
- if (wi)
- l->l_data = (char *)wi;
- else
- l->l_data = 0;
- }
-
- /* add our canvas to the layer's canvaslist */
- ASSERT(l->l_cvlist != cv);
- cv->c_lnext = l->l_cvlist;
- l->l_cvlist = cv;
- cv->c_layer = l;
- cv->c_xoff = cv->c_xs;
- cv->c_yoff = cv->c_ys;
- RethinkViewportOffsets(cv);
-
- if (flayer == 0)
- flayer = l;
-
- if (wi && wi->w_type == W_TYPE_GROUP)
- {
- /* auto-start windowlist on groups */
- struct display *d = display;
- struct layer *oldflayer = flayer;
- flayer = l;
- display_wlist(0, 0, wi);
- flayer = oldflayer;
- display = d;
- }
-
- if (wi && D_other == wi)
- D_other = wi->w_next; /* Might be 0, but that's OK. */
- if (cv == D_forecv)
- {
- D_fore = wi;
- fore = D_fore; /* XXX ? */
- if (wi)
- {
-#ifdef MULTIUSER
- ObtainAutoWritelock(display, wi);
-#endif
- /*
- * Place the window at the head of the most-recently-used list
- */
- if (windows != wi)
- {
- for (pp = &windows; (p = *pp); pp = &p->w_next)
- if (p == wi)
- break;
- ASSERT(p);
- *pp = p->w_next;
- p->w_next = windows;
- windows = p;
- WListLinkChanged();
- }
- }
- }
-}
-
-
/*
* SetForeWindow changes the window in the input focus of the display.
* Puts window wi in canvas display->d_forecv.
@@ -5149,12 +5264,12 @@ static int
NextWindow()
{
register struct win **pp;
- int n = fore ? fore->w_number : MAXWIN;
+ int n = fore ? fore->w_number : maxwin;
struct win *group = fore ? fore->w_group : 0;
for (pp = fore ? wtab + n + 1 : wtab; pp != wtab + n; pp++)
{
- if (pp == wtab + MAXWIN)
+ if (pp == wtab + maxwin)
pp = wtab;
if (*pp)
{
@@ -5177,7 +5292,7 @@ PreviousWindow()
for (pp = wtab + n - 1; pp != wtab + n; pp--)
{
if (pp == wtab - 1)
- pp = wtab + MAXWIN - 1;
+ pp = wtab + maxwin - 1;
if (*pp)
{
if (!fore || group == (*pp)->w_group)
@@ -5204,36 +5319,6 @@ MoreWindows()
return 0;
}
-static void
-UpdateLayoutCanvas(cv, wi)
-struct canvas *cv;
-struct win *wi;
-{
- for (; cv; cv = cv->c_slnext)
- {
- if (cv->c_layer && Layer2Window(cv->c_layer) == wi)
- {
- /* A simplistic version of SetCanvasWindow(cv, 0) */
- struct layer *l = cv->c_layer;
- cv->c_layer = 0;
- if (l->l_cvlist == 0 && (wi == 0 || l != wi->w_savelayer))
- KillLayerChain(l);
- l = &cv->c_blank;
- l->l_data = 0;
- if (l->l_cvlist != cv)
- {
- cv->c_lnext = l->l_cvlist;
- l->l_cvlist = cv;
- }
- cv->c_layer = l;
- /* Do not end here. Multiple canvases can have the same window */
- }
-
- if (cv->c_slperp)
- UpdateLayoutCanvas(cv->c_slperp, wi);
- }
-}
-
void
KillWindow(wi)
struct win *wi;
@@ -5342,15 +5427,21 @@ int where;
int l;
s = ss = buf;
- for (pp = ((flags & 4) && where >= 0) ? wtab + where + 1: wtab; pp < wtab + MAXWIN; pp++)
+ if ((flags & 8) && where < 0)
{
+ *s = 0;
+ return ss;
+ }
+ for (pp = ((flags & 4) && where >= 0) ? wtab + where + 1: wtab; pp < wtab + maxwin; pp++)
+ {
+ int rend = -1;
if (pp - wtab == where && ss == buf)
- ss = s;
+ ss = s;
if ((p = *pp) == 0)
continue;
if ((flags & 1) && display && p == D_fore)
continue;
- if (D_fore && D_fore->w_group != p->w_group)
+ if (display && D_fore && D_fore->w_group != p->w_group)
continue;
cmd = p->w_title;
@@ -5364,9 +5455,24 @@ int where;
*s++ = ' ';
*s++ = ' ';
}
- sprintf(s, "%d", p->w_number);
if (p->w_number == where)
- ss = s;
+ {
+ ss = s;
+ if (flags & 8)
+ break;
+ }
+ if (!(flags & 4) || where < 0 || ((flags & 4) && where < p->w_number))
+ {
+ if (p->w_monitor == MON_DONE && renditions[REND_MONITOR] != -1)
+ rend = renditions[REND_MONITOR];
+ else if ((p->w_bell == BELL_DONE || p->w_bell == BELL_FOUND) && renditions[REND_BELL] != -1)
+ rend = renditions[REND_BELL];
+ else if ((p->w_silence == SILENCE_FOUND || p->w_silence == SILENCE_DONE) && renditions[REND_SILENCE] != -1)
+ rend = renditions[REND_SILENCE];
+ }
+ if (rend != -1)
+ AddWinMsgRend(s, rend);
+ sprintf(s, "%d", p->w_number);
s += strlen(s);
if (display && p == D_fore)
*s++ = '*';
@@ -5379,6 +5485,8 @@ int where;
*s++ = ' ';
strncpy(s, cmd, l);
s += l;
+ if (rend != -1)
+ AddWinMsgRend(s, -1);
}
*s = 0;
return ss;
@@ -5477,13 +5585,11 @@ int where;
char buf[1024];
char *s, *ss;
- if (!display)
- return;
- if (where == -1 && D_fore)
+ if (display && where == -1 && D_fore)
where = D_fore->w_number;
ss = AddWindows(buf, sizeof(buf), 0, where);
s = buf + strlen(buf);
- if (ss - buf > D_width / 2)
+ if (display && ss - buf > D_width / 2)
{
ss -= D_width / 2;
if (s - ss < D_width)
@@ -5963,7 +6069,7 @@ char *fn, **av;
if (*buf != '\0')
nwin.aka = buf;
num = atoi(*av);
- if (num < 0 || num > MAXWIN - 1)
+ if (num < 0 || (maxwin && num > maxwin - 1) || (!maxwin && num > MAXWIN - 1))
{
Msg(0, "%s: illegal screen number %d.", fn, num);
num = 0;
@@ -6080,7 +6186,7 @@ char *data; /* dummy */
{
if ((pp->buf = (char *)malloc(D_user->u_plop.len)) == NULL)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return;
}
bcopy(D_user->u_plop.buf, pp->buf, D_user->u_plop.len);
@@ -6155,6 +6261,7 @@ char *data;
act.nr = *(int *)data;
act.args = noargs;
act.argl = 0;
+ act.quiet = 0;
DoAction(&act, -1);
}
@@ -6286,7 +6393,7 @@ char *data;
#endif
if (!(u->u_plop.buf = SaveStr(u->u_password)))
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
D_user->u_plop.len = 0;
}
else
@@ -6298,6 +6405,18 @@ char *data;
}
#endif /* PASSWORD */
+static int
+digraph_find(buf)
+const char *buf;
+{
+ int i;
+ for (i = 0; i < MAX_DIGRAPH && digraphs[i].d[0]; i++)
+ if ((digraphs[i].d[0] == (unsigned char)buf[0] && digraphs[i].d[1] == (unsigned char)buf[1]) ||
+ (digraphs[i].d[0] == (unsigned char)buf[1] && digraphs[i].d[1] == (unsigned char)buf[0]))
+ break;
+ return i;
+}
+
static void
digraph_fn(buf, len, data)
char *buf;
@@ -6349,43 +6468,14 @@ char *data; /* dummy */
}
if (len < 2)
return;
- if (len >= 1 && ((*buf == 'U' && buf[1] == '+') || (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X'))))
- {
- x = 0;
- for (i = 2; i < len; i++)
- {
- if (buf[i] >= '0' && buf[i] <= '9')
- x = x * 16 | (buf[i] - '0');
- else if (buf[i] >= 'a' && buf[i] <= 'f')
- x = x * 16 | (buf[i] - ('a' - 10));
- else if (buf[i] >= 'A' && buf[i] <= 'F')
- x = x * 16 | (buf[i] - ('A' - 10));
- else
- break;
- }
- }
- else if (buf[0] == '0')
+ if (!parse_input_int(buf, len, &x))
{
- x = 0;
- for (i = 1; i < len; i++)
- {
- if (buf[i] < '0' || buf[i] > '7')
- break;
- x = x * 8 | (buf[i] - '0');
- }
- }
- else
- {
- for (i = 0; i < (int)(sizeof(digraphs)/sizeof(*digraphs)); i++)
- if ((digraphs[i][0] == (unsigned char)buf[0] && digraphs[i][1] == (unsigned char)buf[1]) ||
- (digraphs[i][0] == (unsigned char)buf[1] && digraphs[i][1] == (unsigned char)buf[0]))
- break;
- if (i == (int)(sizeof(digraphs)/sizeof(*digraphs)))
+ i = digraph_find(buf);
+ if ((x = digraphs[i].value) <= 0)
{
Msg(0, "Unknown digraph");
return;
}
- x = digraphs[i][2];
}
i = 1;
*buf = x;
@@ -6432,7 +6522,7 @@ int i;
fore = D_fore;
act = 0;
#ifdef COPY_PASTE
- if (InMark() || InInput() || InWList())
+ if (flayer && flayer->l_mode == 1)
act = i < KMAP_KEYS+KMAP_AKEYS ? &mmtab[i] : &kmap_exts[i - (KMAP_KEYS+KMAP_AKEYS)].mm;
#endif
if ((!act || act->nr == RC_ILLEGAL) && !D_mapdefault)
@@ -7051,6 +7141,49 @@ char *data;
buf[len] = '\034';
}
+void
+SetForeCanvas(d, cv)
+struct display *d;
+struct canvas *cv;
+{
+ struct display *odisplay = display;
+ if (d->d_forecv == cv)
+ return;
+
+ display = d;
+ D_forecv = cv;
+ if ((focusminwidth && (focusminwidth < 0 || D_forecv->c_xe - D_forecv->c_xs + 1 < focusminwidth)) ||
+ (focusminheight && (focusminheight < 0 || D_forecv->c_ye - D_forecv->c_ys + 1 < focusminheight)))
+ {
+ ResizeCanvas(&D_canvas);
+ RecreateCanvasChain();
+ RethinkDisplayViewports();
+ ResizeLayersToCanvases(); /* redisplays */
+ }
+ fore = D_fore = Layer2Window(D_forecv->c_layer);
+ if (D_other == fore)
+ D_other = 0;
+ flayer = D_forecv->c_layer;
+#ifdef RXVT_OSC
+ if (D_xtermosc[2] || D_xtermosc[3])
+ {
+ Activate(-1);
+ }
+ else
+#endif
+ {
+ RefreshHStatus();
+#ifdef RXVT_OSC
+ RefreshXtermOSC();
+#endif
+ flayer = D_forecv->c_layer;
+ CV_CALL(D_forecv, LayRestore();LaySetCursor());
+ WindowChanged(0, 'F');
+ }
+
+ display = odisplay;
+}
+
#ifdef RXVT_OSC
void
RefreshXtermOSC()
diff --git a/src/pty.c b/src/pty.c
index 6a6bdd6..def7f93 100644
--- a/src/pty.c
+++ b/src/pty.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/putenv.c b/src/putenv.c
index f2c18df..2a907f9 100644
--- a/src/putenv.c
+++ b/src/putenv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/resize.c b/src/resize.c
index a9a8772..5d1df4b 100644
--- a/src/resize.c
+++ b/src/resize.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -323,6 +323,34 @@ kaablamm()
Msg(0, "Aborted because of window size change.");
}
+/* Kills non-resizable layers. */
+#define RESIZE_OR_KILL_LAYERS(l, wi, he) do \
+ { \
+ struct layer *_last = NULL, *_iter; \
+ flayer = (l); \
+ while (flayer->l_next) \
+ { \
+ if (LayResize(wi, he) == 0) \
+ { \
+ _last = flayer; \
+ flayer = flayer->l_next; \
+ } \
+ else \
+ { \
+ struct canvas *_cv; \
+ for (_cv = flayer->l_cvlist; _cv; _cv = _cv->c_lnext) \
+ _cv->c_display->d_kaablamm = 1; \
+ ExitOverlayPage(); \
+ if (_last) \
+ _last->l_next = flayer; \
+ } \
+ } \
+ /* We assume that the bottom-most layer, i.e. when flayer->l_next == 0, \
+ * is always resizable. Currently, WinLf and BlankLf can be the bottom-most layers. \
+ */ \
+ LayResize(wi, he); \
+ } while (0)
+
void
ResizeLayer(l, wi, he, norefdisp)
struct layer *l;
@@ -338,52 +366,39 @@ struct display *norefdisp;
return;
p = Layer2Window(l);
+ /* If 'flayer' and 'l' are for the same window, then we will not
+ * restore 'flayer'. */
if (oldflayer && (l == oldflayer || Layer2Window(oldflayer) == p))
- while (oldflayer->l_next)
- oldflayer = oldflayer->l_next;
-
+ oldflayer = NULL;
+
+ flayer = l;
+
if (p)
{
+ /* It's a window layer. Kill the overlays on it in all displays. */
for (d = displays; d; d = d->d_next)
for (cv = d->d_cvlist; cv; cv = cv->c_next)
{
if (p == Layer2Window(cv->c_layer))
{
- flayer = cv->c_layer;
- if (flayer->l_next)
- d->d_kaablamm = 1;
- while (flayer->l_next)
- ExitOverlayPage();
+ /* Canvas 'cv' on display 'd' shows this window. Remove any non-resizable
+ * layers over it. */
+ RESIZE_OR_KILL_LAYERS(cv->c_layer, wi, he);
}
}
- l = p->w_savelayer;
- }
- flayer = l;
- if (p == 0 && flayer->l_next && flayer->l_next->l_next == 0 && LayResize(wi, he) == 0)
- {
- flayer = flayer->l_next;
- LayResize(wi, he);
- flayer = l;
}
else
{
- if (flayer->l_next)
- for (cv = flayer->l_cvlist; cv; cv = cv->c_lnext)
- cv->c_display->d_kaablamm = 1;
- while (flayer->l_next)
- ExitOverlayPage();
+ /* It's a Blank layer. Just kill the non-resizable overlays over it. */
+ RESIZE_OR_KILL_LAYERS(flayer, wi, he);
}
- if (p)
- flayer = &p->w_layer;
- LayResize(wi, he);
- /* now everybody is on flayer, redisplay */
- l = flayer;
+
for (display = displays; display; display = display->d_next)
{
if (display == norefdisp)
continue;
for (cv = D_cvlist; cv; cv = cv->c_next)
- if (cv->c_layer == l)
+ if (Layer2Window(cv->c_layer) == p)
{
CV_CALL(cv, LayRedisplayLine(-1, -1, -1, 0));
RefreshArea(cv->c_xs, cv->c_ys, cv->c_xe, cv->c_ye, 0);
@@ -394,11 +409,14 @@ struct display *norefdisp;
D_kaablamm = 0;
}
}
- flayer = oldflayer;
+
+ /* If we started resizing a non-flayer layer, then restore the flayer.
+ * Otherwise, flayer should already be updated to the topmost foreground layer. */
+ if (oldflayer)
+ flayer = oldflayer;
display = olddisplay;
}
-
static void
FreeMline(ml)
struct mline *ml;
@@ -497,6 +515,7 @@ CheckMaxSize(wi)
int wi;
{
unsigned char *oldnull = null;
+ unsigned char *oldblank = blank;
struct win *p;
int i;
struct mline *ml;
@@ -516,11 +535,11 @@ int wi;
#ifdef COLOR
mline_old.color = (unsigned char *)xrealloc((char *)mline_old.color, maxwidth);
# ifdef COLORS256
- mline_old.colorx = (unsigned char *)xrealloc((char *)mline_old.color, maxwidth);
+ mline_old.colorx = (unsigned char *)xrealloc((char *)mline_old.colorx, maxwidth);
# endif
#endif
if (!(blank && null && mline_old.image && mline_old.attr IFFONT(&& mline_old.font) IFCOLOR(&& mline_old.color) IFCOLORX(&& mline_old.colorx)))
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
MakeBlankLine(blank, maxwidth);
bzero((char *)null, maxwidth);
@@ -542,49 +561,34 @@ int wi;
# endif
#endif
+#define RESET_AFC(x, bl) do { if (x == old##bl) x = bl; } while (0)
+
+#define RESET_LINES(lines, count) \
+ do { \
+ ml = lines; \
+ for (i = 0; i < count; i++, ml++) \
+ { \
+ RESET_AFC(ml->image, blank); \
+ RESET_AFC(ml->attr, null); \
+ IFFONT(RESET_AFC(ml->font, null)); \
+ IFCOLOR(RESET_AFC(ml->color, null)); \
+ IFCOLORX(RESET_AFC(ml->colorx, null)); \
+ } \
+ } while (0)
+
/* We have to run through all windows to substitute
- * the null references.
+ * the null and blank references.
*/
for (p = windows; p; p = p->w_next)
{
- ml = p->w_mlines;
- for (i = 0; i < p->w_height; i++, ml++)
- {
- if (ml->attr == oldnull)
- ml->attr = null;
-#ifdef FONT
- if (ml->font == oldnull)
- ml->font = null;
-#endif
-#ifdef COLOR
- if (ml->color == oldnull)
- ml->color= null;
-#ifdef COLORS256
- if (ml->colorx == oldnull)
- ml->colorx = null;
-#endif
-#endif
- }
+ RESET_LINES(p->w_mlines, p->w_height);
+
#ifdef COPY_PASTE
- ml = p->w_hlines;
- for (i = 0; i < p->w_histheight; i++, ml++)
- {
- if (ml->attr == oldnull)
- ml->attr = null;
-# ifdef FONT
- if (ml->font == oldnull)
- ml->font = null;
-# endif
-# ifdef COLOR
- if (ml->color == oldnull)
- ml->color= null;
-# ifdef COLORS256
- if (ml->colorx == oldnull)
- ml->colorx = null;
-# endif
-# endif
- }
+ RESET_LINES(p->w_hlines, p->w_histheight);
+ RESET_LINES(p->w_alt_hlines, p->w_alt_histheight);
#endif
+
+ RESET_LINES(p->w_alt_mlines, p->w_alt_height);
}
}
@@ -642,11 +646,32 @@ int wi, he, hi;
int ncx, ncy, naka, t;
int y, shift;
- if (wi == 0)
- he = hi = 0;
+ if (wi <= 0 || he <= 0)
+ wi = he = hi = 0;
if (p->w_type == W_TYPE_GROUP)
return 0;
+
+ if (wi > 1000)
+ {
+ Msg(0, "Window width too large. Truncated to 1000.");
+ wi = 1000;
+ }
+
+ if (he > 1000)
+ {
+ Msg(0, "Window height too large. Truncated to 1000.");
+ he = 1000;
+ }
+
+#ifdef COPY_PASTE
+ if (hi > 1000)
+ {
+ Msg(0, "Window history too big. Truncated to 1000.");
+ hi = 1000;
+ }
+#endif
+
if (p->w_width == wi && p->w_height == he && p->w_histheight == hi)
{
debug("ChangeWindowSize: No change.\n");
@@ -684,7 +709,7 @@ int wi, he, hi;
if ((nmlines = (struct mline *)calloc(he, sizeof(struct mline))) == 0)
{
KillWindow(p);
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return -1;
}
}
@@ -917,7 +942,7 @@ int wi, he, hi;
#endif
}
KillWindow(p);
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return -1;
}
for (; t < wi; t++)
@@ -1040,16 +1065,20 @@ struct win *p;
struct mline *ml;
int t;
- ml = p->w_alt_mlines; p->w_alt_mlines = p->w_mlines; p->w_mlines = ml;
- t = p->w_alt_width; p->w_alt_width = p->w_width; p->w_width = t;
- t = p->w_alt_height; p->w_alt_height = p->w_height; p->w_height = t;
- t = p->w_alt_histheight; p->w_alt_histheight = p->w_histheight; p->w_histheight = t;
- t = p->w_alt_x; p->w_alt_x = p->w_x; p->w_x = t;
- t = p->w_alt_y; p->w_alt_y = p->w_y; p->w_y = t;
+#define SWAP(item, t) do { (t) = p->w_alt_##item; p->w_alt_##item = p->w_##item; p->w_##item = (t); } while (0)
+
+ SWAP(mlines, ml);
+ SWAP(width, t);
+ SWAP(height, t);
+ SWAP(histheight, t);
+ SWAP(x, t);
+ SWAP(y, t);
+
#ifdef COPY_PASTE
- ml = p->w_alt_hlines; p->w_alt_hlines = p->w_hlines; p->w_hlines = ml;
- t = p->w_alt_histidx; p->w_alt_histidx = p->w_histidx; p->w_histidx = t;
+ SWAP(hlines, ml);
+ SWAP(histidx, t);
#endif
+#undef SWAP
}
void
@@ -1057,20 +1086,34 @@ EnterAltScreen(p)
struct win *p;
{
int ox = p->w_x, oy = p->w_y;
- FreeAltScreen(p);
- SwapAltScreen(p);
+ if (!p->w_alt_current)
+ {
+ /* If not already using the alternate screen buffer, then create
+ a new one and swap it with the 'real' screen buffer. */
+ FreeAltScreen(p);
+ SwapAltScreen(p);
+ }
+ else
+ {
+ /* Already using the alternate buffer. Just clear the screen. To do so, it
+ is only necessary to reset the height(s) without resetting the width. */
+ p->w_height = 0;
+ p->w_histheight = 0;
+ }
ChangeWindowSize(p, p->w_alt_width, p->w_alt_height, p->w_alt_histheight);
p->w_x = ox;
p->w_y = oy;
+ p->w_alt_current = 1;
}
void
LeaveAltScreen(p)
struct win *p;
{
- if (!p->w_alt_mlines)
+ if (!p->w_alt_current)
return;
SwapAltScreen(p);
ChangeWindowSize(p, p->w_alt_width, p->w_alt_height, p->w_alt_histheight);
FreeAltScreen(p);
+ p->w_alt_current = 0;
}
diff --git a/src/sched.c b/src/sched.c
index 74e1afd..c2e00df 100644
--- a/src/sched.c
+++ b/src/sched.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/sched.h b/src/sched.h
index 5160d9c..fdc3fc4 100644
--- a/src/sched.h
+++ b/src/sched.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
struct event
diff --git a/src/screen.c b/src/screen.c
index 7239560..5c15a39 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -1,4 +1,7 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -118,6 +121,8 @@ int VBellWait, MsgWait, MsgMinWait, SilenceWait;
extern struct acluser *users;
extern struct display *displays, *display;
+extern struct LayFuncs MarkLf;
+
extern int visual_bell;
#ifdef COPY_PASTE
@@ -205,6 +210,7 @@ char *wlisttit;
int auto_detach = 1;
int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag;
int cmdflag;
+int queryflag = -1;
int adaptflag;
#ifdef MULTIUSER
@@ -235,7 +241,7 @@ int cjkwidth;
#ifdef NETHACK
int nethackflag = 0;
#endif
-int maxwin = MAXWIN;
+int maxwin;
struct layer *flayer;
@@ -463,10 +469,10 @@ char **av;
screenlogfile = SaveStr("screenlog.%n");
logtstamp_string = SaveStr("-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n");
hstatusstring = SaveStr("%h");
- captionstring = SaveStr("%3n %t");
+ captionstring = SaveStr("%4n %t");
timestring = SaveStr("%c:%s %M %d %H%? %l%?");
- wlisttit = SaveStr("Num Name%=Flags");
- wliststr = SaveStr("%3n %t%=%f");
+ wlisttit = SaveStr(" Num Name%=Flags");
+ wliststr = SaveStr("%4n %t%=%f");
#ifdef COPY_PASTE
BufferFile = SaveStr(DEFAULT_BUFFERFILE);
#endif
@@ -678,6 +684,10 @@ char **av;
case 'q':
quietflag = 1;
break;
+ case 'Q':
+ queryflag = 1;
+ cmdflag = 1;
+ break;
case 'r':
case 'R':
#ifdef MULTI
@@ -757,17 +767,12 @@ char **av;
real_gid = getgid();
eff_uid = geteuid();
eff_gid = getegid();
- if (eff_uid != real_uid)
- {
- /* if running with s-bit, we must install a special signal
- * handler routine that resets the s-bit, so that we get a
- * core file anyway.
- */
+
#ifdef SIGBUS /* OOPS, linux has no bus errors! */
- signal(SIGBUS, CoreDump);
+ signal(SIGBUS, CoreDump);
#endif /* SIGBUS */
- signal(SIGSEGV, CoreDump);
- }
+ signal(SIGSEGV, CoreDump);
+
#ifdef USE_LOCALE
setlocale(LC_ALL, "");
@@ -813,7 +818,7 @@ char **av;
size_t newsz;
char *newbuf = malloc(3 * len);
if (!newbuf)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
newsz = RecodeBuf(nwin_options.aka, len,
nwin_options.encoding, 0, newbuf);
newbuf[newsz] = '\0';
@@ -1076,7 +1081,7 @@ char **av;
else
{
SockDir = SOCKDIR;
- if (lstat(SockDir, &st))
+ if (stat(SockDir, &st))
{
n = (eff_uid == 0 && (real_uid || eff_gid == real_gid)) ? 0755 :
(eff_gid != real_gid) ? 0775 :
@@ -1174,7 +1179,7 @@ char **av;
if (!*av)
Panic(0, "Please specify a command.");
SET_GUID();
- SendCmdMessage(sty, SockMatch, av);
+ SendCmdMessage(sty, SockMatch, av, queryflag >= 0);
exit(0);
}
else if (rflag || xflag)
@@ -1414,8 +1419,13 @@ char **av;
debug("We open one default window, as screenrc did not specify one.\n");
if (MakeWindow(&nwin) == -1)
{
- Msg(0, "Sorry, could not find a PTY.");
- sleep(5);
+ fd_set rfd;
+ struct timeval tv = { MsgWait/1000, 1000*(MsgWait%1000) };
+ FD_SET(0, &rfd);
+
+ Msg(0, "Sorry, could not find a PTY or TTY.");
+ // allow user to exit early by pressing any key.
+ select(1, &rfd, NULL, NULL, &tv);
Finit(0);
/* NOTREACHED */
}
@@ -1468,6 +1478,26 @@ int wstat_valid;
{
int killit = 0;
+ if (p->w_destroyev.data == (char *)p)
+ {
+ wstat = p->w_exitstatus;
+ wstat_valid = 1;
+ evdeq(&p->w_destroyev);
+ p->w_destroyev.data = 0;
+ }
+
+#if defined(BSDJOBS) && !defined(BSDWAIT)
+ if (!wstat_valid && p->w_pid > 0)
+ {
+ /* EOF on file descriptor. The process is probably also dead.
+ * try a waitpid */
+ if (waitpid(p->w_pid, &wstat, WNOHANG | WUNTRACED) == p->w_pid)
+ {
+ p->w_pid = 0;
+ wstat_valid = 1;
+ }
+ }
+#endif
if (ZombieKey_destroy && ZombieKey_onerror && wstat_valid &&
WIFEXITED(wstat) && WEXITSTATUS(wstat) == 0)
killit = 1;
@@ -1604,39 +1634,55 @@ SigInt SIGDEFARG
static sigret_t
CoreDump SIGDEFARG
{
+ /* if running with s-bit, we must reset the s-bit, so that we get a
+ * core file anyway.
+ */
+
struct display *disp;
char buf[80];
+ char *dump_msg = " (core dumped)";
+
+ int running_w_s_bit = getuid() != geteuid();
+#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
+ if (running_w_s_bit)
+ dump_msg = "";
+#endif
+
#if defined(SYSVSIGS) && defined(SIGHASARG)
signal(sigsig, SIG_IGN);
#endif
setgid(getgid());
setuid(getuid());
unlink("core");
+
#ifdef SIGHASARG
- sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sigsig,
+ sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sigsig, dump_msg);
#else
- sprintf(buf, "\r\n[screen caught a fatal signal.%s]\r\n",
+ sprintf(buf, "\r\n[screen caught a fatal signal.%s]\r\n", dump_msg);
#endif
-#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
- ""
-#else /* SHADOWPW && !DEBUG */
- " (core dumped)"
-#endif /* SHADOWPW && !DEBUG */
- );
+
for (disp = displays; disp; disp = disp->d_next)
{
+ if (disp->d_nonblock < -1 || disp->d_nonblock > 1000000)
+ continue;
fcntl(disp->d_userfd, F_SETFL, 0);
SetTTY(disp->d_userfd, &D_OldMode);
write(disp->d_userfd, buf, strlen(buf));
Kill(disp->d_userpid, SIG_BYE);
}
+
+ if (running_w_s_bit)
+ {
#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
- Kill(getpid(), SIGKILL);
- eexit(11);
+ Kill(getpid(), SIGKILL);
+ eexit(11);
#else /* SHADOWPW && !DEBUG */
- abort();
+ abort();
#endif /* SHADOWPW && !DEBUG */
+ }
+ else
+ abort();
SIGRETURN;
}
@@ -1708,7 +1754,16 @@ DoWait()
else
#endif
{
- WindowDied(p, wstat, 1);
+ /* Screen will detect the window has died when the window's
+ * file descriptor signals EOF (which it will do when the process in
+ * the window terminates). So do this in a timeout of 10 seconds.
+ * (not doing this at all might also work)
+ * See #27061 for more details.
+ */
+ p->w_destroyev.data = (char *)p;
+ p->w_exitstatus = wstat;
+ SetTimeout(&p->w_destroyev, 10 * 1000);
+ evenq(&p->w_destroyev);
}
break;
}
@@ -1776,7 +1831,7 @@ int i;
RestoreLoginSlot();
#endif
AddStr("[screen is terminating]\r\n");
- Flush();
+ Flush(3);
SetTTY(D_userfd, &D_OldMode);
fcntl(D_userfd, F_SETFL, 0);
freetty();
@@ -1997,7 +2052,7 @@ MakeNewEnv()
free((char *)NewEnv);
NewEnv = np = (char **) malloc((unsigned) (op - environ + 7 + 1) * sizeof(char **));
if (!NewEnv)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
sprintf(stybuf, "STY=%s", strlen(SockName) <= MAXSTR - 5 ? SockName : "?");
*np++ = stybuf; /* NewEnv[0] */
*np++ = Term; /* NewEnv[1] */
@@ -2023,11 +2078,11 @@ MakeNewEnv()
void
/*VARARGS2*/
#if defined(USEVARARGS) && defined(__STDC__)
-Msg(int err, char *fmt, VA_DOTS)
+Msg(int err, const char *fmt, VA_DOTS)
#else
Msg(err, fmt, VA_DOTS)
int err;
-char *fmt;
+const char *fmt;
VA_DECL
#endif
{
@@ -2069,6 +2124,9 @@ VA_DECL
}
else
printf("%s\r\n", buf);
+
+ if (queryflag >= 0)
+ write(queryflag, buf, strlen(buf));
}
/*
@@ -2077,11 +2135,11 @@ VA_DECL
void
/*VARARGS2*/
#if defined(USEVARARGS) && defined(__STDC__)
-Panic(int err, char *fmt, VA_DOTS)
+Panic(int err, const char *fmt, VA_DOTS)
#else
Panic(err, fmt, VA_DOTS)
int err;
-char *fmt;
+const char *fmt;
VA_DECL
#endif
{
@@ -2125,7 +2183,7 @@ VA_DECL
if (D_status)
RemoveStatus();
FinitTerm();
- Flush();
+ Flush(3);
#ifdef UTMPOK
RestoreLoginSlot();
#endif
@@ -2168,7 +2226,7 @@ static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
#endif
static char winmsg_buf[MAXSTR];
-#define MAX_WINMSG_REND 16 /* rendition changes */
+#define MAX_WINMSG_REND 256 /* rendition changes */
static int winmsg_rend[MAX_WINMSG_REND];
static int winmsg_rendpos[MAX_WINMSG_REND];
static int winmsg_numrend;
@@ -2331,7 +2389,7 @@ char **cmdv;
bt = (struct backtick *)malloc(sizeof *bt);
if (!bt)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return;
}
bzero(bt, sizeof(*bt));
@@ -2353,7 +2411,7 @@ char **cmdv;
bt->buf = (char *)malloc(MAXSTR);
if (bt->buf == 0)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
setbacktick(num, 0, 0, (char **)0);
return;
}
@@ -2417,6 +2475,22 @@ time_t now;
return bt->result;
}
+int
+AddWinMsgRend(str, r)
+const char *str;
+int r;
+{
+ if (winmsg_numrend >= MAX_WINMSG_REND || str < winmsg_buf ||
+ str >= winmsg_buf + MAXSTR)
+ return -1;
+
+ winmsg_rend[winmsg_numrend] = r;
+ winmsg_rendpos[winmsg_numrend] = str - winmsg_buf;
+ winmsg_numrend++;
+
+ return 0;
+}
+
char *
MakeWinMsgEv(str, win, esc, padlen, ev, rec)
char *str;
@@ -2672,9 +2746,7 @@ int rec;
oldfore = D_fore;
D_fore = win;
}
- ss = AddWindows(p, l - 1, (*s == 'w' ? 0 : 1) | (longflg ? 0 : 2) | (plusflg ? 4 : 0), win ? win->w_number : -1);
- if (minusflg)
- *ss = 0;
+ ss = AddWindows(p, l - 1, (*s == 'w' ? 0 : 1) | (longflg ? 0 : 2) | (plusflg ? 4 : 0) | (minusflg ? 8 : 0), win ? win->w_number : -1);
if (display)
D_fore = oldfore;
}
@@ -2773,6 +2845,18 @@ int rec;
if (minusflg)
qmflag = 1;
break;
+ case 'P':
+ p--;
+#ifdef COPY_PASTE
+ if (display && ev && ev != &D_hstatusev) /* Hack */
+ {
+ /* Is the layer in the current canvas in copy mode? */
+ struct canvas *cv = (struct canvas *)ev->data;
+ if (ev == &cv->c_captev && cv->c_layer->l_layfn == &MarkLf)
+ qmflag = 1;
+ }
+#endif
+ break;
case '>':
truncpos = p - winmsg_buf;
truncper = num > 100 ? 100 : num;
@@ -3157,6 +3241,15 @@ char *data;
}
WindowChanged(p, 'f');
}
+ if (p->w_silence == SILENCE_FOUND)
+ {
+ /* Unset the flag if the user switched to this window. */
+ if (p->w_layer.l_cvlist)
+ {
+ p->w_silence = SILENCE_ON;
+ WindowChanged(p, 'f');
+ }
+ }
}
for (display = displays; display; display = display->d_next)
diff --git a/src/screen.h b/src/screen.h
index c0fdecb..5c93f32 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,7 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
#include "os.h"
@@ -146,6 +146,7 @@ struct mode
/* #include "logfile.h" */ /* (requires stat.h) struct logfile */
#include "image.h"
+#include "canvas.h"
#include "display.h"
#include "window.h"
@@ -172,13 +173,18 @@ struct mode
#define MSG_WINCH 6
#define MSG_HANGUP 7
#define MSG_COMMAND 8
+#define MSG_QUERY 9
/*
* versions of struct msg:
* 0: screen version 3.6.6 (version count introduced)
- * 1: screen version 4.1.0
+ * 1: screen version 4.1.0devel (revisions e3fc19a upto 8147d08)
+ * A few revisions after 8147d08 incorrectly
+ * carried version 1, but should have carried 2.
+ * 2: screen version 4.1.0devel (revisions 8b46d8a upto YYYYYYY)
*/
-#define MSG_VERSION 1
+#define MSG_VERSION 2
+
#define MSG_REVISION (('m'<<24) | ('s'<<16) | ('g'<<8) | MSG_VERSION)
struct msg
{
@@ -226,6 +232,8 @@ struct msg
char cmd[MAXPATHLEN]; /* command */
int apid; /* pid of frontend */
char preselect[20];
+ char writeback[MAXPATHLEN]; /* The socket to write the result.
+ Only used for MSG_QUERY */
}
command;
char message[MAXPATHLEN * 2];
@@ -248,7 +256,7 @@ struct msg
#define VBELLWAIT 1 /* No. of seconds a vbell will be displayed */
#define BELL_ON 0 /* No bell has occurred in the window */
-#define BELL_FOUND 1 /* A bell has occurred, but user not yet notified */
+#define BELL_FOUND 1 /* A bell has occurred, but user not yet notified */
#define BELL_DONE 2 /* A bell has occured, user has been notified */
#define BELL_VISUAL 3 /* A bell has occured in fore win, notify him visually */
@@ -263,8 +271,10 @@ struct msg
#define DUMP_EXCHANGE 2
#define DUMP_SCROLLBACK 3
-#define SILENCE_OFF 0
-#define SILENCE_ON 1
+#define SILENCE_OFF 0 /* Not checking for silence */
+#define SILENCE_ON 1 /* Window being monitored for silence */
+#define SILENCE_FOUND 2 /* Window is silent */
+#define SILENCE_DONE 3 /* Window is silent and user is notified */
extern char strnomem[];
diff --git a/src/search.c b/src/search.c
index 965dfe9..cd2693e 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/socket.c b/src/socket.c
index 48e8ad9..9dbf461 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -49,6 +49,7 @@
#endif
#include "extern.h"
+#include "list_generic.h"
static int CheckPid __P((int));
static void ExecCreate __P((struct msg *));
@@ -65,15 +66,17 @@ static void AskPassword __P((struct msg *));
extern char *RcFileName, *extra_incap, *extra_outcap;
extern int ServerSocket, real_uid, real_gid, eff_uid, eff_gid;
extern int dflag, iflag, rflag, lsflag, quietflag, wipeflag, xflag;
+extern int queryflag;
extern char *attach_tty, *LoginName, HostName[];
extern struct display *display, *displays;
-extern struct win *fore, *wtab[], *console_window, *windows;
+extern struct win *fore, **wtab, *console_window, *windows;
extern struct layer *flayer;
extern struct layout *layout_attach, *layout_last, layout_last_marker;
extern struct NewWindow nwin_undef;
#ifdef MULTIUSER
extern char *multi;
#endif
+extern int maxwin;
extern char *getenv();
@@ -181,8 +184,21 @@ char *match;
if (strncmp(match, "tty", 3) && strncmp(n, "tty", 3) == 0)
n += 3;
if (strncmp(match, n, matchlen))
- continue;
- cmatch = (*(n + matchlen) == 0);
+ {
+ if (n == name && *match > '0' && *match <= '9')
+ {
+ while (*n >= '0' && *n <= '9')
+ n++;
+ if (*n == '.')
+ n++;
+ if (strncmp(match, n, matchlen))
+ continue;
+ }
+ else
+ continue;
+ }
+ else
+ cmatch = (*(n + matchlen) == 0);
debug1(" -> matched %s\n", match);
}
sprintf(SockPath + sdirlen, "/%s", name);
@@ -435,7 +451,7 @@ MakeServerSocket()
if (stat(SockPath, &st) == -1)
Panic(errno, "stat");
if ((int)st.st_uid != real_uid)
- Panic(0, "Unfortunatelly you are not its owner.");
+ Panic(0, "Unfortunately you are not its owner.");
if ((st.st_mode & 0700) == 0600)
Panic(0, "To resume it, use \"screen -r\"");
else
@@ -527,7 +543,7 @@ MakeServerSocket()
if (stat(SockPath, &st) == -1)
Panic(errno, "stat");
if (st.st_uid != real_uid)
- Panic(0, "Unfortunatelly you are not its owner.");
+ Panic(0, "Unfortunately you are not its owner.");
if ((st.st_mode & 0700) == 0600)
Panic(0, "To resume it, use \"screen -r\"");
else
@@ -723,7 +739,7 @@ struct msg *mp;
if (*buf)
nwin.aka = buf;
num = atoi(p);
- if (num < 0 || num > MAXWIN - 1)
+ if (num < 0 || num > maxwin - 1)
num = 0;
nwin.StartAt = num;
p += l + 1;
@@ -1156,6 +1172,26 @@ ReceiveMsg()
FinishDetach(&m);
break;
#endif
+ case MSG_QUERY:
+ {
+ char *oldSockPath = SaveStr(SockPath);
+ strcpy(SockPath, m.m.command.writeback);
+ int s = MakeClientSocket(0);
+ strcpy(SockPath, oldSockPath);
+ Free(oldSockPath);
+ if (s >= 0)
+ {
+ queryflag = s;
+ DoCommandMsg(&m);
+ close(s);
+ }
+ else
+ queryflag = -1;
+
+ Kill(m.m.command.apid, (queryflag >= 0) ? SIGCONT : SIG_BYE); /* Send SIG_BYE if an error happened */
+ queryflag = -1;
+ }
+ break;
case MSG_COMMAND:
DoCommandMsg(&m);
break;
@@ -1164,6 +1200,32 @@ ReceiveMsg()
}
}
+void
+ReceiveRaw(s)
+int s;
+{
+ char rd[256];
+ int len = 0;
+#ifdef NAMEDPIPE
+ if (fcntl(s, F_SETFL, 0) == -1)
+ Panic(errno, "BLOCK fcntl");
+#else
+ struct sockaddr_un a;
+ len = sizeof(a);
+ if ((s = accept(s, (struct sockaddr *) &a, (void *)&len)) < 0)
+ {
+ Msg(errno, "accept");
+ return;
+ }
+#endif
+ while ((len = read(s, rd, 255)) > 0)
+ {
+ rd[len] = 0;
+ printf("%s", rd);
+ }
+ close(s);
+}
+
#if defined(_SEQUENT_) && !defined(NAMEDPIPE)
#undef connect
/*
@@ -1363,6 +1425,7 @@ struct msg *m;
char *na = 0;
newscreen.nr = RC_SCREEN;
newscreen.args = &na;
+ newscreen.quiet = 0;
DoAction(&newscreen, -1);
}
else
@@ -1378,9 +1441,11 @@ struct msg *m;
if (!AclCheckPermCmd(D_user, ACL_EXEC, &comms[RC_WINDOWLIST]))
#endif
{
+ struct display *olddisplay = display;
flayer = D_forecv->c_layer;
- display_wlist(1, WLIST_NUM, (struct win *)0);
+ display_windows(1, WLIST_NUM, (struct win *)0);
noshowwin = 1;
+ display = olddisplay; /* display_windows can change display */
}
}
Activate(0);
@@ -1475,7 +1540,7 @@ struct msg *m;
ASSERT(display);
pwdata = (struct pwdata *)malloc(sizeof(struct pwdata));
if (!pwdata)
- Panic(0, strnomem);
+ Panic(0, "%s", strnomem);
pwdata->l = 0;
pwdata->m = *m;
D_processinputdata = (char *)pwdata;
@@ -1587,13 +1652,17 @@ struct msg *mp;
}
if (fc != fullcmd)
*--fc = 0;
- if (Parse(fullcmd, fc - fullcmd, args, argl) <= 0)
- return;
+ if (Parse(fullcmd, sizeof fullcmd, args, argl) <= 0)
+ {
+ queryflag = -1;
+ return;
+ }
#ifdef MULTIUSER
user = *FindUserPtr(mp->m.attach.auser);
if (user == 0)
{
Msg(0, "Unknown user %s tried to send a command!", mp->m.attach.auser);
+ queryflag = -1;
return;
}
#else
@@ -1602,7 +1671,8 @@ struct msg *mp;
#ifdef PASSWORD
if (user->u_password && *user->u_password)
{
- Msg(0, "User %s has a password, cannot use -X option.", mp->m.attach.auser);
+ Msg(0, "User %s has a password, cannot use remote commands (using -Q or -X option).", mp->m.attach.auser);
+ queryflag = -1;
return;
}
#endif
@@ -1623,7 +1693,15 @@ struct msg *mp;
{
int i = -1;
if (strcmp(mp->m.command.preselect, "-"))
- i = WindowByNoN(mp->m.command.preselect);
+ {
+ i = WindowByNoN(mp->m.command.preselect);
+ if (i < 0 || !wtab[i])
+ {
+ Msg(0, "Could not find pre-select window.");
+ queryflag = -1;
+ return;
+ }
+ }
fore = i >= 0 ? wtab[i] : 0;
}
else if (!fore)
diff --git a/src/teln.c b/src/teln.c
index 518fbe7..1764dbc 100644
--- a/src/teln.c
+++ b/src/teln.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/term.c b/src/term.c
index 8a04a8a..991de1b 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -178,6 +178,10 @@ struct term term[T_N] =
/* keycaps */
/* define T_CAPS */
+
+/* mouse */
+ { "Km", T_STR }, KMAPDEF("\033[M") KMAPMDEF("\222")
+
/* nolist */
{ "k0", T_STR }, KMAPDEF("\033[10~")
{ "k1", T_STR }, KMAPDEF("\033OP")
@@ -236,7 +240,7 @@ struct term term[T_N] =
{ "kh", T_STR }, KMAPDEF("\033[1~") KMAPMDEF("\201")
{ "@1", T_STR },
{ "kH", T_STR }, KMAPDEF("\033[4~") KMAPMDEF("\205")
- { "@7", T_STR },
+ { "@7", T_STR }, KMAPDEF("\033[4~") KMAPMDEF("\205")
{ "kN", T_STR }, KMAPDEF("\033[6~") KMAPMDEF("\006")
{ "kP", T_STR }, KMAPDEF("\033[5~") KMAPMDEF("\002")
{ "kI", T_STR }, KMAPDEF("\033[2~")
diff --git a/src/termcap.c b/src/termcap.c
index fb9f56c..32ae63d 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -31,8 +31,6 @@
#include "screen.h"
#include "extern.h"
-#undef DEBUGG
-
extern struct display *display, *displays;
extern int real_uid, real_gid, eff_uid, eff_gid;
extern struct term term[]; /* terminal capabilities */
@@ -139,7 +137,7 @@ int he;
if ((D_tentry = (char *)malloc(TERMCAP_BUFSIZE + (extra_incap ? strlen(extra_incap) + 1 : 0))) == 0)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return -1;
}
@@ -226,7 +224,8 @@ int he;
/* ISO2022 */
if ((D_EA && InStr(D_EA, "\033(B")) || (D_AS && InStr(D_AS, "\033(0")))
D_CG0 = 1;
- if (InStr(D_termname, "xterm") || InStr(D_termname, "rxvt"))
+ if (InStr(D_termname, "xterm") || InStr(D_termname, "rxvt") ||
+ (D_CKM && InStr(D_CKM, "\033[M")))
D_CXT = 1;
/* "be" seems to be standard for xterms... */
if (D_CXT)
@@ -261,7 +260,7 @@ int he;
D_US = D_UE = 0;
if (D_SG > 0)
D_SO = D_SE = 0;
- /* Unfortunatelly there is no 'mg' capability.
+ /* Unfortunately there is no 'mg' capability.
* For now we think that mg > 0 if sg and ug > 0.
*/
if (D_UG > 0 && D_SG > 0)
@@ -553,6 +552,8 @@ int map;
else
break;
}
+ if (n < KMAP_KEYS)
+ domap = 1;
if (map == 0 && domap)
return 0;
if (map && !domap)
@@ -1197,7 +1198,7 @@ char *s;
if ((D_xtable = (char ***)calloc(256, sizeof(char **))) == 0)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return -1;
}
@@ -1215,7 +1216,7 @@ char *s;
{
if ((D_xtable[curchar] = (char **)calloc(257, sizeof(char *))) == 0)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
FreeTransTable();
return -1;
}
@@ -1249,7 +1250,7 @@ char *s;
l = l * templnsub + templlen;
if ((ctable[c] = (char *)malloc(l + 1)) == 0)
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
FreeTransTable();
return -1;
}
diff --git a/src/terminfo/screeninfo.src b/src/terminfo/screeninfo.src
index e68f537..c5f254a 100644
--- a/src/terminfo/screeninfo.src
+++ b/src/terminfo/screeninfo.src
@@ -71,3 +71,10 @@ screen-s|VT 100/ANSI X3.64 virtual terminal with hardstatus line,
civis=\E[?25l, cnorm=\E[34h\E[?25h, cvvis=\E[34l,
op=\E[39;49m, setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~..--++\054\054hhII00,
+screen-256color|VT 100/ANSI X3.64 virtual terminal,
+ ccc,
+ colors#256, pairs#32767,
+ initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\,
+ setab=\E[48;5;%p1%dm, setaf=\E[38;5;%p1%dm,
+ setb=\E[48;5;%p1%dm, setf=\E[38;5;%p1%dm,
+ use=screen,
diff --git a/src/tty.sh b/src/tty.sh
index 54a9a72..f2afd54 100644
--- a/src/tty.sh
+++ b/src/tty.sh
@@ -24,7 +24,7 @@ sed -e '1,26d' \
chmod -w $1
exit 0
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
diff --git a/src/utmp.c b/src/utmp.c
index 3214df6..afa0948 100644
--- a/src/utmp.c
+++ b/src/utmp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -268,7 +268,7 @@ InitUtmp()
if ((utmpfd = open(UtmpName, O_RDWR)) == -1)
{
if (errno != EACCES)
- Msg(errno, UtmpName);
+ Msg(errno, "%s", UtmpName);
debug("InitUtmp failed.\n");
utmpok = 0;
return;
diff --git a/src/viewport.c b/src/viewport.c
new file mode 100644
index 0000000..f1607d5
--- /dev/null
+++ b/src/viewport.c
@@ -0,0 +1,140 @@
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+#include "config.h"
+#include "screen.h"
+#include "extern.h"
+#include "viewport.h"
+
+extern struct display *display;
+
+int
+RethinkDisplayViewports()
+{
+ struct canvas *cv;
+ struct viewport *vp, *vpn;
+
+ /* free old viewports */
+ for (cv = display->d_cvlist; cv; cv = cv->c_next)
+ {
+ for (vp = cv->c_vplist; vp; vp = vpn)
+ {
+ vp->v_canvas = 0;
+ vpn = vp->v_next;
+ bzero((char *)vp, sizeof(*vp));
+ free(vp);
+ }
+ cv->c_vplist = 0;
+ }
+ display->d_vpxmin = -1;
+ display->d_vpxmax = -1;
+
+ for (cv = display->d_cvlist; cv; cv = cv->c_next)
+ {
+ if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0)
+ return -1;
+#ifdef HOLE
+ vp->v_canvas = cv;
+ vp->v_xs = cv->c_xs;
+ vp->v_ys = (cv->c_ys + cv->c_ye) / 2;
+ vp->v_xe = cv->c_xe;
+ vp->v_ye = cv->c_ye;
+ vp->v_xoff = cv->c_xoff;
+ vp->v_yoff = cv->c_yoff;
+ vp->v_next = cv->c_vplist;
+ cv->c_vplist = vp;
+
+ if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0)
+ return -1;
+ vp->v_canvas = cv;
+ vp->v_xs = (cv->c_xs + cv->c_xe) / 2;
+ vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4;
+ vp->v_xe = cv->c_xe;
+ vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1;
+ vp->v_xoff = cv->c_xoff;
+ vp->v_yoff = cv->c_yoff;
+ vp->v_next = cv->c_vplist;
+ cv->c_vplist = vp;
+
+ if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0)
+ return -1;
+ vp->v_canvas = cv;
+ vp->v_xs = cv->c_xs;
+ vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4;
+ vp->v_xe = (3 * cv->c_xs + cv->c_xe) / 4 - 1;
+ vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1;
+ vp->v_xoff = cv->c_xoff;
+ vp->v_yoff = cv->c_yoff;
+ vp->v_next = cv->c_vplist;
+ cv->c_vplist = vp;
+
+ if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0)
+ return -1;
+ vp->v_canvas = cv;
+ vp->v_xs = cv->c_xs;
+ vp->v_ys = cv->c_ys;
+ vp->v_xe = cv->c_xe;
+ vp->v_ye = (3 * cv->c_ys + cv->c_ye) / 4 - 1;
+ vp->v_xoff = cv->c_xoff;
+ vp->v_yoff = cv->c_yoff;
+ vp->v_next = cv->c_vplist;
+ cv->c_vplist = vp;
+#else
+ vp->v_canvas = cv;
+ vp->v_xs = cv->c_xs;
+ vp->v_ys = cv->c_ys;
+ vp->v_xe = cv->c_xe;
+ vp->v_ye = cv->c_ye;
+ vp->v_xoff = cv->c_xoff;
+ vp->v_yoff = cv->c_yoff;
+ vp->v_next = cv->c_vplist;
+ cv->c_vplist = vp;
+#endif
+
+ if (cv->c_xs < display->d_vpxmin || display->d_vpxmin == -1)
+ display->d_vpxmin = cv->c_xs;
+ if (cv->c_xe > display->d_vpxmax || display->d_vpxmax == -1)
+ display->d_vpxmax = cv->c_xe;
+ }
+ return 0;
+}
+
+void
+RethinkViewportOffsets(cv)
+struct canvas *cv;
+{
+ struct viewport *vp;
+
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ vp->v_xoff = cv->c_xoff;
+ vp->v_yoff = cv->c_yoff;
+ }
+}
+
+
diff --git a/src/viewport.h b/src/viewport.h
new file mode 100644
index 0000000..a19b6b8
--- /dev/null
+++ b/src/viewport.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * 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 3, 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 (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ * $Id$ GNU
+ */
+
+#ifndef SCREEN_VIEWPORT_H
+#define SCREEN_VIEWPORT_H
+
+#include "canvas.h"
+
+struct viewport
+{
+ struct viewport *v_next; /* next vp on canvas */
+ struct canvas *v_canvas; /* back pointer to canvas */
+ int v_xoff; /* layer x offset on display */
+ int v_yoff; /* layer y offset on display */
+ int v_xs; /* vp upper left */
+ int v_xe; /* vp upper right */
+ int v_ys; /* vp lower left */
+ int v_ye; /* vp lower right */
+};
+
+extern int RethinkDisplayViewports __P((void));
+extern void RethinkViewportOffsets __P((struct canvas *));
+
+#endif /* SCREEN_VIEWPORT_H */
+
diff --git a/src/window.c b/src/window.c
index 5b15878..1716796 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1,4 +1,7 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -41,7 +44,7 @@
#include "logfile.h" /* logfopen() */
extern struct display *displays, *display;
-extern struct win *windows, *fore, *wtab[], *console_window;
+extern struct win *windows, *fore, *console_window;
extern char *ShellArgs[];
extern char *ShellProg;
extern char screenterm[];
@@ -93,6 +96,7 @@ static void pseu_readev_fn __P((struct event *, char *));
static void pseu_writeev_fn __P((struct event *, char *));
#endif
static void win_silenceev_fn __P((struct event *, char *));
+static void win_destroyev_fn __P((struct event *, char *));
static int OpenDevice __P((char **, int, int *, char **));
static int ForkWindow __P((struct win *, char **, char *));
@@ -103,6 +107,7 @@ static int zmodem_parse __P((struct win *, char *, int));
#endif
+struct win **wtab; /* window table */
int VerboseCreate = 0; /* XXX move this to user.h */
@@ -207,7 +212,8 @@ struct LayFuncs WinLf =
WinClearLine,
WinRewrite,
WinResize,
- WinRestore
+ WinRestore,
+ 0
};
static int
@@ -280,8 +286,7 @@ int *lenp;
debug2("window %d, user %s: ", fore->w_number, D_user->u_name);
debug2("writelock %d (wlockuser %s)\n", fore->w_wlock,
fore->w_wlockuser ? fore->w_wlockuser->u_name : "NULL");
- /* XXX FIXME only display !*/
- WBell(fore, visual_bell);
+ Msg(0, "write: permission denied (user %s)", D_user->u_name);
*bufpp += *lenp;
*lenp = 0;
return;
@@ -553,6 +558,13 @@ struct NewWindow *newwin;
extern struct acluser *users;
#endif
+ if (!wtab)
+ {
+ if (!maxwin)
+ maxwin = MAXWIN;
+ wtab = calloc(maxwin, sizeof(struct win *));
+ }
+
debug1("NewWindow: StartAt %d\n", newwin->StartAt);
debug1("NewWindow: aka %s\n", newwin->aka?newwin->aka:"NULL");
debug1("NewWindow: dir %s\n", newwin->dir?newwin->dir:"NULL");
@@ -601,7 +613,7 @@ struct NewWindow *newwin;
if ((p = (struct win *)calloc(1, sizeof(struct win))) == 0)
{
close(f);
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return -1;
}
@@ -637,7 +649,7 @@ struct NewWindow *newwin;
{
free((char *)p);
close(f);
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return -1;
}
#endif
@@ -840,6 +852,9 @@ struct NewWindow *newwin;
SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
evenq(&p->w_silenceev);
}
+ p->w_destroyev.type = EV_TIMEOUT;
+ p->w_destroyev.data = 0;
+ p->w_destroyev.handler = win_destroyev_fn;
SetForeWindow(p);
Activate(p->w_norefresh);
@@ -1019,6 +1034,7 @@ struct win *wp;
wp->w_layer.l_cvlist = 0;
if (flayer == &wp->w_layer)
flayer = 0;
+ LayerCleanupMemory(&wp->w_layer);
#ifdef MULTIUSER
FreeWindowAcl(wp);
@@ -1026,6 +1042,7 @@ struct win *wp;
evdeq(&wp->w_readev); /* just in case */
evdeq(&wp->w_writeev); /* just in case */
evdeq(&wp->w_silenceev);
+ evdeq(&wp->w_destroyev);
#ifdef COPY_PASTE
FreePaster(&wp->w_paster);
#endif
@@ -1436,6 +1453,7 @@ char **args, *ttyn;
return pid;
}
+#ifndef HAVE_EXECVPE
void
execvpe(prog, args, env)
char *prog, **args, **env;
@@ -1481,6 +1499,7 @@ char *prog, **args, **env;
if (eaccess)
errno = EACCES;
}
+#endif
#ifdef PSEUDOS
@@ -1511,7 +1530,7 @@ char **av;
}
if (!(pwin = (struct pseudowin *)calloc(1, sizeof(struct pseudowin))))
{
- Msg(0, strnomem);
+ Msg(0, "%s", strnomem);
return -1;
}
@@ -1906,7 +1925,11 @@ char *data;
p->w_pwin->p_inlen += len;
}
#endif
+
+ LayPause(&p->w_layer, 1);
WriteString(p, bp, len);
+ LayPause(&p->w_layer, 0);
+
return;
}
@@ -2046,9 +2069,20 @@ char *data;
continue;
#endif
Msg(0, "Window %d: silence for %d seconds", p->w_number, p->w_silencewait);
+ p->w_silence = SILENCE_FOUND;
+ WindowChanged(p, 'f');
}
}
+static void
+win_destroyev_fn(ev, data)
+struct event *ev;
+char *data;
+{
+ struct win *p = (struct win *)ev->data;
+ WindowDied(p, p->w_exitstatus, 1);
+}
+
#ifdef ZMODEM
static int
@@ -2099,7 +2133,7 @@ int len;
D_readev.condpos = D_readev.condneg = 0;
while (len-- > 0)
AddChar(*bp++);
- Flush();
+ Flush(0);
Activate(D_fore ? D_fore->w_norefresh : 0);
return 1;
}
@@ -2233,3 +2267,54 @@ struct display *d;
}
#endif
+
+int
+WindowChangeNumber(struct win *win, int n)
+{
+ struct win *p;
+ int old = win->w_number;
+
+ if (n < 0 || n >= maxwin)
+ {
+ Msg(0, "Given window position is invalid.");
+ return 0;
+ }
+
+ p = wtab[n];
+ wtab[n] = win;
+ win->w_number = n;
+ wtab[old] = p;
+ if (p)
+ p->w_number = old;
+#ifdef MULTIUSER
+ /* exchange the acls for these windows. */
+ AclWinSwap(old, n);
+#endif
+#ifdef UTMPOK
+ /* exchange the utmp-slots for these windows */
+ if ((win->w_slot != (slot_t) -1) && (win->w_slot != (slot_t) 0))
+ {
+ RemoveUtmp(win);
+ SetUtmp(win);
+ }
+ if (p && (p->w_slot != (slot_t) -1) && (p->w_slot != (slot_t) 0))
+ {
+ /* XXX: first display wins? */
+#if 0
+ /* Does this make more sense? */
+ display = p->w_lastdisp ? p->w_lastdisp : p->w_layer.l_cvlist ? p->w_layer.l_cvlist->c_display : 0;
+#else
+ display = win->w_layer.l_cvlist ? win->w_layer.l_cvlist->c_display : 0;
+#endif
+ RemoveUtmp(p);
+ SetUtmp(p);
+ }
+#endif
+
+ WindowChanged(win, 'n');
+ WindowChanged((struct win *)0, 'w');
+ WindowChanged((struct win *)0, 'W');
+ WindowChanged((struct win *)0, 0);
+ return 1;
+}
+
diff --git a/src/window.h b/src/window.h
index eddf6ac..47f5c9e 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1,4 +1,7 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -24,9 +27,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
****************************************************************
- * $Id$ FAU
+ * $Id$ GNU
*/
+#ifndef SCREEN_WINDOW_H
+#define SCREEN_WINDOW_H
/* keep this in sync with the initialisations in window.c */
struct NewWindow
@@ -128,7 +133,7 @@ struct paster
struct paster;
#endif
-struct win
+struct win
{
struct win *w_next; /* next window */
int w_type; /* type of window */
@@ -182,7 +187,7 @@ struct win
int w_CharsetR; /* charset number GR */
int w_charsets[4]; /* Font = charsets[Charset] */
#endif
- int w_ss;
+ int w_ss;
int w_saved;
int w_Saved_x, w_Saved_y;
struct mchar w_SavedRend;
@@ -222,7 +227,7 @@ struct win
int w_monitor; /* monitor status */
int w_silencewait; /* wait for silencewait secs */
int w_silence; /* silence status (Lloyd Zusman) */
- char w_vbwait;
+ char w_vbwait;
char w_norefresh; /* dont redisplay when switching to that win */
#ifdef RXVT_OSC
char w_xtermosc[4][MAXSTR]; /* special xterm/rxvt escapes */
@@ -241,8 +246,8 @@ struct win
#else
int w_histheight; /* always 0 */
#endif
- int w_pid; /* process at the other end of ptyfd */
- int w_deadpid; /* saved w_pid of a process that closed the ptyfd to us */
+ int w_pid; /* process at the other end of ptyfd */
+ int w_deadpid; /* saved w_pid of a process that closed the ptyfd to us */
char *w_cmdargs[MAXARGS]; /* command line argument vector */
char *w_dir; /* directory for chdir */
@@ -280,6 +285,14 @@ struct win
struct mline *w_alt_hlines;
int w_alt_histidx;
#endif
+ int w_alt_current; /* Is the alternate buffer currently being used? */
+
+ struct event w_destroyev; /* window destroy event */
+#ifdef BSDWAIT
+ union wait w_exitstatus; /* window exit status */
+#else
+ int w_exitstatus;
+#endif
};
@@ -323,3 +336,8 @@ struct win
: &fore->w_mlines[y - fore->w_histheight])
#define Layer2Window(l) ((struct win *)(l)->l_bottom->l_data)
+
+int WindowChangeNumber __P((struct win *, int));
+
+#endif /* SCREEN_WINDOW_H */
+