Initial git import. - sam - An updated version of the sam text editor. | |
git clone git://vernunftzentrum.de/sam.git | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit f8d68c3f2e8aa987821894c9b82aa63bb411e714 | |
Author: Rob King <[email protected]> | |
Date: Fri, 31 Jul 2015 23:02:18 -0500 | |
Initial git import. | |
Diffstat: | |
LICENSE | 18 ++++++++++++++++++ | |
Makefile | 40 +++++++++++++++++++++++++++++++ | |
README | 118 +++++++++++++++++++++++++++++++ | |
config.mk | 23 +++++++++++++++++++++++ | |
doc/B | 43 ++++++++++++++++++++++++++++++ | |
doc/Makefile | 18 ++++++++++++++++++ | |
doc/keyboard | 206 +++++++++++++++++++++++++++++++ | |
doc/sam.1 | 1027 +++++++++++++++++++++++++++++++ | |
doc/sam.1.pdf | 0 | |
doc/sam.ps | 8261 +++++++++++++++++++++++++++++++ | |
doc/sam.tut.ms | 1776 ++++++++++++++++++++++++++++++ | |
doc/se.ps | 1487 ++++++++++++++++++++++++++++++ | |
include/frame.h | 72 +++++++++++++++++++++++++++++++ | |
include/libc.h | 54 +++++++++++++++++++++++++++++++ | |
include/libg.h | 225 +++++++++++++++++++++++++++++++ | |
include/regexp.h | 65 +++++++++++++++++++++++++++++++ | |
include/u.h | 117 +++++++++++++++++++++++++++++++ | |
libXg/Gwin.h | 43 ++++++++++++++++++++++++++++++ | |
libXg/GwinP.h | 45 +++++++++++++++++++++++++++++++ | |
libXg/Makefile | 58 ++++++++++++++++++++++++++++++ | |
libXg/arc.c | 45 +++++++++++++++++++++++++++++++ | |
libXg/arith.c | 191 +++++++++++++++++++++++++++++++ | |
libXg/balloc.c | 60 +++++++++++++++++++++++++++++++ | |
libXg/bitblt.c | 59 +++++++++++++++++++++++++++++++ | |
libXg/bitbltclip.c | 68 +++++++++++++++++++++++++++++++ | |
libXg/border.c | 28 ++++++++++++++++++++++++++++ | |
libXg/bscreenrect.c | 18 ++++++++++++++++++ | |
libXg/circle.c | 23 +++++++++++++++++++++++ | |
libXg/clipline.c | 225 +++++++++++++++++++++++++++++++ | |
libXg/clipr.c | 21 +++++++++++++++++++++ | |
libXg/copymasked.c | 49 +++++++++++++++++++++++++++++++ | |
libXg/cursorset.c | 16 ++++++++++++++++ | |
libXg/cursorswitch.c | 66 +++++++++++++++++++++++++++++++ | |
libXg/disc.c | 23 +++++++++++++++++++++++ | |
libXg/ellipse.c | 23 +++++++++++++++++++++++ | |
libXg/font.c | 18 ++++++++++++++++++ | |
libXg/gcs.c | 401 +++++++++++++++++++++++++++++++ | |
libXg/getrect.c | 73 +++++++++++++++++++++++++++++++ | |
libXg/gwin.c | 466 +++++++++++++++++++++++++++++++ | |
libXg/latin1.c | 313 +++++++++++++++++++++++++++++++ | |
libXg/ldconvert.c | 55 +++++++++++++++++++++++++++++++ | |
libXg/libgint.h | 93 +++++++++++++++++++++++++++++++ | |
libXg/menuhit.c | 236 +++++++++++++++++++++++++++++++ | |
libXg/point.c | 21 +++++++++++++++++++++ | |
libXg/polysegment.c | 27 +++++++++++++++++++++++++++ | |
libXg/rdbitmap.c | 63 +++++++++++++++++++++++++++++++ | |
libXg/rdbitmapfile.c | 65 +++++++++++++++++++++++++++++++ | |
libXg/rectclip.c | 25 +++++++++++++++++++++++++ | |
libXg/rune.c | 213 +++++++++++++++++++++++++++++++ | |
libXg/segment.c | 25 +++++++++++++++++++++++++ | |
libXg/string.c | 38 +++++++++++++++++++++++++++++++ | |
libXg/strwidth.c | 23 +++++++++++++++++++++++ | |
libXg/test.c | 237 +++++++++++++++++++++++++++++++ | |
libXg/texture.c | 42 +++++++++++++++++++++++++++++++ | |
libXg/wrbitmap.c | 55 +++++++++++++++++++++++++++++++ | |
libXg/wrbitmapfile.c | 50 +++++++++++++++++++++++++++++++ | |
libXg/xtbinit.c | 830 ++++++++++++++++++++++++++++++ | |
libframe/Makefile | 47 +++++++++++++++++++++++++++++++ | |
libframe/frbox.c | 156 +++++++++++++++++++++++++++++++ | |
libframe/frdelete.c | 104 +++++++++++++++++++++++++++++++ | |
libframe/frdraw.c | 59 +++++++++++++++++++++++++++++++ | |
libframe/frinit.c | 42 +++++++++++++++++++++++++++++++ | |
libframe/frinsert.c | 247 +++++++++++++++++++++++++++++++ | |
libframe/frptofchar.c | 116 ++++++++++++++++++++++++++++++ | |
libframe/frselect.c | 94 +++++++++++++++++++++++++++++++ | |
libframe/frstr.c | 41 +++++++++++++++++++++++++++++++ | |
libframe/frutil.c | 107 +++++++++++++++++++++++++++++++ | |
libframe/misc.c | 93 +++++++++++++++++++++++++++++++ | |
rsam/Makefile | 18 ++++++++++++++++++ | |
rsam/rsam.c | 147 +++++++++++++++++++++++++++++++ | |
sam/B.rc | 51 +++++++++++++++++++++++++++++++ | |
sam/B.sh | 56 +++++++++++++++++++++++++++++++ | |
sam/Makefile | 89 +++++++++++++++++++++++++++++++ | |
sam/address.c | 241 +++++++++++++++++++++++++++++++ | |
sam/buffer.c | 179 +++++++++++++++++++++++++++++++ | |
sam/cmd.c | 591 +++++++++++++++++++++++++++++++ | |
sam/disc.c | 335 +++++++++++++++++++++++++++++++ | |
sam/error.c | 132 +++++++++++++++++++++++++++++++ | |
sam/errors.h | 63 +++++++++++++++++++++++++++++++ | |
sam/file.c | 465 +++++++++++++++++++++++++++++++ | |
sam/io.c | 257 +++++++++++++++++++++++++++++++ | |
sam/list.c | 48 +++++++++++++++++++++++++++++++ | |
sam/mesg.c | 762 +++++++++++++++++++++++++++++++ | |
sam/mesg.h | 102 +++++++++++++++++++++++++++++++ | |
sam/moveto.c | 168 +++++++++++++++++++++++++++++++ | |
sam/multi.c | 91 +++++++++++++++++++++++++++++++ | |
sam/parse.h | 69 ++++++++++++++++++++++++++++++ | |
sam/plan9.c | 174 +++++++++++++++++++++++++++++++ | |
sam/rasp.c | 276 ++++++++++++++++++++++++++++++ | |
sam/regexp.c | 820 ++++++++++++++++++++++++++++++ | |
sam/sam.c | 682 +++++++++++++++++++++++++++++++ | |
sam/sam.h | 408 +++++++++++++++++++++++++++++++ | |
sam/samsave | 14 ++++++++++++++ | |
sam/shell.c | 155 +++++++++++++++++++++++++++++++ | |
sam/string.c | 179 +++++++++++++++++++++++++++++++ | |
sam/sys.c | 61 +++++++++++++++++++++++++++++++ | |
sam/unix.c | 220 +++++++++++++++++++++++++++++++ | |
sam/xec.c | 492 +++++++++++++++++++++++++++++++ | |
samterm/Makefile | 49 +++++++++++++++++++++++++++++++ | |
samterm/flayer.c | 436 +++++++++++++++++++++++++++++++ | |
samterm/flayer.h | 48 +++++++++++++++++++++++++++++++ | |
samterm/icons.c | 54 +++++++++++++++++++++++++++++++ | |
samterm/io.c | 204 +++++++++++++++++++++++++++++++ | |
samterm/main.c | 592 +++++++++++++++++++++++++++++++ | |
samterm/menu.c | 380 ++++++++++++++++++++++++++++++ | |
samterm/mesg.c | 794 +++++++++++++++++++++++++++++++ | |
samterm/plan9.c | 113 +++++++++++++++++++++++++++++++ | |
samterm/rasp.c | 263 +++++++++++++++++++++++++++++++ | |
samterm/samterm.h | 158 +++++++++++++++++++++++++++++++ | |
samterm/scroll.c | 145 +++++++++++++++++++++++++++++++ | |
samterm/unix.c | 159 +++++++++++++++++++++++++++++++ | |
111 files changed, 29826 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/LICENSE b/LICENSE | |
@@ -0,0 +1,18 @@ | |
+ | |
+/* | |
+ * The authors of this software are Rob Pike and Howard Trickey. | |
+ * Copyright (c) 1998 by Lucent Technologies. | |
+ * | |
+ * Rob King made some changes. | |
+ * Copyright (c) 2015 by Rob King. | |
+ * | |
+ * Permission to use, copy, modify, and distribute this software for any | |
+ * purpose without fee is hereby granted, provided that this entire notice | |
+ * is included in all copies of any software which is or includes a copy | |
+ * or modification of this software and in all copies of the supporting | |
+ * documentation for such software. | |
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED | |
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE … | |
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY | |
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. | |
+ */ | |
diff --git a/Makefile b/Makefile | |
@@ -0,0 +1,40 @@ | |
+# Copyright (c) 1998 Lucent Technologies - All rights reserved. | |
+# Changes Copyright (c) 2014-2015 Rob King | |
+# | |
+# master makefile for sam. configure sub-makefiles first. | |
+# | |
+ | |
+all: lXg lframe rsamdir samdir samtermdir docdir | |
+ | |
+lXg: | |
+ cd libXg; $(MAKE) | |
+lframe: | |
+ cd libframe; $(MAKE) | |
+ | |
+docdir: | |
+ cd doc; $(MAKE) | |
+ | |
+rsamdir: | |
+ cd rsam; $(MAKE) | |
+ | |
+samdir: | |
+ cd sam; $(MAKE) | |
+ | |
+samtermdir: | |
+ cd samterm; $(MAKE) | |
+ | |
+install: | |
+ cd libXg; $(MAKE) install | |
+ cd libframe; $(MAKE) install | |
+ cd sam; $(MAKE) install | |
+ cd samterm; $(MAKE) install | |
+ cd doc; $(MAKE) install | |
+ cd rsam; $(MAKE) install | |
+ | |
+clean: | |
+ cd libXg; $(MAKE) clean | |
+ cd libframe; $(MAKE) clean | |
+ cd sam; $(MAKE) clean | |
+ cd samterm; $(MAKE) clean | |
+ cd rsam; $(MAKE) clean | |
+ | |
diff --git a/README b/README | |
@@ -0,0 +1,118 @@ | |
+ | |
+ * The authors of this software are Rob Pike and Howard Trickey. | |
+ * Copyright (c) 1998 by Lucent Technologies. | |
+ * | |
+ * Rob King made some changes. | |
+ * Those changes, Copyright (c) 2014-2015 by Rob King. | |
+ * | |
+ * Permission to use, copy, modify, and distribute this software for any | |
+ * purpose without fee is hereby granted, provided that this entire notice | |
+ * is included in all copies of any software which is or includes a copy | |
+ * or modification of this software and in all copies of the supporting | |
+ * documentation for such software. | |
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED | |
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE … | |
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY | |
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. | |
+ | |
+This is an X11 version of Rob Pike's editor, sam. Documentation describing | |
+its use and construction are provided in subdirectory doc. The file | |
+doc/sam.1 contains the manual page; doc/sam.1.pdf is a PDF version of that | |
+page. doc/sam.tut.ms is a tutorial that can be formatted with troff -ms. | |
+It substitutes Bold and Italics for the fonts named CW and CS; if your system | |
+has these fonts, remove the CW and CS macros at the beginning of the file. The | |
+files doc/sam.ps and doc/se.ps are postscript versions of published papers | |
+describing sam and structural regular expressions. These papers reflect | |
+sam's capabilities at the time of publication several years ago; while the | |
+general description remains accurate, some functions may have changed or been | |
+removed. The file doc/keyboard is an example of a Unicode input configuration | |
+file; it serves as a good starting point for a customized version (see the | |
+manual page for more information). | |
+ | |
+Sam is composed of three programs: sam itself, which does the command | |
+processing and file manipulation; and samterm, which controls the display | |
+and interacts with the user. You can run sam on one machine and samterm on | |
+another connected via remote execution. A third program, rsam, is automatically | |
+interpolated between the terminal and the remote instance of sam by default | |
+to allow an additional control channel on the remote machine. | |
+ | |
+This version of sam is based on the Plan 9 implementation. Its | |
+design and expression reflect the functionality of the Plan 9 environment; | |
+most notably, characters are represented internally by 16-bit values called | |
+Runes. Header files include/u.h and include/libc.h and source files | |
+libframe/misc.c, libXg/rune.c, sam/unix.c and samterm/unix.c contain | |
+code that insinuates sam into the Unix world. Two other files, | |
+sam/plan9.c and samterm/plan9.c, contain Plan 9-specific code; they | |
+are not used in the Unix version of sam and are provided as examples | |
+of the Plan 9 interface. | |
+ | |
+The typedefs for uchar, ushort, and ulong defined in include/u.h, may conflict | |
+with exisiting definitions in include file <sys/types.h> on some systems. | |
+If this occurs, remove the offending definitions from include/u.h. | |
+ | |
+The distribution consists of several directories: | |
+ | |
+ sam - The source for sam. It loads against libXg to pick | |
+ up some utility routines. | |
+ | |
+ samterm - The source for samterm. It loads against libframe, | |
+ libXg, and your local X11 libraries. | |
+ | |
+ rsam - The source for rsam. | |
+ | |
+ libframe - The source for the frame library. This library is used | |
+ by samterm so it must be made first. | |
+ | |
+ libXg - The source code of the graphics library and some general | |
+ utility modules. Header file u.h provides much of the | |
+ interface between sam and the local environment. It is | |
+ included in every source file. Sam's graphics | |
+ operations are implemented by Plan 9 libg functions. This | |
+ library emulates those functions using X11 operations. | |
+ | |
+ include - header files. | |
+ | |
+ doc - The documentation for sam. | |
+ | |
+Each source directory contains a makefile. | |
+The master makefile in the top directory builds the subdirectories in | |
+proper order. | |
+ | |
+Most customization effort is confined to configuring the makefiles. | |
+They are configured by editing config.mk; see that file for details. | |
+ | |
+After configuring the makefiles, change to the top-level directory and | |
+type "make". Typing "make install" installs B, sam, samterm and samsave in | |
+their permanent homes as well as their on-line documentation. | |
+ | |
+During testing, the path of samterm may be specified using the -t command line | |
+option to sam. Similarly, the path of sam itself may be specified using the | |
+-s command line option; this is handy for testing the remote execution feature. | |
+ | |
+The script doc/B is a Bourne shell-compatible script that sends a 'B' command | |
+to a running instance of sam. | |
+ | |
+The original protocol between sam and samterm assumed that memory addresses | |
+and longs were 32 bits. Dave Hanson removed this dependency from the | |
+protocol allowing sam to run on 64-bit processors. However, other | |
+dependencies on structure alignment remain. The USE64BITS configuration | |
+variable in config.mk can be set to cope with 64-bit systems. | |
+ | |
+Note that sam seems to have some issues when running under a compositing windo… | |
+ | |
+Rob Pike designed and implemented the original Unix version of sam and | |
+the current version ported from Plan 9. Howard Trickey provided the X | |
+version of the graphics library, libXg. Matty Farrow and his colleagues | |
+at the University of Sydney extended libXg to support Runes. Boyd Roberts | |
+supplied the external command interface and the shell scripts for the 'B' | |
+command. Doug Gwyn contributed many useful ideas to the X implementation of | |
+sam. James Clark provided the simulations of the V10 Unix Man macros at the | |
+beginning of the original manual pages. Rob King modified sam to support | |
+scalable fonts, environment variable-based configration, the ability to | |
+control remote sam processes via the B script on remote machines, dynamic | |
+key substitutions from a configuration file, handle 64-bit architectures | |
+better, and to compile cleanly on modern Linux systems. | |
+ | |
+Please send bug fixes and comments to: | |
+ | |
+Rob King, [email protected] | |
diff --git a/config.mk b/config.mk | |
@@ -0,0 +1,23 @@ | |
+# config.mk - makefile configuration for sam | |
+# copyright 2015 Rob King <[email protected]> | |
+ | |
+# DESTDIR is the root of the installation tree | |
+DESTDIR=/usr/local | |
+ | |
+# BINDIR is the directory where binaries go | |
+BINDIR=$(DESTDIR)/bin | |
+ | |
+# MANDIR is where manual pages go | |
+MANDIR=$(DESTDIR)/share/man/man1 | |
+ | |
+# USE64BITS should be 1 for little-endian architectures with 64-bit pointers, | |
+# 2 for big-endian architectures with 64-bit pointers, and 0 otherwisew. | |
+# x86_64 systems would generally use 1 here, while DEC Alpha systems would | |
+# generally use 2. | |
+USE64BITS=1 | |
+ | |
+# FREETYPEINC should name the directory of your freetype2 includes. | |
+FREETYPEINC=/usr/include/freetype2 | |
+ | |
+# TMPDIR should be set to a directory for temporary files with lots of room | |
+TMPDIR=/tmp | |
diff --git a/doc/B b/doc/B | |
@@ -0,0 +1,43 @@ | |
+#!/bin/sh | |
+ | |
+if [ $# = 0 ] ; then | |
+ echo "usage: B [-r machine] files..." 1>&2 | |
+ exit 1 | |
+fi | |
+ | |
+machine=localhost | |
+if [ $1 = "-r" ] ; then | |
+ shift | |
+ machine=$1 | |
+ shift | |
+ | |
+ if [ "$machine" = "" ] ; then | |
+ echo "usage: B [-r machine] files..." 1>&2 | |
+ exit 1 | |
+ fi | |
+ echo "machine = $machine" | |
+fi | |
+ | |
+pipe="${HOME}/.sam.${machine}" | |
+dir=`/bin/pwd` | |
+files= | |
+for i in $* | |
+do | |
+ case "$i" in | |
+ /*) files="$files $i" | |
+ ;; | |
+ *) files="$files $dir/$i" | |
+ ;; | |
+ esac | |
+done | |
+ | |
+if [ ! -w "$pipe" ] ; then | |
+ pipe="${HOME}/.sam.fifo" # created by rsam | |
+fi | |
+ | |
+if [ ! -w "$pipe" ]; then | |
+ sam $files & # start sam if it's not already running | |
+else | |
+ echo "B $files" >> $pipe | |
+fi | |
+ | |
diff --git a/doc/Makefile b/doc/Makefile | |
@@ -0,0 +1,18 @@ | |
+# Copyright 2014-2014 Rob King <[email protected]> | |
+ | |
+include ../config.mk | |
+ | |
+all: sam.1.pdf | |
+ | |
+sam.1.pdf: sam.1 | |
+ tbl $< | groff -mdoc -Tpdf > $@ | |
+ | |
+install: sam.1 B | |
+ cp sam.1 "$(MANDIR)" | |
+ cp B "$(BINDIR)" | |
+ ln -sf "$(MANDIR)/sam.1" "$(MANDIR)/B.1" | |
+ ln -sf "$(MANDIR)/sam.1" "$(MANDIR)/samterm.1" | |
+ ln -sf "$(MANDIR)/sam.1" "$(MANDIR)/rsam.1" | |
+ ln -sf "$(MANDIR)/sam.1" "$(MANDIR)/sam.save.1" | |
+ ln -sf "$(MANDIR)/sam.1" "$(MANDIR)/samsave.1" | |
+ | |
diff --git a/doc/keyboard b/doc/keyboard | |
@@ -0,0 +1,206 @@ | |
+!! 0xa1 | |
+c$ 0xa2 | |
+l$ 0xa3 | |
+g$ 0xa4 | |
+y$ 0xa5 | |
+|| 0xa6 | |
+SS 0xa7 | |
+"" 0xa8 | |
+cO 0xa9 | |
+sa 0xaa | |
+<< 0xab | |
+no 0xac | |
+-- 0xad | |
+rO 0xae | |
+__ 0xaf | |
+de 0xb0 | |
++- 0xb1 | |
+s2 0xb2 | |
+s3 0xb3 | |
+'' 0xb4 | |
+mi 0xb5 | |
+pg 0xb6 | |
+.. 0xb7 | |
+,, 0xb8 | |
+s1 0xb9 | |
+so 0xba | |
+>> 0xbb | |
+14 0xbc | |
+12 0xbd | |
+34 0xbe | |
+?? 0xbf | |
+`A 0xc0 | |
+'A 0xc1 | |
+^A 0xc2 | |
+~A 0xc3 | |
+"A 0xc4 | |
+oA 0xc5 | |
+AE 0xc6 | |
+,C 0xc7 | |
+`E 0xc8 | |
+'E 0xc9 | |
+^E 0xca | |
+"E 0xcb | |
+`I 0xcc | |
+'I 0xcd | |
+^I 0xce | |
+"I 0xcf | |
+D- 0xd0 | |
+~N 0xd1 | |
+`O 0xd2 | |
+'O 0xd3 | |
+^O 0xd4 | |
+~O 0xd5 | |
+"O 0xd6 | |
+mu 0xd7 | |
+/O 0xd8 | |
+`U 0xd9 | |
+'U 0xda | |
+^U 0xdb | |
+"U 0xdc | |
+'Y 0xdd | |
+|P 0xde | |
+ss 0xdf | |
+`a 0xe0 | |
+'a 0xe1 | |
+^a 0xe2 | |
+~a 0xe3 | |
+"a 0xe4 | |
+oa 0xe5 | |
+ae 0xe6 | |
+,c 0xe7 | |
+`e 0xe8 | |
+'e 0xe9 | |
+^e 0xea | |
+"e 0xeb | |
+`i 0xec | |
+'i 0xed | |
+^i 0xee | |
+"i 0xef | |
+d- 0xf0 | |
+~n 0xf1 | |
+`o 0xf2 | |
+'o 0xf3 | |
+^o 0xf4 | |
+~o 0xf5 | |
+"o 0xf6 | |
+-: 0xf7 | |
+/o 0xf8 | |
+`u 0xf9 | |
+'u 0xfa | |
+^u 0xfb | |
+"u 0xfc | |
+'y 0xfd | |
+|p 0xfe | |
+"y 0xff | |
+wk 0x2654 | |
+wq 0x2655 | |
+wr 0x2656 | |
+wb 0x2657 | |
+wn 0x2658 | |
+wp 0x2659 | |
+bk 0x265a | |
+bq 0x265b | |
+br 0x265c | |
+bb 0x265d | |
+bn 0x265e | |
+bp 0x265f | |
+*a 0x3b1 Greek letter alpha | |
+*b 0x3b2 | |
+*g 0x3b3 | |
+*d 0x3b4 | |
+*e 0x3b5 | |
+*z 0x3b6 | |
+*y 0x3b7 | |
+*h 0x3b8 | |
+*i 0x3b9 | |
+*k 0x3ba | |
+*l 0x3bb | |
+*m 0x3bc | |
+*n 0x3bd | |
+*c 0x3be | |
+*o 0x3bf | |
+*p 0x3c0 | |
+*r 0x3c1 | |
+ts 0x3c2 | |
+*s 0x3c3 | |
+*t 0x3c4 | |
+*u 0x3c5 | |
+*f 0x3c6 | |
+*x 0x3c7 | |
+*q 0x3c8 | |
+*w 0x3c9 | |
+*A 0x391 | |
+*B 0x392 | |
+*G 0x393 | |
+*D 0x394 | |
+*E 0x395 | |
+*Z 0x396 | |
+*Y 0x397 | |
+*H 0x398 | |
+*I 0x399 | |
+*K 0x39a | |
+*L 0x39b | |
+*M 0x39c | |
+*N 0x39d | |
+*C 0x39e | |
+*O 0x39f | |
+*P 0x3a0 | |
+*R 0x3a1 | |
+*S 0x3a3 | |
+*T 0x3a4 | |
+*U 0x3a5 | |
+*F 0x3a6 | |
+*X 0x3a7 | |
+*Q 0x3a8 | |
+*W 0x3a9 | |
+<- 0x2190 | |
+ua 0x2191 | |
+-> 0x2192 | |
+da 0x2193 | |
+ab 0x2194 | |
+V= 0x21d0 | |
+=V 0x21d2 | |
+fa 0x2200 | |
+te 0x2203 | |
+pd 0x2202 | |
+es 0x2205 | |
+De 0x2206 | |
+gr 0x2207 | |
+mo 0x2208 | |
+!m 0x2209 | |
+st 0x220d | |
+** 0x2217 | |
+bu 0x2219 | |
+sr 0x221a | |
+pt 0x221d | |
+if 0x221e | |
+an 0x2220 | |
+l& 0x2227 | |
+l| 0x2228 | |
+ca 0x2229 | |
+cu 0x222a | |
+is 0x222b | |
+tf 0x2234 | |
+~= 0x2243 | |
+cg 0x2245 | |
+~~ 0x2248 | |
+!= 0x2260 | |
+== 0x2261 | |
+<= 0x2266 | |
+>= 0x2267 | |
+sb 0x2282 | |
+sp 0x2283 | |
+!b 0x2284 | |
+ib 0x2286 | |
+ip 0x2287 | |
+O+ 0x2295 | |
+O- 0x2296 | |
+Ox 0x2297 | |
+tu 0x22a2 | |
+Tu 0x22a8 | |
+lz 0x22c4 Lozenge | |
+el 0x22ef Elipsis | |
+:( 0x2639 Frowny | |
+:) 0x263a Smiley | |
+;) 0x263b Dark smiley | |
diff --git a/doc/sam.1 b/doc/sam.1 | |
@@ -0,0 +1,1026 @@ | |
+.Dd $Mdocdate$ | |
+.Dt SAM 1 | |
+.Os | |
+.Sh NAME | |
+.Nm sam | |
+.Nd screen editor with structural regular expressions | |
+.Sh SYNOPSIS | |
+.Nm | |
+.Op Fl d | |
+.Op Fl t Ar terminal | |
+.Ar | |
+.Nm | |
+.Fl r Ar machine | |
+.Op Fl s Ar file | |
+.Op Fl t Ar terminal | |
+.Ar | |
+.Nm sam.save | |
+.Nm B | |
+.Op Fl r Ar machine | |
+.Ar | |
+.Sh DESCRIPTION | |
+.Nm sam | |
+is a multi-file editor. | |
+It modifies a local copy of an external file. | |
+The copy is here called a | |
+.Em file "." | |
+The files are listed in a menu available through mouse button 3 or the | |
+.Li n | |
+command. | |
+Each file has an associated name, usually the name of the external file from w… | |
+.Dq modified | |
+bit that indicates whether the editor's file agrees with the external file. | |
+The external file is not read into the editor's file until it first becomes th… | |
+The options are | |
+.Bl -tag -width Ds | |
+.It Fl d | |
+Do not download the terminal part of | |
+.Nm "." | |
+Editing will be done with the command language only, as in | |
+.Xr ed 1 "." | |
+.It Fl r Ar machine | |
+Run the host part remotely on the specified machine, the terminal part locally… | |
+.Nm | |
+associated with | |
+.Ar machine "." | |
+.It Fl s Ar file | |
+Start the host part from the indicated file on the remote host. | |
+By default, this is | |
+.Pa rsam "," | |
+which is a program that interposes itself between the host and terminal parts … | |
+.Nm | |
+and allows | |
+.Nm | |
+to be controlled via commands on the remote system. | |
+.It Fl t Ar file | |
+Start the terminal part from the indicated file. | |
+Useful for debugging. | |
+.El | |
+.Ss Regular expressions | |
+Regular expressions are more-or-less as they are in | |
+.Xr regex 7 "," | |
+with the addition of | |
+.Li \[rs]n | |
+to represent newlines. | |
+A regular expression may never contain a literal newline character. | |
+The elements of regular expressions are: | |
+.Bl -tag -width Ds | |
+.It Li "." | |
+Match any character except newline. | |
+.It Li \[rs]n | |
+Match newline. | |
+.It Li \[rs]x | |
+For any character except | |
+.Li n | |
+match the character | |
+.Po | |
+here | |
+.Sy x | |
+.Pc "." | |
+.It Li "[abc]" | |
+Match any character in the square brackets. | |
+.Li \[rs]n | |
+may be mentioned. | |
+.It Li "[^abc]" | |
+Match any character not in the square brackets, but never a newline. | |
+Both this and the positive form above accept a range of ASCII characters indic… | |
+.Li "a-z" "." | |
+.It Li "^" | |
+Match the null string immediately after a newline. | |
+.It Li "$" | |
+Match the null string immediately before a newline. | |
+.El | |
+.Pp | |
+Any other character except newline matches itself. | |
+.Pp | |
+In the following, | |
+.Sy r1 | |
+and | |
+.Sy r2 | |
+are regular expressions. | |
+.Bl -tag -width Ds | |
+.It Pq Sy r1 | |
+Match what | |
+.Sy r1 | |
+matches. | |
+.It Sy r1|r2 | |
+Match what | |
+.Sy r1 | |
+or | |
+.Sy r2 | |
+matches. | |
+.It Sy r1* | |
+Match zero or more adjacent matches of | |
+.Sy r1 "." | |
+.It Sy r1+ | |
+Match one or more adjacent matches of | |
+.Sy r1 "." | |
+.It Sy "r1?" | |
+Match zero or one matches of | |
+.Sy r1 "." | |
+.El | |
+.Pp | |
+The operators | |
+.Li "*" "," | |
+.Li "+" "," | |
+and | |
+.Li "?" | |
+are highest precedence, then catenation, then | |
+.Li "|" | |
+is lowest. | |
+The empty regular expression stands for the last complete expression encounter… | |
+A regular expression in | |
+.Nm | |
+matches the longest leftmost substring formally matched by the expression. | |
+Searching in the reverse direction is equivalent to search backwards with the … | |
+.Ss Addresses | |
+An address identifies a substring in a file. | |
+In the following | |
+.Do | |
+character | |
+.Sy n | |
+.Dc | |
+means the null string after the | |
+.Sy n\fR-th | |
+character in the file, with 1 the first character in the file. | |
+.Do | |
+Line | |
+.Sy n | |
+.Dc | |
+means the | |
+.Sy n\fR-th | |
+match, starting at the beginning of the file, of the regular expression | |
+.Li ".*\[rs]n?" "." | |
+.Po | |
+The peculiar properties of a last line without a newline are temporarily undef… | |
+.Pc | |
+All files always have a current substring, called | |
+.Sy dot "," | |
+that is the default address. | |
+.Ss Simple addresses | |
+.Bl -tag -width Ds | |
+.It Li # Sy n | |
+The empty string after character | |
+.Sy n ";" | |
+.Li #0 | |
+is the beginning of the file. | |
+.It Sy n | |
+Line | |
+.Sy n "." | |
+.It Li / Sy regexp Li / | |
+.It Li ? Sy regexp Li ? | |
+The substring that matches the regular expression, found by looking toward the… | |
+.Pq Li / | |
+or beginning | |
+.Pq Li ? | |
+of the file, and if necessary continuing the search from the other end to the … | |
+The matched substring may straddle the starting point. | |
+When entering a pattern containing a literal question mark for a backward sear… | |
+.It Li 0 | |
+The string before the first full line. | |
+This is not necessarily the null string; see | |
+.Li + | |
+and | |
+.Li - | |
+below. | |
+.It Li $ | |
+The null string at the end of the file. | |
+.It Li "." | |
+Dot. | |
+.It Li "'" | |
+The mark in the file | |
+.Po | |
+see the | |
+.Sy k | |
+command below | |
+.Pc "." | |
+.It Sy "regexp" | |
+.Do | |
+A regular expression in double quotes. | |
+.Dc | |
+Preceding a simple address | |
+.Do | |
+default | |
+.Li "." | |
+.Dc "," | |
+refers to the address evaluated in the unique file whose menu line matches the… | |
+.El | |
+.Ss Compound addresses | |
+In the following, | |
+.Sy a1 | |
+and | |
+.Sy a2 | |
+are addresses. | |
+.Bl -tag -width Ds | |
+.It Sy a1+a2 | |
+The address | |
+.Sy a2 | |
+evaulated starting at the end of | |
+.Sy a1 "." | |
+.It Sy a1-a2 | |
+The address | |
+.Sy a2 | |
+evaluated looking the reverse direction starting at the beginning of | |
+.Sy a1 "." | |
+.It Sy "a1,a2" | |
+The substring from the beinning of | |
+.Sy a1 | |
+to the end of | |
+.Sy a2 "." | |
+If | |
+.Sy a1 | |
+is missing, | |
+.Li 0 | |
+is substituted. | |
+If | |
+.Sy a2 | |
+is missing, | |
+.Li $ | |
+is substituted. | |
+.It Sy a1;a2 | |
+Like | |
+.Dq Sy a1,a2 | |
+but with | |
+.Sy a2 | |
+evaluated at the end of, and dot set to, | |
+.Sy a1 "." | |
+.El | |
+.Pp | |
+The operators | |
+.Li + | |
+and | |
+.Li - | |
+are high precedence, while | |
+.Li , | |
+and | |
+.Li ; | |
+are low precedence. | |
+.Pp | |
+In both | |
+.Li + | |
+and | |
+.Li - | |
+forms, if | |
+.Sy a2 | |
+is a line or character address with a missing number, the number defaults to 1. | |
+If | |
+.Sy a1 | |
+is missing, | |
+.Li "." | |
+is subtituted. | |
+If both | |
+.Sy a1 | |
+and | |
+.Sy a2 | |
+are present and distinguishable, | |
+.Li + | |
+may be elided. | |
+.Sy a2 | |
+may be a regular expression; if it is delimited by | |
+.Li "?" | |
+characters, the effect of the | |
+.Li + | |
+or | |
+.Li - | |
+is reversed. | |
+.Pp | |
+It is an error for a compound address to represent a malformed substring. | |
+.Pp | |
+Some useful idioms: | |
+.Bl -tag -width Ds | |
+.It Sy a1+- Po Sy a1-+ Pc | |
+selects the line containing the end | |
+.Dq beginning | |
+of | |
+.Sy a1 "." | |
+.It Sy 0/regexp/ | |
+locates the first match of the expression in the file. | |
+.Do | |
+The form | |
+.Li 0;// | |
+sets dot unnecessarily. | |
+.Dc | |
+.It Sy "./regexp///" | |
+find the second following occurence of the expression, and | |
+.Sy ".,/regexp/" | |
+extends dot. | |
+.El | |
+.Ss Commands | |
+In the following, text demarcated by slashes represnets text delimited by any … | |
+Any number of trailing delimiters may be elided, with multiple elisions then r… | |
+In any delimited text, newline may not appear literally; | |
+.Li \[rs]n | |
+may be typed for newline; and | |
+.Li \[rs]/ | |
+quotes the delimiter, here | |
+.Li / "." | |
+Backslash is other interpreted literally, except in | |
+.Sy s | |
+commands. | |
+.Pp | |
+Most commands may be prefixed with an address to indicate their range of opera… | |
+Those that may not are marked with a | |
+.Sy "*" | |
+below. | |
+If a command takes an address and none is supplised, dot is used. | |
+The sole exception is the | |
+.Sy w | |
+command, which defaults to | |
+.Li "0,$" "." | |
+In the description, | |
+.Dq range | |
+is used to represent whatever address is supplied. | |
+Many commands set the value of dot as a side effect. | |
+If so, it is always to the | |
+.Dq result | |
+of the change: the empty string for a deletion, the new text for an insertion,… | |
+.Po | |
+but see the | |
+.Sy s | |
+and | |
+.Sy e | |
+commands | |
+.Pc "." | |
+.Ss Text commands | |
+.Bl -tag -width Ds | |
+.It Sy a/text/ | |
+Insert the text into the file after the range. | |
+Set dot. | |
+.Pp | |
+May also be written as | |
+.Bd -literal -offset indent | |
+ a | |
+ lines | |
+ of | |
+ text | |
+ . | |
+.Ed | |
+.It Sy c \fR or Sy i | |
+Same as | |
+.Sy a "," | |
+but | |
+.Sy c | |
+replaces the text, while | |
+.Sy i | |
+inserts | |
+.Em before | |
+the range. | |
+.It Sy d | |
+Delete the text in range. | |
+Set dot. | |
+.It Sy s/regexp/text/ | |
+Substitute | |
+.Sy text | |
+for the first match to the regular expression in the range. | |
+Set dot to the modified range. | |
+In | |
+.Sy text | |
+the character | |
+.Li "&" | |
+stands for the string that matched the expression. | |
+Backslash behaves as usual unless followed by a digit: | |
+.Sy \[rs]d | |
+stands for the string that matched the subexpression begun by the | |
+.Sy d\fR-th | |
+left parenthesis. | |
+If | |
+.Sy s | |
+is followed immediately by a number | |
+.Sy n "," | |
+as in | |
+.Li "s2/x/y/" "," | |
+the | |
+.Sy n\fR-th | |
+match in the range is substituted. | |
+If the command is followed by | |
+.Sy g "," | |
+as in | |
+.Li "s/x/y/g" "," | |
+all matches in the range are substituted. | |
+.It Sy "m a1" | |
+Move the range to after | |
+.Sy a1 "." | |
+Set dot. | |
+.It Sy "t a1" | |
+Copy the range to after | |
+.Sy a1 "." | |
+Set dot. | |
+.El | |
+.Ss Display commands | |
+.Bl -tag -width Ds | |
+.It Sy p | |
+Print the text in the range. | |
+Set dot. | |
+.It Sy = | |
+Print the line address and character address of the range. | |
+.It Sy =# | |
+Print just the character address of the range. | |
+.El | |
+.Ss File commands. | |
+.Bl -tag -width Ds | |
+.It * Sy "b file-list" | |
+Set the current file to the first file named in the list that | |
+.Nm | |
+also has in its menu. | |
+The list may be expressed | |
+.Sy "<shell-command" | |
+in which case the file names are taken as words | |
+.Pq "in the shell sense" | |
+generated by the shell command. | |
+.It * Sy "B file-list" | |
+Same as | |
+.Sy b "," | |
+except that filenames not in the menu are entered there, and all file names in… | |
+.It * Sy n | |
+Print a menu of files. | |
+The format is: | |
+.Bl -tag -width Ds | |
+.It "' or blank" | |
+indicating the file is modified or clean, | |
+.It "- or +" | |
+indicating the file is unread or has been read | |
+.Po | |
+in the terminal, | |
+.Li "*" | |
+means more than one window is open | |
+.Pc "," | |
+.It ". or blank" | |
+indicating the current file, | |
+.El | |
+a blank, | |
+and the filename. | |
+.It "*" Sy "D file-list" | |
+Delete the named files from the menu. | |
+If no files are named, the current file is deleted. | |
+It is an error to delete a modified file, but a subsequent | |
+.Sy D | |
+will delete such a file. | |
+.El | |
+.Ss I/O commands | |
+.Bl -tag -width Ds | |
+.It "*" Sy "e filename" | |
+Replace the file by the contents of the named external file. | |
+Set dot to the beginning of the file. | |
+.It Sy "r filename" | |
+Replace the text in the range by the contents of the named external file. | |
+Set dot. | |
+.It Sy "w filename" | |
+Write the range | |
+.Po | |
+default | |
+.Li 0,$ | |
+.Pc | |
+to the named external file. | |
+.It "*" Sy "f filename" | |
+Set the file name and print the resulting menu entry. | |
+.El | |
+.Pp | |
+If the file name argument is absent from any of these, the current file name i… | |
+.Sy e | |
+always sets the file name, | |
+.Sy r | |
+and | |
+.Sy w | |
+will do so if the file has no name. | |
+.Bl -tag -width Ds | |
+.It Sy "< shell-command" | |
+Replace the range by the standard output of the shell command. | |
+.It Sy "> shell-command" | |
+Sends the range to the standard input of the shell command. | |
+.It Sy "| shell-command" | |
+Send the range to the standard input, and replace it by the standard output, o… | |
+.It "*" Sy "! shell-command" | |
+Run the shell command. | |
+.It "*" Sy "cd directory" | |
+Change working directory. | |
+If no directory is specified, | |
+.Ev "$HOME" | |
+is used. | |
+.El | |
+.Pp | |
+In any of | |
+.Sy "<" "," | |
+.Sy ">" "," | |
+.Sy "|" ", or" | |
+.Sy "!" "," | |
+if the shell command is omitted, the last shell command | |
+.Pq "of any type" | |
+is substituted. | |
+If | |
+.Nm | |
+is downloaded, | |
+.Sy "!" | |
+sets standard input to | |
+.Pa "/dev/null" "," | |
+and otherwise unassigned output | |
+.Po | |
+.Pa stdout | |
+for | |
+.Sy "!" | |
+and | |
+.Sy ">" "," | |
+.Pa stderr | |
+for all | |
+.Pc | |
+is placed in | |
+.Pa "${HOME}/sam.err" | |
+and the first few lines are printed. | |
+.Ss Loops and conditionals | |
+.Bl -tag -width Ds | |
+.It Sy "x/regexp/ command" | |
+For each match of the regular expression in the range, run the command with do… | |
+Set dot to the last match. | |
+If the regular expression and its slashes are omitted, | |
+.Li "/.*\[rs]n/" | |
+is assumed. | |
+Null string matches potentially occur before every character of the range and … | |
+.It Sy "y/regexp/ command" | |
+Like | |
+.Sy x "," | |
+but run the command for each substring that lies before, between, or after the… | |
+.Sy x "." | |
+There is no default behavior. | |
+Null substrings potentially occur before every character in the range. | |
+.It "*" Sy "X/regexp/ command" | |
+For each file whose menu entry matches the regular expression, make that the c… | |
+If the expression is omitted, the command is run in every file. | |
+.It "*" Sy "Y/regexp/ command" | |
+Same as | |
+.Sy X "," | |
+but for files that do not match the regular expression, and the expression is … | |
+.It Sy "g/regexp/ command" | |
+.It Sy "v/regexp/ command" | |
+If the range contains | |
+.Po | |
+.Sy g | |
+.Pc | |
+or does not contain | |
+.Po | |
+.Sy v | |
+.Pc | |
+a match for the expression, set dot to the range and run the command. | |
+.El | |
+.Pp | |
+These may be nested arbitrarily deeply, but only one instance of either | |
+.Sy X | |
+or | |
+.Sy Y | |
+may appear in a single command. | |
+An empty command in an | |
+.Sy x | |
+or | |
+.Sy y | |
+defaults to | |
+.Sy p ";" | |
+an empty command in | |
+.Sy X | |
+or | |
+.Sy Y | |
+defaults to | |
+.Sy f "." | |
+.Sy g | |
+and | |
+.Sy v | |
+do not have defaults. | |
+.Ss Miscellany | |
+.Bl -tag -width Ds | |
+.It Sy k | |
+Set the current file's mark to the range. | |
+Does not set dot. | |
+.It "*" Sy q | |
+Quit. | |
+It is an error to quit with modified files, but a second | |
+.Sy q | |
+will succeed. | |
+.It "*" Sy "u n" | |
+Undo the last | |
+.Sy n | |
+.Pq "default 1" | |
+top-level commands that changed the contents or name of the current file, and … | |
+Successive | |
+.Sy u | |
+commands move further back in time. | |
+The only commands for which | |
+.Sy u | |
+is ineffective are | |
+.Sy cd "," | |
+.Sy u "," | |
+.Sy q "," | |
+.Sy w "," | |
+and | |
+.Sy D "." | |
+.It Sy empty | |
+If the range is explicit, set dot to the range. | |
+If | |
+.Nm | |
+is downloaded, the resulting dot is selected on the screen; otherwise it is pr… | |
+If no address is specified | |
+.Pq "the command is a newline" | |
+dot is extended in either direction to the line boundaries and printed. | |
+If dot is thereby unchanges, i is set to | |
+.Li ".+1" | |
+and printed. | |
+.El | |
+.Ss Grouping and multiple changes | |
+Commands may be groups by enclosing them in curly braces. | |
+Commands within the braces must appear on separate lines | |
+.Pq "no backslashes are required between commands" "." | |
+Semantically, the opening brance is like a command: it takes an | |
+.Pq optional | |
+address and sets dot for each sub-command. | |
+Commands within the braces are executed sequentially, but changes made by one … | |
+.Pq "see the next paragraph" "." | |
+Braces may be nested arbitrarily. | |
+.Pp | |
+When a command makes a number of changes to a file, as in | |
+.Li "x/re/c/text/" "," | |
+the addresses of all changes to the file are computed in the original file. | |
+If the changes are in sequence, they are applied to the file. | |
+Successive insertions at the same address are catenated into a single insertio… | |
+.Ss The terminal | |
+What follows refers to the behavior of | |
+.Nm | |
+when downloaded, that is, when operating as a display editor on a bitmap displ… | |
+This is the default behavior; invoking | |
+.Nm | |
+with the | |
+.Fl d | |
+.Pq "no download" | |
+option provides access to the command language only. | |
+.Pp | |
+Each file may have zero or more windows open. | |
+Each window is equivalent and is updated simultaneously with changes in other … | |
+Each window has an independent value of dot, indicated by a highlighted substr… | |
+Dot may be in a region not within the window. | |
+There is usually a | |
+.Dq "current window" "," | |
+marked with a dark border, to which typed text and editing commands apply. | |
+The escape key selects | |
+.Pq "sets dot to" | |
+text typed since the last mouse button hit. | |
+.Pp | |
+The button 3 menu controls window operations. | |
+The top of the menu provides the following operators, each of which uses one o… | |
+.Bl -tag -width Ds | |
+.It Sy new | |
+Create a new empty file: | |
+Depress button 3 where one corner of the new rectangle should appear | |
+.Pq "box cursor" "," | |
+and move the mouse while holding down button 3 to the diagonally opposite corn… | |
+.Dq Sweeping | |
+a null rectangle gets a large window disjoint from the command window or the w… | |
+.Nm | |
+window, depending on where the null rectangle is. | |
+.It Sy zerox | |
+Create a copy of an existing window. | |
+After selecting the window to copy with button 1, | |
+sweep out the window for the copy. | |
+.It Sy reshape | |
+Change the size and location of a window. | |
+First click button 3 in the window to be changed | |
+.Pq "gunsight cursor" "." | |
+Then sweep out a window as for the | |
+.Sy new | |
+menu selection. | |
+.It Sy close | |
+Delete the window. | |
+In the last window of a file, | |
+.Sy close | |
+is equivalent to a | |
+.Sy D | |
+for the file. | |
+.It Sy write | |
+Equivalent to a | |
+.Sy w | |
+for the file. | |
+.El | |
+.Pp | |
+Below these operators is a list of available files, starting with | |
+.Sy "~~sam~~" "," | |
+the command window. | |
+Selecting a file from the list makes the most recently used window on that fil… | |
+If no windows are open on the file, the user is prompted to open one. | |
+Files other than | |
+.Sy "~~sam~~" | |
+are marked with one of the characters | |
+.Li "-+*" | |
+according as zero, one, or more windows are open on the file. | |
+A further mark, | |
+.Li "." "," | |
+appears on the file in the current window and a single quote, | |
+.Li "'" "," | |
+on a file modified since last write. | |
+.Pp | |
+The command window, created automatically when | |
+.Nm | |
+starts, is an ordinary window except that text typed to it is interpreted as c… | |
+There is an | |
+.Dq "output point" | |
+that separates commands being typed from previous output. | |
+Commands typed in the command window apply to the current open file\[en]the fi… | |
+.Ss Manipulating text | |
+Typed characters replace the current selection | |
+.Pq dot | |
+in the current window. | |
+Backspace deletes the previous character. | |
+Escape selects | |
+.Pq "sets dot to" | |
+everything typed since the last mouse hit. | |
+.Pp | |
+Button 1 changes selection. | |
+Pointing to a non-current window with button 1 makes it current; within the cu… | |
+Double-clicking selects text to the boundaries of words, lines, quoted strings… | |
+.Pp | |
+Button 2 provides a menu of editing commands: | |
+.Bl -tag -width Ds | |
+.It Sy cut | |
+Delete dot and save the delted text in the snarf buffer. | |
+.It Sy paste | |
+Replace the text in dot by the contents of the snarf buffer. | |
+.It Sy snarf | |
+Save the text in dot in the snarf buffer. | |
+.It Sy look | |
+Search forward for the next occurence of the literal text in dot. | |
+If dot is the null string, the text in the snarf buffer is used. | |
+The snarf buffer is unaffected. | |
+.It Sy <exch> | |
+Exchange the snarf buffer with the current system-wide text selection. | |
+The exchange of a large amount of selected text is truncated to the size of th… | |
+.Pq "currently 4K" | |
+without warning. | |
+.It Sy "/regexp" | |
+Search forward for the next match of the last regular expression typed in a co… | |
+.Pq "Not in command window." | |
+.It Sy send | |
+Send the text in dot, or the snarf buffer if dot is the null string, as if it … | |
+Saves the sent text in the snarf buffer. | |
+.Pq "Command window only." | |
+.El | |
+.Ss Abnormal termination | |
+If | |
+.Nm | |
+terminates other than by a | |
+.Sy q | |
+command | |
+.Pq "by hangup, deleting its window, etc." "," | |
+modified files are saved in an executable file, | |
+.Pq "${HOME}/sam.save" "." | |
+This program, when executed, asks whether to write each file back to an extern… | |
+The answer | |
+.Sy y | |
+causes writing; anything else skips the file. | |
+If a machine crash prevents the creation of a | |
+.P "sam.save" | |
+file, all changes are lost. | |
+If an editing session is difficult to replicate, writing changed files often i… | |
+.Ss Remote execution | |
+.Nm sam | |
+allows the host and terminal parts of the editor to run on diffrent machines, … | |
+.Dq downloading "." | |
+This process can be suppressed with the | |
+.Fl d | |
+option, which then runs only the host part in the manner of | |
+.Xr ed 1 "." | |
+.Pp | |
+Running the host part on another machine is accomplished using the | |
+.Fl r | |
+option, which is used to specify a remote machine name suitable for passing to… | |
+.Ev RSH | |
+environment variable. | |
+.Pp | |
+By default, | |
+.Nm sam | |
+will run a command called | |
+.Nm rsam | |
+as the host-part on the remote machine. | |
+.Nm rsam | |
+opens up an additional control channel on the remote machine, allowing | |
+.Nm sam | |
+to be controlled via the | |
+.Nm B | |
+command on the remote machine as well. | |
+.Pp | |
+The only components of | |
+.Nm sam | |
+that need to be on the remote machine are | |
+.Nm rsam | |
+and | |
+.Nm sam "," | |
+and any command specified as the argument to the | |
+.Fl s | |
+option. | |
+Users may also like to have the | |
+.Nm B | |
+command present on the remote system; invoking this command on the remote syst… | |
+.Po | |
+if | |
+.Nm sam | |
+was invoked with its default remote host command, i.e. | |
+.Nm rsam | |
+.Pc | |
+open files in the local terminal. | |
+This allows users to run the terminal part of | |
+.Nm sam | |
+locally while controlling it via a remote shell connection. | |
+.Ss Controlling running instances of Nm | |
+.Nm B | |
+is a shell command that causes a downloaded instance of | |
+.Nm sam | |
+to load the named files. | |
+The | |
+.Fl r | |
+option causes the instance of | |
+.Nm sam | |
+connected to | |
+.Ar machine | |
+to load the named files; the default is the most-recently started local instan… | |
+.Pp | |
+.Nm B | |
+may also be called on a remote machine, causing the downloaded instance of sam… | |
+.Ss Unicode Text Input | |
+.Nm sam | |
+allows the input of arbitrary Unicode characters from the Basic Multilingual P… | |
+.Pq BMP | |
+via five-character and two-character sequences. | |
+These sequences are entered while holding down the system compose key | |
+.Po | |
+on most keyboards, this key is labeled | |
+.Sy Alt | |
+.Pc "." | |
+.Pp | |
+The first method allows the entry of any code point in the BMP. | |
+While holding down the compose key, an uppercase | |
+.Li X | |
+character is typed, followed by exactly four lowercase hexadecimal digits nami… | |
+.Pp | |
+Commonly used codepoints can be entered with an abbreviated two-character sequ… | |
+These sequence definitions are read from a file called | |
+.Pa ".keyboard" | |
+in the user's home directory. | |
+Each line in this file consists of two characters, followed by any number of s… | |
+Holding down the compose key and typing the two listed characters will insert … | |
+For example, given the | |
+.Pa ".keyboard" | |
+line: | |
+.Bd -literal -offset indent | |
+12 0x00BD | |
+.Ed | |
+.Pp | |
+then typing the characters 1 and 2 while holding down the compose key will ins… | |
+.Pq \[u00BD] | |
+into the file. | |
+.Pp | |
+After the hexadecimal codepoint specification, the rest of the line is ignored… | |
+.Pp | |
+If no | |
+.Pa ".keyboard" | |
+file is present, the following key sequences are defined by default: | |
+.Pp | |
+.TS | |
+box; | |
+c | c | c | c | c | c | c | c | |
+- | - | - | - | - | - | - | - | |
+c | c | c | c | c | c | c | c. | |
+Keys Codepoint Keys Codepoint Keys Codepoin… | |
+!! \[u00A1] c$ \[u00A2] l$ \[u00A3] … | |
+y$ \[u00A5] || \[u00A6] SS \[u00A7] … | |
+cO \[u00A9] sa \[u00AA] << \[u00AB] … | |
+-- \[u00AD] rO \[u00AE] __ \[u00AF] … | |
++- \[u00B1] s2 \[u00B2] s3 \[u00B3] … | |
+mi \[u00B5] pg \[u00B6] .. \[u00B7] … | |
+s1 \[u00B9] so \[u00BA] >> \[u00BB] … | |
+12 \[u00BD] 34 \[u00BE] ?? \[u00BF] … | |
+'A \[u00C1] ^A \[u00C2] ~A \[u00C3] … | |
+oA \[u00C5] AE \[u00C6] ,C \[u00C7] … | |
+'E \[u00C9] ^E \[u00CA] "E \[u00CB] … | |
+'I \[u00CD] ^I \[u00CE] "I \[u00CF] … | |
+~N \[u00D1] `O \[u00D2] 'O \[u00D3] … | |
+~O \[u00D5] "O \[u00D6] mu \[u00D7] … | |
+`U \[u00D9] 'U \[u00DA] ^U \[u00DB] … | |
+'Y \[u00DD] |P \[u00DE] ss \[u00DF] … | |
+'a \[u00E1] ^a \[u00E2] ~a \[u00E3] … | |
+oa \[u00E5] ae \[u00E6] ,c \[u00E7] … | |
+'e \[u00E9] ^e \[u00EA] "e \[u00EB] … | |
+'i \[u00ED] ^i \[u00EE] "i \[u00EF] … | |
+~n \[u00F1] `o \[u00F2] 'o \[u00F3] … | |
+~o \[u00F5] "o \[u00F6] -: \[u00F7] … | |
+`u \[u00F9] 'u \[u00FA] ^u \[u00FB] … | |
+'y \[u00FD] |p \[u00FE] "y \[u00FF] … | |
+.TE | |
+.TS | |
+box; | |
+c | c | c | c | c | c | c | c | |
+- | - | - | - | - | - | - | - | |
+c | c | c | c | c | c | c | c. | |
+Keys Codepoint Keys Codepoint Keys Codepoin… | |
+wq \[u2655] wr \[u2656] wb \[u2657] … | |
+wp \[u2659] bk \[u265A] bq \[u265B] … | |
+bb \[u265D] bn \[u265E] bp \[u265F] … | |
+*b \[u03B2] *g \[u03B3] *d \[u03B4] … | |
+*z \[u03B6] *y \[u03B7] *h \[u03B8] … | |
+*k \[u03BA] *l \[u03BB] *m \[u03BC] … | |
+*c \[u03BE] *o \[u03BF] *p \[u03C0] … | |
+ts \[u03C2] *s \[u03C3] *t \[u03C4] … | |
+*f \[u03C6] *x \[u03C7] *q \[u03C8] … | |
+*A \[u0391] *B \[u0392] *G \[u0393] … | |
+*E \[u0395] *Z \[u0396] *Y \[u0397] … | |
+*I \[u0399] *K \[u039A] *L \[u039B] … | |
+*N \[u039D] *C \[u039E] *O \[u039F] … | |
+*R \[u03A1] *S \[u03A3] *T \[u03A4] … | |
+*F \[u03A6] *X \[u03A7] *Q \[u03A8] … | |
+<- \[u2190] ua \[u2191] -> \[u2192] … | |
+ab \[u2194] V= \[u21D0] =V \[u21D2] … | |
+te \[u2203] pd \[u2202] es \[u2205] … | |
+gr \[u2207] mo \[u2208] !m \[u2209] … | |
+** \[u2217] bu \[u2219] sr \[u221A] … | |
+if \[u221E] an \[u2220] l& \[u2227] … | |
+ca \[u2229] cu \[u222A] is \[u222B] … | |
+~= \[u2243] cg \[u2245] ~~ \[u2248] … | |
+== \[u2261] <= \[u2266] >= \[u2267] … | |
+sp \[u2283] !b \[u2284] ib \[u2286] … | |
+O+ \[u2295] O- \[u2296] Ox \[u2297] … | |
+Tu \[u22A8] lz \[u22C4] el \[u22EF] … | |
+:) \[u263A] ;) \[u263B] | |
+.TE | |
+.Sh ENVIRONMENT | |
+The following environment variables affect the operation of | |
+.Nm sam ":" | |
+.Bl -tag -width Ds | |
+.It Ev FOREGROUND | |
+Sets the foreground color used by | |
+.Nm | |
+to draw its terminal. | |
+Common English color names can be used | |
+.Po | |
+see | |
+.Xr rgb 5 | |
+.Pc "," | |
+or exact colors can be specified as | |
+.Sy "#rrggbb" "," | |
+where | |
+.Sy "rr" "," | |
+.Sy "gg" "," | |
+and | |
+.Sy "bb" | |
+are hexadecimal digits describing the red, green, and blue components of the c… | |
+By default, this is the string | |
+.Dq black "." | |
+.It Ev BACKGROUND | |
+As | |
+.Ev FOREGROUND "," | |
+but describing the background color used to draw the terminal. | |
+By default, this is the string | |
+.Dq white "." | |
+.It Ev FONT | |
+A string representing a | |
+.Xr fc-match 1 | |
+compatible font pattern. | |
+The font described by this pattern will be used to render text in the terminal. | |
+By default, this is the string | |
+.Dq "monospace" "." | |
+.It Ev RSH | |
+The name of a command to be used to connect to a remote machine when | |
+.Nm | |
+is invoked with the | |
+.Fl r | |
+option. | |
+It will be passed at least two arguments: the name of the machine to connect t… | |
+.Po | |
+e.g. | |
+.Nm rsam | |
+.Pc "." | |
+Any additional arguments should be passed to the command on the remote machine. | |
+By default, this is the string | |
+.Dq "ssh" "." | |
+.El | |
+.Sh FILES | |
+.Bl -tag -width Ds | |
+.It Pa "${HOME}/.keyboard" | |
+Provides a mapping of two-character sequences to Unicode code points. | |
+Note that the code points must be in the Basic Multilingual Plane. | |
+.It Pa "${HOME}/sam.save" | |
+Created if | |
+.Nm | |
+terminates abnormally. | |
+Executing this file will prompt the user to restore the files that were being … | |
+.It Pa "${HOME}/sam.err" | |
+Stores output of shell commands executed by | |
+.Nm "." | |
+.El | |
+.Sh SEE ALSO | |
+.Xr ed 1 | |
+.Sh BUGS | |
+When a | |
+.Nm sam | |
+window is resized, the command window may have the wrong size. | |
+.Pp | |
+Under some window managers, resizing the window may cause a panic. | |
+.Pp | |
+.Nm | |
+has issues with compositing window managers like compiz, resulting in some ren… | |
+.Pp | |
+The only human language in which colors may be specified is English. | |
+.Pp | |
+The only human language in which output is generated is English. | |
+.Pp | |
+There is no support for right-to-left text, ligatures, composed characters, or… | |
+\ No newline at end of file | |
diff --git a/doc/sam.1.pdf b/doc/sam.1.pdf | |
Binary files differ. | |
diff --git a/doc/sam.ps b/doc/sam.ps | |
@@ -0,0 +1,8261 @@ | |
+%!PS | |
+%%Version: 3.3.2 | |
+%%DocumentFonts: (atend) | |
+%%Pages: (atend) | |
+%%EndComments | |
+% | |
+% Version 3.3.2 prologue for troff files. | |
+% | |
+ | |
+/#copies 1 store | |
+/aspectratio 1 def | |
+/formsperpage 1 def | |
+/landscape false def | |
+/linewidth .3 def | |
+/magnification 1 def | |
+/margin 0 def | |
+/orientation 0 def | |
+/resolution 720 def | |
+/rotation 1 def | |
+/xoffset 0 def | |
+/yoffset 0 def | |
+ | |
+/roundpage true def | |
+/useclippath true def | |
+/pagebbox [0 0 612 792] def | |
+ | |
+/R /Times-Roman def | |
+/I /Times-Italic def | |
+/B /Times-Bold def | |
+/BI /Times-BoldItalic def | |
+/H /Helvetica def | |
+/HI /Helvetica-Oblique def | |
+/HB /Helvetica-Bold def | |
+/HX /Helvetica-BoldOblique def | |
+/CW /Courier def | |
+/CO /Courier def | |
+/CI /Courier-Oblique def | |
+/CB /Courier-Bold def | |
+/CX /Courier-BoldOblique def | |
+/PA /Palatino-Roman def | |
+/PI /Palatino-Italic def | |
+/PB /Palatino-Bold def | |
+/PX /Palatino-BoldItalic def | |
+/Hr /Helvetica-Narrow def | |
+/Hi /Helvetica-Narrow-Oblique def | |
+/Hb /Helvetica-Narrow-Bold def | |
+/Hx /Helvetica-Narrow-BoldOblique def | |
+/KR /Bookman-Light def | |
+/KI /Bookman-LightItalic def | |
+/KB /Bookman-Demi def | |
+/KX /Bookman-DemiItalic def | |
+/AR /AvantGarde-Book def | |
+/AI /AvantGarde-BookOblique def | |
+/AB /AvantGarde-Demi def | |
+/AX /AvantGarde-DemiOblique def | |
+/NR /NewCenturySchlbk-Roman def | |
+/NI /NewCenturySchlbk-Italic def | |
+/NB /NewCenturySchlbk-Bold def | |
+/NX /NewCenturySchlbk-BoldItalic def | |
+/ZD /ZapfDingbats def | |
+/ZI /ZapfChancery-MediumItalic def | |
+/S /S def | |
+/S1 /S1 def | |
+/GR /Symbol def | |
+ | |
+/inch {72 mul} bind def | |
+/min {2 copy gt {exch} if pop} bind def | |
+ | |
+/show {show} bind def % so later references don't bind | |
+/widthshow {widthshow} bind def | |
+/stringwidth {stringwidth} bind def | |
+ | |
+/setup { | |
+ counttomark 2 idiv {def} repeat pop | |
+ | |
+ landscape {/orientation 90 orientation add def} if | |
+ /scaling 72 resolution div def | |
+ linewidth setlinewidth | |
+ 1 setlinecap | |
+ | |
+ pagedimensions | |
+ xcenter ycenter translate | |
+ orientation rotation mul rotate | |
+ width 2 div neg height 2 div translate | |
+ xoffset inch yoffset inch neg translate | |
+ margin 2 div dup neg translate | |
+ magnification dup aspectratio mul scale | |
+ scaling scaling scale | |
+ | |
+ addmetrics | |
+ 0 0 moveto | |
+} def | |
+ | |
+/pagedimensions { | |
+ useclippath userdict /gotpagebbox known not and { | |
+ /pagebbox [clippath pathbbox newpath] def | |
+ roundpage currentdict /roundpagebbox known and {roundpagebbox}… | |
+ } if | |
+ pagebbox aload pop | |
+ 4 -1 roll exch 4 1 roll 4 copy | |
+ landscape {4 2 roll} if | |
+ sub /width exch def | |
+ sub /height exch def | |
+ add 2 div /xcenter exch def | |
+ add 2 div /ycenter exch def | |
+ userdict /gotpagebbox true put | |
+} def | |
+ | |
+/addmetrics { | |
+ /Symbol /S null Sdefs cf | |
+ /Times-Roman /S1 StandardEncoding dup length array copy S1defs cf | |
+} def | |
+ | |
+/pagesetup { | |
+ /page exch def | |
+ currentdict /pagedict known currentdict page known and { | |
+ page load pagedict exch get cvx exec | |
+ } if | |
+} def | |
+ | |
+/decodingdefs [ | |
+ {counttomark 2 idiv {y moveto show} repeat} | |
+ {neg /y exch def counttomark 2 idiv {y moveto show} repeat} | |
+ {neg moveto {2 index stringwidth pop sub exch div 0 32 4 -1 roll width… | |
+ {neg moveto {spacewidth sub 0.0 32 4 -1 roll widthshow} repeat} | |
+ {counttomark 2 idiv {y moveto show} repeat} | |
+ {neg setfunnytext} | |
+] def | |
+ | |
+/setdecoding {/t decodingdefs 3 -1 roll get bind def} bind def | |
+ | |
+/w {neg moveto show} bind def | |
+/m {neg dup /y exch def moveto} bind def | |
+/done {/lastpage where {pop lastpage} if} def | |
+ | |
+/f { | |
+ dup /font exch def findfont exch | |
+ dup /ptsize exch def scaling div dup /size exch def scalefont setfont | |
+ linewidth ptsize mul scaling 10 mul div setlinewidth | |
+ /spacewidth ( ) stringwidth pop def | |
+} bind def | |
+ | |
+/changefont { | |
+ /fontheight exch def | |
+ /fontslant exch def | |
+ currentfont [ | |
+ 1 0 | |
+ fontheight ptsize div fontslant sin mul fontslant cos div | |
+ fontheight ptsize div | |
+ 0 0 | |
+ ] makefont setfont | |
+} bind def | |
+ | |
+/sf {f} bind def | |
+ | |
+/cf { | |
+ dup length 2 idiv | |
+ /entries exch def | |
+ /chtab exch def | |
+ /newencoding exch def | |
+ /newfont exch def | |
+ | |
+ findfont dup length 1 add dict | |
+ /newdict exch def | |
+ {1 index /FID ne {newdict 3 1 roll put}{pop pop} ifelse} forall | |
+ | |
+ newencoding type /arraytype eq {newdict /Encoding newencoding put} if | |
+ | |
+ newdict /Metrics entries dict put | |
+ newdict /Metrics get | |
+ begin | |
+ chtab aload pop | |
+ 1 1 entries {pop def} for | |
+ newfont newdict definefont pop | |
+ end | |
+} bind def | |
+ | |
+% | |
+% A few arrays used to adjust reference points and character widths in some | |
+% of the printer resident fonts. If square roots are too high try changing | |
+% the lines describing /radical and /radicalex to, | |
+% | |
+% /radical [0 -75 550 0] | |
+% /radicalex [-50 -75 500 0] | |
+% | |
+% Move braceleftbt a bit - default PostScript character is off a bit. | |
+% | |
+ | |
+/Sdefs [ | |
+ /bracketlefttp [201 500] | |
+ /bracketleftbt [201 500] | |
+ /bracketrighttp [-81 380] | |
+ /bracketrightbt [-83 380] | |
+ /braceleftbt [203 490] | |
+ /bracketrightex [220 -125 500 0] | |
+ /radical [0 0 550 0] | |
+ /radicalex [-50 0 500 0] | |
+ /parenleftex [-20 -170 0 0] | |
+ /integral [100 -50 500 0] | |
+ /infinity [10 -75 730 0] | |
+] def | |
+ | |
+/S1defs [ | |
+ /underscore [0 80 500 0] | |
+ /endash [7 90 650 0] | |
+] def | |
+% | |
+% Tries to round clipping path dimensions, as stored in array pagebbox, so they | |
+% match one of the known sizes in the papersizes array. Lower left coordinates | |
+% are always set to 0. | |
+% | |
+ | |
+/roundpagebbox { | |
+ 7 dict begin | |
+ /papersizes [8.5 inch 11 inch 14 inch 17 inch] def | |
+ | |
+ /mappapersize { | |
+ /val exch def | |
+ /slop .5 inch def | |
+ /diff slop def | |
+ /j 0 def | |
+ 0 1 papersizes length 1 sub { | |
+ /i exch def | |
+ papersizes i get val sub abs | |
+ dup diff le {/diff exch def /j i def} {pop} ifelse | |
+ } for | |
+ diff slop lt {papersizes j get} {val} ifelse | |
+ } def | |
+ | |
+ pagebbox 0 0 put | |
+ pagebbox 1 0 put | |
+ pagebbox dup 2 get mappapersize 2 exch put | |
+ pagebbox dup 3 get mappapersize 3 exch put | |
+ end | |
+} bind def | |
+ | |
+%%EndProlog | |
+%%BeginSetup | |
+mark | |
+/linewidth 0.5 def | |
+/#copies 1 store | |
+/landscape false def | |
+/resolution 720 def | |
+setup | |
+2 setdecoding | |
+%%EndSetup | |
+%%Page: 1 1 | |
+/saveobj save def | |
+mark | |
+1 pagesetup | |
+12 B f | |
+(The Text Editor)2 827 1 2343 1230 t | |
+12 CW f | |
+(sam)3200 1230 w | |
+10 I f | |
+(ROB PIKE)1 441 1 2659 1470 t | |
+10 R f | |
+(AT&T Bell Laboratories)2 993 1 2383 1650 t | |
+(Murray Hill, New Jersey 07974)4 1267 1 2246 1770 t | |
+10 I f | |
+(ABSTRACT)2643 2150 w | |
+10 CW f | |
+(Sam)1080 2446 w | |
+10 R f | |
+( textual com-)2 541( A)1 129( text editor intended for bitmap displays.)6 166… | |
+( the mouse-driven, cut-and-paste interface to make complex)7 2450(mand langua… | |
+( language is characterized by the composi-)6 1719( The)1 208( editing tasks e… | |
+( treat-)1 237( The)1 207( regular expressions to describe the structure of th… | |
+(ment of files as a database, with changes logged as atomic transactions, guid… | |
+(mentation and makes a general `undo' mechanism straightforward.)7 2672 1 1080… | |
+10 CW f | |
+(Sam)1330 3202 w | |
+10 R f | |
+( a low-bandwidth stream, one)4 1224(is implemented as two processes connected… | |
+( it can run)3 435( Therefore)1 453( the other the editing algorithms.)5 1360(… | |
+( with both pro-)3 600(with the display process in a bitmap terminal and the e… | |
+( process in the terminal and the edi-)7 1442(cesses on a bitmap-equipped host… | |
+( can even run without a bitmap)6 1243( suppressing the display process, it)5 … | |
+(terminal.)1080 3802 w | |
+( 17, number)2 502(This paper is reprinted from Software\320Practice and Exper… | |
+(11, pp. 813-845.)2 658 1 1080 4078 t | |
+6 R f | |
+(KEY WORDS)1 354 1 1080 4318 t | |
+8 R f | |
+( Undo)1 258( expressions)1 391( Caches Regular)2 642(Text editors)1 382 4 149… | |
+10 B f | |
+(Introduction)720 4438 w | |
+10 CW f | |
+(Sam)720 4594 w | |
+10 R f | |
+( that combines cut-and-paste interactive editing with an unusual command)9 30… | |
+( is written as two programs: one, the `host)8 1775( It)1 123( composition of … | |
+( the command language and provides file access; the other,)9 2428(part,' runs… | |
+( bitmap display and supports the)5 1337(the `terminal part,' runs asynchronou… | |
+( host part may be even run in isolation on an ordinary terminal to edit)14 28… | |
+( command language, much like a traditional line editor, without assistance fr… | |
+( runs on a Blit)4 583( often, the terminal part)4 952(display. Most)1 573 3 7… | |
+6 R f | |
+(1)2828 5264 w | |
+10 R f | |
+(terminal \(actually on a Teletype DMD 5620, the pro-)8 2153 1 2887 5314 t | |
+( Sun com-)2 423(duction version of the Blit\), whose host connection is an or… | |
+(puter the host and display processes run on a single machine, connected by a … | |
+10 CW f | |
+(Sam)970 5710 w | |
+10 R f | |
+( unlike)1 282( has no facilities for multiple fonts, graphics or tables,)9 22… | |
+(MacWrite,)720 5830 w | |
+6 R f | |
+(2)1149 5780 w | |
+10 R f | |
+(Bravo,)1211 5830 w | |
+6 R f | |
+(3)1480 5780 w | |
+10 R f | |
+(Tioga)1542 5830 w | |
+6 R f | |
+(4)1775 5780 w | |
+10 R f | |
+(or Lara.)1 322 1 1837 5830 t | |
+6 R f | |
+(5)2159 5780 w | |
+10 R f | |
+( this)1 176( \(Throughout)1 561( has a rich command language.)5 1266(Also unl… | |
+(paper, the phrase)2 708 1 720 5950 t | |
+10 I f | |
+(command language)1 800 1 1468 5950 t | |
+10 R f | |
+( commands activated from the mouse)5 1575(refers to textual commands;)3 1157 … | |
+(form the)1 344 1 720 6070 t | |
+10 I f | |
+(mouse language.)1 679 1 1092 6070 t | |
+10 R f | |
+(\))1771 6070 w | |
+10 CW f | |
+(Sam)1856 6070 w | |
+10 R f | |
+(developed as an editor for use by programmers, and tries to join the styles)1… | |
+(of the Unix text editor)4 968 1 720 6190 t | |
+10 CW f | |
+(ed)1733 6190 w | |
+6 R f | |
+(6,7)1853 6140 w | |
+10 R f | |
+( cut-and-paste editors by providing a comfortable)6 2100(with that of interac… | |
+( The)1 214( language driven by regular expressions.)5 1658(mouse-driven inter… | |
+( language, and acquired a notation for describing the)8 2186(command language… | |
+( a dataflow-like syntax for specifying)5 1594(structure of files more richly … | |
+(changes.)720 6670 w | |
+(The interactive style was influenced by)5 1576 1 970 6826 t | |
+10 CW f | |
+(jim)2573 6826 w | |
+10 R f | |
+(,)2753 6826 w | |
+6 R f | |
+(1)2778 6776 w | |
+10 R f | |
+( for the Blit, and by)5 798(an early cut-and-paste editor)3 1144 2 2835 6826 t | |
+10 CW f | |
+(mux)4805 6826 w | |
+10 R f | |
+(,)4985 6826 w | |
+6 R f | |
+(8)5010 6776 w | |
+10 R f | |
+(the Blit window system.)3 1000 1 720 6946 t | |
+10 CW f | |
+(Mux)1779 6946 w | |
+10 R f | |
+(merges the original Blit window system,)5 1662 1 1993 6946 t | |
+10 CW f | |
+(mpx)3688 6946 w | |
+10 R f | |
+(,)3868 6946 w | |
+6 R f | |
+(1)3893 6896 w | |
+10 R f | |
+(with cut-and-paste editing,)2 1084 1 3956 6946 t | |
+8 S1 f | |
+(__________________)720 7046 w | |
+8 R f | |
+(* Unix is a registered trademark of AT&T.)7 1365 1 720 7146 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 1 1 | |
+%%Page: 2 2 | |
+/saveobj save def | |
+mark | |
+2 pagesetup | |
+10 R f | |
+(- 2 -)2 166 1 2797 480 t | |
+( like a multiplexed version of)5 1199(forming something)1 768 2 720 840 t | |
+10 CW f | |
+(jim)2717 840 w | |
+10 R f | |
+(that edits the output of \(and input to\) command ses-)9 2113 1 2927 840 t | |
+(sions rather than files.)3 882 1 720 960 t | |
+( paper describes the command language, then the mouse language, and explains)… | |
+( first of the host part, then of the)8 1290( is followed by a description of … | |
+( influenced the design of)4 991( principle that)2 555( A)1 122(terminal part.… | |
+10 CW f | |
+(sam)2952 1356 w | |
+10 R f | |
+(is that it should have no explicit limits, such as)9 1882 1 3158 1356 t | |
+( honor these two)3 663( To)1 161( secondary consideration is that it be effic… | |
+( breaking them into)3 783(goals together requires a method for efficiently ma… | |
+( control of the command language.)5 1407(lines, perhaps while making thousand… | |
+10 CW f | |
+(Sam)4460 1716 w | |
+10 R f | |
+('s method)1 400 1 4640 1716 t | |
+( updates may)2 541( These)1 295( as a transaction database, implementing chan… | |
+( is achieved through a collection of caches that minimizes)9 2328( Efficiency… | |
+(disc traffic and data motion, both within the two parts of the program and be… | |
+(The terminal part of)3 804 1 970 2232 t | |
+10 CW f | |
+(sam)1800 2232 w | |
+10 R f | |
+( interesting is how the two halves of the edi-)9 1791( More)1 268(is fairly s… | |
+( data structure that)3 746( is achieved through a)4 888( This)1 231(tor stay … | |
+(organizes the communications and is maintained in parallel by both halves.)10… | |
+(The last part of the paper chronicles the writing of)9 2067 1 970 2628 t | |
+10 CW f | |
+(sam)3069 2628 w | |
+10 R f | |
+( lessons that were learned)4 1057(and discusses the)2 702 2 3281 2628 t | |
+(through its development and use.)4 1324 1 720 2748 t | |
+( is composed largely of two papers of reasonable length: a description of the… | |
+(user interface of)2 653 1 720 3024 t | |
+10 CW f | |
+(sam)1401 3024 w | |
+10 R f | |
+( are combined because the implementa-)5 1597( They)1 258(and a discussion of … | |
+(tion is strongly influenced by the user interface, and vice versa.)10 2528 1 … | |
+10 B f | |
+(The Interface)1 579 1 720 3384 t | |
+10 CW f | |
+(Sam)720 3540 w | |
+10 R f | |
+( names may be provided when it is invoked:)8 1765( File)1 206(is a text edito… | |
+9 CW f | |
+(sam file1 file2 ...)3 1026 1 1008 3710 t | |
+10 R f | |
+( are not read until necessary to)6 1255( Files)1 251( files and discard unnee… | |
+( file is read; the)4 673( operations apply to an internal copy made when the)… | |
+( simplify the discussion, the)4 1124( To)1 162( is changed only by an explici… | |
+(internal copy is here called a)5 1144 1 720 4250 t | |
+10 I f | |
+(file)1889 4250 w | |
+10 R f | |
+(, while the disc-resident original is called a)7 1714 1 2017 4250 t | |
+10 I f | |
+(disc file.)1 339 1 3756 4250 t | |
+10 CW f | |
+(Sam)970 4406 w | |
+10 R f | |
+( connected to a bitmap display that presents a cut-and-paste editor driven by… | |
+( special window, called the)4 1116( this mode, the command language is still … | |
+10 CW f | |
+(sam)720 4646 w | |
+10 I f | |
+(window,)930 4646 w | |
+10 R f | |
+( editing may be)3 637( Cut-and-paste)1 616( as commands to be executed in the… | |
+(used in any window \320 even in the)7 1467 1 720 4766 t | |
+10 CW f | |
+(sam)2223 4766 w | |
+10 R f | |
+( mode of operation,)3 812( other)1 241( The)1 216(window to construct command… | |
+(invoked by starting)2 774 1 720 4886 t | |
+10 CW f | |
+(sam)1520 4886 w | |
+10 R f | |
+(with the option)2 608 1 1726 4886 t | |
+10 CW f | |
+(-d)2360 4886 w | |
+10 R f | |
+( the mouse or bitmap display,)5 1193(\(for `no download'\), does not use)5 13… | |
+( even on an ordinary terminal, interactively or)7 1849(but still permits edit… | |
+(from a script.)2 535 1 720 5126 t | |
+(The following sections describe first the command language \(under)8 2783 1 9… | |
+10 CW f | |
+(sam -d)1 360 1 3789 5282 t | |
+10 R f | |
+(and in the)2 418 1 4185 5282 t | |
+10 CW f | |
+(sam)4640 5282 w | |
+10 R f | |
+(win-)4857 5282 w | |
+( two languages are nearly independent, but connect through the)9 2573( These)… | |
+10 I f | |
+(current text,)1 488 1 720 5522 t | |
+10 R f | |
+(described below.)1 676 1 1233 5522 t | |
+10 B f | |
+(The Command Language)2 1090 1 720 5762 t | |
+10 R f | |
+( array of characters \(that is, a string\); the)8 1644(A file consists of its… | |
+10 I f | |
+(name)4125 5918 w | |
+10 R f | |
+(of the associated)2 671 1 4369 5918 t | |
+(disc file; the)2 498 1 720 6038 t | |
+10 I f | |
+(modified bit)1 483 1 1245 6038 t | |
+10 R f | |
+( those of the disc file; and a substring of the)10 1758(that states whether t… | |
+(contents, called the)2 786 1 720 6158 t | |
+10 I f | |
+(current text)1 472 1 1540 6158 t | |
+10 R f | |
+(or)2046 6158 w | |
+10 I f | |
+(dot)2163 6158 w | |
+10 R f | |
+( the current text is a null string, dot falls)9 1689( If)1 126( and 2\).)2 32… | |
+( The)1 211(between characters.)1 791 2 720 6278 t | |
+10 I f | |
+(value)1753 6278 w | |
+10 R f | |
+( the location of the current text; the)7 1441(of dot is)2 340 2 2000 6278 t | |
+10 I f | |
+(contents)3811 6278 w | |
+10 R f | |
+(of dot are the charac-)4 866 1 4174 6278 t | |
+(ters it contains.)2 610 1 720 6398 t | |
+10 CW f | |
+(Sam)1381 6398 w | |
+10 R f | |
+(imparts to the text no two-dimensional interpretation such as columns or fiel… | |
+( the idea of a `line' of text as understood by most Unix programs \320 a)15 3… | |
+(sequence of characters terminated by a newline character \320 is only weakly … | |
+(The)970 6794 w | |
+10 I f | |
+(current file)1 453 1 1156 6794 t | |
+10 R f | |
+( in the)2 264( current text is therefore dot)5 1141( The)1 211(is the file to… | |
+( explicitly name a particular file or piece of text, the command is)12 2827( … | |
+( presence of multiple files and consider)6 1629( the moment, ignore the)4 988… | |
+(editing a single file.)3 794 1 720 7154 t | |
+( for non-editing commands such as writing the file to disc,)10 2354( Except)1… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 2 2 | |
+%%Page: 3 3 | |
+/saveobj save def | |
+mark | |
+3 pagesetup | |
+10 R f | |
+(- 3 -)2 166 1 2797 480 t | |
+cleartomark | |
+saveobj restore | |
+%ps_include: begin | |
+save | |
+/ed {exch def} def | |
+{} /showpage ed | |
+{} /copypage ed | |
+{} /erasepage ed | |
+{} /letter ed | |
+currentdict /findfont known systemdict /findfont known and { | |
+ /findfont systemdict /findfont get def | |
+} if | |
+36 dict dup /PS-include-dict-dw ed begin | |
+/context ed | |
+count array astore /o-stack ed | |
+%ps_include: variables begin | |
+/llx 24 def | |
+/lly 241 def | |
+/urx 587.76 def | |
+/ury 550.6 def | |
+/w 0 def | |
+/o 0 def | |
+/s 0 def | |
+/cx 2880 def | |
+/cy -2220 def | |
+/sx 4320 def | |
+/sy 2520 def | |
+/ax 0.5 def | |
+/ay 0.5 def | |
+/rot 0 def | |
+%ps_include: variables end | |
+{llx lly urx ury} /bbox ed | |
+{newpath 2 index exch 2 index exch dup 6 index exch | |
+ moveto 3 {lineto} repeat closepath} /boxpath ed | |
+{dup mul exch dup mul add sqrt} /len ed | |
+{2 copy gt {exch} if pop} /min ed | |
+{2 copy lt {exch} if pop} /max ed | |
+{transform round exch round exch A itransform} /nice ed | |
+{6 array} /n ed | |
+n defaultmatrix n currentmatrix n invertmatrix n concatmatrix /A ed | |
+urx llx sub 0 A dtransform len /Sx ed | |
+0 ury lly sub A dtransform len /Sy ed | |
+llx urx add 2 div lly ury add 2 div A transform /Cy ed /Cx ed | |
+rot dup sin abs /S ed cos abs /C ed | |
+Sx S mul Sy C mul add /H ed | |
+Sx C mul Sy S mul add /W ed | |
+sy H div /Scaley ed | |
+sx W div /Scalex ed | |
+s 0 eq {Scalex Scaley min dup /Scalex ed /Scaley ed} if | |
+sx Scalex W mul sub 0 max ax 0.5 sub mul cx add /cx ed | |
+sy Scaley H mul sub 0 max ay 0.5 sub mul cy add /cy ed | |
+urx llx sub 0 A dtransform exch atan rot exch sub /rot ed | |
+n currentmatrix initgraphics setmatrix | |
+cx cy translate | |
+Scalex Scaley scale | |
+rot rotate | |
+Cx neg Cy neg translate | |
+A concat | |
+bbox boxpath clip newpath | |
+w 0 ne {gsave bbox boxpath 1 setgray fill grestore} if | |
+end | |
+gsave | |
+%ps_include: inclusion begin | |
+/picstr 98 string def | |
+24 241 translate | |
+563.76 309.60 scale | |
+ | |
+783 430 1 [783 0 0 -430 0 430] | |
+{currentfile picstr readhexstring pop} image | |
+ | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+02001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfffffffe7fffffffe227ff0feffffffffffffff3ff87ff11ffcffffffff | |
+fffffffe7fe7ffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffde01ffffe7fffffffe227fe7f9f833900fffffef3ff3e0711ffcffdffff1 | |
+e0fffffe7fe7ffe7f3e0ffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfcfffffe7fffffffe233fe7f3f3b39e7fffffcf9ff3e7311ffcff9fffe9 | |
+ce7fffffffe7ffc7e3ce7fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfcfe3ffe4f879cfff773f80f3e7f3de7f0e73019fc0673bbffc8e03ffe9 | |
+ce7ff3907f07ffa7d3ce7fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfcfe3ffe27339cfff779fe7e7e7f25e7e6673cfcff3e73bbffc479fffd9 | |
+ce7ff3de7e67ff67b3fe7fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfcfe3ffe7279cdfff779fe7e7e7f25e7ce737cfcff3e73bbffce79fffd9 | |
+ce7ff25e7ce7ffe7f3fe7fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02ffdfcfffffe7279c3fffffcfe7e7e7f25e7ce70fcfe7f3e67ffffce79fffb9 | |
+ce7ff25e7ce7ffe7f3fcffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fcfffffe7279f7fffffcfe7e7e7f93e7c07dfcfe7f3e0fffffce79fff80 | |
+ce7ff25e7ce7ffe7f3f9ffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fcfffffe7279e1fffffe7e7e7e7f93e7cff87cff3f3e7fffffce79fff80 | |
+ce7ff93e7ce7ffe7f3f3ffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fcfe3ffe7279d9fffffe7e7e7e7f93e7cff67cff3f3e7fffffce79ffff9 | |
+ce7ff93e7ce7ffe7f3e7ffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fcfe3ffe67339cffffff3e7e7f3b93e7e6673cff9f3e7fffffce79ffff9 | |
+ce7ff93e7e47ffe7f3c07fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fcfe3ffe0f879cffffff381f3f8393e7f0e73e1f9c0e7fffffce7c3ffe0 | |
+e0fff9300f27ff81c0c07fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889ffffffffffffffffffff9fff3fffffffffffffffcffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221ffffffffffffffffffff9fff9fffffffffffffffcffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889ffffffffffffffffffffffffeffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffe7fffffffe227ff0feffffffffffffff3ff87ff11ffcffffffff | |
+fffffffe7fe7fffffffffffcfffcffffffffffffffffffefffffffffffffffff | |
+fffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221e07ffffe7fffffffe227fe7f9f833903fffffff3ff3e0711ffcffdffff1 | |
+e0fffffe7fe7ff83c1fffffcff7cfffffffffffffeffff9c03ffffffffffff3e | |
+0fffff00ffffffffff3fffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889e73ffffe7fffffffe233fe7f3f3b3939fffffff9ff3e7311ffcff9fffe9 | |
+ce7fffffffe7ff399cfffffffe7cfffffffffffffcffff3f9ffffffffffffe3c | |
+e7ffffe7ffffffffff9fffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221e73e3ffe4f879cfff773f80f3e7f3d39e0f07279fc0673bbffc8e03ffe9 | |
+ce7ff3907f07ff399cffe720f80c8fffff9cfff0701fff3f9fffe1ffe73cfd3c | |
+ffffffe7fff87ff9cf9fffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889e73e3ffe27339cfff779fe7e7e7f2539ce67313cff3e73bbffc479fffd9 | |
+ce7ff3de7e67ff399cffe7bcfe7c47ffff9effe73cfffe7f9fffccffe73cfb3c | |
+ffffffe7fff33ff9cfcfffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221e77e3ffe7279cdfff779fe7e7e7f253bfe67f39cff3e73bbffce79fffd9 | |
+ce7ff25e7ce7ff399cffe4bcfe7ce7ffff92ffff3cfffe7f9fff9cfff37cff3c | |
+ffffffe7ffe73ff9efcfffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889e0fffffe7279c3fffffcfe7e7e7f2507fe63f39e7f3e67ffffce79fffb9 | |
+ce7ff25e7ce7ff819cffe4bcfe7ce7ffff92ffff3cfffe7f9fff9cfff0e01f3c | |
+0fffffe7ffe73ffccfcfffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221e67ffffe7279f7fffffcfe7e7e7f9333e070739e7f3e0fffffce79fff80 | |
+ce7ff25e7ce7fff99cffe4bcfe7ce7ffff92fff03cfffe7f9fff80fffde01f3c | |
+e7ffffe7ffe03ffcdfcfffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889e67ffffe7279e1fffffe7e7e7e7f9333ce7e339f3f3e7fffffce79fff80 | |
+ce7ff93e7ce7fff99cfff27cfe7ce7ffffc9ffe73cfffe7f9fff9ffff87cff3c | |
+e7ffffe7ffe7fffcdfcfffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221e73e3ffe7279d9fffffe7e7e7e7f9339ce7f339f3f3e7fffffce79ffff9 | |
+ce7ff93e7ce7fff99cfff27cfe7ce7ffc7c9ffe73cfffe7f9fc79ff1f67cff3c | |
+e78fffe7f1e7fc7e3fcfffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889e73e3ffe67339cffffff3e7e7f3b9339cc67333f9f3e7fffffce79ffff9 | |
+ce7ff93e7e47ff399cfff27cfe7ce7ffc7c9ffe63cfffe7f9fc7ccf1e73cff3c | |
+e78fffe7f1f33c7e3fcfffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221e71e3ffe0f879cffffff381f3f839338e270707f9c0e7fffffce7c3ffe0 | |
+e0fff9300f27ff83c1fff2601f0ce7ffc7c9fff13e1fff3f9fc7e1f1e73ffc0e | |
+0f8fffe7f1f87c7f3f9fffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889ffffffffffffffffffff9fff3ffffffffffff3ffcffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff3fffffffffffffffff | |
+ffcfffffffffffff7f9fffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221ffffffffffffffffffff9fff9ffffffffffff3ffcffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff9fffffffffffffffff | |
+ffcffffffffffffe7f3fffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889ffffffffffffffffffffffffeffffffffffff3fffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffff | |
+ff9ffffffffffffc7effffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889e0fe7ffffffff0fffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fcfe7fffffffe7fffffffff807fffffffbfffff03ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fcffffffffffe7ffffffffff3ffffffff3fffff39ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fcf07c8f87ff80c670e5bfff3fffc3ffc070fff39ffe73fffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fcfe7c4733ffe7e066601fff3fff99fff3e67ff39ffe7bfffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fcfe7ce673ffe7e64f249fff3fff39fff3cf3ff3bffe4bfffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fcfe7ce673ffe7e7cf249fff3fff39fff3cf3ff07ffe4bfffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fcfe7ce603ffe7e7cf249fff3fff01fff3cf3ff33ffe4bfffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fcfe7ce67fffe7e7cf249fff3fff3ffff3cf3ff33fff27fffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fcfe7ce67fffe7e7cf249fff3f8f3ffff3cf3ff39f1f27fffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fcfe7ce733ffe7e7e6649fff3f8f99fff3e67ff39f1f27fffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221e0100ce787ff81c1f0e49fff3f8fc3fff870fff38f1f27fffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffff80000000800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221c00000000001fffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff3f80000001800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889c00000000001fff87ffffffffffffffffffffcfffcfffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff0f80078c67f00000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221c00000000001fff3fffffffffc0ffffffffffcfffcffdfffc1f8fffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff1f800ccc61800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889c00000000001fff3fffffffffce7fffffffffffffcff9fff9cf4fffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff3f8018cc61800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221c7c73398f0c7ffc0633872dffce7ffe1ffe320fe0c8e03ff9cf4fffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7d80180c61800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889cc63f1f998c3fff3f033300ffce7ffccfff03cfccc479ffffcecfffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffff980180c61800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221c063319b0cdbfff3f327924ffcefff9cfff33cf9cce79ffffcecfffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffef080180c61800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889c06301830cdbfff3f3e7924ffc1fff9cfff3fcf9cce79ffff9dcfffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffce080180c61800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221c7e301830cdbfff3f3e7924ffccfff80fff3fcf9cce79ffff3c07ffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fff8c0000ccee1800000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889cc6301830c6dfff3f3e7924ffccfff9ffff3fcf9cce79fffe7c07ffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fff08000078760f00000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221cc6301830c6dfff3f3e7924ffce7c79ffff3fcf9cce79fffcffcfffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe00000000000000000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889cce30181986dfff3f3f3324ffce7c7ccfff3fcfc8ce79fff80fcfffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffc10000000000000000ffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221c767c3e0f06dffc0e0f8724ffce3c7e1ffe0e01e4ce7c3ff80f07ffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ff837ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889c00000000001ffffffffffffffffffffffffffffcffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffc77ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221c00000000001fffffffffffffffffffffffffff9cffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffef7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889c00000000001fffffffffffffffffffffffffffc1ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fffffffff7ffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffe7ffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889f3ffffffffcffffff9fffffc47ffffffcffffffffc47ffffe7ffe7fffff | |
+fffffffffffffffffcfffffe1ff83fffffffffffffffffffffffffffffffffff | |
+ffff7fc9f078380f0ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221f3ffffffffcffffff9fffffc47dfffffcfffffff7c47ffffe7fbe7fffff | |
+ffffffff7ffffffffcfffffcffff3ffffff7ffffffffffffffffffffffffffff | |
+ffff7fc4e7339e7e67feffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889f3fffffffffffffffffffffc479fffffcffffffe7c47fffffff3e7fffff | |
+fffffffe7ffffffffcfffffcffff3fffffe7ffffffffffffffffffffffffffff | |
+ffff7fce7f33fe7ce7feffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221f27c3ce7fe0f91ce41f83ffeee0387ffc8f0f8380eefff3907c0647ffff | |
+ce7ff8380fff8723e0fff0f01fff3f078380fff07198ce1e73ffffffffffffff | |
+ffff7fce7f31fe7ce7feffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889f1399ce7ffcf88ce79f39ffeef9f33ffc466739e7eefff3de7f3e23ffff | |
+cf7ff39e7fff3311ccffe67cffff3e7339e7ffe7381c0cce7bffffffffffffff | |
+ffff7fce70383e7c07feffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221f393ce6fffcf9ccf79f3fffeef9e79ffce4f33fe7eefff25e7f3e73ffff | |
+c97fff9e7ffe73399cffcf3cffff3ff33fe7ffff399cc9e64bffffffffffffff | |
+ffff7fce673f1e7cfffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889f393ce1fffcf9ce679f1ffffff9e79ffce4f31fe7fffff25e7f3e73ffff | |
+c97fff9e7ffe73399cffcf3cffff3ff31fe7ffff39fcf9e64bffffffffffffff | |
+ffff7fce673f9e7cfffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221f393cfbfffcf9ce6f9f83fffff9e79ffce4f383e7fffff25e7f3e73ffff | |
+c97ff81e7ffe03399cffcf3cffff3f0383e7fff039fcf9e64bffffffffffffff | |
+ffff7fcce6339e7e67feffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889f393cf0fffcf9ce6f9ff1fffff9e79ffce4f3f1e7fffff93e7f3e73ffff | |
+e4fff39e7ffe7f399cffcf3cffff3e73f1e7ffe739fcf9e727ffffffffffffff | |
+ffff7fc1f1383f0f0ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221f393cecfffcf9cf1f9ff9fffff9e79ffce4f3f9e7fffff93e7f3e73ffe3 | |
+e4fff39e7ffe7f399cffcf3cffff3e73f9e7ffe739fcf9e727ffffffffffffff | |
+ffff7fcffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889f3399ce7ffcf9cf1f9f39fffff9f33ffce66739e7fffff93e7f3e73ffe3 | |
+e4fff31e7fff3339c8ffe67cffff3e6339e7ffe639fcfccf27ffffffffffffff | |
+ffff7fcffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221f07c3ce7fe019cf1c0383fffffc387ffce70f83f0fffff9300f8673ffe3 | |
+e4fff89f0fff8739e4fff0f03ff8071383f0fff130783e1f27ffffffffffffff | |
+ffff7fcffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fffffffffff87feffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fffffffffff3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fffffffffff3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fe0e47838cc07feffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fce62339c0f3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fcfe73f9ccf3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fc7e73f9cff3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fe0e7381cff3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffc67339cff3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffe67339cff3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+02001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fce67331cff3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ff81 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+00007fe0e738983c0ffe00000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+00007ffffffffffffffe00000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+00007ffffffffffffffe00000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+00007ffffffffffffffe00000000000000000000000000000000000000000000 | |
+0001 | |
+0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffc1fffffcffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9fffffcffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffe1e7ffffffffff3ffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9fffffcffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffcfe7fff03fffff3ffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9f87c3ce7ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffcffffff03ffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9f3399cefffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffff0107f077fff9383f87fffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9e793ccdfffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffcfe7e677fff89f3f33fffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9e793ccbfffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffcfe7ce71fff9cf3e73fffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9e793cc3fffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fff80fffffcfe7ce7c7ff9cf3e7ffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9e793cc9fffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fff80fffffcfe7ce7f3ff9cf3e7ffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9e793cccfffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffcfe7ce7f3ff9cf3e7ffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fff9f3399ce7ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffff1fffcfe7ce7f3c79cf3e7ffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffc0387c3ce7ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffff1fffcfe7e4673c799f3f33fffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffff1fff0300f2707c78380787fffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffe7ffff9fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffce7ffff9fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffffffe0fffff9fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffefffffffefffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ff9ffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffcfffffffe7ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ff9ffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ff9cb7399cf3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ff3ffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ff3c03399cf9ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ff3c1c6633879cfffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fe7c9339cdfcffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fe79ce0703339efffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fc7c9339c3fc7feffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fe7fce67327992fffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fe7c9339f7fcffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fcffce7f3e7992fffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ff3c9339e1f9ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fcfc0e7f3e7992fffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ff9c9339d9f3ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f9f9ce7f3e79c9fffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffcc93119ce7ffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f9f9ce7f3e79c9fffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffec93899cefffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f3f98e7f3f33c9fffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f3fc4c1e0f87c9fffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7ffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fe7fffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fe7fffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fcffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7fcf07198ce1e73effffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7f9e7381c0cce7beffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7f9ff399cc9e64beffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7f3ff39fcf9e64beffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7f3f039fcf9e64beffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7e7e739fcf9e727effffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7e7e739fcf9e727effffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7cfe639fcfccf27effffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff7cff130783e1f27effffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff79fffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff79fffffffffffffeffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221dffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+00000000000000000000000000000000000000000000077fef81fffff3ffffff | |
+fceec00c0303e633f060300060060fc77ffe7feffff8f07fffff3ff3fff3f9f0 | |
+7fffff3fdf3fffffffffffffffdfff80e07ff01c1f8ffffffffffffffe000000 | |
+0001 | |
+0ffffffffffffffffffffffffffffffffffffffffffff77fef9ffffff3ffffff | |
+fcee600c060626330000300030060c677ffe7fcffff4e73ffffffff3ffe3f1e7 | |
+3fffffff9f3fffffffffffffff9fff80e07ff019cf4ffffffffffffffeffffff | |
+ffe1 | |
+0ffffffffffffffffffffffffffffffffffffffffffff77fef9ff1fff27c3ce7 | |
+fc44603f860c061303e0301e301fcc622ffe4701fff4e73ff9c83f83ffd3e9e7 | |
+3ff9c83e0323ffffe4739ffe0e03fffeefffffd9cf4ffffffffffffffeffffff | |
+ffe1 | |
+0e001ffffffffffffffffffffffffffffffffffffffff77fef9ff1fff1399ce7 | |
+fc44300c0c0c06d30060303318060c622ffe23cfffece73ff9ef3f33ffb3d9ff | |
+3ff9ef3f9f11ffffe233dffce79ffffcefffff99cecffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffffcffffe7fffff77fef9ff1fff393ce6f | |
+fc44300c0c0c06d30060306318060c622ffe73cfffece73ff92f3e73fff3f9ff | |
+3ff92f3f9f39ffffe7325fffe79ffff9e3ffff39cecffffffffffffffeffffff | |
+ffe1 | |
+0e221fffffffffffffffbffffffffffffcffffe7fffff77fef83fffff393ce1f | |
+fc00180c0c0c06d3e06030630c060cc00ffe73cfffdce73ff92f3e73fff3f9fe | |
+7ff92f3f9f39ffffe7325fffe79ffff3f8fffe79cdcffffffffffffffeffffff | |
+ffe1 | |
+0e889fffffffffffffff3fffffffffffffffffe7fffff77fef9ffffff393cfbf | |
+fc00180c0c0c03630060307f0c060f800ffe73cfffc0673ff92f3e73fff3f9fc | |
+fff92f3f9f39ffffe7325ffe079fffe7fe7ffcf9cc07fffffffffffffeffffff | |
+ffe1 | |
+0e221f19e1f0673c3c1c0707ffc1ffe720f91f070f39f77fef9ffffff393cf0f | |
+fc000c0c0c0c03630060306006060c000ffe73cfffc0673ffc9f3e73fff3f9f9 | |
+fffc9f3f9f39ffffe7393ffce79fffe7fe7ffcf9cc07fffffffffffffeffffff | |
+ffe1 | |
+0e889f81cce6673999cf3e73ff9cffe7bcf88e66673df77fef9ff1fff393cecf | |
+fc000c0c0c0c03630060306006060c000ffe73cffffce73ffc9f3e73fff3f9f3 | |
+fffc9f3f9f39fff1e7393ffce79fffcffe78f9f9cfcffffffffffffffeffffff | |
+ffe1 | |
+0e221f999cce673399ff3e7ffffcffe4bcf9cce4f325f77fef9ff1fff3399ce7 | |
+fc00060c0c0623630060303303060c000ffe73cffffce73ffc9f3f23fff3f9e0 | |
+3ffc9f3f9f39fff1e7393ffcc79fffcfce78f9f9cfcffffffffffffffeffffff | |
+ffe1 | |
+0e889f9f9cce673398ff3e3ffffcffe4bcf9cce4f325f77fef9ff1fff07c3ce7 | |
+fc00063f0603e36303fdfe1e031f8c000ffe73e1fff0707ffc980793ffc0e060 | |
+3ffc9807c339fff1e7393ffe27c3ffcfe0f8f9fc1f07fffffffffffffeffffff | |
+ffe1 | |
+0e221f9f80ce67301c1f3f07ffc0ffe4bcf9cce4f325f77fefffffffffffffff | |
+fc0003000600000000000000018000000fffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffcfffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889f9f9fce6733ff8f3fe3ff9cfff27cf9cce4f393f77fefffffffffffffff | |
+fc0003000300000000000000018000000fffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffcfffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221f9f9fce6733ffcf3ff3ff9cfff27cf9cce4f393f77fefffffffffffffff | |
+fc0000000080000000000000000000000fffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffff9fffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889f9fcce4623999cf3e73ff98fff27cf9ce466793f77fefffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221f07e1f2713c3c1f8707ffc4fff26019cf270f93f77fefffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffe7ffffffffffffffffffffffffffffffff77fefffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221ffffffe7ffffffffffffffffffffffffffffffff77fefffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffe7ffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221ffffffffffffffffffffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fffe0ce7ffffffffffffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fffcece7ffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fff9fcf7ff23e1ce7fffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fff9fc97ff11cccf7fffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fff9fc97ff399cc97fffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fff9fc97ff399cc97fffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fff9fe4fff3980c97fffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fff9fe4fff399fe4ffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fc79fe4fff399fe4fffc7fffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fc7cee4fff39cce4fffc7fffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fc7e0e4fff39e1e4fffc7fffffffffffffffffff7222f07f3ffffffff87 | |
+fffffffffffffffffffffffffffff3ffff87c3ffffffffffff0f87ffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fffffffffffffffffffe7fffffffffffffffffff7088fe7f3ffffffff3f | |
+ffffffffe0f83fffffffefffffe733ffff3f9fffffffe07ffe7f3fffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fffffffffffffffffffe7fffffffffffffffffff7222fe7ffffffffff3f | |
+ffffffffe6739fffffffcfffffe733ffff3f9fffffffe73ffe7f3fffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fffffffffffffffffffcffffffffffffffffffff7088fe783e47c3ffc06 | |
+33872dffe7339ffc8fff01c3ffe23279cc0603c38cffe733980c078719ffe0ff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221ffffffffffffffffffffffffffffffffffffffff7222fe7f3e2399fff3f | |
+033300ffe73f9ffc47ffcf99ffe23139cf3f9f99c0ffe7339e7f3f3381ffce7f | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffffffffffffffff7088fe7f3e7339fff3f | |
+327924ffe73f9ffce7ffcf3cffe93399cf3f9f39ccffe7739e7f3e7399ffcfff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fffe0ce7ffffffffffffffffffffffffffffffff7222fe7f3e7339fff3f | |
+3e7924ffe73f3ffce7ffcf3cffe93399cf3f9f39cfffe0f39e7f3e739fffc7ff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fffcece7ffffffffffffffffffffffffffffffff7088fe7f3e7301fff3f | |
+3e7924ffe73e7ffce7ffcf3cffe93399cf3f9f01cfffe7739e7f3e039fffe0ff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fff9fcf7ff39e1c670f39fffffffffffffffffff7222fe7f3e733ffff3f | |
+3e7924ffe73cfffce7ffcf3cffe93399cf3f9f3fcfffe7339e7f3e7f9ffffc7f | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fff9fc97ff39cce066739fffffffffffffffffff7088fe7f3e733ffff3f | |
+3e7924ffe739fe3ce7ffcf3cffef3399cf3f9f3fcff1e7339e7f3e7f9fe3fe7f | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fff9fc97ff9b9ce64f39bfffffffffffffffffff7222fe7f3e7399fff3f | |
+3f3324ffe6701e3ce7ffcf99ffef33388f3f9f99cff1e7311e7f3f339fe3ce7f | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fff9fc97ff879ce7cf387fffffffffffffffffff7088f0080673c3ffc0e | |
+0f8724ffe0f01e3ce7ffe1c3ffef307c4c0e07c383f1e078981c0f8707e3e0ff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fff9fe4fffef80e7cf3effffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fff9fe4fffc39fe7cf3c3fffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fc79fe4fffb39fe7cf3b3fffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889fc7cee4fff39cce7e6739fffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221fc7e0e4fff39e1c1f0f39fffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221ffffffffffffffffffffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221ffffffffffffffffffffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221ffffffffffffffffffffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221f878cfffffffffffffffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889f33c0fffffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221e79ccfffffffffffffffffffffffffffffffffff7222fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889e79cffffffffffffffffffffffffffffffffffff7088fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221e79cffffffffffffffffffffffffffffffffffff7000fffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889e79cffffffffffffffffffffffffffffffffffff7ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e221e79cffffffffffffffffffffffffffffffffffff7ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffff | |
+ffe1 | |
+0e889f33cffffffffffffffffffffffffffffffffffff0000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000ffffff | |
+ffe1 | |
+0e221f8783ffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffffe7fffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffe0ce7ffffffffe7fffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffcece7ffffffffe7fffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fff9fcf7ff19e1e0e478393f0ffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fff9fc97ff81ccce6233989e67fffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfff9fc97ff999ccfe73f99cce7fffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0effdfff9fc97ff9f9cc7e73f99cce7fffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fff9fe4fff9f80e0e73819cc07fffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fff9fe4fff9f9ffc673399ccfffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fc79fe4fff9f9ffe673399ccffffc7fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fc7cee4fff9fccce6733199e67ffc7fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fc7e0e4fff07e1e0e738983f0fffc7fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffff9ffffffe7fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffff9ffffffe7fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffff9ffffffcffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fcffffffff3fffffffffffffffff3ffffffffffffffffffffffffffffff | |
+fffffe1fffffffffffcfffffffffffffff07fffffffffffffffffffffffffffc | |
+fffffffffff9fff9ffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fcff7fffff3fffffffffffffffdf3ffffffffffffffffffffffffffffff | |
+fffffcfffffffffff7cfffffffffffffffe7fffffffffffffffff7fffffffffc | |
+fffffffffff9fef9ffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffe7fffff3fffffffffffffff9f3ffffffffffffffffffffffffffffff | |
+fffffcffffffffffe7cfffffffffffffffe7ffffffffffffffffe7fffffffffc | |
+fffffffffffffcf9ffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221e0f80fff8723c1c8f83c3c1ffe0323e1ffcb7879ce0f87ffe1ce63383c3 | |
+c67ff018ce1cb7ff80c8f87ff9ce0e7383e7fff07198ce1e73ff80e1fff83ffc | |
+9f0f39ffce41f0191fffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fcfe7fff33119cc4733999cfff9f11ccffc03339cce733ffccce7033999 | |
+e07ffcfc0ccc03ffe7c4733ff9cce67339e7ffe7381c0cce7bffe7ccfff39ffc | |
+4e6739ffcf79fcf88fffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fcfe7ffe7339fcce673399ffff9f399cffc92799ccfe73ff9cce7333f3c | |
+e67ffcfcc9e493ffe7ce673ff9ccfe73f9e7ffff399cc9e64bffe79e7fff9ffc | |
+e4f39bffc979fcf9cfffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fcfe7ffe7f39fcce673398ffff9f399cffc92799cc7e73ff9fce73f1f3c | |
+e7fffcfcf9e493ffe7ce673ff9cc7e73f9e7ffff39fcf9e64bffe79e7fff9ffc | |
+e4f387ffc979fcf9cfffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fcfe7ffe7f39c0ce67301c1fff9f3980ffc92799ce0e03ff9fce73f833c | |
+e7fffcfcf9e493ffe7ce603ff9ce0e7381e7fff039fcf9e64bffe79e7ff81ffc | |
+e4f3efffc979fcf9cfffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fcfe7ffe7f399cce6733ff8fff9f399fffc92799cfc67fff9fce73ff13c | |
+e7fffcfcf9e493ffe7ce67fff9cfc67339e7ffe739fcf9e727ffe79e7ff39ffc | |
+e4f3c3ffe4f9fcf9cfffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fcfe7ffe7f399cce6733ffcfff9f399fffc92799cfe67fff9fce73ff93c | |
+e7fffcfcf9e493ffe7ce67fff9cfe67339e7ffe739fcf9e727ffe79e7ff39ffc | |
+e4f3b3ffe4f9fcf9cfffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fcfe7fff333998ce723999cfff9f39ccffc933388ce733ffccc473f3999 | |
+e7fffcfcfccc93ffe7ce733ff88ce62331e7ffe639fcfccf27ffe7ccfff31ffc | |
+ce6739ffe4f9fcf9cfffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221e01f0fff8739c4ce793c3c1fffc339e1ffc9387c4e0f87ffe1e260f83c3 | |
+c1fff0383e1c93fff0ce787ffc4e0f138900fff130783e1f27fff0e1fff89ffc | |
+1f0f39ffe4c03e19cfffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffffff3ffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffff07ffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffff0783fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffffe7f3fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffe7f3fffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f83ffe0cb783e7f3fff838cc670f39fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f39ffce40339e7f3fff39c0e06673dfffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ff9ffcfc93f9e7f3ffff9cce64f325fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ff9ffc7c93f9e7f3ffff9cfe7cf325fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f81ffe0c9381e7f3fff81cfe7cf325fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f39fffc49339e7f3fff39cfe7cf393fffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f39fffe49339e7f3fff39cfe7cf393e3fffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f31ffce49331e7f3fff31cfe7e6793e3fffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f89ffe0c938900807ff8983c1f0f93e3fffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000 | |
+000000000000001fffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffff3fe7fffffffffffffffffffffff3fffffffffffffffffffff | |
+fffffff9ffffffffffffff3fffffffffcffffe79ffffffffffffffffffc00003 | |
+006000000000001ffffffffffffffffff07fffff3fffffffffffffffffffffff | |
+ffe1 | |
+0e221f03fffffdf3fe7ffffffff7fffdffffffffdf3fffffffffffffffffffff | |
+fffffff9ffffffffffffff3fff7fffffcffffe79ffffffbfffffffffffc00003 | |
+006010000000001ffffffffff7fffffffe7fffff3fffffffffffffffffffffff | |
+ffe1 | |
+0e889fcffffff9f3ffffffffffe7fff9ffffffff9f3fffffffffffffffffffff | |
+fffffff9ffffffffffffff3ffe7ffffffffffe7fffffff3fffffffffffc00003 | |
+000030000000001fffffffffe7fffffffe7fffff3fffffffffffffffffffffff | |
+ffe1 | |
+0e221fcf91ffe032307e0fff8380e0e03c3ffffe0323e1ffcb7879ce0f87ff2d | |
+e0e73ff93f0fff39c1f0f83ff80e1ffe0f91f041fc3c1c0787ffc1c8ffc7c733 | |
+63e0fe731f1ccc7ffc6787c380e0e47c1e7f0fff279cffffffffffffffffffff | |
+ffe1 | |
+0e889fcf88fff9f11e7ce7ff39e7ce79f99fffff9f11ccffc03339cce733ff00 | |
+ce673ff89e67ff399ce6733ffe7ccfffcf88e679f999cf3f33ff9cc47fcc63f3 | |
+b060303f318fcc7ffe073399e7ce62399e7e67ff139cffffffffffffffffffff | |
+ffe1 | |
+0e221fcf9cfff9f39e7cffff3fe7fe79f39fffff9f399cffc92799ccfe73ff24 | |
+fe67bff9cce7ff399fce673ffe79e7ffcf9cce79f39fcf3e73fffcce7fc06333 | |
+18603033018ccc3ffe667339e7fe67339e7ce7ff399effffffffffffffffffff | |
+ffe1 | |
+0e889fcf9cfff9f39e7c7fff1fe7fe79f39fffff9f399cffc92799cc7e73ff24 | |
+fe733ff9cce7ff398fce673ffe79e7ffcf9cce79f3ffcf3e73fffcce7fc06303 | |
+18603030018c067ffe7e733fe7fe67339e7ce7ff39ccffffffffffffffffffff | |
+ffe1 | |
+0e221fcf9cfff9f39e7e0fff83e7e079f01fffff9f3980ffc92799ce0e03ff24 | |
+e0737ff9cc07ff39c1c0673ffe79e7ffcf9cce79f3fc0f3e03ffc0ce7fc7e303 | |
+186030301f8c065ffe7e033fe7e067339e7c07ff39cdffffffffffffffffffff | |
+ffe1 | |
+0e889fcf9cfff9f39e7fc7fff1e7ce79f3ffffff9f399fffc92799cfc67fff24 | |
+ce737ff9ccffff39f8cfe73ffe79e7ffcf9cce79f3f9cf3e7fff9cce7fcc6303 | |
+18603030318c065ffe7e7f3fe7ce67339e7cffff39cdffffffffffffffffffff | |
+ffe1 | |
+0e221fcf9cfff9f39e7fe7fff9e7ce79f3fe3fff9f399fffc92799cfe67fff24 | |
+ce78fff9ccffff39fccfe73ffe79e7ffcf9cce79f3f9cf3e7fff9cce7fcc6303 | |
+18603030318c039ffe7e7f3fe7ce67339e7cffff39e3ffffffffffffffffffff | |
+ffe1 | |
+0e889fcf9cfff9f39e7ce7ff39e7cc79f99e3fff9f39ccffc933388ce733ff24 | |
+cc78fff99e67ff119ce6723ffe7ccfffcf9ce479f9998f3f33ff98ce7fcce303 | |
+30603030338c039ffe7f3399e7cc67391e7e67ff33e3ffffffffffffffffffff | |
+ffe1 | |
+0e221f039cfffc33900e0fff83f0e27c3c3e3fffc339e1ffc9387c4e0f87ff24 | |
+e27cfff83f0fff89c1f0f93fff0e1ffe019cf2403c3c4f8787ffc4ce7fc767c3 | |
+e3fc1e7c1d9f019ffc1f87c3f0e2673c900f0fff07f3ffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffff3fffffffffffffffffffffffffff | |
+fffdffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000 | |
+000000000000011fffffffffffffffff9ffffffffff7ffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffff3fffffffffffffffffffffffffff | |
+fff9ffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000 | |
+000000000000031ffffffffffffffff39fffffffffe7ffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffffffe7fffffffffffffffffffffffffff | |
+fff1ffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000 | |
+000000000000071ffffffffffffffff83fffffffffc7ffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffe7fffffff9fffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffe7ffffff83ffffffff3ffffffff3ffffffffffffff9ff | |
+fffffffffffffffe7fffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffffe7fffffff9ffffdfeffffffff83fffffdffffffffffffff | |
+fffffffffffffffffffe7fffffff3ffffffff3ffffffff3fdffffffbfffef9ff | |
+fffffffffffffffe7fbfffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffff9ffff9fcffffffff39fffff9ffffffffffffff | |
+fffffffffffffffffffe7fffffff3fffffffffffffffffff9ffffff3fffcf9ff | |
+ffffffffffffffffff3fffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f278cf0f078307c8f83ff93ce60301c3c8fff39ffe0e03ffc3c8f87ffe1 | |
+e1e3323e1c67ff8391f07ff19e1f3f8783c183e47c1ff83e03ffc1c07ff0191f | |
+0fff8793c9f0f8307c0787ffe1e1e3323e1c67ffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f13c0e667339e7c4733ff89ce79fcf99c47fff9ffce79fff99c4733ffcc | |
+ccf0311cce07ff3988e67ff81ccf3f33399cf3e2399fff3f9fff9cf3fffcf88e | |
+67ff3389c4e6739e7f3f33ffccccf0311cce07ffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f39ccce67f3fe7ce673ff9cce79fcf3cce7fff9fffe79fff3cce673ff9c | |
+9e733399ce67fff99cce7ff999cf3e73f99ff3e7339fff3f9ffffcf3fffcf9cc | |
+e7fe799cce4f33fe7f3e73ff9c9e733399ce67ffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f39cfce63f1fe7ce673ff9cce79fcf3cce7ffc7fffe79fff3cce673ff9f | |
+9e73f399ce7ffff99cce7ff9f9cf3e73f98ff3e7339fff3f9ffffcf3fffcf9cc | |
+e7fe799cce4f31fe7f3e73ff9f9e73f399ce7fffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f39cfc070783e7ce673ff9cce79fcf3cce7fff9ffe079fff3cce603ff9f | |
+9e73f3980e7fff819cce7ff9f80f3e0381c1f3e7339fff3f9fffc0f3fffcf9cc | |
+07fe799cce4f383e7f3e03ff9f9e73f3980e7fffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f39cfcffe3f1e7ce673ff9cce79fcf3cce7fff9ffce79fff3cce67fff9f | |
+9e73f399fe7fff399cce7ff9f9ff3e7f39f8f3e7339fff3f9fff9cf3fffcf9cc | |
+fffe799cce4f3f1e7f3e7fff9f9e73f399fe7fffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f39cfcfff3f9e7ce673ff9cce79fcf3cce7fff9ffce79fff3cce67fff9f | |
+9e73f399fe7fff399cce7ff9f9ff3e7f39fcf3e7339fff3f9fff9cf3fffcf9cc | |
+fffe799cce4f3f9e7f3e7fff9f9e73f399fe7f8fffffffffffffffffffffffff | |
+ffe1 | |
+0e889f33cfe667339e7ce723ff99c479fcf99ce7ff39ffcc79fff99ce733ffcc | |
+ccf3f39cce7fff319ce47ff9fccf3f33319cf3e7391fff3f9fff98f3fffcf9ce | |
+67ff3399cce6739e7f3f33ffccccf3f39cce7f8fffffffffffffffffffffffff | |
+ffe1 | |
+0e221f0783f0f078300ce793ff83e27c3e1c3ce7ff83ffe27c3ffc3ce787ffe1 | |
+e1e0f39e1c1fff899cf27ff07e18078789c180673c9ff807c3ffc4f87ffe19cf | |
+0fff8783c1f0f8300f8787ffe1e1e0f39e1c1f8fffffffffffffffffffffffff | |
+ffe1 | |
+0e889f3ffffffffffffffff3ffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffff9fffffffffffffffffffff | |
+ffffff9fcfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f3ffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffff39fffffffffffffffffffff | |
+ffffff9fcfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f3fffffffffffffff07ffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffffffffffffffffff83fffffffffffffffffffff | |
+ffffff9fcfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffff9fffffffc1fffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f39fffffffffffffffffffffff9ffffffbf9fffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f39ffffffffffffffffffffffffffffff3f9fffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f11c3c6787ffe1e1e4739e1c8c1fc391c079f39ffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f1199e0733ffcccce2339ccc479f9988f3f9f39ffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f493ce6673ff9c9e6733d9cce79f399cf3f9f3dffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f493ce7e73ff9f9e673999cce79f399cf3f9f99ffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f493ce7e03ff9f9e6739b80ce79f019cf3f9f9bffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f493ce7e7fff9f9e6739b9fce79f3f9cf3f9f9bffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f793ce7e7fff9f9e673c79fce79f3f9cf3f9fc7e3ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f7999e7f33ffcccce73c7ccce79f999cf3f9fc7e3ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f79c3c1f87ffe1e1e73c7e1ce403c39cf8403e7e3ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffeff3ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffcff3ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffff8fe7ffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f3fffffffffffffffffffffffffffffff3fffff07fffff3fffffffe0fe7 | |
+ffe7ffffcfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f3ffffbfdffffffff07ffffffffffffff3fffffe7fffff3ffffffffcfe7 | |
+ffe7ffffcfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f3ffff3f9fffffffe73ffffffffffffffffffffe7fffff3ffffffffcfff | |
+ffe7ffffcfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f279cc06038791ffe73ff2de0e73ffc183cb727e7ce7ff27e1fff87cf07 | |
+f0e73c3e0fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f139cf3f9f3388ffff3ff00ce673ff9cf3c0313e7ce7ff13ccfff33cfe7 | |
+e667799ccfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f399cf3f9e799cffff3ff24fe67bff9ff3c9339e7cf7ff399cffe73cfe7 | |
+ce66f399cfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f399cf3f9e799cfff8fff24fe733ff8ff3c9339e7e67ff399cffe7fcfe7 | |
+cfe5f399cfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f399cf3f9e799cffff3ff24e0737ffc1f3c9339e7e6fff3980ffe7fcfe7 | |
+cfe1f019cfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f399cf3f9e799cffff3ff24ce737fff8f3c9339e7e6fff399fffe7fcfe7 | |
+cfe4f3f9cfffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f399cf3f9e799cffff3ff24ce78ffffcf3c9339e7f1fff399fffe7fcfe7 | |
+cfe673f9cf1fffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f3388f3f9f339cffe73ff24cc78fff9cf3c9333e7f1fff33ccfff33cfe7 | |
+e667399c8f1fffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f07c4f87c3879cfff07ff24e27cfffc1804930700f9fff07e1fff860100 | |
+f0e73c3e4f1fffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffffdffffffffff3ffffbffffffffffffffff | |
+ffffffffff9fffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffffffffffffffffff9ffffffffff3ffff3ffffffffffffffff | |
+ffffffffff9fffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffffffffffffff1ffffffffff3fffe3ffffffffffffffff | |
+ffffffffff3fffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fff9fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fff9fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fff9fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f3991f0e33c39cc9f0f23ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f3d88e6703999cc4e6711ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f259cce733399cce4f339ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f259cce73f399cce4f339ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f259cc073f019cce4f339ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f939ccff3f3f9cce4f339ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f939ccff3f3f9cce4f339ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889f939ce673f9988cce6739ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221f939cf0e0fc3c4c1f0f39ffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffcffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221ffffffffffffffcffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889ffffffffffffffcffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e221fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e889fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0e001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffe1 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+0001 | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffff | |
+showpage | |
+%ps_include: inclusion end | |
+grestore | |
+PS-include-dict-dw begin | |
+o 0 ne {gsave A defaultmatrix /A ed llx lly nice urx ury nice | |
+ initgraphics 0.1 setlinewidth boxpath stroke grestore} if | |
+clear o-stack aload pop | |
+context end restore | |
+%ps_include: end | |
+/saveobj save def | |
+mark | |
+8 I f | |
+(Figure 1. A typical)3 623 1 720 3580 t | |
+8 CW f | |
+(sam)1370 3580 w | |
+8 I f | |
+( The)1 167(screen, with the editing menu presented.)5 1320 2 1541 3580 t | |
+8 CW f | |
+(sam)3055 3580 w | |
+8 I f | |
+(\(command language\) window is in the middle, with file)8 1814 1 3226 3580 t | |
+( partially obscured window is a)5 1029( The)1 164( user interface makes it ea… | |
+( Each)1 206( typing and mouse operations apply, as indicated by its heavy bor… | |
+( The)1 162(window has its current text highlighted in reverse video.)8 1810 2… | |
+8 CW f | |
+(sam)2714 3880 w | |
+8 I f | |
+( string on the last visible line, indi-)7 1121(window's current text is the n… | |
+( also Figure 2.)3 470( See)1 150(cated by a vertical bar.)4 740 3 720 3980 t | |
+10 R f | |
+( and leave dot set to the text resulting from the change.)11 2202(most comman… | |
+(For example, the delete command,)4 1389 1 720 4340 t | |
+10 CW f | |
+(d)2135 4340 w | |
+10 R f | |
+(, deletes the text in dot, replacing it by the null string and setting dot to… | |
+( change command,)2 767( The)1 213(the result.)1 402 3 720 4460 t | |
+10 CW f | |
+(c)2135 4460 w | |
+10 R f | |
+(, replaces dot by text delimited by an arbitrary punctuation character,)10 28… | |
+( Thus,)1 275(conventionally a slash.)2 913 2 720 4580 t | |
+9 CW f | |
+(c/Peter/)1008 4750 w | |
+10 R f | |
+(replaces the text in dot by the string)7 1429 1 720 4930 t | |
+10 CW f | |
+(Peter)2174 4930 w | |
+10 R f | |
+(. Similarly,)1 473 1 2474 4930 t | |
+9 CW f | |
+(a/Peter/)1008 5100 w | |
+10 R f | |
+(\(append\) adds the string after dot, and)6 1516 1 720 5280 t | |
+9 CW f | |
+(i/Peter/)1008 5450 w | |
+10 R f | |
+( three leave dot set to the new text,)8 1389( All)1 178(\(insert\) inserts be… | |
+10 CW f | |
+(Peter)3343 5630 w | |
+10 R f | |
+(.)3643 5630 w | |
+( lexically terminates a command.)4 1335(Newlines are part of the syntax of co… | |
+( it is often convenient to insert)6 1282( since)1 242( But)1 207(Within the i… | |
+(multiple lines of text,)3 856 1 720 6026 t | |
+10 CW f | |
+(sam)1601 6026 w | |
+10 R f | |
+(has a special syntax for that case:)6 1330 1 1806 6026 t | |
+9 CW f | |
+(a)1008 6196 w | |
+(some lines of text)3 972 1 1008 6306 t | |
+(to be inserted in the file,)5 1458 1 1008 6416 t | |
+(terminated by a period)3 1188 1 1008 6526 t | |
+(on a line by itself)4 1026 1 1008 6636 t | |
+(.)1008 6746 w | |
+10 R f | |
+(In the one-line syntax, a newline character may be specified by a C-like esca… | |
+9 CW f | |
+(c/\\n/)1008 7096 w | |
+10 R f | |
+(replaces dot by a single newline character.)6 1692 1 720 7276 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 3 3 | |
+%%Page: 4 4 | |
+/saveobj save def | |
+mark | |
+4 pagesetup | |
+10 R f | |
+(- 4 -)2 166 1 2797 480 t | |
+10 CW f | |
+(Sam)970 840 w | |
+10 R f | |
+(also has a substitute command,)4 1241 1 1175 840 t | |
+10 CW f | |
+(s)2441 840 w | |
+10 R f | |
+(:)2501 840 w | |
+9 CW f | |
+(s/)1008 1010 w | |
+9 I f | |
+(expression)1116 1010 w | |
+9 CW f | |
+(/)1501 1010 w | |
+9 I f | |
+(replacement)1555 1010 w | |
+9 CW f | |
+(/)2000 1010 w | |
+10 R f | |
+( if dot is the)4 530( Thus,)1 288( expression.)1 490(substitutes the replacem… | |
+(string)720 1310 w | |
+10 CW f | |
+(Peter)973 1310 w | |
+10 R f | |
+(, the command)2 591 1 1273 1310 t | |
+9 CW f | |
+(s/t/st/)1008 1480 w | |
+10 R f | |
+(changes it to)2 517 1 720 1660 t | |
+10 CW f | |
+(Pester)1268 1660 w | |
+10 R f | |
+( general,)1 349(. In)1 164 2 1628 1660 t | |
+10 CW f | |
+(s)2172 1660 w | |
+10 R f | |
+(is unnecessary, but it was inherited from)6 1653 1 2263 1660 t | |
+10 CW f | |
+(ed)3947 1660 w | |
+10 R f | |
+( has some conve-)3 711(and it)1 231 2 4098 1660 t | |
+( instance, the replacement text may include the matched text, specified by)11… | |
+10 CW f | |
+(&)4525 1780 w | |
+10 R f | |
+(:)4585 1780 w | |
+9 CW f | |
+(s/Peter/Oh, &, &, &, &!/)4 1296 1 1008 1950 t | |
+10 R f | |
+(There are also three commands that apply programs to text:)9 2376 1 970 2166 t | |
+9 CW f | |
+(<)1008 2336 w | |
+9 I f | |
+(Unix program)1 513 1 1116 2336 t | |
+10 R f | |
+( the)1 149( Similarly,)1 450(replaces dot by the output of the Unix program.)… | |
+10 CW f | |
+(>)3254 2516 w | |
+10 R f | |
+(command runs the program with dot as its)7 1699 1 3341 2516 t | |
+(standard input, and)2 763 1 720 2636 t | |
+10 CW f | |
+(|)1508 2636 w | |
+10 R f | |
+( example,)1 388( For)1 189(does both.)1 411 3 1593 2636 t | |
+9 CW f | |
+(| sort)1 324 1 1008 2806 t | |
+10 R f | |
+( special sig-)2 483( newlines have no)3 724( Again,)1 321(replaces dot by the… | |
+( these)1 235(nificance for)1 512 2 720 3106 t | |
+10 CW f | |
+(sam)1497 3106 w | |
+10 R f | |
+( text acted upon and resulting from these commands is not neces-)11 2665(comm… | |
+(sarily bounded by newlines, although for connection with Unix programs, newli… | |
+(obey conventions.)1 727 1 720 3346 t | |
+(One more command:)2 843 1 970 3502 t | |
+10 CW f | |
+(p)1838 3502 w | |
+10 R f | |
+( I summarizes)2 560( Table)1 277(prints the contents of dot.)4 1019 3 1923 35… | |
+10 CW f | |
+(sam)3804 3502 w | |
+10 R f | |
+('s commands.)1 555 1 3984 3502 t | |
+(The value of dot may be changed by specifying an)9 2015 1 970 3658 t | |
+10 I f | |
+(address)3010 3658 w | |
+10 R f | |
+( simplest address is)3 778( The)1 206(for the command.)2 709 3 3347 3658 t | |
+(a line number:)2 577 1 720 3778 t | |
+9 CW f | |
+(3)1008 3948 w | |
+10 R f | |
+(refers to the third line of the file, so)8 1417 1 720 4128 t | |
+9 CW f | |
+(3d)1008 4298 w | |
+10 R f | |
+( 3.)1 111(deletes the third line of the file, and implicitly renumbers the li… | |
+(\(This is one of the few places where)7 1485 1 720 4598 t | |
+10 CW f | |
+(sam)2236 4598 w | |
+10 R f | |
+( Line)1 239(deals with lines directly.\))3 1028 2 2447 4598 t | |
+10 CW f | |
+(0)3745 4598 w | |
+10 R f | |
+( string at the begin-)4 797(is the null)2 407 2 3836 4598 t | |
+( a command consists of only an address, a)8 1846( If)1 137(ning of the file.)… | |
+10 CW f | |
+(p)3429 4718 w | |
+10 R f | |
+(command is assumed, so typing an)5 1504 1 3536 4718 t | |
+(unadorned)720 4838 w | |
+10 CW f | |
+(3)1173 4838 w | |
+10 R f | |
+( are a couple of other basic addresses: a period addresses)10 2325( There)1 2… | |
+(dot itself; and a dollar sign \()6 1127 1 720 4958 t | |
+10 CW f | |
+($)1847 4958 w | |
+10 R f | |
+(\) addresses the null string at the end of the file.)10 1872 1 1907 4958 t | |
+( the address)2 477( Thus,)1 278( single substring of the file.)5 1109(An addr… | |
+10 CW f | |
+(3)3779 5114 w | |
+10 R f | |
+(addresses the characters after)3 1173 1 3867 5114 t | |
+( A)1 125( file.)1 186(the second newline of the file through the third newlin… | |
+10 I f | |
+(compound address)1 755 1 3574 5234 t | |
+10 R f | |
+(is constructed by)2 683 1 4357 5234 t | |
+(the comma operator)2 798 1 720 5354 t | |
+9 I f | |
+(address1)1008 5524 w | |
+9 CW f | |
+(,)1333 5524 w | |
+9 I f | |
+(address2)1387 5524 w | |
+10 R f | |
+( the substring of the file from the beginning of)9 1860(and addresses)1 551 2… | |
+10 I f | |
+(address1)3157 5704 w | |
+10 R f | |
+(to the end of)3 505 1 3544 5704 t | |
+10 I f | |
+(address2)4075 5704 w | |
+10 R f | |
+( example,)1 389(. For)1 215 2 4436 5704 t | |
+(the command)1 543 1 720 5824 t | |
+10 CW f | |
+(3,5p)1290 5824 w | |
+10 R f | |
+(prints the third through fifth lines of the file and)9 1936 1 1557 5824 t | |
+10 CW f | |
+(.,$d)3520 5824 w | |
+10 R f | |
+( the begin-)2 429(deletes the text from)3 824 2 3787 5824 t | |
+(ning of dot to the end of the file.)8 1296 1 720 5944 t | |
+(These addresses are all absolute positions in the file, but)9 2247 1 970 6100… | |
+10 CW f | |
+(sam)3242 6100 w | |
+10 R f | |
+( indicated by)2 518(also has relative addresses,)3 1075 2 3447 6100 t | |
+10 CW f | |
+(+)720 6220 w | |
+10 R f | |
+(or)805 6220 w | |
+10 CW f | |
+(-)913 6220 w | |
+10 R f | |
+( example,)1 388(. For)1 214 2 973 6220 t | |
+9 CW f | |
+($-3)1008 6390 w | |
+10 R f | |
+(is the third line before the end of the file and)10 1780 1 720 6570 t | |
+9 CW f | |
+(.+1)1008 6740 w | |
+10 R f | |
+( no address appears to the left of the)8 1457( If)1 118(is the line after dot… | |
+10 CW f | |
+(+)3104 6920 w | |
+10 R f | |
+(or)3191 6920 w | |
+10 CW f | |
+(-)3301 6920 w | |
+10 R f | |
+(, dot is assumed; if nothing appears to the)8 1679 1 3361 6920 t | |
+(right,)720 7040 w | |
+10 CW f | |
+(1)959 7040 w | |
+10 R f | |
+( Therefore,)1 467(is assumed.)1 461 2 1044 7040 t | |
+10 CW f | |
+(.+1)1997 7040 w | |
+10 R f | |
+(may be abbreviated to just a plus sign.)7 1532 1 2202 7040 t | |
+(The)970 7196 w | |
+10 CW f | |
+(+)1156 7196 w | |
+10 R f | |
+(operator acts relative to the end of its first argument, while the)11 2556 1 … | |
+10 CW f | |
+(-)3834 7196 w | |
+10 R f | |
+(operator acts relative to the)4 1114 1 3926 7196 t | |
+(beginning. Thus)1 679 1 720 7316 t | |
+10 CW f | |
+(.+1)1428 7316 w | |
+10 R f | |
+( first line after dot,)4 758(addresses the)1 533 2 1637 7316 t | |
+10 CW f | |
+(.-)2956 7316 w | |
+10 R f | |
+(addresses the first line before dot, and)6 1534 1 3104 7316 t | |
+10 CW f | |
+(+-)4666 7316 w | |
+10 R f | |
+(refers)4814 7316 w | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 4 4 | |
+%%Page: 5 5 | |
+/saveobj save def | |
+mark | |
+5 pagesetup | |
+10 R f | |
+(- 5 -)2 166 1 2797 480 t | |
+(Table I.)1 310 1 2393 900 t | |
+10 CW f | |
+(Sam)2728 900 w | |
+10 R f | |
+(commands)2933 900 w | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 R f | |
+(Text commands)1 641 1 1077 1136 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 CW f | |
+(a/)1077 1372 w | |
+10 I f | |
+(text)1197 1372 w | |
+10 CW f | |
+(/)1341 1372 w | |
+10 R f | |
+(Append text after dot)3 851 1 2160 1372 t | |
+10 CW f | |
+(c/)1077 1492 w | |
+10 I f | |
+(text)1197 1492 w | |
+10 CW f | |
+(/)1341 1492 w | |
+10 R f | |
+(Change text in dot)3 736 1 2160 1492 t | |
+10 CW f | |
+(i/)1077 1612 w | |
+10 I f | |
+(text)1197 1612 w | |
+10 CW f | |
+(/)1341 1612 w | |
+10 R f | |
+(Insert text before dot)3 834 1 2160 1612 t | |
+10 CW f | |
+(d)1077 1732 w | |
+10 R f | |
+(Delete text in dot)3 691 1 2160 1732 t | |
+10 CW f | |
+(s/)1077 1852 w | |
+10 I f | |
+(regexp)1197 1852 w | |
+10 CW f | |
+(/)1468 1852 w | |
+10 I f | |
+(text)1528 1852 w | |
+10 CW f | |
+(/)1672 1852 w | |
+10 R f | |
+(Substitute text for match of regular expression in dot)8 2109 1 2160 1852 t | |
+10 CW f | |
+(m)1077 1972 w | |
+10 I f | |
+(address)1197 1972 w | |
+10 R f | |
+(Move text in dot after address)5 1195 1 2160 1972 t | |
+10 CW f | |
+(t)1077 2092 w | |
+10 I f | |
+(address)1197 2092 w | |
+10 R f | |
+(Copy text in dot after address)5 1179 1 2160 2092 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 R f | |
+(Display commands)1 769 1 1077 2328 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 CW f | |
+(p)1077 2540 w | |
+10 R f | |
+(Print contents of dot)3 814 1 2160 2540 t | |
+10 CW f | |
+(=)1077 2660 w | |
+10 R f | |
+(Print value \(line numbers and character numbers\) of dot)8 2234 1 2160 2660 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 R f | |
+(File commands)1 614 1 1077 2896 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 CW f | |
+(b)1077 3108 w | |
+10 I f | |
+(file-list)1197 3108 w | |
+10 R f | |
+(Set current file to first file in list that)8 1466 1 2160 3108 t | |
+10 CW f | |
+(sam)3651 3108 w | |
+10 R f | |
+(has in menu)2 483 1 3856 3108 t | |
+10 CW f | |
+(B)1077 3228 w | |
+10 I f | |
+(file-list)1197 3228 w | |
+10 R f | |
+(Same as)1 330 1 2160 3228 t | |
+10 CW f | |
+(b)2515 3228 w | |
+10 R f | |
+(, but load new files)4 763 1 2575 3228 t | |
+10 CW f | |
+(n)1077 3348 w | |
+10 R f | |
+(Print menu lines of all files)5 1086 1 2160 3348 t | |
+10 CW f | |
+(D)1077 3468 w | |
+10 I f | |
+(file-list)1197 3468 w | |
+10 R f | |
+(Delete named files from)3 967 1 2160 3468 t | |
+10 CW f | |
+(sam)3152 3468 w | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 R f | |
+(I/O commands)1 591 1 1077 3704 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 CW f | |
+(e)1077 3916 w | |
+10 I f | |
+(filename)1197 3916 w | |
+10 R f | |
+(Replace file with named disc file)5 1317 1 2160 3916 t | |
+10 CW f | |
+(r)1077 4036 w | |
+10 I f | |
+(filename)1197 4036 w | |
+10 R f | |
+(Replace dot by contents of named disc file)7 1700 1 2160 4036 t | |
+10 CW f | |
+(w)1077 4156 w | |
+10 I f | |
+(filename)1197 4156 w | |
+10 R f | |
+(Write file to named disc file)5 1123 1 2160 4156 t | |
+10 CW f | |
+(f)1077 4276 w | |
+10 I f | |
+(filename)1197 4276 w | |
+10 R f | |
+(Set file name and print new menu line)7 1523 1 2160 4276 t | |
+10 CW f | |
+(<)1077 4396 w | |
+10 I f | |
+(Unix-command)1197 4396 w | |
+10 R f | |
+(Replace dot by standard output of command)6 1770 1 2160 4396 t | |
+10 CW f | |
+(>)1077 4516 w | |
+10 I f | |
+(Unix-command)1197 4516 w | |
+10 R f | |
+(Send dot to standard input of command)6 1577 1 2160 4516 t | |
+10 CW f | |
+(|)1077 4636 w | |
+10 I f | |
+(Unix-command)1197 4636 w | |
+10 R f | |
+(Replace dot by result of command applied to dot)8 1948 1 2160 4636 t | |
+10 CW f | |
+(!)1077 4756 w | |
+10 I f | |
+(Unix-command)1197 4756 w | |
+10 R f | |
+(Run the command)2 733 1 2160 4756 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 R f | |
+(Loops and conditionals)2 933 1 1077 4992 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 CW f | |
+(x/)1077 5204 w | |
+10 I f | |
+(regexp)1197 5204 w | |
+10 CW f | |
+(/)1468 5204 w | |
+10 I f | |
+(command)1588 5204 w | |
+10 R f | |
+(For each match of regexp, set dot and run command)9 2079 1 2160 5204 t | |
+10 CW f | |
+(y/)1077 5324 w | |
+10 I f | |
+(regexp)1197 5324 w | |
+10 CW f | |
+(/)1468 5324 w | |
+10 I f | |
+(command)1588 5324 w | |
+10 R f | |
+(Between adjacent matches of regexp, set dot and run command)9 2522 1 2160 532… | |
+10 CW f | |
+(X/)1077 5444 w | |
+10 I f | |
+(regexp)1197 5444 w | |
+10 CW f | |
+(/)1468 5444 w | |
+10 I f | |
+(command)1588 5444 w | |
+10 R f | |
+(Run command in each file whose menu line matches regexp)9 2404 1 2160 5444 t | |
+10 CW f | |
+(Y/)1077 5564 w | |
+10 I f | |
+(regexp)1197 5564 w | |
+10 CW f | |
+(/)1468 5564 w | |
+10 I f | |
+(command)1588 5564 w | |
+10 R f | |
+(Run command in each file whose menu line does not match)10 2386 1 2160 5564 t | |
+10 CW f | |
+(g/)1077 5684 w | |
+10 I f | |
+(regexp)1197 5684 w | |
+10 CW f | |
+(/)1468 5684 w | |
+10 I f | |
+(command)1588 5684 w | |
+10 R f | |
+(If dot contains a match of regexp, run command)8 1921 1 2160 5684 t | |
+10 CW f | |
+(v/)1077 5804 w | |
+10 I f | |
+(regexp)1197 5804 w | |
+10 CW f | |
+(/)1468 5804 w | |
+10 I f | |
+(command)1588 5804 w | |
+10 R f | |
+(If dot does not contain a match of regexp, run command)10 2243 1 2160 5804 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 R f | |
+(Miscellany)1077 6040 w | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+10 CW f | |
+(k)1077 6252 w | |
+10 R f | |
+(Set address mark to value of dot)6 1287 1 2160 6252 t | |
+10 CW f | |
+(q)1077 6372 w | |
+10 R f | |
+(Quit)2160 6372 w | |
+10 CW f | |
+(u)1077 6492 w | |
+10 I f | |
+(n)1197 6492 w | |
+10 R f | |
+(Undo last)1 386 1 2160 6492 t | |
+10 I f | |
+(n)2571 6492 w | |
+10 R f | |
+(\(default 1\) changes)2 764 1 2646 6492 t | |
+10 CW f | |
+({ })1 180 1 1077 6612 t | |
+10 R f | |
+(Braces group commands)2 987 1 2160 6612 t | |
+10 S f | |
+(_ ________________________________________________________________________)1 … | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 5 5 | |
+%%Page: 6 6 | |
+/saveobj save def | |
+mark | |
+6 pagesetup | |
+10 R f | |
+(- 6 -)2 166 1 2797 480 t | |
+( multiple lines, and)3 788( may span)2 417( \(Dot)1 239(to the line containin… | |
+10 CW f | |
+(+)3687 840 w | |
+10 R f | |
+(selects the line after the end of)6 1261 1 3779 840 t | |
+(dot, then)1 350 1 720 960 t | |
+10 CW f | |
+(-)1095 960 w | |
+10 R f | |
+(backs up one line.\))3 754 1 1180 960 t | |
+( addresses the text matched by the expression.)7 1855(The final type of addre… | |
+(The expression is enclosed in slashes, as in)7 1720 1 720 1236 t | |
+9 CW f | |
+(/)1008 1406 w | |
+9 I f | |
+(expression)1062 1406 w | |
+9 CW f | |
+(/)1447 1406 w | |
+10 R f | |
+( the same as those in the Unix program)8 1647(The expressions are)2 812 2 720… | |
+10 CW f | |
+(egrep)3215 1586 w | |
+10 R f | |
+(,)3515 1586 w | |
+6 R f | |
+(6,7)3540 1536 w | |
+10 R f | |
+(and include closures, alternations,)3 1389 1 3651 1586 t | |
+( find the)2 335( They)1 256(and so on.)2 410 3 720 1706 t | |
+10 I f | |
+(leftmost longest)1 632 1 1747 1706 t | |
+10 R f | |
+( match after the)3 623(string that matches the expression, that is, the first… | |
+( the search is started, and if more than one match begins at the same spot, t… | |
+( assume familiarity with the syntax for regular expressions in Unix programs.… | |
+6 R f | |
+(9)4201 1896 w | |
+10 R f | |
+(\) For example,)2 585 1 4231 1946 t | |
+9 CW f | |
+(/x/)1008 2116 w | |
+10 R f | |
+(matches the next)2 671 1 720 2296 t | |
+10 CW f | |
+(x)1416 2296 w | |
+10 R f | |
+(character in the file,)3 797 1 1501 2296 t | |
+9 CW f | |
+(/xx*/)1008 2466 w | |
+10 R f | |
+(matches the next run of one or more)7 1444 1 720 2646 t | |
+10 CW f | |
+(x)2189 2646 w | |
+10 R f | |
+('s, and)1 266 1 2249 2646 t | |
+9 CW f | |
+(/x|Peter/)1008 2816 w | |
+10 R f | |
+(matches the next)2 677 1 720 2996 t | |
+10 CW f | |
+(x)1425 2996 w | |
+10 R f | |
+(or)1513 2996 w | |
+10 CW f | |
+(Peter)1624 2996 w | |
+10 R f | |
+( character' operator, a)3 885( compatibility with other Unix programs, the `a… | |
+(period, does not match a newline, so)6 1459 1 720 3116 t | |
+9 CW f | |
+(/.*/)1008 3286 w | |
+10 R f | |
+( from dot to the end of the line, but excludes the newline and so will not ma… | |
+(line boundary.)1 577 1 720 3586 t | |
+( is forwards by default, so)5 1222( direction)1 416( The)1 241(Regular expres… | |
+10 CW f | |
+(/Peter/)720 3862 w | |
+10 R f | |
+(is really an abbreviation for)4 1103 1 1165 3862 t | |
+10 CW f | |
+(+/Peter/)2293 3862 w | |
+10 R f | |
+( search can be reversed with a minus sign, so)9 1796(. The)1 230 2 2773 3862 t | |
+9 CW f | |
+(-/Peter/)1008 4032 w | |
+10 R f | |
+(finds the first)2 595 1 720 4212 t | |
+10 CW f | |
+(Peter)1371 4212 w | |
+10 R f | |
+( with other address forms, so)5 1314( expressions may be used)4 1139( Regular… | |
+10 CW f | |
+(0+/Peter/)720 4332 w | |
+10 R f | |
+(finds the first)2 539 1 1288 4332 t | |
+10 CW f | |
+(Peter)1855 4332 w | |
+10 R f | |
+(in the file and)3 561 1 2183 4332 t | |
+10 CW f | |
+($-/Peter/)2772 4332 w | |
+10 R f | |
+( II summarizes)2 599( Table)1 280(finds the last.)2 542 3 3340 4332 t | |
+10 CW f | |
+(sam)4788 4332 w | |
+10 R f | |
+('s)4968 4332 w | |
+(addresses.)720 4452 w | |
+( who use Unix text editors such as)7 1389(The language discussed so far will … | |
+10 CW f | |
+(ed)4809 4608 w | |
+10 R f | |
+(or)4957 4608 w | |
+10 CW f | |
+(vi)720 4728 w | |
+10 R f | |
+(.)840 4728 w | |
+6 R f | |
+(9)865 4678 w | |
+10 R f | |
+( operations these commands allow, with the exception of regular expres-)10 28… | |
+( Indeed,)1 351( a mouse-based interface.)3 1028(sions and line numbers, are c… | |
+10 CW f | |
+(sam)4788 4848 w | |
+10 R f | |
+('s)4968 4848 w | |
+( For)1 194( usually made.)2 590(mouse language \(discussed at length below\) … | |
+(large or repetitive changes, however, a textual language outperforms a manual… | |
+(Imagine that, instead of deleting just one occurrence of the string)10 2708 1… | |
+10 CW f | |
+(Peter)3714 5244 w | |
+10 R f | |
+( wanted to eliminate)3 849(, we)1 177 2 4014 5244 t | |
+(every)720 5364 w | |
+10 CW f | |
+(Peter)970 5364 w | |
+10 R f | |
+( some text.)2 442( needed is an iterator that runs a command for each occurre… | |
+10 CW f | |
+(Sam)4788 5364 w | |
+10 R f | |
+('s)4968 5364 w | |
+(iterator is called)2 643 1 720 5484 t | |
+10 CW f | |
+(x)1388 5484 w | |
+10 R f | |
+(, for extract:)2 490 1 1448 5484 t | |
+9 CW f | |
+(x/)1008 5654 w | |
+9 I f | |
+(expression)1116 5654 w | |
+9 CW f | |
+(/)1501 5654 w | |
+9 I f | |
+(command)1609 5654 w | |
+10 R f | |
+( text matched)2 554(finds all matches in dot of the specified expression, and… | |
+( to delete all the)4 638( So)1 156(and runs the command.)3 932 3 720 5954 t | |
+10 CW f | |
+(Peters:)2471 5954 w | |
+9 CW f | |
+(0,$ x/Peter/ d)2 756 1 1008 6124 t | |
+10 R f | |
+( are to improve readability;)4 1163(\(Blanks in these examples)3 1100 2 720 6… | |
+10 CW f | |
+(sam)3027 6304 w | |
+10 R f | |
+( This)1 247(neither requires nor interprets them.\))4 1542 2 3251 6304 t | |
+(searches the entire file \()4 964 1 720 6424 t | |
+10 CW f | |
+(0,$)1684 6424 w | |
+10 R f | |
+( of the string)3 514(\) for occurrences)2 680 2 1864 6424 t | |
+10 CW f | |
+(Peter)3085 6424 w | |
+10 R f | |
+(, and runs the)3 544 1 3385 6424 t | |
+10 CW f | |
+(d)3956 6424 w | |
+10 R f | |
+(command with dot set to)4 997 1 4043 6424 t | |
+( contrast, the comparable)3 1003( \(By)1 200(each such occurrence.)2 876 3 72… | |
+10 CW f | |
+(ed)2824 6544 w | |
+10 R f | |
+(command would delete all)3 1057 1 2969 6544 t | |
+10 I f | |
+(lines)4051 6544 w | |
+10 R f | |
+(containing)4265 6544 w | |
+10 CW f | |
+(Peter)4712 6544 w | |
+10 R f | |
+(;)5012 6544 w | |
+10 CW f | |
+(sam)720 6664 w | |
+10 R f | |
+(deletes only the)2 653 1 938 6664 t | |
+10 CW f | |
+(Peters)1629 6664 w | |
+10 R f | |
+( address)1 337(.\) The)1 276 2 1989 6664 t | |
+10 CW f | |
+(0,$)2640 6664 w | |
+10 R f | |
+( be abbreviated to just a)5 1011(is commonly used, and may)4 1171 2 2858 6664… | |
+( another example,)2 712(comma. As)1 480 2 720 6784 t | |
+9 CW f | |
+(, x/Peter/ p)2 648 1 1008 6954 t | |
+10 R f | |
+(prints a list of)3 556 1 720 7134 t | |
+10 CW f | |
+(Peters,)1303 7134 w | |
+10 R f | |
+(one for each appearance in the file, with no intervening text \(not even newl… | |
+(separate the instances\).)2 922 1 720 7254 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 6 6 | |
+%%Page: 7 7 | |
+/saveobj save def | |
+mark | |
+7 pagesetup | |
+10 R f | |
+(- 7 -)2 166 1 2797 480 t | |
+(Table II.)1 343 1 2402 900 t | |
+10 CW f | |
+(Sam)2770 900 w | |
+10 R f | |
+(addresses)2975 900 w | |
+10 S f | |
+(_ _________________________________________________________________)1 3264 1 … | |
+10 R f | |
+(Simple addresses)1 691 1 1248 1136 t | |
+10 S f | |
+(_ _________________________________________________________________)1 3264 1 … | |
+10 CW f | |
+(#)1248 1348 w | |
+10 I f | |
+(n)1308 1348 w | |
+10 R f | |
+(The empty string after character)4 1279 1 2250 1348 t | |
+10 I f | |
+(n)3554 1348 w | |
+(n)1248 1468 w | |
+10 R f | |
+(Line)2250 1468 w | |
+10 I f | |
+(n)2458 1468 w | |
+10 R f | |
+(.)2508 1468 w | |
+10 CW f | |
+(/)1248 1588 w | |
+10 I f | |
+(regexp)1308 1588 w | |
+10 CW f | |
+(/)1579 1588 w | |
+10 R f | |
+(The first following match of the regular expression)7 2038 1 2250 1588 t | |
+10 CW f | |
+(-/)1248 1708 w | |
+10 I f | |
+(regexp)1368 1708 w | |
+10 CW f | |
+(/)1639 1708 w | |
+10 R f | |
+(The first previous match of the regular expression)7 1993 1 2250 1708 t | |
+10 CW f | |
+($)1248 1828 w | |
+10 R f | |
+(The null string at the end of the file)8 1415 1 2250 1828 t | |
+10 CW f | |
+(.)1248 1948 w | |
+10 R f | |
+(Dot)2250 1948 w | |
+10 CW f | |
+(')1248 2068 w | |
+10 R f | |
+(The address mark, set by)4 995 1 2250 2068 t | |
+10 CW f | |
+(k)3270 2068 w | |
+10 R f | |
+(command)3355 2068 w | |
+10 CW f | |
+(")1248 2188 w | |
+10 I f | |
+(regexp)1308 2188 w | |
+10 CW f | |
+(")1579 2188 w | |
+10 R f | |
+(Dot in the file whose menu line matches regexp)8 1908 1 2250 2188 t | |
+10 S f | |
+(_ _________________________________________________________________)1 3264 1 … | |
+10 R f | |
+(Compound addresses)1 852 1 1248 2424 t | |
+10 S f | |
+(_ _________________________________________________________________)1 3264 1 … | |
+10 I f | |
+(a1)1248 2636 w | |
+10 CW f | |
+(+)1348 2636 w | |
+10 I f | |
+(a2)1408 2636 w | |
+10 R f | |
+(The address)1 479 1 2250 2636 t | |
+10 I f | |
+(a2)2754 2636 w | |
+10 R f | |
+(evaluated starting at right of)4 1126 1 2879 2636 t | |
+10 I f | |
+(a1)4030 2636 w | |
+(a1)1248 2756 w | |
+10 CW f | |
+(-)1348 2756 w | |
+10 I f | |
+(a2 a2)1 942 1 1408 2756 t | |
+10 R f | |
+(evaluated in the reverse direction starting at left of)8 2012 1 2375 2756 t | |
+10 I f | |
+(a1)4412 2756 w | |
+(a1)1248 2876 w | |
+10 CW f | |
+(,)1348 2876 w | |
+10 I f | |
+(a2)1408 2876 w | |
+10 R f | |
+(From the left of)3 630 1 2250 2876 t | |
+10 I f | |
+(a1)2905 2876 w | |
+10 R f | |
+(to the right of)3 547 1 3030 2876 t | |
+10 I f | |
+(a2)3602 2876 w | |
+10 R f | |
+(\(default)3727 2876 w | |
+10 CW f | |
+(0,$)4062 2876 w | |
+10 R f | |
+(\))4242 2876 w | |
+10 I f | |
+(a1)1248 2996 w | |
+10 CW f | |
+(;)1348 2996 w | |
+10 I f | |
+(a2)1408 2996 w | |
+10 R f | |
+(Like)2250 2996 w | |
+10 CW f | |
+(,)2458 2996 w | |
+10 R f | |
+(but sets dot after evaluating)4 1104 1 2543 2996 t | |
+10 I f | |
+(a1)3672 2996 w | |
+10 S f | |
+(_ _________________________________________________________________)1 3264 1 … | |
+10 R f | |
+(The operators)1 569 1 1440 3232 t | |
+10 CW f | |
+(+)2052 3232 w | |
+10 R f | |
+(and)2155 3232 w | |
+10 CW f | |
+(-)2342 3232 w | |
+10 R f | |
+(are high precedence, while)3 1122 1 2445 3232 t | |
+10 CW f | |
+(,)3610 3232 w | |
+10 R f | |
+(and)3713 3232 w | |
+10 CW f | |
+(;)3901 3232 w | |
+10 R f | |
+(are low)1 315 1 4005 3232 t | |
+( both)1 208(precedence. In)1 610 2 1440 3352 t | |
+10 CW f | |
+(+)2288 3352 w | |
+10 R f | |
+(and)2378 3352 w | |
+10 CW f | |
+(-)2552 3352 w | |
+10 R f | |
+(forms,)2642 3352 w | |
+10 I f | |
+(a2)2930 3352 w | |
+10 R f | |
+(defaults to 1 and)3 678 1 3060 3352 t | |
+10 I f | |
+(a1)3768 3352 w | |
+10 R f | |
+(defaults to)1 423 1 3897 3352 t | |
+( both)1 203(dot. If)1 269 2 1440 3472 t | |
+10 I f | |
+(a1)1937 3472 w | |
+10 R f | |
+(and)2062 3472 w | |
+10 I f | |
+(a2)2231 3472 w | |
+10 R f | |
+(are present,)1 459 1 2356 3472 t | |
+10 CW f | |
+(+)2840 3472 w | |
+10 R f | |
+(may be elided.)2 585 1 2925 3472 t | |
+10 S f | |
+(_ _________________________________________________________________)1 3264 1 … | |
+10 R f | |
+(Of course, the text extracted by)5 1267 1 970 3852 t | |
+10 CW f | |
+(x)2265 3852 w | |
+10 R f | |
+(may be selected by a regular expression, which complicates decid-)9 2687 1 23… | |
+( is resolved by generating the matches)6 1597( This)1 240( matches is chosen … | |
+( starting)1 338(starting from the beginning of dot using the leftmost-longest… | |
+( adja-)1 228( expressions may also match null strings, but a null match)10 23… | |
+( example,)1 388( For)1 189(cent to a non-null match is never selected; at lea… | |
+9 CW f | |
+(, c/AAA/)1 432 1 1008 4502 t | |
+(x/B*/ c/-/)1 540 1 1008 4612 t | |
+(, p)1 162 1 1008 4722 t | |
+10 R f | |
+(produces as output)2 749 1 720 4902 t | |
+9 CW f | |
+(-A-A-A-)1008 5072 w | |
+10 R f | |
+(because the pattern)2 764 1 720 5252 t | |
+10 CW f | |
+(B*)1509 5252 w | |
+10 R f | |
+(matches the null strings separating the)5 1529 1 1654 5252 t | |
+10 CW f | |
+(A)3208 5252 w | |
+10 R f | |
+('s.)3268 5252 w | |
+(The)970 5408 w | |
+10 CW f | |
+(x)1150 5408 w | |
+10 R f | |
+(command has a complement,)3 1165 1 1235 5408 t | |
+10 CW f | |
+(y)2425 5408 w | |
+10 R f | |
+( syntax, that executes the command with dot set to)9 2024(, with similar)2 53… | |
+(the text)1 297 1 720 5528 t | |
+10 I f | |
+(between)1042 5528 w | |
+10 R f | |
+( example,)1 388( For)1 189(the matches of the expression.)4 1206 3 1394 5528 t | |
+9 CW f | |
+(, c/AAA/)1 432 1 1008 5698 t | |
+(y/A/ c/-/)1 486 1 1008 5808 t | |
+(, p)1 162 1 1008 5918 t | |
+10 R f | |
+(produces the same result as the example above.)7 1890 1 720 6098 t | |
+(The)970 6254 w | |
+10 CW f | |
+(x)1158 6254 w | |
+10 R f | |
+(and)1251 6254 w | |
+10 CW f | |
+(y)1428 6254 w | |
+10 R f | |
+(commands are looping constructs, and)4 1566 1 1521 6254 t | |
+10 CW f | |
+(sam)3120 6254 w | |
+10 R f | |
+(has a pair of conditional commands to go)7 1707 1 3333 6254 t | |
+( have similar syntax:)3 830( They)1 255(with them.)1 428 3 720 6374 t | |
+9 CW f | |
+(g/)1008 6544 w | |
+9 I f | |
+(expression)1116 6544 w | |
+9 CW f | |
+(/)1501 6544 w | |
+9 I f | |
+(command)1609 6544 w | |
+10 R f | |
+( is different from)3 688( This)1 231(\(guard\) runs the command exactly once … | |
+10 CW f | |
+(x)4955 6724 w | |
+10 R f | |
+(,)5015 6724 w | |
+(which runs the command for)4 1148 1 720 6844 t | |
+10 I f | |
+(each)1893 6844 w | |
+10 R f | |
+(match:)2106 6844 w | |
+10 CW f | |
+(x)2403 6844 w | |
+10 R f | |
+(loops;)2488 6844 w | |
+10 CW f | |
+(g)2758 6844 w | |
+10 R f | |
+( Thus,)1 275(merely tests, without changing the value of dot.)7 1901 2 2843 6… | |
+9 CW f | |
+(, x/Peter/ d)2 648 1 1008 7014 t | |
+10 R f | |
+(deletes all occurrences of)3 1010 1 720 7194 t | |
+10 CW f | |
+(Peter)1755 7194 w | |
+10 R f | |
+(, but)1 178 1 2055 7194 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 7 7 | |
+%%Page: 8 8 | |
+/saveobj save def | |
+mark | |
+8 pagesetup | |
+10 R f | |
+(- 8 -)2 166 1 2797 480 t | |
+9 CW f | |
+(, g/Peter/ d)2 648 1 1008 830 t | |
+10 R f | |
+( string\) if)2 384(deletes the whole file \(reduces it to a null)8 1687 2 720… | |
+10 CW f | |
+(Peter)2822 1010 w | |
+10 R f | |
+( complemen-)1 530( The)1 211(occurs anywhere in the text.)4 1146 3 3153 1010 t | |
+(tary conditional is)2 722 1 720 1130 t | |
+10 CW f | |
+(v)1467 1130 w | |
+10 R f | |
+(, which runs the command if there is)7 1459 1 1527 1130 t | |
+10 I f | |
+(no)3011 1130 w | |
+10 R f | |
+(match of the expression.)3 976 1 3136 1130 t | |
+( For)1 190(These control-structure-like commands may be composed to construct… | |
+(example, to print those lines of text that contain the string)10 2307 1 720 1… | |
+10 CW f | |
+(Peter)3052 1406 w | |
+10 R f | |
+(:)3352 1406 w | |
+9 CW f | |
+(, x/.*\\n/ g/Peter/ p)3 1080 1 1008 1576 t | |
+10 R f | |
+(The)720 1756 w | |
+10 CW f | |
+(x)908 1756 w | |
+10 R f | |
+( file into lines, the)4 761(breaks the)1 415 2 1001 1756 t | |
+10 CW f | |
+(g)2211 1756 w | |
+10 R f | |
+(selects those lines containing)3 1190 1 2305 1756 t | |
+10 CW f | |
+(Peter)3529 1756 w | |
+10 R f | |
+(, and the)2 359 1 3829 1756 t | |
+10 CW f | |
+(p)4222 1756 w | |
+10 R f | |
+( This)1 237(prints them.)1 487 2 4316 1756 t | |
+(command gives an address for the)5 1416 1 720 1876 t | |
+10 CW f | |
+(x)2172 1876 w | |
+10 R f | |
+(command \(the whole file\), but because)5 1607 1 2268 1876 t | |
+10 CW f | |
+(g)3911 1876 w | |
+10 R f | |
+(does not have an explicit)4 1033 1 4007 1876 t | |
+( the value of dot produced by the)7 1359(address, it applies to)3 831 2 720 1… | |
+10 CW f | |
+(x)2941 1996 w | |
+10 R f | |
+( commands in)2 573( All)1 184(command, that is, to each line.)5 1251 3 3032 1… | |
+10 CW f | |
+(sam)720 2116 w | |
+10 R f | |
+(except for the command to write a file to disc use dot for the default addres… | |
+(Composition may be continued indefinitely.)4 1764 1 970 2272 t | |
+9 CW f | |
+(, x/.*\\n/ g/Peter/ v/SaltPeter/ p)4 1782 1 1008 2442 t | |
+10 R f | |
+(prints those lines containing)3 1125 1 720 2622 t | |
+10 CW f | |
+(Peter)1870 2622 w | |
+10 R f | |
+(but)2195 2622 w | |
+10 I f | |
+(not)2348 2622 w | |
+10 R f | |
+(those containing)1 658 1 2501 2622 t | |
+10 CW f | |
+(SaltPeter)3184 2622 w | |
+10 R f | |
+(.)3724 2622 w | |
+10 B f | |
+(Structural Regular Expressions)2 1350 1 720 2862 t | |
+10 R f | |
+( non-interactive ones such as)4 1177(Unlike other Unix text editors, includin… | |
+10 CW f | |
+(sed)3732 3018 w | |
+10 R f | |
+(and)3943 3018 w | |
+10 CW f | |
+(awk)4118 3018 w | |
+10 R f | |
+(,)4298 3018 w | |
+6 R f | |
+(7)4323 2968 w | |
+10 CW f | |
+(sam)4384 3018 w | |
+10 R f | |
+(is good for)2 445 1 4595 3018 t | |
+( on-line phone book composed of records,)6 1737( example is an)3 604( An)1 18… | |
+(separated by blank lines, of the form)6 1461 1 720 3258 t | |
+9 CW f | |
+(Herbert Tic)1 594 1 1008 3428 t | |
+(44 Turnip Ave., Endive, NJ)4 1404 1 1008 3538 t | |
+(201-5555642)1008 3648 w | |
+(Norbert Twinge)1 756 1 1008 3868 t | |
+(16 Potato St., Cabbagetown, NJ)4 1620 1 1008 3978 t | |
+(201-5553145)1008 4088 w | |
+(...)1008 4308 w | |
+10 R f | |
+(The format may be encoded as a regular expression:)8 2083 1 720 4488 t | |
+9 CW f | |
+(\(.+\\n\)+)1008 4658 w | |
+10 R f | |
+( command to print Mr. Tic's entire record is then)9 1958( The)1 205(that is, … | |
+9 CW f | |
+(, x/\(.+\\n\)+/ g/\303Herbert Tic$/ p)4 1674 1 1008 5008 t | |
+10 R f | |
+(and that to extract just the phone number is)8 1726 1 720 5188 t | |
+9 CW f | |
+(, x/\(.+\\n\)+/ g/\303Herbert Tic$/ x/\303[0-9]*-[0-9]*\\n/ p)5 2754 1 1008 5… | |
+10 R f | |
+( Tic's record, extracts the phone number from)7 1862(The latter command break… | |
+(the record, and finally prints the number.)6 1636 1 720 5658 t | |
+(A more involved problem is that of renaming a particular variable, say)11 292… | |
+10 CW f | |
+(n)3932 5814 w | |
+10 R f | |
+(, to)1 138 1 3992 5814 t | |
+10 CW f | |
+(num)4165 5814 w | |
+10 R f | |
+(in a C program.)3 660 1 4380 5814 t | |
+(The obvious first attempt,)3 1033 1 720 5934 t | |
+9 CW f | |
+(, x/n/ c/num/)2 702 1 1008 6104 t | |
+10 R f | |
+( flawed: it changes not only the variable)7 1628(is badly)1 317 2 720 6284 t | |
+10 CW f | |
+(n)2694 6284 w | |
+10 R f | |
+(but any letter)2 535 1 2783 6284 t | |
+10 CW f | |
+(n)3347 6284 w | |
+10 R f | |
+( need to extract all the)5 904( We)1 192(that appears.)1 508 3 3436 6284 t | |
+(variables, and select those that match)5 1486 1 720 6404 t | |
+10 CW f | |
+(n)2231 6404 w | |
+10 R f | |
+(and only)1 347 1 2316 6404 t | |
+10 CW f | |
+(n)2688 6404 w | |
+10 R f | |
+(:)2748 6404 w | |
+9 CW f | |
+(, x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/)4 2430 1 1008 6574 t | |
+10 R f | |
+(The pattern)1 458 1 720 6754 t | |
+10 CW f | |
+([A-Za-z_][A-Za-z_0-9]*)1204 6754 w | |
+10 R f | |
+( Next)1 246(matches C identifiers.)2 876 2 2550 6754 t | |
+10 CW f | |
+(g/n/)3699 6754 w | |
+10 R f | |
+(selects those containing an)3 1074 1 3966 6754 t | |
+10 CW f | |
+(n)720 6874 w | |
+10 R f | |
+(. Then)1 303 1 780 6874 t | |
+10 CW f | |
+(v/../)1131 6874 w | |
+10 R f | |
+(rejects those containing two \(or more\) characters, and finally)8 2614 1 147… | |
+10 CW f | |
+(c/num/)4141 6874 w | |
+10 R f | |
+(changes the)1 491 1 4549 6874 t | |
+(remainder \(identifiers)1 871 1 720 6994 t | |
+10 CW f | |
+(n)1620 6994 w | |
+10 R f | |
+(\) to)1 140 1 1680 6994 t | |
+10 CW f | |
+(num)1849 6994 w | |
+10 R f | |
+( version clearly works much better, but there may still be problems.)11 2754(… | |
+(For example, in C character and string constants, the sequence)9 2510 1 720 7… | |
+10 CW f | |
+(\\n)3257 7114 w | |
+10 R f | |
+( and)1 170(is interpreted as a newline character,)5 1466 2 3404 7114 t | |
+(we don't want to change it to)6 1165 1 720 7234 t | |
+10 CW f | |
+(\\num.)1910 7234 w | |
+10 R f | |
+(This problem can be forestalled with a)6 1536 1 2235 7234 t | |
+10 CW f | |
+(y)3796 7234 w | |
+10 R f | |
+(command:)3881 7234 w | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 8 8 | |
+%%Page: 9 9 | |
+/saveobj save def | |
+mark | |
+9 pagesetup | |
+10 R f | |
+(- 9 -)2 166 1 2797 480 t | |
+9 CW f | |
+(, y/\\\\n/ x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/)5 2808 1 1008 830 t | |
+10 R f | |
+(\(the second)1 464 1 720 1010 t | |
+10 CW f | |
+(\\)1216 1010 w | |
+10 R f | |
+( reject)1 254(is necessary because of lexical conventions in regular expressi… | |
+(character constants and strings outright:)4 1592 1 720 1130 t | |
+9 CW f | |
+(, y/'[\303']*'/ y/"[\303"]*"/ x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/)6 3… | |
+10 R f | |
+(The)720 1480 w | |
+10 CW f | |
+(y)907 1480 w | |
+10 R f | |
+( only)1 211( The)1 213( strings.)1 325(commands in this version exclude from … | |
+(remaining problem is to deal with the possible occurrence of)9 2439 1 720 160… | |
+10 CW f | |
+(\\')3186 1600 w | |
+10 R f | |
+(or)3332 1600 w | |
+10 CW f | |
+(\\")3441 1600 w | |
+10 R f | |
+(within these sequences, but it's easy)5 1453 1 3587 1600 t | |
+(to see how to resolve this difficulty.)6 1435 1 720 1720 t | |
+( of the command)3 683( simple version)2 615( A)1 124(The point of these compo… | |
+( can be undone;)3 644( \(Mistakes)1 449( it can be honed by adding a clause o… | |
+( result-)1 283( The)1 208( the mouse language makes it unnecessary to retype … | |
+(ing chains of commands are somewhat reminiscent of shell pipelines.)9 2783 1 … | |
+6 R f | |
+(7)3503 2186 w | |
+10 R f | |
+(Unlike pipelines, though, which pass)4 1481 1 3559 2236 t | |
+(along modified)1 612 1 720 2356 t | |
+10 I f | |
+(data)1361 2356 w | |
+10 R f | |
+(,)1539 2356 w | |
+10 CW f | |
+(sam)1593 2356 w | |
+10 R f | |
+(commands pass a)2 707 1 1802 2356 t | |
+10 I f | |
+(view)2538 2356 w | |
+10 R f | |
+( text at each step of the command is the)9 1623( The)1 210(of the data.)2 456… | |
+( by step until the correct piece is available to the final)11 2237(same, but … | |
+(step of the command line, which ultimately makes the change.)9 2494 1 720 259… | |
+(In other Unix programs, regular expressions are used only for selection, as i… | |
+10 CW f | |
+(sam g)1 272 1 4317 2752 t | |
+10 R f | |
+(command,)4621 2752 w | |
+(never for extraction as in the)5 1159 1 720 2872 t | |
+10 CW f | |
+(x)1907 2872 w | |
+10 R f | |
+(or)1995 2872 w | |
+10 CW f | |
+(y)2106 2872 w | |
+10 R f | |
+( patterns in)2 448( example,)1 391(command. For)1 611 3 2194 2872 t | |
+10 CW f | |
+(awk)3671 2872 w | |
+6 R f | |
+(7)3851 2822 w | |
+10 R f | |
+(are used to select lines to be)6 1132 1 3908 2872 t | |
+( The)1 207( but cannot be used to describe the format of the input text, or t… | |
+( the structure of a piece of text rather than its contents, as in the)14 2671… | |
+10 CW f | |
+(x)4980 3112 w | |
+10 R f | |
+(command, has been given a name:)5 1455 1 720 3232 t | |
+10 I f | |
+(structural regular expressions.)2 1268 1 2216 3232 t | |
+10 R f | |
+(When they are composed, as in the)6 1490 1 3550 3232 t | |
+( use is discussed at greater length elsewhere.)7 1779( Their)1 266(above exam… | |
+6 R f | |
+(10)4635 3302 w | |
+10 B f | |
+(Multiple files)1 564 1 720 3628 t | |
+10 CW f | |
+(Sam)720 3784 w | |
+10 R f | |
+(has a few other commands, mostly relating to input and output.)10 2526 1 925 … | |
+9 CW f | |
+(e discfilename)1 756 1 1008 3954 t | |
+10 R f | |
+(replaces the contents and name of the current file with those of the named di… | |
+9 CW f | |
+(w discfilename)1 756 1 1008 4304 t | |
+10 R f | |
+(writes the contents to the named disc file; and)8 1831 1 720 4484 t | |
+9 CW f | |
+(r discfilename)1 756 1 1008 4654 t | |
+10 R f | |
+( file's name if)3 590( these commands use the current)5 1350( All)1 188(repla… | |
+( Finally,)1 359(none is specified.)2 696 2 720 4954 t | |
+9 CW f | |
+(f discfilename)1 756 1 1008 5124 t | |
+10 R f | |
+(changes the name associated with the file and displays the result:)10 2596 1 … | |
+9 CW f | |
+('-. discfilename)1 864 1 1008 5474 t | |
+10 R f | |
+(This output is called the file's)5 1226 1 720 5654 t | |
+10 I f | |
+(menu line,)1 423 1 1978 5654 t | |
+10 R f | |
+( contents of the file's line in the button 3 menu)10 1951(because it is the)3… | |
+( The)1 205( first three characters are a concise notation for the state of th… | |
+( sign indicates the number of windows open on the)9 2052( minus)1 271( The)1 … | |
+(file \(see the next section\):)4 1071 1 720 6014 t | |
+10 CW f | |
+(-)1826 6014 w | |
+10 R f | |
+(means none,)1 509 1 1921 6014 t | |
+10 CW f | |
+(+)2465 6014 w | |
+10 R f | |
+(means one, and)2 636 1 2560 6014 t | |
+10 CW f | |
+(*)3230 6014 w | |
+10 R f | |
+( the period)2 445( Finally,)1 368(means more than one.)3 903 3 3324 6014 t | |
+( are useful for controlling the)5 1192( characters)1 432( These)1 292(indicat… | |
+10 CW f | |
+(X)4119 6134 w | |
+10 R f | |
+(command, described)1 831 1 4209 6134 t | |
+(shortly.)720 6254 w | |
+10 CW f | |
+(Sam)970 6410 w | |
+10 R f | |
+( \(such as all the source for a program\) by invoking it with a)13 2384(may b… | |
+(list of file names as arguments, and more may be added or deleted on demand.)… | |
+9 CW f | |
+(B discfile1 discfile2 ...)3 1350 1 1008 6700 t | |
+10 R f | |
+(adds the named files to)4 921 1 720 6880 t | |
+10 CW f | |
+(sam)1666 6880 w | |
+10 R f | |
+('s list, and)2 414 1 1846 6880 t | |
+9 CW f | |
+(D discfile1 discfile2 ...)3 1350 1 1008 7050 t | |
+10 R f | |
+(removes them from)2 790 1 720 7230 t | |
+10 CW f | |
+(sam)1539 7230 w | |
+10 R f | |
+( these commands have a)4 990( Both)1 250('s memory \(without effect on associ… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 9 9 | |
+%%Page: 10 10 | |
+/saveobj save def | |
+mark | |
+10 pagesetup | |
+10 R f | |
+(- 10 -)2 216 1 2772 480 t | |
+(syntax for using the shell)4 1005 1 720 840 t | |
+6 R f | |
+(7)1725 790 w | |
+10 R f | |
+(\(the Unix command interpreter\) to generate the lists:)7 2099 1 1780 840 t | |
+9 CW f | |
+(B <echo *.c)2 594 1 1008 1010 t | |
+10 R f | |
+(will add all C source files, and)6 1218 1 720 1190 t | |
+9 CW f | |
+(B <grep -l variable *.c)4 1242 1 1008 1360 t | |
+10 R f | |
+( files referencing a particular variable \(the Unix command)8 2377(will add a… | |
+10 CW f | |
+(grep -l)1 420 1 3980 1540 t | |
+10 R f | |
+(lists all files in)3 608 1 4432 1540 t | |
+( Finally,)1 379( the specified regular expression\).)4 1429(its arguments tha… | |
+10 CW f | |
+(D)4168 1660 w | |
+10 R f | |
+(without arguments)1 767 1 4273 1660 t | |
+(deletes the current file.)3 914 1 720 1780 t | |
+(There are two ways to change which file is current:)9 2047 1 970 1936 t | |
+9 CW f | |
+(b filename)1 540 1 1008 2106 t | |
+10 R f | |
+( The)1 213(makes the named file current.)4 1215 2 720 2286 t | |
+10 CW f | |
+(B)2181 2286 w | |
+10 R f | |
+( but also adds any new files to)7 1270(command does the same,)3 1028 2 2274 2… | |
+10 CW f | |
+(sam)4606 2286 w | |
+10 R f | |
+('s list.)1 254 1 4786 2286 t | |
+( The)1 208( mouse actions, not by textual commands.\))6 1728(\(In practice, o… | |
+(other way is to use a form of address that refers to files:)12 2223 1 720 252… | |
+9 CW f | |
+(")1008 2696 w | |
+9 I f | |
+(expression)1062 2696 w | |
+9 CW f | |
+(")1447 2696 w | |
+9 I f | |
+(address)1555 2696 w | |
+10 R f | |
+( matches the expression \(there must be exactly)7 1923(refers to the address … | |
+( example,)1 388( For)1 189(one match\).)1 471 3 720 2996 t | |
+9 CW f | |
+("peter.c" 3)1 594 1 1008 3166 t | |
+10 R f | |
+( whose name matches)3 885(refers to the third line of the file)7 1299 2 720 3… | |
+10 CW f | |
+(peter.c)2933 3346 w | |
+10 R f | |
+( is most useful in the move \()7 1164(. This)1 257 2 3353 3346 t | |
+10 CW f | |
+(m)4774 3346 w | |
+10 R f | |
+(\) and)1 206 1 4834 3346 t | |
+(copy \()1 252 1 720 3466 t | |
+10 CW f | |
+(t)972 3466 w | |
+10 R f | |
+(\) commands:)1 519 1 1032 3466 t | |
+9 CW f | |
+(0,$ t "peter.c" 0)3 918 1 1008 3636 t | |
+10 R f | |
+(makes a copy of the current file at the beginning of)10 2040 1 720 3816 t | |
+10 CW f | |
+(peter.c)2785 3816 w | |
+10 R f | |
+(.)3205 3816 w | |
+(The)970 3972 w | |
+10 CW f | |
+(X)1150 3972 w | |
+10 R f | |
+(command is a looping construct, like)5 1477 1 1235 3972 t | |
+10 CW f | |
+(x)2737 3972 w | |
+10 R f | |
+(, that refers to files instead of strings:)7 1487 1 2797 3972 t | |
+9 CW f | |
+(X/)1008 4142 w | |
+9 I f | |
+(expression)1116 4142 w | |
+9 CW f | |
+(/)1501 4142 w | |
+9 I f | |
+(command)1609 4142 w | |
+10 R f | |
+( best example is)3 641( The)1 205(runs the command in all files whose menu li… | |
+9 CW f | |
+(X/'/ w)1 324 1 1008 4492 t | |
+10 R f | |
+(which writes to disc all modified files.)6 1571 1 720 4672 t | |
+10 CW f | |
+(Y)2347 4672 w | |
+10 R f | |
+(is the complement of)3 859 1 2438 4672 t | |
+10 CW f | |
+(X)3328 4672 w | |
+10 R f | |
+( command on all files whose)5 1181(: it runs the)3 471 2 3388 4672 t | |
+(menu lines don't match the expression:)5 1568 1 720 4792 t | |
+9 CW f | |
+(Y/\\.c/ D)1 432 1 1008 4962 t | |
+10 R f | |
+(deletes all files that don't have)5 1223 1 720 5142 t | |
+10 CW f | |
+(.c)1968 5142 w | |
+10 R f | |
+(in their names, that is, it keeps all C source files and deletes the rest.)14… | |
+(Braces allow commands to be grouped, so)6 1689 1 970 5298 t | |
+9 CW f | |
+({)1008 5468 w | |
+9 I f | |
+(command1)1440 5578 w | |
+(command2)1440 5688 w | |
+9 CW f | |
+(})1008 5798 w | |
+10 R f | |
+( Thus,)1 275(is syntactically a single command that runs two commands.)8 2379… | |
+9 CW f | |
+(X/\\.c/ ,g/variable/ {)2 1134 1 1008 6148 t | |
+(f)1440 6258 w | |
+(, x/.*\\n/ g/variable/ p)3 1242 1 1440 6368 t | |
+(})1008 6478 w | |
+10 R f | |
+(finds all occurrences of)3 936 1 720 6658 t | |
+10 CW f | |
+(variable)1682 6658 w | |
+10 R f | |
+( out the file names and lines of each match.)9 1748(in C source files, and pr… | |
+(The precise semantics of compound operations is discussed in the implementati… | |
+(Finally, the undo command,)3 1152 1 970 6934 t | |
+10 CW f | |
+(u)2156 6934 w | |
+10 R f | |
+( files were affected.)3 815(, undoes the last command, no matter how many)8 2… | |
+(Multiple undo operations move further back in time, so)8 2212 1 720 7054 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 10 10 | |
+%%Page: 11 11 | |
+/saveobj save def | |
+mark | |
+11 pagesetup | |
+10 R f | |
+(- 11 -)2 216 1 2772 480 t | |
+9 CW f | |
+(u)1008 830 w | |
+(u)1008 940 w | |
+10 R f | |
+(\(which may be abbreviated)3 1086 1 720 1120 t | |
+10 CW f | |
+(u2)1832 1120 w | |
+10 R f | |
+( be undone, however, nor)4 1022( undo may not)3 578( An)1 173(\) undoes the l… | |
+( though, including for example)4 1243( else is undoable,)3 697( Everything)1 … | |
+10 CW f | |
+(e)4980 1240 w | |
+10 R f | |
+(commands:)720 1360 w | |
+9 CW f | |
+(e filename)1 540 1 1008 1530 t | |
+(u)1008 1640 w | |
+10 R f | |
+( of the undo,)3 538( Because)1 393( file completely, including its name, dot,… | |
+( Only)1 259(potentially dangerous commands are not guarded by confirmations.)… | |
+10 CW f | |
+(D)3772 1940 w | |
+10 R f | |
+( informa-)1 382(, which destroys the)3 826 2 3832 1940 t | |
+( a modified file, but a second)6 1210( will not delete)3 618( It)1 118(tion n… | |
+10 CW f | |
+(D)4471 2060 w | |
+10 R f | |
+(of the same)2 476 1 4564 2060 t | |
+( The)1 205(file will succeed regardless.)3 1108 2 720 2180 t | |
+10 CW f | |
+(q)2058 2180 w | |
+10 R f | |
+(command, which exits)2 902 1 2143 2180 t | |
+10 CW f | |
+(sam)3070 2180 w | |
+10 R f | |
+(, is similarly guarded.)3 869 1 3250 2180 t | |
+10 B f | |
+(Mouse Interface)1 695 1 720 2420 t | |
+10 CW f | |
+(Sam)720 2576 w | |
+10 R f | |
+( dif-)1 173( only)1 206( The)1 208(is most commonly run connected to a bitmap… | |
+(ference in the command language between regular, mouse-driven)7 2637 1 720 26… | |
+10 CW f | |
+(sam)3386 2696 w | |
+10 R f | |
+(and)3595 2696 w | |
+10 CW f | |
+(sam -d)1 360 1 3768 2696 t | |
+10 R f | |
+(is that if an address is)5 883 1 4157 2696 t | |
+(provided without a command,)3 1217 1 720 2816 t | |
+10 CW f | |
+(sam -d)1 360 1 1968 2816 t | |
+10 R f | |
+(will print the text referenced by the address, but regular)9 2280 1 2360 2816… | |
+10 CW f | |
+(sam)4672 2816 w | |
+10 R f | |
+(will)4884 2816 w | |
+(highlight it on the screen \320 in fact, dot is always highlighted \(see Figu… | |
+cleartomark | |
+saveobj restore | |
+%ps_include: begin | |
+save | |
+/ed {exch def} def | |
+{} /showpage ed | |
+{} /copypage ed | |
+{} /erasepage ed | |
+{} /letter ed | |
+currentdict /findfont known systemdict /findfont known and { | |
+ /findfont systemdict /findfont get def | |
+} if | |
+36 dict dup /PS-include-dict-dw ed begin | |
+/context ed | |
+count array astore /o-stack ed | |
+%ps_include: variables begin | |
+/llx 80 def | |
+/lly 322 def | |
+/urx 531.44 def | |
+/ury 468.88 def | |
+/w 0 def | |
+/o 0 def | |
+/s 0 def | |
+/cx 2880 def | |
+/cy -3910 def | |
+/sx 4320 def | |
+/sy 1468 def | |
+/ax 0.5 def | |
+/ay 0.5 def | |
+/rot 0 def | |
+%ps_include: variables end | |
+{llx lly urx ury} /bbox ed | |
+{newpath 2 index exch 2 index exch dup 6 index exch | |
+ moveto 3 {lineto} repeat closepath} /boxpath ed | |
+{dup mul exch dup mul add sqrt} /len ed | |
+{2 copy gt {exch} if pop} /min ed | |
+{2 copy lt {exch} if pop} /max ed | |
+{transform round exch round exch A itransform} /nice ed | |
+{6 array} /n ed | |
+n defaultmatrix n currentmatrix n invertmatrix n concatmatrix /A ed | |
+urx llx sub 0 A dtransform len /Sx ed | |
+0 ury lly sub A dtransform len /Sy ed | |
+llx urx add 2 div lly ury add 2 div A transform /Cy ed /Cx ed | |
+rot dup sin abs /S ed cos abs /C ed | |
+Sx S mul Sy C mul add /H ed | |
+Sx C mul Sy S mul add /W ed | |
+sy H div /Scaley ed | |
+sx W div /Scalex ed | |
+s 0 eq {Scalex Scaley min dup /Scalex ed /Scaley ed} if | |
+sx Scalex W mul sub 0 max ax 0.5 sub mul cx add /cx ed | |
+sy Scaley H mul sub 0 max ay 0.5 sub mul cy add /cy ed | |
+urx llx sub 0 A dtransform exch atan rot exch sub /rot ed | |
+n currentmatrix initgraphics setmatrix | |
+cx cy translate | |
+Scalex Scaley scale | |
+rot rotate | |
+Cx neg Cy neg translate | |
+A concat | |
+bbox boxpath clip newpath | |
+w 0 ne {gsave bbox boxpath 1 setgray fill grestore} if | |
+end | |
+gsave | |
+%ps_include: inclusion begin | |
+/picstr 79 string def | |
+80 322 translate | |
+451.44 146.88 scale | |
+ | |
+627 204 1 [627 0 0 -204 0 204] | |
+{currentfile picstr readhexstring pop} image | |
+ | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+fe00000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe00000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe00000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff3fffffff3cffffffffffffffffffffdfe7f3bff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff3fffefff3cffffffff07ffffffffff3fe7f3cff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff3fffe7ff3fffffffff33fffffffffe7fe7f3e7f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff27fff3f820fc1f0fff39c3c9f8723e7f0783e7e | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff13fff9f33cf9ce66033999c4f3311cfe6733f3e | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff39fffce73cf9fce603393cce67339cfce673f3e | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff3980fc673cf8fcffff393cce67339cfce673f3f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdfffffffffffffffffff3980fce73cfc1cffff393cce60339cfce673f3f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdfffffffffffffffffff39fff9e73cff8cfe03393cce67f39cfce673f3f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdfffffffffffffffffff39fff3e73cffccfe03393cce67f39cfce673f3e | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdfffffffffffffffffff33ffe7f23cf9ce67ff3399ccf3339cfe4723f3e | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdfffffffffffffffffff07ffeff9201c1f0fff07c3c1f8739e7f2793e7e | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdfffffffffffffffffffffffffffffffffffffffffcffffffe7fffffe7f | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdfffffffffffffffffffffffffffffffffffffffffcfffffff3fffffcff | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdfffffffffffffffffffffffffffffffffffffffffcfffffffdfffffbfe | |
+7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2ffdffffffffffffffffffffffffff9fffe7ffff7ff9ffffffffffffe7fffd | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffff7fff9fffe7fbfcf0f9ffff7fffffffe7fffe | |
+7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffffffe7ffffffffff3f9e679ffff3fffffffe7ffff | |
+3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff8380c641f2307c079e6793fff9fc3c1f0e47c3f | |
+3f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff39e7e079f11e7f3f3e6f89fffcf999ce662399f | |
+9f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff3fe7e679f39e7f3f3f1f9cfffe739fcce67339f | |
+9f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff1fe7e7f9f39e7f3f3f499cc07e33ffccfe7339f | |
+9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff83e7e7f9f39e7f3f3e4b9cc07e73fc0cfe7301f | |
+9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffff1e7e7f9f39e7f3f3e679cfffcf3f9ccfe733ff | |
+9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffff9e7e7f9f39e7f3f3e679cfff9f3f9ccfe733ff | |
+9f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff39e7e7f9f39e7f3f3e2399fff3f9998e667399f | |
+9f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff83f0c1c033900f879f1183fff7fc3c4f0e73c3f | |
+3f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffffffffffffffffffff9ffffffffffffffffffffff | |
+3f9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffffffffffffffffffffcfffffffffffffffffffffe | |
+7f9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffd | |
+ff3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffffffffffffffffffe7ffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffbfffffffffe7ffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffffffff3fffffffffe7ffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff19e1c06731991ffe4fc7fffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff81ccf3e738188ffe27c7fffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff999cf3e73999cffe73c7fffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff9f9cf3e739f9cffe73fffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff9f80f3e739f9cffe73fffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff9f9ff3e739f9cffe73fffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff9f9ff3e739f9cffe73c7fffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff9fccf3e239f9cffe67c7fffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff07e1f8713079cffe0fc7fffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffffffffffffffffffffffe7fffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffffffffffffffffffffffe7fffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffffffffffffffffffffffcffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fc7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe3fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffff83ffffffffee7fbffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221f03fff3ffffffff9e7fcffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f39fff3ffffffff3e7fe7fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221f39e1f3f0f83e1f3e4fe7fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f39ccf3e6739cce7e27f3fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221f3b9cf3cf33f9ce7e73f3fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f079ff3cf31f9ce7e73f3fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221f3b9ff3cf38380e7e73f3fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f399ff3cf3f19fe7e73f3fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221f399ff3cf3f99fe7e73f3fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f39ccf3e6739cce7e67f3fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221f03e18070f83e1f3e0fe7fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffff3fffe7fffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffff9fffcffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffefffbffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffffffffff9fffffffffffffffffc3e1fffffffff9 | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffff9ffff7fffffff81fff9fcffffffffff9 | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffffffffffffffe7fffffff9cfff9fcffffffffff9 | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff19e1f041f8380f0e33ff9cce60301e1c67ffef9 | |
+3f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff81cce679f39e7e6703ff9cce79fcfcce07ffab8 | |
+9f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff999cce79f3fe7ce733ff9dce79fcf9ce67ffc79 | |
+cf1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff9f9cce79f1fe7ce73fff83ce79fcf9ce7fff119 | |
+cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff9f80ce79f83e7c073fff9dce79fcf80e7fffc79 | |
+cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff9f9fce79ff1e7cff3fff9cce79fcf9fe7fffab9 | |
+cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff9f9fce79ff9e7cff3fff9cce79fcf9fe7fffef9 | |
+cf1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffff9fcce479f39e7e673fff9cc479fcfcce7fffff9 | |
+9f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffff07e1f240383f0f0e0fff81e260703e1c1fffff8 | |
+3f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffffffffe7ffffffffffffffffffffffffffffffff | |
+ff9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fffffffffffffffffffffffce7ffffffffffffffffffffffffffffffff | |
+ff9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fffffffffffffffffffffffe0fffffffffffffffffffffffffffffffff | |
+ff3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe3fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe3fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffc000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889ffffffffffffffffffc00007c000000001180000001860000010000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221ffffffffffffffffffcf8000c00000000618000200186000000c000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889ffffffffffffffffffccc000c00000000c180003001800000006000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221ffffffffffffffffffcc61e0c0f07c1e0c1b000180fbe07c1e06070000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889ffffffffffffffffffcc6330c198c633181d8000c19860c63303070000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221ffffffffffffffffffcc6630c30cc0631818c000631860c06303070000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889ffffffffffffffffffcc6600c30ce0631818cfe0731860e06003000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221ffffffffffffffffffcc6600c30c7c7f1818cfe06318607c6003000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889ffffffffffffffffffcc6600c30c0e601818c000c318600e6003000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221ffffffffffffffffffcc6600c30c06601818c001831860066003070000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889ffffffffffffffffffccc330c198c6331819800301b860c63303070000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221ffffffffffffffffffcf81e7f8f07c1e0c1f000200dbfc7c1e06070000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889ffffffffffffffffffc00000000000000c000000000000000006030000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221ffffffffffffffffffc00000000000000600000000000000000c030000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889ffffffffffffffffffc000000000000001000000000000000010060000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889c000000000000000000000000001f00000000040030000000000000c00 | |
+0100000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c000000000000000000000800000300000000187830000400000000c00 | |
+00c0000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889c00000000000000000000180000030000000030cc30000600000000c00 | |
+0060000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c0000000000000000007c7f39878303c1f07830cc36000301e1f078dc1 | |
+e060700000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889c000000000000000000c6181f8cc3066318cc60c83b0001833318ccee3 | |
+3030700000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c000000000000000000c0181998c30c33018c6070318000c630198cc66 | |
+3030700000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889c000000000000000000e0181818030c33818c605b319fc0e6001980c66 | |
+3030000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c0000000000000000007c181818030c31f1fc60da319fc0c601f980c67 | |
+f030000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889c0000000000000000000e181818030c30398060cc31800186031980c66 | |
+0030000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c00000000000000000006181818030c30198060cc31800306031980c66 | |
+0030700000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889c000000000000000000c618180cc3066318cc60ee330006033338ccc63 | |
+3030700000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c0000000000000000007c0f3e079fe3c1f07830773e000401e1d878c61 | |
+e060700000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889c000000000000000000000000000000000000300000000000000000000 | |
+0060300000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c000000000000000000000000000000000000180000000000000000000 | |
+00c0300000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2889c000000000000000000000000000000000000040000000000000000000 | |
+0100600000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe2221c00000000000000000000000000000000000000000000000000000001f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889c0000000000000000001e0000000040200000c0000000000203008001f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221c000000000000000000300000000180c00000c0000000000183006001f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889c000000000000000000300000000301800000c00000000000c3003001f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221c000000000000000000fe730f078301831878dc3e39800100c3603039f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889c000000000000000000303f198cc6030318ccee631f80054063b01839f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221c00000000000000000030333198c60303198cc6031980038063181839f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889c00000000000000000030303198c603031980c60318000ee063181801f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221c00000000000000000030303f9fc603031980c63f1800038063181801f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889c000000000000000000303030180603031980c6631800054063181801f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221c000000000000000000303030180603031980c6631800010063181839f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889c0000000000000000003030198cc60303b8ccc6671800000063301839f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221c000000000000000000fc7c0f07830181d878c63b3e000000c3e03039f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889c000000000000000000000000000301800000000000000000c0003019f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221c000000000000000000000000000180c0000000000000000180006019f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889c00000000000000000000000000004020000000000000000200008031f | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fc7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe3fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2889ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2221ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe2001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+fffffffffffffffffffffffffe3fff | |
+fe00000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe00000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+fe00000000000000000000000000000000000000000000000000000000000000 | |
+0000000000000000000000000000000000000000000000000000000000000000 | |
+000000000000000000000000003fff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffff | |
+showpage | |
+%ps_include: inclusion end | |
+grestore | |
+PS-include-dict-dw begin | |
+o 0 ne {gsave A defaultmatrix /A ed llx lly nice urx ury nice | |
+ initgraphics 0.1 setlinewidth boxpath stroke grestore} if | |
+clear o-stack aload pop | |
+context end restore | |
+%ps_include: end | |
+/saveobj save def | |
+mark | |
+8 I f | |
+(Figure 2. A)2 370 1 720 4744 t | |
+8 CW f | |
+(sam)1112 4744 w | |
+8 I f | |
+( bar down the left represents the file, with the bubble showing the fraction … | |
+( current text, which is highlighted, need not fit on a)10 1703( The)1 167( be… | |
+( it consists of one partial line, one complete line, and final partial line.)… | |
+10 R f | |
+( in all)2 236( any time, only one window)5 1131( At)1 153(Each file may have … | |
+(of)720 5340 w | |
+10 CW f | |
+(sam)830 5340 w | |
+10 R f | |
+(is the)1 216 1 1037 5340 t | |
+10 I f | |
+(current window,)1 658 1 1280 5340 t | |
+10 R f | |
+( may be the)3 466(that is, the window to which typing and mouse actions refer… | |
+10 CW f | |
+(sam)720 5460 w | |
+10 R f | |
+( a file has multiple)4 752( When)1 290( file windows.)2 573(window \(that in … | |
+( current file is the last file)6 1074( The)1 213(windows, the image of the fi… | |
+(affected by a command, so if the)6 1401 1 720 5700 t | |
+10 CW f | |
+(sam)2162 5700 w | |
+10 R f | |
+( the)1 164(window is current, the current window is not a window on)10 2493 2… | |
+( window on a file has its own value of dot, and when switching between)14 314… | |
+( flipping between)2 711( Thus,)1 281( file, the file's value of dot is change… | |
+(windows behaves in the obvious, convenient way.)6 2003 1 720 6060 t | |
+( 3 has a list of commands to)7 1154( Button)1 328( numbered left to right.)4 … | |
+( as printed by the)4 708(manipulate windows, followed by a list of `menu line… | |
+10 CW f | |
+(f)4037 6336 w | |
+10 R f | |
+(command, one per file)3 913 1 4127 6336 t | |
+( the list is long, the Blit menu software)8 1577( If)1 119( file name.)2 430(… | |
+( the)1 153( Using)1 295( manageable by generating a scrolling menu instead of… | |
+( makes that file the current file, and the most recently current window in)13… | |
+( if that file is already current, selecting it in the menu cycles through the… | |
+( is no)2 239( there)1 234( If)1 126(windows on the file; this simple trick av… | |
+(window open on the file,)4 996 1 720 7056 t | |
+10 CW f | |
+(sam)1741 7056 w | |
+10 R f | |
+(changes the mouse cursor to prompt the user to create one.)10 2342 1 1946 705… | |
+( commands)1 465(The commands on the button 3 menu are straightforward \(see F… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 11 11 | |
+%%Page: 12 12 | |
+/saveobj save def | |
+mark | |
+12 pagesetup | |
+10 R f | |
+(- 12 -)2 216 1 2772 480 t | |
+(to manipulate windows in)3 1048 1 720 840 t | |
+10 CW f | |
+(mux)1797 840 w | |
+10 R f | |
+(,)1977 840 w | |
+6 R f | |
+(8)2002 790 w | |
+10 R f | |
+(the Blit's window system.)3 1057 1 2061 840 t | |
+10 CW f | |
+(New)3172 840 w | |
+10 R f | |
+( empty)1 278(makes a new file, and gives it one)7 1381 2 3381 840 t | |
+(window, whose size is determined by a rectangle swept by the mouse.)11 2820 1… | |
+10 CW f | |
+(Xerox)3592 960 w | |
+10 R f | |
+( a window to be)4 650(prompts for)1 471 2 3919 960 t | |
+( multiple windows are created on one file.)7 1848(selected, and makes a clone… | |
+10 CW f | |
+(Reshape)720 1200 w | |
+10 R f | |
+( and)1 172(changes the size of the indicated window,)6 1678 2 1167 1200 t | |
+10 CW f | |
+(close)3045 1200 w | |
+10 R f | |
+( that is the last window open)6 1162( If)1 119(deletes it.)1 386 3 3373 1200 t | |
+(on the file,)2 434 1 720 1320 t | |
+10 CW f | |
+(close)1180 1320 w | |
+10 R f | |
+(first does a)2 440 1 1506 1320 t | |
+10 CW f | |
+(D)1972 1320 w | |
+10 R f | |
+(command on the file.)3 852 1 2058 1320 t | |
+10 CW f | |
+(Write)2961 1320 w | |
+10 R f | |
+(is identical to a)3 611 1 3287 1320 t | |
+10 CW f | |
+(w)3924 1320 w | |
+10 R f | |
+(command on the file; it is)5 1030 1 4010 1320 t | |
+( Finally,)1 373(in the menu purely for convenience.)5 1511 2 720 1440 t | |
+10 CW f | |
+(\304\304sam\304\304)2643 1440 w | |
+10 R f | |
+( the com-)2 407(is a menu item that appears between)6 1531 2 3102 1440 t | |
+( it makes the)3 544( Selecting)1 434(mands and the file names.)4 1088 3 720 1… | |
+10 CW f | |
+(sam)2822 1560 w | |
+10 R f | |
+(window the current window, causing subsequent)5 2002 1 3038 1560 t | |
+(typing to be interpreted as commands.)5 1526 1 720 1680 t | |
+cleartomark | |
+saveobj restore | |
+%ps_include: begin | |
+save | |
+/ed {exch def} def | |
+{} /showpage ed | |
+{} /copypage ed | |
+{} /erasepage ed | |
+{} /letter ed | |
+currentdict /findfont known systemdict /findfont known and { | |
+ /findfont systemdict /findfont get def | |
+} if | |
+36 dict dup /PS-include-dict-dw ed begin | |
+/context ed | |
+count array astore /o-stack ed | |
+%ps_include: variables begin | |
+/llx 242 def | |
+/lly 297 def | |
+/urx 369.44 def | |
+/ury 494.28 def | |
+/w 0 def | |
+/o 0 def | |
+/s 0 def | |
+/cx 2880 def | |
+/cy -2906 def | |
+/sx 4320 def | |
+/sy 1972 def | |
+/ax 0.5 def | |
+/ay 0.5 def | |
+/rot 0 def | |
+%ps_include: variables end | |
+{llx lly urx ury} /bbox ed | |
+{newpath 2 index exch 2 index exch dup 6 index exch | |
+ moveto 3 {lineto} repeat closepath} /boxpath ed | |
+{dup mul exch dup mul add sqrt} /len ed | |
+{2 copy gt {exch} if pop} /min ed | |
+{2 copy lt {exch} if pop} /max ed | |
+{transform round exch round exch A itransform} /nice ed | |
+{6 array} /n ed | |
+n defaultmatrix n currentmatrix n invertmatrix n concatmatrix /A ed | |
+urx llx sub 0 A dtransform len /Sx ed | |
+0 ury lly sub A dtransform len /Sy ed | |
+llx urx add 2 div lly ury add 2 div A transform /Cy ed /Cx ed | |
+rot dup sin abs /S ed cos abs /C ed | |
+Sx S mul Sy C mul add /H ed | |
+Sx C mul Sy S mul add /W ed | |
+sy H div /Scaley ed | |
+sx W div /Scalex ed | |
+s 0 eq {Scalex Scaley min dup /Scalex ed /Scaley ed} if | |
+sx Scalex W mul sub 0 max ax 0.5 sub mul cx add /cx ed | |
+sy Scaley H mul sub 0 max ay 0.5 sub mul cy add /cy ed | |
+urx llx sub 0 A dtransform exch atan rot exch sub /rot ed | |
+n currentmatrix initgraphics setmatrix | |
+cx cy translate | |
+Scalex Scaley scale | |
+rot rotate | |
+Cx neg Cy neg translate | |
+A concat | |
+bbox boxpath clip newpath | |
+w 0 ne {gsave bbox boxpath 1 setgray fill grestore} if | |
+end | |
+gsave | |
+%ps_include: inclusion begin | |
+/picstr 23 string def | |
+242 297 translate | |
+127.44 197.28 scale | |
+ | |
+177 274 1 [177 0 0 -274 0 274] | |
+{currentfile picstr readhexstring pop} image | |
+ | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffc00000000000000000000000000000000000000fffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffe47c39cfffffffffffffefffff | |
+ffc0000fffffffffffffe23999efffffffffffffefffff | |
+ffc0000fffffffffffffe733992fffffffffffffefffff | |
+ffc0000fffffffffffffe733992fffffffffffffefffff | |
+ffc0000fffffffffffffe730192fffffffffffffefffff | |
+ffc0000fffffffffffffe733fc9fffffffffffffefffff | |
+ffc0000fffffffffffffe733fc9fffffffffffffefffff | |
+ffc0000fffffffffffffe7399c9fffffffffffffefffff | |
+ffc0000fffffffffffffe73c3c9fffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffce78719c3ce7ffffffffffefffff | |
+ffc0000fffffffffffce7338199ce7ffffffffffefffff | |
+ffc0000fffffffffffe6e73993ce6fffffffffffefffff | |
+ffc0000fffffffffffe1e739f3ce1fffffffffffefffff | |
+ffc0000ffffffffffffbe039f3cfbfffffffffffefffff | |
+ffc0000ffffffffffff0e7f9f3cf0fffffffffffefffff | |
+ffc0000fffffffffffece7f9f3cecfffffffffffefffff | |
+ffc0000fffffffffffce7339f99ce7ffffffffffefffff | |
+ffc0000fffffffffffce78707c3ce7ffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000ffffffffffffffff3ffffffffffffffffefffff | |
+ffc0000ffffffffffffffff3ffffffffffffffffefffff | |
+ffc0000ffffffffffffffff3ffffffffffffffffefffff | |
+ffc0000fffffffff8cf0f0723c1c9f87ffffffffefffff | |
+ffc0000fffffffffc0e6673119cc4f33ffffffffefffff | |
+ffc0000fffffffffccce67f39fcce673ffffffffefffff | |
+ffc0000fffffffffcfce63f39fcce673ffffffffefffff | |
+ffc0000fffffffffcfc070739c0ce603ffffffffefffff | |
+ffc0000fffffffffcfcffe3399cce67fffffffffefffff | |
+ffc0000fffffffffcfcfff3399cce67fffffffffefffff | |
+ffc0000fffffffffcfe66733998ccf33ffffffffefffff | |
+ffc0000fffffffff83f0f0739c4c1f87ffffffffefffff | |
+ffc0000ffffffffffffffffffffcffffffffffffefffff | |
+ffc0000ffffffffffffffffffffcffffffffffffefffff | |
+ffc0000ffffffffffffffffffffcffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffc1ffffffffffffffffffefffff | |
+ffc0000ffffffffffffff9ffffffffffffffffffefffff | |
+ffc0000ffffffffffffff9ffffffffffffffffffefffff | |
+ffc0000ffffffffffff0f9f87c1f0fffffffffffefffff | |
+ffc0000fffffffffffe679f339ce67ffffffffffefffff | |
+ffc0000fffffffffffce79e799fce7ffffffffffefffff | |
+ffc0000fffffffffffcff9e798fce7ffffffffffefffff | |
+ffc0000fffffffffffcff9e79c1c07ffffffffffefffff | |
+ffc0000fffffffffffcff9e79f8cffffffffffffefffff | |
+ffc0000fffffffffffcff9e79fccffffffffffffefffff | |
+ffc0000fffffffffffe679f339ce67ffffffffffefffff | |
+ffc0000ffffffffffff0c0387c1f0fffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc00008000000000000000000000000000000000fffff | |
+ffc00008000000000000000000000000000000000fffff | |
+ffc00008000000000000000300000000000000000fffff | |
+ffc00008000000000000000300800000000000000fffff | |
+ffc00008000000000000000001800000000000000fffff | |
+ffc000080000000000319cdf07f0f000000000000fffff | |
+ffc000080000000000308fc301819800000000000fffff | |
+ffc000080000000000368cc30183180000ff80000fffff | |
+ffc000080000000000368c030183180000fe00000fffff | |
+ffc000080000000000368c030183f80000f800000fffff | |
+ffc0000800000000001b0c030183000000fc00000fffff | |
+ffc0000800000000001b0c030183000000fe00000fffff | |
+ffc0000800000000001b0c030181980000df00000fffff | |
+ffc0000800000000001b1f1fe0f0f00000cf80000fffff | |
+ffc000080000000000000000000000000087c0000fffff | |
+ffc000080000000000000000000000000083e0000fffff | |
+ffc0000ffffffffffffffffffffffffffffe0fffefffff | |
+ffc0000fffffffffffffffffffffffffffff07ffefffff | |
+ffc0000fffffffffffffffffffffffffffff83ffefffff | |
+ffc0000fffffffffffffffffffffffffffffc1ffefffff | |
+ffc0000fffffffffffffffffffffffffffffe0ffefffff | |
+ffc0000ffffffffffffff07832dffffffffff1ffefffff | |
+ffc0000fffffffffeef76733900f77bbfffffbffefffff | |
+ffc0000fffffffffc6e367ff924e371bffffffffefffff | |
+ffc0000fffffffff80c063ff924c0603ffffffffefffff | |
+ffc0000fffffffffb1d8f078124d8ec7ffffffffefffff | |
+ffc0000fffffffffbbddfe33924ddeefffffffffefffff | |
+ffc0000fffffffffffffff33924fffffffffffffefffff | |
+ffc0000fffffffffffffe733124fffffffffffffefffff | |
+ffc0000ffffffffffffff078924fffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000ffffffffffffff3f9ffffffffffffffffefffff | |
+ffc0000ffffffffffffff3f9ffffffffffffffffefffff | |
+ffc0000ffffffffffffff3f9ffffffffffffffffefffff | |
+ffc0000ffff9fffffe0f83c18cf0f0783fff0fffefffff | |
+ffc0000ffff9fffffce73399c0e667339ffe67ffefffff | |
+ffc0000ffff9ffffffe67339ccce67f3fffce7ffefffff | |
+ffc0000fffc03fffffe67339cfce63f1fffcffffefffff | |
+ffc0000fffc03ffffe067339cfc070783ffcffffefffff | |
+ffc0000ffff9fffffce67339cfcffe3f1ffcffffefffff | |
+ffc0000ffff9fc7ffce67339cfcfff3f9e3cffffefffff | |
+ffc0000ffff9fc7ffcc72391cfe667339e3e67ffefffff | |
+ffc0000ffffffc7ffe2793c983f0f0783e3f0fffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000fffffffffffffffffffffffffffffffffefffff | |
+ffc0000ffffffffffffc1e0fffffffffffffffffefffff | |
+ffc0000fffffffffffff9fcfffffffffffffffffefffff | |
+ffc0000fffffffffffff9fcfffffffffffffffffefffff | |
+ffc0000ffffffffffe0f9fcfc3f0fffc3fffffffefffff | |
+ffc0000ffffffffffce79fcf99e67ff99fffffffefffff | |
+ffc0000fffffffffffe79fcf3cce7ff39fffffffefffff | |
+ffc0000fffe03fffffe79fcf3ccffff3ffffffffefffff | |
+ffc0000fffe03ffffe079fcf3ccffff3ffffffffefffff | |
+ffc0000ffffffffffce79fcf3ccffff3ffffffffefffff | |
+ffc0000ffffffffffce79fcf3ccff8f3ffffffffefffff | |
+ffdffffffffffffffcc79fcf99e678f99fffffffefffff | |
+ffdffffffffffffffe240201c3f0f8fc3fffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdffffffffffffffcffffe1f0ffffffffffffffefffff | |
+ffdffffffffffffffcffffcfe7ffffffffffffffefffff | |
+ffdffffffffffffffcffffcfe7ffffffffffffffefffff | |
+ffdffffffffdfffffc9e730180f0e33ffe1fffffefffff | |
+ffdffffffff57ffffc4e73cfe7e6703ffccfffffefffff | |
+ffdffffffff8fffffce673cfe7ce733ff9cfffffefffff | |
+ffdfffffffe23ffffce673cfe7ce73fff9ffffffefffff | |
+ffdffffffff8fffffce673cfe7c073fff9ffffffefffff | |
+ffdffffffff57ffffce673cfe7cff3fff9ffffffefffff | |
+ffdffffffffdfffffce673cfe7cff3fc79ffffffefffff | |
+ffdffffffffffffffcce23cfe7e673fc7ccfffffefffff | |
+ffdffffffffffffffc1f130381f0e0fc7e1fffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdffffffffffffffffffff9ffffffffffffffffefffff | |
+ffdffffffffffffffffffff9ffffffffffffffffefffff | |
+ffdffffffffffffffffffff9ffffffffffffffffefffff | |
+ffdfffffffffffffff0cb7c1fff0ffffffffffffefffff | |
+ffdffffffffffffffe640399ffe67fffffffffffefffff | |
+ffdffffffffffffffce49339ffce7fffffffffffefffff | |
+ffdfffffffe03ffffcfc9339ffcfffffffffffffefffff | |
+ffdfffffffe03ffffcfc9339ffcfffffffffffffefffff | |
+ffdffffffffffffffcfc9339ffcfffffffffffffefffff | |
+ffdffffffffffffffcfc9339e3cfffffffffffffefffff | |
+ffdffffffffffffffe649391e3e67fffffffffffefffff | |
+ffdfffffffffffffff0c93c9e3f0ffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdffffff1ffffffffe79fffffffffffffffffffefffff | |
+ffdffffff1ffffffffe79fffffffffffffffffffefffff | |
+ffdffffff1ffffffffe7ffffffffffffffffffffefffff | |
+ffdffffff9f9ffffff041f83e1fff87fffffffffefffff | |
+ffdffffff9f9fffffe679f39ccfff33fffffffffefffff | |
+ffdffffff3f9fffffce79f3f9cffe73fffffffffefffff | |
+ffdfffffffc03ffffce79f1f9fffe7ffffffffffefffff | |
+ffdfffffffc03ffffce79f839fffe7ffffffffffefffff | |
+ffdffffffff9fffffce79ff19fffe7ffffffffffefffff | |
+ffdffffffff9fffffce79ff99ff1e7ffffffffffefffff | |
+ffdffffffff9fffffe479f39ccf1f33fffffffffefffff | |
+ffdfffffffffffffff240383e1f1f87fffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffff0e3319c3c67ffc3fffffffefffff | |
+ffdffffffffffffffe67038199e07ff99fffffffefffff | |
+ffdffffffffffffffce733993ce67ff39fffffffefffff | |
+ffdfffffffe03ffffce73f9f3ce7fff3ffffffffefffff | |
+ffdfffffffe03ffffc073f9f3ce7fff3ffffffffefffff | |
+ffdffffffffffffffcff3f9f3ce7fff3ffffffffefffff | |
+ffdffffffffffffffcff3f9f3ce7f8f3ffffffffefffff | |
+ffdffffffffffffffe673f9f99e7f8f99fffffffefffff | |
+ffdfffffffffffffff0e0f07c3c1f8fc3fffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdffffffffffffffffffffffffffffff9ffffffefffff | |
+ffdffffffffffffffffffffffffffffff9ffffffefffff | |
+ffdffffffffffffffffffffffffffffff9ffffffefffff | |
+ffdfffffffffffffff0e3319c3c6707ff91fffffefffff | |
+ffdffffffffffffffe67038199e0673ff88fffffefffff | |
+ffdffffffffffffffce733993ce667fff9cfffffefffff | |
+ffdfffffffe03ffffce73f9f3ce7e3fff9cfffffefffff | |
+ffdfffffffe03ffffc073f9f3ce7f07ff9cfffffefffff | |
+ffdffffffffffffffcff3f9f3ce7fe3ff9cfffffefffff | |
+ffdffffffffffffffcff3f9f3ce7ff3c79cfffffefffff | |
+ffdffffffffffffffe673f9f99e7e73c79cfffffefffff | |
+ffdfffffffffffffff0e0f07c3c1f07c79cfffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffff879e0fffffffffffffffffefffff | |
+ffdfffffffffffffff3f9fcfffffffffffffffffefffff | |
+ffdfffffffffffffff3fffcfffffffffffffffffefffff | |
+ffdffffffffffffffc041fcfe1fff87fffffffffefffff | |
+ffdfffffffffffffff3f9fcfccfff33fffffffffefffff | |
+ffdfffffffffffffff3f9fcf9cffe73fffffffffefffff | |
+ffdfffffffe03fffff3f9fcf9cffe7ffffffffffefffff | |
+ffdfffffffe03fffff3f9fcf80ffe7ffffffffffefffff | |
+ffdfffffffffffffff3f9fcf9fffe7ffffffffffefffff | |
+ffdfffffffffffffff3f9fcf9ff1e7ffffffffffefffff | |
+ffdfffffffffffffff3f9fcfccf1f33fffffffffefffff | |
+ffdffffffffffffffc0c0201e1f1f87fffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffff0783ffffffffffffefffff | |
+ffdfffffffffffffffffffffe7f3ffffffffffffefffff | |
+ffdfffffffffffffffffffffe7f3ffffffffffffefffff | |
+ffdfffffffffffffff078783e7f3f0fc3fff0fffefffff | |
+ffdffffffffffffffe673339e7f3e6799ffe67ffefffff | |
+ffdffffffffffffffce673f9e7f3cf339ffce7ffefffff | |
+ffdfffffffe03ffffce67ff9e7f3cf33fffcffffefffff | |
+ffdfffffffe03ffffce67f81e7f3cf33fffcffffefffff | |
+ffdffffffffffffffce67f39e7f3cf33fffcffffefffff | |
+ffdffffffffffffffce67f39e7f3cf33fe3cffffefffff | |
+ffdffffffffffffffe473331e7f3e6799e3e67ffefffff | |
+ffdfffffffffffffff278789008070fc3e3f0fffefffff | |
+ffdfffffffffffffffe7ffffffffffffffffffffefffff | |
+ffdffffffffffffffce7ffffffffffffffffffffefffff | |
+ffdffffffffffffffe0fffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffff3fffffffffffffffffffffefffff | |
+ffdfffffffffffffff3fffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdffffffffffffff83f0fffe1ffffffffffffffefffff | |
+ffdfffffffffffffff3e67ffccffffffffffffffefffff | |
+ffdfffffffffffffff3cf3ff9cffffffffffffffefffff | |
+ffdfffffffe03fffff3cf3ff9fffffffffffffffefffff | |
+ffdfffffffe03fffff3cf3ff9fffffffffffffffefffff | |
+ffdfffffffffffffff3cf3ff9fffffffffffffffefffff | |
+ffdfffffffffffffff3cf3c79fffffffffffffffefffff | |
+ffdfffffffffffffff3e67c7ccffffffffffffffefffff | |
+ffdffffffffffffff8070fc7e1ffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffdfffffffffffffffffffffffffffffffffffffefffff | |
+ffc00000000000000000000000000000000000000fffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffffffffffffffffffffffff | |
+showpage | |
+%ps_include: inclusion end | |
+grestore | |
+PS-include-dict-dw begin | |
+o 0 ne {gsave A defaultmatrix /A ed llx lly nice urx ury nice | |
+ initgraphics 0.1 setlinewidth boxpath stroke grestore} if | |
+clear o-stack aload pop | |
+context end restore | |
+%ps_include: end | |
+/saveobj save def | |
+mark | |
+8 I f | |
+( prevent its)2 361( black rectangle on the left is a scroll bar; the menu is … | |
+( the)1 121( Above)1 243(becoming unwieldy.)1 642 3 720 4092 t | |
+8 CW f | |
+(\304\304sam\304\304)1750 4092 w | |
+8 I f | |
+( a list of files, presented exactly as with the)9 1397(line is a list of comm… | |
+8 CW f | |
+(f)4810 4092 w | |
+8 I f | |
+(com-)4881 4092 w | |
+(mand.)720 4192 w | |
+10 R f | |
+(When)970 4468 w | |
+10 CW f | |
+(sam)1241 4468 w | |
+10 R f | |
+(requests that a window be swept, in response to)8 1972 1 1454 4468 t | |
+10 CW f | |
+(new)3460 4468 w | |
+10 R f | |
+(,)3640 4468 w | |
+10 CW f | |
+(xerox)3699 4468 w | |
+10 R f | |
+(or)4033 4468 w | |
+10 CW f | |
+(reshape)4150 4468 w | |
+10 R f | |
+(, it changes)2 470 1 4570 4468 t | |
+( may be used to)4 631( this state, the mouse)4 844( In)1 135(the mouse cursor… | |
+( one corner and releasing it at the opposite corner.)9 2103(indicate an arbit… | |
+( button 3 may simply be clicked, whereupon)7 1860(More conveniently,)1 795 2 … | |
+10 CW f | |
+(sam)3412 4828 w | |
+10 R f | |
+(creates the maximal rectangle that)4 1411 1 3629 4828 t | |
+( the)1 155(contains the cursor and abuts)4 1187 2 720 4948 t | |
+10 CW f | |
+(sam)2095 4948 w | |
+10 R f | |
+( placing the)2 482(window. By)1 522 2 2308 4948 t | |
+10 CW f | |
+(sam)3345 4948 w | |
+10 R f | |
+(window in the middle of the screen,)6 1482 1 3558 4948 t | |
+( stacked fully-overlapping windows can be)5 1721(the user can define two regi… | |
+( simple user interface trick makes window creation notice-)8 2403( This)1 236… | |
+(ably easier.)1 454 1 720 5308 t | |
+(The cut-and-paste editor is essentially the same as that in Smalltalk-80.)10 … | |
+6 R f | |
+(11)3914 5414 w | |
+10 R f | |
+( always)1 313(The text in dot is)4 718 2 4009 5464 t | |
+( after the)2 358( a character is typed it replaces dot, and sets dot to the n… | |
+( button, moving)2 657( 1 is used for selection: pressing the)7 1492( Button)1… | |
+( to\) the text between the points where the button was)10 2248(the mouse, and… | |
+( a null string; this is called clicking.)7 1477( and releasing at the same po… | |
+(Clicking twice quickly, or)3 1077 1 720 6064 t | |
+10 I f | |
+(double clicking,)1 648 1 1833 6064 t | |
+10 R f | |
+(selects larger objects; for example, double clicking in a word)9 2524 1 2516 … | |
+( clicking just inside an opening bracket selects the text contained in the br… | |
+( double-clicking)1 656( The)1 209( similarly for parentheses, quotes, and so … | |
+( If)1 127(rules reflect a bias toward programmers.)5 1667 2 720 6424 t | |
+10 CW f | |
+(sam)2550 6424 w | |
+10 R f | |
+( more for word processing, double-clicks)5 1701(were intended)1 573 2 2766 64… | |
+(would probably select linguistic structures such as sentences.)7 2441 1 720 6… | |
+( is the)2 245( This)1 231( outside the current window, it makes the indicated… | |
+(easiest way to switch between windows and files.)7 1980 1 720 6820 t | |
+( mostly apply to the)4 835( These)1 298( of editing functions \(see Figure 4\… | |
+(selected text:)1 537 1 720 7096 t | |
+10 CW f | |
+(cut)1295 7096 w | |
+10 R f | |
+( remembers it in a hidden buffer called the)8 1792(deletes the selected text,… | |
+10 I f | |
+(snarf buffer,)1 507 1 4533 7096 t | |
+10 CW f | |
+(paste)720 7216 w | |
+10 R f | |
+(replaces the selected text by the contents of the snarf buffer,)10 2426 1 104… | |
+10 CW f | |
+(snarf)3501 7216 w | |
+10 R f | |
+(just copies the selected text to)5 1211 1 3829 7216 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 12 12 | |
+%%Page: 13 13 | |
+/saveobj save def | |
+mark | |
+13 pagesetup | |
+10 R f | |
+(- 13 -)2 216 1 2772 480 t | |
+(the snarf buffer,)2 667 1 720 840 t | |
+10 CW f | |
+(look)1426 840 w | |
+10 R f | |
+( next literal occurrence of the selected text, and)8 1990(searches forward fo… | |
+10 CW f | |
+(<mux>)4740 840 w | |
+10 R f | |
+(exchanges snarf buffers with the window system in which)8 2510 1 720 960 t | |
+10 CW f | |
+(sam)3280 960 w | |
+10 R f | |
+( the last regular)3 693( Finally,)1 384(is running.)1 453 3 3510 960 t | |
+( occurrence of a match for the)6 1291(expression used appears as a menu entry… | |
+(expression.)720 1200 w | |
+cleartomark | |
+saveobj restore | |
+%ps_include: begin | |
+save | |
+/ed {exch def} def | |
+{} /showpage ed | |
+{} /copypage ed | |
+{} /erasepage ed | |
+{} /letter ed | |
+currentdict /findfont known systemdict /findfont known and { | |
+ /findfont systemdict /findfont get def | |
+} if | |
+36 dict dup /PS-include-dict-dw ed begin | |
+/context ed | |
+count array astore /o-stack ed | |
+%ps_include: variables begin | |
+/llx 268 def | |
+/lly 352 def | |
+/urx 342.16 def | |
+/ury 438.4 def | |
+/w 0 def | |
+/o 0 def | |
+/s 0 def | |
+/cx 2880 def | |
+/cy -1872 def | |
+/sx 4320 def | |
+/sy 864 def | |
+/ax 0.5 def | |
+/ay 0.5 def | |
+/rot 0 def | |
+%ps_include: variables end | |
+{llx lly urx ury} /bbox ed | |
+{newpath 2 index exch 2 index exch dup 6 index exch | |
+ moveto 3 {lineto} repeat closepath} /boxpath ed | |
+{dup mul exch dup mul add sqrt} /len ed | |
+{2 copy gt {exch} if pop} /min ed | |
+{2 copy lt {exch} if pop} /max ed | |
+{transform round exch round exch A itransform} /nice ed | |
+{6 array} /n ed | |
+n defaultmatrix n currentmatrix n invertmatrix n concatmatrix /A ed | |
+urx llx sub 0 A dtransform len /Sx ed | |
+0 ury lly sub A dtransform len /Sy ed | |
+llx urx add 2 div lly ury add 2 div A transform /Cy ed /Cx ed | |
+rot dup sin abs /S ed cos abs /C ed | |
+Sx S mul Sy C mul add /H ed | |
+Sx C mul Sy S mul add /W ed | |
+sy H div /Scaley ed | |
+sx W div /Scalex ed | |
+s 0 eq {Scalex Scaley min dup /Scalex ed /Scaley ed} if | |
+sx Scalex W mul sub 0 max ax 0.5 sub mul cx add /cx ed | |
+sy Scaley H mul sub 0 max ay 0.5 sub mul cy add /cy ed | |
+urx llx sub 0 A dtransform exch atan rot exch sub /rot ed | |
+n currentmatrix initgraphics setmatrix | |
+cx cy translate | |
+Scalex Scaley scale | |
+rot rotate | |
+Cx neg Cy neg translate | |
+A concat | |
+bbox boxpath clip newpath | |
+w 0 ne {gsave bbox boxpath 1 setgray fill grestore} if | |
+end | |
+gsave | |
+%ps_include: inclusion begin | |
+/picstr 13 string def | |
+268 352 translate | |
+ 74.16 86.40 scale | |
+ | |
+103 120 1 [103 0 0 -120 0 120] | |
+{currentfile picstr readhexstring pop} image | |
+ | |
+ffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffff | |
+f800000000000000000001ffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffdfffffffdffff | |
+fbfffffffffff9fffffffdffff | |
+fbffffffe1ce603ffffffdffff | |
+fbffffffccce79fffffffdffff | |
+fbffffff9cce79fffffffdffff | |
+fbffffff9fce79fffffffdffff | |
+fbffffff9fce79fffffffdffff | |
+fbffffff9fce79fffffffdffff | |
+fbffffff9fce79fffffffdffff | |
+fbffffffccc479fffffffdffff | |
+fbffffffe1e27c3ffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffdfffffffdffff | |
+fbfffffffffff9fffffffdffff | |
+fbffff27c1e0e03c3ffffdffff | |
+fbffff139cce79f99ffffdffff | |
+fbffff39fccff9f39ffffdffff | |
+fbffff39fcc7f9f39ffffdffff | |
+fbffff39c0e0f9f01ffffdffff | |
+fbffff399cfc79f3fffffdffff | |
+fbffff399cfe79f3fffffdffff | |
+fbffff3398ce79f99ffffdffff | |
+fbffff07c4e0fc3c3ffffdffff | |
+fbffff3ffffffffffffffdffff | |
+fbffff3ffffffffffffffdffff | |
+fbffff3ffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffe1ffffdffff | |
+fbfffffffffffffcfffffdffff | |
+fbfffffffffffffcfffffdffff | |
+fbffff8391e0e3301ffffdffff | |
+fbffff3988ce703cfffffdffff | |
+fbffff3f9cfe733cfffffdffff | |
+fbffff1f9cfe73fcfffffdffff | |
+fbffff839ce073fcfffffdffff | |
+fbfffff19cce73fcfffffdffff | |
+fbfffff99cce73fcfffffdffff | |
+fbffff399ccc73fcfffffdffff | |
+fbffff839ce260f03ffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffff07fffff3ffffffdffff | |
+fbfffffe7fffff3ffffffdffff | |
+fbfffffe7fffff3ffffffdffff | |
+fbfffffe7e1f0f39fffffdffff | |
+fbfffffe7cce673bfffffdffff | |
+fbfffffe79e4f337fffffdffff | |
+fbfffffe79e4f32ffffffdffff | |
+fbfffffe79e4f30ffffffdffff | |
+fbfffffe79e4f327fffffdffff | |
+fbfffffe79e4f333fffffdffff | |
+fbfffffe7cce6739fffffdffff | |
+fbfffff00e1f0f39fffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffbfffffffbfffffdffff | |
+fbfffff3fffffff9fffffdffff | |
+fbffffe72dce673cfffffdffff | |
+fbffffcf00ce673e7ffffdffff | |
+fbffff9f24ce737f3ffffdffff | |
+fbffff1f24ce70ff1ffffdffff | |
+fbffff9f24ce7dff3ffffdffff | |
+fbffffcf24ce787e7ffffdffff | |
+fbffffe724ce767cfffffdffff | |
+fbfffff324c46739fffffdffff | |
+fbfffffb24e2673bfffffdffff | |
+fbfffffffffffffffffffdffff | |
+fbfffffffffffffffffffdffff | |
+f800000000000000000001ffff | |
+f800000000000000000001ffff | |
+f800c04000030000200001ffff | |
+f800c18000030000180001ffff | |
+f8018300000180000c0001ffff | |
+f801830000c180dc0c0c01ffff | |
+f803060000c0c0ee060c01ffff | |
+f803060000c0c0c6060c01ffff | |
+f806060007f860c6067f81ffff | |
+f806060007f860c6067f81ffff | |
+f80c060000c030c6060c01ffff | |
+f80c0601c0c030c6060c01ffff | |
+f8180601c0c018c6060c01ffff | |
+f8180301c00018c60c001e0fff | |
+f830030000000c000c001e3fff | |
+f830018000000c0018001effff | |
+f80000400000000020001e7fff | |
+ffffffffffffffffffffe03fff | |
+ffffffffffffffffffffe41fff | |
+ffffffffffffffffffffe60fff | |
+ffffffffffffffffffffef07ff | |
+ffffffffffffffffffffef83ff | |
+ffffffffffffffffffffffc1ff | |
+ffffffffffffffffffffffe0ff | |
+fffffffffffffffffffffff07f | |
+fffffffffffffffffffffff83f | |
+fffffffffffffffffffffffc1f | |
+fffffffffffffffffffffffe3f | |
+ffffffffffffffffffffffff7f | |
+ffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffff | |
+ffffffffffffffffffffffffff | |
+showpage | |
+%ps_include: inclusion end | |
+grestore | |
+PS-include-dict-dw begin | |
+o 0 ne {gsave A defaultmatrix /A ed llx lly nice urx ury nice | |
+ initgraphics 0.1 setlinewidth boxpath stroke grestore} if | |
+clear o-stack aload pop | |
+context end restore | |
+%ps_include: end | |
+/saveobj save def | |
+mark | |
+8 I f | |
+( bottom entry tracks the most recently used regular expression, which may be … | |
+10 R f | |
+( mouse language is entirely due to the equal-)8 1794(The relationship between… | |
+( example, to make a set of changes)7 1419( For)1 193( button 1 on the mouse.)… | |
+( be set by double clicking on the left brace that begins the subroutine, whic… | |
+( address-free command then typed in the)6 1660( An)1 178(dot for the command … | |
+10 CW f | |
+(sam)3858 3040 w | |
+10 R f | |
+(window will apply only)3 971 1 4069 3040 t | |
+( idea is to select what you want, and)8 1453( The)1 206( text between the ope… | |
+( of)1 108( And)1 222( want to do with it, whether invoked by a menu selection… | |
+( relationship)1 516( This)1 247( command completes.)2 912(course, the value o… | |
+( to explain, but comfortable, even natural, in)7 1859(between mouse interface… | |
+(practice.)720 3640 w | |
+10 B f | |
+(The Implementation)1 875 1 720 3880 t | |
+10 R f | |
+(The next few sections describe how)5 1447 1 720 4036 t | |
+10 CW f | |
+(sam)2196 4036 w | |
+10 R f | |
+( together, first the host part, then the inter-component com-)9 2411(is put)1… | |
+( dis-)1 181( explaining how the command language is implemented, the)8 2462( … | |
+( presen-)1 320( The)1 207(cussion follows \(roughly\) the path of a character… | |
+( because that is how the program was designed and because the algo-)12 2844(t… | |
+(rithms are easy to provide, given the right data structures.)9 2299 1 720 451… | |
+10 B f | |
+(Parsing and execution)2 945 1 720 4756 t | |
+10 R f | |
+( recursive descent)2 754(The command language is interpreted by parsing each … | |
+( editors instead)2 617( Most)1 262( top-down executor.)2 813(parser, and when… | |
+( and unambiguous to)3 875( of a parser makes it easy)6 1080( Use)1 217(employ… | |
+( conventions such as back-)4 1102( escape)1 299( First,)1 268(detect when a c… | |
+( the command isn't finished, the parser keeps)7 1850( if)1 117( multiple-line… | |
+( example, a multiple-line append driven by an)7 1836(reading. For)1 513 2 720… | |
+10 CW f | |
+(x)3094 5512 w | |
+10 R f | |
+(command is straightforward:)2 1154 1 3179 5512 t | |
+9 CW f | |
+(x/.*\\n/ g/Peter/ a)2 972 1 1008 5682 t | |
+(one line about Peter)3 1080 1 1008 5792 t | |
+(another line about Peter)3 1296 1 1008 5902 t | |
+(.)1008 6012 w | |
+10 R f | |
+(Other Unix editors would require a backslash after all but the last line.)12 … | |
+( advantage is specific to the two-process structure of)8 2167(The other)1 393… | |
+10 CW f | |
+(sam)3564 6348 w | |
+10 R f | |
+( host process must decide)4 1057(. The)1 239 2 3744 6348 t | |
+( easily resolved)2 631( problem is)2 462( This)1 234(when a command is comple… | |
+(by having the lexical analyzer read the single stream of events from the term… | |
+(ing and mouse commands, but passing to the parser characters typed to the)12 … | |
+10 CW f | |
+(sam)3823 6708 w | |
+10 R f | |
+( This)1 234(command window.)1 772 2 4034 6708 t | |
+( complicated by the availability of cut-and-paste editing in the)9 2510(schem… | |
+10 CW f | |
+(sam)3979 6828 w | |
+10 R f | |
+(window, but that dif-)3 853 1 4187 6828 t | |
+(ficulty is resolved by applying the rules used in)8 1925 1 720 6948 t | |
+10 CW f | |
+(mux)2674 6948 w | |
+10 R f | |
+(: when a newline is typed to the)7 1296 1 2854 6948 t | |
+10 CW f | |
+(sam)4179 6948 w | |
+10 R f | |
+(window, all text)2 653 1 4387 6948 t | |
+( permits arbi-)2 554( This)1 236( newline is made available to the parser.)7 … | |
+(trary editing to be done to a command before typing newline and thereby reque… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 13 13 | |
+%%Page: 14 14 | |
+/saveobj save def | |
+mark | |
+14 pagesetup | |
+10 R f | |
+(- 14 -)2 216 1 2772 480 t | |
+( and commands is regular enough to be)7 1574(The parser is driven by a table … | |
+( replacement text in a substitution, so the syn-)8 1859( are few special case… | |
+( include whether the command allows)5 1542( These)1 293( can be encoded with … | |
+(an address \(for example,)3 989 1 720 1200 t | |
+10 CW f | |
+(e)1737 1200 w | |
+10 R f | |
+( in)1 105(does not\), whether it takes a regular expression \(as)8 2044 2 182… | |
+10 CW f | |
+(x)4001 1200 w | |
+10 R f | |
+(and)4088 1200 w | |
+10 CW f | |
+(s)4259 1200 w | |
+10 R f | |
+(\), whether it takes)3 721 1 4319 1200 t | |
+(replacement text \(as in)3 915 1 720 1320 t | |
+10 CW f | |
+(c)1663 1320 w | |
+10 R f | |
+(or)1751 1320 w | |
+10 CW f | |
+(i)1862 1320 w | |
+10 R f | |
+( syntax of regular expres-)4 1035( internal)1 333( The)1 208(\), which may be… | |
+( Regular)1 377( parser; a regular expression is a leaf of the command parse t… | |
+(expressions are discussed fully in the next section.)7 2014 1 720 1560 t | |
+( a com-)2 315(The parser table also has information about defaults, so the in… | |
+( example, the parser fills in the implicit)7 1676( For)1 204(plete tree.)1 40… | |
+10 CW f | |
+(0)3048 1836 w | |
+10 R f | |
+(and)3148 1836 w | |
+10 CW f | |
+($)3332 1836 w | |
+10 R f | |
+(in the abbreviated address)3 1084 1 3432 1836 t | |
+10 CW f | |
+(,)4556 1836 w | |
+10 R f | |
+(\(comma\),)4655 1836 w | |
+(inserts a)1 345 1 720 1956 t | |
+10 CW f | |
+(+)1105 1956 w | |
+10 R f | |
+( default)1 318(to the left of an unadorned regular expression in an address, … | |
+(address)720 2076 w | |
+10 CW f | |
+(.)1044 2076 w | |
+10 R f | |
+(\(dot\) for commands that expect an address but are not given one.)11 2589 1 … | |
+( address is evaluated left-to-right)4 1358( The)1 216( complete command is pa… | |
+( the)1 156( like many of)3 560( Addresses,)1 495(starting from the value of d… | |
+(data structures in)2 682 1 720 2472 t | |
+10 CW f | |
+(sam)1427 2472 w | |
+10 R f | |
+(, are held in a C structure and passed around by value:)11 2162 1 1607 2472 t | |
+9 CW f | |
+( Position in a file */)5 1188( /*)1 270( Posn;)1 918(typedef long)1 648 4 100… | |
+(typedef struct Range{)2 1134 1 1008 2752 t | |
+( p2;)1 216(Posn p1,)1 1026 2 1440 2862 t | |
+(}Range;)1008 2972 w | |
+(typedef struct Address{)2 1242 1 1008 3082 t | |
+(Range r;)1 540 1 1440 3192 t | |
+(File *f;)1 1026 1 1440 3302 t | |
+(}Address;)1008 3412 w | |
+10 R f | |
+( encoded as a substring \(character positions)6 1795(An address is)2 556 2 72… | |
+10 CW f | |
+(p1)3106 3592 w | |
+10 R f | |
+(to)3261 3592 w | |
+10 CW f | |
+(p2)3374 3592 w | |
+10 R f | |
+(\) in a file)3 393 1 3494 3592 t | |
+10 CW f | |
+(f)3922 3592 w | |
+10 R f | |
+( data type)2 408(. \(The)1 273 2 3982 3592 t | |
+10 CW f | |
+(File)4698 3592 w | |
+10 R f | |
+(is)4973 3592 w | |
+(described in detail below.\))3 1059 1 720 3712 t | |
+( interpreter is an)3 690(The address)1 491 2 970 3868 t | |
+10 CW f | |
+(Address)2189 3868 w | |
+10 R f | |
+(-valued function that traverses the parse tree describing an)8 2431 1 2609 38… | |
+(address \(the parse tree for the address has type)8 1855 1 720 3988 t | |
+10 CW f | |
+(Addrtree)2600 3988 w | |
+10 R f | |
+(\):)3080 3988 w | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 14 14 | |
+%%Page: 15 15 | |
+/saveobj save def | |
+mark | |
+15 pagesetup | |
+10 R f | |
+(- 15 -)2 216 1 2772 480 t | |
+9 CW f | |
+(Address)1008 830 w | |
+(address\(ap, a, sign\))2 1080 1 1008 940 t | |
+(Addrtree *ap;)1 702 1 1440 1050 t | |
+(Address a;)1 540 1 1440 1160 t | |
+(int sign;)1 486 1 1440 1270 t | |
+({)1008 1380 w | |
+(Address a2;)1 594 1 1440 1490 t | |
+(do)1440 1600 w | |
+(switch\(ap->type\){)1872 1710 w | |
+(case '.':)1 486 1 1872 1820 t | |
+(a=a.f->dot;)2304 1930 w | |
+(break;)2304 2040 w | |
+(case '$':)1 486 1 1872 2150 t | |
+(a.r.p1=a.r.p2=a.f->nbytes;)2304 2260 w | |
+(break;)2304 2370 w | |
+(case '"':)1 486 1 1872 2480 t | |
+(a=matchfile\(a, ap->aregexp\)->dot;)1 1782 1 2304 2590 t | |
+(break;)2304 2700 w | |
+(case ',':)1 486 1 1872 2810 t | |
+(a2=address\(ap->right, a, 0\);)2 1512 1 2304 2920 t | |
+(a=address\(ap->left, a, 0\);)2 1404 1 2304 3030 t | |
+(if\(a.f!=a2.f || a2.r.p2<a.r.p1\))2 1674 1 2304 3140 t | |
+(error\(Eorder\);)2736 3250 w | |
+(a.r.p2=a2.r.p2;)2304 3360 w | |
+(return a;)1 486 1 2304 3470 t | |
+(/* and so on */)4 810 1 1872 3580 t | |
+(})1872 3690 w | |
+(while\(\(ap=ap->right\)!=0\);)1440 3800 w | |
+(return a;)1 486 1 1440 3910 t | |
+(})1008 4020 w | |
+10 R f | |
+( non-local)1 408(Throughout, errors are handled by a)5 1460 2 970 4236 t | |
+10 CW f | |
+(goto)2869 4236 w | |
+10 R f | |
+(\(a)3140 4236 w | |
+10 CW f | |
+(setjmp/longjmp)3248 4236 w | |
+10 R f | |
+(in C terminology\) hid-)3 921 1 4119 4236 t | |
+( routine called)2 587(den in a)2 334 2 720 4356 t | |
+10 CW f | |
+(error)1674 4356 w | |
+10 R f | |
+(that immediately aborts the execution, retracts any partially made changes)9 … | |
+( argument to)2 513( The)1 209( level of the parser.)4 783(\(see the section b… | |
+10 CW f | |
+(error)4644 4476 w | |
+10 R f | |
+(is)4973 4476 w | |
+( possibly helpful message such as `?addresses out of)8 2179(an enumeration ty… | |
+( common messages are kept short; for example the message for a failed regular… | |
+(search is `?search.')2 760 1 720 4836 t | |
+(Character addresses such as)3 1125 1 970 4992 t | |
+10 CW f | |
+(#3)2126 4992 w | |
+10 R f | |
+(are trivial to implement, as the)5 1251 1 2277 4992 t | |
+10 CW f | |
+(File)3559 4992 w | |
+10 R f | |
+(data structure is accessible by)4 1210 1 3830 4992 t | |
+( However,)1 447(character number.)1 726 2 720 5112 t | |
+10 CW f | |
+(sam)1925 5112 w | |
+10 R f | |
+( of newlines \320 it is too expen-)7 1277(keeps no information about the posi… | |
+( Except)1 330( are computed by reading the file, counting newlines.)8 2148(si… | |
+( access is fast enough to make the technique practical, and)10 2325(in very l… | |
+(lines are not central to the structure of the command language.)10 2492 1 720… | |
+(The command interpreter, called)3 1308 1 970 5628 t | |
+10 CW f | |
+(cmdexec)2305 5628 w | |
+10 R f | |
+( parse table includes a func-)5 1131( The)1 208( also straightforward.)2 857(… | |
+( as arguments the calculated address)5 1484( function receives)2 725( That)1 … | |
+( command and the command tree \(of type)7 1729(for the)1 271 2 720 5868 t | |
+10 CW f | |
+(Cmdtree)2754 5868 w | |
+10 R f | |
+(\), which may contain information such as the)7 1866 1 3174 5868 t | |
+( for example, is the function for the)7 1414( Here,)1 268(subtree for compoun… | |
+10 CW f | |
+(g)3786 5988 w | |
+10 R f | |
+(and)3871 5988 w | |
+10 CW f | |
+(v)4040 5988 w | |
+10 R f | |
+(commands:)4125 5988 w | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 15 15 | |
+%%Page: 16 16 | |
+/saveobj save def | |
+mark | |
+16 pagesetup | |
+10 R f | |
+(- 16 -)2 216 1 2772 480 t | |
+9 CW f | |
+(int)1008 830 w | |
+(g_cmd\(a, cp\))1 648 1 1008 940 t | |
+(Address a;)1 540 1 1440 1050 t | |
+(Cmdtree *cp;)1 648 1 1440 1160 t | |
+({)1008 1270 w | |
+(compile\(cp->regexp\);)1440 1380 w | |
+(if\(execute\(a.f, a.r.p1, a.r.p2\) != \(cp->cmdchar=='v'\)\){)4 2970 1 1440 1… | |
+(a.f->dot=a;)1872 1600 w | |
+(return cmdexec\(a, cp->subcmd\);)2 1620 1 1872 1710 t | |
+(})1440 1820 w | |
+( indicate that execution is to continue */)7 2268( /*)1 324(return TRUE;)1 64… | |
+(})1008 2040 w | |
+10 R f | |
+(\()720 2220 w | |
+10 CW f | |
+(Compile)753 2220 w | |
+10 R f | |
+(and)1202 2220 w | |
+10 CW f | |
+(execute)1375 2220 w | |
+10 R f | |
+( Because)1 387(are part of the regular expression code, described in the next… | |
+(the parser and the)3 706 1 720 2340 t | |
+10 CW f | |
+(File)1451 2340 w | |
+10 R f | |
+(data structure do most of the work, most commands are similarly brief.)11 283… | |
+10 B f | |
+(Regular expressions)1 858 1 720 2580 t | |
+10 R f | |
+(The regular expression code in)4 1266 1 720 2736 t | |
+10 CW f | |
+(sam)2020 2736 w | |
+10 R f | |
+( than compiled on-the-fly, implementation of)5 1854(is an interpreted, rather… | |
+(Thompson's non-deterministic finite automaton algorithm.)4 2392 1 720 2856 t | |
+6 R f | |
+(12)3112 2806 w | |
+10 R f | |
+( the expressions)2 656(The syntax and semantics of)4 1177 2 3207 2856 t | |
+(are as in the Unix program)5 1092 1 720 2976 t | |
+10 CW f | |
+(egrep)1842 2976 w | |
+10 R f | |
+( only)1 209( The)1 211( alternation, closures, character classes, and so on.)… | |
+(changes in the notation are two additions:)6 1755 1 720 3096 t | |
+10 CW f | |
+(\\n)2515 3096 w | |
+10 R f | |
+( and)1 183(is translated to, and matches, a newline character,)7 2083 2 2675 … | |
+10 CW f | |
+(@)4980 3096 w | |
+10 R f | |
+( In)1 140(matches any character.)2 924 2 720 3216 t | |
+10 CW f | |
+(egrep)1816 3216 w | |
+10 R f | |
+(, the character)2 575 1 2116 3216 t | |
+10 CW f | |
+(.)2723 3216 w | |
+10 R f | |
+(matches any character except newline, and in)6 1856 1 2816 3216 t | |
+10 CW f | |
+(sam)4705 3216 w | |
+10 R f | |
+(the)4918 3216 w | |
+(same rule seemed safest, to prevent idioms like)7 2033 1 720 3336 t | |
+10 CW f | |
+(.*)2799 3336 w | |
+10 R f | |
+(from spanning newlines.)2 1027 1 2965 3336 t | |
+10 CW f | |
+(Egrep)4063 3336 w | |
+10 R f | |
+(expressions are)1 632 1 4408 3336 t | |
+( certainly it would make sense if all the special charac-)10 2209(arguably to… | |
+( wouldn't have peculiar mean-)4 1223(ters were two-character sequences, so th… | |
+( regular expressions are necessary, and)5 1660(ings \320 but for an interesti… | |
+10 CW f | |
+(egrep)4740 3696 w | |
+10 R f | |
+( it seemed superfluous to define a new)7 1568( Also,)1 269( Unix programs.)2 … | |
+(syntax, since various Unix programs \()5 1520 1 720 3936 t | |
+10 CW f | |
+(ed)2240 3936 w | |
+10 R f | |
+(,)2360 3936 w | |
+10 CW f | |
+(egrep)2410 3936 w | |
+10 R f | |
+(and)2735 3936 w | |
+10 CW f | |
+(vi)2904 3936 w | |
+10 R f | |
+(\) define too many already.)4 1050 1 3024 3936 t | |
+(The expressions are compiled by a routine,)6 1812 1 970 4092 t | |
+10 CW f | |
+(compile)2823 4092 w | |
+10 R f | |
+( the description of the non-)5 1164(, that generates)2 633 2 3243 4092 t | |
+( second routine,)2 669( A)1 139(deterministic finite state machine.)3 1405 3 … | |
+10 CW f | |
+(execute)2975 4212 w | |
+10 R f | |
+(, interprets the machine to generate the)6 1645 1 3395 4212 t | |
+( else-)1 238( algorithm is described)3 985( The)1 229(leftmost-longest match … | |
+(where.)720 4452 w | |
+6 R f | |
+(12,13)988 4402 w | |
+10 CW f | |
+(Execute)1152 4452 w | |
+10 R f | |
+( sets a global variable, of type)6 1213(reports whether a match was found, an… | |
+10 CW f | |
+(Range)4459 4452 w | |
+10 R f | |
+(, to the)2 281 1 4759 4452 t | |
+(substring matched.)1 755 1 720 4572 t | |
+( such as when searching backwards for an)7 1752(A trick is required to evalua… | |
+( example,)1 388(expression. For)1 641 2 720 4848 t | |
+9 CW f | |
+(-/P.*r/)1008 5018 w | |
+10 R f | |
+( expression, however, is defined for a)6 1532( The)1 211( file for a match of… | |
+( solution is to construct a machine identical to the machine for a forward se… | |
+( the concatenation operators \(the other operators are symmetric under direct… | |
+(to exchange the meaning of the operators)6 1652 1 720 5558 t | |
+10 CW f | |
+(\303)2398 5558 w | |
+10 R f | |
+(and)2484 5558 w | |
+10 CW f | |
+($)2654 5558 w | |
+10 R f | |
+(, and then to read the file backwards, looking for the usual)11 2326 1 2714 5… | |
+(earliest longest match.)2 896 1 720 5678 t | |
+10 CW f | |
+(Execute)970 5834 w | |
+10 R f | |
+( as)1 118( interpret looping constructs such)4 1368( To)1 170(generates only … | |
+(the)720 5954 w | |
+10 CW f | |
+(x)874 5954 w | |
+10 R f | |
+(command,)966 5954 w | |
+10 CW f | |
+(sam)1417 5954 w | |
+10 R f | |
+(must therefore synchronize between calls of)5 1794 1 1629 5954 t | |
+10 CW f | |
+(execute)3455 5954 w | |
+10 R f | |
+( null)1 187(to avoid problems with)3 946 2 3907 5954 t | |
+( example, even given the leftmost-longest rule, the expression)8 2522(matches… | |
+10 CW f | |
+(a*)3820 6074 w | |
+10 R f | |
+( in the)2 264(matches three times)2 805 2 3971 6074 t | |
+(string)720 6194 w | |
+10 CW f | |
+(ab)978 6194 w | |
+10 R f | |
+(\(the character)1 549 1 1128 6194 t | |
+10 CW f | |
+(a)1706 6194 w | |
+10 R f | |
+(, the null string between the)5 1130 1 1766 6194 t | |
+10 CW f | |
+(a)2925 6194 w | |
+10 R f | |
+(and)3014 6194 w | |
+10 CW f | |
+(b)3187 6194 w | |
+10 R f | |
+( returning a)2 468( After)1 264(, and the final null string\).)5 1061 3 3247 … | |
+(match for the)2 532 1 720 6314 t | |
+10 CW f | |
+(a)1277 6314 w | |
+10 R f | |
+(,)1337 6314 w | |
+10 CW f | |
+(sam)1387 6314 w | |
+10 R f | |
+(must not match the null string before the)7 1624 1 1592 6314 t | |
+10 CW f | |
+(b)3241 6314 w | |
+10 R f | |
+( algorithm starts)2 650(. The)1 230 2 3301 6314 t | |
+10 CW f | |
+(execute)4206 6314 w | |
+10 R f | |
+( end)1 170(at the)1 219 2 4651 6314 t | |
+( match, and if the match it returns is null and abuts the previous match, rej… | |
+(advances the initial position one character.)5 1702 1 720 6554 t | |
+10 B f | |
+(Memory allocation)1 807 1 720 6794 t | |
+10 R f | |
+(The C language has no memory allocation primitives, although a standard libra… | |
+10 CW f | |
+(malloc)4454 6950 w | |
+10 R f | |
+(, pro-)1 226 1 4814 6950 t | |
+( however, it can be better to write a custom)9 1769( specific uses,)2 569( Fo… | |
+( rather, pair of allocators\) described here work in both the terminal and ho… | |
+(parts of)1 325 1 720 7310 t | |
+10 CW f | |
+(sam)1093 7310 w | |
+10 R f | |
+( are designed for efficient manipulation of strings, which are allocated and … | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 16 16 | |
+%%Page: 17 17 | |
+/saveobj save def | |
+mark | |
+17 pagesetup | |
+10 R f | |
+(- 17 -)2 216 1 2772 480 t | |
+( \(very large strings are written to disc\).)7 1643(frequently and vary in le… | |
+(More important, strings may be large and change size often, so to minimize me… | |
+(reclaim and to coalesce the unused portions of strings when they are truncate… | |
+(Objects to be allocated in)4 1023 1 970 1236 t | |
+10 CW f | |
+(sam)2020 1236 w | |
+10 R f | |
+( the first is C)4 529(are of two flavors:)3 740 2 2227 1236 t | |
+10 CW f | |
+(structs)3524 1236 w | |
+10 R f | |
+(, which are small and often)5 1096 1 3944 1236 t | |
+( integers whose base)3 868(addressed by pointer variables; the second is vari… | |
+( memory allocator in)3 841( The)1 207( used to access them.)4 848(pointer is … | |
+10 CW f | |
+(sam)3322 1476 w | |
+10 R f | |
+(is therefore in two parts: first, a tradi-)7 1511 1 3529 1476 t | |
+(tional first-fit allocator that provides fixed storage for)7 2145 1 720 1596 t | |
+10 CW f | |
+(structs)2891 1596 w | |
+10 R f | |
+( second, a garbage-compacting alloca-)4 1531(; and)1 198 2 3311 1596 t | |
+( two)1 190( The)1 220( reduces storage overhead for variable-sized objects, a… | |
+( allocator controlling the)3 997(types of objects are allocated from adjoinin… | |
+( prevents fragmentation)2 958( into two arenas simplifies compaction and)6 17… | |
+( garbage-compactable objects \(discussed in the next para-)7 2358( access rul… | |
+( so when the first-fit arena needs space, it moves the garbage-compacted)11 2… | |
+( is therefore created only at successively higher addresses,)8 2340( Storage)… | |
+(either when more garbage-compacted space is needed or when the first-fit aren… | |
+( the sole reposi-)3 647(Objects that may be compacted declare to the allocato… | |
+( then update the)3 668( compactor can)2 633( The)1 217(tory of the address of… | |
+( type)1 199( example, the implementation of)4 1300( For)1 190(address when th… | |
+10 CW f | |
+(List)3811 2832 w | |
+10 R f | |
+(\(really a variable-length)2 962 1 4078 2832 t | |
+(array\) is:)1 357 1 720 2952 t | |
+9 CW f | |
+(typedef struct List{)2 1080 1 1008 3122 t | |
+(int nused;)1 1188 1 1440 3232 t | |
+(long *ptr;)1 1134 1 1440 3342 t | |
+(}List;)1008 3452 w | |
+10 R f | |
+(The)720 3632 w | |
+10 CW f | |
+(ptr)910 3632 w | |
+10 R f | |
+( a)1 79( When)1 298(cell must always be used directly, and never copied.)8 21… | |
+10 CW f | |
+(List)3696 3632 w | |
+10 R f | |
+(is to be created the)4 792 1 3972 3632 t | |
+10 CW f | |
+(List)4800 3632 w | |
+10 R f | |
+(structure is allocated in the ordinary first-fit arena and its)9 2303 1 720 3… | |
+10 CW f | |
+(ptr)3051 3752 w | |
+10 R f | |
+(is allocated in the garbage-compacted arena.)5 1782 1 3258 3752 t | |
+(A similar data type for strings, called)6 1520 1 720 3872 t | |
+10 CW f | |
+(String)2271 3872 w | |
+10 R f | |
+( ele-)1 181(, stores variable-length character arrays of up to 32767)8 2228 2… | |
+(ments.)720 3992 w | |
+( matter of programming style:)4 1227(A related)1 374 2 970 4148 t | |
+10 CW f | |
+(sam)2603 4148 w | |
+10 R f | |
+(frequently passes structures by value, which simplifies)6 2225 1 2815 4148 t | |
+( programs have passed structures by reference, but implicit allocation on the… | |
+( passing is a relatively new feature of C \(it is not in the standard referen… | |
+(manual for C)2 537 1 720 4508 t | |
+6 R f | |
+(14)1257 4458 w | |
+10 R f | |
+( convenient and expressive,)3 1115( It's)1 187( commercial C compilers.)3 104… | |
+(though, and simplifies memory management by avoiding the allocator altogether… | |
+(aliases.)720 4748 w | |
+10 B f | |
+(Data structures for manipulating files)4 1610 1 720 4988 t | |
+10 R f | |
+(Experience with)1 651 1 720 5144 t | |
+10 CW f | |
+(jim)1396 5144 w | |
+10 R f | |
+( files)1 198( First,)1 260( requirements of the file data structure were few,… | |
+( the implementation must)3 1026( Second,)1 371( read and written quickly; add… | |
+( should be practical to edit many files, and)8 1719( \(It)1 147( sizes of fil… | |
+( implies that files be stored on disc, not)8 1593( This)1 231(files up to meg… | |
+( of virtual memory may argue otherwise, but the implementation of virtual)11 … | |
+( changes to files need)4 879( Third,)1 302( system is not something to depend… | |
+( are inverses of each other, which simplifies)7 1785( These)1 292( only two p… | |
+( the file, either)3 609( it must be easy and efficient to access)8 1610( Fina… | |
+(forwards or backwards, a byte at a time.)7 1598 1 720 6104 t | |
+(The)970 6260 w | |
+10 CW f | |
+(File)1157 6260 w | |
+10 R f | |
+( characters.)1 461(data type is constructed from three simpler data structure… | |
+( has an insertion and deletion operator, and the insertion and deletion opera… | |
+10 CW f | |
+(File)720 6500 w | |
+10 R f | |
+(type itself are constructed from them.)5 1497 1 985 6500 t | |
+(The simplest type is the)4 950 1 970 6656 t | |
+10 CW f | |
+(String)1945 6656 w | |
+10 R f | |
+( code that man-)3 621( The)1 206( hold strings in main memory.)5 1211(, which… | |
+(ages)720 6776 w | |
+10 CW f | |
+(Strings)926 6776 w | |
+10 R f | |
+( some moderate size, and in practice they are)8 1816(guarantees that they wil… | |
+(rarely larger than 8 Kbytes.)4 1098 1 720 6896 t | |
+10 CW f | |
+(Strings)1869 6896 w | |
+10 R f | |
+( little)1 211(have two purposes: they hold short strings like file names with… | |
+( are therefore used as)4 862( They)1 259( efficient to modify.)3 811(overhead… | |
+(the data structure for in-memory caches.)5 1612 1 720 7136 t | |
+(The disc copy of the file is managed by a data structure called a)13 2749 1 9… | |
+10 CW f | |
+(Disc)3760 7292 w | |
+10 R f | |
+( corresponds to a)3 730(, which)1 310 2 4000 7292 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 17 17 | |
+%%Page: 18 18 | |
+/saveobj save def | |
+mark | |
+18 pagesetup | |
+10 R f | |
+(- 18 -)2 216 1 2772 480 t | |
+( A)1 133(temporary file.)1 604 2 720 840 t | |
+10 CW f | |
+(Disc)1493 840 w | |
+10 R f | |
+( storage in main memory other than bookkeeping information; the actual)10 300… | |
+( reduce the number of open files needed,)7 1665( To)1 167(data being held is … | |
+10 CW f | |
+(sam)3935 960 w | |
+10 R f | |
+(opens a dozen tempo-)3 894 1 4146 960 t | |
+(rary Unix files and multiplexes the)5 1395 1 720 1080 t | |
+10 CW f | |
+(Discs)2141 1080 w | |
+10 R f | |
+( many files to be edited; the entire)7 1362( permits)1 326( This)1 229(upon t… | |
+10 CW f | |
+(sam)4860 1080 w | |
+10 R f | |
+(source \(48 files\) may be edited comfortably with a single instance of)11 28… | |
+10 CW f | |
+(sam)3571 1200 w | |
+10 R f | |
+( temporary file)2 609( one)1 176(. Allocating)1 504 3 3751 1200 t | |
+(per)720 1320 w | |
+10 CW f | |
+(Disc)874 1320 w | |
+10 R f | |
+( spreading the traffic)3 831( Also,)1 265( on the number of open files.)6 115… | |
+(among temporary files keeps the files shorter, and shorter files are more eff… | |
+(Unix I/O subsystem.)2 825 1 720 1560 t | |
+(A)970 1716 w | |
+10 CW f | |
+(Disc)1070 1716 w | |
+10 R f | |
+( between 1 and 4096 characters of)6 1386(is an array of fixed-length blocks, … | |
+( block addresses within the tempo-)5 1400( The)1 207( file system is 4096 byt… | |
+( stored in a)3 450(rary file and the length of each block are)8 1633 2 720 19… | |
+10 CW f | |
+(List)2831 1956 w | |
+10 R f | |
+( changes are made the live part of blocks)8 1653(. When)1 316 2 3071 1956 t | |
+( to keep the sizes between 2048)6 1300( are created and coalesced when necess… | |
+( actively changing part of the)5 1172( An)1 173(and 4096 bytes.)2 632 3 720 2… | |
+10 CW f | |
+(Disc)2723 2196 w | |
+10 R f | |
+( has about a kilobyte of slop that)7 1316(therefore typically)1 735 2 2989 21… | |
+( an)1 130( When)1 299( inserted or deleted without changing more than one blo… | |
+( one is allocated to receive the overflow, and the)9 1970(insertion would ove… | |
+(memory-resident list of blocks is rearranged to reflect the insertion of the … | |
+( data)1 200( The)1 214( modification to the file is prohibitively expensive.)… | |
+(type)720 2832 w | |
+10 CW f | |
+(Buffer)921 2832 w | |
+10 R f | |
+(consists of a)2 502 1 1310 2832 t | |
+10 CW f | |
+(Disc)1841 2832 w | |
+10 R f | |
+(to hold the data and a)5 872 1 2109 2832 t | |
+10 CW f | |
+(String)3009 2832 w | |
+10 R f | |
+( is the first of a)5 617( This)1 231(that acts as a cache.)4 795 3 3397 2832 t | |
+( throughout the data structures in)5 1378(series of caches)2 647 2 720 2952 t | |
+10 CW f | |
+(sam.)2782 2952 w | |
+10 R f | |
+(The caches not only improve performance, they)6 1981 1 3059 2952 t | |
+( the flow of data, particularly in the communication between the host and ter… | |
+( idea is developed below, in the section on communications.)9 2406(nal. This)… | |
+( traffic, changes to a)4 855(To reduce disc)2 607 2 970 3348 t | |
+10 CW f | |
+(Buffer)2468 3348 w | |
+10 R f | |
+(are mediated by a variable-length string, in memory,)7 2176 1 2864 3348 t | |
+( an insertion or deletion is made to a)8 1502( When)1 294(that acts as a cach… | |
+10 CW f | |
+(Buffer)3354 3468 w | |
+10 R f | |
+( can be accommo-)3 743(, if the change)3 583 2 3714 3468 t | |
+( cache becomes bigger than a block because of an insertion, some)11 2643( the… | |
+( written to the)3 558(of it is)2 258 2 720 3708 t | |
+10 CW f | |
+(Disc)1561 3708 w | |
+10 R f | |
+( the change does not intersect the cache, the cache)9 1999( If)1 116(and dele… | |
+( the new position if the change is smaller than a block; otherwise, it)13 274… | |
+( the)1 158(is sent directly to)3 722 2 720 3948 t | |
+10 CW f | |
+(Disc)1636 3948 w | |
+10 R f | |
+( is because large changes are typically sequential, whereupon the next)10 290… | |
+(change is unlikely to overlap the current one.)7 1802 1 720 4068 t | |
+(A)970 4224 w | |
+10 CW f | |
+(File)1067 4224 w | |
+10 R f | |
+(comprises a)1 474 1 1332 4224 t | |
+10 CW f | |
+(String)1831 4224 w | |
+10 R f | |
+( such as dot and the mod-)6 1027(to hold the file name and some ancillary dat… | |
+( most important components, though, are a pair of)8 2006( The)1 206(ified bit… | |
+10 CW f | |
+(Buffers)3298 4344 w | |
+10 R f | |
+(, one called the transcript and the)6 1322 1 3718 4344 t | |
+( use is described in the next section.)7 1437( Their)1 266(other the contents… | |
+( times)1 243( it may seem that the data is touched many)9 1701( Although)1 42… | |
+(on its way from the)4 825 1 720 4740 t | |
+10 CW f | |
+(Disc)1582 4740 w | |
+10 R f | |
+( \(by one Unix system call\) directly into the cache of the associated)12 278… | |
+10 CW f | |
+(Buffer)720 4860 w | |
+10 R f | |
+( the cache, the text is written directly from the)9 1922( when flushing)2 610… | |
+( principle applied throughout)3 1172( A)1 125( operations act directly on the… | |
+10 CW f | |
+(sam)4765 4980 w | |
+10 R f | |
+(is)4973 4980 w | |
+(that the fewer times the data is copied, the faster the program will run \(se… | |
+6 R f | |
+(15)4650 5050 w | |
+10 R f | |
+(\).)4710 5100 w | |
+cleartomark | |
+saveobj restore | |
+%%BeginGlobal | |
+% | |
+% Version 3.3.2 drawing procedures for dpost. Automatically pulled in when | |
+% needed. | |
+% | |
+ | |
+/inpath false def | |
+/savematrix matrix def | |
+ | |
+/Dl { | |
+ inpath | |
+ {pop pop neg lineto} | |
+ {newpath neg moveto neg lineto stroke} | |
+ ifelse | |
+} bind def | |
+ | |
+/De { | |
+ /y1 exch 2 div def | |
+ /x1 exch 2 div def | |
+ /savematrix savematrix currentmatrix def | |
+ neg exch x1 add exch translate | |
+ x1 y1 scale | |
+ 0 0 1 0 360 | |
+ inpath | |
+ {1 0 moveto arc savematrix setmatrix} | |
+ {newpath arc savematrix setmatrix stroke} | |
+ ifelse | |
+} bind def | |
+ | |
+/Da { | |
+ /dy2 exch def | |
+ /dx2 exch def | |
+ /dy1 exch def | |
+ /dx1 exch def | |
+ dy1 add neg exch dx1 add exch | |
+ dx1 dx1 mul dy1 dy1 mul add sqrt | |
+ dy1 dx1 neg atan | |
+ dy2 neg dx2 atan | |
+ inpath | |
+ {arc} | |
+ {newpath arc stroke} | |
+ ifelse | |
+} bind def | |
+ | |
+/DA { | |
+ /dy2 exch def | |
+ /dx2 exch def | |
+ /dy1 exch def | |
+ /dx1 exch def | |
+ dy1 add neg exch dx1 add exch | |
+ dx1 dx1 mul dy1 dy1 mul add sqrt | |
+ dy1 dx1 neg atan | |
+ dy2 neg dx2 atan | |
+ inpath | |
+ {arcn} | |
+ {newpath arcn stroke} | |
+ ifelse | |
+} bind def | |
+ | |
+/Ds { | |
+ /y2 exch def | |
+ /x2 exch def | |
+ /y1 exch def | |
+ /x1 exch def | |
+ /y0 exch def | |
+ /x0 exch def | |
+ x0 5 x1 mul add 6 div | |
+ y0 5 y1 mul add -6 div | |
+ x2 5 x1 mul add 6 div | |
+ y2 5 y1 mul add -6 div | |
+ x1 x2 add 2 div | |
+ y1 y2 add -2 div | |
+ inpath | |
+ {curveto} | |
+ {newpath x0 x1 add 2 div y0 y1 add -2 div moveto curveto strok… | |
+ ifelse | |
+} bind def | |
+%%EndGlobal | |
+/saveobj save def | |
+mark | |
+10 R f | |
+2966 6183 2966 6471 Dl | |
+3599 6183 2966 6183 Dl | |
+3600 6471 3600 6183 Dl | |
+2967 6471 3600 6471 Dl | |
+10 CW f | |
+(Disc)3163 6347 w | |
+2966 6586 2966 6874 Dl | |
+3599 6586 2966 6586 Dl | |
+3600 6874 3600 6586 Dl | |
+2967 6874 3600 6874 Dl | |
+10 R f | |
+(temp. file)1 383 1 3092 6750 t | |
+3283 6471 3283 6586 Dl | |
+1642 6183 1642 6471 Dl | |
+2275 6183 1642 6183 Dl | |
+2275 6471 2275 6183 Dl | |
+1642 6471 2275 6471 Dl | |
+10 CW f | |
+(Disc)1838 6347 w | |
+1642 6586 1642 6874 Dl | |
+2275 6586 1642 6586 Dl | |
+2275 6874 2275 6586 Dl | |
+1642 6874 2275 6874 Dl | |
+10 R f | |
+(temp. file)1 383 1 1767 6750 t | |
+1958 6471 1958 6586 Dl | |
+1642 5722 1642 6010 Dl | |
+2275 5722 1642 5722 Dl | |
+2275 6010 2275 5722 Dl | |
+1642 6010 2275 6010 Dl | |
+10 CW f | |
+(Buffer)1778 5826 w | |
+10 R f | |
+(\(transcript\))1737 5946 w | |
+2390 5722 2390 6010 Dl | |
+2793 5722 2390 5722 Dl | |
+2794 6010 2794 5722 Dl | |
+2391 6010 2794 6010 Dl | |
+10 CW f | |
+(String)2412 5826 w | |
+10 R f | |
+(\(cache\))2446 5946 w | |
+2275 5866 2390 5866 Dl | |
+2966 5722 2966 6010 Dl | |
+3599 5722 2966 5722 Dl | |
+3600 6010 3600 5722 Dl | |
+2967 6010 3600 6010 Dl | |
+10 CW f | |
+(Buffer)3103 5826 w | |
+10 R f | |
+(\(contents\))3084 5946 w | |
+3715 5722 3715 6010 Dl | |
+4118 5722 3715 5722 Dl | |
+4118 6010 4118 5722 Dl | |
+3715 6010 4118 6010 Dl | |
+10 CW f | |
+(String)3737 5826 w | |
+10 R f | |
+(\(cache\))3771 5946 w | |
+3600 5866 3715 5866 Dl | |
+2182 5262 2182 5550 Dl | |
+2988 5262 2182 5262 Dl | |
+2988 5550 2988 5262 Dl | |
+2182 5550 2988 5550 Dl | |
+10 CW f | |
+(File)2465 5426 w | |
+1958 6011 1958 6183 Dl | |
+3283 6011 3283 6183 Dl | |
+1958 5636 1958 5722 Dl | |
+2318 5636 1958 5636 Dl | |
+2318 5550 2318 5636 Dl | |
+3283 5636 3283 5722 Dl | |
+2851 5636 3283 5636 Dl | |
+2851 5550 2851 5636 Dl | |
+8 I f | |
+( temporary files are stored in the standard repository for such files on the … | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 18 18 | |
+%%Page: 19 19 | |
+/saveobj save def | |
+mark | |
+19 pagesetup | |
+10 R f | |
+(- 19 -)2 216 1 2772 480 t | |
+( a)1 73(The contents of)2 627 2 970 840 t | |
+10 CW f | |
+(File)1699 840 w | |
+10 R f | |
+(are accessed by a routine that copies to a buffer a substring of a file start… | |
+( read a byte at a time, a per-)8 1166( To)1 168(at a specified offset.)3 824 … | |
+10 CW f | |
+(File)2878 960 w | |
+10 R f | |
+( a specified initial)3 731(array is loaded starting from)4 1159 2 3150 960 t | |
+( implementation is done by a macro similar to the)9 2012( The)1 208(position,… | |
+(C standard I/O)2 616 1 720 1200 t | |
+10 CW f | |
+(getc)1375 1200 w | |
+10 R f | |
+(macro.)1654 1200 w | |
+6 R f | |
+(14)1928 1150 w | |
+10 R f | |
+( reading may be done at any address, a minor change to the)12 2520(Because th… | |
+( array is read-only; there is no)6 1197( This)1 228(macro allows the file to … | |
+10 CW f | |
+(putc)3904 1320 w | |
+10 R f | |
+(.)4144 1320 w | |
+10 B f | |
+(Doing and undoing)2 820 1 720 1560 t | |
+10 CW f | |
+(Sam)720 1716 w | |
+10 R f | |
+( command language makes it easy to spec-)7 1733( The)1 209( to files.)2 333(h… | |
+( variable-length changes to a file millions of bytes long, and such changes m… | |
+( usual techniques for inserting and deleting strings are inadequate)9 2633( T… | |
+( The)1 207(under these conditions.)2 930 2 720 2076 t | |
+10 CW f | |
+(Buffer)1884 2076 w | |
+10 R f | |
+(and)2271 2076 w | |
+10 CW f | |
+(Disc)2442 2076 w | |
+10 R f | |
+(data structures are designed for efficient random access to)8 2331 1 2709 207… | |
+( be taken to avoid super-linear behavior when making many changes simultane-)… | |
+(ously.)720 2316 w | |
+10 CW f | |
+(Sam)970 2472 w | |
+10 R f | |
+(uses a two-pass algorithm for making changes, and treats each file as a datab… | |
+( when a command is)4 865( Instead,)1 374( the contents.)2 552( are not made d… | |
+(started, a `mark' containing a sequence number is placed in the transcript)11… | |
+10 CW f | |
+(Buffer)3714 2712 w | |
+10 R f | |
+( made)1 246(, and each change)3 720 2 4074 2712 t | |
+( name, is appended to the end of the tran-)9 1715(to the file, either an inse… | |
+( the command is complete, the transcript is rewound to the mark and applied t… | |
+( is to simplify tracking the)5 1198(One reason for separating evaluation from… | |
+( two-pass algorithm also allows all)5 1481( The)1 224(addresses of changes ma… | |
+(changes to apply to the)4 965 1 720 3348 t | |
+10 I f | |
+(original)1721 3348 w | |
+10 R f | |
+( the same command.)3 857(data: no change can affect another change made in)8 … | |
+( evaluating an)2 606(This is particularly important when)4 1506 2 720 3468 t | |
+10 CW f | |
+(x)2880 3468 w | |
+10 R f | |
+(command because it prevents regular expression)5 2052 1 2988 3468 t | |
+( is)1 114( the two-pass algorithm)3 1004( Also,)1 285(matches from stumbling … | |
+( to affect each other; for example,)6 1366(cleaner than the way other Unix ed… | |
+10 CW f | |
+(ed)4313 3708 w | |
+10 R f | |
+('s idioms to do)3 607 1 4433 3708 t | |
+( Instead,)1 364( on the implementation.)3 953(things like delete every other … | |
+10 CW f | |
+(sam)4090 3828 w | |
+10 R f | |
+('s simple model, in)3 770 1 4270 3828 t | |
+(which all changes in a command occur effectively simultaneously, is easy to e… | |
+( substring from locations 123 to 456'' and)7 1825(The records in the transcri… | |
+( changes are not at monotonically)5 1370( is an error if the)5 692( \(It)1 15… | |
+( the update is occurring, these numbers must be offset by earlier)11 2633( Wh… | |
+( to the update routine; moreover, all the numbers have been)10 2466(changes, … | |
+(computed before the first is examined.)5 1536 1 720 4584 t | |
+( it takes is to)4 566( All)1 193(Treating the file as a transaction system ha… | |
+( deletions and vice versa, and)5 1200(invert the transcript after it has been… | |
+(saving them in a holding)4 989 1 720 4980 t | |
+10 CW f | |
+(Buffer)1734 4980 w | |
+10 R f | |
+( can then be deleted from the transcript)7 1567( `do' transcript)2 593(. The)… | |
+10 CW f | |
+(Buffer)4510 4980 w | |
+10 R f | |
+(and)4896 4980 w | |
+( an undo is requested, the transcript is rewound and the undo transcript)12 2… | |
+( the transcript)2 561(executed. Because)1 767 2 720 5220 t | |
+10 CW f | |
+(Buffer)2079 5220 w | |
+10 R f | |
+( it accumulates successive)3 1066(is not truncated after each command,)5 1504… | |
+( can therefore back up the file arbitrarily, which is more helpful)11 2626( s… | |
+( \()1 87( form of undo.)3 589(than the more commonly implemented self-inverse… | |
+10 CW f | |
+(Sam)3450 5460 w | |
+10 R f | |
+(provides no way to undo an undo,)6 1381 1 3659 5460 t | |
+( mark in the)3 495( Each)1 254( re-interpreting the `do' transcript.\))4 1419… | |
+( offset into the transcript of the previous mark, to aid in)11 2390(transcrip… | |
+( also contain the value of dot and the modified bit so these can be restored)… | |
+( merely demands undoing all files whose latest change has the)10 2625( multip… | |
+(same sequence number as the current file.)6 1670 1 720 6060 t | |
+( encountered in the middle of a complicated com-)8 2017(Another benefit of ha… | |
+( rewinding the transcript to the mark beginning)7 1933( By)1 174( files in an… | |
+(the command, the partial command can be trivially undone.)8 2380 1 720 6456 t | |
+( implemented, it was unacceptably slow, so a cache was added to)11 2614(When … | |
+( reduced the number)3 820( This)1 229( small changes by a single larger one.)… | |
+(of insertions into the transaction)4 1308 1 720 6852 t | |
+10 CW f | |
+(Buffer)2058 6852 w | |
+10 R f | |
+( in performance, but made it)5 1161(, and made a dramatic improvement)5 1461 … | |
+( the caching method only works if changes)7 1718(impossible to handle changes… | |
+( cache was added, the transaction could in principle be sorted if the changes… | |
+( therefore acceptable performance with a)5 1664( current status is)3 676( The… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 19 19 | |
+%%Page: 20 20 | |
+/saveobj save def | |
+mark | |
+20 pagesetup | |
+10 R f | |
+(- 20 -)2 216 1 2772 480 t | |
+(minor restriction on global changes, which is sometimes, but rarely, an annoy… | |
+( simpler algorithms, but it is not pro-)7 1627(The update algorithm obviously… | |
+( principle of avoiding copying the data is still honored here,)10 2519( \(The… | |
+( through)1 343(although not as piously: the data is moved from contents' cach… | |
+( dead start a hundred)4 839( read from a)3 493( To)1 164( figures confirm the… | |
+( a VAX-11/750 takes 1.4 seconds of user time, 2.5 seconds of system time, and… | |
+( the same file in)4 670( Reading)1 391(real time.)1 385 3 720 1596 t | |
+10 CW f | |
+(ed)2199 1596 w | |
+10 R f | |
+( of system time, and 8)5 918(takes 6.0 seconds of user time, 1.7 seconds)7 17… | |
+(seconds of real time.)3 862 1 720 1716 t | |
+10 CW f | |
+(Sam)1644 1716 w | |
+10 R f | |
+( stated)1 271( more interesting example is the one)6 1520( A)1 134(uses about… | |
+( The)1 205(above: inserting a character between every pair of characters in t… | |
+10 CW f | |
+(sam)3801 1836 w | |
+10 R f | |
+(command is)1 486 1 4006 1836 t | |
+9 CW f | |
+(,y/@/ a/x/)1 540 1 1008 2006 t | |
+10 R f | |
+( 3 CPU seconds per kilobyte of input file, of which about a third is spent in… | |
+( translates to about 500 changes per second.)7 1759(code. This)1 442 2 720 23… | |
+10 CW f | |
+(Ed)2972 2306 w | |
+10 R f | |
+( make a similar)3 613(takes 1.5 seconds per kilobyte to)5 1309 2 3118 2306 t | |
+( same example in)3 702( The)1 207(change \(ignoring newlines\), but cannot un… | |
+10 CW f | |
+(ex)3554 2426 w | |
+10 R f | |
+(,)3674 2426 w | |
+6 R f | |
+(9)3699 2376 w | |
+10 R f | |
+(a variant of)2 458 1 3756 2426 t | |
+10 CW f | |
+(ed)4241 2426 w | |
+10 R f | |
+(done at the Uni-)3 652 1 4388 2426 t | |
+( summary,)1 428( In)1 139( takes 3 seconds.)3 689(versity of California at Be… | |
+10 CW f | |
+(sam)720 2666 w | |
+10 R f | |
+('s performance is comparable to that of other Unix editors, although it solve… | |
+10 B f | |
+(Communications)720 2906 w | |
+10 R f | |
+(The discussion so far has described the implementation of the host part of)12… | |
+10 CW f | |
+(sam)3899 3062 w | |
+10 R f | |
+(; the next few sections)4 961 1 4079 3062 t | |
+( machine with mouse and bitmap display can be engaged to improve interaction.… | |
+10 CW f | |
+(Sam)4607 3182 w | |
+10 R f | |
+(is not)1 224 1 4816 3182 t | |
+(the first editor to be written as two processes,)8 1811 1 720 3302 t | |
+6 R f | |
+(16)2531 3252 w | |
+10 R f | |
+(but its implementation has some unusual aspects.)6 1969 1 2616 3302 t | |
+(There are several ways)3 924 1 970 3458 t | |
+10 CW f | |
+(sam)1922 3458 w | |
+10 R f | |
+( first and simplest is to)5 929( The)1 208('s host and terminal parts may be … | |
+( This)1 229( command language to edit text on an ordinary terminal.)9 2256(fo… | |
+(mode is invoked by starting)4 1111 1 720 3698 t | |
+10 CW f | |
+(sam)1856 3698 w | |
+10 R f | |
+(with the)1 325 1 2061 3698 t | |
+10 CW f | |
+(-d)2412 3698 w | |
+10 R f | |
+( no options,)2 472(option. With)1 532 2 2558 3698 t | |
+10 CW f | |
+(sam)3588 3698 w | |
+10 R f | |
+(runs separate host and terminal)4 1246 1 3794 3698 t | |
+( Typically,)1 458( over the physical connection that joins them.)7 1815(progr… | |
+( display for)2 469(the connection is an RS-232 link between a Blit \(the prot… | |
+10 CW f | |
+(sam)3879 3938 w | |
+10 R f | |
+(\) and a host running the)5 981 1 4059 3938 t | |
+(Ninth Edition of the Unix operating system.)6 1782 1 720 4058 t | |
+6 R f | |
+(8)2502 4008 w | |
+10 R f | |
+(\(This is the version of the system used in the Computing Sci-)11 2480 1 2560… | |
+( are discussed in the)4 828( relevant aspects)2 669( Its)1 155(ences Research… | |
+(Blit paper.)1 432 1 720 4298 t | |
+6 R f | |
+(1)1152 4248 w | |
+10 R f | |
+( implementation of)2 779(\) The)1 223 2 1182 4298 t | |
+10 CW f | |
+(sam)2218 4298 w | |
+10 R f | |
+(for the Sun computer runs both processes on the same machine)10 2608 1 2432 4… | |
+(and connects them by a pipe.)5 1159 1 720 4418 t | |
+( division)1 351( The)1 208( of an RS-232 link necessitated the split between … | |
+( a self-contained one,)3 859(is a mixed blessing: a program in two parts is m… | |
+( terminal may be physically separated from)6 1736( The)1 206( configurations … | |
+( to be taken home while leaving the files)8 1628(the host, allowing the conve… | |
+( is also possible to run the host part on a remote machine:)12 2298( It)1 111… | |
+9 CW f | |
+(sam -r host)2 594 1 1008 5224 t | |
+10 R f | |
+( the network to establish the host part)7 1503(connects to the terminal in th… | |
+(of)720 5524 w | |
+10 CW f | |
+(sam)831 5524 w | |
+10 R f | |
+( allows)1 288( This)1 230( parts.)1 246( it cross-connects the I/O to join th… | |
+10 CW f | |
+(sam)4755 5524 w | |
+10 R f | |
+(to)4962 5524 w | |
+(be run on machines that do not support bitmap displays; for example,)11 2869 … | |
+10 CW f | |
+(sam)3623 5644 w | |
+10 R f | |
+( our)1 168(is the editor of choice on)5 1035 2 3837 5644 t | |
+(Cray X-MP/24.)1 632 1 720 5764 t | |
+10 CW f | |
+(Sam -r)1 334 1 1412 5764 t | |
+10 R f | |
+(involves)1780 5764 w | |
+10 I f | |
+(three)2153 5764 w | |
+10 R f | |
+( The)1 214(machines: the remote host, the terminal, and the local host.)9 243… | |
+(local host's job is simple but vital: it passes the data between the remote h… | |
+( exchange messages asynchronously \(rather than, say, as remote procedure)9 3… | |
+( correction because, whatever the configuration, the connection is)8 2709(cal… | |
+( mundane interaction tasks such as popping up menus and interpret-)10 2763( t… | |
+( example, the host knows nothing about)6 1657( For)1 200( not actions.)2 508(… | |
+( says)1 211(what is displayed on the screen, and when the user types a charac… | |
+( position in the)3 601(``insert a one-byte string at location 123 in file 7,'… | |
+( other words, the messages look very much like the transaction records in the… | |
+( host or terminal part of)5 961(Either the)1 393 2 970 6916 t | |
+10 CW f | |
+(sam)2352 6916 w | |
+10 R f | |
+( command language oper-)3 1048( The)1 208(may initiate a change to a file.)6 … | |
+( mouse operations are executed directly in the terminal to optimize)10 2708(a… | |
+( \(A)1 165( the terminal, and vice versa.)5 1200( initiated by the host progr… | |
+( which means that characters typed while a time-)8 1999(token is exchanged to… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 20 20 | |
+%%Page: 21 21 | |
+/saveobj save def | |
+mark | |
+21 pagesetup | |
+10 R f | |
+(- 21 -)2 216 1 2772 480 t | |
+( main-)1 264( To)1 167( buffered and do not appear until the command is compl… | |
+( track changes through a per-file data structure that records)9 2351(tain con… | |
+( data structure, called a)4 954( The)1 213(what portions of the file the term… | |
+10 CW f | |
+(Rasp)3994 1080 w | |
+10 R f | |
+(\(a weak pun: it's a)4 773 1 4267 1080 t | |
+( A)1 128(file with holes\) is held and updated by both the host and terminal.… | |
+10 CW f | |
+(Rasp)3574 1200 w | |
+10 R f | |
+( of)1 113(is a list)2 296 2 3845 1200 t | |
+10 CW f | |
+(Strings)4284 1200 w | |
+10 R f | |
+(holding)4734 1200 w | |
+( number of bytes in the interstices.)6 1415(those parts of the file known to … | |
+( needs the lengths of the various pieces\),)7 1619(Of course, the host doesn'… | |
+(but the structure is the same on both ends.)8 1679 1 720 1560 t | |
+(The)970 1716 w | |
+10 CW f | |
+(Rasp)1158 1716 w | |
+10 R f | |
+( the terminal keeps the text for portions of the)9 1909( Since)1 280(in the t… | |
+(file it has displayed, it need not request data from the host when revisiting… | |
+(obscured windows, which speeds things up considerably over low-speed links.)9… | |
+(It's trivial for the terminal to maintain its)7 1683 1 970 2112 t | |
+10 CW f | |
+(Rasp)2684 2112 w | |
+10 R f | |
+( on the terminal apply to)5 1015(, because all changes made)4 1101 2 2924 211… | |
+( made by the host are compared against the)8 1740( Changes)1 396( already loa… | |
+10 CW f | |
+(Rasp)4363 2232 w | |
+10 R f | |
+(during the)1 410 1 4630 2232 t | |
+( changes to pieces of the file loaded in the terminal are sent in)13 2509( Sm… | |
+( in the holes, are transmitted as messages with-)8 1894( changes, and changes… | |
+( a command is)3 610( When)1 298( the lengths of the deleted and inserted stri… | |
+( in their)2 319(completed, the terminal examines its visible windows to see i… | |
+10 CW f | |
+(Rasps)4015 2712 w | |
+10 R f | |
+(intersect the visi-)2 696 1 4344 2712 t | |
+( 512 bytes of sur-)4 731( then requests the missing data from the host, along… | |
+( technique)1 414( This)1 229( the file.)2 332(rounding data, to minimize the … | |
+( first level sends a minimum of informa-)7 1646( The)1 209(provides a kind of… | |
+( the file not being edited interactively; the second level waits until a chan… | |
+( is also helped by having the terminal respond)8 1933( course, performance)2 … | |
+( for small changes to active pieces of the file,)9 1906( Except)1 338( and si… | |
+(which are transmitted to the terminal without negotiation, the terminal is wh… | |
+(what is displayed; the host uses the)6 1405 1 720 3672 t | |
+10 CW f | |
+(Rasp)2150 3672 w | |
+10 R f | |
+(only to tell the terminal what might be relevant.)8 1907 1 2415 3672 t | |
+( host, the messages to the terminal describing the change are gener-)11 2727(… | |
+( the transcript of the changes to the contents of the)10 2023(ated by the rou… | |
+10 CW f | |
+(File)4008 3948 w | |
+10 R f | |
+( changes are)2 494(. Since)1 298 2 4248 3948 t | |
+( no extra code in the communications; the usual mes-)9 2173(undone by the sam… | |
+(sages describing changes to the file are sufficient to back up the screen ima… | |
+(The)970 4344 w | |
+10 CW f | |
+(Rasp)1164 4344 w | |
+10 R f | |
+(is a particularly good example of the way caches are used in)11 2556 1 1443 4… | |
+10 CW f | |
+(sam)4038 4344 w | |
+10 R f | |
+( it facilitates)2 524(. First,)1 298 2 4218 4344 t | |
+( so doing, it provides)4 870( In)1 140( portion of the text by placing the bu… | |
+( be)1 138( the form of data is to)6 968( Since)1 290(efficient access to a la… | |
+( characters will frequently be scanned sequentially,)6 2090(imposed by the us… | |
+( help keep performance good and linear when working with such)10 2724( Caches… | |
+(data.)720 4944 w | |
+(Second, the)1 468 1 970 5100 t | |
+10 CW f | |
+(Rasp)1465 5100 w | |
+10 R f | |
+(and several of the other caches have some)7 1696 1 1732 5100 t | |
+10 I f | |
+(read-ahead;)3456 5100 w | |
+10 R f | |
+(that is, the cache is loaded)5 1063 1 3977 5100 t | |
+( manipulating linear struc-)3 1090( When)1 299( than is needed for the job im… | |
+( time to access)3 588(tures, the accesses are usually sequential, and read-ah… | |
+( mode for people as well as programs; con-)8 1764( access is a common)4 839( … | |
+(sider scrolling through a document while looking for something.)8 2579 1 720 … | |
+( at least the implementation.)4 1158(Finally, like any good data structure, t… | |
+(The)720 5856 w | |
+10 CW f | |
+(Rasp)906 5856 w | |
+10 R f | |
+( between the host and terminal parts, but I)8 1718(was actually invented to c… | |
+( caches were more explicitly intended to serve a)8 1957( Other)1 282( was als… | |
+(double purpose: for example, the caches in)6 1728 1 720 6096 t | |
+10 CW f | |
+(Files)2476 6096 w | |
+10 R f | |
+(that coalesce updates not only reduce traffic to the tran-)9 2237 1 2803 6096… | |
+(script and contents)2 749 1 720 6216 t | |
+10 CW f | |
+(Buffers)1494 6216 w | |
+10 R f | |
+( clump screen updates so that complicated changes to the screen are)11 2718(,… | |
+( not need to write)4 715( saved me considerable work: I did)6 1427( This)1 23… | |
+( they)1 200( Also,)1 267( pay off in surprising ways.)5 1108( Caches)1 341( o… | |
+(tend to be independent, so their performance improvements are multiplicative.… | |
+10 B f | |
+(Data structures in the terminal)4 1320 1 720 6816 t | |
+10 R f | |
+(The terminal's job is to display and to maintain a consistent image of pieces… | |
+( text is always in memory, the data structures are considerably simpler than … | |
+(part.)720 7212 w | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 21 21 | |
+%%Page: 22 22 | |
+/saveobj save def | |
+mark | |
+22 pagesetup | |
+10 R f | |
+(- 22 -)2 216 1 2772 480 t | |
+10 CW f | |
+(Sam)970 840 w | |
+10 R f | |
+( does)1 211(typically has far more windows than)5 1466 2 1177 840 t | |
+10 CW f | |
+(mux)2882 840 w | |
+10 R f | |
+(, the window system within which its Blit imple-)8 1978 1 3062 840 t | |
+(mentation runs.)1 633 1 720 960 t | |
+10 CW f | |
+(Mux)1414 960 w | |
+10 R f | |
+(has a fairly small number of asynchronously updated windows;)8 2618 1 1630 96… | |
+10 CW f | |
+(sam)4284 960 w | |
+10 R f | |
+(needs a large)2 540 1 4500 960 t | |
+( different)1 376( The)1 213( static and often fully obscured.)5 1299(number o… | |
+(tradeoffs guided)1 670 1 720 1200 t | |
+10 CW f | |
+(sam)1434 1200 w | |
+10 R f | |
+( windows, called)2 710(away from the memory-intensive implementation of)5 218… | |
+10 CW f | |
+(Layers)4595 1200 w | |
+10 R f | |
+(,)4955 1200 w | |
+6 R f | |
+(17)4980 1150 w | |
+10 R f | |
+(used in)1 297 1 720 1320 t | |
+10 CW f | |
+(mux.)1053 1320 w | |
+10 R f | |
+( window,)1 384(Rather than depending on a complete bitmap image of the displa… | |
+10 CW f | |
+(sam)4860 1320 w | |
+10 R f | |
+( image from its in-memory text \(stored in the)8 1876(regenerates the)1 610 2… | |
+10 CW f | |
+(Rasp)3240 1440 w | |
+10 R f | |
+(\) when necessary, although it will use)6 1560 1 3480 1440 t | |
+( Like)1 243(such an image if it is available.)6 1300 2 720 1560 t | |
+10 CW f | |
+(Layers)2299 1560 w | |
+10 R f | |
+(, though,)1 364 1 2659 1560 t | |
+10 CW f | |
+(sam)3059 1560 w | |
+10 R f | |
+(uses the screen bitmap as active storage in)7 1765 1 3275 1560 t | |
+(which to update the image using)5 1306 1 720 1680 t | |
+10 CW f | |
+(bitblt)2053 1680 w | |
+10 R f | |
+(.)2413 1680 w | |
+6 R f | |
+(18,19)2438 1630 w | |
+10 R f | |
+(The resulting organization, pictured in Figure 6, has a global)9 2440 1 2600 … | |
+(array of windows, called)3 989 1 720 1800 t | |
+10 CW f | |
+(Flayers)1735 1800 w | |
+10 R f | |
+( structure)1 376(, each of which holds an image of a piece of text held in a … | |
+(called a)1 319 1 720 1920 t | |
+10 CW f | |
+(Frame)1076 1920 w | |
+10 R f | |
+( rectangular window full of text displayed in some)8 2102(, which in turn rep… | |
+10 CW f | |
+(Bitmap)4655 1920 w | |
+10 R f | |
+(.)5015 1920 w | |
+(Each)720 2040 w | |
+10 CW f | |
+(Flayer)947 2040 w | |
+10 R f | |
+( display, and simultaneously)3 1151(appears in a global list that orders them… | |
+( in the termi-)3 519( complement)1 520( The)1 206(as an element of a per-file… | |
+(nal of the)2 377 1 720 2280 t | |
+10 CW f | |
+(File)1122 2280 w | |
+10 R f | |
+(on the host is called a)5 863 1 1387 2280 t | |
+10 CW f | |
+(Text)2275 2280 w | |
+10 R f | |
+(; each connects its)3 729 1 2515 2280 t | |
+10 CW f | |
+(Flayers)3269 2280 w | |
+10 R f | |
+(to the associated)2 660 1 3714 2280 t | |
+10 CW f | |
+(Rasp)4399 2280 w | |
+10 R f | |
+(.)4639 2280 w | |
+1800 2478 1800 2766 Dl | |
+2606 2478 1800 2478 Dl | |
+2606 2766 2606 2478 Dl | |
+1800 2766 2606 2766 Dl | |
+10 CW f | |
+(Text)2083 2642 w | |
+2722 2478 2722 2766 Dl | |
+3370 2478 2722 2478 Dl | |
+3370 2766 3370 2478 Dl | |
+2722 2766 3370 2766 Dl | |
+(Rasp)2926 2642 w | |
+2721 2622 2606 2622 Dl | |
+3542 2622 3370 2622 Dl | |
+3542 2622 3470 2640 Dl | |
+3542 2622 3470 2604 Dl | |
+10 R f | |
+(to host)1 270 1 3677 2642 t | |
+2203 2881 2203 2766 Dl | |
+1987 2881 2203 2881 Dl | |
+1987 3097 1987 2881 Dl | |
+2102 3097 1987 3097 Dl | |
+2102 2953 2102 3241 Dl | |
+2642 2953 2102 2953 Dl | |
+2642 3241 2642 2953 Dl | |
+2102 3241 2642 3241 Dl | |
+10 CW f | |
+(Flayer)2192 3117 w | |
+2642 2953 2642 3241 Dl | |
+3182 2953 2642 2953 Dl | |
+3182 3241 3182 2953 Dl | |
+2642 3241 3182 3241 Dl | |
+3182 2953 3182 3241 Dl | |
+3722 2953 3182 2953 Dl | |
+3722 3241 3722 2953 Dl | |
+3182 3241 3722 3241 Dl | |
+3722 2953 3722 3241 Dl | |
+4262 2953 3722 2953 Dl | |
+4262 3241 4262 2953 Dl | |
+3722 3241 4262 3241 Dl | |
+(...)3902 3117 w | |
+(...)2822 3578 w | |
+2102 3414 2102 3702 Dl | |
+2642 3414 2102 3414 Dl | |
+2642 3702 2642 3414 Dl | |
+2102 3702 2642 3702 Dl | |
+(Frame)2222 3578 w | |
+2372 3413 2372 3241 Dl | |
+2912 3413 2912 3241 Dl | |
+3452 3413 3452 3241 Dl | |
+3992 3413 3992 3241 Dl | |
+1498 3414 1498 3702 Dl | |
+1930 3414 1498 3414 Dl | |
+1930 3702 1930 3414 Dl | |
+1498 3702 1930 3702 Dl | |
+(Bitmap)1534 3518 w | |
+10 R f | |
+(\(cache\))1568 3638 w | |
+2102 3558 1930 3558 Dl | |
+2372 3817 2372 3702 Dl | |
+2012 3817 2372 3817 Dl | |
+2012 4033 2012 3817 Dl | |
+2127 4033 2012 4033 Dl | |
+2128 3889 2128 4177 Dl | |
+2452 3889 2128 3889 Dl | |
+2452 4177 2452 3889 Dl | |
+2128 4177 2452 4177 Dl | |
+10 CW f | |
+(Box)2200 4053 w | |
+2452 3889 2452 4177 Dl | |
+2776 3889 2452 3889 Dl | |
+2776 4177 2776 3889 Dl | |
+2452 4177 2776 4177 Dl | |
+2776 3889 2776 4177 Dl | |
+3100 3889 2776 3889 Dl | |
+3100 4177 3100 3889 Dl | |
+2776 4177 3100 4177 Dl | |
+3100 3889 3100 4177 Dl | |
+3424 3889 3100 3889 Dl | |
+3424 4177 3424 3889 Dl | |
+3100 4177 3424 4177 Dl | |
+(...)3172 4053 w | |
+8 I f | |
+(Figure 6. Data structures in the terminal.)6 1360 1 720 4355 t | |
+8 CW f | |
+(Flayers)2126 4355 w | |
+8 I f | |
+(are also linked together into a front-to-back list.)7 1587 1 2488 4355 t | |
+8 CW f | |
+(Boxes)4122 4355 w | |
+8 I f | |
+(are discussed in the)3 651 1 4389 4355 t | |
+(next section.)1 397 1 720 4455 t | |
+10 R f | |
+(The)970 4731 w | |
+10 CW f | |
+(Bitmap)1155 4731 w | |
+10 R f | |
+(for a)1 190 1 1545 4731 t | |
+10 CW f | |
+(Frame)1765 4731 w | |
+10 R f | |
+( a fully visible window, the)5 1124( For)1 195(contains the image of the text… | |
+10 CW f | |
+(Bitmap)4680 4731 w | |
+10 R f | |
+(will be the screen \(or at least the)7 1315 1 720 4851 t | |
+10 CW f | |
+(Layer)2063 4851 w | |
+10 R f | |
+(in which)1 350 1 2391 4851 t | |
+10 CW f | |
+(sam)2769 4851 w | |
+10 R f | |
+( while for partially obscured windows)5 1527(is being run\),)2 536 2 2977 485… | |
+(the)720 4971 w | |
+10 CW f | |
+(Bitmap)867 4971 w | |
+10 R f | |
+( the window is fully obscured, the)6 1357( If)1 116(will be off-screen.)2 728… | |
+10 CW f | |
+(Bitmap)3478 4971 w | |
+10 R f | |
+(will be null.)2 481 1 3863 4971 t | |
+(The)970 5127 w | |
+10 CW f | |
+(Bitmap)1159 5127 w | |
+10 R f | |
+( image)1 279( making changes to the display, most of the original)9 2152( Whe… | |
+( The)1 207( this.)1 197(will look the same in the final image, and the update… | |
+10 CW f | |
+(Frame)4038 5247 w | |
+10 R f | |
+(software updates)1 675 1 4365 5247 t | |
+(the image in the)3 644 1 720 5367 t | |
+10 CW f | |
+(Bitmap)1390 5367 w | |
+10 R f | |
+(incrementally; the)1 725 1 1776 5367 t | |
+10 CW f | |
+(Bitmap)2528 5367 w | |
+10 R f | |
+(is not just an image, it is a data structure.)9 1653 1 2915 5367 t | |
+6 R f | |
+(18,19)4568 5317 w | |
+10 R f | |
+(The job)1 310 1 4730 5367 t | |
+( therefore to use as much as possible of the existing image \(con-)12 2622(of… | |
+( a sort of two-dimensional string insertion)6 1713(verting the text from ASCI… | |
+( details of this process are described in the next section.)10 2221(algorithm… | |
+(The)970 5883 w | |
+10 CW f | |
+(Frame)1173 5883 w | |
+10 R f | |
+(software has no code to support overlapping windows; its job is to keep a sin… | |
+10 CW f | |
+(Bitmap)720 6003 w | |
+10 R f | |
+( falls to the)3 471( It)1 119(up to date.)2 435 3 1113 6003 t | |
+10 CW f | |
+(Flayer)2171 6003 w | |
+10 R f | |
+(software to multiplex the various)4 1349 1 2564 6003 t | |
+10 CW f | |
+(Bitmaps)3945 6003 w | |
+10 R f | |
+(onto the screen.)2 643 1 4397 6003 t | |
+(The problem of maintaining overlapping)4 1638 1 720 6123 t | |
+10 CW f | |
+(Flayers)2386 6123 w | |
+10 R f | |
+(is easier than for)3 671 1 2834 6123 t | |
+10 CW f | |
+(Layers)3533 6123 w | |
+6 R f | |
+(17)3893 6073 w | |
+10 R f | |
+( are made)2 395(because changes)1 664 2 3981 6123 t | |
+( reconstructed from the data stored in the)7 1722(synchronously and because t… | |
+10 CW f | |
+(Frame)720 6363 w | |
+10 R f | |
+(; the)1 180 1 1020 6363 t | |
+10 CW f | |
+(Layers)1231 6363 w | |
+10 R f | |
+( In)1 139(software makes no such assumptions.)4 1525 2 1622 6363 t | |
+10 CW f | |
+(sam)3317 6363 w | |
+10 R f | |
+(, the window being changed is almost)6 1543 1 3497 6363 t | |
+( when)1 247( However,)1 446(always fully visible, because the current window … | |
+( it may be necessary to)5 927(multi-file changes are being made, or when more… | |
+(update partially obscured windows.)3 1420 1 720 6723 t | |
+( If)1 125( fully visible, invisible \(fully obscured\), or partially visible.… | |
+(fully visible, the)2 687 1 720 6999 t | |
+10 CW f | |
+(Bitmap)1449 6999 w | |
+10 R f | |
+(is part of the screen, so when the)7 1427 1 1851 6999 t | |
+10 CW f | |
+(Flayer)3320 6999 w | |
+10 R f | |
+(update routine calls the)3 977 1 3722 6999 t | |
+10 CW f | |
+(Frame)4740 6999 w | |
+10 R f | |
+( is invisible, there is no associated)6 1489( the window)2 534( If)1 136(upda… | |
+10 CW f | |
+(Bitmap)720 7239 w | |
+10 R f | |
+( necessary is to update the)5 1075(, and all that is)4 614 2 1080 7239 t | |
+10 CW f | |
+(Frame)2800 7239 w | |
+10 R f | |
+( the window is)3 604( If)1 122(data structure, not the image.)4 1183 3 3131 7… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 22 22 | |
+%%Page: 23 23 | |
+/saveobj save def | |
+mark | |
+23 pagesetup | |
+10 R f | |
+(- 23 -)2 216 1 2772 480 t | |
+(partially visible, the)2 817 1 720 840 t | |
+10 CW f | |
+(Frame)1572 840 w | |
+10 R f | |
+( called to update the image in the off-screen)8 1839(routine is)1 385 2 1907 … | |
+10 CW f | |
+(Bitmap)4167 840 w | |
+10 R f | |
+(, which may)2 513 1 4527 840 t | |
+( The)1 207(require regenerating it from the text of the window.)8 2078 2 720 … | |
+10 CW f | |
+(Flayer)3032 960 w | |
+10 R f | |
+(code then clips this)3 775 1 3419 960 t | |
+10 CW f | |
+(Bitmap)4221 960 w | |
+10 R f | |
+(against the)1 432 1 4608 960 t | |
+10 CW f | |
+(Bitmaps)720 1080 w | |
+10 R f | |
+(of all)1 208 1 1165 1080 t | |
+10 CW f | |
+(Frames)1398 1080 w | |
+10 R f | |
+(in front of the)3 552 1 1783 1080 t | |
+10 CW f | |
+(Frame)2360 1080 w | |
+10 R f | |
+(being modified, and the remainder is copied to the display.)9 2350 1 2685 108… | |
+( than recreating the image off-screen for every change, or clipping all the c… | |
+( amounts of)2 476( these caches can also consume prohibitive)6 1731( Unfortun… | |
+( freed fairly liberally \320 after every change to the front-to-back order of… | |
+10 CW f | |
+(Flayers)4595 1476 w | |
+10 R f | |
+(.)5015 1476 w | |
+(The result is that the off-screen)5 1274 1 720 1596 t | |
+10 CW f | |
+(Bitmaps)2025 1596 w | |
+10 R f | |
+(exist only while multi-window changes are occurring, which is)8 2564 1 2476 1… | |
+( the user interface causes fully-)5 1278( Also,)1 271( improvement they provi… | |
+( creating a canonically sized and placed window requires)8 2357(obscured wind… | |
+(only a button click \320 which reduces the need for caching still further.)12… | |
+10 B f | |
+(Screen update)1 608 1 720 2232 t | |
+10 R f | |
+( update:)1 321(Only two low-level primitives are needed for incremental)7 230… | |
+10 CW f | |
+(bitblt)3373 2388 w | |
+10 R f | |
+(, which copies rectangles of pix-)5 1307 1 3733 2388 t | |
+(els, and)1 328 1 720 2508 t | |
+10 CW f | |
+(string)1096 2508 w | |
+10 R f | |
+(\(which in turn calls)3 840 1 1503 2508 t | |
+10 CW f | |
+(bitblt)2390 2508 w | |
+10 R f | |
+(\), which draws a null-terminated character string in a)8 2290 1 2750 2508 t | |
+10 CW f | |
+(Bitmap)720 2628 w | |
+10 R f | |
+(. A)1 153 1 1080 2628 t | |
+10 CW f | |
+(Frame)1264 2628 w | |
+10 R f | |
+(contains a list of)3 676 1 1595 2628 t | |
+10 CW f | |
+(Boxes)2302 2628 w | |
+10 R f | |
+( win-)1 215(, each of which defines a horizontal strip of text in the)11 2223… | |
+( A)1 126(dow \(see Figure 7\).)3 788 2 720 2748 t | |
+10 CW f | |
+(Box)1663 2748 w | |
+10 R f | |
+(has a character string)3 856 1 1872 2748 t | |
+10 CW f | |
+(str)2757 2748 w | |
+10 R f | |
+(, and a)2 271 1 2937 2748 t | |
+10 CW f | |
+(Rectangle rect)1 809 1 3237 2748 t | |
+10 R f | |
+(that defines the location)3 966 1 4074 2748 t | |
+( text in)2 280( \(The)1 239(of the strip in the window.)5 1060 3 720 2868 t | |
+10 CW f | |
+(str)2325 2868 w | |
+10 R f | |
+(is stored in the)3 592 1 2531 2868 t | |
+10 CW f | |
+(Box)3150 2868 w | |
+10 R f | |
+(separately from the)2 774 1 3357 2868 t | |
+10 CW f | |
+(Rasp)4158 2868 w | |
+10 R f | |
+(associated with)1 615 1 4425 2868 t | |
+(the window's file, so)3 853 1 720 2988 t | |
+10 CW f | |
+(Boxes)1603 2988 w | |
+10 R f | |
+( the)1 151( invariant is that the image of)6 1201( The)1 210(are self-contain… | |
+10 CW f | |
+(Box)4298 2988 w | |
+10 R f | |
+(can be repro-)2 533 1 4507 2988 t | |
+(duced by calling)2 660 1 720 3108 t | |
+10 CW f | |
+(string)1405 3108 w | |
+10 R f | |
+(with argument)1 581 1 1790 3108 t | |
+10 CW f | |
+(str)2397 3108 w | |
+10 R f | |
+(to draw the string in)4 809 1 2603 3108 t | |
+10 CW f | |
+(rect)3438 3108 w | |
+10 R f | |
+(, and the resulting picture fits per-)6 1362 1 3678 3108 t | |
+(fectly within)1 509 1 720 3228 t | |
+10 CW f | |
+(rect)1255 3228 w | |
+10 R f | |
+( other words, the)3 674(. In)1 159 2 1495 3228 t | |
+10 CW f | |
+(Boxes)2354 3228 w | |
+10 R f | |
+( tiling may be compli-)4 889( The)1 206(define the tiling of the window.)5 12… | |
+( editors use horizontal scrolling to)5 1413( Some)1 288( of text, which are f… | |
+( be)1 119(avoid this complication, but to be comfortable this technique requi… | |
+10 I f | |
+(too)4193 3468 w | |
+10 R f | |
+(long;)4346 3468 w | |
+10 CW f | |
+(sam)4577 3468 w | |
+10 R f | |
+(has no)1 258 1 4782 3468 t | |
+( programs and terminals traditionally fold long)6 1907( and perhaps more impo… | |
+(lines to make their contents fully visible.)6 1630 1 720 3708 t | |
+(Two special kinds of)3 841 1 970 3864 t | |
+10 CW f | |
+(Boxes)1839 3864 w | |
+10 R f | |
+( and tabs)2 361( Newlines)1 430(contain a single character: either a newline … | |
+( newline)1 353( A)1 134(are white space.)2 663 3 720 3984 t | |
+10 CW f | |
+(Box)1907 3984 w | |
+10 R f | |
+( following)1 425(always extends to the right edge of the window, forcing the)… | |
+10 CW f | |
+(Box)720 4104 w | |
+10 R f | |
+( on where it is located: it forces the next)9 1618( width of a tab depends)5 … | |
+10 CW f | |
+(Box)4336 4104 w | |
+10 R f | |
+(to begin at a)3 497 1 4543 4104 t | |
+( a minimum width equivalent to a blank \(blanks are drawn by)11 2472( also ha… | |
+10 CW f | |
+(string)4363 4224 w | |
+10 R f | |
+(and are)1 291 1 4749 4224 t | |
+(not treated specially\); newlines have a minimum width of zero.)9 2524 1 720 … | |
+929 4506 929 4614 Dl | |
+1505 4506 929 4506 Dl | |
+1505 4614 1505 4506 Dl | |
+929 4614 1505 4614 Dl | |
+1505 4506 1505 4614 Dl | |
+2700 4506 1505 4506 Dl | |
+2700 4614 2700 4506 Dl | |
+1505 4614 2700 4614 Dl | |
+10 CW f | |
+(for\(i=0; i<NL; i++\){)2 1200 1 1502 4580 t | |
+2700 4506 2700 4614 Dl | |
+3132 4506 2700 4506 Dl | |
+3132 4614 3132 4506 Dl | |
+2700 4614 3132 4614 Dl | |
+3132 4506 3132 4614 Dl | |
+4471 4506 3132 4506 Dl | |
+4471 4614 4471 4506 Dl | |
+3132 4614 4471 4614 Dl | |
+(/* for each element */)4 1320 1 3141 4580 t | |
+4471 4506 4471 4614 Dl | |
+4831 4506 4471 4506 Dl | |
+4831 4614 4831 4506 Dl | |
+4471 4614 4831 4614 Dl | |
+8 I f | |
+( line of text showing its)5 747(Figure 7. A)2 368 2 720 4852 t | |
+8 CW f | |
+(Boxes)1857 4852 w | |
+8 I f | |
+( first two blank)3 487(. The)1 182 2 2097 4852 t | |
+8 CW f | |
+(Boxes)2788 4852 w | |
+8 I f | |
+( are handled)2 407( Spaces)1 263(contain tabs; the last contains a newline.)6… | |
+(as ordinary characters.)2 750 1 720 4952 t | |
+10 R f | |
+(The update algorithms always use the)5 1631 1 970 5228 t | |
+10 CW f | |
+(Bitmap)2651 5228 w | |
+10 R f | |
+(image of the text \(either the display or cache)8 1979 1 3061 5228 t | |
+10 CW f | |
+(Bitmap)720 5348 w | |
+10 R f | |
+( examine the characters within a)5 1318(\); they never)2 518 2 1080 5348 t | |
+10 CW f | |
+(Box)2947 5348 w | |
+10 R f | |
+(except when the)2 660 1 3158 5348 t | |
+10 CW f | |
+(Box)3849 5348 w | |
+10 R f | |
+(needs to be split in two.)5 980 1 4060 5348 t | |
+( the window consists of a tiling of)7 1365(Before a change,)2 672 2 720 5468 t | |
+10 CW f | |
+(Boxes)2783 5468 w | |
+10 R f | |
+(; after the change the window is tiled differently.)8 1957 1 3083 5468 t | |
+( algorithms are not strictly)4 1075( The)1 210( rearrange the tiles in place,… | |
+( move)1 250(optimal \320 for example, they can clear a pixel that is later go… | |
+( that doesn't need to be moved, and they move each tile at most once.)14 2975… | |
+10 CW f | |
+(Frinsert)3971 5828 w | |
+10 R f | |
+(on a Blit can)3 550 1 4490 5828 t | |
+(absorb over a thousand characters a second if the strings being inserted are … | |
+(Consider)970 6104 w | |
+10 CW f | |
+(frdelete)1368 6104 w | |
+10 R f | |
+( job is to delete a substring from a)8 1456(. Its)1 187 2 1848 6104 t | |
+10 CW f | |
+(Frame)3528 6104 w | |
+10 R f | |
+( the image of the)4 723(and restore)1 452 2 3865 6104 t | |
+10 CW f | |
+(Frame)720 6224 w | |
+10 R f | |
+( comprising possibly a partial line,)5 1428( image of a substring has a pecul… | |
+( reference, call this the)4 937( For)1 197( line.)1 208(zero or more full lin… | |
+10 I f | |
+(Z-shape.)4155 6344 w | |
+10 CW f | |
+(Frdelete)4560 6344 w | |
+10 R f | |
+( necessary, the)2 584(begins by splitting, if)3 854 2 720 6464 t | |
+10 CW f | |
+(Boxes)2183 6464 w | |
+10 R f | |
+(containing the ends of the substring so the substring begins and)10 2532 1 25… | |
+(ends on)1 311 1 720 6584 t | |
+10 CW f | |
+(Box)1059 6584 w | |
+10 R f | |
+( Z-shape is)2 446( the substring is being deleted, its image is not needed, s… | |
+( tiles \(that is, the images of)6 1092( Then,)1 282(then cleared.)1 511 3 720… | |
+10 CW f | |
+(Boxes)2632 6704 w | |
+10 R f | |
+(\) are copied, using)3 743 1 2932 6704 t | |
+10 CW f | |
+(bitblt)3701 6704 w | |
+10 R f | |
+(, from immediately after)3 979 1 4061 6704 t | |
+( \()1 92(the Z-shape to the beginning of the Z-shape, resulting in a new Z-sh… | |
+10 CW f | |
+(Boxes)3798 6824 w | |
+10 R f | |
+(whose contents would)2 908 1 4132 6824 t | |
+(span two lines in the new position must first be split.\))10 2142 1 720 6944 t | |
+( the)1 158(Copying the remainder of)3 1059 2 970 7100 t | |
+10 CW f | |
+(Frame)2223 7100 w | |
+10 R f | |
+(tile by tile this way will clearly accomplish the deletion but)10 2481 1 2559… | |
+( new)1 221(eventually, typically when the copying algorithm encounters a tab … | |
+10 CW f | |
+(x)4980 7220 w | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 23 23 | |
+%%Page: 24 24 | |
+/saveobj save def | |
+mark | |
+24 pagesetup | |
+10 R f | |
+(- 24 -)2 216 1 2772 480 t | |
+( correspondence implies that the Z-shape has its)7 2021( This)1 243( same.)1 … | |
+( aligned vertically, and a sequence of at most two)9 2073(beginning and endin… | |
+10 CW f | |
+(bitblts)3983 960 w | |
+10 R f | |
+(can be used to)3 601 1 4439 960 t | |
+( clear out the resulting empty space at the bottom of the win-)12 2526( last … | |
+( number of complete lines in the Z-shape closed by the final)11 2476(dow; the… | |
+10 CW f | |
+(bitblts.)720 1320 w | |
+10 R f | |
+( horizontally adjacent)2 877(The final step is to merge)5 1043 2 1230 1320 t | |
+10 CW f | |
+(Boxes)3181 1320 w | |
+10 R f | |
+( complete source to)3 797( The)1 211(of plain text.)2 520 3 3512 1320 t | |
+10 CW f | |
+(frdelete)720 1440 w | |
+10 R f | |
+(is less than 100 lines of C.)6 1053 1 1225 1440 t | |
+10 CW f | |
+(frinsert)970 1596 w | |
+10 R f | |
+( the)1 150(is more complicated because it must do four passes: one to constru… | |
+10 CW f | |
+(Box)4415 1596 w | |
+10 R f | |
+(list for the)2 417 1 4623 1596 t | |
+( one to reconnoitre, one to copy \(in opposite order to)10 2175(inserted stri… | |
+10 CW f | |
+(frdelete)3529 1716 w | |
+10 R f | |
+(\) the)1 187 1 4009 1716 t | |
+10 CW f | |
+(Boxes)4228 1716 w | |
+10 R f | |
+(to make the)2 480 1 4560 1716 t | |
+( though,)1 335( Overall,)1 381(hole for the new text, and finally one to copy… | |
+10 CW f | |
+(frinsert)4317 1836 w | |
+10 R f | |
+(has a)1 210 1 4830 1836 t | |
+(similar flavor to)2 676 1 720 1956 t | |
+10 CW f | |
+(frdelete)1437 1956 w | |
+10 R f | |
+(, and needn't be described further.)5 1445 1 1917 1956 t | |
+10 CW f | |
+(Frinsert)3428 1956 w | |
+10 R f | |
+(and its subsidiary routines)3 1092 1 3948 1956 t | |
+(comprise 211 lines of C.)4 980 1 720 2076 t | |
+(The terminal source code is 3024 lines of C, and the host source is 5797 line… | |
+10 B f | |
+(Discussion)720 2472 w | |
+(History)720 2712 w | |
+10 R f | |
+( of)1 113(The immediate ancestor)2 967 2 720 2868 t | |
+10 CW f | |
+(sam)1830 2868 w | |
+10 R f | |
+(was the original text editor for the Blit, called)8 1863 1 2040 2868 t | |
+10 CW f | |
+(jim)3933 2868 w | |
+10 R f | |
+(.)4113 2868 w | |
+10 CW f | |
+(Sam)4193 2868 w | |
+10 R f | |
+(inherited)4403 2868 w | |
+10 CW f | |
+(jim)4788 2868 w | |
+10 R f | |
+('s)4968 2868 w | |
+(two-process structure and mouse language almost unchanged, but)7 2721 1 720 2… | |
+10 CW f | |
+(jim)3480 2988 w | |
+10 R f | |
+(suffered from several drawbacks)3 1342 1 3698 2988 t | |
+( addressed in the design of)5 1112(that were)1 377 2 720 3108 t | |
+10 CW f | |
+(sam)2244 3108 w | |
+10 R f | |
+( most important of these was the lack of a command lan-)11 2376(. The)1 240 2… | |
+(guage. Although)1 694 1 720 3228 t | |
+10 CW f | |
+(jim)1442 3228 w | |
+10 R f | |
+( direct help with large or repetitive)6 1398(was easy to use for simple editi… | |
+( but this was no)4 640( it provided a command to pass selected text through a… | |
+(more satisfactory than could be expected of a stopgap measure.)9 2527 1 720 3… | |
+10 CW f | |
+(Jim)970 3624 w | |
+10 R f | |
+( interface to text, and)4 877(was written primarily as a vehicle for experime… | |
+(the experiment was successful.)3 1263 1 720 3744 t | |
+10 CW f | |
+(Jim)2041 3744 w | |
+10 R f | |
+(had some spin-offs:)2 804 1 2254 3744 t | |
+10 CW f | |
+(mux)3091 3744 w | |
+10 R f | |
+(, the second window system for the Blit, is)8 1769 1 3271 3744 t | |
+( the terminal part of)4 829(essentially a multiplexed version of)4 1453 2 720… | |
+10 CW f | |
+(jim)3036 3864 w | |
+10 R f | |
+(; and the debugger)3 767 1 3216 3864 t | |
+10 CW f | |
+(pi)4017 3864 w | |
+10 R f | |
+('s user interface)2 654 1 4137 3864 t | |
+6 R f | |
+(20)4791 3814 w | |
+10 R f | |
+(was)4885 3864 w | |
+(closely modeled on)2 785 1 720 3984 t | |
+10 CW f | |
+(jim)1534 3984 w | |
+10 R f | |
+( after a couple of years,)5 955('s. But)1 296 2 1714 3984 t | |
+10 CW f | |
+(jim)2994 3984 w | |
+10 R f | |
+( maintain and limiting)3 896(had become difficult to)3 941 2 3203 3984 t | |
+(to use, and its replacement was overdue.)6 1613 1 720 4104 t | |
+(I began the design of)4 837 1 970 4260 t | |
+10 CW f | |
+(sam)1832 4260 w | |
+10 R f | |
+(by asking)1 386 1 2037 4260 t | |
+10 CW f | |
+(jim)2448 4260 w | |
+10 R f | |
+( was probably a mistake;)4 997( This)1 229( they wanted.)2 537(customers what… | |
+( of the)2 259(the answers were essentially a list of features to be found in … | |
+( for a ``global substitute,'' but no)6 1359( instance, one common request was… | |
+( was looking for a scheme that would sup-)8 1724( I)1 87( it within a cut-and… | |
+( were)1 225( Ideas)1 267( context of some general command language.)6 1852(po… | |
+( line lengths)2 499(not forthcoming, though, particularly given my insistence… | |
+( a region of the screen that)6 1088( worse, I recognized that, since the mous… | |
+(was not an integral number of lines, the command language would best forget a… | |
+(and that meant the command language had to treat the file as a single string,… | |
+( I)1 96( very far and it was time to try building.)9 1710(Eventually, I decid… | |
+( of)1 115(knew that the terminal part could be built easily \320 that part)11… | |
+10 CW f | |
+(jim)3344 5496 w | |
+10 R f | |
+(behaved acceptably well \320 and that)5 1484 1 3556 5496 t | |
+( hard work was going to be in the host part: the file interface, command inte… | |
+(Moreover, I had some ideas about how the architecture of)9 2386 1 720 5736 t | |
+10 CW f | |
+(jim)3140 5736 w | |
+10 R f | |
+(could be improved without destroying its)5 1687 1 3353 5736 t | |
+( I began)2 331( So)1 161( worked out as well as I had hoped.)8 1451(basic str… | |
+( with the way)3 556(by designing the file data structure, starting)6 1770 2 7… | |
+10 CW f | |
+(jim)3076 5976 w | |
+10 R f | |
+(worked \320 comparable to a single structure)6 1754 1 3286 5976 t | |
+(merging)720 6096 w | |
+10 CW f | |
+(Disc)1080 6096 w | |
+10 R f | |
+(and)1347 6096 w | |
+10 CW f | |
+(Buffer)1518 6096 w | |
+10 R f | |
+( cache more general \320 and thinking about how glo-)9 2109(, which I split t… | |
+( answer was clearly that it had to be done in two passes, and the)14 2618( Th… | |
+(transcript-oriented implementation fell out naturally.)4 2106 1 720 6336 t | |
+10 CW f | |
+(Sam)970 6492 w | |
+10 R f | |
+( data structures and algorithms for manipulating text,)7 2190(was written bot… | |
+( retrospect, it turned out)4 973( In)1 138(through the command language and u… | |
+( were several times when I had)6 1247( There)1 284( general.)1 345(well, but … | |
+( command language, in)3 938( The)1 207( proceed with it.)3 655(a large body o… | |
+( beginning)1 429(particular, took almost a year to figure out, but can be imp… | |
+( inventing the)2 568( Similarly,)1 457(of that year\) in a day or two.)7 1199… | |
+10 CW f | |
+(Rasp)2978 7092 w | |
+10 R f | |
+(data structure delayed the connection of the)6 1788 1 3252 7092 t | |
+(host and terminal pieces by another few months.)7 1978 1 720 7212 t | |
+10 CW f | |
+(Sam)2754 7212 w | |
+10 R f | |
+(took about two years to write, although only about)8 2074 1 2966 7212 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 24 24 | |
+%%Page: 25 25 | |
+/saveobj save def | |
+mark | |
+25 pagesetup | |
+10 R f | |
+(- 25 -)2 216 1 2772 480 t | |
+(four months were spent actually working on it.)7 1870 1 720 840 t | |
+( process was unusual: the subset of the protocol that maintains the)11 2661(P… | |
+10 CW f | |
+(Rasp)4363 996 w | |
+10 R f | |
+(was simu-)1 410 1 4630 996 t | |
+(lated, debugged and verified by an automatic protocol analyzer,)8 2568 1 720 … | |
+6 R f | |
+(21)3288 1066 w | |
+10 R f | |
+( rest)1 171( The)1 207( from the start.)3 594(and was bug-free)2 692 4 3376 1… | |
+( keeping menus up to date, was unfortunately too unwieldy for such)11 2757(of… | |
+( in and)2 276(analysis, and was debugged by more traditional methods, primari… | |
+(out of the host.)3 600 1 720 1476 t | |
+10 B f | |
+(Reflections)720 1716 w | |
+10 CW f | |
+(Sam)720 1872 w | |
+10 R f | |
+( of the computing science)4 1078(is essentially the only interactive editor u… | |
+( same could not be said of)6 1055( The)1 207(research center in which I work.… | |
+10 CW f | |
+(jim)3303 1992 w | |
+10 R f | |
+( kept)1 198(; the lack of a command language)6 1359 2 3483 1992 t | |
+( of a user interface as comfortable as)7 1485( union)1 255( The)1 207(some pe… | |
+10 CW f | |
+(jim)3905 2112 w | |
+10 R f | |
+('s with a command lan-)4 955 1 4085 2112 t | |
+(guage as powerful as)3 851 1 720 2232 t | |
+10 CW f | |
+(ed)1600 2232 w | |
+10 R f | |
+( to)1 108('s\262 is essential)2 591 2 1720 2232 t | |
+10 CW f | |
+(sam)2449 2232 w | |
+10 R f | |
+( When)1 293('s success.)1 426 2 2629 2232 t | |
+10 CW f | |
+(sam)3378 2232 w | |
+10 R f | |
+(was first made available to the)5 1242 1 3588 2232 t | |
+10 CW f | |
+(jim)4860 2232 w | |
+10 R f | |
+( the months that followed, even)5 1315( In)1 144( to it within two or three d… | |
+(people who had never adopted)4 1219 1 720 2472 t | |
+10 CW f | |
+(jim)1964 2472 w | |
+10 R f | |
+(started using)1 508 1 2169 2472 t | |
+10 CW f | |
+(sam)2702 2472 w | |
+10 R f | |
+(exclusively.)2907 2472 w | |
+(To be honest,)2 555 1 970 2628 t | |
+10 CW f | |
+(ed)1558 2628 w | |
+10 R f | |
+(still gets occasional use, but usually when something quick needs to be done … | |
+(the overhead of downloading the terminal part of)7 1981 1 720 2748 t | |
+10 CW f | |
+(sam)2729 2748 w | |
+10 R f | |
+( as a `line' editor,)4 709( Also,)1 266(isn't worth the trouble.)3 922 3 2936… | |
+10 CW f | |
+(sam)4860 2748 w | |
+(-d)720 2868 w | |
+10 R f | |
+( it is)2 183( But)1 200( line editor.)2 468(is a bit odd; when using a good o… | |
+(fair to say that)3 598 1 720 2988 t | |
+10 CW f | |
+(sam)1351 2988 w | |
+10 R f | |
+('s command language has displaced)4 1464 1 1531 2988 t | |
+10 CW f | |
+(ed)3027 2988 w | |
+10 R f | |
+('s for most of the complicated editing that has)8 1893 1 3147 2988 t | |
+(kept line editors \(that is, command-driven editors\) with us.)8 2348 1 720 3… | |
+10 CW f | |
+(Sam)970 3264 w | |
+10 R f | |
+('s command language is even fancier than)6 1745 1 1150 3264 t | |
+10 CW f | |
+(ed)2931 3264 w | |
+10 R f | |
+('s, and most)2 508 1 3051 3264 t | |
+10 CW f | |
+(sam)3595 3264 w | |
+10 R f | |
+(customers don't come near to)4 1229 1 3811 3264 t | |
+( think the answer is yes, for two reasons.)8 1625( I)1 83( it need to be so s… | |
+(First, the)1 362 1 970 3540 t | |
+10 I f | |
+(model)1363 3540 w | |
+10 R f | |
+(for)1638 3540 w | |
+10 CW f | |
+(sam)1786 3540 w | |
+10 R f | |
+('s command language is really relatively simple, and certainly simpler than)1… | |
+(that of)1 262 1 720 3660 t | |
+10 CW f | |
+(ed)1011 3660 w | |
+10 R f | |
+( instance, there is only one kind of textual loop in)10 2009(. For)1 217 2 11… | |
+10 CW f | |
+(sam)3385 3660 w | |
+10 R f | |
+(\320 the)1 250 1 3593 3660 t | |
+10 CW f | |
+(x)3871 3660 w | |
+10 R f | |
+(command \320 while)2 772 1 3959 3660 t | |
+10 CW f | |
+(ed)4759 3660 w | |
+10 R f | |
+(has)4907 3660 w | |
+(three \(the)1 381 1 720 3780 t | |
+10 CW f | |
+(g)1128 3780 w | |
+10 R f | |
+( implicit loop over lines in multi-line substi-)7 1792(command, the global fl… | |
+(tutions\). Also,)1 598 1 720 3900 t | |
+10 CW f | |
+(ed)1346 3900 w | |
+10 R f | |
+( within lines, but in)4 784('s substitute command is necessary to make change… | |
+10 CW f | |
+(sam)4392 3900 w | |
+10 R f | |
+(the)4599 3900 w | |
+10 CW f | |
+(s)4748 3900 w | |
+10 R f | |
+(com-)4835 3900 w | |
+(mand is more of a familiar convenience than a necessity;)9 2270 1 720 4020 t | |
+10 CW f | |
+(c)3015 4020 w | |
+10 R f | |
+(and)3100 4020 w | |
+10 CW f | |
+(t)3269 4020 w | |
+10 R f | |
+(can do all the work.)4 790 1 3354 4020 t | |
+( to be about as powerful as)6 1082(Second, given a community that expects an … | |
+10 CW f | |
+(ed)4078 4176 w | |
+10 R f | |
+(, it's hard to see how)5 842 1 4198 4176 t | |
+10 CW f | |
+(sam)720 4296 w | |
+10 R f | |
+( want to do ``global substi-)5 1150( People)1 336( that expectation.)2 713(co… | |
+( sophistication)1 587( The)1 211( fancy changes.)2 629(tutes,'' and most are … | |
+( do global substitutes)3 848(of the command language is really just a veneer … | |
+( always want something more, however, and it's gratifying to be able)11 2831(… | |
+( real power of)3 595( The)1 218(to provide it.)2 542 3 720 4776 t | |
+10 CW f | |
+(sam)2113 4776 w | |
+10 R f | |
+('s command language comes from composability of the operators,)8 2747 1 2293 … | |
+( other words,)2 542( In)1 142( orthogonal to the underlying model.)5 1511(whi… | |
+10 CW f | |
+(sam)3708 4896 w | |
+10 R f | |
+(is not itself complex, but it)5 1118 1 3922 4896 t | |
+( you don't want to do anything complex, you can ignore the complexity)12 2915… | |
+(altogether, and many people do so.)5 1395 1 720 5136 t | |
+(Sometimes I am asked the opposite question: why didn't I just make)11 2801 1 … | |
+10 CW f | |
+(sam)3802 5292 w | |
+10 R f | |
+(a real programmable edi-)3 1026 1 4014 5292 t | |
+( main reason is a matter of taste: I like the editor to be the)14 2400( The)1… | |
+( a wor-)2 284( is one technical reason, though: programmability in editors is… | |
+( usually short-)2 604( editors are used to make particular,)6 1529( Programma… | |
+( things are generally easy)4 1038( If)1 122( providing shorthands for common … | |
+(to do in the first place, shorthands are not as helpful.)10 2197 1 720 5892 t | |
+10 CW f | |
+(Sam)2977 5892 w | |
+10 R f | |
+(makes common editing operations very easy,)5 1848 1 3192 5892 t | |
+( Also,)1 274( to complex editing problems seem commensurate with the problems… | |
+(the ability to edit the)4 840 1 720 6132 t | |
+10 CW f | |
+(sam)1588 6132 w | |
+10 R f | |
+( only takes a mouse button click)6 1300(window makes it easy to repeat comman… | |
+(to execute a command again.)4 1161 1 720 6252 t | |
+8 S1 f | |
+(__________________)720 6900 w | |
+8 R f | |
+(\262 The people who criticize)4 872 1 720 6990 t | |
+8 CW f | |
+(ed)1618 6990 w | |
+8 R f | |
+( and its close relative)4 698(as an interactive program often forget that it)… | |
+8 CW f | |
+(sed)3906 6990 w | |
+4 R f | |
+(7)4050 6950 w | |
+8 R f | |
+(still thrive as pro-)3 583 1 4097 6990 t | |
+( strength of these programs is independent of their convenience for interacti… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 25 25 | |
+%%Page: 26 26 | |
+/saveobj save def | |
+mark | |
+26 pagesetup | |
+10 R f | |
+(- 26 -)2 216 1 2772 480 t | |
+10 B f | |
+(Pros and cons)2 595 1 720 840 t | |
+10 CW f | |
+(Sam)720 996 w | |
+10 R f | |
+( the good things is the idea of struc-)8 1472( Among)1 355( its share of prob… | |
+( were arrived at serendipi-)4 1054( They)1 258(tural regular expressions, who… | |
+(tously when I attempted to distill the essence of)8 1936 1 720 1236 t | |
+10 CW f | |
+(ed)2685 1236 w | |
+10 R f | |
+( global substitution and recognized that)5 1599('s way of doing)3 636 2 2805 … | |
+(the looping command in)3 975 1 720 1356 t | |
+10 CW f | |
+(ed)1720 1356 w | |
+10 R f | |
+(was implicitly imposing a structure \(an array of lines\) on the file.)11 260… | |
+(Another of)1 444 1 970 1512 t | |
+10 CW f | |
+(sam)1448 1512 w | |
+10 R f | |
+( used an editor with a true)6 1097( had never before)3 721( I)1 92('s good th… | |
+( Undo)1 276(undo, but I would never go back now.)7 1545 2 720 1632 t | |
+10 I f | |
+(must)2570 1632 w | |
+10 R f | |
+( exam-)1 278( For)1 193(be done well, but if it is, it can be relied on.)11 1… | |
+( not sure how to write some intricate command, because if you make a)13 2869(… | |
+( from writing)2 545( learned two things about undo)5 1270( I)1 90(mistake, it… | |
+10 CW f | |
+(sam)4456 1872 w | |
+10 R f | |
+(: first, it's)2 404 1 4636 1872 t | |
+( the system)2 458(easy to provide if you design it in from the beginning, and… | |
+(has some subtle properties that may be unfamiliar or error-prone for users.)1… | |
+10 CW f | |
+(Sam)970 2268 w | |
+10 R f | |
+( avoids all fixed-size tables and data)6 1519( it)1 92( Because)1 393('s lack… | |
+(structures,)720 2388 w | |
+10 CW f | |
+(sam)1159 2388 w | |
+10 R f | |
+( More-)1 299( to make global changes to files that some of our other tools ca… | |
+( admit)1 255(over, the design keeps the performance linear when doing such op… | |
+10 CW f | |
+(sam)4650 2508 w | |
+10 R f | |
+(does)4857 2508 w | |
+(get slow when editing a huge file.)6 1351 1 720 2628 t | |
+( is poorly integrated into the surrounding)6 1680( the most obvious is that i… | |
+( design, the user interface in)5 1135( By)1 169(window system.)1 653 3 720 29… | |
+10 CW f | |
+(sam)2704 2904 w | |
+10 R f | |
+(feels almost identical to that of)5 1245 1 2911 2904 t | |
+10 CW f | |
+(mux)4183 2904 w | |
+10 R f | |
+(, but a thick wall)4 677 1 4363 2904 t | |
+(separates text in)2 655 1 720 3024 t | |
+10 CW f | |
+(sam)1406 3024 w | |
+10 R f | |
+(from the programs running in)4 1206 1 1617 3024 t | |
+10 CW f | |
+(mux)2854 3024 w | |
+10 R f | |
+( instance, the `snarf buffer' in)5 1220(. For)1 221 2 3034 3024 t | |
+10 CW f | |
+(sam)4507 3024 w | |
+10 R f | |
+(must be)1 321 1 4719 3024 t | |
+( that in)2 284(maintained separately from)2 1100 2 720 3144 t | |
+10 CW f | |
+(mux)2132 3144 w | |
+10 R f | |
+( is regrettable, but probably necessary given the unusual con-)9 2472(. This)… | |
+(figuration of the system, with a programmable terminal on the far end of an R… | |
+10 CW f | |
+(Sam)970 3420 w | |
+10 R f | |
+( it was written over such a long time, and has)10 1846( But)1 199( it.)1 110(… | |
+( to clean up the code and remove)7 1323(so many new \(to me\) ideas in it, th… | |
+( worst part is in the interconnection of the host)9 1898( The)1 209( problems… | |
+( a redesign for a more conventional window sys-)8 1946(and terminal parts, wh… | |
+( of the connec-)3 598( program must be split in two to use the terminal effec… | |
+( design if performance is to be acceptable.)7 1712(tion forces the separation… | |
+( procedure call protocol driven by the host, emitting only graphics commands,… | |
+( the other hand, if the terminal)6 1284( On)1 184(easy to write but wouldn't … | |
+( simpler file services from the host, regular expression searches would)10 28… | |
+( A)1 131( would be unreasonably slow.)4 1226(require that the terminal read t… | |
+( retrospect, the communications protocol)4 1658( In)1 139(compromise in which… | |
+( designed and verified formally, although I do not know of any tool that can … | |
+(relate the protocol to its implementation.)5 1627 1 720 4860 t | |
+(Not all of)2 385 1 970 5016 t | |
+10 CW f | |
+(sam)1382 5016 w | |
+10 R f | |
+( \(vener-)1 314( Some)1 280('s users are comfortable with its command languag… | |
+( a sort of ``)4 471(able\) people use)2 664 2 720 5136 t | |
+10 CW f | |
+(ed)1855 5136 w | |
+10 R f | |
+(subset'' of)1 431 1 2007 5136 t | |
+10 CW f | |
+(sam)2470 5136 w | |
+10 R f | |
+('s command language, and even ask why)6 1680 1 2650 5136 t | |
+10 CW f | |
+(sam)4362 5136 w | |
+10 R f | |
+('s command)1 498 1 4542 5136 t | |
+(language is not exactly)3 942 1 720 5256 t | |
+10 CW f | |
+(ed)1695 5256 w | |
+10 R f | |
+( course, is that)3 604( reason, of)2 434('s. \(The)1 343 3 1815 5256 t | |
+10 CW f | |
+(sam)3230 5256 w | |
+10 R f | |
+('s model for text does not include new-)7 1630 1 3410 5256 t | |
+( central to)2 399(lines, which are)2 631 2 720 5376 t | |
+10 CW f | |
+(ed)1775 5376 w | |
+10 R f | |
+( the text an array of newlines to the command language would be too)13 2759(.… | |
+( editors, such as)3 647( Some)1 281( mouse.)1 314(much of a break from the se… | |
+10 CW f | |
+(vi)4328 5496 w | |
+10 R f | |
+(, are willing to)3 592 1 4448 5496 t | |
+( difficulty is that)3 706( The)1 219( though.\))1 375(make this break,)2 687 … | |
+10 CW f | |
+(sam)2746 5616 w | |
+10 R f | |
+('s syntax is so close to)5 967 1 2926 5616 t | |
+10 CW f | |
+(ed)3932 5616 w | |
+10 R f | |
+('s that people believe it)4 988 1 4052 5616 t | |
+10 I f | |
+(should)720 5736 w | |
+10 R f | |
+( in hindsight, that making)4 1050( thought, with some justification)4 1318( I… | |
+10 CW f | |
+(sam)4010 5736 w | |
+10 R f | |
+(similar to)1 387 1 4221 5736 t | |
+10 CW f | |
+(ed)4639 5736 w | |
+10 R f | |
+(would)4790 5736 w | |
+( and raised the users' expectations too)6 1573( I may have overstepped)4 1015… | |
+( hard to decide which way to resolve this problem.)9 2019(much. It's)1 430 2 … | |
+(Finally, there is a tradeoff in)5 1187 1 970 6132 t | |
+10 CW f | |
+(sam)2192 6132 w | |
+10 R f | |
+(that was decided by the environment in which it runs:)9 2235 1 2407 6132 t | |
+10 CW f | |
+(sam)4677 6132 w | |
+10 R f | |
+(is a)1 147 1 4893 6132 t | |
+( The)1 220( system there might instead be multiple single-file editors.)8 244… | |
+( choice)1 298( the)1 159( If)1 128(decision was made primarily because starti… | |
+( still choose the multi-file architecture, because it allows groups of)10 270… | |
+( is delightful)2 518( It)1 117( a unit; the usefulness of the multi-file comm… | |
+(to have the source to an entire program available at your fingertips.)11 2683… | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 26 26 | |
+%%Page: 27 27 | |
+/saveobj save def | |
+mark | |
+27 pagesetup | |
+10 R f | |
+(- 27 -)2 216 1 2772 480 t | |
+10 B f | |
+(Acknowledgements)720 840 w | |
+10 R f | |
+(Tom Cargill suggested the idea behind the)6 1699 1 720 996 t | |
+10 CW f | |
+(Rasp)2445 996 w | |
+10 R f | |
+( Wilson and Ken Thompson influ-)5 1384( Norman)1 379(data structure.)1 566 3 … | |
+( improved by comments from Al Aho, Jon Bentley, Chris)9 2392( paper was)2 448… | |
+(Fraser, Gerard Holzmann, Brian Kernighan, Ted Kowalski, Doug McIlroy and Denn… | |
+9 B f | |
+(REFERENCES)720 1476 w | |
+8 R f | |
+( Pike, `The Blit: a multiplexed graphics terminal,')7 1588(1. R.)1 184 2 760 … | |
+8 I f | |
+(AT&T Bell Labs. Tech. J.,)4 835 1 2552 1648 t | |
+8 B f | |
+(63)3407 1648 w | |
+8 R f | |
+(, \(8\), 1607-1631 \(1984\).)3 770 1 3487 1648 t | |
+( Johnson,)1 302(2. L.)1 179 2 760 1784 t | |
+8 I f | |
+(MacWrite,)1261 1784 w | |
+8 R f | |
+(Apple Computer Inc., Cupertino, Calif. 1983.)5 1453 1 1618 1784 t | |
+( Lampson, `Bravo Manual,' in)4 969(3. B.)1 184 2 760 1920 t | |
+8 I f | |
+(Alto User's Handbook,)2 738 1 1933 1920 t | |
+8 R f | |
+( 1979.)1 220(pp. 31-62, Xerox Palo Alto Research Center, Palo Alto, Calif.)9 … | |
+( Teitelman, `A tour through Cedar,')5 1138(4. W.)1 205 2 760 2056 t | |
+8 I f | |
+(IEEE Software,)1 497 1 2123 2056 t | |
+8 B f | |
+(1)2640 2056 w | |
+8 R f | |
+(\(2\), 44-73 \(1984\).)2 570 1 2700 2056 t | |
+( Gutknecht, `Concepts of the text editor Lara,')7 1473(5. J.)1 161 2 760 2192… | |
+8 I f | |
+(Comm. ACM,)1 439 1 2414 2192 t | |
+8 B f | |
+(28)2873 2192 w | |
+8 R f | |
+(, \(9\), 942-960 \(1985\).)3 690 1 2953 2192 t | |
+( Telephone Laboratories,)2 797(6. Bell)1 243 2 760 2328 t | |
+8 I f | |
+(UNIX Programmer's Manual,)2 965 1 1820 2328 t | |
+8 R f | |
+(Holt, Rinehart and Winston, New York 1983.)6 1456 1 2805 2328 t | |
+( W. Kernighan and R. Pike,)5 882(7. B.)1 184 2 760 2464 t | |
+8 I f | |
+(The Unix Programming Environment,)3 1216 1 1846 2464 t | |
+8 R f | |
+(Prentice-Hall, Englewood Cliffs, New Jersey 1984.)5 1637 1 3082 2464 t | |
+(8.)760 2600 w | |
+8 I f | |
+( Programmer's Manual, Research Version, Ninth Edition, Volume 1,)8 2215(Unix … | |
+8 R f | |
+(AT&T Bell Laboratories, Murray)3 1076 1 3964 2600 t | |
+(Hill, New Jersey 1986.)3 733 1 870 2700 t | |
+(9.)760 2836 w | |
+8 I f | |
+( Distribution, Volumes 1 and 2C,)5 1174(Unix Time-Sharing System Programmer's… | |
+8 R f | |
+(University of)1 445 1 4595 2836 t | |
+(California, Berkeley, Calif. 1981.)3 1068 1 870 2936 t | |
+( Pike, `Structural Regular Expressions,')4 1264(10. R.)1 224 2 720 3072 t | |
+8 I f | |
+(Proc. EUUG Spring Conf., Helsinki 1987,)5 1357 1 2229 3072 t | |
+8 R f | |
+(Eur. Unix User's Group, Buntingford, Herts,)5 1433 1 3607 3072 t | |
+(UK 1987.)1 316 1 870 3172 t | |
+( Goldberg,)1 341(11. A.)1 228 2 720 3308 t | |
+8 I f | |
+(Smalltalk-80 \261 The Interactive Programming Environment,)5 1891 1 1309 3308… | |
+8 R f | |
+(Addison-Wesley, Reading, Mass. 1984.)3 1269 1 3220 3308 t | |
+( Thompson, `Regular expression search algorithm,')5 1637(12. K.)1 228 2 720 3… | |
+8 I f | |
+(Comm. ACM,)1 439 1 2605 3444 t | |
+8 B f | |
+(11)3064 3444 w | |
+8 R f | |
+(, \(6\), 419-422 \(1968\).)3 690 1 3144 3444 t | |
+( V. Aho, J. E. Hopcroft and J. D. Ullman,)9 1344(13. A.)1 228 2 720 3580 t | |
+8 I f | |
+( of Computer Algorithms,)3 826(The Design and Analysis)3 802 2 2314 3580 t | |
+8 R f | |
+(Addison-Wesley, Reading, Mass.)2 1075 1 3965 3580 t | |
+(1974.)870 3680 w | |
+( W. Kernighan and D. M. Ritchie,)6 1085(14. B.)1 224 2 720 3816 t | |
+8 I f | |
+(The C Programming Language,)3 1023 1 2049 3816 t | |
+8 R f | |
+(Prentice-Hall, Englewood Cliffs, New Jersey 1978.)5 1637 1 3092 3816 t | |
+( M. Waite, `The cost of lexical analysis,')7 1297(15. W.)1 245 2 720 3952 t | |
+8 I f | |
+(Softw. Pract. Exp.,)2 599 1 2282 3952 t | |
+8 B f | |
+(16)2901 3952 w | |
+8 R f | |
+(, \(5\), 473-488 \(1986\).)3 690 1 2981 3952 t | |
+( W. Fraser, `A generalized text editor,')6 1232(16. C.)1 224 2 720 4088 t | |
+8 I f | |
+(Comm. ACM,)1 439 1 2196 4088 t | |
+8 B f | |
+(23)2655 4088 w | |
+8 R f | |
+(, \(3\), 154-158 \(1980\).)3 690 1 2735 4088 t | |
+( Pike, `Graphics in overlapping bitmap layers,')6 1493(17. R.)1 224 2 720 422… | |
+8 I f | |
+(ACM Trans. on Graph.,)3 765 1 2457 4224 t | |
+8 B f | |
+(2)3242 4224 w | |
+8 R f | |
+(, \(2\) 135-160 \(1983\).)3 670 1 3282 4224 t | |
+( J. Guibas and J. Stolfi, `A language for bitmap manipulation,')10 1990(18. L… | |
+8 I f | |
+(ACM Trans. on Graph.,)3 765 1 2949 4360 t | |
+8 B f | |
+(1)3734 4360 w | |
+8 R f | |
+(, \(3\), 191-214 \(1982\).)3 690 1 3774 4360 t | |
+( Pike, B. Locanthi and J. Reiser, `Hardware/software trade-offs for bitmap gr… | |
+8 I f | |
+(Softw. Pract. Exp.,)2 617 1 4153 4496 t | |
+8 B f | |
+(15)4799 4496 w | |
+8 R f | |
+(, \(2\),)1 161 1 4879 4496 t | |
+(131-151 \(1985\).)1 518 1 870 4596 t | |
+( A. Cargill, `The feel of Pi,')6 886(20. T.)1 219 2 720 4732 t | |
+8 I f | |
+(Winter USENIX Conference Proceedings, Denver 1986,)5 1791 1 1845 4732 t | |
+8 R f | |
+(62-71, USENIX Assoc., El Cerrito, CA.)5 1283 1 3656 4732 t | |
+( J. Holzmann, `Tracing protocols,')4 1098(21. G.)1 228 2 720 4868 t | |
+8 I f | |
+(AT&T Tech. J.,)2 491 1 2066 4868 t | |
+8 B f | |
+(64)2577 4868 w | |
+8 R f | |
+(, \(10\), 2413-2434 \(1985\).)3 810 1 2657 4868 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 27 27 | |
+%%Trailer | |
+done | |
+%%Pages: 27 | |
+%%DocumentFonts: Courier Times-Bold Times-Italic Times-Roman Times-Roman Symbol | |
diff --git a/doc/sam.tut.ms b/doc/sam.tut.ms | |
@@ -0,0 +1,1776 @@ | |
+.de P1 | |
+.KS | |
+.DS | |
+.ft CW | |
+.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n | |
+.. | |
+.de P2 | |
+.ft 1 | |
+.DE | |
+.KE | |
+.. | |
+.de CW | |
+.lg 0 | |
+\%\&\\$3\fB\\$1\fP\&\\$2 | |
+.lg | |
+.. | |
+.de WC | |
+.lg 0 | |
+\%\&\\$3\fI\\$1\fP\&\\$2 | |
+.lg | |
+.. | |
+.TL | |
+A tutorial for the | |
+.CW sam | |
+.B | |
+command language | |
+.AU | |
+Rob Pike | |
+.AI | |
+.MH | |
+.AB | |
+.CW sam | |
+is an interactive text editor with a command language that makes heavy use | |
+of regular expressions. | |
+Although the language is syntactically similar to | |
+.CW ed (1), | |
+the details are interestingly different. | |
+This tutorial introduces the command language, but does not discuss | |
+the screen and mouse interface. | |
+With apologies to those unfamiliar with the Ninth Edition Blit software, | |
+it is assumed that the similarity of | |
+.CW sam | |
+to | |
+.CW mux (9) | |
+at this level makes | |
+.CW sam 's | |
+mouse language easy to learn. | |
+.PP | |
+The | |
+.CW sam | |
+command language applies identically to two environments: | |
+when running | |
+.CW sam | |
+on an ordinary terminal | |
+(\f2via\f1\f1 | |
+.CW sam\ -d ), | |
+and in the command window of a | |
+.I downloaded | |
+.CW sam , | |
+that is, one using the bitmap display and mouse. | |
+.AE | |
+.SH | |
+Introduction | |
+.PP | |
+This tutorial describes the command language of | |
+.CW sam , | |
+an interactive text editor that runs on Blits and | |
+some computers with bitmap displays. | |
+For most editing tasks, the mouse-based editing features | |
+are sufficient, and they are easy to use and to learn. | |
+.PP | |
+The command language is often useful, however, particularly | |
+when making global changes. | |
+Unlike the commands in | |
+.CW ed , | |
+which are necessary to make changes, | |
+.CW sam | |
+commands tend to be used | |
+only for complicated or repetitive editing tasks. | |
+It is in these more involved uses that | |
+the differences between | |
+.CW sam | |
+and other text editors are most evident. | |
+.PP | |
+.CW sam 's | |
+language makes it easy to do some things that other editors, | |
+including programs like | |
+.CW sed | |
+and | |
+.CW awk , | |
+do not handle gracefully, so this tutorial serves partly as a | |
+lesson in | |
+.CW sam 's | |
+manner of manipulating text. | |
+The examples below therefore concentrate entirely on the language, | |
+assuming that facility with the use of the mouse in | |
+.CW sam | |
+is at worst easy to pick up. | |
+In fact, | |
+.CW sam | |
+can be run without the mouse at all (not | |
+.I downloaded ), | |
+by specifying the | |
+.CW -d | |
+flag, and it is this domain that the tutorial | |
+occupies; the command language in these modes | |
+are identical. | |
+.PP | |
+A word to the Unix adept: | |
+although | |
+.CW sam | |
+is syntactically very similar to | |
+.CW ed , | |
+it is fundamentally and deliberately different in design and detailed semantic… | |
+You might use knowledge of | |
+.CW ed | |
+to predict how the substitute command works, | |
+but you'd only be right if you had used some understanding of | |
+.CW sam 's | |
+workings to influence your prediction. | |
+Be particularly careful about idioms. | |
+Idioms form in curious nooks of languages and depend on | |
+undependable peculiarities. | |
+.CW ed | |
+idioms simply don't work in | |
+.CW sam : | |
+.CW 1,$s/a/b/ | |
+makes one substitution in the whole file, not one per line. | |
+.CW sam | |
+has its own idioms. | |
+Much of the purpose of this tutorial is to publish them | |
+and make fluency in | |
+.CW sam | |
+a matter of learning, not cunning. | |
+.PP | |
+The tutorial depends on familiarity with regular expressions, although | |
+some experience with a more traditional Unix editor may be helpful. | |
+To aid readers familiar with | |
+.CW ed , | |
+I have pointed out in square brackets [] some of | |
+the relevant differences between | |
+.CW ed | |
+and | |
+.CW sam . | |
+Read these comments only if you wish | |
+to understand the differences; the lesson is about | |
+.CW sam , | |
+not | |
+.CW sam | |
+.I vs. | |
+.CW ed . | |
+Another typographic convention is that output appears in | |
+.CW "this font, | |
+while typed input appears as | |
+.WC "slanty text. | |
+.PP | |
+Nomenclature: | |
+.CW sam | |
+keeps a copy of the text it is editing. | |
+This copy is called a | |
+.I file . | |
+To avoid confusion, I have called the permanent storage on disc a | |
+.I | |
+Unix file. | |
+.R | |
+.SH | |
+Text | |
+.PP | |
+To get started, we need some text to play with. | |
+Any text will do; try something from | |
+James Gosling's Emacs manual: | |
+.P1 | |
+$ \fIsam -d | |
+a | |
+This manual is organized in a rather haphazard manner. The first | |
+several sections were written hastily in an attempt to provide a | |
+general introduction to the commands in Emacs and to try to show | |
+the method in the madness that is the Emacs command structure. | |
+\&. | |
+.ft | |
+.P2 | |
+.WC "sam -d | |
+starts | |
+.CW sam | |
+running. | |
+The | |
+.CW a | |
+command adds text until a line containing just a period, and sets the | |
+.I | |
+current text | |
+.R | |
+(also called | |
+.I dot ) | |
+to what was typed \(em everything between the | |
+.CW a | |
+and the period. | |
+.CW ed "" [ | |
+would leave dot set to only the last line.] | |
+The | |
+.CW p | |
+command prints the current text: | |
+.P1 | |
+.WC p | |
+This manual is organized in a rather haphazard manner. The first | |
+several sections were written hastily in an attempt to provide a | |
+general introduction to the commands in Emacs and to try to show | |
+the method in the madness that is the Emacs command structure. | |
+.P2 | |
+[Again, | |
+.CW ed | |
+would print only the last line.] | |
+The | |
+.CW a | |
+command adds its text | |
+.I after | |
+dot; the | |
+.CW i | |
+command is like | |
+.CW a, | |
+but adds the text | |
+.I before | |
+dot. | |
+.P1 | |
+.ft I | |
+i | |
+Introduction | |
+\&. | |
+p | |
+.ft | |
+Introduction | |
+.P2 | |
+There is also a | |
+.CW c | |
+command that changes (replaces) the current text, | |
+and | |
+.CW d | |
+that deletes it; these are illustrated below. | |
+.PP | |
+To see all the text, we can specify what text to print; | |
+for the moment, suffice it to say that | |
+.WC 0,$ | |
+specifies the entire file. | |
+.CW ed "" [ | |
+users would probably type | |
+.WC 1,$ , | |
+which in practice is the same thing, but see below.] | |
+.P1 | |
+.WC 0,$p | |
+Introduction | |
+This manual is organized in a rather haphazard manner. The first | |
+several sections were written hastily in an attempt to provide a | |
+general introduction to the commands in Emacs and to try to show | |
+the method in the madness that is the Emacs command structure. | |
+.P2 | |
+Except for the | |
+.CW w | |
+command described below, | |
+.I all | |
+commands, | |
+including | |
+.CW p , | |
+set dot to the text they touch. | |
+Thus, | |
+.CW a | |
+and | |
+.CW i | |
+set dot to the new text, | |
+.CW p | |
+to the text printed, and so on. | |
+Similarly, all commands | |
+(except | |
+.CW w ) | |
+by default operate on the current | |
+text [unlike | |
+.CW ed , | |
+for which some commands (such as | |
+.CW g ) | |
+default to the entire file]. | |
+.PP | |
+Things are not going to get very interesting until we can | |
+set dot arbitrarily. | |
+This is done by | |
+.I addresses , | |
+which specify a piece of the file. | |
+The address | |
+.CW 1 , | |
+for example, sets dot to the first line of the file. | |
+.P1 | |
+.WC 1p | |
+Introduction | |
+.WC c | |
+.WC Preamble | |
+.WC . | |
+.P2 | |
+The | |
+.CW c | |
+command didn't need to specify dot; the | |
+.CW p | |
+left it on line one. | |
+It's therefore easy to delete the first line utterly; | |
+the last command left dot set to line one: | |
+.P1 | |
+.WC d | |
+.WC 1p | |
+This manual is organized in a rather haphazard manner. The first | |
+.P2 | |
+(Line numbers change | |
+to reflect changes to the file.) | |
+.PP | |
+The address \f(CW/\f2text\f(CW/\f1 | |
+sets dot to the first appearance of | |
+.I text , | |
+after dot. | |
+.CW ed "" [ | |
+matches the first line containing | |
+.I text .] | |
+If | |
+.I text | |
+is not found, the search restarts at the beginning of the file | |
+and continues until dot. | |
+.P1 | |
+.WC /Emacs/p | |
+Emacs | |
+.P2 | |
+It's difficult to indicate typographically, but in this example no newline app… | |
+after | |
+.CW Emacs : | |
+the text to be printed is the string | |
+.CW Emacs ', ` | |
+exactly. | |
+(The final | |
+.CW p | |
+may be left off \(em it is the default command. | |
+When downloaded, however, the default is instead to select the text, | |
+to highlight it, | |
+and to make it visible by moving the window on the file if necessary. | |
+Thus, | |
+.CW /Emacs/ | |
+indicates on the display the next occurrence of the text.) | |
+.PP | |
+Imagine we wanted to change the word | |
+.CW haphazard | |
+to | |
+.CW thoughtless . | |
+Obviously, what's needed is another | |
+.CW c | |
+command, but the method used so far to insert text includes a newline. | |
+The syntax for including text without newlines is to surround the | |
+text with slashes (which is the same as the syntax for | |
+text searches, but what is going on should be clear from context). | |
+The text must appear immediately after the | |
+.CW c | |
+(or | |
+.CW a | |
+or | |
+.CW i ). | |
+Given this, it is easy to make the required change: | |
+.P1 | |
+.WC /haphazard/c/thoughtless/ | |
+1p | |
+This manual is organized in a rather thoughtless manner. The first | |
+.P2 | |
+[Changes can always be done with a | |
+.CW c | |
+command, even if the text is smaller than a line]. | |
+You'll find that this way of providing text to commands is much | |
+more common than is the multiple-lines syntax. | |
+If you want to include a slash | |
+.CW / | |
+in the text, just precede it with a backslash | |
+.CW \e , | |
+and use a backslash to protect a backslash itself. | |
+.P1 | |
+.WC /Emacs/c/Emacs\e\e360/ | |
+.WC 4p | |
+general introduction to the commands in Emacs\e360 and to try to show | |
+.P2 | |
+We could also make this particular change by | |
+.P1 | |
+.WC /Emacs/a/\e\e360/ | |
+.P2 | |
+.PP | |
+This is as good a place as any to introduce the | |
+.CW u | |
+command, which undoes the last command. | |
+A second | |
+.CW u | |
+will undo the penultimate command, and so on. | |
+.P1 | |
+.WC u | |
+.WC 4p | |
+general introduction to the commands in Emacs and to try to show | |
+.WC u | |
+.WC 3p | |
+This manual is organized in a rather haphazard manner. The first | |
+.P2 | |
+Undoing can only back up; there is no way to undo a previous | |
+.CW u . | |
+.SH | |
+Addresses | |
+.PP | |
+We've seen the simplest forms of addresses, but there is more | |
+to learn before we can get too much further. | |
+An address selects a region in the file \(em a substring \(em | |
+and therefore must define the beginning and the end of a region. | |
+Thus, the address | |
+.CW 13 | |
+selects from the beginning of line thirteen to the end of line thirteen, and | |
+.CW /Emacs/ | |
+selects from the beginning of the word | |
+.CW Emacs ' ` | |
+to the end. | |
+.PP | |
+Addresses may be combined with a comma: | |
+.P1 | |
+13,15 | |
+.P2 | |
+selects lines thirteen through fifteen. The definition of the comma | |
+operator is to select from the beginning of the left hand address (the | |
+beginning of line 13) to the end of the right hand address (the | |
+end of line 15). | |
+.PP | |
+A few special simple addresses come in handy: | |
+.CW . | |
+(a period) represents dot, the current text, | |
+.CW 0 | |
+(line zero) selects the null string at the beginning of the file, and | |
+.CW $ | |
+selects the null string at the end of the file | |
+[not the last line of the file]. | |
+Therefore, | |
+.P1 | |
+0,13 | |
+.P2 | |
+selects from the beginning of the file to the end of line thirteen, | |
+.P1 | |
+\&.,$ | |
+.P2 | |
+selects from the beginning of the current text to the end of the file, and | |
+.P1 | |
+0,$ | |
+.P2 | |
+selects the whole file [that is, a single string containing the whole file, | |
+not a list of all the lines in the file]. | |
+.PP | |
+These are all | |
+.I absolute | |
+addresses: they refer to specific places in the file. | |
+.CW sam | |
+also has relative addresses, which depend | |
+on the value of dot, | |
+and in fact we have already seen one form: | |
+.CW /Emacs/ | |
+finds the first occurrence of | |
+.CW Emacs | |
+searching forwards from dot. | |
+Which occurrence of | |
+.CW Emacs | |
+it finds depends on the value of dot. | |
+What if you wanted the first occurrence | |
+.CW before | |
+dot? Just precede the pattern with a minus sign, which reverses the direction | |
+of the search: | |
+.P1 | |
+-/Emacs/ | |
+.P2 | |
+In fact, the complete syntax for forward searching is | |
+.P1 | |
++/Emacs/ | |
+.P2 | |
+but the plus sign is the default, and in practice is rarely used. | |
+Here is an example that includes it for clarity: | |
+.P1 | |
+0+/Emacs/ | |
+.P2 | |
+selects the first occurrence of | |
+.CW Emacs | |
+in the file; read it as ``go to line 0, then search forwards for | |
+.CW Emacs .'' | |
+Since the | |
+.CW + | |
+is optional, this can be written | |
+.CW 0/Emacs/ . | |
+Similarly, | |
+.P1 | |
+$-/Emacs/ | |
+.P2 | |
+finds the last occurrence in the file, so | |
+.P1 | |
+0/Emacs/,$-/Emacs/ | |
+.P2 | |
+selects the text from the first to last | |
+.CW Emacs , | |
+inclusive. | |
+Slightly more interesting: | |
+.P1 | |
+/Emacs/+/Emacs/ | |
+.P2 | |
+(there is an implicit | |
+.CW .+ | |
+at the beginning) selects the second | |
+.CW Emacs | |
+following dot. | |
+.PP | |
+Line numbers may also be relative. | |
+.P1 | |
+-2 | |
+.P2 | |
+selects the second previous line, and | |
+.P1 | |
++5 | |
+.P2 | |
+selects the fifth following line (here the plus sign is obligatory). | |
+.PP | |
+Since addresses may select (and dot may be) more than one line, | |
+we need a definition of `previous' and `following:' | |
+`previous' means | |
+.I | |
+before the beginning | |
+.R | |
+of dot, and `following' | |
+means | |
+.I | |
+after the end | |
+.R | |
+of dot. | |
+For example, if the file contains \fBA\fIAA\fBA\f1, | |
+with dot set to the middle two | |
+.CW A 's | |
+(the slanting characters), | |
+.CW -/A/ | |
+sets dot to the first | |
+.CW A , | |
+and | |
+.CW +/A/ | |
+sets dot to the last | |
+.CW A . | |
+Except under odd circumstances (such as when the only occurrence of the | |
+text in the file is already the current text), the text selected by a | |
+search will be disjoint from dot. | |
+.PP | |
+To select the | |
+.CW "troff -ms | |
+paragraph containing dot, however long it is, use | |
+.P1 | |
+-/.PP/,/.PP/-1 | |
+.P2 | |
+which will include the | |
+.CW .PP | |
+that begins the paragraph, and exclude the one that ends it. | |
+.PP | |
+When typing relative line number addresses, the default number is | |
+.CW 1 , | |
+so the above could be written slightly more simply: | |
+.P1 | |
+-/.PP/,/.PP/- | |
+.P2 | |
+.PP | |
+What does the address | |
+.CW +1-1 | |
+or the equivalent | |
+.CW +- | |
+mean? It looks like it does nothing, but recall that dot need not be a | |
+complete line of text. | |
+.CW +1 | |
+selects the line after the end of the current text, and | |
+.CW -1 | |
+selects the line before the beginning. Therefore | |
+.CW +1-1 | |
+selects the line before the line after the end of dot, that is, | |
+the complete line containing the end of dot. | |
+We can use this construction to expand a selection to include a complete line, | |
+say the first line in the file containing | |
+.CW Emacs : | |
+.P1 | |
+.WC 0/Emacs/+-p | |
+general introduction to the commands in Emacs and to try to show | |
+.P2 | |
+The address | |
+.CW +- | |
+is an idiom. | |
+.SH | |
+Loops | |
+.PP | |
+Above, we changed one occurrence of | |
+.CW Emacs | |
+to | |
+.CW Emacs\e360 , | |
+but if the name of the editor is really changing, it would be useful | |
+to change | |
+.I all | |
+instances of the name in a single command. | |
+.CW sam | |
+provides a command, | |
+.CW x | |
+(extract), for just that job. | |
+The syntax is | |
+\f(CWx/\f2pattern\f(CW/\f2command\f1. | |
+For each occurrence of the pattern in the selected text, | |
+.CW x | |
+sets dot to the occurrence and runs command. | |
+For example, to change | |
+.CW Emacs | |
+to | |
+.CW vi, | |
+.P1 | |
+.WC 0,$x/Emacs/c/vi/ | |
+.WC 0,$p | |
+This manual is organized in a rather haphazard manner. The first | |
+several sections were written hastily in an attempt to provide a | |
+general introduction to the commands in vi and to try to show | |
+the method in the madness that is the vi command structure. | |
+.P2 | |
+This | |
+works by subdividing the current text | |
+.CW 0,$ "" ( | |
+\(em the whole file) into appearances of its textual argument | |
+.CW Emacs ), ( | |
+and then running the command that follows | |
+.CW c/vi/ ) ( | |
+with dot set to the text. | |
+We can read this example as, ``find all occurrences of | |
+.CW Emacs | |
+in the file, and for each one, | |
+set the current text to the occurrence and run the command | |
+.CW c/vi/ , | |
+which will replace the current text by | |
+.CW vi. '' | |
+[This command is somewhat similar to | |
+.CW ed 's | |
+.CW g | |
+command. The differences will develop below, but note that the | |
+default address, as always, is dot rather than the whole file.] | |
+.PP | |
+A single | |
+.CW u | |
+command is sufficient to undo an | |
+.CW x | |
+command, regardless of how many individual changes the | |
+.CW x | |
+makes. | |
+.P1 | |
+.WC u | |
+.WC 0,$p | |
+This manual is organized in a rather haphazard manner. The first | |
+several sections were written hastily in an attempt to provide a | |
+general introduction to the commands in Emacs and to try to show | |
+the method in the madness that is the Emacs command structure. | |
+.P2 | |
+.PP | |
+Of course, | |
+.CW c | |
+is not the only command | |
+.CW x | |
+can run. An | |
+.CW a | |
+command can be used to put proprietary markings on | |
+.CW Emacs : | |
+.P1 | |
+.WC 0,$x/Emacs/a/{TM}/ | |
+.WC /Emacs/+-p | |
+general introduction to the commands in Emacs{TM} and to try to show | |
+.P2 | |
+[There is no way to see the changes as they happen, as in | |
+.CW ed 's | |
+.CW g/Emacs/s//&{TM}/p ; | |
+see the section on Multiple Changes, below.] | |
+.PP | |
+The | |
+.CW p | |
+command is also useful when driven by an | |
+.CW x , | |
+but be careful that you say what you mean; | |
+.P1 | |
+.WC 0,$x/Emacs/p | |
+EmacsEmacs | |
+.P2 | |
+since | |
+.CW x | |
+sets dot to the text in the slashes, printing only that text | |
+is not going to be very | |
+informative. But the command that | |
+.CW x | |
+runs can contain addresses. For example, if we want to print all | |
+lines containing | |
+.CW Emacs , | |
+just use | |
+.CW +- : | |
+.P1 | |
+.WC 0,$x/Emacs/+-p | |
+general introduction to the commands in Emacs{TM} and to try to show | |
+the method in the madness that is the Emacs{TM} command structure. | |
+.P2 | |
+Finally, let's restore the state of the file with another | |
+.CW x | |
+command, and make use of a handy shorthand: | |
+a comma in an address has its left side default to | |
+.CW 0 , | |
+and its right side default to | |
+.CW $ , | |
+so the easy-to-type address | |
+.CW , | |
+refers to the whole file: | |
+.P1 | |
+.WC ",x/Emacs/ /{TM}/d | |
+.WC ,p | |
+This manual is organized in a rather haphazard manner. The first | |
+several sections were written hastily in an attempt to provide a | |
+general introduction to the commands in Emacs and to try to show | |
+the method in the madness that is the Emacs command structure. | |
+.P2 | |
+Notice what this | |
+.CW x | |
+does: for each occurrence of Emacs, | |
+find the | |
+.CW {TM} | |
+that follows, and delete it. | |
+.PP | |
+The `text' | |
+.CW sam | |
+accepts | |
+for searches in addresses and in | |
+.CW x | |
+commands is not simple text, but rather | |
+.I regular\ expressions. | |
+Unix has several distinct interpretations of regular expressions. | |
+The form used by | |
+.CW sam | |
+is that of | |
+.CW regexp (6), | |
+including parentheses | |
+.CW () | |
+for grouping and an `or' operator | |
+.CW | | |
+for matching strings in parallel. | |
+.CW sam | |
+also matches the character sequence | |
+.CW \en | |
+with a newline character. | |
+Replacement text, such as used in the | |
+.CW a | |
+and | |
+.CW c | |
+commands, is still plain text, but the sequence | |
+.CW \en | |
+represents newline in that context, too. | |
+.PP | |
+Here is an example. Say we wanted to double space the document, that is, | |
+turn every newline into two newlines. | |
+The following all do the job: | |
+.P1 | |
+.WC ",x/\en/ a/\en/ | |
+.WC ",x/\en/ c/\en\en/ | |
+.WC ",x/$/ a/\en/ | |
+.WC ",x/^/ i/\en/ | |
+.P2 | |
+The last example is slightly different, because it puts a newline | |
+.I before | |
+each line; the other examples place it after. | |
+The first two examples manipulate newlines directly | |
+[something outside | |
+.CW ed 's | |
+ken]; the last two | |
+use regular expressions: | |
+.CW $ | |
+is the empty string at the end of a line, while | |
+.CW ^ | |
+is the empty string at the beginning. | |
+.PP | |
+These solutions all have a possible drawback: if there is already a blank line | |
+(that is, two consecutive newlines), they make it much larger (four | |
+consecutive newlines). | |
+A better method is to extend every group of newlines by one: | |
+.P1 | |
+.WC ",x/\en+/ a/\en/ | |
+.P2 | |
+The regular expression operator | |
+.CW + | |
+means `one or more;' | |
+.CW \en+ | |
+is identical to | |
+.CW \en\en* . | |
+Thus, this example | |
+takes every sequence of newlines and adds another | |
+to the end. | |
+.PP | |
+A more common example is indenting a block of text by a tab stop. | |
+The following all work, | |
+although the first is arguably the cleanest (the blank text in slashes is a ta… | |
+.P1 | |
+.WC ",x/^/a/ / | |
+.WC ",x/^/c/ / | |
+.WC ",x/.*\en/i/ / | |
+.P2 | |
+The last example uses the pattern (idiom, really) | |
+.CW .*\en | |
+to match lines: | |
+.CW .* | |
+matches the longest possible string of non-newline characters. | |
+Taking initial tabs away is just as easy: | |
+.P1 | |
+.WC ",x/^ /d | |
+.P2 | |
+In these examples I have specified an address (the whole file), but | |
+in practice commands like these are more likely to be run without | |
+an address, using the value of dot set by selecting text with the mouse. | |
+.SH | |
+Conditionals | |
+.PP | |
+The | |
+.CW x | |
+command is a looping construct: | |
+for each match of a regular expression, | |
+it extracts (sets dot to) the match and runs a command. | |
+.CW sam | |
+also has a conditional, | |
+.CW g : | |
+\f(CWg/\f2pattern\f(CW/\f2command\f1 | |
+runs the command if dot contains a match of the pattern | |
+.I | |
+without changing the value of dot. | |
+.R | |
+The inverse, | |
+.CW v , | |
+runs the command if dot does | |
+.I not | |
+contain a match of the pattern. | |
+(The letters | |
+.CW g | |
+and | |
+.CW v | |
+are historical and have no mnemonic significance. You might | |
+think of | |
+.CW g | |
+as `guard.') | |
+.CW ed "" [ | |
+users should read the above definitions very carefully; the | |
+.CW g | |
+command in | |
+.CW sam | |
+is fundamentally different from that in | |
+.CW ed .] | |
+Here is an example of the difference between | |
+.CW x | |
+and | |
+.CW g: | |
+.P1 | |
+,x/Emacs/c/vi/ | |
+.P2 | |
+changes each occurrence of the word | |
+.CW Emacs | |
+in the file to the word | |
+.CW vi , | |
+but | |
+.P1 | |
+,g/Emacs/c/vi/ | |
+.P2 | |
+changes the | |
+.I "whole file | |
+to | |
+.CW vi | |
+if there is the word | |
+.CW Emacs | |
+anywhere in the file. | |
+.PP | |
+Neither of these commands is particularly interesting in isolation, | |
+but they are valuable when combined with | |
+.CW x | |
+and with themselves. | |
+.SH | |
+Composition | |
+.PP | |
+One way to think about the | |
+.CW x | |
+command is that, given a selection (a value of dot) | |
+it iterates through interesting subselections (values of dot within). | |
+In other words, it takes a piece of text and cuts it into smaller pieces. | |
+But the text that it cuts up may already be a piece cut by a previous | |
+.CW x | |
+command or selected by a | |
+.CW g . | |
+.CW sam 's | |
+most interesting property is the ability to define a sequence of commands | |
+to perform a particular task.\(dg | |
+.FS | |
+\(dg | |
+The obvious analogy with shell pipelines is only partially valid, | |
+because the individual | |
+.CW sam | |
+commands are all working on the same text; it is only how the text is | |
+sliced up that is changing. | |
+.FE | |
+A simple example is to change all occurrences of | |
+.CW Emacs | |
+to | |
+.CW emacs ; | |
+certainly the command | |
+.P1 | |
+.WC ",x/Emacs/ c/emacs/ | |
+.P2 | |
+will work, but we can use an | |
+.CW x | |
+command to save retyping most of the word | |
+.CW Emacs : | |
+.P1 | |
+.WC ",x/Emacs/ x/E/ c/e/ | |
+.P2 | |
+(Blanks can be used | |
+to separate commands on a line to make them easier to read.) | |
+What this command does is find all occurrences of | |
+.CW Emacs | |
+.CW ,x/Emacs/ ), ( | |
+and then | |
+.I | |
+with dot set to that text, | |
+.R | |
+find all occurrences of the letter | |
+.CW E | |
+.CW x/E/ ), ( | |
+and then | |
+.I | |
+with dot set to that text, | |
+.R | |
+run the command | |
+.CW c/e/ | |
+to change the character to lower case. | |
+Note that the address for the command \(em the whole file, specified by a comma | |
+\(em is only given to the leftmost | |
+piece of the command; the rest of the pieces have dot set for them by | |
+the execution of the pieces to their left. | |
+.PP | |
+As another simple example, consider a problem | |
+solved above: printing all lines in the file containing the word | |
+.CW Emacs: | |
+.P1 | |
+.WC ",x/.*\en/ g/Emacs/p | |
+general introduction to the commands in Emacs and to try to show | |
+the method in the madness that is the Emacs command structure. | |
+.P2 | |
+This command says to break the file into lines | |
+.CW ,x/.*\en/ ), ( | |
+and for each line that contains the string | |
+.CW Emacs | |
+.CW g/Emacs/ ), ( | |
+run the command | |
+.CW p | |
+with dot set to the line (not the match of | |
+.CW Emacs ), | |
+which prints the line. | |
+To save typing, because | |
+.CW .*\en | |
+is a common pattern in | |
+.CW x | |
+commands, | |
+if the | |
+.CW x | |
+is followed immediately by a space, the pattern | |
+.CW .*\en | |
+is assumed. | |
+Therefore, the above could be written more succinctly: | |
+.P1 | |
+.WC ",x g/Emacs/p | |
+.P2 | |
+The solution we used before was | |
+.P1 | |
+.WC ,x/Emacs/+-p | |
+.P2 | |
+which runs the command | |
+.CW +-p | |
+with dot set to each match of | |
+.CW Emacs | |
+in the file (recall that the idiom | |
+.CW +-p | |
+prints the line containing the end of dot). | |
+.PP | |
+The two commands usually produce the same result | |
+(the | |
+.CW +-p | |
+form will print a line twice if it contains | |
+.CW Emacs | |
+twice). Which is better? | |
+.CW ,x/Emacs/+-p | |
+is easier to type and will be much faster if the file is large and | |
+there are few occurrences of the string, but it is really an odd special case. | |
+.CW ",x/.*\en/ g/Emacs/p | |
+is slower \(em it breaks each line out separately, then examines | |
+it for a match \(em but is conceptually cleaner, and generalizes more easily. | |
+For example, consider the following piece of the Emacs manual: | |
+.P1 | |
+command name="append-to-file", key="[unbound]" | |
+Takes the contents of the current buffer and appends it to the | |
+named file. If the file doesn't exist, it will be created. | |
+ | |
+command name="apropos", key="ESC-?" | |
+Prompts for a keyword and then prints a list of those commands | |
+whose short description contains that keyword. For example, | |
+if you forget which commands deal with windows, just type | |
+"@b[ESC-?]@t[window]@b[ESC]". | |
+ | |
+\&\f2and so on\f(CW | |
+.P2 | |
+This text consists of groups of non-empty lines, with a simple format | |
+for the text within each group. | |
+Imagine that we wanted to find the description of the `apropos' | |
+command. | |
+The problem is to break the file into individual descriptions, | |
+and then to find the description of `apropos' and to print it. | |
+The solution is straightforward: | |
+.P1 | |
+.WC ,x/(.+\en)+/\ g/command\ name="apropos"/p | |
+command name="apropos", key="ESC-?" | |
+Prompts for a keyword and then prints a list of those commands | |
+whose short description contains that keyword. For example, | |
+if you forget which commands deal with windows, just type | |
+"@b[ESC-?]@t[window]@b[ESC]". | |
+.P2 | |
+The regular expression | |
+.CW (.+\en)+ | |
+matches one or more lines with one or more characters each, that is, | |
+the text between blank lines, so | |
+.CW ,x/(.+\en)+/ | |
+extracts each description; then | |
+.CW g/command\ name="apropos"/ | |
+selects the description for `apropos' and | |
+.CW p | |
+prints it. | |
+.PP | |
+Imagine that we had a C program containing the variable | |
+.CW n , | |
+but we wanted to change it to | |
+.CW num . | |
+This command is a first cut: | |
+.P1 | |
+.WC ",x/n/ c/num/ | |
+.P2 | |
+but is obviously flawed: it will change all | |
+.CW n 's | |
+in the file, not just the | |
+.I identifier | |
+.CW n . | |
+A better solution is to use an | |
+.CW x | |
+command to extract the identifiers, and then use | |
+.CW g | |
+to find the | |
+.CW n 's: | |
+.P1 | |
+.WC ",x/[a-zA-Z_][a-zA-Z_0-9]*/ g/n/ v/../ c/num/ | |
+.P2 | |
+It looks awful, but it's fairly easy to understand when read | |
+left to right. | |
+A C identifier is an alphabetic or underscore followed by zero or more | |
+alphanumerics or underscores, that is, matches of the regular expression | |
+.CW [a-zA-Z_][a-zA-Z_0-9]* . | |
+The | |
+.CW g | |
+command selects those identifiers containing | |
+.CW n , | |
+and the | |
+.CW v | |
+is a trick: it rejects those identifiers containing more than one | |
+character. Hence the | |
+.CW c/num/ | |
+applies only to free-standing | |
+.CW n 's. | |
+.PP | |
+There is still a problem here: | |
+we don't want to change | |
+.CW n 's | |
+that are part of the character constant | |
+.CW \en . | |
+There is a command | |
+.CW y , | |
+complementary to | |
+.CW x , | |
+that is just what we need: | |
+\f(CWy/\f2pattern\f(CW/\f2command\f1 | |
+runs the command on the pieces of text | |
+.I between | |
+matches of the pattern; | |
+if | |
+.CW x | |
+selects, | |
+.CW y | |
+rejects. | |
+Here is the final command: | |
+.P1 | |
+.WC ",y/\e\en/ x/[a-zA-Z_][a-zA-Z_0-9]*/ g/n/ v/../ c/num/ | |
+.P2 | |
+The | |
+.CW y/\e\en/ | |
+(with backslash doubled to make it a literal character) | |
+removes the two-character sequence | |
+.CW \en | |
+from consideration, so the rest of the command will not touch it. | |
+There is more we could do here; for example, another | |
+.CW y | |
+could be prefixed to protect comments in the code. | |
+I won't elaborate the example any further, but you should have | |
+an idea of the way in which the looping and conditional commands | |
+in | |
+.CW sam | |
+may be composed to do interesting things. | |
+.SH | |
+Grouping | |
+.PP | |
+There is another way to arrange commands. | |
+By enclosing them in brace brackets | |
+.CW {} , | |
+commands may be applied in parallel. | |
+This example uses the | |
+.CW = | |
+command, which reports the line and character numbers of dot, | |
+together with | |
+.CW p , | |
+to report on appearances of | |
+.CW Emacs | |
+in our original file: | |
+.P1 | |
+.WC ,p | |
+This manual is organized in a rather haphazard manner. The first | |
+several sections were written hastily in an attempt to provide a | |
+general introduction to the commands in Emacs and to try to show | |
+the method in the madness that is the Emacs command structure. | |
+.ft I | |
+,x/Emacs/{ | |
+ = | |
+ +-p | |
+} | |
+.ft | |
+3; #171,#176 | |
+general introduction to the commands in Emacs and to try to show | |
+4; #234,#239 | |
+the method in the madness that is the Emacs command structure. | |
+.P2 | |
+(The number before the semicolon is the line number; | |
+the numbers beginning with | |
+.CW # | |
+are character numbers.) | |
+As a more interesting example, consider changing all occurrences of | |
+.CW Emacs | |
+to | |
+.CW vi | |
+and vice versa. We can type | |
+.P1 | |
+.ft I | |
+,x/Emacs|vi/{ | |
+ g/Emacs/ c/vi/ | |
+ g/vi/ c/Emacs/ | |
+} | |
+.ft | |
+.P2 | |
+or even | |
+.P1 | |
+.ft I | |
+,x/[a-zA-Z]+/{ | |
+ g/Emacs/ v/....../ c/vi/ | |
+ g/vi/ v/.../ c/Emacs/ | |
+} | |
+.ft | |
+.P2 | |
+to make sure we don't change strings embedded in words. | |
+.SH | |
+Multiple Changes | |
+.PP | |
+You might wonder why, once | |
+.CW Emacs | |
+has been changed to | |
+.CW vi | |
+in the above example, | |
+the second command in the braces doesn't put it back again. | |
+The reason is that the commands are run in parallel: | |
+within any top-level | |
+.CW sam | |
+command, all changes to the file refer to the state of the file | |
+before any of the changes in that command are made. | |
+After all the changes have been determined, they are all applied | |
+simultaneously. | |
+.PP | |
+This means, as mentioned, that commands within a compound | |
+command see the state of the file before any of the changes apply. | |
+This method of evaluation makes some things easier (such as the exchange of | |
+.CW Emacs | |
+and | |
+.CW vi ), | |
+and some things harder. | |
+For instance, it is impossible to use a | |
+.CW p | |
+command to print the changes as they happen, | |
+because they haven't happened when the | |
+.CW p | |
+is executed. | |
+An indirect ramification is that changes must occur in forward | |
+order through the file, | |
+and must not overlap. | |
+.SH | |
+Unix | |
+.PP | |
+.CW sam | |
+has a few commands to connect to Unix processes. | |
+The simplest is | |
+.CW ! , | |
+which runs the command with input and output connected to the terminal. | |
+.P1 | |
+.WC !date | |
+Wed May 28 23:25:21 EDT 1986 | |
+! | |
+.P2 | |
+(When downloaded, the input is connected to | |
+.CW /dev/null | |
+and only the first few lines of output are printed; | |
+any overflow is stored in | |
+.CW $HOME/sam.err .) | |
+The final | |
+.CW ! | |
+is a prompt to indicate when the command completes. | |
+.PP | |
+Slightly more interesting is | |
+.CW > , | |
+which provides the current text as standard input to the Unix command: | |
+.P1 | |
+.WC "1,2 >wc | |
+ 2 22 131 | |
+! | |
+.P2 | |
+The complement of | |
+.CW > | |
+is, naturally, | |
+.CW < : | |
+it replaces the current text with the standard output of the Unix command: | |
+.P1 | |
+.WC "1 <date | |
+! | |
+.WC 1p | |
+Wed May 28 23:26:44 EDT 1986 | |
+.P2 | |
+The last command is | |
+.CW | , | |
+which is a combination of | |
+.CW < | |
+and | |
+.CW > : | |
+the current text is provided as standard input to the Unix command, | |
+and the Unix command's standard output is collected and used to | |
+replace the original text. | |
+For example, | |
+.P1 | |
+.WC ",| sort | |
+.P2 | |
+runs | |
+.CW sort (1) | |
+on the file, sorting the lines of the text lexicographically. | |
+Note that | |
+.CW < , | |
+.CW > | |
+and | |
+.CW | | |
+are | |
+.CW sam | |
+commands, not Unix shell operators. | |
+.PP | |
+The next example converts all appearances of | |
+.CW Emacs | |
+to upper case using | |
+.CW tr (1): | |
+.P1 | |
+.WC ",x/Emacs/ | tr a-z A-Z | |
+.P2 | |
+.CW tr | |
+is run once for each occurrence of | |
+.CW Emacs . | |
+Of course, you could do this example more efficiently with a simple | |
+.CW c | |
+command, but here's a trickier one: | |
+given a Unix mail box as input, | |
+convert all the | |
+.CW Subject | |
+headers to distinct fortunes: | |
+.P1 | |
+.WC ",x/^Subject:.*\en/ x/[^:]*\en/ < /usr/games/fortune | |
+.P2 | |
+(The regular expression | |
+.CW [^:] | |
+refers to any character | |
+.I except | |
+.CW : | |
+and newline; the negation operator | |
+.CW ^ | |
+excludes newline from the list of characters.) | |
+Again, | |
+.CW /usr/games/fortune | |
+is run once for each | |
+.CW Subject | |
+line, so each | |
+.CW Subject | |
+line is changed to a different fortune. | |
+.SH | |
+A few other text commands | |
+.PP | |
+For completeness, I should mention three other commands that | |
+manipulate text. The | |
+.CW m | |
+command moves the current text to after the text specified by the | |
+(obligatory) address after the command. | |
+Thus | |
+.P1 | |
+.WC "/Emacs/+- m 0 | |
+.P2 | |
+moves the next line containing | |
+.CW Emacs | |
+to the beginning of the file. | |
+Similarly, | |
+.CW t | |
+(another historic character) copies the text: | |
+.P1 | |
+.WC "/Emacs/+- t 0 | |
+.P2 | |
+would make, at the beginning of the file, a copy of the next line | |
+containing | |
+.CW Emacs . | |
+.PP | |
+The third command is more interesting: it makes substitutions. | |
+Its syntax is | |
+\f(CWs/\f2pattern\f(CW/\f2replacement\f(CW/\f1. | |
+Within the current text, it finds the first occurrence of | |
+the pattern and replaces it by the replacement text, | |
+leaving dot set to the entire address of the substitution. | |
+.P1 | |
+.WC 1p | |
+This manual is organized in a rather haphazard manner. The first | |
+.WC s/haphazard/thoughtless/ | |
+.WC p | |
+This manual is organized in a rather thoughtless manner. The first | |
+.P2 | |
+Occurrences of the character | |
+.CW & | |
+in the replacement text stand for the text matching the pattern. | |
+.P1 | |
+.WC s/T/"&&&&"/ | |
+.WC p | |
+"TTTT"his manual is organized in a rather thoughtless manner. The first | |
+.P2 | |
+There are two variants. The first is that a number may be specified | |
+after the | |
+.CW s , | |
+to indicate which occurrence of the pattern to substitute; the default | |
+is the first. | |
+.P1 | |
+.WC s2/is/was/ | |
+.WC p | |
+"TTTT"his manual was organized in a rather thoughtless manner. The first | |
+.P2 | |
+The second is that suffixing a | |
+.CW g | |
+(global) causes replacement of all occurrences, not just the first. | |
+.P1 | |
+.WC s/[a-zA-Z]/x/g | |
+.WC p | |
+"xxxx"xxx xxxxxx xxx xxxxxxxxx xx x xxxxxx xxxxxxxxxxx xxxxxxx xxx xxxxx | |
+.P2 | |
+Notice that in all these examples | |
+dot is left | |
+set to the entire line. | |
+.PP | |
+[The substitute command is vital to | |
+.CW ed, | |
+because it is the only way to make changes within a line. | |
+It is less valuable in | |
+.CW sam , | |
+in which the concept of a line is much less important. | |
+For example, many | |
+.CW ed | |
+substitution idioms are handled well by | |
+.CW sam 's | |
+basic commands. Consider the commands | |
+.P1 | |
+s/good/bad/ | |
+s/good// | |
+s/good/& bye/ | |
+.P2 | |
+which are equivalent in | |
+.CW sam | |
+to | |
+.P1 | |
+/good/c/bad/ | |
+/good/d | |
+/good/a/ bye/ | |
+.P2 | |
+and for which the context search is likely unnecessary because the desired | |
+text is already dot. | |
+Also, beware this | |
+.CW ed | |
+idiom: | |
+.P1 | |
+1,$s/good/bad/ | |
+.P2 | |
+which changes the first | |
+.CW good | |
+on each line; the same command in | |
+.CW sam | |
+will only change the first one in the whole file. | |
+The correct | |
+.CW sam | |
+version is | |
+.P1 | |
+,x s/good/bad/ | |
+.P2 | |
+but what is more likely meant is | |
+.P1 | |
+,x/good/ c/bad/ | |
+.P2 | |
+.CW sam | |
+operates under different rules.] | |
+.SH | |
+Files | |
+.PP | |
+So far, we have only been working with a single file, | |
+but | |
+.CW sam | |
+is a multi-file editor. | |
+Only one file may be edited at a time, but | |
+it is easy to change which file is the `current' file for editing. | |
+To see how to do this, we need a | |
+.CW sam | |
+with a few files; | |
+the easiest way to do this is to start it | |
+with a list of Unix file names to edit. | |
+.P1 | |
+$ \fIecho *.ms\f(CW | |
+conquest.ms death.ms emacs.ms famine.ms slaughter.ms | |
+$ \fIsam -d *.ms\f(CW | |
+ -. conquest.ms | |
+.P2 | |
+(I'm sorry the Horsemen don't appear in liturgical order.) | |
+The line printed by | |
+.CW sam | |
+is an indication that the Unix file | |
+.CW conquest.ms | |
+has been read, and is now the current file. | |
+.CW sam | |
+does not read the Unix file until | |
+the associated | |
+.CW sam | |
+file becomes current. | |
+.PP | |
+The | |
+.CW n | |
+command prints the names of all the files: | |
+.P1 | |
+.WC n | |
+ -. conquest.ms | |
+ - death.ms | |
+ - emacs.ms | |
+ - famine.ms | |
+ - slaughter.ms | |
+.P2 | |
+This list is also available in the menu on mouse button 3. | |
+The command | |
+.CW f | |
+tells the name of just the current file: | |
+.P1 | |
+.WC f | |
+ -. conquest.ms | |
+.P2 | |
+The characters to the left of the file name encode helpful information about | |
+the file. | |
+The minus sign becomes a plus sign if the file has a window open, and an | |
+asterisk if more than one is open. | |
+The period (another meaning of dot) identifies the current file. | |
+The leading blank changes to an apostrophe if the file is different | |
+from the contents of the associated Unix file, as far as | |
+.CW sam | |
+knows. | |
+This becomes evident if we make a change. | |
+.P1 | |
+.WC 1d | |
+.WC f | |
+\&'-. conquest.ms | |
+.P2 | |
+If the file is restored by an undo command, the apostrophe disappears. | |
+.P1 | |
+.WC u | |
+.WC f | |
+ -. conquest.ms | |
+.P2 | |
+The file name may be changed by providing a new name with the | |
+.CW f | |
+command: | |
+.P1 | |
+.CW "f pestilence.ms | |
+\&'-. pestilence.ms | |
+.P2 | |
+.WC f | |
+prints the new status of the file, | |
+that is, it changes the name if one is provided, and prints the | |
+name regardless. | |
+A file name change may also be undone. | |
+.P1 | |
+.WC u | |
+.WC f | |
+ -. conquest.ms | |
+.P2 | |
+.PP | |
+When | |
+.CW sam | |
+is downloaded, the current file may be changed simply by selecting | |
+the desired file from the menu (selecting the same file subsequently | |
+cycles through the windows opened on the file). | |
+Otherwise, the | |
+.CW b | |
+command can be used to choose the desired file:\(dg | |
+.FS | |
+\(dg A bug prevents the | |
+.CW b | |
+command from working when downloaded. | |
+Because the menu is more convenient anyway, and | |
+because the method | |
+of choosing files from the command language is slated to change, | |
+the bug hasn't been fixed. | |
+.FE | |
+.P1 | |
+.WC "b emacs.ms | |
+ -. emacs.ms | |
+.P2 | |
+Again, | |
+.CW sam | |
+prints the name (actually, executes an implicit | |
+.CW f | |
+command) because the Unix file | |
+.CW emacs.ms | |
+is being read for the first time. | |
+It is an error to ask for a file | |
+.CW sam | |
+doesn't know about, but the | |
+.CW B | |
+command will prime | |
+.CW sam 's | |
+menu with a new file, and make it current. | |
+.P1 | |
+.WC "b flood.pic | |
+?no such file `flood.pic' | |
+.WC "B flood.pic | |
+ -. flood.pic | |
+.WC n | |
+ - conquest.ms | |
+ - death.ms | |
+ - emacs.ms | |
+ - famine.ms | |
+ -. flood.pic | |
+ - slaughter.ms | |
+.P2 | |
+Both | |
+.CW b | |
+and | |
+.CW B | |
+will accept a list of file names. | |
+.CW b | |
+simply takes the first file in the list, but | |
+.CW B | |
+loads them all. | |
+The list may be typed on one line \(em | |
+.P1 | |
+.WC "B devil.tex satan.tex 666.tex emacs.tex | |
+.P2 | |
+\(em or generated by a Unix command \(em | |
+.P1 | |
+.WC "B <echo *.tex | |
+.P2 | |
+The latter form requires a Unix command; | |
+.CW sam | |
+does not understand the shell file name metacharacters, so | |
+.CW "B *.tex | |
+attempts to load a single file named | |
+.CW *.tex . | |
+(The | |
+.CW < | |
+form is of course derived from | |
+.CW sam 's | |
+.CW < | |
+command.) | |
+.CW echo | |
+is not the only useful command to run subservient to | |
+.CW B ; | |
+for example, | |
+.P1 | |
+.WC "B <grep -l Emacs * | |
+.P2 | |
+will load only those files containing the string | |
+.CW Emacs . | |
+Finally, a special case: a | |
+.CW B | |
+with no arguments creates an empty, nameless file within | |
+.CW sam . | |
+.PP | |
+The complement of | |
+.CW B | |
+is | |
+.CW D : | |
+.P1 | |
+.WC "D devil.tex satan.tex 666.tex emacs.tex | |
+.P2 | |
+eradicates the files from | |
+.CW sam 's | |
+memory (not from the Unix machine's disc). | |
+.CW D | |
+without any file names removes the current file from | |
+.CW sam . | |
+.PP | |
+There are three other commands that relate the current file | |
+to Unix files. | |
+The | |
+.CW w | |
+command writes the file to disc; | |
+without arguments, it writes the entire file to the Unix file associated | |
+with the current file in | |
+.CW sam | |
+(it is the only command whose default address is not dot). | |
+Of course, you can specify an address to be written, | |
+and a different file name, with the obvious syntax: | |
+.P1 | |
+.WC "1,2w /tmp/revelations | |
+/tmp/revelations: #44 | |
+.P2 | |
+.CW sam | |
+responds with the file name and the number of characters written to the file. | |
+The | |
+.CW write | |
+command on the button 3 menu is identical in function to an unadorned | |
+.CW w | |
+command. | |
+.PP | |
+The other two commands, | |
+.CW e | |
+and | |
+.CW r , | |
+read data from Unix files. | |
+The | |
+.CW e | |
+command clears out the current file, | |
+reads the data from the named file (or uses the current file's old name if | |
+none is explicitly provided), and sets the file name. | |
+It's much like a | |
+.CW B | |
+command, but puts the information in the current file instead of a new one. | |
+.CW e | |
+without any file name is therefore an easy way to refresh | |
+.CW sam 's | |
+copy of a Unix file. | |
+[Unlike in | |
+.CW ed , | |
+.CW e | |
+doesn't complain if the file is modified. The principle is not | |
+to protect against things that can be undone if wrong.] | |
+Since its job is to replace the whole text, | |
+.CW e | |
+never takes an address. | |
+.PP | |
+The | |
+.CW r | |
+command is like | |
+.CW e , | |
+but it doesn't clear the file: | |
+the text in the Unix file replaces dot, or the specified text if an | |
+address is given. | |
+.P1 | |
+.WC "r emacs.ms | |
+.P2 | |
+has essentially the effect of | |
+.P1 | |
+.WC "<cat emacs.ms | |
+.P2 | |
+The commands | |
+.CW r | |
+and | |
+.CW w | |
+will set the name of the file if the current file has no name already defined; | |
+.CW e | |
+sets the name even if the file already has one. | |
+.PP | |
+There is a command, analogous to | |
+.CW x , | |
+that iterates over files instead of pieces of text: | |
+.CW X | |
+(capital | |
+.CW x ). | |
+The syntax is easy; it's just like that of | |
+.CW x | |
+\(em \f(CWX/\f2pattern\f(CW/\f2command\f1. | |
+(The complementary command is | |
+.CW Y , | |
+analogous to | |
+.CW y .) | |
+The effect is to run the command in each file whose menu entry | |
+(that is, whose line printed by an | |
+.CW f | |
+command) matches the pattern. | |
+For example, since an apostrophe identifies modified files, | |
+.P1 | |
+.WC "X/'/ w | |
+.P2 | |
+writes the changed files out to disc. | |
+Here is a longer example: find all uses of a particular variable | |
+in the C source files: | |
+.P1 | |
+.WC "X/\e.c$/ ,x/variable/+-p | |
+.P2 | |
+We can use an | |
+.CW f | |
+command to identify which file the variable appears in: | |
+.P1 | |
+.ft I | |
+X/\e.c$/ ,g/variable/ { | |
+ f | |
+ ,x/variable/+-{ | |
+ = | |
+ p | |
+ } | |
+} | |
+.ft | |
+.P2 | |
+Here, the | |
+.CW g | |
+command guarantees that only the names of files containing the variable | |
+will be printed (but beware that | |
+.CW sam | |
+may confuse matters by printing the names of files it reads in during | |
+the command). | |
+The | |
+.CW = | |
+command shows where in the file the variable appears, and the | |
+.CW p | |
+command prints the line. | |
+.PP | |
+The | |
+.CW D | |
+command is handy as the target of an | |
+.CW X . | |
+This example deletes from the menu all C files that do not contain | |
+a particular variable: | |
+.P1 | |
+.WC "X/\e.c$/ ,v/variable/ D | |
+.P2 | |
+If no pattern is provided for the | |
+.CW X , | |
+the command (which defaults to | |
+.CW f ) | |
+is run in all files, so | |
+.P1 | |
+.WC "X D | |
+.P2 | |
+cleans | |
+.CW sam | |
+up for a fresh start. | |
+.PP | |
+But rather than working any further, let's stop now: | |
+.P1 | |
+.WC q | |
+$ | |
+.P2 | |
+.fi | |
+.PP | |
+Some of the file manipulating commands can be undone: | |
+undoing a | |
+.CW f , | |
+.CW e , | |
+or | |
+.CW r | |
+restores the previous state of the file, | |
+but | |
+.CW w , | |
+.CW B | |
+and | |
+.CW D | |
+are irrevocable. | |
+And, of course, so is | |
+.CW q . | |
diff --git a/doc/se.ps b/doc/se.ps | |
@@ -0,0 +1,1487 @@ | |
+%!PS | |
+%%Version: 3.3.2 | |
+%%DocumentFonts: (atend) | |
+%%Pages: (atend) | |
+%%EndComments | |
+% | |
+% Version 3.3.2 prologue for troff files. | |
+% | |
+ | |
+/#copies 1 store | |
+/aspectratio 1 def | |
+/formsperpage 1 def | |
+/landscape false def | |
+/linewidth .3 def | |
+/magnification 1 def | |
+/margin 0 def | |
+/orientation 0 def | |
+/resolution 720 def | |
+/rotation 1 def | |
+/xoffset 0 def | |
+/yoffset 0 def | |
+ | |
+/roundpage true def | |
+/useclippath true def | |
+/pagebbox [0 0 612 792] def | |
+ | |
+/R /Times-Roman def | |
+/I /Times-Italic def | |
+/B /Times-Bold def | |
+/BI /Times-BoldItalic def | |
+/H /Helvetica def | |
+/HI /Helvetica-Oblique def | |
+/HB /Helvetica-Bold def | |
+/HX /Helvetica-BoldOblique def | |
+/CW /Courier def | |
+/CO /Courier def | |
+/CI /Courier-Oblique def | |
+/CB /Courier-Bold def | |
+/CX /Courier-BoldOblique def | |
+/PA /Palatino-Roman def | |
+/PI /Palatino-Italic def | |
+/PB /Palatino-Bold def | |
+/PX /Palatino-BoldItalic def | |
+/Hr /Helvetica-Narrow def | |
+/Hi /Helvetica-Narrow-Oblique def | |
+/Hb /Helvetica-Narrow-Bold def | |
+/Hx /Helvetica-Narrow-BoldOblique def | |
+/KR /Bookman-Light def | |
+/KI /Bookman-LightItalic def | |
+/KB /Bookman-Demi def | |
+/KX /Bookman-DemiItalic def | |
+/AR /AvantGarde-Book def | |
+/AI /AvantGarde-BookOblique def | |
+/AB /AvantGarde-Demi def | |
+/AX /AvantGarde-DemiOblique def | |
+/NR /NewCenturySchlbk-Roman def | |
+/NI /NewCenturySchlbk-Italic def | |
+/NB /NewCenturySchlbk-Bold def | |
+/NX /NewCenturySchlbk-BoldItalic def | |
+/ZD /ZapfDingbats def | |
+/ZI /ZapfChancery-MediumItalic def | |
+/S /S def | |
+/S1 /S1 def | |
+/GR /Symbol def | |
+ | |
+/inch {72 mul} bind def | |
+/min {2 copy gt {exch} if pop} bind def | |
+ | |
+/show {show} bind def % so later references don't bind | |
+/widthshow {widthshow} bind def | |
+/stringwidth {stringwidth} bind def | |
+ | |
+/setup { | |
+ counttomark 2 idiv {def} repeat pop | |
+ | |
+ landscape {/orientation 90 orientation add def} if | |
+ /scaling 72 resolution div def | |
+ linewidth setlinewidth | |
+ 1 setlinecap | |
+ | |
+ pagedimensions | |
+ xcenter ycenter translate | |
+ orientation rotation mul rotate | |
+ width 2 div neg height 2 div translate | |
+ xoffset inch yoffset inch neg translate | |
+ margin 2 div dup neg translate | |
+ magnification dup aspectratio mul scale | |
+ scaling scaling scale | |
+ | |
+ addmetrics | |
+ 0 0 moveto | |
+} def | |
+ | |
+/pagedimensions { | |
+ useclippath userdict /gotpagebbox known not and { | |
+ /pagebbox [clippath pathbbox newpath] def | |
+ roundpage currentdict /roundpagebbox known and {roundpagebbox}… | |
+ } if | |
+ pagebbox aload pop | |
+ 4 -1 roll exch 4 1 roll 4 copy | |
+ landscape {4 2 roll} if | |
+ sub /width exch def | |
+ sub /height exch def | |
+ add 2 div /xcenter exch def | |
+ add 2 div /ycenter exch def | |
+ userdict /gotpagebbox true put | |
+} def | |
+ | |
+/addmetrics { | |
+ /Symbol /S null Sdefs cf | |
+ /Times-Roman /S1 StandardEncoding dup length array copy S1defs cf | |
+} def | |
+ | |
+/pagesetup { | |
+ /page exch def | |
+ currentdict /pagedict known currentdict page known and { | |
+ page load pagedict exch get cvx exec | |
+ } if | |
+} def | |
+ | |
+/decodingdefs [ | |
+ {counttomark 2 idiv {y moveto show} repeat} | |
+ {neg /y exch def counttomark 2 idiv {y moveto show} repeat} | |
+ {neg moveto {2 index stringwidth pop sub exch div 0 32 4 -1 roll width… | |
+ {neg moveto {spacewidth sub 0.0 32 4 -1 roll widthshow} repeat} | |
+ {counttomark 2 idiv {y moveto show} repeat} | |
+ {neg setfunnytext} | |
+] def | |
+ | |
+/setdecoding {/t decodingdefs 3 -1 roll get bind def} bind def | |
+ | |
+/w {neg moveto show} bind def | |
+/m {neg dup /y exch def moveto} bind def | |
+/done {/lastpage where {pop lastpage} if} def | |
+ | |
+/f { | |
+ dup /font exch def findfont exch | |
+ dup /ptsize exch def scaling div dup /size exch def scalefont setfont | |
+ linewidth ptsize mul scaling 10 mul div setlinewidth | |
+ /spacewidth ( ) stringwidth pop def | |
+} bind def | |
+ | |
+/changefont { | |
+ /fontheight exch def | |
+ /fontslant exch def | |
+ currentfont [ | |
+ 1 0 | |
+ fontheight ptsize div fontslant sin mul fontslant cos div | |
+ fontheight ptsize div | |
+ 0 0 | |
+ ] makefont setfont | |
+} bind def | |
+ | |
+/sf {f} bind def | |
+ | |
+/cf { | |
+ dup length 2 idiv | |
+ /entries exch def | |
+ /chtab exch def | |
+ /newencoding exch def | |
+ /newfont exch def | |
+ | |
+ findfont dup length 1 add dict | |
+ /newdict exch def | |
+ {1 index /FID ne {newdict 3 1 roll put}{pop pop} ifelse} forall | |
+ | |
+ newencoding type /arraytype eq {newdict /Encoding newencoding put} if | |
+ | |
+ newdict /Metrics entries dict put | |
+ newdict /Metrics get | |
+ begin | |
+ chtab aload pop | |
+ 1 1 entries {pop def} for | |
+ newfont newdict definefont pop | |
+ end | |
+} bind def | |
+ | |
+% | |
+% A few arrays used to adjust reference points and character widths in some | |
+% of the printer resident fonts. If square roots are too high try changing | |
+% the lines describing /radical and /radicalex to, | |
+% | |
+% /radical [0 -75 550 0] | |
+% /radicalex [-50 -75 500 0] | |
+% | |
+% Move braceleftbt a bit - default PostScript character is off a bit. | |
+% | |
+ | |
+/Sdefs [ | |
+ /bracketlefttp [201 500] | |
+ /bracketleftbt [201 500] | |
+ /bracketrighttp [-81 380] | |
+ /bracketrightbt [-83 380] | |
+ /braceleftbt [203 490] | |
+ /bracketrightex [220 -125 500 0] | |
+ /radical [0 0 550 0] | |
+ /radicalex [-50 0 500 0] | |
+ /parenleftex [-20 -170 0 0] | |
+ /integral [100 -50 500 0] | |
+ /infinity [10 -75 730 0] | |
+] def | |
+ | |
+/S1defs [ | |
+ /underscore [0 80 500 0] | |
+ /endash [7 90 650 0] | |
+] def | |
+% | |
+% Tries to round clipping path dimensions, as stored in array pagebbox, so they | |
+% match one of the known sizes in the papersizes array. Lower left coordinates | |
+% are always set to 0. | |
+% | |
+ | |
+/roundpagebbox { | |
+ 7 dict begin | |
+ /papersizes [8.5 inch 11 inch 14 inch 17 inch] def | |
+ | |
+ /mappapersize { | |
+ /val exch def | |
+ /slop .5 inch def | |
+ /diff slop def | |
+ /j 0 def | |
+ 0 1 papersizes length 1 sub { | |
+ /i exch def | |
+ papersizes i get val sub abs | |
+ dup diff le {/diff exch def /j i def} {pop} ifelse | |
+ } for | |
+ diff slop lt {papersizes j get} {val} ifelse | |
+ } def | |
+ | |
+ pagebbox 0 0 put | |
+ pagebbox 1 0 put | |
+ pagebbox dup 2 get mappapersize 2 exch put | |
+ pagebbox dup 3 get mappapersize 3 exch put | |
+ end | |
+} bind def | |
+ | |
+%%EndProlog | |
+%%BeginSetup | |
+mark | |
+/linewidth 0.5 def | |
+/#copies 1 store | |
+/landscape false def | |
+/resolution 720 def | |
+% | |
+% Encoding vector and redefinition of findfont for the ISO Latin1 standard. | |
+% The 18 characters missing from ROM based fonts on older printers are noted | |
+% below. | |
+% | |
+ | |
+/ISOLatin1Encoding [ | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /space | |
+ /exclam | |
+ /quotedbl | |
+ /numbersign | |
+ /dollar | |
+ /percent | |
+ /ampersand | |
+ /quoteright | |
+ /parenleft | |
+ /parenright | |
+ /asterisk | |
+ /plus | |
+ /comma | |
+ /minus | |
+ /period | |
+ /slash | |
+ /zero | |
+ /one | |
+ /two | |
+ /three | |
+ /four | |
+ /five | |
+ /six | |
+ /seven | |
+ /eight | |
+ /nine | |
+ /colon | |
+ /semicolon | |
+ /less | |
+ /equal | |
+ /greater | |
+ /question | |
+ /at | |
+ /A | |
+ /B | |
+ /C | |
+ /D | |
+ /E | |
+ /F | |
+ /G | |
+ /H | |
+ /I | |
+ /J | |
+ /K | |
+ /L | |
+ /M | |
+ /N | |
+ /O | |
+ /P | |
+ /Q | |
+ /R | |
+ /S | |
+ /T | |
+ /U | |
+ /V | |
+ /W | |
+ /X | |
+ /Y | |
+ /Z | |
+ /bracketleft | |
+ /backslash | |
+ /bracketright | |
+ /asciicircum | |
+ /underscore | |
+ /quoteleft | |
+ /a | |
+ /b | |
+ /c | |
+ /d | |
+ /e | |
+ /f | |
+ /g | |
+ /h | |
+ /i | |
+ /j | |
+ /k | |
+ /l | |
+ /m | |
+ /n | |
+ /o | |
+ /p | |
+ /q | |
+ /r | |
+ /s | |
+ /t | |
+ /u | |
+ /v | |
+ /w | |
+ /x | |
+ /y | |
+ /z | |
+ /braceleft | |
+ /bar | |
+ /braceright | |
+ /asciitilde | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /dotlessi | |
+ /grave | |
+ /acute | |
+ /circumflex | |
+ /tilde | |
+ /macron | |
+ /breve | |
+ /dotaccent | |
+ /dieresis | |
+ /.notdef | |
+ /ring | |
+ /cedilla | |
+ /.notdef | |
+ /hungarumlaut | |
+ /ogonek | |
+ /caron | |
+ /space | |
+ /exclamdown | |
+ /cent | |
+ /sterling | |
+ /currency | |
+ /yen | |
+ /brokenbar % missing | |
+ /section | |
+ /dieresis | |
+ /copyright | |
+ /ordfeminine | |
+ /guillemotleft | |
+ /logicalnot | |
+ /hyphen | |
+ /registered | |
+ /macron | |
+ /degree % missing | |
+ /plusminus % missing | |
+ /twosuperior % missing | |
+ /threesuperior % missing | |
+ /acute | |
+ /mu % missing | |
+ /paragraph | |
+ /periodcentered | |
+ /cedilla | |
+ /onesuperior % missing | |
+ /ordmasculine | |
+ /guillemotright | |
+ /onequarter % missing | |
+ /onehalf % missing | |
+ /threequarters % missing | |
+ /questiondown | |
+ /Agrave | |
+ /Aacute | |
+ /Acircumflex | |
+ /Atilde | |
+ /Adieresis | |
+ /Aring | |
+ /AE | |
+ /Ccedilla | |
+ /Egrave | |
+ /Eacute | |
+ /Ecircumflex | |
+ /Edieresis | |
+ /Igrave | |
+ /Iacute | |
+ /Icircumflex | |
+ /Idieresis | |
+ /Eth % missing | |
+ /Ntilde | |
+ /Ograve | |
+ /Oacute | |
+ /Ocircumflex | |
+ /Otilde | |
+ /Odieresis | |
+ /multiply % missing | |
+ /Oslash | |
+ /Ugrave | |
+ /Uacute | |
+ /Ucircumflex | |
+ /Udieresis | |
+ /Yacute % missing | |
+ /Thorn % missing | |
+ /germandbls | |
+ /agrave | |
+ /aacute | |
+ /acircumflex | |
+ /atilde | |
+ /adieresis | |
+ /aring | |
+ /ae | |
+ /ccedilla | |
+ /egrave | |
+ /eacute | |
+ /ecircumflex | |
+ /edieresis | |
+ /igrave | |
+ /iacute | |
+ /icircumflex | |
+ /idieresis | |
+ /eth % missing | |
+ /ntilde | |
+ /ograve | |
+ /oacute | |
+ /ocircumflex | |
+ /otilde | |
+ /odieresis | |
+ /divide % missing | |
+ /oslash | |
+ /ugrave | |
+ /uacute | |
+ /ucircumflex | |
+ /udieresis | |
+ /yacute % missing | |
+ /thorn % missing | |
+ /ydieresis | |
+] def | |
+ | |
+/NewFontDirectory FontDirectory maxlength dict def | |
+ | |
+% | |
+% Apparently no guarantee findfont is defined in systemdict so the obvious | |
+% | |
+% systemdict /findfont get exec | |
+% | |
+% can generate an error. So far the only exception is a VT600 (version 48.0). | |
+% | |
+ | |
+userdict /@RealFindfont known not { | |
+ userdict begin | |
+ /@RealFindfont systemdict begin /findfont load end def | |
+ end | |
+} if | |
+ | |
+/findfont { | |
+ dup NewFontDirectory exch known not { | |
+ dup | |
+ %dup systemdict /findfont get exec % not always in syst… | |
+ dup userdict /@RealFindfont get exec | |
+ dup /Encoding get StandardEncoding eq { | |
+ dup length dict begin | |
+ {1 index /FID ne {def}{pop pop} ifelse} forall | |
+ /Encoding ISOLatin1Encoding def | |
+ currentdict | |
+ end | |
+ /DummyFontName exch definefont | |
+ } if | |
+ NewFontDirectory 3 1 roll put | |
+ } if | |
+ NewFontDirectory exch get | |
+} bind def | |
+ | |
+setup | |
+2 setdecoding | |
+%%EndSetup | |
+%%Page: 1 1 | |
+/saveobj save def | |
+mark | |
+1 pagesetup | |
+12 B f | |
+(Structural Regular Expressions)2 1622 1 2069 1230 t | |
+10 I f | |
+(Rob Pike)1 363 1 2698 1470 t | |
+10 R f | |
+(AT&T Bell Laboratories)2 993 1 2383 1650 t | |
+(Murray Hill, New Jersey 07974)4 1267 1 2246 1770 t | |
+10 I f | |
+(ABSTRACT)2643 2150 w | |
+10 R f | |
+(The current)1 465 1 1330 2410 t | |
+9 R f | |
+(UNIX)1821 2410 w | |
+10 R f | |
+( the built\255in concept of a)5 999(\256 text processing tools are weakened b… | |
+( describe the `shape' of files when the typical)8 1908( is a simple notation … | |
+( regular)1 316( Using)1 298( is regular expressions.)3 942( notation)1 361( T… | |
+( files has interesting)3 841(expressions to describe the structure in additio… | |
+(applications, and yields elegant methods for dealing with some problems the c… | |
+( are composed, the result is)5 1157( operations using these expressions)4 146… | |
+(reminiscent of shell pipelines.)3 1199 1 1080 3130 t | |
+10 B f | |
+(The Peter\255On\255Silicon Problem)2 1299 1 720 3490 t | |
+10 R f | |
+( model,)1 301(In the traditional)2 666 2 970 3646 t | |
+9 R f | |
+(UNIX)1961 3646 w | |
+10 R f | |
+(text files are arrays of lines, and all the familiar tools)10 2120 1 2212 364… | |
+10 S1 f | |
+(\320)4358 3646 w | |
+10 CW f | |
+(grep)4484 3646 w | |
+10 R f | |
+(,)4724 3646 w | |
+10 CW f | |
+(sort)4775 3646 w | |
+10 R f | |
+(,)5015 3646 w | |
+10 CW f | |
+(awk)720 3766 w | |
+10 R f | |
+(, etc.)1 197 1 900 3766 t | |
+10 S1 f | |
+(\320)1128 3766 w | |
+10 R f | |
+( of)1 113( output)1 287( The)1 211(expect arrays of lines as input.)5 1244 4 … | |
+10 CW f | |
+(ls)3144 3766 w | |
+10 R f | |
+(\(regardless of options\) is a list of files, one)8 1746 1 3294 3766 t | |
+(per line, that may be selected by tools such as)9 1825 1 720 3886 t | |
+10 CW f | |
+(grep)2570 3886 w | |
+10 R f | |
+(:)2810 3886 w | |
+10 CW f | |
+(ls \255l /usr/ken/bin | grep 'rws.*root')5 2220 1 1080 4066 t | |
+10 R f | |
+(\(I assume that the reader is familiar with the)8 1803 1 720 4246 t | |
+9 R f | |
+(UNIX)2551 4246 w | |
+10 R f | |
+( model is powerful, but it is also pervasive,)8 1769(tools.\) The)1 464 2 280… | |
+( Many)1 298(sometimes overly so.)2 877 2 720 4366 t | |
+9 R f | |
+(UNIX)1933 4366 w | |
+10 R f | |
+( more general, and more useful, if they could be)9 2041(programs would be)2 8… | |
+( example,)1 400( For)1 201(applied to arbitrarily structured input.)4 1549 3 … | |
+10 CW f | |
+(diff)2907 4486 w | |
+10 R f | |
+( C)1 105(could in principle report differences at the)6 1751 2 3184 4486 t | |
+( if the interesting quantum of information isn't a line, most of)11 2537( But… | |
+(the tools \(including)2 804 1 720 4726 t | |
+10 CW f | |
+(diff)1562 4726 w | |
+10 R f | |
+( solution so the line\255)4 873( perverting the)2 608( Worse,)1 348(\) don't … | |
+(oriented tools can implement it often obscures the original problem.)9 2714 1… | |
+( consider the problem of turning)5 1320(To see how a line oriented view of te… | |
+( input is an array of blank and non\255blank characters, like this:)11 2451( … | |
+10 CW f | |
+(#######)1320 5252 w | |
+(#########)1260 5322 w | |
+(#### #####)1 660 1 1200 5392 t | |
+( #)1 180(#### ####)1 720 2 1140 5462 t | |
+(#### #####)1 840 1 1140 5532 t | |
+(#### ###)1 840 1 1080 5602 t | |
+(######## #####)1 960 1 1080 5672 t | |
+(#### #########)1 840 1 1080 5742 t | |
+( ####)1 300( #)1 180(#### #)1 360 3 1080 5812 t | |
+( ##)1 300( ###)1 300(## #)1 240 3 1080 5882 t | |
+( ###)1 300(### #)1 480 2 1080 5952 t | |
+(### ##)1 540 1 1080 6022 t | |
+(## #)1 360 1 1140 6092 t | |
+(# ####)1 480 1 1200 6162 t | |
+(# #)1 180 1 1200 6232 t | |
+(## # ##)2 660 1 1080 6302 t | |
+10 R f | |
+(The output is to be statements in a language for laying out integrated circui… | |
+10 CW f | |
+(rect minx miny maxx maxy)4 1440 1 1080 6662 t | |
+10 R f | |
+( simplify the problem slightly,)4 1247( To)1 169(The statements encode where … | |
+(the coordinate system has)3 1032 1 720 6962 t | |
+10 I f | |
+(x)1778 6962 w | |
+10 R f | |
+(positive to the right and)4 954 1 1848 6962 t | |
+10 I f | |
+(y)2828 6962 w | |
+10 R f | |
+( output need not be efficient in its)7 1346( The)1 206(positive down.)1 590 3… | |
+(use of rectangles.)2 723 1 720 7082 t | |
+10 CW f | |
+(Awk)1507 7082 w | |
+10 R f | |
+( which is a mixture of text processing and)8 1790(is the obvious language for… | |
+( the input is an array of lines, as)8 1345( Since)1 281(geometry, hence arith… | |
+10 CW f | |
+(awk)3511 7202 w | |
+10 R f | |
+(expects, the job should be fairly)5 1316 1 3724 7202 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 1 1 | |
+%%Page: 2 2 | |
+/saveobj save def | |
+mark | |
+2 pagesetup | |
+10 R f | |
+(\255 2 \255)2 166 1 2797 480 t | |
+( is an)2 211( Here)1 243(easy, and in fact it is.)5 846 3 720 840 t | |
+10 CW f | |
+(awk)2045 840 w | |
+10 R f | |
+(program for the job:)3 807 1 2250 840 t | |
+10 CW f | |
+(BEGIN{)1080 1020 w | |
+(y=1)1330 1140 w | |
+(})1080 1260 w | |
+(/^/{)1080 1380 w | |
+(for\(x=1; x<=length\($0\); x++\))2 1680 1 1330 1500 t | |
+(if\(substr\($0, x, 1\)=="#"\))2 1500 1 1580 1620 t | |
+(print "rect", x, y, x+1, y+1)5 1680 1 1830 1740 t | |
+(y++)1330 1860 w | |
+(})1080 1980 w | |
+10 R f | |
+(Although it is certainly easy to write, there is something odd about this pro… | |
+10 CW f | |
+(awk)720 2280 w | |
+10 R f | |
+(results in only one obvious advantage)5 1512 1 926 2280 t | |
+10 S1 f | |
+(\320)2464 2280 w | |
+10 R f | |
+(the ease of tracking)3 781 1 2590 2280 t | |
+10 CW f | |
+(y)3397 2280 w | |
+10 R f | |
+( breaking out the pieces of)5 1056( task of)2 296(. The)1 231 3 3457 2280 t | |
+( simple procedural code that does not use any advanced technology such as)12 … | |
+( peculiarity becomes more evident if the problem is)8 2234( This)1 250( manip… | |
+(rephrased to demand that each horizontal run of rectangles be folded into a s… | |
+10 CW f | |
+(BEGIN{)1080 2820 w | |
+(y=1)1330 2940 w | |
+(})1080 3060 w | |
+(/^/{)1080 3180 w | |
+(for\(x=1; x<=length\($0\); x++\))2 1680 1 1330 3300 t | |
+(if\(substr\($0, x, 1\)=="#"\){)2 1560 1 1580 3420 t | |
+(x0=x;)1830 3540 w | |
+(while\(++x<=length\($0\) && substr\($0, x, 1\)=="#"\))4 2820 1 1830 3660 t | |
+(;)2080 3780 w | |
+(print "rect", x0, y, x, y+1)5 1620 1 1830 3900 t | |
+(})1580 4020 w | |
+(y++)1330 4140 w | |
+(})1080 4260 w | |
+10 R f | |
+( In)1 133(Here a considerable amount of code is being spent to do a job a reg… | |
+(fact, the only regular expression in the program is)8 2044 1 720 4560 t | |
+10 CW f | |
+(^)2796 4560 w | |
+10 R f | |
+( ver\255)1 191( \(Newer)1 354( input.)1 262(, which is almost irrelevant to t… | |
+(sions of)1 324 1 720 4680 t | |
+10 CW f | |
+(awk)1079 4680 w | |
+10 R f | |
+(have mechanisms to use regular expressions within actions, but even there the… | |
+(between the patterns that match text and the actions that manipulate the text… | |
+10 CW f | |
+(Awk's)970 4956 w | |
+10 R f | |
+(patterns)1302 4956 w | |
+10 S1 f | |
+(\320)1650 4956 w | |
+10 R f | |
+( in slashes)2 427(the text)1 304 2 1782 4956 t | |
+10 CW f | |
+(//)2546 4956 w | |
+10 R f | |
+(that select the input on which to run the actions, the pro\255)11 2341 1 2699… | |
+( braces)1 280(grams in the)2 498 2 720 5076 t | |
+10 CW f | |
+({})1524 5076 w | |
+10 S1 f | |
+(\320)1670 5076 w | |
+10 R f | |
+( But)1 196(pass to the actions the entire line containing the text matched by… | |
+( that)1 176( Imagine)1 378( can only be a line.)5 759(much of the power of th… | |
+10 CW f | |
+(awk)4860 5196 w | |
+10 R f | |
+( so the patterns instead passed precisely the text they matched, with no impl… | |
+( first program could then be written:)6 1448(aries. Our)1 418 2 720 5436 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 2 2 | |
+%%Page: 3 3 | |
+/saveobj save def | |
+mark | |
+3 pagesetup | |
+10 R f | |
+(\255 3 \255)2 166 1 2797 480 t | |
+10 CW f | |
+(BEGIN{)1080 900 w | |
+(x=1)1330 1020 w | |
+(y=1)1330 1140 w | |
+(})1080 1260 w | |
+(/ /{)1 240 1 1080 1380 t | |
+(x++)1330 1500 w | |
+(})1080 1620 w | |
+(/#/{)1080 1740 w | |
+(print "rect", x, x+1, y, y+1)5 1680 1 1330 1860 t | |
+(x++)1330 1980 w | |
+(})1080 2100 w | |
+(/\\n/{)1080 2220 w | |
+(x=1)1330 2340 w | |
+(y++)1330 2460 w | |
+(})1080 2580 w | |
+10 R f | |
+( regular expressions to break out complete strings of blanks and)10 2606(and … | |
+10 CW f | |
+(#)4699 2760 w | |
+10 R f | |
+('s sim\255)1 281 1 4759 2760 t | |
+(ply:)720 2880 w | |
+10 CW f | |
+(BEGIN{)1080 3060 w | |
+(x=1)1330 3180 w | |
+(y=1)1330 3300 w | |
+(})1080 3420 w | |
+(/ +/{)1 300 1 1080 3540 t | |
+(x+=length\($0\))1330 3660 w | |
+(})1080 3780 w | |
+(/#+/{)1080 3900 w | |
+(print "rect", x, x+length\($0\), y, y+1)5 2220 1 1330 4020 t | |
+(x+=length\($0\))1330 4140 w | |
+(})1080 4260 w | |
+(/\\n/{)1080 4380 w | |
+(x=1)1330 4500 w | |
+(y++)1330 4620 w | |
+(})1080 4740 w | |
+10 R f | |
+( are)1 148(In these programs, regular expressions are being used to do more t… | |
+(used in all the traditional)4 1050 1 720 5040 t | |
+9 R f | |
+(UNIX)1806 5040 w | |
+10 R f | |
+( the expressions are doing a simple parsing \(or at least a)11 2375(tools. In… | |
+( expressions are called)3 900( Such)1 250(breaking into lexical tokens\) of t… | |
+10 I f | |
+(structural regular expressions)2 1213 1 3547 5160 t | |
+10 R f | |
+(or just)1 254 1 4786 5160 t | |
+10 I f | |
+(structural expressions.)1 911 1 720 5280 t | |
+10 R f | |
+( notably shorter than the originals, but they are conceptually simpler, becau… | |
+( The)1 208(the structure of the input is expressed in the structure of the pr… | |
+( between the patterns and the actions: the patterns select portions of the in… | |
+( actions contain no code to disassemble the input.)8 1979( The)1 205(while th… | |
+(The lexical analysis generator)3 1233 1 970 5952 t | |
+10 CW f | |
+(lex)2241 5952 w | |
+10 R f | |
+( but its)2 301(uses regular expressions to define the structure of text,)8 22… | |
+( \(its output must be run through the C)8 1594(implementation is poor, and si… | |
+( conve\255)1 302( even ignoring issues of speed and)6 1400( But)1 200(compile… | |
+(nience,)720 6312 w | |
+10 CW f | |
+(lex)1041 6312 w | |
+10 R f | |
+( the next)2 364( As)1 171( structural expressions.)2 938(still misses out on … | |
+( be nested to describe the structure of a file recursively, with)11 2510(sect… | |
+(surprising results.)1 711 1 720 6552 t | |
+10 B f | |
+(Interactive Text Editing)2 1027 1 720 6792 t | |
+10 R f | |
+(It is ironic that)3 589 1 970 6948 t | |
+9 R f | |
+(UNIX)1583 6948 w | |
+10 R f | |
+( typ\255)1 188(files are uninterpreted byte streams, yet the style of program… | |
+(ifies)720 7068 w | |
+9 R f | |
+(UNIX)925 7068 w | |
+10 R f | |
+( imposed on files)3 713(has a fairly rigid structure)4 1071 2 1185 7068 t | |
+10 S1 f | |
+(\320)3003 7068 w | |
+10 R f | |
+( silent limits)2 514( \(The)1 247(arrays of not\255too\255long lines.)3 1142 … | |
+( the)1 153( Although)1 434( line lengths by most tools can be frustrating.\))… | |
+10 CW f | |
+(awk)3611 7188 w | |
+10 R f | |
+(variant introduced above does)3 1218 1 3822 7188 t | |
+(not exist, there is an interactive text editor,)7 1706 1 720 7308 t | |
+10 CW f | |
+(sam)2451 7308 w | |
+10 R f | |
+(, that treats its files as simple byte streams.)8 1710 1 2631 7308 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 3 3 | |
+%%Page: 4 4 | |
+/saveobj save def | |
+mark | |
+4 pagesetup | |
+10 R f | |
+(\255 4 \255)2 166 1 2797 480 t | |
+(The)970 840 w | |
+10 CW f | |
+(sam)1153 840 w | |
+10 R f | |
+(command language looks much like that of)6 1744 1 1361 840 t | |
+10 CW f | |
+(ed)3133 840 w | |
+10 R f | |
+(, but the details are different because)6 1483 1 3253 840 t | |
+10 CW f | |
+(sam)4764 840 w | |
+10 R f | |
+(is)4973 840 w | |
+( example, the simple address)4 1151( For)1 189(not line\255oriented.)1 688 3 … | |
+10 CW f | |
+(/string/)1080 1140 w | |
+10 R f | |
+( there are short\255)3 646( Although)1 434( not the next line containing ``st… | |
+(hands to simplify common actions, the idea of a line must be stated explicitl… | |
+10 CW f | |
+(sam)3941 1440 w | |
+10 R f | |
+(.)4121 1440 w | |
+10 CW f | |
+(Sam)970 1596 w | |
+10 R f | |
+(has the same simple text addition and modification commands)8 2509 1 1177 159… | |
+10 CW f | |
+(ed)3713 1596 w | |
+10 R f | |
+(has:)3860 1596 w | |
+10 CW f | |
+(a)4048 1596 w | |
+10 R f | |
+(adds text after the cur\255)4 905 1 4135 1596 t | |
+(rent location,)1 527 1 720 1716 t | |
+10 CW f | |
+(i)1272 1716 w | |
+10 R f | |
+(adds text before it,)3 743 1 1357 1716 t | |
+10 CW f | |
+(d)2125 1716 w | |
+10 R f | |
+(deletes it, and)2 552 1 2210 1716 t | |
+10 CW f | |
+(c)2787 1716 w | |
+10 R f | |
+(replaces it.)1 432 1 2872 1716 t | |
+(Unlike in)1 376 1 970 1872 t | |
+10 CW f | |
+(ed)1372 1872 w | |
+10 R f | |
+(, the current location in)4 933 1 1492 1872 t | |
+10 CW f | |
+(sam)2451 1872 w | |
+10 R f | |
+( simplifies some)2 660( This)1 230( \(and usually isn't\) a line.)5 1031(need… | |
+( example,)1 397( For)1 198(operations considerably.)1 985 3 720 1992 t | |
+10 CW f | |
+(ed)2334 1992 w | |
+10 R f | |
+( a file.)2 268(has several ways to delete all occurrences of a string in)10 2… | |
+(One method is)2 583 1 720 2112 t | |
+10 CW f | |
+(g/string/ s///g)1 900 1 1080 2292 t | |
+10 R f | |
+( substitute command is used to delete text within a line, while a delete comm… | |
+( deleted contains a newline, this technique doesn't work.)8 2271( if the stri… | |
+( just an array of characters, but some characters are more equal than others.… | |
+10 CW f | |
+(Sam)4496 2712 w | |
+10 R f | |
+(is more)1 318 1 4722 2712 t | |
+(forthright:)720 2832 w | |
+10 CW f | |
+(x/string/d)1080 3012 w | |
+10 R f | |
+(The)720 3192 w | |
+10 CW f | |
+(x)905 3192 w | |
+10 R f | |
+( runs the subsequent command)4 1256(\(`extract'\) command searches for each o… | |
+( that this is subtly different)5 1075( Note)1 244( \(not to the line containi… | |
+(from)720 3432 w | |
+10 CW f | |
+(ed)940 3432 w | |
+10 R f | |
+('s)1060 3432 w | |
+10 CW f | |
+(g)1159 3432 w | |
+10 R f | |
+(command:)1246 3432 w | |
+10 CW f | |
+(x)1695 3432 w | |
+10 R f | |
+(extracts the complete text for the command,)6 1767 1 1782 3432 t | |
+10 CW f | |
+(g)3576 3432 w | |
+10 R f | |
+( is also)2 282( There)1 284(merely selects lines.)2 811 3 3663 3432 t | |
+(a complement to)2 666 1 720 3552 t | |
+10 CW f | |
+(x)1411 3552 w | |
+10 R f | |
+(, called)1 288 1 1471 3552 t | |
+10 CW f | |
+(y)1784 3552 w | |
+10 R f | |
+(, that extracts the pieces)4 956 1 1844 3552 t | |
+10 I f | |
+(between)2825 3552 w | |
+10 R f | |
+(the matches of the pattern.)4 1056 1 3177 3552 t | |
+(The)970 3708 w | |
+10 CW f | |
+(x)1151 3708 w | |
+10 R f | |
+(command is a loop, and)4 956 1 1237 3708 t | |
+10 CW f | |
+(sam)2220 3708 w | |
+10 R f | |
+(has a corresponding conditional command, called)5 1990 1 2427 3708 t | |
+10 CW f | |
+(g)4444 3708 w | |
+10 R f | |
+(\(unrelated to)1 509 1 4531 3708 t | |
+10 CW f | |
+(ed)720 3828 w | |
+10 R f | |
+('s)840 3828 w | |
+10 CW f | |
+(g)937 3828 w | |
+10 R f | |
+(\):)997 3828 w | |
+10 CW f | |
+(g/pattern/command)1080 4008 w | |
+10 R f | |
+( that it does not loop, and it does not change)10 1783( Note)1 246( matches t… | |
+( lines con\255)2 424( the command to print all)5 1033( Hence)1 309(the curren… | |
+(taining a string is)3 692 1 720 4428 t | |
+10 CW f | |
+(x/.*\\n/ g/string/p)1 1080 1 1080 4608 t | |
+10 S1 f | |
+(\320)720 4788 w | |
+10 R f | |
+( reverse conditional is)3 891( The)1 209( contains the string.)3 795(extract … | |
+10 CW f | |
+(v)4512 4788 w | |
+10 R f | |
+(, so to print)3 468 1 4572 4788 t | |
+(all lines containing `rob' but not `robot':)6 1621 1 720 4908 t | |
+10 CW f | |
+(x/.*\\n/ g/rob/ v/robot/p)2 1440 1 1080 5088 t | |
+10 R f | |
+(A more dramatic example is to capitalize all occurrences of words `i':)11 279… | |
+10 CW f | |
+(x/[A\255Za\255z]+/ g/i/ v/../ c/I/)3 1680 1 1080 5448 t | |
+10 S1 f | |
+(\320)720 5628 w | |
+10 R f | |
+( more characters, and change the)5 1316(extract all the words, find those tha… | |
+( people have overcome the dif\255)5 1253( Some)1 282(string to `I' \(borrowin… | |
+( expressions,)1 530(ficulty of selecting words or identifiers using regular e… | |
+( the precise definition of `identifier' is immutable in the implementation.)1… | |
+(With)720 6108 w | |
+10 CW f | |
+(sam)945 6108 w | |
+10 R f | |
+(, the definition is part of the program and easy to change, although more lon… | |
+(The program to capitalize `i's should be writable as)8 2057 1 970 6264 t | |
+10 CW f | |
+(x/[A\255Za\255z]+/ g/^i$/ c/I/)2 1440 1 1080 6444 t | |
+10 R f | |
+(That is, the definition of)4 977 1 720 6624 t | |
+10 CW f | |
+(^)1724 6624 w | |
+10 R f | |
+(and)1811 6624 w | |
+10 CW f | |
+($)1982 6624 w | |
+10 R f | |
+( compatibility and because of)4 1188( For)1 192( input.)1 259(should reflect … | |
+(some problems in the implementation, however,)5 1929 1 720 6744 t | |
+10 CW f | |
+(^)2674 6744 w | |
+10 R f | |
+(and)2759 6744 w | |
+10 CW f | |
+($)2928 6744 w | |
+10 R f | |
+(in)3013 6744 w | |
+10 CW f | |
+(sam)3116 6744 w | |
+10 R f | |
+(always match line boundaries.)3 1209 1 3321 6744 t | |
+(In)970 6900 w | |
+10 CW f | |
+(ed)1078 6900 w | |
+10 R f | |
+( each global is still)4 754(, it would not be very useful to nest global comm… | |
+( However,)1 445(a line.)1 249 2 720 7020 t | |
+10 CW f | |
+(sam)1444 7020 w | |
+10 R f | |
+( benefit comes from separating)4 1256( \(This)1 266('s extract commands can b… | |
+( problem of changing all occurrences of the variable)8 2131( the)1 152( Consi… | |
+10 CW f | |
+(n)4980 7140 w | |
+10 R f | |
+(in a C program to some other name, say)8 1595 1 720 7260 t | |
+10 CW f | |
+(num)2340 7260 w | |
+10 R f | |
+( method above will work)4 999(. The)1 230 2 2520 7260 t | |
+10 S1 f | |
+(\320)3774 7260 w | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 4 4 | |
+%%Page: 5 5 | |
+/saveobj save def | |
+mark | |
+5 pagesetup | |
+10 R f | |
+(\255 5 \255)2 166 1 2797 480 t | |
+10 CW f | |
+(x/[a\255zA\255Z0\2559]+/ g/n/ v/../ c/num/)3 1980 1 1080 900 t | |
+10 S1 f | |
+(\320)720 1080 w | |
+10 R f | |
+( are places in C where the `identifier')7 1508(except that there)2 663 2 847 … | |
+10 CW f | |
+(n)3046 1080 w | |
+10 R f | |
+(occurs but not as a variable, in particular as the)9 1906 1 3134 1080 t | |
+(constant)720 1200 w | |
+10 CW f | |
+(\\n)1081 1200 w | |
+10 R f | |
+( cou\255)1 204( prevent incorrect changes, the command can be prefixed by a)1… | |
+(ple of)1 230 1 720 1320 t | |
+10 CW f | |
+(y)975 1320 w | |
+10 R f | |
+(commands to weed out characters and strings:)6 1841 1 1060 1320 t | |
+10 CW f | |
+(y/".*"/ y/'.*'/ x/[a\255zA\255Z0\2559]+/ g/n/ v/../ c/num/)5 2940 1 1080 1500… | |
+10 R f | |
+(This example illustrates the power of composing extractions and conditionals,… | |
+(was encountered when editing a real program \(in fact,)8 2192 1 720 1836 t | |
+10 CW f | |
+(sam)2942 1836 w | |
+10 R f | |
+( with shell pipe\255)3 659( is an obvious analogy)4 914(\). There)1 345 3 312… | |
+(lines, but these command)3 1019 1 720 1956 t | |
+10 I f | |
+(chains)1765 1956 w | |
+10 R f | |
+(are subtly)1 393 1 2052 1956 t | |
+10 S1 f | |
+(\320)2472 1956 w | |
+10 R f | |
+(and importantly)1 638 1 2599 1956 t | |
+10 S1 f | |
+(\320)3264 1956 w | |
+10 R f | |
+( flows into)2 432( Data)1 240(different from pipelines.)2 977 3 3391 1956 t | |
+( chains, the data flow is implicit:)6 1338( In)1 138( pipeline and emerges tr… | |
+( commands are operating on the same data \(except that the last element of th… | |
+( is being)2 345( What)1 269( flows through the chain.)4 1008(text\); the comp… | |
+( in the)2 262(passed from link to link in the chain is a view of the data, un… | |
+( data stays the same, only the structure is modified.)9 2045(chain. The)1 446… | |
+10 B f | |
+(More than one line, and less than one line)8 1771 1 720 2796 t | |
+10 R f | |
+(The standard)1 532 1 970 2952 t | |
+9 R f | |
+(UNIX)1539 2952 w | |
+10 R f | |
+(tools have difficulty handling several lines at a time, if they can do so at … | |
+10 CW f | |
+(Grep)720 3072 w | |
+10 R f | |
+(,)960 3072 w | |
+10 CW f | |
+(sort)1022 3072 w | |
+10 R f | |
+(and)1299 3072 w | |
+10 CW f | |
+(diff)1480 3072 w | |
+10 R f | |
+( if they could operate on larger)6 1296(work on lines only, although it would… | |
+( as a)2 197(pieces, such)1 491 2 720 3192 t | |
+10 CW f | |
+(refer)1443 3192 w | |
+10 R f | |
+(database.)1778 3192 w | |
+10 CW f | |
+(awk)2206 3192 w | |
+10 R f | |
+(can be tricked into accepting multiple\255line records, but then the)9 2619 1… | |
+( sub\255pieces \(typically ordinary lines\) by explicit code.)7 2236(actions … | |
+10 CW f | |
+(sed)4119 3312 w | |
+10 R f | |
+(has a unique and)3 704 1 4336 3312 t | |
+(clumsy mechanism for manipulating multiple lines, which few have mastered.)9 … | |
+( a)1 84( Consider)1 426(Structural expressions make it easy to specify multip… | |
+10 CW f | |
+(refer)4332 3588 w | |
+10 R f | |
+(database,)4672 3588 w | |
+( percent sign and)3 685( line of a record begins with a)7 1210( Each)1 252(wh… | |
+( the line:)2 366(a character indicating the type of information on)7 1981 2 7… | |
+10 CW f | |
+(A)3100 3828 w | |
+10 R f | |
+(for author,)1 429 1 3193 3828 t | |
+10 CW f | |
+(T)3655 3828 w | |
+10 R f | |
+( with)1 211( Staying)1 364(for title, etc.)2 504 3 3748 3828 t | |
+10 CW f | |
+(sam)4860 3828 w | |
+10 R f | |
+(notation, the command to search a)5 1370 1 720 3948 t | |
+10 CW f | |
+(refer)2115 3948 w | |
+10 R f | |
+(database for all papers written by Bimmler is:)7 1828 1 2440 3948 t | |
+10 CW f | |
+(x/\(.+\\n\)+/ g/%A.*Bimmler/p)1 1560 1 1080 4128 t | |
+10 S1 f | |
+(\320)720 4308 w | |
+10 R f | |
+( set of lines containing `Bimm\255)5 1257(break the file into non\255empty se… | |
+( be compatible with the other tools, a `)8 1572( \(To)1 198( after `%A'.)2 48… | |
+10 CW f | |
+(.)3498 4428 w | |
+10 R f | |
+( Except)1 331(' does not match a newline.\))5 1151 2 3558 4428 t | |
+(for the structural expression, this is a regular)7 1836 1 720 4548 t | |
+10 CW f | |
+(grep)2589 4548 w | |
+10 R f | |
+( that)1 184(operation, implying)1 797 2 2862 4548 t | |
+10 CW f | |
+(grep)3877 4548 w | |
+10 R f | |
+(could benefit from an)3 889 1 4151 4548 t | |
+( `stream)1 339( the short term, however, a)5 1147( In)1 149(additional regula… | |
+10 CW f | |
+(sam)720 4788 w | |
+10 R f | |
+(,' analogous to)2 591 1 900 4788 t | |
+10 CW f | |
+(sed,)1516 4788 w | |
+10 R f | |
+(would be convenient, and is currently being implemented.)7 2322 1 1781 4788 t | |
+( example, we can)3 713( For)1 196( search program.)2 681(The ability to compo… | |
+(select just the)2 544 1 720 5064 t | |
+10 I f | |
+(titles)1289 5064 w | |
+10 R f | |
+(of the papers written by Bimmler by applying another extraction:)9 2605 1 150… | |
+10 CW f | |
+(x/\(.+\\n\)+/ g/%A.*Bimmler/ x/.*\\n/ g/%T/p)3 2400 1 1080 5244 t | |
+10 R f | |
+( into individual lines, then prints the lines con\255)8 1912(This program bre… | |
+(taining)720 5544 w | |
+10 CW f | |
+(%T)1023 5544 w | |
+10 R f | |
+(.)1143 5544 w | |
+( examples of multiple\255line components of files that may profitably be extr… | |
+(such as C functions, messages in mail boxes, paragraphs in)9 2415 1 720 5820 t | |
+10 CW f | |
+(troff)3166 5820 w | |
+10 R f | |
+( records in on\255line telephone)4 1162(input and)1 381 2 3497 5820 t | |
+( that, unlike in systems that define file structures)8 1948(books. Note)1 509… | |
+10 I f | |
+(a priori)1 310 1 3203 5940 t | |
+10 R f | |
+(, the structures are applied by the pro\255)7 1527 1 3513 5940 t | |
+( sometimes a C)3 644( means the structure can change from application to appl… | |
+( and sometimes it is just a byte)7 1343(program is an array of functions, but… | |
+(stream.)720 6300 w | |
+( determine the appearance of their input,)6 1627(If the standard commands adm… | |
+( a version of)3 553(many currently annoying problems could become simple: ima… | |
+10 CW f | |
+(diff)4107 6576 w | |
+10 R f | |
+(that could print)2 649 1 4391 6576 t | |
+( or functions instead of changed lines, or a)8 1710(changed sentences)1 740 2… | |
+10 CW f | |
+(sort)3197 6696 w | |
+10 R f | |
+(that could sort a)3 647 1 3464 6696 t | |
+10 CW f | |
+(refer)4138 6696 w | |
+10 R f | |
+(database. The)1 575 1 4465 6696 t | |
+(case of)1 281 1 720 6816 t | |
+10 CW f | |
+(sort)1028 6816 w | |
+10 R f | |
+( the input records be described by a struc\255)8 1676(is particularly interes… | |
+( current bewildering maze of options to control the)8 2062( The)1 209(tural e… | |
+( be largely replaced by a structural expression to extract the key from the r… | |
+(multiple expressions to define multiple keys.)5 1794 1 720 7176 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 5 5 | |
+%%Page: 6 6 | |
+/saveobj save def | |
+mark | |
+6 pagesetup | |
+10 R f | |
+(\255 6 \255)2 166 1 2797 480 t | |
+10 B f | |
+(The)720 840 w | |
+10 CW f | |
+(awk)912 840 w | |
+10 B f | |
+(of the future?)2 582 1 1117 840 t | |
+10 R f | |
+(It is entertaining to imagine a version of)7 1622 1 970 996 t | |
+10 CW f | |
+(awk)2621 996 w | |
+10 R f | |
+( as discussed)2 524( First,)1 263(that applies these ideas throughout.)4 1423… | |
+( For)1 199( to the actions would be defined, rather than merely selected, by … | |
+(example,)720 1236 w | |
+10 CW f | |
+(/#+/ { print })3 840 1 1080 1416 t | |
+10 R f | |
+(would print only)2 667 1 720 1596 t | |
+10 CW f | |
+(#)1412 1596 w | |
+10 R f | |
+(characters; conventional)1 972 1 1497 1596 t | |
+10 CW f | |
+(awk)2494 1596 w | |
+10 R f | |
+(would instead print every line containing)5 1640 1 2699 1596 t | |
+10 CW f | |
+(#)4364 1596 w | |
+10 R f | |
+(characters.)4449 1596 w | |
+( of using the restrictive idea of a)7 1317( Instead)1 342( parsed.)1 314(Next… | |
+( instance, in)2 496( For)1 197( demarcate fields.)2 722(field separator, the … | |
+(the program)1 485 1 720 1992 t | |
+10 CW f | |
+(/\(.+\\n\)+/ {)1 660 1 1080 2172 t | |
+10 I f | |
+(action)1800 2172 w | |
+10 CW f | |
+(})2110 2172 w | |
+10 R f | |
+( lines, but the outermost closure \(the)6 1481(the action sees groups of)4 99… | |
+10 CW f | |
+(+)3229 2352 w | |
+10 R f | |
+(operator\) examines, and hence can extract,)5 1722 1 3318 2352 t | |
+(the individual lines.)2 802 1 720 2472 t | |
+10 CW f | |
+(ed)1577 2472 w | |
+10 R f | |
+( We)1 192( back\255referencing operators.)2 1128(uses parentheses to define s… | |
+( to define the `fields' in)5 980(can modify this idea)3 834 2 720 2592 t | |
+10 CW f | |
+(awk)2567 2592 w | |
+10 R f | |
+(, so)1 147 1 2747 2592 t | |
+10 CW f | |
+($1)2927 2592 w | |
+10 R f | |
+(defines the first element of the closure \(the first)8 1960 1 3080 2592 t | |
+(line\),)720 2712 w | |
+10 CW f | |
+($2)961 2712 w | |
+10 R f | |
+( arrays, so the)3 575( interestingly, the closures could generate indices for… | |
+( say,)1 191(fields would be called,)3 925 2 720 2832 t | |
+10 CW f | |
+(input[1])1869 2832 w | |
+10 R f | |
+(and so on, perhaps with the unadorned identifier)7 1986 1 2382 2832 t | |
+10 CW f | |
+(input)4401 2832 w | |
+10 R f | |
+(holding)4734 2832 w | |
+( generate multi\255dimensional)2 1163( has the advantage that nested closures… | |
+( is some subtlety involving the relationship between)7 2192( \(There)1 331(ar… | |
+10 CW f | |
+(input)4740 3072 w | |
+10 R f | |
+(indices and the order of the closures in the pattern, but the details are not… | |
+(Finally, as in)2 524 1 970 3348 t | |
+10 CW f | |
+(sam)1521 3348 w | |
+10 R f | |
+( expressions would be applicable to the output of structural expressions;)10 … | |
+( following program computes)3 1185( The)1 205( actions.)1 333(that is, we wou… | |
+(how many pages of articles Bimmler has written:)7 1967 1 720 3588 t | |
+10 CW f | |
+( break into records)3 1140(/\(.+\\n\)+/{ #)1 900 2 1080 3768 t | |
+( is Bimmler author? \(see text\))5 1800( #)1 300(input ~ /%A.*Bimmler/{)2 132… | |
+( extract page numbers)3 1260(/%P.*\([0\2559]+\)\255\([0\2559]+\)/{ #)1 1740 2… | |
+(pages+=input[2]\255input[1]+1)1830 4128 w | |
+(})1580 4248 w | |
+(})1330 4368 w | |
+(})1080 4488 w | |
+(END{)1080 4608 w | |
+(print pages)1 660 1 1330 4728 t | |
+(})1080 4848 w | |
+10 R f | |
+(Real)720 5028 w | |
+10 CW f | |
+(awk)935 5028 w | |
+10 R f | |
+( \(that is, regular expressions\) only like)6 1582(uses patterns)1 520 2 1147… | |
+10 CW f | |
+(sam)3282 5028 w | |
+10 R f | |
+('s)3462 5028 w | |
+10 CW f | |
+(g)3567 5028 w | |
+10 R f | |
+(command, but our)2 746 1 3660 5028 t | |
+10 CW f | |
+(awk)4439 5028 w | |
+10 R f | |
+('s patterns)1 421 1 4619 5028 t | |
+(are)720 5148 w | |
+10 CW f | |
+(x)871 5148 w | |
+10 R f | |
+( is why in the pro\255)5 750( This)1 232( we need both to exploit structural … | |
+(gram above the test for whether)5 1276 1 720 5268 t | |
+10 CW f | |
+(input)2024 5268 w | |
+10 R f | |
+(contains a paper by Bimmler must be written as an explicit pattern)11 2688 1 … | |
+( separated by a dash, which is how)7 1393( innermost pattern searches for lin… | |
+10 CW f | |
+(refer)720 5508 w | |
+10 R f | |
+(stores the starting and ending pages of the article.)8 1977 1 1045 5508 t | |
+( real)1 178( The)1 209(This is a contrived example, of course, but it illustr… | |
+10 CW f | |
+(awk)4261 5664 w | |
+10 R f | |
+(suffers from a)2 569 1 4471 5664 t | |
+( making the parsing actions of the)6 1366( would be improved by)4 939( It)1 1… | |
+( lan\255)1 185( A)1 127( pattern\255matching abilities available in the actio… | |
+(guage with regular expressions should not base its text manipulation on a)11 … | |
+10 CW f | |
+(substr)3673 6024 w | |
+10 R f | |
+(function.)4058 6024 w | |
+10 B f | |
+(Comments)720 6264 w | |
+10 R f | |
+( is a powerful and convenient, if unfa\255)7 1545(The use of regular expressi… | |
+( current)1 308(miliar, way to address a number of difficulties the)8 2010 2 7… | |
+9 R f | |
+(UNIX)3062 6540 w | |
+10 R f | |
+( is obviously around this)4 988( There)1 283(tools share.)1 456 3 3313 6540 t | |
+( all.)1 172(new notation a number of interesting problems, and I am not prete… | |
+( the possibilities,)2 678(Rather, I have skipped enthusiastically from exampl… | |
+( these ideas, and perhaps to)5 1117( hope is to encourage others to think abo… | |
+(apply them to old tools as well as new ones.)9 1760 1 720 7020 t | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 6 6 | |
+%%Page: 7 7 | |
+/saveobj save def | |
+mark | |
+7 pagesetup | |
+10 R f | |
+(\255 7 \255)2 166 1 2797 480 t | |
+10 B f | |
+(Acknowledgements)720 840 w | |
+10 R f | |
+( some of their ideas)4 806(John Linderman, Chris Van Wyk, Tom Duff and Norman… | |
+( hope I have not misrepresented them.)6 1522( I)1 83(in these notes.)2 569 3 … | |
+cleartomark | |
+showpage | |
+saveobj restore | |
+%%EndPage: 7 7 | |
+%%Trailer | |
+done | |
+%%Pages: 7 | |
+%%DocumentFonts: Times-Roman Times-Bold Times-Italic Times-Roman Courier | |
diff --git a/include/frame.h b/include/frame.h | |
@@ -0,0 +1,72 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+ | |
+typedef struct Frbox Frbox; | |
+typedef struct Frame Frame; | |
+ | |
+struct Frbox | |
+{ | |
+ long wid; /* in pixels */ | |
+ long nrune; /* <0 ==> negate and treat a… | |
+ union{ | |
+ uchar *ptr; | |
+ struct{ | |
+ short bc; /* break char */ | |
+ short minwid; | |
+ } b; | |
+ } a; | |
+}; | |
+ | |
+struct Frame | |
+{ | |
+ XftFont *font; /* of chars in the frame … | |
+ Bitmap *b; /* on which frame appears */ | |
+ Rectangle r; /* in which text appears */ | |
+ Rectangle entire; /* of full frame */ | |
+ Frbox *box; | |
+ ulong p0, p1; /* selection */ | |
+ short left; /* left edge of text */ | |
+ ushort nbox, nalloc; | |
+ ushort maxtab; /* max size of tab, in pi… | |
+ ushort nchars; /* # runes in frame */ | |
+ ushort nlines; /* # lines with text */ | |
+ ushort maxlines; /* total # lines in frame */ | |
+ ushort lastlinefull; /* last line fills frame */ | |
+ ushort modified; /* changed since frselect() */ | |
+}; | |
+ | |
+ulong frcharofpt(Frame*, Point); | |
+Point frptofchar(Frame*, ulong); | |
+int frdelete(Frame*, ulong, ulong); | |
+void frinsert(Frame*, Rune*, Rune*, ulong); | |
+void frselect(Frame*, Mouse*); | |
+void frselectp(Frame*, Fcode); | |
+void frselectf(Frame*, Point, Point, Fcode); | |
+void frinit(Frame*, Rectangle, XftFont*, Bitmap*); | |
+void frsetrects(Frame*, Rectangle, Bitmap*); | |
+void frclear(Frame*); | |
+void frgetmouse(void); | |
+ | |
+uchar *_frallocstr(unsigned); | |
+void _frinsure(Frame*, int, unsigned); | |
+Point _frdraw(Frame*, Point); | |
+void _frgrowbox(Frame*, int); | |
+void _frfreebox(Frame*, int, int); | |
+void _frmergebox(Frame*, int); | |
+void _frdelbox(Frame*, int, int); | |
+void _frsplitbox(Frame*, int, int); | |
+int _frfindbox(Frame*, int, ulong, ulong); | |
+void _frclosebox(Frame*, int, int); | |
+int _frcanfit(Frame*, Point, Frbox*); | |
+void _frcklinewrap(Frame*, Point*, Frbox*); | |
+void _frcklinewrap0(Frame*, Point*, Frbox*); | |
+void _fradvance(Frame*, Point*, Frbox*); | |
+int _frnewwid(Frame*, Point, Frbox*); | |
+void _frclean(Frame*, Point, int, int); | |
+void _frredraw(Frame*, Point); | |
+void _fraddbox(Frame*, int, int); | |
+Point _frptofcharptb(Frame*, ulong, Point, int); | |
+Point _frptofcharnb(Frame*, ulong, int); | |
+int _frstrlen(Frame*, int); | |
+ | |
+#define NRUNE(b) ((b)->nrune<0? 1 : (b)->nrune) | |
+#define NBYTE(b) strlen((char*)(b)->a.ptr) | |
diff --git a/include/libc.h b/include/libc.h | |
@@ -0,0 +1,54 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+ | |
+ /* Plan 9 C library interface */ | |
+ | |
+ | |
+#define sprint sprintf | |
+#define dup(a,b) dup2(a,b) | |
+#define seek(a,b,c) lseek(a,b,c) | |
+#define create(name, mode, perm) creat(name, perm) | |
+#define exec(a,b) execv(a,b) | |
+#define USED(a) | |
+#define SET(a) | |
+ | |
+#define _exits(v) if (v!=0) _exit(1); else _exit… | |
+ | |
+enum | |
+{ | |
+ OREAD = 0, /* open for read */ | |
+ OWRITE = 1, /* open for write */ | |
+ ORDWR = 2, /* open for read/write */ | |
+ ERRLEN = 64 /* length of error message */ | |
+}; | |
+ | |
+enum | |
+{ | |
+ UTFmax = 3, /* maximum bytes per rune */ | |
+ Runesync = 0x80, /* cannot represent part of a u… | |
+ Runeself = 0x80, /* rune and utf sequences are t… | |
+ Runeerror = 0x80 /* decoding error in utf */ | |
+}; | |
+ | |
+/* | |
+ * new rune routines | |
+ */ | |
+extern int runetochar(char*, Rune*); | |
+extern int chartorune(Rune*, char*); | |
+extern int runelen(long); | |
+extern int fullrune(char*, int); | |
+ | |
+/* | |
+ * rune routines from converted str routines | |
+ */ | |
+extern int utflen(char*); /* was countrune */ | |
+extern char* utfrune(char*, long); | |
+extern char* utfrrune(char*, long); | |
+extern char* utfutf(char*, char*); | |
+/* | |
+ * Miscellaneous functions | |
+ */ | |
+extern void fprint(int, char *, ...); | |
+extern int notify (void(*)(void *, char *)); | |
+extern int errstr(char *); | |
+extern char* getuser(void); | |
+extern void exits(char*); | |
diff --git a/include/libg.h b/include/libg.h | |
@@ -0,0 +1,225 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#ifndef _LIBG_H | |
+#define _LIBG_H | |
+ | |
+#ifndef _LIBXG_EXTENSION | |
+ This header file is not defined in pure ANSI/POSIX | |
+#endif | |
+/* | |
+ * Like Plan9's libg.h, but suitable for inclusion on non-Plan9 machines | |
+ */ | |
+ | |
+#define Cursor xCursor | |
+#include <X11/Xft/Xft.h> | |
+#undef Cursor | |
+ | |
+enum{ EMAXMSG = 128+8192 }; /* max event size */ | |
+ | |
+/* | |
+ * Types | |
+ */ | |
+ | |
+typedef struct Bitmap Bitmap; | |
+typedef struct Point Point; | |
+typedef struct Rectangle Rectangle; | |
+typedef struct Cursor Cursor; | |
+typedef struct Mouse Mouse; | |
+typedef struct Menu Menu; | |
+typedef struct Event Event; | |
+typedef struct RGB RGB; | |
+ | |
+struct Point | |
+{ | |
+ int x; | |
+ int y; | |
+}; | |
+ | |
+struct Rectangle | |
+{ | |
+ Point min; | |
+ Point max; | |
+}; | |
+ | |
+struct Bitmap | |
+{ | |
+ Rectangle r; /* rectangle in data area, local coords */ | |
+ Rectangle clipr; /* clipping region */ | |
+ int ldepth; | |
+ int id; /* as known by the X server */ | |
+ Bitmap *cache; /* zero; distinguishes bitmap fro… | |
+ int flag; /* flag used by X implementation of li… | |
+}; | |
+ | |
+struct Mouse | |
+{ | |
+ int buttons; /* bit array: LMR=124 */ | |
+ Point xy; | |
+ unsigned long msec; | |
+}; | |
+ | |
+struct Cursor | |
+{ | |
+ Point offset; | |
+ unsigned char clr[2*16]; | |
+ unsigned char set[2*16]; | |
+ int id; /* init to zero; used by library */ | |
+}; | |
+ | |
+struct Menu | |
+{ | |
+ char **item; | |
+ char *(*gen)(int); | |
+ int lasthit; | |
+}; | |
+ | |
+struct Event | |
+{ | |
+ int kbdc; | |
+ Mouse mouse; | |
+ int n; /* number of characters in mesage… | |
+ unsigned char data[EMAXMSG]; /* message from an arbitrar… | |
+}; | |
+ | |
+struct RGB | |
+{ | |
+ unsigned long red; | |
+ unsigned long green; | |
+ unsigned long blue; | |
+}; | |
+ | |
+/* | |
+ * Codes for bitblt etc. | |
+ * | |
+ * D | |
+ * 0 1 | |
+ * --------- | |
+ * 0 | 1 | 2 | | |
+ * S |---|---| | |
+ * 1 | 4 | 8 | | |
+ * --------- | |
+ * | |
+ * Usually used as D|S; DorS is so tracebacks are readable. | |
+ */ | |
+typedef | |
+enum Fcode | |
+{ | |
+ Zero = 0x0, | |
+ DnorS = 0x1, | |
+ DandnotS = 0x2, | |
+ notS = 0x3, | |
+ notDandS = 0x4, | |
+ notD = 0x5, | |
+ DxorS = 0x6, | |
+ DnandS = 0x7, | |
+ DandS = 0x8, | |
+ DxnorS = 0x9, | |
+ D = 0xA, | |
+ DornotS = 0xB, | |
+ S = 0xC, | |
+ notDorS = 0xD, | |
+ DorS = 0xE, | |
+ F = 0xF | |
+} Fcode; | |
+ | |
+/* | |
+ * Miscellany | |
+ */ | |
+ | |
+typedef void (*Errfunc)(char *); | |
+ | |
+extern Point add(Point, Point); | |
+extern Point sub(Point, Point); | |
+extern Point mul(Point, int); | |
+extern Point divpt(Point, int); | |
+extern Rectangle rsubp(Rectangle, Point); | |
+extern Rectangle raddp(Rectangle, Point); | |
+extern Rectangle inset(Rectangle, int); | |
+extern Rectangle rmul(Rectangle, int); | |
+extern Rectangle rdiv(Rectangle, int); | |
+extern Rectangle rshift(Rectangle, int); | |
+extern Rectangle rcanon(Rectangle); | |
+extern Bitmap* balloc(Rectangle, int); | |
+extern void bfree(Bitmap*); | |
+extern int rectclip(Rectangle*, Rectangle); | |
+extern void xtbinit(Errfunc, char*, int*, char**, char**); | |
+extern void bclose(void); | |
+extern void berror(char*); | |
+extern void bitblt(Bitmap*, Point, Bitmap*, Rectangle, Fcode); | |
+extern void copymasked(Bitmap*, Point, Bitmap*, Bitmap*, Rectangle); | |
+extern int bitbltclip(void*); | |
+extern Point string(Bitmap*, Point, XftFont*, char*, Fcode); | |
+extern void segment(Bitmap*, Point, Point, int, Fcode); | |
+extern void point(Bitmap*, Point, int, Fcode); | |
+extern void arc(Bitmap*, Point, Point, Point, int, Fcode); | |
+extern void circle(Bitmap*, Point, int, int, Fcode); | |
+extern void disc(Bitmap*, Point, int, int, Fcode); | |
+extern void ellipse(Bitmap*, Point, int, int, int, Fcode); | |
+extern void polysegment(Bitmap *, int, Point *, int, Fcode); | |
+extern long strwidth(XftFont*, char*); | |
+extern Point strsize(XftFont*, char*); | |
+extern long charwidth(XftFont*, Rune); | |
+extern void texture(Bitmap*, Rectangle, Bitmap*, Fcode); | |
+extern void wrbitmap(Bitmap*, int, int, unsigned char*); | |
+extern void rdbitmap(Bitmap*, int, int, unsigned char*); | |
+extern void wrbitmapfile(int, Bitmap*); | |
+extern Bitmap* rdbitmapfile(int); | |
+extern int ptinrect(Point, Rectangle); | |
+extern int rectXrect(Rectangle, Rectangle); | |
+extern int eqpt(Point, Point); | |
+extern int eqrect(Rectangle, Rectangle); | |
+extern void border(Bitmap*, Rectangle, int, Fcode); | |
+extern void cursorswitch(Cursor*); | |
+extern void cursorset(Point); | |
+extern Rectangle bscreenrect(Rectangle*); | |
+extern void bflush(void); | |
+extern int clipline(Rectangle, Point*, Point*); | |
+extern int clipr(Bitmap*, Rectangle); | |
+extern int scrpix(int*,int*); | |
+ | |
+extern void einit(unsigned long); | |
+extern unsigned long estart(unsigned long, int, int); | |
+extern unsigned long etimer(unsigned long, long); | |
+extern unsigned long event(Event*); | |
+extern unsigned long eread(unsigned long, Event*); | |
+extern Mouse emouse(void); | |
+extern int ekbd(void); | |
+extern int ecanread(unsigned long); | |
+extern int ecanmouse(void); | |
+extern int ecankbd(void); | |
+extern void ereshaped(Rectangle); /* supplied by user */ | |
+extern void eflush(unsigned long); | |
+extern int menuhit(int, Mouse*, Menu*); | |
+extern Rectangle getrect(int, Mouse*); | |
+extern unsigned long rgbpix(Bitmap*, RGB); | |
+extern void rdcolmap(Bitmap*, RGB*); | |
+extern void wrcolmap(Bitmap*, RGB*); | |
+ | |
+/* Extra functions supplied by libXg */ | |
+extern int snarfswap(char*, int, char**); | |
+extern int scrollfwdbut(void); | |
+ | |
+enum{ | |
+ Emouse = 1, | |
+ Ekeyboard = 2 | |
+}; | |
+ | |
+extern Point Pt(int, int); | |
+extern Rectangle Rect(int, int, int, int); | |
+extern Rectangle Rpt(Point, Point); | |
+ | |
+ | |
+#define Dx(r) ((r).max.x-(r).min.x) | |
+#define Dy(r) ((r).max.y-(r).min.y) | |
+ | |
+ | |
+extern Bitmap screen; | |
+extern XftFont *font; | |
+extern XftColor fontcolor; | |
+extern XftColor bgcolor; | |
+ | |
+#define BGSHORT(p) (((p)[0]<<0) | ((p)[1]<<8)) | |
+#define BGLONG(p) ((BGSHORT(p)<<0) | (BGSHORT(p+2)<<16)) | |
+#define BPSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8)) | |
+#define BPLONG(p, v) (BPSHORT(p, (v)), BPSHORT(p+2, (v)>… | |
+ | |
+#endif | |
diff --git a/include/regexp.h b/include/regexp.h | |
@@ -0,0 +1,65 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+ | |
+typedef struct Resub Resub; | |
+typedef struct Reclass Reclass; | |
+typedef struct Reinst Reinst; | |
+typedef struct Reprog Reprog; | |
+ | |
+/* | |
+ * Sub expression matches | |
+ */ | |
+struct Resub{ | |
+ union | |
+ { | |
+ char *sp; | |
+ Rune *rsp; | |
+ }s; | |
+ union | |
+ { | |
+ char *ep; | |
+ Rune *rep; | |
+ }e; | |
+}; | |
+ | |
+/* | |
+ * character class, each pair of rune's defines a range | |
+ */ | |
+struct Reclass{ | |
+ Rune *end; | |
+ Rune spans[64]; | |
+}; | |
+ | |
+/* | |
+ * Machine instructions | |
+ */ | |
+struct Reinst{ | |
+ int type; | |
+ union { | |
+ Reclass *cp; /* class pointer */ | |
+ Rune r; /* character */ | |
+ int subid; /* sub-expression id for RBRA… | |
+ Reinst *right; /* right child of OR */ | |
+ }u1; | |
+ union { /* regexp relies on these two being in the same union */ | |
+ Reinst *left; /* left child of OR */ | |
+ Reinst *next; /* next instruction for CAT & LBR… | |
+ }u2; | |
+}; | |
+ | |
+/* | |
+ * Reprogram definition | |
+ */ | |
+struct Reprog{ | |
+ Reinst *startinst; /* start pc */ | |
+ Reclass class[16]; /* .data */ | |
+ Reinst firstinst[5]; /* .text */ | |
+}; | |
+ | |
+extern Reprog *regcomp(char*); | |
+extern Reprog *regcomplit(char*); | |
+extern Reprog *regcompnl(char*); | |
+extern void regerror(char*); | |
+extern int regexec(Reprog*, char*, Resub*, int); | |
+extern void regsub(char*, char*, Resub*, int); | |
+extern int rregexec(Reprog*, Rune*, Resub*, int); | |
+extern void rregsub(Rune*, Rune*, Resub*, int); | |
diff --git a/include/u.h b/include/u.h | |
@@ -0,0 +1,117 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <stdlib.h> | |
+#include <string.h> | |
+#include <sys/types.h> | |
+#include <setjmp.h> | |
+#include <stdio.h> | |
+#include <unistd.h> | |
+#include <fcntl.h> | |
+#include <stdint.h> | |
+ | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+typedef unsigned char uchar; | |
+typedef unsigned short Rune; | |
+ | |
+ /* System configuration parameters */ | |
+ | |
+#ifdef SYSVR3 | |
+#include <malloc.h> | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+#define remove(v) unlink(v) | |
+#define WEXITSTATUS(s) (((s)>>8)&0xFF) | |
+extern char *getenv(char*); | |
+extern char *getlogin(void); | |
+extern char *strerror(int); | |
+extern void *memmove(void*, const void*, size_t); | |
+#define NEEDMEMMOVE | |
+#define NEEDSTRERROR | |
+#define NEEDVARARG | |
+#endif /* SYSVR3 */ | |
+ | |
+#ifdef IRIX5 | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+#endif /* IRIX5 */ | |
+ | |
+#ifdef IRIX | |
+extern void *memmove(void*, const void*, size_t); | |
+#define NEEDMEMMOVE | |
+#endif /* IRIX */ | |
+ | |
+#ifdef UMIPS | |
+typedef unsigned long ulong; | |
+typedef unsigned short ushort; | |
+#define const /* mips compiler doesn't support c… | |
+extern char *strerror(int); | |
+extern void *memmove(void*, const void*, size_t); | |
+#define NEEDMEMMOVE | |
+#define NEEDSTRERROR | |
+#define NEEDVARARG | |
+#define NOFIFO /* turn off exstart in samterm/un… | |
+#endif /* UMIPS */ | |
+ | |
+#ifdef SUNOS | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+extern char *strerror(int); | |
+extern void *memmove(void*, const void*, size_t); | |
+extern void *memcpy(void*, const void*, size_t); | |
+#define NEEDMEMMOVE | |
+#define NEEDSTRERROR | |
+#endif /* SUNOS */ | |
+ | |
+#ifdef SOLARIS | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+#endif | |
+ | |
+#ifdef AIX | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+#endif /* AIX */ | |
+ | |
+#ifdef OSF1 | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+extern void *memmove(void*, const void*, size_t); | |
+#endif /* OSF1 */ | |
+ | |
+#ifdef HPUX | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+#define NEEDSTRERROR | |
+#endif /* HPUX */ | |
+ | |
+#ifdef APOLLO | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+#endif /* APOLLO */ | |
+ | |
+#ifdef CONVEX | |
+typedef unsigned long ulong; | |
+#endif /* CONVEX */ | |
+ | |
+#ifdef DYNIX | |
+#define SIG_ERR BADSIG | |
+#define NEEDMEMMOVE | |
+#define remove(v) unlink(v) | |
+#define WEXITSTATUS(s) (((s)>>8)&0xFF) | |
+#define NEEDMEMMOVE | |
+#define NOFIFO /* turn off exstart in samterm/un… | |
+#endif /* DYNIX */ | |
+ | |
+#ifdef PTX | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+#endif /* PTX */ | |
+ | |
+#ifdef BSDi | |
+typedef unsigned long ulong; | |
+#endif /* BSDi */ | |
+ | |
+#ifdef v10 | |
+typedef unsigned short ushort; | |
+typedef unsigned long ulong; | |
+#endif | |
diff --git a/libXg/Gwin.h b/libXg/Gwin.h | |
@@ -0,0 +1,43 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#ifndef GWIN_H | |
+#define GWIN_H | |
+ | |
+/* New resource names */ | |
+ | |
+#define XtNscrollForwardR "scrollForwardR" | |
+#define XtCScrollForwardR "ScrollForwardR" | |
+#define XtNreshaped "reshaped" | |
+#define XtCReshaped "Reshaped" | |
+#define XtNgotchar "gotchar" | |
+#define XtCGotchar "Gotchar" | |
+#define XtNgotmouse "gotmouse" | |
+#define XtCGotmouse "Gotmouse" | |
+#define XtNp9font "p9font" | |
+#define XtCP9font "P9font" | |
+#define XtNcomposeMod "composeMod" | |
+#define XtCComposeMod "ComposeMod" | |
+ | |
+/* External reference to the class record pointer */ | |
+extern WidgetClass gwinWidgetClass; | |
+ | |
+/* Type definition for gwin widgets */ | |
+typedef struct _GwinRec *GwinWidget; | |
+ | |
+/* Type definition for gwin resources */ | |
+typedef struct { | |
+ int buttons; | |
+ struct { | |
+ int x; | |
+ int y; | |
+ } xy; | |
+ unsigned long msec; | |
+ } Gwinmouse; | |
+ | |
+typedef void (*Reshapefunc)(int, int, int, int); | |
+typedef void (*Charfunc)(int); | |
+typedef void (*Mousefunc)(Gwinmouse*); | |
+ | |
+/* Method declarations */ | |
+extern String GwinSelectionSwap(Widget, String); | |
+ | |
+#endif /* GWIN_H */ | |
diff --git a/libXg/GwinP.h b/libXg/GwinP.h | |
@@ -0,0 +1,45 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#ifndef GWINP_H | |
+#define GWINP_H | |
+ | |
+#include "Gwin.h" | |
+ | |
+/* Gwin is derived from Core */ | |
+ | |
+/* Gwin instance part */ | |
+typedef struct { | |
+ /* New resource fields */ | |
+ Pixel foreground; | |
+ Boolean forwardr; /* does right button scroll fo… | |
+ Reshapefunc reshaped; /* Notify app of reshape */ | |
+ Charfunc gotchar; /* Notify app of char arrival */ | |
+ Mousefunc gotmouse; /* Notify app of mouse change */ | |
+ String selection; /* Current selection */ | |
+ int compose; | |
+} GwinPart; | |
+ | |
+/* Full instance record */ | |
+typedef struct _GwinRec { | |
+ CorePart core; | |
+ GwinPart gwin; | |
+} GwinRec; | |
+ | |
+/* New type for class methods */ | |
+typedef String (*SelSwapProc)(Widget, String); | |
+ | |
+/* Class part */ | |
+typedef struct { | |
+ SelSwapProc select_swap; | |
+ XtPointer extension; | |
+} GwinClassPart; | |
+ | |
+/* Full class record */ | |
+typedef struct _GwinClassRec { | |
+ CoreClassPart core_class; | |
+ GwinClassPart gwin_class; | |
+} GwinClassRec, *GwinWidgetClass; | |
+ | |
+/* External definition for class record */ | |
+extern GwinClassRec gwinClassRec; | |
+ | |
+#endif /* GWINP_H */ | |
diff --git a/libXg/Makefile b/libXg/Makefile | |
@@ -0,0 +1,58 @@ | |
+# Copyright (c) 1998 Lucent Technologies - All rights reserved. | |
+# | |
+# Prototype Makefile for libXg | |
+# | |
+# define operating system. ONE of: | |
+# -DIRIX -DSUNOS -DUMIPS -DSYSVR3 -DAIX -DOSF1 | |
+# -DHPUX -DAPOLLO -DCONVEX -DDYNIX | |
+# | |
+# Additionally, -D_POSIX_SOURCE (or its equivalent) may be specified | |
+# if your compiler supports posix-compatible compilation | |
+include ../config.mk | |
+ | |
+OS=-DIRIX5 | |
+ | |
+# add -Iincludedir for any include directories that need to be searched | |
+INCS=-I../include -I$(FREETYPEINC) | |
+ | |
+# set this if your X libraries are in different locations | |
+# or if you need extra libraries to load with X11 applications | |
+XLIBS=-lXt | |
+ | |
+# add name of library orderer - use ":" if none | |
+RANLIB=: | |
+ | |
+# add name of librarian | |
+AR=ar | |
+ | |
+# the name of the library | |
+LIB=libXg.a | |
+ | |
+CFLAGS=$(OS) -D_LIBXG_EXTENSION $(INCS) | |
+CC=cc | |
+ | |
+OBJS= arc.o arith.o balloc.o bitblt.o bitbltclip.o border.o bscreenrect… | |
+ circle.o clipline.o clipr.o copymasked.o cursorset.o cursorswitch.o\ | |
+ disc.o ellipse.o font.o gcs.o getrect.o gwin.o ldconvert.o latin1.o\ | |
+ menuhit.o point.o polysegment.o rdbitmap.o rdbitmapfile.o\ | |
+ rectclip.o rune.o segment.o string.o strwidth.o texture.o\ | |
+ wrbitmap.o wrbitmapfile.o xtbinit.o | |
+ | |
+all install: $(LIB) | |
+compile: $(LIB) | |
+test: $(LIB) test.o | |
+ $(CC) -o $@ $? $(LIB) $(XLIBS) -lm | |
+ echo try running test | |
+clean: | |
+ rm -f *.o test *.a | |
+ | |
+nuke: clean | |
+ rm -f $(LIB) | |
+ | |
+$(LIB): $(OBJS) | |
+ $(AR) rv $(LIB) $(OBJS) | |
+ $(RANLIB) $(LIB) | |
+ | |
+$(LIB)(%.o): %.o | |
+ | |
+$(OBJS): ../include/libg.h libgint.h ../include/libc.h | |
diff --git a/libXg/arc.c b/libXg/arc.c | |
@@ -0,0 +1,45 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+#include <math.h> | |
+ | |
+#define rad2deg(x) 180*((x)/3.141592653589793238462643383279502884197169399375… | |
+ | |
+void | |
+arc(Bitmap *b, Point p0, Point p1, Point p2, int v, Fcode f) | |
+{ | |
+ unsigned int d; | |
+ int x, y, r, start, end, delta; | |
+ GC g; | |
+ | |
+ p1.x -= p0.x; | |
+ p1.y -= p0.y; | |
+ p2.x -= p0.x; | |
+ p2.y -= p0.y; | |
+ r = (int)sqrt((double)(p1.x*p1.x + p1.y*p1.y)); | |
+ start = (int)(64*rad2deg(atan2(-p2.y, p2.x))); | |
+ end = (int)(64*rad2deg(atan2(-p1.y, p1.x))); | |
+ if(start < 0) | |
+ start += 64*360; | |
+ if(end < 0) | |
+ end += 64*360; | |
+ delta = end - start; | |
+ if(delta < 0) | |
+ delta += 64*360; | |
+ x = p0.x - r; | |
+ y = p0.y - r; | |
+ if(b->flag&SHIFT){ | |
+ x -= b->r.min.x; | |
+ y -= b->r.min.y; | |
+ } | |
+ d = 2*r; | |
+ g = _getfillgc(f, b, v); | |
+ /* | |
+ * delta is positive, so this draws counterclockwise arc | |
+ * from start to start+delta | |
+ */ | |
+ XDrawArc(_dpy, (Drawable)b->id, g, x, y, d, d, start, delta); | |
+} | |
+ | |
diff --git a/libXg/arith.c b/libXg/arith.c | |
@@ -0,0 +1,191 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+ | |
+Point | |
+add(Point a, Point b) | |
+{ | |
+ a.x += b.x; | |
+ a.y += b.y; | |
+ return a; | |
+} | |
+ | |
+Point | |
+sub(Point a, Point b) | |
+{ | |
+ a.x -= b.x; | |
+ a.y -= b.y; | |
+ return a; | |
+} | |
+ | |
+Rectangle | |
+inset(Rectangle r, int n) | |
+{ | |
+ r.min.x += n; | |
+ r.min.y += n; | |
+ r.max.x -= n; | |
+ r.max.y -= n; | |
+ return r; | |
+} | |
+ | |
+Point | |
+divpt(Point a, int b) | |
+{ | |
+ a.x /= b; | |
+ a.y /= b; | |
+ return a; | |
+} | |
+ | |
+Point | |
+mul(Point a, int b) | |
+{ | |
+ a.x *= b; | |
+ a.y *= b; | |
+ return a; | |
+} | |
+ | |
+Rectangle | |
+rsubp(Rectangle r, Point p) | |
+{ | |
+ r.min.x -= p.x; | |
+ r.min.y -= p.y; | |
+ r.max.x -= p.x; | |
+ r.max.y -= p.y; | |
+ return r; | |
+} | |
+ | |
+Rectangle | |
+raddp(Rectangle r, Point p) | |
+{ | |
+ r.min.x += p.x; | |
+ r.min.y += p.y; | |
+ r.max.x += p.x; | |
+ r.max.y += p.y; | |
+ return r; | |
+} | |
+ | |
+Rectangle | |
+rmul(Rectangle r, int a) | |
+{ | |
+ if (a != 1) { | |
+ r.min.x *= a; | |
+ r.min.y *= a; | |
+ r.max.x *= a; | |
+ r.max.y *= a; | |
+ } | |
+ return r; | |
+} | |
+ | |
+Rectangle | |
+rdiv(Rectangle r, int a) | |
+{ | |
+ if (a != 1) { | |
+ r.min.x /= a; | |
+ r.min.y /= a; | |
+ r.max.x /= a; | |
+ r.max.y /= a; | |
+ } | |
+ return r; | |
+} | |
+ | |
+Rectangle | |
+rshift(Rectangle r, int a) | |
+{ | |
+ if (a > 0) { | |
+ r.min.x <<= a; | |
+ r.min.y <<= a; | |
+ r.max.x <<= a; | |
+ r.max.y <<= a; | |
+ } | |
+ else if (a < 0) { | |
+ a = -a; | |
+ r.min.x >>= a; | |
+ r.min.y >>= a; | |
+ r.max.x >>= a; | |
+ r.max.y >>= a; | |
+ } | |
+ return r; | |
+} | |
+ | |
+eqpt(Point p, Point q) | |
+{ | |
+ return p.x==q.x && p.y==q.y; | |
+} | |
+ | |
+eqrect(Rectangle r, Rectangle s) | |
+{ | |
+ return r.min.x==s.min.x && r.max.x==s.max.x && | |
+ r.min.y==s.min.y && r.max.y==s.max.y; | |
+} | |
+ | |
+rectXrect(Rectangle r, Rectangle s) | |
+{ | |
+ return r.min.x<s.max.x && s.min.x<r.max.x && | |
+ r.min.y<s.max.y && s.min.y<r.max.y; | |
+} | |
+ | |
+int | |
+rectinrect(Rectangle r, Rectangle s) | |
+{ | |
+ /* !ptinrect(r.min, s) in line for speed */ | |
+ if(!(r.min.x>=s.min.x && r.min.x<s.max.x && | |
+ r.min.y>=s.min.y && r.min.y<s.max.y)) | |
+ return 0; | |
+ return r.max.x<=s.max.x && r.max.y<=s.max.y; | |
+} | |
+ | |
+ptinrect(Point p, Rectangle r) | |
+{ | |
+ return p.x>=r.min.x && p.x<r.max.x && | |
+ p.y>=r.min.y && p.y<r.max.y; | |
+} | |
+ | |
+Rectangle | |
+rcanon(Rectangle r) | |
+{ | |
+ int t; | |
+ if (r.max.x < r.min.x) { | |
+ t = r.min.x; | |
+ r.min.x = r.max.x; | |
+ r.max.x = t; | |
+ } | |
+ if (r.max.y < r.min.y) { | |
+ t = r.min.y; | |
+ r.min.y = r.max.y; | |
+ r.max.y = t; | |
+ } | |
+ return r; | |
+} | |
+ | |
+Rectangle | |
+Rect(int x1, int y1, int x2, int y2) | |
+{ | |
+ Rectangle r; | |
+ | |
+ r.min.x = x1; | |
+ r.min.y = y1; | |
+ r.max.x = x2; | |
+ r.max.y = y2; | |
+ return r; | |
+} | |
+ | |
+Rectangle | |
+Rpt(Point p1, Point p2) | |
+{ | |
+ Rectangle r; | |
+ | |
+ r.min = p1; | |
+ r.max = p2; | |
+ return r; | |
+} | |
+ | |
+Point | |
+Pt(int x, int y) | |
+{ | |
+ Point p; | |
+ | |
+ p.x = x; | |
+ p.y = y; | |
+ return p; | |
+} | |
diff --git a/libXg/balloc.c b/libXg/balloc.c | |
@@ -0,0 +1,60 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+Bitmap* | |
+balloc(Rectangle r, int ldepth) | |
+{ | |
+ Bitmap *b; | |
+ | |
+ b = _balloc(r, ldepth); | |
+ bitblt(b, r.min, b, r, Zero); | |
+ return b; | |
+} | |
+ | |
+Bitmap* | |
+_balloc(Rectangle r, int ldepth) | |
+{ | |
+ int id; | |
+ Bitmap *b; | |
+ int ld; | |
+ Rectangle rx; | |
+ | |
+ b = (Bitmap *)malloc(sizeof(Bitmap)); | |
+ if(b == 0) | |
+ berror("balloc malloc"); | |
+ if (ldepth == 0) | |
+ ld = 0; | |
+ else | |
+ ld = screen.ldepth; | |
+ rx = r; | |
+ if (Dx(rx) == 0) | |
+ rx.max.x++; | |
+ if (Dy(rx) == 0) | |
+ rx.max.y++; | |
+ id = (int) XCreatePixmap(_dpy, (Drawable)screen.id, | |
+ Dx(rx), Dy(rx), _ld2d[ld]); | |
+ b->ldepth = ldepth; | |
+ b->r = r; | |
+ b->clipr = r; | |
+ b->id = id; | |
+ b->cache = 0; | |
+ if(ldepth == 0) | |
+ b->flag = DP1|BL1; | |
+ else | |
+ b->flag = screen.flag&BL1; | |
+ if(r.min.x==0 && r.min.y ==0) | |
+ b->flag |= ZORG; | |
+ else | |
+ b->flag |= SHIFT; | |
+ return b; | |
+} | |
+ | |
+void | |
+bfree(Bitmap *b) | |
+{ | |
+ XFreePixmap(_dpy, (Pixmap)b->id); | |
+ free(b); | |
+} | |
diff --git a/libXg/bitblt.c b/libXg/bitblt.c | |
@@ -0,0 +1,59 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+bitblt(Bitmap *d, Point p, Bitmap *s, Rectangle r, Fcode f) | |
+{ | |
+ int sx, sy, dx, dy, bfunc; | |
+ GC g; | |
+ unsigned long plane; | |
+ Bitmap *btmp; | |
+ | |
+ if(Dx(r)<=0 || Dy(r)<=0) | |
+ return; | |
+ sx = r.min.x; | |
+ sy = r.min.y; | |
+ if(s->flag&SHIFT){ | |
+ sx -= s->r.min.x; | |
+ sy -= s->r.min.y; | |
+ } | |
+ dx = p.x; | |
+ dy = p.y; | |
+ if(d->flag&SHIFT){ | |
+ dx -= d->r.min.x; | |
+ dy -= d->r.min.y; | |
+ } | |
+ g = _getcopygc(f, d, s, &bfunc); | |
+ if(bfunc == UseCopyArea) | |
+ XCopyArea(_dpy, (Drawable)s->id, (Drawable)d->id, g, | |
+ sx, sy, Dx(r), Dy(r), dx, dy); | |
+ else if(bfunc == UseFillRectangle){ | |
+ XFillRectangle(_dpy, (Drawable)d->id, g, | |
+ dx, dy, Dx(r), Dy(r)); | |
+ }else{ | |
+ /* bfunc == UseCopyPlane */ | |
+ plane = _ld2dmask[s->ldepth]; | |
+ plane &= ~(plane>>1); | |
+ if(0/*f == S*/) | |
+ XCopyPlane(_dpy, (Drawable)s->id, (Drawable)d->id, g, | |
+ sx, sy, Dx(r), Dy(r), dx, dy, plane); | |
+ else { | |
+ /* | |
+ * CopyPlane can only do func code S, | |
+ * so copy src rect into a bitmap with the same depth | |
+ * as the dest, then do the bitblt from the tmp. | |
+ * This won't recurse again because we only get | |
+ * UseCopyPlane with differing bitmap depths | |
+ */ | |
+ btmp = _balloc(Rect(0,0,Dx(r),Dy(r)), d->ldepth); | |
+ XCopyPlane(_dpy, (Drawable)s->id, (Drawable)btmp->id, … | |
+ sx, sy, Dx(r), Dy(r), 0, 0, plane); | |
+ bitblt(d, p, btmp, btmp->r, f); | |
+ bfree(btmp); | |
+ } | |
+ } | |
+ XFlush(_dpy); | |
+} | |
diff --git a/libXg/bitbltclip.c b/libXg/bitbltclip.c | |
@@ -0,0 +1,68 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+int | |
+bitbltclip(void *vp) | |
+{ | |
+ int dx, dy; | |
+ int i; | |
+ struct bbcarg{ | |
+ Bitmap *dm; | |
+ Point p; | |
+ Bitmap *sm; | |
+ Rectangle r; | |
+ Fcode f; | |
+ }*bp; | |
+ | |
+ bp = (struct bbcarg *)vp; | |
+ dx = Dx(bp->r); | |
+ dy = Dy(bp->r); | |
+ if(bp->p.x < bp->dm->clipr.min.x){ | |
+ i = bp->dm->clipr.min.x-bp->p.x; | |
+ bp->r.min.x += i; | |
+ bp->p.x += i; | |
+ dx -= i; | |
+ } | |
+ if(bp->p.y < bp->dm->clipr.min.y){ | |
+ i = bp->dm->clipr.min.y-bp->p.y; | |
+ bp->r.min.y += i; | |
+ bp->p.y += i; | |
+ dy -= i; | |
+ } | |
+ if(bp->p.x+dx > bp->dm->clipr.max.x){ | |
+ i = bp->p.x+dx-bp->dm->clipr.max.x; | |
+ bp->r.max.x -= i; | |
+ dx -= i; | |
+ } | |
+ if(bp->p.y+dy > bp->dm->clipr.max.y){ | |
+ i = bp->p.y+dy-bp->dm->clipr.max.y; | |
+ bp->r.max.y -= i; | |
+ dy -= i; | |
+ } | |
+ if(bp->r.min.x < bp->sm->clipr.min.x){ | |
+ i = bp->sm->clipr.min.x-bp->r.min.x; | |
+ bp->p.x += i; | |
+ bp->r.min.x += i; | |
+ dx -= i; | |
+ } | |
+ if(bp->r.min.y < bp->sm->clipr.min.y){ | |
+ i = bp->sm->clipr.min.y-bp->r.min.y; | |
+ bp->p.y += i; | |
+ bp->r.min.y += i; | |
+ dy -= i; | |
+ } | |
+ if(bp->r.max.x > bp->sm->clipr.max.x){ | |
+ i = bp->r.max.x-bp->sm->clipr.max.x; | |
+ bp->r.max.x -= i; | |
+ dx -= i; | |
+ } | |
+ if(bp->r.max.y > bp->sm->clipr.max.y){ | |
+ i = bp->r.max.y-bp->sm->clipr.max.y; | |
+ bp->r.max.y -= i; | |
+ dy -= i; | |
+ } | |
+ return dx>0 && dy>0; | |
+} | |
diff --git a/libXg/border.c b/libXg/border.c | |
@@ -0,0 +1,28 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+ | |
+void | |
+border(Bitmap *l, Rectangle r, int i, Fcode c) | |
+{ | |
+ if(i > 0){ | |
+ bitblt(l, r.min, | |
+ l, Rect(r.min.x, r.min.y, r.max.x, r.min.y+i), c); | |
+ bitblt(l, Pt(r.min.x, r.max.y-i), | |
+ l, Rect(r.min.x, r.max.y-i, r.max.x, r.max.y), c); | |
+ bitblt(l, Pt(r.min.x, r.min.y+i), | |
+ l, Rect(r.min.x, r.min.y+i, r.min.x+i, r.max.y-i), c); | |
+ bitblt(l, Pt(r.max.x-i, r.min.y+i), | |
+ l, Rect(r.max.x-i, r.min.y+i, r.max.x, r.max.y-i), c); | |
+ }else if(i < 0){ | |
+ bitblt(l, Pt(r.min.x, r.min.y+i), | |
+ l, Rect(r.min.x, r.min.y+i, r.max.x, r.min.y), c); | |
+ bitblt(l, Pt(r.min.x, r.max.y), | |
+ l, Rect(r.min.x, r.max.y, r.max.x, r.max.y-i), c); | |
+ bitblt(l, Pt(r.min.x+i, r.min.y+i), | |
+ l, Rect(r.min.x+i, r.min.y+i, r.min.x, r.max.y-i), c); | |
+ bitblt(l, Pt(r.max.x, r.min.y+i), | |
+ l, Rect(r.max.x, r.min.y+i, r.max.x-i, r.max.y-i), c); | |
+ } | |
+} | |
diff --git a/libXg/bscreenrect.c b/libXg/bscreenrect.c | |
@@ -0,0 +1,18 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+/* | |
+ * The screen data structure should always be up to date | |
+ * (Not true in the Plan 9 library, which is why this | |
+ * function exists). | |
+ */ | |
+Rectangle | |
+bscreenrect(Rectangle *clipr) | |
+{ | |
+ if(clipr) | |
+ *clipr = screen.clipr; | |
+ return screen.r; | |
+} | |
diff --git a/libXg/circle.c b/libXg/circle.c | |
@@ -0,0 +1,23 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+circle(Bitmap *b, Point p, int r, int v, Fcode f) | |
+{ | |
+ unsigned int d; | |
+ int x, y; | |
+ GC g; | |
+ | |
+ x = p.x - r; | |
+ y = p.y - r; | |
+ if (b->flag&SHIFT){ | |
+ x -= b->r.min.x; | |
+ y -= b->r.min.y; | |
+ } | |
+ d = 2*r; | |
+ g = _getfillgc(f, b, v); | |
+ XDrawArc(_dpy, (Drawable)b->id, g, x, y, d, d, 0, 23040/* 360 deg */); | |
+} | |
diff --git a/libXg/clipline.c b/libXg/clipline.c | |
@@ -0,0 +1,225 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+typedef struct Linedesc | |
+{ | |
+ int x0; | |
+ int y0; | |
+ char xmajor; | |
+ char slopeneg; | |
+ long dminor; | |
+ long dmajor; | |
+} Linedesc; | |
+ | |
+int _clipline(Rectangle, Point*, Point*, Linedesc*); | |
+ | |
+#define XYswap(p) t=(p)->x, (p)->x=(p)->y, (p)->y=t | |
+#define Swap(x, y) t=x, x=y, y=t | |
+ | |
+static long | |
+lfloor(long x, long y) /* first integer <= x/y */ | |
+{ | |
+ if(y <= 0){ | |
+ if(y == 0) | |
+ return x; | |
+ y = -y; | |
+ x = -x; | |
+ } | |
+ if(x < 0){ /* be careful; C div. is undefined */ | |
+ x = -x; | |
+ x += y-1; | |
+ return -(x/y); | |
+ } | |
+ return x/y; | |
+} | |
+ | |
+static long | |
+lceil(long x, long y) /* first integer >= x/y */ | |
+{ | |
+ if(y <= 0){ | |
+ if(y == 0) | |
+ return x; | |
+ y = -y; | |
+ x = -x; | |
+ } | |
+ if(x < 0){ | |
+ x = -x; | |
+ return -(x/y); | |
+ } | |
+ x += y-1; | |
+ return x/y; | |
+} | |
+ | |
+int | |
+_gminor(long x, Linedesc *l) | |
+{ | |
+ long y; | |
+ | |
+ y = 2*(x-l->x0)*l->dminor + l->dmajor; | |
+ y = lfloor(y, 2*l->dmajor) + l->y0; | |
+ return l->slopeneg? -y : y; | |
+} | |
+ | |
+int | |
+_gmajor(long y, Linedesc *l) | |
+{ | |
+ long x; | |
+ | |
+ x = 2*((l->slopeneg? -y : y)-l->y0)*l->dmajor - l->dminor; | |
+ x = lceil(x, 2*l->dminor) + l->x0; | |
+ if(l->dminor) | |
+ while(_gminor(x-1, l) == y) | |
+ x--; | |
+ return x; | |
+} | |
+ | |
+void | |
+gsetline(Point *pp0, Point *pp1, Linedesc *l) | |
+{ | |
+ long dx, dy, t; | |
+ Point endpt; | |
+ int swapped; | |
+ Point p0, p1; | |
+ | |
+ swapped = 0; | |
+ p0 = *pp0; | |
+ p1 = *pp1; | |
+ l->xmajor = 1; | |
+ l->slopeneg = 0; | |
+ dx = p1.x - p0.x; | |
+ dy = p1.y - p0.y; | |
+ if(abs(dy) > abs(dx)){ /* Steep */ | |
+ l->xmajor = 0; | |
+ XYswap(&p0); | |
+ XYswap(&p1); | |
+ Swap(dx, dy); | |
+ } | |
+ if(dx < 0){ | |
+ swapped++; | |
+ Swap(p0.x, p1.x); | |
+ Swap(p0.y, p1.y); | |
+ dx = -dx; | |
+ dy = -dy; | |
+ } | |
+ if(dy < 0){ | |
+ l->slopeneg = 1; | |
+ dy = -dy; | |
+ p0.y = -p0.y; | |
+ } | |
+ l->dminor = dy; | |
+ l->dmajor = dx; | |
+ l->x0 = p0.x; | |
+ l->y0 = p0.y; | |
+ p1.x = swapped? p0.x+1 : p1.x-1; | |
+ p1.y = _gminor(p1.x, l); | |
+ if(l->xmajor == 0){ | |
+ XYswap(&p0); | |
+ XYswap(&p1); | |
+ } | |
+ if(pp0->x > pp1->x){ | |
+ *pp1 = *pp0; | |
+ *pp0 = p1; | |
+ }else | |
+ *pp1 = p1; | |
+} | |
+/* | |
+ * Modified clip-to-rectangle algorithm | |
+ * works in bitmaps | |
+ * Everything in SCREEN coordinates. | |
+ * | |
+ * Newman & Sproull 124 (1st edition) | |
+ */ | |
+ | |
+static | |
+code(Point *p, Rectangle *r) | |
+{ | |
+ return( (p->x<r->min.x? 1 : p->x>=r->max.x? 2 : 0) | | |
+ (p->y<r->min.y? 4 : p->y>=r->max.y? 8 : 0)); | |
+} | |
+ | |
+int | |
+clipline(Rectangle r, Point *p0, Point *p1) | |
+{ | |
+ Linedesc l; | |
+ | |
+ return _clipline(r, p0, p1, &l); | |
+} | |
+ | |
+int | |
+_clipline(Rectangle r, Point *p0, Point *p1, Linedesc *l) | |
+{ | |
+ int c0, c1, n; | |
+ long t, ret; | |
+ Point temp; | |
+ int swapped; | |
+ | |
+ if(p0->x==p1->x && p0->y==p1->y) | |
+ return 0; | |
+ gsetline(p0, p1, l); | |
+ /* line is now closed */ | |
+ if(l->xmajor == 0){ | |
+ XYswap(p0); | |
+ XYswap(p1); | |
+ XYswap(&r.min); | |
+ XYswap(&r.max); | |
+ } | |
+ c0 = code(p0, &r); | |
+ c1 = code(p1, &r); | |
+ ret = 1; | |
+ swapped = 0; | |
+ n = 0; | |
+ while(c0 | c1){ | |
+ if(c0 & c1){ /* no point of line in r */ | |
+ ret = 0; | |
+ goto Return; | |
+ } | |
+ if(++n > 10){ /* horrible points; overflow etc. etc. */ | |
+ ret = 0; | |
+ goto Return; | |
+ } | |
+ if(c0 == 0){ /* swap points */ | |
+ temp = *p0; | |
+ *p0 = *p1; | |
+ *p1 = temp; | |
+ Swap(c0, c1); | |
+ swapped ^= 1; | |
+ } | |
+ if(c0 == 0) | |
+ break; | |
+ if(c0 & 1){ /* push towards left edge */ | |
+ p0->x = r.min.x; | |
+ p0->y = _gminor(p0->x, l); | |
+ }else if(c0 & 2){ /* push towards right edge */ | |
+ p0->x = r.max.x-1; | |
+ p0->y = _gminor(p0->x, l); | |
+ }else if(c0 & 4){ /* push towards top edge */ | |
+ p0->y = r.min.y; | |
+ if(l->slopeneg) | |
+ p0->x = _gmajor(p0->y-1, l)-1; | |
+ else | |
+ p0->x = _gmajor(p0->y, l); | |
+ }else if(c0 & 8){ /* push towards bottom edge */ | |
+ p0->y = r.max.y-1; | |
+ if(l->slopeneg) | |
+ p0->x = _gmajor(p0->y, l); | |
+ else | |
+ p0->x = _gmajor(p0->y+1, l)-1; | |
+ } | |
+ c0 = code(p0, &r); | |
+ } | |
+ | |
+ Return: | |
+ if(l->xmajor == 0){ | |
+ XYswap(p0); | |
+ XYswap(p1); | |
+ } | |
+ if(swapped){ | |
+ temp = *p0; | |
+ *p0 = *p1; | |
+ *p1 = temp; | |
+ } | |
+ return ret; | |
+} | |
diff --git a/libXg/clipr.c b/libXg/clipr.c | |
@@ -0,0 +1,21 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+int | |
+clipr(Bitmap *d, Rectangle r) | |
+{ | |
+ if(rectclip(&r, d->r) == 0) | |
+ return 0; | |
+ d->clipr = r; | |
+ if(r.min.x != d->r.min.x || | |
+ r.min.y != d->r.min.y || | |
+ r.max.x != d->r.max.x || | |
+ r.max.y != d->r.max.y) | |
+ d->flag |= CLIP; | |
+ else | |
+ d->flag &= ~CLIP; | |
+ return 1; | |
+} | |
diff --git a/libXg/copymasked.c b/libXg/copymasked.c | |
@@ -0,0 +1,49 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+/* | |
+ * m should be a 1-bit-deep bitmap with origin (0,0) and the | |
+ * same extents as r. s should have the same depth as d. | |
+ * Rectangle r of s is copied to d wherever corresponding | |
+ * bits of m are 1 | |
+ */ | |
+void | |
+copymasked(Bitmap *d, Point p, Bitmap *s, Bitmap *m, Rectangle r) | |
+{ | |
+ int sx, sy, dx, dy; | |
+ XGCValues gcv; | |
+ GC g; | |
+ | |
+ if(Dx(r)<=0 || Dy(r)<=0) | |
+ return; | |
+ sx = r.min.x; | |
+ sy = r.min.y; | |
+ if(s->flag&SHIFT){ | |
+ sx -= s->r.min.x; | |
+ sy -= s->r.min.y; | |
+ } | |
+ dx = p.x; | |
+ dy = p.y; | |
+ if(d->flag&SHIFT){ | |
+ dx -= d->r.min.x; | |
+ dy -= d->r.min.y; | |
+ } | |
+ gcv.fill_style = FillStippled; | |
+ gcv.stipple = (Pixmap)m->id; | |
+ gcv.function = GXclear; | |
+ gcv.ts_x_origin = dx; | |
+ gcv.ts_y_origin = dy; | |
+ gcv.fill_style = FillStippled; | |
+ g = _getgc(d, GCFunction|GCStipple|GCTileStipXOrigin | |
+ |GCTileStipYOrigin|GCFillStyle, &gcv); | |
+ XFillRectangle(_dpy, (Drawable)d->id, g, | |
+ dx, dy, Dx(r), Dy(r)); | |
+ gcv.function = GXor; | |
+ gcv.fill_style = FillSolid; | |
+ g = _getgc(d, GCFunction|GCFillStyle, &gcv); | |
+ XCopyArea(_dpy, (Drawable)s->id, (Drawable)d->id, g, | |
+ sx, sy, Dx(r), Dy(r), dx, dy); | |
+} | |
diff --git a/libXg/cursorset.c b/libXg/cursorset.c | |
@@ -0,0 +1,16 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+/* | |
+ * Only allow cursor to move within screen Bitmap | |
+ */ | |
+void | |
+cursorset(Point p) | |
+{ | |
+ /* motion will be relative to window origin */ | |
+ p = sub(p, screen.r.min); | |
+ XWarpPointer(_dpy, None, (Window)screen.id, 0, 0, 0, 0, p.x, p.y); | |
+} | |
diff --git a/libXg/cursorswitch.c b/libXg/cursorswitch.c | |
@@ -0,0 +1,66 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+/* | |
+ * Use the id field in Cursor to hold the X id corresponding | |
+ * to the cursor, so that it doesn't have to be recreated on | |
+ * each cursorswitch. This doesn't quite match the semantics | |
+ * of Plan9 libg, since the user could create a cursor (say | |
+ * with malloc) with garbage in the id field; or the user | |
+ * could change the contents of the other fields and we | |
+ * wouldn't know about it. Neither of these happen in | |
+ * existing uses of libg. | |
+ */ | |
+static Cursor arrow = | |
+{ | |
+ {-1, -1}, | |
+ {0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0x00, | |
+ 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0, | |
+ 0xE7, 0xF0, 0xE3, 0xF8, 0xC1, 0xFC, 0x00, 0xFE, | |
+ 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, | |
+ }, | |
+ {0x00, 0x00, 0x7F, 0xC0, 0x7F, 0x00, 0x7C, 0x00, | |
+ 0x7E, 0x00, 0x7F, 0x00, 0x6F, 0x80, 0x67, 0xC0, | |
+ 0x43, 0xE0, 0x41, 0xF0, 0x00, 0xF8, 0x00, 0x7C, | |
+ 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, | |
+ } | |
+}; | |
+ | |
+static Bitmap *bsrc, *bmask; | |
+static Rectangle crect = { 0, 0, 16, 16 }; | |
+ | |
+void | |
+cursorswitch(Cursor *c) | |
+{ | |
+ if(c == 0) | |
+ c = &arrow; | |
+ if(c->id == 0){ | |
+ if(bsrc == 0){ | |
+ bsrc = balloc(crect, 0); | |
+ bmask = balloc(crect, 0); | |
+ } | |
+ /* | |
+ * Cursor should have fg where "set" is 1, | |
+ * and bg where "clr" is 1 and "set" is 0, | |
+ * and should leave places alone where "set" and "clr" are bot… | |
+ */ | |
+ wrbitmap(bsrc, 0, 16, c->set); | |
+#ifdef CURSORBUG | |
+ /* | |
+ * Some X servers (e.g., Sun X-on-news for some color | |
+ * monitors) don't do XCreatePixmapCursor properly: | |
+ * only the mask gets displayed, all black | |
+ */ | |
+ wrbitmap(bmask, 0, 16, c->set); | |
+#else | |
+ wrbitmap(bmask, 0, 16, c->clr); | |
+ bitblt(bmask, Pt(0,0), bsrc, crect, S|D); | |
+#endif | |
+ c->id = (int) XCreatePixmapCursor(_dpy, (Pixmap)bsrc->id, (Pix… | |
+ &_fgcolor, &_bgcolor, -c->offset.x, -c->offset.y); | |
+ } | |
+ XDefineCursor(_dpy, (Window)screen.id, (xCursor)c->id); | |
+} | |
diff --git a/libXg/disc.c b/libXg/disc.c | |
@@ -0,0 +1,23 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+disc(Bitmap *b, Point p, int r, int v, Fcode f) | |
+{ | |
+ unsigned int d; | |
+ int x, y; | |
+ GC g; | |
+ | |
+ x = p.x - r; | |
+ y = p.y - r; | |
+ if (b->flag&SHIFT){ | |
+ x -= b->r.min.x; | |
+ y -= b->r.min.y; | |
+ } | |
+ d = 2*r; | |
+ g = _getfillgc(f, b, v); | |
+ XFillArc(_dpy, (Drawable)b->id, g, x, y, d, d, 0, 23040/* 360 deg */); | |
+} | |
diff --git a/libXg/ellipse.c b/libXg/ellipse.c | |
@@ -0,0 +1,23 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+/* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */ | |
+ | |
+void | |
+ellipse(Bitmap *bp, Point p, int a, int b, int v, Fcode f) | |
+{ | |
+ int x, y; | |
+ GC g; | |
+ | |
+ x = p.x - a; | |
+ y = p.y - b; | |
+ if (bp->flag&SHIFT){ | |
+ x -= bp->r.min.x; | |
+ y -= bp->r.min.y; | |
+ } | |
+ g = _getfillgc(f, bp, v); | |
+ XDrawArc(_dpy, (Drawable)bp->id, g, x, y, 2*a, 2*b, 0, 23040/* 360 deg… | |
+} | |
diff --git a/libXg/font.c b/libXg/font.c | |
@@ -0,0 +1,18 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+#define PJW 0 /* use NUL==pjw for invisible characters */ | |
+ | |
+long | |
+charwidth(XftFont *f, Rune r) | |
+{ | |
+ | |
+ char chars[UTFmax + 1] = {0}; | |
+ | |
+ runetochar(chars, &r); | |
+ return strwidth(f, chars); | |
+} | |
+ | |
diff --git a/libXg/gcs.c b/libXg/gcs.c | |
@@ -0,0 +1,401 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+/* | |
+ * Libg applications are written assuming that black is ~0 | |
+ * and white is 0. Some screens use the reverse convention. | |
+ * We get the effect the application desired by seeing what | |
+ * happens if both the source and dest are converted to the | |
+ * black==~0 convention, and then converting the dest back | |
+ * to whatever convention it uses. | |
+ * | |
+ * Offscreen bitmaps of depth 1 use the black==~0 convention. | |
+ * | |
+ * Bitmaps of depth > 1 are probably in color. Libg operations that | |
+ * would produce a 1 should produce the foreground color, and | |
+ * libg operations that would produce a 0 should produce the background | |
+ * color. Operations that use bitmaps of depth > 1 as source | |
+ * should interpret the foreground pixel as "black" (1) and the | |
+ * background pixel as "white" (0). It is hard to make this work, | |
+ * but the important cases are Fcodes Zero, F, S, and S^D, so | |
+ * we make sure that those work. When a fill value is given for | |
+ * a bitmap of depth > 1, assume ~0 means foreground, but otherwise | |
+ * take any other value literally (assume it came from rgbpix). | |
+ * This may be wrong for the case of 0, but libg programmers | |
+ * usually use Fcode Zero instead of passing 0 with Fcode S. | |
+ * | |
+ * We assume there are at most two depths of bitmaps: depth 1 | |
+ * and depth of the screen. | |
+ */ | |
+ | |
+/* | |
+ * gx func code corresponding to libg func code when both | |
+ * source and dest use 1 for black. This is a straight translation. | |
+ */ | |
+static int gx[16] = { | |
+ GXclear, /* Zero */ | |
+ GXnor, /* DnorS */ | |
+ GXandInverted, /* DandnotS */ | |
+ GXcopyInverted, /* notS */ | |
+ GXandReverse, /* notDandS */ | |
+ GXinvert, /* notD */ | |
+ GXxor, /* DxorS */ | |
+ GXnand, /* DnandS */ | |
+ GXand, /* DandS */ | |
+ GXequiv, /* DxnorS */ | |
+ GXnoop, /* D */ | |
+ GXorInverted, /* DornotS */ | |
+ GXcopy, /* S */ | |
+ GXorReverse, /* notDorS */ | |
+ GXor, /* DorS */ | |
+ GXset, /* F */ | |
+}; | |
+ | |
+/* | |
+ * gx func code corresponding to libg func code when 0 means black | |
+ * in dst and 1 means black in src. These means the table has op' | |
+ * where dst <- dst op' src == not ( not(dst) op src ). | |
+ * The comment on each line is op, in Fcode terms. | |
+ */ | |
+static int d0s1gx[16] = { | |
+ GXset, /* Zero */ | |
+ GXorReverse, /* DnorS */ | |
+ GXor, /* DandnotS */ | |
+ GXcopy, /* notS */ | |
+ GXnand, /* notDandS */ | |
+ GXinvert, /* notD */ | |
+ GXxor, /* DxorS */ | |
+ GXandReverse, /* DnandS */ | |
+ GXorInverted, /* DandS */ | |
+ GXequiv, /* DxnorS */ | |
+ GXnoop, /* D */ | |
+ GXand, /* DornotS */ | |
+ GXcopyInverted, /* S */ | |
+ GXnor, /* notDorS */ | |
+ GXandInverted, /* DorS */ | |
+ GXclear, /* F */ | |
+}; | |
+/* | |
+ * gx func code corresponding to libg func code when 1 means black | |
+ * in dst and 0 means black in src. These means the table has op' | |
+ * where dst <- dst op' src == dst op not(src) ) | |
+ * The comment on each line is op, in Fcode terms. | |
+ */ | |
+static int d1s0gx[16] = { | |
+ GXclear, /* Zero */ | |
+ GXandReverse, /* DnorS */ | |
+ GXand, /* DandnotS */ | |
+ GXcopy, /* notS */ | |
+ GXnor, /* notDandS */ | |
+ GXinvert, /* notD */ | |
+ GXequiv, /* DxorS */ | |
+ GXorReverse, /* DnandS */ | |
+ GXandInverted, /* DandS */ | |
+ GXxor, /* DxnorS */ | |
+ GXnoop, /* D */ | |
+ GXor, /* DornotS */ | |
+ GXcopyInverted, /* S */ | |
+ GXnand, /* notDorS */ | |
+ GXorInverted, /* DorS */ | |
+ GXset, /* F */ | |
+}; | |
+ | |
+/* | |
+ * gx func code corresponding to libg func code when 0 means black | |
+ * in both the src and the dst. These means the table has op' | |
+ * where dst <- dst op' src == not (not(dst) op not(src)) ) | |
+ * The comment on each line is op, in Fcode terms. | |
+ */ | |
+static int d0s0gx[16] = { | |
+ GXset, /* Zero */ | |
+ GXnand, /* DnorS */ | |
+ GXorInverted, /* DandnotS */ | |
+ GXcopyInverted, /* notS */ | |
+ GXorReverse, /* notDandS */ | |
+ GXinvert, /* notD */ | |
+ GXequiv, /* DxorS */ | |
+ GXnor, /* DnandS */ | |
+ GXor, /* DandS */ | |
+ GXxor, /* DxnorS */ | |
+ GXnoop, /* D */ | |
+ GXandInverted, /* DornotS */ | |
+ GXcopy, /* S */ | |
+ GXandReverse, /* notDorS */ | |
+ GXand, /* DorS */ | |
+ GXclear, /* F */ | |
+}; | |
+ | |
+/* | |
+ * 1 for those Fcodes that are degenerate (don't involve src) | |
+ */ | |
+static int degengc[16] = { | |
+ 1, /* Zero */ | |
+ 0, /* DnorS */ | |
+ 0, /* DandnotS */ | |
+ 0, /* notS */ | |
+ 0, /* notDandS */ | |
+ 1, /* notD */ | |
+ 0, /* DxorS */ | |
+ 0, /* DnandS */ | |
+ 0, /* DandS */ | |
+ 0, /* DxnorS */ | |
+ 1, /* D */ | |
+ 0, /* DornotS */ | |
+ 0, /* S */ | |
+ 0, /* notDorS */ | |
+ 0, /* DorS */ | |
+ 1, /* F */ | |
+}; | |
+ | |
+/* | |
+ * GCs are all for same screen, and depth is either 1 or screen depth. | |
+ * Return a GC for the depth of b, with values as specified by gcv. | |
+ * | |
+ * Also, set (or unset) the clip rectangle if necessary. | |
+ * (This implementation should be improved if setting a clip rectangle is not … | |
+ */ | |
+GC | |
+_getgc(Bitmap *b, unsigned long gcvm, XGCValues *pgcv) | |
+{ | |
+ static GC gc0, gcn; | |
+ static clipset = 0; | |
+ GC g; | |
+ XRectangle xr; | |
+ | |
+ g = (b->ldepth==0)? gc0 : gcn; | |
+ if(!g){ | |
+ g = XCreateGC(_dpy, (Drawable)b->id, gcvm, pgcv); | |
+ if(b->ldepth==0) | |
+ gc0 = g; | |
+ else | |
+ gcn = g; | |
+ } else | |
+ XChangeGC(_dpy, g, gcvm, pgcv); | |
+ if(b->flag&CLIP){ | |
+ xr.x = b->clipr.min.x; | |
+ xr.y = b->clipr.min.y; | |
+ xr.width = Dx(b->clipr); | |
+ xr.height = Dy(b->clipr); | |
+ if(b->flag&SHIFT){ | |
+ xr.x -= b->r.min.x; | |
+ xr.y -= b->r.min.y; | |
+ } | |
+ XSetClipRectangles(_dpy, g, 0, 0, &xr, 1, YXBanded); | |
+ clipset = 1; | |
+ }else if(clipset){ | |
+ pgcv->clip_mask = None; | |
+ XChangeGC(_dpy, g, GCClipMask, pgcv); | |
+ clipset = 0; | |
+ } | |
+ return g; | |
+} | |
+ | |
+/* | |
+ * Return a GC that will fill bitmap b using a pixel value v and Fcode f. | |
+ * Pixel value v is according to libg convention, so 0 means | |
+ * white (or background) and ~0 means black (or foreground). | |
+ */ | |
+GC | |
+_getfillgc(Fcode f, Bitmap *b, unsigned long val) | |
+{ | |
+ int xf, m; | |
+ unsigned long v, fg, bg, spix, vmax; | |
+ XGCValues gcv; | |
+ | |
+ f &= F; | |
+ vmax = _ld2dmask[b->ldepth]; | |
+ v = val & vmax; | |
+ spix = v; | |
+ xf = GXcopy; | |
+ m = b->flag; | |
+ if(m & DP1){ | |
+ xf = (m&BL1)? gx[f] : d0s1gx[f]; | |
+ }else{ | |
+ fg = _fgpixel; | |
+ bg = _bgpixel; | |
+ switch(f){ | |
+ case Zero: | |
+ labZero: | |
+ spix = bg; | |
+ break; | |
+ case F: | |
+ labF: | |
+ spix = fg; | |
+ break; | |
+ case D: | |
+ labD: | |
+ xf = GXnoop; | |
+ break; | |
+ case notD: | |
+ labnotD: | |
+ xf = GXxor; | |
+ spix = fg^bg; | |
+ break; | |
+ case S: | |
+ if(val == ~0) | |
+ spix = fg; | |
+ else | |
+ spix = v; | |
+ break; | |
+ case notS: | |
+ if(val == ~0) | |
+ spix = bg; | |
+ else | |
+ spix = v; | |
+ break; | |
+ case DxorS: | |
+ xf = GXxor; | |
+ if(val == ~0) | |
+ spix = fg^bg; | |
+ else | |
+ spix = v; | |
+ break; | |
+ case DxnorS: | |
+ xf = GXxor; | |
+ if(val == 0) | |
+ spix = fg^bg; | |
+ else | |
+ spix = v; | |
+ break; | |
+ default: | |
+ /* hard to do anything other than v==0 or v==~0 case */ | |
+ if(v < vmax-v){ | |
+ /* v is closer to 0 than vmax */ | |
+ switch(f&~S){ | |
+ case D&~S: goto labD; | |
+ case notD&~S: goto labnotD; | |
+ case Zero&~S: goto labZero; | |
+ case F&~S: goto labF; | |
+ } | |
+ }else{ | |
+ /* v is closer to vmax than 0 */ | |
+ switch(f&S){ | |
+ case D&S: goto labD; | |
+ case notD&S: goto labnotD; | |
+ case Zero&S: goto labZero; | |
+ case F&S: goto labF; | |
+ } | |
+ } | |
+ | |
+ } | |
+ } | |
+ gcv.foreground = spix; | |
+ gcv.function = xf; | |
+ return _getgc(b, GCForeground|GCFunction, &gcv); | |
+} | |
+ | |
+/* | |
+ * Return a GC to be used to copy an area from bitmap sb to | |
+ * bitmap db. Sometimes the calling function shouldn't use | |
+ * XCopyArea, but instead should use XCopyPlane or XFillRectangle. | |
+ * The *bltfunc arg is set to one of UseCopyArea, UseCopyPlane, | |
+ * UseFillRectangle. | |
+ */ | |
+GC | |
+_getcopygc(Fcode f, Bitmap *db, Bitmap *sb, int *bltfunc) | |
+{ | |
+ unsigned long spix, bg, fg, df, sf; | |
+ int xf, c; | |
+ XGCValues gcv; | |
+ unsigned long gcvm; | |
+ | |
+ f &= F; | |
+ gcvm = 0; | |
+ df = db->flag; | |
+ if(degengc[f]){ | |
+ *bltfunc = UseFillRectangle; | |
+ if(df&SCR || !(df&DP1)){ | |
+ fg = _fgpixel; | |
+ bg = _bgpixel; | |
+ }else{ | |
+ /* must be DP1 and BL1 */ | |
+ fg = 1; | |
+ bg = 0; | |
+ } | |
+ switch(f){ | |
+ case Zero: | |
+ xf = GXcopy; | |
+ spix = bg; | |
+ break; | |
+ case F: | |
+ xf = GXcopy; | |
+ spix = fg; | |
+ break; | |
+ case D: | |
+ xf = GXnoop; | |
+ spix = fg; | |
+ break; | |
+ case notD: | |
+ xf = GXxor; | |
+ spix = fg^bg; | |
+ break; | |
+ } | |
+ gcv.function = xf; | |
+ gcv.foreground = spix; | |
+ gcvm = GCFunction|GCForeground; | |
+ }else{ | |
+ /* src is involved in f */ | |
+ | |
+#define code(f1,f2) ((((f1)&(DP1|BL1))<<2)|((f2)&(DP1|BL1))) | |
+ | |
+ sf = sb->flag; | |
+ c = code(df,sf); | |
+ *bltfunc = UseCopyArea; | |
+ switch(code(df,sf)){ | |
+ case code(DP1|BL1,DP1|BL1): | |
+ case code(BL1,BL1): | |
+ xf = gx[f]; | |
+ break; | |
+ case code(DP1|BL1,DP1): | |
+ xf = d1s0gx[f]; | |
+ break; | |
+ case code(DP1,DP1|BL1): | |
+ xf = d0s1gx[f]; | |
+ break; | |
+ case code(DP1,DP1): | |
+ case code(0,0): | |
+ xf = d0s0gx[f]; | |
+ break; | |
+ default: | |
+ /* | |
+ * One bitmap has depth 1, the other has screen depth. | |
+ * We know the bitmap must have BL1. | |
+ * CopyPlane must be used; it won't really work | |
+ * for more than fcode==S. | |
+ */ | |
+ | |
+ *bltfunc = UseCopyPlane; | |
+ xf = GXcopy; | |
+ switch(c){ | |
+ | |
+ case code(0,DP1|BL1): | |
+ case code(BL1,DP1|BL1): | |
+ fg = _fgpixel; | |
+ bg = _bgpixel; | |
+ break; | |
+ case code(DP1|BL1,0): | |
+ fg = 0; | |
+ bg = 1; | |
+ break; | |
+ case code(DP1|BL1,BL1): | |
+ fg = 1; | |
+ bg = 0; | |
+ break; | |
+ default: | |
+ berror("bad combination of copy bitmaps"); | |
+ } | |
+ gcv.foreground = fg; | |
+ gcv.background = bg; | |
+ gcvm |= GCForeground|GCBackground; | |
+ } | |
+ gcv.function = xf; | |
+ gcvm |= GCFunction; | |
+ | |
+#undef code | |
+ } | |
+ | |
+ return _getgc(db, gcvm, &gcv); | |
+} | |
diff --git a/libXg/getrect.c b/libXg/getrect.c | |
@@ -0,0 +1,73 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+static Cursor sweep={ | |
+ {-7, -7}, | |
+ {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, | |
+ 0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7, | |
+ 0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F, | |
+ 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,}, | |
+ {0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02, | |
+ 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2, | |
+ 0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38, | |
+ 0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,} | |
+}; | |
+ | |
+static void | |
+grabcursor(void) | |
+{ | |
+ /* Grab X server with an limp wrist. */ | |
+ while (XGrabPointer(_dpy, screen.id, False, | |
+ ButtonPressMask|ButtonReleaseMask| | |
+ ButtonMotionMask|StructureNotifyMask, | |
+ GrabModeAsync, GrabModeAsync, None, None, CurrentTime) | |
+ != GrabSuccess) | |
+ sleep(2); | |
+ /* Grab the keyboard too */ | |
+ XSetInputFocus(_dpy, screen.id, RevertToParent, CurrentTime); | |
+} | |
+ | |
+static void | |
+ungrabcursor(void) | |
+{ | |
+ XUngrabPointer(_dpy, CurrentTime); | |
+} | |
+ | |
+Rectangle | |
+getrect(int but, Mouse *m){ | |
+ Rectangle r, rc; | |
+ | |
+ but = 1<<(but-1); | |
+ cursorswitch(&sweep); | |
+ while(m->buttons) | |
+ *m = emouse(); | |
+ grabcursor(); | |
+ while(!(m->buttons & but)){ | |
+ *m = emouse(); | |
+ if(m->buttons & (7^but)) | |
+ goto Return; | |
+ } | |
+ r.min = m->xy; | |
+ r.max = m->xy; | |
+ do{ | |
+ rc = rcanon(r); | |
+ border(&screen, rc, 2, F&~D); | |
+ *m = emouse(); | |
+ border(&screen, rc, 2, F&~D); | |
+ r.max = m->xy; | |
+ }while(m->buttons & but); | |
+ | |
+ Return: | |
+ cursorswitch((Cursor *)0); | |
+ if(m->buttons & (7^but)){ | |
+ rc.min.x = rc.max.x = 0; | |
+ rc.min.y = rc.max.y = 0; | |
+ while(m->buttons) | |
+ *m = emouse(); | |
+ } | |
+ ungrabcursor(); | |
+ return rc; | |
+} | |
diff --git a/libXg/gwin.c b/libXg/gwin.c | |
@@ -0,0 +1,466 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <stdio.h> | |
+#if defined(v10) || defined(HPUX) | |
+typedef char* caddr_t; | |
+#endif | |
+#include <X11/IntrinsicP.h> | |
+#include <X11/StringDefs.h> | |
+#include <X11/Xatom.h> | |
+#include <X11/keysym.h> | |
+ | |
+#ifndef XtSpecificationRelease | |
+#define R3 | |
+#define XtPointer caddr_t | |
+#define XtOffsetOf(s_type,field) XtOffset(s_type*,field) | |
+#define XtExposeCompressMultiple TRUE | |
+#endif | |
+ | |
+#include "GwinP.h" | |
+ | |
+/* Forward declarations */ | |
+static void Realize(Widget, XtValueMask *, XSetWindowAttributes *); | |
+static void Resize(Widget); | |
+static void Redraw(Widget, XEvent *, Region); | |
+static void Mappingaction(Widget, XEvent *, String *, Cardinal*); | |
+static void Keyaction(Widget, XEvent *, String *, Cardinal*); | |
+static void Mouseaction(Widget, XEvent *, String *, Cardinal*); | |
+static String SelectSwap(Widget, String); | |
+ | |
+/* Data */ | |
+ | |
+#define Offset(field) XtOffsetOf(GwinRec, gwin.field) | |
+ | |
+static XtResource resources[] = { | |
+ {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), | |
+ Offset(foreground), XtRString, (XtPointer)XtDefaultForeground}, | |
+ {XtNscrollForwardR, XtCScrollForwardR, XtRBoolean, sizeof(Boolean), | |
+ Offset(forwardr), XtRImmediate, (XtPointer)TRUE}, | |
+ {XtNreshaped, XtCReshaped, XtRFunction, sizeof(Reshapefunc), | |
+ Offset(reshaped), XtRFunction, (XtPointer) NULL}, | |
+ {XtNgotchar, XtCGotchar, XtRFunction, sizeof(Charfunc), | |
+ Offset(gotchar), XtRFunction, (XtPointer) NULL}, | |
+ {XtNgotmouse, XtCGotmouse, XtRFunction, sizeof(Mousefunc), | |
+ Offset(gotmouse), XtRFunction, (XtPointer) NULL}, | |
+ {XtNselection, XtCSelection, XtRString, sizeof(String), | |
+ Offset(selection), XtRString, (XtPointer) NULL}, | |
+ {XtNcomposeMod, XtCComposeMod, XtRInt, sizeof(int), | |
+ Offset(compose), XtRImmediate, (XtPointer) 0} | |
+}; | |
+#undef Offset | |
+ | |
+static XtActionsRec actions[] = { | |
+ {"key", Keyaction}, | |
+ {"mouse", Mouseaction}, | |
+ {"mapping", Mappingaction} | |
+}; | |
+ | |
+static char tms[] = | |
+ "<Key> : key() \n\ | |
+ <Motion> : mouse() \n\ | |
+ <BtnDown> : mouse() \n\ | |
+ <BtnUp> : mouse() \n\ | |
+ <Mapping> : mapping() \n"; | |
+ | |
+/* Class record declaration */ | |
+ | |
+GwinClassRec gwinClassRec = { | |
+ /* Core class part */ | |
+ { | |
+ /* superclass */ (WidgetClass)&widgetClassRec, | |
+ /* class_name */ "Gwin", | |
+ /* widget_size */ sizeof(GwinRec), | |
+ /* class_initialize */ NULL, | |
+ /* class_part_initialize*/ NULL, | |
+ /* class_inited */ FALSE, | |
+ /* initialize */ NULL, | |
+ /* initialize_hook */ NULL, | |
+ /* realize */ Realize, | |
+ /* actions */ actions, | |
+ /* num_actions */ XtNumber(actions), | |
+ /* resources */ resources, | |
+ /* num_resources */ XtNumber(resources), | |
+ /* xrm_class */ NULLQUARK, | |
+ /* compress_motion */ TRUE, | |
+ /* compress_exposure */ XtExposeCompressMultiple, | |
+ /* compress_enterleave*/ TRUE, | |
+ /* visible_interest */ FALSE, | |
+ /* destroy */ NULL, | |
+ /* resize */ Resize, | |
+ /* expose */ Redraw, | |
+ /* set_values */ NULL, | |
+ /* set_values_hook */ NULL, | |
+ /* set_values_almost */ XtInheritSetValuesAlmost, | |
+ /* get_values_hook */ NULL, | |
+ /* accept_focus */ XtInheritAcceptFocus, | |
+ /* version */ XtVersion, | |
+ /* callback_offsets */ NULL, | |
+ /* tm_table */ tms, | |
+ /* query_geometry */ XtInheritQueryGeometry, | |
+ /* display_accelerator */ NULL, | |
+ /* extension */ NULL | |
+ }, | |
+ /* Gwin class part */ | |
+ { | |
+ /* select_swap */ SelectSwap, | |
+ } | |
+}; | |
+ | |
+/* Class record pointer */ | |
+WidgetClass gwinWidgetClass = (WidgetClass) &gwinClassRec; | |
+ | |
+static XModifierKeymap *modmap; | |
+static int keypermod; | |
+ | |
+static void | |
+Realize(Widget w, XtValueMask *valueMask, XSetWindowAttributes *attrs) | |
+{ | |
+ XtValueMask mask; | |
+ | |
+ *valueMask |= CWBackingStore; | |
+ attrs->backing_store = Always; | |
+ | |
+ XtCreateWindow(w, InputOutput, (Visual *)0, *valueMask, attrs); | |
+ XtSetKeyboardFocus(w->core.parent, w); | |
+ if (modmap = XGetModifierMapping(XtDisplay(w))) | |
+ keypermod = modmap->max_keypermod; | |
+ | |
+ Resize(w); | |
+} | |
+ | |
+static void | |
+Resize(Widget w) | |
+{ | |
+ if(XtIsRealized(w)) | |
+ (*(XtClass(w)->core_class.expose))(w, (XEvent *)NULL, (Region)… | |
+} | |
+ | |
+static void | |
+Redraw(Widget w, XEvent *e, Region r) | |
+{ | |
+ Reshapefunc f; | |
+ | |
+ f = ((GwinWidget)w)->gwin.reshaped; | |
+ if(f) | |
+ (*f)(w->core.x, w->core.y, | |
+ w->core.x+w->core.width, w->core.y+w->core.height); | |
+} | |
+ | |
+static void | |
+Mappingaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
+{ | |
+ if (modmap) | |
+ XFreeModifiermap(modmap); | |
+ modmap = XGetModifierMapping(e->xany.display); | |
+ if (modmap) | |
+ keypermod = modmap->max_keypermod; | |
+} | |
+ | |
+#define STUFFCOMPOSE() \ | |
+ f = ((GwinWidget)w)->gwin.gotchar; \ | |
+ if (f) \ | |
+ for (c = 0; c < composing; c++) \ | |
+ (*f)(compose[c]) | |
+ | |
+static void | |
+Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
+{ | |
+ static unsigned char compose[5]; | |
+ static int composing = -2; | |
+ | |
+ int c, minmod; | |
+ KeySym k, mk; | |
+ Charfunc f; | |
+ Modifiers md; | |
+ | |
+ /* | |
+ * I tried using XtGetActionKeysym, but it didn't seem to | |
+ * do case conversion properly | |
+ * (at least, with Xterminal servers and R4 intrinsics) | |
+ */ | |
+ if(e->xany.type != KeyPress) | |
+ return; | |
+ XtTranslateKeycode(e->xany.display, (KeyCode)e->xkey.keycode, | |
+ e->xkey.state, &md, &k); | |
+ /* | |
+ * The following song and dance is so we can have our chosen | |
+ * modifier key behave like a compose key, i.e, press and release | |
+ * and then type the compose sequence, like Plan 9. We have | |
+ * to find out which key is the compose key first 'though. | |
+ */ | |
+ if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose | |
+ && composing == -2 && modmap) { | |
+ minmod = (((GwinWidget)w)->gwin.compose+2)*keypermod; | |
+ for (c = minmod; c < minmod+keypermod; c++) { | |
+ XtTranslateKeycode(e->xany.display, | |
+ modmap->modifiermap[c], | |
+ e->xkey.state, &md, &mk); | |
+ if (k == mk) { | |
+ composing = -1; | |
+ break; | |
+ } | |
+ } | |
+ return; | |
+ } | |
+ /* Handle Multi_key separately, since it isn't a modifier */ | |
+ if(k == XK_Multi_key) { | |
+ composing = -1; | |
+ return; | |
+ } | |
+ if(k == NoSymbol) | |
+ return; | |
+ if(k&0xFF00){ | |
+ switch(k){ | |
+ case XK_BackSpace: | |
+ case XK_Tab: | |
+ case XK_Escape: | |
+ case XK_Delete: | |
+ case XK_KP_0: | |
+ case XK_KP_1: | |
+ case XK_KP_2: | |
+ case XK_KP_3: | |
+ case XK_KP_4: | |
+ case XK_KP_5: | |
+ case XK_KP_6: | |
+ case XK_KP_7: | |
+ case XK_KP_8: | |
+ case XK_KP_9: | |
+ case XK_KP_Divide: | |
+ case XK_KP_Multiply: | |
+ case XK_KP_Subtract: | |
+ case XK_KP_Add: | |
+ case XK_KP_Decimal: | |
+ k &= 0x7F; | |
+ break; | |
+ case XK_Linefeed: | |
+ k = '\r'; | |
+ break; | |
+ case XK_KP_Enter: | |
+ case XK_Return: | |
+ k = '\n'; | |
+ break; | |
+ case XK_Left: | |
+ case XK_Down: | |
+ case XK_Right: | |
+ case XK_Next: | |
+ k = 0x80; /* VIEW -- "Scroll" */ | |
+ break; | |
+ case XK_Up: | |
+ case XK_Prior: | |
+ k = 0x81; /* PREVIEW -- "Scroll back" */ | |
+ break; | |
+ default: | |
+ return; /* not ISO-1 or tty control */ | |
+ } | |
+ } | |
+ /* Compensate for servers that call a minus a hyphen */ | |
+ if(k == XK_hyphen) | |
+ k = XK_minus; | |
+ /* Do control mapping ourselves if translator doesn't */ | |
+ if((e->xkey.state&ControlMask) && !(md&ControlMask)) | |
+ k &= 0x9f; | |
+ if(k == NoSymbol) | |
+ return; | |
+ /* Check to see if we are in a composition sequence */ | |
+ if (!((GwinWidget)w)->gwin.compose && (e->xkey.state & Mod1Mask) | |
+ && composing == -2) | |
+ composing = -1; | |
+ if (composing > -2) { | |
+ compose[++composing] = k; | |
+ if ((*compose == 'X') && (composing > 0)) { | |
+ if ((k < '0') || (k > 'f') || | |
+ ((k > '9') && (k < 'a'))) { | |
+ STUFFCOMPOSE(); | |
+ c = (unsigned short)k; | |
+ composing = -2; | |
+ } else if (composing == 4) { | |
+ c = (int)unicode(compose); | |
+ if (c == -1) { | |
+ STUFFCOMPOSE(); | |
+ c = (unsigned short)compose[4]; | |
+ } | |
+ composing = -2; | |
+ } | |
+ } else if (composing == 1) { | |
+ c = (int)latin1(compose); | |
+ if (c == -1) { | |
+ STUFFCOMPOSE(); | |
+ c = (unsigned short)compose[1]; | |
+ } | |
+ composing = -2; | |
+ } | |
+ } else { | |
+ if (composing >= 0) { | |
+ composing++; | |
+ STUFFCOMPOSE(); | |
+ } | |
+ c = (unsigned short)k; | |
+ composing = -2; | |
+ } | |
+ | |
+ if (composing >= -1) | |
+ return; | |
+ | |
+ f = ((GwinWidget)w)->gwin.gotchar; | |
+ if(f) | |
+ (*f)(c); | |
+} | |
+ | |
+static void | |
+Mouseaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
+{ | |
+ int s; | |
+ XButtonEvent *be; | |
+ XMotionEvent *me; | |
+ Gwinmouse m; | |
+ Mousefunc f; | |
+ | |
+ switch(e->type){ | |
+ case ButtonPress: | |
+ be = (XButtonEvent *)e; | |
+ m.xy.x = be->x; | |
+ m.xy.y = be->y; | |
+ m.msec = be->time; | |
+ s = be->state; /* the previous state */ | |
+ switch(be->button){ | |
+ case 1: s |= Button1Mask; break; | |
+ case 2: s |= Button2Mask; break; | |
+ case 3: s |= Button3Mask; break; | |
+ case 4: s |= Button4Mask; break; | |
+ } | |
+ break; | |
+ case ButtonRelease: | |
+ be = (XButtonEvent *)e; | |
+ m.xy.x = be->x; | |
+ m.xy.y = be->y; | |
+ m.msec = be->time; | |
+ s = be->state; | |
+ switch(be->button){ | |
+ case 1: s &= ~Button1Mask; break; | |
+ case 2: s &= ~Button2Mask; break; | |
+ case 3: s &= ~Button3Mask; break; | |
+ case 4: s &= ~Button4Mask; break; | |
+ } | |
+ break; | |
+ case MotionNotify: | |
+ me = (XMotionEvent *)e; | |
+ s = me->state; | |
+ m.xy.x = me->x; | |
+ m.xy.y = me->y; | |
+ m.msec = me->time; | |
+ break; | |
+ default: | |
+ return; | |
+ } | |
+ m.buttons = 0; | |
+ if(s & Button1Mask) m.buttons |= 1; | |
+ if(s & Button2Mask) m.buttons |= 2; | |
+ if(s & Button3Mask) m.buttons |= 4; | |
+ if(s & Button4Mask) m.buttons |= 8; | |
+ f = ((GwinWidget)w)->gwin.gotmouse; | |
+ if(f) | |
+ (*f)(&m); | |
+} | |
+ | |
+static void | |
+SelCallback(Widget w, XtPointer cldata, Atom *sel, Atom *seltype, | |
+ XtPointer val, unsigned long *len, int *fmt) | |
+{ | |
+ String s; | |
+ int n; | |
+ GwinWidget gw = (GwinWidget)w; | |
+ | |
+ if(gw->gwin.selection) | |
+ XtFree(gw->gwin.selection); | |
+ if(*seltype != XA_STRING) | |
+ n = 0; | |
+ else | |
+ n = (*len) * (*fmt/8); | |
+ s = (String)XtMalloc(n+1); | |
+ if(n > 0) | |
+ memcpy(s, (char *)val, n); | |
+ s[n] = 0; | |
+ gw->gwin.selection = s; | |
+ XtFree(val); | |
+} | |
+ | |
+static Boolean | |
+SendSel(Widget w, Atom *sel, Atom *target, Atom *rtype, XtPointer *ans, | |
+ unsigned long *anslen, int *ansfmt) | |
+{ | |
+ GwinWidget gw = (GwinWidget)w; | |
+ static Atom targets = 0; | |
+ XrmValue src, dst; | |
+ char *s; | |
+ | |
+ if(*target == XA_STRING){ | |
+ s = gw->gwin.selection; | |
+ if(!s) | |
+ s = ""; | |
+ *rtype = XA_STRING; | |
+ *ans = (XtPointer) XtNewString(s); | |
+ *anslen = strlen(*ans); | |
+ *ansfmt = 8; | |
+ return TRUE; | |
+ } | |
+#ifndef R3 | |
+ if(targets == 0){ | |
+ src.addr = "TARGETS"; | |
+ src.size = strlen(src.addr)+1; | |
+ dst.size = sizeof(Atom); | |
+ dst.addr = (XtPointer) &targets; | |
+ XtConvertAndStore(w, XtRString, &src, XtRAtom, &dst); | |
+ } | |
+ if(*target == targets){ | |
+ *rtype = XA_ATOM; | |
+ *ans = (XtPointer) XtNew(Atom); | |
+ *(Atom*) *ans = XA_STRING; | |
+ *anslen = 1; | |
+ *ansfmt = 32; | |
+ return TRUE; | |
+ } | |
+#endif | |
+ return FALSE; | |
+} | |
+ | |
+static String | |
+SelectSwap(Widget w, String s) | |
+{ | |
+ GwinWidget gw; | |
+ String ans; | |
+ | |
+ gw = (GwinWidget)w; | |
+ if(gw->gwin.selection){ | |
+ XtFree(gw->gwin.selection); | |
+ gw->gwin.selection = 0; | |
+ } | |
+#ifdef R3 | |
+ XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, SelCallback, 0, | |
+ CurrentTime); | |
+#else | |
+ XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, SelCallback, 0, | |
+ XtLastTimestampProcessed(XtDisplay(w))); | |
+#endif | |
+ while(gw->gwin.selection == 0) | |
+ XtAppProcessEvent(XtWidgetToApplicationContext(w) , XtIMAll); | |
+ ans = gw->gwin.selection; | |
+ gw->gwin.selection = XtMalloc(strlen(s)+1); | |
+ strcpy(gw->gwin.selection, s); | |
+#ifdef R3 | |
+ XtOwnSelection(w, XA_PRIMARY, CurrentTime, SendSel, NULL, NULL); | |
+#else | |
+ XtOwnSelection(w, XA_PRIMARY, XtLastTimestampProcessed(XtDisplay(w)), | |
+ SendSel, NULL, NULL); | |
+#endif | |
+ return ans; | |
+} | |
+ | |
+/* The returned answer should be free()ed when no longer needed */ | |
+String | |
+GwinSelectionSwap(Widget w, String s) | |
+{ | |
+ XtCheckSubclass(w, gwinWidgetClass, NULL); | |
+ return (*((GwinWidgetClass) XtClass(w))->gwin_class.select_swap)(w, s); | |
+} | |
+ | |
diff --git a/libXg/latin1.c b/libXg/latin1.c | |
@@ -0,0 +1,313 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+/* Changes copyright 2014-2014 Rob King. */ | |
+ | |
+#include <stdio.h> | |
+#include <stdlib.h> | |
+#include <string.h> | |
+ | |
+#define MAPPING_MAX 65535 | |
+ | |
+struct latin | |
+{ | |
+ unsigned short l; | |
+ unsigned char c[2]; | |
+}; | |
+ | |
+struct latin latintab[] = { | |
+ 0x00a1, '!','!', /* spanish initial ! */ | |
+ 0x00a2, 'c','$', /* cent */ | |
+ 0x00a3, 'l','$', /* pound sterling */ | |
+ 0x00a4, 'g','$', /* general currency */ | |
+ 0x00a5, 'y','$', /* yen */ | |
+ 0x00a6, '|','|', /* broken vertical bar */ | |
+ 0x00a7, 'S','S', /* section symbol */ | |
+ 0x00a8, '\"','\"', /* dieresis */ | |
+ 0x00a9, 'c','O', /* copyright */ | |
+ 0x00aa, 's','a', /* super a, feminine ordinal */ | |
+ 0x00ab, '<','<', /* left angle quotation */ | |
+ 0x00ac, 'n','o', /* not sign, hooked overbar */ | |
+ 0x00ad, '-','-', /* soft hyphen */ | |
+ 0x00ae, 'r','O', /* registered trademark */ | |
+ 0x00af, '_','_', /* macron */ | |
+ 0x00b0, 'd','e', /* degree */ | |
+ 0x00b1, '+','-', /* plus-minus */ | |
+ 0x00b2, 's','2', /* sup 2 */ | |
+ 0x00b3, 's','3', /* sup 3 */ | |
+ 0x00b4, '\'','\'', /* acute accent */ | |
+ 0x00b5, 'm','i', /* micron */ | |
+ 0x00b6, 'p','g', /* paragraph (pilcrow) */ | |
+ 0x00b7, '.','.', /* centered . */ | |
+ 0x00b8, ',',',', /* cedilla */ | |
+ 0x00b9, 's','1', /* sup 1 */ | |
+ 0x00ba, 's','o', /* super o, masculine ordinal */ | |
+ 0x00bb, '>','>', /* right angle quotation */ | |
+ 0x00bc, '1','4', /* 1/4 */ | |
+ 0x00bd, '1','2', /* 1/2 */ | |
+ 0x00be, '3','4', /* 3/4 */ | |
+ 0x00bf, '?','?', /* spanish initial ? */ | |
+ 0x00c0, '`','A', /* A grave */ | |
+ 0x00c1, '\'','A', /* A acute */ | |
+ 0x00c2, '^','A', /* A circumflex */ | |
+ 0x00c3, '~','A', /* A tilde */ | |
+ 0x00c4, '\"','A', /* A dieresis */ | |
+ 0x00c5, 'o','A', /* A circle */ | |
+ 0x00c6, 'A','E', /* AE ligature */ | |
+ 0x00c7, ',','C', /* C cedilla */ | |
+ 0x00c8, '`','E', /* E grave */ | |
+ 0x00c9, '\'','E', /* E acute */ | |
+ 0x00ca, '^','E', /* E circumflex */ | |
+ 0x00cb, '\"','E', /* E dieresis */ | |
+ 0x00cc, '`','I', /* I grave */ | |
+ 0x00cd, '\'','I', /* I acute */ | |
+ 0x00ce, '^','I', /* I circumflex */ | |
+ 0x00cf, '\"','I', /* I dieresis */ | |
+ 0x00d0, 'D','-', /* Eth */ | |
+ 0x00d1, '~','N', /* N tilde */ | |
+ 0x00d2, '`','O', /* O grave */ | |
+ 0x00d3, '\'','O', /* O acute */ | |
+ 0x00d4, '^','O', /* O circumflex */ | |
+ 0x00d5, '~','O', /* O tilde */ | |
+ 0x00d6, '\"','O', /* O dieresis */ | |
+ 0x00d7, 'm','u', /* times sign */ | |
+ 0x00d8, '/','O', /* O slash */ | |
+ 0x00d9, '`','U', /* U grave */ | |
+ 0x00da, '\'','U', /* U acute */ | |
+ 0x00db, '^','U', /* U circumflex */ | |
+ 0x00dc, '\"','U', /* U dieresis */ | |
+ 0x00dd, '\'','Y', /* Y acute */ | |
+ 0x00de, '|','P', /* Thorn */ | |
+ 0x00df, 's','s', /* sharp s */ | |
+ 0x00e0, '`','a', /* a grave */ | |
+ 0x00e1, '\'','a', /* a acute */ | |
+ 0x00e2, '^','a', /* a circumflex */ | |
+ 0x00e3, '~','a', /* a tilde */ | |
+ 0x00e4, '\"','a', /* a dieresis */ | |
+ 0x00e5, 'o','a', /* a circle */ | |
+ 0x00e6, 'a','e', /* ae ligature */ | |
+ 0x00e7, ',','c', /* c cedilla */ | |
+ 0x00e8, '`','e', /* e grave */ | |
+ 0x00e9, '\'','e', /* e acute */ | |
+ 0x00ea, '^','e', /* e circumflex */ | |
+ 0x00eb, '\"','e', /* e dieresis */ | |
+ 0x00ec, '`','i', /* i grave */ | |
+ 0x00ed, '\'','i', /* i acute */ | |
+ 0x00ee, '^','i', /* i circumflex */ | |
+ 0x00ef, '\"','i', /* i dieresis */ | |
+ 0x00f0, 'd','-', /* eth */ | |
+ 0x00f1, '~','n', /* n tilde */ | |
+ 0x00f2, '`','o', /* o grave */ | |
+ 0x00f3, '\'','o', /* o acute */ | |
+ 0x00f4, '^','o', /* o circumflex */ | |
+ 0x00f5, '~','o', /* o tilde */ | |
+ 0x00f6, '\"','o', /* o dieresis */ | |
+ 0x00f7, '-',':', /* divide sign */ | |
+ 0x00f8, '/','o', /* o slash */ | |
+ 0x00f9, '`','u', /* u grave */ | |
+ 0x00fa, '\'','u', /* u acute */ | |
+ 0x00fb, '^','u', /* u circumflex */ | |
+ 0x00fc, '\"','u', /* u dieresis */ | |
+ 0x00fd, '\'','y', /* y acute */ | |
+ 0x00fe, '|','p', /* thorn */ | |
+ 0x00ff, '\"','y', /* y dieresis */ | |
+ 0x2654, 'w','k', /* chess white king */ | |
+ 0x2655, 'w','q', /* chess white queen */ | |
+ 0x2656, 'w','r', /* chess white rook */ | |
+ 0x2657, 'w','b', /* chess white bishop */ | |
+ 0x2658, 'w','n', /* chess white knight */ | |
+ 0x2659, 'w','p', /* chess white pawn */ | |
+ 0x265a, 'b','k', /* chess black king */ | |
+ 0x265b, 'b','q', /* chess black queen */ | |
+ 0x265c, 'b','r', /* chess black rook */ | |
+ 0x265d, 'b','b', /* chess black bishop */ | |
+ 0x265e, 'b','n', /* chess black knight */ | |
+ 0x265f, 'b','p', /* chess black pawn */ | |
+ 0x03b1, '*','a', /* alpha */ | |
+ 0x03b2, '*','b', /* beta */ | |
+ 0x03b3, '*','g', /* gamma */ | |
+ 0x03b4, '*','d', /* delta */ | |
+ 0x03b5, '*','e', /* epsilon */ | |
+ 0x03b6, '*','z', /* zeta */ | |
+ 0x03b7, '*','y', /* eta */ | |
+ 0x03b8, '*','h', /* theta */ | |
+ 0x03b9, '*','i', /* iota */ | |
+ 0x03ba, '*','k', /* kappa */ | |
+ 0x03bb, '*','l', /* lambda */ | |
+ 0x03bc, '*','m', /* mu */ | |
+ 0x03bd, '*','n', /* nu */ | |
+ 0x03be, '*','c', /* xsi */ | |
+ 0x03bf, '*','o', /* omicron */ | |
+ 0x03c0, '*','p', /* pi */ | |
+ 0x03c1, '*','r', /* rho */ | |
+ 0x03c2, 't','s', /* terminal sigma */ | |
+ 0x03c3, '*','s', /* sigma */ | |
+ 0x03c4, '*','t', /* tau */ | |
+ 0x03c5, '*','u', /* upsilon */ | |
+ 0x03c6, '*','f', /* phi */ | |
+ 0x03c7, '*','x', /* chi */ | |
+ 0x03c8, '*','q', /* psi */ | |
+ 0x03c9, '*','w', /* omega */ | |
+ 0x0391, '*','A', /* Alpha */ | |
+ 0x0392, '*','B', /* Beta */ | |
+ 0x0393, '*','G', /* Gamma */ | |
+ 0x0394, '*','D', /* Delta */ | |
+ 0x0395, '*','E', /* Epsilon */ | |
+ 0x0396, '*','Z', /* Zeta */ | |
+ 0x0397, '*','Y', /* Eta */ | |
+ 0x0398, '*','H', /* Theta */ | |
+ 0x0399, '*','I', /* Iota */ | |
+ 0x039a, '*','K', /* Kappa */ | |
+ 0x039b, '*','L', /* Lambda */ | |
+ 0x039c, '*','M', /* Mu */ | |
+ 0x039d, '*','N', /* Nu */ | |
+ 0x039e, '*','C', /* Xsi */ | |
+ 0x039f, '*','O', /* Omicron */ | |
+ 0x03a0, '*','P', /* Pi */ | |
+ 0x03a1, '*','R', /* Rho */ | |
+ 0x03a3, '*','S', /* Sigma */ | |
+ 0x03a4, '*','T', /* Tau */ | |
+ 0x03a5, '*','U', /* Upsilon */ | |
+ 0x03a6, '*','F', /* Phi */ | |
+ 0x03a7, '*','X', /* Chi */ | |
+ 0x03a8, '*','Q', /* Psi */ | |
+ 0x03a9, '*','W', /* Omega */ | |
+ 0x2190, '<','-', /* left arrow */ | |
+ 0x2191, 'u','a', /* up arrow */ | |
+ 0x2192, '-','>', /* right arrow */ | |
+ 0x2193, 'd','a', /* down arrow */ | |
+ 0x2194, 'a','b', /* arrow both */ | |
+ 0x21d0, 'V','=', /* left double-line arrow */ | |
+ 0x21d2, '=','V', /* right double-line arrow */ | |
+ 0x2200, 'f','a', /* forall */ | |
+ 0x2203, 't','e', /* there exists */ | |
+ 0x2202, 'p','d', /* partial differential */ | |
+ 0x2205, 'e','s', /* empty set */ | |
+ 0x2206, 'D','e', /* delta */ | |
+ 0x2207, 'g','r', /* gradient */ | |
+ 0x2208, 'm','o', /* element of */ | |
+ 0x2209, '!','m', /* not element of */ | |
+ 0x220d, 's','t', /* such that */ | |
+ 0x2217, '*','*', /* math asterisk */ | |
+ 0x2219, 'b','u', /* bullet */ | |
+ 0x221a, 's','r', /* radical */ | |
+ 0x221d, 'p','t', /* proportional */ | |
+ 0x221e, 'i','f', /* infinity */ | |
+ 0x2220, 'a','n', /* angle */ | |
+ 0x2227, 'l','&', /* logical and */ | |
+ 0x2228, 'l','|', /* logical or */ | |
+ 0x2229, 'c','a', /* intersection */ | |
+ 0x222a, 'c','u', /* union */ | |
+ 0x222b, 'i','s', /* integral */ | |
+ 0x2234, 't','f', /* therefore */ | |
+ 0x2243, '~','=', /* asymptotically equal */ | |
+ 0x2245, 'c','g', /* congruent */ | |
+ 0x2248, '~','~', /* almost equal */ | |
+ 0x2260, '!','=', /* not equal */ | |
+ 0x2261, '=','=', /* equivalent */ | |
+ 0x2266, '<','=', /* less than or equal */ | |
+ 0x2267, '>','=', /* greater than or equal */ | |
+ 0x2282, 's','b', /* proper subset */ | |
+ 0x2283, 's','p', /* proper superset */ | |
+ 0x2284, '!','b', /* not subset */ | |
+ 0x2286, 'i','b', /* reflexive subset */ | |
+ 0x2287, 'i','p', /* reflexive superset */ | |
+ 0x2295, 'O','+', /* circle plus */ | |
+ 0x2296, 'O','-', /* circle minus */ | |
+ 0x2297, 'O','x', /* circle multiply */ | |
+ 0x22a2, 't','u', /* turnstile */ | |
+ 0x22a8, 'T','u', /* valid */ | |
+ 0x22c4, 'l','z', /* lozenge */ | |
+ 0x22ef, 'e','l', /* ellipses */ | |
+ 0x2639, ':','(', /* saddy */ | |
+ 0x263a, ':',')', /* white-face smiley */ | |
+ 0x263b, ';',')', /* dark-face smiley */ | |
+ 0, 0, | |
+}; | |
+ | |
+struct latin *mappings = NULL; | |
+ | |
+void | |
+freelatin(void) | |
+{ | |
+ free(mappings); | |
+} | |
+ | |
+void | |
+initlatin(void) | |
+{ | |
+ FILE *keyboard = NULL; | |
+ if (getenv("HOME")) | |
+ { | |
+ char path[1024] = {0}; | |
+ snprintf(path, 1023, "%s/.keyboard", getenv("HOME")); | |
+ keyboard = fopen(path, "r"); | |
+ } | |
+ | |
+ if (!keyboard) | |
+ { | |
+ mappings = latintab; | |
+ return; | |
+ } | |
+ | |
+ mappings = calloc(MAPPING_MAX + 1, sizeof(struct latin)); | |
+ if (!mappings) | |
+ { | |
+ mappings = latintab; | |
+ fclose(keyboard); | |
+ return; | |
+ } | |
+ | |
+ int j = 0; | |
+ while (j < MAPPING_MAX) | |
+ { | |
+ int count = fscanf(keyboard, " %c%c %hx%*[^\n]\n", &(mappings[… | |
+ if (count == 3) | |
+ { | |
+ j++; | |
+ | |
+ } | |
+ else if (count == EOF) | |
+ { | |
+ memset(&(mappings[j]), 0, sizeof(struct latin)); | |
+ break; | |
+ } | |
+ else | |
+ { | |
+ memset(&(mappings[j]), 0, sizeof(struct latin)); | |
+ } | |
+ } | |
+ | |
+ fclose(keyboard); | |
+ atexit(freelatin); | |
+} | |
+ | |
+long | |
+latin1(unsigned char *k) | |
+{ | |
+ struct latin *l; | |
+ | |
+ for(l=mappings; l->l; l++) | |
+ if(k[0]==l->c[0] && k[1]==l->c[1]) | |
+ return l->l; | |
+ return -1; | |
+} | |
+ | |
+long | |
+unicode(unsigned char *k) | |
+{ | |
+ long i, c; | |
+ | |
+ k++; /* skip 'X' */ | |
+ c = 0; | |
+ for(i=0; i<4; i++,k++){ | |
+ c <<= 4; | |
+ if('0'<=*k && *k<='9') | |
+ c += *k-'0'; | |
+ else if('a'<=*k && *k<='f') | |
+ c += 10 + *k-'a'; | |
+ else if('A'<=*k && *k<='F') | |
+ c += 10 + *k-'A'; | |
+ else | |
+ return -1; | |
+ } | |
+ return c; | |
+} | |
diff --git a/libXg/ldconvert.c b/libXg/ldconvert.c | |
@@ -0,0 +1,55 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+_ldconvert(char *in, int inld, char *out, int outld, int w, int h) | |
+{ | |
+ int a, b, i, j, i1, j1, j2, mask; | |
+ int ind, inl, outd, outl; | |
+ int hh, ww; | |
+ char *p, *q; | |
+ | |
+ i1 = 8 >> inld; | |
+ j1 = 8 >> outld; | |
+ ind = 1 << inld; | |
+ outd = 1 << outld; | |
+ inl = ((w << inld) + 7)/8; | |
+ outl = ((w << outld) + 7)/8; | |
+ b = 0; | |
+ | |
+ if (ind > outd) { | |
+ mask = 256 - (256 >> outd); | |
+ for (hh = 0; hh < h; hh++, in += inl, out += outl) | |
+ for (p = in, q = out, ww = 0; ww < w; ww++) { | |
+ for (j = j1; j > 0; ) { | |
+ a = *p++; | |
+ for (i = i1; i > 0; i--, j--) { | |
+ b |= a & mask; | |
+ a <<= ind; | |
+ b <<= outd; | |
+ } | |
+ } | |
+ *q++ = (b >> 8); | |
+ } | |
+ } else { | |
+ j2 = 1 << (outld - inld); | |
+ mask = 256 - (256 >> ind); | |
+ for (hh = 0; hh < h; hh++, in += inl, out += outl) | |
+ for (p = in, q = out, ww = 0; ww < w; ww++) { | |
+ a = *p++; | |
+ for (i = i1; i > 0; ) { | |
+ for (j = j1; j > 0; j--, i--) { | |
+ b |= a & mask; | |
+ a <<= ind; | |
+ b <<= outd; | |
+ } | |
+ for (j = j2; j > 0; j--) | |
+ b |= (b << ind); | |
+ *q++ = (b >> 8); | |
+ } | |
+ } | |
+ } | |
+} | |
diff --git a/libXg/libgint.h b/libXg/libgint.h | |
@@ -0,0 +1,93 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+/* internal libg implementation file - include after libg */ | |
+ | |
+/* | |
+ * include defs of standard library routines, if possible, | |
+ * and string routines | |
+ */ | |
+#ifdef _POSIX_SOURCE | |
+#include <stdlib.h> | |
+#include <string.h> | |
+#endif /* _POSIX_SOURCE */ | |
+ | |
+/* | |
+ * use defines to rename X11 types Cursor, Font, Event | |
+ */ | |
+ | |
+#define Cursor xCursor | |
+#define Font xFont | |
+#define Event xEvent | |
+ | |
+#if defined(v10) || defined(HPUX) | |
+typedef char* caddr_t; | |
+#endif | |
+ | |
+#include <X11/Xlib.h> | |
+#include <X11/Xatom.h> | |
+#include <X11/Xutil.h> | |
+#include <X11/Xft/Xft.h> | |
+ | |
+#undef Cursor | |
+#undef Font | |
+#undef Event | |
+ | |
+/* Return a GCs for solid filling/strings/etc., segments/points, and tiling */ | |
+extern GC _getfillgc(Fcode, Bitmap*, unsigned long); | |
+extern GC _getcopygc(Fcode, Bitmap*, Bitmap*, int*); | |
+extern GC _getgc(Bitmap*, unsigned long, XGCValues *); | |
+ | |
+/* convert between different bitmap depths */ | |
+extern void _ldconvert(char *, int, char *, int, int, int); | |
+ | |
+/* balloc without zero init (which uses a gc!) */ | |
+extern Bitmap *_balloc(Rectangle, int); | |
+ | |
+/* X Display for this application's connection */ | |
+extern Display *_dpy; | |
+ | |
+/* screen depth foreground and background for this application */ | |
+extern unsigned long _fgpixel, _bgpixel; | |
+extern XColor _fgcolor, _bgcolor; | |
+ | |
+/* indexed by log depth (0 <= ld <= 5), to give depth and planemask */ | |
+extern int _ld2d[]; | |
+extern unsigned long _ld2dmask[]; | |
+ | |
+/* libg.h defines: | |
+ * extern Bitmap screen; -- Bitmap for application Window after xbinit() | |
+ * extern Font *font; -- Font for application default font after xbinit… | |
+ */ | |
+ | |
+/* | |
+ * Conventions: | |
+ * The .id field of a Bitmap is an X Pixmap unless the Bitmap is screen, | |
+ * in which case it is a Window. | |
+ * The .id field of a Cursor is set to the X xCursor the first time the | |
+ * cursor is used. | |
+ * The .id field of a Font is set to the X xFont. | |
+ * | |
+ * Coordinate conventions: libg bitmaps can have non (0,0) origins, | |
+ * but not X Pixmaps, so we have to subtract the min point of a Bitmap | |
+ * from coords in the Bitmap before using the point in the corresponding Pix… | |
+ * The screen Bitmap, however, contains the rectangle in X coords of the | |
+ * widget in which the application is started, relative to the window. | |
+ * The origin may or may not be (0,0), but in any case, coordinates should | |
+ * NOT be translated before using in X calls on the Window. | |
+ */ | |
+ | |
+/* values for bitmap flag field (see _getcopygc if change first two vals) */ | |
+enum { | |
+ DP1= 0x1, /* depth == 1 (ldepth == 0) */ | |
+ BL1= 0x2, /* black == 1 model */ | |
+ SCR= 0x4, /* on screen */ | |
+ ZORG= 0x8, /* r.min == Pt(0,0) */ | |
+ SHIFT= 0x20, /* !SCR & !ZORG */ | |
+ CLIP= 0x40 /* r != clipr */ | |
+}; | |
+ | |
+/* values for return bltfunc arg of _getcopygc */ | |
+enum { | |
+ UseCopyArea, | |
+ UseCopyPlane, | |
+ UseFillRectangle | |
+}; | |
diff --git a/libXg/menuhit.c b/libXg/menuhit.c | |
@@ -0,0 +1,236 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+enum | |
+{ | |
+ Margin = 3, /* outside to text */ | |
+ Border = 2, /* outside to selection boxes */ | |
+ Blackborder = 1, /* width of outlining border */ | |
+ Vspacing = 1, /* extra spacing between lines of text */ | |
+ Maxunscroll = 25, /* maximum #entries before scrolling turns on… | |
+ Nscroll = 20, /* number entries in scrolling part */ | |
+ Scrollwid = 14, /* width of scroll bar */ | |
+ Gap = 4 /* between text and scroll bar */ | |
+}; | |
+ | |
+static Bitmap *menutxt; | |
+ | |
+static uchar menutxtbits[] = { | |
+ 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, | |
+ 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, | |
+ 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, | |
+ 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, | |
+}; | |
+ | |
+/* | |
+ * r is a rectangle holding the text elements. | |
+ * return the rectangle, including its black edge, holding element i. | |
+ */ | |
+static Rectangle | |
+menurect(Rectangle r, int i) | |
+{ | |
+ if(i < 0) | |
+ return Rect(0, 0, 0, 0); | |
+ r.min.y += (font->height+Vspacing)*i; | |
+ r.max.y = r.min.y+font->height+Vspacing; | |
+ return inset(r, Border-Margin); | |
+} | |
+ | |
+/* | |
+ * r is a rectangle holding the text elements. | |
+ * return the element number containing p. | |
+ */ | |
+static int | |
+menusel(Rectangle r, Point p) | |
+{ | |
+ if(!ptinrect(p, r)) | |
+ return -1; | |
+ return (p.y-r.min.y)/(font->height+Vspacing); | |
+} | |
+ | |
+/* | |
+ * menur is a rectangle holding all the highlightable text elements. | |
+ * track mouse while inside the box, return what's selected when button | |
+ * is raised, -1 as soon as it leaves box. | |
+ * invariant: nothing is highlighted on entry or exit. | |
+ */ | |
+static int | |
+menuscan(int but, Mouse *m, Rectangle menur, int lasti) | |
+{ | |
+ int i; | |
+ Rectangle r; | |
+ | |
+ r = menurect(menur, lasti); | |
+ bitblt(&screen, r.min, &screen, r, F&~D); | |
+ *m = emouse(); | |
+ while(m->buttons & (1<<(but-1))){ | |
+ *m = emouse(); | |
+ i = menusel(menur, m->xy); | |
+ if(i == lasti) | |
+ continue; | |
+ bitblt(&screen, r.min, &screen, r, F&~D); | |
+ if(i == -1) | |
+ return i; | |
+ r = menurect(menur, i); | |
+ bitblt(&screen, r.min, &screen, r, F&~D); | |
+ lasti = i; | |
+ } | |
+ return lasti; | |
+} | |
+ | |
+void | |
+menupaint(Menu *menu, Rectangle textr, int off, int nitemdrawn) | |
+{ | |
+ int i; | |
+ Point pt; | |
+ Rectangle r; | |
+ char *item; | |
+ | |
+ r = inset(textr, Border-Margin); | |
+ bitblt(&screen, r.min, &screen, r, 0); | |
+ pt = Pt(textr.min.x+textr.max.x, textr.min.y); | |
+ for(i = 0; i<nitemdrawn; i++, pt.y += font->height+Vspacing){ | |
+ item = menu->item? menu->item[i+off] : (*menu->gen)(i+off); | |
+ string(&screen, | |
+ Pt((pt.x-strwidth(font, item))/2, pt.y), | |
+ font, item, S); | |
+ } | |
+} | |
+ | |
+static void | |
+menuscrollpaint(Rectangle scrollr, int off, int nitem, int nitemdrawn) | |
+{ | |
+ Rectangle r; | |
+ | |
+ bitblt(&screen, scrollr.min, &screen, scrollr, 0); | |
+ r.min.x = scrollr.min.x; | |
+ r.max.x = scrollr.max.x; | |
+ r.min.y = scrollr.min.y + (Dy(scrollr)*off)/nitem; | |
+ r.max.y = scrollr.min.y + (Dy(scrollr)*(off+nitemdrawn))/nitem; | |
+ if(r.max.y < r.min.y+2) | |
+ r.max.y = r.min.y+2; | |
+ border(&screen, r, 1, F); | |
+ if(menutxt == 0){ | |
+ menutxt = balloc(Rect(0, 0, 16, 16), 0); | |
+ if(menutxt) | |
+ wrbitmap(menutxt, 0, 16, menutxtbits); | |
+ } | |
+ if(menutxt) | |
+ texture(&screen, inset(r, 1), menutxt, S); | |
+} | |
+ | |
+int | |
+menuhit(int but, Mouse *m, Menu *menu) | |
+{ | |
+ int i, nitem, nitemdrawn, maxwid, lasti, off, noff, wid, screenitem; | |
+ int scrolling; | |
+ Rectangle r, menur, sc, textr, scrollr; | |
+ Bitmap *b; | |
+ Point pt; | |
+ char *item; | |
+ | |
+ sc = screen.clipr; | |
+ clipr(&screen, screen.r); | |
+ maxwid = 0; | |
+ for(nitem = 0; | |
+ item = menu->item? menu->item[nitem] : (*menu->gen)(nitem); | |
+ nitem++){ | |
+ i = strwidth(font, item); | |
+ if(i > maxwid) | |
+ maxwid = i; | |
+ } | |
+ if(menu->lasthit<0 || menu->lasthit>=nitem) | |
+ menu->lasthit = 0; | |
+ screenitem = (Dy(screen.r)-10)/(font->height+Vspacing); | |
+ if(nitem>Maxunscroll || nitem>screenitem){ | |
+ scrolling = 1; | |
+ nitemdrawn = Nscroll; | |
+ if(nitemdrawn > screenitem) | |
+ nitemdrawn = screenitem; | |
+ wid = maxwid + Gap + Scrollwid; | |
+ off = menu->lasthit - nitemdrawn/2; | |
+ if(off < 0) | |
+ off = 0; | |
+ if(off > nitem-nitemdrawn) | |
+ off = nitem-nitemdrawn; | |
+ lasti = menu->lasthit-off; | |
+ }else{ | |
+ scrolling = 0; | |
+ nitemdrawn = nitem; | |
+ wid = maxwid; | |
+ off = 0; | |
+ lasti = menu->lasthit; | |
+ } | |
+ r = inset(Rect(0, 0, wid, nitemdrawn*(font->height+Vspacing)), -Margin… | |
+ r = rsubp(r, Pt(wid/2, lasti*(font->height+Vspacing)+font->height/2)); | |
+ r = raddp(r, m->xy); | |
+ pt = Pt(0, 0); | |
+ if(r.max.x>screen.r.max.x) | |
+ pt.x = screen.r.max.x-r.max.x; | |
+ if(r.max.y>screen.r.max.y) | |
+ pt.y = screen.r.max.y-r.max.y; | |
+ if(r.min.x<screen.r.min.x) | |
+ pt.x = screen.r.min.x-r.min.x; | |
+ if(r.min.y<screen.r.min.y) | |
+ pt.y = screen.r.min.y-r.min.y; | |
+ menur = raddp(r, pt); | |
+ textr.max.x = menur.max.x-Margin; | |
+ textr.min.x = textr.max.x-maxwid; | |
+ textr.min.y = menur.min.y+Margin; | |
+ textr.max.y = textr.min.y + nitemdrawn*(font->height+Vspacing); | |
+ if(scrolling){ | |
+ scrollr = inset(menur, Border); | |
+ scrollr.max.x = scrollr.min.x+Scrollwid; | |
+ }else | |
+ scrollr = Rect(0, 0, 0, 0); | |
+ | |
+ b = balloc(menur, screen.ldepth); | |
+ if(b == 0) | |
+ b = &screen; | |
+ bitblt(b, menur.min, &screen, menur, S); | |
+ bitblt(&screen, menur.min, &screen, menur, 0); | |
+ border(&screen, menur, Blackborder, F); | |
+ r = menurect(textr, lasti); | |
+ cursorset(divpt(add(r.min, r.max), 2)); | |
+ menupaint(menu, textr, off, nitemdrawn); | |
+ if(scrolling) | |
+ menuscrollpaint(scrollr, off, nitem, nitemdrawn); | |
+ r = menurect(textr, lasti); | |
+ cursorset(divpt(add(r.min, r.max), 2)); | |
+ menupaint(menu, textr, off, nitemdrawn); | |
+ if(scrolling) | |
+ menuscrollpaint(scrollr, off, nitem, nitemdrawn); | |
+ while(m->buttons & (1<<(but-1))){ | |
+ lasti = menuscan(but, m, textr, lasti); | |
+ if(lasti >= 0) | |
+ break; | |
+ while(!ptinrect(m->xy, textr) && (m->buttons & (1<<(but-1)))){ | |
+ if(scrolling && ptinrect(m->xy, scrollr)){ | |
+ noff = ((m->xy.y-scrollr.min.y)*nitem)/Dy(scro… | |
+ noff -= nitemdrawn/2; | |
+ if(noff < 0) | |
+ noff = 0; | |
+ if(noff > nitem-nitemdrawn) | |
+ noff = nitem-nitemdrawn; | |
+ if(noff != off){ | |
+ off = noff; | |
+ menupaint(menu, textr, off, nitemdrawn… | |
+ menuscrollpaint(scrollr, off, nitem, n… | |
+ } | |
+ } | |
+ *m = emouse(); | |
+ } | |
+ } | |
+ bitblt(&screen, menur.min, b, menur, S); | |
+ if(b != &screen) | |
+ bfree(b); | |
+ clipr(&screen, sc); | |
+ if(lasti >= 0){ | |
+ menu->lasthit = lasti+off; | |
+ return menu->lasthit; | |
+ } | |
+ return -1; | |
+} | |
diff --git a/libXg/point.c b/libXg/point.c | |
@@ -0,0 +1,21 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+point(Bitmap *b, Point p, int v, Fcode f) | |
+{ | |
+ int x, y; | |
+ GC g; | |
+ | |
+ x = p.x; | |
+ y = p.y; | |
+ if(b->flag&SHIFT){ | |
+ x -= b->r.min.x; | |
+ y -= b->r.min.y; | |
+ } | |
+ g = _getfillgc(f, b, v); | |
+ XDrawPoint(_dpy, (Drawable)b->id, g, x, y); | |
+} | |
diff --git a/libXg/polysegment.c b/libXg/polysegment.c | |
@@ -0,0 +1,27 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+polysegment(Bitmap *d, int n, Point *pp, int v, Fcode f) | |
+{ | |
+ XPoint *xp; | |
+ int i; | |
+ GC g; | |
+ | |
+ if (!(xp = (XPoint *)calloc(n, sizeof(XPoint)))) | |
+ berror("polysegment: could not allocate XPoints"); | |
+ for (i = 0; i < n; i++, pp++) | |
+ if(d->flag&SHIFT){ | |
+ xp[i].x = pp->x - d->r.min.x; | |
+ xp[i].y = pp->y - d->r.min.y; | |
+ } else { | |
+ xp[i].x = pp->x; | |
+ xp[i].y = pp->y; | |
+ } | |
+ g = _getfillgc(f, d, v); | |
+ XDrawLines(_dpy, (Drawable)d->id, g, xp, n, CoordModeOrigin); | |
+ free(xp); | |
+} | |
diff --git a/libXg/rdbitmap.c b/libXg/rdbitmap.c | |
@@ -0,0 +1,63 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+rdbitmap(Bitmap *b, int miny, int maxy, unsigned char *data) | |
+{ | |
+ XImage *gim, *eim; | |
+ int x, y, w, h, pix, l, offset, px; | |
+ int inld, outld; | |
+ char *tdata; | |
+ | |
+ /* | |
+ * The XGetImage returned image may be wrong in a number of ways: | |
+ * wrong bit order, byte order, bit pad, scanline pad, | |
+ * and constant shift. | |
+ * So use a SLOW loop, for now | |
+ */ | |
+ w = Dx(b->r); | |
+ h = maxy - miny; | |
+ outld = b->ldepth; | |
+ inld = (b->ldepth == 0) ? 0 : screen.ldepth; | |
+ gim = XGetImage(_dpy, (Drawable)b->id, 0, miny - b->r.min.y, | |
+ w, h, ~0, ZPixmap); | |
+ px = 1<<(3-outld); /* pixels per byte */ | |
+ /* set l to number of bytes of data per scan line */ | |
+ if(b->r.min.x >= 0) | |
+ offset = b->r.min.x % px; | |
+ else | |
+ offset = px - b->r.min.x % px; | |
+ l = (-b->r.min.x+px-1)/px; | |
+ if(b->r.max.x >= 0) | |
+ l += (b->r.max.x+px-1)/px; | |
+ else | |
+ l -= b->r.max.x/px; | |
+ l *= h; | |
+ if(l <= 0) | |
+ return; | |
+ tdata = (char *)malloc(l); | |
+ if (tdata == (char *) 0) | |
+ berror("rdbitmap malloc"); | |
+ eim = XCreateImage(_dpy, 0, 1 << inld, ZPixmap, 0, tdata, | |
+ w+offset, h, 8, 0); | |
+ eim->bitmap_pad = 8; | |
+ eim->bitmap_bit_order = MSBFirst; | |
+ eim->byte_order = MSBFirst; | |
+ | |
+ for(y = 0; y < h; y++) | |
+ for(x = 0; x < w; x++) { | |
+ pix = XGetPixel(gim, x, y); | |
+ XPutPixel(eim, x+offset, y, pix); | |
+ } | |
+ | |
+ if (inld == outld) | |
+ memcpy((char *)data, tdata, l); | |
+ else | |
+ _ldconvert(tdata, inld, (char*)data, outld, w, h); | |
+ | |
+ XDestroyImage(gim); | |
+ XDestroyImage(eim); | |
+} | |
diff --git a/libXg/rdbitmapfile.c b/libXg/rdbitmapfile.c | |
@@ -0,0 +1,65 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+#define CHUNK 6000 | |
+ | |
+Bitmap* | |
+rdbitmapfile(int fd) | |
+{ | |
+ char hdr[5*12+1]; | |
+ unsigned char *data; | |
+ long dy, px; | |
+ unsigned long l, t, n; | |
+ long miny, maxy; | |
+ Rectangle r; | |
+ int ld; | |
+ Bitmap *b; | |
+ | |
+ if(read(fd, hdr, 5*12)!=5*12) | |
+ berror("rdbitmapfile read"); | |
+ ld = atoi(hdr+0*12); | |
+ r.min.x = atoi(hdr+1*12); | |
+ r.min.y = atoi(hdr+2*12); | |
+ r.max.x = atoi(hdr+3*12); | |
+ r.max.y = atoi(hdr+4*12); | |
+ if(ld<0 || ld>1) | |
+ berror("rdbitmapfile ldepth"); | |
+ if(r.min.x>r.max.x || r.min.y>r.max.y) | |
+ berror("rdbitmapfile rectangle"); | |
+ | |
+ miny = r.min.y; | |
+ maxy = r.max.y; | |
+ px = 1<<(3-ld); /* pixels per byte */ | |
+ /* set l to number of bytes of data per scan line */ | |
+ if(r.min.x >= 0) | |
+ l = (r.max.x+px-1)/px - r.min.x/px; | |
+ else{ /* make positive before divide */ | |
+ t = (-r.min.x)+px-1; | |
+ t = (t/px)*px; | |
+ l = (t+r.max.x+px-1)/px; | |
+ } | |
+ b = balloc(r, ld); | |
+ if(b == 0) | |
+ return 0; | |
+ data = (unsigned char *)malloc(CHUNK); | |
+ if(data == 0) | |
+ berror("rdbitmapfile malloc"); | |
+ while(maxy > miny){ | |
+ dy = maxy - miny; | |
+ if(dy*l > CHUNK) | |
+ dy = CHUNK/l; | |
+ n = dy*l; | |
+ if(read(fd, data, n) != n){ | |
+ free(data); | |
+ bfree(b); | |
+ berror("rdbitmapfile read"); | |
+ } | |
+ wrbitmap(b, miny, miny+dy, data); | |
+ miny += dy; | |
+ } | |
+ free(data); | |
+ return b; | |
+} | |
diff --git a/libXg/rectclip.c b/libXg/rectclip.c | |
@@ -0,0 +1,25 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+ | |
+rectclip(Rectangle *rp, Rectangle b) /* first by reference, sec… | |
+{ | |
+ Rectangle *bp = &b; | |
+ /* | |
+ * Expand rectXrect() in line for speed | |
+ */ | |
+ if((rp->min.x<bp->max.x && bp->min.x<rp->max.x && | |
+ rp->min.y<bp->max.y && bp->min.y<rp->max.y)==0) | |
+ return 0; | |
+ /* They must overlap */ | |
+ if(rp->min.x < bp->min.x) | |
+ rp->min.x = bp->min.x; | |
+ if(rp->min.y < bp->min.y) | |
+ rp->min.y = bp->min.y; | |
+ if(rp->max.x > bp->max.x) | |
+ rp->max.x = bp->max.x; | |
+ if(rp->max.y > bp->max.y) | |
+ rp->max.y = bp->max.y; | |
+ return 1; | |
+} | |
diff --git a/libXg/rune.c b/libXg/rune.c | |
@@ -0,0 +1,213 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <string.h> | |
+ | |
+enum | |
+{ | |
+ Bit1 = 7, | |
+ Bitx = 6, | |
+ Bit2 = 5, | |
+ Bit3 = 4, | |
+ Bit4 = 3, | |
+ | |
+ T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ | |
+ Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ | |
+ T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ | |
+ T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ | |
+ T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ | |
+ | |
+ Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 … | |
+ Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 … | |
+ Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 … | |
+ | |
+ Maskx = (1<<Bitx)-1, /* 0011 1111 */ | |
+ Testx = Maskx ^ 0xFF, /* 1100 0000 */ | |
+ | |
+ Bad = Runeerror | |
+}; | |
+ | |
+int | |
+chartorune(Rune *rune, char *str) | |
+{ | |
+ int c, c1, c2; | |
+ long l; | |
+ | |
+ /* | |
+ * one character sequence | |
+ * 00000-0007F => T1 | |
+ */ | |
+ c = *(uchar*)str; | |
+ if(c < Tx) { | |
+ *rune = c; | |
+ return 1; | |
+ } | |
+ | |
+ /* | |
+ * two character sequence | |
+ * 0080-07FF => T2 Tx | |
+ */ | |
+ c1 = *(uchar*)(str+1) ^ Tx; | |
+ if(c1 & Testx) | |
+ goto bad; | |
+ if(c < T3) { | |
+ if(c < T2) | |
+ goto bad; | |
+ l = ((c << Bitx) | c1) & Rune2; | |
+ if(l <= Rune1) | |
+ goto bad; | |
+ *rune = l; | |
+ return 2; | |
+ } | |
+ | |
+ /* | |
+ * three character sequence | |
+ * 0800-FFFF => T3 Tx Tx | |
+ */ | |
+ c2 = *(uchar*)(str+2) ^ Tx; | |
+ if(c2 & Testx) | |
+ goto bad; | |
+ if(c < T4) { | |
+ l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; | |
+ if(l <= Rune2) | |
+ goto bad; | |
+ *rune = l; | |
+ return 3; | |
+ } | |
+ | |
+ /* | |
+ * bad decoding | |
+ */ | |
+bad: | |
+ *rune = Bad; | |
+ return 1; | |
+} | |
+ | |
+int | |
+runetochar(char *str, Rune *rune) | |
+{ | |
+ long c; | |
+ | |
+ /* | |
+ * one character sequence | |
+ * 00000-0007F => 00-7F | |
+ */ | |
+ c = *rune; | |
+ if(c <= Rune1) { | |
+ str[0] = c; | |
+ return 1; | |
+ } | |
+ | |
+ /* | |
+ * two character sequence | |
+ * 0080-07FF => T2 Tx | |
+ */ | |
+ if(c <= Rune2) { | |
+ str[0] = T2 | (c >> 1*Bitx); | |
+ str[1] = Tx | (c & Maskx); | |
+ return 2; | |
+ } | |
+ | |
+ /* | |
+ * three character sequence | |
+ * 0800-FFFF => T3 Tx Tx | |
+ */ | |
+ str[0] = T3 | (c >> 2*Bitx); | |
+ str[1] = Tx | ((c >> 1*Bitx) & Maskx); | |
+ str[2] = Tx | (c & Maskx); | |
+ return 3; | |
+} | |
+ | |
+int | |
+runelen(long c) | |
+{ | |
+ Rune rune; | |
+ char str[10]; | |
+ | |
+ rune = c; | |
+ return runetochar(str, &rune); | |
+} | |
+ | |
+int | |
+runenlen(Rune *r, int nrune) | |
+{ | |
+ int nb, c; | |
+ | |
+ nb = 0; | |
+ while(nrune--) { | |
+ c = *r++; | |
+ if(c <= Rune1) | |
+ nb++; | |
+ else | |
+ if(c <= Rune2) | |
+ nb += 2; | |
+ else | |
+ nb += 3; | |
+ } | |
+ return nb; | |
+} | |
+ | |
+int | |
+fullrune(char *str, int n) | |
+{ | |
+ int c; | |
+ | |
+ if(n > 0) { | |
+ c = *(uchar*)str; | |
+ if(c < Tx) | |
+ return 1; | |
+ if(n > 1) | |
+ if(c < T3 || n > 2) | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+char* | |
+utfrune(char *s, long c) | |
+{ | |
+ long c1; | |
+ Rune r; | |
+ int n; | |
+ | |
+ if(c < Runesync) /* not part of utf sequence */ | |
+ return strchr(s, c); | |
+ | |
+ for(;;) { | |
+ c1 = *(uchar*)s; | |
+ if(c1 < Runeself) { /* one byte rune */ | |
+ if(c1 == 0) | |
+ return 0; | |
+ if(c1 == c) | |
+ return s; | |
+ s++; | |
+ continue; | |
+ } | |
+ n = chartorune(&r, s); | |
+ if(r == c) | |
+ return s; | |
+ s += n; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+int | |
+utflen(char *s) | |
+{ | |
+ int c; | |
+ long n; | |
+ Rune rune; | |
+ | |
+ n = 0; | |
+ for(;;) { | |
+ c = *(uchar*)s; | |
+ if(c < Runeself) { | |
+ if(c == 0) | |
+ return n; | |
+ s++; | |
+ } else | |
+ s += chartorune(&rune, s); | |
+ n++; | |
+ } | |
+ return 0; | |
+} | |
diff --git a/libXg/segment.c b/libXg/segment.c | |
@@ -0,0 +1,25 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+segment(Bitmap *d, Point p1, Point p2, int v, Fcode f) | |
+{ | |
+ int x1, y1, x2, y2; | |
+ GC g; | |
+ | |
+ x1 = p1.x; | |
+ y1 = p1.y; | |
+ x2 = p2.x; | |
+ y2 = p2.y; | |
+ if(d->flag&SHIFT){ | |
+ x1 -= d->r.min.x; | |
+ y1 -= d->r.min.y; | |
+ x2 -= d->r.min.x; | |
+ y2 -= d->r.min.y; | |
+ } | |
+ g = _getfillgc(f, d, v); | |
+ XDrawLine(_dpy, (Drawable)d->id, g, x1, y1, x2, y2); | |
+} | |
diff --git a/libXg/string.c b/libXg/string.c | |
@@ -0,0 +1,38 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <string.h> | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+enum { Max = 128 }; | |
+ | |
+Point | |
+string(Bitmap *b, Point p, XftFont *ft, char *s, Fcode f) | |
+{ | |
+ size_t length = strlen(s); | |
+ XGlyphInfo extents = {0}; | |
+ int x = p.x; | |
+ int y = p.y; | |
+ | |
+ XftTextExtentsUtf8(_dpy, ft, s, length, &extents); | |
+ | |
+ x = p.x; | |
+ y = p.y; | |
+ if (b->flag & SHIFT){ | |
+ x -= b->r.min.x; | |
+ y -= b->r.min.y; | |
+ } | |
+ y += ft->ascent; | |
+ | |
+ XftDraw *drawable = XftDrawCreate(_dpy, (Drawable)(b->id), DefaultVisu… | |
+ | |
+ XftDrawStringUtf8(drawable, &fontcolor, ft, x, y, s, length); | |
+ XftDrawDestroy(drawable); | |
+ | |
+ x += extents.xOff; | |
+ | |
+ p.x = (b->flag & SHIFT) ? x + b->r.min.x : x; | |
+ p.x = x + b->r.min.x; | |
+ return p; | |
+} | |
diff --git a/libXg/strwidth.c b/libXg/strwidth.c | |
@@ -0,0 +1,23 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+long | |
+strwidth(XftFont *f, char *s) | |
+{ | |
+ XGlyphInfo extents = {0}; | |
+ XftTextExtentsUtf8(_dpy, f, s, strlen(s), &extents); | |
+ | |
+ return extents.xOff; | |
+} | |
+ | |
+Point | |
+strsize(XftFont *f, char *s) | |
+{ | |
+ XGlyphInfo extents = {0}; | |
+ XftTextExtentsUtf8(_dpy, f, s, strlen(s), &extents); | |
+ | |
+ return Pt(strwidth(f, s), extents.yOff); | |
+} | |
diff --git a/libXg/test.c b/libXg/test.c | |
@@ -0,0 +1,237 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <libc.h> | |
+#ifdef __STDC__ | |
+#include <stdlib.h> | |
+#endif | |
+#include <libg.h> | |
+#include <stdio.h> | |
+ | |
+void cont(char *); | |
+void putstring(char *); | |
+void colorinit(void); | |
+void printcolmap(void); | |
+void invertcolmap(void); | |
+ | |
+unsigned char arrowset[] = | |
+ {0x00, 0x00, 0x7F, 0xC0, 0x7F, 0x00, 0x7C, 0x00, | |
+ 0x7E, 0x00, 0x7F, 0x00, 0x6F, 0x80, 0x67, 0xC0, | |
+ 0x43, 0xE0, 0x41, 0xF0, 0x00, 0xF8, 0x00, 0x7C, | |
+ 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00}; | |
+ | |
+char *colors[] = { "Black", "Red", "Green", "Yellow", | |
+ "Cyan", "Magenta", "Blue", "White" }; | |
+RGB colordefs[] = { | |
+ { 0,0,0 }, /* black */ | |
+ {0xFFFFFFFF, 0x00000000, 0x00000000}, /* red */ | |
+ {0x00000000, 0xFFFFFFFF, 0x00000000}, /* green */ | |
+ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000}, /* yellow */ | |
+ {0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, /* cyan */ | |
+ {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF}, /* magenta … | |
+ {0x00000000, 0x00000000, 0xFFFFFFFF}, /* blue */ | |
+ {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, /* white */ | |
+}; | |
+#define Ncol (sizeof(colordefs)/sizeof(colordefs[0])) | |
+unsigned long rgbval[Ncol]; | |
+Bitmap *rgbbitmap[Ncol]; | |
+ | |
+main(int argc, char **argv) | |
+{ | |
+ Point p1,p2,p3; | |
+ Mouse m; | |
+ int r,rx,ry; | |
+ int n, i; | |
+ char *m3gen(int); | |
+ static Menu menu3 = { (char **) 0, m3gen, 0 }; | |
+ char *p, buf[200]; | |
+ Bitmap *bm, *bm2; | |
+ RGB cmap[256]; | |
+ | |
+ xtbinit(0,0,&argc,argv,0); | |
+ einit(Ekeyboard|Emouse); | |
+ p1 = add(screen.r.min, Pt(15,15)); | |
+ p2 = sub(screen.r.max, Pt(15,15)); | |
+ p3 = divpt(add(p1,p2),2); | |
+ fprintf(stderr, "segment(&screen, (%d,%d), (%d,%d), ~0, S)\n", | |
+ p1.x,p1.y,p2.x,p2.y); | |
+ segment(&screen, p1, p2, ~0, S); | |
+ cont("point"); | |
+ fprintf(stderr, "point(&screen, (%d,%d), ~0, S)\n", p1.x,p1.y); | |
+ point(&screen, p1, ~0, S); | |
+ cont("circle"); | |
+ rx = p3.x - p1.x; | |
+ ry = p3.y - p1.y; | |
+ r = (rx < ry)? rx : ry; | |
+ fprintf(stderr, "circle(&screen, (%d,%d), %d, ~0, S)\n", | |
+ p3.x,p3.y,r); | |
+ circle(&screen, p3, r, ~0, S); | |
+ cont("disc"); | |
+ fprintf(stderr, "disc(&screen, (%d,%d), %d, ~0, S)\n", | |
+ p3.x,p3.y,r); | |
+ disc(&screen, p3, r, ~0, S); | |
+ cont("clipped disc"); | |
+ fprintf(stderr, "clipr(&screen, ((%d,%d)(%d,%d))\n", | |
+ p1.x+30, p1.y+5, p3.x-30, p3.y-5); | |
+ clipr(&screen, Rect(p1.x+30, p1.y+5, p3.x-30, p3.y-5)); | |
+ fprintf(stderr, "disc(&screen, (%d,%d), %d, ~0, S)\n", | |
+ p3.x,p3.y,r); | |
+ disc(&screen, p3, r, ~0, S); | |
+ clipr(&screen, screen.r); | |
+ cont("ellipse"); | |
+ fprintf(stderr, "ellipse(&screen, (%d,%d), %d, %d, ~0, S)\n", | |
+ p3.x,p3.y,r,r/2); | |
+ ellipse(&screen, p3, r, r/2, ~0, S); | |
+ cont("arc"); | |
+ fprintf(stderr, "arc(&screen, (%d,%d), (%d,%d), (%d,%d), ~0, S)\n", | |
+ p3.x,p3.y, p3.x+r,p3.y, p3.x+r/2,p3.x-(int)(r*.866)); | |
+ arc(&screen, p3, Pt(p3.x+r,p3.y), Pt(p3.x+r/2,p3.x-(int)(r*.866)), ~0,… | |
+ if(screen.ldepth > 1){ | |
+ cont("color"); | |
+ colorinit(); | |
+ p3 = p1; | |
+ rx *= 2; | |
+ ry *= 2; | |
+ for(i = 0; i<Ncol; i++) { | |
+ texture(&screen, Rpt(p3,add(p3,Pt(rx,ry/Ncol))), | |
+ rgbbitmap[i], S); | |
+ string(&screen, add(p3,Pt(15,15)), font, colors[i], Dx… | |
+ p3.y += ry/Ncol; | |
+ } | |
+ printcolmap(); | |
+ cont("invert colmap"); | |
+ invertcolmap(); | |
+ printcolmap(); | |
+ p3 = p1; | |
+ for(i = 0; i<Ncol; i++) { | |
+ texture(&screen, Rpt(p3,add(p3,Pt(rx,ry/Ncol))), | |
+ rgbbitmap[i], S); | |
+ string(&screen, add(p3,Pt(15,15)), font, colors[i], Dx… | |
+ p3.y += ry/Ncol; | |
+ } | |
+ cont("restore colmap"); | |
+ invertcolmap(); | |
+ } | |
+ cont("wrbitmap, border, and bitblt(S)"); | |
+ bm = balloc(Rect(0,0,16,16), 0); | |
+ fprintf(stderr, "border (%d,%d,%d,%d), -2, F)\n", | |
+ p1.x, p1.y, p1.x+16, p1.y+16); | |
+ border(&screen, Rpt(p1, add(p1,Pt(16,16))), -2, F); | |
+ wrbitmap(bm, 0, 16, arrowset); | |
+ fprintf(stderr, "bitblt(&screen, (%d,%d), bm, (0,0,16,16), S)\n", | |
+ p1.x,p1.y); | |
+ bitblt(&screen, p1, bm, Rect(0,0,16,16), S); | |
+ cont("mouse track (button 1)"); | |
+ do{ | |
+ m = emouse(); | |
+ } while(!(m.buttons&1)); | |
+ fprintf(stderr,"test tracking\n"); | |
+ while(m.buttons&1){ | |
+ point(&screen, m.xy, ~0, S); | |
+ m = emouse(); | |
+ } | |
+ cursorswitch(0); | |
+ cont("menuhit (button 3)"); | |
+ do { | |
+ do{ | |
+ m = emouse(); | |
+ } while(!(m.buttons&4)); | |
+ n = menuhit(3, &m, &menu3); | |
+ fprintf(stderr, "button %d\n", n); | |
+ } while (n != 0); | |
+ cont("keyboard (end with \\n)"); | |
+ fprintf(stderr, "type something\n"); | |
+ for (p = buf; (*p = ekbd()) != '\n' && *p != '\r'; p++) { | |
+ fprintf(stderr, "%c", *p); | |
+ if (*p == '\b') | |
+ p -= 2; | |
+ if (p < buf-1) | |
+ p = buf-1; | |
+ p[1] = 0; | |
+ putstring(buf); | |
+ } | |
+ cont("done"); | |
+ exit(0); | |
+} | |
+ | |
+void colorinit(void) /* set up color definitions */ | |
+{ | |
+ int i; | |
+ | |
+ for (i = 0; i < Ncol; i++) { | |
+ rgbval[i] = rgbpix(&screen, colordefs[i]); | |
+ rgbbitmap[i] = balloc(Rect(0,0,1,1), screen.ldepth); | |
+ point(rgbbitmap[i], Pt(0,0), rgbval[i], S); | |
+ } | |
+} | |
+ | |
+void printcolmap(void) | |
+{ | |
+ int i, n; | |
+ RGB cmap[256]; | |
+ | |
+ rdcolmap(&screen, cmap); | |
+ n = 1 << (1 << screen.ldepth); | |
+ fprintf(stderr, "colormap, %d entries\n", n); | |
+ for(i = 0; i < n; i++) | |
+ fprintf(stderr, "%d:\t%.8x\t%.8x\t%.8x\n", | |
+ i, cmap[i].red, cmap[i].green, cmap[i].blue); | |
+} | |
+ | |
+void invertcolmap(void) | |
+{ | |
+ int i, n; | |
+ RGB cmap[256]; | |
+ | |
+ rdcolmap(&screen, cmap); | |
+ n = 1 << (1 << screen.ldepth); | |
+ for(i = 0; i < n; i++) { | |
+ cmap[i].red = ~cmap[i].red; | |
+ cmap[i].green = ~cmap[i].green; | |
+ cmap[i].blue = ~cmap[i].blue; | |
+ } | |
+ wrcolmap(&screen, cmap); | |
+} | |
+ | |
+void | |
+putstring(char *buf) | |
+{ | |
+ Point p; | |
+ static int jmax = 0, l; | |
+ | |
+ p = add(screen.r.min, Pt(20,20)); | |
+ bitblt(&screen, p, &screen, Rect(p.x, p.y, p.x+jmax, p.y+font->height)… | |
+ string(&screen, p, font, buf, F); | |
+ if ((l = strwidth(font, buf)) > jmax) | |
+ jmax = l; | |
+} | |
+ | |
+void | |
+cont(char *msg) | |
+{ | |
+ Event ev; | |
+ Point mp; | |
+ | |
+ while(event(&ev) != Ekeyboard) | |
+ continue; | |
+ bitblt(&screen, Pt(0,0), &screen, screen.r, Zero); | |
+ mp = add(screen.r.min, Pt(20,20)); | |
+ string(&screen, mp, font, msg, S); | |
+ while(event(&ev) != Ekeyboard) | |
+ continue; | |
+ bitblt(&screen, Pt(0,0), &screen, screen.r, Zero); | |
+} | |
+ | |
+char * | |
+m3gen(int n) | |
+{ | |
+ static char *m3[] ={ "quit", "thing1", "thing2" }; | |
+ | |
+ if (n < 0 || n > 2) | |
+ return 0; | |
+ else | |
+ return m3[n]; | |
+} | |
+ | |
+void | |
+ereshaped(Rectangle r) | |
+{ | |
+} | |
diff --git a/libXg/texture.c b/libXg/texture.c | |
@@ -0,0 +1,42 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+void | |
+texture(Bitmap *d, Rectangle r, Bitmap *s, Fcode f) | |
+{ | |
+ int x, y, w, h, bfunc; | |
+ GC g; | |
+ | |
+ x = r.min.x; | |
+ y = r.min.y; | |
+ if(d->flag&SHIFT){ | |
+ x -= d->r.min.x; | |
+ y -= d->r.min.y; | |
+ } | |
+ g = _getcopygc(f, d, s, &bfunc); | |
+ if(d->flag&SHIFT){ | |
+ XSetTSOrigin(_dpy, g, -d->r.min.x, -d->r.min.y); | |
+ }else | |
+ XSetTSOrigin(_dpy, g, 0, 0); | |
+ w = Dx(r); | |
+ h = Dy(r); | |
+ if(bfunc == UseFillRectangle){ | |
+ /* source isn't involved at all */ | |
+ XFillRectangle(_dpy, (Drawable)d->id, g, x, y, w, h); | |
+ }else if(bfunc == UseCopyArea){ | |
+ XSetTile(_dpy, g, (Drawable)s->id); | |
+ XSetFillStyle(_dpy, g, FillTiled); | |
+ XFillRectangle(_dpy, (Drawable)d->id, g, x, y, w, h); | |
+ XSetFillStyle(_dpy, g, FillSolid); | |
+ }else{ | |
+ if(s->ldepth != 0) | |
+ berror("unsupported texture"); | |
+ XSetStipple(_dpy, g, (Drawable)s->id); | |
+ XSetFillStyle(_dpy, g, FillOpaqueStippled); | |
+ XFillRectangle(_dpy, (Drawable)d->id, g, x, y, w, h); | |
+ XSetFillStyle(_dpy, g, FillSolid); | |
+ } | |
+} | |
diff --git a/libXg/wrbitmap.c b/libXg/wrbitmap.c | |
@@ -0,0 +1,55 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+#include <X11/Intrinsic.h> | |
+#ifndef XtSpecificationRelease | |
+#define R3 | |
+#endif | |
+ | |
+#include <stdio.h> | |
+void | |
+wrbitmap(Bitmap *b, int miny, int maxy, unsigned char *data) | |
+{ | |
+ XImage *im; | |
+ int w, h, inld, outld, l, offset, px; | |
+ GC g; | |
+ char *tdata; | |
+ | |
+ w = Dx(b->r); | |
+ h = maxy - miny; | |
+ inld = b->ldepth; | |
+ outld = (b->ldepth == 0) ? 0 : screen.ldepth; | |
+ px = 1<<(3-outld); /* pixels per byte */ | |
+ /* set l to number of bytes of data per scan line */ | |
+ if(b->r.min.x >= 0) | |
+ offset = b->r.min.x % px; | |
+ else | |
+ offset = px - b->r.min.x % px; | |
+ l = (-b->r.min.x+px-1)/px; | |
+ if(b->r.max.x >= 0) | |
+ l += (b->r.max.x+px-1)/px; | |
+ else | |
+ l -= b->r.max.x/px; | |
+ l *= h; | |
+ | |
+ tdata = (char *)malloc(l); | |
+ if (tdata == (char *) 0) | |
+ berror("wrbitmap malloc"); | |
+ if (inld == outld) | |
+ memcpy((void*)tdata, (void*)data, l); | |
+ else | |
+ _ldconvert((char*)data, inld, tdata, outld, w, h); | |
+ | |
+ im = XCreateImage(_dpy, 0, 1 << outld, ZPixmap, 0, tdata, w, h, 8, 0); | |
+ | |
+ /* Botched interface to XCreateImage doesn't let you set these: */ | |
+ im->bitmap_bit_order = MSBFirst; | |
+ im->byte_order = MSBFirst; | |
+ | |
+ g = _getfillgc(S, b, ~0); | |
+ XSetBackground(_dpy, g, b->flag&DP1 ? 0 : _bgpixel); | |
+ XPutImage(_dpy, (Drawable)b->id, g, im, offset, 0, 0, miny - b->r.min.… | |
+ XDestroyImage(im); | |
+} | |
diff --git a/libXg/wrbitmapfile.c b/libXg/wrbitmapfile.c | |
@@ -0,0 +1,50 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include "libgint.h" | |
+ | |
+#define CHUNK 4096 | |
+ | |
+void | |
+wrbitmapfile(int fd, Bitmap *b) | |
+{ | |
+ char hdr[5*12+1]; | |
+ unsigned char *data; | |
+ long dy, px; | |
+ unsigned long l, t, n; | |
+ long miny, maxy; | |
+ | |
+ sprint(hdr, "%11d %11d %11d %11d %11d ", | |
+ b->ldepth, b->r.min.x, b->r.min.y, b->r.max.x, b->r.max.y); | |
+ if(write(fd, hdr, 5*12) != 5*12) | |
+ berror("wrbitmapfile write"); | |
+ | |
+ px = 1<<(3-b->ldepth); /* pixels per byte */ | |
+ /* set l to number of bytes of data per scan line */ | |
+ if(b->r.min.x >= 0) | |
+ l = (b->r.max.x+px-1)/px - b->r.min.x/px; | |
+ else{ /* make positive before divide */ | |
+ t = (-b->r.min.x)+px-1; | |
+ t = (t/px)*px; | |
+ l = (t+b->r.max.x+px-1)/px; | |
+ } | |
+ miny = b->r.min.y; | |
+ maxy = b->r.max.y; | |
+ data = (unsigned char *)malloc(CHUNK); | |
+ if(data == 0) | |
+ berror("wrbitmapfile malloc"); | |
+ while(maxy > miny){ | |
+ dy = maxy - miny; | |
+ if(dy*l > CHUNK) | |
+ dy = CHUNK/l; | |
+ rdbitmap(b, miny, miny+dy, data); | |
+ n = dy*l; | |
+ if(write(fd, data, n) != n){ | |
+ free(data); | |
+ berror("wrbitmapfile write"); | |
+ } | |
+ miny += dy; | |
+ } | |
+ free(data); | |
+} | |
diff --git a/libXg/xtbinit.c b/libXg/xtbinit.c | |
@@ -0,0 +1,830 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <stdio.h> | |
+#include "libgint.h" | |
+ | |
+#define COMPRESSMOUSE | |
+ | |
+#define Cursor xCursor | |
+#define Font xFont | |
+#define Event xEvent | |
+ | |
+#include <X11/Intrinsic.h> | |
+#include <X11/StringDefs.h> | |
+#include <X11/Shell.h> | |
+#include "Gwin.h" | |
+ | |
+#ifndef XtSpecificationRelease | |
+#define R3 | |
+#define XtAppInitialize(a,b,c,d,e,f,g,h,i) XtInitialize(0,b,c,d,e,f) | |
+#define XtConvertAndStore(a,b,c,d,e) (XtConvert(a,b,c,d,e),1) | |
+#define XtAppPending(a) XtPending() | |
+#define XtAppProcessEvent(a,b) XtProcessEvent(b) | |
+#define XtAppAddTimeOut(a,b,c,d) XtAddTimeOut(b,c,d) | |
+#define XtAppAddInput(a,b,c,d,e) XtAddInput(b,c,d,e) | |
+#define XtPointer caddr_t | |
+#endif | |
+ | |
+#undef Cursor | |
+#undef Font | |
+#undef Event | |
+ | |
+/* libg globals */ | |
+Bitmap screen; | |
+XftFont *font; | |
+XftColor fontcolor; | |
+XftColor bgcolor; | |
+ | |
+/* implementation globals */ | |
+Display *_dpy; | |
+Widget _toplevel; | |
+unsigned long _fgpixel, _bgpixel; | |
+XColor _fgcolor, _bgcolor; | |
+int _ld2d[6] = { 1, 2, 4, 8, 16, 24 }; | |
+unsigned long _ld2dmask[6] = { 0x1, 0x3, 0xF, 0xFF, 0xFFFF, 0x00FFFFFF … | |
+Colormap _libg_cmap; | |
+int _cmap_installed; | |
+ | |
+/* xbinit implementation globals */ | |
+#ifndef R3 | |
+static XtAppContext app; | |
+#endif | |
+static Widget widg; | |
+static int exposed = 0; | |
+static Atom wm_take_focus; | |
+static Mouse lastmouse; | |
+ | |
+typedef struct Ebuf { | |
+ struct Ebuf *next; | |
+ int n; | |
+ unsigned char buf[2]; | |
+} Ebuf; | |
+ | |
+typedef struct Esrc { | |
+ int inuse; | |
+ int size; | |
+ int count; | |
+ Ebuf *head; | |
+ Ebuf *tail; | |
+} Esrc; | |
+ | |
+#define MAXINPUT 1024 /* number of queued input e… | |
+#define MAXSRC 10 | |
+ | |
+static Esrc esrc[MAXSRC]; | |
+static int nsrc; | |
+ | |
+ | |
+static int einitcalled = 0; | |
+static int Smouse = -1; | |
+static int Skeyboard = -1; | |
+static int Stimer = -1; | |
+ | |
+ | |
+static void reshaped(int, int, int, int); | |
+static void gotchar(int); | |
+static void gotmouse(Gwinmouse *); | |
+static int ilog2(int); | |
+static void pixtocolor(Pixel, XColor *); | |
+static Ebuf *ebread(Esrc *); | |
+static Ebuf *ebadd(Esrc *); | |
+static void focinit(Widget); | |
+static void wmproto(Widget, XEvent *, String *, Cardinal *); | |
+static void waitevent(void); | |
+void initlatin(); | |
+ | |
+static Errfunc onerr; | |
+ | |
+String _fallbacks[] = { | |
+ "*gwin.width: 400", | |
+ "*gwin.height: 400", | |
+ NULL | |
+}; | |
+ | |
+#ifndef R3 | |
+static char *shelltrans = | |
+ "<ClientMessage> WM_PROTOCOLS : WMProtocolAction()"; | |
+static XtActionsRec wmpactions[] = { | |
+ {"WMProtocolAction", wmproto} | |
+}; | |
+#endif | |
+ | |
+ /* too many X options */ | |
+static XrmOptionDescRec optable[] = { | |
+}; | |
+ | |
+ | |
+ | |
+ | |
+void | |
+xtbinit(Errfunc f, char *class, int *pargc, char **argv, char **fallbacks) | |
+{ | |
+ int n; | |
+ unsigned int depth; | |
+ Arg args[20]; | |
+ char *p; | |
+ XSetWindowAttributes attr; | |
+ int compose; | |
+ | |
+ initlatin(); | |
+ | |
+ if(!class && argv[0]){ | |
+ p = strrchr(argv[0], '/'); | |
+ if(p) | |
+ class = XtNewString(p+1); | |
+ else | |
+ class = XtNewString(argv[0]); | |
+ if(class[0] >= 'a' && class[0] <= 'z') | |
+ class[0] += 'A' - 'a'; | |
+ } | |
+ onerr = f; | |
+ if (!fallbacks) | |
+ fallbacks = _fallbacks; | |
+ n = 0; | |
+ XtSetArg(args[n], XtNinput, TRUE); n++; | |
+ | |
+ | |
+ if (*pargc >= 3 && strcmp(argv[1], "-r") == 0) | |
+ { | |
+ char name[512] = {0}; | |
+ snprintf(name, 511, "samterm on %s", argv[2]); | |
+ XtSetArg(args[n], XtNtitle, XtNewString(name)); n++; | |
+ XtSetArg(args[n], XtNiconName, XtNewString(name)); n++; | |
+ } | |
+ else | |
+ { | |
+ XtSetArg(args[n], XtNtitle, XtNewString("samterm on localhost")); n++;… | |
+ } | |
+ _toplevel = XtAppInitialize(&app, class, | |
+ optable, sizeof(optable)/sizeof(optable[0]), | |
+ pargc, argv, fallbacks, args, n); | |
+ | |
+ | |
+ n = 0; | |
+ XtSetArg(args[n], XtNreshaped, reshaped); n++; | |
+ XtSetArg(args[n], XtNgotchar, gotchar); n++; | |
+ XtSetArg(args[n], XtNgotmouse, gotmouse); n++; | |
+ widg = XtCreateManagedWidget("gwin", gwinWidgetClass, _toplevel, args, n); | |
+ | |
+ _dpy = XtDisplay(widg); | |
+ XAllocNamedColor(_dpy, DefaultColormap(_dpy, DefaultScreen(_dpy)), getenv(… | |
+ XAllocNamedColor(_dpy, DefaultColormap(_dpy, DefaultScreen(_dpy)), getenv(… | |
+ | |
+ n = 0; | |
+ XtSetArg(args[n], XtNdepth, &depth); n++; | |
+ XtSetArg(args[n], XtNcomposeMod, &compose); n++; | |
+ XtGetValues(widg, args, n); | |
+ | |
+ if (compose < 0 || compose > 5) { | |
+ n = 0; | |
+ XtSetArg(args[n], XtNcomposeMod, 0); n++; | |
+ XtSetValues(widg, args, n); | |
+ } | |
+ | |
+ font = XftFontOpenName(_dpy, DefaultScreen(_dpy), getenv("FONT") ? getenv(… | |
+ screen.id = 0; | |
+ XtRealizeWidget(_toplevel); | |
+ | |
+ pid_t pid = getpid(); | |
+ XChangeProperty(_dpy, XtWindow(_toplevel), XInternAtom(_dpy, "_NET_WM_PID"… | |
+ | |
+ _fgpixel = _fgcolor.pixel; | |
+ _bgpixel = _bgcolor.pixel; | |
+ | |
+ XRenderColor xrcolor = {0}; | |
+ xrcolor.red = _fgcolor.red; | |
+ xrcolor.green = _fgcolor.green; | |
+ xrcolor.blue = _fgcolor.blue; | |
+ xrcolor.alpha = 65535; | |
+ XftColorAllocValue(_dpy, DefaultVisual(_dpy, DefaultScreen(_dpy)), Default… | |
+ | |
+ xrcolor.red = _bgcolor.red; | |
+ xrcolor.green = _bgcolor.green; | |
+ xrcolor.blue = _bgcolor.blue; | |
+ XftColorAllocValue(_dpy, DefaultVisual(_dpy, DefaultScreen(_dpy)), Default… | |
+ | |
+ screen.id = (int) XtWindow(widg); | |
+ screen.ldepth = ilog2(depth); | |
+ screen.flag = SCR; | |
+ if(_fgpixel != 0) | |
+ screen.flag |= BL1; | |
+ if(depth == 1) | |
+ screen.flag |= DP1; | |
+ /* leave screen rect at all zeros until reshaped() sets it */ | |
+ while(!exposed) { | |
+ XFlush(_dpy); | |
+ XtAppProcessEvent(app, XtIMXEvent); | |
+ } | |
+ XFlush(_dpy); | |
+ focinit(_toplevel); | |
+} | |
+ | |
+static void | |
+focinit(Widget w) | |
+{ | |
+#ifndef R3 | |
+ XrmValue src, dst; | |
+ | |
+ src.addr = "WM_TAKE_FOCUS"; | |
+ src.size = strlen((char *)src.addr)+1; | |
+ dst.addr = (XtPointer) &wm_take_focus; | |
+ dst.size = sizeof(Atom); | |
+ XtConvertAndStore(w, XtRString, &src, XtRAtom, &dst); | |
+ XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_take_focus, 1); | |
+ XtAppAddActions(app, wmpactions, XtNumber(wmpactions)); | |
+ XtAugmentTranslations(w, XtParseTranslationTable(shelltrans)); | |
+#endif | |
+} | |
+ | |
+#ifndef R3 | |
+static void | |
+wmproto(Widget w, XEvent *e , String *p, Cardinal *np) | |
+{ | |
+ Time t; | |
+ | |
+ if(e->type == ClientMessage && | |
+ (Atom)(e->xclient.data.l[0]) == wm_take_focus) { | |
+ t = (Time) e->xclient.data.l[1]; | |
+ XtCallAcceptFocus(widg, &t); | |
+ } | |
+} | |
+#endif | |
+ | |
+static void | |
+reshaped(int minx, int miny, int maxx, int maxy) | |
+{ | |
+ Ebuf *eb; | |
+ Mouse m; | |
+ | |
+ screen.r = Rect(minx, miny, maxx, maxy); | |
+ screen.clipr = screen.r; | |
+ if (screen.id) { | |
+ exposed = 1; | |
+ ereshaped(screen.r); | |
+ } | |
+ if(einitcalled){ | |
+ /* | |
+ * Cause a mouse event, so programs like sam | |
+ * will get out of eread and REALLY do the reshape | |
+ */ | |
+ eb = ebadd(&esrc[Smouse]); | |
+ if (eb == 0) | |
+ berror("eballoc can't malloc"); | |
+ memcpy((void*)eb->buf, (void*)&lastmouse, sizeof lastmouse); | |
+ esrc[Smouse].count++; | |
+ } | |
+} | |
+ | |
+static void | |
+gotchar(int c) | |
+{ | |
+ Ebuf *eb; | |
+ | |
+ if(!einitcalled || Skeyboard == -1) | |
+ return; | |
+ eb = ebadd(&esrc[Skeyboard]); | |
+ if (eb == 0) | |
+ berror("eballoc can't malloc"); | |
+ BPSHORT(eb->buf, (unsigned short)(c & 0xffff)); | |
+ esrc[Skeyboard].count++; | |
+} | |
+ | |
+static void | |
+gotmouse(Gwinmouse *gm) | |
+{ | |
+ Ebuf *eb; | |
+ Mouse m; | |
+ | |
+ if(!einitcalled || Smouse == -1) | |
+ return; | |
+ m.buttons = gm->buttons; | |
+ m.xy.x = gm->xy.x; | |
+ m.xy.y = gm->xy.y; | |
+ m.msec = gm->msec; | |
+ lastmouse = m; | |
+ eb = ebadd(&esrc[Smouse]); | |
+ if (eb == 0) | |
+ berror("eballoc can't malloc"); | |
+ memcpy((void*)eb->buf, (void*)&m, sizeof m); | |
+ esrc[Smouse].count++; | |
+} | |
+ | |
+static void | |
+gotinput(XtPointer cldata, int *pfd, XtInputId *id) | |
+{ | |
+ Ebuf *eb, *lasttail, *newe; | |
+ Esrc *es; | |
+ int n; | |
+ | |
+ if(!einitcalled) | |
+ return; | |
+ es = (Esrc *)cldata; | |
+ if (es->count >= MAXINPUT) | |
+ return; | |
+ lasttail = es->tail; | |
+ eb = ebadd(es); | |
+ if (eb == 0) | |
+ return; | |
+ if(es->size){ | |
+ n = read(*pfd, (char *)eb->buf, es->size); | |
+ if (n < 0) | |
+ n = 0; | |
+ if(n < es->size) { | |
+ newe = realloc(eb, sizeof(Ebuf)+n); | |
+ newe->n = n; | |
+ if (es->head == eb) | |
+ es->head = newe; | |
+ else | |
+ lasttail->next = newe; | |
+ es->tail = newe; | |
+ } | |
+ } | |
+ es->count++; | |
+} | |
+ | |
+static void | |
+gottimeout(XtPointer cldata, XtIntervalId *id) | |
+{ | |
+ if(!einitcalled || Stimer == -1) | |
+ return; | |
+ /* | |
+ * Don't queue up timeouts, because there's | |
+ * too big a danger that they might pile up | |
+ * too quickly. | |
+ */ | |
+ esrc[Stimer].head = (Ebuf *)1; | |
+ esrc[Stimer].count = 1; | |
+ XtAppAddTimeOut(app, (long)cldata, gottimeout, cldata); | |
+} | |
+ | |
+static int | |
+ilog2(int n) | |
+{ | |
+ int i, v; | |
+ | |
+ for(i=0, v=1; i < 6; i++, v<<=1) | |
+ if(n <= v) | |
+ break; | |
+ return i; | |
+} | |
+ | |
+static void | |
+pixtocolor(Pixel p, XColor *pc) | |
+{ | |
+#ifdef R3 | |
+ Colormap cmap; | |
+ Arg args[2]; | |
+ int n; | |
+ | |
+ n = 0; | |
+ XtSetArg(args[n], XtNcolormap, &cmap); n++; | |
+ XtGetValues(_toplevel, args, n); | |
+ pc->pixel = p; | |
+ XQueryColor(_dpy, cmap, pc); | |
+#else | |
+ XrmValue xvf, xvt; | |
+ | |
+ xvf.size = sizeof(Pixel); | |
+ xvf.addr = (XtPointer)&p; | |
+ xvt.size = sizeof(XColor); | |
+ xvt.addr = (XtPointer)pc; | |
+ if(!XtConvertAndStore(_toplevel, XtRPixel, &xvf, XtRColor, &xvt)) | |
+ pc->pixel = p; /* maybe that's enough */ | |
+#endif | |
+} | |
+ | |
+unsigned long | |
+rgbpix(Bitmap *b, RGB col) | |
+{ | |
+ XColor c; | |
+ Colormap cmap; | |
+ Arg args[2]; | |
+ int n, depth, dr, dg, db; | |
+ RGB map[256], *m; | |
+ unsigned long d, max, pixel; | |
+ | |
+ if (!_cmap_installed) { | |
+ n = 0; | |
+ XtSetArg(args[n], XtNcolormap, &cmap); n++; | |
+ XtGetValues(_toplevel, args, n); | |
+ c.red = col.red>>16; | |
+ c.green = col.green>>16; | |
+ c.blue = col.blue>>16; | |
+ c.flags = DoRed|DoGreen|DoBlue; | |
+ if(XAllocColor(_dpy, cmap, &c)) | |
+ return (unsigned long)(c.pixel); | |
+ } | |
+ depth = _ld2d[screen.ldepth]; | |
+ rdcolmap(&screen, map); | |
+ max = -1; | |
+ for (n = 0, m = map; n < (1 << depth); n++, m++) | |
+ { | |
+ dr = m->red - col.red; | |
+ dg = m->green - col.green; | |
+ db = m->blue - col.blue; | |
+ d = dr*dr+dg*dg+db*db; | |
+ if (d < max || max == -1) | |
+ { | |
+ max = d; | |
+ pixel = n; | |
+ } | |
+ } | |
+ return pixel; | |
+} | |
+ | |
+void | |
+rdcolmap(Bitmap *b, RGB *map) | |
+{ | |
+ XColor cols[256]; | |
+ int i, n, depth; | |
+ Colormap cmap; | |
+ Arg args[2]; | |
+ | |
+ if (_cmap_installed) { | |
+ cmap = _libg_cmap; | |
+ } else { | |
+ i = 0; | |
+ XtSetArg(args[i], XtNcolormap, &cmap); i++; | |
+ XtGetValues(_toplevel, args, i); | |
+ } | |
+ | |
+ depth = _ld2d[screen.ldepth]; | |
+ n = 1 << depth; | |
+ if (depth == 1) { | |
+ map[0].red = map[0].green = map[0].blue = ~0; | |
+ map[1].red = map[1].green = map[1].blue = 0; | |
+ } | |
+ else { | |
+ if (n > 256) { | |
+ berror("rdcolmap bitmap too deep"); | |
+ return; | |
+ } | |
+ for (i = 0; i < n; i++) | |
+ cols[i].pixel = i; | |
+ XQueryColors(_dpy, cmap, cols, n); | |
+ for (i = 0; i < n; i++) { | |
+ map[i].red = (cols[i].red << 16) | cols[i].red; | |
+ map[i].green = (cols[i].green << 16) | cols[i].green; | |
+ map[i].blue = (cols[i].blue << 16) | cols[i].blue; | |
+ } | |
+ } | |
+} | |
+ | |
+void | |
+wrcolmap(Bitmap *b, RGB *map) | |
+{ | |
+ int i, n, depth; | |
+ Screen *scr; | |
+ XColor cols[256]; | |
+ Arg args[2]; | |
+ XVisualInfo vi; | |
+ Window w; | |
+ | |
+ scr = XtScreen(_toplevel); | |
+ depth = _ld2d[screen.ldepth]; | |
+ n = 1 << depth; | |
+ if (n > 256) { | |
+ berror("wrcolmap bitmap too deep"); | |
+ return; | |
+ } else if (depth > 1) { | |
+ for (i = 0; i < n; i++) { | |
+ cols[i].red = map[i].red >> 16; | |
+ cols[i].green = map[i].green >> 16; | |
+ cols[i].blue = map[i].blue >> 16; | |
+ cols[i].pixel = i; | |
+ cols[i].flags = DoRed|DoGreen|DoBlue; | |
+ } | |
+ if (!XMatchVisualInfo(_dpy, XScreenNumberOfScreen(scr), | |
+ depth, PseudoColor, &vi)) { | |
+ berror("wrcolmap can't get visual"); | |
+ return; | |
+ } | |
+ w = XtWindow(_toplevel); | |
+ _libg_cmap = XCreateColormap(_dpy, w, vi.visual, AllocAll); | |
+ XStoreColors(_dpy, _libg_cmap, cols, n); | |
+ | |
+ i = 0; | |
+ XtSetArg(args[i], XtNcolormap, _libg_cmap); i++; | |
+ XtSetValues(_toplevel, args, i); | |
+ _cmap_installed = 1; | |
+ } | |
+} | |
+ | |
+int | |
+scrollfwdbut(void) | |
+{ | |
+ Arg arg; | |
+ Boolean v; | |
+ String s; | |
+ | |
+ XtSetArg(arg, XtNscrollForwardR, &v); | |
+ XtGetValues(widg, &arg, 1); | |
+ return v ? 3 : 1; | |
+} | |
+ | |
+void | |
+einit(unsigned long keys) | |
+{ | |
+ /* | |
+ * Make sure Smouse = ilog2(Emouse) and Skeyboard == ilog2(Ekeyboard) | |
+ */ | |
+ nsrc = 0; | |
+ if(keys&Emouse){ | |
+ Smouse = 0; | |
+ esrc[Smouse].inuse = 1; | |
+ esrc[Smouse].size = sizeof(Mouse); | |
+ esrc[Smouse].count = 0; | |
+ nsrc = Smouse+1; | |
+ } | |
+ if(keys&Ekeyboard){ | |
+ Skeyboard = 1; | |
+ esrc[Skeyboard].inuse = 1; | |
+ esrc[Skeyboard].size = 1; | |
+ esrc[Skeyboard].count = 0; | |
+ if(Skeyboard >= nsrc) | |
+ nsrc = Skeyboard+1; | |
+ } | |
+ einitcalled = 1; | |
+} | |
+ | |
+unsigned long | |
+estart(unsigned long key, int fd, int n) | |
+{ | |
+ int i; | |
+ | |
+ if(fd < 0) | |
+ berror("bad fd to estart"); | |
+ if(n <= 0 || n > EMAXMSG) | |
+ n = EMAXMSG; | |
+ for(i=0; i<MAXSRC; i++) | |
+ if((key & ~(1<<i)) == 0 && !esrc[i].inuse){ | |
+ if(nsrc <= i) | |
+ nsrc = i+1; | |
+ esrc[i].inuse = 1; | |
+ esrc[i].size = n; | |
+ esrc[i].count = 0; | |
+ XtAppAddInput(app, fd, (XtPointer)XtInputReadMask, | |
+ gotinput, (XtPointer) &esrc[i]); | |
+ return 1<<i; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+unsigned long | |
+etimer(unsigned long key, long n) | |
+{ | |
+ int i; | |
+ | |
+ if(Stimer != -1) | |
+ berror("timer started twice"); | |
+ if(n <= 0) | |
+ n = 1000; | |
+ for(i=0; i<MAXSRC; i++) | |
+ if((key & ~(1<<i)) == 0 && !esrc[i].inuse){ | |
+ if(nsrc <= i) | |
+ nsrc = i+1; | |
+ esrc[i].inuse = 1; | |
+ esrc[i].size = 0; | |
+ esrc[i].count = 0; | |
+ XtAppAddTimeOut(app, n, gottimeout, (XtPointer)n); | |
+ Stimer = i; | |
+ return 1<<i; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+unsigned long | |
+event(Event *e) | |
+{ | |
+ return eread(~0L, e); | |
+} | |
+ | |
+unsigned long | |
+eread(unsigned long keys, Event *e) | |
+{ | |
+ Ebuf *eb; | |
+ int i; | |
+ | |
+ if(keys == 0) | |
+ return 0; | |
+ /* Give Priority to X events */ | |
+ if (XtAppPending(app) & XtIMXEvent) | |
+ XtAppProcessEvent(app, XtIMXEvent); | |
+ | |
+ for(;;){ | |
+ for(i=0; i<nsrc; i++) | |
+ if((keys & (1<<i)) && esrc[i].head){ | |
+ if(i == Smouse) | |
+ e->mouse = emouse(); | |
+ else if(i == Skeyboard) | |
+ e->kbdc = ekbd(); | |
+ else if(i == Stimer) { | |
+ esrc[i].head = 0; | |
+ esrc[i].count = 0; | |
+ } else { | |
+ eb = ebread(&esrc[i]); | |
+ e->n = eb->n; | |
+ if(e->n > 0) | |
+ memcpy((void*)e->data, (void*)eb->… | |
+ free(eb); | |
+ } | |
+ return 1<<i; | |
+ } | |
+ waitevent(); | |
+ } | |
+} | |
+ | |
+void | |
+eflush(unsigned long keys) | |
+{ | |
+ int i; | |
+ Ebuf *eb, *enext; | |
+ | |
+ if(keys == 0) | |
+ return; | |
+ | |
+ for(i=0; i<nsrc; i++) | |
+ if((keys & (1<<i))){ | |
+ for (eb = esrc[i].head; eb; eb = enext) { | |
+ enext = eb->next; | |
+ free(eb); | |
+ } | |
+ esrc[i].count = 0; | |
+ esrc[i].head = 0; | |
+ esrc[i].tail = 0; | |
+ } | |
+} | |
+ | |
+Mouse | |
+emouse(void) | |
+{ | |
+ Mouse m; | |
+ Ebuf *eb; | |
+ | |
+ if(!esrc[Smouse].inuse) | |
+ berror("mouse events not selected"); | |
+ eb = ebread(&esrc[Smouse]); | |
+ memcpy((void*)&m, (void*)eb->buf, sizeof(Mouse)); | |
+ free(eb); | |
+ return m; | |
+} | |
+ | |
+int | |
+ekbd(void) | |
+{ | |
+ Ebuf *eb; | |
+ int c; | |
+ | |
+ if(!esrc[Skeyboard].inuse) | |
+ berror("keyboard events not selected"); | |
+ eb = ebread(&esrc[Skeyboard]); | |
+ c = BGSHORT(eb->buf); | |
+ free(eb); | |
+ return c; | |
+} | |
+ | |
+int | |
+ecanread(unsigned long keys) | |
+{ | |
+ int i; | |
+ | |
+ for(;;){ | |
+ for(i=0; i<nsrc; i++){ | |
+ if((keys & (1<<i)) && esrc[i].head) | |
+ return 1<<i; | |
+ } | |
+ if(XtAppPending(app)) | |
+ waitevent(); | |
+ else | |
+ return 0; | |
+ } | |
+} | |
+ | |
+int | |
+ecanmouse(void) | |
+{ | |
+ if(Smouse == -1) | |
+ berror("mouse events not selected"); | |
+ return ecanread(Emouse); | |
+} | |
+ | |
+int | |
+ecankbd(void) | |
+{ | |
+ if(Skeyboard == -1) | |
+ berror("keyboard events not selected"); | |
+ return ecanread(Ekeyboard); | |
+} | |
+ | |
+static Ebuf* | |
+ebread(Esrc *s) | |
+{ | |
+ Ebuf *eb; | |
+ | |
+ while(s->head == 0) | |
+ waitevent(); | |
+ eb = s->head; | |
+#ifdef COMPRESSMOUSE | |
+ if(s == &esrc[Smouse]) { | |
+ while(eb->next) { | |
+ s->head = eb->next; | |
+ s->count--; | |
+ free(eb); | |
+ eb = s->head; | |
+ } | |
+ } | |
+#endif | |
+ s->head = s->head->next; | |
+ if(s->head == 0) { | |
+ s->tail = 0; | |
+ s->count = 0; | |
+ } else | |
+ s->count--; | |
+ return eb; | |
+} | |
+ | |
+static Ebuf* | |
+ebadd(Esrc *s) | |
+{ | |
+ Ebuf *eb; | |
+ int m; | |
+ | |
+ m = sizeof(Ebuf); | |
+ if(s->size > 1) | |
+ m += (s->size-1); /* overestimate, because of alignment */ | |
+ eb = (Ebuf *)malloc(m); | |
+ if(eb) { | |
+ eb->next = 0; | |
+ eb->n = s->size; | |
+ if(s->tail){ | |
+ s->tail->next = eb; | |
+ s->tail = eb; | |
+ }else | |
+ s->head = s->tail = eb; | |
+ } | |
+ return eb; | |
+} | |
+ | |
+void | |
+berror(char *s) | |
+{ | |
+ if(onerr) | |
+ (*onerr)(s); | |
+ else{ | |
+ fprintf(stderr, "libg error: %s:\n", s); | |
+ exit(1); | |
+ } | |
+} | |
+ | |
+void | |
+bflush(void) | |
+{ | |
+ while(XtAppPending(app) & XtIMXEvent) | |
+ waitevent(); | |
+} | |
+ | |
+static void | |
+waitevent(void) | |
+{ | |
+ XFlush(_dpy); | |
+ if (XtAppPending(app) & XtIMXEvent) | |
+ XtAppProcessEvent(app, XtIMXEvent); | |
+ else | |
+ XtAppProcessEvent(app, XtIMAll); | |
+} | |
+ | |
+int | |
+snarfswap(char *s, int n, char **t) | |
+{ | |
+ *t = GwinSelectionSwap(widg, s); | |
+ if (*t) | |
+ return strlen(*t); | |
+ return 0; | |
+} | |
+ | |
+int scrpix(int *w, int *h) | |
+{ | |
+ if (w) | |
+ *w = WidthOfScreen(XtScreen(_toplevel)); | |
+ if (h) | |
+ *h = HeightOfScreen(XtScreen(_toplevel)); | |
+ return 1; | |
+} | |
+ | |
+#ifdef DEBUG | |
+/* for debugging */ | |
+printgc(char *msg, GC g) | |
+{ | |
+ XGCValues v; | |
+ | |
+ XGetGCValues(_dpy, g, GCFunction|GCForeground|GCBackground|GCFont| | |
+ GCTile|GCFillStyle|GCStipple, &v); | |
+ fprintf(stderr, "%s: gc %x\n", msg, g); | |
+ fprintf(stderr, " fg %d bg %d func %d fillstyle %d font %x tile %x stippl… | |
+ v.foreground, v.background, v.function, v.fill_style, | |
+ v.font, v.tile, v.stipple); | |
+} | |
+#endif | |
+ | |
diff --git a/libframe/Makefile b/libframe/Makefile | |
@@ -0,0 +1,47 @@ | |
+# Copyright (c) 1998 Lucent Technologies - All rights reserved. | |
+# | |
+# Prototype Makefile for libframe | |
+# | |
+# define operating system. ONE of: | |
+# -DIRIX -DSUNOS -DUMIPS -DSYSVR3 -DAIX -DOSF1 | |
+# -DHPUX -DAPOLLO -DCONVEX -DDYNIX | |
+# | |
+# Additionally, -D_POSIX_SOURCE (or its equivalent) may be specified | |
+# if your compiler supports posix-compatible compilation | |
+include ../config.mk | |
+ | |
+OS=-DIRIX5 | |
+ | |
+# add -Iincludedir for any include directories that need to be searched | |
+# for posix header files (for UMIPS, add -I/usr/include/posix) | |
+INCS=-I../include -I$(FREETYPEINC) | |
+ | |
+# add name of library orderer - use ":" if none exists | |
+RANLIB=: | |
+ | |
+# add name of library | |
+AR=ar | |
+ | |
+CFLAGS=-c $(OS) $(INCS) -D_LIBXG_EXTENSION | |
+ | |
+LIB=libframe.a | |
+CC=cc | |
+ | |
+OBJ=frbox.o frdelete.o frdraw.o frinit.o frinsert.o frptofchar.o\ | |
+ frselect.o frstr.o frutil.o misc.o | |
+ | |
+all: $(LIB) | |
+ | |
+$(LIB): $(OBJ) | |
+ $(AR) rv $(LIB) $(OBJ) | |
+ $(RANLIB) $(LIB) | |
+ | |
+clean: | |
+ rm -f *.o *.a | |
+ | |
+nuke: clean | |
+ rm -f $(LIB) | |
+ | |
+install: $(LIB) | |
+ | |
+$(OBJ): ../include/u.h ../include/libc.h ../include/frame.h | |
diff --git a/libframe/frbox.c b/libframe/frbox.c | |
@@ -0,0 +1,156 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+#define SLOP 25 | |
+ | |
+void | |
+_fraddbox(Frame *f, int bn, int n) /* add n boxes after bn, shift the r… | |
+ * box[bn+n]==box[bn] */ | |
+{ | |
+ int i; | |
+ | |
+ if(bn > f->nbox) | |
+ berror("_fraddbox"); | |
+ if(f->nbox+n > f->nalloc) | |
+ _frgrowbox(f, n+SLOP); | |
+ for(i=f->nbox; --i>=bn; ) | |
+ f->box[i+n] = f->box[i]; | |
+ f->nbox+=n; | |
+} | |
+ | |
+void | |
+_frclosebox(Frame *f, int n0, int n1) /* inclusive */ | |
+{ | |
+ int i; | |
+ | |
+ if(n0>=f->nbox || n1>=f->nbox || n1<n0) | |
+ berror("_frclosebox"); | |
+ n1++; | |
+ for(i=n1; i<f->nbox; i++) | |
+ f->box[i-(n1-n0)] = f->box[i]; | |
+ f->nbox -= n1-n0; | |
+} | |
+ | |
+void | |
+_frdelbox(Frame *f, int n0, int n1) /* inclusive */ | |
+{ | |
+ if(n0>=f->nbox || n1>=f->nbox || n1<n0) | |
+ berror("_frdelbox"); | |
+ _frfreebox(f, n0, n1); | |
+ _frclosebox(f, n0, n1); | |
+} | |
+ | |
+void | |
+_frfreebox(Frame *f, int n0, int n1) /* inclusive */ | |
+{ | |
+ int i; | |
+ | |
+ if(n1<n0) | |
+ return; | |
+ if(n0>=f->nbox || n1>=f->nbox) | |
+ berror("_frfreebox"); | |
+ n1++; | |
+ for(i=n0; i<n1; i++) | |
+ if(f->box[i].nrune >= 0) | |
+ free(f->box[i].a.ptr); | |
+} | |
+ | |
+void | |
+_frgrowbox(Frame *f, int delta) | |
+{ | |
+ f->nalloc += delta; | |
+ f->box = realloc(f->box, f->nalloc*sizeof(Frbox)); | |
+ if(f->box == 0) | |
+ berror("_frgrowbox"); | |
+} | |
+ | |
+static | |
+void | |
+dupbox(Frame *f, int bn) | |
+{ | |
+ uchar *p; | |
+ | |
+ if(f->box[bn].nrune < 0) | |
+ berror("dupbox"); | |
+ _fraddbox(f, bn, 1); | |
+ if(f->box[bn].nrune >= 0){ | |
+ p = _frallocstr(NBYTE(&f->box[bn])+1); | |
+ strcpy((char*)p, (char*)f->box[bn].a.ptr); | |
+ f->box[bn+1].a.ptr = p; | |
+ } | |
+} | |
+ | |
+static | |
+uchar* | |
+runeindex(uchar *p, int n) | |
+{ | |
+ int i, w; | |
+ Rune rune; | |
+ | |
+ for(i=0; i<n; i++,p+=w) | |
+ if(*p < Runeself) | |
+ w = 1; | |
+ else{ | |
+ w = chartorune(&rune, (char*)p); | |
+ USED(rune); | |
+ } | |
+ return p; | |
+} | |
+ | |
+static | |
+void | |
+truncatebox(Frame *f, Frbox *b, int n) /* drop last n chars; no allocat… | |
+{ | |
+ if(b->nrune<0 || b->nrune<n) | |
+ berror("truncatebox"); | |
+ b->nrune -= n; | |
+ runeindex(b->a.ptr, b->nrune)[0] = 0; | |
+ b->wid = strwidth(f->font, (char *)b->a.ptr); | |
+} | |
+ | |
+static | |
+void | |
+chopbox(Frame *f, Frbox *b, int n) /* drop first n chars; no allocation… | |
+{ | |
+ if(b->nrune<0 || b->nrune<n) | |
+ berror("chopbox"); | |
+ strcpy((char*)b->a.ptr, (char*)runeindex(b->a.ptr, n)); | |
+ b->nrune -= n; | |
+ b->wid = strwidth(f->font, (char *)b->a.ptr); | |
+} | |
+ | |
+void | |
+_frsplitbox(Frame *f, int bn, int n) | |
+{ | |
+ dupbox(f, bn); | |
+ truncatebox(f, &f->box[bn], f->box[bn].nrune-n); | |
+ chopbox(f, &f->box[bn+1], n); | |
+} | |
+ | |
+void | |
+_frmergebox(Frame *f, int bn) /* merge bn and bn+1 */ | |
+{ | |
+ Frbox *b; | |
+ | |
+ b = &f->box[bn]; | |
+ _frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1); | |
+ strcpy((char*)runeindex(b[0].a.ptr, b[0].nrune), (char*)b[1].a.ptr); | |
+ b[0].wid += b[1].wid; | |
+ b[0].nrune += b[1].nrune; | |
+ _frdelbox(f, bn+1, bn+1); | |
+} | |
+ | |
+int | |
+_frfindbox(Frame *f, int bn, ulong p, ulong q) /* find box containing q… | |
+{ | |
+ Frbox *b; | |
+ | |
+ for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++) | |
+ p += NRUNE(b); | |
+ if(p != q) | |
+ _frsplitbox(f, bn++, (int)(q-p)); | |
+ return bn; | |
+} | |
diff --git a/libframe/frdelete.c b/libframe/frdelete.c | |
@@ -0,0 +1,104 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+int | |
+frdelete(Frame *f, ulong p0, ulong p1) | |
+{ | |
+ Point pt0, pt1, ppt0; | |
+ Frbox *b; | |
+ int n0, n1, n; | |
+ Rectangle r; | |
+ int nn0; | |
+ | |
+ if(p0>=f->nchars || p0==p1 || f->b==0) | |
+ return 0; | |
+ if(p1 > f->nchars) | |
+ p1 = f->nchars; | |
+ n0 = _frfindbox(f, 0, (unsigned long)0, p0); | |
+ n1 = _frfindbox(f, n0, p0, p1); | |
+ pt0 = _frptofcharnb(f, p0, n0); | |
+ pt1 = frptofchar(f, p1); | |
+ if(f->p0!=p0 || f->p1!=p1) /* likely they ARE equal */ | |
+ frselectp(f, F&~D); /* can do better some day */ | |
+ frselectf(f, pt0, pt1, 0); | |
+ if(n0 == f->nbox) | |
+ berror("off end in frdelete"); | |
+ nn0 = n0; | |
+ ppt0 = pt0; | |
+ _frfreebox(f, n0, n1-1); | |
+ f->modified = 1; | |
+ | |
+ /* | |
+ * Invariants: | |
+ * pt0 points to beginning, pt1 points to end | |
+ * n0 is box containing beginning of stuff being deleted | |
+ * n1, b are box containing beginning of stuff to be kept after delet… | |
+ * region between pt0 and pt1 is clear | |
+ */ | |
+ b = &f->box[n1]; | |
+ while(pt1.x!=pt0.x && n1<f->nbox){ | |
+ _frcklinewrap0(f, &pt0, b); | |
+ _frcklinewrap(f, &pt1, b); | |
+ if(b->nrune > 0){ | |
+ n = _frcanfit(f, pt0, b); | |
+ if(n==0) | |
+ berror("_frcanfit==0"); | |
+ if(n != b->nrune){ | |
+ _frsplitbox(f, n1, n); | |
+ b = &f->box[n1]; | |
+ } | |
+ r.min = pt1; | |
+ r.max = pt1; | |
+ r.max.x += b->wid; | |
+ r.max.y += f->font->height; | |
+ bitblt(f->b, pt0, f->b, r, S); | |
+ if(pt0.y == pt1.y) | |
+ r.min.x = r.max.x-(pt1.x-pt0.x); | |
+ bitblt(f->b, r.min, f->b, r, 0); | |
+ } | |
+ _fradvance(f, &pt1, b); | |
+ pt0.x += _frnewwid(f, pt0, b); | |
+ f->box[n0++] = f->box[n1++]; | |
+ b++; | |
+ } | |
+ if(pt1.y != pt0.y){ | |
+ Point pt2; | |
+ | |
+ pt2 = _frptofcharptb(f, 32767, pt1, n1); | |
+ if(pt2.y > f->r.max.y) | |
+ berror("frptofchar in frdelete"); | |
+ if(n1 < f->nbox){ | |
+ int q0, q1, q2; | |
+ | |
+ q0 = pt0.y+f->font->height; | |
+ q1 = pt1.y+f->font->height; | |
+ q2 = pt2.y+f->font->height; | |
+ bitblt(f->b, pt0, f->b, Rect(pt1.x, pt1.y, f->r.max.x,… | |
+ bitblt(f->b, Pt(f->r.min.x, q0), f->b, Rect(f->r.min.x… | |
+ frselectf(f, Pt(pt2.x, pt2.y-(pt1.y-pt0.y)), pt2, 0); | |
+ }else | |
+ frselectf(f, pt0, pt2, 0); | |
+ } | |
+ _frclosebox(f, n0, n1-1); | |
+ if(nn0>0 && f->box[nn0-1].nrune>=0 && ppt0.x-f->box[nn0-1].wid>=(int)f… | |
+ --nn0; | |
+ ppt0.x -= f->box[nn0].wid; | |
+ } | |
+ _frclean(f, ppt0, nn0, n0<f->nbox-1? n0+1 : n0); | |
+ if(f->p1 > p1) | |
+ f->p1 -= p1-p0; | |
+ else if(f->p1 > p0) | |
+ f->p1 = p0; | |
+ if(f->p0 > p1) | |
+ f->p0 -= p1-p0; | |
+ else if(f->p0 > p0) | |
+ f->p0 = p0; | |
+ frselectp(f, F&~D); | |
+ f->nchars -= p1-p0; | |
+ pt0 = frptofchar(f, f->nchars); | |
+ n = f->nlines; | |
+ f->nlines = (pt0.y-f->r.min.y)/f->font->height+(pt0.x>f->left); | |
+ return n - f->nlines; | |
+} | |
diff --git a/libframe/frdraw.c b/libframe/frdraw.c | |
@@ -0,0 +1,59 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+void | |
+_frredraw(Frame *f, Point pt) | |
+{ | |
+ Frbox *b; | |
+ int nb; | |
+ for(nb=0,b=f->box; nb<f->nbox; nb++, b++){ | |
+ _frcklinewrap(f, &pt, b); | |
+ if(b->nrune >= 0) | |
+ string(f->b, pt, f->font, (char *)b->a.ptr, S^D); | |
+ pt.x += b->wid; | |
+ } | |
+} | |
+ | |
+Point | |
+_frdraw(Frame *f, Point pt) | |
+{ | |
+ Frbox *b; | |
+ int nb, n; | |
+ | |
+ for(b=f->box,nb=0; nb<f->nbox; nb++, b++){ | |
+ _frcklinewrap0(f, &pt, b); | |
+ if(pt.y == f->r.max.y){ | |
+ f->nchars -= _frstrlen(f, nb); | |
+ _frdelbox(f, nb, f->nbox-1); | |
+ break; | |
+ } | |
+ if(b->nrune > 0){ | |
+ n = _frcanfit(f, pt, b); | |
+ if(n == 0) | |
+ berror("draw: _frcanfit==0"); | |
+ if(n != b->nrune){ | |
+ _frsplitbox(f, nb, n); | |
+ b = &f->box[nb]; | |
+ } | |
+ pt.x += b->wid; | |
+ }else{ | |
+ if(b->a.b.bc == '\n') | |
+ pt.x = f->left, pt.y+=f->font->height; | |
+ else | |
+ pt.x += _frnewwid(f, pt, b); | |
+ } | |
+ } | |
+ return pt; | |
+} | |
+int | |
+_frstrlen(Frame *f, int nb) | |
+{ | |
+ int n; | |
+ | |
+ for(n=0; nb<f->nbox; nb++) | |
+ n += NRUNE(&f->box[nb]); | |
+ return n; | |
+} | |
diff --git a/libframe/frinit.c b/libframe/frinit.c | |
@@ -0,0 +1,42 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+void | |
+frinit(Frame *f, Rectangle r, XftFont *ft, Bitmap *b) | |
+{ | |
+ f->font = ft; | |
+ f->maxtab = 8*charwidth(ft, '0'); | |
+ f->nbox = 0; | |
+ f->nalloc = 0; | |
+ f->nchars = 0; | |
+ f->nlines = 0; | |
+ f->p0 = 0; | |
+ f->p1 = 0; | |
+ f->box = 0; | |
+ f->lastlinefull = 0; | |
+ frsetrects(f, r, b); | |
+} | |
+ | |
+void | |
+frsetrects(Frame *f, Rectangle r, Bitmap *b) | |
+{ | |
+ f->b = b; | |
+ f->entire = r; | |
+ f->r = r; | |
+ f->r.max.y -= (r.max.y-r.min.y)%f->font->height; | |
+ f->left = r.min.x+1; | |
+ f->maxlines = (r.max.y-r.min.y)/f->font->height; | |
+} | |
+ | |
+void | |
+frclear(Frame *f) | |
+{ | |
+ if(f->nbox) | |
+ _frdelbox(f, 0, f->nbox-1); | |
+ if(f->box) | |
+ free(f->box); | |
+ f->box = 0; | |
+} | |
diff --git a/libframe/frinsert.c b/libframe/frinsert.c | |
@@ -0,0 +1,247 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+#define DELTA 25 | |
+#define TMPSIZE 256 | |
+static Frame frame; | |
+ | |
+static | |
+Point | |
+bxscan(Frame *f, Rune *sp, Rune *ep, Point *ppt) | |
+{ | |
+ int w, c, nb, delta, nl, nr, rw; | |
+ Frbox *b; | |
+ char *s, tmp[TMPSIZE+3]; /* +3 for rune overflow */ | |
+ uchar *p; | |
+ | |
+ frame.r = f->r; | |
+ frame.b = f->b; | |
+ frame.font = f->font; | |
+ frame.maxtab = f->maxtab; | |
+ frame.left = f->left; | |
+ frame.nbox = 0; | |
+ frame.nchars = 0; | |
+ delta = DELTA; | |
+ nl = 0; | |
+ for(nb=0; sp<ep && nl<=f->maxlines; nb++,frame.nbox++){ | |
+ if(nb == frame.nalloc){ | |
+ _frgrowbox(&frame, delta); | |
+ if(delta < 10000) | |
+ delta *= 2; | |
+ } | |
+ b = &frame.box[nb]; | |
+ c = *sp; | |
+ if(c=='\t' || c=='\n'){ | |
+ b->a.b.bc = c; | |
+ b->wid = 5000; | |
+ b->a.b.minwid = (c=='\n')? 0 : charwidth(frame.font, '… | |
+ b->nrune = -1; | |
+ if(c=='\n') | |
+ nl++; | |
+ frame.nchars++; | |
+ sp++; | |
+ }else{ | |
+ s = tmp; | |
+ nr = 0; | |
+ w = 0; | |
+ while(sp < ep){ | |
+ c = *sp; | |
+ if(c=='\t' || c=='\n') | |
+ break; | |
+ rw = runetochar(s, sp); | |
+ if(s+rw >= tmp+TMPSIZE) | |
+ break; | |
+ w += charwidth(frame.font, c); | |
+ sp++; | |
+ s += rw; | |
+ nr++; | |
+ } | |
+ *s++ = 0; | |
+ p = _frallocstr(s-tmp); | |
+ b = &frame.box[nb]; | |
+ b->a.ptr = p; | |
+ memmove(p, tmp, s-tmp); | |
+ b->wid = w; | |
+ b->nrune = nr; | |
+ frame.nchars += nr; | |
+ } | |
+ } | |
+ _frcklinewrap0(f, ppt, &frame.box[0]); | |
+ return _frdraw(&frame, *ppt); | |
+} | |
+ | |
+static | |
+void | |
+chopframe(Frame *f, Point pt, ulong p, int bn) | |
+{ | |
+ Frbox *b; | |
+ | |
+ for(b = &f->box[bn]; ; b++){ | |
+ if(b >= &f->box[f->nbox]) | |
+ berror("endofframe"); | |
+ _frcklinewrap(f, &pt, b); | |
+ if(pt.y >= f->r.max.y) | |
+ break; | |
+ p += NRUNE(b); | |
+ _fradvance(f, &pt, b); | |
+ } | |
+ f->nchars = p; | |
+ f->nlines = f->maxlines; | |
+ if(b<&f->box[f->nbox]) /* BUG */ | |
+ _frdelbox(f, (int)(b-f->box), f->nbox-1); | |
+} | |
+ | |
+void | |
+frinsert(Frame *f, Rune *sp, Rune *ep, ulong p0) | |
+{ | |
+ Point pt0, pt1, ppt0, ppt1, pt; | |
+ Frbox *b; | |
+ int n, n0, nn0, y; | |
+ Rectangle r; | |
+ static struct{ | |
+ Point pt0, pt1; | |
+ }*pts; | |
+ static int nalloc=0; | |
+ int npts; | |
+ | |
+ if(p0>f->nchars || sp==ep || f->b==0) | |
+ return; | |
+ n0 = _frfindbox(f, 0, 0, p0); | |
+ nn0 = n0; | |
+ pt0 = _frptofcharnb(f, p0, n0); | |
+ ppt0 = pt0; | |
+ pt1 = bxscan(f, sp, ep, &ppt0); | |
+ ppt1 = pt1; | |
+ if(n0 < f->nbox){ | |
+ _frcklinewrap(f, &pt0, b = &f->box[n0]); /* for frselec… | |
+ _frcklinewrap0(f, &ppt1, b); | |
+ } | |
+ f->modified = 1; | |
+ /* | |
+ * ppt0 and ppt1 are start and end of insertion as they will appear wh… | |
+ * insertion is complete. pt0 is current location of insertion position | |
+ * (p0); pt1 is terminal point (without line wrap) of insertion. | |
+ */ | |
+ if(p0==f->p0 && p0==f->p1) /* quite likely */ | |
+ frselectf(f, pt0, pt0, F&~D); | |
+ else | |
+ frselectp(f, F&~D); | |
+ /* | |
+ * Find point where old and new x's line up | |
+ * Invariants: | |
+ * pt0 is where the next box (b, n0) is now | |
+ * pt1 is where it will be after then insertion | |
+ * If pt1 goes off the rectangle, we can toss everything from there on | |
+ */ | |
+ for(b = &f->box[n0],npts=0; | |
+ pt1.x!=pt0.x && pt1.y!=f->r.max.y && n0<f->nbox; b++,n0++,npts++){ | |
+ _frcklinewrap(f, &pt0, b); | |
+ _frcklinewrap0(f, &pt1, b); | |
+ if(b->nrune > 0){ | |
+ n = _frcanfit(f, pt1, b); | |
+ if(n == 0) | |
+ berror("_frcanfit==0"); | |
+ if(n != b->nrune){ | |
+ _frsplitbox(f, n0, n); | |
+ b = &f->box[n0]; | |
+ } | |
+ } | |
+ if(npts == nalloc){ | |
+ pts = realloc(pts, (npts+DELTA)*sizeof(pts[0])); | |
+ nalloc += DELTA; | |
+ b = &f->box[n0]; | |
+ } | |
+ pts[npts].pt0 = pt0; | |
+ pts[npts].pt1 = pt1; | |
+ /* has a text box overflowed off the frame? */ | |
+ if(pt1.y == f->r.max.y) | |
+ break; | |
+ _fradvance(f, &pt0, b); | |
+ pt1.x += _frnewwid(f, pt1, b); | |
+ } | |
+ if(pt1.y > f->r.max.y) | |
+ berror("frinsert pt1 too far"); | |
+ if(pt1.y==f->r.max.y && n0<f->nbox){ | |
+ f->nchars -= _frstrlen(f, n0); | |
+ _frdelbox(f, n0, f->nbox-1); | |
+ } | |
+ if(n0 == f->nbox) | |
+ f->nlines = (pt1.y-f->r.min.y)/f->font->height+(pt1.x>f->left); | |
+ else if(pt1.y!=pt0.y){ | |
+ int q0, q1; | |
+ | |
+ y = f->r.max.y; | |
+ q0 = pt0.y+f->font->height; | |
+ q1 = pt1.y+f->font->height; | |
+ f->nlines += (q1-q0)/f->font->height; | |
+ if(f->nlines > f->maxlines) | |
+ chopframe(f, ppt1, p0, nn0); | |
+ if(pt1.y < y){ | |
+ r = f->r; | |
+ r.min.y = q0; | |
+ r.max.y = y-(q1-q0); | |
+ if(q1 < y) | |
+ bitblt(f->b, Pt(f->r.min.x, q1), f->b, r, S); | |
+ r.min = pt0; | |
+ r.max.y = q0; | |
+ bitblt(f->b, pt1, f->b, r, S); | |
+ } | |
+ } | |
+ /* | |
+ * Move the old stuff down to make room. The loop will move the stuff | |
+ * between the insertion and the point where the x's lined up. | |
+ * The bitblts above moved everything down after the point they lined … | |
+ */ | |
+ for((y=pt1.y==f->r.max.y?pt1.y:0),b = &f->box[n0-1]; --npts>=0; --b){ | |
+ pt = pts[npts].pt1; | |
+ if(b->nrune > 0){ | |
+ r.min = pts[npts].pt0; | |
+ r.max = r.min; | |
+ r.max.x += b->wid; | |
+ r.max.y += f->font->height; | |
+ bitblt(f->b, pt, f->b, r, S); | |
+ if(pt.y < y){ /* clear bit hanging off right */ | |
+ r.min = pt; | |
+ r.max = pt; | |
+ r.min.x += b->wid; | |
+ r.max.x = f->r.max.x; | |
+ r.max.y += f->font->height; | |
+ bitblt(f->b, r.min, f->b, r, 0); | |
+ } | |
+ y = pt.y; | |
+ }else{ | |
+ r.min = pt; | |
+ r.max = pt; | |
+ r.max.x += b->wid; | |
+ r.max.y += f->font->height; | |
+ if(r.max.x >= f->r.max.x) | |
+ r.max.x = f->r.max.x; | |
+ bitblt(f->b, r.min, f->b, r, 0); | |
+ y = (pt.x == f->left)? pt.y : 0; | |
+ } | |
+ } | |
+ frselectf(f, ppt0, ppt1, 0); | |
+ _frredraw(&frame, ppt0); | |
+ _fraddbox(f, nn0, frame.nbox); | |
+ for(n=0; n<frame.nbox; n++) | |
+ f->box[nn0+n] = frame.box[n]; | |
+ if(nn0>0 && f->box[nn0-1].nrune>=0 && ppt0.x-f->box[nn0-1].wid>=(int)f… | |
+ --nn0; | |
+ ppt0.x -= f->box[nn0].wid; | |
+ } | |
+ n0 += frame.nbox; | |
+ _frclean(f, ppt0, nn0, n0<f->nbox-1? n0+1 : n0); | |
+ f->nchars += frame.nchars; | |
+ if(f->p0 >= p0) | |
+ f->p0 += frame.nchars; | |
+ if(f->p0 > f->nchars) | |
+ f->p0 = f->nchars; | |
+ if(f->p1 >= p0) | |
+ f->p1 += frame.nchars; | |
+ if(f->p1 > f->nchars) | |
+ f->p1 = f->nchars; | |
+ frselectp(f, F&~D); | |
+} | |
diff --git a/libframe/frptofchar.c b/libframe/frptofchar.c | |
@@ -0,0 +1,116 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+Point | |
+_frptofcharptb(Frame *f, ulong p, Point pt, int bn) | |
+{ | |
+ uchar *s; | |
+ Frbox *b; | |
+ int w, l; | |
+ Rune r; | |
+ | |
+ for(b = &f->box[bn]; bn<f->nbox; bn++,b++){ | |
+ _frcklinewrap(f, &pt, b); | |
+ if(p < (l=NRUNE(b))){ | |
+ if(b->nrune > 0) | |
+ for(s=b->a.ptr; p>0; s+=w, p--){ | |
+ if((r = *s) < Runeself) | |
+ w = 1; | |
+ else | |
+ w = chartorune(&r, (char*)s); | |
+ pt.x += charwidth(f->font, r); | |
+ if(r==0 || pt.x>f->r.max.x) | |
+ berror("frptofchar"); | |
+ } | |
+ break; | |
+ } | |
+ p -= l; | |
+ _fradvance(f, &pt, b); | |
+ } | |
+ return pt; | |
+} | |
+ | |
+Point | |
+frptofchar(Frame *f, ulong p) | |
+{ | |
+ return _frptofcharptb(f, p, Pt(f->left, f->r.min.y), 0); | |
+} | |
+ | |
+Point | |
+_frptofcharnb(Frame *f, ulong p, int nb) /* doesn't do final _fradvance… | |
+{ | |
+ Point pt; | |
+ int nbox; | |
+ | |
+ nbox = f->nbox; | |
+ f->nbox = nb; | |
+ pt = _frptofcharptb(f, p, Pt(f->left, f->r.min.y), 0); | |
+ f->nbox = nbox; | |
+ return pt; | |
+} | |
+ | |
+static | |
+Point | |
+_frgrid(Frame *f, Point p) | |
+{ | |
+ p.y -= f->r.min.y; | |
+ p.y -= p.y%f->font->height; | |
+ p.y += f->r.min.y; | |
+ if(p.x > f->r.max.x) | |
+ p.x = f->r.max.x; | |
+ return p; | |
+} | |
+ | |
+ulong | |
+frcharofpt(Frame *f, Point pt) | |
+{ | |
+ Point qt; | |
+ int w, bn; | |
+ uchar *s; | |
+ Frbox *b; | |
+ ulong p; | |
+ Rune r; | |
+ | |
+ pt = _frgrid(f, pt); | |
+ qt.x = f->left; | |
+ qt.y = f->r.min.y; | |
+ for(b=f->box,bn=0,p=0; bn<f->nbox && qt.y<pt.y; bn++,b++){ | |
+ _frcklinewrap(f, &qt, b); | |
+ if(qt.y >= pt.y) | |
+ break; | |
+ _fradvance(f, &qt, b); | |
+ p += NRUNE(b); | |
+ } | |
+ for(; bn<f->nbox && qt.x<=pt.x; bn++,b++){ | |
+ _frcklinewrap(f, &qt, b); | |
+ if(qt.y > pt.y) | |
+ break; | |
+ if(qt.x+b->wid > pt.x){ | |
+ if(b->nrune < 0) | |
+ _fradvance(f, &qt, b); | |
+ else{ | |
+ s = b->a.ptr; | |
+ for(;;){ | |
+ if((r = *s) < Runeself) | |
+ w = 1; | |
+ else | |
+ w = chartorune(&r, (char*)s); | |
+ if(r == 0) | |
+ berror("end of string in frcha… | |
+ s += w; | |
+ qt.x += charwidth(f->font, r); | |
+ if(qt.x > pt.x) | |
+ break; | |
+ p++; | |
+ } | |
+ } | |
+ }else{ | |
+ p += NRUNE(b); | |
+ _fradvance(f, &qt, b); | |
+ } | |
+ } | |
+ return p; | |
+} | |
diff --git a/libframe/frselect.c b/libframe/frselect.c | |
@@ -0,0 +1,94 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+void | |
+frselect(Frame *f, Mouse *m) /* when called, button 1 is down */ | |
+{ | |
+ ulong p0, p1, q; | |
+ Point mp, pt0, pt1, qt; | |
+ | |
+ mp = m->xy; | |
+ | |
+ Again: | |
+ f->modified = 0; | |
+ frselectp(f, F&~D); | |
+ p0 = p1 = frcharofpt(f, mp); | |
+ pt0 = frptofchar(f, p0); | |
+ pt1 = frptofchar(f, p1); | |
+ frselectf(f, pt0, pt1, F&~D); | |
+ do{ | |
+ if(f->modified) /* special hack so 8½ can frselect in … | |
+ goto Again; | |
+ q = frcharofpt(f, m->xy); | |
+ if(p1 != q){ | |
+ if(p0 == p1) | |
+ frselectf(f, pt0, pt1, F&~D); | |
+ qt = frptofchar(f, q); | |
+ if(p1 < q) | |
+ frselectf(f, pt1, qt, F&~D); | |
+ else | |
+ frselectf(f, qt, pt1, F&~D); | |
+ p1 = q; | |
+ pt1 = qt; | |
+ if(p0 == p1) | |
+ frselectf(f, pt0, pt1, F&~D); | |
+ } | |
+ f->modified = 0; | |
+ if(p0 < p1) | |
+ f->p0 = p0, f->p1 = p1; | |
+ else | |
+ f->p0 = p1, f->p1 = p0; | |
+ frgetmouse(); | |
+ }while(m->buttons & 1); | |
+} | |
+/* it is assumed p0<=p1 and both were generated by frptofchar() */ | |
+void | |
+frselectf(Frame *f, Point p0, Point p1, Fcode c) | |
+{ | |
+ int n; | |
+ Point q0, q1; | |
+ | |
+ if(p0.x == f->left) | |
+ p0.x = f->r.min.x; | |
+ if(p1.x == f->left) | |
+ p1.x = f->r.min.x; | |
+ q0 = p0; | |
+ q1 = p1; | |
+ q0.y += f->font->height; | |
+ q1.y += f->font->height; | |
+ n = (p1.y-p0.y)/f->font->height; | |
+ if(f->b == 0) | |
+ berror("frselectf b==0"); | |
+ if(p0.y == f->r.max.y) | |
+ return; | |
+ if(n == 0){ | |
+ if(p0.x == p1.x) | |
+ if(p0.x == f->r.min.x) | |
+ q1.x++; | |
+ else | |
+ p0.x--; | |
+ bitblt(f->b, p0, f->b, Rpt(p0, q1), c); | |
+ }else{ | |
+ if(p0.x >= f->r.max.x) | |
+ p0.x = f->r.max.x-1; | |
+ bitblt(f->b, p0, f->b, Rect(p0.x, p0.y, f->r.max.x, q0.y), c); | |
+ if(n > 1) | |
+ bitblt(f->b, Pt(f->r.min.x, q0.y), | |
+ f->b, Rect(f->r.min.x, q0.y, f->r.max.x, p1.y)… | |
+ bitblt(f->b, Pt(f->r.min.x, p1.y), | |
+ f->b, Rect(f->r.min.x, p1.y, q1.x, q1.y), c); | |
+ } | |
+} | |
+ | |
+void | |
+frselectp(Frame *f, Fcode c) | |
+{ | |
+ Point pt0, pt1; | |
+ | |
+ pt0 = frptofchar(f, f->p0); | |
+ pt1 = (f->p0==f->p1)? pt0 : frptofchar(f, f->p1); | |
+ frselectf(f, pt0, pt1, c); | |
+} | |
diff --git a/libframe/frstr.c b/libframe/frstr.c | |
@@ -0,0 +1,41 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+/* | |
+ * The code here and elsewhere requires that strings not be gcalloc()ed | |
+ */ | |
+ | |
+#define CHUNK 16 | |
+#define ROUNDUP(n) ((n+CHUNK)&~(CHUNK-1)) | |
+ | |
+uchar * | |
+_frallocstr(unsigned n) | |
+{ | |
+ uchar *p; | |
+ | |
+ p = malloc(ROUNDUP(n)); | |
+ if(p == 0) | |
+ berror("out of memory"); | |
+ return p; | |
+} | |
+ | |
+void | |
+_frinsure(Frame *f, int bn, unsigned n) | |
+{ | |
+ Frbox *b; | |
+ uchar *p; | |
+ | |
+ b = &f->box[bn]; | |
+ if(b->nrune < 0) | |
+ berror("_frinsure"); | |
+ if(ROUNDUP(b->nrune) > n) /* > guarantees room for terminal NUL… | |
+ return; | |
+ p = _frallocstr(n); | |
+ b = &f->box[bn]; | |
+ memmove(p, b->a.ptr, NBYTE(b)+1); | |
+ free(b->a.ptr); | |
+ b->a.ptr = p; | |
+} | |
diff --git a/libframe/frutil.c b/libframe/frutil.c | |
@@ -0,0 +1,107 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+ | |
+int | |
+_frcanfit(Frame *f, Point pt, Frbox *b) | |
+{ | |
+ int left, w, nr; | |
+ uchar *p; | |
+ Rune r; | |
+ | |
+ left = f->r.max.x-pt.x; | |
+ if(b->nrune < 0) | |
+ return b->a.b.minwid <= left; | |
+ if(left >= b->wid) | |
+ return b->nrune; | |
+ for(nr=0,p=b->a.ptr; *p; p+=w,nr++){ | |
+ r = *p; | |
+ if(r < Runeself) | |
+ w = 1; | |
+ else | |
+ w = chartorune(&r, (char*)p); | |
+ left -= charwidth(f->font, r); | |
+ if(left < 0) | |
+ return nr; | |
+ } | |
+ berror("_frcanfit can't"); | |
+ return 0; | |
+} | |
+ | |
+void | |
+_frcklinewrap(Frame *f, Point *p, Frbox *b) | |
+{ | |
+ if((b->nrune<0? b->a.b.minwid : b->wid) > f->r.max.x-p->x){ | |
+ p->x = f->left; | |
+ p->y += f->font->height; | |
+ } | |
+} | |
+ | |
+void | |
+_frcklinewrap0(Frame *f, Point *p, Frbox *b) | |
+{ | |
+ if(_frcanfit(f, *p, b) == 0){ | |
+ p->x = f->left; | |
+ p->y += f->font->height; | |
+ } | |
+} | |
+ | |
+void | |
+_fradvance(Frame *f, Point *p, Frbox *b) | |
+{ | |
+ if(b->nrune<0 && b->a.b.bc=='\n'){ | |
+ p->x = f->left; | |
+ p->y += f->font->height; | |
+ }else | |
+ p->x += b->wid; | |
+} | |
+ | |
+int | |
+_frnewwid(Frame *f, Point pt, Frbox *b) | |
+{ | |
+ int c, x; | |
+ | |
+ c = f->r.max.x; | |
+ x = pt.x; | |
+ if(b->nrune >= 0) | |
+ return b->wid; | |
+ if(b->a.b.bc == '\t'){ | |
+ if(x+b->a.b.minwid > c) | |
+ x = pt.x = f->left; | |
+ x += f->maxtab; | |
+ x -= (x-f->left)%f->maxtab; | |
+ if(x-pt.x<b->a.b.minwid || x>c) | |
+ x = pt.x+b->a.b.minwid; | |
+ b->wid = x-pt.x; | |
+ } | |
+ return b->wid; | |
+} | |
+ | |
+void | |
+_frclean(Frame *f, Point pt, int n0, int n1) /* look for mergeable boxe… | |
+{ | |
+ Frbox *b; | |
+ int nb, c; | |
+ | |
+ c = f->r.max.x; | |
+ for(nb=n0; nb<n1-1; nb++){ | |
+ b = &f->box[nb]; | |
+ _frcklinewrap(f, &pt, b); | |
+ while(b[0].nrune>=0 && nb<n1-1 && b[1].nrune>=0 && pt.x+b[0].w… | |
+ _frmergebox(f, nb); | |
+ n1--; | |
+ b = &f->box[nb]; | |
+ } | |
+ _fradvance(f, &pt, &f->box[nb]); | |
+ } | |
+ for(; nb<f->nbox; nb++){ | |
+ b = &f->box[nb]; | |
+ _frcklinewrap(f, &pt, b); | |
+ _fradvance(f, &pt, &f->box[nb]); | |
+ } | |
+ f->lastlinefull = 0; | |
+ if(pt.y >= f->r.max.y) | |
+ f->lastlinefull = 1; | |
+} | |
diff --git a/libframe/misc.c b/libframe/misc.c | |
@@ -0,0 +1,93 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <pwd.h> | |
+#ifdef NEEDVARARG | |
+#include <varargs.h> | |
+#else | |
+#include <stdarg.h> | |
+#endif | |
+#include <errno.h> | |
+ | |
+void | |
+fprint(int fd, char *z, ...) | |
+{ | |
+ va_list args; | |
+ char buf[2048]; /* pick reasonable blocksize */ | |
+ | |
+ va_start(args, z); | |
+ vsprintf(buf, z, args); | |
+ write(fd, buf, strlen(buf)); | |
+ va_end(args); | |
+} | |
+ | |
+int errstr(char *buf) | |
+{ | |
+ | |
+ strncpy(buf, strerror(errno), ERRLEN); | |
+ return 1; | |
+} | |
+ | |
+char* | |
+getuser(void) | |
+{ | |
+ struct passwd *p; | |
+ | |
+ static char *user = 0; | |
+ | |
+ if (!user) { | |
+ p = getpwuid(getuid()); | |
+ if (p && p->pw_name) { | |
+ user = malloc(strlen(p->pw_name)+1); | |
+ if (user) | |
+ strcpy(user, p->pw_name); | |
+ } | |
+ } | |
+ if(!user) | |
+ user = "unknown"; | |
+ return user; | |
+} | |
+ | |
+#ifdef NEEDSTRERROR | |
+char * | |
+strerror(int n) | |
+{ | |
+ extern char *sys_errlist[]; | |
+ return sys_errlist[n]; | |
+} | |
+#endif /* NEEDSTRERROR */ | |
+ | |
+#ifdef NEEDMEMMOVE | |
+/* | |
+ * memcpy is probably fast, but may not work with overlap | |
+ */ | |
+void* | |
+memmove(void *a1, const void *a2, size_t n) | |
+{ | |
+ char *s1; | |
+ const char *s2; | |
+ | |
+ s1 = a1; | |
+ s2 = a2; | |
+ if(s1 > s2) | |
+ goto back; | |
+ if(s1 + n <= s2) | |
+ return memcpy(a1, a2, n); | |
+ while(n > 0) { | |
+ *s1++ = *s2++; | |
+ n--; | |
+ } | |
+ return a1; | |
+ | |
+back: | |
+ s2 += n; | |
+ if(s2 <= s1) | |
+ return memcpy(a1, a2, n); | |
+ s1 += n; | |
+ while(n > 0) { | |
+ *--s1 = *--s2; | |
+ n--; | |
+ } | |
+ return a1; | |
+} | |
+#endif /* NEEDMEMMOVE */ | |
diff --git a/rsam/Makefile b/rsam/Makefile | |
@@ -0,0 +1,18 @@ | |
+# Copyright (C) 2013-2015 Rob King <[email protected] | |
+# This file may be redistributed and modified for any purpose. | |
+# No warranty is expressed or implied; use at your own risk. | |
+ | |
+include ../config.mk | |
+ | |
+LDFLAGS= | |
+CFLAGS=-DSAMBIN=\"$(BINDIR)/sam\" | |
+ | |
+all: rsam | |
+ | |
+rsam: rsam.o | |
+ | |
+clean: | |
+ rm -f *.o rsam | |
+ | |
+install: rsam | |
+ cp rsam $(BINDIR) | |
diff --git a/rsam/rsam.c b/rsam/rsam.c | |
@@ -0,0 +1,147 @@ | |
+/* Copyright 2013-2015 Rob King <[email protected]> | |
+ * This file may be freely redistributed in source or binary form with or with… | |
+ * No warranty is expressed or implied; use at your own risk. | |
+ */ | |
+ | |
+#define _POSIX_C_SOURCE 200112L | |
+#include <fcntl.h> | |
+#include <limits.h> | |
+#include <stdio.h> | |
+#include <stdlib.h> | |
+#include <string.h> | |
+#include <sys/select.h> | |
+#include <sys/stat.h> | |
+#include <sys/types.h> | |
+#include <unistd.h> | |
+ | |
+#define PARENT_READ readpipe[0] | |
+#define CHILD_WRITE readpipe[1] | |
+#define CHILD_READ writepipe[0] | |
+#define PARENT_WRITE writepipe[1] | |
+#define MAX(x, y) ((x) > (y) ? (x) : (y)) | |
+ | |
+char *fifopath = NULL; | |
+ | |
+void | |
+cleanup(void) | |
+{ | |
+ if (fifopath) | |
+ { | |
+ unlink(fifopath); | |
+ free(fifopath); | |
+ } | |
+} | |
+ | |
+int | |
+main(int argc, char **argv) | |
+{ | |
+ const char *home = getenv("HOME") ? getenv("HOME") : "/tmp"; | |
+ long pathmax = pathconf(home, _PC_PATH_MAX) != -1 ? pathco… | |
+ int writepipe[2] = {-1}; | |
+ int readpipe[2] = {-1}; | |
+ | |
+ fifopath = calloc(pathmax, sizeof(char)); | |
+ if (fifopath == NULL) | |
+ { | |
+ perror("fifopath"); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ if (pipe(writepipe) != 0 || pipe(readpipe) != 0) | |
+ { | |
+ perror("pipe"); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ snprintf(fifopath, pathmax, "%s/.sam.fifo", home); | |
+ unlink(fifopath); | |
+ if (mkfifo(fifopath, 0600) != 0) | |
+ { | |
+ perror("mkfifo"); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ fifopath = fifopath; | |
+ atexit(cleanup); | |
+ | |
+ int fifofd = open(fifopath, O_RDWR); | |
+ if (fifofd < 0) | |
+ { | |
+ perror("open"); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ pid_t child = fork(); | |
+ if (child == 0) | |
+ { | |
+ close(PARENT_WRITE); | |
+ close(PARENT_READ); | |
+ | |
+ dup2(CHILD_READ, STDIN_FILENO); close(CHILD_READ); | |
+ dup2(CHILD_WRITE, STDOUT_FILENO); close(CHILD_WRITE); | |
+ | |
+ execl(SAMBIN, "sam", "-R", NULL); | |
+ return EXIT_FAILURE; | |
+ } | |
+ else if (child < 0) | |
+ { | |
+ perror("fork"); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ close(CHILD_READ); | |
+ close(CHILD_WRITE); | |
+ | |
+ fd_set readfds; | |
+ fd_set writefds; | |
+ | |
+ FD_ZERO(&readfds); | |
+ FD_SET(STDIN_FILENO, &readfds); | |
+ FD_SET(fifofd, &readfds); | |
+ FD_SET(PARENT_READ, &readfds); | |
+ | |
+ while (select(MAX(STDIN_FILENO, MAX(PARENT_READ, fifofd)) + 1, &readfd… | |
+ { | |
+ ssize_t count = 0; | |
+ char buf[8192]; | |
+ | |
+ if (FD_ISSET(STDIN_FILENO, &readfds)) | |
+ { | |
+ count = read(STDIN_FILENO, buf, 8192); | |
+ if (count <= 0) | |
+ { | |
+ exit(EXIT_SUCCESS); | |
+ } | |
+ write(PARENT_WRITE, buf, count); | |
+ } | |
+ | |
+ if (FD_ISSET(fifofd, &readfds)) | |
+ { | |
+ memset(buf, 0, 256); | |
+ count = read(fifofd, buf, 253); | |
+ if (count <= 0) | |
+ { | |
+ exit(EXIT_SUCCESS); | |
+ } | |
+ write(STDOUT_FILENO, "\x19\xff\x00", 3); | |
+ write(STDOUT_FILENO, buf, 255); | |
+ } | |
+ | |
+ if (FD_ISSET(PARENT_READ, &readfds)) | |
+ { | |
+ count = read(PARENT_READ, buf, 8192); | |
+ if (count <= 0) | |
+ { | |
+ exit(EXIT_SUCCESS); | |
+ } | |
+ write(STDOUT_FILENO, buf, count); | |
+ } | |
+ | |
+ FD_ZERO(&readfds); | |
+ FD_SET(STDIN_FILENO, &readfds); | |
+ FD_SET(fifofd, &readfds); | |
+ FD_SET(PARENT_READ, &readfds); | |
+ } | |
+ | |
+ return EXIT_SUCCESS; | |
+} | |
diff --git a/sam/B.rc b/sam/B.rc | |
@@ -0,0 +1,51 @@ | |
+#!/bin/rc | |
+ | |
+files=() | |
+line='' | |
+ | |
+if (~ $#* 0) { | |
+ echo 'usage: B [-nnn] files...' >[1=2] | |
+ exit 1 | |
+} | |
+ | |
+dir=`{/bin/pwd} | |
+ | |
+if (~ $#USER 0) | |
+ USER=$LOGNAME | |
+pipe=/tmp/.sam.$USER | |
+ | |
+switch($DISPLAY) { | |
+ case *:[0-9]*.[0-9]* | |
+ pipe=$pipe.$DISPLAY | |
+ if (! test -r $pipe) | |
+ pipe=`{echo $pipe | sed 's/\.[0-9]*$//'} | |
+ case *:[0-9]* | |
+ pipe=$pipe.$DISPLAY | |
+ if (! test -r $pipe) | |
+ pipe=$pipe.0 | |
+ case "" | |
+ case * | |
+ pipe=$pipe.$DISPLAY | |
+} | |
+ | |
+if (! test -r $pipe) { | |
+ echo `{basename $0}^': No pipe "'$pipe'" to sam.' >[1=2] | |
+ exit 1 | |
+} | |
+ | |
+for (i) { | |
+ switch($i) { | |
+ case /* | |
+ files = ( $files $i ) | |
+ case -* | |
+ line = `{echo $i | sed 's/.//'} | |
+ case * | |
+ files = ( $files $dir/$i ) | |
+ } | |
+} | |
+ | |
+if (! ~ $#files 0) | |
+ echo B $files >> $pipe | |
+ | |
+if (! ~ $line '') | |
+ echo $line >> $pipe | |
diff --git a/sam/B.sh b/sam/B.sh | |
@@ -0,0 +1,56 @@ | |
+#!/bin/sh | |
+ | |
+files= | |
+line="none" | |
+ | |
+if [ $# = 0 ]; then | |
+ echo 'usage: B [-nnnn] files...' 1>&2 | |
+ exit 1 | |
+fi | |
+ | |
+dir=`/bin/pwd` | |
+if [ "$USER" = "" ]; then | |
+ USER=$LOGNAME | |
+fi | |
+pipe=/tmp/.sam.$USER | |
+ | |
+case "$DISPLAY" in | |
+ *:[0-9]*\.[0-9]*) | |
+ pipe=$pipe.$DISPLAY | |
+ if [ ! -r $pipe ]; then | |
+ pipe=`echo $pipe | sed 's/\.[0-9]*$//'` | |
+ fi | |
+ ;; | |
+ *:[0-9]*) | |
+ pipe=$pipe.$DISPLAY | |
+ if [ ! -r $pipe ]; then | |
+ pipe=$pipe.0 | |
+ fi | |
+ ;; | |
+ "") | |
+ ;; | |
+ *) pipe=$pipe.$DISPLAY | |
+ ;; | |
+esac | |
+if [ ! -r $pipe ]; then | |
+ echo `basename $0`": No pipe \""$pipe"\" to sam." 1>&2 | |
+ exit 1 | |
+fi | |
+ | |
+for i in $* | |
+do | |
+ case "$i" in | |
+ /*) files="$files $i" | |
+ ;; | |
+ -*) line=`echo $i | sed 's/.//'` | |
+ ;; | |
+ *) files="$files $dir/$i" | |
+ ;; | |
+ esac | |
+done | |
+ | |
+echo "B $files" >> $pipe | |
+if [ $line != "none" ]; then | |
+ echo $line >> $pipe | |
+fi | |
+ | |
diff --git a/sam/Makefile b/sam/Makefile | |
@@ -0,0 +1,89 @@ | |
+# Copyright (c) 1998 Lucent Technologies - All rights reserved. | |
+# | |
+# Prototype Makefile for sam | |
+# | |
+# define operating system. ONE of: | |
+# -DIRIX -DSUNOS -DUMIPS -DSYSVR3 -DAIX -DOSF1 | |
+# -DHPUX -DAPOLLO -DCONVEX -DDYNIX | |
+# | |
+# -DIRIX is the default and should actually work on any modern system. | |
+# Additionally, -D_POSIX_SOURCE (or its equivalent) may be specified | |
+# if your compiler supports posix-compatible compilation. | |
+# | |
+include ../config.mk | |
+ | |
+# If your system has 64-bit addresses, add -DUSE64BITS to $(OS). | |
+OS=-DIRIX5 -DUSE64BITS=$(USE64BITS) | |
+ | |
+# add -Iincludedir for any include directories that need to be searched | |
+# for posix header files (for UMIPS, add -I/usr/include/posix) | |
+INCS=-I../include | |
+ | |
+# Set the name of the environment variable containing the user's home d… | |
+HOMEDIR=HOME | |
+ | |
+# RSAMNAME and TERMNAME contain the names of the files containing the | |
+# sam and samterm executables, respectively. SAMDIR is the directory | |
+# where sam is to be installed. SAMSAVEDIR is the name of the directory | |
+# where the samsave file restoration script is stored. | |
+RSAMNAME=sam | |
+TERMNAME=$(BINDIR)/samterm | |
+SAMDIR=$(BINDIR) | |
+SAMSAVEDIR=$(BINDIR) | |
+ | |
+# Set TMP to a good place for tmp files (with lots of room) | |
+TMP=$(TMPDIR) | |
+ | |
+# Set SHELLNAME and SHELLPATH to the name of a shell and the pathname | |
+# of its executable | |
+SHELLNAME=sh | |
+SHELLPATH=/bin/sh | |
+ | |
+# Set RXNAME and RXPATHNAME to the name of the remote execution command | |
+# and the pathname of its executable | |
+RXNAME=ssh | |
+RXPATHNAME=/usr/bin/ssh | |
+ | |
+# Set RXSAMNAME to the name of the command to run on the remote host. | |
+RXSAMNAME=/usr/local/bin/rsam | |
+ | |
+SAMSAVE=/bin/sh\\n$(SAMSAVEDIR)/samsave | |
+ | |
+CFLAGS=$(OS) -D_LIBXG_EXTENSION $(INCS) | |
+ | |
+SYSFLAGS= -DHOMEDIR=\"$(HOMEDIR)\" -DRSAMNAME=\"$(RSAMNAME)\" \ | |
+ -DTERMNAME=\"$(TERMNAME)\" -DTMP=\"$(TMP)\" \ | |
+ -DSHELLNAME=\"$(SHELLNAME)\" -DSHELLPATH=\"$(SHELLPATH)\" \ | |
+ -DRXNAME=\"$(RXNAME)\" -DRXPATHNAME=\"$(RXPATHNAME)\" \ | |
+ -DRXSAMNAME=\"$(RXSAMNAME)\" -DSAMSAVE=\"$(SAMSAVE)\" | |
+ | |
+LIB=../libframe/libframe.a ../libXg/libXg.a | |
+CC=cc $(SYSFLAGS) | |
+ | |
+OBJ=sam.o address.o buffer.o cmd.o disc.o error.o file.o io.o \ | |
+ list.o mesg.o moveto.o multi.o rasp.o regexp.o shell.o \ | |
+ string.o sys.o unix.o xec.o | |
+ | |
+all: sam | |
+ | |
+sam: $(OBJ) $(LIB) | |
+ $(CC) -o sam $(OBJ) $(LIB) | |
+ | |
+clean: | |
+ rm -f *.o core sam | |
+ | |
+nuke: clean | |
+ rm -f sam | |
+ | |
+install: sam | |
+ cp sam $(SAMDIR)/$(RSAMNAME) | |
+ cp samsave $(SAMSAVEDIR)/samsave | |
+ chmod +x $(SAMSAVEDIR)/samsave | |
+ | |
+$(OBJ): sam.h ../include/u.h ../include/libc.h errors.h mesg.h | |
+ | |
+cmd.o: parse.h | |
+xec.o: parse.h | |
+ | |
+unix.o: sam.h ../include/u.h ../include/libc.h errors.h mesg.h | |
+ $(CC) -c $(CFLAGS) $(SYSFLAGS) unix.c | |
diff --git a/sam/address.c b/sam/address.c | |
@@ -0,0 +1,241 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+#include "parse.h" | |
+ | |
+Address addr; | |
+String lastpat; | |
+int patset; | |
+File *menu; | |
+ | |
+File *matchfile(String*); | |
+Address charaddr(Posn, Address, int); | |
+ | |
+Address | |
+address(Addr *ap, Address a, int sign) | |
+{ | |
+ File *f = a.f; | |
+ Address a1, a2; | |
+ | |
+ do{ | |
+ switch(ap->type){ | |
+ case 'l': | |
+ case '#': | |
+ a = (*(ap->type=='#'?charaddr:lineaddr))(ap->num, a, s… | |
+ break; | |
+ | |
+ case '.': | |
+ a = f->dot; | |
+ break; | |
+ | |
+ case '$': | |
+ a.r.p1 = a.r.p2 = f->nrunes; | |
+ break; | |
+ | |
+ case '\'': | |
+ a.r = f->mark; | |
+ break; | |
+ | |
+ case '?': | |
+ sign = -sign; | |
+ if(sign == 0) | |
+ sign = -1; | |
+ /* fall through */ | |
+ case '/': | |
+ nextmatch(f, ap->are, sign>=0? a.r.p2 : a.r.p1, sign); | |
+ a.r = sel.p[0]; | |
+ break; | |
+ | |
+ case '"': | |
+ a = matchfile(ap->are)->dot; | |
+ f = a.f; | |
+ if(f->state == Unread) | |
+ load(f); | |
+ break; | |
+ | |
+ case '*': | |
+ a.r.p1 = 0, a.r.p2 = f->nrunes; | |
+ return a; | |
+ | |
+ case ',': | |
+ case ';': | |
+ if(ap->left) | |
+ a1 = address(ap->left, a, 0); | |
+ else | |
+ a1.f = a.f, a1.r.p1 = a1.r.p2 = 0; | |
+ if(ap->type == ';'){ | |
+ f = a1.f; | |
+ f->dot = a = a1; | |
+ } | |
+ if(ap->next) | |
+ a2 = address(ap->next, a, 0); | |
+ else | |
+ a2.f = a.f, a2.r.p1 = a2.r.p2 = f->nrunes; | |
+ if(a1.f != a2.f) | |
+ error(Eorder); | |
+ a.f = a1.f, a.r.p1 = a1.r.p1, a.r.p2 = a2.r.p2; | |
+ if(a.r.p2 < a.r.p1) | |
+ error(Eorder); | |
+ return a; | |
+ | |
+ case '+': | |
+ case '-': | |
+ sign = 1; | |
+ if(ap->type == '-') | |
+ sign = -1; | |
+ if(ap->next==0 || ap->next->type=='+' || ap->next->typ… | |
+ a = lineaddr(1L, a, sign); | |
+ break; | |
+ default: | |
+ panic("address"); | |
+ return a; | |
+ } | |
+ }while(ap = ap->next); /* assign = */ | |
+ return a; | |
+} | |
+ | |
+void | |
+nextmatch(File *f, String *r, Posn p, int sign) | |
+{ | |
+ compile(r); | |
+ if(sign >= 0){ | |
+ if(!execute(f, p, INFINITY)) | |
+ error(Esearch); | |
+ if(sel.p[0].p1==sel.p[0].p2 && sel.p[0].p1==p){ | |
+ if(++p>f->nrunes) | |
+ p = 0; | |
+ if(!execute(f, p, INFINITY)) | |
+ panic("address"); | |
+ } | |
+ }else{ | |
+ if(!bexecute(f, p)) | |
+ error(Esearch); | |
+ if(sel.p[0].p1==sel.p[0].p2 && sel.p[0].p2==p){ | |
+ if(--p<0) | |
+ p = f->nrunes; | |
+ if(!bexecute(f, p)) | |
+ panic("address"); | |
+ } | |
+ } | |
+} | |
+ | |
+File * | |
+matchfile(String *r) | |
+{ | |
+ File *f; | |
+ File *match = 0; | |
+ int i; | |
+ | |
+ for(i = 0; i<file.nused; i++){ | |
+ f = file.filepptr[i]; | |
+ if(f == cmd) | |
+ continue; | |
+ if(filematch(f, r)){ | |
+ if(match) | |
+ error(Emanyfiles); | |
+ match = f; | |
+ } | |
+ } | |
+ if(!match) | |
+ error(Efsearch); | |
+ return match; | |
+} | |
+ | |
+int | |
+filematch(File *f, String *r) | |
+{ | |
+ char *c, buf[STRSIZE+100]; | |
+ String *t; | |
+ | |
+ c = Strtoc(&f->name); | |
+ sprint(buf, "%c%c%c %s\n", " '"[f->state==Dirty], | |
+ "-+"[f->rasp!=0], " ."[f==curfile], c); | |
+ free(c); | |
+ t = tmpcstr(buf); | |
+ Strduplstr(&genstr, t); | |
+ freetmpstr(t); | |
+ /* A little dirty... */ | |
+ if(menu == 0) | |
+ (menu=Fopen())->state=Clean; | |
+ Bdelete(menu->buf, 0, menu->buf->nrunes); | |
+ Binsert(menu->buf, &genstr, 0); | |
+ menu->nrunes = menu->buf->nrunes; | |
+ compile(r); | |
+ return execute(menu, 0, menu->nrunes); | |
+} | |
+ | |
+Address | |
+charaddr(Posn l, Address addr, int sign) | |
+{ | |
+ if(sign == 0) | |
+ addr.r.p1 = addr.r.p2 = l; | |
+ else if(sign < 0) | |
+ addr.r.p2 = addr.r.p1-=l; | |
+ else if(sign > 0) | |
+ addr.r.p1 = addr.r.p2+=l; | |
+ if(addr.r.p1<0 || addr.r.p2>addr.f->nrunes) | |
+ error(Erange); | |
+ return addr; | |
+} | |
+ | |
+Address | |
+lineaddr(Posn l, Address addr, int sign) | |
+{ | |
+ int n; | |
+ int c; | |
+ File *f = addr.f; | |
+ Address a; | |
+ | |
+ SET(c); | |
+ a.f = f; | |
+ if(sign >= 0){ | |
+ if(l == 0){ | |
+ if(sign==0 || addr.r.p2==0){ | |
+ a.r.p1 = a.r.p2 = 0; | |
+ return a; | |
+ } | |
+ a.r.p1 = addr.r.p2; | |
+ Fgetcset(f, addr.r.p2-1); | |
+ }else{ | |
+ if(sign==0 || addr.r.p2==0){ | |
+ Fgetcset(f, (Posn)0); | |
+ n = 1; | |
+ }else{ | |
+ Fgetcset(f, addr.r.p2-1); | |
+ n = Fgetc(f)=='\n'; | |
+ } | |
+ for(; n<l; ){ | |
+ c = Fgetc(f); | |
+ if(c == -1) | |
+ error(Erange); | |
+ else if(c == '\n') | |
+ n++; | |
+ } | |
+ a.r.p1 = f->getcp; | |
+ } | |
+ do; while((c=Fgetc(f))!='\n' && c!=-1); | |
+ a.r.p2 = f->getcp; | |
+ }else{ | |
+ Fbgetcset(f, addr.r.p1); | |
+ if(l == 0) | |
+ a.r.p2 = addr.r.p1; | |
+ else{ | |
+ for(n = 0; n<l; ){ /* always runs once */ | |
+ c = Fbgetc(f); | |
+ if(c == '\n') | |
+ n++; | |
+ else if(c == -1){ | |
+ if(++n != l) | |
+ error(Erange); | |
+ } | |
+ } | |
+ a.r.p2 = f->getcp; | |
+ if(c == '\n') | |
+ a.r.p2++; /* lines start after a newlin… | |
+ } | |
+ do; while((c=Fbgetc(f))!='\n' && c!=-1); | |
+ a.r.p1 = f->getcp; | |
+ if(c == '\n') | |
+ a.r.p1++; /* lines start after a newline */ | |
+ } | |
+ return a; | |
+} | |
diff --git a/sam/buffer.c b/sam/buffer.c | |
@@ -0,0 +1,179 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+int incache(Buffer*, Posn, Posn); | |
+ | |
+Buffer * | |
+Bopen(Discdesc *dd) | |
+{ | |
+ Buffer *b; | |
+ | |
+ b = emalloc(sizeof(Buffer)); | |
+ b->disc = Dopen(dd); | |
+ Strinit(&b->cache); | |
+ return b; | |
+} | |
+ | |
+void | |
+Bterm(Buffer *b) | |
+{ | |
+ Dclose(b->disc); | |
+ Strclose(&b->cache); | |
+ free(b); | |
+} | |
+ | |
+int | |
+Bread(Buffer *b, Rune *addr, int n, Posn p0) | |
+{ | |
+ int m; | |
+ | |
+ if(b->c2>b->disc->nrunes || b->c1>b->disc->nrunes) | |
+ panic("bread cache"); | |
+ if(p0 < 0) | |
+ panic("Bread p0<0"); | |
+ if(p0+n > b->nrunes){ | |
+ n = b->nrunes-p0; | |
+ if(n < 0) | |
+ panic("Bread<0"); | |
+ } | |
+ if(!incache(b, p0, p0+n)){ | |
+ Bflush(b); | |
+ if(n>=BLOCKSIZE/2) | |
+ return Dread(b->disc, addr, n, p0); | |
+ else{ | |
+ Posn minp; | |
+ if(b->nrunes-p0>BLOCKSIZE/2) | |
+ m = BLOCKSIZE/2; | |
+ else | |
+ m = b->nrunes-p0; | |
+ if(m<n) | |
+ m = n; | |
+ minp = p0-BLOCKSIZE/2; | |
+ if(minp<0) | |
+ minp = 0; | |
+ m += p0-minp; | |
+ Strinsure(&b->cache, m); | |
+ if(Dread(b->disc, b->cache.s, m, minp)!=m) | |
+ panic("Bread"); | |
+ b->cache.n = m; | |
+ b->c1 = minp; | |
+ b->c2 = minp+m; | |
+ b->dirty = FALSE; | |
+ } | |
+ } | |
+ memmove(addr, &b->cache.s[p0-b->c1], n*RUNESIZE); | |
+ return n; | |
+} | |
+ | |
+void | |
+Binsert(Buffer *b, String *s, Posn p0) | |
+{ | |
+ if(b->c2>b->disc->nrunes || b->c1>b->disc->nrunes) | |
+ panic("binsert cache"); | |
+ if(p0<0) | |
+ panic("Binsert p0<0"); | |
+ if(s->n == 0) | |
+ return; | |
+ if(incache(b, p0, p0) && b->cache.n+s->n<=STRSIZE){ | |
+ Strinsert(&b->cache, s, p0-b->c1); | |
+ b->dirty = TRUE; | |
+ if(b->cache.n > BLOCKSIZE*2){ | |
+ b->nrunes += s->n; | |
+ Bflush(b); | |
+ /* try to leave some cache around p0 */ | |
+ if(p0 >= b->c1+BLOCKSIZE){ | |
+ /* first BLOCKSIZE can go */ | |
+ Strdelete(&b->cache, 0, BLOCKSIZE); | |
+ b->c1 += BLOCKSIZE; | |
+ }else if(p0 <= b->c2-BLOCKSIZE){ | |
+ /* last BLOCKSIZE can go */ | |
+ b->cache.n -= BLOCKSIZE; | |
+ b->c2 -= BLOCKSIZE; | |
+ }else{ | |
+ /* too hard; negate the cache and pick up next… | |
+ Strzero(&b->cache); | |
+ b->c1 = b->c2 = 0; | |
+ } | |
+ return; | |
+ } | |
+ }else{ | |
+ Bflush(b); | |
+ if(s->n >= BLOCKSIZE/2){ | |
+ b->cache.n = 0; | |
+ b->c1 = b->c2 = 0; | |
+ Dinsert(b->disc, s->s, s->n, p0); | |
+ }else{ | |
+ int m; | |
+ Posn minp; | |
+ if(b->nrunes-p0 > BLOCKSIZE/2) | |
+ m = BLOCKSIZE/2; | |
+ else | |
+ m = b->nrunes-p0; | |
+ minp = p0-BLOCKSIZE/2; | |
+ if(minp < 0) | |
+ minp = 0; | |
+ m += p0-minp; | |
+ Strinsure(&b->cache, m); | |
+ if(Dread(b->disc, b->cache.s, m, minp)!=m) | |
+ panic("Bread"); | |
+ b->cache.n = m; | |
+ b->c1 = minp; | |
+ b->c2 = minp+m; | |
+ Strinsert(&b->cache, s, p0-b->c1); | |
+ b->dirty = TRUE; | |
+ } | |
+ } | |
+ b->nrunes += s->n; | |
+} | |
+ | |
+void | |
+Bdelete(Buffer *b, Posn p1, Posn p2) | |
+{ | |
+ if(p1<0 || p2<0) | |
+ panic("Bdelete p<0"); | |
+ if(b->c2>b->disc->nrunes || b->c1>b->disc->nrunes) | |
+ panic("bdelete cache"); | |
+ if(p1 == p2) | |
+ return; | |
+ if(incache(b, p1, p2)){ | |
+ Strdelete(&b->cache, p1-b->c1, p2-b->c1); | |
+ b->dirty = TRUE; | |
+ }else{ | |
+ Bflush(b); | |
+ Ddelete(b->disc, p1, p2); | |
+ b->cache.n = 0; | |
+ b->c1 = b->c2 = 0; | |
+ } | |
+ b->nrunes -= p2-p1; | |
+} | |
+ | |
+void | |
+Bflush(Buffer *b) | |
+{ | |
+ if(b->dirty){ | |
+ Dreplace(b->disc, b->c1, b->c2, b->cache.s, b->cache.n); | |
+ b->c2 = b->c1+b->cache.n; | |
+ b->dirty = FALSE; | |
+ if(b->nrunes != b->disc->nrunes) | |
+ panic("Bflush"); | |
+ } | |
+} | |
+ | |
+void | |
+Bclean(Buffer *b) | |
+{ | |
+ if(b->dirty){ | |
+ Bflush(b); | |
+ b->c1 = b->c2 = 0; | |
+ Strzero(&b->cache); | |
+ } | |
+} | |
+ | |
+/*int hits, misses; /**/ | |
+ | |
+int | |
+incache(Buffer *b, Posn p1, Posn p2) | |
+{ | |
+ /*if(b->c1<=p1 && p2<=b->c1+b->cache.n)hits++; else misses++;/**/ | |
+ return b->c1<=p1 && p2<=b->c1+b->cache.n; | |
+} | |
diff --git a/sam/cmd.c b/sam/cmd.c | |
@@ -0,0 +1,591 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+#include "parse.h" | |
+ | |
+static char linex[]="\n"; | |
+static char wordx[]=" \t\n"; | |
+struct cmdtab cmdtab[]={ | |
+/* cmdc text regexp addr defcmd defa… | |
+ '\n', 0, 0, 0, 0, aDot, 0, … | |
+ 'a', 1, 0, 0, 0, aDot, 0, … | |
+ 'b', 0, 0, 0, 0, aNo, 0, … | |
+ 'B', 0, 0, 0, 0, aNo, 0, … | |
+ 'c', 1, 0, 0, 0, aDot, 0, … | |
+ 'd', 0, 0, 0, 0, aDot, 0, … | |
+ 'D', 0, 0, 0, 0, aNo, 0, … | |
+ 'e', 0, 0, 0, 0, aNo, 0, … | |
+ 'f', 0, 0, 0, 0, aNo, 0, … | |
+ 'g', 0, 1, 0, 'p', aDot, 0, … | |
+ 'i', 1, 0, 0, 0, aDot, 0, … | |
+ 'k', 0, 0, 0, 0, aDot, 0, … | |
+ 'm', 0, 0, 1, 0, aDot, 0, … | |
+ 'n', 0, 0, 0, 0, aNo, 0, … | |
+ 'p', 0, 0, 0, 0, aDot, 0, … | |
+ 'q', 0, 0, 0, 0, aNo, 0, … | |
+ 'r', 0, 0, 0, 0, aDot, 0, … | |
+ 's', 0, 1, 0, 0, aDot, 1, … | |
+ 't', 0, 0, 1, 0, aDot, 0, … | |
+ 'u', 0, 0, 0, 0, aNo, 1, … | |
+ 'v', 0, 1, 0, 'p', aDot, 0, … | |
+ 'w', 0, 0, 0, 0, aAll, 0, … | |
+ 'x', 0, 1, 0, 'p', aDot, 0, … | |
+ 'y', 0, 1, 0, 'p', aDot, 0, … | |
+ 'X', 0, 1, 0, 'f', aNo, 0, … | |
+ 'Y', 0, 1, 0, 'f', aNo, 0, … | |
+ '!', 0, 0, 0, 0, aNo, 0, … | |
+ '>', 0, 0, 0, 0, aDot, 0, … | |
+ '<', 0, 0, 0, 0, aDot, 0, … | |
+ '|', 0, 0, 0, 0, aDot, 0, … | |
+ '=', 0, 0, 0, 0, aDot, 0, … | |
+ 'c'|0x100,0, 0, 0, 0, aNo, 0, … | |
+ 0, 0, 0, 0, 0, 0, 0, … | |
+}; | |
+Cmd *parsecmd(int); | |
+Addr *compoundaddr(void); | |
+Addr *simpleaddr(void); | |
+void freecmd(void); | |
+void okdelim(int); | |
+ | |
+Rune line[BLOCKSIZE]; | |
+Rune termline[BLOCKSIZE]; | |
+Rune *linep = line; | |
+Rune *terminp = termline; | |
+Rune *termoutp = termline; | |
+List cmdlist; | |
+List addrlist; | |
+List relist; | |
+List stringlist; | |
+int eof; | |
+ | |
+void | |
+resetcmd(void) | |
+{ | |
+ linep = line; | |
+ *linep = 0; | |
+ terminp = termoutp = termline; | |
+ freecmd(); | |
+} | |
+ | |
+int | |
+inputc(void) | |
+{ | |
+ int n, nbuf; | |
+ char buf[3]; | |
+ Rune r; | |
+ | |
+ Again: | |
+ nbuf = 0; | |
+ if(downloaded){ | |
+ while(termoutp == terminp){ | |
+ cmdupdate(); | |
+ if(patset) | |
+ tellpat(); | |
+ while(termlocked > 0){ | |
+ outT0(Hunlock); | |
+ termlocked--; | |
+ } | |
+ if(rcv() == 0) | |
+ return -1; | |
+ } | |
+ r = *termoutp++; | |
+ if(termoutp == terminp) | |
+ terminp = termoutp = termline; | |
+ }else{ | |
+ do{ | |
+ n = read(0, buf+nbuf, 1); | |
+ if(n <= 0) | |
+ return -1; | |
+ nbuf += n; | |
+ }while(!fullrune(buf, nbuf)); | |
+ chartorune(&r, buf); | |
+ } | |
+ if(r == 0){ | |
+ warn(Wnulls); | |
+ goto Again; | |
+ } | |
+ return r; | |
+} | |
+ | |
+int | |
+inputline(void) | |
+{ | |
+ int i, c; | |
+ | |
+ linep = line; | |
+ i = 0; | |
+ do{ | |
+ if((c = inputc())<=0) | |
+ return -1; | |
+ if(i == (sizeof line)/RUNESIZE-1) | |
+ error(Etoolong); | |
+ }while((line[i++]=c) != '\n'); | |
+ line[i] = 0; | |
+ return 1; | |
+} | |
+ | |
+int | |
+getch(void) | |
+{ | |
+ if(eof) | |
+ return -1; | |
+ if(*linep==0 && inputline()<0){ | |
+ eof = TRUE; | |
+ return -1; | |
+ } | |
+ return *linep++; | |
+} | |
+ | |
+int | |
+nextc(void) | |
+{ | |
+ if(*linep == 0) | |
+ return -1; | |
+ return *linep; | |
+} | |
+ | |
+void | |
+ungetch(void) | |
+{ | |
+ if(--linep < line) | |
+ panic("ungetch"); | |
+} | |
+ | |
+Posn | |
+getnum(void) | |
+{ | |
+ Posn n=0; | |
+ int c; | |
+ | |
+ if((c=nextc())<'0' || '9'<c) /* no number defaults to 1 */ | |
+ return 1; | |
+ while('0'<=(c=getch()) && c<='9') | |
+ n = n*10 + (c-'0'); | |
+ ungetch(); | |
+ return n; | |
+} | |
+ | |
+int | |
+skipbl(void) | |
+{ | |
+ int c; | |
+ do | |
+ c = getch(); | |
+ while(c==' ' || c=='\t'); | |
+ if(c >= 0) | |
+ ungetch(); | |
+ return c; | |
+} | |
+ | |
+void | |
+termcommand(void) | |
+{ | |
+ Posn p; | |
+ | |
+ Fgetcset(cmd, cmdpt); | |
+ for(p=cmdpt; p<cmd->nrunes; p++){ | |
+ if(terminp >= &termline[BLOCKSIZE]){ | |
+ cmdpt = cmd->nrunes; | |
+ error(Etoolong); | |
+ } | |
+ *terminp++ = Fgetc(cmd); | |
+ } | |
+ cmdpt = cmd->nrunes; | |
+} | |
+ | |
+void | |
+cmdloop(void) | |
+{ | |
+ Cmd *cmdp; | |
+ File *ocurfile; | |
+ int loaded; | |
+ | |
+ for(;;){ | |
+ if(!downloaded && curfile && curfile->state==Unread) | |
+ load(curfile); | |
+ if((cmdp = parsecmd(0))==0){ | |
+ if(downloaded){ | |
+ rescue(); | |
+ exits("eof"); | |
+ } | |
+ break; | |
+ } | |
+ ocurfile = curfile; | |
+ loaded = curfile && curfile->state!=Unread; | |
+ if(cmdexec(curfile, cmdp) == 0) | |
+ break; | |
+ freecmd(); | |
+ cmdupdate(); | |
+ update(); | |
+ if(downloaded && curfile && | |
+ (ocurfile!=curfile || (!loaded && curfile->state!=Unread))) | |
+ outTs(Hcurrent, curfile->tag); | |
+ /* don't allow type ahead on files that aren't bound */ | |
+ if(downloaded && curfile && curfile->rasp == 0) | |
+ terminp = termoutp; | |
+ } | |
+} | |
+ | |
+Cmd * | |
+newcmd(void){ | |
+ Cmd *p; | |
+ | |
+ p = emalloc(sizeof(Cmd)); | |
+ inslist(&cmdlist, cmdlist.nused, (long)p); | |
+ return p; | |
+} | |
+ | |
+Addr* | |
+newaddr(void) | |
+{ | |
+ Addr *p; | |
+ | |
+ p = emalloc(sizeof(Addr)); | |
+ inslist(&addrlist, addrlist.nused, (long)p); | |
+ return p; | |
+} | |
+ | |
+String* | |
+newre(void) | |
+{ | |
+ String *p; | |
+ | |
+ p = emalloc(sizeof(String)); | |
+ inslist(&relist, relist.nused, (long)p); | |
+ Strinit(p); | |
+ return p; | |
+} | |
+ | |
+String* | |
+newstring(void) | |
+{ | |
+ String *p; | |
+ | |
+ p = emalloc(sizeof(String)); | |
+ inslist(&stringlist, stringlist.nused, (long)p); | |
+ Strinit(p); | |
+ return p; | |
+} | |
+ | |
+void | |
+freecmd(void) | |
+{ | |
+ int i; | |
+ | |
+ while(cmdlist.nused > 0) | |
+ free(cmdlist.ucharpptr[--cmdlist.nused]); | |
+ while(addrlist.nused > 0) | |
+ free(addrlist.ucharpptr[--addrlist.nused]); | |
+ while(relist.nused > 0){ | |
+ i = --relist.nused; | |
+ Strclose(relist.stringpptr[i]); | |
+ free(relist.stringpptr[i]); | |
+ } | |
+ while(stringlist.nused>0){ | |
+ i = --stringlist.nused; | |
+ Strclose(stringlist.stringpptr[i]); | |
+ free(stringlist.stringpptr[i]); | |
+ } | |
+} | |
+ | |
+int | |
+lookup(int c) | |
+{ | |
+ int i; | |
+ | |
+ for(i=0; cmdtab[i].cmdc; i++) | |
+ if(cmdtab[i].cmdc == c) | |
+ return i; | |
+ return -1; | |
+} | |
+ | |
+void | |
+okdelim(int c) | |
+{ | |
+ if(c=='\\' || ('a'<=c && c<='z') | |
+ || ('A'<=c && c<='Z') || ('0'<=c && c<='9')) | |
+ error_c(Edelim, c); | |
+} | |
+ | |
+void | |
+atnl(void) | |
+{ | |
+ skipbl(); | |
+ if(getch() != '\n') | |
+ error(Enewline); | |
+} | |
+ | |
+void | |
+getrhs(String *s, int delim, int cmd) | |
+{ | |
+ int c; | |
+ | |
+ while((c = getch())>0 && c!=delim && c!='\n'){ | |
+ if(c == '\\'){ | |
+ if((c=getch()) <= 0) | |
+ error(Ebadrhs); | |
+ if(c == '\n'){ | |
+ ungetch(); | |
+ c='\\'; | |
+ }else if(c == 'n') | |
+ c='\n'; | |
+ else if(c!=delim && (cmd=='s' || c!='\\')) /* s… | |
+ Straddc(s, '\\'); | |
+ } | |
+ Straddc(s, c); | |
+ } | |
+ ungetch(); /* let client read whether delimeter, '\n' or whatev… | |
+} | |
+ | |
+String * | |
+collecttoken(char *end) | |
+{ | |
+ String *s = newstring(); | |
+ int c; | |
+ | |
+ while((c=nextc())==' ' || c=='\t') | |
+ Straddc(s, getch()); /* blanks significant for getname() */ | |
+ while((c=getch())>0 && utfrune(end, c)==0) | |
+ Straddc(s, c); | |
+ Straddc(s, 0); | |
+ if(c != '\n') | |
+ atnl(); | |
+ return s; | |
+} | |
+ | |
+String * | |
+collecttext(void) | |
+{ | |
+ String *s = newstring(); | |
+ int begline, i, c, delim; | |
+ | |
+ if(skipbl()=='\n'){ | |
+ getch(); | |
+ i = 0; | |
+ do{ | |
+ begline = i; | |
+ while((c = getch())>0 && c!='\n') | |
+ i++, Straddc(s, c); | |
+ i++, Straddc(s, '\n'); | |
+ if(c < 0) | |
+ goto Return; | |
+ }while(s->s[begline]!='.' || s->s[begline+1]!='\n'); | |
+ Strdelete(s, s->n-2, s->n); | |
+ }else{ | |
+ okdelim(delim = getch()); | |
+ getrhs(s, delim, 'a'); | |
+ if(nextc()==delim) | |
+ getch(); | |
+ atnl(); | |
+ } | |
+ Return: | |
+ Straddc(s, 0); /* JUST FOR CMDPRINT() */ | |
+ return s; | |
+} | |
+ | |
+Cmd * | |
+parsecmd(int nest) | |
+{ | |
+ int i, c; | |
+ struct cmdtab *ct; | |
+ Cmd *cp, *ncp; | |
+ Cmd cmd; | |
+ | |
+ cmd.next = cmd.ccmd = 0; | |
+ cmd.re = 0; | |
+ cmd.flag = cmd.num = 0; | |
+ cmd.addr = compoundaddr(); | |
+ if(skipbl() == -1) | |
+ return 0; | |
+ if((c=getch())==-1) | |
+ return 0; | |
+ cmd.cmdc = c; | |
+ if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case… | |
+ getch(); /* the 'd' */ | |
+ cmd.cmdc='c'|0x100; | |
+ } | |
+ i = lookup(cmd.cmdc); | |
+ if(i >= 0){ | |
+ if(cmd.cmdc == '\n') | |
+ goto Return; /* let nl_cmd work it all out */ | |
+ ct = &cmdtab[i]; | |
+ if(ct->defaddr==aNo && cmd.addr) | |
+ error(Enoaddr); | |
+ if(ct->count) | |
+ cmd.num = getnum(); | |
+ if(ct->regexp){ | |
+ /* x without pattern -> .*\n, indicated by cmd.re==0 */ | |
+ /* X without pattern is all files */ | |
+ if((ct->cmdc!='x' && ct->cmdc!='X') || | |
+ ((c = nextc())!=' ' && c!='\t' && c!='\n')){ | |
+ skipbl(); | |
+ if((c = getch())=='\n' || c<0) | |
+ error(Enopattern); | |
+ okdelim(c); | |
+ cmd.re = getregexp(c); | |
+ if(ct->cmdc == 's'){ | |
+ cmd.ctext = newstring(); | |
+ getrhs(cmd.ctext, c, 's'); | |
+ if(nextc() == c){ | |
+ getch(); | |
+ if(nextc() == 'g') | |
+ cmd.flag = getch(); | |
+ } | |
+ | |
+ } | |
+ } | |
+ } | |
+ if(ct->addr && (cmd.caddr=simpleaddr())==0) | |
+ error(Eaddress); | |
+ if(ct->defcmd){ | |
+ if(skipbl() == '\n'){ | |
+ getch(); | |
+ cmd.ccmd = newcmd(); | |
+ cmd.ccmd->cmdc = ct->defcmd; | |
+ }else if((cmd.ccmd = parsecmd(nest))==0) | |
+ panic("defcmd"); | |
+ }else if(ct->text) | |
+ cmd.ctext = collecttext(); | |
+ else if(ct->token) | |
+ cmd.ctext = collecttoken(ct->token); | |
+ else | |
+ atnl(); | |
+ }else | |
+ switch(cmd.cmdc){ | |
+ case '{': | |
+ cp = 0; | |
+ do{ | |
+ if(skipbl()=='\n') | |
+ getch(); | |
+ ncp = parsecmd(nest+1); | |
+ if(cp) | |
+ cp->next = ncp; | |
+ else | |
+ cmd.ccmd = ncp; | |
+ }while(cp = ncp); | |
+ break; | |
+ case '}': | |
+ atnl(); | |
+ if(nest==0) | |
+ error(Enolbrace); | |
+ return 0; | |
+ default: | |
+ error_c(Eunk, cmd.cmdc); | |
+ } | |
+ Return: | |
+ cp = newcmd(); | |
+ *cp = cmd; | |
+ return cp; | |
+} | |
+ | |
+String* /* BUGGERED */ | |
+getregexp(int delim) | |
+{ | |
+ String *r = newre(); | |
+ int c; | |
+ | |
+ for(Strzero(&genstr); ; Straddc(&genstr, c)) | |
+ if((c = getch())=='\\'){ | |
+ if(nextc()==delim) | |
+ c = getch(); | |
+ else if(nextc()=='\\'){ | |
+ Straddc(&genstr, c); | |
+ c = getch(); | |
+ } | |
+ }else if(c==delim || c=='\n') | |
+ break; | |
+ if(c!=delim && c) | |
+ ungetch(); | |
+ if(genstr.n > 0){ | |
+ patset = TRUE; | |
+ Strduplstr(&lastpat, &genstr); | |
+ Straddc(&lastpat, '\0'); | |
+ } | |
+ if(lastpat.n <= 1) | |
+ error(Epattern); | |
+ Strduplstr(r, &lastpat); | |
+ return r; | |
+} | |
+ | |
+Addr * | |
+simpleaddr(void) | |
+{ | |
+ Addr addr; | |
+ Addr *ap, *nap; | |
+ | |
+ addr.next = 0; | |
+ addr.left = 0; | |
+ switch(skipbl()){ | |
+ case '#': | |
+ addr.type = getch(); | |
+ addr.num = getnum(); | |
+ break; | |
+ case '0': case '1': case '2': case '3': case '4': | |
+ case '5': case '6': case '7': case '8': case '9': | |
+ addr.num = getnum(); | |
+ addr.type='l'; | |
+ break; | |
+ case '/': case '?': case '"': | |
+ addr.are = getregexp(addr.type = getch()); | |
+ break; | |
+ case '.': | |
+ case '$': | |
+ case '+': | |
+ case '-': | |
+ case '\'': | |
+ addr.type = getch(); | |
+ break; | |
+ default: | |
+ return 0; | |
+ } | |
+ if(addr.next = simpleaddr()) | |
+ switch(addr.next->type){ | |
+ case '.': | |
+ case '$': | |
+ case '\'': | |
+ if(addr.type!='"') | |
+ case '"': | |
+ error(Eaddress); | |
+ break; | |
+ case 'l': | |
+ case '#': | |
+ if(addr.type=='"') | |
+ break; | |
+ /* fall through */ | |
+ case '/': | |
+ case '?': | |
+ if(addr.type!='+' && addr.type!='-'){ | |
+ /* insert the missing '+' */ | |
+ nap = newaddr(); | |
+ nap->type='+'; | |
+ nap->next = addr.next; | |
+ addr.next = nap; | |
+ } | |
+ break; | |
+ case '+': | |
+ case '-': | |
+ break; | |
+ default: | |
+ panic("simpleaddr"); | |
+ } | |
+ ap = newaddr(); | |
+ *ap = addr; | |
+ return ap; | |
+} | |
+ | |
+Addr * | |
+compoundaddr(void) | |
+{ | |
+ Addr addr; | |
+ Addr *ap, *next; | |
+ | |
+ addr.left = simpleaddr(); | |
+ if((addr.type = skipbl())!=',' && addr.type!=';') | |
+ return addr.left; | |
+ getch(); | |
+ next = addr.next = compoundaddr(); | |
+ if(next && (next->type==',' || next->type==';') && next->left==0) | |
+ error(Eaddress); | |
+ ap = newaddr(); | |
+ *ap = addr; | |
+ return ap; | |
+} | |
diff --git a/sam/disc.c b/sam/disc.c | |
@@ -0,0 +1,335 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+#define BLOCKFILL (BLOCKSIZE/2) | |
+ | |
+static Discdesc desc[NBUFFILES]; | |
+ | |
+void bkalloc(Disc*, int); | |
+void bkfree(Disc*, int); | |
+void bkwrite(Disc*, Rune*, int, int, int); | |
+void bkread(Disc*, Rune*, int, int, int); | |
+ | |
+ | |
+Discdesc * | |
+Dstart(void) | |
+{ | |
+ int i, fd; | |
+ Discdesc *dd; | |
+ | |
+ for(i=0, dd=desc; dd->fd; i++, dd++) | |
+ if(i == NBUFFILES-1) | |
+ panic("too many buffer files"); | |
+ fd = newtmp(i); | |
+ if(fd < 0) | |
+ panic("can't create buffer file"); | |
+ dd->fd = fd; | |
+ return dd; | |
+} | |
+ | |
+Disc * | |
+Dopen(Discdesc *dd) | |
+{ | |
+ Disc *d; | |
+ | |
+ d = emalloc(sizeof(Disc)); | |
+ d->desc = dd; | |
+ return d; | |
+} | |
+ | |
+void | |
+Dclose(Disc *d) | |
+{ | |
+ int i; | |
+ | |
+ for(i=d->block.nused; --i>=0; ) /* backwards because bkfree() s… | |
+ bkfree(d, i); | |
+ free(d->block.listptr); | |
+ free(d); | |
+} | |
+ | |
+int | |
+Dread(Disc *d, Rune *addr, int n, Posn p1) | |
+{ | |
+ int i, nb, nr; | |
+ Posn p = 0, p2 = p1+n; | |
+ | |
+ for(i=0; i<d->block.nused; i++){ | |
+ if((p+=d->block.blkptr[i].nrunes) > p1){ | |
+ p -= d->block.blkptr[i].nrunes; | |
+ goto out; | |
+ } | |
+ } | |
+ if(p == p1) | |
+ return 0; /* eof */ | |
+ return -1; /* past eof */ | |
+ | |
+ out: | |
+ n = 0; | |
+ if(p != p1){ /* trailing partial block */ | |
+ nb = d->block.blkptr[i].nrunes; | |
+ if(p2 > p+nb) | |
+ nr = nb-(p1-p); | |
+ else | |
+ nr = p2-p1; | |
+ bkread(d, addr, nr, i, p1-p); | |
+ /* advance to next block */ | |
+ p += nb; | |
+ addr += nr; | |
+ n += nr; | |
+ i++; | |
+ } | |
+ /* whole blocks */ | |
+ while(p<p2 && (nb = d->block.blkptr[i].nrunes)<=p2-p){ | |
+ if(i >= d->block.nused) | |
+ return n; /* eof */ | |
+ bkread(d, addr, nb, i, 0); | |
+ p += nb; | |
+ addr += nb; | |
+ n += nb; | |
+ i++; | |
+ } | |
+ if(p < p2){ /* any initial partial block left? */ | |
+ nr = p2-p; | |
+ nb = d->block.blkptr[i].nrunes; | |
+ if(nr>nb) | |
+ nr = nb; /* eof */ | |
+ /* just read in the part that survives */ | |
+ bkread(d, addr, nr, i, 0); | |
+ n += nr; | |
+ } | |
+ return n; | |
+} | |
+ | |
+void | |
+Dinsert(Disc *d, Rune *addr, int n, Posn p0) /* if addr null, just make space … | |
+{ | |
+ int i, nb, ni; | |
+ Posn p = 0; | |
+ Rune hold[BLOCKSIZE]; | |
+ int nhold; | |
+ | |
+ for(i=0; i<d->block.nused; i++){ | |
+ if((p+=d->block.blkptr[i].nrunes) >= p0){ | |
+ p -= d->block.blkptr[i].nrunes; | |
+ goto out; | |
+ } | |
+ } | |
+ if(p != p0) | |
+ panic("Dinsert"); /* beyond eof */ | |
+ | |
+ out: | |
+ d->nrunes += n; | |
+ nhold = 0; | |
+ if(i<d->block.nused && (nb=d->block.blkptr[i].nrunes)>p0-p){ | |
+ nhold = nb-(p0-p); | |
+ bkread(d, hold, nhold, i, p0-p); | |
+ d->block.blkptr[i].nrunes -= nhold; /* no write necessa… | |
+ } | |
+ /* insertion point is now at end of block i (which may not exist) */ | |
+ while(n > 0){ | |
+ if(i < d->block.nused | |
+ && (nb=d->block.blkptr[i].nrunes) < BLOCKFILL){ | |
+ /* fill this block */ | |
+ if(nb+n > BLOCKSIZE) | |
+ ni = BLOCKFILL-nb; | |
+ else | |
+ ni = n; | |
+ if(addr) | |
+ bkwrite(d, addr, ni, i, nb); | |
+ nb += ni; | |
+ }else{ /* make new block */ | |
+ if(i < d->block.nused) | |
+ i++; /* put after this block, if it exi… | |
+ bkalloc(d, i); | |
+ if(n > BLOCKSIZE) | |
+ ni = BLOCKFILL; | |
+ else | |
+ ni = n; | |
+ if(addr) | |
+ bkwrite(d, addr, ni, i, 0); | |
+ nb = ni; | |
+ } | |
+ d->block.blkptr[i].nrunes = nb; | |
+ if(addr) | |
+ addr += ni; | |
+ n -= ni; | |
+ } | |
+ if(nhold){ | |
+ if(i < d->block.nused | |
+ && (nb=d->block.blkptr[i].nrunes)+nhold < BLOCKSIZE){ | |
+ /* fill this block */ | |
+ bkwrite(d, hold, nhold, i, nb); | |
+ nb += nhold; | |
+ }else{ /* make new block */ | |
+ if(i < d->block.nused) | |
+ i++; /* put after this block, if it exi… | |
+ bkalloc(d, i); | |
+ bkwrite(d, hold, nhold, i, 0); | |
+ nb = nhold; | |
+ } | |
+ d->block.blkptr[i].nrunes = nb; | |
+ } | |
+} | |
+ | |
+void | |
+Ddelete(Disc *d, Posn p1, Posn p2) | |
+{ | |
+ int i, nb, nd; | |
+ Posn p = 0; | |
+ Rune buf[BLOCKSIZE]; | |
+ | |
+ for(i = 0; i<d->block.nused; i++){ | |
+ if((p+=d->block.blkptr[i].nrunes) > p1){ | |
+ p -= d->block.blkptr[i].nrunes; | |
+ goto out; | |
+ } | |
+ } | |
+ if(p1!=d->nrunes || p2!=p1) | |
+ panic("Ddelete"); | |
+ return; /* beyond eof */ | |
+ | |
+ out: | |
+ d->nrunes -= p2-p1; | |
+ if(p != p1){ /* throw away partial block */ | |
+ nb = d->block.blkptr[i].nrunes; | |
+ bkread(d, buf, nb, i, 0); | |
+ if(p2 >= p+nb) | |
+ nd = nb-(p1-p); | |
+ else{ | |
+ nd = p2-p1; | |
+ memmove(buf+(p1-p), buf+(p1-p)+nd, RUNESIZE*(nb-((p1-p… | |
+ } | |
+ nb -= nd; | |
+ bkwrite(d, buf, nb, i, 0); | |
+ d->block.blkptr[i].nrunes = nb; | |
+ p2 -= nd; | |
+ /* advance to next block */ | |
+ p += nb; | |
+ i++; | |
+ } | |
+ /* throw away whole blocks */ | |
+ while(p<p2 && (nb = d->block.blkptr[i].nrunes)<=p2-p){ | |
+ if(i >= d->block.nused) | |
+ panic("Ddelete 2"); | |
+ bkfree(d, i); | |
+ p2 -= nb; | |
+ } | |
+ if(p >= p2) /* any initial partial block left to delete? */ | |
+ return; /* no */ | |
+ nd = p2-p; | |
+ nb = d->block.blkptr[i].nrunes; | |
+ /* just read in the part that survives */ | |
+ bkread(d, buf, nb-=nd, i, nd); | |
+ /* a little block merging */ | |
+ if(nb<BLOCKSIZE/2 && i>0 && (nd = d->block.blkptr[i-1].nrunes)<BLOCKSI… | |
+ memmove(buf+nd, buf, RUNESIZE*nb); | |
+ bkread(d, buf, nd, --i, 0); | |
+ bkfree(d, i); | |
+ nb += nd; | |
+ } | |
+ bkwrite(d, buf, nb, i, 0); | |
+ d->block.blkptr[i].nrunes = nb; | |
+} | |
+ | |
+void | |
+Dreplace(Disc *d, Posn p1, Posn p2, Rune *addr, int n) | |
+{ | |
+ int i, nb, nr; | |
+ Posn p = 0; | |
+ Rune buf[BLOCKSIZE]; | |
+ | |
+ if(p2-p1 > n) | |
+ Ddelete(d, p1+n, p2); | |
+ else if(p2-p1 < n) | |
+ Dinsert(d, 0, n-(p2-p1), p2); | |
+ if(n == 0) | |
+ return; | |
+ p2 = p1+n; | |
+ /* they're now conformal; replace in place */ | |
+ for(i=0; i<d->block.nused; i++){ | |
+ if((p+=d->block.blkptr[i].nrunes) > p1){ | |
+ p -= d->block.blkptr[i].nrunes; | |
+ goto out; | |
+ } | |
+ } | |
+ panic("Dreplace"); | |
+ | |
+ out: | |
+ if(p != p1){ /* trailing partial block */ | |
+ nb = d->block.blkptr[i].nrunes; | |
+ bkread(d, buf, nb, i, 0); | |
+ if(p2 > p+nb) | |
+ nr = nb-(p1-p); | |
+ else | |
+ nr = p2-p1; | |
+ memmove(buf+p1-p, addr, RUNESIZE*nr); | |
+ bkwrite(d, buf, nb, i, 0); | |
+ /* advance to next block */ | |
+ p += nb; | |
+ addr += nr; | |
+ i++; | |
+ } | |
+ /* whole blocks */ | |
+ while(p<p2 && (nb = d->block.blkptr[i].nrunes)<=p2-p){ | |
+ if(i >= d->block.nused) | |
+ panic("Dreplace 2"); | |
+ bkwrite(d, addr, nb, i, 0); | |
+ p += nb; | |
+ addr += nb; | |
+ i++; | |
+ } | |
+ if(p < p2){ /* any initial partial block left? */ | |
+ nr = p2-p; | |
+ nb = d->block.blkptr[i].nrunes; | |
+ /* just read in the part that survives */ | |
+ bkread(d, buf+nr, nb-nr, i, nr); | |
+ memmove(buf, addr, RUNESIZE*nr); | |
+ bkwrite(d, buf, nb, i, 0); | |
+ } | |
+} | |
+ | |
+void | |
+bkread(Disc *d, Rune *loc, int n, int bk, int off) | |
+{ | |
+ Seek(d->desc->fd, RUNESIZE*(BLOCKSIZE*d->block.blkptr[bk].bnum+off), 0… | |
+ Read(d->desc->fd, loc, n*RUNESIZE); | |
+} | |
+ | |
+void | |
+bkwrite(Disc *d, Rune *loc, int n, int bk, int off) | |
+{ | |
+ Seek(d->desc->fd, RUNESIZE*(BLOCKSIZE*d->block.blkptr[bk].bnum+off), 0… | |
+ Write(d->desc->fd, loc, n*RUNESIZE); | |
+ /* | |
+ * sleazy hack to avoid silly SGI kernel bug | |
+ * fill partial block with garbage | |
+ */ | |
+ if (off+n >= d->block.blkptr[bk].nrunes && off+n < BLOCKSIZE) | |
+ Write(d->desc->fd, genbuf, (BLOCKSIZE-(off+n))*RUNESIZE); | |
+} | |
+ | |
+void | |
+bkalloc(Disc *d, int n) | |
+{ | |
+ Discdesc *dd = d->desc; | |
+ ulong bnum; | |
+ | |
+ if(dd->free.nused) | |
+ bnum = dd->free.longptr[--dd->free.nused]; | |
+ else | |
+ bnum = dd->nbk++; | |
+ if(bnum >= 1<<(8*(sizeof(((Block*)0)->bnum)))) | |
+ error(Etmpovfl); | |
+ inslist(&d->block, n, 0L); | |
+ d->block.blkptr[n].bnum = bnum; | |
+} | |
+ | |
+void | |
+bkfree(Disc *d, int n) | |
+{ | |
+ Discdesc *dd = d->desc; | |
+ | |
+ inslist(&dd->free, dd->free.nused, d->block.blkptr[n].bnum); | |
+ dellist(&d->block, n); | |
+} | |
diff --git a/sam/error.c b/sam/error.c | |
@@ -0,0 +1,132 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+static char *emsg[]={ | |
+ /* error_s */ | |
+ "can't open", | |
+ "can't create", | |
+ "not in menu:", | |
+ "changes to", | |
+ "I/O error:", | |
+ /* error_c */ | |
+ "unknown command", | |
+ "no operand for", | |
+ "bad delimiter", | |
+ /* error */ | |
+ "can't fork", | |
+ "interrupt", | |
+ "address", | |
+ "search", | |
+ "pattern", | |
+ "newline expected", | |
+ "blank expected", | |
+ "pattern expected", | |
+ "can't nest X or Y", | |
+ "unmatched `}'", | |
+ "command takes no address", | |
+ "addresses overlap", | |
+ "substitution", | |
+ "& match too long", | |
+ "bad \\ in rhs", | |
+ "address range", | |
+ "changes not in sequence", | |
+ "addresses out of order", | |
+ "no file name", | |
+ "unmatched `('", | |
+ "unmatched `)'", | |
+ "malformed `[]'", | |
+ "malformed regexp", | |
+ "reg. exp. list overflow", | |
+ "plan 9 command", | |
+ "can't pipe", | |
+ "no current file", | |
+ "string too long", | |
+ "changed files", | |
+ "empty string", | |
+ "file search", | |
+ "non-unique match for \"\"", | |
+ "tag match too long", | |
+ "too many subexpressions", | |
+ "temporary file too large", | |
+ "file is append-only", | |
+}; | |
+static char *wmsg[]={ | |
+ /* warn_s */ | |
+ "duplicate file name", | |
+ "no such file", | |
+ "write might change good version of", | |
+ /* warn_S */ | |
+ "files might be aliased", | |
+ /* warn */ | |
+ "null characters elided", | |
+ "can't run pwd", | |
+ "last char not newline", | |
+ "exit status not 0", | |
+}; | |
+ | |
+void | |
+error(Err s) | |
+{ | |
+ char buf[512]; | |
+ | |
+ sprint(buf, "?%s", emsg[s]); | |
+ hiccough(buf); | |
+} | |
+ | |
+void | |
+error_s(Err s, char *a) | |
+{ | |
+ char buf[512]; | |
+ | |
+ sprint(buf, "?%s \"%s\"", emsg[s], a); | |
+ hiccough(buf); | |
+} | |
+ | |
+void | |
+error_c(Err s, int c) | |
+{ | |
+ char buf[512]; | |
+ | |
+ sprint(buf, "?%s `%c'", emsg[s], c); | |
+ hiccough(buf); | |
+} | |
+ | |
+void | |
+warn(Warn s) | |
+{ | |
+ dprint("?warning: %s\n", wmsg[s]); | |
+} | |
+ | |
+void | |
+warn_S(Warn s, String *a) | |
+{ | |
+ print_s(wmsg[s], a); | |
+} | |
+ | |
+void | |
+warn_SS(Warn s, String *a, String *b) | |
+{ | |
+ print_ss(wmsg[s], a, b); | |
+} | |
+ | |
+void | |
+warn_s(Warn s, char *a) | |
+{ | |
+ dprint("?warning: %s `%s'\n", wmsg[s], a); | |
+} | |
+ | |
+void | |
+termwrite(char *s) | |
+{ | |
+ String *p; | |
+ | |
+ if(downloaded){ | |
+ p = tmpcstr(s); | |
+ if(cmd) | |
+ Finsert(cmd, p, cmdpt); | |
+ else | |
+ Strinsert(&cmdstr, p, cmdstr.n); | |
+ cmdptadv += p->n; | |
+ }else | |
+ Write(2, s, strlen(s)); | |
+} | |
diff --git a/sam/errors.h b/sam/errors.h | |
@@ -0,0 +1,63 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+typedef enum Err{ | |
+ /* error_s */ | |
+ Eopen, | |
+ Ecreate, | |
+ Emenu, | |
+ Emodified, | |
+ Eio, | |
+ /* error_c */ | |
+ Eunk, | |
+ Emissop, | |
+ Edelim, | |
+ /* error */ | |
+ Efork, | |
+ Eintr, | |
+ Eaddress, | |
+ Esearch, | |
+ Epattern, | |
+ Enewline, | |
+ Eblank, | |
+ Enopattern, | |
+ EnestXY, | |
+ Enolbrace, | |
+ Enoaddr, | |
+ Eoverlap, | |
+ Enosub, | |
+ Elongrhs, | |
+ Ebadrhs, | |
+ Erange, | |
+ Esequence, | |
+ Eorder, | |
+ Enoname, | |
+ Eleftpar, | |
+ Erightpar, | |
+ Ebadclass, | |
+ Ebadregexp, | |
+ Eoverflow, | |
+ Enocmd, | |
+ Epipe, | |
+ Enofile, | |
+ Etoolong, | |
+ Echanges, | |
+ Eempty, | |
+ Efsearch, | |
+ Emanyfiles, | |
+ Elongtag, | |
+ Esubexp, | |
+ Etmpovfl, | |
+ Eappend | |
+}Err; | |
+typedef enum Warn{ | |
+ /* warn_s */ | |
+ Wdupname, | |
+ Wfile, | |
+ Wdate, | |
+ /* warn_ss */ | |
+ Wdupfile, | |
+ /* warn */ | |
+ Wnulls, | |
+ Wpwd, | |
+ Wnotnewline, | |
+ Wbadstatus | |
+}Warn; | |
diff --git a/sam/file.c b/sam/file.c | |
@@ -0,0 +1,465 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+/* | |
+ * Files are splayed out a factor of NDISC to reduce indirect block access | |
+ */ | |
+Discdesc *files[NDISC]; | |
+Discdesc *transcripts[NDISC]; | |
+Buffer *undobuf; | |
+static String *ftempstr(Rune*, int); | |
+int fcount; | |
+File *lastfile; | |
+ | |
+void puthdr_csl(Buffer*, char, short, Posn); | |
+void puthdr_cs(Buffer*, char, short); | |
+void puthdr_M(Buffer*, Posn, Range, Range, Mod, short); | |
+void puthdr_cll(Buffer*, char, Posn, Posn); | |
+void Fflush(File*); | |
+ | |
+enum{ | |
+ SKIP=50, /* max dist between file changes folded togeth… | |
+ MAXCACHE=STRSIZE /* max length of cache. must be < 32K-BLOCKSIZ… | |
+}; | |
+ | |
+void | |
+Fstart(void) | |
+{ | |
+ undobuf = Bopen(Dstart()); | |
+ snarfbuf = Bopen(Dstart()); | |
+ plan9buf = Bopen(Dstart()); | |
+} | |
+ | |
+void | |
+Fmark(File *f, Mod m) | |
+{ | |
+ Buffer *t = f->transcript; | |
+ Posn p; | |
+ | |
+ if(f->state == Readerr) | |
+ return; | |
+ if(f->state == Unread) /* this is implicit 'e' of a file */ | |
+ return; | |
+ p = m==0? -1 : f->markp; | |
+ f->markp = t->nrunes; | |
+ puthdr_M(t, p, f->dot.r, f->mark, f->mod, f->state); | |
+ f->ndot = f->dot; | |
+ f->marked = TRUE; | |
+ f->mod = m; | |
+ f->hiposn = -1; | |
+ /* Safety first */ | |
+ f->cp1 = f->cp2 = 0; | |
+} | |
+ | |
+File * | |
+Fopen(void) | |
+{ | |
+ File *f; | |
+ | |
+ f = emalloc(sizeof(File)); | |
+ if(files[fcount] == 0){ | |
+ files[fcount] = Dstart(); | |
+ transcripts[fcount] = Dstart(); | |
+ } | |
+ f->buf = Bopen(files[fcount]); | |
+ f->transcript = Bopen(transcripts[fcount]); | |
+ if(++fcount == NDISC) | |
+ fcount = 0; | |
+ f->nrunes = 0; | |
+ f->markp = 0; | |
+ f->mod = 0; | |
+ f->dot.f = f; | |
+ f->ndot.f = f; | |
+ f->dev = ~0; | |
+ f->qid = ~0; | |
+ Strinit0(&f->name); | |
+ Strinit(&f->cache); | |
+ f->state = Unread; | |
+ Fmark(f, (Mod)0); | |
+ return f; | |
+} | |
+ | |
+void | |
+Fclose(File *f) | |
+{ | |
+ if(f == lastfile) | |
+ lastfile = 0; | |
+ Bterm(f->buf); | |
+ Bterm(f->transcript); | |
+ Strclose(&f->name); | |
+ Strclose(&f->cache); | |
+ if(f->rasp) | |
+ listfree(f->rasp); | |
+ free(f); | |
+} | |
+ | |
+void | |
+Finsert(File *f, String *str, Posn p1) | |
+{ | |
+ Buffer *t = f->transcript; | |
+ | |
+ if(f->state == Readerr) | |
+ return; | |
+ if(str->n == 0) | |
+ return; | |
+ if(str->n<0 || str->n>STRSIZE) | |
+ panic("Finsert"); | |
+ if(f->mod < modnum) | |
+ Fmark(f, modnum); | |
+ if(p1 < f->hiposn) | |
+ error(Esequence); | |
+ if(str->n >= BLOCKSIZE){ /* don't bother with the cache */ | |
+ Fflush(f); | |
+ puthdr_csl(t, 'i', str->n, p1); | |
+ Binsert(t, str, t->nrunes); | |
+ }else{ /* insert into the cache instead of the transcript */ | |
+ if(f->cp2==0 && f->cp1==0 && f->cache.n==0) /* empty ca… | |
+ f->cp1 = f->cp2 = p1; | |
+ if(p1-f->cp2>SKIP || f->cache.n+str->n>MAXCACHE-SKIP){ | |
+ Fflush(f); | |
+ f->cp1 = f->cp2 = p1; | |
+ } | |
+ if(f->cp2 != p1){ /* grab the piece in between */ | |
+ Rune buf[SKIP]; | |
+ String s; | |
+ Fchars(f, buf, f->cp2, p1); | |
+ s.s = buf; | |
+ s.n = p1-f->cp2; | |
+ Strinsert(&f->cache, &s, f->cache.n); | |
+ f->cp2 = p1; | |
+ } | |
+ Strinsert(&f->cache, str, f->cache.n); | |
+ } | |
+ if(f != cmd) | |
+ quitok = FALSE; | |
+ f->closeok = FALSE; | |
+ if(f->state == Clean) | |
+ state(f, Dirty); | |
+ f->hiposn = p1; | |
+} | |
+ | |
+void | |
+Fdelete(File *f, Posn p1, Posn p2) | |
+{ | |
+ if(f->state == Readerr) | |
+ return; | |
+ if(p1==p2) | |
+ return; | |
+ if(f->mod<modnum) | |
+ Fmark(f, modnum); | |
+ if(p1<f->hiposn) | |
+ error(Esequence); | |
+ if(p1-f->cp2>SKIP) | |
+ Fflush(f); | |
+ if(f->cp2==0 && f->cp1==0 && f->cache.n==0) /* empty cache */ | |
+ f->cp1 = f->cp2 = p1; | |
+ if(f->cp2 != p1){ /* grab the piece in between */ | |
+ if(f->cache.n+(p1-f->cp2)>MAXCACHE){ | |
+ Fflush(f); | |
+ f->cp1 = f->cp2 = p1; | |
+ }else{ | |
+ Rune buf[SKIP]; | |
+ String s; | |
+ Fchars(f, buf, f->cp2, p1); | |
+ s.s = buf; | |
+ s.n = p1-f->cp2; | |
+ Strinsert(&f->cache, &s, f->cache.n); | |
+ } | |
+ } | |
+ f->cp2 = p2; | |
+ if(f!=cmd) | |
+ quitok = FALSE; | |
+ f->closeok = FALSE; | |
+ if(f->state==Clean) | |
+ state(f, Dirty); | |
+ f->hiposn = p2; | |
+} | |
+ | |
+void | |
+Fflush(File *f) | |
+{ | |
+ Buffer *t = f->transcript; | |
+ Posn p1 = f->cp1, p2 = f->cp2; | |
+ | |
+ if(f->state == Readerr) | |
+ return; | |
+ if(p1 != p2) | |
+ puthdr_cll(t, 'd', p1, p2); | |
+ if(f->cache.n){ | |
+ puthdr_csl(t, 'i', f->cache.n, p2); | |
+ Binsert(t, &f->cache, t->nrunes); | |
+ Strzero(&f->cache); | |
+ } | |
+ f->cp1 = f->cp2 = 0; | |
+} | |
+ | |
+void | |
+Fsetname(File *f, String *s) | |
+{ | |
+ Buffer *t = f->transcript; | |
+ | |
+ if(f->state == Readerr) | |
+ return; | |
+ if(f->state == Unread){ /* This is setting initial file name */ | |
+ Strduplstr(&f->name, s); | |
+ sortname(f); | |
+ }else{ | |
+ if(f->mod < modnum) | |
+ Fmark(f, modnum); | |
+ puthdr_cs(t, 'f', s->n); | |
+ Binsert(t, s, t->nrunes); | |
+ } | |
+} | |
+ | |
+/* | |
+ * The heart of it all. Fupdate will run along the transcript list, executing | |
+ * the commands and converting them into their inverses for a later undo pass. | |
+ * The pass runs top to bottom, so addresses in the transcript are tracked | |
+ * (by the var. delta) so they stay valid during the operation. This causes | |
+ * all operations to appear to happen simultaneously, which is why the address… | |
+ * passed to Fdelete and Finsert never take into account other changes occurri… | |
+ * in this command (and is why things are done this way). | |
+ */ | |
+int | |
+Fupdate(File *f, int mktrans, int toterm) | |
+{ | |
+ Buffer *t = f->transcript; | |
+ Buffer *u = undobuf; | |
+ int n, ni; | |
+ Posn p0, p1, p2, p, deltadot = 0, deltamark = 0, delta = 0; | |
+ int changes = FALSE; | |
+ union Hdr buf; | |
+ Rune tmp[BLOCKSIZE+1]; /* +1 for NUL in 'f' case */ | |
+ | |
+ if(f->state == Readerr) | |
+ return FALSE; | |
+ if(lastfile && f!=lastfile) | |
+ Bclean(lastfile->transcript); /* save memory when multi… | |
+ lastfile = f; | |
+ Fflush(f); | |
+ if(f->marked) | |
+ p0 = f->markp+sizeof(Mark)/RUNESIZE; | |
+ else | |
+ p0 = 0; | |
+ f->dot = f->ndot; | |
+ while((n=Bread(t, (Rune*)&buf, sizeof buf/RUNESIZE, p0)) > 0){ | |
+ switch(buf.cs.c){ | |
+ default: | |
+ panic("unknown in Fupdate"); | |
+ case 'd': | |
+ p1 = buf.cll.l; | |
+ p2 = buf.cll.l1; | |
+ p0 += sizeof(struct _cll)/RUNESIZE; | |
+ if(p2 <= f->dot.r.p1) | |
+ deltadot -= p2-p1; | |
+ if(p2 <= f->mark.p1) | |
+ deltamark -= p2-p1; | |
+ p1 += delta, p2+=delta; | |
+ delta -= p2-p1; | |
+ if(!mktrans) | |
+ for(p = p1; p<p2; p+=ni){ | |
+ if(p2-p>BLOCKSIZE) | |
+ ni = BLOCKSIZE; | |
+ else | |
+ ni = p2-p; | |
+ puthdr_csl(u, 'i', ni, p1); | |
+ Bread(f->buf, tmp, ni, p); | |
+ Binsert(u, ftempstr(tmp, ni), u->nrune… | |
+ } | |
+ f->nrunes -= p2-p1; | |
+ Bdelete(f->buf, p1, p2); | |
+ changes = TRUE; | |
+ break; | |
+ | |
+ case 'f': | |
+ n = buf.cs.s; | |
+ p0 += sizeof(struct _cs)/RUNESIZE; | |
+ Strinsure(&genstr, n+1); | |
+ Bread(t, tmp, n, p0); | |
+ tmp[n] = 0; | |
+ p0 += n; | |
+ Strdupl(&genstr, tmp); | |
+ if(!mktrans){ | |
+ puthdr_cs(u, 'f', f->name.n); | |
+ Binsert(u, &f->name, u->nrunes); | |
+ } | |
+ Strduplstr(&f->name, &genstr); | |
+ sortname(f); | |
+ changes = TRUE; | |
+ break; | |
+ | |
+ case 'i': | |
+ n = buf.csl.s; | |
+ p1 = buf.csl.l; | |
+ p0 += sizeof(struct _csl)/RUNESIZE; | |
+ if(p1 < f->dot.r.p1) | |
+ deltadot += n; | |
+ if(p1 < f->mark.p1) | |
+ deltamark += n; | |
+ p1 += delta; | |
+ delta += n; | |
+ if(!mktrans) | |
+ puthdr_cll(u, 'd', p1, p1+n); | |
+ changes = TRUE; | |
+ f->nrunes += n; | |
+ while(n > 0){ | |
+ if(n > BLOCKSIZE) | |
+ ni = BLOCKSIZE; | |
+ else | |
+ ni = n; | |
+ Bread(t, tmp, ni, p0); | |
+ Binsert(f->buf, ftempstr(tmp, ni), p1); | |
+ n -= ni; | |
+ p1 += ni; | |
+ p0 += ni; | |
+ } | |
+ break; | |
+ } | |
+ } | |
+ toterminal(f, toterm); | |
+ f->dot.r.p1 += deltadot; | |
+ f->dot.r.p2 += deltadot; | |
+ if(f->dot.r.p1 > f->nrunes) | |
+ f->dot.r.p1 = f->nrunes; | |
+ if(f->dot.r.p2 > f->nrunes) | |
+ f->dot.r.p2 = f->nrunes; | |
+ f->mark.p1 += deltamark; | |
+ f->mark.p2 += deltamark; | |
+ if(f->mark.p1 > f->nrunes) | |
+ f->mark.p1 = f->nrunes; | |
+ if(f->mark.p2 > f->nrunes) | |
+ f->mark.p2 = f->nrunes; | |
+ if(n < 0) | |
+ panic("Fupdate read"); | |
+ if(f == cmd) | |
+ f->mod = 0; /* can't undo command file */ | |
+ if(p0 > f->markp+sizeof(Posn)/RUNESIZE){ /* for undo, this thro… | |
+ if(f->mod > 0){ /* can't undo the dawn of time */ | |
+ Bdelete(t, f->markp+sizeof(Mark)/RUNESIZE, t->nrunes); | |
+ /* copy the undo list back into the transcript */ | |
+ for(p = 0; p<u->nrunes; p+=ni){ | |
+ if(u->nrunes-p>BLOCKSIZE) | |
+ ni = BLOCKSIZE; | |
+ else | |
+ ni = u->nrunes-p; | |
+ Bread(u, tmp, ni, p); | |
+ Binsert(t, ftempstr(tmp, ni), t->nrunes); | |
+ } | |
+ } | |
+ Bdelete(u, (Posn)0, u->nrunes); | |
+ } | |
+ return f==cmd? FALSE : changes; | |
+} | |
+ | |
+void | |
+puthdr_csl(Buffer *b, char c, short s, Posn p) | |
+{ | |
+ struct _csl buf; | |
+ | |
+ if(p < 0) | |
+ panic("puthdr_csP"); | |
+ buf.c = c; | |
+ buf.s = s; | |
+ buf.l = p; | |
+ Binsert(b, ftempstr((Rune*)&buf, sizeof buf/RUNESIZE), b->nrunes); | |
+} | |
+ | |
+void | |
+puthdr_cs(Buffer *b, char c, short s) | |
+{ | |
+ struct _cs buf; | |
+ | |
+ buf.c = c; | |
+ buf.s = s; | |
+ Binsert(b, ftempstr((Rune*)&buf, sizeof buf/RUNESIZE), b->nrunes); | |
+} | |
+ | |
+void | |
+puthdr_M(Buffer *b, Posn p, Range dot, Range mk, Mod m, short s1) | |
+{ | |
+ Mark mark; | |
+ static first = 1; | |
+ | |
+ if(!first && p<0) | |
+ panic("puthdr_M"); | |
+ mark.p = p; | |
+ mark.dot = dot; | |
+ mark.mark = mk; | |
+ mark.m = m; | |
+ mark.s1 = s1; | |
+ Binsert(b, ftempstr((Rune *)&mark, sizeof mark/RUNESIZE), b->nrunes); | |
+} | |
+ | |
+void | |
+puthdr_cll(Buffer *b, char c, Posn p1, Posn p2) | |
+{ | |
+ struct _cll buf; | |
+ | |
+ if(p1<0 || p2<0) | |
+ panic("puthdr_cll"); | |
+ buf.c = c; | |
+ buf.l = p1; | |
+ buf.l1 = p2; | |
+ Binsert(b, ftempstr((Rune*)&buf, sizeof buf/RUNESIZE), b->nrunes); | |
+} | |
+ | |
+long | |
+Fchars(File *f, Rune *addr, Posn p1, Posn p2) | |
+{ | |
+ return Bread(f->buf, addr, p2-p1, p1); | |
+} | |
+ | |
+int | |
+Fgetcset(File *f, Posn p) | |
+{ | |
+ if(p<0 || p>f->nrunes) | |
+ panic("Fgetcset out of range"); | |
+ if((f->ngetc = Fchars(f, f->getcbuf, p, p+NGETC))<0) | |
+ panic("Fgetcset Bread fail"); | |
+ f->getcp = p; | |
+ f->getci = 0; | |
+ return f->ngetc; | |
+} | |
+ | |
+int | |
+Fbgetcset(File *f, Posn p) | |
+{ | |
+ if(p<0 || p>f->nrunes) | |
+ panic("Fbgetcset out of range"); | |
+ if((f->ngetc = Fchars(f, f->getcbuf, p<NGETC? (Posn)0 : p-NGETC, p))<0) | |
+ panic("Fbgetcset Bread fail"); | |
+ f->getcp = p; | |
+ f->getci = f->ngetc; | |
+ return f->ngetc; | |
+} | |
+ | |
+int | |
+Fgetcload(File *f, Posn p) | |
+{ | |
+ if(Fgetcset(f, p)){ | |
+ --f->ngetc; | |
+ f->getcp++; | |
+ return f->getcbuf[f->getci++]; | |
+ } | |
+ return -1; | |
+} | |
+ | |
+int | |
+Fbgetcload(File *f, Posn p) | |
+{ | |
+ if(Fbgetcset(f, p)){ | |
+ --f->getcp; | |
+ return f->getcbuf[--f->getci]; | |
+ } | |
+ return -1; | |
+} | |
+ | |
+static String* | |
+ftempstr(Rune *s, int n) | |
+{ | |
+ static String p; | |
+ | |
+ p.s = s; | |
+ p.n = n; | |
+ p.size = n; | |
+ return &p; | |
+} | |
diff --git a/sam/io.c b/sam/io.c | |
@@ -0,0 +1,257 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+#define NSYSFILE 3 | |
+#define NOFILE 128 | |
+ | |
+void | |
+checkqid(File *f) | |
+{ | |
+ int i, w; | |
+ File *g; | |
+ | |
+ w = whichmenu(f); | |
+ for(i=1; i<file.nused; i++){ | |
+ g = file.filepptr[i]; | |
+ if(w == i) | |
+ continue; | |
+ if(f->dev==g->dev && f->qid==g->qid) | |
+ warn_SS(Wdupfile, &f->name, &g->name); | |
+ } | |
+} | |
+ | |
+void | |
+writef(File *f) | |
+{ | |
+ Rune c; | |
+ Posn n; | |
+ char *name; | |
+ int i, samename, newfile; | |
+ ulong dev, qid; | |
+ long mtime, appendonly, length; | |
+ | |
+ newfile = 0; | |
+ samename = Strcmp(&genstr, &f->name) == 0; | |
+ name = Strtoc(&f->name); | |
+ i = statfile(name, &dev, &qid, &mtime, 0, 0); | |
+ if(i == -1) | |
+ newfile++; | |
+ else if(samename && | |
+ (f->dev!=dev || f->qid!=qid || f->date<mtime)){ | |
+ f->dev = dev; | |
+ f->qid = qid; | |
+ f->date = mtime; | |
+ warn_S(Wdate, &genstr); | |
+ return; | |
+ } | |
+ if(genc) | |
+ free(genc); | |
+ genc = Strtoc(&genstr); | |
+ if((io=create(genc, 1, 0666L)) < 0) | |
+ error_s(Ecreate, genc); | |
+ dprint("%s: ", genc); | |
+ if(statfd(io, 0, 0, 0, &length, &appendonly) > 0 && appendonly && leng… | |
+ error(Eappend); | |
+ n = writeio(f); | |
+ if(f->name.s[0]==0 || samename) | |
+ state(f, addr.r.p1==0 && addr.r.p2==f->nrunes? Clean : Dirty); | |
+ if(newfile) | |
+ dprint("(new file) "); | |
+ if(addr.r.p2>0 && Fchars(f, &c, addr.r.p2-1, addr.r.p2) && c!='\n') | |
+ warn(Wnotnewline); | |
+ closeio(n); | |
+ if(f->name.s[0]==0 || samename){ | |
+ if(statfile(name, &dev, &qid, &mtime, 0, 0) > 0){ | |
+ f->dev = dev; | |
+ f->qid = qid; | |
+ f->date = mtime; | |
+ checkqid(f); | |
+ } | |
+ } | |
+} | |
+ | |
+Posn | |
+readio(File *f, int *nulls, int setdate) | |
+{ | |
+ int n, b, w; | |
+ Rune *r; | |
+ Posn nt; | |
+ Posn p = addr.r.p2; | |
+ ulong dev, qid; | |
+ long mtime; | |
+ char buf[BLOCKSIZE+1], *s; | |
+ | |
+ *nulls = FALSE; | |
+ b = 0; | |
+ for(nt = 0; (n = read(io, buf+b, BLOCKSIZE-b))>0; nt+=(r-genbuf)){ | |
+ n += b; | |
+ b = 0; | |
+ r = genbuf; | |
+ s = buf; | |
+ while(n > 0){ | |
+ if((*r = *(uchar*)s) < Runeself){ | |
+ if(*r) | |
+ r++; | |
+ else | |
+ *nulls = TRUE; | |
+ --n; | |
+ s++; | |
+ continue; | |
+ } | |
+ if(fullrune(s, n)){ | |
+ w = chartorune(r, s); | |
+ if(*r) | |
+ r++; | |
+ else | |
+ *nulls = TRUE; | |
+ n -= w; | |
+ s += w; | |
+ continue; | |
+ } | |
+ b = n; | |
+ memmove(buf, s, b); | |
+ break; | |
+ } | |
+ Finsert(f, tmprstr(genbuf, r-genbuf), p); | |
+ } | |
+ if(b) | |
+ *nulls = TRUE; | |
+ if(*nulls) | |
+ warn(Wnulls); | |
+ if(setdate){ | |
+ if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){ | |
+ f->dev = dev; | |
+ f->qid = qid; | |
+ f->date = mtime; | |
+ checkqid(f); | |
+ } | |
+ } | |
+ return nt; | |
+} | |
+ | |
+Posn | |
+writeio(File *f) | |
+{ | |
+ int m, n; | |
+ Posn p = addr.r.p1; | |
+ char *c; | |
+ | |
+ while(p < addr.r.p2){ | |
+ if(addr.r.p2-p>BLOCKSIZE) | |
+ n = BLOCKSIZE; | |
+ else | |
+ n = addr.r.p2-p; | |
+ if(Fchars(f, genbuf, p, p+n)!=n) | |
+ panic("writef read"); | |
+ c = Strtoc(tmprstr(genbuf, n)); | |
+ m = strlen(c); | |
+ if (m < n) | |
+ panic("corrupted file"); | |
+ if(Write(io, c, m) != m){ | |
+ free(c); | |
+ if(p > 0) | |
+ p += n; | |
+ break; | |
+ } | |
+ free(c); | |
+ p += n; | |
+ } | |
+ return p-addr.r.p1; | |
+} | |
+void | |
+closeio(Posn p) | |
+{ | |
+ close(io); | |
+ io = 0; | |
+ if(p >= 0) | |
+ dprint("#%lu\n", p); | |
+} | |
+ | |
+int remotefd0 = 0; | |
+int remotefd1 = 1; | |
+ | |
+void | |
+bootterm(char *machine, char **argv, char **end) | |
+{ | |
+ int ph2t[2], pt2h[2]; | |
+ | |
+ if(machine){ | |
+ dup(remotefd0, 0); | |
+ dup(remotefd1, 1); | |
+ close(remotefd0); | |
+ close(remotefd1); | |
+ argv[0] = "samterm"; | |
+ *end = 0; | |
+ exec(samterm, argv); | |
+ fprint(2, "can't exec: "); | |
+ perror(samterm); | |
+ _exits("damn"); | |
+ } | |
+ if(pipe(ph2t)==-1 || pipe(pt2h)==-1) | |
+ panic("pipe"); | |
+ switch(fork()){ | |
+ case 0: | |
+ dup(ph2t[0], 0); | |
+ dup(pt2h[1], 1); | |
+ close(ph2t[0]); | |
+ close(ph2t[1]); | |
+ close(pt2h[0]); | |
+ close(pt2h[1]); | |
+ argv[0] = "samterm"; | |
+ *end = 0; | |
+ exec(samterm, argv); | |
+ fprint(2, "can't exec: "); | |
+ perror(samterm); | |
+ _exits("damn"); | |
+ case -1: | |
+ panic("can't fork samterm"); | |
+ } | |
+ dup(pt2h[0], 0); | |
+ dup(ph2t[1], 1); | |
+ close(ph2t[0]); | |
+ close(ph2t[1]); | |
+ close(pt2h[0]); | |
+ close(pt2h[1]); | |
+} | |
+ | |
+void | |
+connectto(char *machine) | |
+{ | |
+ int p1[2], p2[2]; | |
+ | |
+ if(pipe(p1)<0 || pipe(p2)<0){ | |
+ dprint("can't pipe\n"); | |
+ exits("pipe"); | |
+ } | |
+ remotefd0 = p1[0]; | |
+ remotefd1 = p2[1]; | |
+ switch(fork()){ | |
+ case 0: | |
+ dup(p2[0], 0); | |
+ dup(p1[1], 1); | |
+ close(p1[0]); | |
+ close(p1[1]); | |
+ close(p2[0]); | |
+ close(p2[1]); | |
+ execl(getenv("RSH") ? getenv("RSH") : RXPATH, getenv("RSH") ? … | |
+ dprint("can't exec %s\n", RXPATH); | |
+ exits("exec"); | |
+ | |
+ case -1: | |
+ dprint("can't fork\n"); | |
+ exits("fork"); | |
+ } | |
+ close(p1[1]); | |
+ close(p2[0]); | |
+} | |
+ | |
+void | |
+startup(char *machine, int Rflag, char **argv, char **end) | |
+{ | |
+ if(machine) | |
+ connectto(machine); | |
+ if(!Rflag) | |
+ bootterm(machine, argv, end); | |
+ downloaded = 1; | |
+ outTs(Hversion, VERSION); | |
+} | |
diff --git a/sam/list.c b/sam/list.c | |
@@ -0,0 +1,48 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+/* | |
+ * Check that list has room for one more element. | |
+ */ | |
+void | |
+growlist(List *l) | |
+{ | |
+ if(l->listptr==0 || l->nalloc==0){ | |
+ l->nalloc = INCR; | |
+ l->listptr = emalloc(INCR*sizeof(long)); | |
+ l->nused = 0; | |
+ }else if(l->nused == l->nalloc){ | |
+ l->listptr = erealloc(l->listptr, (l->nalloc+INCR)*sizeof(long… | |
+ memset((void*)(l->longptr+l->nalloc), 0, INCR*sizeof(long)); | |
+ l->nalloc += INCR; | |
+ } | |
+} | |
+ | |
+/* | |
+ * Remove the ith element from the list | |
+ */ | |
+void | |
+dellist(List *l, int i) | |
+{ | |
+ memmove(&l->longptr[i], &l->longptr[i+1], (l->nused-(i+1))*sizeof(long… | |
+ l->nused--; | |
+} | |
+ | |
+/* | |
+ * Add a new element, whose position is i, to the list | |
+ */ | |
+void | |
+inslist(List *l, int i, long val) | |
+{ | |
+ growlist(l); | |
+ memmove(&l->longptr[i+1], &l->longptr[i], (l->nused-i)*sizeof(long)); | |
+ l->longptr[i] = val; | |
+ l->nused++; | |
+} | |
+ | |
+void | |
+listfree(List *l) | |
+{ | |
+ free(l->listptr); | |
+ free(l); | |
+} | |
diff --git a/sam/mesg.c b/sam/mesg.c | |
@@ -0,0 +1,762 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+Header h; | |
+uchar indata[DATASIZE]; | |
+uchar outdata[2*DATASIZE+3]; /* room for overflow message */ | |
+uchar *inp; | |
+uchar *outp; | |
+uchar *outmsg = outdata; | |
+Posn cmdpt; | |
+Posn cmdptadv; | |
+Buffer *snarfbuf; | |
+int waitack; | |
+int noflush; | |
+int tversion; | |
+ | |
+long inlong(void); | |
+long invlong(void); | |
+int inshort(void); | |
+int inmesg(Tmesg); | |
+void setgenstr(File*, Posn, Posn); | |
+#ifdef DEBUG | |
+char *hname[] = { | |
+ [Hversion] "Hversion", | |
+ [Hbindname] "Hbindname", | |
+ [Hcurrent] "Hcurrent", | |
+ [Hnewname] "Hnewname", | |
+ [Hmovname] "Hmovname", | |
+ [Hgrow] "Hgrow", | |
+ [Hcheck0] "Hcheck0", | |
+ [Hcheck] "Hcheck", | |
+ [Hunlock] "Hunlock", | |
+ [Hdata] "Hdata", | |
+ [Horigin] "Horigin", | |
+ [Hunlockfile] "Hunlockfile", | |
+ [Hsetdot] "Hsetdot", | |
+ [Hgrowdata] "Hgrowdata", | |
+ [Hmoveto] "Hmoveto", | |
+ [Hclean] "Hclean", | |
+ [Hdirty] "Hdirty", | |
+ [Hcut] "Hcut", | |
+ [Hsetpat] "Hsetpat", | |
+ [Hdelname] "Hdelname", | |
+ [Hclose] "Hclose", | |
+ [Hsetsnarf] "Hsetsnarf", | |
+ [Hsnarflen] "Hsnarflen", | |
+ [Hack] "Hack", | |
+ [Hextcmd] "Hextcmd", | |
+ [Hexit] "Hexit", | |
+}; | |
+ | |
+char *tname[] = { | |
+ [Tversion] "Tversion", | |
+ [Tstartcmdfile] "Tstartcmdfile", | |
+ [Tcheck] "Tcheck", | |
+ [Trequest] "Trequest", | |
+ [Torigin] "Torigin", | |
+ [Tstartfile] "Tstartfile", | |
+ [Tworkfile] "Tworkfile", | |
+ [Ttype] "Ttype", | |
+ [Tcut] "Tcut", | |
+ [Tpaste] "Tpaste", | |
+ [Tsnarf] "Tsnarf", | |
+ [Tstartnewfile] "Tstartnewfile", | |
+ [Twrite] "Twrite", | |
+ [Tclose] "Tclose", | |
+ [Tlook] "Tlook", | |
+ [Tsearch] "Tsearch", | |
+ [Tsend] "Tsend", | |
+ [Tdclick] "Tdclick", | |
+ [Tstartsnarf] "Tstartsnarf", | |
+ [Tsetsnarf] "Tsetsnarf", | |
+ [Tack] "Tack", | |
+ [Texit] "Texit", | |
+}; | |
+ | |
+void | |
+journal(int out, char *s) | |
+{ | |
+ static int fd = 0; | |
+ | |
+ if(fd <= 0) | |
+ fd = create("/tmp/sam.out", 1, 0666L); | |
+ fprint(fd, "%s%s\n", out? "out: " : "in: ", s); | |
+} | |
+ | |
+void | |
+journaln(int out, long n) | |
+{ | |
+ char buf[32]; | |
+ sprint(buf, sizeof (long) > 4 ? "%ld" : "%d", n); | |
+ journal(out, buf); | |
+} | |
+#else | |
+#define journal(a, b) | |
+#define journaln(a, b) | |
+#endif | |
+ | |
+int | |
+rcvchar(void){ | |
+ static uchar buf[64]; | |
+ static i, nleft = 0; | |
+ | |
+ if(nleft <= 0){ | |
+ nleft = read(0, (char *)buf, sizeof buf); | |
+ if(nleft <= 0) | |
+ return -1; | |
+ i = 0; | |
+ } | |
+ --nleft; | |
+ return buf[i++]; | |
+} | |
+ | |
+int | |
+rcv(void){ | |
+ int c; | |
+ static state = 0; | |
+ static count = 0; | |
+ static i = 0; | |
+ | |
+ while((c=rcvchar()) != -1) | |
+ switch(state){ | |
+ case 0: | |
+ h.type = c; | |
+ state++; | |
+ break; | |
+ | |
+ case 1: | |
+ h.count0 = c; | |
+ state++; | |
+ break; | |
+ | |
+ case 2: | |
+ h.count1 = c; | |
+ count = h.count0|(h.count1<<8); | |
+ i = 0; | |
+ if(count > DATASIZE) | |
+ panic("count>DATASIZE"); | |
+ if(count == 0) | |
+ goto zerocount; | |
+ state++; | |
+ break; | |
+ | |
+ case 3: | |
+ indata[i++] = c; | |
+ if(i == count){ | |
+ zerocount: | |
+ indata[i] = 0; | |
+ state = count = 0; | |
+ return inmesg(h.type); | |
+ } | |
+ break; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+File * | |
+whichfile(int tag) | |
+{ | |
+ int i; | |
+ | |
+ for(i = 0; i<file.nused; i++) | |
+ if(file.filepptr[i]->tag==tag) | |
+ return file.filepptr[i]; | |
+ hiccough((char *)0); | |
+ return 0; | |
+} | |
+ | |
+int | |
+inmesg(Tmesg type) | |
+{ | |
+ Rune buf[1025]; | |
+ int i, m; | |
+ short s; | |
+ long l, l1; | |
+ File *f; | |
+ Posn p0, p1; | |
+ Range r; | |
+ String *str; | |
+ char *c; | |
+ Rune *rp; | |
+ | |
+ if(type > TMAX) | |
+ panic("inmesg"); | |
+ | |
+ journal(0, tname[type]); | |
+ | |
+ inp = indata; | |
+ switch(type){ | |
+ case -1: | |
+ panic("rcv error"); | |
+ | |
+ default: | |
+ fprint(2, "unknown type %d\n", type); | |
+ panic("rcv unknown"); | |
+ | |
+ case Tversion: | |
+ tversion = inshort(); | |
+ journaln(0, tversion); | |
+ break; | |
+ | |
+ case Tstartcmdfile: | |
+ l = invlong(); /* for 64-bit pointers */ | |
+ journaln(0, l); | |
+ Strdupl(&genstr, samname); | |
+ cmd = newfile(); | |
+ outTsv(Hbindname, cmd->tag, l); | |
+ outTs(Hcurrent, cmd->tag); | |
+ Fsetname(cmd, &genstr); | |
+ cmd->rasp = emalloc(sizeof(List)); | |
+ cmd->state = Clean; | |
+ if(cmdstr.n){ | |
+ Finsert(cmd, &cmdstr, 0L); | |
+ Strdelete(&cmdstr, 0L, (Posn)cmdstr.n); | |
+ } | |
+ Fupdate(cmd, FALSE, TRUE); | |
+ outT0(Hunlock); | |
+ break; | |
+ | |
+ case Tcheck: | |
+ /* go through whichfile to check the tag */ | |
+ outTs(Hcheck, whichfile(inshort())->tag); | |
+ break; | |
+ | |
+ case Trequest: | |
+ f = whichfile(inshort()); | |
+ p0 = inlong(); | |
+ p1 = p0+inshort(); | |
+ journaln(0, p0); | |
+ journaln(0, p1-p0); | |
+ if(f->state == Unread) | |
+ panic("Trequest: unread"); | |
+ if(p1>f->nrunes) | |
+ p1 = f->nrunes; | |
+ if(p0>f->nrunes) /* can happen e.g. scrolling during command */ | |
+ p0 = f->nrunes; | |
+ if(p0 == p1){ | |
+ i = 0; | |
+ r.p1 = r.p2 = p0; | |
+ }else{ | |
+ r = rdata(f->rasp, p0, p1-p0); | |
+ i = r.p2-r.p1; | |
+ if(Fchars(f, buf, r.p1, r.p2)!=i) | |
+ panic("Trequest 2"); | |
+ } | |
+ buf[i]=0; | |
+ outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1)); | |
+ break; | |
+ | |
+ case Torigin: | |
+ s = inshort(); | |
+ l = inlong(); | |
+ l1 = inlong(); | |
+ journaln(0, l1); | |
+ lookorigin(whichfile(s), l, l1); | |
+ break; | |
+ | |
+ case Tstartfile: | |
+ termlocked++; | |
+ f = whichfile(inshort()); | |
+ if(!f->rasp) /* this might be a duplicate message */ | |
+ f->rasp = emalloc(sizeof(List)); | |
+ current(f); | |
+ outTsv(Hbindname, f->tag, invlong()); /* for 64-bit poi… | |
+ outTs(Hcurrent, f->tag); | |
+ journaln(0, f->tag); | |
+ if(f->state == Unread) | |
+ load(f); | |
+ else{ | |
+ if(f->nrunes>0){ | |
+ rgrow(f->rasp, 0L, f->nrunes); | |
+ outTsll(Hgrow, f->tag, 0L, f->nrunes); | |
+ } | |
+ outTs(Hcheck0, f->tag); | |
+ moveto(f, f->dot.r); | |
+ } | |
+ break; | |
+ | |
+ case Tworkfile: | |
+ i = inshort(); | |
+ f = whichfile(i); | |
+ current(f); | |
+ f->dot.r.p1 = inlong(); | |
+ f->dot.r.p2 = inlong(); | |
+ f->tdot = f->dot.r; | |
+ journaln(0, i); | |
+ journaln(0, f->dot.r.p1); | |
+ journaln(0, f->dot.r.p2); | |
+ break; | |
+ | |
+ case Ttype: | |
+ f = whichfile(inshort()); | |
+ p0 = inlong(); | |
+ journaln(0, p0); | |
+ journal(0, (char*)inp); | |
+ str = tmpcstr((char*)inp); | |
+ i = str->n; | |
+ Finsert(f, str, p0); | |
+ if(Fupdate(f, FALSE, FALSE)) | |
+ modnum++; | |
+ if(f==cmd && p0==f->nrunes-i && i>0 && str->s[i-1]=='\n'){ | |
+ freetmpstr(str); | |
+ termlocked++; | |
+ termcommand(); | |
+ }else | |
+ freetmpstr(str); | |
+ f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this alrea… | |
+ f->tdot = f->dot.r; | |
+ break; | |
+ | |
+ case Tcut: | |
+ f = whichfile(inshort()); | |
+ p0 = inlong(); | |
+ p1 = inlong(); | |
+ journaln(0, p0); | |
+ journaln(0, p1); | |
+ Fdelete(f, p0, p1); | |
+ if(Fupdate(f, FALSE, FALSE)) | |
+ modnum++; | |
+ f->dot.r.p1 = f->dot.r.p2 = p0; | |
+ f->tdot = f->dot.r; /* terminal knows the value of dot alrea… | |
+ break; | |
+ | |
+ case Tpaste: | |
+ f = whichfile(inshort()); | |
+ p0 = inlong(); | |
+ journaln(0, p0); | |
+ for(l=0; l<snarfbuf->nrunes; l+=m){ | |
+ m = snarfbuf->nrunes-l; | |
+ if(m>BLOCKSIZE) | |
+ m = BLOCKSIZE; | |
+ Bread(snarfbuf, genbuf, m, l); | |
+ Finsert(f, tmprstr(genbuf, m), p0); | |
+ } | |
+ if(Fupdate(f, FALSE, TRUE)) | |
+ modnum++; | |
+ f->dot.r.p1 = p0; | |
+ f->dot.r.p2 = p0+snarfbuf->nrunes; | |
+ f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */ | |
+ telldot(f); | |
+ outTs(Hunlockfile, f->tag); | |
+ break; | |
+ | |
+ case Tsnarf: | |
+ i = inshort(); | |
+ p0 = inlong(); | |
+ p1 = inlong(); | |
+ snarf(whichfile(i), p0, p1, snarfbuf, 0); | |
+ break; | |
+ | |
+ case Tstartnewfile: | |
+ l = invlong(); | |
+ Strdupl(&genstr, empty); | |
+ f = newfile(); | |
+ f->rasp = emalloc(sizeof(List)); | |
+ outTsv(Hbindname, f->tag, l); | |
+ Fsetname(f, &genstr); | |
+ outTs(Hcurrent, f->tag); | |
+ current(f); | |
+ load(f); | |
+ break; | |
+ | |
+ case Twrite: | |
+ termlocked++; | |
+ i = inshort(); | |
+ journaln(0, i); | |
+ f = whichfile(i); | |
+ addr.r.p1 = 0; | |
+ addr.r.p2 = f->nrunes; | |
+ if(f->name.s[0] == 0) | |
+ error(Enoname); | |
+ Strduplstr(&genstr, &f->name); | |
+ writef(f); | |
+ break; | |
+ | |
+ case Tclose: | |
+ termlocked++; | |
+ i = inshort(); | |
+ journaln(0, i); | |
+ f = whichfile(i); | |
+ current(f); | |
+ trytoclose(f); | |
+ /* if trytoclose fails, will error out */ | |
+ delete(f); | |
+ break; | |
+ | |
+ case Tlook: | |
+ f = whichfile(inshort()); | |
+ termlocked++; | |
+ p0 = inlong(); | |
+ p1 = inlong(); | |
+ journaln(0, p0); | |
+ journaln(0, p1); | |
+ setgenstr(f, p0, p1); | |
+ for(l = 0; l<genstr.n; l++){ | |
+ i = genstr.s[l]; | |
+ if(utfrune(".*+?(|)\\[]^$", i)) | |
+ Strinsert(&genstr, tmpcstr("\\"), l++); | |
+ } | |
+ Straddc(&genstr, '\0'); | |
+ nextmatch(f, &genstr, p1, 1); | |
+ moveto(f, sel.p[0]); | |
+ break; | |
+ | |
+ case Tsearch: | |
+ termlocked++; | |
+ if(curfile == 0) | |
+ error(Enofile); | |
+ if(lastpat.s[0] == 0) | |
+ panic("Tsearch"); | |
+ nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1); | |
+ moveto(curfile, sel.p[0]); | |
+ break; | |
+ | |
+ case Tsend: | |
+ termlocked++; | |
+ inshort(); /* ignored */ | |
+ p0 = inlong(); | |
+ p1 = inlong(); | |
+ setgenstr(cmd, p0, p1); | |
+ Bdelete(snarfbuf, (Posn)0, snarfbuf->nrunes); | |
+ Binsert(snarfbuf, &genstr, (Posn)0); | |
+ outTl(Hsnarflen, genstr.n); | |
+ if(genstr.s[genstr.n-1] != '\n') | |
+ Straddc(&genstr, '\n'); | |
+ Finsert(cmd, &genstr, cmd->nrunes); | |
+ Fupdate(cmd, FALSE, TRUE); | |
+ cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nrunes; | |
+ telldot(cmd); | |
+ termcommand(); | |
+ break; | |
+ | |
+ case Tdclick: | |
+ f = whichfile(inshort()); | |
+ p1 = inlong(); | |
+ doubleclick(f, p1); | |
+ f->tdot.p1 = f->tdot.p2 = p1; | |
+ telldot(f); | |
+ outTs(Hunlockfile, f->tag); | |
+ break; | |
+ | |
+ case Tstartsnarf: | |
+ if (snarfbuf->nrunes <= 0) { /* nothing to export */ | |
+ outTs(Hsetsnarf, 0); | |
+ break; | |
+ } | |
+ c = 0; | |
+ i = 0; | |
+ m = snarfbuf->nrunes; | |
+ if(m > 32000) { /* tmprstr stores len in a shor… | |
+ m = 32000; | |
+ dprint("?warning: snarf buffer truncated\n"); | |
+ } | |
+ rp = malloc(m*sizeof(Rune)); | |
+ if(rp){ | |
+ Bread(snarfbuf, rp, m, 0); | |
+ c = Strtoc(tmprstr(rp, m)); | |
+ free(rp); | |
+ i = strlen(c); | |
+ } | |
+ outTs(Hsetsnarf, i); | |
+ if(c){ | |
+ Write(1, c, i); | |
+ free(c); | |
+ } else | |
+ dprint("snarf buffer too long\n"); | |
+ break; | |
+ | |
+ case Tsetsnarf: | |
+ m = inshort(); | |
+ if(m > SNARFSIZE) | |
+ error(Etoolong); | |
+ c = malloc(m+1); | |
+ if(c){ | |
+ for(i=0; i<m; i++) | |
+ c[i] = rcvchar(); | |
+ c[m] = 0; | |
+ str = tmpcstr(c); | |
+ free(c); | |
+ Bdelete(snarfbuf, (Posn)0, snarfbuf->nrunes); | |
+ Binsert(snarfbuf, str, (Posn)0); | |
+ freetmpstr(str); | |
+ outT0(Hunlock); | |
+ } | |
+ break; | |
+ | |
+ case Tack: | |
+ waitack = 0; | |
+ break; | |
+ | |
+ case Texit: | |
+ exits(0); | |
+ } | |
+ return TRUE; | |
+} | |
+ | |
+void | |
+snarf(File *f, Posn p1, Posn p2, Buffer *buf, int emptyok) | |
+{ | |
+ Posn l; | |
+ int i; | |
+ | |
+ if(!emptyok && p1==p2) | |
+ return; | |
+ Bdelete(buf, (Posn)0, buf->nrunes); | |
+ /* Stage through genbuf to avoid compaction problems (vestigial) */ | |
+ for(l=p1; l<p2; l+=i){ | |
+ i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l; | |
+ Fchars(f, genbuf, l, l+i); | |
+ Binsert(buf, tmprstr(genbuf, i), buf->nrunes); | |
+ } | |
+} | |
+ | |
+int | |
+inshort(void) | |
+{ | |
+ ushort n; | |
+ | |
+ n = inp[0] | (inp[1]<<8); | |
+ inp += 2; | |
+ return n; | |
+} | |
+ | |
+long | |
+inlong(void) | |
+{ | |
+ ulong n; | |
+ | |
+ n = inp[0] | (inp[1]<<8) | (inp[2]<<16) | (inp[3]<<24); | |
+ inp += 4; | |
+ return n; | |
+} | |
+ | |
+long | |
+invlong(void) | |
+{ | |
+ ulong n; | |
+ | |
+ n = (inp[7]<<24) | (inp[6]<<16) | (inp[5]<<8) | inp[4]; | |
+ n = (n<<16) | (inp[3]<<8) | inp[2]; | |
+ n = (n<<16) | (inp[1]<<8) | inp[0]; | |
+ inp += 8; | |
+ return n; | |
+} | |
+ | |
+void | |
+setgenstr(File *f, Posn p0, Posn p1) | |
+{ | |
+ if(p0 != p1){ | |
+ if(p1-p0 >= TBLOCKSIZE) | |
+ error(Etoolong); | |
+ Strinsure(&genstr, p1-p0); | |
+ Fchars(f, genbuf, p0, p1); | |
+ memmove(genstr.s, genbuf, RUNESIZE*(p1-p0)); | |
+ genstr.n = p1-p0; | |
+ }else{ | |
+ if(snarfbuf->nrunes == 0) | |
+ error(Eempty); | |
+ if(snarfbuf->nrunes > TBLOCKSIZE) | |
+ error(Etoolong); | |
+ Bread(snarfbuf, genbuf, snarfbuf->nrunes, (Posn)0); | |
+ Strinsure(&genstr, snarfbuf->nrunes); | |
+ memmove(genstr.s, genbuf, RUNESIZE*snarfbuf->nrunes); | |
+ genstr.n = snarfbuf->nrunes; | |
+ } | |
+} | |
+ | |
+void | |
+outT0(Hmesg type) | |
+{ | |
+ outstart(type); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTl(Hmesg type, long l) | |
+{ | |
+ outstart(type); | |
+ outlong(l); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTs(Hmesg type, int s) | |
+{ | |
+ outstart(type); | |
+ journaln(1, s); | |
+ outshort(s); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outS(String *s) | |
+{ | |
+ char *c; | |
+ int i; | |
+ | |
+ c = Strtoc(s); | |
+ i = strlen(c); | |
+ outcopy(i, c); | |
+ if(i > 99) | |
+ c[99] = 0; | |
+ journaln(1, i); | |
+ journal(1, c); | |
+ free(c); | |
+} | |
+ | |
+void | |
+outTsS(Hmesg type, int s1, String *s) | |
+{ | |
+ outstart(type); | |
+ outshort(s1); | |
+ outS(s); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTslS(Hmesg type, int s1, Posn l1, String *s) | |
+{ | |
+ outstart(type); | |
+ outshort(s1); | |
+ journaln(1, s1); | |
+ outlong(l1); | |
+ journaln(1, l1); | |
+ outS(s); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTS(Hmesg type, String *s) | |
+{ | |
+ outstart(type); | |
+ outS(s); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTsllS(Hmesg type, int s1, Posn l1, Posn l2, String *s) | |
+{ | |
+ outstart(type); | |
+ outshort(s1); | |
+ outlong(l1); | |
+ outlong(l2); | |
+ journaln(1, l1); | |
+ journaln(1, l2); | |
+ outS(s); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTsll(Hmesg type, int s, Posn l1, Posn l2) | |
+{ | |
+ outstart(type); | |
+ outshort(s); | |
+ outlong(l1); | |
+ outlong(l2); | |
+ journaln(1, l1); | |
+ journaln(1, l2); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTsl(Hmesg type, int s, Posn l) | |
+{ | |
+ outstart(type); | |
+ outshort(s); | |
+ outlong(l); | |
+ journaln(1, l); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTsv(Hmesg type, int s, Posn l) | |
+{ | |
+ outstart(type); | |
+ outshort(s); | |
+ outvlong((void*)l); | |
+ journaln(1, l); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outstart(Hmesg type) | |
+{ | |
+ journal(1, hname[type]); | |
+ outmsg[0] = type; | |
+ outp = outmsg+3; | |
+} | |
+ | |
+void | |
+outcopy(int count, void *data) | |
+{ | |
+ memmove(outp, data, count); | |
+ outp += count; | |
+} | |
+ | |
+void | |
+outshort(int s) | |
+{ | |
+ *outp++ = s; | |
+ *outp++ = s>>8; | |
+} | |
+ | |
+void | |
+outlong(long l) | |
+{ | |
+ *outp++ = l; | |
+ *outp++ = l>>8; | |
+ *outp++ = l>>16; | |
+ *outp++ = l>>24; | |
+} | |
+ | |
+void | |
+outvlong(void *v) | |
+{ | |
+ int i; | |
+ ulong l; | |
+ | |
+ l = (ulong) v; | |
+ for(i = 0; i < 8; i++, l >>= 8) | |
+ *outp++ = l; | |
+} | |
+ | |
+void | |
+outsend(void) | |
+{ | |
+ int outcount; | |
+ | |
+ outcount = outp-outmsg; | |
+ outcount -= 3; | |
+ outmsg[1] = outcount; | |
+ outmsg[2] = outcount>>8; | |
+ outmsg = outp; | |
+ if(!noflush){ | |
+ outcount = outmsg-outdata; | |
+ if (write(1, (char*) outdata, outcount) != outcount) | |
+ rescue(); | |
+ outmsg = outdata; | |
+ return; | |
+ } | |
+ if(outmsg < outdata+DATASIZE) | |
+ return; | |
+ outflush(); | |
+} | |
+ | |
+void | |
+outflush(void) | |
+{ | |
+ if(outmsg == outdata) | |
+ return; | |
+ noflush = 0; | |
+ outT0(Hack); | |
+ waitack = 1; | |
+ do | |
+ if(rcv() == 0){ | |
+ rescue(); | |
+ exits("eof"); | |
+ } | |
+ while(waitack); | |
+ outmsg = outdata; | |
+ noflush = 1; | |
+} | |
diff --git a/sam/mesg.h b/sam/mesg.h | |
@@ -0,0 +1,102 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#define VERSION 0 | |
+ | |
+#define TBLOCKSIZE 512 /* largest piece of text sent t… | |
+#define DATASIZE (UTFmax*TBLOCKSIZE+30) /* ... including protocol head… | |
+#define SNARFSIZE 16384 /* maximum length of exchanged s… | |
+/* | |
+ * Messages originating at the terminal | |
+ */ | |
+typedef enum Tmesg | |
+{ | |
+ Tversion, /* version */ | |
+ Tstartcmdfile, /* terminal just opened command frame */ | |
+ Tcheck, /* ask host to poke with Hcheck */ | |
+ Trequest, /* request data to fill a hole */ | |
+ Torigin, /* gimme an Horigin near here */ | |
+ Tstartfile, /* terminal just opened a file's frame */ | |
+ Tworkfile, /* set file to which commands apply */ | |
+ Ttype, /* add some characters, but terminal already kno… | |
+ Tcut, | |
+ Tpaste, | |
+ Tsnarf, | |
+ Tstartnewfile, /* terminal just opened a new frame */ | |
+ Twrite, /* write file */ | |
+ Tclose, /* terminal requests file close; check mod. sta… | |
+ Tlook, /* search for literal current text */ | |
+ Tsearch, /* search for last regular expression */ | |
+ Tsend, /* pretend he typed stuff */ | |
+ Tdclick, /* double click */ | |
+ Tstartsnarf, /* initiate snarf buffer exchange */ | |
+ Tsetsnarf, /* remember string in snarf buffer */ | |
+ Tack, /* acknowledge Hack */ | |
+ Texit, /* exit */ | |
+ TMAX | |
+}Tmesg; | |
+/* | |
+ * Messages originating at the host | |
+ */ | |
+typedef enum Hmesg | |
+{ | |
+ Hversion, /* version */ | |
+ Hbindname, /* attach name[0] to text in terminal */ | |
+ Hcurrent, /* make named file the typing file */ | |
+ Hnewname, /* create "" name in menu */ | |
+ Hmovname, /* move file name in menu */ | |
+ Hgrow, /* insert space in rasp */ | |
+ Hcheck0, /* see below */ | |
+ Hcheck, /* ask terminal to check whether it needs more … | |
+ Hunlock, /* command is finished; user can do things */ | |
+ Hdata, /* store this data in previously allocated space… | |
+ Horigin, /* set origin of file/frame in terminal */ | |
+ Hunlockfile, /* unlock file in terminal */ | |
+ Hsetdot, /* set dot in terminal */ | |
+ Hgrowdata, /* Hgrow + Hdata folded together */ | |
+ Hmoveto, /* scrolling, context search, etc. */ | |
+ Hclean, /* named file is now 'clean' */ | |
+ Hdirty, /* named file is now 'dirty' */ | |
+ Hcut, /* remove space from rasp */ | |
+ Hsetpat, /* set remembered regular expression */ | |
+ Hdelname, /* delete file name from menu */ | |
+ Hclose, /* close file and remove from menu */ | |
+ Hsetsnarf, /* remember string in snarf buffer */ | |
+ Hsnarflen, /* report length of implicit snarf */ | |
+ Hack, /* request acknowledgement */ | |
+ Hexit, | |
+ Hextcmd, /* execute a external command */ | |
+ HMAX | |
+}Hmesg; | |
+typedef struct Header{ | |
+ uchar type; /* one of the above */ | |
+ uchar count0; /* low bits of data size */ | |
+ uchar count1; /* high bits of data size */ | |
+ uchar data[1]; /* variable size */ | |
+}Header; | |
+/* | |
+ * File transfer protocol schematic, a la Holzmann | |
+ * | |
+ * proc h | |
+ * { pvar n = 0; | |
+ * queue h[4]; | |
+ * | |
+ * do | |
+ * :: (n < N) -> n++; t!Hgrow | |
+ * :: (n == N) -> n++; t!Hcheck0 | |
+ * :: h?Trequest -> t!Hdata | |
+ * :: h?Tcheck -> t!Hcheck | |
+ * od | |
+ * } | |
+ * proc t | |
+ * { queue t[4]; | |
+ * do | |
+ * :: t?Hgrow -> h!Trequest | |
+ * :: t?Hdata -> skip | |
+ * :: t?Hcheck0 -> h!Tcheck | |
+ * :: t?Hcheck -> | |
+ * if | |
+ * :: break | |
+ * :: h!Trequest; h!Tcheck | |
+ * fi | |
+ * od | |
+ * } | |
+ */ | |
diff --git a/sam/moveto.c b/sam/moveto.c | |
@@ -0,0 +1,168 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+void | |
+moveto(File *f, Range r) | |
+{ | |
+ Posn p1 = r.p1, p2 = r.p2; | |
+ | |
+ f->dot.r.p1 = p1; | |
+ f->dot.r.p2 = p2; | |
+ if(f->rasp){ | |
+ telldot(f); | |
+ outTsl(Hmoveto, f->tag, f->dot.r.p1); | |
+ } | |
+} | |
+ | |
+void | |
+telldot(File *f) | |
+{ | |
+ if(f->rasp == 0) | |
+ panic("telldot"); | |
+ if(f->dot.r.p1==f->tdot.p1 && f->dot.r.p2==f->tdot.p2) | |
+ return; | |
+ outTsll(Hsetdot, f->tag, f->dot.r.p1, f->dot.r.p2); | |
+ f->tdot = f->dot.r; | |
+} | |
+ | |
+void | |
+tellpat(void) | |
+{ | |
+ outTS(Hsetpat, &lastpat); | |
+ patset = FALSE; | |
+} | |
+ | |
+#define CHARSHIFT 128 | |
+ | |
+void | |
+lookorigin(File *f, Posn p0, Posn ls) | |
+{ | |
+ int nl, nc, c; | |
+ Posn oldp0; | |
+ | |
+ if(p0 > f->nrunes) | |
+ p0 = f->nrunes; | |
+ oldp0 = p0; | |
+ Fgetcset(f, p0); | |
+ for(nl=nc=c=0; c!=-1 && nl<ls && nc<ls*CHARSHIFT; nc++) | |
+ if((c=Fbgetc(f)) == '\n'){ | |
+ nl++; | |
+ oldp0 = p0-nc; | |
+ } | |
+ if(c == -1) | |
+ p0 = 0; | |
+ else if(nl==0){ | |
+ if(p0>=CHARSHIFT/2) | |
+ p0-=CHARSHIFT/2; | |
+ else | |
+ p0 = 0; | |
+ }else | |
+ p0 = oldp0; | |
+ outTsl(Horigin, f->tag, p0); | |
+} | |
+ | |
+int | |
+alnum(int c) | |
+{ | |
+ /* | |
+ * Hard to get absolutely right. Use what we know about ASCII | |
+ * and assume anything above the Latin control characters is | |
+ * potentially an alphanumeric. | |
+ */ | |
+ if(c<=' ') | |
+ return 0; | |
+ if(0x7F<=c && c<=0xA0) | |
+ return 0; | |
+ if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) | |
+ return 0; | |
+ return 1; | |
+} | |
+ | |
+int | |
+clickmatch(File *f, int cl, int cr, int dir) | |
+{ | |
+ int c; | |
+ int nest = 1; | |
+ | |
+ while((c=(dir>0? Fgetc(f) : Fbgetc(f))) > 0) | |
+ if(c == cr){ | |
+ if(--nest==0) | |
+ return 1; | |
+ }else if(c == cl) | |
+ nest++; | |
+ return cl=='\n' && nest==1; | |
+} | |
+ | |
+Rune* | |
+strrune(Rune *s, Rune c) | |
+{ | |
+ Rune c1; | |
+ | |
+ if(c == 0) { | |
+ while(*s++) | |
+ ; | |
+ return s-1; | |
+ } | |
+ | |
+ while(c1 = *s++) | |
+ if(c1 == c) | |
+ return s-1; | |
+ return 0; | |
+} | |
+ | |
+void | |
+doubleclick(File *f, Posn p1) | |
+{ | |
+ int c, i; | |
+ Rune *r, *l; | |
+ | |
+ if(p1 > f->nrunes) | |
+ return; | |
+ f->dot.r.p1 = f->dot.r.p2 = p1; | |
+ for(i=0; left[i]; i++){ | |
+ l = left[i]; | |
+ r = right[i]; | |
+ /* try left match */ | |
+ if(p1 == 0){ | |
+ Fgetcset(f, p1); | |
+ c = '\n'; | |
+ }else{ | |
+ Fgetcset(f, p1-1); | |
+ c = Fgetc(f); | |
+ } | |
+ if(c!=-1 && strrune(l, c)){ | |
+ if(clickmatch(f, c, r[strrune(l, c)-l], 1)){ | |
+ f->dot.r.p1 = p1; | |
+ f->dot.r.p2 = f->getcp-(c!='\n'); | |
+ } | |
+ return; | |
+ } | |
+ /* try right match */ | |
+ if(p1 == f->nrunes){ | |
+ Fbgetcset(f, p1); | |
+ c = '\n'; | |
+ }else{ | |
+ Fbgetcset(f, p1+1); | |
+ c = Fbgetc(f); | |
+ } | |
+ if(c!=-1 && strrune(r, c)){ | |
+ if(clickmatch(f, c, l[strrune(r, c)-r], -1)){ | |
+ f->dot.r.p1 = f->getcp; | |
+ if(c!='\n' || f->getcp!=0 || | |
+ (Fgetcset(f, (Posn)0),Fgetc(f))=='\n') | |
+ f->dot.r.p1++; | |
+ f->dot.r.p2 = p1+(p1<f->nrunes && c=='\n'); | |
+ } | |
+ return; | |
+ } | |
+ } | |
+ /* try filling out word to right */ | |
+ Fgetcset(f, p1); | |
+ while((c=Fgetc(f))!=-1 && alnum(c)) | |
+ f->dot.r.p2++; | |
+ /* try filling out word to left */ | |
+ Fbgetcset(f, p1); | |
+ while((c=Fbgetc(f))!=-1 && alnum(c)) | |
+ f->dot.r.p1--; | |
+} | |
+ | |
diff --git a/sam/multi.c b/sam/multi.c | |
@@ -0,0 +1,91 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+List file; | |
+ushort tag; | |
+ | |
+File * | |
+newfile(void) | |
+{ | |
+ File *f; | |
+ | |
+ inslist(&file, 0, (long)(f = Fopen())); | |
+ f->tag = tag++; | |
+ if(downloaded) | |
+ outTs(Hnewname, f->tag); | |
+ /* already sorted; file name is "" */ | |
+ return f; | |
+} | |
+ | |
+int | |
+whichmenu(File *f) | |
+{ | |
+ int i; | |
+ | |
+ for(i=0; i<file.nused; i++) | |
+ if(file.filepptr[i]==f) | |
+ return i; | |
+ return -1; | |
+} | |
+ | |
+void | |
+delfile(File *f) | |
+{ | |
+ int w = whichmenu(f); | |
+ | |
+ if(w < 0) /* e.g. x/./D */ | |
+ return; | |
+ if(downloaded) | |
+ outTs(Hdelname, f->tag); | |
+ dellist(&file, w); | |
+ Fclose(f); | |
+} | |
+ | |
+void | |
+sortname(File *f) | |
+{ | |
+ int i, cmp, w; | |
+ int dupwarned; | |
+ | |
+ w = whichmenu(f); | |
+ dupwarned = FALSE; | |
+ dellist(&file, w); | |
+ if(f == cmd) | |
+ i = 0; | |
+ else for(i=0; i<file.nused; i++){ | |
+ cmp = Strcmp(&f->name, &file.filepptr[i]->name); | |
+ if(cmp==0 && !dupwarned){ | |
+ dupwarned = TRUE; | |
+ warn_S(Wdupname, &f->name); | |
+ }else if(cmp<0 && (i>0 || cmd==0)) | |
+ break; | |
+ } | |
+ inslist(&file, i, (long)f); | |
+ if(downloaded) | |
+ outTsS(Hmovname, f->tag, &f->name); | |
+} | |
+ | |
+void | |
+state(File *f, int cleandirty) | |
+{ | |
+ if(f == cmd) | |
+ return; | |
+ if(downloaded && whichmenu(f)>=0){ /* else flist or menu */ | |
+ if(f->state==Dirty && cleandirty!=Dirty) | |
+ outTs(Hclean, f->tag); | |
+ else if(f->state!=Dirty && cleandirty==Dirty) | |
+ outTs(Hdirty, f->tag); | |
+ } | |
+ f->state = cleandirty; | |
+} | |
+ | |
+File * | |
+lookfile(String *s) | |
+{ | |
+ int i; | |
+ | |
+ for(i=0; i<file.nused; i++) | |
+ if(Strcmp(&file.filepptr[i]->name, s) == 0) | |
+ return file.filepptr[i]; | |
+ return 0; | |
+} | |
diff --git a/sam/parse.h b/sam/parse.h | |
@@ -0,0 +1,69 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+typedef struct Addr Addr; | |
+typedef struct Cmd Cmd; | |
+struct Addr | |
+{ | |
+ char type; /* # (char addr), l (line addr), / ? . $ + - … | |
+ union{ | |
+ String *re; | |
+ Addr *aleft; /* left side of , and ; */ | |
+ } g; | |
+ Posn num; | |
+ Addr *next; /* or right side of , and ; … | |
+}; | |
+ | |
+#define are g.re | |
+#define left g.aleft | |
+ | |
+struct Cmd | |
+{ | |
+ Addr *addr; /* address (range of text) */ | |
+ String *re; /* regular expression for e.… | |
+ union{ | |
+ Cmd *cmd; /* target of x, g, {, etc. */ | |
+ String *text; /* text of a, c, i; rhs of… | |
+ Addr *addr; /* address for m, t */ | |
+ } g; | |
+ Cmd *next; /* pointer to next element in… | |
+ short num; | |
+ ushort flag; /* whatever */ | |
+ ushort cmdc; /* command character; 'x' e… | |
+}; | |
+ | |
+#define ccmd g.cmd | |
+#define ctext g.text | |
+#define caddr g.addr | |
+ | |
+extern struct cmdtab{ | |
+ ushort cmdc; /* command character */ | |
+ uchar text; /* takes a textual argument? */ | |
+ uchar regexp; /* takes a regular expression? */ | |
+ uchar addr; /* takes an address (m or t)? */ | |
+ uchar defcmd; /* default command; 0==>none */ | |
+ uchar defaddr; /* default address */ | |
+ uchar count; /* takes a count e.g. s2/// */ | |
+ char *token; /* takes text terminated by one of … | |
+ int (*fn)(File*, Cmd*); /* function to call with parse t… | |
+}cmdtab[]; | |
+ | |
+enum Defaddr{ /* default addresses */ | |
+ aNo, | |
+ aDot, | |
+ aAll | |
+}; | |
+ | |
+int nl_cmd(File*, Cmd*), a_cmd(File*, Cmd*), b_cmd(File*, Cmd*); | |
+int c_cmd(File*, Cmd*), cd_cmd(File*, Cmd*), d_cmd(File*, Cmd*); | |
+int D_cmd(File*, Cmd*), e_cmd(File*, Cmd*); | |
+int f_cmd(File*, Cmd*), g_cmd(File*, Cmd*), i_cmd(File*, Cmd*); | |
+int k_cmd(File*, Cmd*), m_cmd(File*, Cmd*), n_cmd(File*, Cmd*); | |
+int p_cmd(File*, Cmd*), q_cmd(File*, Cmd*); | |
+int s_cmd(File*, Cmd*), u_cmd(File*, Cmd*), w_cmd(File*, Cmd*); | |
+int x_cmd(File*, Cmd*), X_cmd(File*, Cmd*), plan9_cmd(File*, Cmd*); | |
+int eq_cmd(File*, Cmd*); | |
+ | |
+ | |
+String *getregexp(int); | |
+Addr *newaddr(void); | |
+Address address(Addr*, Address, int); | |
+int cmdexec(File*, Cmd*); | |
diff --git a/sam/plan9.c b/sam/plan9.c | |
@@ -0,0 +1,174 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+Rune samname[] = L"~~sam~~"; | |
+ | |
+Rune *left[]= { | |
+ L"{[(<«", | |
+ L"\n", | |
+ L"'\"`", | |
+ 0 | |
+}; | |
+Rune *right[]= { | |
+ L"}])>»", | |
+ L"\n", | |
+ L"'\"`", | |
+ 0 | |
+}; | |
+ | |
+char RSAM[] = "sam"; | |
+char SAMTERM[] = "/bin/aux/samterm"; | |
+char HOME[] = "home"; | |
+char TMPDIR[] = "/tmp"; | |
+char SH[] = "rc"; | |
+char SHPATH[] = "/bin/rc"; | |
+char RX[] = "rx"; | |
+char RXPATH[] = "/bin/rx"; | |
+char SAMSAVECMD[] = "/bin/rc\n/sys/lib/samsave"; | |
+ | |
+void | |
+dprint(char *z, ...) | |
+{ | |
+ char buf[BLOCKSIZE]; | |
+ va_list arg; | |
+ | |
+ va_start(arg, z); | |
+ doprint(buf, &buf[BLOCKSIZE], z, arg); | |
+ va_end(arg); | |
+ termwrite(buf); | |
+} | |
+ | |
+void | |
+print_ss(char *s, String *a, String *b) | |
+{ | |
+ dprint("?warning: %s: `%.*S' and `%.*S'\n", s, a->n, a->s, b->n, b->s); | |
+} | |
+ | |
+void | |
+print_s(char *s, String *a) | |
+{ | |
+ dprint("?warning: %s `%.*S'\n", s, a->n, a->s); | |
+} | |
+ | |
+char* | |
+getuser(void) | |
+{ | |
+ static char user[NAMELEN]; | |
+ int fd; | |
+ | |
+ if(user[0] == 0){ | |
+ fd = open("/dev/user", 0); | |
+ if(fd<0 || read(fd, user, sizeof user)<=0) | |
+ strcpy(user, "none"); | |
+ close(fd); | |
+ } | |
+ return user; | |
+} | |
+ | |
+int | |
+statfile(char *name, ulong *dev, ulong *id, long *time, long *length, long *ap… | |
+{ | |
+ Dir dirb; | |
+ | |
+ if(dirstat(name, &dirb) == -1) | |
+ return -1; | |
+ if(dev) | |
+ *dev = dirb.type|(dirb.dev<<16); | |
+ if(id) | |
+ *id = dirb.qid.path; | |
+ if(time) | |
+ *time = dirb.mtime; | |
+ if(length) | |
+ *length = dirb.length; | |
+ if(appendonly) | |
+ *appendonly = dirb.mode & CHAPPEND; | |
+ return 1; | |
+} | |
+ | |
+int | |
+statfd(int fd, ulong *dev, ulong *id, long *time, long *length, long *appendon… | |
+{ | |
+ Dir dirb; | |
+ | |
+ if(dirfstat(fd, &dirb) == -1) | |
+ return -1; | |
+ if(dev) | |
+ *dev = dirb.type|(dirb.dev<<16); | |
+ if(id) | |
+ *id = dirb.qid.path; | |
+ if(time) | |
+ *time = dirb.mtime; | |
+ if(length) | |
+ *length = dirb.length; | |
+ if(appendonly) | |
+ *appendonly = dirb.mode & CHAPPEND; | |
+ return 1; | |
+} | |
+ | |
+void | |
+notifyf(void *a, char *s) | |
+{ | |
+ USED(a); | |
+ if(bpipeok && strcmp(s, "sys: write on closed pipe") == 0) | |
+ noted(NCONT); | |
+ if(strcmp(s, "interrupt") == 0) | |
+ noted(NCONT); | |
+ panicking = 1; | |
+ rescue(); | |
+ noted(NDFLT); | |
+} | |
+ | |
+int | |
+newtmp(int num) | |
+{ | |
+ int i, fd; | |
+ static char tempnam[30]; | |
+ | |
+ i = getpid(); | |
+ do | |
+ sprint(tempnam, "%s/%d%.4s%dsam", TMPDIR, num, getuser(), i++); | |
+ while(access(tempnam, 0) == 0); | |
+ fd = create(tempnam, ORDWR|OCEXEC|ORCLOSE, 0000); | |
+ if(fd < 0){ | |
+ remove(tempnam); | |
+ fd = create(tempnam, ORDWR|OCEXEC|ORCLOSE, 0000); | |
+ } | |
+ return fd; | |
+} | |
+ | |
+int | |
+waitfor(int pid) | |
+{ | |
+ int rpid; | |
+ Waitmsg wm; | |
+ | |
+ do; while((rpid = wait(&wm)) != pid && rpid != -1); | |
+ return wm.msg[0]; | |
+} | |
+ | |
+void | |
+samerr(char *buf) | |
+{ | |
+ sprint(buf, "%s/sam.err", TMPDIR); | |
+} | |
+ | |
+void* | |
+emalloc(ulong n) | |
+{ | |
+ void *p; | |
+ | |
+ p = malloc(n); | |
+ if(p == 0) | |
+ panic("malloc fails"); | |
+ memset(p, 0, n); | |
+ return p; | |
+} | |
+ | |
+void* | |
+erealloc(void *p, ulong n) | |
+{ | |
+ p = realloc(p, n); | |
+ if(p == 0) | |
+ panic("realloc fails"); | |
+ return p; | |
+} | |
diff --git a/sam/rasp.c b/sam/rasp.c | |
@@ -0,0 +1,276 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+/* | |
+ * GROWDATASIZE must be big enough that all errors go out as Hgrowdata's, | |
+ * so they will be scrolled into visibility in the ~~sam~~ window (yuck!). | |
+ */ | |
+#define GROWDATASIZE 50 /* if size is > this, send data w… | |
+ | |
+void rcut(List*, Posn, Posn); | |
+int rterm(List*, Posn); | |
+void rgrow(List*, Posn, Posn); | |
+ | |
+void | |
+toterminal(File *f, int toterm) | |
+{ | |
+ Buffer *t = f->transcript; | |
+ Posn n, p0, p1, p2, delta = 0, deltacmd = 0; | |
+ Range r; | |
+ union{ | |
+ union Hdr g; | |
+ Rune buf[8+GROWDATASIZE]; | |
+ }hdr; | |
+ Posn growpos, grown; | |
+ | |
+ if(f->rasp == 0) | |
+ return; | |
+ if(f->marked) | |
+ p0 = f->markp+sizeof(Mark)/RUNESIZE; | |
+ else | |
+ p0 = 0; | |
+ grown = 0; | |
+ noflush = 1; | |
+ SET(growpos); | |
+ while(Bread(t, (Rune*)&hdr, sizeof(hdr)/RUNESIZE, p0) > 0){ | |
+ switch(hdr.g.cs.c){ | |
+ default: | |
+ fprint(2, "char %c %.2x\n", hdr.g.cs.c, hdr.g.cs.c); | |
+ panic("unknown in toterminal"); | |
+ | |
+ case 'd': | |
+ if(grown){ | |
+ outTsll(Hgrow, f->tag, growpos, grown); | |
+ grown = 0; | |
+ } | |
+ p1 = hdr.g.cll.l; | |
+ p2 = hdr.g.cll.l1; | |
+ if(p2 <= p1) | |
+ panic("toterminal delete 0"); | |
+ if(f==cmd && p1<cmdpt){ | |
+ if(p2 <= cmdpt) | |
+ deltacmd -= (p2-p1); | |
+ else | |
+ deltacmd -= cmdpt-p1; | |
+ } | |
+ p1 += delta; | |
+ p2 += delta; | |
+ p0 += sizeof(struct _cll)/RUNESIZE; | |
+ if(toterm) | |
+ outTsll(Hcut, f->tag, p1, p2-p1); | |
+ rcut(f->rasp, p1, p2); | |
+ delta -= p2-p1; | |
+ break; | |
+ | |
+ case 'f': | |
+ if(grown){ | |
+ outTsll(Hgrow, f->tag, growpos, grown); | |
+ grown = 0; | |
+ } | |
+ n = hdr.g.cs.s; | |
+ p0 += sizeof(struct _cs)/RUNESIZE + n; | |
+ break; | |
+ | |
+ case 'i': | |
+ n = hdr.g.csl.s; | |
+ p1 = hdr.g.csl.l; | |
+ p0 += sizeof(struct _csl)/RUNESIZE + n; | |
+ if(n <= 0) | |
+ panic("toterminal insert 0"); | |
+ if(f==cmd && p1<cmdpt) | |
+ deltacmd += n; | |
+ p1 += delta; | |
+ if(toterm){ | |
+ if(n>GROWDATASIZE || !rterm(f->rasp, p1)){ | |
+ rgrow(f->rasp, p1, n); | |
+ if(grown && growpos+grown!=p1){ | |
+ outTsll(Hgrow, f->tag, growpos… | |
+ grown = 0; | |
+ } | |
+ if(grown) | |
+ grown += n; | |
+ else{ | |
+ growpos = p1; | |
+ grown = n; | |
+ } | |
+ }else{ | |
+ Rune *rp; | |
+ if(grown){ | |
+ outTsll(Hgrow, f->tag, growpos… | |
+ grown = 0; | |
+ } | |
+ rp = hdr.buf+sizeof(hdr.g.csl)/RUNESIZ… | |
+ rgrow(f->rasp, p1, n); | |
+ r = rdata(f->rasp, p1, n); | |
+ if(r.p1!=p1 || r.p2!=p1+n) | |
+ panic("rdata in toterminal"); | |
+ outTsllS(Hgrowdata, f->tag, p1, n, tmp… | |
+ } | |
+ }else{ | |
+ rgrow(f->rasp, p1, n); | |
+ r = rdata(f->rasp, p1, n); | |
+ if(r.p1!=p1 || r.p2!=p1+n) | |
+ panic("rdata in toterminal"); | |
+ } | |
+ delta += n; | |
+ break; | |
+ } | |
+ } | |
+ if(grown) | |
+ outTsll(Hgrow, f->tag, growpos, grown); | |
+ if(toterm) | |
+ outTs(Hcheck0, f->tag); | |
+ outflush(); | |
+ noflush = 0; | |
+ if(f == cmd){ | |
+ cmdpt += deltacmd+cmdptadv; | |
+ cmdptadv = 0; | |
+ } | |
+} | |
+ | |
+#define M 0x80000000L | |
+#define P(i) r->longptr[i] | |
+#define T(i) (P(i)&M) /* in terminal */ | |
+#define L(i) (P(i)&~M) /* length of this piece */ | |
+ | |
+void | |
+rcut(List *r, Posn p1, Posn p2) | |
+{ | |
+ Posn p, x; | |
+ int i; | |
+ | |
+ if(p1 == p2) | |
+ panic("rcut 0"); | |
+ for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++)) | |
+ ; | |
+ if(i == r->nused) | |
+ panic("rcut 1"); | |
+ if(p<p1){ /* chop this piece */ | |
+ if(p+L(i) < p2){ | |
+ x = p1-p; | |
+ p += L(i); | |
+ }else{ | |
+ x = L(i)-(p2-p1); | |
+ p = p2; | |
+ } | |
+ if(T(i)) | |
+ P(i) = x|M; | |
+ else | |
+ P(i) = x; | |
+ i++; | |
+ } | |
+ while(i<r->nused && p+L(i)<=p2){ | |
+ p += L(i); | |
+ dellist(r, i); | |
+ } | |
+ if(p<p2){ | |
+ if(i == r->nused) | |
+ panic("rcut 2"); | |
+ x = L(i)-(p2-p); | |
+ if(T(i)) | |
+ P(i) = x|M; | |
+ else | |
+ P(i) = x; | |
+ } | |
+ /* can we merge i and i-1 ? */ | |
+ if(i>0 && i<r->nused && T(i-1)==T(i)){ | |
+ x = L(i-1)+L(i); | |
+ dellist(r, i--); | |
+ if(T(i)) | |
+ P(i)=x|M; | |
+ else | |
+ P(i)=x; | |
+ } | |
+} | |
+ | |
+void | |
+rgrow(List *r, Posn p1, Posn n) | |
+{ | |
+ Posn p; | |
+ int i; | |
+ | |
+ if(n == 0) | |
+ panic("rgrow 0"); | |
+ for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++)) | |
+ ; | |
+ if(i == r->nused){ /* stick on end of file */ | |
+ if(p!=p1) | |
+ panic("rgrow 1"); | |
+ if(i>0 && !T(i-1)) | |
+ P(i-1)+=n; | |
+ else | |
+ inslist(r, i, n); | |
+ }else if(!T(i)) /* goes in this empty piece */ | |
+ P(i)+=n; | |
+ else if(p==p1 && i>0 && !T(i-1)) /* special case; simplifies li… | |
+ P(i-1)+=n; | |
+ else if(p==p1) | |
+ inslist(r, i, n); | |
+ else{ /* must break piece in terminal */ | |
+ inslist(r, i+1, (L(i)-(p1-p))|M); | |
+ inslist(r, i+1, n); | |
+ P(i) = (p1-p)|M; | |
+ } | |
+} | |
+ | |
+int | |
+rterm(List *r, Posn p1) | |
+{ | |
+ Posn p; | |
+ int i; | |
+ | |
+ for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++)) | |
+ ; | |
+ if(i==r->nused && (i==0 || !T(i-1))) | |
+ return 0; | |
+ return T(i); | |
+} | |
+ | |
+Range | |
+rdata(List *r, Posn p1, Posn n) | |
+{ | |
+ Posn p; | |
+ int i; | |
+ Range rg; | |
+ | |
+ if(n==0) | |
+ panic("rdata 0"); | |
+ for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++)) | |
+ ; | |
+ if(i==r->nused) | |
+ panic("rdata 1"); | |
+ if(T(i)){ | |
+ n-=L(i)-(p1-p); | |
+ if(n<=0){ | |
+ rg.p1 = rg.p2 = p1; | |
+ return rg; | |
+ } | |
+ p+=L(i++); | |
+ p1 = p; | |
+ } | |
+ if(T(i) || i==r->nused) | |
+ panic("rdata 2"); | |
+ if(p+L(i)<p1+n) | |
+ n = L(i)-(p1-p); | |
+ rg.p1 = p1; | |
+ rg.p2 = p1+n; | |
+ if(p!=p1){ | |
+ inslist(r, i+1, L(i)-(p1-p)); | |
+ P(i)=p1-p; | |
+ i++; | |
+ } | |
+ if(L(i)!=n){ | |
+ inslist(r, i+1, L(i)-n); | |
+ P(i)=n; | |
+ } | |
+ P(i)|=M; | |
+ /* now i is set; can we merge? */ | |
+ if(i<r->nused-1 && T(i+1)){ | |
+ P(i)=(n+=L(i+1))|M; | |
+ dellist(r, i+1); | |
+ } | |
+ if(i>0 && T(i-1)){ | |
+ P(i)=(n+L(i-1))|M; | |
+ dellist(r, i-1); | |
+ } | |
+ return rg; | |
+} | |
diff --git a/sam/regexp.c b/sam/regexp.c | |
@@ -0,0 +1,820 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+Rangeset sel; | |
+String lastregexp; | |
+/* | |
+ * Machine Information | |
+ */ | |
+typedef struct Inst Inst; | |
+ | |
+struct Inst | |
+{ | |
+ long type; /* < 0x10000 ==> literal, otherwise action */ | |
+ union { | |
+ int rsid; | |
+ int rsubid; | |
+ int class; | |
+ struct Inst *rother; | |
+ struct Inst *rright; | |
+ } r; | |
+ union{ | |
+ struct Inst *lleft; | |
+ struct Inst *lnext; | |
+ } l; | |
+}; | |
+#define sid r.rsid | |
+#define subid r.rsubid | |
+#define rclass r.class | |
+#define other r.rother | |
+#define right r.rright | |
+#define left l.lleft | |
+#define next l.lnext | |
+ | |
+#define NPROG 1024 | |
+Inst program[NPROG]; | |
+Inst *progp; | |
+Inst *startinst; /* First inst. of program; might not be program… | |
+Inst *bstartinst; /* same for backwards machine */ | |
+ | |
+typedef struct Ilist Ilist; | |
+struct Ilist | |
+{ | |
+ Inst *inst; /* Instruction of the thread */ | |
+ Rangeset se; | |
+ Posn startp; /* first char of match */ | |
+}; | |
+ | |
+#define NLIST 128 | |
+ | |
+Ilist *tl, *nl; /* This list, next list */ | |
+Ilist list[2][NLIST]; | |
+static Rangeset sempty; | |
+ | |
+/* | |
+ * Actions and Tokens | |
+ * | |
+ * 0x100xx are operators, value == precedence | |
+ * 0x200xx are tokens, i.e. operands for operators | |
+ */ | |
+#define OPERATOR 0x10000 /* Bitmask of all operators */ | |
+#define START 0x10000 /* Start, used for marker o… | |
+#define RBRA 0x10001 /* Right bracket, ) */ | |
+#define LBRA 0x10002 /* Left bracket, ( */ | |
+#define OR 0x10003 /* Alternation, | */ | |
+#define CAT 0x10004 /* Concatentation, implicit o… | |
+#define STAR 0x10005 /* Closure, * */ | |
+#define PLUS 0x10006 /* a+ == aa* */ | |
+#define QUEST 0x10007 /* a? == a|nothing, i.e. 0 … | |
+#define ANY 0x20000 /* Any character but newline,… | |
+#define NOP 0x20001 /* No operation, internal use… | |
+#define BOL 0x20002 /* Beginning of line, ^ */ | |
+#define EOL 0x20003 /* End of line, $ */ | |
+#define CCLASS 0x20004 /* Character class, [] */ | |
+#define NCCLASS 0x20005 /* Negated character clas… | |
+#define END 0x20077 /* Terminate: match found */ | |
+ | |
+#define ISATOR 0x10000 | |
+#define ISAND 0x20000 | |
+ | |
+/* | |
+ * Parser Information | |
+ */ | |
+typedef struct Node Node; | |
+struct Node | |
+{ | |
+ Inst *first; | |
+ Inst *last; | |
+}; | |
+ | |
+#define NSTACK 20 | |
+Node andstack[NSTACK]; | |
+Node *andp; | |
+int atorstack[NSTACK]; | |
+int *atorp; | |
+int lastwasand; /* Last token was operand */ | |
+int cursubid; | |
+int subidstack[NSTACK]; | |
+int *subidp; | |
+int backwards; | |
+int nbra; | |
+Rune *exprp; /* pointer to next character in source expr… | |
+#define DCLASS 10 /* allocation increment */ | |
+int nclass; /* number active */ | |
+int Nclass; /* high water mark */ | |
+Rune **class; | |
+int negateclass; | |
+ | |
+void addinst(Ilist *l, Inst *inst, Rangeset *sep); | |
+void newmatch(Rangeset*); | |
+void bnewmatch(Rangeset*); | |
+void pushand(Inst*, Inst*); | |
+void pushator(int); | |
+Node *popand(int); | |
+int popator(void); | |
+void startlex(Rune*); | |
+int lex(void); | |
+void operator(int); | |
+void operand(int); | |
+void evaluntil(int); | |
+void optimize(Inst*); | |
+void bldcclass(void); | |
+ | |
+void | |
+regerror(Err e) | |
+{ | |
+ Strzero(&lastregexp); | |
+ error(e); | |
+} | |
+ | |
+void | |
+regerror_c(Err e, int c) | |
+{ | |
+ Strzero(&lastregexp); | |
+ error_c(e, c); | |
+} | |
+ | |
+Inst * | |
+newinst(int t) | |
+{ | |
+ if(progp >= &program[NPROG]) | |
+ regerror(Etoolong); | |
+ progp->type = t; | |
+ progp->left = 0; | |
+ progp->right = 0; | |
+ return progp++; | |
+} | |
+ | |
+Inst * | |
+realcompile(Rune *s) | |
+{ | |
+ int token; | |
+ | |
+ startlex(s); | |
+ atorp = atorstack; | |
+ andp = andstack; | |
+ subidp = subidstack; | |
+ cursubid = 0; | |
+ lastwasand = FALSE; | |
+ /* Start with a low priority operator to prime parser */ | |
+ pushator(START-1); | |
+ while((token=lex()) != END){ | |
+ if((token&ISATOR) == OPERATOR) | |
+ operator(token); | |
+ else | |
+ operand(token); | |
+ } | |
+ /* Close with a low priority operator */ | |
+ evaluntil(START); | |
+ /* Force END */ | |
+ operand(END); | |
+ evaluntil(START); | |
+ if(nbra) | |
+ regerror(Eleftpar); | |
+ --andp; /* points to first and only operand */ | |
+ return andp->first; | |
+} | |
+ | |
+void | |
+compile(String *s) | |
+{ | |
+ int i; | |
+ Inst *oprogp; | |
+ | |
+ if(Strcmp(s, &lastregexp)==0) | |
+ return; | |
+ for(i=0; i<nclass; i++) | |
+ free(class[i]); | |
+ nclass = 0; | |
+ progp = program; | |
+ backwards = FALSE; | |
+ startinst = realcompile(s->s); | |
+ optimize(program); | |
+ oprogp = progp; | |
+ backwards = TRUE; | |
+ bstartinst = realcompile(s->s); | |
+ optimize(oprogp); | |
+ Strduplstr(&lastregexp, s); | |
+} | |
+ | |
+void | |
+operand(int t) | |
+{ | |
+ Inst *i; | |
+ if(lastwasand) | |
+ operator(CAT); /* catenate is implicit */ | |
+ i = newinst(t); | |
+ if(t == CCLASS){ | |
+ if(negateclass) | |
+ i->type = NCCLASS; /* UGH */ | |
+ i->rclass = nclass-1; /* UGH */ | |
+ } | |
+ pushand(i, i); | |
+ lastwasand = TRUE; | |
+} | |
+ | |
+void | |
+operator(int t) | |
+{ | |
+ if(t==RBRA && --nbra<0) | |
+ regerror(Erightpar); | |
+ if(t==LBRA){ | |
+/* | |
+ * if(++cursubid >= NSUBEXP) | |
+ * regerror(Esubexp); | |
+ */ | |
+ cursubid++; /* silently ignored */ | |
+ nbra++; | |
+ if(lastwasand) | |
+ operator(CAT); | |
+ }else | |
+ evaluntil(t); | |
+ if(t!=RBRA) | |
+ pushator(t); | |
+ lastwasand = FALSE; | |
+ if(t==STAR || t==QUEST || t==PLUS || t==RBRA) | |
+ lastwasand = TRUE; /* these look like operands */ | |
+} | |
+ | |
+void | |
+cant(char *s) | |
+{ | |
+ char buf[100]; | |
+ | |
+ sprint(buf, "regexp: can't happen: %s", s); | |
+ panic(buf); | |
+} | |
+ | |
+void | |
+pushand(Inst *f, Inst *l) | |
+{ | |
+ if(andp >= &andstack[NSTACK]) | |
+ cant("operand stack overflow"); | |
+ andp->first = f; | |
+ andp->last = l; | |
+ andp++; | |
+} | |
+ | |
+void | |
+pushator(int t) | |
+{ | |
+ if(atorp >= &atorstack[NSTACK]) | |
+ cant("operator stack overflow"); | |
+ *atorp++=t; | |
+ if(cursubid >= NSUBEXP) | |
+ *subidp++= -1; | |
+ else | |
+ *subidp++=cursubid; | |
+} | |
+ | |
+Node * | |
+popand(int op) | |
+{ | |
+ if(andp <= &andstack[0]) | |
+ if(op) | |
+ regerror_c(Emissop, op); | |
+ else | |
+ regerror(Ebadregexp); | |
+ return --andp; | |
+} | |
+ | |
+int | |
+popator(void) | |
+{ | |
+ if(atorp <= &atorstack[0]) | |
+ cant("operator stack underflow"); | |
+ --subidp; | |
+ return *--atorp; | |
+} | |
+ | |
+void | |
+evaluntil(int pri) | |
+{ | |
+ Node *op1, *op2, *t; | |
+ Inst *inst1, *inst2; | |
+ | |
+ while(pri==RBRA || atorp[-1]>=pri){ | |
+ switch(popator()){ | |
+ case LBRA: | |
+ op1 = popand('('); | |
+ inst2 = newinst(RBRA); | |
+ inst2->subid = *subidp; | |
+ op1->last->next = inst2; | |
+ inst1 = newinst(LBRA); | |
+ inst1->subid = *subidp; | |
+ inst1->next = op1->first; | |
+ pushand(inst1, inst2); | |
+ return; /* must have been RBRA */ | |
+ default: | |
+ panic("unknown regexp operator"); | |
+ break; | |
+ case OR: | |
+ op2 = popand('|'); | |
+ op1 = popand('|'); | |
+ inst2 = newinst(NOP); | |
+ op2->last->next = inst2; | |
+ op1->last->next = inst2; | |
+ inst1 = newinst(OR); | |
+ inst1->right = op1->first; | |
+ inst1->left = op2->first; | |
+ pushand(inst1, inst2); | |
+ break; | |
+ case CAT: | |
+ op2 = popand(0); | |
+ op1 = popand(0); | |
+ if(backwards && op2->first->type!=END) | |
+ t = op1, op1 = op2, op2 = t; | |
+ op1->last->next = op2->first; | |
+ pushand(op1->first, op2->last); | |
+ break; | |
+ case STAR: | |
+ op2 = popand('*'); | |
+ inst1 = newinst(OR); | |
+ op2->last->next = inst1; | |
+ inst1->right = op2->first; | |
+ pushand(inst1, inst1); | |
+ break; | |
+ case PLUS: | |
+ op2 = popand('+'); | |
+ inst1 = newinst(OR); | |
+ op2->last->next = inst1; | |
+ inst1->right = op2->first; | |
+ pushand(op2->first, inst1); | |
+ break; | |
+ case QUEST: | |
+ op2 = popand('?'); | |
+ inst1 = newinst(OR); | |
+ inst2 = newinst(NOP); | |
+ inst1->left = inst2; | |
+ inst1->right = op2->first; | |
+ op2->last->next = inst2; | |
+ pushand(inst1, inst2); | |
+ break; | |
+ } | |
+ } | |
+} | |
+ | |
+ | |
+void | |
+optimize(Inst *start) | |
+{ | |
+ Inst *inst, *target; | |
+ | |
+ for(inst=start; inst->type!=END; inst++){ | |
+ target = inst->next; | |
+ while(target->type == NOP) | |
+ target = target->next; | |
+ inst->next = target; | |
+ } | |
+} | |
+ | |
+#ifdef DEBUG | |
+void | |
+dumpstack(void){ | |
+ Node *stk; | |
+ int *ip; | |
+ | |
+ dprint("operators\n"); | |
+ for(ip = atorstack; ip<atorp; ip++) | |
+ dprint("0%o\n", *ip); | |
+ dprint("operands\n"); | |
+ for(stk = andstack; stk<andp; stk++) | |
+ dprint("0%o\t0%o\n", stk->first->type, stk->last->type); | |
+} | |
+void | |
+dump(void){ | |
+ Inst *l; | |
+ | |
+ l = program; | |
+ do{ | |
+ dprint("%d:\t0%o\t%d\t%d\n", l-program, l->type, | |
+ l->left-program, l->right-program); | |
+ }while(l++->type); | |
+} | |
+#endif | |
+ | |
+void | |
+startlex(Rune *s) | |
+{ | |
+ exprp = s; | |
+ nbra = 0; | |
+} | |
+ | |
+ | |
+int | |
+lex(void){ | |
+ int c= *exprp++; | |
+ | |
+ switch(c){ | |
+ case '\\': | |
+ if(*exprp) | |
+ if((c= *exprp++)=='n') | |
+ c='\n'; | |
+ break; | |
+ case 0: | |
+ c = END; | |
+ --exprp; /* In case we come here again */ | |
+ break; | |
+ case '*': | |
+ c = STAR; | |
+ break; | |
+ case '?': | |
+ c = QUEST; | |
+ break; | |
+ case '+': | |
+ c = PLUS; | |
+ break; | |
+ case '|': | |
+ c = OR; | |
+ break; | |
+ case '.': | |
+ c = ANY; | |
+ break; | |
+ case '(': | |
+ c = LBRA; | |
+ break; | |
+ case ')': | |
+ c = RBRA; | |
+ break; | |
+ case '^': | |
+ c = BOL; | |
+ break; | |
+ case '$': | |
+ c = EOL; | |
+ break; | |
+ case '[': | |
+ c = CCLASS; | |
+ bldcclass(); | |
+ break; | |
+ } | |
+ return c; | |
+} | |
+ | |
+long | |
+nextrec(void){ | |
+ if(exprp[0]==0 || (exprp[0]=='\\' && exprp[1]==0)) | |
+ regerror(Ebadclass); | |
+ if(exprp[0] == '\\'){ | |
+ exprp++; | |
+ if(*exprp=='n'){ | |
+ exprp++; | |
+ return '\n'; | |
+ } | |
+ return *exprp++|0x10000; | |
+ } | |
+ return *exprp++; | |
+} | |
+ | |
+void | |
+bldcclass(void) | |
+{ | |
+ long c1, c2, n, na; | |
+ Rune *classp; | |
+ | |
+ classp = emalloc(DCLASS*RUNESIZE); | |
+ n = 0; | |
+ na = DCLASS; | |
+ /* we have already seen the '[' */ | |
+ if(*exprp == '^'){ | |
+ classp[n++] = '\n'; /* don't match newline in negate ca… | |
+ negateclass = TRUE; | |
+ exprp++; | |
+ }else | |
+ negateclass = FALSE; | |
+ while((c1 = nextrec()) != ']'){ | |
+ if(c1 == '-'){ | |
+ Error: | |
+ free(classp); | |
+ regerror(Ebadclass); | |
+ } | |
+ if(n+4 >= na){ /* 3 runes plus NUL */ | |
+ na += DCLASS; | |
+ classp = erealloc(classp, na*RUNESIZE); | |
+ } | |
+ if(*exprp == '-'){ | |
+ exprp++; /* eat '-' */ | |
+ if((c2 = nextrec()) == ']') | |
+ goto Error; | |
+ classp[n+0] = 0xFFFF; | |
+ classp[n+1] = c1; | |
+ classp[n+2] = c2; | |
+ n += 3; | |
+ }else | |
+ classp[n++] = c1; | |
+ } | |
+ classp[n] = 0; | |
+ if(nclass == Nclass){ | |
+ Nclass += DCLASS; | |
+ class = erealloc(class, Nclass*sizeof(Rune*)); | |
+ } | |
+ class[nclass++] = classp; | |
+} | |
+ | |
+int | |
+classmatch(int classno, int c, int negate) | |
+{ | |
+ Rune *p; | |
+ | |
+ p = class[classno]; | |
+ while(*p){ | |
+ if(*p == 0xFFFF){ | |
+ if(p[1]<=c && c<=p[2]) | |
+ return !negate; | |
+ p += 3; | |
+ }else if(*p++ == c) | |
+ return !negate; | |
+ } | |
+ return negate; | |
+} | |
+ | |
+/* | |
+ * Note optimization in addinst: | |
+ * *l must be pending when addinst called; if *l has been looked | |
+ * at already, the optimization is a bug. | |
+ */ | |
+void | |
+addinst(Ilist *l, Inst *inst, Rangeset *sep) | |
+{ | |
+ Ilist *p; | |
+ | |
+ for(p = l; p->inst; p++){ | |
+ if(p->inst==inst){ | |
+ if((sep)->p[0].p1 < p->se.p[0].p1) | |
+ p->se= *sep; /* this would be bug */ | |
+ return; /* It's already there */ | |
+ } | |
+ } | |
+ p->inst = inst; | |
+ p->se= *sep; | |
+ (p+1)->inst = 0; | |
+} | |
+ | |
+int | |
+execute(File *f, Posn startp, Posn eof) | |
+{ | |
+ int flag = 0; | |
+ Inst *inst; | |
+ Ilist *tlp; | |
+ Posn p = startp; | |
+ int nnl = 0, ntl; | |
+ int c; | |
+ int wrapped = 0; | |
+ int startchar = startinst->type<OPERATOR? startinst->type : 0; | |
+ | |
+ list[0][0].inst = list[1][0].inst = 0; | |
+ sel.p[0].p1 = -1; | |
+ Fgetcset(f, startp); | |
+ /* Execute machine once for each character */ | |
+ for(;;p++){ | |
+ doloop: | |
+ c = Fgetc(f); | |
+ if(p>=eof || c<0){ | |
+ switch(wrapped++){ | |
+ case 0: /* let loop run one more click … | |
+ case 2: | |
+ break; | |
+ case 1: /* expired; wrap to beginning */ | |
+ if(sel.p[0].p1>=0 || eof!=INFINITY) | |
+ goto Return; | |
+ list[0][0].inst = list[1][0].inst = 0; | |
+ Fgetcset(f, (Posn)0); | |
+ p = 0; | |
+ goto doloop; | |
+ default: | |
+ goto Return; | |
+ } | |
+ }else if(((wrapped && p>=startp) || sel.p[0].p1>0) && nnl==0) | |
+ break; | |
+ /* fast check for first char */ | |
+ if(startchar && nnl==0 && c!=startchar) | |
+ continue; | |
+ tl = list[flag]; | |
+ nl = list[flag^=1]; | |
+ nl->inst = 0; | |
+ ntl = nnl; | |
+ nnl = 0; | |
+ if(sel.p[0].p1<0 && (!wrapped || p<startp || startp==eof)){ | |
+ /* Add first instruction to this list */ | |
+ if(++ntl >= NLIST) | |
+ Overflow: | |
+ error(Eoverflow); | |
+ sempty.p[0].p1 = p; | |
+ addinst(tl, startinst, &sempty); | |
+ } | |
+ /* Execute machine until this list is empty */ | |
+ for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment =… | |
+ Switchstmt: | |
+ switch(inst->type){ | |
+ default: /* regular character */ | |
+ if(inst->type==c){ | |
+ Addinst: | |
+ if(++nnl >= NLIST) | |
+ goto Overflow; | |
+ addinst(nl, inst->next, &tlp->se); | |
+ } | |
+ break; | |
+ case LBRA: | |
+ if(inst->subid>=0) | |
+ tlp->se.p[inst->subid].p1 = p; | |
+ inst = inst->next; | |
+ goto Switchstmt; | |
+ case RBRA: | |
+ if(inst->subid>=0) | |
+ tlp->se.p[inst->subid].p2 = p; | |
+ inst = inst->next; | |
+ goto Switchstmt; | |
+ case ANY: | |
+ if(c!='\n') | |
+ goto Addinst; | |
+ break; | |
+ case BOL: | |
+ if(p == 0){ | |
+ Step: | |
+ inst = inst->next; | |
+ goto Switchstmt; | |
+ } | |
+ if(f->getci > 1){ | |
+ if(f->getcbuf[f->getci-2]=='\n') | |
+ goto Step; | |
+ }else{ | |
+ Rune c; | |
+ if(Fchars(f, &c, p-1, p)==1 && c=='\n') | |
+ goto Step; | |
+ } | |
+ break; | |
+ case EOL: | |
+ if(c == '\n') | |
+ goto Step; | |
+ break; | |
+ case CCLASS: | |
+ if(c>=0 && classmatch(inst->rclass, c, 0)) | |
+ goto Addinst; | |
+ break; | |
+ case NCCLASS: | |
+ if(c>=0 && classmatch(inst->rclass, c, 1)) | |
+ goto Addinst; | |
+ break; | |
+ case OR: | |
+ /* evaluate right choice later */ | |
+ if(++ntl >= NLIST) | |
+ goto Overflow; | |
+ addinst(tlp, inst->right, &tlp->se); | |
+ /* efficiency: advance and re-evaluate */ | |
+ inst = inst->left; | |
+ goto Switchstmt; | |
+ case END: /* Match! */ | |
+ tlp->se.p[0].p2 = p; | |
+ newmatch(&tlp->se); | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ Return: | |
+ return sel.p[0].p1>=0; | |
+} | |
+ | |
+void | |
+newmatch(Rangeset *sp) | |
+{ | |
+ int i; | |
+ | |
+ if(sel.p[0].p1<0 || sp->p[0].p1<sel.p[0].p1 || | |
+ (sp->p[0].p1==sel.p[0].p1 && sp->p[0].p2>sel.p[0].p2)) | |
+ for(i = 0; i<NSUBEXP; i++) | |
+ sel.p[i] = sp->p[i]; | |
+} | |
+ | |
+int | |
+bexecute(File *f, Posn startp) | |
+{ | |
+ int flag = 0; | |
+ Inst *inst; | |
+ Ilist *tlp; | |
+ Posn p = startp; | |
+ int nnl = 0, ntl; | |
+ int c; | |
+ int wrapped = 0; | |
+ int startchar = bstartinst->type<OPERATOR? bstartinst->type : 0; | |
+ | |
+ list[0][0].inst = list[1][0].inst = 0; | |
+ sel.p[0].p1= -1; | |
+ Fgetcset(f, startp); | |
+ /* Execute machine once for each character, including terminal NUL */ | |
+ for(;;--p){ | |
+ doloop: | |
+ if((c = Fbgetc(f))==-1){ | |
+ switch(wrapped++){ | |
+ case 0: /* let loop run one more click … | |
+ case 2: | |
+ break; | |
+ case 1: /* expired; wrap to end */ | |
+ if(sel.p[0].p1>=0) | |
+ case 3: | |
+ goto Return; | |
+ list[0][0].inst = list[1][0].inst = 0; | |
+ Fgetcset(f, f->nrunes); | |
+ p = f->nrunes; | |
+ goto doloop; | |
+ default: | |
+ goto Return; | |
+ } | |
+ }else if(((wrapped && p<=startp) || sel.p[0].p1>0) && nnl==0) | |
+ break; | |
+ /* fast check for first char */ | |
+ if(startchar && nnl==0 && c!=startchar) | |
+ continue; | |
+ tl = list[flag]; | |
+ nl = list[flag^=1]; | |
+ nl->inst = 0; | |
+ ntl = nnl; | |
+ nnl = 0; | |
+ if(sel.p[0].p1<0 && (!wrapped || p>startp)){ | |
+ /* Add first instruction to this list */ | |
+ if(++ntl >= NLIST) | |
+ Overflow: | |
+ error(Eoverflow); | |
+ /* the minus is so the optimizations in addinst work */ | |
+ sempty.p[0].p1 = -p; | |
+ addinst(tl, bstartinst, &sempty); | |
+ } | |
+ /* Execute machine until this list is empty */ | |
+ for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment =… | |
+ Switchstmt: | |
+ switch(inst->type){ | |
+ default: /* regular character */ | |
+ if(inst->type == c){ | |
+ Addinst: | |
+ if(++nnl >= NLIST) | |
+ goto Overflow; | |
+ addinst(nl, inst->next, &tlp->se); | |
+ } | |
+ break; | |
+ case LBRA: | |
+ if(inst->subid>=0) | |
+ tlp->se.p[inst->subid].p1 = p; | |
+ inst = inst->next; | |
+ goto Switchstmt; | |
+ case RBRA: | |
+ if(inst->subid >= 0) | |
+ tlp->se.p[inst->subid].p2 = p; | |
+ inst = inst->next; | |
+ goto Switchstmt; | |
+ case ANY: | |
+ if(c != '\n') | |
+ goto Addinst; | |
+ break; | |
+ case BOL: | |
+ if(c=='\n' || p==0){ | |
+ Step: | |
+ inst = inst->next; | |
+ goto Switchstmt; | |
+ } | |
+ break; | |
+ case EOL: | |
+ if(f->getci<f->ngetc-1){ | |
+ if(f->getcbuf[f->getci+1]=='\n') | |
+ goto Step; | |
+ }else if(p<f->nrunes-1){ | |
+ Rune c; | |
+ if(Fchars(f, &c, p, p+1)==1 && c=='\n') | |
+ goto Step; | |
+ } | |
+ break; | |
+ case CCLASS: | |
+ if(c>=0 && classmatch(inst->rclass, c, 0)) | |
+ goto Addinst; | |
+ break; | |
+ case NCCLASS: | |
+ if(c>=0 && classmatch(inst->rclass, c, 1)) | |
+ goto Addinst; | |
+ break; | |
+ case OR: | |
+ /* evaluate right choice later */ | |
+ if(++ntl >= NLIST) | |
+ goto Overflow; | |
+ addinst(tlp, inst->right, &tlp->se); | |
+ /* efficiency: advance and re-evaluate */ | |
+ inst = inst->left; | |
+ goto Switchstmt; | |
+ case END: /* Match! */ | |
+ tlp->se.p[0].p1 = -tlp->se.p[0].p1; /* minus s… | |
+ tlp->se.p[0].p2 = p; | |
+ bnewmatch(&tlp->se); | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ Return: | |
+ return sel.p[0].p1>=0; | |
+} | |
+ | |
+void | |
+bnewmatch(Rangeset *sp) | |
+{ | |
+ int i; | |
+ if(sel.p[0].p1<0 || sp->p[0].p1>sel.p[0].p2 || (sp->p[0].p1==sel.p[0].… | |
+ for(i = 0; i<NSUBEXP; i++){ /* note the reversal; p1<=p2… | |
+ sel.p[i].p1 = sp->p[i].p2; | |
+ sel.p[i].p2 = sp->p[i].p1; | |
+ } | |
+} | |
diff --git a/sam/sam.c b/sam/sam.c | |
@@ -0,0 +1,682 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+Rune genbuf[BLOCKSIZE]; | |
+int io; | |
+int panicking; | |
+int rescuing; | |
+Mod modnum; | |
+String genstr; | |
+String rhs; | |
+String wd; | |
+String cmdstr; | |
+Rune empty[] = { 0 }; | |
+char *genc; | |
+File *curfile; | |
+File *flist; | |
+File *cmd; | |
+jmp_buf mainloop; | |
+List tempfile; | |
+int quitok = TRUE; | |
+int downloaded; | |
+int dflag; | |
+int Rflag; | |
+char *machine; | |
+char *home; | |
+int bpipeok; | |
+int termlocked; | |
+char *samterm = SAMTERM; | |
+char *rsamname = RSAM; | |
+ | |
+Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'}; | |
+ | |
+void usage(void); | |
+ | |
+int main(int argc, char *argv[]) | |
+{ | |
+ int i; | |
+ String *t; | |
+ char **ap, **arg; | |
+ | |
+ arg = argv++; | |
+ ap = argv; | |
+ while(argc>1 && argv[0] && argv[0][0]=='-'){ | |
+ switch(argv[0][1]){ | |
+ case 'd': | |
+ dflag++; | |
+ break; | |
+ | |
+ case 'r': | |
+ *ap++ = *argv++; | |
+ *ap++ = *argv; | |
+ --argc; | |
+ if(argc == 1) | |
+ usage(); | |
+ machine = *argv; | |
+ | |
+ rsamname = RXSAMNAME; | |
+ break; | |
+ | |
+ case 'R': | |
+ Rflag++; | |
+ break; | |
+ | |
+ case 't': | |
+ --argc, argv++; | |
+ if(argc == 1) | |
+ usage(); | |
+ samterm = *argv; | |
+ break; | |
+ | |
+ case 's': | |
+ --argc, argv++; | |
+ if(argc == 1) | |
+ usage(); | |
+ rsamname = *argv; | |
+ break; | |
+ | |
+ default: | |
+ dprint("sam: unknown flag %c\n", argv[0][1]); | |
+ exits("usage"); | |
+ } | |
+ --argc, argv++; | |
+ } | |
+ Strinit(&cmdstr); | |
+ Strinit0(&lastpat); | |
+ Strinit0(&lastregexp); | |
+ Strinit0(&genstr); | |
+ Strinit0(&rhs); | |
+ Strinit0(&wd); | |
+ tempfile.listptr = emalloc(0); | |
+ Strinit0(&plan9cmd); | |
+ home = getenv(HOME); | |
+ if(home == 0) | |
+ home = "/"; | |
+ if(!dflag) | |
+ startup(machine, Rflag, arg, ap); | |
+ Fstart(); | |
+ notify(notifyf); | |
+ if(argc>1){ | |
+ for(i=0; i<argc-1; i++) | |
+ if(!setjmp(mainloop)){ | |
+ t = tmpcstr(argv[i]); | |
+ Straddc(t, '\0'); | |
+ Strduplstr(&genstr, t); | |
+ freetmpstr(t); | |
+ Fsetname(newfile(), &genstr); | |
+ } | |
+ }else if(!downloaded) | |
+ newfile()->state = Clean; | |
+ modnum++; | |
+ if(file.nused) | |
+ current(file.filepptr[0]); | |
+ setjmp(mainloop); | |
+ cmdloop(); | |
+ trytoquit(); /* if we already q'ed, quitok will be TRUE */ | |
+ exits(0); | |
+} | |
+ | |
+void | |
+usage(void) | |
+{ | |
+ dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n"); | |
+ exits("usage"); | |
+} | |
+ | |
+void | |
+rescue(void) | |
+{ | |
+ int i, nblank = 0; | |
+ File *f; | |
+ char *c; | |
+ char buf[256]; | |
+ | |
+ if(rescuing++) | |
+ return; | |
+ io = -1; | |
+ for(i=0; i<file.nused; i++){ | |
+ f = file.filepptr[i]; | |
+ if(f==cmd || f->nrunes==0 || f->state!=Dirty) | |
+ continue; | |
+ if(io == -1){ | |
+ sprint(buf, "%s/sam.save", home); | |
+ io = create(buf, 1, 0777); | |
+ if(io<0) | |
+ return; | |
+ } | |
+ if(f->name.s[0]){ | |
+ c = Strtoc(&f->name); | |
+ strncpy(buf, c, sizeof buf-1); | |
+ buf[sizeof buf-1] = 0; | |
+ free(c); | |
+ }else | |
+ sprint(buf, "nameless.%d", nblank++); | |
+ fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf); | |
+ addr.r.p1 = 0, addr.r.p2 = f->nrunes; | |
+ writeio(f); | |
+ fprint(io, "\n---%s\n", (char *)buf); | |
+ } | |
+} | |
+ | |
+void | |
+panic(char *s) | |
+{ | |
+ int wasd; | |
+ | |
+ if(!panicking++ && !setjmp(mainloop)){ | |
+ wasd = downloaded; | |
+ downloaded = 0; | |
+ dprint("sam: panic: %s\n", s); | |
+ if(wasd) | |
+ fprint(2, "sam: panic: %s\n", s); | |
+ rescue(); | |
+ abort(); | |
+ } | |
+} | |
+ | |
+void | |
+hiccough(char *s) | |
+{ | |
+ if(rescuing) | |
+ exits("rescue"); | |
+ if(s) | |
+ dprint("%s\n", s); | |
+ resetcmd(); | |
+ resetxec(); | |
+ resetsys(); | |
+ if(io > 0) | |
+ close(io); | |
+ if(undobuf->nrunes) | |
+ Bdelete(undobuf, (Posn)0, undobuf->nrunes); | |
+ update(); | |
+ if (curfile) { | |
+ if (curfile->state==Unread) | |
+ curfile->state = Clean; | |
+ else if (downloaded) | |
+ outTs(Hcurrent, curfile->tag); | |
+ } | |
+ longjmp(mainloop, 1); | |
+} | |
+ | |
+void | |
+intr(void) | |
+{ | |
+ error(Eintr); | |
+} | |
+ | |
+void | |
+trytoclose(File *f) | |
+{ | |
+ char *t; | |
+ char buf[256]; | |
+ | |
+ if(f == cmd) /* possible? */ | |
+ return; | |
+ if(f->deleted) | |
+ return; | |
+ if(f->state==Dirty && !f->closeok){ | |
+ f->closeok = TRUE; | |
+ if(f->name.s[0]){ | |
+ t = Strtoc(&f->name); | |
+ strncpy(buf, t, sizeof buf-1); | |
+ free(t); | |
+ }else | |
+ strcpy(buf, "nameless file"); | |
+ error_s(Emodified, buf); | |
+ } | |
+ f->deleted = TRUE; | |
+} | |
+ | |
+void | |
+trytoquit(void) | |
+{ | |
+ int c; | |
+ File *f; | |
+ | |
+ if(!quitok) | |
+{ | |
+ for(c = 0; c<file.nused; c++){ | |
+ f = file.filepptr[c]; | |
+ if(f!=cmd && f->state==Dirty){ | |
+ quitok = TRUE; | |
+ eof = FALSE; | |
+ error(Echanges); | |
+ } | |
+ } | |
+} | |
+} | |
+ | |
+void | |
+load(File *f) | |
+{ | |
+ Address saveaddr; | |
+ | |
+ Strduplstr(&genstr, &f->name); | |
+ filename(f); | |
+ if(f->name.s[0]){ | |
+ saveaddr = addr; | |
+ edit(f, 'I'); | |
+ addr = saveaddr; | |
+ }else | |
+ f->state = Clean; | |
+ Fupdate(f, TRUE, TRUE); | |
+} | |
+ | |
+void | |
+cmdupdate(void) | |
+{ | |
+ if(cmd && cmd->mod!=0){ | |
+ Fupdate(cmd, FALSE, downloaded); | |
+ cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nrunes; | |
+ telldot(cmd); | |
+ } | |
+} | |
+ | |
+void | |
+delete(File *f) | |
+{ | |
+ if(downloaded && f->rasp) | |
+ outTs(Hclose, f->tag); | |
+ delfile(f); | |
+ if(f == curfile) | |
+ current(0); | |
+} | |
+ | |
+void | |
+update(void) | |
+{ | |
+ int i, anymod; | |
+ File *f; | |
+ | |
+ settempfile(); | |
+ for(anymod = i=0; i<tempfile.nused; i++){ | |
+ f = tempfile.filepptr[i]; | |
+ if(f==cmd) /* cmd gets done in main() */ | |
+ continue; | |
+ if(f->deleted) { | |
+ delete(f); | |
+ continue; | |
+ } | |
+ if(f->mod==modnum && Fupdate(f, FALSE, downloaded)) | |
+ anymod++; | |
+ if(f->rasp) | |
+ telldot(f); | |
+ } | |
+ if(anymod) | |
+ modnum++; | |
+} | |
+ | |
+File * | |
+current(File *f) | |
+{ | |
+ return curfile = f; | |
+} | |
+ | |
+void | |
+edit(File *f, int cmd) | |
+{ | |
+ int empty = TRUE; | |
+ Posn p; | |
+ int nulls; | |
+ | |
+ if(cmd == 'r') | |
+ Fdelete(f, addr.r.p1, addr.r.p2); | |
+ if(cmd=='e' || cmd=='I'){ | |
+ Fdelete(f, (Posn)0, f->nrunes); | |
+ addr.r.p2 = f->nrunes; | |
+ }else if(f->nrunes!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0… | |
+ empty = FALSE; | |
+ if((io = open(genc, OREAD))<0) { | |
+ if (curfile && curfile->state == Unread) | |
+ curfile->state = Clean; | |
+ error_s(Eopen, genc); | |
+ } | |
+ p = readio(f, &nulls, empty); | |
+ closeio((cmd=='e' || cmd=='I')? -1 : p); | |
+ if(cmd == 'r') | |
+ f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p; | |
+ else | |
+ f->ndot.r.p1 = f->ndot.r.p2 = 0; | |
+ f->closeok = empty; | |
+ if (quitok) | |
+ quitok = empty; | |
+ else | |
+ quitok = FALSE; | |
+ state(f, empty && !nulls? Clean : Dirty); | |
+ if(cmd == 'e') | |
+ filename(f); | |
+} | |
+ | |
+int | |
+getname(File *f, String *s, int save) | |
+{ | |
+ int c, i; | |
+ | |
+ Strzero(&genstr); | |
+ if(genc){ | |
+ free(genc); | |
+ genc = 0; | |
+ } | |
+ if(s==0 || (c = s->s[0])==0){ /* no name provided */ | |
+ if(f) | |
+ Strduplstr(&genstr, &f->name); | |
+ else | |
+ Straddc(&genstr, '\0'); | |
+ goto Return; | |
+ } | |
+ if(c!=' ' && c!='\t') | |
+ error(Eblank); | |
+ for(i=0; (c=s->s[i])==' ' || c=='\t'; i++) | |
+ ; | |
+ while(s->s[i] > ' ') | |
+ Straddc(&genstr, s->s[i++]); | |
+ if(s->s[i]) | |
+ error(Enewline); | |
+ Straddc(&genstr, '\0'); | |
+ if(f && (save || f->name.s[0]==0)){ | |
+ Fsetname(f, &genstr); | |
+ if(Strcmp(&f->name, &genstr)){ | |
+ quitok = f->closeok = FALSE; | |
+ f->qid = 0; | |
+ f->date = 0; | |
+ state(f, Dirty); /* if it's 'e', fix later */ | |
+ } | |
+ } | |
+ Return: | |
+ genc = Strtoc(&genstr); | |
+ return genstr.n-1; /* strlen(name) */ | |
+} | |
+ | |
+void | |
+filename(File *f) | |
+{ | |
+ if(genc) | |
+ free(genc); | |
+ genc = Strtoc(&genstr); | |
+ dprint("%c%c%c %s\n", " '"[f->state==Dirty], | |
+ "-+"[f->rasp!=0], " ."[f==curfile], genc); | |
+} | |
+ | |
+void | |
+undostep(File *f) | |
+{ | |
+ Buffer *t; | |
+ int changes; | |
+ Mark mark; | |
+ | |
+ t = f->transcript; | |
+ changes = Fupdate(f, TRUE, TRUE); | |
+ Bread(t, (Rune*)&mark, (sizeof mark)/RUNESIZE, f->markp); | |
+ Bdelete(t, f->markp, t->nrunes); | |
+ f->markp = mark.p; | |
+ f->dot.r = mark.dot; | |
+ f->ndot.r = mark.dot; | |
+ f->mark = mark.mark; | |
+ f->mod = mark.m; | |
+ f->closeok = mark.s1!=Dirty; | |
+ if(mark.s1==Dirty) | |
+ quitok = FALSE; | |
+ if(f->state==Clean && mark.s1==Clean && changes) | |
+ state(f, Dirty); | |
+ else | |
+ state(f, mark.s1); | |
+} | |
+ | |
+int | |
+undo(void) | |
+{ | |
+ File *f; | |
+ int i; | |
+ Mod max; | |
+ if((max = curfile->mod)==0) | |
+ return 0; | |
+ settempfile(); | |
+ for(i = 0; i<tempfile.nused; i++){ | |
+ f = tempfile.filepptr[i]; | |
+ if(f!=cmd && f->mod==max) | |
+ undostep(f); | |
+ } | |
+ return 1; | |
+} | |
+ | |
+int | |
+readcmd(String *s) | |
+{ | |
+ int retcode; | |
+ | |
+ if(flist == 0) | |
+ (flist = Fopen())->state = Clean; | |
+ addr.r.p1 = 0, addr.r.p2 = flist->nrunes; | |
+ retcode = plan9(flist, '<', s, FALSE); | |
+ Fupdate(flist, FALSE, FALSE); | |
+ flist->mod = 0; | |
+ if (flist->nrunes > BLOCKSIZE) | |
+ error(Etoolong); | |
+ Strzero(&genstr); | |
+ Strinsure(&genstr, flist->nrunes); | |
+ Fchars(flist, genbuf, (Posn)0, flist->nrunes); | |
+ memmove(genstr.s, genbuf, flist->nrunes*RUNESIZE); | |
+ genstr.n = flist->nrunes; | |
+ Straddc(&genstr, '\0'); | |
+ return retcode; | |
+} | |
+ | |
+void | |
+cd(String *str) | |
+{ | |
+ int i; | |
+ File *f; | |
+ String *t; | |
+ | |
+ t = tmpcstr("/bin/pwd"); | |
+ Straddc(t, '\0'); | |
+ if (flist) { | |
+ Fclose(flist); | |
+ flist = 0; | |
+ } | |
+ if (readcmd(t) != 0) { | |
+ Strduplstr(&genstr, tmprstr(baddir, sizeof(baddir)/sizeof(Rune… | |
+ Straddc(&genstr, '\0'); | |
+ } | |
+ freetmpstr(t); | |
+ Strduplstr(&wd, &genstr); | |
+ if(wd.s[0] == 0){ | |
+ wd.n = 0; | |
+ warn(Wpwd); | |
+ }else if(wd.s[wd.n-2] == '\n'){ | |
+ --wd.n; | |
+ wd.s[wd.n-1]='/'; | |
+ } | |
+ if(chdir(getname((File *)0, str, FALSE)? genc : home)) | |
+ syserror("chdir"); | |
+ settempfile(); | |
+ for(i=0; i<tempfile.nused; i++){ | |
+ f = tempfile.filepptr[i]; | |
+ if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){ | |
+ Strinsert(&f->name, &wd, (Posn)0); | |
+ sortname(f); | |
+ } | |
+ } | |
+} | |
+ | |
+int | |
+loadflist(String *s) | |
+{ | |
+ int c, i; | |
+ | |
+ c = s->s[0]; | |
+ for(i = 0; s->s[i]==' ' || s->s[i]=='\t'; i++) | |
+ ; | |
+ if((c==' ' || c=='\t') && s->s[i]!='\n'){ | |
+ if(s->s[i]=='<'){ | |
+ Strdelete(s, 0L, (long)i+1); | |
+ readcmd(s); | |
+ }else{ | |
+ Strzero(&genstr); | |
+ while((c = s->s[i++]) && c!='\n') | |
+ Straddc(&genstr, c); | |
+ Straddc(&genstr, '\0'); | |
+ } | |
+ }else{ | |
+ if(c != '\n') | |
+ error(Eblank); | |
+ Strdupl(&genstr, empty); | |
+ } | |
+ if(genc) | |
+ free(genc); | |
+ genc = Strtoc(&genstr); | |
+ return genstr.s[0]; | |
+} | |
+ | |
+File * | |
+readflist(int readall, int delete) | |
+{ | |
+ Posn i; | |
+ int c; | |
+ File *f; | |
+ String *t; | |
+ | |
+ for(i=0,f=0; f==0 || readall || delete; i++){ /* ++ skips blank… | |
+ Strdelete(&genstr, (Posn)0, i); | |
+ for(i=0; (c = genstr.s[i])==' ' || c=='\t' || c=='\n'; i++) | |
+ ; | |
+ if(i >= genstr.n) | |
+ break; | |
+ Strdelete(&genstr, (Posn)0, i); | |
+ for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++) | |
+ ; | |
+ | |
+ if(i == 0) | |
+ break; | |
+ genstr.s[i] = 0; | |
+ t = tmprstr(genstr.s, i+1); | |
+ f = lookfile(t); | |
+ if(delete){ | |
+ if(f == 0) | |
+ warn_S(Wfile, t); | |
+ else | |
+ trytoclose(f); | |
+ }else if(f==0 && readall) | |
+ Fsetname(f = newfile(), t); | |
+ } | |
+ return f; | |
+} | |
+ | |
+File * | |
+tofile(String *s) | |
+{ | |
+ File *f; | |
+ | |
+ if(s->s[0] != ' ') | |
+ error(Eblank); | |
+ if(loadflist(s) == 0){ | |
+ f = lookfile(&genstr); /* empty string ==> nameless fil… | |
+ if(f == 0) | |
+ error_s(Emenu, genc); | |
+ }else if((f=readflist(FALSE, FALSE)) == 0) | |
+ error_s(Emenu, genc); | |
+ return current(f); | |
+} | |
+ | |
+File * | |
+getfile(String *s) | |
+{ | |
+ File *f; | |
+ | |
+ if(loadflist(s) == 0) | |
+ Fsetname(f = newfile(), &genstr); | |
+ else if((f=readflist(TRUE, FALSE)) == 0) | |
+ error(Eblank); | |
+ return current(f); | |
+} | |
+ | |
+void | |
+closefiles(File *f, String *s) | |
+{ | |
+ if(s->s[0] == 0){ | |
+ if(f == 0) | |
+ error(Enofile); | |
+ trytoclose(f); | |
+ return; | |
+ } | |
+ if(s->s[0] != ' ') | |
+ error(Eblank); | |
+ if(loadflist(s) == 0) | |
+ error(Enewline); | |
+ readflist(FALSE, TRUE); | |
+} | |
+ | |
+void | |
+copy(File *f, Address addr2) | |
+{ | |
+ Posn p; | |
+ int ni; | |
+ for(p=addr.r.p1; p<addr.r.p2; p+=ni){ | |
+ ni = addr.r.p2-p; | |
+ if(ni > BLOCKSIZE) | |
+ ni = BLOCKSIZE; | |
+ Fchars(f, genbuf, p, p+ni); | |
+ Finsert(addr2.f, tmprstr(genbuf, ni), addr2.r.p2); | |
+ } | |
+ addr2.f->ndot.r.p2 = addr2.r.p2+(f->dot.r.p2-f->dot.r.p1); | |
+ addr2.f->ndot.r.p1 = addr2.r.p2; | |
+} | |
+ | |
+void | |
+move(File *f, Address addr2) | |
+{ | |
+ if(addr.r.p2 <= addr2.r.p2){ | |
+ Fdelete(f, addr.r.p1, addr.r.p2); | |
+ copy(f, addr2); | |
+ }else if(addr.r.p1 >= addr2.r.p2){ | |
+ copy(f, addr2); | |
+ Fdelete(f, addr.r.p1, addr.r.p2); | |
+ }else | |
+ error(Eoverlap); | |
+} | |
+ | |
+Posn | |
+nlcount(File *f, Posn p0, Posn p1) | |
+{ | |
+ Posn nl = 0; | |
+ | |
+ Fgetcset(f, p0); | |
+ while(p0++<p1) | |
+ if(Fgetc(f)=='\n') | |
+ nl++; | |
+ return nl; | |
+} | |
+ | |
+void | |
+printposn(File *f, int charsonly) | |
+{ | |
+ Posn l1, l2; | |
+ | |
+ if(!charsonly){ | |
+ l1 = 1+nlcount(f, (Posn)0, addr.r.p1); | |
+ l2 = l1+nlcount(f, addr.r.p1, addr.r.p2); | |
+ /* check if addr ends with '\n' */ | |
+ if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && (Fgetcset(f, addr.r.p… | |
+ --l2; | |
+ dprint("%lu", l1); | |
+ if(l2 != l1) | |
+ dprint(",%lu", l2); | |
+ dprint("; "); | |
+ } | |
+ dprint("#%lu", addr.r.p1); | |
+ if(addr.r.p2 != addr.r.p1) | |
+ dprint(",#%lu", addr.r.p2); | |
+ dprint("\n"); | |
+} | |
+ | |
+void | |
+settempfile(void) | |
+{ | |
+ if(tempfile.nalloc < file.nused){ | |
+ free(tempfile.listptr); | |
+ tempfile.listptr = emalloc(sizeof(*tempfile.filepptr)*file.nus… | |
+ tempfile.nalloc = file.nused; | |
+ } | |
+ tempfile.nused = file.nused; | |
+ memmove(&tempfile.filepptr[0], &file.filepptr[0], file.nused*sizeof(Fi… | |
+} | |
diff --git a/sam/sam.h b/sam/sam.h | |
@@ -0,0 +1,408 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include "errors.h" | |
+ | |
+/* | |
+ * BLOCKSIZE is relatively small to keep memory consumption down. | |
+ */ | |
+ | |
+#define BLOCKSIZE 2048 | |
+#define RUNESIZE sizeof(Rune) | |
+#define NDISC 5 | |
+#define NBUFFILES 3+2*NDISC /* plan 9+undo+snarf+NDISC*(t… | |
+#define NSUBEXP 10 | |
+ | |
+#define TRUE 1 | |
+#define FALSE 0 | |
+ | |
+#define INFINITY 0x7FFFFFFFL | |
+#define INCR 25 | |
+#define STRSIZE (2*BLOCKSIZE) | |
+ | |
+typedef long Posn; /* file position or address */ | |
+typedef ushort Mod; /* modification numbe… | |
+ | |
+typedef struct Address Address; | |
+typedef struct Block Block; | |
+typedef struct Buffer Buffer; | |
+typedef struct Disc Disc; | |
+typedef struct Discdesc Discdesc; | |
+typedef struct File File; | |
+typedef struct List List; | |
+typedef struct Mark Mark; | |
+typedef struct Range Range; | |
+typedef struct Rangeset Rangeset; | |
+typedef struct String String; | |
+ | |
+enum State | |
+{ | |
+ Clean = ' ', | |
+ Dirty = '\'', | |
+ Unread = '-', | |
+ Readerr = '~' | |
+}; | |
+ | |
+struct Range | |
+{ | |
+ Posn p1, p2; | |
+}; | |
+ | |
+struct Rangeset | |
+{ | |
+ Range p[NSUBEXP]; | |
+}; | |
+ | |
+struct Address | |
+{ | |
+ Range r; | |
+ File *f; | |
+}; | |
+ | |
+struct List /* code depends on a long being able to hold a pointer */ | |
+{ | |
+ int nalloc; | |
+ int nused; | |
+ union{ | |
+ void *listp; | |
+ Block *blkp; | |
+ long *longp; | |
+ uchar* *ucharp; | |
+ String* *stringp; | |
+ File* *filep; | |
+ long listv; | |
+ }g; | |
+}; | |
+ | |
+#define listptr g.listp | |
+#define blkptr g.blkp | |
+#define longptr g.longp | |
+#define ucharpptr g.ucharp | |
+#define stringpptr g.stringp | |
+#define filepptr g.filep | |
+#define listval g.listv | |
+ | |
+/* | |
+ * Block must fit in a long because the list routines manage arrays of | |
+ * blocks. Two problems: some machines (e.g. Cray) can't pull this off | |
+ * -- on them, use bitfields -- and the ushort bnum limits temp file sizes | |
+ * to about 200 megabytes. Advantages: small, simple code and small | |
+ * memory overhead. If you really want to edit huge files, making BLOCKSIZE | |
+ * bigger is the easiest way. | |
+* | |
+* The necessary conditions are even stronger: | |
+* sizeof(struct Block)==sizeof(long) | |
+* && the first 32 bits must hold bnum and nrunes. | |
+* When sizeof(ushort)+sizeof(short) < sizeof(long), | |
+* add padding at the beginning on a little endian and at | |
+* the end on a big endian, as shown below for the DEC Alpha. | |
+ */ | |
+struct Block | |
+{ | |
+#if USE64BITS == 1 | |
+ char pad[sizeof(long)-sizeof(ushort)-sizeof(short)]; | |
+#endif | |
+ ushort bnum; /* absolute number on disk */ | |
+ short nrunes; /* runes stored in this block */ | |
+#if USE64BITS == 2 | |
+ char pad[sizeof(long)-sizeof(ushort)-sizeof(short)]; | |
+#endif | |
+}; | |
+ | |
+struct Discdesc | |
+{ | |
+ int fd; /* plan 9 file descriptor of temp file */ | |
+ ulong nbk; /* high water mark */ | |
+ List free; /* array of free block indices */ | |
+}; | |
+ | |
+struct Disc | |
+{ | |
+ Discdesc *desc; /* descriptor of temp file */ | |
+ Posn nrunes; /* runes on disc file */ | |
+ List block; /* list of used block indices */ | |
+}; | |
+ | |
+struct String | |
+{ | |
+ short n; | |
+ short size; | |
+ Rune *s; | |
+}; | |
+ | |
+struct Buffer | |
+{ | |
+ Disc *disc; /* disc storage */ | |
+ Posn nrunes; /* total length of buffer */ | |
+ String cache; /* in-core storage for efficiency … | |
+ Posn c1, c2; /* cache start and end positions in… | |
+ /* note: if dirty, cache is really c1, c1+cach… | |
+ int dirty; /* cache dirty */ | |
+}; | |
+ | |
+#define NGETC 128 | |
+ | |
+struct File | |
+{ | |
+ Buffer *buf; /* cached disc storage */ | |
+ Buffer *transcript; /* what's been done */ | |
+ Posn markp; /* file pointer to start of latest c… | |
+ Mod mod; /* modification stamp */ | |
+ Posn nrunes; /* total length of file */ | |
+ Posn hiposn; /* highest address touched this Mod… | |
+ Address dot; /* current position */ | |
+ Address ndot; /* new current position after upda… | |
+ Range tdot; /* what terminal thinks is current r… | |
+ Range mark; /* tagged spot in text (don't confus… | |
+ List *rasp; /* map of what terminal's got */ | |
+ String name; /* file name */ | |
+ short tag; /* for communicating with terminal */ | |
+ char state; /* Clean, Dirty, Unread, or Readerr*/ | |
+ char closeok; /* ok to close file? */ | |
+ char deleted; /* delete at completion of command */ | |
+ char marked; /* file has been Fmarked at least o… | |
+ * set, this will never go off as undo doesn't | |
+ * revert to the dawn of time */ | |
+ long dev; /* file system from which it was read … | |
+ long qid; /* file from which it was read */ | |
+ long date; /* time stamp of plan9 file */ | |
+ Posn cp1, cp2; /* Write-behind cache positions and */ | |
+ String cache; /* string */ | |
+ Rune getcbuf[NGETC]; | |
+ int ngetc; | |
+ int getci; | |
+ Posn getcp; | |
+}; | |
+ | |
+struct Mark | |
+{ | |
+ Posn p; | |
+ Range dot; | |
+ Range mark; | |
+ Mod m; | |
+ short s1; | |
+}; | |
+ | |
+/* | |
+ * The precedent to any message in the transcript. | |
+ * The component structures must be an integral number of Runes long. | |
+ */ | |
+union Hdr | |
+{ | |
+ struct _csl | |
+ { | |
+ short c; | |
+ short s; | |
+ long l; | |
+ }csl; | |
+ struct _cs | |
+ { | |
+ short c; | |
+ short s; | |
+ }cs; | |
+ struct _cll | |
+ { | |
+ short c; | |
+ long l; | |
+ long l1; | |
+ }cll; | |
+ Mark mark; | |
+}; | |
+ | |
+#define Fgetc(f) ((--(f)->ngetc<0)? Fgetcload(f, (f)->getcp) : (f)->ge… | |
+#define Fbgetc(f) (((f)->getci<=0)? Fbgetcload(f, (f)->getcp) : (f)->ge… | |
+ | |
+int alnum(int); | |
+void Bclean(Buffer*); | |
+void Bterm(Buffer*); | |
+void Bdelete(Buffer*, Posn, Posn); | |
+void Bflush(Buffer*); | |
+void Binsert(Buffer*, String*, Posn); | |
+Buffer *Bopen(Discdesc*); | |
+int Bread(Buffer*, Rune*, int, Posn); | |
+void Dclose(Disc*); | |
+void Ddelete(Disc*, Posn, Posn); | |
+void Dinsert(Disc*, Rune*, int, Posn); | |
+Disc *Dopen(Discdesc*); | |
+int Dread(Disc*, Rune*, int, Posn); | |
+void Dreplace(Disc*, Posn, Posn, Rune*, int); | |
+int Fbgetcload(File*, Posn); | |
+int Fbgetcset(File*, Posn); | |
+long Fchars(File*, Rune*, Posn, Posn); | |
+void Fclose(File*); | |
+void Fdelete(File*, Posn, Posn); | |
+int Fgetcload(File*, Posn); | |
+int Fgetcset(File*, Posn); | |
+void Finsert(File*, String*, Posn); | |
+File *Fopen(void); | |
+void Fsetname(File*, String*); | |
+void Fstart(void); | |
+int Fupdate(File*, int, int); | |
+int Read(int, void*, int); | |
+void Seek(int, long, int); | |
+int plan9(File*, int, String*, int); | |
+int Write(int, void*, int); | |
+int bexecute(File*, Posn); | |
+void cd(String*); | |
+void closefiles(File*, String*); | |
+void closeio(Posn); | |
+void cmdloop(void); | |
+void cmdupdate(void); | |
+void compile(String*); | |
+void copy(File*, Address); | |
+File *current(File*); | |
+void delete(File*); | |
+void delfile(File*); | |
+void dellist(List*, int); | |
+void doubleclick(File*, Posn); | |
+void dprint(char*, ...); | |
+void edit(File*, int); | |
+void *emalloc(ulong); | |
+void *erealloc(void*, ulong); | |
+void error(Err); | |
+void error_c(Err, int); | |
+void error_s(Err, char*); | |
+int execute(File*, Posn, Posn); | |
+int filematch(File*, String*); | |
+void filename(File*); | |
+File *getfile(String*); | |
+int getname(File*, String*, int); | |
+long getnum(void); | |
+void hiccough(char*); | |
+void inslist(List*, int, long); | |
+Address lineaddr(Posn, Address, int); | |
+void listfree(List*); | |
+void load(File*); | |
+File *lookfile(String*); | |
+void lookorigin(File*, Posn, Posn); | |
+int lookup(int); | |
+void move(File*, Address); | |
+void moveto(File*, Range); | |
+File *newfile(void); | |
+void nextmatch(File*, String*, Posn, int); | |
+int newtmp(int); | |
+void notifyf(void*, char*); | |
+void panic(char*); | |
+void printposn(File*, int); | |
+void print_ss(char*, String*, String*); | |
+void print_s(char*, String*); | |
+int rcv(void); | |
+Range rdata(List*, Posn, Posn); | |
+Posn readio(File*, int*, int); | |
+void rescue(void); | |
+void resetcmd(void); | |
+void resetsys(void); | |
+void resetxec(void); | |
+void rgrow(List*, Posn, Posn); | |
+void samerr(char*); | |
+void settempfile(void); | |
+int skipbl(void); | |
+void snarf(File*, Posn, Posn, Buffer*, int); | |
+void sortname(File*); | |
+void startup(char*, int, char**, char**); | |
+void state(File*, int); | |
+int statfd(int, ulong*, ulong*, long*, long*, long*); | |
+int statfile(char*, ulong*, ulong*, long*, long*, long*); | |
+void Straddc(String*, int); | |
+void Strclose(String*); | |
+int Strcmp(String*, String*); | |
+void Strdelete(String*, Posn, Posn); | |
+void Strdupl(String*, Rune*); | |
+void Strduplstr(String*, String*); | |
+void Strinit(String*); | |
+void Strinit0(String*); | |
+void Strinsert(String*, String*, Posn); | |
+void Strinsure(String*, ulong); | |
+void Strzero(String*); | |
+int Strlen(Rune*); | |
+char *Strtoc(String*); | |
+void syserror(char*); | |
+void telldot(File*); | |
+void tellpat(void); | |
+String *tmpcstr(char*); | |
+String *tmprstr(Rune*, int); | |
+void freetmpstr(String*); | |
+void termcommand(void); | |
+void termwrite(char*); | |
+File *tofile(String*); | |
+void toterminal(File*, int); | |
+void trytoclose(File*); | |
+void trytoquit(void); | |
+int undo(void); | |
+void update(void); | |
+int waitfor(int); | |
+void warn(Warn); | |
+void warn_s(Warn, char*); | |
+void warn_SS(Warn, String*, String*); | |
+void warn_S(Warn, String*); | |
+int whichmenu(File*); | |
+void writef(File*); | |
+Posn writeio(File*); | |
+Discdesc *Dstart(void); | |
+ | |
+extern Rune samname[]; /* compiler dependent */ | |
+extern Rune *left[]; | |
+extern Rune *right[]; | |
+ | |
+extern char RSAM[]; /* system dependent */ | |
+extern char SAMTERM[]; | |
+extern char HOME[]; | |
+extern char TMPDIR[]; | |
+extern char SH[]; | |
+extern char SHPATH[]; | |
+extern char RX[]; | |
+extern char RXPATH[]; | |
+extern char SAMSAVECMD[]; | |
+ | |
+extern char *rsamname; /* globals */ | |
+extern char *samterm; | |
+extern Rune genbuf[]; | |
+extern char *genc; | |
+extern int io; | |
+extern int patset; | |
+extern int quitok; | |
+extern Address addr; | |
+extern Buffer *undobuf; | |
+extern Buffer *snarfbuf; | |
+extern Buffer *plan9buf; | |
+extern List file; | |
+extern List tempfile; | |
+extern File *cmd; | |
+extern File *curfile; | |
+extern File *lastfile; | |
+extern Mod modnum; | |
+extern Posn cmdpt; | |
+extern Posn cmdptadv; | |
+extern Rangeset sel; | |
+extern String cmdstr; | |
+extern String genstr; | |
+extern String lastpat; | |
+extern String lastregexp; | |
+extern String plan9cmd; | |
+extern int downloaded; | |
+extern int eof; | |
+extern int bpipeok; | |
+extern int panicking; | |
+extern Rune empty[]; | |
+extern int termlocked; | |
+extern int noflush; | |
+ | |
+#include "mesg.h" | |
+ | |
+void outTs(Hmesg, int); | |
+void outT0(Hmesg); | |
+void outTl(Hmesg, long); | |
+void outTslS(Hmesg, int, long, String*); | |
+void outTS(Hmesg, String*); | |
+void outTsS(Hmesg, int, String*); | |
+void outTsllS(Hmesg, int, long, long, String*); | |
+void outTsll(Hmesg, int, long, long); | |
+void outTsl(Hmesg, int, long); | |
+void outTsv(Hmesg, int, long); | |
+void outstart(Hmesg); | |
+void outcopy(int, void*); | |
+void outshort(int); | |
+void outlong(long); | |
+void outvlong(void*); | |
+void outsend(void); | |
+void outflush(void); | |
diff --git a/sam/samsave b/sam/samsave | |
@@ -0,0 +1,14 @@ | |
+#!/bin/sh | |
+# Copyright (c) 1998 Lucent Technologies - All rights reserved. | |
+PATH=/bin:/usr/bin | |
+file=$1 | |
+case "$2" in | |
+-f) echo "$file" | |
+ cat > $file | |
+ ;; | |
+"") echo "$file?" | |
+ read yn < /dev/tty | |
+ case "$yn" in | |
+ [Yy]*) cat > $file | |
+ esac | |
+esac | |
diff --git a/sam/shell.c b/sam/shell.c | |
@@ -0,0 +1,155 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+#include "parse.h" | |
+ | |
+extern jmp_buf mainloop; | |
+ | |
+char errfile[64]; | |
+String plan9cmd; /* null terminated */ | |
+Buffer *plan9buf; | |
+void checkerrs(void); | |
+ | |
+int | |
+plan9(File *f, int type, String *s, int nest) | |
+{ | |
+ long l; | |
+ int m; | |
+ int pid, fd; | |
+ int retcode; | |
+ int pipe1[2], pipe2[2]; | |
+ | |
+ if(s->s[0]==0 && plan9cmd.s[0]==0) | |
+ error(Enocmd); | |
+ else if(s->s[0]) | |
+ Strduplstr(&plan9cmd, s); | |
+ if(downloaded) | |
+ samerr(errfile); | |
+ else | |
+ strcpy(errfile, "/dev/tty"); | |
+ if(type!='!' && pipe(pipe1)==-1) | |
+ error(Epipe); | |
+ if(type=='|') | |
+ snarf(f, addr.r.p1, addr.r.p2, plan9buf, 1); | |
+ if(downloaded) | |
+ remove(errfile); | |
+ if((pid=fork()) == 0){ | |
+ if(downloaded){ /* also put nasty fd's into errfile */ | |
+ fd = create(errfile, 1, 0666L); | |
+ if(fd < 0) | |
+ fd = create("/dev/null", 1, 0666L); | |
+ dup(fd, 2); | |
+ close(fd); | |
+ /* 2 now points at err file */ | |
+ if(type == '>') | |
+ dup(2, 1); | |
+ else if(type=='!'){ | |
+ dup(2, 1); | |
+ fd = open("/dev/null", 0); | |
+ dup(fd, 0); | |
+ close(fd); | |
+ } | |
+ } | |
+ if(type != '!') { | |
+ if(type=='<' || type=='|') | |
+ dup(pipe1[1], 1); | |
+ else if(type == '>') | |
+ dup(pipe1[0], 0); | |
+ close(pipe1[0]); | |
+ close(pipe1[1]); | |
+ } | |
+ if(type == '|'){ | |
+ if(pipe(pipe2) == -1) | |
+ exits("pipe"); | |
+ if((pid = fork())==0){ | |
+ /* | |
+ * It's ok if we get SIGPIPE here | |
+ */ | |
+ close(pipe2[0]); | |
+ io = pipe2[1]; | |
+ if(retcode=!setjmp(mainloop)){ /* assig… | |
+ char *c; | |
+ for(l = 0; l<plan9buf->nrunes; l+=m){ | |
+ m = plan9buf->nrunes-l; | |
+ if(m>BLOCKSIZE-1) | |
+ m = BLOCKSIZE-1; | |
+ Bread(plan9buf, genbuf, m, l); | |
+ genbuf[m] = 0; | |
+ c = Strtoc(tmprstr(genbuf, m+1… | |
+ Write(pipe2[1], c, strlen(c)); | |
+ free(c); | |
+ } | |
+ } | |
+ exits(retcode? "error" : 0); | |
+ } | |
+ if(pid==-1){ | |
+ fprint(2, "Can't fork?!\n"); | |
+ exits("fork"); | |
+ } | |
+ dup(pipe2[0], 0); | |
+ close(pipe2[0]); | |
+ close(pipe2[1]); | |
+ } | |
+ if(type=='<'){ | |
+ close(0); /* so it won't read from terminal */ | |
+ open("/dev/null", 0); | |
+ } | |
+ execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), (char *)0); | |
+ exits("exec"); | |
+ } | |
+ if(pid == -1) | |
+ error(Efork); | |
+ if(type=='<' || type=='|'){ | |
+ int nulls; | |
+ if(downloaded && addr.r.p1 != addr.r.p2) | |
+ outTl(Hsnarflen, addr.r.p2-addr.r.p1); | |
+ snarf(f, addr.r.p1, addr.r.p2, snarfbuf, 0); | |
+ Fdelete(f, addr.r.p1, addr.r.p2); | |
+ close(pipe1[1]); | |
+ io = pipe1[0]; | |
+ f->tdot.p1 = -1; | |
+ f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0); | |
+ f->ndot.r.p1 = addr.r.p2; | |
+ closeio((Posn)-1); | |
+ }else if(type=='>'){ | |
+ close(pipe1[0]); | |
+ io = pipe1[1]; | |
+ bpipeok = 1; | |
+ writeio(f); | |
+ bpipeok = 0; | |
+ closeio((Posn)-1); | |
+ } | |
+ retcode = waitfor(pid); | |
+ if(type=='|' || type=='<') | |
+ if(retcode!=0) | |
+ warn(Wbadstatus); | |
+ if(downloaded) | |
+ checkerrs(); | |
+ if(!nest) | |
+ dprint("!\n"); | |
+ return retcode; | |
+} | |
+ | |
+void | |
+checkerrs(void) | |
+{ | |
+ char buf[256]; | |
+ int f, n, nl; | |
+ char *p; | |
+ long l; | |
+ | |
+ if(statfile(errfile, 0, 0, 0, &l, 0) > 0 && l != 0){ | |
+ if((f=open((char *)errfile, 0)) != -1){ | |
+ if((n=read(f, buf, sizeof buf-1)) > 0){ | |
+ for(nl=0,p=buf; nl<3 && p<&buf[n]; p++) | |
+ if(*p=='\n') | |
+ nl++; | |
+ *p = 0; | |
+ dprint("%s", buf); | |
+ if(p-buf < l-1) | |
+ dprint("(sam: more in %s)\n", errfile); | |
+ } | |
+ close(f); | |
+ } | |
+ }else | |
+ remove((char *)errfile); | |
+} | |
diff --git a/sam/string.c b/sam/string.c | |
@@ -0,0 +1,179 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+#define MINSIZE 16 /* minimum number of chars all… | |
+#define MAXSIZE 256 /* maximum number of chars fo… | |
+ | |
+ | |
+void | |
+Strinit(String *p) | |
+{ | |
+ p->s = emalloc(MINSIZE*RUNESIZE); | |
+ p->n = 0; | |
+ p->size = MINSIZE; | |
+} | |
+ | |
+void | |
+Strinit0(String *p) | |
+{ | |
+ p->s = emalloc(MINSIZE*RUNESIZE); | |
+ p->s[0] = 0; | |
+ p->n = 1; | |
+ p->size = MINSIZE; | |
+} | |
+ | |
+void | |
+Strclose(String *p) | |
+{ | |
+ free(p->s); | |
+} | |
+ | |
+void | |
+Strzero(String *p) | |
+{ | |
+ if(p->size > MAXSIZE){ | |
+ p->s = erealloc(p->s, RUNESIZE*MAXSIZE); /* throw away the gar… | |
+ p->size = MAXSIZE; | |
+ } | |
+ p->n = 0; | |
+} | |
+ | |
+int | |
+Strlen(Rune *r) | |
+{ | |
+ Rune *s; | |
+ | |
+ for(s=r; *s; s++) | |
+ ; | |
+ return s-r; | |
+} | |
+ | |
+void | |
+Strdupl(String *p, Rune *s) /* copies the null */ | |
+{ | |
+ p->n = Strlen(s)+1; | |
+ Strinsure(p, p->n); | |
+ memmove(p->s, s, p->n*RUNESIZE); | |
+} | |
+ | |
+void | |
+Strduplstr(String *p, String *q) /* will copy the null if there's one t… | |
+{ | |
+ Strinsure(p, q->n); | |
+ p->n = q->n; | |
+ memmove(p->s, q->s, q->n*RUNESIZE); | |
+} | |
+ | |
+void | |
+Straddc(String *p, int c) | |
+{ | |
+ Strinsure(p, p->n+1); | |
+ p->s[p->n++] = c; | |
+} | |
+ | |
+void | |
+Strinsure(String *p, ulong n) | |
+{ | |
+ if(n > STRSIZE) | |
+ error(Etoolong); | |
+ if(p->size < n){ /* p needs to grow */ | |
+ n += 100; | |
+ p->s = erealloc(p->s, n*RUNESIZE); | |
+ p->size = n; | |
+ } | |
+} | |
+ | |
+void | |
+Strinsert(String *p, String *q, Posn p0) | |
+{ | |
+ Strinsure(p, p->n+q->n); | |
+ memmove(p->s+p0+q->n, p->s+p0, (p->n-p0)*RUNESIZE); | |
+ memmove(p->s+p0, q->s, q->n*RUNESIZE); | |
+ p->n += q->n; | |
+} | |
+ | |
+void | |
+Strdelete(String *p, Posn p1, Posn p2) | |
+{ | |
+ memmove(p->s+p1, p->s+p2, (p->n-p2)*RUNESIZE); | |
+ p->n -= p2-p1; | |
+} | |
+ | |
+int | |
+Strcmp(String *a, String *b) | |
+{ | |
+ int i, c; | |
+ | |
+ for(i=0; i<a->n && i<b->n; i++) | |
+ if(c = (a->s[i] - b->s[i])) /* assign = */ | |
+ return c; | |
+ /* damn NULs confuse everything */ | |
+ i = a->n - b->n; | |
+ if(i == 1){ | |
+ if(a->s[a->n-1] == 0) | |
+ return 0; | |
+ }else if(i == -1){ | |
+ if(b->s[b->n-1] == 0) | |
+ return 0; | |
+ } | |
+ return i; | |
+} | |
+ | |
+char* | |
+Strtoc(String *s) | |
+{ | |
+ int i; | |
+ char *c, *d; | |
+ Rune *r; | |
+ c = emalloc(s->n*UTFmax + 1); /* worst case UTFmax bytes per rune, pl… | |
+ d = c; | |
+ r = s->s; | |
+ for(i=0; i<s->n; i++) | |
+ d += runetochar(d, r++); | |
+ if(d==c || d[-1]!=0) | |
+ *d = 0; | |
+ return c; | |
+ | |
+} | |
+ | |
+/* | |
+ * Build very temporary String from Rune* | |
+ */ | |
+String* | |
+tmprstr(Rune *r, int n) | |
+{ | |
+ static String p; | |
+ | |
+ p.s = r; | |
+ p.n = n; | |
+ p.size = n; | |
+ return &p; | |
+} | |
+ | |
+/* | |
+ * Convert null-terminated char* into String | |
+ */ | |
+String* | |
+tmpcstr(char *s) | |
+{ | |
+ String *p; | |
+ Rune *r; | |
+ int i, n; | |
+ | |
+ n = utflen(s); /* don't include NUL */ | |
+ p = emalloc(sizeof(String)); | |
+ r = emalloc(n*RUNESIZE); | |
+ p->s = r; | |
+ for(i=0; i<n; i++,r++) | |
+ s += chartorune(r, s); | |
+ p->n = n; | |
+ p->size = n; | |
+ return p; | |
+} | |
+ | |
+void | |
+freetmpstr(String *s) | |
+{ | |
+ free(s->s); | |
+ free(s); | |
+} | |
diff --git a/sam/sys.c b/sam/sys.c | |
@@ -0,0 +1,61 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+ | |
+static int inerror=FALSE; | |
+ | |
+/* | |
+ * A reasonable interface to the system calls | |
+ */ | |
+ | |
+void | |
+resetsys(void) | |
+{ | |
+ inerror = FALSE; | |
+} | |
+ | |
+void | |
+syserror(char *a) | |
+{ | |
+ char buf[ERRLEN]; | |
+ | |
+ if(!inerror){ | |
+ inerror=TRUE; | |
+ errstr(buf); | |
+ dprint("%s: ", a); | |
+ error_s(Eio, buf); | |
+ } | |
+} | |
+ | |
+int | |
+Read(int f, void *a, int n) | |
+{ | |
+ char buf[ERRLEN]; | |
+ | |
+ if(read(f, (char *)a, n)!=n) { | |
+ if (lastfile) | |
+ lastfile->state = Readerr; | |
+ errstr(buf); | |
+ if (downloaded) | |
+ fprint(2, "read error: %s\n", buf); | |
+ rescue(); | |
+ exits("read"); | |
+ } | |
+ return n; | |
+} | |
+ | |
+int | |
+Write(int f, void *a, int n) | |
+{ | |
+ int m; | |
+ | |
+ if((m=write(f, (char *)a, n))!=n) | |
+ syserror("write"); | |
+ return m; | |
+} | |
+ | |
+void | |
+Seek(int f, long n, int w) | |
+{ | |
+ if(seek(f, n, w)==-1) | |
+ syserror("seek"); | |
+} | |
diff --git a/sam/unix.c b/sam/unix.c | |
@@ -0,0 +1,220 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+#include <sys/stat.h> | |
+#include <sys/wait.h> | |
+#include <signal.h> | |
+ | |
+#ifdef NEEDVARARG | |
+#include <varargs.h> | |
+#else | |
+#include <stdarg.h> | |
+#endif | |
+ | |
+Rune samname[] = { '~', '~', 's', 'a', 'm', '~', '~', 0 }; | |
+ | |
+static Rune l1[] = { '{', '[', '(', '<', 0253, 0}; | |
+static Rune l2[] = { '\n', 0}; | |
+static Rune l3[] = { '\'', '"', '`', 0}; | |
+Rune *left[]= { l1, l2, l3, 0}; | |
+ | |
+static Rune r1[] = {'}', ']', ')', '>', 0273, 0}; | |
+static Rune r2[] = {'\n', 0}; | |
+static Rune r3[] = {'\'', '"', '`', 0}; | |
+Rune *right[]= { r1, r2, r3, 0}; | |
+ | |
+char RSAM[] = RSAMNAME; | |
+char SAMTERM[] = TERMNAME; | |
+char HOME[] = HOMEDIR; | |
+char TMPDIR[] = TMP; | |
+char SH[] = SHELLNAME; | |
+char SHPATH[] = SHELLPATH; | |
+char RX[] = RXNAME; | |
+char RXPATH[] = RXPATHNAME; | |
+char SAMSAVECMD[] = SAMSAVE; | |
+ | |
+void | |
+print_ss(char *s, String *a, String *b) | |
+{ | |
+ char *ap, *bp, *cp; | |
+ Rune *rp; | |
+ | |
+ ap = emalloc(a->n+1); | |
+ for (cp = ap, rp = a->s; *rp; rp++) | |
+ cp += runetochar(cp, rp); | |
+ *cp = 0; | |
+ bp = emalloc(b->n+1); | |
+ for (cp = bp, rp = b->s; *rp; rp++) | |
+ cp += runetochar(cp, rp); | |
+ *cp = 0; | |
+ dprint("?warning: %s `%.*s' and `%.*s'\n", s, a->n, ap, b->n, bp); | |
+ free(ap); | |
+ free(bp); | |
+} | |
+ | |
+void | |
+print_s(char *s, String *a) | |
+{ | |
+ char *ap, *cp; | |
+ Rune *rp; | |
+ | |
+ ap = emalloc(a->n+1); | |
+ for (cp = ap, rp = a->s; *rp; rp++) | |
+ cp += runetochar(cp, rp); | |
+ *cp = 0; | |
+ dprint("?warning: %s `%.*s'\n", s, a->n, ap); | |
+ free(ap); | |
+} | |
+ | |
+int | |
+statfile(char *name, ulong *dev, ulong *id, long *time, long *length, long *ap… | |
+{ | |
+ struct stat dirb; | |
+ | |
+ if (stat(name, &dirb) == -1) | |
+ return -1; | |
+ if (dev) | |
+ *dev = dirb.st_dev; | |
+ if (id) | |
+ *id = dirb.st_ino; | |
+ if (time) | |
+ *time = dirb.st_mtime; | |
+ if (length) | |
+ *length = dirb.st_size; | |
+ if(appendonly) | |
+ *appendonly = 0; | |
+ return 1; | |
+} | |
+ | |
+int | |
+statfd(int fd, ulong *dev, ulong *id, long *time, long *length, long *appendon… | |
+{ | |
+ struct stat dirb; | |
+ | |
+ if (fstat(fd, &dirb) == -1) | |
+ return -1; | |
+ if (dev) | |
+ *dev = dirb.st_dev; | |
+ if (id) | |
+ *id = dirb.st_ino; | |
+ if (time) | |
+ *time = dirb.st_mtime; | |
+ if (length) | |
+ *length = dirb.st_size; | |
+ if(appendonly) | |
+ *appendonly = 0; | |
+ return 1; | |
+} | |
+ | |
+void | |
+hup(int sig) | |
+{ | |
+ rescue(); | |
+ exit(1); | |
+} | |
+ | |
+int | |
+notify (void(*f)(void *, char *)) | |
+{ | |
+ signal(SIGINT, SIG_IGN); | |
+ signal(SIGHUP, hup); | |
+ signal(SIGPIPE, SIG_IGN); | |
+#ifdef v10 | |
+ close(3); /* redirect v10 /dev/tty */ | |
+ open("/dev/null", 2); | |
+#endif | |
+ return 1; | |
+} | |
+ | |
+void | |
+notifyf(void *a, char *b) /* never called */ | |
+{ | |
+} | |
+ | |
+/* | |
+ * if your system doesn't have tempnam(), substitute the following | |
+ * code for this function: | |
+ * FILE *f; | |
+ * f = tmpfile(); | |
+ * if (f == 0) | |
+ * return -1; | |
+ * return fileno(f); | |
+ * | |
+ * we use tempnam to allow temp files to be allocated in the | |
+ * most efficient place; nodes with disks may mount /usr/tmp | |
+ * remotely, causing excessive network traffic. place | |
+ * the temp files locally, if possible. | |
+ */ | |
+int | |
+newtmp(int i) | |
+{ | |
+ char s[1024] = {0}; | |
+ sprint(s, "%s/sam.XXXXXX", TMPDIR); | |
+ int fd = mkstemp(s); | |
+ if (fd >= 0) | |
+ { | |
+ unlink(s); | |
+ } | |
+ return fd; | |
+} | |
+ | |
+void | |
+samerr(char *buf) | |
+{ | |
+ sprint(buf, "%s/sam.err.%.6s", TMPDIR, getuser()); | |
+} | |
+ | |
+int | |
+waitfor(int pid) | |
+{ | |
+ int wm; | |
+ int rpid; | |
+ | |
+ do; while((rpid = wait(&wm)) != pid && rpid != -1); | |
+ return (WEXITSTATUS(wm)); | |
+} | |
+ | |
+void* | |
+emalloc(ulong n) | |
+{ | |
+ void *p; | |
+ | |
+ if (n < sizeof(int)) | |
+ n = sizeof(int); | |
+ p = malloc(n); | |
+ if(p == 0) | |
+ panic("malloc fails"); | |
+ memset(p, 0, n); | |
+ return p; | |
+} | |
+ | |
+void* | |
+erealloc(void *p, ulong n) | |
+{ | |
+ p = realloc(p, n); | |
+ if(p == 0) | |
+ panic("realloc fails"); | |
+ return p; | |
+} | |
+ | |
+void | |
+exits(char *message) | |
+{ | |
+ | |
+ if (message == 0) | |
+ exit(0); | |
+ else | |
+ exit(1); | |
+} | |
+ | |
+void | |
+dprint(char *z, ...) | |
+{ | |
+ va_list args; | |
+ char buf[BLOCKSIZE]; | |
+ | |
+ va_start(args, z); | |
+ vsprintf(buf, z, args); | |
+ termwrite(buf); | |
+ va_end(args); | |
+} | |
+ | |
diff --git a/sam/xec.c b/sam/xec.c | |
@@ -0,0 +1,492 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include "sam.h" | |
+#include "parse.h" | |
+ | |
+int Glooping; | |
+int nest; | |
+ | |
+int append(File*, Cmd*, Posn); | |
+int display(File*); | |
+void looper(File*, Cmd*, int); | |
+void filelooper(Cmd*, int); | |
+void linelooper(File*, Cmd*); | |
+ | |
+void | |
+resetxec(void) | |
+{ | |
+ Glooping = nest = 0; | |
+} | |
+ | |
+int | |
+cmdexec(File *f, Cmd *cp) | |
+{ | |
+ int i; | |
+ Addr *ap; | |
+ Address a; | |
+ | |
+ if(f && f->state==Unread) | |
+ load(f); | |
+ if(f==0 && (cp->addr==0 || cp->addr->type!='"') && | |
+ !utfrune("bBnqUXY!", cp->cmdc) && | |
+ cp->cmdc!=('c'|0x100) && !(cp->cmdc=='D' && cp->ctext)) | |
+ error(Enofile); | |
+ i = lookup(cp->cmdc); | |
+ if(i >= 0 && cmdtab[i].defaddr != aNo){ | |
+ if((ap=cp->addr)==0 && cp->cmdc!='\n'){ | |
+ cp->addr = ap = newaddr(); | |
+ ap->type = '.'; | |
+ if(cmdtab[i].defaddr == aAll) | |
+ ap->type = '*'; | |
+ }else if(ap && ap->type=='"' && ap->next==0 && cp->cmdc!='\n'){ | |
+ ap->next = newaddr(); | |
+ ap->next->type = '.'; | |
+ if(cmdtab[i].defaddr == aAll) | |
+ ap->next->type = '*'; | |
+ } | |
+ if(cp->addr){ /* may be false for '\n' (only) */ | |
+ static Address none = {0,0,0}; | |
+ if(f) | |
+ addr = address(ap, f->dot, 0); | |
+ else /* a " */ | |
+ addr = address(ap, none, 0); | |
+ f = addr.f; | |
+ } | |
+ } | |
+ current(f); | |
+ switch(cp->cmdc){ | |
+ case '{': | |
+ a = cp->addr? address(cp->addr, f->dot, 0): f->dot; | |
+ for(cp = cp->ccmd; cp; cp = cp->next){ | |
+ a.f->dot = a; | |
+ cmdexec(a.f, cp); | |
+ } | |
+ break; | |
+ default: | |
+ i=(*cmdtab[i].fn)(f, cp); | |
+ return i; | |
+ } | |
+ return 1; | |
+} | |
+ | |
+ | |
+int | |
+a_cmd(File *f, Cmd *cp) | |
+{ | |
+ return append(f, cp, addr.r.p2); | |
+} | |
+ | |
+int | |
+b_cmd(File *f, Cmd *cp) | |
+{ | |
+ USED(f); | |
+ f = cp->cmdc=='b'? tofile(cp->ctext) : getfile(cp->ctext); | |
+ if(f->state == Unread) | |
+ load(f); | |
+ else if(nest == 0) | |
+ filename(f); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+c_cmd(File *f, Cmd *cp) | |
+{ | |
+ Fdelete(f, addr.r.p1, addr.r.p2); | |
+ f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p2; | |
+ return append(f, cp, addr.r.p2); | |
+} | |
+ | |
+int | |
+d_cmd(File *f, Cmd *cp) | |
+{ | |
+ USED(cp); | |
+ Fdelete(f, addr.r.p1, addr.r.p2); | |
+ f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p1; | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+D_cmd(File *f, Cmd *cp) | |
+{ | |
+ closefiles(f, cp->ctext); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+e_cmd(File *f, Cmd *cp) | |
+{ | |
+ if(getname(f, cp->ctext, cp->cmdc=='e')==0) | |
+ error(Enoname); | |
+ edit(f, cp->cmdc); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+f_cmd(File *f, Cmd *cp) | |
+{ | |
+ getname(f, cp->ctext, TRUE); | |
+ filename(f); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+g_cmd(File *f, Cmd *cp) | |
+{ | |
+ if(f!=addr.f)panic("g_cmd f!=addr.f"); | |
+ compile(cp->re); | |
+ if(execute(f, addr.r.p1, addr.r.p2) ^ cp->cmdc=='v'){ | |
+ f->dot = addr; | |
+ return cmdexec(f, cp->ccmd); | |
+ } | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+i_cmd(File *f, Cmd *cp) | |
+{ | |
+ return append(f, cp, addr.r.p1); | |
+} | |
+ | |
+int | |
+k_cmd(File *f, Cmd *cp) | |
+{ | |
+ USED(cp); | |
+ f->mark = addr.r; | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+m_cmd(File *f, Cmd *cp) | |
+{ | |
+ Address addr2; | |
+ | |
+ addr2 = address(cp->caddr, f->dot, 0); | |
+ if(cp->cmdc=='m') | |
+ move(f, addr2); | |
+ else | |
+ copy(f, addr2); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+n_cmd(File *f, Cmd *cp) | |
+{ | |
+ int i; | |
+ USED(f); | |
+ USED(cp); | |
+ for(i = 0; i<file.nused; i++){ | |
+ if(file.filepptr[i] == cmd) | |
+ continue; | |
+ f = file.filepptr[i]; | |
+ Strduplstr(&genstr, &f->name); | |
+ filename(f); | |
+ } | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+p_cmd(File *f, Cmd *cp) | |
+{ | |
+ USED(cp); | |
+ return display(f); | |
+} | |
+ | |
+int | |
+q_cmd(File *f, Cmd *cp) | |
+{ | |
+ USED(cp); | |
+ USED(f); | |
+ trytoquit(); | |
+ if(downloaded){ | |
+ outT0(Hexit); | |
+ return TRUE; | |
+ } | |
+ return FALSE; | |
+} | |
+ | |
+int | |
+s_cmd(File *f, Cmd *cp) | |
+{ | |
+ int i, j, c, n; | |
+ Posn p1, op, didsub = 0, delta = 0; | |
+ | |
+ n = cp->num; | |
+ op= -1; | |
+ compile(cp->re); | |
+ for(p1 = addr.r.p1; p1<=addr.r.p2 && execute(f, p1, addr.r.p2); ){ | |
+ if(sel.p[0].p1==sel.p[0].p2){ /* empty match? */ | |
+ if(sel.p[0].p1==op){ | |
+ p1++; | |
+ continue; | |
+ } | |
+ p1 = sel.p[0].p2+1; | |
+ }else | |
+ p1 = sel.p[0].p2; | |
+ op = sel.p[0].p2; | |
+ if(--n>0) | |
+ continue; | |
+ Strzero(&genstr); | |
+ for(i = 0; i<cp->ctext->n; i++) | |
+ if((c = cp->ctext->s[i])=='\\' && i<cp->ctext->n-1){ | |
+ c = cp->ctext->s[++i]; | |
+ if('1'<=c && c<='9') { | |
+ j = c-'0'; | |
+ if(sel.p[j].p2-sel.p[j].p1>BLOCKSIZE) | |
+ error(Elongtag); | |
+ Fchars(f, genbuf, sel.p[j].p1, sel.p[j… | |
+ Strinsert(&genstr, tmprstr(genbuf, (se… | |
+ }else | |
+ Straddc(&genstr, c); | |
+ }else if(c!='&') | |
+ Straddc(&genstr, c); | |
+ else{ | |
+ if(sel.p[0].p2-sel.p[0].p1>BLOCKSIZE) | |
+ error(Elongrhs); | |
+ Fchars(f, genbuf, sel.p[0].p1, sel.p[0].p2); | |
+ Strinsert(&genstr, | |
+ tmprstr(genbuf, (int)(sel.p[0].p2-sel.… | |
+ genstr.n); | |
+ } | |
+ if(sel.p[0].p1!=sel.p[0].p2){ | |
+ Fdelete(f, sel.p[0].p1, sel.p[0].p2); | |
+ delta-=sel.p[0].p2-sel.p[0].p1; | |
+ } | |
+ if(genstr.n){ | |
+ Finsert(f, &genstr, sel.p[0].p2); | |
+ delta+=genstr.n; | |
+ } | |
+ didsub = 1; | |
+ if(!cp->flag) | |
+ break; | |
+ } | |
+ if(!didsub && nest==0) | |
+ error(Enosub); | |
+ f->ndot.r.p1 = addr.r.p1, f->ndot.r.p2 = addr.r.p2+delta; | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+u_cmd(File *f, Cmd *cp) | |
+{ | |
+ int n; | |
+ USED(f); | |
+ USED(cp); | |
+ n = cp->num; | |
+ while(n-- && undo()) | |
+ ; | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+w_cmd(File *f, Cmd *cp) | |
+{ | |
+ if(getname(f, cp->ctext, FALSE)==0) | |
+ error(Enoname); | |
+ writef(f); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+x_cmd(File *f, Cmd *cp) | |
+{ | |
+ if(cp->re) | |
+ looper(f, cp, cp->cmdc=='x'); | |
+ else | |
+ linelooper(f, cp); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+X_cmd(File *f, Cmd *cp) | |
+{ | |
+ USED(f); | |
+ filelooper(cp, cp->cmdc=='X'); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+plan9_cmd(File *f, Cmd *cp) | |
+{ | |
+ plan9(f, cp->cmdc, cp->ctext, nest); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+eq_cmd(File *f, Cmd *cp) | |
+{ | |
+ int charsonly; | |
+ | |
+ switch(cp->ctext->n){ | |
+ case 1: | |
+ charsonly = FALSE; | |
+ break; | |
+ case 2: | |
+ if(cp->ctext->s[0]=='#'){ | |
+ charsonly = TRUE; | |
+ break; | |
+ } | |
+ default: | |
+ SET(charsonly); | |
+ error(Enewline); | |
+ } | |
+ printposn(f, charsonly); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+nl_cmd(File *f, Cmd *cp) | |
+{ | |
+ if(cp->addr == 0){ | |
+ /* First put it on newline boundaries */ | |
+ addr = lineaddr((Posn)0, f->dot, -1); | |
+ addr.r.p2 = lineaddr((Posn)0, f->dot, 1).r.p2; | |
+ if(addr.r.p1==f->dot.r.p1 && addr.r.p2==f->dot.r.p2) | |
+ addr = lineaddr((Posn)1, f->dot, 1); | |
+ display(f); | |
+ }else if(downloaded) | |
+ moveto(f, addr.r); | |
+ else | |
+ display(f); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+cd_cmd(File *f, Cmd *cp) | |
+{ | |
+ USED(f); | |
+ cd(cp->ctext); | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+append(File *f, Cmd *cp, Posn p) | |
+{ | |
+ if(cp->ctext->n>0 && cp->ctext->s[cp->ctext->n-1]==0) | |
+ --cp->ctext->n; | |
+ if(cp->ctext->n>0) | |
+ Finsert(f, cp->ctext, p); | |
+ f->ndot.r.p1 = p; | |
+ f->ndot.r.p2 = p+cp->ctext->n; | |
+ return TRUE; | |
+} | |
+ | |
+int | |
+display(File *f) | |
+{ | |
+ Posn p1, p2; | |
+ int np, n; | |
+ char *c; | |
+ | |
+ p1 = addr.r.p1; | |
+ p2 = addr.r.p2; | |
+ while(p1 < p2){ | |
+ np = p2-p1; | |
+ if(np>BLOCKSIZE-1) | |
+ np = BLOCKSIZE-1; | |
+ n = Fchars(f, genbuf, p1, p1+np); | |
+ if(n <= 0) | |
+ panic("display"); | |
+ genbuf[n] = 0; | |
+ c = Strtoc(tmprstr(genbuf, n+1)); | |
+ if(downloaded) | |
+ termwrite(c); | |
+ else | |
+ Write(1, c, strlen(c)); | |
+ free(c); | |
+ p1+=n; | |
+ } | |
+ f->dot = addr; | |
+ return TRUE; | |
+} | |
+ | |
+void | |
+looper(File *f, Cmd *cp, int xy) | |
+{ | |
+ Posn p, op; | |
+ Range r; | |
+ | |
+ r = addr.r; | |
+ op= xy? -1 : r.p1; | |
+ nest++; | |
+ compile(cp->re); | |
+ for(p = r.p1; p<=r.p2; ){ | |
+ if(!execute(f, p, r.p2)){ /* no match, but y should still run … | |
+ if(xy || op>r.p2) | |
+ break; | |
+ f->dot.r.p1 = op, f->dot.r.p2 = r.p2; | |
+ p = r.p2+1; /* exit next loop */ | |
+ }else{ | |
+ if(sel.p[0].p1==sel.p[0].p2){ /* empty match? */ | |
+ if(sel.p[0].p1==op){ | |
+ p++; | |
+ continue; | |
+ } | |
+ p = sel.p[0].p2+1; | |
+ }else | |
+ p = sel.p[0].p2; | |
+ if(xy) | |
+ f->dot.r = sel.p[0]; | |
+ else | |
+ f->dot.r.p1 = op, f->dot.r.p2 = sel.p[0].p1; | |
+ } | |
+ op = sel.p[0].p2; | |
+ cmdexec(f, cp->ccmd); | |
+ compile(cp->re); | |
+ } | |
+ --nest; | |
+} | |
+ | |
+void | |
+linelooper(File *f, Cmd *cp) | |
+{ | |
+ Posn p; | |
+ Range r, linesel; | |
+ Address a3; | |
+ | |
+ nest++; | |
+ r = addr.r; | |
+ a3.f = f; | |
+ a3.r.p1 = a3.r.p2 = r.p1; | |
+ for(p = r.p1; p<r.p2; p = a3.r.p2){ | |
+ a3.r.p1 = a3.r.p2; | |
+/*pjw if(p!=r.p1 || (linesel = lineaddr((Posn)0, a3, 1)).r.p2==… | |
+ if(p!=r.p1 || ((linesel = lineaddr((Posn)0, a3, 1).r), linesel… | |
+ linesel = lineaddr((Posn)1, a3, 1).r; | |
+ if(linesel.p1 >= r.p2) | |
+ break; | |
+ if(linesel.p2 >= r.p2) | |
+ linesel.p2 = r.p2; | |
+ if(linesel.p2 > linesel.p1) | |
+ if(linesel.p1>=a3.r.p2 && linesel.p2>a3.r.p2){ | |
+ f->dot.r = linesel; | |
+ cmdexec(f, cp->ccmd); | |
+ a3.r = linesel; | |
+ continue; | |
+ } | |
+ break; | |
+ } | |
+ --nest; | |
+} | |
+ | |
+void | |
+filelooper(Cmd *cp, int XY) | |
+{ | |
+ File *f, *cur; | |
+ int i; | |
+ | |
+ if(Glooping++) | |
+ error(EnestXY); | |
+ nest++; | |
+ settempfile(); | |
+ cur = curfile; | |
+ for(i = 0; i<tempfile.nused; i++){ | |
+ f = tempfile.filepptr[i]; | |
+ if(f==cmd) | |
+ continue; | |
+ if(cp->re==0 || filematch(f, cp->re)==XY) | |
+ cmdexec(f, cp->ccmd); | |
+ } | |
+ if(cur && whichmenu(cur)>=0) /* check that cur is still a file … | |
+ current(cur); | |
+ --Glooping; | |
+ --nest; | |
+} | |
diff --git a/samterm/Makefile b/samterm/Makefile | |
@@ -0,0 +1,49 @@ | |
+# Copyright (c) 1998 Lucent Technologies - All rights reserved. | |
+# | |
+# Prototype Makefile for samterm | |
+# | |
+# define operating system. ONE of: | |
+# -DIRIX -DSUNOS -DUMIPS -DSYSVR3 -DAIX -DOSF1 | |
+# -DHPUX -DAPOLLO -DCONVEX -DDYNIX | |
+# | |
+# -DIRIX is the default and should actually work on any modern system. | |
+# Additionally, -D_POSIX_SOURCE (or its equivalent) may be specified | |
+# if your compiler supports posix-compatible compilation. | |
+# | |
+ | |
+include ../config.mk | |
+ | |
+# If your system has 64-bit addresses, add -DUSE64BITS to $(OS). | |
+OS=-DIRIX5 -DUSE64BITS=$(USE64BITS) | |
+ | |
+# add -Iincludedir for any include directories that need to be searched | |
+# for posix header files (for UMIPS, add -I/usr/include/posix) | |
+INCS=-I../include -I$(FREETYPEINC) | |
+ | |
+# SAMTERM contains the name of the file containing the samterm | |
+# executable. | |
+SAMTERM=$(BINDIR)/samterm | |
+ | |
+# set this if your X libraries are in different locations | |
+# or if you need extra libraries to load with X11 applications | |
+XLIBS=-lXt -lX11 -lXft | |
+ | |
+CFLAGS=$(OS) $(INCS) -D_LIBXG_EXTENSION | |
+ | |
+LIBS=../libframe/libframe.a ../libXg/libXg.a | |
+CC=cc | |
+ | |
+OBJ=main.o flayer.o icons.o io.o menu.o mesg.o rasp.o scroll.o unix.o | |
+ | |
+all: samterm | |
+ | |
+samterm: $(OBJ) $(LIBS) | |
+ $(CC) -o samterm $(OBJ) $(LIBS) $(XLIBS) | |
+ | |
+clean: | |
+ rm -f *.o core samterm | |
+ | |
+install: samterm | |
+ cp samterm $(SAMTERM) | |
+ | |
+$(OBJ): samterm.h flayer.h ../include/frame.h ../include/libg.h ../incl… | |
diff --git a/samterm/flayer.c b/samterm/flayer.c | |
@@ -0,0 +1,436 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+#define DELTA 10 | |
+ | |
+static Flayer **llist; /* front to back */ | |
+static int nllist; | |
+static int nlalloc; | |
+static Rectangle lDrect; | |
+ | |
+extern Bitmap screen; | |
+extern Mouse mouse; | |
+ | |
+Vis visibility(Flayer *); | |
+void newvisibilities(int); | |
+void llinsert(Flayer*); | |
+void lldelete(Flayer*); | |
+ | |
+void | |
+flstart(Rectangle r) | |
+{ | |
+ lDrect = r; | |
+} | |
+ | |
+void | |
+flnew(Flayer *l, Rune *(*fn)(Flayer*, long, ulong*), int u0, void *u1) | |
+{ | |
+ if(nllist == nlalloc){ | |
+ nlalloc += DELTA; | |
+ llist = realloc(llist, nlalloc*sizeof(Flayer**)); | |
+ if(llist == 0) | |
+ panic("flnew"); | |
+ } | |
+ l->textfn = fn; | |
+ l->user0 = u0; | |
+ l->user1 = u1; | |
+ llinsert(l); | |
+} | |
+ | |
+Rectangle | |
+flrect(Flayer *l, Rectangle r) | |
+{ | |
+ rectclip(&r, lDrect); | |
+ l->entire = r; | |
+ l->scroll = inset(r, FLMARGIN); | |
+ r.min.x = | |
+ l->scroll.max.x = r.min.x+FLMARGIN+FLSCROLLWID+(FLGAP-FLMARGIN); | |
+ return r; | |
+} | |
+ | |
+void | |
+flinit(Flayer *l, Rectangle r, XftFont *ft) | |
+{ | |
+ lldelete(l); | |
+ llinsert(l); | |
+ l->visible = All; | |
+ l->origin = l->p0 = l->p1 = 0; | |
+ frinit(&l->f, inset(flrect(l, r), FLMARGIN), ft, &screen); | |
+ newvisibilities(1); | |
+ bitblt(&screen, l->entire.min, &screen, l->entire, 0); | |
+ scrdraw(l, 0L); | |
+ flborder(l, 0); | |
+} | |
+ | |
+void | |
+flclose(Flayer *l) | |
+{ | |
+ if(l->visible == All) | |
+ bitblt(&screen, l->entire.min, &screen, l->entire, 0); | |
+ else if(l->visible == Some){ | |
+ if(l->f.b == 0) | |
+ l->f.b = balloc(l->entire, screen.ldepth); | |
+ if(l->f.b){ | |
+ bitblt(l->f.b, l->entire.min, l->f.b, l->entire, 0); | |
+ flrefresh(l, l->entire, 0); | |
+ } | |
+ } | |
+ frclear(&l->f); | |
+ lldelete(l); | |
+ if(l->f.b && l->visible!=All) | |
+ bfree(l->f.b); | |
+ l->textfn = 0; | |
+ newvisibilities(1); | |
+} | |
+ | |
+void | |
+flborder(Flayer *l, int wide) | |
+{ | |
+ if(flprepare(l)){ | |
+ border(l->f.b, l->entire, FLMARGIN, 0); | |
+ border(l->f.b, l->entire, wide? FLMARGIN : 1, F&~D); | |
+ if(l->visible==Some) | |
+ flrefresh(l, l->entire, 0); | |
+ } | |
+} | |
+ | |
+Flayer * | |
+flwhich(Point p) | |
+{ | |
+ int i; | |
+ | |
+ if(p.x==0 && p.y==0) | |
+ return nllist? llist[0] : 0; | |
+ for(i=0; i<nllist; i++) | |
+ if(ptinrect(p, llist[i]->entire)) | |
+ return llist[i]; | |
+ return 0; | |
+} | |
+ | |
+void | |
+flupfront(Flayer *l) | |
+{ | |
+ int v = l->visible; | |
+ | |
+ lldelete(l); | |
+ llinsert(l); | |
+ if(v!=All) | |
+ newvisibilities(0); | |
+} | |
+ | |
+void | |
+newvisibilities(int redraw) | |
+ /* if redraw false, we know it's a flupfront, and needn't | |
+ * redraw anyone becoming partially covered */ | |
+{ | |
+ int i; | |
+ Vis ov; | |
+ Flayer *l; | |
+ | |
+ for(i = 0; i<nllist; i++){ | |
+ l = llist[i]; | |
+ ov = l->visible; | |
+ l->visible = visibility(l); | |
+#define V(a, b) (((a)<<2)|((b))) | |
+ switch(V(ov, l->visible)){ | |
+ case V(Some, None): | |
+ if(l->f.b) | |
+ bfree(l->f.b); | |
+ case V(All, None): | |
+ case V(All, Some): | |
+ l->f.b = 0; | |
+ frclear(&l->f); | |
+ break; | |
+ | |
+ case V(Some, Some): | |
+ if(l->f.b==0 && redraw) | |
+ case V(None, Some): | |
+ flprepare(l); | |
+ if(l->f.b && redraw){ | |
+ flrefresh(l, l->entire, 0); | |
+ bfree(l->f.b); | |
+ l->f.b = 0; | |
+ frclear(&l->f); | |
+ } | |
+ case V(None, None): | |
+ case V(All, All): | |
+ break; | |
+ | |
+ case V(Some, All): | |
+ if(l->f.b){ | |
+ bitblt(&screen, l->entire.min, l->f.b, l->enti… | |
+ bfree(l->f.b); | |
+ l->f.b = &screen; | |
+ break; | |
+ } | |
+ case V(None, All): | |
+ flprepare(l); | |
+ break; | |
+ } | |
+ if(ov==None && l->visible!=None) | |
+ flnewlyvisible(l); | |
+ } | |
+} | |
+ | |
+void | |
+llinsert(Flayer *l) | |
+{ | |
+ int i; | |
+ for(i=nllist; i>0; --i) | |
+ llist[i]=llist[i-1]; | |
+ llist[0]=l; | |
+ nllist++; | |
+} | |
+ | |
+void | |
+lldelete(Flayer *l) | |
+{ | |
+ int i; | |
+ | |
+ for(i=0; i<nllist; i++) | |
+ if(llist[i]==l){ | |
+ --nllist; | |
+ for(; i<nllist; i++) | |
+ llist[i] = llist[i+1]; | |
+ return; | |
+ } | |
+ panic("lldelete"); | |
+} | |
+ | |
+void | |
+flinsert(Flayer *l, Rune *sp, Rune *ep, long p0) | |
+{ | |
+ if(flprepare(l)){ | |
+ frinsert(&l->f, sp, ep, p0-l->origin); | |
+ scrdraw(l, scrtotal(l)); | |
+ if(l->visible==Some) | |
+ flrefresh(l, l->entire, 0); | |
+ } | |
+} | |
+ | |
+void | |
+fldelete(Flayer *l, long p0, long p1) | |
+{ | |
+ if(flprepare(l)){ | |
+ p0 -= l->origin; | |
+ if(p0 < 0) | |
+ p0 = 0; | |
+ p1 -= l->origin; | |
+ if(p1<0) | |
+ p1 = 0; | |
+ frdelete(&l->f, p0, p1); | |
+ scrdraw(l, scrtotal(l)); | |
+ if(l->visible==Some) | |
+ flrefresh(l, l->entire, 0); | |
+ } | |
+} | |
+ | |
+int | |
+flselect(Flayer *l) | |
+{ | |
+ int ret = 0; | |
+ if(l->visible!=All) | |
+ flupfront(l); | |
+ frselect(&l->f, &mouse); | |
+ if(l->f.p0==l->f.p1){ | |
+ if(mouse.msec-l->click<Clicktime && l->f.p0+l->origin==l->p0){ | |
+ ret = 1; | |
+ l->click = 0; | |
+ }else | |
+ l->click = mouse.msec; | |
+ }else | |
+ l->click = 0; | |
+ l->p0 = l->f.p0+l->origin, l->p1 = l->f.p1+l->origin; | |
+ return ret; | |
+} | |
+ | |
+void | |
+flsetselect(Flayer *l, long p0, long p1) | |
+{ | |
+ ulong fp0, fp1; | |
+ | |
+ l->click = 0; | |
+ if(l->visible==None || !flprepare(l)){ | |
+ l->p0 = p0, l->p1 = p1; | |
+ return; | |
+ } | |
+ l->p0 = p0, l->p1 = p1; | |
+ flfp0p1(l, &fp0, &fp1); | |
+ if(fp0==l->f.p0 && fp1==l->f.p1) | |
+ return; | |
+ frselectp(&l->f, F&~D); | |
+ l->f.p0 = fp0, l->f.p1 = fp1; | |
+ frselectp(&l->f, F&~D); | |
+ if(l->visible==Some) | |
+ flrefresh(l, l->entire, 0); | |
+} | |
+ | |
+void | |
+flfp0p1(Flayer *l, ulong *pp0, ulong *pp1) | |
+{ | |
+ long p0 = l->p0-l->origin, p1 = l->p1-l->origin; | |
+ | |
+ if(p0 < 0) | |
+ p0 = 0; | |
+ if(p1 < 0) | |
+ p1 = 0; | |
+ if(p0 > l->f.nchars) | |
+ p0 = l->f.nchars; | |
+ if(p1 > l->f.nchars) | |
+ p1 = l->f.nchars; | |
+ *pp0 = p0; | |
+ *pp1 = p1; | |
+} | |
+ | |
+Rectangle | |
+rscale(Rectangle r, Point old, Point new) | |
+{ | |
+ r.min.x = r.min.x*new.x/old.x; | |
+ r.min.y = r.min.y*new.y/old.y; | |
+ r.max.x = r.max.x*new.x/old.x; | |
+ r.max.y = r.max.y*new.y/old.y; | |
+ return r; | |
+} | |
+ | |
+void | |
+flreshape(Rectangle dr) | |
+{ | |
+ int i; | |
+ Flayer *l; | |
+ Frame *f; | |
+ Rectangle r, olDrect; | |
+ int move; | |
+ | |
+ olDrect = lDrect; | |
+ lDrect = dr; | |
+ move = 0; | |
+ /* no moving on rio; must repaint */ | |
+ bitblt(&screen, lDrect.min, &screen, lDrect, 0); | |
+ for(i=0; i<nllist; i++){ | |
+ l = llist[i]; | |
+ f = &l->f; | |
+ if(move) | |
+ r = raddp(rsubp(l->entire, olDrect.min), dr.min); | |
+ else{ | |
+ r = raddp(rscale(rsubp(l->entire, olDrect.min), | |
+ sub(olDrect.max, olDrect.min), | |
+ sub(dr.max, dr.min)), dr.min); | |
+ if(l->visible==Some && f->b){ | |
+ bfree(f->b); | |
+ frclear(f); | |
+ } | |
+ f->b = 0; | |
+ if(l->visible!=None) | |
+ frclear(f); | |
+ } | |
+ if(!rectclip(&r, dr)) | |
+ panic("flreshape"); | |
+ if(r.max.x-r.min.x<100) | |
+ r.min.x = dr.min.x; | |
+ if(r.max.x-r.min.x<100) | |
+ r.max.x = dr.max.x; | |
+ if(r.max.y-r.min.y<2*FLMARGIN+f->font->height) | |
+ r.min.y = dr.min.y; | |
+ if(r.max.y-r.min.y<2*FLMARGIN+f->font->height) | |
+ r.max.y = dr.max.y; | |
+ if(!move) | |
+ l->visible = None; | |
+ frsetrects(f, inset(flrect(l, r), FLMARGIN), f->b); | |
+ if(!move && f->b) | |
+ scrdraw(l, scrtotal(l)); | |
+ } | |
+ newvisibilities(1); | |
+} | |
+ | |
+int | |
+flprepare(Flayer *l) | |
+{ | |
+ Frame *f; | |
+ ulong n; | |
+ Rune *r; | |
+ | |
+ if(l->visible == None) | |
+ return 0; | |
+ f = &l->f; | |
+ if(f->b == 0){ | |
+ if(l->visible == All) | |
+ f->b = &screen; | |
+ else if((f->b = balloc(l->entire, screen.ldepth))==0) | |
+ return 0; | |
+ bitblt(f->b, l->entire.min, f->b, l->entire, 0); | |
+ border(f->b, l->entire, l==llist[0]? FLMARGIN : 1, F&~D); | |
+ n = f->nchars; | |
+ frinit(f, f->entire, f->font, f->b); | |
+ r = (*l->textfn)(l, n, &n); | |
+ frinsert(f, r, r+n, (ulong)0); | |
+ frselectp(f, F&~D); | |
+ flfp0p1(l, &l->f.p0, &l->f.p1); | |
+ frselectp(f, F&~D); | |
+ scrdraw(l, scrtotal(l)); | |
+ } | |
+ return 1; | |
+} | |
+ | |
+static int somevis, someinvis, justvis; | |
+ | |
+Vis | |
+visibility(Flayer *l) | |
+{ | |
+ somevis = someinvis = 0; | |
+ justvis = 1; | |
+ flrefresh(l, l->entire, 0); | |
+ justvis = 0; | |
+ if(somevis==0) | |
+ return None; | |
+ if(someinvis==0) | |
+ return All; | |
+ return Some; | |
+} | |
+ | |
+void | |
+flrefresh(Flayer *l, Rectangle r, int i) | |
+{ | |
+ Flayer *t; | |
+ Rectangle s; | |
+ | |
+ Top: | |
+ if((t=llist[i++]) == l){ | |
+ if(!justvis) | |
+ bitblt(&screen, r.min, l->f.b, r, S); | |
+ somevis = 1; | |
+ }else{ | |
+ if(!rectXrect(t->entire, r)) | |
+ goto Top; /* avoid stacking unnecessarily */ | |
+ if(t->entire.min.x>r.min.x){ | |
+ s = r; | |
+ s.max.x = t->entire.min.x; | |
+ flrefresh(l, s, i); | |
+ r.min.x = t->entire.min.x; | |
+ } | |
+ if(t->entire.min.y>r.min.y){ | |
+ s = r; | |
+ s.max.y = t->entire.min.y; | |
+ flrefresh(l, s, i); | |
+ r.min.y = t->entire.min.y; | |
+ } | |
+ if(t->entire.max.x<r.max.x){ | |
+ s = r; | |
+ s.min.x = t->entire.max.x; | |
+ flrefresh(l, s, i); | |
+ r.max.x = t->entire.max.x; | |
+ } | |
+ if(t->entire.max.y<r.max.y){ | |
+ s = r; | |
+ s.min.y = t->entire.max.y; | |
+ flrefresh(l, s, i); | |
+ r.max.y = t->entire.max.y; | |
+ } | |
+ /* remaining piece of r is blocked by t; forget about it */ | |
+ someinvis = 1; | |
+ } | |
+} | |
diff --git a/samterm/flayer.h b/samterm/flayer.h | |
@@ -0,0 +1,48 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#undef None | |
+typedef enum Vis{ | |
+ None=0, | |
+ Some, | |
+ All | |
+}Vis; | |
+ | |
+enum{ | |
+ Clicktime=1000 /* one second */ | |
+}; | |
+ | |
+typedef struct Flayer Flayer; | |
+ | |
+struct Flayer | |
+{ | |
+ Frame f; | |
+ long origin; /* offset of first char in flayer */ | |
+ long p0, p1; | |
+ long click; /* time at which selection click occ… | |
+ Rune *(*textfn)(Flayer*, long, ulong*); | |
+ int user0; | |
+ void *user1; | |
+ Rectangle entire; | |
+ Rectangle scroll; | |
+ Vis visible; | |
+}; | |
+ | |
+void flborder(Flayer*, int); | |
+void flclose(Flayer*); | |
+void fldelete(Flayer*, long, long); | |
+void flfp0p1(Flayer*, ulong*, ulong*); | |
+void flinit(Flayer*, Rectangle, XftFont*); | |
+void flinsert(Flayer*, Rune*, Rune*, long); | |
+void flnew(Flayer*, Rune *(*fn)(Flayer*, long, ulong*), int, void*); | |
+int flprepare(Flayer*); | |
+Rectangle flrect(Flayer*, Rectangle); | |
+void flrefresh(Flayer*, Rectangle, int); | |
+void flreshape(Rectangle); | |
+int flselect(Flayer*); | |
+void flsetselect(Flayer*, long, long); | |
+void flstart(Rectangle); | |
+void flupfront(Flayer*); | |
+Flayer *flwhich(Point); | |
+ | |
+#define FLMARGIN 4 | |
+#define FLSCROLLWID 12 | |
+#define FLGAP 4 | |
diff --git a/samterm/icons.c b/samterm/icons.c | |
@@ -0,0 +1,54 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+ | |
+Cursor bullseye={ | |
+ {-7, -7}, | |
+ {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF, | |
+ 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, | |
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF, | |
+ 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,}, | |
+ {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84, | |
+ 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE, | |
+ 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, | |
+ 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,} | |
+}; | |
+Cursor deadmouse={ | |
+ {-7, -7}, | |
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
+ 0x00, 0x00, 0x00, 0x0C, 0x00, 0x8E, 0x1D, 0xC7, | |
+ 0xFF, 0xE3, 0xFF, 0xF3, 0xFF, 0xFF, 0x7F, 0xFE, | |
+ 0x3F, 0xF8, 0x17, 0xF0, 0x03, 0xE0, 0x00, 0x00,}, | |
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x82, | |
+ 0x04, 0x41, 0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, | |
+ 0x17, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00,} | |
+}; | |
+Cursor lockarrow={ | |
+ {-7, -7}, | |
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, | |
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
+ 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xC0, | |
+ 0x03, 0xC0, 0x07, 0xC0, 0x0E, 0xC0, 0x1C, 0xC0, | |
+ 0x38, 0x00, 0x70, 0x00, 0xE0, 0xDB, 0xC0, 0xDB,} | |
+}; | |
+ | |
+uchar darkgreybits[] = { | |
+ 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77, | |
+ 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77, | |
+ 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77, | |
+ 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77, | |
+}; | |
+ | |
+Bitmap *darkgrey; | |
+ | |
+void | |
+iconinit(void) | |
+{ | |
+ darkgrey = balloc(Rect(0, 0, 16, 16), 0); | |
+ wrbitmap(darkgrey, 0, 16, darkgreybits); | |
+} | |
diff --git a/samterm/io.c b/samterm/io.c | |
@@ -0,0 +1,204 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+int cursorfd; | |
+int input; | |
+int got; | |
+int block; | |
+int kbdc; | |
+int reshaped; | |
+uchar *hostp; | |
+uchar *hoststop; | |
+uchar *externbase; | |
+uchar *externp; | |
+uchar *externstop; | |
+void panic(char*); | |
+ | |
+void | |
+initio(void){ | |
+ einit(Emouse|Ekeyboard); | |
+ estart(Ehost, 0, 0); | |
+ extstart(); | |
+} | |
+ | |
+void | |
+frgetmouse(void) | |
+{ | |
+ mouse = emouse(); | |
+} | |
+ | |
+void | |
+mouseunblock(void) | |
+{ | |
+ got &= ~Emouse; | |
+} | |
+ | |
+void | |
+kbdblock(void) | |
+{ /* ca suffit */ | |
+ block = Ekeyboard|Eextern; | |
+} | |
+ | |
+int | |
+button(int but) | |
+{ | |
+ frgetmouse(); | |
+ return mouse.buttons&(1<<(but-1)); | |
+} | |
+ | |
+void | |
+externload(Event *e) | |
+{ | |
+ externbase = malloc(e->n); | |
+ if(externbase == 0) | |
+ return; | |
+ memmove(externbase, e->data, e->n); | |
+ externp = externbase; | |
+ externstop = externbase + e->n; | |
+ got |= Eextern; | |
+} | |
+ | |
+int | |
+waitforio(void) | |
+{ | |
+ ulong type; | |
+ static Event e; | |
+ | |
+ if(got & ~block) | |
+ return got & ~block; | |
+ type = eread(~(got|block), &e); | |
+ switch(type){ | |
+ case Ehost: | |
+ hostp = e.data; | |
+ hoststop = hostp + e.n; | |
+ block = 0; | |
+ break; | |
+ case Eextern: | |
+ externload(&e); | |
+ break; | |
+ case Ekeyboard: | |
+ kbdc = e.kbdc; | |
+ break; | |
+ case Emouse: | |
+ mouse = e.mouse; | |
+ break; | |
+ } | |
+ got |= type; | |
+ return got; | |
+} | |
+ | |
+int | |
+rcvchar(void) | |
+{ | |
+ int c; | |
+ | |
+ if(!(got & Ehost)) | |
+ return -1; | |
+ c = *hostp++; | |
+ if(hostp == hoststop) | |
+ got &= ~Ehost; | |
+ return c; | |
+} | |
+ | |
+char* | |
+rcvstring(void) | |
+{ | |
+ *hoststop = 0; | |
+ got &= ~Ehost; | |
+ return (char*)hostp; | |
+} | |
+ | |
+int | |
+getch(void) | |
+{ | |
+ int c; | |
+ | |
+ while((c = rcvchar()) == -1){ | |
+ block = ~Ehost; | |
+ waitforio(); | |
+ block = 0; | |
+ } | |
+ return c; | |
+} | |
+ | |
+int | |
+externchar(void) | |
+{ | |
+ Rune r; | |
+ | |
+ loop: | |
+ if(got & (Eextern & ~block)){ | |
+ externp += chartorune(&r, (char*)externp); | |
+ if(externp >= externstop){ | |
+ got &= ~Eextern; | |
+ free(externbase); | |
+ } | |
+ if(r == 0) | |
+ goto loop; | |
+ return r; | |
+ } | |
+ return -1; | |
+} | |
+ | |
+int | |
+kbdchar(void) | |
+{ | |
+ int c; | |
+ static Event e; | |
+ | |
+ c = externchar(); | |
+ if(c > 0) | |
+ return c; | |
+ if(got & Ekeyboard){ | |
+ c = kbdc; | |
+ kbdc = -1; | |
+ got &= ~Ekeyboard; | |
+ return c; | |
+ } | |
+ while(ecanread(Eextern)){ | |
+ eread(Eextern, &e); | |
+ externload(&e); | |
+ c = externchar(); | |
+ if(c > 0) | |
+ return c; | |
+ } | |
+ if(!ecankbd()) | |
+ return -1; | |
+ return ekbd(); | |
+} | |
+ | |
+int | |
+qpeekc(void) | |
+{ | |
+ return kbdc; | |
+} | |
+ | |
+void | |
+ereshaped(Rectangle r) | |
+{ | |
+ USED(r); | |
+ | |
+ reshaped = 1; | |
+} | |
+ | |
+int | |
+RESHAPED(void) | |
+{ | |
+ if(reshaped){ | |
+ screen.r = bscreenrect(&screen.clipr); | |
+ reshaped = 0; | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+void | |
+mouseexit(void) | |
+{ | |
+ exits(0); | |
+} | |
diff --git a/samterm/main.c b/samterm/main.c | |
@@ -0,0 +1,592 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+Text cmd; | |
+Rune *scratch; | |
+long nscralloc; | |
+Cursor *cursor; | |
+extern Bitmap screen; | |
+Mouse mouse; | |
+Flayer *which = 0; | |
+Flayer *work = 0; | |
+long snarflen; | |
+long typestart = -1; | |
+long typeend = -1; | |
+long typeesc = -1; | |
+long modified = 0; /* strange lookahead for menus */ | |
+char lock = 1; | |
+char hasunlocked = 0; | |
+char *machine = "localhost"; | |
+ | |
+void | |
+main(int argc, char *argv[]) | |
+{ | |
+ int i, got, scr; | |
+ Text *t; | |
+ Rectangle r; | |
+ Flayer *nwhich; | |
+ | |
+ int fwdbut; | |
+ | |
+ if (argc >= 3 && strcmp(argv[1], "-r") == 0) | |
+ { | |
+ machine = argv[2]; | |
+ } | |
+ | |
+ getscreen(argc, argv); | |
+ fwdbut = scrollfwdbut(); | |
+ iconinit(); | |
+ initio(); | |
+ scratch = alloc(100*RUNESIZE); | |
+ nscralloc = 100; | |
+ r = screen.r; | |
+ r.max.y = r.min.y+Dy(r)/5; | |
+ flstart(screen.clipr); | |
+ rinit(&cmd.rasp); | |
+ flnew(&cmd.l[0], stgettext, 1, &cmd); | |
+ flinit(&cmd.l[0], r, font); | |
+ cmd.nwin = 1; | |
+ which = &cmd.l[0]; | |
+ cmd.tag = Untagged; | |
+ outTs(Tversion, VERSION); | |
+ startnewfile(Tstartcmdfile, &cmd); | |
+ | |
+ got = 0; | |
+ for(;;got = waitforio()){ | |
+ if(hasunlocked && RESHAPED()) | |
+ reshape(); | |
+ if(got&RHost) | |
+ rcv(); | |
+ if(got&RExtern){ | |
+ for(i=0; cmd.l[i].textfn==0; i++) | |
+ ; | |
+ current(&cmd.l[i]); | |
+ flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes); | |
+ type(which, RExtern); | |
+ } | |
+ if(got&RKeyboard) | |
+ if(which) | |
+ type(which, RKeyboard); | |
+ else | |
+ kbdblock(); | |
+ if(got&RMouse){ | |
+ if(lock==2 || !ptinrect(mouse.xy, screen.r)){ | |
+ mouseunblock(); | |
+ continue; | |
+ } | |
+ nwhich = flwhich(mouse.xy); | |
+ scr = which && ptinrect(mouse.xy, which->scroll); | |
+ if(mouse.buttons) | |
+ flushtyping(1); | |
+ if(mouse.buttons&1){ | |
+ if(nwhich){ | |
+ if(nwhich!=which) | |
+ current(nwhich); | |
+ else if(scr) | |
+ scroll(which, 1, fwdbut == 3 ?… | |
+ else{ | |
+ t=(Text *)which->user1; | |
+ if(flselect(which)){ | |
+ outTsl(Tdclick, t->tag… | |
+ t->lock++; | |
+ }else if(t!=&cmd) | |
+ outcmd(); | |
+ } | |
+ } | |
+ }else if((mouse.buttons&2) && which){ | |
+ if(scr) | |
+ scroll(which, 2, 2); | |
+ else | |
+ menu2hit(); | |
+ }else if((mouse.buttons&4)){ | |
+ if(scr) | |
+ scroll(which, 3, fwdbut == 3 ? 3 : 1); | |
+ else | |
+ menu3hit(); | |
+ } | |
+ mouseunblock(); | |
+ } | |
+ } | |
+} | |
+ | |
+ | |
+void | |
+reshape(void){ | |
+ int i; | |
+ | |
+ flreshape(screen.clipr); | |
+ for(i = 0; i<nname; i++) | |
+ if(text[i]) | |
+ hcheck(text[i]->tag); | |
+} | |
+ | |
+void | |
+current(Flayer *nw) | |
+{ | |
+ Text *t; | |
+ | |
+ if(which) | |
+ flborder(which, 0); | |
+ if(nw){ | |
+ flushtyping(1); | |
+ flupfront(nw); | |
+ flborder(nw, 1); | |
+ buttons(Up); | |
+ t = (Text *)nw->user1; | |
+ t->front = nw-&t->l[0]; | |
+ if(t != &cmd) | |
+ work = nw; | |
+ } | |
+ which = nw; | |
+} | |
+ | |
+void | |
+closeup(Flayer *l) | |
+{ | |
+ Text *t=(Text *)l->user1; | |
+ int m; | |
+ | |
+ m = whichmenu(t->tag); | |
+ if(m < 0) | |
+ return; | |
+ flclose(l); | |
+ if(l == which){ | |
+ which = 0; | |
+ current(flwhich(Pt(0, 0))); | |
+ } | |
+ if(l == work) | |
+ work = 0; | |
+ if(--t->nwin == 0){ | |
+ rclear(&t->rasp); | |
+ free((uchar *)t); | |
+ text[m] = 0; | |
+ }else if(l == &t->l[t->front]){ | |
+ for(m=0; m<NL; m++) /* find one; any one will do */ | |
+ if(t->l[m].textfn){ | |
+ t->front = m; | |
+ return; | |
+ } | |
+ panic("close"); | |
+ } | |
+} | |
+ | |
+Flayer * | |
+findl(Text *t) | |
+{ | |
+ int i; | |
+ for(i = 0; i<NL; i++) | |
+ if(t->l[i].textfn==0) | |
+ return &t->l[i]; | |
+ return 0; | |
+} | |
+ | |
+void | |
+duplicate(Flayer *l, Rectangle r, XftFont *f, int close) | |
+{ | |
+ Text *t=(Text *)l->user1; | |
+ Flayer *nl = findl(t); | |
+ Rune *rp; | |
+ ulong n; | |
+ | |
+ if(nl){ | |
+ flnew(nl, stgettext, l->user0, (char *)t); | |
+ flinit(nl, r, f); | |
+ nl->origin = l->origin; | |
+ rp = (*l->textfn)(l, l->f.nchars, &n); | |
+ flinsert(nl, rp, rp+n, l->origin); | |
+ flsetselect(nl, l->p0, l->p1); | |
+ if(close){ | |
+ flclose(l); | |
+ if(l==which) | |
+ which = 0; | |
+ }else | |
+ t->nwin++; | |
+ current(nl); | |
+ hcheck(t->tag); | |
+ } | |
+ cursorswitch(cursor); | |
+} | |
+ | |
+void | |
+buttons(int updown) | |
+{ | |
+ while(((mouse.buttons&7)!=0) != updown) | |
+ frgetmouse(); | |
+} | |
+ | |
+int | |
+getr(Rectangle *rp) | |
+{ | |
+ Point p; | |
+ Rectangle r; | |
+ | |
+ *rp = getrect(3, &mouse); | |
+ if(rp->max.x && rp->max.x-rp->min.x<=5 && rp->max.y-rp->min.y<=5){ | |
+ p = rp->min; | |
+ r = cmd.l[cmd.front].entire; | |
+ *rp = screen.r; | |
+ if(cmd.nwin==1){ | |
+ if (p.y <= r.min.y) | |
+ rp->max.y = r.min.y; | |
+ else if (p.y >= r.max.y) | |
+ rp->min.y = r.max.y; | |
+ if (p.x <= r.min.x) | |
+ rp->max.x = r.min.x; | |
+ else if (p.x >= r.max.x) | |
+ rp->min.x = r.max.x; | |
+ } | |
+ } | |
+ return rectclip(rp, screen.r) && | |
+ rp->max.x-rp->min.x>100 && rp->max.y-rp->min.y>40; | |
+} | |
+ | |
+void | |
+snarf(Text *t, int w) | |
+{ | |
+ Flayer *l = &t->l[w]; | |
+ | |
+ if(l->p1>l->p0){ | |
+ snarflen = l->p1-l->p0; | |
+ outTsll(Tsnarf, t->tag, l->p0, l->p1); | |
+ } | |
+} | |
+ | |
+void | |
+cut(Text *t, int w, int save, int check) | |
+{ | |
+ long p0, p1; | |
+ Flayer *l; | |
+ | |
+ l = &t->l[w]; | |
+ p0 = l->p0; | |
+ p1 = l->p1; | |
+ if(p0 == p1) | |
+ return; | |
+ if(p0 < 0) | |
+ panic("cut"); | |
+ if(save) | |
+ snarf(t, w); | |
+ outTsll(Tcut, t->tag, p0, p1); | |
+ flsetselect(l, p0, p0); | |
+ t->lock++; | |
+ hcut(t->tag, p0, p1-p0); | |
+ if(check) | |
+ hcheck(t->tag); | |
+} | |
+ | |
+void | |
+paste(Text *t, int w) | |
+{ | |
+ if(snarflen){ | |
+ cut(t, w, 0, 0); | |
+ t->lock++; | |
+ outTsl(Tpaste, t->tag, t->l[w].p0); | |
+ } | |
+} | |
+ | |
+void | |
+scrorigin(Flayer *l, int but, long p0) | |
+{ | |
+ Text *t=(Text *)l->user1; | |
+ | |
+ switch(but){ | |
+ case 1: | |
+ outTsll(Torigin, t->tag, l->origin, p0); | |
+ break; | |
+ case 2: | |
+ outTsll(Torigin, t->tag, p0, 1L); | |
+ break; | |
+ case 3: | |
+ horigin(t->tag,p0); | |
+ } | |
+} | |
+ | |
+int | |
+alnum(int c) | |
+{ | |
+ /* | |
+ * Hard to get absolutely right. Use what we know about ASCII | |
+ * and assume anything above the Latin control characters is | |
+ * potentially an alphanumeric. | |
+ */ | |
+ if(c<=' ') | |
+ return 0; | |
+ if(0x7F<=c && c<=0xA0) | |
+ return 0; | |
+ if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) | |
+ return 0; | |
+ return 1; | |
+} | |
+ | |
+int | |
+raspc(Rasp *r, long p) | |
+{ | |
+ ulong n; | |
+ rload(r, p, p+1, &n); | |
+ if(n) | |
+ return scratch[0]; | |
+ return 0; | |
+} | |
+ | |
+long | |
+ctlw(Rasp *r, long o, long p) | |
+{ | |
+ int c; | |
+ | |
+ if(--p < o) | |
+ return o; | |
+ if(raspc(r, p)=='\n') | |
+ return p; | |
+ for(; p>=o && !alnum(c=raspc(r, p)); --p) | |
+ if(c=='\n') | |
+ return p+1; | |
+ for(; p>o && alnum(raspc(r, p-1)); --p) | |
+ ; | |
+ return p>=o? p : o; | |
+} | |
+ | |
+long | |
+ctlu(Rasp *r, long o, long p) | |
+{ | |
+ for(; p-1>=o && raspc(r, p-1)!='\n'; --p) | |
+ ; | |
+ return p>=o? p : o; | |
+} | |
+ | |
+int | |
+center(Flayer *l, long a) | |
+{ | |
+ Text *t; | |
+ | |
+ t = l->user1; | |
+ if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){ | |
+ if(a > t->rasp.nrunes) | |
+ a = t->rasp.nrunes; | |
+ outTsll(Torigin, t->tag, a, 2L); | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+int | |
+onethird(Flayer *l, long a) | |
+{ | |
+ Text *t; | |
+ Rectangle s; | |
+ long lines; | |
+ | |
+ t = l->user1; | |
+ if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){ | |
+ if(a > t->rasp.nrunes) | |
+ a = t->rasp.nrunes; | |
+ s = inset(l->scroll, 1); | |
+ lines = ((s.max.y-s.min.y)/l->f.font->height+1)/3; | |
+ if (lines < 2) | |
+ lines = 2; | |
+ outTsll(Torigin, t->tag, a, lines); | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+ | |
+int | |
+XDisplay(Display *); | |
+ | |
+extern Display * _dpy; | |
+ | |
+void | |
+flushtyping(int clearesc) | |
+{ | |
+ Text *t; | |
+ ulong n; | |
+ | |
+ if(clearesc) | |
+ typeesc = -1; | |
+ if(typestart == typeend) { | |
+ modified = 0; | |
+ return; | |
+ } | |
+ t = which->user1; | |
+ if(t != &cmd) | |
+ modified = 1; | |
+ rload(&t->rasp, typestart, typeend, &n); | |
+ scratch[n] = 0; | |
+ if(t==&cmd && typeend==t->rasp.nrunes && scratch[typeend-typestart-1]=… | |
+ setlock(); | |
+ outcmd(); | |
+ } | |
+ outTslS(Ttype, t->tag, typestart, scratch); | |
+ typestart = -1; | |
+ typeend = -1; | |
+ XFlush(_dpy); | |
+} | |
+ | |
+#define SCROLLKEY 0x80 | |
+#define UPKEY 0x81 | |
+#define ESC 0x1B | |
+ | |
+void | |
+type(Flayer *l, int res) /* what a bloody mess this is */ | |
+{ | |
+ Text *t = (Text *)l->user1; | |
+ Rune buf[100]; | |
+ Rune *p = buf; | |
+ int c, backspacing; | |
+ long a; | |
+ int scrollkey, upkey; | |
+ | |
+ scrollkey = 0; | |
+ upkey = 0; | |
+ if(res == RKeyboard) { | |
+ scrollkey = qpeekc()==SCROLLKEY; /* ICK */ | |
+ upkey = qpeekc() == UPKEY; | |
+ } | |
+ | |
+ if(lock || t->lock){ | |
+ kbdblock(); | |
+ return; | |
+ } | |
+ a = l->p0; | |
+ if(a!=l->p1 && !scrollkey && !upkey){ | |
+ flushtyping(1); | |
+ cut(t, t->front, 1, 1); | |
+ return; /* it may now be locked */ | |
+ } | |
+ backspacing = 0; | |
+ while((c = kbdchar())>0){ | |
+ if(res == RKeyboard){ | |
+ if(c == UPKEY || c==SCROLLKEY || c==ESC) | |
+ break; | |
+ /* backspace, ctrl-u, ctrl-w, del */ | |
+ if(c=='\b' || c==0x15 || c==0x17 || c==0x7F){ | |
+ backspacing = 1; | |
+ break; | |
+ } | |
+ } | |
+ *p++ = c; | |
+ if(c == '\n' || p >= buf+sizeof(buf)/sizeof(buf[0])) | |
+ break; | |
+ } | |
+ if(p > buf){ | |
+ if(typestart < 0) | |
+ typestart = a; | |
+ if(typeesc < 0) | |
+ typeesc = a; | |
+ hgrow(t->tag, a, p-buf, 0); | |
+ t->lock++; /* pretend we Trequest'ed for hdatarune*/ | |
+ hdatarune(t->tag, a, buf, p-buf); | |
+ a += p-buf; | |
+ l->p0 = a; | |
+ l->p1 = a; | |
+ typeend = a; | |
+ if(c=='\n' || typeend-typestart>100) | |
+ flushtyping(0); | |
+ onethird(l, a); | |
+ } | |
+ if(c == SCROLLKEY){ | |
+ flushtyping(0); | |
+ center(l, l->origin+l->f.nchars+1); | |
+ } else if (c == UPKEY) { | |
+ flushtyping(0); | |
+ outTsll(Torigin, t->tag, l->origin, l->f.maxlines+1); | |
+ /* backspacing immediately after outcmd(): sorry */ | |
+ }else if(backspacing && !lock){ | |
+ if(l->f.p0>0 && a>0){ | |
+ switch(c){ | |
+ case '\b': | |
+ case 0x7F: /* del */ | |
+ l->p0 = a-1; | |
+ break; | |
+ case 0x15: /* ctrl-u */ | |
+ l->p0 = ctlu(&t->rasp, l->origin, a); | |
+ break; | |
+ case 0x17: /* ctrl-w */ | |
+ l->p0 = ctlw(&t->rasp, l->origin, a); | |
+ break; | |
+ } | |
+ l->p1 = a; | |
+ if(l->p1 != l->p0){ | |
+ /* cut locally if possible */ | |
+ if(typestart<=l->p0 && l->p1<=typeend){ | |
+ t->lock++; /* to call hcut */ | |
+ hcut(t->tag, l->p0, l->p1-l->p0); | |
+ /* hcheck is local because we know ras… | |
+ hcheck(t->tag); | |
+ }else{ | |
+ flushtyping(0); | |
+ cut(t, t->front, 0, 1); | |
+ } | |
+ } | |
+ if(typeesc >= l->p0) | |
+ typeesc = l->p0; | |
+ if(typestart >= 0){ | |
+ if(typestart >= l->p0) | |
+ typestart = l->p0; | |
+ typeend = l->p0; | |
+ if(typestart == typeend){ | |
+ typestart = -1; | |
+ typeend = -1; | |
+ modified = 0; | |
+ } | |
+ } | |
+ } | |
+ }else{ | |
+ if(c==ESC && typeesc>=0){ | |
+ l->p0 = typeesc; | |
+ l->p1 = a; | |
+ flushtyping(1); | |
+ } | |
+ for(l=t->l; l<&t->l[NL]; l++) | |
+ if(l->textfn) | |
+ flsetselect(l, l->p0, l->p1); | |
+ } | |
+} | |
+ | |
+ | |
+void | |
+outcmd(void){ | |
+ if(work) | |
+ outTsll(Tworkfile, ((Text *)work->user1)->tag, work->p0, work-… | |
+} | |
+ | |
+void | |
+panic(char *s) | |
+{ | |
+ fprint(2, "samterm:panic: "); | |
+ perror(s); | |
+ abort(); | |
+} | |
+ | |
+Rune* | |
+stgettext(Flayer *l, long n, ulong *np) | |
+{ | |
+ Text *t; | |
+ | |
+ t = l->user1; | |
+ rload(&t->rasp, l->origin, l->origin+n, np); | |
+ return scratch; | |
+} | |
+ | |
+long | |
+scrtotal(Flayer *l) | |
+{ | |
+ return ((Text *)l->user1)->rasp.nrunes; | |
+} | |
+ | |
+void* | |
+alloc(ulong n) | |
+{ | |
+ void *p; | |
+ | |
+ p = malloc(n); | |
+ if(p == 0) | |
+ panic("alloc"); | |
+ memset(p, 0, n); | |
+ return p; | |
+} | |
diff --git a/samterm/menu.c b/samterm/menu.c | |
@@ -0,0 +1,380 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+uchar *name[MAXFILES]; /* first byte is ' ' or '\'': modified st… | |
+Text *text[MAXFILES]; /* pointer to Text associated with file */ | |
+ushort tag[MAXFILES]; /* text[i].tag, even if text[i] no… | |
+int nname; | |
+int mw; | |
+ | |
+char *genmenu3(int); | |
+char *genmenu2(int); | |
+char *genmenu2c(int); | |
+ | |
+enum Menu2 | |
+{ | |
+ Cut, | |
+ Paste, | |
+ Snarf, | |
+ Look, | |
+ Exch, | |
+ Search, | |
+ NMENU2 = Search, | |
+ Send = Search, | |
+ NMENU2C | |
+}; | |
+ | |
+enum Menu3 | |
+{ | |
+ New, | |
+ Zerox, | |
+ Reshape, | |
+ Close, | |
+ Write, | |
+ NMENU3 | |
+}; | |
+ | |
+char *menu2str[] = { | |
+ "cut", | |
+ "paste", | |
+ "snarf", | |
+ "look", | |
+ "<exch>", | |
+ 0, /* storage for last pattern */ | |
+}; | |
+ | |
+char *menu3str[] = { | |
+ "new", | |
+ "zerox", | |
+ "reshape", | |
+ "close", | |
+ "write", | |
+}; | |
+ | |
+Menu menu2 = {0, genmenu2}; | |
+Menu menu2c ={0, genmenu2c}; | |
+Menu menu3 = {0, genmenu3}; | |
+ | |
+void | |
+menu2hit(void) | |
+{ | |
+ Text *t=(Text *)which->user1; | |
+ int w = which-t->l; | |
+ int m; | |
+ | |
+ m = menuhit(2, &mouse, t==&cmd? &menu2c : &menu2); | |
+ if(lock || t->lock) | |
+ return; | |
+ | |
+ switch(m){ | |
+ case Cut: | |
+ cut(t, w, 1, 1); | |
+ break; | |
+ | |
+ case Paste: | |
+ paste(t, w); | |
+ break; | |
+ | |
+ case Snarf: | |
+ snarf(t, w); | |
+ break; | |
+ | |
+ case Exch: | |
+ snarf(t, w); | |
+ outT0(Tstartsnarf); | |
+ setlock(); | |
+ break; | |
+ | |
+ case Look: | |
+ outTsll(Tlook, t->tag, which->p0, which->p1); | |
+ setlock(); | |
+ break; | |
+ | |
+ case Search: | |
+ outcmd(); | |
+ if(t==&cmd) | |
+ outTsll(Tsend, 0 /*ignored*/, which->p0, which->p1); | |
+ else | |
+ outT0(Tsearch); | |
+ setlock(); | |
+ break; | |
+ } | |
+} | |
+ | |
+void | |
+menu3hit(void) | |
+{ | |
+ Rectangle r; | |
+ Flayer *l; | |
+ int m, i; | |
+ Text *t; | |
+ | |
+ mw = -1; | |
+ switch(m = menuhit(3, &mouse, &menu3)){ | |
+ case -1: | |
+ break; | |
+ | |
+ case New: | |
+ if(!lock) | |
+ sweeptext(1, 0); | |
+ break; | |
+ | |
+ case Zerox: | |
+ case Reshape: | |
+ if(!lock){ | |
+ cursorswitch(&bullseye); | |
+ buttons(Down); | |
+ if((mouse.buttons&4) && (l = flwhich(mouse.xy)) && get… | |
+ duplicate(l, r, l->f.font, m==Reshape); | |
+ else | |
+ cursorswitch(cursor); | |
+ buttons(Up); | |
+ } | |
+ break; | |
+ | |
+ case Close: | |
+ if(!lock){ | |
+ cursorswitch(&bullseye); | |
+ buttons(Down); | |
+ if((mouse.buttons&4) && (l = flwhich(mouse.xy)) && !lo… | |
+ t=(Text *)l->user1; | |
+ if (t->nwin>1) | |
+ closeup(l); | |
+ else if(t!=&cmd) { | |
+ outTs(Tclose, t->tag); | |
+ setlock(); | |
+ } | |
+ } | |
+ cursorswitch(cursor); | |
+ buttons(Up); | |
+ } | |
+ break; | |
+ | |
+ case Write: | |
+ if(!lock){ | |
+ cursorswitch(&bullseye); | |
+ buttons(Down); | |
+ if((mouse.buttons&4) && (l = flwhich(mouse.xy))){ | |
+ outTs(Twrite, ((Text *)l->user1)->tag); | |
+ setlock(); | |
+ }else | |
+ cursorswitch(cursor); | |
+ buttons(Up); | |
+ } | |
+ break; | |
+ | |
+ default: | |
+ if(t = text[m-NMENU3]){ | |
+ i = t->front; | |
+ if(t->nwin==0 || t->l[i].textfn==0) | |
+ return; /* not ready yet; try again lat… | |
+ if(t->nwin>1 && which==&t->l[i]) | |
+ do | |
+ if(++i==NL) | |
+ i = 0; | |
+ while(i!=t->front && t->l[i].textfn==0); | |
+ current(&t->l[i]); | |
+ }else if(!lock) | |
+ sweeptext(0, tag[m-NMENU3]); | |
+ break; | |
+ } | |
+} | |
+ | |
+ | |
+Text * | |
+sweeptext(int new, int tag) | |
+{ | |
+ Rectangle r; | |
+ Text *t; | |
+ | |
+ if(getr(&r) && (t = malloc(sizeof(Text)))){ | |
+ memset((void*)t, 0, sizeof(Text)); | |
+ current((Flayer *)0); | |
+ flnew(&t->l[0], stgettext, 0, (char *)t); | |
+ flinit(&t->l[0], r, font); /*bnl*/ | |
+ t->nwin = 1; | |
+ rinit(&t->rasp); | |
+ if(new) | |
+ startnewfile(Tstartnewfile, t); | |
+ else{ | |
+ rinit(&t->rasp); | |
+ t->tag = tag; | |
+ startfile(t); | |
+ } | |
+ return t; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+int | |
+whichmenu(int tg) | |
+{ | |
+ int i; | |
+ | |
+ for(i=0; i<nname; i++) | |
+ if(tag[i] == tg) | |
+ return i; | |
+ return -1; | |
+} | |
+ | |
+void | |
+menuins(int n, uchar *s, Text *t, int m, int tg) | |
+{ | |
+ int i; | |
+ | |
+ if(nname == MAXFILES) | |
+ panic("menuins"); | |
+ for(i=nname; i>n; --i) | |
+ name[i]=name[i-1], text[i]=text[i-1], tag[i]=tag[i-1]; | |
+ text[n] = t; | |
+ tag[n] = tg; | |
+ name[n] = alloc(strlen((char*)s)+2); | |
+ name[n][0] = m; | |
+ strcpy((char*)name[n]+1, (char*)s); | |
+ nname++; | |
+ menu3.lasthit = n+NMENU3; | |
+} | |
+ | |
+void | |
+menudel(int n) | |
+{ | |
+ int i; | |
+ | |
+ if(nname==0 || n>=nname || text[n]) | |
+ panic("menudel"); | |
+ free(name[n]); | |
+ --nname; | |
+ for(i = n; i<nname; i++) | |
+ name[i]=name[i+1], text[i]=text[i+1], tag[i]=tag[i+1]; | |
+} | |
+ | |
+void | |
+setpat(char *s) | |
+{ | |
+ static char pat[17]; | |
+ | |
+ pat[0] = '/'; | |
+ strncpy(pat+1, s, 15); | |
+ menu2str[Search] = pat; | |
+} | |
+ | |
+#define NBUF 64 | |
+static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '}; | |
+ | |
+char * | |
+paren(char *s) | |
+{ | |
+ uchar *t = buf; | |
+ | |
+ *t++ = '('; | |
+ do; while(*t++ = *s++); | |
+ t[-1] = ')'; | |
+ *t = 0; | |
+ return (char *)buf; | |
+} | |
+char* | |
+genmenu2(int n) | |
+{ | |
+ Text *t=(Text *)which->user1; | |
+ char *p; | |
+ if(n>=NMENU2+(menu2str[Search]!=0)) | |
+ return 0; | |
+ p = menu2str[n]; | |
+ if(!lock && !t->lock || n==Search || n==Look) | |
+ return p; | |
+ return paren(p); | |
+} | |
+char* | |
+genmenu2c(int n) | |
+{ | |
+ Text *t=(Text *)which->user1; | |
+ char *p; | |
+ if(n >= NMENU2C) | |
+ return 0; | |
+ if(n == Send) | |
+ p="send"; | |
+ else | |
+ p = menu2str[n]; | |
+ if(!lock && !t->lock) | |
+ return p; | |
+ return paren(p); | |
+} | |
+char * | |
+genmenu3(int n) | |
+{ | |
+ Text *t; | |
+ int c, i, k, l, w; | |
+ Rune r; | |
+ char *p; | |
+ | |
+ if(n >= NMENU3+nname) | |
+ return 0; | |
+ if(n < NMENU3){ | |
+ p = menu3str[n]; | |
+ if(lock) | |
+ p = paren(p); | |
+ return p; | |
+ } | |
+ n -= NMENU3; | |
+ if(n == 0) /* unless we've been fooled, this is cmd */ | |
+ return (char *)&name[n][1]; | |
+ if(mw == -1){ | |
+ mw = 7; /* strlen("~~sam~~"); */ | |
+ for(i=1; i<nname; i++){ | |
+ w = utflen((char*)name[i]+1)+4; /* include "'+.… | |
+ if(w > mw) | |
+ mw = w; | |
+ } | |
+ } | |
+ if(mw > NBUF) | |
+ mw = NBUF; | |
+ t = text[n]; | |
+ buf[0] = name[n][0]; | |
+ buf[1] = '-'; | |
+ buf[2] = ' '; | |
+ buf[3] = ' '; | |
+ if(t){ | |
+ if(t->nwin == 1) | |
+ buf[1] = '+'; | |
+ else if(t->nwin > 1) | |
+ buf[1] = '*'; | |
+ if(work && t==(Text *)work->user1) { | |
+ buf[2]= '.'; | |
+ if(modified) | |
+ buf[0] = '\''; | |
+ } | |
+ } | |
+ l = utflen((char*)name[n]+1); | |
+ if(l > NBUF-4-2){ | |
+ i = 4; | |
+ k = 1; | |
+ while(i < NBUF/2){ | |
+ k += chartorune(&r, (char*)name[n]+k); | |
+ i++; | |
+ } | |
+ c = name[n][k]; | |
+ name[n][k] = 0; | |
+ strcpy((char*)buf+4, (char*)name[n]+1); | |
+ name[n][k] = c; | |
+ strcat((char*)buf, "..."); | |
+ while((l-i) >= NBUF/2-4){ | |
+ k += chartorune(&r, (char*)name[n]+k); | |
+ i++; | |
+ } | |
+ strcat((char*)buf, (char*)name[n]+k); | |
+ }else | |
+ strcpy((char*)buf+4, (char*)name[n]+1); | |
+ i = utflen((char*)buf); | |
+ k = strlen((char*)buf); | |
+ while(i<mw && k<sizeof buf-1){ | |
+ buf[k++] = ' '; | |
+ i++; | |
+ } | |
+ buf[k] = 0; | |
+ return (char *)buf; | |
+} | |
diff --git a/samterm/mesg.c b/samterm/mesg.c | |
@@ -0,0 +1,794 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <string.h> | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+extern char *exname; | |
+ | |
+#define HSIZE 3 /* Type + short count */ | |
+Header h; | |
+uchar indata[DATASIZE+1]; /* room for NUL */ | |
+uchar outdata[DATASIZE]; | |
+short outcount; | |
+int hversion; | |
+ | |
+void inmesg(Hmesg, int); | |
+int inshort(int); | |
+long inlong(int); | |
+long invlong(int); | |
+void hsetdot(int, long, long); | |
+void hmoveto(int, long); | |
+void hsetsnarf(int); | |
+void clrlock(void); | |
+int snarfswap(char*, int, char**); | |
+ | |
+void | |
+rcv(void) | |
+{ | |
+ int c; | |
+ static state = 0; | |
+ static count = 0; | |
+ static i = 0; | |
+ static int errs = 0; | |
+ | |
+ while((c=rcvchar()) != -1) | |
+ switch(state){ | |
+ case 0: | |
+ h.type = c; | |
+ state++; | |
+ break; | |
+ | |
+ case 1: | |
+ h.count0 = c; | |
+ state++; | |
+ break; | |
+ | |
+ case 2: | |
+ h.count1 = c; | |
+ count = h.count0|(h.count1<<8); | |
+ i = 0; | |
+ if(count > DATASIZE){ | |
+ if(++errs < 5){ | |
+ dumperrmsg(count, h.type, h.count0, c); | |
+ state = 0; | |
+ continue; | |
+ } | |
+ fprint(2, "type %d count %d\n", h.type, count); | |
+ panic("count>DATASIZE"); | |
+ } | |
+ if(count == 0) | |
+ goto zerocount; | |
+ state++; | |
+ break; | |
+ | |
+ case 3: | |
+ indata[i++] = c; | |
+ if(i == count){ | |
+ zerocount: | |
+ indata[i] = 0; | |
+ inmesg(h.type, count); | |
+ state = count = 0; | |
+ continue; | |
+ } | |
+ break; | |
+ } | |
+} | |
+ | |
+Text * | |
+whichtext(int tg) | |
+{ | |
+ int i; | |
+ | |
+ for(i=0; i<nname; i++) | |
+ if(tag[i] == tg) | |
+ return text[i]; | |
+ panic("whichtext"); | |
+ return 0; | |
+} | |
+ | |
+void | |
+inmesg(Hmesg type, int count) | |
+{ | |
+ Text *t; | |
+ int i, m; | |
+ long l; | |
+ Flayer *lp; | |
+ char syscmd[512]; | |
+ | |
+ m = inshort(0); | |
+ l = inlong(2); | |
+ switch(type){ | |
+ case -1: | |
+ panic("rcv error"); | |
+ default: | |
+ fprint(2, "type %d\n", type); | |
+ panic("rcv unknown"); | |
+ | |
+ case Hversion: | |
+ hversion = m; | |
+ break; | |
+ | |
+ case Hbindname: | |
+ l = invlong(2); /* for 64-bit pointers */ | |
+ if((i=whichmenu(m)) < 0) | |
+ break; | |
+ /* in case of a race, a bindname may already have occurred */ | |
+ if((t=whichtext(m)) == 0) | |
+ t=(Text *)l; | |
+ else /* let the old one win; clean up the new one */ | |
+ while(((Text *)l)->nwin>0) | |
+ closeup(&((Text *)l)->l[((Text *)l)->front]); | |
+ text[i] = t; | |
+ text[i]->tag = m; | |
+ break; | |
+ | |
+ case Hcurrent: | |
+ if(whichmenu(m)<0) | |
+ break; | |
+ t = whichtext(m); | |
+ i = which && ((Text *)which->user1)==&cmd && m!=cmd.tag; | |
+ if(t==0 && (t = sweeptext(0, m))==0) | |
+ break; | |
+ if(t->l[t->front].textfn==0) | |
+ panic("Hcurrent"); | |
+ lp = &t->l[t->front]; | |
+ if(i){ | |
+ flupfront(lp); | |
+ flborder(lp, 0); | |
+ work = lp; | |
+ }else | |
+ current(lp); | |
+ break; | |
+ | |
+ case Hmovname: | |
+ if((m=whichmenu(m)) < 0) | |
+ break; | |
+ t = text[m]; | |
+ l = tag[m]; | |
+ i = name[m][0]; | |
+ text[m] = 0; /* suppress panic in menudel */ | |
+ menudel(m); | |
+ if(t == &cmd) | |
+ m = 0; | |
+ else{ | |
+ if (nname>0 && text[0]==&cmd) | |
+ m = 1; | |
+ else m = 0; | |
+ for(; m<nname; m++) | |
+ if(strcmp((char*)indata+2, (char*)name[m]+1)<0) | |
+ break; | |
+ } | |
+ menuins(m, indata+2, t, i, (int)l); | |
+ break; | |
+ | |
+ case Hgrow: | |
+ if(whichmenu(m) >= 0) | |
+ hgrow(m, l, inlong(6), 1); | |
+ break; | |
+ | |
+ case Hnewname: | |
+ menuins(0, (uchar *)"", (Text *)0, ' ', m); | |
+ break; | |
+ | |
+ case Hcheck0: | |
+ i = whichmenu(m); | |
+ if(i>=0) { | |
+ t = text[i]; | |
+ if (t) | |
+ t->lock++; | |
+ outTs(Tcheck, m); | |
+ } | |
+ break; | |
+ | |
+ case Hcheck: | |
+ i = whichmenu(m); | |
+ if(i>=0) { | |
+ t = text[i]; | |
+ if (t && t->lock) | |
+ t->lock--; | |
+ hcheck(m); | |
+ } | |
+ break; | |
+ | |
+ case Hunlock: | |
+ clrlock(); | |
+ break; | |
+ | |
+ case Hdata: | |
+ if(whichmenu(m) >= 0) | |
+ l += hdata(m, l, indata+6, count-6); | |
+ Checkscroll: | |
+ if(m == cmd.tag){ | |
+ for(i=0; i<NL; i++){ | |
+ lp = &cmd.l[i]; | |
+ if(lp->textfn) | |
+ center(lp, l>=0? l : lp->p1); | |
+ } | |
+ } | |
+ break; | |
+ | |
+ case Horigin: | |
+ if(whichmenu(m) >= 0) | |
+ horigin(m, l); | |
+ break; | |
+ | |
+ case Hunlockfile: | |
+ if(whichmenu(m)>=0 && (t = whichtext(m))->lock){ | |
+ --t->lock; | |
+ l = -1; | |
+ goto Checkscroll; | |
+ } | |
+ break; | |
+ | |
+ case Hsetdot: | |
+ if(whichmenu(m) >= 0) | |
+ hsetdot(m, l, inlong(6)); | |
+ break; | |
+ | |
+ case Hgrowdata: | |
+ if(whichmenu(m)<0) | |
+ break; | |
+ hgrow(m, l, inlong(6), 0); | |
+ whichtext(m)->lock++; /* fake the request */ | |
+ l += hdata(m, l, indata+10, count-10); | |
+ goto Checkscroll; | |
+ | |
+ case Hmoveto: | |
+ if(whichmenu(m)>=0) | |
+ hmoveto(m, l); | |
+ break; | |
+ | |
+ case Hclean: | |
+ if((m = whichmenu(m)) >= 0) | |
+ name[m][0] = ' '; | |
+ break; | |
+ | |
+ case Hdirty: | |
+ if((m = whichmenu(m))>=0) | |
+ name[m][0] = '\''; | |
+ break; | |
+ | |
+ case Hdelname: | |
+ if((m=whichmenu(m)) >= 0) | |
+ menudel(m); | |
+ break; | |
+ | |
+ case Hcut: | |
+ if(whichmenu(m) >= 0) | |
+ hcut(m, l, inlong(6)); | |
+ break; | |
+ | |
+ case Hclose: | |
+ if(whichmenu(m)<0 || (t = whichtext(m))==0) | |
+ break; | |
+ l = t->nwin; | |
+ for(i = 0,lp = t->l; l>0 && i<NL; i++,lp++) | |
+ if(lp->textfn){ | |
+ closeup(lp); | |
+ --l; | |
+ } | |
+ break; | |
+ | |
+ case Hsetpat: | |
+ setpat((char *)indata); | |
+ break; | |
+ | |
+ case Hsetsnarf: | |
+ hsetsnarf(m); | |
+ break; | |
+ | |
+ case Hsnarflen: | |
+ snarflen = inlong(0); | |
+ break; | |
+ | |
+ case Hack: | |
+ outT0(Tack); | |
+ break; | |
+ | |
+#ifndef NOFIFO | |
+ case Hextcmd: | |
+ if (exname != NULL) | |
+ { | |
+ int fifofd = open(exname, O_WRONLY); | |
+ if (fifofd >= 0) | |
+ { | |
+ memset(syscmd, 0, 512); | |
+ snprintf(syscmd, 511, "%s", (char *)indata); | |
+ write(fifofd, syscmd, 511); | |
+ close(fifofd); | |
+ } | |
+ } | |
+ break; | |
+#endif | |
+ | |
+ case Hexit: | |
+ outT0(Texit); | |
+ mouseexit(); | |
+ break; | |
+ } | |
+} | |
+ | |
+void | |
+setlock(void) | |
+{ | |
+ lock++; | |
+ cursorswitch(cursor = &lockarrow); | |
+} | |
+ | |
+void | |
+clrlock(void) | |
+{ | |
+ hasunlocked = 1; | |
+ if(lock > 0) | |
+ lock--; | |
+ if(lock == 0) | |
+ cursorswitch(cursor=(Cursor *)0); | |
+} | |
+ | |
+void | |
+startfile(Text *t) | |
+{ | |
+ outTsv(Tstartfile, t->tag, t); /* for 64-bit pointers */ | |
+ setlock(); | |
+} | |
+ | |
+void | |
+startnewfile(int type, Text *t) | |
+{ | |
+ t->tag = Untagged; | |
+ outTv(type, t); /* for 64-bit pointers … | |
+} | |
+ | |
+int | |
+inshort(int n) | |
+{ | |
+ return indata[n]|(indata[n+1]<<8); | |
+} | |
+ | |
+long | |
+inlong(int n) | |
+{ | |
+ return indata[n]|(indata[n+1]<<8)| | |
+ ((long)indata[n+2]<<16)|((long)indata[n+3]<<24); | |
+} | |
+ | |
+long | |
+invlong(int n) | |
+{ | |
+ long l; | |
+ | |
+ l = (indata[n+7]<<24) | (indata[n+6]<<16) | (indata[n+5]<<8) | indata[… | |
+ l = (l<<16) | (indata[n+3]<<8) | indata[n+2]; | |
+ l = (l<<16) | (indata[n+1]<<8) | indata[n]; | |
+ return l; | |
+} | |
+ | |
+void | |
+outT0(Tmesg type) | |
+{ | |
+ outstart(type); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTl(Tmesg type, long l) | |
+{ | |
+ outstart(type); | |
+ outlong(l); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTs(Tmesg type, int s) | |
+{ | |
+ outstart(type); | |
+ outshort(s); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTss(Tmesg type, int s1, int s2) | |
+{ | |
+ outstart(type); | |
+ outshort(s1); | |
+ outshort(s2); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTsll(Tmesg type, int s1, long l1, long l2) | |
+{ | |
+ outstart(type); | |
+ outshort(s1); | |
+ outlong(l1); | |
+ outlong(l2); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTsl(Tmesg type, int s1, long l1) | |
+{ | |
+ outstart(type); | |
+ outshort(s1); | |
+ outlong(l1); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTsv(Tmesg type, int s1, void *l1) | |
+{ | |
+ outstart(type); | |
+ outshort(s1); | |
+ outvlong(l1); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTv(Tmesg type, void *l1) | |
+{ | |
+ outstart(type); | |
+ outvlong(l1); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTslS(Tmesg type, int s1, long l1, Rune *s) | |
+{ | |
+ char buf[DATASIZE*3+1]; | |
+ char *c; | |
+ | |
+ outstart(type); | |
+ outshort(s1); | |
+ outlong(l1); | |
+ c = buf; | |
+ while(*s) | |
+ c += runetochar(c, s++); | |
+ *c++ = 0; | |
+ outcopy(c-buf, (uchar *)buf); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outTsls(Tmesg type, int s1, long l1, int s2) | |
+{ | |
+ outstart(type); | |
+ outshort(s1); | |
+ outlong(l1); | |
+ outshort(s2); | |
+ outsend(); | |
+} | |
+ | |
+void | |
+outstart(Tmesg type) | |
+{ | |
+ outdata[0] = type; | |
+ outcount = 0; | |
+} | |
+ | |
+void | |
+outcopy(int count, uchar *data) | |
+{ | |
+ while(count--) | |
+ outdata[HSIZE+outcount++] = *data++; | |
+} | |
+ | |
+void | |
+outshort(int s) | |
+{ | |
+ uchar buf[2]; | |
+ | |
+ buf[0]=s; | |
+ buf[1]=s>>8; | |
+ outcopy(2, buf); | |
+} | |
+ | |
+void | |
+outlong(long l) | |
+{ | |
+ uchar buf[4]; | |
+ | |
+ buf[0]=l; | |
+ buf[1]=l>>8; | |
+ buf[2]=l>>16; | |
+ buf[3]=l>>24; | |
+ outcopy(4, buf); | |
+} | |
+ | |
+void | |
+outvlong(void *v) | |
+{ | |
+ int i; | |
+ ulong l; | |
+ uchar buf[8]; | |
+ | |
+ l = (ulong) v; | |
+ for(i = 0; i < sizeof(buf); i++, l >>= 8) | |
+ buf[i] = l; | |
+ | |
+ outcopy(8, buf); | |
+} | |
+ | |
+void | |
+outsend(void) | |
+{ | |
+ if(outcount>DATASIZE-HSIZE) | |
+ panic("outcount>sizeof outdata"); | |
+ outdata[1]=outcount; | |
+ outdata[2]=outcount>>8; | |
+ if(write(1, (char *)outdata, outcount+HSIZE)!=outcount+HSIZE) | |
+ exits("write error"); | |
+} | |
+ | |
+ | |
+void | |
+hsetdot(int m, long p0, long p1) | |
+{ | |
+ Text *t = whichtext(m); | |
+ Flayer *l = &t->l[t->front]; | |
+ | |
+ flushtyping(1); | |
+ flsetselect(l, p0, p1); | |
+} | |
+ | |
+void | |
+horigin(int m, long p0) | |
+{ | |
+ Text *t = whichtext(m); | |
+ Flayer *l = &t->l[t->front]; | |
+ long a; | |
+ ulong n; | |
+ Rune *r; | |
+ | |
+ if(!flprepare(l)){ | |
+ l->origin = p0; | |
+ return; | |
+ } | |
+ a = p0-l->origin; | |
+ if(a>=0 && a<l->f.nchars) | |
+ frdelete(&l->f, 0, a); | |
+ else if(a<0 && -a<l->f.nchars){ | |
+ r = rload(&t->rasp, p0, l->origin, &n); | |
+ frinsert(&l->f, r, r+n, 0); | |
+ }else | |
+ frdelete(&l->f, 0, l->f.nchars); | |
+ l->origin = p0; | |
+ scrdraw(l, t->rasp.nrunes); | |
+ if(l->visible==Some) | |
+ flrefresh(l, l->entire, 0); | |
+ hcheck(m); | |
+} | |
+ | |
+void | |
+hmoveto(int m, long p0) | |
+{ | |
+ Text *t = whichtext(m); | |
+ Flayer *l = &t->l[t->front]; | |
+ | |
+ if(p0<l->origin || p0-l->origin>l->f.nchars*9/10) | |
+ outTsll(Torigin, m, p0, 2L); | |
+} | |
+ | |
+void | |
+hcheck(int m) | |
+{ | |
+ Flayer *l; | |
+ Text *t; | |
+ int reqd = 0, i; | |
+ long n, nl, a; | |
+ Rune *r; | |
+ | |
+ if(m == Untagged) | |
+ return; | |
+ t = whichtext(m); | |
+ if(t == 0) /* possible in a half-built window */ | |
+ return; | |
+ for(l = &t->l[0], i = 0; i<NL; i++, l++){ | |
+ if(l->textfn==0 || !flprepare(l)) /* BUG: don't | |
+ need this if BUG be… | |
+ is fixed */ | |
+ continue; | |
+ a = t->l[i].origin; | |
+ n = rcontig(&t->rasp, a, a+l->f.nchars, 1); | |
+ if(n<l->f.nchars) /* text missing in middle of screen */ | |
+ a+=n; | |
+ else{ /* text missing at end of screen?… | |
+ Again: | |
+ if(l->f.lastlinefull) | |
+ goto Checksel; /* all's well */ | |
+ a = t->l[i].origin+l->f.nchars; | |
+ n = t->rasp.nrunes-a; | |
+ if(n==0) | |
+ goto Checksel; | |
+ if(n>TBLOCKSIZE) | |
+ n = TBLOCKSIZE; | |
+ n = rcontig(&t->rasp, a, a+n, 1); | |
+ if(n>0){ | |
+ rload(&t->rasp, a, a+n, 0); | |
+ nl = l->f.nchars; | |
+ r = scratch; | |
+ flinsert(l, r, r+n, l->origin+nl); | |
+ if(nl == l->f.nchars) /* made no progre… | |
+ goto Checksel; | |
+ goto Again; | |
+ } | |
+ } | |
+ if(!reqd){ | |
+ n = rcontig(&t->rasp, a, a+TBLOCKSIZE, 0); | |
+ if(n <= 0) | |
+ panic("hcheck request==0"); | |
+ outTsls(Trequest, m, a, (int)n); | |
+ outTs(Tcheck, m); | |
+ t->lock++; /* for the Trequest */ | |
+ t->lock++; /* for the Tcheck */ | |
+ reqd++; | |
+ } | |
+ Checksel: | |
+ flsetselect(l, l->p0, l->p1); | |
+ } | |
+} | |
+ | |
+void | |
+flnewlyvisible(Flayer *l) | |
+{ | |
+ hcheck(((Text *)l->user1)->tag); | |
+} | |
+ | |
+void | |
+hsetsnarf(int nc) | |
+{ | |
+ char *s2; | |
+ char *s1; | |
+ int i; | |
+ int n; | |
+ | |
+ cursorswitch(&deadmouse); | |
+ s2 = alloc(nc+1); | |
+ for(i=0; i<nc; i++) | |
+ s2[i] = getch(); | |
+ s2[nc] = 0; | |
+ n = snarfswap(s2, nc, &s1); | |
+ if(n >= 0){ | |
+ if(!s1) | |
+ n = 0; | |
+ if(n > SNARFSIZE-1) | |
+ n = SNARFSIZE-1; | |
+ s1 = realloc(s1, n+1); | |
+ if (!s1) | |
+ exits("malloc"); | |
+ s1[n] = 0; | |
+ snarflen = n; | |
+ outTs(Tsetsnarf, n); | |
+ if(n>0 && write(1, s1, n)!=n) | |
+ exits("write error"); | |
+ free(s1); | |
+ }else | |
+ outTs(Tsetsnarf, 0); | |
+ free(s2); | |
+ cursorswitch(cursor); | |
+} | |
+ | |
+void | |
+hgrow(int m, long a, long new, int req) | |
+{ | |
+ int i; | |
+ Flayer *l; | |
+ Text *t = whichtext(m); | |
+ long o, b; | |
+ | |
+ if(new <= 0) | |
+ panic("hgrow"); | |
+ rresize(&t->rasp, a, 0L, new); | |
+ for(l = &t->l[0], i = 0; i<NL; i++, l++){ | |
+ if(l->textfn == 0) | |
+ continue; | |
+ o = l->origin; | |
+ b = a-o-rmissing(&t->rasp, o, a); | |
+ if(a < o) | |
+ l->origin+=new; | |
+ if(a < l->p0) | |
+ l->p0+=new; | |
+ if(a < l->p1) | |
+ l->p1+=new; | |
+ /* must prevent b temporarily becoming unsigned */ | |
+ if(!req || a<o || (b>0 && b>l->f.nchars) || | |
+ (l->f.nchars==0 && a-o>0)) | |
+ continue; | |
+ if(new>TBLOCKSIZE) | |
+ new = TBLOCKSIZE; | |
+ outTsls(Trequest, m, a, (int)new); | |
+ t->lock++; | |
+ req = 0; | |
+ } | |
+} | |
+ | |
+int | |
+hdata1(Text *t, long a, Rune *r, int len) | |
+{ | |
+ int i; | |
+ Flayer *l; | |
+ long o, b; | |
+ | |
+ for(l = &t->l[0], i=0; i<NL; i++, l++){ | |
+ if(l->textfn==0) | |
+ continue; | |
+ o = l->origin; | |
+ b = a-o-rmissing(&t->rasp, o, a); | |
+ /* must prevent b temporarily becoming unsigned */ | |
+ if(a<o || (b>0 && b>l->f.nchars)) | |
+ continue; | |
+ flinsert(l, r, r+len, o+b); | |
+ } | |
+ rdata(&t->rasp, a, a+len, r); | |
+ rclean(&t->rasp); | |
+ return len; | |
+} | |
+ | |
+int | |
+hdata(int m, long a, uchar *s, int len) | |
+{ | |
+ int i, w; | |
+ Text *t = whichtext(m); | |
+ Rune buf[DATASIZE], *r; | |
+ | |
+ if(t->lock) | |
+ --t->lock; | |
+ if(len == 0) | |
+ return 0; | |
+ r = buf; | |
+ for(i=0; i<len; i+=w,s+=w) | |
+ w = chartorune(r++, (char*)s); | |
+ return hdata1(t, a, buf, r-buf); | |
+} | |
+ | |
+int | |
+hdatarune(int m, long a, Rune *r, int len) | |
+{ | |
+ Text *t = whichtext(m); | |
+ | |
+ if(t->lock) | |
+ --t->lock; | |
+ if(len == 0) | |
+ return 0; | |
+ return hdata1(t, a, r, len); | |
+} | |
+ | |
+void | |
+hcut(int m, long a, long old) | |
+{ | |
+ Flayer *l; | |
+ Text *t = whichtext(m); | |
+ int i; | |
+ long o, b; | |
+ | |
+ if(t->lock) | |
+ --t->lock; | |
+ for(l = &t->l[0], i = 0; i<NL; i++, l++){ | |
+ if(l->textfn == 0) | |
+ continue; | |
+ o = l->origin; | |
+ b = a-o-rmissing(&t->rasp, o, a); | |
+ /* must prevent b temporarily becoming unsigned */ | |
+ if((b<0 || b<l->f.nchars) && a+old>=o){ | |
+ fldelete(l, b<0? o : o+b, | |
+ a+old-rmissing(&t->rasp, o, a+old)); | |
+ } | |
+ if(a+old<o) | |
+ l->origin-=old; | |
+ else if(a<=o) | |
+ l->origin = a; | |
+ if(a+old<l->p0) | |
+ l->p0-=old; | |
+ else if(a<=l->p0) | |
+ l->p0 = a; | |
+ if(a+old<l->p1) | |
+ l->p1-=old; | |
+ else if(a<=l->p1) | |
+ l->p1 = a; | |
+ } | |
+ rresize(&t->rasp, a, old, 0L); | |
+ rclean(&t->rasp); | |
+} | |
diff --git a/samterm/plan9.c b/samterm/plan9.c | |
@@ -0,0 +1,113 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+static char exname[64]; | |
+ | |
+void | |
+getscreen(int argc, char **argv) | |
+{ | |
+ USED(argc); | |
+ USED(argv); | |
+ binit1(panic, 0, "sam", 1); | |
+ bitblt(&screen, screen.clipr.min, &screen, screen.clipr, 0); | |
+} | |
+ | |
+int | |
+screensize(int *w, int *h) | |
+{ | |
+ int fd, n; | |
+ char buf[5*12+1]; | |
+ | |
+ fd = open("/dev/screen", OREAD); | |
+ if(fd < 0) | |
+ return 0; | |
+ n = read(fd, buf, sizeof(buf)-1); | |
+ close(fd); | |
+ if (n != sizeof(buf)-1) | |
+ return 0; | |
+ buf[n] = 0; | |
+ if (h) { | |
+ *h = atoi(buf+4*12)-atoi(buf+2*12); | |
+ if (*h < 0) | |
+ return 0; | |
+ } | |
+ if (w) { | |
+ *w = atoi(buf+3*12)-atoi(buf+1*12); | |
+ if (*w < 0) | |
+ return 0; | |
+ } | |
+ return 1; | |
+} | |
+ | |
+int | |
+snarfswap(char *fromsam, int nc, char **tosam) | |
+{ | |
+ char *s1; | |
+ int f, n; | |
+ | |
+ f = open("/dev/snarf", 0); | |
+ if(f < 0) | |
+ return -1; | |
+ *tosam = s1 = alloc(SNARFSIZE); | |
+ n = read(f, s1, SNARFSIZE-1); | |
+ close(f); | |
+ if(n < 0) | |
+ n = 0; | |
+ if (n == 0) { | |
+ *tosam = 0; | |
+ free(s1); | |
+ } else | |
+ s1[n] = 0; | |
+ f = create("/dev/snarf", 1, 0666); | |
+ if(f >= 0){ | |
+ write(f, fromsam, nc); | |
+ close(f); | |
+ } | |
+ return n; | |
+} | |
+ | |
+void | |
+dumperrmsg(int count, int type, int count0, int c) | |
+{ | |
+ fprint(2, "samterm: host mesg: count %d %x %x %x %s...ignored\n", | |
+ count, type, count0, c, rcvstring()); | |
+} | |
+ | |
+void | |
+removeextern(void) | |
+{ | |
+ remove(exname); | |
+} | |
+ | |
+void | |
+extstart(void) | |
+{ | |
+ char buf[32]; | |
+ int fd, p[2]; | |
+ | |
+ if(pipe(p) < 0) | |
+ return; | |
+ sprint(exname, "/srv/sam.%s", getuser()); | |
+ fd = create(exname, 1, 0600); | |
+ if(fd < 0){ /* assume existing guy is more important */ | |
+ Err: | |
+ close(p[0]); | |
+ close(p[1]); | |
+ return; | |
+ } | |
+ sprint(buf, "%d", p[0]); | |
+ if(write(fd, buf, strlen(buf)) <= 0) | |
+ goto Err; | |
+ close(fd); | |
+ /* | |
+ * leave p[0] open so if the file is removed the event | |
+ * library won't get an error | |
+ */ | |
+ estart(Eextern, p[1], 8192); | |
+ atexit(removeextern); | |
+} | |
diff --git a/samterm/rasp.c b/samterm/rasp.c | |
@@ -0,0 +1,263 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+void | |
+rinit(Rasp *r) | |
+{ | |
+ r->nrunes=0; | |
+ r->sect=0; | |
+} | |
+ | |
+void | |
+rclear(Rasp *r) | |
+{ | |
+ Section *s, *ns; | |
+ | |
+ for(s=r->sect; s; s=ns){ | |
+ ns = s->next; | |
+ free(s->text); | |
+ free(s); | |
+ } | |
+ r->sect = 0; | |
+} | |
+ | |
+Section* | |
+rsinsert(Rasp *r, Section *s) /* insert before s */ | |
+{ | |
+ Section *t; | |
+ Section *u; | |
+ | |
+ t = alloc(sizeof(Section)); | |
+ if(r->sect == s){ /* includes empty list case: r->sect==s==0 */ | |
+ r->sect = t; | |
+ t->next = s; | |
+ }else{ | |
+ u = r->sect; | |
+ if(u == 0) | |
+ panic("rsinsert 1"); | |
+ do{ | |
+ if(u->next == s){ | |
+ t->next = s; | |
+ u->next = t; | |
+ goto Return; | |
+ } | |
+ u=u->next; | |
+ }while(u); | |
+ panic("rsinsert 2"); | |
+ } | |
+ Return: | |
+ return t; | |
+} | |
+ | |
+void | |
+rsdelete(Rasp *r, Section *s) | |
+{ | |
+ Section *t; | |
+ | |
+ if(s == 0) | |
+ panic("rsdelete"); | |
+ if(r->sect == s){ | |
+ r->sect = s->next; | |
+ goto Free; | |
+ } | |
+ for(t=r->sect; t; t=t->next) | |
+ if(t->next == s){ | |
+ t->next = s->next; | |
+ Free: | |
+ if(s->text) | |
+ free(s->text); | |
+ free(s); | |
+ return; | |
+ } | |
+ panic("rsdelete 2"); | |
+} | |
+ | |
+void | |
+splitsect(Rasp *r, Section *s, long n0) | |
+{ | |
+ if(s == 0) | |
+ panic("splitsect"); | |
+ rsinsert(r, s->next); | |
+ if(s->text == 0) | |
+ s->next->text = 0; | |
+ else{ | |
+ s->next->text = alloc(RUNESIZE*(TBLOCKSIZE+1)); | |
+ Strcpy(s->next->text, s->text+n0); | |
+ s->text[n0] = 0; | |
+ } | |
+ s->next->nrunes = s->nrunes-n0; | |
+ s->nrunes = n0; | |
+} | |
+ | |
+Section * | |
+findsect(Rasp *r, Section *s, long p, long q) /* find sect containing q… | |
+{ | |
+ if(s==0 && p!=q) | |
+ panic("findsect"); | |
+ for(; s && p+s->nrunes<=q; s=s->next) | |
+ p += s->nrunes; | |
+ if(p != q){ | |
+ splitsect(r, s, q-p); | |
+ s = s->next; | |
+ } | |
+ return s; | |
+} | |
+ | |
+void | |
+rresize(Rasp *r, long a, long old, long new) | |
+{ | |
+ Section *s, *t, *ns; | |
+ | |
+ s = findsect(r, r->sect, 0L, a); | |
+ t = findsect(r, s, a, a+old); | |
+ for(; s!=t; s=ns){ | |
+ ns=s->next; | |
+ rsdelete(r, s); | |
+ } | |
+ /* now insert the new piece before t */ | |
+ if(new > 0){ | |
+ ns=rsinsert(r, t); | |
+ ns->nrunes=new; | |
+ ns->text=0; | |
+ } | |
+ r->nrunes += new-old; | |
+} | |
+ | |
+void | |
+rdata(Rasp *r, long p0, long p1, Rune *cp) | |
+{ | |
+ Section *s, *t, *ns; | |
+ | |
+ s = findsect(r, r->sect, 0L, p0); | |
+ t = findsect(r, s, p0, p1); | |
+ for(; s!=t; s=ns){ | |
+ ns=s->next; | |
+ if(s->text) | |
+ panic("rdata"); | |
+ rsdelete(r, s); | |
+ } | |
+ p1 -= p0; | |
+ s = rsinsert(r, t); | |
+ s->text = alloc(RUNESIZE*(TBLOCKSIZE+1)); | |
+ memmove(s->text, cp, RUNESIZE*p1); | |
+ s->text[p1] = 0; | |
+ s->nrunes = p1; | |
+} | |
+ | |
+void | |
+rclean(Rasp *r) | |
+{ | |
+ Section *s; | |
+ | |
+ for(s=r->sect; s; s=s->next) | |
+ while(s->next && (s->text!=0)==(s->next->text!=0)){ | |
+ if(s->text){ | |
+ if(s->nrunes+s->next->nrunes>TBLOCKSIZE) | |
+ break; | |
+ Strcpy(s->text+s->nrunes, s->next->text); | |
+ } | |
+ s->nrunes += s->next->nrunes; | |
+ rsdelete(r, s->next); | |
+ } | |
+} | |
+ | |
+void | |
+Strcpy(Rune *to, Rune *from) | |
+{ | |
+ do; while(*to++ = *from++); | |
+} | |
+ | |
+Rune* | |
+rload(Rasp *r, ulong p0, ulong p1, ulong *nrp) | |
+{ | |
+ Section *s; | |
+ long p; | |
+ int n, nb; | |
+ | |
+ nb = 0; | |
+ Strgrow(&scratch, &nscralloc, p1-p0+1); | |
+ scratch[0] = 0; | |
+ for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next) | |
+ p += s->nrunes; | |
+ while(p<p1 && s){ | |
+ /* | |
+ * Subtle and important. If we are preparing to handle an 'rd… | |
+ * call, it's because we have an 'rresize' hole here, so the | |
+ * screen doesn't have data for that space anyway (it got cut | |
+ * first). So pretend it isn't there. | |
+ */ | |
+ if(s->text){ | |
+ n = s->nrunes-(p0-p); | |
+ if(n>p1-p0) /* all in this section */ | |
+ n = p1-p0; | |
+ memmove(scratch+nb, s->text+(p0-p), n*RUNESIZE); | |
+ nb += n; | |
+ scratch[nb] = 0; | |
+ } | |
+ p += s->nrunes; | |
+ p0 = p; | |
+ s = s->next; | |
+ } | |
+ if(nrp) | |
+ *nrp = nb; | |
+ return scratch; | |
+} | |
+ | |
+int | |
+rmissing(Rasp *r, ulong p0, ulong p1) | |
+{ | |
+ Section *s; | |
+ long p; | |
+ int n, nm=0; | |
+ | |
+ for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next) | |
+ p += s->nrunes; | |
+ while(p<p1 && s){ | |
+ if(s->text == 0){ | |
+ n = s->nrunes-(p0-p); | |
+ if(n > p1-p0) /* all in this section */ | |
+ n = p1-p0; | |
+ nm += n; | |
+ } | |
+ p += s->nrunes; | |
+ p0 = p; | |
+ s = s->next; | |
+ } | |
+ return nm; | |
+} | |
+ | |
+int | |
+rcontig(Rasp *r, ulong p0, ulong p1, int text) | |
+{ | |
+ Section *s; | |
+ long p, n; | |
+ int np=0; | |
+ | |
+ for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next) | |
+ p += s->nrunes; | |
+ while(p<p1 && s && (text? (s->text!=0) : (s->text==0))){ | |
+ n = s->nrunes-(p0-p); | |
+ if(n > p1-p0) /* all in this section */ | |
+ n = p1-p0; | |
+ np += n; | |
+ p += s->nrunes; | |
+ p0 = p; | |
+ s = s->next; | |
+ } | |
+ return np; | |
+} | |
+ | |
+void | |
+Strgrow(Rune **s, long *n, int want) /* can always toss the old data wh… | |
+{ | |
+ if(*n >= want) | |
+ return; | |
+ free(*s); | |
+ *s = alloc(RUNESIZE*want); | |
+ *n = want; | |
+} | |
diff --git a/samterm/samterm.h b/samterm/samterm.h | |
@@ -0,0 +1,158 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#define SAMTERM | |
+ | |
+#define RUNESIZE sizeof(Rune) | |
+#define MAXFILES 256 | |
+#define NL 5 | |
+ | |
+enum{ | |
+ Up, | |
+ Down | |
+}; | |
+ | |
+typedef struct Text Text; | |
+typedef struct Section Section; | |
+typedef struct Rasp Rasp; | |
+ | |
+struct Section | |
+{ | |
+ long nrunes; | |
+ Rune *text; /* if null, we haven't got it */ | |
+ Section *next; | |
+}; | |
+ | |
+struct Rasp | |
+{ | |
+ long nrunes; | |
+ Section *sect; | |
+}; | |
+ | |
+#define Untagged ((ushort)65535) | |
+ | |
+struct Text | |
+{ | |
+ Rasp rasp; | |
+ short nwin; | |
+ short front; /* input window */ | |
+ ushort tag; | |
+ char lock; | |
+ Flayer l[NL]; /* screen storage */ | |
+}; | |
+ | |
+enum Resource | |
+{ | |
+ Eextern = 0x08, | |
+ Ehost = 0x04, | |
+ RHost = Ehost, | |
+ RExtern = Eextern, | |
+ RKeyboard = Ekeyboard, | |
+ RMouse = Emouse | |
+}; | |
+ | |
+extern Text *text[]; | |
+extern uchar *name[]; | |
+extern ushort tag[]; | |
+extern int nname; | |
+extern Cursor bullseye; | |
+extern Cursor deadmouse; | |
+extern Cursor lockarrow; | |
+extern Cursor *cursor; | |
+extern Flayer *which; | |
+extern Flayer *work; | |
+extern Text cmd; | |
+extern Rune *scratch; | |
+extern long nscralloc; | |
+extern char lock; | |
+extern char hasunlocked; | |
+extern long snarflen; | |
+extern Mouse mouse; | |
+extern long modified; | |
+ | |
+Rune *stgettext(Flayer*, long, ulong*); | |
+void *alloc(ulong n); | |
+ | |
+void iconinit(void); | |
+void getscreen(int, char**); | |
+void initio(void); | |
+void setlock(void); | |
+void outcmd(void); | |
+void rinit(Rasp*); | |
+void startnewfile(int, Text*); | |
+void cursorset(Point); | |
+void getmouse(void); | |
+void mouseunblock(void); | |
+void kbdblock(void); | |
+void extstart(void); | |
+int button(int but); | |
+int load(char*, int); | |
+int waitforio(void); | |
+int rcvchar(void); | |
+int getch(void); | |
+int kbdchar(void); | |
+int qpeekc(void); | |
+void mouseexit(void); | |
+void cut(Text*, int, int, int); | |
+void paste(Text*, int); | |
+void snarf(Text*, int); | |
+int center(Flayer*, long); | |
+int xmenuhit(int, Menu*); | |
+void buttons(int); | |
+int getr(Rectangle*); | |
+void current(Flayer*); | |
+void duplicate(Flayer*, Rectangle, XftFont*, int); | |
+void startfile(Text*); | |
+void panic(char*); | |
+void closeup(Flayer*); | |
+void Strgrow(Rune**, long*, int); | |
+int RESHAPED(void); | |
+void reshape(void); | |
+void rcv(void); | |
+void type(Flayer*, int); | |
+void menu2hit(void); | |
+void menu3hit(void); | |
+void scroll(Flayer*, int, int); | |
+void hcheck(int); | |
+void rclear(Rasp*); | |
+int whichmenu(int); | |
+void hcut(int, long, long); | |
+void horigin(int, long); | |
+void hgrow(int, long, long, int); | |
+int hdata(int, long, uchar*, int); | |
+int hdatarune(int, long, Rune*, int); | |
+Rune *rload(Rasp*, ulong, ulong, ulong*); | |
+void menuins(int, uchar*, Text*, int, int); | |
+void menudel(int); | |
+Text *sweeptext(int, int); | |
+void setpat(char*); | |
+void scrdraw(Flayer*, long tot); | |
+int rcontig(Rasp*, ulong, ulong, int); | |
+int rmissing(Rasp*, ulong, ulong); | |
+void rresize(Rasp *, long, long, long); | |
+void rdata(Rasp*, long, long, Rune*); | |
+void rclean(Rasp*); | |
+void scrorigin(Flayer*, int, long); | |
+long scrtotal(Flayer*); | |
+void flnewlyvisible(Flayer*); | |
+char *rcvstring(void); | |
+void Strcpy(Rune*, Rune*); | |
+void Strncpy(Rune*, Rune*, long); | |
+void flushtyping(int); | |
+void dumperrmsg(int, int, int, int); | |
+int screensize(int*,int*); | |
+ | |
+#include "../sam/mesg.h" | |
+ | |
+void outTs(Tmesg, int); | |
+void outT0(Tmesg); | |
+void outTl(Tmesg, long); | |
+void outTslS(Tmesg, int, long, Rune*); | |
+void outTsll(Tmesg, int, long, long); | |
+void outTsl(Tmesg, int, long); | |
+void outTsv(Tmesg, int, void*); | |
+void outTv(Tmesg, void*); | |
+void outstart(Tmesg); | |
+void outcopy(int, uchar*); | |
+void outshort(int); | |
+void outlong(long); | |
+void outvlong(void*); | |
+void outsend(void); | |
diff --git a/samterm/scroll.c b/samterm/scroll.c | |
@@ -0,0 +1,145 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+extern Bitmap *darkgrey; | |
+extern Mouse mouse; | |
+ | |
+Rectangle | |
+scrpos(Rectangle r, long p0, long p1, long tot) | |
+{ | |
+ long h; | |
+ Rectangle q; | |
+ | |
+ q = inset(r, 1); | |
+ h = q.max.y-q.min.y; | |
+ if(tot == 0) | |
+ return q; | |
+ if(tot > 1024L*1024L) | |
+ tot>>=10, p0>>=10, p1>>=10; | |
+ if(p0 > 0) | |
+ q.min.y += h*p0/tot; | |
+ if(p1 < tot) | |
+ q.max.y -= h*(tot-p1)/tot; | |
+ if(q.max.y < q.min.y+2){ | |
+ if(q.min.y+2 <= r.max.y) | |
+ q.max.y = q.min.y+2; | |
+ else | |
+ q.min.y = q.max.y-2; | |
+ } | |
+ return q; | |
+} | |
+ | |
+void | |
+scrflip(Flayer *l, Rectangle r) | |
+{ | |
+ if(rectclip(&r, l->scroll)) | |
+ bitblt(l->f.b, r.min, l->f.b, r, F&~D); | |
+} | |
+ | |
+void | |
+scrdraw(Flayer *l, long tot) | |
+{ | |
+ Rectangle r, r1, r2; | |
+ Bitmap *b; | |
+ static Bitmap *x; | |
+ int h; | |
+ | |
+ if(l->f.b == 0) | |
+ panic("scrdraw"); | |
+ r = l->scroll; | |
+ r.min.x += 1; /* border between margin and bar */ | |
+ r1 = r; | |
+ if(l->visible == All){ | |
+ if(x == 0){ | |
+ if (screensize(0, &h) == 0) | |
+ h = 2048; | |
+ x = balloc(Rect(0, 0, 32, h), l->f.b->ldepth); | |
+ if(x == 0) | |
+ panic("scrdraw balloc"); | |
+ } | |
+ b = x; | |
+ r1.min.x = 0; | |
+ r1.max.x = Dx(r); | |
+ }else | |
+ b = l->f.b; | |
+ bitblt(b, r1.min, b, r1, F); | |
+ texture(b, inset(r1, 1), darkgrey, S); | |
+ r2 = scrpos(r1, l->origin, l->origin+l->f.nchars, tot); | |
+ bitblt(b, r2.min, b, r2, 0); | |
+ if(b!=l->f.b) | |
+ bitblt(l->f.b, r.min, b, r1, S); | |
+} | |
+ | |
+void | |
+scroll(Flayer *l, int pbut, int but) | |
+{ | |
+ int in = 0, oin; | |
+ long tot = scrtotal(l); | |
+ Rectangle scr, r, s, rt; | |
+ int x, y, my, oy, h; | |
+ long p0; | |
+ | |
+ s = inset(l->scroll, 1); | |
+ x = s.min.x+FLSCROLLWID/2; | |
+ scr = scrpos(l->scroll, l->origin, l->origin+l->f.nchars, tot); | |
+ r = scr; | |
+ y = scr.min.y; | |
+ my = mouse.xy.y; | |
+ do{ | |
+ oin = in; | |
+ in = abs(x-mouse.xy.x)<=FLSCROLLWID/2; | |
+ if(oin != in) | |
+ scrflip(l, r); | |
+ if(in){ | |
+ oy = y; | |
+ my = mouse.xy.y; | |
+ if(my < s.min.y) | |
+ my = s.min.y; | |
+ if(my >= s.max.y) | |
+ my = s.max.y; | |
+ if(!eqpt(mouse.xy, Pt(x, my))) | |
+ cursorset(Pt(x, my)); | |
+ if(but == 1){ | |
+ p0 = l->origin-frcharofpt(&l->f, Pt(s.max.x, m… | |
+ rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot… | |
+ y = rt.min.y; | |
+ }else if(but == 2){ | |
+ y = my; | |
+ if(y > s.max.y-2) | |
+ y = s.max.y-2; | |
+ }else if(but == 3){ | |
+ p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, m… | |
+ rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot… | |
+ y = rt.min.y; | |
+ } | |
+ if(y != oy){ | |
+ scrflip(l, r); | |
+ r = raddp(scr, Pt(0, y-scr.min.y)); | |
+ scrflip(l, r); | |
+ } | |
+ } | |
+ }while(button(pbut)); | |
+ if(in){ | |
+ h = s.max.y-s.min.y; | |
+ scrflip(l, r); | |
+ p0 = 0; | |
+ if(but == 1) | |
+ p0 = (long)(my-s.min.y)/l->f.font->height+1; | |
+ else if(but == 2){ | |
+ if(tot > 1024L*1024L) | |
+ p0 = ((tot>>10)*(y-s.min.y)/h)<<10; | |
+ else | |
+ p0 = tot*(y-s.min.y)/h; | |
+ }else if(but == 3){ | |
+ p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); | |
+ if(p0 > tot) | |
+ p0 = tot; | |
+ } | |
+ scrorigin(l, but, p0); | |
+ } | |
+} | |
diff --git a/samterm/unix.c b/samterm/unix.c | |
@@ -0,0 +1,159 @@ | |
+/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <libg.h> | |
+#include <frame.h> | |
+#include "flayer.h" | |
+#include "samterm.h" | |
+ | |
+#include <sys/stat.h> | |
+#include <errno.h> | |
+#include <signal.h> | |
+ | |
+#ifdef APOLLO | |
+#define O_NONBLOCK O_NDELAY | |
+#endif | |
+ | |
+#if defined(UMIPS) || defined(SUNOS) | |
+#define atexit(p) /* sigh */ | |
+#endif | |
+ | |
+char *exname = NULL; | |
+static char *fallbacks[] = { | |
+ "*scrollForwardR: true", | |
+ "*geometry: 740x780", | |
+ NULL | |
+}; | |
+ | |
+void | |
+getscreen(int argc, char **argv) | |
+{ | |
+ int fd; | |
+ Rectangle r; | |
+ | |
+ signal(SIGINT, SIG_IGN); | |
+ xtbinit(0, "Sam", &argc, argv, fallbacks); | |
+ r = inset(screen.r, 4); | |
+ bitblt(&screen, r.min, &screen, r, 0); | |
+} | |
+ | |
+int | |
+screensize(int *w, int *h) | |
+{ | |
+ return scrpix(w,h); | |
+} | |
+ | |
+void | |
+dumperrmsg(int count, int type, int count0, int c) | |
+{ | |
+ uchar *cp; | |
+ int i; | |
+ | |
+ cp = (uchar *) rcvstring(); | |
+ fprint(2, "samterm: host mesg: count %d %ux %ux %ux %s...ignored\n", | |
+ count, type, count0, c, cp); | |
+ i = 0; | |
+ while (*cp) { | |
+ fprint(2, "%x ", *cp); | |
+ if (i++ >= 20) { | |
+ fprint(2, "\n"); | |
+ i = 0; | |
+ } | |
+ cp++; | |
+ } | |
+} | |
+ | |
+void | |
+removeextern(void) | |
+{ | |
+ if (exname) { | |
+ (void)unlink(exname); | |
+ exname = 0; | |
+ } | |
+} | |
+/* | |
+ * some systems do not support non-blocking i/o on named pipes | |
+ * or do not provide working POSIX interfaces to the pipes. | |
+ * in that case, add the name of the system to the 'ifdef' that | |
+ * disables the code at the beginning of the function. | |
+ * The external 'B' command will not work. | |
+ */ | |
+ | |
+void | |
+extstart(void) | |
+{ | |
+#ifndef NOFIFO | |
+ extern char *machine; | |
+ char *disp; | |
+ char *user; | |
+ char *home; | |
+ int fd; | |
+ int flags; | |
+ | |
+ user = getuser(); | |
+ disp = getenv("DISPLAY"); | |
+ home = getenv("HOME"); | |
+ | |
+ if (home == NULL) | |
+ { | |
+ return; | |
+ } | |
+ | |
+ exname = (char *)alloc(4 + 6 + strlen(home) + 1 + strlen(user) + 1 + s… | |
+ sprint(exname, "%s/.sam.%s", home, machine); | |
+ | |
+ /* Make the named pipe. */ | |
+ if (mkfifo(exname, 0600) == -1) { | |
+ struct stat statb; | |
+ extern int errno; | |
+ | |
+ if (errno != EEXIST || stat(exname, &statb) == -1) | |
+ return; | |
+ | |
+ if (!S_ISFIFO(statb.st_mode)) { | |
+ removeextern(); | |
+ if (mkfifo(exname, 0600) == -1) | |
+ return; | |
+ } | |
+ } | |
+ | |
+ fd = open(exname, O_RDONLY | O_NONBLOCK); | |
+ if (fd == -1) { | |
+ removeextern(); | |
+ return; | |
+ } | |
+ | |
+ /* | |
+ * Turn off no-delay and provide ourselves as a lingering | |
+ * writer so as not to get end of file on read. | |
+ */ | |
+ flags = fcntl(fd, F_GETFL, 0); | |
+ if (flags == -1 || fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) == -1 | |
+ || open(exname, O_WRONLY) == -1) { | |
+ (void)close(fd); | |
+ removeextern(); | |
+ return; | |
+ } | |
+ | |
+ estart(Eextern, fd, 8192); | |
+ atexit(removeextern); | |
+#endif | |
+} | |
+ | |
+/* | |
+ * we have to supply a dummy exit function, because some vendors can't … | |
+ * bothered to provide atexit(). we clean up the named pipes on a norm… | |
+ * exit, but leave them laying around on abnormal exits. | |
+ */ | |
+void | |
+exits(char *message) | |
+{ | |
+ if (exname) { | |
+ unlink(exname); | |
+ exname = 0; | |
+ } | |
+ if (message == 0) | |
+ exit (0); | |
+ else | |
+ exit(1); | |
+} |